From dc360abb0220d308289e60fae597f83993d762d7 Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Thu, 8 Dec 2022 05:09:34 +1100 Subject: bus/sms_ctrl: Reworked Sega Master System controller bus. Rationalised interface, got rid of TH from the "pulled" lines, and extended to support output on all data lines. Renamed to be less specific as the same interface is shared by multiple consoles. Removed a lot of unnecessary indirection through I/O ports and multiple levels of inversion in peripheral emulation that was obfuscating the code. Made Rapid Fire Unit switches toggles so they can be assigned to controller buttons and switched on/off easily during gameplay. You can still see/change the current state in the Toggle Inputs menu if you don't want to assign buttons. Implemented idle timeout in Furrtek 4-player Master System adapter. Improved crosshair tracking in Graphic Board, added ability to raise/lower pen, and greatly cleaned up code. Fixed paddle controller when used with export consoles. Added 3-button and 6-button Mega Drive control devices. sega/sms.cpp: SG-1000 Mark III has pin 7 of controller ports tied low - indicate this to attached controllers (this pin became TH on the Master System). sega/mdconsole.cpp: Replaced controller emulation in the driver with Sega controller ports. Also removed some vestigial code from the driver base class. sharp/x68k.cpp: Replaced controller emulation in the driver with MSX controller ports. bus/msx/ctrl: Added a Sega controller adapter device, supported by X68000 software including chelnov and ssf2. --- hash/sms.xml | 14 +- scripts/src/bus.lua | 20 +- src/devices/bus/gamegear/ggext.h | 2 +- src/devices/bus/gamegear/smsctrladp.cpp | 22 +- src/devices/bus/gamegear/smsctrladp.h | 2 + src/devices/bus/msx/ctrl/ctrl.cpp | 2 + src/devices/bus/msx/ctrl/sgadapt.cpp | 112 ++++++++ src/devices/bus/msx/ctrl/sgadapt.h | 20 ++ src/devices/bus/sms_ctrl/controllers.cpp | 55 ++++ src/devices/bus/sms_ctrl/controllers.h | 28 ++ src/devices/bus/sms_ctrl/graphic.cpp | 161 ++++++------ src/devices/bus/sms_ctrl/graphic.h | 42 +-- src/devices/bus/sms_ctrl/joypad.cpp | 64 ++--- src/devices/bus/sms_ctrl/joypad.h | 35 +-- src/devices/bus/sms_ctrl/lphaser.cpp | 193 +++++++------- src/devices/bus/sms_ctrl/lphaser.h | 49 +--- src/devices/bus/sms_ctrl/md6bt.cpp | 170 +++++++++++++ src/devices/bus/sms_ctrl/md6bt.h | 18 ++ src/devices/bus/sms_ctrl/mdpad.cpp | 82 ++++++ src/devices/bus/sms_ctrl/mdpad.h | 18 ++ src/devices/bus/sms_ctrl/multitap.cpp | 166 ++++++------ src/devices/bus/sms_ctrl/multitap.h | 40 +-- src/devices/bus/sms_ctrl/paddle.cpp | 209 +++++++++------ src/devices/bus/sms_ctrl/paddle.h | 44 +--- src/devices/bus/sms_ctrl/rfu.cpp | 164 +++++++----- src/devices/bus/sms_ctrl/rfu.h | 44 +--- src/devices/bus/sms_ctrl/smsctrl.cpp | 106 ++------ src/devices/bus/sms_ctrl/smsctrl.h | 152 +++++++---- src/devices/bus/sms_ctrl/sports.cpp | 201 ++++++++------- src/devices/bus/sms_ctrl/sports.h | 52 +--- src/devices/bus/sms_ctrl/sportsjp.cpp | 149 ++++------- src/devices/bus/sms_ctrl/sportsjp.h | 48 +--- src/mame/sega/mdconsole.cpp | 338 ++++++++---------------- src/mame/sega/mdconsole.h | 52 ++-- src/mame/sega/megadriv.cpp | 94 +++---- src/mame/sega/megadriv.h | 17 +- src/mame/sega/megadriv_acbl.cpp | 8 +- src/mame/sega/megadriv_rad.cpp | 12 +- src/mame/sega/megaplay.cpp | 16 +- src/mame/sega/shtzone.cpp | 10 +- src/mame/sega/sms.cpp | 19 +- src/mame/sega/sms.h | 25 +- src/mame/sega/sms_m.cpp | 145 +++++------ src/mame/sharp/x68k.cpp | 424 +++---------------------------- src/mame/sharp/x68k.h | 49 +--- 45 files changed, 1691 insertions(+), 2002 deletions(-) create mode 100644 src/devices/bus/msx/ctrl/sgadapt.cpp create mode 100644 src/devices/bus/msx/ctrl/sgadapt.h create mode 100644 src/devices/bus/sms_ctrl/controllers.cpp create mode 100644 src/devices/bus/sms_ctrl/controllers.h create mode 100644 src/devices/bus/sms_ctrl/md6bt.cpp create mode 100644 src/devices/bus/sms_ctrl/md6bt.h create mode 100644 src/devices/bus/sms_ctrl/mdpad.cpp create mode 100644 src/devices/bus/sms_ctrl/mdpad.h diff --git a/hash/sms.xml b/hash/sms.xml index 1f6a4140fa2..b2219d9464d 100644 --- a/hash/sms.xml +++ b/hash/sms.xml @@ -2842,7 +2842,7 @@ license:CC0 - + Galactic Protector (Japan) 1988 @@ -3371,8 +3371,8 @@ license:CC0 1987 Sega - - + + @@ -6615,8 +6615,8 @@ license:CC0 1987 Sega - - + + @@ -6643,8 +6643,8 @@ license:CC0 - - + + diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua index 9542ab4b8d7..57fee72cdde 100644 --- a/scripts/src/bus.lua +++ b/scripts/src/bus.lua @@ -1809,6 +1809,8 @@ if (BUSES["MSX_CTRL"]~=null) then MAME_DIR .. "src/devices/bus/msx/ctrl/libbler.h", MAME_DIR .. "src/devices/bus/msx/ctrl/mouse.cpp", MAME_DIR .. "src/devices/bus/msx/ctrl/mouse.h", + MAME_DIR .. "src/devices/bus/msx/ctrl/sgadapt.cpp", + MAME_DIR .. "src/devices/bus/msx/ctrl/sgadapt.h", MAME_DIR .. "src/devices/bus/msx/ctrl/towns6b.cpp", MAME_DIR .. "src/devices/bus/msx/ctrl/towns6b.h", MAME_DIR .. "src/devices/bus/msx/ctrl/townspad.cpp", @@ -3519,24 +3521,30 @@ end if (BUSES["SMS_CTRL"]~=null) then files { - MAME_DIR .. "src/devices/bus/sms_ctrl/smsctrl.cpp", - MAME_DIR .. "src/devices/bus/sms_ctrl/smsctrl.h", + MAME_DIR .. "src/devices/bus/sms_ctrl/controllers.cpp", + MAME_DIR .. "src/devices/bus/sms_ctrl/controllers.h", + MAME_DIR .. "src/devices/bus/sms_ctrl/graphic.cpp", + MAME_DIR .. "src/devices/bus/sms_ctrl/graphic.h", MAME_DIR .. "src/devices/bus/sms_ctrl/joypad.cpp", MAME_DIR .. "src/devices/bus/sms_ctrl/joypad.h", MAME_DIR .. "src/devices/bus/sms_ctrl/lphaser.cpp", MAME_DIR .. "src/devices/bus/sms_ctrl/lphaser.h", + MAME_DIR .. "src/devices/bus/sms_ctrl/md6bt.cpp", + MAME_DIR .. "src/devices/bus/sms_ctrl/md6bt.h", + MAME_DIR .. "src/devices/bus/sms_ctrl/mdpad.cpp", + MAME_DIR .. "src/devices/bus/sms_ctrl/mdpad.h", + MAME_DIR .. "src/devices/bus/sms_ctrl/multitap.cpp", + MAME_DIR .. "src/devices/bus/sms_ctrl/multitap.h", MAME_DIR .. "src/devices/bus/sms_ctrl/paddle.cpp", MAME_DIR .. "src/devices/bus/sms_ctrl/paddle.h", MAME_DIR .. "src/devices/bus/sms_ctrl/rfu.cpp", MAME_DIR .. "src/devices/bus/sms_ctrl/rfu.h", + MAME_DIR .. "src/devices/bus/sms_ctrl/smsctrl.cpp", + MAME_DIR .. "src/devices/bus/sms_ctrl/smsctrl.h", MAME_DIR .. "src/devices/bus/sms_ctrl/sports.cpp", MAME_DIR .. "src/devices/bus/sms_ctrl/sports.h", MAME_DIR .. "src/devices/bus/sms_ctrl/sportsjp.cpp", MAME_DIR .. "src/devices/bus/sms_ctrl/sportsjp.h", - MAME_DIR .. "src/devices/bus/sms_ctrl/multitap.cpp", - MAME_DIR .. "src/devices/bus/sms_ctrl/multitap.h", - MAME_DIR .. "src/devices/bus/sms_ctrl/graphic.cpp", - MAME_DIR .. "src/devices/bus/sms_ctrl/graphic.h", } end diff --git a/src/devices/bus/gamegear/ggext.h b/src/devices/bus/gamegear/ggext.h index 04d802eca02..250e7ff6500 100644 --- a/src/devices/bus/gamegear/ggext.h +++ b/src/devices/bus/gamegear/ggext.h @@ -61,7 +61,7 @@ public: // pin 10 - Not connected // uint8_t port_r(); - void port_w( uint8_t data ); + void port_w(uint8_t data); void th_pin_w(int state); diff --git a/src/devices/bus/gamegear/smsctrladp.cpp b/src/devices/bus/gamegear/smsctrladp.cpp index d066f815697..e5c40b333e9 100644 --- a/src/devices/bus/gamegear/smsctrladp.cpp +++ b/src/devices/bus/gamegear/smsctrladp.cpp @@ -10,6 +10,8 @@ #include "emu.h" #include "smsctrladp.h" +#include "bus/sms_ctrl/controllers.h" + //************************************************************************** @@ -30,7 +32,8 @@ DEFINE_DEVICE_TYPE(SMS_CTRL_ADAPTOR, sms_ctrl_adaptor_device, "sms_ctrl_adaptor" sms_ctrl_adaptor_device::sms_ctrl_adaptor_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, SMS_CTRL_ADAPTOR, tag, owner, clock), device_gg_ext_port_interface(mconfig, *this), - m_subctrl_port(*this, "ctrl") + m_subctrl_port(*this, "ctrl"), + m_th_state(0x40) { } @@ -41,6 +44,7 @@ sms_ctrl_adaptor_device::sms_ctrl_adaptor_device(const machine_config &mconfig, void sms_ctrl_adaptor_device::device_start() { + save_item(NAME(m_th_state)); } @@ -50,7 +54,8 @@ void sms_ctrl_adaptor_device::device_start() uint8_t sms_ctrl_adaptor_device::peripheral_r() { - return m_subctrl_port->port_r(); + uint8_t const in = m_subctrl_port->in_r(); + return BIT(in, 0, 4) | 0x10 | (BIT(in, 4) << 5) | m_th_state | (BIT(in, 5) << 7); } @@ -60,12 +65,16 @@ uint8_t sms_ctrl_adaptor_device::peripheral_r() void sms_ctrl_adaptor_device::peripheral_w(uint8_t data) { - m_subctrl_port->port_w(data); + // FIXME: need driver state to be passed through + uint8_t const out = (bitswap<2>(data, 6, 7) << 5) | 0x1f; + uint8_t const mask = bitswap<2>(~data, 6, 7) << 5; // assume only driven low until this is fixed + m_subctrl_port->out_w(out, mask); } WRITE_LINE_MEMBER( sms_ctrl_adaptor_device::th_pin_w ) { + m_th_state = state ? 0x40 : 0x00; m_port->th_pin_w(state); } @@ -76,9 +85,8 @@ WRITE_LINE_MEMBER( sms_ctrl_adaptor_device::th_pin_w ) void sms_ctrl_adaptor_device::device_add_mconfig(machine_config &config) { - SMS_CONTROL_PORT(config, m_subctrl_port, sms_control_port_devices, "joypad"); - if (m_port != nullptr) - m_subctrl_port->set_screen_tag(m_port->m_screen); - m_subctrl_port->th_input_handler().set(FUNC(sms_ctrl_adaptor_device::th_pin_w)); + // Game Gear screen is an LCD - it won't work with lightguns anyway + SMS_CONTROL_PORT(config, m_subctrl_port, sms_control_port_devices, SMS_CTRL_OPTION_JOYPAD); + m_subctrl_port->th_handler().set(FUNC(sms_ctrl_adaptor_device::th_pin_w)); } diff --git a/src/devices/bus/gamegear/smsctrladp.h b/src/devices/bus/gamegear/smsctrladp.h index 46646bde0f0..613fab1e5a8 100644 --- a/src/devices/bus/gamegear/smsctrladp.h +++ b/src/devices/bus/gamegear/smsctrladp.h @@ -44,6 +44,8 @@ private: DECLARE_WRITE_LINE_MEMBER(th_pin_w); required_device m_subctrl_port; + + uint8_t m_th_state; }; diff --git a/src/devices/bus/msx/ctrl/ctrl.cpp b/src/devices/bus/msx/ctrl/ctrl.cpp index 71dc9b6c119..200c36bdd44 100644 --- a/src/devices/bus/msx/ctrl/ctrl.cpp +++ b/src/devices/bus/msx/ctrl/ctrl.cpp @@ -12,6 +12,7 @@ #include "joystick.h" #include "libbler.h" #include "mouse.h" +#include "sgadapt.h" #include "towns6b.h" #include "townspad.h" @@ -46,6 +47,7 @@ void msx_general_purpose_port_devices(device_slot_interface &device) device.option_add("libbler", MSX_LIBBLERPAD); device.option_add("martypad", MSX_MARTYPAD); device.option_add("mouse", MSX_MOUSE); + device.option_add("sega", MSX_SEGACTRL); device.option_add("towns6b", MSX_TOWNS6B); device.option_add("townspad", MSX_TOWNSPAD); } diff --git a/src/devices/bus/msx/ctrl/sgadapt.cpp b/src/devices/bus/msx/ctrl/sgadapt.cpp new file mode 100644 index 00000000000..cc1225d37e8 --- /dev/null +++ b/src/devices/bus/msx/ctrl/sgadapt.cpp @@ -0,0 +1,112 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +/********************************************************************** + + Sega controller adapter emulation + +**********************************************************************/ + +#include "emu.h" +#include "sgadapt.h" + +#include "bus/sms_ctrl/controllers.h" +#include "bus/sms_ctrl/smsctrl.h" + +//#define VERBOSE 1 +//#define LOG_OUTPUT_FUNC osd_printf_info +#include "logmacro.h" + + +namespace { + +class sega_adapter_device : public device_t, public device_msx_general_purpose_port_interface +{ +public: + sega_adapter_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + + virtual u8 read() override; + virtual void pin_6_w(int state) override; + virtual void pin_7_w(int state) override; + virtual void pin_8_w(int state) override; + +protected: + virtual void device_start() override; + virtual void device_add_mconfig(machine_config &config) override; + +private: + required_device m_port; + + u8 m_out; + u8 m_th_in; +}; + + +sega_adapter_device::sega_adapter_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : device_t(mconfig, MSX_SEGACTRL, tag, owner, clock) + , device_msx_general_purpose_port_interface(mconfig, *this) + , m_port(*this, "ctrl") + , m_out(0x7f) + , m_th_in(0x40) +{ +} + +u8 sega_adapter_device::read() +{ + return (m_port->in_r() & 0x3f) | m_th_in; +} + +void sega_adapter_device::pin_6_w(int state) +{ + if (u8(state ? 1 : 0) != BIT(m_out, 4)) + { + if (state) + m_out |= 0x10; + else + m_out &= ~0x10; + LOG("TL %u -> %u (out 0x%02X)\n", BIT(~m_out, 4), BIT(m_out, 4), m_out); + m_port->out_w(m_out, m_out ^ 0x7f); + } +} + +void sega_adapter_device::pin_7_w(int state) +{ + if (u8(state ? 1 : 0) != BIT(m_out, 5)) + { + if (state) + m_out |= 0x20; + else + m_out &= ~0x20; + LOG("TR %u -> %u (out 0x%02X)\n", BIT(~m_out, 5), BIT(m_out, 5), m_out); + m_port->out_w(m_out, m_out ^ 0x7f); + } +} + +void sega_adapter_device::pin_8_w(int state) +{ + if (u8(state ? 1 : 0) != BIT(m_out, 6)) + { + if (state) + m_out |= 0x40; + else + m_out &= ~0x40; + LOG("TH %u -> %u (out 0x%02X)\n", BIT(~m_out, 6), BIT(m_out, 6), m_out); + m_port->out_w(m_out, m_out ^ 0x7f); + } +} + +void sega_adapter_device::device_start() +{ + save_item(NAME(m_out)); + save_item(NAME(m_th_in)); +} + +void sega_adapter_device::device_add_mconfig(machine_config &config) +{ + SMS_CONTROL_PORT(config, m_port, sms_control_port_devices, SMS_CTRL_OPTION_MD_6BUTTON); + m_port->th_handler().set([this] (int state) { m_th_in = state ? 0x40 : 0x00; }); +} + +} // anonymous namespace + + +DEFINE_DEVICE_TYPE_PRIVATE(MSX_SEGACTRL, device_msx_general_purpose_port_interface, sega_adapter_device, "msx_segactrl", "X68000 Sega Controller Adapter") diff --git a/src/devices/bus/msx/ctrl/sgadapt.h b/src/devices/bus/msx/ctrl/sgadapt.h new file mode 100644 index 00000000000..f0b2ad63ac6 --- /dev/null +++ b/src/devices/bus/msx/ctrl/sgadapt.h @@ -0,0 +1,20 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +/********************************************************************** + + Sega controller adapter emulation + +**********************************************************************/ + +#ifndef MAME_BUS_MSX_CTRL_SGADAPT_H +#define MAME_BUS_MSX_CTRL_SGADAPT_H + +#pragma once + +#include "ctrl.h" + + +DECLARE_DEVICE_TYPE(MSX_SEGACTRL, device_msx_general_purpose_port_interface) +DECLARE_DEVICE_TYPE(MSX_SEGACTRL, device_msx_general_purpose_port_interface) + +#endif // MAME_BUS_MSX_CTRL_SGADAPT_H diff --git a/src/devices/bus/sms_ctrl/controllers.cpp b/src/devices/bus/sms_ctrl/controllers.cpp new file mode 100644 index 00000000000..eab82ade634 --- /dev/null +++ b/src/devices/bus/sms_ctrl/controllers.cpp @@ -0,0 +1,55 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +/********************************************************************** + + Sega DE-9 controllers + +**********************************************************************/ + +#include "emu.h" +#include "controllers.h" + +#include "graphic.h" +#include "joypad.h" +#include "lphaser.h" +#include "md6bt.h" +#include "mdpad.h" +#include "multitap.h" +#include "paddle.h" +#include "rfu.h" +#include "sports.h" +#include "sportsjp.h" + + +char const *const SMS_CTRL_OPTION_GRAPHIC = "graphic"; +char const *const SMS_CTRL_OPTION_LPHASER = "lphaser"; +char const *const SMS_CTRL_OPTION_MD_6BUTTON = "md6button"; +char const *const SMS_CTRL_OPTION_MD_PAD = "mdpad"; +char const *const SMS_CTRL_OPTION_MULTITAP = "multitap"; +char const *const SMS_CTRL_OPTION_JOYPAD = "mspad"; +char const *const SMS_CTRL_OPTION_PADDLE = "paddle"; +char const *const SMS_CTRL_OPTION_RAPID_FIRE = "rapidfire"; +char const *const SMS_CTRL_OPTION_SPORTS = "sports"; +char const *const SMS_CTRL_OPTION_SPORTS_JP = "sportsjp"; + + + +void sms_control_port_devices(device_slot_interface &device) +{ + device.option_add(SMS_CTRL_OPTION_GRAPHIC, SMS_GRAPHIC); + device.option_add(SMS_CTRL_OPTION_LPHASER, SMS_LIGHT_PHASER); + device.option_add(SMS_CTRL_OPTION_MD_6BUTTON, SMS_MD6BUTTON); + device.option_add(SMS_CTRL_OPTION_MD_PAD, SMS_MDPAD); + device.option_add(SMS_CTRL_OPTION_MULTITAP, SMS_MULTITAP); + device.option_add(SMS_CTRL_OPTION_JOYPAD, SMS_JOYPAD); + device.option_add(SMS_CTRL_OPTION_PADDLE, SMS_PADDLE); + device.option_add(SMS_CTRL_OPTION_RAPID_FIRE, SMS_RAPID_FIRE); + device.option_add(SMS_CTRL_OPTION_SPORTS, SMS_SPORTS_PAD); + device.option_add(SMS_CTRL_OPTION_SPORTS_JP, SMS_SPORTS_PAD_JP); +} + + +void sms_control_port_passive_devices(device_slot_interface &device) +{ + device.option_add(SMS_CTRL_OPTION_JOYPAD, SMS_JOYPAD); +} diff --git a/src/devices/bus/sms_ctrl/controllers.h b/src/devices/bus/sms_ctrl/controllers.h new file mode 100644 index 00000000000..15d840d85e5 --- /dev/null +++ b/src/devices/bus/sms_ctrl/controllers.h @@ -0,0 +1,28 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +/********************************************************************** + + Sega DE-9 controllers + +**********************************************************************/ +#ifndef MAME_BUS_SMS_CTRL_CONTROLLERS_H +#define MAME_BUS_SMS_CTRL_CONTROLLERS_H + +#pragma once + + +extern char const *const SMS_CTRL_OPTION_GRAPHIC; +extern char const *const SMS_CTRL_OPTION_LPHASER; +extern char const *const SMS_CTRL_OPTION_MD_6BUTTON; +extern char const *const SMS_CTRL_OPTION_MD_PAD; +extern char const *const SMS_CTRL_OPTION_MULTITAP; +extern char const *const SMS_CTRL_OPTION_JOYPAD; +extern char const *const SMS_CTRL_OPTION_PADDLE; +extern char const *const SMS_CTRL_OPTION_RAPID_FIRE; +extern char const *const SMS_CTRL_OPTION_SPORTS; +extern char const *const SMS_CTRL_OPTION_SPORTS_JP; + +void sms_control_port_devices(device_slot_interface &device); +void sms_control_port_passive_devices(device_slot_interface &device); + +#endif // MAME_BUS_SMS_CTRL_CONTROLLERS_H diff --git a/src/devices/bus/sms_ctrl/graphic.cpp b/src/devices/bus/sms_ctrl/graphic.cpp index 1ada76748e7..c2ea024ebf2 100644 --- a/src/devices/bus/sms_ctrl/graphic.cpp +++ b/src/devices/bus/sms_ctrl/graphic.cpp @@ -36,55 +36,69 @@ Then 2 nibbles are read to form a byte containing the absolute Y coordiante. #include "graphic.h" - -//************************************************************************** -// DEVICE DEFINITIONS -//************************************************************************** - -DEFINE_DEVICE_TYPE(SMS_GRAPHIC, sms_graphic_device, "sms_graphic", "Sega SMS Graphic Board") - +namespace { static INPUT_PORTS_START( sms_graphic ) PORT_START("BUTTONS") PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 ) // MENU PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON2 ) // DO PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON3 ) // PEN - PORT_BIT( 0xf8, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_UNKNOWN ) // some kind of ready signal? + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_TOGGLE PORT_NAME("%p Pen") // pretend pen pressure is all-or-nothing PORT_START("X") - PORT_BIT( 0xff, 0x00, IPT_LIGHTGUN_X) PORT_CROSSHAIR(X, 1.0, 0.0, 0) PORT_SENSITIVITY(50) PORT_KEYDELTA(15) + PORT_BIT( 0xff, 0x00, IPT_LIGHTGUN_X) PORT_CROSSHAIR(X, 254 / 268.0, 6 / 268.0, 0) PORT_SENSITIVITY(50) PORT_KEYDELTA(1) PORT_START("Y") - PORT_BIT( 0xff, 0x00, IPT_LIGHTGUN_Y) PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_SENSITIVITY(50) PORT_KEYDELTA(15) + PORT_BIT( 0xff, 0x00, IPT_LIGHTGUN_Y) PORT_CROSSHAIR(Y, 255 / 224.0, -19 / 224.0, 0) PORT_SENSITIVITY(50) PORT_KEYDELTA(1) INPUT_PORTS_END -//------------------------------------------------- -// input_ports - device-specific input ports -//------------------------------------------------- - -ioport_constructor sms_graphic_device::device_input_ports() const -{ - return INPUT_PORTS_NAME( sms_graphic ); -} //************************************************************************** -// LIVE DEVICE +// TYPE DEFINITIONS //************************************************************************** +class sms_graphic_device : public device_t, public device_sms_control_interface +{ +public: + // construction/destruction + sms_graphic_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + // device_sms_control_interface implementation + virtual uint8_t in_r() override; + virtual void out_w(uint8_t data, uint8_t mem_mask) override; + +protected: + // device_t implementation + virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(sms_graphic); } + virtual void device_start() override; + +private: + required_ioport m_buttons; + required_ioport m_x_axis; + required_ioport m_y_axis; + + uint8_t m_phase; + uint8_t m_select; + uint8_t m_data; +}; + + //------------------------------------------------- // sms_graphic_device - constructor //------------------------------------------------- -sms_graphic_device::sms_graphic_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : device_t(mconfig, SMS_GRAPHIC, tag, owner, clock) - , device_sms_control_port_interface(mconfig, *this) - , m_buttons(*this, "BUTTONS") - , m_x(*this, "X") - , m_y(*this, "Y") - , m_index(0) - , m_previous_write(0xff) - , m_pressure(0xfd) +sms_graphic_device::sms_graphic_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + device_t(mconfig, SMS_GRAPHIC, tag, owner, clock), + device_sms_control_interface(mconfig, *this), + m_buttons(*this, "BUTTONS"), + m_x_axis(*this, "X"), + m_y_axis(*this, "Y"), + m_phase(0), + m_select(0x7f), + m_data(0xff) { } @@ -95,8 +109,12 @@ sms_graphic_device::sms_graphic_device(const machine_config &mconfig, const char void sms_graphic_device::device_start() { - save_item(NAME(m_index)); - save_item(NAME(m_previous_write)); + m_phase = 0; + m_data = 0xff; + + save_item(NAME(m_phase)); + save_item(NAME(m_select)); + save_item(NAME(m_data)); } @@ -104,54 +122,55 @@ void sms_graphic_device::device_start() // sms_peripheral_r - joypad read //------------------------------------------------- -uint8_t sms_graphic_device::peripheral_r() +uint8_t sms_graphic_device::in_r() { - switch (m_index) - { - case 0: // Initial state / "I am a board" - // If any regular button is pressed raise/lower TL ? -// if ((m_buttons->read() & 0x07) != 0x07) -// return 0xf0; - return 0xd0; - - case 1: // Read buttons (active low) - return m_buttons->read(); - - case 2: // Some thing only FD, FE, and FF cause the other values to be read - return m_pressure >> 4; - - case 3: - return m_pressure & 0x0f; - - case 4: // High nibble X? - return m_x->read() >> 4; - - case 5: // Low nibble X? - return m_x->read() & 0x0f; - - case 6: // High nibble Y? - return m_y->read() >> 4; - - case 7: // Low Nibble Y? - return m_y->read() & 0x0f; - } - - return 0xff; + if (BIT(m_select, 5)) + return 0x20; // low four bits must be low to recognise Graphic Board, TL is a kind of active-low ready flag + else if (m_phase) + return BIT(m_data, BIT(m_select, 6) ? 0 : 4, 4) | 0x30; + else + return (m_buttons->read() & 0x1f) | 0x20; } -void sms_graphic_device::peripheral_w(uint8_t data) + +void sms_graphic_device::out_w(uint8_t data, uint8_t mem_mask) { - // Check for toggle on TH/TL - if ((data ^ m_previous_write) & 0xc0) + if (BIT(data, 5)) { - m_index++; + // TR high - deselected + m_phase = 0; } - - // If TR is high, restart - if (data & 0x80) + else if (!BIT(m_select, 5) && BIT(m_select, 6) && !BIT(data, 6)) { - m_index = 0; + // negative edge on TH seems to trigger acquisition + switch (m_phase) + { + case 0: + m_data = BIT(m_buttons->read(), 5) ? 0xfe : 0x00; // values made up to satisfy software + m_phase = 1; + break; + case 1: + m_data = m_x_axis->read(); + m_phase = 2; + break; + case 2: + m_data = m_y_axis->read(); + m_phase = 3; + break; + default: + break; // TODO: what actually happens if you keep clocking TH? + } } - m_previous_write = data; + m_select = data; } + +} // anonymous namespace + + + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +DEFINE_DEVICE_TYPE_PRIVATE(SMS_GRAPHIC, device_sms_control_interface, sms_graphic_device, "sms_graphic", "Sega Master System Graphic Board") diff --git a/src/devices/bus/sms_ctrl/graphic.h b/src/devices/bus/sms_ctrl/graphic.h index 036f4660033..b186dc2367f 100644 --- a/src/devices/bus/sms_ctrl/graphic.h +++ b/src/devices/bus/sms_ctrl/graphic.h @@ -5,54 +5,14 @@ Sega Master System "Graphic Board" emulation **********************************************************************/ - #ifndef MAME_BUS_SMS_CTRL_GRAPHIC_H #define MAME_BUS_SMS_CTRL_GRAPHIC_H #pragma once - #include "smsctrl.h" - -//************************************************************************** -// TYPE DEFINITIONS -//************************************************************************** - -// ======================> sms_graphic_device - -class sms_graphic_device : public device_t, - public device_sms_control_port_interface -{ -public: - // construction/destruction - sms_graphic_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - // optional information overrides - virtual ioport_constructor device_input_ports() const override; - -protected: - // device-level overrides - virtual void device_start() override; - - // device_sms_control_port_interface overrides - virtual uint8_t peripheral_r() override; - virtual void peripheral_w(uint8_t data) override; - -private: - required_ioport m_buttons; - required_ioport m_x; - required_ioport m_y; - - int m_index; - uint8_t m_previous_write; - uint8_t m_pressure; -}; - - -// device type definition -DECLARE_DEVICE_TYPE(SMS_GRAPHIC, sms_graphic_device) - +DECLARE_DEVICE_TYPE(SMS_GRAPHIC, device_sms_control_interface) #endif // MAME_BUS_SMS_CTRL_GRAPHIC_H diff --git a/src/devices/bus/sms_ctrl/joypad.cpp b/src/devices/bus/sms_ctrl/joypad.cpp index 4cd664a952e..ac33fdf8b80 100644 --- a/src/devices/bus/sms_ctrl/joypad.cpp +++ b/src/devices/bus/sms_ctrl/joypad.cpp @@ -25,41 +25,42 @@ Release data from the Sega Retro project: #include "joypad.h" +namespace { -//************************************************************************** -// DEVICE DEFINITIONS -//************************************************************************** - -DEFINE_DEVICE_TYPE(SMS_JOYPAD, sms_joypad_device, "sms_joypad", "Sega SMS Control Pad") - - -static INPUT_PORTS_START( sms_joypad ) +INPUT_PORTS_START( sms_joypad ) PORT_START("JOYPAD") PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY - PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) // Vcc - PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 ) // TL - PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED ) // TH - PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON2 ) // TR + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) // TL + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 ) // TR INPUT_PORTS_END -//------------------------------------------------- -// input_ports - device-specific input ports -//------------------------------------------------- -ioport_constructor sms_joypad_device::device_input_ports() const +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +class sms_joypad_device : public device_t, public device_sms_control_interface { - return INPUT_PORTS_NAME( sms_joypad ); -} +public: + // construction/destruction + sms_joypad_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + // device_sms_control_interface implementation + virtual uint8_t in_r() override { return m_joypad->read(); } +protected: + // device_t implementation + virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(sms_joypad); } + virtual void device_start() override { } + +private: + required_ioport m_joypad; +}; -//************************************************************************** -// LIVE DEVICE -//************************************************************************** //------------------------------------------------- // sms_joypad_device - constructor @@ -67,26 +68,17 @@ ioport_constructor sms_joypad_device::device_input_ports() const sms_joypad_device::sms_joypad_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, SMS_JOYPAD, tag, owner, clock), - device_sms_control_port_interface(mconfig, *this), + device_sms_control_interface(mconfig, *this), m_joypad(*this, "JOYPAD") { } +} // anonymous namespace -//------------------------------------------------- -// device_start - device-specific startup -//------------------------------------------------- - -void sms_joypad_device::device_start() -{ -} -//------------------------------------------------- -// sms_peripheral_r - joypad read -//------------------------------------------------- +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** -uint8_t sms_joypad_device::peripheral_r() -{ - return m_joypad->read(); -} +DEFINE_DEVICE_TYPE_PRIVATE(SMS_JOYPAD, device_sms_control_interface, sms_joypad_device, "sms_joypad", "Sega Master System Control Pad") diff --git a/src/devices/bus/sms_ctrl/joypad.h b/src/devices/bus/sms_ctrl/joypad.h index 60b4fe9f4c0..a711b86b11d 100644 --- a/src/devices/bus/sms_ctrl/joypad.h +++ b/src/devices/bus/sms_ctrl/joypad.h @@ -5,47 +5,14 @@ Sega Mark III "Joypad" / Master System "Control Pad" emulation **********************************************************************/ - #ifndef MAME_BUS_SMS_CTRL_JOYPAD_H #define MAME_BUS_SMS_CTRL_JOYPAD_H #pragma once - #include "smsctrl.h" - -//************************************************************************** -// TYPE DEFINITIONS -//************************************************************************** - -// ======================> sms_joypad_device - -class sms_joypad_device : public device_t, - public device_sms_control_port_interface -{ -public: - // construction/destruction - sms_joypad_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - // optional information overrides - virtual ioport_constructor device_input_ports() const override; - -protected: - // device-level overrides - virtual void device_start() override; - - // device_sms_control_port_interface overrides - virtual uint8_t peripheral_r() override; - -private: - required_ioport m_joypad; -}; - - -// device type definition -DECLARE_DEVICE_TYPE(SMS_JOYPAD, sms_joypad_device) - +DECLARE_DEVICE_TYPE(SMS_JOYPAD, device_sms_control_interface) #endif // MAME_BUS_SMS_CTRL_JOYPAD_H diff --git a/src/devices/bus/sms_ctrl/lphaser.cpp b/src/devices/bus/sms_ctrl/lphaser.cpp index 7e64e7c7236..dd518c1c5e1 100644 --- a/src/devices/bus/sms_ctrl/lphaser.cpp +++ b/src/devices/bus/sms_ctrl/lphaser.cpp @@ -19,43 +19,57 @@ Notes: **********************************************************************/ #include "emu.h" -#include "screen.h" #include "lphaser.h" +#include "screen.h" + +//#define VERBOSE 1 +#include "logmacro.h" +namespace { + //************************************************************************** -// DEVICE DEFINITIONS +// TYPE DEFINITIONS //************************************************************************** -DEFINE_DEVICE_TYPE(SMS_LIGHT_PHASER, sms_light_phaser_device, "sms_light_phaser", "Sega SMS Light Phaser") +class sms_light_phaser_device : public device_t, public device_sms_control_interface +{ +public: + // construction/destruction + sms_light_phaser_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + DECLARE_INPUT_CHANGED_MEMBER(position_changed) { sensor_check(0); } -#define LGUN_RADIUS 6 -#define LGUN_X_INTERVAL 4 + // device_sms_control_interface implementation + virtual uint8_t in_r() override { return m_trigger->read(); } +protected: + // device_t implementation + virtual ioport_constructor device_input_ports() const override; + virtual void device_start() override; + virtual void device_reset() override; -READ_LINE_MEMBER( sms_light_phaser_device::th_pin_r ) -{ - // The returned value is inverted due to IP_ACTIVE_LOW mapping. - return ~m_sensor_last_state; -} +private: + required_ioport m_trigger; + required_ioport m_x_axis; + required_ioport m_y_axis; + emu_timer *m_update_timer; -INPUT_CHANGED_MEMBER( sms_light_phaser_device::position_changed ) -{ - if (newval != oldval) - { - sensor_check(0); - } -} + int m_sensor_last_state; + + TIMER_CALLBACK_MEMBER(sensor_check); + int bright_aim_area(int lgun_x, int lgun_y ); + uint16_t screen_hpos_nonscaled(int scaled_hpos); + uint16_t screen_vpos_nonscaled(int scaled_vpos); +}; -static INPUT_PORTS_START( sms_light_phaser ) - PORT_START("CTRL_PORT") - PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 ) // TL (trigger) - PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_READ_LINE_DEVICE_MEMBER(DEVICE_SELF, sms_light_phaser_device, th_pin_r) - PORT_BIT( 0x9f, IP_ACTIVE_LOW, IPT_UNUSED ) +INPUT_PORTS_START(sms_light_phaser) + PORT_START("LPHASER_T") + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) // TL (trigger) + PORT_BIT( 0x2f, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_START("LPHASER_X") PORT_BIT( 0xff, 0x00, IPT_LIGHTGUN_X) PORT_CROSSHAIR(X, 1.0, 0.0, 0) PORT_SENSITIVITY(50) PORT_KEYDELTA(15) PORT_CHANGED_MEMBER(DEVICE_SELF, sms_light_phaser_device, position_changed, 0) @@ -71,27 +85,22 @@ INPUT_PORTS_END ioport_constructor sms_light_phaser_device::device_input_ports() const { - return INPUT_PORTS_NAME( sms_light_phaser ); + return INPUT_PORTS_NAME(sms_light_phaser); } - -//************************************************************************** -// LIVE DEVICE -//************************************************************************** - //------------------------------------------------- // sms_light_phaser_device - constructor //------------------------------------------------- sms_light_phaser_device::sms_light_phaser_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, SMS_LIGHT_PHASER, tag, owner, clock), - device_sms_control_port_interface(mconfig, *this), - m_lphaser_pins(*this, "CTRL_PORT"), - m_lphaser_x(*this, "LPHASER_X"), - m_lphaser_y(*this, "LPHASER_Y"), - m_sensor_last_state(0), - m_lphaser_timer(nullptr) + device_sms_control_interface(mconfig, *this), + m_trigger(*this, "LPHASER_T"), + m_x_axis(*this, "LPHASER_X"), + m_y_axis(*this, "LPHASER_Y"), + m_update_timer(nullptr), + m_sensor_last_state(0) { } @@ -102,24 +111,17 @@ sms_light_phaser_device::sms_light_phaser_device(const machine_config &mconfig, void sms_light_phaser_device::device_start() { - save_item(NAME(m_sensor_last_state)); - m_lphaser_timer = timer_alloc(FUNC(sms_light_phaser_device::sensor_check), this); -} + m_update_timer = timer_alloc(FUNC(sms_light_phaser_device::sensor_check), this); + m_sensor_last_state = 1; -void sms_light_phaser_device::device_reset() -{ - m_sensor_last_state = 1; // off (1) + save_item(NAME(m_sensor_last_state)); } -//------------------------------------------------- -// sms_peripheral_r - light phaser read -//------------------------------------------------- - -uint8_t sms_light_phaser_device::peripheral_r() +void sms_light_phaser_device::device_reset() { - return m_lphaser_pins->read(); + // TODO: sensor check now? The device itself doesn't respond to system reset } @@ -148,13 +150,21 @@ uint8_t sms_light_phaser_device::peripheral_r() */ int sms_light_phaser_device::bright_aim_area(int lgun_x, int lgun_y) { + + constexpr int LGUN_RADIUS = 6; + constexpr int LGUN_X_INTERVAL = 4; + + // brightness of the lightgray color in the frame drawn by Light Phaser games + constexpr uint8_t SENSOR_MIN_BRIGHTNESS = 0x7f; + + screen_device &scr(*screen()); const int r_x_r = LGUN_RADIUS * LGUN_RADIUS; - const rectangle &visarea = m_port->m_screen->visible_area(); + const rectangle &visarea = scr.visible_area(); rectangle aim_area; - int beam_x = m_port->m_screen->hpos(); - int beam_y = m_port->m_screen->vpos(); - int beam_x_orig = beam_x; - int beam_y_orig = beam_y; + int beam_x = scr.hpos(); + int beam_y = scr.vpos(); + const int beam_x_orig = beam_x; + const int beam_y_orig = beam_y; int result = 1; bool new_check_point = false; @@ -163,16 +173,14 @@ int sms_light_phaser_device::bright_aim_area(int lgun_x, int lgun_y) while (!new_check_point) { - /* If beam's y doesn't point to a line where the aim area is, - change it to the first line where the beam enters that area. */ + // If beam's y doesn't point to a line where the aim area is, change it to the first line where the beam enters that area. if (beam_y < aim_area.min_y || beam_y > aim_area.max_y) { beam_y = aim_area.min_y; } int dy = abs(beam_y - lgun_y); - /* Caculate distance in x of the radius, relative to beam's y distance. - First try some shortcuts. */ + // Calculate distance in x of the radius, relative to beam's y distance. First try some shortcuts. double dx_radius = 0; if (dy == 0) { @@ -180,9 +188,9 @@ int sms_light_phaser_device::bright_aim_area(int lgun_x, int lgun_y) } else if (dy != LGUN_RADIUS) { - /* step 1: r^2 = dx^2 + dy^2 */ - /* step 2: dx^2 = r^2 - dy^2 */ - /* step 3: dx = sqrt(r^2 - dy^2) */ + // step 1: r^2 = dx^2 + dy^2 + // step 2: dx^2 = r^2 - dy^2 + // step 3: dx = sqrt(r^2 - dy^2) dx_radius = ceil(sqrt(double(r_x_r - (dy * dy)))); } @@ -191,8 +199,7 @@ int sms_light_phaser_device::bright_aim_area(int lgun_x, int lgun_y) while (!new_check_point) { - /* If beam's x has passed the aim area, change it to the - next line and go back to recheck y/x coordinates. */ + // If beam's x has passed the aim area, change it to the next line and go back to recheck y/x coordinates. if (beam_x > aim_area.max_x) { beam_x = visarea.min_x; @@ -200,8 +207,7 @@ int sms_light_phaser_device::bright_aim_area(int lgun_x, int lgun_y) break; } - /* If beam's x isn't in the aim area, change it to the - next point where the beam enters that area. */ + // If beam's x isn't in the aim area, change it to the next point where the beam enters that area. if (beam_x < aim_area.min_x) { beam_x = aim_area.min_x; @@ -209,58 +215,52 @@ int sms_light_phaser_device::bright_aim_area(int lgun_x, int lgun_y) if (beam_x_orig != beam_x || beam_y_orig != beam_y) { - /* adopt the new coordinates to adjust the timer */ + // adopt the new coordinates to adjust the timer new_check_point = true; break; } if (m_sensor_last_state == 0) { - /* sensor is already on */ - /* keep sensor on until out of the aim area */ + // sensor is already on - keep sensor on until out of the aim area result = 0; } else { - rgb_t color; - uint8_t brightness; - /* brightness of the lightgray color in the frame drawn by Light Phaser games */ - const uint8_t sensor_min_brightness = 0x7f; - - m_port->m_screen->update_now(); - color = m_port->m_screen->pixel(beam_x, beam_y); + scr.update_now(); + const rgb_t color = scr.pixel(beam_x, beam_y); - /* reference: http://www.w3.org/TR/AERT#color-contrast */ - brightness = (color.r() * 0.299) + (color.g() * 0.587) + (color.b() * 0.114); - //printf ("color brightness: %2X for x %d y %d\n", brightness, beam_x, beam_y); + // reference: http://www.w3.org/TR/AERT#color-contrast + const uint8_t brightness = (color.r() * 0.299) + (color.g() * 0.587) + (color.b() * 0.114); + LOG("color brightness: %2X for x %d y %d\n", brightness, beam_x, beam_y); - result = (brightness >= sensor_min_brightness) ? 0 : 1; + result = (brightness >= SENSOR_MIN_BRIGHTNESS) ? 0 : 1; } - if (result == 0) /* sensor on */ + if (result == 0) // sensor on { - /* Set next check for when sensor will be off */ + // Set next check for when sensor will be off beam_x = aim_area.max_x + 1; - /* adopt the new coordinates to adjust the timer */ + // adopt the new coordinates to adjust the timer new_check_point = true; } else { - /* Next check will happen after the minimum interval */ + // Next check will happen after the minimum interval beam_x += LGUN_X_INTERVAL; } } } - m_lphaser_timer->adjust(m_port->m_screen->time_until_pos(beam_y, beam_x)); + m_update_timer->adjust(scr.time_until_pos(beam_y, beam_x)); return result; } uint16_t sms_light_phaser_device::screen_hpos_nonscaled(int scaled_hpos) { - const rectangle &visarea = m_port->m_screen->visible_area(); + const rectangle &visarea = screen()->visible_area(); int offset_x = (scaled_hpos * (visarea.max_x - visarea.min_x)) / 255; return visarea.min_x + offset_x; } @@ -268,7 +268,7 @@ uint16_t sms_light_phaser_device::screen_hpos_nonscaled(int scaled_hpos) uint16_t sms_light_phaser_device::screen_vpos_nonscaled(int scaled_vpos) { - const rectangle &visarea = m_port->m_screen->visible_area(); + const rectangle &visarea = screen()->visible_area(); int offset_y = (scaled_vpos * (visarea.max_y - visarea.min_y)) / 255; return visarea.min_y + offset_y; } @@ -276,13 +276,26 @@ uint16_t sms_light_phaser_device::screen_vpos_nonscaled(int scaled_vpos) TIMER_CALLBACK_MEMBER(sms_light_phaser_device::sensor_check) { - const int x = screen_hpos_nonscaled(m_lphaser_x->read()); - const int y = screen_vpos_nonscaled(m_lphaser_y->read()); - - int sensor_new_state = bright_aim_area(x, y); - if (sensor_new_state != m_sensor_last_state) + if (screen()) { - m_port->th_pin_w(sensor_new_state); - m_sensor_last_state = sensor_new_state; + const int x = screen_hpos_nonscaled(m_x_axis->read()); + const int y = screen_vpos_nonscaled(m_y_axis->read()); + + int sensor_new_state = bright_aim_area(x, y); + if (sensor_new_state != m_sensor_last_state) + { + th_w(sensor_new_state); + m_sensor_last_state = sensor_new_state; + } } } + +} // anonymous namespace + + + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +DEFINE_DEVICE_TYPE_PRIVATE(SMS_LIGHT_PHASER, device_sms_control_interface, sms_light_phaser_device, "sms_light_phaser", "Sega Master System Light Phaser") diff --git a/src/devices/bus/sms_ctrl/lphaser.h b/src/devices/bus/sms_ctrl/lphaser.h index a75f4a0d042..c9d3a2b6eb5 100644 --- a/src/devices/bus/sms_ctrl/lphaser.h +++ b/src/devices/bus/sms_ctrl/lphaser.h @@ -5,61 +5,14 @@ Sega Master System "Light Phaser" (light gun) emulation **********************************************************************/ - #ifndef MAME_BUS_SMS_CTRL_LPHASER_H #define MAME_BUS_SMS_CTRL_LPHASER_H #pragma once - #include "smsctrl.h" - -//************************************************************************** -// TYPE DEFINITIONS -//************************************************************************** - -// ======================> sms_light_phaser_device - -class sms_light_phaser_device : public device_t, - public device_sms_control_port_interface -{ -public: - // construction/destruction - sms_light_phaser_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - // optional information overrides - virtual ioport_constructor device_input_ports() const override; - - DECLARE_READ_LINE_MEMBER( th_pin_r ); - DECLARE_INPUT_CHANGED_MEMBER( position_changed ); - -protected: - // device-level overrides - virtual void device_start() override; - virtual void device_reset() override; - - // device_sms_control_port_interface overrides - virtual uint8_t peripheral_r() override; - -private: - required_ioport m_lphaser_pins; - required_ioport m_lphaser_x; - required_ioport m_lphaser_y; - - int m_sensor_last_state; - emu_timer *m_lphaser_timer; - - TIMER_CALLBACK_MEMBER(sensor_check); - int bright_aim_area(int lgun_x, int lgun_y ); - uint16_t screen_hpos_nonscaled(int scaled_hpos); - uint16_t screen_vpos_nonscaled(int scaled_vpos); -}; - - -// device type definition -DECLARE_DEVICE_TYPE(SMS_LIGHT_PHASER, sms_light_phaser_device) - +DECLARE_DEVICE_TYPE(SMS_LIGHT_PHASER, device_sms_control_interface) #endif // MAME_BUS_SMS_CTRL_LPHASER_H diff --git a/src/devices/bus/sms_ctrl/md6bt.cpp b/src/devices/bus/sms_ctrl/md6bt.cpp new file mode 100644 index 00000000000..18560813e3b --- /dev/null +++ b/src/devices/bus/sms_ctrl/md6bt.cpp @@ -0,0 +1,170 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +/********************************************************************** + + Sega Mega Drive Six Button Control Pad emulation + + Called "Fighting Pad 6B" (ファイティングパッド6B) in Japan + Called "6 Button Arcade Pad" in North America + Called "Bloc d’arcade à 6 boutons" in Canada + Called "Joystick 6 Botões" in Brazil + +**********************************************************************/ + +#include "emu.h" +#include "md6bt.h" + +//#define VERBOSE 1 +//#define LOG_OUTPUT_FUNC osd_printf_info +#include "logmacro.h" + + +namespace { + +INPUT_PORTS_START( sms_md6button ) + PORT_START("PAD") + PORT_BIT( 0x001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY + PORT_BIT( 0x002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY + PORT_BIT( 0x004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY + PORT_BIT( 0x008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY + PORT_BIT( 0x010, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("%p B") + PORT_BIT( 0x020, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("%p C") + PORT_BIT( 0x040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("%p A") + PORT_BIT( 0x080, IP_ACTIVE_LOW, IPT_START ) + PORT_BIT( 0x100, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_NAME("%p Z") + PORT_BIT( 0x200, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_NAME("%p Y") + PORT_BIT( 0x400, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME("%p X") + PORT_BIT( 0x800, IP_ACTIVE_LOW, IPT_SELECT ) PORT_NAME("%p Mode") +INPUT_PORTS_END + + + +class sms_md6button_device : public device_t, public device_sms_control_interface +{ +public: + sms_md6button_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock); + + virtual u8 in_r() override; + virtual void out_w(u8 data, u8 mem_mask) override; + +protected: + virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(sms_md6button); } + virtual void device_start() override; + virtual void device_reset() override; + +private: + TIMER_CALLBACK_MEMBER(timeout); + + required_ioport m_pad; + + emu_timer *m_idle_timer; + + u8 m_th; + u8 m_phase; + u8 m_mode; +}; + + +sms_md6button_device::sms_md6button_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) : + device_t(mconfig, SMS_MD6BUTTON, tag, owner, clock), + device_sms_control_interface(mconfig, *this), + m_pad(*this, "PAD"), + m_idle_timer(nullptr), + m_th(1), + m_phase(0), + m_mode(0) +{ +} + + +u8 sms_md6button_device::in_r() +{ + ioport_value const lines = m_pad->read(); + u8 result; + switch (m_phase) + { + default: + case 0: + case 1: + if (m_th) + result = BIT(lines, 0, 6); // CBRLDU + else + result = (BIT(lines, 6, 2) << 4) | BIT(lines, 0, 2); // SA00DU + break; + case 2: + if (m_th) + result = BIT(lines, 0, 6); // CBRLDU + else + result = (BIT(lines, 6, 2) << 4); // SA0000 + break; + case 3: + if (m_th) + result = (BIT(lines, 4, 2) << 4) | BIT(lines, 8, 4); // CBMXYZ + else + result = (BIT(lines, 6, 2) << 4) | 0x0f; // SA---- + break; + } + LOG("%s: TH = %u read 0x%02X\n", machine().describe_context(), m_th, result); + return result; +} + + +void sms_md6button_device::out_w(u8 data, u8 mem_mask) +{ + u8 const th = BIT(data, 6); + + if (!th) + { + m_idle_timer->reset(); + } + else if (m_th) + { + // not an edge + } + else if (BIT(m_mode, 0)) + { + m_idle_timer->adjust(attotime::from_usec(1500)); + m_phase = (m_phase + 1) & 0x03; + LOG("%s: 6-button mode, TH rising, phase = %u\n", machine().describe_context(), m_phase); + } + else + { + LOG("%s: 3-button mode, TH rising, phase = %u\n", machine().describe_context(), m_phase); + } + + m_th = th; +} + + +void sms_md6button_device::device_start() +{ + m_idle_timer = timer_alloc(FUNC(sms_md6button_device::timeout), this); + + m_phase = 0; + m_mode = 0; + + save_item(NAME(m_th)); + save_item(NAME(m_phase)); + save_item(NAME(m_mode)); +} + + +void sms_md6button_device::device_reset() +{ + // TODO: doesn't work reset happens before inputs are read + if (!m_mode) + m_mode = BIT(m_pad->read(), 11) | 0x02; +} + + +TIMER_CALLBACK_MEMBER(sms_md6button_device::timeout) +{ + m_phase = 0; + LOG("timeout, phase = %u\n", m_phase); +} + +} // anonymous namespace + + + +DEFINE_DEVICE_TYPE_PRIVATE(SMS_MD6BUTTON, device_sms_control_interface, sms_md6button_device, "sms_md6button", "Sega Mega Drive Six Button Control Pad") diff --git a/src/devices/bus/sms_ctrl/md6bt.h b/src/devices/bus/sms_ctrl/md6bt.h new file mode 100644 index 00000000000..4a843f5ddec --- /dev/null +++ b/src/devices/bus/sms_ctrl/md6bt.h @@ -0,0 +1,18 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +/********************************************************************** + + Sega Mega Drive Six Button Control Pad emulation + +**********************************************************************/ +#ifndef MAME_BUS_SMS_CTRL_MD6BT_H +#define MAME_BUS_SMS_CTRL_MD6BT_H + +#pragma once + +#include "smsctrl.h" + + +DECLARE_DEVICE_TYPE(SMS_MD6BUTTON, device_sms_control_interface) + +#endif // MAME_BUS_SMS_CTRL_MD6BT_H diff --git a/src/devices/bus/sms_ctrl/mdpad.cpp b/src/devices/bus/sms_ctrl/mdpad.cpp new file mode 100644 index 00000000000..d0c22c42085 --- /dev/null +++ b/src/devices/bus/sms_ctrl/mdpad.cpp @@ -0,0 +1,82 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +/********************************************************************** + + Sega Mega Drive Control Pad emulation + +**********************************************************************/ + +#include "emu.h" +#include "mdpad.h" + + +namespace { + +INPUT_PORTS_START( sms_mdpad ) + PORT_START("PAD") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("%p B") + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("%p C") + PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("%p A") + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_START ) +INPUT_PORTS_END + + + +class sms_mdpad_device : public device_t, public device_sms_control_interface +{ +public: + sms_mdpad_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock); + + virtual u8 in_r() override; + virtual void out_w(u8 data, u8 mem_mask) override; + +protected: + virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(sms_mdpad); } + virtual void device_start() override; + +private: + required_ioport m_pad; + + u8 m_th; +}; + + +sms_mdpad_device::sms_mdpad_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) : + device_t(mconfig, SMS_MDPAD, tag, owner, clock), + device_sms_control_interface(mconfig, *this), + m_pad(*this, "PAD"), + m_th(1) +{ +} + + +u8 sms_mdpad_device::in_r() +{ + ioport_value const lines = m_pad->read(); + if (m_th) + return BIT(lines, 0, 6); + else + return (BIT(lines, 6, 2) << 4) | BIT(lines, 0, 2); +} + + +void sms_mdpad_device::out_w(u8 data, u8 mem_mask) +{ + m_th = BIT(data, 6); +} + + +void sms_mdpad_device::device_start() +{ + save_item(NAME(m_th)); +} + +} // anonymous namespace + + + +DEFINE_DEVICE_TYPE_PRIVATE(SMS_MDPAD, device_sms_control_interface, sms_mdpad_device, "sms_mdpad", "Sega Mega Drive Control Pad") diff --git a/src/devices/bus/sms_ctrl/mdpad.h b/src/devices/bus/sms_ctrl/mdpad.h new file mode 100644 index 00000000000..8cb045e682e --- /dev/null +++ b/src/devices/bus/sms_ctrl/mdpad.h @@ -0,0 +1,18 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +/********************************************************************** + + Sega Mega Drive Control Pad emulation + +**********************************************************************/ +#ifndef MAME_BUS_SMS_CTRL_MDPAD_H +#define MAME_BUS_SMS_CTRL_MDPAD_H + +#pragma once + +#include "smsctrl.h" + + +DECLARE_DEVICE_TYPE(SMS_MDPAD, device_sms_control_interface) + +#endif // MAME_BUS_SMS_CTRL_MDPAD_H diff --git a/src/devices/bus/sms_ctrl/multitap.cpp b/src/devices/bus/sms_ctrl/multitap.cpp index 74d6c749cb5..6d5017095a5 100644 --- a/src/devices/bus/sms_ctrl/multitap.cpp +++ b/src/devices/bus/sms_ctrl/multitap.cpp @@ -4,25 +4,56 @@ Furrtek's homemade multitap emulation + Schematic: http://www.smspower.org/uploads/Homebrew/BOoM-SMS-sms4p_2.png + + Works by pulling ground low on one of the four ports at a time. + Doesn't pass through power, only works with passive devices. + **********************************************************************/ #include "emu.h" #include "multitap.h" +#include "controllers.h" + +//#define VERBOSE 1 +//#define LOG_OUTPUT_FUNC osd_printf_info +#include "logmacro.h" -// Scheme: http://www.smspower.org/uploads/Homebrew/BOoM-SMS-sms4p_2.png +namespace { //************************************************************************** -// DEVICE DEFINITIONS +// TYPE DEFINITIONS //************************************************************************** -DEFINE_DEVICE_TYPE(SMS_MULTITAP, sms_multitap_device, "sms_multitap", "Furrtek SMS Multitap") +class sms_multitap_device : public device_t, public device_sms_control_interface +{ +public: + // construction/destruction + sms_multitap_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + // device_sms_control_interface implementation + virtual uint8_t in_r() override; + virtual void out_w(uint8_t data, uint8_t mem_mask) override; +protected: + // device_t implementation + virtual void device_add_mconfig(machine_config &config) override; + virtual void device_resolve_objects() override; + virtual void device_start() override; + +private: + TIMER_CALLBACK_MEMBER(reset_timeout); + + required_device_array m_subctrl_ports; + + emu_timer *m_reset_timer; + + uint8_t m_read_state; + uint8_t m_th_state; +}; -//************************************************************************** -// LIVE DEVICE -//************************************************************************** //------------------------------------------------- // sms_multitap_device - constructor @@ -30,14 +61,19 @@ DEFINE_DEVICE_TYPE(SMS_MULTITAP, sms_multitap_device, "sms_multitap", "Furrtek S sms_multitap_device::sms_multitap_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, SMS_MULTITAP, tag, owner, clock), - device_sms_control_port_interface(mconfig, *this), - m_subctrl1_port(*this, "ctrl1"), - m_subctrl2_port(*this, "ctrl2"), - m_subctrl3_port(*this, "ctrl3"), - m_subctrl4_port(*this, "ctrl4"), + device_sms_control_interface(mconfig, *this), + m_subctrl_ports(*this, "ctrl%u", 1U), + m_reset_timer(nullptr), m_read_state(0), - m_last_data(0) + m_th_state(1) +{ +} + + +void sms_multitap_device::device_resolve_objects() { + m_read_state = 0; + m_th_state = 1; } @@ -47,8 +83,10 @@ sms_multitap_device::sms_multitap_device(const machine_config &mconfig, const ch void sms_multitap_device::device_start() { + m_reset_timer = timer_alloc(FUNC(sms_multitap_device::reset_timeout), this); + save_item(NAME(m_read_state)); - save_item(NAME(m_last_data)); + save_item(NAME(m_th_state)); } @@ -56,30 +94,13 @@ void sms_multitap_device::device_start() // sms_peripheral_r - multitap read //------------------------------------------------- -uint8_t sms_multitap_device::peripheral_r() +uint8_t sms_multitap_device::in_r() { - uint8_t data = 0xff; - - switch(m_read_state) - { - case 0: - data = m_subctrl1_port->port_r(); - break; - case 1: - data = m_subctrl2_port->port_r(); - break; - case 2: - data = m_subctrl3_port->port_r(); - break; - case 3: - data = m_subctrl4_port->port_r(); - break; - } - - // force TH level high (1), as the line is not connected to subports. - data |= 0x40; - - return data; + // only low two bits of count value are decoded + uint8_t const port = m_read_state & 0x03; + uint8_t const result = m_subctrl_ports[port]->in_r(); + LOG("%s: read player %u = 0x%02X\n", machine().describe_context(), port + 1, result); + return result; } @@ -87,35 +108,27 @@ uint8_t sms_multitap_device::peripheral_r() // sms_peripheral_w - multitap write //------------------------------------------------- -void sms_multitap_device::peripheral_w(uint8_t data) +void sms_multitap_device::out_w(uint8_t data, uint8_t mem_mask) { - uint8_t output_data; - - // check if TH level is low (0) and was high (1) - if (!(data & 0x40) && (m_last_data & 0x40)) + uint8_t const th_state = BIT(data, 6); + if (!th_state) { - m_read_state = (m_read_state + 1) & 3; + m_reset_timer->reset(); // capacitor discharged through diode + if (m_th_state) + { + m_read_state = (m_read_state + 1) & 0x0f; // 74LS393 4-bit counter + LOG("%s: TH falling, count = 0x%X (player %u)\n", machine().describe_context(), m_read_state, (m_read_state & 0x03) + 1); + } } - m_last_data = data; - - // output default TH level (1), as the line is not connected to subports. - output_data = data | 0x40; - - switch(m_read_state) + else if (!m_th_state) { - case 0: - m_subctrl1_port->port_w(output_data); - break; - case 1: - m_subctrl2_port->port_w(output_data); - break; - case 2: - m_subctrl3_port->port_w(output_data); - break; - case 3: - m_subctrl4_port->port_w(output_data); - break; + // start charging 0.1u capacitor via 100k resistor - timeout approximated + m_reset_timer->adjust(attotime::from_msec(10)); } + m_th_state = th_state; + + for (auto &port : m_subctrl_ports) + port->out_w(data | 0x40, mem_mask & ~0x40); // TH not connected to controllers } @@ -125,17 +138,24 @@ void sms_multitap_device::peripheral_w(uint8_t data) void sms_multitap_device::device_add_mconfig(machine_config &config) { - // Controller subports setup, without the TH callback declaration, - // because the circuit scheme shows TH of subports without connection. - SMS_CONTROL_PORT(config, m_subctrl1_port, sms_control_port_devices, "joypad"); - SMS_CONTROL_PORT(config, m_subctrl2_port, sms_control_port_devices, "joypad"); - SMS_CONTROL_PORT(config, m_subctrl3_port, sms_control_port_devices, "joypad"); - SMS_CONTROL_PORT(config, m_subctrl4_port, sms_control_port_devices, "joypad"); - if (m_port != nullptr) - { - m_subctrl1_port->set_screen_tag(m_port->m_screen); - m_subctrl2_port->set_screen_tag(m_port->m_screen); - m_subctrl3_port->set_screen_tag(m_port->m_screen); - m_subctrl4_port->set_screen_tag(m_port->m_screen); - } + // TH not connected, no point configuring screen when power isn't passed through + for (auto port : m_subctrl_ports) + SMS_CONTROL_PORT(config, port, sms_control_port_passive_devices, SMS_CTRL_OPTION_JOYPAD); +} + + +TIMER_CALLBACK_MEMBER(sms_multitap_device::reset_timeout) +{ + m_read_state = 0; + LOG("Timeout, count = 0x%X (player %u)\n", m_read_state, (m_read_state & 0x03) + 1); } + +} // anonymous namespace + + + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +DEFINE_DEVICE_TYPE_PRIVATE(SMS_MULTITAP, device_sms_control_interface, sms_multitap_device, "sms_multitap", "Furrtek Sega Master System Multitap") diff --git a/src/devices/bus/sms_ctrl/multitap.h b/src/devices/bus/sms_ctrl/multitap.h index 6a2351c48f5..7484c0d1c68 100644 --- a/src/devices/bus/sms_ctrl/multitap.h +++ b/src/devices/bus/sms_ctrl/multitap.h @@ -5,52 +5,14 @@ Furrtek's homemade multitap emulation **********************************************************************/ - #ifndef MAME_BUS_SMS_CTRL_MULTITAP_H #define MAME_BUS_SMS_CTRL_MULTITAP_H #pragma once - #include "smsctrl.h" - -//************************************************************************** -// TYPE DEFINITIONS -//************************************************************************** - -// ======================> sms_multitap_device - -class sms_multitap_device : public device_t, - public device_sms_control_port_interface -{ -public: - // construction/destruction - sms_multitap_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - -protected: - // device-level overrides - virtual void device_start() override; - virtual void device_add_mconfig(machine_config &config) override; - - // device_sms_control_port_interface overrides - virtual uint8_t peripheral_r() override; - virtual void peripheral_w(uint8_t data) override; - -private: - required_device m_subctrl1_port; - required_device m_subctrl2_port; - required_device m_subctrl3_port; - required_device m_subctrl4_port; - - uint8_t m_read_state; - uint8_t m_last_data; -}; - - -// device type definition -DECLARE_DEVICE_TYPE(SMS_MULTITAP, sms_multitap_device) - +DECLARE_DEVICE_TYPE(SMS_MULTITAP, device_sms_control_interface) #endif // MAME_BUS_SMS_CTRL_MULTITAP_H diff --git a/src/devices/bus/sms_ctrl/paddle.cpp b/src/devices/bus/sms_ctrl/paddle.cpp index 06f1c9bfa16..c51601ab252 100644 --- a/src/devices/bus/sms_ctrl/paddle.cpp +++ b/src/devices/bus/sms_ctrl/paddle.cpp @@ -1,127 +1,184 @@ // license:BSD-3-Clause -// copyright-holders:Fabio Priuli +// copyright-holders:Vas Crabb /********************************************************************** Sega Mark III "Paddle Control" emulation -Release data from the Sega Retro project: + Release data from the Sega Retro project: - Year: 1987 Country/region: JP Model code: HPD-200 + Year: 1987 Country/region: JP Model code: HPD-200 -Notes: + Notes: - The main chip contained in the device is labeled 315-5243. + The main chip contained in the device is labeled 315-5243. - The Paddle Control was only released in Japan. To work with the device, - paddle games need to detect the system region as Japanese, else they switch - to a different mode that uses the TH line as output to select which nibble - of the X axis will be read. This other mode is similar to how the US Sports - Pad works, so on an Export system, paddle games are somewhat playable with - that device, though it needs to be used inverted and the trackball needs to - be moved slowly, else the software for the paddle think it's moving backward. + On Japanese systems (Mark III and Master System), the games + read the port and expect the value on the low four bits + (usually used joystick switches) to alternate between the low + and high nybbles of the paddle position, with TR indicating + the current state. + + On export consoles, the games toggle the TH output before + reading a nybble, expecting to be able to select the high or + low nybble of the paddle position. It spins for longer between + pulling TH low and reading the low nybble than it does between + pulling TH high and reading the high nybble, suggesting that + pulling TH low triggers acquisition. + + Only a single paddle controller was released that works with + both Japanese and export consoles, and the Mark III has the pin + that became TH tied low while it's left high when reading the + paddle on Japanese Master Systems. This suggests that if the + TH line doesn't change state for some amount of time, the + paddle will periodically switch between high and low nybbles. **********************************************************************/ #include "emu.h" #include "paddle.h" +//#define VERBOSE 1 +//#define LOG_OUTPUT_FUNC osd_printf_info +#include "logmacro.h" -//************************************************************************** -// DEVICE DEFINITIONS -//************************************************************************** +namespace { -DEFINE_DEVICE_TYPE(SMS_PADDLE, sms_paddle_device, "sms_paddle", "Sega SMS Paddle") +INPUT_PORTS_START( sms_paddle ) + PORT_START("BUTTON") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 ) + + PORT_START("PADDLE") + PORT_BIT( 0xff, 0x80, IPT_PADDLE) PORT_MINMAX(0, 255) PORT_SENSITIVITY(40) PORT_KEYDELTA(20) PORT_CENTERDELTA(0) +INPUT_PORTS_END -// time interval not verified -// Player 2 of Galactic Protector is the most sensible to this timming. -#define PADDLE_INTERVAL attotime::from_hz(XTAL(10'738'635)/3/100) -CUSTOM_INPUT_MEMBER( sms_paddle_device::rldu_pins_r ) +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +class sms_paddle_device : public device_t, public device_sms_control_interface { - uint8_t data = m_paddle_x->read(); +public: + // construction/destruction + sms_paddle_device(const machine_config &mconfig, char const *tag, device_t *owner, u32 clock); - if (m_read_state) - data >>= 4; + // device_sms_control_interface implementation + virtual u8 in_r() override; + virtual void out_w(u8 data, u8 mem_mask) override; - // The returned value is inverted due to IP_ACTIVE_LOW mapping. - return ~data; -} +protected: + // device_t implementation + virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(sms_paddle); } + virtual void device_start() override; +private: + TIMER_CALLBACK_MEMBER(timeout); -READ_LINE_MEMBER( sms_paddle_device::tr_pin_r ) -{ - // The returned value is inverted due to IP_ACTIVE_LOW mapping. - return ~m_read_state; -} + // time interval guessed + // Player 2 of Galactic Protector is the most sensitive to this timing + static attotime interval() { return attotime::from_hz(XTAL(10'738'635) / 3 / 100); } + // delay guessed + static attotime delay() { return attotime::from_msec(5); } -static INPUT_PORTS_START( sms_paddle ) - PORT_START("CTRL_PORT") - PORT_BIT( 0x0f, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_CUSTOM_MEMBER(sms_paddle_device, rldu_pins_r) // R,L,D,U - PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) // Vcc - PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 ) // TL - PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED ) // TH - PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_READ_LINE_MEMBER(sms_paddle_device, tr_pin_r) // TR + required_ioport m_button; + required_ioport m_axis; - PORT_START("PADDLE_X") // Paddle knob - PORT_BIT( 0xff, 0x80, IPT_PADDLE) PORT_SENSITIVITY(40) PORT_KEYDELTA(20) PORT_CENTERDELTA(0) PORT_MINMAX(0,255) -INPUT_PORTS_END + emu_timer *m_idle_timer; + u8 m_th; + u8 m_nybble; + u8 m_data; +}; -//------------------------------------------------- -// input_ports - device-specific input ports -//------------------------------------------------- -ioport_constructor sms_paddle_device::device_input_ports() const +sms_paddle_device::sms_paddle_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) : + device_t(mconfig, SMS_PADDLE, tag, owner, clock), + device_sms_control_interface(mconfig, *this), + m_button(*this, "BUTTON"), + m_axis(*this, "PADDLE"), + m_idle_timer(nullptr), + m_th(1), + m_nybble(1), + m_data(0) { - return INPUT_PORTS_NAME( sms_paddle ); } +u8 sms_paddle_device::in_r() +{ + LOG("%s: read %s nybble = 0x%x\n", machine().describe_context(), m_nybble ? "high" : "low", m_data & 0x0f); + return (m_nybble << 5) | (m_button->read() << 4) | (m_data & 0x0f); +} -//************************************************************************** -// LIVE DEVICE -//************************************************************************** - -//------------------------------------------------- -// sms_paddle_device - constructor -//------------------------------------------------- -sms_paddle_device::sms_paddle_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - device_t(mconfig, SMS_PADDLE, tag, owner, clock), - device_sms_control_port_interface(mconfig, *this), - m_paddle_pins(*this, "CTRL_PORT"), - m_paddle_x(*this, "PADDLE_X"), - m_read_state(0), - m_interval(PADDLE_INTERVAL) +void sms_paddle_device::out_w(u8 data, u8 mem_mask) { + u8 const th = BIT(data, 6); + if (th != m_th) + { + m_idle_timer->reset(delay()); + if (!th) + { + m_nybble = 0; + m_data = m_axis->read(); + LOG("%s: TH %u -> %u\n, acquire data 0x%02X", machine().describe_context(), m_th, th, m_data); + } + else if (!m_nybble) + { + m_nybble = 1; + m_data >>= 4; + LOG("%s: TH %u -> %u\n, shift data", machine().describe_context(), m_th, th); + } + else + { + LOG("%s: TH %u -> %u\n", machine().describe_context(), m_th, th); + } + m_th = th; + } } -//------------------------------------------------- -// device_start - device-specific startup -//------------------------------------------------- - void sms_paddle_device::device_start() { - m_start_time = machine().time(); + m_idle_timer = timer_alloc(FUNC(sms_paddle_device::timeout), this); - save_item(NAME(m_start_time)); - save_item(NAME(m_read_state)); -} + m_nybble = 1; + m_data = 0; + + save_item(NAME(m_th)); + save_item(NAME(m_nybble)); + save_item(NAME(m_data)); + m_idle_timer->adjust(delay(), 0, interval()); +} -//------------------------------------------------- -// sms_peripheral_r - paddle read -//------------------------------------------------- -uint8_t sms_paddle_device::peripheral_r() +TIMER_CALLBACK_MEMBER(sms_paddle_device::timeout) { - int num_intervals = (machine().time() - m_start_time).as_double() / m_interval.as_double(); - m_read_state = num_intervals & 1; - - return m_paddle_pins->read(); + if (m_nybble) + { + m_nybble = 0; + m_data = m_axis->read(); + LOG("timeout: acquire data 0x%02X\n", m_data); + } + else + { + m_nybble = 1; + m_data >>= 4; + LOG("timeout: shift data\n"); + } } + +} // anonymous namespace + + + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +DEFINE_DEVICE_TYPE_PRIVATE(SMS_PADDLE, device_sms_control_interface, sms_paddle_device, "sms_paddle", "Sega Mark III Paddle (Japan)") diff --git a/src/devices/bus/sms_ctrl/paddle.h b/src/devices/bus/sms_ctrl/paddle.h index 21604a882ed..d61e21042ad 100644 --- a/src/devices/bus/sms_ctrl/paddle.h +++ b/src/devices/bus/sms_ctrl/paddle.h @@ -1,58 +1,18 @@ // license:BSD-3-Clause -// copyright-holders:Fabio Priuli +// copyright-holders:Vas Crabb /********************************************************************** Sega Mark III "Paddle Control" emulation **********************************************************************/ - #ifndef MAME_BUS_SMS_CTRL_PADDLE_H #define MAME_BUS_SMS_CTRL_PADDLE_H #pragma once - #include "smsctrl.h" - -//************************************************************************** -// TYPE DEFINITIONS -//************************************************************************** - -// ======================> sms_paddle_device - -class sms_paddle_device : public device_t, - public device_sms_control_port_interface -{ -public: - // construction/destruction - sms_paddle_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - // optional information overrides - virtual ioport_constructor device_input_ports() const override; - - DECLARE_CUSTOM_INPUT_MEMBER( rldu_pins_r ); // Right, Left, Down and Up lines. - DECLARE_READ_LINE_MEMBER( tr_pin_r ); - -protected: - // device-level overrides - virtual void device_start() override; - - // device_sms_control_port_interface overrides - virtual uint8_t peripheral_r() override; - -private: - required_ioport m_paddle_pins; - required_ioport m_paddle_x; - - uint8_t m_read_state; - attotime m_start_time; - const attotime m_interval; -}; - - -// device type definition -DECLARE_DEVICE_TYPE(SMS_PADDLE, sms_paddle_device) +DECLARE_DEVICE_TYPE(SMS_PADDLE, device_sms_control_interface) #endif // MAME_BUS_SMS_CTRL_PADDLE_H diff --git a/src/devices/bus/sms_ctrl/rfu.cpp b/src/devices/bus/sms_ctrl/rfu.cpp index d28a2ded703..d116b803db2 100644 --- a/src/devices/bus/sms_ctrl/rfu.cpp +++ b/src/devices/bus/sms_ctrl/rfu.cpp @@ -14,76 +14,98 @@ Release data from the Sega Retro project: Notes: - This emulated device is the version released by Sega. In Brazil, Tec Toy - released a version that does not have any switch to turn on/off auto-repeat. + This emulated device is the version released by Sega. In Brazil, + Tec Toy released a version that does not have any switch to turn + on/off auto-repeat. + + Uses a separate oscillator consisting of a 27k resistor, a 1u + capacitor, and two NOR gates from a 74HCTLS02 for each button. In + reality, the two oscillators will run at slightly different speeds + and drift away from each other, so the buttons won't be + synchronised. + + The rapid fire oscillators should start when the button is pressed, + but this would require pushing TL and TR state from the controller + to the port. **********************************************************************/ #include "emu.h" #include "rfu.h" +#include "controllers.h" + +namespace { //************************************************************************** -// DEVICE DEFINITIONS +// TYPE DEFINITIONS //************************************************************************** -DEFINE_DEVICE_TYPE(SMS_RAPID_FIRE, sms_rapid_fire_device, "sms_rapid_fire", "Sega SMS Rapid Fire Unit") - -// time interval not verified -#define RAPID_FIRE_INTERVAL attotime::from_hz(10) - - -static INPUT_PORTS_START( sms_rapid_fire ) - PORT_START("rfu_sw") // Rapid Fire Unit switches - PORT_CONFNAME( 0x03, 0x00, "Rapid Fire Unit" ) - PORT_CONFSETTING( 0x00, DEF_STR( Off ) ) - PORT_CONFSETTING( 0x01, "Button 1" ) - PORT_CONFSETTING( 0x02, "Button 2" ) - PORT_CONFSETTING( 0x03, "Button 1 + 2" ) +class sms_rapid_fire_device : public device_t, public device_sms_control_interface +{ +public: + // construction/destruction + sms_rapid_fire_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + // device_sms_control_interface implementation + virtual uint8_t in_r() override; + virtual void out_w(uint8_t data, uint8_t mem_mask) override; + + DECLARE_WRITE_LINE_MEMBER(rapid_changed); + +protected: + // device_t implementation + virtual void device_add_mconfig(machine_config &config) override; + virtual ioport_constructor device_input_ports() const override; + virtual void device_config_complete() override; + virtual void device_start() override; + virtual void device_reset() override; + +private: + required_device m_subctrl_port; + required_ioport m_rfire_sw; + + uint8_t m_in; + uint8_t m_drive; + uint8_t m_rapid; +}; + + +INPUT_PORTS_START( sms_rapid_fire ) + PORT_START("rfu_sw") + PORT_BIT( 0x00, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_TOGGLE PORT_NAME("Rapid Fire 1") PORT_WRITE_LINE_MEMBER(sms_rapid_fire_device, rapid_changed) + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_TOGGLE PORT_NAME("Rapid Fire 2") PORT_WRITE_LINE_MEMBER(sms_rapid_fire_device, rapid_changed) INPUT_PORTS_END -//------------------------------------------------- -// input_ports - device-specific input ports -//------------------------------------------------- - ioport_constructor sms_rapid_fire_device::device_input_ports() const { - return INPUT_PORTS_NAME( sms_rapid_fire ); + return INPUT_PORTS_NAME(sms_rapid_fire); } - -//************************************************************************** -// LIVE DEVICE -//************************************************************************** - //------------------------------------------------- // sms_rapid_fire_device - constructor //------------------------------------------------- sms_rapid_fire_device::sms_rapid_fire_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, SMS_RAPID_FIRE, tag, owner, clock), - device_sms_control_port_interface(mconfig, *this), - m_rfire_sw(*this, "rfu_sw"), + device_sms_control_interface(mconfig, *this), m_subctrl_port(*this, "ctrl"), - m_read_state(0), - m_interval(RAPID_FIRE_INTERVAL) + m_rfire_sw(*this, "rfu_sw"), + m_in(0x03), + m_drive(0x00), + m_rapid(0x00) { } -//------------------------------------------------- -// device_start - device-specific startup -//------------------------------------------------- - -void sms_rapid_fire_device::device_start() +WRITE_LINE_MEMBER(sms_rapid_fire_device::rapid_changed) { - m_start_time = machine().time(); - - save_item(NAME(m_start_time)); - save_item(NAME(m_read_state)); + m_rapid = m_rfire_sw->read(); + m_subctrl_port->out_w(m_in | m_rapid, m_drive & ~m_rapid); } @@ -91,51 +113,57 @@ void sms_rapid_fire_device::device_start() // sms_peripheral_r - rapid fire read //------------------------------------------------- -uint8_t sms_rapid_fire_device::peripheral_r() +uint8_t sms_rapid_fire_device::in_r() { - uint8_t data; + uint8_t const read_state = machine().time().as_ticks(10) & 1; // time interval not verified - int num_intervals = (machine().time() - m_start_time).as_double() / m_interval.as_double(); - m_read_state = num_intervals & 1; + return m_subctrl_port->in_r() | (read_state ? m_rfire_sw->read() : 0U); +} - data = m_subctrl_port->port_r(); - /* Check Rapid Fire switch for Button 1 (TL) */ - if (!(data & 0x20) && (m_rfire_sw->read() & 0x01)) - data |= m_read_state << 5; +void sms_rapid_fire_device::out_w(uint8_t data, uint8_t mem_mask) +{ + // TR pulled up via a 4k7 resistor, connected directly to console pin when rapid fire disabled + m_subctrl_port->out_w(data | m_rapid, mem_mask & ~m_rapid); + m_in = data; + m_drive = mem_mask; +} - /* Check Rapid Fire switch for Button 2 (TR) */ - if (!(data & 0x80) && (m_rfire_sw->read() & 0x02)) - data |= m_read_state << 7; - return data; +void sms_rapid_fire_device::device_add_mconfig(machine_config &config) +{ + SMS_CONTROL_PORT(config, m_subctrl_port, sms_control_port_devices, SMS_CTRL_OPTION_JOYPAD); + m_subctrl_port->th_handler().set(FUNC(sms_rapid_fire_device::th_w)); } -//------------------------------------------------- -// sms_peripheral_w - rapid fire write -//------------------------------------------------- - -void sms_rapid_fire_device::peripheral_w(uint8_t data) +void sms_rapid_fire_device::device_config_complete() { - m_subctrl_port->port_w(data); + configure_screen( + [this] (auto const &s) + { subdevice("ctrl")->set_screen(s); }); } -//------------------------------------------------- -// device_add_mconfig - add device configuration -//------------------------------------------------- - -WRITE_LINE_MEMBER( sms_rapid_fire_device::th_pin_w ) +void sms_rapid_fire_device::device_start() { - m_port->th_pin_w(state); + save_item(NAME(m_in)); + save_item(NAME(m_drive)); + save_item(NAME(m_rapid)); } -void sms_rapid_fire_device::device_add_mconfig(machine_config &config) +void sms_rapid_fire_device::device_reset() { - SMS_CONTROL_PORT(config, m_subctrl_port, sms_control_port_devices, "joypad"); - if (m_port != nullptr) - m_subctrl_port->set_screen_tag(m_port->m_screen); - m_subctrl_port->th_input_handler().set(FUNC(sms_rapid_fire_device::th_pin_w)); + m_rapid = m_rfire_sw->read(); } + +} // anonymous namespace + + + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +DEFINE_DEVICE_TYPE_PRIVATE(SMS_RAPID_FIRE, device_sms_control_interface, sms_rapid_fire_device, "sms_rapid_fire", "Sega Master System Rapid Fire Unit") diff --git a/src/devices/bus/sms_ctrl/rfu.h b/src/devices/bus/sms_ctrl/rfu.h index f37b70b1c92..8cb4a32f253 100644 --- a/src/devices/bus/sms_ctrl/rfu.h +++ b/src/devices/bus/sms_ctrl/rfu.h @@ -5,56 +5,14 @@ Sega SG-1000/Mark-III/SMS "Rapid Fire Unit" emulation **********************************************************************/ - #ifndef MAME_BUS_SMS_CTRL_RFU_H #define MAME_BUS_SMS_CTRL_RFU_H #pragma once - #include "smsctrl.h" - -//************************************************************************** -// TYPE DEFINITIONS -//************************************************************************** - -// ======================> sms_rapid_fire_device - -class sms_rapid_fire_device : public device_t, - public device_sms_control_port_interface -{ -public: - // construction/destruction - sms_rapid_fire_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - -protected: - // device-level overrides - virtual void device_start() override; - - // optional information overrides - virtual ioport_constructor device_input_ports() const override; - virtual void device_add_mconfig(machine_config &config) override; - - // device_sms_control_port_interface overrides - virtual uint8_t peripheral_r() override; - virtual void peripheral_w(uint8_t data) override; - -private: - DECLARE_WRITE_LINE_MEMBER(th_pin_w); - - required_ioport m_rfire_sw; - required_device m_subctrl_port; - - uint8_t m_read_state; - attotime m_start_time; - const attotime m_interval; -}; - - -// device type definition -DECLARE_DEVICE_TYPE(SMS_RAPID_FIRE, sms_rapid_fire_device) - +DECLARE_DEVICE_TYPE(SMS_RAPID_FIRE, device_sms_control_interface) #endif // MAME_BUS_SMS_CTRL_RFU_H diff --git a/src/devices/bus/sms_ctrl/smsctrl.cpp b/src/devices/bus/sms_ctrl/smsctrl.cpp index cec153b863e..8db72026c28 100644 --- a/src/devices/bus/sms_ctrl/smsctrl.cpp +++ b/src/devices/bus/sms_ctrl/smsctrl.cpp @@ -1,132 +1,78 @@ // license:BSD-3-Clause -// copyright-holders:Fabio Priuli +// copyright-holders:Vas Crabb /********************************************************************** - Sega Master System controller port emulation + Sega DE-9 controller port emulation **********************************************************************/ #include "emu.h" -#include "screen.h" #include "smsctrl.h" -// slot devices -#include "joypad.h" -#include "lphaser.h" -#include "paddle.h" -#include "sports.h" -#include "sportsjp.h" -#include "rfu.h" -#include "multitap.h" -#include "graphic.h" - //************************************************************************** // GLOBAL VARIABLES //************************************************************************** -DEFINE_DEVICE_TYPE(SMS_CONTROL_PORT, sms_control_port_device, "sms_control_port", "Sega SMS controller port") +DEFINE_DEVICE_TYPE(SMS_CONTROL_PORT, sms_control_port_device, "sms_control_port", "Sega DE-9 controller port") //************************************************************************** -// CARD INTERFACE +// CONTROLLER INTERFACE //************************************************************************** -//------------------------------------------------- -// device_sms_control_port_interface - constructor -//------------------------------------------------- - -device_sms_control_port_interface::device_sms_control_port_interface(const machine_config &mconfig, device_t &device) - : device_interface(device, "smsctrl") +device_sms_control_interface::device_sms_control_interface(machine_config const &mconfig, device_t &device) : + device_interface(device, "smsctrl"), + m_port(dynamic_cast(device.owner())) { - m_port = dynamic_cast(device.owner()); } -//------------------------------------------------- -// ~device_sms_control_port_interface - destructor -//------------------------------------------------- - -device_sms_control_port_interface::~device_sms_control_port_interface() +device_sms_control_interface::~device_sms_control_interface() { } - -//************************************************************************** -// LIVE DEVICE -//************************************************************************** - -//------------------------------------------------- -// sms_control_port_device - constructor -//------------------------------------------------- - -sms_control_port_device::sms_control_port_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - device_t(mconfig, SMS_CONTROL_PORT, tag, owner, clock), - device_slot_interface(mconfig, *this), - m_screen(*this, finder_base::DUMMY_TAG), - m_device(nullptr), - m_th_pin_handler(*this) +u8 device_sms_control_interface::in_r() { + return 0xff; } -//------------------------------------------------- -// sms_control_port_device - destructor -//------------------------------------------------- - -sms_control_port_device::~sms_control_port_device() +void device_sms_control_interface::out_w(u8 data, u8 mem_mask) { } -//------------------------------------------------- -// device_start - device-specific startup -//------------------------------------------------- - -void sms_control_port_device::device_start() -{ - m_device = dynamic_cast(get_card_device()); - - m_th_pin_handler.resolve_safe(); -} +//************************************************************************** +// SLOT DEVICE +//************************************************************************** -uint8_t sms_control_port_device::port_r() +sms_control_port_device::sms_control_port_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) : + device_t(mconfig, SMS_CONTROL_PORT, tag, owner, clock), + device_single_card_slot_interface(mconfig, *this), + m_screen(*this, finder_base::DUMMY_TAG), + m_th_handler(*this), + m_controller(nullptr) { - uint8_t data = 0xff; - if (m_device) - data = m_device->peripheral_r(); - return data; } -void sms_control_port_device::port_w( uint8_t data ) + +sms_control_port_device::~sms_control_port_device() { - if (m_device) - m_device->peripheral_w(data); } -void sms_control_port_device::th_pin_w(int state) +void sms_control_port_device::device_resolve_objects() { - m_th_pin_handler(state); + m_th_handler.resolve_safe(); } -//------------------------------------------------- -// SLOT_INTERFACE( sms_control_port_devices ) -//------------------------------------------------- - -void sms_control_port_devices(device_slot_interface &device) +void sms_control_port_device::device_start() { - device.option_add("joypad", SMS_JOYPAD); - device.option_add("lphaser", SMS_LIGHT_PHASER); - device.option_add("paddle", SMS_PADDLE); - device.option_add("sportspad", SMS_SPORTS_PAD); - device.option_add("sportspadjp", SMS_SPORTS_PAD_JP); - device.option_add("rapidfire", SMS_RAPID_FIRE); - device.option_add("multitap", SMS_MULTITAP); - device.option_add("graphic", SMS_GRAPHIC); + m_controller = get_card_device(); } diff --git a/src/devices/bus/sms_ctrl/smsctrl.h b/src/devices/bus/sms_ctrl/smsctrl.h index cee1daa0cb9..6725f877bda 100644 --- a/src/devices/bus/sms_ctrl/smsctrl.h +++ b/src/devices/bus/sms_ctrl/smsctrl.h @@ -1,38 +1,55 @@ // license:BSD-3-Clause -// copyright-holders:Fabio Priuli +// copyright-holders:Vas Crabb /********************************************************************** - Sega Master System controller port emulation + Sega DE-9 controller port emulation -********************************************************************** + 1 Up in + 2 Down in + 3 Left in + 4 Right in + 5 +5V + 6 TL TxD in + 7 TH in/out edge-sensitive + 8 GND + 9 TR RxD in/out + SG-1000 Mark III: + * Pin 7 (TH) tied to ground + * Pin 9 (TR) is input only -**********************************************************************/ + Mega Drive: + * All pins besides +5V and GND are in/out +**********************************************************************/ #ifndef MAME_BUS_SMS_CTRL_SMSCTRL_H #define MAME_BUS_SMS_CTRL_SMSCTRL_H +#pragma once + #include "screen.h" -#pragma once +#include //************************************************************************** -// TYPE DEFINITIONS +// FORWARD DECLARATIONS //************************************************************************** -// ======================> sms_control_port_device +class device_sms_control_interface; -class device_sms_control_port_interface; -class sms_control_port_device : public device_t, - public device_slot_interface + +//************************************************************************** +// CLASS DECLARATIONS +//************************************************************************** + +class sms_control_port_device : public device_t, public device_single_card_slot_interface { public: - // construction/destruction template - sms_control_port_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *dflt) - : sms_control_port_device(mconfig, tag, owner, 0) + sms_control_port_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *dflt) : + sms_control_port_device(mconfig, tag, owner, 0) { option_reset(); opts(*this); @@ -40,70 +57,95 @@ public: set_fixed(false); } - sms_control_port_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + sms_control_port_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock); virtual ~sms_control_port_device(); - // static configuration helpers - auto th_input_handler() { return m_th_pin_handler.bind(); } - - // Physical DE-9 connector interface - - // Data returned by the port_r methods: - // bit 0 - pin 1 - Up - // bit 1 - pin 2 - Down - // bit 2 - pin 3 - Left - // bit 3 - pin 4 - Right - // bit 4 - pin 5 - Vcc (no data) - // bit 5 - pin 6 - TL (Button 1/Light Phaser Trigger) - // bit 6 - pin 7 - TH (Light Phaser sensor) - // pin 8 - GND - // bit 7 - pin 9 - TR (Button 2) - // - uint8_t port_r(); - void port_w( uint8_t data ); - - void th_pin_w(int state); + auto th_handler() { return m_th_handler.bind(); } // 0 for pulled low, 1 for pulled high or high impedance + template void set_screen(T &&tag) { m_screen.set_tag(std::forward(tag)); } - template void set_screen_tag(T &&tag) { m_screen.set_tag(std::forward(tag)); } - - // for peripherals that interact with the machine's screen - required_device m_screen; + // Bit Pin Signal + // 0 1 Up + // 1 2 Down + // 2 3 Left + // 3 4 Right + // 4 6 TL + // 5 9 TR + // + // return bits set for pulled high or high impedance + // return bits clear for pulled low + u8 in_r(); + + // Bit Pin Signal + // 0 1 Up + // 1 2 Down + // 2 3 Left + // 3 4 Right + // 4 6 TL + // 5 9 TR + // 6 7 TH + // + // mem_mask bits set for lines driven by low impedance output + // mem_mask bits clear for lines with high-impedance pull-up/pull-down + void out_w(u8 data, u8 mem_mask); protected: - // device-level overrides + virtual void device_resolve_objects() override; virtual void device_start() override; - device_sms_control_port_interface *m_device; - private: - devcb_write_line m_th_pin_handler; -}; + optional_device m_screen; + devcb_write_line m_th_handler; + + device_sms_control_interface *m_controller; + friend class device_sms_control_interface; +}; -// ======================> device_sms_control_port_interface -// class representing interface-specific live sms_expansion card -class device_sms_control_port_interface : public device_interface +class device_sms_control_interface : public device_interface { public: - // construction/destruction - virtual ~device_sms_control_port_interface(); + virtual ~device_sms_control_interface(); - virtual uint8_t peripheral_r() { return 0xff; } - virtual void peripheral_w(uint8_t data) { } + virtual u8 in_r(); + virtual void out_w(u8 data, u8 mem_mask); protected: - device_sms_control_port_interface(const machine_config &mconfig, device_t &device); + device_sms_control_interface(machine_config const &mconfig, device_t &device); + + template void configure_screen(T &&act) { if (m_port) act(std::as_const(m_port->m_screen)); } + + screen_device *screen() const { return m_port ? m_port->m_screen.target() : nullptr; } + DECLARE_WRITE_LINE_MEMBER(th_w) { if (m_port) m_port->m_th_handler(state); } - sms_control_port_device *m_port; +private: + sms_control_port_device *const m_port; }; -// device type definition -DECLARE_DEVICE_TYPE(SMS_CONTROL_PORT, sms_control_port_device) +//************************************************************************** +// INLINE MEMBER FUNCTIONS +//************************************************************************** + +inline u8 sms_control_port_device::in_r() +{ + return m_controller ? m_controller->in_r() : 0xff; +} -void sms_control_port_devices(device_slot_interface &device); +inline void sms_control_port_device::out_w(u8 data, u8 mem_mask) +{ + if (m_controller) + m_controller->out_w(data, mem_mask); +} + + + +//************************************************************************** +// DEVICE TYPE DECLARATIONS +//************************************************************************** + +DECLARE_DEVICE_TYPE(SMS_CONTROL_PORT, sms_control_port_device) #endif // MAME_BUS_SMS_CTRL_SMSCTRL_H diff --git a/src/devices/bus/sms_ctrl/sports.cpp b/src/devices/bus/sms_ctrl/sports.cpp index d58cfb68095..664382246f6 100644 --- a/src/devices/bus/sms_ctrl/sports.cpp +++ b/src/devices/bus/sms_ctrl/sports.cpp @@ -23,7 +23,7 @@ Notes: when it does not detect use by a Japanese SMS console, because the Sega Mark III lacks the TH line. There was a different Sports Pad model released in Japan and no information was found about it supporting both modes, so - that model is currently emulated as a different device (see sportsjp.c). + that model is currently emulated as a different device (see sportsjp.cpp). It was discovered that games designed for the Paddle Controller, released in Japan, will switch to a mode incompatible with the original Paddle when @@ -41,153 +41,158 @@ Notes: #include "sports.h" +namespace { + +INPUT_PORTS_START( sms_sports_pad ) + PORT_START("SPORTS_BT") + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) // TL + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 ) // TR + + PORT_START("SPORTS_X") // X axis + PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_X ) PORT_SENSITIVITY(50) PORT_KEYDELTA(40) PORT_REVERSE + + PORT_START("SPORTS_Y") // Y axis + PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_Y ) PORT_SENSITIVITY(50) PORT_KEYDELTA(40) PORT_REVERSE +INPUT_PORTS_END + + //************************************************************************** -// DEVICE DEFINITIONS +// TYPE DEFINITIONS //************************************************************************** -DEFINE_DEVICE_TYPE(SMS_SPORTS_PAD, sms_sports_pad_device, "sms_sports_pad", "Sega SMS Sports Pad (US)") +class sms_sports_pad_device : public device_t, public device_sms_control_interface +{ +public: + // construction/destruction + sms_sports_pad_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + // device_sms_control_interface implementation + virtual uint8_t in_r() override; + virtual void out_w(uint8_t data, uint8_t mem_mask) override; + +protected: + // device_t implementation + virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(sms_sports_pad); } + virtual void device_start() override; + +private: + TIMER_CALLBACK_MEMBER(timeout); -// time interval not verified -#define SPORTS_PAD_INTERVAL attotime::from_hz(XTAL(10'738'635)/3/512) + required_ioport m_buttons; + required_ioport m_x_axis; + required_ioport m_y_axis; + emu_timer *m_timeout_timer; -TIMER_CALLBACK_MEMBER(sms_sports_pad_device::read_tick) + uint8_t m_phase; + uint8_t m_th_state; + uint8_t m_x_base; + uint8_t m_y_base; + uint8_t m_data; +}; + + +TIMER_CALLBACK_MEMBER(sms_sports_pad_device::timeout) { // values for x and y axis need to be reset for Sports Pad games, but // are not reset for paddle games, so it was assumed the reset occurs // only when this timer fires after the read state reaches its maximum value. - if (m_read_state == 3) + if (3U == m_phase) { - m_x_axis_reset_value = m_sports_x->read(); - m_y_axis_reset_value = m_sports_y->read(); + m_x_base = m_x_axis->read(); + m_y_base = m_y_axis->read(); } else { // set to maximum value, so it wraps to 0 at next increment - m_read_state = 3; + m_phase = 3; } } -READ_LINE_MEMBER( sms_sports_pad_device::th_pin_r ) +//------------------------------------------------- +// sms_sports_pad_device - constructor +//------------------------------------------------- + +sms_sports_pad_device::sms_sports_pad_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + device_t(mconfig, SMS_SPORTS_PAD, tag, owner, clock), + device_sms_control_interface(mconfig, *this), + m_buttons(*this, "SPORTS_BT"), + m_x_axis(*this, "SPORTS_X"), + m_y_axis(*this, "SPORTS_Y"), + m_timeout_timer(nullptr), + m_phase(0), + m_th_state(1), + m_x_base(0), + m_y_base(0) { - return m_th_pin_state; } -WRITE_LINE_MEMBER( sms_sports_pad_device::th_pin_w ) +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void sms_sports_pad_device::device_start() { - m_read_state = (m_read_state + 1) & 3; - m_sportspad_timer->adjust(m_interval); - m_th_pin_state = state; + m_timeout_timer = timer_alloc(FUNC(sms_sports_pad_device::timeout), this); + + m_phase = 0; + m_x_base = 0x80; // value 0x80 helps when starting paddle games. + m_y_base = 0x80; + + save_item(NAME(m_phase)); + save_item(NAME(m_th_state)); + save_item(NAME(m_x_base)); + save_item(NAME(m_y_base)); } -CUSTOM_INPUT_MEMBER( sms_sports_pad_device::rldu_pins_r ) +uint8_t sms_sports_pad_device::in_r() { - uint8_t data = 0; + uint8_t result = m_buttons->read(); - switch (m_read_state) + switch (m_phase) { case 0: - data = (m_sports_x->read() - m_x_axis_reset_value) >> 4; + result |= BIT(m_x_axis->read() - m_x_base, 4, 4); break; case 1: - data = (m_sports_x->read() - m_x_axis_reset_value); + result |= BIT(m_x_axis->read() - m_x_base, 0, 4); break; case 2: - data = (m_sports_y->read() - m_y_axis_reset_value) >> 4; + result |= BIT(m_y_axis->read() - m_y_base, 4, 4); break; case 3: - data = (m_sports_y->read() - m_y_axis_reset_value); + result |= BIT(m_y_axis->read() - m_y_base, 0, 4); break; } - // The returned value is inverted due to IP_ACTIVE_LOW mapping. - return ~(data & 0x0f); + return result; } -static INPUT_PORTS_START( sms_sports_pad ) - PORT_START("SPORTS_IN") - PORT_BIT( 0x0f, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_CUSTOM_MEMBER(sms_sports_pad_device, rldu_pins_r) // R,L,D,U - PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) // Vcc - PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 ) // TL (Button 1) - PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_READ_LINE_MEMBER(sms_sports_pad_device, th_pin_r) // TH - PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON2 ) // TR (Button 2) - - PORT_START("SPORTS_OUT") - PORT_BIT( 0x0f, IP_ACTIVE_LOW, IPT_UNUSED ) // Directional pins - PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) // Vcc - PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED ) // TL (Button 1) - PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_OUTPUT ) PORT_WRITE_LINE_MEMBER(sms_sports_pad_device, th_pin_w) // TH - PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) // TR (Button 2) - - PORT_START("SPORTS_X") /* Sports Pad X axis */ - PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_X ) PORT_SENSITIVITY(50) PORT_KEYDELTA(40) PORT_REVERSE - - PORT_START("SPORTS_Y") /* Sports Pad Y axis */ - PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_Y ) PORT_SENSITIVITY(50) PORT_KEYDELTA(40) PORT_REVERSE -INPUT_PORTS_END - - -//------------------------------------------------- -// input_ports - device-specific input ports -//------------------------------------------------- - -ioport_constructor sms_sports_pad_device::device_input_ports() const +void sms_sports_pad_device::out_w(uint8_t data, uint8_t mem_mask) { - return INPUT_PORTS_NAME( sms_sports_pad ); -} - + uint8_t const th_state = BIT(data, 6); + // FIXME: this is definitely wrong - work out how it actually responds to edges + if (th_state != m_th_state) + { + m_phase = (m_phase + 1) & 3; + m_timeout_timer->adjust(attotime::from_hz(XTAL(10'738'635) / 3 / 512)); // timeout not verified + } -//************************************************************************** -// LIVE DEVICE -//************************************************************************** - -//------------------------------------------------- -// sms_sports_pad_device - constructor -//------------------------------------------------- - -sms_sports_pad_device::sms_sports_pad_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - device_t(mconfig, SMS_SPORTS_PAD, tag, owner, clock), - device_sms_control_port_interface(mconfig, *this), - m_sports_in(*this, "SPORTS_IN"), - m_sports_out(*this, "SPORTS_OUT"), - m_sports_x(*this, "SPORTS_X"), - m_sports_y(*this, "SPORTS_Y"), - m_read_state(0), - m_th_pin_state(0), - m_x_axis_reset_value(0x80), // value 0x80 helps when starting paddle games. - m_y_axis_reset_value(0x80), - m_interval(SPORTS_PAD_INTERVAL), - m_sportspad_timer(nullptr) -{ + m_th_state = th_state; } +} // anonymous namespace -//------------------------------------------------- -// device_start - device-specific startup -//------------------------------------------------- - -void sms_sports_pad_device::device_start() -{ - m_sportspad_timer = timer_alloc(FUNC(sms_sports_pad_device::read_tick), this); - save_item(NAME(m_read_state)); - save_item(NAME(m_th_pin_state)); - save_item(NAME(m_x_axis_reset_value)); - save_item(NAME(m_y_axis_reset_value)); -} -uint8_t sms_sports_pad_device::peripheral_r() -{ - return m_sports_in->read(); -} +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** -void sms_sports_pad_device::peripheral_w(uint8_t data) -{ - m_sports_out->write(data); -} +DEFINE_DEVICE_TYPE_PRIVATE(SMS_SPORTS_PAD, device_sms_control_interface, sms_sports_pad_device, "sms_sports_pad", "Sega SMS Sports Pad (US)") diff --git a/src/devices/bus/sms_ctrl/sports.h b/src/devices/bus/sms_ctrl/sports.h index cdf1202befd..ac6e75e5626 100644 --- a/src/devices/bus/sms_ctrl/sports.h +++ b/src/devices/bus/sms_ctrl/sports.h @@ -5,64 +5,14 @@ Sega Master System "Sports Pad" (US model) emulation **********************************************************************/ - #ifndef MAME_BUS_SMS_CTRL_SPORTS_H #define MAME_BUS_SMS_CTRL_SPORTS_H #pragma once - #include "smsctrl.h" - -//************************************************************************** -// TYPE DEFINITIONS -//************************************************************************** - -// ======================> sms_sports_pad_device - -class sms_sports_pad_device : public device_t, - public device_sms_control_port_interface -{ -public: - // construction/destruction - sms_sports_pad_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - // optional information overrides - virtual ioport_constructor device_input_ports() const override; - - DECLARE_CUSTOM_INPUT_MEMBER( rldu_pins_r ); // Right, Left, Down and Up lines. - DECLARE_READ_LINE_MEMBER( th_pin_r ); - DECLARE_WRITE_LINE_MEMBER( th_pin_w ); - -protected: - // device-level overrides - virtual void device_start() override; - - // device_sms_control_port_interface overrides - virtual uint8_t peripheral_r() override; - virtual void peripheral_w(uint8_t data) override; - -private: - required_ioport m_sports_in; - required_ioport m_sports_out; - required_ioport m_sports_x; - required_ioport m_sports_y; - - uint8_t m_read_state; - uint8_t m_th_pin_state; - uint8_t m_x_axis_reset_value; - uint8_t m_y_axis_reset_value; - const attotime m_interval; - emu_timer *m_sportspad_timer; - - TIMER_CALLBACK_MEMBER(read_tick); -}; - - -// device type definition -DECLARE_DEVICE_TYPE(SMS_SPORTS_PAD, sms_sports_pad_device) - +DECLARE_DEVICE_TYPE(SMS_SPORTS_PAD, device_sms_control_interface) #endif // MAME_BUS_SMS_CTRL_SPORTS_H diff --git a/src/devices/bus/sms_ctrl/sportsjp.cpp b/src/devices/bus/sms_ctrl/sportsjp.cpp index a0c2a69d2ad..ecdbc1a7967 100644 --- a/src/devices/bus/sms_ctrl/sportsjp.cpp +++ b/src/devices/bus/sms_ctrl/sportsjp.cpp @@ -45,59 +45,47 @@ Notes: #include "sportsjp.h" +namespace { -//************************************************************************** -// DEVICE DEFINITIONS -//************************************************************************** - -DEFINE_DEVICE_TYPE(SMS_SPORTS_PAD_JP, sms_sports_pad_jp_device, "sms_sports_pad_jp", "Sega SMS Sports Pad (JP)") - -// time interval not verified -#define SPORTS_PAD_JP_INTERVAL attotime::from_hz(20000) - - - -// The returned value is inverted due to IP_ACTIVE_LOW mapping. -READ_LINE_MEMBER( sms_sports_pad_jp_device::tl_pin_r ) { return ~m_tl_pin_state; } -READ_LINE_MEMBER( sms_sports_pad_jp_device::tr_pin_r ) { return ~m_tr_pin_state; } -CUSTOM_INPUT_MEMBER( sms_sports_pad_jp_device::rldu_pins_r ) { return ~(m_rldu_pins_state & 0x0f); } - - -static INPUT_PORTS_START( sms_sports_pad_jp ) - PORT_START("SPORTS_JP_IN") - PORT_BIT( 0x0f, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_CUSTOM_MEMBER(sms_sports_pad_jp_device, rldu_pins_r) // R,L,D,U - PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) // Vcc - PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_READ_LINE_MEMBER(sms_sports_pad_jp_device, tl_pin_r) // TL - PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED ) // TH - PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_READ_LINE_MEMBER(sms_sports_pad_jp_device, tr_pin_r) // TR - - PORT_START("SPORTS_JP_BT") /* Sports Pad buttons nibble */ - PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 ) - PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON2 ) +INPUT_PORTS_START( sms_sports_pad_jp ) + PORT_START("SPORTS_JP_BT") // buttons + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 ) // TL + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON2 ) // TR PORT_BIT( 0x0c, IP_ACTIVE_LOW, IPT_UNUSED ) - PORT_START("SPORTS_JP_X") /* Sports Pad X axis */ + PORT_START("SPORTS_JP_X") // X axis PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_X ) PORT_SENSITIVITY(50) PORT_KEYDELTA(40) - PORT_START("SPORTS_JP_Y") /* Sports Pad Y axis */ + PORT_START("SPORTS_JP_Y") // Y axis PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_Y ) PORT_SENSITIVITY(50) PORT_KEYDELTA(40) INPUT_PORTS_END -//------------------------------------------------- -// input_ports - device-specific input ports -//------------------------------------------------- -ioport_constructor sms_sports_pad_jp_device::device_input_ports() const +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +class sms_sports_pad_jp_device : public device_t, public device_sms_control_interface { - return INPUT_PORTS_NAME( sms_sports_pad_jp ); -} +public: + // construction/destruction + sms_sports_pad_jp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + // device_sms_control_interface implementation + virtual uint8_t in_r() override; +protected: + // device_t implementation + virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(sms_sports_pad_jp); } + virtual void device_start() override { } + +private: + required_ioport m_buttons; + required_ioport m_x_axis; + required_ioport m_y_axis; +}; -//************************************************************************** -// LIVE DEVICE -//************************************************************************** //------------------------------------------------- // sms_sports_pad_jp_device - constructor @@ -105,75 +93,44 @@ ioport_constructor sms_sports_pad_jp_device::device_input_ports() const sms_sports_pad_jp_device::sms_sports_pad_jp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, SMS_SPORTS_PAD_JP, tag, owner, clock), - device_sms_control_port_interface(mconfig, *this), - m_sports_jp_in(*this, "SPORTS_JP_IN"), - m_sports_jp_bt(*this, "SPORTS_JP_BT"), - m_sports_jp_x(*this, "SPORTS_JP_X"), - m_sports_jp_y(*this, "SPORTS_JP_Y"), - m_rldu_pins_state(0x0f), - m_tl_pin_state(1), - m_tr_pin_state(1), - m_interval(SPORTS_PAD_JP_INTERVAL) + device_sms_control_interface(mconfig, *this), + m_buttons(*this, "SPORTS_JP_BT"), + m_x_axis(*this, "SPORTS_JP_X"), + m_y_axis(*this, "SPORTS_JP_Y") { } //------------------------------------------------- -// device_start - device-specific startup +// sms_peripheral_r - sports pad read //------------------------------------------------- -void sms_sports_pad_jp_device::device_start() +uint8_t sms_sports_pad_jp_device::in_r() { - m_start_time = machine().time(); + int const num_intervals = machine().time().as_ticks(20000); // time interval not verified - save_item(NAME(m_start_time)); - save_item(NAME(m_rldu_pins_state)); - save_item(NAME(m_tl_pin_state)); - save_item(NAME(m_tr_pin_state)); + switch (num_intervals % 5) + { + default: // shut up dumb compilers + case 0: // X high nibble + return 0x00 | ((m_x_axis->read() >> 4) & 0x0f); + case 1: // X low nibble + return 0x10 | (m_x_axis->read() & 0x0f); + case 2: // Y high nibble + return 0x00 | ((m_y_axis->read() >> 4) & 0x0f); + case 3: // Y low nibble + return 0x10 | (m_y_axis->read() & 0x0f); + case 4: // buttons 1 and 2 + return 0x30 | m_buttons->read(); + } } +} // anonymous namespace -//------------------------------------------------- -// sms_peripheral_r - sports pad read -//------------------------------------------------- -uint8_t sms_sports_pad_jp_device::peripheral_r() -{ - int num_intervals = (machine().time() - m_start_time).as_double() / m_interval.as_double(); - switch (num_intervals % 5) - { - case 0: - // X high nibble - m_rldu_pins_state = m_sports_jp_x->read() >> 4; - m_tl_pin_state = 0; - m_tr_pin_state = 0; - break; - case 1: - // X low nibble - m_rldu_pins_state = m_sports_jp_x->read(); - m_tl_pin_state = 1; - m_tr_pin_state = 0; - break; - case 2: - // Y high nibble - m_rldu_pins_state = m_sports_jp_y->read() >> 4; - m_tl_pin_state = 0; - m_tr_pin_state = 0; - break; - case 3: - // Y low nibble - m_rldu_pins_state = m_sports_jp_y->read(); - m_tl_pin_state = 1; - m_tr_pin_state = 0; - break; - case 4: - // buttons 1 and 2 - m_rldu_pins_state = m_sports_jp_bt->read(); - m_tl_pin_state = 1; - m_tr_pin_state = 1; - break; - } +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** - return m_sports_jp_in->read(); -} +DEFINE_DEVICE_TYPE_PRIVATE(SMS_SPORTS_PAD_JP, device_sms_control_interface, sms_sports_pad_jp_device, "sms_sports_pad_jp", "Sega Mark III Sports Pad (Japan)") diff --git a/src/devices/bus/sms_ctrl/sportsjp.h b/src/devices/bus/sms_ctrl/sportsjp.h index 92ee2ccd70c..016605c5d2e 100644 --- a/src/devices/bus/sms_ctrl/sportsjp.h +++ b/src/devices/bus/sms_ctrl/sportsjp.h @@ -5,60 +5,14 @@ Sega Master System "Sports Pad" (Japanese model) emulation **********************************************************************/ - #ifndef MAME_BUS_SMS_CTROL_SPORTSJP_H #define MAME_BUS_SMS_CTROL_SPORTSJP_H #pragma once - #include "smsctrl.h" - -//************************************************************************** -// TYPE DEFINITIONS -//************************************************************************** - -// ======================> sms_sports_pad_jp_device - -class sms_sports_pad_jp_device : public device_t, - public device_sms_control_port_interface -{ -public: - // construction/destruction - sms_sports_pad_jp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - // optional information overrides - virtual ioport_constructor device_input_ports() const override; - - DECLARE_CUSTOM_INPUT_MEMBER( rldu_pins_r ); // Right, Left, Down and Up lines. - DECLARE_READ_LINE_MEMBER( tl_pin_r ); - DECLARE_READ_LINE_MEMBER( tr_pin_r ); - -protected: - // device-level overrides - virtual void device_start() override; - - // device_sms_control_port_interface overrides - virtual uint8_t peripheral_r() override; - -private: - required_ioport m_sports_jp_in; - required_ioport m_sports_jp_bt; - required_ioport m_sports_jp_x; - required_ioport m_sports_jp_y; - - uint8_t m_rldu_pins_state; - uint8_t m_tl_pin_state; - uint8_t m_tr_pin_state; - attotime m_start_time; - const attotime m_interval; -}; - - -// device type definition -DECLARE_DEVICE_TYPE(SMS_SPORTS_PAD_JP, sms_sports_pad_jp_device) - +DECLARE_DEVICE_TYPE(SMS_SPORTS_PAD_JP, device_sms_control_interface) #endif // MAME_BUS_SMS_CTROL_SPORTSJP_H diff --git a/src/mame/sega/mdconsole.cpp b/src/mame/sega/mdconsole.cpp index 0021f421f11..48a2bcfc201 100644 --- a/src/mame/sega/mdconsole.cpp +++ b/src/mame/sega/mdconsole.cpp @@ -6,6 +6,7 @@ #include "bus/generic/carts.h" #include "bus/generic/slot.h" +#include "bus/sms_ctrl/controllers.h" #include "imagedev/chd_cd.h" #include "sound/sn76496.h" @@ -24,139 +25,57 @@ /* They're needed to give the users the choice between different controllers */ uint8_t md_cons_state::mess_md_io_read_data_port(offs_t offset) { - int portnum = offset; + // get bits set to output first - bit 7 always reads the latch + uint8_t const mask = m_io_ctrl_regs[offset] | 0x80; + uint8_t result = mask & m_io_data_regs[offset]; - uint8_t retdata; - int controller; - uint8_t helper_6b = (m_megadrive_io_ctrl_regs[portnum] & 0x3f) | 0xc0; // bits 6 & 7 always come from megadrive_io_data_regs - uint8_t helper_3b = (m_megadrive_io_ctrl_regs[portnum] & 0x7f) | 0x80; // bit 7 always comes from megadrive_io_data_regs - - switch (portnum) + switch (offset) { - case 0: - controller = (m_io_ctrlr->read() & 0x0f); - break; - - case 1: - controller = (m_io_ctrlr->read() & 0xf0); - break; + case 0: + case 1: + result |= ~mask & (m_io_ctrl_th_in[offset] | (m_ctrl_ports[offset]->in_r() & 0x3f)); + break; - default: - controller = 0; - break; + default: // TODO: where does this come from on a console? + result |= 0x7f; } - /* Are we using a 6 buttons Joypad? */ - if (controller) - { - if (m_megadrive_io_data_regs[portnum] & 0x40) - { - if (m_io_stage[portnum] == 2) - { - /* here we read B, C & the additional buttons */ - retdata = (m_megadrive_io_data_regs[portnum] & helper_6b) | - ((((m_io_pad6b[0][portnum] ? m_io_pad6b[0][portnum]->read() : 0) & 0x30) | - ((m_io_pad6b[1][portnum] ? m_io_pad6b[1][portnum]->read() : 0) & 0x0f)) & ~helper_6b); - } - else - { - /* here we read B, C & the directional buttons */ - retdata = (m_megadrive_io_data_regs[portnum] & helper_6b) | - (((m_io_pad6b[0][portnum] ? m_io_pad6b[0][portnum]->read() : 0) & 0x3f) & ~helper_6b); - } - } - else - { - if (m_io_stage[portnum] == 1) - { - /* here we read ((Start & A) >> 2) | 0x00 */ - retdata = (m_megadrive_io_data_regs[portnum] & helper_6b) | - ((((m_io_pad6b[0][portnum] ? m_io_pad6b[0][portnum]->read() : 0) & 0xc0) >> 2) & ~helper_6b); - } - else if (m_io_stage[portnum]==2) - { - /* here we read ((Start & A) >> 2) | 0x0f */ - retdata = (m_megadrive_io_data_regs[portnum] & helper_6b) | - (((((m_io_pad6b[0][portnum] ? m_io_pad6b[0][portnum]->read() : 0) & 0xc0) >> 2) | 0x0f) & ~helper_6b); - } - else - { - /* here we read ((Start & A) >> 2) | Up and Down */ - retdata = (m_megadrive_io_data_regs[portnum] & helper_6b) | - (((((m_io_pad6b[0][portnum] ? m_io_pad6b[0][portnum]->read() : 0) & 0xc0) >> 2) | - ((m_io_pad6b[0][portnum] ? m_io_pad6b[0][portnum]->read() : 0) & 0x03)) & ~helper_6b); - } - } - - // osd_printf_debug("read io data port stage %d port %d %02x\n",mess_io_stage[portnum],portnum,retdata); + // handle test input for SVP test + if (!offset && m_cart && m_cart->read_test()) + result = m_io_data_regs[0] & 0xc0; - retdata |= (retdata << 8); - } - /* Otherwise it's a 3 buttons Joypad */ - else - { - uint8_t svp_test = 0; - if (m_cart) - svp_test = m_cart->read_test(); - - // handle test input for SVP test - if (portnum == 0 && svp_test) - { - retdata = (m_megadrive_io_data_regs[0] & 0xc0); - } - else if (m_megadrive_io_data_regs[portnum] & 0x40) - { - /* here we read B, C & the directional buttons */ - retdata = (m_megadrive_io_data_regs[portnum] & helper_3b) | - ((((m_io_pad3b[portnum] ? m_io_pad3b[portnum]->read() : 0) & 0x3f) | 0x40) & ~helper_3b); - } - else - { - /* here we read ((Start & A) >> 2) | Up and Down */ - retdata = (m_megadrive_io_data_regs[portnum] & helper_3b) | - (((((m_io_pad3b[portnum] ? m_io_pad3b[portnum]->read() : 0) & 0xc0) >> 2) | - ((m_io_pad3b[portnum] ? m_io_pad3b[portnum]->read() : 0) & 0x03) | 0x40) & ~helper_3b); - } - } - - return retdata; + return result; } void md_cons_state::mess_md_io_write_data_port(offs_t offset, uint16_t data) { - int portnum = offset; - int controller; + // FIXME: need to update the port when I/O direction changes, too - switch (portnum) + switch (offset) { - case 0: - controller = (m_io_ctrlr->read() & 0x0f); - break; - - case 1: - controller = (m_io_ctrlr->read() & 0xf0); - break; + case 0: + case 1: + m_ctrl_ports[offset]->out_w((data | ~m_io_ctrl_regs[offset]) & 0x7f, m_io_ctrl_regs[offset] & 0x7f); + break; - default: - controller = 0; - break; + default: // TODO: where does this go on a console? + break; } - if (controller) - { - if (m_megadrive_io_ctrl_regs[portnum] & 0x40) - { - if (((m_megadrive_io_data_regs[portnum] & 0x40) == 0x00) && ((data & 0x40) == 0x40)) - { - m_io_stage[portnum]++; - m_io_timeout[portnum]->adjust(m_maincpu->cycles_to_attotime(8192)); - } + m_io_data_regs[offset] = data; +} - } - } - m_megadrive_io_data_regs[portnum] = data; - //osd_printf_debug("Writing IO Data Register #%d data %04x\n",portnum,data); + +void md_cons_state::md_ctrl_ports(machine_config &config) +{ + SMS_CONTROL_PORT(config, m_ctrl_ports[0], sms_control_port_devices, SMS_CTRL_OPTION_MD_PAD); + m_ctrl_ports[0]->th_handler().set([this] (int state) { m_io_ctrl_th_in[0] = state ? 0x40 : 0x00; }); + m_ctrl_ports[0]->set_screen(m_screen); + + SMS_CONTROL_PORT(config, m_ctrl_ports[1], sms_control_port_devices, SMS_CTRL_OPTION_MD_PAD); + m_ctrl_ports[1]->th_handler().set([this] (int state) { m_io_ctrl_th_in[1] = state ? 0x40 : 0x00; }); + m_ctrl_ports[1]->set_screen(m_screen); } @@ -167,96 +86,22 @@ void md_cons_state::mess_md_io_write_data_port(offs_t offset, uint16_t data) *************************************/ -static INPUT_PORTS_START( md_base ) - PORT_START("PAD1_3B") /* Joypad 1 (3 button + start) NOT READ DIRECTLY */ - PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x00) - PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x00) - PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x00) - PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x00) - PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1) PORT_NAME("P1 B") PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x00) - PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(1) PORT_NAME("P1 C") PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x00) - PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) PORT_NAME("P1 A") PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x00) - PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x00) - - PORT_START("PAD2_3B") /* Joypad 2 (3 button + start) NOT READ DIRECTLY */ - PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x00) - PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x00) - PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x00) - PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x00) - PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2) PORT_NAME("P2 B") PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x00) - PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(2) PORT_NAME("P2 C") PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x00) - PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) PORT_NAME("P2 A") PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x00) - PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x00) - - PORT_START("PAD1_6B") /* Joypad 1 (6 button + start + mode) NOT READ DIRECTLY */ - PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x01) - PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x01) - PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x01) - PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x01) - PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1) PORT_NAME("P1 B") PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x01) - PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(1) PORT_NAME("P1 C") PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x01) - PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) PORT_NAME("P1 A") PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x01) - PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x01) - - PORT_START("EXTRA1") /* Extra buttons for Joypad 1 (6 button + start + mode) NOT READ DIRECTLY */ - PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_PLAYER(1) PORT_NAME("P1 Z") PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x01) - PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_PLAYER(1) PORT_NAME("P1 Y") PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x01) - PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(1) PORT_NAME("P1 X") PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x01) - PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_BUTTON7 ) PORT_PLAYER(1) PORT_NAME("P1 Mode") PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x01) - - PORT_START("PAD2_6B") /* Joypad 2 (6 button + start + mode) NOT READ DIRECTLY */ - PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x10) - PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x10) - PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x10) - PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x10) - PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2) PORT_NAME("P2 B") PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x10) - PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(2) PORT_NAME("P2 C") PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x10) - PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) PORT_NAME("P2 A") PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x10) - PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x10) - - PORT_START("EXTRA2") /* Extra buttons for Joypad 2 (6 button + start + mode) NOT READ DIRECTLY */ - PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_PLAYER(2) PORT_NAME("P2 Z") PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x10) - PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_PLAYER(2) PORT_NAME("P2 Y") PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x10) - PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(2) PORT_NAME("P2 X") PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x10) - PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_BUTTON7 ) PORT_PLAYER(2) PORT_NAME("P2 Mode") PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x10) - - PORT_START("RESET") /* Buttons on Genesis Console */ - PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_SERVICE1 ) PORT_NAME("Reset Button") PORT_IMPULSE(1) // reset, resets 68k (and..?) -INPUT_PORTS_END - static INPUT_PORTS_START( md ) - PORT_INCLUDE( md_base ) - - PORT_START("CTRLSEL") /* Controller selection */ - PORT_CONFNAME( 0x0f, 0x00, "Player 1 Controller" ) - PORT_CONFSETTING( 0x00, "Joystick 3 Buttons" ) - PORT_CONFSETTING( 0x01, "Joystick 6 Buttons" ) -// PORT_CONFSETTING( 0x02, "Sega Mouse" ) + // Unemulated controllers: + // Sega Mouse + // Sega Menacer + // Konami Justifier + // Sega Team Player + // EA 4-Play /* there exists both a 2 buttons version of the Mouse (Jpn ver, to be used with RPGs, it can aslo be used as trackball) and a 3 buttons version (US ver, no trackball feats.) */ -// PORT_CONFSETTING( 0x03, "Sega Menacer" ) -// PORT_CONFSETTING( 0x04, "Konami Justifier" ) -// PORT_CONFSETTING( 0x05, "Team Player (Sega Multitap)" ) -// PORT_CONFSETTING( 0x06, "4-Play (EA Multitap)" ) -// PORT_CONFSETTING( 0x07, "J-Cart" ) - PORT_CONFNAME( 0xf0, 0x00, "Player 2 Controller" ) - PORT_CONFSETTING( 0x00, "Joystick 3 Buttons" ) - PORT_CONFSETTING( 0x10, "Joystick 6 Buttons" ) -INPUT_PORTS_END - -static INPUT_PORTS_START( megajet ) - PORT_INCLUDE( md_base ) - PORT_START("CTRLSEL") /* Fixed controller setting for Player 1 */ - PORT_CONFNAME( 0x0f, 0x01, "Player 1 Controller" ) // Fixed - PORT_CONFSETTING( 0x01, "Joystick 6 Buttons" ) - PORT_CONFNAME( 0xf0, 0x00, "Player 2 Controller" ) - PORT_CONFSETTING( 0x00, "Joystick 3 Buttons" ) - PORT_CONFSETTING( 0x10, "Joystick 6 Buttons" ) + PORT_START("RESET") // Buttons on Mega Drive console + PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_SERVICE1 ) PORT_NAME("Reset Button") PORT_IMPULSE(1) // reset, resets 68k (and..?) INPUT_PORTS_END static INPUT_PORTS_START( gen_nomd ) - PORT_INCLUDE( megajet ) + PORT_INCLUDE( md ) PORT_MODIFY("RESET") /* No reset button */ PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_UNUSED ) @@ -271,24 +116,10 @@ INPUT_PORTS_END void md_cons_state::machine_start() { - static const char *const pad6names[2][4] = { - { "PAD1_6B", "PAD2_6B", "UNUSED", "UNUSED" }, - { "EXTRA1", "EXTRA2", "UNUSED", "UNUSED" } - }; - static const char *const pad3names[4] = { "PAD1_3B", "PAD2_3B", "UNUSED", "UNUSED" }; + m_io_ctrl_th_in[0] = 0x40; + m_io_ctrl_th_in[1] = 0x40; - m_io_ctrlr = ioport("CTRLSEL"); - - for (int i = 0; i < 4; i++) - { - m_io_pad3b[i] = ioport(pad3names[i]); - m_io_pad6b[0][i] = ioport(pad6names[0][i]); - m_io_pad6b[1][i] = ioport(pad6names[1][i]); - } - - // setup timers for 6 button pads - for (int i = 0; i < 3; i++) - m_io_timeout[i] = timer_alloc(FUNC(md_base_state::io_timeout_timer_callback), this); + save_item(NAME(m_io_ctrl_th_in)); m_vdp->stop_timers(); @@ -415,7 +246,9 @@ void md_cons_slot_state::ms_megadriv(machine_config &config) { md_ntsc(config); - subdevice("megadriv")->screen_vblank().set(FUNC(md_cons_state::screen_vblank_console)); + m_screen->screen_vblank().set(FUNC(md_cons_slot_state::screen_vblank_console)); + + md_ctrl_ports(config); MD_CART_SLOT(config, m_cart, md_cart, nullptr).set_must_be_loaded(true); SOFTWARE_LIST(config, "cart_list").set_original("megadriv"); @@ -425,7 +258,9 @@ void md_cons_slot_state::ms_megadpal(machine_config &config) { md_pal(config); - subdevice("megadriv")->screen_vblank().set(FUNC(md_cons_state::screen_vblank_console)); + m_screen->screen_vblank().set(FUNC(md_cons_slot_state::screen_vblank_console)); + + md_ctrl_ports(config); MD_CART_SLOT(config, m_cart, md_cart, nullptr).set_must_be_loaded(true); SOFTWARE_LIST(config, "cart_list").set_original("megadriv"); @@ -435,12 +270,23 @@ void md_cons_slot_state::ms_megadriv2(machine_config &config) { md2_ntsc(config); - subdevice("megadriv")->screen_vblank().set(FUNC(md_cons_state::screen_vblank_console)); + m_screen->screen_vblank().set(FUNC(md_cons_slot_state::screen_vblank_console)); + + md_ctrl_ports(config); MD_CART_SLOT(config, m_cart, md_cart, nullptr).set_must_be_loaded(true); SOFTWARE_LIST(config, "cart_list").set_original("megadriv"); } +void md_cons_slot_state::ms_megajet(machine_config &config) +{ + ms_megadriv2(config); + + // P1 controller is integrated + m_ctrl_ports[0]->set_default_option(SMS_CTRL_OPTION_MD_6BUTTON); + m_ctrl_ports[0]->set_fixed(true); +} + void md_cons_slot_state::genesis_tmss(machine_config &config) { ms_megadriv(config); @@ -451,7 +297,9 @@ void md_cons_state::dcat16_megadriv(machine_config &config) { dcat16_megadriv_base(config); - subdevice("megadriv")->screen_vblank().set(FUNC(md_cons_state::screen_vblank_console)); + m_screen->screen_vblank().set(FUNC(md_cons_state::screen_vblank_console)); + + md_ctrl_ports(config); // has SD card slot instead? // MD_CART_SLOT(config, m_cart, md_cart, nullptr).set_must_be_loaded(true); @@ -465,7 +313,7 @@ void md_cons_state::dcat16_megadriv(machine_config &config) *************************************/ -/* we don't use the bios rom (it's not needed and only provides security on early models) */ +/* we don't use the BIOS ROM (it's not needed and only provides security on early models) */ ROM_START(genesis) ROM_REGION(MD_CPU_REGION_SIZE, "maincpu", ROMREGION_ERASEFF) @@ -515,8 +363,8 @@ ROM_END void md_cons_state::init_mess_md_common() { - m_megadrive_io_read_data_port_ptr = read8sm_delegate(*this, FUNC(md_cons_state::mess_md_io_read_data_port)); - m_megadrive_io_write_data_port_ptr = write16sm_delegate(*this, FUNC(md_cons_state::mess_md_io_write_data_port)); + m_io_read_data_port_ptr = read8sm_delegate(*this, FUNC(md_cons_state::mess_md_io_read_data_port)); + m_io_write_data_port_ptr = write16sm_delegate(*this, FUNC(md_cons_state::mess_md_io_write_data_port)); } void md_cons_state::init_genesis() @@ -660,7 +508,7 @@ void md_cons_state::genesis_32x(machine_config &config) m_32x->add_route(0, "lspeaker", 1.00); m_32x->add_route(1, "rspeaker", 1.00); - subdevice("megadriv")->screen_vblank().set(FUNC(md_cons_state::screen_vblank_console)); + m_screen->screen_vblank().set(FUNC(md_cons_state::screen_vblank_console)); // we need to remove and re-add the YM because the balance is different // due to MAME having severe issues if the dac output is > 0.40? (sound is corrupted even if DAC is silent?!) @@ -668,6 +516,8 @@ void md_cons_state::genesis_32x(machine_config &config) m_ymsnd->add_route(0, "lspeaker", (0.50)/2); m_ymsnd->add_route(1, "rspeaker", (0.50)/2); + md_ctrl_ports(config); + generic_cartslot_device &cartslot(GENERIC_CARTSLOT(config, "cartslot", generic_plain_slot, "_32x_cart", "32x,bin")); cartslot.set_must_be_loaded(true); cartslot.set_device_load(FUNC(md_cons_state::_32x_cart)); @@ -692,7 +542,7 @@ void md_cons_state::mdj_32x(machine_config &config) m_32x->add_route(0, "lspeaker", 1.00); m_32x->add_route(1, "rspeaker", 1.00); - subdevice("megadriv")->screen_vblank().set(FUNC(md_cons_state::screen_vblank_console)); + m_screen->screen_vblank().set(FUNC(md_cons_state::screen_vblank_console)); // we need to remove and re-add the sound system because the balance is different // due to MAME having severe issues if the dac output is > 0.40? (sound is corrupted even if DAC is silent?!) @@ -700,6 +550,8 @@ void md_cons_state::mdj_32x(machine_config &config) m_ymsnd->add_route(0, "lspeaker", (0.50)/2); m_ymsnd->add_route(1, "rspeaker", (0.50)/2); + md_ctrl_ports(config); + generic_cartslot_device &cartslot(GENERIC_CARTSLOT(config, "cartslot", generic_plain_slot, "_32x_cart", "32x,bin")); cartslot.set_must_be_loaded(true); cartslot.set_device_load(FUNC(md_cons_state::_32x_cart)); @@ -724,7 +576,7 @@ void md_cons_state::md_32x(machine_config &config) m_32x->add_route(0, "lspeaker", 1.00); m_32x->add_route(1, "rspeaker", 1.00); - subdevice("megadriv")->screen_vblank().set(FUNC(md_cons_state::screen_vblank_console)); + m_screen->screen_vblank().set(FUNC(md_cons_state::screen_vblank_console)); // we need to remove and re-add the sound system because the balance is different // due to MAME having severe issues if the dac output is > 0.40? (sound is corrupted even if DAC is silent?!) @@ -732,6 +584,8 @@ void md_cons_state::md_32x(machine_config &config) m_ymsnd->add_route(0, "lspeaker", (0.50)/2); m_ymsnd->add_route(1, "rspeaker", (0.50)/2); + md_ctrl_ports(config); + generic_cartslot_device &cartslot(GENERIC_CARTSLOT(config, "cartslot", generic_plain_slot, "_32x_cart", "32x,bin")); cartslot.set_must_be_loaded(true); cartslot.set_device_load(FUNC(md_cons_state::_32x_cart)); @@ -776,7 +630,7 @@ void md_cons_cd_state::genesis_scd(machine_config &config) { md_ntsc(config); - subdevice("megadriv")->screen_vblank().set(FUNC(md_cons_state::screen_vblank_console)); + m_screen->screen_vblank().set(FUNC(md_cons_cd_state::screen_vblank_console)); SEGA_SEGACD_US(config, m_segacd, 0); m_segacd->set_palette("gen_vdp:gfx_palette"); @@ -785,6 +639,8 @@ void md_cons_cd_state::genesis_scd(machine_config &config) config.set_perfect_quantum("segacd:segacd_68k"); // perfect sync to the fastest cpu + md_ctrl_ports(config); + CDROM(config, "cdrom").set_interface("scd_cdrom"); SOFTWARE_LIST(config, "cd_list").set_original("segacd"); @@ -794,7 +650,7 @@ void md_cons_cd_state::genesis2_scd(machine_config &config) { md2_ntsc(config); - subdevice("megadriv")->screen_vblank().set(FUNC(md_cons_state::screen_vblank_console)); + m_screen->screen_vblank().set(FUNC(md_cons_cd_state::screen_vblank_console)); SEGA_SEGACD_US(config, m_segacd, 0); m_segacd->set_palette("gen_vdp:gfx_palette"); @@ -803,6 +659,8 @@ void md_cons_cd_state::genesis2_scd(machine_config &config) config.set_perfect_quantum("segacd:segacd_68k"); // perfect sync to the fastest cpu + md_ctrl_ports(config); + CDROM(config, "cdrom").set_interface("scd_cdrom"); SOFTWARE_LIST(config, "cd_list").set_original("segacd"); @@ -812,7 +670,7 @@ void md_cons_cd_state::md_scd(machine_config &config) { md_pal(config); - subdevice("megadriv")->screen_vblank().set(FUNC(md_cons_state::screen_vblank_console)); + m_screen->screen_vblank().set(FUNC(md_cons_cd_state::screen_vblank_console)); SEGA_SEGACD_EUROPE(config, m_segacd, 0); m_segacd->set_palette("gen_vdp:gfx_palette"); @@ -821,6 +679,8 @@ void md_cons_cd_state::md_scd(machine_config &config) config.set_perfect_quantum("segacd:segacd_68k"); // perfect sync to the fastest cpu + md_ctrl_ports(config); + CDROM(config, "cdrom").set_interface("scd_cdrom"); SOFTWARE_LIST(config, "cd_list").set_original("megacd"); @@ -830,7 +690,7 @@ void md_cons_cd_state::md2_scd(machine_config &config) { md2_pal(config); - subdevice("megadriv")->screen_vblank().set(FUNC(md_cons_state::screen_vblank_console)); + m_screen->screen_vblank().set(FUNC(md_cons_cd_state::screen_vblank_console)); SEGA_SEGACD_EUROPE(config, m_segacd, 0); m_segacd->set_palette("gen_vdp:gfx_palette"); @@ -839,6 +699,8 @@ void md_cons_cd_state::md2_scd(machine_config &config) config.set_perfect_quantum("segacd:segacd_68k"); // perfect sync to the fastest cpu + md_ctrl_ports(config); + CDROM(config, "cdrom").set_interface("scd_cdrom"); SOFTWARE_LIST(config, "cd_list").set_original("megacd"); @@ -848,7 +710,7 @@ void md_cons_cd_state::mdj_scd(machine_config &config) { md_ntsc(config); - subdevice("megadriv")->screen_vblank().set(FUNC(md_cons_state::screen_vblank_console)); + m_screen->screen_vblank().set(FUNC(md_cons_cd_state::screen_vblank_console)); SEGA_SEGACD_JAPAN(config, m_segacd, 0); m_segacd->set_palette("gen_vdp:gfx_palette"); @@ -857,6 +719,8 @@ void md_cons_cd_state::mdj_scd(machine_config &config) config.set_perfect_quantum("segacd:segacd_68k"); // perfect sync to the fastest cpu + md_ctrl_ports(config); + CDROM(config, "cdrom").set_interface("scd_cdrom"); SOFTWARE_LIST(config, "cd_list").set_original("megacdj"); @@ -866,7 +730,7 @@ void md_cons_cd_state::md2j_scd(machine_config &config) { md2_ntsc(config); - subdevice("megadriv")->screen_vblank().set(FUNC(md_cons_state::screen_vblank_console)); + m_screen->screen_vblank().set(FUNC(md_cons_cd_state::screen_vblank_console)); SEGA_SEGACD_JAPAN(config, m_segacd, 0); m_segacd->set_palette("gen_vdp:gfx_palette"); @@ -875,6 +739,8 @@ void md_cons_cd_state::md2j_scd(machine_config &config) config.set_perfect_quantum("segacd:segacd_68k"); // perfect sync to the fastest cpu + md_ctrl_ports(config); + CDROM(config, "cdrom").set_interface("scd_cdrom"); SOFTWARE_LIST(config, "cd_list").set_original("megacdj"); @@ -896,7 +762,7 @@ void md_cons_cd_state::genesis_32x_scd(machine_config &config) CDROM(config, "cdrom").set_interface("scd_cdrom"); config.device_remove("cartslot"); - GENERIC_CARTSLOT(config, "cartslot", generic_plain_slot, "_32x_cart", "32x,bin").set_device_load(FUNC(md_cons_state::_32x_cart)); + GENERIC_CARTSLOT(config, "cartslot", generic_plain_slot, "_32x_cart", "32x,bin").set_device_load(FUNC(md_cons_cd_state::_32x_cart)); //config.m_perfect_cpu_quantum = subtag("32x_master_sh2"); SOFTWARE_LIST(config, "cd_list").set_original("segacd"); @@ -916,7 +782,7 @@ void md_cons_cd_state::md_32x_scd(machine_config &config) CDROM(config, "cdrom").set_interface("scd_cdrom"); config.device_remove("cartslot"); - GENERIC_CARTSLOT(config, "cartslot", generic_plain_slot, "_32x_cart", "32x,bin").set_device_load(FUNC(md_cons_state::_32x_cart)); + GENERIC_CARTSLOT(config, "cartslot", generic_plain_slot, "_32x_cart", "32x,bin").set_device_load(FUNC(md_cons_cd_state::_32x_cart)); //config.m_perfect_cpu_quantum = subtag("32x_master_sh2"); SOFTWARE_LIST(config, "cd_list").set_original("megacd"); @@ -936,7 +802,7 @@ void md_cons_cd_state::mdj_32x_scd(machine_config &config) CDROM(config, "cdrom").set_interface("scd_cdrom"); config.device_remove("cartslot"); - GENERIC_CARTSLOT(config, "cartslot", generic_plain_slot, "_32x_cart", "32x,bin").set_device_load(FUNC(md_cons_state::_32x_cart)); + GENERIC_CARTSLOT(config, "cartslot", generic_plain_slot, "_32x_cart", "32x,bin").set_device_load(FUNC(md_cons_cd_state::_32x_cart)); //config.m_perfect_cpu_quantum = subtag("32x_master_sh2"); SOFTWARE_LIST(config, "cd_list").set_original("megacdj"); @@ -1193,7 +1059,7 @@ CONS( 1994, 32x_mcdj, 32x_scd, 0, mdj_32x_scd, md, md_cons_c CONS( 1995, gen_nomd, 0, 0, ms_megadriv2, gen_nomd, md_cons_slot_state, init_genesis, "Sega", "Genesis Nomad (USA Genesis handheld)", MACHINE_SUPPORTS_SAVE ) // handheld without LCD -CONS( 1993, megajet, gen_nomd, 0, ms_megadriv2, megajet, md_cons_slot_state, init_md_jpn, "Sega", "Mega Jet (Japan Mega Drive handheld)", MACHINE_SUPPORTS_SAVE ) +CONS( 1993, megajet, gen_nomd, 0, ms_megajet, md, md_cons_slot_state, init_md_jpn, "Sega", "Mega Jet (Japan Mega Drive handheld)", MACHINE_SUPPORTS_SAVE ) // LaserActive (Laserdisc Player(ex: CLD-A100) with 'Control Pack' Addon slot) // Mega Drive Pack(PAC-S1)/Genesis Pack(PAC-S10) plugged into the Control Pack slot, for plays Mega Drive/Genesis Cartridge, Mega-CD/Sega CD, Mega-LD stuffs diff --git a/src/mame/sega/mdconsole.h b/src/mame/sega/mdconsole.h index 1290be529d5..69cb0a9c52d 100644 --- a/src/mame/sega/mdconsole.h +++ b/src/mame/sega/mdconsole.h @@ -12,6 +12,7 @@ #include "bus/megadrive/md_slot.h" #include "bus/megadrive/md_carts.h" +#include "bus/sms_ctrl/smsctrl.h" class md_cons_state : public md_base_state @@ -22,50 +23,55 @@ public: m_32x(*this,"sega32x"), m_segacd(*this,"segacd"), m_cart(*this, "mdslot"), - m_tmss(*this, "tmss") + m_tmss(*this, "tmss"), + m_ctrl_ports(*this, "ctrl%u", 1U) { } - ioport_port *m_io_ctrlr = nullptr; - ioport_port *m_io_pad3b[4]{}; - ioport_port *m_io_pad6b[2][4]{}; - - optional_device m_32x; - optional_device m_segacd; - optional_device m_cart; - optional_region_ptr m_tmss; - void init_mess_md_common(); void init_genesis(); void init_md_eur(); void init_md_jpn(); - uint8_t mess_md_io_read_data_port(offs_t offset); - void mess_md_io_write_data_port(offs_t offset, uint16_t data); + void md_32x(machine_config &config); + void genesis_32x(machine_config &config); + void mdj_32x(machine_config &config); + void dcat16_megadriv(machine_config &config); + +protected: + virtual void machine_start() override; + virtual void machine_reset() override; DECLARE_WRITE_LINE_MEMBER(screen_vblank_console); DECLARE_DEVICE_IMAGE_LOAD_MEMBER( _32x_cart ); + void install_cartslot(); + void install_tmss(); + + optional_device m_32x; + optional_device m_segacd; + optional_device m_cart; + optional_region_ptr m_tmss; + optional_device_array m_ctrl_ports; + + void md_ctrl_ports(machine_config &config); + +private: + uint8_t mess_md_io_read_data_port(offs_t offset); + void mess_md_io_write_data_port(offs_t offset, uint16_t data); + void _32x_scanline_callback(int x, uint32_t priority, uint32_t &lineptr); void _32x_interrupt_callback(int scanline, int irq6); void _32x_scanline_helper_callback(int scanline); - void install_cartslot(); - void install_tmss(); uint16_t tmss_r(offs_t offset); void tmss_swap_w(uint16_t data); void dcat16_megadriv_base(machine_config &config); - void dcat16_megadriv(machine_config &config); - - void md_32x(machine_config &config); - void genesis_32x(machine_config &config); - void mdj_32x(machine_config &config); -protected: - virtual void machine_start() override; - virtual void machine_reset() override; + uint8_t m_io_ctrl_th_in[2]; }; + class md_cons_slot_state : public md_cons_state { public: @@ -76,6 +82,7 @@ public: void ms_megadpal(machine_config &config); void ms_megadriv(machine_config &config); void ms_megadriv2(machine_config &config); + void ms_megajet(machine_config &config); void genesis_tmss(machine_config &config); @@ -84,6 +91,7 @@ protected: virtual void machine_start() override; }; + class md_cons_cd_state : public md_cons_state { public: diff --git a/src/mame/sega/megadriv.cpp b/src/mame/sega/megadriv.cpp index 80a238bf9b9..8256ea437da 100644 --- a/src/mame/sega/megadriv.cpp +++ b/src/mame/sega/megadriv.cpp @@ -170,61 +170,41 @@ INPUT_PORTS_START( megadriv ) PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_SERVICE1 ) PORT_NAME("Reset Button") PORT_IMPULSE(1) // reset, resets 68k (and..?) INPUT_PORTS_END -INPUT_PORTS_START( megadri6 ) - PORT_INCLUDE( megadriv ) - - PORT_START("EXTRA1") /* Extra buttons for Joypad 1 (6 button + start + mode) NOT READ DIRECTLY */ - PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_BUTTON7 ) PORT_PLAYER(1) PORT_NAME("P1 Z") // z - PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_PLAYER(1) PORT_NAME("P1 Y") // y - PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_PLAYER(1) PORT_NAME("P1 X") // x - PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_BUTTON8 ) PORT_PLAYER(1) PORT_NAME("P1 MODE") // mode - - PORT_START("EXTRA2") /* Extra buttons for Joypad 2 (6 button + start + mode) NOT READ DIRECTLY */ - PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_BUTTON7 ) PORT_PLAYER(2) PORT_NAME("P2 Z") // z - PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_PLAYER(2) PORT_NAME("P2 Y") // y - PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_PLAYER(2) PORT_NAME("P2 X") // x - PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_BUTTON8 ) PORT_PLAYER(2) PORT_NAME("P2 MODE") // mode -INPUT_PORTS_END - void md_base_state::megadrive_reset_io() { - int i; - - m_megadrive_io_data_regs[0] = 0x7f; - m_megadrive_io_data_regs[1] = 0x7f; - m_megadrive_io_data_regs[2] = 0x7f; - m_megadrive_io_ctrl_regs[0] = 0x00; - m_megadrive_io_ctrl_regs[1] = 0x00; - m_megadrive_io_ctrl_regs[2] = 0x00; - m_megadrive_io_tx_regs[0] = 0xff; - m_megadrive_io_tx_regs[1] = 0xff; - m_megadrive_io_tx_regs[2] = 0xff; - - for (i=0; i<3; i++) - { + m_io_data_regs[0] = 0x7f; + m_io_data_regs[1] = 0x7f; + m_io_data_regs[2] = 0x7f; + m_io_ctrl_regs[0] = 0x00; + m_io_ctrl_regs[1] = 0x00; + m_io_ctrl_regs[2] = 0x00; + m_io_tx_regs[0] = 0xff; + m_io_tx_regs[1] = 0xff; + m_io_tx_regs[2] = 0xff; + + for (int i = 0; i < 3; i++) m_io_stage[i] = -1; - } } /************* 6 buttons version **************************/ uint8_t md_base_state::megadrive_io_read_data_port_6button(offs_t offset) { int portnum = offset; - uint8_t retdata, helper = (m_megadrive_io_ctrl_regs[portnum] & 0x3f) | 0xc0; // bits 6 & 7 always come from m_megadrive_io_data_regs + uint8_t retdata, helper = (m_io_ctrl_regs[portnum] & 0x3f) | 0xc0; // bits 6 & 7 always come from m_io_data_regs - if (m_megadrive_io_data_regs[portnum] & 0x40) + if (m_io_data_regs[portnum] & 0x40) { if (m_io_stage[portnum] == 2) { /* here we read B, C & the additional buttons */ - retdata = (m_megadrive_io_data_regs[portnum] & helper) | + retdata = (m_io_data_regs[portnum] & helper) | ((((m_io_pad_3b[portnum] ? m_io_pad_3b[portnum]->read() : 0) & 0x30) | ((m_io_pad_6b[portnum] ? m_io_pad_6b[portnum]->read() : 0) & 0x0f)) & ~helper); } else { /* here we read B, C & the directional buttons */ - retdata = (m_megadrive_io_data_regs[portnum] & helper) | + retdata = (m_io_data_regs[portnum] & helper) | (((m_io_pad_3b[portnum] ? m_io_pad_3b[portnum]->read() : 0) & 0x3f) & ~helper); } } @@ -233,19 +213,19 @@ uint8_t md_base_state::megadrive_io_read_data_port_6button(offs_t offset) if (m_io_stage[portnum] == 1) { /* here we read ((Start & A) >> 2) | 0x00 */ - retdata = (m_megadrive_io_data_regs[portnum] & helper) | + retdata = (m_io_data_regs[portnum] & helper) | ((((m_io_pad_3b[portnum] ? m_io_pad_3b[portnum]->read() : 0) & 0xc0) >> 2) & ~helper); } else if (m_io_stage[portnum]==2) { /* here we read ((Start & A) >> 2) | 0x0f */ - retdata = (m_megadrive_io_data_regs[portnum] & helper) | + retdata = (m_io_data_regs[portnum] & helper) | (((((m_io_pad_3b[portnum] ? m_io_pad_3b[portnum]->read() : 0) & 0xc0) >> 2) | 0x0f) & ~helper); } else { /* here we read ((Start & A) >> 2) | Up and Down */ - retdata = (m_megadrive_io_data_regs[portnum] & helper) | + retdata = (m_io_data_regs[portnum] & helper) | (((((m_io_pad_3b[portnum] ? m_io_pad_3b[portnum]->read() : 0) & 0xc0) >> 2) | ((m_io_pad_3b[portnum] ? m_io_pad_3b[portnum]->read() : 0) & 0x03)) & ~helper); } @@ -261,18 +241,18 @@ uint8_t md_base_state::megadrive_io_read_data_port_6button(offs_t offset) uint8_t md_base_state::megadrive_io_read_data_port_3button(offs_t offset) { int portnum = offset; - uint8_t retdata, helper = (m_megadrive_io_ctrl_regs[portnum] & 0x7f) | 0x80; // bit 7 always comes from m_megadrive_io_data_regs + uint8_t retdata, helper = (m_io_ctrl_regs[portnum] & 0x7f) | 0x80; // bit 7 always comes from m_io_data_regs - if (m_megadrive_io_data_regs[portnum] & 0x40) + if (m_io_data_regs[portnum] & 0x40) { /* here we read B, C & the directional buttons */ - retdata = (m_megadrive_io_data_regs[portnum] & helper) | + retdata = (m_io_data_regs[portnum] & helper) | ((((m_io_pad_3b[portnum] ? m_io_pad_3b[portnum]->read() : 0) & 0x3f) | 0x40) & ~helper); } else { /* here we read ((Start & A) >> 2) | Up and Down */ - retdata = (m_megadrive_io_data_regs[portnum] & helper) | + retdata = (m_io_data_regs[portnum] & helper) | (((((m_io_pad_3b[portnum] ? m_io_pad_3b[portnum]->read() : 0) & 0xc0) >> 2) | ((m_io_pad_3b[portnum] ? m_io_pad_3b[portnum]->read() : 0) & 0x03) | 0x40) & ~helper); } @@ -283,7 +263,7 @@ uint8_t md_base_state::megadrive_io_read_data_port_3button(offs_t offset) uint8_t md_base_state::megadrive_io_read_ctrl_port(int portnum) { uint8_t retdata; - retdata = m_megadrive_io_ctrl_regs[portnum]; + retdata = m_io_ctrl_regs[portnum]; //osd_printf_debug("read io ctrl port %d %02x\n",portnum,retdata); return retdata | (retdata << 8); @@ -292,7 +272,7 @@ uint8_t md_base_state::megadrive_io_read_ctrl_port(int portnum) uint8_t md_base_state::megadrive_io_read_tx_port(int portnum) { uint8_t retdata; - retdata = m_megadrive_io_tx_regs[portnum]; + retdata = m_io_tx_regs[portnum]; return retdata | (retdata << 8); } @@ -338,7 +318,7 @@ uint16_t md_base_state::megadriv_68k_io_read(offs_t offset) case 0x1: case 0x2: case 0x3: - retdata = m_megadrive_io_read_data_port_ptr(offset-1); + retdata = m_io_read_data_port_ptr(offset-1); break; case 0x4: @@ -370,7 +350,7 @@ uint16_t md_base_state::megadriv_68k_io_read(offs_t offset) void md_base_state::megadrive_io_write_data_port_3button(offs_t offset, uint16_t data) { int portnum = offset; - m_megadrive_io_data_regs[portnum] = data; + m_io_data_regs[portnum] = data; //osd_printf_debug("Writing IO Data Register #%d data %04x\n",portnum,data); } @@ -381,9 +361,9 @@ void md_base_state::megadrive_io_write_data_port_3button(offs_t offset, uint16_t void md_base_state::megadrive_io_write_data_port_6button(offs_t offset, uint16_t data) { int portnum = offset; - if (m_megadrive_io_ctrl_regs[portnum]&0x40) + if (m_io_ctrl_regs[portnum]&0x40) { - if (((m_megadrive_io_data_regs[portnum]&0x40)==0x00) && ((data&0x40) == 0x40)) + if (((m_io_data_regs[portnum]&0x40)==0x00) && ((data&0x40) == 0x40)) { m_io_stage[portnum]++; m_io_timeout[portnum]->adjust(m_maincpu->cycles_to_attotime(8192), portnum); @@ -391,7 +371,7 @@ void md_base_state::megadrive_io_write_data_port_6button(offs_t offset, uint16_t } - m_megadrive_io_data_regs[portnum] = data; + m_io_data_regs[portnum] = data; //osd_printf_debug("Writing IO Data Register #%d data %04x\n",portnum,data); } @@ -401,13 +381,13 @@ void md_base_state::megadrive_io_write_data_port_6button(offs_t offset, uint16_t void md_base_state::megadrive_io_write_ctrl_port(int portnum, uint16_t data) { - m_megadrive_io_ctrl_regs[portnum] = data; + m_io_ctrl_regs[portnum] = data; // osd_printf_debug("Setting IO Control Register #%d data %04x\n",portnum,data); } void md_base_state::megadrive_io_write_tx_port(int portnum, uint16_t data) { - m_megadrive_io_tx_regs[portnum] = data; + m_io_tx_regs[portnum] = data; } void md_base_state::megadrive_io_write_rx_port(int portnum, uint16_t data) @@ -435,7 +415,7 @@ void md_base_state::megadriv_68k_io_write(offs_t offset, uint16_t data, uint16_t case 0x1: case 0x2: case 0x3: - m_megadrive_io_write_data_port_ptr(offset-1,data); + m_io_write_data_port_ptr(offset-1,data); break; case 0x4: @@ -821,9 +801,9 @@ void md_base_state::machine_start() m_io_pad_3b[3] = ioport("UNK"); save_item(NAME(m_io_stage)); - save_item(NAME(m_megadrive_io_data_regs)); - save_item(NAME(m_megadrive_io_ctrl_regs)); - save_item(NAME(m_megadrive_io_tx_regs)); + save_item(NAME(m_io_data_regs)); + save_item(NAME(m_io_ctrl_regs)); + save_item(NAME(m_io_tx_regs)); if (m_z80snd) m_genz80.z80_run_timer = timer_alloc(FUNC(md_base_state::megadriv_z80_run_state), this); @@ -1048,8 +1028,8 @@ void md_base_state::megadriv_init_common() m_maincpu->set_tas_write_callback(*this, FUNC(md_base_state::megadriv_tas_callback)); - m_megadrive_io_read_data_port_ptr = read8sm_delegate(*this, FUNC(md_base_state::megadrive_io_read_data_port_3button)); - m_megadrive_io_write_data_port_ptr = write16sm_delegate(*this, FUNC(md_base_state::megadrive_io_write_data_port_3button)); + m_io_read_data_port_ptr = read8sm_delegate(*this, FUNC(md_base_state::megadrive_io_read_data_port_3button)); + m_io_write_data_port_ptr = write16sm_delegate(*this, FUNC(md_base_state::megadrive_io_write_data_port_3button)); } void md_base_state::init_megadriv() diff --git a/src/mame/sega/megadriv.h b/src/mame/sega/megadriv.h index eb95bc8eedc..be48ac8f3a5 100644 --- a/src/mame/sega/megadriv.h +++ b/src/mame/sega/megadriv.h @@ -21,9 +21,6 @@ INPUT_PORTS_EXTERN( md_common ); INPUT_PORTS_EXTERN( megadriv ); -INPUT_PORTS_EXTERN( megadri6 ); -INPUT_PORTS_EXTERN( ssf2mdb ); -INPUT_PORTS_EXTERN( mk3mdb ); class md_base_state : public driver_device @@ -39,8 +36,8 @@ public: m_megadrive_ram(*this,"megadrive_ram"), m_screen(*this,"megadriv"), m_io_reset(*this, "RESET"), - m_megadrive_io_read_data_port_ptr(*this), - m_megadrive_io_write_data_port_ptr(*this) + m_io_read_data_port_ptr(*this), + m_io_write_data_port_ptr(*this) { } required_device m_maincpu; @@ -96,11 +93,11 @@ public: /* Megadrive / Genesis has 3 I/O ports */ emu_timer *m_io_timeout[3]; int m_io_stage[3]; - uint8_t m_megadrive_io_data_regs[3]; - uint8_t m_megadrive_io_ctrl_regs[3]; - uint8_t m_megadrive_io_tx_regs[3]; - read8sm_delegate m_megadrive_io_read_data_port_ptr; - write16sm_delegate m_megadrive_io_write_data_port_ptr; + uint8_t m_io_data_regs[3]; + uint8_t m_io_ctrl_regs[3]; + uint8_t m_io_tx_regs[3]; + read8sm_delegate m_io_read_data_port_ptr; + write16sm_delegate m_io_write_data_port_ptr; WRITE_LINE_MEMBER(vdp_sndirqline_callback_genesis_z80); WRITE_LINE_MEMBER(vdp_lv6irqline_callback_genesis_68k); diff --git a/src/mame/sega/megadriv_acbl.cpp b/src/mame/sega/megadriv_acbl.cpp index f39e45ec68e..f8fb3636757 100644 --- a/src/mame/sega/megadriv_acbl.cpp +++ b/src/mame/sega/megadriv_acbl.cpp @@ -1209,8 +1209,8 @@ void md_boot_state::init_mk3mdb() init_megadriv(); // 6 button game, so overwrite 3 button io handlers - m_megadrive_io_read_data_port_ptr = read8sm_delegate(*this, FUNC(md_base_state::megadrive_io_read_data_port_6button)); - m_megadrive_io_write_data_port_ptr = write16sm_delegate(*this, FUNC(md_base_state::megadrive_io_write_data_port_6button)); + m_io_read_data_port_ptr = read8sm_delegate(*this, FUNC(md_base_state::megadrive_io_read_data_port_6button)); + m_io_write_data_port_ptr = write16sm_delegate(*this, FUNC(md_base_state::megadrive_io_write_data_port_6button)); } void md_boot_state::init_ssf2mdb() @@ -1222,8 +1222,8 @@ void md_boot_state::init_ssf2mdb() init_megadrij(); // 6 button game, so overwrite 3 button io handlers - m_megadrive_io_read_data_port_ptr = read8sm_delegate(*this, FUNC(md_base_state::megadrive_io_read_data_port_6button)); - m_megadrive_io_write_data_port_ptr = write16sm_delegate(*this, FUNC(md_base_state::megadrive_io_write_data_port_6button)); + m_io_read_data_port_ptr = read8sm_delegate(*this, FUNC(md_base_state::megadrive_io_read_data_port_6button)); + m_io_write_data_port_ptr = write16sm_delegate(*this, FUNC(md_base_state::megadrive_io_write_data_port_6button)); } void md_boot_state::init_srmdb() diff --git a/src/mame/sega/megadriv_rad.cpp b/src/mame/sega/megadriv_rad.cpp index 466579f86ec..677a71a4fbe 100644 --- a/src/mame/sega/megadriv_rad.cpp +++ b/src/mame/sega/megadriv_rad.cpp @@ -552,16 +552,16 @@ void megadriv_radica_6button_state::init_megadriv_radica_6button_pal() { init_megadrie(); // 6 button game, so overwrite 3 button io handlers - m_megadrive_io_read_data_port_ptr = read8sm_delegate(*this, FUNC(md_base_state::megadrive_io_read_data_port_6button)); - m_megadrive_io_write_data_port_ptr = write16sm_delegate(*this, FUNC(md_base_state::megadrive_io_write_data_port_6button)); + m_io_read_data_port_ptr = read8sm_delegate(*this, FUNC(md_base_state::megadrive_io_read_data_port_6button)); + m_io_write_data_port_ptr = write16sm_delegate(*this, FUNC(md_base_state::megadrive_io_write_data_port_6button)); } void megadriv_radica_6button_state::init_megadriv_radica_6button_ntsc() { init_megadriv(); // 6 button game, so overwrite 3 button io handlers - m_megadrive_io_read_data_port_ptr = read8sm_delegate(*this, FUNC(md_base_state::megadrive_io_read_data_port_6button)); - m_megadrive_io_write_data_port_ptr = write16sm_delegate(*this, FUNC(md_base_state::megadrive_io_write_data_port_6button)); + m_io_read_data_port_ptr = read8sm_delegate(*this, FUNC(md_base_state::megadrive_io_read_data_port_6button)); + m_io_write_data_port_ptr = write16sm_delegate(*this, FUNC(md_base_state::megadrive_io_write_data_port_6button)); } void megadriv_dgunl_state::init_dgunl3227() @@ -647,8 +647,8 @@ void megadriv_ra145_state::init_ra145() m_romsize = 0x8000000; init_megadriv(); // 6 button game, so overwrite 3 button io handlers - m_megadrive_io_read_data_port_ptr = read8sm_delegate(*this, FUNC(md_base_state::megadrive_io_read_data_port_6button)); - m_megadrive_io_write_data_port_ptr = write16sm_delegate(*this, FUNC(md_base_state::megadrive_io_write_data_port_6button)); + m_io_read_data_port_ptr = read8sm_delegate(*this, FUNC(md_base_state::megadrive_io_read_data_port_6button)); + m_io_write_data_port_ptr = write16sm_delegate(*this, FUNC(md_base_state::megadrive_io_write_data_port_6button)); } // US versions show 'Genesis' on the menu, show a www.radicagames.com splash screen, and use NTSC versions of the ROMs, sometimes region locked diff --git a/src/mame/sega/megaplay.cpp b/src/mame/sega/megaplay.cpp index 6a435523093..354090c231c 100644 --- a/src/mame/sega/megaplay.cpp +++ b/src/mame/sega/megaplay.cpp @@ -428,7 +428,7 @@ void mplay_state::bios_gamesel_w(uint8_t data) void mplay_state::mp_io_write(offs_t offset, uint16_t data) { if (offset == 0x03) - m_megadrive_io_data_regs[2] = (data & m_megadrive_io_ctrl_regs[2]) | (m_megadrive_io_data_regs[2] & ~m_megadrive_io_ctrl_regs[2]); + m_io_data_regs[2] = (data & m_io_ctrl_regs[2]) | (m_io_data_regs[2] & ~m_io_ctrl_regs[2]); else megadriv_68k_io_write(offset & 0x1f, data); } @@ -436,7 +436,7 @@ void mplay_state::mp_io_write(offs_t offset, uint16_t data) uint16_t mplay_state::mp_io_read(offs_t offset) { if (offset == 0x03) - return m_megadrive_io_data_regs[2]; + return m_io_data_regs[2]; else return megadriv_68k_io_read(offset & 0x1f); } @@ -504,25 +504,25 @@ void mplay_state::bank_w(offs_t offset, uint8_t data) uint8_t mplay_state::bios_6402_r() { - return m_megadrive_io_data_regs[2];// & 0xfe; + return m_io_data_regs[2];// & 0xfe; } void mplay_state::bios_6402_w(uint8_t data) { - m_megadrive_io_data_regs[2] = (m_megadrive_io_data_regs[2] & 0x07) | ((data & 0x70) >> 1); + m_io_data_regs[2] = (m_io_data_regs[2] & 0x07) | ((data & 0x70) >> 1); // logerror("BIOS: 0x6402 write: 0x%02x\n", data); } uint8_t mplay_state::bios_6204_r() { - return m_megadrive_io_data_regs[2]; + return m_io_data_regs[2]; // return (m_bios_width & 0xf8) + (m_bios_6204 & 0x07); } void mplay_state::bios_width_w(uint8_t data) { m_bios_width = data; - m_megadrive_io_data_regs[2] = (m_megadrive_io_data_regs[2] & 0x07) | ((data & 0xf8)); + m_io_data_regs[2] = (m_io_data_regs[2] & 0x07) | ((data & 0xf8)); // logerror("BIOS: 0x6204 - Width write: %02x\n", data); } @@ -963,8 +963,8 @@ void mplay_state::init_megaplay() m_ic37_ram = std::make_unique(0x10000); init_megadrij(); - m_megadrive_io_read_data_port_ptr = read8sm_delegate(*this, FUNC(md_base_state::megadrive_io_read_data_port_3button)); - m_megadrive_io_write_data_port_ptr = write16sm_delegate(*this, FUNC(md_base_state::megadrive_io_write_data_port_3button)); + m_io_read_data_port_ptr = read8sm_delegate(*this, FUNC(md_base_state::megadrive_io_read_data_port_3button)); + m_io_write_data_port_ptr = write16sm_delegate(*this, FUNC(md_base_state::megadrive_io_write_data_port_3button)); // for now ... m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0xa10000, 0xa1001f, read16sm_delegate(*this, FUNC(mplay_state::mp_io_read)), write16sm_delegate(*this, FUNC(mplay_state::mp_io_write))); diff --git a/src/mame/sega/shtzone.cpp b/src/mame/sega/shtzone.cpp index d7f496fac84..973b36d8611 100644 --- a/src/mame/sega/shtzone.cpp +++ b/src/mame/sega/shtzone.cpp @@ -59,9 +59,11 @@ TODO: #include "emu.h" #include "sms.h" + #include "cpu/z80/z80.h" #include "machine/nvram.h" #include "sound/beep.h" + #include "emupal.h" #include "screen.h" #include "speaker.h" @@ -72,13 +74,13 @@ namespace { class shtzone_state : public sms_state { public: - shtzone_state(const machine_config &mconfig, device_type type, const char *tag) - : sms_state(mconfig, type, tag), + shtzone_state(const machine_config &mconfig, device_type type, const char *tag) : + sms_state(mconfig, type, tag), m_timercpu(*this, "timercpu"), m_buzzer(*this, "buzzer"), m_slots(*this, {"slot", "slot2", "slot3", "slot4", "slot5"}), m_led(*this, "led") - { } + { } void shtzone(machine_config &config); @@ -354,7 +356,7 @@ ROM_START( shtzone ) ROM_FILL(0x0000, 0x4000, 0xff) ROM_END -} // Anonymous namespace +} // anonymous namespace GAME( 1987, shtzone, 0, shtzone, shtzone, shtzone_state, empty_init, ROT0, "Sega", "Shooting Zone System BIOS", MACHINE_NOT_WORKING | MACHINE_IS_BIOS_ROOT ) diff --git a/src/mame/sega/sms.cpp b/src/mame/sega/sms.cpp index 29a65c3c4b2..6c091f0935d 100644 --- a/src/mame/sega/sms.cpp +++ b/src/mame/sega/sms.cpp @@ -245,6 +245,7 @@ DC00 - Selection buttons #2, 9-16 (R) #include "emu.h" #include "sms.h" +#include "bus/sms_ctrl/controllers.h" #include "cpu/z80/z80.h" #include "softlist_dev.h" #include "speaker.h" @@ -494,25 +495,25 @@ INPUT_PORTS_END void sms_state::sms_base(machine_config &config) { - /* basic machine hardware */ SPEAKER(config, "mono").front_center(); SMS_CART_SLOT(config, "slot", sms_cart, nullptr); SOFTWARE_LIST(config, "cart_list").set_original("sms"); - SMS_CONTROL_PORT(config, m_port_ctrl1, sms_control_port_devices, "joypad"); - m_port_ctrl1->set_screen_tag(m_main_scr); - m_port_ctrl1->th_input_handler().set(FUNC(sms_state::sms_ctrl1_th_input)); + SMS_CONTROL_PORT(config, m_port_ctrl1, sms_control_port_devices, SMS_CTRL_OPTION_JOYPAD); + m_port_ctrl1->set_screen(m_main_scr); + m_port_ctrl1->th_handler().set(FUNC(sms_state::sms_ctrl1_th_input)); - SMS_CONTROL_PORT(config, m_port_ctrl2, sms_control_port_devices, "joypad"); - m_port_ctrl2->set_screen_tag(m_main_scr); - m_port_ctrl2->th_input_handler().set(FUNC(sms_state::sms_ctrl2_th_input)); + SMS_CONTROL_PORT(config, m_port_ctrl2, sms_control_port_devices, SMS_CTRL_OPTION_JOYPAD); + m_port_ctrl2->set_screen(m_main_scr); + m_port_ctrl2->th_handler().set(FUNC(sms_state::sms_ctrl2_th_input)); } void sms_state::sms_ntsc_base(machine_config &config) { sms_base(config); + Z80(config, m_maincpu, XTAL(10'738'635)/3); m_maincpu->set_addrmap(AS_PROGRAM, &sms_state::sms_mem); m_maincpu->set_addrmap(AS_IO, &sms_state::sms_io); @@ -937,8 +938,8 @@ void sms1_state::sg1000m3(machine_config &config) SOFTWARE_LIST(config, "cart_list2").set_original("sg1000"); // Mark III does not have TH connected. - m_port_ctrl1->th_input_handler().set_nop(); - m_port_ctrl2->th_input_handler().set_nop(); + m_port_ctrl1->th_handler().set_nop(); + m_port_ctrl2->th_handler().set_nop(); m_has_bios_full = false; m_is_mark_iii = true; diff --git a/src/mame/sega/sms.h b/src/mame/sega/sms.h index 93ea36645b8..e3d2b204f96 100644 --- a/src/mame/sega/sms.h +++ b/src/mame/sega/sms.h @@ -2,35 +2,28 @@ // copyright-holders:Wilbert Pol, Charles MacDonald,Mathis Rosenhauer,Brad Oliver,Michael Luong,Fabio Priuli,Enik Land /***************************************************************************** * - * includes/sms.h + * sega/sms.h * ****************************************************************************/ - #ifndef MAME_INCLUDES_SMS_H #define MAME_INCLUDES_SMS_H -#define LOG_REG -#define LOG_PAGING -#define LOG_COLOR - -#define NVRAM_SIZE (0x08000) -#define CPU_ADDRESSABLE_SIZE (0x10000) - -#define MAX_CARTRIDGES 16 - -#define CONTROL1_TAG "ctrl1" -#define CONTROL2_TAG "ctrl2" +#pragma once #include "bus/gamegear/ggext.h" #include "bus/sega8/sega8_slot.h" #include "bus/sg1000_exp/sg1000exp.h" #include "bus/sms_ctrl/smsctrl.h" #include "bus/sms_exp/smsexp.h" +#include "machine/timer.h" #include "sound/ymopl.h" #include "video/315_5124.h" #include "screen.h" -#include "machine/timer.h" + +#define LOG_REG +#define LOG_PAGING +#define LOG_COLOR class sms_state : public driver_device @@ -42,8 +35,8 @@ public: m_vdp(*this, "sms_vdp"), m_main_scr(*this, "screen"), m_ym(*this, "ym2413"), - m_port_ctrl1(*this, CONTROL1_TAG), - m_port_ctrl2(*this, CONTROL2_TAG), + m_port_ctrl1(*this, "ctrl1"), + m_port_ctrl2(*this, "ctrl2"), m_port_gg_ext(*this, "ext"), m_port_gg_dc(*this, "GG_PORT_DC"), m_port_pause(*this, "PAUSE"), diff --git a/src/mame/sega/sms_m.cpp b/src/mame/sega/sms_m.cpp index c57547d7fab..6c57c77f155 100644 --- a/src/mame/sega/sms_m.cpp +++ b/src/mame/sega/sms_m.cpp @@ -1,14 +1,11 @@ // license:BSD-3-Clause // copyright-holders:Wilbert Pol, Charles MacDonald,Mathis Rosenhauer,Brad Oliver,Michael Luong,Fabio Priuli,Enik Land #include "emu.h" -#include "crsshair.h" -#include "cpu/z80/z80.h" -#include "video/315_5124.h" -#include "sound/ymopl.h" #include "sms.h" -#define VERBOSE 0 -#define LOG(x) do { if (VERBOSE) logerror x; } while (0) +#include "cpu/z80/z80.h" + +#include "crsshair.h" #define ENABLE_NONE 0x00 #define ENABLE_EXPANSION 0x01 @@ -26,8 +23,7 @@ TIMER_CALLBACK_MEMBER(sms_state::lphaser_th_generate) void sms_state::lphaser_hcount_latch() { - /* A delay seems to occur when the Light Phaser latches the - VDP hcount, then an offset is added here to the hpos. */ + // A delay seems to occur when the Light Phaser latches the VDP hcount, then an offset is added here to the hpos. m_lphaser_th_timer->adjust(m_main_scr->time_until_pos(m_main_scr->vpos(), m_main_scr->hpos() + m_lphaser_x_offs)); } @@ -37,18 +33,18 @@ WRITE_LINE_MEMBER(sms_state::sms_ctrl1_th_input) // Check if TH of controller port 1 is set to input (1) if (m_io_ctrl_reg & 0x02) { - if (state == 0) + if (!state) { m_ctrl1_th_latch = 1; } else { // State is 1. If changed from 0, hcount is latched. - if (m_ctrl1_th_state == 0) + if (!m_ctrl1_th_state) lphaser_hcount_latch(); } - m_ctrl1_th_state = state; } + m_ctrl1_th_state = state; } @@ -57,18 +53,18 @@ WRITE_LINE_MEMBER(sms_state::sms_ctrl2_th_input) // Check if TH of controller port 2 is set to input (1) if (m_io_ctrl_reg & 0x08) { - if (state == 0) + if (!state) { m_ctrl2_th_latch = 1; } else { // State is 1. If changed from 0, hcount is latched. - if (m_ctrl2_th_state == 0) + if (!m_ctrl2_th_state) lphaser_hcount_latch(); } - m_ctrl2_th_state = state; } + m_ctrl2_th_state = state; } @@ -84,7 +80,6 @@ WRITE_LINE_MEMBER(gamegear_state::gg_ext_th_input) void sms_state::sms_get_inputs() { - uint8_t data1 = 0xff; uint8_t data2 = 0xff; m_port_dc_reg = 0xff; @@ -96,43 +91,36 @@ void sms_state::sms_get_inputs() if (m_is_gamegear) { + // FIXME: make the Game Gear EXT port sane - it's more like a Mega Drive port + // For Game Gear, this function is used only if SMS mode is // enabled, else only register $dc receives input data, through // direct read of the m_port_gg_dc I/O port. - data1 = m_port_gg_dc->read(); + uint8_t data1 = m_port_gg_dc->read(); m_port_dc_reg &= ~0x03f | data1; data2 = m_port_gg_ext->port_r(); + m_ctrl2_th_state = BIT(data2, 6); + data2 = bitswap<6>(data2, 7, 5, 3, 2, 1, 0); } else { - data1 = m_port_ctrl1->port_r(); - m_port_dc_reg &= ~0x0f | data1; // Up, Down, Left, Right - m_port_dc_reg &= ~0x10 | (data1 >> 1); // TL (Button 1) - m_port_dc_reg &= ~0x20 | (data1 >> 2); // TR (Button 2) + m_port_dc_reg &= ~0x3f | m_port_ctrl1->in_r(); // Up, Down, Left, Right, TL, TR - data2 = m_port_ctrl2->port_r(); + data2 = m_port_ctrl2->in_r(); } m_port_dc_reg &= ~0xc0 | (data2 << 6); // Up, Down - m_port_dd_reg &= ~0x03 | (data2 >> 2); // Left, Right - m_port_dd_reg &= ~0x04 | (data2 >> 3); // TL (Button 1) - m_port_dd_reg &= ~0x08 | (data2 >> 4); // TR (Button 2) - - if (!m_is_mark_iii) - { - m_port_dd_reg &= ~0x40 | data1; // TH ctrl1 - m_port_dd_reg &= ~0x80 | (data2 << 1); // TH ctrl2 - } + m_port_dd_reg &= ~0x0f | (data2 >> 2); // Left, Right, TL, TR + m_port_dd_reg &= ~0x40 | (m_ctrl1_th_state << 6); // TH ctrl1 + m_port_dd_reg &= ~0x80 | (m_ctrl2_th_state << 7); // TH ctrl2 } void sms_state::sms_io_control_w(uint8_t data) { bool latch_hcount = false; - uint8_t ctrl1_port_data = 0xff; - uint8_t ctrl2_port_data = 0xff; if (m_is_gamegear && !(m_cartslot->exists() && m_cartslot->get_sms_mode())) { @@ -143,58 +131,46 @@ void sms_state::sms_io_control_w(uint8_t data) // Controller Port 1: // check if TR or TH are set to output (0). - if ((data & 0x03) != 0x03) + if (!m_is_gamegear && ((data & 0x33) != (m_io_ctrl_reg & 0x33))) { - if (!(data & 0x01)) // TR set to output - { - ctrl1_port_data &= ~0x80 | (data << 3); - } - if (!(data & 0x02)) // TH set to output - { - ctrl1_port_data &= ~0x40 | (data << 1); - } - if (!m_is_gamegear) - m_port_ctrl1->port_w(ctrl1_port_data); + m_port_ctrl1->out_w(((BIT(data, 4, 2) | BIT(data, 0, 2)) << 5) | 0x1f, BIT(~data, 0, 2) << 5); } - // check if TH is set to input (1). - if (data & 0x02) - { - if (!m_is_gamegear) - ctrl1_port_data &= ~0x40 | m_port_ctrl1->port_r(); - // check if TH input level is high (1) and was output/low (0) - if ((ctrl1_port_data & 0x40) && !(m_io_ctrl_reg & 0x22)) + // check if TH input level is high (1) and was output/low (0) + if ((data & 0x02) && !(m_io_ctrl_reg & 0x22)) + { + if (m_is_gamegear || m_ctrl1_th_state) latch_hcount = true; } // Controller Port 2: // check if TR or TH are set to output (0). - if ((data & 0x0c) != 0x0c) + if (m_is_gamegear) { - if (!(data & 0x04)) // TR set to output + if ((data & 0x0c) != 0x0c) { - ctrl2_port_data &= ~0x80 | (data << 1); - } - if (!(data & 0x08)) // TH set to output - { - ctrl2_port_data &= ~0x40 | (data >> 1); - } - if (!m_is_gamegear) - m_port_ctrl2->port_w(ctrl2_port_data); - else + uint8_t ctrl2_port_data = 0xff; + if (!(data & 0x04)) // TR set to output + { + ctrl2_port_data &= ~0x80 | (data << 1); + } + if (!(data & 0x08)) // TH set to output + { + ctrl2_port_data &= ~0x40 | (data >> 1); + } m_port_gg_ext->port_w(ctrl2_port_data); + } } - // check if TH is set to input (1). - if (data & 0x08) + else if ((data & 0xcc) != (m_io_ctrl_reg & 0xcc)) { - if (!m_is_gamegear) - ctrl2_port_data &= ~0x40 | m_port_ctrl2->port_r(); - else - ctrl2_port_data &= ~0x40 | m_port_gg_ext->port_r(); + m_port_ctrl2->out_w(((BIT(data, 6, 2) | BIT(data, 2, 2)) << 5) | 0x1f, BIT(~data, 2, 2) << 5); + } - // check if TH input level is high (1) and was output/low (0) - if ((ctrl2_port_data & 0x40) && !(m_io_ctrl_reg & 0x88)) + // check if TH input level is high (1) and was output/low (0) + if ((data & 0x08) && !(m_io_ctrl_reg & 0x88)) + { + if (m_is_gamegear ? BIT(m_port_gg_ext->port_r(), 6) : m_ctrl2_th_state) latch_hcount = true; } @@ -398,14 +374,11 @@ uint8_t sms_state::sms_input_port_dd_r() // Check if TH of controller port 1 is set to output (0) if (!(m_io_ctrl_reg & 0x02)) { - if (m_ioctrl_region_is_japan) - { - m_port_dd_reg &= ~0x40; - } - else + m_port_dd_reg &= ~0x40; + if (!m_ioctrl_region_is_japan) { // Read TH state set through IO control port - m_port_dd_reg &= ~0x40 | ((m_io_ctrl_reg & 0x20) << 1); + m_port_dd_reg |= (m_io_ctrl_reg & 0x20) << 1; } } else // TH set to input (1) @@ -422,14 +395,11 @@ uint8_t sms_state::sms_input_port_dd_r() // Check if TH of controller port 2 is set to output (0) if (!(m_io_ctrl_reg & 0x08)) { - if (m_ioctrl_region_is_japan) - { - m_port_dd_reg &= ~0x80; - } - else + m_port_dd_reg &= ~0x80; + if (!m_ioctrl_region_is_japan) { // Read TH state set through IO control port - m_port_dd_reg &= ~0x80 | (m_io_ctrl_reg & 0x80); + m_port_dd_reg |= m_io_ctrl_reg & 0x80; } } else // TH set to input (1) @@ -1009,6 +979,9 @@ void sms_state::setup_bios() void sms_state::machine_start() { + m_ctrl1_th_state = 1; + m_ctrl2_th_state = 1; + // turn on the Power LED if (m_has_pwr_led) { @@ -1119,13 +1092,17 @@ void sms_state::machine_reset() m_led_pwr = 1; } - if (!m_is_mark_iii) + if (m_is_mark_iii) + { + // pin 7 is tied to ground on the Mark III + m_port_ctrl1->out_w(0x3f, 0x40); + m_port_ctrl2->out_w(0x3f, 0x40); + } + else { m_io_ctrl_reg = 0xff; m_ctrl1_th_latch = 0; m_ctrl2_th_latch = 0; - m_ctrl1_th_state = 1; - m_ctrl2_th_state = 1; } setup_bios(); diff --git a/src/mame/sharp/x68k.cpp b/src/mame/sharp/x68k.cpp index 0f0927f5ba9..3a63caf3837 100644 --- a/src/mame/sharp/x68k.cpp +++ b/src/mame/sharp/x68k.cpp @@ -303,242 +303,42 @@ void x68k_state::set_adpcm() m_adpcm_timer->adjust(attotime::from_ticks(rate, res_clock), 0, attotime::from_ticks(rate, res_clock)); } -// Megadrive 3 button gamepad -// According to XM6, bits 4 and 7 are always 1 (is this correct?) -// Bits 4 and 5 of PPI port C control each controller's multiplexer -// Button inputs (Start, A, B and C) are read in bits 5 and 6 (rather than 4 -// and 5 like on a Megadrive) - -uint8_t x68k_state::md_3button_r(int port) -{ - if(port == 1) - { - uint8_t porta = m_md3b->read() & 0xff; - uint8_t portb = (m_md3b->read() >> 8) & 0xff; - if(m_mdctrl.mux1 & 0x10) - { - return porta | 0x90; - } - else - { - return (portb & 0x60) | (porta & 0x03) | 0x90; - } - } - if(port == 2) - { - uint8_t porta = (m_md3b->read() >> 16) & 0xff; - uint8_t portb = (m_md3b->read() >> 24) & 0xff; - if(m_mdctrl.mux2 & 0x20) - { - return porta | 0x90; - } - else - { - return (portb & 0x60) | (porta & 0x03) | 0x90; - } - } - return 0xff; -} - -// Megadrive 6 button gamepad -TIMER_CALLBACK_MEMBER(x68k_state::md_6button_port1_timeout) -{ - m_mdctrl.seq1 = 0; -} - -TIMER_CALLBACK_MEMBER(x68k_state::md_6button_port2_timeout) -{ - m_mdctrl.seq2 = 0; -} - -void x68k_state::md_6button_init() -{ - m_mdctrl.io_timeout1 = timer_alloc(FUNC(x68k_state::md_6button_port1_timeout), this); - m_mdctrl.io_timeout2 = timer_alloc(FUNC(x68k_state::md_6button_port2_timeout), this); -} - -uint8_t x68k_state::md_6button_r(int port) -{ - if(port == 1) - { - uint8_t porta = m_md6b->read() & 0xff; - uint8_t portb = (m_md6b->read() >> 8) & 0xff; - uint8_t extra = m_md6b_extra->read() & 0x0f; - - switch(m_mdctrl.seq1) - { - case 1: - default: - if(m_mdctrl.mux1 & 0x10) - { - return porta | 0x90; - } - else - { - return (portb & 0x60) | (porta & 0x03) | 0x90; - } - case 2: - if(m_mdctrl.mux1 & 0x10) - { - return porta | 0x90; - } - else - { - return (portb & 0x60) | 0x90; - } - case 3: - if(m_mdctrl.mux1 & 0x10) - { - return (porta & 0x60) | (extra & 0x0f) | 0x90; - } - else - { - return (portb & 0x60) | 0x9f; - } - } - } - if(port == 2) - { - uint8_t porta = (m_md6b->read() >> 16) & 0xff; - uint8_t portb = (m_md6b->read() >> 24) & 0xff; - uint8_t extra = (m_md6b_extra->read() >> 4) & 0x0f; - - switch(m_mdctrl.seq2) - { - case 1: - default: - if(m_mdctrl.mux2 & 0x20) - { - return porta | 0x90; - } - else - { - return (portb & 0x60) | (porta & 0x03) | 0x90; - } - case 2: - if(m_mdctrl.mux2 & 0x20) - { - return porta | 0x90; - } - else - { - return (portb & 0x60) | 0x90; - } - case 3: - if(m_mdctrl.mux2 & 0x20) - { - return (porta & 0x60) | (extra & 0x0f) | 0x90; - } - else - { - return (portb & 0x60) | 0x9f; - } - } - } - return 0xff; -} - -// XPD-1LR dual D-pad controller. -// Sold with Video Game Anthology Vol 4: Libble Rabble. -// Also compatible with Video Game Anthology Vol 5: Crazy Climber 1 & 2 -// Uses the same input multiplexer hardware as Megadrive controllers -// Output is the same as for standard controllers, but when ctl is high, -// the directions refer to the right D-pad, and when low, the left D-pad -// The buttons are read the same as normal, regardless of ctl. -uint8_t x68k_state::xpd1lr_r(int port) -{ - if(port == 1) - { - uint8_t porta = m_xpd1lr->read() & 0xff; - uint8_t portb = (m_xpd1lr->read() >> 8) & 0xff; - if(m_mdctrl.mux1 & 0x10) - { - return porta; - } - else - { - return portb | (porta & 0x60); - } - } - if(port == 2) - { - uint8_t porta = (m_xpd1lr->read() >> 16) & 0xff; - uint8_t portb = (m_xpd1lr->read() >> 24) & 0xff; - if(m_mdctrl.mux2 & 0x20) - { - return porta; - } - else - { - return portb | (porta & 0x60); - } - } - return 0xff; -} - -// Judging from the XM6 source code, PPI ports A and B are joystick inputs +// PPI ports A and B are joystick inputs uint8_t x68k_state::ppi_port_a_r() { - int ctrl = m_ctrltype->read() & 0x0f; + // first read the joystick inputs + uint8_t const input = m_joy[0]->read(); + uint8_t result = 0x90 | (BIT(input, 4, 2) << 5) | BIT(input, 0, 4); - switch(ctrl) - { - case 0x00: // standard MSX/FM-Towns joystick - if(m_joy.joy1_enable == 0) - return m_joy1->read(); - else - return 0xff; - case 0x01: // 3-button Megadrive gamepad - return md_3button_r(1); - case 0x02: // 6-button Megadrive gamepad - return md_6button_r(1); - case 0x03: // XPD-1LR - return xpd1lr_r(1); - } + // trigger lines can be pulled down by port C outputs + result &= ~(BIT(m_ppi_portc, 6, 2) << 5); - return 0xff; + return result; } uint8_t x68k_state::ppi_port_b_r() { - int ctrl = m_ctrltype->read() & 0xf0; - - switch(ctrl) - { - case 0x00: // standard MSX/FM-Towns joystick - if(m_joy.joy2_enable == 0) - return m_joy2->read(); - else - return 0xff; - case 0x10: // 3-button Megadrive gamepad - return md_3button_r(2); - case 0x20: // 6-button Megadrive gamepad - return md_6button_r(2); - case 0x30: // XPD-1LR - return xpd1lr_r(2); - } - - return 0xff; + uint8_t const input = m_joy[1]->read(); + return 0x90 | (BIT(input, 4, 2) << 5) | BIT(input, 0, 4); } uint8_t x68k_state::ppi_port_c_r() { - return m_ppi_port[2]; + return m_ppi_portc; } /* PPI port C (Joystick control, R/W) - bit 7 - IOC7 - Function B operation of joystick 1 (?) - bit 6 - IOC6 - Function A operation of joystick 1 (?) - bit 5 - IOC5 - Enable Joystick 2 - bit 4 - IOC4 - Enable Joystick 1 + bit 7 - IOC7 - Pull down joystick 1 trigger B (JS pin 7) + bit 6 - IOC6 - Pull down joystick 1 trigger A (JS pin 6) + bit 5 - IOC5 - Joystick 2 strobe (JT pin 8) + bit 4 - IOC4 - Joystick 1 strobe (JS pin 8) bits 3,2 - ADPCM Sample rate bits 1,0 - ADPCM Pan (00 = Both, 01 = Right only, 10 = Left only, 11 = Off) */ void x68k_state::ppi_port_c_w(uint8_t data) { // ADPCM / Joystick control - m_ppi_port[2] = data; - if((data & 0x0f) != (m_ppi_prev & 0x0f)) + if((data & 0x0f) != (m_ppi_portc & 0x0f)) { m_adpcm.pan = data & 0x03; m_adpcm.rate = (data & 0x0c) >> 2; @@ -551,26 +351,18 @@ void x68k_state::ppi_port_c_w(uint8_t data) m_adpcm_out[1]->flt_volume_set_volume((m_adpcm.pan & 2) ? 0.0f : 1.0f); } - // The joystick enable bits also handle the multiplexer for various controllers - m_joy.joy1_enable = data & 0x10; - m_mdctrl.mux1 = data & 0x10; - if((m_ppi_prev & 0x10) == 0x00 && (data & 0x10) == 0x10) - { - m_mdctrl.seq1++; - m_mdctrl.io_timeout1->adjust(m_maincpu->cycles_to_attotime(8192)); - } - - m_joy.joy2_enable = data & 0x20; - m_mdctrl.mux2 = data & 0x20; - if((m_ppi_prev & 0x20) == 0x00 && (data & 0x20) == 0x20) - { - m_mdctrl.seq2++; - m_mdctrl.io_timeout2->adjust(m_maincpu->cycles_to_attotime(8192)); - } - m_ppi_prev = data; + // Set joystick outputs + if(BIT(data, 6) != BIT(m_ppi_portc, 6)) + m_joy[0]->pin_6_w(BIT(~data, 6)); + if(BIT(data, 7) != BIT(m_ppi_portc, 7)) + m_joy[0]->pin_7_w(BIT(~data, 7)); + if(BIT(data, 4) != BIT(m_ppi_portc, 4)) + m_joy[0]->pin_8_w(BIT(data, 4)); + if(BIT(data, 5) != BIT(m_ppi_portc, 5)) + m_joy[1]->pin_8_w(BIT(data, 5)); - m_joy.ioc6 = data & 0x40; - m_joy.ioc7 = data & 0x80; + // update saved value + m_ppi_portc = data; } @@ -1261,39 +1053,8 @@ void x68030_state::x68030_map(address_map &map) } static INPUT_PORTS_START( x68000 ) - PORT_START("ctrltype") - PORT_CONFNAME(0x0f, 0x00, "Joystick Port 1") - PORT_CONFSETTING(0x00, "Standard 2-button MSX/FM-Towns joystick") - PORT_CONFSETTING(0x01, "3-button Megadrive gamepad") - PORT_CONFSETTING(0x02, "6-button Megadrive gamepad") - PORT_CONFSETTING(0x03, "XPD-1LR dual D-pad gamepad") - PORT_CONFNAME(0xf0, 0x00, "Joystick Port 2") - PORT_CONFSETTING(0x00, "Standard 2-button MSX/FM-Towns joystick") - PORT_CONFSETTING(0x10, "3-button Megadrive gamepad") - PORT_CONFSETTING(0x20, "6-button Megadrive gamepad") - PORT_CONFSETTING(0x30, "XPD-1LR dual D-pad gamepad") // TODO: Sharp Cyber Stick (CZ-8NJ2) support - PORT_START( "joy1" ) - PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_CODE(JOYCODE_Y_UP_SWITCH) PORT_PLAYER(1) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x00) - PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_CODE(JOYCODE_Y_DOWN_SWITCH) PORT_PLAYER(1) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x00) - PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_CODE(JOYCODE_X_LEFT_SWITCH) PORT_PLAYER(1) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x00) - PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_CODE(JOYCODE_X_RIGHT_SWITCH) PORT_PLAYER(1) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x00) - PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x00) - PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_CODE(JOYCODE_BUTTON1) PORT_PLAYER(1) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x00) - PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_CODE(JOYCODE_BUTTON2) PORT_PLAYER(1) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x00) - PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x00) - - PORT_START( "joy2" ) - PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_CODE(JOYCODE_Y_UP_SWITCH) PORT_PLAYER(2) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x00) - PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_CODE(JOYCODE_Y_DOWN_SWITCH) PORT_PLAYER(2) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x00) - PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_CODE(JOYCODE_X_LEFT_SWITCH) PORT_PLAYER(2) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x00) - PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_CODE(JOYCODE_X_RIGHT_SWITCH) PORT_PLAYER(2) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x00) - PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x00) - PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_CODE(JOYCODE_BUTTON1) PORT_PLAYER(2) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x00) - PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_CODE(JOYCODE_BUTTON2) PORT_PLAYER(2) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x00) - PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x00) - PORT_START("options") PORT_CONFNAME( 0x02, 0x02, "Enable fake bus errors") PORT_CONFSETTING( 0x00, DEF_STR( Off )) @@ -1308,133 +1069,6 @@ static INPUT_PORTS_START( x68000 ) PORT_START("mouse3") // Y-axis PORT_BIT( 0xff, 0x00, IPT_MOUSE_Y) PORT_SENSITIVITY(100) PORT_KEYDELTA(0) PORT_PLAYER(1) - - // 3-button Megadrive gamepad - PORT_START("md3b") - PORT_BIT( 0x00000001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_NAME("MD Pad 1 Up") PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x01) - PORT_BIT( 0x00000002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_NAME("MD Pad 1 Down") PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x01) - PORT_BIT( 0x00000004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_NAME("MD Pad 1 Left") PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x01) - PORT_BIT( 0x00000008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_NAME("MD Pad 1 Right") PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x01) - PORT_BIT( 0x00000010, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x01) - PORT_BIT( 0x00000020, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1) PORT_NAME("MD Pad 1 B Button") PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x01) - PORT_BIT( 0x00000040, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(1) PORT_NAME("MD Pad 1 C Button") PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x01) - PORT_BIT( 0x00000080, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x01) - - PORT_BIT( 0x00000100, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x01) - PORT_BIT( 0x00000200, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x01) - PORT_BIT( 0x00000400, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x01) - PORT_BIT( 0x00000800, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x01) - PORT_BIT( 0x00001000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x01) - PORT_BIT( 0x00002000, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) PORT_NAME("MD Pad 1 A Button") PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x01) - PORT_BIT( 0x00004000, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(1) PORT_NAME("MD Pad 1 Start Button") PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x01) - PORT_BIT( 0x00008000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x01) - - PORT_BIT( 0x00010000, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_NAME("MD Pad 2 Up") PORT_8WAY PORT_PLAYER(2) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x10) - PORT_BIT( 0x00020000, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_NAME("MD Pad 2 Down") PORT_8WAY PORT_PLAYER(2) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x10) - PORT_BIT( 0x00040000, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_NAME("MD Pad 2 Left") PORT_8WAY PORT_PLAYER(2) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x10) - PORT_BIT( 0x00080000, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_NAME("MD Pad 2 Right") PORT_8WAY PORT_PLAYER(2) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x10) - PORT_BIT( 0x00100000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x10) - PORT_BIT( 0x00200000, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2) PORT_NAME("MD Pad 2 B Button") PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x10) - PORT_BIT( 0x00400000, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(2) PORT_NAME("MD Pad 2 C Button") PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x10) - PORT_BIT( 0x00800000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x10) - - PORT_BIT( 0x01000000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x10) - PORT_BIT( 0x02000000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x10) - PORT_BIT( 0x04000000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x10) - PORT_BIT( 0x08000000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x10) - PORT_BIT( 0x10000000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x10) - PORT_BIT( 0x20000000, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) PORT_NAME("MD Pad 2 A Button") PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x10) - PORT_BIT( 0x40000000, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(2) PORT_NAME("MD Pad 2 Start Button") PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x10) - PORT_BIT( 0x80000000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x10) - - // 6-button Megadrive gamepad - PORT_START("md6b") - PORT_BIT( 0x00000001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_NAME("MD Pad 1 Up") PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x02) - PORT_BIT( 0x00000002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_NAME("MD Pad 1 Down") PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x02) - PORT_BIT( 0x00000004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_NAME("MD Pad 1 Left") PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x02) - PORT_BIT( 0x00000008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_NAME("MD Pad 1 Right") PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x02) - PORT_BIT( 0x00000010, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x02) - PORT_BIT( 0x00000020, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1) PORT_NAME("MD Pad 1 B Button") PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x02) - PORT_BIT( 0x00000040, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(1) PORT_NAME("MD Pad 1 C Button") PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x02) - PORT_BIT( 0x00000080, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x02) - - PORT_BIT( 0x00000100, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x02) - PORT_BIT( 0x00000200, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x02) - PORT_BIT( 0x00000400, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x02) - PORT_BIT( 0x00000800, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x02) - PORT_BIT( 0x00001000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x02) - PORT_BIT( 0x00002000, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) PORT_NAME("MD Pad 1 A Button") PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x02) - PORT_BIT( 0x00004000, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(1) PORT_NAME("MD Pad 1 Start Button") PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x02) - PORT_BIT( 0x00008000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x02) - - PORT_BIT( 0x00010000, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_NAME("MD Pad 2 Up") PORT_8WAY PORT_PLAYER(2) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x20) - PORT_BIT( 0x00020000, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_NAME("MD Pad 2 Down") PORT_8WAY PORT_PLAYER(2) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x20) - PORT_BIT( 0x00040000, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_NAME("MD Pad 2 Left") PORT_8WAY PORT_PLAYER(2) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x20) - PORT_BIT( 0x00080000, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_NAME("MD Pad 2 Right") PORT_8WAY PORT_PLAYER(2) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x20) - PORT_BIT( 0x00100000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x20) - PORT_BIT( 0x00200000, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2) PORT_NAME("MD Pad 2 B Button") PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x20) - PORT_BIT( 0x00400000, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(2) PORT_NAME("MD Pad 2 C Button") PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x20) - PORT_BIT( 0x00800000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x20) - - PORT_BIT( 0x01000000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x20) - PORT_BIT( 0x02000000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x20) - PORT_BIT( 0x04000000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x20) - PORT_BIT( 0x08000000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x20) - PORT_BIT( 0x10000000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x20) - PORT_BIT( 0x20000000, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) PORT_NAME("MD Pad 2 A Button") PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x20) - PORT_BIT( 0x40000000, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(2) PORT_NAME("MD Pad 2 Start Button") PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x20) - PORT_BIT( 0x80000000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x20) - - // extra inputs - PORT_START("md6b_extra") - PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_PLAYER(1) PORT_NAME("MD Pad 1 Z Button") PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x02) - PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_PLAYER(1) PORT_NAME("MD Pad 1 Y Button") PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x02) - PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(1) PORT_NAME("MD Pad 1 X Button") PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x02) - PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_BUTTON7 ) PORT_PLAYER(1) PORT_NAME("MD Pad 1 Mode Button") PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x02) - - PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_PLAYER(2) PORT_NAME("MD Pad 2 Z Button") PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x20) - PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_PLAYER(2) PORT_NAME("MD Pad 2 Y Button") PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x20) - PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(2) PORT_NAME("MD Pad 2 X Button") PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x20) - PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_BUTTON7 ) PORT_PLAYER(2) PORT_NAME("MD Pad 2 Mode Button") PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x20) - - // Dempa/Micomsoft XPD-1LR (dual D-pad gamepad sold with Libble Rabble) - PORT_START("xpd1lr") - PORT_BIT( 0x00000001, IP_ACTIVE_LOW, IPT_JOYSTICKLEFT_UP ) PORT_NAME("XPD Pad 1 Left/Up") PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x03) - PORT_BIT( 0x00000002, IP_ACTIVE_LOW, IPT_JOYSTICKLEFT_DOWN ) PORT_NAME("XPD Pad 1 Left/Down") PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x03) - PORT_BIT( 0x00000004, IP_ACTIVE_LOW, IPT_JOYSTICKLEFT_LEFT ) PORT_NAME("XPD Pad 1 Left/Left") PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x03) - PORT_BIT( 0x00000008, IP_ACTIVE_LOW, IPT_JOYSTICKLEFT_RIGHT ) PORT_NAME("XPD Pad 1 Left/Right") PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x03) - PORT_BIT( 0x00000010, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x03) - PORT_BIT( 0x00000020, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1) PORT_NAME("XPD Pad 1 B Button") PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x03) - PORT_BIT( 0x00000040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) PORT_NAME("XPD Pad 1 A Button") PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x03) - PORT_BIT( 0x00000080, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x03) - - PORT_BIT( 0x00000100, IP_ACTIVE_LOW, IPT_JOYSTICKRIGHT_UP ) PORT_NAME("XPD Pad 1 Right/Up") PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x03) - PORT_BIT( 0x00000200, IP_ACTIVE_LOW, IPT_JOYSTICKRIGHT_DOWN ) PORT_NAME("XPD Pad 1 Right/Down") PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x03) - PORT_BIT( 0x00000400, IP_ACTIVE_LOW, IPT_JOYSTICKRIGHT_LEFT ) PORT_NAME("XPD Pad 1 Right/Left") PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x03) - PORT_BIT( 0x00000800, IP_ACTIVE_LOW, IPT_JOYSTICKRIGHT_RIGHT ) PORT_NAME("XPD Pad 1 Right/Right") PORT_8WAY PORT_PLAYER(1) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x03) - PORT_BIT( 0x00001000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x03) - PORT_BIT( 0x00002000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x03) - PORT_BIT( 0x00004000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x03) - PORT_BIT( 0x00008000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0x0f, EQUALS, 0x03) - - PORT_BIT( 0x00010000, IP_ACTIVE_LOW, IPT_JOYSTICKLEFT_UP ) PORT_NAME("XPD Pad 2 Left/Up") PORT_8WAY PORT_PLAYER(2) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x30) - PORT_BIT( 0x00020000, IP_ACTIVE_LOW, IPT_JOYSTICKLEFT_DOWN ) PORT_NAME("XPD Pad 2 Left/Down") PORT_8WAY PORT_PLAYER(2) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x30) - PORT_BIT( 0x00040000, IP_ACTIVE_LOW, IPT_JOYSTICKLEFT_LEFT ) PORT_NAME("XPD Pad 2 Left/Left") PORT_8WAY PORT_PLAYER(2) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x30) - PORT_BIT( 0x00080000, IP_ACTIVE_LOW, IPT_JOYSTICKLEFT_RIGHT ) PORT_NAME("XPD Pad 2 Left/Right") PORT_8WAY PORT_PLAYER(2) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x30) - PORT_BIT( 0x00100000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x30) - PORT_BIT( 0x00200000, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2) PORT_NAME("XPD Pad 2 B Button") PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x30) - PORT_BIT( 0x00400000, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) PORT_NAME("XPD Pad 2 A Button") PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x30) - PORT_BIT( 0x00800000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x30) - - PORT_BIT( 0x01000000, IP_ACTIVE_LOW, IPT_JOYSTICKRIGHT_UP ) PORT_NAME("XPD Pad 2 Right/Up") PORT_8WAY PORT_PLAYER(2) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x30) - PORT_BIT( 0x02000000, IP_ACTIVE_LOW, IPT_JOYSTICKRIGHT_DOWN ) PORT_NAME("XPD Pad 2 Right/Down") PORT_8WAY PORT_PLAYER(2) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x30) - PORT_BIT( 0x04000000, IP_ACTIVE_LOW, IPT_JOYSTICKRIGHT_LEFT ) PORT_NAME("XPD Pad 2 Right/Left") PORT_8WAY PORT_PLAYER(2) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x30) - PORT_BIT( 0x08000000, IP_ACTIVE_LOW, IPT_JOYSTICKRIGHT_RIGHT ) PORT_NAME("XPD Pad 2 Right/Right") PORT_8WAY PORT_PLAYER(2) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x30) - PORT_BIT( 0x10000000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x30) - PORT_BIT( 0x20000000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x30) - PORT_BIT( 0x40000000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x30) - PORT_BIT( 0x80000000, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_CONDITION("ctrltype", 0xf0, EQUALS, 0x30) - INPUT_PORTS_END void x68k_state::floppy_load_unload(bool load, floppy_image_device *dev) @@ -1568,9 +1202,6 @@ void x68k_state::driver_start() m_adpcm_timer = timer_alloc(FUNC(x68ksupr_state::adpcm_drq_tick), this); m_bus_error_timer = timer_alloc(FUNC(x68ksupr_state::bus_error), this); - // Initialise timers for 6-button MD controllers - md_6button_init(); - m_sysport.cputype = 0xff; // 68000, 10MHz m_is_32bit = false; @@ -1625,6 +1256,9 @@ void x68k_state::x68000_base(machine_config &config) rs232_port_device &keyboard(RS232_PORT(config, "keyboard", keyboard_devices, "x68k")); keyboard.rxd_handler().set(m_mfpdev, FUNC(mc68901_device::si_w)); + MSX_GENERAL_PURPOSE_PORT(config, m_joy[0], msx_general_purpose_port_devices, "townspad"); + MSX_GENERAL_PURPOSE_PORT(config, m_joy[1], msx_general_purpose_port_devices, "townspad"); + I8255A(config, m_ppi, 0); m_ppi->in_pa_callback().set(FUNC(x68k_state::ppi_port_a_r)); m_ppi->in_pb_callback().set(FUNC(x68k_state::ppi_port_b_r)); diff --git a/src/mame/sharp/x68k.h b/src/mame/sharp/x68k.h index 364c153cc35..5932d84f43d 100644 --- a/src/mame/sharp/x68k.h +++ b/src/mame/sharp/x68k.h @@ -13,6 +13,10 @@ #pragma once +#include "x68k_crtc.h" + +#include "bus/msx/ctrl/ctrl.h" +#include "bus/x68k/x68kexp.h" #include "cpu/m68000/m68000.h" #include "cpu/m68000/m68030.h" #include "imagedev/floppy.h" @@ -27,8 +31,6 @@ #include "sound/flt_vol.h" #include "sound/okim6258.h" #include "sound/ymopm.h" -#include "x68k_crtc.h" -#include "bus/x68k/x68kexp.h" #include "emupal.h" #include "screen.h" @@ -58,19 +60,13 @@ public: , m_ppi(*this, "ppi8255") , m_screen(*this, "screen") , m_upd72065(*this, "upd72065") + , m_joy(*this, "joy%u", 1U) , m_expansion(*this, "exp%u", 1U) , m_adpcm_out(*this, {"adpcm_outl", "adpcm_outr"}) , m_options(*this, "options") , m_mouse1(*this, "mouse1") , m_mouse2(*this, "mouse2") , m_mouse3(*this, "mouse3") - , m_xpd1lr(*this, "xpd1lr") - , m_ctrltype(*this, "ctrltype") - , m_joy1(*this, "joy1") - , m_joy2(*this, "joy2") - , m_md3b(*this, "md3b") - , m_md6b(*this, "md6b") - , m_md6b_extra(*this, "md6b_extra") , m_eject_drv_out(*this, "eject_drv%u", 0U) , m_ctrl_drv_out(*this, "ctrl_drv%u", 0U) , m_access_drv_out(*this, "access_drv%u", 0U) @@ -109,6 +105,7 @@ protected: required_device m_ppi; required_device m_screen; required_device m_upd72065; + required_device_array m_joy; required_device_array m_expansion; required_device_array m_adpcm_out; @@ -117,13 +114,6 @@ protected: required_ioport m_mouse1; required_ioport m_mouse2; required_ioport m_mouse3; - required_ioport m_xpd1lr; - required_ioport m_ctrltype; - required_ioport m_joy1; - required_ioport m_joy2; - required_ioport m_md3b; - required_ioport m_md6b; - required_ioport m_md6b_extra; output_finder<4> m_eject_drv_out; output_finder<4> m_ctrl_drv_out; @@ -162,13 +152,6 @@ protected: int select_drive = 0; } m_fdc; struct - { - int ioc7 = 0; // "Function B operation of joystick # one option" - int ioc6 = 0; // "Function A operation of joystick # one option" - int joy1_enable = 0; // IOC4 - int joy2_enable = 0; // IOC5 - } m_joy; - struct { int rate = 0; // ADPCM sample rate int pan = 0; // ADPCM output switch @@ -206,18 +189,7 @@ protected: char last_mouse_y = 0; // previous mouse y-axis value int bufferempty = 0; // non-zero if buffer is empty } m_mouse; - struct - { - // port A - int mux1 = 0; // multiplexer value - int seq1 = 0; // part of 6-button input sequence. - emu_timer* io_timeout1 = nullptr; - // port B - int mux2 = 0; // multiplexer value - int seq2 = 0; // part of 6-button input sequence. - emu_timer* io_timeout2 = nullptr; - } m_mdctrl; - uint8_t m_ppi_port[3]{}; + uint8_t m_ppi_portc = 0; bool m_dmac_int = false; bool m_mfp_int = false; bool m_exp_irq2[2]{}; @@ -228,7 +200,6 @@ protected: emu_timer* m_mouse_timer = nullptr; emu_timer* m_led_timer = nullptr; unsigned char m_scc_prev = 0; - uint16_t m_ppi_prev = 0; emu_timer* m_fdc_tc = nullptr; emu_timer* m_adpcm_timer = nullptr; emu_timer* m_bus_error_timer = nullptr; @@ -250,8 +221,6 @@ protected: TIMER_CALLBACK_MEMBER(adpcm_drq_tick); TIMER_CALLBACK_MEMBER(led_callback); TIMER_CALLBACK_MEMBER(scc_ack); - TIMER_CALLBACK_MEMBER(md_6button_port1_timeout); - TIMER_CALLBACK_MEMBER(md_6button_port2_timeout); TIMER_CALLBACK_MEMBER(bus_error); uint8_t ppi_port_a_r(); uint8_t ppi_port_b_r(); @@ -268,10 +237,6 @@ protected: int read_mouse(); void set_adpcm(); - uint8_t md_3button_r(int port); - void md_6button_init(); - uint8_t md_6button_r(int port); - uint8_t xpd1lr_r(int port); DECLARE_WRITE_LINE_MEMBER(fm_irq); template DECLARE_WRITE_LINE_MEMBER(irq2_line); -- cgit v1.2.3