diff --git a/mm/2s2h/BenPort.cpp b/mm/2s2h/BenPort.cpp index 2c8a0112d..b767efa9e 100644 --- a/mm/2s2h/BenPort.cpp +++ b/mm/2s2h/BenPort.cpp @@ -56,6 +56,7 @@ CrowdControl* CrowdControl::Instance; #include "Enhancements/GameInteractor/GameInteractor.h" #include "Enhancements/Enhancements.h" +#include "2s2h/Enhancements/GfxPatcher/AuthenticGfxPatches.h" // Resource Types/Factories #include "2s2h/resource/type/Animation.h" @@ -313,6 +314,7 @@ extern "C" void InitOTR() { GameInteractor::Instance = new GameInteractor(); BenGui::SetupGuiElements(); InitEnhancements(); + GfxPatcher_ApplyNecessaryAuthenticPatches(); clearMtx = (uintptr_t)&gMtxClear; //OTRMessage_Init(); @@ -920,6 +922,11 @@ extern "C" void ResourceMgr_PatchGfxByName(const char* path, const char* patchNa // index /= 2; // } + // Do not patch custom assets as they most likely do not have the same instructions as authentic assets + if (res->GetInitData()->IsCustom) { + return; + } + Gfx* gfx = (Gfx*)&res->Instructions[index]; if (!originalGfx.contains(path) || !originalGfx[path].contains(patchName)) { @@ -934,6 +941,11 @@ extern "C" void ResourceMgr_PatchGfxCopyCommandByName(const char* path, const ch auto res = std::static_pointer_cast( LUS::Context::GetInstance()->GetResourceManager()->LoadResource(path)); + // Do not patch custom assets as they most likely do not have the same instructions as authentic assets + if (res->GetInitData()->IsCustom) { + return; + } + Gfx* destinationGfx = (Gfx*)&res->Instructions[destinationIndex]; Gfx sourceGfx = res->Instructions[sourceIndex]; diff --git a/mm/2s2h/Enhancements/GfxPatcher/AuthenticGfxPatches.cpp b/mm/2s2h/Enhancements/GfxPatcher/AuthenticGfxPatches.cpp new file mode 100644 index 000000000..affb2d894 --- /dev/null +++ b/mm/2s2h/Enhancements/GfxPatcher/AuthenticGfxPatches.cpp @@ -0,0 +1,51 @@ +#include "AuthenticGfxPatches.h" + +extern "C" { +#include +#include "objects/object_uch/object_uch.h" +#include "overlays/ovl_En_Syateki_Okuta/ovl_En_Syateki_Okuta.h" + +void ResourceMgr_PatchGfxByName(const char* path, const char* patchName, int index, Gfx instruction); +void ResourceMgr_UnpatchGfxByName(const char* path, const char* patchName); +Gfx* ResourceMgr_LoadGfxByName(const char* path); +} + +void PatchAlienEyeBeams() { + // A bug in the Alien's eye beam DL is incorrectly referring to TEXEL1 in the color combiner when + // the texture is loaded into TEXEL0, causing the CC rendering whatever was last loaded into TEXEL1. + // Patching the instruction to TEXEL0 restores the effect as seen on hardware. + ResourceMgr_PatchGfxByName(gAlienEyeBeamDL, "AlienEyeBeamFix", 4, + gsDPSetCombineLERP(NOISE, 0, PRIMITIVE, 0, 0, 0, 0, ENVIRONMENT, COMBINED, 0, + PRIMITIVE_ALPHA, PRIMITIVE, COMBINED, 0, TEXEL0, 0)); +} + +void PatchShootingGalleryOctorokSymbols() { + // The X and O displayed in the shooting gallery when hit are incorrectly set to FMT_I instead of FMT_IA, + // Fast3D throws an assert and does nothing as FMT_I with SIZ_16 is not a valid texture type. + // Patching all the relevant instructions to use FMT_IA matching the exported texture + const char* dLists[] = { gShootingGalleryOctorokCrossDL, gShootingGalleryOctorokCircleDL }; + + for (auto& dl : dLists) { + Gfx* instructions = ResourceMgr_LoadGfxByName(dl); + + // Use a mask to unset and set the new format while preserving the rest of the instruction + const uintptr_t mask = UINTPTR_MAX ^ (_SHIFTL(7, 21, 3)); + + Gfx in3 = instructions[3]; // G_SETTIMG_OTR_HAS + in3.words.w0 = (in3.words.w0 & mask) | _SHIFTL(G_IM_FMT_IA, 21, 3); + Gfx in5 = instructions[5]; // G_SETTILE + in5.words.w0 = (in5.words.w0 & mask) | _SHIFTL(G_IM_FMT_IA, 21, 3); + Gfx in9 = instructions[9]; // G_SETTILE + in9.words.w0 = (in9.words.w0 & mask) | _SHIFTL(G_IM_FMT_IA, 21, 3); + + ResourceMgr_PatchGfxByName(dl, "ShootingGalleryHitFix_3", 3, in3); + ResourceMgr_PatchGfxByName(dl, "ShootingGalleryHitFix_5", 5, in5); + ResourceMgr_PatchGfxByName(dl, "ShootingGalleryHitFix_9", 9, in9); + } +} + +// Applies required patches for authentic bugs to allow the game to play and render properly +void GfxPatcher_ApplyNecessaryAuthenticPatches() { + PatchAlienEyeBeams(); + PatchShootingGalleryOctorokSymbols(); +} diff --git a/mm/2s2h/Enhancements/GfxPatcher/AuthenticGfxPatches.h b/mm/2s2h/Enhancements/GfxPatcher/AuthenticGfxPatches.h new file mode 100644 index 000000000..1a9c8b224 --- /dev/null +++ b/mm/2s2h/Enhancements/GfxPatcher/AuthenticGfxPatches.h @@ -0,0 +1,6 @@ +#ifndef AUTHENTIC_GFX_PATCHES_H +#define AUTHENTIC_GFX_PATCHES_H + +void GfxPatcher_ApplyNecessaryAuthenticPatches(); + +#endif // AUTHENTIC_GFX_PATCHES_H