As one of the main goals is to actually run our favorite games in this emulator, we started now converting some of them into the AppleDouble format, and one of the was the legandary Dark Castle by Silicon Beach Software. It almost worked:
After fixing a bunch of bugs, and adding another bunch of new traps, it actually didn’t take long to get the title screen to appear. However, GetNextEvent was unimplemented at this point, so couldn’t yet proceed past it, and also the animation timing appears to still a bit off. It was nice though to see that the alternate video page switching code appears to work nicely, including also for the first time having 68K code running in VBL service thread! The video below shows this running:
Now that the test application is passing its runtime startup, it’s attempting to initialize various Toolbox managers, which of course gives us a good excuse to start work on the Menu and Window Managers, beginning from InitWindows.
The menu bar and desktop are some of the most iconic parts of the Mac user interface, and as these initialization routines set up these, we have something that is finally stating to look like a real Mac desktop. Another benefit of having file system at this point is that we can actually read the desktop pattern from ‘PAT ‘ resource ID 16 (using new GetPattern trap) from System file, like a real Mac does, and use that to paint the desktop.
Another interesting new feature was the support of virtual code resources read from the System file, using a customized mixed-mode loading mechanism which allows inserting UPP record for a native C code resource, such as in this case MBDF, into the MBDF resource read from the System file – which in this case was used to draw the menu bar!
Now with the first application, a lot of work has been going into fixing the CPU bugs, and implementing missing toolbox APIs one by one as required by the test application. In middle of this though, we added one feature which is quite important to a graphical system: Mouse support.
There’s not much to tell about this new feature, as technically the implementation is pretty trivial, with mouse hardware abstraction and new mouse low mem globals.
Hopefully we can soon use the mouse support for something cool.
Thanks to the earlier work done on Resource Manager for the “Fake” ROM resources, we already had rudimentary support for accessing resources. As the ROZ resource map was built to have exactly same format like “real” resource maps, the main missing features needed were reading and loading the resource map from resource fork using the recently added File Manager traps, and implementing further file reading operations in LoadResource trap.
And now with ability to load resources, the first thing to logically do is to start work on the Segment Loader. The Launch trap is used to:
Handle launch parameters
Init application one (unless doing a “Chain” launch)
Load jump table from CODE resource ID 0
Set up the A5 world and copy jump table to correct place
Set up 68K state
Jump to application entry point in 68K code
At this point, we can now for the first time start running an actual 68K Mac application, although there were, and still are, a bunch of 68K cpu bugs to fix. At least, now we can test the CPU emulator with actual, real program code!
After a short one-month break, and with Device Manager now working, we were finally able to start implementation of the virtual file system, dubbed NativeFS at this point. We use the virtual “.NativeFS” DRVR to mount the file system, which we for now install as ExtFS hook for File Manager. This way, we can make the file system appear as a foreign file system similar to AppleShare for Mac apps, increasing compatibility with apps which can handle those file systems correctly. Also, we can later add real MFS/HFS support to the actual File Manager level if we want.
We also abstracted the native file system layer in such a way, that we are not bound by a single storage solution, but have a native file system backend which we can change if needed, without needing to rebuild the entire NativeFS layer. After long and careful consideration, we decided to use AppleDouble as the first implementation, as it provided the best features for our requirements. Initially, we were thinking about using MacBinary (similar to AppleSingle), which would have made transferring files easier, but would have had much higher overhead in write operations, as having data and resource forks combined in a single file would have required moving the other fork back and forth when changing size of the fork preceding the other one in the file. On Mac OS X, we could have used the real HFS (recently APFS) metadata for catalog information and resource forks, but this way we have immediately support for running applications on other platforms. The file naming convention we used follows the UNIX convention documented by apple in the AppleSingle/AppleDouble Formats for Foreign Files Developer’s Note.
To make interfacing with File Manager easier in the long run, we decided to organize the files in memory as a tree structure, which has similar search properties as real HFS B-trees. This means, that we use CNID-Filename pair as catalog key, and include thread records to map CNIDs to file/folder records. Main difference compared to real HFS that instead of B-trees, which are optimized for on-disk storage, we use AVL-tree (which at the time of writing this is implemented just as a simple unbalanced binary tree)
The NativeFS to File Manager ExtFS bridge was inspired by Apple’s FSM (File System Manager) documentation, which detailed how to use FSM to implement path resolving and generally handling various File Manager calls, which actually matched quite closely to the ExtFS interface.
First file read
After a few weeks of hard coding, we finally got file reading to work, and did the first successful file read test, in which we fetched the data fork contents of a file on the virtual volume using newline mode.