Raw File Patching

Patching any non-.uasset game file (e.g., databases) using script or TOML patches

Raw File Patching

Besides patching .uasset properties, automod can patch any other game file (a raw file) – e.g., a database such as PhoenixShipData.sqlite, a CSV, or a config file. The raw file is extracted from the game, patched, and repacked into the generated mod at its original in-pak path.

Patch file naming

The patch file’s name encodes the target raw file in-pak path, using $ in place of /. For example, to patch Phoenix/Content/SQLiteDB/PhoenixShipData.sqlite, create:

patches\Phoenix\<mod-name>\Phoenix$Content$SQLiteDB$PhoenixShipData.sqlite.sc

Supported patch file extensions: .toml, .patch, .sc, .js, .ts, .lua, .py. Note that .patch files (jd diff format) target .uasset files only; use .toml or a script extension for raw files.

Script patchlets

A raw script patch is a code snippet in any supported language (Scala, TypeScript, JavaScript, Python, or Lua) that receives the file bytes and returns the patched bytes. The input value v exposes:

  • v.orig – the original (extracted) file bytes
  • v.current – the current file bytes (i.e., after any previously merged patches)

The snippet must return a byte array (e.g., Array[Byte] in Scala, a Uint8Array in JavaScript/TypeScript, a bytearray in Python) or a string (encoded as UTF-8).

As an example, the following identity patch leaves the file unchanged:

v.orig

in a file named Phoenix$Content$SQLiteDB$PhoenixShipData.sqlite.sc. The result of the run:

Using cached ...\.cache\Phoenix\Content\SQLiteDB\PhoenixShipData.sqlite
Patching ...\.temp\Phoenix\Content\SQLiteDB\PhoenixShipData.sqlite by using Phoenix\raw-sqlite-test\Phoenix$Content$SQLiteDB$PhoenixShipData.sqlite.sc ...
... done patching ...
Converting to ...\.temp\raw-sqlite-test\pakChunk888-raw-sqlite-test_P.pak ...
Packed 1 files ...

TOML raw JSON patches

A .toml patch file whose base name ends with .json targets a raw JSON file instead of a .uasset. For example, a file named Foo$Bar.json.toml patches Foo/Bar.json using the same TOML property syntax as .uasset patches (with .@:/JSONPath support).

Repacking raw files

Raw files are packed into the mod at their in-pak path, so the mod container preserves the exact location the game expects. Zen games are packed as <mod-name>_P.utoc/.ucas/.pak by default. If a game reads the raw file through its legacy .pak system instead (e.g., Hogwarts Legacy database files, which live in the legacy .pak files next to the zen containers), generate a legacy .pak mod by passing the --pak option:

automod -g <game-id> --pak <mod-name>

This packs the mod as a legacy pakChunk888-<mod-name>_P.pak (using repak). Without --pak, raw files that are not found in the zen container are automatically extracted from the game’s legacy .pak files as a fallback; with --pak, extraction reads them from the legacy .pak files directly. Non-zen games always produce a legacy .pak and need no option.

Extracted raw files are cached under .cache, so subsequent runs reuse them instead of re-extracting.