Merge pull request #3737 from MarcZX100/codex/json2-init-parameter2-3348

feat(libSceJson2): implement InitParameter2 constructors
This commit is contained in:
Dean 2026-10-12 20:01:34 +13:00 committed by GitHub
commit 9231a08b00
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 95 additions and 14 deletions

View File

@ -808,30 +808,53 @@ int APS5_VABI _ZN3sce4Json6Parser5parseERNS0_5ValueEPKcm(Value* out, const char*
}
int APS5_VABI _ZN3sce4Json17InitParameterRttiC1EPNS0_14AllocParamRttiEPvm(void) {
NotImplemented_nid_no_patch(__func__);
return 0;
struct InitParameterRtti {
void* allocParam;
void* userData;
std::size_t fileBufferSize;
};
void APS5_VABI _ZN3sce4Json17InitParameterRttiC1EPNS0_14AllocParamRttiEPvm(InitParameterRtti* self, void* allocParam, void* userData, std::size_t fileBufferSize) {
self->allocParam = allocParam;
self->userData = userData;
self->fileBufferSize = fileBufferSize;
}
struct InitParameter2 {
void* allocator;
void* userData;
std::size_t fileBufferSize;
std::int32_t specialFloatFormatType;
std::uint32_t reserved[3];
};
static_assert(sizeof(InitParameter2) <= 40);
static_assert(sizeof(InitParameter2) == 0x28 && offsetof(InitParameter2, specialFloatFormatType) == 0x18);
void APS5_VABI _ZN3sce4Json14InitParameter2C1Ev(InitParameter2* self) {
*self = {};
}
void APS5_VABI _ZN3sce4Json14InitParameter2C2Ev(InitParameter2* self) {
_ZN3sce4Json14InitParameter2C1Ev(self);
}
void APS5_VABI _ZN3sce4Json14InitParameter212setAllocatorEPNS0_12MemAllocatorEPv(InitParameter2* self, void* allocator, void* userData) {
self->allocator = allocator;
self->userData = userData;
}
void APS5_VABI _ZN3sce4Json18InitParameterRtti216setAllocatorRttiEPNS0_14AllocParamRttiEPv(InitParameter2* self, void* allocParam, void* userData) {
self->allocator = allocParam;
self->userData = userData;
}
void APS5_VABI _ZN3sce4Json14InitParameter217setFileBufferSizeEm(InitParameter2* self, std::size_t size) {
self->fileBufferSize = size;
}
void APS5_VABI _ZN3sce4Json14InitParameter225setSpecialFloatFormatTypeENS0_22SpecialFloatFormatTypeE(InitParameter2* self, std::int32_t type) {
self->specialFloatFormatType = type;
}
int APS5_VABI _ZN3sce4Json11Initializer10initializeEPKNS0_14InitParameter2E(void* self, const InitParameter2* parameter) {
(void)self;
if (parameter == nullptr) throw std::invalid_argument("sce::Json::Initializer::initialize: null parameter");
@ -848,15 +871,6 @@ int APS5_VABI _ZN3sce4Json12MemAllocator11notifyErrorEimPv(void) {
return 0;
}
void APS5_VABI _ZN3sce4Json14InitParameter2C2Ev(InitParameter2* self) {
_ZN3sce4Json14InitParameter2C1Ev(self);
}
int APS5_VABI _ZN3sce4Json18InitParameterRtti216setAllocatorRttiEPNS0_14AllocParamRttiEPv(void) {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZN3sce4Json5Value21setNullAccessCallBackEPFRKS1_NS0_9ValueTypeEPS2_PvES6_() {
NotImplemented_nid_no_patch(__func__);
return 0;

View File

@ -95,6 +95,9 @@ void APS5_VABI _ZN3sce4Json14InitParameter2C2Ev(void*);
void APS5_VABI _ZN3sce4Json14InitParameter212setAllocatorEPNS0_12MemAllocatorEPv(void*, void*, void*);
void APS5_VABI _ZN3sce4Json14InitParameter217setFileBufferSizeEm(void*, std::size_t);
int APS5_VABI _ZN3sce4Json11Initializer10initializeEPKNS0_14InitParameter2E(void*, const void*);
void APS5_VABI _ZN3sce4Json18InitParameterRtti216setAllocatorRttiEPNS0_14AllocParamRttiEPv(void*, void*, void*);
void APS5_VABI _ZN3sce4Json14InitParameter225setSpecialFloatFormatTypeENS0_22SpecialFloatFormatTypeE(void*, std::int32_t);
void APS5_VABI _ZN3sce4Json17InitParameterRttiC1EPNS0_14AllocParamRttiEPvm(void*, void*, void*, std::size_t);
}
static void Check(bool value, int line) {
@ -475,6 +478,69 @@ static void InitParameter2BaseConstructor() {
Require(_ZN3sce4Json11InitializerD1Ev(initializer) == 0);
}
struct StoredInitParameter2 {
void* allocator;
void* userData;
std::size_t fileBufferSize;
std::int32_t specialFloatFormatType;
std::uint32_t reserved[3];
};
static_assert(sizeof(StoredInitParameter2) == 40);
static StoredInitParameter2 Stored(const std::uint8_t* parameter) {
StoredInitParameter2 stored{};
std::memcpy(&stored, parameter, sizeof(stored));
return stored;
}
static bool Untouched(const std::uint8_t* parameter, std::size_t from) {
for (std::size_t i = from; i < 40; ++i)
if (parameter[i] != 0xff) return false;
return true;
}
static void InitParameters() {
using Constructor = void (APS5_VABI*)(void*);
for (Constructor construct : {_ZN3sce4Json14InitParameter2C1Ev, _ZN3sce4Json14InitParameter2C2Ev}) {
alignas(16) std::uint8_t parameter[40];
std::memset(parameter, 0xff, sizeof(parameter));
construct(parameter);
StoredInitParameter2 stored = Stored(parameter);
Require(stored.allocator == nullptr && stored.userData == nullptr && stored.fileBufferSize == 0);
Require(stored.specialFloatFormatType == 0);
Require(stored.reserved[0] == 0 && stored.reserved[1] == 0 && stored.reserved[2] == 0);
int allocParam = 0;
int userData = 0;
_ZN3sce4Json14InitParameter217setFileBufferSizeEm(parameter, 8192);
_ZN3sce4Json14InitParameter225setSpecialFloatFormatTypeENS0_22SpecialFloatFormatTypeE(parameter, 2);
_ZN3sce4Json18InitParameterRtti216setAllocatorRttiEPNS0_14AllocParamRttiEPv(parameter, &allocParam, &userData);
stored = Stored(parameter);
Require(stored.allocator == &allocParam && stored.userData == &userData && stored.fileBufferSize == 8192);
Require(stored.specialFloatFormatType == 2);
Require(stored.reserved[0] == 0 && stored.reserved[1] == 0 && stored.reserved[2] == 0);
_ZN3sce4Json14InitParameter225setSpecialFloatFormatTypeENS0_22SpecialFloatFormatTypeE(parameter, 0);
Require(Stored(parameter).specialFloatFormatType == 0 && Stored(parameter).fileBufferSize == 8192);
alignas(16) std::uint8_t initializer[16]{};
Require(_ZN3sce4Json11InitializerC1Ev(initializer) == 0);
Require(_ZN3sce4Json11Initializer10initializeEPKNS0_14InitParameter2E(initializer, parameter) == 0);
Require(_ZN3sce4Json11Initializer9terminateEv(initializer) == 0);
Require(_ZN3sce4Json11InitializerD1Ev(initializer) == 0);
}
alignas(16) std::uint8_t rttiParameter[40];
std::memset(rttiParameter, 0xff, sizeof(rttiParameter));
int allocParam = 0;
int userData = 0;
_ZN3sce4Json17InitParameterRttiC1EPNS0_14AllocParamRttiEPvm(rttiParameter, &allocParam, &userData, 4096);
void* rttiStored[3]{};
std::memcpy(rttiStored, rttiParameter, sizeof(rttiStored));
Require(rttiStored[0] == &allocParam && rttiStored[1] == &userData && reinterpret_cast<std::uintptr_t>(rttiStored[2]) == 4096);
Require(Untouched(rttiParameter, sizeof(rttiStored)));
}
static void ValueClear() {
Value value{};
_ZN3sce4Json5ValueC1Ev(&value);
@ -553,6 +619,7 @@ int main() {
NullAccess(_ZN3sce4Json11Initializer27setGlobalNullAccessCallbackEPFRKNS0_5ValueENS0_9ValueTypeEPS3_PvES7_);
ValueAccess();
InitParameter2BaseConstructor();
InitParameters();
ValueClear();
StreamParse();
}

View File

@ -356,7 +356,7 @@ Throughout the project, every function at every stage either **does exactly what
- [sceNgs2VoiceControl sampler filter](../../core/libs/prx/libSceNgs2.native/src/Voice.cpp) (libSceNgs2.native) - param `0x1000000a`, its layout and meaning follow KytyPS5 only: location 1 type 1 is an RBJ low-pass biquad at the system sample rate after resampling, scaled by `level`, a set `channel_mask` bit bypasses that channel, type 0 turns the filter off. Other locations and types throw. The voice keeps playing a filter tail after its last block until the history is zero, with outputs below 1e-20 flushed to zero (a KytyPS5 choice); the console's tail length is unknown
- [sceNgs2PanInit / sceNgs2PanGetVolumeMatrix](../../core/libs/prx/libSceNgs2.native/src/Pan.cpp) (libSceNgs2.native) - follow the PS4 firmware 11.00 `libSceNgs2.sprx`, read and checked against its output for 2, 4, 5 and 7 speakers into 1, 2, 6 and 8 channels; not yet confirmed on the PS5 library. Speakers are taken in the order L R, L R Ls Rs, L R C Ls Rs or L R C Ls Rs Lb Rb and kept in a fixed circular order, not sorted; without angles the defaults are 90/270, 40/110/250/320, 0/40/110/250/320 and 0/40/110/150/210/250/320 degrees. As in that library, defaults converted to radians keep the wrap-around entry in degrees, so angles past the last speaker pan almost fully to it. Error codes are not known for the PS5, so invalid arguments throw, including a speaker angle equal to the unit angle, on which that library loops forever. Angles so large that adding or subtracting a turn leaves them unchanged throw for the same reason
- [sceRtcGetDosTime, sceRtcSetDosTime](../../core/libs/prx/libSceRtc/Export.cpp) (libSceRtc) - bit layout from shadPS4 (PS4, the standard FAT date/time). A year outside 1980-2107 makes `GetDosTime` return `INVALID_YEAR` after writing 0 for an earlier one and `0xff9fbf7d` (2107-12-31 23:59:58, the largest encodable time) for a later one, and `SetDosTime` decodes the year as the unsigned 7-bit FAT field (1980-2107) without validating the fields, as the disassembly-derived [fpPS4](https://github.com/red-prig/fpPS4) reimplementation of the PS4 library does; not confirmed on a PS5 title, and shadPS4 instead masks out-of-range years into the packed value and sign-extends the 16-bit date
- [sce::Json::InitParameter2](../../core/libs/prx/libSceJson2/Export.cpp) (libSceJson2) - layout inferred, not known: assumed to start with the allocator, its user data and the file buffer size, in that order, and the whole struct is assumed to fit in 40 bytes; `Initializer::initialize(InitParameter2)` ignores them as `initialize(InitParameter)` does
- [sce::Json::InitParameter2, InitParameterRtti and InitParameterRtti2](../../core/libs/prx/libSceJson2/Export.cpp) (libSceJson2) - layouts inferred, not known. `InitParameter2` is taken as the 40-byte object of [SharpEmu](https://github.com/sharpemu/sharpemu/blob/1811cef94435db7655209fb39f65ddf258b93fd6/src/SharpEmu.Libs/Json/JsonExports.cs) and [KytyPS5](https://github.com/KytyPS5/KytyPS5/blob/eda6ba37ece127ab0396378404d99182e3e8a530/src/libs/libJson2.cpp): the allocator, its user data, the file buffer size, the 32-bit special float format type at 0x18 and 12 bytes both zero, and both constructors zero all of it. `InitParameterRtti2::setAllocatorRtti` writes the allocation parameters and user data where `setAllocator` writes the allocator, as both references do; whether the console also marks the object as using RTTI allocation is unknown. `InitParameterRtti`'s constructor writes the allocation parameters, user data and file buffer size to the first 24 bytes, an order inferred from its mangled arguments. The values of `SpecialFloatFormatType` and what they select are unknown, so `setSpecialFloatFormatType` stores any value and nothing reads it: `Initializer::initialize(InitParameter2)` ignores every field as `initialize(InitParameter)` does, serializing a non-finite real throws whatever the type, and whether the type lets the parser accept NaN or infinity is unknown. The setters return nothing; whether the console's return `this` is unknown
- [sceAjmBatchJobSetResampleParameters, sceAjmBatchJobGetResampleInfo](../../core/libs/prx/libSceAjm.native/src/Ajm.cpp) (libSceAjm) - the ratio is taken as decoded samples per output sample and num_samples as the decoded samples the resampler holds, both inferred from FMOD (Hades II); the console's interpolation is unknown, a 4-point Catmull-Rom is used. The flags argument is ignored, as in shadPS4 and Kyty
- [scePlayerReviewDialogOpen, scePlayerReviewDialogGetResult](../../core/libs/prx/libSceCdlgPlayerReview/Export.cpp) (libSceCdlgPlayerReview) - the PS5-only dialog has no public reference: the parameter is not read and the result is assumed to start with the 32-bit common dialog result, as `sceWebBrowserDialogGetResult` assumes
- [sceHttpWaitRequest](../../core/libs/prx/libSceHttp/Export.cpp) (libSceHttp) - the timeout is assumed to be in microseconds and a negative timeout to wait without limit; the invalid-value error for a null handle or event array or a non-positive event count is assumed, not measured. No request is ever pending, so a wait returns 0 events when its timeout passes