diff options
author | arbee <rb6502@users.noreply.github.com> | 2021-06-15 23:12:56 -0400 |
---|---|---|
committer | arbee <rb6502@users.noreply.github.com> | 2021-06-15 23:12:56 -0400 |
commit | da6196f70d516179b96dcc4699517ef9eb07f7cd (patch) | |
tree | 4909e144ac15de69a815410c8760a8737ca979c0 | |
parent | 79c783eba9742c7dc1da684efc672ce83064b8f8 (diff) |
apple3: Support for the Titan "/// Plus II" Apple II emulation card. [R. Belmont]
-rw-r--r-- | scripts/src/bus.lua | 2 | ||||
-rw-r--r-- | src/devices/bus/a2bus/a2bus.h | 1 | ||||
-rw-r--r-- | src/devices/bus/a2bus/titan3plus2.cpp | 334 | ||||
-rw-r--r-- | src/devices/bus/a2bus/titan3plus2.h | 64 | ||||
-rw-r--r-- | src/mame/drivers/apple3.cpp | 4 | ||||
-rw-r--r-- | src/mame/machine/apple3.cpp | 49 |
6 files changed, 424 insertions, 30 deletions
diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua index c5dd3b198b2..9258a9ea108 100644 --- a/scripts/src/bus.lua +++ b/scripts/src/bus.lua @@ -2464,6 +2464,8 @@ if (BUSES["A2BUS"]~=null) then MAME_DIR .. "src/devices/bus/a2bus/suprterminal.h", MAME_DIR .. "src/devices/bus/a2bus/timemasterho.cpp", MAME_DIR .. "src/devices/bus/a2bus/timemasterho.h", + MAME_DIR .. "src/devices/bus/a2bus/titan3plus2.cpp", + MAME_DIR .. "src/devices/bus/a2bus/titan3plus2.h", MAME_DIR .. "src/devices/bus/a2bus/transwarp.cpp", MAME_DIR .. "src/devices/bus/a2bus/transwarp.h", MAME_DIR .. "src/devices/bus/a2bus/uniprint.cpp", diff --git a/src/devices/bus/a2bus/a2bus.h b/src/devices/bus/a2bus/a2bus.h index 1c7d94bbcdc..5a10f06de39 100644 --- a/src/devices/bus/a2bus/a2bus.h +++ b/src/devices/bus/a2bus/a2bus.h @@ -149,6 +149,7 @@ public: virtual void write_inh_rom(uint16_t offset, uint8_t data) { } virtual uint16_t inh_start() { return INH_START_INVALID; } virtual uint16_t inh_end() { return INH_END_INVALID; } + virtual bool inh_check(uint16_t offset, bool bIsWrite) { return false; } virtual int inh_type() { return INH_NONE; } device_a2bus_card_interface *next() const { return m_next; } diff --git a/src/devices/bus/a2bus/titan3plus2.cpp b/src/devices/bus/a2bus/titan3plus2.cpp new file mode 100644 index 00000000000..e04dc03448a --- /dev/null +++ b/src/devices/bus/a2bus/titan3plus2.cpp @@ -0,0 +1,334 @@ +// license:BSD-3-Clause +// copyright-holders:R. Belmont +/********************************************************************* + + titan3plus3.cpp + + Implemention of the Titan "/// Plus //"" card. + By R. Belmont, based on reverse-engineering by Rob Justice. + + This extends the Apple ///'s II emulation to include a 128K + extended language card and Apple II compatible game I/O. + + The card enables itself if the /// is at 1 MHz and accesses the + card's $CNxx ROM space. If the /// goes back to 2 MHz mode at + any time, the card disables itself. + + Address ranges this messes with: + $C05X - passed through to ///, but also used for annunciators on A2 gameio + $C06X - /// doesn't see when card enabled, A2 paddles + $C07X - passed through to ///, but also used for A2 paddle reset + $C08X - unused by /// (language card control) + $D000-$FFFF: usual (for A2) language card space. Not so usual for ///. + +*********************************************************************/ + +#include "emu.h" +#include "titan3plus2.h" + +/*************************************************************************** + PARAMETERS +***************************************************************************/ + +//************************************************************************** +// GLOBAL VARIABLES +//************************************************************************** + +DEFINE_DEVICE_TYPE(A2BUS_TITAN3PLUS2, a2bus_titan3plus2_device, "titan3p2", "Titan /// Plus //") + +/*************************************************************************** + FUNCTION PROTOTYPES +***************************************************************************/ + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +void a2bus_titan3plus2_device::device_add_mconfig(machine_config &config) +{ + APPLE2_GAMEIO(config, m_gameio, apple2_gameio_device::default_options, nullptr); +} + +a2bus_titan3plus2_device::a2bus_titan3plus2_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : + device_t(mconfig, type, tag, owner, clock), device_a2bus_card_interface(mconfig, *this), + m_gameio(*this, "gameio"), + m_inh_state(0), m_last_offset(0), m_dxxx_bank(0), m_main_bank(0), m_enabled(false) +{ +} + +a2bus_titan3plus2_device::a2bus_titan3plus2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + a2bus_titan3plus2_device(mconfig, A2BUS_TITAN3PLUS2, tag, owner, clock) +{ +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void a2bus_titan3plus2_device::device_start() +{ + memset(m_ram, 0, 128*1024); + + save_item(NAME(m_inh_state)); + save_item(NAME(m_ram)); + save_item(NAME(m_dxxx_bank)); + save_item(NAME(m_main_bank)); + save_item(NAME(m_last_offset)); + save_item(NAME(m_enabled)); + + m_x_calibration = m_y_calibration = attotime::from_nsec(10800).as_double(); +} + +void a2bus_titan3plus2_device::device_reset() +{ + m_inh_state = INH_NONE; + m_dxxx_bank = 0; + m_main_bank = 0; + m_last_offset = -1; +} + +void a2bus_titan3plus2_device::do_io(int offset) +{ + int old_inh_state = m_inh_state; + + switch (offset) + { + case 0x1: case 0x3: case 0x9: case 0xb: + if (offset != m_last_offset) + { + m_last_offset = offset; + return; + } + break; + } + m_last_offset = offset; + + if (offset & 4) + { + switch (offset) + { + case 0x4: m_main_bank = 0x00000; break; + case 0x5: m_main_bank = 0x04000; break; + case 0x6: m_main_bank = 0x08000; break; + case 0x7: m_main_bank = 0x0c000; break; + case 0xc: m_main_bank = 0x10000; break; + case 0xd: m_main_bank = 0x14000; break; + case 0xe: m_main_bank = 0x18000; break; + case 0xf: m_main_bank = 0x1c000; break; + } + } + else + { + m_inh_state = INH_NONE; + m_dxxx_bank = 0; + + if (offset & 0x1) + { + m_inh_state |= INH_WRITE; + } + + switch(offset & 0x03) + { + case 0x00: + case 0x03: + m_inh_state |= INH_READ; + break; + } + + if (!(offset & 8)) + { + m_dxxx_bank = 0x1000; + } + } + + if (m_inh_state != old_inh_state) + { + recalc_slot_inh(); + } + + #if 0 + printf("LC: (ofs %x) new state %c%c dxxx=%04x main=%05x\n", + offset, + (m_inh_state & INH_READ) ? 'R' : 'x', + (m_inh_state & INH_WRITE) ? 'W' : 'x', + m_dxxx_bank, m_main_bank); + #endif +} + + +/*------------------------------------------------- + read_c08x - called for reads from the LC switches +-------------------------------------------------*/ + +uint8_t a2bus_titan3plus2_device::read_c08x(uint8_t offset) +{ + if (!machine().side_effects_disabled()) + { + do_io(offset & 0xf); + } + return 0xff; +} + + +/*------------------------------------------------- + write_c0nx - called for writes to the LC switches +-------------------------------------------------*/ + +void a2bus_titan3plus2_device::write_c08x(uint8_t offset, uint8_t data) +{ + do_io(offset & 0xf); +} + +uint8_t a2bus_titan3plus2_device::read_inh_rom(uint16_t offset) +{ + if (offset < 0xd000) + { + if ((offset >= 0xc080) && (offset <= 0xc08f)) + { + return read_c08x(offset & 0xf); + } + + if ((offset >= 0xc060) && (offset <= 0xc06f)) + { + switch (offset & 0x7) + { + case 1: // button 0 + return (m_gameio->sw0_r() ? 0x80 : 0); + + case 2: // button 1 + return (m_gameio->sw1_r() ? 0x80 : 0); + + case 3: // button 2 + return (m_gameio->sw2_r() ? 0x80 : 0); + + case 4: // joy 1 X axis + if (!m_gameio->is_device_connected()) + return 0x80; + return ((machine().time().as_double() < m_joystick_x1_time) ? 0x80 : 0); + + case 5: // joy 1 Y axis + if (!m_gameio->is_device_connected()) + return 0x80; + return ((machine().time().as_double() < m_joystick_y1_time) ? 0x80 : 0); + + case 6: // joy 2 X axis + if (!m_gameio->is_device_connected()) + return 0x80; + return ((machine().time().as_double() < m_joystick_x2_time) ? 0x80 : 0); + + case 7: // joy 2 Y axis + if (!m_gameio->is_device_connected()) + return 0x80; + return ((machine().time().as_double() < m_joystick_y2_time) ? 0x80 : 0); + } + } + } + else + { + if (offset < 0xe000) + { + return m_ram[(offset & 0xfff) + m_dxxx_bank + m_main_bank]; + } + + return m_ram[(offset & 0x1fff) + 0x2000 + m_main_bank]; + } + + return 0xff; +} + +void a2bus_titan3plus2_device::write_inh_rom(uint16_t offset, uint8_t data) +{ + if (offset < 0xd000) + { + if ((offset >= 0xc080) && (offset <= 0xc08f)) + { + write_c08x(offset & 0xf, data); + return; + } + } + else + { + if (offset < 0xe000) + { + m_ram[(offset & 0xfff) + m_dxxx_bank + m_main_bank] = data; + return; + } + + m_ram[(offset & 0x1fff) + 0x2000 + m_main_bank] = data; + } +} + +u8 a2bus_titan3plus2_device::read_cnxx(u8 offset) +{ + m_enabled = true; + return 0xff; +} + +// returns if we want to /INH a read or write to a specific address +bool a2bus_titan3plus2_device::inh_check(u16 offset, bool bIsWrite) +{ + if (!m_enabled) + { + return false; + } + + // handle LC + if (offset >= 0xd000) + { + if ((bIsWrite) && (m_inh_state & INH_WRITE)) + { + return true; + } + + if (!(bIsWrite) && (m_inh_state & INH_READ)) + { + return true; + } + } + + if ((offset >= 0xc080) && (offset <= 0xc08f)) + { + return true; + } + + if ((offset >= 0xc070) && (offset <= 0xc07f)) + { + m_joystick_x1_time = machine().time().as_double() + m_x_calibration * m_gameio->pdl0_r(); + m_joystick_y1_time = machine().time().as_double() + m_y_calibration * m_gameio->pdl1_r(); + m_joystick_x2_time = machine().time().as_double() + m_x_calibration * m_gameio->pdl2_r(); + m_joystick_y2_time = machine().time().as_double() + m_y_calibration * m_gameio->pdl3_r(); + + return false; // Apple /// should still handle this + } + + if ((offset >= 0xc060) && (offset <= 0xc06f)) + { + return true; + } + + if ((offset >= 0xc058) && (offset <= 0xc05f)) + { + switch (offset & 0xf) + { + case 8: + case 9: + m_gameio->an0_w(offset & 1); + break; + case 0xa: + case 0xb: + m_gameio->an1_w(offset & 1); + break; + case 0xc: + case 0xd: + m_gameio->an2_w(offset & 1); + break; + case 0xe: + case 0xf: + m_gameio->an3_w(offset & 1); + break; + } + return false; // Apple /// should still see this + } + + return false; +} diff --git a/src/devices/bus/a2bus/titan3plus2.h b/src/devices/bus/a2bus/titan3plus2.h new file mode 100644 index 00000000000..f162f115d8e --- /dev/null +++ b/src/devices/bus/a2bus/titan3plus2.h @@ -0,0 +1,64 @@ +// license:BSD-3-Clause +// copyright-holders:R. Belmont +/********************************************************************* + + titan3plus2.h + + Implemention of the Titan /// Plus II card + +*********************************************************************/ + +#ifndef MAME_BUS_A2BUS_TITAN3PLUS2_H +#define MAME_BUS_A2BUS_TITAN3PLUS2_H + +#pragma once + +#include "a2bus.h" +#include "bus/a2gameio/gameio.h" + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +class a2bus_titan3plus2_device: + public device_t, + public device_a2bus_card_interface +{ +public: + // construction/destruction + a2bus_titan3plus2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + +protected: + a2bus_titan3plus2_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + + virtual void device_start() override; + virtual void device_reset() override; + virtual void device_add_mconfig(machine_config &config) override; + + // overrides of standard a2bus slot functions + virtual u8 read_inh_rom(u16 offset) override; + virtual void write_inh_rom(u16 offset, u8 data) override; + virtual bool inh_check(uint16_t offset, bool bIsWrite) override; + +private: + required_device<apple2_gameio_device> m_gameio; + + u8 read_c08x(u8 offset); + void write_c08x(u8 offset, u8 data); + u8 read_cnxx(u8 offset) override; + void do_io(int offset); + + int m_inh_state; + int m_last_offset; + int m_dxxx_bank; + int m_main_bank; + u8 m_ram[128*1024]; + bool m_enabled; + + double m_joystick_x1_time, m_joystick_y1_time, m_joystick_x2_time, m_joystick_y2_time, m_x_calibration, m_y_calibration; +}; + +// device type definition +DECLARE_DEVICE_TYPE(A2BUS_TITAN3PLUS2, a2bus_titan3plus2_device) + +#endif // MAME_BUS_A2BUS_TITAN3PLUS2_H diff --git a/src/mame/drivers/apple3.cpp b/src/mame/drivers/apple3.cpp index 1c633605b89..32262a419a8 100644 --- a/src/mame/drivers/apple3.cpp +++ b/src/mame/drivers/apple3.cpp @@ -26,6 +26,8 @@ #include "bus/a2bus/mouse.h" #include "bus/a2bus/a2zipdrive.h" #include "bus/a2bus/cmsscsi.h" +#include "bus/a2bus/titan3plus2.h" +#include "bus/a2bus/a2mockingboard.h" #include "bus/rs232/rs232.h" @@ -47,6 +49,8 @@ static void apple3_cards(device_slot_interface &device) device.option_add("mouse", A2BUS_MOUSE); // Apple II Mouse Card device.option_add("focusdrive", A2BUS_FOCUSDRIVE); // Focus Drive IDE card device.option_add("cmsscsi", A2BUS_CMSSCSI); // CMS Apple II SCSI Card + device.option_add("titan3plus2", A2BUS_TITAN3PLUS2); // Titan /// Plus 2 card + device.option_add("mockingboard", A2BUS_MOCKINGBOARD); } static void a3_floppies(device_slot_interface &device) diff --git a/src/mame/machine/apple3.cpp b/src/mame/machine/apple3.cpp index a875d6dfc9e..13dd3e0ef84 100644 --- a/src/mame/machine/apple3.cpp +++ b/src/mame/machine/apple3.cpp @@ -770,20 +770,15 @@ uint8_t apple3_state::apple3_memory_r(offs_t offset) { uint8_t rv = 0xff; - if (m_inh_state) + // /INH handling + for (int slot = 1; slot < 5; slot++) { - for (int slot = 1; slot < 4; slot++) + device_a2bus_card_interface *slotdevice = m_a2bus->get_a2bus_card(slot); + if (slotdevice != nullptr) { - device_a2bus_card_interface *slotdevice = m_a2bus->get_a2bus_card(slot); - if (slotdevice != nullptr) + if (slotdevice->inh_check(offset, false)) { - if ((slotdevice->inh_type() & INH_READ) == INH_READ) - { - if ((offset >= slotdevice->inh_start()) && (offset <= slotdevice->inh_end())) - { - return slotdevice->read_inh_rom(offset); - } - } + return slotdevice->read_inh_rom(offset); } } } @@ -925,25 +920,6 @@ uint8_t apple3_state::apple3_memory_r(offs_t offset) void apple3_state::apple3_memory_w(offs_t offset, uint8_t data) { - if (m_inh_state) - { - for (int slot = 1; slot < 4; slot++) - { - device_a2bus_card_interface *slotdevice = m_a2bus->get_a2bus_card(slot); - if (slotdevice != nullptr) - { - if ((slotdevice->inh_type() & INH_WRITE) == INH_WRITE) - { - if ((offset >= slotdevice->inh_start()) && (offset <= slotdevice->inh_end())) - { - slotdevice->write_inh_rom(offset, data); - return; - } - } - } - } - } - if ((m_indir_bank & 0x80) && (offset >= 0x100)) { uint8_t *test; @@ -956,6 +932,19 @@ void apple3_state::apple3_memory_w(offs_t offset, uint8_t data) } } + for (int slot = 1; slot < 5; slot++) + { + device_a2bus_card_interface *slotdevice = m_a2bus->get_a2bus_card(slot); + if (slotdevice != nullptr) + { + if (slotdevice->inh_check(offset, true)) + { + slotdevice->write_inh_rom(offset, data); + return; + } + } + } + if (offset < 0x100) { *apple3_get_zpa_addr(offset) = data; |