diff --git a/ps2xRuntime/include/ps2_call_list.h b/ps2xRuntime/include/ps2_call_list.h index 818b5ea2..8ad4b4ca 100644 --- a/ps2xRuntime/include/ps2_call_list.h +++ b/ps2xRuntime/include/ps2_call_list.h @@ -350,12 +350,14 @@ X(sceGsResetPath) \ X(sceGsSetDefClear) \ X(sceGsSetDefDBuffDc) \ + X(sceGsSetDefDBuff) \ X(sceGsSetDefDispEnv) \ X(sceGsSetDefDrawEnv) \ X(sceGsSetDefDrawEnv2) \ X(sceGsSetDefLoadImage) \ X(sceGsSetDefStoreImage) \ X(sceGsSwapDBuffDc) \ + X(sceGsSwapDBuff) \ X(sceGsSyncPath) \ X(sceGsSyncV) \ X(sceGsSyncVCallback) \ diff --git a/ps2xRuntime/src/lib/stubs/helpers/ps2_stubs_helpers.inl b/ps2xRuntime/src/lib/stubs/helpers/ps2_stubs_helpers.inl index 39165dc2..d09bf1cb 100644 --- a/ps2xRuntime/src/lib/stubs/helpers/ps2_stubs_helpers.inl +++ b/ps2xRuntime/src/lib/stubs/helpers/ps2_stubs_helpers.inl @@ -1552,6 +1552,17 @@ namespace GsClearMem clear1; }; + struct GsDBuffMem + { + GsDispEnvMem disp[2]; + GsGiftagMem giftag0; + GsDrawEnv1Mem draw0; + GsClearMem clear0; + GsGiftagMem giftag1; + GsDrawEnv1Mem draw1; + GsClearMem clear1; + }; + struct GsImageMem { uint16_t x; @@ -1809,6 +1820,15 @@ namespace return true; } + static bool readGsDBuff(uint8_t* rdram, uint32_t addr, GsDBuffMem& out) + { + const uint8_t* ptr = getConstMemPtr(rdram, addr); + if (!ptr) + return false; + std::memcpy(&out, ptr, sizeof(out)); + return true; + } + static bool writeGsDBuffDc(uint8_t *rdram, uint32_t addr, const GsDBuffDcMem &db) { uint8_t *ptr = getMemPtr(rdram, addr); @@ -1818,6 +1838,15 @@ namespace return true; } + static bool writeGsDBuff(uint8_t* rdram, uint32_t addr, const GsDBuffMem& db) + { + uint8_t* ptr = getMemPtr(rdram, addr); + if (!ptr) + return false; + std::memcpy(ptr, &db, sizeof(db)); + return true; + } + static bool readGsRegPairs(uint8_t *rdram, uint32_t addr, GsRegPairMem *pairs, size_t pairCount) { if (!pairs || pairCount == 0u) diff --git a/ps2xRuntime/src/lib/stubs/ps2_stubs_gs.inl b/ps2xRuntime/src/lib/stubs/ps2_stubs_gs.inl index e7256c62..f7a07f7c 100644 --- a/ps2xRuntime/src/lib/stubs/ps2_stubs_gs.inl +++ b/ps2xRuntime/src/lib/stubs/ps2_stubs_gs.inl @@ -449,6 +449,65 @@ void sceGsSetDefDBuffDc(uint8_t *rdram, R5900Context *ctx, PS2Runtime *runtime) setReturnS32(ctx, 0); } +void sceGsSetDefDBuff(uint8_t* rdram, R5900Context* ctx, PS2Runtime* runtime) +{ + const uint32_t envAddr = getRegU32(ctx, 4); + uint32_t psm = getRegU32(ctx, 5); + uint32_t w = getRegU32(ctx, 6); + uint32_t h = getRegU32(ctx, 7); + const uint32_t ztest = readStackU32(rdram, ctx, 16); + const uint32_t zpsm = readStackU32(rdram, ctx, 20); + const uint32_t clear = readStackU32(rdram, ctx, 24); + (void)clear; + + if (w == 0u) + { + w = 640u; + } + if (h == 0u) + { + h = 448u; + } + + const uint32_t fbw = std::max(1u, (w + 63u) / 64u); + const uint64_t pmode = makePmode(1u, 1u, 0u, 0u, 0u, 0x80u); + const uint64_t smode2 = + (static_cast(g_gparam.interlace & 0x1u) << 0) | + (static_cast(g_gparam.ffmode & 0x1u) << 1); + const uint64_t dispfb = makeDispFb(0u, fbw, psm, 0u, 0u); + const uint64_t display = makeDisplay(636u, 32u, 0u, 0u, w - 1u, h - 1u); + + const int32_t drawWidth = static_cast(w); + const int32_t drawHeight = static_cast(h); + + uint32_t zbufAddr = 0u; + { + R5900Context temp = *ctx; + sceGszbufaddr(rdram, &temp, runtime); + zbufAddr = getRegU32(&temp, 2); + } + + GsDBuffMem db{}; + db.disp[0].pmode = pmode; + db.disp[0].smode2 = smode2; + db.disp[0].dispfb = dispfb; + db.disp[0].display = display; + db.disp[0].bgcolor = 0u; + db.disp[1] = db.disp[0]; + + db.giftag0 = { makeGiftagAplusD(14u), 0x0E0E0E0E0E0E0E0EULL }; + seedGsDrawEnv1(db.draw0, drawWidth, drawHeight, 0u, fbw, psm, zbufAddr, zpsm, ztest, false); + db.giftag1 = db.giftag0; + seedGsDrawEnv1(db.draw1, drawWidth, drawHeight, 0u, fbw, psm, zbufAddr, zpsm, ztest, false); + + if (!writeGsDBuff(rdram, envAddr, db)) + { + setReturnS32(ctx, -1); + return; + } + setReturnS32(ctx, 0); +} + void sceGsSetDefDispEnv(uint8_t *rdram, R5900Context *ctx, PS2Runtime *runtime) { uint32_t envAddr = getRegU32(ctx, 4); @@ -605,6 +664,31 @@ void sceGsSwapDBuffDc(uint8_t *rdram, R5900Context *ctx, PS2Runtime *runtime) setReturnS32(ctx, static_cast(which ^ 1u)); } +void sceGsSwapDBuff(uint8_t* rdram, R5900Context* ctx, PS2Runtime* runtime) +{ + const uint32_t envAddr = getRegU32(ctx, 4); + const uint32_t which = getRegU32(ctx, 5) & 1u; + + GsDBuffMem db{}; + if (!runtime || !readGsDBuff(rdram, envAddr, db)) + { + setReturnS32(ctx, -1); + return; + } + + applyGsDispEnv(runtime, db.disp[which]); + if (which == 0u) + { + applyGsRegPairs(runtime, reinterpret_cast(&db.draw0), 8u); + } + else + { + applyGsRegPairs(runtime, reinterpret_cast(&db.draw1), 8u); + } + + setReturnS32(ctx, static_cast(which ^ 1u)); +} + void sceGsSyncPath(uint8_t *rdram, R5900Context *ctx, PS2Runtime *runtime) { int32_t mode = static_cast(getRegU32(ctx, 4));