forked from MeloNX/MeloNX
Add Config Editor
This commit is contained in:
parent
098467f3f3
commit
e02927cadb
Binary file not shown.
@ -23,7 +23,7 @@
|
||||
<BreakpointActionProxy
|
||||
ActionExtensionID = "Xcode.BreakpointAction.DebuggerCommand">
|
||||
<ActionContent
|
||||
consoleCommand = "process handle --stop false SIGUSR1">
|
||||
consoleCommand = "process handle -s false -n false">
|
||||
</ActionContent>
|
||||
</BreakpointActionProxy>
|
||||
</Actions>
|
||||
@ -45,5 +45,30 @@
|
||||
landmarkType = "7">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
<BreakpointProxy
|
||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||
<BreakpointContent
|
||||
uuid = "900AC928-2B0F-4BBE-A47D-D6B17570E9BB"
|
||||
shouldBeEnabled = "Yes"
|
||||
nameForDebugger = "SIGUSR1-Disable"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
filePath = "MeloNX/Views/ContentView.swift"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "131"
|
||||
endingLineNumber = "131"
|
||||
landmarkName = "start(displayid:)"
|
||||
landmarkType = "7">
|
||||
<Actions>
|
||||
<BreakpointActionProxy
|
||||
ActionExtensionID = "Xcode.BreakpointAction.DebuggerCommand">
|
||||
<ActionContent
|
||||
consoleCommand = "process handle --stop false SIGUSR1">
|
||||
</ActionContent>
|
||||
</BreakpointActionProxy>
|
||||
</Actions>
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
</Breakpoints>
|
||||
</Bucket>
|
||||
|
@ -20,25 +20,48 @@ class Ryujinx {
|
||||
|
||||
@Published var controllerMap: [Controller] = []
|
||||
|
||||
public struct Configuration {
|
||||
let gamepath: String
|
||||
let inputids: [String]
|
||||
let debuglogs: Bool
|
||||
let tracelogs: Bool
|
||||
let listinputids: Bool
|
||||
let fullscreen: Bool
|
||||
public struct Configuration : Codable {
|
||||
var gamepath: String
|
||||
var inputids: [String]
|
||||
var debuglogs: Bool
|
||||
var tracelogs: Bool
|
||||
var listinputids: Bool
|
||||
var fullscreen: Bool
|
||||
var hostMappedMemory: Bool
|
||||
var disableVSync: Bool
|
||||
var disableShaderCache: Bool
|
||||
var disableDockedMode: Bool
|
||||
var enableTextureRecompression: Bool
|
||||
var additionalArgs: [String]
|
||||
|
||||
init(gamepath: String, additionalArgs: [String] = [], debuglogs: Bool = false, tracelogs: Bool = false, listinputids: Bool = false, inputids: [String] = [], ryufullscreen: Bool = false) {
|
||||
init(gamepath: String,
|
||||
inputids: [String] = [],
|
||||
debuglogs: Bool = false,
|
||||
tracelogs: Bool = false,
|
||||
listinputids: Bool = false,
|
||||
fullscreen: Bool = false,
|
||||
hostMappedMemory: Bool = false,
|
||||
disableVSync: Bool = true,
|
||||
disableShaderCache: Bool = false,
|
||||
disableDockedMode: Bool = true,
|
||||
enableTextureRecompression: Bool = true,
|
||||
additionalArgs: [String] = []) {
|
||||
self.gamepath = gamepath
|
||||
self.inputids = inputids
|
||||
self.debuglogs = debuglogs
|
||||
self.tracelogs = tracelogs
|
||||
self.inputids = inputids
|
||||
self.listinputids = listinputids
|
||||
self.fullscreen = ryufullscreen
|
||||
self.fullscreen = fullscreen
|
||||
self.disableVSync = disableVSync
|
||||
self.disableShaderCache = disableShaderCache
|
||||
self.disableDockedMode = disableDockedMode
|
||||
self.enableTextureRecompression = enableTextureRecompression
|
||||
self.additionalArgs = additionalArgs
|
||||
self.hostMappedMemory = hostMappedMemory
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
func start(with config: Configuration) throws {
|
||||
guard !isRunning else {
|
||||
@ -94,25 +117,36 @@ class Ryujinx {
|
||||
args.append("Vulkan")
|
||||
|
||||
// Fixes the Stubs.DispatchLoop Crash
|
||||
// args.append(contentsOf: ["--memory-manager-mode", "HostMapped"])
|
||||
args.append(contentsOf: ["--memory-manager-mode", "SoftwarePageTable"])
|
||||
if config.hostMappedMemory {
|
||||
args.append(contentsOf: ["--memory-manager-mode", "HostMapped"])
|
||||
} else {
|
||||
args.append(contentsOf: ["--memory-manager-mode", "SoftwarePageTable"])
|
||||
}
|
||||
if config.fullscreen {
|
||||
// args.append(contentsOf: ["--fullscreen", String(config.fullscreen)])
|
||||
args.append(contentsOf: ["--exclusive-fullscreen", String(config.fullscreen)])
|
||||
args.append(contentsOf: ["--exclusive-fullscreen-width", "1280"])
|
||||
args.append(contentsOf: ["--exclusive-fullscreen-height", "720"])
|
||||
// exclusive-fullscreen
|
||||
}
|
||||
args.append(contentsOf: ["--disable-vsync", "true"]) // ios already forces vsync
|
||||
args.append(contentsOf: ["--disable-shader-cache", "false"])
|
||||
args.append(contentsOf: ["--disable-docked-mode", "true"])
|
||||
args.append(contentsOf: ["--enable-texture-recompression", "true"])
|
||||
|
||||
// Adding default args directly into additionalArgs
|
||||
if config.disableVSync {
|
||||
args.append("--disable-vsync")
|
||||
}
|
||||
if config.disableShaderCache {
|
||||
args.append("--disable-shader-cache")
|
||||
}
|
||||
if config.disableDockedMode {
|
||||
args.append("--disable-docked-mode")
|
||||
}
|
||||
if config.enableTextureRecompression {
|
||||
args.append("--enable-texture-recompression")
|
||||
}
|
||||
|
||||
if config.debuglogs {
|
||||
args.append(contentsOf: ["--enable-debug-logs", String(config.debuglogs)])
|
||||
args.append(contentsOf: ["--enable-debug-logs"])
|
||||
}
|
||||
if config.tracelogs {
|
||||
args.append(contentsOf: ["--enable-trace-logs", String(config.tracelogs)])
|
||||
args.append(contentsOf: ["--enable-trace-logs"])
|
||||
}
|
||||
|
||||
// List the input ids
|
||||
|
@ -20,6 +20,7 @@ struct ContentView: View {
|
||||
@State var game: URL? = nil
|
||||
@State var controllersList: [Controller] = []
|
||||
@State var currentControllers: [Controller] = []
|
||||
@State var config: Ryujinx.Configuration = Ryujinx.Configuration(gamepath: "")
|
||||
|
||||
@State private var settings: [MoltenVKSettings] = [
|
||||
MoltenVKSettings(string: "MVK_CONFIG_SYNCHRONOUS_QUEUE_SUBMITS", value: "0"),
|
||||
@ -77,26 +78,35 @@ struct ContentView: View {
|
||||
}
|
||||
|
||||
List {
|
||||
Button {
|
||||
controllersList = Ryujinx().getConnectedControllers()
|
||||
controllersList.removeAll(where: { $0.id == "0" })
|
||||
} label: {
|
||||
Text("Refresh")
|
||||
Section("Settings") {
|
||||
NavigationLink {
|
||||
SettingsView(config: $config)
|
||||
} label: {
|
||||
Text("Config")
|
||||
}
|
||||
}
|
||||
ForEach(controllersList, id: \.self) { controller in
|
||||
HStack {
|
||||
Button {
|
||||
if currentControllers.contains(where: { $0.id == controller.id }) {
|
||||
currentControllers.removeAll(where: { $0.id == controller.id })
|
||||
} else {
|
||||
currentControllers.append(controller)
|
||||
Section("Controller") {
|
||||
Button {
|
||||
controllersList = Ryujinx().getConnectedControllers()
|
||||
controllersList.removeAll(where: { $0.id == "0" })
|
||||
} label: {
|
||||
Text("Refresh")
|
||||
}
|
||||
ForEach(controllersList, id: \.self) { controller in
|
||||
HStack {
|
||||
Button {
|
||||
if currentControllers.contains(where: { $0.id == controller.id }) {
|
||||
currentControllers.removeAll(where: { $0.id == controller.id })
|
||||
} else {
|
||||
currentControllers.append(controller)
|
||||
}
|
||||
} label: {
|
||||
Text(controller.name)
|
||||
}
|
||||
Spacer()
|
||||
if currentControllers.contains(where: { $0.id == controller.id }) {
|
||||
Image(systemName: "checkmark.circle.fill")
|
||||
}
|
||||
} label: {
|
||||
Text(controller.name)
|
||||
}
|
||||
Spacer()
|
||||
if currentControllers.contains(where: { $0.id == controller.id }) {
|
||||
Image(systemName: "checkmark.circle.fill")
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -109,30 +119,41 @@ struct ContentView: View {
|
||||
|
||||
func start(displayid: UInt32) {
|
||||
|
||||
let config = Ryujinx.Configuration(
|
||||
gamepath: game!.path,
|
||||
additionalArgs: [
|
||||
// "--display-id", String(displayid)
|
||||
],
|
||||
debuglogs: false,
|
||||
tracelogs: false,
|
||||
listinputids: false,
|
||||
inputids: currentControllers.map(\.id),// "1-dc180005-045e-0000-130b-0000ff870001"], // "2-1fd70005-057e-0000-0920-0000ff870000"],
|
||||
ryufullscreen: true
|
||||
if let game {
|
||||
self.config.gamepath = game.path
|
||||
|
||||
)
|
||||
|
||||
|
||||
// Start the emulation
|
||||
do {
|
||||
setupVirtualController()
|
||||
allocateSixGB()
|
||||
|
||||
try Ryujinx().start(with: config)
|
||||
// Start the emulation
|
||||
do {
|
||||
setupVirtualController()
|
||||
|
||||
try Ryujinx().start(with: config)
|
||||
|
||||
|
||||
} catch {
|
||||
print("Error \(error.localizedDescription)")
|
||||
}
|
||||
} else {
|
||||
|
||||
|
||||
} catch {
|
||||
print("Error \(error.localizedDescription)")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func allocateSixGB() -> UnsafeMutableRawPointer? {
|
||||
|
||||
let physicalMemory = ProcessInfo.processInfo.physicalMemory
|
||||
let totalMemoryInGB = Double(physicalMemory) / (1024 * 1024 * 1024)
|
||||
let mem = totalMemoryInGB - 1
|
||||
print(mem)
|
||||
// Allocate memory
|
||||
let pointer = UnsafeMutableRawPointer.allocate(byteCount: Int(mem), alignment: MemoryLayout<UInt8>.alignment)
|
||||
|
||||
// Optionally initialize the memory
|
||||
pointer.initializeMemory(as: UInt8.self, repeating: 0, count: Int(mem))
|
||||
|
||||
print("Successfully allocated 6GB of memory.")
|
||||
return pointer
|
||||
}
|
||||
|
||||
func patchMakeKeyAndVisible() {
|
||||
@ -145,10 +166,32 @@ struct ContentView: View {
|
||||
|
||||
|
||||
private func setMoltenVKSettings() {
|
||||
|
||||
if let configs = loadSettings() {
|
||||
self.config = configs
|
||||
print(configs)
|
||||
}
|
||||
|
||||
settings.forEach { setting in
|
||||
setenv(setting.string, setting.value, 1)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
func loadSettings() -> Ryujinx.Configuration? {
|
||||
guard let jsonString = UserDefaults.standard.string(forKey: "config") else {
|
||||
return nil
|
||||
}
|
||||
|
||||
do {
|
||||
let decoder = JSONDecoder()
|
||||
if let data = jsonString.data(using: .utf8) {
|
||||
return try decoder.decode(Ryujinx.Configuration.self, from: data)
|
||||
}
|
||||
} catch {
|
||||
print("Failed to load settings: \(error)")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
extension UIWindow {
|
||||
|
74
src/MeloNX/MeloNX/Views/SettingsView/SettingsView.swift
Normal file
74
src/MeloNX/MeloNX/Views/SettingsView/SettingsView.swift
Normal file
@ -0,0 +1,74 @@
|
||||
//
|
||||
// SettingsView.swift
|
||||
// MeloNX
|
||||
//
|
||||
// Created by Stossy11 on 25/11/2024.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct SettingsView: View {
|
||||
@Binding var config: Ryujinx.Configuration
|
||||
|
||||
var body: some View {
|
||||
Form {
|
||||
|
||||
Section(header: Text("Graphics and Performance")) {
|
||||
Toggle("Fullscreen", isOn: $config.fullscreen)
|
||||
Toggle("Disable V-Sync", isOn: $config.disableVSync)
|
||||
Toggle("Disable Shader Cache", isOn: $config.disableShaderCache)
|
||||
Toggle("Enable Texture Recompression", isOn: $config.enableTextureRecompression)
|
||||
}
|
||||
|
||||
Section(header: Text("Input Settings")) {
|
||||
Toggle("List Input IDs", isOn: $config.listinputids)
|
||||
Toggle("Host Mapped Memory", isOn: $config.hostMappedMemory)
|
||||
Toggle("Disable Docked Mode", isOn: $config.disableDockedMode)
|
||||
}
|
||||
|
||||
Section(header: Text("Logging Settings")) {
|
||||
Toggle("Enable Debug Logs", isOn: $config.debuglogs)
|
||||
Toggle("Enable Trace Logs", isOn: $config.tracelogs)
|
||||
}
|
||||
|
||||
Section(header: Text("Game Settings")) {
|
||||
//TextField("Game Path", text: $config.gamepath)
|
||||
|
||||
TextField("Additional Arguments", text: Binding(
|
||||
get: {
|
||||
config.additionalArgs.joined(separator: ", ")
|
||||
},
|
||||
set: { newValue in
|
||||
config.additionalArgs = newValue.split(separator: ",").map { String($0).trimmingCharacters(in: .whitespaces) }
|
||||
}
|
||||
))
|
||||
}
|
||||
}
|
||||
.onAppear {
|
||||
if let configs = loadSettings() {
|
||||
self.config = configs
|
||||
print(configs)
|
||||
}
|
||||
}
|
||||
.navigationTitle("Settings")
|
||||
.navigationBarItems(trailing: Button("Save") {
|
||||
saveSettings()
|
||||
})
|
||||
}
|
||||
|
||||
func saveSettings() {
|
||||
do {
|
||||
let encoder = JSONEncoder()
|
||||
encoder.outputFormatting = .prettyPrinted // Optional: Makes the JSON easier to read
|
||||
let data = try encoder.encode(config)
|
||||
let jsonString = String(data: data, encoding: .utf8)
|
||||
|
||||
// Save to UserDefaults
|
||||
UserDefaults.standard.set(jsonString, forKey: "config")
|
||||
|
||||
print("Settings saved successfully!")
|
||||
} catch {
|
||||
print("Failed to save settings: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user