SheepShaver boots Mac OS 9 with a native JIT. Getting it on Apple Silicon? That took work. Full native 9.2? Even harder.
SheepShaver is a legendary Mac OS emulator (fast, compatible, beloved), but it cannot boot Mac OS 9.2. Iirc, you can coax it to run 9.2 through hacks, but you still won't get all the features.
I really wanted SheepShaver + 9.2 back in the early 2000s.
Twenty-five years on, it is still a nope. You can use QEMU (on Apple Silicon, UTM is the best practical option for 9.2.2 today), but that is not SheepShaver, and you can feel it when using it.
What I still want is SheepShaver's particular trick running classic Mac OS: a thin emulation layer with a JIT. The JIT was only part of why it is fast, translating PowerPC instructions to native at runtime, but the bigger idea SheepShaver offered was what it declines to emulate. Rather than simulating a whole Macintosh, SheepShaver emulates the PowerPC CPU and patches the Mac ROM to route everything else (I/O, memory, threads) straight to the host.
Guest memory is just a region of the host's address space at a fixed offset, so a memory access is pointer arithmetic rather than a simulated lookup. It is not quite Wine on Linux, which translates an OS's API calls without running its kernel at all, but it sits much closer to that tightly integrated end of the spectrum than to a fully virtualized machine.
QEMU JIT-translates PowerPC too: its TCG engine dynamically recompiles guest code to native ARM64. So the gap is not really JIT versus interpreter. It is everything around the CPU. QEMU simulates every piece of hardware the original Mac would have seen (the VIA chips that handle timers and interrupts, the ADB controller behind the keyboard and mouse, the SCSI bus that talks to disks, the whole stack) rather than patching the OS to use host services directly. That means translating every guest memory address in software (a TLB lookup) and calling out to C helper routines for low-level system instructions. Community benchmarks put SheepShaver at roughly 5× QEMU's overall score on comparable hardware, with the floating-point gap closer to 10×.
In practice QEMU/UTM on classic Mac workloads feels like running on a ~300 MHz G3: usable and stable, but noticeably slower than SheepShaver at 9.0.4. SheepShaver avoids most of that overhead because it was never a full-system emulator: it runs guest threads as real host threads and uses a JIT that skips supervisor-mode emulation entirely. That architecture is also why it tops out at 9.0.4: the New World ROM that 9.2 requires actually needs the hardware emulation layer SheepShaver has always refused to implement.
Getting SheepShaver's speed and Mac OS 9.2 together, without hacks, turned out to be a much harder problem than it looked.
The rabbit hole went deep.
My history with classic Mac OS was in desktop publishing: Quark 4 on Mac OS 7, PostScript ads that could lock the whole system, the peculiar texture of cooperative multitasking. By the time I was doing web work seriously, I was already on Mac OS X. What I had never touched was the programming side of it: what classic Mac development actually felt like, the toolchain, building something for the platform from scratch. I had always been curious about that.
I have a Quicksilver G4 and a few iBooks in the basement that could theoretically address this. But they are loud, take up space, and draw significant power. So I have been approaching it from modern conveniences instead.
Over the past year that has meant several experiments at once. Classic-vibe-mac compiles C source to a 68k Mac binary and runs it live in System 7.5.5 via WebAssembly Basilisk II; writing Mac programs without leaving the browser. Scriptoscope is a Mac OS-style window manager and Kaleidoscope theme engine for the browser. PDF-A-go-slim borrowed the floating palette paradigm from the 1995 Mac OS Human Interface Guidelines and applied it to a modern browser utility. All of that was aesthetics and runtime at arm's length from the actual software.
Macsurf pushed it closer — a classic Mac app I wanted to compile on QEMU. But that was slow, which led me back to SheepShaver, which led to the problem above.
The detour to Apple Silicon, and then 9.2#
SheepShaver for ARM carries a fork chain:
- the original cebix/macemu,
- community-maintained by kanjitalk755,
- then an ARM64 JIT backend by rcarmo targeting Linux ARM boards.
Nobody had yet taken it to macOS Apple Silicon. Getting there first meant porting that JIT backend to a platform with tighter constraints: MAP_JIT for executable pages, Mach exception handling instead of POSIX signals, address space limits that interact with SheepShaver's unusual architecture in specific ways.
SheepShaver was designed in the late 1990s to run native PowerPC Mac code on native PowerPC Linux. There was originally nothing to emulate at all, just the Mac-specific hardware. That cooperative design is still baked in everywhere, and a lot of its assumptions about address space and memory layout needed rethinking for a modern macOS host.
Getting to 9.2 is a different layer of the problem and one that isn't done yet for any flavor of SheepShaver.
I've put a lot of time into understanding how the nanokernel interacts with the MMU, figuring out what needs to be properly modelled versus what can be safely sidestepped, and then circling back to do real implementations after those investigations proved the shortcuts would not hold. I had expected to draw more directly on existing work, and dingusppc in particular taught me a great deal. It takes the opposite approach to SheepShaver: full-system, device-accurate emulation of older PowerPC Macs (the SCC serial, VIA timer, and ADB controllers SheepShaver skips entirely), with a focus on Old World and beige-G3 hardware. That accuracy-first model is much closer to what the New World ROM actually expects, so it was a valuable reference for the hardware layer even though I was not trying to build the same kind of emulator. QEMU was the other early reference, but it turned out to be most useful as a diagnostic tool rather than an architectural model. The biggest unexpected source of inspiration was Dolphin, the GameCube and Wii emulator: a completely different platform, but the same class of problem.
Much of this has been done in collaboration with an AI coding partner. I wrote about that working pattern in let the AI worry about the code, you worry about the work. This project pushed it further than I expected: less about delegating implementation tasks, more about managing a technical investigation across sessions: knowing when to go deep, when to step back, when a hypothesis had been falsified and it was time to try something else. Project management skills translate into this kind of work more directly than I would have guessed.
The result: SheepShaver boots Mac OS up to 9.0 to the Finder desktop on M-series Macs, with a native AArch64 JIT on by default. There is also preliminary AltiVec support, opt-in for now, because Mac OS 8.6 and 9.0 do not save vector registers across task switches.
I'm still not yet there for 9.2 support, but I am getting incrementally closer. Keep reading...
What is next#
The Apple Silicon JIT work was the prerequisite. Mac OS 9.2 is the actual goal. It is worth being honest about why 9.2 specifically: the features it adds over 9.0 (preemptive multitasking, proper memory protection, 128-bit file encryption) are not things I actually need. Nobody is running production workloads on a classic Mac. But most ambitious hobby projects do not have a compelling real-world justification; that is more or less what makes them hobby projects. The point is getting the thing right. That said, if this all comes together, Final Cut Pro 3 on SheepShaver becomes possible. Which is entirely unnecessary and, I think, quite cool.
Running alongside it: SiliconSheep, a native macOS launcher for SheepShaver that makes the day-to-day experience less of a configuration exercise.
Neither is done. This post is less an announcement than a status note: here is what has been happening, here is what is in progress.
More than nostalgia#
While a lot of this is nostalgia, there is a less sentimental case, and it comes down to how software gets written now.
Building for classic Mac OS was always a grind: period hardware, a finicky toolchain, slow edit-build-test loops on machines that are rare and getting rarer. That friction is most of why the development scene faded. Coding agents change those economics. The same kind of AI partner that helped port this emulator can write 68k and PowerPC code and find its way around an unfamiliar toolchain, which collapses the loop that used to make this work tedious.
Put a genuinely easy-to-run environment on modern hardware next to that, and a path opens up: writing new classic Mac software again. Some of it would run inside Mac OS 9 on an M-series laptop; some could compile down to the real beige hardware still humming in basements. Classic-vibe-mac was a first hint of this; a fast SheepShaver is the other half. I am not promising a renaissance. But the thing that always killed it was friction, and removing friction is exactly what these tools are good at. Get the development experience right and the rest becomes possible.
I do not have formal domain expertise in emulator development. What I have is curiosity, some stubbornness, and an AI partner that turned out to be a good collaborator on gnarly low-level problems. AI will not be to everyone's taste, and I understand that. It is a hobby project; I am sharing it back in case any of it is useful, not because anyone has to approve of the method.
How far this goes, I am not sure yet. But the Finder boots on my M-series Mac with JIT, and I think I could crack 9.2, too.
Final Cut Pro 3 box art © Apple Inc.