1
1
using System ;
2
- using System . Collections ;
3
2
using System . Collections . Generic ;
4
- using System . Linq ;
5
3
using System . Text ;
4
+ using UnityDataTools . FileSystem ;
5
+ using Force . Crc32 ;
6
6
7
- namespace UnityDataTools . FileSystem . TypeTreeReaders ;
7
+ namespace UnityDataTools . Analyzer ;
8
8
9
9
// This class is used to extract all the PPtrs in a serialized object. It executes a callback whenever a PPtr is found.
10
10
// It provides a string representing the property path of the property (e.g. "m_MyObject.m_MyArray[2].m_PPtrProperty").
11
- public class PPtrReader
11
+ public class PPtrAndCrcProcessor : IDisposable
12
12
{
13
- public delegate void CallbackDelegate ( long objectId , int fileId , long pathId , string propertyPath , string propertyType ) ;
13
+ public delegate int CallbackDelegate ( long objectId , int fileId , long pathId , string propertyPath , string propertyType ) ;
14
14
15
15
private SerializedFile m_SerializedFile ;
16
16
private UnityFileReader m_Reader ;
17
17
private long m_Offset ;
18
18
private long m_ObjectId ;
19
+ private uint m_Crc32 ;
20
+ private string m_Folder ;
19
21
private StringBuilder m_StringBuilder = new ( ) ;
22
+ private byte [ ] m_pptrBytes = new byte [ 4 ] ;
20
23
21
24
private CallbackDelegate m_Callback ;
22
25
23
- public PPtrReader ( SerializedFile serializedFile , UnityFileReader reader ,
26
+ private Dictionary < string , UnityFileReader > m_resourceReaders = new ( ) ;
27
+
28
+ public PPtrAndCrcProcessor ( SerializedFile serializedFile , UnityFileReader reader , string folder ,
24
29
CallbackDelegate callback )
25
30
{
26
31
m_SerializedFile = serializedFile ;
27
32
m_Reader = reader ;
33
+ m_Folder = folder ;
28
34
m_Callback = callback ;
29
35
}
36
+
37
+ public void Dispose ( )
38
+ {
39
+ foreach ( var r in m_resourceReaders . Values )
40
+ {
41
+ r . Dispose ( ) ;
42
+ }
43
+
44
+ m_resourceReaders . Clear ( ) ;
45
+ }
30
46
31
- public void Process ( long objectId , long offset , TypeTreeNode node )
47
+ private UnityFileReader GetResourceReader ( string filename )
48
+ {
49
+ var slashPos = filename . LastIndexOf ( '/' ) ;
50
+ if ( slashPos > 0 )
51
+ {
52
+ filename = filename . Remove ( 0 , slashPos + 1 ) ;
53
+ }
54
+
55
+ if ( ! m_resourceReaders . TryGetValue ( filename , out var reader ) )
56
+ {
57
+ reader = new UnityFileReader ( m_Folder + filename , 4 * 1024 * 1024 ) ;
58
+ m_resourceReaders [ filename ] = reader ;
59
+ }
60
+
61
+ return reader ;
62
+ }
63
+
64
+ public uint Process ( long objectId , long offset , TypeTreeNode node )
32
65
{
33
66
m_Offset = offset ;
34
67
m_ObjectId = objectId ;
68
+ m_Crc32 = 0 ;
35
69
36
70
foreach ( var child in node . Children )
37
71
{
38
72
m_StringBuilder . Clear ( ) ;
39
73
m_StringBuilder . Append ( child . Name ) ;
40
74
ProcessNode ( child ) ;
41
75
}
76
+
77
+ return m_Crc32 ;
42
78
}
43
79
44
80
private void ProcessNode ( TypeTreeNode node )
45
81
{
46
82
if ( node . IsBasicType )
47
83
{
84
+ m_Crc32 = m_Reader . ComputeCRC ( m_Offset , node . Size , m_Crc32 ) ;
48
85
m_Offset += node . Size ;
49
86
}
50
87
else if ( node . IsArray )
@@ -63,9 +100,57 @@ private void ProcessNode(TypeTreeNode node)
63
100
64
101
ExtractPPtr ( referencedType ) ;
65
102
}
103
+ else if ( node . Type == "StreamingInfo" )
104
+ {
105
+ if ( node . Children . Count != 3 )
106
+ throw new Exception ( "Invalid StreamingInfo" ) ;
107
+
108
+ var offset = node . Children [ 0 ] . Size == 4 ? m_Reader . ReadInt32 ( m_Offset ) : m_Reader . ReadInt64 ( m_Offset ) ;
109
+ m_Offset += node . Children [ 0 ] . Size ;
110
+
111
+ var size = m_Reader . ReadInt32 ( m_Offset ) ;
112
+ m_Offset += 4 ;
113
+
114
+ var stringSize = m_Reader . ReadInt32 ( m_Offset ) ;
115
+ var filename = m_Reader . ReadString ( m_Offset + 4 , stringSize ) ;
116
+ m_Offset += stringSize + 4 ;
117
+ m_Offset = ( m_Offset + 3 ) & ~ ( 3 ) ;
118
+
119
+ if ( size > 0 )
120
+ {
121
+ var resourceFile = GetResourceReader ( filename ) ;
122
+
123
+ m_Crc32 = resourceFile . ComputeCRC ( offset , size , m_Crc32 ) ;
124
+ }
125
+ }
126
+ else if ( node . Type == "StreamedResource" )
127
+ {
128
+ if ( node . Children . Count != 3 )
129
+ throw new Exception ( "Invalid StreamedResource" ) ;
130
+
131
+ var stringSize = m_Reader . ReadInt32 ( m_Offset ) ;
132
+ var filename = m_Reader . ReadString ( m_Offset + 4 , stringSize ) ;
133
+ m_Offset += stringSize + 4 ;
134
+ m_Offset = ( m_Offset + 3 ) & ~ ( 3 ) ;
135
+
136
+ var offset = m_Reader . ReadInt64 ( m_Offset ) ;
137
+ m_Offset += 8 ;
138
+
139
+ var size = ( int ) m_Reader . ReadInt64 ( m_Offset ) ;
140
+ m_Offset += 8 ;
141
+
142
+ if ( size > 0 )
143
+ {
144
+ var resourceFile = GetResourceReader ( filename ) ;
145
+
146
+ m_Crc32 = resourceFile . ComputeCRC ( offset , size , m_Crc32 ) ;
147
+ }
148
+ }
66
149
else if ( node . CSharpType == typeof ( string ) )
67
150
{
151
+ var prevOffset = m_Offset ;
68
152
m_Offset += m_Reader . ReadInt32 ( m_Offset ) + 4 ;
153
+ m_Crc32 = m_Reader . ComputeCRC ( prevOffset , ( int ) ( m_Offset - prevOffset ) , m_Crc32 ) ;
69
154
}
70
155
else if ( node . IsManagedReferenceRegistry )
71
156
{
@@ -99,10 +184,12 @@ private void ProcessArray(TypeTreeNode node, bool isManagedReferenceRegistry = f
99
184
if ( dataNode . IsBasicType )
100
185
{
101
186
var arraySize = m_Reader . ReadInt32 ( m_Offset ) ;
187
+ m_Crc32 = m_Reader . ComputeCRC ( m_Offset , dataNode . Size * arraySize + 4 , m_Crc32 ) ;
102
188
m_Offset += dataNode . Size * arraySize + 4 ;
103
189
}
104
190
else
105
191
{
192
+ m_Crc32 = m_Reader . ComputeCRC ( m_Offset , 4 , m_Crc32 ) ;
106
193
var arraySize = m_Reader . ReadInt32 ( m_Offset ) ;
107
194
m_Offset += 4 ;
108
195
@@ -127,6 +214,7 @@ private void ProcessArray(TypeTreeNode node, bool isManagedReferenceRegistry = f
127
214
128
215
// First child is rid.
129
216
long rid = m_Reader . ReadInt64 ( m_Offset ) ;
217
+ m_Crc32 = m_Reader . ComputeCRC ( m_Offset , 8 , m_Crc32 ) ;
130
218
m_Offset += 8 ;
131
219
132
220
ProcessManagedReferenceData ( dataNode . Children [ 1 ] , dataNode . Children [ 2 ] , rid ) ;
@@ -142,6 +230,7 @@ private void ProcessManagedReferenceRegistry(TypeTreeNode node)
142
230
143
231
// First child is version number.
144
232
var version = m_Reader . ReadInt32 ( m_Offset ) ;
233
+ m_Crc32 = m_Reader . ComputeCRC ( m_Offset , node . Children [ 0 ] . Size , m_Crc32 ) ;
145
234
m_Offset += node . Children [ 0 ] . Size ;
146
235
147
236
if ( version == 1 )
@@ -187,16 +276,19 @@ bool ProcessManagedReferenceData(TypeTreeNode refTypeNode, TypeTreeNode referenc
187
276
throw new Exception ( "Invalid ReferencedManagedType" ) ;
188
277
189
278
var stringSize = m_Reader . ReadInt32 ( m_Offset ) ;
279
+ m_Crc32 = m_Reader . ComputeCRC ( m_Offset , ( int ) ( m_Offset + stringSize + 4 ) , m_Crc32 ) ;
190
280
var className = m_Reader . ReadString ( m_Offset + 4 , stringSize ) ;
191
281
m_Offset += stringSize + 4 ;
192
282
m_Offset = ( m_Offset + 3 ) & ~ ( 3 ) ;
193
283
194
284
stringSize = m_Reader . ReadInt32 ( m_Offset ) ;
285
+ m_Crc32 = m_Reader . ComputeCRC ( m_Offset , ( int ) ( m_Offset + stringSize + 4 ) , m_Crc32 ) ;
195
286
var namespaceName = m_Reader . ReadString ( m_Offset + 4 , stringSize ) ;
196
287
m_Offset += stringSize + 4 ;
197
288
m_Offset = ( m_Offset + 3 ) & ~ ( 3 ) ;
198
289
199
290
stringSize = m_Reader . ReadInt32 ( m_Offset ) ;
291
+ m_Crc32 = m_Reader . ComputeCRC ( m_Offset , ( int ) ( m_Offset + stringSize + 4 ) , m_Crc32 ) ;
200
292
var assemblyName = m_Reader . ReadString ( m_Offset + 4 , stringSize ) ;
201
293
m_Offset += stringSize + 4 ;
202
294
m_Offset = ( m_Offset + 3 ) & ~ ( 3 ) ;
@@ -229,7 +321,12 @@ private void ExtractPPtr(string referencedType)
229
321
230
322
if ( fileId != 0 || pathId != 0 )
231
323
{
232
- m_Callback ( m_ObjectId , fileId , pathId , m_StringBuilder . ToString ( ) , referencedType ) ;
324
+ var refId = m_Callback ( m_ObjectId , fileId , pathId , m_StringBuilder . ToString ( ) , referencedType ) ;
325
+ m_pptrBytes [ 0 ] = ( byte ) ( refId >> 24 ) ;
326
+ m_pptrBytes [ 1 ] = ( byte ) ( refId >> 16 ) ;
327
+ m_pptrBytes [ 2 ] = ( byte ) ( refId >> 8 ) ;
328
+ m_pptrBytes [ 3 ] = ( byte ) ( refId ) ;
329
+ m_Crc32 = Crc32Algorithm . Append ( m_Crc32 , m_pptrBytes ) ;
233
330
}
234
331
}
235
332
}
0 commit comments