Crusader_Decomp/docs/startup-map-patch-file.md

6.6 KiB

Using map patch file. in retail CRUSADER.EXE

This note records the current evidence-backed read of the startup line:

Using map patch file.

Short version:

  • the line is printed during Init_Everything startup
  • it is gated by a file-existence check for static\fixed.dat
  • it does not mean the -u usecode override is active
  • it means the game found an alternate fixed-map archive and will prefer that archive for later fixed-map loading
  • current recovered behavior looks like replacement-preferred fixed-map source, not merge a few patched records into the base archive

Exact Startup Print Site

The live exported Ghidra C for Init_Everything at 1048:039b shows this sequence:

  1. LoadConfigFile()
  2. Init_CheckFreeDiskSpace()
  3. File_Exists(s_static_fixed_dat)
  4. if present, ConsolePrintf(..., 0x9cc, 0x78)
  5. print the generic loading/progress strings

The relevant string symbols in the live export are:

  • 1478:09bb = s_static\fixed.dat
  • 1478:09cc = s_Using_map_patch_file.
  • 1478:09e4 = s_Loading:_[
  • 1478:09ef = s__]
  • 1478:09fd = s_dot

So the startup line is not speculative or inferred from neighboring strings. The init code really does:

  • check whether static\fixed.dat exists
  • and print Using map patch file. only when that file is present

What The File Is

The nearby fixed-data loader path now closes this pretty tightly.

ItemCacheFixedDat_Init() is called later in startup from the same Init_Everything body. That wrapper immediately calls ItemCache_InitAndLoadFixedDat() at 10a8:163a.

ItemCache_InitAndLoadFixedDat() does all of the following:

  • initializes item data
  • loads the normal base fixed-map archive through FixedDat_LoadData() at 10b8:0616
  • checks again for static\fixed.dat
  • if present, loads that second archive into DAT_1478_1064
  • resets g_currentMapArray = 0xffff

FixedDat_LoadData() itself resolves the standard asset path from g_fixedDatFilenamePtr and opens the regular fixed.dat resource.

That means the printed line is specifically about an alternate fixed-map archive, not a config file, not a save file, and not a usecode package.

What It Does At Runtime

The strongest currently recovered consumer is the fixed-map load path in the same item-cache family.

In the exported Ghidra C, the map-load logic does this:

  • if DAT_1478_1064 == 0, use DAT_1478_1060 (the normal fixed.dat handle)
  • otherwise use DAT_1478_1064 (the static\fixed.dat handle)

That is stronger than a vague patch support claim. The current recovered shape is:

  • base fixed.dat is always loaded
  • static\fixed.dat is conditionally loaded when present
  • later fixed-map reads prefer the static\fixed.dat handle when it exists

Current safest interpretation:

  • the message means the game found an alternate fixed-map archive under STATIC\FIXED.DAT
  • subsequent fixed-object/map loading will use that archive as the active source

Merge Or Fallback Status

Current evidence does not show a merge path.

What is directly recovered:

  • the game keeps two archive handles: base DAT_1478_1060 and optional patch DAT_1478_1064
  • the main fixed-map load path chooses exactly one handle before reading the map entry
  • if DAT_1478_1064 is non-null, that chooser uses it instead of DAT_1478_1060
  • no currently recovered outer code does try patch, then fall back to base if missing
  • no currently recovered outer code reads both archives and concatenates item lists

So the strongest current read is:

  • static\fixed.dat is a replacement-preferred archive source
  • not a recovered additive overlay system

That means the current evidence does not support claims like:

  • missing map entries in static\fixed.dat are automatically read from base fixed.dat
  • items missing from the patch archive are filled from the base archive
  • the patch archive appends extra records onto the base archive at load time

Could there still be fallback hidden inside the archive object's internal methods? Possibly, but there is no evidence of that in the currently recovered call shape. The visible loader logic selects one archive handle up front and passes only that handle into the read methods.

Current safest practical conclusion:

  • if static\fixed.dat is present, the game behaves like it is loading maps from that archive instead of the base archive
  • using it to add a few extra things to the base one is not a recovered supported mode
  • using it as a full replacement archive is the behavior the current code most clearly supports

What It Probably Does Not Mean

Current evidence argues against a few common misreads.

It is not currently the -u startup override:

  • the retail -u lane targets the EUSECODE runtime root, documented separately in docs/usecode-startup-override.md
  • this startup print is in the fixed-map/archive lane instead

It is also not currently evidenced as a merge-style overlay:

  • the recovered map-load chooser selects one handle or the other
  • this consumer does not show check patch archive first, then fall back per-record to base

So the safest current wording is replacement-preferred alternate FIXED.DAT source, not per-entry patch merge.

Practical Meaning

When retail No Remorse prints Using map patch file. at startup, it means:

  • STATIC\FIXED.DAT was found
  • the game has enabled its alternate fixed-map archive lane
  • later fixed map/object loads will prefer that archive over the normal FIXED.DAT

In plain terms: the executable is telling you it found a replacement/patch copy of the world-map data archive and is going to load map content from that patched archive path.

Evidence Summary

  • 1048:039b Init_Everything checks File_Exists("static\\fixed.dat") and prints 1478:09cc only on success
  • 10a8:163a ItemCache_InitAndLoadFixedDat loads base fixed.dat plus optional static\\fixed.dat
  • 10b8:0616 FixedDat_LoadData resolves the standard fixed.dat path from g_fixedDatFilenamePtr
  • recovered fixed-map load logic prefers DAT_1478_1064 (static\\fixed.dat) over DAT_1478_1060 (base fixed.dat) when the optional archive is present

Ghidra Annotation Status

The live-session note to add in Ghidra is straightforward:

Init_Everything startup status print: if static\\fixed.dat exists, print "Using map patch file.". Later ItemCache_InitAndLoadFixedDat loads that archive into DAT_1478_1064, and the fixed-map load path prefers DAT_1478_1064 over the base fixed.dat handle DAT_1478_1060.

In this session the live comment could not be pushed automatically because the reachable MCP bridge endpoints for the open GUI session were unavailable and the local PyGhidra writer path is blocked by the project lock while Ghidra owns the project.