mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-30 21:30:04 +00:00 
			
		
		
		
	Service/CFG: convert to ServiceFramework
This commit is contained in:
		
							parent
							
								
									5dd8ac99e3
								
							
						
					
					
						commit
						b179b86f14
					
				
					 16 changed files with 554 additions and 550 deletions
				
			
		|  | @ -79,7 +79,7 @@ static u64 GetTitleIdForApplet(AppletId id) { | |||
| 
 | ||||
|     ASSERT_MSG(itr != applet_titleids.end(), "Unknown applet id 0x%03X", static_cast<u32>(id)); | ||||
| 
 | ||||
|     return itr->title_ids[CFG::GetRegionValue()]; | ||||
|     return itr->title_ids[CFG::GetCurrentModule()->GetRegionValue()]; | ||||
| } | ||||
| 
 | ||||
| AppletManager::AppletSlotData* AppletManager::GetAppletSlotData(AppletId id) { | ||||
|  |  | |||
|  | @ -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; | ||||
|  |  | |||
|  | @ -3,7 +3,6 @@ | |||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include <algorithm> | ||||
| #include <array> | ||||
| #include <cryptopp/osrng.h> | ||||
| #include <cryptopp/sha.h> | ||||
| #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<float, 8> 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<u8, CONFIG_SAVEFILE_SIZE> cfg_config_file_buffer; | ||||
| 
 | ||||
| static Service::FS::ArchiveHandle cfg_system_save_data_archive; | ||||
| static const std::vector<u8> cfg_system_savedata_id = { | ||||
|     0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x01, 0x00, | ||||
| }; | ||||
| 
 | ||||
| static u32 preferred_region_code = 0; | ||||
| static std::weak_ptr<Module> current_cfg; | ||||
| 
 | ||||
| void GetCountryCodeString(Service::Interface* self) { | ||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||
|     u32 country_code_id = cmd_buff[1]; | ||||
| std::shared_ptr<Module> GetCurrentModule() { | ||||
|     auto cfg = current_cfg.lock(); | ||||
|     ASSERT_MSG(cfg, "No CFG module running!"); | ||||
|     return cfg; | ||||
| } | ||||
| 
 | ||||
| Module::Interface::Interface(std::shared_ptr<Module> 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<u16>(); | ||||
| 
 | ||||
|     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<u32>(country_codes[country_code_id]); | ||||
| } | ||||
| 
 | ||||
| void GetCountryCodeID(Service::Interface* self) { | ||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||
|     u16 country_code = static_cast<u16>(cmd_buff[1]); | ||||
| void Module::Interface::GetCountryCodeID(Kernel::HLERequestContext& ctx) { | ||||
|     IPC::RequestParser rp(ctx, 0x0A, 1, 0); | ||||
|     u16 country_code = rp.Pop<u16>(); | ||||
|     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<u16>(0x00FF); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     cmd_buff[1] = 0; | ||||
|     cmd_buff[2] = country_code_id; | ||||
|     rb.Push(RESULT_SUCCESS); | ||||
|     rb.Push<u16>(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<u8>(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<u32>() & 0x000FFFFF; | ||||
| 
 | ||||
|     IPC::RequestBuilder rb = rp.MakeBuilder(3, 0); | ||||
| 
 | ||||
|     std::array<u8, 12> 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<u8*>(&data)) | ||||
|             .raw; | ||||
|     cmd_buff[2] = data & 0xFF; | ||||
|     rb.Push(cfg->GetConfigInfoBlock(ConsoleModelBlockID, 4, 0x8, reinterpret_cast<u8*>(&data))); | ||||
|     rb.Push<u8>(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<u8*>(&data)) | ||||
|             .raw; | ||||
| 
 | ||||
|     rb.Push(cfg->GetConfigInfoBlock(ConsoleModelBlockID, 4, 0x8, reinterpret_cast<u8*>(&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>(); | ||||
|     u32 block_id = rp.Pop<u32>(); | ||||
|     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<u8> 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>(); | ||||
|     u32 block_id = rp.Pop<u32>(); | ||||
|     auto& buffer = rp.PopMappedBuffer(); | ||||
| 
 | ||||
|     IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); | ||||
|     std::vector<u8> 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>(); | ||||
|     u32 size = rp.Pop<u32>(); | ||||
|     auto& buffer = rp.PopMappedBuffer(); | ||||
| 
 | ||||
|     std::vector<u8> 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<u8> 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<u8> 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<void*> GetConfigInfoBlockPointer(u32 block_id, u32 size, u32 flag) { | ||||
| ResultVal<void*> Module::GetConfigInfoBlockPointer(u32 block_id, u32 size, u32 flag) { | ||||
|     // Read the header
 | ||||
|     SaveFileConfig* config = reinterpret_cast<SaveFileConfig*>(cfg_config_file_buffer.data()); | ||||
| 
 | ||||
|  | @ -346,7 +340,7 @@ static ResultVal<void*> GetConfigInfoBlockPointer(u32 block_id, u32 size, u32 fl | |||
|     return MakeResult<void*>(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<SaveFileConfig*>(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<u8, u8> GetBirthday() { | ||||
| std::tuple<u8, u8> 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<SystemLanguage>(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<SoundOutputMode>(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<u64>(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<Module>(); | ||||
|     std::make_shared<CFG_I>(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_NOR>()->InstallAsService(service_manager); | ||||
|     current_cfg = cfg; | ||||
| } | ||||
| 
 | ||||
| } // namespace CFG
 | ||||
| } // namespace Service
 | ||||
|  |  | |||
|  | @ -5,15 +5,12 @@ | |||
| #pragma once | ||||
| 
 | ||||
| #include <array> | ||||
| #include <memory> | ||||
| #include <string> | ||||
| #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<u16, 187> 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<Interface> { | ||||
|     public: | ||||
|         Interface(std::shared_ptr<Module> 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 (Interface::*function)(Kernel::HLERequestContext& ctx, u16 id), u16 id> | ||||
|         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<Module> 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<void*> 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<u8, u8> 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<u8, u8> 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<u8, CONFIG_SAVEFILE_SIZE> 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<Module> GetCurrentModule(); | ||||
| 
 | ||||
| } // namespace CFG
 | ||||
| } // namespace Service
 | ||||
|  |  | |||
|  | @ -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<Module> 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
 | ||||
| } // namespace Service
 | ||||
|  |  | |||
|  | @ -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<Module> cfg); | ||||
| }; | ||||
| 
 | ||||
| } // namespace CFG
 | ||||
| } // namespace Service
 | ||||
| } // namespace Service
 | ||||
|  |  | |||
|  | @ -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
 | ||||
|  |  | |||
|  | @ -9,13 +9,9 @@ | |||
| namespace Service { | ||||
| namespace CFG { | ||||
| 
 | ||||
| class CFG_NOR final : public Interface { | ||||
| class CFG_NOR final : public ServiceFramework<CFG_NOR> { | ||||
| public: | ||||
|     CFG_NOR(); | ||||
| 
 | ||||
|     std::string GetPortName() const override { | ||||
|         return "cfg:nor"; | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| } // namespace CFG
 | ||||
|  |  | |||
|  | @ -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<Module> 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
 | ||||
|  |  | |||
|  | @ -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<Module> cfg); | ||||
| }; | ||||
| 
 | ||||
| } // namespace CFG
 | ||||
|  |  | |||
|  | @ -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<Module> 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
 | ||||
|  |  | |||
|  | @ -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<Module> cfg); | ||||
| }; | ||||
| 
 | ||||
| } // namespace CFG
 | ||||
|  |  | |||
|  | @ -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(); | ||||
|  |  | |||
|  | @ -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; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue