summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author 0kmg <9137159+0kmg@users.noreply.github.com>2021-07-16 17:12:49 -0800
committer 0kmg <9137159+0kmg@users.noreply.github.com>2021-09-07 22:31:51 -0800
commitc092e80075d7069a1a597387e3029ac157808aff (patch)
treee99c8a14f4cfe1d12ee02576b0dbd398905973d9
parent972d324eb2463a8628a6a20234c66af520dd0b88 (diff)
bus/nes: Improved IRQ emulation for Kaiser KS202 and KS7032.
- Corrected IRQ behavior based on more recent PCB observations. Fixes some flickering on World X-Y interlevel screens in SMB2J bootleg. - Corrected SMB3 bootleg's banking, also per PCB analysis.
-rw-r--r--hash/nes.xml4
-rw-r--r--src/devices/bus/nes/kaiser.cpp117
-rw-r--r--src/devices/bus/nes/kaiser.h27
3 files changed, 82 insertions, 66 deletions
diff --git a/hash/nes.xml b/hash/nes.xml
index c01360d0bd6..909c1363771 100644
--- a/hash/nes.xml
+++ b/hash/nes.xml
@@ -74628,8 +74628,8 @@ Other
</part>
</software>
- <software name="smb3h1" cloneof="smb3" supported="partial">
- <description>Super Mario Bros. 3 (Pirate, Alt)</description>
+ <software name="smb3h1" cloneof="smb3">
+ <description>Super Mario Bros. 3 (pirate, alt)</description>
<year>19??</year>
<publisher>&lt;pirate&gt;</publisher>
<part name="cart" interface="nes_cart">
diff --git a/src/devices/bus/nes/kaiser.cpp b/src/devices/bus/nes/kaiser.cpp
index 8d738e5e389..ebe7d02972c 100644
--- a/src/devices/bus/nes/kaiser.cpp
+++ b/src/devices/bus/nes/kaiser.cpp
@@ -78,17 +78,17 @@ nes_ks7022_device::nes_ks7022_device(const machine_config &mconfig, const char *
{
}
-nes_ks7032_device::nes_ks7032_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, type, tag, owner, clock), m_latch(0), m_irq_count(0), m_irq_enable(0), irq_timer(nullptr)
+nes_ks7032_device::nes_ks7032_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, type, tag, owner, clock), m_latch(0), m_irq_count(0), m_irq_count_latch(0), m_irq_enable(0), irq_timer(nullptr)
{
}
-nes_ks7032_device::nes_ks7032_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_ks7032_device::nes_ks7032_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_ks7032_device(mconfig, NES_KS7032, tag, owner, clock)
{
}
-nes_ks202_device::nes_ks202_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_ks202_device::nes_ks202_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_ks7032_device(mconfig, NES_KS202, tag, owner, clock)
{
}
@@ -207,21 +207,22 @@ void nes_ks7032_device::device_start()
save_item(NAME(m_latch));
save_item(NAME(m_irq_enable));
save_item(NAME(m_irq_count));
+ save_item(NAME(m_irq_count_latch));
save_item(NAME(m_reg));
}
void nes_ks7032_device::pcb_reset()
{
m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg16_89ab(0);
- prg16_cdef(m_prg_chunks - 1);
chr8(0, m_chr_source);
m_latch = 0;
m_irq_enable = 0;
m_irq_count = 0;
- memset(m_reg, 0, sizeof(m_reg));
+ m_irq_count_latch = 0;
+ std::fill(std::begin(m_reg), std::end(m_reg), 0x00);
prg_update();
+ prg8_ef((m_prg_chunks << 1) - 1);
}
void nes_ks7016_device::device_start()
@@ -479,15 +480,15 @@ uint8_t nes_ks7022_device::read_h(offs_t offset)
Kaiser Board KS7032
- Games: A few FDS conversions like Bubble Bobble
- or SMB2
+ Games: FDS conversions of Bubble Bobble, SMB2,
+ and Exciting Soccer
- TODO: available dumps do not seem to use WRAM...
- yet m_reg[4] should switch WRAM bank... investigate!
+ These boards have a KS202 ASIC that provide both
+ banking and a cycle-based IRQ similar to the VRC3.
iNES: mapper 142
- In MAME: Supported?
+ In MAME: Supported.
-------------------------------------------------*/
@@ -497,14 +498,12 @@ void nes_ks7032_device::device_timer(emu_timer &timer, device_timer_id id, int p
{
if (m_irq_enable)
{
- if (m_irq_count == 0xffff)
+ if (++m_irq_count == 0)
{
+ set_irq_line(ASSERT_LINE);
m_irq_enable = 0;
- m_irq_count = 0;
- hold_irq_line();
+ m_irq_count = m_irq_count_latch;
}
- else
- m_irq_count++;
}
}
}
@@ -516,84 +515,100 @@ void nes_ks7032_device::prg_update()
prg8_cd(m_reg[3]);
}
-void nes_ks7032_device::ks7032_write(offs_t offset, uint8_t data)
+void nes_ks7032_device::write_h(offs_t offset, u8 data)
{
LOG_MMC(("ks7032_write, offset: %04x, data: %02x\n", offset, data));
switch (offset & 0x7000)
{
case 0x0000:
- m_irq_count = (m_irq_count & 0xfff0) | (data & 0x0f);
- break;
case 0x1000:
- m_irq_count = (m_irq_count & 0xff0f) | ((data & 0x0f) << 4);
- break;
case 0x2000:
- m_irq_count = (m_irq_count & 0xf0ff) | ((data & 0x0f) << 8);
- break;
case 0x3000:
- m_irq_count = (m_irq_count & 0x0fff) | ((data & 0x0f) << 12);
+ {
+ int shift = (offset >> 10);
+ m_irq_count_latch &= ~(0x000f << shift);
+ m_irq_count_latch |= (data & 0x0f) << shift;
break;
+ }
case 0x4000:
- m_irq_enable = 1;
+ m_irq_enable = BIT(data, 1);
+ if (m_irq_enable)
+ m_irq_count = m_irq_count_latch;
+ set_irq_line(CLEAR_LINE);
+ break;
+ case 0x5000:
+ set_irq_line(CLEAR_LINE);
break;
case 0x6000:
m_latch = data & 0x07;
break;
case 0x7000:
- m_reg[m_latch] = data;
+ m_reg[m_latch] = (m_reg[m_latch] & 0xf0) | (data & 0x0f);
prg_update();
break;
}
}
-uint8_t nes_ks7032_device::read_m(offs_t offset)
+u8 nes_ks7032_device::read_m(offs_t offset)
{
LOG_MMC(("ks7032 read_m, offset: %04x\n", offset));
- return m_prg[((m_reg[4] * 0x2000) + (offset & 0x1fff)) & (m_prg_size - 1)];
+ return m_prg[(m_reg[4] * 0x2000 + offset) & (m_prg_size - 1)];
}
/*-------------------------------------------------
- Kaiser Board KS202
+ Kaiser SMB3 Board with KS202
Games: Super Mario Bros. 3 (Pirate, Alt)
+ A chip, PAL16L8ANC, provides the extra bits overlaid
+ at 0xf000-0xffff. Writes go to both it and the KS202.
+
iNES: mapper 56
- In MAME: Supported?
+ In MAME: Supported.
+
+ TODO: This device needs renaming of some sort. KS202
+ is a chip found on some Kaiser PCBs that actually
+ provides the functionality implemented above in the
+ KS7032 PCB. It's not clear what SMB3's PCB is.
-------------------------------------------------*/
-void nes_ks202_device::write_h(offs_t offset, uint8_t data)
+void nes_ks202_device::write_h(offs_t offset, u8 data)
{
LOG_MMC(("ks202 write_h, offset: %04x, data: %02x\n", offset, data));
- switch (offset & 0x7000)
+ if (offset >= 0x7000)
{
- case 0x7000:
- m_reg[m_latch] = data;
- prg_update();
- switch (offset & 0xc00)
- {
- case 0x800:
- set_nt_mirroring(BIT(data, 0) ? PPU_MIRROR_VERT : PPU_MIRROR_HORZ);
- break;
- case 0xc00:
- chr1_x(offset & 0x07, data, CHRROM);
- break;
- }
- break;
- default:
- ks7032_write(offset, data);
- break;
+ switch (offset & 0xc00)
+ {
+ case 0x000:
+ if ((offset & 3) == 3)
+ prg8_ef((data & 0x10) | 0x0f);
+ else
+ {
+ int reg = (offset & 3) + 1;
+ m_reg[reg] = (m_reg[reg] & 0x0f) | (data & 0x10);
+ }
+ break;
+ case 0x800:
+ set_nt_mirroring(BIT(data, 0) ? PPU_MIRROR_VERT : PPU_MIRROR_HORZ);
+ break;
+ case 0xc00:
+ chr1_x(offset & 0x07, data & 0x7f, CHRROM);
+ break;
+ }
}
+
+ nes_ks7032_device::write_h(offset, data);
}
-uint8_t nes_ks202_device::read_m(offs_t offset)
+u8 nes_ks202_device::read_m(offs_t offset)
{
LOG_MMC(("ks202 read_m, offset: %04x\n", offset));
- return m_prgram[offset & 0x1fff];
+ return m_prgram[offset];
}
/*-------------------------------------------------
diff --git a/src/devices/bus/nes/kaiser.h b/src/devices/bus/nes/kaiser.h
index f76c018175e..690201233d0 100644
--- a/src/devices/bus/nes/kaiser.h
+++ b/src/devices/bus/nes/kaiser.h
@@ -73,27 +73,28 @@ class nes_ks7032_device : public nes_nrom_device
{
public:
// construction/destruction
- nes_ks7032_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_ks7032_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual uint8_t read_m(offs_t offset) override;
- void ks7032_write(offs_t offset, uint8_t data);
- virtual void write_h(offs_t offset, uint8_t data) override { ks7032_write(offset, data); }
+ virtual u8 read_m(offs_t offset) override;
+ virtual void write_h(offs_t offset, u8 data) override;
virtual void pcb_reset() override;
protected:
- nes_ks7032_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+ // construction/destruction
+ nes_ks7032_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
// device-level overrides
virtual void device_start() override;
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
- void prg_update();
+ u8 m_reg[8];
- uint8_t m_latch;
- uint8_t m_reg[8];
+private:
+ void prg_update();
+ u8 m_latch;
- uint16_t m_irq_count;
+ u16 m_irq_count, m_irq_count_latch;
int m_irq_enable;
static const device_timer_id TIMER_IRQ = 0;
@@ -107,11 +108,10 @@ class nes_ks202_device : public nes_ks7032_device
{
public:
// construction/destruction
- nes_ks202_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_ks202_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- // device-level overrides
- virtual uint8_t read_m(offs_t offset) override;
- virtual void write_h(offs_t offset, uint8_t data) override;
+ virtual u8 read_m(offs_t offset) override;
+ virtual void write_h(offs_t offset, u8 data) override;
};
@@ -129,6 +129,7 @@ public:
virtual void pcb_reset() override;
protected:
+ // construction/destruction
nes_ks7016_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u8 mask);
// device-level overrides