LJDT: DOSBox and Game Emulation for Fun
The majority of this series has been very practical, because most of the time I am a dreadful bore and focus on things that are very practical. Want to predictably modify a config file on ten thousand boxes without leaving your computer or manually wasting weeks of your life? Done. Want to read multi-GB files in fractions of a second without spending too much money on more RAM? Done. Some would call this interesting; most would call it boring.
To try to spread my wings just a bit today we’ll learn about something built into openSUSE 13.x which I stumbled upon last night: DOSBox. As its name implies, this opens a “box” (emulator) running DOS, in which you can run old DOS-like things, like those classic games that you haven’t been able to play since your parents upgraded to the 386 processor causing them to run too fast (yes, you are that old), or all of those old arcade games that you cannot even find anymore, but are available online if only you had a thirty-year-old computer on which to run them. Remembering your childhood, showing your family how you used to be awesome on games using nothing more than arrow keys and a spacebar, letting you be “productive” in all kinds of new ways…. yes, Linux Just Does That.
To start out, we’ll just get something going, and then from there we’ll actually dive in properly to see all the options for dosbox. Thankfully, getting things going is a breeze. If you’re already on openSUSE then you likely have it installed since apparently it’s part of the default; if not, install it in about ten seconds:
> sudo zypper in dosbox
The current version is 0.74, which is what I have installed so the repositories are up to date. Next, you need a game. I stumbled upon all of this while trying to find our family’s childhood favorite which is apparently named Digger or ‘Crazy Digger’. Ah yes, the memories of beating cousins who didn’t have it full time, right up until they beat me and then the game was no longer fun. If you want to try it out, here it is: http://www.abandonwaredos.com/abandonware-game.php?abandonware=Digger&gid=MTg2OA==
On this site you’ll notice that it even lists DOSBox version compatibility, which is really nice. 0.74 isn’t listed, but so far it has worked well for me. If you remember an old game of your own, try searching on that site for those and hopefully the “install” will be the same.
The next step is to extract the game somewhere. In my case, the archive with the game is nothing more than a zip with an executable, so nothing to “install” other than dropping files somewhere for dosbox to load. Here comes recommendation #1: Create a dedicated directory somewhere, out of the way but known by you, for all of your old DOS programs. In my case, I created ~/.dosprogs/ which is out of the way but easy to find from any old tool, and which is dedicated to programs. One important point about this: you’re running old software emulated in your computer, so if it goofs and tries to delete lots of stuff, it is good to have dosbox limited to a little area of space, like the directory created above.
There are two ways to use this new location as a “drive” within the old DOS framework. First, load dosbox pointing to that directory as its argument:
> dosbox ~/.dosprogs/
If you do not have a command line, or do not want to use a command line now, just load dosbox (Alt+F2, or whatever) and then run the following commands within dosbox to mount the directory above as the old c: drive (oh drive letters… what a limiting idea):
mount c ~/.dosprogs/ c:
Note that the first command references the directory in the host format, and even understands that ‘~’ means my user’s home directory. The second command just changes to the (newly-mounted) c: drive from the (default) z: drive. If you run the old ‘dir’ command you should see a directory, likely with nothing in it at this point; other old familiar DOS commands may also work, but more on those later.
Lastly, we need to put our game into that location. Extract the zipped archive, put the crdig1.com file in ~/.dosprogs/ and that should do it. If you run ‘dir’ again you’ll see…… nothing. The reason is that there is some kind of drive cache created when a drive letter is mounted which does not see new stuff coming from the host easily, though for some reason it does show things gone when removed from the host (I do not know why). To remount things you can either reload dosbox, or unmount and mount as shown below:
z: mount -u c mount c ~/.dosprogs c:
Doing that old directory listing should show things again nicely, and at this point you can play the game. A quicker way I have found recently is to just press Ctrl+F4 (Ctrl+Shift+F4 if your OS intercepts the original Ctrl+F4 keystrokes) which refreshes the swap image. Trying ‘dir’ again you should now see a current accounting of files/directories in that base directory.
To recap the steps were to create a directory, put a game file in there, run dosbox, mount the game directory as the c: drive, then run the game. In case it is not obvious, to run the game in our case just run ‘crdig1’ (no extension necessary as usual for DOS, and case insensitive too).
Once you start the game you’ll realize that the problems with your CPU being way too fast for 1983 are still present; most of the time we like faster CPUs, but since ours are probably rated in gigahertz with the same number as we used to have in megahertz, it means impossible gaming. Since this software is made to emulate old stuff, it accounts for that. Use Ctrl+F11 (or Ctrl+Shfit+F11 if your host intercepts and treats Ctrl+F11 specially) to slow down the processor of the emulator; Ctrl+F12 (or Ctrl+Shift+F12) speeds things back up. On my system the CPU speed showed up originally at around 3000 cycles, and the game felt normal at about 400, which meant pressing Ctrl+F11 about eleven times. You can slow the system down to 1 cycle, at which point you can see drawing of the screen (eventually) take place at a snail’s pace.
Next step, go play your game for an hour. Get that need building for the past thirty years out of your system, and then let’s get into some fun details about this Linux tool.
Running all of those commands once was okay, but running them all, and setting your CPU, and all of that will eventually get old, so let’s see if we can automate that. When you want to game, you don’t want to type commands just to get into the game, after all. At this point it will start to become clear that dosbox was not created in a day, and is not limited to the basics done so far. When the ‘dosbox’ command is first loaded, it creates a default configuration file which can then be modified per your system and gaming preferences. The default configuration file was created, on my system, under ~/.dosbox/ with the name ‘dosbox-0.74.conf and looks like an old INI file from the DOS days, oddly enough.
# This is the configurationfile for DOSBox 0.74. (Please use the latest version of DOSBox) # Lines starting with a # are commentlines and are ignored by DOSBox. # They are used to (briefly) document the effect of each option. [sdl] # fullscreen: Start dosbox directly in fullscreen. (Press ALT-Enter to go back) # fulldouble: Use double buffering in fullscreen. It can reduce screen flickering, but it can also result in a slow DOSBox. # fullresolution: What resolution to use for fullscreen: original or fixed size (e.g. 1024x768). # Using your monitor's native resolution with aspect=true might give the best results. # If you end up with small window on a large screen, try an output different from surface. # windowresolution: Scale the window to this size IF the output device supports hardware scaling. # (output=surface does not!) # output: What video system to use for output. # Possible values: surface, overlay, opengl, openglnb. # autolock: Mouse will automatically lock, if you click on the screen. (Press CTRL-F10 to unlock) # sensitivity: Mouse sensitivity. # waitonerror: Wait before closing the console if dosbox has an error. # priority: Priority levels for dosbox. Second entry behind the comma is for when dosbox is not focused/minimized. # pause is only valid for the second entry. # Possible values: lowest, lower, normal, higher, highest, pause. # mapperfile: File used to load/save the key/event mappings from. Resetmapper only works with the defaul value. # usescancodes: Avoid usage of symkeys, might not work on all operating systems. fullscreen=false fulldouble=false fullresolution=original windowresolution=original output=surface autolock=true sensitivity=100 waitonerror=true priority=higher,normal mapperfile=mapper-0.74.map usescancodes=true [dosbox] # language: Select another language file. # machine: The type of machine tries to emulate. # Possible values: hercules, cga, tandy, pcjr, ega, vgaonly, svga_s3, svga_et3000, svga_et4000, svga_paradise, vesa_nolfb, vesa_oldvbe. # captures: Directory where things like wave, midi, screenshot get captured. # memsize: Amount of memory DOSBox has in megabytes. # This value is best left at its default to avoid problems with some games, # though few games might require a higher value. # There is generally no speed advantage when raising this value. language= machine=svga_s3 captures=capture memsize=16 [render] # frameskip: How many frames DOSBox skips before drawing one. # aspect: Do aspect correction, if your output method doesn't support scaling this can slow things down!. # scaler: Scaler used to enlarge/enhance low resolution modes. # If 'forced' is appended, then the scaler will be used even if the result might not be desired. # Possible values: none, normal2x, normal3x, advmame2x, advmame3x, advinterp2x, advinterp3x, hq2x, hq3x, 2xsai, super2xsai, supereagle, tv2x, tv3x, rgb2x, rgb3x, scan2x, scan3x. frameskip=0 aspect=false scaler=normal2x [cpu] # core: CPU Core used in emulation. auto will switch to dynamic if available and appropriate. # Possible values: auto, dynamic, normal, simple. # cputype: CPU Type used in emulation. auto is the fastest choice. # Possible values: auto, 386, 386_slow, 486_slow, pentium_slow, 386_prefetch. # cycles: Amount of instructions DOSBox tries to emulate each millisecond. # Setting this value too high results in sound dropouts and lags. # Cycles can be set in 3 ways: # 'auto' tries to guess what a game needs. # It usually works, but can fail for certain games. # 'fixed #number' will set a fixed amount of cycles. This is what you usually need if 'auto' fails. # (Example: fixed 4000). # 'max' will allocate as much cycles as your computer is able to handle. # # Possible values: auto, fixed, max. # cycleup: Amount of cycles to decrease/increase with keycombo.(CTRL-F11/CTRL-F12) # cycledown: Setting it lower than 100 will be a percentage. core=auto cputype=auto cycles=auto cycleup=10 cycledown=20 [mixer] # nosound: Enable silent mode, sound is still emulated though. # rate: Mixer sample rate, setting any device's rate higher than this will probably lower their sound quality. # Possible values: 44100, 48000, 32000, 22050, 16000, 11025, 8000, 49716. # blocksize: Mixer block size, larger blocks might help sound stuttering but sound will also be more lagged. # Possible values: 1024, 2048, 4096, 8192, 512, 256. # prebuffer: How many milliseconds of data to keep on top of the blocksize. nosound=false rate=44100 blocksize=1024 prebuffer=20 [midi] # mpu401: Type of MPU-401 to emulate. # Possible values: intelligent, uart, none. # mididevice: Device that will receive the MIDI data from MPU-401. # Possible values: default, win32, alsa, oss, coreaudio, coremidi, none. # midiconfig: Special configuration options for the device driver. This is usually the id of the device you want to use. # See the README/Manual for more details. mpu401=intelligent mididevice=default midiconfig= [sblaster] # sbtype: Type of Soundblaster to emulate. gb is Gameblaster. # Possible values: sb1, sb2, sbpro1, sbpro2, sb16, gb, none. # sbbase: The IO address of the soundblaster. # Possible values: 220, 240, 260, 280, 2a0, 2c0, 2e0, 300. # irq: The IRQ number of the soundblaster. # Possible values: 7, 5, 3, 9, 10, 11, 12. # dma: The DMA number of the soundblaster. # Possible values: 1, 5, 0, 3, 6, 7. # hdma: The High DMA number of the soundblaster. # Possible values: 1, 5, 0, 3, 6, 7. # sbmixer: Allow the soundblaster mixer to modify the DOSBox mixer. # oplmode: Type of OPL emulation. On 'auto' the mode is determined by sblaster type. All OPL modes are Adlib-compatible, except for 'cms'. # Possible values: auto, cms, opl2, dualopl2, opl3, none. # oplemu: Provider for the OPL emulation. compat might provide better quality (see oplrate as well). # Possible values: default, compat, fast. # oplrate: Sample rate of OPL music emulation. Use 49716 for highest quality (set the mixer rate accordingly). # Possible values: 44100, 49716, 48000, 32000, 22050, 16000, 11025, 8000. sbtype=sb16 sbbase=220 irq=7 dma=1 hdma=5 sbmixer=true oplmode=auto oplemu=default oplrate=44100 [gus] # gus: Enable the Gravis Ultrasound emulation. # gusrate: Sample rate of Ultrasound emulation. # Possible values: 44100, 48000, 32000, 22050, 16000, 11025, 8000, 49716. # gusbase: The IO base address of the Gravis Ultrasound. # Possible values: 240, 220, 260, 280, 2a0, 2c0, 2e0, 300. # gusirq: The IRQ number of the Gravis Ultrasound. # Possible values: 5, 3, 7, 9, 10, 11, 12. # gusdma: The DMA channel of the Gravis Ultrasound. # Possible values: 3, 0, 1, 5, 6, 7. # ultradir: Path to Ultrasound directory. In this directory # there should be a MIDI directory that contains # the patch files for GUS playback. Patch sets used # with Timidity should work fine. gus=false gusrate=44100 gusbase=240 gusirq=5 gusdma=3 ultradir=C:\ULTRASND [speaker] # pcspeaker: Enable PC-Speaker emulation. # pcrate: Sample rate of the PC-Speaker sound generation. # Possible values: 44100, 48000, 32000, 22050, 16000, 11025, 8000, 49716. # tandy: Enable Tandy Sound System emulation. For 'auto', emulation is present only if machine is set to 'tandy'. # Possible values: auto, on, off. # tandyrate: Sample rate of the Tandy 3-Voice generation. # Possible values: 44100, 48000, 32000, 22050, 16000, 11025, 8000, 49716. # disney: Enable Disney Sound Source emulation. (Covox Voice Master and Speech Thing compatible). pcspeaker=true pcrate=44100 tandy=auto tandyrate=44100 disney=true [joystick] # joysticktype: Type of joystick to emulate: auto (default), none, # 2axis (supports two joysticks), # 4axis (supports one joystick, first joystick used), # 4axis_2 (supports one joystick, second joystick used), # fcs (Thrustmaster), ch (CH Flightstick). # none disables joystick emulation. # auto chooses emulation depending on real joystick(s). # (Remember to reset dosbox's mapperfile if you saved it earlier) # Possible values: auto, 2axis, 4axis, 4axis_2, fcs, ch, none. # timed: enable timed intervals for axis. Experiment with this option, if your joystick drifts (away). # autofire: continuously fires as long as you keep the button pressed. # swap34: swap the 3rd and the 4th axis. can be useful for certain joysticks. # buttonwrap: enable button wrapping at the number of emulated buttons. joysticktype=auto timed=true autofire=false swap34=false buttonwrap=false [serial] # serial1: set type of device connected to com port. # Can be disabled, dummy, modem, nullmodem, directserial. # Additional parameters must be in the same line in the form of # parameter:value. Parameter for all types is irq (optional). # for directserial: realport (required), rxdelay (optional). # (realport:COM1 realport:ttyS0). # for modem: listenport (optional). # for nullmodem: server, rxdelay, txdelay, telnet, usedtr, # transparent, port, inhsocket (all optional). # Example: serial1=modem listenport:5000 # Possible values: dummy, disabled, modem, nullmodem, directserial. # serial2: see serial1 # Possible values: dummy, disabled, modem, nullmodem, directserial. # serial3: see serial1 # Possible values: dummy, disabled, modem, nullmodem, directserial. # serial4: see serial1 # Possible values: dummy, disabled, modem, nullmodem, directserial. serial1=dummy serial2=dummy serial3=disabled serial4=disabled [dos] # xms: Enable XMS support. # ems: Enable EMS support. # umb: Enable UMB support. # keyboardlayout: Language code of the keyboard layout (or none). xms=true ems=true umb=true keyboardlayout=auto [ipx] # ipx: Enable ipx over UDP/IP emulation. ipx=false [autoexec] # Lines in this section will be run at startup. # You can put your MOUNT lines here.
If you read through that, you’ll likely notice some good bits already. First, you can set your CPU speed so that you are not needing to manually change that every time you load a dosbox instance. That line is within the ‘[cpu]’ section and is currently:
and for me should be changed to
Next, those pesky mounts will drive me crazy, so at the very bottom is the ‘[autoexec]’ section; if you ever did anything with DOS, or old windows stuff, you’ll likely remember the autoexec.bat file which was the one loaded to setup the DOS and windows environment by running a bunch of files after the tiny system was loaded. This used to be how windows was started (win.com), maybe up until 2000/NT or so (maybe that changed earlier too…. hard to remember how broken that all is). In our case, we just need two lines which we used earlier:
mount c ~/.dosprogs/ c:
If you have any question about which dosbox.conf file to load, the dosbox command has a way to help:
> dosbox -editconf vi #replace 'vi' with your editor of choice
This opens the default conf file and lets you edit it on the fly. Save as usual per your editor, so in ‘vi’ that could be either :wq (colon followed by ‘w’ followed by ‘q’ followed by [Enter]) or ZZ (two capital Z characters). Loading dosbox you should now see your settings in place. Digger should run at a normal pace, and the mount should be instantaneous. Obviously you could also create other conf files for particular games, and then create launchers/shortcuts for each of those config files so that you can launch the game, with its specific settings, with one command or click. To load with a specific conf file, specify it after the -conf parameter to the dosbox command:
> dosbox -conf /path/to/other.conf
Our environment is now setup, and automated, so let’s dive into some additional details. First, in case it was not clear, close the dosbox window to make it go away, or type ‘exit’ within. Another option is to use Ctrl+F9 (or Ctrl+Shift+F9 if your UI treats Ctrl+F9 specially). What if you want to have the old fullscreen DOS experience, though? For that, there is Alt+[Enter], and then again to un-fullscreen the window. This is also configurable under the ‘[sdl]’ section as the following:
While in dosbox you may find a need to do some tinkering around with old commands you used to think were great (before you found a real shell like bash, or ksh, or zsh, or really anything else). To see the available commands, try ‘help’, and to see all of them, add ‘/all’ to that command:
You’ll likely notice that some commands do nothing, and are documented as such, e.g. ‘attrib’. Hacking attributes of files in an emulator does not always make much sense, particularly when the emulator is running on a real OS that has more-sophisticated attributes than DOS did.
While in the middle of a game, you may want to pause things so the roaming bad guys do not kill you while you’re eating a sandwich; since this is all emulated anyway, emulating a pause is also possible with (you guessed it) Alt+Pause. One thing this impacted on my system was the ability to go to/from full screen; it appears that when you tell DOSBox to pause it pauses everything, including the ability to Alt+[Enter] to go to/from full screen. Not a big deal… just pause after going out of full screen, or have an alternate way to get out of full screen.
When first loading dosbox a nice bit of text at the top tells you how to get more information via an introduction to the environment; appropriately, that mini-tutorial is available via the ‘intro’ command, which then gives you details on sub-commands like ‘intro mount’ (mount options for various things like local directories), ‘intro cdrom’ (more specifics on CDROM things, which may be useful for those old CDs still hanging around) and ‘intro special’ (special keys, the Alt+ and Ctrl+ combinations mentioned).
While playing that game of yesteryear and completely smashing an old record, you may even want to get an awesome screenshot of something great, like your high score, or your maintained ability to hurl sixteen-bit fireballs at bad guys. Never fear, Ctrl+F5 is here. Note that while this command seems to work, there is not much indication of what is happening (because a big indicator might ruin the activity which you are capturing) and pictures end up in the ~/.dosbox/capture/ directory by default. This, like so many things, is configurable in the conf file under the ‘[dosbox]’ section:
For mine I set it to ~/Desktop and magically the dosbox_000.png (and dosbox_001.png, etc.) file showed up there. The naming looks pretty simple, and I have no idea what happens after 1,001 screenshots, but if that’s something you’re doing, perhaps you need a new option.
Ctrl+Alt+F5 is the keystroke combination to capture video. This is really interesting because if you start this while at the command prompt and then load a program which changes the video mode (not just any program/command), it creates a new, appropriately-named, video file for that program. All of these also have counters, and appear to write in AVI container format, but it is using the ZMBV format within which means that some systems may appear to support the file (because they only care about the container file’s extension) when in reality more work is needed to playback things within that container. The full explanation can be had here, but basically it sounds like VLC 2.2.0 (or later) should handle this nicely: http://www.dosbox.com/wiki/Recording_Video with a bit more VLC info here: https://forum.videolan.org/viewtopic.php?f=2&t=118917&hilit=DOSBox Another option to get this into another format is, after recording, using ffmpeg (likely installed by default; if not, ‘sudo zypper in ffmpeg’) to convert to something else like MP4:
> ffmpeg -i ./crdig1_000.avi -c:v libx264 crdig1_000.mp4
The resulting mp4 (container) file may be a bit more accessible to many. There are other encodings within the mp4 container from which to choose, but this one was simple enough. With the recording working evidence of hacking scores can have some proof behind it, but just in case you want to hack files anyway, there are ways to get those high scores about which you were always bragging listed somewhere, at least for a screenshot. For those of us who are not good gamers, here you go.
In the case of Digger, the crdig.dat file is the one with all of the scores within. This is a 256-bit, fixed-length file with a bunch of fixed-width data within. The reason that the high scores are recorded as the player’s initials may be as much because of this file format as limited real estate on the old DOS screen. Either way, as is often the case, the way to reverse-engineer this is to first get some known data within, i.e. go play a game or two and get on the scoreboard. If you have siblings/parents/children/cousins who are already on the score board, then that’s fine too.
Open the file with ‘vi’; you do not even need binary mode really for this hack but if you did vi can (of course) do that too. Once open, it may look like this:
sAAB 4225ADB 225AHB 16600ADB 1... 0... 0... 0... 0... 0... 0^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@ ^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@
That’s not very pretty, but it will be enough. If you are extremely aware you may note that those three periods (‘…’) happen to match the default, name-less users in the scoreboard, and of course those zeroes (‘0’) are the default scores, waiting to be filled in. Everything after the periods and a single space, up until (and including) the zero, is that user’s score. The next period (or whatever character) then starts the new user in the scoreboard. As a result, to get on the scoreboard, simply change the periods to your initials and put in your score after a space following those initials; be sure to put the scores in order, or it’ll look like you were hacking things. Once done, save the file and hope you did not mess up. If you did mess up, delete the file and play another game to recreate it.
For the hex geeks out there, here is the final product from hexdump:
me@mybox0:~/Desktop> hexdump -C ../.dosprogs/CRDIG.DAT 00000000 73 41 41 42 20 20 39 39 34 32 32 35 41 44 42 20 |sAAB 994225ADB | 00000010 20 20 32 35 32 32 35 41 48 42 20 20 20 31 36 36 | 25225AHB 166| 00000020 30 30 41 44 42 20 20 20 20 20 20 20 31 2e 2e 2e |00ADB 1...| 00000030 20 20 20 20 20 20 20 30 2e 2e 2e 20 20 20 20 20 | 0... | 00000040 20 20 30 2e 2e 2e 20 20 20 20 20 20 20 30 2e 2e | 0... 0..| 00000050 2e 20 20 20 20 20 20 20 30 2e 2e 2e 20 20 20 20 |. 0... | 00000060 20 20 20 30 2e 2e 2e 20 20 20 20 20 20 20 30 00 | 0... 0.| 00000070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
Again, notice that there is an initial ‘s’ character, followed by three initials, s apce, and then six digits for the score; three initials space, six digits for the score, repeated ten times in total. After that are a bunch of null (0x00) characters which I presume are to pad things up to 256 bytes which seems crazy, but we’re talking about DOS here.
The end result in Digger is that AAB has 994225 points, ADB has 25225, AHB has 16600, and ADB has 1 (an impossible score, of course), and the rest are still left blank. When loading Digger these all show up, in the correct order as planned, and you can rest assured that it is unlikely anybody will ever beat your score, at least without beating your crdig.dat file manually like you did.
While this ventured a bit into a specific game, the points I wanted to make are the following:
- Linux just does this stuff by default, and we take it for granted as a result that others do not have this out of the box; thousands of old games are available with very little work or investment on your part. Non-games are also available, especially if you have the install media available.
- dosbox has tons of features, and a long history of doing a great job; this is no fly-by-night operation setup yesterday riddled with bugs for you to find; just go play.
- Great tools also let you (finally) become the greatest scoring person of all time. Whether or not your conscience can handle that misrepresentation of the facts is an article for another day.