Resolving the three squadrons the phase-1 script condition polls against the roster: all three are phase-1 (route-name map), all fly UN_e007_ADAN_Turret, all n=9, all on Formation_ADAN_Turret09_30 -- so the condition watches 27 Turrets. Three layers agree independently: route names say phase 1, the roster says what they fly and how many, and the script polls exactly those three before latching set_flag(8). Also confirms on the data that 'Turret' is a craft type, not ship-mounted AA: UN_e007_ADAN_Turret is flown by AI_ADAN_CraftSquadron_Rookie/_Veteran in a 30-slot craft formation, never AI_Structure.
10 KiB
Which squadrons fly in which phase — and the ~300 craft are ~150
Status: ✅ the phase map, read out of Route_S<NN>.tbl record names;
✅ the 387-vs-300 gap explained — the live-craft probe double-counts;
❔ what advances a phase (nothing static encodes it).
✅ The phase map is in the route names
stage\Route_S02.tbl has 121 records: 120 routes + 1 roster, and every route
name matches Route_<squadron>_p<N><kind> — 120/120:
Route_ADN101_p1F Route_TCN003_p2S Route_ADS351_p3M
The phase lives in the name and nowhere else; a route record's only named
field is FrameCount. So the squadron→phase mapping was on the disc all along,
one string-parse away, in a table that was being read for fly-in geometry.
108 of 111 S02 squadrons match a route name exactly. The three that do not —
TCN207, TCN208, TCS252 — are typos in the route table (Route_TCT207_p2S,
Route_TCT208_p2S, Route_TCN252_p2F), plus two orphan routes naming no
squadron (Route_ADS352_p3F, Route_kichi_p3F). All three near-misses are
phase 2, so phase 1 is unaffected.
Phase partition of Stage 02 (Σn = 387 overall):
| phase set | squadrons | Σn |
|---|---|---|
| {1} | 33 | 142 |
| {2} | 31 | 110 |
| {3} | 39 | 118 |
| {1,3} | 2 | 5 |
| {2,3} | 1 | 1 |
| {1,2,3} | 2 | 4 |
| none (the 3 typos) | 3 | 7 |
| per phase | 37 / 34 / 44 | 151 / 115 / 128 |
✅ The 387-vs-~300 gap: the probe counts each craft TWICE
roster-to-craft-link records four failed attempts to explain how the roster becomes "~300 live craft". The premise was wrong — there were never 300 craft.
Phase 1's member-level n multiset against the measured craft-per-record
fan-in (41 records, 300 craft):
phase-1 members (42): n=1 x25 n=2 x1 n=4 x4 n=9 x12 sum 151
observed craft/record: 2 x24 4 x1 8 x4 18 x12 sum 300
observed / 2: 1 x24 2 x1 4 x4 9 x12 sum 150
Every bucket matches shape for shape. The only discrepancy is 24 vs 25 records
at the bottom — the already-documented 41-vs-42 off-by-one, and it is an n=1
record. So 300 = 2 × (151 − 1). Unit type corroborates independently: the 12
records showing 18 craft are all UN_e007_ADAN_Turret, and phase 1 has exactly
12 turret squadrons at n=9.
✅ The factor of 2 is an artifact of the probe, not real units
Two static arguments, and the second is decisive because it is a hard capacity bound:
-
Named pilots. Phase 1's eight
f001members all haven=1and carry distinct identities —Character_Player_Test, ELLEN, RAYMOND, GENE, SANDRA, BILLY, ANTONIUS, CARL. A 2× reading means 16 Delta Sabers for 8 named people. -
Formation slots. Squadrons cannot exceed their formation's
FrameCount(see unit-group-table):reading violations among the 37 phase-1 squadrons Σn ≤ FrameCount(1×)0 2·Σn ≤ FrameCount(2×)20 Including 16 squadrons on
Formation_1_only— one slot,n=1— which a 2× reading would have placing two craft in a one-slot formation.
So the true phase-1 population is ~150, and the 296 / 298 / 300 spread is 2 × a 148 / 149 / 150 population after kills. That all three measurements are even is a further tell a 1:1 count would not produce half the time.
Best explanation of the missing 42nd record: the player's own tuple
(TCN001 member 0, Character_Player_Test), which plausibly is not in the
AI-craft pool the +0x130 def-pointer scan walks. That makes the chain exact:
300 = 2 × (151 − 1 player).
⚠️ This is a static argument about a dynamic measurement. It says the probe's number cannot mean what it was taken to mean; it does not identify what the probe is double-counting. That needs a run — the counting rule in the craft scan is the place to look, not the game.
🔴 Refuted along the way
UnitGroupcarries no phase, spawn time or arrival delay. The raw field dump accounts for every slot:1019 = sum(Count)·4 + 5·111, with positional entries tagged by sequential index (0x0,0x1,0x2,…), not hashes. There is no spare field.DisableIntervalcannot explain Stage 02 — it isNofor all 111 squadrons. Corpus-wide its 31Yesrecords sit in just two stages, S04 (5) and S14 (26), all onGNN***squadrons.stage\EnumSquadron_Test.tbldoes not exist (0x213f4a7eis not in the TOC). It was listed as a candidate for the arrival-interval values; it is dead.AIParams_S02.tblis keyed by AI profile, not squadron, and carries only combat tuning.SUBObjectiveSettings_S02.tblis keyedSUBOBJ_005..014with only points/unlock/HUD strings — no squadron, phase or trigger.
✅ Bonus: the UnitGroup record key, confirmed corpus-wide
A squadron record's key is tag_hash(squadron_id) — 1160/1160 across all 28
stages (ADN101 → 0x659aff47). Same hash as
idxd-tag-hash; this is an independent
confirmation of it on a second kind of table.
❔ Still open: what advances a phase
Nothing static encodes a trigger. Swept the stage record and every table it
names — Route, AIParams, SUBObjectiveSettings, FormationSet, nameplate,
EnumUnit, EnumCharacter, EnumLocalString, EnumWeapon — plus the
message\ family, for field names matching
interval|time|phase|delay|wave|spawn|arrival|trigger|start|appear|event|condition.
The only hits anywhere are FrameCount and PresetMessage_Phase1/2/3 in
message\UnitMessageSet_S02.tbl. The trigger is almost certainly in the
executable, not the data.
Falsifiable predictions for the next run
- Per-record craft counts, in probe units (2×): 4 records at 8 =
ADS151, ADT102, ADT107, ADT113(allUN_e010_ADAN_Attacker_S); 1 record at 4 =TCN105(UN_f106_TCAF_Destroyer); 24 records at 2 = the remaining phase-1n=1members. - A phase advance should move the deployed set toward phase 2: 34 squadrons,
36 members, Σ
n115 (≈230 in probe units). TCN207,TCN208andTCS252may fail to arrive in phase 2, because their routes are misnamed.
🟡 2026-08-25 — first long live observation: no phase advance, and a GAME OVER
Flew Stage 02 with an actively hunting pilot for 936 s while polling the
runtime phase mirror [*(0x828F35F8) + 236] every 3 s (phase_probe.py).
The mirror never left 0. That is what the static work predicts rather than a
contradiction: CScriptInterpreter::ChangePhase (opcode 995) is only posted when
the ordinal is > 1 (the guard in mission-bytecode opcode 0x83), so a run
that stays in phase 1 never writes the mirror. It does mean the mirror is
useless as a "which phase am I in" readout for phase 1 — it reads 0, not 1.
[ScriptMission+40] is the real counter and needs a debugger.
The run ended in GAME OVER — and the pilot's hull was still 1500/1500,
so the player did not die. A script lose-branch fired, and the pilot log says
which one is likely: the tracked asset fell from 100.8 % to 23.4 %, with
ASSET-HIT events logged, while the pilot repeatedly AVOIDed
f101_TCAF_Acropolis — a friendly capital ship — 2588 times.
So the escort was being destroyed throughout, and the mission failed with the player untouched. "Escort lost" is now a measured candidate rather than a guess, though the final asset value was 23.4 %, not 0, so the exact threshold (or whether a different unit's loss ended it) is not established.
So a phase advance still has not been observed. Two runs now — 530 s and
936 s — neither reached phase 2. Combined with the static reading that phase 1
polls unit_state on ADN110/ADN111/ADN112, the likeliest explanation is that
those three squadrons were never destroyed; the pilot hunts whatever is nearest,
not the objective. Next: bias the pilot at those squadrons' craft and re-run.
🔴 Refuted: sub_8226D740 does not read the flag register file
Chasing what reads the 32-entry flag file at [phase+120], the promising hit
was three addi rN, r31, 120 inside sub_8226D740, the per-frame engine→script
trigger edge. It is not the flag file. In that function r31 is a local
trigger-record buffer whose fields are handed to sub_8226E220 as
out-parameters (+80, +84, +88, +92, +112, +120), and lfd f1,120(r31) reads a
double from the record. The phase is in r26/r29.
Offsets 88 and 120 are far too common (2091 and 5228 instructions image-wide,
mostly stack frames) for an offset search to isolate the register files.
Who reads the flags is still unknown, so the chain
set_flag(8) → … → END_PHASE has a gap in the middle.
✅ 2026-08-25 — Stage 02 phase 1: destroy 27 Turrets (ADN110/111/112)
Resolving the three squadrons the phase-1 condition polls
(isl-builtins, unit_state at 0xF524) against
the roster:
| squadron | phases | AI | unit | n |
|---|---|---|---|---|
| ADN110 | 1 | AI_ADAN_CraftSquadron_Rookie |
UN_e007_ADAN_Turret |
9 |
| ADN111 | 1 | AI_ADAN_CraftSquadron_Veteran |
UN_e007_ADAN_Turret |
9 |
| ADN112 | 1 | AI_ADAN_CraftSquadron_Rookie |
UN_e007_ADAN_Turret |
9 |
All three are phase 1 (from the Route_S02 name map), all fly the same
craft, all n = 9 — so the condition watches 27 Turrets, and all three
squadrons share Formation_ADAN_Turret09_30.
Three independent layers agree here, which is the point worth recording: the
route names say these are phase-1 squadrons, the roster says what they
fly and how many, and the script polls exactly these three before latching
set_flag(8).
✅ Confirms "Turret" is a craft type, not ship AA
The user's correction stands on the data: UN_e007_ADAN_Turret is flown by
AI_ADAN_CraftSquadron_Rookie/_Veteran — a craft squadron AI, in a
30-slot craft formation — never AI_Structure. It is an enemy the player fights,
not a gun bolted to a capital ship.
🟡 The prediction to test
If phase 1 clears on those three squadrons dying, then destroying 27 Turrets
while the escort survives should push [ScriptMission+40] to 2 and make
ChangePhase write the mirror at [*(0x828F35F8)+236]. Two runs so far killed
whatever was nearest and never advanced.