Merge pull request #3448 from Feuris/carry/agc-debug-raise-exception
feat(libSceAgc): implement sceAgcDebugRaiseException
This commit is contained in:
commit
077eeb05ea
|
|
@ -29,6 +29,7 @@ add_library(libSceAgc SHARED EXCLUDE_FROM_ALL
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/DcbState/src/Predication.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/DcbState/src/Registers.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/DcbState/src/Workload.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Misc/src/Debug.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Misc/src/PacketInfo.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Misc/src/Platform.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Misc/src/RegisterDefaults.cpp
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
#ifndef CORE_LIBS_PRX_LIBSCEAGC_MISC_INCLUDE_DEBUG_HPP
|
||||
#define CORE_LIBS_PRX_LIBSCEAGC_MISC_INCLUDE_DEBUG_HPP
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
#include "prx/libSceAgc/Misc/include/Debug.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include "SceTypes.hpp"
|
||||
#include "prx/libc/include/General.hpp"
|
||||
|
||||
extern "C" {
|
||||
|
||||
int APS5_VABI sceAgcDebugRaiseException(std::uint32_t exceptionId) {
|
||||
APS5_LOG_OUT("sceAgcDebugRaiseException exceptionId=0x%08x", static_cast<unsigned>(exceptionId));
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -50,11 +50,6 @@ int APS5_VABI sceAgcDcbSetWorkloadStreamInactive() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI sceAgcDebugRaiseException() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI sceAgcGetDefaultCxStateFlat() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ extern "C" std::uint32_t* APS5_VABI sceAgcAcbSetMarker(CommandBuffer* buf, const
|
|||
extern "C" std::uint32_t* APS5_VABI sceAgcDcbSetIndexBuffer(CommandBuffer* buf, std::uint64_t indexAddress);
|
||||
extern "C" std::uint32_t* APS5_VABI sceAgcDcbSetBaseIndirectArgs(CommandBuffer* buf, std::uint32_t shaderType, const volatile void* indirectBaseAddr);
|
||||
extern "C" std::uint32_t* APS5_VABI sceAgcSetNop(CommandBuffer* buf, std::uint32_t sizeDw);
|
||||
extern "C" int APS5_VABI sceAgcDebugRaiseException(std::uint32_t exceptionId);
|
||||
|
||||
namespace {
|
||||
|
||||
|
|
@ -403,6 +404,16 @@ void testMemory() {
|
|||
check(storage.words == beforeMask, "invalid mask patch modified packet memory");
|
||||
}
|
||||
|
||||
void testDebugRaiseException() {
|
||||
int result = -1;
|
||||
try {
|
||||
result = sceAgcDebugRaiseException(0x1234abcdu);
|
||||
} catch (const std::exception& error) {
|
||||
throw std::runtime_error(std::string("debug exception stopped the caller: ") + error.what());
|
||||
}
|
||||
check(result == 0, "debug exception did not return 0");
|
||||
}
|
||||
|
||||
void testDefaults() {
|
||||
std::uint32_t state = 0x12345678;
|
||||
check(sceAgcInit_0090(&state, 8) == 0 && state == 0x12345678, "AGC initialization failed or modified caller state");
|
||||
|
|
@ -448,6 +459,7 @@ int main(int argc, char** argv) {
|
|||
testRegisterRange();
|
||||
testPacketPayloadAddress();
|
||||
testMemory();
|
||||
testDebugRaiseException();
|
||||
testDefaults();
|
||||
LibcRunShutdown_nid_postfix();
|
||||
std::puts("AGC command tests passed");
|
||||
|
|
|
|||
|
|
@ -397,6 +397,7 @@ Throughout the project, every function at every stage either **does exactly what
|
|||
- [pthread_sigmask](../../core/libs/prx/libkernel/System/src/Signals.cpp) (libkernel) shares the process-wide mask of `sigprocmask` and `_sigprocmask`, which keeps only the first 32 signals; FreeBSD keeps a mask per thread
|
||||
- [sceKernelRaiseException](../../core/libs/prx/libkernel/System/src/Exception.cpp) reaches a thread that waits in an alertable `TimedWait` wait through an APC. A thread blocked anywhere else, including all waits under `APS5_COARSE_TIMED_WAITS` and host waits inside the emulator, is redirected and runs the handler only when that wait returns
|
||||
- [sceKernelRaiseException](../../core/libs/prx/libkernel/System/src/Exception.cpp) on Windows runs the handler wherever the target thread was interrupted. It waits only while the thread is inside winpthreads or restoring a context through `NtContinue`, and throws if that lasts 1 s, so a handler that calls into other host code the thread was interrupted in, such as the C runtime's heap or a lock of the emulator, can deadlock on it or reenter it
|
||||
- [sceAgcDebugRaiseException](../../core/libs/prx/libSceAgc/Misc/src/Debug.cpp) (libSceAgc) - logs the exception id and returns 0, as retail hardware does nothing per [OpenAGC](https://github.com/OpenAGC/OpenAGC/blob/3c7e8072f0d7684e930454794fd5c02056946d73/src/game_compat.c); the trap (`ud2`) OpenAGC describes for development hardware is not reproduced. Neither is verified on a console. The `uint32` exception id is [KytyPS5](https://github.com/KytyPS5/KytyPS5/blob/6f0cddd4404ec5203e71fea77e75fc373299ba3f/src/libs/agc.cpp)'s claim; OpenAGC declares no arguments, so the logged id may be leftover register contents
|
||||
- [sigaltstack](../../core/libs/prx/libkernel/System/src/Signals.cpp) (libkernel) records each thread's alternate signal stack and reports it back, following FreeBSD's `kern_sigaltstack` (`EINVAL` for flags other than `SS_DISABLE`, `ENOMEM` below `MINSIGSTKSZ` 2048), but handlers never run on it, so `SS_ONSTACK` and `EPERM` are never reported
|
||||
- [libSceUlt queues](../../core/libs/prx/libSceUlt/Export.cpp) use preallocated host storage instead of the supplied guest work area; its existing size formula and the 512-byte object layouts remain unverified. Waiting-queue pool thread limits and waiter priority ordering are not implemented. Finalization wakes blocked queue callers with `ULT_ERROR_STATE`.
|
||||
- [Thread cancellation](../../core/libs/prx/libkernel/Pthread/src/Thread.cpp) (libkernel) follows FreeBSD libthr (states and types 0/1 and 0/2, `PTHREAD_CANCELED` 1, the `_pthread_cleanup_info` node layout), not measured on the console. A request is acted on only in `scePthreadTestcancel`, the condition variable, `sem` and `scePthreadSem` waits, `scePthreadJoin` and the sleeps, and their POSIX names; file and socket calls are not cancellation points. A sleep is not interrupted: the thread exits when it ends. The asynchronous type acts like the deferred one, except at the two set calls.
|
||||
|
|
|
|||
Loading…
Reference in New Issue