For some strange reason I decided to create a version of Q*bert for the Color Gameboy by disassembling the original arcade ROM and rewriting it into 'C'. I could not have pursued this mindless obsession...er, I mean "dream", without the MAME Arcade emulator. MAME and its built in debugger were invaluable for observing variables and the behavior of code segments that I didn't understand simply by reading.
|Q*bert is only 64K of ROM, but that's quite a bit of code to pour through- especially since I had to have an exact understanding of what everything did. Fortunately I found a freeware tool on the Net called IDA, the "Interactive Disassembler". It's actually a commercial product but they give out a crippled version that basically can only disassemble 8086 assembly. Serendipity: 8086 is what Q*bert was written in. IDA is really cool- it shows you where subroutines begin and end and labels memory locations automatically. The labels start out generic (i.e. var_F1C4) but as you figure out what things are you can rename them and the name appears throughout the source.|
Using the description of Q*bert's memory and hardware from the MAME source along with MAME's built in debugger and IDA I began the task of reverse engineering Q*bert. Initially very tedious, the process became quite enjoyable. Instruction by instruction, it was like a puzzle- with each variable or function that I identified and labeled more was revealed about the game and the easier the process became. Eventually I had most of the ROM disassembly labeled, commented and understood.
|Next I had to convert my annotated 8086 assembly listing into 'C'. The ROM is hand-coded assembly, not C-compiler output which made understanding it a lot easier (no stack frames, local vars, etc) but a challenge to convert to 'C'. I quickly abandoned my effort to convert the assembly to proper 'C' and instead created mutant 'C' code that looks like 8086 assembly. That is, I used variables named AH, AL, etc. and lots of gotos. It's pretty ugly but it preserves the exact functionality of the original code.|
A few sections of the original ROM made fairly specific use of the 8086's 16 bit registers and various flags and condition codes. For these I typically coded directly in Z80 assembler since the 'C' code to accomplish it would have been way too inefficient. I also used assembler for most of the graphic and sprite drawing routines. However, the majority of the game is in 'C' and in fact I debugged most of the core logic (hopping, collision detection, etc) using DevStudio in Windows.
The result is a game that is functionally identical to the original game. The levels, the order of enemies, the motion...everything. For just about everything I use the exact same structures, variables and code sequences as the original game. If you play the original arcade game and take a snapshot 45 frames into level 2, round 4 then do the same with my version you will see the exact same image.
|OK- so the game doesn't look *exactly* the same. I had to make some
modifications to make it playable on the Gameboy hardware. The most obvious change
is that the full Q*bert screen doesn't fit on the Gameboy so I scroll the playfield.
This meant that the top of the screen where score and stuff is kept frequently
won't be visible. I used the ubiquitous "status bar" overlaid at the
bottom of the screen to convey the important game info.
The biggest change to maintining identical view to the original is the little spinning disks. On a real Q*bert they are implemented with sprites and contain 6 colors. To get a 16x16 sprite with 6 colors I'd have to layer 4 Gameboy sprites. Compounding this is that there are 2 disks per row in the pyramid...chewing up 8 Gameboy sprites. Given that the game characters all use 3 or more sprites I'd be exceeding the dreaded 10 horizontal sprite maximum abd probably run out of sprites entirely when a few enemies are on the screem.
Instead I implemented the disks with tiles which meant I had a whopping 3 colors to work with. Actually by using HBLANKs I figured out a way to get all 6 colors, but it was a lot of overhead. I may add that in the future though.
The other major difference is that v1.00 has no sound. Initially I wrote a digital sound driver and converted WAVs recorded from MAME into 4bit 8kHz for the CGB. The results were OK in NoCash but sounded horrible on a real Gameboy. I've played some commercial games that have decent sounding digital audio so it should be possible I think. Next I tried normal use of GB sound registers but due to my lack of understanding the resulting beeps and bings weren't worthy of Q*bert so I left sound out completely. If anyone out there is interested in helping me with that please contact me. No money, but you can get your name in lights.