I wanted to put together a decent build system for QBasic programs.
My goal was to be able to use modern tools such as VSCode and git to edit and manage my code from an OSX host, and to easily run on a representative system of the MS-DOS era, which in this case is an i386 system, with 8MB of RAM, running MS-DOS 6.22.
Currently I’m doing this using virtualized hardward (using the incredibly versatile
qemu), but I plan on modifying this in future to send the application to real hardware.
My strategy is similar to any other inject-and-run type system; it’s heavily inspired by how most CI pipelines work:
- Build a predictable base image which can be quickly replicated.
- Build a system to boot that environment and inject my latest code.
- Have the code compiled (or interpreted) inside that environment and be able to quickly interact with the results.
Requirements and workspace layout
First, install the packages we need. This assumes you’re running a modern OSX (I’m using Mojave), with
$ brew install qemu
Now, I want to layout our working folder as follows:
$ mkdir img $ mkdir src $ mkdir live $ mkdir scripts
Building the base image
make a working folder:
$ mkdir qbasic $ cd qbasic $ mkdir msdos-disks/
move some msdos installer files into place:
$ cp *.img ~/qbasic/msdos-disks/
make harddisk image:
$ qemu-img create dos.img 200M
boot the system (with 8mb of RAM attached) with the first msdos disk:
$ qemu-system-i386 -hda dos.img -fda msdos-disks/disk1.img -m 8
As the installer runs, you’ll eventually need to change disk. Switch to the QEMU console with
ctrl-alt-2. Then, the following command to switch image:
(qemu) change floppy0 msdos-disks/disk2.img
… then switch back to the primary output with
ctrl-alt-1. My version of MS-DOS came on three floppy disks, so by the time the installed was complete, and I’d ejected the final disk, the QEMU console session looked like this:
(qemu) change floppy0 msdos-disks/disk2.img (qemu) change floppy0 msdos-disks/disk2.img (qemu) eject floppy0
Mounting the disk image:
$ hdiutil attach -imagekey diskimage-class=CRawDiskImage -mountpoint ./live/ dos.img $ hdiutil detach live