diff --git a/UnionPatcher.Gui/MainForm.cs b/UnionPatcher.Gui/MainForm.cs
index 9276123..4c75668 100644
--- a/UnionPatcher.Gui/MainForm.cs
+++ b/UnionPatcher.Gui/MainForm.cs
@@ -1,4 +1,5 @@
using System;
+using System.IO;
using System.Diagnostics;
using Eto;
using Eto.Drawing;
@@ -21,14 +22,14 @@ namespace LBPUnion.UnionPatcher.Gui {
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();
@@ -42,10 +43,10 @@ namespace LBPUnion.UnionPatcher.Gui {
button.Click += delegate {
dialog.Close();
};
-
+
return dialog;
}
-
+
public Control CreatePatchButton(int tabIndex = 0) {
Button control = new() {
Text = EasterEgg.Restitch ? "Restitch!" : "Patch!",
@@ -53,21 +54,38 @@ namespace LBPUnion.UnionPatcher.Gui {
};
control.Click += delegate {
- if(string.IsNullOrEmpty(this.filePicker.FilePath)) {
+ if(string.IsNullOrWhiteSpace(this.filePicker.FilePath)) {
this.CreateOkDialog("Form Error", "No file specified!").ShowModal();
return;
}
- if(string.IsNullOrEmpty(this.serverUrl.Text)) {
+ if(string.IsNullOrWhiteSpace(this.serverUrl.Text)) {
this.CreateOkDialog("Form Error", "No server URL specified!").ShowModal();
return;
}
- if(string.IsNullOrEmpty(this.outputFileName.FilePath)) {
+ if(string.IsNullOrWhiteSpace(this.outputFileName.FilePath)) {
this.CreateOkDialog("Form Error", "No output file specified!").ShowModal();
return;
}
+ ElfFile eboot = new(this.filePicker.FilePath);
+
+ if(eboot.IsValid == false) {
+ this.CreateOkDialog("Eboot Error", $"{eboot.Name} is not a valid ELF file (magic number mismatch)").ShowModal();
+ return;
+ }
+
+ if(eboot.Is64Bit == null) {
+ this.CreateOkDialog("Eboot Error", $"{eboot.Name} does not target a valid system").ShowModal();
+ return;
+ }
+
+ if(string.IsNullOrWhiteSpace(eboot.Architecture)) {
+ this.CreateOkDialog("Eboot Error", $"{eboot.Name} does not target a valid architecture (PowerPC or ARM)").ShowModal();
+ return;
+ }
+
try {
Patcher.PatchFile(this.filePicker.FilePath, this.serverUrl.Text, this.outputFileName.FilePath);
}
@@ -87,7 +105,7 @@ namespace LBPUnion.UnionPatcher.Gui {
Text = "Help",
TabIndex = tabIndex,
};
-
+
control.Click += delegate {
Process process = new();
@@ -98,7 +116,7 @@ namespace LBPUnion.UnionPatcher.Gui {
return control;
}
-
+
public MainForm() {
this.Title = EasterEgg.Restitch ? "Union Restitcher" : "Union Patcher";
this.ClientSize = new Size(500, -1);
@@ -126,4 +144,4 @@ namespace LBPUnion.UnionPatcher.Gui {
};
}
}
-}
\ No newline at end of file
+}
diff --git a/UnionPatcher/ElfFile.cs b/UnionPatcher/ElfFile.cs
new file mode 100644
index 0000000..b578773
--- /dev/null
+++ b/UnionPatcher/ElfFile.cs
@@ -0,0 +1,74 @@
+using System;
+using System.IO;
+using System.Linq;
+using System.Buffers.Binary;
+
+/*
+Linux ELF header refspec: https://refspecs.linuxfoundation.org/elf/gabi4+/ch4.eheader.html
+Wikipedia entry on ELF: https://en.wikipedia.org/wiki/Executable_and_Linkable_Format
+*/
+
+namespace LBPUnion.UnionPatcher {
+ public class ElfFile {
+ private enum WordSize : byte {
+ ThirtyTwoBits = 0x01,
+ SixtyFourBits = 0x02
+ }
+
+ private enum Endianness : byte {
+ Little = 0x01,
+ Big = 0x02
+ }
+
+ private enum InstructionSetArchitecture : UInt16 {
+ PowerPC = 0x15, //64-bit PowerPC (PS3)
+ ARM = 0x28 //32-bit ARM (Vita)
+ }
+
+ public string Name { get; } = "Binary Blob";
+
+ public bool IsValid { get; }
+ public bool? Is64Bit { get; } = null;
+ public bool? IsBigEndian { get; } = null;
+ public string Architecture { get; } = null;
+
+ public byte[] Contents { get; } = null;
+
+ public ElfFile(byte[] fileContents) {
+ IsValid = fileContents[0x00..0x04].SequenceEqual(new byte[] {0x7F, (byte)'E', (byte)'L', (byte)'F'});
+ if(IsValid == false) return;
+
+ byte identClassValue = fileContents[0x04];
+ byte identDataValue = fileContents[0x05];
+
+ if(identClassValue == (byte)WordSize.ThirtyTwoBits || identClassValue == (byte)WordSize.SixtyFourBits)
+ Is64Bit = identClassValue == (byte)WordSize.SixtyFourBits;
+
+ if(identDataValue == (byte)Endianness.Little || identDataValue == (byte)Endianness.Big)
+ IsBigEndian = identDataValue == (byte)Endianness.Big;
+
+ Architecture = GetFileArchitecture(fileContents, IsBigEndian == true);
+
+ Contents = fileContents;
+ }
+
+ public ElfFile(FileInfo file) : this(File.ReadAllBytes(file.FullName)) {
+ Name = file.Name;
+ }
+
+ public ElfFile(string fileName) : this(new FileInfo(fileName)) {}
+
+ private string GetFileArchitecture(byte[] elfHeader, bool isBigEndian) {
+ byte[] architectureBytes = elfHeader[0x12..0x14];
+ UInt16 fileArch = (isBigEndian) ?
+ BinaryPrimitives.ReadUInt16BigEndian(architectureBytes) :
+ BinaryPrimitives.ReadUInt16LittleEndian(architectureBytes);
+
+ foreach(InstructionSetArchitecture arch in Enum.GetValues(typeof(InstructionSetArchitecture))) {
+ if(fileArch == (UInt16)arch)
+ return arch.ToString();
+ }
+ return null;
+ }
+ }
+}
diff --git a/UnionPatcher/Program.cs b/UnionPatcher/Program.cs
index 371ff24..de1881e 100644
--- a/UnionPatcher/Program.cs
+++ b/UnionPatcher/Program.cs
@@ -15,13 +15,32 @@ namespace LBPUnion.UnionPatcher {
return fileName = Path.GetFileName(Process.GetCurrentProcess().MainModule?.FileName);
}
}
-
+
public static void Main(string[] args) {
if(args.Length < 3) {
PrintHelp();
return;
}
-
+
+ ElfFile eboot = new(new FileInfo(args[0]));
+
+ if(eboot.IsValid == false) {
+ Console.WriteLine($"{eboot.Name} is not a valid ELF file (magic number mismatch)");
+ return;
+ }
+
+ if(eboot.Is64Bit == null) {
+ Console.WriteLine($"{eboot.Name} does not target a valid system");
+ return;
+ }
+
+ if(string.IsNullOrWhiteSpace(eboot.Architecture)) {
+ Console.WriteLine($"{eboot.Name} does not target a valid architecture (PowerPC or ARM)");
+ return;
+ }
+
+ Console.WriteLine($"{eboot.Name} targets {eboot.Architecture}");
+
Patcher.PatchFile(args[0], args[1], args[2]);
Console.WriteLine($"Successfully patched Server URL to {args[1]}.");
}
@@ -31,4 +50,4 @@ namespace LBPUnion.UnionPatcher {
Console.WriteLine($" Usage: {FileName}