Skip to content

Commit a0f4fd7

Browse files
committed
Implement bundle03
1 parent 6c92742 commit a0f4fd7

File tree

6 files changed

+275
-53
lines changed

6 files changed

+275
-53
lines changed

AssetTools.NET/Standard/AssetTypeClass/AssetTypeInstance.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ public class AssetTypeInstance
44
{
55
public int baseFieldCount;
66
public AssetTypeValueField[] baseFields;
7-
public byte[] memoryToClear;
7+
88
public AssetTypeInstance(AssetTypeTemplateField[] baseFields, AssetsFileReader reader, long filePos)
99
{
1010
reader.bigEndian = false;
@@ -18,8 +18,11 @@ public AssetTypeInstance(AssetTypeTemplateField[] baseFields, AssetsFileReader r
1818
this.baseFields[i] = atvf;
1919
}
2020
}
21+
2122
public AssetTypeInstance(AssetTypeTemplateField baseField, AssetsFileReader reader, long filePos)
22-
: this(new[] { baseField }, reader, filePos) { }
23+
: this(new[] { baseField }, reader, filePos)
24+
{
25+
}
2326

2427
public static AssetTypeValueField GetDummyAssetTypeField()
2528
{

AssetTools.NET/Standard/AssetsBundleFileFormat/AssetsBundleEntry.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,19 @@ public class AssetsBundleEntry
55
public uint offset;
66
public uint length;
77
public string name;
8+
9+
public void Read(AssetsFileReader reader)
10+
{
11+
name = reader.ReadNullTerminated();
12+
offset = reader.ReadUInt32();
13+
length = reader.ReadUInt32();
14+
}
15+
16+
public void Write(AssetsFileWriter writer)
17+
{
18+
writer.WriteNullTerminated(name);
19+
writer.Write(offset);
20+
writer.Write(length);
21+
}
822
}
923
}

AssetTools.NET/Standard/AssetsBundleFileFormat/AssetsBundleFile.cs

Lines changed: 135 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -30,17 +30,33 @@ public bool Read(AssetsFileReader reader, bool allowCompressed = false)
3030
this.reader = reader;
3131
reader.ReadNullTerminated();
3232
uint version = reader.ReadUInt32();
33-
if (version == 6 || version == 7)
33+
switch (version)
3434
{
35-
reader.Position = 0;
36-
bundleHeader6 = new AssetBundleHeader06();
37-
bundleHeader6.Read(reader);
38-
if (bundleHeader6.fileVersion >= 7)
39-
{
40-
reader.Align16();
41-
}
42-
if (bundleHeader6.signature == "UnityFS")
43-
{
35+
case 3:
36+
reader.Position = 0;
37+
bundleHeader3 = new AssetBundleHeader03();
38+
bundleHeader3.Read(reader);
39+
if (bundleHeader3.signature != "UnityRaw")
40+
throw new NotImplementedException("Non UnityRaw bundles are not supported yet.");
41+
42+
if (bundleHeader3.blockList.Any(b => b.compressed != b.uncompressed))
43+
throw new NotImplementedException("Compressed UnityRaw bundles are not supported yet.");
44+
45+
assetsLists3 = new AssetsList();
46+
assetsLists3.Read(reader);
47+
return true;
48+
49+
case 6:
50+
case 7:
51+
reader.Position = 0;
52+
bundleHeader6 = new AssetBundleHeader06();
53+
bundleHeader6.Read(reader);
54+
if (bundleHeader6.fileVersion >= 7)
55+
reader.Align16();
56+
57+
if (bundleHeader6.signature != "UnityFS")
58+
throw new NotImplementedException("Non UnityFS bundles are not supported yet.");
59+
4460
bundleInf6 = new AssetBundleBlockAndDirectoryList06();
4561
if ((bundleHeader6.flags & 0x3F) != 0)
4662
{
@@ -59,23 +75,103 @@ public bool Read(AssetsFileReader reader, bool allowCompressed = false)
5975
bundleInf6.Read(bundleHeader6.GetBundleInfoOffset(), reader);
6076
return true;
6177
}
62-
}
63-
else
78+
79+
default:
80+
throw new Exception("AssetsBundleFile.Read : Unknown file version!");
81+
}
82+
}
83+
84+
public bool Write(AssetsFileWriter writer, List<BundleReplacer> replacers, ClassDatabaseFile typeMeta = null)
85+
{
86+
if (bundleHeader3 != null)
87+
return Write03(writer, replacers);
88+
89+
if (bundleHeader6 != null)
90+
return Write06(writer, replacers);
91+
92+
return false;
93+
}
94+
95+
private bool Write03(AssetsFileWriter writer, List<BundleReplacer> replacers)
96+
{
97+
AssetBundleHeader03 newBundleHeader3 = bundleHeader3.Clone();
98+
newBundleHeader3.blockList = new[] { new AssetsBundleOffsetPair() };
99+
newBundleHeader3.Write(writer);
100+
101+
newBundleHeader3.bundleDataOffs = (uint)writer.Position;
102+
103+
Dictionary<string, BundleReplacer> addingReplacers =
104+
replacers.Where(r => r.GetReplacementType() == BundleReplacementType.AddOrModify)
105+
.ToDictionary(r => r.GetOriginalEntryName());
106+
107+
List<AssetsBundleEntry> newEntries = new List<AssetsBundleEntry>();
108+
Dictionary<AssetsBundleEntry, AssetsBundleEntry> newEntryToOldEntry = new Dictionary<AssetsBundleEntry, AssetsBundleEntry>();
109+
Dictionary<AssetsBundleEntry, BundleReplacer> newEntryToReplacer = new Dictionary<AssetsBundleEntry, BundleReplacer>();
110+
foreach (AssetsBundleEntry entry in assetsLists3.entries)
111+
{
112+
addingReplacers.Remove(entry.name);
113+
114+
BundleReplacer replacer = replacers.FirstOrDefault(r => r.GetOriginalEntryName() == entry.name);
115+
if (replacer == null ||
116+
replacer.GetReplacementType() == BundleReplacementType.AddOrModify ||
117+
replacer.GetReplacementType() == BundleReplacementType.Rename)
64118
{
65-
new NotImplementedException("Non UnityFS bundles are not supported yet.");
119+
AssetsBundleEntry newEntry = new AssetsBundleEntry { name = replacer?.GetEntryName() ?? entry.name };
120+
newEntries.Add(newEntry);
121+
newEntryToOldEntry.Add(newEntry, entry);
122+
if (replacer != null && replacer.GetReplacementType() == BundleReplacementType.AddOrModify)
123+
newEntryToReplacer.Add(newEntry, replacer);
66124
}
67125
}
68-
else if (version == 3)
126+
127+
foreach (BundleReplacer replacer in addingReplacers.Values)
69128
{
70-
new NotImplementedException("Version 3 bundles are not supported yet.");
129+
AssetsBundleEntry newEntry = new AssetsBundleEntry { name = replacer.GetEntryName() };
130+
newEntries.Add(newEntry);
131+
newEntryToReplacer.Add(newEntry, replacer);
71132
}
72-
else
133+
134+
bundleHeader3.numberOfAssetsToDownload = (uint)newEntries.Count;
135+
136+
AssetsList newAssetsList = new AssetsList { entries = newEntries.ToArray() };
137+
newAssetsList.Write(writer);
138+
writer.Align16();
139+
140+
bundleHeader3.assetsListSize = (uint)writer.Position - bundleHeader3.bundleDataOffs;
141+
142+
foreach (AssetsBundleEntry newEntry in newEntries)
73143
{
74-
new Exception("AssetsBundleFile.Read : Unknown file version!");
144+
long newEntryPosition = writer.Position;
145+
newEntry.offset = (uint)(writer.Position - bundleHeader3.bundleDataOffs);
146+
147+
if (newEntryToReplacer.TryGetValue(newEntry, out BundleReplacer replacer))
148+
{
149+
replacer.Write(writer);
150+
}
151+
else
152+
{
153+
AssetsBundleEntry oldEntry = newEntryToOldEntry[newEntry];
154+
reader.Position = bundleHeader3.bundleDataOffs + oldEntry.offset;
155+
reader.BaseStream.CopyToCompat(writer.BaseStream, oldEntry.length);
156+
}
157+
158+
newEntry.length = (uint)(writer.Position - newEntryPosition);
75159
}
76-
return false;
160+
161+
newBundleHeader3.minimumStreamedBytes = (uint)writer.Position;
162+
newBundleHeader3.blockList[0].compressed = (uint)writer.Position - newBundleHeader3.bundleDataOffs;
163+
newBundleHeader3.blockList[0].uncompressed = (uint)writer.Position - newBundleHeader3.bundleDataOffs;
164+
newBundleHeader3.fileSize2 = (uint)writer.Position;
165+
166+
writer.Position = 0;
167+
newBundleHeader3.Write(writer);
168+
newAssetsList.Write(writer);
169+
170+
writer.Position = newBundleHeader3.fileSize2;
171+
return true;
77172
}
78-
public bool Write(AssetsFileWriter writer, List<BundleReplacer> replacers, ClassDatabaseFile typeMeta = null)
173+
174+
private bool Write06(AssetsFileWriter writer, List<BundleReplacer> replacers)
79175
{
80176
bundleHeader6.Write(writer);
81177

@@ -84,15 +180,15 @@ public bool Write(AssetsFileWriter writer, List<BundleReplacer> replacers, Class
84180
writer.Align16();
85181
}
86182

87-
AssetBundleBlockAndDirectoryList06 newBundleInf6 = new AssetBundleBlockAndDirectoryList06()
183+
AssetBundleBlockAndDirectoryList06 newBundleInf6 = new AssetBundleBlockAndDirectoryList06
88184
{
89185
checksumLow = 0,
90186
checksumHigh = 0
91187
};
92188
//I could map the assets to their blocks but I don't
93189
//have any more-than-1-block files to test on
94190
//this should work just fine as far as I know
95-
newBundleInf6.blockInf = new AssetBundleBlockInfo06[]
191+
newBundleInf6.blockInf = new[]
96192
{
97193
new AssetBundleBlockInfo06
98194
{
@@ -108,19 +204,14 @@ public bool Write(AssetsFileWriter writer, List<BundleReplacer> replacers, Class
108204
List<AssetBundleDirectoryInfo06> originalDirInfos = new List<AssetBundleDirectoryInfo06>();
109205
List<AssetBundleDirectoryInfo06> dirInfos = new List<AssetBundleDirectoryInfo06>();
110206
List<BundleReplacer> currentReplacers = replacers.ToList();
111-
//this is kind of useless at the moment but leaving it here
112-
//because if the AssetsFile size can be precalculated in the
113-
//future, we can use this to skip rewriting sizes
114-
long currentOffset = 0;
115207

116208
//write all original files, modify sizes if needed and skip those to be removed
117209
for (int i = 0; i < bundleInf6.directoryCount; i++)
118210
{
119211
AssetBundleDirectoryInfo06 info = bundleInf6.dirInf[i];
120212
originalDirInfos.Add(info);
121-
AssetBundleDirectoryInfo06 newInfo = new AssetBundleDirectoryInfo06()
213+
AssetBundleDirectoryInfo06 newInfo = new AssetBundleDirectoryInfo06
122214
{
123-
offset = currentOffset,
124215
decompressedSize = info.decompressedSize,
125216
flags = info.flags,
126217
name = info.name
@@ -131,19 +222,16 @@ public bool Write(AssetsFileWriter writer, List<BundleReplacer> replacers, Class
131222
currentReplacers.Remove(replacer);
132223
if (replacer.GetReplacementType() == BundleReplacementType.AddOrModify)
133224
{
134-
newInfo = new AssetBundleDirectoryInfo06()
225+
newInfo = new AssetBundleDirectoryInfo06
135226
{
136-
offset = currentOffset,
137-
decompressedSize = replacer.GetSize(),
138227
flags = info.flags,
139228
name = replacer.GetEntryName()
140229
};
141230
}
142231
else if (replacer.GetReplacementType() == BundleReplacementType.Rename)
143232
{
144-
newInfo = new AssetBundleDirectoryInfo06()
233+
newInfo = new AssetBundleDirectoryInfo06
145234
{
146-
offset = currentOffset,
147235
decompressedSize = info.decompressedSize,
148236
flags = info.flags,
149237
name = replacer.GetEntryName()
@@ -160,11 +248,6 @@ public bool Write(AssetsFileWriter writer, List<BundleReplacer> replacers, Class
160248
newToOriginalDirInfoLookup[newInfo] = info;
161249
}
162250

163-
if (newInfo.decompressedSize != -1)
164-
{
165-
currentOffset += newInfo.decompressedSize;
166-
}
167-
168251
dirInfos.Add(newInfo);
169252
}
170253

@@ -176,12 +259,9 @@ public bool Write(AssetsFileWriter writer, List<BundleReplacer> replacers, Class
176259
{
177260
AssetBundleDirectoryInfo06 info = new AssetBundleDirectoryInfo06()
178261
{
179-
offset = currentOffset,
180-
decompressedSize = replacer.GetSize(),
181262
flags = (uint)(replacer.HasSerializedData() ? 0x04 : 0x00),
182263
name = replacer.GetEntryName()
183264
};
184-
currentOffset += info.decompressedSize;
185265

186266
dirInfos.Add(info);
187267
}
@@ -595,12 +675,24 @@ public int NumFiles
595675

596676
public bool IsAssetsFile(int index)
597677
{
598-
GetFileRange(index, out long offset, out long length);
599-
return AssetsFile.IsAssetsFile(reader, offset, length);
678+
if (bundleHeader3 != null)
679+
return IsAssetsFile(assetsLists3.entries[index]);
680+
681+
if (bundleHeader6 != null)
682+
return IsAssetsFile(bundleInf6.dirInf[index]);
683+
684+
return false;
685+
}
686+
687+
[Obsolete]
688+
public bool IsAssetsFile(AssetsBundleEntry entry)
689+
{
690+
long offset = bundleHeader3.bundleDataOffs + entry.offset;
691+
return AssetsFile.IsAssetsFile(reader, offset, entry.length);
600692
}
601693

602694
[Obsolete]
603-
public bool IsAssetsFile(AssetsFileReader reader, AssetBundleDirectoryInfo06 entry)
695+
public bool IsAssetsFile(AssetBundleDirectoryInfo06 entry)
604696
{
605697
long offset = bundleHeader6.GetFileDataOffset() + entry.offset;
606698
return AssetsFile.IsAssetsFile(reader, offset, entry.decompressedSize);

0 commit comments

Comments
 (0)