From c0c92d60b5170dd51c631185ad05d22eb37283ad Mon Sep 17 00:00:00 2001 From: etabeta78 Date: Sat, 31 Jan 2015 10:59:42 +0100 Subject: (MESS) snes: converted input code to use slot devices. This means that you now change the emulated controllers (Joypad, Mouse, Multitap, Super Scope) via the Slot Device menu of the UI interface and not anymore from the System Configurations menu. Also, changing controller now requires to reset the system, so please take some timeto choose the desired controller *before* starting the game, if you want to play a game that uses special controllers. [Fabio Priuli] (MESS) snes: fixed Mouse emulation so that it does not jump back erratically if you keep moving beyond the window border. [Fabio Priuli] (MESS) snes: fixed Multitap Adapter emulation so games properly recognize the device and inputs from all 5 controllers are accepted by the games. [Fabio Priuli] (MESS) snes: added emulation of the Pachinko controller used by a few pachinko games for Super Famicom. [Fabio Priuli] (MESS) snes: added emulation of the Yonezawa Twin Tap controllers, which allow to play with up to 8 players a quiz games for Super Famicom. [Fabio Priuli] (MESS) snes: added emulation of the Epoch Barcode Battler unit (even if only as Super Famicom controller, and not as a standalone unit) which is necessary to play Conveni Wars Barcode Battler Senki for Super Famicom. [Fabio Priuli] --- src/emu/bus/snes_ctrl/bcbattle.c | 213 ++++++++++++++++++++++++++++++++++ src/emu/bus/snes_ctrl/bcbattle.h | 61 ++++++++++ src/emu/bus/snes_ctrl/ctrl.c | 135 ++++++++++++++++++++++ src/emu/bus/snes_ctrl/ctrl.h | 101 ++++++++++++++++ src/emu/bus/snes_ctrl/joypad.c | 127 +++++++++++++++++++++ src/emu/bus/snes_ctrl/joypad.h | 56 +++++++++ src/emu/bus/snes_ctrl/mouse.c | 241 +++++++++++++++++++++++++++++++++++++++ src/emu/bus/snes_ctrl/mouse.h | 64 +++++++++++ src/emu/bus/snes_ctrl/multitap.c | 155 +++++++++++++++++++++++++ src/emu/bus/snes_ctrl/multitap.h | 62 ++++++++++ src/emu/bus/snes_ctrl/pachinko.c | 111 ++++++++++++++++++ src/emu/bus/snes_ctrl/pachinko.h | 57 +++++++++ src/emu/bus/snes_ctrl/sscope.c | 187 ++++++++++++++++++++++++++++++ src/emu/bus/snes_ctrl/sscope.h | 61 ++++++++++ src/emu/bus/snes_ctrl/twintap.c | 114 ++++++++++++++++++ src/emu/bus/snes_ctrl/twintap.h | 56 +++++++++ 16 files changed, 1801 insertions(+) create mode 100644 src/emu/bus/snes_ctrl/bcbattle.c create mode 100644 src/emu/bus/snes_ctrl/bcbattle.h create mode 100644 src/emu/bus/snes_ctrl/ctrl.c create mode 100644 src/emu/bus/snes_ctrl/ctrl.h create mode 100644 src/emu/bus/snes_ctrl/joypad.c create mode 100644 src/emu/bus/snes_ctrl/joypad.h create mode 100644 src/emu/bus/snes_ctrl/mouse.c create mode 100644 src/emu/bus/snes_ctrl/mouse.h create mode 100644 src/emu/bus/snes_ctrl/multitap.c create mode 100644 src/emu/bus/snes_ctrl/multitap.h create mode 100644 src/emu/bus/snes_ctrl/pachinko.c create mode 100644 src/emu/bus/snes_ctrl/pachinko.h create mode 100644 src/emu/bus/snes_ctrl/sscope.c create mode 100644 src/emu/bus/snes_ctrl/sscope.h create mode 100644 src/emu/bus/snes_ctrl/twintap.c create mode 100644 src/emu/bus/snes_ctrl/twintap.h (limited to 'src/emu/bus/snes_ctrl') diff --git a/src/emu/bus/snes_ctrl/bcbattle.c b/src/emu/bus/snes_ctrl/bcbattle.c new file mode 100644 index 00000000000..83682589c71 --- /dev/null +++ b/src/emu/bus/snes_ctrl/bcbattle.c @@ -0,0 +1,213 @@ +/********************************************************************** + + Nintendo Super Famicom - Epoch Barcode Battler + + TODO: this should be actually emulated as a standalone system with + a few 7segments LEDs, once we get a dump of its BIOS + At the moment we only emulated the connection with a Super Famicom + + Copyright MESS Team. + Visit http://mamedev.org for licensing and usage restrictions. + +**********************************************************************/ + +#include "bcbattle.h" + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +const device_type SNES_BARCODE_BATTLER = &device_creator; + + +MACHINE_CONFIG_FRAGMENT( snes_battler ) + MCFG_BARCODE_READER_ADD("battler") +MACHINE_CONFIG_END + +machine_config_constructor snes_bcbattle_device::device_mconfig_additions() const +{ + return MACHINE_CONFIG_NAME( snes_battler ); +} + + +//------------------------------------------------- +// device_timer - handler timer events +//------------------------------------------------- + +// This part is the hacky replacement for the real Barcode unit [shared with NES implementation]: +// code periodically checks whether a new code has been scanned and it moves it to the +// m_current_barcode array +void snes_bcbattle_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + if (id == TIMER_BATTLER) + { + int old = m_new_code; + m_new_code = m_reader->get_pending_code(); + // has something new been scanned? + if (old < m_new_code) + { + if (m_reader->get_byte_length() == 13) + { + for (int i = 0; i < 13; i++) + m_current_barcode[i] = m_reader->read_code() + '0'; + } + else if (m_reader->get_byte_length() == 8) + { + for (int i = 0; i < 5; i++) + m_current_barcode[i] = 0x20; + for (int i = 5; i < 13; i++) + m_current_barcode[i] = m_reader->read_code() + '0'; + } + // read one more, to reset the internal byte counter + m_reader->read_code(); + + // the string "SUNSOFT" is accepted as well by Barcode World + m_current_barcode[13] = 'E'; + m_current_barcode[14] = 'P'; + m_current_barcode[15] = 'O'; + m_current_barcode[16] = 'C'; + m_current_barcode[17] = 'H'; + m_current_barcode[18] = 0x0d; + m_current_barcode[19] = 0x0a; + m_pending_code = 1; + } + } +} + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// snes_bcbattle_device - constructor +//------------------------------------------------- + +snes_bcbattle_device::snes_bcbattle_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : + device_t(mconfig, SNES_BARCODE_BATTLER, "Epoch Barcode Battler (SFC)", tag, owner, clock, "snes_bcbattle", __FILE__), + device_snes_control_port_interface(mconfig, *this), + m_reader(*this, "battler") +{ +} + + +//------------------------------------------------- +// device_start +//------------------------------------------------- + +void snes_bcbattle_device::device_start() +{ + // lacking emulation of the standalone Barcode Battler, we refresh periodically the input from the reader + // proper emulation would have the standalone unit acknowledging that a new barcode has been scanned + // and sending the proper serial bits, instead of our read_current_bit() function! + battler_timer = timer_alloc(TIMER_BATTLER); + battler_timer->adjust(attotime::zero, 0, machine().device("maincpu")->cycles_to_attotime(1000)); + + save_item(NAME(m_current_barcode)); + save_item(NAME(m_new_code)); + save_item(NAME(m_pending_code)); + save_item(NAME(m_transmitting)); + save_item(NAME(m_cur_bit)); + save_item(NAME(m_cur_byte)); +} + + +//------------------------------------------------- +// device_reset +//------------------------------------------------- + +void snes_bcbattle_device::device_reset() +{ + m_pending_code = 0; + m_new_code = 0; + m_transmitting = 0; + m_cur_bit = 0; + m_cur_byte = 0; + memset(m_current_barcode, 0, ARRAY_LENGTH(m_current_barcode)); +} + + +//------------------------------------------------- +// read +//------------------------------------------------- + +int snes_bcbattle_device::read_current_bit() +{ + if (m_pending_code) + { + if (m_cur_bit < 4) + { + int bit = BIT(m_current_barcode[m_cur_byte], m_cur_bit - 1); + m_cur_bit++; + return bit; + } + if (m_cur_bit == 4) // only the low nibble is transmitted (this is the main action of the BBII interface for SNES) + { + m_cur_bit = 0; + //printf("%X ", m_current_barcode[m_cur_byte]); + m_cur_byte++; + if (m_cur_byte == 13) + { + m_cur_byte = 0; + m_pending_code = 0; + } + return 0; + } + } + + return 0; +} + + +//------------------------------------------------- +// poll +//------------------------------------------------- + +void snes_bcbattle_device::port_poll() +{ + m_idx = 0; +} + + +//------------------------------------------------- +// read +//------------------------------------------------- + +UINT8 snes_bcbattle_device::read_pin4() +{ + UINT8 ret = 0; + + if (m_idx >= 80) + ret |= 0x00; + else if (m_idx >= 28) // scan actual barcode + { + ret |= read_current_bit(); // if no code is pending transmission, the function returns 0 + m_idx++; + } + else if (m_idx >= 25) // unknown flags? + m_idx++; + else if (m_idx == 24) // barcode present + { + ret |= m_pending_code; + m_idx++; + } + else if (m_idx >= 12) // controller ID + ret |= BIT(0x7000, m_idx++); + else // first 12 bytes are unknown and probably always 0 + m_idx++; + + return ret; +} + + +//------------------------------------------------- +// write +//------------------------------------------------- + +void snes_bcbattle_device::write_strobe(UINT8 data) +{ + int old = m_strobe; + m_strobe = data & 0x01; + + if (m_strobe < old) // 1 -> 0 transition + port_poll(); +} diff --git a/src/emu/bus/snes_ctrl/bcbattle.h b/src/emu/bus/snes_ctrl/bcbattle.h new file mode 100644 index 00000000000..cf72146ede9 --- /dev/null +++ b/src/emu/bus/snes_ctrl/bcbattle.h @@ -0,0 +1,61 @@ +/********************************************************************** + + Nintendo Super Famicom - Epoch Barcode Battler + + Copyright MESS Team. + Visit http://mamedev.org for licensing and usage restrictions. + +**********************************************************************/ + +#pragma once + +#ifndef __SNES_BCBATTLE__ +#define __SNES_BCBATTLE__ + + +#include "emu.h" +#include "ctrl.h" +#include "machine/bcreader.h" + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// ======================> snes_bcbattle_device + +class snes_bcbattle_device : public device_t, + public device_snes_control_port_interface +{ +public: + // construction/destruction + snes_bcbattle_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + + virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr); + virtual machine_config_constructor device_mconfig_additions() const; + +protected: + // device-level overrides + virtual void device_start(); + virtual void device_reset(); + + virtual UINT8 read_pin4(); + virtual void write_strobe(UINT8 data); + virtual void port_poll(); + + int read_current_bit(); + +private: + + static const device_timer_id TIMER_BATTLER = 1; + required_device m_reader; + UINT8 m_current_barcode[20]; + int m_pending_code, m_new_code, m_transmitting, m_cur_bit, m_cur_byte; + emu_timer *battler_timer; + + int m_strobe, m_on, m_idx; +}; + +// device type definition +extern const device_type SNES_BARCODE_BATTLER; + +#endif diff --git a/src/emu/bus/snes_ctrl/ctrl.c b/src/emu/bus/snes_ctrl/ctrl.c new file mode 100644 index 00000000000..a09365dab27 --- /dev/null +++ b/src/emu/bus/snes_ctrl/ctrl.c @@ -0,0 +1,135 @@ +/********************************************************************** + + Nintendo Super Famicom & SNES controller port emulation + + Copyright MESS Team. + Visit http://mamedev.org for licensing and usage restrictions. + +**********************************************************************/ + +#include "ctrl.h" +// slot devices +#include "bcbattle.h" +#include "joypad.h" +#include "mouse.h" +#include "multitap.h" +#include "pachinko.h" +#include "sscope.h" +#include "twintap.h" + + +//************************************************************************** +// GLOBAL VARIABLES +//************************************************************************** + +const device_type SNES_CONTROL_PORT = &device_creator; + + +//************************************************************************** +// CARD INTERFACE +//************************************************************************** + +//------------------------------------------------- +// device_snes_control_port_interface - constructor +//------------------------------------------------- + +device_snes_control_port_interface::device_snes_control_port_interface(const machine_config &mconfig, device_t &device) + : device_slot_card_interface(mconfig,device) +{ + m_port = dynamic_cast(device.owner()); +} + + +//------------------------------------------------- +// ~device_snes_control_port_interface - destructor +//------------------------------------------------- + +device_snes_control_port_interface::~device_snes_control_port_interface() +{ +} + + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// snes_control_port_device - constructor +//------------------------------------------------- + +snes_control_port_device::snes_control_port_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : + device_t(mconfig, SNES_CONTROL_PORT, "Nintendo SNES / SFC control port", tag, owner, clock, "snes_control_port", __FILE__), + device_slot_interface(mconfig, *this) +{ +} + + +//------------------------------------------------- +// snes_control_port_device - destructor +//------------------------------------------------- + +snes_control_port_device::~snes_control_port_device() +{ +} + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void snes_control_port_device::device_start() +{ + m_device = dynamic_cast(get_card_device()); + m_onscreen_cb.bind_relative_to(*owner()); + m_gunlatch_cb.bind_relative_to(*owner()); +} + + +UINT8 snes_control_port_device::read_pin4() +{ + UINT8 data = 0; + if (m_device) + data |= m_device->read_pin4(); + return data; +} + +UINT8 snes_control_port_device::read_pin5() +{ + UINT8 data = 0; + if (m_device) + data |= m_device->read_pin5(); + return data; +} + +void snes_control_port_device::write_strobe(UINT8 data) +{ + if (m_device) + m_device->write_strobe(data); +} + +void snes_control_port_device::write_pin6(UINT8 data) +{ + if (m_device) + m_device->write_pin6(data); +} + +void snes_control_port_device::port_poll() +{ + if (m_device) + m_device->port_poll(); +} + + +//------------------------------------------------- +// SLOT_INTERFACE( snes_control_port_devices ) +//------------------------------------------------- + +SLOT_INTERFACE_START( snes_control_port_devices ) + SLOT_INTERFACE("joypad", SNES_JOYPAD) + SLOT_INTERFACE("mouse", SNES_MOUSE) + SLOT_INTERFACE("multitap", SNES_MULTITAP) + SLOT_INTERFACE("pachinko", SNES_PACHINKO) + SLOT_INTERFACE("sscope", SNES_SUPERSCOPE) + SLOT_INTERFACE("twintap", SNES_TWINTAP) + SLOT_INTERFACE("barcode_battler", SNES_BARCODE_BATTLER) +SLOT_INTERFACE_END diff --git a/src/emu/bus/snes_ctrl/ctrl.h b/src/emu/bus/snes_ctrl/ctrl.h new file mode 100644 index 00000000000..d7f87ef5c42 --- /dev/null +++ b/src/emu/bus/snes_ctrl/ctrl.h @@ -0,0 +1,101 @@ +/********************************************************************** + + Nintendo Super Famicom & SNES controller port emulation + + Copyright MESS Team. + Visit http://mamedev.org for licensing and usage restrictions. + +**********************************************************************/ + + +#pragma once + +#ifndef __SNES_CONTROL_PORT__ +#define __SNES_CONTROL_PORT__ + +#include "emu.h" + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +class snes_control_port_device; + +// ======================> device_snes_control_port_interface + +class device_snes_control_port_interface : public device_slot_card_interface +{ +public: + // construction/destruction + device_snes_control_port_interface(const machine_config &mconfig, device_t &device); + virtual ~device_snes_control_port_interface(); + + virtual UINT8 read_pin4() { return 0; }; + virtual UINT8 read_pin5() { return 0; }; + virtual void write_pin6(UINT8 data) { }; + virtual void write_strobe(UINT8 data) { }; + virtual void port_poll() { }; + +protected: + snes_control_port_device *m_port; +}; + +typedef device_delegate snesctrl_onscreen_delegate; +#define SNESCTRL_ONSCREEN_CB(name) bool name(INT16 x, INT16 y) + +typedef device_delegate snesctrl_gunlatch_delegate; +#define SNESCTRL_GUNLATCH_CB(name) void name(INT16 x, INT16 y) + +// ======================> snes_control_port_device + +class snes_control_port_device : public device_t, + public device_slot_interface +{ +public: + // construction/destruction + snes_control_port_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + virtual ~snes_control_port_device(); + + static void set_onscreen_callback(device_t &device, snesctrl_onscreen_delegate callback) { downcast(device).m_onscreen_cb = callback; } + static void set_gunlatch_callback(device_t &device, snesctrl_gunlatch_delegate callback) { downcast(device).m_gunlatch_cb = callback; } + + UINT8 read_pin4(); + UINT8 read_pin5(); + void write_pin6(UINT8 data); + void write_strobe(UINT8 data); + void port_poll(); + + snesctrl_onscreen_delegate m_onscreen_cb; + snesctrl_gunlatch_delegate m_gunlatch_cb; + +protected: + // device-level overrides + virtual void device_start(); + + device_snes_control_port_interface *m_device; +}; + + +// device type definition +extern const device_type SNES_CONTROL_PORT; + + +//************************************************************************** +// INTERFACE CONFIGURATION MACROS +//************************************************************************** + +#define MCFG_SNES_CONTROL_PORT_ADD(_tag, _slot_intf, _def_slot) \ + MCFG_DEVICE_ADD(_tag, SNES_CONTROL_PORT, 0) \ + MCFG_DEVICE_SLOT_INTERFACE(_slot_intf, _def_slot, false) + +#define MCFG_SNESCTRL_ONSCREEN_CB(_class, _method) \ + snes_control_port_device::set_onscreen_callback(*device, snesctrl_onscreen_delegate(&_class::_method, #_class "::" #_method, downcast<_class *>(owner))); + +#define MCFG_SNESCTRL_GUNLATCH_CB(_class, _method) \ + snes_control_port_device::set_gunlatch_callback(*device, snesctrl_gunlatch_delegate(&_class::_method, #_class "::" #_method, downcast<_class *>(owner))); + + +SLOT_INTERFACE_EXTERN( snes_control_port_devices ); + + +#endif diff --git a/src/emu/bus/snes_ctrl/joypad.c b/src/emu/bus/snes_ctrl/joypad.c new file mode 100644 index 00000000000..a8291c2dfdb --- /dev/null +++ b/src/emu/bus/snes_ctrl/joypad.c @@ -0,0 +1,127 @@ +/********************************************************************** + + Nintendo Super Famicom & SNES Joypad + + Copyright MESS Team. + Visit http://mamedev.org for licensing and usage restrictions. + +**********************************************************************/ + +#include "joypad.h" + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +const device_type SNES_JOYPAD = &device_creator; + + +static INPUT_PORTS_START( snes_joypad ) + PORT_START("JOYPAD") + PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("B") + PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_BUTTON4 ) PORT_NAME("Y") + PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_SELECT ) PORT_NAME("Select") + PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_START1 ) PORT_NAME("Start") + PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) + PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) + PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) + PORT_BIT( 0x0080, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) + PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("A") + PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_BUTTON5 ) PORT_NAME("X") + PORT_BIT( 0x0400, IP_ACTIVE_HIGH, IPT_BUTTON6 ) PORT_NAME("L") + PORT_BIT( 0x0800, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("R") + PORT_BIT( 0xf000, IP_ACTIVE_HIGH, IPT_UNUSED ) +INPUT_PORTS_END + + +//------------------------------------------------- +// input_ports - device-specific input ports +//------------------------------------------------- + +ioport_constructor snes_joypad_device::device_input_ports() const +{ + return INPUT_PORTS_NAME( snes_joypad ); +} + + + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// snes_joypad_device - constructor +//------------------------------------------------- + +snes_joypad_device::snes_joypad_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : + device_t(mconfig, SNES_JOYPAD, "Nintendo SNES / SFC Control Pad", tag, owner, clock, "snes_joypad", __FILE__), + device_snes_control_port_interface(mconfig, *this), + m_joypad(*this, "JOYPAD") +{ +} + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void snes_joypad_device::device_start() +{ + save_item(NAME(m_latch)); + save_item(NAME(m_strobe)); +} + + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void snes_joypad_device::device_reset() +{ + m_latch = 0; + m_strobe = 0; +} + + +//------------------------------------------------- +// poll +//------------------------------------------------- + +void snes_joypad_device::port_poll() +{ + UINT16 temp = m_joypad->read(); + // avoid sending signals that could crash games + // if left, no right + if (temp & 0x40) + temp &= ~0x80; + // if up, no down + if (temp & 0x10) + temp &= ~0x20; + + m_latch = temp | 0xffff0000; +} + +//------------------------------------------------- +// read +//------------------------------------------------- + +UINT8 snes_joypad_device::read_pin4() +{ + UINT8 ret = m_latch & 1; + m_latch >>= 1; + return ret; +} + +//------------------------------------------------- +// write +//------------------------------------------------- + +void snes_joypad_device::write_strobe(UINT8 data) +{ + int old = m_strobe; + m_strobe = data & 0x01; + + if (m_strobe < old) // 1 -> 0 transition + port_poll(); +} + diff --git a/src/emu/bus/snes_ctrl/joypad.h b/src/emu/bus/snes_ctrl/joypad.h new file mode 100644 index 00000000000..9c6920e7a18 --- /dev/null +++ b/src/emu/bus/snes_ctrl/joypad.h @@ -0,0 +1,56 @@ +/********************************************************************** + + Nintendo Super Famicom & SNES Joypad + + Copyright MESS Team. + Visit http://mamedev.org for licensing and usage restrictions. + +**********************************************************************/ + +#pragma once + +#ifndef __SNES_JOYPAD__ +#define __SNES_JOYPAD__ + + +#include "emu.h" +#include "ctrl.h" + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// ======================> snes_joypad_device + +class snes_joypad_device : public device_t, + public device_snes_control_port_interface +{ +public: + // construction/destruction + snes_joypad_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + + // optional information overrides + virtual ioport_constructor device_input_ports() const; + +protected: + // device-level overrides + virtual void device_start(); + virtual void device_reset(); + + // device_sms_control_port_interface overrides + virtual UINT8 read_pin4(); + virtual void write_strobe(UINT8 data); + virtual void port_poll(); + +private: + required_ioport m_joypad; + int m_strobe; + UINT32 m_latch; +}; + + +// device type definition +extern const device_type SNES_JOYPAD; + + +#endif diff --git a/src/emu/bus/snes_ctrl/mouse.c b/src/emu/bus/snes_ctrl/mouse.c new file mode 100644 index 00000000000..1d6cb5b52f6 --- /dev/null +++ b/src/emu/bus/snes_ctrl/mouse.c @@ -0,0 +1,241 @@ +/********************************************************************** + + Nintendo Super Famicom & SNES Mouse + + Copyright MESS Team. + Visit http://mamedev.org for licensing and usage restrictions. + +**********************************************************************/ + +#include "mouse.h" + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +const device_type SNES_MOUSE = &device_creator; + + +static INPUT_PORTS_START( snes_mouse ) + PORT_START("BUTTONS") + PORT_BIT( 0x00ff, IP_ACTIVE_HIGH, IPT_SPECIAL ) // these must be 0! + PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("Button Right") + PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("Button Left") + PORT_BIT( 0x0c00, IP_ACTIVE_HIGH, IPT_UNUSED ) // mouse speed: 0 = slow, 1 = normal, 2 = fast, 3 = unused + PORT_BIT( 0x1000, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x2000, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x4000, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_UNUSED ) + + // we use IPT_LIGHTGUN instead of IPT_MOUSE to avoid input to wrap when you reach the screen border + // due to the relative nature of movement detection in SNES mouse, when we wrap the system would + // detect a sudden jump in the wrong direction, making the usage unfriendly... + PORT_START("MOUSE_X") + PORT_BIT( 0x1ff, 0x100, IPT_LIGHTGUN_X ) PORT_NAME("Superscope X Axis") PORT_SENSITIVITY(30) PORT_KEYDELTA(5) +// PORT_BIT( 0xff, 0x00, IPT_MOUSE_X) PORT_SENSITIVITY(30) PORT_KEYDELTA(5) + + PORT_START("MOUSE_Y") + PORT_BIT( 0x1ff, 0x100, IPT_LIGHTGUN_Y) PORT_NAME("Superscope Y Axis") PORT_SENSITIVITY(30) PORT_KEYDELTA(5) +// PORT_BIT( 0xff, 0x00, IPT_MOUSE_Y) PORT_SENSITIVITY(30) PORT_KEYDELTA(5) +INPUT_PORTS_END + + +//------------------------------------------------- +// input_ports - device-specific input ports +//------------------------------------------------- + +ioport_constructor snes_mouse_device::device_input_ports() const +{ + return INPUT_PORTS_NAME( snes_mouse ); +} + + + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// snes_mouse_device - constructor +//------------------------------------------------- + +snes_mouse_device::snes_mouse_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : + device_t(mconfig, SNES_MOUSE, "Nintendo SNES / SFC Mouse Controller", tag, owner, clock, "snes_mouse", __FILE__), + device_snes_control_port_interface(mconfig, *this), + m_buttons(*this, "BUTTONS"), + m_xaxis(*this, "MOUSE_X"), + m_yaxis(*this, "MOUSE_Y") +{ +} + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void snes_mouse_device::device_start() +{ + save_item(NAME(m_strobe)); + save_item(NAME(m_idx)); + save_item(NAME(m_latch)); + save_item(NAME(m_x)); + save_item(NAME(m_y)); + save_item(NAME(m_oldx)); + save_item(NAME(m_oldy)); + save_item(NAME(m_deltax)); + save_item(NAME(m_deltay)); + save_item(NAME(m_speed)); + save_item(NAME(m_dirx)); + save_item(NAME(m_diry)); +} + + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void snes_mouse_device::device_reset() +{ + m_strobe = 0; + m_idx = 0; + m_latch = 0; + m_x = 0; + m_y = 0; + m_oldx = 0; + m_oldy = 0; + m_deltax = 0; + m_deltay = 0; + m_speed = 0; + m_dirx = -1; + m_diry = -1; +} + + +//------------------------------------------------- +// poll +//------------------------------------------------- + +void snes_mouse_device::port_poll() +{ + INT16 var; + int new_dir; + m_idx = 0; + m_latch = m_buttons->read(); + + m_oldx = m_x; + m_oldy = m_y; + m_x = m_xaxis->read(); + m_y = m_yaxis->read(); + + var = m_x - m_oldx; + if (var) + { + new_dir = (var < 0) ? 1 : 0; + if (m_dirx != new_dir) + m_dirx = new_dir; + } + + if (var < -127) + { + m_deltax = 0x7f; + m_oldx -= 127; + } + else if (var < 0) + { + m_deltax = -var; + m_oldx = m_x; + } + else if (var > 127) + { + m_deltax = 0x7f; + m_oldx += 127; + } + else + { + m_deltax = var; + m_oldx = m_x; + } + + var = m_y - m_oldy; + if (var) + { + new_dir = (var < 0) ? 1 : 0; + if (m_diry != new_dir) + m_diry = new_dir; + } + + if (var < -127) + { + m_deltay = 0x7f; + m_oldy -= 127; + } + else if (var < 0) + { + m_deltay = -var; + m_oldy = m_y; + } + else if (var > 127) + { + m_deltay = 0x7f; + m_oldy += 127; + } + else + { + m_deltay = var; + m_oldy = m_y; + } + + m_deltax |= (m_dirx << 7); + m_deltay |= (m_diry << 7); +} + +//------------------------------------------------- +// read +//------------------------------------------------- + +UINT8 snes_mouse_device::read_pin4() +{ + UINT8 res = 0; + + if (m_strobe == 1) + { + // reading with strobe 1, changes mouse speed + m_speed = (m_speed + 1) % 3; + return res; + } + + if (m_idx >= 32) + res |= 0x01; + else if (m_idx >= 24) + res |= BIT(m_deltax, (31 - m_idx++)); + else if (m_idx >= 16) + res |= BIT(m_deltay, (23 - m_idx++)); + else if (m_idx == 11) + { + res |= BIT(m_speed, 0); + m_idx++; + } + else if (m_idx == 10) + { + res |= BIT(m_speed, 1); + m_idx++; + } + else + res |= BIT(m_latch, m_idx++); + + return res; +} + +//------------------------------------------------- +// write +//------------------------------------------------- + +void snes_mouse_device::write_strobe(UINT8 data) +{ + int old = m_strobe; + m_strobe = data & 0x01; + + if (m_strobe < old) // 1 -> 0 transition + port_poll(); +} + diff --git a/src/emu/bus/snes_ctrl/mouse.h b/src/emu/bus/snes_ctrl/mouse.h new file mode 100644 index 00000000000..fbce1ba6c41 --- /dev/null +++ b/src/emu/bus/snes_ctrl/mouse.h @@ -0,0 +1,64 @@ +/********************************************************************** + + Nintendo Super Famicom & SNES Mouse + + Copyright MESS Team. + Visit http://mamedev.org for licensing and usage restrictions. + +**********************************************************************/ + +#pragma once + +#ifndef __SNES_MOUSE__ +#define __SNES_MOUSE__ + + +#include "emu.h" +#include "ctrl.h" + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// ======================> snes_mouse_device + +class snes_mouse_device : public device_t, + public device_snes_control_port_interface +{ +public: + // construction/destruction + snes_mouse_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + + // optional information overrides + virtual ioport_constructor device_input_ports() const; + +protected: + // device-level overrides + virtual void device_start(); + virtual void device_reset(); + + // device_sms_control_port_interface overrides + virtual UINT8 read_pin4(); + virtual void write_strobe(UINT8 data); + virtual void port_poll(); + +private: + required_ioport m_buttons; + required_ioport m_xaxis; + required_ioport m_yaxis; + int m_strobe; + int m_idx; + UINT32 m_latch; + + INT16 m_x, m_y, m_oldx, m_oldy; + UINT8 m_deltax, m_deltay; + int m_speed; + int m_dirx, m_diry; +}; + + +// device type definition +extern const device_type SNES_MOUSE; + + +#endif diff --git a/src/emu/bus/snes_ctrl/multitap.c b/src/emu/bus/snes_ctrl/multitap.c new file mode 100644 index 00000000000..bf1d04cada9 --- /dev/null +++ b/src/emu/bus/snes_ctrl/multitap.c @@ -0,0 +1,155 @@ +/********************************************************************** + + Nintendo Super Famicom & SNES Multitap Adapter + + Copyright MESS Team. + Visit http://mamedev.org for licensing and usage restrictions. + +**********************************************************************/ + +#include "multitap.h" +#include "joypad.h" +#include "twintap.h" + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +const device_type SNES_MULTITAP = &device_creator; + + +static INPUT_PORTS_START( snes_multitap ) + PORT_START("CONFIG") + PORT_CONFNAME( 0x01, 0x00, "Number of players") + PORT_CONFSETTING( 0x00, "3-5P" ) + PORT_CONFSETTING( 0x01, "2P" ) +INPUT_PORTS_END + + +//------------------------------------------------- +// input_ports - device-specific input ports +//------------------------------------------------- + +ioport_constructor snes_multitap_device::device_input_ports() const +{ + return INPUT_PORTS_NAME( snes_multitap ); +} + + +static SLOT_INTERFACE_START( snes_multitap ) + SLOT_INTERFACE("joypad", SNES_JOYPAD) + SLOT_INTERFACE("twintap", SNES_TWINTAP) +SLOT_INTERFACE_END + +static MACHINE_CONFIG_FRAGMENT( multi5p ) + MCFG_SNES_CONTROL_PORT_ADD("port1", snes_multitap, "joypad") + MCFG_SNES_CONTROL_PORT_ADD("port2", snes_multitap, "joypad") + MCFG_SNES_CONTROL_PORT_ADD("port3", snes_multitap, "joypad") + MCFG_SNES_CONTROL_PORT_ADD("port4", snes_multitap, "joypad") +MACHINE_CONFIG_END + + +//------------------------------------------------- +// machine_config_additions - device-specific +// machine configurations +//------------------------------------------------- + +machine_config_constructor snes_multitap_device::device_mconfig_additions() const +{ + return MACHINE_CONFIG_NAME( multi5p ); +} + + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// snes_multitap_device - constructor +//------------------------------------------------- + +snes_multitap_device::snes_multitap_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : + device_t(mconfig, SNES_MULTITAP, "Nintendo SNES / SFC Multitap Adapter", tag, owner, clock, "snes_joypad", __FILE__), + device_snes_control_port_interface(mconfig, *this), + m_port1(*this, "port1"), + m_port2(*this, "port2"), + m_port3(*this, "port3"), + m_port4(*this, "port4"), + m_cfg(*this, "CONFIG") +{ +} + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void snes_multitap_device::device_start() +{ + save_item(NAME(m_select)); +} + +void snes_multitap_device::device_reset() +{ + m_select = 1; +} + +//------------------------------------------------- +// poll +//------------------------------------------------- + +void snes_multitap_device::port_poll() +{ + m_port1->port_poll(); + if (m_cfg->read() == 0) // 4P + { + m_port2->port_poll(); + m_port3->port_poll(); + m_port4->port_poll(); + } +} + +//------------------------------------------------- +// read +//------------------------------------------------- + +UINT8 snes_multitap_device::read_pin4() +{ + UINT8 ret = 0; + + if (m_cfg->read() == 0) // 4P + ret |= m_select ? m_port1->read_pin4() : m_port3->read_pin4(); + else // 1P + ret |= m_select ? m_port1->read_pin4() : 0; + + return ret; +} + +UINT8 snes_multitap_device::read_pin5() +{ + UINT8 ret = 0; + + if (m_cfg->read() == 0) // 4P + ret |= m_select ? m_port2->read_pin4() : m_port4->read_pin4(); + return ret; +} + +//------------------------------------------------- +// write +//------------------------------------------------- + +void snes_multitap_device::write_strobe(UINT8 data) +{ + m_port1->write_strobe(data); + if (m_cfg->read() == 0) // 4P + { + m_port2->write_strobe(data); + m_port3->write_strobe(data); + m_port4->write_strobe(data); + } +} + +void snes_multitap_device::write_pin6(UINT8 data) +{ + m_select = data & 1; +} diff --git a/src/emu/bus/snes_ctrl/multitap.h b/src/emu/bus/snes_ctrl/multitap.h new file mode 100644 index 00000000000..b43f3116f18 --- /dev/null +++ b/src/emu/bus/snes_ctrl/multitap.h @@ -0,0 +1,62 @@ +/********************************************************************** + + Nintendo Super Famicom & SNES Multitap Adapter + + Copyright MESS Team. + Visit http://mamedev.org for licensing and usage restrictions. + +**********************************************************************/ + +#pragma once + +#ifndef __SNES_MULTITAP__ +#define __SNES_MULTITAP__ + + +#include "emu.h" +#include "ctrl.h" + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// ======================> snes_multitap_device + +class snes_multitap_device : public device_t, + public device_snes_control_port_interface +{ +public: + // construction/destruction + snes_multitap_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + + // optional information overrides + virtual ioport_constructor device_input_ports() const; + virtual machine_config_constructor device_mconfig_additions() const; + +protected: + // device-level overrides + virtual void device_start(); + virtual void device_reset(); + + // device_sms_control_port_interface overrides + virtual UINT8 read_pin4(); + virtual UINT8 read_pin5(); + virtual void write_strobe(UINT8 data); + virtual void write_pin6(UINT8 data); + virtual void port_poll(); + +private: + required_device m_port1; + required_device m_port2; + required_device m_port3; + required_device m_port4; + required_ioport m_cfg; + int m_select; +}; + + +// device type definition +extern const device_type SNES_MULTITAP; + + +#endif diff --git a/src/emu/bus/snes_ctrl/pachinko.c b/src/emu/bus/snes_ctrl/pachinko.c new file mode 100644 index 00000000000..099e4e00f57 --- /dev/null +++ b/src/emu/bus/snes_ctrl/pachinko.c @@ -0,0 +1,111 @@ +/********************************************************************** + + Nintendo Super Famicom - Sunsoft Pachinko Controller + + Copyright MESS Team. + Visit http://mamedev.org for licensing and usage restrictions. + +**********************************************************************/ + +#include "pachinko.h" + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +const device_type SNES_PACHINKO = &device_creator; + + +static INPUT_PORTS_START( snes_pachinko ) + PORT_START("DIAL") + PORT_BIT( 0x7f, 0x3f, IPT_PADDLE) PORT_SENSITIVITY(25) PORT_KEYDELTA(25) PORT_CENTERDELTA(0) PORT_MINMAX(0x18,0x7f) + + PORT_START("BUTTON") + PORT_BIT( 0x00ff, IP_ACTIVE_HIGH, IPT_UNUSED) + PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("Button") + PORT_BIT( 0xfe00, IP_ACTIVE_HIGH, IPT_UNUSED) +INPUT_PORTS_END + + +//------------------------------------------------- +// input_ports - device-specific input ports +//------------------------------------------------- + +ioport_constructor snes_pachinko_device::device_input_ports() const +{ + return INPUT_PORTS_NAME( snes_pachinko ); +} + + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// snes_pachinko_device - constructor +//------------------------------------------------- + +snes_pachinko_device::snes_pachinko_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : + device_t(mconfig, SNES_PACHINKO, "Sunsoft Pachinko Controller", tag, owner, clock, "snes_pachinko", __FILE__), + device_snes_control_port_interface(mconfig, *this), + m_dial(*this, "DIAL"), + m_button(*this, "BUTTON") +{ +} + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void snes_pachinko_device::device_start() +{ + save_item(NAME(m_latch)); + save_item(NAME(m_strobe)); +} + + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void snes_pachinko_device::device_reset() +{ + m_latch = 0; + m_strobe = 0; +} + + +//------------------------------------------------- +// poll +//------------------------------------------------- + +void snes_pachinko_device::port_poll() +{ + UINT8 dial = BITSWAP8(m_dial->read() ^ 0xff,7,6,5,4,3,2,1,0); + m_latch = m_button->read() | (dial << 25) | 0xee7000; // add ID +} + +//------------------------------------------------- +// read +//------------------------------------------------- + +UINT8 snes_pachinko_device::read_pin4() +{ + UINT8 ret = m_latch & 1; + m_latch >>= 1; + return ret; +} + +//------------------------------------------------- +// write +//------------------------------------------------- + +void snes_pachinko_device::write_strobe(UINT8 data) +{ + int old = m_strobe; + m_strobe = data & 0x01; + + if (m_strobe < old) // 1 -> 0 transition + port_poll(); +} diff --git a/src/emu/bus/snes_ctrl/pachinko.h b/src/emu/bus/snes_ctrl/pachinko.h new file mode 100644 index 00000000000..0dc2fe25480 --- /dev/null +++ b/src/emu/bus/snes_ctrl/pachinko.h @@ -0,0 +1,57 @@ +/********************************************************************** + + Nintendo Super Famicom - Sunsoft Pachinko Controller + + Copyright MESS Team. + Visit http://mamedev.org for licensing and usage restrictions. + +**********************************************************************/ + +#pragma once + +#ifndef __SNES_PACHINKO__ +#define __SNES_PACHINKO__ + + +#include "emu.h" +#include "ctrl.h" + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// ======================> snes_pachinko_device + +class snes_pachinko_device : public device_t, + public device_snes_control_port_interface +{ +public: + // construction/destruction + snes_pachinko_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + + // optional information overrides + virtual ioport_constructor device_input_ports() const; + +protected: + // device-level overrides + virtual void device_start(); + virtual void device_reset(); + + // device_sms_control_port_interface overrides + virtual UINT8 read_pin4(); + virtual void write_strobe(UINT8 data); + virtual void port_poll(); + +private: + required_ioport m_dial; + required_ioport m_button; + int m_strobe; + UINT32 m_latch; +}; + + +// device type definition +extern const device_type SNES_PACHINKO; + + +#endif diff --git a/src/emu/bus/snes_ctrl/sscope.c b/src/emu/bus/snes_ctrl/sscope.c new file mode 100644 index 00000000000..93e46879a16 --- /dev/null +++ b/src/emu/bus/snes_ctrl/sscope.c @@ -0,0 +1,187 @@ +/********************************************************************** + + Nintendo Super Famicom & SNES SuperScope + + TODO: x,y positions are not correctly latched + + Copyright MESS Team. + Visit http://mamedev.org for licensing and usage restrictions. + +**********************************************************************/ + +#include "sscope.h" + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +const device_type SNES_SUPERSCOPE = &device_creator; + + +static INPUT_PORTS_START( snes_sscope ) + PORT_START("BUTTONS") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("Superscope Fire") + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("Superscope Cursor") + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("Superscope Turbo") + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_BUTTON4 ) PORT_NAME("Superscope Pause") + PORT_BIT( 0x30, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_UNUSED ) // On-screen (handled below in port_poll) + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNUSED ) // Noise + + PORT_START("SSX") + PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_X ) PORT_NAME("Superscope X Axis") PORT_CROSSHAIR(X, 1.0, 0.0, 0) PORT_SENSITIVITY(25) PORT_KEYDELTA(15) + + PORT_START("SSY") + PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_Y) PORT_NAME("Superscope Y Axis") PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_SENSITIVITY(25) PORT_KEYDELTA(15) +INPUT_PORTS_END + + +//------------------------------------------------- +// input_ports - device-specific input ports +//------------------------------------------------- + +ioport_constructor snes_sscope_device::device_input_ports() const +{ + return INPUT_PORTS_NAME( snes_sscope ); +} + + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// snes_sscope_device - constructor +//------------------------------------------------- + +snes_sscope_device::snes_sscope_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : + device_t(mconfig, SNES_SUPERSCOPE, "Nintendo SNES / SFC SuperScope", tag, owner, clock, "snes_sscope", __FILE__), + device_snes_control_port_interface(mconfig, *this), + m_buttons(*this, "BUTTONS"), + m_xaxis(*this, "SSX"), + m_yaxis(*this, "SSY") +{ +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void snes_sscope_device::device_start() +{ + save_item(NAME(m_strobe)); + save_item(NAME(m_idx)); + save_item(NAME(m_latch)); + save_item(NAME(m_x)); + save_item(NAME(m_y)); + save_item(NAME(m_turbo_lock)); + save_item(NAME(m_pause_lock)); + save_item(NAME(m_fire_lock)); +} + + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void snes_sscope_device::device_reset() +{ + m_strobe = 0; + m_idx = 0; + m_latch = 0; + m_x = 0; + m_y = 0; + m_turbo_lock = 0; + m_pause_lock = 0; + m_fire_lock = 0; +} + + +//------------------------------------------------- +// poll +//------------------------------------------------- + +void snes_sscope_device::port_poll() +{ + // first read input bits + UINT8 input = m_buttons->read(); + m_x = m_xaxis->read(); + m_y = m_yaxis->read(); + m_idx = 0; + + // then start elaborating input bits + // 1. only keep old turbo value + m_latch &= 0x04; + + // 2. set onscreen/offscreen + if (!m_port->m_onscreen_cb.isnull()) + m_latch |= (m_port->m_onscreen_cb(m_x, m_y) ? 0x00 : 0x40); + + // 3. pause is a button that is always edge sensitive + if (BIT(input, 3) && !m_pause_lock) + { + m_latch |= 0x08; + m_pause_lock = 1; + } + else if (!BIT(input, 3)) + m_pause_lock = 0; + + // 4. turbo is a switch; toggle is edge sensitive + if (BIT(input, 2) && !m_turbo_lock) + { + m_latch ^= 0x04; + m_turbo_lock = 1; + } + else if (!BIT(input, 2)) + m_turbo_lock = 0; + + // 5. cursor is a button that is always level sensitive + m_latch |= BIT(input, 1); + + // 6. fire is a button with two behaviors: if turbo is active, trigger is level sensitive; + // otherwise it is edge sensitive + if (BIT(input, 0) && (BIT(m_latch, 2) || !m_fire_lock)) + { + m_latch |= 0x01; + m_fire_lock = 1; + } + else if (!BIT(input, 0)) + m_fire_lock = 0; + + // If we have pressed fire or cursor and we are on-screen and SuperScope is in Port2, then latch video signal. + // Notice that this only works in Port2 because its IOBit pin is connected to bit7 of the IO Port, while Port1 + // has IOBit pin connected to bit6 of the IO Port, and the latter is not detected by the H/V Counters. In other + // words, you can connect SuperScope to Port1, but there is no way SNES could detect its on-screen position + if ((m_latch & 0x03) && !(m_latch & 0x40) && !m_port->m_gunlatch_cb.isnull()) + m_port->m_gunlatch_cb(m_x, m_y); +} + +//------------------------------------------------- +// read +//------------------------------------------------- + +UINT8 snes_sscope_device::read_pin4() +{ + UINT8 res = 0; + + if (m_idx >= 8) // bits 8-15 = ID = all 1s; bits >= 16 all 1s + res |= 0x01; + else + res |= BIT(m_latch, m_idx++); + + return res; +} + +//------------------------------------------------- +// write +//------------------------------------------------- + +void snes_sscope_device::write_strobe(UINT8 data) +{ + int old = m_strobe; + m_strobe = data & 0x01; + + if (m_strobe < old) // 1 -> 0 transition + port_poll(); +} + diff --git a/src/emu/bus/snes_ctrl/sscope.h b/src/emu/bus/snes_ctrl/sscope.h new file mode 100644 index 00000000000..e6a806038fc --- /dev/null +++ b/src/emu/bus/snes_ctrl/sscope.h @@ -0,0 +1,61 @@ +/********************************************************************** + + Nintendo Super Famicom & SNES SuperScope + + Copyright MESS Team. + Visit http://mamedev.org for licensing and usage restrictions. + +**********************************************************************/ + +#pragma once + +#ifndef __SNES_SUPERSCOPE__ +#define __SNES_SUPERSCOPE__ + + +#include "emu.h" +#include "ctrl.h" + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// ======================> snes_sscope_device + +class snes_sscope_device : public device_t, + public device_snes_control_port_interface +{ +public: + // construction/destruction + snes_sscope_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + + // optional information overrides + virtual ioport_constructor device_input_ports() const; + +protected: + // device-level overrides + virtual void device_start(); + virtual void device_reset(); + + // device_sms_control_port_interface overrides + virtual UINT8 read_pin4(); + virtual void write_strobe(UINT8 data); + virtual void port_poll(); + +private: + required_ioport m_buttons; + required_ioport m_xaxis; + required_ioport m_yaxis; + int m_strobe, m_idx; + UINT32 m_latch; + + INT16 m_x, m_y; + int m_turbo_lock, m_pause_lock, m_fire_lock; +}; + + +// device type definition +extern const device_type SNES_SUPERSCOPE; + + +#endif diff --git a/src/emu/bus/snes_ctrl/twintap.c b/src/emu/bus/snes_ctrl/twintap.c new file mode 100644 index 00000000000..6ddcb32b158 --- /dev/null +++ b/src/emu/bus/snes_ctrl/twintap.c @@ -0,0 +1,114 @@ +/********************************************************************** + + Nintendo Super Famicom - Yonezawa / PartyRoom 21 Twin Tap Controller + + This controller consists of two 1-button small units attached to a + single 7pin connector. You plug the connector to Port2 and two + players can compete on the quiz game (Port1 should have a joypad + plugged in, to start the game and browse the menus). By plugging + a multitap adapter to Port2, up to 4 Twin Tap controllers can be + attached at the same time, allowing for 8 players quiz sessions. + + Copyright MESS Team. + Visit http://mamedev.org for licensing and usage restrictions. + +**********************************************************************/ + +#include "twintap.h" + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +const device_type SNES_TWINTAP = &device_creator; + + +static INPUT_PORTS_START( snes_twintap ) + PORT_START("INPUTS") + PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Button 2") + PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Button 1") + PORT_BIT( 0x8ffc, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x7000, IP_ACTIVE_LOW, IPT_UNUSED ) // controller ID unknown +INPUT_PORTS_END + + +//------------------------------------------------- +// input_ports - device-specific input ports +//------------------------------------------------- + +ioport_constructor snes_twintap_device::device_input_ports() const +{ + return INPUT_PORTS_NAME( snes_twintap ); +} + + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// snes_twintap_device - constructor +//------------------------------------------------- + +snes_twintap_device::snes_twintap_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : + device_t(mconfig, SNES_TWINTAP, "Yonezawa Twin Tap Controller", tag, owner, clock, "snes_twintap", __FILE__), + device_snes_control_port_interface(mconfig, *this), + m_inputs(*this, "INPUTS") +{ +} + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void snes_twintap_device::device_start() +{ + save_item(NAME(m_latch)); + save_item(NAME(m_strobe)); +} + + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void snes_twintap_device::device_reset() +{ + m_latch = 0; + m_strobe = 0; +} + + +//------------------------------------------------- +// poll +//------------------------------------------------- + +void snes_twintap_device::port_poll() +{ + m_latch = m_inputs->read(); +} + +//------------------------------------------------- +// read +//------------------------------------------------- + +UINT8 snes_twintap_device::read_pin4() +{ + UINT8 ret = m_latch & 1; + m_latch >>= 1; + return ret; +} + +//------------------------------------------------- +// write +//------------------------------------------------- + +void snes_twintap_device::write_strobe(UINT8 data) +{ + int old = m_strobe; + m_strobe = data & 0x01; + + if (m_strobe < old) // 1 -> 0 transition + port_poll(); +} diff --git a/src/emu/bus/snes_ctrl/twintap.h b/src/emu/bus/snes_ctrl/twintap.h new file mode 100644 index 00000000000..482a20e1bc6 --- /dev/null +++ b/src/emu/bus/snes_ctrl/twintap.h @@ -0,0 +1,56 @@ +/********************************************************************** + + Nintendo Super Famicom - Yonezawa / PartyRoom 21 Twin Tap Controller + + Copyright MESS Team. + Visit http://mamedev.org for licensing and usage restrictions. + +**********************************************************************/ + +#pragma once + +#ifndef __SNES_TWINTAP__ +#define __SNES_TWINTAP__ + + +#include "emu.h" +#include "ctrl.h" + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// ======================> snes_twintap_device + +class snes_twintap_device : public device_t, + public device_snes_control_port_interface +{ +public: + // construction/destruction + snes_twintap_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + + // optional information overrides + virtual ioport_constructor device_input_ports() const; + +protected: + // device-level overrides + virtual void device_start(); + virtual void device_reset(); + + // device_sms_control_port_interface overrides + virtual UINT8 read_pin4(); + virtual void write_strobe(UINT8 data); + virtual void port_poll(); + +private: + required_ioport m_inputs; + int m_strobe; + UINT32 m_latch; +}; + + +// device type definition +extern const device_type SNES_TWINTAP; + + +#endif -- cgit v1.2.3-70-g09d2