An emulator for the TC2000 supercomputer

A few years ago I received a package of tapes that came from a TC2000 system, which was a supercomputer from the late 1980s built by a company called BBN (Bolt, Beranek and Newman). The data on these tapes was recovered without any issues, and it turned out to be a minor treasure trove of software for the TC2000, as well as its cousin the GP1000.

image

One of the tapes was an actual “boot” tape — the system would boot from this tape, which then allows the user to install the operating system (4.3BSD Unix) onto a hard disk. (Unfortunately the system installation tape was not part of this collection; just the boot tape, and a few other supplemental software tapes, so it isn’t possible to reconstruct a “complete” TC2000 system from what we have here.)

Ever since then, I’ve had a bullet point deep in my backlog to build an emulator for this system, and actually boot this tape image, and see the 4.3BSD kernel messages from 1989 flying across the screen. Sort of… like this:

The above is literally the live TC2000 system, booting into the real tape image with vmunix on it, running in your browser, and letting you interact with it (here is the source code!). Admittedly there isn’t much to do in this boot environment. It expects you to execute nxinstall and proceed to install the operating system onto a hard disk, but like I said, the actual full operating system is on another, missing tape. So instead, I took the boot tape image and combined it with some of the aforementioned “supplemental” software tools, which includes a number of games that you can play in the above console. Go to /usr/games/ and experience for yourself the kind of fun that users of the TC2000 were having in 1989.

(I should note that the emulation is not perfect, because much of it needed to be reverse-engineered from the actual instructions of the kernel executable. So, if any program you run in the emulator crashes or gets stuck, you can click the “Restart” button to reboot.)

***

The thing is, this emulator was built almost entirely by an LLM (Claude Opus 5, over the course of a few days of prompting and iterating), and you know what? I think I’m okay with that. If you’ll permit some philosophizing and grappling with the use of an LLM for a hobby project like this:

My hobby is retrocomputing. But ultimately, the real satisfaction I derive from this hobby is making something work. For me, the end result of seeing something working is the satisfying payoff. The tools I use for making something work are a secondary detail. Using an LLM is a new tool for getting something to work. That the LLM was able to build a TC2000 emulator for me is therefore a genuine win.

Is the win cheapened by the fact that I didn’t write most of the code? I don’t believe so. The fact is, if LLMs didn’t exist, then this random idea would have languished in my backlog forever, and would have never gotten done. Would it have been possible for me to write all this code myself? Absolutely, over the course of several years of this project taking priority over other things in my life, which would simply not be worth it. Is the win cheapened by the fact that “anyone can do it” now? I don’t believe so. Yes, it is true that anyone else could have done this. So then… go ahead and do it! Who’s stopping you from picking a random idea you had ages ago, and getting it done?

***

So there we have it: here is the repo of the TC2000 emulator, which emulates a Motorola 88100 CPU, an 88200 CMMU, and all the other accoutrements to get the system booted See the README file in the repo for much more details of how the system works. Unfortunately the emulator can’t go much further without more of the missing pieces from the original TC2000 system: ROM images, the full OS installation tape, and so on. Without these things, the emulator won’t be able to emulate the major selling point of this whole system: the “Butterfly switch” that actually allows multiple processor nodes to run processes independently (currently it emulates just a single node). If you or someone you know has access to these materials, or has additional stories from the BBN days, please get in touch!

Brain dump, May 2026

My old Kindles

With Amazon having ended support for many older-generation Kindle devices, I thought I’d go back and make sure that my existing Kindles will still be usable for the foreseeable future. Up until now, I’ve been using a 2nd generation Kindle (yes, literally the Kindle 2, released in 2009), and my wife has been using a 3rd generation Kindle, released in 2010.

image

We use and enjoy these devices almost every day, because they still work perfectly well for the purpose of reading books. I mostly read free eBooks from Gutenberg, as well as technical PDF files, since my Kindle 2 doesn’t support WiFi, which is fine with me. If I need to load a new book or document onto my Kindle, I don’t mind connecting it to my PC and transferring the book over.

The Kindle 3 that my wife had been using supports WiFi (the first Kindle model to do so), and she had enjoyed borrowing books from our library through her Amazon account. When she heard the news that Amazon was dropping support for her Kindle, despite my pleas, she insisted on finally upgrading to a more modern Kindle, and ended up getting the Kindle 11, released in 2024.

image

Even though the Kindle 11 is better in some ways than the Kindle 3, both my wife and I agree that it’s not 8 generations-worth better. Yes, it’s more responsive overall, and the e-ink refreshes slightly faster, and the backlight can be useful in low light conditions. But certain other things feel like either regressions or just unnecessary product churn. Why, I ask you, did they get rid of physical buttons to go to the next or previous page? These were extremely convenient and intuitive affordances that allowed single-handed navigation through the book, and saved the display from getting smudged due to constant tapping and swiping.

Would it kill them to keep physical buttons for turning pages? Is it some kind of competition of minimalism? Are they showing off their ability to incorporate touch gestures into their e-ink display technology? We get it, you can make a capacitive e-ink touchscreen. But physical buttons are good, too!

I suppose, on the one hand, Amazon can be commended for continuing support for these devices for the last 15 years, which is longer than many other hardware vendors I can name. But on the other hand, is it really that difficult to continue supporting them further? This really feels like planned forced obsolescence. It feels like Amazon unwittingly made these older devices too good, and now wants to force users to upgrade.

In any case, now that my wife has switched to the Kindle 11, I will be switching to her old Kindle 3, but not just a Kindle 3 — a jailbroken Kindle 3! Jailbreaking allows you to do numerous interesting things with the Kindle, including customizing the screensaver illustrations, and even having a functioning console:

image

Typing actual commands into this e-ink console using the Kindle keyboard is as excruciating as you might expect, but just seeing it work is reward enough.

But seriously, the real benefit of jailbreaking is to install a custom non-Amazon reader app that supports the EPUB format natively (among others), whereas previously I would need to convert from the EPUB to the MOBI format. And with these updates, I will be keeping my Kindle 3 until either its hardware fails entirely, or I drop it into a lake. Otherwise, I see no reason at all to upgrade to a newer model.

Retro handhelds

I’ve been kind of obsessed with super-cheap handheld retro gaming consoles lately! During a shopping spree on AliExpress for some unrelated electronics, I randomly came across these devices and picked up a couple, namely the RGB30 ($60 with a discount), and the R36S (regularly $60, but I got a “clone” version for $30 which seems to work just fine). These devices run Linux, and boot from a microSD card that also holds the game ROM files that you want to play. And since it’s Linux, there is naturally a thriving community that builds custom OS images with all kinds of customizable features and tweaks. I loaded dArkOS on both of these devices, and it runs perfectly.

image

I’m not a “gamer” by any stretch at all, nor do I really want to be. I did, however, used to play plenty of games in the old days on MS-DOS, Commodore 64, various arcades, all the way up to Nintendo 64, but not much beyond that.

And that’s where these devices really rise to the occasion: they run an emulation platform (RetroArch, running on top of Linux) that can emulate all of these old game systems, and many others, with impressive accuracy. Just put your ROM files onto the microSD card, and off you go.

These devices are definitely “cheap” in most senses. The ergonomics are so-so, the buttons and joysticks are a bit flimsy, battery life is not great, and so on. However, one area where these devices shine is the display: the screens on these devices are quite nice, with good brightness and crisp pixels, particularly if you emulate the games with integer scaling.

The RGB30 (my favorite of the two, although more expensive) has a display resolution of 720×720 — yes, a square aspect ratio — which is super interesting, because this offers the versatility of playing e.g. GameBoy Advance games with integer scaling (the GBA had a resolution of 240×160, which scales nicely to 720), but also playing arcade games, which are often played in portrait (vertical) orientation, which also looks great on this display.

image

And the R36S has a display resolution of 640×480, which is also very interesting, because this is great for integer scaling of DOS games, most of which used 320×200 VGA resolution, and look fantastic on this device:

image

Spend just a few minutes customizing the key bindings of the device’s buttons to correspond to the specific game’s controls, and you’re good to go. Even mouse-driven point-and-click games for DOS (King’s Quest, Kyrandia, etc.) work great, with the mouse emulated using one of the analog joysticks. If you’re feeling particularly masochistic, you could even run Windows 3.1, or even Windows 95, and go nuts.

image

And that’s why I like these handheld devices so much — they scratch the itch of getting something working just right, and they deliver an instant hit of nostalgia; I play a game for about 10 minutes, get bored, and then move on with my day. It’s perfect.

Defeating a 40-year-old copy protection dongle

image

That’s right — this little device is what stood between me and the ability to run an even older piece of software that I recently unearthed during an expedition of software archaeology.

For a bit more background, I was recently involved in helping a friend’s accounting firm to move away from using an extremely legacy software package that they had locked themselves into using for the last four decades.

This software was built using a programming language called RPG (“Report Program Generator”), which is older than COBOL (!), and was used with IBM’s midrange computers such as the System/3, System/32, and all the way up to the AS/400. Apparently, RPG was subsequently ported to MS-DOS, so that the same software tools built with RPG could run on personal computers, which is how we ended up here.

This accounting firm was actually using a Windows 98 computer (yep, in 2026), and running the RPG software inside a DOS console window. And it turned out that, in order to run this software, it requires a special hardware copy-protection dongle to be attached to the computer’s parallel port! This was a relatively common practice in those days, particularly with “enterprise” software vendors who wanted to protect their very important™ software from unauthorized use.

image

Sadly, most of the text and markings on the dongle’s label has been worn or scratched off, but we can make out several clues:

  • The words “Stamford, CT”, and what’s very likely the logo of a company called “Software Security Inc”. The only evidence for the existence of this company is this record of them exhibiting their wares at SIGGRAPH conferences in the early 1990s, as well as several patents issued to them, relating to software protection.
  • A word that seems to say “RUNTIME”, which will become clear in a bit.

My first course of action was to take a disk image of the Windows 98 PC that was running this software, and get it running in an emulator, so that we could see what the software actually does, and perhaps export the data from this software into a more modern format, to be used with modern accounting tools. But of course all of this requires the hardware dongle; none of the accounting tools seem to work without it plugged in.

Before doing anything, I looked through the disk image for any additional interesting clues, and found plenty of fascinating (and archaeologically significant?) stuff:

image

  • We’ve got a compiler for the RPG II language (excellent!), made by a company called Software West Inc.
  • Even better, there are two versions of the RPG II compiler, released on various dates in the 1990s by Software West.
  • We’ve got the complete source code of the accounting software, written in RPG. It looks like the full accounting package consists of numerous RPG modules, with a gnarly combination of DOS batch files for orchestrating them, all set up as a “menu” system for the user to navigate using number combinations. Clearly the author of this accounting system was originally an IBM mainframe programmer, and insisted on bringing those skills over to DOS, with mixed results.

I began by playing around with the RPG compiler in isolation, and I learned very quickly that it’s the RPG compiler itself that requires the hardware dongle, and then the compiler automatically injects the same copy-protection logic into any executables it generates. This explains the text that seems to say “RUNTIME” on the dongle.

The compiler consists of a few executable files, notably RPGC.EXE, which is the compiler, and SEU.EXE, which is a source editor (“Source Entry Utility”). Here’s what we get when we launch SEU without the dongle, after a couple of seconds:

image

A bit rude, but this gives us an important clue: this program must be trying to communicate over the parallel port over the course of a few seconds (which could give us an opportunity to pause it for debugging, and see what it’s doing during that time), and then exits with a message (which we can now find in a disassembly of the program, and trace how it gets there).

A great tool for disassembling executables of this vintage is Reko. It understands 16-bit real mode executables, and even attempts to decompile them into readable C code that corresponds to the disassembly.

image

And so, looking at the decompiled/disassembled code in Reko, I expected to find in and out instructions, which would be the telltale sign of the program trying to communicate with the parallel port through the PC’s I/O ports. However… I didn’t see an in or out instruction anywhere! But then I noticed something: Reko disassembled the executable into two “segments”: 0800 and 0809, and I was only looking at segment 0809.

image

If we look at segment 0800, we see the smoking gun: in and out instructions, meaning that the copy-protection routine is definitely here, and best of all, the entire code segment is a mere 0x90 bytes, which suggests that the entire routine should be pretty easy to unravel and understand. For some reason, Reko was not able to decompile this code into a C representation, but it still produced a disassembly, which will work just fine for our purposes. Maybe this was a primitive form of obfuscation from those early days, which is now confusing Reko and preventing it from associating this chunk of code with the rest of the program… who knows.

Here is a GitHub Gist with the disassembly of this code, along with my annotations and notes. My x86 assembly knowledge is a little rusty, but here is the gist of what this code does:

  • It’s definitely a single self-contained routine, intended to be called using a “far” CALL instruction, since it returns with a RETF instruction.
  • It begins by detecting the address of the parallel port, by reading the BIOS data area. If the computer has more than one parallel port, the dongle must be connected to the first parallel port (LPT1).
  • It performs a loop where it writes values to the data register of the parallel port, and then reads the status register, and accumulates responses in the BH and BL registers.
  • At the end of the routine, the “result” of the whole procedure is stored in the BX register (BH and BL together), which will presumably be “verified” by the caller of the routine.
  • Very importantly, there doesn’t seem to be any “input” into this routine. It doesn’t pop anything from the stack, nor does it care about any register values passed into it. Which can only mean that the result of this routine is completely constant! No matter what complicated back-and-forth it does with the dongle, the result of this routine should always be the same.

With the knowledge that this routine must exit with some magic value stored in BX, we can now patch the first few bytes of the routine to do just that! Not yet knowing which value to put in BX, let’s start with 1234:

BB 34 12       MOV BX, 1234h
CB             RETF

Only the first four bytes need patching — set BX to our desired value, and get out of there (RETF). Running the patched executable with these new bytes still fails (expectedly) with the same message of “No dongle, no edit”, but it fails immediately, instead of after several seconds of talking to the parallel port. Progress!

Stepping through the disassembly more closely, we get another major clue: The only value that BH can be at the end of the routine is 76h (this is hard-coded into the routine). So, our total value for the magic number in BX must be of the form 76xx. In other words, only the BL value remains unknown:

BB __ 76       MOV BX, 76__h
CB             RETF

Since BL is an 8-bit register, it can only have 256 possible values. And what do we do when we have 256 combinations to try? Brute force it! I whipped up a script that plugs a value into that particular byte (from 0 to 255) and programmatically launches the executable in DosBox, and observes the output. Lo and behold, it worked! The brute forcing didn’t take long at all, because the correct number turned out to be… 6. Meaning that the total magic number in BX should be 7606h:

BB 06 76       MOV BX, 7606h
CB             RETF

image

Bingo!
And then, proceeding to examine the other executable files in the compiler suite, the parallel port routine turns out to be exactly the same. All of the executables have the exact same copy protection logic, as if it was rubber-stamped onto them. In fact, when the compiler (RPGC.EXE) compiles some RPG source code, it seems to copy the parallel port routine from itself into the compiled program. That’s right: the patched version of the compiler will produce executables with the same patched copy protection routine! Very convenient.

I must say, this copy protection mechanism seems a bit… simplistic? A hardware dongle that just passes back a constant number? Defeatable with a four-byte patch? Is this really worthy of a patent? But who am I to pass judgment. It’s possible that I haven’t fully understood the logic, and the copy protection will somehow re-surface in another way. It’s also possible that the creators of the RPG compiler (Software West, Inc) didn’t take proper advantage of the hardware dongle, and used it in a way that is so easily bypassed.

In any case, Software West’s RPG II compiler is now free from the constraint of the parallel port dongle! And at some point soon, I’ll work on purging any PII from the compiler directories, and make this compiler available as an artifact of computing history. It doesn’t seem to be available anywhere else on the web. If anyone reading this was associated with Software West Inc, feel free to get in touch — I have many questions!

Brain dump, October 2025

What do I do with old Android phones that I’d like to keep around for testing purposes, while no longer worrying about the long-term fate of the lithium battery inside them? Here’s what:

I take the battery out, make sure it’s fully discharged, and surgically remove the controller logic board from the battery (don’t try this yourself unless you know exactly what you’re doing).

image

I then solder this PCB directly onto the battery terminals in the phone, and finally solder my actual power inputs onto the positive and negative pads on the underside of the PCB.

image

The above example is a Samsung Galaxy Note 4, still plenty powerful for all kinds of development and testing purposes, and is now usable without a battery! I opted to use a cheap standard barrel connector for my power cable, simply because that’s what I had on hand, and also to emphasize that it must be connected to a proper power supply that outputs ~4 volts and is capable of at least 2 amps.

Here is the Note 4, running off a 12V power supply, through a cheap adjustable buck converter that is tuned to output exactly 4.0V, which makes the phone believe the battery is 85% charged.

image


Speaking of “Android” devices, I had a bit of fun playing with a couple of these intriguing things:

image

This is an LTE/WiFi dongle, which lets you insert your SIM card that has a data plan, for when you want to connect to the internet from your laptop on the go. But under the surface, there are several things about this dongle that are very interesting indeed:

First, this stick is basically a fully-fledged Android device on the inside. That’s right — it contains all the internals of a low-end Android phone, cleverly packaged into a USB stick form-factor.

image

Another interesting thing is the price: at the time of writing, I was able to obtain several of these devices for about $8 each from AliExpress, which is an incredible value for the functionality you can unlock, because:

The final interesting thing about these devices is that they’re very hackable. In fact, there’s an entire community (because of course there is!) that has figured out how to load a completely standard Debian distro onto this stick, with all the bells and whistles that provides, including USB gadget capabilities, allowing you to turn this stick into any type of USB device of your choosing, such as a mass storage device, or an HID keyboard (à la Rubber Ducky, except for 1/10th the price), or an RNDIS network interface (which can capture and record packets), or any number of other types of gadgets, all while still allowing you to “log in” to it via its WiFi hotspot or LTE modem.

I went a little overboard and soldered some wires onto the UART pins, then routed the wires around the metal shielding so that they’d stick out of the plastic case.

image

I then put some hot glue over the wires and smooshed the plastic case over it, so that the wires are nicely secured. And now I have a nicely debuggable platform for doing further tinkering with this amazing little stick!

image
image

Using Claude Code to modernize a 25-year-old kernel driver

As a bit of background, one of my hobbies is helping people recover data from old tape cartridges, such as QIC-80 tapes, which were a rather popular backup medium in the 1990s among individuals, small businesses, BBS operators, and the like. I have a soft spot for tape media; there’s something about the tactile sensation of holding these tapes in my hands that makes the whole process very joyful, even though QIC tapes are notorious for their many design flaws. With some careful inspection and reconditioning, the data on these tapes is still totally recoverable, even after all these years.

Whenever I receive a QIC-80 tape for recovery, I power up one of my older PC workstations which has the appropriate tape drive attached to it, and boot into a very old version of Linux (namely CentOS 3.5), because this is the only way to use the ftape driver, which is the kernel driver necessary for communicating with this tape drive, allowing the user to dump the binary contents of the tape.

You see, the drive that reads these tapes connects to the floppy controller on the motherboard. This clever hack was done as a cost-saving measure: instead of having to purchase a separate SCSI adapter (the standard interface for higher-tier tape media), you can just connect this tape drive to your floppy controller, which was already available on most PCs. It can even work alongside your existing floppy drive, on the same ribbon cable! The tradeoff, of course, is that the data rate is limited by the speed of the floppy controller, which was something like 500 Kbps (that’s kilobits, not bytes).

The other downside is that the protocol for communicating with these tape drives through the floppy controller was very messy, nonstandard, and not very well-supported. It was a “hack” in every sense: your motherboard’s BIOS had no knowledge of the tape drive being connected, and it was entirely up to the end-user software to know exactly how to manipulate the hardware I/O ports, timings, interrupts, etc. to trick the floppy controller into sending the appropriate commands to the tape drive.

image

There were a small number of proprietary tools for MS-DOS and Windows 3.x/9x for dealing with these drives, and only one open-source implementation for Linux, namely ftape. Of course it is possible to use those original DOS/Windows tools to read the tapes, but it’s actually only ftape that allows us to read the “raw” binary contents of the tape, regardless of which proprietary software originally wrote it, which is why I prefer it for dumping the contents and worrying afterwards about decoding the proprietary logical formatting, and then extracting the files from it.

The trouble is, the ftape driver hasn’t been supported since roughly the year 2000, and was soon removed from the Linux kernel for this reason. This is why I’ve needed to run a painfully old version of Linux anytime I have to work with one of these drives. It would be great if ftape worked on a modern distro, with all the benefits and affordances that would provide.

***

So a couple of weeks ago, it occurred to me to make a simple request to Claude Code:

> This repository is a Linux kernel driver that communicates with legacy tape drives connected to the floppy
  controller (FDC) on the motherboard. Unfortunately, this driver hasn't been maintained for a long time, and
  can only compile under kernel version 2.4. I'd like to modernize this driver, allowing it to be built with
  the latest versions of the kernel.

● I'll help you modernize this Linux kernel driver for legacy tape drives. This is a significant task that
  will require updating the code to work with modern kernel APIs and conventions.

And after several iterations of “combobulating” and whatever else Claude claims to do, I suddenly had a kernel driver that was compiling without errors. This is because Claude is able to take the compiler output and feed it back into itself, until the compilation works correctly. There was a laundry list of kernel functions and structures that were understandably deprecated or replaced, in the eternity that elapsed between kernel version 2.4 and version 6.8. Amazingly, Claude found all the outdated bits and replaced them with the correct modern equivalents, requiring just a few manual touch-ups of the code (a bit more on this later).

At this point, however, the kernel driver was still expected to be compiled as part of a full kernel tree, whereas I just wanted it to become a standalone loadable kernel module. OK, no problem:

> Is there a way to compile just this module in-place, instead of copying it into a kernel source tree?

● Yes! You can compile kernel modules out-of-tree without copying them into the kernel source. Let me create
  a proper standalone build system for the ftape driver.

…And it did. Without any further prompting. At the end of this stage, I had a loadable kernel module (.ko) that I could start trying to use with actual live hardware. Unsurprisingly, the module did not yet “work” — it was loading, but something was preventing it from communicating with the tape drive correctly. But I pressed on.

From this point forward, since loading/unloading kernel modules requires sudo, I could no longer let Claude “iterate” on such sensitive operations by itself. Luckily, the ftape driver was already generously sprinkled with logging messages (printk() calls that are printed to dmesg), so I loaded the module myself, and iteratively pasted the output of dmesg into Claude manually, and let Claude compare it to a “known-good” dmesg log that I’d previously saved from a successful tape read. After a few iterations of this, Claude identified the remaining issues preventing the module from communicating with the hardware.

● Perfect! The module has parameters that can be set. The issue is that without configuration, all the base
  addresses default to -1, which gets converted to 0xffff in the config function, causing the detection to fail.
● The "No such device or address" (ENXIO) error occurs because the ftape-internal module is not configured
  with the correct I/O port base address for your floppy controller.
  The issue is in fdc-internal.c:735-737: if fdc->sra == 0xffff, it returns -ENXIO. Since no configuration was
  provided, all values default to -1, which becomes 0xffff....

And at last, I had a kernel module that was able to a) load, b) detect the tape drive, and c) dump the contents of a test tape!

image

***

Using the ftape driver on a modern kernel, a feat that I thought was hopelessly out of reach, was suddenly completed over the course of two evenings.

As a giant caveat, I should note that I have a small bit of prior experience working with kernel modules, and a good amount of experience with C in general, so I don’t want to overstate Claude’s success in this scenario. As in, it wasn’t literally three prompts to get Claude to poop out a working kernel module, but rather several back-and-forth conversations and, yes, several manual fixups of the code. It would absolutely not be possible to perform this modernization without a baseline knowledge of the internals of a kernel module.

This led me to crystallize some thoughts on working with such coding agents in our current moment:

Open yourself up to a genuine collaboration with these tools.

Interacting with Claude Code felt like an actual collaboration with a fellow engineer. People like to compare it to working with a “junior” engineer, and I think that’s broadly accurate: it will do whatever you tell it to do, it’s eager to please, it’s overconfident, it’s quick to apologize and praise you for being “absolutely right” when you point out a mistake it made, and so on. Because of this, you (the human) are still the one who must provide the guardrails, make product decisions, enforce architectural guidelines, and spot potential problems as early as possible.

Be as specific as possible, making sure to use the domain-specific keywords for the task.

I’m not claiming to suddenly be an expert in prompt engineering, but the prompts that I’ve found to be most successful are ones that clearly lay out the verbal scaffolding for a feature, and then describe the gaps in the scaffolding that the LLM should fill in. (For some reason the image that comes to mind is one of those biological stem-cell scaffolds where an artificial human ear will grow.)

Develop an intuition for the kinds of tasks that are “well-suited” for an agent to complete.

These agents are not magical, and can’t do literally everything you ask. If you ask it to do something for which it’s not well-suited, you will become frustrated and prematurely reject these tools before you allow them to shine. On this point, it’s useful to learn how LLMs actually work, so that you develop a sense of their strengths and weaknesses.

Use these tools as a massive force multiplier of your own skills.

I’m sure that if I really wanted to, I could have done this modernization effort on my own. But that would have required me to learn kernel development as it was done 25 years ago. This would have probably taken me several weeks of nonstop poring over documentation that would be completely useless knowledge today. Instead of all that, I spent a couple of days chatting with an agent and having it explain to me all the things it did.

Naturally, I verified and tested the changes it made, and in the process I did end up learning a huge amount of things that will be actually useful to me in the future, such as modern kernel conventions, some interesting details of x86 architecture, as well as several command line incantations that I’ll be keeping in my arsenal.

Use these tools for rapid onboarding onto new frameworks.

I am not a kernel developer by any stretch, but this particular experience ignited a spark that might lead to more kernel-level work, and it turns out that kernel development isn’t nearly as difficult as it might sound. In another unrelated “vibe-coding” session, I built a Flutter app without having used Flutter before. If you’re like me, and your learning style is to learn by doing, these tools can radically accelerate your pace of learning new frameworks, freeing you up to do more high-level architectural thinking.

***

In any case, circling all the way back, I am now happy to say that ftape lives on! Twenty-five years after its last official release, it is once again buildable and usable on modern Linux. I’m still in the process of making some further tweaks and new feature additions, but I have already verified that it works with the floppy-based tape drives in my collection, as well as parallel-port-based drives which it also supports.

image

The physical setup looks very similar, but the OS is now Xubuntu 24.04, instead of CentOS 3.5! 🎉
Until next time!