Switching Banks Made Easy?
THIS IS KINDA TECHNICAL, I suppose.While I don't expect to ever actually complete a VCS Metroid port, for various reasons, I am going forward with it right now. I've targeted it for a 32K cart, and I've been thinking a bit about the best way to switch banks.This is what I've come up with:Call a subroutine in another bank with this code:
brk .word Subroutine
Have the break vector point to this subroutine (copied in every bank):
plp
tsx
inx
dec $00,X
lda ($00, X
sta MiscPtr
inc $00,X
lda ($00,X)
sta MiscPtr+1
lsr
lsr
lsr
lsr
lsr
tax
nop $1FF4,X
Assuming I had ORGed all my banks to addresses of this form:
0xxxxx, 1xxxxx, %010xxxxx, %011xxxxx, etc.
This would switch to another bank, and at that point the program would encounter this code:
jmp (MiscPtr)
Which would begin the subroutine. At the end of the subroutine I would have this code:
jmp ReturnFromBSSubroutine
Which would go here:
ReturnFromBSSubroutine
tsx
inx
inx
lda $00,X ;get high byte of return address
lsr
lsr
lsr
lsr
lsr
tax
nop $1FF4,X
Which would switch banks to this address:
rts
I suppose I could do all this with a JSR instruction also, and save the BRK vector for something else...Anyway. Assuming that this all works (I just dreamed it up this morning, so who knows), it would have these advantages:
1. I wouldn't need to maintain tables of jump addresses in multiple banks.
2. I could move subroutines around freely without having to find and change all the entry/exit points.
3. It is really easy to use. In every bank, at any point, just one opcode plus an address.
4. It uses 4 bytes of RAM: 2 on the stack plus 2 for MiscPtr. If those 4 are contiguous. If not, it takes 5 (since BRK also pushes the flags). Could use JSR to avoid pushing the flags.
Disadvantages:
1. It takes a loooooong time to switch banks. Almost a whole scanline to go to a subroutine and almost half a scanline to come back.
2. I don't have to duplicate any tables, but I do have to duplicate all that code in every bank.
3. Probably something else.
Basically, I want to avoid the issues I had with Reindeer Runner, where I used a really stupid way to switch banks, which backfired on me when I ended up having to move things from one bank to another.
Anybody else have any better ways to do this? I'm looking for a method that:
1. Allows me to call subroutines in other banks and return to the point from which they were called.
2. Not have to maintain and duplicate tables of jump addresses, though that isn't a deal-killer
3. Is fast.
4. Doesn't use a ton of RAM.
5. Allows me to move subroutines around (from bank to bank) without having to spend an hour tracking down and changing jmp addresses.
3 Comments
Recommended Comments