Files
Sylpheed/docs/re/mission-phase-deployment.md
Sylpheed RE agent 4bb4e3691d re: message tables searched — phases are pervasive, the trigger is not in data
StageMessageSet_S02.tbl is resolved. stage-mission-tables.md had recorded it as
absent from the pak; it is present, and the archive prefix is message\ rather
than stage\ like its siblings. Sweeping prefix candidates over the full 16630
entry TOC found it immediately. It holds a voice mapping, a unit message set
pointer, and a list of 31 message tables including ScriptMessage_S02_msg.tbl and
the per-character PresetMessage sets.

message\UnitMessageSet_S02.tbl then gives an independent confirmation of the
phase structure. Its 26 records have exactly four named fields: CrewCount and
PresetMessage_Phase1, Phase2 and Phase3. Every message set carries a different
preset table per phase, so phases now appear in three unrelated table families --
the stage record, the route names, and the message sets. They are not a quirk of
one file.

The promising lead did not survive. ScriptMessage_S02_msg.tbl has 149 records
whose third positional field takes values like Killed and None, which looked
like a trigger. Enumerated across S01 and S02 it is a small closed vocabulary of
None, Emergency, Killed and Noise -- delivery categories for radio chatter,
meaning how a line is played rather than mission control flow -- and the fourth
field is 1 in every record, so it is not an argument either. Rejected.

That leaves no table anywhere carrying a phase-advance condition. Everything
found is a consequence of the phase and never its cause, which points at the
advance logic living in code. The only place left is the executable, and
default.xex is encrypted on disc, so the decrypted image exists only in guest
RAM and reaching it needs a run plus function-level work. Recorded as the honest
end of the static search rather than continuing to guess at table names.
2026-08-24 20:55:34 +00:00

5.4 KiB

Enemies come into play per PHASE, deployed at phase start

Status: 🟡 strongly supported and internally consistent, one unexplained off-by-one; what advances a phase is now the single open question.

This is the answer the wave line of work has been converging on, and it is not the one the route timetable first suggested.

The evidence

Static, from Route_S02.tbl cross-referenced with UnitGroup_S02.tbl:

phase squadrons with routes members
1 37 42
2 34 36
3 44 49
no route 3 3

(Squadrons appear in more than one phase — 37+34+44 = 115 against 111 squadrons — so the member totals overlap and do not sum to 116.)

Dynamic, measured repeatedly across many runs:

deployed = 41 of 116 records, from the first observable instant, never changing

41 deployed against 42 phase-1 members. The deployed set is the phase-1 roster, to within one record.

What this makes coherent

Every previously puzzling observation falls into place:

  • All 116 records exist at mission load — confirmed on two stages — but only the current phase's squadrons hold craft.
  • deployed is 41 before the ready room ends and never moves, because phase 1 deploys as a unit at load rather than on a schedule.
  • No arrival was ever observed in up to 435 s of verified-live flight with 42 kills, because phase 1 never completed in any run — and phases 2 and 3 are where the other 85 members are.
  • The route times are within-phase fly-in timings, not release times, which fits the frames reading (Stage 01 phase 2's t = 1500/1800/2100 → 50/60/70 s at 30 Hz).

So: enemies come into play per phase, deployed together at phase start. The route entry gives each squadron its entrance path and the moment it flies in.

The off-by-one is not explained

41 observed against 42 expected. Candidates, none tested: the player's own record may be counted differently; one squadron may hold craft in a way the liveness read misses; or one phase-1 member may genuinely not deploy. It is recorded rather than rounded away — a one-record gap is exactly the size of the errors that have misled this corpus before.

The single open question: what advances a phase

This is now the whole remaining question, and it is the same one raised many iterations ago in structures/stage-mission-tables.md — the stage record declares Phase_1..3 but nothing found says what ends one.

What is now known that was not then:

  • a phase advance is directly observabledeployed would jump from 41 toward the phase-2 roster, which is unmissable with the current probe;
  • it did not happen in any run, including 435 s of verified-live flight with 42 craft destroyed, so it is not a short timer and not a small kill count;
  • the likely gate is an objective, and SUBObjectiveSettings_S02.tbl names nine of them but carries only rewards and HUD strings — no trigger.

Places not yet looked: StageMessageSet_S02.tbl (never resolved in GP_MAIN_GAME_E.pak), and the executable, whose decrypted image is only available in guest RAM.


Hunting the phase trigger in the message tables (2026-08-24)

StageMessageSet_S<NN>.tbl resolved — the prefix is message\

structures/stage-mission-tables.md recorded this table as , "not in GP_MAIN_GAME_E.pak under that name". It is there; the archive prefix is message\, not stage\ like its siblings. Sweeping the prefix candidates over the full 16 630-entry TOC found it immediately.

It holds three records — VoiceID2SndID, UnitMessageSetTable, and a Files list of 31 message tables: ScriptMessage_S02_msg.tbl, ScriptMessage_S02guide_msg.tbl, DemoMessage_S02_msg.tbl, and per-character PresetMessage_* sets.

Phases are a first-class runtime concept, confirmed independently

message\UnitMessageSet_S02.tbl (26 records) has exactly four named fields:

CrewCount, PresetMessage_Phase1, PresetMessage_Phase2, PresetMessage_Phase3

Every message set carries a different preset message table per phase. That is a third, independent table family organised around Phase_1..3, after the stage record and the route names. Phases are not a quirk of one file.

🔴 Refuted: the script-message trigger field is not a phase trigger

ScriptMessage_S02_msg.tbl has 149 records whose third positional field looked promising — values like Killed alongside None. Enumerated across the corpus it is a small closed vocabulary:

value S02 S01
None 105 72
Emergency 33 5
Killed 5 2
Noise 5 8

These are delivery categories for radio chatter — how a line is played (urgent, over static, on a death) — not mission control flow. The fourth field is 1 in every single record, so it is not an argument either. Rejected.

No table carries a phase-advance condition

Phases now appear in the stage record, in route names, and in message sets, and not one of those files says what ends a phase. Everything found is a consequence of the phase, never its cause.

That points at the advance logic living in code rather than data. The only place left is the executable, and default.xex is encrypted on disc — the decrypted image exists only in guest RAM, which means a run plus function-level work.

Recorded as the honest end of the static search rather than continuing to guess at table names.