Gameboy Emulation

Thu Jan 21 2010

This is just a page with a few notes that somebody may find useful. I hope to develop it as time goes by.

gbemu-test

Assembly Example

First off, I downloaded a very simple ROM file, which was a file called ‘VGB Lord Demo (PD).gb’, and has been instrumental in the testing of an emulator I’ve been developing.

The ROM weighs in at 32,768 bytes, however, a mere 1,536 bytes are actually used, which is definitely a good thing for testing purposes!

The breakdown is like this:

  • 0x000 to 0x1BF – 448 bytes of opcodes
  • 0x1C0 to 0x3BF – 512 bytes of tile (image) data
  • 0x3C0 to 0x5FF – 576 bytes of tile map data

At offset byte #402 within the ROM, the following sequence for loading the tiles into memory occurs:

#1) 21 00 80        ld hl, 8000     <- 0x8000 is the video memory location  
#2) 01 C0 01        ld bc, 01C0     <- 0x1C0 is the location in the ROM for the tile data  
#3) 16 00           ld d, 00        <- Loads the value 0x00 into Register D \*  
#4) 1E 02           ld e, 02        <- Loads the value 0x02 into Register E \*\*  
#5) 0A              ld a, \[bc\]    <- Load the value at BC into A  
#6) 22              ldi \[hl\], a   <- Load into location at HL the value of A and increment value  
#7) 03              inc bc          <- Increment BC  
#8) 15              dec d           <- Decerement D  
                                    <- Z Flag gets set if result equals 0)  
                                    <- N Flag gets set anyway)  
                                    <- H Flag set if no borrow from bit 4)  
                                    <- C Flag Unaffected)  
#9) C2 9C 01        jp nz, 019C     <- Jumps to 0x19C in ROM if Z == 0 (Meaning D != 0 yet)  
#10) 1D             dec e           <- Decrement E (Flags set as previously mentioned)  
#11) C2 9C 01       jp nz, 019C     <- Jumps to 0x19C in ROM if Z == 0 (Meaning E != 0 yet)  
#12) C9             ret             <- Returns back to where this loading function was called
  • Register D starts from 0, and when decremented, will wrap around to 255, thus allowing it to count down to 0 allowing the 256 values

  • Register E is set to 2 and allows the loop to run through a second iteration with D counting down to 0 once again allowing for a total loop of 512 long (2 (E) x 256 (D) = 512)

Given these structures:

rom_data[32768];  
mem_data[32768];

In C, with access to values greater than 8-bit (for values above 255), that chunk of assembly is as simple as this:

for (int i = 0; i < 512; i++)  
{  
    mem_data[0x8000 + i] = rom_data[0x1C0 + i];  
}

Resources

  1. http://www.codeslinger.co.uk/pages/projects/gameboy.html
  2. http://marc.rawer.de/Gameboy/Docs/GBCPUman.pdf
GatsbyNetlifyReactTypeScriptTailwind CSS
© Copyright 2008-2022 Terry Butler