summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/machine/elan_eu3a05commonsys.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/machine/elan_eu3a05commonsys.cpp')
-rw-r--r--src/mame/machine/elan_eu3a05commonsys.cpp307
1 files changed, 307 insertions, 0 deletions
diff --git a/src/mame/machine/elan_eu3a05commonsys.cpp b/src/mame/machine/elan_eu3a05commonsys.cpp
new file mode 100644
index 00000000000..7b1b5f09e5f
--- /dev/null
+++ b/src/mame/machine/elan_eu3a05commonsys.cpp
@@ -0,0 +1,307 @@
+// license:BSD-3-Clause
+// copyright-holders:David Haywood
+
+#include "emu.h"
+#include "elan_eu3a05commonsys.h"
+
+/*
+ Both the Elan EU3A05 and EU3A14 CPU types implement some kind of custom interrupt handling
+
+ It isn't clear if this is a completely new addition to the CPU, or just an interface / controller
+ sitting on top of the existing NMI or IRQ support in the core providing custom vectors.
+
+ The interrupt handlers are 16 4-byte entries starting at 0xffb0 in memory space
+
+*/
+
+
+/*
+ -----------------------
+ Custom Interrupt purposes
+ -----------------------
+
+ TETRIS (enables 5007 : 0a, 5008: 0f)
+
+ ffb0 (enabled)
+ nothing of note?
+
+ ffb4 (enabled)
+ stuff with 500e, 500c and 500d
+
+ ffb8 (enabled)
+ stuff with 50a4 / 50a5 / 50a6 and memory address e2
+
+ ffbc (enabled)
+ stuff with 50a4 / 50a5 / 50a6 and memory address e2 (similar to above, different bits)
+
+ ffc0 - doesn't exist
+ ffc4 - doesn't exist
+ ffc8 - doesn't exist
+ ffd0 - doesn't exist
+
+ ffd4 (enabled)
+ main irq?
+
+ ffd8
+ jumps straight to an rti
+
+ ffdc (enabled) - probably P2 input related? ADC interrupt?
+ accesses 501d / 501b
+
+ -----------------------
+
+ SPACE INVADERS
+
+ ffb0
+ rti
+
+ ffb4
+ rti
+
+ ffb8 (enabled by phoenix)
+ rti
+
+ ffbc (enabled by phoenix)
+ decreases 301 bit 02
+ stuff with 50a5
+
+ ffc0 (enabled by phoenix)
+ decreases 302
+ stuff with 50a5 bit 04
+
+ ffc4 (enabled by phoenix)
+ decreases 303
+ stuff with 50a5 bit 08
+
+ ffc8 (enabled by phoenix)
+ decreases 304
+ stuff with 50a5 bit 10
+
+ ffcc (enabled by phoenix)
+ uses 307
+ stuff with 50a5 bit 20
+
+ ffd0
+ dead loop
+
+ ffd4 (enabled by all games)
+ main interrupt
+
+ ffd8
+ dead loop
+
+ ffdc
+ dead loop
+
+ ffe0
+ dead loop
+
+ ffe4
+ rti
+
+ ffe8
+ dead loop
+
+ ffec
+ dead loop
+
+ -----------------------
+
+ AIR BLASTER JOYSTICK
+
+ all these 60xx jumps expect bank 00 or 0e or 3a or 7d to be active, so IRQs must be masked
+
+ ffb0: jmp to 6000 (ends up jumping to pointer from RAM)
+ ffb4: jmp to e08e (stuff with 500c/500d/506e etc.)
+ ffb8: jmp to 601c (stub handler) (has function in bank 0e - writes 00 then 01 to 50a5)
+ ffbc: jmp to 602a (stub handler)
+ ffc0: jmp to 6038 (stub handler)
+ ffc4: jmp to 6046 (stub handler)
+ ffc8: jmp to 6054 (stub handler)
+ ffcc: jmp to 6062 (stub handler)
+ ffd0: jmp to 6070 (stub handler)
+ ffd4: jmp to 607e (valid code - main IRQ?)
+ ffd8: jmp to 608c (stub handler)
+ ffdc: jmp to 609a (stub handler)
+ ffe0: jmp to 60a8 (stub handler)
+ ffe4: jmp to 60b6 (stub handler)
+ ffe8: jmp to 60c4 (stub handler)
+ ffec: jmp to 60d2 (stub handler)
+
+ fff0: 7d
+
+ fffa: e0 60 (60e0 vector) (stub handler)
+ fffc: 88 e1 (e188 startup vector)
+ fffe: 02 e0 (e002 vector)
+
+
+ -----------------------
+
+ GOLDEN TEE HOME
+
+ ffb0 rti
+ ffb4 rti
+ ffb8 rti
+ ffbc rti
+
+ ffc0 rti
+ ffc4 rti
+ ffc8 rti
+ ffcc rti
+
+ ffd0 rti
+ ffd4 main irq?
+ ffd8 rti
+ ffdc rti
+
+ ffe0 something with 5045 bit 0x08 and 9d in ram (increase or decrease) (ADC interrupt)
+ ffe4 something with 5045 bit 0x20 and 9c in ram (increase of decrease) (ADC interrupt)
+
+ ffe8 rti
+ ffec rti
+
+ regular NMI (e3f0 - jump to ($19e2) which seems to point to rti, but could move..)
+ regular IRQ (e3f3 - points to rti)
+
+*/
+
+
+DEFINE_DEVICE_TYPE(ELAN_EU3A05_COMMONSYS, elan_eu3a05commonsys_device, "elan_eu3a05commonsys", "Elan EU3A05/EU3A14 Common System")
+
+
+elan_eu3a05commonsys_device::elan_eu3a05commonsys_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, type, tag, owner, clock),
+ m_cpu(*this, finder_base::DUMMY_TAG),
+ m_bank(*this, finder_base::DUMMY_TAG)
+{
+}
+
+elan_eu3a05commonsys_device::elan_eu3a05commonsys_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ elan_eu3a05commonsys_device(mconfig, ELAN_EU3A05_COMMONSYS, tag, owner, clock)
+{
+}
+
+void elan_eu3a05commonsys_device::device_start()
+{
+ save_item(NAME(m_rombank_lo));
+ save_item(NAME(m_rombank_hi));
+ save_item(NAME(m_intmask));
+ save_item(NAME(m_custom_irq));
+ save_item(NAME(m_custom_nmi));
+ save_item(NAME(m_custom_irq_vector));
+ save_item(NAME(m_custom_nmi_vector));
+}
+
+void elan_eu3a05commonsys_device::device_reset()
+{
+ // all interrupts disabled?
+ m_intmask[0] = 0x00;
+ m_intmask[1] = 0x00;
+
+ m_custom_irq = 0;
+ m_custom_irq_vector = 0x0000;
+
+ m_custom_nmi = 0;
+ m_custom_nmi_vector = 0x0000;
+
+ m_rombank_lo = 0x7f;
+ m_rombank_hi = 0x00;
+ m_bank->set_bank(0x7f);
+
+}
+
+READ8_MEMBER(elan_eu3a05commonsys_device::intmask_r)
+{
+ return m_intmask[offset];
+}
+
+WRITE8_MEMBER(elan_eu3a05commonsys_device::intmask_w)
+{
+ m_intmask[offset] = data;
+}
+
+
+void elan_eu3a05commonsys_device::generate_custom_interrupt(int level)
+{
+ // Air Blaster uses brk in the code, which is problematic for custom IRQs
+ // m_custom_irq = 1;
+ // m_custom_irq_vector = 0xffd4;
+ // m_maincpu->set_input_line(INPUT_LINE_IRQ0,HOLD_LINE);
+
+ // 5007 5008
+ // --ee --v- ssss ss-t
+ // 10 5432 10
+ // vector = 0xffb0 + 4 * bit position from right
+
+ // each bit seems to relate to an IRQ level
+ // v = vbl interrupt bit (vector 0xffd4)
+ // t = used for object movement (enemies / bullets) on air blaster chase levels (vector 0xffb0) needs to be frequent, timer? or hbl?
+ // s = sound channel related? (air blaster enables s1)
+ // e = 'event' interrupts (rad_gtg)
+
+ // vbl irq masking is important for air blaster or it will suffer from random crashes
+
+ uint16_t intmask = (m_intmask[0] << 8) | m_intmask[1];
+
+ if (intmask & (1 << level))
+ {
+ m_custom_nmi = 1;
+ m_custom_nmi_vector = 0xffb0 + level * 4;
+ m_cpu->pulse_input_line(INPUT_LINE_NMI, attotime::zero);
+ }
+}
+
+READ8_MEMBER(elan_eu3a05commonsys_device::nmi_vector_r)
+{
+ if (m_custom_nmi)
+ {
+ return m_custom_nmi_vector >> (offset*8);
+ }
+ else
+ {
+ fatalerror("NMI without custom vector!");
+ }
+}
+
+// not currently used
+READ8_MEMBER(elan_eu3a05commonsys_device::irq_vector_r)
+{
+ if (m_custom_irq)
+ {
+ return m_custom_irq_vector >> (offset*8);
+ }
+ else
+ {
+ fatalerror("IRQ without custom vector!");
+ }
+}
+
+
+WRITE8_MEMBER(elan_eu3a05commonsys_device::elan_eu3a05_rombank_w)
+{
+ if (offset == 0x00)
+ {
+ // written with the banking?
+ //logerror("%s: elan_eu3a05_rombank_hi_w (set ROM bank) %02x\n", machine().describe_context(), data);
+ m_rombank_hi = data;
+
+ m_bank->set_bank(m_rombank_lo | (m_rombank_hi << 8));
+ }
+ else
+ {
+ //logerror("%s: elan_eu3a05_rombank_lo_w (select ROM bank) %02x\n", machine().describe_context(), data);
+ m_rombank_lo = data;
+ }
+}
+
+READ8_MEMBER(elan_eu3a05commonsys_device::elan_eu3a05_rombank_r)
+{
+ if (offset == 0x00)
+ {
+ return m_rombank_hi;
+ }
+ else
+ {
+ return m_rombank_lo;
+ }
+}