re: mission scripts are readable as dialogue (2683/2683 message calls resolve)

Built-in 64's slot-0 operand is a symbol-table-1 type-6 message id, and every
one of them now has caption text: 2683 of 2683 call sites across the 28 stage
scripts, 1338 distinct names, no residue of any kind.

This only became reachable once build_caption_text was switched to the IXUD
field table (537 -> 8800 lines); before that most of these names had nothing
to resolve to.

Adds isl_dialogue.py plus a committed Stage 02 sample. Does not settle which
recording plays for a given line, multi-page captions, or the other five
languages.
This commit is contained in:
Sylpheed RE agent
2026-08-26 03:09:10 +00:00
parent 253b960f56
commit 7c4595cbf9
3 changed files with 432 additions and 0 deletions

View File

@@ -0,0 +1,220 @@
# Stage02.ssb — dialogue, in script order
Generated by `tools/re-capture/isl_dialogue.py`. Each line is one
`request_script_message` (built-in 64) and the caption it plays.
213 message calls, 213 with text.
004EFC MSG_VOICE_D_252 Rhino 3 has been shot down!
004FA4 MSG_VOICE_D_254 I've lost contact with Rhino 3!
00504C MSG_VOICE_D_256 Katana, come in! Katanaaaa!
0050F4 MSG_VOICE_D_257 Katana! Damn it!
0053C8 MSG_ACRO_034 This is an emergency announcement from the bridge! The ship is operational! All personnel evacuate immediately!
005470 MSG_ACRO_055 Looks like this is it! All personnel, abandon ship!
005518 MSG_ACRO_086 Captain! The ACROPOLIS can't go any further!
0055C0 MSG_VOICE_D_258 The ACROPOLIS has been crippled.
005668 MSG_VOICE_D_260 Katana, the ACROPOLIS has been destroyed!
005710 MSG_VOICE_D_261 Damn, they got the ACROPOLIS! た!
005AE4 MSG_VOICE_A_162 Katana, are you sure you're a rookie? You're too good!
005F80 MSG_VOICE_D_100 This foolishness can't last forever. We're still in good shape!
0061D0 MSG_VOICE_D_259 This is the TCAF ACROPOLIS. We are unable to continue combat!
0064C0 MSG_VOICE_D_180 We're okay now. Thanks for the backup!
006588 MSG_VOICE_D_183 The ship is in the clear now.
0069A4 MSG_VOICE_D_383 One fleet of the enemy targets has been destroyed!
007530 MSG_VOICE_D_285 Targets sighted! They're coming right for us!
0075D8 MSG_VOICE_A_120 Listen, aim for the attackers. Do not let the attackers near the base or the ACROPOLIS.
007678 MSG_VOICE_A_139 The Terran ships are blocking our path!
0077E8 MSG_VOICE_A_141 Enemy fleet sighted. Let's take care of two birds with one stone. All ships prepare to attack!
007898 MSG_VOICE_A_153 Katana, find the enemy attackers and coordinate your attacks with Ellen.
007948 MSG_VOICE_A_126 I repeat, a group of enemy aircraft is approaching! They're heading for Schlos Base!
0079F8 MSG_VOICE_A_124 Radar shows a group of enemy attackers on a direct course for the ACROPOLIS!
007A98 MSG_VOICE_A_152 Listen, if the ACROPOLIS gets in trouble, we have to bail it out fast!
007B48 MSG_VOICE_A_128 Enemy reinforcements! All units, intercept!
007BE8 MSG_VOICE_A_155 You're not getting to Schlos!
007C98 MSG_VOICE_A_123 Another group of attackers has appeared! All ships move to intercept them at once!
007D38 MSG_VOICE_A_169 No matter how many I shoot down, there's always more!
007DE8 MSG_VOICE_A_127 Captain, another group of enemy units is approaching! They could be fighters!
007E88 MSG_VOICE_A_163 This place is swarming with ADAN. When did they get so many ships?
007F38 MSG_VOICE_A_164 This is just like a real war.
007FE8 MSG_VOICE_A_174 Uppity backwater colonists!
008088 MSG_VOICE_A_175 Don't let any of them escape! Fire hard and heavy!
008138 MSG_VOICE_A_166 Don't get pulled into battle with the main fleet.
0081E8 MSG_VOICE_A_003 Finish them off in 3 minutes!
008298 MSG_VOICE_A_004 2 minutes left! Hurry!
008348 MSG_VOICE_A_005 1 minute left! No time to slack off!
0083F8 MSG_VOICE_A_006 Only 30 seconds left!
0085C8 MSG_VOICE_A_168 Damn it! Cut me some slack here!
008744 MSG_VOICE_A_125 A group of enemy aircraft is approaching!
0088C0 MSG_VOICE_A_156 There's too many! We can't stop them all!
008960 MSG_VOICE_A_142 It's time to take back everything you Terran scum stole from us!
008B30 MSG_VOICE_A_171 We've got to keep the enemy away from the ACROPOLIS! Cover me!
008CCC MSG_VOICE_D_286 Attackers approaching!
008D6C MSG_VOICE_A_157 Make sure you don't get hit! If even one of us dies here, we all go down!
008E0C MSG_VOICE_A_158 Who would've thought the ADAN fleet was this big.
008F10 MSG_VOICE_A_144 What are those orange ships? They don't look like normal ARROWHEADS!
009080 MSG_VOICE_D_340 All right! Good work!
009120 MSG_VOICE_A_159 Hey, Gene, do you have your shields up?
009224 MSG_VOICE_A_173 Hey, what squadron are those orange fighters from? I've never seen ships like that before.
009360 MSG_VOICE_D_160 The enemies have been destroyed. We're in the clear, Captain!
009400 MSG_VOICE_A_160 Even with shields, this Delta Saber isn't all that different from my old ARROWHEAD. I've already got it all figured out!
0094A0 MSG_VOICE_A_151 ACROPOLIS to all flights. If you run low on ammunition, return and resupply as necessary.
0095A4 MSG_VOICE_A_136 How could this happen? We're the only ones left!
0096CC MSG_VOICE_A_138 More enemies have entered Sector 37!
0097D0 MSG_VOICE_A_135 Damn, this is bad! The way things are going now, Brandon's lucky he died first!
0099D4 MSG_VOICE_D_000 This is the TCAF CHARON 027. Requesting backup immediately. We're surrounded by enemy fighters!
009B70 MSG_VOICE_D_001 All right, we managed to hang in there. Hurry with those emergency repairs!
009CE0 MSG_VOICE_A_167 I can't shake him!
009EE0 MSG_VOICE_D_155 Captain, the enemy is closing in on our ship!
009FE4 MSG_VOICE_D_157 This is the ACROPOLIS! We're taking concentrated fire! Requesting immediate backup!
00A084 MSG_VOICE_D_159 Katana, it looks like the ACROPOLIS is in trouble! We have to help them!
00A374 MSG_VOICE_D_287 Katana, those attackers are our targets!
00A51C MSG_VOICE_D_288 There's an attacker over there!
00BD2C MSG_VOICE_D_350 Katana, we're pretty banged up. Let's head back to the ACROPOLIS for repairs.
00EA64 MSG_VOICE_D_290 This is bad! Protect the ACROPOLIS! Otherwise, we won't have anywhere to return to!
00EB18 MSG_VOICE_D_291 The ACROPOLIS is taking a beating! Katana, help them!
00F91C MSG_VOICE_D_354 When you get close enough to resupply, information will appear on your indicator.
0108BC MSG_VOICE_D_292 Katana, what are you doing? We have to help the ACROPOLIS! Hurry!
010B4C MSG_VOICE_D_295 We're going to help them, right? It's our duty!
010E6C MSG_VOICE_D_296 Rhino 4 to CHARON 027. We're here to assist you!
01104C MSG_VOICE_D_298 We'll let another unit handle the CHARON. We wouldn't make it there in time anyway.
01126C MSG_VOICE_D_341 Katana, well done!
0137E0 MSG_VOICE_D_349 Hey, Katana. Why aren't you following your directives?
014320 MSG_VOICE_D_348 You aren't listening to me at all, are you Katana? Fine, I'll keep my advice to myself then.
0143E8 MSG_VOICE_D_347 Katana, do you think you should act on your own so much? Sometimes it's best to just follow orders.
0144B0 MSG_VOICE_D_346 Hey Katana. Are you going to ignore your orders? Don't come crying to me if the Leader gets mad.
0145CC MSG_VOICE_D_293 The CHARON 027 is under attack by enemy fighters. They are requesting aid from any nearby units.
0147EC MSG_VOICE_D_294 It looks like the CHARON is very far away. What should we do?
019358 MSG_VOICE_D_252 Rhino 3 has been shot down!
019400 MSG_VOICE_D_254 I've lost contact with Rhino 3!
0194A8 MSG_VOICE_D_256 Katana, come in! Katanaaaa!
019550 MSG_VOICE_D_257 Katana! Damn it!
0197F8 MSG_VOICE_A_182 But how? Is this the end for me?
0198A4 MSG_VOICE_A_183 Admiral Vieira's ship has been shot down!
01A824 MSG_VOICE_B_079 They've broken through! Inform Headquarters!
01AA20 MSG_VOICE_D_089 Magnificent! We broke through without taking a single hit!
01AAE0 MSG_TCAF_480 Yes! Watch and weep, ADAN!
01F2C4 MSG_VOICE_A_176 Rhino Leader, I've sent a tanker around to your location.
01F364 MSG_VOICE_A_177 Raymond, we'll take care of the ACROPOLIS.
01F51C MSG_VOICE_A_201 Katana, I'm worried about the ACROPOLIS. I wonder how things are going at Schlos Base.
01F5CC MSG_VOICE_A_200 Right now all we can do is protect the flagship.
01F67C MSG_VOICE_A_203 You just got drafted, didn't you? Well, that's the reality of war. I feel sorry for you, kid.
01F72C MSG_VOICE_A_184 Object approaching Schlos Base at high speed!
01F904 MSG_VOICE_A_179 That could be the TCAF's flagship! Do whatever it takes to bring it down!
01F9A4 MSG_VOICE_A_181 The enemy is aiming for our ship! Where is our support?
01FA64 MSG_VOICE_D_299 Katana, destroy the ship's engine to stop them in their tracks! Don't let them near the flagship!
01FC3C MSG_VOICE_A_180 Cannons ready! Don't let the enemy flagship escape!
020490 MSG_VOICE_A_190 When attacking an enemy ship, you can't just go in firing blindly. You've got to disable the ship's functionality.
020530 MSG_VOICE_A_191 Destroy the enemy's shield projector or weapons first for an easier victory. Keep that in mind, Katana!
0205D0 MSG_VOICE_A_192 If you destroy the shield projectors, we can use our beam weapons more effectively.
020670 MSG_VOICE_A_194 Aim for the enemy's weapons to weaken their offense.
020710 MSG_VOICE_A_195 Destroy the enemy's engine so they can't move.
0207B0 MSG_VOICE_A_196 Another effective technique is to hit the bridge so you can disrupt its command system.
020964 MSG_VOICE_A_197 Rhinos, don't let the CALIBAN out of your sight.
020B3C MSG_VOICE_A_185 Enemies approaching from directly ahead!
020CF8 MSG_VOICE_A_187 Don't let them near this ship! Now all your training will pay off!
020D98 MSG_VOICE_A_199 Hey, Katana, isn't that Admiral a jerk? I hate him!
020F18 MSG_VOICE_A_202 Stay alert! Any enemies here are likely to attack us all at once!
0210F0 MSG_VOICE_D_162 Admiral Vieira, enemies are approaching our ship!
0212AC MSG_VOICE_D_002 This is the AMALTHEA. We're surrounded by the enemy. Requesting immediate backup!
0213E4 MSG_VOICE_D_304 We're receiving a request for aid from the cruiser AMALTHEA. Any units in the area, please assist them.
021608 MSG_VOICE_D_003 Thank you for the support! We should be okay on our own now!
0216A8 MSG_VOICE_D_004 All fighters scramble immediately! Now it's our turn to help our comrades!
0218E0 MSG_VOICE_A_188 What are you doing? Dispose of them right now!
021A08 MSG_VOICE_A_189 What are you waiting for? Are those Delta Sabers of yours junk?
021B0C MSG_VOICE_D_175 Damn, somebody get these guys off of us! At this rate we'll be sunk in no time!
021BAC MSG_VOICE_D_176 Katana, one of our ships is in trouble. Should we go help them?
021CAC MSG_VOICE_D_175 Damn, somebody get these guys off of us! At this rate we'll be sunk in no time!
021D4C MSG_VOICE_D_176 Katana, one of our ships is in trouble. Should we go help them?
021E10 MSG_VOICE_D_166 That took you long enough! Now get rid of the rest!
021EF8 MSG_VOICE_D_167 Admiral Vieira's ship is safe!
022034 MSG_VOICE_A_198 Don't stray too far from the CALIBAN. Protecting it is our first priority.
022878 MSG_VOICE_D_351 Katana, we're in pretty bad shape. We should head to the tanker soon for repairs.
022918 MSG_VOICE_D_357 Katana, can you see it? The tanker is over there.
023180 MSG_VOICE_D_305 The AMALTHEA is very far away! Can we make it in time?
023948 MSG_VOICE_D_300 This is some pretty heavy fire. Katana, Ellen, destroy that ship's weapons. We can't let the flagship take any more hits!
023A64 MSG_VOICE_D_354 When you get close enough to resupply, information will appear on your indicator.
023DE0 MSG_VOICE_D_306 Assist the AMALTHEA? Roger!
0241D0 MSG_VOICE_D_307 Yeah, there's nothing we can do. If we leave the flagship there's no telling what he'll say.
0249D4 MSG_VOICE_D_303 This guy is pretty tough. Katana, can you take out the enemy's shield projector?
0298A0 MSG_VOICE_D_007 Captain, enemy forces are closing in!
029940 MSG_VOICE_D_006 The Terran forces are in disarray! Hit their carrier!
029C48 MSG_VOICE_A_206 An enemy missile has been fired. There's only one!
02A368 MSG_VOICE_A_212 More enemy cruise missiles have jumped out! How many does that make?
02A408 MSG_VOICE_A_210 We've picked up more incoming objects. 2 missiles!
02A4A8 MSG_VOICE_A_231 It's up to our squadron to stop the missiles!
02B47C MSG_VOICE_A_208 Three more enemy cruise missiles are approaching!
02B684 MSG_VOICE_D_252 Rhino 3 has been shot down!
02B72C MSG_VOICE_D_254 I've lost contact with Rhino 3!
02B7D4 MSG_VOICE_D_256 Katana, come in! Katanaaaa!
02B87C MSG_VOICE_D_257 Katana! Damn it!
02BB50 MSG_ACRO_034 This is an emergency announcement from the bridge! The ship is operational! All personnel evacuate immediately!
02BBF8 MSG_ACRO_055 Looks like this is it! All personnel, abandon ship!
02BCA0 MSG_ACRO_086 Captain! The ACROPOLIS can't go any further!
02BD48 MSG_VOICE_D_258 The ACROPOLIS has been crippled.
02BDF0 MSG_VOICE_D_260 Katana, the ACROPOLIS has been destroyed!
02BE98 MSG_VOICE_D_261 Damn, they got the ACROPOLIS! た!
02C150 MSG_VOICE_A_222 Captain, we've lost contact with Schlos Base!
02CC00 MSG_VOICE_D_008 The enemy forces have been destroyed!
02CD08 MSG_VOICE_D_012 Thanks to you all, we kept damages to the base to a minimum. You have my gratitude!
02CDB0 MSG_VOICE_D_345 I'm glad that went well.
02D140 MSG_VOICE_D_345 I'm glad that went well.
02D3F0 MSG_VOICE_A_216 A cruise missile has hit the base!
02D574 MSG_VOICE_A_216 A cruise missile has hit the base!
02D6F8 MSG_VOICE_A_216 A cruise missile has hit the base!
02D87C MSG_VOICE_A_216 A cruise missile has hit the base!
02DA00 MSG_VOICE_A_216 A cruise missile has hit the base!
02DB90 MSG_VOICE_A_216 A cruise missile has hit the base!
02DD14 MSG_VOICE_A_216 A cruise missile has hit the base!
02DE98 MSG_VOICE_A_216 A cruise missile has hit the base!
02E3F8 MSG_VOICE_A_207 Two more enemy missiles have been fired!
02E4B8 MSG_VOICE_D_308 Target the marks! Understood! missile in front of you!
02E560 MSG_VOICE_A_205 TCAF Schlos Base to ACROPOLIS. Are you able to intercept an enemy cruise missile?
02E6D0 MSG_VOICE_A_244 As soon as we recover a signal, we can send for help from the neighboring systems. Until then, hang in there!
02E770 MSG_VOICE_A_245 You ADAN dogs! Get back to the colonies where you belong!
02E820 MSG_VOICE_A_253 They're putting up more of a fight than expected. Get rid of those pesky fighters first!
02E8C0 MSG_VOICE_A_238 Don't let the missiles get near the base!
02E970 MSG_VOICE_A_246 This isn't an exercise! This is real combat!
02EA20 MSG_VOICE_A_247 We mustn't allow them to attack Lebendorf!
02EAD0 MSG_VOICE_A_228 Has there been contact from any nearby fleets?
02EB80 MSG_VOICE_A_248 Ah, and to think I was almost up for leave! Why did this have to happen now?
02EC30 MSG_VOICE_A_249 Do whatever it takes to protect Schlos Base!
02EE08 MSG_VOICE_A_256 That carrier is in the way! Shoot it down!
02EF88 MSG_VOICE_A_255 Set a new course! Drive off the TCAF fighters!
02F028 MSG_VOICE_A_257 Shoot down the TCAF that are harrying the missiles!
02F1F8 MSG_VOICE_A_239 Whoa, what sort of missiles are these? They're huge!
02F298 MSG_VOICE_A_240 ADAN's really outdone themselves. Let's show 'em we can handle whatever they got!
02F39C MSG_VOICE_D_008 The enemy forces have been destroyed!
02F43C MSG_VOICE_D_009 Don't let the fighters have all the glory. Regroup!
02F540 MSG_VOICE_D_158 Get rid of the enemies around the ACROPOLIS!
02F774 MSG_VOICE_A_215 All right! All the cruise missiles on this side are down! Raymond, what's the situation over there?
02F814 MSG_VOICE_A_241 How many are left?
02F904 MSG_VOICE_A_224 That's the last missile! Take it down!
02F9AC MSG_VOICE_A_223 Only one missile left to go!
02FAEC MSG_VOICE_A_251 A missile has been shot down!
02FB8C MSG_VOICE_A_236 Aim for the tips of the missiles!
02FCB8 MSG_VOICE_A_237 Hey, did the Admiral really just run away?
02FDE4 MSG_VOICE_A_251 A missile has been shot down!
02FF10 MSG_VOICE_A_252 Captain, quite a few of our cruise missiles have been shot down by the enemy!
03003C MSG_VOICE_A_242 Hey, those guys from the ACROPOLIS are pretty good!
0300DC MSG_VOICE_A_243 Look at the way those prototypes move! Those guys from the Genius Program are the real deal after all.
030208 MSG_VOICE_A_251 A missile has been shot down!
030858 MSG_VOICE_A_213 Commodore, more enemy missiles are approaching!
03091C MSG_VOICE_A_221 All right! Look at those fireworks!
0309BC MSG_VOICE_A_217 Pilots, the base can't take any more! We're counting on you!
030A80 MSG_VOICE_A_227 Do whatever it takes to stop those missiles!
030B68 MSG_VOICE_A_219 I don't care what you do, just don't let any more missiles get by! Direct all weapons systems towards stopping them!
030C08 MSG_VOICE_A_225 Fires are in Blocks D7 and D8! Fire control squads, respond!
030CA8 MSG_VOICE_A_229 Give me a report on the damage to the base!
030DB4 MSG_VOICE_A_218 An enemy missile has hit! Damage is severe!
030E54 MSG_VOICE_A_220 Their base has been hit! They're on their last legs!
030EF4 MSG_VOICE_A_230 Prepare for the worst! Evacuate all non-combat personnel.
030FB8 MSG_VOICE_A_226 Air pressure is dropping in Block F11! All personnel, evacuate the area!
031DD4 MSG_VOICE_D_351 Katana, we're in pretty bad shape. We should head to the tanker soon for repairs.
031E74 MSG_VOICE_D_357 Katana, can you see it? The tanker is over there.
032E84 MSG_VOICE_D_354 When you get close enough to resupply, information will appear on your indicator.
03313C MSG_VOICE_D_319 We're going to help the ACROPOLIS, right? Roger!
033418 MSG_VOICE_D_344 You did it, Katana!
0340F0 MSG_VOICE_D_312 Katana, what are you doing? We're supposed to attack the one with the marker!
0341B8 MSG_VOICE_D_311 Wrong one, Katana! You have to aim for the one with the marker!
034280 MSG_VOICE_D_309 Damn, this missile can take a beating!
0345E4 MSG_VOICE_D_316 Katana, that missile is getting close to the base. We have to stop it!

View File

@@ -0,0 +1,70 @@
# ISL `request_script_message` → caption text
**✅ Settled 2026-08-26.** Every mission-script message call resolves to the
dialogue line it plays. The 28 stage scripts are readable as dialogue.
## The link
Built-in **64** (`request_script_message`) takes one operand in slot 0: a
two-word symbol reference into **symbol table 1**. The symbol's name is a
message id such as `MSG_VOICE_D_257`. The text lives in the language pack's
IXUD blocks (`dat/GP_MAIN_GAME_<lang>.pak`) as a **named field** whose key is
`<id>_<page>_<line>`, read via the record/field table documented in
[idxd-container.md](idxd-container.md).
MSG_VOICE_D_257 → field key `MSG_VOICE_D_257_000_00` → "Katana! Damn it!"
## Evidence
Measured over all 28 `StageNN.ssb`:
| | |
|---|---|
| built-in 64 call sites | **2683** |
| slot 0 not staged | 0 |
| operand not in symbol table 1 | 0 |
| operand symbol type | **6** at all 2683 sites |
| distinct message names | 1338 |
| names with caption text at `_000_00` | **2683 / 2683 (100 %)** |
There is no residue: no call site takes a different operand shape, no name is
of a type other than 6, and no name is missing from the caption table. That
totality is the result — a partial rate would have meant the operand encoding
was only sometimes what I thought it was.
Name families and their share of call sites:
MSG_VOICE 2407 MSG_ADAN 118 MSG_ACRO 82
MSG_ADPL 38 MSG_TCAF 35 MSG_RHIN 3
`MSG_VOICE_*` is crew/wingman dialogue; the four-letter families are
ship-side announcements (`ACRO` = ACROPOLIS, `ADAN`/`ADPL` = ADAN,
`TCAF`, `RHIN` = Rhino flight).
## Why this was not obvious earlier
The caption table only became readable on 2026-08-25, when `build_caption_text`
was switched from scraping adjacent string-pool tokens to reading the IXUD
**field** table — which took the extractable line count from 537 to 8800
(8800 of 8800 distinct keys). Before that the great majority of these 1338
names had no text to resolve *to*, and the 100 % figure was unreachable.
## What this does not settle
* **Which recording plays.** The caption is the *text*; the voice bank binding
is a separate and still-unresolved question — see
[voice-bank-leading-region.md](voice-bank-leading-region.md) and the
known case of a generic line playing against a specific subtitle.
* **Multi-line captions.** `isl_dialogue.py` concatenates pages `_000_00`
through `_000_03`. Whether the game wraps by page or by line, and whether
any id uses a page other than `000`, is unmeasured.
* **The other five languages.** Only the English pack was swept.
* **Ordering.** The tool prints call sites in file order, which is *script*
order, not necessarily *play* order — phases and branches are not resolved.
## Tool
tools/re-capture/isl_dialogue.py <StageNN.ssb> [GP_MAIN_GAME_E.pak]
Sample output committed at [../data/isl-stage02-dialogue.txt](../data/isl-stage02-dialogue.txt)
(Stage 02, 213 message calls, 213 with text).

View File

@@ -0,0 +1,142 @@
#!/usr/bin/env python3
"""Render a mission script's dialogue: every `request_script_message` in order,
with the caption text it plays.
isl_dialogue.py <StageNN.ssb> [GP_MAIN_GAME_E.pak]
Built-in 64 takes a symbol-table-1 (type 6) message name; the caption text lives
in the pack's IXUD blocks under `<name>_<page>_<line>`. All 2683 call sites
across the 28 stages resolve, so this is a total mapping rather than a sample.
"""
import collections
import struct
import sys
import isl
NO_NAME = 0xFFFFFFFF
def be32(b, o):
return struct.unpack_from('>I', b, o)[0]
def wstr(b, pool, off):
base = pool + 2 * off
e = base
while b[e:e + 2] != b'\0\0':
e += 2
return ''.join(chr(c) for c in struct.unpack('>%dH' % ((e - base) // 2), b[base:e]))
def captions(pak_entries):
"""`MSG_*` key -> text, read from the IXUD record/field table."""
out = {}
for b in pak_entries.values():
if b[:4] != b'IXUD':
continue
n = be32(b, 4)
o = 8 + 16 * n
m = be32(b, o)
o += 4
fields = [struct.unpack_from('>III', b, o + 12 * i) for i in range(m)]
o += 12 * m
pool = o + 4
for (_k, no, vo) in fields:
if no == NO_NAME:
continue
try:
key, val = wstr(b, pool, no), wstr(b, pool, vo)
except Exception:
continue
if key.startswith('MSG_') and val.strip():
out.setdefault(key, val)
return out
def walk(b, base, nxt, sink):
staged, pending, off = {}, None, base
while off + 4 <= nxt:
w = be32(b, off)
op, ln = w & 0xFF, (w >> 8) & 0xFF
k1, k0 = (w >> 24) & 0xFF, (w >> 16) & 0xFF
if ln < 4 or ln % 4:
return
ws = [be32(b, off + i) for i in range(4, max(ln, 4), 4) if off + i + 4 <= len(b)]
if op in (0, 1) and len(ws) >= 2:
if k0 == 2 and k1 == 1:
pending = ws[1]
elif k0 == 3 and k1 == 2 and pending is not None:
staged[ws[0]] = pending
elif k0 == 3 and k1 == 1:
staged[ws[0]] = ws[1]
if op == 19 and ws:
sink(off, ws[0], dict(staged))
staged = {}
off += ln
def main():
ssb = sys.argv[1]
pak = sys.argv[2] if len(sys.argv) > 2 else \
'/work/sylph_extract/dat/GP_MAIN_GAME_E.pak'
sys.path.insert(0, sys.path[0])
from unitgroup import read_entry # noqa: F401 (kept for parity)
import zlib
import os
def pak_entries(path):
d = open(path, 'rb').read()
assert d[:4] == b'IPFB'
segs, base, i = b'', path[:-4], 0
while os.path.exists('%s.p%02d' % (base, i)):
segs += open('%s.p%02d' % (base, i), 'rb').read()
i += 1
out = {}
for k in range(be32(d, 4)):
h, off, cs = struct.unpack_from('>III', d, 0x10 + 12 * k)
raw = segs[off:off + cs]
if raw[:2] == b'Z1':
raw = zlib.decompress(raw[10:])
out[h] = raw
return out
cap = captions(pak_entries(pak))
b = isl.load(ssb)
s1 = isl.symbols(b, 1)
end = be32(b, 0x0C)
lines = []
def sink(off, bid, st):
if bid != 64:
return
v = st.get(0)
if not isinstance(v, int) or v not in s1:
return
name = s1[v][1]
text = [cap[k] for k in
('%s_000_%02d' % (name, i) for i in range(4)) if k in cap]
lines.append((off, name, ' '.join(text)))
bases = isl.phase_bases(b) + [end]
for i in range(len(bases) - 1):
walk(b, bases[i], bases[i + 1], sink)
name = ssb.replace('\\', '/').split('/')[-1]
print('# %s — dialogue, in script order' % name)
print()
print('Generated by `tools/re-capture/isl_dialogue.py`. Each line is one')
print('`request_script_message` (built-in 64) and the caption it plays.')
print()
print('%d message calls, %d with text.' % (len(lines), sum(1 for _, _, t in lines if t)))
print()
seen = set()
for off, nm, text in lines:
if off in seen:
continue
seen.add(off)
print('%06X %-22s %s' % (off, nm, text))
if __name__ == '__main__':
main()