Video summary
Gameboy Emulator Development - Part 05
Main summary
Key takeaways
Tech Focus of the Video (Game Boy Emulator, Part 05)
Goal
- Finish CPU memory access for:
- Working RAM (WRAM)
- High RAM (HRAM)
- Implement enough instruction behavior to test the emulator.
Context / What was broken before
- In the previous video, the emulator hit unsupported bus access (e.g., around addresses like
0xD600). - This video fixes the emulator’s bus read/write memory map and adds RAM backing storage.
Memory Map Implementation (Bus Read/Write)
The speaker updates the emulator’s bus read and bus write routing using an else if chain to map address ranges to correct backing memory and behavior.
Mapped regions described
-
Cartridge / character-related placeholder
- Addresses starting around
0xA000 - Treated as CHR/character map data / BG map areas
- Not fully implemented yet (marked as “todo/ignore”)
- Addresses starting around
-
Cartridge RAM
- Range
0xC000–0xDFFF - Mapped to cartridge RAM via:
cart_readcart_write
- Range
-
Working RAM (WRAM)
- Range
0xE000–… - Includes WRAM bank 0 / bank 1
- Uses dedicated functions:
wram_readwram_write
- Range
-
Echo RAM
- Described as “reserved aka echo ram” around the
0xE000area - The speaker doesn’t understand it deeply yet and returns
0/ ignores it for now
- Described as “reserved aka echo ram” around the
-
OAM / PPU-related placeholder
0xFE00–0xFE9F: Object Attribute Memory (OAM)- Marked TODO
- Deferred until the PPU is implemented (with a note to avoid derailing CPU emulation progress)
-
Unusable / reserved ranges
- Several regions like
0xFEA0–0xFF00and portions under0xFF00 - Treated as “unusable/reserved” and return
0
- Several regions like
-
I/O registers (deferred)
- Up to
0xFF80includes controller and other I/O registers - Current behavior:
- If accessed, log an error
- Do not exit, so tests can proceed
- Up to
-
High RAM (HRAM)
- Range
0xFF80–0xFFFF - Mapped as HRAM using:
hram_readhram_write
- Note: the speaker mentions HRAM is sometimes called “zero page” (naming varies)
- Range
New RAM Module Added
A new module is introduced:
ram.c- Header:
ram.h
RAM sizes
- WRAM size:
0x2000bytes - HRAM size:
0x80bytes
Provided functions
wram_read(addr)wram_write(addr, value)hram_read(addr)hram_write(addr, value)
Implementation details
- Reads/writes offset the address by subtracting the region base:
- WRAM subtracts
0xC000 - HRAM subtracts
0xFF80
- WRAM subtracts
- Includes a basic example for invalid addresses (though the speaker expects the bus won’t send invalid ranges)
Result
- After compiling/rerunning, the earlier “invalid bus read/write” issue disappears.
- More debug output becomes visible.
Register Debugging Improvements
The debug output improves from showing only:
A B C
to showing:
B, C, D, E, H, L
It also uses combined register printing from fields like ctx->regs.* to better verify instruction effects involving memory/register interactions.
Instruction Implementation / Update: LDH and Bus Testing
Identifying the issue
- Failures around
0xE0are traced to theLDHinstruction. - The target addressing was unsupported/mismapped.
- The fix is to implement
LDHwith correct HRAM addressing.
Implementation summary
- Adds a
proc ldhfunction. - Uses conditional logic based on instruction addressing mode fields.
-
For the “read from C register OR A to HRAM” style:
- If
reg1 == A:- Read from
A - Write to HRAM using the immediate offset/address bits
- Mentions masking with
& 0xFF00
- Read from
- Else:
- Opposite direction (write/fetch depending on mode)
- If
-
Adds an extra CPU cycle for
LDH.
Opcode table integration
- Adds
LDHmapping for:0xE0(LDH A,(a8) style)0xF0(LDH A,(a8) style opposite direction)
- The instruction table entry includes:
- addressing mode noted as “am”
- register types like A8 and A
Verifying Memory Map Correctness via Emulator Tests
After RAM + LDH:
- The emulator progresses further through more
LD/LDHinstructions. - New failures are traced to:
- I/O access at
0xFF00(handled by logging an error and continuing) - Interrupt enable register
IEat0xFFFF- Reads/writes fail because it wasn’t implemented yet
- I/O access at
Implementing Interrupt Enable Register (IE) Support
To fix failures at 0xFFFF:
Changes made
- Add
ieas a field in CPU context:u8 ie
- Add CPU accessors:
cpu_get_ie_register()cpu_set_ie_register(value)
- Update bus/CPU logic to read/write the
IEregister using those accessors.
Result
- Execution proceeds past the earlier failing instruction locations.
Deferred to the Next Video (Part 06)
- Call / jump / return instructions (explicitly stated as the main focus of Part 06)
- PPU / OAM implementation is deferred
- I/O controller/register handling is deferred (currently only error logging exists)
- Echo RAM behavior is simplified/ignored
Main Speakers / Sources
- Primary speaker: the author of “low-level devil” (YouTube)
- Source narration: “Gameboy Emulator Development - Part 05”