From f467c02d1ad63384674e04dee1c8d896b1c68ea5 Mon Sep 17 00:00:00 2001 From: Pokechu22 Date: Sun, 4 Jul 2021 20:32:07 -0700 Subject: [PATCH 1/2] Ignore the top bit of the indirect texture matrix scale This fixes the Zora eye coloration in Twilight Princess. --- Source/Core/VideoCommon/BPMemory.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Source/Core/VideoCommon/BPMemory.h b/Source/Core/VideoCommon/BPMemory.h index 25b54b6ba4..e63fb17dd3 100644 --- a/Source/Core/VideoCommon/BPMemory.h +++ b/Source/Core/VideoCommon/BPMemory.h @@ -375,7 +375,10 @@ union IND_MTXC { BitField<0, 11, s32> me; BitField<11, 11, s32> mf; - BitField<22, 2, u8, u32> s2; // bits 4-5 of scale factor + BitField<22, 1, u8, u32> s2; // bit 4 of scale factor + // The SDK treats the scale factor as 6 bits, 2 on each column; however, hardware seems to ignore + // the top bit. + BitField<22, 2, u8, u32> sdk_s2; u32 hex; }; From b880be0aa56ac9807957574682902cb8cc2a9c9b Mon Sep 17 00:00:00 2001 From: Pokechu22 Date: Mon, 5 Jul 2021 12:55:32 -0700 Subject: [PATCH 2/2] Use separate fmt::formatters for each indirect matrix column This also fixes a bug where the float version of row 1 actually showed row 0 again. --- Source/Core/VideoCommon/BPMemory.h | 43 +++++++++++++++++++++++++++ Source/Core/VideoCommon/BPStructs.cpp | 40 ++++++++++--------------- 2 files changed, 58 insertions(+), 25 deletions(-) diff --git a/Source/Core/VideoCommon/BPMemory.h b/Source/Core/VideoCommon/BPMemory.h index e63fb17dd3..441fafe36c 100644 --- a/Source/Core/VideoCommon/BPMemory.h +++ b/Source/Core/VideoCommon/BPMemory.h @@ -362,6 +362,20 @@ union IND_MTXA BitField<22, 2, u8, u32> s0; // bits 0-1 of scale factor u32 hex; }; +template <> +struct fmt::formatter +{ + constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); } + template + auto format(const IND_MTXA& col, FormatContext& ctx) + { + return format_to(ctx.out(), + "Row 0 (ma): {} ({})\n" + "Row 1 (mb): {} ({})\n" + "Scale bits: {} (shifted: {})", + col.ma / 1024.0f, col.ma, col.mb / 1024.0f, col.mb, col.s0, col.s0); + } +}; union IND_MTXB { @@ -370,6 +384,20 @@ union IND_MTXB BitField<22, 2, u8, u32> s1; // bits 2-3 of scale factor u32 hex; }; +template <> +struct fmt::formatter +{ + constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); } + template + auto format(const IND_MTXB& col, FormatContext& ctx) + { + return format_to(ctx.out(), + "Row 0 (mc): {} ({})\n" + "Row 1 (md): {} ({})\n" + "Scale bits: {} (shifted: {})", + col.mc / 1024.0f, col.mc, col.md / 1024.0f, col.md, col.s1, col.s1 << 2); + } +}; union IND_MTXC { @@ -381,6 +409,21 @@ union IND_MTXC BitField<22, 2, u8, u32> sdk_s2; u32 hex; }; +template <> +struct fmt::formatter +{ + constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); } + template + auto format(const IND_MTXC& col, FormatContext& ctx) + { + return format_to(ctx.out(), + "Row 0 (me): {} ({})\n" + "Row 1 (mf): {} ({})\n" + "Scale bits: {} (shifted: {}), given to SDK as {} ({})", + col.me / 1024.0f, col.me, col.mf / 1024.0f, col.mf, col.s2, col.s2 << 4, + col.sdk_s2, col.sdk_s2 << 4); + } +}; struct IND_MTX { diff --git a/Source/Core/VideoCommon/BPStructs.cpp b/Source/Core/VideoCommon/BPStructs.cpp index 445d84d0fb..97c78474e1 100644 --- a/Source/Core/VideoCommon/BPStructs.cpp +++ b/Source/Core/VideoCommon/BPStructs.cpp @@ -764,35 +764,25 @@ std::pair GetBPRegInfo(u8 cmd, u32 cmddata) // TODO: Description case BPMEM_IND_MTXA: // 0x06 - case BPMEM_IND_MTXB: // 0x07 - case BPMEM_IND_MTXC: // 0x08 case BPMEM_IND_MTXA + 3: - case BPMEM_IND_MTXB + 3: - case BPMEM_IND_MTXC + 3: case BPMEM_IND_MTXA + 6: + return std::make_pair(fmt::format("BPMEM_IND_MTXA Matrix {}", (cmd - BPMEM_IND_MTXA) / 3), + fmt::format("Matrix {} column A\n{}", (cmd - BPMEM_IND_MTXA) / 3, + IND_MTXA{.hex = cmddata})); + + case BPMEM_IND_MTXB: // 0x07 + case BPMEM_IND_MTXB + 3: case BPMEM_IND_MTXB + 6: + return std::make_pair(fmt::format("BPMEM_IND_MTXB Matrix {}", (cmd - BPMEM_IND_MTXB) / 3), + fmt::format("Matrix {} column B\n{}", (cmd - BPMEM_IND_MTXB) / 3, + IND_MTXB{.hex = cmddata})); + + case BPMEM_IND_MTXC: // 0x08 + case BPMEM_IND_MTXC + 3: case BPMEM_IND_MTXC + 6: - { - const u32 matrix_num = (cmd - BPMEM_IND_MTXA) / 3; - const u32 matrix_col = (cmd - BPMEM_IND_MTXA) % 3; - // These all use the same structure, though the meaning is *slightly* different; - // for conveninece implement it only once - const s32 row0 = cmddata & 0x0007ff; // ma or mc or me - const s32 row1 = (cmddata & 0x3ff800) >> 11; // mb or md or mf - const u32 scale = (cmddata & 0xc00000) >> 22; // 2 bits of a 6-bit field for each column - - const float row0f = static_cast(row0) / (1 << 10); - const float row1f = static_cast(row0) / (1 << 10); - - return std::make_pair(fmt::format("BPMEM_IND_MTX{} Matrix {}", "ABC"[matrix_col], matrix_num), - fmt::format("Matrix {} column {} ({})\n" - "Row 0 (m{}): {} ({})\n" - "Row 1 (m{}): {} ({})\n" - "Scale bits: {} (shifted: {})", - matrix_num, matrix_col, "ABC"[matrix_col], "ace"[matrix_col], - row0f, row0, "bdf"[matrix_col], row1f, row1, scale, - scale << (2 * matrix_col))); - } + return std::make_pair(fmt::format("BPMEM_IND_MTXC Matrix {}", (cmd - BPMEM_IND_MTXC) / 3), + fmt::format("Matrix {} column C\n{}", (cmd - BPMEM_IND_MTXC) / 3, + IND_MTXC{.hex = cmddata})); case BPMEM_IND_IMASK: // 0x0F return DescriptionlessReg(BPMEM_IND_IMASK);