diff --git a/src/citra_qt/configuration/configure_system.cpp b/src/citra_qt/configuration/configure_system.cpp index dd4b5caff..398ecb7c7 100644 --- a/src/citra_qt/configuration/configure_system.cpp +++ b/src/citra_qt/configuration/configure_system.cpp @@ -42,22 +42,16 @@ void ConfigureSystem::setConfiguration() { enabled = !Core::System::GetInstance().IsPoweredOn(); if (!enabled) { + cfg = Service::CFG::GetCurrentModule(); 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). // Temporarily register archive types and load the config savegame file to memory. Service::FS::RegisterArchiveTypes(); - ResultCode result = Service::CFG::LoadConfigNANDSaveFile(); + cfg = std::make_shared(); Service::FS::UnregisterArchiveTypes(); - if (result.IsError()) { - ui->label_disable_info->setText(tr("Failed to load system settings data.")); - ui->group_system_settings->setEnabled(false); - enabled = false; - return; - } - ReadSystemSettings(); ui->label_disable_info->hide(); } @@ -65,14 +59,14 @@ void ConfigureSystem::setConfiguration() { void ConfigureSystem::ReadSystemSettings() { // set username - username = Service::CFG::GetUsername(); + username = cfg->GetUsername(); // TODO(wwylele): Use this when we move to Qt 5.5 // ui->edit_username->setText(QString::fromStdU16String(username)); ui->edit_username->setText( QString::fromUtf16(reinterpret_cast(username.data()))); // set birthday - std::tie(birthmonth, birthday) = Service::CFG::GetBirthday(); + std::tie(birthmonth, birthday) = cfg->GetBirthday(); ui->combo_birthmonth->setCurrentIndex(birthmonth - 1); updateBirthdayComboBox( birthmonth - @@ -80,15 +74,15 @@ void ConfigureSystem::ReadSystemSettings() { ui->combo_birthday->setCurrentIndex(birthday - 1); // set system language - language_index = Service::CFG::GetSystemLanguage(); + language_index = cfg->GetSystemLanguage(); ui->combo_language->setCurrentIndex(language_index); // set sound output mode - sound_index = Service::CFG::GetSoundOutputMode(); + sound_index = cfg->GetSoundOutputMode(); ui->combo_sound->setCurrentIndex(sound_index); // set the console id - u64 console_id = Service::CFG::GetConsoleUniqueId(); + u64 console_id = cfg->GetConsoleUniqueId(); ui->label_console_id->setText( tr("Console ID: 0x%1").arg(QString::number(console_id, 16).toUpper())); } @@ -105,7 +99,7 @@ void ConfigureSystem::applyConfiguration() { std::u16string new_username( reinterpret_cast(ui->edit_username->text().utf16())); if (new_username != username) { - Service::CFG::SetUsername(new_username); + cfg->SetUsername(new_username); modified = true; } @@ -113,27 +107,27 @@ void ConfigureSystem::applyConfiguration() { int new_birthmonth = ui->combo_birthmonth->currentIndex() + 1; int new_birthday = ui->combo_birthday->currentIndex() + 1; if (birthmonth != new_birthmonth || birthday != new_birthday) { - Service::CFG::SetBirthday(new_birthmonth, new_birthday); + cfg->SetBirthday(new_birthmonth, new_birthday); modified = true; } // apply language int new_language = ui->combo_language->currentIndex(); if (language_index != new_language) { - Service::CFG::SetSystemLanguage(static_cast(new_language)); + cfg->SetSystemLanguage(static_cast(new_language)); modified = true; } // apply sound int new_sound = ui->combo_sound->currentIndex(); if (sound_index != new_sound) { - Service::CFG::SetSoundOutputMode(static_cast(new_sound)); + cfg->SetSoundOutputMode(static_cast(new_sound)); modified = true; } // update the config savegame if any item is modified. if (modified) - Service::CFG::UpdateConfigNANDSavegame(); + cfg->UpdateConfigNANDSavegame(); } void ConfigureSystem::updateBirthdayComboBox(int birthmonth_index) { @@ -173,9 +167,9 @@ void ConfigureSystem::refreshConsoleID() { return; u32 random_number; u64 console_id; - Service::CFG::GenerateConsoleUniqueId(random_number, console_id); - Service::CFG::SetConsoleUniqueId(random_number, console_id); - Service::CFG::UpdateConfigNANDSavegame(); + cfg->GenerateConsoleUniqueId(random_number, console_id); + cfg->SetConsoleUniqueId(random_number, console_id); + cfg->UpdateConfigNANDSavegame(); ui->label_console_id->setText("Console ID: 0x" + QString::number(console_id, 16).toUpper()); } diff --git a/src/citra_qt/configuration/configure_system.h b/src/citra_qt/configuration/configure_system.h index 094887791..47542b062 100644 --- a/src/citra_qt/configuration/configure_system.h +++ b/src/citra_qt/configuration/configure_system.h @@ -11,6 +11,12 @@ namespace Ui { class ConfigureSystem; } +namespace Service { +namespace CFG { +class Module; +} // namespace CFG +} // namespace Service + class ConfigureSystem : public QWidget { Q_OBJECT @@ -32,6 +38,7 @@ private: std::unique_ptr ui; bool enabled; + std::shared_ptr cfg; std::u16string username; int birthmonth, birthday; int language_index; diff --git a/src/core/hle/service/apt/applet_manager.cpp b/src/core/hle/service/apt/applet_manager.cpp index d8a6d79b9..fafd73bb4 100644 --- a/src/core/hle/service/apt/applet_manager.cpp +++ b/src/core/hle/service/apt/applet_manager.cpp @@ -79,7 +79,7 @@ static u64 GetTitleIdForApplet(AppletId id) { ASSERT_MSG(itr != applet_titleids.end(), "Unknown applet id 0x%03X", static_cast(id)); - return itr->title_ids[CFG::GetRegionValue()]; + return itr->title_ids[CFG::GetCurrentModule()->GetRegionValue()]; } AppletManager::AppletSlotData* AppletManager::GetAppletSlotData(AppletId id) { diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp index 240ff91e9..28f358b4b 100644 --- a/src/core/hle/service/apt/apt.cpp +++ b/src/core/hle/service/apt/apt.cpp @@ -103,7 +103,7 @@ static u32 DecompressLZ11(const u8* in, u8* out) { bool Module::LoadSharedFont() { u8 font_region_code; - switch (CFG::GetRegionValue()) { + switch (CFG::GetCurrentModule()->GetRegionValue()) { case 4: // CHN font_region_code = 2; break; diff --git a/src/core/hle/service/cfg/cfg.cpp b/src/core/hle/service/cfg/cfg.cpp index 3c4f24770..a5e7df9b4 100644 --- a/src/core/hle/service/cfg/cfg.cpp +++ b/src/core/hle/service/cfg/cfg.cpp @@ -3,7 +3,6 @@ // Refer to the license.txt file included. #include -#include #include #include #include "common/file_util.h" @@ -13,7 +12,6 @@ #include "core/file_sys/archive_systemsavedata.h" #include "core/file_sys/errors.h" #include "core/file_sys/file_backend.h" -#include "core/hle/ipc.h" #include "core/hle/ipc_helpers.h" #include "core/hle/result.h" #include "core/hle/service/cfg/cfg.h" @@ -21,9 +19,6 @@ #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/hle/service/fs/archive.h" -#include "core/hle/service/service.h" -#include "core/memory.h" #include "core/settings.h" namespace Service { @@ -113,35 +108,44 @@ static const std::array STEREO_CAMERA_SETTINGS = { static_assert(sizeof(STEREO_CAMERA_SETTINGS) == 0x20, "STEREO_CAMERA_SETTINGS must be exactly 0x20 bytes"); -static const u32 CONFIG_SAVEFILE_SIZE = 0x8000; -static std::array cfg_config_file_buffer; - -static Service::FS::ArchiveHandle cfg_system_save_data_archive; static const std::vector cfg_system_savedata_id = { 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x01, 0x00, }; -static u32 preferred_region_code = 0; +static std::weak_ptr current_cfg; -void GetCountryCodeString(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - u32 country_code_id = cmd_buff[1]; +std::shared_ptr GetCurrentModule() { + auto cfg = current_cfg.lock(); + ASSERT_MSG(cfg, "No CFG module running!"); + return cfg; +} +Module::Interface::Interface(std::shared_ptr cfg, const char* name, u32 max_session) + : ServiceFramework(name, max_session), cfg(std::move(cfg)) {} + +Module::Interface::~Interface() = default; + +void Module::Interface::GetCountryCodeString(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x09, 1, 0); + u16 country_code_id = rp.Pop(); + + IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); if (country_code_id >= country_codes.size() || 0 == country_codes[country_code_id]) { LOG_ERROR(Service_CFG, "requested country code id=%d is invalid", country_code_id); - cmd_buff[1] = ResultCode(ErrorDescription::NotFound, ErrorModule::Config, - ErrorSummary::WrongArgument, ErrorLevel::Permanent) - .raw; + rb.Push(ResultCode(ErrorDescription::NotFound, ErrorModule::Config, + ErrorSummary::WrongArgument, ErrorLevel::Permanent)); + rb.Skip(1, false); return; } - cmd_buff[1] = 0; - cmd_buff[2] = country_codes[country_code_id]; + rb.Push(RESULT_SUCCESS); + // the real CFG service copies only three bytes (including the null-terminator) here + rb.Push(country_codes[country_code_id]); } -void GetCountryCodeID(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - u16 country_code = static_cast(cmd_buff[1]); +void Module::Interface::GetCountryCodeID(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x0A, 1, 0); + u16 country_code = rp.Pop(); u16 country_code_id = 0; // The following algorithm will fail if the first country code isn't 0. @@ -154,42 +158,43 @@ void GetCountryCodeID(Service::Interface* self) { } } + IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); if (0 == country_code_id) { LOG_ERROR(Service_CFG, "requested country code name=%c%c is invalid", country_code & 0xff, country_code >> 8); - cmd_buff[1] = ResultCode(ErrorDescription::NotFound, ErrorModule::Config, - ErrorSummary::WrongArgument, ErrorLevel::Permanent) - .raw; - cmd_buff[2] = 0xFFFF; + rb.Push(ResultCode(ErrorDescription::NotFound, ErrorModule::Config, + ErrorSummary::WrongArgument, ErrorLevel::Permanent)); + rb.Push(0x00FF); return; } - cmd_buff[1] = 0; - cmd_buff[2] = country_code_id; + rb.Push(RESULT_SUCCESS); + rb.Push(country_code_id); } -u32 GetRegionValue() { +u32 Module::GetRegionValue() { if (Settings::values.region_value == Settings::REGION_VALUE_AUTO_SELECT) return preferred_region_code; return Settings::values.region_value; } -void SecureInfoGetRegion(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); +void Module::Interface::SecureInfoGetRegion(Kernel::HLERequestContext& ctx, u16 id) { + IPC::RequestParser rp(ctx, id, 0, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; - cmd_buff[2] = GetRegionValue(); + IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); + rb.Push(RESULT_SUCCESS); + rb.Push(cfg->GetRegionValue()); } -void GenHashConsoleUnique(Service::Interface* self) { - IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x03, 1, 0); +void Module::Interface::GenHashConsoleUnique(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x03, 1, 0); const u32 app_id_salt = rp.Pop() & 0x000FFFFF; IPC::RequestBuilder rb = rp.MakeBuilder(3, 0); std::array buffer; - const ResultCode result = GetConfigInfoBlock(ConsoleUniqueID2BlockID, 8, 2, buffer.data()); + const ResultCode result = cfg->GetConfigInfoBlock(ConsoleUniqueID2BlockID, 8, 2, buffer.data()); rb.Push(result); if (result.IsSuccess()) { std::memcpy(&buffer[8], &app_id_salt, sizeof(u32)); @@ -208,105 +213,94 @@ void GenHashConsoleUnique(Service::Interface* self) { LOG_DEBUG(Service_CFG, "called app_id_salt=0x%X", app_id_salt); } -void GetRegionCanadaUSA(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); +void Module::Interface::GetRegionCanadaUSA(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x04, 0, 0); + IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); - cmd_buff[1] = RESULT_SUCCESS.raw; + rb.Push(RESULT_SUCCESS); u8 canada_or_usa = 1; - if (canada_or_usa == GetRegionValue()) { - cmd_buff[2] = 1; + if (canada_or_usa == cfg->GetRegionValue()) { + rb.Push(true); } else { - cmd_buff[2] = 0; + rb.Push(false); } } -void GetSystemModel(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); +void Module::Interface::GetSystemModel(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x05, 0, 0); + IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); u32 data; // TODO(Subv): Find out the correct error codes - cmd_buff[1] = - Service::CFG::GetConfigInfoBlock(ConsoleModelBlockID, 4, 0x8, reinterpret_cast(&data)) - .raw; - cmd_buff[2] = data & 0xFF; + rb.Push(cfg->GetConfigInfoBlock(ConsoleModelBlockID, 4, 0x8, reinterpret_cast(&data))); + rb.Push(data & 0xFF); } -void GetModelNintendo2DS(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); +void Module::Interface::GetModelNintendo2DS(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x06, 0, 0); + IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); u32 data; // TODO(Subv): Find out the correct error codes - cmd_buff[1] = - Service::CFG::GetConfigInfoBlock(ConsoleModelBlockID, 4, 0x8, reinterpret_cast(&data)) - .raw; - + rb.Push(cfg->GetConfigInfoBlock(ConsoleModelBlockID, 4, 0x8, reinterpret_cast(&data))); u8 model = data & 0xFF; - if (model == Service::CFG::NINTENDO_2DS) - cmd_buff[2] = 0; - else - cmd_buff[2] = 1; + rb.Push(model != Service::CFG::NINTENDO_2DS); } -void GetConfigInfoBlk2(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - u32 size = cmd_buff[1]; - u32 block_id = cmd_buff[2]; - VAddr data_pointer = cmd_buff[4]; +void Module::Interface::GetConfigInfoBlk2(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x01, 2, 2); + u32 size = rp.Pop(); + u32 block_id = rp.Pop(); + auto& buffer = rp.PopMappedBuffer(); - if (!Memory::IsValidVirtualAddress(data_pointer)) { - cmd_buff[1] = -1; // TODO(Subv): Find the right error code - return; - } + IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); + std::vector data(size); + rb.Push(cfg->GetConfigInfoBlock(block_id, size, 0x2, data.data())); + buffer.Write(data.data(), 0, data.size()); + rb.PushMappedBuffer(buffer); +} + +void Module::Interface::GetConfigInfoBlk8(Kernel::HLERequestContext& ctx, u16 id) { + IPC::RequestParser rp(ctx, id, 2, 2); + u32 size = rp.Pop(); + u32 block_id = rp.Pop(); + auto& buffer = rp.PopMappedBuffer(); + + IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); + std::vector data(size); + rb.Push(cfg->GetConfigInfoBlock(block_id, size, 0x8, data.data())); + buffer.Write(data.data(), 0, data.size()); + rb.PushMappedBuffer(buffer); +} + +void Module::Interface::SetConfigInfoBlk4(Kernel::HLERequestContext& ctx, u16 id) { + IPC::RequestParser rp(ctx, id, 2, 2); + u32 block_id = rp.Pop(); + u32 size = rp.Pop(); + auto& buffer = rp.PopMappedBuffer(); std::vector data(size); - cmd_buff[1] = Service::CFG::GetConfigInfoBlock(block_id, size, 0x2, data.data()).raw; - Memory::WriteBlock(data_pointer, data.data(), data.size()); + buffer.Read(data.data(), 0, data.size()); + + IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); + rb.Push(cfg->SetConfigInfoBlock(block_id, size, 0x4, data.data())); + rb.PushMappedBuffer(buffer); } -void GetConfigInfoBlk8(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - u32 size = cmd_buff[1]; - u32 block_id = cmd_buff[2]; - VAddr data_pointer = cmd_buff[4]; - - if (!Memory::IsValidVirtualAddress(data_pointer)) { - cmd_buff[1] = -1; // TODO(Subv): Find the right error code - return; - } - - std::vector data(size); - cmd_buff[1] = Service::CFG::GetConfigInfoBlock(block_id, size, 0x8, data.data()).raw; - Memory::WriteBlock(data_pointer, data.data(), data.size()); +void Module::Interface::UpdateConfigNANDSavegame(Kernel::HLERequestContext& ctx, u16 id) { + IPC::RequestParser rp(ctx, id, 0, 0); + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); + rb.Push(cfg->UpdateConfigNANDSavegame()); } -void SetConfigInfoBlk4(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - u32 block_id = cmd_buff[1]; - u32 size = cmd_buff[2]; - VAddr data_pointer = cmd_buff[4]; - - if (!Memory::IsValidVirtualAddress(data_pointer)) { - cmd_buff[1] = -1; // TODO(Subv): Find the right error code - return; - } - - std::vector data(size); - Memory::ReadBlock(data_pointer, data.data(), data.size()); - cmd_buff[1] = Service::CFG::SetConfigInfoBlock(block_id, size, 0x4, data.data()).raw; +void Module::Interface::FormatConfig(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x0806, 0, 0); + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); + rb.Push(cfg->FormatConfig()); } -void UpdateConfigNANDSavegame(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - cmd_buff[1] = Service::CFG::UpdateConfigNANDSavegame().raw; -} - -void FormatConfig(Service::Interface* self) { - u32* cmd_buff = Kernel::GetCommandBuffer(); - cmd_buff[1] = Service::CFG::FormatConfig().raw; -} - -static ResultVal GetConfigInfoBlockPointer(u32 block_id, u32 size, u32 flag) { +ResultVal Module::GetConfigInfoBlockPointer(u32 block_id, u32 size, u32 flag) { // Read the header SaveFileConfig* config = reinterpret_cast(cfg_config_file_buffer.data()); @@ -346,7 +340,7 @@ static ResultVal GetConfigInfoBlockPointer(u32 block_id, u32 size, u32 fl return MakeResult(pointer); } -ResultCode GetConfigInfoBlock(u32 block_id, u32 size, u32 flag, void* output) { +ResultCode Module::GetConfigInfoBlock(u32 block_id, u32 size, u32 flag, void* output) { void* pointer; CASCADE_RESULT(pointer, GetConfigInfoBlockPointer(block_id, size, flag)); memcpy(output, pointer, size); @@ -354,14 +348,14 @@ ResultCode GetConfigInfoBlock(u32 block_id, u32 size, u32 flag, void* output) { return RESULT_SUCCESS; } -ResultCode SetConfigInfoBlock(u32 block_id, u32 size, u32 flag, const void* input) { +ResultCode Module::SetConfigInfoBlock(u32 block_id, u32 size, u32 flag, const void* input) { void* pointer; CASCADE_RESULT(pointer, GetConfigInfoBlockPointer(block_id, size, flag)); memcpy(pointer, input, size); return RESULT_SUCCESS; } -ResultCode CreateConfigInfoBlk(u32 block_id, u16 size, u16 flags, const void* data) { +ResultCode Module::CreateConfigInfoBlk(u32 block_id, u16 size, u16 flags, const void* data) { SaveFileConfig* config = reinterpret_cast(cfg_config_file_buffer.data()); if (config->total_entries >= CONFIG_FILE_MAX_BLOCK_ENTRIES) return ResultCode(-1); // TODO(Subv): Find the right error code @@ -393,12 +387,12 @@ ResultCode CreateConfigInfoBlk(u32 block_id, u16 size, u16 flags, const void* da return RESULT_SUCCESS; } -ResultCode DeleteConfigNANDSaveFile() { +ResultCode Module::DeleteConfigNANDSaveFile() { FileSys::Path path("/config"); return Service::FS::DeleteFileFromArchive(cfg_system_save_data_archive, path); } -ResultCode UpdateConfigNANDSavegame() { +ResultCode Module::UpdateConfigNANDSavegame() { FileSys::Mode mode = {}; mode.write_flag.Assign(1); mode.create_flag.Assign(1); @@ -414,7 +408,7 @@ ResultCode UpdateConfigNANDSavegame() { return RESULT_SUCCESS; } -ResultCode FormatConfig() { +ResultCode Module::FormatConfig() { ResultCode res = DeleteConfigNANDSaveFile(); // The delete command fails if the file doesn't exist, so we have to check that too if (!res.IsSuccess() && res != FileSys::ERROR_FILE_NOT_FOUND) { @@ -533,7 +527,7 @@ ResultCode FormatConfig() { return RESULT_SUCCESS; } -ResultCode LoadConfigNANDSaveFile() { +ResultCode Module::LoadConfigNANDSaveFile() { // Open the SystemSaveData archive 0x00010017 FileSys::Path archive_path(cfg_system_savedata_id); auto archive_result = @@ -570,18 +564,11 @@ ResultCode LoadConfigNANDSaveFile() { return FormatConfig(); } -void Init() { - AddService(new CFG_I); - AddService(new CFG_NOR); - AddService(new CFG_S); - AddService(new CFG_U); - +Module::Module() { LoadConfigNANDSaveFile(); - - preferred_region_code = 0; } -void Shutdown() {} +Module::~Module() = default; /// Checks if the language is available in the chosen region, and returns a proper one static SystemLanguage AdjustLanguageInfoBlock(u32 region, SystemLanguage language) { @@ -610,7 +597,7 @@ static SystemLanguage AdjustLanguageInfoBlock(u32 region, SystemLanguage languag return language; } -void SetPreferredRegionCode(u32 region_code) { +void Module::SetPreferredRegionCode(u32 region_code) { preferred_region_code = region_code; LOG_INFO(Service_CFG, "Preferred region code set to %u", preferred_region_code); @@ -626,14 +613,14 @@ void SetPreferredRegionCode(u32 region_code) { } } -void SetUsername(const std::u16string& name) { +void Module::SetUsername(const std::u16string& name) { ASSERT(name.size() <= 10); UsernameBlock block{}; name.copy(block.username, name.size()); SetConfigInfoBlock(UsernameBlockID, sizeof(block), 4, &block); } -std::u16string GetUsername() { +std::u16string Module::GetUsername() { UsernameBlock block; GetConfigInfoBlock(UsernameBlockID, sizeof(block), 8, &block); @@ -646,40 +633,40 @@ std::u16string GetUsername() { return username; } -void SetBirthday(u8 month, u8 day) { +void Module::SetBirthday(u8 month, u8 day) { BirthdayBlock block = {month, day}; SetConfigInfoBlock(BirthdayBlockID, sizeof(block), 4, &block); } -std::tuple GetBirthday() { +std::tuple Module::GetBirthday() { BirthdayBlock block; GetConfigInfoBlock(BirthdayBlockID, sizeof(block), 8, &block); return std::make_tuple(block.month, block.day); } -void SetSystemLanguage(SystemLanguage language) { +void Module::SetSystemLanguage(SystemLanguage language) { u8 block = language; SetConfigInfoBlock(LanguageBlockID, sizeof(block), 4, &block); } -SystemLanguage GetSystemLanguage() { +SystemLanguage Module::GetSystemLanguage() { u8 block; GetConfigInfoBlock(LanguageBlockID, sizeof(block), 8, &block); return static_cast(block); } -void SetSoundOutputMode(SoundOutputMode mode) { +void Module::SetSoundOutputMode(SoundOutputMode mode) { u8 block = mode; SetConfigInfoBlock(SoundOutputModeBlockID, sizeof(block), 4, &block); } -SoundOutputMode GetSoundOutputMode() { +SoundOutputMode Module::GetSoundOutputMode() { u8 block; GetConfigInfoBlock(SoundOutputModeBlockID, sizeof(block), 8, &block); return static_cast(block); } -void GenerateConsoleUniqueId(u32& random_number, u64& console_id) { +void Module::GenerateConsoleUniqueId(u32& random_number, u64& console_id) { CryptoPP::AutoSeededRandomPool rng; random_number = rng.GenerateWord32(0, 0xFFFF); u64_le local_friend_code_seed; @@ -688,7 +675,7 @@ void GenerateConsoleUniqueId(u32& random_number, u64& console_id) { console_id = (local_friend_code_seed & 0x3FFFFFFFF) | (static_cast(random_number) << 48); } -ResultCode SetConsoleUniqueId(u32 random_number, u64 console_id) { +ResultCode Module::SetConsoleUniqueId(u32 random_number, u64 console_id) { u64_le console_id_le = console_id; ResultCode res = SetConfigInfoBlock(ConsoleUniqueID1BlockID, sizeof(console_id_le), 0xE, &console_id_le); @@ -708,11 +695,20 @@ ResultCode SetConsoleUniqueId(u32 random_number, u64 console_id) { return RESULT_SUCCESS; } -u64 GetConsoleUniqueId() { +u64 Module::GetConsoleUniqueId() { u64_le console_id_le; GetConfigInfoBlock(ConsoleUniqueID2BlockID, sizeof(console_id_le), 0xE, &console_id_le); return console_id_le; } +void InstallInterfaces(SM::ServiceManager& service_manager) { + auto cfg = std::make_shared(); + std::make_shared(cfg)->InstallAsService(service_manager); + std::make_shared(cfg)->InstallAsService(service_manager); + std::make_shared(cfg)->InstallAsService(service_manager); + std::make_shared()->InstallAsService(service_manager); + current_cfg = cfg; +} + } // namespace CFG } // namespace Service diff --git a/src/core/hle/service/cfg/cfg.h b/src/core/hle/service/cfg/cfg.h index 9ef773c87..62c85f824 100644 --- a/src/core/hle/service/cfg/cfg.h +++ b/src/core/hle/service/cfg/cfg.h @@ -5,15 +5,12 @@ #pragma once #include +#include #include #include "common/common_types.h" - -union ResultCode; +#include "core/hle/service/fs/archive.h" namespace Service { - -class Interface; - namespace CFG { enum SystemModel { @@ -82,289 +79,321 @@ static const std::array country_codes = {{ C("SM"), C("VA"), C("BM"), // 184-186 }}; -/** - * CFG::GetCountryCodeString service function - * Inputs: - * 1 : Country Code ID - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : Country's 2-char string - */ -void GetCountryCodeString(Service::Interface* self); +class Module final { +public: + Module(); + ~Module(); -/** - * CFG::GetCountryCodeID service function - * Inputs: - * 1 : Country Code 2-char string - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : Country Code ID - */ -void GetCountryCodeID(Service::Interface* self); + class Interface : public ServiceFramework { + public: + Interface(std::shared_ptr cfg, const char* name, u32 max_session); + ~Interface(); -u32 GetRegionValue(); + /** + * CFG::GetCountryCodeString service function + * Inputs: + * 1 : Country Code ID + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * 2 : Country's 2-char string + */ + void GetCountryCodeString(Kernel::HLERequestContext& ctx); -/** - * CFG::SecureInfoGetRegion service function - * Inputs: - * 1 : None - * Outputs: - * 0 : Result Header code - * 1 : Result of function, 0 on success, otherwise error code - * 2 : Region value loaded from SecureInfo offset 0x100 - */ -void SecureInfoGetRegion(Service::Interface* self); + /** + * CFG::GetCountryCodeID service function + * Inputs: + * 1 : Country Code 2-char string + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * 2 : Country Code ID + */ + void GetCountryCodeID(Kernel::HLERequestContext& ctx); -/** - * CFG::GenHashConsoleUnique service function - * Inputs: - * 1 : 20 bit application ID salt - * Outputs: - * 0 : Result Header code - * 1 : Result of function, 0 on success, otherwise error code - * 2 : Hash/"ID" lower word - * 3 : Hash/"ID" upper word - */ -void GenHashConsoleUnique(Service::Interface* self); + u32 GetRegionValue(); -/** - * CFG::GetRegionCanadaUSA service function - * Inputs: - * 1 : None - * Outputs: - * 0 : Result Header code - * 1 : Result of function, 0 on success, otherwise error code - * 2 : 1 if the system is a Canada or USA model, 0 otherwise - */ -void GetRegionCanadaUSA(Service::Interface* self); + /** + * CFG::SecureInfoGetRegion service function + * Inputs: + * 1 : None + * Outputs: + * 0 : Result Header code + * 1 : Result of function, 0 on success, otherwise error code + * 2 : Region value loaded from SecureInfo offset 0x100 + */ + void SecureInfoGetRegion(Kernel::HLERequestContext& ctx, u16 id); -/** - * CFG::GetSystemModel service function - * Inputs: - * 0 : 0x00050000 - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : Model of the console - */ -void GetSystemModel(Service::Interface* self); + /** + * CFG::GenHashConsoleUnique service function + * Inputs: + * 1 : 20 bit application ID salt + * Outputs: + * 0 : Result Header code + * 1 : Result of function, 0 on success, otherwise error code + * 2 : Hash/"ID" lower word + * 3 : Hash/"ID" upper word + */ + void GenHashConsoleUnique(Kernel::HLERequestContext& ctx); -/** - * CFG::GetModelNintendo2DS service function - * Inputs: - * 0 : 0x00060000 - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : 0 if the system is a Nintendo 2DS, 1 otherwise - */ -void GetModelNintendo2DS(Service::Interface* self); + /** + * CFG::GetRegionCanadaUSA service function + * Inputs: + * 1 : None + * Outputs: + * 0 : Result Header code + * 1 : Result of function, 0 on success, otherwise error code + * 2 : 1 if the system is a Canada or USA model, 0 otherwise + */ + void GetRegionCanadaUSA(Kernel::HLERequestContext& ctx); -/** - * CFG::GetConfigInfoBlk2 service function - * Inputs: - * 0 : 0x00010082 - * 1 : Size - * 2 : Block ID - * 3 : Descriptor for the output buffer - * 4 : Output buffer pointer - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -void GetConfigInfoBlk2(Service::Interface* self); + /** + * CFG::GetSystemModel service function + * Inputs: + * 0 : 0x00050000 + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * 2 : Model of the console + */ + void GetSystemModel(Kernel::HLERequestContext& ctx); -/** - * CFG::GetConfigInfoBlk8 service function - * Inputs: - * 0 : 0x04010082 / 0x08010082 - * 1 : Size - * 2 : Block ID - * 3 : Descriptor for the output buffer - * 4 : Output buffer pointer - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -void GetConfigInfoBlk8(Service::Interface* self); + /** + * CFG::GetModelNintendo2DS service function + * Inputs: + * 0 : 0x00060000 + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * 2 : 0 if the system is a Nintendo 2DS, 1 otherwise + */ + void GetModelNintendo2DS(Kernel::HLERequestContext& ctx); -/** - * CFG::SetConfigInfoBlk4 service function - * Inputs: - * 0 : 0x04020082 / 0x08020082 - * 1 : Block ID - * 2 : Size - * 3 : Descriptor for the output buffer - * 4 : Output buffer pointer - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * Note: - * The parameters order is different from GetConfigInfoBlk2/8's, - * where Block ID and Size are switched. - */ -void SetConfigInfoBlk4(Service::Interface* self); + /** + * CFG::GetConfigInfoBlk2 service function + * Inputs: + * 0 : 0x00010082 + * 1 : Size + * 2 : Block ID + * 3 : Descriptor for the output buffer + * 4 : Output buffer pointer + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + */ + void GetConfigInfoBlk2(Kernel::HLERequestContext& ctx); -/** - * CFG::UpdateConfigNANDSavegame service function - * Inputs: - * 0 : 0x04030000 / 0x08030000 - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -void UpdateConfigNANDSavegame(Service::Interface* self); + /** + * CFG::GetConfigInfoBlk8 service function + * Inputs: + * 0 : 0x04010082 / 0x08010082 + * 1 : Size + * 2 : Block ID + * 3 : Descriptor for the output buffer + * 4 : Output buffer pointer + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + */ + void GetConfigInfoBlk8(Kernel::HLERequestContext& ctx, u16 id); -/** - * CFG::FormatConfig service function - * Inputs: - * 0 : 0x08060000 - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -void FormatConfig(Service::Interface* self); + /** + * CFG::SetConfigInfoBlk4 service function + * Inputs: + * 0 : 0x04020082 / 0x08020082 + * 1 : Block ID + * 2 : Size + * 3 : Descriptor for the output buffer + * 4 : Output buffer pointer + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * Note: + * The parameters order is different from GetConfigInfoBlk2/8's, + * where Block ID and Size are switched. + */ + void SetConfigInfoBlk4(Kernel::HLERequestContext& ctx, u16 id); -/** - * Reads a block with the specified id and flag from the Config savegame buffer - * and writes the output to output. The input size must match exactly the size of the requested - * block. - * - * @param block_id The id of the block we want to read - * @param size The size of the block we want to read - * @param flag The requested block must have this flag set - * @param output A pointer where we will write the read data - * @returns ResultCode indicating the result of the operation, 0 on success - */ -ResultCode GetConfigInfoBlock(u32 block_id, u32 size, u32 flag, void* output); + /** + * CFG::UpdateConfigNANDSavegame service function + * Inputs: + * 0 : 0x04030000 / 0x08030000 + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + */ + void UpdateConfigNANDSavegame(Kernel::HLERequestContext& ctx, u16 id); -/** - * Reads data from input and writes to a block with the specified id and flag - * in the Config savegame buffer. The input size must match exactly the size of the target block. - * - * @param block_id The id of the block we want to write - * @param size The size of the block we want to write - * @param flag The target block must have this flag set - * @param input A pointer where we will read data and write to Config savegame buffer - * @returns ResultCode indicating the result of the operation, 0 on success - */ -ResultCode SetConfigInfoBlock(u32 block_id, u32 size, u32 flag, const void* input); + /** + * CFG::FormatConfig service function + * Inputs: + * 0 : 0x08060000 + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + */ + void FormatConfig(Kernel::HLERequestContext& ctx); -/** - * Creates a block with the specified id and writes the input data to the cfg savegame buffer in - * memory. The config savegame file in the filesystem is not updated. - * - * @param block_id The id of the block we want to create - * @param size The size of the block we want to create - * @param flags The flags of the new block - * @param data A pointer containing the data we will write to the new block - * @returns ResultCode indicating the result of the operation, 0 on success - */ -ResultCode CreateConfigInfoBlk(u32 block_id, u16 size, u16 flags, const void* data); + /// A helper function for dispatching service functions that have multiple IDs + template + void D(Kernel::HLERequestContext& ctx) { + (this->*function)(ctx, id); + } -/** - * Deletes the config savegame file from the filesystem, the buffer in memory is not affected - * @returns ResultCode indicating the result of the operation, 0 on success - */ -ResultCode DeleteConfigNANDSaveFile(); + private: + std::shared_ptr cfg; + }; -/** - * Writes the config savegame memory buffer to the config savegame file in the filesystem - * @returns ResultCode indicating the result of the operation, 0 on success - */ -ResultCode UpdateConfigNANDSavegame(); +private: + ResultVal GetConfigInfoBlockPointer(u32 block_id, u32 size, u32 flag); -/** - * Re-creates the config savegame file in memory and the filesystem with the default blocks - * @returns ResultCode indicating the result of the operation, 0 on success - */ -ResultCode FormatConfig(); + /** + * Reads a block with the specified id and flag from the Config savegame buffer + * and writes the output to output. The input size must match exactly the size of the requested + * block. + * + * @param block_id The id of the block we want to read + * @param size The size of the block we want to read + * @param flag The requested block must have this flag set + * @param output A pointer where we will write the read data + * @returns ResultCode indicating the result of the operation, 0 on success + */ + ResultCode GetConfigInfoBlock(u32 block_id, u32 size, u32 flag, void* output); -/** - * Open the config savegame file and load it to the memory buffer - * @returns ResultCode indicating the result of the operation, 0 on success - */ -ResultCode LoadConfigNANDSaveFile(); + /** + * Reads data from input and writes to a block with the specified id and flag + * in the Config savegame buffer. The input size must match exactly the size of the target + * block. + * + * @param block_id The id of the block we want to write + * @param size The size of the block we want to write + * @param flag The target block must have this flag set + * @param input A pointer where we will read data and write to Config savegame buffer + * @returns ResultCode indicating the result of the operation, 0 on success + */ + ResultCode SetConfigInfoBlock(u32 block_id, u32 size, u32 flag, const void* input); -/// Initialize the config service -void Init(); + /** + * Creates a block with the specified id and writes the input data to the cfg savegame buffer in + * memory. The config savegame file in the filesystem is not updated. + * + * @param block_id The id of the block we want to create + * @param size The size of the block we want to create + * @param flags The flags of the new block + * @param data A pointer containing the data we will write to the new block + * @returns ResultCode indicating the result of the operation, 0 on success + */ + ResultCode CreateConfigInfoBlk(u32 block_id, u16 size, u16 flags, const void* data); -/// Shutdown the config service -void Shutdown(); + /** + * Deletes the config savegame file from the filesystem, the buffer in memory is not affected + * @returns ResultCode indicating the result of the operation, 0 on success + */ + ResultCode DeleteConfigNANDSaveFile(); -/** - * Set the region code preferred by the game so that CFG will adjust to it when the region setting - * is auto. - * @param region_code the preferred region code to set - */ -void SetPreferredRegionCode(u32 region_code); + /** + * Re-creates the config savegame file in memory and the filesystem with the default blocks + * @returns ResultCode indicating the result of the operation, 0 on success + */ + ResultCode FormatConfig(); -// Utilities for frontend to set config data. -// Note: before calling these functions, LoadConfigNANDSaveFile should be called, -// and UpdateConfigNANDSavegame should be called after making changes to config data. + /** + * Open the config savegame file and load it to the memory buffer + * @returns ResultCode indicating the result of the operation, 0 on success + */ + ResultCode LoadConfigNANDSaveFile(); -/** - * Sets the username in config savegame. - * @param name the username to set. The maximum size is 10 in char16_t. - */ -void SetUsername(const std::u16string& name); +public: + u32 GetRegionValue(); -/** - * Gets the username from config savegame. - * @returns the username - */ -std::u16string GetUsername(); + /** + * Set the region code preferred by the game so that CFG will adjust to it when the region + * setting + * is auto. + * @param region_code the preferred region code to set + */ + void SetPreferredRegionCode(u32 region_code); -/** - * Sets the profile birthday in config savegame. - * @param month the month of birthday. - * @param day the day of the birthday. - */ -void SetBirthday(u8 month, u8 day); + // Utilities for frontend to set config data. + // Note: UpdateConfigNANDSavegame should be called after making changes to config data. -/** - * Gets the profile birthday from the config savegame. - * @returns a tuple of (month, day) of birthday - */ -std::tuple GetBirthday(); + /** + * Sets the username in config savegame. + * @param name the username to set. The maximum size is 10 in char16_t. + */ + void SetUsername(const std::u16string& name); -/** - * Sets the system language in config savegame. - * @param language the system language to set. - */ -void SetSystemLanguage(SystemLanguage language); + /** + * Gets the username from config savegame. + * @returns the username + */ + std::u16string GetUsername(); -/** - * Gets the system language from config savegame. - * @returns the system language - */ -SystemLanguage GetSystemLanguage(); + /** + * Sets the profile birthday in config savegame. + * @param month the month of birthday. + * @param day the day of the birthday. + */ + void SetBirthday(u8 month, u8 day); -/** - * Sets the sound output mode in config savegame. - * @param mode the sound output mode to set - */ -void SetSoundOutputMode(SoundOutputMode mode); + /** + * Gets the profile birthday from the config savegame. + * @returns a tuple of (month, day) of birthday + */ + std::tuple GetBirthday(); -/** - * Gets the sound output mode from config savegame. - * @returns the sound output mode - */ -SoundOutputMode GetSoundOutputMode(); + /** + * Sets the system language in config savegame. + * @param language the system language to set. + */ + void SetSystemLanguage(SystemLanguage language); -/** - * Generates a new random console unique id. - * @param random_number a random generated 16bit number stored at 0x90002, used for generating the - * console_id - * @param console_id the randomly created console id - */ -void GenerateConsoleUniqueId(u32& random_number, u64& console_id); + /** + * Gets the system language from config savegame. + * @returns the system language + */ + SystemLanguage GetSystemLanguage(); -/** - * Sets the random_number and the console unique id in the config savegame. - * @param random_number the random_number to set - * @param console_id the console id to set - */ -ResultCode SetConsoleUniqueId(u32 random_number, u64 console_id); + /** + * Sets the sound output mode in config savegame. + * @param mode the sound output mode to set + */ + void SetSoundOutputMode(SoundOutputMode mode); -/** - * Gets the console unique id from config savegame. - * @returns the console unique id - */ -u64 GetConsoleUniqueId(); + /** + * Gets the sound output mode from config savegame. + * @returns the sound output mode + */ + SoundOutputMode GetSoundOutputMode(); + + /** + * Generates a new random console unique id. + * @param random_number a random generated 16bit number stored at 0x90002, used for generating + * the + * console_id + * @param console_id the randomly created console id + */ + void GenerateConsoleUniqueId(u32& random_number, u64& console_id); + + /** + * Sets the random_number and the console unique id in the config savegame. + * @param random_number the random_number to set + * @param console_id the console id to set + */ + ResultCode SetConsoleUniqueId(u32 random_number, u64 console_id); + + /** + * Gets the console unique id from config savegame. + * @returns the console unique id + */ + u64 GetConsoleUniqueId(); + + /** + * Writes the config savegame memory buffer to the config savegame file in the filesystem + * @returns ResultCode indicating the result of the operation, 0 on success + */ + ResultCode UpdateConfigNANDSavegame(); + +private: + static constexpr u32 CONFIG_SAVEFILE_SIZE = 0x8000; + std::array cfg_config_file_buffer; + Service::FS::ArchiveHandle cfg_system_save_data_archive; + u32 preferred_region_code = 0; +}; + +void InstallInterfaces(SM::ServiceManager& service_manager); +std::shared_ptr GetCurrentModule(); } // namespace CFG } // namespace Service diff --git a/src/core/hle/service/cfg/cfg_i.cpp b/src/core/hle/service/cfg/cfg_i.cpp index e8db0fc42..b43112fdb 100644 --- a/src/core/hle/service/cfg/cfg_i.cpp +++ b/src/core/hle/service/cfg/cfg_i.cpp @@ -2,63 +2,63 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#include "core/hle/service/cfg/cfg.h" #include "core/hle/service/cfg/cfg_i.h" namespace Service { namespace CFG { -const Interface::FunctionInfo FunctionTable[] = { - // cfg common - {0x00010082, GetConfigInfoBlk2, "GetConfigInfoBlk2"}, - {0x00020000, SecureInfoGetRegion, "SecureInfoGetRegion"}, - {0x00030040, GenHashConsoleUnique, "GenHashConsoleUnique"}, - {0x00040000, GetRegionCanadaUSA, "GetRegionCanadaUSA"}, - {0x00050000, GetSystemModel, "GetSystemModel"}, - {0x00060000, GetModelNintendo2DS, "GetModelNintendo2DS"}, - {0x00070040, nullptr, "WriteToFirstByteCfgSavegame"}, - {0x00080080, nullptr, "GoThroughTable"}, - {0x00090040, GetCountryCodeString, "GetCountryCodeString"}, - {0x000A0040, GetCountryCodeID, "GetCountryCodeID"}, - {0x000B0000, nullptr, "IsFangateSupported"}, - // cfg:i - {0x04010082, GetConfigInfoBlk8, "GetConfigInfoBlk8"}, - {0x04020082, SetConfigInfoBlk4, "SetConfigInfoBlk4"}, - {0x04030000, UpdateConfigNANDSavegame, "UpdateConfigNANDSavegame"}, - {0x04040042, nullptr, "GetLocalFriendCodeSeedData"}, - {0x04050000, nullptr, "GetLocalFriendCodeSeed"}, - {0x04060000, SecureInfoGetRegion, "SecureInfoGetRegion"}, - {0x04070000, nullptr, "SecureInfoGetByte101"}, - {0x04080042, nullptr, "SecureInfoGetSerialNo"}, - {0x04090000, nullptr, "UpdateConfigBlk00040003"}, - {0x08010082, GetConfigInfoBlk8, "GetConfigInfoBlk8"}, - {0x08020082, SetConfigInfoBlk4, "SetConfigInfoBlk4"}, - {0x08030000, UpdateConfigNANDSavegame, "UpdateConfigNANDSavegame"}, - {0x080400C2, nullptr, "CreateConfigInfoBlk"}, - {0x08050000, nullptr, "DeleteConfigNANDSavefile"}, - {0x08060000, FormatConfig, "FormatConfig"}, - {0x08080000, nullptr, "UpdateConfigBlk1"}, - {0x08090000, nullptr, "UpdateConfigBlk2"}, - {0x080A0000, nullptr, "UpdateConfigBlk3"}, - {0x080B0082, nullptr, "SetGetLocalFriendCodeSeedData"}, - {0x080C0042, nullptr, "SetLocalFriendCodeSeedSignature"}, - {0x080D0000, nullptr, "DeleteCreateNANDLocalFriendCodeSeed"}, - {0x080E0000, nullptr, "VerifySigLocalFriendCodeSeed"}, - {0x080F0042, nullptr, "GetLocalFriendCodeSeedData"}, - {0x08100000, nullptr, "GetLocalFriendCodeSeed"}, - {0x08110084, nullptr, "SetSecureInfo"}, - {0x08120000, nullptr, "DeleteCreateNANDSecureInfo"}, - {0x08130000, nullptr, "VerifySigSecureInfo"}, - {0x08140042, nullptr, "SecureInfoGetData"}, - {0x08150042, nullptr, "SecureInfoGetSignature"}, - {0x08160000, SecureInfoGetRegion, "SecureInfoGetRegion"}, - {0x08170000, nullptr, "SecureInfoGetByte101"}, - {0x08180042, nullptr, "SecureInfoGetSerialNo"}, -}; - -CFG_I::CFG_I() { - Register(FunctionTable); +CFG_I::CFG_I(std::shared_ptr cfg) : Module::Interface(std::move(cfg), "cfg:i", 23) { + static const FunctionInfo functions[] = { + // cfg common + {0x00010082, &CFG_I::GetConfigInfoBlk2, "GetConfigInfoBlk2"}, + {0x00020000, &CFG_I::D<&CFG_I::SecureInfoGetRegion, 0x0002>, "SecureInfoGetRegion"}, + {0x00030040, &CFG_I::GenHashConsoleUnique, "GenHashConsoleUnique"}, + {0x00040000, &CFG_I::GetRegionCanadaUSA, "GetRegionCanadaUSA"}, + {0x00050000, &CFG_I::GetSystemModel, "GetSystemModel"}, + {0x00060000, &CFG_I::GetModelNintendo2DS, "GetModelNintendo2DS"}, + {0x00070040, nullptr, "WriteToFirstByteCfgSavegame"}, + {0x00080080, nullptr, "GoThroughTable"}, + {0x00090040, &CFG_I::GetCountryCodeString, "GetCountryCodeString"}, + {0x000A0040, &CFG_I::GetCountryCodeID, "GetCountryCodeID"}, + {0x000B0000, nullptr, "IsFangateSupported"}, + // cfg:i + {0x04010082, &CFG_I::D<&CFG_I::GetConfigInfoBlk8, 0x0401>, "GetConfigInfoBlk8"}, + {0x04020082, &CFG_I::D<&CFG_I::SetConfigInfoBlk4, 0x0402>, "SetConfigInfoBlk4"}, + {0x04030000, &CFG_I::D<&CFG_I::UpdateConfigNANDSavegame, 0x0403>, + "UpdateConfigNANDSavegame"}, + {0x04040042, nullptr, "GetLocalFriendCodeSeedData"}, + {0x04050000, nullptr, "GetLocalFriendCodeSeed"}, + {0x04060000, &CFG_I::D<&CFG_I::SecureInfoGetRegion, 0x0406>, "SecureInfoGetRegion"}, + {0x04070000, nullptr, "SecureInfoGetByte101"}, + {0x04080042, nullptr, "SecureInfoGetSerialNo"}, + {0x04090000, nullptr, "UpdateConfigBlk00040003"}, + {0x08010082, &CFG_I::D<&CFG_I::GetConfigInfoBlk8, 0x0801>, "GetConfigInfoBlk8"}, + {0x08020082, &CFG_I::D<&CFG_I::SetConfigInfoBlk4, 0x0802>, "SetConfigInfoBlk4"}, + {0x08030000, &CFG_I::D<&CFG_I::UpdateConfigNANDSavegame, 0x0803>, + "UpdateConfigNANDSavegame"}, + {0x080400C2, nullptr, "CreateConfigInfoBlk"}, + {0x08050000, nullptr, "DeleteConfigNANDSavefile"}, + {0x08060000, &CFG_I::FormatConfig, "FormatConfig"}, + {0x08080000, nullptr, "UpdateConfigBlk1"}, + {0x08090000, nullptr, "UpdateConfigBlk2"}, + {0x080A0000, nullptr, "UpdateConfigBlk3"}, + {0x080B0082, nullptr, "SetGetLocalFriendCodeSeedData"}, + {0x080C0042, nullptr, "SetLocalFriendCodeSeedSignature"}, + {0x080D0000, nullptr, "DeleteCreateNANDLocalFriendCodeSeed"}, + {0x080E0000, nullptr, "VerifySigLocalFriendCodeSeed"}, + {0x080F0042, nullptr, "GetLocalFriendCodeSeedData"}, + {0x08100000, nullptr, "GetLocalFriendCodeSeed"}, + {0x08110084, nullptr, "SetSecureInfo"}, + {0x08120000, nullptr, "DeleteCreateNANDSecureInfo"}, + {0x08130000, nullptr, "VerifySigSecureInfo"}, + {0x08140042, nullptr, "SecureInfoGetData"}, + {0x08150042, nullptr, "SecureInfoGetSignature"}, + {0x08160000, &CFG_I::D<&CFG_I::SecureInfoGetRegion, 0x0816>, "SecureInfoGetRegion"}, + {0x08170000, nullptr, "SecureInfoGetByte101"}, + {0x08180042, nullptr, "SecureInfoGetSerialNo"}, + }; + RegisterHandlers(functions); } } // namespace CFG -} // namespace Service \ No newline at end of file +} // namespace Service diff --git a/src/core/hle/service/cfg/cfg_i.h b/src/core/hle/service/cfg/cfg_i.h index 8cfd47633..0fd972c0e 100644 --- a/src/core/hle/service/cfg/cfg_i.h +++ b/src/core/hle/service/cfg/cfg_i.h @@ -4,19 +4,15 @@ #pragma once -#include "core/hle/service/service.h" +#include "core/hle/service/cfg/cfg.h" namespace Service { namespace CFG { -class CFG_I final : public Interface { +class CFG_I final : public Module::Interface { public: - CFG_I(); - - std::string GetPortName() const override { - return "cfg:i"; - } + explicit CFG_I(std::shared_ptr cfg); }; } // namespace CFG -} // namespace Service \ No newline at end of file +} // namespace Service diff --git a/src/core/hle/service/cfg/cfg_nor.cpp b/src/core/hle/service/cfg/cfg_nor.cpp index 4ce02d115..685a1461e 100644 --- a/src/core/hle/service/cfg/cfg_nor.cpp +++ b/src/core/hle/service/cfg/cfg_nor.cpp @@ -2,21 +2,19 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#include "core/hle/service/cfg/cfg.h" #include "core/hle/service/cfg/cfg_nor.h" namespace Service { namespace CFG { -const Interface::FunctionInfo FunctionTable[] = { - {0x00010040, nullptr, "Initialize"}, - {0x00020000, nullptr, "Shutdown"}, - {0x00050082, nullptr, "ReadData"}, - {0x00060082, nullptr, "WriteData"}, -}; - -CFG_NOR::CFG_NOR() { - Register(FunctionTable); +CFG_NOR::CFG_NOR() : ServiceFramework("cfg:nor", 23) { + static const FunctionInfo functions[] = { + {0x00010040, nullptr, "Initialize"}, + {0x00020000, nullptr, "Shutdown"}, + {0x00050082, nullptr, "ReadData"}, + {0x00060082, nullptr, "WriteData"}, + }; + RegisterHandlers(functions); } } // namespace CFG diff --git a/src/core/hle/service/cfg/cfg_nor.h b/src/core/hle/service/cfg/cfg_nor.h index c337718e7..197c927db 100644 --- a/src/core/hle/service/cfg/cfg_nor.h +++ b/src/core/hle/service/cfg/cfg_nor.h @@ -9,13 +9,9 @@ namespace Service { namespace CFG { -class CFG_NOR final : public Interface { +class CFG_NOR final : public ServiceFramework { public: CFG_NOR(); - - std::string GetPortName() const override { - return "cfg:nor"; - } }; } // namespace CFG diff --git a/src/core/hle/service/cfg/cfg_s.cpp b/src/core/hle/service/cfg/cfg_s.cpp index 9386fe33d..4449b2b6c 100644 --- a/src/core/hle/service/cfg/cfg_s.cpp +++ b/src/core/hle/service/cfg/cfg_s.cpp @@ -2,39 +2,38 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#include "core/hle/service/cfg/cfg.h" #include "core/hle/service/cfg/cfg_s.h" namespace Service { namespace CFG { -const Interface::FunctionInfo FunctionTable[] = { - // cfg common - {0x00010082, GetConfigInfoBlk2, "GetConfigInfoBlk2"}, - {0x00020000, SecureInfoGetRegion, "SecureInfoGetRegion"}, - {0x00030040, GenHashConsoleUnique, "GenHashConsoleUnique"}, - {0x00040000, GetRegionCanadaUSA, "GetRegionCanadaUSA"}, - {0x00050000, GetSystemModel, "GetSystemModel"}, - {0x00060000, GetModelNintendo2DS, "GetModelNintendo2DS"}, - {0x00070040, nullptr, "WriteToFirstByteCfgSavegame"}, - {0x00080080, nullptr, "GoThroughTable"}, - {0x00090040, GetCountryCodeString, "GetCountryCodeString"}, - {0x000A0040, GetCountryCodeID, "GetCountryCodeID"}, - {0x000B0000, nullptr, "IsFangateSupported"}, - // cfg:s - {0x04010082, GetConfigInfoBlk8, "GetConfigInfoBlk8"}, - {0x04020082, SetConfigInfoBlk4, "SetConfigInfoBlk4"}, - {0x04030000, UpdateConfigNANDSavegame, "UpdateConfigNANDSavegame"}, - {0x04040042, nullptr, "GetLocalFriendCodeSeedData"}, - {0x04050000, nullptr, "GetLocalFriendCodeSeed"}, - {0x04060000, nullptr, "SecureInfoGetRegion"}, - {0x04070000, nullptr, "SecureInfoGetByte101"}, - {0x04080042, nullptr, "SecureInfoGetSerialNo"}, - {0x04090000, nullptr, "UpdateConfigBlk00040003"}, -}; - -CFG_S::CFG_S() { - Register(FunctionTable); +CFG_S::CFG_S(std::shared_ptr cfg) : Module::Interface(std::move(cfg), "cfg:s", 23) { + static const FunctionInfo functions[] = { + // cfg common + {0x00010082, &CFG_S::GetConfigInfoBlk2, "GetConfigInfoBlk2"}, + {0x00020000, &CFG_S::D<&CFG_S::SecureInfoGetRegion, 0x0002>, "SecureInfoGetRegion"}, + {0x00030040, &CFG_S::GenHashConsoleUnique, "GenHashConsoleUnique"}, + {0x00040000, &CFG_S::GetRegionCanadaUSA, "GetRegionCanadaUSA"}, + {0x00050000, &CFG_S::GetSystemModel, "GetSystemModel"}, + {0x00060000, &CFG_S::GetModelNintendo2DS, "GetModelNintendo2DS"}, + {0x00070040, nullptr, "WriteToFirstByteCfgSavegame"}, + {0x00080080, nullptr, "GoThroughTable"}, + {0x00090040, &CFG_S::GetCountryCodeString, "GetCountryCodeString"}, + {0x000A0040, &CFG_S::GetCountryCodeID, "GetCountryCodeID"}, + {0x000B0000, nullptr, "IsFangateSupported"}, + // cfg:s + {0x04010082, &CFG_S::D<&CFG_S::GetConfigInfoBlk8, 0x0401>, "GetConfigInfoBlk8"}, + {0x04020082, &CFG_S::D<&CFG_S::SetConfigInfoBlk4, 0x0402>, "SetConfigInfoBlk4"}, + {0x04030000, &CFG_S::D<&CFG_S::UpdateConfigNANDSavegame, 0x0403>, + "UpdateConfigNANDSavegame"}, + {0x04040042, nullptr, "GetLocalFriendCodeSeedData"}, + {0x04050000, nullptr, "GetLocalFriendCodeSeed"}, + {0x04060000, &CFG_S::D<&CFG_S::SecureInfoGetRegion, 0x0406>, "SecureInfoGetRegion"}, + {0x04070000, nullptr, "SecureInfoGetByte101"}, + {0x04080042, nullptr, "SecureInfoGetSerialNo"}, + {0x04090000, nullptr, "UpdateConfigBlk00040003"}, + }; + RegisterHandlers(functions); } } // namespace CFG diff --git a/src/core/hle/service/cfg/cfg_s.h b/src/core/hle/service/cfg/cfg_s.h index 99fea46ee..98853954e 100644 --- a/src/core/hle/service/cfg/cfg_s.h +++ b/src/core/hle/service/cfg/cfg_s.h @@ -4,18 +4,14 @@ #pragma once -#include "core/hle/service/service.h" +#include "core/hle/service/cfg/cfg.h" namespace Service { namespace CFG { -class CFG_S final : public Interface { +class CFG_S final : public Module::Interface { public: - CFG_S(); - - std::string GetPortName() const override { - return "cfg:s"; - } + explicit CFG_S(std::shared_ptr cfg); }; } // namespace CFG diff --git a/src/core/hle/service/cfg/cfg_u.cpp b/src/core/hle/service/cfg/cfg_u.cpp index 7b66fee22..4b554e175 100644 --- a/src/core/hle/service/cfg/cfg_u.cpp +++ b/src/core/hle/service/cfg/cfg_u.cpp @@ -2,29 +2,27 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#include "core/hle/service/cfg/cfg.h" #include "core/hle/service/cfg/cfg_u.h" namespace Service { namespace CFG { -const Interface::FunctionInfo FunctionTable[] = { - // cfg common - {0x00010082, GetConfigInfoBlk2, "GetConfigInfoBlk2"}, - {0x00020000, SecureInfoGetRegion, "SecureInfoGetRegion"}, - {0x00030040, GenHashConsoleUnique, "GenHashConsoleUnique"}, - {0x00040000, GetRegionCanadaUSA, "GetRegionCanadaUSA"}, - {0x00050000, GetSystemModel, "GetSystemModel"}, - {0x00060000, GetModelNintendo2DS, "GetModelNintendo2DS"}, - {0x00070040, nullptr, "WriteToFirstByteCfgSavegame"}, - {0x00080080, nullptr, "GoThroughTable"}, - {0x00090040, GetCountryCodeString, "GetCountryCodeString"}, - {0x000A0040, GetCountryCodeID, "GetCountryCodeID"}, - {0x000B0000, nullptr, "IsFangateSupported"}, -}; - -CFG_U::CFG_U() { - Register(FunctionTable); +CFG_U::CFG_U(std::shared_ptr cfg) : Module::Interface(std::move(cfg), "cfg:u", 23) { + static const FunctionInfo functions[] = { + // cfg common + {0x00010082, &CFG_U::GetConfigInfoBlk2, "GetConfigInfoBlk2"}, + {0x00020000, &CFG_U::D<&CFG_U::SecureInfoGetRegion, 0x0002>, "SecureInfoGetRegion"}, + {0x00030040, &CFG_U::GenHashConsoleUnique, "GenHashConsoleUnique"}, + {0x00040000, &CFG_U::GetRegionCanadaUSA, "GetRegionCanadaUSA"}, + {0x00050000, &CFG_U::GetSystemModel, "GetSystemModel"}, + {0x00060000, &CFG_U::GetModelNintendo2DS, "GetModelNintendo2DS"}, + {0x00070040, nullptr, "WriteToFirstByteCfgSavegame"}, + {0x00080080, nullptr, "GoThroughTable"}, + {0x00090040, &CFG_U::GetCountryCodeString, "GetCountryCodeString"}, + {0x000A0040, &CFG_U::GetCountryCodeID, "GetCountryCodeID"}, + {0x000B0000, nullptr, "IsFangateSupported"}, + }; + RegisterHandlers(functions); } } // namespace CFG diff --git a/src/core/hle/service/cfg/cfg_u.h b/src/core/hle/service/cfg/cfg_u.h index fc7844714..b3ad8b31b 100644 --- a/src/core/hle/service/cfg/cfg_u.h +++ b/src/core/hle/service/cfg/cfg_u.h @@ -4,18 +4,14 @@ #pragma once -#include "core/hle/service/service.h" +#include "core/hle/service/cfg/cfg.h" namespace Service { namespace CFG { -class CFG_U final : public Interface { +class CFG_U final : public Module::Interface { public: - CFG_U(); - - std::string GetPortName() const override { - return "cfg:u"; - } + explicit CFG_U(std::shared_ptr cfg); }; } // namespace CFG diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index 534a65706..dde75a29f 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -242,7 +242,7 @@ void Init() { BOSS::Init(); CAM::InstallInterfaces(*SM::g_service_manager); CECD::Init(); - CFG::Init(); + CFG::InstallInterfaces(*SM::g_service_manager); DLP::Init(); FRD::InstallInterfaces(*SM::g_service_manager); GSP::InstallInterfaces(*SM::g_service_manager); @@ -273,7 +273,6 @@ void Init() { void Shutdown() { NDM::Shutdown(); DLP::Shutdown(); - CFG::Shutdown(); CECD::Shutdown(); BOSS::Shutdown(); FS::ArchiveShutdown(); diff --git a/src/core/loader/ncch.cpp b/src/core/loader/ncch.cpp index 29b84e387..1ee437d64 100644 --- a/src/core/loader/ncch.cpp +++ b/src/core/loader/ncch.cpp @@ -135,7 +135,7 @@ void AppLoader_NCCH::ParseRegionLockoutInfo() { constexpr u32 REGION_COUNT = 7; for (u32 region = 0; region < REGION_COUNT; ++region) { if (region_lockout & 1) { - Service::CFG::SetPreferredRegionCode(region); + Service::CFG::GetCurrentModule()->SetPreferredRegionCode(region); break; } region_lockout >>= 1;