From b0c36dfdf6877985bf019847b274129d5113dd3a Mon Sep 17 00:00:00 2001 From: hap Date: Wed, 27 Mar 2024 14:32:32 +0100 Subject: [PATCH] New systems marked not working ------------------------------ Igor (Excalibur) [hap, Sean Riddle] --- src/devices/cpu/h8/h83217.cpp | 2 + src/mame/chess/excal_ivant.cpp | 7 +- src/mame/chess/excal_mirage.cpp | 2 +- src/mame/excalibur/igor.cpp | 358 ++++++++++++++++++++++++++++++++ src/mame/mame.lst | 3 + src/mame/saitek/chessac.cpp | 6 +- 6 files changed, 371 insertions(+), 7 deletions(-) create mode 100644 src/mame/excalibur/igor.cpp diff --git a/src/devices/cpu/h8/h83217.cpp b/src/devices/cpu/h8/h83217.cpp index 76eb07fff8f..e4ed53cf3ac 100644 --- a/src/devices/cpu/h8/h83217.cpp +++ b/src/devices/cpu/h8/h83217.cpp @@ -89,6 +89,7 @@ void h83217_device::map(address_map &map) map(0xff9b, 0xff9b).rw(m_timer8[2], FUNC(h8_timer8_channel_device::tcsr_r), FUNC(h8_timer8_channel_device::tcsr_w)); map(0xff9c, 0xff9d).rw(m_timer8[2], FUNC(h8_timer8_channel_device::tcor_r), FUNC(h8_timer8_channel_device::tcor_w)); map(0xff9e, 0xff9e).rw(m_timer8[2], FUNC(h8_timer8_channel_device::tcnt_r), FUNC(h8_timer8_channel_device::tcnt_w)); + map(0xff9f, 0xff9f).lw8(NAME([this](u8 data) { logerror("tconr = %02x\n", data); })); map(0xffaa, 0xffab).rw(m_watchdog, FUNC(h8_watchdog_device::wd_r), FUNC(h8_watchdog_device::wd_w)); @@ -110,6 +111,7 @@ void h83217_device::map(address_map &map) map(0xffbc, 0xffbc).w(m_port[6], FUNC(h8_port_device::ddr_w)); map(0xffbe, 0xffbe).rw(m_port[6], FUNC(h8_port_device::port_r), FUNC(h8_port_device::dr_w)); + map(0xffc2, 0xffc2).lw8(NAME([this](u8 data) { logerror("wscr = %02x\n", data); })); map(0xffc3, 0xffc3).rw(FUNC(h83217_device::stcr_r), FUNC(h83217_device::stcr_w)); map(0xffc4, 0xffc4).rw(FUNC(h83217_device::syscr_r), FUNC(h83217_device::syscr_w)); map(0xffc5, 0xffc5).r(FUNC(h83217_device::mdcr_r)); diff --git a/src/mame/chess/excal_ivant.cpp b/src/mame/chess/excal_ivant.cpp index 75ab2519e45..4612cdf8e9e 100644 --- a/src/mame/chess/excal_ivant.cpp +++ b/src/mame/chess/excal_ivant.cpp @@ -5,7 +5,8 @@ Excalibur Ivan The Terrible -The chess engine is by Ron Nelson, similar to the one in Excalibur Mirage. +The chess engine is by Ron Nelson, similar to the one in Excalibur Mirage. It +has speech, and also sound effects that are reminiscent of Battle Chess. Hardware notes: - PCB label: EXCALIBUR ELECTRONICS, INC. 6/28/96, IVANT @@ -148,7 +149,7 @@ void ivant_state::update_lcd() void ivant_state::lcd_com_w(offs_t offset, u8 data, u8 mem_mask) { // P70,P71: LCD common - m_lcd_com = mem_mask << 2 | (data & 3); + m_lcd_com = (mem_mask << 2 & 0xc) | (data & 3); update_lcd(); } @@ -203,7 +204,7 @@ u8 ivant_state::read_inputs() u8 ivant_state::p4_r() { - // P47: multiplexed inputs part + // P47: multiplexed inputs high bit return (read_inputs() & 0x80) | 0x7f; } diff --git a/src/mame/chess/excal_mirage.cpp b/src/mame/chess/excal_mirage.cpp index 93048a25cfa..a9aa1120fa5 100644 --- a/src/mame/chess/excal_mirage.cpp +++ b/src/mame/chess/excal_mirage.cpp @@ -486,7 +486,7 @@ u8 mirage_state::p7_r() void mirage_state::p7_w(offs_t offset, u8 data, u8 mem_mask) { // P70,P71: LCD common - m_lcd_com = mem_mask << 2 | (data & 3); + m_lcd_com = (mem_mask << 2 & 0xc) | (data & 3); update_lcd(); // P74: motor X direction diff --git a/src/mame/excalibur/igor.cpp b/src/mame/excalibur/igor.cpp new file mode 100644 index 00000000000..8cdceab382c --- /dev/null +++ b/src/mame/excalibur/igor.cpp @@ -0,0 +1,358 @@ +// license:BSD-3-Clause +// copyright-holders:hap +// thanks-to:Sean Riddle +/******************************************************************************* + +Excalibur Igor (model 711E) + +Hardware notes: +- PCB label: EXCALIBUR ELECTRONICS, INC. 510-1005A01, 5/28/97 IGOR +- Hitachi H8/3214 MCU, 12MHz XTAL +- small daughterboard (27C080 pinout) with a 128KB ROM under epoxy +- 8-bit DAC (Yageo 10L503G resistor array), KA8602 amplifier +- no LEDs, button sensors chessboard + +There's also a newer version from 2000 (model 711E-2) on weaker hardware, it has +a Samsung KS57C2308 MCU instead. + +TODO: +- it does a cold boot at every reset, so nvram won't work properly unless MAME + adds some kind of auxillary autosave state feature at power-off +- internal artwork +- add SVG for LCD +- where is the low battery signal? + +*******************************************************************************/ + +#include "emu.h" + +#include "cpu/h8/h83217.h" +#include "machine/sensorboard.h" +#include "sound/dac.h" +#include "video/pwm.h" + +#include "screen.h" +#include "speaker.h" + +// internal artwork +//#include "excal_igor.lh" + + +namespace { + +class igor_state : public driver_device +{ +public: + igor_state(const machine_config &mconfig, device_type type, const char *tag) : + driver_device(mconfig, type, tag), + m_maincpu(*this, "maincpu"), + m_board(*this, "board"), + m_cobrom(*this, "cobrom"), + m_lcd_pwm(*this, "lcd_pwm"), + m_dac(*this, "dac"), + m_inputs(*this, "IN.%u", 0), + m_out_lcd(*this, "s%u.%u", 0U, 0U) + { } + + void init_igor(); + + void igor(machine_config &config); + +protected: + virtual void machine_start() override; + +private: + // devices/pointers + required_device m_maincpu; + required_device m_board; + required_region_ptr m_cobrom; + required_device m_lcd_pwm; + required_device m_dac; + required_ioport_array<2> m_inputs; + output_finder<2, 24> m_out_lcd; + + u8 m_lcd_com = 0; + u8 m_dac_data = 0; + emu_timer *m_irqtimer; + + u8 m_port1 = 0xff; + u8 m_port2 = 0xff; + u8 m_port5 = 0xff; + u8 m_port7 = 0xff; + + // I/O handlers + void lcd_pwm_w(offs_t offset, u8 data); + void update_lcd(); + void update_dac(); + u8 read_inputs(); + + TIMER_CALLBACK_MEMBER(update_irq) { read_inputs(); } + + void p1_w(u8 data); + void p2_w(u8 data); + u8 p3_r(); + void p4_w(u8 data); + u8 p5_r(); + void p5_w(offs_t offset, u8 data, u8 mem_mask); + u8 p6_r(); + void p7_w(u8 data); +}; + + +/******************************************************************************* + Initialization +*******************************************************************************/ + +void igor_state::init_igor() +{ + u8 *rom = memregion("cobrom")->base(); + const u32 len = memregion("cobrom")->bytes(); + + // descramble data lines + for (int i = 0; i < len; i++) + rom[i] = bitswap<8>(rom[i], 2,3,1,4,0,5,6,7); + + // descramble address lines + std::vector buf(len); + memcpy(&buf[0], rom, len); + for (int i = 0; i < len; i++) + rom[i] = buf[bitswap<20>(i,19,18,17,16, 15,14,12,13,6,3,8,10, 11,9,7,5,4,2,1,0)]; +} + +void igor_state::machine_start() +{ + m_out_lcd.resolve(); + + // periodically check for interrupts + m_irqtimer = timer_alloc(FUNC(igor_state::update_irq), this); + attotime period = attotime::from_msec(1); + m_irqtimer->adjust(period, 0, period); + + // register for savestates + save_item(NAME(m_lcd_com)); + save_item(NAME(m_dac_data)); + save_item(NAME(m_port1)); + save_item(NAME(m_port2)); + save_item(NAME(m_port5)); + save_item(NAME(m_port7)); +} + + + +/******************************************************************************* + I/O +*******************************************************************************/ + +void igor_state::lcd_pwm_w(offs_t offset, u8 data) +{ + m_out_lcd[offset & 0x3f][offset >> 6] = data; +} + +void igor_state::update_lcd() +{ + u32 lcd_segs = bitswap<8>(m_port1,0,1,2,3,4,5,6,7) << 16 | bitswap<8>(m_port2,0,1,2,3,4,5,6,7) << 8 | m_port7; + + for (int i = 0; i < 2; i++) + { + // LCD common is 0/1/Hi-Z + const u32 data = BIT(m_lcd_com, i + 2) ? (BIT(m_lcd_com, i) ? ~lcd_segs : lcd_segs) : 0; + m_lcd_pwm->write_row(i, data); + } +} + +void igor_state::update_dac() +{ + m_dac->write((m_port5 & 4) ? 0x80 : m_dac_data); +} + +u8 igor_state::read_inputs() +{ + u8 data = 0; + + // get input mux from P2/P7/P5 + u16 inp_mux = BIT(~m_port5, 5) << 9 | bitswap<8>(~m_port7,0,1,7,6,5,4,3,2) << 1 | BIT(~m_port2, 6); + + // read buttons + for (int i = 0; i < 2; i++) + if (BIT(inp_mux, i + 8)) + data |= m_inputs[i]->read(); + + // read chessboard + for (int i = 0; i < 8; i++) + if (BIT(inp_mux, i)) + data |= m_board->read_file(i, true); + + // P64-P66 are also IRQ pins (the ON button is IRQ0) + for (int i = 0; i < 3; i++) + m_maincpu->set_input_line(INPUT_LINE_IRQ0 + i, BIT(data, i + 4) ? ASSERT_LINE : CLEAR_LINE); + + return ~data; +} + +void igor_state::p1_w(u8 data) +{ + // P10-P17: COB ROM address + LCD segs + m_port1 = data; +} + +void igor_state::p2_w(u8 data) +{ + // P20-P27: COB ROM address + LCD segs + // P26: input mux low bit + m_port2 = data; + read_inputs(); +} + +u8 igor_state::p3_r() +{ + // P30-P37: read COB ROM + u32 address = bitswap<4>(m_port7,4,7,6,5) << 16 | m_port2 << 8 | m_port1; + return (m_port5 & 4) ? 0xff : m_cobrom[address & (m_cobrom.bytes() - 1)]; +} + +void igor_state::p4_w(u8 data) +{ + // P40-P47 (not P46): DAC data + m_dac_data = (m_dac_data & 0x40) | (data & 0xbf); + update_dac(); +} + +u8 igor_state::p5_r() +{ + // P50: multiplexed inputs high bit + return read_inputs() >> 7 | 0xfe; +} + +void igor_state::p5_w(offs_t offset, u8 data, u8 mem_mask) +{ + // P51: DAC bit 6 + m_dac_data = (m_dac_data & 0xbf) | BIT(data, 1) << 6; + + // P52: COB ROM CS, KA8602 mute + // P55: input mux high bit + m_port5 = data; + update_dac(); + read_inputs(); + + // P53,P54: LCD common + u8 lcd_com = (mem_mask >> 1 & 0xc) | (data >> 3 & 3); + if (lcd_com != m_lcd_com) + { + m_lcd_com = lcd_com; + update_lcd(); + } +} + +u8 igor_state::p6_r() +{ + // P60-P66: multiplexed inputs part + return read_inputs() | 0x80; +} + +void igor_state::p7_w(u8 data) +{ + // P70-P77: input mux part + LCD segs + // P74-P77: COB ROM address + m_port7 = data; + read_inputs(); +} + + + +/******************************************************************************* + Input Ports +*******************************************************************************/ + +static INPUT_PORTS_START( igor ) + PORT_START("IN.0") + PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_U) PORT_CODE(KEYCODE_LEFT) PORT_NAME("No / Left") + PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_R) PORT_NAME("Repeat") + PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_V) PORT_CODE(KEYCODE_2) PORT_CODE(KEYCODE_2_PAD) PORT_NAME("Verify / Queen") + PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_O) PORT_NAME("Option") + PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_N) PORT_NAME("New Game") + PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_B) PORT_NAME("Black / White") + PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_T) PORT_NAME("Takeback") + PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_Y) PORT_CODE(KEYCODE_RIGHT) PORT_NAME("Yes / Right") + + PORT_START("IN.1") + PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_E) PORT_NAME("Mode") + PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_S) PORT_CODE(KEYCODE_1) PORT_CODE(KEYCODE_1_PAD) PORT_NAME("Set Up / King") + PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_I) PORT_CODE(KEYCODE_4) PORT_CODE(KEYCODE_4_PAD) PORT_NAME("Multi-Move / Bishop") + PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_F2) PORT_NAME("Off / Save") + PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_F1) PORT_CODE(KEYCODE_C) PORT_NAME("On / Clear") + PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_M) PORT_CODE(KEYCODE_6) PORT_CODE(KEYCODE_6_PAD) PORT_NAME("Move / Pawn") + PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_L) PORT_CODE(KEYCODE_3) PORT_CODE(KEYCODE_3_PAD) PORT_NAME("Level / Rook") + PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_H) PORT_CODE(KEYCODE_5) PORT_CODE(KEYCODE_5_PAD) PORT_NAME("Hint / Knight") +INPUT_PORTS_END + + + +/******************************************************************************* + Machine Configs +*******************************************************************************/ + +void igor_state::igor(machine_config &config) +{ + // basic machine hardware + H83214(config, m_maincpu, 12_MHz_XTAL); + m_maincpu->nvram_enable_backup(true); + m_maincpu->standby_cb().set(m_maincpu, FUNC(h83214_device::nvram_set_battery)); + m_maincpu->standby_cb().append([this](int state) { if (state) m_lcd_pwm->clear(); }); + m_maincpu->write_port1().set(FUNC(igor_state::p1_w)); + m_maincpu->write_port2().set(FUNC(igor_state::p2_w)); + m_maincpu->read_port3().set(FUNC(igor_state::p3_r)); + m_maincpu->read_port4().set_constant(0xff); // discard + m_maincpu->write_port4().set(FUNC(igor_state::p4_w)); + m_maincpu->read_port5().set(FUNC(igor_state::p5_r)); + m_maincpu->write_port5().set(FUNC(igor_state::p5_w)); + m_maincpu->read_port6().set(FUNC(igor_state::p6_r)); + m_maincpu->write_port7().set(FUNC(igor_state::p7_w)); + + SENSORBOARD(config, m_board).set_type(sensorboard_device::BUTTONS); + m_board->init_cb().set(m_board, FUNC(sensorboard_device::preset_chess)); + m_board->set_delay(attotime::from_msec(150)); + //m_board->set_nvram_enable(true); + + // video hardware + PWM_DISPLAY(config, m_lcd_pwm).set_size(2, 24); + m_lcd_pwm->output_x().set(FUNC(igor_state::lcd_pwm_w)); + + screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_SVG)); + screen.set_refresh_hz(60); + screen.set_size(1920/5, 1080/5); + screen.set_visarea_full(); + + //config.set_default_layout(layout_excal_igor); + + // sound hardware + SPEAKER(config, "speaker").front_center(); + DAC_8BIT_R2R(config, m_dac).add_route(ALL_OUTPUTS, "speaker", 0.5); +} + + + +/******************************************************************************* + ROM Definitions +*******************************************************************************/ + +ROM_START( igor ) + ROM_REGION16_BE( 0x8000, "maincpu", 0 ) + ROM_LOAD("1997_rcn_1002a_excal_hd6433214l02p.ic1", 0x0000, 0x8000, CRC(adbc7e07) SHA1(0d297ad2fd0d18312966195cfad4658da4bc4442) ) + + ROM_REGION( 0x20000, "cobrom", 0 ) + ROM_LOAD("sound.ic2", 0x00000, 0x20000, CRC(bc540da3) SHA1(68647ce1c7e87eba90d9d1912921213af03e3c5d) ) // no label + + ROM_REGION( 200000, "screen", 0 ) + ROM_LOAD("igor.svg", 0, 200000, NO_DUMP ) +ROM_END + +} // anonymous namespace + + + +/******************************************************************************* + Drivers +*******************************************************************************/ + +// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY, FULLNAME, FLAGS +SYST( 1997, igor, 0, 0, igor, igor, igor_state, init_igor, "Excalibur", "Igor (Excalibur)", MACHINE_NOT_WORKING | MACHINE_SUPPORTS_SAVE | MACHINE_CLICKABLE_ARTWORK ) diff --git a/src/mame/mame.lst b/src/mame/mame.lst index c5f599d912e..374e1f9f76f 100644 --- a/src/mame/mame.lst +++ b/src/mame/mame.lst @@ -17761,6 +17761,9 @@ e9161 // @source:ericsson/eispc.cpp epc // 1984 Ericsson PC +@source:excalibur/igor.cpp +igor + @source:excellent/aquarium.cpp aquarium // (c) 1996 Excellent System aquariumj // (c) 1996 Excellent System diff --git a/src/mame/saitek/chessac.cpp b/src/mame/saitek/chessac.cpp index 0bfc9fb7943..eac007ec4ec 100644 --- a/src/mame/saitek/chessac.cpp +++ b/src/mame/saitek/chessac.cpp @@ -83,9 +83,9 @@ private: u8 m_led_data = 0; u32 m_adpdm_address = 0; - u8 m_port3 = 0; - u8 m_port5 = 0; - u8 m_port7 = 0; + u8 m_port3 = 0xff; + u8 m_port5 = 0xff; + u8 m_port7 = 0xff; // I/O handlers void lcd_pwm_w(offs_t offset, u8 data);