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>
14 KiB
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,Burstare 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:
- The match is forced and unique. For 10 of the 11 entries, exactly one record in that
tab carries that number (
600occurs 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-uniqueLoadingCounteleven times running. - 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. - 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_Beamis the corresponding record, and itsLoadingCount6000 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 defaultedPowersits in the D band (≈ 17…150 by the observed edges) andwep_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
LoadingCountis 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 Overlapon-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.pychases the yellow off-screen waypoint arrow (colour + shape,-samplenot-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.