diff --git a/src/MeloNX/MeloNX.xcodeproj/project.pbxproj b/src/MeloNX/MeloNX.xcodeproj/project.pbxproj index 25549a984..b32e8a35b 100644 --- a/src/MeloNX/MeloNX.xcodeproj/project.pbxproj +++ b/src/MeloNX/MeloNX.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 73; + objectVersion = 70; objects = { /* Begin PBXAggregateTarget section */ @@ -76,107 +76,8 @@ BD43C6302D1B8211003BBC42 /* dotnet.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = dotnet.xcconfig; sourceTree = ""; }; /* End PBXFileReference section */ -/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */ - 4E80AA1D2CD7015100029585 /* PBXFileSystemSynchronizedBuildFileExceptionSet */ = { - isa = PBXFileSystemSynchronizedBuildFileExceptionSet; - membershipExceptions = ( - Info.plist, - ); - target = 4E80A98C2CD6F54500029585 /* MeloNX */; - }; -/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */ - -/* Begin PBXFileSystemSynchronizedGroupBuildPhaseMembershipExceptionSet section */ - 4E9A82F32CF87822006D7086 /* PBXFileSystemSynchronizedGroupBuildPhaseMembershipExceptionSet */ = { - isa = PBXFileSystemSynchronizedGroupBuildPhaseMembershipExceptionSet; - attributesByRelativePath = { - "Dependencies/Dynamic Libraries/Ryujinx.Headless.SDL2.dylib" = ( - CodeSignOnCopy, - ); - "Dependencies/Dynamic Libraries/SoftwareKeyboard.framework" = ( - CodeSignOnCopy, - RemoveHeadersOnCopy, - ); - "Dependencies/Dynamic Libraries/libMoltenVK.dylib" = ( - CodeSignOnCopy, - ); - "Dependencies/Dynamic Libraries/libavcodec.dylib" = ( - CodeSignOnCopy, - ); - "Dependencies/Dynamic Libraries/libavutil.dylib" = ( - CodeSignOnCopy, - ); - Dependencies/XCFrameworks/MoltenVK.xcframework = ( - CodeSignOnCopy, - RemoveHeadersOnCopy, - ); - Dependencies/XCFrameworks/SDL2.xcframework = ( - CodeSignOnCopy, - RemoveHeadersOnCopy, - ); - Dependencies/XCFrameworks/libSPIRV.xcframework = ( - CodeSignOnCopy, - RemoveHeadersOnCopy, - ); - Dependencies/XCFrameworks/libavcodec.xcframework = ( - CodeSignOnCopy, - RemoveHeadersOnCopy, - ); - Dependencies/XCFrameworks/libavfilter.xcframework = ( - CodeSignOnCopy, - RemoveHeadersOnCopy, - ); - Dependencies/XCFrameworks/libavformat.xcframework = ( - CodeSignOnCopy, - RemoveHeadersOnCopy, - ); - Dependencies/XCFrameworks/libavutil.xcframework = ( - CodeSignOnCopy, - RemoveHeadersOnCopy, - ); - Dependencies/XCFrameworks/libswresample.xcframework = ( - CodeSignOnCopy, - RemoveHeadersOnCopy, - ); - Dependencies/XCFrameworks/libswscale.xcframework = ( - CodeSignOnCopy, - RemoveHeadersOnCopy, - ); - Dependencies/XCFrameworks/libteakra.xcframework = ( - CodeSignOnCopy, - RemoveHeadersOnCopy, - ); - }; - buildPhase = 4E80AA092CD6FAA800029585 /* Embed Libraries */; - membershipExceptions = ( - "Dependencies/Dynamic Libraries/libavcodec.dylib", - "Dependencies/Dynamic Libraries/libavutil.dylib", - "Dependencies/Dynamic Libraries/libMoltenVK.dylib", - "Dependencies/Dynamic Libraries/Ryujinx.Headless.SDL2.dylib", - "Dependencies/Dynamic Libraries/SoftwareKeyboard.framework", - Dependencies/XCFrameworks/libavcodec.xcframework, - Dependencies/XCFrameworks/libavfilter.xcframework, - Dependencies/XCFrameworks/libavformat.xcframework, - Dependencies/XCFrameworks/libavutil.xcframework, - Dependencies/XCFrameworks/libSPIRV.xcframework, - Dependencies/XCFrameworks/libswresample.xcframework, - Dependencies/XCFrameworks/libswscale.xcframework, - Dependencies/XCFrameworks/libteakra.xcframework, - Dependencies/XCFrameworks/MoltenVK.xcframework, - Dependencies/XCFrameworks/SDL2.xcframework, - ); - }; - BD43C6122D1B1769003BBC42 /* PBXFileSystemSynchronizedGroupBuildPhaseMembershipExceptionSet */ = { - isa = PBXFileSystemSynchronizedGroupBuildPhaseMembershipExceptionSet; - buildPhase = 4E80A9892CD6F54500029585 /* Sources */; - membershipExceptions = ( - "Core/Headers/Ryujinx-Header.h", - ); - }; -/* End PBXFileSystemSynchronizedGroupBuildPhaseMembershipExceptionSet section */ - /* Begin PBXFileSystemSynchronizedRootGroup section */ - 4E80A98F2CD6F54500029585 /* MeloNX */ = {isa = PBXFileSystemSynchronizedRootGroup; exceptions = (4E80AA1D2CD7015100029585 /* PBXFileSystemSynchronizedBuildFileExceptionSet */, BD43C6122D1B1769003BBC42 /* PBXFileSystemSynchronizedGroupBuildPhaseMembershipExceptionSet */, 4E9A82F32CF87822006D7086 /* PBXFileSystemSynchronizedGroupBuildPhaseMembershipExceptionSet */, ); explicitFileTypes = {}; explicitFolders = (); path = MeloNX; sourceTree = ""; }; + 4E80A98F2CD6F54500029585 /* MeloNX */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = MeloNX; sourceTree = ""; }; 4E80A9A02CD6F54700029585 /* MeloNXTests */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = MeloNXTests; sourceTree = ""; }; 4E80A9AA2CD6F54700029585 /* MeloNXUITests */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = MeloNXUITests; sourceTree = ""; }; /* End PBXFileSystemSynchronizedRootGroup section */ @@ -363,6 +264,7 @@ }; }; buildConfigurationList = 4E80A9882CD6F54500029585 /* Build configuration list for PBXProject "MeloNX" */; + compatibilityVersion = "Xcode 14.0"; developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( @@ -375,7 +277,6 @@ 4E0DED322D05695D00FEF007 /* XCRemoteSwiftPackageReference "SwiftUIJoystick" */, 4EA5AE802D16807500AD0B9F /* XCRemoteSwiftPackageReference "SwiftSVG" */, ); - preferredProjectObjectVersion = 56; productRefGroup = 4E80A98E2CD6F54500029585 /* Products */; projectDirPath = ""; projectRoot = ""; @@ -622,7 +523,7 @@ CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = ""; - DEVELOPMENT_TEAM = 95J8WZ4TN8; + DEVELOPMENT_TEAM = F4QL9A2T88; ENABLE_PREVIEWS = YES; ENABLE_TESTABILITY = NO; FRAMEWORK_SEARCH_PATHS = ( @@ -635,6 +536,8 @@ "$(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; @@ -788,9 +691,16 @@ "$(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 = com.stossy11.MeloNX; + PRODUCT_BUNDLE_IDENTIFIER = com.stossy11.MeloNX1; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_OBJC_BRIDGING_HEADER = "MeloNX/Core/Headers/Ryujinx-Header.h"; @@ -808,7 +718,7 @@ CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = ""; - DEVELOPMENT_TEAM = 95J8WZ4TN8; + DEVELOPMENT_TEAM = F4QL9A2T88; ENABLE_PREVIEWS = YES; ENABLE_TESTABILITY = YES; FRAMEWORK_SEARCH_PATHS = ( @@ -821,6 +731,8 @@ "$(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; @@ -974,9 +886,16 @@ "$(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 = com.stossy11.MeloNX; + PRODUCT_BUNDLE_IDENTIFIER = com.stossy11.MeloNX1; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_OBJC_BRIDGING_HEADER = "MeloNX/Core/Headers/Ryujinx-Header.h"; diff --git a/src/MeloNX/MeloNX.xcodeproj/project.xcworkspace/xcuserdata/techguy.xcuserdatad/UserInterfaceState.xcuserstate b/src/MeloNX/MeloNX.xcodeproj/project.xcworkspace/xcuserdata/techguy.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 000000000..805b0c676 Binary files /dev/null and b/src/MeloNX/MeloNX.xcodeproj/project.xcworkspace/xcuserdata/techguy.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/src/MeloNX/MeloNX.xcodeproj/xcuserdata/techguy.xcuserdatad/xcschemes/xcschememanagement.plist b/src/MeloNX/MeloNX.xcodeproj/xcuserdata/techguy.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 000000000..91a670474 --- /dev/null +++ b/src/MeloNX/MeloNX.xcodeproj/xcuserdata/techguy.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,24 @@ + + + + + SchemeUserState + + MeloNX.xcscheme_^#shared#^_ + + orderHint + 0 + + Ryujinx.xcscheme_^#shared#^_ + + orderHint + 2 + + com.Stossy11.MeloNX.RyujinxAg.xcscheme_^#shared#^_ + + orderHint + 1 + + + + diff --git a/src/MeloNX/MeloNX/Core/Swift/Ryujinx.swift b/src/MeloNX/MeloNX/Core/Swift/Ryujinx.swift index ba96f35b9..bd4057056 100644 --- a/src/MeloNX/MeloNX/Core/Swift/Ryujinx.swift +++ b/src/MeloNX/MeloNX/Core/Swift/Ryujinx.swift @@ -97,10 +97,12 @@ class Ryujinx { isRunning = true - // Start The Emulation on the main thread RunLoop.current.perform { + let url = URL(string: config.gamepath)! + do { let args = self.buildCommandLineArgs(from: config) + let accessing = url.startAccessingSecurityScopedResource() // Convert Arguments to ones that Ryujinx can Read let cArgs = args.map { strdup($0) } @@ -112,6 +114,10 @@ class Ryujinx { if result != 0 { self.isRunning = false + if accessing { + url.stopAccessingSecurityScopedResource() + } + throw RyujinxError.executionError(code: result) } } catch { diff --git a/src/MeloNX/MeloNX/Views/GamesList/GameListView.swift b/src/MeloNX/MeloNX/Views/GamesList/GameListView.swift index 511a5068d..9f888cd4c 100644 --- a/src/MeloNX/MeloNX/Views/GamesList/GameListView.swift +++ b/src/MeloNX/MeloNX/Views/GamesList/GameListView.swift @@ -19,6 +19,9 @@ struct GameLibraryView: View { @Environment(\.colorScheme) var colorScheme @State var firmwareInstaller = false @State var firmwareversion = "0" + @State var isImporting: Bool = false + @State var startgame = false + var filteredGames: [Game] { if searchText.isEmpty { @@ -141,6 +144,12 @@ struct GameLibraryView: View { } label: { Text("Mii Maker") } + Button { + + isImporting.toggle() + } label: { + Text("Open game from system") + } } Button { @@ -188,6 +197,24 @@ struct GameLibraryView: View { print(error) } } + .fileImporter(isPresented: $isImporting, allowedContentTypes: [.zip, .data]) { result in + switch result { + case .success(let url): + guard url.startAccessingSecurityScopedResource() else { + print("Failed to access security-scoped resource") + return + } + defer { url.stopAccessingSecurityScopedResource() } + + + startemu = url + + case .failure(let err): + print("File import failed: \(err.localizedDescription)") + } + } + + } diff --git a/src/MeloNX/MeloNX/Views/SettingsView/Info View/DeviceMemory.swift b/src/MeloNX/MeloNX/Views/SettingsView/Info View/DeviceMemory.swift new file mode 100644 index 000000000..70eccdd2f --- /dev/null +++ b/src/MeloNX/MeloNX/Views/SettingsView/Info View/DeviceMemory.swift @@ -0,0 +1,25 @@ +// +// DeviceMemory.swift +// MeloNX +// +// Created by Tech Guy on 12/31/24. +// +import SwiftUI +import Foundation +import UIKit + +enum DeviceMemory { + /// Check if device has 8GB or more RAM + static var has8GBOrMore: Bool { + #if targetEnvironment(simulator) + return ProcessInfo.processInfo.physicalMemory >= 7 * 1024 * 1024 * 1024 // 8GB in bytes + #else + return ProcessInfo.processInfo.physicalMemory >= 7 * 1024 * 1024 * 1024 // 8GB in bytes + #endif + } + + /// Get total RAM in GB (rounded) + static var totalRAM: Int { + Int(ProcessInfo.processInfo.physicalMemory / 1024 / 1024 / 1024) + 1 + } +} diff --git a/src/MeloNX/MeloNX/Views/SettingsView/Info View/InfoView.swift b/src/MeloNX/MeloNX/Views/SettingsView/Info View/InfoView.swift new file mode 100644 index 000000000..aed7ab426 --- /dev/null +++ b/src/MeloNX/MeloNX/Views/SettingsView/Info View/InfoView.swift @@ -0,0 +1,95 @@ +// +// InfoView.swift +// MeloNX +// +// Created by Tech Guy on 12/31/24. +// + + +import SwiftUI + +struct InfoView: View { + @AppStorage("entitlementExists") private var entitlementExists: Bool = false + @AppStorage("increaseddebugmem") private var increaseddebugmem: Bool = false + @AppStorage("extended-virtual-addressing") private var extended: Bool = false + @State var gd = false + let infoDictionary = Bundle.main.infoDictionary + + var body: some View { + ScrollView { + VStack { + Text("Welcome to MeloNX!") + .font(.largeTitle) + Divider() + Text("Entitlements:") + .font(.title) + .font(Font.headline.weight(.bold)) + Spacer() + .frame(height: 10) + Group { + Text("Required:") + .font(.title2) + .foregroundColor(.red) + .font(Font.headline.weight(.bold)) + Spacer() + .frame(height: 10) + Text("Increased Memory Limit: \(String(describing: entitlementExists))") + Spacer() + .frame(height: 10) + } + Group { + Spacer() + .frame(height: 10) + Text("Reccomended (paid):") + .font(.title2) + .font(Font.headline.weight(.bold)) + Spacer() + .frame(height: 10) + Text("Increased Debugging Memory Limit: \(String(describing: increaseddebugmem))") + .padding() + Text("Extended Virtual Addressing: \(String(describing: extended))") + } + + Divider() + Text("Memory:") + .font(.title) + .font(Font.headline.weight(.bold)) + Spacer() + .frame(height: 10) + Group { + Text("Current:") + .font(.title2) + .foregroundColor(.blue) + .font(Font.headline.weight(.bold)) + Spacer() + .frame(height: 10) + Text(String(DeviceMemory.totalRAM) + "GB") + Spacer() + .frame(height: 10) + } + + } + .padding() + + HStack { + Text("Version: \(getAppVersion())") + .foregroundColor(.white) + .font(.system(size: 12)) + .onTapGesture { + gd.toggle() + } + if getAppVersion() == "2.2", gd { + Text("Geometry Dash????? ;)") + .foregroundStyle(.secondary) + .font(.system(size: 5)) + } + } + } + } + func getAppVersion() -> String { + guard let version = infoDictionary?["CFBundleShortVersionString"] as? String else { + return "Unknown" + } + return version + } +} diff --git a/src/MeloNX/MeloNX/Views/SettingsView/SettingsView.swift b/src/MeloNX/MeloNX/Views/SettingsView/SettingsView.swift index ab3746528..dafa2a518 100644 --- a/src/MeloNX/MeloNX/Views/SettingsView/SettingsView.swift +++ b/src/MeloNX/MeloNX/Views/SettingsView/SettingsView.swift @@ -42,6 +42,8 @@ struct SettingsView: View { var body: some View { iOSNav { List { + + // Graphics & Performance Section { Toggle(isOn: $config.fullscreen) { @@ -296,7 +298,10 @@ struct SettingsView: View { } label: { Text("Advanced Options") } - + NavigationLink(destination: InfoView()) { + Text("About") + + } } header: { Text("Advanced") .font(.title3.weight(.semibold)) @@ -305,6 +310,7 @@ struct SettingsView: View { } footer: { Text("For advanced users. See page size or add custom arguments for experimental features. (Please don't touch this if you don't know what you're doing)") } + } .searchable(text: $searchText, placement: .navigationBarDrawer(displayMode: .always)) .navigationTitle("Settings")