Reviving a 19 Year Old Gameboy Emulator
Back in 2014 I was messing around with the idea of converting Gameboy .GBS soundtracks into Amiga .MOD files for a game I was doing. If you don't know what a .GBS file is, it's basically just a Gameboy ROM with z80 code but with the graphics routines and gameplay stripped out, so it's just the sound driver and music data, so in order to play it back you essentially have to emulate the full Gameboy processor and sound chip. At the time I was sort of infatuated with FreePascal and Lazarus, and wanted to find a Gameboy emulator written in Pascal that I could maybe yank the CPU and sound code from.
Somehow after scavenging over a bunch of old forum posts, I found (apparently) the only Gameboy emulator written in Pascal, ever: UGE. It was written by a guy named Christian Hackbart and released in 2000, and the only available download was from a mirror on Zophar's Domain. I started it up, loaded a ROM, was met with some ear-piercing noise, and then the emulator crashed. I canned the project pretty shortly after and that was pretty much that.
Fast-forward 5 years and I had the idea for another project centered around the Gameboy's sound system, and was compelled to go dig up the old code again and maybe see if I could fix it-- after all, it might be a good learning exercise to fix this thing up, and I kinda like the idea of an old abandoned piece of software rising from the ashes. So I dug in and tried to find out why this bad boy is flipping its graphics upside down, belching out horrible sound, running insanely fast, and crashing.
Fixing the speed
By a stroke of luck, I figured out that the reason the emulator was crashing: the sound emulation. If you untick the sound box in the menu, it stops running the sound code and it can be played for more than 5 seconds before blowing chunks. It still runs insanely fast and the grahpics are upside down though. I tackled the speed issue first. That should be as simple as just throwing in a spinloop to waste time and lock it to 60fps or whatever.
It looks like there was an attempt at this already in the code, using the Win32
QueryPerformanceCounter API, called
RealSpeedEmulation. Unfortunately it calls
QueryPerformanceCounter somehow completely wrong, passing in a member of a record rather than a pointer to that record... No idea why. I just ditched
RealSpeedEmulation and did what GameLad does, which is just spin for a period of time until we need more cycles to be emulated.
Bam! Already it's almost playable, and the sound isn't causing crashes. I think it was crashing before because the extreme speed of the emulation was causing a sound buffer overrun or something.
Fixing the graphics
The emulator actually does render the screen right-side-up when using DirectDraw, but I can't record that with OBS for some reason. It renders flipped graphics when drawing with GDI-- let's fix that. In
dib_out.pas I changed
biheight := 144; to
biheight := -144; and....
Nice. We've eliminated the