Over the weekend I finished an Atari 2600 3D maze game which I will be releasing shortly (possibly as part of a large announcement) but if anybody wants early access to the ROM email me.
One of the things that both the NES version of Hello World and the 2600 version had in common is mapping the graphics processor to memory addresses. This a very common way of communicating with devices when using assembly language. The PPU condenses this to only 8 addresses. The audio unit, Sprite DMA, and IO ports are separate maps, but I don't consider them part of the PPU. As has been pointed out earlier, the PPU has it's own memory. The addresses here do not correspond to PPU memory but are simply registers used to control the PPU.
$2000 is the first of two control registers, with bits used to control the PPU settings as follows:
Bits 0 and 1 controls the screen memory (name table in NES terminology) with 00 being PPU address $2000, 01 being $2400, 10 being $2800 and 11 being $2C00.
Bit 2 enables vertical writing, meaning that when set writing to PPU memory increments the next write address by 32 bytes. As the screen has 32 columns this has the effect of writing a vertical strip of screen memory, which is exceedingly handy for side-scrolling games.
Bit 3 selects which of the two pattern tables the sprites will use for their images.
Bit 4 selects which of the two pattern tables the screen will use for its character set.
Bit 5 selects the sprite size. 0 for 8x8 sprites, 1 for 8x16 sprites.
Bit 6 not used
Bit 7 VBlank interrupt enable. When set will cause an interrupt to be triggered when a vertical blank is occurring.
$2001 is a second control port with bits as follows:
Bit 0 not used
Bit 1 Hides the left most column of the screen if 0
Bit 2 Hides sprites in the leftmost column of the screen if 0
Bit 3 Shows screen if set, blank screen when 0
Bit 4 Enables sprites when set.
Bit 5 intensifies Red colors
Bit 6 intensifies Green colors
Bit 7 intensifies Blue colors
I have heard that only one of the color intensifier bits should be set.
$2002 PPU Status gives status of PPU
Bits 0-5 not used
Bit 6 set when a visible bit in sprite 0 intersects a visible background bit. It is set only when the scan line with the intersection is occurring which means it can be used to trigger events on certain scan lines.
Bit 7 VBlank flag. Set when a VBlank has occurred. Once read it becomes 0 until the next VBlank, but many emulators do not emulate this behaviour.
$2003 Sprite Memory Address writing to this register will set the memory address that $2004 will point to for reading and writing sprite data. It should be pointed out that there is only 256 bytes of sprite memory so only a single write to this address is needed to access all of sprite memory.
$2004 read or write the sprite memory address that was set by $2003. Auto increments the next read or write will be the next address.
$2005 Screen Position written to twice to set the position of the screen. This is used to scroll the screen as if set to non-zero the portion of the screen outside of screen memory will come from one of the other name tables.
$2006 PPU Memory Address writing to this register will set the memory address that $2007 will point to for reading and writing PPU data. It requires two writes to set an address. The first write sets the high byte with the second being the low byte. Yes, this is the opposite of how the 6502 does things.
$2007 read or write the PPU memory address that was set by $2006. Auto increments the next read or write will be the next address. If vertical writing is enabled (via $2000 bit 2), next read/write address will be increment end by 32.
Programming the PPU is simply a matter of reading and writing to the appropriate registers. The sprites are a special case as if you are using a lot of sprites there is a much more efficient way of setting them. But before we cover sprite DMA, it would probably be a good idea to discuss sprites.