diff options
Diffstat (limited to 'src/mame/drivers/saitek_ssystem3.cpp')
-rw-r--r-- | src/mame/drivers/saitek_ssystem3.cpp | 207 |
1 files changed, 185 insertions, 22 deletions
diff --git a/src/mame/drivers/saitek_ssystem3.cpp b/src/mame/drivers/saitek_ssystem3.cpp index 406cee8981a..7239b731303 100644 --- a/src/mame/drivers/saitek_ssystem3.cpp +++ b/src/mame/drivers/saitek_ssystem3.cpp @@ -3,8 +3,53 @@ // thanks-to:Berger /****************************************************************************** +SciSys / Novag Chess Champion: Super System III (aka MK III), distributed by +both SciSys and Novag. Which company was responsible for which part of the +manufacturing chain is unknown. The software is by SciSys (no mention of Novag +in the ROM, it has "COPYRIGHT SCISYS LTD 1979"). + +This is their 1st original product. MK II was licensed from Commodore, and +MK I was, to put it bluntly, a bootleg. The chess engine is by Mike Johnson, +with support from David Levy. + +Hardware notes: (main unit) +- Synertek 6502A @ 2MHz (4MHz XTAL) +- Synertek 6522 +- 8KB ROM (2*Synertek 2332) +- 1KB RAM (2*HM472114P-3) +- MD4332BE + a bunch of TTL for the LCD +- 13 buttons, 4 switches, no leds or sensorboard +- connectors for: PSU, Power Pack, Chess Unit, Printer Unit + +Chess Unit: +- PCB label: Radofin XM-2057-0C +- Fairchild F6808P CPU @ ?MHz (M6808 compatible) +- Fairchild F6821P PIA +- C28A97M 4KB ROM(2332), 128x8 RAM(F6810P) +- 2*HLCD0438, chessboard LCD + +Printer Unit: +- unknown hardware, assume own CPU like the chess unit + +PSU ("permanent storage unit"?) is probably just a 256x4 battery-backed RAM +module, not sure why it was so expensive (~180DM). +A chess clock accessory was also announced but unreleased. + +SciSys Super System IV is on similar hardware. + TODO: - WIP +- 6522 ACR register is initialized with 0xe3. Meaning: PA and PB inputs are set + to latch mode, but the program then never clocks the latch, it functions as if + it meant to write 0xe0. Maybe 6522 CA1 pin emulation is wrong? Documentation + says it's edge-triggered, but here it's tied to VCC. I added a trivial hack to + work around this, see rom defs. +- 6522 timer runs too fast, currently worked around by clocking it at 1MHz. PB6/PB7 + was measured 997Hz on real device, it's 1989Hz on MAME at 2MHz, both 50% duty cycle. +- 2nd 7474 /2 clock divider on each 4000-7fff access, this also applies to 6522 clock + (doesn't affect chess calculation speed, only I/O access, eg. beeper pitch). + Should be doable to add, but 6522 device doesn't support live clock changes. +- add chessboard lcd and printer ******************************************************************************/ @@ -12,7 +57,7 @@ TODO: #include "cpu/m6502/m6502.h" #include "machine/6522via.h" #include "machine/nvram.h" -#include "machine/timer.h" +#include "machine/clock.h" #include "sound/dac.h" #include "sound/volt_reg.h" #include "video/md4330b.h" @@ -33,6 +78,7 @@ public: ssystem3_state(const machine_config &mconfig, device_type type, const char *tag) : driver_device(mconfig, type, tag), m_maincpu(*this, "maincpu"), + m_via(*this, "via"), m_lcd(*this, "lcd"), m_display(*this, "display"), m_dac(*this, "dac"), @@ -48,19 +94,42 @@ protected: private: // devices/pointers required_device<cpu_device> m_maincpu; + required_device<via6522_device> m_via; required_device<md4332b_device> m_lcd; required_device<pwm_display_device> m_display; required_device<dac_bit_interface> m_dac; - required_ioport_array<4> m_inputs; + required_ioport_array<4+1> m_inputs; // address maps void main_map(address_map &map); // I/O handlers + DECLARE_WRITE_LINE_MEMBER(update_lcd); + DECLARE_WRITE32_MEMBER(lcd_q_w); + DECLARE_WRITE8_MEMBER(input_w); + DECLARE_READ8_MEMBER(input_r); + DECLARE_WRITE8_MEMBER(control_w); + DECLARE_READ8_MEMBER(control_r); + + u8 m_inp_mux; + u8 m_control; + u8 m_shift; + u32 m_lcd_q; }; void ssystem3_state::machine_start() { + // zerofill + m_inp_mux = 0; + m_control = 0; + m_shift = 0; + m_lcd_q = 0; + + // register for savestates + save_item(NAME(m_inp_mux)); + save_item(NAME(m_control)); + save_item(NAME(m_shift)); + save_item(NAME(m_lcd_q)); } @@ -69,6 +138,82 @@ void ssystem3_state::machine_start() I/O ******************************************************************************/ +// MD4332B LCD + +WRITE_LINE_MEMBER(ssystem3_state::update_lcd) +{ + // update on falling edge + if (!state) + { + // temporary + output().set_value("digit0", m_lcd_q >> 0 & 0xff); + output().set_value("digit1", m_lcd_q >> 8 & 0xff); + output().set_value("digit2", m_lcd_q >> 16 & 0xff); + output().set_value("digit3", m_lcd_q >> 24 & 0xff); + } +} + +WRITE32_MEMBER(ssystem3_state::lcd_q_w) +{ + m_lcd_q = data; +} + + +// 6522 VIA + +WRITE8_MEMBER(ssystem3_state::input_w) +{ + // PA0-PA7: input mux + m_inp_mux = ~data; +} + +READ8_MEMBER(ssystem3_state::input_r) +{ + u8 data = m_inp_mux; + + // PA1-PA3: multiplexed inputs from PA4-PA7 + // PA0: blocked by diodes + for (int i = 0; i < 4; i++) + if (BIT(m_inp_mux, i+4)) + data |= m_inputs[i]->read() & 0xe; + + // PA4-PA7: multiplexed inputs from PA0-PA3 + for (int i = 0; i < 4; i++) + if (m_inp_mux & m_inputs[i]->read()) + data |= 1 << (i+4); + + return ~data; +} + +WRITE8_MEMBER(ssystem3_state::control_w) +{ + // PB0: speaker out + m_dac->write(~data & m_inputs[4]->read() & 1); + + // PB1: LCD DI + // PB2: LCD CLK + m_lcd->di_w(BIT(data, 1)); + m_lcd->clk_w(BIT(data, 2)); + + // PB2 also clocks a 4015B + // DA: LCD DO, DB: Q3A + if (data & ~m_control & 4) + m_shift = m_shift << 1 | m_lcd->do_r(); + + // PB3: device serial out + + // PB7: tied to PB6 (pulse timer 2) + m_via->write_pb6(BIT(data, 7)); + + m_control = data; +} + +READ8_MEMBER(ssystem3_state::control_r) +{ + // PB4: device busy + // PB5: device attached? + return 0xff; +} @@ -78,9 +223,9 @@ void ssystem3_state::machine_start() void ssystem3_state::main_map(address_map &map) { - map(0x0000, 0x03ff).ram(); - map(0x6000, 0x600f).m("via", FUNC(via6522_device::map)); - map(0x8000, 0x9fff).rom().mirror(0x6000); + map(0x0000, 0x03ff).mirror(0x3c00).ram(); + map(0x6000, 0x600f).mirror(0x1ff0).m(m_via, FUNC(via6522_device::map)); + map(0x8000, 0x9fff).mirror(0x6000).rom(); } @@ -91,28 +236,33 @@ void ssystem3_state::main_map(address_map &map) static INPUT_PORTS_START( ssystem3 ) PORT_START("IN.0") - PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_1) - PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_2) - PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_3) - PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_4) + PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_UNUSED) + PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_9) PORT_CODE(KEYCODE_9_PAD) PORT_NAME("9 / EP / C SQ") + PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_ENTER) PORT_CODE(KEYCODE_ENTER_PAD) PORT_NAME("Enter") + PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_0) PORT_CODE(KEYCODE_0_PAD) PORT_NAME("0 / MD / C Board") PORT_START("IN.1") - PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_5) - PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_6) - PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_7) - PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_8) + PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_UNUSED) + PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_6) PORT_CODE(KEYCODE_6_PAD) PORT_CODE(KEYCODE_F) PORT_NAME("F 6 / Knight / Clock") + PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_5) PORT_CODE(KEYCODE_5_PAD) PORT_CODE(KEYCODE_E) PORT_CODE(KEYCODE_LEFT) PORT_NAME("E 5 / Bishop / Left") + PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_DEL) PORT_CODE(KEYCODE_BACKSPACE) PORT_NAME("CE / Interrupt") PORT_START("IN.2") - PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_Q) - PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_W) - PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_E) - PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_R) + PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_N) PORT_NAME("New Game") + PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_7) PORT_CODE(KEYCODE_7_PAD) PORT_CODE(KEYCODE_G) PORT_CODE(KEYCODE_RIGHT) PORT_NAME("G 7 / Pawn / Right") + PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_4) PORT_CODE(KEYCODE_4_PAD) PORT_CODE(KEYCODE_D) PORT_NAME("D 4 / Rook / #") + PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_1) PORT_CODE(KEYCODE_1_PAD) PORT_CODE(KEYCODE_A) PORT_NAME("A 1 / White") PORT_START("IN.3") - PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_T) - PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_Y) - PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_U) - PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_I) + PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_T) PORT_NAME("Time") // not a toggle switch + PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_8) PORT_CODE(KEYCODE_8_PAD) PORT_CODE(KEYCODE_H) PORT_NAME("H 8 / Black") + PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_3) PORT_CODE(KEYCODE_3_PAD) PORT_CODE(KEYCODE_C) PORT_NAME("C 3 / Queen / #50") + PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_2) PORT_CODE(KEYCODE_2_PAD) PORT_CODE(KEYCODE_B) PORT_NAME("B 2 / King / FP") + + PORT_START("IN.4") + PORT_CONFNAME( 0x01, 0x01, "Sound" ) + PORT_CONFSETTING( 0x00, DEF_STR( Off ) ) + PORT_CONFSETTING( 0x01, DEF_STR( On ) ) INPUT_PORTS_END @@ -127,12 +277,22 @@ void ssystem3_state::ssystem3(machine_config &config) M6502(config, m_maincpu, 4_MHz_XTAL / 2); m_maincpu->set_addrmap(AS_PROGRAM, &ssystem3_state::main_map); - VIA6522(config, "via", 4_MHz_XTAL / 2); + VIA6522(config, m_via, 4_MHz_XTAL / 4); // WRONG! should be 2MHz + m_via->writepa_handler().set(FUNC(ssystem3_state::input_w)); + m_via->readpa_handler().set(FUNC(ssystem3_state::input_r)); + m_via->writepb_handler().set(FUNC(ssystem3_state::control_w)); + m_via->readpb_handler().set(FUNC(ssystem3_state::control_r)); //NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0); /* video hardware */ MD4332B(config, m_lcd); + m_lcd->write_q().set(FUNC(ssystem3_state::lcd_q_w)); + + clock_device &tc_clock(CLOCK(config, "tc_clock", 50)); // from power supply + tc_clock.signal_handler().set(m_lcd, FUNC(md4332b_device::tc_w)); + tc_clock.signal_handler().append(FUNC(ssystem3_state::update_lcd)); + PWM_DISPLAY(config, m_display).set_size(4, 4); //config.set_default_layout(layout_saitek_ssystem3); @@ -152,6 +312,9 @@ ROM_START( ssystem3 ) ROM_REGION( 0x10000, "maincpu", 0 ) ROM_LOAD("c19081e_ss-3-lrom.u4", 0x8000, 0x1000, CRC(9ea46ed3) SHA1(34eef85b356efbea6ddac1d1705b104fc8e2731a) ) // 2332 ROM_LOAD("c19082_ss-3-hrom.u5", 0x9000, 0x1000, CRC(52741e0b) SHA1(2a7b950f9810c5a14a1b9d5e6b2bd93da621662e) ) // " + + // HACK! 6522 ACR register setup + ROM_FILL(0x946d, 1, 0xe0) // was 0xe3 ROM_END } // anonymous namespace |