Yes.
Here's a more detailed memory map of the entire NES memory map:
$0000-$1FFF - System RAM
$2000-$3FFF - PPU registers
$4000-$401F - CPU/APU registers
$4020-$FFFF - forwarded through to the cartridge
|
Examining the 'System RAM' block a little closer... you'll get this:
$0000-$07FF - System RAM
$0800-$0FFF - The same system RAM (mirrored)
$1000-$17FF - The same system RAM (mirrored again)
$1800-$1FFF - The same system RAM (mirrored yet again)
|
What this means is that accessing address $0200 and address $0A00 will
access the same byte of memory. Like both addresses point to the same area of RAM.
But that seems stupid, right? Why does it do that?
The addressing allows for 8K ($2000 bytes) of RAM... but way back then RAM was expensive... so it only had 2K ($0800) of physical RAM. The mirroring happens because the high bits of the address get "chopped off" when accessing the actual RAM chip.
This is easily simulated by masking out the low bits:
1 2 3 4 5
|
// assume addr is in the RAM area ($0000-1FFF)
uint8_t readRAM(uint16_t addr)
{
return RAM[ addr & 0x07FF ]; // <- this handles the mirroring
}
|
If you treat all of addressing space as a singular big array, doing this is not so easy.
And this doesn't even touch on 'bankswitching' which allows for more than $10000 bytes to be accessed by swapping out memory pages.
So yeah... put reads/writes through a function. The array thing was just conceptual... and I probably should have illustrated it differently in hindsight.