Running DOS on QEMU

I was having trouble getting DOS apps to run properly in Dosbox, which is optimized for running games. QEMU, on the other hand, is nice and accurate (albeit a little slower) and not too hard to set up.

$ qemu-img create freedos.img 1000M
$ qemu-system-i386 -hda freedos.img -cdrom FD12CD.iso -boot d
    (run the installer...)
$ qemu-system-i386 -hda freedos.img -boot c

Using a modern printer from emulated DOS

This works on Mac or Linux. You do of course need to have a printer set up already (network or local.)

#!/usr/bin/env python3
import io
import os
import subprocess

"""
DOS printing adapter
Opens a fifo named "print_pipe" and prints text from it every time a form
feed (^L, 0x0C) is received.

Example usage:
$ ./printer.py &
$ qemu-system-i386 -hda freedos.img -boot c -parallel file:print_pipe

Make sure your software sends a form feed. In DBASE III+, this is configured
in the report options.

TODO: print buf after a timeout, even if there's no form feed.
"""

def _adjacent_to_script(f):
    base = os.path.dirname(os.path.realpath(__file__))
    return os.path.join(base, f)

def send_to_printer(s):
    print('Printing page(s)...')
    subprocess.run(['lpr'], input=s, text=True, check=True)

if __name__ == '__main__':
    pipe_name = _adjacent_to_script('print_pipe')
    os.mkfifo(pipe_name)
    try:
        buf = io.StringIO()
        with open(pipe_name, 'r', encoding='cp437') as pipe:
            while True:
                c = pipe.read(1)
                if c == '\x0c': # form feed
                    send_to_printer(buf.getvalue())
                    buf.close()
                    buf = io.StringIO()
                else:
                    buf.write(c)
    finally:
        os.remove(pipe_name)