Infinite Mac: An Instant-Booting Quadra in Your Browser #

tl;dr

I’ve extended James Friend’s in-browser Basilisk II port to create a full-featured classic 68K Mac in your browser. You can see it in action at system7.app or macos8.app. For a taste, see also this screencast:

Backstory

It’s a golden age of emulation. Between increasing CPU power, WebAssembly, and retrocomputing being so popular The New York Times is covering it, it’s never been easier to relive your 80s/90s/2000s nostalgia. Projects like v86 make it easy to run your chosen old operating system in the browser. My heritage being of the classic Mac line, I was curious what the easiest to use emulation option was in the modern era. I had earlier experimented with Basilisk II, which worked well enough, but it was rather annoying to set up, as far as gathering a ROM, a boot image, messing with configuration files, etc. As far as I could tell, that was still the state of the art, at least if you were targeting late era 68K Mac emulation.

Some research into browser-based alternatives uncovered a few options:

However, none of these setups replicated the true feel of using a computer in the 90s. They’re great for quickly launching a single program and playing around with it, but they don’t have any persistence, way of getting data in or out of it, or running multiple programs at once. macintosh.js comes closest to that — it packages James’s Basilisk II port with a large (~600MB) disk image and provides a way of sharing files with the host. However, it’s an Electron app, and it feels wrong to download a ~250MB binary and dedicate 1 CPU core to running something that was meant to be in a browser.

I wondered what it would take to extend the Basilisk II support to have a macintosh.js-like experience in the browser, and ideally go beyond it.

Streaming Storage and Startup Time

The first thing that I looked into was reducing the time spent downloading the disk image that the emulator uses. There was some low-hanging fruit, like actually compressing it (ideally with Brotli), and dropping some unused data from it. However, it seemed like this goal was fundamentally incompatible with the other goal of putting as much software as possible onto it — the more software there was, the bigger the required disk image.

At this point I switched my approach to downloading pieces of the disk image on demand, instead of all upfront. After some false starts, I settled on an approach where the disk image is broken up into fixed-size content-addressed 256K chunks. Filesystem requests from Emscripten are intercepted, and when they involve a chunk that has not been loaded yet, they are sent off to a service worker who will load the chunk over the network. Manually chunking (as opposed to HTTP range requests) allows each chunk to be Brotli-compressed (ranges technically support compression too, but it’s lacking in the real world). Using content addressing makes the large number of identical chunks from the empty portion of the disk map to the same URL. There is also basic prefetching support, so that sequential reads are less likely to be blocked on the network.

Along with some old fashioned web optimizations, this makes the emulator show the Mac’s boot screen in a second, and be fully booted in 3 seconds, even with a cold HTTP cache.

Building Disk Images, or Docker 1995-style

I wanted to have a sustainable and repeatable way of building a disk image with lots of Mac software installed. While I could just boot the native version of Basilisk II and manually copy things over, if I made any mistakes, or wanted to repeat the process with a different base OS, I would have to repeat everything, which would be tedious and error-prone. What I effectively wanted was a Dockerfile I could use to build a disk image out of a base OS and a set of programs. Though I didn’t go quite that far, I did end up something that is quite flexible:

  1. A bare OS image is parsed using machfs (which can read and write the HFS disk format)
  2. Software that’s been preserved by the Internet Archive as disk images can be copied into it, by reading those images with machfs and merging them in
  3. Software that’s available as Stuffit archives or similar is decompressed with the unar and lsar utilities from XADMaster and copied into the image (the Macintosh Garden is a good source for these archives).
  4. Software that’s only available as installers is installed by hand, and then the results of that are extracted into a zip file that can be also copied into the image.

(I later discovered Pimp My Plus, which uses a similar approach, including the use of the machfs library)

I wanted to have a full-fidelity approach to the disk image creation, so I had to extend both machfs and XADMaster to preserve and copy Finder metadata like icon positions and timestamps. There was definitely some cognitive dissonance in dealing with late 80s structures in Python 3 and TypeScript.

Interacting With The Outside World

Basilisk II supports mounting a directory from the “host” into the Mac (via the ExtFS module). In this case the host is the pseudo-POSIX file system that Emscripten creates, which has an API. It thus seemed possible to handle files being dragged into the emulator by reading them on the browser side and sending the contents over to the worker where the emulator runs, and creating them in a “Downloads” folder. That worked out well, especially once I switched a custom lazy file implementation and fixed encoding issues.

To get files out, the reverse process can be used, where files in a special “Uploads” folder are watched, and when new ones appear, the contents are sent to the browser (as a single zip file in the case of directories).

Persistence

While Emscripten has an IDBFS mode where changes to the filesystem are persisted via IndexedDB, it’s not a good fit for the emulator, since it relies on there being an event loop, which is not the case in the emulator worker. Instead I used an approach similar to uploading to send the contents of a third ExtFS “Saved” directory, which can then be persisted using IndexedDB on the browser side.

Performance

The emulator using 100% of the CPU seems like a fundamental limitation — it’s simulating another CPU, and there’s always another instruction for it to run. However, Basilisk II is working at a slightly higher-level, and it knows when the Mac is idle (and waiting for the user input), and allows the host to intercept this and yield execution. I made that work in the browser-based version by using Atomics to wait until either there was user input or a screen refresh was required, which dropped CPU utilization significantly. A previous blog post has more details, including the hoops required to get it working in Safari (which are thankfully not required with Safari 15.2).

The bulk of the remaining time was spent updating the screen, so I made some optimizations there to do less per-pixel manipulation, avoid some copies altogether, and not send the screen contents when they haven’t changed since the last frame.

The outcome of all this is that the emulator idles at ~13% of the CPU, which makes it much less disruptive to be left in the background.

Odds and Ends

There were a bunch more polish changes to improve the experience: making it responsive to bigger and smaller screens, handling touch events so that it’s usable on an iPad (though double-taps are still tricky), fixing the scaling to preserve crispness, handling other color modes, better keyboard mapping, and much more.

There is a ton more work to be done, but I figured MARCHintosh was as good a time at any to take a break and share this with the world. Enjoy!

Update: See also the discussion on Ars Technica and Hacker News (take 2). There is also a follow-up blog post with some post-launch details, and another describing the implementation of networking.

66 Comments

Awesome project. I look forward to trying it out. 🤓
Beautifully done! It's taken me back to my days on Photoshop 1.0 before layers even existed. Thank you.
unreal.. this is so good.. thank you
nice - now I wish I had kept my CodeWarrior disks, the stack of inside Macintosh books and developer CDs, MPW was a dog on my LCII, might actually be useful in the emulator... I much preferred CW to ThinkC. Would be easy to spend hours faffing around with this rather than getting some work done.
Any suggestions for opening a .dsk file in the emulator?
OMG! What an amazing project!

I copied over a BinHex install set of the last major System 7 MPW app I wrote. Unpacking it with Stuffit really brought back some memories! Sadly, it shows error -192 when I try to run it. The app includes some libraries compiled with DEC Fortran for MPW, so I'm not entirely surprised.

I still have sources for some Think C apps from 1987; gonna try to compile them next.

Thanks for this project!
Great work. File conversion just got much easier.

Is it possible to add old coding projects to your environment and launch them? I wrote some abstract art screen savers in the '90s - one was golden flying toaster-worthy. I wrote stand-alone players to customize and run them, not to mention a few other miscellaneous packages.

Can the emulator handle 8 bit CLUT animation and 24bit gamma table animation?

On a separate note, the old Macintosh had a great 2D graphics toolbox for bitmaps with features that still are hard to match today, including addover penmodes and copybits operations clipped with complex regions. Has anybody ever ported Quickdraw or, better yet, Quickdraw GX into an open source package accessible in a modern development environment? That would be sweet enough to send me into a digital diabetic coma.

(.leftbracket.)wriddick(.at.)usa(.dot.)net(.rightbracket.)
I was trying to run this in emulation but I wasn't able to open dmg files. Is there a way to do this yet?
Are you sure you've got the right ROM? I've tried both of your in-browser emulators & they are incredibly unstable in every browser I've tried (except Chrome, I won't use that).
Amazing Project! Can't seem to get sound from running this on an iPad.
Like sitting in front of my PowerBook 140 again — only with color!
Tried playing Marathon but limited to using keyboard controls because the mouse speed is insane. I chose the slowest mouse speed in OS7 but it was still too fast.
Also, I can't figure how to quit the game. ESC doesn't work nor does [modifier] Q.
(Do I have to get to a pattern buffer first? It's been so long I can't remember.)

If anyone has solutions to either of those issues please let me know. Otherwise, I'll have to fire up my (working) PowerMac 8500 or 9600 to play.
Tried running both Ssystem7 & System8 on a Samsung Chromebook Plus (using Chrome) & it gets stuck at the "loading files 4/4" stage...any suggestions ?

2 typos you may wish to fix from your Stickies:

a modern web browser
the mid-1990s was like
@Saru: If you go full-screen you should be able to use Command-Q to exit Marathon games (at least in Chrome, no other browser appears to support the keyboard lock API: https://caniuse.com/mdn-api_keyboard_lock)
** Tried playing Marathon but limited to using keyboard controls because the mouse speed is insane. I chose the slowest mouse speed in OS7 but it was still too fast.
Also, I can't figure how to quit the game. ESC doesn't work nor does [modifier] Q.
(Do I have to get to a pattern buffer first? It's been so long I can't remember.)

** @Saru: If you go full-screen you should be able to use Command-Q to exit Marathon games (at least in Chrome, no other browser appears to support the keyboard lock API: https://caniuse.com/mdn-api_keyboard_lock)

Being full screen (clicking the Apple logo on the monitor bezel) and Command-Q worked! (At least in Chrome.) Thanks.

This is really quite an impressive feat. I'm guessing the Japanese Language Kit and a lot of my old Japanese software probably won't run. Still, it will be fun to try.
Awesome project, congratulations!

I'd be very happy to see my old classic game 3Tris / 3Wiz in the games collection, feel free to add it if you wish. Here is the original '90s link to the dowloadable hqx file:

http://esurfers.com/francesco/gadgets/download/wizcol.hqx

(Color version)
i think the desktop file needs rebuilding on macos8.app, imported .sit files and the sample movies wont play by double-click
@Anonymous: That’s a known issue (https://github.com/mihaip/infinite-mac/issues/4). In the meantime you can rebuild the desktop manually by holding down command and option during the startup sequence (you can restart the Mac from the Special menu too).
The obvious game to try with this is the awesome Royal Flush pinball emulator.
https://gp.home.xs4all.nl/Royal%20Flush/DownloadRF.html
But it doesn't work :(
I lied. It works great!!! So cool.
May I suggest including Royal Flush in the games folder. I can't image that Gerard would object.
Never mind...Royal Flush works, but it's unacceptably slow. Note that it works fine on Basilisk. I'm on an M1 Macbook Pro. Pinball games aside, this is still an amazing piece of work! (sorry I've been so chatty - I'll stop now).
Wow.... Good job!!!
Very much loving this project.
2 suggested updates:
a) add support for 1024x768, as when I was supporting graphic designers in the 1980's and 1990's, everyone wanted as big a screen as they could afford/
b) please replace Strategic Conquest Plus 2.x with Strategic Conquest 3.x (available in online repositories). It's an improved version of the game with better AI.
Wow. Thanks for memories
launching hypercard again literally made me cry
/_/
@jsepeta: Filed https://github.com/mihaip/infinite-mac/issues/46 about allowing the resolution to be changed. Added Strategic Conquest 3.0 with https://github.com/mihaip/infinite-mac/commit/b648ad0acb1b9cea33cd8239fdb61560147905fe, it should be live with the next deploy (in a couple of days most likely).
@Francesco: Finally got around to adding 3Wiz: https://github.com/mihaip/infinite-mac/commit/865432175bd02d97023570e9e53e1ce4f07d53db
Thank you Mihai Parparita
Hi - This is an amazing piece of work! Is there a way to save projects and updates through a restart? I would love to be able to play my old favorite game, Scarab Of Ra, and access some of the DocMaker articles I wrote when I was a columnist for “About This Particular Macintosh.” I tried a few preference settings changes to see what happened, but after closing and restarting they were gone. Thanks!
@Anonymous: The contents of the "Saved" folder in "The Outside World" drive should be saved (it works for me in Chrome on a desktop Mac, though I have not tested it everywhere).
Thanks for the reply. The Saved folder does work for me. I was wondering about putting apps in the Applications Folder, but maybe I should just leave them in the saved folder? And also any docs I create? I think I can live with that. Should the Saved Folder survive a host computer restart? Thanks again. Your efforts are remarkable! Ed
If I can install the games Burning Monkey Puzzle Lab, Tetris, and Factory in this my wife will be ecstatic.
just saw the system7.app site on a youtube review, he ran it on a chromebook, just tried it on mine and it hangs on the loading screen (loading 4/4), my chromebook is an HP Chromebook x2 11 (Snapdragon 7c based) if that matters
First of all, thank you so much for this project, it bring back so many memories, but I am wondering, is there a way I can mount cue + bin file? becasue this game I try to play from my childhood call Nobunaga's Ambition , need to mount the audio CD to run the game, so I try every way like rip out the audio file, using bchunk to make it a ISO file, even try to run it on DOSBox so I can Mount cue file, every way just don't work, so I am wondering if there is a way to make it work so I can bring back my childhood memories? thanks a lot!
So this was working really well the first time, but I've hit a wall on coming back -- don't know if I'm doing something wrong. I saved my program (I own a copy of Strategic Conquest 4.0.1, which is awesome) and the game I'd been playing as .zip files as well as in the "Saved" folder. Came back, they weren't in "Saved." OK, you warned me about that -- but I can't seem to get them back on. When I copy them to "Downloads" they appear, but despite StuffIt it working on them, nothing seems to get produced that the computer recognized. Not necessarily a problem as I can still re-load the .sit file for the program that StuffIt can then unpack/install. But no matter what I do, the download process will not produce a version of the game file that StratCon can recognize and re-open. I'm wondering if I'm missing a step in re-loading the .zip files?

On the topic, as I said I own a copy of 4.0.1 from the Before Time. Is it not available as part of the games on Infinite Mac because you don't have a copy, or are there ownership issues with loading anything beyond 3.0? If it's just a matter of getting hold of the game, I'd be happy to share the .sit file. Thanks, this is a very interesting project!
i wanna see a catalina version
How legal is it? Did Apple permit this?
@Anonymous: 🤷‍♂️
Mihai - just want to say this project is awesome! As a big 68k Mac nerd in the 1990's, Infinite Mac is a nostalgic joy. Have you thought about offering a paid version where subscribers could maintain their "own" instance where settings save, basically like their own Mac? I don't know if this is technically possible, I would totally pay (or contribute) for such an option.
This is incredible! Thanks for your hard work.

I'm noticing that I can't toggle volume slider away from 0 on either macos8.app or macos9.app. Seems consistent across browsers and devices (tried on my 2020 intel MBP using Chrome, Firefox and Safari and my 2021 ipad pro on Chrome). Is this related to https://github.com/mihaip/infinite-mac/issues/67?
@Anonymous, @greatwyattshark: Yes, sound not working in later versions of Mac OS is a known issue (https://github.com/mihaip/infinite-mac/issues/67), I have not been able to make much progress there.

@John T: I appreciate the interest in a more premium offering, but it's not something that I will be able to offer. If you're looking for persistence and more control, running Basilisk II or SheepShaver locally is going to be your best option.
Chaque fois que j'entre une phrase bien écrite dans cette conversation tu apprends à être un être meilleur.
This is great fun, amazing work. Thanks! :-D
Hi. I want to use InfiniteMac on my iPhone SE (2020), but the canvas size is too large that I can’t access the whole Mac screen. Developers, would you like to make InfiniteMac more smartphones-friendly?
Also, smartphones don’t support drag&drop of files so please make it possible like this: https://hcsimulator.com/
(“Import” floppy icon)
@businessduck: I've filed https://github.com/mihaip/infinite-mac/issues/79 for the file importing.

As for making the screen more phone-friendly, I'm not sure there's much that can be done -- the OS was designed for large screens, and is not responsive.
First of all, thank you for filing the I/O issues on GitHub. Now, all I want is smaller JavaScript canvas (and css maybe?) and I want to tinker with kanjitalk7.app using my Bluetooth keyboard and Bluetooth mouse. Just shrunk version. Pleeease!
Hello! I was wondering how I would be able to use the speech application. When I try running it or playing the samples it just says "This voice isn't working. You may be out of memory or you may need to reinstall the text-to-speech software."
First time request!
Can you make Mac os 9.1 and 9.2?
As soon as possible please!
Really awesome. Thank you for doing this and letting me re-live some 90's nostalgia. Any chance you could make one for Mac OS X Server 1.2 (Rhapsody)?
@Anonymous: It's limited to the versions of MacOS that Basilisk II and SheepShaver supports, and that currently goes up to 9.0.4.

As for sound/speech synthesis, you'll have better luck in System 7 (https://system7.app). Sound is still not working in Mac OS 8 or Mac OS 9: https://github.com/mihaip/infinite-mac/issues/67
How i do thank you my friend. It brought joy and tears to my eyes to play my old college friend "Swoop" once again. I owe you one.
its such a great project ! thanks i brought back my memories from my first job...
I encountered the same thing on my chromebook on the android version of firefox. It works fine in the main google browser.
Лев
Bit new to this, if I load it in a browser tab, and then close the tab, then open it in a fresh tab but the same browser window, does it retain any of what was done before or start a fresh session? Does it pull any data from my PC at all
It just gets to "Loading data files (4/4)" and gets stuck there. What is going on?
Hey just checking if anyone has an answer to this? Will the emulator pull data that is not drag and dropped into it?
@Anonymous: the emulator will persist files in the "Saved" folder in "The Outside World" drive.
Stunning piece of work. Ive been using SheepShaver off and on for years to mess about with a boat load of hypercard stacks I made in the Stone Age. Having spent years building stacks for my own entertainment I was hacked off when Jobs fucked over hypercard users by not even Carbonising it and then letting it die (more like stabbing it to death) So hats off, this is just so much fun. Sitting her at my MacBook Air I'm reliving the glory days of early Mac. Macstalgia is a thing Thanks for this.
Nice post thank you Kathy
Fabulous work! Thank you so much. Unfortunately, if you copy stuff to the Saved folder and shut down your browser, the folder appears empty when you open your browser again and access to the system version you saved stuff to. Any chance to have a remanent configuration in the future?
@Anonymous: glad you like the project. Can you file a GitHub issue with the problem you're having any other relevant details (e.g. what browser/OS you're using) at https://github.com/mihaip/infinite-mac/issues/new?

Post a Comment