// license:BSD-3-Clause // copyright-holders:Fabio Priuli /********************************************************************** Sega Mark III "Paddle Control" emulation Release data from the Sega Retro project: Year: 1987 Country/region: JP Model code: HPD-200 Notes: 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. **********************************************************************/ #include "emu.h" #include "paddle.h" //************************************************************************** // 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) CUSTOM_INPUT_MEMBER( sms_paddle_device::rldu_pins_r ) { uint8_t data = m_paddle_x->read(); if (m_read_state) data >>= 4; // The returned value is inverted due to IP_ACTIVE_LOW mapping. return ~data; } READ_LINE_MEMBER( sms_paddle_device::tr_pin_r ) { // 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(DEVICE_SELF, sms_paddle_device, rldu_pins_r, nullptr) // 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_DEVICE_MEMBER( DEVICE_SELF, sms_paddle_device, tr_pin_r ) // TR 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 ); } //************************************************************************** // LIVE DEVICE //************************************************************************** //------------------------------------------------- // sms_paddle_device - constructor //------------------------------------------------- sms_paddle_device::sms_paddle_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t 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_start - device-specific startup //------------------------------------------------- void sms_paddle_device::device_start() { m_start_time = machine().time(); save_item(NAME(m_start_time)); save_item(NAME(m_read_state)); } //------------------------------------------------- // 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(); }