Copy-pasted from a hidden fortress deep under the sea
The NES is one of my favorite consoles; I grew up with it, and still have two clones and a boatload of cartridges sitting around on my shelves.Of course, now that I have knowledge of the arcane and whatnot, I decided to actually do a bit of digging into the process of creating games for the NES. My interest was initially piqued after I watched a video by the creator of Retro City Rampage, who ported his game to the NES (And managed to leave it more or less completely intact).For three years now, I've been making music for the NES hardware, playing games on it, and designing my games after the same 'style' as popular NES titles. Actually creating a game for the machine is fun (And challenging). I'll write down my discoveries here, and other general information.What I'm trying to accomplishBasically, it started with this:For this game, I used a portion of the NES palettes (More info on that below), and obviously began designing music in Famitracker.But then a friend saw the game, and wondered aloud if it would be possible to do this on actual NES hardware. As per usual, I couldn't resist a challenge, so I began my foray into the world of the 2A03.What I have accomplished so farMore or less, I have everything initialized, I have my CHR table loaded, and I'm displaying a large sprite that moves across the screen:The repeating pattern in the background is due to the nametable being zeroed out. More on that later.The 2A03The CPU at the core of the NES is not, as most people think, a 6502. Most people mistakenly think that the 2A03 is the "music chip". They're right, in a way. But the 2A03 is also the main processor.Of course, it is still a 6502, just modified in several ways.The 2A03 is a rare type of processor, pairing both the APU and CPU functionality on one die. It has one general purpose register, two index registers, and operates in 8-bit hexadecimal mode. The 2A03 has a clock speed of around 25mhz, and several dividers pulsing the PPU, IRQ lines and ROM/RAM. The processor is more or less the same as the Commodore 64's 6502, with the exception of the addition of the APU and the bank switching hardware. The PPUThe PPU or "Picture Processing Unit", was a Ricoh RP2C02/RP2C07 (Depending on region), and was really advanced for it's time.Before the NES, all graphics processing was performed by the CPU. Pixels were drawn manually, and thus VRAM was limited (A 320x240 screen at only 8 bits per pixel is already 640K of RAM, something that was impossibly expensive back then). The NES used a few tricks to not only speed up graphics processing, but increase the resolution beyond what the current consoles had available to them (Those being the Commodore series, the Atari machines and the ZX Spectrum).The 'native' resolution of a NES console is 256x240, a really nice 'square' aspect ratio (Nearly 1, actually 1.06).To handle this memory, the console used several concepts that became staples in the Nintendo product stable (Up to the DS). The first of these was the pattern table, an 8KB location in ROM where the game's graphics were stored. Two tables exist in a standard ROM layout, each one capable of holding 256 8x8x4 tiles. Often, one table would be used to store sprites, the other for storing backgrounds.The next piece of the puzzle is the nametable. This is basically an array of 34x32 bytes, each one containing a tile reference. It's usually used to draw anything that isn't a sprite.In my screenshot above, the nametable is filled with zeroes, and tile zero is the top-left of the player sprite. So the background is filled with that.Sprites are handled in a separate way, utilizing OAM (Object Attribute Memory). Each piece of "Object Memory" is basically a structure that looks like this in C:struct OAM_Entry
{
unsigned byte y;
unsigned byte tile;
unsigned byte attributes;
unsigned byte x;
}
; This is the 'iNES' header. Used by emulators to determine what 'virtual cartridge' to use.
; This would have absolutely no effect on an actual NES, where you'd have to use a compatible ROM with
; these settings (In this case, 16KB of PRG ROM, 8KB of CHR ROM, no mapper chip, and mirroring enabled)
.inesprg 1
.ineschr 1
.inesmap 0
.inesmir 1
; Memory bank 0, the first 8KB of PRG ROM
.bank 0
.org $C000
; Include my palette data here
data_palette:
.incbin "./palette_sprites.pal"
.incbin "./palette_bg.pal"
initialize:
.incude "./src/vectors.asm" ; Includes code for RESET, IRQ and NMI vectors.
; Initialize PPU
; Enable Sprite and Background rendering
lda #%00011000
sta $2001
load_palettes:
lda $2002
lda #$3F
sta $2006
lda #$10
sta $2006
ldx #$00
load_palette_loop:
lda data_palette, x
sta $2007
cpx #$20
bne load_palette_loop ; Jump back to loop beginning if we haven't processed all 32 palette entries.
; Enable PPU NMI
lda #%10000000
sta $2000
game_loop:
game_loop_vblank_1:
bit $2002
bpl game_loop_vblank_1
; Anything drawing related would go here
; Loop forever
jmp game_loop
; Memory bank 1, the upper 8KB of the ROM.
; Need to set up vectors here.
.bank 1
.org $FFFA
.dw NMI
.dw RESET
.dw IRQ
; Memory bank 2, CHR ROM
.bank 2
.org $0000
.incbin "./chr/tiles.chr"
@Mega: That's definitely true. But who and who didn't use the information in that era is important. Mainstream, was slightly different. Simple conversations about the technical details could not be talked about as we are now. I know it for a fact. I remember talking to a Motorola tech for hours on end via a 1-800 # back in the day, on die technology alone(go figure :]). As far as literature goes, one could go to the library or get a CPU's instruction set quick reference or reference books via mail order from the manufactures(which was great but not immediate). Again, it's not that it wasn't accessible. It's just that it wasn't mainstream accessible. This is why I like your blog. People who don't know can get bits of information unbiased and put the rest together for themselves. Plus, it brings back great nostalgia for me.. Keep Going…..