Init code: Difference between revisions
From NESdev Wiki
Jump to navigationJump to search
(Because 'sei' is the first instruction, disabling IRQs need not sit in the fixed bank or the replicated portion) |
(the ppu init page moved when we moved to nesdev.com) |
||
Line 10: | Line 10: | ||
*Disable [[APU DMC|DMC]] IRQs [http://nesdev.parodius.com/bbs/viewtopic.php?p=22538#22538] | *Disable [[APU DMC|DMC]] IRQs [http://nesdev.parodius.com/bbs/viewtopic.php?p=22538#22538] | ||
*Set all RAM that your program uses to a known state. This often involves clearing internal RAM (@ $0000-$07FF) (and PRG RAM if needed (@ $6000-$7FFF)), except that which is intended to survive a reset (such as high scores). | *Set all RAM that your program uses to a known state. This often involves clearing internal RAM (@ $0000-$07FF) (and PRG RAM if needed (@ $6000-$7FFF)), except that which is intended to survive a reset (such as high scores). | ||
*Wait at least 30,000 cycles (see [[ | *Wait at least 30,000 cycles (see [[PPU power up state]]) before reading or writing registers $2003 through $2007. This is commonly done by waiting for the PPU to signal the start of vertical blank twice through $2002. | ||
Some mappers have no fixed bank because they switch all 32 KB of PRG at a time. These include [[AxROM]], [[BxROM]], [[GxROM]], and some configurations of [[Nintendo MMC1]]. You'll have to put the interrupt vectors and the code up to the end of the <code>JMP</code> in a separate section that is duplicated in each bank. | Some mappers have no fixed bank because they switch all 32 KB of PRG at a time. These include [[AxROM]], [[BxROM]], [[GxROM]], and some configurations of [[Nintendo MMC1]]. You'll have to put the interrupt vectors and the code up to the end of the <code>JMP</code> in a separate section that is duplicated in each bank. Often, the 256-byte page $FF00-$FFFF contains the vectors, the start of the init code, and a "trampoline" for jumps from code in one bank to code in another. | ||
Sample implementation: | Sample implementation: |
Revision as of 17:58, 20 December 2009
When the NES is powered on or reset, the program should do the following within a fixed bank:
- Set IRQ ignore bit (not strictly necessary as the 6502 sets this flag on all interrupts, including RESET, but it allows program code to simulate a reset by
JMP ($FFFC)
) - Disable PPU NMIs and rendering
- Initialize stack pointer
- Initialize the mapper (if any)
The init code after this point may be placed either in the fixed bank or in a separate bank using a bankswitch followed by a JMP
:
- Disable decimal mode (not strictly necessary as the 2A03 has no decimal mode, but it maintains compatibility with generic 6502 debuggers)
- If using a mapper that generates IRQs, disable APU timer IRQs
- Disable DMC IRQs [1]
- Set all RAM that your program uses to a known state. This often involves clearing internal RAM (@ $0000-$07FF) (and PRG RAM if needed (@ $6000-$7FFF)), except that which is intended to survive a reset (such as high scores).
- Wait at least 30,000 cycles (see PPU power up state) before reading or writing registers $2003 through $2007. This is commonly done by waiting for the PPU to signal the start of vertical blank twice through $2002.
Some mappers have no fixed bank because they switch all 32 KB of PRG at a time. These include AxROM, BxROM, GxROM, and some configurations of Nintendo MMC1. You'll have to put the interrupt vectors and the code up to the end of the JMP
in a separate section that is duplicated in each bank. Often, the 256-byte page $FF00-$FFFF contains the vectors, the start of the init code, and a "trampoline" for jumps from code in one bank to code in another.
Sample implementation:
reset: sei ; ignore IRQs cld ; disable decimal mode ldx #$40 stx $4017 ; disable APU frame IRQ ldx #$ff txs ; Set up stack inx ; now X = 0 stx $2000 ; disable NMI stx $2001 ; disable rendering stx $4010 ; disable DMC IRQs ; Optional (omitted): ; Set up mapper and jmp to further init code here. ; Clear the vblank flag, so we know that we are waiting for the ; start of a vertical blank and not powering on with the ; vblank flag spuriously set bit $2002 ; First of two waits for vertical blank to make sure that the ; PPU has stabilized @vblankwait1: bit $2002 bpl @vblankwait1 ; We now have about 30,000 cycles to burn before the PPU stabilizes. ; One thing we can do with this time is put RAM in a known state. ; Here we fill it with $00. X is still 0... txa @clrmem: sta $000,x sta $100,x sta $200,x sta $300,x sta $400,x sta $500,x sta $600,x sta $700,x ; Remove this if you're storing reset-persistent data inx bne @clrmem @vblankwait2: bit $2002 bpl @vblankwait2