Networking: decode egg-delivery protocol from source; archive console SW

Decoded the console<->pod message layout from the MUNGA framework headers
(the send/recv impl did not survive -- only headers + a test harness):
NetworkPacket = 16B NetworkPacketHeader + a Receiver::Message; the egg is
delivered as ReceiveEggFileMessage chunks (seq/totalLen/thisLen +
notationData[1000]), a full egg packet = 1040B (matches the VPX nb<=1040
cap). Console splits the mission notation file into <=1000B chunks; pod
reassembles + ACKs. Two bytes-on-the-wire details (stream framing +
PPC/x86 endianness) flagged for the first live capture. Full byte tables
in NET-NOTES.md.

Also moves the extracted console software (Console 4.10 PPC app + per-venue
Console.ini + fonts/logs, resource forks preserved) into
410console/4_10-console-extracted/.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Cyd
2026-07-04 22:21:06 -05:00
co-authored by Claude Fable 5
parent 5b44ede702
commit e1d44251da
80 changed files with 84 additions and 0 deletions
+68
View File
@@ -198,6 +198,74 @@ pod "Puck". Remaining protocol unknown is just the on-stream message
framing (NetworkPacketHeader + ReceiveEggFileMessage) — capture it once
the console connects, or read it from network.hpp.
## Egg-delivery protocol — decoded from source (2026-07-04)
Decoded from `CODE/RP/MUNGA/{NETWORK,RECEIVER,HOSTID}.HPP` +
`MUNGA_L4/L4NET.HPP`. The real send/receive *implementation* (framing on
the byte stream) did NOT survive in the archive — only headers + a test
harness (`L4NET.TCP`'s `TestClass`, `#if 0`). So the logical message
layout below is solid; two low-level details (stream framing + endianness)
need a live capture or a binary disasm to pin — see caveats.
**Transport:** console → TCP connect to pod IP : **1501** → the pod
(NetNub `TCP_LISTEN`) accepts. All base types are 32-bit
(`Enumeration=int`, `size_t`, `LWord`, `Time::ticks=long` → 4 bytes each).
**On-wire unit = NetworkPacket = NetworkPacketHeader + a Receiver::Message.**
NetworkPacketHeader (16 bytes):
| off | field | type |
|--|--|--|
| 0 | clientID | ClientID enum (0=NetworkMgr,2=HostMgr,5=Console...) |
| 4 | gameID | Enumeration |
| 8 | fromHost | HostID (Enumeration) |
| 12 | timeStamp | Time (long ticks) |
Receiver::Message header (12 bytes) that every message starts with:
| off | field | type |
|--|--|--|
| 0 | messageLength | size_t (= sizeof the whole message) |
| 4 | messageID | Enumeration (ReceiveEggFileMessageID etc.) |
| 8 | messageFlags | LWord (bit0 ReliableFlag=1) |
**ReceiveEggFileMessage** (the egg carrier; messageLength = 1024):
| off | field | type |
|--|--|--|
| 0 | (Receiver::Message header) | 12 B |
| 12 | sequenceNumber | int (chunk index) |
| 16 | notationFileLength | int (total egg size) |
| 20 | thisMessageLength | int (bytes valid in this chunk, ≤1000) |
| 24 | notationData[1000] | char (the egg chunk) |
So a full egg packet on the wire = **16 (header) + 1024 (message) = 1040
bytes** — matches the `nb≤1040` payload cap seen on the VPX/iserver link.
**Egg-delivery algorithm:** the console splits the mission egg (a text
"notation file", same INI/notation format as Console.ini) into
ceil(len/1000) chunks; sends each as a ReceiveEggFileMessage with
sequenceNumber 0..N, notationFileLength=total, thisMessageLength≤1000. The
pod's `ReceiveEggFileMessageHandler` reassembles into `eggTempBuffer` by
sequence, and when `notationFileLength` bytes have arrived, parses it as
the mission notation file. Pod replies `AcknowledgeEggFileMessage`
("connected, ready, next host"). `messageID` values start at
`NetworkClient::NextMessageID`; ReceiveEggFileMessageID is the first
NetworkManager message ID.
**Caveats to confirm with the first live capture (or a binary disasm of
Console 4.10 send / BTL4OPT receive):**
1. *Stream framing:* whether each 1040-B NetworkPacket is one discrete
NetNub/WATTCP record, or the receiver frames within the TCP stream via
the leading `messageLength`. (NetNub `RECEIVE_PACKET` returns up to
1600 B; MAX aligns with one packet.)
2. *Endianness:* console is **big-endian PPC**, pod is **little-endian
x86** — the multi-byte header/length ints must be byte-swapped by one
side (or sent in network order). `notationData` (egg text) is
endian-agnostic. The capture will show which order the length fields
use; a stand-in sender must match it.
Everything needed to PARSE a capture and BUILD a stand-in egg-sender is
here except those two bytes-on-the-wire details, which the console-connect
milestone resolves immediately.
## Open questions / notes
- Exact TCP listen port(s) — not in the source grep; get from NETNUB.EXE
or a capture at milestone 3.