From e12bfe1d3a6c97ffeae86ebc9f3f7f4b2943a5c6 Mon Sep 17 00:00:00 2001 From: Cyd Date: Sun, 5 Jul 2026 17:41:34 -0500 Subject: [PATCH] NET milestone: real console->pod mission egg over the wire (+ mission-load crash) Captured a real mission egg delivered from the SheepShaver console to the DOSBox pod on TCP 1501, no -egg bypass: 8x ReceiveEggFileMessage chunks, 7514 bytes, reassembled byte-perfect (declared notationFileLength=7514). The egg is the operator's own mission (BattleTech / cavern / night / freeforall, pilot "cyd", vehicle madcat). This closes the networking workstream end to end. - net-tools/decode_egg.py: reassemble an egg from a captured console->pod TCP payload hex dump (skips interleaved StateQuery polls). - net-tools/captured_cavern_mission.egg: the delivered egg. - NET-NOTES.md: milestone writeup + the pod's mission-LOAD crash. The pod faults loading the mission (page fault, wild ptr 0xFF008B5B, exception 000E at game 00FF:219D, NetNub Munga exit 14) -- a game-side bug in the mission-load path, separate from networking. Leading suspect: RIO was disabled for this run and the player vehicle/control setup derefs null. Co-Authored-By: Claude Opus 4.8 --- emulator/NET-NOTES.md | 32 ++++++++++++++ .../net-tools/captured_cavern_mission.egg | Bin 0 -> 7514 bytes emulator/net-tools/decode_egg.py | 39 ++++++++++++++++++ 3 files changed, 71 insertions(+) create mode 100644 emulator/net-tools/captured_cavern_mission.egg create mode 100644 emulator/net-tools/decode_egg.py diff --git a/emulator/NET-NOTES.md b/emulator/NET-NOTES.md index e18f8f5..9b11df8 100644 --- a/emulator/NET-NOTES.md +++ b/emulator/NET-NOTES.md @@ -340,6 +340,38 @@ with a full RIO+sound boot (`net_full.conf`) so the pod presents its normal state (applicationState may change when fully booted). Need the console UI readout to know what state it wants before it will send the mission egg. +## EGG DELIVERED OVER THE WIRE (2026-07-05) — headline goal achieved + +The real SheepShaver console sent a real mission egg to the real DOSBox pod +over the emulated network, captured + reassembled byte-perfect: +- Console -> pod, TCP 1501, **8x ReceiveEggFileMessage chunks** (1040-B + NetworkPackets each = 16 hdr + 1024 msg), **7514 bytes total**, declared + notationFileLength=7514 (exact match). Reassembled with + `net-tools/decode_egg.py`; saved `net-tools/captured_cavern_mission.egg`. +- The egg is a text NOTATION file (same format as Console.ini). Contents = + the operator's actual mission: `[mission] adventure=BattleTech map=cavern + scenario=freeforall time=night weather=clear temperature=27 length=120`; + `[pilots] pilot=200.0.0.113`; `[200.0.0.113] name=cyd vehicle=madcat + experience=veteran badge=VGL dropzone=one color=Grey advancedDamage=1 + role=Role::Default` + embedded pilot badge bitmaps + ordinal fonts. +- Confirms the whole decoded protocol end to end: StateQuery/StateResponse + poll, then egg chunks, pod ACKs, no `-egg` bypass. **Networking DONE.** + +**BUT the pod CRASHES loading the mission** (game-side, NOT network): +`nn.log` shows `Reference to a page you don't own / PF cr2=FF008B5B / +Unhandled exception 000E at 00FF:219D ErrCode 0004 / NETNUB Munga exited +code 14` -- a page fault (wild pointer 0xFF008B5B) in the mission-load path +right after the egg arrives. Suspects: (a) RIO was DISABLED for this run +(net_pcap.conf) and the mission sets up the player's vehicle (madcat) / +controls, which may deref a null RIO/control struct; (b) missing cavern +content or a pilot-config/badge path bug. Note: cavern/night via `-egg +test.egg` with RIO ENABLED rendered fine earlier this session, so RIO-off +is the leading suspect. Real pods run RIO-on headless (no focus stealing), +so this may not reproduce there. NEXT: retry with RIO enabled + DOSBox +`priority=highest,highest` (so clicking the console can't starve the RIO's +ACK deadline during load); if it still faults, disassemble around game +code 00FF:219D. This joins the Division-renderer/crash workstream. + ## Open questions / notes - Exact TCP listen port(s) — not in the source grep; get from NETNUB.EXE or a capture at milestone 3. diff --git a/emulator/net-tools/captured_cavern_mission.egg b/emulator/net-tools/captured_cavern_mission.egg new file mode 100644 index 0000000000000000000000000000000000000000..7e6276238d7b2a39b47c6b4efbcd26a3973331aa GIT binary patch literal 7514 zcmeI1U2mf}6o&naRuD&pM&f2tJU6piX?8R>Q7=5fZIB2=gm&8f_4^(h8;4+$(ax+! zRf$?+`{5jazCJjceR({VO?}T~@vQ3Zsa4qr*>#orqP9D>mxpXCpH*A4<5tzOEt~A2 zRqCN>WmU1R+^eiEA9o%5u4K1UZMLnHY+0xF2h~b#ZjrD`)sNjSix&~wG;LAVvO3mhfQ7l5NgCIOoxY%bLA_MQ@TzbgT2e?OgO;Buw-iXV&ePYB#uqW1uFvWZw=X?#{$=x}}MQ%BG&iNgD z3wqFR2ka&3!q!i7U_eiBRBCFkIWRFk=k|P#uT34NxZJasq(P1gw9@(&(F~_+qe(mv zOU?Mknld;9|@I%}w?561B7Ai?JXM^Jb!-k#`NpX?~b#$9sEG zayzzXJ9y%LGG8XjZPstky+Dmq_L}hp`(73h=X63R7wDt$pj~Q-9@2s3xS^EAd+#80%5rXPl{VCCOqcVPjh08bx+PXpk;*Myr09Gp0$vPTRX2*$Z&gd%AwMp9382W5gwH+~AO7+{S(rvv*wN zFpbC_%^BU#PG-7pwApUh}kGlbYe6y~J3+WoD6E004!u@leJ?aIQPxjC=F8vF+<&}QX&}-_aJI>Xc z`Wa8TwAT(j|Ew+&hyI(^Nz6Bo!-hDdJ$tn8J6(i5yo(HJkE5dC^=7!MbaMHwlYyBq z%mWgP)af1Jm}f3M!{Hq_$m#XayC%-12YV<@hI~qyc#Y)qBwmXmdI#%uk+?JvPsZz! zP6pyhj(0L&Cr$iE%k|VR;t}GkPV(DnokTNCJLq{_uDxS>6f{{~1cx|uNc;UV;-DLo zoDRY~dlVo$`<^{|;dS}&OV(Wa7jkaj>-$9n>PMWff7D)=_Ubq0^!&5BIpTbsJkd>$ zqp=EJZ-$%F$wOH+9S%hGJzGT4AM}Z1&Ng1+p6!}r_vQ7VvWQM=WxZ9!o!rYumBp-T zWbsc^t0TVG634RJ*P`#VvMv{)dW1M>lyyowyByn``D^ic97k6mwi?RYa5vPjDM@uoqCW@RmV1!Y#)_5 z<#obu4|zXP*=j|#+??k*JUAixf;TfSOgCl!rMgkQH>v=m& z{?L#KF3#87{+L4`k8W_C+w<~uA;-d-=3IWy#px7>qqNlbOP>2{)DD+#%k7=LWH(D3 cm&Z5#aXEfgJlXB;*}f@Ml@$+FM|&ar7cUeA?*IS* literal 0 HcmV?d00001 diff --git a/emulator/net-tools/decode_egg.py b/emulator/net-tools/decode_egg.py new file mode 100644 index 0000000..5b7d8d6 --- /dev/null +++ b/emulator/net-tools/decode_egg.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +"""Reassemble a mission egg from a captured console->pod TCP stream. + +Input: a hex dump of the concatenated console->pod TCP payloads, e.g. + tshark -r cap.pcapng -Y 'ip.src== && tcp.len>0' \ + -T fields -e tcp.payload | tr -d '\n' > c2p.hex + +The console delivers the mission as a series of ReceiveEggFileMessage +packets (decoded from CODE/RP/MUNGA/NETWORK.HPP, wire is little-endian): + NetworkPacketHeader (16B) + Receiver::Message hdr (12B: messageLength@+16, + messageID@+20, flags@+24) + [egg body when messageLength==1024: + sequenceNumber, notationFileLength, thisMessageLength, notationData[1000]]. +StateQuery packets (messageLength=16) are interleaved and skipped. + +Usage: python decode_egg.py c2p.hex out.egg +""" +import sys, struct + +data = bytes.fromhex(open(sys.argv[1]).read()) +out = sys.argv[2] if len(sys.argv) > 2 else "reassembled.egg" + +i, chunks, total = 0, {}, None +while i + 28 <= len(data): + mlen, mid = struct.unpack(" 4000: + break + pkt = data[i:i+16+mlen] + if len(pkt) < 16 + mlen: + break + if mlen == 1024: # ReceiveEggFileMessage + seq, flen, tlen = struct.unpack("= total} -> {out}")