Commit Graph
302 Commits
Author SHA1 Message Date
CydandClaude Opus 4.8 a24210adf0 M5 integrate: recognizable arena interior -- verified divide makes texturing land
render_final.py applies the oracle-verified perspective divide (texel8 =
texu/texz*2048, the *8 from the '3 integer bits') with per-quad texel tiling.
The battle frame now reads as a real first-person arena interior: a tiled
floor receding correctly to the vanishing point (panels shrinking toward the
horizon), a paneled ceiling, and a horizon band of structures. The verified
divide fixed the tiling frequency that washed out earlier attempts.

Monochrome because surfaces map to one texture family -- the exact
texid->handle binding needs the board texture-RAM model (texels go to board
tex memory via TXDN/io, not watchable DRAM; confirmed by the storage trace).
Geometry, perspective, texel decode, and the divide are all solved from the
live wire; per-surface texture selection is the last remaining piece.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-19 22:15:44 -05:00
CydandClaude Opus 4.8 b74b0c89e8 M5-A: the faithful IGC perspective divide, verified against the divlogo oracle
igc_divide.py implements EOF.C's texdivide bit-serial restoring division on
the pixel bit-memory, and extracts the texel per the '3 int | 8 texel | 5
subtexel' result layout ((field>>9)&0xff). Verified against the divlogo's
KNOWN mapping (u:0.001->0.999 across screen x[532,660]): the extracted texel
sweeps monotonically 0->251, and a fast float equivalent (texu/texz*2048)
tracks the bit-serial result to +/-1. This fixes the missing scale factor
(the '3 integer bits' = x8) that made earlier renders wash out. M5 plan in
M5-TEXTURING.md. Next: M5-B scene-graph material binding, then integrate.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-19 22:13:10 -05:00
CydandClaude Fable 5 efc41f165b Mech milestone: reconstruct NameFilter (helper 3/3) -- helpers phase complete
NameFilter is the Mech's mechNameFilter (@0x36c), a small fixed debounce record
the ctor initialises. Reconstructed from FUN_00435a7c: a 10-word (0x28) struct,
Initialize() sets [2]=1 / [8]=[9]=-1 / rest 0 exactly. Header-only. Field
semantics unresolved (only caller is Initialize; reader is the unbuilt HUD) --
names best-effort, but size + init values are binary-exact, which is all the
Mech layout + ctor need.

All 3 missing embedded helper classes now reconstructed + compile-verified under
BC4.52 (AlarmIndicator, SequenceController struct+Init, NameFilter). MECH-LAYOUT.md
step 1 marked done. Next: MechSubsystem base + the subsystem roster, then finalize
MECH.HPP (probe sizeof==0x854), then the ctor + segment-table walk.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 20:56:06 -05:00
CydandClaude Opus 4.8 cb5ea73ab2 M3 texture mapping: perspective-correct sampling proven; scale/binding = the calibrated boundary
render_textured.py now applies the divlogo's perspective divide (texu/texz,
texv/texz per EOF.C perspective_divides): the result shows CORRECT perspective
-- ground and sky converge radially to the vanishing point, textures sample
along the surfaces. Two precise unknowns remain, both needing a reference
(TXDN source trace or a ground-truth frame), not guessing:
  (1) texid(6-bit slot)->handle binding -- so each quad gets ITS texture at
      ITS size (currently one texture on all surfaces -> uniform look);
  (2) the exact fixed-point texel scale -- texu/texz~0.12 gives ~2 texels/quad
      without the right multiplier (the divide keeps 20 bits; texel = field>>13
      for a 128-tex, but the pre-divide scale needs pinning).
Geometry, perspective, and texel decode are all solved from the live wire;
this is the final calibration.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-19 20:54:20 -05:00
CydandClaude Fable 5 bc59e39f41 Mech milestone: reconstruct SequenceController (helper 2/3), struct+Init verified
The BT keyframe-animation player embedded in the Mech as legAnimation/
bodyAnimation. Struct field layout (from BT411's binary-offset map), default
ctor, dtor, and Init(Mech*) reconstructed and compile-verified; Init is
ctor-time (Mech ctor calls legAnimation.Init(this)/bodyAnimation.Init(this)) so
it's real (binds owner + caches owner->GetJointSubsystem()). The per-frame gait
engine (SelectSequence/Advance/Reset) is staged with Fail bodies -- it fires
only once the mech is ticking, past the current ctor frontier.

BT stage 23 ok; full tree still links clean. Evidence + real/staged split in
SEQCTL.NOTES.md.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 20:53:54 -05:00
CydandClaude Fable 5 9a4f1c293b Mech milestone: reconstruct AlarmIndicator (helper 1/3), compile-verified
First of the 3 missing Mech embedded-helper classes. AlarmIndicator is the
multi-level status indicator the Mech carries four of (master/heat/stability/
status). Reconstructed as a StateIndicator subclass: the shipped ctor
(@0041b9ec) is byte-for-byte the surviving StateIndicator(unsigned) ctor
(stateCount=oldState=currentState=count; 3 watcher sockets NULL) with a distinct
vtable, so a derived class reproduces it exactly and adds the level API
(SetLevel/GetLevel/GetLevelCount -> SetState/GetState/stateCount). Header-only
(StateIndicator's methods are in SIMULATE.CPP, already in munga.lib).

Compile-verified standalone under BC4.52 with the authentic build flags.
Evidence + placement in ALARM.NOTES.md.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 20:49:26 -05:00
Cyd 26e08a39f7 Fix cross-links in imported RIO docs after the move
Sibling links (hardware<->firmware) now resolve within restoration/;
links to RIOjoy's PROTOCOL.md and Win32RIO/ (which stayed in the RIOjoy
repo) point to gitea web URLs.
2026-07-19 20:48:22 -05:00
Cyd 6bf0ff524d Import RIO board hardware docs from RIOjoy repo (history preserved)
Board photos, scanned schematics, and GAL fuse-map decode of the
physical RIO board set.

git-subtree-dir: restoration/rio-hardware
git-subtree-mainline: def5840e07
git-subtree-split: 42b3944ebe
2026-07-19 20:45:18 -05:00
Cyd def5840e07 Import RIO board firmware from RIOjoy repo (history preserved)
Board firmware dumps, disassembly, make_patch.py, patched images
(RIO 4.3 + FastRIO), analysis, and bench testlogs — moved from the
RIOjoy repo into the Tesla cockpit restoration archive.

git-subtree-dir: restoration/rio-firmware
git-subtree-mainline: 6c0dfcf792
git-subtree-split: 4fb91775fc
2026-07-19 20:45:16 -05:00
CydandClaude Fable 5 6c0dfcf792 Mech layout: correct AverageOf status (survives) -> 3 missing helpers
Full-archive re-check: AverageOf DOES survive (AVERAGE.HPP, the SIGNATURED
lineage BT411 preserved), so telemetryFilter[5]'s type is available. The
genuinely-missing embedded helpers are just AlarmIndicator, SequenceController,
and NameFilter (confirmed absent from all of CODE; no alarm/filter/sequence
headers) -- to be reconstructed from BT411 decomp before the Mech layout finalizes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 20:43:02 -05:00
CydandClaude Fable 5 f3668d6dbf Mech milestone: foundational layout analysis + proxy-layer resolution
Begins the Mech reconstruction milestone (analysis phase). Extends the existing
MECH-LAYOUT.md worksheet with the findings needed to build MECH.HPP + the ctor:

- Resolved the BT411 mechrecon.hpp proxy layer to real 1995 types (ReconAlarm ->
  AlarmIndicator, ReconSeq -> SequenceController, ReconFiltered -> AverageOf<
  Scalar>/NameFilter, ReconChain -> ChainOf, ReconMatrix -> AffineMatrix;
  StateIndicator/Reticle survive as-is; BTVal mostly base-class pose fields).
- CRITICAL: AlarmIndicator, SequenceController, NameFilter, AverageOf are ALSO
  absent from the 4.10 archive -- additional helper classes the milestone must
  reconstruct first (their sizes set the embedded-member offsets).
- Subsystem source availability mapped: full (GAUSS/PPC/SENSOR), .TCP partials
  (AMMOBIN/EMITTER/GNRATOR/HEAT/MISSILE/PROJTILE/PROJWEAP), decomp-only (rest).
- Key tractability insight: StateIndicator is fixed-size (level count stored, not
  arrayed), so a FUNCTIONAL fresh build needs only the right member set/types in
  order -- byte-exact offset matching is a later refinement for network wire
  format, not required to boot.
- Revised reconstruction order: helpers -> MechSubsystem+roster -> finalize
  MECH.HPP (probe sizeof==0x854) -> ctor+segment walk -> per-frame path.

Everything below the Mech ctor runs real reconstructed code; the ctor is the
live frontier (spawn factory validated last commit).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 20:40:43 -05:00
CydandClaude Fable 5 e610a2a3aa 4.10 reconstruction: real spawn factory path -> Mech ctor frontier
BTPlayer::CreatePlayerVehicle reconstructed (faithful; BT411's BT_SPAWN_XZ/
BT_SPAWN_ENEMY bring-up scaffolding dropped): builds the Mech::MakeMessage from
the mission game-model resource and hands it to MakeAndLinkViewpointEntity.
Mech::Make = new Mech(creation_message); a staged Mech ctor chains the real
JointedMover base (so the model skeleton/segments stream from BTL4.RES) then
Fails.

This validates the entire spawn factory chain live: CreatePlayerVehicle ->
MakeAndLinkViewpointEntity -> registry -> Mech::Make -> new Mech -> JointedMover
base ctor (streams the mech model) -> halts at the Mech ctor (mech.cpp:66).

The Mech ctor (@004a1674, 5690 bytes -- the largest function in the game) plus
the subsystem roster is the next MAJOR milestone, not a brick: it needs the full
1995 Mech member layout derived first (MECH.HPP is still reserved[331]; BT411's
decomp uses raw offset pokes that can't compile fresh), the subsystem class
hierarchy (only GAUSS/PPC/SENSOR survive in the 4.10 archive; the rest are the
measured "917 missing functions"), and the segment-table walk. Plan + scope in
MECH.NOTES.md.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 20:33:15 -05:00
CydandClaude Fable 5 956fc57681 4.10 reconstruction: BTPlayer message-handler table + DropZone spawn dispatch
Fixes the incorrect DefaultData reuse of Player::MessageHandlers -- BTPlayer now
has its own handler table (DropZoneReply, VehicleDead, Score, ScoreInflicted,
ScoreUpdate; the last two add BT message IDs) chained onto the base set, matching
the .data table recovered in BT411. A mission-start DropZoneReply now routes to
BTPlayer::DropZoneReplyMessageHandler (the real spawn/respawn dispatch skeleton)
instead of the base "should not be handled by base player class" Fail stub.

Boot ladder now runs the full engine + app + network + mission + player path and
reaches the spawn handshake, halting at CreatePlayerVehicle -> Mech::Make -- the
Mech subsystem frontier (Mech ctor + mech2/3/4 + subsystems + weapons), the next
major reconstruction milestone. Scoring/death handlers, PlayerSimulation, and the
mech-placement tail staged with documented Fail bodies (BTPLAYER.NOTES.md).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 20:24:27 -05:00
CydandClaude Fable 5 c43e6d873a 4.10 reconstruction: real BTPlayer ctor (binary-accurate experience-level flags)
Boot ladder advances past player creation. BTPlayer ctor/dtor/Make/
TestInstance/GetExperienceLevel reconstructed from BT411's Ghidra-recovered
body (@004c0bc8) backdated to 1995 idiom; the reserved[38] placeholder in
BTPLAYER.HPP replaced with the real BT-own members.

Key fidelity call: the game-mode flags are derived from
btMission->ExperienceLevel() (the egg's per-pilot experience key) with the
binary-accurate switch rows from the [T1] disassembly -- NOT from the scenario
role's returnFromDeath, which BT411's port uses as a [T3] stand-in. Mapping and
residual naming/[T4] uncertainty documented in BTPLAYER.NOTES.md.

Live boot now runs: banner -> resources -> app ctor -> network single-user ->
egg -> mission -> SetPlayerData -> BTRegistry::MakePlayer -> BTPlayer ctor
(resolves team, seeds experience flags) -> halts at the base
Player::DropZoneReplyMessageHandler stub (BTPlayer's own message-handler table
is the next brick -- DefaultData still reuses Player::MessageHandlers).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 20:18:37 -05:00
CydandClaude Fable 5 4fb91775fc Add pod-owner ELI5 of the wedge bug (wedge-explained.md)
Plain-language explanation of the reply-latch wedge for non-technical
pod owners, linked from the firmware README top. Frames the bug as a
'busy' sticky note the board forgets to take down on the give-up path,
and how RIO 4.3 fixes it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 20:11:02 -05:00
CydandClaude Fable 5 0906d1efa6 4.10 reconstruction: real l4net standalone path + full BTL4Mission::SetPlayerData
Boot ladder progress (each step verified live under DOSBox-X + 32RTM):

- L4NET.CPP v2: real statics (ClassDerivations/MessageHandlers/DefaultData),
  real single-user ctor (egg NotationFile -> last.egg -> local ReceiveEggFile
  post), real StartConnecting/Shutdown/CreateConsoleHost single-user branches,
  all four message handlers (egg assembly, ack, host connect/disconnect),
  1995 netnub-guard idiom (Net_Common_Ptr NULL => benign return) throughout;
  netnub wire primitives remain Fail-staged.  Sources: BT411 engine/MUNGA_L4/
  L4NET.cpp (preserves the 1995 netnub code as comments beside its Winsock
  port) cross-checked against the surviving 1995 L4NET.HPP.
- BTL4MSSN.CPP: full SetPlayerData reconstruction (vehicle/dropzone/color/
  patch/badge/team/experience/advancedDamage/role + score modifiers + plasma
  badge blit), backdated from BT411's Ghidra-recovered body (@004d2c30);
  every API pinned to the surviving 1995 headers (NOTATION/MISSION/SCNROLE/
  L4GREND/BTMSSN).

Boot now runs: banner -> resource load -> app ctor chain -> network manager
single-user init -> egg dispatch -> mission creation -> SetPlayerData (parses
the real TEST.EGG) -> halts at BTPlayer ctor (next staged brick).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 19:57:04 -05:00
CydandClaude Fable 5 5b35eb973c 4.10 reconstruction: BTL4OPT.EXE links clean and BOOTS to the first staged brick
The reconstructed tree now produces a runnable binary with the authentic
1995 toolchain (BC4.52 / tlink32 / DPMI32):

- BTL4.CPP main TU reconstructed from the 4.11 Ghidra decomp (FUN_0040109c)
  + the 4.10 binary's own string pool + surviving RPL4TOOL.CPP house style;
  probe_main.cpp scaffold retired (BTL4.NOTES.md documents every decoded call)
- L4NET.CPP staged: L4NetworkManager ctor/dtor + 10 vtable-pulled virtuals
  (standalone-benign ones no-op, network ones Fail loudly) + NetNub client
  globals (Net_Common_Ptr=NULL routes L4File to its plain-DOS path)
- build410.sh: libs now built in the AUTHENTIC makefile member order
  (MUNGA.MAK / mungal4.mak / BT.MAK / BTL4.MAK). Order is load-bearing:
  tlink emits static-init records in module pull order, and alphabetical
  order booted into a null-vptr crash (IcomManager::ClassDerivations
  constructing before parent NetworkClient::ClassDerivations). Also fixed
  stage_link to the proven 32-bit lib set (SOSDBXC+SOSMBXC, no WATTCPLG)
- BOXTREE.HPP MemoryBlock unify, BTL4GRND notify stubs, remaining engine
  backfills (audio/gauge/resource/stream TUs) that closed the deep ledger

Smoke test (DOSBox-X + 32RTM, copy of the pod BT tree, our exe swapped in):
  BattleTech v4.10
  BTL4Application::BTL4Application
  l4net.cpp(22): L4NetworkManager -- l4net.cpp not yet reconstructed
Static init, main, -egg parse, BTL4.RES load (version 1.0.6 check passes),
ApplicationManager and the BTL4Application ctor chain all execute real
reconstructed code; boot halts at the first staged Fail() as designed.
Next brick: the real l4net.cpp body.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 19:05:53 -05:00
CydandClaude Fable 5 516500d8b7 FastRIO 4.3: RIOv4_3_fastrio.bin (31250 + widened ACK-wait + all 4.3 edits)
Built with the full 4.3 flag set plus --baud31250 --widen-ackwait;
71 bytes vs stock, differing from RIOv4_3.bin in exactly two bytes
($D62B baud, $D9E7 ACK-wait) — disassembly-verified. Production table
updated; acceptance ladder on the FastRIO cockpit still required
before deployment.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 17:28:27 -05:00
CydandClaude Fable 5 bf3b0f1cc1 Edit 7: RIOv4_3 reports firmware version 4.3
The VersionReply builder at $C6EA hardcoded 4.2; --reportversion=4.3
patches the minor operand byte ($C6FF: 02->03). Verified no host
software gates on the value (legacy prints it, RIOJoy parses it, native
games ignore it — Cyd). Rebuilt RIOv4_3.bin: 69 bytes vs stock, sha
6d67a2fc7713...; docs updated. Chips burned before this edit still
announce 4.2 — re-burn to pick up the number; all other bytes match
the certified image.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 17:20:40 -05:00
CydandClaude Fable 5 42b3944ebe Christen RIO 4.3: RIOv4_3.bin is the production firmware
Final gate passed: 120s mash at 549 presses/min sustained (heaviest
stress run of the campaign) — zero wedges, counters flat, NAK 0, all
247 resends healed. RIOv4_3rc1 renamed to RIOv4_3.bin (same bytes,
sha dc59bd51cae3...); README/ANALYSIS promote it, production table
updated (native-game cabinets -> RIOv4_3.bin; FastRIO 4.3 variant is
build-on-demand with the documented flag set + acceptance ladder).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 16:53:02 -05:00
CydandClaude Fable 5 be70e61d07 Christen RIO 4.3: RIOv4_3.bin is the production firmware
Final gate passed: 120s mash at 549 presses/min sustained (heaviest
stress run of the campaign) — zero wedges, counters flat, NAK 0, all
247 resends healed. RIOv4_3rc1 renamed to RIOv4_3.bin (same bytes,
sha dc59bd51cae3...); README/ANALYSIS promote it, production table
updated (native-game cabinets -> RIOv4_3.bin; FastRIO 4.3 variant is
build-on-demand with the documented flag set + acceptance ladder).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 16:53:02 -05:00
CydandClaude Fable 5 e7869a6d04 RC1 acceptance PASS: E0000305 after check — edit 6 verified on both paths
Over-threshold check exchange repaints and re-renders a live E0 readout
(not the stale 04000000). The +2 drift in $3184 among 65 status frames
refines the counter model: $3184 = started timeout-retry sequences
(give-ups are the exhausted subset); timeout-recovered cycles exit via
the success teardown, NAK-recovered ones via $DA2F ($3185). All
observations from both bench sessions fit. Mash spot-check remains
before christening RIO 4.3.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 16:46:53 -05:00
CydandClaude Fable 5 dd78d323f3 e0test: check-exchange acceptance stage for edit 6; record RC1 first-light
After the flip leaves counters over threshold, the tool now sends a
CheckRequest (ACKing every status frame) — edit-6 chips must repaint
and re-render the E0 readout; 04000000 marks a pre-rc1 chip. Analysis
records the stock-chip archaeology (stock also leaves 04000000, but the
ungated E0 readout papered over it in period — our fixes exposed it)
and RC1's below-threshold first-light PASS (version+check -> F0).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 16:29:16 -05:00
CydandClaude Opus 4.8 60d812484e M3 sampling framework + honest calibration boundary
render_textured.py samples the game textures with the quads' texu/texv/texz
planes, z-buffered. Empirical finding: the planes are texscale-encoded
(2^16) homogeneous coords needing the exact perspective_divides mapping
(texu/texz * .Cturn_z_to_tex from FOOTER.SS) -- measured texu/texz ~0.12 on
the ground quad. That final texel-coordinate calibration is a precise
reverse-engineering step against EOF.C, not a guess; left as the last mile.

The verified M3 result is the texture DECODE: the netdeath textures are real
game art (texstore.py). Geometry + texel format are both solved from the
live wire.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-19 16:23:29 -05:00
CydandClaude Opus 4.8 cc2d9290be M3 texel decode: the game's own textures recovered from the wire
Action 0x1a carries the textures: header[32] {handle, byte_size, u, v, mode}
+ v rows of 256 bytes, texels in 0x00BBGGRR words. The netdeath session's 20
textures decode to real game art -- 'PLAYER 1/5' HUD labels, a squadron
dragon emblem, metal-panel/grating/terrain surfaces, and the pilot callsign
'Cyd' (texsheet.png in the session scratchpad). The M3 texel FORMAT is
solved; texstore.py builds the handle->RGB store. Remaining: per-quad texid
binding + (texu,texv) sampling to skin the geometry.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-19 16:18:39 -05:00
CydandClaude Fable 5 c29a9d5343 RIOv4_3rc1 candidate: wedge fix + E0 threshold + check-display repaint; archive prior images
New edit 6 (--checkrepaint, requires --e0thresh): hooks the CheckRequest
handler's final notify ($C5E4) through a 10-byte cave at $E020 that
repaints F0000000 after the self-test and re-renders the E0 readout only
when a counter is at/over threshold — no more stale 04000000 after
status checks. Candidate = 9600 native-game-compatible base + edits
1-2/5/6, 68 bytes vs stock, disassembly-verified, awaiting burn; on
verification it will be christened RIO 4.3.

All prior patched generations (wedge-only, 31250/31250v2, 62500/125000
science builds, e0t5 pair) moved to rio-firmware/archive/ with their
disassemblies; RIOv4_2.bin stays at top level as the pristine patch
source.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 16:13:13 -05:00
CydandClaude Opus 4.8 b4c2337ab1 Battle geometry, rendered honestly: coherent arena floor + horizon + sky
Fixed the readout: the effect packets are 3-4 edge TEXTURED quads (0x2c/0x42/
0x0d edges + z + texz/texu/texv planes -- NO Gouraud colour, confirming the
scene is textured). Two bugs in the first pass: (1) 0x2c edges were treated
as 'accept both sides', turning every quad into a full-plane fill; (2) only
2-edge packets were caught, dropping ~3/4 of the geometry. render_battle.py
applies the render_wide30 polygon-winding rule (inside = all-edges>=0 OR
all<0) -> 78 polygons of 141 setups.

Result (flat-per-polygon + depth): a geometrically coherent first-person
scene -- sky at far depth, a ground plane ramping smoothly from horizon to
foreground, a clean horizon line, upright structures. The perspective is
consistent; this is real scene geometry, not the muddy u/v wedges of the
first attempt. Surfaces still need texels (TXDN/M3) for their skin.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-19 16:10:49 -05:00
CydandClaude Fable 5 6e22e2fdbc Correct 04000000 finding: CheckRequest self-test leftover, not test mode
Bench refutation (display is static under axis movement; version-only
exchanges leave it alone) kills the A-9-E chord theory. Real mechanism:
the CheckRequest handler at $C5A6 runs a full self-test — sets the
test-display flag $2421, brackets itself with TestModeChange 0x8C,
lamp pattern, pod scan, five-channel encoder sweep — and returns
without repainting, leaving the channel-4 frame (04000000) as a stale
cosmetic snapshot. Board fully healthy; no reset needed. PROTOCOL.md
now warns hosts that 0x8C fires around every check. Candidate firmware
fix (repaint cave off $C5E4) noted for a future burn.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 16:04:11 -05:00
CydandClaude Fable 5 a9ae6ff0c8 Correct 04000000 finding: CheckRequest self-test leftover, not test mode
Bench refutation (display is static under axis movement; version-only
exchanges leave it alone) kills the A-9-E chord theory. Real mechanism:
the CheckRequest handler at $C5A6 runs a full self-test — sets the
test-display flag $2421, brackets itself with TestModeChange 0x8C,
lamp pattern, pod scan, five-channel encoder sweep — and returns
without repainting, leaving the channel-4 frame (04000000) as a stale
cosmetic snapshot. Board fully healthy; no reset needed. PROTOCOL.md
now warns hosts that 0x8C fires around every check. Candidate firmware
fix (repaint cave off $C5E4) noted for a future burn.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 16:04:11 -05:00
CydandClaude Opus 4.8 fecb5a5f20 M4c COMPLETE: real battle geometry from live game wire, end to end
battle_frames.py extracts the per-draw effect programs (the production
build emits them at ~0x815f000, like fxtest's 0x816f000) and rasterizes
their {edge, z, u/v} primitives through the render_fx GPU path. Running the
netdeath battle capture on the production firmware (vrend410) + emu860c +
GPU: 8 frames in 2.8s showing the actual mech-combat arena -- ground plane,
horizon, a building, receding structures -- with 31..148 primitives/frame
growing as the scene loads (cmd 8125 deep).

The full chain is now proven on real game content: game's own firmware ->
C-accelerated i860 -> the card's own IGC/EMC instruction set on the GPU ->
recognizable battle frames. Surfaces are u/v false-colour pending texel
sampling (the TXDN path, M3); the geometry is the game's.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-19 15:48:31 -05:00
CydandClaude Fable 5 054fbc6a40 e0t5 mash regression: PASS (0 wedges, counters flat) + live test-mode incident
120s lamps-on mash on the burned 9600 e0t5 chip: 236/236 presses, 88.0%
analog fill, NAK 0, zero wedges, board counters flat — normal operation
unaffected by the E0-threshold patch. Bonus field data: the keypad
A-9-E chord fired mid-mash and dropped the board into axis test 4
(display 04000000), confirming that button scanning halts in test mode
while ISR-driven serial keeps running — visible in the log as presses
freezing at 236 while analog continued to 1919.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 15:48:30 -05:00
CydandClaude Opus 4.8 979c82b37c M4c end-to-end: production firmware runs LIVE BATTLE WIRE on the C core
live_server now boots fw=vrend410 (the shipped game build) and replays the
netdeath battle capture's 53,088-record VelociRender wire through emu860c +
the GPU tile path: 8 frames in 5.8s, thousands of commands deep (cmd 6235),
25 tiles/100 sends each. The whole authentic backend -- vpxlog transport,
production firmware, C core, GPU raster -- is proven on real game wire.

Honest scope: the rendered image is still the bench readout (texu->SMPTE
ramp via the texz=x seed), not the battle scene -- live_server uses the bars
readout path, not the per-draw effect-primitive extraction (render_fx). The
battle geometry is present in the wire and executes; wiring the fx-primitive
readout into the live loop is the remaining refinement for real content.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-19 15:44:16 -05:00
CydandClaude Opus 4.8 99f46bea78 emu_main: vrend410 map -- the production firmware (game BT/RP VREND.MNG)
Hook addrs re-derived by masked-immediate signature match vs capfw7 (12/13
exact; reply via unique opcode-only signature). vrend410.mng = the shipped
385KB build with its 7-word Division header rewritten to the loader's 3-word
form. Result: the production build boots and dispatches init + create from
the live netdeath battle wire -- where capfw7 died instantly on the newer
action 0x2d. Stalls at cmd 2 in a bla+fst.d memclear (~1.1M iters / ~9MB)
that pure Python can't chew but the C core (emu860c, 90M steps/s) will --
next: live_server on the C core with fw=vrend410.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-19 15:42:49 -05:00
CydandClaude Fable 5 ea6199d516 Docs: record E0-threshold bench PASS (E0000105) + corrected counter semantics
The display observation recalibrates the counters: $3184 = give-up
cycles (once per exhausted retry sequence, not per retransmit), $3185 =
teardowns of any reply cycle needing at least one retransmission — the
counter behind a lone E0000001. Also recorded in the error-handling
inventory: 5 retransmits per cycle, reply-await arms only after the
complete frame, NAK forces exactly one counted retransmit, late ACKs
cannot rescue a cycle. (Previous commit's doc edits had silently missed
their anchors; applied properly this time.)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 15:40:57 -05:00
CydandClaude Fable 5 52a3317ed6 Docs: record E0-threshold bench PASS (E0000105) + corrected counter semantics
The display observation recalibrates the counters: $3184 = give-up
cycles (once per exhausted retry sequence, not per retransmit), $3185 =
teardowns of any reply cycle needing at least one retransmission — the
counter behind a lone E0000001. Also recorded in the error-handling
inventory: 5 retransmits per cycle, reply-await arms only after the
complete frame, NAK forces exactly one counted retransmit, late ACKs
cannot rescue a cycle. (Previous commit's doc edits had silently missed
their anchors; applied properly this time.)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 15:40:57 -05:00
CydandClaude Fable 5 f98fc481cc Firmware README: complete the patched-image inventory (speed ladder, e0t5)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 15:14:14 -05:00
CydandClaude Opus 4.8 28785d9486 M4c: live_server -- the authentic backend for the vpxlog wire feed
Consumes VPXM records (fifodump file or live VPX_FIFOSOCK) and renders
through emu860c + the GPU tile path. The 'new C012 device' of the plan
turned out to already exist: vpxlog.cpp IS the link adapter and already
streams the wire over TCP; this server is the drop-in authentic listener
beside the GL bridge.

Validation on the netdeath battle capture (53,088 records) found the real
gap: the firmware dies with 'unrecognised or illegal action 0x2d' -- the
battle games speak a newer protocol than capfw7 (cap7's booted build).
Census: every boot-carrying capture ships the same old build; the 0x2d
sessions were all captured mid-run. The production build is in the game
files themselves: ALPHA_1/REL410/{BT,RP}/VREND.MNG (identical, 385KB,
csize 0x3ac80). Next: re-derive the hook map for that build (signature
anchors in emu_main) and replay the battle wire on its matching firmware.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-19 15:03:00 -05:00
CydandClaude Fable 5 4374bcf1d8 Firmware: --e0thresh patch — gate the E0 error display (default N=5)
Stock $D5F2 repaints the cockpit display to the E0 counter readout on
the FIRST increment of $3187/$3184/$3185, so one benign give-up shows
E0000001 forever. New opt-in make_patch.py edit 5 hijacks the render's
LDX #$2038 into a 30-byte cave at $E000: all three counters below N ->
exit via the routine's own epilogue (registers restored, display
untouched); any >= N -> resume the render. Counters still accumulate.

Built + disassembly-verified (not yet burned): RIOv4_2_patched_e0t5.bin
(9600) and RIOv4_2_patched_31250v2_e0t5.bin (FastRIO). Docs updated.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 15:02:22 -05:00
CydandClaude Fable 5 cb95c229da Firmware: --e0thresh patch — gate the E0 error display (default N=5)
Stock $D5F2 repaints the cockpit display to the E0 counter readout on
the FIRST increment of $3187/$3184/$3185, so one benign give-up shows
E0000001 forever. New opt-in make_patch.py edit 5 hijacks the render's
LDX #$2038 into a 30-byte cave at $E000: all three counters below N ->
exit via the routine's own epilogue (registers restored, display
untouched); any >= N -> resume the render. Counters still accumulate.

Built + disassembly-verified (not yet burned): RIOv4_2_patched_e0t5.bin
(9600) and RIOv4_2_patched_31250v2_e0t5.bin (FastRIO). Docs updated.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 15:02:22 -05:00
CydandClaude Fable 5 6440a90557 Error-handling inventory: E0 diagnostics, dEAd crash screen, no watchdog
The display has a third use: serial error annunciator. $D5F2 renders
'E0' + three live counters (TX-ring overflow $3187, reply retries
$3184, give-up teardowns $3185); $DAB8/$DAB2 is a terminal crash
screen spelling 'dEAd' when the TX dispatcher meets an unknown command
byte. Also recorded: RX overrun is unhandled (checksum NAKs are the only
symptom), unused vectors hang in BRA-self stubs, FAULT LED = MAX690 PFO,
manual/remote reset works by pulling PFI low, RUN LED = buffered AS*,
and the MAX690 watchdog is unconnected/unserviced — software wedges
persist until reset, matching bench observations.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 14:47:01 -05:00
CydandClaude Fable 5 83fcb198c8 Error-handling inventory: E0 diagnostics, dEAd crash screen, no watchdog
The display has a third use: serial error annunciator. $D5F2 renders
'E0' + three live counters (TX-ring overflow $3187, reply retries
$3184, give-up teardowns $3185); $DAB8/$DAB2 is a terminal crash
screen spelling 'dEAd' when the TX dispatcher meets an unknown command
byte. Also recorded: RX overrun is unhandled (checksum NAKs are the only
symptom), unused vectors hang in BRA-self stubs, FAULT LED = MAX690 PFO,
manual/remote reset works by pulling PFI low, RUN LED = buffered AS*,
and the MAX690 watchdog is unconnected/unserviced — software wedges
persist until reset, matching bench observations.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 14:47:01 -05:00
CydandClaude Fable 5 2f5fc505d6 Display board 1408: full output definition + firmware display content
New display-board-1408.md: pin-level definition of the board's outputs
(8 multiplexed hex digits via ICM7228B, isolated LPT LED monitor block,
no readback path) and, from the firmware disassembly, everything the RIO
puts on it: F0 boot banner, F1 test-mode banner (keypad sequence A-9-E
enters, D exits), and the sub-test displays — five live encoder-count
readouts, button test with input index, two lamp patterns, keypad test.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 14:35:12 -05:00
CydandClaude Opus 4.8 ff91bc675f M4b: offline end-to-end frames -- firmware -> C core -> GPU, live
emu860c gains a C-side write-watch (watch_add/watch_drain: watched ranges
log (addr,val) into a ring buffer at negligible cost). frames.py runs the
cap7 mission on the C core, drains the DMA queue-page writes at each
receive->receive draw span, reconstructs the frame's SEND payloads from
live C memory, dispatches the GPU tile shader per TILE entry, and
accumulates interlaced fields. Result: the complete SMPTE test card
(frame_0004) -- 6 draw frames in 2.0s including boot; the content draws
alternate 25-tile fields with eof/present passes, matching the hardware
cadence.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-19 14:23:29 -05:00
CydandClaude Fable 5 d95e390b0d FastRIO certified: 31250v2 final runs clean; config plumbing for baud/poll
Operator-verified zero lamp misses/hangs through the slow-chord test
(62500's killer) and 392/min mash. Final run: NAK=0, 25 timeout resends
silently healing inbound response loss, counters flat, zero wedges.
--poll 20 delivered ~31Hz analog (1.7x legacy); the shortfall vs 50Hz
is additive host pacing (delay after awaited exchange), not board
saturation - noted as a future host tweak.

AppConfig gains RioBaudRate (default 9600) + AnalogPollMs (default 55),
plumbed through RioCoordinator; existing configs unchanged. Production
matrix recorded in ANALYSIS.md: 9600 patched chip for native-game
cabinets, 31250v2 + poll 20-25 + FTDI for RIOJoy cockpits.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 14:19:30 -05:00
CydandClaude Fable 5 a7e4a3fd61 Hardware docs: Quad Amplifier Board (1413) photos
Four photos of the 1413 Rev. 1: component side with the bolt-on Pyramid
PB-150P, solder side (etch NT 1-0A 3695), and both faces of the Pyramid
module (inputs/level pots, speaker terminals/fuse/power). Photo index
updated.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 14:12:49 -05:00
CydandClaude Fable 5 552d74f337 Hardware docs: 1413 is the Quad Amplifier Board — a bolt-on Pyramid PB-150P
Photos of the physical board (Rev. 1) show the amplification is a stock
Pyramid PB-150P Pro Plus 4-channel car amp mounted as a module; the VWE
board is passive: 12V/remote power distribution, per-corner 3-way
crossovers (Dale IHB-3 820uH/180uH, MMP film caps, CP-5 2R pads), 6-pin
woofer/mid/tweeter corner connectors, and the LED output-check circuit.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 14:02:25 -05:00
CydandClaude Fable 5 40ad8e3b27 GAL U7 decoded: full RIO memory map recovered from the fuse dump
galdecode.py applies the GAL20V8 complex-mode fuse geometry (tables from
MAME jedutil.cpp) to GAL20v8a_5764.JED with pin names from schematic
sheet 1. Result triple-checks: schematic net names, firmware $A0xx
accesses, and the chip's UES signature — which VWE programmed as 'U7'.

Memory map: $2000-$9FFF SRAM (E-qualified), $A000 display write port,
$A010 pod-bus latch, $A020-$A03F HCTL-2016 counters (A3 byte select
via NOT_A3), $C000-$FFFF EPROM (explains the FF-padded dump), with
OE* = E&R/W as the shared read enable.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 13:57:44 -05:00
CydandClaude Fable 5 3c9455eb97 62500 SHELVED: chord-driven RX overrun is host-unfixable; 31250v2 is FastRIO
Slow chorded presses still glitch lamps at 62500 after three rounds of
host-side hardening (NAK-race resend -> stop-and-wait -> typed
resolution): a chord maximizes board ISR latency exactly when lamp
replies arrive, and a 2-byte RX buffer loses bytes no protocol can
recover. Full post-mortem in ANALYSIS.md; all bench evidence archived.
Final ladder: 9600 production / 31250v2 FastRIO / 62500 shelved /
125000 not viable. Stop-and-wait stays on everywhere as cheap delivery
insurance.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 13:40:48 -05:00
CydandClaude Opus 4.8 cff783d2ad Full-mission replay through the C core: 26,422 commands / 3.49B steps in 39s
The complete cap7 mission -- every command, all 8,562 draws -- executes in
39 seconds at 89.6M steps/s sustained (199,857 Python hook services). The
replayed dict matches the QUEUE ground truth exactly; the old 'baseline'
dict (16793/8397) is exposed as a budget-truncated artifact: the historic
Python regressions hit the 2e9-step budget ~96% through and silently
dropped the last 497 commands. This is the first complete execution of the
whole mission. + M4-LIVE-SEAM.md (the remaining path to live DOSBox) and
emu860c.step1() for hook-driven single-steps.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-19 13:37:38 -05:00
CydandClaude Fable 5 bef1499152 RioSerialLink: type-aware resolution closes the straggler-reply hole
Bench round 3 (testlogs/riomash-patched-62500-sw): lamp glitches
persisted because reply-resolution was type-blind — an analog reply
still crossing USB from the previous poll could falsely confirm the
NEXT command (usually a lamp write) before the board judged it. Now a
reply resolves only its MATCHING pending request (analog/version/
check); ACK/NAK stay type-blind, which is safe because the board's TX
ISR prioritizes ACK/NAK ahead of reply data, so a command's ACK cannot
trail into its successor's window. Budget-exhausted drops settle 10ms
before releasing the gate so late stragglers land on an empty pending.

New test: a stray AnalogReply must not resolve a pending lamp command.
283 green; selftest regression unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 13:34:12 -05:00