modules/SceRegistryMgr: Initial implement of regmgr functions.

This commit is contained in:
Zangetsu38
2023-07-05 12:10:12 +02:00
committed by Zangetsu
parent 41239bde8d
commit 5810acf29c
16 changed files with 634 additions and 54 deletions
+1
View File
@@ -134,6 +134,7 @@ add_subdirectory(module)
add_subdirectory(modules)
add_subdirectory(motion)
add_subdirectory(nids)
add_subdirectory(regmgr)
add_subdirectory(renderer)
add_subdirectory(rtc)
add_subdirectory(shader)
+1 -1
View File
@@ -5,4 +5,4 @@ add_library(
target_include_directories(emuenv INTERFACE include)
target_link_libraries(emuenv PUBLIC mem)
target_link_libraries(emuenv PRIVATE app audio config ctrl dialog display ime io kernel lang miniz motion net ngs nids np renderer touch gdbstub codec packages http)
target_link_libraries(emuenv PRIVATE app audio config ctrl dialog display ime io kernel lang miniz motion net ngs nids np regmgr renderer touch gdbstub codec packages http)
+3
View File
@@ -53,6 +53,7 @@ struct NpState;
struct DisplayState;
struct DialogState;
struct Ime;
struct RegMgrState;
struct SfoFile;
struct GDBState;
struct HTTPState;
@@ -96,6 +97,7 @@ private:
std::unique_ptr<DisplayState> _display;
std::unique_ptr<DialogState> _common_dialog;
std::unique_ptr<Ime> _ime;
std::unique_ptr<RegMgrState> _regmgr;
std::unique_ptr<SfoFile> _sfo_handle;
std::unique_ptr<GDBState> _gdb;
std::unique_ptr<HTTPState> _http;
@@ -151,6 +153,7 @@ public:
DisplayState &display;
DialogState &common_dialog;
Ime &ime;
RegMgrState &regmgr;
SfoFile &sfo_handle;
NIDSet missing_nids;
float dpi_scale = 1.f;
+3
View File
@@ -34,6 +34,7 @@
#include <nids/types.h>
#include <np/state.h>
#include <packages/sfo.h>
#include <regmgr/state.h>
#include <renderer/state.h>
#include <touch/state.h>
@@ -76,6 +77,8 @@ EmuEnvState::EmuEnvState()
, common_dialog(*_common_dialog)
, _ime(new Ime)
, ime(*_ime)
, _regmgr(new RegMgrState)
, regmgr(*_regmgr)
, _sfo_handle(new SfoFile)
, sfo_handle(*_sfo_handle)
, _gdb(new GDBState)
+1 -1
View File
@@ -50,6 +50,6 @@ add_library(
)
target_include_directories(gui PUBLIC include ${CMAKE_SOURCE_DIR}/vita3k)
target_link_libraries(gui PUBLIC app compat config dialog emuenv https ime imgui glutil lang np)
target_link_libraries(gui PUBLIC app compat config dialog emuenv https ime imgui glutil lang regmgr np)
target_link_libraries(gui PRIVATE audio ctrl kernel miniz psvpfsparser pugixml::pugixml stb renderer packages sdl2 vkutil host::dialog)
target_link_libraries(gui PUBLIC tracy)
+2
View File
@@ -31,6 +31,7 @@
#include <io/vfs.h>
#include <lang/functions.h>
#include <packages/sfo.h>
#include <regmgr/functions.h>
#include <util/fs.h>
#include <util/log.h>
#include <util/string_utils.h>
@@ -711,6 +712,7 @@ void init(GuiState &gui, EmuEnvState &emuenv) {
get_sys_apps_title(gui, emuenv);
init_home(gui, emuenv);
regmgr::init_regmgr(emuenv.regmgr, emuenv.pref_path);
// Initialize trophy callback
emuenv.np.trophy_state.trophy_unlock_callback = [&gui](NpTrophyUnlockCallbackData &callback_data) {
+1 -1
View File
@@ -750,7 +750,7 @@ void draw_home_screen(GuiState &gui, EmuEnvState &emuenv) {
const auto display_app = [&](const std::vector<gui::App> &apps_list, std::map<std::string, ImGui_Texture> &apps_icon) {
for (const auto &app : apps_list) {
bool selected = false;
const auto is_not_sys_app = app.title_id.find("NPXS") == std::string::npos;
const auto is_not_sys_app = app.path.find("NPXS") == std::string::npos;
if (is_not_sys_app) {
// Filter app by region and type
+13
View File
@@ -110,8 +110,13 @@ bool init(IOState &io, const fs::path &base_path, const fs::path &pref_path, boo
const fs::path ux0_data{ ux0 / "data" };
const fs::path uma0_data{ uma0 / "data" };
const fs::path ux0_app{ ux0 / "app" };
const fs::path ux0_picture{ ux0 / "picture" };
const fs::path ux0_theme{ ux0 / "theme" };
const fs::path ux0_video{ ux0 / "video" };
const fs::path ux0_user{ ux0 / "user" };
const fs::path vd0{ pref_path / (+VitaIoDevice::vd0)._to_string() };
const fs::path vd0_registry{ vd0 / "registry" };
const fs::path vd0_network{ vd0 / "network" };
if (!fs::exists(ux0))
fs::create_directories(ux0);
@@ -119,14 +124,22 @@ bool init(IOState &io, const fs::path &base_path, const fs::path &pref_path, boo
fs::create_directory(ux0_data);
if (!fs::exists(ux0_app))
fs::create_directory(ux0_app);
if (!fs::exists(ux0_picture))
fs::create_directory(ux0_picture);
if (!fs::exists(ux0_theme))
fs::create_directory(ux0_theme);
if (!fs::exists(ux0_video))
fs::create_directory(ux0_video);
if (!fs::exists(ux0_user))
fs::create_directory(ux0_user);
if (!fs::exists(uma0))
fs::create_directory(uma0);
if (!fs::exists(uma0_data))
fs::create_directory(uma0_data);
if (!fs::exists(vd0_registry))
fs::create_directories(vd0_registry);
if (!fs::exists(vd0_network))
fs::create_directories(vd0_network);
fs::create_directories(base_path / "cache/shaders");
fs::create_directory(base_path / "shaderlog");
+43 -27
View File
@@ -17,6 +17,8 @@
#include "SceRegMgr.h"
#include <regmgr/functions.h>
#include <util/tracy.h>
TRACY_MODULE_NAME(SceRegMgr);
@@ -40,30 +42,34 @@ EXPORT(int, sceRegMgrGetInitVals) {
return UNIMPLEMENTED();
}
EXPORT(int, sceRegMgrGetKeyBin) {
TRACY_FUNC(sceRegMgrGetKeyBin);
return UNIMPLEMENTED();
EXPORT(int, sceRegMgrGetKeyBin, const char *category, const char *name, void *buf, SceSize bufSize) {
TRACY_FUNC(sceRegMgrGetKeyBin, category, name, buf, bufSize);
memcpy(buf, regmgr::get_str_value(emuenv.regmgr, category, name).c_str(), bufSize);
return 0;
}
EXPORT(int, sceRegMgrGetKeyInt, const char *category, const char *name, int *buf) {
EXPORT(int, sceRegMgrGetKeyInt, const char *category, const char *name, SceInt32 *buf) {
TRACY_FUNC(sceRegMgrGetKeyInt, category, name, buf);
if ((std::string(category) == "/CONFIG/PSPEMU") && (std::string(name) == "emu_list_flag")) {
STUBBED("Stubbed");
*buf = 1;
*buf = regmgr::get_int_value(emuenv.regmgr, category, name);
return 0;
} else
return UNIMPLEMENTED();
return 0;
}
EXPORT(int, sceRegMgrGetKeyStr) {
TRACY_FUNC(sceRegMgrGetKeyStr);
return UNIMPLEMENTED();
EXPORT(int, sceRegMgrGetKeyStr, const char *category, const char *name, char *buf, const SceSize bufSize) {
TRACY_FUNC(sceRegMgrGetKeyStr, category, name, buf, bufSize);
strncpy(buf, regmgr::get_str_value(emuenv.regmgr, category, name).c_str(), bufSize);
return 0;
}
EXPORT(int, sceRegMgrGetKeys) {
TRACY_FUNC(sceRegMgrGetKeys);
return UNIMPLEMENTED();
EXPORT(int, sceRegMgrGetKeys, const char *category, Keys *keys, const SceUInt32 elementsNumber) {
TRACY_FUNC(sceRegMgrGetKeys, category, keys, elementsNumber);
for (SceUInt32 i = 0; i < elementsNumber; i++) {
keys[i].value = regmgr::get_int_value(emuenv.regmgr, category, keys[i].name.get(emuenv.mem));
}
return 0;
}
EXPORT(int, sceRegMgrGetKeysInfo) {
@@ -96,24 +102,34 @@ EXPORT(int, sceRegMgrResetRegistryLv) {
return UNIMPLEMENTED();
}
EXPORT(int, sceRegMgrSetKeyBin) {
TRACY_FUNC(sceRegMgrSetKeyBin);
return UNIMPLEMENTED();
EXPORT(int, sceRegMgrSetKeyBin, const char *category, const char *name, const void *buf, SceSize bufSize) {
TRACY_FUNC(sceRegMgrSetKeyBin, category, name, buf, bufSize);
regmgr::set_bin_value(emuenv.regmgr, emuenv.pref_path, category, name, buf, bufSize);
return 0;
}
EXPORT(int, sceRegMgrSetKeyInt, const char *category, const char *name, int buf) {
EXPORT(int, sceRegMgrSetKeyInt, const char *category, const char *name, const SceInt32 buf) {
TRACY_FUNC(sceRegMgrSetKeyInt, category, name, buf);
return UNIMPLEMENTED();
regmgr::set_int_value(emuenv.regmgr, emuenv.pref_path, category, name, buf);
return 0;
}
EXPORT(int, sceRegMgrSetKeyStr) {
TRACY_FUNC(sceRegMgrSetKeyStr);
return UNIMPLEMENTED();
EXPORT(int, sceRegMgrSetKeyStr, const char *category, const char *name, char *buf, const SceSize bufSize) {
TRACY_FUNC(sceRegMgrSetKeyStr, category, name, buf, bufSize);
regmgr::set_str_value(emuenv.regmgr, emuenv.pref_path, category, name, buf);
return 0;
}
EXPORT(int, sceRegMgrSetKeys) {
TRACY_FUNC(sceRegMgrSetKeys);
return UNIMPLEMENTED();
EXPORT(int, sceRegMgrSetKeys, const char *category, const Keys *keys, const SceInt32 elementsNumber) {
TRACY_FUNC(sceRegMgrSetKeys, category, keys, elementsNumber);
for (auto i = 0; i < elementsNumber; i++) {
regmgr::set_int_value(emuenv.regmgr, emuenv.pref_path, category, keys[i].name.get(emuenv.mem), keys[i].value);
}
return 0;
}
EXPORT(int, sceRegMgrStartCallback) {
@@ -17,32 +17,61 @@
#include "SceRegMgrForGame.h"
#include <regmgr/functions.h>
#include <util/tracy.h>
TRACY_MODULE_NAME(SceRegMgrForGame);
EXPORT(int, sceRegMgrSystemIsBlueScreen) {
return UNIMPLEMENTED();
}
EXPORT(int, sceRegMgrSystemParamGetBin) {
return UNIMPLEMENTED();
EXPORT(int, sceRegMgrSystemParamGetBin, const int id, void *buf, SceSize bufSize) {
TRACY_FUNC(sceRegMgrSystemParamGetBin, id, buf, bufSize);
const auto [category, name] = regmgr::get_category_and_name_by_id(id, export_name);
memcpy(buf, regmgr::get_str_value(emuenv.regmgr, category, name).c_str(), bufSize);
return 0;
}
EXPORT(int, sceRegMgrSystemParamGetInt) {
return UNIMPLEMENTED();
EXPORT(int, sceRegMgrSystemParamGetInt, const int id, SceInt32 *buf) {
TRACY_FUNC(sceRegMgrSystemParamGetInt, id, buf);
const auto [category, name] = regmgr::get_category_and_name_by_id(id, export_name);
*buf = regmgr::get_int_value(emuenv.regmgr, category, name);
return 0;
}
EXPORT(int, sceRegMgrSystemParamGetStr) {
return UNIMPLEMENTED();
EXPORT(int, sceRegMgrSystemParamGetStr, const int id, char *buf, const SceSize bufSize) {
TRACY_FUNC(sceRegMgrSystemParamGetStr, id, buf, bufSize);
const auto [category, name] = regmgr::get_category_and_name_by_id(id, export_name);
strncpy(buf, regmgr::get_str_value(emuenv.regmgr, category, name).c_str(), bufSize);
return 0;
}
EXPORT(int, sceRegMgrSystemParamSetBin) {
return UNIMPLEMENTED();
EXPORT(int, sceRegMgrSystemParamSetBin, const int id, const void *buf, const SceSize bufSize) {
TRACY_FUNC(sceRegMgrSystemParamSetBin, id, buf, bufSize);
const auto [category, name] = regmgr::get_category_and_name_by_id(id, export_name);
regmgr::set_bin_value(emuenv.regmgr, emuenv.pref_path, category, name, buf, bufSize);
return 0;
}
EXPORT(int, sceRegMgrSystemParamSetInt) {
return UNIMPLEMENTED();
EXPORT(int, sceRegMgrSystemParamSetInt, const int id, const SceInt32 buf) {
TRACY_FUNC(sceRegMgrSystemParamSetInt, id, buf);
const auto [category, name] = regmgr::get_category_and_name_by_id(id, export_name);
regmgr::set_int_value(emuenv.regmgr, emuenv.pref_path, category, name, buf);
return 0;
}
EXPORT(int, sceRegMgrSystemParamSetStr) {
return UNIMPLEMENTED();
EXPORT(int, sceRegMgrSystemParamSetStr, const int id, const char *buf, const SceSize bufSize) {
TRACY_FUNC(sceRegMgrSystemParamSetStr, id, buf, bufSize);
const auto [category, name] = regmgr::get_category_and_name_by_id(id, export_name);
regmgr::set_str_value(emuenv.regmgr, emuenv.pref_path, category, name, buf);
return 0;
}
BRIDGE_IMPL(sceRegMgrSystemIsBlueScreen)
@@ -17,28 +17,57 @@
#include "SceRegMgrForSDK.h"
EXPORT(int, sceRegMgrUtilityGetBin) {
return UNIMPLEMENTED();
#include <regmgr/functions.h>
#include <util/tracy.h>
TRACY_MODULE_NAME(SceRegMgrForSdk);
EXPORT(int, sceRegMgrUtilityGetBin, const int id, void *buf, const SceSize bufSize) {
TRACY_FUNC(sceRegMgrUtilityGetBin, id, buf, bufSize);
const auto [category, name] = regmgr::get_category_and_name_by_id(id, export_name);
memcpy(buf, regmgr::get_str_value(emuenv.regmgr, category, name).c_str(), bufSize);
return 0;
}
EXPORT(int, sceRegMgrUtilityGetInt) {
return UNIMPLEMENTED();
EXPORT(int, sceRegMgrUtilityGetInt, const int id, SceInt32 *buf) {
TRACY_FUNC(sceRegMgrUtilityGetInt, id, buf);
const auto [category, name] = regmgr::get_category_and_name_by_id(id, export_name);
*buf = regmgr::get_int_value(emuenv.regmgr, category, name);
return 0;
}
EXPORT(int, sceRegMgrUtilityGetStr) {
return UNIMPLEMENTED();
EXPORT(int, sceRegMgrUtilityGetStr, const int id, char *buf, const SceSize bufSize) {
TRACY_FUNC(sceRegMgrUtilityGetStr, id, buf, bufSize);
const auto [category, name] = regmgr::get_category_and_name_by_id(id, export_name);
strncpy(buf, regmgr::get_str_value(emuenv.regmgr, category, name).c_str(), bufSize);
return 0;
}
EXPORT(int, sceRegMgrUtilitySetBin) {
return UNIMPLEMENTED();
EXPORT(int, sceRegMgrUtilitySetBin, const int id, const void *buf, const SceSize bufSize) {
TRACY_FUNC(sceRegMgrUtilitySetBin, id, buf, bufSize);
const auto [category, name] = regmgr::get_category_and_name_by_id(id, export_name);
regmgr::set_bin_value(emuenv.regmgr, emuenv.pref_path, category, name, buf, bufSize);
return 0;
}
EXPORT(int, sceRegMgrUtilitySetInt) {
return UNIMPLEMENTED();
EXPORT(int, sceRegMgrUtilitySetInt, const int id, SceInt32 buf) {
TRACY_FUNC(sceRegMgrUtilitySetInt, id, buf);
const auto [category, name] = regmgr::get_category_and_name_by_id(id, export_name);
regmgr::set_int_value(emuenv.regmgr, emuenv.pref_path, category, name, buf);
return 0;
}
EXPORT(int, sceRegMgrUtilitySetStr) {
return UNIMPLEMENTED();
EXPORT(int, sceRegMgrUtilitySetStr, const int id, const char *buf, const SceSize bufSize) {
TRACY_FUNC(sceRegMgrUtilitySetStr, id, buf, bufSize);
const auto [category, name] = regmgr::get_category_and_name_by_id(id, export_name);
regmgr::set_str_value(emuenv.regmgr, emuenv.pref_path, category, name, buf);
return 0;
}
BRIDGE_IMPL(sceRegMgrUtilityGetBin)
+12
View File
@@ -0,0 +1,12 @@
add_library(
regmgr
STATIC
include/regmgr/functions.h
include/regmgr/state.h
include/regmgr/types.h
src/regmgr.cpp
)
target_include_directories(regmgr PUBLIC include)
target_include_directories(regmgr PRIVATE)
target_link_libraries(regmgr PUBLIC util)
+43
View File
@@ -0,0 +1,43 @@
// Vita3K emulator project
// Copyright (C) 2023 Vita3K team
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#pragma once
#include <regmgr/state.h>
#include <regmgr/types.h>
#include <string>
namespace regmgr {
void init_regmgr(RegMgrState &regmgr, const std::wstring &pref_path);
// Setters for binary values
void set_bin_value(RegMgrState &regmgr, const std::wstring &pref_path, const std::string &category, const std::string &name, const void *buf, uint32_t bufSize);
// Geters and setters for int values
int32_t get_int_value(RegMgrState &regmgr, const std::string &category, const std::string &name);
void set_int_value(RegMgrState &regmgr, const std::wstring &pref_path, const std::string &category, const std::string &name, int32_t value);
// Getters and setters for string values
std::string get_str_value(RegMgrState &regmgr, const std::string &category, const std::string &name);
void set_str_value(RegMgrState &regmgr, const std::wstring &pref_path, const std::string &category, const std::string &name, const std::string &value);
//
std::pair<std::string, std::string> get_category_and_name_by_id(const int id, const std::string &export_name);
} // namespace regmgr
+35
View File
@@ -0,0 +1,35 @@
// Vita3K emulator project
// Copyright (C) 2023 Vita3K team
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#pragma once
#include <mutex>
#include <string>
#include <unordered_map>
#include <vector>
struct RegValue {
std::string name;
uint32_t size;
std::string value;
};
struct RegMgrState {
std::mutex mutex;
std::unordered_map<std::string, std::unordered_map<std::string, std::string>> system_dreg;
};
+28
View File
@@ -0,0 +1,28 @@
// Vita3K emulator project
// Copyright (C) 2023 Vita3K team
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#pragma once
#include <mem/ptr.h>
#include <util/types.h>
struct Keys {
int size; // sizeof(this)
Ptr<const char> name;
int type; // todo
SceInt32 value;
};
+366
View File
@@ -0,0 +1,366 @@
// Vita3K emulator project
// Copyright (C) 2023 Vita3K team
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#include <regex>
#include <regmgr/functions.h>
#include <util/log.h>
namespace regmgr {
const std::array<unsigned char, 16> xorKey = { 0x89, 0xFA, 0x95, 0x48, 0xCB, 0x6D, 0x77, 0x9D, 0xA2, 0x25, 0x34, 0xFD, 0xA9, 0x35, 0x59, 0x6E };
static std::string decryptRegistryFile(const fs::path reg_path) {
std::ifstream file(reg_path.string(), std::ios::binary);
if (!file.is_open()) {
LOG_WARN("Error while opening file: {}, install firmware for solve this!", reg_path.string());
return {};
}
// Read the data from the file encrypted
std::vector<uint8_t> encryptedData((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
// Check if file is empty
if (encryptedData.empty()) {
LOG_DEBUG("File is empty: {}", reg_path.string());
return {};
}
// Remove the header of the file (138 bytes)
encryptedData.erase(encryptedData.begin(), encryptedData.begin() + 138);
// Decrypt the data with the xor key
for (size_t i = 0; i < encryptedData.size(); i++) {
encryptedData[i] ^= xorKey[i & 0xF];
}
// Convert the data to a string
std::string res;
for (const auto &byte : encryptedData) {
res += byte;
}
return res;
}
static std::unordered_map<std::string, std::vector<RegValue>> reg_template;
void init_reg_template(RegMgrState &regmgr, const std::string &reg) {
std::unordered_map<int, std::string> reg_map;
std::istringstream iss(reg);
std::string line;
while (std::getline(iss, line)) {
if (line.empty())
continue;
// Found the base register
if (line.find("[BASE") != std::string::npos) {
// Register the names with their numbers
while (std::getline(iss, line) && (line != "[REG-BAS")) {
if (line.empty())
continue;
size_t pos = line.find('=');
if (pos != std::string::npos) {
const auto num = std::stoi(line.substr(0, pos));
const auto name = line.substr(pos + 1);
reg_map[num] = name;
}
}
}
if (line == "[REG-BAS") {
// Register the base register
while (std::getline(iss, line) && (line != ("[REG-J1"))) {
if (line.empty())
continue;
size_t pos = line.find('=');
if (pos != std::string::npos) {
std::string entry = line.substr(0, pos);
std::string value = line.substr(pos + 1);
std::string name = "/";
std::istringstream f(entry);
std::string s;
while (std::getline(f, s, '/')) {
if (!s.empty())
name += reg_map[std::stoi(s)];
}
const auto last_slash_pos = name.find_last_of('/') + 1;
const auto valueName = name.substr(last_slash_pos);
const auto category = name.substr(0, last_slash_pos);
std::istringstream v(value);
std::vector<std::string> values;
while (std::getline(v, s, ':')) {
if (!s.empty())
values.push_back(s);
}
const auto valueSize = static_cast<uint32_t>(std::stoi(values[1]));
const std::regex categoryRangePattern(R"((.*\/)([0-9]{2})-([0-9]{2})(\/.*))");
std::smatch matches;
if (std::regex_search(category, matches, categoryRangePattern)) {
const auto cat_begin = matches[1].str();
const auto firstNum = std::stoi(matches[2].str());
const auto secondNum = std::stoi(matches[3].str());
const auto cat_end = matches[4].str();
for (int i = firstNum; i <= secondNum; i++) {
const std::string categoryName = fmt::format("{}{:0>2d}{}", cat_begin, i, cat_end);
reg_template[categoryName].push_back({ valueName, valueSize, values.back() });
}
} else
reg_template[category].push_back({ valueName, valueSize, values.back() });
}
}
}
}
}
static uint32_t get_space_size(const uint32_t str_size) {
const uint32_t spaceSize = 32;
const uint32_t line = 16;
return spaceSize > str_size ? spaceSize - str_size : ((str_size / line) + 1) * line - str_size;
}
static bool load_system_dreg(RegMgrState &regmgr, const std::wstring &pref_path) {
const auto system_dreg_path{ fs::path(pref_path) / "vd0/registry/system.dreg" };
fs::ifstream file(system_dreg_path, std::ios::in | std::ios::binary);
if (file.is_open()) {
char buf = 0;
// Skip the space
for (uint32_t i = 0; i < 33; i++) {
file.read(&buf, 1);
}
for (const auto &reg : reg_template) {
// Read the category
const uint32_t cat_size = static_cast<uint32_t>(reg.first.size());
std::vector<char> category(cat_size);
file.read(category.data(), cat_size);
const auto category_str = std::string(category.begin(), category.end());
if (category_str != reg.first) {
LOG_ERROR("Invalid category: {}, expected: {}", category_str, reg.first);
return false;
}
// Skip the space
const auto diff_cat = get_space_size(cat_size);
for (uint32_t i = 0; i < diff_cat; i++) {
file.read(&buf, 1);
}
for (const auto &entry : reg.second) {
// Read the name
const uint32_t name_size = static_cast<uint32_t>(entry.name.size());
std::vector<char> name(name_size);
file.read(name.data(), name_size);
const auto name_str = std::string(name.begin(), name.end());
if (name_str != entry.name) {
LOG_ERROR("Invalid entry name: {}, expected: {}", name_str, entry.name);
return false;
}
// Skip the space
const auto diff_name = get_space_size(name_size + 1);
for (uint32_t i = 0; i < diff_name; i++) {
file.read(&buf, 1);
}
// Read the value
const uint32_t value_size = entry.size;
std::vector<char> value(value_size);
file.read(value.data(), value_size);
const auto value_str = std::string(value.begin(), value.end());
regmgr.system_dreg[reg.first][entry.name] = value_str;
// Skip the space
const auto diff_value = get_space_size(value_size);
for (uint32_t i = 0; i < (diff_value + 1); i++) {
file.read(&buf, 1);
}
}
}
file.close();
} else
LOG_WARN("Registry file not found: {}, attempting to create it", system_dreg_path.string());
return !regmgr.system_dreg.empty();
}
static void save_system_dreg(RegMgrState &regmgr, const std::wstring pref_path) {
const auto system_dreg_path{ fs::path(pref_path) / "vd0/registry/system.dreg" };
fs::ofstream file(system_dreg_path, std::ios::out | std::ios::binary);
if (file.is_open()) {
const char buf = 0;
// Write the space
for (uint32_t i = 0; i < 33; i++) {
file.write(&buf, 1);
}
// Write each category
for (const auto &reg : reg_template) {
// Write the category
const uint32_t cat_size = static_cast<uint32_t>(reg.first.size());
std::vector<char> category(cat_size);
strncpy(category.data(), reg.first.c_str(), cat_size);
file.write(reg.first.c_str(), cat_size);
// Write the space
const auto diff_cat = get_space_size(cat_size);
for (uint32_t i = 0; i < diff_cat; i++) {
file.write(&buf, 1);
}
// Write each entry
for (const auto &entry : reg.second) {
// Write the name
const uint32_t name_size = static_cast<uint32_t>(entry.name.size());
std::vector<char> name(name_size);
strncpy(name.data(), entry.name.c_str(), name_size);
file.write(name.data(), name_size);
// Write the space
const auto diff_name = get_space_size(name_size + 1);
for (uint32_t i = 0; i < diff_name; i++) {
file.write(&buf, 1);
}
// Write the value
const uint32_t value_size = entry.size;
std::vector<char> value(value_size);
regmgr.system_dreg[reg.first][entry.name].copy(value.data(), value_size);
file.write(value.data(), value_size);
// Write the space
const auto diff_value = get_space_size(value_size);
for (uint32_t i = 0; i < (diff_value + 1); i++) {
file.write(&buf, 1);
}
}
}
file.close();
}
}
static void init_system_dreg(RegMgrState &regmgr, const std::wstring pref_path) {
regmgr.system_dreg.clear();
for (const auto &reg : reg_template) {
for (const auto &entry : reg.second) {
regmgr.system_dreg[reg.first][entry.name] = entry.value;
}
}
save_system_dreg(regmgr, pref_path);
}
static std::string fix_category(const std::string& category) {
return category.back() == '/' ? category : category + '/';
}
void set_bin_value(RegMgrState &regmgr, const std::wstring &pref_path, const std::string &category, const std::string &name, const void *buf, const uint32_t size) {
std::lock_guard<std::mutex> lock(regmgr.mutex);
const char *data = reinterpret_cast<const char *>(buf);
const std::vector<char> bin(data, data + size);
regmgr.system_dreg[fix_category(category)][name] = std::string(bin.begin(), bin.end());
save_system_dreg(regmgr, pref_path);
}
int32_t get_int_value(RegMgrState &regmgr, const std::string &category, const std::string &name) {
std::lock_guard<std::mutex> lock(regmgr.mutex);
return std::stoi(regmgr.system_dreg[fix_category(category)][name]);
}
void set_int_value(RegMgrState &regmgr, const std::wstring &pref_path, const std::string &category, const std::string &name, int32_t value) {
std::lock_guard<std::mutex> lock(regmgr.mutex);
regmgr.system_dreg[fix_category(category)][name] = std::to_string(value);
save_system_dreg(regmgr, pref_path);
}
std::string get_str_value(RegMgrState &regmgr, const std::string &category, const std::string &name) {
std::lock_guard<std::mutex> lock(regmgr.mutex);
return regmgr.system_dreg[fix_category(category)][name];
}
void set_str_value(RegMgrState &regmgr, const std::wstring &pref_path, const std::string &category, const std::string &name, const std::string &value) {
std::lock_guard<std::mutex> lock(regmgr.mutex);
regmgr.system_dreg[fix_category(category)][name] = value;
save_system_dreg(regmgr, pref_path);
}
void init_regmgr(RegMgrState &regmgr, const std::wstring &pref_path) {
const auto reg = decryptRegistryFile(fs::path(pref_path) / "os0/kd/registry.db0");
if (reg.empty()) {
return;
}
// Initialize the registry template
init_reg_template(regmgr, reg);
// Initialize the system.dreg
if (!load_system_dreg(regmgr, pref_path)) {
init_system_dreg(regmgr, pref_path);
}
}
std::pair<std::string, std::string> get_category_and_name_by_id(const int id, const std::string &export_name) {
switch (id) {
case 0x00023fc2:
return { "/CONFIG/ACCESSIBILITY/", "large_text" };
case 0x00037502:
return { "/CONFIG/SYSTEM/", "language" };
case 0x00088776:
return { "/CONFIG/DATE/", "date_format" };
case 0x00186122:
return { "/CONFIG/SECURITY/PARENTAL/", "passcode" };
case 0x00229142:
return { "/CONFIG/SYSTEM/", "button_assign" };
case 0x00450F32:
return { "/CONFIG/NP/", "account_id" };
case 0x00598438:
return { "/CONFIG/SYSTEM/", "username" };
case 0x00611DC9:
return { "/CONFIG/ACCESSIBILITY/", "bold_text" };
case 0x00668503:
return { "/CONFIG/DATE/", "time_format" };
case 0x00683DCD:
return { "/CONFIG/SYSTEM/", "key_pad" };
case 0x008A2AD7:
return { "/CONFIG/ACCESSIBILITY/", "contrast" };
default:
LOG_WARN("{}: unknown id: {}", export_name, log_hex(id));
return { "", "" };
}
}
} // namespace regmgr