33using System . Collections . Generic ;
44using System . IO ;
55using UndertaleModLib . Models ;
6+ using static UndertaleModLib . UndertaleReader ;
67
78namespace UndertaleModLib
89{
@@ -62,23 +63,36 @@ public static UndertaleChunk Unserialize(UndertaleReader reader)
6263 string name = "(unknown)" ;
6364 try
6465 {
66+ // Read name and length
6567 name = reader . ReadChars ( 4 ) ;
6668 uint length = reader . ReadUInt32 ( ) ;
6769
68- UndertaleChunk chunk = reader . undertaleData . FORM . Chunks [ name ] ;
70+ // Find chunk instance, or create one if not already created (when errors occur during object counting)
71+ if ( ! reader . undertaleData . FORM . Chunks . TryGetValue ( name , out UndertaleChunk chunk ) )
72+ {
73+ if ( ! UndertaleChunkFORM . ChunkConstructors . TryGetValue ( name , out Func < UndertaleChunk > instantiator ) )
74+ {
75+ throw new IOException ( $ "Unknown chunk \" { name } \" ") ;
76+ }
77+ chunk = instantiator ( ) ;
78+ reader . undertaleData . FORM . Chunks [ name ] = chunk ;
79+ }
6980 Util . DebugUtil . Assert ( chunk . Name == name ,
7081 $ "Chunk name mismatch: expected \" { name } \" , got \" { chunk . Name } \" .") ;
7182 chunk . Length = length ;
7283
84+ // Read chunk contents
7385 reader . SubmitMessage ( "Reading chunk " + chunk . Name ) ;
74- var lenReader = reader . EnsureLengthFromHere ( chunk . Length ) ;
86+ EnsureLengthOperation lenReader = reader . EnsureLengthFromHere ( chunk . Length ) ;
7587 reader . CopyChunkToBuffer ( length ) ;
7688 chunk . UnserializeChunk ( reader ) ;
7789
90+ // Process padding
7891 reader . SwitchReaderType ( false ) ;
7992 if ( name != "FORM" && name != reader . LastChunkName )
8093 {
8194 UndertaleGeneralInfo generalInfo = name == "GEN8" ? ( ( UndertaleChunkGEN8 ) chunk ) . Object : reader . undertaleData . GeneralInfo ;
95+
8296 // These versions introduced new padding
8397 // all chunks now start on 16-byte boundaries
8498 // (but the padding is included with length of previous chunk)
@@ -101,6 +115,7 @@ public static UndertaleChunk Unserialize(UndertaleReader reader)
101115 }
102116 }
103117
118+ // Ensure full length was read
104119 lenReader . ToHere ( ) ;
105120
106121 return chunk ;
@@ -119,25 +134,27 @@ public static (uint, UndertaleChunk) CountChunkChildObjects(UndertaleReader read
119134 string name = "(unknown)" ;
120135 try
121136 {
137+ // Read name and length
122138 name = reader . ReadChars ( 4 ) ;
123139 uint length = reader . ReadUInt32 ( ) ;
124140
141+ // Create chunk instance
125142 if ( ! UndertaleChunkFORM . ChunkConstructors . TryGetValue ( name , out Func < UndertaleChunk > instantiator ) )
126143 {
127144 throw new IOException ( $ "Unknown chunk \" { name } \" ") ;
128145 }
129-
130146 UndertaleChunk chunk = instantiator ( ) ;
131147 Util . DebugUtil . Assert ( chunk . Name == name ,
132148 $ "Chunk name mismatch: expected \" { name } \" , got \" { chunk . Name } \" .") ;
133149 chunk . Length = length ;
134150
151+ // Count objects in chunk
135152 long chunkStart = reader . Position ;
136-
137153 reader . SubmitMessage ( "Counting objects of chunk " + chunk . Name ) ;
138154 reader . CopyChunkToBuffer ( length ) ;
139155 uint count = chunk . UnserializeObjectCount ( reader ) ;
140156
157+ // Advance beyond chunk length (parts of the chunk may have been skipped)
141158 reader . SwitchReaderType ( false ) ;
142159 reader . Position = chunkStart + chunk . Length ;
143160
0 commit comments