-
Notifications
You must be signed in to change notification settings - Fork 10
Creating a New Patch Forge for Assassin's Creed Shadows or later
This tutorial shows you how to create a brand-new patch forge (e.g. DataPC_boot_patch_03.forge) for Assassin's Creed Shadows or any Anvil game released after Shadows that the game will load and boot without crashing. A new patch forge lets you mod boot data by adding a thin forge on top of the chain instead of repacking the existing multi-gigabyte patch forges.
The whole process is two file edits. The rest of the meta files are copied from the current top patch and left untouched.
Game compatibility: Written for and tested on Assassin's Creed Shadows after the Ubisoft update that expanded the
PrefetchInfoOverridesandDeletedFilesManifestformats. Toolkit used: AnvilToolkit 1.3.6. Not tested on other Anvil titles.
Why this tutorial exists: After that update, simply dropping in a new patch forge — even an empty one — crashes the game during boot, before the main menu, with no error message. The fix is one specific, non-obvious step (Step 3). Everything else is bookkeeping.
- Background: the boot patch chain
- The one rule that matters
- Overview: what you edit
- What you need before starting
- Step 1: Create the new forge and copy the meta files
- Step 2: Edit the DeletedFilesManifest
- Step 3: Edit the PrefetchInfoOverrides
- Step 4: Repack and test the empty shell
- Adding your actual mod content on top
- How it works (why Step 3 is required)
- Common mistakes and the crashes they cause
The boot data loads as a layered chain of forges, each patching the one below it:
DataPC_boot.forge (base)
└─ DataPC_boot_patch_01.forge
└─ DataPC_boot_patch_02.forge ← current "head" of the chain
└─ DataPC_boot_patch_03.forge ← the new forge you are creating
The head forge (the highest-numbered patch present) is special: the engine treats it as the authority for the cumulative view of the chain. When you add patch_03, it becomes the new head, and it inherits responsibility for describing the merged state below it. That responsibility is what Step 3 satisfies.
Throughout this tutorial:
-
Current head = the highest existing patch forge (here,
DataPC_boot_patch_02.forge). -
New patch = the forge you are creating (here,
DataPC_boot_patch_03.forge).
Adjust the numbers to your situation (if the highest existing patch is patch_05, your new one is patch_06 and its parent is patch_05).
When a new forge becomes the head of the boot patch chain, its
PrefetchInfoOverridesmust carry the prefetch graph forward. Concretely: copy the entirePrefetchingFileInfosobject list into a newPrefetchInfoOverridesset that targets the previous head as its parent.
If you skip this, the boot prefetch graph is starved and the game crashes during early boot (see Common mistakes). Everything else in this tutorial is just making a valid, correctly-named empty shell.
Copy 5 meta files from the current head patch, then edit only 2 of them.
| Meta file | Action |
|---|---|
DeletedFilesManifest |
Edit — add one new set (empty deletions) |
PrefetchInfoOverrides |
Edit — add one new set (carry the prefetch graph) |
PrefetchingFileInfos |
Copy as-is |
GlobalMetaFile (MetaFile) |
Copy as-is |
PrefetchingManifest |
Copy as-is (it is empty in every forge) |
-
AnvilToolkit 1.3.6 (or newer) that can unpack/repack AC Shadows
.forgefiles and round-trip the meta files to/from XML. - The current head patch forge unpacked (e.g.
DataPC_boot_patch_02.forge), so you can copy its meta files. - A text/XML editor. The
PrefetchInfoOverrides.xmlis large (tens of MB); use an editor that handles big files.
The meta files inside a boot patch forge, as AnvilToolkit exposes them:
PrefetchingManifest.PrefetchingManifest (43 bytes, empty in all forges)
DeletedFilesManifest.DeletedFilesManifest
PrefetchInfoOverrides.PrefetchInfoOverrides
PrefetchingFileInfos.PrefetchInfo
GlobalMetaFile.MetaFile
- Create your new forge folder in the extracted folder named for the next number in the chain — e.g.
DataPC_boot_patch_03.forge. - Copy these five meta files from the current head (
DataPC_boot_patch_02) into your new forge, unchanged:PrefetchingManifestDeletedFilesManifestPrefetchInfoOverridesPrefetchingFileInfosGlobalMetaFile
At this point your new patch is a byte-for-byte clone of the current head's metadata. You will make exactly two edits below.
Export the DeletedFilesManifest to XML by double clicking on it in the toolkit and open it. It contains a Version and a list of Sets, one per ancestor forge. Copied from patch_02, it currently has sets targeting patch_01 and boot:
<DeletedFilesManifest>
<Value Name="Version" Type="Int16">1</Value>
<List Name="Sets">
<DeletedFilesManifestSet>
<Value Name="ParentForgeName" Type="String">DataPC_boot_patch_01.forge</Value>
...
<List Name="DeletedFiles"> ... </List>
</DeletedFilesManifestSet>
<DeletedFilesManifestSet>
<Value Name="ParentForgeName" Type="String">DataPC_boot.forge</Value>
...
<List Name="DeletedFiles"> ... </List>
</DeletedFilesManifestSet>
</List>
</DeletedFilesManifest>Add one new set at the top of the Sets list, making sure to edit the ParentForgeName value to target the current head (patch_02) as its parent, with an empty DeletedFiles list (your new patch deletes nothing):
<List Name="Sets">
<DeletedFilesManifestSet>
<Value Name="ParentForgeName" Type="String">DataPC_boot_patch_02.forge</Value>
<List Name="DeletedFiles" />
</DeletedFilesManifestSet>
<!-- the existing patch_01 and boot sets stay below, unchanged -->Compile the XML, your new patch's DeletedFilesManifest now has three sets — the new empty patch_02 set you added, plus the inherited patch_01 and boot sets.
This is the step that makes the game boot. Export the PrefetchInfoOverrides to XML by double clicking on it in the toolkit and open it. Like the deleted-files manifest, it has a Version and a list of OverrideSets targeting ancestor forges.
Then, export and open the PrefetchingFileInfos file in another window. It looks like this:
<PrefetchingFileInfos>
<List Name="Objects">
<PrefetchFileInfoObject ID="..." Path="...">
<List Name="FilterTables" />
<List Name="PrefetchFileInfos"> ... </List>
</PrefetchFileInfoObject>
<!-- ... thousands of these ... -->
</List>
</PrefetchingFileInfos>In the PrefetchInfoOverrides, add one new PrefetchInfoOverrideSet at the top, targeting the current head (patch_02), and set its Objects list to a copy of the entire Objects list from PrefetchingFileInfos:
<List Name="OverrideSets">
<PrefetchInfoOverrideSet>
<Value Name="ParentForgeName" Type="String">DataPC_boot_patch_02.forge</Value>
<List Name="Objects">
<!-- PASTE the full contents of PrefetchingFileInfos > List Name="Objects" here -->
<PrefetchFileInfoObject ID="..." Path="...">
<List Name="FilterTables" />
<List Name="PrefetchFileInfos"> ... </List>
</PrefetchFileInfoObject>
<!-- ... all of them ... -->
</List>
</PrefetchInfoOverrideSet>
<!-- the existing patch_01 and boot override sets stay below, unchanged -->Compile the XML, your new PrefetchInfoOverrides has three sets — the new patch_02 set whose Objects equals the PrefetchingFileInfos objects, plus the inherited patch_01 and boot sets.
Sanity check: the number of
<PrefetchFileInfoObjectentries in your new override set must equal the number inPrefetchingFileInfos. If they differ, you pasted the wrong list or truncated it.
- Repack the
DataPC_boot_patch_03.forgefile with AnvilToolkit. - Launch the game.
Expected result: the game boots to the main menu normally. You now have a valid, empty patch forge — a shell that changes nothing but loads cleanly. This is your foundation.
If it crashes before the menu, jump to Common mistakes.
With the empty shell working, add your real content:
-
Add your
.dataresource(s) to the forge (your new/modified objects). -
Add each new object's prefetch entry to
PrefetchingFileInfos(itsPrefetchFileInfoObjectwith the dependency list), the same way any object declares its prefetch dependencies. -
Mirror those same new entries into the
patch_02PrefetchInfoOverridesset you created in Step 3 — i.e. keep the rule that the head set'sObjectsequals thePrefetchingFileInfosObjects. Since you just add your entries to both lists, they stay in sync. - If your patch removes a file that exists lower in the chain, list it in the
patch_02DeletedFilesManifestset (the one you left empty in Step 2). If you delete nothing, leave it empty.
The golden rule stays the same: whatever is in PrefetchingFileInfos must also be in the head (patch_02) PrefetchInfoOverrides set.
PrefetchingFileInfos describes the prefetch dependency graph for objects the forge is responsible for. PrefetchInfoOverrides re-expresses that graph relative to a parent forge, and the engine reads the head forge's overrides as the authoritative prefetch plan for boot.
When patch_02 was the head, its own PrefetchInfoOverrides (against patch_01 and boot) drove boot prefetch, and the game booted. The moment you add patch_03, it becomes the head — and if its overrides don't re-assert the graph relative to patch_02, the engine's boot prefetch comes up empty. Boot-time subsystems then fail to load in the right order and slightly later a graphics resource handle resolves to null. Both are just symptoms of the same starved prefetch. Copying PrefetchingFileInfos into the new head-relative override set restores the graph.
A single-parent DLC patch (e.g. a ..._dlc_sound_patch_01.forge) has an empty PrefetchInfoOverrides and does fine — which is misleading. That works because a shallow patch overrides nothing and doesn't sit at the head of a deep boot chain. Deep boot-chain patches have the opposite requirement. Don't copy the DLC pattern here.
| Mistake | Symptom |
|---|---|
Empty PrefetchInfoOverrides set (didn't do Step 3) |
Crash during boot, before menu. |
No set for the parent forge (didn't add the patch_02 set at all) |
Crash before game window even appears. |
Mismatched counts (PrefetchInfoOverrides head set ≠ PrefetchingFileInfos) |
Missing objects don't prefetch → null handles at various boot stages. Crash at any point in the game. |