Infinite Mac:

[ comments ]

Date: Tuesday, March 28, 2023

tl;dr: Infinite Mac has a new home at Using a new Emscripten port of Mini vMac, it is now able to run almost every notable version of Mac OS, from 1984’s System 1.0 to 2000’s Mac OS 9.0.4. The project is also now accepting donations (via GitHub Sponsors or PayPal).

3 emulated Macs and a real one on a desk
Spot the odd one out.

Mini vMac

As I mentioned in my last post on the project, my immediate plans were to make even older versions of System Software runnable in the browser. Em Adespoton maintains a compatibility matrix spreadsheet showing which emulators can run specific OS versions, and it looked like my best bet was Mini vMac. There is an existing Emscripten port, but I decided to start from scratch for two reasons:

  1. It used Emscripten’s SDL compatibility layer, presumably to minimize the work to get something up and running. However, that’s both less efficient (as far as additional layers of abstraction to go through) and would not benefit from the JavaScript/browser API wrappers that I’d already developed for Basilisk II and SheepShaver.
  2. It first ran Mini vMac’s custom build system to generate the Makefile and other configuration data for Linux/SDL, and then modified the generated code to get things working. This seemed like a not very maintainable approach for the long run, since any re-runs of the generation system (e.g. to generate with different options) would require the modifications to be redone.

The first step in doing it myself was to get Mini vMac building. It’s an “interesting” project for a few reasons:

  • It doesn’t use version control (source code is available as tarballs for major versions).
  • Rather than a traditional autoconf + make setup, it has its own build system generator (also written in C).
  • Almost all options are specified at compile time (to minimize binary size and runtime cost presumably), so there's a lot of branching that relies on the C preprocessor.
  • It can be built by very old compilers for a broad range of platforms (even classic Mac OS, Carbon, Nintendo DS). Therefore it targets C89 and makes heavy use of macros and typedefs to make things work in such a broad range of environments.

This blog post has a rather negative take on the whole setup, but I have some empathy for Paul (Mini vMac’s author). This is clearly a passion project for him (dating back to 2001), and he’s set things up in a way that suits him. Incidentally, Paul himself has not been heard from for a couple of years, hence Mini vMac is in a bit of a limbo state. An import of the codebase and website to a GitHub org was done in 2022, in case Paul’s site does eventually go down.

With that context out of the way, getting it to build was actually not as painful as it sounds. While the build system is custom, it’s also arbitrary C code, so it’s very easy to hack on (vs. dealign with m4 for autoconf). Since it targets some very low-end platforms it’s also very fast to build, so the iteration speed was great. The initial bring-up involved adding an alternate Makefile generation mode that used the Emscripten toolchain and a glue file to get configuration data in and the framebuffer out. With that scaffolding in place, adding input, disk image mounting, color and sound was pretty straightforward.

Since the emulator allows the speed to be controlled, I exposed that as well. I knew that modern machines emulate classic Mac OS significantly faster than 68K-era Macs ran it (even when targeting WebAssembly and not being able to use JIT), but it was made truly apparent when running in 1x speed mode. I was a lot more patient back in the 90s, back when you had to be aware of how big the event queue was and make sure the computer could keep up.

The framebuffer updating in Mini vMac keeps track of dirty rectangles (another example of its focus on low-end host machines), and it was a nice bit of API “mechanical sympathy” to be able to hook that up to the dirty region option of CanvasRenderingContext2D.putImageData(). Though as it turns out that code path is perhaps not well-tested on some versions of Chrome — non-macOS users reported glitches and I had to add some opt-outs.

System 6

Once I had Mini vMac up and running in the browser, I booted a System 6.0.8 image. I only started using a Mac with System 7.1, so this was my first time spending any significant amount of time with this older version. I recall that System 7 had a reputation for being more RAM hungry and slower than its predecessor, but by modern standards they seem equally snappy and stingy with their memory use (with MultiFinder enabled System 6 uses the same amount of RAM as System 7).

What was more surprising was that things that I took from granted from System 7 (and assumed had been there for ages) were in fact recent additions. Two that I ran into very quickly were typing into Finder windows to select items with that prefix and being able to drag files onto application icons to open them. Around this same time Quinn had a thread about how earlier versions of the Mac UI were not as refined as people remembered them, which was a nice confirmation of my experience.

One of the other surprises that I ran into was that the Infinite HD disk (with its 1GB of Mac software) was taking a very long time to mount. I eventually figured out that its desktop file was being rebuilt (having a visible progress bar for this is another System7 refinement). It turned out that the Desktop DB/Desktop DF files that I was used to were another System 7 advance, while System 6 used a simpler (single) “Desktop” file, which causes problems when switching back and forth. The solution for my situation turned out to rebuild the desktop files twice, first under System 6 and then under Mac OS 8, so that both sets would be included in the generated image.

Once I had it all working, it was a matter of registering and configuring it.

System 6 showing the “About the Finder…” window
System 6.0.8 running on an emulated Mac Plus.


The mid-90s were a tough time.

With Mini vMac running, running older OSes was mostly a matter of figuring out which machines to build and tracking down install disks. MARCHintosh was coming up, and I figured it would be a worthwhile goal to get a gallery up and running in time for that.

But first, I needed a domain name. While,, etc. were all very catchy and memorable, was somehow less so (this was the first version to add support for HFS, and thus notable, even if it was a point release). I initially considered (to further extend my use of more obscure TLDs), but it’s a premium domain name costing $2,700/year, and thus not really within my budget. was a more affordable $84/year, but it was only one of the few macos. domains that was unclaimed, leading me to conclude that Apple’s legal department may have an interest in it (“Mac OS” is also technically an anachronistic way to refer to pre-System 7.5.1 releases). In the end the “obvious” won out, both for its affordability ($12/year) and because it matched the project name. The .app domains names will remain as shortcuts/redirects.

I used the word “gallery” above, and that was the experience I was going for. I wanted a curated experience, with pristine, period-accurate installations. I appreciate what the Internet Archive has done (and will often use it as a source) but at some point the amount of choice (400+ bootable images) becomes overwhelming. I wanted to have a place where you can experience first-hand what someone means by “spatial Finder”. Or if you come across some trivia about option-double clicking only getting its modern behavior (close windows behind you) in System 6.0.4, you can open it and its predecessor side-by-side to see for yourself.

A reference point I had was Stephen Hackett’s macOS screenshot gallery (or his more recent Rogue Amoeba one), or this one of early Mac systems. While they were certainly curated, even a great set of screenshots can’t capture what it’s like to use one of these systems (e.g. the feeling of zoom rects going across the screen).

My other inspiration was UTM’s gallery (which does provide one-click access, but requires native software and waiting for download and installation) and PCjs Machines (which run in the browser, but being about PCs is inherently inferior in the eyes of this 90s Mac fanboy).

For getting pristine versions of each OS, I tried to use “primary” sources as much as possible, i.e. directly from Apple. In some cases Apple still hosts the downloads (unclear why Mac OS 8.6 gets such treatment). In other cases, there were “archive” releases from the 90s that have multiple operating systems (e.g. the 1991 E.T.O. Essentials CD has System 7.0 and earlier, and the 1999 Legacy Recovery CD has some later releases).

The one release that was surprisingly hard to track down was System 0.97/1.0 that shipped with the original Macintosh 128K. I was not the first to run into this, and it appears to boil down to it being a short-lived release (1.1 came out a few months later), relatively few 128K Macs being sold, and the system disk also being the primary data storage mechanism for users. I tracked down all the disk images I could find, and put together a combined one that matched the original’s spirit.

The other thing that was surprisingly hard to find was a detailed changelog for each release. Perhaps there are comp.sys.mac.system posts from the era or Apple press releases, but my archeology skills do not extend to Usenet or wire services. I mostly used Macworld’s Mac Secrets (which being from 1996 is somewhat contemporary) and Mac 512’s System Showcase.

As previously mentioned HFS was introduced with System 2.1, thus earlier versions (that only support MFS) cannot mount the Infinite HD HFS image with the software library. I briefly considered making an MFS generator too, but the only MFS libraries I could find were either read-only or embedded inside sample code from 20 years ago, thus it seemed like a yak too far. I ended up hand-creating an image with some representative programs.

The final gallery includes every notable system software release (I'm sorry, fans of System 7.0.1). Perhaps over time I'll go back and backfill truly everything, but for now generating 36 bootable images was plenty. I tried to make the browsing experience as pleasant as possible — each release has a permalink, and you can command-click on the “Run” button to open things in new windows. Some releases only work with specific Macs, and some can run on multiple (I used the Apple ROMs spreadsheet and Mac ROMan to build up a library of machines) — which machine is used can be chosen via the “Customize” button.

Other Improvements

The focus on gathering together all of the OS releases meant that I didn’t have as much time to work on the emulation aspects. The one thing I spent some time on was improving the audio playback system. Audio is one of the areas that I know less about, and I had kept most of the structure from James Friend’s original Basilisk II port in place. However, as I was bringing up the audio subsystem for Mini vMac I remembered that audio worklets are now widely supported, and they also have an API “mechanical sympathy” with what the emulator expects. I’d also already set up a ring buffer system for the networking support, and in fact the library mentioned emulation as a use-case. The current implementation is a system that is quite a bit simpler, has lower latency, and I understand better, though there are still bugs. Between the audio worklet, the service worker, and the dedicated worker, I’ve managed to use most of the worker types — I now just need an excuse to use a paint worklet to catch them all.

One small tweak that I made was related to scaling. Nearest-neighbor is nice for preserving a crisp look and feel, but it’s not appropriate when trying to fill the screen in full-screen mode or when the host screen itself is doing non-integer scaling. I can see why emulators end up with configuration settings to allow for more historical visual accuracy, but for now I’ve managed to stay away from too many fiddly settings.

I made a few improvements to the experience on mobile/touch devices — there’s now a way to bring up the keyboard and import files (without drag and drop) and controls are visible even when the screen chrome is in its smallest mode. There are still fundamental limitations, these are all desktop UIs that were designed for very precise pointing devices, and they rely on actions like double-clicking that are hard to do precisely on mobile. PCjs appears to have taken a slightly different approach that may be worth considering: touches appear to drive a virtual trackpad that moves the cursor and allows more complex operation (like drag-and-drop) to be accomplished.

I also ran into a few cases where the emulator would not load, especially in-app web views. Those turned out to be caused by the service worker trying to do caching (but not being allowed to), but in general some basic error reporting seemed appropriate. Perhaps setting up Sentry or the like would be appropriate, though I would like to minimize the number of other services I depend on.

I had mentioned wanting to have a way to cover the infrastructure costs of the project ($332.48 so far), and I got around to setting up GitHub Sponsors and PayPal donation accounts. A few people have already donated, for which I am very grateful. I will try not to blow it all on domain names.

What’s Next

First, a break. I’ve been working almost every day on the project to hit my (self-imposed) MARCHintosh deadline of having all OS releases, and it’s gotten to be a bit of a grind.

Beyond that, there are a bunch of software requests that I could incorporate into the Infinite HD image. Though making it even easier to load software (even if I don’t include it directly) would be even better — I recently came across Discmaster and something that lets you load anything from the Internet Archive with one click would be great.

Improving the persistence support is another area I’d like to explore — the “Saved” folder in “The Outside World” is a bit too obscure, and because it uses the File System Manager some programs don’t work well with it. Ideally there should be a whole HFS volume that can be persisted. That would also integrate nicel with the browser’s file system APIs.

Finally, though I said I would take a break from adding additional operating system images, there are pre-release and obscure ones that might be fun to get running. Or perhaps even parallel universe alternatives.

[ comments ]