From 8f6ba8b535d3028f7b1eb9eda4ad740314d6257b Mon Sep 17 00:00:00 2001 From: jvyden Date: Sat, 6 Aug 2022 13:49:27 -0400 Subject: [PATCH 1/7] Make zip function recursive when building --- build-all.sh | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/build-all.sh b/build-all.sh index 0bd01b9..daf126a 100755 --- a/build-all.sh +++ b/build-all.sh @@ -12,20 +12,20 @@ dotnet publish -c MacOS -r osx-arm64 --self-contained # $1: Name.zip # $2: Path to zip -function zipPath() { +function createBuild() { currentDirectory=$(pwd) cd $2 || return 1; - zip "$1" *; + zip -r "$1" *; cd $currentDirectory || return 1; mv "$2/$1" builds/ } -zipPath "UnionPatcher-Windows-x64.zip" "UnionPatcher.Gui.Windows/bin/Release/net6.0-windows/win-x64/publish/" +createBuild "UnionPatcher-Windows-x64.zip" "UnionPatcher.Gui.Windows/bin/Release/net6.0-windows/win-x64/publish/" -zipPath "UnionPatcher-Linux-x64.zip" "UnionPatcher.Gui.Linux/bin/Release/net6.0/linux-x64/publish/" -zipPath "UnionPatcher-Linux-arm.zip" "UnionPatcher.Gui.Linux/bin/Release/net6.0/linux-arm/publish/" -zipPath "UnionPatcher-Linux-arm64.zip" "UnionPatcher.Gui.Linux/bin/Release/net6.0/linux-arm64/publish/" +createBuild "UnionPatcher-Linux-x64.zip" "UnionPatcher.Gui.Linux/bin/Release/net6.0/linux-x64/publish/" +createBuild "UnionPatcher-Linux-arm.zip" "UnionPatcher.Gui.Linux/bin/Release/net6.0/linux-arm/publish/" +createBuild "UnionPatcher-Linux-arm64.zip" "UnionPatcher.Gui.Linux/bin/Release/net6.0/linux-arm64/publish/" -zipPath "UnionPatcher-macOS-x64.zip" "UnionPatcher.Gui.MacOS/bin/Release/net6.0/osx-x64/publish/" -zipPath "UnionPatcher-macOS-arm64.zip" "UnionPatcher.Gui.MacOS/bin/Release/net6.0/osx-arm64/publish/" \ No newline at end of file +createBuild "UnionPatcher-macOS-x64.zip" "UnionPatcher.Gui.MacOS/bin/Release/net6.0/osx-x64/publish/" +createBuild "UnionPatcher-macOS-arm64.zip" "UnionPatcher.Gui.MacOS/bin/Release/net6.0/osx-arm64/publish/" \ No newline at end of file From 3d8473129ac64a5f9f9a9a90d4a37a6e355b6916 Mon Sep 17 00:00:00 2001 From: Dagg <32235163+daggintosh@users.noreply.github.com> Date: Tue, 13 Sep 2022 15:15:04 -0700 Subject: [PATCH 2/7] Added regex matching to find index of LBP server URLs (#27) * Use regex to discover existing server urls - Supports LBP PSP and PS3 - Hardcoded length limit, will fix soonTM * Get maximum length for server URL from EBOOT * Potential fix for LBP3 - Matches all but NULL instead of just all * Potentially extend maximum length Thanks slendy * Leave a NULL character of padding --- UnionPatcher/Patcher.cs | 45 +++++++++++------------------------------ 1 file changed, 12 insertions(+), 33 deletions(-) diff --git a/UnionPatcher/Patcher.cs b/UnionPatcher/Patcher.cs index 17e3bcb..7593974 100644 --- a/UnionPatcher/Patcher.cs +++ b/UnionPatcher/Patcher.cs @@ -1,37 +1,11 @@ using System; using System.IO; using System.Text; +using System.Text.RegularExpressions; namespace LBPUnion.UnionPatcher; public static class Patcher { - private static readonly string[] toBePatched = { - // Normal LittleBigPlanet gameserver URLs - "https://littlebigplanetps3.online.scee.com:10061/LITTLEBIGPLANETPS3_XML", - "http://littlebigplanetps3.online.scee.com:10060/LITTLEBIGPLANETPS3_XML", - // LittleBigPlanet 3 Presence URLs - "http://live.littlebigplanetps3.online.scee.com:10060/LITTLEBIGPLANETPS3_XML", - "http://presence.littlebigplanetps3.online.scee.com:10060/LITTLEBIGPLANETPS3_XML", - #region Spinoff URLs - // LittleBigPlanet PSP URLs - "http://lbppsp.online.scee.com:10060/LITTLEBIGPLANETPSP_XML", - "https://lbppsp.online.scee.com:10061/LITTLEBIGPLANETPSP_XML", - // LittleBigPlanet Vita URLs - "http://lbpvita.online.scee.com:10060/LITTLEBIGPLANETPS3_XML", - "https://lbpvita.online.scee.com:10061/LITTLEBIGPLANETPS3_XML", - #endregion - #region Beta URLS - // LittleBigPlanet 2 Beta URLs - "http://lbp2ps3-beta.online.scee.com:10060/LITTLEBIGPLANETPS3_XML", - "https://lbp2ps3-beta.online.scee.com:10061/LITTLEBIGPLANETPS3_XML", - // LittleBigPlanet (3?) Beta URLs - "http://littlebigplanetps3-beta.online.scee.com:10060/LITTLEBIGPLANETPS3_XML", - "https://littlebigplanetps3-beta.online.scee.com:10061/LITTLEBIGPLANETPS3_XML", - // LittleBigPlanet Vita Beta URLs - "http://lbpvita-beta.online.scee.com:10060/LITTLEBIGPLANETPS3_XML", - "https://lbpvita-beta.online.scee.com:10061/LITTLEBIGPLANETPS3_XML", - #endregion - }; public static void PatchFile(string fileName, Uri serverUrl, string outputFileName) { PatchFile(fileName, serverUrl.ToString(), outputFileName); @@ -72,13 +46,18 @@ public static class Patcher { byte[] serverUrlAsBytes = Encoding.ASCII.GetBytes(serverUrl); bool wroteUrl = false; - foreach(string url in toBePatched) { - if(serverUrl.Length > url.Length) { - throw new ArgumentOutOfRangeException(nameof(serverUrl), $"Server URL ({serverUrl.Length} characters long) is above maximum length {url.Length}"); + + // Find a string including http or https and LITTLEBIGPLANETPS3_XML or LITTLEBIGPLANETPSP_XML, + // then match any additional NULL characters to dynamically gague the maximum length on a per-title basis + // without a hardcoded array of known server URLs + MatchCollection urls = Regex.Matches(dataAsString, "http?[^\x00]*?LITTLEBIGPLANETPS(3|P)_XML\x00*"); + foreach(Match urlMatch in urls) { + string url = urlMatch.Value; + + if(serverUrl.Length > url.Length - 1) { + throw new ArgumentOutOfRangeException(nameof(serverUrl), $"Server URL ({serverUrl.Length} characters long) is above maximum length {url.Length - 1}"); } - - int offset = dataAsString.IndexOf(url, StringComparison.Ordinal); - if(offset < 1) continue; + int offset = urlMatch.Index; writer.BaseStream.Position = offset; for(int i = 0; i < url.Length; i++) { From 7d77decf179f16e01893190b19194aecbb55fe60 Mon Sep 17 00:00:00 2001 From: Dagg <32235163+daggintosh@users.noreply.github.com> Date: Wed, 2 Nov 2022 12:26:15 -0700 Subject: [PATCH 3/7] Swap out the custom message boxes with the stock Eto MessageBox (#29) * Use regex to discover existing server urls - Supports LBP PSP and PS3 - Hardcoded length limit, will fix soonTM * Get maximum length for server URL from EBOOT * Potential fix for LBP3 - Matches all but NULL instead of just all * Potentially extend maximum length Thanks slendy * Leave a NULL character of padding * Use stock eto message boxes instead of custom. * Use Information message box type Ding may be strange but this process takes a while sometimes --- UnionPatcher.Gui/Forms/FilePatchForm.cs | 29 ++++++++++------ UnionPatcher.Gui/Forms/RemotePatchForm.cs | 20 ++++++------ UnionPatcher.Gui/Gui.cs | 40 ++++------------------- 3 files changed, 35 insertions(+), 54 deletions(-) diff --git a/UnionPatcher.Gui/Forms/FilePatchForm.cs b/UnionPatcher.Gui/Forms/FilePatchForm.cs index 27e9fa8..e5ea839 100644 --- a/UnionPatcher.Gui/Forms/FilePatchForm.cs +++ b/UnionPatcher.Gui/Forms/FilePatchForm.cs @@ -1,5 +1,6 @@ using System; using System.Diagnostics; +using System.Text.RegularExpressions; using Eto; using Eto.Drawing; using Eto.Forms; @@ -73,46 +74,54 @@ public class FilePatchForm : Form { private void Patch() { if(string.IsNullOrWhiteSpace(this.filePicker.FilePath)) { - Gui.CreateOkDialog("Form Error", "No file specified!").ShowModal(); + Gui.CreateOkDialog("Form Error", "No file specified!"); return; } if(string.IsNullOrWhiteSpace(this.serverUrl.Text)) { - Gui.CreateOkDialog("Form Error", "No server URL specified!").ShowModal(); + Gui.CreateOkDialog("Form Error", "No server URL specified!"); return; } if(string.IsNullOrWhiteSpace(this.outputFileName.FilePath)) { - Gui.CreateOkDialog("Form Error", "No output file specified!").ShowModal(); + Gui.CreateOkDialog("Form Error", "No output file specified!"); return; } if(this.filePicker.FilePath == this.outputFileName.FilePath) { - Gui.CreateOkDialog("Form Error", "Input and output filename are the same! Please save the patched file with a different name so you have a backup of your the original EBOOT.ELF.").ShowModal(); + Gui.CreateOkDialog("Form Error", "Input and output filename are the same! Please save the patched file with a different name so you have a backup of your the original EBOOT.ELF."); return; } if(!Uri.TryCreate(this.serverUrl.Text, UriKind.Absolute, out _)) { - Gui.CreateOkDialog("Form Error", "Server URL is invalid! Please enter a valid URL.").ShowModal(); + Gui.CreateOkDialog("Form Error", "Server URL is invalid! Please enter a valid URL."); return; } + + if(!Regex.IsMatch(this.serverUrl.Text, "LITTLEBIGPLANETPS3_XML")) { + bool userCertain = Gui.CreateConfirmationDialog("URL Mistype", $"Server URL {this.serverUrl.Text} does not match LITTLEBIGPLANETPS3_XML, are you sure you want to use this?"); + if (!userCertain) { + return; + } + // else, godspeed, captain + } // Validate EBOOT after validating form; more expensive ElfFile eboot = new(this.filePicker.FilePath); if(eboot.IsValid == false) { - Gui.CreateOkDialog("EBOOT Error", $"{eboot.Name} is not a valid ELF file (magic number mismatch)\n" + "The EBOOT must be decrypted before using this tool").ShowModal(); + Gui.CreateOkDialog("EBOOT Error", $"{eboot.Name} is not a valid ELF file (magic number mismatch)\n" + "The EBOOT must be decrypted before using this tool"); return; } if(eboot.Is64Bit == null) { - Gui.CreateOkDialog("EBOOT Error", $"{eboot.Name} does not target a valid system").ShowModal(); + Gui.CreateOkDialog("EBOOT Error", $"{eboot.Name} does not target a valid system"); return; } if(string.IsNullOrWhiteSpace(eboot.Architecture)) { - Gui.CreateOkDialog("EBOOT Error", $"{eboot.Name} does not target a valid architecture (PowerPC or ARM)").ShowModal(); + Gui.CreateOkDialog("EBOOT Error", $"{eboot.Name} does not target a valid architecture (PowerPC or ARM)"); return; } @@ -120,10 +129,10 @@ public class FilePatchForm : Form { Patcher.PatchFile(this.filePicker.FilePath, this.serverUrl.Text, this.outputFileName.FilePath); } catch(Exception e) { - Gui.CreateOkDialog("Error occurred while patching", "An error occured while patching:\n" + e).ShowModal(); + Gui.CreateOkDialog("Error occurred while patching", "An error occured while patching:\n" + e); return; } - Gui.CreateOkDialog("Success!", "The Server URL has been patched to " + this.serverUrl.Text).ShowModal(); + Gui.CreateOkDialog("Success!", "The Server URL has been patched to " + this.serverUrl.Text); } } \ No newline at end of file diff --git a/UnionPatcher.Gui/Forms/RemotePatchForm.cs b/UnionPatcher.Gui/Forms/RemotePatchForm.cs index 1e84400..7354ea9 100644 --- a/UnionPatcher.Gui/Forms/RemotePatchForm.cs +++ b/UnionPatcher.Gui/Forms/RemotePatchForm.cs @@ -34,25 +34,25 @@ public class RemotePatchForm : Form control.Click += delegate { if (string.IsNullOrEmpty(this.ps3LocalIP.Text)) { - Gui.CreateOkDialog("Error", "No PS3 IP address specified!").ShowModal(); + Gui.CreateOkDialog("Error", "No PS3 IP address specified!"); return; } if (string.IsNullOrEmpty(this.lbpGameID.Text)) { - Gui.CreateOkDialog("Error", "No title ID specified!").ShowModal(); + Gui.CreateOkDialog("Error", "No title ID specified!"); return; } if (string.IsNullOrEmpty(this.serverUrl.Text)) { - Gui.CreateOkDialog("Error", "No server URL specified!").ShowModal(); + Gui.CreateOkDialog("Error", "No server URL specified!"); return; } if (!Uri.TryCreate(this.serverUrl.Text, UriKind.Absolute, out _)) { - Gui.CreateOkDialog("Error", "Server URL is invalid! Please enter a valid URL.").ShowModal(); + Gui.CreateOkDialog("Error", "Server URL is invalid! Please enter a valid URL."); return; } @@ -69,11 +69,11 @@ public class RemotePatchForm : Form } catch (Exception e) { - Gui.CreateOkDialog("Error occurred while patching", "An error occured while patching:\n" + e).ShowModal(); + Gui.CreateOkDialog("Error occurred while patching", "An error occured while patching:\n" + e); return; } - Gui.CreateOkDialog("Success!", $"The Server URL for {this.lbpGameID.Text} on the PS3 at {this.ps3LocalIP.Text} has been patched to {this.serverUrl.Text}").ShowModal(); + Gui.CreateOkDialog("Success!", $"The Server URL for {this.lbpGameID.Text} on the PS3 at {this.ps3LocalIP.Text} has been patched to {this.serverUrl.Text}"); }; return control; @@ -91,13 +91,13 @@ public class RemotePatchForm : Form control.Click += delegate { if (string.IsNullOrEmpty(this.ps3LocalIP.Text)) { - Gui.CreateOkDialog("Form Error", "No PS3 IP address specified!").ShowModal(); + Gui.CreateOkDialog("Form Error", "No PS3 IP address specified!"); return; } if (string.IsNullOrEmpty(this.lbpGameID.Text)) { - Gui.CreateOkDialog("Form Error", "No game ID specified!").ShowModal(); + Gui.CreateOkDialog("Form Error", "No game ID specified!"); return; } @@ -107,11 +107,11 @@ public class RemotePatchForm : Form } catch (Exception e) { - Gui.CreateOkDialog("Error occurred while reverting EBOOT", "An error occured while patching:\n" + e).ShowModal(); + Gui.CreateOkDialog("Error occurred while reverting EBOOT", "An error occured while patching:\n" + e); return; } - Gui.CreateOkDialog("Success!", $"UnionRemotePatcher reverted your the EBOOT for {this.lbpGameID.Text} to stock. You're ready to patch your EBOOT again.").ShowModal(); + Gui.CreateOkDialog("Success!", $"UnionRemotePatcher reverted your the EBOOT for {this.lbpGameID.Text} to stock. You're ready to patch your EBOOT again."); }; return control; diff --git a/UnionPatcher.Gui/Gui.cs b/UnionPatcher.Gui/Gui.cs index 9a62e51..808094f 100644 --- a/UnionPatcher.Gui/Gui.cs +++ b/UnionPatcher.Gui/Gui.cs @@ -9,39 +9,11 @@ public static class Gui { new Application().Run(new ModeSelectionForm()); } - public static Dialog CreateOkDialog(string title, string errorMessage) { - DynamicLayout layout = new(); - Button button; - - layout.Spacing = new Size(5, 5); - layout.MinimumSize = new Size(350, 100); - - layout.BeginHorizontal(); - layout.Add(new Label { - Text = errorMessage, - }); - - layout.BeginHorizontal(); - layout.BeginVertical(); - layout.Add(null); - layout.Add(button = new Button { - Text = "OK", - }); - - layout.EndVertical(); - layout.EndHorizontal(); - layout.EndHorizontal(); - - Dialog dialog = new() { - Content = layout, - Padding = new Padding(10, 10, 10, 10), - Title = title, - }; - - button.Click += delegate { - dialog.Close(); - }; - - return dialog; + public static void CreateOkDialog(string title, string errorMessage) { + MessageBox.Show(errorMessage, title, MessageBoxButtons.OK, MessageBoxType.Information); + } + public static bool CreateConfirmationDialog(string title, string errorMessage) { + DialogResult result = MessageBox.Show(errorMessage, title, MessageBoxButtons.YesNo, MessageBoxType.Question); + return result == DialogResult.Yes; } } \ No newline at end of file From 58d9dd3a674a873903cdc009c267c1527ae80281 Mon Sep 17 00:00:00 2001 From: Josh Date: Wed, 2 Nov 2022 14:26:30 -0500 Subject: [PATCH 4/7] Make the file picker only show valid files (#28) * Make the file picker only show valid files * Fix file wildcard patterns --- UnionPatcher.Gui/Forms/FilePatchForm.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/UnionPatcher.Gui/Forms/FilePatchForm.cs b/UnionPatcher.Gui/Forms/FilePatchForm.cs index e5ea839..a52e04d 100644 --- a/UnionPatcher.Gui/Forms/FilePatchForm.cs +++ b/UnionPatcher.Gui/Forms/FilePatchForm.cs @@ -50,7 +50,7 @@ public class FilePatchForm : Form { Rows = { new TableRow( new TableCell(new Label { Text = "EBOOT.elf: ", VerticalAlignment = VerticalAlignment.Center }), - new TableCell(this.filePicker = new FilePicker { TabIndex = 0 }) + new TableCell(this.filePicker = new FilePicker { TabIndex = 0 , FileAction = FileAction.OpenFile, Filters = { new FileFilter("ELF files", "*.elf", "*.ELF"), new FileFilter("All Files", "*.*") }}) ), new TableRow( new TableCell(new Label { Text = "Server URL: ", VerticalAlignment = VerticalAlignment.Center }), @@ -58,7 +58,7 @@ public class FilePatchForm : Form { ), new TableRow( new TableCell(new Label { Text = "Output filename: ", VerticalAlignment = VerticalAlignment.Center }), - new TableCell(this.outputFileName = new FilePicker { TabIndex = 2, FileAction = FileAction.SaveFile }) + new TableCell(this.outputFileName = new FilePicker { TabIndex = 2, FileAction = FileAction.SaveFile, Filters = { new FileFilter("ELF files", "*.elf", "*.ELF"), new FileFilter("All Files", "*.*") }}) ), new TableRow( new TableCell(this.CreateHelpButton(4)), @@ -135,4 +135,4 @@ public class FilePatchForm : Form { Gui.CreateOkDialog("Success!", "The Server URL has been patched to " + this.serverUrl.Text); } -} \ No newline at end of file +} From 47af7d6929264705d3fbd7d263f297b48c2a765a Mon Sep 17 00:00:00 2001 From: Dagg Date: Wed, 9 Nov 2022 14:36:26 -0800 Subject: [PATCH 5/7] macOS Hotfix: Require staging directory (#31) * macOS: Require staging directory * Grammar --- UnionPatcher.Gui/Forms/ModeSelectionForm.cs | 26 +++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/UnionPatcher.Gui/Forms/ModeSelectionForm.cs b/UnionPatcher.Gui/Forms/ModeSelectionForm.cs index a39a4bd..d23fdbd 100644 --- a/UnionPatcher.Gui/Forms/ModeSelectionForm.cs +++ b/UnionPatcher.Gui/Forms/ModeSelectionForm.cs @@ -1,8 +1,9 @@ using System; +using System.IO; using Eto.Drawing; using Eto.Forms; -namespace LBPUnion.UnionPatcher.Gui.Forms; +namespace LBPUnion.UnionPatcher.Gui.Forms; public class ModeSelectionForm : Form { #region UI @@ -23,10 +24,27 @@ public class ModeSelectionForm : Form { new TableCell(new Button(openFilePatcher) { Text = "File Patch (PS3/RPCS3)" }) ), }, - }; + }; } - - private void openRemotePatcher(object sender, EventArgs e) { + + private void openRemotePatcher(object sender, EventArgs e) + { + if (OSUtil.GetPlatform() == OSPlatform.OSX) + { + Gui.CreateOkDialog("Workaround", "UnionPatcher RemotePatcher requires a staging folder on macOS, please set this to the directory of the UnionPatcher app!"); + SelectFolderDialog dialog = new SelectFolderDialog(); + if (dialog.ShowDialog(this) != DialogResult.Ok) + { + Gui.CreateOkDialog("Workaround", "User did not specify a staging folder, aborting!"); + return; + } + Directory.SetCurrentDirectory(dialog.Directory); + if (!Directory.Exists("scetool")) + { + Gui.CreateOkDialog("Workaround", "Invalid folder, remember to set the folder to the directory of the UnionPatcher app!"); + return; + } + } RemotePatchForm rpForm = new RemotePatchForm(); rpForm.Show(); rpForm.Closed += OnSubFormClose; From 7b88e278432671a3e08ea42709bb7d3e1f3e64c3 Mon Sep 17 00:00:00 2001 From: Dagg Date: Sat, 18 Mar 2023 21:38:21 -0700 Subject: [PATCH 6/7] Require staging directory as fallback (#34) * Test requiring staging directory on Windows * Special workaround v1 * Remove variable since its only used once --- UnionPatcher.Gui/Forms/ModeSelectionForm.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/UnionPatcher.Gui/Forms/ModeSelectionForm.cs b/UnionPatcher.Gui/Forms/ModeSelectionForm.cs index d23fdbd..ce45984 100644 --- a/UnionPatcher.Gui/Forms/ModeSelectionForm.cs +++ b/UnionPatcher.Gui/Forms/ModeSelectionForm.cs @@ -29,9 +29,12 @@ public class ModeSelectionForm : Form { private void openRemotePatcher(object sender, EventArgs e) { - if (OSUtil.GetPlatform() == OSPlatform.OSX) + if (!Directory.Exists("scetool")) { - Gui.CreateOkDialog("Workaround", "UnionPatcher RemotePatcher requires a staging folder on macOS, please set this to the directory of the UnionPatcher app!"); + // This will always occur on macOS, so don't show this message for macOS users. + if (OSUtil.GetPlatform() != OSPlatform.OSX) Gui.CreateOkDialog("Workaround Triggered", ".NET could not locate the required files, triggering workaround."); + + Gui.CreateOkDialog("Workaround", "UnionPatcher RemotePatcher requires a staging folder on macOS or in special circumstances on Windows, please set this to the directory of the UnionPatcher app or executable!"); SelectFolderDialog dialog = new SelectFolderDialog(); if (dialog.ShowDialog(this) != DialogResult.Ok) { @@ -41,7 +44,7 @@ public class ModeSelectionForm : Form { Directory.SetCurrentDirectory(dialog.Directory); if (!Directory.Exists("scetool")) { - Gui.CreateOkDialog("Workaround", "Invalid folder, remember to set the folder to the directory of the UnionPatcher app!"); + Gui.CreateOkDialog("Workaround", "Invalid folder, remember to set the folder to the directory of the UnionPatcher app or executable!"); return; } } From c45b9ec37eedade40490a1c000311b099ed71f31 Mon Sep 17 00:00:00 2001 From: Zaprit Date: Fri, 19 Jan 2024 00:05:42 +0000 Subject: [PATCH 7/7] Remove macOS staging directory requirement, and update to .NET 8.0 (#41) * Code cleanup and update to .NET 8 * Fix macOS requiring staging directory to be selected. Also places eboots on Desktop on macos, to avoid them being inside the app bundle. * Fix keys discovery on mac * Removed debug logging, made GetExecutablePath more robust. * Created a script for building on mac, as creating a universal binary is somewhat involved * Update UnionPatcher.Gui/Forms/ModeSelectionForm.cs Co-authored-by: sudokoko * Apply suggestions from code review Co-authored-by: Josh --------- Co-authored-by: sudokoko Co-authored-by: Josh --- .github/workflows/build.yml | 8 +- UnionPatcher.Cli/UnionPatcher.Cli.csproj | 2 +- .../UnionPatcher.Gui.Linux.csproj | 2 +- UnionPatcher.Gui.MacOS/Info.plist | 34 ++++++++ .../UnionPatcher.Gui.MacOS.csproj | 4 +- .../UnionPatcher.Gui.Windows.csproj | 2 +- UnionPatcher.Gui/Forms/ModeSelectionForm.cs | 9 ++- UnionPatcher.Gui/Gui.cs | 5 +- UnionPatcher.Gui/UnionPatcher.Gui.csproj | 4 +- UnionPatcher/OSUtil.cs | 14 ++++ UnionPatcher/RemotePatch.cs | 81 ++++++++++++------- UnionPatcher/UnionPatcher.csproj | 2 +- build-all.sh | 26 +++--- build-mac.sh | 21 +++++ 14 files changed, 155 insertions(+), 59 deletions(-) create mode 100755 UnionPatcher.Gui.MacOS/Info.plist create mode 100755 build-mac.sh diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0aa0fe4..8cec7e0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -14,17 +14,17 @@ jobs: fail-fast: false matrix: os: - - { prettyName: Windows, platform: windows-latest, configurationName: Windows, extraArgs: "", buildPath: "Release/net6.0-windows/publish"} - - { prettyName: Linux, platform: ubuntu-latest, configurationName: Linux, extraArgs: "", buildPath: "Release/net6.0/publish"} + - { prettyName: Windows, platform: windows-latest, configurationName: Windows, extraArgs: "", buildPath: "Release/net8.0-windows/publish"} + - { prettyName: Linux, platform: ubuntu-latest, configurationName: Linux, extraArgs: "", buildPath: "Release/net8.0/publish"} # - { prettyName: MacOS, platform: ubuntu-latest, configurationName: Release, platform: osx-x64 } steps: - name: Checkout uses: actions/checkout@v2 - - name: Install .NET 6.0 + - name: Install .NET 8.0 uses: actions/setup-dotnet@v1 with: - dotnet-version: "6.0.x" + dotnet-version: "8.0.x" - name: Compile for ${{ matrix.os.prettyName }} run: dotnet publish -c ${{ matrix.os.configurationName }} ${{ matrix.os.extraArgs }} diff --git a/UnionPatcher.Cli/UnionPatcher.Cli.csproj b/UnionPatcher.Cli/UnionPatcher.Cli.csproj index a4adeee..5c6e24d 100644 --- a/UnionPatcher.Cli/UnionPatcher.Cli.csproj +++ b/UnionPatcher.Cli/UnionPatcher.Cli.csproj @@ -2,7 +2,7 @@ Exe - net6.0 + net8.0 enable enable UnionPatcher diff --git a/UnionPatcher.Gui.Linux/UnionPatcher.Gui.Linux.csproj b/UnionPatcher.Gui.Linux/UnionPatcher.Gui.Linux.csproj index f9f7aa8..74f3bd8 100644 --- a/UnionPatcher.Gui.Linux/UnionPatcher.Gui.Linux.csproj +++ b/UnionPatcher.Gui.Linux/UnionPatcher.Gui.Linux.csproj @@ -2,7 +2,7 @@ Exe - net6.0 + net8.0 linux-x64 LBPUnion.UnionPatcher.Gui.Linux LBPUnion.UnionPatcher.Gui.Linux diff --git a/UnionPatcher.Gui.MacOS/Info.plist b/UnionPatcher.Gui.MacOS/Info.plist new file mode 100755 index 0000000..883a4ac --- /dev/null +++ b/UnionPatcher.Gui.MacOS/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleIdentifier + com.lbpunion.unionpatcher + NSHumanReadableCopyright + Copyright LBP Union 2024© + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + CFBundleDevelopmentRegion + en + CFBundleIconFile + Icon.icns + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + APPL + CFBundleSignature + ???? + NSPrincipalClass + NSApplication + CFBundleName + UnionPatcher + CFBundleExecutable + LBPUnion.UnionPatcher.Gui.MacOS + LSMinimumSystemVersion + 10.14 + NSRequiresAquaSystemAppearance + False + + diff --git a/UnionPatcher.Gui.MacOS/UnionPatcher.Gui.MacOS.csproj b/UnionPatcher.Gui.MacOS/UnionPatcher.Gui.MacOS.csproj index 62fb7a3..e4eb4d3 100644 --- a/UnionPatcher.Gui.MacOS/UnionPatcher.Gui.MacOS.csproj +++ b/UnionPatcher.Gui.MacOS/UnionPatcher.Gui.MacOS.csproj @@ -2,11 +2,13 @@ Exe - net6.0 + net8.0 osx-x64;osx-arm64 LBPUnion.UnionPatcher.Gui.MacOS LBPUnion.UnionPatcher.Gui.MacOS Icon64.ico + true + true diff --git a/UnionPatcher.Gui.Windows/UnionPatcher.Gui.Windows.csproj b/UnionPatcher.Gui.Windows/UnionPatcher.Gui.Windows.csproj index f754306..8c18143 100644 --- a/UnionPatcher.Gui.Windows/UnionPatcher.Gui.Windows.csproj +++ b/UnionPatcher.Gui.Windows/UnionPatcher.Gui.Windows.csproj @@ -2,7 +2,7 @@ WinExe - net6.0-windows + net8.0-windows LBPUnion.UnionPatcher.Gui.Windows LBPUnion.UnionPatcher.Gui.Windows Icon64.ico diff --git a/UnionPatcher.Gui/Forms/ModeSelectionForm.cs b/UnionPatcher.Gui/Forms/ModeSelectionForm.cs index ce45984..1b3ffbc 100644 --- a/UnionPatcher.Gui/Forms/ModeSelectionForm.cs +++ b/UnionPatcher.Gui/Forms/ModeSelectionForm.cs @@ -1,5 +1,8 @@ using System; using System.IO; +using System.Reflection; +using System.Text; +using Eto; using Eto.Drawing; using Eto.Forms; @@ -29,11 +32,13 @@ public class ModeSelectionForm : Form { private void openRemotePatcher(object sender, EventArgs e) { - if (!Directory.Exists("scetool")) + // If we're on macOS then set the CWD to the app bundle MacOS folder, so that SCETool can be found. + if (OSUtil.GetPlatform() == OSPlatform.OSX) Directory.SetCurrentDirectory(OSUtil.GetExecutablePath()); + + if (!Directory.Exists($"{OSUtil.GetExecutablePath()}/scetool")) { // This will always occur on macOS, so don't show this message for macOS users. if (OSUtil.GetPlatform() != OSPlatform.OSX) Gui.CreateOkDialog("Workaround Triggered", ".NET could not locate the required files, triggering workaround."); - Gui.CreateOkDialog("Workaround", "UnionPatcher RemotePatcher requires a staging folder on macOS or in special circumstances on Windows, please set this to the directory of the UnionPatcher app or executable!"); SelectFolderDialog dialog = new SelectFolderDialog(); if (dialog.ShowDialog(this) != DialogResult.Ok) diff --git a/UnionPatcher.Gui/Gui.cs b/UnionPatcher.Gui/Gui.cs index 808094f..fec6065 100644 --- a/UnionPatcher.Gui/Gui.cs +++ b/UnionPatcher.Gui/Gui.cs @@ -1,5 +1,4 @@ -using Eto.Drawing; -using Eto.Forms; +using Eto.Forms; using LBPUnion.UnionPatcher.Gui.Forms; namespace LBPUnion.UnionPatcher.Gui; @@ -10,7 +9,7 @@ public static class Gui { } public static void CreateOkDialog(string title, string errorMessage) { - MessageBox.Show(errorMessage, title, MessageBoxButtons.OK, MessageBoxType.Information); + MessageBox.Show(errorMessage, title, MessageBoxButtons.OK); } public static bool CreateConfirmationDialog(string title, string errorMessage) { DialogResult result = MessageBox.Show(errorMessage, title, MessageBoxButtons.YesNo, MessageBoxType.Question); diff --git a/UnionPatcher.Gui/UnionPatcher.Gui.csproj b/UnionPatcher.Gui/UnionPatcher.Gui.csproj index 1400570..7915919 100644 --- a/UnionPatcher.Gui/UnionPatcher.Gui.csproj +++ b/UnionPatcher.Gui/UnionPatcher.Gui.csproj @@ -7,11 +7,11 @@ - net6.0 + net8.0 - net6.0-windows + net8.0-windows diff --git a/UnionPatcher/OSUtil.cs b/UnionPatcher/OSUtil.cs index b4eb0da..4aa26f3 100644 --- a/UnionPatcher/OSUtil.cs +++ b/UnionPatcher/OSUtil.cs @@ -1,6 +1,9 @@ using System; using System.Collections.Generic; +using System.Diagnostics; +using System.IO; using System.Linq; +using System.Reflection; using System.Runtime.InteropServices; namespace LBPUnion.UnionPatcher @@ -29,6 +32,17 @@ namespace LBPUnion.UnionPatcher return EnumeratePlatforms().FirstOrDefault(p => RuntimeInformation.IsOSPlatform(p.Value.RuntimePlatform))?.Platform ?? default; } + + public static string GetExecutablePath() + { + var path = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location); + if (string.IsNullOrEmpty(path)) + path = Path.GetDirectoryName(Process.GetCurrentProcess().MainModule?.FileName); + if (string.IsNullOrEmpty(path)) + path = AppContext.BaseDirectory; + + return path; + } } } diff --git a/UnionPatcher/RemotePatch.cs b/UnionPatcher/RemotePatch.cs index 8642559..2e56bee 100644 --- a/UnionPatcher/RemotePatch.cs +++ b/UnionPatcher/RemotePatch.cs @@ -91,16 +91,23 @@ public class RemotePatch { Console.WriteLine("Restoring original EBOOT.BIN from EBOOT.BIN.BAK"); + string workingDir = "."; + if (OSUtil.GetPlatform() == OSPlatform.OSX) + { + workingDir = $"{Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)}/UnionPatcher"; + Directory.CreateDirectory(workingDir); + } + // Create a simple directory structure - Directory.CreateDirectory(@"eboot"); - Directory.CreateDirectory($@"eboot/{gameID}"); - Directory.CreateDirectory($@"eboot/{gameID}/original"); + Directory.CreateDirectory($@"{workingDir}/eboot"); + Directory.CreateDirectory($@"{workingDir}/eboot/{gameID}"); + Directory.CreateDirectory($@"{workingDir}/eboot/{gameID}/original"); // Now we'll check and see if a backup exists on the server, if so download it and then upload it back as EBOOT.BIN if (FTP.FileExists($"ftp://{ps3ip}/dev_hdd0/game/{gameID}/USRDIR/EBOOT.BIN.BAK", user, pass)) { - FTP.DownloadFile($"ftp://{ps3ip}/dev_hdd0/game/{gameID}/USRDIR/EBOOT.BIN.BAK", @$"eboot/{gameID}/original/EBOOT.BIN.BAK", user, pass); - FTP.UploadFile(@$"eboot/{gameID}/original/EBOOT.BIN.BAK", $"ftp://{ps3ip}/dev_hdd0/game/{gameID}/USRDIR/EBOOT.BIN", user, pass); + FTP.DownloadFile($"ftp://{ps3ip}/dev_hdd0/game/{gameID}/USRDIR/EBOOT.BIN.BAK", @$"{workingDir}/eboot/{gameID}/original/EBOOT.BIN.BAK", user, pass); + FTP.UploadFile(@$"{workingDir}/eboot/{gameID}/original/EBOOT.BIN.BAK", $"ftp://{ps3ip}/dev_hdd0/game/{gameID}/USRDIR/EBOOT.BIN", user, pass); } else { @@ -111,6 +118,13 @@ public class RemotePatch public void PSNEBOOTRemotePatch(string ps3ip, string gameID, string serverURL, string user, string pass) { Console.WriteLine("Detected Digital Copy - Running in Full Mode"); + + string workingDir = "."; + if (OSUtil.GetPlatform() == OSPlatform.OSX) + { + workingDir = $"{Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)}/UnionPatcher"; + Directory.CreateDirectory(workingDir); + } string idps = ""; string contentID = ""; @@ -121,25 +135,25 @@ public class RemotePatch this._ps3Mapi.PS3.Notify("UnionRemotePatcher Connected! Patching..."); // Create simple directory structure - Directory.CreateDirectory(@"rifs"); - Directory.CreateDirectory(@"eboot"); - Directory.CreateDirectory($@"eboot/{gameID}"); - Directory.CreateDirectory($@"eboot/{gameID}/original"); - Directory.CreateDirectory($@"eboot/{gameID}/patched"); + Directory.CreateDirectory($@"{workingDir}/rifs"); + Directory.CreateDirectory($@"{workingDir}/eboot"); + Directory.CreateDirectory($@"{workingDir}/eboot/{gameID}"); + Directory.CreateDirectory($@"{workingDir}/eboot/{gameID}/original"); + Directory.CreateDirectory($@"{workingDir}/eboot/{gameID}/patched"); // Let's grab and backup our EBOOT FTP.DownloadFile($"ftp://{ps3ip}/dev_hdd0/game/{gameID}/USRDIR/EBOOT.BIN", - @$"eboot/{gameID}/original/EBOOT.BIN", user, pass); + @$"{workingDir}/eboot/{gameID}/original/EBOOT.BIN", user, pass); // Now we'll check and see if a backup exists on the server or not, if we don't have one on the server, then upload one if (!FTP.FileExists($"ftp://{ps3ip}/dev_hdd0/game/{gameID}/USRDIR/EBOOT.BIN.BAK", user, pass)) - FTP.UploadFile(@$"eboot/{gameID}/original/EBOOT.BIN", + FTP.UploadFile(@$"{workingDir}/eboot/{gameID}/original/EBOOT.BIN", $"ftp://{ps3ip}/dev_hdd0/game/{gameID}/USRDIR/EBOOT.BIN.BAK", user, pass); // Start getting idps and act.dat - these will help us decrypt a PSN eboot idps = PS3MAPI.PS3MAPIClientServer.PS3_GetIDPS(); - File.WriteAllBytes(@"data/idps", IDPSHelper.StringToByteArray(idps)); + File.WriteAllBytes($@"data/idps", IDPSHelper.StringToByteArray(idps)); // Scan the users on the system users = GetUsers(ps3ip, user, pass); @@ -153,12 +167,12 @@ public class RemotePatch $"ftp://{ps3ip}/dev_hdd0/home/{currentUser}/exdata/", user, pass)) if (fileName.Contains(gameID)) { - FTP.DownloadFile($"ftp://{ps3ip}/dev_hdd0/home/{currentUser}/exdata/act.dat", @"data/act.dat", + FTP.DownloadFile($"ftp://{ps3ip}/dev_hdd0/home/{currentUser}/exdata/act.dat", $@"{workingDir}/data/act.dat", user, pass); FTP.DownloadFile($"ftp://{ps3ip}/dev_hdd0/home/{currentUser}/exdata/{fileName}", - @$"rifs/{fileName}", user, pass); + @$"{workingDir}/rifs/{fileName}", user, pass); contentID = fileName.Substring(0, fileName.Length - 4); @@ -168,10 +182,10 @@ public class RemotePatch } // Finally, let's decrypt the EBOOT.BIN - LaunchSCETool($" -v -d \"{Path.GetFullPath(@$"eboot/{gameID}/original/EBOOT.BIN")}\" \"{Path.GetFullPath(@$"eboot/{gameID}/original/EBOOT.ELF")}\""); + LaunchSCETool($" -v -d \"{Path.GetFullPath(@$"{workingDir}/eboot/{gameID}/original/EBOOT.BIN")}\" \"{Path.GetFullPath(@$"{workingDir}/eboot/{gameID}/original/EBOOT.ELF")}\""); // Now, patch the EBOOT; - Patcher.PatchFile($"eboot/{gameID}/original/EBOOT.ELF", serverURL, $"eboot/{gameID}/patched/EBOOT.ELF"); + Patcher.PatchFile($"{workingDir}/eboot/{gameID}/original/EBOOT.ELF", serverURL, $"{workingDir}/eboot/{gameID}/patched/EBOOT.ELF"); // Encrypt the EBOOT (PSN) LaunchSCETool($"--verbose " + @@ -191,10 +205,10 @@ public class RemotePatch $" --np-app-type=SPRX" + $" --np-content-id={contentID}" + $" --np-real-fname=EBOOT.BIN" + - $" --encrypt eboot/{gameID}/patched/EBOOT.ELF eboot/{gameID}/patched/EBOOT.BIN"); + $" --encrypt {workingDir}/eboot/{gameID}/patched/EBOOT.ELF {workingDir}/eboot/{gameID}/patched/EBOOT.BIN"); // And upload the encrypted, patched EBOOT to the system. - FTP.UploadFile(@$"eboot/{gameID}/patched/EBOOT.BIN", + FTP.UploadFile(@$"{workingDir}/eboot/{gameID}/patched/EBOOT.BIN", $"ftp://{ps3ip}/dev_hdd0/game/{gameID}/USRDIR/EBOOT.BIN", user, pass); } @@ -203,38 +217,45 @@ public class RemotePatch { Console.WriteLine("Detected Disc Copy - Running in Simplified Mode"); + string workingDir = "."; + if (OSUtil.GetPlatform() == OSPlatform.OSX) + { + workingDir = $"{Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)}/UnionPatcher"; + Directory.CreateDirectory(workingDir); + } + // Create a simple directory structure - Directory.CreateDirectory(@"eboot"); - Directory.CreateDirectory($@"eboot/{gameID}"); - Directory.CreateDirectory($@"eboot/{gameID}/original"); - Directory.CreateDirectory($@"eboot/{gameID}/patched"); + Directory.CreateDirectory($@"{workingDir}/eboot"); + Directory.CreateDirectory($@"{workingDir}/eboot/{gameID}"); + Directory.CreateDirectory($@"{workingDir}/eboot/{gameID}/original"); + Directory.CreateDirectory($@"{workingDir}/eboot/{gameID}/patched"); // Let's grab and backup our EBOOT FTP.DownloadFile($"ftp://{ps3ip}/dev_hdd0/game/{gameID}/USRDIR/EBOOT.BIN", - @$"eboot/{gameID}/original/EBOOT.BIN", user, pass); + @$"{workingDir}/eboot/{gameID}/original/EBOOT.BIN", user, pass); // Now we'll check and see if a backup exists on the server or not, if we don't have one on the server, then upload one if (!FTP.FileExists($"ftp://{ps3ip}/dev_hdd0/game/{gameID}/USRDIR/EBOOT.BIN.BAK", user, pass)) - FTP.UploadFile(@$"eboot/{gameID}/original/EBOOT.BIN", + FTP.UploadFile(@$"{workingDir}/eboot/{gameID}/original/EBOOT.BIN", $"ftp://{ps3ip}/dev_hdd0/game/{gameID}/USRDIR/EBOOT.BIN.BAK", user, pass); // Check for keys in the data directory - if (!File.Exists("data/keys")) + if (!File.Exists($"./data/keys")) throw new FileNotFoundException( "UnionRemotePatcher cannot find the keys, ldr_curves, or vsh_curves files required to continue. Please make sure you have copies of these files placed in the data directory where you found the executable to run UnionRemotePatcher. Without them, we can't patch your game."); // Decrypt the EBOOT - LaunchSCETool($"-v -d eboot/{gameID}/original/EBOOT.BIN eboot/{gameID}/original/EBOOT.ELF"); + LaunchSCETool($"-v -d {workingDir}/eboot/{gameID}/original/EBOOT.BIN {workingDir}/eboot/{gameID}/original/EBOOT.ELF"); // Now, patch the EBOOT; - Patcher.PatchFile($"eboot/{gameID}/original/EBOOT.ELF", serverURL, $"eboot/{gameID}/patched/EBOOT.ELF"); + Patcher.PatchFile($"{workingDir}/eboot/{gameID}/original/EBOOT.ELF", serverURL, $"{workingDir}/eboot/{gameID}/patched/EBOOT.ELF"); // Encrypt the EBOOT (Disc) LaunchSCETool( - $" -v --sce-type=SELF --skip-sections=FALSE --key-revision=0A --self-app-version=0001000000000000 --self-auth-id=1010000001000003 --self-vendor-id=01000002 --self-ctrl-flags=0000000000000000000000000000000000000000000000000000000000000000 --self-cap-flags=00000000000000000000000000000000000000000000003B0000000100040000 --self-type=APP --self-fw-version=0003005500000000 --compress-data true --encrypt \"{Path.GetFullPath(@$"eboot/{gameID}/patched/EBOOT.ELF")}\" \"{Path.GetFullPath(@$"eboot/{gameID}/patched/EBOOT.BIN")}\""); + $" -v --sce-type=SELF --skip-sections=FALSE --key-revision=0A --self-app-version=0001000000000000 --self-auth-id=1010000001000003 --self-vendor-id=01000002 --self-ctrl-flags=0000000000000000000000000000000000000000000000000000000000000000 --self-cap-flags=00000000000000000000000000000000000000000000003B0000000100040000 --self-type=APP --self-fw-version=0003005500000000 --compress-data true --encrypt \"{Path.GetFullPath(@$"{workingDir}/eboot/{gameID}/patched/EBOOT.ELF")}\" \"{Path.GetFullPath(@$"{workingDir}/eboot/{gameID}/patched/EBOOT.BIN")}\""); // And upload the encrypted, patched EBOOT to the system. - FTP.UploadFile(@$"eboot/{gameID}/patched/EBOOT.BIN", + FTP.UploadFile(@$"{workingDir}/eboot/{gameID}/patched/EBOOT.BIN", $"ftp://{ps3ip}/dev_hdd0/game/{gameID}/USRDIR/EBOOT.BIN", user, pass); } } diff --git a/UnionPatcher/UnionPatcher.csproj b/UnionPatcher/UnionPatcher.csproj index 00942c0..b55e086 100644 --- a/UnionPatcher/UnionPatcher.csproj +++ b/UnionPatcher/UnionPatcher.csproj @@ -3,7 +3,7 @@ LBPUnion.UnionPatcher LBPUnion.UnionPatcher Debug;Release;Windows - net6.0 + net8.0 AnyCPU Icon64.ico diff --git a/build-all.sh b/build-all.sh index daf126a..d9a116c 100755 --- a/build-all.sh +++ b/build-all.sh @@ -1,4 +1,4 @@ -mkdir -p builds; +mkdir -p builds #dotnet clean; dotnet publish -c Windows -r win-x64 --self-contained @@ -13,19 +13,19 @@ dotnet publish -c MacOS -r osx-arm64 --self-contained # $1: Name.zip # $2: Path to zip function createBuild() { - currentDirectory=$(pwd) - cd $2 || return 1; - - zip -r "$1" *; - cd $currentDirectory || return 1; - mv "$2/$1" builds/ + currentDirectory=$(pwd) + cd $2 || return 1 + + zip -r "$1" * + cd $currentDirectory || return 1 + mv "$2/$1" builds/ } -createBuild "UnionPatcher-Windows-x64.zip" "UnionPatcher.Gui.Windows/bin/Release/net6.0-windows/win-x64/publish/" +createBuild "UnionPatcher-Windows-x64.zip" "UnionPatcher.Gui.Windows/bin/Release/net8.0-windows/win-x64/publish/" -createBuild "UnionPatcher-Linux-x64.zip" "UnionPatcher.Gui.Linux/bin/Release/net6.0/linux-x64/publish/" -createBuild "UnionPatcher-Linux-arm.zip" "UnionPatcher.Gui.Linux/bin/Release/net6.0/linux-arm/publish/" -createBuild "UnionPatcher-Linux-arm64.zip" "UnionPatcher.Gui.Linux/bin/Release/net6.0/linux-arm64/publish/" +createBuild "UnionPatcher-Linux-x64.zip" "UnionPatcher.Gui.Linux/bin/Release/net8.0/linux-x64/publish/" +createBuild "UnionPatcher-Linux-arm.zip" "UnionPatcher.Gui.Linux/bin/Release/net8.0/linux-arm/publish/" +createBuild "UnionPatcher-Linux-arm64.zip" "UnionPatcher.Gui.Linux/bin/Release/net8.0/linux-arm64/publish/" -createBuild "UnionPatcher-macOS-x64.zip" "UnionPatcher.Gui.MacOS/bin/Release/net6.0/osx-x64/publish/" -createBuild "UnionPatcher-macOS-arm64.zip" "UnionPatcher.Gui.MacOS/bin/Release/net6.0/osx-arm64/publish/" \ No newline at end of file +# CODESIGN_IDENTITY is the certificate that you want to use for codesigning for mac, if not present then will not be signed +./build-mac.sh $CODESIGN_IDENTITY diff --git a/build-mac.sh b/build-mac.sh new file mode 100755 index 0000000..4e22f6e --- /dev/null +++ b/build-mac.sh @@ -0,0 +1,21 @@ +# Script to build UnionPatcher for mac, builds a universal binary, and zips it up. also codesigns if $1 is specified + +dotnet clean +dotnet publish UnionPatcher.Gui.MacOS --configuration Release /p:Platform="Any CPU" --self-contained -o macbuild +dotnet publish UnionPatcher.Gui.MacOS --configuration Release /p:Platform="Any CPU" --arch x64 --self-contained -o macbuildx86 + +rm -rf macbuilduniversal +mkdir macbuilduniversal +cp -r macbuild/UnionPatcher.Gui.MacOS.app macbuilduniversal/UnionPatcher.app +cp UnionPatcher.Gui.MacOS/Info.plist macbuilduniversal/UnionPatcher.app/Contents/Info.plist +rm -rf macbuilduniversal/UnionPatcher.app/Contents/MacOS/scetool/linux* +rm -rf macbuilduniversal/UnionPatcher.app/Contents/MacOS/scetool/win* + +lipo -create -output macbuilduniversal/UnionPatcher.app/Contents/MacOS/LBPUnion.UnionPatcher.Gui.MacOS macbuildx86/LBPUnion.UnionPatcher.Gui.MacOS macbuild/LBPUnion.UnionPatcher.Gui.MacOS +touch macbuilduniversal/UnionPatcher.app + +if [ -z ${1+x} ]; then + codesign -f --deep -s "$1" macbuilduniversal/UnionPatcher.app +fi +cd macbuilduniversal +zip -r UnionPatcher-macOS-universal.zip UnionPatcher.app