Advanced Mac Substitute Legacy Documentation
Advanced Mac Substitute runs in the xv68k emulation rig.
Example
xv68k --screen=$screen_file -m ams-core -m ams-rsrc -m ams-qd -m ams-ui $program
The screen is 21888 bytes of raw 512x342 bitmap data (with 0 coding for white and 1 for black). The file will be created if it doesn’t exist.
Mac OS support is split into several modules:
ams-coreconsists of anything OS-related, as well as the Event Manager.ams-rsrcimplements the Resource Manager.ams-segimplements the Segment Loader.ams-packimplements the Package Manager.ams-qdprovides QuickDraw and the Font Manager.ams-uiincludes the Window Manager, Control Manager, and Menu Manager.
In addition, the program app is needed to launch the first application.
The lowest-level module is ams-core; all others depend on it.
The GetResource() function (in ams-rsrc) is required
- by
ams-seg, in order to load'CODE'resources, - by
ams-pack, to load'PACK'resources, - by
ams-qd, to load fonts (if any text is rendered), - by
ams-ui, to load the desktop pattern inInitWindows().
Obviously, ams-ui depends on QuickDraw.
GetResource() attempts to communicate with a Freemount server on file descriptors 6 and 7, as would be the case if you ran tcpclient $host $port xv68k .... A resource like 'PAT ' id=16 (the desktop pattern) is mapped to the path "System/r/0010.PAT " and requested from the server. You can either run freemountd in MacRelix with an actual resource file called "System" at top level, and let MacRelix interpret the "r" path component as resource access, or create a "System/r" directory structure with the resources as actual files.
If CurApName is non-empty, it’s the name of the currently running application. GetResource() now checks for resources in the application file first, and if not found, then checks in "System".
If ams-rsrc is unable to reach a file server, or the request fails, then GetResource() sets ResErr to resNotFound (or possibly memFullErr) and returns NULL, and InitWindows() will use qd.gray instead of 'PAT ' id=16 from the System file.
GetNextEvent() and WaitNextEvent() receive user input events from outside via the SPIEL (Simple, Platform-Inclusive Event Lode) protocol. MacRelix’s eventtap view provides this.
Launching Mac applications
Launching a Mac application in xv68k is a complex process because it has a number of moving parts. First, we’ll use FORGE to open a window:
cd /gui/new/port
echo 512x342 > size
ln new/stack view
ln new/eventtap v/events/view
ln new/bitmap v/screen/view
echo 512x342 > v/screen/v/size
touch window
That creates a window whose interior size matches the original Macintosh screen resolution. It contains an eventtap view Z-stacked onto a bitmap view. The eventtap view captures user input events for transport into the emulator (but doesn’t draw anything); the bitmap view displays graphics output.
We also need a way to get the CODE resources from the application file. We’ll use the graft utility to launch a Freemount server, with xv68k as its client, connected by a socket pair:
CTTY=--ctty=tty
SCREEN=--screen=v/screen/v/bits
EVENTS=--events-fd=8
STREAM=v/events/v/stream
APP=$tools/app
App=TestApp
daemonize --cwd $CTTY -- \
graft freemountd --root $dir // \
xv68k --screen=$SCREEN 8< $STREAM -m [ ams-core $EVENTS ] -mams-{rsrc,qd,ui} $APP TestApp
Let’s tackle this in order:
daemonizeis a program that launches other programs as daemons. Normallydaemonizewill change to the root directory, but the--cwdoption inhibits this. The--cttyoption specifies a file to open as the new controlling terminal. In FORGE, every window is a terminal, and itsttyfile is the device file for its terminal (even though it’s not necessarily a TTY device in the sense of teletypes). If we omitted this, the daemonized program would still run, but wouldn’t receiveSIGHUPwhen the window’s close box is clicked. The--word has its usual meaning, separating options from non-option arguments. The\just before the line break allows the entire command to be continued on the next line.graftis a utility that creates a socket pair and launches two other programs. The first program is the server, and its file descriptors 0 and 1 are redirected to one of the sockets. The second program is the client, and its file descriptors 6 and 7 are redirected to the other socket.freemountdis a Freemount file server. The//terminates the command thatgraftruns as the server; the client command follows. The\continues onto the next line again.xv68kis an emulation rig — that is, an executable client of the v68k library. The--screenoption names a file that will be used as a framebuffer. By using the FORGE bitmap view’sbitsfile, writes (and msyncs) to this file are displayed in the window. The eventtap view captures user input events and makes them available (as SPIEL data) by reading itsstreamfile. We open that for reading on file descriptor 8. (No, that’s not scissors.) The-moption loads a module. We can pass arguments to the module by enclosing the subinvocation in square brackets.The
ams-coremodule provides a partial reimplementation of classic Mac OS. The--events-fdoption indicates the file descriptor from which to read SPIEL messages to convert toEventRecords.The
ams-rsrcmodule provides a partial reimplementation of the classic Mac OS Resource Manager. It’s split out into its own module to isolate its dependency on the Freemount client library.The
ams-qdmodule provides a partial reimplementation of classic Mac OS QuickDraw. It’s split out into its own module to support the development of natively accelerated implementations.The
ams-uimodule provides a partial reimplementation of the classic Mac OS Window Manager. It’s split out into its own module to support the development of alternative implementations.The
apptool is a simple program that invokes the_Launchtrap. Its argument is the name of a Mac application in the directory served by Freemount. It’s the bridge between MacRelix’s virtual Unix world andams-core's even more virtual Mac OS world.TestApp is a Mac application that’s been carefully written to use only those Mac OS features that are supported by Advanced Mac Substitute. It also runs natively.

