summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Wilbert Pol <wilbert@jdg.info>2013-09-12 18:48:15 +0000
committer Wilbert Pol <wilbert@jdg.info>2013-09-12 18:48:15 +0000
commit52bfccb35c222ae1cb9e00d01c58960e1e7e7feb (patch)
tree054cdf16d1fd10fb1e34fe765c1d26d939644d56
parentc6a6b78f9501dfe9d61a5c830f4c5876b36b9ff6 (diff)
(MESS) sms.c: Improved I/O handling for Japanese and Korean drivers (Pause button for sg1000m3, TH input for sg1000m3 and smsj, and output via controller ports for Japanese and Korean drivers) [Enik Land]
-rw-r--r--src/mess/drivers/sms.c81
-rw-r--r--src/mess/includes/sms.h2
-rw-r--r--src/mess/machine/sms.c60
-rw-r--r--src/mess/machine/sms_lphaser.c2
-rw-r--r--src/mess/machine/smsctrl.h2
5 files changed, 86 insertions, 61 deletions
diff --git a/src/mess/drivers/sms.c b/src/mess/drivers/sms.c
index fd56b6283c0..801d790d848 100644
--- a/src/mess/drivers/sms.c
+++ b/src/mess/drivers/sms.c
@@ -10,9 +10,15 @@
To do:
- SIO interface for Game Gear (needs netplay, I guess)
- - SMS lightgun support
- - LCD persistence emulation for GG
- - SMS 3D glass support
+ - SMS Store Display Unit
+ - Keyboard support for Sega Mark-III (sg1000m3 driver)
+ - Mark-III expansion slot, used by keyboard and FM module
+ - Japanese Sports Pad model used by the game Sports Pad Soccer
+ (info: http://www.smspower.org/forums/viewtopic.php?t=11876)
+ - Software compatibility flags, by region and/or BIOS
+ - Emulate SRAM cartridges? (for use with Bock's dump tool)
+ - Support for other DE-9 compatible controllers, like the Mega Drive 6-Button
+ that has software support (at least a test tool made by Charles MacDonald)
The Game Gear SIO hardware is not emulated but has some
placeholders in 'machine/sms.c'
@@ -291,8 +297,8 @@ static ADDRESS_MAP_START( sms_io, AS_IO, 8, sms_state )
ADDRESS_MAP_END
-// I/O ports $3E and $3F do not exist o Mark-III
-static ADDRESS_MAP_START( sms_no3e3f_io, AS_IO, 8, sms_state )
+// I/O ports $3E and $3F do not exist on Mark-III
+static ADDRESS_MAP_START( sg1000m3_io, AS_IO, 8, sms_state )
ADDRESS_MAP_GLOBAL_MASK(0xff)
ADDRESS_MAP_UNMAP_HIGH
AM_RANGE(0x40, 0x7f) AM_READ(sms_count_r)
@@ -318,11 +324,12 @@ ADDRESS_MAP_END
// addresses.
// At least the mirrors for I/O ports $3E/$3F don't seem to exist there.
// Leaving the mirrors breaks the Korean cartridge bublboky.
-static ADDRESS_MAP_START( sms_kor_io, AS_IO, 8, sms_state )
+// The version is derived from japanene SMS, that has no output on its
+// controller ports, so port $3F probably does not exist, like on Mark-III.
+static ADDRESS_MAP_START( sms_fm_io, AS_IO, 8, sms_state )
ADDRESS_MAP_GLOBAL_MASK(0xff)
ADDRESS_MAP_UNMAP_HIGH
AM_RANGE(0x3e, 0x3e) AM_WRITE(sms_bios_w)
- AM_RANGE(0x3f, 0x3f) AM_WRITE(sms_io_control_w)
AM_RANGE(0x40, 0x7f) AM_READ(sms_count_r)
AM_RANGE(0x40, 0x7f) AM_DEVWRITE("segapsg", segapsg_device, write)
AM_RANGE(0x80, 0x80) AM_MIRROR(0x3e) AM_DEVREADWRITE("sms_vdp", sega315_5124_device, vram_read, vram_write)
@@ -371,12 +378,9 @@ static INPUT_PORTS_START( sms )
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME(DEF_STR(Pause)) PORT_CODE(KEYCODE_1)
INPUT_PORTS_END
-static INPUT_PORTS_START( sms1 )
+static INPUT_PORTS_START( sg1000m3 )
PORT_INCLUDE( sms )
- PORT_START("RESET")
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_SERVICE1 ) PORT_NAME("Reset Button")
-
PORT_START("SEGASCOPE")
PORT_CONFNAME( 0x01, 0x00, "SegaScope (3-D Glasses)" )
PORT_CONFSETTING( 0x00, DEF_STR( Off ) )
@@ -391,6 +395,13 @@ static INPUT_PORTS_START( sms1 )
PORT_BIT( 0x03, 0x00, IPT_UNUSED ) PORT_CONDITION("SEGASCOPE", 0x01, EQUALS, 0x00)
INPUT_PORTS_END
+static INPUT_PORTS_START( sms1 )
+ PORT_INCLUDE( sg1000m3 )
+
+ PORT_START("RESET")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_SERVICE1 ) PORT_NAME("Reset Button")
+INPUT_PORTS_END
+
static INPUT_PORTS_START( gg )
PORT_START("GG_PORT_DC")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(1) PORT_8WAY
@@ -561,11 +572,11 @@ static MACHINE_CONFIG_DERIVED( sms1_ntsc, sms_ntsc_base )
MCFG_DEFAULT_LAYOUT(layout_sms1)
- MCFG_PALETTE_LENGTH(SEGA315_5124_PALETTE_SIZE)
-
MCFG_VIDEO_START_OVERRIDE(sms_state,sms1)
MCFG_VIDEO_RESET_OVERRIDE(sms_state,sms1)
+ MCFG_PALETTE_LENGTH(SEGA315_5124_PALETTE_SIZE)
+
MCFG_SEGA315_5124_ADD("sms_vdp", _315_5124_ntsc_intf)
MCFG_SEGA315_5124_SET_SCREEN("screen")
@@ -727,11 +738,11 @@ static MACHINE_CONFIG_DERIVED( sms1_pal, sms_pal_base )
MCFG_DEFAULT_LAYOUT(layout_sms1)
- MCFG_PALETTE_LENGTH(SEGA315_5124_PALETTE_SIZE)
-
MCFG_VIDEO_START_OVERRIDE(sms_state,sms1)
MCFG_VIDEO_RESET_OVERRIDE(sms_state,sms1)
+ MCFG_PALETTE_LENGTH(SEGA315_5124_PALETTE_SIZE)
+
MCFG_SEGA315_5124_ADD("sms_vdp", _315_5124_pal_intf)
MCFG_SEGA315_5124_SET_SCREEN("screen")
@@ -741,6 +752,14 @@ static MACHINE_CONFIG_DERIVED( sms1_pal, sms_pal_base )
MACHINE_CONFIG_END
static MACHINE_CONFIG_DERIVED( sms_fm, sms1_ntsc )
+ MCFG_CPU_MODIFY("maincpu")
+ MCFG_CPU_IO_MAP(sms_fm_io)
+
+ // Japanese sms and sg1000m3 consoles do not have TH input
+ MCFG_SMS_CONTROL_PORT_MODIFY(CONTROL1_TAG)
+ MCFG_SMS_CONTROL_PORT_TH_INPUT_HANDLER(NULL)
+ MCFG_SMS_CONTROL_PORT_MODIFY(CONTROL2_TAG)
+ MCFG_SMS_CONTROL_PORT_TH_INPUT_HANDLER(NULL)
MCFG_SOUND_ADD("ym2413", YM2413, XTAL_53_693175MHz/15)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00)
@@ -748,7 +767,7 @@ MACHINE_CONFIG_END
static MACHINE_CONFIG_DERIVED( sg1000m3, sms_fm )
MCFG_CPU_MODIFY("maincpu")
- MCFG_CPU_IO_MAP(sms_no3e3f_io)
+ MCFG_CPU_IO_MAP(sg1000m3_io)
MCFG_DEVICE_REMOVE("slot")
MCFG_SG1000MK3_CARTRIDGE_ADD("slot", sg1000mk3_cart, NULL)
@@ -756,7 +775,7 @@ MACHINE_CONFIG_END
static MACHINE_CONFIG_DERIVED( sms2_fm, sms2_ntsc )
MCFG_CPU_MODIFY("maincpu")
- MCFG_CPU_IO_MAP(sms_kor_io)
+ MCFG_CPU_IO_MAP(sms_fm_io)
MCFG_SOUND_ADD("ym2413", YM2413, XTAL_53_693175MHz/15)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00)
@@ -780,10 +799,10 @@ static MACHINE_CONFIG_START( gamegear, sms_state )
SEGA315_5124_HEIGHT_NTSC, SEGA315_5124_TBORDER_START + SEGA315_5124_NTSC_192_TBORDER_HEIGHT + 3*8, SEGA315_5124_TBORDER_START + SEGA315_5124_NTSC_192_TBORDER_HEIGHT + 21*8 )
MCFG_SCREEN_UPDATE_DRIVER(sms_state, screen_update_gamegear)
- MCFG_PALETTE_LENGTH(SEGA315_5378_PALETTE_SIZE)
-
MCFG_VIDEO_START_OVERRIDE(sms_state,gamegear)
+ MCFG_PALETTE_LENGTH(SEGA315_5378_PALETTE_SIZE)
+
MCFG_SEGA315_5378_ADD("sms_vdp", _315_5124_ntsc_intf)
MCFG_SEGA315_5378_SET_SCREEN("screen")
@@ -947,15 +966,15 @@ ROM_END
***************************************************************************/
-/* YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY FULLNAME FLAGS */
-CONS( 1984, sg1000m3, sms, 0, sg1000m3, sms1, sms_state, sg1000m3, "Sega", "SG-1000 Mark III", GAME_SUPPORTS_SAVE )
-CONS( 1986, sms1, sms, 0, sms1_ntsc, sms1, sms_state, sms1, "Sega", "Master System I", GAME_SUPPORTS_SAVE )
-CONS( 1986, sms1pal, sms, 0, sms1_pal, sms1, sms_state, sms1, "Sega", "Master System I (PAL)" , GAME_SUPPORTS_SAVE )
-CONS( 1986, smssdisp, sms, 0, sms_sdisp, sms, smssdisp_state, smssdisp, "Sega", "Master System Store Display Unit", GAME_NOT_WORKING | GAME_SUPPORTS_SAVE )
-CONS( 1987, smsj, sms, 0, sms_fm, sms1, sms_state, smsj, "Sega", "Master System (Japan)", GAME_SUPPORTS_SAVE )
-CONS( 1990, sms, 0, 0, sms2_ntsc, sms, sms_state, sms1, "Sega", "Master System II", GAME_SUPPORTS_SAVE )
-CONS( 1990, smspal, sms, 0, sms2_pal, sms, sms_state, sms1, "Sega", "Master System II (PAL)", GAME_SUPPORTS_SAVE )
-CONS( 1990, sms2kr, sms, 0, sms2_fm, sms, sms_state, sms2kr, "Samsung", "Gam*Boy II (Korea)", GAME_SUPPORTS_SAVE )
-
-CONS( 1990, gamegear, 0, sms, gamegear, gg, sms_state, gamegear, "Sega", "Game Gear (Europe/America)", GAME_SUPPORTS_SAVE )
-CONS( 1990, gamegeaj, gamegear, 0, gamegear, gg, sms_state, gamegeaj, "Sega", "Game Gear (Japan)", GAME_SUPPORTS_SAVE )
+/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS */
+CONS( 1984, sg1000m3, sms, 0, sg1000m3, sg1000m3, sms_state, sg1000m3, "Sega", "SG-1000 Mark III", GAME_SUPPORTS_SAVE )
+CONS( 1986, sms1, sms, 0, sms1_ntsc, sms1, sms_state, sms1, "Sega", "Master System I", GAME_SUPPORTS_SAVE )
+CONS( 1986, sms1pal, sms, 0, sms1_pal, sms1, sms_state, sms1, "Sega", "Master System I (PAL)" , GAME_SUPPORTS_SAVE )
+CONS( 1986, smssdisp, sms, 0, sms_sdisp, sms, smssdisp_state, smssdisp, "Sega", "Master System Store Display Unit", GAME_NOT_WORKING | GAME_SUPPORTS_SAVE )
+CONS( 1987, smsj, sms, 0, sms_fm, sms1, sms_state, smsj, "Sega", "Master System (Japan)", GAME_SUPPORTS_SAVE )
+CONS( 1990, sms, 0, 0, sms2_ntsc, sms, sms_state, sms1, "Sega", "Master System II", GAME_SUPPORTS_SAVE )
+CONS( 1990, smspal, sms, 0, sms2_pal, sms, sms_state, sms1, "Sega", "Master System II (PAL)", GAME_SUPPORTS_SAVE )
+CONS( 1990, sms2kr, sms, 0, sms2_fm, sms, sms_state, sms2kr, "Samsung", "Gam*Boy II (Korea)", GAME_SUPPORTS_SAVE )
+
+CONS( 1990, gamegear, 0, sms, gamegear, gg, sms_state, gamegear, "Sega", "Game Gear (Europe/America)", GAME_SUPPORTS_SAVE )
+CONS( 1990, gamegeaj, gamegear, 0, gamegear, gg, sms_state, gamegeaj, "Sega", "Game Gear (Japan)", GAME_SUPPORTS_SAVE )
diff --git a/src/mess/includes/sms.h b/src/mess/includes/sms.h
index 93f5000e830..0318b6cdedc 100644
--- a/src/mess/includes/sms.h
+++ b/src/mess/includes/sms.h
@@ -48,6 +48,7 @@ public:
m_port_persist(*this, "PERSISTENCE"),
m_is_gamegear(0),
m_is_region_japan(0),
+ m_is_korean(0),
m_is_sdisp(0),
m_has_bios_0400(0),
m_has_bios_2000(0),
@@ -102,6 +103,7 @@ public:
// model identifiers
UINT8 m_is_gamegear;
UINT8 m_is_region_japan;
+ UINT8 m_is_korean;
UINT8 m_is_sdisp;
UINT8 m_has_bios_0400;
UINT8 m_has_bios_2000;
diff --git a/src/mess/machine/sms.c b/src/mess/machine/sms.c
index d07ed2039ad..c715e43b762 100644
--- a/src/mess/machine/sms.c
+++ b/src/mess/machine/sms.c
@@ -25,7 +25,7 @@ void sms_state::lphaser_hcount_latch()
WRITE_LINE_MEMBER(sms_state::sms_ctrl1_th_input)
{
// Check if TH of controller port 1 is set to input (1)
- if (m_io_ctrl_reg & 0x02)
+ if (m_is_korean || (m_io_ctrl_reg & 0x02))
{
if (state == 0)
{
@@ -45,7 +45,7 @@ WRITE_LINE_MEMBER(sms_state::sms_ctrl1_th_input)
WRITE_LINE_MEMBER(sms_state::sms_ctrl2_th_input)
{
// Check if TH of controller port 2 is set to input (1)
- if (m_io_ctrl_reg & 0x08)
+ if (m_is_korean || (m_io_ctrl_reg & 0x08))
{
if (state == 0)
{
@@ -64,23 +64,28 @@ WRITE_LINE_MEMBER(sms_state::sms_ctrl2_th_input)
void sms_state::sms_get_inputs( address_space &space )
{
- UINT8 data;
+ UINT8 data1, data2;
m_port_dc_reg = 0xff;
m_port_dd_reg = 0xff;
- data = m_port_ctrl1->port_r();
- m_port_dc_reg &= ~0x0F | data; // Up, Down, Left, Right
- m_port_dc_reg &= ~0x10 | (data >> 1); // TL (Button 1)
- m_port_dc_reg &= ~0x20 | (data >> 2); // TR (Button 2)
- m_port_dd_reg &= ~0x40 | data; // TH
-
- data = m_port_ctrl2->port_r();
- m_port_dc_reg &= ~0xc0 | (data << 6); // Up, Down
- m_port_dd_reg &= ~0x03 | (data >> 2); // Left, Right
- m_port_dd_reg &= ~0x04 | (data >> 3); // TL (Button 1)
- m_port_dd_reg &= ~0x08 | (data >> 4); // TR (Button 2)
- m_port_dd_reg &= ~0x80 | (data << 1); // TH
+ data1 = m_port_ctrl1->port_r();
+ m_port_dc_reg &= ~0x0f | data1; // Up, Down, Left, Right
+ m_port_dc_reg &= ~0x10 | (data1 >> 1); // TL (Button 1)
+ m_port_dc_reg &= ~0x20 | (data1 >> 2); // TR (Button 2)
+
+ data2 = m_port_ctrl2->port_r();
+ m_port_dc_reg &= ~0xc0 | (data2 << 6); // Up, Down
+ m_port_dd_reg &= ~0x03 | (data2 >> 2); // Left, Right
+ m_port_dd_reg &= ~0x04 | (data2 >> 3); // TL (Button 1)
+ m_port_dd_reg &= ~0x08 | (data2 >> 4); // TR (Button 2)
+
+ // Japanese consoles do not have TH line connected.
+ if (!m_is_region_japan || m_is_korean)
+ {
+ m_port_dd_reg &= ~0x40 | data1; // TH ctrl1
+ m_port_dd_reg &= ~0x80 | (data2 << 1); // TH ctrl2
+ }
}
@@ -225,10 +230,10 @@ READ8_MEMBER(sms_state::sms_input_port_dc_r)
sms_get_inputs(space);
// Check if TR of controller port 1 is set to output (0)
- if (!(m_io_ctrl_reg & 0x01))
+ if (!m_is_region_japan && !(m_io_ctrl_reg & 0x01))
{
// Read TR state set through IO control port
- m_port_dc_reg &= ~0x20 | (m_is_region_japan ? 0x00 : (m_io_ctrl_reg & 0x10) << 1);
+ m_port_dc_reg &= ~0x20 | ((m_io_ctrl_reg & 0x10) << 1);
}
return m_port_dc_reg;
@@ -248,23 +253,19 @@ READ8_MEMBER(sms_state::sms_input_port_dd_r)
{
m_port_dd_reg &= ~0x10 | (m_port_reset->read() & 0x01) << 4;
}
- else
- {
- m_port_dd_reg |= 0x10;
- }
// Check if TR of controller port 2 is set to output (0)
- if (!(m_io_ctrl_reg & 0x04))
+ if (!m_is_region_japan && !(m_io_ctrl_reg & 0x04))
{
// Read TR state set through IO control port
- m_port_dd_reg &= ~0x08 | (m_is_region_japan ? 0x00 : (m_io_ctrl_reg & 0x40) >> 3);
+ m_port_dd_reg &= ~0x08 | ((m_io_ctrl_reg & 0x40) >> 3);
}
// Check if TH of controller port 1 is set to output (0)
- if (!(m_io_ctrl_reg & 0x02))
+ if (!m_is_region_japan && !(m_io_ctrl_reg & 0x02))
{
// Read TH state set through IO control port
- m_port_dd_reg &= ~0x40 | (m_is_region_japan ? 0x00 : (m_io_ctrl_reg & 0x20) << 1);
+ m_port_dd_reg &= ~0x40 | ((m_io_ctrl_reg & 0x20) << 1);
}
else // TH set to input (1)
{
@@ -276,10 +277,10 @@ READ8_MEMBER(sms_state::sms_input_port_dd_r)
}
// Check if TH of controller port 2 is set to output (0)
- if (!(m_io_ctrl_reg & 0x08))
+ if (!m_is_region_japan && !(m_io_ctrl_reg & 0x08))
{
// Read TH state set through IO control port
- m_port_dd_reg &= ~0x80 | (m_is_region_japan ? 0x00 : (m_io_ctrl_reg & 0x80));
+ m_port_dd_reg &= ~0x80 | (m_io_ctrl_reg & 0x80);
}
else // TH set to input (1)
{
@@ -628,7 +629,7 @@ WRITE8_MEMBER(sms_state::gg_sio_w)
case 0x00: /* Parallel Data */
break;
- case 0x01: /* Data Direction/ NMI Enable */
+ case 0x01: /* Data Direction / NMI Enable */
break;
case 0x02: /* Serial Output */
@@ -652,7 +653,7 @@ READ8_MEMBER(sms_state::gg_sio_r)
case 0x00: /* Parallel Data */
break;
- case 0x01: /* Data Direction/ NMI Enable */
+ case 0x01: /* Data Direction / NMI Enable */
break;
case 0x02: /* Serial Output */
@@ -973,6 +974,7 @@ DRIVER_INIT_MEMBER(sms_state,sms2kr)
m_is_region_japan = 1;
m_has_bios_full = 1;
m_has_fm = 1;
+ m_is_korean = 1;
}
diff --git a/src/mess/machine/sms_lphaser.c b/src/mess/machine/sms_lphaser.c
index 3f28c3c8c4f..abd0674a290 100644
--- a/src/mess/machine/sms_lphaser.c
+++ b/src/mess/machine/sms_lphaser.c
@@ -78,7 +78,7 @@ sms_light_phaser_device::sms_light_phaser_device(const machine_config &mconfig,
m_lphaser_y(*this, "LPHASER_Y")
{
// Workaround for failed validation that occurs when running on a driver
- // with Sega Scope emulation, which adds 2 screens for left/right lens.
+ // with Sega Scope emulation, which adds 2 screens (left/right lenses).
m_screen_tag = ":screen";
}
diff --git a/src/mess/machine/smsctrl.h b/src/mess/machine/smsctrl.h
index 9962782d895..bcb0b683683 100644
--- a/src/mess/machine/smsctrl.h
+++ b/src/mess/machine/smsctrl.h
@@ -26,6 +26,8 @@
#define MCFG_SMS_CONTROL_PORT_ADD(_tag, _slot_intf, _def_slot) \
MCFG_DEVICE_ADD(_tag, SMS_CONTROL_PORT, 0) \
MCFG_DEVICE_SLOT_INTERFACE(_slot_intf, _def_slot, false)
+#define MCFG_SMS_CONTROL_PORT_MODIFY(_tag) \
+ MCFG_DEVICE_MODIFY(_tag)
#define MCFG_SMS_CONTROL_PORT_TH_INPUT_HANDLER(_devcb) \