Jump to content

Macintosh Toolbox

From RetroTechCollection
Macintosh Toolbox
Developer(s) Apple Computer, Inc.
Initial release January 24, 1984
Type System ROM firmware / API framework
Platform Motorola 68000, PowerPC
Size 64 KB (128K/512K), 256 KB (Plus/SE), 1-4 MB (later models)
Written in 68000 assembly, later C
License Proprietary
Status Deprecated (replaced by Carbon/Cocoa)

The Macintosh Toolbox is a comprehensive collection of system-level firmware routines and application programming interfaces (APIs) embedded in the ROM of classic Macintosh computers from 1984 through the Mac OS 9 era. Originally occupying 64 KB of ROM space in the Macintosh 128K, the Toolbox provides the foundational graphical user interface, event handling, resource management, and hardware abstraction layer that defined the Macintosh user experience for over 15 years.

Architecture and Implementation

[edit | edit source]

ROM Organization

[edit | edit source]

The Toolbox resides in ROM alongside the Mac OS kernel routines, occupying distinct memory regions based on the Macintosh model:

Toolbox ROM Evolution
Model ROM Size Toolbox Start Major Components
Macintosh 128K/512K 64 KB $400000 QuickDraw 1.0, Core Managers
Macintosh Plus 128 KB $400000 SCSI Manager, Hierarchical File System
Macintosh SE 256 KB $400000 ADB Manager, improved QuickDraw
Macintosh II 256 KB $40800000 Color QuickDraw, Palette Manager
Macintosh IIci 512 KB $40800000 32-bit QuickDraw, Sound Manager
Power Macintosh 4 MB $40000000 PowerPC native code, 68k emulator

The ROM is divided into functional modules, each containing related managers and their dispatch tables. Early ROMs were hand-optimized 68000 assembly code to fit within severe space constraints—the entire GUI framework, graphics engine, and system utilities compressed into just 64 KB.

Memory Layout and Low Memory Globals

[edit | edit source]

The Toolbox maintains critical system state in low memory globals located at fixed addresses from $000-$1FFF:

  • $000-$0FF: Exception vectors (68000 processor)
  • $100-$1FF: System globals (SysZone, ApplZone, TheZone)
  • $200-$2FF: QuickDraw globals (ThePort, White, Black, Gray)
  • $300-$3FF: Toolbox dispatch table base
  • $400-$7FF: System and application parameter blocks
  • $800-$8FF: VIA hardware registers mirror
  • $900-$BFF: Screen buffer parameters
  • $C00-$DFF: Serial and disk driver globals
  • $E00-$FFF: Interrupt handler workspace

These globals are directly accessed by both ROM routines and applications, creating the tight integration characteristic of classic Mac OS but also contributing to its fragility.

Core Component Managers

[edit | edit source]

QuickDraw Graphics Engine

[edit | edit source]

QuickDraw forms the graphics foundation of the Toolbox, providing coordinate-independent 2D drawing with automatic clipping and sophisticated region algebra:

Data Structures:

  • GrafPort: 108-byte structure defining drawing environment
  • Region: Variable-size scanline-compressed shape representation
  • Pattern: 8×8 bit pattern for fills and pen drawing
  • BitMap: Pixel data with rowBytes and bounds rectangle

Core Drawing Primitives:

  • Line drawing: MoveTo, LineTo with fractional pen positioning
  • Shape primitives: FrameRect, PaintRect, EraseRect, InvertRect, FillRect
  • Region operations: UnionRgn, DiffRgn, XorRgn, SectRgn with arbitrary complexity
  • Text rendering: DrawChar, DrawString with built-in Chicago font
  • BitBlt operations: CopyBits with transfer modes (srcCopy, srcOr, srcXor, srcBic, notSrcCopy, notSrcOr, notSrcXor, notSrcBic)

QuickDraw maintains a complex clipping architecture through the intersection of:

  1. Port clipping region (clipRgn)
  2. Visible region (visRgn)
  3. Current picture clipping if recording

Window Manager

[edit | edit source]

The Window Manager handles the window layer abstraction, maintaining a linked list of WindowRecords in front-to-back order:

WindowRecord Structure (156 bytes):

TYPE WindowRecord = RECORD
    port:           GrafPort;       {QuickDraw port (108 bytes)}
    windowKind:     INTEGER;        {Application or system window}
    visible:        BOOLEAN;        {Window visibility flag}
    hilited:        BOOLEAN;        {Title bar highlight state}
    goAwayFlag:     BOOLEAN;        {Close box present}
    spareFlag:      BOOLEAN;        {Reserved}
    strucRgn:       RgnHandle;      {Structure region}
    contRgn:        RgnHandle;      {Content region}
    updateRgn:      RgnHandle;      {Invalid region needing redraw}
    windowDefProc:  Handle;         {WDEF resource handle}
    dataHandle:     Handle;         {WDEF-specific data}
    titleHandle:    StringHandle;   {Window title}
    titleWidth:     INTEGER;        {Pixel width of title}
    controlList:    ControlHandle;  {Linked list of controls}
    nextWindow:     WindowPeek;     {Next window in list}
    windowPic:      PicHandle;      {Window picture for updates}
    refCon:         LONGINT;        {Application reference}
END;

Window Definition Procedures (WDEFs): System-supplied WDEFs include:

  • WDEF 0: Document window with title bar and optional close/zoom boxes
  • WDEF 1: Alert/dialog box with double border
  • WDEF 2: Plain box without title bar
  • WDEF 4: Floating window (System 7+)
  • WDEF 16: Round-cornered window

Event Manager

[edit | edit source]

The Event Manager implements cooperative multitasking through a polling event loop, managing a 20-event queue in system heap:

EventRecord Structure (16 bytes):

TYPE EventRecord = RECORD
    what:       INTEGER;    {Event type (0-15)}
    message:    LONGINT;    {Event-specific data}
    when:       LONGINT;    {Ticks since boot}
    where:      Point;      {Mouse location}
    modifiers:  INTEGER;    {Modifier keys state}
END;

Event Types:

  • nullEvent (0): No event pending
  • mouseDown (1): Mouse button pressed
  • mouseUp (2): Mouse button released
  • keyDown (3): Key pressed
  • keyUp (4): Key released
  • autoKey (5): Key repeat
  • updateEvt (6): Window needs redrawing
  • diskEvt (7): Disk inserted
  • activateEvt (8): Window activated/deactivated
  • osEvt (15): Operating system event (suspend/resume)

The Event Manager maintains several timing parameters:

  • KeyThresh: Ticks before key repeat (typically 12)
  • KeyRepThresh: Ticks between repeats (typically 4)
  • DoubleTime: Maximum ticks for double-click (typically 32)
  • CaretTime: Ticks between cursor blinks (typically 32)
[edit | edit source]

The Menu Manager maintains hierarchical menus with a sophisticated caching and drawing system:

Menu Structure:

TYPE MenuInfo = RECORD
    menuID:     INTEGER;        {Unique menu identifier}
    menuWidth:  INTEGER;        {Pixel width when drawn}
    menuHeight: INTEGER;        {Pixel height when drawn}
    menuProc:   Handle;         {MDEF resource handle}
    enableFlags: LONGINT;       {Item enable bits}
    menuData:   Str255;         {Pascal string menu items}
END;

Menu Bar Structure: The menu bar is stored as a relocatable block containing:

  1. Number of menus (2 bytes)
  2. Array of menu handles (4 bytes each)
  3. Total width calculation cache

Menu Definition Procedures (MDEFs):

  • MDEF 0: Standard text menu
  • MDEF 1: Scrolling menu (System 7)
  • MDEF 2: Popup menu variant

Resource Manager

[edit | edit source]

The Resource Manager provides a two-level virtual memory system for code and data, searching multiple resource files in a defined order:

Resource File Structure:

Resource Header (256 bytes):
    Data offset:        4 bytes
    Map offset:         4 bytes
    Data length:        4 bytes
    Map length:         4 bytes

Resource Map:
    Header copy:        16 bytes
    Next map handle:    4 bytes
    File ref number:    2 bytes
    Attributes:         2 bytes
    Type list offset:   2 bytes
    Name list offset:   2 bytes

Resource Attributes (bit flags):

  • Bit 0: System reference (resSysRef)
  • Bit 1: Preload at startup (resPreload)
  • Bit 2: Protected from changes (resProtected)
  • Bit 3: Locked in memory (resLocked)
  • Bit 4: Purgeable from memory (resPurgeable)
  • Bit 5: Load into system heap (resSysHeap)

Search Order:

  1. Current resource file (most recently opened)
  2. Application resource fork
  3. System file resource fork
  4. ROM resources (if not overridden)

A-Trap Dispatch Mechanism

[edit | edit source]

68000 Implementation

[edit | edit source]

The Toolbox uses the 68000's illegal instruction exception to implement system calls through A-line traps—opcodes from $A000-$AFFF that trigger exception vector 10 ($28):

Trap Word Format:

Bits 15-12: 1010 (A-line identifier)
Bit 11:     0=OS trap, 1=Toolbox trap
Bit 10:     Auto-pop flag (Toolbox only)
Bit 9:      Reserved (later: extended trap)
Bits 8-0:   Trap number (0-511 or 0-1023)

Dispatch Process:

  1. CPU encounters A-line instruction
  2. Exception 10 triggers, saving PC and SR
  3. Dispatch routine at ($28) examines trap word
  4. For Toolbox traps: index into dispatch table at $E00
  5. For OS traps: index into dispatch table at $400
  6. Jump to routine address from table
  7. Routine executes and returns via RTS/RTD

Register-Based Parameters: Despite Pascal conventions, many traps use registers for speed:

  • D0-D2: Scratch/parameters/results
  • A0-A1: Pointers/handles
  • A2-A4: Preserved across calls
  • A5: QuickDraw globals pointer
  • A6: Stack frame (when used)
  • A7: Stack pointer

Common Trap Examples:

  • $A876 (_NewPtr): Allocate pointer, size in D0, result in A0
  • $A322 (_NewHandle): Allocate handle, size in D0, result in A0
  • $A8FE (_NewWindow): Parameters on stack, result in A0
  • $A873 (_SetPort): GrafPort in A0, no result

Trap Patching Mechanism

[edit | edit source]

The dispatch table's RAM location enables dynamic patching for bug fixes and extensions:

SetTrapAddress Implementation:

PROCEDURE SetTrapAddress(trapAddr: LongInt; trapNum: Integer);
VAR
    tableBase: Ptr;
BEGIN
    IF trapNum AND $0800 <> 0 THEN
        tableBase := Ptr($E00)  {Toolbox table}
    ELSE
        tableBase := Ptr($400); {OS table}
    
    trapNum := trapNum AND $1FF; {Mask to 9 bits}
    LongInt(tableBase + trapNum * 4)^ := trapAddr;
END;

System extensions (INITs/CDEVs) commonly patch traps to:

  • Fix ROM bugs
  • Add functionality
  • Monitor system activity
  • Implement virus protection

PowerPC Mixed-Mode Implementation

[edit | edit source]

PowerPC Macs lack illegal instruction traps, requiring a different approach:

Universal Procedure Pointers (UPPs):

TYPE RoutineDescriptor = RECORD
    goMixedModeTrap:    INTEGER;       {$AAFE}
    version:            BYTE;          {7 for PowerPC}
    flags:              BYTE;          {ISA and calling conventions}
    reserved:           LONGINT;       
    reserved2:          BYTE;
    selectorCount:      BYTE;
    routineCount:       INTEGER;
    {Array of RoutineRecords follows}
END;

Mixed-Mode Switch Process:

  1. Code calls UPP thinking it's a routine address
  2. UPP contains $AAFE trap at offset 0
  3. 68k emulator intercepts trap
  4. Mixed-Mode Manager examines descriptor
  5. Routes to native PPC or emulated 68k code
  6. Handles calling convention translation

Native Implementation Flags: The Power Mac ROM includes tables indicating native implementations:

  • $FFF00000: Native trap table base
  • Bit vector: 1 bit per trap (1=native, 0=emulated)
  • Jump table: Direct PPC routine addresses

System Integration Points

[edit | edit source]

Interrupt Management

[edit | edit source]

The Toolbox coordinates with hardware interrupts through several mechanisms:

Vertical Blanking (VBL) Tasks:

TYPE VBLTask = RECORD
    qLink:      QElemPtr;      {Queue link}
    qType:      INTEGER;        {vType=1}
    vblAddr:    ProcPtr;        {Task procedure}
    vblCount:   INTEGER;        {Ticks until execution}
    vblPhase:   INTEGER;        {Phase offset}
END;

VBL tasks execute at 60.15 Hz (NTSC) or 50 Hz (PAL) for:

  • Cursor animation
  • Sound buffer management
  • Time Manager services
  • AppleTalk maintenance

Deferred Task Manager: Allows interrupt handlers to schedule Toolbox calls for system time:

  • DTInstall: Add task to deferred queue
  • DTRemove: Remove pending task
  • Executes at next non-interrupt opportunity

Memory Management Integration

[edit | edit source]

The Toolbox heavily depends on the Memory Manager's handle-based architecture:

Handle Manipulation During Calls:

  1. Many Toolbox calls can trigger heap compaction
  2. Handles may relocate unless locked
  3. Dereferenced pointers become invalid
  4. Critical sections must call HLock/HUnlock

System vs Application Heap:

  • System heap: Contains Toolbox data structures
  • Application heap: Contains app-specific resources
  • Temporary memory: Allocated from unused RAM

File System Integration

[edit | edit source]

Resource Manager coordinates with File Manager for resource fork access:

Resource Fork Structure:

  • Logical EOF: End of resource data
  • Physical EOF: End of allocated space
  • Resource map: In-memory cache of fork structure
  • Data blocks: Actual resource content

Standard File Package: Provides consistent file dialogs through:

  • SFGetFile: Standard open dialog
  • SFPutFile: Standard save dialog
  • SFPGetFile/SFPPutFile: Positioned variants

Evolution and Extensions

[edit | edit source]

System 7 Additions

[edit | edit source]

System 7 (1991) brought major Toolbox expansions:

New Managers:

  • Edition Manager: Publish/subscribe for compound documents
  • Process Manager: Cooperative multitasking formalization
  • Alias Manager: Robust file/folder references
  • Help Manager: Balloon help system
  • Component Manager: Shared code modules

Enhanced Capabilities:

  • TrueType support in Font Manager
  • Virtual memory awareness
  • 32-bit addressing throughout
  • Interapplication communication via Apple Events

Color QuickDraw

[edit | edit source]

Introduced with Macintosh II (1987), Color QuickDraw expanded the graphics architecture:

PixMap Structure:

TYPE PixMap = RECORD
    baseAddr:       Ptr;            {Pixel data base}
    rowBytes:       INTEGER;        {Bytes per row + flags}
    bounds:         Rect;           {Boundary rectangle}
    pmVersion:      INTEGER;        {PixMap version}
    packType:       INTEGER;        {Packing format}
    packSize:       LONGINT;        {Packed data size}
    hRes:           Fixed;          {Horizontal DPI}
    vRes:           Fixed;          {Vertical DPI}
    pixelType:      INTEGER;        {Chunky/planar}
    pixelSize:      INTEGER;        {Bits per pixel}
    cmpCount:       INTEGER;        {Components per pixel}
    cmpSize:        INTEGER;        {Bits per component}
    planeBytes:     LONGINT;        {Offset to next plane}
    pmTable:        CTabHandle;     {Color table}
    pmReserved:     LONGINT;        {Reserved}
END;

Color Table Structure:

TYPE ColorTable = RECORD
    ctSeed:         LONGINT;        {Unique identifier}
    ctFlags:        INTEGER;        {Private flags}
    ctSize:         INTEGER;        {Number of entries - 1}
    ctTable:        ARRAY[0..0] OF ColorSpec;
END;

International Resources

[edit | edit source]

The Script Manager and international resources enabled localization:

INTL Resources:

  • INTL 0: Number formatting (decimal, thousands, currency)
  • INTL 1: Date/time formatting
  • INTL 2: Keyboard layouts
  • INTL 4: Tokenization tables

Script Systems:

  • Roman (0): Latin scripts
  • Japanese (1): Kanji/Kana support
  • Chinese (2): Traditional Chinese
  • Korean (3): Hangul support
  • Arabic (4): Right-to-left rendering
  • Hebrew (5): Right-to-left with vowel points

Performance Optimizations

[edit | edit source]

Register-Based Calling Conventions

[edit | edit source]

Critical routines bypass stack operations for speed:

QuickDraw Optimizations:

  • Region operations: Pass region handles in A0/A1
  • Line drawing: Coordinates in D0-D3
  • Pattern fills: Pattern pointer in A0

Memory Manager Fast Paths:

  • NewPtr/NewHandle: Size in D0, result in A0
  • GetHandleSize: Handle in A0, size in D0
  • HandToHand: Source in A0, dest in A0

Caching Mechanisms

[edit | edit source]

Font Cache:

  • 512-byte bitmap cache per font
  • Strike matrices for different sizes
  • Width tables for kerning

Resource Map Cache:

  • In-memory map for each open file
  • Handle table for loaded resources
  • One-deep cache for most recent

Menu Bar Cache:

  • Pixel width calculations stored
  • Menu item enables pre-computed
  • Hierarchical menu locations cached

Debugging and Diagnostic Support

[edit | edit source]

MacsBug Integration

[edit | edit source]

The Toolbox includes hooks for MacsBug debugger:

Debug Traps:

  • $A9FF (_Debugger): Enter debugger
  • $ABFF (_DebugStr): Display string and break
  • $A9C6 (_SysBreak): Conditional break

Symbol Tables: ROM includes procedure names for debugging:

  • Trap names: "NewWindow", "DrawString", etc.
  • Global labels: "ThePort", "ApplZone", etc.
  • Hardware addresses: "VIA", "SCC", etc.

Diagnostic Manager

[edit | edit source]

Power Manager and Diagnostic Manager (PowerBooks/Power Macs):

Power Manager Traps:

  • $A285 (_PMgrOp): Power management operations
  • $A485 (_IdleUpdate): Update idle state
  • $A685 (_SerialPower): Serial port power

Diagnostic Selectors:

  • gestaltDiagnostics: Diagnostic ROM presence
  • gestaltPowerMgrVers: Power Manager version
  • gestaltBatteryType: Battery technology

Low-Level Hardware Abstraction

[edit | edit source]

Slot Manager

[edit | edit source]

For NuBus and PDS expansion cards:

Slot Resource Structure:

TYPE SpBlock = RECORD
    spResult:       LONGINT;        {Result/error}
    spsPointer:     Ptr;            {Structure pointer}
    spSize:         LONGINT;        {Size of structure}
    spOffsetData:   LONGINT;        {Data offset}
    spIOFileName:   Ptr;            {Driver name}
    spsExecPBlk:    Ptr;            {Execution block}
    spParamData:    LONGINT;        {Parameters}
    spMisc:         LONGINT;        {Miscellaneous}
    spReserved:     LONGINT;        {Reserved}
    spIOReserved:   INTEGER;        {I/O reserved}
    spRefNum:       INTEGER;        {Driver reference}
    spCategory:     INTEGER;        {sRsrc category}
    spCType:        INTEGER;        {sRsrc type}
    spDrvrSW:       INTEGER;        {Driver software}
    spDrvrHW:       INTEGER;        {Driver hardware}
    spTBMask:       SignedByte;     {Type/board mask}
    spSlot:         SignedByte;     {Slot number}
    spID:           SignedByte;     {sResource ID}
    spExtDev:       SignedByte;     {External device}
    spHwDev:        SignedByte;     {Hardware device}
    spByteLanes:    SignedByte;     {Byte lanes}
    spFlags:        SignedByte;     {Flags}
    spKey:          SignedByte;     {Reserved}
END;

Serial Communications

[edit | edit source]

Serial Driver and Communications Toolbox:

Serial Port Control:

  • $A002 (_OpenDriver): Open .AIn/.AOut or .BIn/.BOut
  • $A003 (_CloseDriver): Close serial port
  • $A004 (_Control): Set baud, parity, handshaking
  • $A005 (_Status): Read port status

Communications Resources:

  • SERD 0: Modem port configuration
  • SERD 1: Printer port configuration
  • SERD 2-15: Additional ports (expansion cards)

ROM Version Detection

[edit | edit source]

Gestalt Manager

[edit | edit source]

Introduced in System 6.0.4 for capability detection:

Common Gestalt Selectors:

gestaltVersion              = 'vers'   {Gestalt version}
gestaltSystemVersion        = 'sysv'   {System software version}
gestaltROMVersion          = 'romv'   {ROM version}
gestaltMachineType         = 'mach'   {Machine type}
gestaltQuickdrawVersion    = 'qd  '   {QuickDraw version}
gestaltToolboxTable        = 'tblt'   {Trap table base}
gestaltOSTable             = 'ostt'   {OS trap table base}
gestaltNativeCPUtype       = 'cput'   {CPU type}
gestaltMMUType             = 'mmu '   {MMU type}
gestaltFPUType             = 'fpu '   {FPU type}

ROM Version History

[edit | edit source]

Major ROM versions and their Toolbox changes:

ROM Version Evolution
Version Size Date Key Toolbox Additions
$0069 64 KB 1984 Original Toolbox
$0075 128 KB 1986 HFS, SCSI Manager
$0076 256 KB 1987 ADB Manager
$0078 256 KB 1987 Color QuickDraw
$037A 512 KB 1989 32-bit QuickDraw
$067C 512 KB 1990 Sound Manager 2.0
$077D 1 MB 1991 System 7 Toolbox
$F1A6 4 MB 1994 PowerPC + emulator

Technical Limitations and Quirks

[edit | edit source]

Known Limitations

[edit | edit source]
  • 32,767 pixel coordinate limit: QuickDraw uses signed 16-bit coordinates
  • 32 KB resource size limit: Without special handling
  • 128 open files limit: File Control Block table size
  • Region complexity limit: ~24 KB for region data
  • 8 MB partition limit (24-bit mode): High byte used for flags

Common Programming Pitfalls

[edit | edit source]
  • Dangling pointers: After memory compaction
  • Resource not found: Missing from search path
  • Stack overflow: Deep recursion in 8 KB default stack
  • A5 world corruption: Incorrect A5 register management
  • VBL task reentrancy: Non-reentrant Toolbox calls

Undocumented Features

[edit | edit source]
  • _Launch trap ($A9F2): Can pass extended parameters
  • _Gestalt trap: Accepts private selectors
  • _StripAddress: Works differently on various ROMs
  • Menu Manager: Hidden color menu support pre-System 7

Toolbox in Modern Context

[edit | edit source]

Carbon Transition

[edit | edit source]

Carbon (Mac OS 8.1-10.14) provided a subset of Toolbox APIs:

  • Removed: Low-memory globals, direct hardware access
  • Deprecated: Segment Loader, vertical retrace
  • Modernized: Event handling, memory management
  • Added: Preemptive threading, Unicode support

Classic Environment

[edit | edit source]

Mac OS X 10.0-10.4 included Classic for running Toolbox applications:

  • Bluebox: Complete 68k/PPC emulation environment
  • Shared clipboard: Between Classic and native apps
  • File system mapping: HFS+ to Unix paths
  • Hardware limitations: No direct hardware access

Preservation and Emulation

[edit | edit source]

Modern emulators preserve Toolbox functionality:

  • Mini vMac: Accurate 68k Mac emulation
  • Basilisk II: 68k Mac with JIT compilation
  • SheepShaver: PowerPC Mac emulation
  • QEMU: Hardware-level Mac emulation

See Also

[edit | edit source]