Merge pull request #3995 from delarun/fix/ngs2-dead-cells
feat(libSceNgs2): implement the Geom reset functions
This commit is contained in:
commit
8fa5cc4866
|
|
@ -2,7 +2,7 @@ include(${CMAKE_CURRENT_SOURCE_DIR}/Ngs2Library.cmake)
|
|||
add_sce_ngs2_library(libSceNgs2.native)
|
||||
|
||||
if(BUILD_TESTING)
|
||||
foreach(ngs2Test IN ITEMS Render Atrac9 Filter Custom Parse Stream UserFx Report)
|
||||
foreach(ngs2Test IN ITEMS Render Atrac9 Filter Custom Parse Stream UserFx Report Geom)
|
||||
string(TOLOWER ${ngs2Test} testName)
|
||||
add_test_executable(ngs2_${testName}_tests ${CMAKE_CURRENT_SOURCE_DIR}/tests/Ngs2${ngs2Test}.cpp)
|
||||
target_include_directories(ngs2_${testName}_tests PRIVATE ${LIBS_INCLUDE_DIR} ${CMAKE_SOURCE_DIR}/3rdparty/LibAtrac9/C/src)
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ function(add_sce_ngs2_library target)
|
|||
add_library(${target} SHARED EXCLUDE_FROM_ALL
|
||||
${ngs2Dir}/src/Atrac9.cpp
|
||||
${ngs2Dir}/src/Custom.cpp
|
||||
${ngs2Dir}/src/Geom.cpp
|
||||
${ngs2Dir}/src/Pan.cpp
|
||||
${ngs2Dir}/src/Rack.cpp
|
||||
${ngs2Dir}/src/Render.cpp
|
||||
|
|
|
|||
|
|
@ -607,20 +607,79 @@ struct Ngs2PanWork {
|
|||
};
|
||||
static_assert(sizeof(Ngs2PanWork) == 40);
|
||||
|
||||
struct Ngs2GeomListenerParam {
|
||||
std::uint32_t reserved[32];
|
||||
struct Ngs2GeomVector {
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
};
|
||||
static_assert(sizeof(Ngs2GeomVector) == 12);
|
||||
|
||||
struct Ngs2GeomCone {
|
||||
float inner_level;
|
||||
float inner_angle;
|
||||
float outer_level;
|
||||
float outer_angle;
|
||||
};
|
||||
static_assert(sizeof(Ngs2GeomCone) == 16);
|
||||
|
||||
struct Ngs2GeomRolloff {
|
||||
std::uint32_t model;
|
||||
float max_distance;
|
||||
float rolloff_factor;
|
||||
float reference_distance;
|
||||
};
|
||||
static_assert(sizeof(Ngs2GeomRolloff) == 16);
|
||||
|
||||
struct Ngs2GeomListenerParam {
|
||||
Ngs2GeomVector position;
|
||||
Ngs2GeomVector orient_front;
|
||||
Ngs2GeomVector orient_up;
|
||||
Ngs2GeomVector velocity;
|
||||
float sound_speed;
|
||||
std::uint32_t reserved[2];
|
||||
};
|
||||
static_assert(sizeof(Ngs2GeomListenerParam) == 60);
|
||||
|
||||
struct Ngs2GeomListenerWork {
|
||||
std::uint32_t reserved[64];
|
||||
float matrix[4][4];
|
||||
Ngs2GeomVector velocity;
|
||||
float sound_speed;
|
||||
std::uint32_t coordinate;
|
||||
std::uint32_t reserved[3];
|
||||
};
|
||||
static_assert(sizeof(Ngs2GeomListenerWork) == 96);
|
||||
|
||||
struct Ngs2GeomSourceParam {
|
||||
std::uint32_t reserved[32];
|
||||
Ngs2GeomVector position;
|
||||
Ngs2GeomVector velocity;
|
||||
Ngs2GeomVector direction;
|
||||
Ngs2GeomCone cone;
|
||||
Ngs2GeomRolloff rolloff;
|
||||
float doppler_factor;
|
||||
float fbw_level;
|
||||
float lfe_level;
|
||||
float max_level;
|
||||
float min_level;
|
||||
float radius;
|
||||
std::uint32_t num_speakers;
|
||||
std::uint32_t matrix_format;
|
||||
std::uint32_t reserved[2];
|
||||
};
|
||||
static_assert(sizeof(Ngs2GeomSourceParam) == 108);
|
||||
|
||||
struct Ngs2GeomA3dAttribute {
|
||||
Ngs2GeomVector position;
|
||||
float volume;
|
||||
std::uint32_t reserved[4];
|
||||
};
|
||||
static_assert(sizeof(Ngs2GeomA3dAttribute) == 32);
|
||||
|
||||
struct Ngs2GeomAttribute {
|
||||
std::uint32_t reserved[32];
|
||||
float pitch_ratio;
|
||||
float level[64];
|
||||
Ngs2GeomA3dAttribute a3d_attrib;
|
||||
std::uint32_t reserved[4];
|
||||
};
|
||||
static_assert(sizeof(Ngs2GeomAttribute) == 308);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
#include <cstdint>
|
||||
|
||||
#include "Ngs2Internal.hpp"
|
||||
|
||||
static constexpr float DEFAULT_SOUND_SPEED = 343.0f;
|
||||
|
||||
int Ngs2GeomResetListenerParam(Ngs2GeomListenerParam* out_listener_param) {
|
||||
if (out_listener_param == nullptr) return SCE_NGS2_ERROR_INVALID_OUT_ADDRESS;
|
||||
*out_listener_param = {};
|
||||
out_listener_param->orient_front.z = 1.0f;
|
||||
out_listener_param->orient_up.y = 1.0f;
|
||||
out_listener_param->sound_speed = DEFAULT_SOUND_SPEED;
|
||||
return SCE_NGS2_OK;
|
||||
}
|
||||
|
||||
int Ngs2GeomResetSourceParam(Ngs2GeomSourceParam* out_source_param) {
|
||||
if (out_source_param == nullptr) return SCE_NGS2_ERROR_INVALID_OUT_ADDRESS;
|
||||
*out_source_param = {};
|
||||
out_source_param->direction.z = 1.0f;
|
||||
out_source_param->cone.inner_level = 1.0f;
|
||||
out_source_param->cone.inner_angle = 360.0f;
|
||||
out_source_param->cone.outer_level = 1.0f;
|
||||
out_source_param->cone.outer_angle = 360.0f;
|
||||
out_source_param->rolloff.max_distance = 1000000.0f;
|
||||
out_source_param->rolloff.rolloff_factor = 1.0f;
|
||||
out_source_param->rolloff.reference_distance = 1.0f;
|
||||
out_source_param->doppler_factor = 1.0f;
|
||||
out_source_param->fbw_level = 1.0f;
|
||||
out_source_param->lfe_level = 1.0f;
|
||||
out_source_param->max_level = 1.0f;
|
||||
out_source_param->num_speakers = 2;
|
||||
out_source_param->matrix_format = 2;
|
||||
return SCE_NGS2_OK;
|
||||
}
|
||||
|
|
@ -203,5 +203,7 @@ void Ngs2RenderSystem(Ngs2System& system, const Ngs2RenderBufferInfo* bufferInfo
|
|||
float Ngs2DefaultLevel(std::uint32_t sourceChannels, std::uint32_t source, std::uint32_t destChannels, std::uint32_t dest);
|
||||
int Ngs2PanInit(Ngs2PanWork* work, const float* speaker_angles, float unit_angle, uint32_t num_speakers);
|
||||
int Ngs2PanGetVolumeMatrix(Ngs2PanWork* work, const Ngs2PanParam* params, uint32_t num_params, uint32_t matrix_format, float* out_volume_matrix);
|
||||
int Ngs2GeomResetListenerParam(Ngs2GeomListenerParam* out_listener_param);
|
||||
int Ngs2GeomResetSourceParam(Ngs2GeomSourceParam* out_source_param);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -25,18 +25,6 @@ int APS5_VABI sceNgs2GeomCalcListener(const Ngs2GeomListenerParam* param, Ngs2Ge
|
|||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI sceNgs2GeomResetListenerParam(Ngs2GeomListenerParam* out_listener_param) {
|
||||
(void)out_listener_param;
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI sceNgs2GeomResetSourceParam(Ngs2GeomSourceParam* out_source_param) {
|
||||
(void)out_source_param;
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI sceNgs2ReportRegisterHandler(uint32_t report_type, void* handler, uintptr_t user_data, Ngs2Handle* out_handle) {
|
||||
(void)report_type;
|
||||
(void)handler;
|
||||
|
|
|
|||
|
|
@ -486,6 +486,14 @@ int APS5_VABI sceNgs2PanGetVolumeMatrix(Ngs2PanWork* work, const Ngs2PanParam* p
|
|||
return Ngs2PanGetVolumeMatrix(work, params, num_params, matrix_format, out_volume_matrix);
|
||||
}
|
||||
|
||||
int APS5_VABI sceNgs2GeomResetListenerParam(Ngs2GeomListenerParam* out_listener_param) {
|
||||
return Ngs2GeomResetListenerParam(out_listener_param);
|
||||
}
|
||||
|
||||
int APS5_VABI sceNgs2GeomResetSourceParam(Ngs2GeomSourceParam* out_source_param) {
|
||||
return Ngs2GeomResetSourceParam(out_source_param);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#pragma GCC visibility pop
|
||||
|
|
|
|||
|
|
@ -0,0 +1,57 @@
|
|||
#include "Ngs2Test.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
|
||||
static constexpr float SoundSpeed = 343.0f;
|
||||
|
||||
static void TestLayouts() {
|
||||
Require(sizeof(Ngs2GeomVector) == 12);
|
||||
Require(sizeof(Ngs2GeomCone) == 16);
|
||||
Require(sizeof(Ngs2GeomRolloff) == 16);
|
||||
Require(sizeof(Ngs2GeomListenerParam) == 60);
|
||||
Require(sizeof(Ngs2GeomListenerWork) == 96);
|
||||
Require(sizeof(Ngs2GeomSourceParam) == 108);
|
||||
Require(sizeof(Ngs2GeomA3dAttribute) == 32);
|
||||
Require(sizeof(Ngs2GeomAttribute) == 308);
|
||||
}
|
||||
|
||||
static void TestResetListenerParam() {
|
||||
Ngs2GeomListenerParam param;
|
||||
std::memset(¶m, 0x5a, sizeof(param));
|
||||
Require(sceNgs2GeomResetListenerParam(¶m) == SCE_NGS2_OK);
|
||||
Require(param.position.x == 0.0f && param.position.y == 0.0f && param.position.z == 0.0f);
|
||||
Require(param.velocity.x == 0.0f && param.velocity.y == 0.0f && param.velocity.z == 0.0f);
|
||||
Require(param.orient_front.x == 0.0f && param.orient_front.y == 0.0f && param.orient_front.z == 1.0f);
|
||||
Require(param.orient_up.x == 0.0f && param.orient_up.y == 1.0f && param.orient_up.z == 0.0f);
|
||||
Require(param.sound_speed == SoundSpeed);
|
||||
Require(param.reserved[0] == 0u && param.reserved[1] == 0u);
|
||||
Require(sceNgs2GeomResetListenerParam(nullptr) == SCE_NGS2_ERROR_INVALID_OUT_ADDRESS);
|
||||
}
|
||||
|
||||
static void TestResetSourceParam() {
|
||||
Ngs2GeomSourceParam param;
|
||||
std::memset(¶m, 0x5a, sizeof(param));
|
||||
Require(sceNgs2GeomResetSourceParam(¶m) == SCE_NGS2_OK);
|
||||
Require(param.position.x == 0.0f && param.position.y == 0.0f && param.position.z == 0.0f);
|
||||
Require(param.velocity.x == 0.0f && param.velocity.y == 0.0f && param.velocity.z == 0.0f);
|
||||
Require(param.direction.x == 0.0f && param.direction.y == 0.0f && param.direction.z == 1.0f);
|
||||
Require(param.cone.inner_level == 1.0f && param.cone.inner_angle == 360.0f);
|
||||
Require(param.cone.outer_level == 1.0f && param.cone.outer_angle == 360.0f);
|
||||
Require(param.rolloff.model == 0u);
|
||||
Require(param.rolloff.max_distance == 1000000.0f);
|
||||
Require(param.rolloff.rolloff_factor == 1.0f);
|
||||
Require(param.rolloff.reference_distance == 1.0f);
|
||||
Require(param.doppler_factor == 1.0f && param.fbw_level == 1.0f && param.lfe_level == 1.0f);
|
||||
Require(param.max_level == 1.0f && param.min_level == 0.0f && param.radius == 0.0f);
|
||||
Require(param.num_speakers == 2u && param.matrix_format == 2u);
|
||||
Require(param.reserved[0] == 0u && param.reserved[1] == 0u);
|
||||
Require(sceNgs2GeomResetSourceParam(nullptr) == SCE_NGS2_ERROR_INVALID_OUT_ADDRESS);
|
||||
}
|
||||
|
||||
int main() {
|
||||
TestLayouts();
|
||||
TestResetListenerParam();
|
||||
TestResetSourceParam();
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -39,6 +39,8 @@ int APS5_VABI sceNgs2VoiceGetState(uintptr_t, Ngs2VoiceState*, size_t);
|
|||
int APS5_VABI sceNgs2VoiceGetStateFlags(uintptr_t, uint32_t*);
|
||||
int APS5_VABI sceNgs2VoiceGetPortInfo(uintptr_t, uint32_t, Ngs2VoicePortInfo*, size_t);
|
||||
int APS5_VABI sceNgs2VoiceQueryInfo(uintptr_t, uint32_t, void*, size_t);
|
||||
int APS5_VABI sceNgs2GeomResetListenerParam(Ngs2GeomListenerParam*);
|
||||
int APS5_VABI sceNgs2GeomResetSourceParam(Ngs2GeomSourceParam*);
|
||||
}
|
||||
|
||||
inline void Check(bool value, int line) {
|
||||
|
|
|
|||
|
|
@ -393,6 +393,7 @@ Throughout the project, every function at every stage either **does exactly what
|
|||
- [gethostbyname](../../core/libs/prx/libScePosixForWebKit/Resolver.cpp) (libScePosixForWebKit) - numeric IPv4 forms, trailing whitespace and 64-bit accumulation follow FreeBSD 11.4 [inet_aton](https://github.com/freebsd/freebsd-src/blob/releng/11.4/lib/libc/inet/inet_addr.c); clearing the resolver error on numeric success follows [fakeaddr](https://github.com/freebsd/freebsd-src/blob/releng/11.4/lib/libc/net/gethostnamadr.c). Exact PS5 behavior is unverified; hostname lookup still uses the host resolver
|
||||
|
||||
- [sceAppContentGetAddcontDownloadProgress](../../core/libs/prx/libSceAppContent/Export.cpp) (libSceAppContent) - imported by PPSA08755, which fails to load without it; added without an implementation because its behavior is unverified. [SharpProspero](https://github.com/SvenGDK/SharpProspero) lists `(uint32_t serviceLabel, entitlementLabel, SceAppContentAddcontDownloadProgress*)`, but no PS5 reference gives the progress layout or the error codes
|
||||
- [sceNgs2GeomResetListenerParam, sceNgs2GeomResetSourceParam](../../core/libs/prx/libSceNgs2.native/src/Geom.cpp) (libSceNgs2.native) - the structures (12, 16, 16, 60, 96, 108, 32 and 308 bytes) come from [KytyPS5](https://github.com/KytyPS5/KytyPS5)'s `ngs2.cpp` and match [shadPS4](https://github.com/shadps4-emu/shadPS4)'s `ngs2_geom.h` field for field, but only KytyPS5 gives the behaviour - shadPS4 logs and returns success without writing the output. The defaults (orient front +Z, orient up +Y, sound speed 343, cone 1/360/1/360, rolloff 0/1000000/1/1, doppler factor, full-band, LFE and maximum level 1, two speakers and matrix format 2) are unverified on a PS5 title; KytyPS5 and iStark/PS5PCEM agree on them. PPSA15552 (Dead Cells) calls `sceNgs2GeomResetSourceParam` after creating its racks. A null output address returns `INVALID_OUT_ADDRESS` as elsewhere in the library rather than throwing as KytyPS5 does. `sceNgs2GeomCalcListener` and `sceNgs2GeomApply` stay unimplemented
|
||||
|
||||
- [_sceFiberGetThreadFramePointerAddress](../../core/libs/prx/libSceFiber/Export.cpp) (libSceFiber, NID `0dy4JtMUcMQ`) forwards to `sceFiberGetThreadFramePointerAddress`; that the argument list matches is inferred from the export without the underscore, as for the underscore Ult exports, not measured
|
||||
- [sceAgcAcbWaitUntilSafeForRendering](../../core/libs/prx/libSceAgc/Acb/src/Control.cpp) (libSceAgc) - `(buffer, videoOutHandle, displayBufferIndex)`, the declared arguments, which PPSA12544 (01.000.010) passes inside `waitUntilSafeForRendering` and `waitUntilSafeForRendering VR` markers on an asynchronous compute command buffer, ignoring the result. It writes the same rendering-wait packet as `sceAgcDcbWaitUntilSafeForRendering`, which the driver now accepts on compute queues too; the wait blocks only that queue's worker. Whether the console encodes the compute variant differently is not known
|
||||
|
|
|
|||
Loading…
Reference in New Issue