# 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", © 1995–1997 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.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 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/` | — | 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]`. 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", © 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 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), `` = 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` / `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.11`…`200.0.0.117`, etc.). Console host = `200.0.0.1`; pods `200.0.0.11`–`200.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 `" Cockpit State: "`. 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 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:SS`␠`AM|PM`␠`` `CR` where `` is usually ` ` (state/verb lines) or the IP-embedded form `Cockpit at 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: `" Cockpit State: "`, `"Cockpit at initiated close!!!"`, `" Loading|Translocating|Stopping|Ending|Reset Mission…"`, `" Received egg file"`, `" 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` 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 | dis `. - **`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 | xref | toc `. - **`rsrcparse.py`** — classic Mac resource-fork parser (reads the AppleDouble `._` sidecar). `map | names | strn [id] | dump [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 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:** 1. **Finish the command-code table.** Pin byte[4] for Load, End, Reset, Get-Next-Departure (method: disassemble each sender's object ctor near `0x3EBxx–0x3EFxx` 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) | | `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 ```