diff options
Diffstat (limited to 'src/mame/machine/elan_eu3a05commonsys.cpp')
-rw-r--r-- | src/mame/machine/elan_eu3a05commonsys.cpp | 307 |
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; + } +} |