Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

14 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🖥️ macrecomp

Drop-in classic Macintosh for your static recompilation project.

   68k CODE resources                     Your recompiled C
   from a 1980s Mac app                   (one function per 68k sub)
          │                                       │
          │  extract · disassemble · lift         │  calls Toolbox traps
          ▼                                       ▼
   ┌──────────────────────────────────────────────────────┐
   │                     macrecomp                          │
   │   m68k CPU state · A5 world · resource mgr · QuickDraw │
   │   Event/Menu/Window/Dialog Mgr · Sound Mgr             │
   └──────────────────────────────────────────────────────┘
          │
          ▼
   SDL2 window + audio

The System 6/7 Toolbox, chopped into a linkable C library — so you never reverse-engineer QuickDraw twice.


What is this?

Static recompilation takes an old program's machine code and turns it into native C that runs today. For a console game the hard part is the hardware (that's what snesrecomp provides). For a classic Macintosh application the hard part is the Toolbox — the ~1000 ROM/System traps every Mac app calls for graphics, windows, menus, events and sound.

Every 68k Mac app draws through QuickDraw, pumps GetNextEvent, and plays sound through the Sound Manager. So why reimplement that for every recomp?

macrecomp packages the pieces a lifted 68k Mac app needs — a small m68k CPU state model, the A5 world + segment/jump-table loader, a resource-fork manager, and a growing HAL that maps Toolbox traps onto SDL2 — as a linkable library plus the tooling to get you there. This is the same "chop the platform into libraries, let each game link against them" approach as N64Recomp and snesrecomp, aimed at the Mac.

It is the sibling of the x86/DOS pcrecomp toolkit, for 68k + Toolbox instead of 8086 + DOS INTs.

The pipeline

  App (HFS resource fork: CODE 0..N + PICT/snd/ASND/MENU…)
        │  ① extract     tools/extract_resources.py   (dc42/HFS → CODE + assets + inventory.json)
        ▼
  CODE segments + asset catalog
        │  ② disassemble  tools/disasm_code.py         (capstone M68K)
        │  ③ classify     tools/scan_traps.py          (enumerate A-line Toolbox traps  ← the scope gate)
        ▼
  function table + trap set
        │  ④ lift         tools/lift68k.py             (68k → C against the macrecomp runtime)
        ▼
  C source ──⑤ HAL──▶  QuickDraw→SDL2, traps→runtime ──⑥ build──▶ native app

Steps ①–③ are cheap and tell you the real cost of a title before you commit to it: the trap set from ③ is exactly the Toolbox surface you must implement.

Status

🚧 v0 — tooling first. The dig tools are real; the runtime HAL grows per game.

Component What it does State
extract_resources.py DiskCopy 4.2 / raw HFS → CODE segments, asset catalog, inventory.json ✅ working
disasm_code.py capstone-M68K disassembly, annotated with traps + A5 jump-table calls ✅ working
scan_traps.py enumerate A-line ($Axxx) Toolbox traps; parse the CODE 0 jump table ✅ working (validated on Finder)
traps.json 1177 trap word↔name mappings (Inside Macintosh) for the two tools above
pict2png.py decode 1-bit QuickDraw PICT (v1) resources → PNG (BitsRect/PackBitsRect)
unprotect.py statically unpack self-decrypting/protected CODE fully solved (jump table + segment bodies, byte-exact)
ghidra/EmuDecrypt.java run an isolated decrypt routine in Ghidra's p-code emulator (the oracle for cracking an unknown cipher)
lift68k.py mechanical 68k → C lifter (per-function; branches→goto; traps→HAL) 98–100% instruction coverage
runtime m68k.{h,c}: CPU state + big-endian memory + faithful CCR flags + function table/dispatch the execution substrate
runtime quickdraw.c + platform_sdl.c: 1-bit framebuffer + pen/rect/line/oval/text/CopyBits → SDL2 window the video HAL ✅ core (self-tested)
runtime toolbox.c: A-trap dispatch, Resource Mgr (serves the app's resources), QuickDraw incl. CopyBits + DrawPicture, Window/Menu/Dialog/File stubs, Memory Mgr heap the OS HAL 🟢 ~95 traps; boots real games
Sound (ASND) · full Menu/Dialog interaction

First customer: shufflepuck-cafe (Broderbund, 1988) — 6 CODE segments, ~52 KB of 68k, B&W QuickDraw.

Using macrecomp in your project

Add it as a submodule (this is how the game repos consume it):

git submodule add https://github.com/sp00nznet/macrecomp.git ext/macrecomp
# In your game's CMakeLists.txt:
add_subdirectory(ext/macrecomp)
target_link_libraries(my_recomp PRIVATE macrecomp SDL2::SDL2main)

Extract a title's resources to start digging:

python ext/macrecomp/tools/extract_resources.py "MyGame.dc42" -o work/
# → work/code/CODE_0.bin … CODE_N.bin, work/inventory.json, work/assets/…

Repo layout

macrecomp/
  tools/      extract / disasm / scan-traps / lift  (the dig kit, Python)
  runtime/    the linkable C library — m68k state, A5 world, Toolbox HAL → SDL2
  include/    public headers (macrecomp/*.h)
  docs/       ARCHITECTURE.md and trap-mapping notes
  examples/   minimal harnesses

Credits & prior art

  • macresources + machfs by Elliot Nunn — pure-Python HFS + resource-fork parsing. The extractor stands on these.
  • capstone — M68K disassembly.
  • Inside Macintosh (Apple, 1985–) and the open-source Executor clean-room Toolbox — reference semantics for the trap HAL. No Apple ROM or code is used or redistributed here.
  • Approach borrowed from N64Recomp and snesrecomp.

License

MIT — see LICENSE. The toolkit is original work. It ships no Apple ROM, System software, or copyrighted game data — you bring your own copy of whatever you're recompiling.

About

Static-recompilation toolkit for classic 68k Macintosh apps: extract resources, statically unpack copy protection, disassemble & lift 68k -> C, and a QuickDraw/Toolbox HAL over SDL2.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages