# 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 0–31. ## 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.