mirror of
https://github.com/holub/mame
synced 2025-04-20 15:32:45 +03:00
(MESS) sms.c: Various changes: [Enik Land]
- adjust/add some comments - restore complete controller port functions to the japanese SMS version - isolate some code to their proper consoles - remove FM support of the sms2kr driver - remove Reset button of the smsj driver - add emulation of the japanese Sports Pad model, required by Sports Pad Soccer - adjust some code of other controller devices.
This commit is contained in:
parent
f3813ffd76
commit
faed87bd57
2
.gitattributes
vendored
2
.gitattributes
vendored
@ -8287,6 +8287,8 @@ src/mess/machine/sms_rfu.c svneol=native#text/plain
|
||||
src/mess/machine/sms_rfu.h svneol=native#text/plain
|
||||
src/mess/machine/sms_sports.c svneol=native#text/plain
|
||||
src/mess/machine/sms_sports.h svneol=native#text/plain
|
||||
src/mess/machine/sms_sportsjp.c svneol=native#text/plain
|
||||
src/mess/machine/sms_sportsjp.h svneol=native#text/plain
|
||||
src/mess/machine/smsctrl.c svneol=native#text/plain
|
||||
src/mess/machine/smsctrl.h svneol=native#text/plain
|
||||
src/mess/machine/smsexp.c svneol=native#text/plain
|
||||
|
@ -10,11 +10,14 @@
|
||||
To do:
|
||||
|
||||
- SIO interface for Game Gear (needs netplay, I guess)
|
||||
- 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)
|
||||
- Gear to Gear Port SMS Controller Adaptor
|
||||
- SMS Store Display Unit (Kiosk)
|
||||
- Sega Game Box 9
|
||||
- SMS Disk System (floppy disk drive) - unreleased
|
||||
- Sega Graphic Board (black version) - unreleased
|
||||
- Rapid button of japanese Master System & korean Gam*Boy I
|
||||
- Keyboard support for Sega Mark III (sg1000m3 driver)
|
||||
- Mark III expansion slot, used by keyboard and FM module
|
||||
- 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
|
||||
@ -297,7 +300,7 @@ static ADDRESS_MAP_START( sms_io, AS_IO, 8, sms_state )
|
||||
ADDRESS_MAP_END
|
||||
|
||||
|
||||
// I/O ports $3E and $3F do not exist on Mark-III
|
||||
// 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
|
||||
@ -320,16 +323,17 @@ static ADDRESS_MAP_START( sg1000m3_io, AS_IO, 8, sms_state )
|
||||
ADDRESS_MAP_END
|
||||
|
||||
|
||||
// It seems the Korean version does some more strict decoding on the I/O
|
||||
// It seems the Korean versions do some more strict decoding on the I/O
|
||||
// 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.
|
||||
// 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 )
|
||||
// Assume the same for the japanese SMS, which derived the first korean
|
||||
// version.
|
||||
static ADDRESS_MAP_START( smsj_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)
|
||||
@ -402,6 +406,13 @@ static INPUT_PORTS_START( sms1 )
|
||||
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_SERVICE1 ) PORT_NAME("Reset Button")
|
||||
INPUT_PORTS_END
|
||||
|
||||
static INPUT_PORTS_START( smsj )
|
||||
PORT_INCLUDE( sg1000m3 )
|
||||
|
||||
//PORT_START("RAPID")
|
||||
//PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_SERVICE1 ) PORT_NAME("Rapid Button") /* Not implemented */
|
||||
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
|
||||
@ -529,6 +540,30 @@ static MACHINE_CONFIG_START( sms_ntsc_base, sms_state )
|
||||
MCFG_SMS_CONTROL_PORT_PIXEL_HANDLER(READ32(sms_state, sms_pixel_color))
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
/*
|
||||
For SMS drivers, the ratio between CPU and pixel clocks, set through dividers, is 2/3. The
|
||||
division that sets the pixel clock, in MCFG_SCREEN_RAW_PARAMS(), results in a remainder
|
||||
that is discarded internally. Due to this rounding, the cycle time and the screen pixel
|
||||
time, derived from their clocks, do not longer match (inversely) the exact original ratio
|
||||
of these clocks. The SMS VDP emulation controls some properties (counters/flags) through
|
||||
screen timing, that the core calculates based on the emulation time. The VDP properties
|
||||
are read in the CPU timeslice. When a CPU operation that access the VDP is executed, the
|
||||
elapsed emulation time is also based on how many CPU cycles have elapsed since start of
|
||||
the current timeslice. Depending on this amount of CPU cycles, when the core divides the
|
||||
elapsed time by the pixel time, the obtained pixel count may be less than expected. Flubba's
|
||||
VDPTest ROM relies on exact results. A workaround is to use an additional macro, for each
|
||||
driver, that resets the refresh rate, and by consequence the pixel time, without discard
|
||||
the remainder of the division. Considered a hack, it's not applied. The line that would be
|
||||
added, after MCFG_SCREEN_RAW_PARAMS(), is one of the following, according to the TV system
|
||||
of the driver.
|
||||
|
||||
- For NTSC drivers:
|
||||
MCFG_SCREEN_REFRESH_RATE((double) XTAL_53_693175MHz/10 / (SEGA315_5124_WIDTH * SEGA315_5124_HEIGHT_NTSC))
|
||||
|
||||
- For PAL drivers:
|
||||
MCFG_SCREEN_REFRESH_RATE((double) MASTER_CLOCK_PAL/10 / (SEGA315_5124_WIDTH * SEGA315_5124_HEIGHT_PAL))
|
||||
*/
|
||||
|
||||
static MACHINE_CONFIG_DERIVED( sms2_ntsc, sms_ntsc_base )
|
||||
/* video hardware */
|
||||
MCFG_SCREEN_ADD("screen", RASTER)
|
||||
@ -753,13 +788,7 @@ 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_CPU_IO_MAP(smsj_io)
|
||||
|
||||
MCFG_SOUND_ADD("ym2413", YM2413, XTAL_53_693175MHz/15)
|
||||
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00)
|
||||
@ -769,16 +798,19 @@ static MACHINE_CONFIG_DERIVED( sg1000m3, sms_fm )
|
||||
MCFG_CPU_MODIFY("maincpu")
|
||||
MCFG_CPU_IO_MAP(sg1000m3_io)
|
||||
|
||||
// Mark III does 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_DEVICE_REMOVE("slot")
|
||||
MCFG_SG1000MK3_CARTRIDGE_ADD("slot", sg1000mk3_cart, NULL)
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
static MACHINE_CONFIG_DERIVED( sms2_fm, sms2_ntsc )
|
||||
static MACHINE_CONFIG_DERIVED( sms2_kr, sms2_ntsc )
|
||||
MCFG_CPU_MODIFY("maincpu")
|
||||
MCFG_CPU_IO_MAP(sms_fm_io)
|
||||
|
||||
MCFG_SOUND_ADD("ym2413", YM2413, XTAL_53_693175MHz/15)
|
||||
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00)
|
||||
MCFG_CPU_IO_MAP(smsj_io)
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
static MACHINE_CONFIG_START( gamegear, sms_state )
|
||||
@ -926,7 +958,7 @@ ROM_END
|
||||
Game driver(s)
|
||||
|
||||
US
|
||||
- Sega Master System I (sms1)
|
||||
- Sega Master System (I) (sms1)
|
||||
- prototype (M404) bios - 1986
|
||||
- without built-in game v1.3 - 1986
|
||||
- built-in Hang On/Safari Hunt v2.4 - 1988
|
||||
@ -943,11 +975,15 @@ ROM_END
|
||||
- without built-in game v2.1 - 1987
|
||||
|
||||
KR
|
||||
- Sega Master System II (sms2kr)
|
||||
- built-in Alex Kidd in Miracle World (Korean)
|
||||
- Samsung Gam*Boy (same as smsj)
|
||||
- without built-in game v2.1 - 1989
|
||||
(same smsj driver used, despite units with plug-in AC adaptor
|
||||
have FM and the ones with built-in AC adaptor do not)
|
||||
- Samsung Gam*Boy II / Aladdin Boy (sms2kr)
|
||||
- built-in Alex Kidd in Miracle World (Korean) - 1992 for A.Boy
|
||||
|
||||
EU
|
||||
- Sega Master System I (sms1pal)
|
||||
- Sega Master System (I) (sms1pal)
|
||||
- without built-in game v1.3 - 1986
|
||||
- built-in Hang On/Safari Hunt v2.4 - 1988
|
||||
- built-in Hang On v3.4 - 1988
|
||||
@ -958,11 +994,26 @@ ROM_END
|
||||
- built-in Sonic the Hedgehog - 1991
|
||||
|
||||
BR
|
||||
- Sega Master System I - 1987
|
||||
- Sega Master System II???
|
||||
- Sega Master System III - Tec Toy, 1987
|
||||
- Sega Master System Compact - Tec Toy, 1992
|
||||
- Sega Master System Girl - Tec Toy, 1992
|
||||
- Tec Toy Master System (I) (same as sms1)
|
||||
- built-in Hang On/Safari Hunt v2.4 - 1989
|
||||
- Tec Toy Master System II (same as sms1)
|
||||
- built-in Alex Kidd in Miracle World - 1991
|
||||
- Tec Toy Master System III Compact (same as sms)
|
||||
- built-in Alex Kidd in Miracle World - 1992
|
||||
- built-in Sonic the Hedgehog - 1993
|
||||
- built-in World Cup Italia '90 (Super Futebol II) - 1994
|
||||
- built-in Hang On/Safari Hunt v2.4 (blue L.Phaser pack)
|
||||
- Tec Toy Master System Super Compact (no driver)
|
||||
- built-in Alex Kidd in Miracle World - 1993 (or 1994?)
|
||||
- built-in Sonic the Hedgehog - 1993
|
||||
- built-in World Cup Italia '90 (Super Futebol II) - 1994
|
||||
- Tec Toy Master System Girl (no driver)
|
||||
- built-in Monica no Castelo do Dragao
|
||||
- built-in Sonic the Hedgehog (T. Monica em O Resgate pack)
|
||||
Notes about BR:
|
||||
- PAL-M has same frequency and line count of NTSC
|
||||
- Tec Toy later changed its logo twice and its name to Tectoy
|
||||
- 20XX models (Handy, Collection, Evolution...) likely have SoC hardware
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
@ -971,10 +1022,10 @@ CONS( 1984, sg1000m3, sms, 0, sg1000m3, sg1000m3, sms_state,
|
||||
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( 1987, smsj, sms, 0, sms_fm, smsj, 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, sms2kr, sms, 0, sms2_kr, 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 )
|
||||
|
@ -48,7 +48,7 @@ public:
|
||||
m_port_persist(*this, "PERSISTENCE"),
|
||||
m_is_gamegear(0),
|
||||
m_is_region_japan(0),
|
||||
m_is_korean(0),
|
||||
m_is_mark_iii(0),
|
||||
m_is_sdisp(0),
|
||||
m_has_bios_0400(0),
|
||||
m_has_bios_2000(0),
|
||||
@ -103,7 +103,7 @@ public:
|
||||
// model identifiers
|
||||
UINT8 m_is_gamegear;
|
||||
UINT8 m_is_region_japan;
|
||||
UINT8 m_is_korean;
|
||||
UINT8 m_is_mark_iii;
|
||||
UINT8 m_is_sdisp;
|
||||
UINT8 m_has_bios_0400;
|
||||
UINT8 m_has_bios_2000;
|
||||
@ -174,7 +174,6 @@ public:
|
||||
protected:
|
||||
void setup_bios();
|
||||
void setup_rom();
|
||||
void setup_sms_cart();
|
||||
void lphaser_hcount_latch();
|
||||
void sms_get_inputs(address_space &space);
|
||||
};
|
||||
|
@ -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_is_korean || (m_io_ctrl_reg & 0x02))
|
||||
if (m_io_ctrl_reg & 0x02)
|
||||
{
|
||||
if (state == 0)
|
||||
{
|
||||
@ -33,7 +33,7 @@ WRITE_LINE_MEMBER(sms_state::sms_ctrl1_th_input)
|
||||
}
|
||||
else
|
||||
{
|
||||
// If previous state was 0 and now is 1, latch hcount.
|
||||
// State is 1. If changed from 0, hcount is latched.
|
||||
if (m_ctrl1_th_state == 0)
|
||||
lphaser_hcount_latch();
|
||||
}
|
||||
@ -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_is_korean || (m_io_ctrl_reg & 0x08))
|
||||
if (m_io_ctrl_reg & 0x08)
|
||||
{
|
||||
if (state == 0)
|
||||
{
|
||||
@ -53,7 +53,7 @@ WRITE_LINE_MEMBER(sms_state::sms_ctrl2_th_input)
|
||||
}
|
||||
else
|
||||
{
|
||||
// If previous state was 0 and now is 1, latch hcount.
|
||||
// State is 1. If changed from 0, hcount is latched.
|
||||
if (m_ctrl2_th_state == 0)
|
||||
lphaser_hcount_latch();
|
||||
}
|
||||
@ -69,6 +69,10 @@ void sms_state::sms_get_inputs( address_space &space )
|
||||
m_port_dc_reg = 0xff;
|
||||
m_port_dd_reg = 0xff;
|
||||
|
||||
// The bit order of the emulated controller port tries to follow its
|
||||
// physical pins numbering. For register bits whose order differs,
|
||||
// it's necessary move the equivalent controller bits to match.
|
||||
|
||||
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)
|
||||
@ -80,8 +84,8 @@ void sms_state::sms_get_inputs( address_space &space )
|
||||
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)
|
||||
// Sega Mark III does not have TH line connected.
|
||||
if (!m_is_mark_iii)
|
||||
{
|
||||
m_port_dd_reg &= ~0x40 | data1; // TH ctrl1
|
||||
m_port_dd_reg &= ~0x80 | (data2 << 1); // TH ctrl2
|
||||
@ -104,7 +108,7 @@ READ8_MEMBER(sms_state::sms_fm_detect_r)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_bios_port & IO_CHIP)
|
||||
if (!m_is_mark_iii && (m_bios_port & IO_CHIP))
|
||||
{
|
||||
return 0xff;
|
||||
}
|
||||
@ -213,14 +217,23 @@ WRITE_LINE_MEMBER(sms_state::sms_pause_callback)
|
||||
else
|
||||
m_paused = 0;
|
||||
|
||||
// clear TH latch of the controller ports
|
||||
m_ctrl1_th_latch = 0;
|
||||
m_ctrl2_th_latch = 0;
|
||||
if (!m_is_mark_iii)
|
||||
{
|
||||
// clear TH latch of the controller ports
|
||||
m_ctrl1_th_latch = 0;
|
||||
m_ctrl2_th_latch = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
READ8_MEMBER(sms_state::sms_input_port_dc_r)
|
||||
{
|
||||
if (m_is_mark_iii)
|
||||
{
|
||||
sms_get_inputs(space);
|
||||
return m_port_dc_reg;
|
||||
}
|
||||
|
||||
if (m_bios_port & IO_CHIP)
|
||||
{
|
||||
return 0xff;
|
||||
@ -230,7 +243,7 @@ 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_is_region_japan && !(m_io_ctrl_reg & 0x01))
|
||||
if (!(m_io_ctrl_reg & 0x01))
|
||||
{
|
||||
// Read TR state set through IO control port
|
||||
m_port_dc_reg &= ~0x20 | ((m_io_ctrl_reg & 0x10) << 1);
|
||||
@ -243,6 +256,12 @@ READ8_MEMBER(sms_state::sms_input_port_dc_r)
|
||||
|
||||
READ8_MEMBER(sms_state::sms_input_port_dd_r)
|
||||
{
|
||||
if (m_is_mark_iii)
|
||||
{
|
||||
sms_get_inputs(space);
|
||||
return m_port_dd_reg;
|
||||
}
|
||||
|
||||
if (m_bios_port & IO_CHIP)
|
||||
return 0xff;
|
||||
|
||||
@ -255,14 +274,14 @@ READ8_MEMBER(sms_state::sms_input_port_dd_r)
|
||||
}
|
||||
|
||||
// Check if TR of controller port 2 is set to output (0)
|
||||
if (!m_is_region_japan && !(m_io_ctrl_reg & 0x04))
|
||||
if (!(m_io_ctrl_reg & 0x04))
|
||||
{
|
||||
// Read TR state set through IO control port
|
||||
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_is_region_japan && !(m_io_ctrl_reg & 0x02))
|
||||
if (!(m_io_ctrl_reg & 0x02))
|
||||
{
|
||||
// Read TH state set through IO control port
|
||||
m_port_dd_reg &= ~0x40 | ((m_io_ctrl_reg & 0x20) << 1);
|
||||
@ -277,7 +296,7 @@ READ8_MEMBER(sms_state::sms_input_port_dd_r)
|
||||
}
|
||||
|
||||
// Check if TH of controller port 2 is set to output (0)
|
||||
if (!m_is_region_japan && !(m_io_ctrl_reg & 0x08))
|
||||
if (!(m_io_ctrl_reg & 0x08))
|
||||
{
|
||||
// Read TH state set through IO control port
|
||||
m_port_dd_reg &= ~0x80 | (m_io_ctrl_reg & 0x80);
|
||||
@ -373,7 +392,16 @@ WRITE8_MEMBER(sms_state::sms_mapper_w)
|
||||
m_mapper[offset] = data;
|
||||
m_mainram[0x1ffc + offset] = data;
|
||||
|
||||
if (m_bios_port & IO_BIOS_ROM || (m_is_gamegear && m_BIOS == NULL))
|
||||
if (m_is_mark_iii)
|
||||
{
|
||||
if (m_cartslot && m_cartslot->m_cart)
|
||||
cartridge_selected = true;
|
||||
else if (m_cardslot && m_cardslot->m_cart)
|
||||
card_selected = true;
|
||||
else
|
||||
return; // nothing to page in
|
||||
}
|
||||
else if (m_bios_port & IO_BIOS_ROM || (m_is_gamegear && m_BIOS == NULL))
|
||||
{
|
||||
if (!(m_bios_port & IO_CARTRIDGE) || (m_is_gamegear && m_BIOS == NULL))
|
||||
cartridge_selected = true;
|
||||
@ -394,7 +422,7 @@ WRITE8_MEMBER(sms_state::sms_mapper_w)
|
||||
switch (offset)
|
||||
{
|
||||
case 0: // Control RAM/ROM
|
||||
if (!(data & 0x08) && !(m_bios_port & IO_BIOS_ROM) && bios_selected) // BIOS ROM
|
||||
if (!(data & 0x08) && bios_selected && !(m_bios_port & IO_BIOS_ROM)) // BIOS ROM
|
||||
{
|
||||
if (!m_has_bios_0400 && !m_has_bios_2000)
|
||||
{
|
||||
@ -677,6 +705,29 @@ void sms_state::setup_rom()
|
||||
m_bank_enabled[1] = ENABLE_NONE;
|
||||
m_bank_enabled[2] = ENABLE_NONE;
|
||||
|
||||
if (m_is_mark_iii)
|
||||
{
|
||||
// Mark III uses the card slot by default, but has hardware method
|
||||
// that prioritizes the cartridge slot if it has a cartridge inserted.
|
||||
if (m_cartslot && m_cartslot->m_cart)
|
||||
{
|
||||
m_bank_enabled[3] = ENABLE_CART;
|
||||
m_bank_enabled[0] = ENABLE_CART;
|
||||
m_bank_enabled[1] = ENABLE_CART;
|
||||
m_bank_enabled[2] = ENABLE_CART;
|
||||
logerror("Switched in cartridge rom.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
m_bank_enabled[3] = ENABLE_CARD;
|
||||
m_bank_enabled[0] = ENABLE_CARD;
|
||||
m_bank_enabled[1] = ENABLE_CARD;
|
||||
m_bank_enabled[2] = ENABLE_CARD;
|
||||
logerror("Switching to card rom port.\n");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* 2. check and set up expansion port */
|
||||
if (!(m_bios_port & IO_EXPANSION) && (m_bios_port & IO_CARTRIDGE) && (m_bios_port & IO_CARD))
|
||||
{
|
||||
@ -746,7 +797,6 @@ void sms_state::setup_bios()
|
||||
if (m_BIOS == NULL || m_BIOS[0] == 0x00)
|
||||
{
|
||||
m_BIOS = NULL;
|
||||
m_bios_port |= IO_BIOS_ROM;
|
||||
m_has_bios_0400 = 0;
|
||||
m_has_bios_2000 = 0;
|
||||
m_has_bios_full = 0;
|
||||
@ -759,14 +809,22 @@ void sms_state::setup_bios()
|
||||
m_bios_page[1] = (1 < m_bios_page_count) ? 1 : 0;
|
||||
m_bios_page[2] = (2 < m_bios_page_count) ? 2 : 0;
|
||||
}
|
||||
|
||||
if (!m_is_mark_iii)
|
||||
{
|
||||
m_bios_port = (IO_EXPANSION | IO_CARTRIDGE | IO_CARD);
|
||||
if (!m_BIOS)
|
||||
{
|
||||
m_bios_port &= ~(IO_CARTRIDGE);
|
||||
m_bios_port |= IO_BIOS_ROM;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MACHINE_START_MEMBER(sms_state,sms)
|
||||
{
|
||||
char str[7];
|
||||
|
||||
m_left_lcd = machine().device("left_lcd");
|
||||
m_right_lcd = machine().device("right_lcd");
|
||||
m_space = &m_maincpu->space(AS_PROGRAM);
|
||||
|
||||
// alibaba and blockhol are ports of games for the MSX system. The
|
||||
@ -775,30 +833,44 @@ MACHINE_START_MEMBER(sms_state,sms)
|
||||
// the "call $4010" without a following RET statement. That is basically
|
||||
// a bug in the program code. The only way this cartridge could have run
|
||||
// successfully on a real unit is if the RAM would be initialized with
|
||||
// a F0 pattern on power up; F0 = RET P. Do that only for consoles in
|
||||
// Japan region (including KR), until confirmed on other consoles.
|
||||
// a F0 pattern on power up; F0 = RET P. Do that only for consoles of
|
||||
// Japan region (including Korea), until confirmed on other consoles.
|
||||
if (m_is_region_japan)
|
||||
{
|
||||
memset((UINT8*)m_space->get_write_ptr(0xc000), 0xf0, 0x1fff);
|
||||
}
|
||||
|
||||
save_item(NAME(m_fm_detect));
|
||||
save_item(NAME(m_io_ctrl_reg));
|
||||
save_item(NAME(m_paused));
|
||||
save_item(NAME(m_bios_port));
|
||||
save_item(NAME(m_mapper));
|
||||
save_item(NAME(m_port_dc_reg));
|
||||
save_item(NAME(m_port_dd_reg));
|
||||
save_item(NAME(m_gg_sio));
|
||||
save_item(NAME(m_bank_enabled));
|
||||
save_item(NAME(m_bios_page));
|
||||
|
||||
save_item(NAME(m_ctrl1_th_state));
|
||||
save_item(NAME(m_ctrl2_th_state));
|
||||
save_item(NAME(m_ctrl1_th_latch));
|
||||
save_item(NAME(m_ctrl2_th_latch));
|
||||
save_item(NAME(m_sscope_state));
|
||||
save_item(NAME(m_frame_sscope_state));
|
||||
if (m_has_fm)
|
||||
{
|
||||
save_item(NAME(m_fm_detect));
|
||||
}
|
||||
|
||||
if (!m_is_mark_iii)
|
||||
{
|
||||
save_item(NAME(m_bios_port));
|
||||
save_item(NAME(m_bios_page));
|
||||
save_item(NAME(m_io_ctrl_reg));
|
||||
save_item(NAME(m_ctrl1_th_latch));
|
||||
save_item(NAME(m_ctrl2_th_latch));
|
||||
}
|
||||
|
||||
if (m_is_gamegear)
|
||||
{
|
||||
save_item(NAME(m_gg_sio));
|
||||
}
|
||||
else
|
||||
{
|
||||
save_item(NAME(m_ctrl1_th_state));
|
||||
save_item(NAME(m_ctrl2_th_state));
|
||||
save_item(NAME(m_sscope_state));
|
||||
save_item(NAME(m_frame_sscope_state));
|
||||
}
|
||||
|
||||
if (m_is_sdisp)
|
||||
{
|
||||
@ -830,40 +902,47 @@ MACHINE_START_MEMBER(sms_state,sms)
|
||||
|
||||
MACHINE_RESET_MEMBER(sms_state,sms)
|
||||
{
|
||||
m_io_ctrl_reg = 0xff;
|
||||
if (m_has_fm)
|
||||
m_fm_detect = 0x01;
|
||||
|
||||
if (!m_is_mark_iii)
|
||||
{
|
||||
m_io_ctrl_reg = 0xff;
|
||||
m_bios_port = 0;
|
||||
m_ctrl1_th_latch = 0;
|
||||
m_ctrl2_th_latch = 0;
|
||||
}
|
||||
|
||||
if (m_is_gamegear)
|
||||
{
|
||||
if (m_cartslot->m_cart && m_cartslot->m_cart->get_sms_mode())
|
||||
m_vdp->set_sega315_5124_compatibility_mode(true);
|
||||
|
||||
/* Initialize SIO stuff for GG */
|
||||
m_gg_sio[0] = 0x7f;
|
||||
m_gg_sio[1] = 0xff;
|
||||
m_gg_sio[2] = 0x00;
|
||||
m_gg_sio[3] = 0xff;
|
||||
m_gg_sio[4] = 0x00;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ctrl1_th_state = 1;
|
||||
m_ctrl2_th_state = 1;
|
||||
m_lphaser_x_offs = (m_cartslot->m_cart) ? m_cartslot->m_cart->get_lphaser_xoffs() : 44;
|
||||
|
||||
m_sscope_state = 0;
|
||||
m_frame_sscope_state = 0;
|
||||
}
|
||||
|
||||
if (m_is_sdisp)
|
||||
{
|
||||
m_store_control = 0;
|
||||
m_current_cartridge = 0;
|
||||
}
|
||||
|
||||
m_bios_port = 0;
|
||||
|
||||
setup_bios();
|
||||
setup_sms_cart();
|
||||
setup_rom();
|
||||
|
||||
if (m_cartslot->m_cart && m_cartslot->m_cart->get_sms_mode())
|
||||
m_vdp->set_sega315_5124_compatibility_mode(true);
|
||||
|
||||
/* Initialize SIO stuff for GG */
|
||||
m_gg_sio[0] = 0x7f;
|
||||
m_gg_sio[1] = 0xff;
|
||||
m_gg_sio[2] = 0x00;
|
||||
m_gg_sio[3] = 0xff;
|
||||
m_gg_sio[4] = 0x00;
|
||||
|
||||
m_ctrl1_th_state = 1;
|
||||
m_ctrl2_th_state = 1;
|
||||
m_ctrl1_th_latch = 0;
|
||||
m_ctrl2_th_latch = 0;
|
||||
m_lphaser_x_offs = (m_cartslot->m_cart) ? m_cartslot->m_cart->get_lphaser_xoffs() : 44;
|
||||
|
||||
m_sscope_state = 0;
|
||||
m_frame_sscope_state = 0;
|
||||
}
|
||||
|
||||
READ8_MEMBER(smssdisp_state::sms_store_cart_select_r)
|
||||
@ -932,25 +1011,10 @@ WRITE_LINE_MEMBER(smssdisp_state::sms_store_int_callback)
|
||||
}
|
||||
}
|
||||
|
||||
void sms_state::setup_sms_cart()
|
||||
{
|
||||
m_bios_port = (IO_EXPANSION | IO_CARTRIDGE | IO_CARD);
|
||||
if (!m_is_gamegear && !m_BIOS)
|
||||
{
|
||||
m_bios_port |= IO_BIOS_ROM;
|
||||
|
||||
// Mark-III has hardware method that prioritizes cartridge slot.
|
||||
if (m_cartslot && m_cartslot->m_cart)
|
||||
m_bios_port &= ~(IO_CARTRIDGE);
|
||||
else
|
||||
m_bios_port &= ~(IO_CARD);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DRIVER_INIT_MEMBER(sms_state,sg1000m3)
|
||||
{
|
||||
m_is_region_japan = 1;
|
||||
m_is_mark_iii = 1;
|
||||
m_has_fm = 1;
|
||||
}
|
||||
|
||||
@ -973,8 +1037,6 @@ DRIVER_INIT_MEMBER(sms_state,sms2kr)
|
||||
{
|
||||
m_is_region_japan = 1;
|
||||
m_has_bios_full = 1;
|
||||
m_has_fm = 1;
|
||||
m_is_korean = 1;
|
||||
}
|
||||
|
||||
|
||||
@ -1001,6 +1063,9 @@ DRIVER_INIT_MEMBER(sms_state,gamegeaj)
|
||||
|
||||
VIDEO_START_MEMBER(sms_state,sms1)
|
||||
{
|
||||
m_left_lcd = machine().device("left_lcd");
|
||||
m_right_lcd = machine().device("right_lcd");
|
||||
|
||||
m_main_scr->register_screen_bitmap(m_prevleft_bitmap);
|
||||
m_main_scr->register_screen_bitmap(m_prevright_bitmap);
|
||||
save_item(NAME(m_prevleft_bitmap));
|
||||
|
@ -25,7 +25,7 @@ CUSTOM_INPUT_MEMBER( sms_paddle_device::dir_pins_r )
|
||||
{
|
||||
UINT8 data = m_paddle_x->read();
|
||||
|
||||
if (m_paddle_read_state)
|
||||
if (m_read_state)
|
||||
data >>= 4;
|
||||
|
||||
// The returned value is inverted due to IP_ACTIVE_LOW mapping.
|
||||
@ -36,7 +36,7 @@ CUSTOM_INPUT_MEMBER( sms_paddle_device::dir_pins_r )
|
||||
CUSTOM_INPUT_MEMBER( sms_paddle_device::tr_pin_r )
|
||||
{
|
||||
// The returned value is inverted due to IP_ACTIVE_LOW mapping.
|
||||
return ~m_paddle_read_state;
|
||||
return ~m_read_state;
|
||||
}
|
||||
|
||||
|
||||
@ -77,7 +77,7 @@ sms_paddle_device::sms_paddle_device(const machine_config &mconfig, const char *
|
||||
device_sms_control_port_interface(mconfig, *this),
|
||||
m_paddle_pins(*this, "CTRL_PORT"),
|
||||
m_paddle_x(*this, "PADDLE_X"),
|
||||
m_paddle_interval(PADDLE_INTERVAL)
|
||||
m_interval(PADDLE_INTERVAL)
|
||||
{
|
||||
}
|
||||
|
||||
@ -88,13 +88,11 @@ sms_paddle_device::sms_paddle_device(const machine_config &mconfig, const char *
|
||||
|
||||
void sms_paddle_device::device_start()
|
||||
{
|
||||
save_item(NAME(m_paddle_read_state));
|
||||
}
|
||||
m_start_time = machine().time();
|
||||
m_read_state = 0;
|
||||
|
||||
|
||||
void sms_paddle_device::device_reset()
|
||||
{
|
||||
m_paddle_read_state = 0;
|
||||
save_item(NAME(m_start_time));
|
||||
save_item(NAME(m_read_state));
|
||||
}
|
||||
|
||||
|
||||
@ -104,8 +102,8 @@ void sms_paddle_device::device_reset()
|
||||
|
||||
UINT8 sms_paddle_device::peripheral_r()
|
||||
{
|
||||
int n_intervals = machine().time().as_double() / m_paddle_interval.as_double();
|
||||
m_paddle_read_state = n_intervals & 1;
|
||||
int num_intervals = (machine().time() - m_start_time).as_double() / m_interval.as_double();
|
||||
m_read_state = num_intervals & 1;
|
||||
|
||||
return m_paddle_pins->read();
|
||||
}
|
||||
|
@ -40,7 +40,6 @@ public:
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_start();
|
||||
virtual void device_reset();
|
||||
|
||||
// device_sms_control_port_interface overrides
|
||||
virtual UINT8 peripheral_r();
|
||||
@ -49,8 +48,9 @@ private:
|
||||
required_ioport m_paddle_pins;
|
||||
required_ioport m_paddle_x;
|
||||
|
||||
UINT8 m_paddle_read_state;
|
||||
const attotime m_paddle_interval;
|
||||
UINT8 m_read_state;
|
||||
attotime m_start_time;
|
||||
const attotime m_interval;
|
||||
};
|
||||
|
||||
|
||||
|
@ -55,7 +55,7 @@ sms_rapid_fire_device::sms_rapid_fire_device(const machine_config &mconfig, cons
|
||||
device_sms_control_port_interface(mconfig, *this),
|
||||
m_rfire_sw(*this, "rfu_sw"),
|
||||
m_subctrl_port(*this, "ctrl"),
|
||||
m_rapid_fire_interval(RAPID_FIRE_INTERVAL)
|
||||
m_interval(RAPID_FIRE_INTERVAL)
|
||||
{
|
||||
}
|
||||
|
||||
@ -66,17 +66,16 @@ sms_rapid_fire_device::sms_rapid_fire_device(const machine_config &mconfig, cons
|
||||
|
||||
void sms_rapid_fire_device::device_start()
|
||||
{
|
||||
save_item(NAME(m_rapid_fire_state));
|
||||
m_start_time = machine().time();
|
||||
m_read_state = 0;
|
||||
|
||||
save_item(NAME(m_start_time));
|
||||
save_item(NAME(m_read_state));
|
||||
|
||||
m_subctrl_port->device_start();
|
||||
}
|
||||
|
||||
|
||||
void sms_rapid_fire_device::device_reset()
|
||||
{
|
||||
m_rapid_fire_state = 0;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// sms_peripheral_r - rapid fire read
|
||||
//-------------------------------------------------
|
||||
@ -85,18 +84,18 @@ UINT8 sms_rapid_fire_device::peripheral_r()
|
||||
{
|
||||
UINT8 data = 0xff;
|
||||
|
||||
int n_intervals = machine().time().as_double() / m_rapid_fire_interval.as_double();
|
||||
m_rapid_fire_state = n_intervals & 1;
|
||||
int num_intervals = (machine().time() - m_start_time).as_double() / m_interval.as_double();
|
||||
m_read_state = num_intervals & 1;
|
||||
|
||||
data = m_subctrl_port->port_r();
|
||||
|
||||
/* Check Rapid Fire switch for Button 1 (TL) */
|
||||
if (!(data & 0x20) && (m_rfire_sw->read() & 0x01))
|
||||
data |= m_rapid_fire_state << 5;
|
||||
data |= m_read_state << 5;
|
||||
|
||||
/* Check Rapid Fire switch for Button 2 (TR) */
|
||||
if (!(data & 0x80) && (m_rfire_sw->read() & 0x02))
|
||||
data |= m_rapid_fire_state << 7;
|
||||
data |= m_read_state << 7;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
@ -40,7 +40,6 @@ public:
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_start();
|
||||
virtual void device_reset();
|
||||
virtual machine_config_constructor device_mconfig_additions() const;
|
||||
|
||||
// device_sms_control_port_interface overrides
|
||||
@ -51,8 +50,9 @@ private:
|
||||
required_ioport m_rfire_sw;
|
||||
required_device<sms_control_port_device> m_subctrl_port;
|
||||
|
||||
UINT8 m_rapid_fire_state;
|
||||
const attotime m_rapid_fire_interval;
|
||||
UINT8 m_read_state;
|
||||
attotime m_start_time;
|
||||
const attotime m_interval;
|
||||
};
|
||||
|
||||
|
||||
|
@ -23,18 +23,18 @@ const device_type SMS_SPORTS_PAD = &device_creator<sms_sports_pad_device>;
|
||||
|
||||
CUSTOM_INPUT_MEMBER( sms_sports_pad_device::dir_pins_r )
|
||||
{
|
||||
UINT8 data = 0xff;
|
||||
UINT8 data = 0;
|
||||
|
||||
switch (m_sports_pad_state)
|
||||
switch (m_read_state)
|
||||
{
|
||||
case 0:
|
||||
data = (m_sports_x->read() >> 4);
|
||||
data = m_sports_x->read() >> 4;
|
||||
break;
|
||||
case 1:
|
||||
data = m_sports_x->read();
|
||||
break;
|
||||
case 2:
|
||||
data = (m_sports_y->read() >> 4);
|
||||
data = m_sports_y->read() >> 4;
|
||||
break;
|
||||
case 3:
|
||||
data = m_sports_y->read();
|
||||
@ -48,7 +48,7 @@ CUSTOM_INPUT_MEMBER( sms_sports_pad_device::dir_pins_r )
|
||||
|
||||
CUSTOM_INPUT_MEMBER( sms_sports_pad_device::th_pin_r )
|
||||
{
|
||||
return m_sports_pad_last_data;
|
||||
return m_last_data;
|
||||
}
|
||||
|
||||
|
||||
@ -56,16 +56,16 @@ INPUT_CHANGED_MEMBER( sms_sports_pad_device::th_pin_w )
|
||||
{
|
||||
attotime cur_time = machine().time();
|
||||
|
||||
if (cur_time - m_sports_pad_last_time > m_sports_pad_interval)
|
||||
if (cur_time - m_last_time > m_interval)
|
||||
{
|
||||
m_sports_pad_state = 0;
|
||||
m_read_state = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_sports_pad_state = (m_sports_pad_state + 1) & 3;
|
||||
m_read_state = (m_read_state + 1) & 3;
|
||||
}
|
||||
m_sports_pad_last_time = cur_time;
|
||||
m_sports_pad_last_data = newval;
|
||||
m_last_time = cur_time;
|
||||
m_last_data = newval;
|
||||
}
|
||||
|
||||
|
||||
@ -118,7 +118,7 @@ sms_sports_pad_device::sms_sports_pad_device(const machine_config &mconfig, cons
|
||||
m_sports_out(*this, "SPORTS_OUT"),
|
||||
m_sports_x(*this, "SPORTS_X"),
|
||||
m_sports_y(*this, "SPORTS_Y"),
|
||||
m_sports_pad_interval(SPORTS_PAD_INTERVAL)
|
||||
m_interval(SPORTS_PAD_INTERVAL)
|
||||
{
|
||||
}
|
||||
|
||||
@ -129,17 +129,13 @@ sms_sports_pad_device::sms_sports_pad_device(const machine_config &mconfig, cons
|
||||
|
||||
void sms_sports_pad_device::device_start()
|
||||
{
|
||||
save_item(NAME(m_sports_pad_state));
|
||||
save_item(NAME(m_sports_pad_last_data));
|
||||
save_item(NAME(m_sports_pad_last_time));
|
||||
}
|
||||
m_read_state = 0;
|
||||
m_last_data = 0;
|
||||
m_last_time = machine().time();
|
||||
|
||||
|
||||
void sms_sports_pad_device::device_reset()
|
||||
{
|
||||
m_sports_pad_state = 0;
|
||||
m_sports_pad_last_data = 0;
|
||||
m_sports_pad_last_time = machine().time();
|
||||
save_item(NAME(m_read_state));
|
||||
save_item(NAME(m_last_data));
|
||||
save_item(NAME(m_last_time));
|
||||
}
|
||||
|
||||
|
||||
|
@ -41,7 +41,6 @@ public:
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_start();
|
||||
virtual void device_reset();
|
||||
|
||||
// device_sms_control_port_interface overrides
|
||||
virtual UINT8 peripheral_r();
|
||||
@ -53,10 +52,10 @@ private:
|
||||
required_ioport m_sports_x;
|
||||
required_ioport m_sports_y;
|
||||
|
||||
UINT8 m_sports_pad_state;
|
||||
UINT8 m_sports_pad_last_data;
|
||||
const attotime m_sports_pad_interval;
|
||||
attotime m_sports_pad_last_time;
|
||||
UINT8 m_read_state;
|
||||
UINT8 m_last_data;
|
||||
const attotime m_interval;
|
||||
attotime m_last_time;
|
||||
};
|
||||
|
||||
|
||||
|
157
src/mess/machine/sms_sportsjp.c
Normal file
157
src/mess/machine/sms_sportsjp.c
Normal file
@ -0,0 +1,157 @@
|
||||
/**********************************************************************
|
||||
|
||||
Sega Master System "Sports Pad" (japanese model) emulation
|
||||
|
||||
Copyright MESS Team.
|
||||
Visit http://mamedev.org for licensing and usage restrictions.
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
// The japanese Sports Pad controller is only required to play the cartridge
|
||||
// Sports Pad Soccer, released in Japan. It uses a different mode than the
|
||||
// used by the US model, due to missing output lines on Sega Mark III
|
||||
// controller ports.
|
||||
|
||||
#include "sms_sportsjp.h"
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// DEVICE DEFINITIONS
|
||||
//**************************************************************************
|
||||
|
||||
const device_type SMS_SPORTS_PAD_JP = &device_creator<sms_sports_pad_jp_device>;
|
||||
|
||||
|
||||
#define SPORTS_PAD_JP_INTERVAL attotime::from_hz(30000) // 30Hz (not measured)
|
||||
|
||||
|
||||
DECLARE_CUSTOM_INPUT_MEMBER( sms_sports_pad_jp_device::dir_pins_r )
|
||||
{
|
||||
UINT8 data = 0;
|
||||
|
||||
switch (m_read_state)
|
||||
{
|
||||
case 0:
|
||||
data = m_sports_jp_x->read() >> 4;
|
||||
break;
|
||||
case 1:
|
||||
data = m_sports_jp_x->read();
|
||||
break;
|
||||
case 2:
|
||||
data = m_sports_jp_y->read() >> 4;
|
||||
break;
|
||||
case 3:
|
||||
data = m_sports_jp_y->read();
|
||||
break;
|
||||
}
|
||||
|
||||
// The returned value is inverted due to IP_ACTIVE_LOW mapping.
|
||||
return ~(data & 0x0f);
|
||||
}
|
||||
|
||||
|
||||
static INPUT_PORTS_START( sms_sports_pad_jp )
|
||||
PORT_START("SPORTS_JP_IN")
|
||||
PORT_BIT( 0x0f, IP_ACTIVE_LOW, IPT_SPECIAL ) PORT_CUSTOM_MEMBER(DEVICE_SELF, sms_sports_pad_jp_device, dir_pins_r, NULL) // Directional pins
|
||||
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) // Vcc
|
||||
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 ) // TL (Button 1)
|
||||
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED ) // TH
|
||||
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON2 ) // TR (Button 2)
|
||||
|
||||
PORT_START("SPORTS_JP_X") /* Sports Pad X axis */
|
||||
PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_X ) PORT_SENSITIVITY(50) PORT_KEYDELTA(40)
|
||||
|
||||
PORT_START("SPORTS_JP_Y") /* Sports Pad Y axis */
|
||||
PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_Y ) PORT_SENSITIVITY(50) PORT_KEYDELTA(40)
|
||||
INPUT_PORTS_END
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// input_ports - device-specific input ports
|
||||
//-------------------------------------------------
|
||||
|
||||
ioport_constructor sms_sports_pad_jp_device::device_input_ports() const
|
||||
{
|
||||
return INPUT_PORTS_NAME( sms_sports_pad_jp );
|
||||
}
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// LIVE DEVICE
|
||||
//**************************************************************************
|
||||
|
||||
//-------------------------------------------------
|
||||
// sms_sports_pad_jp_device - constructor
|
||||
//-------------------------------------------------
|
||||
|
||||
sms_sports_pad_jp_device::sms_sports_pad_jp_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
|
||||
device_t(mconfig, SMS_SPORTS_PAD_JP, "Sports Pad JP", tag, owner, clock, "sms_sports_pad_jp", __FILE__),
|
||||
device_sms_control_port_interface(mconfig, *this),
|
||||
m_sports_jp_in(*this, "SPORTS_JP_IN"),
|
||||
m_sports_jp_x(*this, "SPORTS_JP_X"),
|
||||
m_sports_jp_y(*this, "SPORTS_JP_Y"),
|
||||
m_interval(SPORTS_PAD_JP_INTERVAL)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_start - device-specific startup
|
||||
//-------------------------------------------------
|
||||
|
||||
void sms_sports_pad_jp_device::device_start()
|
||||
{
|
||||
m_start_time = machine().time();
|
||||
m_read_state = 0;
|
||||
|
||||
save_item(NAME(m_start_time));
|
||||
save_item(NAME(m_read_state));
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// sms_peripheral_r - sports pad read
|
||||
//-------------------------------------------------
|
||||
|
||||
UINT8 sms_sports_pad_jp_device::peripheral_r()
|
||||
{
|
||||
UINT8 data;
|
||||
int num_intervals = (machine().time() - m_start_time).as_double() / m_interval.as_double();
|
||||
m_read_state = num_intervals % 5;
|
||||
|
||||
data = m_sports_jp_in->read();
|
||||
|
||||
switch (m_read_state)
|
||||
{
|
||||
case 0:
|
||||
// X high nibble
|
||||
data &= ~0x20; // TL 0
|
||||
data &= ~0x80; // TR 0
|
||||
break;
|
||||
case 1:
|
||||
// X low nibble
|
||||
data |= 0x20; // TL 1
|
||||
data &= ~0x80; // TR 0
|
||||
break;
|
||||
case 2:
|
||||
// Y high nibble
|
||||
data &= ~0x20; // TL 0
|
||||
data &= ~0x80; // TR 0
|
||||
break;
|
||||
case 3:
|
||||
// Y low nibble
|
||||
data |= 0x20; // TL 1
|
||||
data &= ~0x80; // TR 0
|
||||
break;
|
||||
case 4:
|
||||
// buttons 1 and 2
|
||||
data = (data & 0x20) >> 5 | (data & 0x80) >> 6 | 0xfc;
|
||||
data |= 0x20; // TL 1
|
||||
data |= 0x80; // TR 1
|
||||
break;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
66
src/mess/machine/sms_sportsjp.h
Normal file
66
src/mess/machine/sms_sportsjp.h
Normal file
@ -0,0 +1,66 @@
|
||||
/**********************************************************************
|
||||
|
||||
Sega Master System "Sports Pad" (japanese model) emulation
|
||||
|
||||
Copyright MESS Team.
|
||||
Visit http://mamedev.org for licensing and usage restrictions.
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
// The japanese Sports Pad controller is only required to play the cartridge
|
||||
// Sports Pad Soccer, released in Japan. It uses a different mode than the
|
||||
// used by the US model, due to missing output lines on Sega Mark III
|
||||
// controller ports.
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __SMS_SPORTS_PAD_JP__
|
||||
#define __SMS_SPORTS_PAD_JP__
|
||||
|
||||
|
||||
#include "emu.h"
|
||||
#include "machine/smsctrl.h"
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// TYPE DEFINITIONS
|
||||
//**************************************************************************
|
||||
|
||||
// ======================> sms_sports_pad_jp_device
|
||||
|
||||
class sms_sports_pad_jp_device : public device_t,
|
||||
public device_sms_control_port_interface
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
sms_sports_pad_jp_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
|
||||
// optional information overrides
|
||||
virtual ioport_constructor device_input_ports() const;
|
||||
|
||||
CUSTOM_INPUT_MEMBER( dir_pins_r );
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_start();
|
||||
|
||||
// device_sms_control_port_interface overrides
|
||||
virtual UINT8 peripheral_r();
|
||||
|
||||
private:
|
||||
required_ioport m_sports_jp_in;
|
||||
required_ioport m_sports_jp_x;
|
||||
required_ioport m_sports_jp_y;
|
||||
|
||||
UINT8 m_read_state;
|
||||
attotime m_start_time;
|
||||
const attotime m_interval;
|
||||
};
|
||||
|
||||
|
||||
// device type definition
|
||||
extern const device_type SMS_SPORTS_PAD_JP;
|
||||
|
||||
|
||||
#endif
|
@ -118,5 +118,6 @@ SLOT_INTERFACE_START( sms_control_port_devices )
|
||||
SLOT_INTERFACE("lphaser", SMS_LIGHT_PHASER)
|
||||
SLOT_INTERFACE("paddle", SMS_PADDLE)
|
||||
SLOT_INTERFACE("sportspad", SMS_SPORTS_PAD)
|
||||
SLOT_INTERFACE("sportspadjp", SMS_SPORTS_PAD_JP)
|
||||
SLOT_INTERFACE("rapidfire", SMS_RAPID_FIRE)
|
||||
SLOT_INTERFACE_END
|
||||
|
@ -118,6 +118,7 @@ extern const device_type SMS_CONTROL_PORT;
|
||||
#include "machine/sms_lphaser.h"
|
||||
#include "machine/sms_paddle.h"
|
||||
#include "machine/sms_sports.h"
|
||||
#include "machine/sms_sportsjp.h"
|
||||
#include "machine/sms_rfu.h"
|
||||
|
||||
SLOT_INTERFACE_EXTERN( sms_control_port_devices );
|
||||
|
@ -1793,6 +1793,7 @@ $(MESSOBJ)/sega.a: \
|
||||
$(MESS_MACHINE)/sms_lphaser.o \
|
||||
$(MESS_MACHINE)/sms_paddle.o \
|
||||
$(MESS_MACHINE)/sms_sports.o \
|
||||
$(MESS_MACHINE)/sms_sportsjp.o \
|
||||
$(MESS_MACHINE)/sms_rfu.o \
|
||||
$(MESS_MACHINE)/sega8_slot.o \
|
||||
$(MESS_MACHINE)/sega8_rom.o \
|
||||
|
Loading…
Reference in New Issue
Block a user