/// <summary> /// </summary> /// <param name="reader"></param> /// <param name="offset"></param> /// <returns></returns> public bool ReadEtoc(EndianReader reader, long offset) { reader.BaseStream.Seek(offset, SeekOrigin.Begin); if (Tools.ReadCString(reader, 4) != "ETOC") { return(false); } ReadUtfData(reader); EtocPacket = UtfPacket; var etocEntry = FileTable.Single(x => x.FileName.ToString() == "ETOC_HDR"); etocEntry.Encrypted = IsUtfEncrypted; etocEntry.FileSize = EtocPacket.Length; using var stream = new MemoryStream(UtfPacket); using var endianReader = new EndianReader(stream, false); _files = new Utf(); if (_files.ReadUtf(endianReader) == false) { return(false); } var fileEntries = FileTable.Where(fileEntry => fileEntry.FileType == "FILE").ToList(); for (var entryIndex = 0; entryIndex < fileEntries.Count; entryIndex++) { FileTable[entryIndex].LocalDirectory = GetColumnData(_files, entryIndex, "LocalDir"); } return(true); }
/// <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="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="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); }