This one documents what I think is a real bug of the Japanese game Sports Pad Soccer: part of the player 2 input is read from player 1 input instead. The patch also reorganizes code of the Japanese Sports Pad controller device and replace some PORT_CUSTOM/PORT_CHANGED callbacks with PORT_READ_LINE/PORT_WRITE_LINE. [Enik]

This commit is contained in:
Miodrag Milanovic 2016-04-06 07:49:49 +02:00
parent 865253ccb0
commit 33c5196a42
10 changed files with 85 additions and 74 deletions

View File

@ -6128,6 +6128,7 @@
</part> </part>
</software> </software>
<!-- Notes: This has a player 2 input bug: it reads part of player 1 data instead (see sportsjp.cpp) -->
<software name="sportssc" cloneof="worldsoc"> <software name="sportssc" cloneof="worldsoc">
<description>Sports Pad Soccer (Jpn)</description> <description>Sports Pad Soccer (Jpn)</description>
<year>1988</year> <year>1988</year>

View File

@ -12,6 +12,13 @@ Release data from the Sega Retro project:
Year: 1989 Country/region: BR Model code: 010470 Year: 1989 Country/region: BR Model code: 010470
Year: 198? Country/region: KR Model code: ? Year: 198? Country/region: KR Model code: ?
Notes:
The Light Phaser gun doesn't work with the Japanese SMS and Sega Mark III.
There are reports about Light Phaser working on the second Korean SMS
version, and a Korean advert shows support on the first version (Gam*Boy I,
although based on Japanese SMS).
**********************************************************************/ **********************************************************************/
#include "lphaser.h" #include "lphaser.h"
@ -29,7 +36,7 @@ const device_type SMS_LIGHT_PHASER = &device_creator<sms_light_phaser_device>;
#define LGUN_X_INTERVAL 4 #define LGUN_X_INTERVAL 4
CUSTOM_INPUT_MEMBER( sms_light_phaser_device::th_pin_r ) READ_LINE_MEMBER( sms_light_phaser_device::th_pin_r )
{ {
// The returned value is inverted due to IP_ACTIVE_LOW mapping. // The returned value is inverted due to IP_ACTIVE_LOW mapping.
return ~m_sensor_last_state; return ~m_sensor_last_state;
@ -46,7 +53,7 @@ INPUT_CHANGED_MEMBER( sms_light_phaser_device::position_changed )
static INPUT_PORTS_START( sms_light_phaser ) static INPUT_PORTS_START( sms_light_phaser )
PORT_START("CTRL_PORT") PORT_START("CTRL_PORT")
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 ) // TL (trigger) PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 ) // TL (trigger)
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_SPECIAL ) PORT_CUSTOM_MEMBER(DEVICE_SELF, sms_light_phaser_device, th_pin_r, nullptr) PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_SPECIAL ) PORT_READ_LINE_DEVICE_MEMBER(DEVICE_SELF, sms_light_phaser_device, th_pin_r)
PORT_BIT( 0x9f, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_BIT( 0x9f, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_START("LPHASER_X") PORT_START("LPHASER_X")

View File

@ -34,7 +34,7 @@ public:
// optional information overrides // optional information overrides
virtual ioport_constructor device_input_ports() const override; virtual ioport_constructor device_input_ports() const override;
DECLARE_CUSTOM_INPUT_MEMBER( th_pin_r ); DECLARE_READ_LINE_MEMBER( th_pin_r );
DECLARE_INPUT_CHANGED_MEMBER( position_changed ); DECLARE_INPUT_CHANGED_MEMBER( position_changed );
protected: protected:

View File

@ -38,7 +38,7 @@ const device_type SMS_PADDLE = &device_creator<sms_paddle_device>;
#define PADDLE_INTERVAL attotime::from_hz(XTAL_53_693175MHz/15/100) #define PADDLE_INTERVAL attotime::from_hz(XTAL_53_693175MHz/15/100)
CUSTOM_INPUT_MEMBER( sms_paddle_device::dir_pins_r ) CUSTOM_INPUT_MEMBER( sms_paddle_device::rldu_pins_r )
{ {
UINT8 data = m_paddle_x->read(); UINT8 data = m_paddle_x->read();
@ -50,7 +50,7 @@ CUSTOM_INPUT_MEMBER( sms_paddle_device::dir_pins_r )
} }
CUSTOM_INPUT_MEMBER( sms_paddle_device::tr_pin_r ) READ_LINE_MEMBER( sms_paddle_device::tr_pin_r )
{ {
// The returned value is inverted due to IP_ACTIVE_LOW mapping. // The returned value is inverted due to IP_ACTIVE_LOW mapping.
return ~m_read_state; return ~m_read_state;
@ -59,11 +59,11 @@ CUSTOM_INPUT_MEMBER( sms_paddle_device::tr_pin_r )
static INPUT_PORTS_START( sms_paddle ) static INPUT_PORTS_START( sms_paddle )
PORT_START("CTRL_PORT") PORT_START("CTRL_PORT")
PORT_BIT( 0x0f, IP_ACTIVE_LOW, IPT_SPECIAL ) PORT_CUSTOM_MEMBER(DEVICE_SELF, sms_paddle_device, dir_pins_r, nullptr) // Directional pins PORT_BIT( 0x0f, IP_ACTIVE_LOW, IPT_SPECIAL ) PORT_CUSTOM_MEMBER(DEVICE_SELF, sms_paddle_device, rldu_pins_r, nullptr) // R,L,D,U
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) // Vcc PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) // Vcc
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 ) // TL PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 ) // TL
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED ) // TH PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED ) // TH
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_SPECIAL ) PORT_CUSTOM_MEMBER(DEVICE_SELF, sms_paddle_device, tr_pin_r, nullptr) PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_SPECIAL ) PORT_READ_LINE_DEVICE_MEMBER( DEVICE_SELF, sms_paddle_device, tr_pin_r ) // TR
PORT_START("PADDLE_X") // Paddle knob PORT_START("PADDLE_X") // Paddle knob
PORT_BIT( 0xff, 0x80, IPT_PADDLE) PORT_SENSITIVITY(40) PORT_KEYDELTA(20) PORT_CENTERDELTA(0) PORT_MINMAX(0,255) PORT_BIT( 0xff, 0x80, IPT_PADDLE) PORT_SENSITIVITY(40) PORT_KEYDELTA(20) PORT_CENTERDELTA(0) PORT_MINMAX(0,255)

View File

@ -33,8 +33,8 @@ public:
// optional information overrides // optional information overrides
virtual ioport_constructor device_input_ports() const override; virtual ioport_constructor device_input_ports() const override;
DECLARE_CUSTOM_INPUT_MEMBER( dir_pins_r ); DECLARE_CUSTOM_INPUT_MEMBER( rldu_pins_r ); // Right, Left, Down and Up lines.
DECLARE_CUSTOM_INPUT_MEMBER( tr_pin_r ); DECLARE_READ_LINE_MEMBER( tr_pin_r );
protected: protected:
// device-level overrides // device-level overrides

View File

@ -82,21 +82,21 @@ void sms_sports_pad_device::device_timer(emu_timer &timer, device_timer_id id, i
} }
CUSTOM_INPUT_MEMBER( sms_sports_pad_device::th_pin_r ) READ_LINE_MEMBER( sms_sports_pad_device::th_pin_r )
{ {
return m_last_data; return m_th_pin_state;
} }
INPUT_CHANGED_MEMBER( sms_sports_pad_device::th_pin_w ) WRITE_LINE_MEMBER( sms_sports_pad_device::th_pin_w )
{ {
m_read_state = (m_read_state + 1) & 3; m_read_state = (m_read_state + 1) & 3;
m_sportspad_timer->adjust(m_interval); m_sportspad_timer->adjust(m_interval);
m_last_data = newval; m_th_pin_state = state;
} }
CUSTOM_INPUT_MEMBER( sms_sports_pad_device::dir_pins_r ) CUSTOM_INPUT_MEMBER( sms_sports_pad_device::rldu_pins_r )
{ {
UINT8 data = 0; UINT8 data = 0;
@ -123,17 +123,17 @@ CUSTOM_INPUT_MEMBER( sms_sports_pad_device::dir_pins_r )
static INPUT_PORTS_START( sms_sports_pad ) static INPUT_PORTS_START( sms_sports_pad )
PORT_START("SPORTS_IN") PORT_START("SPORTS_IN")
PORT_BIT( 0x0f, IP_ACTIVE_LOW, IPT_SPECIAL ) PORT_CUSTOM_MEMBER(DEVICE_SELF, sms_sports_pad_device, dir_pins_r, nullptr) // Directional pins PORT_BIT( 0x0f, IP_ACTIVE_LOW, IPT_SPECIAL ) PORT_CUSTOM_MEMBER(DEVICE_SELF, sms_sports_pad_device, rldu_pins_r, nullptr) // R,L,D,U
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) // Vcc PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) // Vcc
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 ) // TL (Button 1) PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 ) // TL (Button 1)
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_SPECIAL ) PORT_CUSTOM_MEMBER(DEVICE_SELF, sms_sports_pad_device, th_pin_r, nullptr) PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_SPECIAL ) PORT_READ_LINE_DEVICE_MEMBER(DEVICE_SELF, sms_sports_pad_device, th_pin_r) // TH
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON2 ) // TR (Button 2) PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON2 ) // TR (Button 2)
PORT_START("SPORTS_OUT") PORT_START("SPORTS_OUT")
PORT_BIT( 0x0f, IP_ACTIVE_LOW, IPT_UNUSED ) // Directional pins PORT_BIT( 0x0f, IP_ACTIVE_LOW, IPT_UNUSED ) // Directional pins
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) // Vcc PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) // Vcc
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED ) // TL (Button 1) PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED ) // TL (Button 1)
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_OUTPUT ) PORT_CHANGED_MEMBER(DEVICE_SELF, sms_sports_pad_device, th_pin_w, nullptr) PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_OUTPUT ) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, sms_sports_pad_device, th_pin_w) // TH
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) // TR (Button 2) PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) // TR (Button 2)
PORT_START("SPORTS_X") /* Sports Pad X axis */ PORT_START("SPORTS_X") /* Sports Pad X axis */
@ -171,7 +171,7 @@ sms_sports_pad_device::sms_sports_pad_device(const machine_config &mconfig, cons
m_sports_x(*this, "SPORTS_X"), m_sports_x(*this, "SPORTS_X"),
m_sports_y(*this, "SPORTS_Y"), m_sports_y(*this, "SPORTS_Y"),
m_read_state(0), m_read_state(0),
m_last_data(0), m_th_pin_state(0),
m_x_axis_reset_value(0x80), // value 0x80 helps when start playing paddle games. m_x_axis_reset_value(0x80), // value 0x80 helps when start playing paddle games.
m_y_axis_reset_value(0x80), m_y_axis_reset_value(0x80),
m_interval(SPORTS_PAD_INTERVAL), m_sportspad_timer(nullptr) m_interval(SPORTS_PAD_INTERVAL), m_sportspad_timer(nullptr)
@ -188,7 +188,7 @@ void sms_sports_pad_device::device_start()
m_sportspad_timer = timer_alloc(TIMER_SPORTSPAD); m_sportspad_timer = timer_alloc(TIMER_SPORTSPAD);
save_item(NAME(m_read_state)); save_item(NAME(m_read_state));
save_item(NAME(m_last_data)); save_item(NAME(m_th_pin_state));
save_item(NAME(m_x_axis_reset_value)); save_item(NAME(m_x_axis_reset_value));
save_item(NAME(m_y_axis_reset_value)); save_item(NAME(m_y_axis_reset_value));
} }

View File

@ -33,9 +33,9 @@ public:
// optional information overrides // optional information overrides
virtual ioport_constructor device_input_ports() const override; virtual ioport_constructor device_input_ports() const override;
DECLARE_CUSTOM_INPUT_MEMBER( dir_pins_r ); DECLARE_CUSTOM_INPUT_MEMBER( rldu_pins_r ); // Right, Left, Down and Up lines.
DECLARE_CUSTOM_INPUT_MEMBER( th_pin_r ); DECLARE_READ_LINE_MEMBER( th_pin_r );
DECLARE_INPUT_CHANGED_MEMBER( th_pin_w ); DECLARE_WRITE_LINE_MEMBER( th_pin_w );
protected: protected:
// device-level overrides // device-level overrides
@ -52,7 +52,7 @@ private:
required_ioport m_sports_y; required_ioport m_sports_y;
UINT8 m_read_state; UINT8 m_read_state;
UINT8 m_last_data; UINT8 m_th_pin_state;
UINT8 m_x_axis_reset_value; UINT8 m_x_axis_reset_value;
UINT8 m_y_axis_reset_value; UINT8 m_y_axis_reset_value;
const attotime m_interval; const attotime m_interval;

View File

@ -22,6 +22,13 @@ Notes:
used by the US model, due to the missing TH line on Sega Mark III used by the US model, due to the missing TH line on Sega Mark III
controller ports. controller ports.
A bug was discovered in the player 2 input handling code of the only known
good ROM dump of Sports Pad Soccer (JP):
size="131072" crc="41c948bf" sha1="7634ce39e87049dad1ee4f32a80d728e4bd1f81f"
At address $12D1, instead read the upper 2 bits of port $DC and lower 2 bits
of port $DD (to obtain the lower nibble of the current axis for player 2),
the code wrongly reads the lower nibble of port $DC, that is player 1 data.
**********************************************************************/ **********************************************************************/
#include "sportsjp.h" #include "sportsjp.h"
@ -39,38 +46,24 @@ const device_type SMS_SPORTS_PAD_JP = &device_creator<sms_sports_pad_jp_device>;
DECLARE_CUSTOM_INPUT_MEMBER( sms_sports_pad_jp_device::dir_pins_r ) // The returned value is inverted due to IP_ACTIVE_LOW mapping.
{ READ_LINE_MEMBER( sms_sports_pad_jp_device::tl_pin_r ) { return ~m_tl_pin_state; }
UINT8 data = 0; READ_LINE_MEMBER( sms_sports_pad_jp_device::tr_pin_r ) { return ~m_tr_pin_state; }
CUSTOM_INPUT_MEMBER( sms_sports_pad_jp_device::rldu_pins_r ) { return ~(m_rldu_pins_state & 0x0f); }
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 ) static INPUT_PORTS_START( sms_sports_pad_jp )
PORT_START("SPORTS_JP_IN") 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, nullptr) // Directional pins PORT_BIT( 0x0f, IP_ACTIVE_LOW, IPT_SPECIAL ) PORT_CUSTOM_MEMBER(DEVICE_SELF, sms_sports_pad_jp_device, rldu_pins_r, nullptr) // R,L,D,U
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) // Vcc PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) // Vcc
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 ) // TL (Button 1) PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_SPECIAL ) PORT_READ_LINE_DEVICE_MEMBER( DEVICE_SELF, sms_sports_pad_jp_device, tl_pin_r ) // TL
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED ) // TH PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED ) // TH
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON2 ) // TR (Button 2) PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_SPECIAL ) PORT_READ_LINE_DEVICE_MEMBER( DEVICE_SELF, sms_sports_pad_jp_device, tr_pin_r ) // TR
PORT_START("SPORTS_JP_BT") /* Sports Pad buttons nibble */
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON2 )
PORT_BIT( 0x0c, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_START("SPORTS_JP_X") /* Sports Pad X axis */ PORT_START("SPORTS_JP_X") /* Sports Pad X axis */
PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_X ) PORT_SENSITIVITY(50) PORT_KEYDELTA(40) PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_X ) PORT_SENSITIVITY(50) PORT_KEYDELTA(40)
@ -103,9 +96,12 @@ sms_sports_pad_jp_device::sms_sports_pad_jp_device(const machine_config &mconfig
device_t(mconfig, SMS_SPORTS_PAD_JP, "Sega SMS Sports Pad JP", tag, owner, clock, "sms_sports_pad_jp", __FILE__), device_t(mconfig, SMS_SPORTS_PAD_JP, "Sega SMS Sports Pad JP", tag, owner, clock, "sms_sports_pad_jp", __FILE__),
device_sms_control_port_interface(mconfig, *this), device_sms_control_port_interface(mconfig, *this),
m_sports_jp_in(*this, "SPORTS_JP_IN"), m_sports_jp_in(*this, "SPORTS_JP_IN"),
m_sports_jp_bt(*this, "SPORTS_JP_BT"),
m_sports_jp_x(*this, "SPORTS_JP_X"), m_sports_jp_x(*this, "SPORTS_JP_X"),
m_sports_jp_y(*this, "SPORTS_JP_Y"), m_sports_jp_y(*this, "SPORTS_JP_Y"),
m_read_state(0), m_rldu_pins_state(0x0f),
m_tl_pin_state(1),
m_tr_pin_state(1),
m_interval(SPORTS_PAD_JP_INTERVAL) m_interval(SPORTS_PAD_JP_INTERVAL)
{ {
} }
@ -120,7 +116,9 @@ void sms_sports_pad_jp_device::device_start()
m_start_time = machine().time(); m_start_time = machine().time();
save_item(NAME(m_start_time)); save_item(NAME(m_start_time));
save_item(NAME(m_read_state)); save_item(NAME(m_rldu_pins_state));
save_item(NAME(m_tl_pin_state));
save_item(NAME(m_tr_pin_state));
} }
@ -130,41 +128,41 @@ void sms_sports_pad_jp_device::device_start()
UINT8 sms_sports_pad_jp_device::peripheral_r() UINT8 sms_sports_pad_jp_device::peripheral_r()
{ {
UINT8 data;
int num_intervals = (machine().time() - m_start_time).as_double() / m_interval.as_double(); 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 (num_intervals % 5)
switch (m_read_state)
{ {
case 0: case 0:
// X high nibble // X high nibble
data &= ~0x20; // TL 0 m_rldu_pins_state = m_sports_jp_x->read() >> 4;
data &= ~0x80; // TR 0 m_tl_pin_state = 0;
m_tr_pin_state = 0;
break; break;
case 1: case 1:
// X low nibble // X low nibble
data |= 0x20; // TL 1 m_rldu_pins_state = m_sports_jp_x->read();
data &= ~0x80; // TR 0 m_tl_pin_state = 1;
m_tr_pin_state = 0;
break; break;
case 2: case 2:
// Y high nibble // Y high nibble
data &= ~0x20; // TL 0 m_rldu_pins_state = m_sports_jp_y->read() >> 4;
data &= ~0x80; // TR 0 m_tl_pin_state = 0;
m_tr_pin_state = 0;
break; break;
case 3: case 3:
// Y low nibble // Y low nibble
data |= 0x20; // TL 1 m_rldu_pins_state = m_sports_jp_y->read();
data &= ~0x80; // TR 0 m_tl_pin_state = 1;
m_tr_pin_state = 0;
break; break;
case 4: case 4:
// buttons 1 and 2 // buttons 1 and 2
data = (data & 0x20) >> 5 | (data & 0x80) >> 6 | 0xfc; m_rldu_pins_state = m_sports_jp_bt->read();
data |= 0x20; // TL 1 m_tl_pin_state = 1;
data |= 0x80; // TR 1 m_tr_pin_state = 1;
break; break;
} }
return data; return m_sports_jp_in->read();
} }

View File

@ -33,7 +33,9 @@ public:
// optional information overrides // optional information overrides
virtual ioport_constructor device_input_ports() const override; virtual ioport_constructor device_input_ports() const override;
CUSTOM_INPUT_MEMBER( dir_pins_r ); DECLARE_CUSTOM_INPUT_MEMBER( rldu_pins_r ); // Right, Left, Down and Up lines.
DECLARE_READ_LINE_MEMBER( tl_pin_r );
DECLARE_READ_LINE_MEMBER( tr_pin_r );
protected: protected:
// device-level overrides // device-level overrides
@ -44,10 +46,13 @@ protected:
private: private:
required_ioport m_sports_jp_in; required_ioport m_sports_jp_in;
required_ioport m_sports_jp_bt;
required_ioport m_sports_jp_x; required_ioport m_sports_jp_x;
required_ioport m_sports_jp_y; required_ioport m_sports_jp_y;
UINT8 m_read_state; UINT8 m_rldu_pins_state;
UINT8 m_tl_pin_state;
UINT8 m_tr_pin_state;
attotime m_start_time; attotime m_start_time;
const attotime m_interval; const attotime m_interval;
}; };

View File

@ -60,7 +60,7 @@ General compatibility issues on real hardware (not emulation bugs):
Paddle controller; Paddle controller;
- Few games of the ones with FM support need to detect the system region as - Few games of the ones with FM support need to detect the system region as
Japanese to play FM sound; Japanese to play FM sound;
- The Light Phaser gun doesn't work with the Japanese SMS; - The Light Phaser gun doesn't work with the Japanese SMS and Sega Mark III;
- There are reports about Light Phaser working on the second Korean SMS - There are reports about Light Phaser working on the second Korean SMS
version, and a Korean advert shows support on the first version (Gam*Boy I, version, and a Korean advert shows support on the first version (Gam*Boy I,
although based on Japanese SMS); although based on Japanese SMS);
@ -337,10 +337,10 @@ ADDRESS_MAP_END
// The first Korean SMS version also seems to lack I/O port $3F. Games execute // The first Korean SMS version also seems to lack I/O port $3F. Games execute
// a region detection procedure that, through that port, sets the mode used by // a region detection procedure that, through that port, sets the mode used by
// the TH bits of port $DD and tests their behavior. The region of the first SMS // the TH bits of port $DD and tests their behaviour. The region of the first SMS
// version is detected as Japanese (opposite to the second version). However, // version is detected as Japanese (opposite to the second version). However,
// as it supports Light Phaser games, it doesn't have the same behavior of the // as it supports Light Phaser games, it doesn't have the same behaviour of the
// Japanese SMS. If it had the behavior of other SMS versions, the system // Japanese SMS. If it had the behaviour of other SMS versions, the system
// region would be detected as Export, so it probably lacks the port. // region would be detected as Export, so it probably lacks the port.
static ADDRESS_MAP_START( sms1kr_io, AS_IO, 8, sms_state ) static ADDRESS_MAP_START( sms1kr_io, AS_IO, 8, sms_state )
AM_IMPORT_FROM(sg1000m3_io) AM_IMPORT_FROM(sg1000m3_io)