diff --git a/game/graphics/texture/TextureConverter.cpp b/game/graphics/texture/TextureConverter.cpp index 50a767c9f1..4152691b0a 100644 --- a/game/graphics/texture/TextureConverter.cpp +++ b/game/graphics/texture/TextureConverter.cpp @@ -6,6 +6,8 @@ #include "fmt/core.h" +//TODO: IS THIS CLASS ANYWHERE USED? + TextureConverter::TextureConverter() { m_vram.resize(4 * 1024 * 1024); } @@ -41,63 +43,67 @@ void TextureConverter::download_rgba8888(u8* result, u32 clut_vram_addr, u32 expected_size_bytes) { u32 out_offset = 0; - int read_width = 64 * goal_tex_width; - - // Helper for CLUT addressing - auto calculate_clut_address = [&](u8 value, int clut_psm) -> u32 { - u32 clut_chunk = value / 16; - u32 off_in_chunk = value % 16; - u8 clx = (clut_chunk & 1) ? 8 : 0; - u8 cly = (clut_chunk >> 1) * 2; - if (off_in_chunk >= 8) { - off_in_chunk -= 8; - cly++; - } - clx += off_in_chunk; - if (clut_psm == int(CPSM::PSMCT32)) { - return psmct32_addr(clx, cly, 64) + clut_vram_addr * 256; - } else if (clut_psm == int(CPSM::PSMCT16)) { - return psmct16_addr(clx, cly, 64) + clut_vram_addr * 256; - } - ASSERT(false); // Invalid CLUT format - return 0; - }; + // width is like the TEX0 register, in 64 texel units. + // not sure what the other widths are yet. + u32 read_width = 64 * goal_tex_width; - // Pixel processing function - auto process_pixel = [&](u32 x, u32 y, u32 addr, int clut_psm) -> u32 { - u8 value = *(u8*)(m_vram.data() + addr); - u32 clut_addr = calculate_clut_address(value, clut_psm); + // Looks for CLUT Value for given PSMCT Mode + auto lookup_CLUT = [&](u8 clx, u8 cly, u32 clut_psm) -> u32 { if (clut_psm == int(CPSM::PSMCT32)) { + u32 clut_addr = psmct32_addr(clx, cly, 64) + clut_vram_addr * 256; return *(u32*)(m_vram.data() + clut_addr); } else if (clut_psm == int(CPSM::PSMCT16)) { + u32 clut_addr = psmct16_addr(clx, cly, 64) + clut_vram_addr * 256; return rgba16_to_rgba32(*(u16*)(m_vram.data() + clut_addr)); } - ASSERT(false); + ASSERT(false, "Wrong Clut_PSM given!"); return 0; }; - // Main loop + // Main Code: loop over pixels in output texture image for (u32 y = 0; y < h; y++) { for (u32 x = 0; x < w; x++) { - u32 addr = 0; + u32 rgba_value = 0; + if (psm == int(PSM::PSMT8)) { - addr = psmt8_addr(x, y, read_width) + vram_addr * 256; + u32 addr = psmt8_addr(x, y, read_width) + vram_addr * 256; + u8 value = *(u8*)(m_vram.data() + addr); + + // there's yet another scramble from the CLUT. The palette index turns into an X, Y value + // See GS manual 2.7.3 CLUT Storage Mode, IDTEX8 in CSM1 mode. + u32 clut_chunk = value / 16; + u32 off_in_chunk = value % 16; + u8 clx = (clut_chunk & 1) ? 8 : 0; + u8 cly = (clut_chunk >> 1) * 2; + if (off_in_chunk >= 8) { + off_in_chunk -= 8; + cly++; + } + clx += off_in_chunk; + + rgba_value = lookup_CLUT(clx, cly, clut_psm); } else if (psm == int(PSM::PSMT4)) { - auto addr4 = psmt4_addr_half_byte(x, y, read_width) + vram_addr * 512; - u8 value = *(u8*)(m_vram.data() + addr4 / 2); - value = (addr4 & 1) ? (value >> 4) : (value & 0x0F); - addr = value; + u32 addr = psmt4_addr_half_byte(x, y, read_width) + vram_addr * 512; + u8 value = *(u8*)(m_vram.data() + addr / 2); + value = (addr & 1) ? (value >> 4) : (value & 0x0F); + + // there's yet another scramble from the CLUT. The palette index turns into an X, Y value + // See GS manual 2.7.3 CLUT Storage Mode, IDTEX4 in CSM1 mode. + u8 clx = value & 0x7; + u8 cly = value >> 3; + + rgba_value = lookup_CLUT(clx, cly, clut_psm); } else if (psm == int(PSM::PSMCT16) && clut_psm == 0) { - addr = psmct16_addr(x, y, read_width) + vram_addr * 256; + // plain 16-bit texture + // not a clut. + // will store output pixels, rgba (8888) + u32 addr = psmct16_addr(x, y, read_width) + vram_addr * 256; u16 value = *(u16*)(m_vram.data() + addr); - u32 rgba32 = rgba16_to_rgba32(value); - memcpy(result + out_offset, &rgba32, 4); - out_offset += 4; - continue; + rgba_value = rgba16_to_rgba32(value); + } else { + ASSERT(false); } - // Process pixel through CLUT - u32 rgba_value = process_pixel(x, y, addr, clut_psm); memcpy(result + out_offset, &rgba_value, 4); out_offset += 4; }