diff options
author | 2019-02-27 03:02:31 -0300 | |
---|---|---|
committer | 2019-02-27 01:02:31 -0500 | |
commit | 5309bae38b65195426ff0b988e0204c1efef114e (patch) | |
tree | 9fdd36fcf79530d3726503a2fd29b65703eda9c2 /src/devices/bus/sg1000_exp | |
parent | 78d376dc14b3344b255a5e61b8a6c81ac9d3a277 (diff) |
sg1000m3: Add keyboard cable link for F-16 Fighting Falcon's 2p mode (#4680)
* sg1000m3: Add keyboard cable link for F-16 Fighting Falcon's 2p mode
* included missing files
Diffstat (limited to 'src/devices/bus/sg1000_exp')
-rw-r--r-- | src/devices/bus/sg1000_exp/kblink.cpp | 179 | ||||
-rw-r--r-- | src/devices/bus/sg1000_exp/kblink.h | 82 | ||||
-rw-r--r-- | src/devices/bus/sg1000_exp/sk1100.cpp | 30 | ||||
-rw-r--r-- | src/devices/bus/sg1000_exp/sk1100.h | 3 | ||||
-rw-r--r-- | src/devices/bus/sg1000_exp/sk1100prn.cpp | 125 | ||||
-rw-r--r-- | src/devices/bus/sg1000_exp/sk1100prn.h | 88 |
6 files changed, 493 insertions, 14 deletions
diff --git a/src/devices/bus/sg1000_exp/kblink.cpp b/src/devices/bus/sg1000_exp/kblink.cpp new file mode 100644 index 00000000000..039c7f91196 --- /dev/null +++ b/src/devices/bus/sg1000_exp/kblink.cpp @@ -0,0 +1,179 @@ +// license:BSD-3-Clause +// copyright-holders:Enik Land +/********************************************************************** + + Sega SK-1100 keyboard link cable emulation + +The cable is used only to link two Mark III's through keyboard, what +is supported by the game F-16 Fighting Falcon for its 2 players mode. + +Keyboard link cable info (originally from http://homepage3.nifty.com/st-2/, +but taken from http://www.smspower.org/Games/F16FightingFalcon-SMS-Talk): + +- Cable is 7-pin DIN. +- Crossover scheme of the cable to connect pins + + From To + 1 1 + 2 6 + 3 3 + 4 5 + 5 4 + 6 2 + 7 7 + +Pinout of the printer port (from Charles MacDonald's sc3000h-20040729.txt +document, with the function of pin 6 corrected to /FAULT). +Numbering in counterclockwise/anticlockwise direction: + + 1 : Unused (not connected to anything) + 2 : PPI PC5 (DATA output) + 3 : PPI PC7 (/FEED output) + 4 : PPI PB6 (BUSY input) + 5 : PPI PC6 (/RESET output) + 6 : PPI PB5 (/FAULT input) + 7 : GND + +**********************************************************************/ + +#include "emu.h" +#include "kblink.h" + + + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +DEFINE_DEVICE_TYPE(SK1100_LINK_CABLE, sk1100_link_cable_device, "sk1100_link_cable", "SK-1100 Link Cable") + + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// sk1100_link_cable_device - constructor +//------------------------------------------------- + +sk1100_link_cable_device::sk1100_link_cable_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : + device_t(mconfig, SK1100_LINK_CABLE, tag, owner, clock), + device_sk1100_printer_port_interface(mconfig, *this), + m_stream(*this, "stream"), + m_input_count(0), + m_input_index(0), + m_timer_poll(nullptr), + m_timer_send(nullptr), + m_timer_read(nullptr), + m_update_received_data(true), + m_data(0), + m_reset(0), + m_feed(0), + m_busy(0), + m_fault(0) +{ +} + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void sk1100_link_cable_device::device_start() +{ + m_timer_poll = timer_alloc(TIMER_POLL); + m_timer_send = timer_alloc(TIMER_SEND); + m_timer_read = timer_alloc(TIMER_READ); + + /* register for state saving */ + save_item(NAME(m_data)); + save_item(NAME(m_reset)); + save_item(NAME(m_feed)); + save_item(NAME(m_busy)); + save_item(NAME(m_fault)); + save_item(NAME(m_update_received_data)); + save_item(NAME(m_input_count)); + save_item(NAME(m_input_index)); + save_pointer(NAME(m_input_buffer), sizeof(m_input_buffer)); +} + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void sk1100_link_cable_device::device_reset() +{ + queue(); +} + + +//------------------------------------------------- +// device_add_mconfig - add device configuration +//------------------------------------------------- + +void sk1100_link_cable_device::device_add_mconfig(machine_config &config) +{ + BITBANGER(config, m_stream, 0); +} + + +void sk1100_link_cable_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + switch (id) + { + case TIMER_POLL: + queue(); + break; + + case TIMER_SEND: + m_stream->output(u8(param)); + break; + + case TIMER_READ: + m_update_received_data = true; + break; + + default: + break; + } +} + +void sk1100_link_cable_device::queue() +{ + if (m_input_index == m_input_count) + { + m_input_index = 0; + m_input_count = m_stream->input(m_input_buffer, sizeof(m_input_buffer)); + if (!m_input_count) + { + m_timer_poll->adjust(attotime::from_hz(XTAL(10'738'635)/3)); + } + } +} + +void sk1100_link_cable_device::set_data_read() +{ + // Check if a new byte from the input buffer was read for this timeslice. + if (m_update_received_data == true) + { + if (m_input_count != 0) + { + u8 byte = m_input_buffer[m_input_index++]; + // there is no way to read what was sent from peer as feed bit. + m_fault = BIT(byte, 0); // sent from peer as data bit + m_busy = BIT(byte, 1); // sent from peer as reset bit + queue(); + } + // Set to read next byte only after the end of this timeslice. + m_update_received_data = false; + m_timer_read->adjust(attotime::zero); + } +} + +void sk1100_link_cable_device::set_data_transfer() +{ + u8 byte = (m_feed << 2) | (m_reset << 1) | m_data; + m_timer_send->adjust(attotime::zero, byte); +} + + diff --git a/src/devices/bus/sg1000_exp/kblink.h b/src/devices/bus/sg1000_exp/kblink.h new file mode 100644 index 00000000000..65e5782f4a2 --- /dev/null +++ b/src/devices/bus/sg1000_exp/kblink.h @@ -0,0 +1,82 @@ +// license:BSD-3-Clause +// copyright-holders:Enik Land +/********************************************************************** + + Sega SK-1100 keyboard link cable emulation + +The cable is used only to link two Mark III's through keyboard, what +is supported by the game F-16 Fighting Falcon for its 2 players mode. + +**********************************************************************/ + +#ifndef MAME_BUS_SG1000_EXP_SK1100_KBLINK_H +#define MAME_BUS_SG1000_EXP_SK1100_KBLINK_H + +#pragma once + + +#include "sk1100prn.h" +#include "imagedev/bitbngr.h" + + + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// ======================> sk1100_link_cable_device + +class sk1100_link_cable_device : public device_t, + public device_sk1100_printer_port_interface +{ +public: + // construction/destruction + sk1100_link_cable_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + +protected: + // device-level overrides + virtual void device_start() override; + virtual void device_reset() override; + virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; + virtual void device_add_mconfig(machine_config &config) override; + + // device_sk1100_link_cable_interface overrides + + virtual DECLARE_WRITE_LINE_MEMBER( input_data ) override { m_data = state; set_data_transfer(); } + virtual DECLARE_WRITE_LINE_MEMBER( input_reset ) override { m_reset = state; set_data_transfer(); } + virtual DECLARE_WRITE_LINE_MEMBER( input_feed ) override { m_feed = state; set_data_transfer(); } + + virtual DECLARE_READ_LINE_MEMBER( output_fault ) override { set_data_read(); return m_fault; } + virtual DECLARE_READ_LINE_MEMBER( output_busy ) override { set_data_read(); return m_busy; } + +private: + static constexpr int TIMER_POLL = 1; + static constexpr int TIMER_SEND = 2; + static constexpr int TIMER_READ = 3; + + void queue(); + void set_data_transfer(); + void set_data_read(); + + required_device<bitbanger_device> m_stream; + + u8 m_input_buffer[1000]; + u32 m_input_count; + u32 m_input_index; + emu_timer *m_timer_poll; + emu_timer *m_timer_send; + emu_timer *m_timer_read; + bool m_update_received_data; + int m_data; + int m_reset; + int m_feed; + int m_busy; + int m_fault; +}; + + +// device type definition +DECLARE_DEVICE_TYPE(SK1100_LINK_CABLE, sk1100_link_cable_device) + + +#endif // MAME_BUS_SG1000_EXP_SK1100_KBLINK_H diff --git a/src/devices/bus/sg1000_exp/sk1100.cpp b/src/devices/bus/sg1000_exp/sk1100.cpp index 3ce616afded..1bb0a01adfd 100644 --- a/src/devices/bus/sg1000_exp/sk1100.cpp +++ b/src/devices/bus/sg1000_exp/sk1100.cpp @@ -12,7 +12,6 @@ Release data from the Sega Retro project: TODO: - SP-400 serial printer -- Link between two Mark III's through keyboard, supported by F-16 Fighting Falcon **********************************************************************/ @@ -110,23 +109,23 @@ static INPUT_PORTS_START( sk1100_keys ) PORT_START("PB0") PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('(') - PORT_BIT( 0x06, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x0e, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_START("PB1") PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR(')') - PORT_BIT( 0x06, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x0e, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_START("PB2") PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_0) PORT_CHAR('0') - PORT_BIT( 0x06, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x0e, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_START("PB3") PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('=') - PORT_BIT( 0x06, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x0e, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_START("PB4") PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_BACKSLASH2) PORT_CHAR('^') - PORT_BIT( 0x06, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x0e, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_START("PB5") PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("\xc2\xa5") PORT_CODE(KEYCODE_TILDE) PORT_CHAR(0x00a5) @@ -162,13 +161,13 @@ void sega_sk1100_device::device_add_mconfig(machine_config &config) m_ppi->in_pb_callback().set(FUNC(sega_sk1100_device::ppi_pb_r)); m_ppi->out_pc_callback().set(FUNC(sega_sk1100_device::ppi_pc_w)); -// PRINTER(config, "sp400", 0); /* serial printer */ - CASSETTE(config, m_cassette); m_cassette->set_formats(sc3000_cassette_formats); m_cassette->set_default_state(CASSETTE_STOPPED | CASSETTE_MOTOR_ENABLED | CASSETTE_SPEAKER_ENABLED); m_cassette->set_interface("sc3000_cass"); + SK1100_PRINTER_PORT(config, m_printer_port, sk1100_printer_port_devices, nullptr); + /* software lists */ SOFTWARE_LIST(config, "sc3k_cart_list").set_original("sc3000_cart"); SOFTWARE_LIST(config, "cass_list").set_original("sc3000_cass"); @@ -187,6 +186,7 @@ sega_sk1100_device::sega_sk1100_device(const machine_config &mconfig, const char device_sg1000_expansion_slot_interface(mconfig, *this), m_cassette(*this, "cassette"), m_ppi(*this, UPD9255_0_TAG), + m_printer_port(*this, "printer"), m_pa(*this, {"PA0", "PA1", "PA2", "PA3", "PA4", "PA5", "PA6", "PA7"}), m_pb(*this, {"PB0", "PB1", "PB2", "PB3", "PB4", "PB5", "PB6", "PB7"}), m_keylatch(0) @@ -263,7 +263,7 @@ READ8_MEMBER( sega_sk1100_device::ppi_pb_r ) PB2 Keyboard input PB3 Keyboard input PB4 /CONT input from cartridge terminal B-11 - PB5 FAULT input from printer + PB5 /FAULT input from printer PB6 BUSY input from printer PB7 Cassette tape input */ @@ -274,8 +274,9 @@ READ8_MEMBER( sega_sk1100_device::ppi_pb_r ) /* cartridge contact */ data |= 0x10; - /* printer */ - data |= 0x60; + /* printer port */ + data |= m_printer_port->fault_r() << 5; + data |= m_printer_port->busy_r() << 6; /* tape input */ if (m_cassette->input() > +0.0) data |= 0x80; @@ -302,7 +303,10 @@ WRITE8_MEMBER( sega_sk1100_device::ppi_pc_w ) m_keylatch = data & 0x07; /* cassette */ - m_cassette->output( BIT(data, 4) ? +1.0 : -1.0); + m_cassette->output(BIT(data, 4) ? +1.0 : -1.0); - /* TODO printer */ + /* printer port */ + m_printer_port->data_w(BIT(data, 5)); + m_printer_port->reset_w(BIT(data, 6)); + m_printer_port->feed_w(BIT(data, 7)); } diff --git a/src/devices/bus/sg1000_exp/sk1100.h b/src/devices/bus/sg1000_exp/sk1100.h index 4845fe09e1c..13ff5780f64 100644 --- a/src/devices/bus/sg1000_exp/sk1100.h +++ b/src/devices/bus/sg1000_exp/sk1100.h @@ -13,9 +13,9 @@ #include "sg1000exp.h" +#include "sk1100prn.h" #include "formats/sc3000_bit.h" #include "imagedev/cassette.h" -#include "imagedev/printer.h" #include "machine/i8255.h" @@ -55,6 +55,7 @@ private: required_device<cassette_image_device> m_cassette; required_device<i8255_device> m_ppi; + required_device<sk1100_printer_port_device> m_printer_port; required_ioport_array<8> m_pa; required_ioport_array<8> m_pb; diff --git a/src/devices/bus/sg1000_exp/sk1100prn.cpp b/src/devices/bus/sg1000_exp/sk1100prn.cpp new file mode 100644 index 00000000000..b902ce3992f --- /dev/null +++ b/src/devices/bus/sg1000_exp/sk1100prn.cpp @@ -0,0 +1,125 @@ +// license:BSD-3-Clause +// copyright-holders:Enik Land +/********************************************************************** + + Sega SK-1100 keyboard printer port emulation + +**********************************************************************/ + +#include "emu.h" +#include "sk1100prn.h" +// slot devices +//#include "sp400.h" +#include "kblink.h" + + + +//************************************************************************** +// GLOBAL VARIABLES +//************************************************************************** + +DEFINE_DEVICE_TYPE(SK1100_PRINTER_PORT, sk1100_printer_port_device, "sk1100_printer_port", "Sega SK-1100 Printer Port") + + + +//************************************************************************** +// CARD INTERFACE +//************************************************************************** + +//------------------------------------------------- +// device_sk1100_printer_port_interface - constructor +//------------------------------------------------- + +device_sk1100_printer_port_interface::device_sk1100_printer_port_interface(const machine_config &mconfig, device_t &device) + : device_slot_card_interface(mconfig,device) +{ +} + + +//------------------------------------------------- +// ~device_sk1100_printer_port_interface - destructor +//------------------------------------------------- + +device_sk1100_printer_port_interface::~device_sk1100_printer_port_interface() +{ +} + + + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// sk1100_printer_port_device - constructor +//------------------------------------------------- + +sk1100_printer_port_device::sk1100_printer_port_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : + device_t(mconfig, SK1100_PRINTER_PORT, tag, owner, clock), + device_slot_interface(mconfig, *this), + m_device(nullptr) +{ +} + + +//------------------------------------------------- +// sk1100_printer_port_device - destructor +//------------------------------------------------- + +sk1100_printer_port_device::~sk1100_printer_port_device() +{ +} + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void sk1100_printer_port_device::device_start() +{ + m_device = dynamic_cast<device_sk1100_printer_port_interface *>(get_card_device()); +} + +WRITE_LINE_MEMBER(sk1100_printer_port_device::data_w) +{ + if (m_device) + m_device->input_data(state); +} + +WRITE_LINE_MEMBER(sk1100_printer_port_device::reset_w) +{ + if (m_device) + m_device->input_reset(state); +} + +WRITE_LINE_MEMBER(sk1100_printer_port_device::feed_w) +{ + if (m_device) + m_device->input_feed(state); +} + +READ_LINE_MEMBER(sk1100_printer_port_device::fault_r) +{ + if (m_device) + return m_device->output_fault(); + else + return 1; +} + +READ_LINE_MEMBER(sk1100_printer_port_device::busy_r) +{ + if (m_device) + return m_device->output_busy(); + else + return 1; +} + +//------------------------------------------------- +// SLOT_INTERFACE( sk1100_printer_port_devices ) +//------------------------------------------------- + +void sk1100_printer_port_devices(device_slot_interface &device) +{ + //device.option_add("sp400", SP400_PRINTER); /* serial printer */ + device.option_add("kblink", SK1100_LINK_CABLE); +} diff --git a/src/devices/bus/sg1000_exp/sk1100prn.h b/src/devices/bus/sg1000_exp/sk1100prn.h new file mode 100644 index 00000000000..b926f311f29 --- /dev/null +++ b/src/devices/bus/sg1000_exp/sk1100prn.h @@ -0,0 +1,88 @@ +// license:BSD-3-Clause +// copyright-holders:Enik Land +/********************************************************************** + + Sega SK-1100 keyboard printer port emulation + +********************************************************************** + + +**********************************************************************/ + +#ifndef MAME_BUS_SG1000_EXP_SK1100_PRN_H +#define MAME_BUS_SG1000_EXP_SK1100_PRN_H + +#pragma once + + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// ======================> sk1100_printer_port_device + +class device_sk1100_printer_port_interface; + +class sk1100_printer_port_device : public device_t, public device_slot_interface +{ +public: + // construction/destruction + template <typename T> + sk1100_printer_port_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *dflt) + : sk1100_printer_port_device(mconfig, tag, owner, 0) + { + option_reset(); + opts(*this); + set_default_option(dflt); + set_fixed(false); + } + + sk1100_printer_port_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); + virtual ~sk1100_printer_port_device(); + + DECLARE_READ_LINE_MEMBER(fault_r); + DECLARE_READ_LINE_MEMBER(busy_r); + + DECLARE_WRITE_LINE_MEMBER(data_w); + DECLARE_WRITE_LINE_MEMBER(reset_w); + DECLARE_WRITE_LINE_MEMBER(feed_w); + +protected: + // device-level overrides + virtual void device_start() override; + +private: + device_sk1100_printer_port_interface *m_device; +}; + + +// ======================> device_sk1100_printer_port_interface + +// class representing interface-specific live sk1100_printer_port peripheral +class device_sk1100_printer_port_interface : public device_slot_card_interface +{ + friend class sk1100_printer_port_device; +public: + // construction/destruction + virtual ~device_sk1100_printer_port_interface(); + +protected: + device_sk1100_printer_port_interface(const machine_config &mconfig, device_t &device); + + virtual DECLARE_WRITE_LINE_MEMBER( input_data ) { } + virtual DECLARE_WRITE_LINE_MEMBER( input_reset ) { } + virtual DECLARE_WRITE_LINE_MEMBER( input_feed ) { } + + virtual DECLARE_READ_LINE_MEMBER( output_fault ) { return 1; } + virtual DECLARE_READ_LINE_MEMBER( output_busy ) { return 1; } +}; + + +// device type definition +DECLARE_DEVICE_TYPE(SK1100_PRINTER_PORT, sk1100_printer_port_device) + + +void sk1100_printer_port_devices(device_slot_interface &device); + + +#endif // MAME_BUS_SG1000_EXP_SK1100_PRN_H |