Finding the Finder

Recently, somebody was asking on Emaculation forums, what would happen if Apple’s Finder would be attempted to run in M.A.C.E.? That was an interesting question, which motivated us to try it out.

Mac System Software architecture

To think about what would make Finder work, let’s consider the classic Mac system software as an architecture consisting of roughly three layers (in real Macs):

  • ROM: Most of Toolbox APIs, ROM resources and stage 0 boot loader.
  • System: Patches to ROM, extensions, system zone, the so-called “kernel” of old MacOS.
  • Finder: The “desktop metaphor” front-end running as a regular Mac application.

This categorization is very naïve, does not consider details such as role of hard drive drivers in boot process, etc. Additionally, M.A.C.E. combines roles of ROM and System as a single entity implemented in native code.

The interesting part to highlight is how Finder is basically “just another” application running on the System, and was even replaced by alternate startup applications on the old Macs (such as MiniFinder, MultiFinder, or other applications using the “Set Startup” option). As such, especially on System 6.x and older, the undocumented dependencies between System and Finder might be few in number, if any.

The first run

So, the question was, what would happen if we would try to run it? Well, we got this far on the first attempt, and with a couple minor fixes to progress further:

So, almost there. What we needed was a couple new (missing) routines and some fixes:

  • Fixed the 0x16 and 0x17 csCodes for .NativeFS driver, which return the logical/physical ICN# data for the volume icon (as seen on the desktop). We actually had that icon already one year ago, but this was the first time anything wanted to access it. 🙂
  • Added working directory indexing to GetWDInfo, which Finder uses to close all open working directories, presumably left open by misbehaving applications under System 6.x.
  • Fixed a buffer overflow bug in GetVolInfo (in volume name).
  • Implemented File locking APIs, which Finder wants to use to maintain the Desktop file.

Getting to the desktop

After a long and tedious session of debugging, it was discovered that due to a stupid bug in GetWDInfo Finder was crashing upon attempting to enumerate volumes. After that fix, we got nice Finder desktop, and a lot of functionality already working:

Operating on the Finder windows added need to implement a couple other missing traps, although as dummy versions for now (SetCatInfo and SetVolInfo, which Finder attempts to use to write metadata about modifications done in the spatial finder windows, icons, etc). Some points:

  • Finder and system icons appear as documents, but that might be because those don’t yet exist in the System file. Not sure about that yet.
  • It’s nice to see how a Finder 6.1.8 from Apple’s real System 6.0.7 behaves nicely even though M.A.C.E. System declares being version 7.0. 🙂
  • For some reason, doing “Get Info” on our Hard Drive turns our custom icon returned by the .NativeFS DRVR to a generic floppy icon.
  • It’s interesting how Finder considers at the moment our custom Hard Drive as “AppleTalk” device, but that might be because we’re hooking into the ExtFS file manager hooks which *I think* were used by AppleTalk in the real System 6.x. Just another thing which needs more investigation.
  • The modification and creation dates shown in “Get Info” (and list-style finder windows) use International Utilities date & time formatting functions, which are still placeholders. And as such, they only display mostly the numeric value of date-time instead of the proper, human-readable format.

Making the Desktop file work

At this point, we didn’t yet get the proper application and document icons to appear, so we did a bit more debugging on what was happening with the Desktop file – which Finder uses to keep track of known application creator & types, file comments, etc. It turned out, that we accidentally had all the “hasBundle” (0x2000) bits turned off in applications, which is why they were not detected by Finder.

As this issue was fixed, Finder started to process the applications properly, and quickly needed a some improvements to Resource Manager APIs. Mostly, it wanted to use UniqueID to allocate unique IDs for resources inside the Desktop file’s resource fork (to avoid conflicts). After that, updating Desktop file seems to work quite nicely, resulting in some fancy icons now appearing in the Finder under M.A.C.E.:

For now, running the real Finder remains as a curiosity, but nevertheless works as a great test case for a various number of Toolbox File Manager APIs which still need work (among some other minor bugs). The summary of the major known issues is:

  • The launching of programs “almost” works. Everything else appears to be fine, but it suffers from the same issue as previously found out using the “Transfer” command in THINK Pascal: The Font Manager data caches do not clear completely, leaving some dangling handles/pointers to the old application zone, which cause crash on attempting to reference them after the zone has been reinitialized for the new application.
  • Getting back to Finder (or any shell) is not yet possible, as ExitToShell is still hard-coded to terminate the entire emulator, instead of launching LMGetFinderName() application. Getting this to work would also encourage researching the Emscripten and Process Manager compatibility, as all of those features share a common need for a better in-emulator process management.
  • SetCatInfo/SetVolInfo are still dummy placeholders, so Finder is trying to use them to update metadata, though it is not yet saved.
  • Folder creation (_DirCreate), File/Folder deletion (_Delete), renaming (_Rename) are not yet implemented, so attempting those operations on Finder will still fail.
  • The _Eject trap is not yet implemented (and in any case you will not be able to eject the NativeFS drives).
  • As previously pointed out, Date & Time formatting does not yet work
  • The “Rebuild Desktop” operation (though using option + cmd keys at startup) does not yet seem to do the actual rebuild on a “fresh” start (i.e. if Desktop file has been wiped). Additionally, attempting that operation while old Desktop file exist will error out because _Delete is unimplemented, and old file cannot be removed out of the way.
  • Maybe other issues too, those are just the ones found out in the quick testing.

The “generic” M.A.C.E. environment might benefit of this though, as a replacement shell and/or program launcher, that could be optionally used by the end-user.

Full list of changes since last post

2019-12-12 18:19:41 +0200 • Add UniqueID/…1ID, to allow Desktop file updates
2019-12-12 17:49:18 +0200 • Add Disk Initialization Pack2 to keep Finder happy
2019-12-12 17:46:55 +0200 • Fix byteswap bug in NativeFS _Allocate handler
2019-12-12 15:00:12 +0200 • Add missing NativeFS.c changes for previous commit
2019-12-12 04:34:28 +0200 • Add dummy SetCatInfo and SetVolInfo selectors
2019-12-12 04:02:48 +0200 • Fix GetWDInfo bug (ioVRefNum & ioWDVRefNum mixed)
2019-12-09 02:58:47 +0200 • Fix memFullErr check in SetApplLimit
2019-12-08 06:31:06 +0200 • Fix filename overflow in GetVolInfo NativeFS call
2019-12-08 06:30:06 +0200 • Implemented CloseWD
2019-12-08 06:29:03 +0200 • Add WD indexing to GetWDInfo
2019-12-08 06:27:20 +0200 • Add Finder test app to cmake configs
2019-12-08 06:27:01 +0200 • Implement icon csCodes in NativeFS Control call
2019-12-08 06:25:52 +0200 • Make more macros in memory manager MSVC friendly
2019-12-08 06:25:18 +0200 • Add dummy SetFilLock and RstFilLock
2019-12-08 06:23:36 +0200 • Fix FinderName lowmem global
2019-12-06 23:44:06 +0200 • Add Bash Big Blue to cmake config for testing
2019-12-04 21:21:36 +0200 • Fix QD_LOG to respect debug settings
2019-12-04 20:48:17 +0200 • Add Cairo ShootOut! to cmake config for testing
2019-11-30 02:02:05 +0200 • Fix empty VA_ARGS problem in MaceLog macro
2019-11-29 23:55:30 +0000 • Make SWAP and MIN/MAX macros MSVC compatible
2019-11-29 23:54:08 +0000 • Made vararg ellipsis parameters MSVC compatible
2019-11-29 23:52:21 +0000 • Make Memory Manager return macros MSVC compatible
2019-11-29 23:51:27 +0000 • Make ROMScratch macros MSVC compatible
2019-11-29 23:50:08 +0000 • Move SwapPoint to MacQuickDraw.h to make it inline
2019-11-29 23:48:05 +0000 • Change void* to UInt8* in fake ROM (for MSVC)
2019-11-29 23:46:50 +0000 • Make SANE conversion macros MSVC compatible
2019-11-29 23:33:03 +0000 • Merge branch 'master' of
2019-11-29 23:32:43 +0000 • WinAPI EndianXX_Swap macros
2019-11-30 01:30:54 +0200 • Add UInt128 type to EmuMacTypes.h