re(challenge): poking unlocks the whole story campaign; MISSION SELECT is story-only
Two results from the running game, one positive and one a clean negative. POSITIVE: with word A = 0x0001FFFE (stages 1-16) every entry Stage01..Stage16 is selectable, where the control run had only Stage01 and the rest greyed. Stage16 reads "Lonely Blue Planet - NO RECORD". So any story stage can be launched from the menu by poking one word, with no save editing at all -- a simpler lever than the GHAD stage-field patch used until now. NEGATIVE: with word B = 0x3F (challenge stages 24-29 marked cleared) the list still saturates at Stage16 -- the cursor stops there and further presses do nothing. That matches the disc: the debriefing config declares exactly px_deb_stage01..16, so the list is capped by data, not by the mask. The challenge missions are NOT reachable through MISSION SELECT, and word B does not feed it. Also mapped, without finding the caller: the GP_DIALOG registry (tables.pak #41) gives DLG_GO_CHALLENGE_MISSION_MENU = 41 and DLG_CHALLENGE_MISSION_AVAILABLE = 42 (0-based, in config order). No raw immediate 41/39/37 appears anywhere in the GamePart code region, so dialogs are raised through a computed index and the entry point to GamePart 26 is still unknown. New probe: examples/screen_configs.rs dumps any tables.pak screen config by substring.
This commit is contained in:
18
crates/sylpheed-formats/examples/screen_configs.rs
Normal file
18
crates/sylpheed-formats/examples/screen_configs.rs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
//! RE probe: dump tables.pak screen-config records that mention a given token.
|
||||||
|
//! Usage: screen_configs <disc-root> <substring>
|
||||||
|
use sylpheed_formats::{idxd::IdxdObject, pak::PakArchive};
|
||||||
|
fn main(){
|
||||||
|
let a:Vec<String>=std::env::args().collect();
|
||||||
|
let needle=a.get(2).cloned().unwrap_or_else(||"CHALLENGE".into());
|
||||||
|
let arc=PakArchive::open(format!("{}/dat/tables.pak",a[1])).unwrap();
|
||||||
|
for (i,e) in arc.entries().iter().enumerate(){
|
||||||
|
let Ok(b)=arc.read(e) else{continue};
|
||||||
|
let Ok(o)=IdxdObject::parse(&b) else{continue};
|
||||||
|
let t=o.tokens();
|
||||||
|
if !t.iter().any(|s|s.to_lowercase().contains(&needle.to_lowercase())){continue}
|
||||||
|
let path=t.iter().find(|s|s.contains(".pak+")).cloned().unwrap_or_default();
|
||||||
|
if !path.is_empty() && !path.contains("+eng"){continue}
|
||||||
|
println!("\n=== entry #{i} schema {:08x} [{path}] {} tokens ===",o.schema_hash,t.len());
|
||||||
|
for (j,tok) in t.iter().enumerate(){println!(" {j:3} {tok}");}
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
docs/re/captures/mission-select-all-story-unlocked.png
Normal file
BIN
docs/re/captures/mission-select-all-story-unlocked.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.2 MiB |
BIN
docs/re/captures/mission-select-ends-at-stage16.png
Normal file
BIN
docs/re/captures/mission-select-ends-at-stage16.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.2 MiB |
@@ -310,6 +310,20 @@ claims stages that do not exist (`0`, `17`, `24`–`31` in word A). Poking only
|
|||||||
story ids (`0x0001FFFE` = stages 1–16) does **not** blow the heap. That the list
|
story ids (`0x0001FFFE` = stages 1–16) does **not** blow the heap. That the list
|
||||||
screen changes behaviour with the mask is itself confirmation that word A feeds it.
|
screen changes behaviour with the mask is itself confirmation that word A feeds it.
|
||||||
|
|
||||||
|
**Poking real stage ids unlocks the story campaign in the menu** ✅. With word A =
|
||||||
|
`0x0001FFFE` (stages 1–16) every entry `Stage01`…`Stage16` is selectable
|
||||||
|
([capture](captures/mission-select-all-story-unlocked.png)) where the control had only
|
||||||
|
`Stage01`; `Stage16` reads *"Lonely Blue Planet — NO RECORD"*. So **any story stage
|
||||||
|
can now be launched from the menu**, with no save editing, by poking one word.
|
||||||
|
|
||||||
|
**But MISSION SELECT is story-only** ❌. With word B = `0x3F` (challenge stages 24–29
|
||||||
|
marked cleared) the list still **saturates at `Stage16`**
|
||||||
|
([capture](captures/mission-select-ends-at-stage16.png)) — the cursor stops there and
|
||||||
|
further presses do nothing. That matches the data: the debriefing config declares
|
||||||
|
exactly `px_deb_stage01…16`, so the list length is capped by the disc, not by the
|
||||||
|
mask. **The challenge missions cannot be reached through this screen**, and word B
|
||||||
|
does not feed it.
|
||||||
|
|
||||||
**What the poke did not do (yet):** `EXTRAS` still shows only `MISSION SELECT /
|
**What the poke did not do (yet):** `EXTRAS` still shows only `MISSION SELECT /
|
||||||
MOVIE THEATER / BACK` — no challenge entry — although the menu was built 26 s
|
MOVIE THEATER / BACK` — no challenge entry — although the menu was built 26 s
|
||||||
*after* the poke, so this is not staleness. Entering `MISSION SELECT` then failed,
|
*after* the poke, so this is not staleness. Entering `MISSION SELECT` then failed,
|
||||||
|
|||||||
Reference in New Issue
Block a user