Other than I/O ports for PPU, vectors, service routines, and program code, should there be any specific values saved in memory? Looking at the iNES rom for Super Mario Brothers, there are the following instructions after the header:
Code: Select all
LDA $2020 ; contents of A now 0x00
BPL FB ; branch is not taken
LDA $2020 ; contents of A still 0x00
BPL FB ; branch is not taken (A is not negative)
LDA ($07D7, X) ; contents of A still 0x00
CMP #0A ; 0x00 - 0x0A
BCS 0C ; branch is not taken (carry not set)
BPL F6 ; Branch is taken, but the offset is a large negative which throws PC below the beginning of ROM
I initialize all values of memory to 0x00 before I load in the ROM and setup interrupt vectors and handlers.
Is the rom expecting values at address $2020 and $07DC? Is it supposed to send PC below the starting point of the ROM because the BPL is checking the flag after a DEX which is still positive?
Or should one of the previous branches be taken?
The problem is you shouldn't be executing those instructions at all (they look to me like data disassembled as code)
. The 6502 starts execution at the address pointed to by the RESET vector, not at the start of the ROM. Also, there's something wrong with your disassembly; LDA ($07D7, X)
isn't a valid 6502 addressing mode. Indirect addresses are always 8-bit zero page addresses except for the JMP
EDIT: whoops, the reset vector in SMB1 does point to $8000 so those are the right instructions; multiple errors in your disassembly just made it look like garbage code to me.
should be LDA $2002
, which is a PPU register.
should be LDA $07D7,X
(plain indexed addressing, not indirect)
Yes, the game really is reading from uninitialized memory here. What it's doing is detecting a cold or warm boot. If it's a warm boot (the reset button was pressed) then the previous high score is retained (the RAM starting at $07D7 contains the high score, stored as one decimal digit per byte) If it's a cold boot (the console was just powered on and RAM contains garbage) then the high score is reset to a default value.
Finally BPL $F6
isn't a "large branch", it's a branch by -10 which goes back to the LDA $07D7,X
instruction. Branch displacements are twos complement: $FF is -1, $FE is -2, $FD is -3, and so on up to $80 which is -128. If you're programming in modern C or C++ you can just cast the operand to an int8_t (signed 8-bit integer) to get the correct branch displacement. If you're programming in a language that doesn't have fixed-width integer types, you have to do it by hand like this: (operand & 0x7f) - (operand & 0x80)