Advertisement
Guest User

Untitled

a guest
Dec 18th, 2014
193
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.61 KB | None | 0 0
  1. diff --git a/src/core/hle/service/cfg_u.cpp b/src/core/hle/service/cfg_u.cpp
  2. index 2e9d7bf..6c2323a 100644
  3. --- a/src/core/hle/service/cfg_u.cpp
  4. +++ b/src/core/hle/service/cfg_u.cpp
  5. @@ -2,7 +2,9 @@
  6. // Licensed under GPLv2
  7. // Refer to the license.txt file included.
  8.  
  9. +#include "common/file_util.h"
  10. #include "common/log.h"
  11. +#include "core/file_sys/archive_systemsavedata.h"
  12. #include "core/hle/hle.h"
  13. #include "core/hle/service/cfg_u.h"
  14.  
  15. @@ -11,6 +13,11 @@
  16.  
  17. namespace CFG_U {
  18.  
  19. +static FileSys::Archive_SystemSaveData* cfg_system_save_data = nullptr;
  20. +static const u64 CFG_SAVE_ID = 0x00010017;
  21. +static const u64 CONSOLE_UNIQUE_ID = 0xDEADC0DE;
  22. +static const char CONSOLE_USERNAME[0x1C] = "THIS IS CITRAAAAAAAAAAAAAA";
  23. +
  24. // TODO(Link Mauve): use a constexpr once MSVC starts supporting it.
  25. #define C(code) ((code)[0] | ((code)[1] << 8))
  26.  
  27. @@ -99,8 +106,86 @@ static void GetCountryCodeID(Service::Interface* self) {
  28. cmd_buffer[2] = country_code_id;
  29. }
  30.  
  31. +/// Block header in the config savedata file
  32. +struct SaveConfigBlockEntry {
  33. + u32 block_id;
  34. + u32 offset_or_data;
  35. + u16 size;
  36. + u16 flags;
  37. +};
  38. +
  39. +/// The header of the config savedata file,
  40. +/// contains information about the blocks in the file
  41. +struct SaveFileConfig {
  42. + u16 total_entries;
  43. + u16 data_entries_offset;
  44. + SaveConfigBlockEntry block_entries[1479];
  45. +};
  46. +
  47. +/* Reads a block with the specified id and flag from the Config savegame file and writes the output to output.
  48. + * The input size must match exactly the size of the requested block
  49. + * TODO(Subv): This should actually be in some file common to the CFG process
  50. + * @param block_id The id of the block we want to read
  51. + * @param size The size of the block we want to read
  52. + * @param flag The requested block must have this flag set
  53. + * @param output A pointer where we will write the read data
  54. + * @returns ResultCode indicating the result of the operation, 0 on success
  55. + */
  56. +ResultCode GetConfigInfoBlock(u32 block_id, u32 size, u32 flag, u8* output) {
  57. + FileSys::Mode mode;
  58. + mode.hex = 0;
  59. + mode.read_flag = 1;
  60. + FileSys::Path path("config");
  61. + auto file = cfg_system_save_data->OpenFile(path, mode);
  62. + _dbg_assert_msg_(Service_CFG, file != nullptr, "Could not open the CFG service config file");
  63. + SaveFileConfig config;
  64. + size_t read = file->Read(0, sizeof(SaveFileConfig), reinterpret_cast<u8*>(&config));
  65. +
  66. + if (read != sizeof(SaveFileConfig)) {
  67. + LOG_CRITICAL(Service_CFG, "The config savefile is corrupted");
  68. + return ResultCode(-1); // TODO(Subv): Find the correct error code
  69. + }
  70. +
  71. + auto itr = std::find_if(std::begin(config.block_entries), std::end(config.block_entries),
  72. + [&](SaveConfigBlockEntry const& entry) {
  73. + return entry.block_id == block_id && entry.size == size && (entry.flags & flag);
  74. + });
  75. +
  76. + if (itr == std::end(config.block_entries)) {
  77. + LOG_TRACE(Service_CFG, "Config block %u with size %u and flags %u not found", block_id, size, flag);
  78. + return ResultCode(-1); // TODO(Subv): Find the correct error code
  79. + }
  80. +
  81. + // The data is located in the block header itself if the size is less than 4 bytes
  82. + if (itr->size <= 4) {
  83. + memcpy(output, &itr->offset_or_data, itr->size);
  84. + } else {
  85. + size_t data_read = file->Read(itr->offset_or_data, itr->size, output);
  86. + if (data_read != itr->size) {
  87. + LOG_CRITICAL(Service_CFG, "The config savefile is corrupted");
  88. + return ResultCode(-1); // TODO(Subv): Find the correct error code
  89. + }
  90. + }
  91. +
  92. + return RESULT_SUCCESS;
  93. +}
  94. +
  95. +static void GetConfigInfoBlk2(Service::Interface* self) {
  96. + u32* cmd_buffer = Kernel::GetCommandBuffer();
  97. + u32 size = cmd_buffer[1];
  98. + u32 block_id = cmd_buffer[2];
  99. + u8* data_pointer = Memory::GetPointer(cmd_buffer[4]);
  100. +
  101. + if (data_pointer == nullptr) {
  102. + cmd_buffer[1] = -1; // TODO(Subv): Find the right error code
  103. + return;
  104. + }
  105. +
  106. + cmd_buffer[1] = GetConfigInfoBlock(block_id, size, 0x2, data_pointer).raw;
  107. +}
  108. +
  109. const Interface::FunctionInfo FunctionTable[] = {
  110. - {0x00010082, nullptr, "GetConfigInfoBlk2"},
  111. + {0x00010082, GetConfigInfoBlk2, "GetConfigInfoBlk2"},
  112. {0x00020000, nullptr, "SecureInfoGetRegion"},
  113. {0x00030000, nullptr, "GenHashConsoleUnique"},
  114. {0x00040000, nullptr, "GetRegionCanadaUSA"},
  115. @@ -116,9 +201,51 @@ const Interface::FunctionInfo FunctionTable[] = {
  116.  
  117. Interface::Interface() {
  118. Register(FunctionTable, ARRAY_SIZE(FunctionTable));
  119. + // TODO(Subv): In the future we should use the FS service to query this archive,
  120. + // currently it is not possible because you can only have one open archive of the same type at any time
  121. + std::string syssavedata_directory = FileUtil::GetUserPath(D_SYSSAVEDATA_IDX);
  122. + cfg_system_save_data = new FileSys::Archive_SystemSaveData(syssavedata_directory, CFG_SAVE_ID);
  123. + if (!cfg_system_save_data->Initialize()) {
  124. + LOG_CRITICAL(Service_CFG, "Could not initialize SystemSaveData archive for the CFG:U service");
  125. + } else {
  126. + // Try to open the file in read-only mode to check its existence
  127. + FileSys::Mode mode;
  128. + mode.hex = 0;
  129. + mode.read_flag = 1;
  130. + FileSys::Path path("config");
  131. + auto file = cfg_system_save_data->OpenFile(path, mode);
  132. + if (file == nullptr) {
  133. + mode.create_flag = 1;
  134. + mode.write_flag = 1;
  135. + mode.read_flag = 0;
  136. + // Re-open the file in write-create mode
  137. + file = cfg_system_save_data->OpenFile(path, mode);
  138. +
  139. + // Setup the default config file data header
  140. + SaveFileConfig config = { 3, 0, {} };
  141. + u32 offset = sizeof(SaveFileConfig);
  142. + // Console-unique ID
  143. + config.block_entries[0] = { 0x00090001, offset, 0x8, 0xE };
  144. + offset += 0x8;
  145. + // Username
  146. + config.block_entries[1] = { 0x000A0000, offset, 0x1C, 0xE };
  147. + offset += 0x1C;
  148. + // System Model (Nintendo 3DS XL)
  149. + config.block_entries[2] = { 0x000F0004, 1, 0x4, 0x8 };
  150. +
  151. + // Write the config file data header to the config file
  152. + file->Write(0, sizeof(SaveFileConfig), 1, reinterpret_cast<u8*>(&config));
  153. + // Write the data itself
  154. + file->Write(config.block_entries[0].offset_or_data, 0x8, 1,
  155. + reinterpret_cast<u8 const*>(&CONSOLE_UNIQUE_ID));
  156. + file->Write(config.block_entries[1].offset_or_data, 0x1C, 1,
  157. + reinterpret_cast<u8 const*>(CONSOLE_USERNAME));
  158. + }
  159. + }
  160. }
  161.  
  162. Interface::~Interface() {
  163. + delete cfg_system_save_data;
  164. }
  165.  
  166. } // namespace
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement