Add Installing Firmware

This commit is contained in:
Stossy11 2024-12-18 19:11:37 +11:00
parent 06f3c6d20e
commit 63427eb744
8 changed files with 210 additions and 3 deletions

View File

@ -639,6 +639,10 @@
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
); );
MARKETING_VERSION = 0.0.8; MARKETING_VERSION = 0.0.8;
PRODUCT_BUNDLE_IDENTIFIER = com.stossy11.MeloNX; PRODUCT_BUNDLE_IDENTIFIER = com.stossy11.MeloNX;
@ -790,6 +794,10 @@
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
"$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries",
); );
MARKETING_VERSION = 0.0.8; MARKETING_VERSION = 0.0.8;
PRODUCT_BUNDLE_IDENTIFIER = com.stossy11.MeloNX; PRODUCT_BUNDLE_IDENTIFIER = com.stossy11.MeloNX;

View File

@ -14,8 +14,8 @@
filePath = "MeloNX/Views/GamesList/GameListView.swift" filePath = "MeloNX/Views/GamesList/GameListView.swift"
startingColumnNumber = "9223372036854775807" startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807" endingColumnNumber = "9223372036854775807"
startingLineNumber = "195" startingLineNumber = "256"
endingLineNumber = "195" endingLineNumber = "256"
landmarkName = "loadGames()" landmarkName = "loadGames()"
landmarkType = "7"> landmarkType = "7">
</BreakpointContent> </BreakpointContent>

View File

@ -26,7 +26,11 @@ struct GameInfo {
}; };
extern struct GameInfo get_game_info(int, char*); extern struct GameInfo get_game_info(int, char*);
// Declare the main_ryujinx_sdl function, matching the signature
void install_firmware(const char* inputPtr);
char* installed_firmware_version();
int main_ryujinx_sdl(int argc, char **argv); int main_ryujinx_sdl(int argc, char **argv);
void initialize(); void initialize();

View File

@ -34,6 +34,7 @@ class Ryujinx {
let virtualController = VirtualController() let virtualController = VirtualController()
@Published var controllerMap: [Controller] = [] @Published var controllerMap: [Controller] = []
@State var firmwareversion = "0"
static let shared = Ryujinx() static let shared = Ryujinx()
@ -197,6 +198,38 @@ class Ryujinx {
return args return args
} }
func fetchFirmwareVersion() -> String {
do {
let firmwareVersionPointer = installed_firmware_version()
if let pointer = firmwareVersionPointer {
let firmwareVersion = String(cString: pointer)
DispatchQueue.main.async {
self.firmwareversion = firmwareVersion
}
return firmwareVersion
}
} catch {
print(error)
}
return "0"
}
func installFirmware(firmwarePath: String) {
guard let cString = firmwarePath.cString(using: .utf8) else {
print("Invalid firmware path")
return
}
install_firmware(cString)
let version = fetchFirmwareVersion()
if !version.isEmpty {
self.firmwareversion = version
}
}
func getConnectedControllers() -> [Controller] { func getConnectedControllers() -> [Controller] {
@ -227,6 +260,38 @@ class Ryujinx {
return controllers return controllers
} }
func removeFirmware() {
let fileManager = FileManager.default
let documentsfolder = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first!
let bisFolder = documentsfolder.appendingPathComponent("bis")
let systemFolder = bisFolder.appendingPathComponent("system")
let contentsFolder = systemFolder.appendingPathComponent("Contents")
let registeredFolder = contentsFolder.appendingPathComponent("registered").path
do {
if fileManager.fileExists(atPath: registeredFolder) {
try fileManager.removeItem(atPath: registeredFolder)
print("Folder removed successfully.")
let version = fetchFirmwareVersion()
if version.isEmpty {
self.firmwareversion = "0"
} else {
print("Firmware eeeeee \(version)")
}
} else {
print("Folder does not exist.")
}
} catch {
print("Error removing folder: \(error)")
}
}

View File

@ -17,6 +17,8 @@ struct GameLibraryView: View {
@AppStorage("recentGames") private var recentGamesData: Data = Data() @AppStorage("recentGames") private var recentGamesData: Data = Data()
@State private var recentGames: [Game] = [] @State private var recentGames: [Game] = []
@Environment(\.colorScheme) var colorScheme @Environment(\.colorScheme) var colorScheme
@State var firmwareInstaller = false
@State var firmwareversion = "0"
var filteredGames: [Game] { var filteredGames: [Game] {
if searchText.isEmpty { if searchText.isEmpty {
@ -104,6 +106,42 @@ struct GameLibraryView: View {
.onAppear { .onAppear {
loadGames() loadGames()
loadRecentGames() loadRecentGames()
let firmware = Ryujinx.shared.fetchFirmwareVersion()
firmwareversion = (firmware == "" ? "0" : firmware)
}
}
.toolbar {
ToolbarItem(placement: .topBarLeading) {
Menu {
Button {
} label: {
Text("Firmware Version: \(firmwareversion)")
.tint(.white)
}
if firmwareversion == "0" {
Button {
firmwareInstaller.toggle()
} label: {
Text("Install Firmware")
}
} else {
Button {
Ryujinx.shared.removeFirmware()
let firmware = Ryujinx.shared.fetchFirmwareVersion()
firmwareversion = (firmware == "" ? "0" : firmware)
} label: {
Text("Remove Firmware")
}
}
} label: {
Image(systemName: "plus")
.foregroundColor(.blue)
}
} }
} }
} }
@ -112,8 +150,31 @@ struct GameLibraryView: View {
.onChange(of: searchText) { _ in .onChange(of: searchText) { _ in
isSearching = !searchText.isEmpty isSearching = !searchText.isEmpty
} }
.fileImporter(isPresented: $firmwareInstaller, allowedContentTypes: [.item]) { result in
switch result {
case .success(let url):
do {
let fun = url.startAccessingSecurityScopedResource()
let path = url.path
Ryujinx.shared.installFirmware(firmwarePath: path)
firmwareversion = (Ryujinx.shared.fetchFirmwareVersion() == "" ? "0" : Ryujinx.shared.fetchFirmwareVersion())
if fun {
url.stopAccessingSecurityScopedResource()
}
}
case .failure(let error):
print(error)
}
}
} }
private func addToRecentGames(_ game: Game) { private func addToRecentGames(_ game: Game) {
recentGames.removeAll { $0.id == game.id } recentGames.removeAll { $0.id == game.id }

View File

@ -282,6 +282,13 @@ struct SettingsView: View {
} label: { } label: {
Text("Advanced Options") Text("Advanced Options")
} }
Button {
Ryujinx.shared.removeFirmware()
} label: {
Text("Remove Firmware")
}
} header: { } header: {
Text("Advanced") Text("Advanced")
.font(.title3.weight(.semibold)) .font(.title3.weight(.semibold))

View File

@ -226,6 +226,68 @@ namespace Ryujinx.Headless.SDL2
} }
[UnmanagedCallersOnly(EntryPoint = "install_firmware")]
public static void InstallFirmwareNative(IntPtr inputPtr)
{
try
{
if (inputPtr == IntPtr.Zero)
{
Console.Error.WriteLine("Error: inputPtr is null.");
return;
}
string inputString = Marshal.PtrToStringAnsi(inputPtr);
if (string.IsNullOrEmpty(inputString))
{
Console.Error.WriteLine("Error: inputString is null or empty.");
return;
}
InstallFirmware(inputString);
}
catch (Exception ex)
{
Console.Error.WriteLine($"Error in InstallFirmwareNative: {ex.Message}");
}
}
public static void InstallFirmware(string filePath)
{
if (string.IsNullOrEmpty(filePath))
{
throw new ArgumentException("File path cannot be null or empty.", nameof(filePath));
}
if (_contentManager == null)
{
throw new InvalidOperationException("_contentManager is not initialized.");
}
_contentManager.InstallFirmware(filePath);
}
[UnmanagedCallersOnly(EntryPoint = "installed_firmware_version")]
public static IntPtr GetInstalledFirmwareVersionNative()
{
var result = GetInstalledFirmwareVersion();
return Marshal.StringToHGlobalAnsi(result);
}
public static string GetInstalledFirmwareVersion()
{
var version = _contentManager.GetCurrentFirmwareVersion();
if (version != null)
{
return version.VersionString;
}
return String.Empty;
}
[UnmanagedCallersOnly(EntryPoint = "get_game_controllers")] [UnmanagedCallersOnly(EntryPoint = "get_game_controllers")]
public static unsafe IntPtr GetGamepadList() public static unsafe IntPtr GetGamepadList()