// SPDX-License-Identifier: Unlicense

#include "settings.h"

#include "base64.h"
#include "collection.h"
#include "file.h"
#include "getopt.h"
#include "global.h"
#include "helper.h"
#include "player.h"
#include "sfx.h"
#include "string_.h"

#include <map>

static constexpr f32 cameraXrParallaxHighwayRotation = 0.0f;
static constexpr f32 cameraXrParallaxHighwayScale = 0.1f;
static constexpr f32 cameraXrParallaxHighwayX = -3.1f;
static constexpr f32 cameraXrParallaxHighwayXFactor = 0.08f;
static constexpr f32 cameraXrParallaxHighwayY = -5.0f;
static constexpr f32 cameraXrParallaxHighwayYFactor = 0.0f;
static constexpr f32 cameraXrParallaxHighwayZ = -7.1f;
static constexpr f32 cameraXrParallaxHighwayZFactor = 0.0f;
static constexpr f32 cameraXrParallaxX = 0.0f;
static constexpr f32 cameraXrParallaxXFactor = 0.0f;
static constexpr f32 cameraXrParallaxXRotation = 0.0f;
static constexpr f32 cameraXrParallaxY = 0.0f;
static constexpr f32 cameraXrParallaxYFactor = 0.0f;
static constexpr f32 cameraXrParallaxYRotation = 0.0f;
static constexpr f32 cameraXrParallaxZ = 0.0f;
static constexpr f32 cameraXrParallaxZFactor = 0.0f;

Instrument Settings::applicationInstrument = Instrument::LeadGuitar;
#ifdef SHR3D_COOP
Instrument Settings::applicationInstrumentCoop = Instrument::BassGuitar;
#endif // SHR3D_COOP
BackupMode Settings::applicationBackupMode =
#ifdef __ANDROID__
BackupMode::off;
#else // __ANDROID__
BackupMode::onceOnStart;
#endif // __ANDROID__
EndOfSong Settings::applicationEndOfSong = EndOfSong::loopSong;
bool Settings::applicationToneSwitch = true;
AudioSystem Settings::audioSystem =
#ifdef PLATFORM_WINDOWS
#ifdef SHR3D_AUDIO_SDL
AudioSystem::SDL;
#elif defined(SHR3D_AUDIO_WASAPI)
AudioSystem::WASAPI;
#elif defined(SHR3D_AUDIO_ASIO)
AudioSystem::ASIO;
#endif
#endif // PLATFORM_WINDOWS
#ifdef PLATFORM_LINUX
AudioSystem::SDL;
#endif // PLATFORM_LINUX
#ifdef PLATFORM_ANDROID_SDL
#ifdef SHR3D_AUDIO_SDL
AudioSystem::SDL;
#elif defined(SHR3D_AUDIO_AAUDIO)
AudioSystem::AAudio;
#elif defined(SHR3D_AUDIO_SUPERPOWERED)
AudioSystem::Superpowered;
#endif
#endif // PLATFORM_ANDROID_SDL
#ifdef PLATFORM_OPENXR_ANDROID
#ifdef SHR3D_AUDIO_SDL
AudioSystem::SDL;
#elif defined(SHR3D_AUDIO_AAUDIO)
AudioSystem::AAudio;
#endif
#endif // PLATFORM_OPENXR_ANDROID
#ifdef PLATFORM_EMSCRIPTEN
AudioSystem::WebAudio;
#endif // PLATFORM_EMSCRIPTEN
f32 Settings::audioEffectVolume = 0.6f;
f32 Settings::audioEffectVolumeCoop = 0.6f;
f32 Settings::audioMusicVolume = 0.3f;
#ifdef SHR3D_AUDIO_AAUDIO
i32 Settings::audioAAudioBlockSize = 128;
i32 Settings::audioAAudioChannelInput;
#ifdef SHR3D_COOP
i32 Settings::audioAAudioChannelInputCoop;
#endif // SHR3D_COOP
std::string Settings::audioAAudioDeviceInput = "Default";
std::string Settings::audioAAudioDeviceOutput = "Default";
i32 Settings::audioAAudioSampleRate = 48000;
bool Settings::audioAAudioExclusiveMode = false;
AAudioPerformanceMode Settings::audioAAudioPerformanceMode = AAudioPerformanceMode::None;
#endif // SHR3D_AUDIO_AAUDIO
#ifdef SHR3D_AUDIO_ASIO
std::string Settings::audioAsioDevice;
i32 Settings::audioAsioChannelInput0;
i32 Settings::audioAsioChannelInput1;
#ifdef SHR3D_COOP
i32 Settings::audioAsioChannelInputCoop0;
i32 Settings::audioAsioChannelInputCoop1;
#endif // SHR3D_COOP
#ifdef SHR3D_SFX_CORE_HEXFIN_DIVIDED
#ifdef SHR3D_AUDIO_ASIO_SECOND_DEVICE_FOR_TUNER_DIVIDED
std::string Settings::audioAsioSecondDeviceForTunerDivided;
#endif // SHR3D_AUDIO_ASIO_SECOND_DEVICE_FOR_TUNER_DIVIDED
bool Settings::audioAsioDividedPickup = false;
bool Settings::audioAsioDividedPickupAsMainInput = false;
i32 Settings::audioAsioDividedPickupChannelString0;
i32 Settings::audioAsioDividedPickupChannelString1;
i32 Settings::audioAsioDividedPickupChannelString2;
i32 Settings::audioAsioDividedPickupChannelString3;
i32 Settings::audioAsioDividedPickupChannelString4;
i32 Settings::audioAsioDividedPickupChannelString5;
#endif // SHR3D_SFX_CORE_HEXFIN_DIVIDED
i32 Settings::audioAsioChannelOutput;
i32 Settings::audioAsioBlockSize = 0;
i32 Settings::audioAsioSampleRate = 0;
#endif // SHR3D_AUDIO_ASIO
#ifdef SHR3D_AUDIO_JACK
std::string Settings::audioJackInputDevice0;
std::string Settings::audioJackInputDevice1;
std::string Settings::audioJackOutputDevice0;
std::string Settings::audioJackOutputDevice1;
#ifdef SHR3D_COOP
std::string Settings::audioJackInputDeviceCoop0;
std::string Settings::audioJackInputDeviceCoop1;
#endif // SHR3D_COOP
#ifdef SHR3D_SFX_CORE_HEXFIN_DIVIDED
bool Settings::audioJackDividedPickup = false;
bool Settings::audioJackDividedPickupAsMainInput = false;
std::string Settings::audioJackDividedPickupChannelString0;
std::string Settings::audioJackDividedPickupChannelString1;
std::string Settings::audioJackDividedPickupChannelString2;
std::string Settings::audioJackDividedPickupChannelString3;
std::string Settings::audioJackDividedPickupChannelString4;
std::string Settings::audioJackDividedPickupChannelString5;
#endif // SHR3D_SFX_CORE_HEXFIN_DIVIDED
#endif // SHR3D_AUDIO_JACK
#ifdef SHR3D_AUDIO_PIPEWIRE
std::string Settings::audioPipewireInputDevice0;
std::string Settings::audioPipewireInputDevice1;
std::string Settings::audioPipewireOutputDevice0;
std::string Settings::audioPipewireOutputDevice1;
#ifdef SHR3D_COOP
std::string Settings::audioPipewireInputDeviceCoop0;
std::string Settings::audioPipewireInputDeviceCoop1;
#endif // SHR3D_COOP
#ifdef SHR3D_SFX_CORE_HEXFIN_DIVIDED
bool Settings::audioPipewireDividedPickup = false;
bool Settings::audioPipewireDividedPickupAsMainInput = false;
std::string Settings::audioPipewireDividedPickupChannelString0;
std::string Settings::audioPipewireDividedPickupChannelString1;
std::string Settings::audioPipewireDividedPickupChannelString2;
std::string Settings::audioPipewireDividedPickupChannelString3;
std::string Settings::audioPipewireDividedPickupChannelString4;
std::string Settings::audioPipewireDividedPickupChannelString5;
#endif // SHR3D_SFX_CORE_HEXFIN_DIVIDED
#endif // SHR3D_AUDIO_PIPEWIRE
#ifdef SHR3D_AUDIO_SDL
i32 Settings::audioSdlBlockSize = 128;
i32 Settings::audioSdlChannelInput;
#ifdef SHR3D_COOP
i32 Settings::audioSdlChannelInputCoop;
#endif // SHR3D_COOP
std::string Settings::audioSdlDeviceInput = "Default";
std::string Settings::audioSdlDeviceOutput = "Default";
i32 Settings::audioSdlSampleRate = 48000;
#endif // SHR3D_AUDIO_SDL
#ifdef SHR3D_AUDIO_SUPERPOWERED
i32 Settings::audioSuperpoweredBlockSize = 512;
std::u8string Settings::audioSuperpoweredCofiguration;
i32 Settings::audioSuperpoweredChannelInput;
i32 Settings::audioSuperpoweredChannelOutput;
std::u8string Settings::audioSuperpoweredDeviceInput;
std::u8string Settings::audioSuperpoweredDeviceOutput;
bool Settings::audioSuperpoweredSustainedPerformanceMode = false;
std::u8string Settings::audioSuperpoweredInputPathName;
std::vector<char> Settings::audioSuperpoweredInputMutes;
std::vector<f32> Settings::audioSuperpoweredInputVolume;
std::u8string Settings::audioSuperpoweredOutputPathName;
std::vector<char> Settings::audioSuperpoweredOutputMutes;
std::vector<f32> Settings::audioSuperpoweredOutputVolume;
#ifdef SHR3D_SFX_CORE_HEXFIN_DIVIDED
bool Settings::audioSuperpoweredDividedPickup = false;
i32 Settings::audioSuperpoweredDividedPickupChannelString0;
i32 Settings::audioSuperpoweredDividedPickupChannelString1;
i32 Settings::audioSuperpoweredDividedPickupChannelString2;
i32 Settings::audioSuperpoweredDividedPickupChannelString3;
i32 Settings::audioSuperpoweredDividedPickupChannelString4;
i32 Settings::audioSuperpoweredDividedPickupChannelString5;
#endif // SHR3D_SFX_CORE_HEXFIN_DIVIDED
#endif // SHR3D_AUDIO_SUPERPOWERED
#ifdef SHR3D_AUDIO_WASAPI
i32 Settings::audioWasapiChannelInput0;
#ifdef SHR3D_COOP
i32 Settings::audioWasapiChannelInput1;
#endif // SHR3D_COOP
std::string Settings::audioWasapiDeviceInput = "Default";
std::string Settings::audioWasapiDeviceOutput = "Default";
i32 Settings::audioWasapiBlockSize = 128;
bool Settings::audioWasapiExclusiveMode = false;
i32 Settings::audioWasapiSampleRate = 48000;
#endif // SHR3D_AUDIO_WASAPI
#ifdef SHR3D_AUDIO_WEBAUDIO
i32 Settings::audioWebAudioChannelInput0;
i32 Settings::audioWebAudioSampleRate = 48000;
#endif // SHR3D_AUDIO_WEBAUDIO
vec4 Settings::environmentClearColor = colorVec4(u8"#00000000");
#ifdef SHR3D_ENVIRONMENT_MILK
bool Settings::environmentMilk = false;
std::u8string Settings::environmentMilkActivePresets;
f32 Settings::environmentMilkBeatSensitivity = 1.0f;
i32 Settings::environmentMilkDuration = 60;
i32 Settings::environmentMilkMeshSize = 128;
i32 Settings::environmentMilkFrameSkip = 0;
f32 Settings::environmentMilkFrameSpeed = 1.0f;
bool Settings::environmentMilkShuffle = false;
#endif // SHR3D_ENVIRONMENT_MILK
#ifdef SHR3D_ENVIRONMENT_SKYBOX
std::u8string Settings::environmentSkybox;
f32 Settings::environmentSkyboxRotation = 0.0f;
#endif // SHR3D_ENVIRONMENT_SKYBOX
#ifdef SHR3D_ENVIRONMENT_STAGE
std::u8string Settings::environmentStage;
#ifndef PLATFORM_OPENXR_ANDROID
f32 Settings::environmentStagePlayerHeight = 1.7f;
#endif // PLATFORM_OPENXR_ANDROID
f32 Settings::environmentStageRotation;
f32 Settings::environmentStageScale = 1.0f;
f32 Settings::environmentStageX;
f32 Settings::environmentStageY;
f32 Settings::environmentStageZ;
#endif // SHR3D_ENVIRONMENT_STAGE
CameraMode Settings::cameraMode = CameraMode::parallax;
#ifndef PLATFORM_OPENXR_ANDROID
f32 Settings::cameraFieldOfView = 60.0f;
#endif // PLATFORM_OPENXR_ANDROID
f32 Settings::cameraFixedX = -12.0f;
f32 Settings::cameraFixedXRotation = 0.185f;
f32 Settings::cameraFixedY = -8.0f;
f32 Settings::cameraFixedYRotation = 0.0f;
f32 Settings::cameraFixedZ = -12.0f;
f32 Settings::cameraParallaxAnchorTackingDuration = 3.0f;
f32 Settings::cameraParallaxHighwayRotation =
#ifdef PLATFORM_OPENXR_ANDROID
cameraXrParallaxHighwayRotation;
#else
0.06f;
#endif // PLATFORM_OPENXR_ANDROID
f32 Settings::cameraParallaxHighwayScale =
#ifdef PLATFORM_OPENXR_ANDROID
cameraXrParallaxHighwayScale;
#else
0.18f;
#endif // PLATFORM_OPENXR_ANDROID
f32 Settings::cameraParallaxHighwayX =
#ifdef PLATFORM_OPENXR_ANDROID
cameraXrParallaxHighwayX;
#else
- 1.49f;
#endif // PLATFORM_OPENXR_ANDROID
f32 Settings::cameraParallaxHighwayXFactor =
#ifdef PLATFORM_OPENXR_ANDROID
cameraXrParallaxHighwayXFactor;
#else
0.08f;
#endif // PLATFORM_OPENXR_ANDROID
f32 Settings::cameraParallaxHighwayY =
#ifdef PLATFORM_OPENXR_ANDROID
cameraXrParallaxHighwayY;
#else
-3.95f;
#endif // PLATFORM_OPENXR_ANDROID
f32 Settings::cameraParallaxHighwayYFactor =
#ifdef PLATFORM_OPENXR_ANDROID
cameraXrParallaxHighwayYFactor;
#else
0.0f;
#endif // PLATFORM_OPENXR_ANDROID
f32 Settings::cameraParallaxHighwayZ =
#ifdef PLATFORM_OPENXR_ANDROID
cameraXrParallaxHighwayZ;
#else
- 5.17f;
#endif // PLATFORM_OPENXR_ANDROID
f32 Settings::cameraParallaxHighwayZFactor =
#ifdef PLATFORM_OPENXR_ANDROID
cameraXrParallaxHighwayZFactor;
#else
0.099f;
#endif // PLATFORM_OPENXR_ANDROID
f32 Settings::cameraParallaxX =
#ifdef PLATFORM_OPENXR_ANDROID
cameraXrParallaxX;
#else
0.0f;
#endif // PLATFORM_OPENXR_ANDROID
f32 Settings::cameraParallaxXFactor =
#ifdef PLATFORM_OPENXR_ANDROID
cameraXrParallaxXFactor;
#else
0.08f;
#endif // PLATFORM_OPENXR_ANDROID
f32 Settings::cameraParallaxXRotation =
#ifdef PLATFORM_OPENXR_ANDROID
cameraXrParallaxXRotation;
#else
0.309f;
#endif // PLATFORM_OPENXR_ANDROID
f32 Settings::cameraParallaxY =
#ifdef PLATFORM_OPENXR_ANDROID
cameraXrParallaxY;
#else
0.0f;
#endif // PLATFORM_OPENXR_ANDROID
f32 Settings::cameraParallaxYFactor =
#ifdef PLATFORM_OPENXR_ANDROID
cameraXrParallaxYFactor;
#else
0.025f;
#endif // PLATFORM_OPENXR_ANDROID
f32 Settings::cameraParallaxYRotation =
#ifdef PLATFORM_OPENXR_ANDROID
cameraXrParallaxYRotation;
#else
0.0f;
#endif // PLATFORM_OPENXR_ANDROID
f32 Settings::cameraParallaxZ =
#ifdef PLATFORM_OPENXR_ANDROID
cameraXrParallaxZ;
#else
0.0f;
#endif // PLATFORM_OPENXR_ANDROID
f32 Settings::cameraParallaxZFactor =
#ifdef PLATFORM_OPENXR_ANDROID
cameraXrParallaxZFactor;
#else
0.0f;
#endif // PLATFORM_OPENXR_ANDROID
#ifdef SHR3D_OPENXR_PCVR
CameraMode Settings::cameraPcVrMode = CameraMode::pcVrParallax;
f32 Settings::cameraPcVrParallaxAnchorTackingDuration = 3.0f;
f32 Settings::cameraPcVrParallaxHighwayRotation = cameraXrParallaxHighwayRotation;
f32 Settings::cameraPcVrParallaxHighwayScale = cameraXrParallaxHighwayScale;
f32 Settings::cameraPcVrParallaxHighwayX = cameraXrParallaxHighwayX;
f32 Settings::cameraPcVrParallaxHighwayXFactor = cameraXrParallaxHighwayXFactor;
f32 Settings::cameraPcVrParallaxHighwayY = cameraXrParallaxHighwayY;
f32 Settings::cameraPcVrParallaxHighwayYFactor = cameraXrParallaxHighwayYFactor;
f32 Settings::cameraPcVrParallaxHighwayZ = cameraXrParallaxHighwayZ;
f32 Settings::cameraPcVrParallaxHighwayZFactor = cameraXrParallaxHighwayZFactor;
f32 Settings::cameraPcVrParallaxX = cameraXrParallaxX;
f32 Settings::cameraPcVrParallaxXFactor = cameraXrParallaxXFactor;
f32 Settings::cameraPcVrParallaxXRotation = cameraXrParallaxXRotation;
f32 Settings::cameraPcVrParallaxY = cameraXrParallaxY;
f32 Settings::cameraPcVrParallaxYFactor = cameraXrParallaxYFactor;
f32 Settings::cameraPcVrParallaxYRotation = cameraXrParallaxYRotation;
f32 Settings::cameraPcVrParallaxZ = cameraXrParallaxZ;
f32 Settings::cameraPcVrParallaxZFactor = cameraXrParallaxZFactor;
#endif // SHR3D_OPENXR_PCVR
FullscreenMode Settings::graphicsFullscreen =
#ifdef __ANDROID__
FullscreenMode::borderless;
#else // __ANDROID__
FullscreenMode::windowed;
#endif // __ANDROID__
#ifdef SHR3D_GRAPHICS_MSAA
i32 Settings::graphicsMSAA = 2; // 0=Off, 1=2x, 2=4x, 3=8x
#endif // SHR3D_GRAPHICS_MSAA
#ifdef SHR3D_OPENGL_SPIR_V
bool Settings::graphicsSpirV = false;
#endif // SHR3D_OPENGL_SPIR_V
ScalingMode Settings::graphicsScaling = ScalingMode::HorPlus;
#ifdef PLATFORM_QUEST_3
i32 Settings::graphicsRefreshRate = 0;
#endif // PLATFORM_QUEST_3
#if !defined(PLATFORM_EMSCRIPTEN) && !defined(PLATFORM_QUEST_3)
VSyncMode Settings::graphicsVSync = VSyncMode::noVSync;
#endif // !PLATFORM_EMSCRIPTEN && !PLATFORM_QUEST_3
i32 Settings::graphicsWindowWidth = 1600;
i32 Settings::graphicsWindowHeight = 900;
f32 Settings::highwayFadeFarDistance = 40.0f;
f32 Settings::highwayFadeNearDistance = 5.0;
f32 Settings::highwayFadeNearStrength = 0.2f;
vec4 Settings::highwayAnchorColor[4] = {
  colorVec4(u8"#2E1168FF"),
  colorVec4(u8"#193EA0FF"),
  colorVec4(u8"#00072FF3"),
  colorVec4(u8"#00072FF3")
};
f32 Settings::highwayAnchorColorExponent = 0.5f;
vec4 Settings::highwayCapoColor = colorVec4(u8"#AFAFAF7C");
bool Settings::highwayChordBox = true;
vec4 Settings::highwayChordBoxColor = {
  colorVec4(u8"#DA741FE9"),
};
bool Settings::highwayChordBoxArpeggio = true;
vec4 Settings::highwayChordBoxArpeggioColor = colorVec4(u8"#F8300CE9");
bool Settings::highwayChordFretNumbers = true;
bool Settings::highwayChordName = false;
vec4 Settings::highwayChordNameColor = colorVec4(u8"#FFFFFF88");
vec4 Settings::highwayDotInlayColor[4] = {
  colorVec4(u8"#EB8D176D"),
  colorVec4(u8"#F8B92287"),
  colorVec4(u8"#119CD26D"),
  colorVec4(u8"#45469E87")
};
bool Settings::highwayBeat = true;
vec4 Settings::highwayBeatColor[2] = {
  colorVec4(u8"#8795E5FF"),
  colorVec4(u8"#423E6DFF")
};
bool Settings::highwayBeatStrumDirection = false;
vec4 Settings::highwayBeatStrumDirectionColor[2] = {
  colorVec4(u8"#2BE11AFF"),
  colorVec4(u8"#E11717FF")
};
StrumDirection Settings::highwayBeatStrumDirectionPrimary = StrumDirection::downStroke;
StrumDirection Settings::highwayBeatStrumDirectionNext = StrumDirection::downStroke;
int Settings::highwayBeatStrumsBetweenBeats = 0;
vec4 Settings::highwayFingerNumberColor = colorVec4(u8"#FFFFFFFF");
bool Settings::highwayFingerNumbers = true;
vec4 Settings::highwayFretboardFretColor = colorVec4(u8"#AFAFAF7C");
vec4 Settings::highwayFretboardFretNumberColor[3] = {
  colorVec4(u8"#FFBA17CC"),
  colorVec4(u8"#8795E5CC"),
  colorVec4(u8"#4A609ACC")
};
bool Settings::highwayFretboardNoteNames = false;
vec4 Settings::highwayFretboardNoteNameColor[2] = {
  colorVec4(u8"#BCBED4FF"),
  colorVec4(u8"#8795E5FF")
};
bool Settings::highwayFretboardCollisionNotes = true;
vec4 Settings::highwayFretboardCollisionNotesColor[2] = {
  colorVec4(u8"#D81212FF"),
  colorVec4(u8"#31CDC9F8")
};
bool Settings::highwayFretboardPlayedNotesDot = true;
vec4 Settings::highwayFretboardPlayedNotesDotColor[2] = {
  colorVec4(u8"#D81212FF"),
  colorVec4(u8"#31CDC9F8")
};
#ifdef SHR3D_SFX_CORE_HEXFIN
bool Settings::highwayFretboardPlayedNotesTuner = true;
#endif // SHR3D_SFX_CORE_HEXFIN
vec4 Settings::highwayGroundFretColor[2] = {
  colorVec4(u8"#2037A5FF"),
  colorVec4(u8"#151D4800")
};
bool Settings::highwayStringFadeUnplayed = true;
vec4 Settings::highwaySustainColor = colorVec4(u8"#977DFFCD");
bool Settings::highwayInstrumentBass5StringHideString0 = false;
i32 Settings::highwayInstrumentBass5StringTuning[4] = { -4, -4, -4, -4 };
i32 Settings::highwayInstrumentBassFirstWoundString = 0;
f32 Settings::highwayInstrumentBassFretSpacing = 1.0f;
f32 Settings::highwayInstrumentBassFretSpacingFactor = 0.0f;
vec4 Settings::highwayInstrumentBassStringColor[6] = {
  colorVec4(u8"#E05A01AA"),
  colorVec4(u8"#2381E9AA"),
  colorVec4(u8"#D2A20DAA"),
  colorVec4(u8"#D20000AA"),
  colorVec4(u8"#009B71AA"),
  colorVec4(u8"#999999AA")
};
f32 Settings::highwayInstrumentBassStringSpacing = 0.46f;
bool Settings::highwayInstrumentGuitar7StringHideString0 = false;
i32 Settings::highwayInstrumentGuitar7StringTuning[6] = { -4, -4, -4, -4, -4, -4 };
i32 Settings::highwayInstrumentGuitarFirstWoundString = 3;
f32 Settings::highwayInstrumentGuitarFretSpacing = 1.0f;
f32 Settings::highwayInstrumentGuitarFretSpacingFactor = 0.0f;
vec4 Settings::highwayInstrumentGuitarStringColor[8] = {
  colorVec4(u8"#940FB0AA"),
  colorVec4(u8"#1F9601AA"),
  colorVec4(u8"#E05A01AA"),
  colorVec4(u8"#2381E9AA"),
  colorVec4(u8"#D2A20DAA"),
  colorVec4(u8"#D20000AA"),
  colorVec4(u8"#009B71AA"),
  colorVec4(u8"#999999AA")
};
f32 Settings::highwayInstrumentGuitarStringSpacing = 0.42f;
f32 Settings::highwayNoteBendCurve = 0.5f;
f32 Settings::highwayNoteBendEndTime = 0.5f;
f32 Settings::highwayNoteBendSpeed = 2.0f;
f32 Settings::highwayNoteBendHintOffset = 0.1f;
f32 Settings::highwayNoteBendHintDistance = 0.2f;
f32 Settings::highwayNoteHeight = 1.0f;
i32 Settings::highwayNoteRotate = 0;
f32 Settings::highwayNoteRotateEndTime = 0.5f;
f32 Settings::highwayNoteRotateSpeed = 2.0f;
NoteShape Settings::highwayNoteShape = NoteShape::hex;
NoteSymbols Settings::highwayNoteSymbolFretMute = NoteSymbols::fretMute;
NoteSymbols Settings::highwayNoteSymbolHammerOn = NoteSymbols::hammerOn;
NoteSymbols Settings::highwayNoteSymbolHarmonic = NoteSymbols::harmonic;
NoteSymbols Settings::highwayNoteSymbolPinchHarmonic = NoteSymbols::pinchHarmonic;
NoteSymbols Settings::highwayNoteSymbolPalmMute = NoteSymbols::palmMute;
NoteSymbols Settings::highwayNoteSymbolPop = NoteSymbols::pop;
NoteSymbols Settings::highwayNoteSymbolPullOff = NoteSymbols::pullOff;
NoteSymbols Settings::highwayNoteSymbolSlap = NoteSymbols::slap;
NoteSymbols Settings::highwayNoteSymbolTap = NoteSymbols::tap;
bool Settings::highwayNoteStand = true;
bool Settings::highwayNoteStandZero = true;
f32 Settings::highwayNoteWidth = 1.0f;
f32 Settings::highwayNoteSustainCurveSampleDistance = 0.01f;
f32 Settings::highwayNoteSustainTremoloSampleDistance = 0.02f;
f32 Settings::highwayNoteSustainTremoloShakeStrength = 0.1f;
f32 Settings::highwayNoteSustainWidth = 0.3f;
f32 Settings::highwayNoteSustainWidthZero = 0.75f;
f32 Settings::highwayFretboardNoteHeight = 1.06f;
f32 Settings::highwayFretboardNoteWidth = 1.36f;
bool Settings::highwayFretboardStringNoteNames = true;
#ifdef SHR3D_PARTICLE
bool Settings::highwayParticlePlayedNotes = false;
bool Settings::highwayParticleCollisionNotes = false;
i32 Settings::highwayParticleShape = 1;
i32 Settings::highwayParticleMaxCount = 10000;
f32 Settings::highwayParticleSpawnsPerSecond = 4000.0f;
f32 Settings::highwayParticleSpawnRadius = 0.75f;
f32 Settings::highwayParticleMinSize = 0.07f;
f32 Settings::highwayParticleMaxSize = 0.17f;
f32 Settings::highwayParticleMinLifeTime = 0.1f;
f32 Settings::highwayParticleMaxLifeTime = 0.5f;
f32 Settings::highwayParticleColorVariation = 0.7f;
f32 Settings::highwayParticleMinVelocityX = -0.3f;
f32 Settings::highwayParticleMaxVelocityX = 0.3f;
f32 Settings::highwayParticleMinVelocityY = -0.1f;
f32 Settings::highwayParticleMaxVelocityY = 0.1f;
f32 Settings::highwayParticleMinVelocityZ = 3.8f;
f32 Settings::highwayParticleMaxVelocityZ = 4.1f;
f32 Settings::highwayParticleAccelerationX = 0.0f;
f32 Settings::highwayParticleAccelerationY = -4.0f;
f32 Settings::highwayParticleAccelerationZ = -2.0f;
f32 Settings::highwayParticleMinRotationAngle = -3.1415f;
f32 Settings::highwayParticleMaxRotationAngle = 3.1415f;
#endif // SHR3D_PARTICLE
#ifdef SHR3D_RENDERER_DEVELOPMENT
Renderer Settings::highwayRenderer = Renderer::production;
#endif // SHR3D_RENDERER_DEVELOPMENT
bool Settings::highwayReverseStrings = false;
f32 Settings::highwayScrollSpeed = 14.0f;
#ifdef SHR3D_SFX_CORE_HEXFIN
bool Settings::highwayTuner =
#ifdef PLATFORM_EMSCRIPTEN
false;
#else // PLATFORM_EMSCRIPTEN
true;
#endif // PLATFORM_EMSCRIPTEN
vec4 Settings::highwayTunerColor[4] = {
  colorVec4(u8"#6B6B6B40"),
  colorVec4(u8"#FFFFFFFF"),
  colorVec4(u8"#3265CFFF"),
  colorVec4(u8"#F8F8F8FF")
};
#endif // SHR3D_SFX_CORE_HEXFIN
bool Settings::highwayVUMeter = true;
vec4 Settings::highwayVUMeterColor[5] = {
  colorVec4(u8"#6B6B6B40"),
  colorVec4(u8"#5DEB24D8"),
  colorVec4(u8"#FF0000D8"),
  colorVec4(u8"#3265CFFF"),
  colorVec4(u8"#F8F8F8FF")
};
f32 Settings::highwayViewDistance = 100.0f;
#ifdef SHR3D_OPENXR
f32 Settings::hudDebugXrScale = 0.01f;
f32 Settings::hudDebugXrX = -20.0f;
f32 Settings::hudDebugXrY = 20.0f;
f32 Settings::hudDebugXrZ = -45.0f;
#endif // SHR3D_OPENXR
bool Settings::hudLyrics = true;
vec4 Settings::hudLyricsColor[3] = {
  colorVec4(u8"#6A2491FF"),
  colorVec4(u8"#E18616FF"),
  colorVec4(u8"#5752E9FF")
};
f32 Settings::hudLyricsScale = 2.0f;
f32 Settings::hudLyricsX = -0.96f;
f32 Settings::hudLyricsY[2] = { 0.69f, 0.51f };
bool Settings::hudNewHighscore = true;
#ifdef SHR3D_HUD_DEVELOPMENT
Renderer Settings::hudRenderer = Renderer::production;
#endif // SHR3D_HUD_DEVELOPMENT
bool Settings::hudTimelineLevel = true;
vec4 Settings::hudTimelineLevelColor[8] = {
  colorVec4(u8"#4F0505FF"),
  colorVec4(u8"#000E40FF"),
  colorVec4(u8"#730101FF"),
  colorVec4(u8"#062B8FFF"),
  colorVec4(u8"#404040A0"),
  colorVec4(u8"#808080A0"),
  colorVec4(u8"#404040A0"),
  colorVec4(u8"#808080A0")
};
bool Settings::hudTimelineLevelFlipY = false;
f32 Settings::hudTimelineLevelScaleX = 1.0f;
f32 Settings::hudTimelineLevelScaleY = 0.2f;
f32 Settings::hudTimelineLevelSpacing = 0.2f;
f32 Settings::hudTimelineLevelX = 0.0f;
f32 Settings::hudTimelineLevelY = 0.988f;
#ifdef SHR3D_OPENXR
bool Settings::hudTimelineLevelXrFlipY = false;
f32 Settings::hudTimelineLevelXrScaleX = 50.0f;
f32 Settings::hudTimelineLevelXrScaleY = 5.0f;
f32 Settings::hudTimelineLevelXrSpacing = 20.0f;
f32 Settings::hudTimelineLevelXrX = 0.0f;
f32 Settings::hudTimelineLevelXrY = 30.0f;
f32 Settings::hudTimelineLevelXrZ = -60.0f;
#endif // SHR3D_OPENXR
#ifdef SHR3D_MUSIC_STRETCHER
bool Settings::hudTimelineMusicStretcher = true;
vec4 Settings::hudTimelineMusicStretcherColor[2] = {
  colorVec4(u8"#FFFFFF00"),
  colorVec4(u8"#D64919FF")
};
f32 Settings::hudTimelineMusicStretcherScaleX = 1.0f;
f32 Settings::hudTimelineMusicStretcherScaleY = 0.01f;
f32 Settings::hudTimelineMusicStretcherX = 0.0f;
f32 Settings::hudTimelineMusicStretcherY = 0.96f;
#ifdef SHR3D_OPENXR
f32 Settings::hudTimelineMusicStretcherXrScaleX = 50.0f;
f32 Settings::hudTimelineMusicStretcherXrScaleY = 0.3f;
f32 Settings::hudTimelineMusicStretcherXrX = 0.0f;
f32 Settings::hudTimelineMusicStretcherXrY = 30.0f;
f32 Settings::hudTimelineMusicStretcherXrZ = -59.95f;
#endif // SHR3D_OPENXR
#endif // SHR3D_MUSIC_STRETCHER
bool Settings::hudTimelineTone = true;
vec4 Settings::hudTimelineToneColor[11] = {
  colorVec4(u8"#404040FF"),
  colorVec4(u8"#940FB0FF"),
  colorVec4(u8"#1F9601FF"),
  colorVec4(u8"#E05A01FF"),
  colorVec4(u8"#2381E9FF"),
  colorVec4(u8"#D2A20DFF"),
  colorVec4(u8"#D20000FF"),
  colorVec4(u8"#009B71FF"),
  colorVec4(u8"#999999FF"),
  colorVec4(u8"#CC81EDFF"),
  colorVec4(u8"#C2E96BFF")
};
f32 Settings::hudTimelineToneScaleX = 1.0f;
f32 Settings::hudTimelineToneScaleY = 0.04f;
f32 Settings::hudTimelineToneX = 0.0f;
f32 Settings::hudTimelineToneY = 0.96f;
#ifdef SHR3D_OPENXR
f32 Settings::hudTimelineToneXrScaleX = 50.0f;
f32 Settings::hudTimelineToneXrScaleY = 1.0f;
f32 Settings::hudTimelineToneXrX = 0.0f;
f32 Settings::hudTimelineToneXrY = 30.0f;
f32 Settings::hudTimelineToneXrZ = -60.0f;
#endif // SHR3D_OPENXR
vec4 Settings::hudTimelineQuickRepeaterColor[2] = {
  colorVec4(u8"#0065FFFF"),
  colorVec4(u8"#FF9A00FF")
};
bool Settings::hudTimelineQuickRepeaterFlipY = false;
f32 Settings::hudTimelineQuickRepeaterScaleY = 0.08f;
f32 Settings::hudTimelineQuickRepeaterX = 0.0f;
f32 Settings::hudTimelineQuickRepeaterY = 0.96f;
#ifdef SHR3D_OPENXR
f32 Settings::hudTimelineQuickRepeaterXrScaleX = 50.0f;
f32 Settings::hudTimelineQuickRepeaterXrScaleY = 1.0f;
f32 Settings::hudTimelineQuickRepeaterXrX = 0.0f;
f32 Settings::hudTimelineQuickRepeaterXrY = 30.0f;
f32 Settings::hudTimelineQuickRepeaterXrZ = -60.0f;
#endif // SHR3D_OPENXR
bool Settings::hudScore = false;
vec4 Settings::hudScoreColor[4] = {
  colorVec4(u8"#666666FF"),
  colorVec4(u8"#1263BCFF"),
  colorVec4(u8"#666666FF"),
  colorVec4(u8"#1263BCFF")
};
bool Settings::hudSongInfo = true;
vec4 Settings::hudSongInfoColor[2] = {
  colorVec4(u8"#FFFFFFAA"),
  colorVec4(u8"#FFFFFFAA"),
};
f32 Settings::hudSongInfoScale[2] = { 2.0f, 1.0f };
f32 Settings::hudSongInfoX = 0.95f;
f32 Settings::hudSongInfoY[2] = { 0.3f, 0.2f };
bool Settings::hudArrangementSwitch = true;
vec4 Settings::hudArrangementSwitchColor = colorVec4(u8"#FFFFFFAA");
f32 Settings::hudArrangementSwitchScaleX = 3.0f;
f32 Settings::hudArrangementSwitchScaleY = 3.0f;
f32 Settings::hudArrangementSwitchX = 0.0f;
f32 Settings::hudArrangementSwitchY = 0.60f;
#ifdef SHR3D_OPENXR
f32 Settings::hudArrangementSwitchXrScaleX = 0.1f;
f32 Settings::hudArrangementSwitchXrScaleY = 0.1f;
f32 Settings::hudArrangementSwitchXrX = 0.0f;
f32 Settings::hudArrangementSwitchXrY = 15.0f;
f32 Settings::hudArrangementSwitchXrZ = -60.0f;
#endif // SHR3D_OPENXR
bool Settings::hudToneSwitch = true;
bool Settings::hudToneSwitchTimer = false;
vec4 Settings::hudToneSwitchColor = colorVec4(u8"#FFFFFFAA");
vec4 Settings::hudToneSwitchHintColor = colorVec4(u8"#E79619AA");
f32 Settings::hudToneSwitchScale[2] = { 1.0f, 2.0f };
f32 Settings::hudToneSwitchX = 0.95f;
f32 Settings::hudToneSwitchY[2] = { 0.6f, 0.47f };
#ifdef SHR3D_OPENXR
f32 Settings::hudToneSwitchXrScale[2] = { 1.5f, 1.25f };
f32 Settings::hudToneSwitchXrX = 33.0f;
f32 Settings::hudToneSwitchXrY[2] = { 10.0f, 8.0f };
f32 Settings::hudToneSwitchXrZ = -60.0f;
#endif // SHR3D_OPENXR
bool Settings::hudWatermark = true;
vec4 Settings::hudWatermarkColor = colorVec4(u8"#FFFFFF40");
#ifdef SHR3D_OPENXR
f32 Settings::hudWatermarkXrX = 40.0f;
f32 Settings::hudWatermarkXrY = -2.0f;
f32 Settings::hudWatermarkXrZ = -30.0f;
#endif // SHR3D_OPENXR
bool Settings::metronomeEnabled = false;
f32 Settings::metronomeVolume = 0.5f;
bool Settings::metronomeDecay = true;
f32 Settings::metronomeFrequency0 = 2000.0f;
f32 Settings::metronomeFrequency1 = 1400.0f;
i32 Settings::metronomeClickLength = 100;
MetronomeSide Settings::metronomeSide = MetronomeSide::stereo;
std::u8string Settings::midiAutoConnectDevices;
u8 Settings::midiBinding[128] = { ARRAY_SET128(0xFF) };
f32 Settings::midiFineValueFactor = 0.1f;
NoteDetectionSource Settings::tunerNoteDetectionSource = NoteDetectionSource::pickup;
std::u8string Settings::pathStatsIni = u8"stats.ini";
std::u8string Settings::pathTonesIni = u8"tones.ini";
std::u8string Settings::pathBackup = u8"backup/";
#ifdef SHR3D_SHRED_OR_PSARC
std::u8string Settings::pathCache = u8"cache/";
#endif // SHR3D_SHRED_OR_PSARC
#ifdef SHR3D_SFX_PLUGIN_CLAP
std::u8string Settings::pathClap = u8"clap/"
#ifdef PLATFORM_WINDOWS
//u8"|%COMMONPROGRAMFILES%/CLAP/|%LOCALAPPDATA%/Programs/Common/CLAP/|%CLAP_PATH%/"
#endif // PLATFORM_WINDOWS
;
#endif // SHR3D_SFX_PLUGIN_CLAP
//#ifdef SHR3D_SFX_PLUGIN_LV2
//std::u8string Settings::pathLv2 = u8"lv2/
//#ifdef PLATFORM_WINDOWS
//u8"|%COMMONPROGRAMFILES%/LV2/|%APPDATA%/LV2/"
//#endif // PLATFORM_WINDOWS
//;
//#endif // SHR3D_SFX_PLUGIN_LV2
#ifdef SHR3D_ENVIRONMENT_MILK
std::u8string Settings::pathMilk = u8"milk/";
#endif // SHR3D_ENVIRONMENT_MILK
#ifdef SHR3D_SFX_CORE_NEURALAMPMODELER
std::u8string Settings::pathNam = u8"nam/";
#endif // SHR3D_SFX_CORE_NEURALAMPMODELER
#ifdef SHR3D_PSARC
std::u8string Settings::pathPsarc =
#ifdef PLATFORM_PICO_4
u8"/sdcard/Download/";
#else // PLATFORM_PICO_4
u8"psarc/";
#endif // PLATFORM_PICO_4
#endif // SHR3D_PSARC
#ifdef SHR3D_SHRED
std::u8string Settings::pathShred =
#ifdef PLATFORM_PICO_4
u8"/sdcard/Download/";
#else // PLATFORM_PICO_4
u8"shred/";
#endif // PLATFORM_PICO_4
#endif // SHR3D_SHRED
#ifdef SHR3D_RECORDER
std::u8string Settings::pathRecorder =
#ifdef PLATFORM_PICO_4
u8"/sdcard/Download/";
#else // PLATFORM_PICO_4
u8"recorder/";
#endif // PLATFORM_PICO_4
#endif // SHR3D_RECORDER
#ifdef SHR3D_SFX_PLUGIN_VST
std::u8string Settings::pathVst = u8"vst/"
#ifdef PLATFORM_WINDOWS
//u8"|%PROGRAMFILES(X86)%/Steinberg/VstPlugins|%PROGRAMFILES%/Steinberg/VstPlugins"
#endif // PLATFORM_WINDOWS
;
#endif // SHR3D_SFX_PLUGIN_VST
#ifdef SHR3D_SFX_PLUGIN_VST3
std::u8string Settings::pathVst3 = u8"vst3/"
#ifdef PLATFORM_WINDOWS
//u8"|%COMMONPROGRAMFILES%/VST3|%LOCALAPPDATA%/Programs/Common/VST3"
#endif // PLATFORM_WINDOWS
;
#endif // SHR3D_SFX_PLUGIN_VST3
#ifdef SHR3D_ENVIRONMENT_SKYBOX
std::u8string Settings::pathSkybox =
#ifdef PLATFORM_PICO_4
u8"/sdcard/Download/";
#else // PLATFORM_PICO_4
u8"skybox/";
#endif // PLATFORM_PICO_4
#endif // SHR3D_ENVIRONMENT_SKYBOX
#ifdef SHR3D_ENVIRONMENT_STAGE
std::u8string Settings::pathStage =
#ifdef PLATFORM_PICO_4
u8"/sdcard/Download/";
#else // PLATFORM_PICO_4
u8"stage/";
#endif // PLATFORM_PICO_4
#endif // SHR3D_ENVIRONMENT_STAGE
#ifdef SHR3D_SPOTIFY
std::string Settings::spotifyRedirectUri = "http://127.0.0.1:8888/callback";
std::string Settings::spotifyClientId = "";
std::string Settings::spotifyClientSecret = "";
#endif // SHR3D_SPOTIFY
#ifdef SHR3D_SFX
std::u8string Settings::tunerPlugin
#ifdef SHR3D_SFX_CORE_HEXFIN
= u8"Core,Hexfin";
#else // SHR3D_SFX_CORE_HEXFIN
;
#endif // SHR3D_SFX_CORE_HEXFIN
#ifdef SHR3D_MIDI
std::u8string Settings::tunerMidiDevice;
#endif // SHR3D_MIDI
std::u8string Settings::tunerMidiPlugin;
#endif // SHR3D_SFX
#ifdef SHR3D_SFX_CORE_HEXFIN
f32 Settings::tunerHexfinOnsetThreshold = -35.0;
f32 Settings::tunerHexfinReleaseThreshold = -60.0;
#endif // SHR3D_SFX_CORE_HEXFIN
f32 Settings::uiScale = 1.0f;
#ifdef SHR3D_OPENXR
f32 Settings::uiXrZ = -1.0f;
#endif // SHR3D_OPENXR
#ifdef SHR3D_CUSTOM_CURSOR
bool Settings::uiCursorCustom = true;
i32 Settings::uiCursorSize = 64;
#endif // SHR3D_CUSTOM_CURSOR
vec4 Settings::uiColor[30] = {
  colorVec4(u8"#EDE013B6"), // 0
  colorVec4(u8"#1C1717E6"), // 1
  colorVec4(u8"#4F1313F3"), // 2
  colorVec4(u8"#4D4B4B6F"), // 3
  colorVec4(u8"#4B1073FF"), // 4
  colorVec4(u8"#30CACFFF"), // 5
  colorVec4(u8"#AB14F0FF"), // 6
  colorVec4(u8"#3B3B3BFF"), // 7
  colorVec4(u8"#C00CA7FF"), // 8
  colorVec4(u8"#42FF25FF"), // 9
  colorVec4(u8"#00000000"), // 10
  colorVec4(u8"#70317CFF"), // 11
  colorVec4(u8"#02B8B5FF"), // 12
  colorVec4(u8"#1F9601FF"), // 13
  colorVec4(u8"#1F9601FF"), // 14
  colorVec4(u8"#E05A03FF"), // 15
  colorVec4(u8"#2C2B2BFF"), // 16
  colorVec4(u8"#686868FF"), // 17
  colorVec4(u8"#D66A6AFF"), // 18
  colorVec4(u8"#191919FF"), // 19
  colorVec4(u8"#CF3662FF"), // 20
  colorVec4(u8"#6C3073FF"), // 21
  colorVec4(u8"#49535EFF"), // 22
  colorVec4(u8"#000000FF"), // 23
  colorVec4(u8"#3E234DFF"), // 24
  colorVec4(u8"#4921CBFF"), // 25
  colorVec4(u8"#4244BEFF"), // 26
  colorVec4(u8"#570101FF"), // 27
  // additional custom colors:
  colorVec4(u8"#330084FF"), // 28
  colorVec4(u8"#CB7218FF")  // 29
};
#ifdef SHR3D_OPENXR
#ifdef SHR3D_OPENXR_PCVR
bool Settings::xrEnabled = false;
#endif // SHR3D_OPENXR_PCVR
#ifdef SHR3D_OPENXR_CONTROLLER_PICO4_AND_QUEST3
XrController Settings::xrController =
#ifndef PLATFORM_PICO_4
XrController::quest3;
#else // PLATFORM_PICO_4
XrController::pico4;
#endif // PLATFORM_PICO_4
#endif // SHR3D_OPENXR_CONTROLLER_PICO4_AND_QUEST3
vec4 Settings::xrControllerColor[2] = {
  colorVec4(u8"#AB0000FF"),
  colorVec4(u8"#1A9C15FF")
};
vec4 Settings::xrCursorColor[2] = {
  colorVec4(u8"#FFFFFFFF"),
  colorVec4(u8"#55555555")
};
vec4 Settings::xrPointerColor = colorVec4(u8"#FFFFFFAA");
//    f32 xrUiCircularProjection = 0.0f;
#endif // SHR3D_OPENXR




















static std::map<std::string, std::map<std::string, std::string>> commandLineSettings;

#ifdef SHR3D_GETOPT


#ifndef PLATFORM_EMSCRIPTEN
static void printUsage() {
  puts("Usage: Shr3D.exe [OPTIONS] [FILE]\n"
    "OPTIONS will overwrite some default settings and are mostly for debugging.\n"
    "Using OPTIONS will skip the installation window and it will prevent saving changes in settings.ini.\n"
    "\n"
    "OPTIONS | example       | Description:\n"
    "--------+---------------+----------------------\n"
    " -s     | settings2.ini | Path to settings.ini\n"
    " -p     | psarc2/       | Directory .psarc files\n"
    " -c     | cache2/       | Directory for the cache\n"
    " -r     | 48000         | Audio Sample Rate\n"
    " -b     | 128           | Audio Block Size\n"
    " -f     | 1             | Fullscreen\n"
    " -w     | 1920          | Window width\n"
    " -h     | 1080          | Window height\n"
    " -u     | 1.5           | Ui Scaling\n"
    "\n"
    "FILE is a .psarc file this will be loaded first in the Collection\n"
    "On Emscripten FILE can also be a urls.txt containing paths/urls to .shred and .psarc files\n");

  fflush(stdout);
}
#endif // PLATFORM_EMSCRIPTEN

static void parseCommandLineArgSettingsIni(int argc, char* argv[])
{
  int c;
  while ((c = getopt(argc, argv, "s:")) != -1)
  {
    switch (c)
    {
    case 's':
      Global::pathSettingsIni = reinterpret_cast<const char8_t*>(optarg_);
      goto end;
    }
  }
end:
  optind_ = 0; // reset index for the second parsing of the args
}

static void parseCommandLineArgs(int argc, char* argv[])
{
  int c;
  while ((c = getopt(argc, argv, "s:p:c:r:b:f:w:h:u:")) != -1)
  {
    Global::installMode = InstallMode::continueWithoutSaving;
    // this skips the installation window and prevent writing changes to settings.ini
    switch (c)
    {
    case 's':
      // already handled by parseCommandLineArgSettingsIni
      break;
#ifdef SHR3D_PSARC
    case 'p':
      Settings::pathPsarc = reinterpret_cast<const char8_t*>(optarg_);
      break;
#endif // SHR3D_PSARC
#ifdef SHR3D_SHRED_OR_PSARC
    case 'c':
      Settings::pathCache = reinterpret_cast<const char8_t*>(optarg_);
      break;
#endif // SHR3D_SHRED_OR_PSARC
    case 'r':
      sampleRate() = atoi(optarg_);
      break;
    case 'b':
      blockSize() = atoi(optarg_);
      break;
    case 'f':
      Settings::graphicsFullscreen = FullscreenMode(atoi(optarg_));
      break;
    case 'w':
      Settings::graphicsWindowWidth = atoi(optarg_);
      break;
    case 'h':
      Settings::graphicsWindowHeight = atoi(optarg_);
      break;
    case 'u':
      Settings::uiScale = f32(atof(optarg_));
      break;
    default:
#ifndef PLATFORM_EMSCRIPTEN
      printUsage();
      quick_exit(0);
#endif // PLATFORM_EMSCRIPTEN
      break;
    }
  }

  if (optarg_ != nullptr)
  {
    const std::u8string optarg = reinterpret_cast<const char8_t*>(optarg_);
    DEBUG_PRINT("optarg: %s\n", optarg_);

    if (!optarg.empty())
    {
      u64 found = optarg.find(u8"#");
      if (found == std::string::npos)
        found = optarg.find(u8"|");

      std::u8string filePath;
      std::u8string autoplayArrangement;

      if (found != std::string::npos)
      {
        filePath = optarg.substr(0, found);
        autoplayArrangement = optarg.substr(found + 1);
      }
      else
      {
        filePath = optarg;
      }

#ifdef PLATFORM_EMSCRIPTEN
      if (found != std::string::npos)
        Global::inputHideMenu.toggled = true;

      Global::autoFetchUrl = filePath;
      Global::downloadAutoplayArrangement = autoplayArrangement;
#else // PLATFORM_EMSCRIPTEN
      Global::skipFetchingCollection = true;

      if (File::exists(filePath.c_str()))
      {
        const SongIndex songIndex = SongIndex(Global::songFilePath.size());
        {
          const std::vector<u8> fileData = File::read(filePath.c_str());
          Collection::addSongFile(filePath, fileData.data(), fileData.size());
        }

        if (!autoplayArrangement.empty())
        {
          ArrangementIndex arrangementIndex = -1;
          for (i32 i = 0; i < i32(Global::songInfos[songIndex].arrangementInfos.size()); ++i)
          {
            if (autoplayArrangement == Global::songInfos[songIndex].arrangementInfos[i].arrangementName)
            {
              arrangementIndex = i;
              break;
            }
          }

          Player::playSong(songIndex, arrangementIndex);
        }
      }
#endif // PLATFORM_EMSCRIPTEN
    }
  }
}
#endif // SHR3D_GETOPT

static std::map<std::u8string, std::map<std::u8string, std::u8string>> serializeSettings()
{
  std::map<std::u8string, std::map<std::u8string, std::u8string>> serializedSettings =
  {
    {
      u8"Application",
      {
        { u8"Instrument",                         to_string(to_underlying_(Settings::applicationInstrument)) },
        { u8"BackupMode",                         to_string(to_underlying_(Settings::applicationBackupMode)) },
        { u8"EndOfSong",                          to_string(to_underlying_(Settings::applicationEndOfSong)) },
        { u8"ToneSwitch",                         to_string(Settings::applicationToneSwitch) },
      }
    },
    {
      u8"Audio",
      {
        { u8"System",                             to_string(to_underlying_(Settings::audioSystem)) },
#ifdef SHR3D_AUDIO_AAUDIO
        { u8"AAudioBlockSize",                    to_string(Settings::audioAAudioBlockSize) },
        { u8"AAudioChannelInput",                 to_string(Settings::audioAAudioChannelInput) },
#ifdef SHR3D_COOP
        { u8"AAudioChannelInputCoop",             to_string(Settings::audioAAudioChannelInputCoop) },
#endif // SHR3D_COOP
        { u8"AAudioDeviceInput",                  TODOFIX(Settings::audioAAudioDeviceInput) },
        { u8"AAudioDeviceOutput",                 TODOFIX(Settings::audioAAudioDeviceOutput) },
        { u8"AAudioChannelInput",                 to_string(Settings::audioAAudioChannelInput) },
#ifdef SHR3D_COOP
        { u8"AAudioChannelInputCoop",             to_string(Settings::audioAAudioChannelInputCoop) },
#endif // SHR3D_COOP
        { u8"AAudioSampleRate",                   to_string(Settings::audioAAudioSampleRate) },
        { u8"AAudioExclusiveMode",                to_string(Settings::audioAAudioExclusiveMode) },
        { u8"AAudioPerformanceMode",              to_string(to_underlying_(Settings::audioAAudioPerformanceMode)) },
#endif // SHR3D_AUDIO_AAUDIO
#ifdef SHR3D_AUDIO_ASIO
        { u8"AsioDevice",                         TODOFIX(Settings::audioAsioDevice) },
        { u8"AsioBlockSize",                      to_string(Settings::audioAsioBlockSize) },
        { u8"AsioSampleRate",                     to_string(Settings::audioAsioSampleRate) },
        { u8"AsioChannelInput0",                  to_string(Settings::audioAsioChannelInput0) },
        { u8"AsioChannelInput1",                  to_string(Settings::audioAsioChannelInput1) },
        { u8"AsioChannelOutput",                  to_string(Settings::audioAsioChannelOutput) },
#ifdef SHR3D_COOP
        { u8"AsioChannelInputCoop0",              to_string(Settings::audioAsioChannelInputCoop0) },
        { u8"AsioChannelInputCoop1",              to_string(Settings::audioAsioChannelInputCoop1) },
#endif // SHR3D_COOP
#ifdef SHR3D_SFX_CORE_HEXFIN_DIVIDED
#ifdef SHR3D_AUDIO_ASIO_SECOND_DEVICE_FOR_TUNER_DIVIDED
        { u8"AsioSecondDeviceForTunerDivided",    TODOFIX(Settings::audioAsioSecondDeviceForTunerDivided) },
#endif // SHR3D_AUDIO_ASIO_SECOND_DEVICE_FOR_TUNER_DIVIDED
        { u8"AsioDividedPickup",                  to_string(Settings::audioAsioDividedPickup) },
        { u8"AsioDividedPickupAsMainInput",       to_string(Settings::audioAsioDividedPickupAsMainInput) },
        { u8"AsioDividedPickupChannelString0",    to_string(Settings::audioAsioDividedPickupChannelString0) },
        { u8"AsioDividedPickupChannelString1",    to_string(Settings::audioAsioDividedPickupChannelString1) },
        { u8"AsioDividedPickupChannelString2",    to_string(Settings::audioAsioDividedPickupChannelString2) },
        { u8"AsioDividedPickupChannelString3",    to_string(Settings::audioAsioDividedPickupChannelString3) },
        { u8"AsioDividedPickupChannelString4",    to_string(Settings::audioAsioDividedPickupChannelString4) },
        { u8"AsioDividedPickupChannelString5",    to_string(Settings::audioAsioDividedPickupChannelString5) },
#endif // SHR3D_SFX_CORE_HEXFIN_DIVIDED
#endif // SHR3D_AUDIO_ASIO
#ifdef SHR3D_AUDIO_JACK
        { u8"JackInputDevice0",                   TODOFIX(Settings::audioJackInputDevice0) },
        { u8"JackInputDevice1",                   TODOFIX(Settings::audioJackInputDevice1) },
        { u8"JackOutputDevice0",                  TODOFIX(Settings::audioJackOutputDevice0) },
        { u8"JackOutputDevice1",                  TODOFIX(Settings::audioJackOutputDevice1) },
#ifdef SHR3D_COOP
        { u8"JackInputDeviceCoop0",               TODOFIX(Settings::audioJackInputDeviceCoop0) },
        { u8"JackInputDeviceCoop1",               TODOFIX(Settings::audioJackInputDeviceCoop1) },
#endif // SHR3D_COOP
#ifdef SHR3D_SFX_CORE_HEXFIN_DIVIDED
        { u8"JackDividedPickup",                  to_string(Settings::audioJackDividedPickup) },
        { u8"JackDividedPickupAsMainInput",       to_string(Settings::audioJackDividedPickupAsMainInput) },
        { u8"JackDividedPickupChannelString0",    TODOFIX(Settings::audioJackDividedPickupChannelString0) },
        { u8"JackDividedPickupChannelString1",    TODOFIX(Settings::audioJackDividedPickupChannelString1) },
        { u8"JackDividedPickupChannelString2",    TODOFIX(Settings::audioJackDividedPickupChannelString2) },
        { u8"JackDividedPickupChannelString3",    TODOFIX(Settings::audioJackDividedPickupChannelString3) },
        { u8"JackDividedPickupChannelString4",    TODOFIX(Settings::audioJackDividedPickupChannelString4) },
        { u8"JackDividedPickupChannelString5",    TODOFIX(Settings::audioJackDividedPickupChannelString5) },
#endif // SHR3D_SFX_CORE_HEXFIN_DIVIDED
#endif // SHR3D_AUDIO_JACK
#ifdef SHR3D_AUDIO_PIPEWIRE
        { u8"PipewireInputDevice0",               TODOFIX(Settings::audioPipewireInputDevice0) },
        { u8"PipewireInputDevice1",               TODOFIX(Settings::audioPipewireInputDevice1) },
        { u8"PipewireOutputDevice0",              TODOFIX(Settings::audioPipewireOutputDevice0) },
        { u8"PipewireOutputDevice1",              TODOFIX(Settings::audioPipewireOutputDevice1) },
#ifdef SHR3D_COOP
        { u8"PipewireInputDeviceCoop0",           TODOFIX(Settings::audioPipewireInputDeviceCoop0) },
        { u8"PipewireInputDeviceCoop1",           TODOFIX(Settings::audioPipewireInputDeviceCoop1) },
#endif // SHR3D_COOP
#ifdef SHR3D_SFX_CORE_HEXFIN_DIVIDED
        { u8"PipewireDividedPickup",              to_string(Settings::audioPipewireDividedPickup) },
        { u8"PipewireDividedPickupAsMainInput",   to_string(Settings::audioPipewireDividedPickupAsMainInput) },
        { u8"PipewireDividedPickupChannelString0",TODOFIX(Settings::audioPipewireDividedPickupChannelString0) },
        { u8"PipewireDividedPickupChannelString1",TODOFIX(Settings::audioPipewireDividedPickupChannelString1) },
        { u8"PipewireDividedPickupChannelString2",TODOFIX(Settings::audioPipewireDividedPickupChannelString2) },
        { u8"PipewireDividedPickupChannelString3",TODOFIX(Settings::audioPipewireDividedPickupChannelString3) },
        { u8"PipewireDividedPickupChannelString4",TODOFIX(Settings::audioPipewireDividedPickupChannelString4) },
        { u8"PipewireDividedPickupChannelString5",TODOFIX(Settings::audioPipewireDividedPickupChannelString5) },
#endif // SHR3D_SFX_CORE_HEXFIN_DIVIDED
#endif // SHR3D_AUDIO_PIPEWIRE
#ifdef SHR3D_AUDIO_SDL
        { u8"SdlBlockSize",                       to_string(Settings::audioSdlBlockSize) },
        { u8"SdlChannelInput",                    to_string(Settings::audioSdlChannelInput) },
#ifdef SHR3D_COOP
        { u8"SdlChannelInputCoop",                to_string(Settings::audioSdlChannelInputCoop) },
#endif // SHR3D_COOP
        { u8"SdlDeviceInput",                     TODOFIX(Settings::audioSdlDeviceInput) },
        { u8"SdlDeviceOutput",                    TODOFIX(Settings::audioSdlDeviceOutput) },
        { u8"SdlSampleRate",                      to_string(Settings::audioSdlSampleRate) },
#endif // SHR3D_AUDIO_SDL
#ifdef SHR3D_AUDIO_SUPERPOWERED
        { u8"SuperpoweredBlockSize",                   to_string(Settings::audioSuperpoweredBlockSize) },
        { u8"SuperpoweredCofiguration",                Settings::audioSuperpoweredCofiguration },
        { u8"SuperpoweredChannelInput",                to_string(Settings::audioSuperpoweredChannelInput) },
        { u8"SuperpoweredChannelOutput",               to_string(Settings::audioSuperpoweredChannelOutput) },
        { u8"SuperpoweredDeviceInput",                 Settings::audioSuperpoweredDeviceInput },
        { u8"SuperpoweredDeviceOutput",                Settings::audioSuperpoweredDeviceOutput },
        { u8"SuperpoweredSustainedPerformanceMode",    to_string(Settings::audioSuperpoweredSustainedPerformanceMode) },
#ifdef SHR3D_SFX_CORE_HEXFIN_DIVIDED
        { u8"SuperpoweredDividedPickup",               to_string(Settings::audioSuperpoweredDividedPickup) },
        { u8"SuperpoweredDividedPickupChannelString0", to_string(Settings::audioSuperpoweredDividedPickupChannelString0) },
        { u8"SuperpoweredDividedPickupChannelString1", to_string(Settings::audioSuperpoweredDividedPickupChannelString1) },
        { u8"SuperpoweredDividedPickupChannelString2", to_string(Settings::audioSuperpoweredDividedPickupChannelString2) },
        { u8"SuperpoweredDividedPickupChannelString3", to_string(Settings::audioSuperpoweredDividedPickupChannelString3) },
        { u8"SuperpoweredDividedPickupChannelString4", to_string(Settings::audioSuperpoweredDividedPickupChannelString4) },
        { u8"SuperpoweredDividedPickupChannelString5", to_string(Settings::audioSuperpoweredDividedPickupChannelString5) },
#endif // SHR3D_SFX_CORE_HEXFIN_DIVIDED
#endif // SHR3D_AUDIO_SUPERPOWERED
#ifdef SHR3D_AUDIO_WASAPI
        { u8"WasapiBlockSize",                    to_string(Settings::audioWasapiBlockSize) },
        { u8"WasapiChannelInput0",                to_string(Settings::audioWasapiChannelInput0) },
#ifdef SHR3D_COOP
        { u8"WasapiChannelInput1",                to_string(Settings::audioWasapiChannelInput1) },
#endif // SHR3D_COOP
        { u8"WasapiDeviceInput",                  TODOFIX(Settings::audioWasapiDeviceInput) },
        { u8"WasapiDeviceOutput",                 TODOFIX(Settings::audioWasapiDeviceOutput) },
        { u8"WasapiSampleRate",                   to_string(Settings::audioWasapiSampleRate) },
        { u8"WasapiExclusiveMode",                to_string(Settings::audioWasapiExclusiveMode) },
#endif // SHR3D_AUDIO_WASAPI
#ifdef SHR3D_AUDIO_WEBAUDIO
        { u8"WebAudioChannelInput0",              to_string(Settings::audioWebAudioChannelInput0) },
        { u8"WebAudioSampleRate",                 to_string(Settings::audioWebAudioSampleRate) },
#endif // SHR3D_AUDIO_WEBAUDIO
        { u8"InstrumentVolume",                   to_string(Settings::audioEffectVolume) },
        { u8"InstrumentVolumeCoop",               to_string(Settings::audioEffectVolumeCoop) },
        { u8"MusicVolume",                        to_string(Settings::audioMusicVolume) }
      }
    },
    {
      u8"Environment",
      {
        { u8"ClearColor",                         hexColor(Settings::environmentClearColor) },
#ifdef SHR3D_ENVIRONMENT_MILK
        { u8"Milk",                               to_string(Settings::environmentMilk) },
        { u8"MilkBeatSensitivity",                to_string(Settings::environmentMilkBeatSensitivity) },
        { u8"MilkDuration",                       to_string(Settings::environmentMilkDuration) },
        { u8"MilkMeshSize",                       to_string(Settings::environmentMilkMeshSize) },
        { u8"MilkFrameSkip",                      to_string(Settings::environmentMilkFrameSkip) },
        { u8"MilkFrameSpeed",                     to_string(Settings::environmentMilkFrameSpeed) },
        { u8"MilkShuffle",                        to_string(Settings::environmentMilkShuffle) },
#endif // SHR3D_ENVIRONMENT_MILK
#ifdef SHR3D_ENVIRONMENT_SKYBOX
        { u8"Skybox",                             Settings::environmentSkybox },
        { u8"SkyboxRotation",                     to_string(Settings::environmentSkyboxRotation) },
#endif //  SHR3D_ENVIRONMENT_SKYBOX
      }
    },
    {
      u8"Camera",
      {
        { u8"Mode",                               to_string(to_underlying_(Settings::cameraMode)) },
#ifndef PLATFORM_OPENXR_ANDROID
        { u8"FieldOfView",                        to_string(Settings::cameraFieldOfView) },
#endif // PLATFORM_OPENXR_ANDROID
        { u8"FixedX",                             to_string(Settings::cameraFixedX) },
        { u8"FixedXRotation",                     to_string(Settings::cameraFixedXRotation) },
        { u8"FixedY",                             to_string(Settings::cameraFixedY) },
        { u8"FixedYRotation",                     to_string(Settings::cameraFixedYRotation) },
        { u8"FixedZ",                             to_string(Settings::cameraFixedZ) },
        { u8"ParallaxAnchorTackingDuration",      to_string(Settings::cameraParallaxAnchorTackingDuration) },
        { u8"ParallaxHighwayRotation",            to_string(Settings::cameraParallaxHighwayRotation) },
        { u8"ParallaxHighwayScale",               to_string(Settings::cameraParallaxHighwayScale) },
        { u8"ParallaxHighwayX",                   to_string(Settings::cameraParallaxHighwayX) },
        { u8"ParallaxHighwayXFactor",             to_string(Settings::cameraParallaxHighwayXFactor) },
        { u8"ParallaxHighwayY",                   to_string(Settings::cameraParallaxHighwayY) },
        { u8"ParallaxHighwayYFactor",             to_string(Settings::cameraParallaxHighwayYFactor) },
        { u8"ParallaxHighwayZ",                   to_string(Settings::cameraParallaxHighwayZ) },
        { u8"ParallaxHighwayZFactor",             to_string(Settings::cameraParallaxHighwayZFactor) },
        { u8"ParallaxX",                          to_string(Settings::cameraParallaxX) },
        { u8"ParallaxXFactor",                    to_string(Settings::cameraParallaxXFactor) },
        { u8"ParallaxXRotation",                  to_string(Settings::cameraParallaxXRotation) },
        { u8"ParallaxY",                          to_string(Settings::cameraParallaxY) },
        { u8"ParallaxYFactor",                    to_string(Settings::cameraParallaxYFactor) },
        { u8"ParallaxYRotation",                  to_string(Settings::cameraParallaxYRotation) },
        { u8"ParallaxZ",                          to_string(Settings::cameraParallaxZ) },
        { u8"ParallaxZFactor",                    to_string(Settings::cameraParallaxZFactor) },
#ifdef SHR3D_OPENXR_PCVR
        { u8"PcVrMode",                           to_string(to_underlying_(Settings::cameraPcVrMode)) },
        { u8"PcVrParallaxAnchorTackingDuration",  to_string(Settings::cameraPcVrParallaxAnchorTackingDuration) },
        { u8"PcVrParallaxHighwayRotation",        to_string(Settings::cameraPcVrParallaxHighwayRotation) },
        { u8"PcVrParallaxHighwayScale",           to_string(Settings::cameraPcVrParallaxHighwayScale) },
        { u8"PcVrParallaxHighwayX",               to_string(Settings::cameraPcVrParallaxHighwayX) },
        { u8"PcVrParallaxHighwayXFactor",         to_string(Settings::cameraPcVrParallaxHighwayXFactor) },
        { u8"PcVrParallaxHighwayY",               to_string(Settings::cameraPcVrParallaxHighwayY) },
        { u8"PcVrParallaxHighwayYFactor",         to_string(Settings::cameraPcVrParallaxHighwayYFactor) },
        { u8"PcVrParallaxHighwayZ",               to_string(Settings::cameraPcVrParallaxHighwayZ) },
        { u8"PcVrParallaxHighwayZFactor",         to_string(Settings::cameraPcVrParallaxHighwayZFactor) },
        { u8"PcVrParallaxXFactor",                to_string(Settings::cameraPcVrParallaxXFactor) },
        { u8"PcVrParallaxX",                      to_string(Settings::cameraPcVrParallaxX) },
        { u8"PcVrParallaxXRotation",              to_string(Settings::cameraPcVrParallaxXRotation) },
        { u8"PcVrParallaxYFactor",                to_string(Settings::cameraPcVrParallaxYFactor) },
        { u8"PcVrParallaxY",                      to_string(Settings::cameraPcVrParallaxY) },
        { u8"PcVrParallaxYRotation",              to_string(Settings::cameraPcVrParallaxYRotation) },
        { u8"PcVrParallaxZFactor",                to_string(Settings::cameraPcVrParallaxZFactor) },
        { u8"PcVrParallaxZ",                      to_string(Settings::cameraPcVrParallaxZ) },
#endif // SHR3D_OPENXR_PCVR
      }
    },
    {
      u8"Graphics",
      {
        { u8"Fullscreen",                         to_string(to_underlying_(Settings::graphicsFullscreen)) },
#ifdef SHR3D_GRAPHICS_MSAA
        { u8"MSAA",                               to_string(Settings::graphicsMSAA) },
#endif // SHR3D_GRAPHICS_MSAA
        { u8"Scaling",                            to_string(to_underlying_(Settings::graphicsScaling)) },
#ifdef SHR3D_OPENGL_SPIR_V
        { u8"SpirV",                              to_string(Settings::graphicsSpirV) },
#endif // SHR3D_OPENGL_SPIR_V
#ifdef PLATFORM_QUEST_3
        { u8"RefreshRate",                        to_string(Settings::graphicsRefreshRate) },
#endif // PLATFORM_QUEST_3
#if !defined(PLATFORM_EMSCRIPTEN) && !defined(PLATFORM_QUEST_3)
        { u8"VSync",                              to_string(to_underlying_(Settings::graphicsVSync)) },
#endif // !PLATFORM_EMSCRIPTEN && !PLATFORM_QUEST_3
        { u8"WindowWidth",                        to_string(Settings::graphicsWindowWidth) },
        { u8"WindowHeight",                       to_string(Settings::graphicsWindowHeight) },
      }
    },
    {
      u8"Highway",
      {
        { u8"AnchorColor0",                       hexColor(Settings::highwayAnchorColor[0]) },
        { u8"AnchorColor1",                       hexColor(Settings::highwayAnchorColor[1]) },
        { u8"AnchorColor2",                       hexColor(Settings::highwayAnchorColor[2]) },
        { u8"AnchorColor3",                       hexColor(Settings::highwayAnchorColor[3]) },
        { u8"AnchorColorExponent",                to_string(Settings::highwayAnchorColorExponent) },
        { u8"Beat",                               to_string(Settings::highwayBeat) },
        { u8"BeatColor0",                         hexColor(Settings::highwayBeatColor[0]) },
        { u8"BeatColor1",                         hexColor(Settings::highwayBeatColor[1]) },
        { u8"BeatStrumDirection",                 to_string(Settings::highwayBeatStrumDirection) },
        { u8"BeatStrumDirectionColor0",           hexColor(Settings::highwayBeatStrumDirectionColor[0]) },
        { u8"BeatStrumDirectionColor1",           hexColor(Settings::highwayBeatStrumDirectionColor[1]) },
        { u8"BeatStrumDirectionPrimary",          to_string(to_underlying_(Settings::highwayBeatStrumDirectionPrimary)) },
        { u8"BeatStrumDirectionNext",             to_string(to_underlying_(Settings::highwayBeatStrumDirectionNext)) },
        { u8"BeatStrumsBetweenBeats",             to_string(Settings::highwayBeatStrumsBetweenBeats) },
        { u8"CapoColor",                          hexColor(Settings::highwayCapoColor) },
        { u8"ChordBox",                           to_string(Settings::highwayChordBox) },
        { u8"ChordBoxArpeggio",                   to_string(Settings::highwayChordBoxArpeggio) },
        { u8"ChordBoxArpeggioColor",              hexColor(Settings::highwayChordBoxArpeggioColor) },
        { u8"ChordBoxColor",                      hexColor(Settings::highwayChordBoxColor) },
        { u8"ChordFretNumbers",                   to_string(Settings::highwayChordFretNumbers) },
        { u8"ChordName",                          to_string(Settings::highwayChordName) },
        { u8"ChordNameColor",                     hexColor(Settings::highwayChordNameColor) },
        { u8"DotInlayColor0",                     hexColor(Settings::highwayDotInlayColor[0]) },
        { u8"DotInlayColor1",                     hexColor(Settings::highwayDotInlayColor[1]) },
        { u8"DotInlayColor2",                     hexColor(Settings::highwayDotInlayColor[2]) },
        { u8"DotInlayColor3",                     hexColor(Settings::highwayDotInlayColor[3]) },
        { u8"FadeFarDistance",                    to_string(Settings::highwayFadeFarDistance) },
        { u8"FadeNearDistance",                   to_string(Settings::highwayFadeNearDistance) },
        { u8"FadeNearStrength",                   to_string(Settings::highwayFadeNearStrength) },
        { u8"FingerNumberColor",                  hexColor(Settings::highwayFingerNumberColor) },
        { u8"FingerNumbers",                      to_string(Settings::highwayFingerNumbers) } ,
        { u8"FretboardFretColor",                 hexColor(Settings::highwayFretboardFretColor)},
        { u8"FretboardFretNumberColor0",          hexColor(Settings::highwayFretboardFretNumberColor[0])},
        { u8"FretboardFretNumberColor1",          hexColor(Settings::highwayFretboardFretNumberColor[1])},
        { u8"FretboardFretNumberColor2",          hexColor(Settings::highwayFretboardFretNumberColor[2])},
        { u8"FretboardNoteHeight",                to_string(Settings::highwayFretboardNoteHeight) },
        { u8"FretboardNoteNames",                 to_string(Settings::highwayFretboardNoteNames) },
        { u8"FretboardNoteNameColor0",            hexColor(Settings::highwayFretboardNoteNameColor[0]) },
        { u8"FretboardNoteNameColor1",            hexColor(Settings::highwayFretboardNoteNameColor[1]) },
        { u8"FretboardNoteWidth",                 to_string(Settings::highwayFretboardNoteWidth) },
        { u8"FretboardCollisionNotes",            to_string(Settings::highwayFretboardCollisionNotes) },
        { u8"FretboardCollisionNotesColor0",      hexColor(Settings::highwayFretboardCollisionNotesColor[0])},
        { u8"FretboardCollisionNotesColor1",      hexColor(Settings::highwayFretboardCollisionNotesColor[1])},
        { u8"FretboardPlayedNotes",               to_string(Settings::highwayFretboardPlayedNotesDot) },
        { u8"FretboardPlayedNotesColor0",         hexColor(Settings::highwayFretboardPlayedNotesDotColor[0])},
        { u8"FretboardPlayedNotesColor1",         hexColor(Settings::highwayFretboardPlayedNotesDotColor[1])},
#ifdef SHR3D_SFX_CORE_HEXFIN
        { u8"FretboardPlayedNotesTuner",          to_string(Settings::highwayFretboardPlayedNotesTuner) },
#endif // SHR3D_SFX_CORE_HEXFIN
        { u8"FretboardStringNoteNames",           to_string(Settings::highwayFretboardStringNoteNames) },
#ifdef SHR3D_PARTICLE
        { u8"ParticlePlayedNotes",                to_string(Settings::highwayParticlePlayedNotes) },
        { u8"ParticleCollisionNotes",             to_string(Settings::highwayParticleCollisionNotes) },
        { u8"ParticleShape",                      to_string(Settings::highwayParticleShape) },
        { u8"ParticleMaxCount",                   to_string(Settings::highwayParticleMaxCount) },
        { u8"ParticleSpawnsPerSecond",            to_string(Settings::highwayParticleSpawnsPerSecond) },
        { u8"ParticleSpawnRadius",                to_string(Settings::highwayParticleSpawnRadius) },
        { u8"ParticleMinSize",                    to_string(Settings::highwayParticleMinSize) },
        { u8"ParticleMaxSize",                    to_string(Settings::highwayParticleMaxSize) },
        { u8"ParticleMinLifeTime",                to_string(Settings::highwayParticleMinLifeTime) },
        { u8"ParticleMaxLifeTime",                to_string(Settings::highwayParticleMaxLifeTime) },
        { u8"ParticleColorVariation",             to_string(Settings::highwayParticleColorVariation) },
        { u8"ParticleMinVelocityX",               to_string(Settings::highwayParticleMinVelocityX) },
        { u8"ParticleMaxVelocityX",               to_string(Settings::highwayParticleMaxVelocityX) },
        { u8"ParticleMinVelocityY",               to_string(Settings::highwayParticleMinVelocityY) },
        { u8"ParticleMaxVelocityY",               to_string(Settings::highwayParticleMaxVelocityY) },
        { u8"ParticleMinVelocityZ",               to_string(Settings::highwayParticleMinVelocityZ) },
        { u8"ParticleMaxVelocityZ",               to_string(Settings::highwayParticleMaxVelocityZ) },
        { u8"ParticleAccelerationX",              to_string(Settings::highwayParticleAccelerationX) },
        { u8"ParticleAccelerationY",              to_string(Settings::highwayParticleAccelerationY) },
        { u8"ParticleAccelerationZ",              to_string(Settings::highwayParticleAccelerationZ) },
        { u8"ParticleMinRotationAngle",           to_string(Settings::highwayParticleMinRotationAngle) },
        { u8"ParticleMaxRotationAngle",           to_string(Settings::highwayParticleMaxRotationAngle) },
#endif // SHR3D_PARTICLE
        { u8"GroundFretColor0",                   hexColor(Settings::highwayGroundFretColor[0]) },
        { u8"GroundFretColor1",                   hexColor(Settings::highwayGroundFretColor[1]) },
        { u8"InstrumentBass5StringHideString0",   to_string(Settings::highwayInstrumentBass5StringHideString0) } ,
        { u8"InstrumentBass5StringTuning0",       to_string(Settings::highwayInstrumentBass5StringTuning[0]) },
        { u8"InstrumentBass5StringTuning1",       to_string(Settings::highwayInstrumentBass5StringTuning[1]) },
        { u8"InstrumentBass5StringTuning2",       to_string(Settings::highwayInstrumentBass5StringTuning[2]) },
        { u8"InstrumentBass5StringTuning3",       to_string(Settings::highwayInstrumentBass5StringTuning[3]) },
        { u8"InstrumentBassFirstWoundString",     to_string(Settings::highwayInstrumentBassFirstWoundString) },
        { u8"InstrumentBassFretSpacing",          to_string(Settings::highwayInstrumentBassFretSpacing) },
        { u8"InstrumentBassFretSpacingFactor",    to_string(Settings::highwayInstrumentBassFretSpacingFactor) },
        { u8"InstrumentBassStringColor0",         hexColor(Settings::highwayInstrumentBassStringColor[0]) },
        { u8"InstrumentBassStringColor1",         hexColor(Settings::highwayInstrumentBassStringColor[1]) },
        { u8"InstrumentBassStringColor2",         hexColor(Settings::highwayInstrumentBassStringColor[2]) },
        { u8"InstrumentBassStringColor3",         hexColor(Settings::highwayInstrumentBassStringColor[3]) },
        { u8"InstrumentBassStringColor4",         hexColor(Settings::highwayInstrumentBassStringColor[4]) },
        { u8"InstrumentBassStringColor5",         hexColor(Settings::highwayInstrumentBassStringColor[5]) },
        { u8"InstrumentBassStringSpacing",        to_string(Settings::highwayInstrumentBassStringSpacing) },
        { u8"InstrumentGuitar7StringHideString0", to_string(Settings::highwayInstrumentGuitar7StringHideString0) } ,
        { u8"InstrumentGuitar7StringTuning0",     to_string(Settings::highwayInstrumentGuitar7StringTuning[0]) },
        { u8"InstrumentGuitar7StringTuning1",     to_string(Settings::highwayInstrumentGuitar7StringTuning[1]) },
        { u8"InstrumentGuitar7StringTuning2",     to_string(Settings::highwayInstrumentGuitar7StringTuning[2]) },
        { u8"InstrumentGuitar7StringTuning3",     to_string(Settings::highwayInstrumentGuitar7StringTuning[3]) },
        { u8"InstrumentGuitar7StringTuning4",     to_string(Settings::highwayInstrumentGuitar7StringTuning[4]) },
        { u8"InstrumentGuitar7StringTuning5",     to_string(Settings::highwayInstrumentGuitar7StringTuning[5]) },
        { u8"InstrumentGuitarFirstWoundString",   to_string(Settings::highwayInstrumentGuitarFirstWoundString) },
        { u8"InstrumentGuitarFretSpacing",        to_string(Settings::highwayInstrumentGuitarFretSpacing) },
        { u8"InstrumentGuitarFretSpacingFactor",  to_string(Settings::highwayInstrumentGuitarFretSpacingFactor) },
        { u8"InstrumentGuitarStringColor0",       hexColor(Settings::highwayInstrumentGuitarStringColor[0]) },
        { u8"InstrumentGuitarStringColor1",       hexColor(Settings::highwayInstrumentGuitarStringColor[1]) },
        { u8"InstrumentGuitarStringColor2",       hexColor(Settings::highwayInstrumentGuitarStringColor[2]) },
        { u8"InstrumentGuitarStringColor3",       hexColor(Settings::highwayInstrumentGuitarStringColor[3]) },
        { u8"InstrumentGuitarStringColor4",       hexColor(Settings::highwayInstrumentGuitarStringColor[4]) },
        { u8"InstrumentGuitarStringColor5",       hexColor(Settings::highwayInstrumentGuitarStringColor[5]) },
        { u8"InstrumentGuitarStringColor6",       hexColor(Settings::highwayInstrumentGuitarStringColor[6]) },
        { u8"InstrumentGuitarStringColor7",       hexColor(Settings::highwayInstrumentGuitarStringColor[7]) },
        { u8"InstrumentGuitarStringSpacing",      to_string(Settings::highwayInstrumentGuitarStringSpacing) },
        { u8"NoteBendCurve",                      to_string(Settings::highwayNoteBendCurve) },
        { u8"NoteBendEndTime",                    to_string(Settings::highwayNoteBendEndTime) },
        { u8"NoteBendHintDistance",               to_string(Settings::highwayNoteBendHintDistance) },
        { u8"NoteBendHintOffset",                 to_string(Settings::highwayNoteBendHintOffset) },
        { u8"NoteBendSpeed",                      to_string(Settings::highwayNoteBendSpeed) },
        { u8"NoteHeight",                         to_string(Settings::highwayNoteHeight) },
        { u8"NoteRotate",                         to_string(Settings::highwayNoteRotate) },
        { u8"NoteRotateEndTime",                  to_string(Settings::highwayNoteRotateEndTime) },
        { u8"NoteRotateSpeed",                    to_string(Settings::highwayNoteRotateSpeed) },
        { u8"NoteShape",                          to_string(to_underlying_(Settings::highwayNoteShape)) },
        { u8"NoteStand",                          to_string(Settings::highwayNoteStand) },
        { u8"NoteStandZero",                      to_string(Settings::highwayNoteStandZero) },
        { u8"NoteSustainCurveSampleDistance",     to_string(Settings::highwayNoteSustainCurveSampleDistance) },
        { u8"NoteSustainTremoloSampleDistance",   to_string(Settings::highwayNoteSustainTremoloSampleDistance) },
        { u8"NoteSustainTremoloShakeStrength",    to_string(Settings::highwayNoteSustainTremoloShakeStrength) },
        { u8"NoteSustainWidth",                   to_string(Settings::highwayNoteSustainWidth) },
        { u8"NoteSustainWidthZero",               to_string(Settings::highwayNoteSustainWidthZero) },
        { u8"NoteSymbolFretMute",                 to_string(to_underlying_(Settings::highwayNoteSymbolFretMute)) },
        { u8"NoteSymbolHammerOn",                 to_string(to_underlying_(Settings::highwayNoteSymbolHammerOn)) },
        { u8"NoteSymbolHarmonic",                 to_string(to_underlying_(Settings::highwayNoteSymbolHarmonic)) },
        { u8"NoteSymbolPinchHarmonic",            to_string(to_underlying_(Settings::highwayNoteSymbolPinchHarmonic)) },
        { u8"NoteSymbolPalmMute",                 to_string(to_underlying_(Settings::highwayNoteSymbolPalmMute)) },
        { u8"NoteSymbolPop",                      to_string(to_underlying_(Settings::highwayNoteSymbolPop)) },
        { u8"NoteSymbolPullOff",                  to_string(to_underlying_(Settings::highwayNoteSymbolPullOff)) },
        { u8"NoteSymbolSlap",                     to_string(to_underlying_(Settings::highwayNoteSymbolSlap)) },
        { u8"NoteSymbolTap",                      to_string(to_underlying_(Settings::highwayNoteSymbolTap)) },
        { u8"NoteWidth",                          to_string(Settings::highwayNoteWidth) },
#ifdef SHR3D_RENDERER_DEVELOPMENT
        { u8"Renderer",                           to_string(to_underlying_(Settings::highwayRenderer)) },
#endif // SHR3D_RENDERER_DEVELOPMENT
        { u8"ReverseStrings",                     to_string(Settings::highwayReverseStrings) },
        { u8"StringFadeUnplayed",                 to_string(Settings::highwayStringFadeUnplayed) },
        { u8"ScrollSpeed",                        to_string(Settings::highwayScrollSpeed) },
        { u8"SustainColor",                       hexColor(Settings::highwaySustainColor) },
#ifdef SHR3D_SFX_CORE_HEXFIN
        { u8"Tuner",                              to_string(Settings::highwayTuner) },
        { u8"TunerColor0",                        hexColor(Settings::highwayTunerColor[0]) },
        { u8"TunerColor1",                        hexColor(Settings::highwayTunerColor[1]) },
        { u8"TunerColor2",                        hexColor(Settings::highwayTunerColor[2]) },
        { u8"TunerColor3",                        hexColor(Settings::highwayTunerColor[3]) },
#endif // SHR3D_SFX_CORE_HEXFIN
        { u8"VUMeter",                            to_string(Settings::highwayVUMeter) },
        { u8"VUMeterColor0",                      hexColor(Settings::highwayVUMeterColor[0]) },
        { u8"VUMeterColor1",                      hexColor(Settings::highwayVUMeterColor[1]) },
        { u8"VUMeterColor2",                      hexColor(Settings::highwayVUMeterColor[2]) },
        { u8"VUMeterColor3",                      hexColor(Settings::highwayVUMeterColor[3]) },
        { u8"VUMeterColor4",                      hexColor(Settings::highwayVUMeterColor[4]) },
        { u8"ViewDistance",                       to_string(Settings::highwayViewDistance) }
      }
    },
    {
      u8"Hud",
      {
        { u8"Lyrics",                             to_string(Settings::hudLyrics) },
        { u8"LyricsColor0",                       hexColor(Settings::hudLyricsColor[0]) },
        { u8"LyricsColor1",                       hexColor(Settings::hudLyricsColor[1]) },
        { u8"LyricsColor2",                       hexColor(Settings::hudLyricsColor[2]) },
        { u8"LyricsScale",                        to_string(Settings::hudLyricsScale) },
        { u8"LyricsX",                            to_string(Settings::hudLyricsX)},
        { u8"LyricsY0",                           to_string(Settings::hudLyricsY[0]) },
        { u8"LyricsY1",                           to_string(Settings::hudLyricsY[1]) },
        { u8"ArrangementSwitch",                     to_string(Settings::hudArrangementSwitch) },
        { u8"ArrangementSwitchColor",                hexColor(Settings::hudArrangementSwitchColor) },
        { u8"ArrangementSwitchScaleX",               to_string(Settings::hudArrangementSwitchScaleX)},
        { u8"ArrangementSwitchScaleY",               to_string(Settings::hudArrangementSwitchScaleY)},
        { u8"ArrangementSwitchX",                    to_string(Settings::hudArrangementSwitchX)},
        { u8"ArrangementSwitchY",                    to_string(Settings::hudArrangementSwitchY)},
#ifdef SHR3D_OPENXR
        { u8"ArrangementSwitchXrScaleX",             to_string(Settings::hudArrangementSwitchXrScaleX) },
        { u8"ArrangementSwitchXrScaleY",             to_string(Settings::hudArrangementSwitchXrScaleY) },
        { u8"ArrangementSwitchXrX",                  to_string(Settings::hudArrangementSwitchXrX) },
        { u8"ArrangementSwitchXrY",                  to_string(Settings::hudArrangementSwitchXrY) },
        { u8"ArrangementSwitchXrZ",                  to_string(Settings::hudArrangementSwitchXrZ) },
#endif // SHR3D_OPENXR
        { u8"NewHighscore",                       to_string(Settings::hudNewHighscore) },
#ifdef SHR3D_RENDERER_DEVELOPMENT
        { u8"Renderer",                           to_string(to_underlying_(Settings::hudRenderer)) },
#endif // SHR3D_RENDERER_DEVELOPMENT
        { u8"Score",                              to_string(Settings::hudScore) },
        { u8"ScoreColor0",                        hexColor(Settings::hudScoreColor[0]) },
        { u8"ScoreColor1",                        hexColor(Settings::hudScoreColor[1]) },
        { u8"ScoreColor2",                        hexColor(Settings::hudScoreColor[2]) },
        { u8"ScoreColor3",                        hexColor(Settings::hudScoreColor[3]) },
        { u8"SongInfo",                           to_string(Settings::hudSongInfo) },
        { u8"SongInfoColor0",                     hexColor(Settings::hudSongInfoColor[0])},
        { u8"SongInfoColor1",                     hexColor(Settings::hudSongInfoColor[1])},
        { u8"SongInfoScale0",                     to_string(Settings::hudSongInfoScale[0])},
        { u8"SongInfoScale1",                     to_string(Settings::hudSongInfoScale[1])},
        { u8"SongInfoX",                          to_string(Settings::hudSongInfoX) },
        { u8"SongInfoY0",                         to_string(Settings::hudSongInfoY[0])},
        { u8"SongInfoY1",                         to_string(Settings::hudSongInfoY[1])},
        { u8"TimelineLevel",                      to_string(Settings::hudTimelineLevel) },
        { u8"TimelineLevelColor0",                hexColor(Settings::hudTimelineLevelColor[0]) },
        { u8"TimelineLevelColor1",                hexColor(Settings::hudTimelineLevelColor[1]) },
        { u8"TimelineLevelColor2",                hexColor(Settings::hudTimelineLevelColor[2]) },
        { u8"TimelineLevelColor3",                hexColor(Settings::hudTimelineLevelColor[3]) },
        { u8"TimelineLevelColor4",                hexColor(Settings::hudTimelineLevelColor[4]) },
        { u8"TimelineLevelColor5",                hexColor(Settings::hudTimelineLevelColor[5]) },
        { u8"TimelineLevelColor6",                hexColor(Settings::hudTimelineLevelColor[6]) },
        { u8"TimelineLevelColor7",                hexColor(Settings::hudTimelineLevelColor[7]) },
        { u8"TimelineLevelFlipY",                 to_string(Settings::hudTimelineLevelFlipY) },
        { u8"TimelineLevelScaleX",                to_string(Settings::hudTimelineLevelScaleX) },
        { u8"TimelineLevelScaleY",                to_string(Settings::hudTimelineLevelScaleY) },
        { u8"TimelineLevelSpacing",               to_string(Settings::hudTimelineLevelSpacing) },
        { u8"TimelineLevelX",                     to_string(Settings::hudTimelineLevelX) },
        { u8"TimelineLevelY",                     to_string(Settings::hudTimelineLevelY) },
#ifdef SHR3D_OPENXR
        { u8"TimelineLevelXrFlipY",               to_string(Settings::hudTimelineLevelXrFlipY) },
        { u8"TimelineLevelXrScaleX",              to_string(Settings::hudTimelineLevelXrScaleX) },
        { u8"TimelineLevelXrScaleY",              to_string(Settings::hudTimelineLevelXrScaleY) },
        { u8"TimelineLevelXrSpacing",             to_string(Settings::hudTimelineLevelXrSpacing) },
        { u8"TimelineLevelXrX",                   to_string(Settings::hudTimelineLevelXrX) },
        { u8"TimelineLevelXrY",                   to_string(Settings::hudTimelineLevelXrY) },
        { u8"TimelineLevelXrZ",                   to_string(Settings::hudTimelineLevelXrZ) },
#endif // SHR3D_OPENXR
#ifdef SHR3D_MUSIC_STRETCHER
        { u8"TimelineMusicStretcher",             to_string(Settings::hudTimelineMusicStretcher)},
        { u8"TimelineMusicStretcherColor0",       hexColor(Settings::hudTimelineMusicStretcherColor[0]) },
        { u8"TimelineMusicStretcherColor1",       hexColor(Settings::hudTimelineMusicStretcherColor[1]) },
        { u8"TimelineMusicStretcherScaleX",       to_string(Settings::hudTimelineMusicStretcherScaleX) },
        { u8"TimelineMusicStretcherScaleY",       to_string(Settings::hudTimelineMusicStretcherScaleY) },
        { u8"TimelineMusicStretcherX",            to_string(Settings::hudTimelineMusicStretcherX) },
        { u8"TimelineMusicStretcherY",            to_string(Settings::hudTimelineMusicStretcherY) },
#ifdef SHR3D_OPENXR
        { u8"TimelineMusicStretcherXrScaleX",     to_string(Settings::hudTimelineMusicStretcherXrScaleX) },
        { u8"TimelineMusicStretcherXrScaleY",     to_string(Settings::hudTimelineMusicStretcherXrScaleY) },
        { u8"TimelineMusicStretcherXrX",          to_string(Settings::hudTimelineMusicStretcherXrX) },
        { u8"TimelineMusicStretcherXrY",          to_string(Settings::hudTimelineMusicStretcherXrY) },
        { u8"TimelineMusicStretcherXrZ",          to_string(Settings::hudTimelineMusicStretcherXrZ) },
#endif // SHR3D_OPENXR
#endif // SHR3D_MUSIC_STRETCHER
        { u8"TimelineQuickRepeaterColor0",        hexColor(Settings::hudTimelineQuickRepeaterColor[0]) },
        { u8"TimelineQuickRepeaterColor1",        hexColor(Settings::hudTimelineQuickRepeaterColor[1]) },
        { u8"TimelineQuickRepeaterFlipY",         to_string(Settings::hudTimelineQuickRepeaterFlipY) },
        { u8"TimelineQuickRepeaterScaleY",        to_string(Settings::hudTimelineQuickRepeaterScaleY) },
        { u8"TimelineQuickRepeaterX",             to_string(Settings::hudTimelineQuickRepeaterX) },
        { u8"TimelineQuickRepeaterY",             to_string(Settings::hudTimelineQuickRepeaterY) },
#ifdef SHR3D_OPENXR
        { u8"TimelineQuickRepeaterXrScaleX",      to_string(Settings::hudTimelineQuickRepeaterXrScaleX) },
        { u8"TimelineQuickRepeaterXrScaleY",      to_string(Settings::hudTimelineQuickRepeaterXrScaleY) },
        { u8"TimelineQuickRepeaterXrX",           to_string(Settings::hudTimelineQuickRepeaterXrX) },
        { u8"TimelineQuickRepeaterXrY",           to_string(Settings::hudTimelineQuickRepeaterXrY) },
        { u8"TimelineQuickRepeaterXrZ",           to_string(Settings::hudTimelineQuickRepeaterXrZ) },
#endif // SHR3D_OPENXR
        { u8"TimelineTone",                       to_string(Settings::hudTimelineTone)},
        { u8"TimelineToneColor0",                 hexColor(Settings::hudTimelineToneColor[0]) },
        { u8"TimelineToneColor1",                 hexColor(Settings::hudTimelineToneColor[1]) },
        { u8"TimelineToneColor2",                 hexColor(Settings::hudTimelineToneColor[2]) },
        { u8"TimelineToneColor3",                 hexColor(Settings::hudTimelineToneColor[3]) },
        { u8"TimelineToneColor4",                 hexColor(Settings::hudTimelineToneColor[4]) },
        { u8"TimelineToneColor5",                 hexColor(Settings::hudTimelineToneColor[5]) },
        { u8"TimelineToneColor6",                 hexColor(Settings::hudTimelineToneColor[6]) },
        { u8"TimelineToneColor7",                 hexColor(Settings::hudTimelineToneColor[7]) },
        { u8"TimelineToneColor8",                 hexColor(Settings::hudTimelineToneColor[8]) },
        { u8"TimelineToneColor9",                 hexColor(Settings::hudTimelineToneColor[9]) },
        { u8"TimelineToneColor10",                hexColor(Settings::hudTimelineToneColor[10]) },
        { u8"TimelineToneScaleX",                 to_string(Settings::hudTimelineToneScaleX) },
        { u8"TimelineToneScaleY",                 to_string(Settings::hudTimelineToneScaleY) },
        { u8"TimelineToneX",                      to_string(Settings::hudTimelineToneX) },
        { u8"TimelineToneY",                      to_string(Settings::hudTimelineToneY) },
#ifdef SHR3D_OPENXR
        { u8"TimelineToneXrScaleX",               to_string(Settings::hudTimelineToneXrScaleX) },
        { u8"TimelineToneXrScaleY",               to_string(Settings::hudTimelineToneXrScaleY) },
        { u8"TimelineToneXrX",                    to_string(Settings::hudTimelineToneXrX) },
        { u8"TimelineToneXrY",                    to_string(Settings::hudTimelineToneXrY) },
        { u8"TimelineToneXrZ",                    to_string(Settings::hudTimelineToneXrZ) },
#endif // SHR3D_OPENXR
        { u8"ToneSwitch",                         to_string(Settings::hudToneSwitch) },
        { u8"ToneSwitchTimer",                    to_string(Settings::hudToneSwitchTimer) },
        { u8"ToneSwitchColor",                    hexColor(Settings::hudToneSwitchColor) },
        { u8"ToneSwitchHintColor",                hexColor(Settings::hudToneSwitchHintColor) },
        { u8"ToneSwitchScale0",                   to_string(Settings::hudToneSwitchScale[0])},
        { u8"ToneSwitchScale1",                   to_string(Settings::hudToneSwitchScale[1])},
        { u8"ToneSwitchX",                        to_string(Settings::hudToneSwitchX) },
        { u8"ToneSwitchY0",                       to_string(Settings::hudToneSwitchY[0])},
        { u8"ToneSwitchY1",                       to_string(Settings::hudToneSwitchY[1])},
#ifdef SHR3D_OPENXR
        { u8"ToneSwitchXrScale0",                 to_string(Settings::hudToneSwitchXrScale[0])},
        { u8"ToneSwitchXrScale1",                 to_string(Settings::hudToneSwitchXrScale[1])},
        { u8"ToneSwitchXrX",                      to_string(Settings::hudToneSwitchXrX) },
        { u8"ToneSwitchXrY0",                     to_string(Settings::hudToneSwitchXrY[0])},
        { u8"ToneSwitchXrY1",                     to_string(Settings::hudToneSwitchXrY[1])},
        { u8"ToneSwitchXrZ",                      to_string(Settings::hudToneSwitchXrZ) },
#endif // SHR3D_OPENXR
        { u8"Watermark",                          to_string(Settings::hudWatermark) },
        { u8"WatermarkColor",                     hexColor(Settings::hudWatermarkColor) },
#ifdef SHR3D_OPENXR
        { u8"WatermarkXrX",                       to_string(Settings::hudWatermarkXrX) },
        { u8"WatermarkXrY",                       to_string(Settings::hudWatermarkXrY) },
        { u8"WatermarkXrZ",                       to_string(Settings::hudWatermarkXrZ) }
#endif // SHR3D_OPENXR
      }
    },
    {
      u8"Metronome",
      {
        { u8"Enabled",                            to_string(Settings::metronomeEnabled) },
        { u8"Volume",                             to_string(Settings::metronomeVolume) },
        { u8"Decay",                              to_string(Settings::metronomeDecay) },
        { u8"Frequency0",                         to_string(Settings::metronomeFrequency0) },
        { u8"Frequency1",                         to_string(Settings::metronomeFrequency1) },
        { u8"ClickLength",                        to_string(Settings::metronomeClickLength) },
        { u8"Side",                               to_string(to_underlying_(Settings::metronomeSide)) }
      }
    },
    {
      u8"Midi",
      {
        { u8"FineValueFactor",                    to_string(Settings::midiFineValueFactor) },
        { u8"AutoConnectDevices",                 Settings::midiAutoConnectDevices }
      }
    },
    {
      u8"Paths",
      {
        { u8"StatsIni", Settings::pathStatsIni },
        { u8"TonesIni", Settings::pathTonesIni },
        { u8"Backup", Settings::pathBackup },
#ifdef SHR3D_SHRED_OR_PSARC
        { u8"Cache", Settings::pathCache },
#endif // SHR3D_SHRED_OR_PSARC
#ifdef SHR3D_SFX_PLUGIN_CLAP
        { u8"Clap", Settings::pathClap },
#endif // SHR3D_SFX_PLUGIN_CLAP
#ifdef SHR3D_ENVIRONMENT_MILK
        { u8"Milk", Settings::pathMilk },
#endif // SHR3D_ENVIRONMENT_MILK
#ifdef SHR3D_SFX_CORE_NEURALAMPMODELER
        { u8"Nam", Settings::pathNam },
#endif // SHR3D_SFX_CORE_NEURALAMPMODELER
#ifdef SHR3D_PSARC
        { u8"Psarc", Settings::pathPsarc },
#endif // SHR3D_PSARC
#ifdef SHR3D_SHRED
        { u8"Shred", Settings::pathShred },
#endif // SHR3D_SHRED
#ifdef SHR3D_RECORDER
        { u8"Recorder", Settings::pathRecorder },
#endif // SHR3D_RECORDER
#ifdef SHR3D_SFX_PLUGIN_VST
        { u8"Vst", Settings::pathVst },
#endif // SHR3D_SFX_PLUGIN_VST
#ifdef SHR3D_SFX_PLUGIN_VST3
        { u8"Vst3", Settings::pathVst3 },
#endif // SHR3D_SFX_PLUGIN_VST3
#ifdef SHR3D_ENVIRONMENT_SKYBOX
        { u8"Skybox", Settings::pathSkybox },
#endif // SHR3D_ENVIRONMENT_SKYBOX
#ifdef SHR3D_ENVIRONMENT_STAGE
        { u8"Stage", Settings::pathStage }
#endif // SHR3D_ENVIRONMENT_STAGE
      }
    },
#ifdef SHR3D_SPOTIFY
    {
      u8"Spotify",
      {
        { u8"ClientId",     Settings::spotifyClientId },
        { u8"ClientSecret", Settings::spotifyClientSecret },
        { u8"RedirectUri",  Settings::spotifyRedirectUri }
      }
    },
#endif // SHR3D_SPOTIFY
    {
      u8"Tuner",
      {
        { u8"NoteDetectionSource", to_string(to_underlying_(Settings::tunerNoteDetectionSource)) },
#ifdef SHR3D_SFX
        { u8"TunerPlugin",         Settings::tunerPlugin },
        { u8"MidiPlugin",          Settings::tunerMidiPlugin },
#endif // SHR3D_SFX
#ifdef SHR3D_SFX_CORE_HEXFIN
        { u8"HexfinOnsetThreshold",   to_string(Settings::tunerHexfinOnsetThreshold) },
        { u8"HexfinReleaseThreshold", to_string(Settings::tunerHexfinReleaseThreshold) }
#endif // SHR3D_SFX_CORE_HEXFIN
      }
    },
    {
      u8"Ui",
      {
        { u8"Scale",        to_string(Settings::uiScale) },
#ifdef SHR3D_OPENXR
        { u8"XrZ",        to_string(Settings::uiXrZ) },
#endif // SHR3D_OPENXR
#ifdef SHR3D_CUSTOM_CURSOR
        { u8"CursorCustom", to_string(Settings::uiCursorCustom) },
        { u8"CursorSize",   to_string(Settings::uiCursorSize) },
#endif // SHR3D_CUSTOM_CURSOR
        { u8"Color0",       hexColor(Settings::uiColor[0]) },
        { u8"Color1",       hexColor(Settings::uiColor[1]) },
        { u8"Color2",       hexColor(Settings::uiColor[2]) },
        { u8"Color3",       hexColor(Settings::uiColor[3]) },
        { u8"Color4",       hexColor(Settings::uiColor[4]) },
        { u8"Color5",       hexColor(Settings::uiColor[5]) },
        { u8"Color6",       hexColor(Settings::uiColor[6]) },
        { u8"Color7",       hexColor(Settings::uiColor[7]) },
        { u8"Color8",       hexColor(Settings::uiColor[8]) },
        { u8"Color9",       hexColor(Settings::uiColor[9]) },
        { u8"Color10",      hexColor(Settings::uiColor[10]) },
        { u8"Color11",      hexColor(Settings::uiColor[11]) },
        { u8"Color12",      hexColor(Settings::uiColor[12]) },
        { u8"Color13",      hexColor(Settings::uiColor[13]) },
        { u8"Color14",      hexColor(Settings::uiColor[14]) },
        { u8"Color15",      hexColor(Settings::uiColor[15]) },
        { u8"Color16",      hexColor(Settings::uiColor[16]) },
        { u8"Color17",      hexColor(Settings::uiColor[17]) },
        { u8"Color18",      hexColor(Settings::uiColor[18]) },
        { u8"Color19",      hexColor(Settings::uiColor[19]) },
        { u8"Color20",      hexColor(Settings::uiColor[20]) },
        { u8"Color21",      hexColor(Settings::uiColor[21]) },
        { u8"Color22",      hexColor(Settings::uiColor[22]) },
        { u8"Color23",      hexColor(Settings::uiColor[23]) },
        { u8"Color24",      hexColor(Settings::uiColor[24]) },
        { u8"Color25",      hexColor(Settings::uiColor[25]) },
        { u8"Color26",      hexColor(Settings::uiColor[26]) },
        { u8"Color27",      hexColor(Settings::uiColor[27]) },
        // additional custom colors:
        { u8"Color28",      hexColor(Settings::uiColor[28]) },
        { u8"Color29",      hexColor(Settings::uiColor[29]) },
      }
    },
#ifdef SHR3D_OPENXR
    {
      u8"XR",
      {
#ifdef SHR3D_OPENXR_PCVR
        { u8"Enabled",              to_string(Settings::xrEnabled) },
#endif // SHR3D_OPENXR_PCVR
#ifdef SHR3D_OPENXR_CONTROLLER_PICO4_AND_QUEST3
        { u8"Controller",           to_string(to_underlying_(Settings::xrController)) },
#endif // SHR3D_OPENXR_CONTROLLER_PICO4_AND_QUEST3
        { u8"ControllerColor0",     hexColor(Settings::xrControllerColor[0]) },
        { u8"ControllerColor1",     hexColor(Settings::xrControllerColor[1]) },
        { u8"CursorColor0",         hexColor(Settings::xrCursorColor[0]) },
        { u8"CursorColor1",         hexColor(Settings::xrCursorColor[1]) },
        { u8"PointerColor",         hexColor(Settings::xrPointerColor) },
        //{ u8"UiCircularProjection", to_string(Settings::xrUiCircularProjection) },
      }
    }
#endif // SHR3D_OPENXR
  };

#ifdef SHR3D_MIDI
  for (i32 i = 0; i < ARRAY_SIZE(Const::midiBindingsNames); ++i)
  {
    if (Settings::midiBinding[i] == 0xFF)
      serializedSettings[u8"Midi"].insert({ std::u8string(u8"Binding") + Const::midiBindingsNames[i], u8"" });
    else
      serializedSettings[u8"Midi"].insert({ std::u8string(u8"Binding") + Const::midiBindingsNames[i], to_string(Settings::midiBinding[i]) + u8';' + to_string(to_underlying_(Global::midiNoteMode[Settings::midiBinding[i]])) });
  }
#endif // SHR3D_MIDI

#ifdef SHR3D_AUDIO_SUPERPOWERED
  {
    const i32 inputCounts = Settings::audioSuperpoweredInputVolume.size();
    for (i32 i = 0; i < inputCounts; ++i)
    {
      const std::u8string mute = std::u8string(u8"SuperpoweredInput") + to_string(i) + u8"Mute";
      serializedSettings[u8"Audio"][mute] = to_string(Settings::audioSuperpoweredInputMutes[i]);
      const std::u8string volume = std::u8string(u8"SuperpoweredInput") + to_string(i) + u8"Volume";
      serializedSettings[u8"Audio"][volume] = to_string(Settings::audioSuperpoweredInputVolume[i]);
    }
    const i32 outputCounts = Settings::audioSuperpoweredOutputVolume.size();
    for (i32 i = 0; i < inputCounts; ++i)
    {
      const std::u8string mute = std::u8string(u8"SuperpoweredOutput") + to_string(i) + u8"Mute";
      serializedSettings[u8"Audio"][mute] = to_string(Settings::audioSuperpoweredOutputMutes[i]);
      const std::u8string volume = std::u8string(u8"SuperpoweredOutput") + to_string(i) + u8"Volume";
      serializedSettings[u8"Audio"][volume] = to_string(Settings::audioSuperpoweredOutputVolume[i]);
    }
  }
#endif // SHR3D_AUDIO_SUPERPOWERED

#ifdef SHR3D_ENVIRONMENT_MILK
  if (Global::milkActivePresets.size() >= 1)
  {
    serializedSettings[u8"Environment"][u8"MilkActivePresets"] += Global::milkPresetNames[Global::milkActivePresets[0]];
    for (i32 i = 1; i < Global::milkActivePresets.size(); ++i)
    {
      serializedSettings[u8"Environment"][u8"MilkActivePresets"] += u8'|' + Global::milkPresetNames[Global::milkActivePresets[i]];
    }
  }
  else
  {
    serializedSettings[u8"Environment"][u8"MilkActivePresets"] = u8"";
  }
#endif // SHR3D_ENVIRONMENT_MILK

#ifdef SHR3D_MIDI
  if (Global::tunerMidiDevice != 0)
  {
    serializedSettings[u8"Tuner"][u8"MidiDevice"] = Global::midiDeviceNames[Global::tunerMidiDevice];
  }
#endif // SHR3D_MIDI

  if (Global::tunerMidiPlugin.system != SfxSystem::empty)
  {
    std::u8string& tunerMidiPlugin = serializedSettings[u8"Tuner"][u8"MidiPlugin"];

    // remove old parameters
    const u64 splitPos = tunerMidiPlugin.find_first_of(',');
    if (splitPos != std::string::npos)
      tunerMidiPlugin.resize(splitPos);

    // add new paramters
    const std::u8string parameters = Sfx::saveParameters(Global::tunerMidiPlugin, 0);
    const std::u8string parametersBase64 = Base64::encode(reinterpret_cast<const u8*>(parameters.data()), parameters.size());

    tunerMidiPlugin += u8',' + parametersBase64;
  }

#ifdef SHR3D_ENVIRONMENT_STAGE
  {
    std::map<std::u8string, std::u8string>& environment = serializedSettings[u8"Environment"];

    environment.insert({ u8"Stage", Settings::environmentStage });
#ifndef PLATFORM_OPENXR_ANDROID
    environment.insert({ u8"StagePlayerHeight", to_string(Settings::environmentStagePlayerHeight) });
#endif // PLATFORM_OPENXR_ANDROID
    environment.insert({ u8"StageRotation", to_string(Settings::environmentStageRotation) });
    environment.insert({ u8"StageScale", to_string(Settings::environmentStageScale) });
    environment.insert({ u8"StageX", to_string(Settings::environmentStageX) });
    environment.insert({ u8"StageY", to_string(Settings::environmentStageY) });
    environment.insert({ u8"StageZ", to_string(Settings::environmentStageZ) });
  }
#endif // SHR3D_ENVIRONMENT_STAGE

  return serializedSettings;
}

static void deserializeSettings(const std::map<std::u8string, std::map<std::u8string, std::u8string>>& serializedSettings)
{
  if (serializedSettings.contains(u8"Application"))
  {
    const auto& application = serializedSettings.at(u8"Application");
    if (application.contains(u8"Instrument"))
      Settings::applicationInstrument = Instrument(atoi2(application.at(u8"Instrument").c_str()));
    if (application.contains(u8"BackupMode"))
      Settings::applicationBackupMode = BackupMode(atoi2(application.at(u8"BackupMode").c_str()));
    if (application.contains(u8"EndOfSong"))
      Settings::applicationEndOfSong = EndOfSong(atoi2(application.at(u8"EndOfSong").c_str()));
    if (application.contains(u8"ToneSwitch"))
      Settings::applicationToneSwitch = bool(atoi2(application.at(u8"ToneSwitch").c_str()));
  }
  if (serializedSettings.contains(u8"Audio"))
  {
    const auto& audio = serializedSettings.at(u8"Audio");
    if (audio.contains(u8"System"))
      Settings::audioSystem = AudioSystem(atoi2(audio.at(u8"System").c_str()));
    if (audio.contains(u8"InstrumentVolume"))
      Settings::audioEffectVolume = f32(atof2(audio.at(u8"InstrumentVolume").c_str()));
    if (audio.contains(u8"InstrumentVolumeCoop"))
      Settings::audioEffectVolumeCoop = f32(atof2(audio.at(u8"InstrumentVolumeCoop").c_str()));
    if (audio.contains(u8"MusicVolume"))
      Settings::audioMusicVolume = f32(atof2(audio.at(u8"MusicVolume").c_str()));
#ifdef SHR3D_AUDIO_AAUDIO
    if (audio.contains(u8"AAudioBlockSize"))
      Settings::audioAAudioBlockSize = atoi2(audio.at(u8"AAudioBlockSize").c_str());
    if (audio.contains(u8"AAudioChannelInput"))
      Settings::audioAAudioChannelInput = atoi2(audio.at(u8"AAudioChannelInput").c_str());
#ifdef SHR3D_COOP
    if (audio.contains(u8"AAudioChannelInputCoop"))
      Settings::audioAAudioChannelInputCoop = atoi2(audio.at(u8"AAudioChannelInputCoop").c_str());
#endif // SHR3D_COOP
    if (audio.contains(u8"AAudioDeviceInput"))
      Settings::audioAAudioDeviceInput = TODOFIX(audio.at(u8"AAudioDeviceInput"));
    if (audio.contains(u8"AAudioDeviceOutput"))
      Settings::audioAAudioDeviceOutput = TODOFIX(audio.at(u8"AAudioDeviceOutput"));
    if (audio.contains(u8"AAudioChannelInput"))
      Settings::audioAAudioChannelInput = atoi2(audio.at(u8"AAudioChannelInput").c_str());
#ifdef SHR3D_COOP
    if (audio.contains(u8"AAudioChannelInputCoop"))
      Settings::audioAAudioChannelInputCoop = atoi2(audio.at(u8"AAudioChannelInputCoop").c_str());
#endif // SHR3D_COOP
    if (audio.contains(u8"AAudioSampleRate"))
      Settings::audioAAudioSampleRate = atoi2(audio.at(u8"AAudioSampleRate").c_str());
    if (audio.contains(u8"AAudioExclusiveMode"))
      Settings::audioAAudioExclusiveMode = bool(atoi2(audio.at(u8"AAudioExclusiveMode").c_str()));
    if (audio.contains(u8"AAudioPerformanceMode"))
      Settings::audioAAudioPerformanceMode = AAudioPerformanceMode(atoi2(audio.at(u8"AAudioPerformanceMode").c_str()));
#endif // SHR3D_AUDIO_AAUDIO
#ifdef SHR3D_AUDIO_ASIO
    if (audio.contains(u8"AsioDevice"))
      Settings::audioAsioDevice = TODOFIX(audio.at(u8"AsioDevice"));
    if (audio.contains(u8"AsioBlockSize"))
      Settings::audioAsioBlockSize = atoi2(audio.at(u8"AsioBlockSize").c_str());
    if (audio.contains(u8"AsioSampleRate"))
      Settings::audioAsioSampleRate = atoi2(audio.at(u8"AsioSampleRate").c_str());
    if (audio.contains(u8"AsioChannelOutput"))
      Settings::audioAsioChannelOutput = atoi2(audio.at(u8"AsioChannelOutput").c_str());
    if (audio.contains(u8"AsioChannelInput0"))
      Settings::audioAsioChannelInput0 = atoi2(audio.at(u8"AsioChannelInput0").c_str());
    if (audio.contains(u8"AsioChannelInput1"))
      Settings::audioAsioChannelInput1 = atoi2(audio.at(u8"AsioChannelInput1").c_str());
#ifdef SHR3D_COOP
    if (audio.contains(u8"AsioChannelInputCoop0"))
      Settings::audioAsioChannelInputCoop0 = atoi2(audio.at(u8"AsioChannelInputCoop0").c_str());
    if (audio.contains(u8"AsioChannelInputCoop1"))
      Settings::audioAsioChannelInputCoop1 = atoi2(audio.at(u8"AsioChannelInputCoop1").c_str());
#endif // SHR3D_COOP
#ifdef SHR3D_SFX_CORE_HEXFIN_DIVIDED
#ifdef SHR3D_AUDIO_ASIO_SECOND_DEVICE_FOR_TUNER_DIVIDED
    if (audio.contains(u8"AsioSecondDeviceForTunerDivided"))
      Settings::audioAsioSecondDeviceForTunerDivided = TODOFIX(audio.at(u8"AsioSecondDeviceForTunerDivided"));
#endif // SHR3D_AUDIO_ASIO_SECOND_DEVICE_FOR_TUNER_DIVIDED
    if (audio.contains(u8"AsioDividedPickup"))
      Settings::audioAsioDividedPickup = bool(atoi2(audio.at(u8"AsioDividedPickup").c_str()));
    if (audio.contains(u8"AsioDividedPickupAsMainInput"))
      Settings::audioAsioDividedPickupAsMainInput = bool(atoi2(audio.at(u8"AsioDividedPickupAsMainInput").c_str()));
    if (audio.contains(u8"AsioDividedPickupChannelString0"))
      Settings::audioAsioDividedPickupChannelString0 = atoi2(audio.at(u8"AsioDividedPickupChannelString0").c_str());
    if (audio.contains(u8"AsioDividedPickupChannelString1"))
      Settings::audioAsioDividedPickupChannelString1 = atoi2(audio.at(u8"AsioDividedPickupChannelString1").c_str());
    if (audio.contains(u8"AsioDividedPickupChannelString2"))
      Settings::audioAsioDividedPickupChannelString2 = atoi2(audio.at(u8"AsioDividedPickupChannelString2").c_str());
    if (audio.contains(u8"AsioDividedPickupChannelString3"))
      Settings::audioAsioDividedPickupChannelString3 = atoi2(audio.at(u8"AsioDividedPickupChannelString3").c_str());
    if (audio.contains(u8"AsioDividedPickupChannelString4"))
      Settings::audioAsioDividedPickupChannelString4 = atoi2(audio.at(u8"AsioDividedPickupChannelString4").c_str());
    if (audio.contains(u8"AsioDividedPickupChannelString5"))
      Settings::audioAsioDividedPickupChannelString5 = atoi2(audio.at(u8"AsioDividedPickupChannelString5").c_str());
#endif // SHR3D_SFX_CORE_HEXFIN_DIVIDED
#endif // SHR3D_AUDIO_ASIO
#ifdef SHR3D_AUDIO_JACK
    if (audio.contains(u8"JackInputDevice0"))
      Settings::audioJackInputDevice0 = TODOFIX(audio.at(u8"JackInputDevice0"));
    if (audio.contains(u8"JackInputDevice1"))
      Settings::audioJackInputDevice1 = TODOFIX(audio.at(u8"JackInputDevice1"));
    if (audio.contains(u8"JackOutputDevice0"))
      Settings::audioJackOutputDevice0 = TODOFIX(audio.at(u8"JackOutputDevice0"));
    if (audio.contains(u8"JackOutputDevice1"))
      Settings::audioJackOutputDevice1 = TODOFIX(audio.at(u8"JackOutputDevice1"));
#ifdef SHR3D_COOP
    if (audio.contains(u8"JackInputDeviceCoop0"))
      Settings::audioJackInputDeviceCoop0 = TODOFIX(audio.at(u8"JackInputDeviceCoop0"));
    if (audio.contains(u8"JackInputDeviceCoop1"))
      Settings::audioJackInputDeviceCoop1 = TODOFIX(audio.at(u8"JackInputDeviceCoop1"));
#endif // SHR3D_COOP
#ifdef SHR3D_SFX_CORE_HEXFIN_DIVIDED
    if (audio.contains(u8"JackDividedPickup"))
      Settings::audioJackDividedPickup = bool(atoi2(audio.at(u8"JackDividedPickup").c_str()));
    if (audio.contains(u8"JackDividedPickupAsMainInput"))
      Settings::audioJackDividedPickupAsMainInput = bool(atoi2(audio.at(u8"JackDividedPickupAsMainInput").c_str()));
    if (audio.contains(u8"JackDividedPickupChannelString0"))
      Settings::audioJackDividedPickupChannelString0 = TODOFIX(audio.at(u8"JackDividedPickupChannelString0"));
    if (audio.contains(u8"JackDividedPickupChannelString1"))
      Settings::audioJackDividedPickupChannelString1 = TODOFIX(audio.at(u8"JackDividedPickupChannelString1"));
    if (audio.contains(u8"JackDividedPickupChannelString2"))
      Settings::audioJackDividedPickupChannelString2 = TODOFIX(audio.at(u8"JackDividedPickupChannelString2"));
    if (audio.contains(u8"JackDividedPickupChannelString3"))
      Settings::audioJackDividedPickupChannelString3 = TODOFIX(audio.at(u8"JackDividedPickupChannelString3"));
    if (audio.contains(u8"JackDividedPickupChannelString4"))
      Settings::audioJackDividedPickupChannelString4 = TODOFIX(audio.at(u8"JackDividedPickupChannelString4"));
    if (audio.contains(u8"JackDividedPickupChannelString5"))
      Settings::audioJackDividedPickupChannelString5 = TODOFIX(audio.at(u8"JackDividedPickupChannelString5"));
#endif // SHR3D_SFX_CORE_HEXFIN_DIVIDED
#endif // SHR3D_AUDIO_JACK
#ifdef SHR3D_AUDIO_PIPEWIRE
    if (audio.contains(u8"PipewireInputDevice0"))
      Settings::audioPipewireInputDevice0 = TODOFIX(audio.at(u8"PipewireInputDevice0"));
    if (audio.contains(u8"PipewireInputDevice1"))
      Settings::audioPipewireInputDevice1 = TODOFIX(audio.at(u8"PipewireInputDevice1"));
    if (audio.contains(u8"PipewireOutputDevice0"))
      Settings::audioPipewireOutputDevice0 = TODOFIX(audio.at(u8"PipewireOutputDevice0"));
    if (audio.contains(u8"PipewireOutputDevice1"))
      Settings::audioPipewireOutputDevice1 = TODOFIX(audio.at(u8"PipewireOutputDevice1"));
#ifdef SHR3D_COOP
    if (audio.contains(u8"PipewireInputDeviceCoop0"))
      Settings::audioPipewireInputDeviceCoop0 = TODOFIX(audio.at(u8"PipewireInputDeviceCoop0"));
    if (audio.contains(u8"PipewireInputDeviceCoop1"))
      Settings::audioPipewireInputDeviceCoop1 = TODOFIX(audio.at(u8"PipewireInputDeviceCoop1"));
#endif // SHR3D_COOP
#ifdef SHR3D_SFX_CORE_HEXFIN_DIVIDED
    if (audio.contains(u8"PipewireDividedPickup"))
      Settings::audioPipewireDividedPickup = bool(atoi2(audio.at(u8"PipewireDividedPickup").c_str()));
    if (audio.contains(u8"PipewireDividedPickupAsMainInput"))
      Settings::audioPipewireDividedPickupAsMainInput = bool(atoi2(audio.at(u8"PipewireDividedPickupAsMainInput").c_str()));
    if (audio.contains(u8"PipewireDividedPickupChannelString0"))
      Settings::audioPipewireDividedPickupChannelString0 = TODOFIX(audio.at(u8"PipewireDividedPickupChannelString0"));
    if (audio.contains(u8"PipewireDividedPickupChannelString1"))
      Settings::audioPipewireDividedPickupChannelString1 = TODOFIX(audio.at(u8"PipewireDividedPickupChannelString1"));
    if (audio.contains(u8"PipewireDividedPickupChannelString2"))
      Settings::audioPipewireDividedPickupChannelString2 = TODOFIX(audio.at(u8"PipewireDividedPickupChannelString2"));
    if (audio.contains(u8"PipewireDividedPickupChannelString3"))
      Settings::audioPipewireDividedPickupChannelString3 = TODOFIX(audio.at(u8"PipewireDividedPickupChannelString3"));
    if (audio.contains(u8"PipewireDividedPickupChannelString4"))
      Settings::audioPipewireDividedPickupChannelString4 = TODOFIX(audio.at(u8"PipewireDividedPickupChannelString4"));
    if (audio.contains(u8"PipewireDividedPickupChannelString5"))
      Settings::audioPipewireDividedPickupChannelString5 = TODOFIX(audio.at(u8"PipewireDividedPickupChannelString5"));
#endif // SHR3D_SFX_CORE_HEXFIN_DIVIDED
#endif // SHR3D_AUDIO_PIPEWIRE
#ifdef SHR3D_AUDIO_SDL
    if (audio.contains(u8"SdlBlockSize"))
      Settings::audioSdlBlockSize = atoi2(audio.at(u8"SdlBlockSize").c_str());
    if (audio.contains(u8"SdlChannelInput"))
      Settings::audioSdlChannelInput = atoi2(audio.at(u8"SdlChannelInput").c_str());
#ifdef SHR3D_COOP
    if (audio.contains(u8"SdlChannelInputCoop"))
      Settings::audioSdlChannelInputCoop = atoi2(audio.at(u8"SdlChannelInputCoop").c_str());
#endif // SHR3D_COOP
    if (audio.contains(u8"SdlDeviceInput"))
      Settings::audioSdlDeviceInput = TODOFIX(audio.at(u8"SdlDeviceInput"));
    if (audio.contains(u8"SdlDeviceOutput"))
      Settings::audioSdlDeviceOutput = TODOFIX(audio.at(u8"SdlDeviceOutput"));
    if (audio.contains(u8"SdlSampleRate"))
      Settings::audioSdlSampleRate = atoi2(audio.at(u8"SdlSampleRate").c_str());
#endif // SHR3D_AUDIO_SDL
#ifdef SHR3D_AUDIO_SUPERPOWERED
    if (audio.contains(u8"SuperpoweredBlockSize"))
      Settings::audioSuperpoweredBlockSize = atoi2(audio.at(u8"SuperpoweredBlockSize").c_str());
    if (audio.contains(u8"SuperpoweredCofiguration"))
      Settings::audioSuperpoweredCofiguration = audio.at(u8"SuperpoweredCofiguration");
    if (audio.contains(u8"SuperpoweredChannelInput"))
      Settings::audioSuperpoweredChannelInput = atoi2(audio.at(u8"SuperpoweredChannelInput").c_str());
    if (audio.contains(u8"SuperpoweredChannelOutput"))
      Settings::audioSuperpoweredChannelOutput = atoi2(audio.at(u8"SuperpoweredChannelOutput").c_str());
    if (audio.contains(u8"SuperpoweredDeviceInput"))
      Settings::audioSuperpoweredDeviceInput = audio.at(u8"SuperpoweredDeviceInput");
    if (audio.contains(u8"SuperpoweredDeviceOutput"))
      Settings::audioSuperpoweredDeviceOutput = audio.at(u8"SuperpoweredDeviceOutput");
    if (audio.contains(u8"SuperpoweredSustainedPerformanceMode"))
      Settings::audioSuperpoweredSustainedPerformanceMode = bool(atoi2(audio.at(u8"SuperpoweredSustainedPerformanceMode").c_str()));
    if (audio.contains(u8"SuperpoweredInputPathName"))
      Settings::audioSuperpoweredInputPathName = audio.at(u8"SuperpoweredInputPathName");
    if (audio.contains(u8"SuperpoweredOutputPathName"))
      Settings::audioSuperpoweredOutputPathName = audio.at(u8"SuperpoweredOutputPathName");
#ifdef SHR3D_SFX_CORE_HEXFIN_DIVIDED
    if (audio.contains(u8"SuperpoweredDividedPickup"))
      Settings::audioSuperpoweredDividedPickup = bool(atoi2(audio.at(u8"SuperpoweredDividedPickup").c_str()));;
    if (audio.contains(u8"SuperpoweredDividedPickupChannelString0"))
      Settings::audioSuperpoweredDividedPickupChannelString0 = atoi2(audio.at(u8"SuperpoweredDividedPickupChannelString0").c_str());
    if (audio.contains(u8"SuperpoweredDividedPickupChannelString1"))
      Settings::audioSuperpoweredDividedPickupChannelString1 = atoi2(audio.at(u8"SuperpoweredDividedPickupChannelString1").c_str());
    if (audio.contains(u8"SuperpoweredDividedPickupChannelString2"))
      Settings::audioSuperpoweredDividedPickupChannelString2 = atoi2(audio.at(u8"SuperpoweredDividedPickupChannelString2").c_str());
    if (audio.contains(u8"SuperpoweredDividedPickupChannelString3"))
      Settings::audioSuperpoweredDividedPickupChannelString3 = atoi2(audio.at(u8"SuperpoweredDividedPickupChannelString3").c_str());
    if (audio.contains(u8"SuperpoweredDividedPickupChannelString4"))
      Settings::audioSuperpoweredDividedPickupChannelString4 = atoi2(audio.at(u8"SuperpoweredDividedPickupChannelString4").c_str());
    if (audio.contains(u8"SuperpoweredDividedPickupChannelString5"))
      Settings::audioSuperpoweredDividedPickupChannelString5 = atoi2(audio.at(u8"SuperpoweredDividedPickupChannelString5").c_str());
#endif // SHR3D_SFX_CORE_HEXFIN_DIVIDED
#endif // SHR3D_AUDIO_SUPERPOWERED
#ifdef SHR3D_AUDIO_WASAPI
    if (audio.contains(u8"WasapiBlockSize"))
      Settings::audioWasapiBlockSize = atoi2(audio.at(u8"WasapiBlockSize").c_str());
    if (audio.contains(u8"WasapiChannelInput0"))
      Settings::audioWasapiChannelInput0 = atoi2(audio.at(u8"WasapiChannelInput0").c_str());
#ifdef SHR3D_COOP
    if (audio.contains(u8"WasapiChannelInput1"))
      Settings::audioWasapiChannelInput1 = atoi2(audio.at(u8"WasapiChannelInput1").c_str());
#endif // SHR3D_COOP
    if (audio.contains(u8"WasapiDeviceInput"))
      Settings::audioWasapiDeviceInput = TODOFIX(audio.at(u8"WasapiDeviceInput"));
    if (audio.contains(u8"WasapiDeviceOutput"))
      Settings::audioWasapiDeviceOutput = TODOFIX(audio.at(u8"WasapiDeviceOutput"));
    if (audio.contains(u8"WasapiSampleRate"))
      Settings::audioWasapiSampleRate = atoi2(audio.at(u8"WasapiSampleRate").c_str());
    if (audio.contains(u8"WasapiExclusiveMode"))
      Settings::audioWasapiExclusiveMode = bool(atoi2(audio.at(u8"WasapiExclusiveMode").c_str()));
#endif // SHR3D_AUDIO_WASAPI
#ifdef SHR3D_AUDIO_WEBAUDIO
    if (audio.contains(u8"WebAudioChannelInput0"))
      Settings::audioWebAudioChannelInput0 = atoi2(audio.at(u8"WebAudioChannelInput0").c_str());
    if (audio.contains(u8"WebAudioSampleRate"))
      Settings::audioWebAudioSampleRate = atoi2(audio.at(u8"WebAudioSampleRate").c_str());
#endif // SHR3D_AUDIO_WEBAUDIO
  }
  if (serializedSettings.contains(u8"Environment"))
  {
    const auto& environment = serializedSettings.at(u8"Environment");
    if (environment.contains(u8"ClearColor"))
      Settings::environmentClearColor = colorVec4(environment.at(u8"ClearColor").c_str());
#ifdef SHR3D_ENVIRONMENT_MILK
    if (environment.contains(u8"Milk"))
      Settings::environmentMilk = bool(atoi2(environment.at(u8"Milk").c_str()));
    if (environment.contains(u8"MilkActivePresets"))
      Settings::environmentMilkActivePresets = environment.at(u8"MilkActivePresets");
    if (environment.contains(u8"MilkBeatSensitivity"))
      Settings::environmentMilkBeatSensitivity = f32(atof2(environment.at(u8"MilkBeatSensitivity").c_str()));
    if (environment.contains(u8"MilkDuration"))
      Settings::environmentMilkDuration = atoi2(environment.at(u8"MilkDuration").c_str());
    if (environment.contains(u8"MilkMeshSize"))
      Settings::environmentMilkMeshSize = atoi2(environment.at(u8"MilkMeshSize").c_str());
    if (environment.contains(u8"MilkFrameSkip"))
      Settings::environmentMilkFrameSkip = atoi2(environment.at(u8"MilkFrameSkip").c_str());
    if (environment.contains(u8"MilkFrameSpeed"))
      Settings::environmentMilkFrameSpeed = f32(atof2(environment.at(u8"MilkFrameSpeed").c_str()));
    if (environment.contains(u8"MilkShuffle"))
      Settings::environmentMilkShuffle = bool(atoi2(environment.at(u8"MilkShuffle").c_str()));
#endif // SHR3D_ENVIRONMENT_MILK
#ifdef SHR3D_ENVIRONMENT_SKYBOX
    if (environment.contains(u8"Skybox"))
      Settings::environmentSkybox = environment.at(u8"Skybox");
    if (environment.contains(u8"SkyboxRotation"))
      Settings::environmentSkyboxRotation = f32(atof2(environment.at(u8"SkyboxRotation").c_str()));
#endif // SHR3D_ENVIRONMENT_SKYBOX
#ifdef SHR3D_ENVIRONMENT_STAGE
    if (environment.contains(u8"Stage"))
      Settings::environmentStage = environment.at(u8"Stage");
#ifndef PLATFORM_OPENXR_ANDROID
    if (environment.contains(u8"StagePlayerHeight"))
      Settings::environmentStagePlayerHeight = f32(atof2(environment.at(u8"StagePlayerHeight").c_str()));
#endif // PLATFORM_OPENXR_ANDROID
    if (environment.contains(u8"StageRotation"))
      Settings::environmentStageRotation = f32(atof2(environment.at(u8"StageRotation").c_str()));
    if (environment.contains(u8"StageScale"))
      Settings::environmentStageScale = f32(atof2(environment.at(u8"StageScale").c_str()));
    if (environment.contains(u8"StageX"))
      Settings::environmentStageX = f32(atof2(environment.at(u8"StageX").c_str()));
    if (environment.contains(u8"StageY"))
      Settings::environmentStageY = f32(atof2(environment.at(u8"StageY").c_str()));
    if (environment.contains(u8"StageZ"))
      Settings::environmentStageZ = f32(atof2(environment.at(u8"StageZ").c_str()));
#endif // SHR3D_ENVIRONMENT_STAGE
  }
  if (serializedSettings.contains(u8"Camera"))
  {
    const auto& camera = serializedSettings.at(u8"Camera");
    if (camera.contains(u8"Mode"))
      Settings::cameraMode = CameraMode(atoi2(camera.at(u8"Mode").c_str()));
#ifndef PLATFORM_OPENXR_ANDROID
    if (camera.contains(u8"FieldOfView"))
      Settings::cameraFieldOfView = f32(atof2(camera.at(u8"FieldOfView").c_str()));
#endif // PLATFORM_OPENXR_ANDROID
    if (camera.contains(u8"FixedX"))
      Settings::cameraFixedX = f32(atof2(camera.at(u8"FixedX").c_str()));
    if (camera.contains(u8"FixedXRotation"))
      Settings::cameraFixedXRotation = f32(atof2(camera.at(u8"FixedXRotation").c_str()));
    if (camera.contains(u8"FixedY"))
      Settings::cameraFixedY = f32(atof2(camera.at(u8"FixedY").c_str()));
    if (camera.contains(u8"FixedYRotation"))
      Settings::cameraFixedYRotation = f32(atof2(camera.at(u8"FixedYRotation").c_str()));
    if (camera.contains(u8"FixedZ"))
      Settings::cameraFixedZ = f32(atof2(camera.at(u8"FixedZ").c_str()));
    if (camera.contains(u8"ParallaxAnchorTackingDuration"))
      Settings::cameraParallaxAnchorTackingDuration = f32(atof2(camera.at(u8"ParallaxAnchorTackingDuration").c_str()));
    if (camera.contains(u8"ParallaxHighwayRotation"))
      Settings::cameraParallaxHighwayRotation = f32(atof2(camera.at(u8"ParallaxHighwayRotation").c_str()));
    if (camera.contains(u8"ParallaxHighwayScale"))
      Settings::cameraParallaxHighwayScale = f32(atof2(camera.at(u8"ParallaxHighwayScale").c_str()));
    if (camera.contains(u8"ParallaxHighwayX"))
      Settings::cameraParallaxHighwayX = f32(atof2(camera.at(u8"ParallaxHighwayX").c_str()));
    if (camera.contains(u8"ParallaxHighwayXFactor"))
      Settings::cameraParallaxHighwayXFactor = f32(atof2(camera.at(u8"ParallaxHighwayXFactor").c_str()));
    if (camera.contains(u8"ParallaxHighwayY"))
      Settings::cameraParallaxHighwayY = f32(atof2(camera.at(u8"ParallaxHighwayY").c_str()));
    if (camera.contains(u8"ParallaxHighwayYFactor"))
      Settings::cameraParallaxHighwayYFactor = f32(atof2(camera.at(u8"ParallaxHighwayYFactor").c_str()));
    if (camera.contains(u8"ParallaxHighwayZ"))
      Settings::cameraParallaxHighwayZ = f32(atof2(camera.at(u8"ParallaxHighwayZ").c_str()));
    if (camera.contains(u8"ParallaxHighwayZFactor"))
      Settings::cameraParallaxHighwayZFactor = f32(atof2(camera.at(u8"ParallaxHighwayZFactor").c_str()));
    if (camera.contains(u8"ParallaxX"))
      Settings::cameraParallaxX = f32(atof2(camera.at(u8"ParallaxX").c_str()));
    if (camera.contains(u8"ParallaxXFactor"))
      Settings::cameraParallaxXFactor = f32(atof2(camera.at(u8"ParallaxXFactor").c_str()));
    if (camera.contains(u8"ParallaxXRotation"))
      Settings::cameraParallaxXRotation = f32(atof2(camera.at(u8"ParallaxXRotation").c_str()));
    if (camera.contains(u8"ParallaxY"))
      Settings::cameraParallaxY = f32(atof2(camera.at(u8"ParallaxY").c_str()));
    if (camera.contains(u8"ParallaxYFactor"))
      Settings::cameraParallaxYFactor = f32(atof2(camera.at(u8"ParallaxYFactor").c_str()));
    if (camera.contains(u8"ParallaxYRotation"))
      Settings::cameraParallaxYRotation = f32(atof2(camera.at(u8"ParallaxYRotation").c_str()));
    if (camera.contains(u8"ParallaxZ"))
      Settings::cameraParallaxZ = f32(atof2(camera.at(u8"ParallaxZ").c_str()));
    if (camera.contains(u8"ParallaxZFactor"))
      Settings::cameraParallaxZFactor = f32(atof2(camera.at(u8"ParallaxZFactor").c_str()));
#ifdef SHR3D_OPENXR_PCVR
    if (camera.contains(u8"PcVrMode"))
      Settings::cameraPcVrMode = CameraMode(atoi2(camera.at(u8"PcVrMode").c_str()));
    if (camera.contains(u8"PcVrParallaxAnchorTackingDuration"))
      Settings::cameraPcVrParallaxAnchorTackingDuration = f32(atof2(camera.at(u8"PcVrParallaxAnchorTackingDuration").c_str()));
    if (camera.contains(u8"PcVrParallaxHighwayRotation"))
      Settings::cameraPcVrParallaxHighwayRotation = f32(atof2(camera.at(u8"PcVrParallaxHighwayRotation").c_str()));
    if (camera.contains(u8"PcVrParallaxHighwayScale"))
      Settings::cameraPcVrParallaxHighwayScale = f32(atof2(camera.at(u8"PcVrParallaxHighwayScale").c_str()));
    if (camera.contains(u8"PcVrParallaxHighwayX"))
      Settings::cameraPcVrParallaxHighwayX = f32(atof2(camera.at(u8"PcVrParallaxHighwayX").c_str()));
    if (camera.contains(u8"PcVrParallaxHighwayXFactor"))
      Settings::cameraPcVrParallaxHighwayXFactor = f32(atof2(camera.at(u8"PcVrParallaxHighwayXFactor").c_str()));
    if (camera.contains(u8"PcVrParallaxHighwayY"))
      Settings::cameraPcVrParallaxHighwayY = f32(atof2(camera.at(u8"PcVrParallaxHighwayY").c_str()));
    if (camera.contains(u8"PcVrParallaxHighwayYFactor"))
      Settings::cameraPcVrParallaxHighwayYFactor = f32(atof2(camera.at(u8"PcVrParallaxHighwayYFactor").c_str()));
    if (camera.contains(u8"PcVrParallaxHighwayZ"))
      Settings::cameraPcVrParallaxHighwayZ = f32(atof2(camera.at(u8"PcVrParallaxHighwayZ").c_str()));
    if (camera.contains(u8"PcVrParallaxHighwayZFactor"))
      Settings::cameraPcVrParallaxHighwayZFactor = f32(atof2(camera.at(u8"PcVrParallaxHighwayZFactor").c_str()));
    if (camera.contains(u8"PcVrParallaxX"))
      Settings::cameraPcVrParallaxX = f32(atof2(camera.at(u8"PcVrParallaxX").c_str()));
    if (camera.contains(u8"PcVrParallaxXFactor"))
      Settings::cameraPcVrParallaxXFactor = f32(atof2(camera.at(u8"PcVrParallaxXFactor").c_str()));
    if (camera.contains(u8"PcVrParallaxXRotation"))
      Settings::cameraPcVrParallaxXRotation = f32(atof2(camera.at(u8"PcVrParallaxXRotation").c_str()));
    if (camera.contains(u8"PcVrParallaxY"))
      Settings::cameraPcVrParallaxY = f32(atof2(camera.at(u8"PcVrParallaxY").c_str()));
    if (camera.contains(u8"PcVrParallaxYFactor"))
      Settings::cameraPcVrParallaxYFactor = f32(atof2(camera.at(u8"PcVrParallaxYFactor").c_str()));
    if (camera.contains(u8"PcVrParallaxYRotation"))
      Settings::cameraPcVrParallaxYRotation = f32(atof2(camera.at(u8"PcVrParallaxYRotation").c_str()));
    if (camera.contains(u8"PcVrParallaxZ"))
      Settings::cameraPcVrParallaxZ = f32(atof2(camera.at(u8"PcVrParallaxZ").c_str()));
    if (camera.contains(u8"PcVrParallaxZFactor"))
      Settings::cameraPcVrParallaxZFactor = f32(atof2(camera.at(u8"PcVrParallaxZFactor").c_str()));
#endif // SHR3D_OPENXR_PCVR
  }
  if (serializedSettings.contains(u8"Graphics"))
  {
    const auto& graphics = serializedSettings.at(u8"Graphics");
    if (graphics.contains(u8"Fullscreen"))
      Settings::graphicsFullscreen = FullscreenMode(atoi2(graphics.at(u8"Fullscreen").c_str()));
#ifdef SHR3D_GRAPHICS_MSAA
    if (graphics.contains(u8"MSAA"))
      Settings::graphicsMSAA = atoi2(graphics.at(u8"MSAA").c_str());
#endif // SHR3D_GRAPHICS_MSAA
    if (graphics.contains(u8"Scaling"))
      Settings::graphicsScaling = ScalingMode(atoi2(graphics.at(u8"Scaling").c_str()));
#ifdef SHR3D_OPENGL_SPIR_V
    if (graphics.contains(u8"SpirV"))
      Settings::graphicsSpirV = atoi2(graphics.at(u8"SpirV").c_str());
#endif // SHR3D_OPENGL_SPIR_V
#ifdef PLATFORM_QUEST_3
    if (graphics.contains(u8"RefreshRate"))
      Settings::graphicsRefreshRate = atoi2(graphics.at(u8"RefreshRate").c_str());
#endif // PLATFORM_QUEST_3
#if !defined(PLATFORM_EMSCRIPTEN) && !defined(PLATFORM_QUEST_3)
    if (graphics.contains(u8"VSync"))
      Settings::graphicsVSync = VSyncMode(atoi2(graphics.at(u8"VSync").c_str()));
#endif // !PLATFORM_EMSCRIPTEN && !PLATFORM_QUEST_3
    if (graphics.contains(u8"WindowWidth"))
      Settings::graphicsWindowWidth = atoi2(graphics.at(u8"WindowWidth").c_str());
    if (graphics.contains(u8"WindowHeight"))
      Settings::graphicsWindowHeight = atoi2(graphics.at(u8"WindowHeight").c_str());
  }
  if (serializedSettings.contains(u8"Highway"))
  {
    const auto& highway = serializedSettings.at(u8"Highway");
    if (highway.contains(u8"AnchorColor0"))
      Settings::highwayAnchorColor[0] = colorVec4(highway.at(u8"AnchorColor0").c_str());
    if (highway.contains(u8"AnchorColor1"))
      Settings::highwayAnchorColor[1] = colorVec4(highway.at(u8"AnchorColor1").c_str());
    if (highway.contains(u8"AnchorColor2"))
      Settings::highwayAnchorColor[2] = colorVec4(highway.at(u8"AnchorColor2").c_str());
    if (highway.contains(u8"AnchorColor3"))
      Settings::highwayAnchorColor[3] = colorVec4(highway.at(u8"AnchorColor3").c_str());
    if (highway.contains(u8"AnchorColorExponent"))
      Settings::highwayAnchorColorExponent = f32(atof2(highway.at(u8"AnchorColorExponent").c_str()));
    if (highway.contains(u8"Beat"))
      Settings::highwayBeat = bool(atoi2(highway.at(u8"Beat").c_str()));
    if (highway.contains(u8"BeatColor0"))
      Settings::highwayBeatColor[0] = colorVec4(highway.at(u8"BeatColor0").c_str());
    if (highway.contains(u8"BeatColor1"))
      Settings::highwayBeatColor[1] = colorVec4(highway.at(u8"BeatColor1").c_str());
    if (highway.contains(u8"BeatStrumDirection"))
      Settings::highwayBeatStrumDirection = bool(atoi2(highway.at(u8"BeatStrumDirection").c_str()));
    if (highway.contains(u8"BeatStrumDirectionColor0"))
      Settings::highwayBeatStrumDirectionColor[0] = colorVec4(highway.at(u8"BeatStrumDirectionColor0").c_str());
    if (highway.contains(u8"BeatStrumDirectionColor1"))
      Settings::highwayBeatStrumDirectionColor[1] = colorVec4(highway.at(u8"BeatStrumDirectionColor1").c_str());
    if (highway.contains(u8"BeatStrumDirectionPrimary"))
      Settings::highwayBeatStrumDirectionPrimary = StrumDirection(atoi2(highway.at(u8"BeatStrumDirectionPrimary").c_str()));
    if (highway.contains(u8"BeatStrumDirectionNext"))
      Settings::highwayBeatStrumDirectionNext = StrumDirection(atoi2(highway.at(u8"BeatStrumDirectionNext").c_str()));
    if (highway.contains(u8"BeatStrumsBetweenBeats"))
      Settings::highwayBeatStrumsBetweenBeats = atoi2(highway.at(u8"BeatStrumsBetweenBeats").c_str());
    if (highway.contains(u8"CapoColor"))
      Settings::highwayCapoColor = colorVec4(highway.at(u8"CapoColor").c_str());
    if (highway.contains(u8"ChordBox"))
      Settings::highwayChordBox = bool(atoi2(highway.at(u8"ChordBox").c_str()));
    if (highway.contains(u8"ChordBoxColor"))
      Settings::highwayChordBoxColor = colorVec4(highway.at(u8"ChordBoxColor").c_str());
    if (highway.contains(u8"ChordBoxArpeggio"))
      Settings::highwayChordBoxArpeggio = bool(atoi2(highway.at(u8"ChordBoxArpeggio").c_str()));
    if (highway.contains(u8"ChordBoxArpeggioColor"))
      Settings::highwayChordBoxArpeggioColor = colorVec4(highway.at(u8"ChordBoxArpeggioColor").c_str());
    if (highway.contains(u8"ChordFretNumbers"))
      Settings::highwayChordFretNumbers = bool(atoi2(highway.at(u8"ChordFretNumbers").c_str()));
    if (highway.contains(u8"ChordName"))
      Settings::highwayChordName = bool(atoi2(highway.at(u8"ChordName").c_str()));
    if (highway.contains(u8"ChordNameColor"))
      Settings::highwayChordNameColor = colorVec4(highway.at(u8"ChordNameColor").c_str());
    if (highway.contains(u8"DotInlayColor0"))
      Settings::highwayDotInlayColor[0] = colorVec4(highway.at(u8"DotInlayColor0").c_str());
    if (highway.contains(u8"DotInlayColor1"))
      Settings::highwayDotInlayColor[1] = colorVec4(highway.at(u8"DotInlayColor1").c_str());
    if (highway.contains(u8"DotInlayColor2"))
      Settings::highwayDotInlayColor[2] = colorVec4(highway.at(u8"DotInlayColor2").c_str());
    if (highway.contains(u8"DotInlayColor3"))
      Settings::highwayDotInlayColor[3] = colorVec4(highway.at(u8"DotInlayColor3").c_str());
    if (highway.contains(u8"FadeFarDistance"))
      Settings::highwayFadeFarDistance = f32(atof2(highway.at(u8"FadeFarDistance").c_str()));
    if (highway.contains(u8"FadeNearDistance"))
      Settings::highwayFadeNearDistance = f32(atof2(highway.at(u8"FadeNearDistance").c_str()));
    if (highway.contains(u8"FadeNearStrength"))
      Settings::highwayFadeNearStrength = f32(atof2(highway.at(u8"FadeNearStrength").c_str()));
    if (highway.contains(u8"FingerNumberColor"))
      Settings::highwayFingerNumberColor = colorVec4(highway.at(u8"FingerNumberColor").c_str());
    if (highway.contains(u8"FingerNumbers"))
      Settings::highwayFingerNumbers = bool(atoi2(highway.at(u8"FingerNumbers").c_str()));
    if (highway.contains(u8"FretboardFretColor"))
      Settings::highwayFretboardFretColor = colorVec4(highway.at(u8"FretboardFretColor").c_str());
    if (highway.contains(u8"FretboardFretNumberColor0"))
      Settings::highwayFretboardFretNumberColor[0] = colorVec4(highway.at(u8"FretboardFretNumberColor0").c_str());
    if (highway.contains(u8"FretboardFretNumberColor1"))
      Settings::highwayFretboardFretNumberColor[1] = colorVec4(highway.at(u8"FretboardFretNumberColor1").c_str());
    if (highway.contains(u8"FretboardFretNumberColor2"))
      Settings::highwayFretboardFretNumberColor[2] = colorVec4(highway.at(u8"FretboardFretNumberColor2").c_str());
    if (highway.contains(u8"FretboardNoteNames"))
      Settings::highwayFretboardNoteNames = bool(atoi2(highway.at(u8"FretboardNoteNames").c_str()));
    if (highway.contains(u8"FretboardNoteNameColor0"))
      Settings::highwayFretboardNoteNameColor[0] = colorVec4(highway.at(u8"FretboardNoteNameColor0").c_str());
    if (highway.contains(u8"FretboardNoteNameColor1"))
      Settings::highwayFretboardNoteNameColor[1] = colorVec4(highway.at(u8"FretboardNoteNameColor1").c_str());
    if (highway.contains(u8"FretboardCollisionNotes"))
      Settings::highwayFretboardCollisionNotes = bool(atoi2(highway.at(u8"FretboardCollisionNotes").c_str()));
    if (highway.contains(u8"FretboardCollisionNotesColor0"))
      Settings::highwayFretboardCollisionNotesColor[0] = colorVec4(highway.at(u8"FretboardCollisionNotesColor0").c_str());
    if (highway.contains(u8"FretboardCollisionNotesColor1"))
      Settings::highwayFretboardCollisionNotesColor[1] = colorVec4(highway.at(u8"FretboardCollisionNotesColor1").c_str());
    if (highway.contains(u8"FretboardPlayedNotes"))
      Settings::highwayFretboardPlayedNotesDot = bool(atoi2(highway.at(u8"FretboardPlayedNotes").c_str()));
    if (highway.contains(u8"FretboardPlayedNotesColor0"))
      Settings::highwayFretboardPlayedNotesDotColor[0] = colorVec4(highway.at(u8"FretboardPlayedNotesColor0").c_str());
    if (highway.contains(u8"FretboardPlayedNotesColor1"))
      Settings::highwayFretboardPlayedNotesDotColor[1] = colorVec4(highway.at(u8"FretboardPlayedNotesColor1").c_str());
    if (highway.contains(u8"FretboardStringNoteNames"))
      Settings::highwayFretboardStringNoteNames = bool(atoi2(highway.at(u8"FretboardStringNoteNames").c_str()));
#ifdef SHR3D_SFX_CORE_HEXFIN
    if (highway.contains(u8"FretboardPlayedNotesTuner"))
      Settings::highwayFretboardPlayedNotesTuner = bool(atoi2(highway.at(u8"FretboardPlayedNotesTuner").c_str()));
#endif // SHR3D_SFX_CORE_HEXFIN
#ifdef SHR3D_PARTICLE
    if (highway.contains(u8"ParticleDetectedNotes"))
      Settings::highwayParticlePlayedNotes = bool(atoi2(highway.at(u8"ParticleDetectedNotes").c_str()));
    if (highway.contains(u8"ParticleCollisionNotes"))
      Settings::highwayParticleCollisionNotes = bool(atoi2(highway.at(u8"ParticleCollisionNotes").c_str()));
    if (highway.contains(u8"ParticleShape"))
      Settings::highwayParticleShape = atoi2(highway.at(u8"ParticleShape").c_str());
    if (highway.contains(u8"ParticleMaxCount"))
      Settings::highwayParticleMaxCount = atoi2(highway.at(u8"ParticleMaxCount").c_str());
    if (highway.contains(u8"ParticleSpawnsPerSecond"))
      Settings::highwayParticleSpawnsPerSecond = f32(atof2(highway.at(u8"ParticleSpawnsPerSecond").c_str()));
    if (highway.contains(u8"ParticleSpawnRadius"))
      Settings::highwayParticleSpawnRadius = f32(atof2(highway.at(u8"ParticleSpawnRadius").c_str()));
    if (highway.contains(u8"ParticleMinSize"))
      Settings::highwayParticleMinSize = f32(atof2(highway.at(u8"ParticleMinSize").c_str()));
    if (highway.contains(u8"ParticleMaxSize"))
      Settings::highwayParticleMaxSize = f32(atof2(highway.at(u8"ParticleMaxSize").c_str()));
    if (highway.contains(u8"ParticleMinLifeTime"))
      Settings::highwayParticleMinLifeTime = f32(atof2(highway.at(u8"ParticleMinLifeTime").c_str()));
    if (highway.contains(u8"ParticleMaxLifeTime"))
      Settings::highwayParticleMaxLifeTime = f32(atof2(highway.at(u8"ParticleMaxLifeTime").c_str()));
    if (highway.contains(u8"ParticleColorVariation"))
      Settings::highwayParticleColorVariation = f32(atof2(highway.at(u8"ParticleColorVariation").c_str()));
    if (highway.contains(u8"ParticleMinVelocityX"))
      Settings::highwayParticleMinVelocityX = f32(atof2(highway.at(u8"ParticleMinVelocityX").c_str()));
    if (highway.contains(u8"ParticleMaxVelocityX"))
      Settings::highwayParticleMaxVelocityX = f32(atof2(highway.at(u8"ParticleMaxVelocityX").c_str()));
    if (highway.contains(u8"ParticleMinVelocityY"))
      Settings::highwayParticleMinVelocityY = f32(atof2(highway.at(u8"ParticleMinVelocityY").c_str()));
    if (highway.contains(u8"ParticleMaxVelocityY"))
      Settings::highwayParticleMaxVelocityY = f32(atof2(highway.at(u8"ParticleMaxVelocityY").c_str()));
    if (highway.contains(u8"ParticleMinVelocityZ"))
      Settings::highwayParticleMinVelocityZ = f32(atof2(highway.at(u8"ParticleMinVelocityZ").c_str()));
    if (highway.contains(u8"ParticleMaxVelocityZ"))
      Settings::highwayParticleMaxVelocityZ = f32(atof2(highway.at(u8"ParticleMaxVelocityZ").c_str()));
    if (highway.contains(u8"ParticleAccelerationX"))
      Settings::highwayParticleAccelerationX = f32(atof2(highway.at(u8"ParticleAccelerationX").c_str()));
    if (highway.contains(u8"ParticleAccelerationY"))
      Settings::highwayParticleAccelerationY = f32(atof2(highway.at(u8"ParticleAccelerationY").c_str()));
    if (highway.contains(u8"ParticleAccelerationZ"))
      Settings::highwayParticleAccelerationZ = f32(atof2(highway.at(u8"ParticleAccelerationZ").c_str()));
    if (highway.contains(u8"ParticleMinRotationAngle"))
      Settings::highwayParticleMinRotationAngle = f32(atof2(highway.at(u8"ParticleMinRotationAngle").c_str()));
    if (highway.contains(u8"ParticleMaxRotationAngle"))
      Settings::highwayParticleMaxRotationAngle = f32(atof2(highway.at(u8"ParticleMaxRotationAngle").c_str()));
#endif // SHR3D_PARTICLE
    if (highway.contains(u8"GroundFretColor0"))
      Settings::highwayGroundFretColor[0] = colorVec4(highway.at(u8"GroundFretColor0").c_str());
    if (highway.contains(u8"GroundFretColor1"))
      Settings::highwayGroundFretColor[1] = colorVec4(highway.at(u8"GroundFretColor1").c_str());
    if (highway.contains(u8"InstrumentBass5StringHideString0"))
      Settings::highwayInstrumentBass5StringHideString0 = bool(atoi2(highway.at(u8"InstrumentBass5StringHideString0").c_str()));
    if (highway.contains(u8"InstrumentBass5StringTuning0"))
      Settings::highwayInstrumentBass5StringTuning[0] = atoi2(highway.at(u8"InstrumentBass5StringTuning0").c_str());
    if (highway.contains(u8"InstrumentBass5StringTuning1"))
      Settings::highwayInstrumentBass5StringTuning[1] = atoi2(highway.at(u8"InstrumentBass5StringTuning1").c_str());
    if (highway.contains(u8"InstrumentBass5StringTuning2"))
      Settings::highwayInstrumentBass5StringTuning[2] = atoi2(highway.at(u8"InstrumentBass5StringTuning2").c_str());
    if (highway.contains(u8"InstrumentBass5StringTuning3"))
      Settings::highwayInstrumentBass5StringTuning[3] = atoi2(highway.at(u8"InstrumentBass5StringTuning3").c_str());
    if (highway.contains(u8"InstrumentBassFirstWoundString"))
      Settings::highwayInstrumentBassFirstWoundString = atoi2(highway.at(u8"InstrumentBassFirstWoundString").c_str());
    if (highway.contains(u8"InstrumentBassFretSpacing"))
      Settings::highwayInstrumentBassFretSpacing = f32(atof2(highway.at(u8"InstrumentBassFretSpacing").c_str()));
    if (highway.contains(u8"InstrumentBassFretSpacingFactor"))
      Settings::highwayInstrumentBassFretSpacingFactor = f32(atof2(highway.at(u8"InstrumentBassFretSpacingFactor").c_str()));
    if (highway.contains(u8"InstrumentBassStringColor0"))
      Settings::highwayInstrumentBassStringColor[0] = colorVec4(highway.at(u8"InstrumentBassStringColor0").c_str());
    if (highway.contains(u8"InstrumentBassStringColor1"))
      Settings::highwayInstrumentBassStringColor[1] = colorVec4(highway.at(u8"InstrumentBassStringColor1").c_str());
    if (highway.contains(u8"InstrumentBassStringColor2"))
      Settings::highwayInstrumentBassStringColor[2] = colorVec4(highway.at(u8"InstrumentBassStringColor2").c_str());
    if (highway.contains(u8"InstrumentBassStringColor3"))
      Settings::highwayInstrumentBassStringColor[3] = colorVec4(highway.at(u8"InstrumentBassStringColor3").c_str());
    if (highway.contains(u8"InstrumentBassStringColor4"))
      Settings::highwayInstrumentBassStringColor[4] = colorVec4(highway.at(u8"InstrumentBassStringColor4").c_str());
    if (highway.contains(u8"InstrumentBassStringColor5"))
      Settings::highwayInstrumentBassStringColor[5] = colorVec4(highway.at(u8"InstrumentBassStringColor5").c_str());
    if (highway.contains(u8"InstrumentBassStringSpacing"))
      Settings::highwayInstrumentBassStringSpacing = f32(atof2(highway.at(u8"InstrumentBassStringSpacing").c_str()));
    if (highway.contains(u8"InstrumentGuitar7StringHideString0"))
      Settings::highwayInstrumentGuitar7StringHideString0 = bool(atoi2(highway.at(u8"InstrumentGuitar7StringHideString0").c_str()));
    if (highway.contains(u8"InstrumentGuitar7StringTuning0"))
      Settings::highwayInstrumentGuitar7StringTuning[0] = atoi2(highway.at(u8"InstrumentGuitar7StringTuning0").c_str());
    if (highway.contains(u8"InstrumentGuitar7StringTuning1"))
      Settings::highwayInstrumentGuitar7StringTuning[1] = atoi2(highway.at(u8"InstrumentGuitar7StringTuning1").c_str());
    if (highway.contains(u8"InstrumentGuitar7StringTuning2"))
      Settings::highwayInstrumentGuitar7StringTuning[2] = atoi2(highway.at(u8"InstrumentGuitar7StringTuning2").c_str());
    if (highway.contains(u8"InstrumentGuitar7StringTuning3"))
      Settings::highwayInstrumentGuitar7StringTuning[3] = atoi2(highway.at(u8"InstrumentGuitar7StringTuning3").c_str());
    if (highway.contains(u8"InstrumentGuitar7StringTuning4"))
      Settings::highwayInstrumentGuitar7StringTuning[4] = atoi2(highway.at(u8"InstrumentGuitar7StringTuning4").c_str());
    if (highway.contains(u8"InstrumentGuitar7StringTuning5"))
      Settings::highwayInstrumentGuitar7StringTuning[5] = atoi2(highway.at(u8"InstrumentGuitar7StringTuning5").c_str());
    if (highway.contains(u8"InstrumentGuitarFirstWoundString"))
      Settings::highwayInstrumentGuitarFirstWoundString = atoi2(highway.at(u8"InstrumentGuitarFirstWoundString").c_str());
    if (highway.contains(u8"InstrumentGuitarFretSpacing"))
      Settings::highwayInstrumentGuitarFretSpacing = f32(atof2(highway.at(u8"InstrumentGuitarFretSpacing").c_str()));
    if (highway.contains(u8"InstrumentGuitarFretSpacingFactor"))
      Settings::highwayInstrumentGuitarFretSpacingFactor = f32(atof2(highway.at(u8"InstrumentGuitarFretSpacingFactor").c_str()));
    if (highway.contains(u8"InstrumentGuitarStringColor0"))
      Settings::highwayInstrumentGuitarStringColor[0] = colorVec4(highway.at(u8"InstrumentGuitarStringColor0").c_str());
    if (highway.contains(u8"InstrumentGuitarStringColor1"))
      Settings::highwayInstrumentGuitarStringColor[1] = colorVec4(highway.at(u8"InstrumentGuitarStringColor1").c_str());
    if (highway.contains(u8"InstrumentGuitarStringColor2"))
      Settings::highwayInstrumentGuitarStringColor[2] = colorVec4(highway.at(u8"InstrumentGuitarStringColor2").c_str());
    if (highway.contains(u8"InstrumentGuitarStringColor3"))
      Settings::highwayInstrumentGuitarStringColor[3] = colorVec4(highway.at(u8"InstrumentGuitarStringColor3").c_str());
    if (highway.contains(u8"InstrumentGuitarStringColor4"))
      Settings::highwayInstrumentGuitarStringColor[4] = colorVec4(highway.at(u8"InstrumentGuitarStringColor4").c_str());
    if (highway.contains(u8"InstrumentGuitarStringColor5"))
      Settings::highwayInstrumentGuitarStringColor[5] = colorVec4(highway.at(u8"InstrumentGuitarStringColor5").c_str());
    if (highway.contains(u8"InstrumentGuitarStringColor6"))
      Settings::highwayInstrumentGuitarStringColor[6] = colorVec4(highway.at(u8"InstrumentGuitarStringColor6").c_str());
    if (highway.contains(u8"InstrumentGuitarStringColor7"))
      Settings::highwayInstrumentGuitarStringColor[7] = colorVec4(highway.at(u8"InstrumentGuitarStringColor7").c_str());
    if (highway.contains(u8"InstrumentGuitarStringSpacing"))
      Settings::highwayInstrumentGuitarStringSpacing = f32(atof2(highway.at(u8"InstrumentGuitarStringSpacing").c_str()));
    if (highway.contains(u8"NoteBendCurve"))
      Settings::highwayNoteBendCurve = f32(atof2(highway.at(u8"NoteBendCurve").c_str()));
    if (highway.contains(u8"NoteBendEndTime"))
      Settings::highwayNoteBendEndTime = f32(atof2(highway.at(u8"NoteBendEndTime").c_str()));
    if (highway.contains(u8"NoteBendSpeed"))
      Settings::highwayNoteBendSpeed = f32(atof2(highway.at(u8"NoteBendSpeed").c_str()));
    if (highway.contains(u8"NoteBendHintOffset"))
      Settings::highwayNoteBendHintOffset = f32(atof2(highway.at(u8"NoteBendHintOffset").c_str()));
    if (highway.contains(u8"NoteBendHintDistance"))
      Settings::highwayNoteBendHintDistance = f32(atof2(highway.at(u8"NoteBendHintDistance").c_str()));
    if (highway.contains(u8"NoteHeight"))
      Settings::highwayNoteHeight = f32(atof2(highway.at(u8"NoteHeight").c_str()));
    if (highway.contains(u8"NoteRotate"))
      Settings::highwayNoteRotate = atoi2(highway.at(u8"NoteRotate").c_str());
    if (highway.contains(u8"NoteRotateEndTime"))
      Settings::highwayNoteRotateEndTime = f32(atof2(highway.at(u8"NoteRotateEndTime").c_str()));
    if (highway.contains(u8"NoteRotateSpeed"))
      Settings::highwayNoteRotateSpeed = f32(atof2(highway.at(u8"NoteRotateSpeed").c_str()));
    if (highway.contains(u8"NoteShape"))
      Settings::highwayNoteShape = NoteShape(atoi2(highway.at(u8"NoteShape").c_str()));
    if (highway.contains(u8"NoteSymbolFretMute"))
      Settings::highwayNoteSymbolFretMute = NoteSymbols(atoi2(highway.at(u8"NoteSymbolFretMute").c_str()));
    if (highway.contains(u8"NoteSymbolHammerOn"))
      Settings::highwayNoteSymbolHammerOn = NoteSymbols(atoi2(highway.at(u8"NoteSymbolHammerOn").c_str()));
    if (highway.contains(u8"NoteSymbolHarmonic"))
      Settings::highwayNoteSymbolHarmonic = NoteSymbols(atoi2(highway.at(u8"NoteSymbolHarmonic").c_str()));
    if (highway.contains(u8"NoteSymbolPinchHarmonic"))
      Settings::highwayNoteSymbolPinchHarmonic = NoteSymbols(atoi2(highway.at(u8"NoteSymbolPinchHarmonic").c_str()));
    if (highway.contains(u8"NoteSymbolPalmMute"))
      Settings::highwayNoteSymbolPalmMute = NoteSymbols(atoi2(highway.at(u8"NoteSymbolPalmMute").c_str()));
    if (highway.contains(u8"NoteSymbolPop"))
      Settings::highwayNoteSymbolPop = NoteSymbols(atoi2(highway.at(u8"NoteSymbolPop").c_str()));
    if (highway.contains(u8"NoteSymbolPullOff"))
      Settings::highwayNoteSymbolPullOff = NoteSymbols(atoi2(highway.at(u8"NoteSymbolPullOff").c_str()));
    if (highway.contains(u8"NoteSymbolSlap"))
      Settings::highwayNoteSymbolSlap = NoteSymbols(atoi2(highway.at(u8"NoteSymbolSlap").c_str()));
    if (highway.contains(u8"NoteSymbolTap"))
      Settings::highwayNoteSymbolTap = NoteSymbols(atoi2(highway.at(u8"NoteSymbolTap").c_str()));
    if (highway.contains(u8"NoteStand"))
      Settings::highwayNoteStand = bool(atoi2(highway.at(u8"NoteStand").c_str()));
    if (highway.contains(u8"NoteStandZero"))
      Settings::highwayNoteStandZero = bool(atoi2(highway.at(u8"NoteStandZero").c_str()));
    if (highway.contains(u8"NoteWidth"))
      Settings::highwayNoteWidth = f32(atof2(highway.at(u8"NoteWidth").c_str()));
    if (highway.contains(u8"NoteSustainCurveSampleDistance"))
      Settings::highwayNoteSustainCurveSampleDistance = f32(atof2(highway.at(u8"NoteSustainCurveSampleDistance").c_str()));
    if (highway.contains(u8"NoteSustainTremoloSampleDistance"))
      Settings::highwayNoteSustainTremoloSampleDistance = f32(atof2(highway.at(u8"NoteSustainTremoloSampleDistance").c_str()));
    if (highway.contains(u8"NoteSustainTremoloShakeStrength"))
      Settings::highwayNoteSustainTremoloShakeStrength = f32(atof2(highway.at(u8"NoteSustainTremoloShakeStrength").c_str()));
    if (highway.contains(u8"NoteSustainWidth"))
      Settings::highwayNoteSustainWidth = f32(atof2(highway.at(u8"NoteSustainWidth").c_str()));
    if (highway.contains(u8"NoteSustainWidthZero"))
      Settings::highwayNoteSustainWidthZero = f32(atof2(highway.at(u8"NoteSustainWidthZero").c_str()));
    if (highway.contains(u8"FretboardNoteHeight"))
      Settings::highwayFretboardNoteHeight = f32(atof2(highway.at(u8"FretboardNoteHeight").c_str()));
    if (highway.contains(u8"FretboardNoteWidth"))
      Settings::highwayFretboardNoteWidth = f32(atof2(highway.at(u8"FretboardNoteWidth").c_str()));
#ifdef SHR3D_RENDERER_DEVELOPMENT
    if (highway.contains(u8"Renderer"))
      Settings::highwayRenderer = Renderer(atoi2(highway.at(u8"Renderer").c_str()));
#endif // SHR3D_RENDERER_DEVELOPMENT
    if (highway.contains(u8"ReverseStrings"))
      Settings::highwayReverseStrings = bool(atoi2(highway.at(u8"ReverseStrings").c_str()));
    if (highway.contains(u8"StringFadeUnplayed"))
      Settings::highwayStringFadeUnplayed = bool(atoi2(highway.at(u8"StringFadeUnplayed").c_str()));
    if (highway.contains(u8"ScrollSpeed"))
      Settings::highwayScrollSpeed = f32(atof2(highway.at(u8"ScrollSpeed").c_str()));
    if (highway.contains(u8"SustainColor"))
      Settings::highwaySustainColor = colorVec4(highway.at(u8"SustainColor").c_str());
#ifdef SHR3D_SFX_CORE_HEXFIN
    if (highway.contains(u8"Tuner"))
      Settings::highwayTuner = bool(atoi2(highway.at(u8"Tuner").c_str()));
    if (highway.contains(u8"TunerColor0"))
      Settings::highwayTunerColor[0] = colorVec4(highway.at(u8"TunerColor0").c_str());
    if (highway.contains(u8"TunerColor1"))
      Settings::highwayTunerColor[1] = colorVec4(highway.at(u8"TunerColor1").c_str());
    if (highway.contains(u8"TunerColor2"))
      Settings::highwayTunerColor[2] = colorVec4(highway.at(u8"TunerColor2").c_str());
    if (highway.contains(u8"TunerColor3"))
      Settings::highwayTunerColor[3] = colorVec4(highway.at(u8"TunerColor3").c_str());
#endif // SHR3D_SFX_CORE_HEXFIN
    if (highway.contains(u8"VUMeter"))
      Settings::highwayVUMeter = bool(atoi2(highway.at(u8"VUMeter").c_str()));
    if (highway.contains(u8"VUMeterColor0"))
      Settings::highwayVUMeterColor[0] = colorVec4(highway.at(u8"VUMeterColor0").c_str());
    if (highway.contains(u8"VUMeterColor1"))
      Settings::highwayVUMeterColor[1] = colorVec4(highway.at(u8"VUMeterColor1").c_str());
    if (highway.contains(u8"VUMeterColor2"))
      Settings::highwayVUMeterColor[2] = colorVec4(highway.at(u8"VUMeterColor2").c_str());
    if (highway.contains(u8"VUMeterColor3"))
      Settings::highwayVUMeterColor[3] = colorVec4(highway.at(u8"VUMeterColor3").c_str());
    if (highway.contains(u8"VUMeterColor4"))
      Settings::highwayVUMeterColor[4] = colorVec4(highway.at(u8"VUMeterColor4").c_str());
    if (highway.contains(u8"ViewDistance"))
      Settings::highwayViewDistance = f32(atof2(highway.at(u8"ViewDistance").c_str()));
  }
  if (serializedSettings.contains(u8"Hud"))
  {
    const auto& hud = serializedSettings.at(u8"Hud");
    if (hud.contains(u8"Lyrics"))
      Settings::hudLyrics = bool(atoi2(hud.at(u8"Lyrics").c_str()));
    if (hud.contains(u8"LyricsColor0"))
      Settings::hudLyricsColor[0] = colorVec4(hud.at(u8"LyricsColor0").c_str());
    if (hud.contains(u8"LyricsColor1"))
      Settings::hudLyricsColor[1] = colorVec4(hud.at(u8"LyricsColor1").c_str());
    if (hud.contains(u8"LyricsColor2"))
      Settings::hudLyricsColor[2] = colorVec4(hud.at(u8"LyricsColor2").c_str());
    if (hud.contains(u8"LyricsScale"))
      Settings::hudLyricsScale = f32(atof2(hud.at(u8"LyricsScale").c_str()));
    if (hud.contains(u8"LyricsX"))
      Settings::hudLyricsX = f32(atof2(hud.at(u8"LyricsX").c_str()));
    if (hud.contains(u8"LyricsY0"))
      Settings::hudLyricsY[0] = f32(atof2(hud.at(u8"LyricsY0").c_str()));
    if (hud.contains(u8"LyricsY1"))
      Settings::hudLyricsY[1] = f32(atof2(hud.at(u8"LyricsY1").c_str()));
    if (hud.contains(u8"NewHighscore"))
      Settings::hudNewHighscore = bool(atoi2(hud.at(u8"NewHighscore").c_str()));
#ifdef SHR3D_RENDERER_DEVELOPMENT
    if (hud.contains(u8"Renderer"))
      Settings::hudRenderer = Renderer(atoi2(hud.at(u8"Renderer").c_str()));
#endif // SHR3D_RENDERER_DEVELOPMENT
    if (hud.contains(u8"TimelineLevel"))
      Settings::hudTimelineLevel = bool(atoi2(hud.at(u8"TimelineLevel").c_str()));
    if (hud.contains(u8"TimelineLevelColor0"))
      Settings::hudTimelineLevelColor[0] = colorVec4(hud.at(u8"TimelineLevelColor0").c_str());
    if (hud.contains(u8"TimelineLevelColor1"))
      Settings::hudTimelineLevelColor[1] = colorVec4(hud.at(u8"TimelineLevelColor1").c_str());
    if (hud.contains(u8"TimelineLevelColor2"))
      Settings::hudTimelineLevelColor[2] = colorVec4(hud.at(u8"TimelineLevelColor2").c_str());
    if (hud.contains(u8"TimelineLevelColor3"))
      Settings::hudTimelineLevelColor[3] = colorVec4(hud.at(u8"TimelineLevelColor3").c_str());
    if (hud.contains(u8"TimelineLevelColor4"))
      Settings::hudTimelineLevelColor[4] = colorVec4(hud.at(u8"TimelineLevelColor4").c_str());
    if (hud.contains(u8"TimelineLevelColor5"))
      Settings::hudTimelineLevelColor[5] = colorVec4(hud.at(u8"TimelineLevelColor5").c_str());
    if (hud.contains(u8"TimelineLevelColor6"))
      Settings::hudTimelineLevelColor[6] = colorVec4(hud.at(u8"TimelineLevelColor6").c_str());
    if (hud.contains(u8"TimelineLevelColor7"))
      Settings::hudTimelineLevelColor[7] = colorVec4(hud.at(u8"TimelineLevelColor7").c_str());
    if (hud.contains(u8"TimelineLevelFlipY"))
      Settings::hudTimelineLevelFlipY = bool(atoi2(hud.at(u8"TimelineLevelFlipY").c_str()));
    if (hud.contains(u8"TimelineLevelScaleX"))
      Settings::hudTimelineLevelScaleX = f32(atof2(hud.at(u8"TimelineLevelScaleX").c_str()));
    if (hud.contains(u8"TimelineLevelScaleY"))
      Settings::hudTimelineLevelScaleY = f32(atof2(hud.at(u8"TimelineLevelScaleY").c_str()));
    if (hud.contains(u8"TimelineLevelSpacing"))
      Settings::hudTimelineLevelSpacing = f32(atof2(hud.at(u8"TimelineLevelSpacing").c_str()));
    if (hud.contains(u8"TimelineLevelX"))
      Settings::hudTimelineLevelX = f32(atof2(hud.at(u8"TimelineLevelX").c_str()));
    if (hud.contains(u8"TimelineLevelY"))
      Settings::hudTimelineLevelY = f32(atof2(hud.at(u8"TimelineLevelY").c_str()));
#ifdef SHR3D_OPENXR
    if (hud.contains(u8"TimelineLevelXrFlipY"))
      Settings::hudTimelineLevelXrFlipY = bool(atoi2(hud.at(u8"TimelineLevelXrFlipY").c_str()));
    if (hud.contains(u8"TimelineLevelXrScaleX"))
      Settings::hudTimelineLevelXrScaleX = f32(atof2(hud.at(u8"TimelineLevelXrScaleX").c_str()));
    if (hud.contains(u8"TimelineLevelXrScaleY"))
      Settings::hudTimelineLevelXrScaleY = f32(atof2(hud.at(u8"TimelineLevelXrScaleY").c_str()));
    if (hud.contains(u8"TimelineLevelXrSpacing"))
      Settings::hudTimelineLevelXrSpacing = f32(atof2(hud.at(u8"TimelineLevelXrSpacing").c_str()));
    if (hud.contains(u8"TimelineLevelXrX"))
      Settings::hudTimelineLevelXrX = f32(atof2(hud.at(u8"TimelineLevelXrX").c_str()));
    if (hud.contains(u8"TimelineLevelXrY"))
      Settings::hudTimelineLevelXrY = f32(atof2(hud.at(u8"TimelineLevelXrY").c_str()));
    if (hud.contains(u8"TimelineLevelXrZ"))
      Settings::hudTimelineLevelXrZ = f32(atof2(hud.at(u8"TimelineLevelXrZ").c_str()));
#endif // SHR3D_OPENXR
#ifdef SHR3D_MUSIC_STRETCHER
    if (hud.contains(u8"TimelineMusicStretcher"))
      Settings::hudTimelineMusicStretcher = bool(atoi2(hud.at(u8"TimelineMusicStretcher").c_str()));
    if (hud.contains(u8"TimelineMusicStretcherColor0"))
      Settings::hudTimelineMusicStretcherColor[0] = colorVec4(hud.at(u8"TimelineMusicStretcherColor0").c_str());
    if (hud.contains(u8"TimelineMusicStretcherColor1"))
      Settings::hudTimelineMusicStretcherColor[1] = colorVec4(hud.at(u8"TimelineMusicStretcherColor1").c_str());
    if (hud.contains(u8"TimelineMusicStretcherScaleX"))
      Settings::hudTimelineMusicStretcherScaleX = f32(atof2(hud.at(u8"TimelineMusicStretcherScaleX").c_str()));
    if (hud.contains(u8"TimelineMusicStretcherScaleY"))
      Settings::hudTimelineMusicStretcherScaleY = f32(atof2(hud.at(u8"TimelineMusicStretcherScaleY").c_str()));
    if (hud.contains(u8"TimelineMusicStretcherX"))
      Settings::hudTimelineMusicStretcherX = f32(atof2(hud.at(u8"TimelineMusicStretcherX").c_str()));
    if (hud.contains(u8"TimelineMusicStretcherY"))
      Settings::hudTimelineMusicStretcherY = f32(atof2(hud.at(u8"TimelineMusicStretcherY").c_str()));
#ifdef SHR3D_OPENXR
    if (hud.contains(u8"TimelineMusicStretcherXrScaleX"))
      Settings::hudTimelineMusicStretcherXrScaleX = f32(atof2(hud.at(u8"TimelineMusicStretcherXrScaleX").c_str()));
    if (hud.contains(u8"TimelineMusicStretcherXrScaleY"))
      Settings::hudTimelineMusicStretcherXrScaleY = f32(atof2(hud.at(u8"TimelineMusicStretcherXrScaleY").c_str()));
    if (hud.contains(u8"TimelineMusicStretcherXrX"))
      Settings::hudTimelineMusicStretcherXrX = f32(atof2(hud.at(u8"TimelineMusicStretcherXrX").c_str()));
    if (hud.contains(u8"TimelineMusicStretcherXrY"))
      Settings::hudTimelineMusicStretcherXrY = f32(atof2(hud.at(u8"TimelineMusicStretcherXrY").c_str()));
    if (hud.contains(u8"TimelineMusicStretcherXrZ"))
      Settings::hudTimelineMusicStretcherXrZ = f32(atof2(hud.at(u8"TimelineMusicStretcherXrZ").c_str()));
#endif // SHR3D_OPENXR
#endif // SHR3D_MUSIC_STRETCHER
    if (hud.contains(u8"TimelineTone"))
      Settings::hudTimelineTone = bool(atoi2(hud.at(u8"TimelineTone").c_str()));
    if (hud.contains(u8"TimelineToneColor0"))
      Settings::hudTimelineToneColor[0] = colorVec4(hud.at(u8"TimelineToneColor0").c_str());
    if (hud.contains(u8"TimelineToneColor1"))
      Settings::hudTimelineToneColor[1] = colorVec4(hud.at(u8"TimelineToneColor1").c_str());
    if (hud.contains(u8"TimelineToneColor2"))
      Settings::hudTimelineToneColor[2] = colorVec4(hud.at(u8"TimelineToneColor2").c_str());
    if (hud.contains(u8"TimelineToneColor3"))
      Settings::hudTimelineToneColor[3] = colorVec4(hud.at(u8"TimelineToneColor3").c_str());
    if (hud.contains(u8"TimelineToneColor4"))
      Settings::hudTimelineToneColor[4] = colorVec4(hud.at(u8"TimelineToneColor4").c_str());
    if (hud.contains(u8"TimelineToneColor5"))
      Settings::hudTimelineToneColor[5] = colorVec4(hud.at(u8"TimelineToneColor5").c_str());
    if (hud.contains(u8"TimelineToneColor6"))
      Settings::hudTimelineToneColor[6] = colorVec4(hud.at(u8"TimelineToneColor6").c_str());
    if (hud.contains(u8"TimelineToneColor7"))
      Settings::hudTimelineToneColor[7] = colorVec4(hud.at(u8"TimelineToneColor7").c_str());
    if (hud.contains(u8"TimelineToneColor8"))
      Settings::hudTimelineToneColor[8] = colorVec4(hud.at(u8"TimelineToneColor8").c_str());
    if (hud.contains(u8"TimelineToneColor9"))
      Settings::hudTimelineToneColor[9] = colorVec4(hud.at(u8"TimelineToneColor9").c_str());
    if (hud.contains(u8"TimelineToneColor10"))
      Settings::hudTimelineToneColor[10] = colorVec4(hud.at(u8"TimelineToneColor10").c_str());
    if (hud.contains(u8"TimelineToneScaleX"))
      Settings::hudTimelineToneScaleX = f32(atof2(hud.at(u8"TimelineToneScaleX").c_str()));
    if (hud.contains(u8"TimelineToneScaleY"))
      Settings::hudTimelineToneScaleY = f32(atof2(hud.at(u8"TimelineToneScaleY").c_str()));
    if (hud.contains(u8"TimelineToneX"))
      Settings::hudTimelineToneX = f32(atof2(hud.at(u8"TimelineToneX").c_str()));
    if (hud.contains(u8"TimelineToneY"))
      Settings::hudTimelineToneY = f32(atof2(hud.at(u8"TimelineToneY").c_str()));
#ifdef SHR3D_OPENXR
    if (hud.contains(u8"TimelineToneXrScaleX"))
      Settings::hudTimelineToneXrScaleX = f32(atof2(hud.at(u8"TimelineToneXrScaleX").c_str()));
    if (hud.contains(u8"TimelineToneXrScaleY"))
      Settings::hudTimelineToneXrScaleY = f32(atof2(hud.at(u8"TimelineToneXrScaleY").c_str()));
    if (hud.contains(u8"TimelineToneXrX"))
      Settings::hudTimelineToneXrX = f32(atof2(hud.at(u8"TimelineToneXrX").c_str()));
    if (hud.contains(u8"TimelineToneXrY"))
      Settings::hudTimelineToneXrY = f32(atof2(hud.at(u8"TimelineToneXrY").c_str()));
    if (hud.contains(u8"TimelineToneXrZ"))
      Settings::hudTimelineToneXrZ = f32(atof2(hud.at(u8"TimelineToneXrZ").c_str()));
#endif // SHR3D_OPENXR
    if (hud.contains(u8"TimelineQuickRepeaterColor0"))
      Settings::hudTimelineQuickRepeaterColor[0] = colorVec4(hud.at(u8"TimelineQuickRepeaterColor0").c_str());
    if (hud.contains(u8"TimelineQuickRepeaterColor1"))
      Settings::hudTimelineQuickRepeaterColor[1] = colorVec4(hud.at(u8"TimelineQuickRepeaterColor1").c_str());
    if (hud.contains(u8"TimelineQuickRepeaterFlipY"))
      Settings::hudTimelineQuickRepeaterFlipY = bool(atoi2(hud.at(u8"TimelineQuickRepeaterFlipY").c_str()));
    if (hud.contains(u8"TimelineQuickRepeaterScaleY"))
      Settings::hudTimelineQuickRepeaterScaleY = f32(atof2(hud.at(u8"TimelineQuickRepeaterScaleY").c_str()));
    if (hud.contains(u8"TimelineQuickRepeaterX"))
      Settings::hudTimelineQuickRepeaterX = f32(atof2(hud.at(u8"TimelineQuickRepeaterX").c_str()));
    if (hud.contains(u8"TimelineQuickRepeaterY"))
      Settings::hudTimelineQuickRepeaterY = f32(atof2(hud.at(u8"TimelineQuickRepeaterY").c_str()));
#ifdef SHR3D_OPENXR
    if (hud.contains(u8"TimelineQuickRepeaterXrScaleX"))
      Settings::hudTimelineQuickRepeaterXrScaleX = f32(atof2(hud.at(u8"TimelineQuickRepeaterXrScaleX").c_str()));
    if (hud.contains(u8"TimelineQuickRepeaterXrScaleY"))
      Settings::hudTimelineQuickRepeaterXrScaleY = f32(atof2(hud.at(u8"TimelineQuickRepeaterXrScaleY").c_str()));
    if (hud.contains(u8"TimelineQuickRepeaterXrX"))
      Settings::hudTimelineQuickRepeaterXrX = f32(atof2(hud.at(u8"TimelineQuickRepeaterXrX").c_str()));
    if (hud.contains(u8"TimelineQuickRepeaterXrY"))
      Settings::hudTimelineQuickRepeaterXrY = f32(atof2(hud.at(u8"TimelineQuickRepeaterXrY").c_str()));
    if (hud.contains(u8"TimelineQuickRepeaterXrZ"))
      Settings::hudTimelineQuickRepeaterXrZ = f32(atof2(hud.at(u8"TimelineQuickRepeaterXrZ").c_str()));
#endif // SHR3D_OPENXR
    if (hud.contains(u8"Score"))
      Settings::hudScore = bool(atoi2(hud.at(u8"Score").c_str()));
    if (hud.contains(u8"SongInfo"))
      Settings::hudSongInfo = bool(atoi2(hud.at(u8"SongInfo").c_str()));
    if (hud.contains(u8"SongInfoColor0"))
      Settings::hudSongInfoColor[0] = colorVec4(hud.at(u8"SongInfoColor0").c_str());
    if (hud.contains(u8"SongInfoColor1"))
      Settings::hudSongInfoColor[1] = colorVec4(hud.at(u8"SongInfoColor1").c_str());
    if (hud.contains(u8"SongInfoScale0"))
      Settings::hudSongInfoScale[0] = f32(atof2(hud.at(u8"SongInfoScale0").c_str()));
    if (hud.contains(u8"SongInfoScale1"))
      Settings::hudSongInfoScale[1] = f32(atof2(hud.at(u8"SongInfoScale1").c_str()));
    if (hud.contains(u8"SongInfoX"))
      Settings::hudSongInfoX = f32(atof2(hud.at(u8"SongInfoX").c_str()));
    if (hud.contains(u8"SongInfoY0"))
      Settings::hudSongInfoY[0] = f32(atof2(hud.at(u8"SongInfoY0").c_str()));
    if (hud.contains(u8"SongInfoY1"))
      Settings::hudSongInfoY[1] = f32(atof2(hud.at(u8"SongInfoY1").c_str()));
    if (hud.contains(u8"ArrangementSwitch"))
      Settings::hudArrangementSwitch = bool(atoi2(hud.at(u8"ArrangementSwitch").c_str()));
    if (hud.contains(u8"ArrangementSwitchColor"))
      Settings::hudArrangementSwitchColor = colorVec4(hud.at(u8"ArrangementSwitchColor").c_str());
    if (hud.contains(u8"ArrangementSwitchScaleX"))
      Settings::hudArrangementSwitchScaleX = f32(atof2(hud.at(u8"ArrangementSwitchScaleX").c_str()));
    if (hud.contains(u8"ArrangementSwitchScaleY"))
      Settings::hudArrangementSwitchScaleY = f32(atof2(hud.at(u8"ArrangementSwitchScaleY").c_str()));
    if (hud.contains(u8"ArrangementSwitchX"))
      Settings::hudArrangementSwitchX = f32(atof2(hud.at(u8"ArrangementSwitchX").c_str()));
    if (hud.contains(u8"ArrangementSwitchY"))
      Settings::hudArrangementSwitchY = f32(atof2(hud.at(u8"ArrangementSwitchY").c_str()));
#ifdef SHR3D_OPENXR
    if (hud.contains(u8"ArrangementSwitchXrScaleX"))
      Settings::hudArrangementSwitchXrScaleX = f32(atof2(hud.at(u8"ArrangementSwitchXrScaleX").c_str()));
    if (hud.contains(u8"ArrangementSwitchXrScaleY"))
      Settings::hudArrangementSwitchXrScaleY = f32(atof2(hud.at(u8"ArrangementSwitchXrScaleY").c_str()));
    if (hud.contains(u8"ArrangementSwitchXrX"))
      Settings::hudArrangementSwitchXrX = f32(atof2(hud.at(u8"ArrangementSwitchXrX").c_str()));
    if (hud.contains(u8"ArrangementSwitchXrY"))
      Settings::hudArrangementSwitchXrY = f32(atof2(hud.at(u8"ArrangementSwitchXrY").c_str()));
    if (hud.contains(u8"ArrangementSwitchXrZ"))
      Settings::hudArrangementSwitchXrZ = f32(atof2(hud.at(u8"ArrangementSwitchXrZ").c_str()));
#endif // SHR3D_OPENXR
    if (hud.contains(u8"ToneSwitch"))
      Settings::hudToneSwitch = bool(atoi2(hud.at(u8"ToneSwitch").c_str()));
    if (hud.contains(u8"ToneSwitchTimer"))
      Settings::hudToneSwitchTimer = bool(atoi2(hud.at(u8"ToneSwitchTimer").c_str()));
    if (hud.contains(u8"ToneSwitchColor"))
      Settings::hudToneSwitchColor = colorVec4(hud.at(u8"ToneSwitchColor").c_str());
    if (hud.contains(u8"ToneSwitchHintColor"))
      Settings::hudToneSwitchHintColor = colorVec4(hud.at(u8"ToneSwitchHintColor").c_str());
    if (hud.contains(u8"ToneSwitchScale0"))
      Settings::hudToneSwitchScale[0] = f32(atof2(hud.at(u8"ToneSwitchScale0").c_str()));
    if (hud.contains(u8"ToneSwitchScale1"))
      Settings::hudToneSwitchScale[1] = f32(atof2(hud.at(u8"ToneSwitchScale1").c_str()));
    if (hud.contains(u8"ToneSwitchX"))
      Settings::hudToneSwitchX = f32(atof2(hud.at(u8"ToneSwitchX").c_str()));
    if (hud.contains(u8"ToneSwitchY0"))
      Settings::hudToneSwitchY[0] = f32(atof2(hud.at(u8"ToneSwitchY0").c_str()));
    if (hud.contains(u8"ToneSwitchY1"))
      Settings::hudToneSwitchY[1] = f32(atof2(hud.at(u8"ToneSwitchY1").c_str()));
#ifdef SHR3D_OPENXR
    if (hud.contains(u8"ToneSwitchXrScale0"))
      Settings::hudToneSwitchXrScale[0] = f32(atof2(hud.at(u8"ToneSwitchXrScale0").c_str()));
    if (hud.contains(u8"ToneSwitchXrScale1"))
      Settings::hudToneSwitchXrScale[1] = f32(atof2(hud.at(u8"ToneSwitchXrScale1").c_str()));
    if (hud.contains(u8"ToneSwitchXrX"))
      Settings::hudToneSwitchXrX = f32(atof2(hud.at(u8"ToneSwitchXrX").c_str()));
    if (hud.contains(u8"ToneSwitchXrY0"))
      Settings::hudToneSwitchXrY[0] = f32(atof2(hud.at(u8"ToneSwitchXrY0").c_str()));
    if (hud.contains(u8"ToneSwitchXrY1"))
      Settings::hudToneSwitchXrY[1] = f32(atof2(hud.at(u8"ToneSwitchXrY1").c_str()));
    if (hud.contains(u8"ToneSwitchXrZ"))
      Settings::hudToneSwitchXrZ = f32(atof2(hud.at(u8"ToneSwitchXrZ").c_str()));
#endif // SHR3D_OPENXR
    if (hud.contains(u8"Watermark"))
      Settings::hudWatermark = bool(atoi2(hud.at(u8"Watermark").c_str()));
    if (hud.contains(u8"WatermarkColor"))
      Settings::hudWatermarkColor = colorVec4(hud.at(u8"WatermarkColor").c_str());
#ifdef SHR3D_OPENXR
    if (hud.contains(u8"WatermarkXrX"))
      Settings::hudWatermarkXrX = f32(atof2(hud.at(u8"WatermarkXrX").c_str()));
    if (hud.contains(u8"WatermarkXrY"))
      Settings::hudWatermarkXrY = f32(atof2(hud.at(u8"WatermarkXrY").c_str()));
    if (hud.contains(u8"WatermarkXrZ"))
      Settings::hudWatermarkXrZ = f32(atof2(hud.at(u8"WatermarkXrZ").c_str()));
#endif // SHR3D_OPENXR
  }
  if (serializedSettings.contains(u8"Metronome"))
  {
    const auto& metronome = serializedSettings.at(u8"Metronome");
    if (metronome.contains(u8"Enabled"))
      Settings::metronomeEnabled = bool(atoi2(metronome.at(u8"Enabled").c_str()));
    if (metronome.contains(u8"Volume"))
      Settings::metronomeVolume = f32(atof2(metronome.at(u8"Volume").c_str()));
    if (metronome.contains(u8"Decay"))
      Settings::metronomeDecay = bool(atoi2(metronome.at(u8"Decay").c_str()));
    if (metronome.contains(u8"Frequency0"))
      Settings::metronomeFrequency0 = f32(atof2(metronome.at(u8"Frequency0").c_str()));
    if (metronome.contains(u8"Frequency1"))
      Settings::metronomeFrequency1 = f32(atof2(metronome.at(u8"Frequency1").c_str()));
    if (metronome.contains(u8"ClickLength"))
      Settings::metronomeClickLength = atoi2(metronome.at(u8"ClickLength").c_str());
    if (metronome.contains(u8"Side"))
      Settings::metronomeSide = MetronomeSide(atoi2(metronome.at(u8"Side").c_str()));
  }
#ifdef SHR3D_MIDI
  if (serializedSettings.contains(u8"Midi"))
  {
    const auto& midi = serializedSettings.at(u8"Midi");
    if (midi.contains(u8"FineValueFactor"))
      Settings::midiFineValueFactor = f32(atof2(midi.at(u8"FineValueFactor").c_str()));
    if (midi.contains(u8"AutoConnectDevices"))
      Settings::midiAutoConnectDevices = midi.at(u8"AutoConnectDevices");
    for (u8 i = 0; i < ARRAY_SIZE(Const::midiBindingsNames); ++i)
    {
      const std::u8string bindingName = std::u8string(u8"Binding") + Const::midiBindingsNames[i];
      if (midi.contains(bindingName) && !midi.at(bindingName).empty())
      {
        const std::u8string value = serializedSettings.at(u8"Midi").at(bindingName);
        const u64 seperator = value.find_last_of(';');
        ASSERT(seperator != std::string::npos);
        Settings::midiBinding[i] = u8(atoi2(value.substr(0, seperator).c_str()));
        Global::midiNoteMode[Settings::midiBinding[i]] = MidiNoteMode(atoi2(value.substr(seperator + 1).c_str()));
        Global::midiNoteBinding[Settings::midiBinding[i]] = i;
      }
    }
  }
#endif // SHR3D_MIDI
  if (serializedSettings.contains(u8"Paths"))
  {
    const auto& paths = serializedSettings.at(u8"Paths");
    if (paths.contains(u8"StatsIni"))
      Settings::pathStatsIni = paths.at(u8"StatsIni");
    if (paths.contains(u8"TonesIni"))
      Settings::pathTonesIni = paths.at(u8"TonesIni");
    if (paths.contains(u8"Backup"))
      Settings::pathBackup = paths.at(u8"Backup");
#ifdef SHR3D_SHRED_OR_PSARC
    if (paths.contains(u8"Cache"))
      Settings::pathCache = paths.at(u8"Cache");
#endif // SHR3D_SHRED_OR_PSARC
#ifdef SHR3D_SFX_PLUGIN_CLAP
    if (paths.contains(u8"Clap"))
      Settings::pathClap = paths.at(u8"Clap");
#endif // SHR3D_SFX_PLUGIN_CLAP
#ifdef SHR3D_ENVIRONMENT_MILK
    if (paths.contains(u8"Milk"))
      Settings::pathMilk = paths.at(u8"Milk");
#endif // SHR3D_ENVIRONMENT_MILK
#ifdef SHR3D_SFX_CORE_NEURALAMPMODELER
    if (paths.contains(u8"Nam"))
      Settings::pathNam = paths.at(u8"Nam");
#endif // SHR3D_SFX_CORE_NEURALAMPMODELER
    if (paths.contains(u8"Psarc"))
      Settings::pathPsarc = paths.at(u8"Psarc");
#ifdef SHR3D_SHRED
    if (paths.contains(u8"Shred"))
      Settings::pathShred = paths.at(u8"Shred");
#endif // SHR3D_SHRED
#ifdef SHR3D_SFX_PLUGIN_VST
    if (paths.contains(u8"Vst"))
      Settings::pathVst = paths.at(u8"Vst");
#endif // SHR3D_SFX_PLUGIN_VST
#ifdef SHR3D_SFX_PLUGIN_VST3
    if (paths.contains(u8"Vst3"))
      Settings::pathVst3 = paths.at(u8"Vst3");
#endif // SHR3D_SFX_PLUGIN_VST3
#ifdef SHR3D_ENVIRONMENT_SKYBOX
    if (paths.contains(u8"Skybox"))
      Settings::pathSkybox = paths.at(u8"Skybox");
#endif // SHR3D_ENVIRONMENT_SKYBOX
#ifdef SHR3D_ENVIRONMENT_STAGE
    if (paths.contains(u8"Stage"))
      Settings::pathStage = paths.at(u8"Stage");
#endif // SHR3D_ENVIRONMENT_STAGE
  }
#ifdef SHR3D_SPOTIFY
  if (serializedSettings.contains(u8"Spotify"))
  {
    const auto& spotify = serializedSettings.at(u8"Spotify");
    if (spotify.contains(u8"ClientId"))
      Settings::spotifyClientId = spotify.at(u8"ClientId");
    if (spotify.contains(u8"ClientSecret"))
      Settings::spotifyClientSecret = spotify.at(u8"ClientSecret");
    if (spotify.contains(u8"RedirectUri"))
      Settings::spotifyRedirectUri = spotify.at(u8"RedirectUri");
  }
#endif // SHR3D_SPOTIFY
  if (serializedSettings.contains(u8"Tuner"))
  {
    const auto& tuner = serializedSettings.at(u8"Tuner");
    if (tuner.contains(u8"NoteDetectionSource"))
      Settings::tunerNoteDetectionSource = NoteDetectionSource(atoi2(tuner.at(u8"NoteDetectionSource").c_str()));
#ifdef SHR3D_SFX
    if (tuner.contains(u8"TunerPlugin"))
      Settings::tunerPlugin = tuner.at(u8"TunerPlugin");
#ifdef SHR3D_MIDI
    if (tuner.contains(u8"MidiDevice"))
      Settings::tunerMidiDevice = tuner.at(u8"MidiDevice");
#endif // SHR3D_MIDI
    if (tuner.contains(u8"MidiPlugin"))
      Settings::tunerMidiPlugin = tuner.at(u8"MidiPlugin");
#endif // SHR3D_SFX
#ifdef SHR3D_SFX_CORE_HEXFIN
    if (tuner.contains(u8"HexfinOnsetThreshold"))
      Settings::tunerHexfinOnsetThreshold = f32(atof2(tuner.at(u8"HexfinOnsetThreshold").c_str()));
    if (tuner.contains(u8"HexfinReleaseThreshold"))
      Settings::tunerHexfinReleaseThreshold = f32(atof2(tuner.at(u8"HexfinReleaseThreshold").c_str()));
#endif // SHR3D_SFX_CORE_HEXFIN
  }
  if (serializedSettings.contains(u8"Ui"))
  {
    const auto& ui = serializedSettings.at(u8"Ui");
    if (ui.contains(u8"Scale"))
      Settings::uiScale = f32(atof2(ui.at(u8"Scale").c_str()));
#ifdef SHR3D_OPENXR
    if (ui.contains(u8"XrZ"))
      Settings::uiXrZ = f32(atof2(ui.at(u8"XrZ").c_str()));
#endif // SHR3D_OPENXR
#ifdef SHR3D_CUSTOM_CURSOR
    if (ui.contains(u8"CursorCustom"))
      Settings::uiCursorCustom = bool(atoi2(ui.at(u8"CursorCustom").c_str()));
    if (ui.contains(u8"CursorSize"))
      Settings::uiCursorSize = atoi2(ui.at(u8"CursorSize").c_str());
#endif // SHR3D_CUSTOM_CURSOR
    if (ui.contains(u8"Color0"))
      Settings::uiColor[0] = colorVec4(ui.at(u8"Color0").c_str());
    if (ui.contains(u8"Color1"))
      Settings::uiColor[1] = colorVec4(ui.at(u8"Color1").c_str());
    if (ui.contains(u8"Color2"))
      Settings::uiColor[2] = colorVec4(ui.at(u8"Color2").c_str());
    if (ui.contains(u8"Color3"))
      Settings::uiColor[3] = colorVec4(ui.at(u8"Color3").c_str());
    if (ui.contains(u8"Color4"))
      Settings::uiColor[4] = colorVec4(ui.at(u8"Color4").c_str());
    if (ui.contains(u8"Color5"))
      Settings::uiColor[5] = colorVec4(ui.at(u8"Color5").c_str());
    if (ui.contains(u8"Color6"))
      Settings::uiColor[6] = colorVec4(ui.at(u8"Color6").c_str());
    if (ui.contains(u8"Color7"))
      Settings::uiColor[7] = colorVec4(ui.at(u8"Color7").c_str());
    if (ui.contains(u8"Color8"))
      Settings::uiColor[8] = colorVec4(ui.at(u8"Color8").c_str());
    if (ui.contains(u8"Color9"))
      Settings::uiColor[9] = colorVec4(ui.at(u8"Color9").c_str());
    if (ui.contains(u8"Color10"))
      Settings::uiColor[10] = colorVec4(ui.at(u8"Color10").c_str());
    if (ui.contains(u8"Color11"))
      Settings::uiColor[11] = colorVec4(ui.at(u8"Color11").c_str());
    if (ui.contains(u8"Color12"))
      Settings::uiColor[12] = colorVec4(ui.at(u8"Color12").c_str());
    if (ui.contains(u8"Color13"))
      Settings::uiColor[13] = colorVec4(ui.at(u8"Color13").c_str());
    if (ui.contains(u8"Color14"))
      Settings::uiColor[14] = colorVec4(ui.at(u8"Color14").c_str());
    if (ui.contains(u8"Color15"))
      Settings::uiColor[15] = colorVec4(ui.at(u8"Color15").c_str());
    if (ui.contains(u8"Color16"))
      Settings::uiColor[16] = colorVec4(ui.at(u8"Color16").c_str());
    if (ui.contains(u8"Color17"))
      Settings::uiColor[17] = colorVec4(ui.at(u8"Color17").c_str());
    if (ui.contains(u8"Color18"))
      Settings::uiColor[18] = colorVec4(ui.at(u8"Color18").c_str());
    if (ui.contains(u8"Color19"))
      Settings::uiColor[19] = colorVec4(ui.at(u8"Color19").c_str());
    if (ui.contains(u8"Color20"))
      Settings::uiColor[20] = colorVec4(ui.at(u8"Color20").c_str());
    if (ui.contains(u8"Color21"))
      Settings::uiColor[21] = colorVec4(ui.at(u8"Color21").c_str());
    if (ui.contains(u8"Color22"))
      Settings::uiColor[22] = colorVec4(ui.at(u8"Color22").c_str());
    if (ui.contains(u8"Color23"))
      Settings::uiColor[23] = colorVec4(ui.at(u8"Color23").c_str());
    if (ui.contains(u8"Color24"))
      Settings::uiColor[24] = colorVec4(ui.at(u8"Color24").c_str());
    if (ui.contains(u8"Color25"))
      Settings::uiColor[25] = colorVec4(ui.at(u8"Color25").c_str());
    if (ui.contains(u8"Color26"))
      Settings::uiColor[26] = colorVec4(ui.at(u8"Color26").c_str());
    if (ui.contains(u8"Color27"))
      Settings::uiColor[27] = colorVec4(ui.at(u8"Color27").c_str());
    // additional custom colors:
    if (ui.contains(u8"Color28"))
      Settings::uiColor[28] = colorVec4(ui.at(u8"Color28").c_str());
    if (ui.contains(u8"Color29"))
      Settings::uiColor[29] = colorVec4(ui.at(u8"Color29").c_str());
  }

#ifdef SHR3D_AUDIO_SUPERPOWERED
  if (serializedSettings.contains(u8"Audio"))
  {
    const auto& audio = serializedSettings.at(u8"Audio");
    for (i32 i = 0;; ++i)
    {
      const std::u8string mute = std::u8string(u8"SuperpoweredInput") + to_string(i) + u8"Mute";
      if (!audio.contains(mute))
        break;
      Settings::audioSuperpoweredInputMutes.push_back(atoi2(audio.at(mute).c_str()));
    }
    for (i32 i = 0;; ++i)
    {
      const std::u8string volume = std::u8string(u8"SuperpoweredInput") + to_string(i) + u8"Volume";
      if (!audio.contains(volume))
        break;
      Settings::audioSuperpoweredInputVolume.push_back(f32(atof2(audio.at(volume).c_str())));
    }
    for (i32 i = 0;; ++i)
    {
      const std::u8string mute = std::u8string(u8"SuperpoweredOutput") + to_string(i) + u8"Mute";
      if (!audio.contains(mute))
        break;
      Settings::audioSuperpoweredOutputMutes.push_back(atoi2(audio.at(mute).c_str()));
    }
    for (i32 i = 0;; ++i)
    {
      const std::u8string volume = std::u8string(u8"SuperpoweredOutput") + to_string(i) + u8"Volume";
      if (!audio.contains(volume))
        break;
      Settings::audioSuperpoweredOutputVolume.push_back(f32(atof2(audio.at(volume).c_str())));
    }
  }
#endif // SHR3D_AUDIO_SUPERPOWERED

#ifdef SHR3D_OPENXR
  if (serializedSettings.contains(u8"XR"))
  {
    const auto& xr = serializedSettings.at(u8"XR");
#ifdef SHR3D_OPENXR_PCVR
    if (xr.contains(u8"Enabled"))
      Settings::xrEnabled = bool(atoi2(xr.at(u8"Enabled").c_str()));
#endif // SHR3D_OPENXR_PCVR
#ifdef SHR3D_OPENXR_CONTROLLER_PICO4_AND_QUEST3
    if (xr.contains(u8"Controller"))
      Settings::xrController = XrController(atoi2(xr.at(u8"Controller").c_str()));
#endif // SHR3D_OPENXR_CONTROLLER_PICO4_AND_QUEST3
    if (xr.contains(u8"ControllerColor0"))
      Settings::xrControllerColor[0] = colorVec4(xr.at(u8"ControllerColor0").c_str());
    if (xr.contains(u8"ControllerColor1"))
      Settings::xrControllerColor[1] = colorVec4(xr.at(u8"ControllerColor1").c_str());
    if (xr.contains(u8"CursorColor0"))
      Settings::xrCursorColor[0] = colorVec4(xr.at(u8"CursorColor0").c_str());
    if (xr.contains(u8"CursorColor1"))
      Settings::xrCursorColor[1] = colorVec4(xr.at(u8"CursorColor1").c_str());
    if (xr.contains(u8"PointerColor"))
      Settings::xrPointerColor = colorVec4(xr.at(u8"PointerColor").c_str());
    //if (xr.contains(u8"CircularProjection"))
    //  Settings::xrUiCircularProjection = f32(atof2(xr.at(u8"CircularProjection").c_str()));
  }
#endif // SHR3D_OPENXR
}

void Settings::init(
#ifdef SHR3D_GETOPT
  int argc, char* argv[]
#endif // SHR3D_GETOPT
)
{
  // 1. check if a different settings.ini is specified to be loaded
#ifdef SHR3D_GETOPT

  // on emscripten a command line argument uses '=' instead of ' ' as the separator.
#ifdef PLATFORM_EMSCRIPTEN
  std::vector<std::string> emArgs;
  emArgs.push_back(argv[0]);
  for (i32 i = 1; i < argc; ++i)
  {
    i32 split = 0;
    for (u32 j = 0;; ++j)
    {
      switch (argv[i][j])
      {
      case '\0':
        emArgs.push_back({ &argv[i][split], j });
        goto nextArg;
      case '=':
        emArgs.push_back({ &argv[i][0], j });
        split = j + 1;
      }
    }
  nextArg:;
  }
  argc = emArgs.size();
  std::vector<char*> emArgv(argc);
  for (i32 i = 0; i < argc; ++i)
    emArgv[i] = emArgs[i].data();
  argv = emArgv.data();
#endif // PLATFORM_EMSCRIPTEN

#ifndef NDEBUG
  printf("argc: %d\n", argc);
  for (int i = 0; i < argc; ++i)
    printf("argv[%d]: %s\n", i, argv[i]);
#endif // NDEBUG

  parseCommandLineArgSettingsIni(argc, argv);
#endif // SHR3D_GETOPT

  // 2. load that settings.ini or the default one
  if (File::exists(Global::pathSettingsIni.c_str()))
  {
    const std::vector<u8> settingsIniData = File::read(Global::pathSettingsIni.c_str());
    deserializeSettings(Ini::loadIniContent(reinterpret_cast<const char8_t*>(settingsIniData.data()), settingsIniData.size()));
  }

  // 3. parse the rest of the args
#ifdef SHR3D_GETOPT
  parseCommandLineArgs(argc, argv);
#endif // SHR3D_GETOPT
}

void Settings::fini()
{
  const auto serializedSettings = serializeSettings();
  Ini::saveIniFile(Global::pathSettingsIni.c_str(), serializedSettings);
}
