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"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
enableGPUValidationMode = "1"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">

View File

@ -98,7 +98,9 @@ class Ryujinx {
// Fixes the Stubs.DispatchLoop Crash
args.append(contentsOf: ["--memory-manager-mode", "SoftwarePageTable"])
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
args.append(contentsOf: ["--enable-debug-logs", String(config.debuglogs)])

View File

@ -10,16 +10,19 @@ import SDL2
import GameController
struct ContentView: View {
@State public var theWindow: UIWindow? = nil
@State private var virtualController: GCVirtualController?
@State var game: URL? = nil
init() {
// Initialize SDL
DispatchQueue.main.async {
DispatchQueue.main.async { [self] in
SDL_SetMainReady()
SDL_iPhoneSetEventPump(SDL_TRUE)
SDL_Init(SDL_INIT_VIDEO)
// Apply the window patch early
patchMakeKeyAndVisible()
}
}
@ -31,8 +34,7 @@ struct ContentView: View {
GCInputButtonA,
GCInputButtonB,
GCInputButtonX,
GCInputButtonY,
//GCInputDirectionPad
GCInputButtonY
]
let controller = GCVirtualController(configuration: configuration)
@ -41,24 +43,66 @@ struct ContentView: View {
}
var body: some View {
if let game {
SDLViewRepresentable {
setupVirtualController()
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)")
}
SDLViewRepresentable { displayid in
start(displayid: displayid)
}
} else {
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 {
var sdlwin: OpaquePointer?
private var sdlWindowID: UInt32 = 1 // Adjust this ID based on Ryujinx window ID
override init(frame: CGRect) {
super.init(frame: frame)
startSDLWindowRetrieval()
DispatchQueue.main.async { [self] in
makeSDLWindow()
}
}
required init?(coder: NSCoder) {
super.init(coder: coder)
startSDLWindowRetrieval()
DispatchQueue.main.async { [self] in
makeSDLWindow()
}
}
private func startSDLWindowRetrieval() {
Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { timer in
self.makeSDLWindow()
// Stop the timer once the window is successfully retrieved
if self.sdlwin != nil {
timer.invalidate()
}
}
func getWindowFlags() -> UInt32 {
return SDL_WINDOW_VULKAN.rawValue
}
private func makeSDLWindow() {
// Attempt to retrieve the SDL window created by Ryujinx
sdlwin = SDL_GetWindowFromID(sdlWindowID)
let width: Int32 = 1280 // Replace with the desired width
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
guard sdlwin != nil else {
print("Error getting SDL window: \(String(cString: SDL_GetError()))")
print("Error creating SDL window: \(String(cString: SDL_GetError()))")
return
}
print("SDL window retrieved successfully.")
print("SDL window created successfully.")
// Position SDL window over this UIView
DispatchQueue.main.async {
self.syncSDLWindowPosition()
}
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)
}
// 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.")
}

View File

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

View File

@ -185,7 +185,8 @@ namespace Ryujinx.Headless.SDL2
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)
{