public static StringTableContainer FromData(SaveState state) { int stringTableCount = state.ReadVariableLengthOffset(); var reader = state.Reader; var container = new StringTableContainer(); for (int i = 0; i < stringTableCount; i++) { int blockCount = reader.ReadInt32(); if (blockCount < 0) { return(null); } int blockSize = reader.ReadInt32(); if (blockSize < 0) { return(null); } if ((blockCount * blockSize) > reader.StreamRemainder() || ((blockSize - 1) & blockSize) != 0) { return(null); } var table = new Table() { BitShiftMask = BitOperations.TrailingZeroCount(blockSize), BlockCount = blockCount, BlockSize = blockSize, Data = new byte[blockCount][], }; for (int j = 0; j < table.BlockCount; j++) { table.Data[j] = reader.ReadBytesStrict(table.BlockSize); } // No clue what this is int unknownCount = reader.ReadInt32(); if (unknownCount < 0 || (unknownCount * 8) > reader.StreamRemainder()) { return(null); } table.UnknownData = reader.ReadBytesStrict(unknownCount * 8); // Insert container.Tables.Add(table); } return(container); }
private void ReadHeaderData() { Reader.BaseStream.Position = SaveDataOffset + SaveDataLength - 0x8; uint typeDataChunkOffset = Reader.ReadUInt32(); uint rawDataChunkOffset = Reader.ReadUInt32(); // String/GUID tables Reader.BaseStream.Position = SaveDataOffset + rawDataChunkOffset; { // UTF-8 strings StringPool = StringTableContainer.FromData(this); // UTF-16 strings WideStringPool = WideStringTableContainer.FromData(this); // GUIDs if (SaveVersion >= 26) { GUIDPool = GUIDTableContainer.FromData(this); } } // Serialized type information and object instances Reader.BaseStream.Position = SaveDataOffset + typeDataChunkOffset; { // Create basic objects that are immediately registered with the engine int objectInstanceTypeCount = ReadVariableLengthOffset(); LocalSaveObjects = new Dictionary <int, object>(); for (int i = 0; i < objectInstanceTypeCount; i++) { Type objectType = RTTI.GetTypeByName(ReadIndexedString()); int instanceCount = ReadVariableLengthOffset(); for (int j = 0; j < instanceCount; j++) { int objectId = ReadVariableLengthOffset(); LocalSaveObjects.Add(objectId, RTTI.CreateObjectInstance(objectType)); } } // Handles to game data objects int gameDataObjectCount = ReadVariableLengthOffset(); GameDataObjects = new Dictionary <int, BaseGGUUID>(); for (int i = 0; i < gameDataObjectCount; i++) { int objectId = ReadVariableLengthOffset(); var guid = new BaseGGUUID().FromData(Reader); GameDataObjects.Add(objectId, guid); } // RTTI/class member layouts RTTIContainer = RTTIMapContainer.FromData(this); // File prefetch int prefetchFileCount = ReadVariableLengthOffset(); PrefetchFilePaths = new List <string>(prefetchFileCount); for (int i = 0; i < prefetchFileCount; i++) { PrefetchFilePaths.Add(ReadIndexedString()); } } Reader.BaseStream.Position = SaveDataOffset; }