Texture Modding in Custom Forges - Kamzik123/AnvilToolkit-Resources GitHub Wiki
This tutorial shows you how to put a texture mod into your own custom patch forge for Assassin's Creed Shadows or Black Flag Resynced (BFR), without repacking the game's huge original forges.
Two things trip people up here, and this page covers both:
-
Mip dependencies (RawAssets). In Shadows and BFR, the largest mips of a texture are not stored in the TextureMap. They sit in separate
.RawAssetfiles in the forge. If you don't remove those dependencies, you'd have to copy the RawAssets into your custom forge too. Part 1 shows how to get rid of them. -
Prefetch data. If you put a
.datawith a prefetch entry into your custom forge (a Material, TextureSet, Mesh, etc.), you need to copy that entry into your forge'sPrefetchingFileInfosfile. Part 2 shows how. A.datathat holds only a TextureMap never has an entry, so a pure texture swap skips this step.
Before you start: You need a custom patch forge. If you don't have one yet, follow Creating a New Patch Forge for Assassin's Creed Shadows or later first. With AnvilToolkit 1.3.7+ it's a single click (Game Explorer → right-click → New → Patch Forge).
This page doesn't cover image editing itself (replacing the image, pixel formats, etc.). For that, see the Texture Viewer page.
- How Shadows/BFR textures are stored
- Overview of the workflow
- Part 1: Remove the mip dependencies
- Part 2: Copy the prefetch data into your custom forge
- Part 3: Repack and test
- Common mistakes
A texture is made up of mips: the full-resolution image plus a chain of smaller and smaller copies (half size, quarter size, and so on). In older games the whole chain sits inside the TextureMap file. In Shadows and BFR it's split in two:
| Part | Where it lives | What it holds |
|---|---|---|
| TextureMap | Inside a .data file, e.g. RED_GEN_Bamboo_Blinds_01_DiffuseMap.data
|
The smaller mips, plus links (by ID) to the RawAssets below |
| RawAsset(s) | Loose files in the forge itself, not in any .data, e.g. 878D995BF6300000.RawAsset
|
The largest mips (up to 4), the ones that actually make the texture look sharp |
When you unpack a forge you'll see thousands of them next to the .data files (DataPC_boot_patch_02.forge alone has over 6,000):
DataPC_boot_patch_02.forge/
1005_-_RED_GEN_Bamboo_Blinds_01_DiffuseMap.data
1094_-_RED_GEN_LUT_DIFF_Paint_Red_02_DiffuseMap.data
...
26632_-_81A406BA37400000.RawAsset
26633_-_878D995BF5F00000.RawAsset
26634_-_878D995BF6300000.RawAsset
...
This is why the custom forge gets confusing. If you edit and save a texture normally, AnvilToolkit writes your new high-resolution mips back into those RawAsset files. Your custom forge would then need the edited RawAssets as well as the .data. That's more files to track, they're named only by a hex ID, and they're easy to forget. Leave them out and the game uses the original RawAssets, so your texture shows the old image up close or looks broken.
Removing the mip dependencies avoids all of that. It turns the texture into a standard, self-contained TextureMap with every mip stored inside it, so the .data is the only thing your custom forge needs.
1. Copy the texture's .data from the original forge into your custom forge, then unpack it
2. Open the TextureMap → load its RawAssets → Tools → Remove CompiledMip dependencies
3. Edit/replace the image → Save
4. Repack the .data
5. For any non-TextureMap .data in your forge (Material, TextureSet, Mesh, ...), copy its prefetch
entry from the original forge's PrefetchingFileInfos into your custom forge's PrefetchingFileInfos
6. Repack your custom forge → test in game
- Unpack the original forge that contains the texture you want to mod (right-click the
.forge→ Unpack). - Find the
.datathat contains the TextureMap. Texture data files are usually named after the texture, e.g.RED_GEN_Bamboo_Blinds_01_DiffuseMap.data. -
Copy that
.datainto your custom forge's folder (for exampleDataPC_boot_patch_03.forge). - In your custom forge, right-click the copied
.data→ Unpack.
Which forge do I copy from? If the same
.dataexists in more than one forge of the chain (e.g. in bothDataPC_boot.forgeandDataPC_boot_patch_01.forge), always take it from the highest-numbered patch. That's the version the game currently uses.
- Double-click the
.TextureMapinside the unpacked.data. The Texture Viewer opens. - The viewer needs the RawAssets to rebuild the full-resolution texture. It looks for them automatically in the current folder and the two folders above it. Your custom forge doesn't contain them, so it will ask you to select them.
- In the file dialog, browse to the original forge's unpacked folder (the one you copied the
.datafrom). The dialog's title lists the RawAsset IDs it needs, and the file-name box is already filled in with a matching filter. Select the requested.RawAssetfile(s) and confirm.
Tip: Do this every time. If you cancel the dialog, the texture can't be loaded. Don't just copy the RawAssets into your custom forge to make the prompt go away. The point of this tutorial is that they don't need to be there.
- Click the Tools button in the Texture Viewer.
- Choose Remove CompiledMip dependencies.
Because you loaded the RawAssets in Step 2, the viewer already holds the full mip chain, including the large mips that came from the RawAssets. This command drops the links to the RawAssets, so on the next save the whole chain goes into the TextureMap itself. Nothing gets written to any RawAsset.
Note: The
.datawill get bigger than the original, because it now carries the high-resolution mips that used to sit in the RawAssets. That's expected.
- Replace or edit the image as usual (Replace button, drag & drop, flip, etc.). See the Texture Viewer page for details. You can also do this before Step 3, the order doesn't matter as long as you remove the dependencies before you save.
- Click Save.
Repeat Steps 2-4 for every TextureMap in this .data you want to change.
Go back up to your custom forge folder, right-click the .data → Repack.
At this point your custom forge contains the edited .data and no RawAssets, which is exactly what you want.
Before the game loads a .data file, it checks a list of other files that .data depends on and loads those first. This is the prefetch data. In Shadows and BFR, the lists for all the .data files in a forge are stored together in one meta file in that forge, PrefetchingFileInfos:
DataPC_boot_patch_03.forge/
0_-_Body_Torso_Naoe.data ← your modded .data
1_-_PrefetchingManifest.PrefetchingManifest
2_-_DeletedFilesManifest.DeletedFilesManifest
3_-_PrefetchInfoOverrides.PrefetchInfoOverrides
4_-_PrefetchingFileInfos.PrefetchInfo ← the file you edit here
5_-_GlobalMetaFile.MetaFile
A new patch forge starts with an empty PrefetchingFileInfos. When you add a .data to it, the original prefetch entry for that .data is still in the original forge's PrefetchingFileInfos, and the game doesn't look there for your copy. You need to copy the entry over yourself. If you don't, the files your .data depends on aren't preloaded, and things can fail to load or crash.
Each .data that has prefetch data gets one PrefetchFileInfoObject. The Path on it is the .data's root file, so it contains the .data's name. Inside is the list of files to preload. A real example from DataPC_boot.forge, for Body_Torso_Naoe.data:
<PrefetchFileInfoObject ID="2159653212301" Path="DataPC_boot\Body_Torso_Naoe\Body_Torso_Naoe.Material">
<List Name="FilterTables" />
<List Name="PrefetchFileInfos">
<PrefetchInfo ID="2116211603279" Path="DataPC_boot\Skin_SssProfile_ACF\Skin_SssProfile_ACF.SssProfile">
<List Name="DataLayerFilterIndices" />
</PrefetchInfo>
<PrefetchInfo ID="2134380624537" Path="DataPC_boot\Head_Template_NormalMap\Head_Template_NormalMap.TextureMap">
<List Name="DataLayerFilterIndices" />
</PrefetchInfo>
<!-- ... more dependencies ... -->
</List>
</PrefetchFileInfoObject>TextureMaps never have an entry. A
.datathat holds only a TextureMap (like..._DiffuseMap.data) doesn't depend on anything, so it has no prefetch entry and there is nothing to copy. If your custom forge contains only TextureMap.datafiles, skip straight to Part 3.You need this part when your mod also includes other
.datafiles, for example a Material or TextureSet you edited to point at a new texture, or a Mesh. Those usually do have entries.
- In your custom forge, export
PrefetchInfoOverrides.PrefetchInfoOverridesto XML (double-click it, or right-click → Export). - Open the XML in a text editor. It can be very large (tens of MB), so use an editor that handles big files (Notepad++, VS Code, etc.).
- Search the XML for the name of your
.data, e.g.Body_Torso_Naoe. You want the<PrefetchFileInfoObjectline whosePathcontains that name, not a<PrefetchInfoline. A<PrefetchInfoline only means some other.datadepends on yours. - Select the whole block, from
<PrefetchFileInfoObject ...>down to its matching</PrefetchFileInfoObject>, and copy it.
Searching by ID instead: The
IDon the object is the ID of the.data's root file. If a name search finds several similar results, search for the exact ID instead (e.g.ID="2159653212301").
-
In your custom forge, export
PrefetchingFileInfos.PrefetchInfoto XML the same way. -
For a fresh patch forge, the list will be empty:
<PrefetchingFileInfos> <List Name="Objects" /> </PrefetchingFileInfos>
-
Turn the empty list into an open/close pair and paste your copied block(s) inside:
<PrefetchingFileInfos> <List Name="Objects"> <PrefetchFileInfoObject ID="2159653212301" Path="DataPC_boot\Body_Torso_Naoe\Body_Torso_Naoe.Material"> <List Name="FilterTables" /> <List Name="PrefetchFileInfos"> <!-- ... copied exactly as-is ... --> </List> </PrefetchFileInfoObject> </List> </PrefetchingFileInfos>
If the list already has entries (from earlier mods), just paste the new block next to them inside
<List Name="Objects">. -
Save the XML, then import it back into the
PrefetchingFileInfos.PrefetchInfofile (right-click → Import, and select your edited XML).
Repeat Steps 2-3 for every non-TextureMap .data you put in your custom forge.
Only edit
PrefetchingFileInfos. Don't edit your custom forge'sPrefetchInfoOverrides. It describes the forges below yours in the chain and must stay exactly as the New → Patch Forge command created it.
- Go up to the folder containing your custom forge and right-click it → Repack.
- Wait until the AnvilToolkit Console says the forge was written successfully.
- Launch the game and check your texture, both up close (where the large mips are used) and from a distance.
| Mistake | Result |
|---|---|
| Saved without removing the mip dependencies | The new large mips went into the RawAsset files, not the TextureMap. Your custom forge doesn't contain those RawAssets, so the game uses the originals and the texture looks unchanged (or wrong) up close. Re-open the texture, remove the dependencies, and save again. |
| Cancelled the RawAsset prompt | The texture can't be loaded. Point the dialog at the original forge's folder, where the RawAssets are. |
| Copied RawAssets into the custom forge "to be safe" | Not needed once the dependencies are removed. They just bloat your mod. |
Didn't copy the prefetch entry for a non-TextureMap .data
|
The files that .data depends on aren't preloaded. Things may fail to load or crash. |
Added your entries to PrefetchInfoOverrides too |
Not needed and shouldn't be done. Only PrefetchingFileInfos gets your entries. |
Copied a <PrefetchInfo> line instead of the <PrefetchFileInfoObject> block |
You copied a reference to your .data from someone else's entry, not your .data's own entry. Search again for the <PrefetchFileInfoObject line. |
Copied the .data or its prefetch entry from an older forge in the chain |
You could revert changes Ubisoft made in a later patch. Always take both from the highest-numbered patch that contains the .data. |