forked from MeloNX/MeloNX
Create the window in swift again
This commit is contained in:
parent
10e45533e1
commit
05880cc8a5
Binary file not shown.
@ -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">
|
||||||
|
@ -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)])
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -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.")
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user