diff --git a/src/MeloNX/MeloNX.xcodeproj/project.xcworkspace/xcuserdata/stossy11.xcuserdatad/UserInterfaceState.xcuserstate b/src/MeloNX/MeloNX.xcodeproj/project.xcworkspace/xcuserdata/stossy11.xcuserdatad/UserInterfaceState.xcuserstate index 8f16c7229..ecd81e663 100644 Binary files a/src/MeloNX/MeloNX.xcodeproj/project.xcworkspace/xcuserdata/stossy11.xcuserdatad/UserInterfaceState.xcuserstate and b/src/MeloNX/MeloNX.xcodeproj/project.xcworkspace/xcuserdata/stossy11.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/src/MeloNX/MeloNX.xcodeproj/xcuserdata/stossy11.xcuserdatad/xcschemes/xcschememanagement.plist b/src/MeloNX/MeloNX.xcodeproj/xcuserdata/stossy11.xcuserdatad/xcschemes/xcschememanagement.plist index 62375ba69..8ff6cf524 100644 --- a/src/MeloNX/MeloNX.xcodeproj/xcuserdata/stossy11.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/src/MeloNX/MeloNX.xcodeproj/xcuserdata/stossy11.xcuserdatad/xcschemes/xcschememanagement.plist @@ -12,12 +12,12 @@ Ryujinx.xcscheme_^#shared#^_ orderHint - 1 + 2 com.Stossy11.MeloNX.RyujinxAg.xcscheme_^#shared#^_ orderHint - 2 + 1 SuppressBuildableAutocreation diff --git a/src/MeloNX/MeloNX/App/Core/Headers/Ryujinx-Header.h b/src/MeloNX/MeloNX/App/Core/Headers/Ryujinx-Header.h index fee1cb5dd..4443e6841 100644 --- a/src/MeloNX/MeloNX/App/Core/Headers/Ryujinx-Header.h +++ b/src/MeloNX/MeloNX/App/Core/Headers/Ryujinx-Header.h @@ -9,7 +9,7 @@ #define RyujinxHeader -#import "SDL2/SDL.h" +#include #import "utils.h" #ifdef __cplusplus @@ -40,8 +40,6 @@ int get_current_fps(); void initialize(); -const char* get_game_controllers(); - #ifdef __cplusplus } #endif diff --git a/src/MeloNX/MeloNX/App/Core/Ryujinx/Controller/WaitforVC.swift b/src/MeloNX/MeloNX/App/Core/Ryujinx/Controller/WaitforVC.swift index ab11205de..85698d639 100644 --- a/src/MeloNX/MeloNX/App/Core/Ryujinx/Controller/WaitforVC.swift +++ b/src/MeloNX/MeloNX/App/Core/Ryujinx/Controller/WaitforVC.swift @@ -10,64 +10,48 @@ import GameController import UIKit import SwiftUI -func waitforcontroller() { - if let window = theWindow { - // Function to recursively search for GCControllerView - func findGCControllerView(in view: UIView) -> UIView? { - // Check if current view is GCControllerView - if String(describing: type(of: view)) == "ControllerView" { - return view - } - - // Search through subviews - for subview in view.subviews { - if let found = findGCControllerView(in: subview) { - return found - } - } - - return nil +var hostingController: UIHostingController? // Store reference to prevent deallocation + +func waitForController() { + guard let window = theWindow else { return } + + // Function to search for an existing UIHostingController with ControllerView + func findGCControllerView(in view: UIView) -> UIHostingController? { + if let hostingVC = view.next as? UIHostingController { + return hostingVC } - let controllerView = ControllerView() - let controllerHostingController = UIHostingController(rootView: controllerView) - let containerView = TransparentHostingContainerView(frame: window.bounds) - containerView.backgroundColor = .clear - - controllerHostingController.view.frame = containerView.bounds - controllerHostingController.view.backgroundColor = .clear - containerView.addSubview(controllerHostingController.view) + for subview in view.subviews { + if let found = findGCControllerView(in: subview) { + return found + } + } - class LandscapeViewController: UIViewController { - override var supportedInterfaceOrientations: UIInterfaceOrientationMask { - return .landscape + return nil + } + + let controllerView = ControllerView() + let newHostingController = UIHostingController(rootView: controllerView) + + // Store reference globally to prevent deallocation + hostingController = newHostingController + + let containerView = newHostingController.view! + containerView.backgroundColor = .clear + containerView.frame = window.bounds + containerView.autoresizingMask = [.flexibleWidth, .flexibleHeight] + + Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { timer in + if findGCControllerView(in: window) == nil { + window.addSubview(containerView) + window.bringSubviewToFront(containerView) + + if let sdlWindow = SDL_GetWindowFromID(1) { + SDL_SetWindowPosition(sdlWindow, 0, 0) } - override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation { - return .landscapeLeft - } + timer.invalidate() // Stop the timer after adding the view } - - let landscapeVC = LandscapeViewController() - landscapeVC.modalPresentationStyle = .fullScreen - window.rootViewController?.present(landscapeVC, animated: false, completion: nil) - - Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { timer in - if findGCControllerView(in: window) == nil { - window.addSubview(containerView) - - window.bringSubviewToFront(containerView) - - let window = SDL_GetWindowFromID(1) - - SDL_SetWindowPosition(window, 0, 0); - - timer.invalidate() - } else { - timer.invalidate() - } - } - } } diff --git a/src/MeloNX/MeloNX/App/Core/Ryujinx/Display/DisplayVisible.swift b/src/MeloNX/MeloNX/App/Core/Ryujinx/Display/DisplayVisible.swift index fe97bd84d..b122900ec 100644 --- a/src/MeloNX/MeloNX/App/Core/Ryujinx/Display/DisplayVisible.swift +++ b/src/MeloNX/MeloNX/App/Core/Ryujinx/Display/DisplayVisible.swift @@ -23,10 +23,7 @@ extension UIWindow { if UserDefaults.standard.bool(forKey: "isVirtualController") { if let window = theWindow { - - - - waitforcontroller() + waitForController() } } } diff --git a/src/MeloNX/MeloNX/App/Core/Ryujinx/Ryujinx.swift b/src/MeloNX/MeloNX/App/Core/Ryujinx/Ryujinx.swift index 43388bda7..787393766 100644 --- a/src/MeloNX/MeloNX/App/Core/Ryujinx/Ryujinx.swift +++ b/src/MeloNX/MeloNX/App/Core/Ryujinx/Ryujinx.swift @@ -279,35 +279,58 @@ class Ryujinx { } } - func getConnectedControllers() -> [Controller] { - + private func generateGamepadId(joystickIndex: Int32) -> String? { + var guid = SDL_JoystickGetDeviceGUID(joystickIndex) - guard let jsonPtr = get_game_controllers() else { - return [] + if guid.data.0 == 0 && guid.data.1 == 0 && guid.data.2 == 0 && guid.data.3 == 0 { + return nil } - - // Convert the unmanaged memory (C string) to a Swift String - let jsonString = String(cString: jsonPtr) - + + let reorderedGUID: [UInt8] = [ + guid.data.3, guid.data.2, guid.data.1, guid.data.0, + guid.data.5, guid.data.4, + guid.data.7, guid.data.6, + guid.data.8, guid.data.9, + guid.data.10, guid.data.11, guid.data.12, guid.data.13, guid.data.14, guid.data.15 + ] + + let guidString = reorderedGUID.map { String(format: "%02X", $0) }.joined().lowercased() + + func substring(_ str: String, _ start: Int, _ end: Int) -> String { + let startIdx = str.index(str.startIndex, offsetBy: start) + let endIdx = str.index(str.startIndex, offsetBy: end) + return String(str[startIdx.. [Controller] { var controllers: [Controller] = [] - - // Splitting the string by newline - let lines = jsonString.components(separatedBy: "\n") - - // Parsing each line - for line in lines { - if line.contains(":") { - let parts = line.components(separatedBy: ":") - if parts.count == 2 { - let id = parts[0].trimmingCharacters(in: .whitespacesAndNewlines) - let name = parts[1].trimmingCharacters(in: .whitespacesAndNewlines) - controllers.append(Controller(id: id, name: name)) + + let numJoysticks = SDL_NumJoysticks() + + for i in 0.. 2 { - let controller = controllersList[2] - currentControllers.append(controller) - } else if let controller = controllersList.first(where: { $0.id == onscreencontroller.id }), !controllersList.isEmpty { + currentControllers = [] + + if controllersList.count == 1 { + let controller = controllersList[0] currentControllers.append(controller) + } else if (controllersList.count - 1) >= 1 { + for controller in controllersList { + if controller.id != onscreencontroller.id && !currentControllers.contains(where: { $0.id == controller.id }) { + currentControllers.append(controller) + } + } } } + + func showAlert(title: String, message: String, showOk: Bool, completion: @escaping (Bool) -> Void) { DispatchQueue.main.async { diff --git a/src/MeloNX/MeloNX/App/Views/SettingsView/SettingsView.swift b/src/MeloNX/MeloNX/App/Views/SettingsView/SettingsView.swift index a6b31d4ea..dad1a4c83 100644 --- a/src/MeloNX/MeloNX/App/Views/SettingsView/SettingsView.swift +++ b/src/MeloNX/MeloNX/App/Views/SettingsView/SettingsView.swift @@ -198,7 +198,7 @@ struct SettingsView: View { - ForEach(controllersList) { controller in + ForEach(currentControllers) { controller in var customBinding: Binding { Binding( @@ -223,14 +223,26 @@ struct SettingsView: View { } .tint(.blue) } label: { - let controller = String((controllersList.firstIndex(where: { $0.id == controller.id }) ?? 0) + 1) - - Text("Player \(controller)") + if let controller = currentControllers.firstIndex(where: { $0.id == controller.id } ) { + Text("Player \(controller + 1)") + .onAppear() { + // print(currentControllers.firstIndex(where: { $0.id == controller.id }) ?? 0) + print(currentControllers.count) + + if currentControllers.count > 2 { + print(currentControllers[1]) + print(currentControllers[2]) + } + } + } } } } + .onMove { from, to in + currentControllers.move(fromOffsets: from, toOffset: to) + } } header: { Text("Input Selector") .font(.title3.weight(.semibold)) diff --git a/src/MeloNX/MeloNX/Dependencies/Dynamic Libraries/libMoltenVK.dylib b/src/MeloNX/MeloNX/Dependencies/Dynamic Libraries/libMoltenVK.dylib index 3253ff11f..7e3092cd5 100755 Binary files a/src/MeloNX/MeloNX/Dependencies/Dynamic Libraries/libMoltenVK.dylib and b/src/MeloNX/MeloNX/Dependencies/Dynamic Libraries/libMoltenVK.dylib differ diff --git a/src/MeloNX/MeloNX/Dependencies/XCFrameworks/MoltenVK.xcframework/ios-arm64/MoltenVK.framework/Info.plist b/src/MeloNX/MeloNX/Dependencies/XCFrameworks/MoltenVK.xcframework/ios-arm64/MoltenVK.framework/Info.plist index 2e0914e03..195d07044 100644 Binary files a/src/MeloNX/MeloNX/Dependencies/XCFrameworks/MoltenVK.xcframework/ios-arm64/MoltenVK.framework/Info.plist and b/src/MeloNX/MeloNX/Dependencies/XCFrameworks/MoltenVK.xcframework/ios-arm64/MoltenVK.framework/Info.plist differ diff --git a/src/MeloNX/MeloNX/Dependencies/XCFrameworks/MoltenVK.xcframework/ios-arm64/MoltenVK.framework/MoltenVK b/src/MeloNX/MeloNX/Dependencies/XCFrameworks/MoltenVK.xcframework/ios-arm64/MoltenVK.framework/MoltenVK index 3253ff11f..d26ed962f 100755 Binary files a/src/MeloNX/MeloNX/Dependencies/XCFrameworks/MoltenVK.xcframework/ios-arm64/MoltenVK.framework/MoltenVK and b/src/MeloNX/MeloNX/Dependencies/XCFrameworks/MoltenVK.xcframework/ios-arm64/MoltenVK.framework/MoltenVK differ diff --git a/src/Ryujinx.Headless.SDL2/Program.cs b/src/Ryujinx.Headless.SDL2/Program.cs index d8aac2fe4..69fedb229 100644 --- a/src/Ryujinx.Headless.SDL2/Program.cs +++ b/src/Ryujinx.Headless.SDL2/Program.cs @@ -95,12 +95,6 @@ using System.IO; using System.Runtime.InteropServices; using SDL2; -public class GamepadInfo -{ - public string Id { get; set; } - public string Name { get; set; } -} - namespace Ryujinx.Headless.SDL2 { class Program @@ -316,44 +310,6 @@ namespace Ryujinx.Headless.SDL2 _emulationContext = null; } } - - - - - [UnmanagedCallersOnly(EntryPoint = "get_game_controllers")] - public static unsafe IntPtr GetGamepadList() - { - List gamepads = new List(); - IGamepad gamepad; - if (_inputManager == null) - { - _inputManager = new InputManager(new SDL2KeyboardDriver(), new SDL2GamepadDriver()); - } - - // Collect gamepads from the keyboard driver - foreach (string id in _inputManager.KeyboardDriver.GamepadsIds) - { - gamepad = _inputManager.KeyboardDriver.GetGamepad(id); - gamepads.Add(new GamepadInfo { Id = id, Name = gamepad.Name }); - gamepad.Dispose(); - } - - // Collect gamepads from the gamepad driver - foreach (string id in _inputManager.GamepadDriver.GamepadsIds) - { - gamepad = _inputManager.GamepadDriver.GetGamepad(id); - gamepads.Add(new GamepadInfo { Id = id, Name = gamepad.Name }); - gamepad.Dispose(); - } - - // Serialize the gamepad list to a custom string format - string result = string.Join("\n", gamepads.Select(g => $"{g.Id}:{g.Name}")); // Ensure System.Linq is available - - // Convert the string to unmanaged memory - IntPtr ptr = Marshal.StringToHGlobalAnsi(result); - - return ptr; - } [UnmanagedCallersOnly(EntryPoint = "get_game_info")] public static GameInfoNative GetGameInfoNative(int descriptor, IntPtr extensionPtr)