SweetNES Baby-Steps
As I begin work on the SweetNES project, I’m come to see that it’s difficult to get any gratification back until a good portion of the emulator has been written. In other words, I won’t be playing any spectacular games for quite some time. The reason is because so many of the subsystems are depended on one another. A logical first approach is to start work on the 6502 instructions and CPU core. However, no graphics will get to the screen without work in the PPU. In addition, a game won’t be playable without input and sound. Of course all these are interconnected and have strict timing tolerances. It would seem that the whole emulator would need to be written before anything could be tested. So for the past week I’ve been asking myself the best way to begin work so that I can get some feedback as soon as possible, otherwise, I could go way down the wrong path and find it difficult to re-engineer later.
The solution I came up with is something I call baby-step ROMs. I thought I could quickly write the most basic game possible and then build up from there. What’s the most basic game possible? What I came up with is a ROM that makes the whole screen a single color. With a few modifications to the “NES ASM Tutorial” linked below I was able to write a ROM that did just that. It may sound overly simple, but I can assure you that a lot needs to happen just to get a solid color on the screen. The benefit is that I have a whole lot less to worry about than getting a professionally programmed game to work out of the gate. I don’t even have to have the entire 6502 instruction set programmed to make this run. It only requires a dozen or so instructions.
In case anyone is interested, here is the game code that I’ll be building the emulator to run over the next couple weeks:
; Assemble with NESASM3 .inesprg 1 ; One 16K program ROM .ineschr 0 ; No 8K character ROM .inesmir 0 ; Horizontal mirroring .inesmap 0 ; Mapper 0 .bank 0 .org $C000 ; Entry point for the program RESET: SEI ; Set the Interrupt-Disable flag (block IRQs) CLD ; Clear the Decimal Mode flag (just to be sure). LDX #$FF TXS ; Reset stack pointer to top of the stack INX ; X = 0 STX $2000 ; Disable NMI interrupt STX $2001 ; Disable rendering JSR VBLANK ; Wait for the first v-blank LDA #%00001010 ; Setup the PPU: BG clipping, BG visible STA $2001 JSR VBLANK ; Wait for the second v-blank LDA #$3F ; Set the PPU to write at $3F00 STA $2006 LDA #$00 STA $2006 LOADPAL: LDA PALDATA, X ; X = 0 STA $2007 ; Write the byte to the PPU INX ; Move to the next byte CPX #4 BNE LOADPAL ; Have we written enough bytes yet? FOREVER: JMP FOREVER ; Inifinite loop ; Waits for v-blank VBLANK: BIT $2002 ; Test if v-blank has occured BPL VBLANK ; Loop RTS ; NMI interrupt handler NMI: RTI; ; Do nothing and just return ; Simple palette PALDATA: db $31 ; Sky blue db $1A ; Dark green db $29 ; Light green db $28 ; Tan ; Create the vector table .bank 1 .org $FFFA ; Adjust offset to start at vectors .dw NMI ; Called when NMI interrupt fires .dw RESET ; Called when on power/reset .dw 0 ; External IRQ not used
Once I can get this working, I’ll build it up to do more and more until I’m ready to tackle a real game.
Resources:
- NES ASM Tutorial (PDF)
Update [1/1/2007]: Well it didn’t take long for me to get burned by making wrong assumptions. I erroneously assumed that because the code worked as I expected it to in FCEUltra that it was correct. However, when I tested it in Nestopia it didn’t work. Apparently not all emulators are accurate. Shocking!
I had to make some additional changes to run this correctly in both emulators and I’m fairly confident now that it would also run on real hardware. The corrected code is now what’s listed above and should produce a beautiful sky-blue color on accurate emulators.
There’s an important lesson here. If I want my emulator to accurately simulate a real Nintendo® then I also need to compare my results against a real Nintendo® and not against another emulator.
November 15th, 2007 at 4:21 am
[…] it to me to make a difficult job even harder. After briefly discussing my approach for getting the SweetNES project rolling I decided to document the entire endeavor. I […]