summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/bus/sms_ctrl/rfu.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/bus/sms_ctrl/rfu.cpp')
-rw-r--r--src/devices/bus/sms_ctrl/rfu.cpp164
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")