System File
Volume Number: | | 3
|
Issue Number: | | 8
|
Column Tag: | | Resource Roundup
|
Sleuthing the New System File
By Joel West, Contributing Editor
This month, Im going to talk about the new traps available in System 4.1 under the Macintosh Plus -- and, to a lesser extent, the 512, SE and Macintosh II. (When I sat down to write this article, I wanted to call it Trapping System Compatibility, or Seeking the Compatibility Trap, but finally decide to give up on the puns.)
This all started when I was working on my book, Programming with Macintosh Programmers Workshop (due to be published by Bantam this month.) I wanted to include an up-to-date list of traps; in particular, I wanted to pull together all the traps and indicate exactly when it was safe to use them. (If you have the book already, Im referring to Appendix E.)
At the time I was writing the appendix, all I had was the APDA draft for Inside Macintosh, Volume V, which described new features developed for the Macintosh II. After the draft was published, many of the features described for Mac II were retrofitted for the Plus. For the Macintosh SE, some of the new stuff made it before the SE ROM was frozen (several months before the II), while other stuff also had to be retrofitted.
I have a fastidious pre-occupation for detail, and sometimes I get carried away. In this case, what started out as a simple exercise ended up being a rather elaborate endeavor. I probably spent 10-15 working days over three months trying to get the exact answer to exactly which trap is available when. I ended up testing five different System files on the Mac 512, Mac Plus, Prodigy 4, Macintosh SE and Macintosh II. I didnt test all possible combinations, but all the valid ones for the Mac Plus, SE and II, and all but one (System 3.3, very similar to System 4.0) for the Macintosh 512.
My work was assisted by the generous help of Silicon Beach Software, who supplied an SE and a prototype Mac II. Neil Rhodes also lent his production Mac II, while my former employer coughed up the prehistoric 512. Ive ignored the Macintosh XL, aka Lisa 2, since most developers traded theirs in when the opportunity presented itself and it never sold that well, anyway.
Educated Guessing
First let me note (standard disclaimer follows) that I am not privy to any confidential Apple information regarding the ROM or trap patches. If I were, I probably couldnt share my thoughts on the subject.
However, I like to consider myself clever and resourceful, and I felt that a studied application of documented techniques would produce valuable results. Those of you who are regular readers of MacTutor will recognize this as sleuthing.
In this case, I know the availability of each by trap word ($A000-AFFF) with certainty, both the traps that have names, and those that do not. However, some of the OS traps share the same trap number and use high-order bits to distinguish between the traps, but my analysis of the trap dispatch table cant distinguish this. Also, for the dispatched traps, I cant tell which new traps are added that share the same dispatch word.
There are also some problems with occasional ROM traps looking like RAM traps, since some other interloper (like a development system or application) may have patched a perfectly good ROM trap. From a compatibility standpoint, its not as important to know which ROM-based traps are patched, so although there might be a glitch or two here, its not worth losing sleep over.
After pouring over all the information and asking a few sources for help, I know the trap names with a strong degree of certainty. Ive left off a few traps for which I have discerned names because Apple has not told anyone (including me) how to call them, nor guaranteed that they will work in the future. There are quite a few traps that are defined but not named at all (at least, outside Apple), but presumably those are called from within the ROM only and subject to change at any time.
Finally, when we get down to why a particular trap was added or modified, all I can do is make an educated guess. But since Ive spent so much time studying trap compatibility, I thought people might be interested in the results of my education.
The Format of a Trap
A trap is an unimplemented Motorola 68000 instruction that generates a standard 68000 exception vector interrupt, which is used by the Macintosh to transfer control to the appropriate code.
The 68000 uses instructions that are a multiple of 16 bits, with many instructions contained in a single 16-bit word. In the case of Macintosh traps, the instructions are 16-bit words (trap words) in which the first hex digit is A, so these are sometimes referred to as A-line traps. All 4096 A-line traps are considered illegal instructions.
(I heard a story that Motorola wanted to use A-line traps someday for a future processor, but with Apple machines now holding the majority of the chips out there, that possibility is gone. However, Motorola has reserved the 4096 F-line traps for coprocessor calls, such as for the MC68881 and MC68851 of the Macintosh II.)
When it sees an illegal instruction in the range $A000 to $AFFF, the MC68000 (or MC68020) transfers control to the exception handling routine pointed to by location $028. For a Macintosh, this transfers control to the trap dispatcher.
As shown by Figure 1, the range of possible traps is split into two groups, with $A000 to $A7FF allocated to OS traps, and $A800 to $AFFF for Toolbox traps. The lowest bits of the trap word are the trap number.
All traps from $A000-$A7FF are OS traps that accept any parameters in low-numbered registers, such as A0 and D0, returning any results similarly in registers.
Most of the traps from $A800 on are Toolbox traps, which have parameters passed on the stack along the lines of the standard Lisa (now MPW) Pascal calling sequence. There are also a number of stack-based traps for OS managers above $A800, and a handful of register-based OS traps as well, but for our purposes, these are numbered and treated as Toolbox traps.
The basic OS traps are numbered $A000 to $A0FF, with the upper 3 bits are used for other indicator flags. The figure summarizes what these flags are used for, and their hex mask equivalents are:
$100 trap returns a value in A0
$200 HFS traps
$400 asynchronous I/O call; or
allocate in system heap
The $200 and $400 bits are also used by some other traps, including _GetTrapAddress.
There can be two (usually related) OS traps with the same OS trap number, differing only in their indicator bits. For example, _PostEvent is $A02F and _PPostEvent is $A12F. More significantly, _Open is $A000, while its HFS counterpart is _HOpen at $A200, and their are many similar HFS pairs.
Trap Tables
The trap dispatcher transfers control to the correct routine using a trap table, which contains the address (possibly encoded) of the corresponding routine. The trap table is always in RAM, because it is possible for a program to modify the entry for any trap, as well see.
The trap table on the original Macintosh was compressed, with only 16 bits for the trap address. Using the 68000 restriction that instructions begin on even addresses, this allowed 64K of ROM addressability, plus patches in the first 64K of low memory, presumably in the System Heap.
The Macintosh 512, of course, is just a Macintosh (128) with more RAM; same connectors, maybe (as noted in earlier MacTutor articles) a better power supply -- but the same ROM, traps and trap table. Ill talk about the 512 from now on, since presumably everyone has at least 512K.
The 64K ROM also cheated by overlapping the OS and Toolbox trap tables into a single table. As shown in Table 1, this limits a Mac 512 to 512 of both kinds of traps. More significantly, certain trap words are not available on the Macintosh 512 -- since that spot in the trap table is taken for the opposite (Toolbox or OS) purpose.
Generally, the first 80 slots (A000 to A04F) in the 64K ROM are allocated to OS traps, and the last 432 slots (A850 to A9FF) are allocated for the Toolbox. But a few stragglers from the OS take slots allowed for the Toolbox, although the ROM doesnt seem to care which type of trap is in the slot .
The Plus and SE split the two trap tables. A full 256 OS traps are defined, and 512 Toolbox traps -- $A800 to $A9FF -- are allowed for the Plus and SE. When you get to the Macintosh II, the maximum 1024 Toolbox traps are provided, with the extended traps -- $AA00 to $ABFF -- used for Color QuickDraw.
Inherent Limits
Some people have told me that they have a certain machine and wish they could have a certain new capability, typically offered with the next machine up.
For example, many folks want Color QuickDraw on their SE or Plus. While I cant say it wont happen, it would require some changes to the trap dispatcher, because the necessary traps are not possible using the built-in SE or Plus trap tables. (Theres also the question of how to get the code itself, but if there are BIOS clones in the IBM world, certainly the Mac world will inspire color clone conversions of the SE if theres enough demand.)
More significantly, many people will find that there are certain things they cannot do and never will do with their old-ROM machine. The gap between the 64K ROM and the rest of the world is now huge and largely unbridgable; if youre not aware of the differences, then read on.
First, bridging this gap would require throwing out the trap dispatch mechanism on the 512 to allow for more traps, with separate OS & Toolbox traps. However, 512K is at the low end nowadays for dynamic memory in the Macintosh world, and thats the largest configuration Apple ever offered in the 64K ROM world. Apple could have gone to a lot of trouble to try to improve marginally adequate machines (or third-party upgraded machines), but they didnt, perhaps wisely so. The clincher is that these old-ROM machines now form 20% (my estimate) of the installed base, and that number is getting smaller every day.
The Good Ol Days
Once upon a time, things were much simpler. There were only traps and glue. There was one list of available traps. Occasionally, the glue got more elaborate in a new release of Lisa Pascal, but this was strictly a compile-time decision. When your program ran, you knew it would face only one set of traps.
Along came the 128K ROM of the Macintosh Plus, and the world was never the same again. The 128K ROM had a whole list of new traps not available on the 64K ROM. All of a sudden, the Macintosh software architecture was not a fixed target, but an evolving one.
(Its smaller sibling, the Mac 512K enhanced, has the exact same ROM as the Plus, with less memory and different peripheral interfaces, but these differences are uninteresting for our purposes and the 512Ke will be treated as a Plus for the remainder of this article.)
To make matters worse, a certain subset of the 128K ROM traps -- those involving the File Manager -- were also available on 64K ROM machines using trap patches. All you have to do is place the file Hard Disk 20 on your boot disk and youre all set, with full access to the Hierarchical File System of the 128K ROM.
The traps patched by Hard Disk 20 to 64K ROM machines are shown in Table 2. A total of 13 traps are analogous to existing traps, most of which add an H to their corresponding 64K trap, such as _HOpen vs. _Open.
As their Pascal names suggests, the higher-level PBH routines are HFS-oriented ParamBlockRec calls. In addition, the _HFSDispatch trap provides 11 separate routines, not shown.
However, even with this range of options, things were easy by comparison to today. At least there were only three configurations:
Mac 512 (or a 128 for masochists)
Mac 512 + HFS (using Hard Disk 20)
Mac Plus (including Mac 512Ke)
Come 1987, with new machines and System files, the configuration possibilities became much, much more complex, as well see in a minute.
Dispatched Traps
In some cases, several routines share the same trap word. A trap selector is a value that distinguishes between calls to the different routines; a trap word that requires a selector is called a dispatched trap.
In the original ROM, the only dispatched traps were the packages, which were disk-based resources of type PACK, loaded into RAM (like any other resource) in an as-needed basis. Six of the eight possible packages were defined, and their dedicated traps were:
_Pack2 Disk Initialization
_Pack3 Standard File
_Pack4 SANE floating-point
_Pack5 SANE trancendentals
_Pack6 International Utilities
_Pack7 Binary/Decimal Conversion
The Hierarchical File System added _HFSDispatch as a non-package dispatched trap. System 3.0 added a new package (_Pack0) for the List Manager, while the 128K ROM included _SCSIDispatch.
Now there are six more. TextEdit, Script Manager, Shutdown Manager and Printing Manager have four, available on all systems. Specific to the Mac II is the Slot Manager, while Color Picker Package is primarily designed for the Mac II, but available on any 128K ROM machine. For five of the managers listed (all but TextEdit), the dispatched trap is used to support all routines of the manager.
Most of the dispatched traps take stack-based parameters, and these use a selector on the stack. Packages use 32-bit selectors, while others may use either 16- or 32-bit selectors.
The two register-based dispatched traps, _HFSDispatch and _SlotManager, use a 16-bit selector in register D0, and usually a parameter record pointer in A0.
System Versions
The Macintosh system software has changed tremendously since 1984. Table 3 gives a chronology of the System and Finder versions publicly released as of this writing. Ive omitted beta versions and others that Apple never encouraged people to use, such as System 3.1 or 3.11. I couldnt find the 1.0 disk that came with my original Macintosh in February 1984, but since no one should be using that version today, I figured it wasnt important enough to go digging through storage to find its exact date.
Until System 4.1, the System and Finder had textual version dates in the resource fork, in the STR and FNDR resources, respectively. These generally coincide with the modification date for the file, but where there was a conflict, I took the modification date (which seemed to correspond to a release date). Why the new System and Finder dont have dates is beyond me, but I hope they put them back in. Without them, it is hard to write utilities that indicate which version each system is running; an important consideration for network management.
One interesting curiosity is the similarity of System 3.3 and System 4.0. They are only three days apart and share the same finder, and, as noted later, are very similar in the traps they implement. System 4.0 was obviously designed for the Macintosh SE.
Im sure most of you have seen Apples smiley-face compatibility table for System/Finder versions and different Macintosh models, either in the developer mailing or in the APDA newsletter. But for further reference later on, the recommendations are summarized in Table 4.
RAM patches
Trap patches have always been with us. But somewhere around System 3.0 (Finder 5.1) Apple developed a formal scheme for implementing trap patches using PTCH resources in the System file. Since this is Resource Roundup, no column would be complete without at least a prefunctonary discussion of an interesting resource.
One or more PTCH resources are loaded at startup time. They contain routines that will be available to all applications until the machine is powered off, and these routines are loaded into the system heap. The address of the patch replaces the ROM address that was previously stored in the trap dispatch table.
Patches were originally intended to fix bugs in the ROM. Not suprisingly, no piece of software is done until after its tested, and some complex software only gets properly tested by end-users. Its an unfortunate reality of this business that the most embarassing crashes only show up after youve shipped out 100,000 disks.
Since the original system software releases, however, trap patches have taken on new importance. They now have three uses:
Fix a bug;
Extend existing capabilities; or
Add a new trap
Between System 2.0 and 3.2, no new traps are defined by RAM patches. However, after that, the number of traps increases significantly, particularly for the Macintosh Plus. Table 5 summarizes the number of documented traps for each machine for System 3.2 and System 4.1. System 3.2 is not recommended for the SE, so I listed the minimum configuraton of 4.0. Some people used beta releases of 4.1 on the II, but again its not kosher, so the Mac II list starts with 4.1.
If you have your own count of traps, it might be slightly different. There are some gray areas when it comes to defining exactly what is a documented trap.
System 4.1
Looking at the trap count, its pretty obvious that System 4.1 makes a Macintosh Plus almost identical to an SE from a software standpoint. It has the same Toolbox calls available, and in the OS, is missing only the ADB-related stuff and a couple of slot-oriented calls.
Table 6 summarizes the programming-level features of System 4.1, primarily in the area of new and enhanced traps. The list is short for the 512; the other machines share most of the same functionality.
For those traps not provided in ROM, there are corresponding PTCH resources in System 4.1, as shown in Table 7. Resource #0 is used for all systems; if the other numbers seem strange, theyre nothing more than the concatenation of the two bytes of machine and ROM version returned by the _Environs trap. Notice how huge the trap patches are for the Mac Plus -- this must be one important reason why System 4.1 provides a resizable system heap.
Traps can also be patched by any other code loaded at system startup time, notably INIT resources. In case you missed the scoop, startup looks for files of type INIT or RDEV in the system (blessed) folder and then runs any INIT resources found there.
Incidentally, if youre having trouble fitting System 4.1 onto a floppy-based boot disk, you can strip out the unused PTCH resources. If you dont have a Macintosh II, you can also delete all the snd ,snth, and cicn resources; this saves nearly 40K for a Macintosh Plus. However, you should edit the STR #0 (version) resource and the Get Info box to indicate your hack, and DO NOT DISTRIBUTE THIS VERSION TO SOMEONE ELSE. If the modification is performed only by people smart enough to know how to do it, its much less likely to cause naïve users to come to grief.
New Traps
With System 4.1, a few new traps are available on all machines, including the 512.
Two, in fact, came in with earlier System versions 3.3 and 4.0, both released in January. Other than adding the Shutdown Manager, in fact, System 4.0 is almost identical to 3.3. Both contain the trap-based Printing Manager.
Owners of the Macintosh 512 can also take advantage of the Script Manager under System 4.1, via a dispatched trap. The _KeyTrans trap provides a new scheme for keycode translation, unlike the original (low-memory global) approach described in an earlier column (Be A Keyboard Sleuth, August 1986.)
The other new traps are provided to Macintosh Plus (and SE) owners to keep up with their II-owning brethren. The use of these traps is described in the Macintosh II documentation, such as Inside Macintosh Volume V.
The Toolbox functionality of Plus and SE is essentially the same as the II, except for color. The OS is different, reflecting three hardware-dependent differences of the Macintosh II:
32-bit memory addressing
NuBus slots
Sound Manager
The new traps available in System 4.1 are listed in Table 8, along with where the trap can be found -- since several made it into ROM on the SE and Mac II. A few traps were already defined in the SEs ROM, but were patched in System 4.1 to get it right.
Enhanced Capabilities
A number of traps are not new, but are previously ROM-based traps redefined by RAM patches in System 4.1. Those redefined for the Mac 512 are shown in Table 9, while Table 10 lists those for the three other machines. I dont have any way of knowing which patches have changed from the previously RAM-based traps, so these lists exclude traps that were RAM-based previously.
Some of these patches are to fix bugs, but System 4.1 also contains enhanced capabilities for two important managers.
Table 10: Traps changed from System 3.2 to System 4.1
Name | Word | Plus | SE | II | Remarks
|
|
_Read | A002 | patched | ROM | ROM
|
_FreeMem | A01C | ROM | patched | ROM
|
_SetHandleSize | A024 | unpatched | ROM | ROM
|
_HLock | A029 | unpatched | ROM | ROM
|
_HUnlock | A02A | ROM | patched | patched
|
_GetOSEvent | A031 | patched | ram | patched | Also Mac 512
|
_CompactMem | A04C | patched | patched | patched
|
_RelString | A050 | unpatched | ROM | ROM
|
_RmvTime | A059 | patched | ROM | ROM
|
_PrimeTime | A05A | patched | ram | ROM | Patched/ Sys 4.0
|
_HFSDispatch | A060 | ram | patched | ROM
|
_StackSpace | A065 | ROM | patched | ROM
|
_HGetState | A069 | ram | patched | ROM
|
_TESelView | A811 | patched | ROM | ROM
|
_TEPinScroll | A812 | patched | patched | patched
|
_TEAutoView | A813 | patched | patched | ROM
|
_InsMenuItem | A826 | patched | patched | ROM
|
_SetFScaleDisable | A834 | patched | ROM | ROM
|
_FontMetrics | A835 | patched | ROM | ROM
|
_MeasureText | A837 | patched | RAM | ROM
|
_Fix2Long | A840 | patched | ROM | ROM
|
_Frac2Fix | A842 | patched | ROM | ROM
|
_FracDiv | A84B | patched | ROM | ROM
|
_FixDiv | A84D | patched | ROM | ROM
|
_FixMul | A868 | ROM | patched | patched
|
_FixRatio | A869 | unpatched | ROM | ROM
|
_FixRound | A86C | patched | patched | ROM
|
_GetClip | A87A | unpatched | ROM | ROM
|
_DrawText | A885 | ROM | patched | ROM
|
_TextFace | A888 | ROM | unpatched | ROM
|
_FillRect | A8A5 | ROM | patched | ROM
|
_PtInRect | A8AD | ROM | unpatched | ROM
|
_FillRgn | A8D6 | ROM | patched | ROM
|
_StdGetPic | A8EE | patched | patched | ROM | color PICT
|
_DrawPicture | A8F6 | patched | patched | ROM | color PICT
|
_InitFonts | A8FE | patched | patched | ram
|
_RealFont | A902 | patched | ROM | ROM
|
_SetFontLock | A903 | patched | ROM | ROM
|
_InitWindows | A912 | patched | patched | patched
|
_ValidRect | A92A | patched | patched | patched
|
_FindWindow | A92C | patched | patched | ROM
|
_InitMenus | A930 | patched | patched | ram | Also Mac 512
|
_NewMenu | A931 | patched | patched | ROM | Menu Manager
|
_DisposMenu | A932 | patched | patched | ROM | Menu Manager
|
_AppendMenu | A933 | patched | patched | ROM | Menu Manager
|
_ClearMenuBar | A934 | patched | patched | ROM | Menu Manager
|
_InsertMenu | A935 | patched | patched | ROM | Menu Manager
|
_DeleteMenu | A936 | patched | patched | patched | Menu Manager
|
_DrawMenuBar | A937 | patched | patched | ram | Menu Manager
|
_HiliteMenu | A938 | patched | ram | patched | Menu Manager
|
_EnableItem | A939 | patched | ram | ROM | Menu Manager
|
_DisableItem | A93A | patched | ram | ROM | Menu Manager
|
_GetMenuBar | A93B | patched | patched | ROM | Menu Manager
|
_SetMenuBar | A93C | patched | patched | ROM | Menu Manager
|
_MenuSelect | A93D | patched | patched | ROM | Menu Manager
|
_MenuKey | A93E | patched | patched | ROM | Menu Manager
|
_GetItmIcon | A93F | patched | patched | ROM | Menu Manager
|
_SetItmIcon | A940 | patched | patched | ROM | Menu Manager
|
_GetItmStyle | A941 | patched | patched | ROM | Menu Manager
|
_SetItmStyle | A942 | patched | patched | ROM | Menu Manager
|
_GetItmMark | A943 | patched | patched | ROM | Menu Manager
|
_SetItmMark | A944 | patched | patched | ROM | Menu Manager
|
_CheckItem | A945 | patched | patched | ROM | Menu Manager
|
_GetItem | A946 | patched | patched | ROM | Menu Manager
|
_SetItem | A947 | patched | patched | ROM | Menu Manager
|
_CalcMenuSize | A948 | patched | patched | ROM | Menu Manager
|
_GetMHandle | A949 | patched | patched | patched | Menu Manager
|
_SetMFlash | A94A | patched | patched | ROM | Menu Manager
|
_PlotIcon | A94B | patched | patched | ROM | Menu Manager
|
_FlashMenuBar | A94C | patched | patched | ROM | Menu Manager
|
_AddResMenu | A94D | patched | patched | ROM | Menu Manager
|
_CountMItems | A950 | patched | patched | ROM | Menu Manager
|
_InsertResMenu | A951 | patched | patched | ROM | Menu Manager
|
_DelMenuItem | A952 | patched | patched | ROM | Menu Manager
|
_GetResource | A9A0 | ROM | patched | patched
|
_LoadResource | A9A2 | ROM | patched | patched
|
_TEGetText | A9CB | patched | ROM | ROM | TextEdit
|
_TEInit | A9CC | patched | patched | ram | Also Mac 512
|
_TEDispose | A9CD | patched | ROM | ROM | TextEdit
|
_TextBox | A9CE | patched | patched | patched | TextEdit
|
_TESetText | A9CF | patched | ROM | ROM | TextEdit
|
_TECalText | A9D0 | patched | ROM | ROM | TextEdit
|
_TESetSelect | A9D1 | patched | ROM | ROM | TextEdit
|
_TENew | A9D2 | patched | ROM | ROM | TextEdit
|
_TEUpdate | A9D3 | patched | ROM | ROM | TextEdit
|
_TEClick | A9D4 | patched | ROM | ROM | TextEdit
|
_TECopy | A9D5 | patched | ROM | ROM | TextEdit
|
_TECut | A9D6 | patched | ROM | ROM | TextEdit
|
_TEDelete | A9D7 | patched | ROM | ROM | TextEdit
|
_TEActivate | A9D8 | patched | ROM | ROM | TextEdit
|
_TEDeactivate | A9D9 | patched | ROM | ROM | TextEdit
|
_TEIdle | A9DA | patched | ROM | ROM | TextEdit
|
_TEPaste | A9DB | patched | ROM | ROM | TextEdit
|
_TEScroll | A9DD | patched | ROM | ROM | _TEKey unchanged
|
_TEInsert | A9DE | patched | ROM | ROM | TextEdit
|
_TESetJust | A9DF | patched | ROM | ROM | TextEdit
|
_Munger | A9E0 | ram | patched | ROM
|
Most noticeably, the new TextEdit supports what weve all been asking for -- mixed fonts and styles in an editing record managed by TextEdit. Three new traps -- _TEGetOffset, _TEStyleNew and the dispatched _TEDispatch are provided, while the existing TextEdit traps have been modified to use the new style data structure. As Table 10 shows, this is provided in ROM by the Macintosh SE and II, but in RAM by the Macintosh Plus.
And if you havent heard by now, the Mac II (and System 4.1) provides hierarchical menus. Selecting an item from a normal menu causes another menu to pop up. The revised Menu Manager also includes the _PopUpMenuSelect trap and a menu bar definition procedure (type mbdf) to complement the menu definition procedure (MDEF).
As an aside, new File Manager traps for external and shared file systems have been provided since the original HFS release. These traps are allocated as new selectors off of _HFSDispatch. At least some are installed for those having the AppleShare client driver (an RDEV file) in their blessed folder; the SE that I tested with, for example, was using AppleShare at the time.
Other Changes
There are a number of bug fix changes in System 4.1, including many I dont know about. However, there are a few that either Apple has talked about or that I can guess to explain the remaining traps on Table 10. There are also changes that correspond more to a change in specification than a bug correction.
The draft IM Volume V included notes about how many of the fixed-point arithmetic traps had problems that are now fixed. To summarize, _FixRound had trouble with negative numbers, _FracDiv and _FixDiv had problems with large quotients, and _FracToFix and _FixToLong acted up when rounding up to the next number. Its nice to know that Apples programmers are human, just like the rest of us. For the Macintosh II, _ClosePort was patched to be able to close a CGrafPort (color drawing port). Earlier in the Color QuickDraw specification, there was a separate trap to close these ports, but they were later combined into one and _CloseCPort went away.
Also, many of the Mac II traps didnt make it into the ROM-burning party, and had to be added to PTCH #376. This includes the entire Palette Manager, not shown.
There are many other changes I have no explanation for. Such changes include all of the unnamed OS traps in the range $A0BF to $A0FF, of which many are patched by System 4.1. Im sure the folks at Apple know what these are -- and probably Duane Maxwell at Levco, since the Levco ROM supplied with the Prodigy 4 patches some of these traps, according to my sleuthing.
SysEnvirons
As you may have gathered by now, System 4.1 and the 128K (or later) ROM offer a lot of attractive capabilities for the Macintosh developer. But with all the possible configurations, how do you tell what is available when your program is running?
I suspect Apples Tech Support department anticipated a flurry of questions on this subject, because they proposed and developed a new routine just to provide such information. The routine SysEnvirons is now the official way to check for compatibility testing The details of calling it are well-described in Macintosh Technical Note #129, so I wont reiterate them here. If you dont have the tech note in front of you, the information returned by SysEnvirons is summarized in Table 11.
The rules on how SysEnvirons works and when it is available are interesting, and certainly relevant for a discussion of trap patches, so let me touch on a few points.
Beginning with System 4.1, theres a _SysEnvirons trap provided as a RAM patch for the Macintosh Plus, SE and II. It is not available on the Macintosh 512, nor is it in ROM for any machine yet released. Apple provides a standard glue routine for calling the trap, which will be part of MPW 2.0 and presumably other development systems.
The glue can be used on any machine, whether it includes the _SysEnvirons trap or not. Figure 2 shows a flow chart for how the glue works.
Note that the glue is more than just stuffing a few registers for the _SysEnvirons trap. For a 64K ROM machine, _SysEnvirons uses the same trap number as _StdLine, so its not practical to include a trap patch for it. Instead, the glue fills in as many values as possible for a 64K ROM machine, as it also does for the Plus (and SE) when used on a System version before 4.1.
Some of this information was already available in low memory globals. Apple has recently been making nasty noises about not using low-memory globals in the future, so you should use SysEnvirons wherever possible. Since the main problem with low-memory globals is saving their context in a multi-application environment (Switcher and its sucessors), most of the compatibility globals should be the last ones to go. After all, they dont changes values dynamically.
However, as Apple discovered on the Apple II, programs reading reserved memory locations (rather than using ROM calls) create permanent compatibility headaches, so if you use the ROM call, the OS can provide the requested information to you without being stuck with a particular memory representation into the 21st Century.
Sleuth Your Own Traps
David is never happy unless he gets a program with every article, so being a loyal columnist, I try to oblige him. In this case, I offer a way to do your own trap sleuthing.
Anyone who can say _GetTrapAddress can detect which traps are defined or patched. Detecting patches is the easiest, since the list of the trap patches is public record. To quote from Inside Macintosh, Volume II, page 383:
You can tell whether a routine is patched by comparing its address to the global variable ROMBase; if the address is less than ROMBase, the routine is patched.
You have to watch out, however, since this technique is not 100% accurate. RAM patches can come from other sources, such as AppleShare. Also, some applications patch traps. For example, MPW patches most of the File Manager traps so that it can provide shell I/O.
What about traps that arent implemented at all: how do you find them? One way would be to attempt to call the trap and see if the Macintosh crashes, but this would be a slow way to check out a list of 700 or so possible traps, not to mention extremely frustrating.
There is a better way. Apple has indirectly documented an approved technique to the outside world recently -- such as in the SysEnvirons tech note and MacApp 1.1 source code. Im told it will probably be the subject of a future tech note.
Trap word $A89F is Apples standard unimplemented trap. If you get an address from the call:
GetTrapAddress($9F)
that is also the address of any unimplemented trap; just compare the address of any trap you check to this value.
The example (written in MPW C) shows an MPW tool to answer the question: does this trap exist? This allows you to inquire for one specific trap, which I find much more handy than my 160K Excel file containing all the traps for all configurations. The example also shows the algorithm for your own program to detect an unimplemented trap, such as whether to use the new TextEdit (check for _TEStyleNew) or the Script Manager (try _ScriptUtil).
The program distinguishes between system heap trap patches (presumably from the system) and application heap patches (presumably from the application). Neither rule is ironclad. Since there can be more than one application heap zone, it assumes that anything outside the system heap but below the ROM is in the application heap. Also, many programs place their actual patch in the application heap, but the trap table points to a single jump in the system heap -- so the address will fit into that first 64K of low memory on a Mac 512.
There are probably a few machines that violate this simple heuristic. Levcos Prodigy has its own PROM that is neither RAM nor Apple ROM, as I suspect some of the coprocessor and display card companies do. If you were testing on such a machine, you might add tests to mark those references.
Coming Attractions
With my book behind me, Im now doing some interesting things with Color QuickDraw. If youre at the Macworld show in Boston (August 11-13), stop by MacTutor booth and ask for me if you want to see what Im up to, or just have some suggestions for future topics to be covered in Resource Roundup.
It seems like every MacTutor reader I talk to asks me about my promised article on how to write your own printer driver. Since I wrote the last article (Printer Sleuthing, March 1987) Ive been too busy with my book to do anything else, but I hope to get it to it in the coming months.
In the meantime, if you want to write your own printer driver, I would note that this has never been for the faint-hearted, and maybe only for the foolish. Even for an extremely skilled and knowledgeable Macintosh programmer, its probably several man-months to get even a hack driver working. I personally have not done it (yet), which is one reason I havent written the article.
Also, Apple has never been very forthcoming with details on this subject, and recent indications (see Macintosh Technical Note #122: Device-Independent Printing) are that this will be even more true in the future, as they make private device-dependent fields for their new (and current) printers. The 2.0 version of the MPW interfaces also delete some previously-provided information about print records, including the bDevCItoh and bDevLaser constants indicating the printer type (does this mean a new printer is due soon?)
Theres some good news for application writers (the majority of us), however, since the new trap-based Printing Manager increases the amount of information provided in a device-independent way. More in a future column!
/* IsTrap.c: Detect trap availability
Written by Joel West in MPW C, June 1987
Compiled as an MPW tool (shell command); usage:
IsTrap A010 A060print information
on traps $A010 and $A060
IsTrap A800 -A830 information on all traps
from $A800 to $A830
There is one option letter (which like UNIX
and unlike MPW, must come first):
-p show detailed progress information
Status values returned:
0 ok
1 syntax error
2 trap not implemented
*/
#include <Memory.h>/* for THz heap zone ptr */
#include <OSUtils.h> /* for GetTrapAddress() */
#include <stdio.h>
#define UNDEFTRAP 0x9F
#define GETLONG(addr) *( (long *) addr)
/* grab a low-memory global value */
#define ROMBase GETLONG(0x2AEL)
typedef short Half;
typedef unsigned short UHalf;
/* traps are Axxx, normally negative numbers */
typedef unsigned long Addr;
/* for unsigned address comparisons */
int strspn(),strlen();
long MyGetTrapAddr();
void syntaxerr();
THz syshz;
#define INSYSHEAP(a) (a > (long) syshz && a < (long) syshz->bkLim)
main(argc,argv)
int argc;
char **argv;
{int argno,len,status;
Boolean range,verbose=0;
Addr trapword, trapaddr, unimpaddr, rombegin;
UHalf oldword=0,t;
char *p;
unimpaddr = GetTrapAddress(UNDEFTRAP);
rombegin = ROMBase;
syshz = SystemZone();
argno = 1; /* parameter number */
if (argno < argc && ! strcmp(argv[argno], -p)) /* -v for you UNIX
types */
{ verbose++;
argno++;
}
if (argno >= argc)
syntaxerr(argv);
if (verbose)
{ printf(ROM @ %X\n, rombegin);
printf(System heap from %X to %X\n, syshz, syshz->bkLim);
}
status = 0;
for (; argno<argc; argno++)
{ range = 0;
p = argv[argno];
if (*p == -)
{ p++;
range++;
}
len = strlen(p);
if (len && len == strspn(p, 0123456789ABCDEF))
{ sscanf(p,%lx,&trapword);
if (range)
t = oldword+1;
else
t = trapword;
for (; t<=trapword; t++)
{ trapaddr = MyGetTrapAddr(t);
printf(Trap %lX is , t);
if (verbose)
printf(%lX, , trapaddr);
if (trapaddr == unimpaddr)
{ printf(undefined\n);
status = 2; /* indicate result to shell */
}
else
if (trapaddr >= rombegin)
printf(in ROM\n);
else if (INSYSHEAP(trapaddr))
printf(patched\n);
else /* in application heap? */
printf(overridden\n);
}
oldword = trapword;
}
else
syntaxerr(argv);
}
exit(status);
}
void syntaxerr(argv)
char **argv;
{
fprintf(stderr, # %s - invalid syntax.\n, argv[0]);
fprintf(stderr, # %s - usage: %s [-p] trap \n, argv[0], argv[0]);
exit(1);
}
/*
Find the trap address for a given trap word.The 128K ROM provides NGetTrapAddress
(a glue routine), which distinguishes between OS and Toolbox traps.
This eventually uses the same trap number as GetTrapAddress, so it seems
to work fine on the 64K ROM.
*/
long MyGetTrapAddr(trapword)
UHalf trapword;
{UHalf trapnum;
TrapType typ;
if ((long)trapword < 0x0000A800L)
{ typ = OSTrap;
trapnum = trapword & 0xFF;
}
else
{ typ = ToolTrap;
trapnum = trapword & 0x3FF;
}
return NGetTrapAddress(trapnum, typ);
}