summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
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
commitda6196f70d516179b96dcc4699517ef9eb07f7cd (patch)
tree4909e144ac15de69a815410c8760a8737ca979c0
parent79c783eba9742c7dc1da684efc672ce83064b8f8 (diff)
apple3: Support for the Titan "/// Plus II" Apple II emulation card. [R. Belmont]
-rw-r--r--scripts/src/bus.lua2
-rw-r--r--src/devices/bus/a2bus/a2bus.h1
-rw-r--r--src/devices/bus/a2bus/titan3plus2.cpp334
-rw-r--r--src/devices/bus/a2bus/titan3plus2.h64
-rw-r--r--src/mame/drivers/apple3.cpp4
-rw-r--r--src/mame/machine/apple3.cpp49
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;