When I was a child at the beginning of the 90s I’ve got my first PC. It had 640KB RAM, 2x5.25” diskette drivers and a CGA display. Of course, I immediately started playing all the games that were available for this beast machine and till this day I remember the feeling and excitement of playing all games with a wonderful 4 colors combination with 320x200 resolution 🤮.
One of the memorable games that I used to play was Dig Dug — a 1982 game created by Namco, originally for arcades and later ported to PCs. In this game, generally, you need to eliminate the enemies: Pookas and Dragons, by using a bike pump to inflate them with air until they explode, or by crushing them under large falling rocks.
So, I’ve decided to use my software engineering skills together with 8086 assembly knowledge I’ve earned 20 years ago while in high-school, for something good and try extracting all available textures directly from the game’s binary. For this task I’ve used DosBox debugger. Luckily, Dig Dug is a COM executable file, meaning that all code and data are stored in one segment. That made the assembly level debugging a little bit easier.
Before diving into some assembly, several words regarding how CGA graphics work. In 320x200 graphical mode, the CGA used a 16KB of memory, divided to 2x8KB buffers. The first buffer contained even numbered rows (0, 2, 4, …) and the second buffer contained odd numbered rows (1, 3, 5, …) (these two buffers were used for producing an interlaced output). The buffers are mapped starting from offset 0xB800. Each byte within a row contained the data of 4 pixels, i.e. each row size is 80 bytes. The value of each pixel was determined according to predefined color pallets, as demonstrated below:
(The CGA had several other modes, color pallets and resolutions).
Back to reversing, after some step-by-step debugging and some trials and errors, an interesting assembly function had emerged at address [CS:10A8]. This function is executed several times and manipulate the video buffer which is pointed by ES segment set to offset 0xB800. Check the below function code snippet:
I believe that the confusing part of this function is the one related to the correct texture placement in the buffers. It starts with:
[CS:10B5] and cl, 3h
[CS:10B8] add cl, cl
As mentioned, each byte contains data of 4 consecutive pixels, each 2-bits. The texture can be drawn anywhere on the screen and therefor drawing can start at an offset within a byte and end in the next byte in the buffer memory. Calculating the reminder of 4 will yield the start quarter within a byte and multiplying by 2 will result the exact bit offset within the byte. The bottom line is that CL holds the number of bits to rotate for placing the texture in the correct offset within a byte.
Next, a mask is created and rotated according to CL. This mask makes sure that current pixels which are out of the texture scope will not be changed. Note that the data in the memory and registers is inversed.
[CS:10C8] mov ax,0FF00h
[CS:10CB] ror ax,cl
[CS:10CD] and es:[bx+di],ax
After that, a texture byte is read from memory, rotated the same as the mask and then placed into the video buffer:
[CS:10D5] xor ah,ah
[CS:10D7] ror ax,cl
[CS:10D9] or es:[bx+di],ax
In total there are 4 possible different masks. The below diagram demonstrates a simple texture placement in all possible offsets within video buffer bytes and the relevant mask:
As an example for drawing textures using this function, consider the below textures and the extracted code snippet which draws the DIG DUG title when the game loads:
The below resulted image is actually extracted directly from the video buffer, while in debug mode, executing the above code.
OK — that’s all assembly for today 😊.
Having the knowledge of CGA graphics and the function which draws texture, I’ve examined the binary file (the whole game is one 23.6KB file). In total 198 textures were found (~25% of the binary size is textures data):
- 103 textures at offset 0x4270–0x57B8.
- 32 textures at offset 0x579E-0x59AD.
- 63 textures at offset 0x5A2E-0x5E1D.
Writing a simple C program with SDL2 library, all original textures are revealed:
Nice… Mission completed.
The C program for extracting the texture is available in the following link:
Dig Dug Reverse Engineering and Graphic Textures Extraction Permalink Failed to load latest commit information. Dig Dug…
Final thoughts following this work:
- Reverse engineering of an old binary is like archeology — you are digging something old knowing what you need and want to find, but at any time you may give up thinking maybe you took somewhere a wrong path.
- Back in that days, development was a labor-intensive task that now we can appreciate: each game had to be implemented from the beginning to the target machine as each had different specifications (CPU with different instruction set (ISA), graphics adapters, resolution, …)
- Even though the technology was “basic” (we are talking on a game from the beginning of the 80s), it had some complex ideas implemented for providing a high user experience: animations, music, graphics tricks, …
Some information in this article is extracted from Wikipedia. Check the below links for additional information:
Dig Dug - Wikipedia
Dig Dug [a] is a 1982 maze arcade game developed and published by Namco. It was distributed by Atari, Inc. in North…
Color Graphics Adapter - Wikipedia
The Color Graphics Adapter ( CGA), originally also called the Color/Graphics Adapter or IBM Color/Graphics Monitor…
COM file - Wikipedia
A COM file is a type of simple executable file. On the Digital Equipment operating systems of the 1970s, .COM was used…
That’s all for now — let me know what you think.