-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 56fe29b
Showing
10 changed files
with
395 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
.idea/ | ||
.vscode/ | ||
/packages/ | ||
bin/ | ||
obj/ | ||
riderModule.iml | ||
/_ReSharper.Caches/ | ||
*.user |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
|
||
Microsoft Visual Studio Solution File, Format Version 12.00 | ||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GenericStripper", "GenericStripper\GenericStripper.csproj", "{512279BF-4F83-447E-B818-CBF94378E222}" | ||
EndProject | ||
Global | ||
GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||
Debug|Any CPU = Debug|Any CPU | ||
Release|Any CPU = Release|Any CPU | ||
EndGlobalSection | ||
GlobalSection(ProjectConfigurationPlatforms) = postSolution | ||
{512279BF-4F83-447E-B818-CBF94378E222}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
{512279BF-4F83-447E-B818-CBF94378E222}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
{512279BF-4F83-447E-B818-CBF94378E222}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
{512279BF-4F83-447E-B818-CBF94378E222}.Release|Any CPU.Build.0 = Release|Any CPU | ||
EndGlobalSection | ||
EndGlobal |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<OutputType>Exe</OutputType> | ||
<TargetFramework>net7.0</TargetFramework> | ||
<ImplicitUsings>enable</ImplicitUsings> | ||
<Nullable>enable</Nullable> | ||
</PropertyGroup> | ||
|
||
|
||
<ItemGroup> | ||
<PackageReference Include="Mono.Cecil" Version="0.11.5"/> | ||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3"/> | ||
<PackageReference Include="Spectre.Console" Version="0.47.1-preview.0.11"/> | ||
<PackageReference Include="Spectre.Console.Cli" Version="0.47.1-preview.0.11"/> | ||
</ItemGroup> | ||
|
||
|
||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
using Mono.Cecil; | ||
|
||
namespace GenericStripper.Modules.BeatSaber; | ||
|
||
public class BsAssemblyModule | ||
{ | ||
private readonly BsLibLoader _bslibLoader; | ||
private readonly FileInfo _file; | ||
private readonly ModuleDefinition _module; | ||
|
||
public BsAssemblyModule(string gamePath, string fileName, params string[] resolverDirs) | ||
{ | ||
_bslibLoader = new BsLibLoader(gamePath); | ||
|
||
_file = new FileInfo(fileName); | ||
if (!_file.Exists) throw new FileNotFoundException("Failed to find assembly to strip!", fileName); | ||
|
||
_module = LoadModules(resolverDirs); | ||
} | ||
|
||
private ModuleDefinition LoadModules(IEnumerable<string> directories) | ||
{ | ||
_bslibLoader.AddSearchDirectory(_file.Directory?.FullName ?? | ||
throw new Exception("Failed to get assembly directory!")); | ||
foreach (var directory in directories) | ||
{ | ||
if (!Directory.Exists(directory)) continue; | ||
_bslibLoader.AddSearchDirectory(directory); | ||
} | ||
|
||
ReaderParameters parameters = new() | ||
{ | ||
AssemblyResolver = _bslibLoader, | ||
ReadingMode = ReadingMode.Immediate, | ||
ReadWrite = false, | ||
InMemory = true | ||
}; | ||
|
||
return ModuleDefinition.ReadModule(_file.FullName, parameters); | ||
} | ||
|
||
public void Virtualize() | ||
{ | ||
foreach (var type in _module.Types) VirtualizeType(type); | ||
} | ||
|
||
private static void VirtualizeType(TypeDefinition type) | ||
{ | ||
if (type.IsSealed) type.IsSealed = false; | ||
|
||
if (type.IsInterface) return; | ||
if (type.IsAbstract) return; | ||
|
||
foreach (var subType in type.NestedTypes) VirtualizeType(subType); | ||
|
||
foreach (var m in type.Methods.Where(m => m.IsManaged | ||
&& m is | ||
{ | ||
IsIL: true, IsStatic: false, IsVirtual: false, IsAbstract: false, | ||
IsAddOn: false, IsConstructor: false, IsSpecialName: false, | ||
IsGenericInstance: false, HasOverrides: false | ||
})) | ||
{ | ||
m.IsVirtual = true; | ||
m.IsPublic = true; | ||
m.IsPrivate = false; | ||
m.IsNewSlot = true; | ||
m.IsHideBySig = true; | ||
} | ||
|
||
foreach (var field in type.Fields.Where(field => field.IsPrivate)) field.IsFamily = true; | ||
} | ||
|
||
public void Strip() | ||
{ | ||
foreach (var type in _module.Types) StripType(type); | ||
} | ||
|
||
private static void StripType(TypeDefinition type) | ||
{ | ||
foreach (var m in type.Methods.Where(m => m.Body != null)) | ||
{ | ||
m.Body.Instructions.Clear(); | ||
m.Body.InitLocals = false; | ||
m.Body.Variables.Clear(); | ||
} | ||
|
||
foreach (var subType in type.NestedTypes) StripType(subType); | ||
} | ||
|
||
public void Write(string outFile) | ||
{ | ||
_module.Write(outFile); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
using Mono.Cecil; | ||
|
||
namespace GenericStripper.Modules.BeatSaber; | ||
|
||
public class BsLibLoader : BaseAssemblyResolver | ||
{ | ||
public BsLibLoader(string gamePath) | ||
{ | ||
_ = new LibLoader(gamePath); | ||
} | ||
|
||
public override AssemblyDefinition Resolve(AssemblyNameReference name, ReaderParameters parameters) | ||
{ | ||
LibLoader.SetupAssemblyFilenames(); | ||
if (LibLoader.FilenameLocations == null) throw new Exception("Failed to setup assembly filenames!"); | ||
|
||
if (LibLoader.FilenameLocations.TryGetValue($"{name.Name}.{name.Version}.dll", out var path)) | ||
{ | ||
if (File.Exists(path)) return AssemblyDefinition.ReadAssembly(path, parameters); | ||
} | ||
else if (LibLoader.FilenameLocations.TryGetValue($"{name.Name}.dll", out path)) | ||
{ | ||
if (File.Exists(path)) return AssemblyDefinition.ReadAssembly(path, parameters); | ||
} | ||
|
||
return base.Resolve(name, parameters); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
using System.Diagnostics; | ||
using System.IO.Compression; | ||
using System.Net; | ||
using System.Runtime.InteropServices; | ||
using Newtonsoft.Json; | ||
using Newtonsoft.Json.Linq; | ||
|
||
namespace GenericStripper.Modules.BeatSaber; | ||
|
||
public class BeatSaber : IModule | ||
{ | ||
private readonly HttpClient _client; | ||
|
||
public BeatSaber(string gamePath) | ||
{ | ||
GamePath = gamePath; | ||
_client = new HttpClient(); | ||
_client.DefaultRequestHeaders.Add("User-Agent", "GenericStripper"); | ||
} | ||
|
||
public string GameName => "Beat Saber"; | ||
public string GamePath { get; } | ||
|
||
public void StripDll(string file, string outDir, params string[] resolveDirs) | ||
{ | ||
if (!File.Exists(file)) throw new FileNotFoundException("Failed to find assembly to strip!", file); | ||
var fileInf = new FileInfo(file); | ||
|
||
var bsAssemblyModule = new BsAssemblyModule(GamePath, file, resolveDirs); | ||
bsAssemblyModule.Virtualize(); | ||
bsAssemblyModule.Strip(); | ||
|
||
Console.WriteLine($"Stripped {fileInf.Name}!"); | ||
|
||
Directory.CreateDirectory(Path.Combine(outDir, Path.GetRelativePath(GamePath, fileInf.Directory!.ToString()))); | ||
var outFile = Path.Combine(outDir, Path.GetRelativePath(GamePath, fileInf.FullName)); | ||
bsAssemblyModule.Write(outFile); | ||
} | ||
|
||
public async Task InstallBsipa() | ||
{ | ||
if (File.Exists(Path.Combine(GamePath, "IPA.exe"))) return; | ||
Console.WriteLine("Installing BSIPA..."); | ||
|
||
var res = await _client.GetAsync( | ||
"https://api.github.com/repos/nike4613/BeatSaber-IPA-Reloaded/releases/latest"); | ||
if (res.StatusCode != HttpStatusCode.OK) throw new Exception("Failed to get latest BSIPA release!"); | ||
|
||
var latestRelease = | ||
JsonConvert.DeserializeObject<Dictionary<string, dynamic>>(await res.Content.ReadAsStringAsync()); | ||
if (latestRelease == null) throw new Exception("Failed to parse BSIPA release!"); | ||
|
||
var assets = latestRelease["assets"] as JArray; | ||
var arch = RuntimeInformation.OSArchitecture.ToString().ToLower(); | ||
var asset = assets?.FirstOrDefault(x => x["name"]?.ToString().Contains(arch) ?? false); | ||
|
||
if (asset == null) throw new Exception("Failed to find a BSIPA asset for this system!"); | ||
|
||
var assetRes = await _client.GetAsync(asset["browser_download_url"]?.ToString()); | ||
if (assetRes.StatusCode != HttpStatusCode.OK) throw new Exception("Failed to download BSIPA asset!"); | ||
|
||
await using var assetStream = await assetRes.Content.ReadAsStreamAsync(); | ||
using var archive = new ZipArchive(assetStream); | ||
archive.ExtractToDirectory(GamePath); | ||
|
||
if (!File.Exists(Path.Combine(GamePath, "IPA.exe"))) throw new Exception("Failed to extract BSIPA asset!"); | ||
|
||
var bsipa = new Process | ||
{ | ||
StartInfo = | ||
{ | ||
FileName = Path.Combine(GamePath, "IPA.exe"), | ||
WorkingDirectory = GamePath, | ||
Arguments = "--nowait" | ||
} | ||
}; | ||
|
||
bsipa.Start(); | ||
await bsipa.WaitForExitAsync(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
namespace GenericStripper.Modules; | ||
|
||
public interface IModule | ||
{ | ||
public string GameName { get; } | ||
|
||
public string GamePath { get; } | ||
|
||
public void StripDll(string file, string outDir, params string[] resolveDirs); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
using System.Diagnostics.CodeAnalysis; | ||
using System.Runtime.InteropServices; | ||
|
||
namespace GenericStripper.Modules; | ||
|
||
[SuppressMessage("Interoperability", | ||
"SYSLIB1054:Use \'LibraryImportAttribute\' instead of \'DllImportAttribute\' to generate P/Invoke marshalling code at compile time")] | ||
public class LibLoader | ||
{ | ||
public LibLoader(string gamePath) | ||
{ | ||
GamePath = gamePath; | ||
} | ||
|
||
private static string GamePath { get; set; } = string.Empty; | ||
private static string LibPath => Path.Combine(GamePath, "Libs"); | ||
private static string NativePath => Path.Combine(LibPath, "Native"); | ||
internal static Dictionary<string, string>? FilenameLocations { get; private set; } | ||
|
||
public static void SetupAssemblyFilenames() | ||
{ | ||
if (FilenameLocations != null) return; | ||
|
||
FilenameLocations = new Dictionary<string, string>(); | ||
var files = Directory.GetFiles(LibPath, "*.dll", SearchOption.AllDirectories); | ||
files = files.Where(f => !f.StartsWith(NativePath)).ToArray(); | ||
|
||
foreach (var file in files) | ||
{ | ||
var filename = Path.GetFileName(file); | ||
FilenameLocations[filename] = file; | ||
} | ||
|
||
if (Directory.Exists(NativePath)) | ||
{ | ||
var ptr = AddDllDirectory(NativePath); | ||
if (ptr == IntPtr.Zero) throw new Exception("Failed to add Native directory to DLL search path!"); | ||
|
||
var nativeDirectories = Directory.GetDirectories(NativePath, "*", SearchOption.AllDirectories); | ||
foreach (var nativeDirectory in nativeDirectories) | ||
{ | ||
ptr = AddDllDirectory(nativeDirectory); | ||
if (ptr == IntPtr.Zero) | ||
throw new Exception($"Failed to add Native directory to DLL search path: {nativeDirectory}"); | ||
} | ||
} | ||
|
||
var unityData = Directory.EnumerateDirectories(GamePath, "*_Data", SearchOption.TopDirectoryOnly).First(); | ||
var unityPlugins = Path.Combine(unityData, "Plugins"); | ||
if (Directory.Exists(unityPlugins)) | ||
{ | ||
var ptr = AddDllDirectory(unityPlugins); | ||
if (ptr == IntPtr.Zero) | ||
throw new Exception($"Failed to add Unity Plugins directory to DLL search path: {unityPlugins}"); | ||
} | ||
|
||
foreach (var dir in Environment.GetEnvironmentVariable("path")?.Split(Path.PathSeparator) ?? | ||
Array.Empty<string>()) | ||
{ | ||
if (!Directory.Exists(dir)) continue; | ||
|
||
var ptr = AddDllDirectory(dir); | ||
if (ptr == IntPtr.Zero) throw new Exception($"Failed to add directory to DLL search path: {dir}"); | ||
} | ||
} | ||
|
||
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] | ||
private static extern IntPtr AddDllDirectory(string lpPathName); | ||
} |
Oops, something went wrong.