Research
This commit is contained in:
parent
28cbbe3470
commit
a9153546ae
56 changed files with 6731 additions and 258 deletions
234
plan-mid.md
234
plan-mid.md
|
|
@ -15,6 +15,226 @@ Detailed completed analysis belongs in the files under `docs/`, not in this plan
|
|||
|
||||
## Progress Snapshot
|
||||
|
||||
Latest verified batch: [docs/psx/art-binding-recovery.md](docs/psx/art-binding-recovery.md) now includes a 2026-04-12 live MCP CLUT override routing closure pass on active `SLUS_002.68` centered on `0x80041458`, `0x80041144`, `0x80044bdc`, `0x80044e9c`, `0x800a9f48`, and `0x800a9f66`. Current best read is now exporter-critical and path-explicit: main-visible injects authored palette token while special-visible does not; submitter override gate is shared (`flags & 0xfffffff0`); and active override resolution diverges by submitter/resource-format lane (image-table and sprite format-2 use `psx_clut_override_table_by_palette_token[token]`, sprite non-format-2 uses token as a row key into `psx_clut_table_by_resource_bank`). Practical consequence is that token `0` is effectively no-override for this world-object path and exporter CLUT logic must branch by route lane plus submitter/resource format instead of flattening token handling. Live artifacts in this batch are targeted comments at `0x800415b0`, `0x800412d0`, `0x80044e10`, and `0x80044eb8`.
|
||||
|
||||
Latest verified batch: [docs/psx/art-binding-recovery.md](docs/psx/art-binding-recovery.md) now includes a 2026-04-12 live MCP wall-family discriminator pass for the exporter regression where atlases repeat and wall faces collapse. Current best read is now split-explicit for `0x003e..0x004f`: constructor bind in `psx_object_create_simple_record`/`psx_object_create_compound_record` still converges on per-type `DAT_800758d8[type]`, while real divergence happens post-bind through selector install (`0x800260e8`), frame-token latch (`0x80025d68` -> `obj+0x94`), and stage-1 versus stage-2 route semantics (`0x80041458` vs `0x80041144`), including main-visible-only authored palette-token injection for `>=0x003e`. Immediate exporter consequence is to prioritize effective route/latch-state discrimination over inventing a new pre-constructor resource-bank split. Live artifacts in this batch are targeted comments at `0x80046038`, `0x80026100`, `0x80041554`, and `0x80040f88`.
|
||||
|
||||
Latest verified batch: [docs/psx/art-binding-recovery.md](docs/psx/art-binding-recovery.md) now includes the 2026-04-12 VRAM-proof palette/export follow-up for `map_renderer/src/lib/psx-cache.js`, `src/config.js`, and `src/vue/controller/scene-presentation.js`. Current best read is now rule-explicit: `mode 1` PSX bundles should not trust bundle header palette index `+0x14` as the rendered selector, they should decode against one shared contiguous 256-entry CLUT equivalent to live VRAM row `0xF0`, `x=0`, with the old header value preserved only as diagnostic `defaultPaletteIndex`. The same batch also closes the static-export omission: the processed PSX catalog already contained `62` maps, so the "single map" symptom was export inclusion/config rather than cache enumeration.
|
||||
|
||||
Latest verified batch: [docs/psx/art-binding-recovery.md](docs/psx/art-binding-recovery.md) now includes the 2026-04-12 focused no-placeholder exporter follow-up for `map 104` in `map_renderer/src/lib/psx-cache.js` plus renderer provenance surfacing in `src/vue/controller/scene-presentation.js`. Current best read is now exporter-explicit: mixed-role unresolved buckets no longer fall back to synthetic atlases, they resolve per authored-family + raw-`u5` cohort into actual PSX bundle art with preserved `mappingSource` / `artCohort` provenance. Focused validation rebuild now exports `1002` art items (`52` roots + `950` constructors), `0` fallback items, `1` atlas, and `136` shape definitions for scene fingerprint `3497e7f641856415`.
|
||||
|
||||
Latest verified batch: [docs/psx/map-rendering.md](docs/psx/map-rendering.md) now includes the 2026-04-12 final live map-104 cohort closure pass on active writable `SLUS_002.68` anchored to scene fingerprint `3497e7f641856415` (`0x0042` roots `0x0022` items `25/35`, roots `0x0030` items `30/31`, constructor `0x0030` items `85/86`, and control `0x0066` item `53`) with focused create/update/draw/control inspection at `0x800249f4`, `0x80024eec`, `0x800131a8`, `0x80025d68`, `0x80041458`, `0x80041144`, `0x8002be6c`, `0x80013618`, and `0x80013688`. Current best read is now exporter-actionable: authored route seed split (`0x0022` vs `0x0030`) remains the strongest safe first-key divider; root-`0x0030` and constructor-`0x0030` cohorts still fail to diverge at creation and should not be split by origin alone; sampled `bit0x0400` and policy/runtime captures remain non-discriminating for this anchor set; and the immediate safe exporter change is route-seed bucketization for unresolved `0x0042` placeholders with conservative hold on deeper heuristics until runtime diagnostics sample concrete non-null values. Live artifacts in this batch are targeted decompiler comments at `0x800249f4`, `0x80024eec`, `0x800131a8`, `0x80025d68`, and `0x80041458`.
|
||||
|
||||
Latest verified batch: [docs/psx/map-rendering.md](docs/psx/map-rendering.md) now includes a 2026-04-12 focused live runtime/control-island policy pass on active writable `SLUS_002.68` centered on `0x80063e54`, `0x80063e68`, `0x800675ec`, and `0x800675f8` with routing/draw/order consumers at `0x800131a8`, `0x80041458`, and `0x8002bf0c`. Current best read is now split-explicit: island tables are control/runtime gating structures and per-type policy modifies ordering/render/publication behavior, but stage-1 vs stage-2 visible lane choice still hinges primarily on object-local route bit `obj+0x1c & 0x0400` and submitter choice remains resource-kind based. Live artifacts in this batch are six conservative helper renames (`0x8002e598`, `0x8002e484`, `0x8002e498`, `0x8002e3e8`, `0x800308ac`, `0x800304c4`) plus targeted comments at `0x80039fd8`, `0x80013518`, `0x80013550`, `0x8004161c`, `0x8002bf2c`, and `0x80034d60`.
|
||||
|
||||
Latest verified batch: [docs/psx/map-rendering.md](docs/psx/map-rendering.md) now includes a 2026-04-12 focused live loader/install pre-constructor closure pass on active writable `SLUS_002.68` centered on `0x80039444`, `0x8003917c`, `0x80045ffc`, `0x8002badc`, and `0x80040768`. Current best read is now install-boundary explicit: WDL load installs type art/state lanes and section-pack pointers before root dispatch; CLUT install is explicit in `level_palette_header_apply`; detached runtime-stream payload install is explicit in `psx_install_level_audio_runtime_stream_bundle`; and constructors therefore start with preinstalled art/state/policy/CLUT context instead of raw section-0 rows alone. Live artifacts in this batch are one conservative function rename (`0x80040768`) plus five targeted decompiler comments across loader/install entry points.
|
||||
|
||||
Latest verified batch: [docs/psx/map-rendering.md](docs/psx/map-rendering.md) now includes a 2026-04-12 focused live draw-submission closure pass on active writable `SLUS_002.68` centered on `0x8004137c`, `0x80041458`, `0x80041144`, `0x80040d44`, `0x80044bdc`, and `0x80044e9c`. Current best read is now submission-explicit: both world-visible lanes select submitter by bound resource kind (`kind==5` image-table else sprite), both consume live frame token `obj+0x94`, and CLUT resolution converges on `psx_clut_table_by_resource_bank` with optional `psx_clut_override_table_by_palette_token[(flags>>8)]`. The strongest lane split is palette-token injection: main-visible ORs authored high-byte token (`source+0x06` or `+0x0c`) into submit flags, while special-visible does not, giving an executable-backed discriminator for unresolved placeholder-family export behavior.
|
||||
|
||||
Latest verified batch: [docs/psx/map-rendering.md](docs/psx/map-rendering.md) now includes a 2026-04-12 focused live selector/transition pre-latch closure pass on active writable `SLUS_002.68` centered on `0x80018578`, `0x8001bca0`, `0x8001e6e8`, `0x800260e8`, and `0x80025d68` with direct row bytes from `0x80063c1c` and `0x80063d68`. Current best read is now stage-explicit: type-`0x0042` pre-latch reseat is early-gated by view margin and object lane bit `0x0020`; transition row lookup remains `DAT_80063a00` -> `DAT_80063b4c`; selector `3/4` effects route through `psx_object_select_state_script` install (`obj+0x9e`) before final live frame-token latch at `obj+0x94` in `psx_object_advance_state_script`. Live artifacts in this batch are five targeted decompiler comments at `0x80018578`, `0x8001bca0`, `0x8001e6e8`, `0x800260e8`, and `0x80025d68`, plus a new exporter implication section for map-104 placeholder-family splitting by pre-latch selector versus latched frame token.
|
||||
|
||||
Latest verified batch: [docs/psx/map-rendering.md](docs/psx/map-rendering.md) now includes a 2026-04-12 focused live type-art install and constructor-binding closure pass on active writable `SLUS_002.68` centered on `0x80045ffc`, `0x800249f4`, `0x80024eec`, `0x80038f18`, and `0x80041458` with globals `0x800758d8/0x800758c8`. Current best read is now lane-explicit from load/install to draw: install writes active-header slot then resolves kind-4/5 resource and commits built-resource cache; constructors consume active-header by type and either reuse built-resource (kind 5) or build per-instance resource; draw uses ctor-bound `obj+0x10` resource and live `obj+0x94` frame token with submitter selected by resource kind. Live artifacts in this batch are five targeted decompiler comments at `0x80045ffc`, `0x800249f4`, `0x80024eec`, `0x80038f18`, and `0x80041458` to preserve exporter-relevant semantics for unresolved map-104 families.
|
||||
|
||||
Latest verified batch: [docs/psx/map-storage-model.md](docs/psx/map-storage-model.md) now includes a 2026-04-12 live section-0 authored-family descriptor-dispatch closure on active `SLUS_002.68` centered on `0x800256b0`, `0x800258cc`, and descriptor table lane `0x80063118/0x80063220/0x800626f8`. Current best read is now convergence-explicit: unresolved families `0x0042`, `0x0049`, and `0x0055..0x0063` share descriptor row `0x800626f8` (slot0 `0x80013618`, slot1 `0x80013688`, slot2 `0x800254c8`) for both root-dispatch and constructor-placement section-0 records, so type divergence should be pursued in per-type banks/policy/state lanes rather than in section-0 descriptor callback identity.
|
||||
|
||||
Latest verified batch: [docs/psx/map-storage-model.md](docs/psx/map-storage-model.md) now includes a 2026-04-12 live object-creation/state-selection closure pass on active `SLUS_002.68` centered on `psx_object_create_simple_record`, `psx_object_create_compound_record`, `psx_spawn_compound_record_advance_state_once`, `psx_spawn_simple_record_set_active_flag`, `psx_object_select_state_from_transition_table`, `psx_object_advance_state_script`, and `psx_type42_transition_selector_tick`. Current best read is now chain-explicit from authored row to visible frame: constructors copy authored `u5` into `obj+0x1c` and seed selector via `u4`; transition/reselection lanes can mutate selector/low control bits; `psx_object_advance_state_script` latches final live frame token into `obj+0x94`; projection/draw consume `obj+0x94` directly through `psx_resource_frame_*` helpers with submit path chosen by bound resource kind. Live artifacts in this batch are one helper rename (`0x8003a37c -> psx_queue_global_draw_tint_pulse_once`), two supporting data labels (`0x80067544`, `0x80067614`), and targeted decompiler comments across spawn/select/latch/projection entry points.
|
||||
|
||||
Latest verified batch: [docs/psx/map-storage-model.md](docs/psx/map-storage-model.md) now includes a 2026-04-12 live loader/storage ownership clarification pass on active `SLUS_002.68` centered on `wdl_resource_bundle_load_by_index` (`0x80039444`), `psx_lzss_unpack_into_level_buffer` (`0x8003b00c`), `psx_lzss_pack_level_buffer` (`0x8003aba8`), and `psx_load_type_state_banks` (`0x8003917c`). Current best read is now ownership-explicit in extractor terms: `0x80067838` is promoted to `psx_level_section_pack_base`, `0x800676d8` to `psx_level_clut_table_ptr`, the `0x3e00` compressed/decompressed lane (`0x8006b5d8` -> `0x8006769c`) is confirmed as persistent runtime substrate with save-side repack parity, and constructor consume-site `0x80024c60` now explicitly links loader-installed `psx_type_simple_component_bank[type]` payloads to live behavior program fields.
|
||||
|
||||
Latest verified batch: [docs/psx/map-storage-model.md](docs/psx/map-storage-model.md) now includes a 2026-04-12 live marker/control runtime-island clarification pass on active `SLUS_002.68` centered on `0x80063e54`, `0x80063e68`, `0x800675ec`, and post-load mode-action sequencing at `0x80039ef4`. Current best read is now control-explicit: the selector/map tables are post-load and slot-gating control structures (not direct art lanes), runtime block persistence is guarded by snapshot sentinels (`0x80031878`/`0x80031a3c`), and a previously anonymous bounded marker-action queue family (`0x80030cf0/0x80030dfc/0x80030ed4/0x80030ebc`, count at `0x80067798`) now has conservative live names/comments to preserve queue-mediated transition behavior.
|
||||
|
||||
Latest verified batch: [docs/psx/map-rendering.md](docs/psx/map-rendering.md) now includes a 2026-04-12 live visibility-routing and draw-lane clarification pass on active `SLUS_002.68` centered on `psx_object_integrate_motion_and_route_visible`, `psx_main_visible_list_sort_range`, `psx_main_visible_order_graph_unlink_pair`, `psx_main_visible_order_graph_detach_object`, `psx_draw_main_visible_object`, `psx_draw_special_visible_queue`, `psx_sprite_resource_submit_frame`, and `psx_image_table_submit_frame`. Current best read is now rule-explicit: stage-1 routes through main-visible list/sort and stage-2 routes through the special-visible queue; ordering uses dependency-graph links with policy-bit influence (`0x0008`, `0x0600`); submitter choice is strictly resource-kind (`kind==5` image-table else sprite); main-visible applies authored palette-token overrides while special-visible does not; and submitters converge on CLUT selection through `psx_clut_table_by_resource_bank` with optional override via `psx_clut_override_table_by_palette_token[(flags>>8)]`.
|
||||
|
||||
Latest verified batch: [docs/psx/map-storage-model.md](docs/psx/map-storage-model.md) now includes a 2026-04-12 live runtime-bank/art-install clarification pass on active `SLUS_002.68` centered on `0x8003917c`, `0x80045ffc`, constructor consumers, and type-bank globals `0x800758c8/cc/d0/d4/d8` plus policy table pointer `0x800675f8`. Current best read is now role-split and loader-to-renderer explicit: state-bank installs seed scripts/components/extents; art installs resolve active-header and built-resource lanes with post-install alias behavior; and policy-table install at load bridges into world draw/order/interaction consumers. Live artifacts in this batch are two evidence-backed renames (`0x8003917c -> psx_install_type_state_script_component_extents_banks`, `0x80045ffc -> psx_install_type_art_active_header_and_built_resource`) plus targeted decompiler comments at `0x800396cc`, `0x800399b4`, `0x8003970c`, `0x800399f4`, `0x80039ad0`, `0x8003977c`, `0x800460c8`, `0x800460d4`, `0x800398f0`, and `0x80041604`.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now includes a 2026-04-12 live countdown-versus-slot frame-order closure centered on map-54 split `0x800208f0` and world-frame call order at `0x8002b830`. Current best read is now ordering-explicit: countdown terminal mode split/write runs before behavior and deferred-control lanes that can reach slot-`0x0f` arm sink `0x800232f0`, so boundary timing pressure is strongest, failure-side suppression is plausible, and plain countdown-success direct causality remains weakest. Live artifacts in this batch are conservative decompiler comments at `0x8002b830`, `0x80020900`, and `0x800232f0`.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now includes a 2026-04-12 live authored-producer reachability correction pass centered on `0x80026710`, `0x8002677c`, `0x80027ecc`, and `0x800214ac`. Current best read is now guard-corrected: `0x80026710` bounds record arg-count (`word0-1 < 0x0a`), not opcode value, so opcode `54 -> subop 49 -> sink 0x800214ac` remains a viable authored-program lane. Practical consequence is that strongest candidate producer context is again the type-state behavior record stream seeded from `psx_type_simple_component_bank[type]`, with tuple `(0x0f,0x0a,0x04)` classified as authored-static source data transported through optional runtime arg-index remap.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now includes a 2026-04-12 live progression-latch timing pass centered on `0x80027548`, `psx_map_progression_table`, and map-54 boundary transitions. Current best read is now ordering-explicit: `0x80027548` stages `next_map` via `psx_level_session_set_next_map_id` into deferred latch `DAT_800678d0`, `current_map_id` only commits at session rollover (`0x80031edc`), and natural tuple miss risk is therefore a deferred preemption window (`54 -> 55` rollover before slot-`0x0f` `(0x0a,0x04)` emit), not a same-tick overwrite race.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now includes a 2026-04-12 live synthesis-only conservative-stabilization pass for the natural in-level JL-9 event lane. Current best read is now wording-stable without overreach: callback entries `0x8002745c`/`0x80027548` stay classified as indirect callback-table targets (no direct callers), countdown tick `0x80020794` stays classified as world-frame control timing with explicit map-54 boundary split, and live comments now explicitly separate timing/context evidence from still-unproven direct tuple-production proof.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now includes a 2026-04-12 live callback-table ownership pass on region `0x800641f0..0x80064220` for entries `0x8002745c` and `0x80027548`. Current best read is now owner-explicit: this region is part of `psx_behavior_opcode_handler_table` (`DAT_800641ac`) dispatched by `psx_object_behavior_opcode_dispatch` (`0x8002677c`), with exact indices `0x15` and `0x19`; selection is opcode-driven from behavior program words, while the only proven active caller lane still enforces `(opcode_word-1) < 0x0a` at `0x80026710`, so these entries remain topology/timing evidence rather than the strongest direct proven producer lane for slot-`0x0f` arm. Live artifacts in this batch are conservative decompiler comments at `0x8002685c`, `0x80026710`, `0x8002745c`, and `0x80027548`.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now includes a 2026-04-12 live slot-`0x0f` subcase taxonomy pass beyond tuple `(0x0a,0x04)` on active `SLUS_002.68`. Current best read is now family-explicit: surrounding `0x0f` branches cluster as transition/countdown/objective-state and message lanes (`0x0a/1..3`, `0x0a/0x2e`, `0x01/1`, `0x04/1`, `0x06/0x42`), while `(0x0a,0x04)` remains the only recovered eligibility-arm write to `psx_debug_extra_channel_gate` under non-hidden header-state-3 predicates. Live artifacts in this batch are one conservative rename (`0x80049014 -> psx_audio_cdxa_select_and_play_cue`) plus targeted decompiler comments at `0x80023154`, `0x800231b0`, `0x8002321c`, `0x80023334`, `0x80023390`, `0x800236d8`, and `0x800237cc`.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now includes a 2026-04-11 live transition-callback provenance pass centered on `0x8002745c` and `0x80027548`. Current best read is now provenance-explicit and timing-aware: both entries are indirect callback-table targets from region `0x800641f0..0x80064220` (no direct caller xrefs), `0x8002745c` can carry or suppress slot-`0x0f` tuple opportunity depending on branch (`DAT_80078a14==0` path calls `0x80020f7c`, alternate path skips it), and `0x80027548` progression apply (`map_progression_table[current_map_id]`) makes natural tuple firing more timing-sensitive by advancing transition state before later control-event handling.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now includes a 2026-04-11 live producer-side authored-source closure pass centered on the action-record frame consumed by `psx_level_gate_slot_dispatch_from_action_record` (`0x800214ac`). Current best read is now loader-explicit: `psx_load_type_state_banks` (`0x800391f0`) installs `psx_type_simple_component_bank[type]` from level bundle type-state payloads, object constructors seed component `program_base/pc` from that bank (`0x80024c60/0x80024c88`), and behavior tick/dispatch (`0x80026740 -> 0x8002677c -> 0x80027ecc`) transports authored operands into the sink frame. Practical consequence is that tuple `(slot,arg1,arg2)=(0x0f,0x0a,0x04)` now looks authored-static at source context with runtime index-resolution as transport, while exact emitting type-row attribution remains open. Live artifacts added in this batch are conservative decompiler comments at `0x80039250`, `0x80024c60`, and `0x80026740`.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now includes a 2026-04-11 live countdown-versus-slot-family structure check driven by the timed-segment failure clue. Current best read is now causality-tight: `psx_control_event_countdown_transition_tick` (`0x80020794`) and `psx_control_event_apply_countdown_step` (`0x800205e8`) are in the world-frame countdown lane, while natural JL-9 arm remains slot-dispatch lane (`0x800214ac -> table 0x800640a0 -> slot0f 0x800230e4 -> writer 0x800232f0`) with no recovered direct countdown-to-slot call edge; practical consequence is that timer behavior is likely related by shared control-state/timing pressure rather than being the same direct feeder branch.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now includes a 2026-04-11 live multi-map last-mission chain validation pass centered on `psx_map_progression_table`, selector-to-map mapping, and late transition helpers. Current best read is now split-map explicit: map `54` is still the strongest natural selector anchor (`0x0f -> 54`), while maps `55..58` are downstream transition phases in the same slot-`0x0f` gate family (`map_to_slot[54..58]=0x0f`) with contiguous progression (`54->55->56->57->58->0xff`), which better explains the JL-9 gate-host family without displacing `54` as the most reproducible natural host.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now includes a 2026-04-11 live synthesis pass driven by two new clues (`timed failure` and `multi-map last mission`) with fresh caller/xref evidence from active `SLUS_002.68`. Current best read is now ranking-explicit: optional scripted event inside the countdown/transition chain is strongest, countdown-branch timing miss second, map-to-map transition interaction third, and plain countdown-success branch weakest; practical consequence is that next runtime validation should prioritize tuple-emission observability (`slot 0x0f`, `0x0a/0x04`) at the map-54 boundary path (`0x800208f0`) with progression callback context (`0x80027548`).
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now includes a 2026-04-11 live alternate-feeder search centered on sink targets `0x800214ac` and `0x800230e4` with explicit control/deferred/callback lane checks. Current best read is now tighter in one key way: no new direct literal/table feeder into either sink was recovered beyond `0x800636d4 -> 0x800214ac` and `0x800640dc -> 0x800230e4`, so the strongest non-`54 -> 49` candidate is currently transition/control-driven (`psx_level_gate_slot05_handler` at `0x80022068`, `psx_control_event_slot0e_handler` case-6 at `0x80023074`, and helper callsite `0x8002748c` into `psx_control_event_apply_level_channel_preset`) rather than a newly proven behavior-opcode producer path.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now includes a 2026-04-11 live level-54 boundary clue pass for natural `MFM4` failures. Current best read is now map-specific and timing-tight: `psx_control_event_countdown_transition_tick` (`0x80020794`) has an explicit split at `current_map_id 0x36` (`<=54 -> mode 0x1a`, `>54 -> mode 0x1b`), and additional optional late control lanes (`psx_level_gate_slot05_handler` `(0x0a,0x28)` plus progression callback `0x80027548`) can advance state before slot `0x0f` `(0x0a,0x04)` arm writes `psx_debug_extra_channel_gate`. Practical consequence is that natural failure is now best explained as optional-path/timing miss around map-54 late transitions, not wrong-host selection.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now includes a 2026-04-11 live slot-handler sibling recovery pass centered on `psx_level_gate_slot_handler_table` (`0x800640a0`) with newly created table-entry functions at `0x800215fc`, `0x80021810`, `0x800219e4`, `0x80021fac`, `0x80022214`, `0x800222e8`, `0x800223cc`, `0x800226e0`, `0x800227ac`, `0x80022b50`, `0x80023854`, and `0x80023af0`, plus a control-pair rename at `0x80022940`. Current best read is now sibling-explicit across slot-family `0x0a..0x0f`: adjacent `0x0a` subcases are control/message/transition lanes, while slot `0x0f` case `(0x0a,0x04)` remains the only recovered sibling branch that arms `psx_debug_extra_channel_gate` at `0x800232f0`.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now includes a 2026-04-11 live upstream-producer closure pass for `psx_level_gate_slot_dispatch_from_action_record` (`0x800214ac`). Current best read is now structure-explicit: the sink consumes a pointer-frame (`record+0/+4/+8/+c`) forwarded from `psx_behavior_subopcode_dispatch` (`0x80027ecc`) as `local_60+1`, and those pointer fields are produced in `psx_object_behavior_opcode_dispatch` by either direct pointer words or index-resolved slot pointers (`base + index*4`). Practical consequence is that tuple `(slot,arg1,arg2)=(0x0f,0x0a,0x04)` is now bounded as behavior-script-produced pointer data rather than a sink-local immediate constant, while the exact shipped authored producer instance remains an open runtime-trace target.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now includes a 2026-04-11 live event-only synthesis continuation pass for the natural gate-arm lane. Current best read is now slightly tighter but still conservative: `0x800230e4` is promoted to `psx_control_event_slot0f_handler` (slot-family role, not single-branch setter), slot-table entries `0x800640d4/0x800640d8/0x800640dc` are explicitly labeled as slot `0x0d/0x0e/0x0f` handler entries, and comments at `0x80064284` and `0x800636d4` now preserve the key split between structural topology (`54 -> 49 -> sink`) and still-unproven active reachability beyond the known `<0x0a` caller lane.
|
||||
|
||||
Latest verified batch created a dedicated event-only working note at [docs/psx/jl-9-in-level-event.md](docs/psx/jl-9-in-level-event.md). Current best read is now organized around the natural gate-arm problem specifically: sink dispatcher `0x800214ac..0x800215f8`, slot-family handlers `0x0d/0x0e/0x0f`, exact arm tuple `(slot 0x0f, arg1 0x0a, arg2 0x04)`, host family `{54,55,56,57,58,82}`, and the still-open upstream authored producer. Practical consequence is that future JL-9 event passes should resume from the dedicated event note instead of re-mixing event-only details into the broader passcode and inventory note.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now includes a 2026-04-11 sink-feeder-only closure pass on live `SLUS_002.68` centered on `0x800214ac..0x800215f8` with explicit argument-byte loads at `0x800215cc/0x800215e0`. Current best read is now artifact-tight: `0x800214ac` is promoted as `psx_level_gate_slot_dispatch_from_action_record`; dispatch slot is loaded from `*(*(record+0))`; handler args are loaded from `*(*(record+8))` and `*(*(record+0xc))`; and the JL-9 gate-arm tuple is bounded to slot `0x0f` with `(arg1,arg2)=(0x0a,0x04)` into `psx_set_debug_extra_channel_gate` (`0x800230e4`) through `psx_level_gate_slot_handler_table[0x0f]` at `0x800640dc`. Upstream table topology is now preserved in live comments as `psx_behavior_opcode_handler_table[54]=0x80027ecc` and `psx_behavior_subop_handler_table[49]=0x800214ac`, while active reachability from the currently proven gameplay caller path remains bounded by `(opcode_word-1) < 0x0a` at `0x80026710`.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now includes a 2026-04-11 host-level closure pass dedicated to natural JL-9 event hosting across family `{54,55,56,57,58,82}` using live table bytes and late-transition caller checks. Current best read is now ranking-explicit: map `54` remains the strongest natural host because it is the reciprocal selector-anchored slot-`0x0f` entry (`0x0f -> 0x36`), while `55..57` stay plausible transition-phase hosts, `82` remains family-valid but weakly anchored for published-code replication, and `58` is now de-prioritized as a stable host because `psx_map_progression_table[58] = 0xff` marks terminal progression pressure; practical failure model for natural `MFM4` is now timing/event-miss (missing tuple `(0x0a,0x04)` before hidden phase), not passcode decode mismatch.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now includes a 2026-04-11 live caller/context reassessment around `0x80026690` / `0x8002677c` with a sibling control-runner check. Current best read is now split cleanly between active proof and topology: the only proven caller into `psx_object_behavior_opcode_dispatch` remains the `<0x0a` bounded lane at `0x80026710`, while `54 -> 49 -> 0x800214ac` remains structurally valid table linkage but should be deprioritized as an immediate active explanation until a second caller/context lane is recovered. The same batch also lands conservative live artifacts (`0x80027ecc` function creation/name and `0x80020f7c` rename with caller-bound comments).
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now includes a 2026-04-11 live MCP late-objective pass focused on mission-complete text handlers, transition siblings, and uncommon reward-branch outcomes in the slot `0x0d`/`0x0e`/`0x0f` control-event family. Current best read is now path-tight: slot `0x0e` case `0x0a/6` is a concrete late transition that applies selector `0x0f`, selector `0x0f` is the only sampled direct selector lane into channel `0x0f`, and natural JL-9 gate arm remains bounded to slot `0x0f` case `0x0a/4` (`0x800232f0`) under `hidden==0 && runtime_header_state==3`; practical consequence is that the remaining blocker is now specific authored event provenance inside that channel-`0x0f` family, not branch existence.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now includes a 2026-04-11 live closure pass dedicated to decoding the control-event 0x0a family around `0x80022c6c..0x80023390`. Current best read is now sibling-explicit: slot `0x0d` (`0x80022c6c`) and slot `0x0e` (`0x80022ea8`) are recovered as mission-complete/control-event siblings to slot `0x0f` (`0x800230e4`), and tuple `(0x0a,0x04)` remains the strongest natural pre-hidden gate-arm branch because it is the only recovered in-family case that writes `psx_debug_extra_channel_gate` under `hidden==0 && runtime_header_state==3`.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now includes a 2026-04-11 event-only synthesis pass for the natural JL-9 in-level gate-arm lane plus a conservative live Ghidra naming/comment sweep on still-raw central entities. Current best read stays intentionally split between what is proven and what is only topology: sink-side event evidence remains strong (`0x800214ac..0x800215f8` -> `slot 0x0f` -> `0x800230e4`, tuple branch `0x0a/0x04` at `0x800232f0`), while upstream `54 -> 49` is retained as structural table linkage pending proof of a second active caller/context beyond the known `(opcode_word-1) < 0x0a` guard at `0x80026710`.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now includes a 2026-04-11 active-caller recheck focused on natural gate-arm production into sink dispatcher `0x800214ac..0x800215f8`. Current best read is now priority-corrected: sink-side tuple closure remains strong (`slot 0x0f`, `arg1 0x0a`, `arg2 0x04` into `0x800230e4`), but the only proven gameplay caller lane into `psx_object_behavior_opcode_dispatch` remains bounded by `(opcode_word-1) < 0x0a` at `0x80026710`, so the earlier `54 -> 49` path should stay as table topology and be deprioritized as an immediate active explanation until a second caller/context lane is recovered.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now includes a 2026-04-11 user experiment follow-up that materially weakens `MFM4` as the main mystery. Current best read is now experiment-backed: a natural `MFM4` trial did **not** yield `JL-9`, while `JFM4` plus manual gate byte `0x8006739d = 0x01`, then `L0SR`, then `R1 + Circle`, still produced `JL-9`. Practical consequence is that `MFM4` remains the best natural prime candidate on code grounds, but the dominant unresolved question is now the natural in-level gate-arm event rather than the passcode choice itself. Deferred user experiments to revisit later are `2`, `4`, `5`, and `6` from the current emulator test plan.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now includes user-validated downstream closure for the forced JL-9 test. Current best read is now causal-explicit: manual byte poke `0x8006739d = 0x01`, then `L0SR`, then `R1 + Circle` successfully produces `JL-9`, which proves the late hidden/input grant half is correct and that the gate byte alone is sufficient for the extra `0x0d` branch once hidden trigger runs. Practical consequence is that the more direct thing being bypassed is the natural in-level gate-arm event, while `MFM4` is now demoted from “lead candidate” to “best natural prime candidate” for recreating the same latch without manual memory edits.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now includes a focused 2026-04-11 live `SLUS_002.68` hard-clear-theory check and manual gate-poke closure. Current best read is now split cleanly: the "beat the game on hard, then enter `L0SR`" story remains weak-to-medium because completion/congratulation handlers were found but no direct bridge from endgame flow into `psx_debug_extra_channel_gate` was recovered; meanwhile the practical emulator route is now strong, because `psx_debug_extra_channel_gate` is confirmed as byte `0x8006739d`, read as nonzero at `0x8002fff4`, with no recovered clear in inspected session/load/menu paths, so manual `0x01` poke + hidden `L0SR` + `R1 + Circle` is now the best forced test for the extra `0x0d` lane.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now includes a focused 2026-04-11 live `SLUS_002.68` published-mission-code sweep against the user-supplied level-code table. Current best read is now candidate-explicit: ordinary decode rows are `i=0x00..0x0e`, ordinary selector return is `s=i+1`, and first-char difficulty only writes `psx_level_runtime_header_state`. Practical JL-9 consequence is that `MFM4` (Level 15 hard) is now the only strong published-code prime recovered so far, because ordinary row `i=0x0e` yields selector `s=0x0f`, maps through `DAT_80063e54[0x0f]=0x36`, and lands in gate family `DAT_80063e68[54]=0x0f` while also setting `runtime_header_state=3`; `LRTN/MRTN/PRTN` remain strong negatives because the `?RTN` family clears header state to `0`.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now includes a focused 2026-04-11 live `SLUS_002.68` reachability-correction pass on the previously claimed step-2 producer chain. Current best read is now split cleanly between topology and proof: table topology still shows `DAT_800641ac[54] = 0x80027ecc` and `DAT_80063610[49] = 0x800214ac`, but static reachability currently proves only one caller to `psx_object_behavior_opcode_dispatch` (`0x80026740`) and that path bounds `(opcode_word-1) < 0x0a` before dispatch, so high-index entries are not yet proven active from the known path. Practical consequence is that sink-side gate-writer evidence remains strong (`0x800214ac..0x800215f8` -> `DAT_800640a0[0x0f] = 0x800230e4`, args `0x0a/0x04`), while the open upstream task is now narrowed to recovering a second proven caller/context that can feed high behavior-opcode indices.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now includes a focused 2026-04-11 live `SLUS_002.68` step-2 producer-path closure pass for the gate-arm dispatcher source. Current best read is now structurally explicit upstream: `psx_object_behavior_opcode_dispatch` table index `54` reaches handler `0x80027ecc`, which secondary-dispatches through `DAT_80063610[subop]`; sub-op `49` maps to `0x800214ac`, which then performs the level-gated slot dispatch into `DAT_800640a0[0x0f] = 0x800230e4` with arg bytes from record pointers (`0x800215cc/0x800215e0`). Practical consequence is that step-2 is now identified as an in-level behavior/control opcode event lane (`54 -> 49`), with the remaining open item narrowed to one concrete authored mission/object instance rather than the producer subsystem itself.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now includes a focused 2026-04-11 live `SLUS_002.68` NRTN/?RTN decode-to-apply closure over `0x8003ec8c`, `0x80034c14..0x80034ddc`, and `0x80021138`. Current best read is now delay-slot exact: special index `0x0f` clears `psx_level_runtime_header_state` but returns raw selector `0x10`, eval maps through `DAT_80063e54[0x10]=0x3f`, and caller therefore does not take the `s0==0` skip; apply executes selector-`0x10` case at `0x8002142c` (writes `DAT_800675e4=0x1d`, common helper `a0=0x36`). Practical JL-9 consequence remains strict: NRTN/?RTN does not itself satisfy gate-arm predicate `runtime_header_state==3` and cannot alone coexist with the required non-hidden gate-arm state.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now records a 2026-04-11 correction to the earlier Mission 16 / developer-office theory. Current best read is that the attractive `DAT_80063e54[0x0f] = 0x36 -> DAT_80063e68[0x36] = 0x0f` chain was the wrong table index for the runtime `?RTN` path; the live caller path uses returned selector `0x10`, maps through `DAT_80063e54[0x10] = 0x3f`, and only later executes selector-`0x10` apply logic with common-helper `a0 = 0x36`. Practical consequence is narrower: office-like content may still be involved, but current static evidence no longer proves that `NRTN/?RTN` places the session directly inside the slot-`0x0f` gate family.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now includes a focused 2026-04-11 live `SLUS_002.68` hypothesis check for the exact `NRTN -> in-level office event -> ?0SR/L0SR -> input 0x1e` recipe. Current best read is now classification-explicit: the two-phase structure remains code-backed (`pre-hidden gate-arm at 0x800232f0` then hidden/input trigger at `0x80013154..0x80013174`), dispatch evidence still supports a real in-level slot-`0x0f` gate-arm path via `0x800214ac..0x800215f8` into `0x800230e4`, but the exact player-visible office event and deterministic `NRTN` role are still not singularly closed by static evidence; practical status is therefore `plausible but unproven` rather than contradicted.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now includes a focused 2026-04-11 live `SLUS_002.68` clarification pass on what user-facing "step 2" actually means. Current best read is now much less misleading: the gate-arm write is not a second passcode-screen action but an in-level scripted/control dispatch routed through `0x800214ac..0x800215f8`, where `DAT_800640a0[0x0f] = 0x800230e4` (`psx_set_debug_extra_channel_gate`) and the exact writer tuple is `(slot 0x0f, param_2 0x0a, param_3 0x04)`; meanwhile hidden `?0SR` / `L0SR` still uses the shared passcode decoder but returns selector `0`, so it does not follow the ordinary nonzero mission/apply-load branch. Practical consequence is that the current JL-9 recipe is now explicitly `normal passcode prime -> in-level scripted gate-arm event -> hidden passcode -> R1+Circle`, with the remaining blocker narrowed to naming the concrete in-level event.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now includes a focused 2026-04-11 live `SLUS_002.68` step-2 caller narrowing pass on the gate-arm writer path (`0x800230e4` -> `0x800232f0`). Current best read is now dispatch-concrete: reachability is through an indirect level-gated dispatcher at `0x800214ac..0x800215f8` (`DAT_80063e68[current_level]` compare + `DAT_800640a0[a2]` handler table), with slot `0x0f` resolving to `psx_set_debug_extra_channel_gate`; handler arguments are loaded from action-record byte pointers; and the exact gate-arm tuple is tightened to `(dispatch index 0x0f, param_2 0x0a, param_3 0x04)`, narrowed to a small level-scripted family where `DAT_80063e68 == 0x0f` (`54..58,82`) rather than a single globally named menu callback.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now includes a focused 2026-04-11 live `SLUS_002.68` gate-survivability closure pass across passcode application, level-load/session loops, and menu-reset helpers. Current best read is now lifecycle-explicit: `psx_debug_extra_channel_gate` (`0x8006739d`) remains one-writer/one-reader (`0x800232f0` set, `0x8002fff4` read) with no recovered static clear in inspected load/menu paths; hidden decode (`0x8003ed28`) still returns selector `0` and skips normal apply/load branch checks around `0x80034d84`; and practical two-phase ordering remains `non-hidden gate arm first -> hidden/input trigger later`, with step 2 supported after a level load in the same running session.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now includes a focused 2026-04-11 live `SLUS_002.68` passcode-screen semantics closure for the normal-versus-hidden entry question and the JL-9 sequence wording check. Current best read is now user-flow explicit: normal and hidden passcodes both route through `psx_passcode_screen_eval_current_entry`/`psx_passcode_decode_to_mission_selector`; hidden `0x10` still sets `psx_hidden_passcode_flag` in that same decoder; and the unnamed caller block around `0x80034c14` has distinct immediate branch behavior for eval return `0` versus nonzero before transition/setup calls. Practical consequence is that the existing JL-9 sequence remains directionally right on two-phase logic (`pre-hidden gate arm` then hidden/input trigger) but is now marked operationally under-specified until one live trace pins the exact player-visible producer for `param_2==0x0a,param_3==4` into `psx_set_debug_extra_channel_gate`.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now includes a focused 2026-04-11 live `SLUS_002.68` gate-arm caller-path closure around `psx_set_debug_extra_channel_gate` (`0x800230e4`) and the exact writer at `0x800232f0`. Current best read is now sequence-tight: the writer executes only in the `param_2==0x0a,param_3==4` branch; the store requires `psx_hidden_passcode_flag==0 && psx_level_runtime_header_state==3`; and the required `runtime_header_state==3` comes from the normal passcode first-char delta branch at `0x8003ed58` rather than special hidden/sibling passcode branches. Practical closure remains two-phase (`normal non-hidden state-3 prime -> gate-arm event -> hidden passcode -> input code 0x1e`) with one bounded remaining gap: naming the exact player-visible producer for the `0x0a/4` event inside the nearby undefined dispatch block.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now includes a focused 2026-04-11 live `SLUS_002.68` RP-16 startup/default follow-up that pushed on undefined nearby init stubs, startup mode-action dispatch callsites, selected-id writer closure, active-channel writes, and level mode/difficulty tables. Current best read is tighter and still negative for startup RP-16: `committed_selected_item_id` has only two recovered writers (`0x80039f68` reset-to-zero and `0x8002f170` table-commit sink), startup dispatch remains `8 -> (optional 2) -> 4` without a direct commit call, and scanned `channel_commit_row_selected_item_id` rows (`0x00..0x19`, table at `0x80064355` with selected byte at `+9`) contain no `sel=0x01`. Practical classification remains `RP-16 not a proven startup/default weapon` while preserving `0x01` as a real non-startup row.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now includes a focused 2026-04-11 live `SLUS_002.68` special-passcode priming closure pass over `?0SR/?RTN/?QQQ` versus `psx_level_runtime_header_state`, `psx_hidden_passcode_flag`, and `psx_debug_extra_channel_gate`. Current best read is now branch-tight: `?RTN` (`0x0f`) clears runtime-header state to `0`, `?0SR` (`0x10`) sets hidden flag to `1`, `?QQQ` (`0x11`) returns sentinel `0x12` without priming runtime-header state, and none of these specials can independently satisfy gate-arm (`hidden==0 && header_state==3`) at `0x800232f0`; practical JL-9 closure remains a two-phase flow where gate-arm is pre-hidden and hidden/input trigger occurs afterward.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now includes a strict executable-only 2026-04-11 JL-9 validation lane over passcode decode, input-code mapping, gate write, grant call, and selected-id commit sink. Current best read is now narrowed to one concrete blocker for an exact user-facing recipe: code proves `hidden index 0x10 arm` + `input code 0x1e` + `gate read at 0x8002fff4` + late `unlock(0x0d)` and commit sink at `0x8002f168/0x8002f170`, but still does not independently map one deterministic player-visible action that drives the `0x800232f0` writer path (`psx_set_debug_extra_channel_gate`, `param_2='\\n' case 4`) under `hidden==0 && runtime_header_state==3`. Practical next closure is therefore one live caller-arg probe on `0x800230e4`/`0x800232f0`, not another broad sweep.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now includes a focused 2026-04-11 live `SLUS_002.68` lifecycle closure pass for `psx_debug_extra_channel_gate` (`0x8006739d`) and `psx_hidden_passcode_flag` (`0x80067454`) across session init, passcode decode/arm, and debug grant entry. Current best read is now explicit and condition-tight: hidden flag has bounded set/clear points (`0x8003ed28`/`0x8002bab8` set, `0x8002b9e4` timed clear), extra gate remains one-writer/one-reader with no recovered static clear (`0x800232f0` set under `hidden==0 && header_state==3`, `0x8002fff4` read for late `0x0d` unlock), and the strongest practical JL-9 sequence is now a two-phase A->B->input flow where gate-arm occurs pre-hidden and grant trigger occurs during hidden-mode timer.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now includes a focused 2026-04-11 live `SLUS_002.68` RP-16 startup/default-init closure pass over post-load reset, mission/loadout init, difficulty/mode-transition apply, and selected-id writer coverage. Current best read is now explicit for the startup question: `psx_level_post_load_runtime_reset` clears `committed_selected_item_id` to `0` before dispatching mode actions, `psx_weapon_channels_init_mode_loadout` and `psx_weapon_channels_apply_mode_transition_state` contain no fixed selected-id `0x01` seed, and recovered fixed-immediate commit callsites (`0x11`, `0x12`, and one context-specific `0x01`) occur in gameplay/control lanes rather than the named startup initializer path. Practical classification is now `RP-16 not proven startup/default weapon` while still remaining a real executable-backed row with unresolved non-startup acquisition role.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now includes a focused 2026-04-11 live `SLUS_002.68` input-side closure pass for the hidden/debug JL-9 trigger path. The active database now carries conservative input-map helper promotions (`0x80042ec4` -> `psx_input_map_install_profile`, `0x8002abb8` -> `psx_input_map_set_code_to_padmask`, `0x8002abe0` -> `psx_input_map_update_state_for_pad`, `0x8002adbc` -> `psx_input_map_get_code_and_edge`) plus new decompiler comments at `0x80042ec4`, `0x8002abe0`, and `0x80012c30`. Current best read is now explicit and executable-backed: `psx_object_update_runtime_input_modes` gates debug grant on `local_14 == 0x1e`; input code `0x1e` resolves through an exact-match 0x32-entry map; and that code maps to mask `0x2800` in every recovered profile branch, corresponding to the practical chord `R1 + Circle` under the active digital pad bit layout.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now includes a focused 2026-04-11 live `SLUS_002.68` section0-slot closure pass for JL-9 legit-path testing. Current best read is now decisively tighter: `psx_section0_dispatch_root_seed_marker_channel_table` seeds slot `0x14` as `(kind=3, channel=0x0d)`, `psx_section0_dispatch_root_apply_packed_channel_actions` dispatches kind `3` into `psx_weapon_channel_unlock_and_seed_markers(channel)`, and shipped PSX scene-cache root records contain authored bytes with `(byte & 0x3f)==0x14` across 22 maps (119 hits / 3298 scanned root records). Practical consequence is that non-debug shipped data can in fact drive the `unlock(0x0d)` lane; remaining uncertainty is route/timing reachability in ordinary play, not byte-path existence.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now includes a 2026-04-11 live `SLUS_002.68` passcode decode closure pass centered on `psx_passcode_screen_eval_current_entry` (`0x80034e38`), `psx_passcode_decode_to_mission_selector` (`0x8003ec8c`), and table block `0x80064bbc/0x80064bd0/0x80064be4/0x80064bf8`. The pass closes the transform math (`entry[1..3]-0x1b` triplet match + first-char delta lane), recovers concrete table bytes from memory, and confirms special index behavior: `0x10` sets `psx_hidden_passcode_flag`, `0x0f` clears `psx_level_runtime_header_state`, and `0x11` returns sentinel `0x12`, with all three bypassing first-char validation. Current strongest string closure is hidden/debug `?0SR` (canonical `L0SR` when selector is `0`), plus `?RTN` and `?QQQ` sibling specials. Practical JL-9 consequence remains a staged hidden/debug gate path (`hidden flag` + `input code 0x1e` + `psx_debug_extra_channel_gate`) rather than an ordinary direct unlock lane.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now includes a focused 2026-04-11 live `SLUS_002.68` final-enable-sequence closure pass for the JL-9 hidden/debug lane at `0x8002ba9c`, `0x800232f0`, `0x8002fd90`, and `0x8002fff4`. Current best read is now explicit in executable terms: final `0x0d` unlock is gated by `psx_debug_extra_channel_gate` read at `0x8002fff4`; that gate is written only under `psx_hidden_passcode_flag==0 && psx_level_runtime_header_state==3` at `0x800232f0`; grant entry itself requires `psx_hidden_passcode_flag!=0` plus input code `0x1e` at `0x80013174`; and the strongest practical outcome is a two-phase hidden flow rather than a guaranteed one-action trigger.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now includes a focused 2026-04-11 live `SLUS_002.68` RP-16 classification pass around selected-id `0x01` with direct row/acquisition/HUD evidence. Current best read is tighter in four concrete ways: row `0x01` (`0x80064690`) is real structured weapon-definition data (`RP-16`) rather than invalid filler; primary shop direct-unlock progression still runs through `03..0c` and does not include `0x01`; the observed shop-side `0x01` table entry sits in the secondary `0x0a..0x0e` ammo-top-up branch (`0x8002e32c`) rather than primary unlock helper `0x8002e5f0`; and HUD short-label lookup for selected weapon id remains table-driven through `FUN_800455d4` (`0x80064e90` / `0x80064e9c`) with row-name identity still anchored by inline row bytes. Practical classification is now "real early row with legacy/startup/placeholder-like behavior" rather than "invalid/unused slot", pending one concrete non-debug acquisition writer.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now includes a focused 2026-04-11 live `SLUS_002.68` legitimate-acquisition verdict pass using emulator-grounded selected-id mapping (`0x8014577e`, `0x0c=JL-2`, `0x0d=JL-9`) as hard anchor. Current best read is now explicit by lane: normal loadout and shop direct unlock paths remain capped at `<=0x0c`; hidden/debug input gate still leads to the only recovered fixed-immediate `unlock(0x0d)` site (`0x80030004`); scripted packed-action dispatch remains the only plausible non-debug `0x0d` exception but is still authored-data dependent and unproven in shipped section0 content; practical classification therefore remains `JL-9 strongest hidden/debug-conditioned` rather than presently proven normal-flow unlock.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now includes a focused 2026-04-11 live `SLUS_002.68` broad acquisition-systems pass over default loadout/init, mission transition mode apply, pickups, shops, scripted packed awards, and debug grant paths for ids `0x0d` (`JL-9`) and `0x01` (`RP-16?`). Current best split is now explicit and source-backed: ordinary loadout and shop front path remain `<=0x0c` with no direct `0x0d`; debug grant still conditionally unlocks `0x0d` behind `psx_debug_extra_channel_gate`; scripted/pickup data-driven paths can still produce either id when authored; and `0x01` is not excluded from normal content because the shop channel map contains `0x01` in the alternate branch and low-id action commit paths also accept it.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now records a 2026-04-11 live `SLUS_002.68` reconciliation pass that incorporates the user-verified selected-weapon byte map at `0x8014577e` (`00..0d`) and tightens the old local-id-versus-row-id ambiguity. Current best model is explicitly two-domain: callers feed compact channel/local codes into `psx_apply_channel_effect_and_commit_selected_item_id` (`0x8002ef34`), then `0x8002f15c` resolves through `channel_commit_row_selected_item_id[(channel*10)+9]` into committed row-id domain (`00..0d`) before `0x8002f168` stores to the nested runtime `+0x1c` field family that includes the selected byte at `0x8014577e`. This corrects earlier shorthand that could imply direct caller-code equality with committed selected row id.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now includes a focused 2026-04-11 live `SLUS_002.68` gate-closure pass for the exact JL-9 visibility preconditions requested around `psx_debug_extra_channel_gate`, `psx_hidden_passcode_flag`, and the selected-weapon watch at `0x8014577e`. Current best read is tighter in four practical ways: `DAT_8006739d` remains one-writer/one-reader (`0x800232f0` write, `0x8002fff4` read); `DAT_80067454` writer/reader roles are now bounded across decode/arm/reset/input handlers; unlock-capable channel-`0x0d` entry points are explicitly separated into debug bulk grant versus scripted packed-action dispatch; and normal-lane evidence still clusters at `<=0x0c` while non-debug shipped `0x0d` authoring remains unproven. The pass also landed one conservative live rename (`0x8002ba9c` -> `psx_hidden_passcode_arm_runtime_state`) plus durability comments at `0x8002bab8`, `0x80013154`, `0x8002fff4`, and `0x8002f170`.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now captures the decisive starter-only RAM compare against the earlier all-weapons dump and retracts the previous `0x1456fc` inventory-list hypothesis. The compact `0x1456fc..0x145748` `0x0002..0x000b` sequence is unchanged across both dumps and is therefore not the live owned-weapon list; the dynamic lane starts at `0x14574c` and the strongest current field closure is now byte `0x14577e` (`0x0c` in the all-weapons dump versus `0x02` in the starter-only dump), which executable-side passes tie to selected/committed weapon row-id state inside the nested runtime `+0x1c` field family. The compare also keeps `0x67944` interesting as a changing watch (`0x0000000b` versus `0x00000001`) but downgrades it to unproven because no direct static xrefs were recovered for `0x80067944`. Current best read is now channel-state ownership plus dynamic runtime current-weapon fields, not a contiguous owned-id inventory array.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now captures a focused live `SLUS_002.68` ownership-model pass tied to the observed dump split (`0x801456fc..0x80145748` static, `0x8014574c..0x801457d0` changed). Current best read is tighter in four concrete ways: ownership query is channel-state based (`psx_marker_channel_mode_is_enabled` reads `psx_marker_channel_runtime_block[(channel*4)+0x34]`), per-channel ammo/step state is `+0x6c` (via `psx_marker_channel_get_mode_step_value` and channel add/unlock helpers), active selected channel is byte `+0x32`, and commit-to-weapon resolution remains table-driven (`channel_commit_row_table[(channel*10)+9]` at `0x8002f15c` into `idx*0x26` row access at `0x800315d8`) rather than a direct contiguous owned-id list. The live database also fixes a symbol collision by renaming `0x8002fd90` to `psx_debug_grant_weapon_channels_and_ammo`, preserving explicit post-gate extra unlock semantics at `0x8002fff4 -> channel 0x0d`.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now adds a focused live `SLUS_002.68` runtime-ownership pass on RAM block `0x8014574c..0x801457d0` and closes the strongest current interpretation for watched byte `0x8014577e` (`file offset 0x14577e`). Current best read is now tighter in four concrete ways: `0x14577e` sits inside the nested player-runtime `+0x1c` field family reached through `DAT_800789f8 -> +0x8 -> +0x18 -> +0x1c`; that field family is written from `channel_commit_row_selected_item_id` in `psx_apply_channel_effect_and_commit_selected_item_id` and reset in `psx_set_debug_extra_channel_gate`; the surrounding block shape matches heap-resident per-object runtime state initialized by `psx_object_create_simple_record`; and the observed byte delta `0x0c` (all-weapons) versus `0x02` (starter-only) is therefore strongest as selected weapon row-id metadata, not primary ownership/ammo/HUD-cache storage.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now adds a focused live `SLUS_002.68` ownership/xref pass on the user-tracked block `0x80067938..0x80067958`, with direct closure on the `0x80067944` ambiguity. Current best read is now tighter in four concrete ways: `0x80067944` has no recovered static xrefs in this image under word/halfword/byte probes and is therefore not currently supported as selected-weapon-id or selected-row-id storage; `0x80067938` is reaffirmed as `psx_ctor_placement_section_ptr` installed by `wdl_resource_bundle_load_by_index` and consumed by `psx_apply_deferred_control_command` as constructor/deferred-control section state; nearby `0x8006793c/0x80067940/0x80067948` are input-mode dispatch state in `psx_object_update_runtime_input_modes`; and `0x80067954/0x80067958` are present/spec-upload draw-env state with one conservative helper promotion (`FUN_800461d0` -> `psx_draw_progress_overlay_and_swap_drawenv`).
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now closes the compact local-id versus weapon-row-id question for live `SLUS_002.68` as a table-driven conversion, not a standalone arithmetic helper. The new strongest chain is `caller channel/local code -> psx_apply_channel_effect_and_commit_selected_item_id(0x8002ef34) -> channel_commit_row_selected_item_id[(channel*10)+9] load at 0x8002f15c -> committed_selected_item_id -> idx*0x26 resolver at 0x800315d8 from base 0x8006466a`, with concrete JL mapping `local/channel 0x0b -> row 0x0c (0x80064832, JL-2)` and `local/channel 0x0c -> row 0x0d (0x80064858, JL-9)`. Three durable live comments were added at `0x8002f15c`, `0x800315d8`, and `0x8001d3fc` to preserve this conversion model for future RAM-dump reconciliation passes.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now closes the user-reported pointer delta near selected-weapon state watches (`0x80078248` in all-weapons versus `0x800782b8` in starter-only) as a render double-buffer artifact, not a weapon/inventory struct discriminator. Live `SLUS_002.68` decompiles now show `psx_platform_init` seeding both draw-env records, paired disp-env records at `+0x5c`, and `DAT_80067954` flipping between them in `psx_present_frame_and_flip`, `render_reset_draw_state`, and `FUN_800461d0`. Current practical consequence is tighter scope: this nearby pointer lane should no longer be treated as selected-weapon ownership state, and weapon identity work should stay on the channel-commit and weapon-row resolver path.
|
||||
|
||||
Latest verified batch: the earlier `0x1456fc` / `0x145744` / `0x67944` patch-candidate story is now superseded by the starter-only compare and should be treated as withdrawn. `0x1456fc..0x145748` is static across both dumps, so it is not the live owned-weapon list; byte `0x14577e` is now the strongest executable-backed dynamic selected-weapon row-id field, while `0x67944` remains only a changing watch without direct static-xref closure.
|
||||
|
||||
Latest verified batch: the earlier watched-value shorthand `JL-?=11` has now been superseded by direct emulator verification of the selected-weapon byte at `0x8014577e`: `0x0c = JL-2`, `0x0d = JL-9`, with the full `00..0d` row-id map now captured in [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md). This removes the older inference step for JL-2 versus JL-9 identity and shifts the remaining work entirely onto legitimate-acquisition proof and RP-16 classification.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now captures the current blocker much more precisely after another multi-lane `SLUS_002.68` pass. The strongest RAM-side lead has moved decisively to dense small-byte runtime clusters around file offsets `0x133000`, `0x133416`, and `0x1335d4`, with a weaker secondary candidate around `0x422c..0x4440`; by contrast, the earlier `DAT_80064355[(channel*10)+9]` field is now explicitly documented as not acting like a plain final JL row id in the sampled dump. On the code side, `0x8001E37C` is now promoted to `psx_handle_special_input_code`, which is the strongest current upstream helper for the hidden `0x1e` trigger range, while the ammo-side helper family is now tighter through newly named marker/runtime helpers. The remaining blocker is now singular and concrete: one executable-side inventory/HUD anchor is still needed to prove which of the current RAM candidate regions is the real live weapon-slot table.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now captures a third targeted six-agent `SLUS_002.68` cycle that sharpened both the RAM and input-code stories without yet fully closing them. The main negative result is now explicit: the candidate commit-table byte at `DAT_80064355[(channel*10)+9]` does not show plain `0x0c/0x0d` values in the sampled main-RAM dump rows, so that exact field is not behaving like a direct final JL row id in this capture. The strongest new positive lead is elsewhere in the same dump: denser table-like `0x0c/0x0d` clusters now stand out around file offsets `0x133000`, `0x133416`, and `0x1335d4`, which are better candidates for real live inventory/slot state and should be the next RAM target. The same pass also promoted `0x8001E37C` to `psx_handle_special_input_code`, tightening the upstream side of the hidden-passcode trigger path even though the exact `0x1e` -> button-chord mapping still remains open.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now captures another six-agent `SLUS_002.68` pass focused on the JL-2 ammo lane, the JL-9 debug trigger path, the 2 MiB main RAM dump, and direct inventory/HUD mapping helpers. The strongest new clarification is on the trigger story: executable evidence now closes `hidden passcode active -> gated input code 0x1e -> psx_debug_grant_weapon_channels_and_ammo -> extra 0x0d unlock behind psx_debug_extra_channel_gate`, but still does not prove that input code `0x1e` specifically means `R1 + Circle`. The same pass also tightened the RAM-dump read without rejecting it: `binary/Crusader - No Remorse Weapons Main Ram.bin` is still plausible main RAM and now has candidate compact slot-like records near file offsets `0xA0/0xB0/0xC0`, but the dump still needs one confirmed executable-side inventory/HUD anchor before it can decode the runtime weapon list. Live database cleanup in the same pass also added `0x800232f0` -> `psx_set_debug_extra_channel_gate` and reinforced the selected/equipped chain around `0x8002ef34`, `0x8002f15c`, `0x800315d8`, `0x8003d02c`, and `0x800424ac`.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now records a fresh six-agent `SLUS_002.68` pass that added a second runtime-artifact lane instead of only rechecking the executable. The new distinction is now explicit: `binary/Crusader - No Remorse Memdump Weapons.bin` remains a VRAM/HUD artifact, while `binary/Crusader - No Remorse Weapons Main Ram.bin` is plausible 2 MiB PSX main RAM but still not self-decoding enough to resolve the selected `JL-?` slot as `JL-2` versus `JL-9` without the executable-side id/name chain. The same pass also tightened the live database around the selected/equipped path with fresh comments on `0x8002ef34`, `0x8002f15c`, `0x800315d8`, `0x8003d02c`, `0x800424ac`, and explicit extra-unlock naming at `0x80030004` -> `psx_weapon_channel_unlock_and_seed_markers`, while keeping `JL-2 AMMO` as the strongest current normal-lane lead.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) has now been normalized after a new six-agent `SLUS_002.68` pass instead of continuing to accumulate repeated follow-up narratives. The same batch adds two concrete deltas: the checked `binary/Crusader - No Remorse Memdump Weapons.bin` artifact now has a narrower runtime-artifact read as PSX VRAM with HUD/icon-atlas content but no direct slot-RAM proof for `JL-2` versus `JL-9`, and the next weapon-side unknown is now better framed as `JL-2` ammo/storage behavior because `JL-2 AMMO` exists at `0x800642b6` while `JL-9` still remains the stronger extra hidden/debug-conditioned lane. The live PSX database also gained a few more small durable artifacts in this pass, including the explicit helper name `psx_weapon_channel_unlock_and_seed_markers` at `0x80030004` plus confirming HUD/commit comments around `0x8002f15c`, `0x800323b0`, `0x80042690`, and the weapon-def base `0x8006466a`.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now records a narrow 2026-04-11 follow-up on live `SLUS_002.68` that split symbolic cleanup from runtime-artifact checking. The live PSX database now carries evidence-backed JL-lane data names (`psx_hidden_passcode_flag`, `psx_debug_extra_channel_gate`, `psx_level_runtime_header_state`, `channel_commit_row_table`, `channel_commit_row_selected_item_id`, `committed_selected_item_id`, `psx_weapon_spawn_type`, `psx_weapon_spawn_audio_event_id`, and `psx_weapon_spawn_state_selector`), while the checked `binary/Crusader - No Remorse Memdump Weapons.bin` artifact is now explicitly reclassified as a full 1 MiB PSX VRAM dump rather than slot/inventory RAM. The same pass also sharpens the next pivot if the extra hidden/debug lane remains `JL-9`: `JL-2` now has direct `JL-2 AMMO` string evidence (`0x800642b6`) without a matching plain `JL-9 AMMO` peer, so the next useful unknown becomes JL-2's ammo/storage and normal-acquisition behavior rather than more blind JL-9 existence proof.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now includes a 2026-04-11 MCP-only direct mapping proof pass for the requested chain on live `SLUS_002.68`: channel commit (`0x8002ef34`) -> committed item id load from `DAT_80064355[(channel*10)+9]` at `0x8002f15c` -> row-indexed weapon-def access with explicit `idx*0x26` stride at `0x800315d8/0x8003160c` from base `0x8006466a` -> concrete row split `0x0c=0x80064832 (JL-2)` vs `0x0d=0x80064858 (JL-9)`. The note now also includes row-byte diff evidence from MCP compare (`+0x24: 0x4b -> 0x0f`, name-field byte `0x32 -> 0x39`) and records that `0x800322b4..0x800325f8` remains only supporting UI-tail evidence (`0x0121 -> 0x013f`), not the primary commit/resolver path.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now includes a 2026-04-11 MCP-only row-field consumer trace for `JL-2` (`0x80064832`) versus `JL-9` (`0x80064858`) on live `SLUS_002.68`. The new closure is lane-level: shared `+0x1c=0x18` still converges through `psx_weapon_def_apply_spawn_profile_by_index` (`0x8003d02c`) into the same type-indexed active art-header bind path in constructors (`0x800249f4` / `0x80024eec` via `DAT_800758d8`), while diverged `+0x24` (`0x4b` vs `0x0f`) remains consumed as a compact transition/state selector (returned from `0x8003d02c`, then used in callers like `0x80018bc4/0x80018bf8`) rather than a direct base-resource pointer. Current best answer is shared base-art lane with distinct selector/state lane, and runtime capture is still required only for exact final frame/resource-token closure.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now includes a 2026-04-11 MCP-only four-lane acquisition comparison on live `SLUS_002.68` across normal loadout (`0x8002f814`), shop (`0x8003de68`), scripted grant (`0x800311f4..0x800313b4`), and debug grant (`0x8002fd90`). The strongest new discriminator is address-local and explicit: only debug grant performs the post-`0x0c` extra unlock call (`0x80030004 -> psx_weapon_channel_unlock_and_seed_markers(0x0d)`) behind `DAT_8006739d` read at `0x8002fff4`, while the L0SR-linked gate chain remains `0x8003ed28 (DAT_80067454=1)` -> `0x80013154/0x80013174` -> `0x8002fd90`. Current best conclusion remains that the extra post-L0SR non-PC weapon lane is `JL-9` (`0x80064858`, index `0x0d`) rather than `JL-2` (`0x80064832`, index `0x0c`), with three conservative new comments at `0x8003de68`, `0x80031344`, and `0x80030004`.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now includes a 2026-04-11 MCP-only recheck of the hidden passcode to extra-unlock chain on live `SLUS_002.68`. The practical read is tighter: hidden decode branch at `0x8003ed28` sets `DAT_80067454`, runtime input gate at `0x80013154/0x80013174` reaches `psx_debug_grant_weapon_channels_and_ammo`, and the extra late unlock remains a second gate (`DAT_8006739d` at `0x8002fff4`) for index `0x0d`. Current direct conclusion remains that the extra late unlock lane maps to `JL-9` (index `0x0d`) rather than `JL-2` (`0x0c`), with the remaining closure target narrowed to one direct UI label-resolver chain plus full `DAT_8006739d` writer-context classification.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now includes a 2026-04-11 MCP-only pass that tightened the unresolved `0x800323xx` lane and selected-id tail evidence in live `SLUS_002.68`. The lane is now anchored as render-mode UI state via `psx_render_mode_dispatch` (`0x800350a8`) and callback table `0x800648b4`, with `psx_ui_state_handler_322b4_color_cycle` driving `DAT_800678f8` from `0x80064880` and a terminal toggle `0x0121 -> 0x013f`, then consumed by `psx_hud_draw_selected_item_tile_bar` at `0x800424ac`. This batch also landed conservative naming/comments (`0x8003ddcc`, `0x800424ac`, and comments at `0x800323b0`, `0x800323e4`, `0x80042690`) and keeps the strongest current JL read as selected-id-backed (`JL-2 ~ 0x0121`, `JL-9 ~ 0x013f`) while direct channel-number equivalence remains a dedicated follow-up target.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now includes a 2026-04-11 shipped-map weighting follow-up that keeps executable-side evidence authoritative and uses scene-cache evidence as support. Current best read tightens one practical decision: `JL-2` remains the stronger normal-lane shipped candidate (`0x0c`), while `JL-9` remains the stronger exceptional/debug-conditioned lane (`0x0d` behind `DAT_8006739d`). The pass also leaves concrete continuation anchors: current `DAT_8006739d` writer condition at `0x800232f0`, late-mode candidate range (`46..58` and `63`) from `0x80063e68`, and dense section0 cache targets (`map 46/49/63`) for direct placement correlation.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now records a focused live `SLUS_002.68` row-to-consumer pass that resolves the earlier JL-9 selector ambiguity. Current best read is tighter in three concrete ways: the candidate pair is corrected to `JL-2(+0x24=0x4b)` versus `JL-9(+0x24=0x0f)` while both keep `+0x23=0x0e`; both rows still converge through shared `+0x1c=0x18` into the same type-indexed base art bind path (`psx_weapon_def_apply_spawn_profile_by_index` -> object constructors -> `psx_type_art_active_header_bank[type]`); and the `+0x24` consumer lane is now evidenced as transition/spawn-state-facing rather than direct bundle-id-facing. Remaining closure stays narrow: runtime capture is still required to export final JL-9 frame/resource identity with certainty.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now adds a direct UI/state disambiguation pass for the hidden-passcode "all weapons received" outcome on live `SLUS_002.68`. The previously suspicious `0x800323xx` lane is now recovered as render-mode UI color/flash handling (`psx_render_mode_dispatch` callback table at `0x800648b4`, `0x80064880` halfword ramp into `DAT_800678f8`, consumed by `FUN_800424ac` tile-color writes), not weapon-name display/selection logic. The strongest identity proof now sits in the commit path: `psx_apply_channel_effect_and_commit_selected_item_id` commits `DAT_80064355[channel*10]`, channel `0x0d` row at `0x800643ce` stores item id `0x0d`, and weapon-def index `0x0d` is row `0x80064858` (`JL-9`) versus index `0x0c` row `0x80064832` (`JL-2`).
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now includes a narrow 2026-04-11 reconfirmation pass over hidden passcode decode and late weapon unlock gating in live `SLUS_002.68`. The new evidence closes two practical points: `DAT_8006739d` usage in this image is now exhaustively bounded to one writer (`0x800232c0`) and one reader (`0x8002fd90`), and the extra conditional unlock call in `psx_debug_grant_weapon_channels_and_ammo` is now tied to index `0x0d` as the post-`0x0c` final JL lane, strengthening the JL-9-over-JL-2 conclusion for the hidden/debug route while keeping one explicit caveat that a single direct UI label resolver chain was not recovered in this pass. This batch also landed small durable artifacts in the live database: `FUN_8003ddcc` -> `psx_shop_entry_get_mode_gated_cost_by_slot`, new thin wrappers `psx_script_dispatch_packed_channel_actions_from_object` (`0x800203b0`) and `psx_script_dispatch_marker_mode_action_from_byte` (`0x800203ec`), and targeted decompiler comments at `0x8003de68`, `0x8002fff4`, and `0x80064858` to preserve the `0x0c` (`JL-2`) versus `0x0d` (`JL-9`) acquisition split.
|
||||
|
||||
Latest verified batch: [docs/psx/jl-9-investigation.md](docs/psx/jl-9-investigation.md) now consolidates the focused live `SLUS_002.68` JL-9 / hidden-passcode / debug-leftover sweep instead of leaving those results spread across subagent-only Ghidra edits. The live PSX database now has a tighter weapon-side helper family (`psx_weapon_marker_activate_by_index`, `psx_weapon_marker_add_with_cap_by_index`, `psx_weapon_def_get_u16_with_mode_gate`, `psx_weapon_def_apply_spawn_profile_by_index`, `psx_weapon_shop_try_apply_entry`, `psx_debug_grant_weapon_channels_and_ammo`, and the passcode decoder/generator pair), and the practical read is sharper in four ways: `JL-9` is now closed as a real final indexed PSX weapon-definition row rather than a stray string; the hidden passcode decoder is now directly recovered as transformed table logic instead of only inferred from folklore; the strongest current `how do you get JL-9` answer is a hidden passcode branch that sets `DAT_80067454` and then reaches the bulk weapon-unlock helper's extra late channel; and the remaining PSX gaps are now narrower again, concentrated in exact `channel -> JL-9` proof, exact sprite/frame/resource mapping, and exact level-placement correlation rather than in the broader existence question.
|
||||
|
||||
Latest verified batch: [docs/psx/map-rendering.md](docs/psx/map-rendering.md) and [docs/psx/map-viewer-plan.md](docs/psx/map-viewer-plan.md) now capture the next six-agent PSX table-typing pass rather than another broad sweep. The live database now promotes `DAT_80067938` to `psx_ctor_placement_section_ptr`, `DAT_800676d8` to `level_clut_table_ptr`, `DAT_80067840` to `psx_control_opcode_stream_table`, and `DAT_80063e54/0x80063e68` to paired per-level selector/channel tables, while the earlier `DAT_800675ec` marker/control runtime block now has a stronger local field map centered on `+0x34`, `+0x6c`, and `+0x88/+0x8c`. Current best read is tighter in three practical ways: the constructor-placement section is now clearly a section-pack root with subordinate indexed control rows rather than one opaque blob; the CLUT and opcode-stream tables are now pushed off the shortlist of direct `0x0042` art discriminators and into palette/control support; and the real remaining structural blocker family is now the level-indexed `0x63e54/0x63e68/0x675ec` control island plus the exact installed rows fed from the decompressed/runtime-bank install chain.
|
||||
|
||||
Latest verified batch: [docs/psx/map-rendering.md](docs/psx/map-rendering.md) now records a storage-mapping pass on live `SLUS_002.68` that stayed off broad draw-path analysis and traced ownership from WDL section installs through compressed-state unpack into runtime banks consumed by type `0x0042` object creation/presentation. The live database now also carries four small evidence-backed names in this lane (`FUN_8003b00c` -> `psx_lzss_unpack_into_level_buffer`, `FUN_8003aba8` -> `psx_lzss_pack_level_buffer`, `DAT_8006b5d8` -> `psx_level_state_compressed_blob`, `DAT_8006763c` -> `psx_level_heap_cursor`) plus targeted comments at `0x80039af0` and `0x800249f4`. Current best read is tighter in one practical way: the map-storage ownership chain is now concretely anchored from level-load section pointers to constructor/draw-time bank consumers, and the remaining blockers are narrowed to unresolved subordinate table schemas and per-item map-104 `0x0042` resource/state correlation.
|
||||
|
||||
Latest verified batch: [docs/psx/map-rendering.md](docs/psx/map-rendering.md) now captures a focused PSX type-policy provenance pass around `DAT_800675f8` / `psx_type_policy_table_ptr` for `map 104` type `0x0042` and control type `0x0066`. The live `SLUS_002.68` database now adds one safe reader rename (`0x8001408c` -> `psx_update_nearest_policy80_contact_marker`) plus targeted comments at `0x800398f0`, `0x8002bf0c`, `0x80041604`, and `0x800140c8` that pin installation and major consumer roles. Current best read is tighter in three practical ways: pointer provenance is now explicit as level-load section-pack storage (single writer at `0x800398f0` in `wdl_resource_bundle_load_by_index`), consumer coverage now extends beyond the older `0x1000/0x0600/0x2000` set to additional policy bits (`0x0008`, `0x0010`, `0x0020`, `0x0080`, `0x0100`, `0x0800`, `0x4000`, `0x8000`), and the fixed map-104 sample rows (`25/30/31/35/85/86` and control `53`) still show `runtimeDiagnostic.typePolicy.word=null`, confirming concrete row-word capture remains a runtime export gap rather than an executable-static decode gap.
|
||||
|
||||
Latest verified batch: [docs/psx/map-rendering.md](docs/psx/map-rendering.md) now captures a focused object-local route-bit provenance pass for fixed `map 104` `0x0042` sample items `25/30/31/35/85/86` at the decisive `obj+0x1c & 0x0400` branch in `psx_object_integrate_motion_and_route_visible`. Current best read is now stricter and evidence-backed: `psx_object_create_simple_record` (`0x80024b48`) and `psx_object_create_compound_record` (`0x80025040`) remain the strongest object-local writers because they copy authored `u5` directly into `obj+0x1c`; inspected named mutators in the same lane (`psx_type42_transition_selector_tick`, `psx_object_select_state_from_transition_table`, `psx_object_advance_state_script`, `psx_apply_deferred_control_to_live_objects`, `psx_object_handle_control_pair_0a`) change other route/control bits but did not reveal a direct object-local `0x0400` set/clear transform; and recovered `0x0400` writes remain nested/global (`psx_object_state_machine_dispatch_tick` nested runtime write at `0x8001a078`, global policy write in `psx_object_handle_control_pair_0a` at `0x80022a14`). The remaining gap stays narrow: a live capture is still required to close object-local `0x0400` provenance for this sample pack.
|
||||
|
||||
Latest verified batch: [docs/psx/map-rendering.md](docs/psx/map-rendering.md) now records a focused frame-geometry pass on active `SLUS_002.68` following the selector/latch bridge into exact width/height/origin consumers. The live evidence chain is now explicit from `psx_object_select_state_script` (`obj+0x9e` install) and `psx_object_advance_state_script` (`obj+0x94` latch) into `psx_project_object_main_visible` / `psx_project_object_special_visible_queue`, then into `psx_resource_frame_origin_x/y` and `psx_resource_frame_width/height`. Current best read tightened one step further: for the fixed `map 104` `0x0042` sample pack, `64x40` versus `64x64` is most strongly a live frame-token (`obj+0x94`) outcome within a shared type resource lane, not a late presentation modifier; the remaining closure task is a compact live sample of bound-resource kind plus latched frame token for items `25/30/31/35/85/86`.
|
||||
|
||||
Latest verified batch: [docs/psx/map-rendering.md](docs/psx/map-rendering.md) now captures a broad but concrete table-inventory pass against live `SLUS_002.68` focused on unresolved `map 104` / type `0x0042` storage and rendering coverage. The live database now adds six marker-channel/runtime-state helper names (`0x8002f190`, `0x8002f250`, `0x80031840`, `0x8003185c`, `0x80031878`, `0x80031a3c`) and targeted table comments on `0x80063e68`, `0x800675ec`, and `0x80063e54`. Current best read is tighter in two practical ways: the known descriptor/transition/runtime-bank tables are reaffirmed as shared/generic infrastructure rather than a missing unique `0x0042` fork, and the `0x80063e54/0x80063e68/0x800675ec` level-indexed control island is now promoted as a high-value unresolved table family worth explicit struct/table mapping in the next batch.
|
||||
|
||||
Latest verified batch: [docs/psx/map-rendering.md](docs/psx/map-rendering.md) and [docs/psx/map-viewer-plan.md](docs/psx/map-viewer-plan.md) now capture another six-agent concrete `map 104` `0x0042` pass over the same fixed sample pack instead of broadening the search surface. The live PSX database now also names two selector-overlap probes, the runtime snapshot/release helpers, and a wider root marker/channel helper family. Current best read is tighter in three practical ways: the `64x64` versus `64x40` split still looks more like shared-resource / different-frame-state behavior than a different constructor bind path; the selector-to-frame bridge is now explicit through `obj+0x9e` install, `obj+0x94` latch, and the later frame-geometry consumers; and the stage-1 versus stage-2 branch point is now explicit in `psx_object_integrate_motion_and_route_visible`, even though the exact live `0x0400` provenance for this sample pack still needs capture. The next `map 104` pass should therefore stay on items `25/30/31/35/85/86` and capture bound resource identity plus live frame/state and route-bit state at the decisive branch instead of widening heuristics.
|
||||
|
||||
Latest verified batch: [docs/psx/map-rendering.md](docs/psx/map-rendering.md) and [docs/psx/map-viewer-plan.md](docs/psx/map-viewer-plan.md) now capture the first concrete `map 104` `0x0042` `runtimeDiagnostic` follow-up against exported scene items rather than another generic six-track theory pass. The live PSX database now names the spawn-side selector bridge (`psx_transition_spawn_and_seed_selector_from_record`), a root-family decoder helper (`psx_section0_dispatch_root_find_marker_record_by_channel`), two nearby resource-upload helpers, the type-policy pointer (`psx_type_policy_table_ptr`), and the transition row tables (`psx_type_transition_mode_policy_rows`, `psx_type_transition_selector_rows`). Current best read is tighter in four practical ways: the root and constructor section-0 families now have explicit named entry points but still converge through the same shared `0x0042` descriptor row; constructors are now proven to seed `obj+0x1c` by directly copying the authored lane word, so exported `initialWord` values are meaningful authored state; the strongest recovered `0x0400` control is still nested-state-side rather than a direct object-local `0x0042` writer; and `DAT_800675f8` is now better modeled as a level-loaded per-type policy pointer, not a per-lane discriminator. The next `map 104` pass should therefore sample bound-resource identity plus live frame/state against the fixed item set (`item:25/30/31/35/85/86`) rather than widening donor logic or revisiting descriptor speculation.
|
||||
|
||||
Latest verified batch: [docs/psx/map-rendering.md](docs/psx/map-rendering.md), [docs/psx/map-viewer-plan.md](docs/psx/map-viewer-plan.md), and [map_renderer/src/lib/psx-cache.js](k:/ghidra/crusader_map_viewer/map_renderer/src/lib/psx-cache.js) now capture both sides of the next PSX narrowing step. The live Ghidra work stayed split across six non-overlapping `0x0042` tracks, and the viewer exporter now serializes the resulting channel model as a per-item `runtimeDiagnostic` payload in scene version `psx-runtime-record-probe-v10`. Current best read is now operationally tighter: the next `map 104` pass no longer needs to rediscover which fields matter, only to populate the exported channels for representative `0x0042` items with live evidence for pre-latch selector dispatch, latched state, object-local route flags, nested runtime state, resource kind, and the live type-policy word.
|
||||
|
||||
Latest verified batch: [docs/psx/map-rendering.md](docs/psx/map-rendering.md), [docs/psx/map-viewer-plan.md](docs/psx/map-viewer-plan.md), and [docs/psx/psx.md](docs/psx/psx.md) now capture another six-track live `SLUS_002.68` PSX batch with deliberately separate coverage areas instead of overlapping helper sweeps. Current best read is tighter in four ways: the per-type art/cache pair is now named by behavior (`DAT_800758d8 = psx_type_art_active_header_bank`, `DAT_800758c8 = psx_type_art_built_resource_bank`); `psx_type42_transition_selector_tick` now has an early eligibility gate through `psx_object_is_within_view_margin` before it can emit selector `3/4` ahead of the later latch copy; the root-dispatch-side `0x0042` mode gate still looks control-only rather than a distinct map-facing presentation family; and the anonymous control-island recovery now proves `0x0400` writes in the wider nested runtime state machine and related policy controls without yet pinning a direct object-local `obj+0x1c |= 0x0400` writer. The next `0x0042` discriminator is therefore narrower again: a concrete runtime sample now needs to separate pre-latch selector dispatch, latched `obj+0x94`, object-local `obj+0x1c`, nested runtime state words, and bound resource kind instead of treating them as one flat route/state bucket.
|
||||
|
||||
Latest verified batch: [docs/psx/map-rendering.md](docs/psx/map-rendering.md), [docs/psx/map-viewer-plan.md](docs/psx/map-viewer-plan.md), and [docs/psx/psx.md](docs/psx/psx.md) now capture the next focused live `SLUS_002.68` follow-up on unresolved `0x0042` rather than another broad render pass. Current best read is tighter in five ways: type `0x0042` is now pinned to exact descriptor-table slot `0x80063220 -> 0x800626f8`; both section-0 constructor placements and root-dispatch rows still enter that same generic create/update/release family; type `0x0042` now also has a dedicated transition helper `psx_type42_transition_selector_tick` that can dispatch low turning selectors `3/4` before the `+0x94`-style runtime latch copy; `obj+0x1c` writer behavior is clearer because constructors seed it from authored `u5` while `psx_object_select_state_from_transition_table` only mutates bit `0x0002`; and `DAT_800675f8` now reads as policy bits (`0x1000` nearby-publication suppression, `0x0600` stage-1 ordering class, `0x2000` semitrans policy) rather than as the missing main route discriminator. The remaining next-step discriminator is therefore narrower again: concrete `0x0042` samples need to correlate pre-latch selector dispatch, latched `obj+0x94`, `obj+0x1c` bit `0x0400`, and bound resource kind, not just raw `u5` or generic transition-row contents.
|
||||
|
||||
Latest verified batch: [docs/psx/map-rendering.md](docs/psx/map-rendering.md), [docs/psx/map-viewer-plan.md](docs/psx/map-viewer-plan.md), and [docs/psx/psx.md](docs/psx/psx.md) now capture one more six-track live `SLUS_002.68` PSX pass centered on unresolved `0x0042` routing. Current best read is narrower in four practical ways: constructor and root-dispatch records both hand authored flags into `obj+0x1c`; `0x0020` is still the broad world-visible gate, `0x0002` still reads as orientation/extents behavior rather than a lane split, and `0x0400` is now the strongest recovered stage-2 special-visible selector; `psx_object_select_state_from_transition_table` now gives a concrete per-type selector source ahead of `psx_object_select_state_script`; `psx_load_type_state_banks` now reads as the `DAT_800758cc/d0/d4` installer while `psx_stream_install_type_runtime_banks` is the packed-stream helper that can also install `DAT_800758d8`; and `DAT_80067794` is now tighter as save/transition runtime-header state via `psx_snapshot_level_runtime_header_block` / `psx_apply_level_runtime_header_block`, not as the missing `0x0042` art-binding source. The next executable-backed discriminator is therefore more specific again: sample representative `map 104` `0x0042` objects through `obj+0x1c`, `obj+0x10`, `obj+0x9e`, and `obj+0x94`, plus the `DAT_80063b4c` transition-table row for type `0x0042`, instead of spending another batch on raw `u5` or descriptor-table speculation.
|
||||
|
||||
Latest verified batch: [docs/psx/map-rendering.md](docs/psx/map-rendering.md) and [docs/psx/map-viewer-plan.md](docs/psx/map-viewer-plan.md) now consolidate the full six-track live `SLUS_002.68` PSX sweep instead of leaving the result fragmented across individual helper passes. Current best read is narrower in a way that changes the next execution order: unresolved `0x0042` is no longer plausibly blocked on a missing unique per-type descriptor fork or on HUD/overlay presentation behavior. `0x0042` still shares the generic `0x003e..0x0050` descriptor cluster, constructor-placement `0x0042` still reads as a compound -> advance-state -> main-visible route inside that generic family, both world-facing lanes choose sprite versus image-table submitters from the bound resource header kind, and the HUD/overlay lane remains an explicit non-map-facing exception that can branch from overlay-slot policy instead of normal world-object kind checks. The next practical discriminator for viewer recovery is therefore representative runtime-bank/state/resource-kind evidence for `map 104` `0x0042` families, especially the split between constructor-placement `u5=0x0020` and root-dispatch `u5=0x0030/0x0022`, not more broad donor reuse or descriptor-table speculation.
|
||||
|
||||
Latest verified batch: [docs/psx/map-rendering.md](docs/psx/map-rendering.md) now records a focused live `SLUS_002.68` world-frame/render-wrapper cleanup around `0x80031f0c`, `0x80031f9c`, `0x800320bc`, `0x80039dc4`, `0x8003977c`, and `0x800391f0`. The live PSX database now names `0x80031e0c` as `psx_lset_session_loop`, `0x80031f0c` as `psx_lset_world_frame_wrapper`, `0x80031f6c` as `psx_lset_session_teardown`, `0x800350a8` as `psx_render_mode_dispatch`, `0x80039ef4` as `psx_level_post_load_runtime_reset`, and `0x80044104` as `psx_present_frame_and_flip`, with direct technical comments set at the same loader/bank/runtime-header anchors. Current best read is tighter for reconstruction work: this lane now provides a clean evidence-backed chain from map-index bundle load and per-type bank install through runtime-header application to per-frame world visible draw and display flip, reducing ambiguity between storage decode and final presentation wrappers.
|
||||
|
||||
Latest verified batch: [docs/psx/map-rendering.md](docs/psx/map-rendering.md) now records a focused live `SLUS_002.68` main-visible ordering/update cleanup around `0x8001263c`, `0x80012c30`, `0x8002d59c`, `0x8002d778`, `0x8002ca74`, and `0x8002e064`. The live PSX database now has the missing parent function object covering the `0x80012b44/60/c0/f0` lane (`psx_object_integrate_motion_and_route_visible`) plus explicit helper names/contracts for `psx_object_update_runtime_input_modes`, `psx_main_visible_list_swap_entries`, `psx_main_visible_order_graph_unlink_pair`, and `psx_main_visible_order_graph_detach_object`; direct technical decompiler comments were also applied to the update/rebucket/sort call sites and sort entry points. Current best read is tighter for exporter coherence: object update now cleanly resolves into state advance -> optional projection -> conditional rebucket -> optional nearby-interaction publish, while stage-1 draw submission remains refresh-gated and dependency-sorted before `psx_draw_world_visible_passes` consumes the slice.
|
||||
|
||||
Latest verified batch: [docs/psx/map-rendering.md](docs/psx/map-rendering.md) now captures a focused live `SLUS_002.68` resource creation/submission cleanup around `0x80044434`, `0x800444e4`, `0x80044614`, `0x80044bdc`, `0x80044e9c`, and `0x80045ffc`. The live PSX database now also renames `0x800445c8` to `psx_overlay_slot_clone_bound_resource` and `0x80044fa4` to `psx_resource_release_image_vram_slot_if_needed`, with stale "verified by subagent pass" comments replaced by technical comments in the local HUD/overlay lane. Current best read is tighter for viewer art binding: kind `5` is the image-table submit path, kind `4` is the single-image bound sprite path, and the special-visible lane remains palette-override-distinct from main-visible despite sharing the same kind discriminator.
|
||||
|
||||
Latest verified batch: [docs/psx/map-rendering.md](docs/psx/map-rendering.md) now records a focused live `SLUS_002.68` interaction/reselection cleanup around `psx_type4_reselect_motion_state` and `psx_object_update_nearby_interactions`. The live PSX database now names `0x80028050` as `psx_object_test_strict_nonoverlap_flag8_pair`, `0x800281d4` as `psx_object_test_strict_nonoverlap_flag8_subject`, `0x80028700` as `psx_object_adjust_param9c_by_view_side`, `0x800287bc` as `psx_object_update_param9c_from_contact_target`, `0x80028eb4` as `psx_object_apply_contact_push_bias`, and `0x8002923c` as `psx_object_spawn_type11_contact_proxy`, with concise technical decompiler comments added at each entry. Current best read is tighter for exporter work: post-spawn contact handling in this lane mutates runtime extents/width state (`+0x30..+0x38`, `+0x9c`) and can spawn type-`0x11` contact proxies in-flow, so unresolved-family art fallback logic should continue to model these as runtime interaction effects rather than as static constructor-placement fields.
|
||||
|
||||
Latest verified batch: [docs/psx/map-rendering.md](docs/psx/map-rendering.md) now records a focused live `SLUS_002.68` presentation-lane cleanup around the HUD/overlay pass and adjacent helpers. The live PSX database now names `0x80035cc0` as `psx_overlay_slot_create`, `0x80036000` as `psx_overlay_slot_release`, `0x80038114` as `psx_overlay_slot_step_color_fade`, and `0x800388a8` as `psx_hud_overlay_init_resources`, with direct technical decompiler comments replacing one earlier generic "verified by subagent pass" note at `psx_draw_hud_overlay_pass`. Current best read is tighter for viewer work: `psx_level_session_loop -> psx_hud_overlay_init_resources` seeds HUD resources during level-session startup, `psx_draw_world_visible_passes` still executes world stage-1 then stage-2 lanes before calling `psx_draw_hud_overlay_pass`, and the `psx_overlay_slot_*` table is a non-map-facing presentation queue layered after world routing rather than a source of authored map geometry. The practical implication is narrower false-match risk: unresolved map-family art fallback should not reuse evidence from this overlay slot lane, because these slots are UI/presentation primitives independent of section-0 map record dispatch and world-object projection.
|
||||
|
||||
Latest verified batch: [docs/regret-hidden-debugger-investigation.md](docs/regret-hidden-debugger-investigation.md) now also records the debugger-side cleanup pass after the first `.unk` loader/runtime split, the final exhaustive Regret-side caller sweep, and the first practical seeding/simulation model. The live `REGRET.EXE` database now has the source-pane constructor/pointer/draw/viewport methods, the source-buffer create/load/split/destroy chain, the breakpoint-table helpers, the current-entry push/pop helpers, the interpreter saved-farptr helpers (`13f0:0000/003c`), the interpreter-context create/init pair (`13f0:00e8/0244`), the shared slot-chunk accessor at `13f8:1d72`, and the named interpreter wrapper at `13f8:10da` that feeds `usecode_debugger_interpreter_hook`. The practical consequence is sharper than before: the remaining blocker is not `can we export readable source` or even `can compiled usecode carry line numbers`, because retail Remorse already can, and it is no longer `what else in Regret might still be debugger-related`. The remaining blocker is now narrowly `where inside the already-identified interpreter dispatcher/runtime path does Regret seed the current-entry stack, and how can that same engine-side path be reused or reproduced for stable RUN/step behavior`, with the strongest current simulation route now being a small in-process reuse of existing VM context data rather than blind external memory poking or offline-only source-file tricks.
|
||||
|
||||
Latest verified batch: [docs/jp-remorse-hidden-debugger-investigation.md](docs/jp-remorse-hidden-debugger-investigation.md) now records the first debugger-focused comparison pass on `/ja/CRUSADER.EXE`. Current best read is narrower than the No Regret result but still decision-relevant: the JP Win32 build clearly retains broad executable cheat/debug machinery, yet live byte searches on the active image found no hits for the classic hidden usecode-debugger UI bundle (`Goto Line`, `Watch what?`, `Inspect what?`, `Global name`, `Search for`, `FILE NOT FOUND`, `Unable to open this file`, `Nothing to find`, `Not found`, `Done`) even though the same method still recovers positive-control strings like `JASSICA16`, `Immortality enabled.`, and `Cheats are now active.`. The practical consequence is that JP currently strengthens the `broad Win32 cheat/debug preservation` story, but not the `JP preserved the missing retail debugger bootstrap` theory; No Regret remains the stronger sibling-build anchor for the hidden-debugger unlock problem.
|
||||
|
|
@ -25,7 +245,7 @@ Latest verified batch: [docs/retail-debugger-entry-options.md](docs/retail-debug
|
|||
|
||||
Latest verified batch: [docs/startup-map-patch-file.md](docs/startup-map-patch-file.md) now closes the long-standing startup string `Using map patch file.` tightly enough to stop treating it as a vague debug/status artifact. Current best read is that `Init_Everything` prints that line only when `static\fixed.dat` exists, and the later fixed-map cache path then prefers the loaded `static\fixed.dat` archive handle over the base `fixed.dat` handle for map/fixed-object reads. The remaining uncertainty in this lane is now narrow: whether any later consumer does a finer-grained fallback/merge than the first recovered chooser, not what the startup line is referring to in the first place.
|
||||
|
||||
Latest verified batch: [docs/psx/psx.md](docs/psx/psx.md), [docs/psx/map-rendering.md](docs/psx/map-rendering.md), [docs/psx/map-viewer-plan.md](docs/psx/map-viewer-plan.md), and [docs/psx/art-binding-recovery.md](docs/psx/art-binding-recovery.md) now tighten the PSX render-side model another step in both Ghidra and the viewer exporter. The earlier `DAT_800758d4` consumer finding remains intact and is still wired into the viewer-side cache path as explicit `companionExtents` metadata, but the bigger practical change in this batch is the first measured art-binding recovery pass for the viewer exporter: the PSX cache builder now treats large zero-block `DAT_800758d8` constructor-placement bands as inherited-art candidates, first via same-map `DAT_800758cc` script-signature donors and then via a constrained nearest-donor fallback inside the current `0x003e..0x0064` family. That rebuild moved the scene set from `58,262` fallback items / `1,714` bundle-mapped items to `25,038` fallback items / `34,938` bundle-mapped items, making early representative maps such as `0`, `9`, and `43` mostly real-art while leaving `map 104` and the remaining `0x0042` / `0x0055..0x0063` constructor-placement band as the clearest unresolved outliers. The practical remaining gap is therefore narrower now: not "why are most PSX scenes placeholders" but "what executable-backed alias/resource rule explains the remaining zero-block constructor-placement families without leaning on donor heuristics."
|
||||
Latest verified batch: [docs/psx/psx.md](docs/psx/psx.md), [docs/psx/map-rendering.md](docs/psx/map-rendering.md), [docs/psx/map-viewer-plan.md](docs/psx/map-viewer-plan.md), and [docs/psx/art-binding-recovery.md](docs/psx/art-binding-recovery.md) now tighten the PSX render-side model another step in both Ghidra and the viewer exporter. The earlier `DAT_800758d4` consumer finding remains intact and is still wired into the viewer-side cache path as explicit `companionExtents` metadata, but the bigger practical change in this batch is the first measured art-binding recovery pass for the viewer exporter: the PSX cache builder now treats large zero-block `DAT_800758d8` constructor-placement bands as inherited-art candidates, first via same-map `DAT_800758cc` script-signature donors and then via a constrained nearest-donor fallback inside the current `0x003e..0x0064` family. That rebuild moved the scene set from `58,262` fallback items / `1,714` bundle-mapped items to `25,038` fallback items / `34,938` bundle-mapped items, making early representative maps such as `0`, `9`, and `43` mostly real-art while leaving `map 104` and the remaining `0x0042` / `0x0055..0x0063` constructor-placement band as the clearest unresolved outliers. The newest live follow-up now sharpens the next branch enough to change execution order: `psx_draw_main_visible_object` applies authored palette overrides only for type bands `0x003e..0x00ab` (`source+0x06` high byte) and `>=0x00ac` (`source+0x0c` high byte), `psx_draw_special_visible_queue` skips those overrides entirely, and `psx_sprite_resource_submit_frame` versus `psx_image_table_submit_frame` resolve the same high-byte token through different CLUT tables. The latest coherence pass narrows that again in a way the exporter has to respect: `psx_level_session_loop` installs CLUT tables during level load via `wdl_resource_bundle_load_by_index -> level_palette_header_apply -> level_palette_upload_cluts`, both constructors bind the drawable resource at spawn from `DAT_800758d8`, `psx_object_integrate_motion_and_route_visible` advances state and routes objects into stage-1 versus stage-2 visibility, and `psx_main_visible_list_sort_range` dependency-sorts the stage-1 slice before draw submission. The newest six-track subagent sweep closes two more structural gaps: `0x0042` still shares the generic descriptor cluster used across `0x003e..0x0050` instead of owning a unique descriptor fork, and the root-dispatch `u5=0x0022` versus `u5=0x0030` split currently looks like a main-visible presentation/orientation variant rather than a separate draw lane. The viewer-side donor fence now reflects that narrower read: mixed-family and mixed-`u5` provisional donor merges for unresolved generic-family types are blocked, so `map 104` `0x0042` is back on explicit placeholders instead of one shared false wall. The practical remaining gap is therefore narrower now: not "why are most PSX scenes placeholders" and not even just "which palette index is right", but "which runtime-bank/state/resource-kind combination explains the remaining `0x0042` presentation families without reopening broad donor heuristics."
|
||||
|
||||
- Overall useful decompilation progress: about 59%
|
||||
- Reasonable uncertainty band: about 56% to 64%
|
||||
|
|
@ -77,6 +297,7 @@ Measured live naming floor for `CRUSADER.EXE` right now:
|
|||
- The PSX lane is no longer just side inventory. Retail/pre-alpha bundle loading, mission-briefing/passcode structure, the reduced-content pre-alpha disc, and now the retail map object's last projection stage all have dedicated notes and enough stable naming to support future targeted passes.
|
||||
- The Remorse class-lift preparation lane now has a usable document cluster: overall plan, candidate inventory, endpoint spec, ABI constraints, family notes for `EntityDispatchEntry` and `SpriteNode`, a conservative `Entity` family split, a VM runtime/owner-resource layout note, a compatibility-header draft, and one grouped resume index.
|
||||
- The same class-lift prep lane is now more execution-ready: the `0x4588` broker family has its own focused object note, the toolchain story has a dedicated fingerprint-evidence note, and there is now a concrete first-batch class-authoring checklist ready for the first MCP-backed namespace/struct/vtable pass.
|
||||
- The live Remorse class-authoring lane now also has its first bounded NPC AI family lifted as class owners instead of flat process names: `Remorse::NPCActionProcess` plus `StandProcess`, `PaceProcess`, `SurrenderProcess`, `GuardProcess`, and `LoiterProcess` now exist in-session with their direct create/run/destroy surfaces moved under class ownership, while the shared guard/loiter idle helper remains a free function on purpose until a stronger single-class owner emerges.
|
||||
- The live Remorse VM class-lift lane also recovered from a decompiler breakage in `Remorse::EntityVmRuntime::Create`: the root cause was a hidden-return-storage allocator helper signature at `1000:42e2`, `Create` now decompiles again, and the provisional `/Remorse/EntityVmSlotEntry` datatype now exists with the stable `+0x1e..+0x24` buffer-pair fields named.
|
||||
- The live Remorse VM class-lift lane is tighter again: the old `UsecodeProcess_*` context lifecycle bodies at `1420:0eec`, `1420:10b6`, `1420:10da`, `1420:1162`, `1420:118f`, and `1420:1278` now live under `Remorse::EntityVmContext::{CreateFromSlotIndex, FreeBuffer, SyncGlobalValueAndDispatch, Destroy, Save, Load}`, with short raw `000d:` provenance comments preserved on each entry.
|
||||
- The same VM class-lift lane tightened one step further through local PyGhidra fallback once the live `run_write_script(...)` route still returned `404 No context found for request`: `/Remorse/EntityVmContext` is now a real datatype, `entity_vm_slot_entry_create_or_clear` and `InitSlotOwnerBuffers` now carry `EntityVmSlotEntry *`, `AcquireSlotForEntity` now returns `EntityVmSlotEntry *`, and `InitSlots` / `ReleaseSlots` now take direct `EntityVmRuntime * this`.
|
||||
|
|
@ -141,7 +362,7 @@ Measured live naming floor for `CRUSADER.EXE` right now:
|
|||
3. Promote ledger coverage from existing verified notes before broadening into fresh executable-wide sweeps.
|
||||
4. Use overlap repair only where it unlocks an active high-payoff lane.
|
||||
5. Use the map-renderer/tooling lane to validate shape ids, map placements, and viewer semantics before promoting additional static-object names in Ghidra.
|
||||
6. Keep the PSX lane focused on the final state/variant/art bridge now that the first post-spawn interaction/reselection cluster is named; avoid broad renderer-side heuristics that bypass those runtime paths.
|
||||
6. Keep the PSX lane focused on the final lane-aware state/resource/frame/palette bridge now that the first post-spawn interaction/reselection cluster is named; avoid broad renderer-side heuristics that bypass those runtime paths or flatten main-visible and special-visible palette behavior together.
|
||||
|
||||
## Next Resume Point
|
||||
|
||||
|
|
@ -160,13 +381,14 @@ The newest broad-sweep UI batch tightened three more local families without need
|
|||
8. Tighten the seg006 masked-helper caller chains so the local state-selector/value family can be tied to concrete gameplay subsystems.
|
||||
9. Classify the paired seg070 loops behind `entity_vm_runtime_owner_resource_create`, especially which temporary buffers and record schemas each family populates.
|
||||
10. Stay on the Remorse VM class-lift batch while the repaired runtime lane is warm: use the now-recovered `CreateFromSlotIndex` caller pack to decide whether any remaining scalar positions deserve stronger typedefs, but keep the return semantically conservative until the base-process inheritance model is explicit enough to justify a prettier live return type.
|
||||
11. The current broader Remorse follow-up batch is now materially tighter: `WatchEntityController` is effectively re-identified as the live camera-process create lane, `DialogMenuObject` is the last compact family here without a safe live re-anchor, `PresentationCallbackBroker` now has install/teardown plus both slot `+0x08` and preserved slot `+0x0c` caller evidence, `CacheBackendObject` has its indexed entry writer, and `SpriteNode::Create` now looks like the shared compact node constructor for `GumpCreate_*` wrappers. The clearest next unresolved items are therefore: a safer live reanchor for `DialogMenuObject`, a decision on whether the camera-process lane should stay under the stronger live `Camera_*` naming or also receive a class-owner layer, deeper slot `+0x0c` payload classification in the broker lane, and higher-level subtype/layout work above the compact `SpriteNode` base.
|
||||
12. In the local GhidraMCP upgrade lane, add support for dual POST body decoding (`application/json` plus form-urlencoded) and a constrained live write-side PyGhidra endpoint family so future custom-storage/type repairs can stay inside the active MCP session when Python is enabled.
|
||||
13. Promote additional ledger rows directly from already-verified docs and live comments, especially where segments already deserve `Foothold`, `Partial`, or `Deep`; the new seg029 step-aware sweep batch, seg031 queue-release batch, seg090 movement-helper batch, seg033 NPC-process foothold, and seg032 item-type foothold should be the immediate template.
|
||||
11. Stay on the new Remorse NPC action-process class-lift lane while seg033 is warm: the owner-first move is done, so the next bounded pass should recover process-function-table slot order, inspect `StandProcess::Run` and `PaceProcess::Run` for equally strong family-local helpers, and decide whether a provisional `/Remorse/NPCActionProcess` datatype is safe or whether the family should remain owner-only for now.
|
||||
12. The current broader Remorse follow-up batch is now materially tighter: `WatchEntityController` is effectively re-identified as the live camera-process create lane, `DialogMenuObject` is the last compact family here without a safe live re-anchor, `PresentationCallbackBroker` now has install/teardown plus both slot `+0x08` and preserved slot `+0x0c` caller evidence, `CacheBackendObject` has its indexed entry writer, and `SpriteNode::Create` now looks like the shared compact node constructor for `GumpCreate_*` wrappers. The clearest next unresolved items are therefore: a safer live reanchor for `DialogMenuObject`, a decision on whether the camera-process lane should stay under the stronger live `Camera_*` naming or also receive a class-owner layer, deeper slot `+0x0c` payload classification in the broker lane, and higher-level subtype/layout work above the compact `SpriteNode` base.
|
||||
13. In the local GhidraMCP upgrade lane, add support for dual POST body decoding (`application/json` plus form-urlencoded) and a constrained live write-side PyGhidra endpoint family so future custom-storage/type repairs can stay inside the active MCP session when Python is enabled.
|
||||
14. Promote additional ledger rows directly from already-verified docs and live comments, especially where segments already deserve `Foothold`, `Partial`, or `Deep`; the new seg029 step-aware sweep batch, seg031 queue-release batch, seg090 movement-helper batch, seg033 NPC-process foothold, and seg032 item-type foothold should be the immediate template.
|
||||
14. If the VM lane stalls, revisit `000e:ffb0` from the now-better-constrained video/audio caller windows and try to recover an adjacent non-overlapped helper before attempting broad boundary repair.
|
||||
15. Continue the map-renderer cross-check lane by building one conservative shape-id/map-placement crosswalk from `shapedata_more_complete.txt`, extracted corpora, and authored scene evidence before promoting more trigger-heavy classes in NE.
|
||||
16. Keep the PSX pre-alpha lane alive as a secondary target: classify the `LoadExec` callers, test whether the stale `TALK1.XA` path is still reachable, and compare the shipped `LSET1` bundles against the retail extractor outputs.
|
||||
17. Continue the retail PSX state/art lane from the new art-binding recovery baseline: keep `DAT_800758d4` on the runtime-bounds side unless new family-specific evidence contradicts it, treat `map 104` plus the remaining `0x0042` / `0x0055..0x0063` zero-block constructor-placement band as the primary regression target, and trace the next family-specific callers around `psx_type4_reselect_motion_state`, `FUN_80028c94`, constructor-side resource creation, and the drawable-resource/frame submission lane until the remaining donor-based fallback logic can be replaced with an executable-backed alias/resource rule.
|
||||
17. Continue the retail PSX state/art lane from the new art-binding recovery baseline: keep `DAT_800758d4` on the runtime-bounds side unless new family-specific evidence contradicts it, treat `map 104` plus the remaining `0x0042` / `0x0055..0x0063` zero-block constructor-placement band as the primary regression target, and trace the next family-specific callers around `psx_type4_reselect_motion_state`, `FUN_80028c94`, constructor-side resource creation, and the drawable-resource/frame submission lane until the remaining donor-based fallback logic can be replaced with an executable-backed lane-aware alias/resource/frame/palette rule. The first practical split to preserve is now explicit in the live database: main-visible objects can consume authored override bytes from different source offsets by type band, while the special-visible queue does not, and the next renderer-side check should keep the full coherence order intact: load-time CLUT install, spawn-time resource bind, frame-time state advance and routing, then stage-1 dependency sort before submission.
|
||||
|
||||
## Remaining Work To Reach A Reasonably Complete Decompilation State
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue