Crusader_Decomp/docs/versions/version-differences.md
2026-04-01 00:31:23 +02:00

7.8 KiB

Version Export Differences

2026-03-31 exporter check

  • Renderer config correction: the retail No Remorse and No Regret static folders now both use EUSECODE.FLX, not USECODE.FLX, and the map renderer config has been updated to match the files now present in STATIC/ and STATIC_REGRET/.
  • Mission-table correction: Remorse 1.01 also needed a version-specific mission-table override. Its executable does contain the same 17-entry base-map sequence as retail, but at file offset 0x0e16c6 rather than the retail location.

No Remorse JP

  • Status: supported in the map renderer. JP scene export works, and JP mission metadata now generates correctly from a verified live Ghidra table read.
  • Verified commands:
    • node src/build-cache.js remorse-jp
    • node src/export-static.js --game=remorse-jp --output=_tmp_export_remorse_jp
  • Implemented renderer support:
    • JP mission table is now supplied from a verified Ghidra live-table read at 0x0047b72c
    • extracted base-map sequence: 0, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 40
    • consumer path verified in FUN_00428e00, with the key table-read site at 0x00429056
  • Current renderer/export fix: if STATIC_JP/GAMEPAL.PAL is missing, the exporter now falls back to STATIC/GAMEPAL.PAL.
  • Important limitation: this is only a temporary compatibility fallback. The Japanese asset set does not currently include a visible GAMEPAL.PAL, and it still needs investigation whether the correct palette lives in another file such as PALETTE.DAT, one of the other .PAL assets, or an executable/resource path.
  • Asset/executable mismatch note: the Japanese static folder uses JUSECODE.FLX, but a Ghidra string pass over /ja/CRUSADER.EXE found eusecode.flx at 0x0047be90 and found no jusecode string at all. The string is consumed by startup_apply_u_override_if_present, which looks like a startup override hook for the usecode path rather than a JP-specific rename path.
  • Additional Ghidra note: the JP executable string pass found static\fixed.dat, fixed.dat, shapes.flx, glob.flx, fonts.flx, eusecode.flx, and dtable.flx, but no explicit .pal filename strings. GAMEPAL only surfaced as the source path string ".\\gamepal.c", so palette filename handling still needs more direct loader tracing.
  • Ghidra documentation added:
    • comment at 0x00466ebc for the JP startup usecode override path
    • comment at 0x0047b72c for the verified warp base-map table
    • comment at 0x00429056 for the table consumer path that adds -mapoff
  • Archive comparison note: FIXDEMO.DAT is in STATIC_JP, not STATIC_DEMO. It is byte-for-byte identical to the prefix of JP FIXED.DAT, but it is truncated: only the first two non-empty map payloads are readable, and the remaining 61 non-empty table entries run past EOF. That makes it look more like a cut-down/demo fragment than a complete alternate archive. It may still be worth exposing separately later for comparison, but it is not a full parallel map set.

No Remorse Demo

  • Status: supported in the map renderer. The detected demo map exports cleanly, and demo mission metadata now generates correctly.
  • Verified commands:
    • node src/build-cache.js remorse-demo 1
    • node src/export-static.js --game=remorse-demo --output=_tmp_export_remorse_demo
  • Implemented renderer support:
    • demo mission table now reads from STATIC_DEMO/CRUSADER.EXE at file offset 0x0e3a88
    • extraction is fixed-length (17 entries) instead of sentinel-bounded
    • exported demo mission metadata now resolves map 1 as the base map for mission 1
  • Important naming difference: demo usecode is stored as EUSECODE.FLX rather than plain USECODE.FLX.
  • Investigation note: STATIC_DEMO also contains USECODE.ZIP plus an extracted USECODEZIP/ folder with EUSECODE.FLX, OVERLOAD.DAT, UNKCOFF.DAT, and UNKDS.DAT. This needs a later provenance/content check to determine whether the zip is archival noise, patch material, or the authoritative demo usecode bundle.
  • Root cause and fix: the earlier garbage mission extraction came from using the retail Remorse file offset (0x0e4088) against the demo executable. The demo binary does still carry the same 17-entry base-map sequence, but at 0x0e3a88, and it does not expose the immediate retail-style double-zero terminator after those entries.
  • Ghidra string/xref pass on /demo/CRUSADER.EXE:
    • eusecode.flx is present at 1478:07aa and is consumed by FUN_1420_0cdf, a 16-bit startup routine with the same broad shape as the JP/retail -u override path. It force-writes the first character to 'e', resolves the full path, checks file existence, and only then swaps the usecode source.
    • gamepal.pal is present explicitly at 1478:07d9, unlike the JP executable. It is referenced from FUN_1028_0000, which looks like an early palette/static resource initialization path.
    • fixed.dat is present at 1478:075f and is referenced from FUN_10b8_0616, which resolves a path under the static directory before passing it into a loader helper.
    • nonfixed.dat is present at 1478:0769, but this pass did not recover any direct xrefs to the string yet, so it may be unused, late-bound, or referenced through a table path not exposed by the current MCP queries.
    • The demo executable also carries -demo, "Loading demo: [", and "Demo mode.\n\r" strings, which supports the idea that this build has a materially different startup/game-flow path from retail.
    • Added Ghidra comments at 1420:0cdf, 1028:0000, and 10b8:0616 to preserve those verified findings in the demo database.

Other follow-up

  • Demo renderer/export support is now working end-to-end.
  • JP renderer/export support is now working end-to-end.
  • No Regret demo renderer/export support is now working end-to-end.
  • The viewer now preserves map selection more intelligently across versions: equal-count variants within a family try to keep the same map ID, one-map builds auto-select their only map, and switching between the Remorse and Regret families falls back to the last remembered map for the target family.

No Regret Demo

  • Status: supported in the map renderer. Both detected demo maps export cleanly.
  • Verified commands:
    • node src/export-static.js --game=regret-demo --output=_tmp_export_regret_demo
    • node scripts/compare-family-export-data.js
  • Verified asset layout:
    • STATIC_REGRET_DEMO/FIXED.DAT exposes two non-empty maps: 1 and 2
    • STATIC_REGRET_DEMO/REGRET.EXE is a tiny MZ stub-like launcher (11,942 bytes)
    • STATIC_REGRET_DEMO/REGRET.DAT is the real payload-bearing image (988,372 bytes) and contains the expected fixed.dat, nonfixed.dat, eusecode.flx, gamepal.pal, and -demo strings
  • Mission-table support:
    • the renderer now reads the demo base-map table from REGRET.DAT, not REGRET.EXE
    • verified table location: absolute file offset 0x0e295c
    • extraction remains fixed-length at 17 entries, matching the other supported variants
  • Export blocker and fix:
    • the first Regret demo export failed because STATIC_REGRET_DEMO/SHAPES.FLX contains empty entries that retail Regret still has art for; shape 404 was the first hard failure
    • the renderer now supports per-entry SHAPES.FLX fallback through fallbackStaticDirs, so sparse demo shape archives can borrow only the missing retail shapes instead of replacing the whole archive
    • build fingerprinting was updated so these layered archive inputs participate in cache invalidation
  • Family comparison note:
    • retail Regret and Regret demo share only maps 1 and 2
    • both shared maps differ in the normalized exported scene payload; the demo versions have more fixed-source rows, more editor items, and more sprites than retail for those two maps
  • Follow-up report: cross-version export diffs now live in docs/versions/family-export-differences.md, generated from map_renderer/generated/version-differences/family-export-differences.{json,md}.