How to recover data from QIC tapes

Simple: ask me to do it for you!

But if you insist on trying it yourself, here is a rough guide on the steps required to recover data safely and effectively from QIC-150 and QIC-80 cartridges.


First there is the matter of hardware. You’ll need to obtain a QIC-80 tape drive, such as the Colorado 250MB drive which was very common at the time. These are drives that usually connect to the floppy controller on the PC’s motherboard. There are a few types of drives that connect to the parallel port, but these are not recommended since they are much less compatible with various software.

Now you have a few choices. You may choose to take a binary image of the tape, which will be literally a dump of all the data on it. This can be done with Linux using the ftape driver.  Or you can attempt to use the original software that was used to write the tape. This would require you to stage the specific operating system and backup software, boot into it, and use it to restore the data from the tape.

Getting a binary image

This option is more straightforward, and also faster and more reliable, but the disadvantage is that you’ll need to manually decode the data and extract the files from it. Fortunately the data written to QIC-80 tapes mostly adheres to a single specification, and there are ready-made tools to decode this format.

To get a binary dump, you’ll need to boot into Linux. However, because the ftape driver has long been abandoned, it’s only available in very old distributions of Linux. The last version of Ubuntu that included ftape in the kernel was 6.06. Fortunately this version is readily available for download and can be used as a bootable live CD. Once it’s booted, you can load the ftape module by executing:

$ sudo modprobe zftape

This should create the appropriate logical devices that will let you access the tape drive. The device you’ll usually need is /dev/nqft0.

And to start reading data immediately, just execute dd as usual:

$ sudo dd if=/dev/nqft0 of=data.bin conv=sync,noerror &

Don’t forget the ampersand at the end, so that dd will run in the background and give you back control of the console.  The conv=sync,noerror parameter will make dd continue if it encounters errors and pad the output with zeros in case of a bad block. Although the skipping of errors hasn’t seemed to work very reliably with QIC-80 drives. If the drive goes into a loop of shoe-shining the tape for more than a minute, you should probably give up on that volume of the tape. Speaking of volumes:

The tape may consist of multiple volumes, which basically means that multiple backups were written to it in succession.  When your first dd call is complete, it will stop at the end of the first volume on the tape. But there may be additional volumes. You may call dd again right afterwards, which will proceed to read the next volume, and so on. You can also use the vtblc tool to see an actual list of the volumes on the tape.

You may also want to skip directly to another volume on the tape. This is useful if you encounter errors while reading one volume, and want to jump directly to another volume. I’ve found that the best bet is to perform a fresh boot, then skip to the desired volume, and start reading.  To skip to a volume, use the mt fsf command:

$ sudo mt -f /dev/nqft0 fsf x

…where x is the number of volumes to skip. So for example if you want to read the third volume on the tape, execute fsf 2 and start reading.

Note that the drive might not actually fast-forward as soon as you make the mt fsf call. It will usually fast-forward when you actually make the dd call to start reading data.

Using original backup software

If you want to go the route of using the original backup software that was used to write the tape, you’re now in the Wild West of compatibility, trial and error, and general frustration.  Most of the frustration comes from the old software’s incompatibility with modern CPUs (too fast) and modern RAM (too much).

Since the majority of these tapes were written during the DOS era, you’ll need to get a solid DOS environment going, which is surprisingly simple with today’s hardware. If your motherboard supports booting from a USB drive, it will probably be able to boot into DOS. This is because DOS uses the BIOS for disk access, and the motherboard provides access to the USB disk through the BIOS, so that DOS will consider the USB disk to be the C: drive.

There are a lot of different tape backup tools for DOS, but one that I’ve found to be very reliable is HP Backup 7.0. This software has recognized and recovered the vast majority of DOS backups that I’ve seen.  If this tool fails to recognize the tape format, try one of these other tools:

Central Point Backup

This is bundled with PC Tools 9.0. This is another DOS-based backup tool, but it could write the backup in a slightly different format. However, there are very specific steps for getting this software to work.  It does not work on modern (fast) CPUs because it relies on timing logic that causes an integer overflow. This can manifest as an “overflow” error or a “divide by zero” error.

To run Central Point Backup on a modern processor, you will first need to run the SlowDown utility from Bret Johnson.   I’ve found that these parameters work:

C:\> SLOWDOWN /m:25 /Int70

Note that this will cause the keyboard to become sluggish, and you might have some trouble typing, but it’s the only way.


Windows NT came with its own backup utility that could be used to write to floppy tapes. The trouble, however, is getting Windows NT to boot on a live modern system.  The goal is to get a boot disk that runs Windows NT Service Pack 6, which does in fact work well with modern hardware.  If you want to do this from scratch, you can try the following:

  • Connect a spare SATA hard drive (a real one) to your computer.
  • Boot into Linux and make sure to have qemu installed.
  • Run qemu, booting from the Windows NT install ISO image, and having the real hard drive as the emulated disk. For the initial installation, give qemu more modest parameters, including less memory (-m 256) and a lesser CPU (-cpu pentium).
  • After Windows NT is installed, power down the emulated machine, and copy the Service Pack 6 update executable onto the disk.
  • Power the emulated machine back up and install SP6.
  • You can then power it down, and you now have a hard drive loaded with Windows NT SP6, ready to be booted on real modern hardware.

Microsoft Backup (Windows 95)

Windows 95 is extremely tricky to get working on modern hardware, to the point where I would not even recommend attempting it. It may be possible to apply the AMD-K6 update patch, which supposedly allows it to run correctly on fast processors, and then apply the PATCHMEM update that allows it to support large amounts of RAM, but I have not had success with either of these. For me, Windows 95 is forever relegated to running in an emulator only. And fortunately I haven’t seen very many floppy tapes that were written using the backup utility from Windows 95.

QIC-150 and other SCSI tape drives

Reading data from QIC-150 tapes, or most other types of tapes from that time period, is slightly different from reading QIC-80 tapes, mostly because the majority of these types of tape drives connect to the SCSI interface of your PC. This means you’ll need a SCSI adapter that plugs into your motherboard. I’ve had a lot of success with Adaptec UltraWide cards, which are PCI cards, meaning that you’ll need a motherboard that still has older-style PCI slots.

And of course you’ll need a QIC-150 tape drive, such as the Archive Viper 2150, or the Tandberg TDC3660. Newer models of tape drives might be backwards-compatible with older types of tapes, but make sure to check the compatibility list for your drive before attempting to use it to read a tape.

Extracting the data from a tape is extremely simple using Linux. The most recent Linux distributions should work fine (as of 2020). If your tape drive is connected correctly to your SCSI adapter (and terminated properly using a terminating resistor), it will be detected automatically by Linux and should appear as a tape device, such as /dev/nst0.

To start reading data from the tape, execute the following:

$ sudo dd if=/dev/nst0 of=foo.bin conv=noerror,sync

See the previous section on QIC-80 tapes on further usage of dd, and how to read multiple volumes of data from the tape.

In my travels I have also seen tapes that have a nonstandard block size (i.e. greater than 512 bytes). This may manifest as an error given by dd such as “Cannot allocate memory.” In these cases, you can try setting the block size to a generous amount when invoking dd:

$ dd if=/dev/nst0 of=foo.bin conv=noerror,sync bs=64k

A large enough buffer size should fix the allocation error, but if you plan to use it with the “sync” option, then you must know the exact size of the buffer (i.e. the exact block size used by the tape). Otherwise the blocks will be written to the output file with padding that fills up any unused space in each block buffer. A common block size I’ve seen is 16k, especially in 8mm tapes.

Using original backup software

Of course it is also possible to use the original backup software that was used to write the tape. However, it’s much safer to obtain a binary dump of the tape in Linux first, before attempting to read the tape again using other tools. This way you’ll have a pristine image of the tape in case the tape becomes damaged or worn out during subsequent reads.

In many cases there are software tools that will extract the archived file collection directly from a binary image. But if these tools do not recognize the format of your tape image, you will indeed have to use the original software that was used to write it, assuming you can remember what it was. This can be quite difficult: setting up SCSI support in DOS can be a pain; the tape might not have been written using DOS at all, but something like Amiga, and so on. Regardless, the major hurdle is getting the data from the tape to the PC. Decoding the contents of the data is usually a minor detail.

…Or, if you don’t feel like it

I offer first-rate tape recovery services, at a fraction of the cost of other companies. Get in touch anytime and let me know how I can help!

Discovering little worlds

Like so many other people during the COVID lockdown, I’ve been looking for additional hobbies that could be done from home, which would occupy my time and help keep my mind off the collapse of civilization as we know it, and maybe even ground my thoughts and keep them away from hyperbole and catastrophizing.

While cleaning and organizing my basement I came across this small USB device. It’s barely larger than a flash drive, but it’s no flash drive at all — it’s a software-defined radio (SDR), namely an RTL-SDR V3 dongle.

I don’t even recall how this device ended up in my possession;  I think it was probably from one of my previous jobs:  they were throwing away a bunch of equipment that was no longer useful, and allowed me to keep some of the items.  Regardless, I had never actually used the SDR, and hadn’t really thought about what the SDR would be useful for.  I had a vague understanding that the SDR can let me tune in to any random radio frequency, but how interesting can that be?  Well, it turns out that playing around with this device led me into a rabbit hole of epic proportions.

Once I found the right software to work with the SDR device (SDRSharp for Windows, and CubicSDR for Mac), I was up and running.  The first rather trivial thing to do was to tune in to the local FM radio stations. Here they are, as viewed through a spectrogram:

FM radio

But that’s kind of boring. I wonder what lies outside of the FM radio band? Well, the next obvious destination is the local police frequencies, which are around 460 MHz to 490 MHz in my area. These are narrow-band FM (NFM) stations, so we adjust our software settings accordingly. In mere moments, I’m listening to police dispatchers communicating with units and telling them about robberies, car accidents, and the like:

And of course there are a few local HAM radio repeaters nearby, which tells me that the HAM community is very much alive and well.  Since I can’t transmit anything using my tiny SDR device, I can only listen in on the HAM conversations, but that’s okay since the conversation wasn’t particularly scintillating anyway, and I’m not sure that getting into the little world of HAM radio is really my goal here. As much as I salute the enthusiasts who keep HAM radio going, they can party on without me.

Mind you, all of this was using the cheap tiny antenna that came with the SDR itself.  But then I discovered that the SDR can be used for something else entirely: receiving signals from satellites!

Arguably the easiest satellites to pick up signals are the NOAA 15/18/19 satellites, which are weather satellites that transmit images of cloud cover over the ground. By “easiest” I mean requiring the least amount of additional equipment:  it only requires a rabbit-ear (V-dipole) antenna connected to your SDR, and a cloud-free day to get a good signal. Here is the signal at 137.9 MHz, and the resulting image, which is produced by special software that demodulates the “audio” data that was recorded:

The downside is that these satellites are in a sun-synchronous orbit, and will only pass by your location for ~15-minute intervals at the most, and can only be caught at very early or late hours of the day. The other downside is that the NOAA satellites are aging, and will probably be decommissioned in the coming years. And anyway, the images they transmit are not the highest quality. Time to step it up to the next level, namely the GOES satellites!

The GOES-16 satellite is a newer weather satellite that is geostationary, and is positioned permanently above the Americas. In fact its longitude is almost exactly over the East coast, which is perfect for my purposes, and its inclination from my location is about 45 degrees (because it orbits around the equator, as all geostationary satellites must do).

But because it’s geostationary it’s also much farther away, and therefore its signal is much weaker, and requires additional equipment:

The setup consists of an old WiFi grid antenna, which feeds into a SAW filter and amplifier, which then feeds into the SDR that’s now connected to a Raspberry Pi (the total cost was about $100).  The Raspberry Pi is running a package called goestools which demodulates the signal from the satellite in real time, and translates the signal into images. The satellite transmits images of Earth in many different spectral bands, ranging from visible light to deep infrared.

And so, the final little world I discovered on this adventure is this one:

The full resolution of these images is 10K, which is mind-blowing, and my next step is to create animations from these images, which are sent by the satellite every 15 minutes.

I think I’ll leave this antenna setup as a permanent installation in my house, so that I can grab these signals anytime I like. Even though this imagery is available on the web if you know where to look, there is something profoundly awesome in knowing that you personally can receive selfies of our world, from 35,000 kilometers away, using about $100 worth of equipment. It’s been a very satisfying few weeks, in spite of everything else that’s happening this year.

Thoughts on the new Star Trek

I watched Star Trek: Picard recently, and… I am sad.

Gene Roddenberry had a vision: a future which is truly post-racial, post-war, post-poverty, etc. It’s a world for us to strive towards, to admire, to want to live in.  But the world of Star Trek: Picard seems to have all the same problems we have in the 21st century.  The Federation is a systemically racist organization that refuses to help an enemy in a time of desperate need. There is deep wealth inequality between different classes of people on Earth. People treat sentient androids like property. And all of “space” is a hostile battleground where one dares not venture without being armed to the teeth.

That’s not a world I look forward to living in, and it would be depressing to me if this is how humanity “turns out” in three hundred years.

Aside from pontificating about today’s political issues, the show’s plot is completely incoherent, and the writing is so lazy and unfocused. Remember Picard’s caretakers at his château who were former Tal Shiar? Those were some interesting characters, but will we ever see them again? Was there any point in having the Borg involved in the story at all? Does the Romulan Samurai kid (bet you can’t think of his name!) have any purpose than to chop people’s heads off? Will Agnes’s murder of Bruce Maddox be swept under the rug? Will the fact that Picard is now a synthetic golem ever be mentioned again?

One perfect example of lazy writing is embodied in the hand-held purple repair device that the Androids conveniently give to Captain Rios. This device basically grants wishes: you can wish it to repair your broken warp core! Or you can wish it to create a mirage of a hundred starships, complete with warp signatures that can fool Romulan sensors! What luck!

And think about how Old Trek and New Trek are different in terms of fandom. There are fans who transform their basement to look like the bridge of the Enterprise. There are fans who program their desktop computer to look like an LCARS interface. And of course there are countless fans who attend conventions dressed up like characters from the Original Series and Next Generation. But will there be any fans who’ll want to recreate the bridge of Captain Rios’s ship (bet you don’t know what it’s called)? Will there be any fans who will admire or want to emulate any of these new characters?

Is it possible anymore to have a show where the whole universe isn’t about to blow up all the time? Can we just have a show where the Enterprise goes to a planet, and Picard negotiates a peace accord, while Data and Geordi get into a wacky holodeck adventure?  I ask for so precious little!

Reverse engineering a 25-year-old Visual Basic app

Following up from last week’s misadventures with the Avant Stellar keyboard (trying and failing to extract macro information from the keyboard’s internal memory), there was another glimmer of hope:  my friend found a backup file that possibly contains all the macros that were saved to the keyboard.  If I could just reverse-engineer this backup, we could extract the macros directly from the file.  It is a 2 KB file with a .KBD extension, unrecognizable as any binary format I’ve seen to date. Here is a partial hex dump of the file:

It’s pretty clear that the file contains a key mapping, as evidenced by the list of incrementing 32-bit numbers at the beginning, up to offset 0x210.  There are roughly 120 increasing numbers, which is roughly the number of keys on the keyboard, so we can safely assume that this is the key mapping.  After the key mapping, I presume, comes the macro information, and this is where things get tricky, since there’s virtually no way to tell how the macros are encoded in the file. The data simply looks too general to make sense of.

An obvious possibility would be to “load” the backup file into the Avant software tool that came with the keyboard, and visually inspect the macro(s) assigned to each key.  But no matter what I tried, the software would not load the file.  Or rather, it loaded the key mapping, but not the macros.  Time to think about the nuclear option: disassemble the Avant software and see how it’s actually processing the backup file.

Looking at the folder contents of the Avant software tool, I immediately notice a dead giveaway: VBRUN300.DLL, which means this tool was written in Visual Basic 3.0.  This makes our job much easier, because there are actually ready-made tools for decompiling Visual Basic executables. (If you recall, Visual Basic compiles executables into p-code instead of native machine code, which makes them much more straightforward to decompile.)  All of this took me quite a while to remember, because I hadn’t used these tools since my early, early hacking days, and it took a little while longer to find them in my archives!  The go-to utility for performing this task was literally called VB3 Decompiler, and the way to find this tool on the web today is… outside the scope of this post.

The decompilation basically results in several Visual Basic source files, in which the original function names are intact, but the local and global variables are changed to generic identifiers, since those names are not stored in the compiled code. It takes a little bit of further massaging to get these files to actually build within Visual Basic, but after that, it’s almost as if you have the original source code of the program at your fingertips.

There was one other minor hurdle because the Avant software uses custom UI components (.VBX files) that don’t allow themselves to be used in Design mode (as part of a copy-protection or licensing mechanism), but this is bypassable using another utility in the decompiler suite that “fools” Visual Basic into loading the components anyway.

With the source code buildable and debuggable, we can now easily run the program and load the .KBD backup file, and trace through where it processes the data in the file:

Even though the variable names aren’t very descriptive in the above screenshot, it’s easy enough to spot the loop that deserializes the keyboard macros, and how each macro is composed.  Not only that, but we can determine what was preventing it from displaying the macros in the first place — it turned out that it expects the keyboard to be physically connected while running, and while I’m pretty sure that we tried loading the backup with the keyboard attached, it wasn’t working anyway, probably because the keyboard is malfunctioning and no longer able to communicate properly.  But at last, with this requirement bypassed, the macros that were loaded from the backup file finally reveal themselves:

Confirmation dialogs

Recently a friend of mine contacted me with an interesting issue.  He got ahold of a keyboard from an old PC workstation used with some legacy accounting software. But this was no regular keyboard — it was an Avant Stellar keyboard, in which all of the keys were remappable, and any key could be programmed with custom macros.

The original owner of the keyboard was no longer at the accounting firm, but my friend was very interested in determining what macros were assigned to each key, so that the accounting firm could use the old software more effectively, and hopefully transition away from it more easily.

I helped by managing to dig up the original software that shipped with these keyboards, which worked with MS-DOS and older versions of Windows. Here is what the software looks like:

Clearly this software is where the user gets to create their own macros and remap all of the key bindings. No less clearly, the software allows us to “Upload” and “Download” the mappings.  So, naturally, my friend thought the most sensible action would be to “Download” the current state of the keyboard and view all the macros in the UI of this software tool.  And so, he clicked the Download button, and… nothing seemed to happen. After a brief progress message, the interface stayed the same.

Now here’s the question: What does “upload” and “download” mean?  In 2020, download generally means “fetch something from an external source and save it onto the computer,” and upload means “send something from the computer to an external source.”  And you might think, in the context of this keyboard, download means “retrieve the current state of the keyboard onto the computer”…

But sadly, twenty years ago, the programmers of this software had the opposite definition of “download” in their minds.  Downloading meant loading the current mappings from the software onto the keyboard!

And even more sadly, the programmers didn’t include a prominent confirmation dialog that says, “CAUTION: this will load the new mapping onto the keyboard and overwrite any previous settings!”  And with a single click, the keyboard was overwritten without any warning or backup.  The only thing the programmers did was include a tooltip that appears when hovering over the Download button:

…but the tooltip appeared only after it was already too late.