forked from MeloNX/MeloNX
Add Installing Firmware
This commit is contained in:
parent
06f3c6d20e
commit
63427eb744
@ -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;
|
||||||
|
Binary file not shown.
@ -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>
|
||||||
|
@ -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();
|
||||||
|
@ -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)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -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 }
|
||||||
|
|
||||||
|
@ -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))
|
||||||
|
@ -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()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user