ssystem3: add notes, add i/o (nw)

This commit is contained in:
hap 2019-08-22 23:51:40 +02:00
parent 59dc75b09b
commit e28fc1d91f
2 changed files with 186 additions and 23 deletions

View File

@ -75,7 +75,7 @@ void md4330b_device::update_q()
u32 out = m_shift; u32 out = m_shift;
if (m_tc) if (m_tc)
out = ~out; out = ~out;
out &= (1 << m_qmax) - 1; out &= (u64(1) << m_qmax) - 1;
m_write_q(0, out); m_write_q(0, out);
} }

View File

@ -3,8 +3,53 @@
// thanks-to:Berger // 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: TODO:
- WIP - 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 "cpu/m6502/m6502.h"
#include "machine/6522via.h" #include "machine/6522via.h"
#include "machine/nvram.h" #include "machine/nvram.h"
#include "machine/timer.h" #include "machine/clock.h"
#include "sound/dac.h" #include "sound/dac.h"
#include "sound/volt_reg.h" #include "sound/volt_reg.h"
#include "video/md4330b.h" #include "video/md4330b.h"
@ -33,6 +78,7 @@ public:
ssystem3_state(const machine_config &mconfig, device_type type, const char *tag) : ssystem3_state(const machine_config &mconfig, device_type type, const char *tag) :
driver_device(mconfig, type, tag), driver_device(mconfig, type, tag),
m_maincpu(*this, "maincpu"), m_maincpu(*this, "maincpu"),
m_via(*this, "via"),
m_lcd(*this, "lcd"), m_lcd(*this, "lcd"),
m_display(*this, "display"), m_display(*this, "display"),
m_dac(*this, "dac"), m_dac(*this, "dac"),
@ -48,19 +94,42 @@ protected:
private: private:
// devices/pointers // devices/pointers
required_device<cpu_device> m_maincpu; required_device<cpu_device> m_maincpu;
required_device<via6522_device> m_via;
required_device<md4332b_device> m_lcd; required_device<md4332b_device> m_lcd;
required_device<pwm_display_device> m_display; required_device<pwm_display_device> m_display;
required_device<dac_bit_interface> m_dac; required_device<dac_bit_interface> m_dac;
required_ioport_array<4> m_inputs; required_ioport_array<4+1> m_inputs;
// address maps // address maps
void main_map(address_map &map); void main_map(address_map &map);
// I/O handlers // 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() 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 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) void ssystem3_state::main_map(address_map &map)
{ {
map(0x0000, 0x03ff).ram(); map(0x0000, 0x03ff).mirror(0x3c00).ram();
map(0x6000, 0x600f).m("via", FUNC(via6522_device::map)); map(0x6000, 0x600f).mirror(0x1ff0).m(m_via, FUNC(via6522_device::map));
map(0x8000, 0x9fff).rom().mirror(0x6000); map(0x8000, 0x9fff).mirror(0x6000).rom();
} }
@ -91,28 +236,33 @@ void ssystem3_state::main_map(address_map &map)
static INPUT_PORTS_START( ssystem3 ) static INPUT_PORTS_START( ssystem3 )
PORT_START("IN.0") PORT_START("IN.0")
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_1) PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_UNUSED)
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_2) 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_3) 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_4) 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_START("IN.1")
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_5) PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_UNUSED)
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_6) 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_7) 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_8) 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_START("IN.2")
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_Q) 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_W) 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_E) 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_R) 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_START("IN.3")
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_T) 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_Y) 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_U) 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_I) 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 INPUT_PORTS_END
@ -127,12 +277,22 @@ void ssystem3_state::ssystem3(machine_config &config)
M6502(config, m_maincpu, 4_MHz_XTAL / 2); M6502(config, m_maincpu, 4_MHz_XTAL / 2);
m_maincpu->set_addrmap(AS_PROGRAM, &ssystem3_state::main_map); 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); //NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);
/* video hardware */ /* video hardware */
MD4332B(config, m_lcd); 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); PWM_DISPLAY(config, m_display).set_size(4, 4);
//config.set_default_layout(layout_saitek_ssystem3); //config.set_default_layout(layout_saitek_ssystem3);
@ -152,6 +312,9 @@ ROM_START( ssystem3 )
ROM_REGION( 0x10000, "maincpu", 0 ) ROM_REGION( 0x10000, "maincpu", 0 )
ROM_LOAD("c19081e_ss-3-lrom.u4", 0x8000, 0x1000, CRC(9ea46ed3) SHA1(34eef85b356efbea6ddac1d1705b104fc8e2731a) ) // 2332 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) ) // " 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 ROM_END
} // anonymous namespace } // anonymous namespace