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 +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +class sms_graphic_device : public device_t, public device_sms_control_interface { - return INPUT_PORTS_NAME( sms_graphic ); -} +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; +}; -//************************************************************************** -// LIVE DEVICE -//************************************************************************** //------------------------------------------------- // 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; + } + else if (!BIT(m_select, 5) && BIT(m_select, 6) && !BIT(data, 6)) + { + // 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? + } } - // If TR is high, restart - if (data & 0x80) - { - m_index = 0; - } - - 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") { } - -//------------------------------------------------- -// device_start - device-specific startup -//------------------------------------------------- - -void sms_joypad_device::device_start() -{ -} +} // anonymous namespace -//------------------------------------------------- -// sms_peripheral_r - joypad read -//------------------------------------------------- -uint8_t sms_joypad_device::peripheral_r() -{ - return m_joypad->read(); -} +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +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") - - -#define LGUN_RADIUS 6 -#define LGUN_X_INTERVAL 4 - - -READ_LINE_MEMBER( sms_light_phaser_device::th_pin_r ) +class sms_light_phaser_device : public device_t, public device_sms_control_interface { - // The returned value is inverted due to IP_ACTIVE_LOW mapping. - return ~m_sensor_last_state; -} +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); } + + // 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; + +private: + required_ioport m_trigger; + required_ioport m_x_axis; + required_ioport m_y_axis; + + emu_timer *m_update_timer; + + 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); +}; -INPUT_CHANGED_MEMBER( sms_light_phaser_device::position_changed ) -{ - if (newval != oldval) - { - sensor_check(0); - } -} - - -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() { + m_update_timer = timer_alloc(FUNC(sms_light_phaser_device::sensor_check), this); + + m_sensor_last_state = 1; + save_item(NAME(m_sensor_last_state)); - m_lphaser_timer = timer_alloc(FUNC(sms_light_phaser_device::sensor_check), this); } void sms_light_phaser_device::device_reset() { - m_sensor_last_state = 1; // off (1) -} - - -//------------------------------------------------- -// sms_peripheral_r - light phaser read -//------------------------------------------------- - -uint8_t sms_light_phaser_device::peripheral_r() -{ - 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; + scr.update_now(); + const rgb_t color = scr.pixel(beam_x, beam_y); - m_port->m_screen->update_now(); - color = m_port->m_screen->pixel(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); - /* 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); - - 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" -// Scheme: http://www.smspower.org/uploads/Homebrew/BOoM-SMS-sms4p_2.png +//#define VERBOSE 1 +//#define LOG_OUTPUT_FUNC osd_printf_info +#include "logmacro.h" +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,25 +61,32 @@ 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; +} + + //------------------------------------------------- // device_start - device-specific startup //------------------------------------------------- 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" + + +namespace { + +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 + + + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +class sms_paddle_device : public device_t, public device_sms_control_interface +{ +public: + // construction/destruction + sms_paddle_device(const machine_config &mconfig, char const *tag, device_t *owner, u32 clock); + + // device_sms_control_interface implementation + virtual u8 in_r() override; + virtual void out_w(u8 data, u8 mem_mask) override; + +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); + + // 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); } + + required_ioport m_button; + required_ioport m_axis; + + emu_timer *m_idle_timer; + + u8 m_th; + u8 m_nybble; + u8 m_data; +}; + + +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) +{ +} + + +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); +} + + +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; + } +} + + +void sms_paddle_device::device_start() +{ + m_idle_timer = timer_alloc(FUNC(sms_paddle_device::timeout), this); + + 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()); +} + + +TIMER_CALLBACK_MEMBER(sms_paddle_device::timeout) +{ + 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(SMS_PADDLE, sms_paddle_device, "sms_paddle", "Sega SMS Paddle") - -// 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 ) -{ - uint8_t data = m_paddle_x->read(); - - if (m_read_state) - data >>= 4; - - // The returned value is inverted due to IP_ACTIVE_LOW mapping. - return ~data; -} - - -READ_LINE_MEMBER( sms_paddle_device::tr_pin_r ) -{ - // The returned value is inverted due to IP_ACTIVE_LOW mapping. - return ~m_read_state; -} - - -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 - - 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 - - -//------------------------------------------------- -// input_ports - device-specific input ports -//------------------------------------------------- - -ioport_constructor sms_paddle_device::device_input_ports() const -{ - return INPUT_PORTS_NAME( sms_paddle ); -} - - - -//************************************************************************** -// 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) -{ -} - - -//------------------------------------------------- -// device_start - device-specific startup -//------------------------------------------------- - -void sms_paddle_device::device_start() -{ - m_start_time = machine().time(); - - save_item(NAME(m_start_time)); - save_item(NAME(m_read_state)); -} - - -//------------------------------------------------- -// sms_peripheral_r - paddle read -//------------------------------------------------- - -uint8_t sms_paddle_device::peripheral_r() -{ - 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(); -} +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") +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); -// time interval not verified -#define RAPID_FIRE_INTERVAL attotime::from_hz(10) + // 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; +}; -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" ) +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; - - 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; - - /* Check Rapid Fire switch for Button 2 (TR) */ - if (!(data & 0x80) && (m_rfire_sw->read() & 0x02)) - data |= m_read_state << 7; - - return data; + return m_subctrl_port->in_r() | (read_state ? m_rfire_sw->read() : 0U); } -//------------------------------------------------- -// sms_peripheral_w - rapid fire write -//------------------------------------------------- - -void sms_rapid_fire_device::peripheral_w(uint8_t data) +void sms_rapid_fire_device::out_w(uint8_t data, uint8_t mem_mask) { - m_subctrl_port->port_w(data); -} - - -//------------------------------------------------- -// device_add_mconfig - add device configuration -//------------------------------------------------- - -WRITE_LINE_MEMBER( sms_rapid_fire_device::th_pin_w ) -{ - m_port->th_pin_w(state); + // 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; } void sms_rapid_fire_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_rapid_fire_device::th_pin_w)); + 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)); } + + +void sms_rapid_fire_device::device_config_complete() +{ + configure_screen( + [this] (auto const &s) + { subdevice("ctrl")->set_screen(s); }); +} + + +void sms_rapid_fire_device::device_start() +{ + save_item(NAME(m_in)); + save_item(NAME(m_drive)); + save_item(NAME(m_rapid)); +} + + +void sms_rapid_fire_device::device_reset() +{ + 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_interface::~device_sms_control_interface() +{ +} -device_sms_control_port_interface::~device_sms_control_port_interface() + +u8 device_sms_control_interface::in_r() +{ + return 0xff; +} + + +void device_sms_control_interface::out_w(u8 data, u8 mem_mask) { } //************************************************************************** -// LIVE DEVICE +// SLOT 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) : +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_slot_interface(mconfig, *this), + device_single_card_slot_interface(mconfig, *this), m_screen(*this, finder_base::DUMMY_TAG), - m_device(nullptr), - m_th_pin_handler(*this) + m_th_handler(*this), + m_controller(nullptr) { } -//------------------------------------------------- -// sms_control_port_device - destructor -//------------------------------------------------- - sms_control_port_device::~sms_control_port_device() { } -//------------------------------------------------- -// device_start - device-specific startup -//------------------------------------------------- +void sms_control_port_device::device_resolve_objects() +{ + m_th_handler.resolve_safe(); +} + void sms_control_port_device::device_start() { - m_device = dynamic_cast(get_card_device()); - - m_th_pin_handler.resolve_safe(); -} - - -uint8_t sms_control_port_device::port_r() -{ - uint8_t data = 0xff; - if (m_device) - data = m_device->peripheral_r(); - return data; -} - -void sms_control_port_device::port_w( uint8_t data ) -{ - if (m_device) - m_device->peripheral_w(data); -} - - -void sms_control_port_device::th_pin_w(int state) -{ - m_th_pin_handler(state); -} - - -//------------------------------------------------- -// SLOT_INTERFACE( sms_control_port_devices ) -//------------------------------------------------- - -void sms_control_port_devices(device_slot_interface &device) -{ - 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 -#include "screen.h" - #pragma once +#include "screen.h" + +#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(); } + 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)); } - // 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) + // Bit Pin Signal + // 0 1 Up + // 1 2 Down + // 2 3 Left + // 3 4 Right + // 4 6 TL + // 5 9 TR // - uint8_t port_r(); - void port_w( uint8_t data ); + // return bits set for pulled high or high impedance + // return bits clear for pulled low + u8 in_r(); - void th_pin_w(int state); - - 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 + // 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); - sms_control_port_device *m_port; + 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); } + +private: + sms_control_port_device *const m_port; }; -// device type definition + +//************************************************************************** +// INLINE MEMBER FUNCTIONS +//************************************************************************** + +inline u8 sms_control_port_device::in_r() +{ + return m_controller ? m_controller->in_r() : 0xff; +} + + +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) - -void sms_control_port_devices(device_slot_interface &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,129 +41,91 @@ Notes: #include "sports.h" +namespace { -//************************************************************************** -// DEVICE DEFINITIONS -//************************************************************************** +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 -DEFINE_DEVICE_TYPE(SMS_SPORTS_PAD, sms_sports_pad_device, "sms_sports_pad", "Sega SMS Sports Pad (US)") - -// time interval not verified -#define SPORTS_PAD_INTERVAL attotime::from_hz(XTAL(10'738'635)/3/512) - - -TIMER_CALLBACK_MEMBER(sms_sports_pad_device::read_tick) -{ - // 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) - { - m_x_axis_reset_value = m_sports_x->read(); - m_y_axis_reset_value = m_sports_y->read(); - } - else - { - // set to maximum value, so it wraps to 0 at next increment - m_read_state = 3; - } -} - - -READ_LINE_MEMBER( sms_sports_pad_device::th_pin_r ) -{ - return m_th_pin_state; -} - - -WRITE_LINE_MEMBER( sms_sports_pad_device::th_pin_w ) -{ - m_read_state = (m_read_state + 1) & 3; - m_sportspad_timer->adjust(m_interval); - m_th_pin_state = state; -} - - -CUSTOM_INPUT_MEMBER( sms_sports_pad_device::rldu_pins_r ) -{ - uint8_t data = 0; - - switch (m_read_state) - { - case 0: - data = (m_sports_x->read() - m_x_axis_reset_value) >> 4; - break; - case 1: - data = (m_sports_x->read() - m_x_axis_reset_value); - break; - case 2: - data = (m_sports_y->read() - m_y_axis_reset_value) >> 4; - break; - case 3: - data = (m_sports_y->read() - m_y_axis_reset_value); - break; - } - - // The returned value is inverted due to IP_ACTIVE_LOW mapping. - return ~(data & 0x0f); -} - - -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_START("SPORTS_X") // 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_START("SPORTS_Y") // 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 +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +class sms_sports_pad_device : public device_t, public device_sms_control_interface { - return INPUT_PORTS_NAME( sms_sports_pad ); +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); + + required_ioport m_buttons; + required_ioport m_x_axis; + required_ioport m_y_axis; + + emu_timer *m_timeout_timer; + + 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 (3U == m_phase) + { + 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_phase = 3; + } } - -//************************************************************************** -// 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) + 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) { } @@ -174,20 +136,63 @@ sms_sports_pad_device::sms_sports_pad_device(const machine_config &mconfig, cons void sms_sports_pad_device::device_start() { - m_sportspad_timer = timer_alloc(FUNC(sms_sports_pad_device::read_tick), this); + m_timeout_timer = timer_alloc(FUNC(sms_sports_pad_device::timeout), 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)); + 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)); } -uint8_t sms_sports_pad_device::peripheral_r() + +uint8_t sms_sports_pad_device::in_r() { - return m_sports_in->read(); + uint8_t result = m_buttons->read(); + + switch (m_phase) + { + case 0: + result |= BIT(m_x_axis->read() - m_x_base, 4, 4); + break; + case 1: + result |= BIT(m_x_axis->read() - m_x_base, 0, 4); + break; + case 2: + result |= BIT(m_y_axis->read() - m_y_base, 4, 4); + break; + case 3: + result |= BIT(m_y_axis->read() - m_y_base, 0, 4); + break; + } + + return result; } -void sms_sports_pad_device::peripheral_w(uint8_t data) + +void sms_sports_pad_device::out_w(uint8_t data, uint8_t mem_mask) { - m_sports_out->write(data); + 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 + } + + m_th_state = th_state; } + +} // anonymous namespace + + + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +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 -//------------------------------------------------- - -void sms_sports_pad_jp_device::device_start() -{ - m_start_time = machine().time(); - - 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)); -} - - //------------------------------------------------- // sms_peripheral_r - sports pad read //------------------------------------------------- -uint8_t sms_sports_pad_jp_device::peripheral_r() +uint8_t sms_sports_pad_jp_device::in_r() { - int num_intervals = (machine().time() - m_start_time).as_double() / m_interval.as_double(); + int const num_intervals = machine().time().as_ticks(20000); // time interval not verified 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; + 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(); } - - return m_sports_jp_in->read(); } + +} // anonymous namespace + + + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +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 0: + case 1: + result |= ~mask & (m_io_ctrl_th_in[offset] | (m_ctrl_ports[offset]->in_r() & 0x3f)); + break; - case 1: - controller = (m_io_ctrlr->read() & 0xf0); - 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); - } - } + // handle test input for SVP test + if (!offset && m_cart && m_cart->read_test()) + result = m_io_data_regs[0] & 0xc0; - // osd_printf_debug("read io data port stage %d port %d %02x\n",mess_io_stage[portnum],portnum,retdata); - - 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 0: + case 1: + m_ctrl_ports[offset]->out_w((data | ~m_io_ctrl_regs[offset]) & 0x7f, m_io_ctrl_regs[offset] & 0x7f); + break; - case 1: - controller = (m_io_ctrlr->read() & 0xf0); - 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) +static INPUT_PORTS_START( md ) + // 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_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_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( 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" ) -/* 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" ) -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_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; - 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++) - { + 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)); - } + // 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.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; - - 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);