Before It's Lost — Rebuilding the Sega Saturn's development environment on a modern PC

Featured image for article: Before It's Lost — Rebuilding the Sega Saturn's development environment on a modern PC

A thirty-year-old Sega Saturn still works. Capacitors leak and optical drives wear out, but fix those and the machine runs. Hardware turns out to be surprisingly stubborn.

What gets lost first is the stuff around it.

There is a piece of Saturn development equipment called CartDev — a development cartridge that goes into the cartridge slot. Connect it to a PC and you can push a program you wrote into the machine's memory, run it, stop it partway, and look at the registers and memory. It was the official development environment, the one the game developers of the day actually used.

The CartDev board seated in the Saturn's cartridge slot, with the Saturn CartDev Rev. B unit underneath

I have one. It isn't broken. And yet there is no longer a PC that can talk to it.

This post is about rebuilding the road back to it.

Three generations of the Sega Saturn CartDev toolchain

1994 — when there were only five layers

The setup looked like this:

SNASM2 / SNBUGSAT → DOS → SCSI host adapter → CartDev → Sega Saturn

On the PC ran SN Systems' SNASM2: an SH-2 assembler and a debugger called SNBUGSAT.EXE. Load a program in the debugger and it runs on real hardware; stop it and the register window fills with R0–R15 and PC.

The thing worth noticing is that there is nothing exotic anywhere in that chain. DOS was the standard OS of the day, and a SCSI card was an expansion card you bought off a shelf. From a developer's point of view this was simply "plugging a cable into a Saturn" — about as straightforward as it gets.

Five layers, and two of them are hardware. There isn't much room for anything to go wrong.

The 2000s — USB slots into the middle

In time, DOS disappeared from PCs. So did ISA slots. So did SCSI cards, at least as ordinary equipment.

I still needed the CartDev for emulator development, so I took to launching it through a virtual machine.

Run VMware on a host OS (32-bit Windows or Linux), put DOS inside it, and run SNASM2 inside the DOS. In place of the SCSI card, use an Adaptec USBXchange — a USB-to-SCSI bridge — and pass the device the host enumerates through to the guest.

SNASM2 / SNBUGSAT → DOS (guest) → SCSI (ASPI) → VMware → host OS → USB → USBXchange → CartDev → Sega Saturn

Nine layers. Four more than in 1994, and all four of the new ones are things that have no business being there: a virtual machine whose only job is to run DOS, a host OS underneath it whose only job is to run the virtual machine, and then USB and the USBXchange.

Those last two are the telling ones. The CartDev is a SCSI device, and what SNASM2 emits are SCSI commands. In 1994 those went out of the SCSI card and straight down the cable. In this arrangement they get wrapped up and carried over USB, and the bridge at the far end unwraps them back into SCSI. There is a SCSI → USB → SCSI round trip sitting in the middle of the path.

It worked, though. For a long time this was the only realistic way to use a CartDev.

With one condition: all nine layers had to hold at the same time.

2026 — the stack comes apart

The blocks were pulled out from the bottom up.

DOS won't run on the host. 64-bit Windows dropped the 16-bit subsystem (NTVDM), closing off any way to run DOS programs directly. The only way to run DOS is inside a virtual machine — which means the VM stopped being a convenience and became a mandatory part.

The SCSI passthrough doesn't get through. Having the host recognise the USBXchange as a SCSI device and then handing that device to the guest depends on both the host OS's drivers and the VM's implementation. Driver signing requirements on 64-bit systems, changes in how generic SCSI devices are handled, changes in the passthrough implementation — any one of them breaks the path.

VMware itself changed. Product lineups, licensing terms, and how you obtain it have all changed repeatedly over twenty years. Knowing that "version X of VMware works" loses its value the moment version X stops being available.

So where does that leave things?

The CartDev isn't broken. The Saturn isn't broken. The SNASM2 binaries are right here. And none of it can be run. What it takes to run has narrowed down to one specific combination of specific versions of software that can no longer be obtained.

This is what it means for hardware to become lost technology. The object doesn't break. The road to the object collapses first.

So: take out everything in between

I changed the question.

Of those nine layers, which ones are actually necessary? What the CartDev understands are SCSI commands arriving via the USBXchange bridge. DOS, SNASM2, VMware — every one of those layers exists only to assemble those SCSI commands.

If that's all it is, then a PC can assemble and send them directly.

The problem was that nobody knows what those commands are. There is no specification. All that exists is a record of the system back when it worked.

So, on an old setup that still barely ran, I started the real debugger and captured the entire USB conversation. Load a program in the debugger, run it, stop it — and record everything that crossed the USB wire while that happened.

36,718 packets; 6,120 SCSI transactions. That became the foundation for everything that followed.

At the same time I ran an SH-2 disassembler over SATMON.BIN, the monitor program the CartDev leaves resident in the Saturn's memory, and read it. A capture tells you what happened; it doesn't tell you why. Only by cross-checking the two does the meaning of a command actually pin down.

Breakpoints, for example, never showed up in the captures at all. I found a table of jump targets inside SATMON.BIN, indexed by command number, and worked backwards from it: this command calls that routine, and that routine does this.

It runs

Once the protocol was readable, the rest was just writing it.

What came out is a single tool that runs on nothing but the Python 3 standard library. No DOS, no virtual machine, no SCSI driver. A straight line from the PC's USB port, through the USBXchange and the CartDev, into the Saturn's memory.

$ python3 cartdev.py detect
device:  usb 03f3:2001 (bus 3 device 9)
  vendor:   SEGA OA
  product:  Saturn CartDev
  revision: C69

$ python3 cartdev.py connect
  waiting for the monitor to come up ... ready after 16.2 s
connected.

$ python3 cartdev.py go program.coff
writing 109060 bytes in 3 segment(s), 32768-byte chunks, verifying each chunk
  ... 109060/109060 bytes (100%)
loaded; PC set to 0x06004000
starting at PC=0x06004000 ...
running.

The moment that last running. appeared, the SGL demo came up on the TV next to me, on the real Saturn.

109,060 bytes takes about six seconds. Every block written is read back and compared, so if anything gets corrupted on the way it surfaces immediately rather than as a mystery crash.

Breakpoints and single step work too:

$ python3 cartdev.py bp 0x06004016 --run
breakpoint armed at 0x06004016
running ...
  PC=0x06004016  PR=0x060151e4  SR=0x00000000  R15=0x06006e40
  break cause 12 (user break)

Name an address, run, stop there, read the registers. The same thing SNBUGSAT.EXE was doing in 1994.

The stack now looks like this:

cartdev.py → libusb → USBXchange → CartDev → Sega Saturn

Five layers, three of them hardware. Back to the same count as 1994, and four fewer than the nine of the 2000s — and the four that went were all the fragile ones. Count only the software and there is one layer less than in 1994.

No virtual machine. No DOS. No negotiating with a SCSI driver. It is designed to run on Linux, on Windows, and (untested) on macOS.

These days it can be driven from a GUI as well, which makes developing and debugging Saturn software easier than it ever was in the SNASM2 era.

Before it's lost

The strongest impression left by all of this is that the hardware was never what broke.

The CartDev hasn't changed in thirty years. Neither has the Saturn. What changed was the PC, and the layers stacked up to suit the PC peeled away one at a time.

And when those layers peel away, the hardware underneath becomes unusable while remaining perfectly intact. It runs, but you can't reach it. That is a strange way for something to break.

The same thing is surely happening in a lot of places. Equipment stranded when the environment it needed disappeared. Protocols with no specification. Peripherals that can do nothing without the one host they were built for.

Most technology will be lost at exactly that point. But as for the Sega Saturn — it will go on living for as long as I do.