From 04ef63c74270dfe9df458bd8335aac7a7097468a Mon Sep 17 00:00:00 2001 From: Adam Bird Date: Sat, 10 Jun 2023 11:53:13 -0400 Subject: [PATCH] add gSPExtraGeometryMode macros and command for inverting culling (#310) --- include/libultraship/libultra/gbi.h | 17 +++++++++++++++++ src/graphic/Fast3D/gfx_pc.cpp | 15 +++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/include/libultraship/libultra/gbi.h b/include/libultraship/libultra/gbi.h index d47ab96bc..f72898d72 100644 --- a/include/libultraship/libultra/gbi.h +++ b/include/libultraship/libultra/gbi.h @@ -183,6 +183,7 @@ // RDP Cmd #define G_SETGRAYSCALE 0x39 +#define G_EXTRAGEOMETRYMODE 0x3a #define G_SETINTENSITY 0x40 /* @@ -359,6 +360,11 @@ #endif #endif +/* + * G_EXTRAGEOMETRY flags: set extra custom geometry modes + */ +#define G_EX_INVERT_CULLING 0x00000001 + /* Need these defined for Sprite Microcode */ #ifdef _LANGUAGE_ASSEMBLY #define G_TX_LOADTILE 7 @@ -2653,6 +2659,17 @@ typedef union { #define gsSPGrayscale(state) \ { (_SHIFTL(G_SETGRAYSCALE, 24, 8)), (state) } +#define gSPExtraGeometryMode(pkt, c, s) \ + _DW({ \ + Gfx* _g = (Gfx*)(pkt); \ + \ + _g->words.w0 = _SHIFTL(G_EXTRAGEOMETRYMODE, 24, 8) | _SHIFTL(~(u32)(c), 0, 24); \ + _g->words.w1 = (u32)(s); \ + }) + +#define gSPSetExtraGeometryMode(pkt, word) gSPExtraGeometryMode((pkt), 0, word) +#define gSPClearExtraGeometryMode(pkt, word) gSPExtraGeometryMode((pkt), word, 0) + #ifdef F3DEX_GBI_2 /* * One gSPGeometryMode(pkt,c,s) GBI is equal to these two GBIs. diff --git a/src/graphic/Fast3D/gfx_pc.cpp b/src/graphic/Fast3D/gfx_pc.cpp index f00de19d1..ed321fe87 100644 --- a/src/graphic/Fast3D/gfx_pc.cpp +++ b/src/graphic/Fast3D/gfx_pc.cpp @@ -116,6 +116,8 @@ static struct RSP { uint32_t geometry_mode; int16_t fog_mul, fog_offset; + uint32_t extra_geometry_mode; + struct { // U0.16 uint16_t s, t; @@ -1382,6 +1384,11 @@ static void gfx_sp_tri1(uint8_t vtx1_idx, uint8_t vtx2_idx, uint8_t vtx3_idx, bo cross = -cross; } + // If inverted culling is requested, negate the cross + if ((rsp.extra_geometry_mode & G_EX_INVERT_CULLING) == 1) { + cross = -cross; + } + switch (rsp.geometry_mode & G_CULL_BOTH) { case G_CULL_FRONT: if (cross <= 0) { @@ -1769,6 +1776,11 @@ static void gfx_sp_geometry_mode(uint32_t clear, uint32_t set) { rsp.geometry_mode |= set; } +static void gfx_sp_extra_geometry_mode(uint32_t clear, uint32_t set) { + rsp.extra_geometry_mode &= ~clear; + rsp.extra_geometry_mode |= set; +} + static void gfx_adjust_viewport_or_scissor(XYWidthHeight* area) { if (!fbActive) { area->width *= RATIO_X; @@ -3035,6 +3047,9 @@ static void gfx_run_dl(Gfx* cmd) { gfx_s2dex_bg_copy((uObjBg*)cmd->words.w1); // not seg_addr here it seems } + break; + case G_EXTRAGEOMETRYMODE: + gfx_sp_extra_geometry_mode(~C0(0, 24), cmd->words.w1); break; } ++cmd;