From 4160fa0aa07d3946cbed5e397c54e6260f67dc5a Mon Sep 17 00:00:00 2001 From: Archez Date: Sun, 15 Sep 2024 13:33:11 -0400 Subject: [PATCH] Add opcode for (un)registering blended textures as a gfx instruction (#673) --- include/libultraship/libultra/gbi.h | 11 ++++++++ src/graphic/Fast3D/gfx_pc.cpp | 42 ++++++++++++++++++++++++---- src/graphic/Fast3D/lus_gbi.h | 1 + src/window/gui/GfxDebuggerWindow.cpp | 20 +++++++++++++ 4 files changed, 69 insertions(+), 5 deletions(-) diff --git a/include/libultraship/libultra/gbi.h b/include/libultraship/libultra/gbi.h index b1ab996..fdd8fba 100644 --- a/include/libultraship/libultra/gbi.h +++ b/include/libultraship/libultra/gbi.h @@ -177,6 +177,7 @@ #define G_MTX_OTR 0x36 #define G_TEXRECT_WIDE 0x37 #define G_FILLWIDERECT 0x38 +#define G_REGBLENDEDTEX 0x3f #define G_MOVEMEM_OTR 0x42 /* GFX Effects */ @@ -2659,6 +2660,16 @@ typedef union Gfx { #define gsSPInvalidateTexCache() \ { _SHIFTL(G_INVALTEXCACHE, 24, 8), 0 } +#define gSPRegisterBlendedTex(pkt, timg, mask, replc) \ + { \ + Gfx *_g0 = (Gfx*)(pkt), *_g1 = (Gfx*)(pkt); \ + \ + _g0->words.w0 = _SHIFTL(G_REGBLENDEDTEX, 24, 8); \ + _g0->words.w1 = (uintptr_t)timg; \ + _g1->words.w0 = (uintptr_t)mask; \ + _g1->words.w1 = (uintptr_t)replc; \ + } + #define gsSPSetFB(pkt, fb) \ { \ Gfx* _g = (Gfx*)(pkt); \ diff --git a/src/graphic/Fast3D/gfx_pc.cpp b/src/graphic/Fast3D/gfx_pc.cpp index f0f10f2..105700a 100644 --- a/src/graphic/Fast3D/gfx_pc.cpp +++ b/src/graphic/Fast3D/gfx_pc.cpp @@ -3463,6 +3463,36 @@ bool gfx_read_fb_handler_custom(F3DGfx** cmd0) { return false; } +bool gfx_register_blended_texture_handler_custom(F3DGfx** cmd0) { + F3DGfx* cmd = *cmd0; + + // Flush incase we are replacing a previous blended texture that hasn't been finialized to the GPU + gfx_flush(); + + char* timg = (char*)cmd->words.w1; + + ++(*cmd0); + cmd = *cmd0; + + uint8_t* mask = (uint8_t*)cmd->words.w0; + uint8_t* replacementTex = (uint8_t*)cmd->words.w1; + + if (!gfx_check_image_signature(timg)) { + SPDLOG_ERROR( + "OTR_G_REGBLENDEDTEX: Texture is not a valid OTR resource name, unable to register blended texture"); + return false; + } + + // With no mask, we should clear the blended texture + if (mask == nullptr) { + gfx_unregister_blended_texture(timg); + } else { + gfx_register_blended_texture(timg, mask, replacementTex); + } + + return false; +} + bool gfx_set_timg_fb_handler_custom(F3DGfx** cmd0) { F3DGfx* cmd = *cmd0; @@ -3803,11 +3833,13 @@ static constexpr UcodeHandler otrHandlers = { { OTR_G_FILLWIDERECT, { "G_FILLWIDERECT", gfx_fill_wide_rect_handler_custom } }, // G_FILLWIDERECT (0x38) { OTR_G_SETGRAYSCALE, { "G_SETGRAYSCALE", gfx_set_grayscale_handler_custom } }, // G_SETGRAYSCALE (0x39) { OTR_G_EXTRAGEOMETRYMODE, - { "G_EXTRAGEOMETRYMODE", gfx_extra_geometry_mode_handler_custom } }, // G_EXTRAGEOMETRYMODE (0x3a) - { OTR_G_COPYFB, { "G_COPYFB", gfx_copy_fb_handler_custom } }, // G_COPYFB (0x3b) - { OTR_G_IMAGERECT, { "G_IMAGERECT", gfx_image_rect_handler_custom } }, // G_IMAGERECT (0x3c) - { OTR_G_DL_INDEX, { "G_DL_INDEX", gfx_dl_index_handler } }, // G_DL_INDEX (0x3d) - { OTR_G_READFB, { "G_READFB", gfx_read_fb_handler_custom } }, // G_READFB (0x3e) + { "G_EXTRAGEOMETRYMODE", gfx_extra_geometry_mode_handler_custom } }, // G_EXTRAGEOMETRYMODE (0x3a) + { OTR_G_COPYFB, { "G_COPYFB", gfx_copy_fb_handler_custom } }, // G_COPYFB (0x3b) + { OTR_G_IMAGERECT, { "G_IMAGERECT", gfx_image_rect_handler_custom } }, // G_IMAGERECT (0x3c) + { OTR_G_DL_INDEX, { "G_DL_INDEX", gfx_dl_index_handler } }, // G_DL_INDEX (0x3d) + { OTR_G_READFB, { "G_READFB", gfx_read_fb_handler_custom } }, // G_READFB (0x3e) + { OTR_G_REGBLENDEDTEX, + { "G_REGBLENDEDTEX", gfx_register_blended_texture_handler_custom } }, // G_REGBLENDEDTEX (0x3f) { OTR_G_SETINTENSITY, { "G_SETINTENSITY", gfx_set_intensity_handler_custom } }, // G_SETINTENSITY (0x40) { OTR_G_MOVEMEM_HASH, { "OTR_G_MOVEMEM_HASH", gfx_movemem_handler_otr } }, }; diff --git a/src/graphic/Fast3D/lus_gbi.h b/src/graphic/Fast3D/lus_gbi.h index 1f2e406..24efae6 100644 --- a/src/graphic/Fast3D/lus_gbi.h +++ b/src/graphic/Fast3D/lus_gbi.h @@ -63,6 +63,7 @@ constexpr int8_t OTR_G_COPYFB = OPCODE(0x3b); constexpr int8_t OTR_G_IMAGERECT = OPCODE(0x3c); constexpr int8_t OTR_G_DL_INDEX = OPCODE(0x3d); constexpr int8_t OTR_G_READFB = OPCODE(0x3e); +constexpr int8_t OTR_G_REGBLENDEDTEX = OPCODE(0x3f); constexpr int8_t OTR_G_SETINTENSITY = OPCODE(0x40); constexpr int8_t OTR_G_MOVEMEM_HASH = OPCODE(0x42); diff --git a/src/window/gui/GfxDebuggerWindow.cpp b/src/window/gui/GfxDebuggerWindow.cpp index 6d7f3bc..ea4cac2 100644 --- a/src/window/gui/GfxDebuggerWindow.cpp +++ b/src/window/gui/GfxDebuggerWindow.cpp @@ -512,6 +512,26 @@ void GfxDebuggerWindow::DrawDisasNode(const F3DGfx* cmd, std::vectorwords.w1; + cmd++; + + uint8_t* mask = (uint8_t*)cmd->words.w0; + uint8_t* replacementTex = (uint8_t*)cmd->words.w1; + + if (Ship::Context::GetInstance()->GetResourceManager()->OtrSignatureCheck(timg)) { + timg += 7; + nodeWithText(cmd0, fmt::format("G_REGBLENDEDTEX: src {}, mask {}, blended {}", timg, (void*)mask, + (void*)replacementTex)); + } else { + nodeWithText(cmd0, fmt::format("G_REGBLENDEDTEX: src {}, mask {}, blended {}", (void*)timg, + (void*)mask, (void*)replacementTex)); + } + + cmd++; + break; + } + default: { simpleNode(cmd, opcode); cmd++;