From bf2309aa290c4b432c3e048d4d8d49688f201c65 Mon Sep 17 00:00:00 2001 From: Nathan Woods Date: Sun, 19 Mar 2017 17:37:57 -0400 Subject: [CoCo 3] Fixed an issue clearing interrupts on the GIME implementation The normal way to acknowledge a GIME interrupt is by reading from $FF92/3. However, the act of disabling interrupts by writing to the same registers will also do the trick, and we were not emulating this technique. Thanks to Glen Hewlett and Tim Lindner for helping to identify this problem --- src/mame/video/gime.cpp | 84 ++++++++++++++++++++++++++----------------------- src/mame/video/gime.h | 8 ++--- 2 files changed, 49 insertions(+), 43 deletions(-) diff --git a/src/mame/video/gime.cpp b/src/mame/video/gime.cpp index a4ccfdd9419..d79eb39f2a6 100644 --- a/src/mame/video/gime.cpp +++ b/src/mame/video/gime.cpp @@ -624,15 +624,15 @@ uint8_t gime_base_device::read(offs_t offset) switch(offset & 0xF0) { case 0x00: - data = read_gime_register(offset); + data = read_gime_register(offset); // $FF90 - $FF9F break; case 0x10: - data = read_mmu_register(offset); + data = read_mmu_register(offset); // $FFA0 - $FFAF break; case 0x20: - data = read_palette_register(offset); + data = read_palette_register(offset); // $FFB0 - $FFBF break; default: @@ -656,22 +656,14 @@ inline uint8_t gime_base_device::read_gime_register(offs_t offset) uint8_t result; switch(offset) { - case 2: // read pending IRQs + case 2: // $FF92 - read pending IRQs result = m_irq; - if (result != 0x00) - { - m_irq = 0x00; - recalculate_irq(); - } + change_gime_irq(0x00); break; - case 3: // read pending FIRQs + case 3: // $FF93 - read pending FIRQs result = m_firq; - if (result != 0x00) - { - m_firq = 0x00; - recalculate_firq(); - } + change_gime_firq(0x00); break; #ifdef NOPE_NOT_READABLE @@ -741,20 +733,20 @@ void gime_base_device::write(offs_t offset, uint8_t data) switch(offset & 0xF0) { case 0x00: - write_gime_register(offset & 0x0F, data); + write_gime_register(offset & 0x0F, data); // $FF90 - $FF9F break; case 0x10: - write_mmu_register(offset & 0x0F, data); + write_mmu_register(offset & 0x0F, data); // $FFA0 - $FFAF break; case 0x20: - write_palette_register(offset & 0x0F, data & 0x3F); + write_palette_register(offset & 0x0F, data & 0x3F); // $FFB0 - $FFBF break; case 0x30: case 0x40: - write_sam_register(offset - 0x30); + write_sam_register(offset - 0x30); // $FFC0 - $FFDF break; } } @@ -836,6 +828,13 @@ inline void gime_base_device::write_gime_register(offs_t offset, uint8_t data) (data & 0x02) ? "EI1 " : "", (data & 0x01) ? "EI0 " : ""); } + + // While normally interrupts are acknowledged by reading from this + // register and not writing to it, the act of disabling these interrupts + // has the exact same effect + // + // Kudos to Glen Hewlett for identifying this problem + change_gime_irq(m_irq & data); break; case 0x03: @@ -859,6 +858,13 @@ inline void gime_base_device::write_gime_register(offs_t offset, uint8_t data) (data & 0x02) ? "EI1 " : "", (data & 0x01) ? "EI0 " : ""); } + + // While normally interrupts are acknowledged by reading from this + // register and not writing to it, the act of disabling these interrupts + // has the exact same effect + // + // Kudos to Glen Hewlett for identifying this problem + change_gime_firq(m_firq & data); break; case 0x04: @@ -1041,52 +1047,52 @@ inline void gime_base_device::write_sam_register(offs_t offset) } - //------------------------------------------------- // interrupt_rising_edge //------------------------------------------------- void gime_base_device::interrupt_rising_edge(uint8_t interrupt) { - /* evaluate IRQ */ + // evaluate IRQ if ((m_gime_registers[0x00] & 0x20) && (m_gime_registers[0x02] & interrupt)) - { - m_irq |= interrupt; - recalculate_irq(); - } + change_gime_irq(m_irq | interrupt); - /* evaluate FIRQ */ + // evaluate FIRQ if ((m_gime_registers[0x00] & 0x10) && (m_gime_registers[0x03] & interrupt)) - { - m_firq |= interrupt; - recalculate_firq(); - } + change_gime_firq(m_firq | interrupt); } - //------------------------------------------------- -// recalculate_irq +// change_gime_irq //------------------------------------------------- -void gime_base_device::recalculate_irq(void) +void gime_base_device::change_gime_irq(uint8_t data) { - m_write_irq(irq_r()); + // did the value actually change? + if (m_irq != data) + { + m_irq = data; + m_write_irq(irq_r()); + } } - //------------------------------------------------- -// recalculate_firq +// change_gime_firq //------------------------------------------------- -void gime_base_device::recalculate_firq(void) +void gime_base_device::change_gime_firq(uint8_t data) { - m_write_firq(firq_r()); + // did the value actually change? + if (m_firq != data) + { + m_firq = data; + m_write_firq(firq_r()); + } } - //************************************************************************** // VIDEO STATE //************************************************************************** diff --git a/src/mame/video/gime.h b/src/mame/video/gime.h index 3e141df22a4..52e4aeca021 100644 --- a/src/mame/video/gime.h +++ b/src/mame/video/gime.h @@ -82,8 +82,8 @@ public: bool update_rgb(bitmap_rgb32 &bitmap, const rectangle &cliprect); // interrupt outputs - bool firq_r(void) { return m_firq != 0x00; } - bool irq_r(void) { return m_irq != 0x00; } + bool firq_r() const { return m_firq != 0x00; } + bool irq_r() const { return m_irq != 0x00; } // interrupt inputs void set_il0(bool value) { set_interrupt_value(INTERRUPT_EI0, value); } @@ -233,8 +233,8 @@ private: // interrupts void interrupt_rising_edge(uint8_t interrupt); - void recalculate_irq(void); - void recalculate_firq(void); + void change_gime_irq(uint8_t data); + void change_gime_firq(uint8_t data); ATTR_FORCE_INLINE void set_interrupt_value(uint8_t interrupt, bool value) { -- cgit v1.2.3