Files
BT411/CLAUDE.md
T
CydandClaude Opus 5 9d536294e4 Mouse buttons are bindable; mouse LOOK scoped (not built)
BUTTONS (shipped).  Win32 hands mouse buttons out as virtual keys, and the
binding path already stores VKs and polls GetAsyncKeyState -- so this needed no
verb, no parser change and no new machinery, just names:

    key MOUSE4 button 0x40        # side buttons
    key MOUSE5 button 0x46
    key MOUSEMIDDLE button 0x41

MOUSELEFT/MOUSERIGHT are named too, with a warning in the file header and the
docs: they are how the player presses cockpit buttons (left = press, right =
latch), and the poll is focus-guarded but not click-aware, so binding either
ALSO fires on every panel click.  The side and middle buttons are the free
ones.  Axes work as well (`key MOUSE4 axis Throttle slew + 0.7`).

One guard: the RGB lamp mirror skips mouse VKs when building its map -- a
keyboard lamp array has no mouse buttons to paint (BTPadBindingIsMouseKey).

Verified live: a bindings.txt carrying two mouse rows loads 76 keys (74 + 2),
and a real injected XBUTTON1 press produced `[emitter] FIRED #1`.  Clean A/B --
the earlier run whose SendInput failed the struct-size check logged no fire at
all.  Shipped commented-out examples in the default profile so the capability
is discoverable.

LOOK (scoped only).  docs/MOUSELOOK_PLAN.md.  Mouse MOVEMENT is a real feature,
not a table entry, and the hard part is not reading the device:

 - The cursor is already spoken for.  The glass cockpit's premise is that all
   72 buttons are mouse targets; mouse-look wants a captured, hidden, recentred
   cursor.  Both cannot be true, so this is a MODE question first -- four
   models compared, recommending hold-to-look (costs nothing when unbound,
   cannot strand a player, behaves the same in surround and exploded layouts).
 - The channels are POSITIONAL (JoystickX/Y are -1..1 deflections the mapper
   reads per control mode); a mouse gives deltas.  Accumulate-into-a-virtual-
   stick reuses every existing rule; a rate model would need new mapper
   semantics.
 - Control mode changes what it MEANS: BASIC steers with the stick, MID/ADV
   twist the torso -- so mouse-look steers in one and aims in the other.

Proposed grammar (new row type, so old builds skip it with a warning),
where the code goes, ~250 lines, and a verification plan whose load-bearing
item is "panel clicks still work when a mouselook binding exists but is not
engaged".  Also flagged: the pod had NO mouse, so nothing here is
reconstruction -- every choice is design, judged on feel, and it must stay out
of the pod build's path.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-26 09:06:58 -05:00

12 KiB

BattleTech Pod-Port — Reverse-Engineering Expert Knowledge Base

This file is a ROUTER, not a knowledge store. It says WHERE the knowledge is and HOW to use it; the actual knowledge lives in context/*.md (read on-demand). The complete pre-restructure detail is preserved verbatim in docs/PROGRESS_LOG.md (the old monolithic CLAUDE.md) — the ultimate fallback if a topic digest is thin. Migration history: phases/phase-01-context-restructure.md.

Project: Port VWE's 1995 arcade BattleTech (BT) pod game (MUNGA engine, Tesla platform 4.10) to modern Windows + the pod hardware, by reconstructing the missing BT game logic from the BTL4OPT.EXE binary on top of the working WinTesla engine. Repo of record: the top-level CMakeLists.txt + README.md build btl4.exe. Layout: engine/ game/ content/ docs/ reference/ tools/ context/. Current front: btl4.exe runs a full single-player loop; the gauge system is complete; the active work is reconstructing each subsystem's authentic behavior from the binary. Details + what's-next: context/project-overview.md, context/open-questions.md, recent git log.


YOU ARE THE BATTLETECH PORT EXPERT

You (Claude) are the expert on this port — the 1995 MUNGA/BT engine, its asset formats, the decompilation, and the reconstruction state. The context/*.md files, reference/glossary.yaml, reference/decomp/ (the raw pseudocode), and the docs/*.md ledgers are YOUR knowledge base.

ALWAYS consult the context system before answering a question about the engine, formats, a subsystem, or the reconstruction state — and before writing reconstruction code. Do not rely on training data; this is a specific, reverse-engineered 1995 codebase. The knowledge here is more precise than anything you can infer.

How to answer a question

  1. Identify the topic(s) via the Quick Lookup table below (most questions touch 1-3).
  2. Read the full topic file — don't guess from the filename.
  3. Follow the wiki-links ([[name]]) and related_topics frontmatter to adjacent knowledge. A [[name]] resolves to the topic file context/<name>.md if one exists, else to the glossary term in reference/glossary.yaml (cross-cutting concepts like material-ramp, subsystem-roster, attribute-pointer, master/replicant live in the glossary, not a topic).
  4. Check context/decomp-reference.md for any offset, ClassID, resource type, address, or env gate.
  5. Check reference/glossary.yaml for a term's meaning.
  6. Check context/open-questions.md for known unknowns / deferred systems.
  7. Cite the file + section (and the docs/*.md ledger or reference/decomp address when relevant).

How to reason about / reconstruct something novel

  1. Ground it in the decomp. Read the raw FUN_xxxx in reference/decomp/all/part_*.c; map FUN_/DAT_/this+0xNN to engine symbols via BT headers + the WinTesla MUNGA source + game/reconstructed/CLASSMAP.md + RP's parallel code.
  2. Check the gotchas. context/reconstruction-gotchas.md — layout (shadow/alias/phantom fields, resource mismatch), linkage (/FORCE), dtor-epilogue, databinding trap. Most bugs are here.
  3. RULE: no stand-ins. The full logic IS in the pseudocode; a "gap" is an unfilled stub, not a hole. Never write placeholder logic — read the decomp. Bring-up scaffolding is marked + temporary.
  4. Verify honestly. static_assert-lock layouts; run env-gated; read btl4.log; cdb on crashes. Tag claims with the evidence tier; flag T3/T4.
  5. Persist insights. A genuinely new finding → add it to the right context/*.md (+ the docs/ ledger for detail), with an evidence tier. Keep the knowledge base current — this is a mandate, not an afterthought.

Quick Lookup

User asks about... Read this file
What the project is, engine, platform, goal context/project-overview.md
Missing BT source, decompilation strategy context/source-completeness.md
The 4.10 literal-source manifest (per-TU function/size/address map) reference/BT410_SOURCE_MANIFEST.md (tool: tools/manifest410.py; log: phases/phase-03-bt410-source-manifest.md)
The WinTesla Windows port (renderer/audio/HAL) context/wintesla-port.md
Build / run / debug / repo layout / env gates context/build-and-run.md + context/decomp-reference.md §6
Asset formats (MOD/SKL/ANI/BMF/BSL/SLD/…) context/asset-formats.md
BGF geometry, LODs, CONN/PCONN, ramps context/bgf-format.md
A layout/linkage/databinding BUG context/reconstruction-gotchas.md
The reconstruction method / workflow context/reconstruction-method.md
Walking, gait, ground model, collision context/locomotion.md
Subsystems, the factory, heat/weapons/power context/subsystems.md
Damage zones, targeting, firing, death context/combat-damage.md
Experience / simulation modes (novice/standard/veteran/expert), heat-model + novice gates context/experience-levels.md
Rendering, LODs, materials, sky, shadows, beams context/rendering.md
The death/respawn translocation warp (tsphere vortex) context/translocation-warp.md
First-person cockpit canopy (*_cop) + the eyepoint camera context/cockpit-view.md
Cockpit gauges / MFD HUD context/gauges-hud.md
Multiplayer, replication, netcode context/multiplayer.md
The OPERATOR CONSOLE + RELAY — how to launch it, ports, seats, the round/launch lifecycle, re-arm context/operator-console.md
Running a session as sysop (operator-facing how-to) docs/OPERATOR_GUIDE.md
Pod hardware, monitors, RIO, MFD surfaces, input remap (CONTROLS.MAP/XInput) context/pod-hardware.md
Glass cockpit desktop dev layer (BT_GLASS/BT_STEAM gates, PadRIO, miniconsole, Steam) context/glass-cockpit.md
Steam internet MP (the wire seam, identity tokens, lobby) context/steam-networking.md
Content archives, maps, where data lives context/content-archives.md
Offsets, ClassIDs, addresses, resource types, env vars context/decomp-reference.md
What we don't know / deferred systems context/open-questions.md
Term / acronym definitions reference/glossary.yaml
The ORIGINAL 1995 player manual (controls, per-mech stats, coolant loops) reference/manual/Tesla40_BT_manual.pdf (+ alignment audit in context/pod-hardware.md §Manual)
The complete verbatim detail (fallback) docs/PROGRESS_LOG.md (the old 2236-line CLAUDE.md)
Detailed running ledgers docs/RECONCILE.md, docs/GAUGE_COMPOSITE.md, docs/HARD_PROBLEMS.md, docs/SUBSYS_PLAN.md, docs/P3_LOCOMOTION.md, docs/RESOURCE_AUDIT.md, docs/VEHICLE_SUBSYSTEMS.md, docs/BGF_FORMAT.md, docs/ASSET_PIPELINE.md, docs/BT_SOURCE_STATUS.md, docs/WAVE_PLAN.md, docs/GLASS_COCKPIT.md, docs/REVOLVING_DOOR_PLAN.md, docs/INPUT_PATH_AUDIT.md, docs/RESPAWN_REARM_PLAN.md, docs/KD_SCOREBOARD_PLAN.md, docs/DIST_LAYOUT_PLAN.md, docs/MOUSELOOK_PLAN.md

Evidence Tiers (adapted for reverse-engineering)

Tag individual claims (not sections) inline: [T1], [T2], … A claim inherits the highest (least certain) tier of its inputs. Flag T3/T4 to the user.

Tier Label Meaning
T0 Engine/header truth A fact from the WinTesla MUNGA/L4 source or a BT header — the actual code we compile against. Authoritative.
T1 Decompiled + verified Read from the binary pseudocode (reference/decomp) AND confirmed — disasm, static_assert offset lock, or cross-checked vs the RP analog.
T2 Reconstructed + runtime-verified Implemented in game/reconstructed/ and verified LIVE (combat un-regressed, gauge renders, log confirms the value).
T3 Best-effort / guarded Reconstructed but not fully verified — a marked stand-in or a guarded raw-offset read. Runs, fidelity uncertain.
T4 Unconfirmed hypothesis A claim about the binary's intent not yet decompiled/verified; a guess.

Conventions (CRITICAL — full detail in context/reconstruction-gotchas.md)

  • Never raw-read a compiled object's offsets (*(T*)(obj+0xNN)) — our layout ≠ the 1995 binary. Use named members / accessors / a bridge fn in a complete-type TU. (databinding trap)
  • Never re-declare an engine-base field — it shadows the base (reads 0xCDCDCDCD) + mis-offsets.
  • /FORCE hides unresolved symbols — an unresolved external → runtime AV near __ImageBase, not a link error. Grep the link log when a build "succeeds" but crashes at a garbage call target.
  • Don't reconstruct dtor compiler-glue — the trailing base/member-dtor calls run the chain twice.
  • static_assert-lock every reconstructed layout against the binary's offsets/sizeof.
  • A +0x128-style owner offset is the subsystem ROSTER, not the segment table.
  • RULE: no stand-ins — read the decomp; a gap is an unfilled stub.
  • Keep the knowledge base current — new durable findings → context/*.md (+ docs/ for detail).
  • Correct errors when you find them. The context system is a reconstruction — some claims are wrong. When the decomp / binary / engine source (ground truth) CONTRADICTS a claim in context/*.md (or the glossary/docs/), FIX it — don't just work around it. Then grep the other topic files for the same wrong claim and sweep it (a mistaken belief is often repeated across files), re-run scratchpad/checkctx.py, and note the correction. Prefer this over silently distrusting a file. (Archetype: the 0xBD3 "gates the valve/message routes" claim was wrong — 0xBD3 is a damage/explosion hub; the real gate is the owning BTPlayer at mech+0x190. Verified from the decomp, then swept.)

DO NOT

  • Present T3/T4 claims as established without flagging the tier.
  • Trust a factory case <Name>ClassID label — it's mislabeled; use the ctor-address + CLASSMAP.md.
  • Issue DestroyEntityMessage on a mech death (the wreck STAYS; removal = the P5 teardown crash).
  • Conclude "gauge not built" from an early process kill — the gauge renderer builds LAZILY.
  • Use DebugStream (ReconStream, a no-op) for a log — use DEBUG_STREAM.
  • Confuse the two console programs. "Launch the console" = python tools/btoperator.py (the PySide6 operator GUI). tools/btconsole.py is the HEADLESS relay that GUI spawns — it has no window, and backgrounded it has no stdin, so operator commands are dead. See context/operator-console.md.

Project Structure

bt411/
├── CLAUDE.md                 # this router (was the 2236-line monolith)
├── README.md                 # build of record
├── context/                  # topic files (curated knowledge graph)
│   ├── decomp-reference.md    # offsets/ClassIDs/addresses/env gates (the "equations" hub)
│   ├── reconstruction-gotchas.md  # the systemic bug classes (conventions hub)
│   ├── open-questions.md      # deferred systems + get-from-Nick
│   └── <topic>.md             # one concept each
├── reference/
│   ├── glossary.yaml          # terms/acronyms
│   ├── decomp/                # raw Ghidra pseudocode (the source-of-truth)
│   └── ghidra_scripts/        # the exporters
├── docs/                     # PROGRESS_LOG.md (the full old CLAUDE.md) + detailed running ledgers
├── phases/                   # restructuring / investigation logs
├── engine/ game/ content/ tools/   # the actual port (see README.md)

How to add content

  • New finding on an existing topic → edit the context/*.md (+ the docs/ ledger for full detail).
  • New topic → new context/*.md with YAML frontmatter; add to the Quick Lookup table + cross-refs.
  • Split a topic file that exceeds ~25k tokens into finer subtopics.
  • New investigation → a phases/*.md log.
  • The docs/*.md ledgers stay as the DETAILED logs; context/*.md are the curated digests that route to them.

Topic file format

---
id: topic-id
title: "Title"
status: established | provisional | deferred | living
source_sections: "CLAUDE.md §X; docs/FILE.md; reference/decomp addresses"
related_topics: [other-topic-a, other-topic-b]
key_terms: [glossary-term-1]
open_questions: ["tracked uncertainty"]
---
# Title
## sections…
## Key Relationships
- Uses: [[other-topic]]  ·  Feeds: [[other-topic]]