blog · git · desktop · images · contact


Reviving PC DOS 7 in QEMU

2024-04-17

pcdos7box.jpg

When I bought OS/2 Warp 4 (again – we threw away our box some ~20 years ago 😭) in 2020, the seller also included a PC DOS 7 box (which we also threw away back then 😭). Yay!

One of the first things I did was grab disk images from the floppies. Luckily, they all still worked. Now the thing about those floppies is that all but the first one use IBM’s XDF format, which allows you to put 1.8 MB on one disk, instead of the standard 1.44 MB. In the case of PC DOS 7, it saved about 1-2 floppies.

One β€œeasy” way to create image files of those floppies is to boot OS/2 on real hardware, put in the floppies, and use xdfcopy. I did it under Warp 4, but Warp 3 should work as well. It can create a disk image by doing something like xdfcopy a: pcdos7-disk-2.img.

xdfcopy.jpg

But of course, almost nothing else can read those disks these days.

Back on Linux, you can mount the resulting images just like any other image. But QEMU, for example, still cannot use them. (Or rather, when PC DOS runs in QEMU and you attach one of those images as a floppy drive, it just freezes.) I do, however, like having retro operating systems installed in QEMU as this allows me to easily launch them without having to put strain on my old hardware, like IDE drives, so getting PC DOS to work in QEMU was something that I had on my TODO list for a while now.

Here’s how I managed to install it anyway. It’s not a 100% clean way, though. (If there’s a better way, let me know, as long as it doesn’t involve running some shady untrusted EXE file from The Internet.)

I could have done the opposite of what I did for the previous blog post, but that would be boring, wouldn’t it?

Installation in QEMU

Start with a clean disk image and boot from the first PC DOS floppy:

qemu-system-x86_64 -enable-kvm -cpu host -m 16 -smp 1 \
    -rtc base=localtime \
    -drive file=pcdos7.img,if=ide,format=raw \
    -drive file=pc-dos-7-1.img,if=floppy,format=raw \
    -boot a

Select all packages in the installer, so that we hopefully get as much data from the first floppy as possible (although I’m not sure if that really matters). At some point, it wants you to insert disk 2:

setup.png

This won’t work. Instead, poweroff the VM. When you reboot the VM, you actually have a working installation already, there’s just a bunch of programs missing. But it does boot. So the next step is to extract those programs from the remaining XDF disks.

The first PC DOS floppy includes a file called FILES.TXT, which appears to be a list of files that can be found on the floppies, an excerpt follows. They’re stored in archives and the first floppy includes the corresponding program UNPACK2.

FILENAME       BUNDLE         DISK   SIZE     DIRECTORY     DESCRIPTION
----------------------------------------------------------------------------------------------------
HERC.VID       SHELL1         3     6656     \              DOSSHELL: Hercules-Videotreiber
VGA.VID        SHELL1         3     6656     \              DOSSHELL: VGA-Videotreiber
EGA.VID        SHELL1         3     6144     \              DOSSHELL: EGA-Videotreiber
CGA.VID        SHELL1         3     6144     \              DOSSHELL: CGA-Videotreiber
...

As I said, the XDF images can be mounted on a Linux host, so we can do just that and grab all the files. I wrote the following shell script to do this.

#!/bin/sh

set -xe

mphdd=/tmp/fat-exchange-pcdos7-floppy-data.img.mp
mpfloppy=/tmp/floppy-mount
floppybase=/tmp/pcdosfloppies

fat-exchange make pcdos7-floppy-data
fat-exchange mount pcdos7-floppy-data

mkdir -p "$mpfloppy"
for i in 1 2 3 4 5
do
    mkdir -p "$mphdd/$i"

    sudo mount -o ro "$floppybase"/pc-dos-7-$i.img "$mpfloppy"
    cp -v /tmp/floppy-mount/* "$mphdd/$i"
    sudo umount "$mpfloppy"
done

(
echo '@echo off'

cat "$mphdd"/1/FILES.TXT | dos2unix |
while read -r filename pack disknum size subdir _
do
    if [ "x$filename" = "xFILENAME" ] || test -z "$pack" || [ "x$pack" = "x-" ]
    then
        continue
    fi

    echo "a:\\unpack2 d:\\$disknum\\$pack c:\\dos$subdir /C /N:$filename"
done
) | unix2dos >"$mphdd"/inst.bat

# Debug only
cat "$mphdd"/inst.bat
tree "$mphdd"

fat-exchange umount pcdos7-floppy-data

fat-exchange needs an explanation: It’s a short script I wrote to help me manage temporary disk images for exchanging data between my Linux host and a VM. fat-exchange make creates such an image and fat-exchange mount mounts it under $mphdd.

The script then does two things: First, it copies all files from all floppies to the exchange drive. The result looks something like this:

/tmp/fat-exchange-pcdos7-floppy-data.img.mp
β”œβ”€β”€ 1
β”‚Β Β  β”œβ”€β”€ ATTRIB.EXE
β”‚Β Β  β”œβ”€β”€ AUTOEXEC.BAT
β”‚Β Β  β”œβ”€β”€ BLISTLAY.OUT
β”‚Β Β  β”œβ”€β”€ ...
β”‚Β Β  β”œβ”€β”€ XDF.COM
β”‚Β Β  └── XDFCOPY.EXE
β”œβ”€β”€ 2
β”‚Β Β  β”œβ”€β”€ DOS2
β”‚Β Β  β”œβ”€β”€ DOS4
β”‚Β Β  β”œβ”€β”€ PEN1
β”‚Β Β  β”œβ”€β”€ SHELL2
β”‚Β Β  β”œβ”€β”€ STAC1
β”‚Β Β  └── WUNDEL
β”œβ”€β”€ 3
β”‚Β Β  β”œβ”€β”€ AV2
β”‚Β Β  β”œβ”€β”€ BACKUP2
β”‚Β Β  β”œβ”€β”€ SHELL1
β”‚Β Β  β”œβ”€β”€ STAC3
β”‚Β Β  └── WBACKUP1
β”œβ”€β”€ 4
β”‚Β Β  β”œβ”€β”€ DOS3
β”‚Β Β  β”œβ”€β”€ PCM2
β”‚Β Β  β”œβ”€β”€ PEN2
β”‚Β Β  β”œβ”€β”€ PS1
β”‚Β Β  β”œβ”€β”€ STAC2
β”‚Β Β  └── WBACKUP2
β”œβ”€β”€ 5
β”‚Β Β  β”œβ”€β”€ AV1
β”‚Β Β  β”œβ”€β”€ BACKUP1
β”‚Β Β  β”œβ”€β”€ DOS1
β”‚Β Β  β”œβ”€β”€ REXX
β”‚Β Β  └── WBACKUP3

Then, it creates inst.bat. That’s a series of UNPACK2 commands based on FILES.TXT and it looks like this:

@echo off
a:\unpack2 d:\1\WGRP c:\dos\ /C /N:AVBKUD.GRP
a:\unpack2 d:\1\WGRP c:\dos\ /C /N:BKUD.GRP
...
a:\unpack2 d:\3\SHELL1 c:\dos\ /C /N:HERC.VID
a:\unpack2 d:\3\SHELL1 c:\dos\ /C /N:VGA.VID
...
a:\unpack2 d:\2\DOS4 c:\dos\SYSTEM\ /C /N:VIEW.OVL
a:\unpack2 d:\2\DOS4 c:\dos\SYSTEM\ /C /N:VIEW.LIB
...
a:\unpack2 d:\5\REXX c:\dos\ /C /N:REXX.EXE
a:\unpack2 d:\5\REXX c:\dos\ /C /N:RXWRSCR.RX
a:\unpack2 d:\5\REXX c:\dos\ /C /N:RXCLS.RX
a:\unpack2 d:\5\REXX c:\dos\ /C /N:RXQSYS.RX
a:\unpack2 d:\5\REXX c:\dos\ /C /N:RXSLEEP.RX
...

I can now boot the half-installed PC DOS VM and attach this newly created disk image as D::

qemu-system-x86_64 -enable-kvm -cpu host -m 16 -smp 1 \
    -rtc base=localtime \
    -drive file=pcdos7.img,if=ide,format=raw \
    -drive file=/tmp/fat-exchange-pcdos7-floppy-data.img,if=ide,media=disk,format=raw

Before I can launch inst.bat, I have to insert the first floppy in QEMU:

change floppy0 /tmp/pcdosfloppies/pc-dos-7-1.img raw

And now running d:\inst.bat installs the missing programs.

What’s also missing, is CONFIG.SYS and AUTOEXEC.BAT. Possibly other config files as well, but I haven’t noticed anything else yet. Luckily, those aren’t hard to recreate or copy from another working installation. I use the following.

CONFIG.SYS:

FILES=30
BUFFERS=10
COUNTRY=049,850,C:\DOS\COUNTRY.SYS
DOS=HIGH
DEVICE=C:\DOS\HIMEM.SYS
DEVICE=C:\DOS\SETVER.EXE
DEVICE=C:\DOS\POWER.EXE
DEVICE=C:\DOS\DISPLAY.SYS CON=(,,1)

AUTOEXEC.BAT:

@ECHO OFF
SET PATH=C:\DOS;%PATH%
SET TEMP=C:\DOS
C:\DOS\MODE.COM CON CP PREP=((850) C:\DOS\EGA.CPI)
C:\DOS\MODE.COM CON CP SEL=850
C:\DOS\KEYB.COM GR,,C:\DOS\KEYBOARD.SYS /ID:129
C:\DOS\MOUSE.COM
C:\DOS\DOSKEY.COM

The resulting installation now appears to be working just fine.

dos1.png dos2.png dos3.png dos4.png dos5.png dos6.png

– Update 2024-04-18: What’s apparently missing is a setup step of DOSSHELL. If you want to use graphical mode, you have to copy the corresponding driver and config files, e.g.:

C:\DOS>copy VGA.GRB DOSSHELL.GRB
C:\DOS>copy VGA.VID DOSSHELL.VID
C:\DOS>copy VGA.INI DOSSHELL.INI

DOSSHELL.INI already exists but only a rudimentary version of it. It doesn’t contain program groups yet, nor color schemes.

After these steps, DOSSHELL can now be configured to like this (compare this with the screenshot above):

dos3-fixed.png

Comments?