static void Main(string[] args) { Console.WriteLine("CriPakTools\n"); Console.WriteLine("Based off Falo's code relased on Xentax forums (see readme.txt), modded by Nanashi3 from FuwaNovels.\nInsertion code by EsperKnight\n\n"); if (args.Length == 0) { Console.WriteLine("CriPakTool Usage:\n"); Console.WriteLine("CriPakTool.exe IN_FILE - Displays all contained chunks.\n"); Console.WriteLine("CriPakTool.exe IN_FILE EXTRACT_ME - Extracts a file.\n"); Console.WriteLine("CriPakTool.exe IN_FILE ALL - Extracts all files.\n"); Console.WriteLine("CriPakTool.exe IN_FILE REPLACE_ME REPLACE_WITH [OUT_FILE] - Replaces REPLACE_ME with REPLACE_WITH. Optional output it as a new CPK file otherwise it's replaced.\n"); return; } string cpk_name = args[0]; CPK cpk = new CPK(new Tools()); cpk.ReadCPK(cpk_name); BinaryReader oldFile = new BinaryReader(File.OpenRead(cpk_name)); if (args.Length == 1) { List <FileEntry> entries = cpk.FileTable.OrderBy(x => x.FileOffset).ToList(); for (int i = 0; i < entries.Count; i++) { Console.WriteLine(((entries[i].DirName != null) ? entries[i].DirName + "/" : "") + entries[i].FileName); } } else if (args.Length == 2) { string extractMe = args[1]; List <FileEntry> entries = null; entries = (extractMe.ToUpper() == "ALL") ? cpk.FileTable.Where(x => x.FileType == "FILE").ToList() : cpk.FileTable.Where(x => ((x.DirName != null) ? x.DirName + "/" : "") + x.FileName.ToString().ToLower() == extractMe.ToLower()).ToList(); if (entries.Count == 0) { Console.WriteLine("Cannot find " + extractMe + "."); } for (int i = 0; i < entries.Count; i++) { if (!String.IsNullOrEmpty((string)entries[i].DirName)) { Directory.CreateDirectory(entries[i].DirName.ToString()); } oldFile.BaseStream.Seek((long)entries[i].FileOffset, SeekOrigin.Begin); string isComp = Encoding.ASCII.GetString(oldFile.ReadBytes(8)); oldFile.BaseStream.Seek((long)entries[i].FileOffset, SeekOrigin.Begin); byte[] chunk = oldFile.ReadBytes(Int32.Parse(entries[i].FileSize.ToString())); if (isComp == "CRILAYLA") { int size = Int32.Parse((entries[i].ExtractSize ?? entries[i].FileSize).ToString()); chunk = cpk.DecompressCRILAYLA(chunk, size); } Console.WriteLine("Extracting: " + ((entries[i].DirName != null) ? entries[i].DirName + "/" : "") + entries[i].FileName.ToString()); File.WriteAllBytes(((entries[i].DirName != null) ? entries[i].DirName + "/" : "") + entries[i].FileName.ToString(), chunk); } } else { if (args.Length < 3) { Console.WriteLine("Usage for insertion CriPakTools IN_CPK REPLACE_THIS REPLACE_WITH [OUT_CPK]"); return; } string ins_name = args[1]; string replace_with = args[2]; FileInfo fi = new FileInfo(cpk_name); string outputName = fi.FullName + ".tmp"; if (args.Length >= 4) { outputName = fi.DirectoryName + "\\" + args[3]; } BinaryWriter newCPK = new BinaryWriter(File.OpenWrite(outputName)); List <FileEntry> entries = cpk.FileTable.OrderBy(x => x.FileOffset).ToList(); for (int i = 0; i < entries.Count; i++) { if (entries[i].FileType != "CONTENT") { if (entries[i].FileType == "FILE") { // I'm too lazy to figure out how to update the ContextOffset position so this works :) if ((ulong)newCPK.BaseStream.Position < cpk.ContentOffset) { ulong padLength = cpk.ContentOffset - (ulong)newCPK.BaseStream.Position; for (ulong z = 0; z < padLength; z++) { newCPK.Write((byte)0); } } } if (entries[i].FileName.ToString() != ins_name) { oldFile.BaseStream.Seek((long)entries[i].FileOffset, SeekOrigin.Begin); entries[i].FileOffset = (ulong)newCPK.BaseStream.Position; cpk.UpdateFileEntry(entries[i]); byte[] chunk = oldFile.ReadBytes(Int32.Parse(entries[i].FileSize.ToString())); newCPK.Write(chunk); } else { byte[] newbie = File.ReadAllBytes(replace_with); entries[i].FileOffset = (ulong)newCPK.BaseStream.Position; entries[i].FileSize = Convert.ChangeType(newbie.Length, entries[i].FileSizeType); entries[i].ExtractSize = Convert.ChangeType(newbie.Length, entries[i].FileSizeType); cpk.UpdateFileEntry(entries[i]); newCPK.Write(newbie); } if ((newCPK.BaseStream.Position % 0x800) > 0) { long cur_pos = newCPK.BaseStream.Position; for (int j = 0; j < (0x800 - (cur_pos % 0x800)); j++) { newCPK.Write((byte)0); } } } else { // Content is special.... just update the position cpk.UpdateFileEntry(entries[i]); } } cpk.WriteCPK(newCPK); cpk.WriteITOC(newCPK); cpk.WriteTOC(newCPK); cpk.WriteETOC(newCPK); cpk.WriteGTOC(newCPK); newCPK.Close(); oldFile.Close(); if (args.Length < 4) { File.Delete(cpk_name); File.Move(outputName, cpk_name); File.Delete(outputName); } } }
static void Main(string[] args) { Console.WriteLine("CriPakTools\n"); Console.WriteLine("Based off Falo's code relased on Xentax forums (see readme.txt), modded by Nanashi3 from FuwaNovels.\nInsertion code by EsperKnight\n\n"); if (args.Length == 0) { Console.WriteLine("CriPakTool Usage:\n"); Console.WriteLine("CriPakTool.exe IN_FILE - Displays all contained chunks.\n"); Console.WriteLine("CriPakTool.exe IN_FILE EXTRACT_ME - Extracts a file.\n"); Console.WriteLine("CriPakTool.exe IN_FILE ALL - Extracts all files.\n"); Console.WriteLine("CriPakTool.exe IN_FILE REPLACE_ME REPLACE_WITH [OUT_FILE] - Replaces REPLACE_ME with REPLACE_WITH. Optional output it as a new CPK file otherwise it's replaced.\n"); return; } string cpk_name = args[0]; CPK cpk = new CPK(new Tools()); cpk.ReadCPK(cpk_name); BinaryReader oldFile = new BinaryReader(File.OpenRead(cpk_name)); if (args.Length == 1) { List<FileEntry> entries = cpk.FileTable.OrderBy(x => x.FileOffset).ToList(); for (int i = 0; i < entries.Count; i++) { Console.WriteLine(((entries[i].DirName != null) ? entries[i].DirName + "/" : "") + entries[i].FileName); } } else if (args.Length == 2) { string extractMe = args[1]; List<FileEntry> entries = null; entries = (extractMe.ToUpper() == "ALL") ? cpk.FileTable.Where(x => x.FileType == "FILE").ToList() : cpk.FileTable.Where(x => ((x.DirName != null) ? x.DirName + "/" : "") + x.FileName.ToString().ToLower() == extractMe.ToLower()).ToList(); if (entries.Count == 0) { Console.WriteLine("Cannot find " + extractMe + "."); } for (int i = 0; i < entries.Count; i++) { if (!String.IsNullOrEmpty((string)entries[i].DirName)) { Directory.CreateDirectory(entries[i].DirName.ToString()); } oldFile.BaseStream.Seek((long)entries[i].FileOffset, SeekOrigin.Begin); string isComp = Encoding.ASCII.GetString(oldFile.ReadBytes(8)); oldFile.BaseStream.Seek((long)entries[i].FileOffset, SeekOrigin.Begin); byte[] chunk = oldFile.ReadBytes(Int32.Parse(entries[i].FileSize.ToString())); if (isComp == "CRILAYLA") { int size = Int32.Parse((entries[i].ExtractSize ?? entries[i].FileSize).ToString()); chunk = cpk.DecompressCRILAYLA(chunk, size); } File.WriteAllBytes(((entries[i].DirName != null) ? entries[i].DirName + "/" : "") + entries[i].FileName.ToString(), chunk); } } else { if (args.Length < 3) { Console.WriteLine("Usage for insertion CriPakTools IN_CPK REPLACE_THIS REPLACE_WITH [OUT_CPK]"); return; } string ins_name = args[1]; string replace_with = args[2]; FileInfo fi = new FileInfo(cpk_name); string outputName = fi.FullName + ".tmp"; if (args.Length >= 4) { outputName = fi.DirectoryName + "\\" + args[3]; } BinaryWriter newCPK = new BinaryWriter(File.OpenWrite(outputName)); List<FileEntry> entries = cpk.FileTable.OrderBy(x => x.FileOffset).ToList(); for (int i = 0; i < entries.Count; i++) { if (entries[i].FileType != "CONTENT") { if (entries[i].FileType == "FILE") { // I'm too lazy to figure out how to update the ContextOffset position so this works :) if ((ulong)newCPK.BaseStream.Position < cpk.ContentOffset) { ulong padLength = cpk.ContentOffset - (ulong)newCPK.BaseStream.Position; for (ulong z = 0; z < padLength; z++) { newCPK.Write((byte)0); } } } if (entries[i].FileName.ToString() != ins_name) { oldFile.BaseStream.Seek((long)entries[i].FileOffset, SeekOrigin.Begin); entries[i].FileOffset = (ulong)newCPK.BaseStream.Position; cpk.UpdateFileEntry(entries[i]); byte[] chunk = oldFile.ReadBytes(Int32.Parse(entries[i].FileSize.ToString())); newCPK.Write(chunk); } else { byte[] newbie = File.ReadAllBytes(replace_with); entries[i].FileOffset = (ulong)newCPK.BaseStream.Position; entries[i].FileSize = Convert.ChangeType(newbie.Length, entries[i].FileSizeType); entries[i].ExtractSize = Convert.ChangeType(newbie.Length, entries[i].FileSizeType); cpk.UpdateFileEntry(entries[i]); newCPK.Write(newbie); } if ((newCPK.BaseStream.Position % 0x800) > 0) { long cur_pos = newCPK.BaseStream.Position; for (int j = 0; j < (0x800 - (cur_pos % 0x800)); j++) { newCPK.Write((byte)0); } } } else { // Content is special.... just update the position cpk.UpdateFileEntry(entries[i]); } } cpk.WriteCPK(newCPK); cpk.WriteITOC(newCPK); cpk.WriteTOC(newCPK); cpk.WriteETOC(newCPK); cpk.WriteGTOC(newCPK); newCPK.Close(); oldFile.Close(); if (args.Length < 4) { File.Delete(cpk_name); File.Move(outputName, cpk_name); File.Delete(outputName); } } }
public static void Main(string[] args) { Console.WriteLine("CriPakTools\n"); Console.WriteLine("Based off Falo's code relased on Xentax forums (see readme.txt), modded by Nanashi3 from FuwaNovels.\nInsertion code by EsperKnight\n\n"); if (args.Length == 0) { Console.WriteLine("CriPakTool Usage:\n"); Console.WriteLine("CriPakTool.exe IN_FILE - Displays all contained chunks.\n"); Console.WriteLine("CriPakTool.exe IN_FILE EXTRACT_ME - Extracts a file.\n"); Console.WriteLine("CriPakTool.exe IN_FILE ALL - Extracts all files.\n"); Console.WriteLine("CriPakTool.exe IN_FILE REPLACE_ME REPLACE_WITH [OUT_FILE] - Replaces REPLACE_ME with REPLACE_WITH. Optional output it as a new CPK file otherwise it's replaced.\n"); return; } bool doExtract = false; bool doReplace = false; bool doDisplay = false; bool bUseCompress = false; bool doBatchReplace = false; //添加批量替换功能 bool bUseLegacyCompress = false; //添加旧式解压参数 string outDir = "."; string inFile = ""; string outFile = ""; string replaceMe = ""; string replaceWith = ""; string batch_text_name = ""; for (int i = 0; i < args.Length; i++) { string option = args[i]; if (option[0] == '-') { switch (option[1]) { case 'x': doExtract = true; break; case 'c': bUseCompress = true; break; case 'r': doReplace = true; replaceMe = args[i + 1]; replaceWith = args[i + 2]; break; case 'l': doDisplay = true; break; case 'd': outDir = args[i + 1]; break; case 'i': inFile = args[i + 1]; break; case 'o': outFile = args[i + 1]; break; case 'b': doBatchReplace = true; batch_text_name = args[i + 1]; break; case 'y': bUseLegacyCompress = true; break; case 'h': Console.WriteLine("CriPakTool Usage:"); Console.WriteLine(" -l - Displays all contained chunks."); Console.WriteLine(" -x - Extracts all files."); Console.WriteLine(" -c - use CRILAYLA compression"); Console.WriteLine(" -r REPLACE_ME REPLACE_WITH - Replaces REPLACE_ME with REPLACE_WITH."); Console.WriteLine(" -o OUT_FILE - Set output file."); Console.WriteLine(" -d OUT_DIR - Set output directory."); Console.WriteLine(" -i IN_FILE - Set input file."); Console.WriteLine(" -b BATCH_REPLACE_LIST_TXT - Batch Replace file recorded in filelist.txt ."); Console.WriteLine(" -h HELP"); Console.WriteLine(" [Extract files from cpk]"); Console.WriteLine(" CriPakTool.exe -x -i xxx.cpk -d xxx.cpk_unpacked"); Console.WriteLine(" [Display files from cpk]"); Console.WriteLine(" CriPakTool.exe -l -i xxx.cpk"); Console.WriteLine(" [Batch Replace files into cpk]"); Console.WriteLine(" CriPakTool.exe -b filelist.txt -c -i xxx.cpk -o xxx_patched.cpk"); Console.WriteLine(" //e.g. FILELIST.TXT"); Console.WriteLine(" original_file_name(in cpk),patch_file_name(in folder)"); Console.WriteLine(" /HD_font_a.ftx,patch/BOOT.cpk_unpacked/HD_font_a.ftx"); Console.WriteLine(" OTHER/ICON0.PNG,patch/BOOT.cpk_unpacked/OTHER/ICON0.PNG"); Console.WriteLine("..."); return; default: Console.WriteLine("CriPakTool Usage:"); Console.WriteLine(" -l - Displays all contained chunks."); Console.WriteLine(" -x - Extracts all files."); Console.WriteLine(" -c - use CRILAYLA compression"); Console.WriteLine(" -r REPLACE_ME REPLACE_WITH - Replaces REPLACE_ME with REPLACE_WITH."); Console.WriteLine(" -o OUT_FILE - Set output file."); Console.WriteLine(" -d OUT_DIR - Set output directory."); Console.WriteLine(" -i IN_FILE - Set input file."); Console.WriteLine(" -b BATCH_REPLACE_LIST_TXT - Batch Replace file recorded in filelist.txt ."); break; } } } if (inFile == "") { Console.WriteLine("ERROR :You must give -i argv"); return; } if (!File.Exists(inFile)) { Console.WriteLine("ERROR :INPUT FILE NOT EXISTS"); return; } if (!(doExtract || doReplace || doDisplay || doBatchReplace)) { //Lazy sanity checking for now Console.WriteLine("no? \n"); return; } string cpk_name = inFile; CPK cpk = new CPK(new Tools()); cpk.ReadCPK(cpk_name); BinaryReader oldFile = new BinaryReader(File.OpenRead(cpk_name)); if (doDisplay) { List <FileEntry> entries = cpk.FileTable.OrderBy(x => x.FileOffset).ToList(); for (int i = 0; i < entries.Count; i++) { Console.WriteLine("FILE ID:{0},File Name:{1},File Type:{5},FileOffset:{2:x8},Extract Size:{3:x8},Chunk Size:{4:x8}", entries[i].ID, (((entries[i].DirName != null) ? entries[i].DirName + "/" : "") + entries[i].FileName), entries[i].FileOffset, entries[i].ExtractSize, entries[i].FileSize, entries[i].FileType); } } else if (doExtract) { //if (!Directory.Exists(outDir)) //{ // Directory.CreateDirectory(outDir); //} List <FileEntry> entries = null; entries = cpk.FileTable.Where(x => x.FileType == "FILE").ToList(); if (entries.Count == 0) { Console.WriteLine("err while extracting."); } for (int i = 0; i < entries.Count; i++) { if (!String.IsNullOrEmpty((string)entries[i].DirName)) { Directory.CreateDirectory(outDir + "/" + entries[i].DirName.ToString()); } oldFile.BaseStream.Seek((long)entries[i].FileOffset, SeekOrigin.Begin); string isComp = Encoding.ASCII.GetString(oldFile.ReadBytes(8)); oldFile.BaseStream.Seek((long)entries[i].FileOffset, SeekOrigin.Begin); byte[] chunk = oldFile.ReadBytes(Int32.Parse(entries[i].FileSize.ToString())); Console.WriteLine("FileName :{0}\n FileOffset:{1:x8} ExtractSize:{2:x8} ChunkSize:{3:x8}", entries[i].FileName.ToString(), (long)entries[i].FileOffset, entries[i].ExtractSize, entries[i].FileSize); if (isComp == "CRILAYLA") { Console.WriteLine("Got CRILAYLA !"); int size = Int32.Parse((entries[i].ExtractSize ?? entries[i].FileSize).ToString()); if (size != 0) { if (bUseLegacyCompress == false) { chunk = cpk.DecompressCRILAYLA(chunk, size); } else { chunk = cpk.DecompressLegacyCRI(chunk, size); } } } File.WriteAllBytes(outDir + "/" + ((entries[i].DirName != null) ? entries[i].DirName + "/" : "") + entries[i].FileName.ToString(), chunk); } } else if (doBatchReplace) { //批量处理功能 ,读取filelist.txt内文件,将相应文件批量导入到cpk FileInfo fi = new FileInfo(cpk_name); string outputName = outFile; BinaryWriter newCPK = new BinaryWriter(File.OpenWrite(outputName)); List <FileEntry> entries = cpk.FileTable.OrderBy(x => x.FileOffset).ToList(); Tools tool = new Tools(); Dictionary <string, string> batch_file_list = tool.ReadBatchScript(batch_text_name); for (int i = 0; i < entries.Count; i++) { if (entries[i].FileType != "CONTENT") { if (entries[i].FileType == "FILE") { // I'm too lazy to figure out how to update the ContextOffset position so this works :) if ((ulong)newCPK.BaseStream.Position < cpk.ContentOffset) { ulong padLength = cpk.ContentOffset - (ulong)newCPK.BaseStream.Position; for (ulong z = 0; z < padLength; z++) { newCPK.Write((byte)0); } } } string currentName = ((entries[i].DirName != null) ? entries[i].DirName + "/" : "") + entries[i].FileName; if (!currentName.Contains("/")) { currentName = "/" + currentName; } if (!batch_file_list.Keys.Contains(currentName.ToString())) //如果不在表中,复制原始数据 { oldFile.BaseStream.Seek((long)entries[i].FileOffset, SeekOrigin.Begin); entries[i].FileOffset = (ulong)newCPK.BaseStream.Position; if (entries[i].FileName.ToString() == "ETOC_HDR") { cpk.EtocOffset = entries[i].FileOffset; Console.WriteLine("Fix ETOC_OFFSET to {0:x8}", cpk.EtocOffset); } cpk.UpdateFileEntry(entries[i]); byte[] chunk = oldFile.ReadBytes(Int32.Parse(entries[i].FileSize.ToString())); newCPK.Write(chunk); if ((newCPK.BaseStream.Position % 0x800) > 0 && i < entries.Count - 1) { long cur_pos = newCPK.BaseStream.Position; for (int j = 0; j < (0x800 - (cur_pos % 0x800)); j++) { newCPK.Write((byte)0); } } } else { string replace_with = batch_file_list[currentName.ToString()]; //Got patch file name Console.WriteLine("Patching: {0}", currentName.ToString()); byte[] newbie = File.ReadAllBytes(replace_with); entries[i].FileOffset = (ulong)newCPK.BaseStream.Position; int o_ext_size = Int32.Parse((entries[i].ExtractSize).ToString()); int o_com_size = Int32.Parse((entries[i].FileSize).ToString()); if ((o_com_size < o_ext_size) && entries[i].FileType == "FILE" && bUseCompress == true) { // is compressed Console.Write("Compressing data:{0:x8}", newbie.Length); byte[] dest_comp = cpk.CompressCRILAYLA(newbie); entries[i].FileSize = Convert.ChangeType(dest_comp.Length, entries[i].FileSizeType); entries[i].ExtractSize = Convert.ChangeType(newbie.Length, entries[i].FileSizeType); cpk.UpdateFileEntry(entries[i]); newCPK.Write(dest_comp); Console.Write(">> {0:x8}\r\n", dest_comp.Length); } else { Console.Write("Storing data:{0:x8}\r\n", newbie.Length); entries[i].FileSize = Convert.ChangeType(newbie.Length, entries[i].FileSizeType); entries[i].ExtractSize = Convert.ChangeType(newbie.Length, entries[i].FileSizeType); cpk.UpdateFileEntry(entries[i]); newCPK.Write(newbie); } if ((newCPK.BaseStream.Position % 0x800) > 0 && i < entries.Count - 1) { long cur_pos = newCPK.BaseStream.Position; for (int j = 0; j < (0x800 - (cur_pos % 0x800)); j++) { newCPK.Write((byte)0); } } } } else { // Content is special.... just update the position cpk.UpdateFileEntry(entries[i]); } } cpk.WriteCPK(newCPK); cpk.WriteITOC(newCPK); cpk.WriteTOC(newCPK); cpk.WriteETOC(newCPK, cpk.EtocOffset); cpk.WriteGTOC(newCPK); newCPK.Close(); oldFile.Close(); } else { string ins_name = replaceMe; string replace_with = replaceWith; FileInfo fi = new FileInfo(cpk_name); string outputName = outFile; BinaryWriter newCPK = new BinaryWriter(File.OpenWrite(outputName)); List <FileEntry> entries = cpk.FileTable.OrderBy(x => x.FileOffset).ToList(); for (int i = 0; i < entries.Count; i++) { if (entries[i].FileType != "CONTENT") { if (entries[i].FileType == "FILE") { // I'm too lazy to figure out how to update the ContextOffset position so this works :) if ((ulong)newCPK.BaseStream.Position < cpk.ContentOffset) { ulong padLength = cpk.ContentOffset - (ulong)newCPK.BaseStream.Position; for (ulong z = 0; z < padLength; z++) { newCPK.Write((byte)0); } } } if (entries[i].FileName.ToString() != ins_name) { oldFile.BaseStream.Seek((long)entries[i].FileOffset, SeekOrigin.Begin); Console.WriteLine("{0},{1}", entries[i].FileName, entries[i].FileType); entries[i].FileOffset = (ulong)newCPK.BaseStream.Position; cpk.UpdateFileEntry(entries[i]); byte[] chunk = oldFile.ReadBytes(Int32.Parse(entries[i].FileSize.ToString())); newCPK.Write(chunk); if ((newCPK.BaseStream.Position % 0x800) > 0 && i < entries.Count - 1) { long cur_pos = newCPK.BaseStream.Position; for (int j = 0; j < (0x800 - (cur_pos % 0x800)); j++) { newCPK.Write((byte)0); } } } else { //Got patch file name Console.WriteLine("{0} Patched.", entries[i].FileName.ToString()); byte[] newbie = File.ReadAllBytes(replace_with); entries[i].FileOffset = (ulong)newCPK.BaseStream.Position; int o_ext_size = Int32.Parse((entries[i].ExtractSize).ToString()); int o_com_size = Int32.Parse((entries[i].FileSize).ToString()); if ((o_com_size < o_ext_size) && entries[i].FileType == "FILE" && bUseCompress == true) { // is compressed byte[] dest_comp = cpk.CompressCRILAYLA(newbie); entries[i].FileSize = Convert.ChangeType(dest_comp.Length, entries[i].FileSizeType); entries[i].ExtractSize = Convert.ChangeType(newbie.Length, entries[i].FileSizeType); cpk.UpdateFileEntry(entries[i]); newCPK.Write(dest_comp); Console.WriteLine("Compressing {0:x8} >> {1:x8}", newbie.Length, dest_comp.Length); } else { entries[i].FileSize = Convert.ChangeType(newbie.Length, entries[i].FileSizeType); entries[i].ExtractSize = Convert.ChangeType(newbie.Length, entries[i].FileSizeType); cpk.UpdateFileEntry(entries[i]); newCPK.Write(newbie); } if ((newCPK.BaseStream.Position % 0x800) > 0 && i < entries.Count - 1) { long cur_pos = newCPK.BaseStream.Position; for (int j = 0; j < (0x800 - (cur_pos % 0x800)); j++) { newCPK.Write((byte)0); } } } } else { Console.WriteLine("{0},{1}", entries[i].FileName, entries[i].FileType); // Content is special.... just update the position cpk.UpdateFileEntry(entries[i]); } } cpk.WriteCPK(newCPK); cpk.WriteITOC(newCPK); cpk.WriteTOC(newCPK); cpk.WriteETOC(newCPK, cpk.EtocOffset); cpk.WriteGTOC(newCPK); newCPK.Close(); oldFile.Close(); } }
static void Main(string[] args) { if (args.Length == 0) { Console.WriteLine("err no args\n"); return; } bool doExtract = false; bool doReplace = false; bool doDisplay = false; string outDir = "."; string inFile = ""; string outFile = ""; string replaceMe = ""; string replaceWith = ""; for (int i = 0; i < args.Length; i++) { string option = args[i]; if (option[0] == '-') { switch (option[1]) { case 'x': doExtract = true; break; case 'r': doReplace = true; replaceMe = args[i + 1]; replaceWith = args[i + 2]; break; case 'l': doDisplay = true; break; case 'd': outDir = args[i + 1]; break; case 'i': inFile = args[i + 1]; break; case 'o': outFile = args[i + 1]; break; default: Console.WriteLine("CriPakTool Usage:"); Console.WriteLine(" -l - Displays all contained chunks."); Console.WriteLine(" -x - Extracts all files."); Console.WriteLine(" -r REPLACE_ME REPLACE_WITH - Replaces REPLACE_ME with REPLACE_WITH."); Console.WriteLine(" -o OUT_FILE - Set output file."); Console.WriteLine(" -d OUT_DIR - Set output directory."); Console.WriteLine(" -i IN_FILE - Set input file."); break; } } } if (!(doExtract || doReplace || doDisplay)) //Lazy sanity checking for now { Console.WriteLine("no? \n"); return; } string cpk_name = inFile; CPK cpk = new CPK(new Tools()); cpk.ReadCPK(cpk_name); BinaryReader oldFile = new BinaryReader(File.OpenRead(cpk_name)); if (doDisplay) { List <FileEntry> entries = cpk.FileTable.OrderBy(x => x.FileOffset).ToList(); for (int i = 0; i < entries.Count; i++) { Console.WriteLine(((entries[i].DirName != null) ? entries[i].DirName + "/" : "") + entries[i].FileName); } } else if (doExtract) { List <FileEntry> entries = null; entries = cpk.FileTable.Where(x => x.FileType == "FILE").ToList(); if (entries.Count == 0) { Console.WriteLine("err while extracting."); } for (int i = 0; i < entries.Count; i++) { if (!String.IsNullOrEmpty((string)entries[i].DirName)) { Directory.CreateDirectory(outDir + "/" + entries[i].DirName.ToString()); } oldFile.BaseStream.Seek((long)entries[i].FileOffset, SeekOrigin.Begin); string isComp = Encoding.ASCII.GetString(oldFile.ReadBytes(8)); oldFile.BaseStream.Seek((long)entries[i].FileOffset, SeekOrigin.Begin); byte[] chunk = oldFile.ReadBytes(Int32.Parse(entries[i].FileSize.ToString())); if (isComp == "CRILAYLA") { int size = Int32.Parse((entries[i].ExtractSize ?? entries[i].FileSize).ToString()); if (size != 0) { chunk = cpk.DecompressCRILAYLA(chunk, size); } } File.WriteAllBytes(outDir + "/" + ((entries[i].DirName != null) ? entries[i].DirName + "/" : "") + entries[i].FileName.ToString(), chunk); } } else { string ins_name = replaceMe; string replace_with = replaceWith; FileInfo fi = new FileInfo(cpk_name); string outputName = outFile; BinaryWriter newCPK = new BinaryWriter(File.OpenWrite(outputName)); List <FileEntry> entries = cpk.FileTable.OrderBy(x => x.FileOffset).ToList(); for (int i = 0; i < entries.Count; i++) { if (entries[i].FileType != "CONTENT") { if (entries[i].FileType == "FILE") { // I'm too lazy to figure out how to update the ContextOffset position so this works :) if ((ulong)newCPK.BaseStream.Position < cpk.ContentOffset) { ulong padLength = cpk.ContentOffset - (ulong)newCPK.BaseStream.Position; for (ulong z = 0; z < padLength; z++) { newCPK.Write((byte)0); } } } if (entries[i].FileName.ToString() != ins_name) { oldFile.BaseStream.Seek((long)entries[i].FileOffset, SeekOrigin.Begin); entries[i].FileOffset = (ulong)newCPK.BaseStream.Position; cpk.UpdateFileEntry(entries[i]); byte[] chunk = oldFile.ReadBytes(Int32.Parse(entries[i].FileSize.ToString())); newCPK.Write(chunk); } else { byte[] newbie = File.ReadAllBytes(replace_with); entries[i].FileOffset = (ulong)newCPK.BaseStream.Position; entries[i].FileSize = Convert.ChangeType(newbie.Length, entries[i].FileSizeType); entries[i].ExtractSize = Convert.ChangeType(newbie.Length, entries[i].FileSizeType); cpk.UpdateFileEntry(entries[i]); newCPK.Write(newbie); } if ((newCPK.BaseStream.Position % 0x800) > 0) { long cur_pos = newCPK.BaseStream.Position; for (int j = 0; j < (0x800 - (cur_pos % 0x800)); j++) { newCPK.Write((byte)0); } } } else { // Content is special.... just update the position cpk.UpdateFileEntry(entries[i]); } } cpk.WriteCPK(newCPK); cpk.WriteITOC(newCPK); cpk.WriteTOC(newCPK); cpk.WriteETOC(newCPK); cpk.WriteGTOC(newCPK); newCPK.Close(); oldFile.Close(); } }