Files
TeslaRel410/emulator/vpx-device/ethernet_steam.h
T
CydandClaude Fable 5 f2687a3146 BT410 5.3.72: the fault caught in the act; the inside view gets its cockpit
VPX_PF_WATCH (fork, cpu/paging.cpp): on a guest page fault at the watched
linear address, dump guest registers, the last 64 serial RX deliveries with
guest cs:eip at each, the code bytes at the faulting EIP and the stack top.
serialnamedpipe's doReceive feeds the ring.  Armed in podrun.sh and
launch_pod.ps1.

The first catch decoded the residual fault completely: CS:EIP 00FF:000066D4
in the DPMI host, EBX = F000CA60 -- an IVT entry read as a dword, segment
F000 offset CA60, a BIOS default interrupt handler -- and the faulting access
is [EBX+0x3004], whose 0x80000000 segment-base wrap gives exactly cr2
7000FA64.  The host probes a word 0x3004 bytes past a real-mode vector value
treated as a flat pointer: harmless for its own low-memory handlers, a fault
for BIOS F000:xxxx defaults.  The serial ring shows a steady 1-byte/1-3ms
vRIO stream with nothing special at the fault -- the stream determines which
vectors get walked, not the crash itself.  The 0x3004 appears nowhere in
DPMI32VM.OVL or 32RTM.EXE as an immediate, so the probe now also dumps code
bytes at EIP; faulthunt.sh loops runs until the next catch.

Shipped baseline streak: 4/4 clean -- consistent with exposure, not yet
discriminating.

The inside view now loads the COCKPIT skeleton: the fleet-wide X-variant
naming convention (MAD->MAX etc., all 64 skeletons present) selects the same
25-joint chain with a single object -- max_cop.bgf, the MAX_COP canopy shell
with the PUNCH-texel windows from the capture forensics.  The donor names the
same mechanism from the decomp side (inside = SkeletonType_A with '_cop'
selection).  Fallback to the body skeleton when no X file exists.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-29 18:09:22 -05:00

58 lines
2.2 KiB
C++

/*
* VWE fork: NE2000 backend that tunnels guest Ethernet frames over Steam
* (`backend=steam`), so a private group can fly missions over the internet.
*
* Why L2 and not an ordinary L3 tunnel: the 1995 mesh (WATTCP + netnub +
* L4NetworkManager) dials peers by raw IP on one flat subnet and ARPs for
* them, so whole FRAMES have to cross the internet for the DOS binaries to
* see the same-switch world they were built for.
*
* All of the transport lives in vwesteam:: (steamlink.h) and is shared
* VERBATIM with the host's steam<->pcap gateway; this class is only the
* EthernetConnection adapter -- config resolution, the receive-side
* acceptance policy, and the log lines. Steamworks is bound at runtime in
* there, exactly as the pcap backend binds WPCAP.DLL, so a build on a machine
* with no SDK still runs and just fails Initialize() with a readable reason.
*
* Only REMOTE players run this. The session host's pod stays on
* backend=pcap and reaches the tunnel through the gateway, which is what
* keeps exactly one process per machine on ISteamNetworkingMessages.
*
* Conf: [ne2000] backend=steam, macaddr=<stable MAC, never "random">
* [ethernet, steam] peers= lobby= session= channel=
* Contracts: ../steam/SESSION-CONTRACT.md (session file, env, addressing).
*/
#ifndef DOSBOX_ETHERNET_STEAM_H
#define DOSBOX_ETHERNET_STEAM_H
#include "config.h"
#ifdef WIN32
#include "ethernet.h"
#include <stdint.h>
/** A Steam-P2P Ethernet connection
* Carries raw Ethernet frames to the other pods in the session over
* SteamNetworkingMessages instead of over a host NIC. Needs Steam running,
* a stable [ne2000] macaddr, and a peer roster (session file, csv or lobby).
*/
class SteamEthernetConnection : public EthernetConnection {
public:
SteamEthernetConnection();
~SteamEthernetConnection();
bool Initialize(Section* config) override;
void SendPacket(const uint8_t* packet, int len) override;
void GetPackets(std::function<void(const uint8_t*, int)> callback) override;
private:
uint8_t mac[6] = {}; /*!< [ne2000] macaddr; the RX filter's "ether dst self" */
bool up = false; /*!< Init() took -- gates the refcounted Shutdown() */
};
#endif
#endif