Interrupt disrupting my MMC1 bankswap

Discuss technical or other issues relating to programming the Nintendo Entertainment System, Famicom, or compatible systems.

Moderator: Moderators

Post Reply
Pennywise
Posts: 70
Joined: Tue Jul 14, 2009 11:04 am

Interrupt disrupting my MMC1 bankswap

Post by Pennywise » Tue Oct 27, 2020 7:44 pm

So, I've expanded a ROM to 512kb and basically made it into the mapper variant where there's basically 2 256kb ROMs and when I execute the code to switch between, I sometimes get an interrupt, which breaks my hack. I've been able to accommodate for the interrupt and basically have the routine reset in such a case, but the bank swap no longer works. Would anyone know why this is happening? Do I perhaps need to reset the register or something? Here's my current code:

LDA $8015,Y
STA $0044
CPY #$0A
BCC $D644
LDA #$01
STA $0006
LDA #$10
STA $A000
LSR
STA $A000
LSR
STA $A000
LSR
STA $A000
LSR
STA $A000
LDA $0006
CMP #$01
BNE $D619
LDA #$00
STA $0006
LDA #$01
STA $0326
STY $0327
RTS

lidnariq
Posts: 10073
Joined: Sun Apr 13, 2008 11:12 am
Location: Seattle

Re: Interrupt disrupting my MMC1 bankswap

Post by lidnariq » Tue Oct 27, 2020 7:55 pm

This official oversize MMC1 definition is problematic for these reasons, as you're finding.

If you genuinely mean IRQ (and not NMI), you might be able to get away with just protecting your code with SEI/CLI.

Alternatively, it might be easier in the end to mapper hack whatever game you're working on to something that natively supports 512KB PRG, such as MMC3, FME-7, or Namco 340.

Fiskbit
Posts: 238
Joined: Sat Nov 18, 2017 9:15 pm

Re: Interrupt disrupting my MMC1 bankswap

Post by Fiskbit » Thu Oct 29, 2020 6:39 pm

The code you've posted makes it a bit hard to be sure what's going on, since it's lacking addresses (so branch targets are unspecified) and the interrupt handler isn't present. That said, you'll need to be resetting the shift register both unconditionally in the interrupt before writing to MMC1 (because the handler may have interrupted a set of 5 MMC1 writes) and in the code you posted in the case where you detect an interrupt occurred. Note that this also sets the MMC1 mode such that the last bank is fixed at $C000-FFFF, which may be a problem if you're using a less common mode. It should look similar to this:

Code: Select all

SwapRomHalf:
; Clear the MMC1 interrupted flag so we know if our register writes are interrupted.
; Interrupt handlers must set this if writing to MMC1.
LDA #$00
STA mmc1_interrupted

LDA #$10
STA $A000
LSR
STA $A000
LSR
STA $A000
LSR
STA $A000
LSR
STA $A000

; If the flag is still clear, we're good.
LDA mmc1_interrupted
BEQ +

; The flag is set, so we were interrupted and should assume our write did not go through.
; Reset the shift register and try again.
LDA #$80
STA $A000
JMP SwapRomHalf

+
(There's no need to clear the mmc1_interrupted flag afterward because it gets explicitly cleared before it's used.)

Pennywise
Posts: 70
Joined: Tue Jul 14, 2009 11:04 am

Re: Interrupt disrupting my MMC1 bankswap

Post by Pennywise » Fri Oct 30, 2020 11:31 am

I ended up basically copying what the game does to handle interrupts interrupting MMC1 register writes.

Basically if the code detects an interrupt has occurred, it will write #$FF to the register and restart the writes over again. It seems to be doing the trick.

Post Reply