summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Dirk Best <mail@dirk-best.de>2018-04-18 00:24:44 +0200
committer Dirk Best <mail@dirk-best.de>2018-04-18 00:25:33 +0200
commitf0a77cb766b59603c4318014459adf71cde69647 (patch)
treef7a920ade0f58245f4ac3a71d3c378ab6f5edc3e
parent9dce73c8e77154544ae2b73f18fa32fa787ecfc2 (diff)
model1/model2: Emulate Model 1 I/O board, remove I/O RAM device
This includes an emulation of the Sega 315-5338A I/O controller which is also hooked up to the ufo21 driver now.
-rw-r--r--scripts/target/mame/arcade.lua6
-rw-r--r--src/mame/drivers/model1.cpp195
-rw-r--r--src/mame/drivers/model2.cpp144
-rw-r--r--src/mame/drivers/segaufo.cpp26
-rw-r--r--src/mame/includes/model1.h13
-rw-r--r--src/mame/includes/model2.h10
-rw-r--r--src/mame/machine/315_5338a.cpp163
-rw-r--r--src/mame/machine/315_5338a.h133
-rw-r--r--src/mame/machine/m1io.cpp109
-rw-r--r--src/mame/machine/m1io.h98
-rw-r--r--src/mame/machine/model1.cpp2
-rw-r--r--src/mame/machine/model1io.cpp282
-rw-r--r--src/mame/machine/model1io.h143
13 files changed, 901 insertions, 423 deletions
diff --git a/scripts/target/mame/arcade.lua b/scripts/target/mame/arcade.lua
index 914c8f6b27b..2b46c660e42 100644
--- a/scripts/target/mame/arcade.lua
+++ b/scripts/target/mame/arcade.lua
@@ -3368,8 +3368,10 @@ files {
MAME_DIR .. "src/mame/video/zaxxon.cpp",
MAME_DIR .. "src/mame/machine/315_5296.cpp",
MAME_DIR .. "src/mame/machine/315_5296.h",
- MAME_DIR .. "src/mame/machine/m1io.cpp",
- MAME_DIR .. "src/mame/machine/m1io.h",
+ MAME_DIR .. "src/mame/machine/315_5338a.cpp",
+ MAME_DIR .. "src/mame/machine/315_5338a.h",
+ MAME_DIR .. "src/mame/machine/model1io.cpp",
+ MAME_DIR .. "src/mame/machine/model1io.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 e87d8529f58..d6a40ee1b67 100644
--- a/src/mame/drivers/model1.cpp
+++ b/src/mame/drivers/model1.cpp
@@ -283,56 +283,6 @@ Notes:
OPR-14748.16 - 1M SOP40 MASKROMs, tied to 315-5423 & 315-5424. Note both ROMs are identical.
-I/O PCB
--------
-
-837-8950-01 (C) SEGA 1992
-|-------------------------------------------|
-| CN6 J3 J2 |
-| CN5|
-| DSW3 LED1 |
-| |
-| SW7 |---------| |
-| 32MHz |SEGA | DSW1 |
-| SW6 |315-5338A| |
-| | | |
-| SW5 |---------| DSW2 |
-| CN1|
-| SW4 MB8464 |
-| 14869.25 |
-| 3771 |
-| Z80 |
-| 93C45 |
-| PC910 PC910 |
-| LED2 J1 |
-| M6253 |
-| CN3 CN2 CN4 TL1 |
-|-------------------------------------------|
-Notes:
- 315-5338A - Sega Custom (QFP100)
- Z80 - Zilog Z0840004PSC Z80 CPU, running at 4.000MHz (DIP40, clock 32 / 8)
- 14869.25 - ST Microelectronics M27C512 64k x8 EPROM (DIP28, labelled 'EPR-14869')
- There is an alternative revision B 'EPR-14869B' also
- MB8464 - Fujitsu MB8464 8k x8 SRAM (DIP28)
- 93C45 - 128bytes x8 EEPROM (DIP8)
- M6253 - OKI M6253 (DIP18)
- 3771 - Fujitsu MB3771 Master Reset IC (DIP8)
- PC910 - Sharp PC910 opto-isolator (x2, DIP8)
- DSW1/2/3 - 8-position Dip Switch (x3)
- J1 - Jumper, set to 2-3
- J2, J3 - Jumper, both set to 1-2
- CN1 - 50 pin connector (joins to control panel assembly)
- CN2 - 26 pin connector (joins to foot pedal assembly)
- CN3 - 10 pin connector for power input
- CN4 - 6 pin connector (joins to sound PCB -> CN2, used for sound communication from Main PCB to Sound PCB)
- CN5 - 12 pin connector for input/output controls
- CN6 - 12 pin connector (joins to Motor PCB)
- TL1 - Connector for network optical cable link
- SW7 - Push Button Service Switch
- SW6 - Push Button Test Switch
- SW5, SW4 - Push Button Switches (purpose unknown)
-
-
Motor PCB
---------
@@ -635,12 +585,25 @@ Notes:
#include "cpu/i386/i386.h"
#include "machine/clock.h"
-#include "machine/nvram.h"
-#include "machine/m1io.h"
+#include "machine/model1io.h"
#include "speaker.h"
#include "vr.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::io_r )
+{
+ return m_dpram[offset];
+}
+
+WRITE8_MEMBER( model1_state::io_w )
+{
+ m_dpram[offset] = data;
+}
+
WRITE8_MEMBER( model1_state::vf_outputs_w )
{
// 7654---- unknown (not used?)
@@ -723,18 +686,6 @@ WRITE8_MEMBER( model1_state::netmerc_outputs_w )
machine().bookkeeping().coin_counter_w(0, BIT(data, 0));
}
-WRITE16_MEMBER( model1_state::drive_board_w )
-{
- if (offset == 0x01)
- {
- // drive board commands
- m_digits[0] = data;
- return;
- }
-
- logerror("drive_board_w: %02x %02x\n", offset, data);
-}
-
READ16_MEMBER(model1_state::fifoin_status_r)
{
return 0xffff;
@@ -823,31 +774,6 @@ MACHINE_RESET_MEMBER(model1_state,model1)
}
}
-READ16_MEMBER(model1_state::network_ctl_r)
-{
- if(offset)
- return 0x40;
- else
- return m_io_command;
-}
-
-WRITE16_MEMBER(model1_state::network_ctl_w)
-{
- if (offset == 0)
- {
- m_io_command = data & 0xff;
-
- // totally made up; proper emulation of I/O board needed
- // (command 3 is EEPROM write, so should take a lot longer)
- m_io_timer->adjust(data == 3 ? attotime::from_msec(100) : attotime::from_usec(10));
- }
-}
-
-TIMER_DEVICE_CALLBACK_MEMBER(model1_state::io_command_acknowledge)
-{
- m_io_command = 0;
-}
-
WRITE16_MEMBER(model1_state::md1_w)
{
COMBINE_DATA(m_display_list1+offset);
@@ -930,12 +856,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, 0xc0001f).rw("io", FUNC(m1io_device::read), FUNC(m1io_device::write)).umask16(0x00ff);
- map(0xc00020, 0xc0003f).w(this, FUNC(model1_state::drive_board_w));
-
- map(0xc00040, 0xc00043).rw(this, FUNC(model1_state::network_ctl_r), FUNC(model1_state::network_ctl_w));
-
- map(0xc00200, 0xc002ff).ram().share("nvram");
+ map(0xc00000, 0xc007ff).ram().share("dpram"); // 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));
@@ -1258,13 +1179,8 @@ ROM_START( vr )
ROM_LOAD32_BYTE( "mpr-14900.41", 0x000002, 0x80000, CRC(aa7c017d) SHA1(0fa2b59a8bb5f5907b2b2567e69d11c73b398dc1) )
ROM_LOAD32_BYTE( "mpr-14901.42", 0x000003, 0x80000, CRC(175b7a9a) SHA1(c86602e771cd49bab425b4ba7926d2f44858bd39) )
- ROM_REGION( 0x100, "nvram", 0 ) // default nvram
- ROM_LOAD( "vr_defaults.nv", 0x000, 0x100, CRC(5ccdc835) SHA1(7e809de470f78fb897b938ca2aee2e12f1c8f3a4) )
-
- ROM_REGION ( 0x10000, "io_board", 0)
- ROM_LOAD("epr-14869.25", 0x00000, 0x10000, CRC(6187cd7a) SHA1(b65fdd0ad31794a565a0ca4dc67a3f16b329fd71) )
-// ROM_LOAD("epr-14869b.25", 0x00000, 0x10000, BAD_DUMP CRC(b410f22b) SHA1(75c5009ca4d21ebb53d54d4e3fb8aa55a4c74a07) ) // stray FFs at xx49, xx5F, xxC9, xxDF
- // there is also epr-14869c in model2 daytona
+ ROM_REGION16_LE(0x80, "ioboard:eeprom", 0)
+ ROM_LOAD("93c45.bin", 0x00, 0x80, CRC(65aac303) SHA1(17687fedf1578e977cae4e7c3f5c00cad4aa490d) )
ROM_END
ROM_START( vformula )
@@ -1645,7 +1561,6 @@ MACHINE_CONFIG_START(model1_state::model1)
MCFG_DEVICE_ADD("copro_fifo_out", GENERIC_FIFO_U32, 0)
MCFG_TIMER_DRIVER_ADD_SCANLINE("scantimer", model1_state, model1_interrupt, "screen", 0, 1)
- MCFG_TIMER_DRIVER_ADD("iotimer", model1_state, io_command_acknowledge)
#if 1
MCFG_CPU_ADD("tgp_copro", MB86233, 16000000)
@@ -1657,12 +1572,12 @@ MACHINE_CONFIG_START(model1_state::model1)
MCFG_MACHINE_START_OVERRIDE(model1_state,model1)
MCFG_MACHINE_RESET_OVERRIDE(model1_state,model1)
- MCFG_NVRAM_ADD_0FILL("nvram")
- MCFG_DEVICE_ADD("io", SEGA_M1IO, 0)
- MCFG_M1IO_DI0_CB(IOPORT("IN.0"))
- MCFG_M1IO_DI1_CB(IOPORT("IN.1"))
- MCFG_M1IO_DI2_CB(IOPORT("IN.2"))
+ MCFG_DEVICE_ADD("ioboard", SEGA_MODEL1IO, 0)
+ MCFG_MODEL1IO_READ_CB(READ8(model1_state, io_r))
+ MCFG_MODEL1IO_WRITE_CB(WRITE8(model1_state, io_w))
+ MCFG_MODEL1IO_IN0_CB(IOPORT("IN.0"))
+ MCFG_MODEL1IO_IN1_CB(IOPORT("IN.1"))
MCFG_S24TILE_DEVICE_ADD("tile", 0x3fff)
MCFG_S24TILE_DEVICE_PALETTE("palette")
@@ -1698,18 +1613,19 @@ MACHINE_CONFIG_END
MACHINE_CONFIG_START(model1_state::vf)
model1_hle(config);
- MCFG_DEVICE_MODIFY("io")
- MCFG_M1IO_DO_CB(WRITE8(model1_state, vf_outputs_w))
+ MCFG_DEVICE_MODIFY("ioboard")
+ MCFG_MODEL1IO_IN2_CB(IOPORT("IN.2"))
+ MCFG_MODEL1IO_OUTPUT_CB(WRITE8(model1_state, vf_outputs_w))
MACHINE_CONFIG_END
MACHINE_CONFIG_START(model1_state::vr)
model1(config);
- MCFG_DEVICE_MODIFY("io")
- MCFG_M1IO_AN0_CB(IOPORT("WHEEL"))
- MCFG_M1IO_AN1_CB(IOPORT("ACCEL"))
- MCFG_M1IO_AN2_CB(IOPORT("BRAKE"))
- MCFG_M1IO_DO_CB(WRITE8(model1_state, vr_outputs_w))
+ MCFG_DEVICE_MODIFY("ioboard")
+ MCFG_MODEL1IO_AN0_CB(IOPORT("WHEEL"))
+ MCFG_MODEL1IO_AN1_CB(IOPORT("ACCEL"))
+ MCFG_MODEL1IO_AN2_CB(IOPORT("BRAKE"))
+ MCFG_MODEL1IO_OUTPUT_CB(WRITE8(model1_state, vr_outputs_w))
MCFG_M1COMM_ADD(M1COMM_TAG)
MCFG_DEVICE_BIOS("epr15112");
@@ -1718,11 +1634,11 @@ MACHINE_CONFIG_END
MACHINE_CONFIG_START(model1_state::vformula)
model1(config);
- MCFG_DEVICE_MODIFY("io")
- MCFG_M1IO_AN0_CB(IOPORT("WHEEL"))
- MCFG_M1IO_AN1_CB(IOPORT("ACCEL"))
- MCFG_M1IO_AN2_CB(IOPORT("BRAKE"))
- MCFG_M1IO_DO_CB(WRITE8(model1_state, vr_outputs_w))
+ MCFG_DEVICE_MODIFY("ioboard")
+ MCFG_MODEL1IO_AN0_CB(IOPORT("WHEEL"))
+ MCFG_MODEL1IO_AN1_CB(IOPORT("ACCEL"))
+ MCFG_MODEL1IO_AN2_CB(IOPORT("BRAKE"))
+ MCFG_MODEL1IO_OUTPUT_CB(WRITE8(model1_state, vr_outputs_w))
MCFG_M1COMM_ADD(M1COMM_TAG)
MCFG_DEVICE_BIOS("epr15624");
@@ -1731,14 +1647,13 @@ MACHINE_CONFIG_END
MACHINE_CONFIG_START(model1_state::swa)
model1_hle(config);
- MCFG_DEVICE_MODIFY("io")
- MCFG_M1IO_AN0_CB(IOPORT("STICK1X"))
- MCFG_M1IO_AN1_CB(IOPORT("STICK1Y"))
- MCFG_M1IO_AN2_CB(IOPORT("THROTTLE"))
- MCFG_M1IO_AN3_CB(NOOP)
- MCFG_M1IO_AN4_CB(IOPORT("STICK2X"))
- MCFG_M1IO_AN5_CB(IOPORT("STICK2Y"))
- MCFG_M1IO_DO_CB(WRITE8(model1_state, swa_outputs_w))
+ MCFG_DEVICE_MODIFY("ioboard")
+ MCFG_MODEL1IO_AN0_CB(IOPORT("STICK1X"))
+ MCFG_MODEL1IO_AN1_CB(IOPORT("STICK1Y"))
+ MCFG_MODEL1IO_AN2_CB(IOPORT("THROTTLE"))
+ MCFG_MODEL1IO_AN4_CB(IOPORT("STICK2X"))
+ MCFG_MODEL1IO_AN5_CB(IOPORT("STICK2Y"))
+ MCFG_MODEL1IO_OUTPUT_CB(WRITE8(model1_state, swa_outputs_w))
MCFG_SPEAKER_STANDARD_STEREO("dleft", "dright")
MCFG_DSBZ80_ADD(DSBZ80_TAG)
@@ -1757,11 +1672,11 @@ MACHINE_CONFIG_START(model1_state::wingwar)
MCFG_CPU_MODIFY("maincpu")
MCFG_CPU_PROGRAM_MAP(model1_comm_mem)
- MCFG_DEVICE_MODIFY("io")
- MCFG_M1IO_AN0_CB(IOPORT("STICKX"))
- MCFG_M1IO_AN1_CB(IOPORT("STICKY"))
- MCFG_M1IO_AN2_CB(IOPORT("THROTTLE"))
- MCFG_M1IO_DO_CB(WRITE8(model1_state, wingwar_outputs_w))
+ 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(model1_state, wingwar_outputs_w))
MCFG_M1COMM_ADD(M1COMM_TAG)
MCFG_DEVICE_BIOS("epr15112");
@@ -1770,8 +1685,8 @@ MACHINE_CONFIG_END
MACHINE_CONFIG_START(model1_state::wingwar360)
wingwar(config);
- MCFG_DEVICE_MODIFY("io")
- MCFG_M1IO_DO_CB(WRITE8(model1_state, wingwar360_outputs_w))
+ MCFG_DEVICE_MODIFY("ioboard")
+ MCFG_MODEL1IO_OUTPUT_CB(WRITE8(model1_state, wingwar360_outputs_w))
MACHINE_CONFIG_END
void model1_state::polhemus_map(address_map &map)
@@ -1786,14 +1701,14 @@ MACHINE_CONFIG_START(model1_state::netmerc)
MCFG_CPU_ADD("polhemus", I386SX, 16000000)
MCFG_CPU_PROGRAM_MAP(polhemus_map)
- MCFG_DEVICE_MODIFY("io")
- MCFG_M1IO_AN0_CB(IOPORT("STICKX"))
- MCFG_M1IO_AN2_CB(IOPORT("STICKY"))
- MCFG_M1IO_DO_CB(WRITE8(model1_state, netmerc_outputs_w))
+ MCFG_DEVICE_MODIFY("ioboard")
+ MCFG_MODEL1IO_AN0_CB(IOPORT("STICKX"))
+ MCFG_MODEL1IO_AN2_CB(IOPORT("STICKY"))
+ MCFG_MODEL1IO_OUTPUT_CB(WRITE8(model1_state, netmerc_outputs_w))
MACHINE_CONFIG_END
-DRIVER_INIT_MEMBER(model1_state,wingwar360)
+DRIVER_INIT_MEMBER( model1_state, wingwar360 )
{
// install r360 hack
m_maincpu->space(AS_PROGRAM).install_read_handler(0xc00014, 0xc00015, read16_delegate(FUNC(model1_state::r360_r),this));
diff --git a/src/mame/drivers/model2.cpp b/src/mame/drivers/model2.cpp
index 53787d0c878..86f297d4ad5 100644
--- a/src/mame/drivers/model2.cpp
+++ b/src/mame/drivers/model2.cpp
@@ -97,7 +97,7 @@
#include "machine/msm6253.h"
#include "machine/nvram.h"
#include "machine/315_5296.h"
-#include "machine/m1io.h"
+#include "machine/model1io.h"
#include "sound/2612intf.h"
#include "video/segaic24.h"
#include "speaker.h"
@@ -1176,11 +1176,6 @@ WRITE32_MEMBER(model2_state::geo_w)
/*****************************************************************************/
-READ32_MEMBER(model2o_state::daytona_unk_r)
-{
- return 0x00400000;
-}
-
READ32_MEMBER(model2_state::irq_request_r)
{
m_maincpu->i960_noburst();
@@ -1537,6 +1532,76 @@ WRITE8_MEMBER( model2o_state::vcop_output_w )
machine().bookkeeping().coin_counter_w(0, BIT(~data, 0));
}
+
+//**************************************************************************
+// I/O BOARD
+//**************************************************************************
+
+READ32_MEMBER( model2o_state::dpram_r )
+{
+ uint32_t data = m_dpram[offset] & mem_mask;
+
+ // intercept reads for the lightgun ports
+ // needs to be done because the vcop ioboard isn't emulated
+ // can be removed once that's done (837-11130 + 837-11131)
+
+ if (offset >= 0x100/4 && offset <= 0x10f/4)
+ {
+ if (ACCESSING_BITS_16_31)
+ {
+ data &= 0x0000ffff;
+ data |= (m_lightgun_ports[offset & 0x03].read_safe(0) >> 8) << 16;
+ }
+ if (ACCESSING_BITS_0_15)
+ {
+ data &= 0xffff0000;
+ data |= m_lightgun_ports[offset & 0x03].read_safe(0) & 0xff;
+ }
+ }
+
+ if (offset >= 0x110/4 && offset <= 0x113/4)
+ {
+ if (ACCESSING_BITS_0_15)
+ {
+ data &= 0xffff0000;
+ data |= lightgun_offscreen_r(space, 0);
+ }
+ }
+
+ return data;
+}
+
+WRITE32_MEMBER( model2o_state::dpram_w )
+{
+ COMBINE_DATA(&m_dpram[offset]);
+}
+
+// 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( model2o_state::io_r )
+{
+ if ((offset & 1) == 0)
+ return m_dpram[offset >> 1];
+ else
+ return m_dpram[offset >> 1] >> 16;
+}
+
+WRITE8_MEMBER( model2o_state::io_w )
+{
+ if ((offset & 1) == 0)
+ {
+ m_dpram[offset >> 1] &= 0x00ff0000;
+ m_dpram[offset >> 1] |= data;
+ }
+ else
+ {
+ m_dpram[offset >> 1] &= 0x000000ff;
+ m_dpram[offset >> 1] |= data << 16;
+ }
+}
+
/* model 2/2a common memory map */
void model2_tgp_state::model2_tgp_mem(address_map &map)
{
@@ -1562,12 +1627,7 @@ void model2o_state::model2o_mem(address_map &map)
map(0x00200000, 0x0021ffff).ram();
map(0x00220000, 0x0023ffff).rom().region("maincpu", 0x20000);
map(0x00980004, 0x00980007).r(this, FUNC(model2o_state::fifo_control_2o_r));
-
- map(0x01c00000, 0x01c0001f).rw("io", FUNC(m1io_device::read), FUNC(m1io_device::write)).umask32(0x00ff00ff);
- map(0x01c00040, 0x01c00043).r(this, FUNC(model2o_state::daytona_unk_r));
- map(0x01c00100, 0x01c0010f).r(this, FUNC(model2o_state::lightgun_coords_r)).umask32(0x00ff00ff);
- map(0x01c00110, 0x01c00113).r(this, FUNC(model2o_state::lightgun_offscreen_r)).umask32(0x00ff00ff);
- map(0x01c00200, 0x01c002ff).ram().share("backup2");
+ map(0x01c00000, 0x01c007ff).rw(this, FUNC(model2o_state::dpram_r), FUNC(model2o_state::dpram_w)).share("dpram"); // 2k*8-bit dual port ram
map(0x01c80000, 0x01c80003).rw(this, FUNC(model2o_state::model2_serial_r), FUNC(model2o_state::model2_serial_w));
}
@@ -2556,11 +2616,13 @@ MACHINE_CONFIG_START(model2o_state::model2o)
MCFG_EEPROM_SERIAL_93C46_ADD("eeprom")
MCFG_NVRAM_ADD_1FILL("backup1")
- MCFG_NVRAM_ADD_1FILL("backup2")
- MCFG_DEVICE_ADD("io", SEGA_M1IO, 0)
- MCFG_M1IO_DI0_CB(IOPORT("IN0"))
- MCFG_M1IO_DI1_CB(IOPORT("IN1"))
+ MCFG_DEVICE_ADD("ioboard", SEGA_MODEL1IO, 0)
+ MCFG_DEVICE_BIOS("epr14869c");
+ MCFG_MODEL1IO_READ_CB(READ8(model2o_state, io_r))
+ MCFG_MODEL1IO_WRITE_CB(WRITE8(model2o_state, io_w))
+ MCFG_MODEL1IO_IN0_CB(IOPORT("IN0"))
+ MCFG_MODEL1IO_IN1_CB(IOPORT("IN1"))
model2_timers(config);
model2_screen(config);
@@ -2629,11 +2691,11 @@ MACHINE_CONFIG_START(model2o_state::daytona)
model2o(config);
sj25_0207_01(config);
- MCFG_DEVICE_MODIFY("io")
- MCFG_M1IO_AN0_CB(IOPORT("STEER"))
- MCFG_M1IO_AN1_CB(IOPORT("ACCEL"))
- MCFG_M1IO_AN2_CB(IOPORT("BRAKE"))
- MCFG_M1IO_DO_CB(WRITE8(model2o_state, daytona_output_w))
+ MCFG_DEVICE_MODIFY("ioboard")
+ MCFG_MODEL1IO_AN0_CB(IOPORT("STEER"))
+ MCFG_MODEL1IO_AN1_CB(IOPORT("ACCEL"))
+ MCFG_MODEL1IO_AN2_CB(IOPORT("BRAKE"))
+ MCFG_MODEL1IO_OUTPUT_CB(WRITE8(model2o_state, daytona_output_w))
MACHINE_CONFIG_END
MACHINE_CONFIG_START(model2o_maxx_state::daytona_maxx)
@@ -2653,19 +2715,19 @@ MACHINE_CONFIG_END
MACHINE_CONFIG_START(model2o_state::desert)
model2o(config);
- MCFG_DEVICE_MODIFY("io")
- MCFG_M1IO_AN0_CB(IOPORT("STEER"))
- MCFG_M1IO_AN1_CB(IOPORT("ACCEL"))
- MCFG_M1IO_AN2_CB(IOPORT("BRAKE"))
- MCFG_M1IO_DO_CB(WRITE8(model2o_state, desert_output_w))
+ MCFG_DEVICE_MODIFY("ioboard")
+ MCFG_MODEL1IO_AN0_CB(IOPORT("STEER"))
+ MCFG_MODEL1IO_AN1_CB(IOPORT("ACCEL"))
+ MCFG_MODEL1IO_AN2_CB(IOPORT("BRAKE"))
+ MCFG_MODEL1IO_OUTPUT_CB(WRITE8(model2o_state, desert_output_w))
MACHINE_CONFIG_END
MACHINE_CONFIG_START(model2o_state::vcop)
model2o(config);
- MCFG_DEVICE_MODIFY("io")
- MCFG_M1IO_DI2_CB(IOPORT("IN2"))
- MCFG_M1IO_DO_CB(WRITE8(model2o_state, vcop_output_w))
+ MCFG_DEVICE_MODIFY("ioboard")
+ MCFG_MODEL1IO_IN2_CB(IOPORT("IN2"))
+ MCFG_MODEL1IO_OUTPUT_CB(WRITE8(model2o_state, vcop_output_w))
MACHINE_CONFIG_END
/* 2A-CRX */
@@ -5855,9 +5917,6 @@ ROM_START( daytona ) /* Daytona USA (Japan, Revision A), Original Model 2 w/Mode
MODEL2_CPU_BOARD /* Model 2 CPU board extra roms */
- ROM_REGION( 0x10000, "iocpu", 0 ) // 837-10539 I/O board
- ROM_LOAD("epr-14869c.25", 0x000000, 0x010000, CRC(24b68e64) SHA1(c19d044d4c2fe551474492aa51922587394dd371) )
-
ROM_REGION( 0x10000, "drivecpu", 0 ) // 838-10646 drive board
ROM_LOAD("epr-16488a.ic12", 0x000000, 0x010000, CRC(546c5d1a) SHA1(5533301fe7e3b499e6cee12230d2c656c3c667da) )
ROM_END
@@ -5919,9 +5978,6 @@ ROM_START( daytonase ) /* Daytona USA (Japan, Revision A), Original Model 2 w/Mo
MODEL2_CPU_BOARD /* Model 2 CPU board extra roms */
- ROM_REGION( 0x10000, "iocpu", 0 ) // 837-10539 I/O board
- ROM_LOAD("epr-14869c.25", 0x000000, 0x010000, CRC(24b68e64) SHA1(c19d044d4c2fe551474492aa51922587394dd371) )
-
ROM_REGION( 0x10000, "drivecpu", 0 ) // 838-10646 drive board
ROM_LOAD("epr-16488a.ic12", 0x000000, 0x010000, CRC(546c5d1a) SHA1(5533301fe7e3b499e6cee12230d2c656c3c667da) )
ROM_END
@@ -5982,9 +6038,6 @@ ROM_START( daytona93 ) /* Daytona USA (Deluxe cabinet, '93 version. There is sai
MODEL2_CPU_BOARD /* Model 2 CPU board extra roms */
- ROM_REGION( 0x10000, "iocpu", 0 ) // 837-10539 I/O board
- ROM_LOAD("epr-14869c.25", 0x000000, 0x010000, CRC(24b68e64) SHA1(c19d044d4c2fe551474492aa51922587394dd371) )
-
ROM_REGION( 0x10000, "drivecpu", 0 ) // 838-10646 drive board
ROM_LOAD("epr-16488a.ic12", 0x000000, 0x010000, BAD_DUMP CRC(546c5d1a) SHA1(5533301fe7e3b499e6cee12230d2c656c3c667da) ) // unconfirmed
ROM_END
@@ -6046,9 +6099,6 @@ ROM_START( daytonas ) /* Daytona USA (With Saturn Adverts) */
MODEL2_CPU_BOARD /* Model 2 CPU board extra roms */
- ROM_REGION( 0x10000, "iocpu", 0 ) // 837-10539 I/O board
- ROM_LOAD("epr-14869c.25", 0x000000, 0x010000, CRC(24b68e64) SHA1(c19d044d4c2fe551474492aa51922587394dd371) )
-
ROM_REGION( 0x10000, "drivecpu", 0 ) // 838-10646 drive board
ROM_LOAD("epr-16488a.ic12", 0x000000, 0x010000, BAD_DUMP CRC(546c5d1a) SHA1(5533301fe7e3b499e6cee12230d2c656c3c667da) ) // unconfirmed
ROM_END
@@ -6112,9 +6162,6 @@ ROM_START( daytonat )/* Daytona USA (Japan, Turbo hack) */
MODEL2_CPU_BOARD /* Model 2 CPU board extra roms */
- ROM_REGION( 0x10000, "iocpu", 0 ) // 837-10539 I/O board
- ROM_LOAD("epr-14869c.25", 0x000000, 0x010000, CRC(24b68e64) SHA1(c19d044d4c2fe551474492aa51922587394dd371) )
-
ROM_REGION( 0x10000, "drivecpu", 0 ) // 838-10646 drive board
ROM_LOAD("epr-16488a.ic12", 0x000000, 0x010000, CRC(546c5d1a) SHA1(5533301fe7e3b499e6cee12230d2c656c3c667da) )
ROM_END
@@ -6176,9 +6223,6 @@ ROM_START( daytonata )/* Daytona USA (Japan, Turbo hack) */
MODEL2_CPU_BOARD /* Model 2 CPU board extra roms */
- ROM_REGION( 0x10000, "iocpu", 0 ) // 837-10539 I/O board
- ROM_LOAD("epr-14869c.25", 0x000000, 0x010000, CRC(24b68e64) SHA1(c19d044d4c2fe551474492aa51922587394dd371) )
-
ROM_REGION( 0x10000, "drivecpu", 0 ) // 838-10646 drive board
ROM_LOAD("epr-16488a.ic12", 0x000000, 0x010000, CRC(546c5d1a) SHA1(5533301fe7e3b499e6cee12230d2c656c3c667da) )
ROM_END
@@ -6251,9 +6295,6 @@ ROM_START( daytonam ) /* Daytona USA (Japan, To The MAXX) */
MODEL2_CPU_BOARD /* Model 2 CPU board extra roms */
- ROM_REGION( 0x10000, "iocpu", 0 ) // 837-10539 I/O board
- ROM_LOAD("epr-14869c.25", 0x000000, 0x010000, CRC(24b68e64) SHA1(c19d044d4c2fe551474492aa51922587394dd371) )
-
ROM_REGION( 0x10000, "drivecpu", 0 ) // 838-10646 drive board
ROM_LOAD("epr-16488a.ic12", 0x000000, 0x010000, CRC(546c5d1a) SHA1(5533301fe7e3b499e6cee12230d2c656c3c667da) )
@@ -6322,9 +6363,6 @@ ROM_START( daytonagtx )
MODEL2_CPU_BOARD /* Model 2 CPU board extra roms */
- ROM_REGION( 0x10000, "iocpu", 0 ) // 837-10539 I/O board
- ROM_LOAD("epr-14869c.25", 0x000000, 0x010000, CRC(24b68e64) SHA1(c19d044d4c2fe551474492aa51922587394dd371) )
-
ROM_REGION( 0x10000, "drivecpu", 0 ) // 838-10646 drive board
ROM_LOAD("epr-16488a.ic12", 0x000000, 0x010000, CRC(546c5d1a) SHA1(5533301fe7e3b499e6cee12230d2c656c3c667da) )
ROM_END
diff --git a/src/mame/drivers/segaufo.cpp b/src/mame/drivers/segaufo.cpp
index 6f9e1504163..c301da8bc41 100644
--- a/src/mame/drivers/segaufo.cpp
+++ b/src/mame/drivers/segaufo.cpp
@@ -45,6 +45,7 @@
#include "cpu/z80/z80.h"
#include "machine/pit8253.h"
#include "machine/315_5296.h"
+#include "machine/315_5338a.h"
#include "machine/timer.h"
#include "sound/2612intf.h"
#include "sound/upd7759.h"
@@ -108,7 +109,8 @@ protected:
DECLARE_WRITE8_MEMBER(ex_stepper_w);
DECLARE_WRITE8_MEMBER(ex_cp_lamps_w);
DECLARE_WRITE8_MEMBER(ex_crane_xyz_w);
- DECLARE_WRITE8_MEMBER(ex_ufo21_lamps_w);
+ DECLARE_WRITE8_MEMBER(ex_ufo21_lamps1_w);
+ DECLARE_WRITE8_MEMBER(ex_ufo21_lamps2_w);
DECLARE_WRITE8_MEMBER(ex_ufo800_lamps_w);
DECLARE_READ8_MEMBER(ex_upd_busy_r);
DECLARE_WRITE8_MEMBER(ex_upd_start_w);
@@ -434,13 +436,19 @@ WRITE8_MEMBER(ufo_state::ex_ufo800_lamps_w)
/* 315-5338A */
-WRITE8_MEMBER(ufo_state::ex_ufo21_lamps_w)
+WRITE8_MEMBER(ufo_state::ex_ufo21_lamps1_w)
{
// d0: ? (ufo21 reads from it too, but value is discarded)
// d1-d6 are the 6 red leds on each ufo
// d7: ?
for (int i = 1; i < 7; i++)
- output().set_lamp_value(10 + offset * 10 + i, data >> i & 1);
+ output().set_lamp_value(10 + i, data >> i & 1);
+}
+
+WRITE8_MEMBER(ufo_state::ex_ufo21_lamps2_w)
+{
+ for (int i = 1; i < 7; i++)
+ output().set_lamp_value(20 + i, data >> i & 1);
}
WRITE8_MEMBER(ufo_state::ex_upd_start_w)
@@ -477,15 +485,11 @@ void ufo_state::ufo_portmap(address_map &map)
map(0xc0, 0xff).rw(m_io2, FUNC(sega_315_5296_device::read), FUNC(sega_315_5296_device::write));
}
-
void ufo_state::ex_ufo21_portmap(address_map &map)
{
ufo_portmap(map);
map(0x20, 0x20).w(m_upd, FUNC(upd7759_device::port_w));
- map(0x60, 0x60).w(this, FUNC(ufo_state::ex_upd_start_w)).nopr();
- map(0x61, 0x61).r(this, FUNC(ufo_state::ex_upd_busy_r));
- map(0x64, 0x65).w(this, FUNC(ufo_state::ex_ufo21_lamps_w)).nopr();
-// AM_RANGE(0x68, 0x68) AM_WRITENOP // ?
+ map(0x60, 0x6f).rw("io3", FUNC(sega_315_5338a_device::read), FUNC(sega_315_5338a_device::write));
}
void ufo_state::ex_ufo800_portmap(address_map &map)
@@ -849,6 +853,12 @@ MACHINE_CONFIG_START(ufo_state::ufo21)
MCFG_315_5296_OUT_PORTF_CB(WRITE8(ufo_state, ex_crane_xyz_w))
MCFG_315_5296_OUT_PORTG_CB(NOOP)
+ MCFG_DEVICE_ADD("io3", SEGA_315_5338A, 0)
+ MCFG_315_5338A_OUT0_CB(WRITE8(ufo_state, ex_upd_start_w))
+ MCFG_315_5338A_IN1_CB(READ8(ufo_state, ex_upd_busy_r))
+ MCFG_315_5338A_OUT4_CB(WRITE8(ufo_state, ex_ufo21_lamps1_w))
+ MCFG_315_5338A_OUT5_CB(WRITE8(ufo_state, ex_ufo21_lamps2_w))
+
/* sound hardware */
MCFG_SOUND_ADD("upd", UPD7759, UPD7759_STANDARD_CLOCK)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.75)
diff --git a/src/mame/includes/model1.h b/src/mame/includes/model1.h
index f29b9202b0c..ca834cda70a 100644
--- a/src/mame/includes/model1.h
+++ b/src/mame/includes/model1.h
@@ -40,7 +40,6 @@ public:
, m_dsbz80(*this, DSBZ80_TAG)
, m_tgp_copro(*this, "tgp_copro")
, m_screen(*this, "screen")
- , m_io_timer(*this, "iotimer")
, m_copro_fifo_in(*this, "copro_fifo_in")
, m_copro_fifo_out(*this, "copro_fifo_out")
, m_poly_rom(*this, "polygons")
@@ -51,6 +50,7 @@ public:
, m_display_list0(*this, "display_list0")
, m_display_list1(*this, "display_list1")
, m_color_xlat(*this, "color_xlat")
+ , m_dpram(*this, "dpram")
, m_paletteram16(*this, "palette")
, m_palette(*this, "palette")
, m_tiles(*this, "tile")
@@ -62,11 +62,8 @@ public:
DECLARE_MACHINE_START(model1);
DECLARE_MACHINE_RESET(model1);
- DECLARE_READ16_MEMBER(network_ctl_r);
- DECLARE_WRITE16_MEMBER(network_ctl_w);
- TIMER_DEVICE_CALLBACK_MEMBER(io_command_acknowledge);
-
- DECLARE_WRITE16_MEMBER(drive_board_w);
+ DECLARE_READ8_MEMBER(io_r);
+ DECLARE_WRITE8_MEMBER(io_w);
DECLARE_WRITE16_MEMBER(bank_w);
@@ -235,8 +232,6 @@ private:
int m_last_irq;
- uint8_t m_io_command;
-
// Devices
required_device<v60_device> m_maincpu; // V60
required_device<segam1audio_device> m_m1audio; // Model 1 standard sound board
@@ -245,7 +240,6 @@ private:
optional_device<dsbz80_device> m_dsbz80; // Digital Sound Board
optional_device<mb86233_device> m_tgp_copro;
required_device<screen_device> m_screen;
- required_device<timer_device> m_io_timer;
required_device<generic_fifo_u32_device> m_copro_fifo_in, m_copro_fifo_out;
required_region_ptr<uint32_t> m_poly_rom;
@@ -257,6 +251,7 @@ private:
required_shared_ptr<uint16_t> m_display_list0;
required_shared_ptr<uint16_t> m_display_list1;
required_shared_ptr<uint16_t> m_color_xlat;
+ required_shared_ptr<uint16_t> m_dpram;
// Sound
int m_sound_irq;
diff --git a/src/mame/includes/model2.h b/src/mame/includes/model2.h
index b5798e9e9a7..9704aa022ed 100644
--- a/src/mame/includes/model2.h
+++ b/src/mame/includes/model2.h
@@ -382,7 +382,8 @@ class model2o_state : public model2_tgp_state
{
public:
model2o_state(const machine_config &mconfig, device_type type, const char *tag)
- : model2_tgp_state(mconfig, type, tag)
+ : model2_tgp_state(mconfig, type, tag),
+ m_dpram(*this, "dpram")
{}
DECLARE_MACHINE_RESET(model2o);
@@ -393,13 +394,18 @@ public:
void vcop(machine_config &config);
protected:
- DECLARE_READ32_MEMBER(daytona_unk_r);
+ DECLARE_READ32_MEMBER(dpram_r);
+ DECLARE_WRITE32_MEMBER(dpram_w);
+ DECLARE_READ8_MEMBER(io_r);
+ DECLARE_WRITE8_MEMBER(io_w);
DECLARE_READ32_MEMBER(fifo_control_2o_r);
DECLARE_WRITE8_MEMBER(daytona_output_w);
DECLARE_WRITE8_MEMBER(desert_output_w);
DECLARE_WRITE8_MEMBER(vcop_output_w);
void model2o_mem(address_map &map);
+
+ required_shared_ptr<uint32_t> m_dpram;
};
/*****************************
diff --git a/src/mame/machine/315_5338a.cpp b/src/mame/machine/315_5338a.cpp
new file mode 100644
index 00000000000..5c7a3c7c211
--- /dev/null
+++ b/src/mame/machine/315_5338a.cpp
@@ -0,0 +1,163 @@
+// license: BSD-3-Clause
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ Sega 315-5338A
+
+ I/O Controller
+
+***************************************************************************/
+
+#include "emu.h"
+#include "315_5338a.h"
+
+//#define VERBOSE 1
+#include "logmacro.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(SEGA_315_5338A, sega_315_5338a_device, "315_5338a", "Sega 315-5338A I/O Controller")
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// sega_315_5338a_device - constructor
+//-------------------------------------------------
+
+sega_315_5338a_device::sega_315_5338a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, SEGA_315_5338A, tag, owner, clock),
+ m_read_cb(*this), m_write_cb(*this),
+ m_out0_cb(*this),
+ m_in1_cb(*this),
+ m_in2_cb(*this),
+ m_in3_cb(*this),
+ m_in4_cb(*this),
+ m_out4_cb(*this),
+ m_out5_cb(*this),
+ m_in6_cb(*this),
+ m_port0(0xff), m_config(0), m_serial_output(0), m_address(0)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void sega_315_5338a_device::device_start()
+{
+ // resolve callbacks
+ m_read_cb.resolve_safe(0xff);
+ m_write_cb.resolve_safe();
+ m_out0_cb.resolve_safe();
+ m_in1_cb.resolve_safe(0xff);
+ m_in2_cb.resolve_safe(0xff);
+ m_in3_cb.resolve_safe(0xff);
+ m_in4_cb.resolve_safe(0xff);
+ m_out4_cb.resolve_safe();
+ m_out5_cb.resolve_safe();
+ m_in6_cb.resolve_safe(0xff);
+
+ // register for save states
+ save_item(NAME(m_port0));
+ save_item(NAME(m_config));
+ save_item(NAME(m_serial_output));
+ save_item(NAME(m_address));
+}
+
+
+//**************************************************************************
+// INTERFACE
+//**************************************************************************
+
+READ8_MEMBER( sega_315_5338a_device::read )
+{
+ uint8_t data = 0xff;
+
+ switch (offset)
+ {
+ // return output latch
+ case 0x00: data = m_port0; break;
+
+ // standard input ports
+ case 0x01: data = m_in1_cb(0); break;
+ case 0x02: data = m_in2_cb(0); break;
+ case 0x03: data = m_in3_cb(0); break;
+
+ // input/output port
+ case 0x04: data = m_in4_cb(0); break;
+
+ // input port
+ case 0x06: data = m_in6_cb(0); break;
+
+ // serial data input
+ case 0x0c: data = m_read_cb(m_address); break;
+
+ // status register
+ case 0x0d:
+ // 7654---- unknown
+ // ----3--- transfer finished?
+ // -----21- unknown
+ // -------0 command acknowledged (0 = ack)
+ data = 0x08;
+ break;
+ }
+
+ LOG("RD %02x = %02x\n", offset, data);
+
+ return data;
+}
+
+WRITE8_MEMBER( sega_315_5338a_device::write )
+{
+ LOG("WR %02x = %02x\n", offset, data);
+
+ switch (offset)
+ {
+ // latched output port
+ case 0x00: m_port0 = data; m_out0_cb(data); break;
+
+ // input/output port
+ case 0x04: m_out4_cb(data); break;
+
+ // output port
+ case 0x05: m_out5_cb(data); break;
+
+ // config register?
+ case 0x08:
+ // 765----- unknown
+ // ---4---- port 4 direction (0 = output, 1 = input)
+ // ----3210 unknown
+ m_config = data;
+ break;
+
+ // command register
+ case 0x09:
+ switch (data)
+ {
+ case 0x00:
+ m_address = (m_address & 0xff00) | (m_serial_output << 0);
+ break;
+ case 0x01:
+ m_address = (m_address & 0x00ff) | (m_serial_output << 8);
+ break;
+ case 0x07:
+ m_write_cb(m_address, m_serial_output, 0xff);
+ break;
+ case 0x87:
+ // sent after setting up the address and when wanting to receive serial data
+ break;
+ default:
+ logerror("Unknown command: %02x\n", data);
+ }
+ break;
+
+ // serial data output
+ case 0x0a: m_serial_output = data; break;
+ }
+}
diff --git a/src/mame/machine/315_5338a.h b/src/mame/machine/315_5338a.h
new file mode 100644
index 00000000000..8b53fdf0698
--- /dev/null
+++ b/src/mame/machine/315_5338a.h
@@ -0,0 +1,133 @@
+// license: BSD-3-Clause
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ Sega 315-5338A
+
+ I/O Controller
+
+ Custom 100-pin QFP LSI. Supports 7 8-bit input/output ports and can
+ directly interact with dual port RAM. Also supports a master/slave
+ configuration where one controller acts as master and sends commands
+ and data over a serial link to another controller.
+
+ TODO:
+ - Serial
+ - Slave mode
+ - and probably lots more
+
+***************************************************************************/
+
+#ifndef MAME_MACHINE_315_5338A_H
+#define MAME_MACHINE_315_5338A_H
+
+#pragma once
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_315_5338A_READ_CB(_devcb) \
+ devcb = &downcast<sega_315_5338a_device &>(*device).set_read_callback(DEVCB_##_devcb);
+
+#define MCFG_315_5338A_WRITE_CB(_devcb) \
+ devcb = &downcast<sega_315_5338a_device &>(*device).set_write_callback(DEVCB_##_devcb);
+
+#define MCFG_315_5338A_OUT0_CB(_devcb) \
+ devcb = &downcast<sega_315_5338a_device &>(*device).set_out0_callback(DEVCB_##_devcb);
+
+#define MCFG_315_5338A_IN1_CB(_devcb) \
+ devcb = &downcast<sega_315_5338a_device &>(*device).set_in1_callback(DEVCB_##_devcb);
+
+#define MCFG_315_5338A_IN2_CB(_devcb) \
+ devcb = &downcast<sega_315_5338a_device &>(*device).set_in2_callback(DEVCB_##_devcb);
+
+#define MCFG_315_5338A_IN3_CB(_devcb) \
+ devcb = &downcast<sega_315_5338a_device &>(*device).set_in3_callback(DEVCB_##_devcb);
+
+#define MCFG_315_5338A_IN4_CB(_devcb) \
+ devcb = &downcast<sega_315_5338a_device &>(*device).set_in4_callback(DEVCB_##_devcb);
+
+#define MCFG_315_5338A_OUT4_CB(_devcb) \
+ devcb = &downcast<sega_315_5338a_device &>(*device).set_out4_callback(DEVCB_##_devcb);
+
+#define MCFG_315_5338A_OUT5_CB(_devcb) \
+ devcb = &downcast<sega_315_5338a_device &>(*device).set_out5_callback(DEVCB_##_devcb);
+
+#define MCFG_315_5338A_IN6_CB(_devcb) \
+ devcb = &downcast<sega_315_5338a_device &>(*device).set_in6_callback(DEVCB_##_devcb);
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class sega_315_5338a_device : public device_t
+{
+public:
+ // construction/destruction
+ sega_315_5338a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ // configuration
+ template <class Object> devcb_base &set_read_callback(Object &&cb)
+ { return m_read_cb.set_callback(std::forward<Object>(cb)); }
+
+ template <class Object> devcb_base &set_write_callback(Object &&cb)
+ { return m_write_cb.set_callback(std::forward<Object>(cb)); }
+
+ template <class Object> devcb_base &set_out0_callback(Object &&cb)
+ { return m_out0_cb.set_callback(std::forward<Object>(cb)); }
+
+ template <class Object> devcb_base &set_in1_callback(Object &&cb)
+ { return m_in1_cb.set_callback(std::forward<Object>(cb)); }
+
+ template <class Object> devcb_base &set_in2_callback(Object &&cb)
+ { return m_in2_cb.set_callback(std::forward<Object>(cb)); }
+
+ template <class Object> devcb_base &set_in3_callback(Object &&cb)
+ { return m_in3_cb.set_callback(std::forward<Object>(cb)); }
+
+ template <class Object> devcb_base &set_in4_callback(Object &&cb)
+ { return m_in4_cb.set_callback(std::forward<Object>(cb)); }
+
+ template <class Object> devcb_base &set_out4_callback(Object &&cb)
+ { return m_out4_cb.set_callback(std::forward<Object>(cb)); }
+
+ template <class Object> devcb_base &set_out5_callback(Object &&cb)
+ { return m_out5_cb.set_callback(std::forward<Object>(cb)); }
+
+ template <class Object> devcb_base &set_in6_callback(Object &&cb)
+ { return m_in6_cb.set_callback(std::forward<Object>(cb)); }
+
+ DECLARE_READ8_MEMBER(read);
+ DECLARE_WRITE8_MEMBER(write);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+
+private:
+ // callbacks
+ devcb_read8 m_read_cb;
+ devcb_write8 m_write_cb;
+
+ devcb_write8 m_out0_cb;
+ devcb_read8 m_in1_cb;
+ devcb_read8 m_in2_cb;
+ devcb_read8 m_in3_cb;
+ devcb_read8 m_in4_cb;
+ devcb_write8 m_out4_cb;
+ devcb_write8 m_out5_cb;
+ devcb_read8 m_in6_cb;
+
+ uint8_t m_port0;
+ uint8_t m_config;
+ uint8_t m_serial_output;
+ uint16_t m_address;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(SEGA_315_5338A, sega_315_5338a_device)
+
+#endif // MAME_MACHINE_315_5338A_H
diff --git a/src/mame/machine/m1io.cpp b/src/mame/machine/m1io.cpp
deleted file mode 100644
index b1ac5b996fe..00000000000
--- a/src/mame/machine/m1io.cpp
+++ /dev/null
@@ -1,109 +0,0 @@
-// license: BSD-3-Clause
-// copyright-holders: Dirk Best
-/***************************************************************************
-
- Sega Model 1/2 I/O RAM Abstraction
-
-***************************************************************************/
-
-#include "emu.h"
-#include "m1io.h"
-
-//#define VERBOSE 1
-#include "logmacro.h"
-
-
-//**************************************************************************
-// DEVICE DEFINITIONS
-//**************************************************************************
-
-DEFINE_DEVICE_TYPE(SEGA_M1IO, m1io_device, "m1io", "Sega Model 1/2 I/O RAM")
-
-
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
-
-//-------------------------------------------------
-// m1io_device - constructor
-//-------------------------------------------------
-
-m1io_device::m1io_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, SEGA_M1IO, tag, owner, clock),
- m_an_cb{ {*this}, {*this}, {*this}, {*this}, {*this}, {*this}, {*this}, {*this} },
- m_di_cb{ {*this}, {*this}, {*this} },
- m_do_cb(*this),
- m_out(0xff)
-{
-}
-
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-
-void m1io_device::device_start()
-{
- // resolve callbacks
- for (int i = 0; i < 8; i++)
- m_an_cb[i].resolve_safe(0xff);
-
- for (int i = 0; i < 3; i++)
- m_di_cb[i].resolve_safe(0xff);
-
- m_do_cb.resolve_safe();
-}
-
-
-//**************************************************************************
-// INTERFACE
-//**************************************************************************
-
-READ8_MEMBER( m1io_device::read )
-{
- uint8_t data = 0xff;
-
- switch (offset)
- {
- // analog inputs
- case 0x00: data = m_an_cb[0](0); break;
- case 0x01: data = m_an_cb[1](0); break;
- case 0x02: data = m_an_cb[2](0); break;
- case 0x03: data = m_an_cb[3](0); break;
- case 0x04: data = m_an_cb[4](0); break;
- case 0x05: data = m_an_cb[5](0); break;
- case 0x06: data = m_an_cb[6](0); break;
- case 0x07: data = m_an_cb[7](0); break;
-
- // digital inputs
- case 0x08: data = m_di_cb[0](0); break;
- case 0x09: data = m_di_cb[1](0); break;
- case 0x0a: data = m_di_cb[2](0); break;
-
- // unknown
- case 0x0b: break;
- case 0x0c: break;
- case 0x0d: break;
- case 0x0e: break; // bit 7654 input (vr board 0-3)
-
- // digital output
- case 0x0f: data = m_out;
- }
-
- LOG("RD %02x = %02x\n", offset, data);
-
- return data;
-}
-
-WRITE8_MEMBER( m1io_device::write )
-{
- LOG("WR %02x = %02x\n", offset, data);
-
- switch (offset)
- {
- // digital output
- case 0x0f:
- m_out = data;
- m_do_cb(m_out);
- break;
- }
-}
diff --git a/src/mame/machine/m1io.h b/src/mame/machine/m1io.h
deleted file mode 100644
index 4700d053b5a..00000000000
--- a/src/mame/machine/m1io.h
+++ /dev/null
@@ -1,98 +0,0 @@
-// license: BSD-3-Clause
-// copyright-holders: Dirk Best
-/***************************************************************************
-
- Sega Model 1/2 I/O RAM Abstraction
-
- This device handles the 16 bytes of dual-port RAM that are used to
- communicate with the I/O board. It should go away once we properly
- emulate the I/O boards.
-
-***************************************************************************/
-
-#ifndef MAME_MACHINE_M1IO_H
-#define MAME_MACHINE_M1IO_H
-
-#pragma once
-
-//**************************************************************************
-// INTERFACE CONFIGURATION MACROS
-//**************************************************************************
-
-#define MCFG_M1IO_AN0_CB(_devcb) \
- devcb = &downcast<m1io_device &>(*device).set_an_callback(DEVCB_##_devcb, 0);
-
-#define MCFG_M1IO_AN1_CB(_devcb) \
- devcb = &downcast<m1io_device &>(*device).set_an_callback(DEVCB_##_devcb, 1);
-
-#define MCFG_M1IO_AN2_CB(_devcb) \
- devcb = &downcast<m1io_device &>(*device).set_an_callback(DEVCB_##_devcb, 2);
-
-#define MCFG_M1IO_AN3_CB(_devcb) \
- devcb = &downcast<m1io_device &>(*device).set_an_callback(DEVCB_##_devcb, 3);
-
-#define MCFG_M1IO_AN4_CB(_devcb) \
- devcb = &downcast<m1io_device &>(*device).set_an_callback(DEVCB_##_devcb, 4);
-
-#define MCFG_M1IO_AN5_CB(_devcb) \
- devcb = &downcast<m1io_device &>(*device).set_an_callback(DEVCB_##_devcb, 5);
-
-#define MCFG_M1IO_AN6_CB(_devcb) \
- devcb = &downcast<m1io_device &>(*device).set_an_callback(DEVCB_##_devcb, 6);
-
-#define MCFG_M1IO_AN7_CB(_devcb) \
- devcb = &downcast<m1io_device &>(*device).set_an_callback(DEVCB_##_devcb, 7);
-
-#define MCFG_M1IO_DI0_CB(_devcb) \
- devcb = &downcast<m1io_device &>(*device).set_di_callback(DEVCB_##_devcb, 0);
-
-#define MCFG_M1IO_DI1_CB(_devcb) \
- devcb = &downcast<m1io_device &>(*device).set_di_callback(DEVCB_##_devcb, 1);
-
-#define MCFG_M1IO_DI2_CB(_devcb) \
- devcb = &downcast<m1io_device &>(*device).set_di_callback(DEVCB_##_devcb, 2);
-
-#define MCFG_M1IO_DO_CB(_devcb) \
- devcb = &downcast<m1io_device &>(*device).set_do_callback(DEVCB_##_devcb);
-
-
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-class m1io_device : public device_t
-{
-public:
- // construction/destruction
- m1io_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- // configuration
- template <class Object> devcb_base &set_an_callback(Object &&cb, int index)
- { return m_an_cb[index].set_callback(std::forward<Object>(cb)); }
-
- template <class Object> devcb_base &set_di_callback(Object &&cb, int index)
- { return m_di_cb[index].set_callback(std::forward<Object>(cb)); }
-
- template <class Object> devcb_base &set_do_callback(Object &&cb)
- { return m_do_cb.set_callback(std::forward<Object>(cb)); }
-
- DECLARE_READ8_MEMBER(read);
- DECLARE_WRITE8_MEMBER(write);
-
-protected:
- // device-level overrides
- virtual void device_start() override;
-
-private:
- // callbacks
- devcb_read8 m_an_cb[8];
- devcb_read8 m_di_cb[3];
- devcb_write8 m_do_cb;
-
- uint8_t m_out;
-};
-
-// device type definition
-DECLARE_DEVICE_TYPE(SEGA_M1IO, m1io_device)
-
-#endif // MAME_MACHINE_M1IO_H
diff --git a/src/mame/machine/model1.cpp b/src/mame/machine/model1.cpp
index 235fbb1097d..92197746908 100644
--- a/src/mame/machine/model1.cpp
+++ b/src/mame/machine/model1.cpp
@@ -1727,7 +1727,6 @@ MACHINE_START_MEMBER(model1_state,model1)
{
m_digits.resolve();
m_copro_ram_data = std::make_unique<u32[]>(0x8000);
- m_io_command = 0;
save_pointer(NAME(m_copro_ram_data.get()), 0x8000);
save_item(NAME(m_v60_copro_ram_adr));
@@ -1741,7 +1740,6 @@ MACHINE_START_MEMBER(model1_state,model1)
save_item(NAME(m_copro_hle_list_length));
save_item(NAME(m_copro_hle_active_list_length));
save_item(NAME(m_copro_hle_active_list_pos));
- save_item(NAME(m_io_command));
if(m_tgp_copro) {
m_copro_fifo_in->setup(16,
diff --git a/src/mame/machine/model1io.cpp b/src/mame/machine/model1io.cpp
new file mode 100644
index 00000000000..ad9a90dbada
--- /dev/null
+++ b/src/mame/machine/model1io.cpp
@@ -0,0 +1,282 @@
+// license: BSD-3-Clause
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ Sega Model 1/2 I/O Board
+
+
+ I/O PCB
+ -------
+
+ 837-8950-01 (C) SEGA 1992
+ |-------------------------------------------|
+ | CN6 J3 J2 |
+ | CN5|
+ | DSW3 LED1 |
+ | |
+ | SW7 |---------| |
+ | 32MHz |SEGA | DSW1 |
+ | SW6 |315-5338A| |
+ | | | |
+ | SW5 |---------| DSW2 |
+ | CN1|
+ | SW4 MB8464 |
+ | 14869.25 |
+ | 3771 |
+ | Z80 |
+ | 93C45 |
+ | PC910 PC910 |
+ | LED2 J1 |
+ | M6253 |
+ | CN3 CN2 CN4 TL1 |
+ |-------------------------------------------|
+ Notes:
+ 315-5338A - Sega Custom (QFP100)
+ Z80 - Zilog Z0840004PSC Z80 CPU, running at 4.000MHz (DIP40, clock 32 / 8)
+ 14869.25 - ST Microelectronics M27C512 64k x8 EPROM (DIP28, labelled 'EPR-14869')
+ There is an alternative revision B 'EPR-14869B' also
+ MB8464 - Fujitsu MB8464 8k x8 SRAM (DIP28)
+ 93C45 - 128bytes x8 EEPROM (DIP8)
+ M6253 - OKI M6253 (DIP18)
+ 3771 - Fujitsu MB3771 Master Reset IC (DIP8)
+ PC910 - Sharp PC910 opto-isolator (x2, DIP8)
+ DSW1/2/3 - 8-position Dip Switch (x3)
+ J1 - Jumper, set to 2-3
+ J2, J3 - Jumper, both set to 1-2
+ CN1 - 50 pin connector (joins to control panel assembly)
+ CN2 - 26 pin connector (joins to foot pedal assembly)
+ CN3 - 10 pin connector for power input
+ CN4 - 6 pin connector (joins to sound PCB -> CN2, used for sound communication from Main PCB to Sound PCB)
+ CN5 - 12 pin connector for input/output controls
+ CN6 - 12 pin connector (joins to Motor PCB)
+ TL1 - Connector for network optical cable link
+ SW7 - Push Button Service Switch
+ SW6 - Push Button Test Switch
+ SW5, SW4 - Push Button Switches (purpose unknown)
+
+***************************************************************************/
+
+#include "emu.h"
+#include "model1io.h"
+#include "cpu/z80/z80.h"
+#include "machine/msm6253.h"
+#include "machine/315_5338a.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(SEGA_MODEL1IO, model1io_device, "model1io", "Sega Model 1 I/O Board")
+
+//-------------------------------------------------
+// mem_map - z80 memory map
+//-------------------------------------------------
+
+void model1io_device::mem_map(address_map &map)
+{
+ map(0x0000, 0x3fff).rom();
+ map(0x4000, 0x5fff).ram();
+ map(0x8000, 0x800f).rw("io", FUNC(sega_315_5338a_device::read), FUNC(sega_315_5338a_device::write));
+ map(0xc000, 0xc003).rw("adc", FUNC(msm6253_device::d0_r), FUNC(msm6253_device::address_w));
+}
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+static INPUT_PORTS_START( model1io )
+ PORT_START("buttons")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Board 0")
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Board 1")
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Board 2")
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Board 3")
+INPUT_PORTS_END
+
+ioport_constructor model1io_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(model1io);
+}
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+ROM_START( model1io )
+ ROM_REGION(0x10000, "iocpu", 0)
+ ROM_DEFAULT_BIOS("epr14869")
+
+ // Virtua Racing (837-8950-01)
+ ROM_SYSTEM_BIOS(0, "epr14869", "EPR-14869")
+ ROMX_LOAD("epr-14869.25", 0x0000, 0x10000, CRC(6187cd7a) SHA1(b65fdd0ad31794a565a0ca4dc67a3f16b329fd71), ROM_BIOS(1))
+
+ // Virtua Fighter (837-8936)
+ ROM_SYSTEM_BIOS(1, "epr14869b", "EPR-14869B")
+ ROMX_LOAD("epr-14869b.25", 0x0000, 0x10000, BAD_DUMP CRC(b410f22b) SHA1(75c5009ca4d21ebb53d54d4e3fb8aa55a4c74a07), ROM_BIOS(2)) // stray FFs at xx49, xx5F, xxC9, xxDF
+
+ // Daytona USA (837-10539)
+ ROM_SYSTEM_BIOS(2, "epr14869c", "EPR-14869C")
+ ROMX_LOAD("epr-14869c.25", 0x0000, 0x10000, CRC(24b68e64) SHA1(c19d044d4c2fe551474492aa51922587394dd371), ROM_BIOS(3))
+ROM_END
+
+const tiny_rom_entry *model1io_device::device_rom_region() const
+{
+ return ROM_NAME(model1io);
+}
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+MACHINE_CONFIG_START( model1io_device::device_add_mconfig )
+ MCFG_CPU_ADD("iocpu", Z80, 32_MHz_XTAL/8)
+ MCFG_CPU_PROGRAM_MAP(mem_map)
+
+ MCFG_EEPROM_SERIAL_93C46_ADD("eeprom") // 93C45
+
+ MCFG_DEVICE_ADD("io", SEGA_315_5338A, 0)
+ MCFG_315_5338A_READ_CB(READ8(model1io_device, io_r))
+ MCFG_315_5338A_WRITE_CB(WRITE8(model1io_device, io_w))
+ MCFG_315_5338A_OUT0_CB(WRITE8(model1io_device, out0_w))
+ MCFG_315_5338A_IN1_CB(READ8(model1io_device, in1_r))
+ MCFG_315_5338A_IN2_CB(READ8(model1io_device, in2_r))
+ MCFG_315_5338A_IN3_CB(READ8(model1io_device, in3_r))
+ MCFG_315_5338A_OUT5_CB(WRITE8(model1io_device, out5_w))
+ MCFG_315_5338A_IN6_CB(READ8(model1io_device, in6_r))
+
+ MCFG_DEVICE_ADD("adc", MSM6253, 0)
+ MCFG_MSM6253_IN0_ANALOG_READ(model1io_device, analog0_r)
+ MCFG_MSM6253_IN1_ANALOG_READ(model1io_device, analog1_r)
+ MCFG_MSM6253_IN2_ANALOG_READ(model1io_device, analog2_r)
+ MCFG_MSM6253_IN3_ANALOG_READ(model1io_device, analog3_r)
+MACHINE_CONFIG_END
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// m1io_device - constructor
+//-------------------------------------------------
+
+model1io_device::model1io_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, SEGA_MODEL1IO, tag, owner, clock),
+ m_eeprom(*this, "eeprom"),
+ m_buttons(*this, "buttons"),
+ m_read_cb(*this), m_write_cb(*this),
+ m_in_cb{ {*this}, {*this}, {*this}, {*this}, {*this}, {*this} },
+ m_an_cb{ {*this}, {*this}, {*this}, {*this}, {*this}, {*this}, {*this}, {*this} },
+ m_output_cb(*this),
+ m_secondary_controls(false)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void model1io_device::device_start()
+{
+ // resolve callbacks
+ m_read_cb.resolve_safe(0xff);
+ m_write_cb.resolve_safe();
+
+ for (unsigned i = 0; i < 6; i++)
+ m_in_cb[i].resolve_safe(0xff);
+
+ for (unsigned i = 0; i < 8; i++)
+ m_an_cb[i].resolve_safe(0xff);
+
+ m_output_cb.resolve_safe();
+}
+
+
+//**************************************************************************
+// INTERFACE
+//**************************************************************************
+
+READ8_MEMBER( model1io_device::io_r )
+{
+ return m_read_cb(offset);
+}
+
+WRITE8_MEMBER( model1io_device::io_w )
+{
+ m_write_cb(offset, data, 0xff);
+}
+
+WRITE8_MEMBER( model1io_device::out0_w )
+{
+ // 7------- eeprom clk
+ // -6------ eeprom cs
+ // --5----- eeprom di
+ // ---4---- eeprom related (0 on reads, 1 on writes)
+ // ----32-- unknown (not used?)
+ // ------1- led? set to 1 in startup, after eeprom written to ram
+ // -------0 control panel switch (0 = first, 1 = second)
+
+ m_eeprom->clk_write(BIT(data, 7) ? ASSERT_LINE : CLEAR_LINE);
+ m_eeprom->di_write(BIT(data, 5));
+ m_eeprom->cs_write(BIT(data, 6) ? ASSERT_LINE : CLEAR_LINE);
+
+ m_secondary_controls = bool(BIT(data, 0));
+}
+
+READ8_MEMBER( model1io_device::in1_r )
+{
+ return m_secondary_controls ? m_in_cb[3](0) : m_in_cb[0](0);
+}
+
+READ8_MEMBER( model1io_device::in2_r )
+{
+ return m_secondary_controls ? m_in_cb[4](0) : m_in_cb[1](0);
+}
+
+READ8_MEMBER( model1io_device::in3_r )
+{
+ return m_secondary_controls ? m_in_cb[5](0) : m_in_cb[2](0);
+}
+
+WRITE8_MEMBER( model1io_device::out5_w )
+{
+ m_output_cb(data);
+}
+
+READ8_MEMBER( model1io_device::in6_r )
+{
+ // 7------- eeprom do
+ // -654---- unknown
+ // ----3--- button board 3
+ // -----2-- button board 2
+ // ------1- button board 1
+ // -------0 button board 0
+
+ uint8_t data = 0;
+
+ data |= m_eeprom->do_read() << 7;
+ data |= 0x70;
+ data |= m_buttons->read();
+
+ return data;
+}
+
+ioport_value model1io_device::analog0_r()
+{
+ return m_secondary_controls ? m_an_cb[4](0) : m_an_cb[0](0);
+}
+
+ioport_value model1io_device::analog1_r()
+{
+ return m_secondary_controls ? m_an_cb[5](0) : m_an_cb[1](0);
+}
+
+ioport_value model1io_device::analog2_r()
+{
+ return m_secondary_controls ? m_an_cb[6](0) : m_an_cb[2](0);
+}
+
+ioport_value model1io_device::analog3_r()
+{
+ return m_secondary_controls ? m_an_cb[7](0) : m_an_cb[3](0);
+}
diff --git a/src/mame/machine/model1io.h b/src/mame/machine/model1io.h
new file mode 100644
index 00000000000..70335812482
--- /dev/null
+++ b/src/mame/machine/model1io.h
@@ -0,0 +1,143 @@
+// license: BSD-3-Clause
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ Sega Model 1/2 I/O Board
+
+ 837-8950-01
+ 837-8936
+ 837-10539
+
+***************************************************************************/
+
+#ifndef MAME_MACHINE_MODEL1IO_H
+#define MAME_MACHINE_MODEL1IO_H
+
+#pragma once
+
+#include "machine/eepromser.h"
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_MODEL1IO_READ_CB(_devcb) \
+ devcb = &downcast<model1io_device &>(*device).set_read_callback(DEVCB_##_devcb);
+
+#define MCFG_MODEL1IO_WRITE_CB(_devcb) \
+ devcb = &downcast<model1io_device &>(*device).set_write_callback(DEVCB_##_devcb);
+
+#define MCFG_MODEL1IO_IN0_CB(_devcb) \
+ devcb = &downcast<model1io_device &>(*device).set_in_callback(DEVCB_##_devcb, 0);
+
+#define MCFG_MODEL1IO_IN1_CB(_devcb) \
+ devcb = &downcast<model1io_device &>(*device).set_in_callback(DEVCB_##_devcb, 1);
+
+#define MCFG_MODEL1IO_IN2_CB(_devcb) \
+ devcb = &downcast<model1io_device &>(*device).set_in_callback(DEVCB_##_devcb, 2);
+
+#define MCFG_MODEL1IO_IN3_CB(_devcb) \
+ devcb = &downcast<model1io_device &>(*device).set_in_callback(DEVCB_##_devcb, 3);
+
+#define MCFG_MODEL1IO_IN4_CB(_devcb) \
+ devcb = &downcast<model1io_device &>(*device).set_in_callback(DEVCB_##_devcb, 4);
+
+#define MCFG_MODEL1IO_IN5_CB(_devcb) \
+ devcb = &downcast<model1io_device &>(*device).set_in_callback(DEVCB_##_devcb, 5);
+
+#define MCFG_MODEL1IO_AN0_CB(_devcb) \
+ devcb = &downcast<model1io_device &>(*device).set_an_callback(DEVCB_##_devcb, 0);
+
+#define MCFG_MODEL1IO_AN1_CB(_devcb) \
+ devcb = &downcast<model1io_device &>(*device).set_an_callback(DEVCB_##_devcb, 1);
+
+#define MCFG_MODEL1IO_AN2_CB(_devcb) \
+ devcb = &downcast<model1io_device &>(*device).set_an_callback(DEVCB_##_devcb, 2);
+
+#define MCFG_MODEL1IO_AN3_CB(_devcb) \
+ devcb = &downcast<model1io_device &>(*device).set_an_callback(DEVCB_##_devcb, 3);
+
+#define MCFG_MODEL1IO_AN4_CB(_devcb) \
+ devcb = &downcast<model1io_device &>(*device).set_an_callback(DEVCB_##_devcb, 4);
+
+#define MCFG_MODEL1IO_AN5_CB(_devcb) \
+ devcb = &downcast<model1io_device &>(*device).set_an_callback(DEVCB_##_devcb, 5);
+
+#define MCFG_MODEL1IO_AN6_CB(_devcb) \
+ devcb = &downcast<model1io_device &>(*device).set_an_callback(DEVCB_##_devcb, 6);
+
+#define MCFG_MODEL1IO_AN7_CB(_devcb) \
+ devcb = &downcast<model1io_device &>(*device).set_an_callback(DEVCB_##_devcb, 7);
+
+#define MCFG_MODEL1IO_OUTPUT_CB(_devcb) \
+ devcb = &downcast<model1io_device &>(*device).set_output_callback(DEVCB_##_devcb);
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class model1io_device : public device_t
+{
+public:
+ // construction/destruction
+ model1io_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ // configuration
+ template <class Object> devcb_base &set_read_callback(Object &&cb)
+ { return m_read_cb.set_callback(std::forward<Object>(cb)); }
+
+ template <class Object> devcb_base &set_write_callback(Object &&cb)
+ { return m_write_cb.set_callback(std::forward<Object>(cb)); }
+
+ template <class Object> devcb_base &set_in_callback(Object &&cb, int index)
+ { return m_in_cb[index].set_callback(std::forward<Object>(cb)); }
+
+ template <class Object> devcb_base &set_an_callback(Object &&cb, int index)
+ { return m_an_cb[index].set_callback(std::forward<Object>(cb)); }
+
+ template <class Object> devcb_base &set_output_callback(Object &&cb)
+ { return m_output_cb.set_callback(std::forward<Object>(cb)); }
+
+ void mem_map(address_map &map);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual ioport_constructor device_input_ports() const override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+private:
+ required_device<eeprom_serial_93cxx_device> m_eeprom;
+ required_ioport m_buttons;
+
+ DECLARE_READ8_MEMBER(io_r);
+ DECLARE_WRITE8_MEMBER(io_w);
+
+ DECLARE_WRITE8_MEMBER(out0_w);
+ DECLARE_READ8_MEMBER(in1_r);
+ DECLARE_READ8_MEMBER(in2_r);
+ DECLARE_READ8_MEMBER(in3_r);
+ DECLARE_WRITE8_MEMBER(out5_w);
+ DECLARE_READ8_MEMBER(in6_r);
+
+ 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[6];
+ devcb_read8 m_an_cb[8];
+ devcb_write8 m_output_cb;
+
+ bool m_secondary_controls;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(SEGA_MODEL1IO, model1io_device)
+
+#endif // MAME_MACHINE_MODEL1IO_H