← Home

Daisy Wheel Diaries, part 3: write your own printer driver!

This is the third part of the Daisy Wheel Diaries series. The first part can be found here, and the second part here.

Ink Suppliers

Most types of printer need some kind of ink. Impact printers usually used ink ribbons, like the typewriters which proceeded them. However, some daisy wheel printers used ink rollers instead, like the LetterMaster.

You might wonder how an "ink roller" works, or what exactly it is. As the name suggests, it's a roller containing ink. The mechanism is quite clever, really! It's mounted below the printwheel – the "daisy wheel" part of a daisy wheel printer – and as the printwheel spins, it brushes against the ink roller, collecting ink and rotating it. It ensures each "petal" is inked before it even hits the page. Very simple, very effective. Also less prone to problems than a ribbon might be, since it doesn't go between the print head and the page.

One of the problems with buying an obscure printer model from more than two decades ago is that it might be difficult to obtain ink for it. That's no problem, of course, if it comes with plentiful ink already. But as is probably obvious from those printouts, the ink roller on this thing has mostly dried up. So, we must obtain more ink - but how?

You may recall that in Part 1, I noticed that the part number for the specific ink roller the LetterMaster requires is no longer in Royal's product catalogue. But I also noticed that the neighbouring part numbers are also ink rollers... could they be compatible? Because if they were compatible, I could just buy new ink straight from Royal!

Well, here's the part 013109, aka IR-40:

Image of 013109/IR-40

And here's the part the LetterMaster needs, 013018, aka IR-100:

Image of 013018/IR-100

Look the same to you?

Thought not.

Oh well.

You may notice I just mentioned the codes "IR-40" and "IR-100". When I wrote Part 1, I didn't know the ink rollers also had these other codes. But after writing Part 2, I did a lot of Googling in a desperate search for ink, and found out the part also had that name. Turns out it's the more common name for it: you'd use "013018" to order the item from Royal, but the thing itself is actually the IR-100. Cool.

And because I now know the more common name, I have another thing to search for. So I search for IR-100 ink, and what would you know...

...you can get it on Amazon and eBay! Hooray!

Well... if you were to actually follow those links, you'd discover that you could get it. Past tense, not conditional. That rare instance of two packs of IR-100 being on eBay? That was on March 23. Someone bought them. Without a time machine, I can't get them, now. And on Amazon, while there is a product listing, it is not available from anyone.

Drat.

I desparately searched for IR-100 ink, but it is nowhere to be found. So, time for alternatives.

Alternative Ink

You may recall from Part 1 that I am not the only person to have documented the Royal LetterMaster on YouTube, someone else had made a video. Well, in that video, the author, "pamperchu", mentions that they "sprayed a little WD-40" on the ink roller to soften it up.

I thought I'd try the same. At my parents' house, there's some WD-40 in the garage, so...

Image of me holding the LetterMaster's ink roller next to the print mechanism I removed it from

Image of me holding a can of WD-40

Image of LetterMaster's ink roller, removed and placed on a piece of white paper, that has been sprayed with WD-40 with visible dampness on the paper

Let's see if the output's any better.

(there should be a picture here, but it seems I didn't take one :/)

...just as faint as before. Oh well.

Along the way when trying to find somewhere I could get ink, I happened upon this Yahoo! Answers page. The person there suggested reïnking the ink roller with an ink pad. I'll have to try that.

So, the ink problem still hasn't been dealt with. But we still have another half of this tale. Let's be honest, you didn't come here for the ink, so let's cut to the chase...

Microsoft can't write a printer driver

Remember how in Part 2 I got it to work on Windows using the default "Generic / Text Only" driver?

Remember how I said it doesn't handle margins properly, leading to it returning short at the end of lines? It's a bit of a problem.

Let me explain a bit better.

The LetterMaster is a budget printer. In order to keep costs down, the thing is quite limited in width. It can print on a US Letter (8.5"x11") page, but the print head can't actually cover the entirety of the page on the horizontal axis. Instead, it has a smaller printable area of about 6.6", starting at 1" in from the left and ending at 0.9" in from the right. On non-continuous paper, there's a similarly constrained printable area on the vertical axis.

This means that when you send characters to it over the Centronics cable, it'll start printing from the left margin onwards, until it hits the right margin. As the printer firmware has native support for bidirectional printing (rather than needing the PC to emulate it with cursor commands), it'll then move down to the next line and start printing in the opposite direction, automatically wrapping to the margin. Pretty great, huh?

So, you can send this to the printer verbatim (pretend it's a C string):

"Lorem ipsum dolor sit amet, consectetur adipscing elit. Etiam a luctus dui, In non laoreet augue, vitae aliquet ipsum."

And your output on paper will look like this (imagine this is a neatly framed page with margins):

Lorem ipsum dolor sit amet, consectetur adipscing elit. Etiam a luctus dui, In n
on laoreet augue, vitae aliquet ipsum.

It wraps at the character boundary and doesn't bother to break between words, but hey, it wraps correctly. With manual word-wrapping by the PC, it'd look perfect.

Unfortunately, Windows doesn't quite send text verbatim. Windows's "Generic / Text Only" printer driver makes an incompatible assumption: it expects that the printer starts printing from 0" in, right at the edge of the paper. In order to add a horizontal margin, it begins each line with several spaces. Likewise, it prepends the output with several newlines to add a vertical margin.

So, it sends something more like this: (again, imagine it's a C string, with implicit concatenation)

"\n\n\n\n"
"      Lorem ipsum dolor sit amet, consectetur adipscing elit. Etiam a luctus dui, In n\r\n"
"      on laoreet augue, vitae aliquet ipsum.\r\n"

And the output ends up looking like this:





      Lorem ipsum dolor sit amet, consectetur adipscing elit. Etiam a luctus dui
, In n
      on laoreet augue, vitae aliquet ipsum.

Oh dear, oh deary me... It's doubled the vertical and horizontal margins, and we have this cut off bit of each line moved into the fake left margin. Eww!

Luckily, the "Generic / Text Only" driver supports setting a "printable area" for exactly this reason. So, I inform it that there's a 1" margin on the left, a 1" vertical margin, a 0.9" margin on the right, and...









            Lorem ipsum dolor sit amet, consectetur adipscing elit. Etiam a luct
us dui, In n
            on laoreet augue, vitae aliquet ipsum.

Goddamnit Microsoft. Why are there only options to ADD margins? Why can't I REMOVE them? (No, negative numbers don't work - I did try that.)

Now, you can just set a left margin of 0 in Page Setup when printing, and increase the right margin so the line isn't too long and forced to wrap. And I think that works, although until now I didn't realise you'd have to touch the right margin - I only changed the left one, so I still had wrapping issues.

Thing is, margins aren't the only issue with "Generic / Text Only". It can't even handle basic formatting options.

See, the LetterMaster actually can do some very limited effects for your text. It can do bold text, achieved by making two impacts rather than one for each character. It can also do underlining, achieved by overstriking an underscore (_). These aren't special tricks done by the host PC telling it to go back one character, either! Automatic bold and underline modes are supported by the firmware, and can be turned on and off with escape sequences.

Luckily, the "Generic / Text Only" options let you specify the printer's bold on/off and underline on/off commands, if it has them. In the case of the LetterMaster, these are "\e&" (bold off), "\eO" (bold on), "\eR" (underline off) and "\eE" (underline on). The LetterMaster didn't come up with these command sequences, actually. Its command set is a subset of the Diablo 630's – an early and high-quality daisy-wheel printer whose popularity led to its command set becoming the de facto standard. Interestingly, the LetterMaster's manual, which contains a list of features, doesn't actually mention anywhere that its command set is a subset of the Diablo's! This is most likely because it had become an expected feature ("Diablo emulation") for all daisy-wheel printers to have, so it'd probably be more notable not to use a Diablo subset.

So, I filled in the sequences in the configuration, opened WordPad, and made myself a test document with bold and underline. Then I printed it, aaaaand...

...where's the bold? Where's the underline?

That's odd. I could've sworn... hmm. Let's see what output was actually sent to the printer. You can do this with Windows's "Print to File" option. So I do that, open it in notepad, and what's the first thing I see?

␛O

(Well, it looked something like that: I'm going by memory. Actually, I think Notepad just displays a "missing glyph" type thing when it encounters escape.)

It had produced the correct escape sequences. But they were on the first line, followed by tons of whitespace. They were not surrounding the actual text needing bolding and underlining. What the hell?

...Microsoft, why? Did you not test this thing?! For goodness' sake...

Since Microsoft can't do it, let's write our own!

Finally to the fun bit! So, you're thinking this sounds almost masochistic, right? Who would want to go and write a full kernel-mode C++ driver for a daisy-wheel printer that deals with the GDI? Wouldn't that be really painful?

Yes, it really would.

Which is why I didn't do it. You don't need to write a single line of C++. But how come?

Well, turns out there's a thing called the Microsoft Universal Printer Driver, aka Unidrv. Ever heard of Winprinters, those devices with no on-board PostScript processor, which did all the rendering in software? Unidrv is a tool Microsoft created to make writing drivers for them easier. Rather than writing your own full printer driver, you can write a simple plaintext .GPD file specifying the printer's command set, and optionally a plugin DLL or two, and Unidrv handles the rest. This combo of description files and optional plugin DLLs is called a "Minidriver".

GPD code looks like this:

*ModelName: "ACMEPrint 6000"
*GPDFileName: "ACMEPrint.gpd"
*GPDSpecVersion: "1.0"
*GPDFileVersion: "0.1"
*MasterUnits: PAIR(300, 300)
*PrinterType: TTY
*PrintRate: 10
*PrintRateUnit: CPS
*% etc. etc.

Doesn't that look simple? Sounds pretty great, doesn't it?

And it is. I discovered this existed when mucking about with the "Generic / Text Only" driver. When I clicked on its "About" thing, I found out it was "Unidrv", and naturally DuckDuckGo'd it. It has its own Wikipedia page!. I also found the .GPD file for "Generic / Text Only": TTY.GPD. Pretty cool stuff.

Learning of Unidrv, I thought: why not write my own minidriver for the LetterMaster? It's just a text file. So I did. I read through the MSDN documentation, wrote myself an INF file, and went to install it.

The process is much like you saw in Part 2, except this time I choose Have Disk, select the inf file, and...

Oh, this driver is unsigned, is it? Are you sure you want to continue?

I tell Windows that yes, I do. Then it just fails.

I look up the error code, and that's the error code for... unsigned driver installation.

Goddamnit Microsoft. If you were going to refuse to install anyway, WHY DID YOU PROMPT ME?!?!

sigh

Alright, I reboot Windows into the mode where it doesn't check for a signature on driver installation. All seems well, it's installing, and then...

The INF file is malformed? Huh? All the files are there, and it looks okay to me...

Several hours of hopeless attempts at fixing it later, staying up until 7am and horribly ruining my sleep cycle and Cicadian rhythms, waiting many agonising hours to install the entirety of Visual Studio 2013 Express, just so I can install the Windows Driver Kit, just so I can use some bloody Perl scripts (there's no frigging dependency! WHY DO I NEED TO DOWNLOAD ALL OF VISUAL STUDIO AND ALL OF THE WINDOWS DRIVER KIT TO GET THESE, MICROSOFT? WHY?!) to check the validity of my INF files... – all of this done in a slow Windows 8.1 VM running off a USB2 hard disk (the sluggishness compared to an SSD is agony itself) – and finally...

...after going to sleep, since that was just the install process alone...

...it turns out there were some issues with my INF file, say the Perl scripts. Okay, I fix them. Let's try again.

After a lot of trial and error, by which I mean chanting arcane and unreasonable, almost undocumented incantations in an unspeakable Eldritch tongue known only as the "Microsoft INF file syntax" which no mere mortal, let alone a parser, can compreHĔ͒L̿̔ͮͬ̏pͪ̉ͬ̊ ͆͛m̈́̂̔e̔͂͗̇̽̃ ͆̓ͫͫP̉ͫ͐͋ͩ͂̎Lͬ͒̓e͗̓A͛ͯ̒͂̉͆ͧS̓̆ͭ͊̒e͐̈ͫ̅ͯ̓ ͫͪ͒t̉͌ͭͩ͛̆ͪH̐͛͌̔E͐̇̓ͮ̚ ̄̓̏̑ͧCo͗̊M͆ͩ̆ͥ̾M͊̈́̃̄̂̌ͨA͛̇̃̇͋S̔͗ͬ ͦ̋T͛H̓̽ͮ̌ͩ̅E̎̔͑̈ C̓ͪ͊ͮ̈ͤ͑OMͮ̉ͣ͐͌̂M̋A̅̃S ̓͋͆̑̆T͒ͭ͊HE͊ͬͦ̈Yͥ̆ ̓͒͒͋̂̆AR̀ͦͩ̈E̽ͫ̇ͥ ̇̐͐̓E̽ͩV̈ͭ̄ͫ͛ͭ̆e̊ͩ͊̍RỲ̏̊̀̏w͊̾̈ͣ̽ͤh̐͒̾͋͂͋̆3ͤ̇͛̏̚Ř̀ͧ̎ͦ̎̚Eͥ́ͯ̄ͪ̏̍ ̈HͣEͯ͊͌ͤL̈ͤ́̇Pͣ̋ ͪͤͪWh͑͆ͭ̏ÃT͑̓ͭͧ̔̚ ͑ͬ͌͋͑̐ǏS̄̋ ̈̌̍͋̈́̀Tͨͬ̾̚H͗̍̐̉́Î̍̎̅ͥ̐ͯSͤͦ̚ ͑͂Aͣ̔̈́̐B̑͛̎̇̀OͦͥM̈́̂̄̆͊inͪA̔t͒͆͌̇ͮI̔ͦ̋ͯÕͪ̓͒ͥNͫ ̊̀I̊̆͌ͮ ̔ͨ͋̄̂ďͤ͋͛̇͂oo̓͂̿͑̂nͧ̈́ͬͯ:͋T Eͨͩ̓vͥͦěe͌ͣͯnN̐̊̂̿T̓ͯ̈̅ͣͯ̚T̉ ͮ̄ͩ̆͒̈K͛͑̉̇͐͐Ṅ̅͒oͧ̊͌Wͮͦ ̆Wͬͦhw̌̀a͗̽͋̎ͬ̒T̏̐͗ ͭ̄a̐̑ͣ̑̎̒n͐ i̇ͭ̎̒̽̎T̾͛áNͨ͑̉̚i̐ͯ̈U̐̋͊m ̀i͂̀ͥ̽S̑̓̓ͧ̿ ̓W͑̔̌̾hͯȲ ͦW͛̾ͣͭ́̐͌Hͯ̅̅̌̎͑̚yͯ̓ͮ͌ͩ̿ͮ ̏̆̾ͩ͆aͯ̇R͑̂e͗ ͆̽t̄ͬͬͤ̂̑h͌̈́ͣë́̈̍̇ͣR̄ͦͩ̀ͫ̐Ě ͒́ͥͧ̓ͬa̋L̍l̆ͥ̇ ͫẗ́̀ͩH̽ͩ͌̈̐̆E̎͑sͬͯ̓̎͆ͩ͆ĕ͊ ̈́ͥ̿̓ͣͪA̐̐ͦ̋Aͧ͒ͭC͂ͥͬ̄̏c̆ú͗r̓ͯ̓̂̏S͐̒ͨ̍̇Eͨͨ̉̿ͩDͧ͛ͭͤ̽dͣ͑̋͊̑͑ ͂͑̄͆ͥ͒maͮ̿̂͐ͮ̓gͤͣ̐̑ͫ̉N̄̽͛̐Eͫtͩ͆̄̊Iͭ̊̏̅͑ͨͬc͋͊́̒ͪ̿ ̐̎͆ͣͤ̇D͋ͨ̇I͑Š̄͆̊̅͂̾sͪkͫͨ̾́ͬSͯ͌̽ͬ Á͑ͨ̊ã̉͋́́ͭa͛̉ͥ̚Aͩ̾ͦͫa͊͂͌ã̓ͣͯͫAͧ̈ͥAͨ̎̍̉̃̿Âͭ͐̊͆ͤͮAͩ̎͑a͛ͨͨ̽ͮͮa̐̒ͩͬ̚A͂̾̓̎̚Aͤ̿͛͐̔̚A̅ͪ͑̇ãͪͣ̃ͧ"valid INF file" is produced.

But yes, now all is good (apart from the lingering smell of blood and the incomprehensible howling outside, obviously), and...

Unable to install printer. Some driver files are missing or incorrect. Reinstall the driver or try using the latest version.

Oh, OK, still broken? What now? Okay, the INF horror "file" is fine. So that means the GPD is broken. But there's no way to check that right?

I spend ages poring over the .GPD trying to find mistakes. I do actually find some, when checking against the reference docs. But I'm dying for something to actually tell me what's wrong with it. How can I test it, though?

Scouring through the Windows Driver Kit, I discover that actually, there is a file called gpdcheck.exe. Could it be...?

Sure enough, it's a GPD syntax checker. It finds some basic syntax errors, and it turns out one of the constants MSDN mentions doesn't actually exist (WHAT?!?!). So I fix all that, and then we try again once more.

We go through the same process as before, everything is good, and then...

Unable to install printer. Cannot complete this function.

CANNOT COMPLETE THIS FUNCTION? CANNOT COMPLETE THIS FUNCTION?! WHAT DOES TTHAT EVEN MEAN?!

I Google it. I try, desparately, to find the answer. I look through Windows's logging system. There is nothing. There is no hope. GPDcheck says everything's fine. Yet it doesn't work. I can't find an error in the driver. I ask on StackOverflow, which is quite a long shot. Nobody is able to help.

/ (╯°□°)╯︵ ┻━┻

I'm done.

You suck, Microsoft.

(Though the source is on GitHub, and it's extensively, almost excessively commented - go read it if you want, it might be interesting to you, and contains lots of fun details about the LetterMaster's command set!)

Where do we go now?

The minidriver project seems like a dead end... I do not know what is wrong with that cursed gpd file, and don't know how I might ever find out. I got so fed up with that VM's sluggishness (and its inability to do something else), that I ended up getting rid of it, replacing it with a Boot Camp dual-boot setup. This means I no longer have the Windows Driver Kit (or its Visual Studio prerequisite) installed anywhere, and there's no way I'm reïnstalling it.

But that's alright, because I have another idea I know is workable. It turns out that there is a way to get the printer working on OS X, at least, a way to send raw data to it. And we can send raw data to the printer, bypassing "Generic / Text Only" on Windows, too. So, I just need to write a small command-line app that can speak LetterMaster and translate Markdown or something, and which can pipe that output to the printer. It'll probably be written in Haskell. And then, finally, I shall get proper underline, bold, and margins... or even other stuff. I'd really like to do fancy stuff like diacritics (àîúëõ) by telling the printer to overstrike.

And I still need to deal with the ink problem.

So, this will be continued in part 4. Watch this space!