Files
TeslaSuite/410console/CONSOLE-4.10-DECOMP.md
T
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

555 lines
28 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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.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** (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 `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", © 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 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
`"<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 **`0xBBA``0xBDF`** (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:SS`␠`AM|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) |
| `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
```