Files
Syplheed-Reborn/docs/re/weapon-datasheet-runtime.md
Claude (auto-RE) 07eff85819 re: in-flight HUD — independent confirmation of the ammo mapping
The tutorials need no save and are ~1 min from a cold boot, so they are the
cheapest route into a live flight scene. The HUD prints the equipped weapons as
NOSE BM 06000 / MAIN MPM 00300 — matching wep_01's LoadingCount 6000 and wep_02's
300, with the weapons identified from the HANGAR loadout rather than from the
ammo number. That makes it a genuinely independent confirmation of
Ammo Capacity == LoadingCount, from a different renderer in a different mode.

Also inventories the HUD elements (heat gauges, shield/armor pools, target armor
gauge, per-weapon RANGE markers) and notes that the RANGE gauge draws each
weapon's MaximumRange on a scale — a route to a real number where the Arsenal
panel only gives a letter class.

Adds autopilot.py (waypoint-arrow chaser). It detects reliably but oscillates;
recorded as such rather than as a working tool.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-28 18:50:46 +00:00

14 KiB
Raw Blame History

Weapon DATA SHEET — runtime capture (Route B)

Status: 🟡 first dynamic capture, 2026-07-28. The Arsenal's Gallery Mode panel is a direct runtime readout of the IDXD weapon record, which makes it an oracle for the fields the disc leaves defaulted. Two field mappings are CONFIRMED; two defaulted values are recovered at 🟡 PROBABLE. Captured from the retail game under Xenia Canary (software Vulkan, headless) — see the container recipe.

Problem

sylpheed-formats::game_data reads the combat tables out of dat/GP_MAIN_GAME_E.pak, but a field left at its default value carries no value on disc — the key is present in the IDXD string pool with no value token in front of it. Those defaults live in title code, so a static read can only ever say "not set", never what the game uses. That is a real hole for the reimplementation: e.g. Weapon_DSaber_P_wep_01_Beam — the Delta Saber's starting beam gun — has no TriggerShotCount and no Power on disc.

Ruled out first: the defaults are not hiding in another pak. hidden/DefTables.pak contains no WEAPON-schema (0x6ab4825a) objects at all, and the other GP_MAIN_GAME_* paks are localized duplicates of the English one.

The two scratch analyses that produced the shopping list live next to the crate: crates/sylpheed-formats/examples/defaulted_fields.rs (per-schema: which keys are declared but defaulted, and by whom) and examples/default_owners.rs (per-key: every owner, valued or <DEFAULT>).

Caveat on those tools: they classify a token as a value only if it is numeric or non-identifier-shaped. Boolean/enum-valued fields therefore read as <DEFAULT> spuriously (Yes, Homing, Single, Burst are identifier-shaped). Every finding below concerns numeric fields, where the classification is sound.

Finding — the DATA SHEET reads the record

In ARSENAL → (weapon type) → Y (Gallery Mode) each entry shows a DATA SHEET, and it is shown for weapons that have not been developed yet — only fully hidden (dashed) entries are withheld. The same panel appears in HANGAR → (hard point), with an extra Weapon Type row.

DATA SHEET row IDXD field Confidence Evidence
Ammo Capacity LoadingCount CONFIRMED every one of the 10 identified entries lands on a LoadingCount that exists in its own weapon-type tab — and see the circularity note below
Max. Lock Ons TriggerShotCount CONFIRMED FALCON 9AM = 12 vs wep_02's 12; BUZZARD 10AM = 22 vs wep_04's 22 (two distinctive values, two independent records)
Hard Point mount slot CONFIRMED matches the HANGAR slot the weapon is mountable/equipped on (STILETTO BG I → NOSE, FALCON 9AM → MAIN WEAPON1)
Range Class bucket of MaximumRange 🟡 PROBABLE monotone in the on-disc metres, see the bracket table below
Damage Class bucket of Power 🟡 PROBABLE monotone in the on-disc power, see below
Weight Class bucket of the hangar-table Weight HYPOTHESIS only one clean pair so far (wep_33, Weight 0.3 → "Light")
Speed Class present only on missiles (MPM = A, ASM = B); no on-disc pairing established
Sight Homing, Lock on Overlap (Available / ) the plausible on-disc partners (Homing, OverlapLockon) are identifier-valued and not yet decoded; NEEDS-HUMAN

Why the Ammo Capacity evidence is not circular

Each UI entry was identified by matching its Ammo Capacity against the records in that weapon-type tab, so "the ammo matches" cannot on its own prove the mapping. What does:

  1. The match is forced and unique. For 10 of the 11 entries, exactly one record in that tab carries that number (600 occurs three times overall — wep_04, wep_24, wep_55 — but in three different tabs: MPM, BEAM, B/R). An unrelated quantity would not land on a valid, tab-unique LoadingCount eleven times running.
  2. A second, independent field then agrees. FALCON 9AM and BUZZARD 10AM were pinned by ammo alone, and their Max. Lock Ons (12, 22) then matched those same records' TriggerShotCount (12, 22) — values that play no part in the identification. A wrong identification would have to be wrong twice, consistently.
  3. One entry is identified without ammo at all. STILETTO BG I is described in-game as "the initially mounted Delta Saber beam gun" and is the weapon the HANGAR shows equipped on the nose; wep_01_Beam is the corresponding record, and its LoadingCount 6000 is what the panel shows.

The weakest identification is LIGHT MACHINE GUN MG I: three guns share LoadingCount = 3000 (wep_09, wep_33, wep_83). wep_33 is picked on Weight Class = Light (it has by far the smallest Mass, 1.5 vs 3.6 / 33.0) — 🟡 PROBABLE, not certain.

Finding — recovered defaults

Weapon UI name Field On disc Runtime Conf.
Weapon_DSaber_P_wep_05_ASMissile TERRIER SMH TriggerShotCount (defaulted) 4 🟡
Weapon_DSaber_P_wep_60_ASMissile HOUND SMH TriggerShotCount (defaulted) 4 🟡

Both defaulted weapons read 4, which is consistent with a single title-code default of TriggerShotCount = 4 rather than two per-weapon constants — but two samples cannot tell those apart. HYPOTHESIS: the title-code default for TriggerShotCount is 4. It would be confirmed by a third weapon that defaults the field and also reads 4 (candidates that were still locked in this save: wep_27, wep_30, and the seven Beams), or refuted by one that reads anything else.

Power and MaximumRange defaults are not exactly recoverable from this panel — it shows only the letter bucket. They are bracketed instead (below).

Captured rows

All values are from one session on save slot 01 (Stage 02, "At Standby", 5 % clear, 4101 P); marks a value that matches the on-disc record exactly.

UI name Record Rng Dmg Spd Weight Ammo Lock Homing Overlap Hard point
LIGHT MACHINE GUN MG I wep_33_Gun 🟡 D E Light 3000 ✓ NOSE WEAPON (Nose)
BROAD SWORD SG I see below E D Light 200 NOSE WEAPON (Nose)
STILETTO BG I wep_01_Beam E E Light 6000 ✓ NOSE WEAPON (Nose)
DAGGER BG2 wep_37_Beam D E Light 4000 ✓ NOSE WEAPON (Nose)
PILUM BP wep_24_Beam B D Light 600 ✓ MAIN WEAPON1 (Fore)
FALCON 9AM wep_02_Missile D D A Heavy 300 ✓ 12 ✓ Available MAIN WEAPON1 (Fore)
BUZZARD 10AM wep_04_Missile C D A Heavy 600 ✓ 22 ✓ Available MAIN WEAPON1 (Fore)
DART 23 ROCKET wep_55_Rocket C D Heavy 600 ✓ MAIN WEAPON1 (Fore)
TERRIER SMH wep_05_ASMissile D C B Heavy 45 ✓ 4 Available Available MAIN WEAPON2 (Rear)
HOUND SMH wep_60_ASMissile B C B Medium 18 ✓ 4 Available Available MAIN WEAPON2 (Rear)
TOMAHAWK ALPHA RAIL GUN wep_03_Cannon C C Medium 75 ✓ MAIN WEAPON3 (Lower)

BROAD SWORD SG I is unidentified — NEEDS-HUMAN. Ammo Capacity 200 narrows it to wep_38 / wep_41 / wep_42_Shotgun (all LoadingCount = 200); "SG" and the GUN tab fit a shotgun. wep_42 is excluded by range (2500 m would not share class E with wep_38/ wep_41's 3000 m if the class is a pure range bucket), leaving wep_38 vs wep_41, which the panel cannot separate. Its Damage Class D also does not fit the Power bracket below (all three shotguns are Power ≤ 16, i.e. bucket E), so either the identification or the "Damage Class = bucket of Power" model is wrong for shotguns.

Letter-class brackets

Sorting the identified rows by their on-disc numbers gives monotone, non-overlapping bands:

Range Class   E: 3000                       (wep_01)
              D: 3500 · 4000 · 4000 · 4000  (wep_33, wep_37, wep_02, wep_05)
              C: 4500 · 5000 · 5000         (wep_55, wep_04, wep_03)
              B: 6500 · 6500                (wep_24, wep_60)

Damage Class  E: 10 · 14 · 16               (wep_33, wep_01, wep_37)
              D: 70 · 75 · 100              (wep_24, wep_04, wep_55)
              C: 200 · 400                  (wep_03, wep_05)

Two consequences for the reimplementation:

  • The thresholds are not pinned — only bracketed (e.g. the D/C range boundary lies in (4000, 4500]). More weapons, or a static read of the title-code table, would pin them.
  • They bracket the defaulted numbers: wep_02_Missile's defaulted Power sits in the D band (≈ 17…150 by the observed edges) and wep_60_ASMissile's in the C band (≈ 150…500). 🟡 PROBABLE, and only as good as the bucket model.

How this was captured

Container recipe (sylph-container/mission.md), with two corrections worth keeping:

  • Skip the intro movie with A. The brief warns it crashes; it does not. Skipping cuts boot-to-main-menu from ~13 min to ~1 min under lavapipe. (Thanks: user tip.)
  • The title screen falls back to the attract loop within a few seconds, so a screenshot→look→tap cycle always misses it. Poll the framebuffer and tap in the same process. Both are automated in scratchpad/skip_intro.sh (movie detected by frame-to- frame RMSE; title by the green Ⓐ glyph at pixel 625,618).
  • Under lavapipe the game polls input at its own low frame rate: a 60 ms d-pad tap is dropped roughly half the time; 200 ms is reliable and 300 ms starts to auto-repeat.
  • The Hangar hard-point weapon carousel is cycled with d-pad down, not left/right.

Path: title → A → LOAD GAME → slot 01 → Load game? YES → READY ROOM → ARSENAL → type tab (LB/RB) → Y for the DATA SHEET → d-pad down through the list.

Open / next

  • Only 9 weapons of ~61 are revealed at 5 % completion, and none of the four whose LoadingCount is defaulted (wep_11, wep_28, wep_36, wep_70) is among them. Progressing the save (or a later save) is what unlocks the rest — the panel itself already shows undeveloped weapons, so no points need to be spent.
  • Craft (UNIT-schema) defaults are not reachable this way. The Hangar exposes exactly one craft-level runtime number, Gross Weight (a class, "Light"). The defaulted craft fields (ShieldRatio, BarrelRoll_Count*, HoldPosition_*Ratio, Slalom_TurnCount_Max, UsingChaffRatio, …) are AI/flight-model constants with no UI surface; they would need in-flight behavioural measurement or a guest-memory read, not a menu screenshot.
  • The Sight Homing / Lock on Overlap on-disc partners are still unidentified.

Screenshots for every row above: /sylph-home/re/caps/ in the container.

Evidence PNGs are committed under captures/weapon-datasheet/ (64-colour quantized for size; the numbers stay legible).


Addendum — the in-flight HUD (2026-07-28)

Reached via TUTORIAL → BASIC CONTROLS / HEADS-UP DISPLAY from the title menu (no save needed). Evidence: captures/hud-runtime/.

The HUD corroborates the ammo mapping, independently

The Delta Saber's HUD prints its two equipped weapons as NOSE <TYPE> <AMMO> and MAIN <TYPE> <AMMO>. With the loadout known from the HANGAR (nose = STILETTO BG I, main = FALCON 9AM) the HUD reads NOSE BM 06000 and MAIN MPM 00300 — exactly wep_01_Beam's LoadingCount = 6000 and wep_02_Missile's 300.

This matters because it is not the Arsenal panel: the weapons were identified from the HANGAR loadout, and the numbers come from a different renderer in a different game mode. It is a genuinely independent confirmation of Ammo Capacity == LoadingCount.

The type tags (BM, MPM) are the same short codes as the Arsenal type tabs.

HUD element inventory

HUD element Backing data Conf.
NOSE / MAIN + type tag + 5-digit ammo equipped weapon, LoadingCount
HEAT / L.HEAT bar under each weapon the Heating / Cooling pair 🟡
Speed readout + throttle scale (0, 100, A/B) craft velocity
SHIELD and ARMOR bars (two separate pools) craft HP + a shield pool 🟡
Target reticle: name / type / distance + ring Armor Gauge target unit record 🟡
RANGE gauge with MAIN and NOSE tick markers each equipped weapon's MaximumRange, plotted against target distance 🟡
YOU KILLED: WARSHIPS nnnn + a second counter score / ScorePoint

The RANGE gauge is the interesting one for future work: it draws a per-weapon marker on a distance scale, so a weapon whose MaximumRange is defaulted on disc (wep_25, wep_58, wep_82) would have its value drawn rather than bucketed into a letter — if the scale can be calibrated against two weapons with known ranges, that recovers a real number where the Arsenal panel only gives a class.

Craft velocity

Full afterburner (RT) peaked at 1193 against UN_f001_TCAF_DeltaSaber_T's on-disc MaximumVelocity = 1200. 🟡 PROBABLE — one observation, and the readout may have been still climbing. Cruise sat at 350, which is not the record's CruisingVelocity (700), so the number is the current throttle setting, not a named constant; don't read more into it.

Notes for the next session

  • The tutorials need no save game and are reachable in ~1 min from a cold boot, which makes them the cheapest way back into a live flight scene.
  • tools/re-capture/autopilot.py chases the yellow off-screen waypoint arrow (colour + shape, -sample not -resize, ~0.65 s per detection). It finds the arrow reliably but oscillates — the proportional gain is too high for the craft's turn rate. It needs a damping/derivative term before it can actually fly a waypoint.
  • The HEADS-UP DISPLAY tutorial reaches a scripted targeting segment where the ship stops moving (target distance pinned) and the on-screen controller highlights A; tapping and holding A did not advance it. NEEDS-HUMAN: what input that segment wants.
  • Canary is unstable here: it died twice mid-session (once loading BEAM Resource3D, once hanging on tutorial teardown) with no crash dump. Re-launch is cheap; just don't assume a long session survives.