Created
April 18, 2025 17:18
-
-
Save jarrodnorwell/fb1159d82daadcf6f5ce32dccc9c910a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
enum CytrusSettingsHeaders : String, CaseIterable { | |
case core = "Core" | |
case debugging = "Debugging" | |
case system = "System" | |
case systemSaveGame = "System Save Game" | |
case renderer = "Renderer" | |
case defaultLayout = "Default Layout" | |
case customLayout = "Custom Layout" | |
case audio = "Audio" | |
case miscellaneous = "Miscellaneous" | |
var header: SettingHeader { | |
switch self { | |
case .core, | |
.debugging, | |
.system, | |
.systemSaveGame, | |
.renderer, | |
.defaultLayout, | |
.audio, | |
.miscellaneous: .init(text: rawValue) | |
case .customLayout: .init(text: rawValue, | |
secondaryText: "Set Default Layout to Custom Layout") | |
} | |
} | |
static var allHeaders: [SettingHeader] { allCases.map { $0.header } } | |
} | |
enum CytrusSettingsItems : String, CaseIterable { | |
// Core | |
case cpuJIT = "cytrus.cpuJIT" | |
case cpuClockPercentage = "cytrus.cpuClockPercentage" | |
case new3DS = "cytrus.new3DS" | |
case lleApplets = "cytrus.lleApplets" | |
case deterministicAsyncOperations = "cytrus.deterministicAsyncOperations" | |
case enableRequiredOnlineLLEModules = "cytrus.enableRequiredOnlineLLEModules" | |
// System | |
case regionValue = "cytrus.regionValue" | |
case pluginLoader = "cytrus.pluginLoader" | |
case allowPluginLoader = "cytrus.allowPluginLoader" | |
case stepsPerHour = "cytrus.stepsPerHour" | |
// Renderer | |
case spirvShaderGeneration = "cytrus.spirvShaderGeneration" | |
case useAsyncShaderCompilation = "cytrus.useAsyncShaderCompilation" | |
case useAsyncPresentation = "cytrus.useAsyncPresentation" | |
case useHardwareShaders = "cytrus.useHardwareShaders" | |
case useDiskShaderCache = "cytrus.useDiskShaderCache" | |
case useShadersAccurateMul = "cytrus.useShadersAccurateMul" | |
case useNewVSync = "cytrus.useNewVSync" | |
case useShaderJIT = "cytrus.useShaderJIT" | |
case resolutionFactor = "cytrus.resolutionFactor" | |
case textureFilter = "cytrus.textureFilter" | |
case textureSampling = "cytrus.textureSampling" | |
case delayGameRenderThreadUS = "cytrus.delayGameRenderThreadUS" | |
case layoutOption = "cytrus.layoutOption" | |
case customTopX = "cytrus.customTopX" | |
case customTopY = "cytrus.customTopY" | |
case customTopWidth = "cytrus.customTopWidth" | |
case customTopHeight = "cytrus.customTopHeight" | |
case customBottomX = "cytrus.customBottomX" | |
case customBottomY = "cytrus.customBottomY" | |
case customBottomWidth = "cytrus.customBottomWidth" | |
case customBottomHeight = "cytrus.customBottomHeight" | |
case customSecondLayerOpacity = "cytrus.customSecondLayerOpacity" | |
case render3D = "cytrus.render3D" | |
case factor3D = "cytrus.factor3D" | |
case monoRender = "cytrus.monoRender" | |
case filterMode = "cytrus.filterMode" | |
case ppShaderName = "cytrus.ppShaderName" | |
case anaglyphShaderName = "cytrus.anaglyphShaderName" | |
case dumpTextures = "cytrus.dumpTextures" | |
case customTextures = "cytrus.customTextures" | |
case preloadTextures = "cytrus.preloadTextures" | |
case asyncCustomLoading = "cytrus.asyncCustomLoading" | |
case disableRightEyeRender = "cytrus.disableRightEyeRender" | |
// Audio | |
case audioMuted = "cytrus.audioMuted" | |
case audioEmulation = "cytrus.audioEmulation" | |
case audioStretching = "cytrus.audioStretching" | |
case realtimeAudio = "cytrus.realtimeAudio" | |
case volume = "cytrus.volume" | |
case outputType = "cytrus.outputType" | |
case inputType = "cytrus.inputType" | |
// Miscellaneous | |
case logLevel = "cytrus.logLevel" | |
case webAPIURL = "cytrus.webAPIURL" | |
case systemLanguage = "cytrus.systemLanguage" | |
case username = "cytrus.username" | |
var title: String { | |
switch self { | |
case .cpuJIT: "CPU JIT" | |
case .cpuClockPercentage: "CPU Clock Percentage" | |
case .new3DS: "New 3DS" | |
case .lleApplets: "LLE Applets" | |
case .deterministicAsyncOperations: "Deterministic Async Operations" | |
case .enableRequiredOnlineLLEModules: "Required Online LLE Modules" | |
case .regionValue: "Region Value" | |
case .pluginLoader: "Plugin Loader" | |
case .allowPluginLoader: "Allow Plugin Loader" | |
case .stepsPerHour: "Steps Per Hour" | |
case .spirvShaderGeneration: "SPIR-V Shader Generation" | |
case .useAsyncShaderCompilation: "Async Shader Compilation" | |
case .useAsyncPresentation: "Async Presentation" | |
case .useHardwareShaders: "Hardware Shaders" | |
case .useDiskShaderCache: "Disk Shader Cache" | |
case .useShadersAccurateMul: "Shaders Accurate Mul" | |
case .useNewVSync: "New VSync" | |
case .useShaderJIT: "Shader JIT" | |
case .resolutionFactor: "Resolution Factor" | |
case .textureFilter: "Texture Filter" | |
case .textureSampling: "Texture Sampling" | |
case .delayGameRenderThreadUS: "Delay Game Render Thread US" | |
case .layoutOption: "Layout Option" | |
case .customTopX: "Custom Top X" | |
case .customTopY: "Custom Top Y" | |
case .customTopWidth: "Custom Top Width" | |
case .customTopHeight: "Custom Top Height" | |
case .customBottomX: "Custom Bottom X" | |
case .customBottomY: "Custom Bottom Y" | |
case .customBottomWidth: "Custom Bottom Width" | |
case .customBottomHeight: "Custom Bottom Height" | |
case .customSecondLayerOpacity: "Custom Second Layer Opacity" | |
case .render3D: "Render 3D" | |
case .factor3D: "Factor 3D" | |
case .monoRender: "Mono Render" | |
case .filterMode: "Filter Mode" | |
case .ppShaderName: "PP Shader Name" | |
case .anaglyphShaderName: "Anaglyph Shader Name" | |
case .dumpTextures: "Dump Textures" | |
case .customTextures: "Custom Textures" | |
case .preloadTextures: "Preload Textures" | |
case .asyncCustomLoading: "Async Custom Loading" | |
case .disableRightEyeRender: "Disable Right Eye Render" | |
case .audioMuted: "Audio Muted" | |
case .audioEmulation: "Audio Emulation" | |
case .audioStretching: "Audio Stretching" | |
case .realtimeAudio: "Realtime Audio" | |
case .volume: "Volume" | |
case .outputType: "Output Type" | |
case .inputType: "Input Type" | |
case .logLevel: "Log Level" | |
case .webAPIURL: "Web API URL" | |
case .systemLanguage: "System Language" | |
case .username: "Username" | |
} | |
} | |
func setting(_ delegate: SettingDelegate? = nil) -> BaseSetting { | |
switch self { | |
case .cpuJIT, | |
.new3DS, | |
.lleApplets, | |
.deterministicAsyncOperations, | |
.enableRequiredOnlineLLEModules, | |
.pluginLoader, | |
.allowPluginLoader, | |
.spirvShaderGeneration, | |
.useAsyncShaderCompilation, | |
.useAsyncPresentation, | |
.useHardwareShaders, | |
.useDiskShaderCache, | |
.useShadersAccurateMul, | |
.useNewVSync, | |
.useShaderJIT, | |
.filterMode, | |
.dumpTextures, | |
.customTextures, | |
.preloadTextures, | |
.asyncCustomLoading, | |
.disableRightEyeRender, | |
.audioMuted, | |
.audioStretching, | |
.realtimeAudio: | |
BoolSetting(key: rawValue, | |
title: title, | |
details: nil, | |
value: UserDefaults.standard.bool(forKey: rawValue), | |
delegate: delegate) | |
case .cpuClockPercentage: | |
InputNumberSetting(key: rawValue, | |
title: title, | |
details: nil, | |
min: 5, max: 400, | |
value: UserDefaults.standard.double(forKey: rawValue), | |
delegate: delegate) | |
case .regionValue: | |
SelectionSetting(key: rawValue, | |
title: title, | |
details: nil, | |
values: [ | |
"Automatic" : -1, | |
"Japan" : 0, | |
"USA" : 1, | |
"Europe" : 2, | |
"Australia" : 3, | |
"China" : 4, | |
"Korea" : 5, | |
"Taiwan" : 6 | |
], | |
selectedValue: UserDefaults.standard.value(forKey: rawValue), | |
action: {}, | |
delegate: delegate) | |
case .stepsPerHour: | |
InputNumberSetting(key: rawValue, | |
title: title, | |
details: nil, | |
min: 0, max: 9999, | |
value: UserDefaults.standard.double(forKey: rawValue), | |
delegate: delegate) | |
case .resolutionFactor: | |
StepperSetting(key: rawValue, | |
title: title, | |
details: nil, | |
min: 0, | |
max: 10, | |
value: UserDefaults.standard.double(forKey: rawValue), | |
delegate: delegate) | |
case .textureFilter: | |
SelectionSetting(key: rawValue, | |
title: title, | |
details: nil, | |
values: [ | |
"None" : 0, | |
"Anime4K" : 1, | |
"Bicubic" : 2, | |
"ScaleForce" : 3, | |
"xBRZ" : 4, | |
"MMPX" : 5 | |
], | |
selectedValue: UserDefaults.standard.value(forKey: rawValue), | |
action: {}, | |
delegate: delegate) | |
case .textureSampling: | |
SelectionSetting(key: rawValue, | |
title: title, | |
values: [ | |
"Game Controlled" : 0, | |
"Nearest Neighbor" : 1, | |
"Linear" : 2 | |
], | |
selectedValue: UserDefaults.standard.value(forKey: rawValue), | |
action: {}, | |
delegate: delegate) | |
case .delayGameRenderThreadUS: | |
InputNumberSetting(key: rawValue, | |
title: title, | |
details: nil, | |
min: 0, max: 16000, | |
value: UserDefaults.standard.double(forKey: rawValue), | |
delegate: delegate) | |
case .layoutOption: | |
SelectionSetting(key: rawValue, | |
title: title, | |
details: nil, | |
values: [ | |
"Default" : 0, | |
"Single Screen" : 1, | |
"Large Screen" : 2, | |
"Side Screen" : 3, | |
"Hybrid Screen" : 5, | |
"Custom Layout" : 6 | |
], | |
selectedValue: UserDefaults.standard.value(forKey: rawValue), | |
action: {}, | |
delegate: delegate) | |
case .customTopX, | |
.customTopY, | |
.customTopWidth, | |
.customTopHeight, | |
.customBottomX, | |
.customBottomY, | |
.customBottomWidth, | |
.customBottomHeight: | |
InputNumberSetting(key: rawValue, | |
title: title, | |
details: nil, | |
min: 0, max: 9999, | |
value: UserDefaults.standard.double(forKey: rawValue), | |
delegate: delegate) | |
case .customSecondLayerOpacity: | |
InputNumberSetting(key: rawValue, | |
title: title, | |
details: nil, | |
min: 0, max: 100, | |
value: UserDefaults.standard.double(forKey: rawValue), | |
delegate: delegate) | |
case .render3D: | |
SelectionSetting(key: rawValue, | |
title: title, | |
details: nil, | |
values: [ | |
"Off" : 0, | |
"Side by Side" : 1, | |
"Anaglyph" : 2, | |
"Interlaced" : 3, | |
"ReverseInterlaced" : 4, | |
"CardboardVR" : 5 | |
], | |
selectedValue: UserDefaults.standard.value(forKey: rawValue), | |
action: {}, | |
delegate: delegate) | |
case .factor3D: | |
StepperSetting(key: rawValue, | |
title: title, | |
details: nil, | |
min: 0, | |
max: 100, | |
value: UserDefaults.standard.double(forKey: rawValue), | |
delegate: delegate) | |
case .monoRender: | |
SelectionSetting(key: rawValue, | |
title: title, | |
details: nil, | |
values: [ | |
"Left Eye" : 0, | |
"Right Eye" : 1 | |
], | |
selectedValue: UserDefaults.standard.value(forKey: rawValue), | |
action: {}, | |
delegate: delegate) | |
case .ppShaderName: | |
InputStringSetting(key: rawValue, | |
title: title, | |
placeholder: "none (builtin)", | |
value: UserDefaults.standard.string(forKey: rawValue), | |
action: {}, | |
delegate: delegate) | |
case .anaglyphShaderName: | |
InputStringSetting(key: rawValue, | |
title: title, | |
placeholder: "dubois (builtin)", | |
value: UserDefaults.standard.string(forKey: rawValue), | |
action: {}, | |
delegate: delegate) | |
case .audioEmulation: | |
SelectionSetting(key: rawValue, | |
title: title, | |
values: [ | |
"HLE" : 0, | |
"LLE" : 1, | |
"LLE (Multithreaded)" : 2 | |
], | |
selectedValue: UserDefaults.standard.value(forKey: rawValue), | |
action: {}, | |
delegate: delegate) | |
case .volume: | |
StepperSetting(key: rawValue, | |
title: title, | |
details: nil, | |
min: 0, | |
max: 1, | |
value: UserDefaults.standard.double(forKey: rawValue), | |
delegate: delegate) | |
case .outputType: | |
SelectionSetting(key: rawValue, | |
title: title, | |
values: [ | |
"Automatic" : 0, | |
"None" : 1, | |
"CoreAudio" : 2, | |
"OpenAL" : 3, | |
"SDL3" : 4 | |
], | |
selectedValue: UserDefaults.standard.value(forKey: rawValue), | |
action: {}, | |
delegate: delegate) | |
case .inputType: | |
SelectionSetting(key: rawValue, | |
title: title, | |
values: [ | |
"Automatic" : 0, | |
"None" : 1, | |
"Static" : 2, | |
"OpenAL" : 3 | |
], | |
selectedValue: UserDefaults.standard.value(forKey: rawValue), | |
action: {}, | |
delegate: delegate) | |
case .logLevel: | |
SelectionSetting(key: rawValue, | |
title: title, | |
details: nil, | |
values: [ | |
"Trace" : 0, | |
"Debug" : 1, | |
"Info" : 2, | |
"Warning" : 3, | |
"Error" : 4, | |
"Critical" : 5 | |
], | |
selectedValue: UserDefaults.standard.value(forKey: rawValue), | |
action: {}, | |
delegate: delegate) | |
case .webAPIURL: | |
InputStringSetting(key: rawValue, | |
title: title, | |
details: nil, | |
placeholder: "http(s)://address:port", | |
value: UserDefaults.standard.string(forKey: rawValue), | |
action: { | |
MultiplayerManager.shared().updateWebAPIURL() | |
}, | |
delegate: delegate) | |
case .systemLanguage: | |
SelectionSetting(key: rawValue, | |
title: title, | |
values: [ | |
"Japanese" : 0, | |
"English" : 1, | |
"French" : 2, | |
"German" : 3, | |
"Italian" : 4, | |
"Spanish" : 5, | |
"Simplified Chinese" : 6, | |
"Korean" : 7, | |
"Dutch" : 8, | |
"Portuguese" : 9, | |
"Russian" : 10, | |
"Traditional Chinese" : 11 | |
], | |
selectedValue: UserDefaults.standard.value(forKey: rawValue), | |
action: { | |
guard let systemLanguage = UserDefaults.standard.value(forKey: rawValue) as? Int else { return } | |
SystemSaveGame.shared.set(systemLanguage) | |
}, | |
delegate: delegate) | |
case .username: | |
InputStringSetting(key: rawValue, | |
title: title, | |
placeholder: "Cytrus", | |
value: UserDefaults.standard.string(forKey: rawValue), | |
action: { | |
guard let username = UserDefaults.standard.string(forKey: rawValue) else { return } | |
SystemSaveGame.shared.set(username) | |
}, | |
delegate: delegate) | |
} | |
} | |
static func settings(_ header: CytrusSettingsHeaders) -> [CytrusSettingsItems] { | |
var debugging: [CytrusSettingsItems] = [.logLevel] | |
if AppStoreCheck.shared.debugging { | |
debugging.insert(.cpuJIT, at: 0) | |
} | |
return switch header { | |
case .core: | |
[ | |
.cpuClockPercentage, | |
.new3DS, | |
.lleApplets, | |
.deterministicAsyncOperations, | |
.enableRequiredOnlineLLEModules | |
] | |
case .debugging: | |
debugging | |
case .system: | |
[ | |
.regionValue, | |
.pluginLoader, | |
.allowPluginLoader, | |
.stepsPerHour | |
] | |
case .systemSaveGame: | |
[ | |
.systemLanguage, | |
.username | |
] | |
case .renderer: | |
[ | |
.spirvShaderGeneration, | |
.useAsyncShaderCompilation, | |
.useAsyncPresentation, | |
.useHardwareShaders, | |
.useDiskShaderCache, | |
.useShadersAccurateMul, | |
.useNewVSync, | |
.useShaderJIT, | |
.resolutionFactor, | |
.textureFilter, | |
.textureSampling, | |
.delayGameRenderThreadUS, | |
.render3D, | |
.factor3D, | |
.monoRender, | |
.filterMode, | |
.ppShaderName, | |
.anaglyphShaderName, | |
.dumpTextures, | |
.customTextures, | |
.preloadTextures, | |
.asyncCustomLoading, | |
.disableRightEyeRender | |
] | |
case .defaultLayout: | |
[ | |
.layoutOption | |
] | |
case .customLayout: | |
[ | |
.customTopX, | |
.customTopY, | |
.customTopWidth, | |
.customTopHeight, | |
.customBottomX, | |
.customBottomY, | |
.customBottomWidth, | |
.customBottomHeight, | |
.customSecondLayerOpacity | |
] | |
case .audio: | |
[ | |
.audioMuted, | |
.audioEmulation, | |
.audioStretching, | |
.realtimeAudio, | |
.volume, | |
.outputType, | |
.inputType | |
] | |
case .miscellaneous: | |
[ | |
.webAPIURL | |
] | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment