From 66ae0c6ab9f193762ffb2a9bb4eb237f3ce4c11d Mon Sep 17 00:00:00 2001 From: Fabio Priuli Date: Thu, 25 Apr 2013 10:14:13 +0000 Subject: [PATCH] (MESS) NES IRQ clean up part 2: Konami IRQs are now implemented based on the docs and not kludged (in particular, now they are cycle based too). nw. + a minor fix for NT restore... --- src/mess/machine/nes_konami.c | 123 +++++++++++++++++++++++++++------ src/mess/machine/nes_konami.h | 63 ++++++++++------- src/mess/machine/nes_slot.c | 2 +- src/mess/machine/nes_sunsoft.c | 12 ++-- 4 files changed, 145 insertions(+), 55 deletions(-) diff --git a/src/mess/machine/nes_konami.c b/src/mess/machine/nes_konami.c index 04991bceaff..7dedaa7d399 100644 --- a/src/mess/machine/nes_konami.c +++ b/src/mess/machine/nes_konami.c @@ -62,28 +62,28 @@ nes_konami_vrc2_device::nes_konami_vrc2_device(const machine_config &mconfig, co { } -nes_konami_vrc3_device::nes_konami_vrc3_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) - : nes_nrom_device(mconfig, type, name, tag, owner, clock, shortname, source) -{ -} - nes_konami_vrc3_device::nes_konami_vrc3_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : nes_nrom_device(mconfig, NES_VRC3, "NES Cart Konami VRC-3 PCB", tag, owner, clock, "nes_vrc3", __FILE__) { } +nes_konami_vrc4_device::nes_konami_vrc4_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) + : nes_nrom_device(mconfig, type, name, tag, owner, clock, shortname, source) +{ +} + nes_konami_vrc4_device::nes_konami_vrc4_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : nes_konami_vrc3_device(mconfig, NES_VRC4, "NES Cart Konami VRC-4 PCB", tag, owner, clock, "nes_vrc4", __FILE__) + : nes_nrom_device(mconfig, NES_VRC4, "NES Cart Konami VRC-4 PCB", tag, owner, clock, "nes_vrc4", __FILE__) { } nes_konami_vrc6_device::nes_konami_vrc6_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : nes_konami_vrc3_device(mconfig, NES_VRC6, "NES Cart Konami VRC-6 PCB", tag, owner, clock, "nes_vrc6", __FILE__) + : nes_konami_vrc4_device(mconfig, NES_VRC6, "NES Cart Konami VRC-6 PCB", tag, owner, clock, "nes_vrc6", __FILE__) { } nes_konami_vrc7_device::nes_konami_vrc7_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : nes_konami_vrc3_device(mconfig, NES_VRC7, "NES Cart Konami VRC-7 PCB", tag, owner, clock, "nes_vrc7", __FILE__) + : nes_konami_vrc4_device(mconfig, NES_VRC7, "NES Cart Konami VRC-7 PCB", tag, owner, clock, "nes_vrc7", __FILE__) { } @@ -126,6 +126,10 @@ void nes_konami_vrc2_device::pcb_reset() void nes_konami_vrc3_device::device_start() { common_start(); + irq_timer = timer_alloc(TIMER_IRQ); + irq_timer->adjust(attotime::zero, 0, machine().device("maincpu")->cycles_to_attotime(1)); + + save_item(NAME(m_irq_mode)); save_item(NAME(m_irq_enable)); save_item(NAME(m_irq_enable_latch)); save_item(NAME(m_irq_count)); @@ -139,6 +143,7 @@ void nes_konami_vrc3_device::pcb_reset() prg16_cdef(m_prg_chunks - 1); chr8(0, m_chr_source); + m_irq_mode = 0; m_irq_enable = 0; m_irq_enable_latch = 0; m_irq_count = 0; @@ -149,7 +154,11 @@ void nes_konami_vrc3_device::pcb_reset() void nes_konami_vrc4_device::device_start() { common_start(); + irq_timer = timer_alloc(TIMER_IRQ); + irq_timer->adjust(attotime::zero, 0, machine().device("maincpu")->cycles_to_attotime(1)); + save_item(NAME(m_irq_mode)); + save_item(NAME(m_irq_prescale)); save_item(NAME(m_irq_enable)); save_item(NAME(m_irq_enable_latch)); save_item(NAME(m_irq_count)); @@ -167,6 +176,7 @@ void nes_konami_vrc4_device::pcb_reset() chr8(0, m_chr_source); m_irq_mode = 0; + m_irq_prescale = 341; m_irq_enable = 0; m_irq_enable_latch = 0; m_irq_count = 0; @@ -182,6 +192,11 @@ void nes_konami_vrc7_device::device_start() m_ym2413 = device().subdevice("ym"); common_start(); + irq_timer = timer_alloc(TIMER_IRQ); + irq_timer->adjust(attotime::zero, 0, machine().device("maincpu")->cycles_to_attotime(1)); + + save_item(NAME(m_irq_mode)); + save_item(NAME(m_irq_prescale)); save_item(NAME(m_irq_enable)); save_item(NAME(m_irq_enable_latch)); save_item(NAME(m_irq_count)); @@ -197,6 +212,8 @@ void nes_konami_vrc7_device::pcb_reset() prg8_ef(0xff); chr8(0, m_chr_source); + m_irq_mode = 0; + m_irq_prescale = 341; m_irq_enable = 0; m_irq_enable_latch = 0; m_irq_count = 0; @@ -333,18 +350,37 @@ WRITE8_MEMBER(nes_konami_vrc2_device::write_h) iNES: mapper 73 - In MESS: Supported. It also uses konami_irq. + In MESS: Supported. -------------------------------------------------*/ -void nes_konami_vrc3_device::hblank_irq(int scanline, int vblank, int blanked) +void nes_konami_vrc3_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) { - /* Increment & check the IRQ scanline counter */ - if (m_irq_enable && (++m_irq_count == 0x100)) + if (id == TIMER_IRQ) { - m_irq_count = m_irq_count_latch; - m_irq_enable = m_irq_enable_latch; - machine().device("maincpu")->execute().set_input_line(M6502_IRQ_LINE, HOLD_LINE); + if (m_irq_enable) + { + if (m_irq_mode) // 8bits mode + { + if ((m_irq_count & 0x00ff) == 0xff) + { + machine().device("maincpu")->execute().set_input_line(M6502_IRQ_LINE, HOLD_LINE); + m_irq_count = m_irq_count_latch; + } + else + m_irq_count = (m_irq_count & 0xff00) | ((m_irq_count & 0x00ff) + 1); + } + else // 16bits mode + { + if (m_irq_count == 0xffff) + { + machine().device("maincpu")->execute().set_input_line(M6502_IRQ_LINE, HOLD_LINE); + m_irq_count = m_irq_count_latch; + } + else + m_irq_count++; + } + } } } @@ -355,21 +391,26 @@ WRITE8_MEMBER(nes_konami_vrc3_device::write_h) switch (offset & 0x7000) { case 0x0000: + m_irq_count_latch = (m_irq_count_latch & 0xfff0) | ((data & 0x0f) << 0); + break; case 0x1000: - /* dunno which address controls these */ - m_irq_count_latch = data; - m_irq_enable_latch = data; + m_irq_count_latch = (m_irq_count_latch & 0xff0f) | ((data & 0x0f) << 4); break; case 0x2000: - m_irq_enable = data; + m_irq_count_latch = (m_irq_count_latch & 0xf0ff) | ((data & 0x0f) << 8); break; case 0x3000: - m_irq_count &= ~0x0f; - m_irq_count |= data & 0x0f; + m_irq_count_latch = (m_irq_count_latch & 0x0fff) | ((data & 0x0f) << 12); break; case 0x4000: - m_irq_count &= ~0xf0; - m_irq_count |= (data & 0x0f) << 4; + m_irq_mode = data & 0x04; + m_irq_enable = data & 0x02; + m_irq_enable_latch = data & 0x01; + if (data & 0x02) + m_irq_count = m_irq_count_latch; + break; + case 0x5000: + m_irq_enable = m_irq_enable_latch; break; case 0x7000: prg16_89ab(data); @@ -388,6 +429,42 @@ WRITE8_MEMBER(nes_konami_vrc3_device::write_h) -------------------------------------------------*/ +void nes_konami_vrc4_device::irq_tick() +{ + if (m_irq_count == 0xff) + { + m_irq_count = m_irq_count_latch; + machine().device("maincpu")->execute().set_input_line(M6502_IRQ_LINE, HOLD_LINE); + } + else + m_irq_count++; +} + +void nes_konami_vrc4_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + if (id == TIMER_IRQ) + { + if (m_irq_enable) + { + if (m_irq_mode) // cycle mode + irq_tick(); + else // scanline mode + { + // A prescaler divides the passing CPU cycles by 114, 114, then 113 (and repeats that order). + // This approximates 113+2/3 CPU cycles, which is one NTSC scanline. + // Since this is a CPU-based IRQ, though, it is triggered also during non visible scanlines... + if (m_irq_prescale < 3) + { + m_irq_prescale += 341; + irq_tick(); + } + + m_irq_prescale -= 3; + } + } + } +} + void nes_konami_vrc4_device::set_prg() { if (m_latch & 0x02) diff --git a/src/mess/machine/nes_konami.h b/src/mess/machine/nes_konami.h index ef36d5d4eaf..546228cf183 100644 --- a/src/mess/machine/nes_konami.h +++ b/src/mess/machine/nes_konami.h @@ -51,47 +51,60 @@ class nes_konami_vrc3_device : public nes_nrom_device { public: // construction/destruction - nes_konami_vrc3_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source); nes_konami_vrc3_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); // device-level overrides virtual void device_start(); - virtual DECLARE_WRITE8_MEMBER(write_h); - - virtual void hblank_irq(int scanline, int vblank, int blanked); - virtual void pcb_reset(); - -protected: - UINT16 m_irq_count, m_irq_count_latch; - int m_irq_enable, m_irq_enable_latch; - int m_irq_mode; // used by VRC-4, VRC-6 & VRC-7. currently not implemented: 0 = prescaler mode / 1 = CPU mode -}; - - -// ======================> nes_konami_vrc4_device - -class nes_konami_vrc4_device : public nes_konami_vrc3_device -{ -public: - // construction/destruction - nes_konami_vrc4_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); - - // device-level overrides - virtual void device_start(); + virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr); virtual DECLARE_WRITE8_MEMBER(write_h); virtual void pcb_reset(); private: + UINT16 m_irq_count, m_irq_count_latch; + int m_irq_enable, m_irq_enable_latch; + int m_irq_mode; + + static const device_timer_id TIMER_IRQ = 0; + emu_timer *irq_timer; +}; + + +// ======================> nes_konami_vrc4_device + +class nes_konami_vrc4_device : public nes_nrom_device +{ +public: + // construction/destruction + nes_konami_vrc4_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source); + nes_konami_vrc4_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + + // device-level overrides + virtual void device_start(); + virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr); + virtual DECLARE_WRITE8_MEMBER(write_h); + + virtual void pcb_reset(); + +protected: void set_prg(); UINT8 m_mmc_vrom_bank[8]; UINT8 m_latch, m_mmc_prg_bank; + + void irq_tick(); + UINT16 m_irq_count, m_irq_count_latch; + int m_irq_enable, m_irq_enable_latch; + int m_irq_mode; + int m_irq_prescale; + + static const device_timer_id TIMER_IRQ = 0; + emu_timer *irq_timer; }; // ======================> nes_konami_vrc6_device -class nes_konami_vrc6_device : public nes_konami_vrc3_device +class nes_konami_vrc6_device : public nes_konami_vrc4_device { public: // construction/destruction @@ -106,7 +119,7 @@ public: // ======================> nes_konami_vrc7_device -class nes_konami_vrc7_device : public nes_konami_vrc3_device +class nes_konami_vrc7_device : public nes_konami_vrc4_device { public: // construction/destruction diff --git a/src/mess/machine/nes_slot.c b/src/mess/machine/nes_slot.c index 583b5cefa8e..62c1447a24e 100644 --- a/src/mess/machine/nes_slot.c +++ b/src/mess/machine/nes_slot.c @@ -734,7 +734,7 @@ void device_nes_cart_interface::nes_banks_restore() chr1_x(i, m_chr_orig[i] / 0x400, m_chr_src[i]); for (int i = 0; i < 4; i++) - set_nt_page(i, m_nt_src[i], m_nt_orig[i], m_nt_writable[i]); + set_nt_page(i, m_nt_src[i], m_nt_orig[i] / 0x400, m_nt_writable[i]); set_nt_mirroring(m_mirroring); } diff --git a/src/mess/machine/nes_sunsoft.c b/src/mess/machine/nes_sunsoft.c index 0c954d91634..6db79f3e89c 100644 --- a/src/mess/machine/nes_sunsoft.c +++ b/src/mess/machine/nes_sunsoft.c @@ -314,12 +314,12 @@ WRITE8_MEMBER(nes_sunsoft_3_device::write_h) break; case 0x6800: switch (data & 3) - { - case 0x00: set_nt_mirroring(PPU_MIRROR_VERT); break; - case 0x01: set_nt_mirroring(PPU_MIRROR_HORZ); break; - case 0x02: set_nt_mirroring(PPU_MIRROR_LOW); break; - case 0x03: set_nt_mirroring(PPU_MIRROR_HIGH); break; - } + { + case 0x00: set_nt_mirroring(PPU_MIRROR_VERT); break; + case 0x01: set_nt_mirroring(PPU_MIRROR_HORZ); break; + case 0x02: set_nt_mirroring(PPU_MIRROR_LOW); break; + case 0x03: set_nt_mirroring(PPU_MIRROR_HIGH); break; + } break; case 0x7800: prg16_89ab(data);