summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author etabeta78 <etabeta78@users.noreply.github.com>2015-01-26 22:46:33 +0100
committer etabeta78 <etabeta78@users.noreply.github.com>2015-01-26 22:46:33 +0100
commit65523cb53fba90208cf81992c81e466b6145bcb7 (patch)
treea8cdd8f47cad3755cf2b221fd320204c10baa73e
parent79732c9bc4a6b3b5eba9b0245c2a4560c53e3c8d (diff)
(MESS) nes: converted input code to use slot devices. this means that now you
change the emulated controllers (Zapper, NES Four Score Adapter, Bandai Power Pad and Family Trainer, Famicom Keyboard Component, Arkanoid Vaus Paddle and Mahjong Controller) 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 time *before* starting the game if you want to play a game that uses particular controllers. [Fabio Priuli] (MESS) nes: added emulation of the Konami Hyper Shot controllers, which are necessary to play Hyper Olympics and Hyper Sports for Famicom. [Fabio Priuli] (MESS) nes: added emulation of the Yonezawa Party Tap controllers, which are necessary to play in more than two players some quiz games for Famicom. [Fabio Priuli] (MESS) nes: added emulation of the Pachinko controller used by a few pachinko games for Famicom. [Fabio Priuli] (MESS) nes: added emulation of the Epoch Barcode Battler unit (even if only as Famicom controller, and not as a standalone unit) which is necessary to play Barcode World for Famicom. [Fabio Priuli]
-rw-r--r--src/emu/bus/bus.mak25
-rw-r--r--src/emu/bus/nes_ctrl/4score.c190
-rw-r--r--src/emu/bus/nes_ctrl/4score.h85
-rw-r--r--src/emu/bus/nes_ctrl/arkpaddle.c131
-rw-r--r--src/emu/bus/nes_ctrl/arkpaddle.h71
-rw-r--r--src/emu/bus/nes_ctrl/bcbattle.c193
-rw-r--r--src/emu/bus/nes_ctrl/bcbattle.h55
-rw-r--r--src/emu/bus/nes_ctrl/ctrl.c208
-rw-r--r--src/emu/bus/nes_ctrl/ctrl.h104
-rw-r--r--src/emu/bus/nes_ctrl/fckeybrd.c232
-rw-r--r--src/emu/bus/nes_ctrl/fckeybrd.h55
-rw-r--r--src/emu/bus/nes_ctrl/ftrainer.c154
-rw-r--r--src/emu/bus/nes_ctrl/ftrainer.h52
-rw-r--r--src/emu/bus/nes_ctrl/hori.c169
-rw-r--r--src/emu/bus/nes_ctrl/hori.h79
-rw-r--r--src/emu/bus/nes_ctrl/joypad.c317
-rw-r--r--src/emu/bus/nes_ctrl/joypad.h112
-rw-r--r--src/emu/bus/nes_ctrl/konamihs.c102
-rw-r--r--src/emu/bus/nes_ctrl/konamihs.h50
-rw-r--r--src/emu/bus/nes_ctrl/miracle.c178
-rw-r--r--src/emu/bus/nes_ctrl/miracle.h55
-rw-r--r--src/emu/bus/nes_ctrl/mjpanel.c132
-rw-r--r--src/emu/bus/nes_ctrl/mjpanel.h52
-rw-r--r--src/emu/bus/nes_ctrl/pachinko.c108
-rw-r--r--src/emu/bus/nes_ctrl/pachinko.h50
-rw-r--r--src/emu/bus/nes_ctrl/partytap.c108
-rw-r--r--src/emu/bus/nes_ctrl/partytap.h50
-rw-r--r--src/emu/bus/nes_ctrl/powerpad.c136
-rw-r--r--src/emu/bus/nes_ctrl/powerpad.h53
-rw-r--r--src/emu/bus/nes_ctrl/suborkey.c230
-rw-r--r--src/emu/bus/nes_ctrl/suborkey.h52
-rw-r--r--src/emu/bus/nes_ctrl/zapper.c97
-rw-r--r--src/emu/bus/nes_ctrl/zapper.h53
-rw-r--r--src/mess/drivers/nes.c601
-rw-r--r--src/mess/includes/nes.h59
-rw-r--r--src/mess/machine/nes.c619
-rw-r--r--src/mess/mess.mak1
37 files changed, 3822 insertions, 1196 deletions
diff --git a/src/emu/bus/bus.mak b/src/emu/bus/bus.mak
index 0c6f5484174..21f071394bb 100644
--- a/src/emu/bus/bus.mak
+++ b/src/emu/bus/bus.mak
@@ -1087,6 +1087,31 @@ endif
#-------------------------------------------------
#
+#@src/emu/bus/nes_ctrl/ctrl.h,BUSES += NES_CTRL
+#-------------------------------------------------
+
+ifneq ($(filter NES_CTRL,$(BUSES)),)
+OBJDIRS += $(BUSOBJ)/nes_ctrl
+BUSOBJS += $(BUSOBJ)/nes_ctrl/ctrl.o
+BUSOBJS += $(BUSOBJ)/nes_ctrl/joypad.o
+BUSOBJS += $(BUSOBJ)/nes_ctrl/4score.o
+BUSOBJS += $(BUSOBJ)/nes_ctrl/arkpaddle.o
+BUSOBJS += $(BUSOBJ)/nes_ctrl/bcbattle.o
+BUSOBJS += $(BUSOBJ)/nes_ctrl/ftrainer.o
+BUSOBJS += $(BUSOBJ)/nes_ctrl/fckeybrd.o
+BUSOBJS += $(BUSOBJ)/nes_ctrl/hori.o
+BUSOBJS += $(BUSOBJ)/nes_ctrl/konamihs.o
+BUSOBJS += $(BUSOBJ)/nes_ctrl/miracle.o
+BUSOBJS += $(BUSOBJ)/nes_ctrl/mjpanel.o
+BUSOBJS += $(BUSOBJ)/nes_ctrl/pachinko.o
+BUSOBJS += $(BUSOBJ)/nes_ctrl/partytap.o
+BUSOBJS += $(BUSOBJ)/nes_ctrl/powerpad.o
+BUSOBJS += $(BUSOBJ)/nes_ctrl/suborkey.o
+BUSOBJS += $(BUSOBJ)/nes_ctrl/zapper.o
+endif
+
+#-------------------------------------------------
+#
#@src/emu/bus/snes/snes_slot.h,BUSES += SNES
#-------------------------------------------------
diff --git a/src/emu/bus/nes_ctrl/4score.c b/src/emu/bus/nes_ctrl/4score.c
new file mode 100644
index 00000000000..ef384855612
--- /dev/null
+++ b/src/emu/bus/nes_ctrl/4score.c
@@ -0,0 +1,190 @@
+/**********************************************************************
+
+ Nintendo Entertainment System Four Score Adapter
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+
+ TODO: current implementation is a HACK, due to limitations of the
+ slot system!
+ A real Four Score would be connected to both the controller ports of
+ the NES, but current core cannot emulate something like this until
+ devices can live their own life and being connected to other devices
+ at request.
+ In current implementation the device has to be mounted separately in
+ the two ports and each enables 2 inputs (this is more or less as hacky
+ as the non-slot previous one, where the 4 ports were always available
+ to the emulated system, but it's not a great consolation :( )
+ Two subdevices are currently used so to warn the user that the first
+ one gives P1+P3 inputs and the second one gives P2+P4 inputs.
+ For the same reason, we don't currently emulate the 2P/4P switch,
+ since we could at best have two switches to disable the second player
+ inputs.
+
+ Note: Two Pads are hardcoded in inputs below, instead of acting as
+ passthrough for 2 standard joypad devices, in order to show in the
+ internal UI that they belong to P1+P3 and P2+P4, otherwise they would
+ be listed as P1+P2 and P3+P4 respectively. This *HAS* to be changed
+ once the slot support in the code has improved (4 standard joypads
+ shall be attached to the unit!)
+
+**********************************************************************/
+
+#include "4score.h"
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+const device_type NES_4SCORE_P1P3 = &device_creator<nes_4score_p1p3_device>;
+const device_type NES_4SCORE_P2P4 = &device_creator<nes_4score_p2p4_device>;
+
+
+static INPUT_PORTS_START( nes_4score_p1p3 )
+ PORT_START("PAD1")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("A") PORT_PLAYER(1)
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("B") PORT_PLAYER(1)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_SELECT ) PORT_PLAYER(1)
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_START ) PORT_PLAYER(1)
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_PLAYER(1)
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_PLAYER(1)
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_PLAYER(1)
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(1)
+
+ PORT_START("PAD3")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("A") PORT_PLAYER(3)
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("B") PORT_PLAYER(3)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_SELECT ) PORT_PLAYER(3)
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_START ) PORT_PLAYER(3)
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_PLAYER(3)
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_PLAYER(3)
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_PLAYER(3)
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(3)
+INPUT_PORTS_END
+
+
+static INPUT_PORTS_START( nes_4score_p2p4 )
+ PORT_START("PAD2")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("A") PORT_PLAYER(2)
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("B") PORT_PLAYER(2)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_SELECT ) PORT_PLAYER(2)
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_START ) PORT_PLAYER(2)
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_PLAYER(2)
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_PLAYER(2)
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2)
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2)
+
+ PORT_START("PAD4")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("A") PORT_PLAYER(4)
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("B") PORT_PLAYER(4)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_SELECT ) PORT_PLAYER(4)
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_START ) PORT_PLAYER(4)
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_PLAYER(4)
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_PLAYER(4)
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_PLAYER(4)
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(4)
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor nes_4score_p1p3_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( nes_4score_p1p3 );
+}
+
+ioport_constructor nes_4score_p2p4_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( nes_4score_p2p4 );
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// nes_4score_device - constructor
+//-------------------------------------------------
+
+nes_4score_device::nes_4score_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source)
+ : device_t(mconfig, type, name, tag, owner, clock, shortname, source),
+ device_nes_control_port_interface(mconfig, *this)
+{
+}
+
+nes_4score_p1p3_device::nes_4score_p1p3_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ nes_4score_device(mconfig, NES_4SCORE_P1P3, "Nintendo Four Score Adapter P1/P3", tag, owner, clock, "nes_4score_p1p3", __FILE__),
+ m_joypad1(*this, "PAD1"),
+ m_joypad3(*this, "PAD3")
+{
+}
+
+nes_4score_p2p4_device::nes_4score_p2p4_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ nes_4score_device(mconfig, NES_4SCORE_P2P4, "Nintendo Four Score Adapter P2/P4", tag, owner, clock, "nes_4score_p2p4", __FILE__),
+ m_joypad2(*this, "PAD2"),
+ m_joypad4(*this, "PAD4")
+{
+}
+
+
+//-------------------------------------------------
+// device_start
+//-------------------------------------------------
+
+void nes_4score_device::device_start()
+{
+ save_item(NAME(m_latch));
+}
+
+
+//-------------------------------------------------
+// device_reset
+//-------------------------------------------------
+
+void nes_4score_device::device_reset()
+{
+ m_latch = 0;
+}
+
+
+//-------------------------------------------------
+// read
+//-------------------------------------------------
+
+UINT8 nes_4score_device::read_bit0()
+{
+ UINT8 ret = m_latch & 1;
+ m_latch >>= 1;
+ return ret;
+}
+
+//-------------------------------------------------
+// write
+//-------------------------------------------------
+
+void nes_4score_p1p3_device::write(UINT8 data)
+{
+ if (data & 0x01)
+ return;
+
+ // P3 & P4 inputs in NES Four Score are read serially with P1 & P2
+ m_latch = m_joypad1->read();
+ m_latch |= (m_joypad3->read() << 8); // pad 3
+ m_latch |= (0x08 << 16); // signature
+}
+
+void nes_4score_p2p4_device::write(UINT8 data)
+{
+ if (data & 0x01)
+ return;
+
+ // P3 & P4 inputs in NES Four Score are read serially with P1 & P2
+ m_latch = m_joypad2->read();
+ m_latch |= (m_joypad4->read() << 8); // pad 4
+ m_latch |= (0x04 << 16); // signature
+}
diff --git a/src/emu/bus/nes_ctrl/4score.h b/src/emu/bus/nes_ctrl/4score.h
new file mode 100644
index 00000000000..f7a688fb162
--- /dev/null
+++ b/src/emu/bus/nes_ctrl/4score.h
@@ -0,0 +1,85 @@
+/**********************************************************************
+
+ Nintendo Entertainment System Four Score Adapter
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __NES_FOURSCORE__
+#define __NES_FOURSCORE__
+
+
+#include "emu.h"
+#include "ctrl.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> nes_4score_device
+
+class nes_4score_device : public device_t,
+ public device_nes_control_port_interface
+{
+public:
+ // construction/destruction
+ nes_4score_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source);
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+
+ virtual UINT8 read_bit0();
+
+protected:
+ UINT32 m_latch;
+};
+
+// ======================> nes_4score_p1p3_device
+
+class nes_4score_p1p3_device : public nes_4score_device
+{
+public:
+ // construction/destruction
+ nes_4score_p1p3_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ virtual ioport_constructor device_input_ports() const;
+
+protected:
+ virtual void write(UINT8 data);
+
+private:
+ required_ioport m_joypad1;
+ required_ioport m_joypad3;
+};
+
+// ======================> nes_4score_p2p4_device
+
+class nes_4score_p2p4_device : public nes_4score_device
+{
+public:
+ // construction/destruction
+ nes_4score_p2p4_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ virtual ioport_constructor device_input_ports() const;
+
+protected:
+ virtual void write(UINT8 data);
+
+private:
+ required_ioport m_joypad2;
+ required_ioport m_joypad4;
+};
+
+
+// device type definition
+extern const device_type NES_4SCORE_P1P3;
+extern const device_type NES_4SCORE_P2P4;
+
+
+#endif
diff --git a/src/emu/bus/nes_ctrl/arkpaddle.c b/src/emu/bus/nes_ctrl/arkpaddle.c
new file mode 100644
index 00000000000..61dd183603c
--- /dev/null
+++ b/src/emu/bus/nes_ctrl/arkpaddle.c
@@ -0,0 +1,131 @@
+/**********************************************************************
+
+ Nintendo Family Computer & Entertainment System -
+ Arkanoid Paddle input device
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+#include "arkpaddle.h"
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+const device_type NES_ARKPADDLE = &device_creator<nes_vaus_device>;
+const device_type NES_ARKPADDLE_FC = &device_creator<nes_vausfc_device>;
+
+
+static INPUT_PORTS_START( arkanoid_paddle )
+ PORT_START("PADDLE")
+ PORT_BIT( 0xff, 0x7f, IPT_PADDLE) PORT_SENSITIVITY(25) PORT_KEYDELTA(25) PORT_CENTERDELTA(0) PORT_MINMAX(0x62,0xf2)
+ PORT_START("BUTTON")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("Paddle button")
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor nes_vaus_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( arkanoid_paddle );
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// nes_vaus_device - constructor
+//-------------------------------------------------
+
+nes_vaus_device::nes_vaus_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source)
+ : device_t(mconfig, type, name, tag, owner, clock, shortname, source),
+ device_nes_control_port_interface(mconfig, *this),
+ m_paddle(*this, "PADDLE"),
+ m_button(*this, "BUTTON")
+{
+}
+
+nes_vaus_device::nes_vaus_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ device_t(mconfig, NES_ARKPADDLE, "Arkanoid Vaus NES Controller", tag, owner, clock, "nes_vaus", __FILE__),
+ device_nes_control_port_interface(mconfig, *this),
+ m_paddle(*this, "PADDLE"),
+ m_button(*this, "BUTTON")
+{
+}
+
+nes_vausfc_device::nes_vausfc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ nes_vaus_device(mconfig, NES_ARKPADDLE_FC, "Arkanoid Vaus FC Controller", tag, owner, clock, "nes_vausfc", __FILE__)
+{
+}
+
+
+//-------------------------------------------------
+// device_start
+//-------------------------------------------------
+
+void nes_vaus_device::device_start()
+{
+ save_item(NAME(m_latch));
+ save_item(NAME(m_start_conv));
+}
+
+
+//-------------------------------------------------
+// device_reset
+//-------------------------------------------------
+
+void nes_vaus_device::device_reset()
+{
+ m_latch = 0;
+ m_start_conv = 0;
+}
+
+
+//-------------------------------------------------
+// read
+//-------------------------------------------------
+
+UINT8 nes_vaus_device::read_bit34()
+{
+ UINT8 ret = (m_button->read() << 3);
+ ret |= (m_latch & 0x80) >> 3;
+ m_latch <<= 1;
+ m_latch &= 0xff;
+ return ret;
+}
+
+UINT8 nes_vausfc_device::read_exp(offs_t offset)
+{
+ UINT8 ret = 0;
+ if (offset == 0) //$4016
+ ret = m_button->read() << 1;
+ else //$4017
+ {
+ ret = (m_latch & 0x80) >> 6;
+ m_latch <<= 1;
+ m_latch &= 0xff;
+ }
+ return ret;
+}
+
+//-------------------------------------------------
+// write
+//-------------------------------------------------
+
+void nes_vaus_device::write(UINT8 data)
+{
+ int old = m_start_conv;
+
+ if (data == 0 && old == 1)
+ m_latch = (UINT8) (m_paddle->read() ^ 0xff);
+
+ m_start_conv = data;
+}
diff --git a/src/emu/bus/nes_ctrl/arkpaddle.h b/src/emu/bus/nes_ctrl/arkpaddle.h
new file mode 100644
index 00000000000..a683f3e9904
--- /dev/null
+++ b/src/emu/bus/nes_ctrl/arkpaddle.h
@@ -0,0 +1,71 @@
+/**********************************************************************
+
+ Nintendo Family Computer & Entertainment System -
+ Arkanoid Paddle input device
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __NES_ARKPADDLE__
+#define __NES_ARKPADDLE__
+
+
+#include "emu.h"
+#include "ctrl.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> nes_vaus_device
+
+class nes_vaus_device : public device_t,
+ public device_nes_control_port_interface
+{
+public:
+ // construction/destruction
+ nes_vaus_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source);
+ nes_vaus_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();
+
+ virtual UINT8 read_bit34();
+ virtual void write(UINT8 data);
+
+ required_ioport m_paddle;
+ required_ioport m_button;
+ UINT8 m_start_conv;
+ UINT32 m_latch;
+};
+
+
+// ======================> nes_vaus_device
+
+class nes_vausfc_device : public nes_vaus_device
+{
+public:
+ // construction/destruction
+ nes_vausfc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+protected:
+ virtual UINT8 read_bit34() { return 0; }
+ virtual UINT8 read_exp(offs_t offset);
+};
+
+
+// device type definition
+extern const device_type NES_ARKPADDLE;
+extern const device_type NES_ARKPADDLE_FC;
+
+
+#endif
diff --git a/src/emu/bus/nes_ctrl/bcbattle.c b/src/emu/bus/nes_ctrl/bcbattle.c
new file mode 100644
index 00000000000..403bdeec1ae
--- /dev/null
+++ b/src/emu/bus/nes_ctrl/bcbattle.c
@@ -0,0 +1,193 @@
+/**********************************************************************
+
+ Nintendo Family Computer - 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 Famicom
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+#include "bcbattle.h"
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+const device_type NES_BARCODE_BATTLER = &device_creator<nes_bcbattle_device>;
+
+
+static INPUT_PORTS_START( nes_battler )
+INPUT_PORTS_END
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor nes_bcbattle_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( nes_battler );
+}
+
+MACHINE_CONFIG_FRAGMENT( nes_battler )
+ MCFG_BARCODE_READER_ADD("battler")
+MACHINE_CONFIG_END
+
+machine_config_constructor nes_bcbattle_device::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( nes_battler );
+}
+
+
+//-------------------------------------------------
+// device_timer - handler timer events
+//-------------------------------------------------
+
+void nes_bcbattle_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ if (id == TIMER_BATTLER)
+ {
+ int old = m_new_code;
+ // has something new been scanned?
+ if (old < m_reader->get_pending_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;
+ }
+ m_new_code = m_reader->get_pending_code();
+ }
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// nes_bcbattle_device - constructor
+//-------------------------------------------------
+
+nes_bcbattle_device::nes_bcbattle_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ device_t(mconfig, NES_BARCODE_BATTLER, "Epoch Barcode Battler", tag, owner, clock, "nes_bcbattle", __FILE__),
+ device_nes_control_port_interface(mconfig, *this),
+ m_reader(*this, "battler")
+{
+}
+
+
+//-------------------------------------------------
+// device_start
+//-------------------------------------------------
+
+void nes_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<cpu_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 nes_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 nes_bcbattle_device::read_current_bit()
+{
+ if (m_pending_code && !m_transmitting)
+ {
+ // we start with 1
+ m_transmitting = 1;
+ m_cur_byte = 0;
+ m_cur_bit = 0;
+ return 1;
+ }
+
+ if (m_transmitting)
+ {
+ if (m_cur_bit == 0)
+ {
+ m_cur_bit++;
+ return 1;
+ }
+ if (m_cur_bit < 9)
+ {
+ int bit = (BIT(m_current_barcode[m_cur_byte], m_cur_bit - 1)) ^ 1;
+ m_cur_bit++;
+ return bit;
+ }
+ if (m_cur_bit == 9)
+ {
+ m_cur_bit = 0;
+ //printf("%X ", m_current_barcode[m_cur_byte]);
+ m_cur_byte++;
+ if (m_cur_byte == 20)
+ {
+ m_cur_byte = 0;
+ m_transmitting = 0;
+ m_pending_code = 0;
+ }
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
+UINT8 nes_bcbattle_device::read_exp(offs_t offset)
+{
+ UINT8 ret = 0;
+ if (offset == 1) //$4017
+ {
+ ret |= read_current_bit() << 2;
+ }
+
+ return ret;
+}
diff --git a/src/emu/bus/nes_ctrl/bcbattle.h b/src/emu/bus/nes_ctrl/bcbattle.h
new file mode 100644
index 00000000000..c38c8d54c1b
--- /dev/null
+++ b/src/emu/bus/nes_ctrl/bcbattle.h
@@ -0,0 +1,55 @@
+/**********************************************************************
+
+ Nintendo Family Computer - Epoch Barcode Battler
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __NES_BCBATTLE__
+#define __NES_BCBATTLE__
+
+
+#include "emu.h"
+#include "ctrl.h"
+#include "machine/bcreader.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> nes_bcbattle_device
+
+class nes_bcbattle_device : public device_t,
+ public device_nes_control_port_interface
+{
+public:
+ // construction/destruction
+ nes_bcbattle_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ virtual ioport_constructor device_input_ports() const;
+ 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_exp(offs_t offset);
+ int read_current_bit();
+
+ static const device_timer_id TIMER_BATTLER = 1;
+ required_device<barcode_reader_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;
+};
+
+// device type definition
+extern const device_type NES_BARCODE_BATTLER;
+
+#endif
diff --git a/src/emu/bus/nes_ctrl/ctrl.c b/src/emu/bus/nes_ctrl/ctrl.c
new file mode 100644
index 00000000000..c90b2bf82e5
--- /dev/null
+++ b/src/emu/bus/nes_ctrl/ctrl.c
@@ -0,0 +1,208 @@
+/**********************************************************************
+
+ Nintendo Family Computer & Entertainment System controller ports
+ and Family Computer expansion port emulation
+
+ Here we emulate in fact 3 different kind of ports, which are
+ connected to different bis of memory locations $4016 and $4017:
+ - NES controller ports: these are hooked to bit 0,3,4 of the
+ corresponding address ($4016 for port1, $4017 for port2)
+ - FC controller ports: these are only hooked to bit 0 of the
+ corresponding address (so that e.g. a NES Zapper could not
+ be connected to a later FC AV model, because its inputs
+ would not be detected)
+ - FC expansion port: this is hooked to bits 0-4 of both addresses
+ To make things a little bit more complex, old FC models have the
+ controller hardwired to the unit, and the P2 controllers are
+ directly hooked also to one of the expansion port lines (namely,
+ microphone inputs from P2 go to $4016 bit 2)
+
+ Even if the controller port and the expansion port are
+ physically different (the FC expansion is a 15pin port, while
+ the controller ports are 7pin), we emulate them as variants of a
+ common device, exposing the following handlers:
+ - read_bit0: for bit0 reads, which are typically used for serial
+ inputs from controllers
+ - read_bit34: for bit3,4 reading, expected to be at the correct
+ offset (but we don't currently check for read_bit34 & 0xf8==0)
+ - read_exp: for reads going through the expansion, with a offset
+ parameter to decide whether we are reading from $4016 and $4017
+ - write: to acknowledge writes to $4016
+
+ The driver emulation will take care to only call the correct
+ handlers they have hooks for: Basic usage is that the expansion
+ port calls read_exp, FC ctrl ports call read_bit0, and NES ctrl
+ ports call both read_bit0 and read_bit34. However, to cope with
+ the original FC microphone, we will have the second controller
+ port calling read_exp too.
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+#include "ctrl.h"
+// slot devices
+#include "4score.h"
+#include "arkpaddle.h"
+#include "bcbattle.h"
+#include "ftrainer.h"
+#include "fckeybrd.h"
+#include "hori.h"
+#include "joypad.h"
+#include "konamihs.h"
+#include "miracle.h"
+#include "mjpanel.h"
+#include "pachinko.h"
+#include "partytap.h"
+#include "powerpad.h"
+#include "suborkey.h"
+#include "zapper.h"
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+const device_type NES_CONTROL_PORT = &device_creator<nes_control_port_device>;
+
+
+
+//**************************************************************************
+// CARD INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// device_nes_control_port_interface - constructor
+//-------------------------------------------------
+
+device_nes_control_port_interface::device_nes_control_port_interface(const machine_config &mconfig, device_t &device) :
+ device_slot_card_interface(mconfig, device)
+{
+ m_port = dynamic_cast<nes_control_port_device *>(device.owner());
+}
+
+
+//-------------------------------------------------
+// ~device_nes_control_port_interface - destructor
+//-------------------------------------------------
+
+device_nes_control_port_interface::~device_nes_control_port_interface()
+{
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// nes_control_port_device - constructor
+//-------------------------------------------------
+
+nes_control_port_device::nes_control_port_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ device_t(mconfig, NES_CONTROL_PORT, "Nintendo NES/FC control port", tag, owner, clock, "nes_control_port", __FILE__),
+ device_slot_interface(mconfig, *this)
+{
+}
+
+
+//-------------------------------------------------
+// nes_control_port_device - destructor
+//-------------------------------------------------
+
+nes_control_port_device::~nes_control_port_device()
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void nes_control_port_device::device_start()
+{
+ m_device = dynamic_cast<device_nes_control_port_interface *>(get_card_device());
+ m_brightpixel_cb.bind_relative_to(*owner());
+}
+
+
+UINT8 nes_control_port_device::read_bit0()
+{
+ UINT8 data = 0;
+ if (m_device)
+ data = m_device->read_bit0();
+ return data;
+}
+
+UINT8 nes_control_port_device::read_bit34()
+{
+ UINT8 data = 0;
+ if (m_device)
+ data = m_device->read_bit34();
+ return data;
+}
+
+UINT8 nes_control_port_device::read_exp(offs_t offset)
+{
+ UINT8 data = 0;
+ if (m_device)
+ data = m_device->read_exp(offset);
+ return data;
+}
+
+void nes_control_port_device::write(UINT8 data)
+{
+ if (m_device)
+ m_device->write(data);
+}
+
+
+
+//-------------------------------------------------
+// SLOT_INTERFACE( nes_control_port_devices )
+//-------------------------------------------------
+
+SLOT_INTERFACE_START( nes_control_port1_devices )
+ SLOT_INTERFACE("joypad", NES_JOYPAD)
+ SLOT_INTERFACE("zapper", NES_ZAPPER)
+ SLOT_INTERFACE("4score_p1p3", NES_4SCORE_P1P3)
+// SLOT_INTERFACE("miracle_piano", NES_MIRACLE)
+SLOT_INTERFACE_END
+
+SLOT_INTERFACE_START( nes_control_port2_devices )
+ SLOT_INTERFACE("joypad", NES_JOYPAD)
+ SLOT_INTERFACE("zapper", NES_ZAPPER)
+ SLOT_INTERFACE("vaus", NES_ARKPADDLE)
+ SLOT_INTERFACE("powerpad", NES_POWERPAD)
+ SLOT_INTERFACE("4score_p2p4", NES_4SCORE_P2P4)
+SLOT_INTERFACE_END
+
+SLOT_INTERFACE_START( fc_control_port1_devices )
+ SLOT_INTERFACE("joypad", NES_JOYPAD)
+ SLOT_INTERFACE("ccpad_left", NES_CCPAD_LEFT)
+SLOT_INTERFACE_END
+
+SLOT_INTERFACE_START( fc_control_port2_devices )
+ SLOT_INTERFACE("joypad", NES_JOYPAD)
+ SLOT_INTERFACE("joypad_old", NES_FCPAD_P2)
+ SLOT_INTERFACE("ccpad_right", NES_CCPAD_RIGHT)
+SLOT_INTERFACE_END
+
+SLOT_INTERFACE_START( fc_expansion_devices )
+ SLOT_INTERFACE("joypad", NES_JOYPAD)
+ SLOT_INTERFACE("arcstick", NES_ARCSTICK)
+ SLOT_INTERFACE("fc_keyboard", NES_FCKEYBOARD)
+ SLOT_INTERFACE("zapper", NES_ZAPPER)
+ SLOT_INTERFACE("vaus", NES_ARKPADDLE_FC)
+ SLOT_INTERFACE("family_trainer", NES_FTRAINER)
+ SLOT_INTERFACE("konamihs", NES_KONAMIHS)
+ SLOT_INTERFACE("mj_panel", NES_MJPANEL)
+ SLOT_INTERFACE("pachinko", NES_PACHINKO)
+ SLOT_INTERFACE("partytap", NES_PARTYTAP)
+ SLOT_INTERFACE("hori_twin", NES_HORITWIN)
+ SLOT_INTERFACE("hori_4p", NES_HORI4P)
+ SLOT_INTERFACE("barcode_battler", NES_BARCODE_BATTLER)
+ SLOT_INTERFACE("subor_keyboard", NES_SUBORKEYBOARD)
+SLOT_INTERFACE_END
diff --git a/src/emu/bus/nes_ctrl/ctrl.h b/src/emu/bus/nes_ctrl/ctrl.h
new file mode 100644
index 00000000000..a87b3c9dc9f
--- /dev/null
+++ b/src/emu/bus/nes_ctrl/ctrl.h
@@ -0,0 +1,104 @@
+/**********************************************************************
+
+ Nintendo Family Computer & Entertainment System controller port
+ emulation
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************
+
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __NES_CONTROL_PORT__
+#define __NES_CONTROL_PORT__
+
+#include "emu.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class nes_control_port_device;
+
+// ======================> device_nes_control_port_interface
+
+class device_nes_control_port_interface : public device_slot_card_interface
+{
+public:
+ // construction/destruction
+ device_nes_control_port_interface(const machine_config &mconfig, device_t &device);
+ virtual ~device_nes_control_port_interface();
+
+ virtual UINT8 read_bit0() { return 0; };
+ virtual UINT8 read_bit34() { return 0; };
+ virtual UINT8 read_exp(offs_t offset) { return 0; };
+ virtual void write(UINT8 data) { };
+
+protected:
+ nes_control_port_device *m_port;
+};
+
+
+typedef device_delegate<bool (int x, int y)> nesctrl_brightpixel_delegate;
+#define NESCTRL_BRIGHTPIXEL_CB(name) bool name(int x, int y)
+
+
+// ======================> nes_control_port_device
+
+class nes_control_port_device : public device_t,
+ public device_slot_interface
+{
+public:
+ // construction/destruction
+ nes_control_port_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+ virtual ~nes_control_port_device();
+
+ static void set_brightpixel_callback(device_t &device, nesctrl_brightpixel_delegate callback) { downcast<nes_control_port_device &>(device).m_brightpixel_cb = callback; }
+
+ UINT8 read_bit0();
+ UINT8 read_bit34();
+ UINT8 read_exp(offs_t offset);
+ void write(UINT8 data);
+
+ nesctrl_brightpixel_delegate m_brightpixel_cb;
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ device_nes_control_port_interface *m_device;
+};
+
+
+// device type definition
+extern const device_type NES_CONTROL_PORT;
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_NES_CONTROL_PORT_ADD(_tag, _slot_intf, _def_slot) \
+ MCFG_DEVICE_ADD(_tag, NES_CONTROL_PORT, 0) \
+ MCFG_DEVICE_SLOT_INTERFACE(_slot_intf, _def_slot, false)
+
+// currently this is emulated as a control port...
+#define MCFG_FC_EXPANSION_PORT_ADD(_tag, _slot_intf, _def_slot) \
+ MCFG_DEVICE_ADD(_tag, NES_CONTROL_PORT, 0) \
+ MCFG_DEVICE_SLOT_INTERFACE(_slot_intf, _def_slot, false)
+
+#define MCFG_NESCTRL_BRIGHTPIXEL_CB(_class, _method) \
+ nes_control_port_device::set_brightpixel_callback(*device, nesctrl_brightpixel_delegate(&_class::_method, #_class "::" #_method, downcast<_class *>(owner)));
+
+
+SLOT_INTERFACE_EXTERN( nes_control_port1_devices );
+SLOT_INTERFACE_EXTERN( nes_control_port2_devices );
+SLOT_INTERFACE_EXTERN( fc_control_port1_devices );
+SLOT_INTERFACE_EXTERN( fc_control_port2_devices );
+SLOT_INTERFACE_EXTERN( fc_expansion_devices );
+
+
+#endif
diff --git a/src/emu/bus/nes_ctrl/fckeybrd.c b/src/emu/bus/nes_ctrl/fckeybrd.c
new file mode 100644
index 00000000000..f31fc04e848
--- /dev/null
+++ b/src/emu/bus/nes_ctrl/fckeybrd.c
@@ -0,0 +1,232 @@
+/**********************************************************************
+
+ Nintendo Family Computer Keyboard Component
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+#include "fckeybrd.h"
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+const device_type NES_FCKEYBOARD = &device_creator<nes_fckeybrd_device>;
+
+
+static INPUT_PORTS_START( fc_keyboard )
+ PORT_START("FCKEY.0")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F8) PORT_CHAR(UCHAR_MAMEKEY(F8))
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR('[')
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR(']')
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Kana")
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_RSHIFT)
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_BACKSLASH2) PORT_CHAR('\\')
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Stop") PORT_CODE(KEYCODE_BACKSPACE)
+
+ PORT_START("FCKEY.1")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F7) PORT_CHAR(UCHAR_MAMEKEY(F7))
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('@')
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_COLON) PORT_CHAR(':')
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(';')
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CHAR('_')
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CHAR('/')
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-')
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('^')
+
+ PORT_START("FCKEY.2")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F6) PORT_CHAR(UCHAR_MAMEKEY(F6))
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_O) PORT_CHAR('O')
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_L) PORT_CHAR('L')
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_K) PORT_CHAR('K')
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.')
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',')
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_P) PORT_CHAR('P')
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_0) PORT_CHAR('0')
+
+ PORT_START("FCKEY.3")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F5) PORT_CHAR(UCHAR_MAMEKEY(F5))
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_I) PORT_CHAR('I')
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_U) PORT_CHAR('U')
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_J) PORT_CHAR('J')
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_M) PORT_CHAR('M')
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_N) PORT_CHAR('N')
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_9) PORT_CHAR('9')
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_8) PORT_CHAR('8')
+
+ PORT_START("FCKEY.4")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F4) PORT_CHAR(UCHAR_MAMEKEY(F4))
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Y) PORT_CHAR('Y')
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_G) PORT_CHAR('G')
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_H) PORT_CHAR('H')
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_B) PORT_CHAR('B')
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_V) PORT_CHAR('V')
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_7) PORT_CHAR('7')
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_6) PORT_CHAR('6')
+
+ PORT_START("FCKEY.5")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F3) PORT_CHAR(UCHAR_MAMEKEY(F3))
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_T) PORT_CHAR('T')
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_R) PORT_CHAR('R')
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_D) PORT_CHAR('D')
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F) PORT_CHAR('F')
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_C) PORT_CHAR('C')
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_5) PORT_CHAR('5')
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_4) PORT_CHAR('4')
+
+ PORT_START("FCKEY.6")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F2) PORT_CHAR(UCHAR_MAMEKEY(F2))
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_W) PORT_CHAR('W')
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_S) PORT_CHAR('S')
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_A) PORT_CHAR('A')
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_X) PORT_CHAR('X')
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Z) PORT_CHAR('Z')
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_E) PORT_CHAR('E')
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_3) PORT_CHAR('3')
+
+ PORT_START("FCKEY.7")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F1) PORT_CHAR(UCHAR_MAMEKEY(F1))
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_TAB) PORT_CHAR(UCHAR_MAMEKEY(ESC))
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Q) PORT_CHAR('Q')
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_LCONTROL) PORT_CHAR(UCHAR_SHIFT_2)
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_SHIFT_1)
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Grph") PORT_CODE(KEYCODE_LALT)
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_1) PORT_CHAR('1')
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_2) PORT_CHAR('2')
+
+ PORT_START("FCKEY.8")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Clr")
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP))
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT))
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT))
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN))
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Del") PORT_CODE(KEYCODE_DEL)
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Ins") PORT_CODE(KEYCODE_INSERT)
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor nes_fckeybrd_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( fc_keyboard );
+}
+
+
+static MACHINE_CONFIG_FRAGMENT( fc_keyboard )
+ MCFG_CASSETTE_ADD("tape")
+ MCFG_CASSETTE_DEFAULT_STATE(CASSETTE_STOPPED | CASSETTE_MOTOR_ENABLED | CASSETTE_SPEAKER_ENABLED)
+ MCFG_CASSETTE_INTERFACE("fc_cass")
+MACHINE_CONFIG_END
+
+
+//-------------------------------------------------
+// machine_config_additions - device-specific
+// machine configurations
+//-------------------------------------------------
+
+machine_config_constructor nes_fckeybrd_device::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( fc_keyboard );
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// nes_fckeybrd_device - constructor
+//-------------------------------------------------
+
+nes_fckeybrd_device::nes_fckeybrd_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ device_t(mconfig, NES_FCKEYBOARD, "Nintendo Family Computer Keyboard Component", tag, owner, clock, "nes_fckeybrd", __FILE__),
+ device_nes_control_port_interface(mconfig, *this),
+ m_cassette(*this, "tape"),
+ m_kbd(*this, "FCKEY")
+{
+}
+
+
+//-------------------------------------------------
+// device_start
+//-------------------------------------------------
+
+void nes_fckeybrd_device::device_start()
+{
+ save_item(NAME(m_fck_scan));
+ save_item(NAME(m_fck_mode));
+}
+
+
+//-------------------------------------------------
+// device_reset
+//-------------------------------------------------
+
+void nes_fckeybrd_device::device_reset()
+{
+ m_fck_scan = 0;
+ m_fck_mode = 0;
+}
+
+
+//-------------------------------------------------
+// read
+//-------------------------------------------------
+
+UINT8 nes_fckeybrd_device::read_exp(offs_t offset)
+{
+ UINT8 ret = 0;
+ if (offset == 0) //$4016
+ {
+ // FC Keyboard: tape input
+ if ((m_cassette->get_state() & CASSETTE_MASK_UISTATE) == CASSETTE_PLAY)
+ {
+ double level = m_cassette->input();
+ if (level < 0)
+ ret |= 0x00;
+ else
+ ret |= 0x02;
+ }
+ }
+ else //$4017
+ {
+ // FC Keyboard: rows of the keyboard matrix are read 4-bits at time and returned as bit1->bit4
+ if (m_fck_scan < 9)
+ ret |= ~(((m_kbd[m_fck_scan]->read() >> (m_fck_mode * 4)) & 0x0f) << 1) & 0x1e;
+ else
+ ret |= 0x1e;
+ }
+
+ return ret;
+}
+
+//-------------------------------------------------
+// write
+//-------------------------------------------------
+
+void nes_fckeybrd_device::write(UINT8 data)
+{
+ // tape output (not fully tested)
+ if ((m_cassette->get_state() & CASSETTE_MASK_UISTATE) == CASSETTE_RECORD)
+ m_cassette->output(((data & 0x07) == 0x07) ? +1.0 : -1.0);
+
+ if (BIT(data, 2)) // keyboard active
+ {
+ UINT8 out = BIT(data, 1); // scan
+
+ if (m_fck_mode && !out && ++m_fck_scan > 9)
+ m_fck_scan = 0;
+
+ m_fck_mode = out; // access lower or upper 4 bits
+
+ if (BIT(data, 0)) // reset
+ m_fck_scan = 0;
+ }
+}
diff --git a/src/emu/bus/nes_ctrl/fckeybrd.h b/src/emu/bus/nes_ctrl/fckeybrd.h
new file mode 100644
index 00000000000..df265370fff
--- /dev/null
+++ b/src/emu/bus/nes_ctrl/fckeybrd.h
@@ -0,0 +1,55 @@
+/**********************************************************************
+
+ Nintendo Family Computer Keyboard Component
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __NES_FCKEYBRD__
+#define __NES_FCKEYBRD__
+
+
+#include "emu.h"
+#include "ctrl.h"
+#include "imagedev/cassette.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> nes_fckeybrd_device
+
+class nes_fckeybrd_device : public device_t,
+ public device_nes_control_port_interface
+{
+public:
+ // construction/destruction
+ nes_fckeybrd_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ 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();
+
+ virtual UINT8 read_exp(offs_t offset);
+ virtual void write(UINT8 data);
+
+private:
+ required_device<cassette_image_device> m_cassette;
+ required_ioport_array<9> m_kbd;
+ UINT8 m_fck_scan, m_fck_mode;
+};
+
+
+// device type definition
+extern const device_type NES_FCKEYBOARD;
+
+
+#endif
diff --git a/src/emu/bus/nes_ctrl/ftrainer.c b/src/emu/bus/nes_ctrl/ftrainer.c
new file mode 100644
index 00000000000..38fdc326ed6
--- /dev/null
+++ b/src/emu/bus/nes_ctrl/ftrainer.c
@@ -0,0 +1,154 @@
+/**********************************************************************
+
+ Nintendo Family Computer - Bandai Family Trainer Mat
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+#include "ftrainer.h"
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+const device_type NES_FTRAINER = &device_creator<nes_ftrainer_device>;
+
+
+static INPUT_PORTS_START( nes_joypad )
+ PORT_START("LAYOUT")
+ PORT_CONFNAME( 0x01, 0x00, "Family Trainer Button Layout")
+ PORT_CONFSETTING( 0x00, "Side A" )
+ PORT_CONFSETTING( 0x01, "Side B" )
+
+ // difference between the two sides is that we mirror the key mapping to match the real pad layout!
+ PORT_START("FT_COL.0")
+ // side A layout
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer Mid1") PORT_CODE(KEYCODE_J) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
+ // side B layout
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer 12") PORT_CODE(KEYCODE_M) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer 8") PORT_CODE(KEYCODE_J) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer 4") PORT_CODE(KEYCODE_U) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
+
+ PORT_START("FT_COL.1")
+ // side A layout
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer Low1") PORT_CODE(KEYCODE_N) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer Mid2") PORT_CODE(KEYCODE_H) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer Top1") PORT_CODE(KEYCODE_Y) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
+ // side B layout
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer 11") PORT_CODE(KEYCODE_N) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer 7") PORT_CODE(KEYCODE_H) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer 3") PORT_CODE(KEYCODE_Y) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
+
+ PORT_START("FT_COL.2")
+ // side A layout
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer Low2") PORT_CODE(KEYCODE_B) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer Mid3") PORT_CODE(KEYCODE_G) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer Top2") PORT_CODE(KEYCODE_T) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
+ // side B layout
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer 10") PORT_CODE(KEYCODE_B) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer 6") PORT_CODE(KEYCODE_G) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer 2") PORT_CODE(KEYCODE_T) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
+
+ PORT_START("FT_COL.3")
+ // side A layout
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer Mid4") PORT_CODE(KEYCODE_F) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
+ // side B layout
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer 9") PORT_CODE(KEYCODE_V) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer 5") PORT_CODE(KEYCODE_F) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer 1") PORT_CODE(KEYCODE_R) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor nes_ftrainer_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( nes_joypad );
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// nes_ftrainer_device - constructor
+//-------------------------------------------------
+
+nes_ftrainer_device::nes_ftrainer_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ device_t(mconfig, NES_FTRAINER, "Bandai Family Trainer", tag, owner, clock, "nes_famtrain", __FILE__),
+ device_nes_control_port_interface(mconfig, *this),
+ m_trainer(*this, "FT_COL")
+{
+}
+
+
+//-------------------------------------------------
+// device_start
+//-------------------------------------------------
+
+void nes_ftrainer_device::device_start()
+{
+ save_item(NAME(m_row_scan));
+}
+
+
+//-------------------------------------------------
+// device_reset
+//-------------------------------------------------
+
+void nes_ftrainer_device::device_reset()
+{
+ m_row_scan = 0;
+}
+
+
+//-------------------------------------------------
+// read
+//-------------------------------------------------
+
+UINT8 nes_ftrainer_device::read_exp(offs_t offset)
+{
+ UINT8 ret = 0;
+ if (offset == 1) //$4017
+ {
+ if (!BIT(m_row_scan, 0))
+ {
+ // read low line: buttons 9,10,11,12
+ for (int i = 0; i < 4; i++)
+ ret |= ((m_trainer[i]->read() & 0x01) << (1 + i));
+ }
+ else if (!BIT(m_row_scan, 1))
+ {
+ // read mid line: buttons 5,6,7,8
+ for (int i = 0; i < 4; i++)
+ ret |= ((m_trainer[i]->read() & 0x02) << (1 + i));
+ }
+ else if (!BIT(m_row_scan, 2))
+ {
+ // read high line: buttons 1,2,3,4
+ for (int i = 0; i < 4; i++)
+ ret |= ((m_trainer[i]->read() & 0x04) << (1 + i));
+ }
+ }
+ return ret;
+}
+
+//-------------------------------------------------
+// write
+//-------------------------------------------------
+
+void nes_ftrainer_device::write(UINT8 data)
+{
+ // select row to scan
+ m_row_scan = data & 0x07;
+}
diff --git a/src/emu/bus/nes_ctrl/ftrainer.h b/src/emu/bus/nes_ctrl/ftrainer.h
new file mode 100644
index 00000000000..52c3ae0529c
--- /dev/null
+++ b/src/emu/bus/nes_ctrl/ftrainer.h
@@ -0,0 +1,52 @@
+/**********************************************************************
+
+ Nintendo Family Computer - Bandai Family Trainer Mat
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __NES_FTRAINER__
+#define __NES_FTRAINER__
+
+
+#include "emu.h"
+#include "ctrl.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> nes_ftrainer_device
+
+class nes_ftrainer_device : public device_t,
+ public device_nes_control_port_interface
+{
+public:
+ // construction/destruction
+ nes_ftrainer_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ virtual ioport_constructor device_input_ports() const;
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+
+ virtual UINT8 read_exp(offs_t offset);
+ virtual void write(UINT8 data);
+
+private:
+ required_ioport_array<4> m_trainer;
+ UINT8 m_row_scan;
+};
+
+
+// device type definition
+extern const device_type NES_FTRAINER;
+
+
+#endif
diff --git a/src/emu/bus/nes_ctrl/hori.c b/src/emu/bus/nes_ctrl/hori.c
new file mode 100644
index 00000000000..e9d48a98bf3
--- /dev/null
+++ b/src/emu/bus/nes_ctrl/hori.c
@@ -0,0 +1,169 @@
+/**********************************************************************
+
+ Nintendo Family Computer Hori Twin (and 4P?) adapters
+
+ Emulation of the 4Players adapter is quite pointless: if 2P mode
+ (default mode) it behaves like a Hori Twin adapter, in 4P mode
+ it has P1 and P2 inputs overwriting the inputs coming from the
+ main controllers (possibly creating a bit of confusion, since
+ you get 6 sets of inputs with only 4 acknowledged by the running
+ system).
+ For the moment we keep it available for documentation purposes.
+
+ TODO: find out confirmation whether in 2P mode, inputs from joypads
+ connected to the 4players adapter are really seen as P3 and P4 inputs.
+ it seems the most reasonable setup (so that users with only 2
+ external pads can use the adapter in 4P games), but one never knows...
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+#include "hori.h"
+#include "joypad.h"
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+const device_type NES_HORITWIN = &device_creator<nes_horitwin_device>;
+const device_type NES_HORI4P = &device_creator<nes_hori4p_device>;
+
+
+static INPUT_PORTS_START( nes_hori4p )
+ PORT_START("CONFIG")
+ PORT_CONFNAME( 0x01, 0x00, "4 Players / 2 Players")
+ PORT_CONFSETTING( 0x00, "2 Players" )
+ PORT_CONFSETTING( 0x01, "4 Players" )
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor nes_hori4p_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( nes_hori4p );
+}
+
+
+static SLOT_INTERFACE_START( hori_adapter )
+ SLOT_INTERFACE("joypad", NES_JOYPAD)
+SLOT_INTERFACE_END
+
+static MACHINE_CONFIG_FRAGMENT( horitwin )
+ MCFG_FC_EXPANSION_PORT_ADD("port1", hori_adapter, "joypad")
+ MCFG_FC_EXPANSION_PORT_ADD("port2", hori_adapter, "joypad")
+MACHINE_CONFIG_END
+
+static MACHINE_CONFIG_FRAGMENT( hori4p )
+ MCFG_FC_EXPANSION_PORT_ADD("port1", hori_adapter, "joypad")
+ MCFG_FC_EXPANSION_PORT_ADD("port2", hori_adapter, "joypad")
+ MCFG_FC_EXPANSION_PORT_ADD("port3", hori_adapter, "joypad")
+ MCFG_FC_EXPANSION_PORT_ADD("port4", hori_adapter, "joypad")
+MACHINE_CONFIG_END
+
+
+//-------------------------------------------------
+// machine_config_additions - device-specific
+// machine configurations
+//-------------------------------------------------
+
+machine_config_constructor nes_horitwin_device::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( horitwin );
+}
+
+machine_config_constructor nes_hori4p_device::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( hori4p );
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// nes_horitwin_device - constructor
+//-------------------------------------------------
+
+nes_horitwin_device::nes_horitwin_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ device_t(mconfig, NES_HORITWIN, "Hori Twin Adapter", tag, owner, clock, "nes_horitwin", __FILE__),
+ device_nes_control_port_interface(mconfig, *this),
+ m_port1(*this, "port1"),
+ m_port2(*this, "port2")
+{
+}
+
+nes_hori4p_device::nes_hori4p_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ device_t(mconfig, NES_HORI4P, "Hori 4P Adapter", tag, owner, clock, "nes_hori4p", __FILE__),
+ device_nes_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")
+{
+}
+
+
+//-------------------------------------------------
+// read
+//-------------------------------------------------
+
+UINT8 nes_horitwin_device::read_exp(offs_t offset)
+{
+ UINT8 ret = 0;
+ if (offset == 0) //$4016
+ ret |= (m_port1->read_bit0() << 1);
+ else //$4017
+ ret |= (m_port2->read_bit0() << 1);
+ return ret;
+}
+
+UINT8 nes_hori4p_device::read_exp(offs_t offset)
+{
+ UINT8 ret = 0;
+ if (m_cfg->read() == 0) // 2P
+ {
+ if (offset == 0) //$4016
+ ret |= (m_port1->read_bit0() << 1);
+ else //$4017
+ ret |= (m_port2->read_bit0() << 1);
+ }
+ else // 4P
+ {
+ if (offset == 0) //$4016
+ {
+ ret |= (m_port1->read_bit0() << 0);
+ ret |= (m_port3->read_bit0() << 1);
+ }
+ else //$4017
+ {
+ ret |= (m_port2->read_bit0() << 0);
+ ret |= (m_port4->read_bit0() << 1);
+ }
+ }
+ return ret;
+}
+
+//-------------------------------------------------
+// write
+//-------------------------------------------------
+
+void nes_horitwin_device::write(UINT8 data)
+{
+ m_port1->write(data);
+ m_port2->write(data);
+}
+
+void nes_hori4p_device::write(UINT8 data)
+{
+ m_port1->write(data);
+ m_port2->write(data);
+ m_port3->write(data);
+ m_port4->write(data);
+}
diff --git a/src/emu/bus/nes_ctrl/hori.h b/src/emu/bus/nes_ctrl/hori.h
new file mode 100644
index 00000000000..15601a7cc8e
--- /dev/null
+++ b/src/emu/bus/nes_ctrl/hori.h
@@ -0,0 +1,79 @@
+/**********************************************************************
+
+ Nintendo Family Computer Hori Twin (and 4P?) adapters
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __NES_HORI__
+#define __NES_HORI__
+
+
+#include "emu.h"
+#include "ctrl.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> nes_horitwin_device
+
+class nes_horitwin_device : public device_t,
+ public device_nes_control_port_interface
+{
+public:
+ // construction/destruction
+ nes_horitwin_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ virtual machine_config_constructor device_mconfig_additions() const;
+
+protected:
+ // device-level overrides
+ virtual void device_start() {}
+
+ virtual UINT8 read_exp(offs_t offset);
+ virtual void write(UINT8 data);
+
+private:
+ required_device<nes_control_port_device> m_port1;
+ required_device<nes_control_port_device> m_port2;
+};
+
+// ======================> nes_hori4p_device
+
+class nes_hori4p_device : public device_t,
+ public device_nes_control_port_interface
+{
+public:
+ // construction/destruction
+ nes_hori4p_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ virtual ioport_constructor device_input_ports() const;
+ virtual machine_config_constructor device_mconfig_additions() const;
+
+protected:
+ // device-level overrides
+ virtual void device_start() {}
+
+ virtual UINT8 read_exp(offs_t offset);
+ virtual void write(UINT8 data);
+
+private:
+ required_device<nes_control_port_device> m_port1;
+ required_device<nes_control_port_device> m_port2;
+ required_device<nes_control_port_device> m_port3;
+ required_device<nes_control_port_device> m_port4;
+ required_ioport m_cfg;
+};
+
+
+// device type definition
+extern const device_type NES_HORITWIN;
+extern const device_type NES_HORI4P;
+
+
+#endif
diff --git a/src/emu/bus/nes_ctrl/joypad.c b/src/emu/bus/nes_ctrl/joypad.c
new file mode 100644
index 00000000000..2688e5e61e5
--- /dev/null
+++ b/src/emu/bus/nes_ctrl/joypad.c
@@ -0,0 +1,317 @@
+/**********************************************************************
+
+ Nintendo Family Computer & Entertainment System Joypads
+
+ The original Famicom had two hardwired controller, with the second
+ controller slightly different from the first one: it featured no
+ Start nor Select buttons, but had a built-in microphone (with
+ very limited capabilities, since it basically only detected two
+ states: something blowing into it / nothing blowing into it) for
+ some games to react to users "talking" into it
+
+ Crazy Climber Pads are not really a kind of separate controllers,
+ but just a couple of small sticks to be put on top of d-pads of
+ the regular controllers. Users should then control the game by
+ using both controllers, turned 90 degrees, as a couple of dual
+ sticks like in the arcade control panel. However, we emulate them
+ separately so to map the controls to a friendlier default.
+
+ The Arcade Stick we emulate is a controller (apparently manufactured
+ by Hori, but possibly licensed by Nintendo, since it use the official
+ logo and brand) which fits into the expansion port and allows to
+ daisy chain a second controller to the first one, to play 4players
+ game (an image of such connection is shown e.g. in Nekketsu Koukou
+ Dodgeball Bu manual)
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+#include "joypad.h"
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+const device_type NES_JOYPAD = &device_creator<nes_joypad_device>;
+const device_type NES_FCPAD_P2 = &device_creator<nes_fcpad2_device>;
+const device_type NES_CCPAD_LEFT = &device_creator<nes_ccpadl_device>;
+const device_type NES_CCPAD_RIGHT = &device_creator<nes_ccpadr_device>;
+const device_type NES_ARCSTICK = &device_creator<nes_arcstick_device>;
+
+
+static INPUT_PORTS_START( nes_joypad )
+ PORT_START("JOYPAD")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("A")
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("B")
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_SELECT )
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_START )
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_8WAY
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_8WAY
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_8WAY
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_8WAY
+INPUT_PORTS_END
+
+static INPUT_PORTS_START( nes_fcpad_p2 )
+ PORT_START("JOYPAD")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("A")
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("B")
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_SELECT ) PORT_NAME("Microphone")
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNUSED )
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_8WAY
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_8WAY
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_8WAY
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_8WAY
+INPUT_PORTS_END
+
+static INPUT_PORTS_START( nes_ccpad_left )
+ PORT_START("JOYPAD")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED )
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_UNUSED )
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_SELECT )
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_START )
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_RIGHT ) PORT_8WAY
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_LEFT ) PORT_8WAY
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_UP ) PORT_8WAY
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_DOWN ) PORT_8WAY
+INPUT_PORTS_END
+
+static INPUT_PORTS_START( nes_ccpad_right )
+ PORT_START("JOYPAD")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED )
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_UNUSED )
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNUSED )
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNUSED )
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_JOYSTICKRIGHT_RIGHT ) PORT_8WAY
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICKRIGHT_LEFT ) PORT_8WAY
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICKRIGHT_UP ) PORT_8WAY
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICKRIGHT_DOWN ) PORT_8WAY
+INPUT_PORTS_END
+
+static INPUT_PORTS_START( nes_arcstick )
+ PORT_START("CONFIG")
+ PORT_CONFNAME( 0x01, 0x01, "4 Way / 8 Way Joystick")
+ PORT_CONFSETTING( 0x00, "4 Way" )
+ PORT_CONFSETTING( 0x01, "8 Way" )
+ PORT_CONFNAME( 0x02, 0x00, "Player ID")
+ PORT_CONFSETTING( 0x00, "Player I" )
+ PORT_CONFSETTING( 0x02, "Player II" )
+
+ PORT_START("JOYPAD")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("A")
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("B")
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_SELECT )
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_START )
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_8WAY PORT_CONDITION("CONFIG", 0x01, EQUALS, 0x01)
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_CONDITION("CONFIG", 0x01, EQUALS, 0x01)
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_CONDITION("CONFIG", 0x01, EQUALS, 0x01)
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_CONDITION("CONFIG", 0x01, EQUALS, 0x01)
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_4WAY PORT_CONDITION("CONFIG", 0x01, EQUALS, 0x00)
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_4WAY PORT_CONDITION("CONFIG", 0x01, EQUALS, 0x00)
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_4WAY PORT_CONDITION("CONFIG", 0x01, EQUALS, 0x00)
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_4WAY PORT_CONDITION("CONFIG", 0x01, EQUALS, 0x00)
+INPUT_PORTS_END
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor nes_joypad_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( nes_joypad );
+}
+
+ioport_constructor nes_fcpad2_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( nes_fcpad_p2 );
+}
+
+ioport_constructor nes_ccpadl_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( nes_ccpad_left );
+}
+
+ioport_constructor nes_ccpadr_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( nes_ccpad_right );
+}
+
+ioport_constructor nes_arcstick_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( nes_arcstick );
+}
+
+
+
+static SLOT_INTERFACE_START( arcstick_daisy )
+ SLOT_INTERFACE("arcstick", NES_ARCSTICK)
+SLOT_INTERFACE_END
+
+static MACHINE_CONFIG_FRAGMENT( arcstick )
+ // expansion port to allow daisy chaining
+ MCFG_FC_EXPANSION_PORT_ADD("subexp", arcstick_daisy, NULL)
+MACHINE_CONFIG_END
+
+
+//-------------------------------------------------
+// machine_config_additions - device-specific
+// machine configurations
+//-------------------------------------------------
+
+machine_config_constructor nes_arcstick_device::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( arcstick );
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// nes_joypad_device - constructor
+//-------------------------------------------------
+
+nes_joypad_device::nes_joypad_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) :
+ device_t(mconfig, type, name, tag, owner, clock, shortname, source),
+ device_nes_control_port_interface(mconfig, *this),
+ m_joypad(*this, "JOYPAD")
+{
+}
+
+nes_joypad_device::nes_joypad_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ device_t(mconfig, NES_JOYPAD, "Nintendo NES / FC Control Pad", tag, owner, clock, "nes_joypad", __FILE__),
+ device_nes_control_port_interface(mconfig, *this),
+ m_joypad(*this, "JOYPAD")
+{
+}
+
+nes_fcpad2_device::nes_fcpad2_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ nes_joypad_device(mconfig, NES_FCPAD_P2, "Nintendo Family Computer P2 Pad", tag, owner, clock, "nes_fcpad2", __FILE__)
+{
+}
+
+nes_ccpadl_device::nes_ccpadl_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ nes_joypad_device(mconfig, NES_CCPAD_LEFT, "Crazy Climber Left Pad", tag, owner, clock, "nes_ccpadl", __FILE__)
+{
+}
+
+nes_ccpadr_device::nes_ccpadr_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ nes_joypad_device(mconfig, NES_CCPAD_RIGHT, "Crazy Climber Right Pad", tag, owner, clock, "nes_ccpadr", __FILE__)
+{
+}
+
+nes_arcstick_device::nes_arcstick_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ nes_joypad_device(mconfig, NES_ARCSTICK, "Nintendo Family Computer Arcade Stick", tag, owner, clock, "nes_arcstick", __FILE__),
+ m_daisychain(*this, "subexp"),
+ m_cfg(*this, "CONFIG")
+{
+}
+
+
+//-------------------------------------------------
+// device_start
+//-------------------------------------------------
+
+void nes_joypad_device::device_start()
+{
+ save_item(NAME(m_latch));
+}
+
+
+//-------------------------------------------------
+// device_reset
+//-------------------------------------------------
+
+void nes_joypad_device::device_reset()
+{
+ m_latch = 0;
+}
+
+
+//-------------------------------------------------
+// read
+//-------------------------------------------------
+
+UINT8 nes_joypad_device::read_bit0()
+{
+ UINT8 ret = m_latch & 1;
+ m_latch >>= 1;
+ return ret;
+}
+
+UINT8 nes_fcpad2_device::read_exp(offs_t offset)
+{
+ UINT8 ret = 0;
+ if (!offset) // microphone input
+ ret |= m_joypad->read() & 0x04;
+
+ return ret;
+}
+
+// NOTE: I haven't found any documentation about what happens when
+// users connect two arcade stick both set as P1 or P2 in config.
+// does the FC only acknowledge the first one, or do they conflict
+// with each other? currently, we only support the following setup:
+// if the first pad is set as P1, the daisy chained pad is checked
+// for P2 only, and vice versa.
+UINT8 nes_arcstick_device::read_exp(offs_t offset)
+{
+ UINT8 ret = 0;
+ if (offset == 0) //$4016
+ {
+ if ((m_cfg->read() & 2) == 0) // we are P1 input
+ {
+ ret |= (m_latch & 1) << 1;
+ m_latch >>= 1;
+ }
+ else
+ ret |= m_daisychain->read_exp(0);
+ }
+ else //$4017
+ {
+ if ((m_cfg->read() & 2) == 2) // we are P2 input
+ {
+ ret |= (m_latch & 1) << 1;
+ m_latch >>= 1;
+ }
+ else
+ ret |= m_daisychain->read_exp(1);
+ }
+
+ return ret;
+}
+
+//-------------------------------------------------
+// write
+//-------------------------------------------------
+
+void nes_joypad_device::write(UINT8 data)
+{
+ if (data & 0x01)
+ return;
+
+ m_latch = m_joypad->read();
+}
+
+void nes_fcpad2_device::write(UINT8 data)
+{
+ if (data & 0x01)
+ return;
+
+ // microphone is hooked to expansion bits, not to the controller bit
+ m_latch = m_joypad->read() & ~0x04;
+}
+
+void nes_arcstick_device::write(UINT8 data)
+{
+ m_daisychain->write(data);
+
+ if (data & 0x01)
+ return;
+
+ m_latch = m_joypad->read();
+}
+
diff --git a/src/emu/bus/nes_ctrl/joypad.h b/src/emu/bus/nes_ctrl/joypad.h
new file mode 100644
index 00000000000..00c6aea58e4
--- /dev/null
+++ b/src/emu/bus/nes_ctrl/joypad.h
@@ -0,0 +1,112 @@
+/**********************************************************************
+
+ Nintendo Family Computer & Entertainment System Joypads
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __NES_JOYPAD__
+#define __NES_JOYPAD__
+
+
+#include "emu.h"
+#include "ctrl.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> nes_joypad_device
+
+class nes_joypad_device : public device_t,
+ public device_nes_control_port_interface
+{
+public:
+ // construction/destruction
+ nes_joypad_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source);
+ nes_joypad_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ virtual ioport_constructor device_input_ports() const;
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+
+ virtual UINT8 read_bit0();
+ virtual void write(UINT8 data);
+
+ required_ioport m_joypad;
+ UINT32 m_latch;
+};
+
+// ======================> nes_fcpad2_device
+
+class nes_fcpad2_device : public nes_joypad_device
+{
+public:
+ // construction/destruction
+ nes_fcpad2_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ virtual ioport_constructor device_input_ports() const;
+
+protected:
+ virtual UINT8 read_exp(offs_t offset);
+ virtual void write(UINT8 data);
+};
+
+// ======================> nes_ccpadl_device
+
+class nes_ccpadl_device : public nes_joypad_device
+{
+public:
+ // construction/destruction
+ nes_ccpadl_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ virtual ioport_constructor device_input_ports() const;
+};
+
+// ======================> nes_ccpadr_device
+
+class nes_ccpadr_device : public nes_joypad_device
+{
+public:
+ // construction/destruction
+ nes_ccpadr_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ virtual ioport_constructor device_input_ports() const;
+};
+
+// ======================> nes_arcstick_device
+
+class nes_arcstick_device : public nes_joypad_device
+{
+public:
+ // construction/destruction
+ nes_arcstick_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ virtual ioport_constructor device_input_ports() const;
+ virtual machine_config_constructor device_mconfig_additions() const;
+
+protected:
+ virtual UINT8 read_bit0() { return 0; }
+ virtual UINT8 read_exp(offs_t offset);
+ virtual void write(UINT8 data);
+
+ required_device<nes_control_port_device> m_daisychain;
+ required_ioport m_cfg;
+};
+
+
+// device type definition
+extern const device_type NES_JOYPAD;
+extern const device_type NES_FCPAD_P2;
+extern const device_type NES_CCPAD_LEFT;
+extern const device_type NES_CCPAD_RIGHT;
+extern const device_type NES_ARCSTICK;
+
+#endif
diff --git a/src/emu/bus/nes_ctrl/konamihs.c b/src/emu/bus/nes_ctrl/konamihs.c
new file mode 100644
index 00000000000..187d3d80e2e
--- /dev/null
+++ b/src/emu/bus/nes_ctrl/konamihs.c
@@ -0,0 +1,102 @@
+/**********************************************************************
+
+ Nintendo Family Computer Konami Hyper Shot Controllers
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+#include "konamihs.h"
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+const device_type NES_KONAMIHS = &device_creator<nes_konamihs_device>;
+
+
+static INPUT_PORTS_START( nes_konamihs )
+ PORT_START("P1")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("PI Run")
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("PI Jump")
+
+ PORT_START("P2")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("PII Run")
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("PII Jump")
+INPUT_PORTS_END
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor nes_konamihs_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( nes_konamihs );
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// nes_konamihs_device - constructor
+//-------------------------------------------------
+
+nes_konamihs_device::nes_konamihs_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ device_t(mconfig, NES_KONAMIHS, "Konami Hyper Shot Controller", tag, owner, clock, "nes_konamihs", __FILE__),
+ device_nes_control_port_interface(mconfig, *this),
+ m_ipt_p1(*this, "P1"),
+ m_ipt_p2(*this, "P2")
+{
+}
+
+
+//-------------------------------------------------
+// device_start
+//-------------------------------------------------
+
+void nes_konamihs_device::device_start()
+{
+ save_item(NAME(m_latch_p1));
+ save_item(NAME(m_latch_p2));
+}
+
+
+//-------------------------------------------------
+// device_reset
+//-------------------------------------------------
+
+void nes_konamihs_device::device_reset()
+{
+ m_latch_p1 = 0;
+ m_latch_p2 = 0;
+}
+
+
+//-------------------------------------------------
+// read
+//-------------------------------------------------
+
+UINT8 nes_konamihs_device::read_exp(offs_t offset)
+{
+ UINT8 ret = 0;
+ if (offset == 1) //$4017
+ {
+ ret |= m_latch_p1 << 1;
+ ret |= m_latch_p2 << 3;
+ }
+ return ret;
+}
+
+//-------------------------------------------------
+// write
+//-------------------------------------------------
+
+void nes_konamihs_device::write(UINT8 data)
+{
+ if ((data & 0x02) == 0)
+ m_latch_p1 = m_ipt_p1->read();
+ if ((data & 0x04) == 0)
+ m_latch_p2 = m_ipt_p2->read();
+}
diff --git a/src/emu/bus/nes_ctrl/konamihs.h b/src/emu/bus/nes_ctrl/konamihs.h
new file mode 100644
index 00000000000..71d6dd737cb
--- /dev/null
+++ b/src/emu/bus/nes_ctrl/konamihs.h
@@ -0,0 +1,50 @@
+/**********************************************************************
+
+ Nintendo Family Computer Konami Hyper Shot Controllers
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __NES_KONAMIHS__
+#define __NES_KONAMIHS__
+
+
+#include "emu.h"
+#include "ctrl.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> nes_konamihs_device
+
+class nes_konamihs_device : public device_t,
+ public device_nes_control_port_interface
+{
+public:
+ // construction/destruction
+ nes_konamihs_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ virtual ioport_constructor device_input_ports() const;
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+
+ virtual UINT8 read_exp(offs_t offset);
+ virtual void write(UINT8 data);
+
+ required_ioport m_ipt_p1;
+ required_ioport m_ipt_p2;
+ UINT32 m_latch_p1, m_latch_p2;
+};
+
+// device type definition
+extern const device_type NES_KONAMIHS;
+
+#endif
diff --git a/src/emu/bus/nes_ctrl/miracle.c b/src/emu/bus/nes_ctrl/miracle.c
new file mode 100644
index 00000000000..82ce2cc3796
--- /dev/null
+++ b/src/emu/bus/nes_ctrl/miracle.c
@@ -0,0 +1,178 @@
+/**********************************************************************
+
+ Nintendo Entertainment System - Miracle Piano Keyboard
+
+ TODO: basically everything, this is just a skeleton with no
+ real MIDI handling at the moment.
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+#include "miracle.h"
+#include "bus/midi/midi.h"
+
+#define MIRACLE_MIDI_WAITING 0
+#define MIRACLE_MIDI_RECEIVE 1
+#define MIRACLE_MIDI_SEND 2
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+const device_type NES_MIRACLE = &device_creator<nes_miracle_device>;
+
+
+MACHINE_CONFIG_FRAGMENT( nes_miracle )
+// MCFG_CPU_ADD("piano_cpu", I8051, XTAL_11_0592MHz) // xtal to be verified
+
+ MCFG_MIDI_PORT_ADD("mdin", midiin_slot, "midiin")
+ MCFG_MIDI_PORT_ADD("mdout", midiout_slot, "midiout")
+MACHINE_CONFIG_END
+
+machine_config_constructor nes_miracle_device::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( nes_miracle );
+}
+
+
+//-------------------------------------------------
+// device_timer - handler timer events
+//-------------------------------------------------
+
+void nes_miracle_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ if (id == TIMER_STROBE_ON)
+ {
+ m_strobe_clock++;
+ }
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// nes_miracle_device - constructor
+//-------------------------------------------------
+
+nes_miracle_device::nes_miracle_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ device_t(mconfig, NES_MIRACLE, "Miracle Piano Controller", tag, owner, clock, "nes_miracle", __FILE__)
+ , device_nes_control_port_interface(mconfig, *this)
+// , m_cpu(*this, "piano_cpu")
+{
+}
+
+
+//-------------------------------------------------
+// device_start
+//-------------------------------------------------
+
+void nes_miracle_device::device_start()
+{
+ strobe_timer = timer_alloc(TIMER_STROBE_ON);
+ strobe_timer->adjust(attotime::never);
+ save_item(NAME(m_strobe_on));
+ save_item(NAME(m_sent_bits));
+ save_item(NAME(m_strobe_clock));
+ save_item(NAME(m_midi_mode));
+}
+
+
+//-------------------------------------------------
+// device_reset
+//-------------------------------------------------
+
+void nes_miracle_device::device_reset()
+{
+ m_strobe_on = 0;
+ m_sent_bits = 0;
+ m_strobe_clock = 0;
+ m_midi_mode = MIRACLE_MIDI_WAITING;
+}
+
+
+//-------------------------------------------------
+// read
+//-------------------------------------------------
+
+// TODO: here, reads from serial midi in bit0, when in MIDI_SEND mode
+
+UINT8 nes_miracle_device::read_bit0()
+{
+ UINT8 ret = 0;
+ if (m_strobe_clock >= 66)
+ {
+ // more than 66 clocks since strobe on write means send mode
+ m_midi_mode = MIRACLE_MIDI_SEND;
+ strobe_timer->reset();
+ m_strobe_on = 0;
+ m_strobe_clock = 0;
+// printf("send start\n");
+ }
+
+ if (m_midi_mode == MIRACLE_MIDI_SEND)
+ {
+ //NES reads from Miracle Piano!
+ // ret |= ...
+ }
+
+ return ret;
+}
+
+//-------------------------------------------------
+// write
+//-------------------------------------------------
+
+// TODO: here, writes to serial midi in bit0, when in MIDI_RECEIVE mode
+
+void nes_miracle_device::write(UINT8 data)
+{
+ if (data == 1 && !m_strobe_on)
+ {
+ strobe_timer->adjust(attotime::zero, 0, machine().device<cpu_device>("maincpu")->cycles_to_attotime(1));
+ m_strobe_on = 1;
+ return;
+ }
+
+ if (m_strobe_on)
+ {
+ // was timer running?
+ if (m_strobe_clock > 0)
+ {
+ if (m_strobe_clock < 66 && data == 0)
+ {
+ // less than 66 clocks before new write means receive mode
+ m_midi_mode = MIRACLE_MIDI_RECEIVE;
+// printf("receive start\n");
+ strobe_timer->reset();
+ m_strobe_on = 0;
+ m_strobe_clock = 0;
+ return;
+ }
+ }
+
+ if (m_midi_mode == MIRACLE_MIDI_SEND && data == 0)
+ {
+ // strobe off after the end of a byte
+ m_midi_mode = MIRACLE_MIDI_WAITING;
+// printf("send end\n");
+ }
+ }
+
+ if (m_midi_mode == MIRACLE_MIDI_RECEIVE)
+ {
+ //NES writes (data & 1) to Miracle Piano!
+ // 1st write is data present flag (1=data present)
+ // next 8 writes are actual data bits (with ^1)
+ m_sent_bits++;
+ // then we go back to waiting
+ if (m_sent_bits == 9)
+ {
+// printf("receive end\n");
+ m_midi_mode = MIRACLE_MIDI_WAITING;
+ m_sent_bits = 0;
+ }
+ }
+}
diff --git a/src/emu/bus/nes_ctrl/miracle.h b/src/emu/bus/nes_ctrl/miracle.h
new file mode 100644
index 00000000000..fcc8c17c42b
--- /dev/null
+++ b/src/emu/bus/nes_ctrl/miracle.h
@@ -0,0 +1,55 @@
+/**********************************************************************
+
+ Nintendo Entertainment System - Miracle Piano Keyboard
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __NES_MIRACLE__
+#define __NES_MIRACLE__
+
+
+#include "emu.h"
+#include "ctrl.h"
+//#include "cpu/mcs51/mcs51.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> nes_miracle_device
+
+class nes_miracle_device : public device_t,
+ public device_nes_control_port_interface
+{
+public:
+ // construction/destruction
+ nes_miracle_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_bit0();
+ virtual void write(UINT8 data);
+
+ static const device_timer_id TIMER_STROBE_ON = 0;
+ emu_timer *strobe_timer;
+
+ //required_device<i8051_device> m_cpu;
+ int m_strobe_on, m_midi_mode, m_sent_bits;
+ UINT32 m_strobe_clock;
+};
+
+// device type definition
+extern const device_type NES_MIRACLE;
+
+#endif
diff --git a/src/emu/bus/nes_ctrl/mjpanel.c b/src/emu/bus/nes_ctrl/mjpanel.c
new file mode 100644
index 00000000000..16e582338c9
--- /dev/null
+++ b/src/emu/bus/nes_ctrl/mjpanel.c
@@ -0,0 +1,132 @@
+/**********************************************************************
+
+ Nintendo Family Computer Mahjong Panel
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+#include "mjpanel.h"
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+const device_type NES_MJPANEL = &device_creator<nes_mjpanel_device>;
+
+
+static INPUT_PORTS_START( nes_mjpanel )
+ PORT_START("MJPANEL.0")
+ PORT_BIT( 0xff, IP_ACTIVE_HIGH, IPT_UNUSED )
+
+ PORT_START("MJPANEL.1")
+ PORT_BIT( 0x03, IP_ACTIVE_HIGH, IPT_UNUSED )
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_MAHJONG_N )
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_MAHJONG_M )
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_MAHJONG_L )
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_MAHJONG_K )
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_MAHJONG_J )
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_MAHJONG_I )
+
+ PORT_START("MJPANEL.2")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_MAHJONG_H )
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_MAHJONG_G )
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_MAHJONG_F )
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_MAHJONG_E )
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_MAHJONG_D )
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_MAHJONG_C )
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_MAHJONG_B )
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_MAHJONG_A )
+
+ PORT_START("MJPANEL.3")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED )
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_MAHJONG_RON )
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_MAHJONG_REACH )
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_MAHJONG_CHI )
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_MAHJONG_PON )
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_MAHJONG_KAN )
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_SELECT ) PORT_NAME("Mahjong Select")
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_START ) PORT_NAME("Mahjong Start")
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor nes_mjpanel_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( nes_mjpanel );
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// nes_mjpanel_device - constructor
+//-------------------------------------------------
+
+nes_mjpanel_device::nes_mjpanel_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ device_t(mconfig, NES_MJPANEL, "Famicom Mahjong Panel", tag, owner, clock, "nes_mjpanel", __FILE__),
+ device_nes_control_port_interface(mconfig, *this),
+ m_panel(*this, "MJPANEL")
+{
+}
+
+
+//-------------------------------------------------
+// device_start
+//-------------------------------------------------
+
+void nes_mjpanel_device::device_start()
+{
+ save_item(NAME(m_latch));
+}
+
+
+//-------------------------------------------------
+// device_reset
+//-------------------------------------------------
+
+void nes_mjpanel_device::device_reset()
+{
+ m_latch = 0;
+}
+
+
+//-------------------------------------------------
+// read
+//-------------------------------------------------
+
+UINT8 nes_mjpanel_device::read_exp(offs_t offset)
+{
+ UINT8 ret = 0;
+ if (offset)
+ {
+ ret = (m_latch & 1) << 1;
+ m_latch >>= 1;
+ }
+ else
+ logerror("Error: Mahjong panel read from $4016\n");
+
+ return ret;
+}
+
+//-------------------------------------------------
+// write
+//-------------------------------------------------
+
+void nes_mjpanel_device::write(UINT8 data)
+{
+ if (data & 0x01)
+ return;
+
+ if (data & 0xf8)
+ logerror("Error: Mahjong panel read with mux data %02x\n", (data & 0xfe));
+ else
+ m_latch = m_panel[(data & 0xfe) >> 1]->read();
+}
diff --git a/src/emu/bus/nes_ctrl/mjpanel.h b/src/emu/bus/nes_ctrl/mjpanel.h
new file mode 100644
index 00000000000..6df7680eb26
--- /dev/null
+++ b/src/emu/bus/nes_ctrl/mjpanel.h
@@ -0,0 +1,52 @@
+/**********************************************************************
+
+ Nintendo Family Computer Mahjong Panel
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __NES_MJPANEL__
+#define __NES_MJPANEL__
+
+
+#include "emu.h"
+#include "ctrl.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> nes_mjpanel_device
+
+class nes_mjpanel_device : public device_t,
+ public device_nes_control_port_interface
+{
+public:
+ // construction/destruction
+ nes_mjpanel_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ virtual ioport_constructor device_input_ports() const;
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+
+ virtual UINT8 read_exp(offs_t offset);
+ virtual void write(UINT8 data);
+
+private:
+ required_ioport_array<4> m_panel;
+ UINT32 m_latch;
+};
+
+
+// device type definition
+extern const device_type NES_MJPANEL;
+
+
+#endif
diff --git a/src/emu/bus/nes_ctrl/pachinko.c b/src/emu/bus/nes_ctrl/pachinko.c
new file mode 100644
index 00000000000..875aa92e771
--- /dev/null
+++ b/src/emu/bus/nes_ctrl/pachinko.c
@@ -0,0 +1,108 @@
+/**********************************************************************
+
+ Nintendo Family Computer Pachinko Controller
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+#include "pachinko.h"
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+const device_type NES_PACHINKO = &device_creator<nes_pachinko_device>;
+
+
+static INPUT_PORTS_START( nes_pachinko )
+ PORT_START("JOYPAD")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("A")
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("B")
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_SELECT )
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_START )
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_8WAY
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_8WAY
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_8WAY
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_8WAY
+
+ PORT_START("TRIGGER")
+ PORT_BIT( 0xff, 0, IPT_PEDAL ) PORT_MINMAX(0, 0x63) PORT_SENSITIVITY(25) PORT_KEYDELTA(20)
+INPUT_PORTS_END
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor nes_pachinko_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( nes_pachinko );
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// nes_pachinko_device - constructor
+//-------------------------------------------------
+
+nes_pachinko_device::nes_pachinko_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ device_t(mconfig, NES_PACHINKO, "Famicom Pachinko Controller", tag, owner, clock, "nes_pachinko", __FILE__),
+ device_nes_control_port_interface(mconfig, *this),
+ m_joypad(*this, "JOYPAD"),
+ m_trigger(*this, "TRIGGER")
+{
+}
+
+
+//-------------------------------------------------
+// device_start
+//-------------------------------------------------
+
+void nes_pachinko_device::device_start()
+{
+ save_item(NAME(m_latch));
+}
+
+
+//-------------------------------------------------
+// device_reset
+//-------------------------------------------------
+
+void nes_pachinko_device::device_reset()
+{
+ m_latch = 0;
+}
+
+
+//-------------------------------------------------
+// read
+//-------------------------------------------------
+
+UINT8 nes_pachinko_device::read_exp(offs_t offset)
+{
+ UINT8 ret = 0;
+ // this controller behaves like a standard P3 joypad, with longer stream of inputs
+ if (offset == 0) //$4016
+ {
+ ret |= (m_latch & 1) << 1;
+ m_latch >>= 1;
+ }
+ return ret;
+}
+
+//-------------------------------------------------
+// write
+//-------------------------------------------------
+
+void nes_pachinko_device::write(UINT8 data)
+{
+ if (data & 0x01)
+ return;
+
+ m_latch = m_joypad->read();
+ m_latch |= ((m_trigger->read() ^ 0xff) & 0xff) << 8;
+ m_latch |= 0xff0000;
+}
diff --git a/src/emu/bus/nes_ctrl/pachinko.h b/src/emu/bus/nes_ctrl/pachinko.h
new file mode 100644
index 00000000000..ab07e4fa961
--- /dev/null
+++ b/src/emu/bus/nes_ctrl/pachinko.h
@@ -0,0 +1,50 @@
+/**********************************************************************
+
+ Nintendo Family Computer Pachinko Controller
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __NES_PACHINKO__
+#define __NES_PACHINKO__
+
+
+#include "emu.h"
+#include "ctrl.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> nes_pachinko_device
+
+class nes_pachinko_device : public device_t,
+ public device_nes_control_port_interface
+{
+public:
+ // construction/destruction
+ nes_pachinko_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ virtual ioport_constructor device_input_ports() const;
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+
+ virtual UINT8 read_exp(offs_t offset);
+ virtual void write(UINT8 data);
+
+ required_ioport m_joypad;
+ required_ioport m_trigger;
+ UINT32 m_latch;
+};
+
+// device type definition
+extern const device_type NES_PACHINKO;
+
+#endif
diff --git a/src/emu/bus/nes_ctrl/partytap.c b/src/emu/bus/nes_ctrl/partytap.c
new file mode 100644
index 00000000000..f81fb89bd2f
--- /dev/null
+++ b/src/emu/bus/nes_ctrl/partytap.c
@@ -0,0 +1,108 @@
+/**********************************************************************
+
+ Nintendo Family Computer Yonezawa / PartyRoom 21 Party Tap Controller
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+#include "partytap.h"
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+const device_type NES_PARTYTAP = &device_creator<nes_partytap_device>;
+
+
+static INPUT_PORTS_START( nes_partytap )
+ PORT_START("INPUTS")
+ PORT_BIT( 0x03, IP_ACTIVE_HIGH, IPT_UNUSED )
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P1 Button") PORT_CODE(KEYCODE_Z)
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P2 Button") PORT_CODE(KEYCODE_X)
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P3 Button") PORT_CODE(KEYCODE_C)
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P4 Button") PORT_CODE(KEYCODE_V)
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P5 Button") PORT_CODE(KEYCODE_B)
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P6 Button") PORT_CODE(KEYCODE_N)
+INPUT_PORTS_END
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor nes_partytap_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( nes_partytap );
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// nes_partytap_device - constructor
+//-------------------------------------------------
+
+nes_partytap_device::nes_partytap_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ device_t(mconfig, NES_PARTYTAP, "Yonezawa Party Tap Controller", tag, owner, clock, "nes_partytap", __FILE__),
+ device_nes_control_port_interface(mconfig, *this),
+ m_inputs(*this, "INPUTS")
+{
+}
+
+
+//-------------------------------------------------
+// device_start
+//-------------------------------------------------
+
+void nes_partytap_device::device_start()
+{
+ save_item(NAME(m_latch));
+ save_item(NAME(m_mode));
+}
+
+
+//-------------------------------------------------
+// device_reset
+//-------------------------------------------------
+
+void nes_partytap_device::device_reset()
+{
+ m_mode = 0xe0;
+ m_latch = 0;
+}
+
+
+//-------------------------------------------------
+// read
+//-------------------------------------------------
+
+UINT8 nes_partytap_device::read_exp(offs_t offset)
+{
+ UINT8 ret = 0;
+ if (offset == 1) //$4017
+ {
+ ret |= m_latch & 0x1c;
+ m_latch >>= 3;
+ // append mode bits
+ m_latch |= m_mode;
+ }
+ return ret;
+}
+
+//-------------------------------------------------
+// write
+//-------------------------------------------------
+
+void nes_partytap_device::write(UINT8 data)
+{
+ // inputs are read in two chunks of 3 bits, before the second one is read bit2 is written here
+ // probably a mechanism for the game to detect which group of inputs is being read
+ m_mode = BIT(data, 2) ? 0xa0 : 0xe0;
+
+ if (data & 0x01)
+ return;
+
+ m_latch = m_inputs->read();
+}
diff --git a/src/emu/bus/nes_ctrl/partytap.h b/src/emu/bus/nes_ctrl/partytap.h
new file mode 100644
index 00000000000..1b85832ea4d
--- /dev/null
+++ b/src/emu/bus/nes_ctrl/partytap.h
@@ -0,0 +1,50 @@
+/**********************************************************************
+
+ Nintendo Family Computer Yonezawa / PartyRoom 21 Party Tap Controller
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __NES_PARTYTAP__
+#define __NES_PARTYTAP__
+
+
+#include "emu.h"
+#include "ctrl.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> nes_partytap_device
+
+class nes_partytap_device : public device_t,
+ public device_nes_control_port_interface
+{
+public:
+ // construction/destruction
+ nes_partytap_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ virtual ioport_constructor device_input_ports() const;
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+
+ virtual UINT8 read_exp(offs_t offset);
+ virtual void write(UINT8 data);
+
+ required_ioport m_inputs;
+ UINT8 m_mode;
+ UINT32 m_latch;
+};
+
+// device type definition
+extern const device_type NES_PARTYTAP;
+
+#endif
diff --git a/src/emu/bus/nes_ctrl/powerpad.c b/src/emu/bus/nes_ctrl/powerpad.c
new file mode 100644
index 00000000000..ba3a5795b43
--- /dev/null
+++ b/src/emu/bus/nes_ctrl/powerpad.c
@@ -0,0 +1,136 @@
+/**********************************************************************
+
+ Nintendo Entertainment System - Bandai Power Pad
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+#include "powerpad.h"
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+const device_type NES_POWERPAD = &device_creator<nes_powerpad_device>;
+
+
+static INPUT_PORTS_START( nes_powerpad )
+ PORT_START("LAYOUT")
+ PORT_CONFNAME( 0x01, 0x00, "Power Pad Button Layout")
+ PORT_CONFSETTING( 0x00, "Side A" )
+ PORT_CONFSETTING( 0x01, "Side B" )
+
+ // difference between the two sides is that we mirror the key mapping to match the real pad layout!
+ PORT_START("POWERPAD1")
+ // side A layout
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad Top1") PORT_CODE(KEYCODE_Y) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad Mid1") PORT_CODE(KEYCODE_J) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad Mid2") PORT_CODE(KEYCODE_H) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad Low1") PORT_CODE(KEYCODE_N) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad Low2") PORT_CODE(KEYCODE_B) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad Mid3") PORT_CODE(KEYCODE_G) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
+ // side B layout
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad 2") PORT_CODE(KEYCODE_T) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad 1") PORT_CODE(KEYCODE_R) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad 5") PORT_CODE(KEYCODE_F) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad 9") PORT_CODE(KEYCODE_V) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad 6") PORT_CODE(KEYCODE_G) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad 10") PORT_CODE(KEYCODE_B) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad 11") PORT_CODE(KEYCODE_N) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad 7") PORT_CODE(KEYCODE_H) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
+
+ PORT_START("POWERPAD2")
+ // side A layout
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad Top2") PORT_CODE(KEYCODE_T) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad Mid4") PORT_CODE(KEYCODE_F) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
+ PORT_BIT( 0xf0, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x00)
+ // side B layout
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad 4") PORT_CODE(KEYCODE_U) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad 3") PORT_CODE(KEYCODE_Y) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad 12") PORT_CODE(KEYCODE_M) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad 8") PORT_CODE(KEYCODE_J) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
+ PORT_BIT( 0xf0, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_CONDITION("LAYOUT", 0x01, EQUALS, 0x01)
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor nes_powerpad_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( nes_powerpad );
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// nes_powerpad_device - constructor
+//-------------------------------------------------
+
+nes_powerpad_device::nes_powerpad_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ device_t(mconfig, NES_POWERPAD, "Bandai Power Pad", tag, owner, clock, "nes_powerpad", __FILE__),
+ device_nes_control_port_interface(mconfig, *this),
+ m_ipt1(*this, "POWERPAD1"),
+ m_ipt2(*this, "POWERPAD2")
+{
+}
+
+
+//-------------------------------------------------
+// device_start
+//-------------------------------------------------
+
+void nes_powerpad_device::device_start()
+{
+ save_item(NAME(m_latch));
+}
+
+
+//-------------------------------------------------
+// device_reset
+//-------------------------------------------------
+
+void nes_powerpad_device::device_reset()
+{
+ m_latch[0] = 0;
+ m_latch[1] = 0;
+}
+
+
+//-------------------------------------------------
+// read
+//-------------------------------------------------
+
+UINT8 nes_powerpad_device::read_bit34()
+{
+ UINT8 ret = 0;
+ ret |= (m_latch[0] & 0x01) << 3;
+ ret |= (m_latch[1] & 0x01) << 4;
+ m_latch[0] >>= 1;
+ m_latch[1] >>= 1;
+ return ret;
+}
+
+//-------------------------------------------------
+// write
+//-------------------------------------------------
+
+void nes_powerpad_device::write(UINT8 data)
+{
+ if (data & 0x01)
+ return;
+
+ m_latch[0] = m_ipt1->read();
+ m_latch[1] = m_ipt2->read() | 0xf0;
+}
diff --git a/src/emu/bus/nes_ctrl/powerpad.h b/src/emu/bus/nes_ctrl/powerpad.h
new file mode 100644
index 00000000000..0bf6d5fa53d
--- /dev/null
+++ b/src/emu/bus/nes_ctrl/powerpad.h
@@ -0,0 +1,53 @@
+/**********************************************************************
+
+ Nintendo Entertainment System - Bandai Power Pad
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __NES_POWERPAD__
+#define __NES_POWERPAD__
+
+
+#include "emu.h"
+#include "ctrl.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> nes_powerpad_device
+
+class nes_powerpad_device : public device_t,
+ public device_nes_control_port_interface
+{
+public:
+ // construction/destruction
+ nes_powerpad_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ virtual ioport_constructor device_input_ports() const;
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+
+ virtual UINT8 read_bit34();
+ virtual void write(UINT8 data);
+
+private:
+ required_ioport m_ipt1;
+ required_ioport m_ipt2;
+ UINT32 m_latch[2];
+};
+
+
+// device type definition
+extern const device_type NES_POWERPAD;
+
+
+#endif
diff --git a/src/emu/bus/nes_ctrl/suborkey.c b/src/emu/bus/nes_ctrl/suborkey.c
new file mode 100644
index 00000000000..eb937120d1c
--- /dev/null
+++ b/src/emu/bus/nes_ctrl/suborkey.c
@@ -0,0 +1,230 @@
+/**********************************************************************
+
+ Nintendo Family Computer Subor Keyboard (used by some Famiclones)
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+#include "suborkey.h"
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+const device_type NES_SUBORKEYBOARD = &device_creator<nes_suborkey_device>;
+
+
+static INPUT_PORTS_START( fc_suborkey )
+ PORT_START("SUBOR.0")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_4) PORT_CHAR('4')
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_G) PORT_CHAR('G')
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F) PORT_CHAR('F')
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_C) PORT_CHAR('C')
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F2) PORT_CHAR(UCHAR_MAMEKEY(F2))
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_E) PORT_CHAR('E')
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_5) PORT_CHAR('5')
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_V) PORT_CHAR('V')
+
+ PORT_START("SUBOR.1")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_2) PORT_CHAR('2')
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_D) PORT_CHAR('D')
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_S) PORT_CHAR('S')
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_END) PORT_CHAR(UCHAR_MAMEKEY(END))
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F1) PORT_CHAR(UCHAR_MAMEKEY(F1))
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_W) PORT_CHAR('W')
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_3) PORT_CHAR('3')
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_X) PORT_CHAR('X')
+
+ PORT_START("SUBOR.2")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_INSERT) PORT_CHAR(UCHAR_MAMEKEY(INSERT))
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("NEXT")
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT))
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F8) PORT_CHAR(UCHAR_MAMEKEY(F8))
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("PRIOR")
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_DEL) PORT_CHAR(UCHAR_MAMEKEY(DEL))
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_HOME) PORT_CHAR(UCHAR_MAMEKEY(HOME))
+
+ PORT_START("SUBOR.3")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_9) PORT_CHAR('9')
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_I) PORT_CHAR('I')
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_L) PORT_CHAR('L')
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',')
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F5) PORT_CHAR(UCHAR_MAMEKEY(F5))
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_O) PORT_CHAR('O')
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_0) PORT_CHAR('0')
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.')
+
+ PORT_START("SUBOR.4")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(']')
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP))
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT))
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F7) PORT_CHAR(UCHAR_MAMEKEY(F7))
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('[')
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('\\')
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN))
+
+ PORT_START("SUBOR.5")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Q) PORT_CHAR('Q')
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_CAPSLOCK) PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK))
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Z) PORT_CHAR('Z')
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_TAB) PORT_CHAR('\t')
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_ESC) PORT_CHAR(UCHAR_MAMEKEY(ESC))
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_A) PORT_CHAR('A')
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_1) PORT_CHAR('1')
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_LCONTROL) PORT_CHAR(UCHAR_SHIFT_2)
+
+ PORT_START("SUBOR.6")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_7) PORT_CHAR('7')
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Y) PORT_CHAR('Y')
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_K) PORT_CHAR('K')
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_M) PORT_CHAR('M')
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F4) PORT_CHAR(UCHAR_MAMEKEY(F4))
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_U) PORT_CHAR('U')
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_8) PORT_CHAR('8')
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_J) PORT_CHAR('J')
+
+ PORT_START("SUBOR.7")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-')
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_COLON) PORT_CHAR(':')
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR('\'')
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/')
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F6) PORT_CHAR(UCHAR_MAMEKEY(F6))
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_P) PORT_CHAR('P')
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=')
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_SHIFT_1)
+
+ PORT_START("SUBOR.8")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_T) PORT_CHAR('T')
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_H) PORT_CHAR('H')
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_N) PORT_CHAR('N')
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F3) PORT_CHAR(UCHAR_MAMEKEY(F3))
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_R) PORT_CHAR('R')
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_6) PORT_CHAR('6')
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_B) PORT_CHAR('B')
+
+ PORT_START("SUBOR.9")
+ PORT_BIT( 0xff, IP_ACTIVE_HIGH, IPT_UNUSED )
+
+ PORT_START("SUBOR.10")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("LMENU")
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_4_PAD) PORT_CHAR(UCHAR_MAMEKEY(4_PAD))
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_7_PAD) PORT_CHAR(UCHAR_MAMEKEY(7_PAD))
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F11) PORT_CHAR(UCHAR_MAMEKEY(F11))
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F12) PORT_CHAR(UCHAR_MAMEKEY(F12))
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_1_PAD) PORT_CHAR(UCHAR_MAMEKEY(1_PAD))
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_2_PAD) PORT_CHAR(UCHAR_MAMEKEY(2_PAD))
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_8_PAD) PORT_CHAR(UCHAR_MAMEKEY(8_PAD))
+
+ PORT_START("SUBOR.11")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_MINUS_PAD)PORT_CHAR(UCHAR_MAMEKEY(MINUS_PAD))
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_PLUS_PAD) PORT_CHAR(UCHAR_MAMEKEY(PLUS_PAD))
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_ASTERISK) PORT_CHAR(UCHAR_MAMEKEY(ASTERISK))
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_9_PAD) PORT_CHAR(UCHAR_MAMEKEY(9_PAD))
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F10) PORT_CHAR(UCHAR_MAMEKEY(F10))
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_5_PAD) PORT_CHAR(UCHAR_MAMEKEY(5_PAD))
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_SLASH_PAD)PORT_CHAR(UCHAR_MAMEKEY(SLASH_PAD))
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_NUMLOCK) PORT_CHAR(UCHAR_MAMEKEY(NUMLOCK))
+
+ PORT_START("SUBOR.12")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_TILDE) PORT_CHAR('`')
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_6_PAD) PORT_CHAR(UCHAR_MAMEKEY(6_PAD))
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("PAUSE")
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("SPACE2")
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F9) PORT_CHAR(UCHAR_MAMEKEY(F9))
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_3_PAD) PORT_CHAR(UCHAR_MAMEKEY(3_PAD))
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Keypad .") PORT_CODE(KEYCODE_DEL_PAD)
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_0_PAD) PORT_CHAR(UCHAR_MAMEKEY(0_PAD))
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor nes_suborkey_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( fc_suborkey );
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// nes_suborkey_device - constructor
+//-------------------------------------------------
+
+nes_suborkey_device::nes_suborkey_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ device_t(mconfig, NES_SUBORKEYBOARD, "FC Subor Keyboard", tag, owner, clock, "nes_suborkey", __FILE__),
+ device_nes_control_port_interface(mconfig, *this),
+ m_kbd(*this, "SUBOR")
+{
+}
+
+
+//-------------------------------------------------
+// device_start
+//-------------------------------------------------
+
+void nes_suborkey_device::device_start()
+{
+ save_item(NAME(m_fck_scan));
+ save_item(NAME(m_fck_mode));
+}
+
+
+//-------------------------------------------------
+// device_reset
+//-------------------------------------------------
+
+void nes_suborkey_device::device_reset()
+{
+ m_fck_scan = 0;
+ m_fck_mode = 0;
+}
+
+
+//-------------------------------------------------
+// read
+//-------------------------------------------------
+
+UINT8 nes_suborkey_device::read_exp(offs_t offset)
+{
+ UINT8 ret = 0;
+ if (offset == 1) //$4017
+ {
+ // Subor Keyboard: rows of the keyboard matrix are read 4-bits at time and returned as bit1->bit4
+ if (m_fck_scan < 13)
+ ret |= ~(((m_kbd[m_fck_scan]->read() >> (m_fck_mode * 4)) & 0x0f) << 1) & 0x1e;
+ else
+ ret |= 0x1e;
+ }
+
+ return ret;
+}
+
+//-------------------------------------------------
+// write
+//-------------------------------------------------
+
+void nes_suborkey_device::write(UINT8 data)
+{
+ if (BIT(data, 2)) // keyboard active
+ {
+ UINT8 out = BIT(data, 1); // scan
+ if (m_fck_mode && !out && ++m_fck_scan > 12)
+ m_fck_scan = 0;
+
+ m_fck_mode = out; // access lower or upper 4 bits
+
+ if (BIT(data, 0)) // reset
+ m_fck_scan = 0;
+ }
+}
diff --git a/src/emu/bus/nes_ctrl/suborkey.h b/src/emu/bus/nes_ctrl/suborkey.h
new file mode 100644
index 00000000000..c48c9715657
--- /dev/null
+++ b/src/emu/bus/nes_ctrl/suborkey.h
@@ -0,0 +1,52 @@
+/**********************************************************************
+
+ Nintendo Family Computer Subor Keyboard (used by some Famiclones)
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __NES_SUBORKEY__
+#define __NES_SUBORKEY__
+
+
+#include "emu.h"
+#include "ctrl.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> nes_suborkey_device
+
+class nes_suborkey_device : public device_t,
+ public device_nes_control_port_interface
+{
+public:
+ // construction/destruction
+ nes_suborkey_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ virtual ioport_constructor device_input_ports() const;
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+
+ virtual UINT8 read_exp(offs_t offset);
+ virtual void write(UINT8 data);
+
+private:
+ required_ioport_array<13> m_kbd;
+ UINT8 m_fck_scan, m_fck_mode;
+};
+
+
+// device type definition
+extern const device_type NES_SUBORKEYBOARD;
+
+
+#endif
diff --git a/src/emu/bus/nes_ctrl/zapper.c b/src/emu/bus/nes_ctrl/zapper.c
new file mode 100644
index 00000000000..36965206f46
--- /dev/null
+++ b/src/emu/bus/nes_ctrl/zapper.c
@@ -0,0 +1,97 @@
+/**********************************************************************
+
+ Nintendo Family Computer & Entertainment System Zapper Lightgun
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+#include "zapper.h"
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+const device_type NES_ZAPPER = &device_creator<nes_zapper_device>;
+
+
+static INPUT_PORTS_START( nes_zapper )
+ PORT_START("ZAPPER_X")
+ PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_X) PORT_CROSSHAIR(X, 1.0, 0.0, 0) PORT_SENSITIVITY(70) PORT_KEYDELTA(30) PORT_MINMAX(0,255)
+ PORT_START("ZAPPER_Y")
+ PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_Y) PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_SENSITIVITY(50) PORT_KEYDELTA(30) PORT_MINMAX(0,255)
+ PORT_START("ZAPPER_T")
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("Lightgun Trigger")
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor nes_zapper_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( nes_zapper );
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// nes_zapper_device - constructor
+//-------------------------------------------------
+
+nes_zapper_device::nes_zapper_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ device_t(mconfig, NES_ZAPPER, "Nintendo Zapper Lightgun", tag, owner, clock, "nes_zapper", __FILE__),
+ device_nes_control_port_interface(mconfig, *this),
+ m_lightx(*this, "ZAPPER_X"),
+ m_lighty(*this, "ZAPPER_Y"),
+ m_trigger(*this, "ZAPPER_T")
+{
+}
+
+
+//-------------------------------------------------
+// device_start
+//-------------------------------------------------
+
+void nes_zapper_device::device_start()
+{
+}
+
+
+//-------------------------------------------------
+// device_reset
+//-------------------------------------------------
+
+void nes_zapper_device::device_reset()
+{
+}
+
+
+//-------------------------------------------------
+// read
+//-------------------------------------------------
+
+UINT8 nes_zapper_device::read_bit34()
+{
+ UINT8 ret = m_trigger->read();
+ if (!m_port->m_brightpixel_cb.isnull() &&
+ m_port->m_brightpixel_cb(m_lightx->read(), m_lighty->read()))
+ ret &= ~0x08; // sprite hit
+ else
+ ret |= 0x08; // no sprite hit
+ return ret;
+}
+
+UINT8 nes_zapper_device::read_exp(offs_t offset)
+{
+ UINT8 ret = 0;
+ if (offset == 1) // $4017
+ ret |= nes_zapper_device::read_bit34();
+ return ret;
+}
diff --git a/src/emu/bus/nes_ctrl/zapper.h b/src/emu/bus/nes_ctrl/zapper.h
new file mode 100644
index 00000000000..ed19fdfc265
--- /dev/null
+++ b/src/emu/bus/nes_ctrl/zapper.h
@@ -0,0 +1,53 @@
+/**********************************************************************
+
+ Nintendo Family Computer & Entertainment System Zapper Lightgun
+
+ Copyright MESS Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __NES_ZAPPER__
+#define __NES_ZAPPER__
+
+
+#include "emu.h"
+#include "ctrl.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> nes_zapper_device
+
+class nes_zapper_device : public device_t,
+ public device_nes_control_port_interface
+{
+public:
+ // construction/destruction
+ nes_zapper_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ virtual ioport_constructor device_input_ports() const;
+
+protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+
+ virtual UINT8 read_bit34();
+ virtual UINT8 read_exp(offs_t offset);
+
+private:
+ required_ioport m_lightx;
+ required_ioport m_lighty;
+ required_ioport m_trigger;
+};
+
+
+// device type definition
+extern const device_type NES_ZAPPER;
+
+
+#endif
diff --git a/src/mess/drivers/nes.c b/src/mess/drivers/nes.c
index 11b47141047..9a5ff708c76 100644
--- a/src/mess/drivers/nes.c
+++ b/src/mess/drivers/nes.c
@@ -48,140 +48,8 @@ static ADDRESS_MAP_START( nes_map, AS_PROGRAM, 8, nes_state )
// 0x8000-0xffff -> HIGH HANDLER defined on a pcb base
ADDRESS_MAP_END
-
-static INPUT_PORTS_START( nes_pads12 )
- PORT_START("PAD1")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("P1 A") PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x000f, EQUALS, 0x0001)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("P1 B") PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x000f, EQUALS, 0x0001)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_SELECT ) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x000f, EQUALS, 0x0001)
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_START ) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x000f, EQUALS, 0x0001)
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x000f, EQUALS, 0x0001)
- PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x000f, EQUALS, 0x0001)
- PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x000f, EQUALS, 0x0001)
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x000f, EQUALS, 0x0001)
-
- PORT_START("PAD2")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("P2 A") PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0010)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("P2 B") PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0010)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_SELECT ) PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0010)
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_START ) PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0010)
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0010)
- PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0010)
- PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0010)
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0010)
-INPUT_PORTS_END
-
-static INPUT_PORTS_START( nes_pads34 )
- PORT_START("PAD3")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("P3 A") PORT_PLAYER(3) PORT_CONDITION("CTRLSEL", 0x0f00, EQUALS, 0x0100)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("P3 B") PORT_PLAYER(3) PORT_CONDITION("CTRLSEL", 0x0f00, EQUALS, 0x0100)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_SELECT ) PORT_PLAYER(3) PORT_CONDITION("CTRLSEL", 0x0f00, EQUALS, 0x0100)
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_START ) PORT_PLAYER(3) PORT_CONDITION("CTRLSEL", 0x0f00, EQUALS, 0x0100)
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_PLAYER(3) PORT_CONDITION("CTRLSEL", 0x0f00, EQUALS, 0x0100)
- PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_PLAYER(3) PORT_CONDITION("CTRLSEL", 0x0f00, EQUALS, 0x0100)
- PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_PLAYER(3) PORT_CONDITION("CTRLSEL", 0x0f00, EQUALS, 0x0100)
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(3) PORT_CONDITION("CTRLSEL", 0x0f00, EQUALS, 0x0100)
-
- PORT_START("PAD4")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("P4 A") PORT_PLAYER(4) PORT_CONDITION("CTRLSEL", 0xf000, EQUALS, 0x1000)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("P4 B") PORT_PLAYER(4) PORT_CONDITION("CTRLSEL", 0xf000, EQUALS, 0x1000)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_SELECT ) PORT_PLAYER(4) PORT_CONDITION("CTRLSEL", 0xf000, EQUALS, 0x1000)
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_START ) PORT_PLAYER(4) PORT_CONDITION("CTRLSEL", 0xf000, EQUALS, 0x1000)
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_PLAYER(4) PORT_CONDITION("CTRLSEL", 0xf000, EQUALS, 0x1000)
- PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_PLAYER(4) PORT_CONDITION("CTRLSEL", 0xf000, EQUALS, 0x1000)
- PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_PLAYER(4) PORT_CONDITION("CTRLSEL", 0xf000, EQUALS, 0x1000)
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(4) PORT_CONDITION("CTRLSEL", 0xf000, EQUALS, 0x1000)
-INPUT_PORTS_END
-
-
-static INPUT_PORTS_START( nes_powerpad )
-// difference between the two sides is that we mirror the key mapping to match the real pad layout!
- PORT_START("POWERPAD1")
-// side A layout
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad Top1") PORT_CODE(KEYCODE_Y) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0050)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0050)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad Mid1") PORT_CODE(KEYCODE_J) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0050)
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0050)
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad Mid2") PORT_CODE(KEYCODE_H) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0050)
- PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad Low1") PORT_CODE(KEYCODE_N) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0050)
- PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad Low2") PORT_CODE(KEYCODE_B) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0050)
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad Mid3") PORT_CODE(KEYCODE_G) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0050)
-// side B layout
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad 2") PORT_CODE(KEYCODE_T) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0060)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad 1") PORT_CODE(KEYCODE_R) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0060)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad 5") PORT_CODE(KEYCODE_F) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0060)
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad 9") PORT_CODE(KEYCODE_V) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0060)
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad 6") PORT_CODE(KEYCODE_G) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0060)
- PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad 10") PORT_CODE(KEYCODE_B) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0060)
- PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad 11") PORT_CODE(KEYCODE_N) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0060)
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad 7") PORT_CODE(KEYCODE_H) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0060)
- PORT_START("POWERPAD2")
-// side A layout
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0050)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad Top2") PORT_CODE(KEYCODE_T) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0050)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0050)
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad Mid4") PORT_CODE(KEYCODE_F) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0050)
- PORT_BIT( 0xf0, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0050)
-// side B layout
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad 4") PORT_CODE(KEYCODE_U) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0060)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad 3") PORT_CODE(KEYCODE_Y) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0060)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad 12") PORT_CODE(KEYCODE_M) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0060)
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("PowerPad 8") PORT_CODE(KEYCODE_J) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0060)
- PORT_BIT( 0xf0, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0060)
-INPUT_PORTS_END
-
-static INPUT_PORTS_START( nes_zapper1 )
- PORT_START("ZAPPER1_X")
- PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_X) PORT_CROSSHAIR(X, 1.0, 0.0, 0) PORT_SENSITIVITY(70) PORT_KEYDELTA(30) PORT_MINMAX(0,255) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x000f, EQUALS, 0x0002)
- PORT_START("ZAPPER1_Y")
- PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_Y) PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_SENSITIVITY(50) PORT_KEYDELTA(30) PORT_MINMAX(0,255) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x000f, EQUALS, 0x0002)
- PORT_START("ZAPPER1_T")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("P1 Lightgun Trigger") PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x000f, EQUALS, 0x0002)
-INPUT_PORTS_END
-
-static INPUT_PORTS_START( nes_zapper2 )
- PORT_START("ZAPPER2_X")
- PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_X) PORT_CROSSHAIR(X, 1.0, 0.0, 0) PORT_SENSITIVITY(70) PORT_KEYDELTA(30) PORT_MINMAX(0,255 ) PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0020)
- PORT_START("ZAPPER2_Y")
- PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_Y) PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_SENSITIVITY(50) PORT_KEYDELTA(30) PORT_MINMAX(0,255 ) PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0020)
- PORT_START("ZAPPER2_T")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("P2 Lightgun Trigger") PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0020)
-INPUT_PORTS_END
-
-static INPUT_PORTS_START( nes_paddle )
- PORT_START("PADDLE")
- PORT_BIT( 0xff, 0x7f, IPT_PADDLE) PORT_SENSITIVITY(25) PORT_KEYDELTA(25) PORT_CENTERDELTA(0) PORT_MINMAX(0x62,0xf2) PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0040)
- PORT_START("PADDLE_BUTTON")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("Paddle button") PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0040)
-INPUT_PORTS_END
-
static INPUT_PORTS_START( nes )
- PORT_INCLUDE( nes_pads12 )
- PORT_INCLUDE( nes_pads34 )
- PORT_INCLUDE( nes_powerpad )
- PORT_INCLUDE( nes_zapper1 )
- PORT_INCLUDE( nes_zapper2 )
- PORT_INCLUDE( nes_paddle )
-
- PORT_START("CTRLSEL")
- PORT_CONFNAME( 0x000f, 0x0001, "P1 Controller")
- PORT_CONFSETTING( 0x0000, "Unconnected" )
- PORT_CONFSETTING( 0x0001, "Gamepad" )
- PORT_CONFSETTING( 0x0002, "Zapper" )
- PORT_CONFNAME( 0x00f0, 0x0010, "P2 Controller")
- PORT_CONFSETTING( 0x0000, "Unconnected" )
- PORT_CONFSETTING( 0x0010, "Gamepad" )
- PORT_CONFSETTING( 0x0020, "Zapper" )
- PORT_CONFSETTING( 0x0040, "Arkanoid paddle" )
- PORT_CONFSETTING( 0x0050, "Power Pad (Side A layout)" )
- PORT_CONFSETTING( 0x0060, "Power Pad (Side B layout)" )
- PORT_CONFNAME( 0x0f00, 0x0000, "P3 Controller")
- PORT_CONFSETTING( 0x0000, "Unconnected" )
- PORT_CONFSETTING( 0x0100, "Gamepad" )
- PORT_CONFNAME( 0xf000, 0x0000, "P4 Controller")
- PORT_CONFSETTING( 0x0000, "Unconnected" )
- PORT_CONFSETTING( 0x1000, "Gamepad" )
-
+ // input devices go through slot options
PORT_START("CONFIG")
PORT_CONFNAME( 0x01, 0x00, "Draw Top/Bottom 8 Lines")
PORT_CONFSETTING( 0x01, DEF_STR(No) )
@@ -191,440 +59,8 @@ static INPUT_PORTS_START( nes )
PORT_CONFSETTING( 0x00, DEF_STR(Yes) )
INPUT_PORTS_END
-
-static INPUT_PORTS_START( fc_pads12 )
- PORT_START("PAD1")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("P1 A") PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x000f, EQUALS, 0x0001)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("P1 B") PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x000f, EQUALS, 0x0001)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_SELECT ) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x000f, EQUALS, 0x0001)
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_START ) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x000f, EQUALS, 0x0001)
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x000f, EQUALS, 0x0001)
- PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x000f, EQUALS, 0x0001)
- PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x000f, EQUALS, 0x0001)
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x000f, EQUALS, 0x0001)
-
- PORT_START("PAD2")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("P2 A") PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0010)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("P2 B") PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0010)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_SELECT ) PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0010)
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_START ) PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0010)
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0010)
- PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0010)
- PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0010)
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0010)
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("P2 A") PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x00f0)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("P2 B") PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x00f0)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_SELECT ) PORT_NAME("Microphone") PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x00f0)
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x00f0)
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x00f0)
- PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x00f0)
- PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x00f0)
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x00f0)
-INPUT_PORTS_END
-
-static INPUT_PORTS_START( fc_pads34 )
- PORT_START("PAD3")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("P3 A") PORT_PLAYER(3) PORT_CONDITION("CTRLSEL", 0x0f00, EQUALS, 0x0100)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("P3 B") PORT_PLAYER(3) PORT_CONDITION("CTRLSEL", 0x0f00, EQUALS, 0x0100)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_SELECT ) PORT_PLAYER(3) PORT_CONDITION("CTRLSEL", 0x0f00, EQUALS, 0x0100)
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_START ) PORT_PLAYER(3) PORT_CONDITION("CTRLSEL", 0x0f00, EQUALS, 0x0100)
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_PLAYER(3) PORT_CONDITION("CTRLSEL", 0x0f00, EQUALS, 0x0100)
- PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_PLAYER(3) PORT_CONDITION("CTRLSEL", 0x0f00, EQUALS, 0x0100)
- PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_PLAYER(3) PORT_CONDITION("CTRLSEL", 0x0f00, EQUALS, 0x0100)
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(3) PORT_CONDITION("CTRLSEL", 0x0f00, EQUALS, 0x0100)
-
- PORT_START("PAD4")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("P4 A") PORT_PLAYER(4) PORT_CONDITION("CTRLSEL", 0xf000, EQUALS, 0x1000)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("P4 B") PORT_PLAYER(4) PORT_CONDITION("CTRLSEL", 0xf000, EQUALS, 0x1000)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_SELECT ) PORT_PLAYER(4) PORT_CONDITION("CTRLSEL", 0xf000, EQUALS, 0x1000)
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_START ) PORT_PLAYER(4) PORT_CONDITION("CTRLSEL", 0xf000, EQUALS, 0x1000)
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_PLAYER(4) PORT_CONDITION("CTRLSEL", 0xf000, EQUALS, 0x1000)
- PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_PLAYER(4) PORT_CONDITION("CTRLSEL", 0xf000, EQUALS, 0x1000)
- PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_PLAYER(4) PORT_CONDITION("CTRLSEL", 0xf000, EQUALS, 0x1000)
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(4) PORT_CONDITION("CTRLSEL", 0xf000, EQUALS, 0x1000)
-INPUT_PORTS_END
-
-static INPUT_PORTS_START( fc_lightgun )
- PORT_START("ZAPPER2_X")
- PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_X) PORT_CROSSHAIR(X, 1.0, 0.0, 0) PORT_SENSITIVITY(70) PORT_KEYDELTA(30) PORT_MINMAX(0,255) PORT_PLAYER(2) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x01)
- PORT_START("ZAPPER2_Y")
- PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_Y) PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_SENSITIVITY(50) PORT_KEYDELTA(30) PORT_MINMAX(0,255) PORT_PLAYER(2) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x01)
- PORT_START("ZAPPER2_T")
- PORT_BIT( 0x03, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("Lightgun Trigger") PORT_PLAYER(2) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x01)
-INPUT_PORTS_END
-
-static INPUT_PORTS_START( fc_paddle )
- PORT_START("PADDLE")
- PORT_BIT( 0xff, 0x7f, IPT_PADDLE) PORT_SENSITIVITY(25) PORT_KEYDELTA(25) PORT_CENTERDELTA(0) PORT_MINMAX(0x62,0xf2) PORT_PLAYER(2) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x04)
- PORT_START("PADDLE_BUTTON")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("Paddle button") PORT_PLAYER(2) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x04)
-INPUT_PORTS_END
-
-static INPUT_PORTS_START( fc_cclimb )
- PORT_START("CC_LEFT")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x000f, EQUALS, 0x0002)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x000f, EQUALS, 0x0002)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_SELECT ) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x000f, EQUALS, 0x0002)
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_START ) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x000f, EQUALS, 0x0002)
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_UP ) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x000f, EQUALS, 0x0002)
- PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_DOWN ) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x000f, EQUALS, 0x0002)
- PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_LEFT ) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x000f, EQUALS, 0x0002)
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICKLEFT_RIGHT ) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x000f, EQUALS, 0x0002)
-
- PORT_START("CC_RIGHT")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0020)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0020)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0020)
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0020)
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_JOYSTICKRIGHT_UP ) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0020)
- PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICKRIGHT_DOWN ) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0020)
- PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICKRIGHT_LEFT ) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0020)
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICKRIGHT_RIGHT ) PORT_PLAYER(1)PORT_CONDITION("CTRLSEL", 0x00f0, EQUALS, 0x0020)
-INPUT_PORTS_END
-
-static INPUT_PORTS_START( fc_keyboard )
- PORT_START("FCKEY0")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F8) PORT_CHAR(UCHAR_MAMEKEY(F8)) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR('[') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR(']') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Kana") PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_RSHIFT) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_BACKSLASH2) PORT_CHAR('\\') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Stop") PORT_CODE(KEYCODE_BACKSPACE) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
-
- PORT_START("FCKEY1")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F7) PORT_CHAR(UCHAR_MAMEKEY(F7)) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('@') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_COLON) PORT_CHAR(':') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(';') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CHAR('_') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CHAR('/') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('^') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
-
- PORT_START("FCKEY2")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F6) PORT_CHAR(UCHAR_MAMEKEY(F6)) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_O) PORT_CHAR('O') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_L) PORT_CHAR('L') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_K) PORT_CHAR('K') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_P) PORT_CHAR('P') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
-
- PORT_START("FCKEY3")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F5) PORT_CHAR(UCHAR_MAMEKEY(F5)) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_I) PORT_CHAR('I') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_U) PORT_CHAR('U') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_J) PORT_CHAR('J') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_M) PORT_CHAR('M') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_N) PORT_CHAR('N') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
-
- PORT_START("FCKEY4")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F4) PORT_CHAR(UCHAR_MAMEKEY(F4)) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Y) PORT_CHAR('Y') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_G) PORT_CHAR('G') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_H) PORT_CHAR('H') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_B) PORT_CHAR('B') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_V) PORT_CHAR('V') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
-
- PORT_START("FCKEY5")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F3) PORT_CHAR(UCHAR_MAMEKEY(F3)) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_T) PORT_CHAR('T') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_R) PORT_CHAR('R') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_D) PORT_CHAR('D') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F) PORT_CHAR('F') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_C) PORT_CHAR('C') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
-
- PORT_START("FCKEY6")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F2) PORT_CHAR(UCHAR_MAMEKEY(F2)) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_W) PORT_CHAR('W') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_S) PORT_CHAR('S') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_A) PORT_CHAR('A') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_X) PORT_CHAR('X') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Z) PORT_CHAR('Z') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_E) PORT_CHAR('E') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
-
- PORT_START("FCKEY7")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F1) PORT_CHAR(UCHAR_MAMEKEY(F1)) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_TAB) PORT_CHAR(UCHAR_MAMEKEY(ESC)) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Q) PORT_CHAR('Q') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_LCONTROL) PORT_CHAR(UCHAR_SHIFT_2) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_SHIFT_1) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Grph") PORT_CODE(KEYCODE_LALT) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
-
- PORT_START("FCKEY8")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Clr") PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP)) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT)) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT)) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN)) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Del") PORT_CODE(KEYCODE_DEL) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Ins") PORT_CODE(KEYCODE_INSERT) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x02)
-
-INPUT_PORTS_END
-
-static INPUT_PORTS_START( subor_keyboard )
- PORT_START("SUBKEY0")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_G) PORT_CHAR('G') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F) PORT_CHAR('F') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_C) PORT_CHAR('C') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F2) PORT_CHAR(UCHAR_MAMEKEY(F2)) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_E) PORT_CHAR('E') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_V) PORT_CHAR('V') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
-
- PORT_START("SUBKEY1")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_D) PORT_CHAR('D') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_S) PORT_CHAR('S') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_END) PORT_CHAR(UCHAR_MAMEKEY(END)) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F1) PORT_CHAR(UCHAR_MAMEKEY(F1)) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_W) PORT_CHAR('W') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_X) PORT_CHAR('X') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
-
- PORT_START("SUBKEY2")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_INSERT) PORT_CHAR(UCHAR_MAMEKEY(INSERT)) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("NEXT") PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT)) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F8) PORT_CHAR(UCHAR_MAMEKEY(F8)) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("PRIOR") PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_DEL) PORT_CHAR(UCHAR_MAMEKEY(DEL)) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_HOME) PORT_CHAR(UCHAR_MAMEKEY(HOME)) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
-
- PORT_START("SUBKEY3")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_I) PORT_CHAR('I') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_L) PORT_CHAR('L') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F5) PORT_CHAR(UCHAR_MAMEKEY(F5)) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_O) PORT_CHAR('O') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
-
- PORT_START("SUBKEY4")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(']') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP)) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT)) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F7) PORT_CHAR(UCHAR_MAMEKEY(F7)) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('[') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('\\') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN)) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
-
- PORT_START("SUBKEY5")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Q) PORT_CHAR('Q') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_CAPSLOCK) PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK)) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Z) PORT_CHAR('Z') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_TAB) PORT_CHAR('\t') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_ESC) PORT_CHAR(UCHAR_MAMEKEY(ESC)) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_A) PORT_CHAR('A') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_LCONTROL) PORT_CHAR(UCHAR_SHIFT_2) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
-
- PORT_START("SUBKEY6")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Y) PORT_CHAR('Y') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_K) PORT_CHAR('K') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_M) PORT_CHAR('M') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F4) PORT_CHAR(UCHAR_MAMEKEY(F4)) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_U) PORT_CHAR('U') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_J) PORT_CHAR('J') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
-
- PORT_START("SUBKEY7")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_COLON) PORT_CHAR(':') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR('\'') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F6) PORT_CHAR(UCHAR_MAMEKEY(F6)) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_P) PORT_CHAR('P') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_SHIFT_1) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
-
- PORT_START("SUBKEY8")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_T) PORT_CHAR('T') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_H) PORT_CHAR('H') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_N) PORT_CHAR('N') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F3) PORT_CHAR(UCHAR_MAMEKEY(F3)) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_R) PORT_CHAR('R') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_B) PORT_CHAR('B') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
-
- PORT_START("SUBKEY9")
- PORT_BIT( 0xff, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
-
- PORT_START("SUBKEY10")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("LMENU") PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_4_PAD) PORT_CHAR(UCHAR_MAMEKEY(4_PAD)) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_7_PAD) PORT_CHAR(UCHAR_MAMEKEY(7_PAD)) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F11) PORT_CHAR(UCHAR_MAMEKEY(F11)) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F12) PORT_CHAR(UCHAR_MAMEKEY(F12)) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_1_PAD) PORT_CHAR(UCHAR_MAMEKEY(1_PAD)) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_2_PAD) PORT_CHAR(UCHAR_MAMEKEY(2_PAD)) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_8_PAD) PORT_CHAR(UCHAR_MAMEKEY(8_PAD)) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
-
- PORT_START("SUBKEY11")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_MINUS_PAD)PORT_CHAR(UCHAR_MAMEKEY(MINUS_PAD)) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_PLUS_PAD) PORT_CHAR(UCHAR_MAMEKEY(PLUS_PAD)) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_ASTERISK) PORT_CHAR(UCHAR_MAMEKEY(ASTERISK)) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_9_PAD) PORT_CHAR(UCHAR_MAMEKEY(9_PAD)) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F10) PORT_CHAR(UCHAR_MAMEKEY(F10)) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_5_PAD) PORT_CHAR(UCHAR_MAMEKEY(5_PAD)) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_SLASH_PAD)PORT_CHAR(UCHAR_MAMEKEY(SLASH_PAD)) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_NUMLOCK) PORT_CHAR(UCHAR_MAMEKEY(NUMLOCK)) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
-
- PORT_START("SUBKEY12")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_TILDE) PORT_CHAR('`') PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_6_PAD) PORT_CHAR(UCHAR_MAMEKEY(6_PAD)) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("PAUSE") PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("SPACE2") PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F9) PORT_CHAR(UCHAR_MAMEKEY(F9)) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_3_PAD) PORT_CHAR(UCHAR_MAMEKEY(3_PAD)) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Keypad .") PORT_CODE(KEYCODE_DEL_PAD) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_0_PAD) PORT_CHAR(UCHAR_MAMEKEY(0_PAD)) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x03)
-
-INPUT_PORTS_END
-
-static INPUT_PORTS_START( mahjong_panel )
- PORT_START("MAH0")
- PORT_BIT( 0xff, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x07)
-
- PORT_START("MAH1")
- PORT_BIT( 0x03, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x07)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_MAHJONG_N ) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x07)
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_MAHJONG_M ) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x07)
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_MAHJONG_L ) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x07)
- PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_MAHJONG_K ) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x07)
- PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_MAHJONG_J ) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x07)
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_MAHJONG_I ) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x07)
-
- PORT_START("MAH2")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_MAHJONG_H ) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x07)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_MAHJONG_G ) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x07)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_MAHJONG_F ) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x07)
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_MAHJONG_E ) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x07)
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_MAHJONG_D ) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x07)
- PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_MAHJONG_C ) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x07)
- PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_MAHJONG_B ) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x07)
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_MAHJONG_A ) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x07)
-
- PORT_START("MAH3")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x07)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_MAHJONG_RON ) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x07)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_MAHJONG_REACH ) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x07)
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_MAHJONG_CHI ) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x07)
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_MAHJONG_PON ) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x07)
- PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_MAHJONG_KAN ) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x07)
- PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_SELECT ) PORT_NAME("P1 Mahjong Select") PORT_CONDITION("EXP", 0x0f, EQUALS, 0x07)
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_START ) PORT_NAME("P1 Mahjong Start") PORT_CONDITION("EXP", 0x0f, EQUALS, 0x07)
-INPUT_PORTS_END
-
-// these are read differently than the powerpad inputs, but we share the tags, to reduce
-static INPUT_PORTS_START( fc_ftrainer )
-// difference between the two sides is that we mirror the key mapping to match the real pad layout!
- PORT_START("FT_COL0")
-// side A layout
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x05)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer Mid1") PORT_CODE(KEYCODE_J) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x05)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x05)
-// side B layout
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer 12") PORT_CODE(KEYCODE_M) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x06)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer 8") PORT_CODE(KEYCODE_J) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x06)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer 4") PORT_CODE(KEYCODE_U) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x06)
-
- PORT_START("FT_COL1")
-// side A layout
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer Low1") PORT_CODE(KEYCODE_N) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x05)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer Mid2") PORT_CODE(KEYCODE_H) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x05)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer Top1") PORT_CODE(KEYCODE_Y) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x05)
-// side B layout
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer 11") PORT_CODE(KEYCODE_N) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x06)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer 7") PORT_CODE(KEYCODE_H) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x06)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer 3") PORT_CODE(KEYCODE_Y) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x06)
-
- PORT_START("FT_COL2")
-// side A layout
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer Low2") PORT_CODE(KEYCODE_B) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x05)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer Mid3") PORT_CODE(KEYCODE_G) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x05)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer Top2") PORT_CODE(KEYCODE_T) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x05)
-// side B layout
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer 10") PORT_CODE(KEYCODE_B) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x06)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer 6") PORT_CODE(KEYCODE_G) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x06)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer 2") PORT_CODE(KEYCODE_T) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x06)
-
- PORT_START("FT_COL3")
-// side A layout
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x05)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer Mid4") PORT_CODE(KEYCODE_F) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x05)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x05)
-// side B layout
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer 9") PORT_CODE(KEYCODE_V) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x06)
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer 5") PORT_CODE(KEYCODE_F) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x06)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_NAME("Family Trainer 1") PORT_CODE(KEYCODE_R) PORT_CONDITION("EXP", 0x0f, EQUALS, 0x06)
-INPUT_PORTS_END
-
-
-
static INPUT_PORTS_START( famicom )
- PORT_INCLUDE( fc_pads12 )
- PORT_INCLUDE( fc_pads34 )
- PORT_INCLUDE( fc_lightgun )
- // FIXME: was it possible to attache two paddles in a Famicom (as the Arkanoid 2 box suggests)?!? investigate...
- PORT_INCLUDE( fc_paddle )
- // Crazy Climber is not really a separate controller, but a couple of small sticks to be
- // put on top of d-pads of the regular controllers. Users should then control the game
- // by using both controllers, turned 90 degrees, as a couple of dual sticks as in the arcade
- PORT_INCLUDE( fc_cclimb )
- PORT_INCLUDE( fc_keyboard )
- PORT_INCLUDE( subor_keyboard )
- PORT_INCLUDE( mahjong_panel )
- PORT_INCLUDE( fc_ftrainer )
-
- PORT_START("CTRLSEL")
- PORT_CONFNAME( 0x000f, 0x0001, "P1 Controller")
- PORT_CONFSETTING( 0x0000, "Unconnected" )
- PORT_CONFSETTING( 0x0001, "Gamepad" )
- PORT_CONFSETTING( 0x0002, "Crazy Climber pad (Left)" )
- PORT_CONFNAME( 0x00f0, 0x0010, "P2 Controller")
- PORT_CONFSETTING( 0x0000, "Unconnected" )
- PORT_CONFSETTING( 0x0010, "Gamepad" )
- PORT_CONFSETTING( 0x0020, "Crazy Climber pad (Right)" )
- PORT_CONFSETTING( 0x00f0, "Gamepad (Older Version)" )
- PORT_CONFNAME( 0x0f00, 0x0000, "P3 Controller") PORT_CONDITION("EXP", 0x0f, EQUALS, 0x08)
- PORT_CONFSETTING( 0x0000, "Unconnected" )
- PORT_CONFSETTING( 0x0100, "Gamepad" )
- PORT_CONFNAME( 0xf000, 0x0000, "P4 Controller") PORT_CONDITION("EXP", 0x0f, EQUALS, 0x08)
- PORT_CONFSETTING( 0x0000, "Unconnected" )
- PORT_CONFSETTING( 0x1000, "Gamepad" )
-
- PORT_START("EXP")
- PORT_CONFNAME( 0x0f, 0x00, "Expansion Port")
- PORT_CONFSETTING( 0x00, "(Empty)" )
- PORT_CONFSETTING( 0x01, "Light Gun" )
- PORT_CONFSETTING( 0x02, "FC Keyboard" )
- PORT_CONFSETTING( 0x03, "Subor Keyboard" )
- PORT_CONFSETTING( 0x04, "Arkanoid paddle" )
- PORT_CONFSETTING( 0x05, "Family Trainer (Side A)" )
- PORT_CONFSETTING( 0x06, "Family Trainer (Side B)" )
- PORT_CONFSETTING( 0x07, "Mahjong Panel" )
- PORT_CONFSETTING( 0x08, "Hori Twin Adapter" )
-
+ // input devices go through slot options
PORT_START("CONFIG")
PORT_CONFNAME( 0x01, 0x00, "Draw Top/Bottom 8 Lines")
PORT_CONFSETTING( 0x01, DEF_STR(No) )
@@ -634,7 +70,7 @@ static INPUT_PORTS_START( famicom )
PORT_CONFSETTING( 0x00, DEF_STR(Yes) )
PORT_START("FLIPDISK") /* fake key */
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON3) PORT_NAME("Change Disk Side")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("Change Disk Side") PORT_CODE(KEYCODE_SPACE)
INPUT_PORTS_END
@@ -674,6 +110,11 @@ static MACHINE_CONFIG_START( nes, nes_state )
MCFG_NES_APU_CPU("maincpu")
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.90)
+ MCFG_NES_CONTROL_PORT_ADD("ctrl1", nes_control_port1_devices, "joypad")
+ MCFG_NESCTRL_BRIGHTPIXEL_CB(nes_state, bright_pixel)
+ MCFG_NES_CONTROL_PORT_ADD("ctrl2", nes_control_port2_devices, "joypad")
+ MCFG_NESCTRL_BRIGHTPIXEL_CB(nes_state, bright_pixel)
+
MCFG_NES_CARTRIDGE_ADD("nes_slot", nes_cart, NULL)
MCFG_SOFTWARE_LIST_ADD("cart_list", "nes")
MCFG_SOFTWARE_LIST_ADD("ade_list", "nes_ade") // Camerica/Codemasters Aladdin Deck Enhancer mini-carts
@@ -729,9 +170,12 @@ static MACHINE_CONFIG_DERIVED( dendy, nes )
MACHINE_CONFIG_END
static MACHINE_CONFIG_DERIVED( famicom, nes )
- MCFG_CASSETTE_ADD( "tape" )
- MCFG_CASSETTE_DEFAULT_STATE(CASSETTE_STOPPED | CASSETTE_MOTOR_ENABLED | CASSETTE_SPEAKER_ENABLED)
- MCFG_CASSETTE_INTERFACE("fc_cass")
+ MCFG_DEVICE_REMOVE("ctrl1")
+ MCFG_DEVICE_REMOVE("ctrl2")
+ MCFG_NES_CONTROL_PORT_ADD("ctrl1", fc_control_port1_devices, "joypad")
+ MCFG_NES_CONTROL_PORT_ADD("ctrl2", fc_control_port2_devices, "joypad")
+ MCFG_FC_EXPANSION_PORT_ADD("exp", fc_expansion_devices, NULL)
+ MCFG_NESCTRL_BRIGHTPIXEL_CB(nes_state, bright_pixel)
MCFG_SOFTWARE_LIST_ADD("flop_list", "famicom_flop")
MCFG_SOFTWARE_LIST_ADD("cass_list", "famicom_cass")
@@ -769,9 +213,11 @@ void nes_state::setup_disk(nes_disksys_device *slot)
MACHINE_START_MEMBER( nes_state, fds )
{
m_ciram = auto_alloc_array(machine(), UINT8, 0x800);
- setup_ioports();
setup_disk(m_disk);
- state_register();
+
+ // register saves
+ save_item(NAME(m_last_frame_flip));
+ save_pointer(NAME(m_ciram), 0x800);
}
MACHINE_RESET_MEMBER( nes_state, fds )
@@ -781,17 +227,11 @@ MACHINE_RESET_MEMBER( nes_state, fds )
// the rest is the same as for nes/famicom/dendy
m_maincpu->reset();
-
- memset(m_pad_latch, 0, sizeof(m_pad_latch));
- memset(m_zapper_latch, 0, sizeof(m_zapper_latch));
- m_paddle_latch = 0;
- m_paddle_btn_latch = 0;
}
static MACHINE_CONFIG_DERIVED( fds, famicom )
MCFG_MACHINE_START_OVERRIDE( nes_state, fds )
MCFG_MACHINE_RESET_OVERRIDE( nes_state, fds )
- MCFG_DEVICE_REMOVE("tape")
MCFG_DEVICE_REMOVE("nes_slot")
MCFG_DEVICE_ADD("disk", NES_DISKSYS, 0)
@@ -827,11 +267,6 @@ MACHINE_RESET_MEMBER( nes_state, famitwin )
// the rest is the same as for nes/famicom/dendy
m_maincpu->reset();
-
- memset(m_pad_latch, 0, sizeof(m_pad_latch));
- memset(m_zapper_latch, 0, sizeof(m_zapper_latch));
- m_paddle_latch = 0;
- m_paddle_btn_latch = 0;
}
static MACHINE_CONFIG_DERIVED( famitwin, famicom )
diff --git a/src/mess/includes/nes.h b/src/mess/includes/nes.h
index 02b22a2b9c5..7c34c693545 100644
--- a/src/mess/includes/nes.h
+++ b/src/mess/includes/nes.h
@@ -13,8 +13,8 @@
#include "video/ppu2c0x.h"
#include "bus/nes/nes_slot.h"
#include "bus/nes/nes_carts.h"
+#include "bus/nes_ctrl/ctrl.h"
#include "sound/nes_apu.h"
-#include "imagedev/cassette.h"
/***************************************************************************
CONSTANTS
@@ -30,12 +30,6 @@
TYPE DEFINITIONS
***************************************************************************/
-struct nes_input
-{
- UINT32 shift;
- UINT32 i0, i1, i2;
-};
-
/*PPU fast banking constants and structures */
#define CHRROM 0
@@ -57,44 +51,22 @@ struct nes_input
class nes_state : public driver_device
{
public:
- enum
- {
- TIMER_ZAPPER_TICK,
- TIMER_LIGHTGUN_TICK
- };
-
nes_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag),
m_maincpu(*this, "maincpu"),
m_ppu(*this, "ppu"),
m_sound(*this, "nessound"),
+ m_ctrl1(*this, "ctrl1"),
+ m_ctrl2(*this, "ctrl2"),
+ m_exp(*this, "exp"),
m_cartslot(*this, "nes_slot"),
- m_disk(*this, "disk"),
- m_cassette(*this, "tape")
+ m_disk(*this, "disk")
{ }
/* video-related */
int m_last_frame_flip;
/* misc */
- ioport_port *m_io_ctrlsel;
- ioport_port *m_io_fckey[9];
- ioport_port *m_io_subkey[13];
- ioport_port *m_io_pad[4];
- ioport_port *m_io_powerpad[2];
- ioport_port *m_io_mahjong[4];
- ioport_port *m_io_ftrainer[4];
- ioport_port *m_io_cc_left;
- ioport_port *m_io_cc_right;
- ioport_port *m_io_zapper1_t;
- ioport_port *m_io_zapper1_x;
- ioport_port *m_io_zapper1_y;
- ioport_port *m_io_zapper2_t;
- ioport_port *m_io_zapper2_x;
- ioport_port *m_io_zapper2_y;
- ioport_port *m_io_paddle;
- ioport_port *m_io_paddle_btn;
- ioport_port *m_io_exp;
ioport_port *m_io_disksel;
UINT8 *m_vram;
@@ -103,9 +75,11 @@ public:
required_device<cpu_device> m_maincpu;
required_device<ppu2c0x_device> m_ppu;
required_device<nesapu_device> m_sound;
+ required_device<nes_control_port_device> m_ctrl1;
+ required_device<nes_control_port_device> m_ctrl2;
+ optional_device<nes_control_port_device> m_exp;
optional_device<nes_cart_slot_device> m_cartslot;
optional_device<nes_disksys_device> m_disk;
- optional_device<cassette_image_device> m_cassette;
int nes_ppu_vidaccess(int address, int data);
void ppu_nmi(int *ppu_regs);
@@ -113,7 +87,6 @@ public:
DECLARE_READ8_MEMBER(nes_in0_r);
DECLARE_READ8_MEMBER(nes_in1_r);
DECLARE_WRITE8_MEMBER(nes_in0_w);
- DECLARE_WRITE8_MEMBER(nes_in1_w);
DECLARE_READ8_MEMBER(fc_in0_r);
DECLARE_READ8_MEMBER(fc_in1_r);
DECLARE_WRITE8_MEMBER(fc_in0_w);
@@ -127,8 +100,7 @@ public:
DECLARE_READ8_MEMBER(psg_4015_r);
DECLARE_WRITE8_MEMBER(psg_4015_w);
DECLARE_WRITE8_MEMBER(psg_4017_w);
- void state_register();
- void setup_ioports();
+ NESCTRL_BRIGHTPIXEL_CB(bright_pixel);
DECLARE_DRIVER_INIT(famicom);
@@ -139,19 +111,6 @@ public:
DECLARE_MACHINE_RESET(famitwin);
void setup_disk(nes_disksys_device *slot);
- // input related
- UINT32 m_pad_latch[4];
- UINT8 m_zapper_latch[2][3];
- UINT8 m_paddle_latch, m_paddle_btn_latch;
- UINT8 m_mjpanel_latch;
- UINT8 m_fck_scan, m_fck_mode;
- UINT8 m_mic_obstruct;
- UINT8 m_powerpad_latch[2];
- UINT8 m_ftrainer_scan;
-
-protected:
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
-
private:
memory_bank *m_prg_bank_mem[5];
};
diff --git a/src/mess/machine/nes.c b/src/mess/machine/nes.c
index 14ca4c6aabe..b6cf0d1d086 100644
--- a/src/mess/machine/nes.c
+++ b/src/mess/machine/nes.c
@@ -7,21 +7,8 @@
****************************************************************************/
#include "emu.h"
-#include "crsshair.h"
#include "cpu/m6502/m6502.h"
#include "includes/nes.h"
-#include "imagedev/flopdrv.h"
-
-/***************************************************************************
- CONSTANTS
-***************************************************************************/
-
-/* Set to dump info about the inputs to the errorlog */
-#define LOG_JOY 0
-
-/* Set to generate prg & chr files when the cart is loaded */
-#define SPLIT_PRG 0
-#define SPLIT_CHR 0
/***************************************************************************
FUNCTIONS
@@ -44,77 +31,12 @@ void nes_state::machine_reset()
m_cartslot->pcb_reset();
m_maincpu->reset();
-
- memset(m_pad_latch, 0, sizeof(m_pad_latch));
- memset(m_zapper_latch, 0, sizeof(m_zapper_latch));
- m_paddle_latch = 0;
- m_paddle_btn_latch = 0;
}
//-------------------------------------------------
// machine_start
//-------------------------------------------------
-void nes_state::state_register()
-{
- save_item(NAME(m_last_frame_flip));
-
- save_pointer(NAME(m_ciram), 0x800);
-
- save_item(NAME(m_pad_latch));
- save_item(NAME(m_zapper_latch));
- save_item(NAME(m_paddle_latch));
- save_item(NAME(m_paddle_btn_latch));
- save_item(NAME(m_mjpanel_latch));
- save_item(NAME(m_fck_scan));
- save_item(NAME(m_fck_mode));
- save_item(NAME(m_mic_obstruct));
- save_item(NAME(m_powerpad_latch));
- save_item(NAME(m_ftrainer_scan));
-}
-
-void nes_state::setup_ioports()
-{
- for (int i = 0; i < 9; i++)
- {
- char str[7];
- sprintf(str, "FCKEY%i", i);
- m_io_fckey[i] = ioport(str);
- }
- for (int i = 0; i < 13; i++)
- {
- char str[9];
- sprintf(str, "SUBKEY%i", i);
- m_io_subkey[i] = ioport(str);
- }
- for (int i = 0; i < 4; i++)
- {
- char str[8];
- sprintf(str, "PAD%i", i + 1);
- m_io_pad[i] = ioport(str);
- sprintf(str, "MAH%i", i);
- m_io_mahjong[i] = ioport(str);
- sprintf(str, "FT_COL%i", i);
- m_io_ftrainer[i] = ioport(str);
- }
-
- m_io_ctrlsel = ioport("CTRLSEL");
- m_io_exp = ioport("EXP");
- m_io_paddle = ioport("PADDLE");
- m_io_paddle_btn = ioport("PADDLE_BUTTON");
- m_io_cc_left = ioport("CC_LEFT");
- m_io_cc_right = ioport("CC_RIGHT");
- m_io_zapper1_t = ioport("ZAPPER1_T");
- m_io_zapper1_x = ioport("ZAPPER1_X");
- m_io_zapper1_y = ioport("ZAPPER1_Y");
- m_io_zapper2_t = ioport("ZAPPER2_T");
- m_io_zapper2_x = ioport("ZAPPER2_X");
- m_io_zapper2_y = ioport("ZAPPER2_Y");
- m_io_powerpad[0] = ioport("POWERPAD1");
- m_io_powerpad[1] = ioport("POWERPAD2");
- m_io_disksel = ioport("FLIPDISK");
-}
-
void nes_state::machine_start()
{
address_space &space = m_maincpu->space(AS_PROGRAM);
@@ -126,7 +48,7 @@ void nes_state::machine_start()
m_ciram = auto_alloc_array(machine(), UINT8, 0x800);
// other pointers got set in the loading routine, because they 'belong' to the cart itself
- setup_ioports();
+ m_io_disksel = ioport("FLIPDISK");
if (m_cartslot && m_cartslot->m_cart)
{
@@ -178,7 +100,9 @@ void nes_state::machine_start()
m_cartslot->m_cart->pcb_reg_postload(machine());
}
- state_register();
+ // register saves
+ save_item(NAME(m_last_frame_flip));
+ save_pointer(NAME(m_ciram), 0x800);
}
@@ -188,518 +112,71 @@ void nes_state::machine_start()
READ8_MEMBER(nes_state::nes_in0_r)
{
- int cfg = m_io_ctrlsel->read();
-
- // Some games expect bit 6 to be set because the last entry on the data bus shows up
- // in the unused upper 3 bits, so typically a read from $4016 leaves 0x40 there.
UINT8 ret = 0x40;
- ret |= (m_pad_latch[0] & 0x01);
-
- // shift
- m_pad_latch[0] >>= 1;
-
- // zapper
- if ((cfg & 0x000f) == 0x0002)
- {
- int x = m_zapper_latch[0][1]; // x-position
- int y = m_zapper_latch[0][2]; // y-position
- UINT32 pix, color_base;
-
- // get the pixel at the gun position
- pix = m_ppu->get_pixel(x, y);
-
- // get the color base from the ppu
- color_base = m_ppu->get_colorbase();
-
- // check if the cursor is over a bright pixel
- if ((pix == color_base + 0x20) || (pix == color_base + 0x30) ||
- (pix == color_base + 0x33) || (pix == color_base + 0x34))
- ret &= ~0x08; // sprite hit
- else
- ret |= 0x08; // no sprite hit
-
- // light gun trigger
- ret |= (m_zapper_latch[0][0] << 4);
- }
-
- if (LOG_JOY)
- logerror("joy 0 read, val: %02x, pc: %04x\n", ret, space.device().safe_pc());
-
+ ret |= m_ctrl1->read_bit0();
+ ret |= m_ctrl1->read_bit34();
return ret;
}
READ8_MEMBER(nes_state::nes_in1_r)
{
- int cfg = m_io_ctrlsel->read();
-
- // Some games expect bit 6 to be set because the last entry on the data bus shows up
- // in the unused upper 3 bits, so typically a read from $4017 leaves 0x40 there.
UINT8 ret = 0x40;
- ret |= (m_pad_latch[1] & 0x01);
-
- // shift
- m_pad_latch[1] >>= 1;
-
- // zapper
- if ((cfg & 0x00f0) == 0x0020)
- {
- int x = m_zapper_latch[1][1]; // x-position
- int y = m_zapper_latch[1][2]; // y-position
- UINT32 pix, color_base;
-
- // get the pixel at the gun position
- pix = m_ppu->get_pixel(x, y);
-
- // get the color base from the ppu
- color_base = m_ppu->get_colorbase();
-
- // check if the cursor is over a bright pixel
- if ((pix == color_base + 0x20) || (pix == color_base + 0x30) ||
- (pix == color_base + 0x33) || (pix == color_base + 0x34))
- ret &= ~0x08; // sprite hit
- else
- ret |= 0x08; // no sprite hit
-
- // light gun trigger
- ret |= (m_zapper_latch[1][0] << 4);
- }
-
- // arkanoid paddle
- if ((cfg & 0x00f0) == 0x0040)
- {
- ret |= (m_paddle_btn_latch << 3); // button
- ret |= ((m_paddle_latch & 0x80) >> 3); // paddle data
- m_paddle_latch <<= 1;
- m_paddle_latch &= 0xff;
- }
-
- // powerpad
- if ((cfg & 0x00f0) == 0x0050 || (cfg & 0x00f0) == 0x0060)
- {
- ret |= ((m_powerpad_latch[0] & 0x01) << 3);
- ret |= ((m_powerpad_latch[1] & 0x01) << 4);
- m_powerpad_latch[0] >>= 1;
- m_powerpad_latch[1] >>= 1;
- }
-
- if (LOG_JOY)
- logerror("joy 1 read, val: %02x, pc: %04x\n", ret, space.device().safe_pc());
-
+ ret |= m_ctrl2->read_bit0();
+ ret |= m_ctrl2->read_bit34();
return ret;
}
WRITE8_MEMBER(nes_state::nes_in0_w)
{
- int cfg = m_io_ctrlsel->read();
-
- if (LOG_JOY)
- logerror("joy write, val: %02x, pc: %04x\n", data, space.device().safe_pc());
-
- // Check if lightgun has been chosen as input: if so, enable crosshair
- timer_set(attotime::zero, TIMER_ZAPPER_TICK);
-
- if (data & 0x01)
- return;
-
- // Toggling bit 0 high then low resets controllers
- m_pad_latch[0] = 0;
- m_pad_latch[1] = 0;
- m_zapper_latch[0][0] = 0;
- m_zapper_latch[0][1] = 0;
- m_zapper_latch[0][2] = 0;
- m_zapper_latch[1][0] = 0;
- m_zapper_latch[1][1] = 0;
- m_zapper_latch[1][2] = 0;
- m_paddle_btn_latch = 0;
- m_paddle_latch = 0;
- m_powerpad_latch[0] = 0;
- m_powerpad_latch[1] = 0;
-
- // P1 inputs
- switch (cfg & 0x000f)
- {
- case 0x01: // pad 1
- m_pad_latch[0] = m_io_pad[0]->read();
- break;
-
- case 0x02: // zapper (secondary)
- m_zapper_latch[0][0] = m_io_zapper1_t->read();
- m_zapper_latch[0][1] = m_io_zapper1_x->read();
- m_zapper_latch[0][2] = m_io_zapper1_y->read();
- break;
- }
-
- // P2 inputs
- switch ((cfg & 0x00f0) >> 4)
- {
- case 0x01: // pad 2
- m_pad_latch[1] = m_io_pad[1]->read();
- break;
-
- case 0x02: // zapper (primary) - most games expect pad in port1 & zapper in port2
- m_zapper_latch[1][0] = m_io_zapper2_t->read();
- m_zapper_latch[1][1] = m_io_zapper2_x->read();
- m_zapper_latch[1][2] = m_io_zapper2_y->read();
- break;
-
- case 0x04: // arkanoid paddle
- m_paddle_btn_latch = m_io_paddle_btn->read();
- m_paddle_latch = (UINT8) (m_io_paddle->read() ^ 0xff);
- break;
-
- case 0x05: // power pad
- case 0x06: // power pad
- m_powerpad_latch[0] = m_io_powerpad[0]->read();
- m_powerpad_latch[1] = m_io_powerpad[1]->read() | 0xf0;
- break;
- }
-
- // P3 & P4 inputs in NES Four Score are read serially with P1 & P2
- // P3 inputs
- if ((cfg & 0x0f00))
- m_pad_latch[0] |= ((m_io_pad[2]->read() << 8) | (0x08 << 16)); // pad 3 + signature
-
- // P4 inputs
- if ((cfg & 0xf000))
- m_pad_latch[1] |= ((m_io_pad[3]->read() << 8) | (0x04 << 16)); // pad 4 + signature
-}
-
-
-WRITE8_MEMBER(nes_state::nes_in1_w)
-{
+ m_ctrl1->write(data);
+ m_ctrl2->write(data);
}
READ8_MEMBER(nes_state::fc_in0_r)
{
- int cfg = m_io_ctrlsel->read();
- int exp = m_io_exp->read();
-
- // Some games expect bit 6 to be set because the last entry on the data bus shows up
- // in the unused upper 3 bits, so typically a read from $4016 leaves 0x40 there.
UINT8 ret = 0x40;
- ret |= (m_pad_latch[0] & 0x01);
-
- // shift
- m_pad_latch[0] >>= 1;
-
- // microphone bit
- if ((cfg & 0x00f0) == 0x00f0)
- ret |= m_mic_obstruct; //bit2!
-
- // EXP input
- switch (exp & 0x0f)
- {
- case 0x02: // FC Keyboard: tape input
- if ((m_cassette->get_state() & CASSETTE_MASK_UISTATE) == CASSETTE_PLAY)
- {
- double level = m_cassette->input();
- if (level < 0)
- ret |= 0x00;
- else
- ret |= 0x02;
- }
- break;
-
- case 0x04: // Arkanoid paddle
- ret |= (m_paddle_btn_latch << 1); // button
- break;
-
- case 0x07: // Mahjong Panel
- ret |= ((m_mjpanel_latch & 0x01) << 1);
- m_mjpanel_latch >>= 1;
- break;
-
- case 0x08: // 'multitap' p3
- ret |= ((m_pad_latch[2] & 0x01) << 1);
- m_pad_latch[2] >>= 1;
- break;
- }
-
- if (LOG_JOY)
- logerror("joy 0 read, val: %02x, pc: %04x\n", ret, space.device().safe_pc());
-
+ // bit 0 to controller port
+ ret |= m_ctrl1->read_bit0();
+
+ // expansion port bits (in the original FC, P2 controller was hooked to these lines
+ // too, so in principle some homebrew hardware modification could use the same
+ // connection with P1 controller too)
+ ret |= m_ctrl1->read_exp(0);
+ ret |= m_ctrl2->read_exp(0);
+
+ // at the same time, we might have a standard joypad connected to the expansion port which
+ // shall be read as P3 (this is needed here to avoid implementing the expansion port as a
+ // different device compared to the standard control port... it might be changed later)
+ ret |= (m_exp->read_bit0() << 1);
+ // finally, read the expansion port as expected
+ ret |= m_exp->read_exp(0);
return ret;
}
READ8_MEMBER(nes_state::fc_in1_r)
{
- int exp = m_io_exp->read();
-
- // Some games expect bit 6 to be set because the last entry on the data bus shows up
- // in the unused upper 3 bits, so typically a read from $4017 leaves 0x40 there.
UINT8 ret = 0x40;
- ret |= (m_pad_latch[1] & 0x01);
-
- // shift
- m_pad_latch[1] >>= 1;
-
-
- // EXP input
- switch (exp & 0x0f)
- {
- case 0x01: // Lightgun
- {
- int x = m_zapper_latch[0][1]; // x-position
- int y = m_zapper_latch[0][2]; // y-position
- UINT32 pix, color_base;
-
- // get the pixel at the gun position
- pix = m_ppu->get_pixel(x, y);
-
- // get the color base from the ppu
- color_base = m_ppu->get_colorbase();
-
- // check if the cursor is over a bright pixel
- if ((pix == color_base + 0x20) || (pix == color_base + 0x30) ||
- (pix == color_base + 0x33) || (pix == color_base + 0x34))
- ret &= ~0x08; // sprite hit
- else
- ret |= 0x08; // no sprite hit
-
- // light gun trigger
- ret |= (m_zapper_latch[0][0] << 4);
- }
- break;
-
- case 0x02: // FC Keyboard: rows of the keyboard matrix are read 4-bits at time and returned as bit1->bit4
- if (m_fck_scan < 9)
- ret |= ~(((m_io_fckey[m_fck_scan]->read() >> (m_fck_mode * 4)) & 0x0f) << 1) & 0x1e;
- else
- ret |= 0x1e;
- break;
-
- case 0x03: // Subor Keyboard: rows of the keyboard matrix are read 4-bits at time and returned as bit1->bit4
- if (m_fck_scan < 12)
- ret |= ~(((m_io_subkey[m_fck_scan]->read() >> (m_fck_mode * 4)) & 0x0f) << 1) & 0x1e;
- else
- ret |= 0x1e;
- break;
-
- case 0x04: // Arkanoid paddle
- ret |= ((m_paddle_latch & 0x80) >> 6); // paddle data
- m_paddle_latch <<= 1;
- m_paddle_latch &= 0xff;
- break;
-
- case 0x05: // family trainer
- case 0x06: // family trainer
- if (!BIT(m_ftrainer_scan, 0))
- {
- // read low line: buttons 9,10,11,12
- for (int i = 0; i < 4; i++)
- ret |= ((m_io_ftrainer[i]->read() & 0x01) << (1 + i));
- }
- else if (!BIT(m_ftrainer_scan, 1))
- {
- // read mid line: buttons 5,6,7,8
- for (int i = 0; i < 4; i++)
- ret |= ((m_io_ftrainer[i]->read() & 0x02) << (1 + i));
- }
- else if (!BIT(m_ftrainer_scan, 2))
- {
- // read high line: buttons 1,2,3,4
- for (int i = 0; i < 4; i++)
- ret |= ((m_io_ftrainer[i]->read() & 0x04) << (1 + i));
- }
- break;
-
- case 0x07: // Mahjong Panel
- ret |= ((m_mjpanel_latch & 0x01) << 1);
- m_mjpanel_latch >>= 1;
- break;
-
- case 0x08: // 'multitap' p4
- ret |= ((m_pad_latch[3] & 0x01) << 1);
- m_pad_latch[3] >>= 1;
- break;
- }
-
- if (LOG_JOY)
- logerror("joy 1 read, val: %02x, pc: %04x\n", ret, space.device().safe_pc());
-
+ // bit 0 to controller port
+ ret |= m_ctrl2->read_bit0();
+
+ // expansion port bits (in the original FC, P2 controller was hooked to these lines
+ // too, so in principle some homebrew hardware modification could use the same
+ // connection with P1 controller too)
+ ret |= m_ctrl1->read_exp(1);
+ ret |= m_ctrl2->read_exp(1);
+
+ // finally, read the expansion port as expected (standard pad cannot be hooked as P4, so
+ // no read_bit0 here)
+ ret |= m_exp->read_exp(1);
return ret;
}
WRITE8_MEMBER(nes_state::fc_in0_w)
{
- int cfg = m_io_ctrlsel->read();
- int exp = m_io_exp->read();
-
- if (LOG_JOY)
- logerror("joy write, val: %02x, pc: %04x\n", data, space.device().safe_pc());
-
- // Check if lightgun has been chosen as input: if so, enable crosshair
- timer_set(attotime::zero, TIMER_LIGHTGUN_TICK);
-
- // keyboards
- if ((exp & 0x0f) == 0x02 || (exp & 0x0f) == 0x03)
- {
- // tape output (not fully tested)
- if ((m_cassette->get_state() & CASSETTE_MASK_UISTATE) == CASSETTE_RECORD)
- m_cassette->output(((data & 0x07) == 0x07) ? +1.0 : -1.0);
-
- if (BIT(data, 2)) // keyboard active
- {
- int lines = ((exp & 0x0f) == 0x02) ? 9 : 12;
- UINT8 out = BIT(data, 1); // scan
-
- if (m_fck_mode && !out && ++m_fck_scan > lines)
- m_fck_scan = 0;
-
- m_fck_mode = out; // access lower or upper 4 bits
-
- if (BIT(data, 0)) // reset
- m_fck_scan = 0;
- }
- }
-
- // family trainer
- if ((exp & 0x0f) == 0x05 || (exp & 0x0f) == 0x06)
- {
- // select raw to scan
- m_ftrainer_scan = data & 0x07;
- }
-
- if (data & 0x01)
- return;
-
- // Toggling bit 0 high then low resets controllers
- m_pad_latch[0] = 0;
- m_pad_latch[1] = 0;
- m_pad_latch[2] = 0;
- m_pad_latch[3] = 0;
- m_zapper_latch[0][0] = 0;
- m_zapper_latch[0][1] = 0;
- m_zapper_latch[0][2] = 0;
- m_paddle_btn_latch = 0;
- m_paddle_latch = 0;
- m_mjpanel_latch = 0;
- m_mic_obstruct = 0;
-
- // P1 inputs
- switch (cfg & 0x000f)
- {
- case 0x01: // pad 1
- m_pad_latch[0] = m_io_pad[0]->read();
- break;
-
- case 0x02: // crazy climber (left stick)
- m_pad_latch[0] = m_io_cc_left->read();
- break;
- }
-
- // P2 inputs
- switch ((cfg & 0x00f0) >> 4)
- {
- case 0x01: // pad 2
- m_pad_latch[1] = m_io_pad[1]->read();
- break;
-
- case 0x02: // crazy climber (right stick)
- m_pad_latch[1] = m_io_cc_right->read();
- break;
-
- case 0x0f: // pad 2 old style with microphone instead of START/SELECT keys
- // we only emulate obstruction of mic (when you blow or talk into it)
- m_mic_obstruct = m_io_pad[1]->read() & 0x04;
- m_pad_latch[1] = (m_io_pad[1]->read() & ~0x04);
- break;
- }
-
- // P3 & P4 inputs in Famicom (e.g. through Hori Twin Adapter or Hori 4 Players Adapter)
- // are read in parallel with P1 & P2 (just using diff bits)
- // P3 inputs
- if ((exp & 0x0f) == 8 && (cfg & 0x0f00) == 0x0100)
- m_pad_latch[2] = m_io_pad[2]->read(); // pad 3
-
- // P4 inputs
- if ((exp & 0x0f) == 8 && (cfg & 0xf000) == 0x1000)
- m_pad_latch[3] = m_io_pad[3]->read(); // pad 4
-
-
- // EXP input
- switch (exp & 0x0f)
- {
- case 0x01: // Lightgun
- m_zapper_latch[0][0] = m_io_zapper2_t->read();
- m_zapper_latch[0][1] = m_io_zapper2_x->read();
- m_zapper_latch[0][2] = m_io_zapper2_y->read();
- break;
-
- case 0x02: // FC Keyboard
- case 0x03: // Subor Keyboard
- // these are scanned differently than other devices:
- // writes to $4016 with bit2 set always update the
- // line counter and writing bit0 set resets the counter
- break;
-
- case 0x04: // Arkanoid paddle
- m_paddle_btn_latch = m_io_paddle_btn->read();
- m_paddle_latch = (UINT8) (m_io_paddle->read() ^ 0xff);
- break;
-
- case 0x05: // family trainer
- case 0x06: // family trainer
- // these are scanned differently than other devices:
- // bit0-bit2 of writes to $4016 select the row to read
- // from from the mat input "columns"
- break;
-
-
- case 0x07: // Mahjong Panel
- if (data & 0xf8)
- logerror("Error: Mahjong panel read with mux data %02x\n", (data & 0xfe));
- else
- m_mjpanel_latch = m_io_mahjong[(data & 0xfe) >> 1]->read();
- break;
- }
-
-}
-
-
-void nes_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
-{
- switch (id)
- {
- case TIMER_ZAPPER_TICK:
- if ((m_io_ctrlsel->read() & 0x000f) == 0x0002)
- {
- /* enable lightpen crosshair */
- crosshair_set_screen(machine(), 0, CROSSHAIR_SCREEN_ALL);
- }
- else
- {
- /* disable lightpen crosshair */
- crosshair_set_screen(machine(), 0, CROSSHAIR_SCREEN_NONE);
- }
-
- if ((m_io_ctrlsel->read() & 0x00f0) == 0x0020)
- {
- /* enable lightpen crosshair */
- crosshair_set_screen(machine(), 1, CROSSHAIR_SCREEN_ALL);
- }
- else
- {
- /* disable lightpen crosshair */
- crosshair_set_screen(machine(), 1, CROSSHAIR_SCREEN_NONE);
- }
- break;
- case TIMER_LIGHTGUN_TICK:
- if ((m_io_exp->read() & 0x0f) == 0x01)
- {
- /* enable lightpen crosshair */
- crosshair_set_screen(machine(), 0, CROSSHAIR_SCREEN_ALL);
- }
- else
- {
- /* disable lightpen crosshair */
- crosshair_set_screen(machine(), 0, CROSSHAIR_SCREEN_NONE);
- }
- break;
- default:
- assert_always(FALSE, "Unknown id in nes_state::device_timer");
- }
+ m_ctrl1->write(data);
+ m_ctrl2->write(data);
+ m_exp->write(data);
}
@@ -711,3 +188,19 @@ DRIVER_INIT_MEMBER(nes_state,famicom)
space.install_write_handler(0x4016, 0x4016, write8_delegate(FUNC(nes_state::fc_in0_w), this));
space.install_read_handler(0x4017, 0x4017, read8_delegate(FUNC(nes_state::fc_in1_r), this));
}
+
+NESCTRL_BRIGHTPIXEL_CB(nes_state::bright_pixel)
+{
+ // get the pixel at the gun position
+ UINT32 pix = m_ppu->get_pixel(x, y);
+
+ // get the color base from the ppu
+ UINT32 color_base = m_ppu->get_colorbase();
+
+ // check if the cursor is over a bright pixel
+ if ((pix == color_base + 0x20) || (pix == color_base + 0x30) ||
+ (pix == color_base + 0x33) || (pix == color_base + 0x34))
+ return true;
+ else
+ return false;
+}
diff --git a/src/mess/mess.mak b/src/mess/mess.mak
index 13ae90f2b22..c454f79059f 100644
--- a/src/mess/mess.mak
+++ b/src/mess/mess.mak
@@ -614,6 +614,7 @@ BUSES += MEGADRIVE
BUSES += MSX_SLOT
BUSES += NEOGEO
BUSES += NES
+BUSES += NES_CTRL
BUSES += NUBUS
BUSES += O2
BUSES += ORICEXT