Using DOSBox and emscripten to Put Old Games onto the Web
You are reading an older blog post. Please be aware that the information contained in it may be technologically outdated. This text may not necessarily reflect my current opinions or capabilities.
August 28th, 2015
Back in January of this year, the Internet Archive published their interactive DOS game library, allowing anyone to play old games that used to run on MS-DOS machines right in their browser, without the need for any plug-in or external software. This was very inspiring to me and reminded me of the time when I took my first steps in the world of programming using Turbo Pascal and compiling for DOS. Naturally, I made games in it.
I made a mental note to check out the underlying technology, but in January I was knee-deep in the process of finishing my master's thesis (followed by a move and a new job), so the “DOS in my browser” thing went somewhere near the bottom of my priority list.
In early June I dedicated a weekend to finally figuring that stuff out, which culminated in me adding a playable version of Revelation Mentis to my website. The way I first learned programming was by taking existing source code (typically little games) and tinkering with it, first changing values, then single instructions, then larger blocks of code. RM is notable in my personal history for being the first game (as well as the first non-trivial program) that I created on my own and completely from scratch, so it seemed like a good candidate for something to put on my website for posterity.
As I found out, many talented developers have made this process comparatively smooth – smoother than I had expected, anyway. Still, it's not a “drag and drop” kind of solution, you still need some coding chops to put all the pieces together. I'd like to walk you through what I did, just in case you're interested in doing something similar or you're curious about how it works.
Setting Up the Build Environment
In a nutshell, emscripten compiles C/C++ code to JavaScript, while DOSBox is an application that can run most DOS applications, including my old Revelation Mentis binary. I won't pretend to be knowledgeable enough about emscripten to know how exactly the various abstractions are divided between the two, but the end result is a (from what I can tell) complete version of DOSBox including graphics, sound, file system access and more that runs without a hitch in modern browsers.
My development machine is running Ubuntu Linux 15.04, which packages emscripten 1.22 as of today. That turned out to not be enough for the version of DOSBox that I used, so I got the portable SDK and followed the instructions for installation of the most recent version of emscripten on Linux, which are straightforward. The compilation involved can take a while though, so it's best to have your beverage of choice ready at this point.
With a recent version of emscripten up and running, the next step is to grab em-dosbox, a port of DOSBox to emscripten maintained by Boris Gjenero, and follow those installation instructions as well. The first make
command leaves you with a bare instance of DOSBox compiled to HTML and JavaScript. Due to the same-origin policy, you'll need to launch the generated webpage through a local webserver (for example python -m SimpleHTTPServer 8000
) to get it running.
Packaging the Game Data
The next question is how to get the DOS application binary into our webpage. The em-dosbox documentation has instructions for that too, the tool includes a packager that can easily put your EXE file into a virtual filesystem that em-dosbox can later use. That should allow you to quickly get your DOS application up and running.
In the case of Revelation Mentis, I had some fine-tuning to do in order to get the exact experience that I wanted. Out of the box, some characters in the title screen ASCII art are rendered wrong. This is because my machine from back then used code page 850 and I (blissfully ignorant of internationalization at the time) used the 0xF7 Cedilla as part of my game's title screen. After a few minutes spent on the DOSBox wiki, I learned that I needed a dosbox.conf with the line keyboardlayout=gr
in the [dos]
section to rectify this problem. Unnecessarily, this should also change the keyboard layout to German for all users, but as it turns out Revelation Mentis only uses keys that are identical on US and DE keyboards, so it's not an issue. Packaging my dosbox.conf along with the game binary was accomplished by following em-dosbox instructions again.
By default, the generated instance of DOSBox automatically launches the intended binary. Unfortunately, after exiting the game the user is left at a DOS prompt. By passing it the -exit
parameter, DOSBox can be instructed to terminate itself after the designated DOS process has ended. There are two easy ways to accomplish this with em-dosbox, you can either modify the packager script to include the option (advisable if you're rather sure you want this behavior for everything you package) or you can modify the generated HTML file afterwards (recommended if you just want to test it out or you're not sure if it's what you want).
If you decide to adjust the packager script, look into src/packager.py
for the line where a string containing Module['arguments']
is being written – in the current repository snapshot I'm looking at it's line 124:
f.write("Module['arguments'] = [ " + cmdline + " ];\n</script>\n")
Please note that this is Python code outputting JavaScript code (and a closing HTML tag), so don't waste too many brain cells wrapping your head around the syntax here. You can add the exit parameter as follows:
f.write("Module['arguments'] = [ '-exit', " + cmdline + " ];\n</script>\n")
If you instead decide to change the generated HTML file, it's actually that very line that the packager script is writing that you need to adjust. Look for the JavaScript line starting with Module['arguments']
that looks about like this:
Module['arguments'] = [ './binary.exe' ];
And change it to this:
Module['arguments'] = [ '-exit', './binary.exe' ];
But keep in mind that this line gets overwritten every time you run the packager.
After all this, I had a version of DOSBox inside a webpage that ran my game as intended. The only remaining task was to change the resulting webpage into something suiting my tastes.
Polishing the Front End
With all the compiling and packaging woes out of the way, you should now have one HTML file and some JS and data files. This is where your HTML and JavaScript knowledge comes in and you get to make whatever changes you want to the HTML code. There's nothing particularly challenging or unique about this part, so I'll just quickly go over what I did.
I hid a number of UI elements that I didn't want, like the DOSBox stdout text field and the graphics/mouse settings. I chose to hide them through CSS rather than outright removing them, since I wasn't sure how the DOSBox JavaScript actually interacts with them, and I didn't feel inclined to disentangle the DOSBox JS, the DOM elements and the glue code in order to remove them cleanly.
I applied a palatable dark gray background and a drop shadow – this is of course up to personal taste and you may want to go with your own design. I also added a CSS-based loading animation from Tobias Ahlin's SpinKit to be displayed while the browser fetches the data files.
I wrote a JS snippet that adjusts the size and position of the DOSBox HTML canvas depending on the window size. It's a pretty neat little algorithm that actually causes the game to “snap” to clean multiples of its native resolution of 320x200 with some tolerance, preserving pixel-accurate rendering whenever possible.
Somewhat notably, I also added a little JavaScript hack to detect when my game would finish running. Since DOSBox was configured to terminate upon the process ending, all drawing operations to the HTML canvas element would simply cease. So what I did was to check the document title for the currently running process, which DOSBox updates while it's running. As soon as the name of my game binary no longer appears, I hide the canvas element and show a “Thank you for playing” message instead.
Conclusion
And that's pretty much it! As you can see, while the whole process is certainly not geared towards the average user, it's nothing that an adventurous hobbyist coder couldn't get done in an afternoon.
Now something that I haven't really talked about is the amount of abstraction in this technology stack. My first reaction to the Internet Archive DOS game library was probably something along the lines of “Wow, JavaScript has come a long way.” It's hard not to be impressed by what amounts to a PC emulator running in JS inside a browser. However, with abstraction comes overhead, and my little 20KB DOS binary now requires 35MB of data to be downloaded by the user (the bulk of it is DOSBox I assume). It's a DOS binary running inside DOSBox, which has been compiled to JS using emscripten, running in a browser on my – and your – machine.
Any real discussion of the ramifications of this technology for archivists and the question whether everything should be running in a browser would definitely exceed the scope of this article, but when I first tweeted about this renaissance of Revelation Mentis, someone linked me this talk, which I found fun to watch.
Please let me know if this is helpful to you! If it compels you to play around with emscripten and do something cool, I would like to see the results!
Comments
You can leave a comment by replying to this Mastodon post from your own account on Mastodon, Firefish, Akkoma, or any other ActivityPub-capable social network that can exchange replies with Mastodon.