Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions ps2xRuntime/src/lib/gs/gs_cpu_backend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -948,9 +948,14 @@ uint32_t GSCpuBackend::LookupCLUT(const GSDrawState &state,
uint8_t sourcePsm)
{
const uint32_t clutIndex = resolveClutIndex(index, cpsm, csm, csa, sourcePsm);
const uint32_t clutWidth = (state.texclut.cbw != 0u) ? static_cast<uint32_t>(state.texclut.cbw) : 1u;
const uint32_t clutX = static_cast<uint32_t>(state.texclut.cou) + (clutIndex & 0x0Fu);
const uint32_t clutY = static_cast<uint32_t>(state.texclut.cov) + (clutIndex >> 4);
const bool csm2 = csm != 0u;
const uint32_t clutWidth = csm2 && state.texclut.cbw != 0u
? static_cast<uint32_t>(state.texclut.cbw)
: 1u;
const uint32_t clutX = (csm2 ? static_cast<uint32_t>(state.texclut.cou) << 4u : 0u) +
(clutIndex & 0x0Fu);
const uint32_t clutY = (csm2 ? static_cast<uint32_t>(state.texclut.cov) : 0u) +
(clutIndex >> 4);

switch (cpsm)
{
Expand Down
63 changes: 60 additions & 3 deletions ps2xTest/src/ps2_gs_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2993,7 +2993,7 @@ void register_ps2_gs_tests()
"TEX2 should override the active CLUT base and format state without requiring a new TEX0 write");
});

tc.Run("GS TEXCLUT offsets T8 CLUT fetch coordinates", [](TestCase &t)
tc.Run("GS CSM2 TEXCLUT offsets T8 CLUT fetch coordinates", [](TestCase &t)
{
std::vector<uint8_t> vram(PS2_GS_VRAM_SIZE, 0u);
GS gs;
Expand Down Expand Up @@ -3032,7 +3032,7 @@ void register_ps2_gs_tests()
vram[texOff] = 0u;

const uint32_t wrongClutOff = GSPSMCT32::addrPSMCT32(kClutCbp, 1u, 0u, 0u);
const uint32_t expectedClutOff = GSPSMCT32::addrPSMCT32(kClutCbp, 1u, 3u, 2u);
const uint32_t expectedClutOff = GSPSMCT32::addrPSMCT32(kClutCbp, 1u, 48u, 2u);
std::memcpy(vram.data() + wrongClutOff, &kWrongColor, sizeof(kWrongColor));
std::memcpy(vram.data() + expectedClutOff, &kExpectedColor, sizeof(kExpectedColor));

Expand All @@ -3054,7 +3054,64 @@ void register_ps2_gs_tests()
uint32_t pixel = 0u;
std::memcpy(&pixel, vram.data(), sizeof(pixel));
t.Equals(pixel, kExpectedColor,
"TEXCLUT should offset the CLUT lookup coordinates instead of always starting from the CLUT base");
"CSM2 should apply TEXCLUT COU in 16-pixel units and COV in rows");
});

tc.Run("GS CSM1 ignores TEXCLUT fetch coordinates", [](TestCase &t)
{
std::vector<uint8_t> vram(PS2_GS_VRAM_SIZE, 0u);
GS gs;
gs.init(vram.data(), static_cast<uint32_t>(vram.size()), nullptr);

constexpr uint32_t kTexTbp = 64u;
constexpr uint32_t kClutCbp = 128u;
constexpr uint64_t kFrameReg =
(1ull << 16) |
(static_cast<uint64_t>(GS_PSM_CT32) << 24);
constexpr uint64_t kTex0 =
(static_cast<uint64_t>(kTexTbp) << 0) |
(1ull << 14) |
(static_cast<uint64_t>(GS_PSM_T8) << 20) |
(1ull << 34) |
(1ull << 35) |
(static_cast<uint64_t>(kClutCbp) << 37) |
(static_cast<uint64_t>(GS_PSM_CT32) << 51);
constexpr uint64_t kTexClut =
(1ull << 0) |
(3ull << 6) |
(2ull << 12);
constexpr uint64_t kPrim =
static_cast<uint64_t>(GS_PRIM_SPRITE) |
(1ull << 4) |
(1ull << 8);
constexpr uint32_t kExpectedColor = 0xFF3366CCu;
constexpr uint32_t kWrongColor = 0xFF00FF00u;

const uint32_t texOff = GSPSMT8::addrPSMT8(kTexTbp, 1u, 0u, 0u);
vram[texOff] = 0u;

const uint32_t expectedClutOff = GSPSMCT32::addrPSMCT32(kClutCbp, 1u, 0u, 0u);
const uint32_t wrongClutOff = GSPSMCT32::addrPSMCT32(kClutCbp, 1u, 3u, 2u);
std::memcpy(vram.data() + expectedClutOff, &kExpectedColor, sizeof(kExpectedColor));
std::memcpy(vram.data() + wrongClutOff, &kWrongColor, sizeof(kWrongColor));

gs.writeRegister(GS_REG_FRAME_1, kFrameReg);
gs.writeRegister(GS_REG_ZBUF_1, (1ull << 32));
gs.writeRegister(GS_REG_SCISSOR_1, 0ull);
gs.writeRegister(GS_REG_TEST_1, 0x30000ull);
gs.writeRegister(GS_REG_TEX0_1, kTex0);
gs.writeRegister(GS_REG_TEXCLUT, kTexClut);
gs.writeRegister(GS_REG_PRIM, kPrim);
gs.writeRegister(GS_REG_RGBAQ, 0x80808080ull);
gs.writeRegister(GS_REG_UV, 0ull);
gs.writeRegister(GS_REG_XYZ2, 0ull);
gs.writeRegister(GS_REG_UV, 0ull);
gs.writeRegister(GS_REG_XYZ2, (16ull << 0) | (16ull << 16));

uint32_t pixel = 0u;
std::memcpy(&pixel, vram.data(), sizeof(pixel));
t.Equals(pixel, kExpectedColor,
"CSM1 should use its fixed CLUT layout regardless of TEXCLUT state");
});

tc.Run("GS TEXA expands CT24 alpha and honors AEM for black texels", [](TestCase &t)
Expand Down