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()