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>
28 KiB
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 (68KCODEresources + PowerPC PEF/CFM fragment in the data fork). - Internal identity: type
APPL, creatorvwe4, version resource2.4.0b3/ "Console 2.4.0b3", © 1995–1997 FASA Interactive, Inc. (The "4.10" in the folder name is the site/config release, not the app's ownvers.) - 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:
- Pod command/control — one MacTCP TCP stream per pod on port 1501
(console
200.0.0.1, pods200.0.0.11–200.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 (0–12) that the console records inConsole Log. - 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_Find4DServererror 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 APPLvwe4 → type 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]. Somainexecutes at code0x82E5Cand the runtime TOC/r2= data offset0x8000. (This TOC value is the key that lets us resolve allr2-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 …— readsConsole.ini, writesConsole Log, loads/saves mission egg files. - Device Manager (→ MacTCP):
PBOpenSync,PBControlAsync,PBControlSync— open the.IPPdriver 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", © 1995–1997 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 1000–1011): 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 matchpictID=inConsole.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:Mission data is incomplete.The mission is ready to load.The mission is being loaded.The mission is ready for translocation.The mission is being translocated.The mission is in progress.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 Log → Console.ini.
6.1 Transport
- Custom C++ classes
CTCPDriver/CTCPStream/CTCPEndpoint/CTCPAsyncCall/CTCPResolverCallwrap MacTCP. The literal driver name.IPPappears at data0x1053Fright next toCTCPDriver— this is the classic MacTCP IP driver opened withPBOpenSync, then driven withPBControlAsync/Sync. - One TCP connection per pod. From
Console.inieach[NetworkEndpoint::Cockpit::*]setsclassID=Ptcp,defaultPort=1501,localHostPort=1501, and the pod'saddressIP(200.0.0.11…200.0.0.117, etc.). Console host =200.0.0.1; pods200.0.0.11–200.0.0.120(from the log). The manyPtcpsub-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, 0–12; 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 0–12 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 0xBBA–0xBDF (decimal
3002–3039). 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/YYYYHH:MM:SS␠AM|PM␠<message>CRwhere<message>is usually<pod-IP> <text>(state/verb lines) or the IP-embedded formCockpit 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 by0x851C4; the leading date/time comes from the global at TOC-0x77CC(r2)(data0x834). Field separator string is at data0x17B8.
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= data0x8000): resolvesr2-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/.IPPstring + ini + log.) - Cockpit State machine 0–12, 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:
- Finish the command-code table. Pin byte[4] for Load, End, Reset,
Get-Next-Departure (method: disassemble each sender's object ctor near
0x3EBxx–0x3EFxxforli r0,N; stb r0,-0x10(r1)). Also decode the header word-2 (0x3CB38) — sequence counter vs. timestamp. - 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).
- Egg transfer mechanism. Determine whether the
.eggmission bundle (note theEgg.inistring at data0x98E9, and the MUNGA segment) travels to the pod over the same 1501 stream during "Translocate", or via a separate transfer.Received egg fileis logged console-side — clarify direction (console reads egg from disk vs. receives from DB/pod). - States 0/4/5. Never seen in this log; identify their handlers
(
jumptable[0]=0x63BECdefault,[4]/[5]=0x63B78) and meaning. - 4D protocol. Out of scope here (proprietary ACI 4D client); the console↔ 4D link governs scheduling ("Get Next Departure") and the pilot roster.
- Relocations.
pefparsedoes 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) |
0x39748→0x3BD28 |
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