As you know, the Game Boy's CPU has a 16-bit address space: it can access up to 65,536 bytes of memory at any time, labelled from $0000 to $FFFF. Now, although from the CPU all of these bytes are equal, the programmer needs to be aware that not all of these bytes are the same. Simple example: some of the memory is the ROM where the game code is, some of the memory is the RAM. We need to know where each is.
Here are the different memory types; I will explain them one by one. We will also see how they're used with RGBDS.
|Begins at||Ends at||Name|
ROM is where the game's program and data are stored. RGBDS provides two memory types for that area,
ROM0 ($0000-$3FFF) and
ROMX ($4000-$7FFF). This is due to something called banking, but we'll forget it for now. We will instead pass the
-t option to RGBLINK to make
ROM0 span the entire ROM space.
ROM is, as its name suggests, read-only. (You may see writes to the ROM space in games, but that's also due to banking, so forget it for now.) It's where the CPU will be executing code from almost always. Aside from banking, which we will pretend doesn't exist for now, there isn't anything special about ROM.
We already discussed VRAM in the Displaying lesson, but here's a quick recap. Between $8000 and $97FF are stored the tiles; 16 ($10) bytes per tile, and 384 ($180) tiles in three "blocks" of 128 ($80) tiles each. Then are two tilemaps, one at $9800-$9BFF, and one at $9C00-$9FFF. Each tilemap is 32*32 bytes.
VRAM has a big flaw, in that it can only be accessed while the PPU is not; that is, it must be accessed during LCD modes 0, 1 and 2.
SRAM stands for Save RAM. It's somewhat misleading, which is why some refer to it as XRAM (External RAM or Expansion RAM), but SRAM is the most common term. SRAM is RAM on the cartridge; most of the time, it's backed up by a battery and used to store save data, but some games also use it as extra work RAM (Pokémon games use SRAM as scratch buffers for sprite decompression, Super Mario Land 2 uses some of its SRAM to store variables and level data).
By default, SRAM is in a "locked" state, which, like locked VRAM, ignores writes and returns $FF when read. (Editor's note: it's actually possible that $FF may NOT be always returned. It's best to not rely on reads from locked SRAM.) How SRAM is unlocked depends on the MBC.
WRAM is the console's work RAM. It's present in the console itself, and serves as the main writable storage. There are 8 kB of WRAM, and you can pretty much use it however you please.
Echo RAM is the product of a hardware quirk that causes most of WRAM to also be accessible at $E000-FDFF. It's recommended to avoid relying on it for several reasons, though its behavior appears to be mostly stable and well-understood.
You're going to have to get used to this: the Game Boy has no protection features whatsoever, so things that you aren't supposed to do or absolutely mustn't... well, you can still do them, and it'll yield some interesting results. (Most of the time. Sometimes it'll just crash, or be equally underwhelming :D)
OAM can be considered a extension of VRAM, if you stretch the definition. It's the area of memory where information about objects (commonly referred to as "sprites", though the term "sprite" gets annoyingly often misused). It works similarly to VRAM, being locked from the CPU while the PPU is accessing it, although it has its own specificities.
The area between OAM and IO is pretty weird. It has the same "locking" behavior as OAM, but the rest of its behavior depends on the console model and revision. Best not rely on it at all.
This area of memory is a mess of hardware-mapped registers. It's here that a lot of interfacing with the Game Boy is performed, such as configuring graphics, playing sound, or communicate with another Game Boy.
There's a slightly special byte of IO, which is register
IE; it's mapped at $FFFF, ie. just after the end of HRAM. Why it's there seems to be due to the way the CPU works internally.
These 127 bytes of RAM work just like WRAM, except that they can be accessed slightly faster by a certain instruction; therefore, it's a good place to store temporary variables in.