mirror of
https://github.com/holub/mame
synced 2025-04-26 02:07:14 +03:00
(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]
This commit is contained in:
parent
c6a6b78f95
commit
52bfccb35c
@ -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 )
|
||||
/* 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 )
|
||||
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 )
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
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)
|
||||
|
||||
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
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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";
|
||||
}
|
||||
|
||||
|
@ -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) \
|
||||
|
Loading…
Reference in New Issue
Block a user