An unofficial AppImage of
dosemu2, built from the official
sources. dosemu2 is a virtual machine that runs DOS programs under Linux.
Download one file, chmod +x, run.
The AppImage carries its own C library and dynamic loader, so it runs on any Linux distribution: glibc or musl, new or old. This is the AnyLinux method (sharun + uruntime + DwarFS).
Upstream project: https://github.com/dosemu2/dosemu2
Builds are published to a rolling
latest release, which carries one build at a
time, and to a per-commit release that keeps earlier builds reachable.
The file name carries the dosemu2 version it was built from.
chmod +x dosemu2-*.AppImage
./dosemu2-*.AppImageThere is an aarch64 build for arm64 hosts.
If appimageupdatetool is installed, the AppImage can update itself in place:
appimageupdatetool dosemu2-*.AppImageIf your distribution does not package it, AM
can install it (am -i appimageupdatetool).
dosemu2 reads /etc/dosemu/dosemu.conf first, then
~/.dosemu/dosemurc. The AppImage ships neither, so it uses whatever is
on the host and your settings survive an update.
You need Docker. First build the build environment — Arch, the bundled soundfont, and these, each compiled from a pinned commit or tag:
- binutils
- thunk_gen
- fdpp
- smallerc
- djstub
- dj64dev
- comcom64
- libsearpc
- libmt32emu
docker build -f docker/Dockerfile-appimage -t dosemu2-appimage-build-env .Then build the AppImage. DOSEMU2_REF is required and can be any
dosemu2 commit, tag or branch:
docker run --rm -u 0 -v "$PWD":/workspace -w /workspace \
-e DOSEMU2_REF=devel -e WORKSPACE=/workspace \
dosemu2-appimage-build-env sh -c './build-appimage.sh'The finished .AppImage lands in out/, owned by root because the
build runs as root inside the container. out/DOSEMU2_COMMIT records
the exact commit it came from.
The DOSEMU2_REF file in the repository root sets the dosemu2 commit
that CI builds and tests. To propose a newer one, edit that file and
open a pull request. CI then builds and smoke-tests both architectures
against the commit you put there, and publishes nothing.
Releases are never automatic. A maintainer publishes in one of two ways:
- pushes to
trunkwith[publish]in the message of the last commit pushed - runs the workflow from the Actions tab with the commit to publish
build-appimage.sh runs inside the build environment and:
- Clones dosemu2 at
DOSEMU2_REFand builds it with--prefix=/usr --sysconfdir=/etc, installing into the container's own/usr. The sysconfdir is what makes it read/etc/dosemu/dosemu.conf; autoconf would otherwise default it to/usr/etc, which exists on no host. - Copies the data dosemu2 looks up by absolute path at runtime into the
AppDir: fdpp's kernel, comcom64's
command.com, dj64'scrt0.elf, dosemu2's keymaps and command utilities, the oldschool TTF fonts, the LADSPA plugins, and the soundfont. - Runs
quick-sharunoverdosemu2.bin, every plugin.so, and alsa-lib's PulseAudio and PipeWire modules, which collects the full library closure including libc and the loader, then packs the result as a DwarFS AppImage.
dosemu2 and its toolchain bake absolute /usr/... paths into their
binaries at compile time. quick-sharun rewrites such paths in place, and
on libdosemu2.so that corrupts them: DOSEMUCMDS_DEFAULT is a
compile-time pointer into the middle of another string literal, so
rewriting the literal moves what the pointer reads. The script disables
that patcher and uses PATH_MAPPING, an LD_PRELOAD interceptor that
redirects the path at runtime instead.
The SDL text plugin asks fontconfig for the fonts by family name and refuses a substitute, so the AppImage ships its own fontconfig configuration pointing at the two bundled fonts.
dosemu2 is built with every optional plugin its dependencies allow:
- DOS: fdpp, comcom64, dj64
- Video: SDL3 with TrueType text, X11, terminal, console
- Sound: ALSA with the PulseAudio and PipeWire backends, FluidSynth with a bundled soundfont, munt for MT-32, LADSPA
- Other: slirp networking, keyboard maps, parallel port
MIDI plays through GeneralUser
GS, which the AppImage
carries. If your system has a soundfont in one of the places dosemu2
searches, such as /usr/share/soundfonts/default.sf2, dosemu2 uses that
one instead. For a soundfont anywhere else, set $_fluid_sfont in
~/.dosemu/dosemurc:
$_fluid_sfont = "~/.sf2/mysoundfont.sf2"
With a portable home (a <name>.AppImage.home directory next to the
AppImage), ~ means that directory, not your real home.
Two things are left out:
- libao output. It loads its backends from a fixed path in
/usrthat an AppImage cannot supply, so the plugin could only ever reportunable to open output device. ALSA and SDL cover sound output. - MT-32 ROMs. munt is built in, but the ROM files are proprietary.
dosemu2 looks for them in
~/.munt_roms; set$_munt_romsto use another directory.
How much Landlock sandboxing you get depends on the kernel. Below ABI 8,
startup logs Warning: your kernel is too old, using minimal Landlock protection and runs with a reduced sandbox. Below ABI 2, or with no
Landlock at all, it logs landlock_init() failed and runs without one.
MIT, see LICENSE. Compatible with dosemu2's GPL-2.0-only: this repo contains build glue, not dosemu2 source.
The AppImage payload is dosemu2 itself under GPL-2.0-only, plus its bundled runtime libraries under their own licenses.