Skip to content

Commit a6a95b1

Browse files
committed
Allow patcher to resign and replace executable
1 parent 84c05ec commit a6a95b1

File tree

8 files changed

+87
-27
lines changed

8 files changed

+87
-27
lines changed

Refresher.sln.DotSettings

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,5 @@
2424
<s:Boolean x:Key="/Default/UserDictionary/Words/=Reverify/@EntryIndexedValue">True</s:Boolean>
2525
<s:Boolean x:Key="/Default/UserDictionary/Words/=RFSH/@EntryIndexedValue">True</s:Boolean>
2626
<s:Boolean x:Key="/Default/UserDictionary/Words/=RPCS/@EntryIndexedValue">True</s:Boolean>
27-
<s:Boolean x:Key="/Default/UserDictionary/Words/=USRDIR/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
27+
<s:Boolean x:Key="/Default/UserDictionary/Words/=USRDIR/@EntryIndexedValue">True</s:Boolean>
28+
<s:Boolean x:Key="/Default/UserDictionary/Words/=webman/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

Refresher/Accessors/ConsolePatchAccessor.cs

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,42 +15,40 @@ public ConsolePatchAccessor(string remoteIp)
1515
this._client.AutoConnect();
1616
}
1717

18-
private string GetPath(string path)
18+
private static string GetPath(string path)
1919
{
2020
if (Path.IsPathRooted(path)) return path;
2121
return BasePath + path;
2222
}
2323

24-
public override bool DirectoryExists(string path) => this._client.DirectoryExists(this.GetPath(path));
24+
public override bool DirectoryExists(string path) => this._client.DirectoryExists(GetPath(path));
2525

26-
public override bool FileExists(string path) => this._client.FileExists(this.GetPath(path));
26+
public override bool FileExists(string path) => this._client.FileExists(GetPath(path));
2727

2828
public override IEnumerable<string> GetDirectoriesInDirectory(string path) =>
29-
this._client.GetListing(this.GetPath(path))
29+
this._client.GetListing(GetPath(path))
3030
.Where(l => l.Type == FtpObjectType.Directory)
3131
.Select(l => l.FullName);
3232

3333
public override IEnumerable<string> GetFilesInDirectory(string path) =>
34-
this._client.GetListing(this.GetPath(path))
34+
this._client.GetListing(GetPath(path))
3535
.Where(l => l.Type == FtpObjectType.File)
3636
.Select(l => l.FullName);
3737

3838
public override Stream OpenRead(string path)
3939
{
4040
MemoryStream ms = new();
41-
this._client.DownloadStream(ms, this.GetPath(path));
41+
this._client.DownloadStream(ms, GetPath(path));
4242
ms.Seek(0, SeekOrigin.Begin);
4343
return ms;
4444

4545
// technically we can use a stream directly but this uses a lot more requests
46-
// and webman doesnt like that
47-
return this._client.OpenRead(this.GetPath(path));
46+
// and webman doesnt like that, it tends to just slow down to a crawl after a bunch of them :(
47+
// return this._client.OpenRead(GetPath(path));
4848
}
4949

50-
public override Stream OpenWrite(string path)
51-
{
52-
return this._client.OpenWrite(this.GetPath(path));
53-
}
50+
public override Stream OpenWrite(string path) => this._client.OpenWrite(GetPath(path));
51+
public override void RemoveFile(string path) => this._client.DeleteFile(GetPath(path));
5452

5553
public void Dispose()
5654
{

Refresher/Accessors/EmulatorPatchAccessor.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,8 @@ private string GetPath(string path)
2323

2424
public override Stream OpenRead(string path) => File.OpenRead(this.GetPath(path));
2525
public override Stream OpenWrite(string path) => File.OpenWrite(this.GetPath(path));
26+
public override void RemoveFile(string path) => File.Delete(this.GetPath(path));
27+
28+
public override void DuplicateFile(string inPath, string outPath)
29+
=> File.Copy(this.GetPath(inPath), this.GetPath(outPath));
2630
}

Refresher/Accessors/PatchAccessor.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ public abstract class PatchAccessor
88
public abstract IEnumerable<string> GetFilesInDirectory(string path);
99
public abstract Stream OpenRead(string path);
1010
public abstract Stream OpenWrite(string path);
11+
public abstract void RemoveFile(string path);
1112

1213
public string DownloadFile(string path)
1314
{
@@ -27,4 +28,12 @@ public void UploadFile(string inPath, string outPath)
2728

2829
inStream.CopyTo(outStream);
2930
}
31+
32+
public virtual void DuplicateFile(string inPath, string outPath)
33+
{
34+
using Stream inStream = this.OpenRead(inPath);
35+
using Stream outStream = this.OpenWrite(outPath);
36+
37+
inStream.CopyTo(outStream);
38+
}
3039
}

Refresher/Refresher.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
<EmbeddedResource Include="Resources\refresher.ico" LogicalName="refresher.ico" />
2323
<PackageReference Include="FluentFTP" Version="47.1.0" />
2424
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
25-
<PackageReference Include="SCEToolSharp" Version="1.0.7" />
25+
<PackageReference Include="SCEToolSharp" Version="1.0.8" />
2626
</ItemGroup>
2727

2828

Refresher/UI/ConsolePatchForm.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,7 @@ protected override TableRow AddRemoteField()
2222
{
2323
return AddField("PS3's IP", out this._remoteAddress);
2424
}
25+
26+
protected override bool NeedsResign => true;
27+
protected override bool ShouldReplaceExecutable => true;
2528
}

Refresher/UI/EmulatorPatchForm.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,7 @@ protected override TableRow AddRemoteField()
4343
{
4444
return AddField("RPCS3 dev_hdd0 folder", out this._folderField);
4545
}
46+
47+
protected override bool NeedsResign => false;
48+
protected override bool ShouldReplaceExecutable => false;
4649
}

Refresher/UI/IntegratedPatchForm.cs

Lines changed: 55 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Diagnostics;
2+
using System.Diagnostics.CodeAnalysis;
23
using Eto.Drawing;
34
using Eto.Forms;
45
using Refresher.Accessors;
@@ -12,7 +13,7 @@ namespace Refresher.UI;
1213
public abstract class IntegratedPatchForm : PatchForm<Patcher>
1314
{
1415
private readonly DropDown _gameDropdown;
15-
private readonly TextBox _outputField;
16+
private readonly TextBox? _outputField;
1617

1718
private string _tempFile;
1819
private string _usrDir;
@@ -21,18 +22,22 @@ public abstract class IntegratedPatchForm : PatchForm<Patcher>
2122

2223
protected override TableLayout FormPanel { get; }
2324

25+
[SuppressMessage("ReSharper", "VirtualMemberCallInConstructor")]
2426
protected IntegratedPatchForm(string subtitle) : base(subtitle)
2527
{
2628
this.FormPanel = new TableLayout(new List<TableRow>
2729
{
28-
// ReSharper disable once VirtualMemberCallInConstructor
2930
this.AddRemoteField(),
3031
AddField("Game to patch", out this._gameDropdown),
3132
AddField("Server URL", out this.UrlField),
32-
AddField("Identifier (EBOOT.<value>.elf)", out this._outputField),
3333
});
34+
35+
if (!this.ShouldReplaceExecutable)
36+
{
37+
this.FormPanel.Rows.Add(AddField("Identifier (EBOOT.<value>.elf)", out this._outputField));
38+
this._outputField!.PlaceholderText = "refresh";
39+
}
3440

35-
this._outputField.PlaceholderText = "refresh";
3641
this._gameDropdown.SelectedValueChanged += this.GameChanged;
3742

3843
this.InitializePatcher();
@@ -93,13 +98,21 @@ protected void GameChanged(object? sender, EventArgs ev)
9398

9499
string licenseDir = Path.Join(Path.GetTempPath(), "refresher-" + Random.Shared.Next());
95100
Directory.CreateDirectory(licenseDir);
96-
IEnumerable<string> licenseFiles = this.Accessor.GetFilesInDirectory(Path.Combine("home", "00000001", "exdata"));
97-
98-
foreach (string licenseFile in licenseFiles)
101+
102+
// if this is a NP game then download RIFs/RAPs, disc copies don't need anything else
103+
if (game.TitleId.StartsWith('N'))
99104
{
100-
if(!licenseFile.Contains(game.TitleId)) continue;
101-
string downloadedFile = this.Accessor.DownloadFile(licenseFile);
102-
File.Move(downloadedFile, Path.Join(licenseDir, Path.GetFileName(licenseFile)));
105+
// TODO: the first user might not have the licenses necessary, should download from all users
106+
IEnumerable<string> licenseFiles = this.Accessor.GetFilesInDirectory(Path.Combine("home", "00000001", "exdata"));
107+
foreach (string licenseFile in licenseFiles)
108+
{
109+
// only download if it contains our game's title id
110+
// TODO: determine content id directly so we skip dlc licenses
111+
if(!licenseFile.Contains(game.TitleId)) continue;
112+
113+
string downloadedFile = this.Accessor.DownloadFile(licenseFile);
114+
File.Move(downloadedFile, Path.Join(licenseDir, Path.GetFileName(licenseFile)));
115+
}
103116
}
104117

105118
this.LogMessage($"EBOOT Path: {ebootPath}");
@@ -123,11 +136,38 @@ protected void GameChanged(object? sender, EventArgs ev)
123136

124137
public override void CompletePatch(object? sender, EventArgs e) {
125138
Debug.Assert(this.Accessor != null);
126-
string identifier = string.IsNullOrWhiteSpace(this._outputField.Text) ? this._outputField.PlaceholderText : this._outputField.Text;
127139

128-
string destination = Path.Combine(this._usrDir, $"EBOOT.{identifier}.elf");
140+
string? identifier = string.IsNullOrWhiteSpace(this._outputField?.Text) ? this._outputField?.PlaceholderText : this._outputField?.Text;
141+
identifier ??= "";
142+
143+
string fileToUpload;
144+
if (this.NeedsResign)
145+
{
146+
string encryptedTempFile = Path.GetTempFileName();
147+
LibSceToolSharp.SetDiscEncryptOptions();
148+
LibSceToolSharp.Encrypt(this._tempFile, encryptedTempFile);
149+
150+
fileToUpload = encryptedTempFile;
151+
}
152+
else
153+
{
154+
fileToUpload = this._tempFile;
155+
}
156+
157+
string destinationFile = this.ShouldReplaceExecutable ? "EBOOT.BIN" : $"EBOOT.{identifier}.BIN";
158+
string destination = Path.Combine(this._usrDir, destinationFile);
159+
160+
// if we're replacing the executable, back it up to EBOOT.BIN.ORIG before we do so
161+
if (this.ShouldReplaceExecutable)
162+
{
163+
string backup = destination + ".ORIG";
164+
if (!this.Accessor.FileExists(backup))
165+
this.Accessor.DuplicateFile(destination, backup);
166+
167+
this.Accessor.RemoveFile(destination);
168+
}
129169

130-
this.Accessor.UploadFile(this._tempFile, destination);
170+
this.Accessor.UploadFile(fileToUpload, destination);
131171
MessageBox.Show($"Successfully patched EBOOT! It was saved to '{destination}'.");
132172

133173
// Re-initialize patcher so we can patch with the same parameters again
@@ -136,4 +176,6 @@ public override void CompletePatch(object? sender, EventArgs e) {
136176
}
137177

138178
protected abstract TableRow AddRemoteField();
179+
protected abstract bool NeedsResign { get; }
180+
protected abstract bool ShouldReplaceExecutable { get; }
139181
}

0 commit comments

Comments
 (0)