diff options
Diffstat (limited to 'src/devices/bus/sms_ctrl/rfu.cpp')
-rw-r--r-- | src/devices/bus/sms_ctrl/rfu.cpp | 164 |
1 files changed, 96 insertions, 68 deletions
diff --git a/src/devices/bus/sms_ctrl/rfu.cpp b/src/devices/bus/sms_ctrl/rfu.cpp index d28a2ded703..13462c43f3c 100644 --- a/src/devices/bus/sms_ctrl/rfu.cpp +++ b/src/devices/bus/sms_ctrl/rfu.cpp @@ -14,76 +14,98 @@ Release data from the Sega Retro project: Notes: - This emulated device is the version released by Sega. In Brazil, Tec Toy - released a version that does not have any switch to turn on/off auto-repeat. + This emulated device is the version released by Sega. In Brazil, + Tec Toy released a version that does not have any switch to turn + on/off auto-repeat. + + Uses a separate oscillator consisting of a 27k resistor, a 1u + capacitor, and two NOR gates from a 74HCTLS02 for each button. In + reality, the two oscillators will run at slightly different speeds + and drift away from each other, so the buttons won't be + synchronised. + + The rapid fire oscillators should start when the button is pressed, + but this would require pushing TL and TR state from the controller + to the port. **********************************************************************/ #include "emu.h" #include "rfu.h" +#include "controllers.h" + +namespace { //************************************************************************** -// DEVICE DEFINITIONS +// TYPE DEFINITIONS //************************************************************************** -DEFINE_DEVICE_TYPE(SMS_RAPID_FIRE, sms_rapid_fire_device, "sms_rapid_fire", "Sega SMS Rapid Fire Unit") - -// time interval not verified -#define RAPID_FIRE_INTERVAL attotime::from_hz(10) - - -static INPUT_PORTS_START( sms_rapid_fire ) - PORT_START("rfu_sw") // Rapid Fire Unit switches - PORT_CONFNAME( 0x03, 0x00, "Rapid Fire Unit" ) - PORT_CONFSETTING( 0x00, DEF_STR( Off ) ) - PORT_CONFSETTING( 0x01, "Button 1" ) - PORT_CONFSETTING( 0x02, "Button 2" ) - PORT_CONFSETTING( 0x03, "Button 1 + 2" ) +class sms_rapid_fire_device : public device_t, public device_sms_control_interface +{ +public: + // construction/destruction + sms_rapid_fire_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + // device_sms_control_interface implementation + virtual uint8_t in_r() override; + virtual void out_w(uint8_t data, uint8_t mem_mask) override; + + void rapid_changed(int state); + +protected: + // device_t implementation + virtual void device_add_mconfig(machine_config &config) override ATTR_COLD; + virtual ioport_constructor device_input_ports() const override ATTR_COLD; + virtual void device_config_complete() override; + virtual void device_start() override ATTR_COLD; + virtual void device_reset() override ATTR_COLD; + +private: + required_device<sms_control_port_device> m_subctrl_port; + required_ioport m_rfire_sw; + + uint8_t m_in; + uint8_t m_drive; + uint8_t m_rapid; +}; + + +INPUT_PORTS_START( sms_rapid_fire ) + PORT_START("rfu_sw") + PORT_BIT( 0x00, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_TOGGLE PORT_NAME("Rapid Fire 1") PORT_WRITE_LINE_MEMBER(FUNC(sms_rapid_fire_device::rapid_changed)) + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_TOGGLE PORT_NAME("Rapid Fire 2") PORT_WRITE_LINE_MEMBER(FUNC(sms_rapid_fire_device::rapid_changed)) INPUT_PORTS_END -//------------------------------------------------- -// input_ports - device-specific input ports -//------------------------------------------------- - ioport_constructor sms_rapid_fire_device::device_input_ports() const { - return INPUT_PORTS_NAME( sms_rapid_fire ); + return INPUT_PORTS_NAME(sms_rapid_fire); } - -//************************************************************************** -// LIVE DEVICE -//************************************************************************** - //------------------------------------------------- // sms_rapid_fire_device - constructor //------------------------------------------------- sms_rapid_fire_device::sms_rapid_fire_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, SMS_RAPID_FIRE, tag, owner, clock), - device_sms_control_port_interface(mconfig, *this), - m_rfire_sw(*this, "rfu_sw"), + device_sms_control_interface(mconfig, *this), m_subctrl_port(*this, "ctrl"), - m_read_state(0), - m_interval(RAPID_FIRE_INTERVAL) + m_rfire_sw(*this, "rfu_sw"), + m_in(0x03), + m_drive(0x00), + m_rapid(0x00) { } -//------------------------------------------------- -// device_start - device-specific startup -//------------------------------------------------- - -void sms_rapid_fire_device::device_start() +void sms_rapid_fire_device::rapid_changed(int state) { - m_start_time = machine().time(); - - save_item(NAME(m_start_time)); - save_item(NAME(m_read_state)); + m_rapid = m_rfire_sw->read(); + m_subctrl_port->out_w(m_in | m_rapid, m_drive & ~m_rapid); } @@ -91,51 +113,57 @@ void sms_rapid_fire_device::device_start() // sms_peripheral_r - rapid fire read //------------------------------------------------- -uint8_t sms_rapid_fire_device::peripheral_r() +uint8_t sms_rapid_fire_device::in_r() { - uint8_t data; + uint8_t const read_state = machine().time().as_ticks(10) & 1; // time interval not verified - int num_intervals = (machine().time() - m_start_time).as_double() / m_interval.as_double(); - m_read_state = num_intervals & 1; + return m_subctrl_port->in_r() | (read_state ? m_rfire_sw->read() : 0U); +} - data = m_subctrl_port->port_r(); - /* Check Rapid Fire switch for Button 1 (TL) */ - if (!(data & 0x20) && (m_rfire_sw->read() & 0x01)) - data |= m_read_state << 5; +void sms_rapid_fire_device::out_w(uint8_t data, uint8_t mem_mask) +{ + // TR pulled up via a 4k7 resistor, connected directly to console pin when rapid fire disabled + m_subctrl_port->out_w(data | m_rapid, mem_mask & ~m_rapid); + m_in = data; + m_drive = mem_mask; +} - /* Check Rapid Fire switch for Button 2 (TR) */ - if (!(data & 0x80) && (m_rfire_sw->read() & 0x02)) - data |= m_read_state << 7; - return data; +void sms_rapid_fire_device::device_add_mconfig(machine_config &config) +{ + SMS_CONTROL_PORT(config, m_subctrl_port, sms_control_port_devices, SMS_CTRL_OPTION_JOYPAD); + m_subctrl_port->th_handler().set(FUNC(sms_rapid_fire_device::th_w)); } -//------------------------------------------------- -// sms_peripheral_w - rapid fire write -//------------------------------------------------- - -void sms_rapid_fire_device::peripheral_w(uint8_t data) +void sms_rapid_fire_device::device_config_complete() { - m_subctrl_port->port_w(data); + configure_screen( + [this] (auto const &s) + { subdevice<sms_control_port_device>("ctrl")->set_screen(s); }); } -//------------------------------------------------- -// device_add_mconfig - add device configuration -//------------------------------------------------- - -WRITE_LINE_MEMBER( sms_rapid_fire_device::th_pin_w ) +void sms_rapid_fire_device::device_start() { - m_port->th_pin_w(state); + save_item(NAME(m_in)); + save_item(NAME(m_drive)); + save_item(NAME(m_rapid)); } -void sms_rapid_fire_device::device_add_mconfig(machine_config &config) +void sms_rapid_fire_device::device_reset() { - SMS_CONTROL_PORT(config, m_subctrl_port, sms_control_port_devices, "joypad"); - if (m_port != nullptr) - m_subctrl_port->set_screen_tag(m_port->m_screen); - m_subctrl_port->th_input_handler().set(FUNC(sms_rapid_fire_device::th_pin_w)); + m_rapid = m_rfire_sw->read(); } + +} // anonymous namespace + + + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +DEFINE_DEVICE_TYPE_PRIVATE(SMS_RAPID_FIRE, device_sms_control_interface, sms_rapid_fire_device, "sms_rapid_fire", "Sega Master System Rapid Fire Unit") |