diff --git a/docs/re/data/isl-stage02-dialogue.txt b/docs/re/data/isl-stage02-dialogue.txt index b572289..fb6b641 100644 --- a/docs/re/data/isl-stage02-dialogue.txt +++ b/docs/re/data/isl-stage02-dialogue.txt @@ -3,7 +3,11 @@ 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. +213 message calls, 213 with text, 43 spanning more than one page. + +A page is one subtitle box (measured maximum 4 wrapped lines). +Successive pages are successive utterances and may be different +speakers, so a multi-page id is a whole exchange, not one line. 004EFC MSG_VOICE_D_252 Rhino 3 has been shot down! 004FA4 MSG_VOICE_D_254 I've lost contact with Rhino 3! @@ -13,6 +17,7 @@ Generated by `tools/re-capture/isl_dialogue.py`. Each line is one 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. + All personnel, evacuate! 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! @@ -22,20 +27,29 @@ Generated by `tools/re-capture/isl_dialogue.py`. Each line is one 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! + Rhinos, prepare for combat. Are you all clear on your targets? + The attackers with the orange markers, right? Roger that! 0075D8 MSG_VOICE_A_120 Listen, aim for the attackers. Do not let the attackers near the base or the ACROPOLIS. + Incoming! All squadrons, commence attack! 007678 MSG_VOICE_A_139 The Terran ships are blocking our path! + We'll take care of them. You press on to the enemy base! 0077E8 MSG_VOICE_A_141 Enemy fleet sighted. Let's take care of two birds with one stone. All ships prepare to attack! + Any chump who gets in our way is getting fragged! 007898 MSG_VOICE_A_153 Katana, find the enemy attackers and coordinate your attacks with Ellen. + Attackers like those are the bane of big, slow warships. We've got to make sure that none of them get by! 007948 MSG_VOICE_A_126 I repeat, a group of enemy aircraft is approaching! They're heading for Schlos Base! + Rhino Flight, move in to intercept them. 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! + Looks like they invited everyone to the party! 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. + Listen, don't panic. Just focus on getting out of here alive. 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. @@ -47,6 +61,7 @@ Generated by `tools/re-capture/isl_dialogue.py`. Each line is one 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! + Don't break formation! Stay together and hit them hard! 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! @@ -54,13 +69,25 @@ Generated by `tools/re-capture/isl_dialogue.py`. Each line is one 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? + Yes, Rhino Leader. 009224 MSG_VOICE_A_173 Hey, what squadron are those orange fighters from? I've never seen ships like that before. + They must be an experimental squadron from the ACROPOLIS. + Oh, those guys. Do you really think they can hold their own? 009360 MSG_VOICE_D_160 The enemies have been destroyed. We're in the clear, Captain! + Good job, pilots. Thank you! 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! + I always wanted to try piloting a Delta Saber, but I never anticipated a situation like this. 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! + There's no chance of taking that base down! Let's get out of here! 0096CC MSG_VOICE_A_138 More enemies have entered Sector 37! + TCAF Schlos Base to Cruiser CALIBAN in Sector 37. Please engage the enemy ships in your sector. + Unable to comply. We've sustained too much damage. Ask someone else! + All our ships have sustained damage. You have to hold them on your own. + No way! There has to be another squadron somewhere. 0097D0 MSG_VOICE_A_135 Damn, this is bad! The way things are going now, Brandon's lucky he died first! + Don't say that again, Antonius. Unless you want a mouth full of broken teeth! + Sorry, Sandra. 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! @@ -71,18 +98,25 @@ Generated by `tools/re-capture/isl_dialogue.py`. Each line is one 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! + Roger! Katana, let's hurry! 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! + You're from the ACROPOLIS? Thanks for your help! Now, get these guys off of our backs! 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? + The ability to make independent decisions is one of the hallmarks of a great pilot. But, this is different. + You're gonna be in trouble if you keep ignoring the situation and flying off on your own! + Keep screwing around like that and you're putting your life and your comrades' in danger. Keep that in mind! 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. + Did you hear, Katana? A distress signal from one of our comrades. I'll let you decide to help the CHARON or not. + What are you going to do, Katana? All the other units have their hands full. 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! @@ -90,17 +124,23 @@ Generated by `tools/re-capture/isl_dialogue.py`. Each line is one 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! + Oh no! 01A824 MSG_VOICE_B_079 They've broken through! Inform Headquarters! + Don't just let them get away! After them, now! 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. + Hey, rookie. Come see me any time to restock on ammo or repair your ship. 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! + It's an interstellar cruise missile! + Intercept that missile! 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? + Hey, hey, we're here. No need to shout. 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. @@ -111,8 +151,10 @@ Generated by `tools/re-capture/isl_dialogue.py`. Each line is one 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! + ACROPOLIS squadron, move in and intercept them! 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! + Ellen! If you keep blabbering like that, you'll get shot down! 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! @@ -136,13 +178,18 @@ Generated by `tools/re-capture/isl_dialogue.py`. Each line is one 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? + If we destroy the shield projector, the enemy's defense will drop. So target the marked area. 0298A0 MSG_VOICE_D_007 Captain, enemy forces are closing in! + As if those giant missiles weren't enough ... Attack! 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! + Again? All right, we'll do our best to shoot it down! 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! + Send the missile coordinates to the pilots and Schlos Base. 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! + More missiles approaching! Pilots, intercept them! 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! @@ -151,9 +198,11 @@ Generated by `tools/re-capture/isl_dialogue.py`. Each line is one 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. + All personnel, evacuate! 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! + We've failed. There's no hope for us now. 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. @@ -168,20 +217,27 @@ Generated by `tools/re-capture/isl_dialogue.py`. Each line is one 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! + Target the marks! Understood! + Katana, can you see that marker? Attack that missile! 02E560 MSG_VOICE_A_205 TCAF Schlos Base to ACROPOLIS. Are you able to intercept an enemy cruise missile? + We've already sent some fighters. They should make it in time. + I see. You're the only ones left we can count on. 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! + Whatever you say, boss! 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? + I keep sending the distress signal, but there's no response! 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! + If I was at the base, I'd be getting in an escape pod now! 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! @@ -193,12 +249,14 @@ Generated by `tools/re-capture/isl_dialogue.py`. Each line is one 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? + That jerk. I knew he wanted us to escort him just so he could escape! 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! + Shoot them down! 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! @@ -217,4 +275,5 @@ Generated by `tools/re-capture/isl_dialogue.py`. Each line is one 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! + Rhinos, stay together! Concentrate on destroying the missiles one by one! 0345E4 MSG_VOICE_D_316 Katana, that missile is getting close to the base. We have to stop it! diff --git a/docs/re/structures/isl-message-dialogue-link.md b/docs/re/structures/isl-message-dialogue-link.md index 1578ab3..6680e42 100644 --- a/docs/re/structures/isl-message-dialogue-link.md +++ b/docs/re/structures/isl-message-dialogue-link.md @@ -41,6 +41,34 @@ Name families and their share of call sites: ship-side announcements (`ACRO` = ACROPOLIS, `ADAN`/`ADPL` = ADAN, `TCAF`, `RHIN` = Rhino flight). +## Page and line structure — and a correction to this page's first tool + +**✅ Measured 2026-08-26**, on the English pack. A caption id is keyed +`__`: + +* a **page** is one subtitle box, holding **3 or 4 wrapped lines** (4 506 pages + of 4, 263 of 3 — no other width occurs); +* successive **pages are successive utterances**, and may be different + speakers. A multi-page id is therefore a whole exchange, not one long line: + + MSG_DEMO_009 page 0 No way! There's more of them? + page 1 Rhino Leader to ACROPOLIS! There's a whole fleet of them now! + page 2 What? Is there any way you can get out of there? + page 3 If we get rid of those fighters, we can cut our way out of here. + +Of 4 091 distinct ids, **452 span more than one page** (374 `MSG_VOICE`, +78 `MSG_DEMO`), up to 8 pages. + +**This refuted the first version of `isl_dialogue.py`**, committed earlier the +same day, which read only page `000`. **356 of the 1338 script message names +are multi-page**, so a quarter of the dialogue it printed was silently +truncated to its opening utterance. The tool now walks pages until one is +empty. The 2683/2683 resolution figure above is unaffected — it counted ids +that *have* text, and every id does have a page `000` — but the *rendered* +text was incomplete, and the caveat this page originally carried ("whether any +id uses a page other than `000` is unmeasured") understated it as a question +when it was already a defect. + ## Why this was not obvious earlier The caption table only became readable on 2026-08-25, when `build_caption_text` @@ -55,9 +83,9 @@ names had no text to resolve *to*, and the 100 % figure was unreachable. 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. +* **Which page a `MSG_DEMO_*` id belongs to.** The `DEMO` family is not called + from the stage scripts at all — 78 of its ids are multi-page, so something + else drives cutscene dialogue. That driver is unidentified. * **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. diff --git a/tools/re-capture/isl_dialogue.py b/tools/re-capture/isl_dialogue.py index 4e58e49..b2188e3 100644 --- a/tools/re-capture/isl_dialogue.py +++ b/tools/re-capture/isl_dialogue.py @@ -6,7 +6,8 @@ with the caption text it plays. Built-in 64 takes a symbol-table-1 (type 6) message name; the caption text lives in the pack's IXUD blocks under `__`. All 2683 call sites -across the 28 stages resolve, so this is a total mapping rather than a sample. +across the 28 stages resolve, so this is a total mapping rather than a sample. 356 of the 1338 distinct +message names span more than one page; every page is printed. """ import collections import struct @@ -16,6 +17,12 @@ import isl NO_NAME = 0xFFFFFFFF +# A caption id is keyed `__`. A page is one subtitle box of up +# to four wrapped lines; successive pages are successive utterances. Measured +# maxima on the English pack: 8 pages, 4 lines. +MAX_PAGES = 16 +MAX_LINES = 8 + def be32(b, o): return struct.unpack_from('>I', b, o)[0] @@ -114,9 +121,15 @@ def main(): 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))) + pages = [] + for page in range(MAX_PAGES): + box = [cap[k] for k in + ('%s_%03d_%02d' % (name, page, i) for i in range(MAX_LINES)) + if k in cap] + if not box: + break + pages.append(' '.join(box)) + lines.append((off, name, pages)) bases = isl.phase_bases(b) + [end] for i in range(len(bases) - 1): @@ -128,14 +141,22 @@ def main(): 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))) + multi = sum(1 for _, _, p in lines if len(p) > 1) + print('%d message calls, %d with text, %d spanning more than one page.' + % (len(lines), sum(1 for _, _, p in lines if p), multi)) + print() + print('A page is one subtitle box (measured maximum 4 wrapped lines).') + print('Successive pages are successive utterances and may be different') + print('speakers, so a multi-page id is a whole exchange, not one line.') print() seen = set() - for off, nm, text in lines: + for off, nm, pages in lines: if off in seen: continue seen.add(off) - print('%06X %-22s %s' % (off, nm, text)) + print('%06X %-22s %s' % (off, nm, pages[0] if pages else '')) + for extra in pages[1:]: + print('%6s %-22s %s' % ('', '', extra)) if __name__ == '__main__':