Brian Robert Callahan

academic, developer, with an eye towards a brighter techno-social life



[prev]
[next]

2021-06-04
I participated in my first "game" jam

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.

Setting up the MS-DOS environment

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.

Choosing a C compiler

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.

Porting sprite to MS-DOS

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.

Building PDCurses

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.

Building sprite

Now that I had PDCurses, I could build sprite itself. As I am limited to CGA graphics, this means an 80x25 text mode with 16 colors. On Unix, I have 256 colors and a text mode of arbitrary size. Because of this arbitrary size on Unix, I have three canvas sizes: 8x8 small, 16x16, and 32x32 extended. On Unix, if you choose the extended canvas, at startup sprite will figure out how big your terminal is and only give you the extended canvas if your terminal is large enough. If not, sprite will fall back to a 16x16 canvas. An 80x25 is too small for the extended canvas, so I removed all the code for the extended canvas. The user still has the option for a small canvas.

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.

Testing sprite for MS-DOS

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!

But wait, there's more!

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!

Conclusion

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.

Top

RSS