public Level5_Resource(byte[] data) { data = Decompress.Level5Decom(data); using (DataReader r = new DataReader(new System.IO.MemoryStream(data))) { var magic = new string(r.ReadChars(6)); if (magic != "CHRC00" && magic != "CHRN01") { throw new FormatException("RES file is corrupt"); } // ----------------------- var unknown0 = r.ReadInt16(); var stringTableOffset = r.ReadInt16() << 2; var unknown1 = r.ReadInt16(); var materialTableOffset = r.ReadInt16() << 2; var materialTableSectionCount = r.ReadInt16(); var resourceNodeOffsets = r.ReadInt16() << 2; var resourceNodeCount = r.ReadInt16(); r.Seek((uint)stringTableOffset); while (r.Position < r.BaseStream.Length) { string mname = r.ReadString(); if (mname == "") { break; } if (!ResourceNames.ContainsKey(CRC32.Crc32C(mname))) { ResourceNames.Add(CRC32.Crc32C(mname), mname); } } r.Seek((uint)materialTableOffset); for (int i = 0; i < materialTableSectionCount; i++) { var offset = r.ReadInt16() << 2; var count = r.ReadInt16(); var unknown = r.ReadInt16(); var size = r.ReadInt16(); if (unknown == 0x270F) { continue; } var temp = r.Position; for (int j = 0; j < count; j++) { r.Position = (uint)(offset + j * size); var key = r.ReadUInt32(); string resourceName = (ResourceNames.ContainsKey(key) ? ResourceNames[key] : key.ToString("X")); //Console.WriteLine(resourceName + " " + unknown.ToString("X") + " " + size.ToString("X")); if (unknown == 0xF0) { TextureNames.Add(resourceName); } if (unknown == 0x122) { Level5_Material mat = new Level5_Material(); mat.Name = resourceName; r.Skip(12); key = r.ReadUInt32(); resourceName = (ResourceNames.ContainsKey(key) ? ResourceNames[key] : key.ToString("X")); mat.TexName = resourceName; Console.WriteLine(resourceName + " " + unknown.ToString("X") + " " + size.ToString("X")); Materials.Add(mat); } } r.Seek(temp); } r.Seek((uint)resourceNodeOffsets); for (int i = 0; i < resourceNodeCount; i++) { var offset = r.ReadInt16() << 2; var count = r.ReadInt16(); var unknown = r.ReadInt16(); var size = r.ReadInt16(); if (unknown == 0x270F) { continue; } var temp = r.Position; r.Seek((uint)offset); for (int j = 0; j < count; j++) { var key = r.ReadUInt32(); //Console.WriteLine((ResourceNames.ContainsKey(key) ? ResourceNames[key] : key.ToString("X")) + " " + unknown.ToString("X") + " " + size.ToString("X")); r.Position += (uint)(size - 4); } r.Seek(temp); } } }
public void Open(FileItem File) { using (DataReader r = new DataReader(new MemoryStream(File.GetFileBinary()))) { if (!new string(r.ReadChars(4)).Equals("XPCK")) { throw new Exception("File header error"); } uint fileCount = (uint)(r.ReadUInt16() & 0xFFF); var fileInfoOffset = r.ReadUInt16() * 4; var fileTableOffset = r.ReadUInt16() * 4; var dataOffset = r.ReadUInt16() * 4; r.ReadUInt16(); var filenameTableSize = r.ReadUInt16() * 4; var hashToData = new Dictionary <uint, byte[]>(); r.Seek((uint)fileInfoOffset); for (int i = 0; i < fileCount; i++) { var nameCRC = r.ReadUInt32(); r.ReadInt16(); var offset = (uint)r.ReadUInt16(); var size = (uint)r.ReadUInt16(); var offsetExt = (uint)r.ReadByte(); var sizeExt = (uint)r.ReadByte(); offset |= offsetExt << 16; size |= sizeExt << 16; offset = (uint)(offset * 4 + dataOffset); var data = r.GetSection(offset, (int)size); //Decompress.CheckLevel5Zlib(data, out data); hashToData.Add(nameCRC, data); } byte[] nameTable = r.GetSection((uint)fileTableOffset, filenameTableSize); if (!Decompress.CheckLevel5Zlib(nameTable, out nameTable)) { nameTable = Decompress.lzss_Decompress(nameTable); } using (DataReader nt = new DataReader(new MemoryStream(nameTable))) { for (int i = 0; i < fileCount; i++) { var name = nt.ReadString(); if (hashToData.ContainsKey(CRC32.Crc32C(name))) { Files.Add(name, hashToData[CRC32.Crc32C(name)]); } else { Console.WriteLine("Couldn't find " + name + " " + CRC32.Crc32C(name).ToString("X")); } } } } }