diff --git a/Source/Core/VideoCommon/BPMemory.h b/Source/Core/VideoCommon/BPMemory.h index 0d21166094..4729e06be5 100644 --- a/Source/Core/VideoCommon/BPMemory.h +++ b/Source/Core/VideoCommon/BPMemory.h @@ -1212,24 +1212,64 @@ struct fmt::formatter } }; -union X12Y12 +union ScissorPos { - BitField<0, 12, u32> y; - BitField<12, 12, u32> x; + // The top bit is ignored, and not included in the mask used by GX SDK functions + // (though libogc includes it for the bottom coordinate (only) for some reason) + // x_full and y_full include that bit for the FIFO analyzer, though it is usually unset. + // The SDK also adds 342 to these values. + BitField<0, 11, u32> y; + BitField<0, 12, u32> y_full; + BitField<12, 11, u32> x; + BitField<12, 12, u32> x_full; u32 hex; }; +template <> +struct fmt::formatter +{ + constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); } + template + auto format(const ScissorPos& pos, FormatContext& ctx) + { + return format_to(ctx.out(), + "X: {} (raw: {})\n" + "Y: {} (raw: {})", + pos.x - 342, pos.x_full, pos.y - 342, pos.y_full); + } +}; + +union ScissorOffset +{ + // The scissor offset ignores the top bit (though it isn't masked off by the GX SDK). + // Each value is also divided by 2 (so 0-511 map to 0-1022). + // x_full and y_full include that top bit for the FIFO analyzer, though it is usually unset. + // The SDK also adds 342 to each value (before dividing it). + BitField<0, 9, u32> x; + BitField<0, 10, u32> x_full; + BitField<10, 9, u32> y; + BitField<10, 10, u32> y_full; + u32 hex; +}; +template <> +struct fmt::formatter +{ + constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); } + template + auto format(const ScissorOffset& off, FormatContext& ctx) + { + return format_to(ctx.out(), + "X: {} (raw: {})\n" + "Y: {} (raw: {})", + (off.x << 1) - 342, off.x_full, (off.y << 1) - 342, off.y_full); + } +}; + union X10Y10 { BitField<0, 10, u32> x; BitField<10, 10, u32> y; u32 hex; }; -union S32X10Y10 -{ - BitField<0, 10, s32> x; - BitField<10, 10, s32> y; - u32 hex; -}; // Framebuffer/pixel stuff (incl fog) enum class SrcBlendFactor : u32 @@ -2309,8 +2349,8 @@ struct BPMemory IND_MTX indmtx[3]; // 06-0e GXSetIndTexMtx, 2x3 matrices IND_IMASK imask; // 0f TevStageIndirect tevind[16]; // 10 GXSetTevIndirect - X12Y12 scissorTL; // 20 - X12Y12 scissorBR; // 21 + ScissorPos scissorTL; // 20 + ScissorPos scissorBR; // 21 LPSize lineptwidth; // 22 line and point width u32 sucounter; // 23 u32 rascounter; // 24 @@ -2344,7 +2384,7 @@ struct BPMemory u32 boundbox0; // 55 u32 boundbox1; // 56 u32 unknown7[2]; // 57,58 - S32X10Y10 scissorOffset; // 59 + ScissorOffset scissorOffset; // 59 u32 unknown8[6]; // 5a,5b,5c,5d, 5e,5f BPS_TmemConfig tmem_config; // 60-66 u32 metric; // 67 diff --git a/Source/Core/VideoCommon/BPStructs.cpp b/Source/Core/VideoCommon/BPStructs.cpp index 503ef6154f..7e5ecf1689 100644 --- a/Source/Core/VideoCommon/BPStructs.cpp +++ b/Source/Core/VideoCommon/BPStructs.cpp @@ -815,19 +815,10 @@ std::pair GetBPRegInfo(u8 cmd, u32 cmddata) fmt::to_string(TevStageIndirect{.fullhex = cmddata})); case BPMEM_SCISSORTL: // 0x20 - { - const X12Y12 top_left{.hex = cmddata}; - return std::make_pair(RegName(BPMEM_SCISSORTL), - fmt::format("Scissor Top: {}\nScissor Left: {}", top_left.y, top_left.x)); - } + return std::make_pair(RegName(BPMEM_SCISSORTL), fmt::to_string(ScissorPos{.hex = cmddata})); case BPMEM_SCISSORBR: // 0x21 - { - const X12Y12 bottom_right{.hex = cmddata}; - return std::make_pair( - RegName(BPMEM_SCISSORBR), - fmt::format("Scissor Bottom: {}\nScissor Right: {}", bottom_right.y, bottom_right.x)); - } + return std::make_pair(RegName(BPMEM_SCISSORBR), fmt::to_string(ScissorPos{.hex = cmddata})); case BPMEM_LINEPTWIDTH: // 0x22 return std::make_pair(RegName(BPMEM_LINEPTWIDTH), fmt::to_string(LPSize{.hex = cmddata})); @@ -1002,11 +993,8 @@ std::pair GetBPRegInfo(u8 cmd, u32 cmddata) // TODO: Description case BPMEM_SCISSOROFFSET: // 0x59 - { - const S32X10Y10 xy{.hex = cmddata}; return std::make_pair(RegName(BPMEM_SCISSOROFFSET), - fmt::format("Scissor X offset: {}\nScissor Y offset: {}", xy.x, xy.y)); - } + fmt::to_string(ScissorOffset{.hex = cmddata})); case BPMEM_PRELOAD_ADDR: // 0x60 return DescriptionlessReg(BPMEM_PRELOAD_ADDR);