diff --git a/UnleashedRecomp/config.h b/UnleashedRecomp/config.h index c6f1c43..715db5b 100644 --- a/UnleashedRecomp/config.h +++ b/UnleashedRecomp/config.h @@ -7,9 +7,9 @@ class Config public: inline static std::vector> Definitions{}; - CONFIG_DEFINE("System", Language, Language, Language::English); + CONFIG_DEFINE_ENUM("System", ELanguage, Language, ELanguage::English); CONFIG_DEFINE("System", bool, Hints, true); - CONFIG_DEFINE("System", ScoreBehaviour, ScoreBehaviour, ScoreBehaviour::CheckpointReset); + CONFIG_DEFINE_ENUM("System", EScoreBehaviour, ScoreBehaviour, EScoreBehaviour::CheckpointReset); CONFIG_DEFINE("System", bool, UnleashOutOfControlDrain, true); CONFIG_DEFINE("System", bool, WerehogHubTransformVideo, true); CONFIG_DEFINE("System", bool, LogoSkip, false); @@ -21,11 +21,11 @@ public: CONFIG_DEFINE("Audio", float, MusicVolume, 1.0f); CONFIG_DEFINE("Audio", float, SEVolume, 1.0f); - CONFIG_DEFINE("Audio", VoiceLanguage, VoiceLanguage, VoiceLanguage::English); + CONFIG_DEFINE_ENUM("Audio", EVoiceLanguage, VoiceLanguage, EVoiceLanguage::English); CONFIG_DEFINE("Audio", bool, Subtitles, true); CONFIG_DEFINE("Audio", bool, WerehogBattleMusic, true); - CONFIG_DEFINE("Video", GraphicsAPI, GraphicsAPI, GraphicsAPI::D3D12); + CONFIG_DEFINE_ENUM("Video", EGraphicsAPI, GraphicsAPI, EGraphicsAPI::D3D12); CONFIG_DEFINE("Video", size_t, WindowWidth, 1280); CONFIG_DEFINE("Video", size_t, WindowHeight, 720); @@ -42,11 +42,11 @@ public: CONFIG_DEFINE("Video", size_t, MSAA, 4); CONFIG_DEFINE("Video", size_t, AnisotropicFiltering, 16); CONFIG_DEFINE("Video", int32_t, ShadowResolution, 4096); - CONFIG_DEFINE("Video", GITextureFiltering, GITextureFiltering, GITextureFiltering::Bicubic); + CONFIG_DEFINE_ENUM("Video", EGITextureFiltering, GITextureFiltering, EGITextureFiltering::Bicubic); CONFIG_DEFINE("Video", bool, AlphaToCoverage, false); - CONFIG_DEFINE("Video", bool, Xbox360ColorCorrection, false); - CONFIG_DEFINE("Video", MovieScaleMode, MovieScaleMode, MovieScaleMode::Fit); - CONFIG_DEFINE("Video", UIScaleMode, UIScaleMode, UIScaleMode::Centre); + CONFIG_DEFINE("Video", bool, Xbox360ColourCorrection, false); + CONFIG_DEFINE_ENUM("Video", EMovieScaleMode, MovieScaleMode, EMovieScaleMode::Fit); + CONFIG_DEFINE_ENUM("Video", EUIScaleMode, UIScaleMode, EUIScaleMode::Centre); static std::filesystem::path GetUserPath() { diff --git a/UnleashedRecomp/config_detail.h b/UnleashedRecomp/config_detail.h index 8e25513..f85aa48 100644 --- a/UnleashedRecomp/config_detail.h +++ b/UnleashedRecomp/config_detail.h @@ -7,6 +7,15 @@ #define CONFIG_DEFINE(section, type, name, defaultValue) \ inline static ConfigDef name{section, #name, defaultValue}; +#define CONFIG_DEFINE_ENUM_TEMPLATE(type) \ + inline static std::unordered_map g_##type##_template = + +#define CONFIG_DEFINE_ENUM(section, type, name, defaultValue) \ + inline static ConfigDef name{section, #name, defaultValue, g_##type##_template}; + +#define CONFIG_DEFINE_IMPL(section, type, name, defaultValue, readImpl) \ + inline static ConfigDef name{section, #name, defaultValue, [](ConfigDef* def, const toml::v3::table& table) readImpl}; + #define CONFIG_DEFINE_CALLBACK(section, type, name, defaultValue, readCallback) \ inline static ConfigDef name{section, #name, defaultValue, [](ConfigDef* def) readCallback}; @@ -33,6 +42,9 @@ public: std::string Name{}; T DefaultValue{}; T Value{ DefaultValue }; + std::unordered_map EnumTemplate{}; + std::unordered_map EnumTemplateReverse{}; + std::function*, const toml::v3::table&)> ReadImpl; std::function*)> ReadCallback; ConfigDef(std::string section, std::string name, T defaultValue) @@ -41,34 +53,58 @@ public: Config::Definitions.emplace_back(this); } + ConfigDef(std::string section, std::string name, T defaultValue, std::unordered_map enumTemplate) + : Section(section), Name(name), DefaultValue(defaultValue), EnumTemplate(enumTemplate) + { + for (const auto& pair : EnumTemplate) + EnumTemplateReverse[pair.second] = pair.first; + + Config::Definitions.emplace_back(this); + } + ConfigDef(std::string section, std::string name, T defaultValue, std::function*)> readCallback) : Section(section), Name(name), DefaultValue(defaultValue), ReadCallback(readCallback) { Config::Definitions.emplace_back(this); } + ConfigDef(std::string section, std::string name, T defaultValue, std::function*, const toml::v3::table&)> readImpl) + : Section(section), Name(name), DefaultValue(defaultValue), ReadImpl(readImpl) + { + Config::Definitions.emplace_back(this); + } + void ReadValue(toml::v3::ex::parse_result& toml) override { if (auto pSection = toml[Section].as_table()) { const auto& section = *pSection; - if constexpr (std::is_same::value) + if (ReadImpl) { - Value = section[Name].value_or(DefaultValue); - } - else if constexpr (std::is_enum_v) - { - Value = T(section[Name].value_or(std::underlying_type_t(DefaultValue))); + ReadImpl(this, section); } else { - Value = section[Name].value_or(DefaultValue); + if constexpr (std::is_same::value) + { + Value = section[Name].value_or(DefaultValue); + } + else if constexpr (std::is_enum_v) + { + auto it = EnumTemplate.begin(); + + Value = EnumTemplate[section[Name].value_or(static_cast(it->first))]; + } + else + { + Value = section[Name].value_or(DefaultValue); + } + + if (ReadCallback) + ReadCallback(this); } } - - if (ReadCallback) - ReadCallback(this); } void MakeDefault() override @@ -102,11 +138,20 @@ public: { if constexpr (std::is_same::value) { - return Value; + return std::format("\"{}\"", Value); } else if constexpr (std::is_enum_v) { - return std::format("{}", std::underlying_type_t(Value)); + auto it = EnumTemplateReverse.find(Value); + + if (it != EnumTemplateReverse.end()) + { + return std::format("\"{}\"", it->second); + } + else + { + return "\"N/A\""; + } } else { @@ -133,7 +178,7 @@ public: } }; -enum class Language : uint32_t +enum class ELanguage : uint32_t { English = 1, Japanese, @@ -143,40 +188,89 @@ enum class Language : uint32_t Italian }; -enum class ScoreBehaviour : uint32_t +CONFIG_DEFINE_ENUM_TEMPLATE(ELanguage) +{ + { "English", ELanguage::English }, + { "Japanese", ELanguage::Japanese }, + { "German", ELanguage::German }, + { "French", ELanguage::French }, + { "Spanish", ELanguage::Spanish }, + { "Italian", ELanguage::Italian } +}; + +enum class EScoreBehaviour : uint32_t { CheckpointReset, CheckpointRetain }; -enum class VoiceLanguage : uint32_t +CONFIG_DEFINE_ENUM_TEMPLATE(EScoreBehaviour) +{ + { "CheckpointReset", EScoreBehaviour::CheckpointReset }, + { "CheckpointRetain", EScoreBehaviour::CheckpointRetain } +}; + +enum class EVoiceLanguage : uint32_t { English, Japanese }; -enum class GraphicsAPI : uint32_t +CONFIG_DEFINE_ENUM_TEMPLATE(EVoiceLanguage) +{ + { "English", EVoiceLanguage::English }, + { "Japanese", EVoiceLanguage::Japanese } +}; + +enum class EGraphicsAPI : uint32_t { D3D12, Vulkan }; -enum class GITextureFiltering : uint32_t +CONFIG_DEFINE_ENUM_TEMPLATE(EGraphicsAPI) +{ + { "D3D12", EGraphicsAPI::D3D12 }, + { "Vulkan", EGraphicsAPI::Vulkan } +}; + +enum class EGITextureFiltering : uint32_t { Linear, Bicubic }; -enum class MovieScaleMode : uint32_t +CONFIG_DEFINE_ENUM_TEMPLATE(EGITextureFiltering) +{ + { "Linear", EGITextureFiltering::Linear }, + { "Bicubic", EGITextureFiltering::Bicubic } +}; + +enum class EMovieScaleMode : uint32_t { Stretch, Fit, Fill }; -enum class UIScaleMode : uint32_t +CONFIG_DEFINE_ENUM_TEMPLATE(EMovieScaleMode) +{ + { "Stretch", EMovieScaleMode::Stretch }, + { "Fit", EMovieScaleMode::Fit }, + { "Fill", EMovieScaleMode::Fill } +}; + +enum class EUIScaleMode : uint32_t { Stretch, Edge, Centre }; + +CONFIG_DEFINE_ENUM_TEMPLATE(EUIScaleMode) +{ + { "Stretch", EUIScaleMode::Stretch }, + { "Edge", EUIScaleMode::Edge }, + { "Centre", EUIScaleMode::Centre }, + { "Center", EUIScaleMode::Centre } +}; diff --git a/UnleashedRecomp/game.cpp b/UnleashedRecomp/game.cpp index 74b4810..b491e52 100644 --- a/UnleashedRecomp/game.cpp +++ b/UnleashedRecomp/game.cpp @@ -73,7 +73,7 @@ PPC_FUNC(sub_82624308) { __imp__sub_82624308(ctx, base); - if (Config::ScoreBehaviour != ScoreBehaviour::CheckpointRetain) + if (Config::ScoreBehaviour != EScoreBehaviour::CheckpointRetain) return; auto pGameDocument = SWA::CGameDocument::GetInstance(); @@ -91,7 +91,7 @@ PPC_FUNC(sub_8245F048) { __imp__sub_8245F048(ctx, base); - if (Config::ScoreBehaviour != ScoreBehaviour::CheckpointRetain) + if (Config::ScoreBehaviour != EScoreBehaviour::CheckpointRetain) return; auto pGameDocument = SWA::CGameDocument::GetInstance(); @@ -212,7 +212,7 @@ void SetXButtonHomingMidAsmHook(PPCRegister& r30) PPC_FUNC_IMPL(__imp__sub_825197C0); PPC_FUNC(sub_825197C0) { - if (Config::Language == Language::Japanese) + if (Config::Language == ELanguage::Japanese) { ctx.r3.u64 = 0; return; diff --git a/UnleashedRecomp/gpu/video.cpp b/UnleashedRecomp/gpu/video.cpp index bfb5821..97841ac 100644 --- a/UnleashedRecomp/gpu/video.cpp +++ b/UnleashedRecomp/gpu/video.cpp @@ -561,7 +561,7 @@ static void CreateHostDevice() Window::Init(); - g_vulkan = Config::GraphicsAPI == GraphicsAPI::Vulkan; + g_vulkan = Config::GraphicsAPI == EGraphicsAPI::Vulkan; LoadShaderCache(); diff --git a/UnleashedRecomp/kernel/imports.cpp b/UnleashedRecomp/kernel/imports.cpp index 040d0d2..e073d9b 100644 --- a/UnleashedRecomp/kernel/imports.cpp +++ b/UnleashedRecomp/kernel/imports.cpp @@ -78,7 +78,7 @@ void XGetVideoMode() uint32_t XGetGameRegion() { // printf("!!! STUB !!! XGetGameRegion\n"); - if (Config::Language == Language::Japanese) + if (Config::Language == ELanguage::Japanese) return 0x0101; return 0x03FF; diff --git a/UnleashedRecomp/ui/window.cpp b/UnleashedRecomp/ui/window.cpp index 1b53a8e..c3fe0d9 100644 --- a/UnleashedRecomp/ui/window.cpp +++ b/UnleashedRecomp/ui/window.cpp @@ -79,7 +79,7 @@ void Window::Init() { /* TODO: move this since it'll have to change on soft reboot from the options menu. */ - auto title = Config::Language == Language::Japanese + auto title = Config::Language == ELanguage::Japanese ? "Sonic World Adventure" : "SONIC UNLEASHED";