It seems that in order to run the routines at the same address, the patched code must be in bank zero in order to execute interrupts properly. And this will give little space for the snes init and IO emulation code, it will be in another bank.
Bank 0: patched PRG ROM
Bank 1: original PRG ROM for data
Bank 2: init and IO snes code
It boots on bank zero where it goes to code installed in a data 'hole' and then to the nes init vector:
Code: Select all
free@:
sei ; native mode
clc
xce
jml SnesInit ; long jump to the other bank
Then it initialises everything in SnesInit form bank 2, and calls jml EndSnesInit
Code: Select all
EndSnesInit:
sec
xce ; emulation mode
jmp NesInitVector
This will take 11bytes somewhere in the bank zero
And the BRK code will work on the same principle, jumping to bank 2 in native mode and going back to bank 0 for an RTS in emulation mode.
The other solution if I want to run the nes prg from another bank, is to replace the rti instructions with a custom code going back to the proper bank. I found out that all the 256 65C816 instructions are available in emulation, maybe it can help.
Having the patched prg rom in bank 1 or 2 would make interrupts easier (Reset, NMI and BRK). I prefer this solution, but I must find a clean way to 'rti' back to the original code once in bank 0.
Edit: When an interrupt occurs in emulation from a PRG bank other than bank 0, the original bank is lost. Following the Programer's manual, a long jump to the rti in the original bank will work, restoring the bank number.
And for BRK, the rti will return on the byte after the BRK opcode, hence on the last "parameter" byte. And therefore, a pull of registers and a long jump to the saved return address + 2 should do it. The tricky part is to do it while in emulation mode???
Edit2:
I tried this code
Code: Select all
sec
xce ; Emulation
jml next
.ENDS
.BANK 3
.ORG 0
.SECTION "Other"
next:
And it compiles, I assume that a long jump works also in emulation. And because it does not change the status registers it could be used to go to a static address like the nes reset vector while in emulation.
And the "Absolute Indirect Long Addressing" jump could be used to come back from a BRK while in emulation.
This looks promising, it would allow to have the SMB1 patched PRG in bank 1 or 2 and run the emulation on bank 0.
Bank 0: init and IO snes code (executed in native mode, no interrupts in native mode)
Bank 1: patched PRG ROM (executed in emulation mode, interrupts go to the bank 0 vector routines which return to bank 1)
Bank 2: original PRG ROM for data