Infinite Mac: Snow and A/UX #
tl;dr: Infinite Mac now uses a custom WebAssembly build of the Snow emulator to simulate many early 68K Macintoshes. Snow is a more capable emulator; in addition to classic Mac OS, it is now possible to run A/UX (Apple’s late ’80s UNIX/Mac hybrid).
Snow
Since its launch, all of the early (pre-System 7) instances on Infinite Mac have been powered by Mini vMac. I’ve previously discussed how it’s a somewhat idiosyncratic and seemingly abandoned codebase. While the core emulator works well enough, I had a long list of features for deeper integration into the site (and bugs). I did not relish the thought of diving back into a sea of cryptically named functions and C preprocessor tricks. Separately, “learn Rust” had been on my wishlist, but I never had a project in mind for it.
It was thus fortuitous that Snow was released late last year. It’s an emulator that covers the same era1 as Mini vMac, with a focus on accuracy. It also happens to be written in Rust, and has an active maintainer and community. I set out to bring up Snow as a new emulator core inside Infinite Mac, with the goal of eventually replacing my use of Mini vMac.
Snow is a well-structured codebase; there’s already a separation between the core and the native frontend. It was pretty natural to add a new crate that hooked up the core to the Infinite Mac abstractions for video, input, audio, disk images, etc. For file I/O and audio, Snow didn’t quite have the flexibility I needed, but it was feasible to add a layer of indirection. The maintainer was open to merging these changes; my fork is mostly Infinite Mac-specific work, and thus easy to keep up to date.
The flipside of Snow being a more accurate emulator is that it also replicates the limitations of early Mac hardware. For example, the original Mac 128K only had an internal 400K floppy drive, and a connector for attaching an external one. But there was no first-party hard drive (at least, not without hacks) and third-party ones sound finicky2. Mini vMac did not quite operate at that level (it instead patches the ROM and relies on that custom driver) and thus it was possible to “cheat” – I had simulated an “Infinite HD” for it with 1.4 MB of installed software, even though that was anachronistic3.

Disk swapper’s elbow, now in your browser

Some familiar names in early Mac software about boxes
In lieu of a hard drive, I ended up extending the CD-ROM library feature with a “Floppies” companion. It draws upon the Internet Archive (especially the Moof-A-Day collection) and the Macintosh Garden to showcase early Mac software. Unlike with CD-ROMs, the disk images are small enough that it’s worth it for me to host them – it both improves reliability and allows me to preprocess them, to handle compression and other edge cases.
Despite the Mac having a reputation of not having a lot of software, it was still impressive just how much there was released even in its first couple of years of its existence. I’m sure I’ve missed including some classics, but I’m happy to add more if you let me know.
Additional changes were required to handle Snow’s verisimilitude. MODE32 is now available to allow the IIcx and other non-32-bit-clean machines to actually address more than 8 MB of RAM. I had to make sure that a CD-ROM driver was installed on all disk images, otherwise CDs could not be mounted. Similar to the hard drive situation, I had been relying on Basilisk II’s ROM patching for this support.
The most complicated change involved teaching the OS to handle dynamic screen sizes and color depths. Snow emulates real NuBus graphics cards (unlike Mini vMac and Basilisk II’s virtual screen drivers), and they would default to black and white. The configuration is driven by a scrn resource that’s stored in the System suitcase of the boot disk. Its contents need to be dynamically generated based on the chosen screen resolution, so my normal approach of doing this at disk image building time (which is what I do for Stickies text) would not work. I instead leave a placeholder entry on disk, track its location, and overlay at runtime the values for the current screen parameters.
Snow brings some additional capabilities too, so all this work was not just to maintain the status quo. It has built-in support for the BlueSCSI Toolbox protocol, allowing file sharing with the host. This means that it’s possible to have a variant of The Outside World drive, though not as slick as Basilisk II’s virtual folder structure. It also emulates a SCSI-based printer, which I’ve hooked up to Infinite Mac too – you can now “print” to export graphics as downloadable PNGs. There’s also a long tail of Mac features you can now experience, such as booting from ROM with the Mac Classic. Finally, Snow aims to more accurately replicate the speed of the machine, though if you get impatient there is an “Uncapped” speed setting.
A/UX
A secondary reason for adopting Snow was that it seemed quite likely that it would be able to run A/UX, Apple’s alternate UNIX-based OS from the late 80s and early 90s. While Shoebill was also an option I had considered, I didn’t relish the idea of incorporating yet another frozen-in-time emulator4 just to run one OS. Sure enough, a few months after I’d started the port, Snow 1.5 was released, bringing A/UX support.

1988: The Year of UNIX on the desktop (and System 6)
A/UX mostly just worked – it was a matter of adding additional system images and categorizing them appropriately. Much like early releases of Mac system software and NeXTStep, it’s hard to find original installation media – 1.0 is still MIA and 1.1 was only recently archived5. The OS installations are most fresh-out-of-the-box, though I did end up making some tweaks to make the booting marginally friendlier.

It’s nice to be able to sign your work
This is my first time actually using A/UX, and it generates some cognitive dissonance. On one hand, it’s a classic Mac, with a Finder (at least starting with A/UX 2.0) and other familiar trappings. On the other, it’s a UNIX system, with a terminal and other things that engender “It’s a UNIX system! I know this!” feelings. But the UNIX is old (I kept typing vim instead of vi, and really missed tab completion) and feels quirky at times6.
The combination of the Mac GUI and UNIX does feel powerful, though the integration is much clunkier than what was ultimately achieved with Mac OS X, more than 10 years later7. The seams between the two (or even three, if you count X Windows-based UNIX GUI programs) worlds are pretty visible. There was an attempt at bridging the gap, via A/UX Toolbox programs, but it doesn’t appear to have been commonly used. For example, only the X Windows version of Mosaic was available, as opposed to a best-of-both-worlds A/UX Toolbox take on the Mac port. And in the other direction, A/UX did include a Commando mode that added a GUI to common command-line tools. However, it didn’t solve the fundamental issues of discovery in a CLI (you had to know the name of the command to invoke Commando for it).

Commando output for grep – curious what it would have been for git
While later versions of A/UX could directly mount HFS disks, it still required the use of UFS for booting, which made integration with Macs (and their resource forks and metadata) clunkier. The solution was the AppleSingle and AppleDouble formats, which is the one part of A/UX that lives on: AppleDouble is still used in .zip archives in modern macOS.
If you’d like to learn more about A/UX, this post on Virtually Fun and this one on The Long View are worth reading – they both describe the story and have some ruminations as to why it was a dead end. There’s also the A/UX FAQ and this software archive.
Learning Rust
As for my “learn Rust via the Snow bring-up” goal, I did not achieve it, at least not in a traditional way. I got the book, made my way through the first few chapters, and developed some familiarity with Rust concepts. But I couldn’t quite sustain the interest in learning all of the mechanics, especially with Snow being a relatively mature and complex codebase, and my needs being simple, mostly glue code.
This was around January, shortly after coding agents had hit an inflection point. I figured this would be a good test case: did I need to learn the syntax and other basics, or could I skip straight to the interesting parts? While the agent (Claude Code initially, Codex nowadays) knows Rust a lot better than I do, I still felt like I was adding value. Its first attempt to get things to build under Emscripten involved littering #[cfg] checks everywhere. I had to direct it to use stubs, and generally prioritize diff size and maintainability. Similarly, to actually get to the boot stage, I had to draw on past experiences about draining sound buffers.
For the most part, I’m fine with where things ended up – I still understand the generated code, even if I wasn’t the one entering it in. Developing more familiarity with the Rust ecosystem also allowed me to use it in other places: it now powers automatic decompression of disk images inside of StuffIt archives. I still have a lot to learn too, and it’s mostly on me to decide how much I want the agent to be in teaching vs. do-it-for-me mode.
I’ve also found agents to be helpful when debugging, much like the experiences of Linus Torvalds and Arbee8. With emulators there are many things to keep track of (host, emulated CPU, MMU, devices, guest OS/kernel, guest processes, etc.), and agents can churn overnight doing an instrument/run/get a breadcrumb/repeat loop. Getting to a smoking gun is not as satisfying as doing it by hand, but I don’t always have the time or energy for it.
Other Site Improvements
The agent-assisted debugging enabled me to make some more fixes to DingusPPC, and the Mac OS X Public Beta now boots correctly (you can admire the courage to have a non-functional Apple logo in the center of the menu bar). I also made some performance improvements (DMA is good for emulators too) and implemented CD-ROM insertion for that emulator, allowing the CD-ROM library to work for the more modern PowerPC machines that it emulates.
There were also a bunch of quality-of-life improvements: an on-screen keyboard to allow obscure keys to be entered, a cleaner way to open Infinite HD at startup (without littering aliases to it), support for client-side (CORS) fetching of external disk images, and even a fix for a longstanding SheepShaver issue.
As for what’s next, I’m debating between breadth and depth; we’ll see what sparks joy.
- Early Motorola 68K-powered Macs, though Snow keeps increasing its time horizon. ↩
- Third-party hard drives were also rare enough that I’ve seen no attempts at reverse engineering them. This thread is converging on enough information about the Tecmar Mac Drive that it may be feasible now. ↩
- Amusingly this then ended up in David Pogue’s Apple: The First 50 Years book. Hopefully the screenshots within it are not treated as gospel in a future The First 100 Years edition. ↩
- The author is alive and well, but there is a conflict of interest – the author works at Apple now. It is amusing to think that it is Apple conflicting with itself. ↩
- And it’s not much fun to install from scratch. ↩
-
Why does the manual encourage you to run
sync;sync;syncas part of system shutdown – would onesync(or two) not have been enough? ↩ - Or what NeXT had around the same time, another way in which it was ahead of its time. ↩
- A MAME maintainer working on Mac support – see also their AI tips. ↩

