Files
Sylpheed/docs/re/structures/unit-datasheet-schema.md
Sylpheed RE agent 80b83235c8 re: the unit family is the only schema on the disc; an .xpr search cannot prove absence
Two exhaustive probes agree on the same 15 records. The six Shift-JIS type words
occur in the six GP_MAIN_GAME_* paks and nowhere else, and a disc-wide sweep of
every parsed record name for a wildcard shape (???, *, ###, NNN, <...>) returns
7 distinct names - exactly the seven already in the schema: Turret_???,
Hatch_???, Bridge_???, Thruster_???, ShieldGenerator_???, Versatile_???, NS_*,
each x6. So the weapon datasheet, the arsenal item and StageResource ship NO
schema; the unit datasheet is the only structure the disc describes to itself.
Wildcard field names are confined to the schema records too - NozzleSpec_???,
NozzleFrame_???, CannonFrame_???, MuzzleFrame_???.

No untyped gaps either. The full residual is 30 slots and every one holds a
sample value rather than a missing type: 28 booleans spelled Yes, plus
Generic.ID = Ship_ and Generic.Type = Vessel. The booleans follow one pattern -
the six destructible part types each carry the same four-boolean core
(IsDestructible, IsInvolved, IsRadarVisible, IsShielded), Turret_??? adds IsAuto,
Generic carries only IsDestructible, and NS_* has its own pair AttenuationAlpha /
AttenuationVolume. 28 + 2 = 30; 7 fully-typed records + 8 with examples = 15.

The third result is a refutation of my own instrument. Testing the four
genuinely-undeclared effects against the 166 .xpr packages put eff_f0002 and
eff_f0002_barn in Base.xpr and found nothing for eff_e0044 or eff_h308 - but the
control kills the negative: eff_n0071, which we measured LIVE as an Explosion
record's ExplosionFxModel, also returns nothing from the same search. A
known-live name the test cannot find means the test has no power here. Only the
positive half counts: eff_f0002/_barn do ship. Nothing follows about eff_e0044
or eff_h308, and the earlier "no mesh" remarks about eff_e0058/_e0059/_e0060 are
weaker than written - absent from a byte search over .xpr is not absent from the
disc. How an effect mesh is actually reached is now the open question, since
eff_n0071 is not a plain name string in any of the 166 packages.

All sixteen artefacts byte-identical.
2026-08-28 08:38:26 +00:00

120 lines
5.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ✅ The unit datasheet ships its own schema
Chasing the previous iteration's Shift-JIS value turned up something much larger
than the placeholder I called it. **Correction to that entry: `文字列` is not a
developer's leftover — it is one member of a six-word *type* vocabulary, and the
records carrying it are a machine-readable schema for the unit datasheet.**
## The whole non-ASCII population is six words
Across every parsed IDXD string on the disc:
| | distinct | non-ASCII |
|---|---|---|
| values | 99 328 | **6** |
| record names | 3 496 | 0 |
| field names | 12 173 | 0 |
All six decode cleanly as Shift-JIS, and all six are type names:
| bytes | Shift-JIS | meaning | uses |
|---|---|---|---|
| `95B68E9A97F1` | `文字列` | string | 366 |
| `4E535F22…22` | `NS_"文字列"` | NS_ string | 12 |
| `90AE9094` | `整数` | integer | 66 |
| `90AE9094926C` | `整数値` | integer value | 6 |
| `958293AE8FAC9094926C` | `浮動小数値` | floating-point value | 504 |
| `…5B308160315D` | `浮動小数値[0〜1]` | float in [0,1] | 36 |
990 type-valued fields in total. So the reader defect noted last time is real but
**bounded to these six strings** — nothing else on the disc is non-ASCII, and
`name_hash` re-encodes Latin-1 byte-for-byte, so hashing was never affected.
## 15 wildcard schema records, one per substructure
The 990 fields sit in **15 records × 6 `GP_MAIN_GAME_*` paks = 90 instances**,
i.e. **15 records with one user** under the per-pak-copy rule. Their names are
exactly the unit substructure family — and six of them carry a literal wildcard:
`Generic`, `Maneuver`, `Effect`, `Shield`, `Mass`, `SE`, `Explosion`,
`StructureCount`, plus `Turret_???`, `Hatch_???`, `Bridge_???`, `Thruster_???`,
`ShieldGenerator_???`, `Versatile_???` and `NS_*`.
🔑 **`???` is the numeric-suffix wildcard**, at record *and* field level:
`Turret_???` is the schema for `Turret_000…00N`, and inside it
`CannonFrame_???` / `MuzzleFrame_???` stand for the numbered frame slots.
⚠️ The control separates schema from data cleanly. The six `_???` records and
`NS_*` exist **only** as schema — 6 of 6 instances typed. The eight real
substructure names are typed in 6 instances and untyped in the rest:
`Generic` 6 of 3 651, `Maneuver`/`Shield`/`Mass`/`SE`/`Explosion`/`Effect`/
`StructureCount` 6 of 684 each. A schema record is one extra instance of a name
the datasheets already use.
## Where the type is an enum, the schema holds an example
Not every field is typed — `Generic` is 20 typed of 23, `Turret_???` 20 of 25.
The untyped slots hold a **sample value** instead, which names the enum:
| field | schema slot | reading |
|---|---|---|
| `IsDestructible`, `IsAuto`, `IsShielded`, `IsRadarVisible`, `IsInvolved` | `Yes` | boolean |
| `Generic.Type` | `Vessel` | the Craft/Vessel enum (43 + 71) |
| `Generic.ID` | `Ship_` | the ID *prefix* convention |
`Maneuver` is the one fully-typed record: **34 of 34**.
Two readings worth keeping for the port:
* every `ResistanceTo*` (`Shell`, `Explosion`, `Optics`) and every `Color_*`
channel is **`FLOAT[0..1]`** — declared normalised, matching the sampled
values (`ResistanceToShell 0.1`, `ResistanceToExplosion 0.5`) in
[[unit-datasheet-static]];
* `Generic.NozzleSpec_???` has its own type `NS_"文字列"`, and `NS_*` is a
record — the nozzle spec is a nested sub-schema, not a plain string.
⚠️ `Turret_???` carries the game's own typo **`NomalModel`** (beside
`DamagedModel`), which is a join key in the usual way.
This is the authoritative field-type table for the unit datasheet: types the
disc declares, rather than types inferred from sampled values.
Regenerate with `tools/re-capture/datasheet_schema.py` →
[`docs/re/data/datasheet-schema.txt`](../data/datasheet-schema.txt).
## ✅ The unit family is the only schema on the disc
Two independent probes, both exhaustive, both landing on the same 15 records:
* **the type words** — the six Shift-JIS type names occur in the six
`GP_MAIN_GAME_*` paks and nowhere else;
* **the wildcard names** — sweeping every parsed record name disc-wide for a
`???`, `*`, `###`, `NNN` or `<…>` shape returns **7 distinct names**, and they
are *exactly* the seven already in the schema (`Turret_???`, `Hatch_???`,
`Bridge_???`, `Thruster_???`, `ShieldGenerator_???`, `Versatile_???`, `NS_*`),
each ×6.
So the weapon datasheet, the arsenal item and `StageResource` ship **no**
schema — the unit datasheet is the only structure the disc describes to itself.
The wildcard *field* names are likewise confined to the schema records:
`NozzleSpec_???`, `NozzleFrame_???`, `CannonFrame_???`, `MuzzleFrame_???`.
## ✅ Every untyped slot is an example — 30 of 30, no gaps
The full untyped residual across all 15 schema records is **30 slots**, and
every one holds a sample value rather than a missing type:
* **28 booleans** spelled `Yes`, and they follow one pattern — the six
destructible part types (`Turret_???`, `Hatch_???`, `Bridge_???`,
`Thruster_???`, `ShieldGenerator_???`, `Versatile_???`) each carry the same
four-boolean core **`IsDestructible`, `IsInvolved`, `IsRadarVisible`,
`IsShielded`**; `Turret_???` adds `IsAuto`; `Generic` carries only
`IsDestructible`; `NS_*` has its own pair `AttenuationAlpha` /
`AttenuationVolume`;
* `Generic.ID` = `Ship_` (the prefix) and `Generic.Type` = `Vessel` (the enum).
`28 + 2 = 30`. **Seven of the fifteen records are fully typed** (`Maneuver`,
`Shield`, `Mass`, `SE`, `Explosion`, `Effect`, `StructureCount`) and eight carry
examples: `7 + 8 = 15`. There is no field anywhere in the schema whose type the
disc leaves unstated.