diff --git a/src/MeloNX/MeloNX.xcodeproj/project.pbxproj b/src/MeloNX/MeloNX.xcodeproj/project.pbxproj
index e4e5a333e..fcf369e9f 100644
--- a/src/MeloNX/MeloNX.xcodeproj/project.pbxproj
+++ b/src/MeloNX/MeloNX.xcodeproj/project.pbxproj
@@ -634,6 +634,7 @@
"$(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;
@@ -806,6 +807,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",
);
MARKETING_VERSION = 0.0.8;
PRODUCT_BUNDLE_IDENTIFIER = com.stossy11.MeloNX;
@@ -845,6 +850,7 @@
"$(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;
@@ -1017,6 +1023,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",
);
MARKETING_VERSION = 0.0.8;
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 c300499fa..f5c700e80 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 62375ba69..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
- 1
+ 2
com.Stossy11.MeloNX.RyujinxAg.xcscheme_^#shared#^_
orderHint
- 2
+ 1
SuppressBuildableAutocreation
diff --git a/src/MeloNX/MeloNX/Core/Swift/Ryujinx.swift b/src/MeloNX/MeloNX/Core/Swift/Ryujinx.swift
index 52e0ae7b7..204afd17f 100644
--- a/src/MeloNX/MeloNX/Core/Swift/Ryujinx.swift
+++ b/src/MeloNX/MeloNX/Core/Swift/Ryujinx.swift
@@ -152,9 +152,9 @@ class Ryujinx {
args.append(contentsOf: ["--memory-manager-mode", config.memoryManagerMode])
- // args.append(contentsOf: ["--exclusive-fullscreen", String(config.fullscreen)])
- // args.append(contentsOf: ["--exclusive-fullscreen-width", "\(Int(UIScreen.main.bounds.width))"])
- // args.append(contentsOf: ["--exclusive-fullscreen-height", "\(Int(UIScreen.main.bounds.height))"])
+ args.append(contentsOf: ["--exclusive-fullscreen", String(true)])
+ args.append(contentsOf: ["--exclusive-fullscreen-width", "\(Int(UIScreen.main.bounds.width))"])
+ args.append(contentsOf: ["--exclusive-fullscreen-height", "\(Int(UIScreen.main.bounds.height))"])
// We don't need this. Ryujinx should handle it fine :3
if config.fullscreen {
@@ -174,10 +174,11 @@ class Ryujinx {
args.append(contentsOf: ["--resolution-scale", String(config.resscale)])
}
- if config.disableShaderCache {
+ if !config.disableShaderCache { // same with disableShaderCache
args.append("--disable-shader-cache")
}
- if config.disableDockedMode {
+
+ if !config.disableDockedMode { // disableDockedMode is actually enableDockedMode, i just have flipped it around in the settings page to make it easier to understand :3
args.append("--disable-docked-mode")
}
if config.enableTextureRecompression {
diff --git a/src/MeloNX/MeloNX/Views/ContentView.swift b/src/MeloNX/MeloNX/Views/ContentView.swift
index f91f38dd5..0fa635617 100644
--- a/src/MeloNX/MeloNX/Views/ContentView.swift
+++ b/src/MeloNX/MeloNX/Views/ContentView.swift
@@ -22,7 +22,6 @@ struct MoltenVKSettings: Codable, Hashable {
struct ContentView: View {
// MARK: - Properties
@State private var theWindow: UIWindow?
- @State private var virtualController: GCVirtualController?
@State private var game: Game?
@State private var controllersList: [Controller] = []
@State private var currentControllers: [Controller] = []
@@ -37,6 +36,11 @@ struct ContentView: View {
@AppStorage("quit") var quit: Bool = false
@State var quits: Bool = false
+ @State private var clumpOffset: CGFloat = -100
+ private let clumpWidth: CGFloat = 100
+ private let animationDuration: Double = 1.0
+ @State private var isAnimating = false
+ @State var isLoading = true
// MARK: - Initialization
init() {
@@ -58,18 +62,27 @@ struct ContentView: View {
// MARK: - Body
var body: some View {
if let game, quits == false {
- emulationView
- .onAppear() {
- Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { timer in
- timer.invalidate()
- quits = quit
-
- if quits {
- quit = false
+ if isLoading {
+ emulationView
+ .onAppear() {
+ Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { timer in
timer.invalidate()
+ quits = quit
+
+ if quits {
+ quit = false
+ timer.invalidate()
+ }
}
}
+ } else {
+ VStack {
+
}
+ .onAppear() {
+ isAnimating = false
+ }
+ }
} else {
mainMenuView
.onAppear() {
@@ -81,15 +94,80 @@ struct ContentView: View {
// MARK: - View Components
private var emulationView: some View {
- ZStack {
-
- }
- .onAppear {
-
- setupEmulation()
+ GeometryReader { screenGeometry in
+ ZStack {
+ HStack(spacing: screenGeometry.size.width * 0.04) {
+ if let icon = game?.icon {
+ Image(uiImage: icon)
+ .resizable()
+ .frame(
+ width: min(screenGeometry.size.width * 0.25, 250),
+ height: min(screenGeometry.size.width * 0.25, 250)
+ )
+ .clipShape(RoundedRectangle(cornerRadius: 16))
+ .shadow(color: .black.opacity(0.5), radius: 10, x: 0, y: 5)
+ }
+
+ VStack(alignment: .leading, spacing: screenGeometry.size.height * 0.015) {
+ Text("Loading \(game?.titleName ?? "Game")")
+ .font(.system(size: min(screenGeometry.size.width * 0.04, 32)))
+ .foregroundColor(.white)
+
+ GeometryReader { geometry in
+ let containerWidth = min(screenGeometry.size.width * 0.35, 350)
+
+ ZStack(alignment: .leading) {
+ // Background track
+ Rectangle()
+ .cornerRadius(10)
+ .frame(width: containerWidth, height: min(screenGeometry.size.height * 0.015, 12))
+ .foregroundColor(.gray.opacity(0.3))
+ .shadow(color: .black.opacity(0.2), radius: 4, x: 0, y: 2)
+
+ // Animated loading bar
+ Rectangle()
+ .cornerRadius(10)
+ .frame(width: clumpWidth, height: min(screenGeometry.size.height * 0.015, 12))
+ .foregroundColor(.blue)
+ .shadow(color: .blue.opacity(0.5), radius: 4, x: 0, y: 2)
+ .offset(x: isAnimating ? containerWidth : -clumpWidth)
+ .animation(
+ Animation.linear(duration: 1.0)
+ .repeatForever(autoreverses: false),
+ value: isAnimating
+ )
+ }
+ .clipShape(RoundedRectangle(cornerRadius: 16))
+ .onAppear {
+ isAnimating = true
+
+ setupEmulation()
+
+
+ Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { timer in
+ if get_current_fps() != 0 {
+ isLoading = false
+ isAnimating = false
+ timer.invalidate()
+ }
+ print(get_current_fps())
+ }
+ }
+ }
+ .frame(height: min(screenGeometry.size.height * 0.015, 12))
+ .frame(width: min(screenGeometry.size.width * 0.35, 350))
+ }
+ }
+ .padding(.horizontal, screenGeometry.size.width * 0.06)
+ .padding(.vertical, screenGeometry.size.height * 0.05)
+ .position(
+ x: screenGeometry.size.width / 2,
+ y: screenGeometry.size.height * 0.5
+ )
}
+ }
}
-
+
private var mainMenuView: some View {
MainTabView(startemu: $game, config: $config, MVKconfig: $settings, controllersList: $controllersList, currentControllers: $currentControllers, onscreencontroller: $onscreencontroller)
.onAppear() {
@@ -116,7 +194,6 @@ struct ContentView: View {
}
private func setupEmulation() {
- virtualController?.disconnect()
patchMakeKeyAndVisible()
if (currentControllers.first(where: { $0 == onscreencontroller }) != nil) {
@@ -203,6 +280,8 @@ struct ContentView: View {
print("Error: \(error.localizedDescription)")
}
}
+
+
private func setMoltenVKSettings() {
diff --git a/src/MeloNX/MeloNX/Views/GamesList/GameListView.swift b/src/MeloNX/MeloNX/Views/GamesList/GameListView.swift
index 917a7ee9e..4d722d14d 100644
--- a/src/MeloNX/MeloNX/Views/GamesList/GameListView.swift
+++ b/src/MeloNX/MeloNX/Views/GamesList/GameListView.swift
@@ -140,7 +140,7 @@ struct GameLibraryView: View {
Button {
- var game = Game(containerFolder: URL(string: "none")!, fileType: .item, fileURL: URL(string: "MiiMaker")!, titleName: "Mii Maker", titleId: "0", developer: "Nintendo", version: firmwareversion)
+ let game = Game(containerFolder: URL(string: "none")!, fileType: .item, fileURL: URL(string: "MiiMaker")!, titleName: "Mii Maker", titleId: "0", developer: "Nintendo", version: firmwareversion)
self.startemu = game
} label: {
@@ -165,7 +165,7 @@ struct GameLibraryView: View {
Text("Show MeloNX Folder")
}
} label: {
- Image(systemName: "ellipsis")
+ Image(systemName: "ellipsis.circle")
.foregroundColor(.blue)
}
@@ -349,7 +349,6 @@ struct GameLibraryView: View {
}
}
-// Make sure your Game model conforms to Codable
extension Game: Codable {
enum CodingKeys: String, CodingKey {
case titleName, titleId, developer, version, fileURL
diff --git a/src/MeloNX/MeloNX/Views/SettingsView/SettingsView.swift b/src/MeloNX/MeloNX/Views/SettingsView/SettingsView.swift
index e016d8e88..838f227fc 100644
--- a/src/MeloNX/MeloNX/Views/SettingsView/SettingsView.swift
+++ b/src/MeloNX/MeloNX/Views/SettingsView/SettingsView.swift
@@ -52,7 +52,7 @@ struct SettingsView: View {
.tint(.blue)
Toggle(isOn: $config.disableShaderCache) {
- labelWithIcon("Disable Shader Cache", iconName: "memorychip")
+ labelWithIcon("Shader Cache", iconName: "memorychip")
}
.tint(.blue)
@@ -62,7 +62,7 @@ struct SettingsView: View {
.tint(.blue)
Toggle(isOn: $config.disableDockedMode) {
- labelWithIcon("Disable Docked Mode", iconName: "dock.rectangle")
+ labelWithIcon("Docked Mode", iconName: "dock.rectangle")
}
.tint(.blue)
diff --git a/src/Ryujinx.Headless.SDL2/Program.cs b/src/Ryujinx.Headless.SDL2/Program.cs
index f6f9de017..585bc00ff 100644
--- a/src/Ryujinx.Headless.SDL2/Program.cs
+++ b/src/Ryujinx.Headless.SDL2/Program.cs
@@ -1306,7 +1306,7 @@ namespace Ryujinx.Headless.SDL2
options.IgnoreMissingServices,
options.AspectRatio,
options.AudioVolume,
- options.UseHypervisor ?? true,
+ options.UseHypervisor ?? false,
options.MultiplayerLanInterfaceId,
Common.Configuration.Multiplayer.MultiplayerMode.LdnMitm);
@@ -1499,75 +1499,75 @@ namespace Ryujinx.Headless.SDL2
return new FileStream(safeHandle, FileAccess.ReadWrite);
}
- public class GameInfo
- {
- public double FileSize;
- public string? TitleName;
- public string? TitleId;
- public string? Developer;
- public string? Version;
- public byte[]? Icon;
- }
-
-public unsafe struct GameInfoNative
-{
- public ulong FileSize;
- public fixed byte TitleName[512];
- public ulong TitleId;
- public fixed byte Developer[256];
- public uint Version;
- public byte* ImageData; // Changed to pointer
- public uint ImageSize; // Actual size of image data
-
- public GameInfoNative(ulong fileSize, string titleName, ulong titleId, string developer, uint version, byte[] imageData)
- {
- FileSize = fileSize;
- TitleId = titleId;
- Version = version;
-
- fixed (byte* developerPtr = Developer)
- fixed (byte* titleNamePtr = TitleName)
+ public class GameInfo
{
- CopyStringToFixedArray(titleName, titleNamePtr, 512);
- CopyStringToFixedArray(developer, developerPtr, 256);
+ public double FileSize;
+ public string? TitleName;
+ public string? TitleId;
+ public string? Developer;
+ public string? Version;
+ public byte[]? Icon;
}
- if (imageData == null || imageData.Length > 4096 * 4096)
+ public unsafe struct GameInfoNative
{
- // throw new ArgumentException("Image data must not exceed 4 MB.");
- ImageSize = (uint)0;
- ImageData = null;
- }
- else
- {
- ImageSize = (uint)imageData.Length;
-
- ImageData = (byte*)Marshal.AllocHGlobal(imageData.Length);
-
- Marshal.Copy(imageData, 0, (IntPtr)ImageData, imageData.Length);
- }
- }
+ public ulong FileSize;
+ public fixed byte TitleName[512];
+ public ulong TitleId;
+ public fixed byte Developer[256];
+ public uint Version;
+ public byte* ImageData;
+ public uint ImageSize;
- // Don't forget to free the allocated memory
- public void Dispose()
- {
- if (ImageData != null)
- {
- Marshal.FreeHGlobal((IntPtr)ImageData);
- ImageData = null;
- }
- }
- private static void CopyStringToFixedArray(string source, byte* destination, int length)
- {
- var span = new Span(destination, length);
- Encoding.UTF8.GetBytes(source, span);
- }
+ public GameInfoNative(ulong fileSize, string titleName, ulong titleId, string developer, uint version, byte[] imageData)
+ {
+ FileSize = fileSize;
+ TitleId = titleId;
+ Version = version;
- private static void CopyArrayToFixedArray(byte[] source, byte* destination, int maxLength)
- {
- var span = new Span(destination, maxLength);
- source.AsSpan().CopyTo(span);
+ fixed (byte* developerPtr = Developer)
+ fixed (byte* titleNamePtr = TitleName)
+ {
+ CopyStringToFixedArray(titleName, titleNamePtr, 512);
+ CopyStringToFixedArray(developer, developerPtr, 256);
+ }
+
+ if (imageData == null || imageData.Length > 4096 * 4096)
+ {
+ // throw new ArgumentException("Image data must not exceed 4 MB.");
+ ImageSize = (uint)0;
+ ImageData = null;
+ }
+ else
+ {
+ ImageSize = (uint)imageData.Length;
+
+ ImageData = (byte*)Marshal.AllocHGlobal(imageData.Length);
+
+ Marshal.Copy(imageData, 0, (IntPtr)ImageData, imageData.Length);
+ }
+ }
+
+ // Don't forget to free the allocated memory
+ public void Dispose()
+ {
+ if (ImageData != null)
+ {
+ Marshal.FreeHGlobal((IntPtr)ImageData);
+ ImageData = null;
+ }
+ }
+ private static void CopyStringToFixedArray(string source, byte* destination, int length)
+ {
+ var span = new Span(destination, length);
+ Encoding.UTF8.GetBytes(source, span);
+ }
+
+ private static void CopyArrayToFixedArray(byte[] source, byte* destination, int maxLength)
+ {
+ var span = new Span(destination, maxLength);
+ source.AsSpan().CopyTo(span);
+ }
}
}
- }
}