From 5b533f87d725125bbc61599a5152586ccd28942d Mon Sep 17 00:00:00 2001 From: Dirk Best Date: Wed, 16 May 2018 02:19:06 +0200 Subject: model1: Emulate the I/O board used by Wing War and Netmerc It's also used by Virtua Cop, will be hooked up later to it. --- scripts/target/mame/arcade.lua | 2 + src/mame/drivers/model1.cpp | 283 ++++++++++++++++++++++----------- src/mame/includes/model1.h | 9 +- src/mame/layout/model1io2.lay | 46 ++++++ src/mame/machine/315_5338a.cpp | 17 +- src/mame/machine/model1io2.cpp | 349 +++++++++++++++++++++++++++++++++++++++++ src/mame/machine/model1io2.h | 153 ++++++++++++++++++ 7 files changed, 760 insertions(+), 99 deletions(-) create mode 100644 src/mame/layout/model1io2.lay create mode 100644 src/mame/machine/model1io2.cpp create mode 100644 src/mame/machine/model1io2.h diff --git a/scripts/target/mame/arcade.lua b/scripts/target/mame/arcade.lua index ffa0fc69264..823e64c38e4 100644 --- a/scripts/target/mame/arcade.lua +++ b/scripts/target/mame/arcade.lua @@ -3382,6 +3382,8 @@ files { MAME_DIR .. "src/mame/machine/315_5649.h", MAME_DIR .. "src/mame/machine/model1io.cpp", MAME_DIR .. "src/mame/machine/model1io.h", + MAME_DIR .. "src/mame/machine/model1io2.cpp", + MAME_DIR .. "src/mame/machine/model1io2.h", MAME_DIR .. "src/mame/machine/fd1089.cpp", MAME_DIR .. "src/mame/machine/fd1089.h", MAME_DIR .. "src/mame/machine/fd1094.cpp", diff --git a/src/mame/drivers/model1.cpp b/src/mame/drivers/model1.cpp index dd0a02a5c04..293a1c2a714 100644 --- a/src/mame/drivers/model1.cpp +++ b/src/mame/drivers/model1.cpp @@ -585,16 +585,24 @@ Notes: #include "cpu/i386/i386.h" #include "machine/clock.h" -#include "machine/mb8421.h" #include "machine/model1io.h" +#include "machine/model1io2.h" #include "speaker.h" #include "vr.lh" +#include "model1io2.lh" // On the real system, another 315-5338A is acting as slave // and writes the data to the dual port RAM. This isn't // emulated yet, data just gets written to RAM. +READ8_MEMBER( model1_state::dpram_r ) +{ + // insert waitstate + m_maincpu->adjust_icount(-1); + return m_dpram->right_r(space, offset); +} + WRITE8_MEMBER( model1_state::vf_outputs_w ) { // 7654---- unknown (not used?) @@ -677,6 +685,63 @@ WRITE8_MEMBER( model1_state::netmerc_outputs_w ) machine().bookkeeping().coin_counter_w(0, BIT(data, 0)); } +READ8_MEMBER( model1_state::r360_r ) +{ + return m_r360_state; +} + +WRITE8_MEMBER( model1_state::r360_w ) +{ + /* + this uses the feedback board protocol + command group B - these seem to be gamestates + + bf = init + be = attract + bd = setup #1 (lower safety bar etc.) + bc = setup #2 (push emergency button) + bb = ready to go + ba = ingame + b9 = game over + + results: + 40 = default status + 41 = * (setup #1 ack) + 42 = lowered safety bar + 43 = closed belt + 44 = lever up + 45 = pushed button + 46 = game start + 47 = game over + 48 = lever down + 49 = released belt + */ + switch (data & 0xff) + { + case 0xbf: + case 0xbe: + m_r360_state = ~0x40; + break; + + case 0xbd: + m_r360_state = ~0x44; + break; + + case 0xbc: + m_r360_state = ~0x45; + break; + + case 0xbb: + m_r360_state = ~0x46; + break; + + case 0xba: + case 0xb9: + m_r360_state = ~0x40; + break; + } +} + READ16_MEMBER(model1_state::fifoin_status_r) { return 0xffff; @@ -871,7 +936,7 @@ void model1_state::model1_mem(address_map &map) map(0x900000, 0x903fff).ram().w(this, FUNC(model1_state::p_w)).share("palette"); map(0x910000, 0x91bfff).ram().share("color_xlat"); - map(0xc00000, 0xc00fff).rw("dpram", FUNC(mb8421_device::right_r), FUNC(mb8421_device::right_w)).umask16(0x00ff); // 2k*8-bit dual port ram + map(0xc00000, 0xc00fff).r(this, FUNC(model1_state::dpram_r)).w(m_dpram, FUNC(mb8421_device::right_w)).umask16(0x00ff); // 2k*8-bit dual port ram map(0xc40000, 0xc40000).rw(m_m1uart, FUNC(i8251_device::data_r), FUNC(i8251_device::data_w)); map(0xc40002, 0xc40002).rw(m_m1uart, FUNC(i8251_device::status_r), FUNC(i8251_device::control_w)); @@ -1028,17 +1093,44 @@ static INPUT_PORTS_START( wingwar ) PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(1) PORT_NAME("Smoke") PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) - PORT_START("IN.2") /* 8Bit RX-line from r360 board */ - PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED ) - PORT_START("STICKX") PORT_BIT( 0xff, 0x80, IPT_AD_STICK_X ) PORT_SENSITIVITY(100) PORT_KEYDELTA(4) PORT_REVERSE PORT_START("STICKY") - PORT_BIT( 0xff, 0x80, IPT_AD_STICK_Y ) PORT_SENSITIVITY(100) PORT_KEYDELTA(4) PORT_REVERSE + PORT_BIT( 0xff, 0x80, IPT_AD_STICK_Y ) PORT_SENSITIVITY(100) PORT_KEYDELTA(4) PORT_START("THROTTLE") PORT_BIT( 0xff, 0x01, IPT_PEDAL ) PORT_MINMAX(1,0xff) PORT_SENSITIVITY(100) PORT_KEYDELTA(16) + + PORT_START("ioboard:dsw1") + PORT_DIPUNKNOWN_DIPLOC(0x01, 0x01, "DSW1:1") + PORT_DIPUNKNOWN_DIPLOC(0x02, 0x02, "DSW1:2") + PORT_DIPUNKNOWN_DIPLOC(0x04, 0x04, "DSW1:3") + PORT_DIPUNKNOWN_DIPLOC(0x08, 0x08, "DSW1:4") + PORT_DIPUNKNOWN_DIPLOC(0x10, 0x10, "DSW1:5") + PORT_DIPUNKNOWN_DIPLOC(0x20, 0x20, "DSW1:6") + PORT_DIPUNKNOWN_DIPLOC(0x40, 0x40, "DSW1:7") + PORT_DIPUNKNOWN_DIPLOC(0x80, 0x80, "DSW1:8") + + PORT_START("ioboard:dsw2") + PORT_DIPUNKNOWN_DIPLOC(0x01, 0x01, "DSW2:1") + PORT_DIPUNKNOWN_DIPLOC(0x02, 0x02, "DSW2:2") + PORT_DIPUNKNOWN_DIPLOC(0x04, 0x04, "DSW2:3") + PORT_DIPUNKNOWN_DIPLOC(0x08, 0x08, "DSW2:4") + PORT_DIPUNKNOWN_DIPLOC(0x10, 0x10, "DSW2:5") + PORT_DIPUNKNOWN_DIPLOC(0x20, 0x20, "DSW2:6") + PORT_DIPUNKNOWN_DIPLOC(0x40, 0x40, "DSW2:7") + PORT_DIPUNKNOWN_DIPLOC(0x80, 0x80, "DSW2:8") + + PORT_START("ioboard:dsw3") + PORT_DIPUNKNOWN_DIPLOC(0x01, 0x01, "DSW3:1") + PORT_DIPUNKNOWN_DIPLOC(0x02, 0x02, "DSW3:2") + PORT_DIPUNKNOWN_DIPLOC(0x04, 0x04, "DSW3:3") + PORT_DIPUNKNOWN_DIPLOC(0x08, 0x08, "DSW3:4") + PORT_DIPUNKNOWN_DIPLOC(0x10, 0x10, "DSW3:5") + PORT_DIPUNKNOWN_DIPLOC(0x20, 0x20, "DSW3:6") + PORT_DIPUNKNOWN_DIPLOC(0x40, 0x40, "DSW3:7") + PORT_DIPUNKNOWN_DIPLOC(0x80, 0x80, "DSW3:8") INPUT_PORTS_END static INPUT_PORTS_START( wingwar360 ) @@ -1050,6 +1142,12 @@ static INPUT_PORTS_START( wingwar360 ) PORT_MODIFY("IN.1") PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_MODIFY("STICKX") + PORT_BIT( 0xff, 0x80, IPT_AD_STICK_X ) PORT_SENSITIVITY(100) PORT_KEYDELTA(4) + + PORT_MODIFY("STICKY") + PORT_BIT( 0xff, 0x80, IPT_AD_STICK_Y ) PORT_SENSITIVITY(100) PORT_KEYDELTA(4) PORT_REVERSE INPUT_PORTS_END static INPUT_PORTS_START( netmerc ) @@ -1066,14 +1164,41 @@ static INPUT_PORTS_START( netmerc ) PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("MVD Holder") PORT_BIT( 0xf8, IP_ACTIVE_LOW, IPT_UNUSED ) - PORT_START("IN.2") - PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED ) - PORT_START("STICKX") PORT_BIT( 0xff, 0x7f, IPT_AD_STICK_X ) PORT_SENSITIVITY(100) PORT_KEYDELTA(4) PORT_REVERSE PORT_START("STICKY") PORT_BIT( 0xff, 0x7f, IPT_AD_STICK_Y ) PORT_SENSITIVITY(100) PORT_KEYDELTA(4) PORT_REVERSE + + PORT_START("ioboard:dsw1") + PORT_DIPUNKNOWN_DIPLOC(0x01, 0x01, "DSW1:1") + PORT_DIPUNKNOWN_DIPLOC(0x02, 0x02, "DSW1:2") + PORT_DIPUNKNOWN_DIPLOC(0x04, 0x04, "DSW1:3") + PORT_DIPUNKNOWN_DIPLOC(0x08, 0x08, "DSW1:4") + PORT_DIPUNKNOWN_DIPLOC(0x10, 0x10, "DSW1:5") + PORT_DIPUNKNOWN_DIPLOC(0x20, 0x20, "DSW1:6") + PORT_DIPUNKNOWN_DIPLOC(0x40, 0x40, "DSW1:7") + PORT_DIPUNKNOWN_DIPLOC(0x80, 0x80, "DSW1:8") + + PORT_START("ioboard:dsw2") + PORT_DIPUNKNOWN_DIPLOC(0x01, 0x01, "DSW2:1") + PORT_DIPUNKNOWN_DIPLOC(0x02, 0x02, "DSW2:2") + PORT_DIPUNKNOWN_DIPLOC(0x04, 0x04, "DSW2:3") + PORT_DIPUNKNOWN_DIPLOC(0x08, 0x08, "DSW2:4") + PORT_DIPUNKNOWN_DIPLOC(0x10, 0x10, "DSW2:5") + PORT_DIPUNKNOWN_DIPLOC(0x20, 0x20, "DSW2:6") + PORT_DIPUNKNOWN_DIPLOC(0x40, 0x40, "DSW2:7") + PORT_DIPUNKNOWN_DIPLOC(0x80, 0x80, "DSW2:8") + + PORT_START("ioboard:dsw3") + PORT_DIPUNKNOWN_DIPLOC(0x01, 0x01, "DSW3:1") + PORT_DIPUNKNOWN_DIPLOC(0x02, 0x02, "DSW3:2") + PORT_DIPUNKNOWN_DIPLOC(0x04, 0x04, "DSW3:3") + PORT_DIPUNKNOWN_DIPLOC(0x08, 0x08, "DSW3:4") + PORT_DIPUNKNOWN_DIPLOC(0x10, 0x10, "DSW3:5") + PORT_DIPUNKNOWN_DIPLOC(0x20, 0x20, "DSW3:6") + PORT_DIPUNKNOWN_DIPLOC(0x40, 0x40, "DSW3:7") + PORT_DIPUNKNOWN_DIPLOC(0x80, 0x80, "DSW3:8") INPUT_PORTS_END @@ -1352,6 +1477,9 @@ ROM_START( wingwar ) ROM_LOAD32_BYTE( "mpr-16742.40", 0x000001, 0x80000, CRC(e9cc12bb) SHA1(40c83c968be3b11fad193a00e7b760f074450683) ) ROM_LOAD32_BYTE( "mpr-16739.41", 0x000002, 0x80000, CRC(6c73e98f) SHA1(7b31e62922ab6d0df97c3ecc52b78e6d086c8635) ) ROM_LOAD32_BYTE( "mpr-16740.42", 0x000003, 0x80000, CRC(44b31007) SHA1(4bb265fea25a7bbcbb8ab080fdcf09849b18f1de) ) + + ROM_REGION( 0x10000, "ioboard:iocpu", 0 ) // taken from r360 version, is it the same? + ROM_LOAD("epr-16891.6", 0x00000, 0x10000, CRC(a33f84d1) SHA1(3079397c7241c1a6f494fa310faff0989dfa04a0) ) ROM_END ROM_START( wingwaru ) @@ -1404,6 +1532,9 @@ ROM_START( wingwaru ) ROM_LOAD32_BYTE( "mpr-16742.40", 0x000001, 0x80000, CRC(e9cc12bb) SHA1(40c83c968be3b11fad193a00e7b760f074450683) ) ROM_LOAD32_BYTE( "mpr-16739.41", 0x000002, 0x80000, CRC(6c73e98f) SHA1(7b31e62922ab6d0df97c3ecc52b78e6d086c8635) ) ROM_LOAD32_BYTE( "mpr-16740.42", 0x000003, 0x80000, CRC(44b31007) SHA1(4bb265fea25a7bbcbb8ab080fdcf09849b18f1de) ) + + ROM_REGION( 0x10000, "ioboard:iocpu", 0 ) // taken from r360 version, is it the same? + ROM_LOAD("epr-16891.6", 0x00000, 0x10000, CRC(a33f84d1) SHA1(3079397c7241c1a6f494fa310faff0989dfa04a0) ) ROM_END ROM_START( wingwarj ) @@ -1456,6 +1587,9 @@ ROM_START( wingwarj ) ROM_LOAD32_BYTE( "mpr-16742.40", 0x000001, 0x80000, CRC(e9cc12bb) SHA1(40c83c968be3b11fad193a00e7b760f074450683) ) ROM_LOAD32_BYTE( "mpr-16739.41", 0x000002, 0x80000, CRC(6c73e98f) SHA1(7b31e62922ab6d0df97c3ecc52b78e6d086c8635) ) ROM_LOAD32_BYTE( "mpr-16740.42", 0x000003, 0x80000, CRC(44b31007) SHA1(4bb265fea25a7bbcbb8ab080fdcf09849b18f1de) ) + + ROM_REGION( 0x10000, "ioboard:iocpu", 0 ) // taken from r360 version, is it the same? + ROM_LOAD("epr-16891.6", 0x00000, 0x10000, CRC(a33f84d1) SHA1(3079397c7241c1a6f494fa310faff0989dfa04a0) ) ROM_END // Dumper's note: As per other R360 games wingwar is just a slightly modified version with 4 roms different on the rom board. @@ -1511,7 +1645,7 @@ ROM_START( wingwar360 ) ROM_LOAD32_BYTE( "mpr-16739.41", 0x000002, 0x80000, CRC(6c73e98f) SHA1(7b31e62922ab6d0df97c3ecc52b78e6d086c8635) ) ROM_LOAD32_BYTE( "mpr-16740.42", 0x000003, 0x80000, CRC(44b31007) SHA1(4bb265fea25a7bbcbb8ab080fdcf09849b18f1de) ) - ROM_REGION( 0x10000, "ioboard", 0 ) + ROM_REGION( 0x10000, "ioboard:iocpu", 0 ) ROM_LOAD("epr-16891.6", 0x00000, 0x10000, CRC(a33f84d1) SHA1(3079397c7241c1a6f494fa310faff0989dfa04a0) ) // Dumper's note: Video & Drive is the control board in the attendants' tower, same hardware as G-Loc R360 with the two program roms being the only difference. @@ -1558,7 +1692,7 @@ ROM_START( netmerc ) ROM_REGION32_LE( 0x200000, "tgp_data", ROMREGION_ERASE00 ) // IC39-IC42 unpopulated - ROM_REGION( 0x10000, "ioboard", 0 ) /* IO board */ + ROM_REGION( 0x10000, "ioboard:iocpu", 0 ) ROM_LOAD( "epr-18021.ic6", 0x00000, 0x10000, CRC(5551837e) SHA1(bf5b9aad99c0f8f5e262e0855796f39119d11a97) ) ROM_REGION( 0x8000, "polhemus", 0 ) /* POLHEMUS board */ @@ -1690,11 +1824,19 @@ MACHINE_CONFIG_START(model1_state::wingwar) MCFG_DEVICE_MODIFY("maincpu") MCFG_DEVICE_PROGRAM_MAP(model1_comm_mem) - MCFG_DEVICE_MODIFY("ioboard") - MCFG_MODEL1IO_AN0_CB(IOPORT("STICKX")) - MCFG_MODEL1IO_AN1_CB(IOPORT("STICKY")) - MCFG_MODEL1IO_AN2_CB(IOPORT("THROTTLE")) - MCFG_MODEL1IO_OUTPUT_CB(WRITE8(*this, model1_state, wingwar_outputs_w)) + MCFG_DEVICE_REMOVE("ioboard") + + MCFG_DEVICE_ADD("ioboard", SEGA_MODEL1IO2, 0) + MCFG_MODEL1IO2_READ_CB(READ8("dpram", mb8421_device, left_r)) + MCFG_MODEL1IO2_WRITE_CB(WRITE8("dpram", mb8421_device, left_w)) + MCFG_MODEL1IO2_IN0_CB(IOPORT("IN.0")) + MCFG_MODEL1IO2_IN1_CB(IOPORT("IN.1")) + MCFG_MODEL1IO2_AN0_CB(IOPORT("STICKX")) + MCFG_MODEL1IO2_AN1_CB(IOPORT("STICKY")) + MCFG_MODEL1IO2_AN2_CB(IOPORT("THROTTLE")) + MCFG_MODEL1IO2_OUTPUT_CB(WRITE8(*this, model1_state, wingwar_outputs_w)) + + MCFG_DEFAULT_LAYOUT(layout_model1io2) MCFG_M1COMM_ADD(M1COMM_TAG) MCFG_DEVICE_BIOS("epr15112"); @@ -1704,7 +1846,12 @@ MACHINE_CONFIG_START(model1_state::wingwar360) wingwar(config); MCFG_DEVICE_MODIFY("ioboard") - MCFG_MODEL1IO_OUTPUT_CB(WRITE8(*this, model1_state, wingwar360_outputs_w)) + MCFG_MODEL1IO2_IN2_CB(READ8(*this, model1_state, r360_r)) + MCFG_MODEL1IO2_DRIVE_WRITE_CB(WRITE8(*this, model1_state, r360_w)) + MCFG_MODEL1IO2_AN2_CB(NOOP) + MCFG_MODEL1IO2_OUTPUT_CB(WRITE8(*this, model1_state, wingwar360_outputs_w)) + + MCFG_DEFAULT_LAYOUT(layout_model1io2) MACHINE_CONFIG_END void model1_state::polhemus_map(address_map &map) @@ -1719,83 +1866,31 @@ MACHINE_CONFIG_START(model1_state::netmerc) MCFG_DEVICE_ADD("polhemus", I386SX, 16000000) MCFG_DEVICE_PROGRAM_MAP(polhemus_map) - MCFG_DEVICE_MODIFY("ioboard") - MCFG_MODEL1IO_AN0_CB(IOPORT("STICKX")) - MCFG_MODEL1IO_AN2_CB(IOPORT("STICKY")) - MCFG_MODEL1IO_OUTPUT_CB(WRITE8(*this, model1_state, netmerc_outputs_w)) + MCFG_DEVICE_REMOVE("ioboard") + + MCFG_DEVICE_ADD("ioboard", SEGA_MODEL1IO2, 0) + MCFG_MODEL1IO2_READ_CB(READ8("dpram", mb8421_device, left_r)) + MCFG_MODEL1IO2_WRITE_CB(WRITE8("dpram", mb8421_device, left_w)) + MCFG_MODEL1IO2_IN0_CB(IOPORT("IN.0")) + MCFG_MODEL1IO2_IN1_CB(IOPORT("IN.1")) + MCFG_MODEL1IO2_AN0_CB(IOPORT("STICKX")) + MCFG_MODEL1IO2_AN2_CB(IOPORT("STICKY")) + MCFG_MODEL1IO2_OUTPUT_CB(WRITE8(*this, model1_state, netmerc_outputs_w)) + MCFG_DEFAULT_LAYOUT(layout_model1io2) MACHINE_CONFIG_END -void model1_state::init_wingwar360() -{ - // install r360 hack - m_maincpu->space(AS_PROGRAM).install_read_handler(0xc00014, 0xc00015, read16_delegate(FUNC(model1_state::r360_r),this)); - m_maincpu->space(AS_PROGRAM).install_write_handler(0xc00022, 0xc00023, write16_delegate(FUNC(model1_state::r360_w),this)); -} - -READ16_MEMBER(model1_state::r360_r) -{ - return m_r360_state; -} - -WRITE16_MEMBER(model1_state::r360_w) -{ - /* - this uses the feedback board protocol - command group B - these seem to be gamestates - - bf = init - be = attract - bd = setup #1 (lower safety bar etc.) - bc = setup #2 (push emergency button) - bb = ready to go - ba = ingame - b9 = game over - - results: - 40 = default status - 41 = * (setup #1 ack) - 42 = lowered safety bar - 43 = closed belt - 44 = lever up - 45 = pushed button - 46 = game start - 47 = game over - 48 = lever down - 49 = released belt - */ - switch (data & 0xff) - { - case 0xbf: - case 0xbe: - m_r360_state = ~0x40; - break; - - case 0xbd: - m_r360_state = ~0x44; - break; - - case 0xbc: - m_r360_state = ~0x45; - break; - - case 0xbb: - m_r360_state = ~0x46; - break; - - case 0xba: - case 0xb9: - m_r360_state = ~0x40; - break; - } -} - -GAME( 1993, vf, 0, vf, vf, model1_state, empty_init, ROT0, "Sega", "Virtua Fighter", MACHINE_IMPERFECT_GRAPHICS ) -GAMEL(1992, vr, 0, vr, vr, model1_state, empty_init, ROT0, "Sega", "Virtua Racing", 0, layout_vr ) -GAME( 1993, vformula, vr, vformula, vr, model1_state, empty_init, ROT0, "Sega", "Virtua Formula", MACHINE_IMPERFECT_GRAPHICS ) -GAME( 1993, swa, 0, swa, swa, model1_state, empty_init, ROT0, "Sega", "Star Wars Arcade", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND ) -GAME( 1994, wingwar, 0, wingwar, wingwar, model1_state, empty_init, ROT0, "Sega", "Wing War (World)", MACHINE_NOT_WORKING ) -GAME( 1994, wingwaru, wingwar, wingwar, wingwar, model1_state, empty_init, ROT0, "Sega", "Wing War (US)", MACHINE_NOT_WORKING ) -GAME( 1994, wingwarj, wingwar, wingwar, wingwar, model1_state, empty_init, ROT0, "Sega", "Wing War (Japan)", MACHINE_NOT_WORKING ) -GAME( 1994, wingwar360, wingwar, wingwar360, wingwar360, model1_state, init_wingwar360, ROT0, "Sega", "Wing War R360 (US)", MACHINE_NOT_WORKING ) -GAME( 1993, netmerc, 0, netmerc, netmerc, model1_state, empty_init, ROT0, "Sega", "Sega NetMerc", MACHINE_NOT_WORKING ) +//************************************************************************** +// SYSTEM DRIVERS +//************************************************************************** + +// YEAR NAME PARENT MACHINE INPUT CLASS INIT ROTATION COMPANY FULLNAME FLAGS +GAME( 1993, vf, 0, vf, vf, model1_state, empty_init, ROT0, "Sega", "Virtua Fighter", MACHINE_IMPERFECT_GRAPHICS ) +GAMEL(1992, vr, 0, vr, vr, model1_state, empty_init, ROT0, "Sega", "Virtua Racing", 0, layout_vr ) +GAME( 1993, vformula, vr, vformula, vr, model1_state, empty_init, ROT0, "Sega", "Virtua Formula", MACHINE_IMPERFECT_GRAPHICS ) +GAME( 1993, swa, 0, swa, swa, model1_state, empty_init, ROT0, "Sega", "Star Wars Arcade", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND ) +GAME( 1994, wingwar, 0, wingwar, wingwar, model1_state, empty_init, ROT0, "Sega", "Wing War (World)", MACHINE_NOT_WORKING ) +GAME( 1994, wingwaru, wingwar, wingwar, wingwar, model1_state, empty_init, ROT0, "Sega", "Wing War (US)", MACHINE_NOT_WORKING ) +GAME( 1994, wingwarj, wingwar, wingwar, wingwar, model1_state, empty_init, ROT0, "Sega", "Wing War (Japan)", MACHINE_NOT_WORKING ) +GAME( 1994, wingwar360, wingwar, wingwar360, wingwar360, model1_state, empty_init, ROT0, "Sega", "Wing War R360 (US)", MACHINE_NOT_WORKING ) +GAME( 1993, netmerc, 0, netmerc, netmerc, model1_state, empty_init, ROT0, "Sega", "Sega NetMerc", MACHINE_NOT_WORKING ) diff --git a/src/mame/includes/model1.h b/src/mame/includes/model1.h index a3f6a2b2903..c89e12463e0 100644 --- a/src/mame/includes/model1.h +++ b/src/mame/includes/model1.h @@ -12,6 +12,7 @@ #include "cpu/v60/v60.h" #include "machine/i8251.h" #include "machine/gen_fifo.h" +#include "machine/mb8421.h" #include "machine/m1comm.h" #include "machine/timer.h" #include "video/segaic24.h" @@ -34,6 +35,7 @@ public: model1_state(const machine_config &mconfig, device_type type, const char *tag) : driver_device(mconfig, type, tag) , m_maincpu(*this, "maincpu") + , m_dpram(*this, "dpram") , m_m1audio(*this, M1AUDIO_TAG) , m_m1uart(*this, "m1uart") , m_m1comm(*this, "m1comm") @@ -116,9 +118,8 @@ public: u32 m_copro_ram_adr; uint16_t m_r360_state; - void init_wingwar360(); - DECLARE_READ16_MEMBER(r360_r); - DECLARE_WRITE16_MEMBER(r360_w); + DECLARE_READ8_MEMBER(r360_r); + DECLARE_WRITE8_MEMBER(r360_w); // Rendering DECLARE_VIDEO_START(model1); @@ -235,6 +236,7 @@ private: // Devices required_device m_maincpu; // V60 + required_device m_dpram; required_device m_m1audio; // Model 1 standard sound board required_device m_m1uart; optional_device m_m1comm; // Model 1 communication board @@ -502,6 +504,7 @@ private: // I/O related output_finder<2> m_digits; + DECLARE_READ8_MEMBER(dpram_r); DECLARE_WRITE8_MEMBER(vf_outputs_w); DECLARE_WRITE8_MEMBER(vr_outputs_w); DECLARE_WRITE8_MEMBER(swa_outputs_w); diff --git a/src/mame/layout/model1io2.lay b/src/mame/layout/model1io2.lay new file mode 100644 index 00000000000..3c62bd3a522 --- /dev/null +++ b/src/mame/layout/model1io2.lay @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/mame/machine/315_5338a.cpp b/src/mame/machine/315_5338a.cpp index 1d6cc4abcdc..3dff2458933 100644 --- a/src/mame/machine/315_5338a.cpp +++ b/src/mame/machine/315_5338a.cpp @@ -88,6 +88,8 @@ READ8_MEMBER( sega_315_5338a_device::read ) data = m_port_value[offset]; break; + case 0x08: data = m_port_config; break; + // serial data read back? case 0x0a: data = m_serial_output; break; @@ -124,11 +126,22 @@ WRITE8_MEMBER( sega_315_5338a_device::write ) case 0x05: case 0x06: m_port_value[offset] = data; - m_out_port_cb[offset](data); + if (BIT(m_port_config, offset) == 0) + m_out_port_cb[offset](data); break; // port direction register (0 = output, 1 = input) - case 0x08: m_port_config = data; break; + case 0x08: + // handle ports that were previously set to input and are now output + { + uint8_t changed = data ^ m_port_config; + for (unsigned i = 0; i < 7; i++) + if (BIT(changed, i) && BIT(data, i) == 0) + m_out_port_cb[i](m_port_value[i]); + } + + m_port_config = data; + break; // command register case 0x09: diff --git a/src/mame/machine/model1io2.cpp b/src/mame/machine/model1io2.cpp new file mode 100644 index 00000000000..dd606859f95 --- /dev/null +++ b/src/mame/machine/model1io2.cpp @@ -0,0 +1,349 @@ +// license: BSD-3-Clause +// copyright-holders: Dirk Best +/*************************************************************************** + + Sega Model 1 I/O Board (Advanced) + + Used by: + - Wing War (R360) (837-10859) + - NetMerc (837-11659) + - Virtua Cop (837-11130 with 837-11131) + + Diagnostic LCD: + + It's possible to attach a small LCD to the board and enable a + diagnostic mode. To try this in MAME, enable the 'Diagnostic' + view, then map keys to I/O board buttons. Hold button 0 and + press F3 to reset. The main screen will display 'I/O board error' + but the LCD at the bottom is now active. Control it with board + buttons 0 (up), 1 (down) and 2 (select). + + It's also possible to show some debug values while the game is + running. To do this, hold board button '1' and push reset. Use + buttons 0 and 1 to scroll the screen. + + Debug mode: + + You can attach a terminal to SIO channel B. Attach it to the + MAME slot option 'ioboard:debug'. You need to set the dip + switch to 'Debug Console' and hold board button 0 at startup. + + Default settings are 9600-8-N-1. It will output "RS". + You can then enter the following commands: + + - DT[word1][word2]: Returns word2 bytes from location word1 + - GO: ? + - IN[byte1]: Return value from I/O port byte1 + - LH: ? + - OP[byte1][byte2]: Write value byte2 to I/O port byte1 + - T: Nothing + - XR: Return 26 bytes starting at location ff07 + - XM[26 bytes]: Write 26 bytes to location starting at ff07 + - ZP[word1][word2]: ff03=word1, ff05=word2 + - VR: Return id string + + NMI is related to the debug mode, not hooked up. + +***************************************************************************/ + +#include "emu.h" +#include "model1io2.h" +#include "cpu/z80/tmpz84c015.h" +#include "machine/msm6253.h" +#include "machine/315_5338a.h" +#include "bus/rs232/rs232.h" +#include "screen.h" + + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +DEFINE_DEVICE_TYPE(SEGA_MODEL1IO2, model1io2_device, "model1io2", "Sega Model 1 I/O Board (Advanced)") + +//------------------------------------------------- +// mem_map - z80 memory map +//------------------------------------------------- + +void model1io2_device::mem_map(address_map &map) +{ + map(0x0000, 0x7fff).rom(); + map(0x8000, 0x800f).rw("io", FUNC(sega_315_5338a_device::read), FUNC(sega_315_5338a_device::write)); + map(0x8040, 0x8040).portr("board"); + map(0x8080, 0x8080).portr("dsw1"); + map(0x8100, 0x8100).rw(this, FUNC(model1io2_device::fpga_r), FUNC(model1io2_device::fpga_w)); +// map(0x8180, 0x8183).nopr(); // displayed as 4 byte values in the diagnostic screen +// map(0x81a0, 0x81af).nopw(); // the (reserved) test in the diagnostic screen sets these + map(0x8200, 0x8203).mirror(0x04).rw("adc", FUNC(msm6253_device::d0_r), FUNC(msm6253_device::address_w)); +// map(0x8400, 0x8400) // jumps here when debug mode is set and board button 0 is not active on reset + map(0xe000, 0xefff).ram(); // backup ram + map(0xf000, 0xffff).ram(); +} + +//------------------------------------------------- +// input_ports - device-specific input ports +//------------------------------------------------- + +static INPUT_PORTS_START( model1io2 ) + PORT_START("board") + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Board 0") // on reset: port 4 does diagnostic menu (in debug mode: prevents jump to 8400) + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Board 1") // on reset: port 4 does parameter display + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Board 2") // button 2 and 3 adjust the baud rate in debug + PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Board 3") // mode when active at reset (9600, 4800, 2400, 1200) + PORT_DIPNAME(0x30, 0x30, "Mode") // jumpers on board? + PORT_DIPSETTING( 0x00, "Debug Console") + PORT_DIPSETTING( 0x10, "Normal 2") + PORT_DIPSETTING( 0x20, "Normal 1") + PORT_DIPSETTING( 0x30, "Normal 0") // default: no sio rx int (wingwar) +// might be mapped like this: +// PORT_DIPUNKNOWN(0x10, 0x10) // MODE (or ROM_EMU?) +// PORT_DIPUNKNOWN(0x20, 0x20) // GA_INT + PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_CUSTOM) PORT_READ_LINE_DEVICE_MEMBER("eeprom", eeprom_serial_93cxx_device, do_read) + PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_UNUSED) +INPUT_PORTS_END + +ioport_constructor model1io2_device::device_input_ports() const +{ + return INPUT_PORTS_NAME(model1io2); +} + +//------------------------------------------------- +// device_add_mconfig - add device configuration +//------------------------------------------------- + +MACHINE_CONFIG_START( model1io2_device::device_add_mconfig ) + MCFG_DEVICE_ADD("iocpu", TMPZ84C015, 19.6608_MHz_XTAL / 2) // TMPZ84C015AF-12 + MCFG_DEVICE_PROGRAM_MAP(mem_map) + + // SIO channel a baud rate adjusted by dsw1 1+2: 38400, 19200, 9600, 4800 + MCFG_TMPZ84C015_ZC2_CB(WRITELINE("iocpu", tmpz84c015_device, rxca_w)) + MCFG_DEVCB_CHAIN_OUTPUT(WRITELINE("iocpu", tmpz84c015_device, txca_w)) + MCFG_TMPZ84C015_ZC3_CB(WRITELINE("iocpu", tmpz84c015_device, rxtxcb_w)) + + MCFG_TMPZ84C015_OUT_TXDB_CB(WRITELINE("debug", rs232_port_device, write_txd)) + + MCFG_TMPZ84C015_IN_PA_CB(IOPORT("dsw2")) + MCFG_TMPZ84C015_IN_PB_CB(IOPORT("dsw3")) + + MCFG_DEVICE_ADD("debug", RS232_PORT, default_rs232_devices, nullptr) + MCFG_RS232_RXD_HANDLER(WRITELINE("iocpu", tmpz84c015_device, rxb_w)) + + MCFG_DEVICE_ADD("io", SEGA_315_5338A, 0) + MCFG_315_5338A_READ_CB(READ8(*this, model1io2_device, io_r)) + MCFG_315_5338A_WRITE_CB(WRITE8(*this, model1io2_device, io_w)) + MCFG_315_5338A_IN0_CB(READ8(*this, model1io2_device, in0_r)) + MCFG_315_5338A_IN1_CB(READ8(*this, model1io2_device, in1_r)) + MCFG_315_5338A_IN2_CB(READ8(*this, model1io2_device, in2_r)) + MCFG_315_5338A_IN4_CB(READ8(*this, model1io2_device, in4_r)) + MCFG_315_5338A_OUT3_CB(WRITE8(*this, model1io2_device, out3_w)) + MCFG_315_5338A_OUT4_CB(WRITE8(*this, model1io2_device, out4_w)) + MCFG_315_5338A_OUT5_CB(WRITE8(*this, model1io2_device, out5_w)) + MCFG_315_5338A_OUT6_CB(WRITE8(*this, model1io2_device, out6_w)) + + MCFG_EEPROM_SERIAL_93C46_ADD("eeprom") // 93C45 + + MCFG_DEVICE_ADD("adc", MSM6253, 0) + MCFG_MSM6253_IN0_ANALOG_READ(model1io2_device, analog0_r) + MCFG_MSM6253_IN1_ANALOG_READ(model1io2_device, analog1_r) + MCFG_MSM6253_IN2_ANALOG_READ(model1io2_device, analog2_r) + MCFG_MSM6253_IN3_ANALOG_READ(model1io2_device, analog3_r) + + // diagnostic lcd display + MCFG_SCREEN_ADD("screen", LCD) + MCFG_SCREEN_REFRESH_RATE(50) + MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) // not accurate + MCFG_SCREEN_SIZE(6*20+1, 19) + MCFG_SCREEN_VISIBLE_AREA(0, 6*20, 0, 19-1) + MCFG_SCREEN_UPDATE_DEVICE("lcd", hd44780_device, screen_update) + MCFG_SCREEN_PALETTE("palette") + + MCFG_PALETTE_ADD("palette", 3) + MCFG_PALETTE_INIT_OWNER(model1io2_device, lcd) + + MCFG_HD44780_ADD("lcd") + MCFG_HD44780_LCD_SIZE(2, 20) + MCFG_HD44780_PIXEL_UPDATE_CB(model1io2_device, lcd_pixel_update) +MACHINE_CONFIG_END + + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// model1io2_device - constructor +//------------------------------------------------- + +model1io2_device::model1io2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + device_t(mconfig, SEGA_MODEL1IO2, tag, owner, clock), + m_eeprom(*this, "eeprom"), + m_lcd(*this, "lcd"), + m_led_comm_err(*this, "led_comm_err"), + m_read_cb(*this), m_write_cb(*this), + m_in_cb{ {*this}, {*this}, {*this} }, + m_drive_read_cb(*this), m_drive_write_cb(*this), + m_an_cb{ {*this}, {*this}, {*this}, {*this}, {*this}, {*this}, {*this}, {*this} }, + m_output_cb(*this), + m_secondary_controls(false), + m_lcd_data(0) +{ +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void model1io2_device::device_start() +{ + // resolve callbacks + m_led_comm_err.resolve(); + + m_read_cb.resolve_safe(0xff); + m_write_cb.resolve_safe(); + + for (unsigned i = 0; i < 3; i++) + m_in_cb[i].resolve_safe(0xff); + + m_drive_read_cb.resolve_safe(0xff); + m_drive_write_cb.resolve_safe(); + + for (unsigned i = 0; i < 8; i++) + m_an_cb[i].resolve_safe(0xff); + + m_output_cb.resolve_safe(); + + // register for save states + save_item(NAME(m_secondary_controls)); + save_item(NAME(m_lcd_data)); +} + + +//************************************************************************** +// DIAGNOSTIC LCD +//************************************************************************** + +PALETTE_INIT_MEMBER( model1io2_device, lcd ) +{ + palette.set_pen_color(0, rgb_t(138, 146, 148)); // background + palette.set_pen_color(1, rgb_t( 92, 83, 88)); // lcd pixel on + palette.set_pen_color(2, rgb_t(131, 136, 139)); // lcd pixel off +} + +HD44780_PIXEL_UPDATE( model1io2_device::lcd_pixel_update ) +{ + // char size is 5x8 + if (x > 4 || y > 7) + return; + + if (line < 2 && pos < 20) + bitmap.pix16(1 + y + line*8 + line, 1 + pos*6 + x) = state ? 1 : 2; +} + + +//************************************************************************** +// INTERFACE +//************************************************************************** + +READ8_MEMBER( model1io2_device::io_r ) +{ + return m_read_cb(offset); +} + +WRITE8_MEMBER( model1io2_device::io_w ) +{ + m_write_cb(offset, data, 0xff); +} + +READ8_MEMBER( model1io2_device::in0_r ) +{ + return m_in_cb[0](0); +} + +READ8_MEMBER( model1io2_device::in1_r ) +{ + return m_in_cb[1](0); +} + +READ8_MEMBER( model1io2_device::in2_r ) +{ + return m_in_cb[2](0); +} + +WRITE8_MEMBER( model1io2_device::out3_w ) +{ + m_output_cb(data); +} + +READ8_MEMBER( model1io2_device::in4_r ) +{ + return m_drive_read_cb(0); +} + +WRITE8_MEMBER( model1io2_device::out4_w ) +{ + m_lcd_data = data; + m_drive_write_cb(data); +} + +WRITE8_MEMBER( model1io2_device::out5_w ) +{ + // 7------- not used? + // -6------ eeprom di + // --5----- eeprom clk + // ---4---- eeprom cs + // ----3--- unknown + // -----2-- lcd e + // ------1- lcd rw + // -------0 lcd rs + + m_eeprom->clk_write(BIT(data, 5) ? ASSERT_LINE : CLEAR_LINE); + m_eeprom->di_write(BIT(data, 6)); + m_eeprom->cs_write(BIT(data, 4) ? ASSERT_LINE : CLEAR_LINE); + + if (BIT(data, 2) == 1 && BIT(data, 1) == 0) + m_lcd->write(space, BIT(data, 0), m_lcd_data); +} + +WRITE8_MEMBER( model1io2_device::out6_w ) +{ + // 7------- unknown (input related?) + // -6------ control panel switch + // --5----- comm_err led + // ---4---- unknown + // ----32-- not used? + // ------1- unknown (sio channel a related) + // -------0 interrupt processing (1 while in the int routine) + + m_secondary_controls = BIT(data, 6); + m_led_comm_err = BIT(~data, 5); +} + +READ8_MEMBER( model1io2_device::fpga_r ) +{ + return 0x80; +} + +WRITE8_MEMBER( model1io2_device::fpga_w ) +{ + // fpga data uploaded here (vcop) +} + +ioport_value model1io2_device::analog0_r() +{ + return m_secondary_controls ? m_an_cb[4](0) : m_an_cb[0](0); +} + +ioport_value model1io2_device::analog1_r() +{ + return m_secondary_controls ? m_an_cb[5](0) : m_an_cb[1](0); +} + +ioport_value model1io2_device::analog2_r() +{ + return m_secondary_controls ? m_an_cb[6](0) : m_an_cb[2](0); +} + +ioport_value model1io2_device::analog3_r() +{ + return m_secondary_controls ? m_an_cb[7](0) : m_an_cb[3](0); +} diff --git a/src/mame/machine/model1io2.h b/src/mame/machine/model1io2.h new file mode 100644 index 00000000000..d91c114f6ec --- /dev/null +++ b/src/mame/machine/model1io2.h @@ -0,0 +1,153 @@ +// license: BSD-3-Clause +// copyright-holders: Dirk Best +/*************************************************************************** + + Sega Model 1 I/O Board (Advanced) + +***************************************************************************/ + +#ifndef MAME_MACHINE_MODEL1IO2_H +#define MAME_MACHINE_MODEL1IO2_H + +#pragma once + +#include "machine/eepromser.h" +#include "video/hd44780.h" + + +//************************************************************************** +// INTERFACE CONFIGURATION MACROS +//************************************************************************** + +#define MCFG_MODEL1IO2_READ_CB(_devcb) \ + devcb = &downcast(*device).set_read_callback(DEVCB_##_devcb); + +#define MCFG_MODEL1IO2_WRITE_CB(_devcb) \ + devcb = &downcast(*device).set_write_callback(DEVCB_##_devcb); + +#define MCFG_MODEL1IO2_IN0_CB(_devcb) \ + devcb = &downcast(*device).set_in_callback<0>(DEVCB_##_devcb); + +#define MCFG_MODEL1IO2_IN1_CB(_devcb) \ + devcb = &downcast(*device).set_in_callback<1>(DEVCB_##_devcb); + +#define MCFG_MODEL1IO2_IN2_CB(_devcb) \ + devcb = &downcast(*device).set_in_callback<2>(DEVCB_##_devcb); + +#define MCFG_MODEL1IO2_DRIVE_READ_CB(_devcb) \ + devcb = &downcast(*device).set_drive_read_callback(DEVCB_##_devcb); + +#define MCFG_MODEL1IO2_DRIVE_WRITE_CB(_devcb) \ + devcb = &downcast(*device).set_drive_write_callback(DEVCB_##_devcb); + +#define MCFG_MODEL1IO2_AN0_CB(_devcb) \ + devcb = &downcast(*device).set_an_callback<0>(DEVCB_##_devcb); + +#define MCFG_MODEL1IO2_AN1_CB(_devcb) \ + devcb = &downcast(*device).set_an_callback<1>(DEVCB_##_devcb); + +#define MCFG_MODEL1IO2_AN2_CB(_devcb) \ + devcb = &downcast(*device).set_an_callback<2>(DEVCB_##_devcb); + +#define MCFG_MODEL1IO2_AN3_CB(_devcb) \ + devcb = &downcast(*device).set_an_callback<3>(DEVCB_##_devcb); + +#define MCFG_MODEL1IO2_AN4_CB(_devcb) \ + devcb = &downcast(*device).set_an_callback<4>(DEVCB_##_devcb); + +#define MCFG_MODEL1IO2_AN5_CB(_devcb) \ + devcb = &downcast(*device).set_an_callback<5>(DEVCB_##_devcb); + +#define MCFG_MODEL1IO2_AN6_CB(_devcb) \ + devcb = &downcast(*device).set_an_callback<6>(DEVCB_##_devcb); + +#define MCFG_MODEL1IO2_AN7_CB(_devcb) \ + devcb = &downcast(*device).set_an_callback<7>(DEVCB_##_devcb); + +#define MCFG_MODEL1IO2_OUTPUT_CB(_devcb) \ + devcb = &downcast(*device).set_output_callback(DEVCB_##_devcb); + + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +class model1io2_device : public device_t +{ +public: + // construction/destruction + model1io2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + // configuration + template devcb_base &set_read_callback(Object &&cb) + { return m_read_cb.set_callback(std::forward(cb)); } + + template devcb_base &set_write_callback(Object &&cb) + { return m_write_cb.set_callback(std::forward(cb)); } + + template devcb_base &set_in_callback(Object &&cb) + { return m_in_cb[Index].set_callback(std::forward(cb)); } + + template devcb_base &set_drive_read_callback(Object &&cb) + { return m_drive_read_cb.set_callback(std::forward(cb)); } + + template devcb_base &set_drive_write_callback(Object &&cb) + { return m_drive_write_cb.set_callback(std::forward(cb)); } + + template devcb_base &set_an_callback(Object &&cb) + { return m_an_cb[Index].set_callback(std::forward(cb)); } + + template devcb_base &set_output_callback(Object &&cb) + { return m_output_cb.set_callback(std::forward(cb)); } + + void mem_map(address_map &map); + void io_map(address_map &map); + + DECLARE_PALETTE_INIT(lcd); + HD44780_PIXEL_UPDATE(lcd_pixel_update); + +protected: + // device-level overrides + virtual void device_start() override; + virtual ioport_constructor device_input_ports() const override; + virtual void device_add_mconfig(machine_config &config) override; + +private: + required_device m_eeprom; + required_device m_lcd; + output_finder<> m_led_comm_err; + + DECLARE_READ8_MEMBER(io_r); + DECLARE_WRITE8_MEMBER(io_w); + DECLARE_READ8_MEMBER(in0_r); + DECLARE_READ8_MEMBER(in1_r); + DECLARE_READ8_MEMBER(in2_r); + DECLARE_READ8_MEMBER(in4_r); + DECLARE_WRITE8_MEMBER(out3_w); + DECLARE_WRITE8_MEMBER(out4_w); + DECLARE_WRITE8_MEMBER(out5_w); + DECLARE_WRITE8_MEMBER(out6_w); + DECLARE_READ8_MEMBER(fpga_r); + DECLARE_WRITE8_MEMBER(fpga_w); + + ioport_value analog0_r(); + ioport_value analog1_r(); + ioport_value analog2_r(); + ioport_value analog3_r(); + + devcb_read8 m_read_cb; + devcb_write8 m_write_cb; + devcb_read8 m_in_cb[3]; + devcb_read8 m_drive_read_cb; + devcb_write8 m_drive_write_cb; + devcb_read8 m_an_cb[8]; + devcb_write8 m_output_cb; + + bool m_secondary_controls; + uint8_t m_lcd_data; +}; + +// device type definition +DECLARE_DEVICE_TYPE(SEGA_MODEL1IO2, model1io2_device) + +#endif // MAME_MACHINE_MODEL1IO2_H -- cgit v1.2.3