Skip to content
Shane DeSeranno edited this page Nov 4, 2015 · 1 revision

Go Home

Part 06 - More MMU

Cartridge (0x0000 to 0x7FFF)

Now would be a good time to get the rest of the devices wired up to the MMU. Even if they don't do much, it would still be good to get that work out of the way. We have already wired up the boot ROM and the first 16KB chunk of cartridge ROM. The second 16KB chunk of cartridge ROM is switchable. As discussed on Memory Bank Controllers, each cartridge may have it's own controller in it that allows different chunks of memory to be swapped in. The simplest case is "None". This just means the game is small enough that it doesn't need more than 32KB of ROM, so the entire memory is available from 0x0000 to 0x7FFF.

Eventually, we will have to read each of these MBCs and implement them in the cartridge. ADD MORE DETAILS.

GPU (0x8000 to 0x9FFF)

We need to create a GPU class and map these addresses to it. This contains RAM that the GPU will use to render. For us, we can just allocate an 8KB chunk of memory and ensure it can be read and written.

Cartridge (0xA000 to 0xBFFF)

This is 8KB of RAM that is stored on the cartridge, often with a battery backup to allow for storing of high scores and saved games. The behavior of this will depend on the MBC used by the cartridge.

MMU (0xC000 to 0xDFFF)

This is an 8KB chunk of working RAM that is provided by the MMU.

MMU (0xE000 to 0xFDFF)

This is a strange thing. It is essentially a mirror of the memory at 0xC000 to 0xDDFF. It is rarely used, but should be expected to work. For example, if a request for 0xE123 is made, then the memory at 0xC123 should be returned by the MMU.

GPU (0xFE00 to 0xFE9F)

This is referred to as the Sprite Attribute Table. The GameBoy GPU can display up to 40 sprites either in 8x8 or in 8x16 pixels. Because of a limitation of hardware, only ten sprites can be displayed per scan line. See the link for more details.

MMU (0xFEA0 to 0xFEFF)

These are unused and should fail if something is read or written to them.

Gamepad (0xFF00)

This one byte is enough to read data from the gamepad!

Serial Data (0xFF01 to 0xFF02)

We can choose to not implement this for now.

No Clue (0xFF03)

This isn't referenced in the specification at all!

Timer (0xFF04 to 0xFF07)

Eventually, we'll have to wire up some logic here to provide timer logic via these addresses.

No Clue (0xFF08 to 0xFF09)

This isn't referenced in the specification at all!

Audio (0xFF10 to 0xFF3F)

This is used to control all of the sounds.

GPU (0xFF40 to 0xFF6B)

This controls various features of the LCD display. It can do things like turn it off.

Unknown (0xFF6C to 0xFF7F)

These are unspecified.

MMU (0xFF80 to 0xFFFE)

This is referred to as high RAM (HRAM). It has some unique uses, but generally is is read/write capable. However, this is also where the stack lives. If you recall, during boot, the Stack Pointer (SP) was set to 0xFFFE. That points to the end of this HRAM. When the PUSH OpCode is called, it pushes the value to this SP location, then moves the SP up by one. Later, when a POP is done, the SP is moved down, and the value retrieved.

MMU (0xFFFF)

This is a special byte that is used to enable interrupts. Interrupts are a special feature on hardware to stop the processing of code, and immediate jump the execution (interrupt) to a special piece of code. For example, if you wanted to do something at the next VBlank (when the screen is done drawing), then you could enable the interrupt and it would trigger that piece of code.

That pretty much covers all the pieces. We need to make a set of classes for each of these components, and register them with the MMU so it can route the ReadByte and SetMemory requests to the correct device.

Clone this wiki locally