Fix unhandled opcode crash with authentic gfx patches (#5206)

This commit is contained in:
Archez 2025-03-24 21:27:38 -04:00 committed by GitHub
commit 5bf1dc8285
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -18,7 +18,7 @@ typedef struct {
int startInstruction; int startInstruction;
} DListPatchInfo; } DListPatchInfo;
static DListPatchInfo freezardEffectDListPatchInfos[] = { static DListPatchInfo freezardBodyDListPatchInfos[] = {
{ gFreezardIntactDL, 5 }, { gFreezardIntactDL, 5 },
{ gFreezardTopRightHornChippedDL, 5 }, { gFreezardTopRightHornChippedDL, 5 },
{ gFreezardHeadChippedDL, 5 }, { gFreezardHeadChippedDL, 5 },
@ -67,76 +67,97 @@ static DListPatchInfo ironKnuckleDListPatchInfos[] = {
void PatchDekuStickTextureOverflow() { void PatchDekuStickTextureOverflow() {
// Custom texture for holding Deku Stick that accounts for overflow texture reading // Custom texture for holding Deku Stick that accounts for overflow texture reading
Gfx gDekuStickOverflowTexFix = gsDPSetTextureImage(G_IM_FMT_I, G_IM_SIZ_8b, 1, gDekuStickOverflowTex); Gfx dekuSticTexkWithOverflowFixGfx = gsDPSetTextureImage(G_IM_FMT_I, G_IM_SIZ_8b, 1, gDekuStickOverflowTex);
// Gfx instructions to fix authentic vanilla bug where the Deku Stick texture is read as the wrong size // Gfx instructions to fix authentic vanilla bug where the Deku Stick texture is read as the wrong size
Gfx gDekuStickTexFix[] = { Gfx dekuStickTexWithSizeFixGfx[] = {
gsDPLoadTextureBlock(gDekuStickTex, G_IM_FMT_I, G_IM_SIZ_8b, 8, 8, 0, G_TX_NOMIRROR | G_TX_WRAP, gsDPLoadTextureBlock(gDekuStickTex, G_IM_FMT_I, G_IM_SIZ_8b, 8, 8, 0, G_TX_NOMIRROR | G_TX_WRAP,
G_TX_NOMIRROR | G_TX_WRAP, 4, 4, G_TX_NOLOD, G_TX_NOLOD) G_TX_NOMIRROR | G_TX_WRAP, 4, 4, G_TX_NOLOD, G_TX_NOLOD),
}; };
const char* dlist = gLinkChildLinkDekuStickDL; const char* dlist = gLinkChildLinkDekuStickDL;
int start = 5; int start = 5;
// Patch using custom overflowed texture
if (!CVarGetInteger(CVAR_ENHANCEMENT("FixTexturesOOB"), 0)) { if (!CVarGetInteger(CVAR_ENHANCEMENT("FixTexturesOOB"), 0)) {
// Unpatch the other texture fix // Unpatch the other texture fix
for (size_t i = 0; i < 7; i++) { for (size_t i = 0; i < 8; i++) {
int instruction = start + (i == 0 ? 0 : i + 1); int instruction = start + i;
std::string unpatchName = "DekuStickFix" + std::to_string(instruction); std::string unpatchName = "dekuStickWithSizeFix_" + std::to_string(instruction);
ResourceMgr_UnpatchGfxByName(dlist, unpatchName.c_str()); ResourceMgr_UnpatchGfxByName(dlist, unpatchName.c_str());
} }
std::string patchName = "DekuStickOverflow" + std::to_string(start); std::string patchName = "dekuStickWithOverflowFix_" + std::to_string(start);
ResourceMgr_PatchGfxByName(dlist, patchName.c_str(), start, gDekuStickOverflowTexFix); std::string patchName2 = "dekuStickWithOverflowFix_" + std::to_string(start + 1);
} else { ResourceMgr_PatchGfxByName(dlist, patchName.c_str(), start, dekuSticTexkWithOverflowFixGfx);
ResourceMgr_PatchGfxByName(dlist, patchName2.c_str(), start + 1, gsSPNoOp());
} else { // Patch texture to use correct image size/fmt
// Unpatch the other texture fix // Unpatch the other texture fix
std::string unpatchName = "DekuStickOverflow" + std::to_string(start); std::string unpatchName = "dekuStickWithOverflowFix_" + std::to_string(start);
std::string unpatchName2 = "dekuStickWithOverflowFix_" + std::to_string(start + 1);
ResourceMgr_UnpatchGfxByName(dlist, unpatchName.c_str()); ResourceMgr_UnpatchGfxByName(dlist, unpatchName.c_str());
ResourceMgr_UnpatchGfxByName(dlist, unpatchName2.c_str());
for (size_t i = 0; i < 7; i++) {
int instruction = start + (i == 0 ? 0 : i + 1); for (size_t i = 0; i < 8; i++) {
std::string patchName = "DekuStickFix" + std::to_string(instruction); int instruction = start + i;
ResourceMgr_PatchGfxByName(dlist, patchName.c_str(), instruction, gDekuStickTexFix[i]); std::string patchName = "dekuStickWithSizeFix_" + std::to_string(instruction);
if (i == 0) {
ResourceMgr_PatchGfxByName(dlist, patchName.c_str(), instruction, gsSPNoOp());
} else {
ResourceMgr_PatchGfxByName(dlist, patchName.c_str(), instruction, dekuStickTexWithSizeFixGfx[i - 1]);
}
} }
} }
} }
void PatchFreezardTextureOverflow() { void PatchFreezardTextureOverflow() {
// Custom texture for Freezard effect that accounts for overflow texture reading // Custom texture for Freezard effect that accounts for overflow texture reading
Gfx gEffUnknown12OverflowTextFix = gsDPSetTextureImage(G_IM_FMT_IA, G_IM_SIZ_16b, 1, gEffUnknown12OverflowTex); Gfx freezardBodyTextureWithOverflowFixGfx =
gsDPSetTextureImage(G_IM_FMT_IA, G_IM_SIZ_16b, 1, gEffUnknown12OverflowTex);
// Gfx instructions to fix authentic vanilla bug where the Freezard effect texture is read as the wrong format // Gfx instructions to fix authentic vanilla bug where the Freezard effect texture is read as the wrong format
Gfx gEffUnknown12TexFix[] = { Gfx freezardBodyTextureWithFormatFixGfx[] = {
gsDPLoadTextureBlock(gEffUnknown12Tex, G_IM_FMT_I, G_IM_SIZ_8b, 32, 32, 0, G_TX_NOMIRROR | gsDPLoadTextureBlock(gEffUnknown12Tex, G_IM_FMT_I, G_IM_SIZ_8b, 32, 32, 0, G_TX_NOMIRROR | G_TX_WRAP,
G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, 5, 5, G_TX_NOLOD, G_TX_NOLOD) G_TX_NOMIRROR | G_TX_WRAP, 5, 5, G_TX_NOLOD, G_TX_NOLOD),
}; };
for (const auto& patchInfo : freezardEffectDListPatchInfos) { bool fixTexturesOOB = CVarGetInteger(CVAR_ENHANCEMENT("FixTexturesOOB"), 0);
for (const auto& patchInfo : freezardBodyDListPatchInfos) {
const char* dlist = patchInfo.dlist; const char* dlist = patchInfo.dlist;
int start = patchInfo.startInstruction; int start = patchInfo.startInstruction;
char patchNameBuf[24];
// Patch using custom overflowed texture // Patch using custom overflowed texture
if (!CVarGetInteger(CVAR_ENHANCEMENT("FixTexturesOOB"), 0)) { if (!fixTexturesOOB) {
// Unpatch the other texture fix // Unpatch the other texture fix
for (size_t i = 0; i < 7; i++) { for (size_t i = 0; i < 8; i++) {
int instruction = start + (i == 0 ? 0 : i + 1); int instruction = start + i;
std::string unpatchName = "gEffUnknown12Fix" + std::to_string(instruction); std::string unpatchName = "freezardBodyTextureWithFormatFix_" + std::to_string(instruction);
ResourceMgr_UnpatchGfxByName(dlist, unpatchName.c_str()); ResourceMgr_UnpatchGfxByName(dlist, unpatchName.c_str());
} }
std::string patchName = "gEffUnknown12Overflow" + std::to_string(start); std::string patchName = "freezardBodyTextureWithOverflowFix_" + std::to_string(start);
ResourceMgr_PatchGfxByName(dlist, patchName.c_str(), start, gEffUnknown12OverflowTextFix); std::string patchName2 = "freezardBodyTextureWithOverflowFix_" + std::to_string(start + 1);
} else { // Patch texture to use correct image size ResourceMgr_PatchGfxByName(dlist, patchName.c_str(), start, freezardBodyTextureWithOverflowFixGfx);
ResourceMgr_PatchGfxByName(dlist, patchName2.c_str(), start + 1, gsSPNoOp());
} else { // Patch texture to use correct image size/fmt
// Unpatch the other texture fix // Unpatch the other texture fix
std::string unpatchName = "gEffUnknown12Overflow" + std::to_string(start); std::string unpatchName = "freezardBodyTextureWithOverflowFix_" + std::to_string(start);
std::string unpatchName2 = "freezardBodyTextureWithOverflowFix_" + std::to_string(start + 1);
ResourceMgr_UnpatchGfxByName(dlist, unpatchName.c_str()); ResourceMgr_UnpatchGfxByName(dlist, unpatchName.c_str());
ResourceMgr_UnpatchGfxByName(dlist, unpatchName2.c_str());
for (size_t i = 0; i < 7; i++) { for (size_t i = 0; i < 8; i++) {
int instruction = start + (i == 0 ? 0 : i + 1); int instruction = start + i;
std::string patchName = "gEffUnknown12Fix" + std::to_string(instruction); std::string patchName = "freezardBodyTextureWithFormatFix_" + std::to_string(instruction);
ResourceMgr_PatchGfxByName(dlist, patchName.c_str(), instruction, gEffUnknown12TexFix[i]);
if (i == 0) {
ResourceMgr_PatchGfxByName(dlist, patchName.c_str(), instruction, gsSPNoOp());
} else {
ResourceMgr_PatchGfxByName(dlist, patchName.c_str(), instruction,
freezardBodyTextureWithFormatFixGfx[i - 1]);
}
} }
} }
} }
@ -144,44 +165,53 @@ void PatchFreezardTextureOverflow() {
void PatchIronKnuckleTextureOverflow() { void PatchIronKnuckleTextureOverflow() {
// Custom texture for Iron Knuckle that accounts for overflow texture reading // Custom texture for Iron Knuckle that accounts for overflow texture reading
Gfx gIronKnuckleMetalOverflowTexFix = gsDPSetTextureImage(G_IM_FMT_I, G_IM_SIZ_8b, 1, gIronKnuckleMetalOverflowTex); Gfx ironKnuckleFireTexWithOverflowFixGfx =
gsDPSetTextureImage(G_IM_FMT_I, G_IM_SIZ_8b, 1, gIronKnuckleMetalOverflowTex);
// Gfx instructions to fix authentic vanilla bug where the Iron Knuckle texture is read as the wrong format // Gfx instructions to fix authentic vanilla bug where the Iron Knuckle texture is read as the wrong format
Gfx gIronKnuckleMetalTexFix[] = { Gfx ironKnuckleFireTexWithFormatFixGfx[] = {
gsDPLoadTextureBlock(gIronKnuckleMetalTex, G_IM_FMT_I, G_IM_SIZ_4b, 32, 64, 0, G_TX_MIRROR | G_TX_WRAP, gsDPLoadTextureBlock_4b(gIronKnuckleMetalTex, G_IM_FMT_I, 32, 64, 0, G_TX_MIRROR | G_TX_WRAP,
G_TX_MIRROR | G_TX_WRAP, 5, 6, G_TX_NOLOD, G_TX_NOLOD) G_TX_MIRROR | G_TX_WRAP, 5, 6, G_TX_NOLOD, G_TX_NOLOD),
}; };
bool fixTexturesOOB = CVarGetInteger(CVAR_ENHANCEMENT("FixTexturesOOB"), 0);
for (const auto& patchInfo : ironKnuckleDListPatchInfos) { for (const auto& patchInfo : ironKnuckleDListPatchInfos) {
const char* dlist = patchInfo.dlist; const char* dlist = patchInfo.dlist;
int start = patchInfo.startInstruction; int start = patchInfo.startInstruction;
// OTRTODO: Patching to use the correct size format for Iron Knuckle causes a tile size failure
// Until this is solved, Iron Knuckle will be hardcoded to always display with the "authentic" texture fix
// Patch using custom overflowed texture // Patch using custom overflowed texture
// if (!CVarGetInteger(CVAR_ENHANCEMENT("FixTexturesOOB"), 0)) { if (!fixTexturesOOB) {
// Unpatch the other texture fix // Unpatch the other texture fix
for (size_t i = 0; i < 7; i++) { for (size_t i = 0; i < 8; i++) {
int instruction = start + (i == 0 ? 0 : i + 1); int instruction = start + i;
std::string unpatchName = "MetalTexFix" + std::to_string(instruction); std::string unpatchName = "ironKnuckleFireTexWithSizeFix_" + std::to_string(instruction);
ResourceMgr_UnpatchGfxByName(dlist, unpatchName.c_str()); ResourceMgr_UnpatchGfxByName(dlist, unpatchName.c_str());
} }
std::string patchName = "MetalTexOverflow" + std::to_string(start); std::string patchName = "ironKnuckleFireTexWithOverflowFix_" + std::to_string(start);
ResourceMgr_PatchGfxByName(dlist, patchName.c_str(), start, gIronKnuckleMetalOverflowTexFix); std::string patchName2 = "ironKnuckleFireTexWithOverflowFix_" + std::to_string(start + 1);
// } else { // Patch texture to use correct image size ResourceMgr_PatchGfxByName(dlist, patchName.c_str(), start, ironKnuckleFireTexWithOverflowFixGfx);
// // Unpatch the other texture fix ResourceMgr_PatchGfxByName(dlist, patchName2.c_str(), start + 1, ironKnuckleFireTexWithOverflowFixGfx);
// std::string unpatchName = "MetalTexOverflow" + std::to_string(start); } else { // Patch texture to use correct image size/fmt
// ResourceMgr_UnpatchGfxByName(dlist, unpatchName.c_str()); // Unpatch the other texture fix
std::string unpatchName = "ironKnuckleFireTexWithOverflowFix_" + std::to_string(start);
std::string unpatchName2 = "ironKnuckleFireTexWithOverflowFix_" + std::to_string(start + 1);
ResourceMgr_UnpatchGfxByName(dlist, unpatchName.c_str());
ResourceMgr_UnpatchGfxByName(dlist, unpatchName2.c_str());
// // Patch texture to use correct image size for (size_t i = 0; i < 8; i++) {
// for (size_t i = 0; i < 7; i++) { int instruction = start + i;
// int instruction = start + (i == 0 ? 0 : i + 1); std::string patchName = "ironKnuckleFireTexWithSizeFix_" + std::to_string(instruction);
// std::string patchName = "MetalTexFix" + std::to_string(instruction);
// ResourceMgr_PatchGfxByName(dlist, patchName.c_str(), instruction, gIronKnuckleMetalTexFix[i]); if (i == 0) {
// } ResourceMgr_PatchGfxByName(dlist, patchName.c_str(), instruction, gsSPNoOp());
// } } else {
ResourceMgr_PatchGfxByName(dlist, patchName.c_str(), instruction,
ironKnuckleFireTexWithFormatFixGfx[i - 1]);
}
}
}
} }
} }