public void Deserialize(Stream input) { var magic = input.ReadValueU32(Endian.Little); if (magic != 0x666D726D && // fmrm magic.Swap() != 0x666D726D) { throw new FormatException(); } var endian = magic == 0x666D726D ? Endian.Little : Endian.Big; var version = input.ReadValueU32(endian); if (version != 1) { throw new FormatException(); } this.Version = version; /*var maxKeyLength =*/ input.ReadValueS32(endian); var maxValueLength = input.ReadValueS32(endian); var stringTableSize = input.ReadValueU32(endian); var huffmanSize = input.ReadValueU32(endian); var indexSize = input.ReadValueU32(endian); var dataSize = input.ReadValueU32(endian); var strings = new List <KeyValuePair <uint, string> >(); using (var data = input.ReadToMemoryStream(stringTableSize)) { var localStringTableSize = data.ReadValueU32(endian); if (localStringTableSize != stringTableSize) { throw new FormatException(); } var count = data.ReadValueU32(endian); var offsets = new List <KeyValuePair <uint, uint> >(); for (uint i = 0; i < count; i++) { var hash = data.ReadValueU32(endian); var offset = data.ReadValueU32(endian); offsets.Add(new KeyValuePair <uint, uint>(hash, offset)); } foreach (var kv in offsets) { var hash = kv.Key; var offset = kv.Value; data.Seek(8 + offset, SeekOrigin.Begin); var length = data.ReadValueU16(endian); var text = data.ReadString(length, Encoding.UTF8); if (text.HashCrc32() != hash) { throw new InvalidOperationException(); } strings.Add(new KeyValuePair <uint, string>(hash, text)); } } Huffman.Pair[] huffmanTree; using (var data = input.ReadToMemoryStream(huffmanSize)) { var count = data.ReadValueU16(endian); huffmanTree = new Huffman.Pair[count]; for (ushort i = 0; i < count; i++) { var left = data.ReadValueS32(endian); var right = data.ReadValueS32(endian); huffmanTree[i] = new Huffman.Pair(left, right); } } using (var index = input.ReadToMemoryStream(indexSize)) { var totalBits = input.ReadValueS32(endian); var data = input.ReadBytes(dataSize); var bitArray = new BitArray(data) { Length = totalBits }; var files = new List <KeyValuePair <string, uint> >(); var fileCount = index.ReadValueU16(endian); for (ushort i = 0; i < fileCount; i++) { var nameIndex = index.ReadValueU16(endian); var name = strings[nameIndex].Value; var offset = index.ReadValueU32(endian); files.Add(new KeyValuePair <string, uint>(name, offset)); } foreach (var fileInfo in files.OrderBy(f => f.Key)) { var file = new Coalesced.File() { Name = fileInfo.Key }; index.Seek(fileInfo.Value, SeekOrigin.Begin); var sectionCount = index.ReadValueU16(endian); var sections = new List <KeyValuePair <string, uint> >(); for (ushort i = 0; i < sectionCount; i++) { var nameIndex = index.ReadValueU16(endian); var name = strings[nameIndex].Value; var offset = index.ReadValueU32(endian); sections.Add(new KeyValuePair <string, uint>(name, offset)); } foreach (var sectionInfo in sections.OrderBy(s => s.Key)) { var section = new Dictionary <string, List <string> >(); index.Seek(fileInfo.Value + sectionInfo.Value, SeekOrigin.Begin); var valueCount = index.ReadValueU16(endian); var values = new List <KeyValuePair <string, uint> >(); for (ushort i = 0; i < valueCount; i++) { var nameIndex = index.ReadValueU16(endian); var name = strings[nameIndex].Value; var offset = index.ReadValueU32(endian); values.Add(new KeyValuePair <string, uint>(name, offset)); } foreach (var valueInfo in values.OrderBy(v => v.Key)) { var value = new List <string>(); index.Seek(fileInfo.Value + sectionInfo.Value + valueInfo.Value, SeekOrigin.Begin); var itemCount = index.ReadValueU16(endian); for (ushort i = 0; i < itemCount; i++) { var offset = index.ReadValueS32(endian); var type = (offset & 0xE0000000) >> 29; if (type == 1) { value.Add(null); } else if (type == 2) { offset &= 0x1FFFFFFF; var text = Huffman.Decoder.Decode( huffmanTree, bitArray, offset, maxValueLength); value.Add(text); } /*else if (type == 0 || type == 3) * { * offset &= 0x1FFFFFFF; * var text = Huffman.Decoder.Decode( * huffmanTree, bitArray, offset, maxValueLength); * value.Add("<<wtf" + type.ToString() + ">>" + text); * }*/ else { throw new NotImplementedException(); } } section.Add(valueInfo.Key, value); } file.Sections.Add(sectionInfo.Key, section); } this.Files.Add(file); } } this.Endian = endian; }
public void Deserialize(Stream input) { var magic = input.ReadValueU32(Endian.Little); if (magic != 0x666D726D && // fmrm magic.Swap() != 0x666D726D) { throw new FormatException(); } var endian = magic == 0x666D726D ? Endian.Little : Endian.Big; var version = input.ReadValueU32(endian); if (version != 1) { throw new FormatException(); } this.Version = version; /*var maxKeyLength =*/ input.ReadValueS32(endian); var maxValueLength = input.ReadValueS32(endian); var stringTableSize = input.ReadValueU32(endian); var huffmanSize = input.ReadValueU32(endian); var indexSize = input.ReadValueU32(endian); var dataSize = input.ReadValueU32(endian); var strings = new List<KeyValuePair<uint, string>>(); using (var data = input.ReadToMemoryStream(stringTableSize)) { var localStringTableSize = data.ReadValueU32(endian); if (localStringTableSize != stringTableSize) { throw new FormatException(); } var count = data.ReadValueU32(endian); var offsets = new List<KeyValuePair<uint, uint>>(); for (uint i = 0; i < count; i++) { var hash = data.ReadValueU32(endian); var offset = data.ReadValueU32(endian); offsets.Add(new KeyValuePair<uint, uint>(hash, offset)); } foreach (var kv in offsets) { var hash = kv.Key; var offset = kv.Value; data.Seek(8 + offset, SeekOrigin.Begin); var length = data.ReadValueU16(endian); var text = data.ReadString(length, Encoding.UTF8); if (text.HashCrc32() != hash) { throw new InvalidOperationException(); } strings.Add(new KeyValuePair<uint, string>(hash, text)); } } Huffman.Pair[] huffmanTree; using (var data = input.ReadToMemoryStream(huffmanSize)) { var count = data.ReadValueU16(endian); huffmanTree = new Huffman.Pair[count]; for (ushort i = 0; i < count; i++) { var left = data.ReadValueS32(endian); var right = data.ReadValueS32(endian); huffmanTree[i] = new Huffman.Pair(left, right); } } using (var index = input.ReadToMemoryStream(indexSize)) { var totalBits = input.ReadValueS32(endian); var data = input.ReadBytes(dataSize); var bitArray = new BitArray(data) { Length = totalBits }; var files = new List<KeyValuePair<string, uint>>(); var fileCount = index.ReadValueU16(endian); for (ushort i = 0; i < fileCount; i++) { var nameIndex = index.ReadValueU16(endian); var name = strings[nameIndex].Value; var offset = index.ReadValueU32(endian); files.Add(new KeyValuePair<string, uint>(name, offset)); } foreach (var fileInfo in files.OrderBy(f => f.Key)) { var file = new Coalesced.File() { Name = fileInfo.Key }; index.Seek(fileInfo.Value, SeekOrigin.Begin); var sectionCount = index.ReadValueU16(endian); var sections = new List<KeyValuePair<string, uint>>(); for (ushort i = 0; i < sectionCount; i++) { var nameIndex = index.ReadValueU16(endian); var name = strings[nameIndex].Value; var offset = index.ReadValueU32(endian); sections.Add(new KeyValuePair<string, uint>(name, offset)); } foreach (var sectionInfo in sections.OrderBy(s => s.Key)) { var section = new Dictionary<string, List<Coalesced.Entry>>(); index.Seek(fileInfo.Value + sectionInfo.Value, SeekOrigin.Begin); var valueCount = index.ReadValueU16(endian); var values = new List<KeyValuePair<string, uint>>(); for (ushort i = 0; i < valueCount; i++) { var nameIndex = index.ReadValueU16(endian); var name = strings[nameIndex].Value; var offset = index.ReadValueU32(endian); values.Add(new KeyValuePair<string, uint>(name, offset)); } foreach (var valueInfo in values.OrderBy(v => v.Key)) { var value = new List<Coalesced.Entry>(); index.Seek(fileInfo.Value + sectionInfo.Value + valueInfo.Value, SeekOrigin.Begin); var itemCount = index.ReadValueU16(endian); for (ushort i = 0; i < itemCount; i++) { var offset = index.ReadValueS32(endian); var type = (offset & 0xE0000000) >> 29; if (type == 1) { value.Add(new Coalesced.Entry(1, null)); } else if (type == 0 || type == 2 || type == 3 || type == 4) { offset &= 0x1FFFFFFF; var text = Huffman.Decoder.Decode( huffmanTree, bitArray, offset, maxValueLength); value.Add(new Coalesced.Entry(2, text)); } else { throw new NotImplementedException(); } } section.Add(valueInfo.Key, value); } file.Sections.Add(sectionInfo.Key, section); } this.Files.Add(file); } } this.Endian = endian; }