diff options
| author | 2014-12-19 21:51:31 -0500 | |
|---|---|---|
| committer | 2014-12-21 16:39:14 -0500 | |
| commit | 9029efd873758a1cd668e8394d089d4486bc9c43 (patch) | |
| tree | 566fe12195043fd614d9912ef6427b173c247b20 /src | |
| parent | CFG: Implemented block 0x00070001 in the config savefile (diff) | |
| download | yuzu-9029efd873758a1cd668e8394d089d4486bc9c43.tar.gz yuzu-9029efd873758a1cd668e8394d089d4486bc9c43.tar.xz yuzu-9029efd873758a1cd668e8394d089d4486bc9c43.zip | |
CFG:U: Implemented some more blocks
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/hle/service/cfg_u.cpp | 34 |
1 files changed, 30 insertions, 4 deletions
diff --git a/src/core/hle/service/cfg_u.cpp b/src/core/hle/service/cfg_u.cpp index ef8e8c3c9..0e56f1245 100644 --- a/src/core/hle/service/cfg_u.cpp +++ b/src/core/hle/service/cfg_u.cpp | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | #include "common/file_util.h" | 5 | #include "common/file_util.h" |
| 6 | #include "common/log.h" | 6 | #include "common/log.h" |
| 7 | #include "common/string_util.h" | ||
| 7 | #include "core/file_sys/archive_systemsavedata.h" | 8 | #include "core/file_sys/archive_systemsavedata.h" |
| 8 | #include "core/hle/hle.h" | 9 | #include "core/hle/hle.h" |
| 9 | #include "core/hle/service/cfg_u.h" | 10 | #include "core/hle/service/cfg_u.h" |
| @@ -35,11 +36,21 @@ enum SystemLanguage { | |||
| 35 | LANGUAGE_RU | 36 | LANGUAGE_RU |
| 36 | }; | 37 | }; |
| 37 | 38 | ||
| 39 | struct UsernameBlock { | ||
| 40 | char16_t username[10]; ///< Exactly 20 bytes long, padded with zeros at the end if necessary | ||
| 41 | u32 zero; | ||
| 42 | u32 ng_word; | ||
| 43 | }; | ||
| 44 | static_assert(sizeof(UsernameBlock) == 0x1C, "Size of UsernameBlock must be 0x1C"); | ||
| 45 | |||
| 38 | static std::unique_ptr<FileSys::Archive_SystemSaveData> cfg_system_save_data; | 46 | static std::unique_ptr<FileSys::Archive_SystemSaveData> cfg_system_save_data; |
| 39 | static const u64 CFG_SAVE_ID = 0x00010017; | 47 | static const u64 CFG_SAVE_ID = 0x00010017; |
| 40 | static const u64 CONSOLE_UNIQUE_ID = 0xDEADC0DE; | 48 | static const u64 CONSOLE_UNIQUE_ID = 0xDEADC0DE; |
| 41 | static const u32 CONSOLE_MODEL = NINTENDO_3DS_XL; | 49 | static const u32 CONSOLE_MODEL = NINTENDO_3DS_XL; |
| 42 | static const u8 CONSOLE_LANGUAGE = LANGUAGE_EN; | 50 | static const u8 CONSOLE_LANGUAGE = LANGUAGE_EN; |
| 51 | static const char CONSOLE_USERNAME[0x14] = "CITRA"; | ||
| 52 | /// This will be initialized in the Interface constructor, and will be used when creating the block | ||
| 53 | static UsernameBlock CONSOLE_USERNAME_BLOCK; | ||
| 43 | /// TODO(Subv): Find out what this actually is | 54 | /// TODO(Subv): Find out what this actually is |
| 44 | static const u8 SOUND_OUTPUT_MODE = 2; | 55 | static const u8 SOUND_OUTPUT_MODE = 2; |
| 45 | static const u32 CONFIG_SAVEFILE_SIZE = 0x8000; | 56 | static const u32 CONFIG_SAVEFILE_SIZE = 0x8000; |
| @@ -55,6 +66,9 @@ static const u8 STEREO_CAMERA_SETTINGS[32] = { | |||
| 55 | // TODO(Link Mauve): use a constexpr once MSVC starts supporting it. | 66 | // TODO(Link Mauve): use a constexpr once MSVC starts supporting it. |
| 56 | #define C(code) ((code)[0] | ((code)[1] << 8)) | 67 | #define C(code) ((code)[0] | ((code)[1] << 8)) |
| 57 | 68 | ||
| 69 | /// TODO(Subv): Find what the other bytes are | ||
| 70 | static const std::array<u8, 4> COUNTRY_INFO = { 0, 0, 0, C("US") }; | ||
| 71 | |||
| 58 | static const std::array<u16, 187> country_codes = { | 72 | static const std::array<u16, 187> country_codes = { |
| 59 | 0, C("JP"), 0, 0, 0, 0, 0, 0, // 0-7 | 73 | 0, C("JP"), 0, 0, 0, 0, 0, 0, // 0-7 |
| 60 | C("AI"), C("AG"), C("AR"), C("AW"), C("BS"), C("BB"), C("BZ"), C("BO"), // 8-15 | 74 | C("AI"), C("AG"), C("AR"), C("AW"), C("BS"), C("BB"), C("BZ"), C("BO"), // 8-15 |
| @@ -207,7 +221,7 @@ ResultCode CreateConfigInfoBlk(u32 block_id, u32 size, u32 flags, u8 const* data | |||
| 207 | config->block_entries[config->total_entries] = { block_id, 0, size, flags }; | 221 | config->block_entries[config->total_entries] = { block_id, 0, size, flags }; |
| 208 | if (size > 4) { | 222 | if (size > 4) { |
| 209 | s32 total_entries = config->total_entries - 1; | 223 | s32 total_entries = config->total_entries - 1; |
| 210 | u32 offset = 0; | 224 | u32 offset = config->data_entries_offset; |
| 211 | // Perform a search to locate the next offset for the new data | 225 | // Perform a search to locate the next offset for the new data |
| 212 | while (total_entries >= 0) { | 226 | while (total_entries >= 0) { |
| 213 | // Ignore the blocks that don't have a separate data offset | 227 | // Ignore the blocks that don't have a separate data offset |
| @@ -221,12 +235,10 @@ ResultCode CreateConfigInfoBlk(u32 block_id, u32 size, u32 flags, u8 const* data | |||
| 221 | break; | 235 | break; |
| 222 | } | 236 | } |
| 223 | 237 | ||
| 224 | offset += config->data_entries_offset; | ||
| 225 | |||
| 226 | config->block_entries[config->total_entries].offset_or_data = offset; | 238 | config->block_entries[config->total_entries].offset_or_data = offset; |
| 227 | 239 | ||
| 228 | // Write the data at the new offset | 240 | // Write the data at the new offset |
| 229 | memcpy(&cfg_config_file_buffer[config->data_entries_offset + offset], data, size); | 241 | memcpy(&cfg_config_file_buffer[offset], data, size); |
| 230 | } else { | 242 | } else { |
| 231 | // The offset_or_data field in the header contains the data itself if it's 4 bytes or less | 243 | // The offset_or_data field in the header contains the data itself if it's 4 bytes or less |
| 232 | memcpy(&config->block_entries[config->total_entries].offset_or_data, data, size); | 244 | memcpy(&config->block_entries[config->total_entries].offset_or_data, data, size); |
| @@ -295,6 +307,12 @@ ResultCode FormatConfig() { | |||
| 295 | res = CreateConfigInfoBlk(0x00070001, 0x1, 0xE, &SOUND_OUTPUT_MODE); | 307 | res = CreateConfigInfoBlk(0x00070001, 0x1, 0xE, &SOUND_OUTPUT_MODE); |
| 296 | if (!res.IsSuccess()) | 308 | if (!res.IsSuccess()) |
| 297 | return res; | 309 | return res; |
| 310 | res = CreateConfigInfoBlk(0x000B0000, 0x4, 0xE, COUNTRY_INFO.data()); | ||
| 311 | if (!res.IsSuccess()) | ||
| 312 | return res; | ||
| 313 | res = CreateConfigInfoBlk(0x000A0000, 0x1C, 0xE, reinterpret_cast<u8*>(&CONSOLE_USERNAME_BLOCK)); | ||
| 314 | if (!res.IsSuccess()) | ||
| 315 | return res; | ||
| 298 | // Save the buffer to the file | 316 | // Save the buffer to the file |
| 299 | res = UpdateConfigNANDSavegame(); | 317 | res = UpdateConfigNANDSavegame(); |
| 300 | if (!res.IsSuccess()) | 318 | if (!res.IsSuccess()) |
| @@ -402,6 +420,14 @@ Interface::Interface() { | |||
| 402 | file->Read(0, CONFIG_SAVEFILE_SIZE, cfg_config_file_buffer.data()); | 420 | file->Read(0, CONFIG_SAVEFILE_SIZE, cfg_config_file_buffer.data()); |
| 403 | return; | 421 | return; |
| 404 | } | 422 | } |
| 423 | |||
| 424 | // Initialize the Username block | ||
| 425 | // TODO(Subv): Do this somewhere else, or in another way | ||
| 426 | CONSOLE_USERNAME_BLOCK.ng_word = 0; | ||
| 427 | CONSOLE_USERNAME_BLOCK.zero = 0; | ||
| 428 | std::fill(std::begin(CONSOLE_USERNAME_BLOCK.username) + | ||
| 429 | Common::UTF8ToUTF16(CONSOLE_USERNAME).copy(CONSOLE_USERNAME_BLOCK.username, 0x14), | ||
| 430 | std::end(CONSOLE_USERNAME_BLOCK.username), 0); | ||
| 405 | FormatConfig(); | 431 | FormatConfig(); |
| 406 | } | 432 | } |
| 407 | 433 | ||