mirror of
https://github.com/ran-j/PS2Recomp.git
synced 2026-09-29 09:50:27 -04:00
fix(runtime): stop double-counting nloop in sceGifPkRefLoadImage A+D header GIFtag (#149)
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.
This commit is contained in:
committed by
GitHub
parent
c4355c8cda
commit
81f2a7f5e1
@@ -504,7 +504,10 @@ namespace ps2_stubs
|
||||
sizeof(words));
|
||||
writePacketBuilderCurrent(rdram, runtime, stateAddr, packetAddr + 16u);
|
||||
|
||||
const uint64_t giftag[2] = {makeGiftagAplusD(4u), 0xEULL};
|
||||
// Seed an open A+D tag (nloop=0, EOP clear): closePacketGifTag adds the true
|
||||
// appended qword count, so a pre-set nloop would double-count. Open variant
|
||||
// (not makeGiftagAplusD) because that always sets EOP on this chained tag.
|
||||
const uint64_t giftag[2] = {makeGiftagAplusDOpen(0u), 0xEULL};
|
||||
uint32_t currentAddr = packetAddr + 16u;
|
||||
writeGuestBytes(rdram, runtime, currentAddr, reinterpret_cast<const uint8_t *>(giftag), sizeof(giftag));
|
||||
writePacketBuilderCurrent(rdram, runtime, stateAddr, currentAddr + 16u);
|
||||
|
||||
@@ -1673,6 +1673,14 @@ namespace
|
||||
(static_cast<uint64_t>(1u) << 60);
|
||||
}
|
||||
|
||||
// Like makeGiftagAplusD but leaves EOP (bit 15) clear, for a chained/open
|
||||
// A+D tag whose nloop is finalized later by closePacketGifTag.
|
||||
static uint64_t makeGiftagAplusDOpen(uint32_t nloop)
|
||||
{
|
||||
return (static_cast<uint64_t>(nloop & 0x7FFFu) << 0) |
|
||||
(static_cast<uint64_t>(1u) << 60);
|
||||
}
|
||||
|
||||
static uint32_t readStackU32(uint8_t *rdram, R5900Context *ctx, uint32_t offset)
|
||||
{
|
||||
uint32_t sp = getRegU32(ctx, 29);
|
||||
|
||||
Reference in New Issue
Block a user