internal override void UnserializeChunk(UndertaleReader reader) { Chunks.Clear(); uint startPos = reader.Position; // First, find the last chunk in the file because of padding changes // (also, calculate all present chunks while we're at it) reader.AllChunkNames = new List <string>(); string lastChunk = ""; while (reader.Position < reader.BaseStream.Length) { lastChunk = new string(reader.ReadChars(4)); reader.AllChunkNames.Add(lastChunk); uint length = reader.ReadUInt32(); reader.Position += length; } reader.LastChunkName = lastChunk; reader.Position = startPos; // Now, parse the chunks while (reader.Position < startPos + Length) { UndertaleChunk chunk = reader.ReadUndertaleChunk(); if (chunk != null) { if (Chunks.ContainsKey(chunk.Name)) { throw new IOException("Duplicate chunk " + chunk.Name); } Chunks.Add(chunk.Name, chunk); } } }
public static UndertaleChunk Unserialize(UndertaleReader reader) { string name = "(unknown)"; try { name = new string(reader.ReadChars(4)); uint length = reader.ReadUInt32(); // TODO: I can't think of a cleaner way to do this... Type type = Type.GetType(typeof(UndertaleChunk).FullName + name); if (type == null) { throw new IOException("Unknown chunk " + name + "!!!"); /*Debug.WriteLine("Unknown chunk " + name + "!!!"); * reader.Position = reader.Position + length; * return null;*/ } UndertaleChunk chunk = (UndertaleChunk)Activator.CreateInstance(type); Debug.Assert(chunk.Name == name); chunk.Length = length; Debug.WriteLine("Reading chunk " + chunk.Name); var lenReader = reader.EnsureLengthFromHere(chunk.Length); chunk.UnserializeChunk(reader); if (name != "FORM" && name != "AUDO") // TODO: needs a better way to detect last chunk { UndertaleGeneralInfo generalInfo = name == "GEN8" ? ((UndertaleChunkGEN8)chunk).Object : reader.undertaleData.GeneralInfo; // These versions introduced new padding // all chunks now start on 16-byte boundaries // (but the padding is included with length of previous chunk) if (generalInfo.Major >= 2 || (generalInfo.Major == 1 && generalInfo.Build >= 9999)) { while (reader.Position % 16 != 0) { if (reader.ReadByte() != 0) { throw new Exception("Chunk padding error"); } } } } lenReader.ToHere(); return(chunk); } catch (UndertaleSerializationException e) { throw new UndertaleSerializationException(e.Message + " in chunk " + name); } catch (Exception e) { throw new UndertaleSerializationException(e.Message + "\nat " + reader.Position.ToString("X8") + " while reading chunk " + name, e); } }
internal override void UnserializeChunk(UndertaleReader reader) { Chunks.Clear(); uint startPos = reader.Position; while (reader.Position < startPos + Length) { UndertaleChunk chunk = reader.ReadUndertaleChunk(); if (chunk != null) { if (Chunks.ContainsKey(chunk.Name)) { throw new IOException("Duplicate chunk " + chunk.Name); } Chunks.Add(chunk.Name, chunk); } } }