@@ -383,9 +383,16 @@ void GSClut::Read32(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
383383 case PSMT4 :
384384 case PSMT4HL :
385385 case PSMT4HH :
386+
386387 clut += (TEX0 .CSA & 15 ) << 4 ;
387388 // TODO: merge these functions
388- ReadCLUT_T32_I4 (clut, m_buff32);
389+
390+ // This is for a situation with Breath of Fire Dragon Quarter where it reinterprets the buffer under CSM2 after reading as CSM1.
391+ if (TEX0 .CSM == 1 && m_write.TEX0 .CSM == 0 )
392+ ReadCLUT_T32_I4_Swizzled (clut, m_buff32);
393+ else
394+ ReadCLUT_T32_I4 (clut, m_buff32);
395+
389396 ExpandCLUT64_T32_I8 (m_buff32, (u64 *)m_buff64); // sw renderer does not need m_buff64 anymore
390397 break ;
391398 }
@@ -632,6 +639,28 @@ __forceinline void GSClut::WriteCLUT_T16_I4_CSM1(const u16* RESTRICT src, u16* R
632639 }
633640}
634641
642+ // These functions are only used if the CLUT is in 32bit mode and it swaps to CSM2, a very obscure setup used by Breath of Fire Dragon Quarter.
643+ // This doesn't handle offsetting the CLUT or anything crazy, that would be a lot more work
644+ void GSClut::ReadCLUT_T32_I4_Swizzled (const u16 * RESTRICT clut, u32 * RESTRICT dst)
645+ {
646+ // Point to the base of the palette block
647+ GSVector4i* s = (GSVector4i*)clut;
648+ GSVector4i* d = (GSVector4i*)dst;
649+
650+ GSVector4i v0 = s[0 ];
651+ GSVector4i v1 = s[2 ];
652+ GSVector4i v2 = s[32 ];
653+ GSVector4i v3 = s[34 ];
654+
655+ GSVector4i::sw16 (v0, v2, v1, v3);
656+
657+ d[0 ] = v0;
658+ d[1 ] = v1;
659+ d[2 ] = v2;
660+ d[3 ] = v3;
661+ }
662+
663+
635664void GSClut::ReadCLUT_T32_I8 (const u16 * RESTRICT clut, u32 * RESTRICT dst, int offset)
636665{
637666 // Okay this deserves a small explanation
0 commit comments