Init code: Difference between revisions
From NESdev Wiki
Jump to navigationJump to search
m (1 revision: Rest of pages not related to reference) |
(Because 'sei' is the first instruction, disabling IRQs need not sit in the fixed bank or the replicated portion) |
||
Line 1: | Line 1: | ||
When the NES is powered on or reset, the program should do the following within a fixed bank: | 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 <code>JMP ($FFFC)</code>) | *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 <code>JMP ($FFFC)</code>) | ||
*Disable [[NES PPU|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 <code>JMP</code>: | |||
*Disable decimal mode (not strictly necessary as the 2A03 has no decimal mode, but it maintains compatibility with generic 6502 debuggers) | *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 Frame Counter|APU timer IRQs]] | *If using a mapper that generates IRQs, disable [[APU Frame Counter|APU timer IRQs]] | ||
*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 [[Power-up state of PPU]]) 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. | *Wait at least 30,000 cycles (see [[Power-up state of PPU]]) 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. | ||
Line 43: | Line 43: | ||
; We now have about 30,000 cycles to burn before the PPU stabilizes. | ; 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 | txa | ||
@clrmem: | @clrmem: |
Revision as of 17:55, 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 Power-up state of PPU) 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.
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