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:
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user