From 3b0739f65ca3004b4dbe8326e02f4ad7f112e809 Mon Sep 17 00:00:00 2001 From: Kurt Date: Tue, 23 Jun 2015 22:44:20 -0700 Subject: [PATCH] Add patch creation interface (romfs redir) Still have to redesign the main window for the ExeFS/RomFS/3DS/Patch creation buttons to replace the existing on-click events. --- pk3DS/Main.cs | 19 ++-- pk3DS/Subforms/Patch.Designer.cs | 143 +++++++++++++++++++++++++++++++ pk3DS/Subforms/Patch.cs | 123 ++++++++++++++++++++++++++ pk3DS/Subforms/Patch.resx | 120 ++++++++++++++++++++++++++ pk3DS/pk3DS.csproj | 9 ++ 5 files changed, 406 insertions(+), 8 deletions(-) create mode 100644 pk3DS/Subforms/Patch.Designer.cs create mode 100644 pk3DS/Subforms/Patch.cs create mode 100644 pk3DS/Subforms/Patch.resx diff --git a/pk3DS/Main.cs b/pk3DS/Main.cs index fcbd7c6..0ad0d24 100644 --- a/pk3DS/Main.cs +++ b/pk3DS/Main.cs @@ -65,7 +65,8 @@ public Main() public static string ExeFSPath; public static string ExHeaderPath; public volatile int threads; - private static string[] allGARCs = { "gametext", "storytext", "personal", "trpoke", "trdata", "evolution", "megaevo", "levelup", "eggmove", "item", "move", "maisonpkS", "maisontrS", "maisonpkN", "maisontrN" }; + internal volatile static int Language; + internal static string[] allGARCs = { "gametext", "storytext", "personal", "trpoke", "trdata", "evolution", "megaevo", "levelup", "eggmove", "item", "move", "maisonpkS", "maisontrS", "maisonpkN", "maisontrN" }; private bool skipBoth; // Main Form Methods @@ -113,6 +114,9 @@ private void B_Open_Click(object sender, EventArgs e) } private void changeLanguage(object sender, EventArgs e) { + if (CB_Lang.InvokeRequired) + CB_Lang.Invoke((MethodInvoker)delegate { Language = CB_Lang.SelectedIndex; }); + else Language = CB_Lang.SelectedIndex; if (!GB_RomFS.Enabled) return; new Thread(() => { @@ -601,13 +605,12 @@ private void L_SubTools_Click(object sender, EventArgs e) } // GARC Requests - public string getGARCFileName(string requestedGARC) + private string getGARCFileName(string requestedGARC) + { + return getGARCFileName(requestedGARC, Language); + } + internal static string getGARCFileName(string requestedGARC, int lang) { - int lang = 0; - if (CB_Lang.InvokeRequired) - CB_Lang.Invoke((MethodInvoker)delegate { lang = CB_Lang.SelectedIndex; }); - else lang = CB_Lang.SelectedIndex; - string ans = ""; switch (requestedGARC) { @@ -633,7 +636,7 @@ public string getGARCFileName(string requestedGARC) } return ans; } - public string getGARCPath(int A, int B, int C) + internal static string getGARCPath(int A, int B, int C) { return String.Format("{0}a{0}{1}{0}{2}{0}{3}", Path.DirectorySeparatorChar, A, B, C); } diff --git a/pk3DS/Subforms/Patch.Designer.cs b/pk3DS/Subforms/Patch.Designer.cs new file mode 100644 index 0000000..1c838fc --- /dev/null +++ b/pk3DS/Subforms/Patch.Designer.cs @@ -0,0 +1,143 @@ +namespace pk3DS +{ + partial class Patch + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.CHKLB_GARCs = new System.Windows.Forms.CheckedListBox(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.B_PatchCIA = new System.Windows.Forms.Button(); + this.CHK_Lang = new System.Windows.Forms.CheckBox(); + this.RTB_GARCs = new System.Windows.Forms.RichTextBox(); + this.label2 = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // CHKLB_GARCs + // + this.CHKLB_GARCs.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left))); + this.CHKLB_GARCs.FormattingEnabled = true; + this.CHKLB_GARCs.Location = new System.Drawing.Point(12, 12); + this.CHKLB_GARCs.Name = "CHKLB_GARCs"; + this.CHKLB_GARCs.Size = new System.Drawing.Size(150, 289); + this.CHKLB_GARCs.TabIndex = 0; + // + // textBox1 + // + this.textBox1.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.textBox1.Location = new System.Drawing.Point(168, 28); + this.textBox1.Name = "textBox1"; + this.textBox1.ReadOnly = true; + this.textBox1.Size = new System.Drawing.Size(104, 20); + this.textBox1.TabIndex = 1; + this.textBox1.Text = "a/#/* -> a#/*"; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(168, 12); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(109, 13); + this.label1.TabIndex = 2; + this.label1.Text = "ExeFS Path Override:"; + // + // B_PatchCIA + // + this.B_PatchCIA.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.B_PatchCIA.Location = new System.Drawing.Point(168, 278); + this.B_PatchCIA.Name = "B_PatchCIA"; + this.B_PatchCIA.Size = new System.Drawing.Size(104, 23); + this.B_PatchCIA.TabIndex = 3; + this.B_PatchCIA.Text = "Redirect [CIA]"; + this.B_PatchCIA.UseVisualStyleBackColor = true; + this.B_PatchCIA.Click += new System.EventHandler(this.B_PatchCIA_Click); + // + // CHK_Lang + // + this.CHK_Lang.AutoSize = true; + this.CHK_Lang.Location = new System.Drawing.Point(171, 54); + this.CHK_Lang.Name = "CHK_Lang"; + this.CHK_Lang.Size = new System.Drawing.Size(110, 17); + this.CHK_Lang.TabIndex = 4; + this.CHK_Lang.Text = "Patch Languages"; + this.CHK_Lang.UseVisualStyleBackColor = true; + // + // RTB_GARCs + // + this.RTB_GARCs.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left))); + this.RTB_GARCs.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.RTB_GARCs.Location = new System.Drawing.Point(168, 90); + this.RTB_GARCs.Name = "RTB_GARCs"; + this.RTB_GARCs.Size = new System.Drawing.Size(75, 160); + this.RTB_GARCs.TabIndex = 5; + this.RTB_GARCs.Text = ""; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(165, 74); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(72, 13); + this.label2.TabIndex = 6; + this.label2.Text = "Extra GARCs:"; + // + // Patch + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(284, 312); + this.Controls.Add(this.label2); + this.Controls.Add(this.RTB_GARCs); + this.Controls.Add(this.CHK_Lang); + this.Controls.Add(this.B_PatchCIA); + this.Controls.Add(this.label1); + this.Controls.Add(this.textBox1); + this.Controls.Add(this.CHKLB_GARCs); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "Patch"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "Patch Manager"; + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.CheckedListBox CHKLB_GARCs; + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Button B_PatchCIA; + private System.Windows.Forms.CheckBox CHK_Lang; + private System.Windows.Forms.RichTextBox RTB_GARCs; + private System.Windows.Forms.Label label2; + } +} \ No newline at end of file diff --git a/pk3DS/Subforms/Patch.cs b/pk3DS/Subforms/Patch.cs new file mode 100644 index 0000000..297678c --- /dev/null +++ b/pk3DS/Subforms/Patch.cs @@ -0,0 +1,123 @@ +using System; +using System.Collections.Specialized; +using System.IO; +using System.Linq; +using System.Text; +using System.Windows.Forms; + +namespace pk3DS +{ + public partial class Patch : Form + { + public Patch() + { + InitializeComponent(); + RTB_GARCs.Clear(); + CHKLB_GARCs.Items.Clear(); + foreach (string s in Main.allGARCs) + CHKLB_GARCs.Items.Add(s); + } + + internal static bool patchExeFS(string path, string[] oldstr, string[] newstr, ref string result, string outPath = null) + { + int ctr = 0; + if (oldstr.Length != newstr.Length) + { + result = "Input replacements do not match output replacements."; + return false; + } + + string text = File.ReadAllText(path, Encoding.Unicode); + for (int i = 0; i < oldstr.Length; i++) + { + if (!text.Contains(oldstr[i])) + result += "Does not contain " + oldstr + Environment.NewLine; + else + ctr++; + + text = text.Replace(oldstr[i], newstr[i]); + } + + if (ctr == 0) + { result = "Did not find the old path strings to replace."; return false; } + result += String.Format("Redirected {0} file paths.", ctr); + File.WriteAllText(outPath ?? path, text, Encoding.Unicode); + return true; + } + internal static string exportGARCs(string[] garcPaths, string[] newPaths, string parentRomFS, string patchFolder) + { + if (Directory.Exists(patchFolder)) + Directory.Delete(patchFolder, true); + Directory.CreateDirectory(patchFolder); + + // Stuff files into new patch folder + for (int i = 0; i < garcPaths.Length; i++) + { + if ((garcPaths[i] ?? "").Length == 0) continue; + string folder = Path.GetDirectoryName(newPaths[i]); + Directory.CreateDirectory(folder); + File.Copy(Path.Combine(parentRomFS, garcPaths[i]), folder); + } + return patchFolder; + } + + private void B_PatchCIA_Click(object sender, EventArgs e) + { + try + { + string[] garcs = getGARCs(); + string[] garcPaths = getPaths(garcs); + + const string oldROM = "rom:/a/"; + const string newROM = "rom2:/a"; + + string[] newPaths = (string[]) garcPaths.Clone(); + + // Patch the reference + for (int i = 0; i < newPaths.Length; i++) + { + int posA = newPaths[i].LastIndexOf(oldROM, StringComparison.Ordinal); + newPaths[i] = (posA == -1) ? null : newPaths[i].Remove(posA, oldROM.Length).Insert(posA, newROM); + } + string patchFolder = String.Format("{0} ({1})", "Patch", new DateTime().ToString("yyMMdd@HHmmss")); + string result = ""; + if (!patchExeFS(Main.ExeFSPath, garcPaths, newPaths, ref result, Path.Combine(patchFolder, ".code.bin"))) + return; + + Util.Alert("Patch contents saved to:" + Environment.NewLine + exportGARCs(garcPaths, newPaths, Main.RomFSPath, patchFolder), result); + } + catch (Exception ex) + { Util.Error("Could not create patch:", ex.ToString()); } + } + + private string[] getGARCs() + { + StringCollection sc = new StringCollection(); + foreach (int indexChecked in CHKLB_GARCs.CheckedIndices) + sc.Add(CHKLB_GARCs.Items[indexChecked].ToString()); + + string[] rtbLines = RTB_GARCs.Lines; + foreach (string s in rtbLines.Where(s => s.Length == 7 && !sc.Contains(s.Replace('/', Path.DirectorySeparatorChar)))) + sc.Add(s.Replace('/', Path.DirectorySeparatorChar)); + + string[] garcs = new string[sc.Count]; + sc.CopyTo(garcs, 0); + return garcs; + } + private string[] getPaths(string[] sc) + { + bool languages = CHK_Lang.Checked; + StringCollection paths = new StringCollection(); + foreach (string s in sc) + if (!languages || (s != "gametext" || s != "storytext")) + paths.Add(Main.getGARCFileName(s, Main.Language)); + else + for (int l = 0; l < 8; l++) + paths.Add(Main.getGARCFileName(s, l)); + + string[] garcs = new string[paths.Count]; + paths.CopyTo(garcs, 0); + return garcs; + } + } +} diff --git a/pk3DS/Subforms/Patch.resx b/pk3DS/Subforms/Patch.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/pk3DS/Subforms/Patch.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/pk3DS/pk3DS.csproj b/pk3DS/pk3DS.csproj index f5137c0..c732edb 100644 --- a/pk3DS/pk3DS.csproj +++ b/pk3DS/pk3DS.csproj @@ -65,6 +65,12 @@ + + Form + + + Patch.cs + Form @@ -207,6 +213,9 @@ Main.cs + + Patch.cs + TitleScreen.cs