Booterify: (Re)converting games to PC-Booter

Introduction

Booterify is a simple bootloader that fits in the first sector of a floppy (512 bytes) and a tool to create boot disks form a DOS executable (.COM or .EXE).

My goal in doing this was to recreate disks for old PC booter games that used to boot directly without using DOS, but booterify can of course be used to make a PC booter out of new retro creations.

Current version features:
  • Supports .COM executables
  • Supports .EXE executables (64 kB max.)
  • Provides a BPB (Bios parameter block) to enable booting from USB keys
  • Detects potential DOS interrupt calls, displays their address and hex dump around the call
  • Can generate a list of breakpoints in bochs syntax for each DOS service call instance
  • Implemented DOS services:
    • int 21h/AH=02h : Print a character
    • int 21h/AH=09h : Display string
    • int 21h/AH=25h : Get interrupt vector
    • int 21h/AH=35h : Set interrupt vector
  • Loader for PCjr cartridge and PCjr ROM manipulation tool.
See below: List of tested games



What is a PC Booter?

The PC Booter term refers to games or software that used to start without relying on an already installed operating system, usually directly from a floppy at power on.

This technique was popular during the 80's. For PCs without a hard drive, this was somewhat convenient as it saved some steps: No need to boot dos first and the change the disk to start the game. On the other hand, it also made the game a bit more difficult to copy backup (it was a form of copy protection) and prevented hard drive installation...

Many games from this era are now available on abandonware sites, but most have been converted to .COM and .EXE formats for convenience.




Why now?

I acquired a Tandy 1000 EX with a single floppy drive and no hard drive. I thought it would be fun to relive the experience of booting the games directly, as I used to do years ago.

Of course nothing would have been easier than creating a bootable DOS floppy (with format /s for instance) with an autoexec.bat to start the .COM or .EXE version of the game. But that would not have been very interesting. Instead, I chose the difficult (and very instructive) path of creating my own loader and tool to convert .COM and .EXE file to a floppy disk image.




How booterify works

The PC BIOS loads the first floppy sector (512 bytes) to a known memory location and executes it. This small piece of code often loads a larger program to do the real work, but for booterify, 512 bytes is more than enough to load and run the game.

The loader calls the BIOS interrupt 13h, function 2 in a loop to read floppy sectors to memory. Since sector 0 holds the loader, the game program is divided in blocks of 512 bytes and simply stored from Sector 1 to N according to its total size (maximum 64kB at the moment).

Some memory locations in the loader program are automatically patched by the floppy image creation tool:
  • Number of sectors to copy
  • Number of sectors per track (depends on the type of floppy [eg: For a 360k floppy, there are 9 sectors per track])
  • Program entry point offset (initial IP) for the program (ex: For a .COM, it is always at 100h)
  • Initial start pointer (SP) offset (For a .COM, points at the end of the segment)
  • Destination code segment (CS)
  • Data and stack segments (DS, SS) (All equal to CS for .COM executables)
.COM executables are easy. Only the first two parameters (size and sectors per track) will vary. The other parameters make .EXE support possible, provided the load module size does not exceed 64Kb. The floppy image creation tool will detect the file format (.COM or .EXE) and take care of complications specific to .EXE files, such as segment relocation.

Beware: Be it a .EXE or a .COM, the game or utility will work fine as long as it does not make calls to DOS services[1]. The image creation utility will try to detect byte sequences that look like DOS interrupt calls (CD xx sequences) and will emit a warning and a hex dump around the call. Disk creation will not be aborted however. Said byte sequences may appear anywhere, not only in code (eg: In data).

It is up to you do disassemble your executable or the hex dump to investigate. You can of course just try booting the thing too. As a rule of thumb, if the game has data files, it certainly will not work. If the file is a single executable, maybe it will work. (And if the game was listed somewhere as a PC booter, it is a good sign.)

[1] The loader remains in memory and implements in fact a few DOS services: INT 21,AH=09h, INT 21h,AH=25h and INT 21h,AH=35h. The other int 21h services are not implemented and control is immediately returned to the caller via RETI.



Creating a disk image

Here is help:
$ ./booterify -h
Usage: ./booterify [options] bootsector.bin executable output.dsk

Where:
 - bootsector.bin is the bootloader,
 - executable is the input file (.exe or .com),
 - output.dsk is the output file.

Options:
 -h             Prints help
 -c             Force input file format as .com (default: auto-detect)
 -e             Force input file format as .exe (default: auto-detect)
 -s             Sectors per track
 -t             Target disk size (padded with zeros). If 0, no padding.

 Debugging/Development:
 -B file        Generate list of breakpoints commands for bochs for all
                instances of DOS int calls

Common disk parameters:
	360k floppy:  -s 9 -t 368640
	1.44MB floppy:  -s 18 -t 1474560

Note: Padding with -t as above is not required when writing to
	a physical floppy, but it can help for emulators or virtual
	machines that use the file size to determine the floppy type.
Here is a use example creating a bootable 360kB disk for Alley Cat:
$ ./booterify -s 9 -t 368640 bootsector.bin ../exeinfo/cat.exe boot1.dsk
Bootstrap file: bootsector.bin
Bootstrap size: 512
Payload file: ../exeinfo/cat.exe
Payload file type: .EXE
Output file: boot1.dsk
Sectors per track: 9
Output file padding: 368640 B / 360.00 kB / 0.35 MB)
Reading exe file...
File size: 55067
Load module size: 54555
Relocating...
Relocation 0 : 0723:0009 (linear address 0x00007239) : 0x0010 -> 0x1010
Relocation 1 : 0723:0541 (linear address 0x00007771) : 0x0010 -> 0x1010
Relocation 2 : 0723:1125 (linear address 0x00008355) : 0x0010 -> 0x1010
Relocation 3 : 0723:13ed (linear address 0x0000861d) : 0x0010 -> 0x1010
Relocation 4 : 0723:14b8 (linear address 0x000086e8) : 0x0010 -> 0x1010
Relocation 5 : 0723:1501 (linear address 0x00008731) : 0x0010 -> 0x1010
Relocation 6 : 0723:2ade (linear address 0x00009d0e) : 0x0010 -> 0x1010
Relocation 7 : 0723:3a98 (linear address 0x0000acc8) : 0x0010 -> 0x1010
Relocation 8 : 0723:5c9f (linear address 0x0000cecf) : 0x0010 -> 0x1010
Payload size: 54555
Code : 0x1723:0x0000
Stack : 0x1000:0x0100
Writing boot1.dsk...
Bootstrap: 107 sectors to copy, 9 sectors per track, initial IP 0x0000




Testing the image

The disk image created as above can be tested in vmware:



The bochs emulator is also a good testing tool, especially if you need to debug. You will have to use a line such as this one in the configuration file:
floppya: type=1_2, 360k="boot1.dsk", status=inserted, write_protected=1



Transfering the image to a floppy

Under Linux

Under Linux creating a physical disk is a simple matter of inserting a formatted disk and using dd to copy the data directly:
dd if=boot1.dsk of=/dev/fd0
107+1 records in
107+1 records out
55067 bytes (55 kB) copied, 4.69115 s, 11.7 kB/s
As expected, a PC will boot using the disk created above:
Loading...

Loading...

Success!

Success!



Under DOS with a hard drive or two floppy drives

The rawrite tool, often used to create Linux boot disk before the coming of bootable CD-ROMs and USB pens, is perfect for the job.


Under Windows

You could probably use rawrite32.


Under DOS with a single floppy drive

If you only own one drive able to write the target floppy format and it happens to be the only drive in the host machine which do not have a hard drive, instead of temporarily moving the drive to another computer, consider using PPUSBComm.

With PPUSBComm a disk image can be sent using USB and the target machine's parallel port and the image is written directly to floppy sectors so no temporary storage (hard drive or extra floppy drive) is required.
Transfer in progress

Transfer in progress

Writing sectors

Writing sectors

Success!

Success!



The game shown above is Tandy Cat (Alley Cat patched for Tandy graphics).


PCjr support

Since version 1.6, booterify includes a loader (pcjrloader.asm) for loading from a PCjr ROM cartridge instead of a floppy. A companion tool called jrromchk is also introduced to compute the CRC, set the size in the ROM header and convert between raw binary and .JRC rom formats.

Have a look to my PCjr cartridge project for a good example on how to use this to make an Alley Cat cartridge.

Alley Cat on a PCjr cartridge!

Alley Cat on a PCjr cartridge!






Downloads

Here is the source code. To compile the loader (bootsector.bin) you will need nasm. And to compile the disk image creation tool, the usual Linux development tools are required (gcc, make, etc.).

For the moment, I only distribute the project in source form. But if there is some interest, I'm willing to prepare a Windows build. (But it will still be a command-line tool)

New, June 2018: For a precompiled Windows version working in command-line, download the .zip file below.

RSS feed for this table
Version 1.6
October 20, 2019 (Sunday)
First version able to convert executables to PCjr cartridge ROMs.
  • Bios parameter block and output file padding can now be disabled using -f 0
  • Add the jrromchk tool, to convert between .JRC and raw PCjr ROM formats
  • Add a loader for PCjr cartridges (pcjrloader.asm)
File(s):
booterify-1.6.tar.gz (14.9 KB)
booterify_win32-1.6.zip (147 KB)
Show previous releases...
Version 1.4
February 5, 2019 (Tuesday)
  • Initialize the command-line fields of the PSP correctly for .COM executables. (Use length of 1 and add a 0D terminator instead of zero'ing everything)
  • Implement int 21h,02 (DOS putchar)
  • Add a version string in the loader and in the tool
  • Add a makefile for cross-compiling the windows version with MXE
File(s):
booterify-1.4.tar.gz (11.4 KB)
booterify_win32-1.4.zip (94.3 KB)
Version 1.3
March 1, 2017 (Wednesday)
Disk images now have a standard FAT12 filesystem so besides being bootable, floppies may also contain extra data (.EXE version of the program, documentation, etc...)
File(s):
booterify-1.3.tar.gz (10.6 KB)
booterify_win32-1.3.zip (93.8 KB)
Version 1.2
July 26, 2016 (Tuesday)
First release version
File(s):
booterify-1.2.tar.gz (7.6 KB)
This project is also available on GitHub!
To request features, report issues or contribute, you may send me an email or use the GitHub repository:
https://github.com/raphnet/booterify



Tested games

Here is a short list of games I tested with booterify:
  • Agent USA
  • Alley Cat (original and a version patched for Tandy graphics)
  • Apple Panic
  • Burger Time
  • Digger
  • Dig-Dug
  • Galaxian
  • Miss Pac-man
  • Pac-man
  • Pipes
I also tested with RATillery, a game I created.

If you test with other games or software, please let me know! I would be delighted to learn that someone other than me had a use for this project...


References

Here are a few technical references that were of significant help for this project:


Disclaimer

I cannot be held responsible for any damages that could occur to you or your equipment while following the procedures present on this page. Also, I GIVE ABSOLUTELY NO WARRANTY on the correctness and usability of the informations on this page. Please note, however, that the procedures above have worked in my case without any damages or problems.

Now you cannot say that I did not warn you :)