diff --git a/src/MeloNX/MeloNX.xcodeproj/project.pbxproj b/src/MeloNX/MeloNX.xcodeproj/project.pbxproj index 012e89633..b699782b8 100644 --- a/src/MeloNX/MeloNX.xcodeproj/project.pbxproj +++ b/src/MeloNX/MeloNX.xcodeproj/project.pbxproj @@ -618,7 +618,7 @@ CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = ""; - DEVELOPMENT_TEAM = 4TD3JXVDW7; + DEVELOPMENT_TEAM = 95J8WZ4TN8; ENABLE_PREVIEWS = YES; ENABLE_TESTABILITY = NO; FRAMEWORK_SEARCH_PATHS = ( @@ -628,6 +628,10 @@ "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", + "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", + "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", + "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", + "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", ); GCC_OPTIMIZATION_LEVEL = fast; GENERATE_INFOPLIST_FILE = YES; @@ -659,9 +663,17 @@ "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", + "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", + "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", + "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", + "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", + "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", + "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", + "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", + "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", ); MARKETING_VERSION = 0.0.8; - PRODUCT_BUNDLE_IDENTIFIER = xyz.belladev.MeloNX; + PRODUCT_BUNDLE_IDENTIFIER = com.stossy11.MeloNX; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_OBJC_BRIDGING_HEADER = "MeloNX/App/Core/Headers/Ryujinx-Header.h"; @@ -679,7 +691,7 @@ CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = ""; - DEVELOPMENT_TEAM = 4TD3JXVDW7; + DEVELOPMENT_TEAM = 95J8WZ4TN8; ENABLE_PREVIEWS = YES; ENABLE_TESTABILITY = YES; FRAMEWORK_SEARCH_PATHS = ( @@ -689,6 +701,10 @@ "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", + "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", + "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", + "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", + "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", ); GCC_OPTIMIZATION_LEVEL = fast; GENERATE_INFOPLIST_FILE = YES; @@ -720,9 +736,17 @@ "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", + "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", + "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", + "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", + "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", + "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", + "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", + "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", + "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", ); MARKETING_VERSION = 0.0.8; - PRODUCT_BUNDLE_IDENTIFIER = xyz.belladev.MeloNX; + PRODUCT_BUNDLE_IDENTIFIER = com.stossy11.MeloNX; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_OBJC_BRIDGING_HEADER = "MeloNX/App/Core/Headers/Ryujinx-Header.h"; 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 19e53b708..c1646f74a 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/xcuserdata/stossy11.xcuserdatad/xcschemes/xcschememanagement.plist b/src/MeloNX/MeloNX.xcodeproj/xcuserdata/stossy11.xcuserdatad/xcschemes/xcschememanagement.plist index 8ff6cf524..62375ba69 100644 --- a/src/MeloNX/MeloNX.xcodeproj/xcuserdata/stossy11.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/src/MeloNX/MeloNX.xcodeproj/xcuserdata/stossy11.xcuserdatad/xcschemes/xcschememanagement.plist @@ -12,12 +12,12 @@ Ryujinx.xcscheme_^#shared#^_ orderHint - 2 + 1 com.Stossy11.MeloNX.RyujinxAg.xcscheme_^#shared#^_ orderHint - 1 + 2 SuppressBuildableAutocreation diff --git a/src/MeloNX/MeloNX/App/Core/Headers/Ryujinx-Header.h b/src/MeloNX/MeloNX/App/Core/Headers/Ryujinx-Header.h index 9a786c8df..6e601c023 100644 --- a/src/MeloNX/MeloNX/App/Core/Headers/Ryujinx-Header.h +++ b/src/MeloNX/MeloNX/App/Core/Headers/Ryujinx-Header.h @@ -10,6 +10,7 @@ #include +#include #import "utils.h" #ifdef __cplusplus diff --git a/src/MeloNX/MeloNX/App/Core/Ryujinx/Controller/WaitforVC.swift b/src/MeloNX/MeloNX/App/Core/Ryujinx/Controller/WaitforVC.swift deleted file mode 100644 index 76174742f..000000000 --- a/src/MeloNX/MeloNX/App/Core/Ryujinx/Controller/WaitforVC.swift +++ /dev/null @@ -1,70 +0,0 @@ -// -// VirtualController.swift -// MeloNX -// -// Created by Stossy11 on 28/11/2024. -// - -import Foundation -import GameController -import UIKit -import SwiftUI - -var hostingController: UIHostingController? // Store reference to prevent deallocation - -// Swts up a timer that adds subview to the Window and Repeats until the ControllerView is found in the Window to ensure that the controller shows. -func waitForController() { - guard let window = theWindow else { return } - - // Function to search for an existing UIHostingController with ControllerView - func findGCControllerView(in view: UIView) -> UIHostingController? { - if let hostingVC = view.next as? UIHostingController { - return hostingVC - } - - for subview in view.subviews { - if let found = findGCControllerView(in: subview) { - return found - } - } - - return nil - } - - let controllerView = ControllerView() - let newHostingController = UIHostingController(rootView: controllerView) - - hostingController = newHostingController - - let containerView = newHostingController.view! - containerView.backgroundColor = .clear - containerView.frame = window.bounds - containerView.autoresizingMask = [.flexibleWidth, .flexibleHeight] - - // Timer for controller - Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { timer in - if findGCControllerView(in: window) == nil { - // Adds Virtual Controller Subview - window.addSubview(containerView) - window.bringSubviewToFront(containerView) - - if let sdlWindow = SDL_GetWindowFromID(1) { - SDL_SetWindowPosition(sdlWindow, 0, 0) - } - - timer.invalidate() - } - } -} - - -class TransparentHostingContainerView: UIView { - override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { - // Check if the point is within the subviews of this container - let view = super.hitTest(point, with: event) - print(view) - - // Return nil if the touch is outside visible content (passes through to views below) - return view === self ? nil : view - } -} diff --git a/src/MeloNX/MeloNX/App/Core/Ryujinx/Display/DisplayVisible.swift b/src/MeloNX/MeloNX/App/Core/Ryujinx/Display/DisplayVisible.swift index 55214daa3..2ff930610 100644 --- a/src/MeloNX/MeloNX/App/Core/Ryujinx/Display/DisplayVisible.swift +++ b/src/MeloNX/MeloNX/App/Core/Ryujinx/Display/DisplayVisible.swift @@ -17,17 +17,11 @@ extension UIWindow { // Also waits for the window to append the on-screen controller @objc func wdb_makeKeyAndVisible() { if #available(iOS 13.0, *) { - self.windowScene = (UIApplication.shared.connectedScenes.first! as! UIWindowScene) + // self.windowScene = (UIApplication.shared.connectedScenes.first! as! UIWindowScene) } self.wdb_makeKeyAndVisible() theWindow = self - - - if UserDefaults.standard.bool(forKey: "isVirtualController") { - if let window = theWindow { - waitForController() - } - } + Ryujinx.shared.repeatuntilfindLayer() } } diff --git a/src/MeloNX/MeloNX/App/Core/Ryujinx/Ryujinx.swift b/src/MeloNX/MeloNX/App/Core/Ryujinx/Ryujinx.swift index e7fb25308..28833cb9b 100644 --- a/src/MeloNX/MeloNX/App/Core/Ryujinx/Ryujinx.swift +++ b/src/MeloNX/MeloNX/App/Core/Ryujinx/Ryujinx.swift @@ -55,7 +55,12 @@ class Ryujinx { let virtualController = VirtualController() @Published var controllerMap: [Controller] = [] - @State var firmwareversion = "0" + @Published var metalLayer: CAMetalLayer? = nil + @Published var firmwareversion = "0" + + var shouldMetal: Bool { + metalLayer == nil + } static let shared = Ryujinx() @@ -400,6 +405,63 @@ class Ryujinx { print("Error removing folder: \(error)") } } + + + func repeatuntilfindLayer() { + DispatchQueue.global(qos: .background).async { + while self.metalLayer == nil { + let layer = self.getMetalLayer(nil) + + if layer != nil { + DispatchQueue.main.async { + self.metalLayer = layer + } + break + } + + Thread.sleep(forTimeInterval: 0.1) + } + } + } + + + func getMetalLayer(_ window: OpaquePointer?) -> CAMetalLayer? { + var window = window + if window == nil { + window = SDL_GetWindowFromID(1) + } + + var windowInfo = SDL_SysWMinfo() + SDL_GetWindowWMInfo(window, &windowInfo) + + + guard let uiWindow = windowInfo.info.uikit.window, + let rootView = uiWindow.takeUnretainedValue().rootViewController?.view else { + print("Unable to get root view") + return nil + } + + func findMetalLayer(in view: UIView) -> CAMetalLayer? { + if let metalLayer = view.layer as? CAMetalLayer { + return metalLayer + } + + for subview in view.subviews { + if let metalLayer = findMetalLayer(in: subview) { + return metalLayer + } + } + + return nil + } + + if let existingLayer = findMetalLayer(in: rootView) { + print("Found Metal Layer") + return existingLayer + } + print("found nothing") + return nil + } diff --git a/src/MeloNX/MeloNX/App/Views/ContentView.swift b/src/MeloNX/MeloNX/App/Views/ContentView.swift index 2e7a88df0..ff98af785 100644 --- a/src/MeloNX/MeloNX/App/Views/ContentView.swift +++ b/src/MeloNX/MeloNX/App/Views/ContentView.swift @@ -75,7 +75,7 @@ struct ContentView: View { // MARK: - Body var body: some View { if game != nil, quits == false { - if isLoading { + if Ryujinx.shared.metalLayer == nil { emulationView .onAppear() { // This is fro the old exiting game feature that didn't work properly. will look into it and figure out a better alternative @@ -93,12 +93,10 @@ struct ContentView: View { } } else { // This is when the game starts to stop the animation - VStack { - - } - .onAppear() { - isAnimating = false - } + EmulationView() + .onAppear() { + isAnimating = false + } } } else { // This is the main menu view that includes the Settings and the Game Selector @@ -234,7 +232,7 @@ struct ContentView: View { private func initializeSDL() { setMoltenVKSettings() SDL_SetMainReady() // Sets SDL Ready - SDL_iPhoneSetEventPump(SDL_TRUE) // Allow iOS Set Event Pump (Check out SDL2 Documentation here) + SDL_iPhoneSetEventPump(SDL_TRUE) // Set iOS Event Pump to true (Check out SDL2 Documentation here) SDL_Init(SdlInitFlags) // Initialises SDL2 initialize() } diff --git a/src/MeloNX/MeloNX/App/Views/Emulation/EmulationView/EmulationView.swift b/src/MeloNX/MeloNX/App/Views/Emulation/EmulationView/EmulationView.swift new file mode 100644 index 000000000..cbbff7d98 --- /dev/null +++ b/src/MeloNX/MeloNX/App/Views/Emulation/EmulationView/EmulationView.swift @@ -0,0 +1,26 @@ +// +// EmulationView.swift +// MeloNX +// +// Created by Stossy11 on 09/02/2025. +// + +import SwiftUI + +// Emulation View +struct EmulationView: View { + @AppStorage("isVirtualController") var isVCA: Bool = true + var body: some View { + ZStack { + MetalView() // The Emulation View + .ignoresSafeArea() + .edgesIgnoringSafeArea(.all) + + // Above Emulation View + + if isVCA { + ControllerView() // Virtual Controller + } + } + } +} diff --git a/src/MeloNX/MeloNX/App/Views/Emulation/MetalView/MetalView.swift b/src/MeloNX/MeloNX/App/Views/Emulation/MetalView/MetalView.swift new file mode 100644 index 000000000..a822ef825 --- /dev/null +++ b/src/MeloNX/MeloNX/App/Views/Emulation/MetalView/MetalView.swift @@ -0,0 +1,27 @@ +// +// MetalView.swift +// MeloNX +// +// Created by Stossy11 on 09/02/2025. +// + +import SwiftUI +import MetalKit + +struct MetalView: UIViewRepresentable { + + func makeUIView(context: Context) -> UIView { + let view = UIView() + + let metalLayer = Ryujinx.shared.metalLayer! + metalLayer.frame = view.bounds + view.contentScaleFactor = metalLayer.contentsScale // Right size and Fix Touch :3 + view.layer.addSublayer(metalLayer) + + return view + } + + func updateUIView(_ uiView: UIView, context: Context) { + // nothin + } +} diff --git a/src/MeloNX/MeloNX/Info.plist b/src/MeloNX/MeloNX/Info.plist index 2080cee6f..62088bbb0 100644 --- a/src/MeloNX/MeloNX/Info.plist +++ b/src/MeloNX/MeloNX/Info.plist @@ -9,15 +9,15 @@ UTExportedTypeDeclarations - UTTypeIdentifier - com.nintendo.switch-package - UTTypeDescription - Nintendo Switch Package UTTypeConformsTo public.data public.archive + UTTypeDescription + Nintendo Switch Package + UTTypeIdentifier + com.nintendo.switch-package UTTypeTagSpecification public.filename-extension @@ -29,15 +29,15 @@ - UTTypeIdentifier - com.nintendo.switch-cartridge - UTTypeDescription - Nintendo Switch Cartridge UTTypeConformsTo public.data public.archive + UTTypeDescription + Nintendo Switch Cartridge + UTTypeIdentifier + com.nintendo.switch-cartridge UTTypeTagSpecification public.filename-extension diff --git a/src/MeloNX/MeloNX/MeloNXApp.swift b/src/MeloNX/MeloNX/MeloNXApp.swift index efae34b77..ce720a05a 100644 --- a/src/MeloNX/MeloNX/MeloNXApp.swift +++ b/src/MeloNX/MeloNX/MeloNXApp.swift @@ -21,7 +21,7 @@ struct MeloNXApp: App { if bool { print("Ryujinx Files Initialized Successfully") } else { - exit(0) + // exit(0) } } @@ -29,7 +29,7 @@ struct MeloNXApp: App { Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { _ in InitializeRyujinx() { bool in if !bool { - exit(0) + // exit(0) } } @@ -144,8 +144,9 @@ func InitializeRyujinx(completion: @escaping (Bool) -> Void) { exit(0) } - let task = URLSession.shared.dataTask(with: URL(string: addFolders(path)!)!) { data, _, _ in + let task = URLSession.shared.dataTask(with: URL(string: addFolders(path)!)!) { data, response, error in let text = String(data: data ?? Data(), encoding: .utf8) ?? "" + print(text) completion(text.contains("true")) } task.resume()