So I got MMC5 wrapped up enough to run Castlevania 3 with the exception of the vertical scrolling that crops up right in the beginning. I've seen this posted several times before and ran through all suggested fixes with no luck, so I'm wondering if my issue is different/deeper. Here's what I'm seeing:
And here's the relevant code:
MMC5
PPU
CPU
I note the CPU code up above because it was mentioned before in a similar post that the author wasn't handling maskable interrupts correctly.
Edit: Also worth noting, the screenshot is immediately when the screen loads up, so it looks like the proper background gets rendered insanely late.
And here's the relevant code:
MMC5
Code:
...
case 0x5203:
// IRQ Counter
m.IrqLatch = int(v)
m.IrqCounter = 0
case 0x5204:
if !m.IrqEnabled {
m.IrqEnabled = (v&0x80 == 0x80)
}
...
func (m *Mmc5) ReadIrqStatus() Word {
m.IrqStatus &= 0x7F
return m.IrqStatus
}
func (m *Mmc5) AcknowledgeIrq() {
m.IrqStatus &= 0x7F
}
func (m *Mmc5) NotifyScanline() {
if ppu.inScanline() {
if ppu.renderingEnabled() {
if m.IrqStatus&0x40 == 0x0 {
m.IrqStatus = 0x40
m.IrqCounter = 0
} else {
m.IrqCounter++
if m.IrqCounter == m.IrqLatch {
cpu.RequestInterrupt(InterruptIrq)
m.IrqStatus |= 0x80
}
}
} else {
m.IrqStatus &= 0xBF
}
}
}
case 0x5203:
// IRQ Counter
m.IrqLatch = int(v)
m.IrqCounter = 0
case 0x5204:
if !m.IrqEnabled {
m.IrqEnabled = (v&0x80 == 0x80)
}
...
func (m *Mmc5) ReadIrqStatus() Word {
m.IrqStatus &= 0x7F
return m.IrqStatus
}
func (m *Mmc5) AcknowledgeIrq() {
m.IrqStatus &= 0x7F
}
func (m *Mmc5) NotifyScanline() {
if ppu.inScanline() {
if ppu.renderingEnabled() {
if m.IrqStatus&0x40 == 0x0 {
m.IrqStatus = 0x40
m.IrqCounter = 0
} else {
m.IrqCounter++
if m.IrqCounter == m.IrqLatch {
cpu.RequestInterrupt(InterruptIrq)
m.IrqStatus |= 0x80
}
}
} else {
m.IrqStatus &= 0xBF
}
}
}
PPU
Code:
...
// Last tick of a scanline
if p.Cycle == 341 {
if m, ok := rom.(*Mmc5); ok {
m.NotifyScanline()
}
p.Cycle = 0
p.Scanline++
}
...
// Last tick of a scanline
if p.Cycle == 341 {
if m, ok := rom.(*Mmc5); ok {
m.NotifyScanline()
}
p.Cycle = 0
p.Scanline++
}
...
CPU
Code:
case InterruptIrq:
if !c.getIrqDisable() {
c.PerformIrq()
c.InterruptRequested = InterruptNone
}
if !c.getIrqDisable() {
c.PerformIrq()
c.InterruptRequested = InterruptNone
}
I note the CPU code up above because it was mentioned before in a similar post that the author wasn't handling maskable interrupts correctly.
Edit: Also worth noting, the screenshot is immediately when the screen loads up, so it looks like the proper background gets rendered insanely late.