Revert ContentView

This commit is contained in:
Ben Lawrence 2024-11-29 18:18:38 +13:00
parent 3ce5b7d4a0
commit 5a60eeda5d
2 changed files with 135 additions and 180 deletions

View File

@ -16,230 +16,185 @@ struct MoltenVKSettings: Codable, Hashable {
} }
struct ContentView: View { struct ContentView: View {
// MARK: - Properties @State public var theWindow: UIWindow? = nil
@State private var theWindow: UIWindow?
@State private var virtualController: GCVirtualController? @State private var virtualController: GCVirtualController?
@State private var game: URL? @State var game: URL? = nil
@State private var controllersList: [Controller] = [] @State var controllersList: [Controller] = []
@State private var currentControllers: [Controller] = [] @State var currentControllers: [Controller] = []
@State private var config: Ryujinx.Configuration @State var config: Ryujinx.Configuration = Ryujinx.Configuration(gamepath: "")
@State private var settings: [MoltenVKSettings]
@State private var isVirtualControllerActive: Bool = false @State var settings: [MoltenVKSettings] = [
// MoltenVKSettings(string: "MVK_CONFIG_SYNCHRONOUS_QUEUE_SUBMITS", value: ""),
// MoltenVKSettings(string: "MVK_CONFIG_PREFILL_METAL_COMMAND_BUFFERS", value: "1"),
MoltenVKSettings(string: "MVK_CONFIG_MAX_ACTIVE_METAL_COMMAND_BUFFERS_PER_QUEUE", value: "1024"),
MoltenVKSettings(string: "MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS", value: "1"),
MoltenVKSettings(string: "MVK_CONFIG_RESUME_LOST_DEVICE", value: "1")
]
// MARK: - Initialization
init() { init() {
let defaultConfig = Ryujinx.Configuration(gamepath: "") // Initialize SDL
_config = State(initialValue: defaultConfig) DispatchQueue.main.async { [self] in
setMoltenVKSettings()
let defaultSettings: [MoltenVKSettings] = [ SDL_SetMainReady()
MoltenVKSettings(string: "MVK_CONFIG_MAX_ACTIVE_METAL_COMMAND_BUFFERS_PER_QUEUE", value: "1024"), SDL_iPhoneSetEventPump(SDL_TRUE)
MoltenVKSettings(string: "MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS", value: "1"), SDL_Init(SDL_INIT_VIDEO)
MoltenVKSettings(string: "MVK_CONFIG_RESUME_LOST_DEVICE", value: "1") patchMakeKeyAndVisible()
]
_settings = State(initialValue: defaultSettings)
initializeSDL()
}
// MARK: - Body
var body: some View {
iOSNav {
if let game {
emulationView
} else {
mainMenuView
}
}
.onChange(of: isVirtualControllerActive) { newValue in
if newValue {
createVirtualController()
} else {
destroyVirtualController()
}
} }
} }
// MARK: - View Components func setupVirtualController() {
private var emulationView: some View {
ZStack {}
.onAppear {
setupEmulation()
}
}
private var mainMenuView: some View {
HStack {
GameListView(startemu: $game)
.onAppear {
createVirtualController()
refreshControllersList()
}
settingsListView
}
}
private var settingsListView: some View {
List {
Section("Settings") {
NavigationLink("Config") {
SettingsView(config: $config, MoltenVKSettings: $settings)
}
}
Section("Controller") {
Button("Refresh", action: refreshControllersList)
ForEach(controllersList, id: \.self) { controller in
if controller.name != "Apple Touch Controller" {
controllerRow(for: controller)
}
}
}
}
}
private func controllerRow(for controller: Controller) -> some View {
HStack {
Button(controller.name) {
toggleController(controller)
}
Spacer()
if currentControllers.contains(where: { $0.id == controller.id }) {
Image(systemName: "checkmark.circle.fill")
}
}
}
// MARK: - Controller Management
private func createVirtualController() {
let configuration = GCVirtualController.Configuration() let configuration = GCVirtualController.Configuration()
configuration.elements = [ configuration.elements = [
/*
GCInputLeftThumbstick, GCInputLeftThumbstick,
GCInputRightThumbstick, GCInputRightThumbstick,
GCInputButtonA, GCInputButtonA,
GCInputButtonB, GCInputButtonB,
GCInputButtonX, GCInputButtonX,
GCInputButtonY, GCInputButtonY
*/
] ]
virtualController = GCVirtualController(configuration: configuration) let controller = GCVirtualController(configuration: configuration)
virtualController?.connect() self.virtualController = controller
self.virtualController?.connect()
controllersList.removeAll(where: { $0.name == "Apple Touch Controller" })
} }
private func destroyVirtualController() { var body: some View {
virtualController?.disconnect() iOSNav {
virtualController = nil
if let game {
// Remove virtual controller from current controllers ZStack {
controllersList.removeAll(where: { $0.name == "Apple Touch Controller" })
}
// MARK: - Helper Methods
private func initializeSDL() {
DispatchQueue.main.async {
setMoltenVKSettings()
SDL_SetMainReady()
SDL_iPhoneSetEventPump(SDL_TRUE)
SDL_Init(SDL_INIT_VIDEO)
}
}
private func setupEmulation() {
virtualController?.disconnect()
controllerCallback = {
DispatchQueue.main.async {
controllersList = Ryujinx.shared.getConnectedControllers()
currentControllers.removeAll(where: { $0.name == "Apple Touch Controller" })
if controllersList.count == 2,
controllersList.contains(where: { $0.name == "Apple Touch Controller" }) {
currentControllers.append(controllersList[1])
} }
.onAppear {
start(displayid: 0)
}
} else {
HStack {
GameListView(startemu: $game)
// .onAppear() {
// Timer.scheduledTimer(withTimeInterval: 1.0, repeats: false) { _ in
// controllersList = Ryujinx.shared.getConnectedControllers()
// controllersList.removeAll(where: { $0.id == "0" })
// }
// }
List {
Section("Settings") {
NavigationLink {
SettingsView(config: $config, MoltenVKSettings: $settings)
} label: {
Text("Config")
}
}
Section("Controller") {
Button {
controllersList = Ryujinx.shared.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")
}
}
}
}
}
}
}
}
}
func start(displayid: UInt32) {
if let game {
self.config.gamepath = game.path
self.config.inputids = currentControllers.map(\.id)
allocateSixGB()
// Start the emulation
print("Is MetalHud Enabled? " + (MTLHud.shared.isEnabled ? "yeah" : "nope"))
do {
setupVirtualController()
print(currentControllers) try Ryujinx.shared.start(with: config)
start(displayid: 1)
} catch {
print("Error \(error.localizedDescription)")
} }
}
showVirtualController()
}
private func refreshControllersList() {
Timer.scheduledTimer(withTimeInterval: 0.5, repeats: false) { _ in
controllersList = Ryujinx.shared.getConnectedControllers()
controllersList.removeAll(where: { $0.id == "0" })
controllersList.removeAll(where: { $0.name == "Apple Touch Controller" })
if let controller = controllersList.first, !controllersList.isEmpty {
currentControllers.append(controller)
}
}
}
private func toggleController(_ controller: Controller) {
if currentControllers.contains(where: { $0.id == controller.id }) {
currentControllers.removeAll(where: { $0.id == controller.id })
} else { } else {
currentControllers.append(controller)
} }
} }
private func start(displayid: UInt32) { func allocateSixGB() -> UnsafeMutableRawPointer? {
guard let game else { return }
config.gamepath = game.path
config.inputids = currentControllers.map(\.id)
allocateMemory()
do {
try Ryujinx.shared.start(with: config)
} catch {
print("Error: \(error.localizedDescription)")
}
}
private func allocateMemory() {
let physicalMemory = ProcessInfo.processInfo.physicalMemory let physicalMemory = ProcessInfo.processInfo.physicalMemory
let totalMemoryInGB = Double(physicalMemory) / (1024 * 1024 * 1024) let totalMemoryInGB = Double(physicalMemory) / (1024 * 1024 * 1024)
let mem = totalMemoryInGB
let pointer = UnsafeMutableRawPointer.allocate( print(mem)
byteCount: Int(totalMemoryInGB), // Allocate memory
alignment: MemoryLayout<UInt8>.alignment let pointer = UnsafeMutableRawPointer.allocate(byteCount: Int(mem), alignment: MemoryLayout<UInt8>.alignment)
)
pointer.initializeMemory(as: UInt8.self, repeating: 0, count: Int(totalMemoryInGB)) // Optionally initialize the memory
pointer.initializeMemory(as: UInt8.self, repeating: 0, count: Int(mem))
print("Successfully allocated 6GB of memory.")
return pointer
} }
func patchMakeKeyAndVisible() {
let uiwindowClass = UIWindow.self
if let m1 = class_getInstanceMethod(uiwindowClass, #selector(UIWindow.makeKeyAndVisible)),
let m2 = class_getInstanceMethod(uiwindowClass, #selector(UIWindow.wdb_makeKeyAndVisible)) {
method_exchangeImplementations(m1, m2)
}
}
private func setMoltenVKSettings() { private func setMoltenVKSettings() {
if let configs = loadSettings() { if let configs = loadSettings() {
self.config = configs self.config = configs
print(configs)
} }
settings.forEach { setting in settings.forEach { setting in
setenv(setting.string, setting.value, 1) setenv(setting.string, setting.value, 1)
} }
} }
} }
// MARK: - Helper Functions
func loadSettings() -> Ryujinx.Configuration? { func loadSettings() -> Ryujinx.Configuration? {
guard let jsonString = UserDefaults.standard.string(forKey: "config"), guard let jsonString = UserDefaults.standard.string(forKey: "config") else {
let data = jsonString.data(using: .utf8) else {
return nil return nil
} }
do { do {
return try JSONDecoder().decode(Ryujinx.Configuration.self, from: data) let decoder = JSONDecoder()
if let data = jsonString.data(using: .utf8) {
return try decoder.decode(Ryujinx.Configuration.self, from: data)
}
} catch { } catch {
print("Failed to load settings: \(error)") print("Failed to load settings: \(error)")
return nil
} }
return nil
} }