static int ProcessFile(string FileInput) { if (!File.Exists(FileInput)) { Console.WriteLine("ERROR: Specified file doesn't exist."); Console.Read(); return(1); } using (BinaryReader Reader = new BinaryReader(File.Open(FileInput, FileMode.Open, FileAccess.Read, FileShare.Read))) MagicInputFile = Reader.ReadInt32(); if (MagicInputFile == MagicChunk) { Console.WriteLine("Chunk file detected."); if (!File.Exists($"{AppDomain.CurrentDomain.BaseDirectory}\\oo2core_5_win64.dll")) { Console.WriteLine("ERROR: oo2core_5_win64.dll is missing. Can't decompress chunk file."); if (!FlagAutoConfirm) { Console.Read(); } return(2); } Chunk.DecompressChunks(FileInput, FlagPKGExtraction, FlagAutoConfirm, FlagUnpackAll, FlagPKGDelete); if (!FlagAutoConfirm) { Console.Read(); } return(0); } else if (MagicInputFile == MagicPKG) { Console.WriteLine("PKG file detected."); PKG.ExtractPKG(FileInput, FlagPKGExtraction, FlagAutoConfirm, FlagUnpackAll, FlagPKGDelete); if (!FlagAutoConfirm) { Console.Read(); } return(0); } else { Console.WriteLine($"ERROR: Invalid magic {MagicInputFile.ToString("X8")}."); if (!FlagAutoConfirm) { Console.Read(); } return(0); } }
public static void DecompressChunks(String FileInput, bool FlagAutoConfirm, bool FlagUnpackAll, bool FlagBaseGame) { string NamePKG = $"{Environment.CurrentDirectory}\\{Path.GetFileNameWithoutExtension(FileInput)}.pkg"; BinaryReader Reader = new BinaryReader(File.Open(FileInput, FileMode.Open, FileAccess.Read, FileShare.Read)); // Key = ChunkOffset, Value = ChunkSize Dictionary <long, long> MetaChunk = new Dictionary <long, long>(); // Read header Reader.BaseStream.Seek(4, SeekOrigin.Begin); int ChunkCount = Reader.ReadInt32(); int ChunkPadding = ChunkCount.ToString().Length; double DiskSpace = (Int64)ChunkCount * (Int64)0x40000 * 1e-9; Utils.Print($"{ChunkCount} chunks in this file. Requires at least: {Math.Round(DiskSpace, 2)} GB.", false); // Read file list long totalChunkSize = 0; for (int i = 0; i < ChunkCount; i++) { // Process file size byte[] ArrayTmp1 = new byte[8]; byte[] ArrayChunkSize = Reader.ReadBytes(3); //int Low = ArrayChunkSize[0] & 0x0F; int High = ArrayChunkSize[0] >> 4; ArrayChunkSize[0] = BitConverter.GetBytes(High)[0]; Array.Copy(ArrayChunkSize, ArrayTmp1, ArrayChunkSize.Length); long ChunkSize = BitConverter.ToInt64(ArrayTmp1, 0); ChunkSize = (ChunkSize >> 4) + (ChunkSize & 0xF); totalChunkSize += ChunkSize; // Process offset byte[] ArrayTmp2 = new byte[8]; byte[] ArrayChunkOffset = Reader.ReadBytes(5); Array.Copy(ArrayChunkOffset, ArrayTmp2, ArrayChunkOffset.Length); long ChunkOffset = BitConverter.ToInt64(ArrayTmp2, 0); MetaChunk.Add(ChunkOffset, ChunkSize); // Console.WriteLine((i + 1).ToString("D8") + "," + ChunkOffset + "," + ChunkSize); } //Console.WriteLine(totalChunkSize); // Write decompressed chunks to pkg BinaryWriter Writer = new BinaryWriter(File.Create(NamePKG)); int DictCount = 1; foreach (KeyValuePair <long, long> Entry in MetaChunk) { Console.Write($"\rProcessing {DictCount.ToString().PadLeft(ChunkPadding)} / {ChunkCount}..."); if (Entry.Value != 0) { Reader.BaseStream.Seek(Entry.Key, SeekOrigin.Begin); byte[] ChunkCompressed = Reader.ReadBytes((int)Entry.Value); // Unsafe cast byte[] ChunkDecompressed = Utils.Decompress(ChunkCompressed, ChunkCompressed.Length, 0x40000); if (!FlagBaseGame) { Utils.DecryptChunk(ChunkDecompressed, Utils.GetChunkKey(DictCount - 1)); } Writer.Write(ChunkDecompressed); } else { Reader.BaseStream.Seek(Entry.Key, SeekOrigin.Begin); byte[] ChunkDecompressed = Reader.ReadBytes(0x40000); if (!FlagBaseGame) { Utils.DecryptChunk(ChunkDecompressed, Utils.GetChunkKey(DictCount - 1)); } Writer.Write(ChunkDecompressed); } DictCount++; } Reader.Close(); Writer.Close(); Utils.Print("Finished.", true); Utils.Print($"Output at: {NamePKG}", false); // Write csv Utils.Print("Writing file list.", false); PKG.ExtractPKG(NamePKG, FlagAutoConfirm, FlagUnpackAll, true); }
/* Exit Codes: * 0 - No error * 1 - Input file missing * 2 - oo2core_5_win64.dll file missing * 3 - Other exception */ static int Main(string[] args) { int MagicChunk = 0x00504D43; int MagicPKG = 0x20474B50; int MagicInputFile; string FileInput = ""; string StrPKGExtraction = ""; string AutoConfirm = ""; bool FlagPKGExtraction = true; bool FlagAutoConfirm = false; Console.WriteLine("=============================="); Utils.Print("WorldChunkTool v1.1.1 by MHVuze", false); // Display commands if (args.Length == 0) { Console.WriteLine("Usage: WorldChunkTool <chunkN_file|PKG_file> (PKGext) (AutoConf)"); Console.WriteLine("PKGext: use 'false' to turn off PKG file extraction, defaults to 'true'"); Console.WriteLine("AutoConf: Use 'true' to bypass confirmation prompts, defaults to 'false'"); Console.Read(); return(0); } // Check file FileInput = args[0]; if (!File.Exists(FileInput)) { Console.WriteLine("ERROR: Specified file doesn't exist."); Console.Read(); return(1); } // Turn PKG extraction output on or off if (args.Length > 1) { StrPKGExtraction = args[1]; } if (StrPKGExtraction.Equals("false", StringComparison.InvariantCultureIgnoreCase)) { FlagPKGExtraction = false; Console.WriteLine("PKG extraction turned off."); } // Accept confirmation prompts if (args.Length > 2) { AutoConfirm = args[2]; } if (AutoConfirm.Equals("true", StringComparison.InvariantCultureIgnoreCase)) { FlagAutoConfirm = true; Console.WriteLine("Auto Confirmation turned on."); } // Determine action based on file magic try { using (BinaryReader Reader = new BinaryReader(File.Open(FileInput, FileMode.Open))) MagicInputFile = Reader.ReadInt32(); if (MagicInputFile == MagicChunk) { Console.WriteLine("Chunk file detected."); if (!File.Exists($"{AppDomain.CurrentDomain.BaseDirectory}\\oo2core_5_win64.dll")) { Console.WriteLine("ERROR: oo2core_5_win64.dll is missing. Can't decompress chunk file."); if (!FlagAutoConfirm) { Console.Read(); } return(2); } Chunk.DecompressChunks(FileInput, FlagPKGExtraction, FlagAutoConfirm); if (!FlagAutoConfirm) { Console.Read(); } return(0); } else if (MagicInputFile == MagicPKG) { Console.WriteLine("PKG file detected."); PKG.ExtractPKG(FileInput, FlagPKGExtraction, FlagAutoConfirm); if (!FlagAutoConfirm) { Console.Read(); } return(0); } else { Console.WriteLine($"ERROR: Invalid magic {MagicInputFile.ToString("X8")}."); if (!FlagAutoConfirm) { Console.Read(); } return(0); } } catch (Exception e) { Console.WriteLine("ERROR: The following exception was caught."); Console.WriteLine(e); if (!FlagAutoConfirm) { Console.Read(); } return(3); } }
static int ProcessFile(string FileInput) { if (!File.Exists(FileInput)) { Console.WriteLine("ERROR: Specified file doesn't exist."); Console.Read(); return(1); } using (BinaryReader Reader = new BinaryReader(File.Open(FileInput, FileMode.Open, FileAccess.Read, FileShare.Read))) MagicInputFile = Reader.ReadInt32(); if (MagicInputFile == MagicChunk) { Console.WriteLine("Chunk file detected."); if (!File.Exists($"{AppDomain.CurrentDomain.BaseDirectory}\\oo2core_8_win64.dll")) { Console.WriteLine("ERROR: oo2core_8_win64.dll is missing. Can't decompress chunk file."); if (!FlagAutoConfirm) { Console.Read(); } return(2); } // Build PKG if (FlagBuildPkg) { Chunk.DecompressChunks(FileInput, FlagAutoConfirm, FlagUnpackAll, FlagBaseGame); } // On-the-fly decompression and unpacking else { ChunkOTF ChunkOtfInst = new ChunkOTF(); List <FileNode> FileCatalog = new List <FileNode>(); string FilePath = $"{Environment.CurrentDirectory}\\{Path.GetFileNameWithoutExtension(FileInput)}"; if (FlagUnpackAll) { FilePath = $"{Environment.CurrentDirectory}\\chunk_combined"; } FileCatalog = ChunkOtfInst.AnalyzeChunk(FileInput, FileCatalog, FlagBaseGame); Console.WriteLine("Extracting chunk file, please wait."); ChunkOtfInst.ExtractSelected(FileCatalog, FilePath, FlagBaseGame); Utils.Print("\nFinished.", false); if (!FlagUnpackAll) { Utils.Print($"Output at: {FilePath}", false); } if (!FlagAutoConfirm) { Console.WriteLine("Press Enter to quit"); } if (!FlagAutoConfirm) { Console.Read(); } } return(0); } else if (MagicInputFile == MagicPKG) { Console.WriteLine("PKG file detected."); PKG.ExtractPKG(FileInput, FlagAutoConfirm, FlagUnpackAll, false); if (!FlagAutoConfirm) { Console.Read(); } return(0); } else { Console.WriteLine($"ERROR: Invalid magic {MagicInputFile.ToString("X8")}."); if (!FlagAutoConfirm) { Console.Read(); } return(0); } }
public static void DecompressChunks(String FileInput, bool FlagPKGExtraction, bool FlagAutoConfirm) { string NamePKG = $"{Environment.CurrentDirectory}\\{Path.GetFileNameWithoutExtension(FileInput)}.pkg"; BinaryReader Reader = new BinaryReader(File.Open(FileInput, FileMode.Open)); // Key = ChunkOffset, Value = ChunkSize Dictionary <long, long> MetaChunk = new Dictionary <long, long>(); // Read header Reader.BaseStream.Seek(4, SeekOrigin.Begin); int ChunkCount = Reader.ReadInt32(); int ChunkPadding = ChunkCount.ToString().Length; Utils.Print($"{ChunkCount} chunks in this file.", false); // Read file list for (int i = 0; i < ChunkCount; i++) { // Process file size byte[] ArrayTmp1 = new byte[8]; byte[] ArrayChunkSize = Reader.ReadBytes(3); //int Low = ArrayChunkSize[0] & 0x0F; int High = ArrayChunkSize[0] >> 4; ArrayChunkSize[0] = BitConverter.GetBytes(High)[0]; Array.Copy(ArrayChunkSize, ArrayTmp1, ArrayChunkSize.Length); long ChunkSize = BitConverter.ToInt64(ArrayTmp1, 0); ChunkSize = (ChunkSize >> 4) + (ChunkSize & 0xF); // Process offset byte[] ArrayTmp2 = new byte[8]; byte[] ArrayChunkOffset = Reader.ReadBytes(5); Array.Copy(ArrayChunkOffset, ArrayTmp2, ArrayChunkOffset.Length); long ChunkOffset = BitConverter.ToInt64(ArrayTmp2, 0); MetaChunk.Add(ChunkOffset, ChunkSize); } // Write decompressed chunks to pkg BinaryWriter Writer = new BinaryWriter(File.Create(NamePKG)); int DictCount = 1; foreach (KeyValuePair <long, long> Entry in MetaChunk) { Console.Write($"\rProcessing {DictCount.ToString().PadLeft(ChunkPadding)} / {ChunkCount}..."); if (Entry.Value != 0) { Reader.BaseStream.Seek(Entry.Key, SeekOrigin.Begin); byte[] ChunkCompressed = Reader.ReadBytes((int)Entry.Value); // Unsafe cast byte[] ChunkDecompressed = Utils.Decompress(ChunkCompressed, ChunkCompressed.Length, 0x40000); Writer.Write(ChunkDecompressed); } else { Reader.BaseStream.Seek(Entry.Key, SeekOrigin.Begin); byte[] ChunkDecompressed = Reader.ReadBytes(0x40000); Writer.Write(ChunkDecompressed); } DictCount++; } Reader.Close(); Writer.Close(); Utils.Print("Finished.", true); Utils.Print($"Output at: {NamePKG}", false); if (!FlagAutoConfirm) { Console.WriteLine("The PKG file will now be extracted. Press Enter to continue or close window to quit."); Console.Read(); } Console.SetCursorPosition(0, Console.CursorTop - 1); Console.WriteLine("=============================="); PKG.ExtractPKG(NamePKG, FlagPKGExtraction, FlagAutoConfirm); if (!FlagAutoConfirm) { Console.Read(); } }