Merge pull request #10153 from voidlakhan/feat/regmgr-core-registry-access

feat(libSceRegMgr): implement core registry access and query interfaces
This commit is contained in:
Dean authored and GitHub committed 2026-10-26 20:40:32 +13:00
commit 35ac3402c8
4 files changed
+113 -12

No files matched your search

+80 -9
View File
@@ -1,22 +1,93 @@
#include "prx/libSceRegMgr/include/Api.hpp"
#include <cstdint>
#include <cstddef>
#include <cstring>
#include <mutex>
#include <string>
#include <unordered_map>
#include <vector>
#include "SceTypes.hpp"
#include "prx/libc/include/General.hpp"
namespace {
constexpr int SCE_REG_MGR_ERROR_INVALID_PARAM = static_cast<int>(0x80820001);
constexpr int SCE_REG_MGR_ERROR_NOT_FOUND = static_cast<int>(0x80820002);
constexpr int SCE_REG_MGR_ERROR_BUFFER_TOO_SMALL = static_cast<int>(0x80820004);
constexpr int SCE_REG_MGR_ERROR_INVALID_TYPE = static_cast<int>(0x80820006);
enum EntryType {
TypeInt = 0,
TypeStr = 1,
TypeBin = 2,
};
struct RegEntry {
EntryType type;
int32_t intVal = 0;
std::string strVal;
std::vector<uint8_t> binVal;
};
class RegistryStore {
public:
RegistryStore() = default;
int getInt(int64_t key, int32_t* out) {
if (out == nullptr) return SCE_REG_MGR_ERROR_INVALID_PARAM;
std::lock_guard<std::mutex> lock(mutex_);
auto it = entries_.find(key);
if (it == entries_.end()) return SCE_REG_MGR_ERROR_NOT_FOUND;
if (it->second.type != TypeInt) return SCE_REG_MGR_ERROR_INVALID_TYPE;
*out = it->second.intVal;
return 0;
}
int getStr(int64_t key, char* out, int len) {
if (len == 0) NotImplemented_nid_no_patch(__func__);
if (out == nullptr || len < 0) return SCE_REG_MGR_ERROR_INVALID_PARAM;
std::lock_guard<std::mutex> lock(mutex_);
auto it = entries_.find(key);
if (it == entries_.end()) return SCE_REG_MGR_ERROR_NOT_FOUND;
if (it->second.type != TypeStr) return SCE_REG_MGR_ERROR_INVALID_TYPE;
if (static_cast<size_t>(len) <= it->second.strVal.size()) return SCE_REG_MGR_ERROR_BUFFER_TOO_SMALL;
std::memcpy(out, it->second.strVal.c_str(), it->second.strVal.size() + 1);
return 0;
}
int getBin(int64_t key, void* out, int size) {
if (size == 0) NotImplemented_nid_no_patch(__func__);
if (out == nullptr || size < 0) return SCE_REG_MGR_ERROR_INVALID_PARAM;
std::lock_guard<std::mutex> lock(mutex_);
auto it = entries_.find(key);
if (it == entries_.end()) return SCE_REG_MGR_ERROR_NOT_FOUND;
if (it->second.type != TypeBin) return SCE_REG_MGR_ERROR_INVALID_TYPE;
if (static_cast<size_t>(size) < it->second.binVal.size()) return SCE_REG_MGR_ERROR_BUFFER_TOO_SMALL;
std::memcpy(out, it->second.binVal.data(), it->second.binVal.size());
return 0;
}
private:
std::mutex mutex_;
std::unordered_map<int64_t, RegEntry> entries_;
};
RegistryStore gStore;
} // namespace
extern "C" {
int APS5_VABI sceRegMgrGetBin(std::uint32_t optionId, void* data, std::size_t size) {
NotImplemented_nid_no_patch(__func__);
return 0;
int APS5_VABI sceRegMgrGetBin(std::int64_t optionId, void* data, int size) {
return gStore.getBin(optionId, data, size);
}
int APS5_VABI sceRegMgrGetInt(int32_t optionId, int32_t* outInt) {
NotImplemented_nid_no_patch(__func__);
return 0;
int APS5_VABI sceRegMgrGetInt(std::int64_t optionId, int32_t* outInt) {
return gStore.getInt(optionId, outInt);
}
int APS5_VABI sceRegMgrGetStr(int32_t optionId, char* outString, std::size_t stringLength) {
NotImplemented_nid_no_patch(__func__);
return 0;
int APS5_VABI sceRegMgrGetStr(std::int64_t optionId, char* outString, int stringLength) {
return gStore.getStr(optionId, outString, stringLength);
}
int APS5_VABI sceRegMgrSetBin(std::uint32_t optionId, const void* data, std::size_t size) {
NotImplemented_nid_no_patch(__func__);
+5 -3
View File
@@ -1,12 +1,14 @@
#pragma once
#include <cstddef>
#include <cstdint>
#include "SceTypes.hpp"
extern "C" {
int APS5_VABI sceRegMgrGetBin(std::uint32_t optionId, void* data, std::size_t size);
int APS5_VABI sceRegMgrGetInt(int32_t optionId, int32_t* outInt);
int APS5_VABI sceRegMgrGetStr(int32_t optionId, char* outString, std::size_t stringLength);
int APS5_VABI sceRegMgrGetBin(std::int64_t optionId, void* data, int size);
int APS5_VABI sceRegMgrGetInt(std::int64_t optionId, int32_t* outInt);
int APS5_VABI sceRegMgrGetStr(std::int64_t optionId, char* outString, int stringLength);
int APS5_VABI sceRegMgrSetBin(std::uint32_t optionId, const void* data, std::size_t size);
int APS5_VABI sceRegMgrSetInt(int32_t optionId, int32_t inInt);
int APS5_VABI sceRegMgrSetStr(int32_t optionId, const char* inStirng, std::size_t stringLength);
+23
View File
@@ -2,6 +2,7 @@
#include "prx/libc/include/general/VabiMacros.hpp"
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <stdexcept>
#include <string>
@@ -21,4 +22,26 @@ int main() {
std::int32_t value = 0;
Require(ReportsNotImplemented("sceRegMgrNonSysGetInt", [&] { sceRegMgrNonSysGetInt(0, 0, &value); }));
Require(ReportsNotImplemented("sceRegMgrNonSysGetInt", [&] { sceRegMgrNonSysGetInt(-1, 1, nullptr); }));
int32_t intVal = 0;
char strBuf[64] = {};
uint8_t binBuf[32] = {};
Require(sceRegMgrGetInt(0x1000, nullptr) == static_cast<int>(0x80820001));
Require(sceRegMgrGetStr(0x1001, nullptr, 10) == static_cast<int>(0x80820001));
Require(sceRegMgrGetStr(0x1001, strBuf, -1) == static_cast<int>(0x80820001));
Require(sceRegMgrGetBin(0x1002, nullptr, 10) == static_cast<int>(0x80820001));
Require(sceRegMgrGetBin(0x1002, binBuf, -1) == static_cast<int>(0x80820001));
intVal = 0x55AA;
Require(sceRegMgrGetInt(888888, &intVal) == static_cast<int>(0x80820002));
Require(intVal == 0x55AA);
std::strcpy(strBuf, "CANARY");
Require(sceRegMgrGetStr(888888, strBuf, sizeof(strBuf)) == static_cast<int>(0x80820002));
Require(std::strcmp(strBuf, "CANARY") == 0);
binBuf[0] = 0x77;
Require(sceRegMgrGetBin(888888, binBuf, sizeof(binBuf)) == static_cast<int>(0x80820002));
Require(binBuf[0] == 0x77);
return 0;
}
+5
View File
@@ -1,5 +1,10 @@
# libSceRegMgr technical debt
### Functional
- [Registry store](../../../core/libs/prx/libSceRegMgr/Export.cpp) (libSceRegMgr) - entries are queried through an in-memory process-local store without persistence. Callable prototypes for `sceRegMgrGetInt`, `sceRegMgrGetStr`, and `sceRegMgrGetBin` derive from [regmgr.h](https://github.com/ps5-payload-dev/regdump/blob/883524cc48c8497267ba7fc94ff0ac58880c4227/regmgr.h#L3713-L3729). Implemented getters return error codes for invalid parameters (`0x80820001`), missing keys (`0x80820002`), buffer sizing (`0x80820004`), and type mismatches (`0x80820006`) as unverified host implementation assumptions, as the cited regmgr.h does not establish error codes or validation behavior. Setters (`sceRegMgrSetInt`, `sceRegMgrSetStr`, `sceRegMgrSetBin`, `sceRegMgrSetbin`), reset (`sceRegMgrResetVal`), and zero-length getter paths remain unimplemented throwing `NotImplemented_nid_no_patch` until callable contracts and error codes are supported by evidence.
- [Unverified registry APIs](../../../core/libs/prx/libSceRegMgr/Export.cpp) (libSceRegMgr) - export names and NIDs for initial-value getters, version queries, region queries and conversions, error checks, control/backup routines, and `sceRegMgrNonSys*` variants are present in the [PS5 3.20 export inventory](https://github.com/DNNDHH/PS5-3.20_Libs/blob/cf6eede3f6588d779664e01874638f09484324b7/libSceRegMgr.c) and [NID database](https://github.com/zecoxao/sce_symbols/blob/9620e03b2964dbf0cfc1cb143ab24a65125091de/aerolib.csv), but their callable contracts and runtime behavior remain unverified and retain `NotImplemented_nid_no_patch`.
### Unknown function info
- [sceRegMgrCheckError](../../../core/libs/prx/libSceRegMgr/Export.cpp) (libSceRegMgr) - unknown signature