diff --git a/src/android/app/src/main/jni/system_save_game.cpp b/src/android/app/src/main/jni/system_save_game.cpp index 003ad1b638..bdf97c8bcd 100644 --- a/src/android/app/src/main/jni/system_save_game.cpp +++ b/src/android/app/src/main/jni/system_save_game.cpp @@ -19,11 +19,7 @@ void Java_org_citra_citra_1emu_utils_SystemSaveGame_save([[maybe_unused]] JNIEnv void Java_org_citra_citra_1emu_utils_SystemSaveGame_load([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jobject obj) { - if (Core::System::GetInstance().IsPoweredOn()) { - cfg = Service::CFG::GetModule(Core::System::GetInstance()); - } else { - cfg = std::make_shared(); - } + cfg = Service::CFG::GetModule(Core::System::GetInstance()); } jboolean Java_org_citra_citra_1emu_utils_SystemSaveGame_getIsSystemSetupNeeded( diff --git a/src/citra_qt/configuration/configure_system.cpp b/src/citra_qt/configuration/configure_system.cpp index f0ae442d63..ebf2eb6dd7 100644 --- a/src/citra_qt/configuration/configure_system.cpp +++ b/src/citra_qt/configuration/configure_system.cpp @@ -293,16 +293,11 @@ void ConfigureSystem::SetConfiguration() { QTime time = QTime::fromMSecsSinceStartOfDay(static_cast(time_offset * 1000)); ui->edit_init_time_offset_time->setTime(time); - if (!enabled) { - cfg = Service::CFG::GetModule(system); - ASSERT_MSG(cfg, "CFG Module missing!"); - ReadSystemSettings(); - ui->group_system_settings->setEnabled(false); - } else { - // This tab is enabled only when game is not running (i.e. all service are not initialized). - cfg = std::make_shared(); - ReadSystemSettings(); + cfg = Service::CFG::GetModule(system); + ReadSystemSettings(); + ui->group_system_settings->setEnabled(enabled); + if (enabled) { ui->label_disable_info->hide(); } diff --git a/src/core/frontend/applets/swkbd.cpp b/src/core/frontend/applets/swkbd.cpp index 12f8b2e25e..51f21cda6f 100644 --- a/src/core/frontend/applets/swkbd.cpp +++ b/src/core/frontend/applets/swkbd.cpp @@ -148,7 +148,6 @@ void DefaultKeyboard::Execute(const Frontend::KeyboardConfig& config_) { SoftwareKeyboard::Execute(config_); auto cfg = Service::CFG::GetModule(Core::System::GetInstance()); - ASSERT_MSG(cfg, "CFG Module missing!"); std::string username = Common::UTF16ToUTF8(cfg->GetUsername()); switch (this->config.button_config) { case ButtonConfig::None: diff --git a/src/core/hle/service/apt/applet_manager.cpp b/src/core/hle/service/apt/applet_manager.cpp index 36f4012074..db55a6d105 100644 --- a/src/core/hle/service/apt/applet_manager.cpp +++ b/src/core/hle/service/apt/applet_manager.cpp @@ -1358,8 +1358,6 @@ void AppletManager::EnsureHomeMenuLoaded() { } auto cfg = Service::CFG::GetModule(system); - ASSERT_MSG(cfg, "CFG Module missing!"); - auto menu_title_id = GetTitleIdForApplet(AppletId::HomeMenu, cfg->GetRegionValue()); auto process = NS::LaunchTitle(FS::MediaType::NAND, menu_title_id); if (!process) { diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp index 0d6505ca2c..7542308245 100644 --- a/src/core/hle/service/apt/apt.cpp +++ b/src/core/hle/service/apt/apt.cpp @@ -195,8 +195,6 @@ static u32 DecompressLZ11(const u8* in, u8* out) { bool Module::LoadSharedFont() { auto cfg = Service::CFG::GetModule(system); - ASSERT_MSG(cfg, "CFG Module missing!"); - u8 font_region_code; switch (cfg->GetRegionValue()) { case 4: // CHN diff --git a/src/core/hle/service/cfg/cfg.cpp b/src/core/hle/service/cfg/cfg.cpp index 6d42c5918f..52b9820431 100644 --- a/src/core/hle/service/cfg/cfg.cpp +++ b/src/core/hle/service/cfg/cfg.cpp @@ -28,7 +28,9 @@ #include "core/hle/service/cfg/cfg_nor.h" #include "core/hle/service/cfg/cfg_s.h" #include "core/hle/service/cfg/cfg_u.h" +#include "core/loader/loader.h" +SERVICE_CONSTRUCT_IMPL(Service::CFG::Module) SERIALIZE_EXPORT_IMPL(Service::CFG::Module) namespace Service::CFG { @@ -195,8 +197,10 @@ void Module::Interface::GetCountryCodeID(Kernel::HLERequestContext& ctx) { } u32 Module::GetRegionValue() { - if (Settings::values.region_value.GetValue() == Settings::REGION_VALUE_AUTO_SELECT) + if (Settings::values.region_value.GetValue() == Settings::REGION_VALUE_AUTO_SELECT) { + UpdatePreferredRegionCode(); return preferred_region_code; + } return Settings::values.region_value.GetValue(); } @@ -599,7 +603,7 @@ void Module::SaveMCUConfig() { } } -Module::Module() { +Module::Module(Core::System& system_) : system(system_) { LoadConfigNANDSaveFile(); LoadMCUConfig(); // Check the config savegame EULA Version and update it to 0x7F7F if necessary @@ -651,20 +655,23 @@ static std::tuple AdjustLanguageInfoBlock( return {default_region, region_languages[default_region][0]}; } -void Module::SetPreferredRegionCodes(std::span region_codes) { - const SystemLanguage current_language = GetSystemLanguage(); +void Module::UpdatePreferredRegionCode() { + if (!system.IsPoweredOn()) { + return; + } + + const auto preferred_regions = system.GetAppLoader().GetPreferredRegions(); + const auto current_language = GetRawSystemLanguage(); const auto [region, adjusted_language] = - AdjustLanguageInfoBlock(region_codes, current_language); + AdjustLanguageInfoBlock(preferred_regions, current_language); preferred_region_code = region; LOG_INFO(Service_CFG, "Preferred region code set to {}", preferred_region_code); - if (Settings::values.region_value.GetValue() == Settings::REGION_VALUE_AUTO_SELECT) { - if (current_language != adjusted_language) { - LOG_WARNING(Service_CFG, "System language {} does not fit the region. Adjusted to {}", - current_language, adjusted_language); - SetSystemLanguage(adjusted_language); - } + if (current_language != adjusted_language) { + LOG_WARNING(Service_CFG, "System language {} does not fit the region. Adjusted to {}", + current_language, adjusted_language); + SetSystemLanguage(adjusted_language); } } @@ -705,6 +712,13 @@ void Module::SetSystemLanguage(SystemLanguage language) { } SystemLanguage Module::GetSystemLanguage() { + if (Settings::values.region_value.GetValue() == Settings::REGION_VALUE_AUTO_SELECT) { + UpdatePreferredRegionCode(); + } + return GetRawSystemLanguage(); +} + +SystemLanguage Module::GetRawSystemLanguage() { u8 block{}; GetConfigBlock(LanguageBlockID, sizeof(block), AccessFlag::SystemRead, &block); return static_cast(block); @@ -810,15 +824,21 @@ bool Module::IsSystemSetupNeeded() { } std::shared_ptr GetModule(Core::System& system) { - auto cfg = system.ServiceManager().GetService("cfg:u"); - if (!cfg) - return nullptr; - return cfg->GetModule(); + if (system.IsPoweredOn()) { + auto cfg = system.ServiceManager().GetService("cfg:u"); + if (cfg) { + return cfg->GetModule(); + } + } + + // If the system is not running or the module is missing, + // create an ad-hoc module instance to read data from. + return std::make_shared(system); } void InstallInterfaces(Core::System& system) { auto& service_manager = system.ServiceManager(); - auto cfg = std::make_shared(); + auto cfg = std::make_shared(system); std::make_shared(cfg)->InstallAsService(service_manager); std::make_shared(cfg)->InstallAsService(service_manager); std::make_shared(cfg)->InstallAsService(service_manager); @@ -826,15 +846,8 @@ void InstallInterfaces(Core::System& system) { } std::string GetConsoleIdHash(Core::System& system) { - u64_le console_id{}; + u64_le console_id = GetModule(system)->GetConsoleUniqueId(); std::array buffer; - if (system.IsPoweredOn()) { - auto cfg = GetModule(system); - ASSERT_MSG(cfg, "CFG Module missing!"); - console_id = cfg->GetConsoleUniqueId(); - } else { - console_id = std::make_unique()->GetConsoleUniqueId(); - } std::memcpy(buffer.data(), &console_id, sizeof(console_id)); std::array hash; diff --git a/src/core/hle/service/cfg/cfg.h b/src/core/hle/service/cfg/cfg.h index bff4021b4d..4ac9b3e143 100644 --- a/src/core/hle/service/cfg/cfg.h +++ b/src/core/hle/service/cfg/cfg.h @@ -178,7 +178,7 @@ DECLARE_ENUM_FLAG_OPERATORS(AccessFlag); class Module final { public: - Module(); + Module(Core::System& system_); ~Module(); class Interface : public ServiceFramework { @@ -445,13 +445,6 @@ private: public: u32 GetRegionValue(); - /** - * Set the region codes preferred by the game so that CFG will adjust to it when the region - * setting is auto. - * @param region_codes the preferred region codes to set - */ - void SetPreferredRegionCodes(std::span region_codes); - // Utilities for frontend to set config data. // Note: UpdateConfigNANDSavegame should be called after making changes to config data. @@ -589,6 +582,11 @@ public: void SaveMCUConfig(); private: + void UpdatePreferredRegionCode(); + SystemLanguage GetRawSystemLanguage(); + + Core::System& system; + static constexpr u32 CONFIG_SAVEFILE_SIZE = 0x8000; std::array cfg_config_file_buffer; std::unique_ptr cfg_system_save_data_archive; @@ -609,4 +607,5 @@ std::string GetConsoleIdHash(Core::System& system); } // namespace Service::CFG +SERVICE_CONSTRUCT(Service::CFG::Module) BOOST_CLASS_EXPORT_KEY(Service::CFG::Module) diff --git a/src/core/hle/service/frd/frd.cpp b/src/core/hle/service/frd/frd.cpp index bae62a30e2..c8b7d46a45 100644 --- a/src/core/hle/service/frd/frd.cpp +++ b/src/core/hle/service/frd/frd.cpp @@ -100,7 +100,6 @@ void Module::Interface::GetMyScreenName(Kernel::HLERequestContext& ctx) { IPC::RequestBuilder rb = rp.MakeBuilder(7, 0); auto cfg = Service::CFG::GetModule(frd->system); - ASSERT_MSG(cfg, "CFG Module missing!"); auto username = cfg->GetUsername(); ASSERT_MSG(username.length() <= 10, "Username longer than expected!"); ScreenName screen_name{}; diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h index f21c11fa62..deee7c230a 100644 --- a/src/core/loader/loader.h +++ b/src/core/loader/loader.h @@ -91,6 +91,14 @@ public: */ virtual FileType GetFileType() = 0; + /** + * Returns the preferred region codes of this file + * @return A vector of the preferred region codes + */ + [[nodiscard]] virtual std::span GetPreferredRegions() const { + return {}; + } + /** * Load the application and return the created Process instance * @param process The newly created process. diff --git a/src/core/loader/ncch.cpp b/src/core/loader/ncch.cpp index 9392c1fb84..04dcf42ce4 100644 --- a/src/core/loader/ncch.cpp +++ b/src/core/loader/ncch.cpp @@ -196,8 +196,7 @@ void AppLoader_NCCH::ParseRegionLockoutInfo(u64 program_id) { return; } - auto cfg = Service::CFG::GetModule(Core::System::GetInstance()); - ASSERT_MSG(cfg, "CFG Module missing!"); + preferred_regions.clear(); std::vector smdh_buffer; if (ReadIcon(smdh_buffer) == ResultStatus::Success && smdh_buffer.size() >= sizeof(SMDH)) { @@ -205,19 +204,16 @@ void AppLoader_NCCH::ParseRegionLockoutInfo(u64 program_id) { std::memcpy(&smdh, smdh_buffer.data(), sizeof(SMDH)); u32 region_lockout = smdh.region_lockout; constexpr u32 REGION_COUNT = 7; - std::vector regions; for (u32 region = 0; region < REGION_COUNT; ++region) { if (region_lockout & 1) { - regions.push_back(region); + preferred_regions.push_back(region); } region_lockout >>= 1; } - cfg->SetPreferredRegionCodes(regions); } else { const auto region = Core::GetSystemTitleRegion(program_id); if (region.has_value()) { - const std::array regions{region.value()}; - cfg->SetPreferredRegionCodes(regions); + preferred_regions.push_back(region.value()); } } } diff --git a/src/core/loader/ncch.h b/src/core/loader/ncch.h index b240302de6..57ec25c5ba 100644 --- a/src/core/loader/ncch.h +++ b/src/core/loader/ncch.h @@ -30,6 +30,10 @@ public: return IdentifyType(file); } + [[nodiscard]] std::span GetPreferredRegions() const override { + return preferred_regions; + } + ResultStatus Load(std::shared_ptr& process) override; std::pair, ResultStatus> LoadCoreVersion() override; @@ -87,6 +91,8 @@ private: FileSys::NCCHContainer update_ncch; FileSys::NCCHContainer* overlay_ncch; + std::vector preferred_regions; + std::string filepath; };