cfg: Update preferred region data on-demand. (#7206)
This commit is contained in:
parent
68e6a2185d
commit
c0ecdb689d
|
@ -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,
|
void Java_org_citra_citra_1emu_utils_SystemSaveGame_load([[maybe_unused]] JNIEnv* env,
|
||||||
[[maybe_unused]] jobject obj) {
|
[[maybe_unused]] jobject obj) {
|
||||||
if (Core::System::GetInstance().IsPoweredOn()) {
|
|
||||||
cfg = Service::CFG::GetModule(Core::System::GetInstance());
|
cfg = Service::CFG::GetModule(Core::System::GetInstance());
|
||||||
} else {
|
|
||||||
cfg = std::make_shared<Service::CFG::Module>();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
jboolean Java_org_citra_citra_1emu_utils_SystemSaveGame_getIsSystemSetupNeeded(
|
jboolean Java_org_citra_citra_1emu_utils_SystemSaveGame_getIsSystemSetupNeeded(
|
||||||
|
|
|
@ -293,16 +293,11 @@ void ConfigureSystem::SetConfiguration() {
|
||||||
QTime time = QTime::fromMSecsSinceStartOfDay(static_cast<int>(time_offset * 1000));
|
QTime time = QTime::fromMSecsSinceStartOfDay(static_cast<int>(time_offset * 1000));
|
||||||
ui->edit_init_time_offset_time->setTime(time);
|
ui->edit_init_time_offset_time->setTime(time);
|
||||||
|
|
||||||
if (!enabled) {
|
|
||||||
cfg = Service::CFG::GetModule(system);
|
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<Service::CFG::Module>();
|
|
||||||
ReadSystemSettings();
|
ReadSystemSettings();
|
||||||
|
|
||||||
|
ui->group_system_settings->setEnabled(enabled);
|
||||||
|
if (enabled) {
|
||||||
ui->label_disable_info->hide();
|
ui->label_disable_info->hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -148,7 +148,6 @@ void DefaultKeyboard::Execute(const Frontend::KeyboardConfig& config_) {
|
||||||
SoftwareKeyboard::Execute(config_);
|
SoftwareKeyboard::Execute(config_);
|
||||||
|
|
||||||
auto cfg = Service::CFG::GetModule(Core::System::GetInstance());
|
auto cfg = Service::CFG::GetModule(Core::System::GetInstance());
|
||||||
ASSERT_MSG(cfg, "CFG Module missing!");
|
|
||||||
std::string username = Common::UTF16ToUTF8(cfg->GetUsername());
|
std::string username = Common::UTF16ToUTF8(cfg->GetUsername());
|
||||||
switch (this->config.button_config) {
|
switch (this->config.button_config) {
|
||||||
case ButtonConfig::None:
|
case ButtonConfig::None:
|
||||||
|
|
|
@ -1358,8 +1358,6 @@ void AppletManager::EnsureHomeMenuLoaded() {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto cfg = Service::CFG::GetModule(system);
|
auto cfg = Service::CFG::GetModule(system);
|
||||||
ASSERT_MSG(cfg, "CFG Module missing!");
|
|
||||||
|
|
||||||
auto menu_title_id = GetTitleIdForApplet(AppletId::HomeMenu, cfg->GetRegionValue());
|
auto menu_title_id = GetTitleIdForApplet(AppletId::HomeMenu, cfg->GetRegionValue());
|
||||||
auto process = NS::LaunchTitle(FS::MediaType::NAND, menu_title_id);
|
auto process = NS::LaunchTitle(FS::MediaType::NAND, menu_title_id);
|
||||||
if (!process) {
|
if (!process) {
|
||||||
|
|
|
@ -195,8 +195,6 @@ static u32 DecompressLZ11(const u8* in, u8* out) {
|
||||||
|
|
||||||
bool Module::LoadSharedFont() {
|
bool Module::LoadSharedFont() {
|
||||||
auto cfg = Service::CFG::GetModule(system);
|
auto cfg = Service::CFG::GetModule(system);
|
||||||
ASSERT_MSG(cfg, "CFG Module missing!");
|
|
||||||
|
|
||||||
u8 font_region_code;
|
u8 font_region_code;
|
||||||
switch (cfg->GetRegionValue()) {
|
switch (cfg->GetRegionValue()) {
|
||||||
case 4: // CHN
|
case 4: // CHN
|
||||||
|
|
|
@ -28,7 +28,9 @@
|
||||||
#include "core/hle/service/cfg/cfg_nor.h"
|
#include "core/hle/service/cfg/cfg_nor.h"
|
||||||
#include "core/hle/service/cfg/cfg_s.h"
|
#include "core/hle/service/cfg/cfg_s.h"
|
||||||
#include "core/hle/service/cfg/cfg_u.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)
|
SERIALIZE_EXPORT_IMPL(Service::CFG::Module)
|
||||||
|
|
||||||
namespace Service::CFG {
|
namespace Service::CFG {
|
||||||
|
@ -195,8 +197,10 @@ void Module::Interface::GetCountryCodeID(Kernel::HLERequestContext& ctx) {
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 Module::GetRegionValue() {
|
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 preferred_region_code;
|
||||||
|
}
|
||||||
|
|
||||||
return Settings::values.region_value.GetValue();
|
return Settings::values.region_value.GetValue();
|
||||||
}
|
}
|
||||||
|
@ -599,7 +603,7 @@ void Module::SaveMCUConfig() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Module::Module() {
|
Module::Module(Core::System& system_) : system(system_) {
|
||||||
LoadConfigNANDSaveFile();
|
LoadConfigNANDSaveFile();
|
||||||
LoadMCUConfig();
|
LoadMCUConfig();
|
||||||
// Check the config savegame EULA Version and update it to 0x7F7F if necessary
|
// Check the config savegame EULA Version and update it to 0x7F7F if necessary
|
||||||
|
@ -651,22 +655,25 @@ static std::tuple<u32 /*region*/, SystemLanguage> AdjustLanguageInfoBlock(
|
||||||
return {default_region, region_languages[default_region][0]};
|
return {default_region, region_languages[default_region][0]};
|
||||||
}
|
}
|
||||||
|
|
||||||
void Module::SetPreferredRegionCodes(std::span<const u32> region_codes) {
|
void Module::UpdatePreferredRegionCode() {
|
||||||
const SystemLanguage current_language = GetSystemLanguage();
|
if (!system.IsPoweredOn()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto preferred_regions = system.GetAppLoader().GetPreferredRegions();
|
||||||
|
const auto current_language = GetRawSystemLanguage();
|
||||||
const auto [region, adjusted_language] =
|
const auto [region, adjusted_language] =
|
||||||
AdjustLanguageInfoBlock(region_codes, current_language);
|
AdjustLanguageInfoBlock(preferred_regions, current_language);
|
||||||
|
|
||||||
preferred_region_code = region;
|
preferred_region_code = region;
|
||||||
LOG_INFO(Service_CFG, "Preferred region code set to {}", preferred_region_code);
|
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) {
|
if (current_language != adjusted_language) {
|
||||||
LOG_WARNING(Service_CFG, "System language {} does not fit the region. Adjusted to {}",
|
LOG_WARNING(Service_CFG, "System language {} does not fit the region. Adjusted to {}",
|
||||||
current_language, adjusted_language);
|
current_language, adjusted_language);
|
||||||
SetSystemLanguage(adjusted_language);
|
SetSystemLanguage(adjusted_language);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void Module::SetUsername(const std::u16string& name) {
|
void Module::SetUsername(const std::u16string& name) {
|
||||||
ASSERT(name.size() <= 10);
|
ASSERT(name.size() <= 10);
|
||||||
|
@ -705,6 +712,13 @@ void Module::SetSystemLanguage(SystemLanguage language) {
|
||||||
}
|
}
|
||||||
|
|
||||||
SystemLanguage Module::GetSystemLanguage() {
|
SystemLanguage Module::GetSystemLanguage() {
|
||||||
|
if (Settings::values.region_value.GetValue() == Settings::REGION_VALUE_AUTO_SELECT) {
|
||||||
|
UpdatePreferredRegionCode();
|
||||||
|
}
|
||||||
|
return GetRawSystemLanguage();
|
||||||
|
}
|
||||||
|
|
||||||
|
SystemLanguage Module::GetRawSystemLanguage() {
|
||||||
u8 block{};
|
u8 block{};
|
||||||
GetConfigBlock(LanguageBlockID, sizeof(block), AccessFlag::SystemRead, &block);
|
GetConfigBlock(LanguageBlockID, sizeof(block), AccessFlag::SystemRead, &block);
|
||||||
return static_cast<SystemLanguage>(block);
|
return static_cast<SystemLanguage>(block);
|
||||||
|
@ -810,15 +824,21 @@ bool Module::IsSystemSetupNeeded() {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Module> GetModule(Core::System& system) {
|
std::shared_ptr<Module> GetModule(Core::System& system) {
|
||||||
auto cfg = system.ServiceManager().GetService<Service::CFG::Module::Interface>("cfg:u");
|
if (system.IsPoweredOn()) {
|
||||||
if (!cfg)
|
auto cfg = system.ServiceManager().GetService<Module::Interface>("cfg:u");
|
||||||
return nullptr;
|
if (cfg) {
|
||||||
return cfg->GetModule();
|
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<Module>(system);
|
||||||
|
}
|
||||||
|
|
||||||
void InstallInterfaces(Core::System& system) {
|
void InstallInterfaces(Core::System& system) {
|
||||||
auto& service_manager = system.ServiceManager();
|
auto& service_manager = system.ServiceManager();
|
||||||
auto cfg = std::make_shared<Module>();
|
auto cfg = std::make_shared<Module>(system);
|
||||||
std::make_shared<CFG_I>(cfg)->InstallAsService(service_manager);
|
std::make_shared<CFG_I>(cfg)->InstallAsService(service_manager);
|
||||||
std::make_shared<CFG_S>(cfg)->InstallAsService(service_manager);
|
std::make_shared<CFG_S>(cfg)->InstallAsService(service_manager);
|
||||||
std::make_shared<CFG_U>(cfg)->InstallAsService(service_manager);
|
std::make_shared<CFG_U>(cfg)->InstallAsService(service_manager);
|
||||||
|
@ -826,15 +846,8 @@ void InstallInterfaces(Core::System& system) {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetConsoleIdHash(Core::System& system) {
|
std::string GetConsoleIdHash(Core::System& system) {
|
||||||
u64_le console_id{};
|
u64_le console_id = GetModule(system)->GetConsoleUniqueId();
|
||||||
std::array<u8, sizeof(console_id)> buffer;
|
std::array<u8, sizeof(console_id)> buffer;
|
||||||
if (system.IsPoweredOn()) {
|
|
||||||
auto cfg = GetModule(system);
|
|
||||||
ASSERT_MSG(cfg, "CFG Module missing!");
|
|
||||||
console_id = cfg->GetConsoleUniqueId();
|
|
||||||
} else {
|
|
||||||
console_id = std::make_unique<Service::CFG::Module>()->GetConsoleUniqueId();
|
|
||||||
}
|
|
||||||
std::memcpy(buffer.data(), &console_id, sizeof(console_id));
|
std::memcpy(buffer.data(), &console_id, sizeof(console_id));
|
||||||
|
|
||||||
std::array<u8, CryptoPP::SHA256::DIGESTSIZE> hash;
|
std::array<u8, CryptoPP::SHA256::DIGESTSIZE> hash;
|
||||||
|
|
|
@ -178,7 +178,7 @@ DECLARE_ENUM_FLAG_OPERATORS(AccessFlag);
|
||||||
|
|
||||||
class Module final {
|
class Module final {
|
||||||
public:
|
public:
|
||||||
Module();
|
Module(Core::System& system_);
|
||||||
~Module();
|
~Module();
|
||||||
|
|
||||||
class Interface : public ServiceFramework<Interface> {
|
class Interface : public ServiceFramework<Interface> {
|
||||||
|
@ -445,13 +445,6 @@ private:
|
||||||
public:
|
public:
|
||||||
u32 GetRegionValue();
|
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<const u32> region_codes);
|
|
||||||
|
|
||||||
// Utilities for frontend to set config data.
|
// Utilities for frontend to set config data.
|
||||||
// Note: UpdateConfigNANDSavegame should be called after making changes to config data.
|
// Note: UpdateConfigNANDSavegame should be called after making changes to config data.
|
||||||
|
|
||||||
|
@ -589,6 +582,11 @@ public:
|
||||||
void SaveMCUConfig();
|
void SaveMCUConfig();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void UpdatePreferredRegionCode();
|
||||||
|
SystemLanguage GetRawSystemLanguage();
|
||||||
|
|
||||||
|
Core::System& system;
|
||||||
|
|
||||||
static constexpr u32 CONFIG_SAVEFILE_SIZE = 0x8000;
|
static constexpr u32 CONFIG_SAVEFILE_SIZE = 0x8000;
|
||||||
std::array<u8, CONFIG_SAVEFILE_SIZE> cfg_config_file_buffer;
|
std::array<u8, CONFIG_SAVEFILE_SIZE> cfg_config_file_buffer;
|
||||||
std::unique_ptr<FileSys::ArchiveBackend> cfg_system_save_data_archive;
|
std::unique_ptr<FileSys::ArchiveBackend> cfg_system_save_data_archive;
|
||||||
|
@ -609,4 +607,5 @@ std::string GetConsoleIdHash(Core::System& system);
|
||||||
|
|
||||||
} // namespace Service::CFG
|
} // namespace Service::CFG
|
||||||
|
|
||||||
|
SERVICE_CONSTRUCT(Service::CFG::Module)
|
||||||
BOOST_CLASS_EXPORT_KEY(Service::CFG::Module)
|
BOOST_CLASS_EXPORT_KEY(Service::CFG::Module)
|
||||||
|
|
|
@ -100,7 +100,6 @@ void Module::Interface::GetMyScreenName(Kernel::HLERequestContext& ctx) {
|
||||||
IPC::RequestBuilder rb = rp.MakeBuilder(7, 0);
|
IPC::RequestBuilder rb = rp.MakeBuilder(7, 0);
|
||||||
|
|
||||||
auto cfg = Service::CFG::GetModule(frd->system);
|
auto cfg = Service::CFG::GetModule(frd->system);
|
||||||
ASSERT_MSG(cfg, "CFG Module missing!");
|
|
||||||
auto username = cfg->GetUsername();
|
auto username = cfg->GetUsername();
|
||||||
ASSERT_MSG(username.length() <= 10, "Username longer than expected!");
|
ASSERT_MSG(username.length() <= 10, "Username longer than expected!");
|
||||||
ScreenName screen_name{};
|
ScreenName screen_name{};
|
||||||
|
|
|
@ -91,6 +91,14 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual FileType GetFileType() = 0;
|
virtual FileType GetFileType() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the preferred region codes of this file
|
||||||
|
* @return A vector of the preferred region codes
|
||||||
|
*/
|
||||||
|
[[nodiscard]] virtual std::span<const u32> GetPreferredRegions() const {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load the application and return the created Process instance
|
* Load the application and return the created Process instance
|
||||||
* @param process The newly created process.
|
* @param process The newly created process.
|
||||||
|
|
|
@ -196,8 +196,7 @@ void AppLoader_NCCH::ParseRegionLockoutInfo(u64 program_id) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto cfg = Service::CFG::GetModule(Core::System::GetInstance());
|
preferred_regions.clear();
|
||||||
ASSERT_MSG(cfg, "CFG Module missing!");
|
|
||||||
|
|
||||||
std::vector<u8> smdh_buffer;
|
std::vector<u8> smdh_buffer;
|
||||||
if (ReadIcon(smdh_buffer) == ResultStatus::Success && smdh_buffer.size() >= sizeof(SMDH)) {
|
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));
|
std::memcpy(&smdh, smdh_buffer.data(), sizeof(SMDH));
|
||||||
u32 region_lockout = smdh.region_lockout;
|
u32 region_lockout = smdh.region_lockout;
|
||||||
constexpr u32 REGION_COUNT = 7;
|
constexpr u32 REGION_COUNT = 7;
|
||||||
std::vector<u32> regions;
|
|
||||||
for (u32 region = 0; region < REGION_COUNT; ++region) {
|
for (u32 region = 0; region < REGION_COUNT; ++region) {
|
||||||
if (region_lockout & 1) {
|
if (region_lockout & 1) {
|
||||||
regions.push_back(region);
|
preferred_regions.push_back(region);
|
||||||
}
|
}
|
||||||
region_lockout >>= 1;
|
region_lockout >>= 1;
|
||||||
}
|
}
|
||||||
cfg->SetPreferredRegionCodes(regions);
|
|
||||||
} else {
|
} else {
|
||||||
const auto region = Core::GetSystemTitleRegion(program_id);
|
const auto region = Core::GetSystemTitleRegion(program_id);
|
||||||
if (region.has_value()) {
|
if (region.has_value()) {
|
||||||
const std::array regions{region.value()};
|
preferred_regions.push_back(region.value());
|
||||||
cfg->SetPreferredRegionCodes(regions);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,10 @@ public:
|
||||||
return IdentifyType(file);
|
return IdentifyType(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] std::span<const u32> GetPreferredRegions() const override {
|
||||||
|
return preferred_regions;
|
||||||
|
}
|
||||||
|
|
||||||
ResultStatus Load(std::shared_ptr<Kernel::Process>& process) override;
|
ResultStatus Load(std::shared_ptr<Kernel::Process>& process) override;
|
||||||
|
|
||||||
std::pair<std::optional<u32>, ResultStatus> LoadCoreVersion() override;
|
std::pair<std::optional<u32>, ResultStatus> LoadCoreVersion() override;
|
||||||
|
@ -87,6 +91,8 @@ private:
|
||||||
FileSys::NCCHContainer update_ncch;
|
FileSys::NCCHContainer update_ncch;
|
||||||
FileSys::NCCHContainer* overlay_ncch;
|
FileSys::NCCHContainer* overlay_ncch;
|
||||||
|
|
||||||
|
std::vector<u32> preferred_regions;
|
||||||
|
|
||||||
std::string filepath;
|
std::string filepath;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Reference in New Issue