private void InitGGPK() { if (content != null) { return; } string ggpkPath = textBoxContentGGPK.Text; if (!File.Exists(ggpkPath)) { OutputLine(string.Format("GGPK {0} not exists.", ggpkPath)); return; } OutputLine(string.Format("Parsing {0}", ggpkPath)); content = new GGPK(); content.Read(ggpkPath, Output); RecordsByPath = new Dictionary <string, FileRecord>(content.RecordOffsets.Count); DirectoryTreeNode.TraverseTreePostorder(content.DirectoryRoot, null, n => RecordsByPath.Add(n.GetDirectoryPath() + n.Name, n as FileRecord)); textBoxContentGGPK.Enabled = false; buttonSelectPOE.Enabled = false; CreateExampleRegistryFile(ggpkPath); }
public GGPKRecord(int length, GGPK ggpk) : base(length, ggpk) { Offset = ggpk.FileStream.Position - 8; GGPKVersion = (uint)ggpk.FileStream.ReadInt32(); // 3 RootDirectoryOffset = ggpk.FileStream.ReadInt64(); FirstFreeRecordOffset = ggpk.FileStream.ReadInt64(); }
public void ReloadAllData(string ggpkPath) { this.ggpkPath = ggpkPath; content = new GGPK(); content.Read(ggpkPath, outputFunc); CollectTranslatableStrings(); MergeUserTranslations(); }
/// <summary> /// Reloads the entire content.ggpk, rebuilds the tree /// </summary> private void ReloadGGPK() { treeView1.Items.Clear(); ResetViewer(); textBoxOutput.Visibility = System.Windows.Visibility.Visible; textBoxOutput.Text = string.Empty; content = null; workerThread = new Thread(new ThreadStart(() => { content = new GGPK(); try { content.Read(ggpkPath, Output); } catch (Exception ex) { Output(string.Format(Settings.Strings["ReloadGGPK_Failed"], ex.Message)); return; } if (content.IsReadOnly) { Output(Settings.Strings["ReloadGGPK_ReadOnly"] + Environment.NewLine); UpdateTitle(Settings.Strings["MainWindow_Title_Readonly"]); } OutputLine(Settings.Strings["ReloadGGPK_Traversing_Tree"]); // Collect all FileRecordPath -> FileRecord pairs for easier replacing RecordsByPath = new Dictionary <string, FileRecord>(content.RecordOffsets.Count); DirectoryTreeNode.TraverseTreePostorder(content.DirectoryRoot, null, n => RecordsByPath.Add(n.GetDirectoryPath() + n.Name, n as FileRecord)); treeView1.Dispatcher.BeginInvoke(new Action(() => { try { AddDirectoryTreeToControl(content.DirectoryRoot, null); } catch (Exception ex) { Output(string.Format(Settings.Strings["Error_Read_Directory_Tree"], ex.Message)); return; } workerThread = null; }), null); OutputLine(Settings.Strings["ReloadGGPK_Successful"]); })); workerThread.Start(); }
public FileRecord(int length, GGPK ggpk) : base(length, ggpk) { var s = ggpk.FileStream; Offset = s.Position - 8; var nameLength = s.ReadInt32(); Hash = new byte[32]; s.Read(Hash, 0, 32); var name = new byte[2 * (nameLength - 1)]; s.Read(name, 0, name.Length); Name = Encoding.Unicode.GetString(name); s.Seek(2, SeekOrigin.Current); // Null terminator DataOffset = s.Position; DataLength = Length - (nameLength * 2 + 44); // Length - (8 + nameLength * 2 + 32 + 4) s.Seek(DataLength, SeekOrigin.Current); }
private static void InitGGPK() { if (content != null) { return; } ggpkPath = searchContentGGPK(); if (!File.Exists(ggpkPath)) { OutputLine(string.Format("GGPK {0} not exists.", ggpkPath)); return; } OutputLine(string.Format("Parsing {0}", ggpkPath)); content = new GGPK(); content.Read(ggpkPath, Output); RecordsByPath = new Dictionary <string, FileRecord>(content.RecordOffsets.Count); DirectoryTreeNode.TraverseTreePostorder(content.DirectoryRoot, null, n => RecordsByPath.Add(n.GetDirectoryPath() + n.Name, n as FileRecord)); }
/// <summary> /// Read a DirectoryRecord from GGPK /// </summary> public DirectoryRecord(int length, GGPK ggpk) : base(length, ggpk) { var s = ggpk.FileStream; Offset = s.Position - 8; var nameLength = s.ReadInt32(); var totalEntries = s.ReadInt32(); Hash = new byte[32]; s.Read(Hash, 0, 32); var name = new byte[2 * (nameLength - 1)]; s.Read(name, 0, name.Length); Name = Encoding.Unicode.GetString(name); s.Seek(2, SeekOrigin.Current); // Null terminator EntriesBegin = s.Position; Entries = new DirectoryEntry[totalEntries]; for (var i = 0; i < totalEntries; i++) { Entries[i] = new DirectoryEntry((uint)s.ReadInt32(), s.ReadInt64()); } }
#pragma warning disable CS8618 protected TreeNode(int length, GGPK ggpk) : base(length, ggpk) { }
public static void Main(string[] args) { Console.WriteLine("PatchGGPK3 Copyright (C) 2021-2022 aianlinb."); // © if (args.Length == 0) { args = new string[2]; Console.Write("Path To GGPK: "); args[0] = Console.ReadLine() !; Console.Write("Path To Zip File: "); args[1] = Console.ReadLine() !; } else if (args.Length != 2) { Console.WriteLine("Usage: PatchGGPK3 <PathToGGPK> <ZipFile>"); return; } if (!File.Exists(args[0])) { Console.WriteLine("FileNotFound: " + args[0]); return; } if (!File.Exists(args[1])) { Console.WriteLine("FileNotFound: " + args[1]); return; } Console.WriteLine("GGPK: " + args[0]); Console.WriteLine("Patch file: " + args[1]); Console.WriteLine("Reading ggpk file . . ."); var ggpk = new GGPK(args[0]); Console.WriteLine("Replacing files . . ."); var zip = ZipFile.OpenRead(args[1]); int successed = 0, failed = 0; Console.WriteLine(); foreach (var e in zip.Entries) { if (e.FullName.EndsWith('/')) { continue; } Console.Write("Replacing " + e.FullName + " . . . "); if (ggpk.FindNode(e.FullName) is not FileRecord fr) { ++failed; Console.WriteLine(); Console.WriteLine("Not found in GGPK!"); continue; } var fs = e.Open(); var b = new byte[e.Length]; for (var l = 0; l < b.Length;) { l += fs.Read(b, l, b.Length - l); } fs.Close(); fr.ReplaceContent(b); ++successed; Console.WriteLine("Done"); } Console.WriteLine(); Console.WriteLine("All finished!"); Console.WriteLine($"Replaced {successed} files, {failed} files failed"); }
protected BaseRecord(int length, GGPK ggpk) { Length = length; Ggpk = ggpk; }
protected internal FreeRecord(int length, GGPK ggpk, long nextFreeOffset, long recordBegin) : base(length, ggpk) { Offset = recordBegin; NextFreeOffset = nextFreeOffset; }
protected internal FreeRecord(int length, GGPK ggpk) : base(length, ggpk) { Offset = ggpk.FileStream.Position - 8; NextFreeOffset = ggpk.FileStream.ReadInt64(); ggpk.FileStream.Seek(Length - 16, SeekOrigin.Current); }