diff --git a/src/MeloNX/MeloNX.xcodeproj/project.pbxproj b/src/MeloNX/MeloNX.xcodeproj/project.pbxproj index 531ce3111..066587266 100644 --- a/src/MeloNX/MeloNX.xcodeproj/project.pbxproj +++ b/src/MeloNX/MeloNX.xcodeproj/project.pbxproj @@ -25,6 +25,7 @@ /* Begin PBXBuildFile section */ 4E0DED342D05695D00FEF007 /* SwiftUIJoystick in Frameworks */ = {isa = PBXBuildFile; productRef = 4E0DED332D05695D00FEF007 /* SwiftUIJoystick */; }; + 4E8A80772D5FDD2D0041B48F /* GameController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4E80AA622CD7122800029585 /* GameController.framework */; }; 4EA5AE822D16807500AD0B9F /* SwiftSVG in Frameworks */ = {isa = PBXBuildFile; productRef = 4EA5AE812D16807500AD0B9F /* SwiftSVG */; }; CA8F9C322D3F5AB200D7E586 /* GameController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4E80AA622CD7122800029585 /* GameController.framework */; }; /* End PBXBuildFile section */ @@ -197,6 +198,7 @@ 4E0DED342D05695D00FEF007 /* SwiftUIJoystick in Frameworks */, CA8F9C322D3F5AB200D7E586 /* GameController.framework in Frameworks */, 4EA5AE822D16807500AD0B9F /* SwiftSVG in Frameworks */, + 4E8A80772D5FDD2D0041B48F /* GameController.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -656,10 +658,15 @@ "$(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; INFOPLIST_FILE = MeloNX/Info.plist; + INFOPLIST_KEY_GCSupportsControllerUserInteraction = YES; INFOPLIST_KEY_GCSupportsGameMode = YES; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.games"; INFOPLIST_KEY_LSSupportsOpeningDocumentsInPlace = YES; @@ -670,7 +677,7 @@ INFOPLIST_KEY_UIRequiresFullScreen = YES; INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown"; INFOPLIST_KEY_UISupportsDocumentBrowser = YES; - IPHONEOS_DEPLOYMENT_TARGET = 15.0; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -710,6 +717,14 @@ "$(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 = 1.1.0; PRODUCT_BUNDLE_IDENTIFIER = com.stossy11.MeloNX; @@ -755,10 +770,15 @@ "$(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; INFOPLIST_FILE = MeloNX/Info.plist; + INFOPLIST_KEY_GCSupportsControllerUserInteraction = YES; INFOPLIST_KEY_GCSupportsGameMode = YES; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.games"; INFOPLIST_KEY_LSSupportsOpeningDocumentsInPlace = YES; @@ -769,7 +789,7 @@ INFOPLIST_KEY_UIRequiresFullScreen = YES; INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown"; INFOPLIST_KEY_UISupportsDocumentBrowser = YES; - IPHONEOS_DEPLOYMENT_TARGET = 15.0; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -809,6 +829,14 @@ "$(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 = 1.1.0; PRODUCT_BUNDLE_IDENTIFIER = com.stossy11.MeloNX; 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 6b56913a2..ae985c98a 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 fbd8d81c1..8ff6cf524 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 - 3 + 2 com.Stossy11.MeloNX.RyujinxAg.xcscheme_^#shared#^_ orderHint - 4 + 1 SuppressBuildableAutocreation diff --git a/src/MeloNX/MeloNX/App/Core/Entitlements/EntitlementChecker.swift b/src/MeloNX/MeloNX/App/Core/Entitlements/EntitlementChecker.swift new file mode 100644 index 000000000..4caed0c8d --- /dev/null +++ b/src/MeloNX/MeloNX/App/Core/Entitlements/EntitlementChecker.swift @@ -0,0 +1,58 @@ +// +// EntitlementChecker.swift +// MeloNX +// +// Created by Stossy11 on 15/02/2025. +// + +import Foundation +import Security + +typealias SecTaskRef = OpaquePointer + +@_silgen_name("SecTaskCopyValueForEntitlement") +func SecTaskCopyValueForEntitlement( + _ task: SecTaskRef, + _ entitlement: NSString, + _ error: NSErrorPointer +) -> CFTypeRef? + +@_silgen_name("SecTaskCreateFromSelf") +func SecTaskCreateFromSelf( + _ allocator: CFAllocator? +) -> SecTaskRef? + +@_silgen_name("SecTaskCopyValuesForEntitlements") +func SecTaskCopyValuesForEntitlements( + _ task: SecTaskRef, + _ entitlements: CFArray, + _ error: UnsafeMutablePointer?>? +) -> CFDictionary? + +func checkAppEntitlements(_ ents: [String]) -> [String: Any]? { + guard let task = SecTaskCreateFromSelf(nil) else { + print("Failed to create SecTask") + return nil + } + + guard let entitlements = SecTaskCopyValuesForEntitlements(task, ents as CFArray, nil) else { + print("Failed to get entitlements") + return nil + } + + return entitlements as? [String: Any] +} + +func checkAppEntitlement(_ ent: String) -> Bool? { + guard let task = SecTaskCreateFromSelf(nil) else { + print("Failed to create SecTask") + return nil + } + + guard let entitlements = SecTaskCopyValueForEntitlement(task, ent as NSString, nil) else { + print("Failed to get entitlements") + return nil + } + + return entitlements.boolValue != nil && entitlements.boolValue +} diff --git a/src/MeloNX/MeloNX/App/Core/Ryujinx/Enums/Display/AspectRatio.swift b/src/MeloNX/MeloNX/App/Core/Ryujinx/Enums/Display/AspectRatio.swift new file mode 100644 index 000000000..30db0a1fd --- /dev/null +++ b/src/MeloNX/MeloNX/App/Core/Ryujinx/Enums/Display/AspectRatio.swift @@ -0,0 +1,28 @@ +// +// AspectRatio.swift +// MeloNX +// +// Created by Stossy11 on 16/02/2025. +// + +import Foundation + +public enum AspectRatio: String, Codable, CaseIterable { + case fixed4x3 = "Fixed4x3" + case fixed16x9 = "Fixed16x9" + case fixed16x10 = "Fixed16x10" + case fixed21x9 = "Fixed21x9" + case fixed32x9 = "Fixed32x9" + case stretched = "Stretched" + + var displayName: String { + switch self { + case .fixed4x3: return "4:3" + case .fixed16x9: return "16:9 (Default)" + case .fixed16x10: return "16:10" + case .fixed21x9: return "21:9" + case .fixed32x9: return "32:9" + case .stretched: return "Stretched (Full Screen)" + } + } +} diff --git a/src/MeloNX/MeloNX/App/Core/Ryujinx/Enums/LanguageAndRegion/Language.swift b/src/MeloNX/MeloNX/App/Core/Ryujinx/Enums/LanguageAndRegion/Language.swift new file mode 100644 index 000000000..ff3732f25 --- /dev/null +++ b/src/MeloNX/MeloNX/App/Core/Ryujinx/Enums/LanguageAndRegion/Language.swift @@ -0,0 +1,52 @@ +// +// Language.swift +// MeloNX +// +// Created by Stossy11 on 16/02/2025. +// + +import Foundation + +public enum SystemLanguage: String, Codable, CaseIterable { + case japanese = "Japanese" + case americanEnglish = "AmericanEnglish" + case french = "French" + case german = "German" + case italian = "Italian" + case spanish = "Spanish" + case chinese = "Chinese" + case korean = "Korean" + case dutch = "Dutch" + case portuguese = "Portuguese" + case russian = "Russian" + case taiwanese = "Taiwanese" + case britishEnglish = "BritishEnglish" + case canadianFrench = "CanadianFrench" + case latinAmericanSpanish = "LatinAmericanSpanish" + case simplifiedChinese = "SimplifiedChinese" + case traditionalChinese = "TraditionalChinese" + case brazilianPortuguese = "BrazilianPortuguese" + + var displayName: String { + switch self { + case .japanese: return "Japanese" + case .americanEnglish: return "American English" + case .french: return "French" + case .german: return "German" + case .italian: return "Italian" + case .spanish: return "Spanish" + case .chinese: return "Chinese" + case .korean: return "Korean" + case .dutch: return "Dutch" + case .portuguese: return "Portuguese" + case .russian: return "Russian" + case .taiwanese: return "Taiwanese" + case .britishEnglish: return "British English" + case .canadianFrench: return "Canadian French" + case .latinAmericanSpanish: return "Latin American Spanish" + case .simplifiedChinese: return "Simplified Chinese" + case .traditionalChinese: return "Traditional Chinese" + case .brazilianPortuguese: return "Brazilian Portuguese" + } + } +} diff --git a/src/MeloNX/MeloNX/App/Core/Ryujinx/Enums/LanguageAndRegion/Region.swift b/src/MeloNX/MeloNX/App/Core/Ryujinx/Enums/LanguageAndRegion/Region.swift new file mode 100644 index 000000000..249f03912 --- /dev/null +++ b/src/MeloNX/MeloNX/App/Core/Ryujinx/Enums/LanguageAndRegion/Region.swift @@ -0,0 +1,31 @@ +// +// Region.swift +// MeloNX +// +// Created by Stossy11 on 16/02/2025. +// + +import Foundation + +public enum SystemRegionCode: String, Codable, CaseIterable { + case japan = "Japan" + case usa = "USA" + case europe = "Europe" + case australia = "Australia" + case china = "China" + case korea = "Korea" + case taiwan = "Taiwan" + + var displayName: String { + switch self { + case .japan: return "Japan" + case .usa: return "United States" + case .europe: return "Europe" + case .australia: return "Australia" + case .china: return "China" + case .korea: return "Korea" + case .taiwan: return "Taiwan" + } + } +} + diff --git a/src/MeloNX/MeloNX/App/Core/Ryujinx/Ryujinx.swift b/src/MeloNX/MeloNX/App/Core/Ryujinx/Ryujinx.swift index 76b038b5a..ab226fce7 100644 --- a/src/MeloNX/MeloNX/App/Core/Ryujinx/Ryujinx.swift +++ b/src/MeloNX/MeloNX/App/Core/Ryujinx/Ryujinx.swift @@ -28,26 +28,6 @@ struct iOSNav: View { } } -public enum AspectRatio: String, Codable, CaseIterable { - case fixed4x3 = "Fixed4x3" - case fixed16x9 = "Fixed16x9" - case fixed16x10 = "Fixed16x10" - case fixed21x9 = "Fixed21x9" - case fixed32x9 = "Fixed32x9" - case stretched = "Stretched" - - var displayName: String { - switch self { - case .fixed4x3: return "4:3" - case .fixed16x9: return "16:9 (Default)" - case .fixed16x10: return "16:10" - case .fixed21x9: return "21:9" - case .fixed32x9: return "32:9" - case .stretched: return "Stretched (Full Screen)" - } - } -} - class Ryujinx { private var isRunning = false @@ -60,6 +40,8 @@ class Ryujinx { @Published var emulationUIView = UIView() @Published var games: [Game] = [] + @Published var defMLContentSize: CGFloat? + var shouldMetal: Bool { metalLayer == nil } @@ -93,6 +75,8 @@ class Ryujinx { var dfsIntegrityChecks: Bool var disablePTC: Bool var disablevsync: Bool + var language: SystemLanguage + var regioncode: SystemRegionCode init(gamepath: String, @@ -116,7 +100,9 @@ class Ryujinx { expandRam: Bool = false, dfsIntegrityChecks: Bool = false, disablePTC: Bool = false, - disablevsync: Bool = false + disablevsync: Bool = false, + language: SystemLanguage = .americanEnglish, + regioncode: SystemRegionCode = .usa ) { self.gamepath = gamepath self.inputids = inputids @@ -140,6 +126,8 @@ class Ryujinx { self.dfsIntegrityChecks = dfsIntegrityChecks self.disablePTC = disablePTC self.disablevsync = disablevsync + self.language = language + self.regioncode = regioncode } } @@ -262,6 +250,10 @@ class Ryujinx { // We don't need this. Ryujinx should handle it fine :3 // this also causes crashes in some games :3 + args.append(contentsOf: ["--system-language", config.language.rawValue]) + + args.append(contentsOf: ["--system-region", config.regioncode.rawValue]) + args.append(contentsOf: ["--aspect-ratio", config.aspectRatio.rawValue]) if config.nintendoinput { @@ -276,7 +268,7 @@ class Ryujinx { args.append("--disable-vsync") } - + if config.hypervisor { args.append("--use-hypervisor") } @@ -295,7 +287,8 @@ class Ryujinx { } if config.ignoreMissingServices { - args.append(contentsOf: ["--ignore-missing-services", String(config.maxAnisotropy)]) + // args.append(contentsOf: ["--ignore-missing-services"]) + args.append("--ignore-missing-services") } if config.maxAnisotropy != 0 { @@ -318,15 +311,15 @@ class Ryujinx { } if config.debuglogs { - args.append(contentsOf: ["--enable-debug-logs"]) + args.append("--enable-debug-logs") } if config.tracelogs { - args.append(contentsOf: ["--enable-trace-logs"]) + args.append("--enable-trace-logs") } // List the input ids if config.listinputids { - args.append(contentsOf: ["--list-inputs-ids"]) + args.append("--list-inputs-ids") } // Append the input ids (limit to 4 just in case) diff --git a/src/MeloNX/MeloNX/App/Views/ContentView.swift b/src/MeloNX/MeloNX/App/Views/ContentView.swift index 6ee4d3f7d..cc4c695ff 100644 --- a/src/MeloNX/MeloNX/App/Views/ContentView.swift +++ b/src/MeloNX/MeloNX/App/Views/ContentView.swift @@ -42,7 +42,7 @@ struct ContentView: View { @AppStorage("quit") var quit: Bool = false @State var quits: Bool = false @AppStorage("MVK_CONFIG_PREFILL_METAL_COMMAND_BUFFERS") var mVKPreFillBuffer: Bool = true - @AppStorage("MVK_CONFIG_SYNCHRONOUS_QUEUE_SUBMITS") var syncqsubmits: Bool = false + @AppStorage("MVK_CONFIG_SYNCHRONOUS_QUEUE_SUBMITS") var syncqsubmits: Bool = true // Loading Animation @State private var clumpOffset: CGFloat = -100 diff --git a/src/MeloNX/MeloNX/App/Views/ControllerView/ControllerView.swift b/src/MeloNX/MeloNX/App/Views/ControllerView/ControllerView.swift index d778d8c2c..a11f2f484 100644 --- a/src/MeloNX/MeloNX/App/Views/ControllerView/ControllerView.swift +++ b/src/MeloNX/MeloNX/App/Views/ControllerView/ControllerView.swift @@ -129,6 +129,8 @@ struct ControllerView: View { struct ShoulderButtonsViewLeft: View { @State var width: CGFloat = 160 @State var height: CGFloat = 20 + @AppStorage("On-ScreenControllerScale") var controllerScale: Double = 1.0 + var body: some View { HStack { ButtonView(button: .leftTrigger) @@ -142,6 +144,9 @@ struct ShoulderButtonsViewLeft: View { width *= 1.2 height *= 1.2 } + + width *= CGFloat(controllerScale) + height *= CGFloat(controllerScale) } } } @@ -149,6 +154,8 @@ struct ShoulderButtonsViewLeft: View { struct ShoulderButtonsViewRight: View { @State var width: CGFloat = 160 @State var height: CGFloat = 20 + @AppStorage("On-ScreenControllerScale") var controllerScale: Double = 1.0 + var body: some View { HStack { ButtonView(button: .rightShoulder) @@ -162,12 +169,16 @@ struct ShoulderButtonsViewRight: View { width *= 1.2 height *= 1.2 } + + width *= CGFloat(controllerScale) + height *= CGFloat(controllerScale) } } } struct DPadView: View { @State var size: CGFloat = 145 + @AppStorage("On-ScreenControllerScale") var controllerScale: Double = 1.0 var body: some View { VStack { ButtonView(button: .dPadUp) @@ -184,12 +195,16 @@ struct DPadView: View { if UIDevice.current.systemName.contains("iPadOS") { size *= 1.2 } + + size *= CGFloat(controllerScale) } } } struct ABXYView: View { @State var size: CGFloat = 145 + @AppStorage("On-ScreenControllerScale") var controllerScale: Double = 1.0 + var body: some View { VStack { ButtonView(button: .X) @@ -206,6 +221,8 @@ struct ABXYView: View { if UIDevice.current.systemName.contains("iPadOS") { size *= 1.2 } + + size *= CGFloat(controllerScale) } } } @@ -218,6 +235,7 @@ struct ButtonView: View { @AppStorage("onscreenhandheld") var onscreenjoy: Bool = false @Environment(\.colorScheme) var colorScheme @Environment(\.presentationMode) var presentationMode + @AppStorage("On-ScreenControllerScale") var controllerScale: Double = 1.0 @@ -256,6 +274,9 @@ struct ButtonView: View { width *= 1.2 height *= 1.2 } + + width *= CGFloat(controllerScale) + height *= CGFloat(controllerScale) } } diff --git a/src/MeloNX/MeloNX/App/Views/ControllerView/Joystick/JoystickView.swift b/src/MeloNX/MeloNX/App/Views/ControllerView/Joystick/JoystickView.swift index dc1db3d8c..7747719c2 100644 --- a/src/MeloNX/MeloNX/App/Views/ControllerView/Joystick/JoystickView.swift +++ b/src/MeloNX/MeloNX/App/Views/ControllerView/Joystick/JoystickView.swift @@ -13,11 +13,14 @@ public struct Joystick: View { @State var iscool: Bool? = nil @ObservedObject public var joystickMonitor = JoystickMonitor() + @AppStorage("On-ScreenControllerScale") var controllerScale: Double = 1.0 var dragDiameter: CGFloat { var selfs = CGFloat(160) + selfs *= controllerScale if UIDevice.current.systemName.contains("iPadOS") { return selfs * 1.2 } + return selfs } private let shape: JoystickShape = .circle diff --git a/src/MeloNX/MeloNX/App/Views/Emulation/EmulationView/EmulationView.swift b/src/MeloNX/MeloNX/App/Views/Emulation/EmulationView/EmulationView.swift index c8a4c1590..ac577a973 100644 --- a/src/MeloNX/MeloNX/App/Views/Emulation/EmulationView/EmulationView.swift +++ b/src/MeloNX/MeloNX/App/Views/Emulation/EmulationView/EmulationView.swift @@ -11,16 +11,18 @@ import SwiftUI struct EmulationView: View { @AppStorage("isVirtualController") var isVCA: Bool = true @AppStorage("showScreenShotButton") var ssb: Bool = false + @State var isPresentedThree: Bool = false @State var isAirplaying = Air.shared.connected + @Environment(\.scenePhase) var scenePhase var body: some View { ZStack { if isAirplaying { Text("") .onAppear { - Air.play(AnyView(MetalView(airplay: true).ignoresSafeArea())) + Air.play(AnyView(MetalView().ignoresSafeArea())) } } else { - MetalView(airplay: false) // The Emulation View + MetalView() // The Emulation View .ignoresSafeArea() .edgesIgnoringSafeArea(.all) } @@ -31,6 +33,7 @@ struct EmulationView: View { ControllerView() // Virtual Controller } + if ssb { Group { VStack { diff --git a/src/MeloNX/MeloNX/App/Views/Emulation/MetalView/MetalView.swift b/src/MeloNX/MeloNX/App/Views/Emulation/MetalView/MetalView.swift index 11e4f4963..59fcb1a70 100644 --- a/src/MeloNX/MeloNX/App/Views/Emulation/MetalView/MetalView.swift +++ b/src/MeloNX/MeloNX/App/Views/Emulation/MetalView/MetalView.swift @@ -10,7 +10,7 @@ import MetalKit struct MetalView: UIViewRepresentable { - var airplay: Bool // just in case :3 + var airplay: Bool = Air.shared.connected // just in case :3 func makeUIView(context: Context) -> UIView { let metalLayer = Ryujinx.shared.metalLayer! diff --git a/src/MeloNX/MeloNX/App/Views/SettingsView/SettingsView.swift b/src/MeloNX/MeloNX/App/Views/SettingsView/SettingsView.swift index 24548b067..980b94dda 100644 --- a/src/MeloNX/MeloNX/App/Views/SettingsView/SettingsView.swift +++ b/src/MeloNX/MeloNX/App/Views/SettingsView/SettingsView.swift @@ -40,9 +40,11 @@ struct SettingsView: View { @AppStorage("oldWindowCode") var windowCode: Bool = false + @AppStorage("On-ScreenControllerScale") var controllerScale: Double = 1.0 @State private var showResolutionInfo = false @State private var showAnisotropicInfo = false + @State private var showControllerInfo = false @State private var searchText = "" var filteredMemoryModes: [(String, String)] { @@ -270,6 +272,35 @@ struct SettingsView: View { Text("Select input devices and on-screen controls to play with. ") } + // Language and Region Settings + Section { + Picker(selection: $config.language) { + ForEach(SystemLanguage.allCases, id: \.self) { ratio in + Text(ratio.displayName).tag(ratio) + } + } label: { + labelWithIcon("Language", iconName: "character.bubble") + } + + Picker(selection: $config.regioncode) { + ForEach(SystemRegionCode.allCases, id: \.self) { ratio in + Text(ratio.displayName).tag(ratio) + } + } label: { + labelWithIcon("Region", iconName: "globe") + } + + + // globe + } header: { + Text("Language and Region Settings") + .font(.title3.weight(.semibold)) + .textCase(nil) + .headerProminence(.increased) + } footer: { + Text("Configure the System Language and the Region.") + } + // Input Settings Section { @@ -283,6 +314,46 @@ struct SettingsView: View { } .tint(.blue) .disabled(true) + + VStack(alignment: .leading, spacing: 10) { + HStack { + labelWithIcon("On-Screen Controller Scale", iconName: "magnifyingglass") + .font(.headline) + Spacer() + Button { + showControllerInfo.toggle() + } label: { + Image(systemName: "info.circle") + .symbolRenderingMode(.hierarchical) + .foregroundStyle(.secondary) + } + .buttonStyle(.plain) + .help("Learn more about On-Screen Controller Scale") + .alert(isPresented: $showControllerInfo) { + Alert( + title: Text("On-Screen Controller Scale"), + message: Text("Adjust the On-Screen Controller size."), + dismissButton: .default(Text("OK")) + ) + } + } + + Slider(value: $controllerScale, in: 0.1...3.0, step: 0.05) { + Text("Resolution Scale") + } minimumValueLabel: { + Text("0.1x") + .font(.footnote) + .foregroundColor(.secondary) + } maximumValueLabel: { + Text("3.0x") + .font(.footnote) + .foregroundColor(.secondary) + } + Text("\(controllerScale, specifier: "%.2f")x") + .font(.subheadline) + .foregroundColor(.secondary) + } + .padding(.vertical, 8) } header: { Text("Input Settings") .font(.title3.weight(.semibold)) diff --git a/src/MeloNX/MeloNX/Dependencies/Dynamic Libraries/libMoltenVK.dylib b/src/MeloNX/MeloNX/Dependencies/Dynamic Libraries/libMoltenVK.dylib index b64e5535f..c1b12b543 100755 Binary files a/src/MeloNX/MeloNX/Dependencies/Dynamic Libraries/libMoltenVK.dylib and b/src/MeloNX/MeloNX/Dependencies/Dynamic Libraries/libMoltenVK.dylib differ diff --git a/src/MeloNX/MeloNX/Dependencies/XCFrameworks/MoltenVK.xcframework/ios-arm64/MoltenVK.framework/MoltenVK b/src/MeloNX/MeloNX/Dependencies/XCFrameworks/MoltenVK.xcframework/ios-arm64/MoltenVK.framework/MoltenVK index b64e5535f..495d9fb19 100755 Binary files a/src/MeloNX/MeloNX/Dependencies/XCFrameworks/MoltenVK.xcframework/ios-arm64/MoltenVK.framework/MoltenVK and b/src/MeloNX/MeloNX/Dependencies/XCFrameworks/MoltenVK.xcframework/ios-arm64/MoltenVK.framework/MoltenVK differ diff --git a/src/MeloNX/MeloNX/Info.plist b/src/MeloNX/MeloNX/Info.plist index 0cf82243f..bb9bd4980 100644 --- a/src/MeloNX/MeloNX/Info.plist +++ b/src/MeloNX/MeloNX/Info.plist @@ -15,6 +15,17 @@ + GCSupportedGameControllers + + + ProfileName + ExtendedGamepad + + + ProfileName + MicroGamepad + + LSApplicationQueriesSchemes melonx @@ -25,6 +36,11 @@ LaunchGameIntent + UIBackgroundModes + + audio + processing + UIFileSharingEnabled UTExportedTypeDeclarations diff --git a/src/Ryujinx.Headless.SDL2/Program.cs b/src/Ryujinx.Headless.SDL2/Program.cs index 2809334c2..54c1aee82 100644 --- a/src/Ryujinx.Headless.SDL2/Program.cs +++ b/src/Ryujinx.Headless.SDL2/Program.cs @@ -319,7 +319,6 @@ namespace Ryujinx.Headless.SDL2 if (_window != null) { - _window.Exit(); _emulationContext.Dispose(); _emulationContext = null; @@ -332,6 +331,7 @@ namespace Ryujinx.Headless.SDL2 if (_virtualFileSystem == null) { _virtualFileSystem = VirtualFileSystem.CreateInstance(); } + var extension = Marshal.PtrToStringAnsi(extensionPtr); var stream = OpenFile(descriptor); diff --git a/src/Ryujinx.Memory/PageTable.cs b/src/Ryujinx.Memory/PageTable.cs index ff22d028e..8b77b6fb8 100644 --- a/src/Ryujinx.Memory/PageTable.cs +++ b/src/Ryujinx.Memory/PageTable.cs @@ -4,7 +4,7 @@ namespace Ryujinx.Memory { public const int PageBits = 12; public const int PageSize = 1 << PageBits; - public const int PageMask = PageSize - 1; + public const int PageMask = PageSize - 2; private const int PtLevelBits = 9; // 9 * 4 + 12 = 48 (max address space size) private const int PtLevelSize = 1 << PtLevelBits;