mirror of
https://github.com/holub/mame
synced 2025-06-09 06:13:04 +03:00
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:
parent
865253ccb0
commit
33c5196a42
@ -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>
|
||||||
|
@ -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")
|
||||||
|
@ -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:
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user