There are three lines of Game Boy models based on CPU iterations, each with its own minor revisions:
The Game Boy uses a Sharp SM83, which is similar to Intel 8080, Zilog Z80, and other i8080 knockoffs.
TODO
$0000
– $7FFF
: External bus (ROM region)$8000
– $9FFF
: VRAM$A000
– $BFFF
: External bus (RAM region)$C000
– $DFFF
: WRAM$E000
– $FDFF
: ECHO (WRAM secondary mapping)$FE00
– $FE9F
: Object Attribute Memory (OAM)$FEA0
– $FEFF
: Invalid OAM region (behavior varies per revision)$FF00
– $FF7F
: Memory mapped I/O$FF80
– $FFFE
: High RAM (HRAM)$FFFF
: IE
register$FF00
— P1
/JOYP
: Joypad$FF01
— SB
: Serial byte$FF02
— SC
: Serial control$FF03
: unmapped$FF04
— DIV
: Clock divider$FF05
— TIMA
: Timer value$FF06
— TMA
: Timer reload$FF07
— TAC
: Timer control$FF08
– $FF0E
: unmapped$FF0F
— IF
: Interrupts asserted$FF10
— NR10
: Audio channel 1 sweep$FF11
— NR11
: Audio channel 1 sound length/wave duty$FF12
— NR12
: Audio channel 1 envelope$FF13
— NR13
: Audio channel 1 frequency$FF14
— NR14
: Audio channel 1 control$FF15
— NR20
: Unmapped$FF16
— NR21
: Audio channel 2 sound length/wave duty$FF17
— NR22
: Audio channel 2 envelope$FF18
— NR23
: Audio channel 2 frequency$FF19
— NR24
: Audio channel 2 control$FF1A
— NR30
: Audio channel 3 enable$FF1B
— NR31
: Audio channel 3 sound length$FF1C
— NR32
: Audio channel 3 volume$FF1D
— NR33
: Audio channel 3 frequency$FF1E
— NR34
: Audio channel 3 control$FF1F
— NR40
: Unmapped$FF20
— NR41
: Audio channel 4 sound length$FF21
— NR42
: Audio channel 4 volume$FF22
— NR43
: Audio channel 4 frequency$FF23
— NR44
: Audio channel 4 control$FF24
— NR50
: Audio output mapping$FF25
— NR51
: Audio channel mapping$FF26
— NR52
: Audio channel control$FF27
– $FF2F
: Unmapped$FF30
– $FF3F
: Wave pattern$FF40
— LCDC
: LCD control$FF41
— STAT
: LCD status$FF42
— SCY
: Background vert. scroll$FF43
— SCX
: Background horiz. scroll$FF44
— LY
: LCD Y coordinate$FF45
— LYC
: LCD Y compare$FF46
— DMA
: OAM DMA source address$FF47
— BGP
: Background palette$FF48
— OBP0
: OBJ palette 0$FF49
— OBP1
: OBJ palette 1$FF4A
— WY
: Window Y coord$FF4B
— WX
: Window X coord$FF50
— Boot ROM control$FFFF
— IE
: Interrupts enabledSee 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:
1
: Unmapped (hi-Z), always reads 1I
: Input only (readable by CPU)O
: Output only (writable by CPU)B
: Bidirectional (read/write by CPU)$FF00
— P1
/JOYP
: Joypad11BBIIII
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.
$FF01
— SB
: Serial byteBBBBBBBB
TODO
$FF02
— SC
: Serial controlB111111B
B11111BB
TODO
$FF04
— DIV
: Clock dividerBBBBBBBB
This register is incremented by the CPU clock. (TODO: explain at what rate)
Writing to this register sets it to 0.
$FF05
— TIMA
: Timer valueBBBBBBBB
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.
$FF06
— TMA
: Timer reloadBBBBBBBB
When TIMA overflows, this register’s contents are copied to it. Controls timer overflow frequency.
$FF07
— TAC
: Timer control11111BBB
Bits:
TIMA
increases
TIMA
doesn’t increment when this bit is reset$FF0F
— IF
: Interrupts asserted111BBBBB
Bits:
TODO
$FF40
— LCDC
: LCD controlBBBBBBBB
Bits:
$FF41
— STAT
: LCD status1BBBIII
Bits:
LY
coincidence flagBits 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. scrollBBBBBBBB
TODO
$FF43
— SCX
: Background horiz. scrollBBBBBBBB
TODO
$FF44
— LY
: LCD Y coordinateIIIIIIII
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 compareBBBBBBBB
As long as LY
has the same value as this register, STAT
bit 2 is set.
$FF46
— DMA
: OAM DMA source addressBBBBBBBB
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 paletteBBBBBBBB
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 0BBBBBBBB
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 1BBBBBBBB
Defines how colors of OBJ using palette 1 are displayed.
The mapping is identical to OBP0
.
$FF4A
— WY
: Window Y coordBBBBBBBB
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 coordBBBBBBBB
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?
$FFFF
— IE
: Interrupts enabled111BBBBB
Bits:
TODO
TODO
TODO
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:
$0000
– $1FFF
controls if external RAM is accessible. $xA
enables access and other values disable access.$2000
– $3FFF
controls which bank is swapped into the upper half of ROM address space.$4000
– $5FFF
controls which bank is swapped into the external RAM address space.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:
$00
$08
: RAM$09
: Battery-backed RAM$01
$02
: RAM$03
: Battery-backed RAM$05
: RAM$06
: Battery-backed RAM$0F
: Battery-backed RTC$10
: Battery-backed RAM and RTC$11
$12
: RAM$13
: Battery-backed RAM$19
$1A
: RAM$1B
: Battery-backed RAM$1C
: Rumble$1D
: Battery-backed rumble$1E
: Battery-backed RAM and rumble$20
: Battery backed RAM, flash memory$22
: EEPROM, accelerometer$0B
$0C
: RAM$0D
: Battery-backed RAM$FC
$FD
: EEPROM, RTC, and alarm$FF
: IR sensor$FE
: IR sensorMBC1 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.
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.
$0000
– $3FFF
Default mapped as bank 0. Can be swapped out with specific other banks based on “mode”. See the Mapping section.
$4000
– $7FFF
Default mapped as bank 1. Can be swapped out with most other banks. See the Mapping section.
$A000
– $BFFF
External RAM. Access is disabled by default. Disabled reads are pulled high ($FF
).
$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.
$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.
$4xxx
– $5xxx
Set the high bank value; see the Mapping section. This instead controls the external RAM bank when in RAM mode.
$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.
$A000
– $BFFF
Write a value to external RAM, if enabled. The value is ignored otherwise.
TODO
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)
$0000
– $3FFF
Always mapped as bank 0.
$4000
– $7FFF
Default mapped as bank 1. Can be swapped out with all other banks except bank 0. See the Mapping section.
$A000
– $BFFF
External RAM or RTC register. Access is disabled by default. Disabled reads are pulled high ($FF
).
$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.
$2xxx
– $3xxx
Set the ROM bank value; see the Mapping section.
$4xxx
– $5xxx
Set the RAM bank value, or select a RTC register; see the Mapping section.
$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.
$A000
– $BFFF
Write a value to external RAM or a RTC register, if enabled. The value is otherwise ignored.
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.
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?)
$0000
– $3FFF
Always mapped as bank 0.
$4000
– $7FFF
Default mapped as bank 1. Can be swapped out with all other banks including bank 0. See the Mapping section.
$A000
– $BFFF
External RAM register. Access is disabled by default. Disabled reads are pulled high ($FF
).
$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 (?).
$2xxx
Set the low ROM bank value; see the Mapping section.
$3xxx
Set the high ROM bank value; see the Mapping section.
$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.
$A000
– $BFFF
Write a value to external RAM, if enabled. The value is otherwise ignored.
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 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 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
TODO
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 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 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
Several unlicensed games use unofficial mappers that are less well documented and may have copy protection.
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.
$0000
– $7FFF
Default mapped as bank 0. Can be swapped out with other banks.
$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.
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.
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.
HBlank occurs between lines and allows a short period of time for adjusting PPU parameters, VRAM, and OAM.
Base timing: 204 cycles (max)
HDraw (mode 3) can steal cycles from HBlank depending on scrolling parameters (SCX), window parameters (WX), and OAM.
VBlank occurs between frames and allows a short period of time for adjusting PPU parameters, VRAM, and OAM.
Exact timing: 4560 cycles (10 lines)
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.
Exact timing: 80 cycles (2 cycles per OAM entry)
HDraw is when pixels are drawn.
Base timing: 172 cycles (min)
SCX % 8
TODO
TODO
TODO
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 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
).
IE AND IF
becomes zero, no interrupt vector can be located and instead $0000
is loaded into the program counter.TODO
Under some circumstances, OAM may be corrupted.
Triggers are:
inc
or dec
(this includes the implicit inc hl
performed by ld [hli], a
, and the implicit dec sp
s performed by push de
, for example) with the affected register pointing to OAM (TODO: is this Mode-dependent? Does ld hl, $FE00 ; dec hl
corrupt? Does ld hl, $FEFF ; inc hl
corrupt?)TODO: explain how exactly OAM is corrupted.
The OAM bug is fixed on CGB.
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)
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.
TODO
TODO
This document is licensed under the Creative Commons Attribution 4.0 International License (CC-BY 4.0)