Files
TeslaSuite/410console/CONSOLE-4.10-DECOMP.md
CydandClaude Fable 5 deaade4f72 Track the 410console hand-off docs; ignore the raw Mac archive
The BattleTech port spec, the Console 4.10 decompilation notes, the golden
reference eggs, and the PEF/rsrc analysis tools come into the repo. The .sit
archive and its extraction (Mac binaries, __MACOSX/.finf metadata) stay
untracked for now.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 22:43:32 -05:00

28 KiB
Raw Permalink Blame History

Console 4.10 — Decompilation & Documentation

Reverse-engineering notes for the classic Mac OS operator console that commanded the networked Virtual World Entertainment (VWE) BattleTech / Red Planet pods. Part of the VWE Tesla restoration project.

  • Target dir: c:\VWE\TeslaRel410\410console\4_10-console-extracted\
  • Binary: Console 4.10 (728,064 bytes) — classic Mac OS fat application (68K CODE resources + PowerPC PEF/CFM fragment in the data fork).
  • Internal identity: type APPL, creator vwe4, version resource 2.4.0b3 / "Console 2.4.0b3", © 19951997 FASA Interactive, Inc. (The "4.10" in the folder name is the site/config release, not the app's own vers.)
  • Analysis method: custom Python PEF/PPC + resource-fork tooling (no Ghidra on this machine); capstone in PPC big-endian mode. See 410console/tools/.
  • Status: read-only analysis. Nothing in the target was modified.

0. TL;DR — what the console does

The console is a document-based Mac app (Metrowerks PowerPlant framework, CodeWarrior C++). Each open document is a Mission. The operator picks an Adventure (Solo/Team × BattleTech/Red Planet), a Location (arena) and a Scenario, assigns pilots/vehicles, then drives a fleet of cockpit pods through a mission lifecycle. It talks to two networks:

  1. Pod command/control — one MacTCP TCP stream per pod on port 1501 (console 200.0.0.1, pods 200.0.0.11200.0.0.120). This is the protocol that matters for the emulator. Commands (Load / Translocate / Stop / End / Reset) go out as small binary packets; pods stream back a one-byte Cockpit State (012) that the console records in Console Log.
  2. 4th Dimension (4D) database — a second client link to a 4D server for the pilot roster and mission scheduling ("Get Next Departure", Add/Delete/ Lookup Pilot, scoring). Evidenced by the _4D_Select4DServer / _4D_Find4DServer error strings; the wire protocol for 4D was not reverse-engineered (it is ACI's proprietary 4D client library).

The rest of this document backs every claim above with offsets, string refs, resource dumps and log excerpts.


1. File inventory & formats

File Size Format / role
Console 4.10 728 KB The application. Fat binary: PEF/PPC in data fork, 68K CODE + all UI resources in the resource fork (see §5).
Console Log 5.3 MB Runtime log, CR-terminated records. Ground truth for the pod protocol (§7).
Console.ini 92 KB Live config: 586 ::-namespaced sections — pods, adventures, locations, scenarios, vehicles (§8).
Console.ini copy 91 KB Prior copy of the above.
Stationary.ini 98 KB The stationery/template master config (Mac "stationery" = template document) used to seed a fresh Console.ini.
ini Folder/DB<City>/ Per-venue config overrides: Atlanta, Chicago, Cincinnati, Denver, Detroit, Houston, Miami, Ontario, Pittsburgh, San Jose, Toronto, LaZerPark.
ConsoleSorter/ + Console Log Sorter, Console Log.rpl 0 B here A companion log-sorter tool (data forks empty in this extraction; only Instructions survived).
FRC.rsrc, KR.rsrc, US.rsrc 225 B each Tiny locale resource stubs (French / Korean / US).
Fonts/ (Killmark, Stencil) 0 B Bitmap/suitcase fonts for kill-marker/stencil display (data forks empty here).
PlainText16 Folder/ 173 KB PlainText support (text traits).
.finf/ 32 B each Mac Finder-info sidecars from extraction (type/creator).
__MACOSX/._* AppleDouble sidecars — these carry the resource forks. ._Console 4.10 is 3.38 MB and holds the app's entire resource fork (§5).

Resource-fork location: the app's resource fork was preserved inside __MACOSX/._Console 4.10 (AppleDouble magic 0x00051607, entry id 2 = resource fork at file offset 0x52, length 0x3391CA). Finder info at offset 0x32 reads APPLvwe4type APPL, creator vwe4.


2. PEF container structure

First 16 bytes: 4A6F7921 70656666 70777063 00000001 = Joy! peff pwpc v1 (classic Mac OS CFM PowerPC container, big-endian).

Container header (40 bytes):

Field Value
tag1 / tag2 / arch Joy! / peff / pwpc
formatVersion 1
dateTimeStamp 0xAF4A5504
currentVersion 0
sectionCount 3
instSectionCount 2

Section table (each header 28 bytes; bodies follow the name table):

# Kind default total unpacked packed file off notes
0 Code (0) 0 625,536 625,536 625,536 0x003840 PPC text (0x98B80 bytes).
1 PatternInitData (2) 0 127,204 122,866 88,128 0x09C3C0 RLE-packed data/TOC/strings; unpacks to 0x1DFF2.
2 Loader (4) 0 0 0 14,272 0x000080 Imports/exports/relocs/entry.

Entry points (from the Loader header):

  • main = data-section transition vector at offset 0x5154[code 0x00082E5C, TOC 0x00008000]. So main executes at code 0x82E5C and the runtime TOC/r2 = data offset 0x8000. (This TOC value is the key that lets us resolve all r2-relative constant loads — see §6.)
  • init = none (-1), term = none (-1).
  • exported symbols = 0 (nothing is exported; this is a leaf application, not a shared library).
  • imported libraries = 3, imported symbols = 448, reloc sections = 1.

Tool: py -3.13 tools/pefparse.py "Console 4.10" header|loader|strings|dump|dis.


3. CFM imports (448 symbols across 3 libraries) — interpreted

Only three shared libraries are imported. Notably absent: OpenTransport, AppleTalk, and any TCP shared library — so the console does not use Open Transport. Its IP networking is done the older way, through the MacTCP .IPP driver via the Device Manager (see the PBControlAsync/Sync + PBOpenSync imports and the CTCPDriver/.IPP strings in §6).

MathLib (6)

num2dec, dec2num, str2dec, dec2str (SANE-style decimal ↔ string) and fetestexcept, feclearexcept (FP exception flags). Used for numeric formatting of scores/stats.

InterfaceLib (436) — the Mac Toolbox surface

Grouped by subsystem (representative, not exhaustive):

  • QuickDraw / GWorld / PICT: InitGraf, OpenCPort, NewGWorld*(via UGWorld), LockPixels, CopyBits(implied), OpenCPicture, DrawPicture(implied), PlotCIcon, PlotIconID, RGBBackColor, FrameRoundRect, InvertRgn, ClipRect … — draws the console windows, pod photos (PICT), mech/vehicle art, kill markers.
  • Window Manager: NewCWindow, GetNewCWindow, ZoomWindow, SelectWindow, HiliteWindow, FindWindow, BeginUpdate/EndUpdate, DragWindow(implied) …
  • Menu Manager: NewMenu, InsertMenu(implied), DeleteMenu, DrawMenuBar, MenuKey, HiliteMenu, EnableItem, CountMItems, GetItemMark …
  • Control Manager: NewControl, TrackControl, FindControl, Draw1Control, SetControlValue/Min/Max, HiliteControl, SetControlAction … (scrollers, buttons, the toolbar).
  • List / Dialog / TextEdit: LGetSelect, LSetSelect, LSetCell, LGetCell (List Manager — player/network tables), CautionAlert, ParamText, TEInsert, TEActivate, TEGetHeight, TECut, TEUpdate (mission notes / fields).
  • File Manager: FSpOpenDF, FSpCreate, FSpDelete, FSRead, FSWrite, FSClose, PBOpenSync, PBReadSync, PBWriteSync, PBHCreateSync, PBGetEOFSync, PBSetEOFSync, FSpCreateResFile, FSpOpenResFile, HOpenResFile … — reads Console.ini, writes Console Log, loads/saves mission egg files.
  • Device Manager (→ MacTCP): PBOpenSync, PBControlAsync, PBControlSync — open the .IPP driver and issue TCP control calls (TCPCreate/ActiveOpen/Send/Rcv/Close) — the pod network layer.
  • Printing Manager: PrOpen, PrOpenDoc, PrOpenPage, PrCloseDoc, PrClose — prints score sheets / mission highlights.
  • Apple Event Manager: AEInstallEventHandler, AEProcessAppleEvent, AECreateAppleEvent, AESend, AEGetParamDesc, AEGetNthDesc, AEPutParamDesc, AECreateList, AEGetAttributePtr, AEResolve(+ObjectSupportLib) … (see §9).
  • Misc: Random, BlockMove, GetScrap, SysEnvirons, ExitToShell, NewRoutineDescriptor/NewFatRoutineDescriptor (68K↔PPC mixed-mode glue).

ObjectSupportLib (6) — Apple Event object model

AEResolve, AESetObjectCallbacks, AEInstallObjectAccessor, CreateObjSpecifier, AEObjectInit, CreateOffsetDescriptor — the app is an AppleScript object-model server over its window/document objects (standard PowerPlant UAppleEventsMgr).


4. Code organization (from the 27 named CODE segments)

Because this is a fat binary, the resource fork still carries the CodeWarrior 68K segment names, which are a clean module map of the whole program (the PPC side is the same code, differently packaged):

 1 Main            10 Utilities       19 RP Panes
 2 Commanders      11 Libraries       20 Data Objects
 3 Connection      12 Debug           21 BT Data Objects
 4 Panes           13 TCP/IP          22 RP Data Objects
 5 Table           14 MUNGA           23 Printing
 6 Files           15 Console Menus    24 RP Printing
 7 Apple Events    16 Console Windows  25 BT Printing
 8 Array           17 Console Panes    26 Console Features
 9 Features        18 BT Panes
  • Connection / TCP/IP = the pod networking (CTCPDriver, CTCPStream, CTCPEndpoint, CTCPAsyncCall, CTCPResolverCall, NetworkEndpoint).
  • MUNGA = data marshalling (the mission/egg (de)serializer — "munge").
  • BT / RP split = per-game code (BattleTech vs Red Planet) for panes, data objects, and printing.

.cp source-module names recovered from the binary (the CodeWarrior debug string table) include, among ~140 files: ConsoleApp, ConsoleDoc, ConsoleWindow, PrefsDoc, NetworkEndpoint, NetworkEndpointList, NetworkTable, NetworkWindow, CTCPDriver, CTCPStream, CTCPEndpoint, CTCPAsyncCall, CTCPResolverCall, MissionObject, MissionEvent, MissionEventQueue, MissionView, MissionGraphView, MissionGraphWindow, MissionClockView, Participant, TeamList, TeamPrtcpntList, PlayerTable, BTScenario, BTVehicle, BTLocation, RPScenario, RPVehicle, RPLocation, Vehicle, Weather, Experience, Adventure, ScoreSheetView, DamageMatrix, BTKillMarker and the PowerPlant framework classes (LApplication, LDocument, LWindow, LView, LPane, LTableView, LCommander, LListener/LBroadcaster(implied), UAppleEventsMgr, UGWorld, UMemoryMgr, UReanimator, UModalDialogs).


5. Resource fork (550 resources, 39 types)

Parsed from __MACOSX/._Console 4.10 with tools/rsrcparse.py. Highlights:

  • cfrg (1) — the Code Fragment resource that points the CFM loader at the PEF in the data fork (confirms the fat-binary layout).
  • vers (2)2.4.0b3, "Console 2.4.0b3", © 19951997 FASA Interactive, Inc.
  • SIZE / BNDL / FREF / ICN# — standard app packaging; icm#/ics# application icons.
  • ºMWC (32000) — Metrowerks CodeWarrior project stamp (confirms toolchain).

Operator commands & UI

  • Toolbar buttons (ICN#/icl4/icl8, ids 10001011): Get Next Departure, Translocate, Load Mission, Add Pilot, Delete Pilot, Lookup.
  • MENU/Mcmd (10): Apple, File (New / Close / Save / Save a Copy… / Page Setup… / Print / Quit), Edit, Configuration, Adventure, BattleTech, Red Planet + scenario menus (BTScenario, RPScenario).
  • WIND/PPob (windows): RPMR ConsoleWindow, RPMF ConsoleWindow, BTFA ConsoleWindow, BTSB ConsoleWindow (the four game-mode console layouts), Mission Graph, Toolbar, Network Diagnostic, Lookup.
  • ALRT/DITL: About Box, Save-before-closing/quitting, Confirm Revert, Low Memory Warning, TCP Warning, Landscape/Portrait mode.

Data/game resources

  • Mech/MWpn/MDgZ (×24/×24/×22) — BattleTech mechs + weapons + damage zones: BlackHawk, Loki, MadCat, Owens, Thor, Vulture, Avatar, Sunder, TimberWolf, Satyr, Hellbringer, Summoner, …
  • PICT (×98) — pod photos (Carpe Diem, Calamity Jane, Man O' War,…) and faction crests (Davion, Kurita, Steiner, Liao, Marik, Comstar, VGL). These match pictID= in Console.ini.
  • Txtr (×57) — named text traits (fonts/styles for each field, plasma screen, mission clock).

String lists (STR#) — the semantic vocabulary

61 STR# resources. The protocol-relevant ones:

  • STR# 131 "Mission State" — the console-side (document) mission state descriptions, index 0..6:
    1. Mission data is incomplete.
    2. The mission is ready to load.
    3. The mission is being loaded.
    4. The mission is ready for translocation.
    5. The mission is being translocated.
    6. The mission is in progress.
    7. The mission has been completed.
  • STR# 130 "Network Endpoints" — the 50-name roster: cockpits (Frequent Flyer, Privateer, Man O' War, Divine Wind, Carpe Diem, Gypsy, Puck, Icarus, Calamity Jane, Valkyrie, Pegasus,…), cameras (Alpha/Beta/Gamma/Delta/Epsilon Camera), Mission Review stations, and PC/test targets (BrownCartPC, GaugeCartPC, ZabswareTarget). Index 0 = Bogon Alert! (invalid), <Available> = a free slot.
  • STR# 1002/1003 "Network Errors" — explicitly a 4D database client: _4D_Select4DServer, _4D_Find4DServer, "connection to the database", "asynchronous mode query already in progress", "invalid connection handle".
  • STR# 1001 Database Errors, 1004 Database Tasks, 1005 General Errors, 128 General Strings ("%s Mission %s", "Mission Time & Date: %s, %s", Show/Hide Toolbar, Show/Hide Network), 300 Adventure Strings (BattleTech, Red Planet), plus large game tables (scenarios, drop zones, roles, kill/death/damage strings, textures, football positions, …).
  • eTbl (3) — error tables named Database Errors, Network Errors, 4D Open Errors (again confirming the 4D backend).

6. Pod command/control protocol (MacTCP, port 1501)

This is the highest-value result. Evidence chain: binary strings → disassembly (TOC-resolved) → Console LogConsole.ini.

6.1 Transport

  • Custom C++ classes CTCPDriver / CTCPStream / CTCPEndpoint / CTCPAsyncCall / CTCPResolverCall wrap MacTCP. The literal driver name .IPP appears at data 0x1053F right next to CTCPDriver — this is the classic MacTCP IP driver opened with PBOpenSync, then driven with PBControlAsync/Sync.
  • One TCP connection per pod. From Console.ini each [NetworkEndpoint::Cockpit::*] sets classID=Ptcp, defaultPort=1501, localHostPort=1501, and the pod's addressIP (200.0.0.11200.0.0.117, etc.). Console host = 200.0.0.1; pods 200.0.0.11200.0.0.120 (from the log). The many Ptcp sub-keys (openTimeout, listenTimeout, delay, throughput, reliability, precedence, fragment, timeToLive, security, queryTimeout) are MacTCP TCP/IP ULP parameters passed to TCPActiveOpen / the IP header — further proof this is MacTCP, not OT.

6.2 Receive path — pod → console "Cockpit State"

Message dispatch lives at code 0x63B3C (inside the participant's message handler). The received message's low byte is the type:

0x63B3C  clrlwi  r0, r31, 0x18      ; r0 = msg & 0xFF   (message type)
0x63B40  cmplwi  r0, 0xC            ; 0..12 valid
0x63B44  bgt     0x63BEC            ; >12 → default → "Unknown message type!!!"
0x63B48  lwz     r3, -0x6CA4(r2)    ; TOC[data 0x135C] = jump table @ data 0x17B1C
0x63B4C  slwi    r0, r0, 2
0x63B50  lwzx    r3, r3, r0         ; handler = jumptable[type]
0x63B54  mtctr   r3 ; bctr

Every case calls SetCockpitState(participant+0x30C, type) at 0x62720:

0x62720 SetCockpitState:
   stb   r4, 0x289(r6)     ; participant->cockpitState = type   (field at +0x289)
   li    r4, 0xBBC ; bl BroadcastMessage   ; notify the UI panes/graph

(0x62778 is the matching getter: lbz r3, 0x289(r3).) The console then logs "<IP> Cockpit State: <type>". So the pod's message-type byte is literally the Cockpit State number, 012; type > 12 logs "Unknown message type!!!" (seen twice in the 5.3 MB log). The jump table at data 0x17B1C (13 code pointers, default 0x63BEC) is the physical proof of the 012 range.

6.3 Send path — console → pod commands

Commands are transmitted by NetworkEndpoint::Send at 0x629EC, called as Send(endpoint, &msgHeaderWord, payloadObj, payloadLen). It frames a packet = 16-byte header + payload:

buf = alloc(len + 0x10)
memcpy(buf+0x10, payloadObj, len)     ; body
buf[0..3]  = *msgHeaderWord           ; message-class word  (observed 0x04000000)
buf[4..7]  = 0
buf[8..11] = value from 0x3CB38       ; sequence / timestamp
CTCPStream::Write(endpoint, buf, len+0x10)   ; via 0x39748 → 0x3BD28

The payload object is a small serialized struct whose byte[0] = its size and byte[4] = the command code. Two confirmed by disassembling the object constructors:

Command Ctor payload size command code (byte[4]) Verb logged Sender
Translocate mission 0x3EC74 0x0C 5 Translocating Mission… 0x67438
Stop mission 0x3ECC8 0x10 6 Stopping Mission… 0x6755C

Other senders (same shape, codes not yet pinned): Loading Mission (0x64xxx/Received egg file 0x648C0), Ending Mission 0x66464 (uses a variant send 0x5E474 that packs the destination IP from a 4-byte struct field +0x10..0x13), Reset Mission 0x6769C. Command codes for these are recoverable with the same method (find the li r0,N; stb r0,-0x10(r1) that seeds object byte[4]) — see Open Questions.

6.4 Internal PowerPlant command/broadcast IDs

The app's own command constants cluster in 0xBBA0xBDF (decimal 30023039). Confirmed meanings: 0xBBC = cockpit-state-changed broadcast, 0xBC5 = "received egg file", 0xBCB = ending mission, 0xBBA/0xBBB = handled in the participant ListenToMessage at 0x628D8. (0xBC1 is the most frequent; others 0xBCE 0xBDF map to menu/toolbar commands.)

6.5 Observed mission lifecycle (from the log)

A full run for one pod, with the two state machines interleaved (Cockpit State N = pod→console; verbs = console actions):

Cockpit State 2  (present/connected)
Cockpit State 1  (ready)
Loading Mission…            → console loads the egg
Cockpit State 6
Cockpit State 7
Received egg file           → egg in hand; "Ready to translocate"
Cockpit State 8
Translocating Mission…      → console sends egg/mission to pod   (cmd code 5)
Cockpit State 9
Cockpit State 10 (in progress / running)
Stopping Mission…           (cmd code 6)
Cockpit State 11
Ending Mission…
Cockpit State 12
Cockpit at <IP> initiated close!!!   → pod closed its TCP stream
Cockpit State 3  (closed/disconnected)
Reset Mission…              → console rearms for the next departure
Cockpit State 2 …

Cockpit-state frequencies in the sample log: 1:3997 2:13258 3:12809 6:3098 7:3093 8:3262 9:2852 10:2852 11:2990 12:2890 (states 0, 4, 5 never appear in this log though the dispatch table has slots for them — likely transient/internal). Verb counts: initiated close 24702, Loading 3129, Received egg 3124, Stopping 2996, Ending 2905, Translocating 2882, Reset 953.


7. Console Log format

  • Encoding: Mac Roman. Records are CR-terminated (0x0D; classic Mac, no LF — 98,910 CRs for ~91,607 records in the sample). 0xC9 = "…" ellipsis inside the mission verbs (13,415 occurrences).
  • Record grammar: M/D/YYYY HH:MM:SSAM|PM<message> CR where <message> is usually <pod-IP> <text> (state/verb lines) or the IP-embedded form Cockpit at <pod-IP> initiated close!!!.
  • The timestamps in this capture read year 1956 — the logging Mac's clock was unset (default RTC), not a real date. Times of day are valid.
  • 72 distinct message templates; the load-bearing ones: "<IP> Cockpit State: <N>", "Cockpit at <IP> initiated close!!!", "<IP> Loading|Translocating|Stopping|Ending|Reset Mission…", "<IP> Received egg file", "<IP> Unknown message type!!!".
  • Log writer: each line is assembled by a string-append helper (0x85324, repeatedly) and flushed by 0x851C4; the leading date/time comes from the global at TOC -0x77CC(r2) (data 0x834). Field separator string is at data 0x17B8.

8. Console.ini schema

INI-style but with no newlines — sections are [Name] headers and key=value pairs run together; parse by splitting on [. Section names use a :: hierarchical namespace. 586 sections total in the live file.

Section families (by count): RP 342, BT 196, rpl4 34, NetworkEndpoint 10, Adventure 3, NetworkEndpointList 1.

Every object carries a 4-char classID (an OSType tag naming its C++ class). Confirmed: Ptcp (TCP endpoint), Advn (adventure), RPLn (Red Planet location); BT/RP scenario & vehicle classes follow the same pattern.

8.1 Network endpoints (the pods)

[NetworkEndpointList]
  networkEndpoint = NetworkEndpoint::Cockpit::Frequent Flyer
  networkEndpoint = NetworkEndpoint::Cockpit::Privateer
  … (10 active endpoints)

[NetworkEndpoint::Cockpit::Frequent Flyer]
  classID=Ptcp   hostType=0   state=0   addressUse=0
  addressIP=200.0.0.11
  defaultPort=1501   localHostPort=1501   openInterval=40   openTimeout=10
  listenTimeout=0
  resourceID=130   resourceIndex=2   pictID=308         ; STR# 130 name + PICT photo
  ; MacTCP TCP/IP ULP parameters:
  delay=1 throughput=1 reliability=1 precedence=0 fragment=0
  timeToLive=60 security=0 queryTimeout=60
  loadQueryInterval=1 inProgressQueryInterval=10

resourceID=130 + resourceIndex selects the pod's display name from STR# 130; pictID selects its photo PICT.

8.2 Adventure → Location → Scenario tree (populates the menus)

[Adventure::Solo::Red Planet]      classID=Advn  adventureType=2  resourceID=300 resourceIndex=2  list=RP::Solo::LocationList
[RP::Solo::LocationList]           location=rpl4::Solo::Location::Yip's Yahoorama …
[rpl4::Solo::Location::Wiseguy's Wake]  classID=RPLn resourceID=4000 resourceIndex=3 tag=wise pictID=601 list=RP::Wiseguy's Wake::Solo::ScenarioList
[BT::Cavern::ScenarioList]         scenario=BT::Cavern::NoReturn  scenario=BT::Cavern::FreeForAll
[BT::Solo::LocationList]           location=BT::Solo::Ravines / Arena1 / Polar4 / Cavern …

Four top-level adventures exist in the binary: Adventure::{Solo,Team}::{BattleTech,Red Planet} — matching the four console windows BTFA/BTSB/RPMF/RPMR ConsoleWindow.

8.3 Key inventory

classID, resourceID, resourceIndex, pictID, tag, list, scenario, location, default, value, max, time (structural) and the game-object keys vehicle/vehicel(sic)/vehicleClass, mechID, camo, color, texture, emblem, killMarker, experience, role, position, dropZone, weather, temperature, adventureType, language, scriptCode plus the full Ptcp network key set.

Stationary.ini is the same schema used as a template to regenerate a site's Console.ini; the per-city ini Folder/DB<City> files are venue overrides.


9. Apple Events

The app installs standard AE handlers (AEInstallEventHandler) and is a full AppleScript object-model server (ObjectSupportLib + UAppleEventsMgr.cp). Its aete (id 0, "English") declares only the standard suites — Required (reqd: run/open/print/quit), Standard/Core (CoRe: close/get/set/make/save/ data size), and Miscellaneous Standards (misc: revert/select) — over the generic application/window/document classes. aedt (3) = Required Suite, Core Suite, Misc Standards.

Conclusion: Apple Events are used for OS/Finder integration (open-documents = open mission/ini files, print score sheets, quit), not for commanding pods. Pod command is exclusively the MacTCP protocol in §6. (No custom application scripting suite is defined.)


10. Tooling written (410console/tools/)

Reusable, dependency-light (Python 3.13 + capstone):

  • pefparse.py — PEF container parser + PIDATA (RLE) unpacker + loader (imports/exports/entry) + string extractor + capstone PPC disassembler. header | loader | strings [minlen] | dump <sec> <off> <len> | dis <sec> <off> <count>.
  • ppcxref.py — TOC-aware annotator (r2 = data 0x8000): resolves r2-relative constant loads to data addresses/strings and builds a string→code cross-reference. annotate <start> <count> | xref <substr> | toc <off>.
  • rsrcparse.py — classic Mac resource-fork parser (reads the AppleDouble ._ sidecar). map | names <TYPE> | strn [id] | dump <TYPE> [id].

Example: py -3.13 tools/rsrcparse.py "4_10-console-extracted/__MACOSX/._Console 4.10" strn 131.


11. Confidence & open questions

High confidence (multiple corroborating sources):

  • Fat PEF/PPC app, PowerPlant/CodeWarrior, FASA Interactive, creator vwe4, vers 2.4.0b3. (PEF header + resource fork + strings.)
  • MacTCP .IPP, port 1501, per-pod TCP, addressing scheme. (imports + CTCPDriver/.IPP string + ini + log.)
  • Cockpit State machine 012, pod→console, dispatch at 0x63B3C, stored at Participant +0x289, logged verbatim. (disasm + jump table + log stats.)
  • Send framing = 16-byte header + payload; command payload byte[0]=size, byte[4]=code; Translocate=5, Stop=6. (disasm of 0x629EC + two ctors.)
  • Mission lifecycle ordering. (log, thousands of runs.)
  • ini schema and 4D-database backend. (ini + STR#/eTbl + error strings.)

Open questions / next steps:

  1. Finish the command-code table. Pin byte[4] for Load, End, Reset, Get-Next-Departure (method: disassemble each sender's object ctor near 0x3EBxx0x3EFxx for li r0,N; stb r0,-0x10(r1)). Also decode the header word-2 (0x3CB38) — sequence counter vs. timestamp.
  2. Header semantics. Confirm whether the pod reads packet byte[0] (class=4) or a payload byte as its "message type", and map the console's command codes to the resulting Cockpit State transitions (5→9, 6→11 observed).
  3. Egg transfer mechanism. Determine whether the .egg mission bundle (note the Egg.ini string at data 0x98E9, and the MUNGA segment) travels to the pod over the same 1501 stream during "Translocate", or via a separate transfer. Received egg file is logged console-side — clarify direction (console reads egg from disk vs. receives from DB/pod).
  4. States 0/4/5. Never seen in this log; identify their handlers (jumptable[0]=0x63BEC default, [4]/[5]=0x63B78) and meaning.
  5. 4D protocol. Out of scope here (proprietary ACI 4D client); the console↔ 4D link governs scheduling ("Get Next Departure") and the pilot roster.
  6. Relocations. pefparse does not yet apply the Loader relocation opcode stream (reloc_instr_offset); constant addresses were resolved via the TOC value instead, which was sufficient. A full reloc pass would make every data pointer absolute for deeper xref.

Appendix A — key addresses (code section, base 0)

Addr Role
0x82E5C program main (via TVector @ data 0x5154)
0x63B3C received-message dispatch (msg&0xFF → jumptable @ data 0x17B1C)
0x62720 SetCockpitState(participant, state) → Participant +0x289, broadcast 0xBBC
0x62778 GetCockpitState (lbz +0x289)
0x629EC NetworkEndpoint::Send (16-byte header + payload)
0x397480x3BD28 CTCPStream::Write
0x3EC74 / 0x3ECC8 Translocate (code 5) / Stop (code 6) command-object ctors
0x66464 / 0x67438 / 0x6755C / 0x6769C / 0x648C0 senders: Ending / Translocating / Stopping / Reset / Received-egg
0x85324 / 0x851C4 log-line append / flush
data 0x8000 TOC base (r2)
data 0x17B1C 13-entry cockpit-message jump table

Appendix B — reproduce

cd c:\VWE\TeslaRel410\410console
py -3.13 tools\pefparse.py "4_10-console-extracted\Console 4.10" loader
py -3.13 tools\ppcxref.py xref "Mission"
py -3.13 tools\ppcxref.py annotate 0x629ec 0x60
py -3.13 tools\rsrcparse.py "4_10-console-extracted\__MACOSX\._Console 4.10" map
py -3.13 tools\rsrcparse.py "4_10-console-extracted\__MACOSX\._Console 4.10" strn 131