gbdoc

Open Game Boy Documentation Project

Technical specifications

Models

There are three lines of Game Boy models based on CPU iterations, each with its own minor revisions:

Hardware

CPU

The Game Boy uses a Sharp SM83, which is similar to Intel 8080, Zilog Z80, and other i8080 knockoffs.

TODO

Memory map

Memory mapped I/O

See CGB-specific memory mapped I/O for additional registers in CGB mode.

This section describes the bit mappings of memory mapped I/O.

Mapping Key:

$FF00P1/JOYP: Joypad

This register is used for reading joypad input. The hardware multiplexes the D-pad and the face buttons so only four buttons can be read at a time, based on the value of bits 4 and 5 (0 for select, 1 for deselect). Keys are pulled low (to 0) when pressed and high (to 1) when unpressed. If bits 4 and 5 are both low, then the combination of the D-pad and face buttons is ANDed (i.e. a 0 value implies one or both of the associated keys are pressed). If neither bit 4 or 5 is selected then all keys read 1.

Bit 4 low 5 low
0 Right A
1 Left B
2 Up Select
3 Down Start

Additionally, bits 4 and 5 are used for communicating with the SGB. See the Super Game Boy section for more information.

$FF01SB: Serial byte

TODO

$FF02SC: Serial control

TODO

$FF04DIV: Clock divider

This register is incremented by the CPU clock. (TODO: explain at what rate)

Writing to this register sets it to 0.

$FF05TIMA: Timer value

Increases at a rate specified by TAC. When it overflows, a Timer IRQ is asserted, and this register is reloaded with TMA’s value.

The way the increment is performed in hardware causes spurious increments under certain conditions, refer to Timer.

$FF06TMA: Timer reload

When TIMA overflows, this register’s contents are copied to it. Controls timer overflow frequency.

$FF07TAC: Timer control

Bits:

$FF0FIF: Interrupts asserted

Bits:

TODO

$FF40 — LCDC: LCD control

Bits:

$FF41 — STAT: LCD status

Bits:

Bits 4–6 select which sources are considered for the STAT interrupt. Selecting more than one source may trigger STAT IRQ blocking.

Note that on DMG, writing to this register may assert a STAT IRQ; refer to STAT writing IRQ.

$FF42 — SCY: Background vert. scroll

TODO

$FF43 — SCX: Background horiz. scroll

TODO

$FF44 — LY: LCD Y coordinate

Indicates which line the LCD is currently processing. Values 0-143 indicate VDraw, values 144-153 indicate VBlank.

Note that the LCD is in VBlank for part of line 0; see (TODO).

$FF45 — LYC: LCD Y compare

As long as LY has the same value as this register, STAT bit 2 is set.

$FF46 — DMA: OAM DMA source address

When this register is written to, an OAM DMA transfer starts immediately.

If value $XY is written, the transfer will copy $XY00-$XY9F to $FE00-$FE9F.

$FF47 — BGP: Background palette

Defines how colors of BG (and the window) are displayed.

Bits 0 and 1 define color 0, bits 2 and 3 define color 1, etc. The two bits form a value, where 0 is white, 1 is light gray, 2 is dark gray, and 3 is black.

$FF48 — OBP0: OBJ palette 0

Defines how colors of OBJ using palette 0 are displayed.

The mapping is identical to BGP, however color 0 is never displayed (transparent), so the lower 2 bits are never considered.

$FF49 — OBP1: OBJ palette 1

Defines how colors of OBJ using palette 1 are displayed.

The mapping is identical to OBP0.

$FF4A — WY: Window Y coord

Defines the window’s Y coordinate, that is, the first scanline on which the window is displayed.

TODO: what happens when changing mid-frame? Mid-scanline?

$FF4B — WX: Window X coord

Defines the window’s X coordinate plus 7. (Therefore, a value of 7 will cause the window to span the entire scanline, and a value of 87 will only span half of the screen). Values larger than 167 cause the window to not be displayed.

Values 1-6 act as if the window started to the left of the screen. Value 0 has rather erratic behavior that depends on SCX (TODO: explain how)

TODO: what happens when changing mid-frame? Mid-scanline?

TODO: explain what happens when hiding the window every other scanline, for example

TODO: the official manual states that a WX value of $A6 (166) is “prohibited”. Why?

$FFFFIE: Interrupts enabled

Bits:

TODO

CGB-specific memory mapped I/O

TODO

Cartridges

TODO

Memory bank controllers

The Game Boy Advance has a 16-bit address space, the lower half of which ($0000$7FFF), is devoted to cartridge ROM. Further there is an a 8 kiB region ($A000$BFFF), which is generally used for external RAM (often backed by a battery). However, this leaves 32 kiB usable for ROM which is insufficient for most games. This is where memory bank controllers (MBC for short, sometimes called mappers) come into play: using an MBC the allocated address space can be sliced up and swapped out.

The ROM address space is usually broken into two sections, $0000$3FFF being a (usually) fixed mapping to the beginning of a ROM, or “bank 0”, and $4000$7FFF which can be programmatically swapped to point to other regions of ROM. How this is handled depends on the specific MBC implementation.

Many MBCs share similar traits, namely:

None of these are universal, however. Please see the sections on the respective MBC for details.

A list of known MBC types is as follows:

MBC1

MBC1 is a common memory bank controller for the first few years of Game Boy games. It can be wired up to the cartridge differently sometimes giving it the illusion of being a different MBC type, usually referred to as MBC1-M. However, the physical chip is the same.

Bank swapping

MBC1 bank swapping is a bit unusual due to the fact that it has a high bank and a low bank that combine to make the actual bank number. The high and low bank are combined as such to arrive at the bank number for the $4000 region bank:

LO % MAPPING_SIZE + (HI % 4) * MAPPING_SIZE

The bank for the $0000 region can be swapped when the MBC is “external RAM mode” and wired as MBC1-M, which is controlled by writes to the $6000 region. When in RAM mode, bank “0” is mapped as (HI % 4) * MAPPING_SIZE.

The mapping size is 32 for regular MBC1 cartridges and 16 for MBC1-M cartridges.

Read from $0000$3FFF

Default mapped as bank 0. Can be swapped out with specific other banks based on “mode”. See the Mapping section.

Read from $4000$7FFF

Default mapped as bank 1. Can be swapped out with most other banks. See the Mapping section.

Read from $A000$BFFF

External RAM. Access is disabled by default. Disabled reads are pulled high ($FF).

Write to $0xxx$1xxx

Enable or disable external RAM access. Writing a value of $xA enables access, whereas any other value disables access. The high nybble is ignored.

Write to $2xxx$3xxx

Set the low bank value; see the Mapping section. It cannot be zero and will be coerced to 1 if a value of 0 is written.

Write to $4xxx$5xxx

Set the high bank value; see the Mapping section. This instead controls the external RAM bank when in RAM mode.

Write to $6xxx$7xxx

Adjust mode based on the least significant bit. Writing %…1 enables “external RAM mode” which allows swapping the RAM bank and the bank at $0000. Writing %…0 disables RAM mode and switches the RAM and $0000 ROM banks back to 0.

Write to $A000$BFFF

Write a value to external RAM, if enabled. The value is ignored otherwise.

MBC2

TODO

MBC3

MBC3 is one of the most common MBCs, along with MBC5. It’s especially present in the DMG era. MBC3 improves upon MBC1 by removing the “banking mode”, and can function with a RTC (Real-Time Clock, famously used in the second generation Pokémon games). The Japanese version of Pokémon Crystal contains a special MBC3 labelled MBC30, that can address twice the external RAM and twice the external ROM. (This is the only known difference; JP Crystal is also the only known cart to use MBC30)

Read from $0000$3FFF

Always mapped as bank 0.

Read from $4000$7FFF

Default mapped as bank 1. Can be swapped out with all other banks except bank 0. See the Mapping section.

Read from $A000$BFFF

External RAM or RTC register. Access is disabled by default. Disabled reads are pulled high ($FF).

Write to $0xxx$1xxx

Enable or disable external RAM access. Writing a value of $xA enables access, whereas any other value disables access. The high nybble is ignored.

Write to $2xxx$3xxx

Set the ROM bank value; see the Mapping section.

Write to $4xxx$5xxx

Set the RAM bank value, or select a RTC register; see the Mapping section.

Write to $6xxx$7xxx

Latch RTC registers when writing $00 then $01. Latching the registers should be done before accessing them, but does not stop the clock.

Write to $A000$BFFF

Write a value to external RAM or a RTC register, if enabled. The value is otherwise ignored.

MBC5

MBC5 is ome of the most common MBCs, along with MBC3. It’s especially present in the CGB era, mostly because it is the first MBC to officially support CGB double-speed mode, at least according to Nintendo’s manual. MBC5 improves upon MBC3 by expanding ROM and RAM capabilities (although only one game makes use of all 512 ROM banks, and a handful of all 16 RAM banks), as well as the aforementioned CGB double-speed support. MBC5 cannot work with a RTC, unlike MBC3, but can work with a rumble motor.

Bank swapping

MBC5 can address up to 512 banks, which doesn’t fit the ROM bank value into a single byte. Therefore, that value is split into a low byte, and a high byte, which effectively contains only 1 bit (? If MBC5 can actually support more ROM banks, this may even be a full byte). Since most, or rather all but one, games use at most 256 banks, rendering this extra bit (? byte) unused. (TODO: for games not using this extra byte, what does writing to $3xxx do?)

Read from $0000$3FFF

Always mapped as bank 0.

Read from $4000$7FFF

Default mapped as bank 1. Can be swapped out with all other banks including bank 0. See the Mapping section.

Read from $A000$BFFF

External RAM register. Access is disabled by default. Disabled reads are pulled high ($FF).

Write to $0xxx$1xxx

Enable or disable external RAM access. Writing a value of $xA enables access, whereas any other value disables access. The high nybble is ignored (?).

Write to $2xxx

Set the low ROM bank value; see the Mapping section.

Write to $3xxx

Set the high ROM bank value; see the Mapping section.

Write to $4xxx$5xxx

Set the RAM bank value; see the Mapping section. If the cartridge has rumble, bit 3 is mapped to rumble instead of RAM bank, i.e. bank OR 8 enables rumble.

Write to $A000$BFFF

Write a value to external RAM, if enabled. The value is otherwise ignored.

MBC6

MBC6 is special in that it has a 8 Mbit flash chip that can be mapped into ROM space, as well as having two separate ROM banked regions ($4xxx$5xxx and $6xxx$7xxx) and two SRAM banked regions ($Axxx and $Bxxx). It is only used in one game, Net de Get: Minigame @ 100.

TODO

MBC7

MBC7 is a special memory bank controller for the Game Boy Color that contains an 2-axis accelerometer (ADXL202E) and and a 256 byte EEPROM (93LC56). It is notably used in the game Kirby’s Tilt ‘n’ Tumble.

Accelerometer data must be latched before reading. Data is 16-bit and centered at the value $81D0. Earth’s gravity affects the value by roughly $70, with larger acceleration providing a larger range. Maximum range is unknown.

Save data is accessed through a manually clocked shift register.

TODO

MMM01

MMM01 is a “metamapper” in that it is used in game collection (Momotarō Collection 2 and Taito Variety Pack) to provide a boot menu before locking itself down into a separate “normal” mapper mode that only exposes certain banks to the game inside the collection.

TODO

Pocket Cam

TODO

TAMA5

TAMA5 is a custom MBC developed by Bandai and officially licensed by Nintendo that provides a small EEPROM, along with RTC and piezoelectric buzzer components, similar to HuC-3. It is an unusal MBC in that it only has two addresses with which it can communicate with the MBC. There are other TAMA chips on the PCB, which include TAMA6 and TAMA7 (the ROM). It is only used in one game, Game de Hakken!! Tamagotchi - Osutchi to Mesutchi, also known as Tamagotchi 3.

TODO

HuC-1

HuC-1 is a custom MBC developed by Hudson and officially licensed by Nintendo that provides infrared communication for games that predate the Game Boy Color, such as Pokémon Card GB, the Japanese version of Pokémon Trading Card Game. Oddly, the international versions do not use HuC-1 and instead rely on the GBC’s IR port.

TODO

HuC-3

HuC-3 is a custom MBC developed by Hudson and officially licensed by Nintendo that extends HuC-1 with an RTC and a piezoelectric buzzer. It’s notably used in the Robot Poncots (Robopon outside of Japan) and Pocket Family game series.

TODO

Unlicensed mappers

Several unlicensed games use unofficial mappers that are less well documented and may have copy protection.

Wisdom Tree

Wisdom Tree is an American company devoted to very, very Christian games. Notable for unlicensed games including Super 3D Noah’s Ark, they released games on a wide array of Nintendo platforms including the Game Boy. The Game Boy version uses a very simple mapper with the ROM region ($0000$7FFF) remappable as a single monolithic block.

Read from $0000$7FFF

Default mapped as bank 0. Can be swapped out with other banks.

Write to $0000$3FFF

Swap the 32 KiB bank in the whole ROM region. Unlike most mappers the selected bank is based on the address written, not the value written.

Picture processing unit

The Game Boy’s picture processing unit is responsible for creating video frames. One frame takes 70224 cycles (~59.7275 frames per second).

Timing is divided into 154 lines, 144 during VDraw and 10 during VBlank. Each line takes 456 cycles.

The PPU can be disabled entirely during normal operation via the LCDC register. This prevents normal timing such that re-enabling it can lead to irregular frame rates, at least transiently.

Draw modes

The PPU has 4 distinct modes:

Modes 0, 2, and 3 do not occur during VBlank, only during VDraw. Mode transitions occur in this order:

Different transitions can affect timing characteristics.

Mode 0

HBlank occurs between lines and allows a short period of time for adjusting PPU parameters, VRAM, and OAM.

Timing characteristics

Base timing: 204 cycles (max)

HDraw (mode 3) can steal cycles from HBlank depending on scrolling parameters (SCX), window parameters (WX), and OAM.

Mode 1

VBlank occurs between frames and allows a short period of time for adjusting PPU parameters, VRAM, and OAM.

Timing characteristics

Exact timing: 4560 cycles (10 lines)

Mode 2

Mode 2 occurs after HBlank and before HDraw. It is used to scan OAM to find which OBJs are active. During this time OAM is locked.

Timing characteristics

Exact timing: 80 cycles (2 cycles per OAM entry)

Mode 3

HDraw is when pixels are drawn.

Timing characteristics

Base timing: 172 cycles (min)

Audio processing unit

TODO

Timer

TODO

DMA

TODO

Interrupts

The Game Boy contains 5 interrupt types. Each type has a different priority and vector:

Type Priority Vector
VBlank 0 $0040
LCD STAT 1 $0048
Timer 2 $0050
Serial 3 $0058
Joypad 4 $0060

Interrupts are controlled through three registers:

IF and IE are memory-mapped, whereas IME is controlled through the DI (disable interrupts) and EI (enable interrupts) instructions.

Interrupt requests are edge triggered(Is this true in all cases?): when an IRQ is asserted, it sets the bit corresponding to its priority in the IF register. Interrupt dispatch however is level triggered: if at any time between instructions(Unclear; which T state?) while IME is enabled IE AND IF != 0 IRQ dispatch will begin. Note that multi-M cycle instructions effectively block interrupt dispatch from starting until the end of the instruction.

Interrupt dispatch takes 4 M cycles. The interrupt vector is loaded into the program counter based on the lowest significant bit of IE AND IF after the program counter’s old value has been pushed onto the stack, which takes two M cycles (one per byte, high byte first).

When interrupt dispatch completes the bit associated with the interrupt handled is automatically cleared from IF and IME is set to 0. Returning from the interrupt is handled by the reti instruction, which atomically pops the old program counter from the stack and reenables IME.

Interrupt dispatch canceling

Interrupt dispatch is not atomic. If the value of IE AND IF changes between the first M cycle and when the vector is loaded, the value of the vector may change. This can happen if IE or IF is altered in some way, either by a higher priority IRQ asserting, or by another memory write (e.g. the first stack push overwriting IE or IF).

Serial I/O

TODO

Miscellaneous

Hardware issues

OAM bug

Under some circumstances, OAM may be corrupted.

Triggers are:

TODO: explain how exactly OAM is corrupted.

The OAM bug is fixed on CGB.

STAT IRQ blocking

The STAT IRQ is edge-triggered, based on conditions selected in the STAT register. A STAT IRQ is asserted when one or more selected conditions become true when none were true previously. Trouble arises between mode transitions, because the signal doesn’t go low then high again, but stays low.

For example, enabling Mode 2 and Mode 0 sources will assert an IRQ on LY 0 Mode 2, then on LY 0 Mode 0, but not on LY 1 Mode 2 since both modes are contiguous.

NB: this does not occur with Mode 0 and LYC, because LYC is slightly late on Mode 2, so the signal does go low then high again. (Source)

STAT writing IRQ

When writing to STAT on DMG, bits 3–6 are considered high for one cycle, which temporarily selects all conditions and may thus assert a STAT IRQ. CGB does not exhibit this bug, even in DMG mode.

Super Game Boy

TODO

Cheat codes

TODO

About this document

CC-BY-4.0

This document is licensed under the Creative Commons Attribution 4.0 International License (CC-BY 4.0)