DOSContainer logo DOSContainer

Designing the interaction between HwSpec and Manifest

📅 2025-05-15  · ✍️ Bas v.d. Wiel  ·  🏷 design

After finishing the first implementation of HwSpec, I started working on handling the Manifest configuration file. These two are what should make DOSContainer work like magic for the end user, so they’d better be good. As it turns out, things aren’t at that point just yet. Some musings on the design and how DOSContainer will reconcile the facts of what you have (HwSpec) with what you want (Manifest) in an optimal way.

In my time as a DevOps engineer and IT architect I’ve been exposed to quite a few systems that work around what’s called `desired state’. A system, or collection of systems, is in a currently unknown state. The engineer writes a configuration file according to a formal specification to declare the desired state for the system. Once fed into the configuration management toolbox, the target system is adjusted so that its unknown state changes into the desired state. Systems like Puppet, Ansible and Terraform work in this manner and in the world of Kubernetes everyone loves ArgoCD.

Declaring what you have

In the context of a retro DOS PC, it’s very relevant to declare what you have on your desk. This is what the HwSpec configuration file is for. It lists the exact hardware and operating system characteristics that you’ll be working with. Some of these settings are hard facts not open for negotiation. You have a CGA card in your machine? Ok, so you’re not ever going to get VGA graphics from it. Other items are more like preferences. You can run a wide gamut of DOS versions and the application or game won’t really mind all that much. DOSContainer needs to take both elements into account: hard constraints and preferences.

Declaring what you need

The Manifest configuration file is something you don’t usualy create as an end-user of DOSContainer. It’s for collection builders to set up and maintain. While both files are in TOML format, that’s where the similarities end. As a manifest-developer you need to know exactly what your application or game needs: minimal non-negotiable system requirements. These map straight to the hard facts of the hardware that the user has on their desk.

In the context of a Manifest you’ll also have preferences. A game may work on an 8088 CPU, but may need to be configured differently than it would be on a 80386. Or you may be running on IBM hardware that you’d like to pair with PC-DOS rather than MS-DOS, even though both would run: that’s a preference from the end user that requires the Manifest to cater to. PC-DOS should be declared as a supported option, even if it’s not the preferred operating system from the game or application developer’s standpoint.

Constraints en preferences in HwSpec

Here’s a generic IBM XT-compatible system:

ram = "512KiB"
video = "cga"

[floppy]
floppy_type = "160k"

[cpu]
family = "8088"
clock = 4

[[audio]]
device = "bleeper"

This is the HwSpec declaring only hard facts. We have a fixed amount of memory, graphics hardware, a CPU, a floppy drive and a specific audio device. If a Manifest can work with these, it will build. If it can’t, it simply won’t build.

By adding preferences at the top you can nudge DOSContainer in some directions:

dos_vendor = "IBM"
min_dos = "1.00"
max_dos = "2.00"

These items are optional. If you don’t set them, DOSContainer will look at the ```Manifest`` for the most ideal version of DOS it thinks you’ll need. In this example the system could pick one of three versions: IBM PC-DOS 1.00, 1.10 and 2.00. If the Manifest has a DOS version that intersects with this set, it will get built with the closest match. Leave them out, and the optimal version will be determined solely by the Manifest.

Now for the kicker: if you specify a 1.44MB 3.5" floppy drive, you’ll run into an issue. The ancient DOS versions you specified don’t support this kind of floppy drive. At all. So now what? This is where DOSContainer errs on the side of caution by refusing to build unsupported combinations, unless you force it to do so by adding the -F command line parameter to force its hand. In that case it will pick a the nearest OS version from the Manifest that does support your floppy drive and build a floppy for you.

Another example would be graphics. Very old DOS systems often had a Hercules monochrome graphics card, which was awesome for text and CAD because of its high resolution. It didn’t do colour graphics, however, so games that required CGA were out of luck. Some games, however, would still run when a CGA-emulator was added into the mix. Such an emulator is a piece of software that loads just before the game starts and translates the CGA graphics of the game into something the monochrome Hercules card can display. As a manifest-developer it’s your job to figure out if this trick works with the software you’re packaging, and add it as a Layer that gets injected when the user has Hercules graphics.

Tags: