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 c3855c670..7e812551b 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/xcshareddata/xcschemes/MeloNX.xcscheme b/src/MeloNX/MeloNX.xcodeproj/xcshareddata/xcschemes/MeloNX.xcscheme new file mode 100644 index 000000000..327ff8d71 --- /dev/null +++ b/src/MeloNX/MeloNX.xcodeproj/xcshareddata/xcschemes/MeloNX.xcscheme @@ -0,0 +1,103 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Scheme + LastUpgradeVersion = "1610" + version = "1.7"> + <BuildAction + parallelizeBuildables = "YES" + buildImplicitDependencies = "YES" + buildArchitectures = "Automatic"> + <BuildActionEntries> + <BuildActionEntry + buildForTesting = "YES" + buildForRunning = "YES" + buildForProfiling = "YES" + buildForArchiving = "YES" + buildForAnalyzing = "YES"> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "4E80A98C2CD6F54500029585" + BuildableName = "MeloNX.app" + BlueprintName = "MeloNX" + ReferencedContainer = "container:MeloNX.xcodeproj"> + </BuildableReference> + </BuildActionEntry> + </BuildActionEntries> + </BuildAction> + <TestAction + buildConfiguration = "Debug" + selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" + selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + shouldUseLaunchSchemeArgsEnv = "YES" + shouldAutocreateTestPlan = "YES"> + <Testables> + <TestableReference + skipped = "NO" + parallelizable = "YES"> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "4E80A99C2CD6F54700029585" + BuildableName = "MeloNXTests.xctest" + BlueprintName = "MeloNXTests" + ReferencedContainer = "container:MeloNX.xcodeproj"> + </BuildableReference> + </TestableReference> + <TestableReference + skipped = "NO" + parallelizable = "YES"> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "4E80A9A62CD6F54700029585" + BuildableName = "MeloNXUITests.xctest" + BlueprintName = "MeloNXUITests" + ReferencedContainer = "container:MeloNX.xcodeproj"> + </BuildableReference> + </TestableReference> + </Testables> + </TestAction> + <LaunchAction + buildConfiguration = "Debug" + selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" + selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + launchStyle = "0" + useCustomWorkingDirectory = "NO" + ignoresPersistentStateOnLaunch = "NO" + debugDocumentVersioning = "YES" + debugServiceExtension = "internal" + enableGPUValidationMode = "1" + allowLocationSimulation = "YES"> + <BuildableProductRunnable + runnableDebuggingMode = "0"> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "4E80A98C2CD6F54500029585" + BuildableName = "MeloNX.app" + BlueprintName = "MeloNX" + ReferencedContainer = "container:MeloNX.xcodeproj"> + </BuildableReference> + </BuildableProductRunnable> + </LaunchAction> + <ProfileAction + buildConfiguration = "Release" + shouldUseLaunchSchemeArgsEnv = "YES" + savedToolIdentifier = "" + useCustomWorkingDirectory = "NO" + debugDocumentVersioning = "YES"> + <BuildableProductRunnable + runnableDebuggingMode = "0"> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "4E80A98C2CD6F54500029585" + BuildableName = "MeloNX.app" + BlueprintName = "MeloNX" + ReferencedContainer = "container:MeloNX.xcodeproj"> + </BuildableReference> + </BuildableProductRunnable> + </ProfileAction> + <AnalyzeAction + buildConfiguration = "Debug"> + </AnalyzeAction> + <ArchiveAction + buildConfiguration = "Release" + revealArchiveInOrganizer = "YES"> + </ArchiveAction> +</Scheme> diff --git a/src/MeloNX/MeloNX.xcodeproj/xcuserdata/stossy11.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/src/MeloNX/MeloNX.xcodeproj/xcuserdata/stossy11.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist new file mode 100644 index 000000000..5cede85d8 --- /dev/null +++ b/src/MeloNX/MeloNX.xcodeproj/xcuserdata/stossy11.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Bucket + uuid = "271EB822-2830-4016-A3D7-CA2DEBEDCD27" + type = "1" + version = "2.0"> + <Breakpoints> + <BreakpointProxy + BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint"> + <BreakpointContent + uuid = "1F3099D0-0456-4AD5-8EA1-52BABAF2AA89" + shouldBeEnabled = "Yes" + nameForDebugger = "Ignore-SIGUSR" + ignoreCount = "0" + continueAfterRunningActions = "Yes" + filePath = "MeloNX/MeloNXApp.swift" + startingColumnNumber = "9223372036854775807" + endingColumnNumber = "9223372036854775807" + startingLineNumber = "14" + endingLineNumber = "14" + landmarkName = "body" + landmarkType = "24"> + <Actions> + <BreakpointActionProxy + ActionExtensionID = "Xcode.BreakpointAction.DebuggerCommand"> + <ActionContent + consoleCommand = "process handle --stop false SIGUSR1"> + </ActionContent> + </BreakpointActionProxy> + </Actions> + </BreakpointContent> + </BreakpointProxy> + </Breakpoints> +</Bucket> 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 940154f32..10d539f04 100644 --- a/src/MeloNX/MeloNX.xcodeproj/xcuserdata/stossy11.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/src/MeloNX/MeloNX.xcodeproj/xcuserdata/stossy11.xcuserdatad/xcschemes/xcschememanagement.plist @@ -10,5 +10,23 @@ <integer>0</integer> </dict> </dict> + <key>SuppressBuildableAutocreation</key> + <dict> + <key>4E80A98C2CD6F54500029585</key> + <dict> + <key>primary</key> + <true/> + </dict> + <key>4E80A99C2CD6F54700029585</key> + <dict> + <key>primary</key> + <true/> + </dict> + <key>4E80A9A62CD6F54700029585</key> + <dict> + <key>primary</key> + <true/> + </dict> + </dict> </dict> </plist> diff --git a/src/MeloNX/MeloNX/Core/Swift/Ryujinx.swift b/src/MeloNX/MeloNX/Core/Swift/Ryujinx.swift index 3a1c8c454..4e453773b 100644 --- a/src/MeloNX/MeloNX/Core/Swift/Ryujinx.swift +++ b/src/MeloNX/MeloNX/Core/Swift/Ryujinx.swift @@ -17,14 +17,16 @@ class Ryujinx { let debuglogs: Bool let tracelogs: Bool let listinputids: Bool + let fullscreen: Bool var additionalArgs: [String] - init(gamepath: String, additionalArgs: [String] = [], debuglogs: Bool = false, tracelogs: Bool = false, listinputids: Bool = false, inputids: [String] = []) { + init(gamepath: String, additionalArgs: [String] = [], debuglogs: Bool = false, tracelogs: Bool = false, listinputids: Bool = false, inputids: [String] = [], ryufullscreen: Bool = false) { self.gamepath = gamepath self.debuglogs = debuglogs self.tracelogs = tracelogs self.inputids = inputids self.listinputids = listinputids + self.fullscreen = ryufullscreen self.additionalArgs = additionalArgs } } @@ -87,7 +89,7 @@ class Ryujinx { private func buildCommandLineArgs(from config: Configuration) -> [String] { var args: [String] = [] - + // Add the game path args.append(config.gamepath) // Starts with vulkan @@ -95,7 +97,9 @@ class Ryujinx { args.append("Vulkan") // Fixes the Stubs.DispatchLoop Crash args.append(contentsOf: ["--memory-manager-mode", "SoftwarePageTable"]) - args.append(contentsOf: ["--fullscreen", "true"]) + if config.fullscreen { + args.append(contentsOf: ["--fullscreen", String(config.fullscreen)]) + } // Debug Logs args.append(contentsOf: ["--enable-debug-logs", String(config.debuglogs)]) args.append(contentsOf: ["--enable-trace-logs", String(config.tracelogs)]) diff --git a/src/MeloNX/MeloNX/Views/ContentView.swift b/src/MeloNX/MeloNX/Views/ContentView.swift index 3652fbb4e..d5e386651 100644 --- a/src/MeloNX/MeloNX/Views/ContentView.swift +++ b/src/MeloNX/MeloNX/Views/ContentView.swift @@ -49,7 +49,7 @@ struct ContentView: View { setupVirtualController() - let config = Ryujinx.Configuration(gamepath: game.path, debuglogs: true, tracelogs: true, listinputids: false, inputids: ["1-47150005-05ac-0000-0100-00004f066d01"]) + let config = Ryujinx.Configuration(gamepath: game.path, debuglogs: true, tracelogs: true, listinputids: false, inputids: ["1-47150005-05ac-0000-0100-00004f066d01"], ryufullscreen: true) // Starts the emulation do { try Ryujinx().start(with: config) diff --git a/src/MeloNX/MeloNX/Views/SDLView/SDLView.swift b/src/MeloNX/MeloNX/Views/SDLView/SDLView.swift index 07a7f910e..a6544d35f 100644 --- a/src/MeloNX/MeloNX/Views/SDLView/SDLView.swift +++ b/src/MeloNX/MeloNX/Views/SDLView/SDLView.swift @@ -11,43 +11,68 @@ import SDL2 class SDLView: UIView { var sdlwin: OpaquePointer? - var mtkview: UnsafeMutableRawPointer? - + private var sdlWindowID: UInt32 = 1 // Adjust this ID based on Ryujinx window ID + override init(frame: CGRect) { super.init(frame: frame) - makeSDLWindow() + startSDLWindowRetrieval() } required init?(coder: NSCoder) { super.init(coder: coder) - makeSDLWindow() - + startSDLWindowRetrieval() } - private func makeSDLWindow() { - DispatchQueue.main.async { [self] in + private func startSDLWindowRetrieval() { + Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { timer in + self.makeSDLWindow() - // Gets window created from Ryujinx - sdlwin = SDL_GetWindowFromID(1) - - // Check if it got the window. - guard sdlwin != nil else { - print("Error getting SDL window: \(String(cString: SDL_GetError()))") - return - } - // Create metal View from the Window - mtkview = SDL_Metal_CreateView(sdlwin) - if mtkview == nil { - print("Failed to create SDL Metal view.") - return - } - - // Convert Metal View to Sublayer - if let metalLayerPointer = SDL_Metal_GetLayer(mtkview) { - let metalLayer = Unmanaged<CAMetalLayer>.fromOpaque(metalLayerPointer).takeUnretainedValue() - metalLayer.device = MTLCreateSystemDefaultDevice() - layer.addSublayer(metalLayer) + // Stop the timer once the window is successfully retrieved + if self.sdlwin != nil { + timer.invalidate() } } } + + private func makeSDLWindow() { + // Attempt to retrieve the SDL window created by Ryujinx + sdlwin = SDL_GetWindowFromID(sdlWindowID) + + // Check if we successfully retrieved the SDL window + guard sdlwin != nil else { + print("Error getting SDL window: \(String(cString: SDL_GetError()))") + return + } + + print("SDL window retrieved successfully.") + + // Position SDL window over this UIView + DispatchQueue.main.async { + self.syncSDLWindowPosition() + } + } + + private func syncSDLWindowPosition() { + guard let sdlwin = sdlwin else { return } + DispatchQueue.main.async { + + // Get the frame of the UIView in screen coordinates + let viewFrameInWindow = self.convert(self.bounds, to: nil) + + // Set the SDL window position and size to match the UIView frame + SDL_SetWindowPosition(sdlwin, Int32(viewFrameInWindow.origin.x), Int32(viewFrameInWindow.origin.y)) + SDL_SetWindowSize(sdlwin, Int32(viewFrameInWindow.width), Int32(viewFrameInWindow.height)) + + // Bring SDL window to the front + SDL_RaiseWindow(sdlwin) + } + + print("SDL window positioned over SDLView.") + } + + override func layoutSubviews() { + super.layoutSubviews() + // Adjust SDL window whenever layout changes + syncSDLWindowPosition() + } }