public byte[] DecompressLegacyCRI(byte[] input, int USize) { byte[] result;// = new byte[USize]; MemoryStream ms = new MemoryStream(input); EndianReader br = new EndianReader(ms, true); br.BaseStream.Seek(8, SeekOrigin.Begin); // Skip CRILAYLA int uncompressed_size = br.ReadInt32(); int uncompressed_header_offset = br.ReadInt32(); result = new byte[uncompressed_size + 0x100]; // do some error checks here......... // copy uncompressed 0x100 header to start of file Array.Copy(input, uncompressed_header_offset + 0x10, result, 0, 0x100); int input_end = input.Length - 0x100 - 1; int input_offset = input_end; int output_end = 0x100 + uncompressed_size - 1; byte bit_pool = 0; int bits_left = 0, bytes_output = 0; int[] vle_lens = new int[4] { 2, 3, 5, 8 }; while (bytes_output < uncompressed_size) { if (get_next_bits(input, ref input_offset, ref bit_pool, ref bits_left, 1) > 0) { int backreference_offset = output_end - bytes_output + get_next_bits(input, ref input_offset, ref bit_pool, ref bits_left, 13) + 3; int backreference_length = 3; int vle_level; for (vle_level = 0; vle_level < vle_lens.Length; vle_level++) { int this_level = get_next_bits(input, ref input_offset, ref bit_pool, ref bits_left, vle_lens[vle_level]); backreference_length += this_level; if (this_level != ((1 << vle_lens[vle_level]) - 1)) { break; } } if (vle_level == vle_lens.Length) { int this_level; do { this_level = get_next_bits(input, ref input_offset, ref bit_pool, ref bits_left, 8); backreference_length += this_level; } while (this_level == 255); } for (int i = 0; i < backreference_length; i++) { result[output_end - bytes_output] = result[backreference_offset--]; bytes_output++; } } else { // verbatim byte result[output_end - bytes_output] = (byte)get_next_bits(input, ref input_offset, ref bit_pool, ref bits_left, 8); bytes_output++; } } br.Close(); ms.Close(); return(result); }
/// <summary> /// </summary> /// <param name="reader"></param> /// <returns></returns> public bool ReadUtf(EndianReader reader) { var offset = reader.BaseStream.Position + 8; if (Tools.ReadCString(reader, 4) != "@UTF") { return(false); } Columns = new List <Column>(); TableSize = reader.ReadInt32(); RowsOffset = reader.ReadInt32(); StringsOffset = reader.ReadInt32(); DataOffset = reader.ReadInt32(); DataOffset += offset; RowsOffset += offset; StringsOffset += offset; TableName = reader.ReadInt32(); ColumnCount = reader.ReadInt16(); RowLength = reader.ReadInt16(); RowCount = reader.ReadInt32(); for (var position = 0; position < ColumnCount; position++) { var column = new Column { Flags = reader.ReadByte() }; if (column.Flags == 0) { reader.BaseStream.Seek(3, SeekOrigin.Current); column.Flags = reader.ReadByte(); } column.Name = Tools.ReadCString(reader, -1, reader.ReadInt32() + StringsOffset); Columns.Add(column); } Rows = new List <List <Row> >(); for (var rowIndex = 0; rowIndex < RowCount; rowIndex++) { reader.BaseStream.Seek(RowsOffset + rowIndex * RowLength, SeekOrigin.Begin); var entries = new List <Row>(); for (var columnIndex = 0; columnIndex < ColumnCount; columnIndex++) { var row = new Row(); switch ((ColumnFlags)Columns[columnIndex].Flags & ColumnFlags.StorageMask) { case ColumnFlags.StorageNone: entries.Add(row); continue; case ColumnFlags.StorageZero: entries.Add(row); continue; case ColumnFlags.StorageConstant: entries.Add(row); continue; } row.Position = reader.BaseStream.Position; row.Type = Columns[columnIndex].Flags & (int)ColumnFlags.TypeMask; switch (row.Type) { case 0x00: case 0x01: row.Uint8 = reader.ReadByte(); break; case 0x02: case 0x03: row.Uint16 = reader.ReadUInt16(); break; case 0x04: case 0x05: row.Uint32 = reader.ReadUInt32(); break; case 0x06: case 0x07: row.Uint64 = reader.ReadUInt64(); break; case 0x08: row.Ufloat = reader.ReadSingle(); break; case 0x0A: row.Str = Tools.ReadCString(reader, -1, reader.ReadInt32() + StringsOffset); break; case 0x0B: row.Position = reader.ReadInt32() + DataOffset; row.Data = Tools.GetData(reader, row.Position, reader.ReadInt32()); break; default: continue; } entries.Add(row); } Rows.Add(entries); } return(true); }
public bool ReadCPK(string sPath) { if (File.Exists(sPath)) { uint Files; ushort Align; EndianReader br = new EndianReader(File.OpenRead(sPath), true); MemoryStream ms; EndianReader utfr; if (tools.ReadCString(br, 4) != "CPK ") { br.Close(); return(false); } ReadUTFData(br); CPK_packet = utf_packet; FileEntry CPAK_entry = new FileEntry { FileName = "CPK_HDR", FileOffsetPos = br.BaseStream.Position + 0x10, FileSize = CPK_packet.Length, Encrypted = isUtfEncrypted, FileType = "CPK" }; FileTable.Add(CPAK_entry); ms = new MemoryStream(utf_packet); utfr = new EndianReader(ms, false); utf = new UTF(tools); if (!utf.ReadUTF(utfr)) { br.Close(); return(false); } utfr.Close(); ms.Close(); cpkdata = new Dictionary <string, object>(); try { for (int i = 0; i < utf.columns.Count; i++) { cpkdata.Add(utf.columns[i].name, utf.rows[0].rows[i].GetValue()); } } catch (Exception ex) { //MessageBox.Show(ex.ToString()); Console.WriteLine(ex.ToString()); } TocOffset = (ulong)GetColumsData2(utf, 0, "TocOffset", 3); long TocOffsetPos = GetColumnPostion(utf, 0, "TocOffset"); EtocOffset = (ulong)GetColumsData2(utf, 0, "EtocOffset", 3); long ETocOffsetPos = GetColumnPostion(utf, 0, "EtocOffset"); ItocOffset = (ulong)GetColumsData2(utf, 0, "ItocOffset", 3); long ITocOffsetPos = GetColumnPostion(utf, 0, "ItocOffset"); GtocOffset = (ulong)GetColumsData2(utf, 0, "GtocOffset", 3); long GTocOffsetPos = GetColumnPostion(utf, 0, "GtocOffset"); ContentOffset = (ulong)GetColumsData2(utf, 0, "ContentOffset", 3); long ContentOffsetPos = GetColumnPostion(utf, 0, "ContentOffset"); FileTable.Add(CreateFileEntry("CONTENT_OFFSET", ContentOffset, typeof(ulong), ContentOffsetPos, "CPK", "CONTENT", false)); Files = (uint)GetColumsData2(utf, 0, "Files", 2); Align = (ushort)GetColumsData2(utf, 0, "Align", 1); if (TocOffset != 0xFFFFFFFFFFFFFFFF) { FileEntry entry = CreateFileEntry("TOC_HDR", TocOffset, typeof(ulong), TocOffsetPos, "CPK", "HDR", false); FileTable.Add(entry); if (!ReadTOC(br, TocOffset, ContentOffset)) { return(false); } } if (EtocOffset != 0xFFFFFFFFFFFFFFFF) { FileEntry entry = CreateFileEntry("ETOC_HDR", EtocOffset, typeof(ulong), ETocOffsetPos, "CPK", "HDR", false); FileTable.Add(entry); if (!ReadETOC(br, EtocOffset)) { return(false); } } if (ItocOffset != 0xFFFFFFFFFFFFFFFF) { //FileEntry ITOC_entry = new FileEntry { // FileName = "ITOC_HDR", // FileOffset = ItocOffset, FileOffsetType = typeof(ulong), FileOffsetPos = ITocOffsetPos, // TOCName = "CPK", // FileType = "FILE", Encrypted = true, //}; FileEntry entry = CreateFileEntry("ITOC_HDR", ItocOffset, typeof(ulong), ITocOffsetPos, "CPK", "HDR", false); FileTable.Add(entry); if (!ReadITOC(br, ItocOffset, ContentOffset, Align)) { return(false); } } if (GtocOffset != 0xFFFFFFFFFFFFFFFF) { FileEntry entry = CreateFileEntry("GTOC_HDR", GtocOffset, typeof(ulong), GTocOffsetPos, "CPK", "HDR", false); FileTable.Add(entry); if (!ReadGTOC(br, GtocOffset)) { return(false); } } br.Close(); // at this point, we should have all needed file info //utf = null; files = null; return(true); } return(false); }
public bool ReadITOC(EndianReader br, ulong startoffset, ulong ContentOffset, ushort Align) { br.BaseStream.Seek((long)startoffset, SeekOrigin.Begin); if (tools.ReadCString(br, 4) != "ITOC") { br.Close(); return(false); } ReadUTFData(br); ITOC_packet = utf_packet; FileEntry itoc_entry = FileTable.Where(x => x.FileName.ToString() == "ITOC_HDR").Single(); itoc_entry.Encrypted = isUtfEncrypted; itoc_entry.FileSize = ITOC_packet.Length; MemoryStream ms = new MemoryStream(utf_packet); EndianReader utfr = new EndianReader(ms, false); files = new UTF(tools); if (!files.ReadUTF(utfr)) { br.Close(); return(false); } utfr.Close(); ms.Close(); //uint FilesL = (uint)GetColumnData(files, 0, "FilesL"); //uint FilesH = (uint)GetColumnData(files, 0, "FilesH"); byte[] DataL = (byte[])GetColumnData(files, 0, "DataL"); long DataLPos = GetColumnPostion(files, 0, "DataL"); byte[] DataH = (byte[])GetColumnData(files, 0, "DataH"); long DataHPos = GetColumnPostion(files, 0, "DataH"); //MemoryStream ms; //EndianReader ir; UTF utfDataL, utfDataH; Dictionary <int, uint> SizeTable, CSizeTable; Dictionary <int, long> SizePosTable, CSizePosTable; Dictionary <int, Type> SizeTypeTable, CSizeTypeTable; List <int> IDs = new List <int>(); SizeTable = new Dictionary <int, uint>(); SizePosTable = new Dictionary <int, long>(); SizeTypeTable = new Dictionary <int, Type>(); CSizeTable = new Dictionary <int, uint>(); CSizePosTable = new Dictionary <int, long>(); CSizeTypeTable = new Dictionary <int, Type>(); ushort ID, size1; uint size2; long pos; Type type; if (DataL != null) { ms = new MemoryStream(DataL); utfr = new EndianReader(ms, false); utfDataL = new UTF(tools); utfDataL.ReadUTF(utfr); for (int i = 0; i < utfDataL.num_rows; i++) { ID = (ushort)GetColumnData(utfDataL, i, "ID"); size1 = (ushort)GetColumnData(utfDataL, i, "FileSize"); SizeTable.Add((int)ID, (uint)size1); pos = GetColumnPostion(utfDataL, i, "FileSize"); SizePosTable.Add((int)ID, pos + DataLPos); type = GetColumnType(utfDataL, i, "FileSize"); SizeTypeTable.Add((int)ID, type); if ((GetColumnData(utfDataL, i, "ExtractSize")) != null) { size1 = (ushort)GetColumnData(utfDataL, i, "ExtractSize"); CSizeTable.Add((int)ID, (uint)size1); pos = GetColumnPostion(utfDataL, i, "ExtractSize"); CSizePosTable.Add((int)ID, pos + DataLPos); type = GetColumnType(utfDataL, i, "ExtractSize"); CSizeTypeTable.Add((int)ID, type); } IDs.Add(ID); } } if (DataH != null) { ms = new MemoryStream(DataH); utfr = new EndianReader(ms, false); utfDataH = new UTF(tools); utfDataH.ReadUTF(utfr); for (int i = 0; i < utfDataH.num_rows; i++) { ID = (ushort)GetColumnData(utfDataH, i, "ID"); size2 = (uint)GetColumnData(utfDataH, i, "FileSize"); SizeTable.Add(ID, size2); pos = GetColumnPostion(utfDataH, i, "FileSize"); SizePosTable.Add((int)ID, pos + DataHPos); type = GetColumnType(utfDataH, i, "FileSize"); SizeTypeTable.Add((int)ID, type); if ((GetColumnData(utfDataH, i, "ExtractSize")) != null) { size2 = (uint)GetColumnData(utfDataH, i, "ExtractSize"); CSizeTable.Add(ID, size2); pos = GetColumnPostion(utfDataH, i, "ExtractSize"); CSizePosTable.Add((int)ID, pos + DataHPos); type = GetColumnType(utfDataH, i, "ExtractSize"); CSizeTypeTable.Add((int)ID, type); } IDs.Add(ID); } } FileEntry temp; //int id = 0; uint value = 0, value2 = 0; ulong baseoffset = ContentOffset; // Seems ITOC can mix up the IDs..... but they'll alwaysy be in order... IDs = IDs.OrderBy(x => x).ToList(); for (int i = 0; i < IDs.Count; i++) { int id = IDs[i]; temp = new FileEntry(); SizeTable.TryGetValue(id, out value); CSizeTable.TryGetValue(id, out value2); temp.TOCName = "ITOC"; temp.DirName = null; temp.FileName = id.ToString() + ".bin"; temp.FileSize = value; temp.FileSizePos = SizePosTable[id]; temp.FileSizeType = SizeTypeTable[id]; if (CSizeTable.Count > 0 && CSizeTable.ContainsKey(id)) { temp.ExtractSize = value2; temp.ExtractSizePos = CSizePosTable[id]; temp.ExtractSizeType = CSizeTypeTable[id]; } temp.FileType = "FILE"; temp.FileOffset = baseoffset; temp.ID = id; temp.UserString = null; FileTable.Add(temp); if ((value % Align) > 0) { baseoffset += value + (Align - (value % Align)); } else { baseoffset += value; } //id++; } files = null; utfDataL = null; utfDataH = null; ms.Close(); utfr.Close(); return(true); }
public bool ReadUTF(EndianReader br) { long offset = br.BaseStream.Position; if (tools.ReadCString(br, 4) != "@UTF") { return(false); } table_size = br.ReadInt32(); rows_offset = br.ReadInt32(); strings_offset = br.ReadInt32(); data_offset = br.ReadInt32(); // CPK Header & UTF Header are ignored, so add 8 to each offset rows_offset += (offset + 8); strings_offset += (offset + 8); data_offset += (offset + 8); table_name = br.ReadInt32(); num_columns = br.ReadInt16(); row_length = br.ReadInt16(); num_rows = br.ReadInt32(); //read Columns columns = new List <COLUMN>(); COLUMN column; for (int i = 0; i < num_columns; i++) { column = new COLUMN(); column.flags = br.ReadByte(); if (column.flags == 0) { br.BaseStream.Seek(3, SeekOrigin.Current); column.flags = br.ReadByte(); } column.name = tools.ReadCString(br, -1, (long)(br.ReadInt32() + strings_offset)); columns.Add(column); } //read Rows rows = new List <ROWS>(); ROWS current_entry; ROW current_row; int storage_flag; for (int j = 0; j < num_rows; j++) { br.BaseStream.Seek(rows_offset + (j * row_length), SeekOrigin.Begin); current_entry = new ROWS(); for (int i = 0; i < num_columns; i++) { current_row = new ROW(); storage_flag = (columns[i].flags & (int)COLUMN_FLAGS.STORAGE_MASK); if (storage_flag == (int)COLUMN_FLAGS.STORAGE_NONE) // 0x00 { current_entry.rows.Add(current_row); continue; } if (storage_flag == (int)COLUMN_FLAGS.STORAGE_ZERO) // 0x10 { current_entry.rows.Add(current_row); continue; } if (storage_flag == (int)COLUMN_FLAGS.STORAGE_CONSTANT) // 0x30 { current_entry.rows.Add(current_row); continue; } // 0x50 current_row.type = columns[i].flags & (int)COLUMN_FLAGS.TYPE_MASK; current_row.position = br.BaseStream.Position; switch (current_row.type) { case 0: case 1: current_row.uint8 = br.ReadByte(); break; case 2: case 3: current_row.uint16 = br.ReadUInt16(); break; case 4: case 5: current_row.uint32 = br.ReadUInt32(); break; case 6: case 7: current_row.uint64 = br.ReadUInt64(); break; case 8: current_row.ufloat = br.ReadSingle(); break; case 0xA: current_row.str = tools.ReadCString(br, -1, br.ReadInt32() + strings_offset); break; case 0xB: long position = br.ReadInt32() + data_offset; current_row.position = position; current_row.data = tools.GetData(br, position, br.ReadInt32()); break; default: throw new NotImplementedException(); } current_entry.rows.Add(current_row); } rows.Add(current_entry); } return(true); }
public bool ReadTOC(EndianReader br, ulong TocOffset, ulong ContentOffset) { ulong fTocOffset = TocOffset; ulong add_offset = 0; if (fTocOffset > (ulong)0x800) { fTocOffset = (ulong)0x800; } if (ContentOffset < 0) { add_offset = fTocOffset; } else { if (TocOffset < 0) { add_offset = ContentOffset; } else { if (ContentOffset < fTocOffset) { add_offset = ContentOffset; } else { add_offset = fTocOffset; } } } br.BaseStream.Seek((long)TocOffset, SeekOrigin.Begin); if (tools.ReadCString(br, 4) != "TOC ") { br.Close(); return(false); } ReadUTFData(br); // Store unencrypted TOC TOC_packet = utf_packet; FileEntry toc_entry = FileTable.Where(x => x.FileName.ToString() == "TOC_HDR").Single(); toc_entry.Encrypted = isUtfEncrypted; toc_entry.FileSize = TOC_packet.Length; MemoryStream ms = new MemoryStream(utf_packet); EndianReader utfr = new EndianReader(ms, false); files = new UTF(tools); if (!files.ReadUTF(utfr)) { br.Close(); return(false); } utfr.Close(); ms.Close(); FileEntry temp; for (int i = 0; i < files.num_rows; i++) { temp = new FileEntry(); temp.TOCName = "TOC"; temp.DirName = GetColumnData(files, i, "DirName"); temp.FileName = GetColumnData(files, i, "FileName"); temp.FileSize = GetColumnData(files, i, "FileSize"); temp.FileSizePos = GetColumnPostion(files, i, "FileSize"); temp.FileSizeType = GetColumnType(files, i, "FileSize"); temp.ExtractSize = GetColumnData(files, i, "ExtractSize"); temp.ExtractSizePos = GetColumnPostion(files, i, "ExtractSize"); temp.ExtractSizeType = GetColumnType(files, i, "ExtractSize"); temp.FileOffset = ((ulong)GetColumnData(files, i, "FileOffset") + (ulong)add_offset); temp.FileOffsetPos = GetColumnPostion(files, i, "FileOffset"); temp.FileOffsetType = GetColumnType(files, i, "FileOffset"); temp.FileType = "FILE"; temp.Offset = add_offset; temp.ID = GetColumnData(files, i, "ID"); temp.UserString = GetColumnData(files, i, "UserString"); FileTable.Add(temp); } files = null; return(true); }
/// <summary> /// </summary> /// <param name="buffer"></param> /// <param name="length"></param> /// <returns></returns> public byte[] DecompressCrilayla(byte[] buffer, int length) { var stream = new MemoryStream(buffer); var endianReader = new EndianReader(stream, true); endianReader.BaseStream.Seek(8, SeekOrigin.Begin); var uncompressedLength = endianReader.ReadInt32(); var uncompressedHeaderOffset = endianReader.ReadInt32(); var result = new byte[uncompressedLength + 0x100]; Array.Copy(buffer, uncompressedHeaderOffset + 0x10, result, 0, 0x100); var bitsLeft = 0; var bytesOutput = 0; var inputEnd = buffer.Length - 0x100 - 1; var inputOffset = inputEnd; var outputEnd = 0x100 + uncompressedLength - 1; byte bitPool = 0; var vleLens = new[] { 2, 3, 5, 8 }; while (bytesOutput < uncompressedLength) { if (RetrieveNextBits(buffer, ref inputOffset, ref bitPool, ref bitsLeft, 1) > 0) { var backreferenceOffset = outputEnd - bytesOutput + RetrieveNextBits(buffer, ref inputOffset, ref bitPool, ref bitsLeft, 13) + 3; var backreferenceLength = 3; int vleLevel; for (vleLevel = 0; vleLevel < vleLens.Length; vleLevel++) { int thisLevel = RetrieveNextBits(buffer, ref inputOffset, ref bitPool, ref bitsLeft, vleLens[vleLevel]); backreferenceLength += thisLevel; if (thisLevel != (1 << vleLens[vleLevel]) - 1) { break; } } if (vleLevel == vleLens.Length) { int thisLevel; do { thisLevel = RetrieveNextBits(buffer, ref inputOffset, ref bitPool, ref bitsLeft, 8); backreferenceLength += thisLevel; } while (thisLevel == 255); } for (var index = 0; index < backreferenceLength; index++) { result[outputEnd - bytesOutput] = result[backreferenceOffset--]; bytesOutput++; } } else { result[outputEnd - bytesOutput] = (byte)RetrieveNextBits(buffer, ref inputOffset, ref bitPool, ref bitsLeft, 8); bytesOutput++; } } endianReader.Close(); stream.Close(); return(result); }
/// <summary> /// </summary> /// <param name="cpkFilename"></param> public Cpk(string cpkFilename) { IsUtfEncrypted = false; if (!File.Exists(cpkFilename)) { throw new FileNotFoundException(cpkFilename); } var reader = new EndianReader(File.OpenRead(cpkFilename), true); if (Tools.ReadCString(reader, 4) != "CPK ") { reader.Close(); throw new Exception(); } Utf = new Utf(); ReadUtfData(reader); CpkPacket = UtfPacket; var cpakEntry = new FileEntry { FileType = "CPK", FileName = "CPK_HDR", Encrypted = IsUtfEncrypted, FileSize = CpkPacket.Length, FileOffsetPosition = reader.BaseStream.Position + 0x10 }; FileTable = new List <FileEntry> { cpakEntry }; using (var stream = new MemoryStream(UtfPacket)) using (var utfReader = new EndianReader(stream, false)) { if (!Utf.ReadUtf(utfReader)) { reader.Close(); throw new Exception(); } } CpkData = new Dictionary <string, object>(); for (var columnIndex = 0; columnIndex < Utf.Columns.Count; columnIndex++) { CpkData.Add(Utf.Columns[columnIndex].Name, Utf.Rows[0][columnIndex].GetValue()); } TocOffset = (ulong)GetColumsData2(Utf, 0, "tocOffset", 3); EtocOffset = (ulong)GetColumsData2(Utf, 0, "EtocOffset", 3); GtocOffset = (ulong)GetColumsData2(Utf, 0, "GtocOffset", 3); ItocOffset = (ulong)GetColumsData2(Utf, 0, "ItocOffset", 3); ContentOffset = (ulong)GetColumsData2(Utf, 0, "contentOffset", 3); var tocOffset = GetColumnPostion(Utf, 0, "tocOffset"); var eTocOffset = GetColumnPostion(Utf, 0, "EtocOffset"); var itocOffset = GetColumnPostion(Utf, 0, "ItocOffset"); var gtocOffset = GetColumnPostion(Utf, 0, "GtocOffset"); var contentOffset = GetColumnPostion(Utf, 0, "contentOffset"); FileTable.Add(CreateFileEntry("CONTENT_OFFSET", ContentOffset, typeof(ulong), contentOffset, "CPK", "CONTENT", false)); if (TocOffset != 0xFFFFFFFFFFFFFFFF) { FileTable.Add(CreateFileEntry("TOC_HDR", TocOffset, typeof(ulong), tocOffset, "CPK", "HDR", false)); ReadToc(reader, TocOffset, ContentOffset); } if (EtocOffset != 0xFFFFFFFFFFFFFFFF) { FileTable.Add(CreateFileEntry("ETOC_HDR", EtocOffset, typeof(ulong), eTocOffset, "CPK", "HDR", false)); ReadEtoc(reader, (long)EtocOffset); } if (ItocOffset != 0xFFFFFFFFFFFFFFFF) { FileTable.Add(CreateFileEntry("ITOC_HDR", ItocOffset, typeof(ulong), itocOffset, "CPK", "HDR", false)); ReadItoc(reader, ItocOffset, ContentOffset, (ushort)GetColumsData2(Utf, 0, "Align", 1)); } if (GtocOffset != 0xFFFFFFFFFFFFFFFF) { FileTable.Add(CreateFileEntry("GTOC_HDR", GtocOffset, typeof(ulong), gtocOffset, "CPK", "HDR", false)); ReadGtoc(reader, (long)GtocOffset); } reader.Close(); _files = null; }
/// <summary> /// </summary> /// <param name="reader"></param> /// <param name="startOffset"></param> /// <param name="contentOffset"></param> /// <param name="byteAlignment"></param> /// <returns></returns> public bool ReadItoc(EndianReader reader, ulong startOffset, ulong contentOffset, ushort byteAlignment) { reader.BaseStream.Seek((long)startOffset, SeekOrigin.Begin); if (Tools.ReadCString(reader, 4) != "ITOC") { reader.Close(); return(false); } _files = new Utf(); ReadUtfData(reader); ItocPacket = UtfPacket; var itocEntry = FileTable.Single(x => x.FileName.ToString() == "ITOC_HDR"); itocEntry.Encrypted = IsUtfEncrypted; itocEntry.FileSize = ItocPacket.Length; var stream = new MemoryStream(UtfPacket); var endianReader = new EndianReader(stream, false); if (!_files.ReadUtf(endianReader)) { reader.Close(); return(false); } endianReader.Close(); stream.Close(); var dataL = (byte[])GetColumnData(_files, 0, "DataL"); var dataLPosition = GetColumnPostion(_files, 0, "DataL"); var dataH = (byte[])GetColumnData(_files, 0, "DataH"); var dataHPos = GetColumnPostion(_files, 0, "DataH"); var identifiers = new List <int>(); var sizeTable = new Dictionary <int, uint>(); var sizePositionTable = new Dictionary <int, long>(); var sizeTypeTable = new Dictionary <int, Type>(); var cSizeTable = new Dictionary <int, uint>(); var cSizePosTable = new Dictionary <int, long>(); var cSizeTypeTable = new Dictionary <int, Type>(); if (dataL != null) { var utfDataL = new Utf(); using (var streamL = new MemoryStream(dataL)) using (var endianReaderL = new EndianReader(streamL, false)) { utfDataL.ReadUtf(endianReaderL); } for (var rowIndex = 0; rowIndex < utfDataL.RowCount; rowIndex++) { var identifier = (ushort)GetColumnData(utfDataL, rowIndex, "Id"); sizeTable.Add(identifier, (ushort)GetColumnData(utfDataL, rowIndex, "FileSize")); sizePositionTable.Add(identifier, GetColumnPostion(utfDataL, rowIndex, "FileSize") + dataLPosition); sizeTypeTable.Add(identifier, GetColumnType(utfDataL, rowIndex, "FileSize")); if (GetColumnData(utfDataL, rowIndex, "ExtractSize") != null) { cSizeTable.Add(identifier, (ushort)GetColumnData(utfDataL, rowIndex, "ExtractSize")); cSizePosTable.Add(identifier, GetColumnPostion(utfDataL, rowIndex, "ExtractSize") + dataLPosition); cSizeTypeTable.Add(identifier, GetColumnType(utfDataL, rowIndex, "ExtractSize")); } identifiers.Add(identifier); } } if (dataH != null) { var utfDataH = new Utf(); using (var streamH = new MemoryStream(dataH)) using (var endianReaderH = new EndianReader(streamH, false)) { utfDataH.ReadUtf(endianReaderH); } for (var rowIndex = 0; rowIndex < utfDataH.RowCount; rowIndex++) { var identifier = (ushort)GetColumnData(utfDataH, rowIndex, "Identifier"); sizeTable.Add(identifier, (uint)GetColumnData(utfDataH, rowIndex, "FileSize")); sizePositionTable.Add(identifier, GetColumnPostion(utfDataH, rowIndex, "FileSize") + dataHPos); sizeTypeTable.Add(identifier, GetColumnType(utfDataH, rowIndex, "FileSize")); if (GetColumnData(utfDataH, rowIndex, "ExtractSize") != null) { cSizeTable.Add(identifier, (uint)GetColumnData(utfDataH, rowIndex, "ExtractSize")); cSizePosTable.Add(identifier, GetColumnPostion(utfDataH, rowIndex, "ExtractSize") + dataHPos); cSizeTypeTable.Add(identifier, GetColumnType(utfDataH, rowIndex, "ExtractSize")); } identifiers.Add(identifier); } } var baseOffset = contentOffset; foreach (var id in identifiers.OrderBy(identifier => identifier)) { var fileEntry = new FileEntry(); sizeTable.TryGetValue(id, out var fileSize); cSizeTable.TryGetValue(id, out var extractSize); fileEntry.TocName = "ITOC"; fileEntry.DirectoryName = null; fileEntry.FileName = id.ToString("D4"); fileEntry.FileSize = fileSize; fileEntry.FileSizePosition = sizePositionTable[id]; fileEntry.FileSizeType = sizeTypeTable[id]; if (cSizeTable.Count > 0 && cSizeTable.ContainsKey(id)) { fileEntry.ExtractSize = extractSize; fileEntry.ExtractSizePosition = cSizePosTable[id]; fileEntry.ExtractSizeType = cSizeTypeTable[id]; } fileEntry.FileType = "FILE"; fileEntry.FileOffset = baseOffset; fileEntry.Identifier = id; fileEntry.UserString = null; FileTable.Add(fileEntry); if (fileSize % byteAlignment > 0) { baseOffset += fileSize + (byteAlignment - fileSize % byteAlignment); } else { baseOffset += fileSize; } } _files = null; stream.Close(); endianReader.Close(); return(true); }
/// <summary> /// </summary> /// <param name="reader"></param> /// <param name="tocOffset"></param> /// <param name="contentOffset"></param> /// <returns></returns> public bool ReadToc(EndianReader reader, ulong tocOffset, ulong contentOffset) { var addOffset = tocOffset; if (contentOffset < tocOffset) { addOffset = contentOffset; } reader.BaseStream.Seek((long)tocOffset, SeekOrigin.Begin); if (Tools.ReadCString(reader, 4) != "TOC ") { reader.Close(); return(false); } ReadUtfData(reader); TocPacket = UtfPacket; var tocEntry = FileTable.Single(entry => entry.FileName.ToString() == "TOC_HDR"); _files = new Utf(); tocEntry.Encrypted = IsUtfEncrypted; tocEntry.FileSize = TocPacket.Length; using (var stream = new MemoryStream(UtfPacket)) using (var endianReader = new EndianReader(stream, false)) { if (_files.ReadUtf(endianReader) == false) { reader.Close(); return(false); } } for (var index = 0; index < _files.RowCount; index++) { FileTable.Add(new FileEntry { TocName = "TOC", FileType = "FILE", Offset = addOffset, DirectoryName = GetColumnData(_files, index, "DirName"), FileName = GetColumnData(_files, index, "FileName"), FileSize = GetColumnData(_files, index, "FileSize"), FileSizePosition = GetColumnPostion(_files, index, "FileSize"), FileSizeType = GetColumnType(_files, index, "FileSize"), ExtractSize = GetColumnData(_files, index, "ExtractSize"), ExtractSizePosition = GetColumnPostion(_files, index, "ExtractSize"), ExtractSizeType = GetColumnType(_files, index, "ExtractSize"), FileOffset = (ulong)GetColumnData(_files, index, "FileOffset") + addOffset, FileOffsetPosition = GetColumnPostion(_files, index, "FileOffset"), FileOffsetType = GetColumnType(_files, index, "FileOffset"), Identifier = GetColumnData(_files, index, "Identifier"), UserString = GetColumnData(_files, index, "UserString") }); } _files = null; return(true); }
public bool ReadCPK(string sPath) { if (File.Exists(sPath)) { uint Files; ushort Align; cName = sPath; EndianReader br = new EndianReader(File.OpenRead(sPath), true); MemoryStream ms; EndianReader utfr; if (Tools.ReadCString(br, 4) != "CPK ") { br.Close(); return(false); } ReadUTFData(br); CPK_packet = utf_packet; FileEntry CPAK_entry = new FileEntry { FileName = "CPK_HDR", FileOffsetPos = br.BaseStream.Position + 0x10, FileSize = CPK_packet.Length, Encrypted = isUtfEncrypted, FileType = "CPK" }; FileTable.Add(CPAK_entry); ms = new MemoryStream(utf_packet); utfr = new EndianReader(ms, false); utf = new UTF(); if (!utf.ReadUTF(utfr)) { br.Close(); return(false); } utfr.Close(); ms.Close(); TocOffset = (ulong)GetColumsData(utf, 0, "TocOffset", 3); long TocOffsetPos = GetColumnPostion(utf, 0, "TocOffset"); EtocOffset = (ulong)GetColumsData(utf, 0, "EtocOffset", 3); long ETocOffsetPos = GetColumnPostion(utf, 0, "EtocOffset"); ItocOffset = (ulong)GetColumsData(utf, 0, "ItocOffset", 3); long ITocOffsetPos = GetColumnPostion(utf, 0, "ItocOffset"); GtocOffset = (ulong)GetColumsData(utf, 0, "GtocOffset", 3); long GTocOffsetPos = GetColumnPostion(utf, 0, "GtocOffset"); ContentOffset = (ulong)GetColumsData(utf, 0, "ContentOffset", 3); long ContentOffsetPos = GetColumnPostion(utf, 0, "ContentOffset"); FileTable.Add(CreateFileEntry("CONTENT_OFFSET", ContentOffset, typeof(ulong), ContentOffsetPos, "CPK", "CONTENT", false)); Files = (uint)GetColumsData(utf, 0, "Files", 2); Align = (ushort)GetColumsData(utf, 0, "Align", 1); if (TocOffset != 0xFFFFFFFFFFFFFFFF) { FileEntry entry = CreateFileEntry("TOC_HDR", TocOffset, typeof(ulong), TocOffsetPos, "CPK", "HDR", false); FileTable.Add(entry); if (!ReadTOC(br, TocOffset, ContentOffset)) { return(false); } } if (EtocOffset != 0xFFFFFFFFFFFFFFFF) { FileEntry entry = CreateFileEntry("ETOC_HDR", EtocOffset, typeof(ulong), ETocOffsetPos, "CPK", "HDR", false); FileTable.Add(entry); if (!ReadETOC(br, EtocOffset)) { return(false); } } if (ItocOffset != 0xFFFFFFFFFFFFFFFF) { //FileEntry ITOC_entry = new FileEntry { // FileName = "ITOC_HDR", // FileOffset = ItocOffset, FileOffsetType = typeof(ulong), FileOffsetPos = ITocOffsetPos, // TOCName = "CPK", // FileType = "FILE", Encrypted = true, //}; FileEntry entry = CreateFileEntry("ITOC_HDR", ItocOffset, typeof(ulong), ITocOffsetPos, "CPK", "HDR", false); FileTable.Add(entry); if (!ReadITOC(br, ItocOffset, ContentOffset, Align)) { return(false); } } if (GtocOffset != 0xFFFFFFFFFFFFFFFF) { FileEntry entry = CreateFileEntry("GTOC_HDR", GtocOffset, typeof(ulong), GTocOffsetPos, "CPK", "HDR", false); FileTable.Add(entry); if (!ReadGTOC(br, GtocOffset)) { return(false); } } br.Close(); // at this point, we should have all needed file info //utf = null; files = null; return(true); } return(false); }