orbis/regmgr: decode com ops

This commit is contained in:
DH 2026-01-06 06:22:53 +03:00
parent 7eb01a84ee
commit 733b8bf73f
2 changed files with 241 additions and 45 deletions

View file

@ -137,6 +137,7 @@ public:
rx::shared_mutex regMgrMtx;
kmap<std::uint32_t, std::uint32_t> regMgrInt;
kmap<std::uint32_t, rx::StaticCString<2048>> regMgrStr;
std::vector<std::tuple<std::uint8_t *, size_t>> dialogs{};
FwType fwType = FwType::Unknown;

View file

@ -128,6 +128,107 @@ orbis::sys_mtypeprotect(Thread *thread, uintptr_t addr, size_t len,
return vmem::setTypeAndProtect(thread->tproc, range, type, prot);
}
struct RegMgrComKey {
std::uint8_t data[4]{};
std::uint8_t table{};
std::uint8_t index{};
[[nodiscard]] static constexpr RegMgrComKey unpack(std::uint64_t key) {
RegMgrComKey result;
result.data[0] = static_cast<std::uint8_t>(key & 0xff);
result.data[1] = static_cast<std::uint8_t>((key >> 8) & 0xff);
result.data[2] = static_cast<std::uint8_t>((key >> 16) & 0xff);
result.data[3] = static_cast<std::uint8_t>((key >> 24) & 0xff);
result.table = static_cast<std::uint8_t>(key >> 32);
result.index = static_cast<std::uint8_t>(key >> 40);
return result;
}
[[nodiscard]] constexpr std::uint64_t pack() const {
std::uint64_t result = data[0];
result |= static_cast<std::uint64_t>(data[0]) << 0;
result |= static_cast<std::uint64_t>(data[1]) << 8;
result |= static_cast<std::uint64_t>(data[2]) << 16;
result |= static_cast<std::uint64_t>(data[3]) << 24;
result |= static_cast<std::uint64_t>(table) << 32;
result |= static_cast<std::uint64_t>(index) << 40;
result |= static_cast<std::uint64_t>(calcChecksum()) << 48;
return result;
}
[[nodiscard]] constexpr bool validate(std::uint64_t key) const {
return calcChecksum() == static_cast<std::uint16_t>(key >> 48);
}
[[nodiscard]] constexpr std::uint16_t calcChecksum() const {
return std::uint16_t(data[0]) + data[1] + data[2] + data[3] + table * index;
}
};
constexpr std::int32_t regMgrGetRegId(std::uint64_t encoded) {
constexpr std::uint8_t kRegMgrScrambSdk[] = {
0x6b, 0xe8, 0x98, 0x03, 0x9a, 0x70, 0x23, 0x5a,
0x63, 0xee, 0xf5, 0x7b, 0xff, 0xa4, 0x4c, 0x8c,
};
constexpr std::uint8_t kRegMgrScrambLib[] = {
0x14, 0xee, 0xde, 0xe1, 0x80, 0xac, 0xf3, 0x78,
0x47, 0x43, 0xdb, 0x40, 0x93, 0xdd, 0xb1, 0x34,
};
auto key = RegMgrComKey::unpack(encoded);
auto slot = key.index ^ 0x6b;
const std::uint8_t *table = kRegMgrScrambSdk;
switch ((key.table ^ table[0xf - slot])) {
case 0x19:
table = kRegMgrScrambLib;
break;
case 0x72:
table = kRegMgrScrambSdk;
break;
default:
return 0x800d0205;
}
std::uint32_t decodedKey = (key.data[1] ^ table[slot + 0]) * 0x1000000 +
(key.data[3] ^ table[slot + 1]) * 0x10000 +
(key.data[2] ^ table[slot + 2]) * 0x100 +
(key.data[0] ^ table[slot + 3]);
return decodedKey;
}
struct RegMgrComInt {
uint64_t encodedId;
uint32_t unk;
uint32_t value;
};
static_assert(sizeof(RegMgrComInt) == 0x10);
struct RegMgrComStr {
uint64_t encodedId;
uint32_t unk;
uint32_t padding;
uint64_t len;
rx::StaticCString<2048> string;
};
static_assert(sizeof(RegMgrComStr) == 0x818);
struct RegMgrComBin {
uint64_t encodedId;
uint32_t unk;
uint32_t padding;
uint64_t len;
std::uint8_t data[2048];
};
static_assert(sizeof(RegMgrComBin) == 0x818);
orbis::SysResult orbis::sys_regmgr_call(Thread *thread, uint32_t op,
uint32_t id, ptr<void> result,
ptr<void> value, uint64_t len) {
@ -146,6 +247,7 @@ orbis::SysResult orbis::sys_regmgr_call(Thread *thread, uint32_t op,
g_context->regMgrInt[id] = *(std::uint32_t *)value;
return {};
}
if (op == 2) {
// get int
if (len != sizeof(uint32_t)) {
@ -158,10 +260,20 @@ orbis::SysResult orbis::sys_regmgr_call(Thread *thread, uint32_t op,
thread->where();
// return ErrorCode::NOENT;
return uwrite((ptr<uint>)value, 0u);
return {};
}
return uwrite((ptr<uint>)value, intValIt->second);
return uwrite((ptr<uint>)value, intValIt->second);
}
if (op == 3) {
// set string
rx::StaticCString<2048> string;
ORBIS_RET_ON_ERROR(ureadString(
string.data(), std::min(string.max_size(), len), ptr<char>(value)));
ORBIS_LOG_WARNING(__FUNCTION__, op, id, string.data());
g_context->regMgrStr[id] = string;
return {};
}
@ -173,63 +285,146 @@ orbis::SysResult orbis::sys_regmgr_call(Thread *thread, uint32_t op,
return ErrorCode::INVAL;
}
std::memset(value, 0, len);
auto it = g_context->regMgrStr.find(id);
if (it == g_context->regMgrStr.end()) {
ORBIS_LOG_ERROR("registry string entry not exists", op, id);
thread->where();
std::memset(value, 0, len);
return {};
}
ORBIS_LOG_ERROR(__FUNCTION__, op, id, len);
if (it->second.length() > len) {
return ErrorCode(-0x800d0606);
}
ORBIS_LOG_WARNING(__FUNCTION__, op, id, len, it->second.data());
thread->where();
ORBIS_RET_ON_ERROR(
uwriteRaw(value, it->second.data(), it->second.length() + 1));
return {};
}
if (op == 24) {
// com: set int
RegMgrComInt _request;
ORBIS_RET_ON_ERROR(uread(_request, ptr<RegMgrComInt>(value)));
auto id = regMgrGetRegId(_request.encodedId);
if (id < 0) {
return ErrorCode(-id);
}
ORBIS_LOG_WARNING(__FUNCTION__, op, id, _request.unk, _request.value);
g_context->regMgrInt[id] = _request.value;
return {};
}
if (op == 25) {
struct nonsys_int {
union {
uint64_t encoded_id;
struct {
uint8_t data[4];
uint8_t table;
uint8_t index;
uint16_t checksum;
} encoded_id_parts;
};
uint32_t unk;
uint32_t value;
};
// com: get int
RegMgrComInt _request;
ORBIS_RET_ON_ERROR(uread(_request, ptr<RegMgrComInt>(value)));
auto int_value = reinterpret_cast<nonsys_int *>(value);
ORBIS_LOG_TODO(
__FUNCTION__, int_value->encoded_id,
int_value->encoded_id_parts.data[0],
int_value->encoded_id_parts.data[1],
int_value->encoded_id_parts.data[2],
int_value->encoded_id_parts.data[3], int_value->encoded_id_parts.table,
int_value->encoded_id_parts.index, int_value->encoded_id_parts.checksum,
int_value->unk, int_value->value);
auto id = regMgrGetRegId(_request.encodedId);
// HACK: set default system language and gamepad layout to US/EU region
// 0x12356328ECF5617B -> language where is 0 is Japanese, 1 is English
// 0x22666251FE7BECFF -> confirm button layout, 0 is Circle, 1 is Cross
if (int_value->encoded_id == 0x12356328ECF5617B ||
int_value->encoded_id == 0x22666251FE7BECFF) {
int_value->value = 1;
return {};
if (id < 0) {
return ErrorCode(-id);
}
if (int_value->encoded_id == 0x1ac46343411b3f40) {
int_value->value = 0; // allow debug libraries
return {};
auto it = g_context->regMgrInt.find(id);
if (it == g_context->regMgrInt.end()) {
ORBIS_LOG_ERROR("registry int entry not exists", op, id);
thread->where();
// return ErrorCode::NOENT;
_request.value = 0;
} else {
_request.value = it->second;
}
if (int_value->encoded_id == 0x29b56169422aa3dd) {
int_value->value = 2;
return {};
}
// 0x503f69bde385a6ac // allow loading from dev machine?
// 0x2d946f62aef8f878
int_value->value = 0;
ORBIS_LOG_WARNING(__FUNCTION__, op, id, _request.unk, _request.value);
return uwrite((ptr<RegMgrComInt>)value, _request);
}
if (op == 26) {
// com: set string
RegMgrComStr _request;
ORBIS_RET_ON_ERROR(uread(_request, ptr<RegMgrComStr>(value)));
auto id = regMgrGetRegId(_request.encodedId);
if (id < 0) {
return ErrorCode(-id);
}
if (_request.len > 2048 || _request.string[_request.len - 1] != '\0' ||
_request.string.length() + 1 != _request.len) {
return ErrorCode(-0x800d0205);
}
ORBIS_LOG_WARNING(__FUNCTION__, op, id, _request.unk,
_request.string.data());
g_context->regMgrStr[id] = _request.string;
return {};
}
if (op == 27) {
// com: get string
RegMgrComStr _request;
ORBIS_RET_ON_ERROR(uread(_request, ptr<RegMgrComStr>(value)));
auto id = regMgrGetRegId(_request.encodedId);
if (id < 0) {
return ErrorCode(-id);
}
auto it = g_context->regMgrStr.find(id);
if (it == g_context->regMgrStr.end()) {
ORBIS_LOG_ERROR("registry string entry not exists", op, id);
thread->where();
_request.string = "";
} else {
_request.len = it->second.length();
_request.string = it->second;
}
ORBIS_LOG_WARNING(__FUNCTION__, op, id, _request.string.data());
return uwrite((ptr<RegMgrComStr>)value, _request);
}
if (op == 28) {
// com: set bin
RegMgrComBin _request;
ORBIS_RET_ON_ERROR(uread(_request, ptr<RegMgrComBin>(value)));
auto id = regMgrGetRegId(_request.encodedId);
if (id < 0) {
return ErrorCode(-id);
}
ORBIS_LOG_TODO(__FUNCTION__, op, id, _request.unk);
return {};
}
if (op == 29) {
// com: get bin
RegMgrComBin _request;
ORBIS_RET_ON_ERROR(uread(_request, ptr<RegMgrComBin>(value)));
auto id = regMgrGetRegId(_request.encodedId);
if (id < 0) {
return ErrorCode(-id);
}
ORBIS_LOG_TODO(__FUNCTION__, op, id, _request.unk);
return {};
}
ORBIS_LOG_TODO(__FUNCTION__, op, id);
return {};
}
orbis::SysResult orbis::sys_jitshm_create(Thread *thread /* TODO */) {