Brian Robert Callahan
academic, developer, with an eye towards a brighter techno-social life
Yesterday I submitted my first ever piece of code to a "jam" event. You caught me, I didn't submit a game. And this jam is not a true competition like many jams are. But it was still fun nonetheless.
While I am no Vimlark, participating in jams always seemed like fun. Though I am often far too busy to be able to devote two or three days in a row to work on nothing but a single task. I heard about the PCjam, a jam event in celebration of the 40th anniversary of the release of the IBM Personal Computer probably on /r/retrobattlestations. I figured I could do this and give the whole jam format a try.
I have never actually written a program with MS-DOS and the Intel 8088 as targets. And while I could have broken out an assembler to write my jam program, I figured that since I won't have more than a day or two to spend on the jam, I should instead port something that I have already written to MS-DOS. Porting an existing program was explicitly stated as acceptable in the rules of the jam. The goal of the jam is to simply have a collection of programs newly available for the IBM PC. I decided to port my terminal-based sprite editor since I thought it would be easy and different than what others were likely to submit to the jam. And it would at least be gaming-adjacent!
With that, I was off.
Short of buying an actual retro computer, I'll need to find some way to get MS-DOS up and running. A good candidate for an emulator of some sort. But there are lots of MS-DOS emulators. What I need is an emulator that can dial its emulator CPU core down to an 8088 (or 8086). The jam's host recommends DOSBox-X and I learned that it has just this feature. Great! DOSBox-X also lets us mount a directory as a drive; I created a new directory named dos and in dosbox-x.conf
set it to be automounted.
Next, as sprite is written in C, I will need a C compiler. I don't need the C compiler itself to work on DOS, but I ended up settling on one that did: Open Watcom v2. I evaluated three C compilers that targeted MS-DOS: Open Watcom v2, GCC ia16, and the Amsterdam Compiler Kit.
Here is my quick evaluation of the three:
Targets multiple memory modes | Runs on DOS? | Ease of install | Ease of use | Good license | |
---|---|---|---|---|---|
OW v2 | Yes | Yes | Easy, installer for DOS | Easy, once learned | Not really, custom |
GCC ia16 | Tiny, small, and medium only | Yes | Difficult, I couldn't do it | Easy, it's gcc | Yes, GPL |
ACK | No, tiny only | No | I had to make an OpenBSD port | Easy, once learned | Yes, BSD |
I wanted to use GCC ia16, but I could not get it to work, sadly. The Amsterdam Compiler Kit only targets the tiny memory model, so that means you get only a single segment 64 KB in size, and everything has to fit in it. That's not so good. The only compiler left was Open Watcom v2, so it became the defacto choice by process of elimination. The only real downside is that Open Watcom v2 has a strange license is that accepted as open source by the OSI and no one else. But I suppose I am not doing anything that violates the license, and lots of other people use and have used Open Watcom compilers before, so it is probably fine if less than ideal. Maybe we need to find a way to make GCC ia16 easier to install—or better, merged upstream!
Open Watcom v2 installed without issue on DOSBox-X.
On OpenBSD (and all other Unices), sprite has two library requirements: ncurses for display and libpng for exporting to PNG files. I decided for ease of porting to remove PNG exporting from the MS-DOS version. The libpng documentation suggests that building and using on DOS is not ideal to not possible if you only have access to 640 KB of RAM, which is one of the requirements of the jam. If I can figure it out, I may add PNG export back to the MS-DOS port.
Additionally, as far as I know, ncurses does not work on MS-DOS. This means I had to find another library that could do similar work to ncurses. I found such a library in PDCurses, which has a good license and supports both Unix and MS-DOS. I downloaded PDCurses into my dos directory and got ready to use Open Watcom v2 for the first time.
PDCurses comes with a Makefile
for Open Watcom v2. It was just a matter of running wmake -f Makefile.wcc
and it built! Off to a good start. I don't know if this is strictly necessary, but in order to guarantee that I was definitely compiling for the 8088 I added -0 -ox
to CFLAGS
. The -0
flag tells Open Watcom v2 to target the 8086 CPU.
After compilation, I had a PDCURSES.LIB
file, which contained our static library.
I also wanted to make sure that the save format would be the same between Unix and DOS. However, the CGA color palatte is subtly different from the Unix color palatte. This is most noticeable in the ordering of colors. I changed the logic in init_colors
to match the Unix ordering. This way, you can transfer save files between Unix and DOS and the colors will be correct. I felt that was a necessity for the DOS version.
With that, it was time to build sprite.
I had to copy PDCURSES.LIB
to the sprite directory. I also needed to copy CURSES.H
, CURSPRIV.H
, and PANEL.H
from the PDCurses directory to the sprite directory. I wrote a simple Makefile
, ran wmake
and to my surprise it worked! Or, at least, it compiled. I still had to see if it ran.
Here goes nothing! I ran SPRITE
at the command prompt, and the canvas popped right up. Sprite was running on MS-DOS!
But that was on an emulated 386 or better. I had to see if the 8086 core would work. Then I could be happy. DOSBox-X has a CPU menu on its top bar. At the bottom of the CPU menu is CPU type. I selected the 8086 type. And for good measure, there is also an Emulate CPU speed option, from which I selected 8088 XT 4.77MHz (~240 cycles). And again, it worked. Barring owning real hardware, this is as close as I am going to get to calling it a success, so I called it a success. I pushed my changes to GitHub with a screenshot and submitted the program to PCjam. Jam completed!
I had so much fun porting sprite to MS-DOS that I decided to write a ground-up program for PCjam, though I have not submitted this one. It is an 8080 CP/M assembly language to 8086 MS-DOS assembly language translator. There are still plenty of bugs I am sure in the translator but if you give the translator simple CP/M programs, you should get working MS-DOS programs out of it. Give it a try if you have CP/M assembly lying around and send me pull requests with fixes!
I had fun porting sprite to MS-DOS for PCjam. Perhaps you want to participate as well. You have until August 12 to submit your programs.