David Grace

Bay Area, California

Programmer, SysAdmin, Artist

Decoding Ancient Image Files

I’m going to rewind a bit. I started making games in DOS, using GW-BASIC (and later QuickBASIC) on my first 16-bit computer.

These games aren’t much to talk about, being that I was just a pre-teen at the time. Nontheless, the games hold a special place in my heart. I fondly remember the days of puzzling out the code needed to make my first platformer game. This was all before the Internet, and my only source of documentation was the GW-BASIC Technical Reference Manual by Microsoft.

Twenty-six years later, and I am presented with a unique problem. All of the data I used to store the graphics for my games is now unreadable. JPG and BMP didn’t exist. GIF was around, but it was unknown to me. Universal image file formats were not a common occurrence.

Like everyone else around that time, I stored my image files in extremely unique and proprietary formats. In particular, I used BSAVEd sections of video memory.

From Hunters Law  (circa 1990).

History of BSAVE/BLOAD

BSAVE is sort of a file format. It isn’t really a standard but more of a built-in command in GW-BASIC which allowed you to dump sections of memory to disk. QuickBASIC (and later PDS BASIC) uses the same file format.

So, to save an image, you had to make a copy of video RAM to BASIC memory space, and then save this chunk of memory to disk. It was actually quite simple and I remember I first encountered it in a demo program for GW-BASIC. It was a Lunar Lander game and I was puzzled at how the programmer defined their graphics. I saw no DRAW command or other common graphics operations. Clearly, the programmer was storing graphics in files on the disk and then loading them at run-time.

Brilliant idea, I thought. I didn’t realize it at the time, but I was learning the important concept of segregating layers of functional responsibility. You should draw your graphics elsewhere, save them to disk and then re-load them in the actual game. This simplifies the game code itself, plus it prevents a distracting “flash” seen at the start of my games, where I would draw everything on-screen using BASIC graphics commands and then grab sprites from the frame buffer.

So I worked on developing my own graphics editing programs, which saved data to BSAVE chunks of memory. This is all and great, but now, in the distant year 2016, I have no easy way to view these images. They are linked to the game source code and it’s becoming increasingly hard to run those games.


Back in 2003 I decided I want to preserve the art of my older games and so I wrote a small C++ program which read these BSAVE programs and displayed them using SDL. EgaViewer wasn’t a very advanced program and had no UI, but it did work. However, it could only display certain files from some of my games, and only from the EGA versions – It didn’t decode CGA graphics.

From Lone Survivor (unfinished sequel to Hunters Law).

So this weekend I decided to revisit this project. I re-wrote the program using C# and Microsoft Visual Studio (with a WinForms UI) and it is available at the end of this article.

The program is simple. It first loads the BSAVE data and then it tries to decode said in various manners. Not all of my images were simple dumps of video RAM; Some were multi-sprite dumps (such as font files), and therefore need to be handled specifically by my EgaViewer v2. I also included the ability for EgaViewer v2 to decode CGA graphics, not just EGA.

BSAVE files are not real image files. As I mentioned, they are dumps of memory, and that’s it. The only information contained in the file is where to load that memory and how big it is. Therefore EgaViewer has no real file standard to work against; It has to guess what sort of graphics data it is loading. It’s able to detect most of my common formats, though it has no idea if it is loading EGA or CGA data. Therefore, the program simply reads the data and then attempts to interpret it in various ways for display.

I give full control over the user on what format to use for decoding the data. Currently, it only supports SCREEN 1 (320x200 CGA) and SCREEN 7 (320x200 EGA) video modes, as 99% of my games were created in these two video modes.

User interface for EgaViewer

The code has been released as a MIT licensed project, so if you want to take it and use it to display other video formats, go right ahead. It will display out-of-the-box BSAVEd sprites, plus a few custom formats that I developed during my early years of CGA/EGA game making.

To load an image in the program, just double-click on the file in the list.

The source code for EgaViewer, plus detailed description of image formats.

Installer for EgaViewer (Windows 32/64-bit).

See you next time!