sceGifPkRefLoadImage seeded its A+D header GIFtag with nloop=4 via makeGiftagAplusD(4u), then closePacketGifTag computed the appended register-qword count (4) from the write-cursor delta and ADDED it to the seed, finalizing nloop=8 for a tag with only 4 A+D register qwords (BITBLTBUF/TRXPOS/TRXREG/TRXDIR). A GIF parser consuming that tag eats the following IMAGE GIFtag and its first payload qwords as bogus A+D data, starving the CLUT/texture upload that the setup packet precedes (e.g. DQ8 font-glyph CLUTs staying all-zero). Seed an open A+D tag (nloop=0, nreg=1, EOP clear) instead and let closePacketGifTag add the true count, finalizing 0x1000000000000004 -- the value the regression test pins. The seed is written via a named makeGiftagAplusDOpen(nloop) helper in Support.h (mirrors makeGiftagAplusD but leaves EOP/bit 15 clear for a chained tag whose nloop is finalized at close), rather than a bare (1ULL << 60) literal, to keep the file's GIFtag-construction convention consistent. makeGiftagAplusD(0u) can't be used because it always sets EOP. Adds a byte-level regression test that drives sceGifPkRefLoadImage (setup only, qwcRemaining=0) against a scratch packet-builder state and asserts the finalized header tag lo/hi, the four A+D register descriptors (0x50..0x53), and their four register payloads (BITBLTBUF dbp/dbw/psm, TRXPOS, TRXREG width/height, TRXDIR) -- pinning the full setup packet. Full build clean; ps2x_tests 297/297.
Runtime Library
The runtime library provides the execution environment for recompiled code, including:
- Memory management (32MB main RAM, scratchpad, etc.)
- Register context (128-bit GPRs, VU0 registers, etc.)
- Function table for dynamic linking
- Basic PS2 system call stubs
How to use:
Take your decompiled code and place the cpp files on ps2xRuntime/src/runner and header files on ps2xRuntime/include and compile/be happy.
Vita Build Notes
The Vita runtime uses Quenom/raylib-5.5-vita for vita build. I recommend build runtime only.
Expected environment:
VITASDKpoints to your VitaSDK root.Quenom/raylib-5.5-vitahas already been built and installed into$VITASDK/arm-vita-eabi.- SDL2 with the PVR backend required by that raylib fork is also installed into the same VitaSDK prefix.
PS2X_DEFAULT_BOOT_ELFis mandatory, you need to define where your game is like "ux0:data/RANJ00001/game/SLUS_201.84".
The CMake for ps2xRuntime consumes those preinstalled headers and libraries from VitaSDK. It does not fetch or install the Vita raylib fork for you.
Adding Custom Function Implementations
You can add custom implementations for PS2 system calls or game functions by:
- Creating function implementations that match the signature:
void function_name(uint8_t* rdram, R5900Context* ctx, PS2Runtime *runtime);
- Registering them with the runtime:
runtime.registerFunction(address, function_name);
Advanced Features
Memory Translation The runtime handles PS2's memory addressing, including:
- KSEG0/KSEG1 direct mapping
- TLB lookups for user memory
- Special memory areas (scratchpad, I/O registers)
Vector Unit Support
PS2-specific 128-bit MMI instructions and VU0 macro mode instructions are supported via SSE/AVX intrinsics.
Instruction Patching
You can patch specific instructions in the recompiled code to fix game issues or implement custom behavior.
Limitations
- Graphics and sound output require external implementations
- Some PS2-specific hardware features may not be fully supported
- Performance may vary based on the complexity of the game