Files
Syplheed-Reborn/docs/re/arsenal-develop-economy.md
Claude (auto-RE) f88f4f6847 re: the Arsenal develop economy, and the save blob's index space (first 32 confirmed)
GP_HANGAR_ARSENAL.pak's screen config points at weapon.tbl (item ids, in the
8-category display order) and strings.tbl (names, descriptions, and a
"Conditions to obtain" block per item). The id run No_Equipment .. Wep_83 is
exactly 54 long -- the save blob's length -- and all 60 conditions blocks are
extracted to a CSV: gates are stage completion, a predecessor item, or an ace
kill; costs run 3000-350000 P, and 20 items cost nothing once gated (which is
why items the player never bought read as Developed).

Predicting the save state from those conditions -- before looking at the blob --
says exactly six items are developable here, and the blob's six 2s sit on those
six, in weapon.tbl order, at indices 1/5/10/12/27/31. With the four obtained
items and the differential's own two transitions that is twelve concordances
over indices 0-31, nothing fitted. Broad Sword SG1 at index 5 needed scrolling
the GUN list to see, which is the only one the first screenshots missed.

The tail is NOT settled and is marked so: the Tomahawk is weapon.tbl index 38
and the screen shows it Developed, but blob[38] = 0, and the other tail 4s
(33/39/45/46/47) land on items the Arsenal shows as locked -- the SPECIAL tab is
entirely empty. A +1 shift does not repair it either. Settling it needs a second
development in a late category, which needs a mission payout.

Also recorded: IDXD string pools dedupe repeated values, so only the first
record of a table can be read from the token stream -- record 2 shows just its
unique values, record 6 no cost at all.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-11 17:38:45 +00:00

151 lines
7.9 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 Arsenal develop economy, and what the save's blob indexes
**2026-08-11.** The save file's 54-byte blob was shown to be per-item development
state by [a runtime differential](structures/savegame-format.md#the-develop-differential-one-weapon-three-fields) —
one weapon bought, two entries moved, `2 → 4` for the item and `0 → 2` for the
successor. That named the *values*. This note names the *index space*, and in
passing recovers the whole develop economy from the disc.
## Where the Arsenal gets its data
`dat/GP_HANGAR_ARSENAL.pak` carries one screen-config record per language whose
fields point at the rest:
```
PATH = dat\GP_HANGAR_ARSENAL.pak+eng\
WEAPON = weapon.tbl STRINGS = strings.tbl
WEAPON_CATEGORIES = 8 Detail_Window_Known / Detail_Window_Unknown
ConditionToDevelop = 757,228 WeaponDesc = 734,502 Range = 891,73 …
```
`WEAPON_CATEGORIES = 8` is the eight tabs the screen cycles with LB/RB (GUN,
BEAM, LASER, MULTIPURPOSE MISSILE, ANTI-SHIP MISSILE, BOMB/ROCKET, CANNON,
SPECIAL). The `…= x,y` fields are screen positions for that screen's labels —
`ConditionToDevelop` is *where the conditions text is drawn*, not a condition.
### `eng\weapon.tbl` — the item table (IDXD, schema `0x03c244b5`, 66 records)
Its string pool opens with a stage list, then the literal key `WEAPONS`
followed by the item ids **in table order**:
```
No_Equipment, Machiene_Cannon_MG1, Machiene_Cannon_MG2H, Machiene_Cannon_MG3,
Machiene_Cannon_MG5H, Broad_Sword_SG1, Swing_Sword_SG2H, Twin_Sword_SG3II,
Frail_GP37, Stiletto_BG1, Dagger_BG2, Rapier_BG4H, Pilum_BP, … , Wep_83,
Wep_84, Wep_85, NullWeapon_Arm1, NullWeapon_Arm2, NullWeapon_Arm3
```
The ids are grouped by the eight categories in the same order the screen shows
them, which is why `No_Equipment … Wep_83` is exactly **54** entries — the blob's
length.
Each item then has a record: `Size, Weight, Range, Power, Speed, Stage,
MissionObjective, Dependency, Points`. For the **first** record all of it reads
straight out, and it matches the running game exactly:
| field | disc | in-game DATA SHEET for Light Machine Gun MG I |
|---|---|---|
| Range | `D` | `Range Class D` |
| Power | `E` | `Damage Class E` |
| Speed | `-` | `Speed Class ` |
| Weight | `0.3` | `Weight Class Light` |
| Points | `4000` | `4000 P` on the develop row |
**Caveat, and it is a real one:** IDXD string pools store each distinct string
*once*, so from the second record onward every value that repeats an earlier
string is absent from the token stream. Record 2 (MG2H) shows only its unique
values — `0.4` and `3000` — and record 6 shows no number at all because its cost
had already been seen. So `weapon.tbl`'s per-item fields cannot be read from the
pool alone; they need the binary node/index region, which is still undecoded
(see the module docs in `idxd.rs`). The prose table below is the practical
substitute.
### `eng\strings.tbl` — the economy in prose (IXUD, UTF-16BE)
The same pak's string table holds, per item: the internal id, the display name,
the description, and a **"Conditions to obtain …"** block that spells out the
gate and the price:
> Conditions to obtain Light Swivel Machine Gun MG2H — Completed development of
> the Light Machine Gun MG1 — Must spend 3000 points to develop
All 60 of them are extracted to
[`captures/arsenal-develop-conditions.csv`](captures/arsenal-develop-conditions.csv)
with the stage gate, the cost and the prerequisite split out. The shape of the
economy:
- gates are **stage completion** (`Complete Stage 1 … 15`), **a predecessor
item** (`Completed development of the …`), or **an ace kill** (`Shoot down the
ace pilot in Stage 11/13/14`);
- costs run 3 000 → 350 000 points, and **twenty items have no cost at all**
they are granted the moment their gate opens (`Tomahawk Alpha Rail Gun —
Complete Stage 1`), which is why they read as `Developed` in a list the player
never spent points in;
- two items are anomalies worth flagging: `Adhesive Mine B2A` says "Must spend
points to develop" with **no number**, and ten late entries (`Ballista GSH`,
`Designator LH`, `Smoke Marker Launcher`, `Bumble UV`, `Ballista 24 Rocket
Launcher`, `Thrush 220AM`, `Divider L3GP`, `Mace GP25H`, `Thor Gun System`,
`Spitfire BX`) have a conditions *header* and no conditions — ❔ cut content or
non-player weapons.
## What the blob indexes: the first 32 entries, confirmed
Predicting the save state from the conditions and comparing against the actual
blob is a strong test, because it is made **before** looking at the blob. At the
captured state (Stage 1 complete, Stage 02 at standby, 4101 P) the conditions say
exactly six items are developable — Light Machine Gun MG1, Broad Sword SG1,
Dagger BG2, Pilum BP, Hound SMH, Dart 23 Rocket — and the blob's **six** `2`s sit
at WEAPONS-order indices **1, 5, 10, 12, 27, 31**, which are those six items, in
order. Nothing had to be fitted.
| blob | value | item (WEAPONS order) | confirmed by |
|---|---|---|---|
| 0 | 4 | `No_Equipment` | always available |
| 1 | 2→4 | `Machiene_Cannon_MG1` | the differential: bought for 4000 P |
| 2 | 0→2 | `Machiene_Cannon_MG2H` | the differential: announced as newly developable |
| 5 | 2 | `Broad_Sword_SG1` | `BROAD SWORD SG1 5000P`, **below the fold** in the GUN list |
| 9 | 4 | `Stiletto_BG1` | `Developed`; "Initially Mounted"; mounted as NOSE WEAPON |
| 10 | 2 | `Dagger_BG2` | `DAGGER BG2 5000P` |
| 12 | 2 | `Pilum_BP` | `PILUM BP 6000P` |
| 21 | 4 | `Falcon_9AM` | `Developed`; "Initially Mounted"; mounted as MAIN WEAPON 1 |
| 22 | 4 | `Buzzard_10AM` | `Developed`; free at Stage 1 |
| 26 | 4 | `Terrier_SMH` | `Developed`; free at Stage 1 |
| 27 | 2 | `Hound_SMH` | `HOUND SMH 10000P` |
| 31 | 2 | `Dirt_23_Rocket` | `DART 23 ROCKET 3500P` ("Dart" is the localised "Dirt") |
Twelve concordances, no contradiction, over indices 031.
## What the blob does **not** index: the tail is unexplained
Past index 31 the same alignment fails, and it fails against the screen, not
against a theory:
- `Tomahawk_a_Rail_Gun` is WEAPONS index **38** and the CANNON list shows it
`Developed` (it is free once Stage 1 is complete) — but **blob[38] = 0**.
- The blob's remaining `4`s are at **33, 39, 45, 46, 47**. In WEAPONS order those
are `EMP_Mine_B8E`, `Sling_75KG`, `Shield_Doubler`, `Booster`,
`FireControlSystem` — and **every one of them is shown as not developed**:
BOMB/ROCKET lists only `DART 23 ROCKET 3500P`, CANNON only the Tomahawk, and
**the SPECIAL tab is entirely empty** (all rows dashed). Their conditions agree
— Shield Doubler needs Stage 12, Booster an ace kill in Stage 11, FCS Stage 6.
So five `4`s in the tail correspond to nothing the Arsenal reports as owned, and
one genuinely-owned item reads `0`. A single `+1` shift does not repair it
either: `blob[39] = 4` would put the Tomahawk right, but then `blob[33] = 4`
lands on `Arrow_27_Rocket` (Stage 2 + 5000 P, unreachable here) and 45/46/47
still land on locked SPECIAL items.
**Status: ❔ NEEDS-HUMAN / needs the next differential.** The value alphabet and
the first 32 indices are settled; the tail is not, and should not be written into
the reimplementation as if it were. The cheap way to settle it is a second
development in a **late** category (CANNON or SPECIAL) — whichever index moves
names the tail directly. It needs points: the balance is 101 P, so it waits on a
mission payout.
## Evidence
- [`captures/arsenal-develop-conditions.csv`](captures/arsenal-develop-conditions.csv) — all 60 conditions blocks.
- [`captures/arsenal-categories-all.png`](captures/arsenal-categories-all.png) — the eight category tabs.
- [`captures/arsenal-gun-below-fold.png`](captures/arsenal-gun-below-fold.png) — Broad Sword SG1, the entry that is not visible without scrolling.
- [`captures/arsenal-gun-list-predevelop.png`](captures/arsenal-gun-list-predevelop.png) · [`captures/arsenal-mg1-developed.png`](captures/arsenal-mg1-developed.png) — the differential itself.