diff options
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/hle/service/cfg/cfg.cpp | 139 | ||||
-rw-r--r-- | src/core/hle/service/cfg/cfg.h | 164 | ||||
-rw-r--r-- | src/core/hle/service/cfg/cfg_i.cpp | 57 | ||||
-rw-r--r-- | src/core/hle/service/cfg/cfg_s.cpp | 62 | ||||
-rw-r--r-- | src/core/hle/service/cfg/cfg_u.cpp | 219 |
5 files changed, 304 insertions, 337 deletions
diff --git a/src/core/hle/service/cfg/cfg.cpp b/src/core/hle/service/cfg/cfg.cpp index 2d26c9330..d42682883 100644 --- a/src/core/hle/service/cfg/cfg.cpp +++ b/src/core/hle/service/cfg/cfg.cpp @@ -6,8 +6,11 @@ #include "common/logging/log.h" #include "common/string_util.h" +#include "common/file_util.h" +#include "core/file_sys/archive_systemsavedata.h" #include "core/file_sys/file_backend.h" +#include "core/settings.h" #include "core/hle/service/cfg/cfg.h" #include "core/hle/service/cfg/cfg_i.h" #include "core/hle/service/cfg/cfg_s.h" @@ -23,7 +26,7 @@ const u64 CONSOLE_UNIQUE_ID = 0xDEADC0DE; const ConsoleModelInfo CONSOLE_MODEL = { NINTENDO_3DS_XL, { 0, 0, 0 } }; const u8 CONSOLE_LANGUAGE = LANGUAGE_EN; const char CONSOLE_USERNAME[0x14] = "CITRA"; -/// This will be initialized in CFGInit, and will be used when creating the block +/// This will be initialized in Init, and will be used when creating the block UsernameBlock CONSOLE_USERNAME_BLOCK; /// TODO(Subv): Find out what this actually is const u8 SOUND_OUTPUT_MODE = 2; @@ -47,6 +50,140 @@ 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 }; +void GetCountryCodeString(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + u32 country_code_id = cmd_buff[1]; + + 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; + return; + } + + cmd_buff[1] = 0; + cmd_buff[2] = country_codes[country_code_id]; +} + +void GetCountryCodeID(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + u16 country_code = cmd_buff[1]; + u16 country_code_id = 0; + + // The following algorithm will fail if the first country code isn't 0. + DEBUG_ASSERT(country_codes[0] == 0); + + for (u16 id = 0; id < country_codes.size(); ++id) { + if (country_codes[id] == country_code) { + country_code_id = id; + break; + } + } + + 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; + return; + } + + cmd_buff[1] = 0; + cmd_buff[2] = country_code_id; +} + +void SecureInfoGetRegion(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + + cmd_buff[1] = RESULT_SUCCESS.raw; + cmd_buff[2] = Settings::values.region_value; +} + +void GenHashConsoleUnique(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + u32 app_id_salt = cmd_buff[1]; + + cmd_buff[1] = RESULT_SUCCESS.raw; + cmd_buff[2] = 0x33646D6F ^ (app_id_salt & 0xFFFFF); // 3dmoo hash + cmd_buff[3] = 0x6F534841 ^ (app_id_salt & 0xFFFFF); + + LOG_WARNING(Service_CFG, "(STUBBED) called app_id_salt=0x%X", app_id_salt); +} + +void GetRegionCanadaUSA(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + + cmd_buff[1] = RESULT_SUCCESS.raw; + + u8 canada_or_usa = 1; + if (canada_or_usa == Settings::values.region_value) { + cmd_buff[2] = 1; + } else { + cmd_buff[2] = 0; + } +} + +void GetSystemModel(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + u32 data; + + // TODO(Subv): Find out the correct error codes + cmd_buff[1] = Service::CFG::GetConfigInfoBlock(0x000F0004, 4, 0x8, + reinterpret_cast<u8*>(&data)).raw; + cmd_buff[2] = data & 0xFF; +} + +void GetModelNintendo2DS(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + u32 data; + + // TODO(Subv): Find out the correct error codes + cmd_buff[1] = Service::CFG::GetConfigInfoBlock(0x000F0004, 4, 0x8, + reinterpret_cast<u8*>(&data)).raw; + + u8 model = data & 0xFF; + if (model == Service::CFG::NINTENDO_2DS) + cmd_buff[2] = 0; + else + cmd_buff[2] = 1; +} + +void GetConfigInfoBlk2(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + u32 size = cmd_buff[1]; + u32 block_id = cmd_buff[2]; + u8* data_pointer = Memory::GetPointer(cmd_buff[4]); + + if (data_pointer == nullptr) { + cmd_buff[1] = -1; // TODO(Subv): Find the right error code + return; + } + + cmd_buff[1] = Service::CFG::GetConfigInfoBlock(block_id, size, 0x2, data_pointer).raw; +} + +void GetConfigInfoBlk8(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + u32 size = cmd_buff[1]; + u32 block_id = cmd_buff[2]; + u8* data_pointer = Memory::GetPointer(cmd_buff[4]); + + if (data_pointer == nullptr) { + cmd_buff[1] = -1; // TODO(Subv): Find the right error code + return; + } + + cmd_buff[1] = Service::CFG::GetConfigInfoBlock(block_id, size, 0x8, data_pointer).raw; +} + +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; +} + ResultCode GetConfigInfoBlock(u32 block_id, u32 size, u32 flag, u8* output) { // Read the header SaveFileConfig* config = reinterpret_cast<SaveFileConfig*>(cfg_config_file_buffer.data()); diff --git a/src/core/hle/service/cfg/cfg.h b/src/core/hle/service/cfg/cfg.h index 3488c40d0..ff76dc9dc 100644 --- a/src/core/hle/service/cfg/cfg.h +++ b/src/core/hle/service/cfg/cfg.h @@ -6,6 +6,7 @@ #include <array> #include "core/hle/result.h" +#include "core/hle/service/service.h" namespace Service { namespace CFG { @@ -40,6 +41,169 @@ struct SaveConfigBlockEntry { u16 flags; ///< The flags of the block, possibly used for access control }; +// TODO(Link Mauve): use a constexpr once MSVC starts supporting it. +#define C(code) ((code)[0] | ((code)[1] << 8)) + +static const std::array<u16, 187> country_codes = { + 0, C("JP"), 0, 0, 0, 0, 0, 0, // 0-7 + C("AI"), C("AG"), C("AR"), C("AW"), C("BS"), C("BB"), C("BZ"), C("BO"), // 8-15 + C("BR"), C("VG"), C("CA"), C("KY"), C("CL"), C("CO"), C("CR"), C("DM"), // 16-23 + C("DO"), C("EC"), C("SV"), C("GF"), C("GD"), C("GP"), C("GT"), C("GY"), // 24-31 + C("HT"), C("HN"), C("JM"), C("MQ"), C("MX"), C("MS"), C("AN"), C("NI"), // 32-39 + C("PA"), C("PY"), C("PE"), C("KN"), C("LC"), C("VC"), C("SR"), C("TT"), // 40-47 + C("TC"), C("US"), C("UY"), C("VI"), C("VE"), 0, 0, 0, // 48-55 + 0, 0, 0, 0, 0, 0, 0, 0, // 56-63 + C("AL"), C("AU"), C("AT"), C("BE"), C("BA"), C("BW"), C("BG"), C("HR"), // 64-71 + C("CY"), C("CZ"), C("DK"), C("EE"), C("FI"), C("FR"), C("DE"), C("GR"), // 72-79 + C("HU"), C("IS"), C("IE"), C("IT"), C("LV"), C("LS"), C("LI"), C("LT"), // 80-87 + C("LU"), C("MK"), C("MT"), C("ME"), C("MZ"), C("NA"), C("NL"), C("NZ"), // 88-95 + C("NO"), C("PL"), C("PT"), C("RO"), C("RU"), C("RS"), C("SK"), C("SI"), // 96-103 + C("ZA"), C("ES"), C("SZ"), C("SE"), C("CH"), C("TR"), C("GB"), C("ZM"), // 104-111 + C("ZW"), C("AZ"), C("MR"), C("ML"), C("NE"), C("TD"), C("SD"), C("ER"), // 112-119 + C("DJ"), C("SO"), C("AD"), C("GI"), C("GG"), C("IM"), C("JE"), C("MC"), // 120-127 + C("TW"), 0, 0, 0, 0, 0, 0, 0, // 128-135 + C("KR"), 0, 0, 0, 0, 0, 0, 0, // 136-143 + C("HK"), C("MO"), 0, 0, 0, 0, 0, 0, // 144-151 + C("ID"), C("SG"), C("TH"), C("PH"), C("MY"), 0, 0, 0, // 152-159 + C("CN"), 0, 0, 0, 0, 0, 0, 0, // 160-167 + C("AE"), C("IN"), C("EG"), C("OM"), C("QA"), C("KW"), C("SA"), C("SY"), // 168-175 + C("BH"), C("JO"), 0, 0, 0, 0, 0, 0, // 176-183 + C("SM"), C("VA"), C("BM") // 184-186 +}; + +#undef C + +/** + * 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); + +/** + * 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); + +/** + * 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::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::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); + +/** + * 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::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::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::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::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::UpdateConfigNANDSavegame service function + * Inputs: + * 0 : 0x04030000 / 0x08030000 + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + */ +void UpdateConfigNANDSavegame(Service::Interface* self); + +/** + * CFG::FormatConfig service function + * Inputs: + * 0 : 0x08060000 + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + */ +void FormatConfig(Service::Interface* self); + /// The maximum number of block entries that can exist in the config file static const u32 CONFIG_FILE_MAX_BLOCK_ENTRIES = 1479; diff --git a/src/core/hle/service/cfg/cfg_i.cpp b/src/core/hle/service/cfg/cfg_i.cpp index 6d1eee4e0..5aeadc084 100644 --- a/src/core/hle/service/cfg/cfg_i.cpp +++ b/src/core/hle/service/cfg/cfg_i.cpp @@ -8,59 +8,6 @@ namespace Service { namespace CFG { - -/** - * CFG_I::GetConfigInfoBlk8 service function - * This function is called by two command headers, - * there appears to be no difference between them according to 3dbrew - * 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 - */ -static void GetConfigInfoBlk8(Service::Interface* self) { - u32* cmd_buffer = Kernel::GetCommandBuffer(); - u32 size = cmd_buffer[1]; - u32 block_id = cmd_buffer[2]; - u8* data_pointer = Memory::GetPointer(cmd_buffer[4]); - - if (data_pointer == nullptr) { - cmd_buffer[1] = -1; // TODO(Subv): Find the right error code - return; - } - - cmd_buffer[1] = Service::CFG::GetConfigInfoBlock(block_id, size, 0x8, data_pointer).raw; -} - -/** - * CFG_I::UpdateConfigNANDSavegame service function - * This function is called by two command headers, - * there appears to be no difference between them according to 3dbrew - * Inputs: - * 0 : 0x04030000 / 0x08030000 - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -static void UpdateConfigNANDSavegame(Service::Interface* self) { - u32* cmd_buffer = Kernel::GetCommandBuffer(); - cmd_buffer[1] = Service::CFG::UpdateConfigNANDSavegame().raw; -} - -/** - * CFG_I::FormatConfig service function - * Inputs: - * 0 : 0x08060000 - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -static void FormatConfig(Service::Interface* self) { - u32* cmd_buffer = Kernel::GetCommandBuffer(); - cmd_buffer[1] = Service::CFG::FormatConfig().raw; -} const Interface::FunctionInfo FunctionTable[] = { {0x04010082, GetConfigInfoBlk8, "GetConfigInfoBlk8"}, @@ -68,7 +15,7 @@ const Interface::FunctionInfo FunctionTable[] = { {0x04030000, UpdateConfigNANDSavegame, "UpdateConfigNANDSavegame"}, {0x04040042, nullptr, "GetLocalFriendCodeSeedData"}, {0x04050000, nullptr, "GetLocalFriendCodeSeed"}, - {0x04060000, nullptr, "SecureInfoGetRegion"}, + {0x04060000, SecureInfoGetRegion, "SecureInfoGetRegion"}, {0x04070000, nullptr, "SecureInfoGetByte101"}, {0x04080042, nullptr, "SecureInfoGetSerialNo"}, {0x04090000, nullptr, "UpdateConfigBlk00040003"}, @@ -92,7 +39,7 @@ const Interface::FunctionInfo FunctionTable[] = { {0x08130000, nullptr, "VerifySigSecureInfo"}, {0x08140042, nullptr, "SecureInfoGetData"}, {0x08150042, nullptr, "SecureInfoGetSignature"}, - {0x08160000, nullptr, "SecureInfoGetRegion"}, + {0x08160000, SecureInfoGetRegion, "SecureInfoGetRegion"}, {0x08170000, nullptr, "SecureInfoGetByte101"}, {0x08180042, nullptr, "SecureInfoGetSerialNo"}, }; diff --git a/src/core/hle/service/cfg/cfg_s.cpp b/src/core/hle/service/cfg/cfg_s.cpp index d9a3e5d51..af4adba84 100644 --- a/src/core/hle/service/cfg/cfg_s.cpp +++ b/src/core/hle/service/cfg/cfg_s.cpp @@ -8,68 +8,6 @@ namespace Service { namespace CFG { - -/** - * CFG_S::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 - */ -static void GetConfigInfoBlk2(Service::Interface* self) { - u32* cmd_buffer = Kernel::GetCommandBuffer(); - u32 size = cmd_buffer[1]; - u32 block_id = cmd_buffer[2]; - u8* data_pointer = Memory::GetPointer(cmd_buffer[4]); - - if (data_pointer == nullptr) { - cmd_buffer[1] = -1; // TODO(Subv): Find the right error code - return; - } - - cmd_buffer[1] = Service::CFG::GetConfigInfoBlock(block_id, size, 0x2, data_pointer).raw; -} - -/** - * CFG_S::GetConfigInfoBlk8 service function - * Inputs: - * 0 : 0x04010082 - * 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 - */ -static void GetConfigInfoBlk8(Service::Interface* self) { - u32* cmd_buffer = Kernel::GetCommandBuffer(); - u32 size = cmd_buffer[1]; - u32 block_id = cmd_buffer[2]; - u8* data_pointer = Memory::GetPointer(cmd_buffer[4]); - - if (data_pointer == nullptr) { - cmd_buffer[1] = -1; // TODO(Subv): Find the right error code - return; - } - - cmd_buffer[1] = Service::CFG::GetConfigInfoBlock(block_id, size, 0x8, data_pointer).raw; -} - -/** - * CFG_S::UpdateConfigNANDSavegame service function - * Inputs: - * 0 : 0x04030000 - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - */ -static void UpdateConfigNANDSavegame(Service::Interface* self) { - u32* cmd_buffer = Kernel::GetCommandBuffer(); - cmd_buffer[1] = Service::CFG::UpdateConfigNANDSavegame().raw; -} const Interface::FunctionInfo FunctionTable[] = { {0x00010082, GetConfigInfoBlk2, "GetConfigInfoBlk2"}, diff --git a/src/core/hle/service/cfg/cfg_u.cpp b/src/core/hle/service/cfg/cfg_u.cpp index 221de9918..18939750b 100644 --- a/src/core/hle/service/cfg/cfg_u.cpp +++ b/src/core/hle/service/cfg/cfg_u.cpp @@ -2,12 +2,6 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#include "common/file_util.h" -#include "common/logging/log.h" -#include "common/string_util.h" - -#include "core/settings.h" -#include "core/file_sys/archive_systemsavedata.h" #include "core/hle/hle.h" #include "core/hle/service/cfg/cfg.h" #include "core/hle/service/cfg/cfg_u.h" @@ -15,219 +9,6 @@ namespace Service { namespace CFG { -// TODO(Link Mauve): use a constexpr once MSVC starts supporting it. -#define C(code) ((code)[0] | ((code)[1] << 8)) - -static const std::array<u16, 187> country_codes = { - 0, C("JP"), 0, 0, 0, 0, 0, 0, // 0-7 - C("AI"), C("AG"), C("AR"), C("AW"), C("BS"), C("BB"), C("BZ"), C("BO"), // 8-15 - C("BR"), C("VG"), C("CA"), C("KY"), C("CL"), C("CO"), C("CR"), C("DM"), // 16-23 - C("DO"), C("EC"), C("SV"), C("GF"), C("GD"), C("GP"), C("GT"), C("GY"), // 24-31 - C("HT"), C("HN"), C("JM"), C("MQ"), C("MX"), C("MS"), C("AN"), C("NI"), // 32-39 - C("PA"), C("PY"), C("PE"), C("KN"), C("LC"), C("VC"), C("SR"), C("TT"), // 40-47 - C("TC"), C("US"), C("UY"), C("VI"), C("VE"), 0, 0, 0, // 48-55 - 0, 0, 0, 0, 0, 0, 0, 0, // 56-63 - C("AL"), C("AU"), C("AT"), C("BE"), C("BA"), C("BW"), C("BG"), C("HR"), // 64-71 - C("CY"), C("CZ"), C("DK"), C("EE"), C("FI"), C("FR"), C("DE"), C("GR"), // 72-79 - C("HU"), C("IS"), C("IE"), C("IT"), C("LV"), C("LS"), C("LI"), C("LT"), // 80-87 - C("LU"), C("MK"), C("MT"), C("ME"), C("MZ"), C("NA"), C("NL"), C("NZ"), // 88-95 - C("NO"), C("PL"), C("PT"), C("RO"), C("RU"), C("RS"), C("SK"), C("SI"), // 96-103 - C("ZA"), C("ES"), C("SZ"), C("SE"), C("CH"), C("TR"), C("GB"), C("ZM"), // 104-111 - C("ZW"), C("AZ"), C("MR"), C("ML"), C("NE"), C("TD"), C("SD"), C("ER"), // 112-119 - C("DJ"), C("SO"), C("AD"), C("GI"), C("GG"), C("IM"), C("JE"), C("MC"), // 120-127 - C("TW"), 0, 0, 0, 0, 0, 0, 0, // 128-135 - C("KR"), 0, 0, 0, 0, 0, 0, 0, // 136-143 - C("HK"), C("MO"), 0, 0, 0, 0, 0, 0, // 144-151 - C("ID"), C("SG"), C("TH"), C("PH"), C("MY"), 0, 0, 0, // 152-159 - C("CN"), 0, 0, 0, 0, 0, 0, 0, // 160-167 - C("AE"), C("IN"), C("EG"), C("OM"), C("QA"), C("KW"), C("SA"), C("SY"), // 168-175 - C("BH"), C("JO"), 0, 0, 0, 0, 0, 0, // 176-183 - C("SM"), C("VA"), C("BM") // 184-186 -}; - -#undef C - -/** - * CFG_User::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 - */ -static void GetCountryCodeString(Service::Interface* self) { - u32* cmd_buffer = Kernel::GetCommandBuffer(); - u32 country_code_id = cmd_buffer[1]; - - 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_buffer[1] = ResultCode(ErrorDescription::NotFound, ErrorModule::Config, ErrorSummary::WrongArgument, ErrorLevel::Permanent).raw; - return; - } - - cmd_buffer[1] = 0; - cmd_buffer[2] = country_codes[country_code_id]; -} - -/** - * CFG_User::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 - */ -static void GetCountryCodeID(Service::Interface* self) { - u32* cmd_buffer = Kernel::GetCommandBuffer(); - u16 country_code = cmd_buffer[1]; - u16 country_code_id = 0; - - // The following algorithm will fail if the first country code isn't 0. - DEBUG_ASSERT(country_codes[0] == 0); - - for (u16 id = 0; id < country_codes.size(); ++id) { - if (country_codes[id] == country_code) { - country_code_id = id; - break; - } - } - - if (0 == country_code_id) { - LOG_ERROR(Service_CFG, "requested country code name=%c%c is invalid", country_code & 0xff, country_code >> 8); - cmd_buffer[1] = ResultCode(ErrorDescription::NotFound, ErrorModule::Config, ErrorSummary::WrongArgument, ErrorLevel::Permanent).raw; - cmd_buffer[2] = 0xFFFF; - return; - } - - cmd_buffer[1] = 0; - cmd_buffer[2] = country_code_id; -} - -/** - * CFG_User::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 - */ -static void GetConfigInfoBlk2(Service::Interface* self) { - u32* cmd_buffer = Kernel::GetCommandBuffer(); - u32 size = cmd_buffer[1]; - u32 block_id = cmd_buffer[2]; - u8* data_pointer = Memory::GetPointer(cmd_buffer[4]); - - if (data_pointer == nullptr) { - cmd_buffer[1] = -1; // TODO(Subv): Find the right error code - return; - } - - cmd_buffer[1] = Service::CFG::GetConfigInfoBlock(block_id, size, 0x2, data_pointer).raw; -} - -/** - * CFG_User::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 - */ -static void SecureInfoGetRegion(Service::Interface* self) { - u32* cmd_buffer = Kernel::GetCommandBuffer(); - - cmd_buffer[1] = RESULT_SUCCESS.raw; // No Error - cmd_buffer[2] = Settings::values.region_value; -} - -/** - * CFG_User::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 - */ -static void GenHashConsoleUnique(Service::Interface* self) { - u32* cmd_buffer = Kernel::GetCommandBuffer(); - u32 app_id_salt = cmd_buffer[1]; - - cmd_buffer[1] = RESULT_SUCCESS.raw; // No Error - cmd_buffer[2] = 0x33646D6F ^ (app_id_salt & 0xFFFFF); // 3dmoo hash - cmd_buffer[3] = 0x6F534841 ^ (app_id_salt & 0xFFFFF); - - LOG_WARNING(Service_CFG, "(STUBBED) called app_id_salt=0x%08X", app_id_salt); -} - -/** - * CFG_User::GetRegionCanadaUSA service function - * Inputs: - * 1 : None - * Outputs: - * 0 : Result Header code - * 1 : Result of function, 0 on success, otherwise error code - * 2 : Output value - */ -static void GetRegionCanadaUSA(Service::Interface* self) { - u32* cmd_buffer = Kernel::GetCommandBuffer(); - - cmd_buffer[1] = RESULT_SUCCESS.raw; // No Error - - u8 canada_or_usa = 1; - if (canada_or_usa == Settings::values.region_value) { - cmd_buffer[2] = 1; - } else { - cmd_buffer[2] = 0; - } -} - -/** - * CFG_User::GetSystemModel service function - * Inputs: - * 0 : 0x00050000 - * Outputs: - * 1 : Result of function, 0 on success, otherwise error code - * 2 : Model of the console - */ -static void GetSystemModel(Service::Interface* self) { - u32* cmd_buffer = Kernel::GetCommandBuffer(); - u32 data; - - // TODO(Subv): Find out the correct error codes - cmd_buffer[1] = Service::CFG::GetConfigInfoBlock(0x000F0004, 4, 0x8, - reinterpret_cast<u8*>(&data)).raw; - cmd_buffer[2] = data & 0xFF; -} - -/** - * CFG_User::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 - */ -static void GetModelNintendo2DS(Service::Interface* self) { - u32* cmd_buffer = Kernel::GetCommandBuffer(); - u32 data; - - // TODO(Subv): Find out the correct error codes - cmd_buffer[1] = Service::CFG::GetConfigInfoBlock(0x000F0004, 4, 0x8, - reinterpret_cast<u8*>(&data)).raw; - - u8 model = data & 0xFF; - if (model == Service::CFG::NINTENDO_2DS) - cmd_buffer[2] = 0; - else - cmd_buffer[2] = 1; -} - const Interface::FunctionInfo FunctionTable[] = { {0x00010082, GetConfigInfoBlk2, "GetConfigInfoBlk2"}, {0x00020000, SecureInfoGetRegion, "SecureInfoGetRegion"}, |