summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/machine/abc1600mac.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/machine/abc1600mac.c')
-rw-r--r--src/mame/machine/abc1600mac.c686
1 files changed, 686 insertions, 0 deletions
diff --git a/src/mame/machine/abc1600mac.c b/src/mame/machine/abc1600mac.c
new file mode 100644
index 00000000000..b22f55708c6
--- /dev/null
+++ b/src/mame/machine/abc1600mac.c
@@ -0,0 +1,686 @@
+// license:BSD-3-Clause
+// copyright-holders:Curt Coder
+/**********************************************************************
+
+ Luxor ABC 1600 Memory Access Controller emulation
+
+**********************************************************************/
+
+/*
+
+ TODO:
+
+ - segment/page RAM addresses are not correctly decoded, "sas/format/format" can't find the SASI interface because of this
+ forcetask0 1 t0 0 t1 0 t2 0 t3 0
+ sega19 0 task 0
+ sega 000 segd 00 pga 008 pgd 4058 virtual 02c730 (should be 004730)
+*/
+
+#include "abc1600mac.h"
+
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+#define LOG 0
+
+
+#define A0 BIT(offset, 0)
+#define A1 BIT(offset, 1)
+#define A2 BIT(offset, 2)
+#define A4 BIT(offset, 4)
+#define A7 BIT(offset, 7)
+#define A8 BIT(offset, 8)
+#define X11 BIT(offset, 11)
+#define X12 BIT(offset, 12)
+#define A17 BIT(offset, 17)
+#define A18 BIT(offset, 18)
+#define A19 BIT(offset, 19)
+
+#define A10_A9_A8 ((offset >> 8) & 0x07)
+#define A2_A1_A0 (offset & 0x07)
+#define A1_A2 ((A1 << 1) | A2)
+#define A2_A1 ((offset >> 1) & 0x03)
+
+#define FC0 BIT(fc, 0)
+#define FC1 BIT(fc, 1)
+#define FC2 BIT(fc, 2)
+
+#define PAGE_WP BIT(page_data, 14)
+#define PAGE_NONX BIT(page_data, 15)
+
+#define BOOTE BIT(m_task, 6)
+#define MAGIC BIT(m_task, 7)
+#define READ_MAGIC !MAGIC
+
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+const device_type ABC1600_MAC = &device_creator<abc1600_mac_device>;
+
+
+DEVICE_ADDRESS_MAP_START( map, 8, abc1600_mac_device )
+ AM_RANGE(0x00000, 0xfffff) AM_READWRITE(read, write)
+ADDRESS_MAP_END
+
+
+static ADDRESS_MAP_START( program_map, AS_PROGRAM, 8, abc1600_mac_device )
+ADDRESS_MAP_END
+
+
+//-------------------------------------------------
+// ROM( abc1600_mac )
+//-------------------------------------------------
+
+ROM_START( abc1600_mac )
+ ROM_REGION( 0x4000, "boot", 0 )
+ ROM_LOAD( "boot 6490356-04.1f", 0x0000, 0x4000, CRC(9372f6f2) SHA1(86f0681f7ef8dd190b49eda5e781881582e0c2a4) )
+
+ ROM_REGION( 0x104, "plds", 0 )
+ ROM_LOAD( "1022 6490351-01.17e", 0x000, 0x104, CRC(5dd00d43) SHA1(a3871f0d796bea9df8f25d41b3169dd4b8ef65ab) ) // MAC register address decoder
+ROM_END
+
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const rom_entry *abc1600_mac_device::device_rom_region() const
+{
+ return ROM_NAME( abc1600_mac );
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// abc1600_mac_device - constructor
+//-------------------------------------------------
+
+abc1600_mac_device::abc1600_mac_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, ABC1600_MAC, "ABC 1600 MAC", tag, owner, clock, "abc1600mac", __FILE__),
+ device_memory_interface(mconfig, *this),
+ m_space_config("program", ENDIANNESS_LITTLE, 8, 22, 0, *ADDRESS_MAP_NAME(program_map)),
+ m_rom(*this, "boot"),
+ m_segment_ram(*this, "segment_ram"),
+ m_page_ram(*this, "page_ram"),
+ m_task(0)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void abc1600_mac_device::device_start()
+{
+ // get the CPU device
+ m_cpu = machine().device<m68000_base_device>(m_cpu_tag);
+ assert(m_cpu != NULL);
+
+ // allocate memory
+ m_segment_ram.allocate(0x400);
+ m_page_ram.allocate(0x400);
+
+ // HACK fill segment RAM or abcenix won't boot
+ memset(m_segment_ram, 0xcd, 0x400);
+
+ // state saving
+ save_item(NAME(m_ifc2));
+ save_item(NAME(m_task));
+ save_item(NAME(m_dmamap));
+ save_item(NAME(m_cause));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void abc1600_mac_device::device_reset()
+{
+ // clear task register
+ m_task = 0;
+}
+
+
+//-------------------------------------------------
+// memory_space_config - return a description of
+// any address spaces owned by this device
+//-------------------------------------------------
+
+const address_space_config *abc1600_mac_device::memory_space_config(address_spacenum spacenum) const
+{
+ return (spacenum == AS_PROGRAM) ? &m_space_config : NULL;
+}
+
+
+//-------------------------------------------------
+// get_current_task -
+//-------------------------------------------------
+
+int abc1600_mac_device::get_current_task(offs_t offset)
+{
+ int force_task0 = !(m_ifc2 || A19);
+ int t0 = !(BIT(m_task, 0) || force_task0);
+ int t1 = !(BIT(m_task, 1) || force_task0);
+ int t2 = !(BIT(m_task, 2) || force_task0);
+ int t3 = !(BIT(m_task, 3) || force_task0);
+
+ return (t3 << 3) | (t2 << 2) | (t1 << 1) | t0;
+}
+
+
+//-------------------------------------------------
+// get_segment_address -
+//-------------------------------------------------
+
+offs_t abc1600_mac_device::get_segment_address(offs_t offset)
+{
+ int sega19 = !(!(A8 || m_ifc2) || !A19);
+ int task = get_current_task(offset);
+
+ return (task << 5) | (sega19 << 4) | ((offset >> 15) & 0x0f);
+}
+
+
+//-------------------------------------------------
+// get_page_address -
+//-------------------------------------------------
+
+offs_t abc1600_mac_device::get_page_address(offs_t offset, UINT8 segd)
+{
+ return ((segd & 0x3f) << 4) | ((offset >> 11) & 0x0f);
+}
+
+
+//-------------------------------------------------
+// translate_address -
+//-------------------------------------------------
+
+offs_t abc1600_mac_device::translate_address(offs_t offset, int *nonx, int *wp)
+{
+ // segment
+ offs_t sega = get_segment_address(offset);
+ UINT8 segd = m_segment_ram[sega];
+
+ // page
+ offs_t pga = get_page_address(offset, segd);
+ UINT16 page_data = m_page_ram[pga];
+
+ offs_t virtual_offset = ((page_data & 0x3ff) << 11) | (offset & 0x7ff);
+
+ if (PAGE_NONX)
+ {
+ //logerror("Bus error %06x : %06x\n", offset, virtual_offset);
+ //m_cpu->set_input_line(M68K_LINE_BUSERROR, ASSERT_LINE);
+ //m_cpu->set_input_line(M68K_LINE_BUSERROR, CLEAR_LINE);
+ }
+
+ *nonx = PAGE_NONX;
+ *wp = PAGE_WP;
+
+ return virtual_offset;
+}
+
+
+//-------------------------------------------------
+// read_user_memory -
+//-------------------------------------------------
+
+UINT8 abc1600_mac_device::read_user_memory(offs_t offset)
+{
+ int nonx = 0, wp = 0;
+ offs_t virtual_offset = translate_address(offset, &nonx, &wp);
+
+ return space().read_byte(virtual_offset);
+}
+
+
+//-------------------------------------------------
+// write_user_memory -
+//-------------------------------------------------
+
+void abc1600_mac_device::write_user_memory(offs_t offset, UINT8 data)
+{
+ int nonx = 0, wp = 0;
+ offs_t virtual_offset = translate_address(offset, &nonx, &wp);
+
+ //if (nonx || !wp) return;
+
+ space().write_byte(virtual_offset, data);
+}
+
+
+//-------------------------------------------------
+// read_supervisor_memory -
+//-------------------------------------------------
+
+UINT8 abc1600_mac_device::read_supervisor_memory(address_space &space, offs_t offset)
+{
+ UINT8 data = 0;
+
+ if (!A2 && !A1)
+ {
+ // _EP
+ data = page_r(space, offset);
+ }
+ else if (!A2 && A1 && A0)
+ {
+ // _ES
+ data = segment_r(space, offset);
+ }
+ else if (A2 && A1 && A0)
+ {
+ // _CAUSE
+ data = cause_r(space, offset);
+ }
+
+ return data;
+}
+
+
+//-------------------------------------------------
+// write_supervisor_memory -
+//-------------------------------------------------
+
+void abc1600_mac_device::write_supervisor_memory(address_space &space, offs_t offset, UINT8 data)
+{
+ if (!A2 && !A1)
+ {
+ // _WEP
+ page_w(space, offset, data);
+ }
+ else if (!A2 && A1 && A0)
+ {
+ // _WES
+ segment_w(space, offset, data);
+ }
+ else if (A2 && !A1 && A0)
+ {
+ // W(C)
+ task_w(space, offset, data);
+ }
+}
+
+
+//-------------------------------------------------
+// get_fc -
+//-------------------------------------------------
+
+int abc1600_mac_device::get_fc()
+{
+ UINT16 fc = m_cpu->get_fc();
+
+ m_ifc2 = !(!(MAGIC || FC0) || FC2);
+
+ return fc;
+}
+
+
+//-------------------------------------------------
+// read -
+//-------------------------------------------------
+
+READ8_MEMBER( abc1600_mac_device::read )
+{
+ int fc = get_fc();
+
+ UINT8 data = 0;
+
+ if (!BOOTE && !A19 && !A18 && !A17)
+ {
+ // _BOOTCE
+ data = m_rom->base()[offset & 0x3fff];
+ }
+ else if (A19 && !m_ifc2 && !FC1)
+ {
+ data = read_supervisor_memory(space, offset);
+ }
+ else
+ {
+ data = read_user_memory(offset);
+ }
+
+ return data;
+}
+
+
+//-------------------------------------------------
+// write -
+//-------------------------------------------------
+
+WRITE8_MEMBER( abc1600_mac_device::write )
+{
+ int fc = get_fc();
+
+ if (A19 && !m_ifc2 && !FC1)
+ {
+ write_supervisor_memory(space, offset, data);
+ }
+ else
+ {
+ write_user_memory(offset, data);
+ }
+}
+
+
+//-------------------------------------------------
+// cause_r -
+//-------------------------------------------------
+
+READ8_MEMBER( abc1600_mac_device::cause_r )
+{
+ /*
+
+ bit description
+
+ 0 RSTBUT
+ 1 1
+ 2 DMAOK
+ 3 X16
+ 4 X17
+ 5 X18
+ 6 X19
+ 7 X20
+
+ */
+
+ UINT8 data = 0x02;
+
+ // DMA status
+ data |= m_cause;
+
+ machine().watchdog_reset();
+
+ return data;
+}
+
+
+//-------------------------------------------------
+// task_w -
+//-------------------------------------------------
+
+WRITE8_MEMBER( abc1600_mac_device::task_w )
+{
+ /*
+
+ bit description
+
+ 0 TASKD0* (inverted SEGA5)
+ 1 TASKD1* (inverted SEGA6)
+ 2 TASKD2* (inverted SEGA7)
+ 3 TASKD3* (inverted SEGA8)
+ 4
+ 5
+ 6 BOOTE*
+ 7 MAGIC*
+
+ */
+
+ m_task = data ^ 0xff;
+
+ if (LOG) logerror("%s: %06x Task %u BOOTE %u MAGIC %u\n", machine().describe_context(), offset, get_current_task(offset), BOOTE, MAGIC);
+}
+
+
+//-------------------------------------------------
+// segment_r -
+//-------------------------------------------------
+
+READ8_MEMBER( abc1600_mac_device::segment_r )
+{
+ /*
+
+ bit description
+
+ 0 SEGD0
+ 1 SEGD1
+ 2 SEGD2
+ 3 SEGD3
+ 4 SEGD4
+ 5 SEGD5
+ 6 SEGD6
+ 7 READ_MAGIC
+
+ */
+
+ offs_t sega = get_segment_address(offset);
+ UINT8 segd = m_segment_ram[sega];
+
+ return (READ_MAGIC << 7) | (segd & 0x7f);
+}
+
+
+//-------------------------------------------------
+// segment_w -
+//-------------------------------------------------
+
+WRITE8_MEMBER( abc1600_mac_device::segment_w )
+{
+ /*
+
+ bit description
+
+ 0 SEGD0
+ 1 SEGD1
+ 2 SEGD2
+ 3 SEGD3
+ 4 SEGD4
+ 5 SEGD5
+ 6 SEGD6
+ 7 0
+
+ */
+
+ offs_t sega = get_segment_address(offset);
+
+ m_segment_ram[sega] = data & 0x7f;
+
+ if (LOG) logerror("%s: %06x Task %u Segment %03x : %02x\n", machine().describe_context(), offset, get_current_task(offset), sega, data);
+}
+
+
+//-------------------------------------------------
+// page_r -
+//-------------------------------------------------
+
+READ8_MEMBER( abc1600_mac_device::page_r )
+{
+ /*
+
+ bit description
+
+ 0 X11
+ 1 X12
+ 2 X13
+ 3 X14
+ 4 X15
+ 5 X16
+ 6 X17
+ 7 X18
+
+ 8 X19
+ 9 X20
+ 10 X20
+ 11 X20
+ 12 X20
+ 13 X20
+ 14 _WP
+ 15 NONX
+
+ */
+
+ // segment
+ offs_t sega = get_segment_address(offset);
+ UINT8 segd = m_segment_ram[sega];
+
+ // page
+ offs_t pga = get_page_address(offset, segd);
+ UINT16 pgd = m_page_ram[pga];
+
+ UINT8 data = 0;
+
+ if (A0)
+ {
+ data = pgd & 0xff;
+ }
+ else
+ {
+ int x20 = BIT(pgd, 9);
+
+ data = (pgd >> 8) | (x20 << 2) | (x20 << 3) | (x20 << 4) | (x20 << 5);
+ }
+
+ return data;
+}
+
+
+//-------------------------------------------------
+// page_w -
+//-------------------------------------------------
+
+WRITE8_MEMBER( abc1600_mac_device::page_w )
+{
+ /*
+
+ bit description
+
+ 0 X11
+ 1 X12
+ 2 X13
+ 3 X14
+ 4 X15
+ 5 X16
+ 6 X17
+ 7 X18
+
+ 8 X19
+ 9 X20
+ 10
+ 11
+ 12
+ 13
+ 14 _WP
+ 15 NONX
+
+ */
+
+ // segment
+ offs_t sega = get_segment_address(offset);
+ UINT8 segd = m_segment_ram[sega];
+
+ // page
+ offs_t pga = get_page_address(offset, segd);
+
+ if (A0)
+ {
+ m_page_ram[pga] = (m_page_ram[pga] & 0xff00) | data;
+ }
+ else
+ {
+ m_page_ram[pga] = ((data & 0xc3) << 8) | (m_page_ram[pga] & 0xff);
+ }
+
+ if (LOG) logerror("%s: %06x Task %u Segment %03x Page %03x : %02x -> %04x\n", machine().describe_context(), offset, get_current_task(offset), sega, pga, data, m_page_ram[pga]);
+}
+
+
+//-------------------------------------------------
+// get_dma_address -
+//-------------------------------------------------
+
+offs_t abc1600_mac_device::get_dma_address(int index, UINT16 offset)
+{
+ // A0 = DMA15, A1 = BA1, A2 = BA2
+ UINT8 dmamap_addr = index | BIT(offset, 15);
+ UINT8 dmamap = m_dmamap[dmamap_addr];
+
+ m_cause = (dmamap & 0x1f) << 3;
+
+ return ((dmamap & 0x1f) << 16) | offset;
+}
+
+
+//-------------------------------------------------
+// dma_mreq_r - DMA memory read
+//-------------------------------------------------
+
+UINT8 abc1600_mac_device::dma_mreq_r(int index, UINT16 offset)
+{
+ offs_t virtual_offset = get_dma_address(index, offset);
+
+ return space().read_byte(virtual_offset);
+}
+
+
+//-------------------------------------------------
+// dma_mreq_w - DMA memory write
+//-------------------------------------------------
+
+void abc1600_mac_device::dma_mreq_w(int index, UINT16 offset, UINT8 data)
+{
+ offs_t virtual_offset = get_dma_address(index, offset);
+
+ space().write_byte(virtual_offset, data);
+}
+
+
+//-------------------------------------------------
+// dma_iorq_r - DMA I/O read
+//-------------------------------------------------
+
+UINT8 abc1600_mac_device::dma_iorq_r(int index, UINT16 offset)
+{
+ offs_t virtual_offset = 0x1fe000 | get_dma_address(index, offset);
+
+ return space().read_byte(virtual_offset);
+}
+
+
+//-------------------------------------------------
+// dma_iorq_w - DMA I/O write
+//-------------------------------------------------
+
+void abc1600_mac_device::dma_iorq_w(int index, UINT16 offset, UINT8 data)
+{
+ offs_t virtual_offset = 0x1fe000 | get_dma_address(index, offset);
+
+ space().write_byte(virtual_offset, data);
+}
+
+
+//-------------------------------------------------
+// dmamap_w - DMA map write
+//-------------------------------------------------
+
+WRITE8_MEMBER( abc1600_mac_device::dmamap_w )
+{
+ /*
+
+ bit description
+
+ 0 X16
+ 1 X17
+ 2 X18
+ 3 X19
+ 4 X20
+ 5
+ 6
+ 7 _R/W
+
+ */
+
+ if (LOG) logerror("DMAMAP %u %02x\n", offset & 7, data);
+
+ m_dmamap[offset & 7] = data;
+}