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;
} DListPatchInfo;
static DListPatchInfo freezardEffectDListPatchInfos[] = {
static DListPatchInfo freezardBodyDListPatchInfos[] = {
{ gFreezardIntactDL, 5 },
{ gFreezardTopRightHornChippedDL, 5 },
{ gFreezardHeadChippedDL, 5 },
@ -67,76 +67,97 @@ static DListPatchInfo ironKnuckleDListPatchInfos[] = {
void PatchDekuStickTextureOverflow() {
// 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 gDekuStickTexFix[] = {
Gfx dekuStickTexWithSizeFixGfx[] = {
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;
int start = 5;
// Patch using custom overflowed texture
if (!CVarGetInteger(CVAR_ENHANCEMENT("FixTexturesOOB"), 0)) {
// Unpatch the other texture fix
for (size_t i = 0; i < 7; i++) {
int instruction = start + (i == 0 ? 0 : i + 1);
std::string unpatchName = "DekuStickFix" + std::to_string(instruction);
for (size_t i = 0; i < 8; i++) {
int instruction = start + i;
std::string unpatchName = "dekuStickWithSizeFix_" + std::to_string(instruction);
ResourceMgr_UnpatchGfxByName(dlist, unpatchName.c_str());
}
std::string patchName = "DekuStickOverflow" + std::to_string(start);
ResourceMgr_PatchGfxByName(dlist, patchName.c_str(), start, gDekuStickOverflowTexFix);
} else {
std::string patchName = "dekuStickWithOverflowFix_" + std::to_string(start);
std::string patchName2 = "dekuStickWithOverflowFix_" + std::to_string(start + 1);
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
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());
for (size_t i = 0; i < 7; i++) {
int instruction = start + (i == 0 ? 0 : i + 1);
std::string patchName = "DekuStickFix" + std::to_string(instruction);
ResourceMgr_PatchGfxByName(dlist, patchName.c_str(), instruction, gDekuStickTexFix[i]);
ResourceMgr_UnpatchGfxByName(dlist, unpatchName2.c_str());
for (size_t i = 0; i < 8; i++) {
int instruction = start + 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() {
// 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 gEffUnknown12TexFix[] = {
gsDPLoadTextureBlock(gEffUnknown12Tex, G_IM_FMT_I, G_IM_SIZ_8b, 32, 32, 0, G_TX_NOMIRROR |
G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, 5, 5, G_TX_NOLOD, G_TX_NOLOD)
Gfx freezardBodyTextureWithFormatFixGfx[] = {
gsDPLoadTextureBlock(gEffUnknown12Tex, G_IM_FMT_I, G_IM_SIZ_8b, 32, 32, 0, G_TX_NOMIRROR | G_TX_WRAP,
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;
int start = patchInfo.startInstruction;
char patchNameBuf[24];
// Patch using custom overflowed texture
if (!CVarGetInteger(CVAR_ENHANCEMENT("FixTexturesOOB"), 0)) {
if (!fixTexturesOOB) {
// Unpatch the other texture fix
for (size_t i = 0; i < 7; i++) {
int instruction = start + (i == 0 ? 0 : i + 1);
std::string unpatchName = "gEffUnknown12Fix" + std::to_string(instruction);
for (size_t i = 0; i < 8; i++) {
int instruction = start + i;
std::string unpatchName = "freezardBodyTextureWithFormatFix_" + std::to_string(instruction);
ResourceMgr_UnpatchGfxByName(dlist, unpatchName.c_str());
}
std::string patchName = "gEffUnknown12Overflow" + std::to_string(start);
ResourceMgr_PatchGfxByName(dlist, patchName.c_str(), start, gEffUnknown12OverflowTextFix);
} else { // Patch texture to use correct image size
std::string patchName = "freezardBodyTextureWithOverflowFix_" + std::to_string(start);
std::string patchName2 = "freezardBodyTextureWithOverflowFix_" + std::to_string(start + 1);
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
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, unpatchName2.c_str());
for (size_t i = 0; i < 7; i++) {
int instruction = start + (i == 0 ? 0 : i + 1);
std::string patchName = "gEffUnknown12Fix" + std::to_string(instruction);
ResourceMgr_PatchGfxByName(dlist, patchName.c_str(), instruction, gEffUnknown12TexFix[i]);
for (size_t i = 0; i < 8; i++) {
int instruction = start + i;
std::string patchName = "freezardBodyTextureWithFormatFix_" + std::to_string(instruction);
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() {
// 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 gIronKnuckleMetalTexFix[] = {
gsDPLoadTextureBlock(gIronKnuckleMetalTex, G_IM_FMT_I, G_IM_SIZ_4b, 32, 64, 0, G_TX_MIRROR | G_TX_WRAP,
G_TX_MIRROR | G_TX_WRAP, 5, 6, G_TX_NOLOD, G_TX_NOLOD)
Gfx ironKnuckleFireTexWithFormatFixGfx[] = {
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),
};
bool fixTexturesOOB = CVarGetInteger(CVAR_ENHANCEMENT("FixTexturesOOB"), 0);
for (const auto& patchInfo : ironKnuckleDListPatchInfos) {
const char* dlist = patchInfo.dlist;
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
// if (!CVarGetInteger(CVAR_ENHANCEMENT("FixTexturesOOB"), 0)) {
if (!fixTexturesOOB) {
// Unpatch the other texture fix
for (size_t i = 0; i < 7; i++) {
int instruction = start + (i == 0 ? 0 : i + 1);
std::string unpatchName = "MetalTexFix" + std::to_string(instruction);
for (size_t i = 0; i < 8; i++) {
int instruction = start + i;
std::string unpatchName = "ironKnuckleFireTexWithSizeFix_" + std::to_string(instruction);
ResourceMgr_UnpatchGfxByName(dlist, unpatchName.c_str());
}
std::string patchName = "MetalTexOverflow" + std::to_string(start);
ResourceMgr_PatchGfxByName(dlist, patchName.c_str(), start, gIronKnuckleMetalOverflowTexFix);
// } else { // Patch texture to use correct image size
// // Unpatch the other texture fix
// std::string unpatchName = "MetalTexOverflow" + std::to_string(start);
// ResourceMgr_UnpatchGfxByName(dlist, unpatchName.c_str());
std::string patchName = "ironKnuckleFireTexWithOverflowFix_" + std::to_string(start);
std::string patchName2 = "ironKnuckleFireTexWithOverflowFix_" + std::to_string(start + 1);
ResourceMgr_PatchGfxByName(dlist, patchName.c_str(), start, ironKnuckleFireTexWithOverflowFixGfx);
ResourceMgr_PatchGfxByName(dlist, patchName2.c_str(), start + 1, ironKnuckleFireTexWithOverflowFixGfx);
} else { // Patch texture to use correct image size/fmt
// 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 < 7; i++) {
// int instruction = start + (i == 0 ? 0 : i + 1);
// std::string patchName = "MetalTexFix" + std::to_string(instruction);
// ResourceMgr_PatchGfxByName(dlist, patchName.c_str(), instruction, gIronKnuckleMetalTexFix[i]);
// }
// }
for (size_t i = 0; i < 8; i++) {
int instruction = start + i;
std::string patchName = "ironKnuckleFireTexWithSizeFix_" + std::to_string(instruction);
if (i == 0) {
ResourceMgr_PatchGfxByName(dlist, patchName.c_str(), instruction, gsSPNoOp());
} else {
ResourceMgr_PatchGfxByName(dlist, patchName.c_str(), instruction,
ironKnuckleFireTexWithFormatFixGfx[i - 1]);
}
}
}
}
}