Create the window in swift again

This commit is contained in:
stossy11 2024-11-03 17:09:04 +11:00
parent 10e45533e1
commit 05880cc8a5
7 changed files with 107 additions and 54 deletions

View File

@ -63,7 +63,6 @@
ignoresPersistentStateOnLaunch = "NO" ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES" debugDocumentVersioning = "YES"
debugServiceExtension = "internal" debugServiceExtension = "internal"
enableGPUValidationMode = "1"
allowLocationSimulation = "YES"> allowLocationSimulation = "YES">
<BuildableProductRunnable <BuildableProductRunnable
runnableDebuggingMode = "0"> runnableDebuggingMode = "0">

View File

@ -98,7 +98,9 @@ class Ryujinx {
// Fixes the Stubs.DispatchLoop Crash // Fixes the Stubs.DispatchLoop Crash
args.append(contentsOf: ["--memory-manager-mode", "SoftwarePageTable"]) args.append(contentsOf: ["--memory-manager-mode", "SoftwarePageTable"])
if config.fullscreen { if config.fullscreen {
args.append(contentsOf: ["--fullscreen", String(config.fullscreen)]) // args.append(contentsOf: ["--fullscreen", String(config.fullscreen)])
args.append(contentsOf: ["--exclusive-fullscreen", String(config.fullscreen)])
// exclusive-fullscreen
} }
// Debug Logs // Debug Logs
args.append(contentsOf: ["--enable-debug-logs", String(config.debuglogs)]) args.append(contentsOf: ["--enable-debug-logs", String(config.debuglogs)])

View File

@ -10,16 +10,19 @@ import SDL2
import GameController import GameController
struct ContentView: View { struct ContentView: View {
@State public var theWindow: UIWindow? = nil
@State private var virtualController: GCVirtualController? @State private var virtualController: GCVirtualController?
@State var game: URL? = nil @State var game: URL? = nil
init() { init() {
// Initialize SDL // Initialize SDL
DispatchQueue.main.async { DispatchQueue.main.async { [self] in
SDL_SetMainReady() SDL_SetMainReady()
SDL_iPhoneSetEventPump(SDL_TRUE) SDL_iPhoneSetEventPump(SDL_TRUE)
SDL_Init(SDL_INIT_VIDEO) SDL_Init(SDL_INIT_VIDEO)
// Apply the window patch early
patchMakeKeyAndVisible()
} }
} }
@ -31,8 +34,7 @@ struct ContentView: View {
GCInputButtonA, GCInputButtonA,
GCInputButtonB, GCInputButtonB,
GCInputButtonX, GCInputButtonX,
GCInputButtonY, GCInputButtonY
//GCInputDirectionPad
] ]
let controller = GCVirtualController(configuration: configuration) let controller = GCVirtualController(configuration: configuration)
@ -41,24 +43,66 @@ struct ContentView: View {
} }
var body: some View { var body: some View {
if let game { if let game {
SDLViewRepresentable {
setupVirtualController() SDLViewRepresentable { displayid in
start(displayid: displayid)
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)
} catch {
print("Error \(error.localizedDescription)")
}
} }
} else { } else {
GameListView(startemu: $game) GameListView(startemu: $game)
} }
} }
func start(displayid: UInt32) {
setupVirtualController()
if theWindow == nil {
// Ensure theWindow is set
theWindow = UIApplication.shared.windows.first
}
let config = Ryujinx.Configuration(
gamepath: game!.path,
additionalArgs: [
"--display-id", String(displayid)
],
debuglogs: true,
tracelogs: true,
listinputids: false,
inputids: ["1-47150005-05ac-0000-0100-00004f066d01"],
ryufullscreen: true
)
// Start the emulation
do {
try Ryujinx().start(with: config)
} catch {
print("Error \(error.localizedDescription)")
}
}
func patchMakeKeyAndVisible() {
let uiwindowClass = UIWindow.self
if let m1 = class_getInstanceMethod(uiwindowClass, #selector(UIWindow.makeKeyAndVisible)),
let m2 = class_getInstanceMethod(uiwindowClass, #selector(UIWindow.wdb_makeKeyAndVisible)) {
method_exchangeImplementations(m1, m2)
}
}
} }
extension UIWindow {
@objc func wdb_makeKeyAndVisible() {
print("Making window key and visible...")
if #available(iOS 13.0, *) {
self.windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene
}
self.wdb_makeKeyAndVisible()
// Update ContentView's reference to this window instance
if let rootView = self.rootViewController as? UIHostingController<ContentView> {
rootView.rootView.theWindow = self
}
}
}

View File

@ -11,61 +11,67 @@ import SDL2
class SDLView: UIView { class SDLView: UIView {
var sdlwin: OpaquePointer? var sdlwin: OpaquePointer?
private var sdlWindowID: UInt32 = 1 // Adjust this ID based on Ryujinx window ID
override init(frame: CGRect) { override init(frame: CGRect) {
super.init(frame: frame) super.init(frame: frame)
startSDLWindowRetrieval() DispatchQueue.main.async { [self] in
makeSDLWindow()
}
} }
required init?(coder: NSCoder) { required init?(coder: NSCoder) {
super.init(coder: coder) super.init(coder: coder)
startSDLWindowRetrieval() DispatchQueue.main.async { [self] in
makeSDLWindow()
}
} }
private func startSDLWindowRetrieval() { func getWindowFlags() -> UInt32 {
Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { timer in return SDL_WINDOW_VULKAN.rawValue
self.makeSDLWindow()
// Stop the timer once the window is successfully retrieved
if self.sdlwin != nil {
timer.invalidate()
}
}
} }
private func makeSDLWindow() { private func makeSDLWindow() {
// Attempt to retrieve the SDL window created by Ryujinx let width: Int32 = 1280 // Replace with the desired width
sdlwin = SDL_GetWindowFromID(sdlWindowID) let height: Int32 = 720 // Replace with the desired height
let defaultFlags: UInt32 = SDL_WINDOW_SHOWN.rawValue
let fullscreenFlag: UInt32 = SDL_WINDOW_FULLSCREEN.rawValue // Or SDL_WINDOW_FULLSCREEN_DESKTOP if needed
// Create the SDL window
sdlwin = SDL_CreateWindow(
"Ryujinx",
0,
0,
width,
height,
defaultFlags | fullscreenFlag | getWindowFlags()
)
// Check if we successfully retrieved the SDL window // Check if we successfully retrieved the SDL window
guard sdlwin != nil else { guard sdlwin != nil else {
print("Error getting SDL window: \(String(cString: SDL_GetError()))") print("Error creating SDL window: \(String(cString: SDL_GetError()))")
return return
} }
print("SDL window retrieved successfully.") print("SDL window created successfully.")
// Position SDL window over this UIView // Position SDL window over this UIView
DispatchQueue.main.async { self.syncSDLWindowPosition()
self.syncSDLWindowPosition()
}
} }
private func syncSDLWindowPosition() { private func syncSDLWindowPosition() {
guard let sdlwin = sdlwin else { return } guard let sdlwin = sdlwin else { return }
DispatchQueue.main.async {
// Get the frame of the UIView in screen coordinates // Get the frame of the UIView in screen coordinates
let viewFrameInWindow = self.convert(self.bounds, to: nil) let viewFrameInWindow = self.convert(self.bounds, to: nil)
// Set the SDL window position and size to match the UIView frame // Set the SDL window position and size to match the UIView frame
SDL_SetWindowPosition(sdlwin, Int32(viewFrameInWindow.origin.x), Int32(viewFrameInWindow.origin.y)) SDL_SetWindowPosition(sdlwin, Int32(viewFrameInWindow.origin.x), Int32(viewFrameInWindow.origin.y))
SDL_SetWindowSize(sdlwin, Int32(viewFrameInWindow.width), Int32(viewFrameInWindow.height)) SDL_SetWindowSize(sdlwin, Int32(viewFrameInWindow.width), Int32(viewFrameInWindow.height))
// Bring SDL window to the front // Bring SDL window to the front
SDL_RaiseWindow(sdlwin) SDL_RaiseWindow(sdlwin)
}
print("SDL window positioned over SDLView.") print("SDL window positioned over SDLView.")
} }

View File

@ -7,13 +7,14 @@
import UIKit import UIKit
import SwiftUI import SwiftUI
import SDL2
struct SDLViewRepresentable: UIViewRepresentable { struct SDLViewRepresentable: UIViewRepresentable {
let configure: () -> Void let configure: (UInt32) -> Void
func makeUIView(context: Context) -> SDLView { func makeUIView(context: Context) -> SDLView {
// Configure (start ryu) before initialsing SDLView so SDLView can get the SDL_Window from Ryu // Configure (start ryu) before initialsing SDLView so SDLView can get the SDL_Window from Ryu
configure()
let view = SDLView(frame: .zero) let view = SDLView(frame: .zero)
configure(SDL_GetWindowID(view.sdlwin))
return view return view
} }

View File

@ -185,7 +185,8 @@ namespace Ryujinx.Headless.SDL2
FullscreenFlag = SDL_WindowFlags.SDL_WINDOW_FULLSCREEN_DESKTOP; FullscreenFlag = SDL_WindowFlags.SDL_WINDOW_FULLSCREEN_DESKTOP;
} }
WindowHandle = SDL_CreateWindow($"Ryujinx {Program.Version}{titleNameSection}{titleVersionSection}{titleIdSection}{titleArchSection}", SDL_WINDOWPOS_CENTERED_DISPLAY(DisplayId), SDL_WINDOWPOS_CENTERED_DISPLAY(DisplayId), Width, Height, DefaultFlags | FullscreenFlag | GetWindowFlags()); WindowHandle = SDL_GetWindowFromID(1);
// WindowHandle = SDL_CreateWindow($"Ryujinx {Program.Version}{titleNameSection}{titleVersionSection}{titleIdSection}{titleArchSection}", SDL_WINDOWPOS_CENTERED_DISPLAY(DisplayId), SDL_WINDOWPOS_CENTERED_DISPLAY(DisplayId), Width, Height, DefaultFlags | FullscreenFlag | GetWindowFlags());
if (WindowHandle == IntPtr.Zero) if (WindowHandle == IntPtr.Zero)
{ {