From e23dde49d66a8ea34ca3c1fc0c31ad1ff2e9d7d5 Mon Sep 17 00:00:00 2001 From: Robbbert Date: Thu, 8 Sep 2016 18:46:36 +1000 Subject: [PATCH] chessmst: enabled use of proper external artwork [fhub] --- src/mame/drivers/chessmst.cpp | 555 ++++++++++++++++++++++++++-------- 1 file changed, 427 insertions(+), 128 deletions(-) diff --git a/src/mame/drivers/chessmst.cpp b/src/mame/drivers/chessmst.cpp index d55e2ffdc14..89a7db49d6c 100644 --- a/src/mame/drivers/chessmst.cpp +++ b/src/mame/drivers/chessmst.cpp @@ -1,16 +1,15 @@ // license:BSD-3-Clause // copyright-holders:Sandro Ronco +// fhub (support for external artwork with chess pieces) /*************************************************************************** Chess-Master TODO: - figure out why chessmsta won't work, for starters it assume z80 carry flag is set at poweron? - - a better artwork ****************************************************************************/ - #include "emu.h" #include "cpu/z80/z80.h" #include "machine/z80pio.h" @@ -21,28 +20,431 @@ class chessmst_state : public driver_device { public: chessmst_state(const machine_config &mconfig, device_type type, const char *tag) - : driver_device(mconfig, type, tag), - m_maincpu(*this, "maincpu"), - m_speaker(*this, "speaker") + : driver_device(mconfig, type, tag) + , m_maincpu(*this, "maincpu") + , m_speaker(*this, "speaker") { } - required_device m_maincpu; - required_device m_speaker; - - UINT16 m_matrix; - UINT16 m_led_sel; - UINT8 m_sensor[64]; - - virtual void machine_reset() override; - DECLARE_WRITE8_MEMBER( pio1_port_a_w ); DECLARE_WRITE8_MEMBER( pio1_port_b_w ); DECLARE_READ8_MEMBER( pio2_port_a_r ); DECLARE_WRITE8_MEMBER( pio2_port_b_w ); DECLARE_INPUT_CHANGED_MEMBER(chessmst_sensor); + DECLARE_INPUT_CHANGED_MEMBER(reset_button); + DECLARE_INPUT_CHANGED_MEMBER(clear_pieces); + TIMER_DEVICE_CALLBACK_MEMBER(led_update); + +private: + + virtual void machine_start() override; + virtual void machine_reset() override; + void set_board(); + void set_pieces(); + void clear_pieces(); + void setup_board(UINT8 pos); + void board_presave(); + void board_postload(); + UINT8 m_lastfield, m_lastdata, m_lastpiece, m_thinking; + UINT16 m_matrix; + UINT16 m_led_sel; + bool m_started, m_moveok, m_setup, m_capture, m_castling, m_enpassant, m_cm; + UINT8 m_save_board[64], m_save_sensor[64], m_sensor[64], m_board[64]; + required_device m_maincpu; + required_device m_speaker; }; +enum +{ + EM, // 0 = No piece + BP, BN, BB, BR, BQ, BK, // 1.. 6 = Black pieces + WP, WN, WB, WR, WQ, WK // 7..12 = White pieces +}; + +void chessmst_state::set_board() +{ + static const UINT8 start_board[64] = { + BR, BN, BB, BQ, BK, BB, BN, BR, + BP, BP, BP, BP, BP, BP, BP, BP, + EM, EM, EM, EM, EM, EM, EM, EM, + EM, EM, EM, EM, EM, EM, EM, EM, + EM, EM, EM, EM, EM, EM, EM, EM, + EM, EM, EM, EM, EM, EM, EM, EM, + WP, WP, WP, WP, WP, WP, WP, WP, + WR, WN, WB, WQ, WK, WB, WN, WR }; + + for (UINT8 i=0; i<64; i++) + m_board[i]=start_board[i]; + +} + +void chessmst_state::set_pieces() +{ + for (UINT8 i=0;i<64;i++) + output().set_indexed_value("P", i, m_board[i]); +} + +INPUT_CHANGED_MEMBER(chessmst_state::clear_pieces) +{ + if (!m_started) + { // only immediately after start or reset! + m_started=true; + memset(m_sensor, 1, sizeof(m_sensor)); + for (UINT8 i=0;i<64;i++) + { + m_board[i]=EM; + output().set_indexed_value("P", i, EM); + } + } +} + +void chessmst_state::board_presave() +{ + for (UINT8 i=0;i<64;i++) + m_save_sensor[i] = m_sensor[i]; + for (UINT8 i=0;i<64;i++) + m_save_board[i] = m_board[i]; +} + +void chessmst_state::board_postload() +{ + for (UINT8 i=0;i<64;i++) + m_sensor[i] = m_save_sensor[i]; + for (UINT8 i=0;i<64;i++) + m_board[i] = m_save_board[i]; + + set_pieces(); +} + +void chessmst_state::machine_start() +{ + save_item(NAME(m_save_sensor)); + save_item(NAME(m_save_board)); + machine().save().register_postload(save_prepost_delegate(FUNC(chessmst_state::board_postload),this)); + machine().save().register_presave(save_prepost_delegate(FUNC(chessmst_state::board_presave),this)); +} + +void chessmst_state::machine_reset() +{ + //reset all sensors + memset(m_sensor, 1, sizeof(m_sensor)); + + //positioning the pieces for start next game + for (int i=0; i<64; i+=8) + m_sensor[i+0] = m_sensor[i+1] = m_sensor[i+6] = m_sensor[i+7] = 0; + + set_board(); + set_pieces(); + m_lastfield=99; + m_lastpiece=EM; + m_thinking=0; + m_started=false; + m_setup=false; + m_capture=false; + m_castling=false; + m_enpassant=false; + m_moveok=true; + m_cm = false; +} + +INPUT_CHANGED_MEMBER(chessmst_state::reset_button) +{ + m_maincpu->set_input_line(INPUT_LINE_RESET, newval ? ASSERT_LINE : CLEAR_LINE); + machine_reset(); +} + +TIMER_DEVICE_CALLBACK_MEMBER(chessmst_state::led_update) +{ + switch (m_thinking) + { + case 0: + m_thinking=1; + break; + case 1: if (m_started) + { + if(!m_capture && !m_castling && !m_enpassant) + { + m_thinking=2; + for (UINT8 i=1; i<=8; i++) + { + output().set_indexed_value("led_a", i, 1); + output().set_indexed_value("led_b", i, 1); + output().set_indexed_value("led_c", i, 1); + output().set_indexed_value("led_d", i, 1); + output().set_indexed_value("led_e", i, 1); + output().set_indexed_value("led_f", i, 1); + output().set_indexed_value("led_g", i, 1); + output().set_indexed_value("led_h", i, 1); + output().set_indexed_value("led_i", i, 1); + output().set_indexed_value("led_j", i, 1); + } + } + m_cm = !m_cm; + output().set_indexed_value("led_j", 6, m_cm); + } + break; + case 2: m_cm = !m_cm; + output().set_indexed_value("led_j", 6, m_cm); + } +} + +void chessmst_state::setup_board(UINT8 pos) +{ + static const UINT8 s_board[64] = { + BR, BN, BB, BQ, BK, BB, BN, BR, + BP, BP, BP, BP, BP, BP, BP, BP, + BR, BN, BB, BQ, BK, BB, BN, BR, + BR, BN, BB, BQ, BK, BB, BN, BR, + WR, WN, WB, WQ, WK, WB, WN, WR, + WR, WN, WB, WQ, WK, WB, WN, WR, + WP, WP, WP, WP, WP, WP, WP, WP, + WR, WN, WB, WQ, WK, WB, WN, WR }; + + UINT8 color, currfield, currpiece; + + color=(m_lastpiece?((m_lastpiece-1)%12)/6:2); + currfield=(7-pos%8)*8+pos/8; + currpiece=m_board[currfield]; + if (m_setup) + { + if (m_sensor[pos]) + { // piece up! 0 -> 1 + if (m_lastfield!=99) + { // remove last marked piece + m_board[m_lastfield]=EM; + output().set_indexed_value("P", m_lastfield, EM); + } + m_board[currfield]+=12; + output().set_indexed_value("P", currfield, m_board[currfield]); + m_lastfield=currfield; + m_lastpiece=currpiece; + } + else + { // piece down! 1 -> 0 + if (m_lastfield!=99) { // set last marked piece + m_board[m_lastfield]=EM; + output().set_indexed_value("P", m_lastfield, EM); + m_board[currfield]=m_lastpiece; + output().set_indexed_value("P", currfield, m_lastpiece); + } + else + { // set new piece + currpiece=s_board[currfield]; + m_board[currfield]=currpiece; + output().set_indexed_value("P", currfield, currpiece); + } + m_lastfield=99; + m_lastpiece=EM; + } + } + else + { + if (m_sensor[pos]) + { // piece up! 0 -> 1 + if (currpiece==EM) + return; + if (m_moveok) + { // 1st piece up! + if (m_enpassant) + { + m_board[currfield]=EM; + output().set_indexed_value("P", currfield, EM); + m_enpassant=false; + return; + } + if (m_castling || (m_lastpiece==EM) || ((currpiece-1)/6!=color)) + { + m_board[currfield]+=12; + output().set_indexed_value("P", currfield, m_board[currfield]); + } + else + { + m_board[currfield]=EM; + output().set_indexed_value("P", currfield, EM); + } + m_moveok=false; + } + else + { // 2nd piece up! + if (m_board[m_lastfield]>12) + { + m_board[currfield]=EM; + output().set_indexed_value("P", currfield, EM); + m_capture=true; + return; + } + else + { + m_board[currfield]+=12; + output().set_indexed_value("P", currfield, m_board[currfield]); + } + } + m_lastfield=currfield; + m_lastpiece=currpiece; + } + else + { // piece down! 1 -> 0 + if (m_lastpiece==EM) + return; + if (currfield==m_lastfield) + { // correct wrong click! + m_board[currfield]=m_lastpiece; + output().set_indexed_value("P", currfield, m_lastpiece); + m_lastpiece=(m_lastpiece+5)%12+1; + } + else + { // normal move + m_board[m_lastfield]=EM; + output().set_indexed_value("P", m_lastfield, EM); + if ((m_lastpiece%6==1) && (abs(2*(currfield/8)-7)==7)) + m_lastpiece=(color?WQ:BQ); // promotion? + m_board[currfield]=m_lastpiece; + output().set_indexed_value("P", currfield, m_lastpiece); + m_capture=false; + m_castling=false; + m_enpassant=false; + if ((m_lastpiece%6==0) && (abs(currfield-m_lastfield)==2)) + m_castling=true; // castling? + else + if ((m_lastpiece%6==1) && (m_lastfield/8+color==4) && abs(8-abs(currfield-m_lastfield))==1 + && (m_board[m_lastfield+(2*color-1)*(8-abs(currfield-m_lastfield))]%6==1)) + m_enpassant=true; // enpassant? + } + m_moveok=true; + } + } +} + +INPUT_CHANGED_MEMBER(chessmst_state::chessmst_sensor) +{ + UINT8 pos = (UINT8)(FPTR)param; + + if (newval) + { + m_sensor[pos] = !m_sensor[pos]; + setup_board(pos); + } +} + +WRITE8_MEMBER( chessmst_state::pio1_port_a_w ) +{ + for (int row=1; row<=8; row++) + { + if (m_led_sel & 0x01) + output().set_indexed_value("led_a", row, BIT(data, 8-row)); + if (m_led_sel & 0x02) + output().set_indexed_value("led_b", row, BIT(data, 8-row)); + if (m_led_sel & 0x04) + output().set_indexed_value("led_c", row, BIT(data, 8-row)); + if (m_led_sel & 0x08) + output().set_indexed_value("led_d", row, BIT(data, 8-row)); + if (m_led_sel & 0x10) + output().set_indexed_value("led_e", row, BIT(data, 8-row)); + if (m_led_sel & 0x20) + output().set_indexed_value("led_f", row, BIT(data, 8-row)); + if (m_led_sel & 0x40) + output().set_indexed_value("led_g", row, BIT(data, 8-row)); + if (m_led_sel & 0x80) + output().set_indexed_value("led_h", row, BIT(data, 8-row)); + if (m_led_sel & 0x100) + output().set_indexed_value("led_i", row, BIT(data, 8-row)); + if (m_led_sel & 0x200) + { + output().set_indexed_value("led_j", row, BIT(data, 8-row)); + if ((data&0x01)==m_setup) + { // 'CHANGEBOARD'-LED -> switch setup mode + m_setup=!BIT(data, 0); + m_started=true; + if ((m_lastfield!=99) && (m_board[m_lastfield]>12)) + { + m_board[m_lastfield]=EM; + output().set_indexed_value("P", m_lastfield, EM); + } + m_lastfield=99; + m_lastpiece=EM; + m_capture=false; + m_castling=false; + m_enpassant=false; + m_moveok=true; + } + } + } + + m_led_sel = 0; + m_thinking=0; +} + +WRITE8_MEMBER( chessmst_state::pio1_port_b_w ) +{ + m_matrix = (m_matrix & 0xff) | ((data & 0x01)<<8); + m_led_sel = (m_led_sel & 0xff) | ((data & 0x03)<<8); + + m_speaker->level_w(BIT(data, 6)); +} + +READ8_MEMBER( chessmst_state::pio2_port_a_r ) +{ + UINT8 data = 0x00; + + // The pieces position on the chessboard is identified by 64 Hall + // sensors, which are in a 8x8 matrix with the corresponding LEDs. + for (int i=0; i<8; i++) + { + if (m_matrix & 0x01) + data |= (m_sensor[0+i] ? (1<read(); + if (data != m_lastdata) + { + m_lastdata=data; + if ((data&0x80) || (data&0x10)) + m_started=true; // NEWGAME or BOARD -> switch OFF clear board + else + if (m_setup) + { + if (BIT(data, 0)) + { // HINT -> delete current piece + if (m_lastfield!=99) + { + m_board[m_lastfield]=EM; + output().set_indexed_value("P", m_lastfield, EM); + m_lastfield=99; + m_lastpiece=EM; + } + } + } + } + } + return data; +} + +WRITE8_MEMBER( chessmst_state::pio2_port_b_w ) +{ + m_matrix = (data & 0xff) | (m_matrix & 0x100); + m_led_sel = (data & 0xff) | (m_led_sel & 0x300); +} + +static const z80_daisy_config chessmst_daisy_chain[] = +{ + { "z80pio1" }, + { nullptr } +}; static ADDRESS_MAP_START(chessmst_mem, AS_PROGRAM, 8, chessmst_state) ADDRESS_MAP_UNMAP_HIGH @@ -59,21 +461,6 @@ static ADDRESS_MAP_START( chessmst_io , AS_IO, 8, chessmst_state) AM_RANGE(0x08, 0x0b) AM_MIRROR(0xf0) AM_DEVREADWRITE("z80pio2", z80pio_device, read, write) ADDRESS_MAP_END -INPUT_CHANGED_MEMBER(chessmst_state::reset_button) -{ - m_maincpu->set_input_line(INPUT_LINE_RESET, newval ? ASSERT_LINE : CLEAR_LINE); -} - -INPUT_CHANGED_MEMBER(chessmst_state::chessmst_sensor) -{ - UINT8 pos = (UINT8)(FPTR)param; - - if (newval) - { - m_sensor[pos] = !m_sensor[pos]; - } -} - /* Input ports */ static INPUT_PORTS_START( chessmst ) PORT_START("COL_A") @@ -157,104 +544,16 @@ static INPUT_PORTS_START( chessmst ) PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("Board [3]") PORT_CODE(KEYCODE_3) PORT_CODE(KEYCODE_B) PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("Color [2]") PORT_CODE(KEYCODE_2) PORT_CODE(KEYCODE_C) PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("Level [1]") PORT_CODE(KEYCODE_1) PORT_CODE(KEYCODE_L) - PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("New Game [0]") PORT_CODE(KEYCODE_0) PORT_CODE(KEYCODE_ENTER) + PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("New Game [0]") PORT_CODE(KEYCODE_0) PORT_CODE(KEYCODE_N) PORT_START("EXTRA") - PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Halt") PORT_CODE(KEYCODE_F2) PORT_WRITE_LINE_DEVICE_MEMBER("z80pio1", z80pio_device, strobe_a) // -> PIO(1) ASTB pin - PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Reset") PORT_CODE(KEYCODE_F1) PORT_CHANGED_MEMBER(DEVICE_SELF, chessmst_state, reset_button, 0) // -> Z80 RESET pin + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Halt") PORT_CODE(KEYCODE_ESC) PORT_WRITE_LINE_DEVICE_MEMBER("z80pio1", z80pio_device, strobe_a) // -> PIO(1) ASTB pin + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Reset") PORT_CODE(KEYCODE_F10) PORT_CHANGED_MEMBER(DEVICE_SELF, chessmst_state, reset_button, 0) // -> Z80 RESET pin + + PORT_START("CLEAR") + PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CHANGED_MEMBER(DEVICE_SELF, chessmst_state, clear_pieces, 0) INPUT_PORTS_END -void chessmst_state::machine_reset() -{ - //reset all sensors - memset(m_sensor, 1, sizeof(m_sensor)); - - //positioning the pieces for start next game - for (int i=0; i<64; i+=8) - m_sensor[i+0] = m_sensor[i+1] = m_sensor[i+6] = m_sensor[i+7] = 0; -} - -WRITE8_MEMBER( chessmst_state::pio1_port_a_w ) -{ - for (int row=1; row<=8; row++) - { - if (m_led_sel & 0x01) - output().set_indexed_value("led_a", row, BIT(data, 8-row)); - if (m_led_sel & 0x02) - output().set_indexed_value("led_b", row, BIT(data, 8-row)); - if (m_led_sel & 0x04) - output().set_indexed_value("led_c", row, BIT(data, 8-row)); - if (m_led_sel & 0x08) - output().set_indexed_value("led_d", row, BIT(data, 8-row)); - if (m_led_sel & 0x10) - output().set_indexed_value("led_e", row, BIT(data, 8-row)); - if (m_led_sel & 0x20) - output().set_indexed_value("led_f", row, BIT(data, 8-row)); - if (m_led_sel & 0x40) - output().set_indexed_value("led_g", row, BIT(data, 8-row)); - if (m_led_sel & 0x80) - output().set_indexed_value("led_h", row, BIT(data, 8-row)); - if (m_led_sel & 0x100) - output().set_indexed_value("led_i", row, BIT(data, 8-row)); - if (m_led_sel & 0x200) - output().set_indexed_value("led_j", row, BIT(data, 8-row)); - } - - m_led_sel = 0; -} - -WRITE8_MEMBER( chessmst_state::pio1_port_b_w ) -{ - m_matrix = (m_matrix & 0xff) | ((data & 0x01)<<8); - m_led_sel = (m_led_sel & 0xff) | ((data & 0x03)<<8); - - m_speaker->level_w(BIT(data, 6)); -} - -READ8_MEMBER( chessmst_state::pio2_port_a_r ) -{ - UINT8 data = 0x00; - - // The pieces position on the chessboard is identified by 64 Hall - // sensors, which are in a 8x8 matrix with the corresponding LEDs. - for (int i=0; i<8; i++) - { - if (m_matrix & 0x01) - data |= (m_sensor[0+i] ? (1<read(); - - return data; -} - -WRITE8_MEMBER( chessmst_state::pio2_port_b_w ) -{ - m_matrix = (data & 0xff) | (m_matrix & 0x100); - m_led_sel = (data & 0xff) | (m_led_sel & 0x300); -} - -static const z80_daisy_config chessmst_daisy_chain[] = -{ - { "z80pio1" }, - { nullptr } -}; - static MACHINE_CONFIG_START( chessmst, chessmst_state ) /* basic machine hardware */ @@ -262,13 +561,14 @@ static MACHINE_CONFIG_START( chessmst, chessmst_state ) MCFG_CPU_PROGRAM_MAP(chessmst_mem) MCFG_CPU_IO_MAP(chessmst_io) MCFG_Z80_DAISY_CHAIN(chessmst_daisy_chain) + MCFG_TIMER_DRIVER_ADD_PERIODIC("led_update", chessmst_state, led_update, attotime::from_msec(250)) - MCFG_DEVICE_ADD("z80pio1", Z80PIO, XTAL_9_8304MHz/4) + MCFG_DEVICE_ADD("z80pio1", Z80PIO, XTAL_9_8304MHz/4) // U880 Z80 clone MCFG_Z80PIO_OUT_INT_CB(INPUTLINE("maincpu", INPUT_LINE_IRQ0)) MCFG_Z80PIO_OUT_PA_CB(WRITE8(chessmst_state, pio1_port_a_w)) MCFG_Z80PIO_OUT_PB_CB(WRITE8(chessmst_state, pio1_port_b_w)) - MCFG_DEVICE_ADD("z80pio2", Z80PIO, XTAL_9_8304MHz/4) + MCFG_DEVICE_ADD("z80pio2", Z80PIO, XTAL_9_8304MHz/4) // U880 Z80 clone MCFG_Z80PIO_IN_PA_CB(READ8(chessmst_state, pio2_port_a_r)) MCFG_Z80PIO_OUT_PB_CB(WRITE8(chessmst_state, pio2_port_b_w)) @@ -287,6 +587,7 @@ static MACHINE_CONFIG_START( chessmsta, chessmst_state ) MCFG_CPU_PROGRAM_MAP(chessmst_mem) MCFG_CPU_IO_MAP(chessmst_io) MCFG_Z80_DAISY_CHAIN(chessmst_daisy_chain) + MCFG_TIMER_DRIVER_ADD_PERIODIC("led_update", chessmst_state, led_update, attotime::from_msec(310)) MCFG_DEVICE_ADD("z80pio1", Z80PIO, XTAL_8MHz/4) MCFG_Z80PIO_OUT_INT_CB(INPUTLINE("maincpu", INPUT_LINE_IRQ0)) @@ -305,7 +606,6 @@ static MACHINE_CONFIG_START( chessmsta, chessmst_state ) MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50) MACHINE_CONFIG_END - /* ROM definition */ ROM_START( chessmst ) ROM_REGION( 0x10000, "maincpu", ROMREGION_ERASEFF ) @@ -327,9 +627,8 @@ ROM_START( chessmsta ) ROM_LOAD( "u2616bm108.bin", 0x2000, 0x0800, CRC(6e69ace3) SHA1(e099b6b6cc505092f64b8d51ab9c70aa64f58f70) ) ROM_END - /* Driver */ /* YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY, FULLNAME, FLAGS */ -COMP( 1984, chessmst, 0, 0, chessmst, chessmst, driver_device, 0, "VEB Mikroelektronik Erfurt", "Chess-Master (set 1)", MACHINE_NOT_WORKING | MACHINE_CLICKABLE_ARTWORK ) +COMP( 1984, chessmst, 0, 0, chessmst, chessmst, driver_device, 0, "VEB Mikroelektronik Erfurt", "Chess-Master (set 1)", MACHINE_SUPPORTS_SAVE | MACHINE_CLICKABLE_ARTWORK ) COMP( 1984, chessmsta, chessmst, 0, chessmsta, chessmst, driver_device, 0, "VEB Mikroelektronik Erfurt", "Chess-Master (set 2)", MACHINE_NOT_WORKING | MACHINE_CLICKABLE_ARTWORK )