System Enablers Research
I am investigating the approach that a number of newer Macintosh computers can be made to run on System 6.0.8L by porting the System Enabler launching code from System 7.1, thereby allowing you to drop-in an off-the-shelf enabler for your computer.
Here is my preliminary research on System Enablers so far. This is subject to change as I haven’t had the chance to step through the code, and Macsbug isn’t loaded until after most of this stuff happens.
1. In Apple Engineering, System Enablers were called “gibbly” or “gibblies” (hard g) because the words “extension” and “addition” were already in use. See “Be Our Guest” Develop issue 14. So, when searching code and resources, you need to use the engineer’s term to find anything.
2. Each System Enabler file is of file type ‘gbly’. Guess why? And, within each System Enabler is also a resource of type ‘gbly’ id -16385. The resource starts with a structure version number, then a date-time in Mac seconds format, followed by a count of supported machines, and followed by the BoxFlag id number of each machine that this System Enabler supports. The example below is from System Enabler 003 v1.1. It is structure version 1, internally built on April 12, 1994 at 4:51.26 ($A9D0820E), and supports 2 machines: LC III ($15=21) and LC III+ ($38=56)
View attachment 62187
3. The System itself has a ‘gbly’ resource. It describes which machines it natively supports without the need for an enabler.
4. When the computer boots, after the ROM starts, it loads the boot code from the drive’s boot blocks. The boot code finds the System file. This is how you are able to choose between multiple system folders on the same disk, because the boot block code and globals indicates where to look.
5. In System 6.0.8L (and likely earlier), the OS also stores this exact same boot-blocks code in the System file as resource ‘boot’ ID 1. It appears that the system installer and/or system folder blessing code copies the System file ‘boot’ ID 1 code to the boot block of the drive. Two important hacking notes: a) If you alter the System file ‘boot’1 resource code, something needs to be triggered to copy that to the boot blocks or the changes won’t take effect. B) The code must be 1024 bytes or less to fit in the boot blocks.
6. In System 6.0.8L, at the end of the boot block code, it runs ‘INIT’ 0 in the System File to continue the startup process. A long time ago, commercial developers created their own ‘INIT’ resources and shoved them into the System file to be part of the boot process. Apple didn’t like the System file being altered, so they created ‘INIT’ 31 to run external INIT files in the System folder, which later became called System Extensions.
7. In System 7.0, the boot code is different. Instead of calling ‘INIT’ 0, the boot-blocks code loads and runs the resource ‘boot’ id 2. This is very smart, as the boot block code can be kept small and simple enough just to locate and start the System file code. The code in ‘boot’ id 2 can now be long and specific to that OS. In System 7.0, ‘boot’ 2 does some of the stuff taken out of ‘boot’ 1, and then does System 7 stuff, and finally does the work of the old ‘INIT’ 31 by running all the external System Extensions.
8. In System 7.1, which is the first system with System Enablers, the boot code is improved again. ‘boot’ 1 remains simple enough just to call ‘boot’ 2, just like System 7.0. But, now, ‘boot’ 2 looks for and loads the System Enabler, which then calls the newly existing ‘boot’ 3. If the System Enabler exists and contains a ‘boot’ 3, then it takes over. Otherwise, the ‘boot’ 3 in the System file runs and does the normal stuff that the System 7.0 former ‘boot’ 2 code did with loading extensions, etc.
9. Put simply, System 7.1 has the most basic part of starting System 6 and System 7.0 in ‘boot’ 1 (which is then copied to the boot block). System 7.1 then has the System Enabler find/load code in ‘boot’ 2. Finally, System 7.1 has the run the rest of the system startup code in ‘boot’ 3 (which was at the end of ‘boot’ 1 in System 6 and used to be ‘boot’ 2 in System 7.0).
10. Let’s take a close look at the System Enabler code in System 7.1. This is ‘boot’ resource id 2...
a) Check the System file ‘gbly’ resource for a computer id match. If so, remember this and the date stamp. Because of the date stamp, a newer system enabler can override the system for machines which the system already supports. For example, you could make a System Enabler for an SE/30, which is already supported by System 7.1, and put SE/30 improvements in there.
b) Check the ROM for a ‘gbly’ resource. That’s right! Apple could build enablers to allow a newer computer to run on an older or existing OS (starting in 7.1) without shipping a System Enabler file.
c) Search every file in the root System directory. If it is a ‘gbly’ file type and
NOT INVISIBLE (good try virus writers), then it is opened to see if it has a computer id match. If so, remember this and the date stamp.
d) If any matches were found, clear bit 2 (systemEnableBit) of $B20 (ExtensionsEnabledByte). If no matches were found, set this to 1. Weird huh? 1 is ‘no match’. Aside: This byte holds startup global flags. For example, whether you held down the shift key at startup.
e) Go through all the matches and close each file that is older than the best time stamp so far. This leaves us with the newest System Enabler that matches this computer with its resource file open.
f) Load ‘boot’ 3 from this System Enabler. Show restart dialog if the resource isn’t found. This is a mistake in my opinion. If a System Enabler simply consists of a new DRVR or some string resources, why does boot code have to be included?
g) Move the System Enabler resource file handle under the System resource chain in memory. This eventually will be moved in front of the System file to allow overriding of System resources without altering them on disk.
h) Run ‘boot’ 3. This will either be from the System file, ROM, or a System Enabler, depending on who matched and had the most recent timestamp. Remember, ‘boot’ 3 does all the remaining normal boot stuff like load system code and run extensions. Unfortunately, this is a headache as now the System Enabler must reproduce all the standard startup code. Instead, I wish that ‘boot’ 3 was an optional step to make programmatic changes, then there could have been a ‘boot’ 4 in the System to set up normal OS stuff. Then ‘boot’ 5 in the enabler to make any changes. And finally, ‘boot’ 6 could be loading and extensions and launching the Finder. Instead, it’s all or nothing with ‘boot’ 3.
11. When ‘boot’ 3 is done, in System 7 it runs the Process Manager, which later launches MultiFinder (or whatever startup application) as one of the processes.
12.
Now for the cool part, the source to this code exists in the Apple code floating around in the files Boot1.a, Boot2.a, and Boot3.a. This will make it much easier to understand and port.
Based on this information, here is one possible approach to porting to System 6.0.8L
i. Snap off the second half of the System 6.08L ‘boot’ 1 code and put it into a new ‘boot’ 4.
ii. Copy the ‘boot’ 1 code and ‘boot’ 2 code from System 7.1 to System 6.0.8L.
iii. When it is finished, modify ‘boot’ 2 code to load ‘boot’ 4, not ‘boot’ 3.
iv. Append code to the beginning of ‘boot’ 4 to rearrange the System resource map order to present the System Enabler resources.
v. Insert code somewhere in ‘boot’ 4 to load and call a new ‘boot’ 5 in the System Enabler if it exists. And then, have ‘boot’ 4 finish up the standard System 6.0.8L startup sequence.
This would allow the off-the-shelf System Enabler to be selected by System 6 at startup. It would allow resources from that enabler to override existing System 6 resources, such as newer DRVR and strings. This might get some Macintosh models (like the LC III or Color Classic) working. Custom code for any tweaks could then be inserted into the System Enabler in our new ‘boot’ 5 code resource. This would allow different developers to independently hack code to get their favorite models working. Also, this keeps the memory/disk size of System 6 small, since you only need to add the single enabler of your choice.
I recognize that it is likely that later System Enablers rely on System 7 traps, bug fixes, and functionality. Also, it may be a pain to extract machine-specific code from generic ‘boot’ 3 startup code within a System Enabler. However, if we can get a couple of simpler machines working, a pattern may emerge.
- David