Compiling and using em-dosbox — How to run DOS programs in your browser's JavaScript VM

By Christian Stigen Larsen
Posted 22 Jan 2015 — updated 24 Jan 2015

Archive.org has released a large number of MS-DOS games that can be played in the browser using em-dosbox. Here I'll show you how you can compile em-dosbox and put up your own MS-DOS programs on the web. This guide assumes you're using Mac OS X and Homebrew, but should be informative for other UNIX users as well.

Installing Emscripten

The em-dosbox project is a special fork of DOSBox that uses emscripten to cross-compile LLVM bitcode to JavaScript so it can run in your browser. Emscripten can actually be used to cross-compile practically any LLVM-compilable code to JavaScript!

So before we can build em-dosbox, we need to install emscripten. With Homebrew, you can review installation options with:

$ brew options emscripten

I used

$ brew install emscripten --with-closure-compiler

Homebrew tells you that you need to update your ~/.emscripten after running emcc for the first time:

Manually set LLVM_ROOT to
  /usr/local/opt/emscripten/libexec/llvm/bin

So let's run emcc first.

$ emcc
WARNING  root: (Emscripten: system change: 1.28.2|asmjs-unknown-emscripten||6.0 vs 1.4.7|le32-unknown-nacl, clearing cache)
WARNING  root: LLVM version appears incorrect (seeing "6.0", expected "3.4")
WARNING  root: could not check fastcomp: [Errno 2] No such file or directory
INFO     root: (Emscripten: Running sanity checks)
CRITICAL root: Cannot find clang++, check the paths in ~/.emscripten

Now edit ~/.emscripten and comment out the line with LLVM_ROOT. Set it to what Homebrew suggests:

LLVM_ROOT = "/usr/local/opt/emscripten/libexec/llvm/bin"

Now try running emcc to verify that it runs without any errors.

$ emcc
WARNING  root: (Emscripten: settings file has changed, clearing cache)
INFO     root: (Emscripten: Running sanity checks)
WARNING  root: no input files

Installing em-dosbox

You'll need the em-dosbox source code, and then run autogen.sh. If autogen fails, you probably need to install autotools.

$ git clone https://github.com/dreamlayers/em-dosbox.git
$ cd em-dosbox
$ ./autogen.sh

That should create a configure file. Now run that through emconfigure:

$ emconfigure ./configure

If that works fine, you should be able to build em-dosbox:

$ make -j4

On a successful build, you should find dosbox.js and dosbox.html in src/. These are templates for the web page that you'll use to run MS-DOS programs.

To take an MS-DOS program called TEST.EXE and bundle it with em-dosbox, you simply do:

$ cd src
$ ./packager.py test TEST.EXE

That should create the files test.data and test.html.

However, on my system, it complains that it can't find file_packager.py. This is part of the emscripten package. With Homebrew, emscripten is symlinked to the Cellar directory. You should therefore set EMSCRIPTEN_ROOT in ~/.emscripten to point to where the emscripten files are actually located.

You can check what value EMSCRIPTEN_ROOT is currently set to:

$ em-config EMSCRIPTEN_ROOT

On my system I had to set this to /usr/local/Cellar/emscripten/1.28.2/libexec by modifying ~/.emscripten so it looked like:

import os

EMSCRIPTEN_ROOT = "/usr/local/Cellar/emscripten/1.28.2/libexec"
LLVM_ROOT = "/usr/local/opt/emscripten/libexec/llvm/bin"

# ...

Now, I have an old intro I made with Turbo Pascal and assembly, back in the day. The file is called A-SYSTEM.EXE, so I ran it through the packager:

$ cd em-dosbox/src
$ ./packager.py a-system A-SYSTEM.EXE

This creates a-system.data and a-system.html. But if I open this in my browser, it won't be able to load the data files because of the same-origin policy. Therefore, I'll just start a simple web server in the current directory and access it through that:

$ python -m SimpleHTTPServer
$ open http://localhost:8000/a-system.html

This works pretty well, but the intro runs quite slow. Hitting CTRL-F12 speeds up the CPU and framerate considerably. But such settings can be put in a configuration file. For this to work, you need to move the EXE-file into a subdirectory from src/ and add a dosbox.conf file.

I put this in dosbox.conf:

[cpu]
core = simple
cycles = fixed 20000

[dosbox]

[midi]
mpu401 = none
mididevice = none

Then I built the entire directory with:

$ ./packager.py a-system a-system A-SYSTEM.EXE

The first argument is still the prefix for the .data and .htmlfiles, the second is the directory containing the EXE-file and config file, and the final argument is which DOS program to embed.

I haven't tweaked the dosbox.conf settings yet, but you can view the A-SYSTEM 28k intro here. Just be patient while it loads. It uses XMLHttpRequest to download dosbox.html.mem and a-system.data, which are about 30 Mb each. For some reason, this is slow.

Update: I've tried compressing those files with gzip. While it seems to work fine with Firefox and Safari, on Chrome the emulator seems to ends abruptly. By the way, Firefox seems to be the one giving the best performance with em-dosbox.