(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:
Wilbert Pol 2014-01-14 19:44:56 +00:00
parent f3813ffd76
commit faed87bd57
15 changed files with 499 additions and 164 deletions

2
.gitattributes vendored
View File

@ -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

View File

@ -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 )

View File

@ -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);
};

View File

@ -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));

View File

@ -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();
}

View File

@ -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;
};

View File

@ -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;
}

View File

@ -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;
};

View File

@ -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));
}

View File

@ -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;
};

View 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;
}

View 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

View File

@ -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

View File

@ -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 );

View File

@ -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 \