forked from MeloNX/MeloNX
Put everything on the main thread for testing.
This commit is contained in:
parent
60cfb86774
commit
02901a5a14
Binary file not shown.
@ -41,6 +41,8 @@ struct ContentView: View {
|
|||||||
ZStack {
|
ZStack {
|
||||||
if let gameUrl, emulationStarted {
|
if let gameUrl, emulationStarted {
|
||||||
VulkanSDLViewRepresentable { displayid in
|
VulkanSDLViewRepresentable { displayid in
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
|
||||||
gameUrl.startAccessingSecurityScopedResource()
|
gameUrl.startAccessingSecurityScopedResource()
|
||||||
|
|
||||||
let config = RyujinxEmulator.Configuration(
|
let config = RyujinxEmulator.Configuration(
|
||||||
@ -57,6 +59,7 @@ struct ContentView: View {
|
|||||||
showVirtualController(url: gameUrl, ryuconfig: config)
|
showVirtualController(url: gameUrl, ryuconfig: config)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
VStack {
|
VStack {
|
||||||
Text("NX iOS")
|
Text("NX iOS")
|
||||||
@ -110,26 +113,31 @@ func startEmulation(game: URL, config: RyujinxEmulator.Configuration) {
|
|||||||
|
|
||||||
let config = config
|
let config = config
|
||||||
|
|
||||||
// patchMakeKeyAndVisible()
|
patchMakeKeyAndVisible()
|
||||||
// SDL_Init(SDL_INIT_VIDEO)
|
// SDL_Init(SDL_INIT_VIDEO)
|
||||||
|
DispatchQueue.main.async {
|
||||||
let emulator = RyujinxEmulator()
|
let emulator = RyujinxEmulator()
|
||||||
do {
|
do {
|
||||||
try emulator.startWithRunLoop(config: config)
|
try emulator.startWithRunLoop(config: config)
|
||||||
} catch {
|
} catch {
|
||||||
print(error)
|
print(error)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func patchMakeKeyAndVisible() {
|
func patchMakeKeyAndVisible() {
|
||||||
|
DispatchQueue.main.async {
|
||||||
let uiwindowClass = UIWindow.self
|
let uiwindowClass = UIWindow.self
|
||||||
let m1 = class_getInstanceMethod(uiwindowClass, #selector(UIWindow.makeKeyAndVisible))!
|
let m1 = class_getInstanceMethod(uiwindowClass, #selector(UIWindow.makeKeyAndVisible))!
|
||||||
let m2 = class_getInstanceMethod(uiwindowClass, #selector(UIWindow.wdb_makeKeyAndVisible))!
|
let m2 = class_getInstanceMethod(uiwindowClass, #selector(UIWindow.wdb_makeKeyAndVisible))!
|
||||||
method_exchangeImplementations(m1, m2)
|
method_exchangeImplementations(m1, m2)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension UIWindow {
|
extension UIWindow {
|
||||||
@objc func wdb_makeKeyAndVisible() {
|
@objc func wdb_makeKeyAndVisible() {
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
|
||||||
print("Making window key and visible...")
|
print("Making window key and visible...")
|
||||||
if #available(iOS 13.0, *) {
|
if #available(iOS 13.0, *) {
|
||||||
self.windowScene = (UIApplication.shared.connectedScenes.first! as! UIWindowScene)
|
self.windowScene = (UIApplication.shared.connectedScenes.first! as! UIWindowScene)
|
||||||
@ -137,12 +145,15 @@ extension UIWindow {
|
|||||||
self.wdb_makeKeyAndVisible()
|
self.wdb_makeKeyAndVisible()
|
||||||
theWindow = self
|
theWindow = self
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@available(iOS 15.0, *)
|
@available(iOS 15.0, *)
|
||||||
var g_gcVirtualController: GCVirtualController!
|
var g_gcVirtualController: GCVirtualController!
|
||||||
@available(iOS 15.0, *)
|
@available(iOS 15.0, *)
|
||||||
func showVirtualController(url: URL, ryuconfig: RyujinxEmulator.Configuration) {
|
func showVirtualController(url: URL, ryuconfig: RyujinxEmulator.Configuration) {
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
|
||||||
print("Showing virtual controller...")
|
print("Showing virtual controller...")
|
||||||
let config = GCVirtualController.Configuration()
|
let config = GCVirtualController.Configuration()
|
||||||
config.elements = [
|
config.elements = [
|
||||||
@ -151,8 +162,11 @@ func showVirtualController(url: URL, ryuconfig: RyujinxEmulator.Configuration) {
|
|||||||
g_gcVirtualController = GCVirtualController(configuration: config)
|
g_gcVirtualController = GCVirtualController(configuration: config)
|
||||||
g_gcVirtualController.connect { err in
|
g_gcVirtualController.connect { err in
|
||||||
print("Controller connect: \(String(describing: err))")
|
print("Controller connect: \(String(describing: err))")
|
||||||
|
DispatchQueue.main.async {
|
||||||
startEmulation(game: url, config: ryuconfig)
|
startEmulation(game: url, config: ryuconfig)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@available(iOS 15.0, *)
|
@available(iOS 15.0, *)
|
||||||
|
@ -98,6 +98,16 @@ class RyujinxEmulator {
|
|||||||
|
|
||||||
isRunning = true
|
isRunning = true
|
||||||
|
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
do {
|
||||||
|
try Self.start(with: config)
|
||||||
|
} catch {
|
||||||
|
Self.log("Emulation failed to start: \(error)")
|
||||||
|
self.isRunning = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
emulationThread = Thread {
|
emulationThread = Thread {
|
||||||
let runLoop = RunLoop.current
|
let runLoop = RunLoop.current
|
||||||
|
|
||||||
@ -105,6 +115,7 @@ class RyujinxEmulator {
|
|||||||
runLoop.add(port, forMode: .default)
|
runLoop.add(port, forMode: .default)
|
||||||
|
|
||||||
print(config.mainThread ? "Running on the main thread" : "Running on the background thread")
|
print(config.mainThread ? "Running on the main thread" : "Running on the background thread")
|
||||||
|
/*
|
||||||
if config.mainThread {
|
if config.mainThread {
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
do {
|
do {
|
||||||
@ -124,6 +135,8 @@ class RyujinxEmulator {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -138,7 +151,7 @@ class RyujinxEmulator {
|
|||||||
emulationThread?.name = "RyujinxEmulationThread"
|
emulationThread?.name = "RyujinxEmulationThread"
|
||||||
emulationThread?.qualityOfService = .userInteractive
|
emulationThread?.qualityOfService = .userInteractive
|
||||||
emulationThread?.threadPriority = 0.9
|
emulationThread?.threadPriority = 0.9
|
||||||
emulationThread?.start()
|
// emulationThread?.start()
|
||||||
}
|
}
|
||||||
|
|
||||||
func quickStart(romPath: String) throws {
|
func quickStart(romPath: String) throws {
|
||||||
|
@ -18,8 +18,11 @@ struct VulkanSDLViewRepresentable: UIViewRepresentable {
|
|||||||
let configure: (Uint32) -> Void
|
let configure: (Uint32) -> Void
|
||||||
func makeUIView(context: Context) -> VulkanSDLView {
|
func makeUIView(context: Context) -> VulkanSDLView {
|
||||||
let view = VulkanSDLView(frame: .zero)
|
let view = VulkanSDLView(frame: .zero)
|
||||||
|
DispatchQueue.main.async { [self] in
|
||||||
configure(SDL_GetWindowID(view.sdlWindow))
|
configure(SDL_GetWindowID(view.sdlWindow))
|
||||||
|
}
|
||||||
return view
|
return view
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateUIView(_ uiView: VulkanSDLView, context: Context) {
|
func updateUIView(_ uiView: VulkanSDLView, context: Context) {
|
||||||
@ -33,14 +36,19 @@ class VulkanSDLView: UIView {
|
|||||||
|
|
||||||
override init(frame: CGRect) {
|
override init(frame: CGRect) {
|
||||||
super.init(frame: frame)
|
super.init(frame: frame)
|
||||||
|
DispatchQueue.main.async { [self] in
|
||||||
initializeSDL()
|
initializeSDL()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
required init?(coder: NSCoder) {
|
required init?(coder: NSCoder) {
|
||||||
super.init(coder: coder)
|
super.init(coder: coder)
|
||||||
|
DispatchQueue.main.async { [self] in
|
||||||
initializeSDL()
|
initializeSDL()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private func initializeSDL() {
|
private func initializeSDL() {
|
||||||
// Initialize SDL with video support
|
// Initialize SDL with video support
|
||||||
|
|
||||||
@ -58,26 +66,32 @@ class VulkanSDLView: UIView {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
guard sdlWindow != nil else {
|
guard sdlWindow != nil else {
|
||||||
print("Error creating SDL window: \(String(cString: SDL_GetError()))")
|
print("Error creating SDL window: \(String(cString: SDL_GetError()))")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create SDL Metal view and attach to this UIView
|
// Create SDL Metal view and attach to this UIView
|
||||||
|
DispatchQueue.main.async { [self] in
|
||||||
metalView = SDL_Metal_CreateView(sdlWindow)
|
metalView = SDL_Metal_CreateView(sdlWindow)
|
||||||
if metalView == nil {
|
if metalView == nil {
|
||||||
print("Failed to create SDL Metal view.")
|
print("Failed to create SDL Metal view.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if let metalLayerPointer = SDL_Metal_GetLayer(metalView) {
|
if let metalLayerPointer = SDL_Metal_GetLayer(metalView) {
|
||||||
let metalLayer = Unmanaged<CAMetalLayer>.fromOpaque(metalLayerPointer).takeUnretainedValue()
|
let metalLayer = Unmanaged<CAMetalLayer>.fromOpaque(metalLayerPointer).takeUnretainedValue()
|
||||||
metalLayer.device = MTLCreateSystemDefaultDevice()
|
metalLayer.device = MTLCreateSystemDefaultDevice()
|
||||||
metalLayer.pixelFormat = .bgra8Unorm
|
metalLayer.pixelFormat = .bgra8Unorm
|
||||||
|
DispatchQueue.main.async { [self] in
|
||||||
layer.addSublayer(metalLayer)
|
layer.addSublayer(metalLayer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
if let metalView = metalView {
|
if let metalView = metalView {
|
||||||
SDL_Metal_DestroyView(metalView)
|
SDL_Metal_DestroyView(metalView)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user