Postscript Emulation under DOSBox
So, for whatever reason, I decided to go down the rabbit hole of using a word processor that I had used for many years in my youth: MS Works 3.0 for DOS. At school, I was a heavy ClarisWorks user, and I have fond memories there too, but my Dad wrote 7 novels under this software, so if it was good enough for him, it was good enough for this task. (Also, the menu driven UI was nice in a way that made me later prefer nano to vim.)
Now, while firing up a full VMWare DOS image could have been an option, it was overkill, and there are some known issues with CPU throttling under DOS and emulators, that basically, DOS wants to put a brick on the gas pedal of your emulator, and spin up all your fans. So, DOSBox it was.
Getting DOSBox running was easy enough:
brew install dosbox.
Grabbing the five Works for DOS installation images from here was simple too. (Note, these are still copyright Microsoft, but internet law is funny with regard to abandonware, especially for ancient platforms.)
Figuring out that there’s no way in DOSBox to swap a floppy while you’re in another program, so I needed a lot of:
imgmount a /Users/dmahoney/Downloads/WKS4DOS/Disk1.img
copy *.* c:\WKSINST
imgmount -u a
echo "rinse, repeat"
Before I could run the setup.exe. That was fucking annoying (especially because you can’t copy/paste into DOSBox).
But before too long, there I was, in a word processor.
But…what to do now that you’ve written a document? You’ve got a document in an archaic format that you can’t really open in a modern editor. If it were an MS Word doc, everything under the sun would know what to do with it.
When I was uploading several of dad’s books to his website, years ago, I had a hack: export to RTF. Which is not a printed page, but it’s…something. For a word processor that supports little more than bold, underline, and italic (and can’t even properly display them on screen), it was enough. Some quick regular expressions converted the RTFs to HTML just fine. But it’s not…the document.
I wanted the “printing experience”. I wanted to be able to export files *somewhere* and have them render to a printer, even if that required some glue scripting under the hood.
Needless to say, this software had a printer setting for “generic PostScript printer.” That should surely open with MacOS preview, no? Heck, even if there’s no generic PostScript, the Apple LaserWriter is a gold standard for this, and even the 1.05 version of this software had a driver for that.
Now, sending the thing to an actual LPT port, capturing the output, and firing it at a raw CUPS queue would be fun, but that’s not supported by baseline DOSBox. Specifically, mapping the parallel port isn’t. DOSBox-X and other projects support it (as well as things like running Windows 95, so we might go there), but right now, I knew from experience that these things had a “print to file” option:
It gave me what claimed to be a postscript file:
dmahoney@blackfooted-33 dosbox % file LASER.EPS
LASER.EPS: PostScript document text conforming DSC level 2.0
But preview.app hated it:
Thus began the tale of how I learned way more than I ever wanted to know about how this worked.
Okay, so let’s look at the raw file. I know that PostScript files are actually text files, so we can
cat it, but I fed it through hexdump instead, to make sure there were no sneaky dos characters in there (common issue). Here’s a screenshot, Medium’s paste of a line of this width looks awful.
That’s…it. That’s the whole file. I can see my words there. I assume the rest is basic PostScript commands that just say “print this with your default font”. For a word processor from the days of dot matrix line printers and daisy wheels, this makes sense to me.
But when I run it through Ghostscript (which can read .ps files), I get:
dmahoney@blackfooted-33 dosbox % gs LASER.EPS
GPL Ghostscript 9.55.0 (2021-09-27)
Copyright (C) 2021 Artifex Software, Inc. All rights reserved.
This software is supplied under the GNU AGPLv3 and comes with NO WARRANTY:
see the file COPYING for details.
Error: /undefined in PSp
So, there’s some command, PSp, that this version of PostScript doesn’t recognize? Something old? Something deprecated? I suppose for that I’d need the entire PostScript language spec.
Hilarously, the PDF of the spec (https://www.adobe.com/jp/print/postscript/pdfs/PLRM.pdf) would not render in Safari on my mac. (It worked in Firefox), and after reading, reading, grepping…I found no reference to a command or primitive called PSp.
I should mention at this point that searching for arbitrary two-character strings in Google sucks. But eventually, I put a bunch of them together in the right way and got…this gem. And gloriously, it was searchable. From 1989. When this stuff mattered.
While searching for PSp, I found it. The document explained that the .ps files generated by word and company are basically macros, and that there’s a header that’s normally dumped to the printer first. (I get that this results in smaller files, but there’s indication IN THE FILE as to which macros are in use, nothing that says “this is a word file, use the word macros”. I get that exporting your file to printer-file in a non-networked world means you take your document across the office on a floppy to where they have that one nice laser printer (but don’t have MS Works), and fire it off. How is the base user expected to know about this.
But later on in that chapter I saw a define for the now-familiar but totally-not-standard PostScript PSp:
Okay, I knew what I was looking for. I needed that PostScript prologue, and there it was in C:\WORKS:
So the next problem. There’s no way to tell preview to load that prologue. Yes, I could maybe cat them together?
cat WORKS/POSTSRCP.INI LASER.EPS > test.ps should do it, right?
Okay, what about the ps2pdf utility, furnished by the GhostScript package? No, it doesn’t know how to load a prologue file, at least, not easily.
Okay, what about plain vanilla GhostScript. It’s a sledgehammer, but that’s where we’re at.
It turns out there’s something else in that prologue it doesn’t like. Googling that, it turns out that the people who make GhostScript consider this behavior outside of the spec: there’s a 12 year old bug, closed WontFix.
“Ghostscript follows the spec.
exitserver operator calls startjob operator and throws an error
if startjob fails.
According to PLRM, startjob requires that the current level of save nesting
is no deeper than it was at the time the current job started.
postscript.ps creates new save levels.
So startjob fails and exitserver throws an error.”
Effectively, “we’d rather be right than useful”.
More googling, and I get a presentation called:
“Printing without channels: RSCS, CUPS, And Every Other Printer Known To Mankind”
And it’s about printing from mainframe computers over at vmworkshop.org, which is a conference dedicated to the IBM Z/vm architecture, something where I don’t even dabble, but they went into this exact issue.
Turns out there’s a solution.
Okay, so…here goes everything.
- We need that prologue file. Turns out Works provides the same one MS Word does.
- We need to use full-on Ghostscript.
- We need to tell it to use the JobServer option. (Why does that bug report not mention this?)
- We need to tell it to write out to a PDF, and give it a name. Unlike
ps2pdfthere’s a complicated switch for this.
- There are some other please-shut-the-fuck-up options Ghostscript needs.
Fortunately, I found a great example of the various command line needs for this task here.
And while GhostScript dumps out a number of font warnings, I suspect those are only because there’s a stock set of fonts you’d expect a PostScript printer to have by default (that we won’t use anyway)…the magic here is the word “done” at the end:
And, there we go:
Now, automating this could be fun, too. Either by watching a directory, or doing real parallel port emulation for the things that don’t know how to print to file. I’ve also found projects that turn old dot-matrix control codes into PDF as well.
I’m writing this down in case someone else has this problem. Judging by some of the source material I found, some of this will be lost to history soon.
Writer’s note: writing things with weird inconsistent Camel Case like PostScript (capital P, S), Ghostscript (lowercase s), LaserWriter, DOSBox, VMWare…is really annoying.