diff options
Diffstat (limited to 'src/devices/bus/sms_ctrl/paddle.cpp')
-rw-r--r-- | src/devices/bus/sms_ctrl/paddle.cpp | 149 |
1 files changed, 63 insertions, 86 deletions
diff --git a/src/devices/bus/sms_ctrl/paddle.cpp b/src/devices/bus/sms_ctrl/paddle.cpp index 06f1c9bfa16..04ce2d749ca 100644 --- a/src/devices/bus/sms_ctrl/paddle.cpp +++ b/src/devices/bus/sms_ctrl/paddle.cpp @@ -1,25 +1,36 @@ // license:BSD-3-Clause -// copyright-holders:Fabio Priuli +// copyright-holders:Vas Crabb /********************************************************************** Sega Mark III "Paddle Control" emulation -Release data from the Sega Retro project: + Release data from the Sega Retro project: - Year: 1987 Country/region: JP Model code: HPD-200 + Year: 1987 Country/region: JP Model code: HPD-200 -Notes: + Notes: - The main chip contained in the device is labeled 315-5243. + The main chip contained in the device is labeled 315-5243. - The Paddle Control was only released in Japan. To work with the device, - paddle games need to detect the system region as Japanese, else they switch - to a different mode that uses the TH line as output to select which nibble - of the X axis will be read. This other mode is similar to how the US Sports - Pad works, so on an Export system, paddle games are somewhat playable with - that device, though it needs to be used inverted and the trackball needs to - be moved slowly, else the software for the paddle think it's moving backward. + On Japanese systems (Mark III and Master System), the games + read the port and expect the value on the low four bits + (usually used joystick switches) to alternate between the low + and high nybbles of the paddle position, with TR indicating + the current state. + + On export consoles, the games toggle the TH output before + reading a nybble, expecting to be able to select the high or + low nybble of the paddle position. It spins for longer between + pulling TH low and reading the low nybble than it does between + pulling TH high and reading the high nybble, suggesting that + pulling TH low triggers acquisition. + + Only a single model of paddle controller was released for the + Japanese market. Photos show no connection to pin 7. There + are a few reports of paddle controllers working on export + consoles, but this is not possible unless another hardware + revision exists. **********************************************************************/ @@ -27,101 +38,67 @@ Notes: #include "paddle.h" +namespace { -//************************************************************************** -// DEVICE DEFINITIONS -//************************************************************************** - -DEFINE_DEVICE_TYPE(SMS_PADDLE, sms_paddle_device, "sms_paddle", "Sega SMS Paddle") - -// time interval not verified -// Player 2 of Galactic Protector is the most sensible to this timming. -#define PADDLE_INTERVAL attotime::from_hz(XTAL(10'738'635)/3/100) - +INPUT_PORTS_START( sms_paddle ) + PORT_START("BUTTON") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 ) -CUSTOM_INPUT_MEMBER( sms_paddle_device::rldu_pins_r ) -{ - uint8_t data = m_paddle_x->read(); + PORT_START("PADDLE") + PORT_BIT( 0xff, 0x80, IPT_PADDLE) PORT_MINMAX(0, 255) PORT_SENSITIVITY(40) PORT_KEYDELTA(20) PORT_CENTERDELTA(0) +INPUT_PORTS_END - if (m_read_state) - data >>= 4; - // The returned value is inverted due to IP_ACTIVE_LOW mapping. - return ~data; -} +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** -READ_LINE_MEMBER( sms_paddle_device::tr_pin_r ) +class sms_paddle_device : public device_t, public device_sms_control_interface { - // The returned value is inverted due to IP_ACTIVE_LOW mapping. - return ~m_read_state; -} - - -static INPUT_PORTS_START( sms_paddle ) - PORT_START("CTRL_PORT") - PORT_BIT( 0x0f, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_CUSTOM_MEMBER(sms_paddle_device, rldu_pins_r) // R,L,D,U - PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) // Vcc - PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 ) // TL - PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED ) // TH - PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_READ_LINE_MEMBER(sms_paddle_device, tr_pin_r) // TR +public: + // construction/destruction + sms_paddle_device(const machine_config &mconfig, char const *tag, device_t *owner, u32 clock); - 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) -INPUT_PORTS_END - - -//------------------------------------------------- -// input_ports - device-specific input ports -//------------------------------------------------- - -ioport_constructor sms_paddle_device::device_input_ports() const -{ - return INPUT_PORTS_NAME( sms_paddle ); -} + // device_sms_control_interface implementation + virtual u8 in_r() override; +protected: + // device_t implementation + virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(sms_paddle); } + virtual void device_start() override { } +private: + TIMER_CALLBACK_MEMBER(timeout); -//************************************************************************** -// LIVE DEVICE -//************************************************************************** + required_ioport m_button; + required_ioport m_axis; +}; -//------------------------------------------------- -// sms_paddle_device - constructor -//------------------------------------------------- -sms_paddle_device::sms_paddle_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : +sms_paddle_device::sms_paddle_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) : device_t(mconfig, SMS_PADDLE, tag, owner, clock), - device_sms_control_port_interface(mconfig, *this), - m_paddle_pins(*this, "CTRL_PORT"), - m_paddle_x(*this, "PADDLE_X"), - m_read_state(0), - m_interval(PADDLE_INTERVAL) + device_sms_control_interface(mconfig, *this), + m_button(*this, "BUTTON"), + m_axis(*this, "PADDLE") { } -//------------------------------------------------- -// device_start - device-specific startup -//------------------------------------------------- - -void sms_paddle_device::device_start() +u8 sms_paddle_device::in_r() { - m_start_time = machine().time(); - - save_item(NAME(m_start_time)); - save_item(NAME(m_read_state)); + // time interval guessed + // Player 2 of Galactic Protector is the most sensitive to this timing + uint8_t const nybble = machine().time().as_ticks(XTAL(10'738'635) / 3 / 100) & 1; + return (nybble << 5) | (m_button->read() << 4) | BIT(m_axis->read(), nybble ? 4 : 0, 4); } +} // anonymous namespace -//------------------------------------------------- -// sms_peripheral_r - paddle read -//------------------------------------------------- -uint8_t sms_paddle_device::peripheral_r() -{ - 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(); -} +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +DEFINE_DEVICE_TYPE_PRIVATE(SMS_PADDLE, device_sms_control_interface, sms_paddle_device, "sms_paddle", "Sega Mark III Paddle (Japan)") |