Porting PC Games to Mac OS 9 with OpenGL and Carbon

During the late 1990s and early 2000s, porting PC games to Mac OS 9 required developers to navigate fundamentally different operating system architectures, processor standards, and multimedia libraries. By leveraging Apple's Carbon API to modernize the application framework and utilizing OpenGL for cross-platform 3D graphics rendering, studios like Westlake Interactive, Aspyr, and MacSoft successfully brought high-profile DirectX and Win32 titles to the PowerPC-driven Classic Mac platform.

The Architecture Challenge: Win32 vs. Classic Mac OS

PC games of this era were built around the Win32 API, preemptive multitasking, x86 architecture, and Microsoft DirectX (Direct3D, DirectSound, and DirectInput). In contrast, Mac OS 9 relied on cooperative multitasking, big-endian PowerPC processors, and legacy Macintosh Toolbox APIs.

Directly translating Windows API calls was impossible, meaning developers had to isolate the core game logic—such as artificial intelligence, physics, and gameplay mechanics—from platform-dependent subsystems like windowing, memory management, graphics, and audio.

Graphics Translation: Moving from Direct3D to OpenGL

Prior to the widespread adoption of OpenGL on the Mac, developers relied on Apple’s proprietary QuickDraw 3D RAVE API, which lacked broad industry support. Apple’s official adoption of OpenGL around Mac OS 8.6 and 9 transformed the porting landscape.

  1. API Mapping: Because DirectX was exclusive to Windows, graphics engines built on Direct3D had to be mapped to OpenGL. Developers rewrote the rendering pipeline, converting Direct3D vertex buffers, render states, and texture stages into corresponding OpenGL calls (such as glBegin/glEnd or display lists and vertex arrays depending on the era).
  2. Driver and Hardware Parity: OpenGL on Mac OS 9 required careful optimization for the graphics hardware of the time, primarily ATI Rage, Radeon, and 3dfx Voodoo cards. Developers often had to write custom workarounds for vendor-specific OpenGL extensions and driver quirks.

Modernizing the Framework with Carbon

Carbon was a transitional C-based API introduced by Apple to prepare developers for the launch of Mac OS X. It modified the traditional Macintosh Toolbox by removing deprecated routines and restricting direct memory access to system structures.

  • Dual Compatibility: Writing the core application shell to the Carbon specifications allowed games to run natively on Mac OS 9 while also running on early builds of Mac OS X without needing a complete rewrite.
  • Event Handling: Windows message pumps (GetMessage, DispatchMessage) were replaced by Carbon event loops. Developers mapped Windows keyboard, mouse, and system events to the Carbon Event Manager or Classic Mac WaitNextEvent loops.
  • Memory Management: Win32 virtual memory allocations (VirtualAlloc, malloc) had to be adapted to Mac OS 9’s memory model, which required fixed partition sizes allocated via the Finder's Get Info pane, utilizing NewPtr or Carbon memory calls.

Hardware and Processor Divergence

Beyond graphics and APIs, developers had to address fundamental hardware discrepancies:

  • Endianness Conversion: x86 processors were little-endian, whereas the PowerPC G3 and G4 processors used in Macs were big-endian. Binary asset files (textures, 3D meshes, save files) and network packets had to undergo byte-swapping routines at runtime or be pre-converted during the asset pipeline stage.
  • Sound and Input: DirectSound calls were replaced using Apple's Sound Manager or middleware like the Miles Sound System. For controllers and input, developers replaced DirectInput with Apple's InputSprocket (part of the Game Sprockets suite) or Carbon-compliant HID managers.
  • Toolchains: The primary development environment was Metrowerks CodeWarrior. Developers imported the original C or C++ PC source code, established new PowerPC targets, and resolved platform-specific header dependencies.