//Reads a block from the dictionary and decompresses. private Stream GetDecompressedDataBlock(IDictionaryData dict, Block block, Stream stream) { using (var reader = new FileReader(stream, true)) { if (block.Offset > reader.BaseStream.Length || block.DecompressedSize == 0) { return(new MemoryStream()); } reader.SeekBegin(block.Offset); //Check the dictionary if the files are compressed if (dict.BlocksCompressed) { //Check the magic to see if it's zlib compression ushort Magic = reader.ReadUInt16(); bool IsZLIP = Magic == 0x9C78 || Magic == 0xDA78; reader.SeekBegin(block.Offset); if (IsZLIP) { return(new MemoryStream(STLibraryCompression.ZLIB.Decompress( reader.ReadBytes((int)block.CompressedSize)))); } else //Unknown compression so skip it. { return(new MemoryStream()); } } //File is decompressed so check if it's in the range of the current data file. else if (block.Offset + block.DecompressedSize <= reader.BaseStream.Length) { return(new SubStream(reader.BaseStream, block.Offset, block.DecompressedSize)); } } return(new MemoryStream()); }
public string GetReportByDictionaryMetadata( IDictionaryMetadata rightHeaderDictionaryMetadata, IDictionaryMetadata topHeaderDictionaryMetadata, IDictionaryData rightHeaderDictionary, IDictionaryData topHeaderDictionary) { var sb = new StringBuilder(); sb.Append("<table border=\"1\">"); var rightHeaderFirstRow = rightHeaderDictionary.Rows.First(); var topHeaderFirstRow = topHeaderDictionary.Rows.First(); // Displaying top header rows. for (int i = 0; i < topHeaderFirstRow.Items.Count; i++) { sb.Append("<tr>"); for (int j = 0; j < rightHeaderFirstRow.Items.Count; j++) { sb.Append($"<td></td>"); } foreach (DictionaryRow topRow in topHeaderDictionary.Rows) { sb.Append($"<td>{topRow.Items[i]}</td>"); } sb.Append("</tr>"); } var dataService = new DataService(); // Displaying right header rows and data. foreach (DictionaryRow rightHeaderRow in rightHeaderDictionary.Rows) { sb.Append("<tr>"); foreach (var item in rightHeaderRow.Items) { sb.Append($"<td>{item}</td>"); } foreach (DictionaryRow topHeaderRow in topHeaderDictionary.Rows) { sb.Append($"<td>"); // Getting data from IDataService. sb.Append(dataService.GetIntersectionData( rightHeaderDictionaryMetadata.Id, topHeaderDictionaryMetadata.Id, rightHeaderDictionary.Rows.IndexOf(rightHeaderRow) + 1, topHeaderDictionary.Rows.IndexOf(topHeaderRow) + 1 )); sb.Append($"</td>"); } sb.Append("</tr>"); } return(sb.ToString()); }
public static object Parse(Type t, object data, Action <object, object> onParseItem = null) { if (!typeof(IData).IsAssignableFrom(t)) { return(null); } Type instanceType = typeof(DictionaryData <>).MakeGenericType(t); IDictionaryData obj = (IDictionaryData)Activator.CreateInstance(instanceType); obj.ParseObject(data, onParseItem); return(obj); }
public void Load(Stream stream) { _stream = stream; using (var reader = new FileReader(stream, true)) { reader.SetByteOrder(true); reader.SeekBegin(12); if (reader.ReadUInt32() == 0x78340300) { Version = GameVersion.LM3; } } Tag = this; //Parse dictionary if (Version == GameVersion.LM3) { DictFile = new LM3.DICT_Parser(stream); } else { DictFile = new LM2.DICT_Parser(stream); } this.Label = FileInfo.FileName; DictFile.FilePath = FileInfo.FilePath; //Parse seperate data file string dataPath = FileInfo.FilePath.Replace(".dict", ".data"); if (File.Exists(dataPath)) { _dataStream = File.OpenRead(dataPath); DataFile = new DATA_Parser(_dataStream, Version, DictFile); var root = LoadChunkTabe(); Children.AddRange(root.Children); int index = 0; var subNode = new ObjectTreeNode("Data Entries"); AddChild(subNode); foreach (var child in DataFile.Table.DataEntries) { subNode.AddChild(ReadChunk(child)); } } }
public static Stream LoadDumpedBlocks(IDictionaryData dict, List <Block> blocks, Stream stream, int index) { var block = blocks[index]; var fileName = Path.GetFileNameWithoutExtension(dict.FilePath); var folderPath = Path.GetDirectoryName(dict.FilePath); var dir = Path.Combine(folderPath, fileName, "File_Data"); if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); } if (!File.Exists($"{dir}/{fileName}_{index}.lm3")) { GetDecompressedDataBlock(dict, block, stream).SaveToFile($"{dir}/{fileName}_{index}.lm3"); } return(new FileStream($"{dir}/{fileName}_{index}.lm3", FileMode.Open, FileAccess.Read)); }
public DATA_Parser(Stream stream, DICT.GameVersion version, IDictionaryData dict) { Version = version; Dictionary = dict; foreach (var block in dict.BlockList) { block.DataParser = this; uint size = dict.BlocksCompressed ? block.CompressedSize : block.DecompressedSize; //Some cases the block sizes are too big? if (block.Offset + size > stream.Length) { continue; } block.Dictionary = dict; block.CompressedData = new SubStream(stream, block.Offset, size); } var blocks = dict.BlockList.ToList(); Stream[] blockList = new Stream[100]; if (version == DICT.GameVersion.LM3) { blockList[0] = DataCompressionCache.LoadDumpedBlocks(dict, blocks, stream, 0); blockList[52] = DataCompressionCache.LoadDumpedBlocks(dict, blocks, stream, 52); blockList[53] = DataCompressionCache.LoadDumpedBlocks(dict, blocks, stream, 53); blockList[54] = DataCompressionCache.LoadDumpedBlocks(dict, blocks, stream, 54); blockList[55] = DataCompressionCache.LoadDumpedBlocks(dict, blocks, stream, 55); blockList[58] = DataCompressionCache.LoadDumpedBlocks(dict, blocks, stream, 58); blockList[63] = DataCompressionCache.LoadDumpedBlocks(dict, blocks, stream, 63); blockList[64] = DataCompressionCache.LoadDumpedBlocks(dict, blocks, stream, 64); blockList[65] = DataCompressionCache.LoadDumpedBlocks(dict, blocks, stream, 65); blockList[68] = DataCompressionCache.LoadDumpedBlocks(dict, blocks, stream, 68); blockList[69] = DataCompressionCache.LoadDumpedBlocks(dict, blocks, stream, 69); } else { blockList[0] = GetDecompressedDataBlock(dict, blocks[0], stream); blockList[2] = GetDecompressedDataBlock(dict, blocks[2], stream); blockList[3] = GetDecompressedDataBlock(dict, blocks[3], stream); } var table = new ChunkTable(blockList[0]); Table = table; for (int i = 0; i < table.Files.Count; i++) { var file = table.Files[i]; Stream fileTableBlock = null; Stream fileTableBlock2 = null; if (version == DICT.GameVersion.LM3) { fileTableBlock = blockList[52]; fileTableBlock2 = blockList[63]; } else { fileTableBlock = blockList[2]; fileTableBlock2 = blockList[2]; } if (file.ChunkType == ChunkFileType.Texture) { Files.Add(ParseFileHeaders(fileTableBlock2, file)); } else if (file.ChunkType == ChunkFileType.FileTable) { Files.Add(ParseFileHeaders(fileTableBlock, file)); } else if (file.ChunkType == ChunkFileType.Script) { Files.Add(ParseFileHeaders(fileTableBlock2, file)); } else if (file.ChunkType == ChunkFileType.ClothPhysics) { Files.Add(ParseFileHeaders(fileTableBlock2, file)); } else if (file.ChunkType == (ChunkFileType)0x6510) { Files.Add(ParseFileHeaders(fileTableBlock2, file)); } else { Files.Add(ParseFileHeaders(fileTableBlock, file)); } if (file.SubData.Count == 0) { if (version == DICT.GameVersion.LM3) { file.Data = blockList[53]; if (file.ChunkType == ChunkFileType.FileTable) { file.Data = blockList[58]; } if (file.ChunkType == (ChunkFileType)0x7200) { file.Data = blockList[54]; } if (file.ChunkType == (ChunkFileType)0xF000) { file.Data = blockList[69]; } if (file.ChunkType == (ChunkFileType)0x4300) { file.Data = blockList[53]; } if (file.ChunkType == ChunkFileType.MessageData) { file.Data = blockList[69]; } } else { file.Data = blockList[3]; } if (file.Data != null && file.Flags3 + file.Flags2 <= file.Data.Length) { file.Data = new SubStream(file.Data, file.Flags3, file.Flags2); } } } foreach (var entry in table.DataEntries) { if (version == DICT.GameVersion.LM3) { if (entry.ChunkType == ChunkDataType.TextureData) { entry.Data = blockList[65]; } if (ChunkBlockFlags.ContainsKey(entry.Flags)) { var blockType = ChunkBlockFlags[entry.Flags]; entry.Data = blockList[blockType]; entry.BlockIndex = blockType; } else { continue; } switch (entry.ChunkType) { case (ChunkDataType)0xA201: case (ChunkDataType)0xA202: case (ChunkDataType)0xA203: case (ChunkDataType)0xA204: case (ChunkDataType)0xA205: case (ChunkDataType)0xA206: case (ChunkDataType)0xA207: entry.Data = blockList[64]; break; } } else { if (entry.BlockIndex == 0) { entry.Data = blockList[2]; } if (entry.BlockIndex == 1) { entry.Data = blockList[3]; } } if (entry.ChunkOffset + entry.ChunkSize <= entry.Data.Length) { entry.Data = new SubStream(entry.Data, entry.ChunkOffset, entry.ChunkSize); } } }