diff --git a/ps2xRuntime/src/lib/ps2_vif1_interpreter.cpp b/ps2xRuntime/src/lib/ps2_vif1_interpreter.cpp index 05fc764a8..12a7f50a9 100644 --- a/ps2xRuntime/src/lib/ps2_vif1_interpreter.cpp +++ b/ps2xRuntime/src/lib/ps2_vif1_interpreter.cpp @@ -674,13 +674,13 @@ void PS2Memory::processVIF1Data(const uint8_t *data, uint32_t sizeBytes) } else if (vl == 3u && vn == 3u) { - // V4-5: packed color-like format in a single 16-bit value. + // V4-5 expands 5-bit RGB and 1-bit alpha into the upper bits of each lane. uint16_t packed = 0; std::memcpy(&packed, srcVec, sizeof(packed)); - decompressed[0] = packed & 0x1Fu; - decompressed[1] = (packed >> 5) & 0x1Fu; - decompressed[2] = (packed >> 10) & 0x1Fu; - decompressed[3] = (packed >> 15) & 0x01u; + decompressed[0] = (packed & 0x001Fu) << 3u; + decompressed[1] = (packed & 0x03E0u) >> 2u; + decompressed[2] = (packed & 0x7C00u) >> 7u; + decompressed[3] = (packed & 0x8000u) >> 8u; } else { diff --git a/ps2xTest/src/ps2_memory_tests.cpp b/ps2xTest/src/ps2_memory_tests.cpp index 7c3e8ea5d..4c9e1de0a 100644 --- a/ps2xTest/src/ps2_memory_tests.cpp +++ b/ps2xTest/src/ps2_memory_tests.cpp @@ -531,6 +531,31 @@ void register_ps2_memory_tests() t.Equals(sw, 0x00008001u, "zero-extend w"); }); + tc.Run("VIF UNPACK V4-5 expands packed channels", [](TestCase &t) + { + PS2Memory mem; + t.IsTrue(mem.initialize(), "PS2Memory initialize should succeed"); + std::memset(mem.getVU1Data(), 0, PS2_VU1_DATA_SIZE); + + std::vector packet; + appendU32(packet, makeVifCmd(0x6Fu, 1u, 0u)); // UNPACK V4-5, NUM=1, ADDR=0 + appendU32(packet, 0x0000FC41u); // X=1, Y=2, Z=31, W=1 + + mem.processVIF1Data(packet.data(), static_cast(packet.size())); + + const uint8_t *vu = mem.getVU1Data(); + uint32_t x = 0, y = 0, z = 0, w = 0; + std::memcpy(&x, vu + 0u, 4u); + std::memcpy(&y, vu + 4u, 4u); + std::memcpy(&z, vu + 8u, 4u); + std::memcpy(&w, vu + 12u, 4u); + + t.Equals(x, 8u, "V4-5 should expand X from five bits"); + t.Equals(y, 16u, "V4-5 should expand Y from five bits"); + t.Equals(z, 248u, "V4-5 should expand Z from five bits"); + t.Equals(w, 128u, "V4-5 should expand W from one bit"); + }); + tc.Run("VIF UNPACK bit15 adds TOPS to destination address", [](TestCase &t) { PS2Memory mem;