240 lines
12 KiB
Markdown
240 lines
12 KiB
Markdown
|
|
# Crusader 2 Pre-Pre Alpha (PlayStation) Recon
|
||
|
|
|
||
|
|
## Scope
|
||
|
|
|
||
|
|
- Target disc tree: `E:\emu\psx\Crusader 2 Pre-Pre Alpha`
|
||
|
|
- Active Ghidra program for this pass: `/psx/prealpha/SLUS_002.68`
|
||
|
|
- Comparison baseline: retail PlayStation `Crusader: No Remorse` findings in `docs/psx/psx.md`
|
||
|
|
- Goal of this pass: identify concrete differences from the released PSX build and record any interesting early-build leftovers visible in the executable and disc layout.
|
||
|
|
|
||
|
|
## Immediate Conclusions
|
||
|
|
|
||
|
|
- This pre-alpha does **not** currently look like a fully distinct `Crusader 2` executable identity.
|
||
|
|
- The executable still carries direct `Crusader: No Remorse` branding and other No Remorse-facing UI text.
|
||
|
|
- The level-loader code is already very close to the retail PSX loader: it still embeds all seven `\LSETn\L` prefixes and the same threshold split at map indices `10/20/30/40/50/60`.
|
||
|
|
- The disc content is dramatically reduced compared with retail: only `3` shipped level bundles, `1` XA file, no shipped movie `.STR` files, and no `LICENSEA.DAT` or `ZZZ.ZZZ` root files.
|
||
|
|
- The executable still retains content/system references that do not match the current unpacked pre-alpha disc, including `\AUDIO\TALK1.XA;1` and a `LoadExec` helper for `MENU.EXE`, `ENGINE.EXE`, and `PSX.EXE`.
|
||
|
|
- Current safest read: this build looks more like an earlier trimmed branch of the No Remorse PSX code/content pipeline than a clearly rebranded or content-rich standalone `Crusader 2` PSX build.
|
||
|
|
|
||
|
|
## Disc Tree Differences From Retail PSX
|
||
|
|
|
||
|
|
Top-level inventory contrast from the unpacked trees:
|
||
|
|
|
||
|
|
| Area | Retail `Crusader: No Remorse` | Pre-pre alpha | Current read |
|
||
|
|
|---|---:|---:|---|
|
||
|
|
| `SLUS_002.68` size | `675,840` bytes | `667,648` bytes | pre-alpha executable is smaller by `8,192` bytes |
|
||
|
|
| `.WDL` files | `66` | `7` | heavy content reduction |
|
||
|
|
| `.STR` files | `33` | `0` | no shipped movie streams in the pre-alpha tree |
|
||
|
|
| `.XA` files | `2` | `1` | only `MULTI8.XA` remains |
|
||
|
|
| `LSET` folders | `LSET1` through `LSET7` | `LSET1` only | only `L0.WDL`, `L1.WDL`, `L2.WDL` shipped |
|
||
|
|
| `MOVIES/` contents | populated | empty | folder exists but no `.STR` payloads |
|
||
|
|
| root extras | `LICENSEA.DAT`, `ZZZ.ZZZ` present | both absent | pre-alpha root is much leaner |
|
||
|
|
|
||
|
|
Pre-alpha top-level tree at this point:
|
||
|
|
|
||
|
|
- `AUDIO/MULTI8.XA`
|
||
|
|
- `FMV.BIN`
|
||
|
|
- `LEGAL.SCR`
|
||
|
|
- `LSET1/L0.WDL`
|
||
|
|
- `LSET1/L1.WDL`
|
||
|
|
- `LSET1/L2.WDL`
|
||
|
|
- `MENUS/M13.WDL`
|
||
|
|
- `MENUS/M21.WDL`
|
||
|
|
- `MENUS/M5.WDL`
|
||
|
|
- `SLUS_002.68`
|
||
|
|
- `SPEC_A.WDL`
|
||
|
|
- `SYSTEM.CNF`
|
||
|
|
|
||
|
|
Important contrast with retail:
|
||
|
|
|
||
|
|
- retail ships `62` level bundles across `LSET1..LSET7`
|
||
|
|
- this pre-alpha tree currently ships only `3` level bundles in `LSET1`
|
||
|
|
- retail ships `33` movie streams; this pre-alpha has an empty `MOVIES/` folder
|
||
|
|
- retail ships `MULTI8.XA` and `TALK1.XA`; this pre-alpha tree currently exposes only `MULTI8.XA`
|
||
|
|
|
||
|
|
## Executable Findings
|
||
|
|
|
||
|
|
### 1. Executable identity still says `No Remorse`
|
||
|
|
|
||
|
|
The strongest branding strings in `/psx/prealpha/SLUS_002.68` still point at the first game, not a visible `Crusader 2` identity.
|
||
|
|
|
||
|
|
Relevant strings:
|
||
|
|
|
||
|
|
- `80061d08`: `Crusader: No Remorse (save# `
|
||
|
|
- `80010944`: `This is no time to show Remorse! ... Are you sure you want to Quit?`
|
||
|
|
|
||
|
|
Negative checks from this pass:
|
||
|
|
|
||
|
|
- no recovered `Crusader II` string
|
||
|
|
- no recovered `Regret` string
|
||
|
|
- no recovered alternate save-title branding
|
||
|
|
|
||
|
|
Current safest read:
|
||
|
|
|
||
|
|
- at least at the executable/UI-string layer, this pre-alpha still looks branded as a No Remorse derivative rather than a separately named sequel build
|
||
|
|
|
||
|
|
### 2. The level loader is already essentially retail-shaped
|
||
|
|
|
||
|
|
Function `80038084` was renamed in Ghidra during this pass to `wdl_resource_bundle_load_by_index`.
|
||
|
|
|
||
|
|
Why the rename is justified:
|
||
|
|
|
||
|
|
- the function loads one of seven hardcoded level-path prefixes based on map-index thresholds
|
||
|
|
- it appends the decimal map index and the shared extension tail to form the final level path
|
||
|
|
- it also loads `\SPEC_A.WDL` during the same setup path
|
||
|
|
|
||
|
|
Direct evidence:
|
||
|
|
|
||
|
|
- `80010de0..80010e30` contains the contiguous prefix table:
|
||
|
|
- `\LSET1\L`
|
||
|
|
- `\LSET2\L`
|
||
|
|
- `\LSET3\L`
|
||
|
|
- `\LSET4\L`
|
||
|
|
- `\LSET5\L`
|
||
|
|
- `\LSET6\L`
|
||
|
|
- `\LSET7\L`
|
||
|
|
- `80010e34` contains `\SPEC_A.WDL`
|
||
|
|
- the decompiled threshold ladder in `wdl_resource_bundle_load_by_index` still splits on `9`, `0x13`, `0x1d`, `0x27`, `0x31`, and `0x3b`, which is the same practical `10/20/30/40/50/60` bucket logic previously closed in the retail PSX note
|
||
|
|
|
||
|
|
Important contrast with the disc tree:
|
||
|
|
|
||
|
|
- the code still expects the full seven-folder retail-style layout
|
||
|
|
- the current pre-alpha disc only ships `LSET1/L0..L2`
|
||
|
|
|
||
|
|
This is one of the strongest current signs that the executable pipeline was still aligned with a much larger planned content set than the media actually present in this build.
|
||
|
|
|
||
|
|
### 3. Mission and passcode scaffolding are still close to retail No Remorse
|
||
|
|
|
||
|
|
Recovered strings show that the pre-alpha executable still preserves the same visible mission/passcode UI scaffolding seen in the retail PSX work.
|
||
|
|
|
||
|
|
Relevant strings:
|
||
|
|
|
||
|
|
- `800101a4..80010340`: `Mission Briefing ^Mission 1` through `Mission Briefing ^Mission 15`
|
||
|
|
- `80060b70`: `Congratulations! You have completed your mission. The passcode for the next mission is:`
|
||
|
|
- `80060bd4`: the alternate completion message without the visible passcode line
|
||
|
|
- `80060b50`: `BCDFGHJKLMNPQRSTVWXZ0123456789`
|
||
|
|
|
||
|
|
Current read:
|
||
|
|
|
||
|
|
- the same `15` mission-facing text slots are still present
|
||
|
|
- the same consonant/digit passcode alphabet is still present
|
||
|
|
- this does **not** look like a radically different mission-shell rewrite
|
||
|
|
|
||
|
|
This pushes the current pre-alpha closer to `early/reduced No Remorse PSX branch` than to `already content-diverged sequel shell`.
|
||
|
|
|
||
|
|
### 4. Audio and movie state looks incomplete relative to both retail code and the current disc
|
||
|
|
|
||
|
|
The pre-alpha tree contains only one XA file:
|
||
|
|
|
||
|
|
- `AUDIO/MULTI8.XA`
|
||
|
|
|
||
|
|
But function `80045648` still contains the two-path XA switch logic:
|
||
|
|
|
||
|
|
- param `0` selects `\AUDIO\MULTI8.XA;1`
|
||
|
|
- nonzero selects `\AUDIO\TALK1.XA;1`
|
||
|
|
|
||
|
|
That function was annotated in Ghidra during this pass because the current unpacked disc does **not** contain `TALK1.XA`.
|
||
|
|
|
||
|
|
Interesting consequence:
|
||
|
|
|
||
|
|
- the executable still expects a second XA stream family that is absent from the current pre-alpha disc tree
|
||
|
|
|
||
|
|
Movie side status is even more reduced:
|
||
|
|
|
||
|
|
- `MOVIES/` exists but is empty
|
||
|
|
- no `.STR` files are present in the pre-alpha tree
|
||
|
|
- the main executable did **not** yield `FMV` or `MDEC` strings in this pass
|
||
|
|
- `FMV.BIN` still exists on disk, but the current main executable looks less movie-facing than retail at the string level
|
||
|
|
|
||
|
|
Current safest read:
|
||
|
|
|
||
|
|
- the audio/movie pipeline was not fully stripped from code expectations, but the shipped pre-alpha disc content is notably incomplete compared with retail
|
||
|
|
|
||
|
|
### 5. A split-executable `LoadExec` path still exists
|
||
|
|
|
||
|
|
Function `80046aac` was not renamed yet, but it was comment-annotated in Ghidra during this pass.
|
||
|
|
|
||
|
|
That helper selects one of three executable paths:
|
||
|
|
|
||
|
|
- `cdrom:\ENGINE.EXE;1`
|
||
|
|
- `cdrom:\MENU.EXE;1`
|
||
|
|
- `cdrom:\PSX.EXE;1`
|
||
|
|
|
||
|
|
Then it performs a PSX `LoadExec(...)` handoff after shutting down active systems.
|
||
|
|
|
||
|
|
Important contrast with the current pre-alpha disc tree:
|
||
|
|
|
||
|
|
- none of `ENGINE.EXE`, `MENU.EXE`, or `PSX.EXE` exist in the unpacked root
|
||
|
|
- only `SLUS_002.68` is present as the obvious boot executable
|
||
|
|
|
||
|
|
Current safest read:
|
||
|
|
|
||
|
|
- this build still preserves a real split-executable chainload helper from an earlier architecture or earlier content-layout plan
|
||
|
|
- the current unpacked disc no longer matches that design literally
|
||
|
|
|
||
|
|
I did **not** yet promote a stronger functional name for `80046aac` because the surviving call sites were not fully classified in this pass.
|
||
|
|
|
||
|
|
### 6. Content-name tables remain close to retail rather than showing obvious sequel-only replacements
|
||
|
|
|
||
|
|
The nearby item/ammo/gun tables are broadly familiar from the retail PSX note.
|
||
|
|
|
||
|
|
Recovered examples:
|
||
|
|
|
||
|
|
- ammo table still includes `JL-2 AMMO`, `AR-7 AMMO`, `GL-303 AMMO`, `RP-22 AMMO`, `SG-A1 AMMO`
|
||
|
|
- item table still includes `INHIBITOR`, `CREDITS`, `SCI PLANS`, `BLAST PAC`, `DET PAC`, `DATA LINK`, `LAND MINE`, `SPIDER BOMB`, `MEDICAL KIT`, `ENERGY CUBE`, `FUSION PAC`, `CHEMICAL BATTERY`, `FISSION BATTERY`, `FUSION BATTERY`, `GRAVITON GENERATOR`, `IONIC GENERATOR`, `PLASMA GENERATOR`
|
||
|
|
- gun table still includes `RP-16`, `RP-22`, `RP-32`, `SG-A1`, `AC-88`, `PA-31`, `EM-4`, `PL-1`, `UV-9`, `GL-303`, `AR-7`, `JL-2`, `JL-9`
|
||
|
|
|
||
|
|
Current read:
|
||
|
|
|
||
|
|
- the visible catalog tables are still basically in the retail No Remorse family
|
||
|
|
- this pass did **not** surface any obviously new `Crusader 2`-specific naming layer in the executable text
|
||
|
|
|
||
|
|
### 7. Developer-facing PSYQ graphics/debug strings are still present
|
||
|
|
|
||
|
|
This is not necessarily unique to the pre-alpha, but it is worth preserving because it may help later graphics-focused passes.
|
||
|
|
|
||
|
|
Recovered strings include:
|
||
|
|
|
||
|
|
- `ResetGraph(%d)...`
|
||
|
|
- `SetGraphReverse(%d)...`
|
||
|
|
- `SetGraphDebug:level:%d,type:%d reverse:%d`
|
||
|
|
- `LoadImage`
|
||
|
|
- `StoreImage`
|
||
|
|
- `MoveImage`
|
||
|
|
|
||
|
|
The recovered function `SetGraphDebug` simply stores the requested debug level and prints the diagnostic line when nonzero.
|
||
|
|
|
||
|
|
Current practical value:
|
||
|
|
|
||
|
|
- if later PSX rendering work needs debug/graphics control anchors, these strings and helpers are already easy to relocate in the pre-alpha database
|
||
|
|
|
||
|
|
## Interesting Build-Level Implications
|
||
|
|
|
||
|
|
The combined disc-plus-executable picture currently supports a fairly specific interpretation.
|
||
|
|
|
||
|
|
Most likely current model:
|
||
|
|
|
||
|
|
1. the pre-alpha executable is still largely a No Remorse-derived PSX codebase
|
||
|
|
2. the content payload is heavily reduced compared with retail
|
||
|
|
3. some earlier architectural leftovers survived into this build, especially the split-`LoadExec` helper and the missing-file `TALK1.XA` path
|
||
|
|
4. the loader still expects a much larger planned level inventory than the current disc actually ships
|
||
|
|
|
||
|
|
That does **not** yet prove there is no meaningful `Crusader 2` gameplay/content divergence hidden deeper in the WDL data or untyped runtime tables. It does mean the first clean static answer is: this build is still much closer to `unfinished No Remorse PSX branch with reduced assets` than to an already distinctively rebranded sequel executable.
|
||
|
|
|
||
|
|
## Ghidra Updates From This Pass
|
||
|
|
|
||
|
|
Applied in the live `/psx/prealpha/SLUS_002.68` database:
|
||
|
|
|
||
|
|
- renamed `80038084` to `wdl_resource_bundle_load_by_index`
|
||
|
|
- added a disassembly comment at `80046aac` documenting the `LoadExec` targets `MENU.EXE`, `ENGINE.EXE`, and `PSX.EXE`
|
||
|
|
- added a disassembly comment at `80045648` documenting the `MULTI8.XA` vs `TALK1.XA` selection and the current missing-file mismatch
|
||
|
|
|
||
|
|
## Highest-Value Next Steps
|
||
|
|
|
||
|
|
1. Decompile and classify the callers around `80046aac` so the surviving `MENU.EXE` / `ENGINE.EXE` / `PSX.EXE` path can be labeled as boot flow, frontend transition, or dead leftover with less ambiguity.
|
||
|
|
2. Compare the pre-alpha `L0.WDL`, `L1.WDL`, and `L2.WDL` structure against the retail `LSET` extractor results to see whether they are just reduced No Remorse maps or genuinely divergent content/layout revisions.
|
||
|
|
3. Diff the pre-alpha `SPEC_A.WDL` and `MENUS/*.WDL` files against the retail PSX note to see whether the menu/front-end assets changed more than the executable strings did.
|
||
|
|
4. Trace the mission-briefing and passcode consumers directly in `/psx/prealpha/SLUS_002.68` to see whether the pre-alpha still uses the same mission ordering and password-generation rules as retail.
|
||
|
|
5. Search the pre-alpha executable for early script/event-dispatch tables or type/resource tables that differ from the retail PSX resource-stream model, especially around the WDL loader outputs.
|
||
|
|
6. Inspect `FMV.BIN` separately in Ghidra or as raw data to determine whether it still contains movie-system code/data even though the current disc ships no `.STR` files.
|
||
|
|
7. Run a first asset-focused comparison pass on the three shipped pre-alpha maps in the public renderer/export tooling once the bundle/resource bindings are stable enough to avoid the earlier invalid direct-bundle hypothesis.
|