Implement patches for authentic texture overflows (#2737)

* implement dlist patching for authentic texture overflows

* add overflow patch to deku stick; move toggle
This commit is contained in:
Adam Bird 2023-04-23 19:42:59 -04:00 committed by GitHub
parent 5324dfae67
commit d0041d28ea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 246 additions and 0 deletions

View File

@ -20,6 +20,9 @@ static const ALIGN_ASSET(2) char gBottleGlassTex[] = dgBottleGlassTex;
#define dgDekuStickTex "__OTR__objects/gameplay_keep/gDekuStickTex"
static const ALIGN_ASSET(2) char gDekuStickTex[] = dgDekuStickTex;
#define dgDekuStickOverflowTex "__OTR__objects/gameplay_keep/gDekuStickOverflowTex"
static const ALIGN_ASSET(2) char gDekuStickOverflowTex[] = dgDekuStickOverflowTex;
#define dgLinkHairTex "__OTR__objects/gameplay_keep/gLinkHairTex"
static const ALIGN_ASSET(2) char gLinkHairTex[] = dgLinkHairTex;
@ -2375,6 +2378,9 @@ static const ALIGN_ASSET(2) char gEffUnknown11Tex[] = dgEffUnknown11Tex;
#define dgEffUnknown12Tex "__OTR__objects/gameplay_keep/gEffUnknown12Tex"
static const ALIGN_ASSET(2) char gEffUnknown12Tex[] = dgEffUnknown12Tex;
#define dgEffUnknown12OverflowTex "__OTR__objects/gameplay_keep/gEffUnknown12OverflowTex"
static const ALIGN_ASSET(2) char gEffUnknown12OverflowTex[] = dgEffUnknown12OverflowTex;
#define dgUnknownWoodBoardTex "__OTR__objects/gameplay_keep/gUnknownWoodBoardTex"
static const ALIGN_ASSET(2) char gUnknownWoodBoardTex[] = dgUnknownWoodBoardTex;

View File

@ -101,6 +101,9 @@ static const ALIGN_ASSET(2) char object_ik_Tlut_00F630[] = dobject_ik_Tlut_00F63
#define dobject_ik_Tex_00F7A0 "__OTR__objects/object_ik/object_ik_Tex_00F7A0"
static const ALIGN_ASSET(2) char object_ik_Tex_00F7A0[] = dobject_ik_Tex_00F7A0;
#define dgIronKnuckleMetalOverflowTex "__OTR__objects/object_ik/gIronKnuckleMetalOverflowTex"
static const ALIGN_ASSET(2) char gIronKnuckleMetalOverflowTex[] = dgIronKnuckleMetalOverflowTex;
#define dobject_ik_Tex_00FBA0 "__OTR__objects/object_ik/object_ik_Tex_00FBA0"
static const ALIGN_ASSET(2) char object_ik_Tex_00FBA0[] = dobject_ik_Tex_00FBA0;

View File

@ -7,6 +7,10 @@
<Texture Name="gOcarinaofTimeDesignTex" OutName="ocarina_of_time_design" Format="rgba16" Width="32" Height="16" Offset="0x1400"/>
<Texture Name="gBottleGlassTex" OutName="bottle_glass" Format="rgba16" Width="16" Height="16" Offset="0x1800"/>
<Texture Name="gDekuStickTex" OutName="deku_stick" Format="i8" Width="16" Height="16" Offset="0x1A00"/>
<!-- This is a duplicate texture to accound for authentic texture overflowing -->
<!-- ZAPDTODO: It is set to an offset position -1 of the actual value as ZAPD does not permit
duplicate offset values -->
<Texture Name="gDekuStickOverflowTex" OutName="deku_stick_overflow" Format="i8" Width="16" Height="16" Offset="0x19FF"/>
<Texture Name="gLinkHairTex" OutName="link_hair" Format="rgba16" Width="16" Height="16" Offset="0x1A40"/>
<Texture Name="gLinkTunic1Tex" OutName="link_tunic_1" Format="i8" Width="16" Height="16" Offset="0x1C40"/>
<Texture Name="gLinkTunic2Tex" OutName="link_tunic_2" Format="i8" Width="16" Height="32" Offset="0x1D40"/>
@ -809,6 +813,10 @@
<Texture Name="gEffUnknown10Tex" OutName="eff_unknown_10" Format="i8" Width="32" Height="32" Offset="0x32490"/>
<Texture Name="gEffUnknown11Tex" OutName="eff_unknown_11" Format="i8" Width="32" Height="32" Offset="0x32890"/>
<Texture Name="gEffUnknown12Tex" OutName="eff_unknown_12" Format="i8" Width="32" Height="32" Offset="0x32C90"/>
<!-- This is a duplicate texture to accound for authentic texture overflowing -->
<!-- ZAPDTODO: It is set to an offset position -2 of the actual value as ZAPD does not permit
duplicate offset values -->
<Texture Name="gEffUnknown12OverflowTex" OutName="eff_unknown_12_overflow" Format="ia16" Width="32" Height="32" Offset="0x32C8E"/>
<Texture Name="gUnknownWoodBoardTex" OutName="unknown_wood_board" Format="i8" Width="32" Height="32" Offset="0x33090"/>
<DList Name="gEffIceFragment1DL" Offset="0x33720"/>
<DList Name="gEffIceFragment2DL" Offset="0x33818"/>

View File

@ -38,6 +38,10 @@
<Texture Name="object_ik_Tlut_00F630" OutName="tlut_00F630" Format="rgba16" Width="23" Height="8" Offset="0xf630"/>
<Texture Name="object_ik_Tex_00F7A0" OutName="tex_00F7A0" Format="i4" Width="32" Height="64" Offset="0xF7A0"/>
<!-- This is a duplicate texture to accound for authentic texture overflowing -->
<!-- ZAPDTODO: It is set to an offset position -1 of the actual value as ZAPD does not permit
duplicate offset values -->
<Texture Name="gIronKnuckleMetalOverflowTex" OutName="iron_knuckle_metal_overflow_tex" Format="i8" Width="32" Height="64" Offset="0xF79F"/>
<Texture Name="object_ik_Tex_00FBA0" OutName="tex_00FBA0" Format="ia8" Width="32" Height="32" Offset="0xFBA0"/>
<Texture Name="object_ik_Tex_00FFA0" OutName="tex_00FFA0" Format="rgba16" Width="16" Height="16" Offset="0xFFA0"/>
<Texture Name="object_ik_Tex_0101A0" OutName="tex_0101A0" Format="rgba16" Width="16" Height="16" Offset="0x101A0"/>

View File

@ -7,6 +7,10 @@
<Texture Name="gOcarinaofTimeDesignTex" OutName="ocarina_of_time_design" Format="rgba16" Width="32" Height="16" Offset="0x1400"/>
<Texture Name="gBottleGlassTex" OutName="bottle_glass" Format="rgba16" Width="16" Height="16" Offset="0x1800"/>
<Texture Name="gDekuStickTex" OutName="deku_stick" Format="i8" Width="16" Height="16" Offset="0x1A00"/>
<!-- This is a duplicate texture to accound for authentic texture overflowing -->
<!-- ZAPDTODO: It is set to an offset position -1 of the actual value as ZAPD does not permit
duplicate offset values -->
<Texture Name="gDekuStickOverflowTex" OutName="deku_stick_overflow" Format="i8" Width="16" Height="16" Offset="0x19FF"/>
<Texture Name="gLinkHairTex" OutName="link_hair" Format="rgba16" Width="16" Height="16" Offset="0x1A40"/>
<Texture Name="gLinkTunic1Tex" OutName="link_tunic_1" Format="i8" Width="16" Height="16" Offset="0x1C40"/>
<Texture Name="gLinkTunic2Tex" OutName="link_tunic_2" Format="i8" Width="16" Height="32" Offset="0x1D40"/>
@ -806,6 +810,10 @@
<Texture Name="gEffUnknown10Tex" OutName="eff_unknown_10" Format="i8" Width="32" Height="32" Offset="0x32490"/>
<Texture Name="gEffUnknown11Tex" OutName="eff_unknown_11" Format="i8" Width="32" Height="32" Offset="0x32890"/>
<Texture Name="gEffUnknown12Tex" OutName="eff_unknown_12" Format="i8" Width="32" Height="32" Offset="0x32C90"/>
<!-- This is a duplicate texture to accound for authentic texture overflowing -->
<!-- ZAPDTODO: It is set to an offset position -2 of the actual value as ZAPD does not permit
duplicate offset values -->
<Texture Name="gEffUnknown12OverflowTex" OutName="eff_unknown_12_overflow" Format="ia16" Width="32" Height="32" Offset="0x32C8E"/>
<Texture Name="gUnknownWoodBoardTex" OutName="unknown_wood_board" Format="i8" Width="32" Height="32" Offset="0x33090"/>
<DList Name="gEffIceFragment1DL" Offset="0x33720"/>
<DList Name="gEffIceFragment2DL" Offset="0x33818"/>

View File

@ -38,6 +38,10 @@
<Texture Name="object_ik_Tlut_00F630" OutName="tlut_00F630" Format="rgba16" Width="23" Height="8" Offset="0xf630"/>
<Texture Name="object_ik_Tex_00F7A0" OutName="tex_00F7A0" Format="i4" Width="32" Height="64" Offset="0xF7A0"/>
<!-- This is a duplicate texture to accound for authentic texture overflowing -->
<!-- ZAPDTODO: It is set to an offset position -1 of the actual value as ZAPD does not permit
duplicate offset values -->
<Texture Name="gIronKnuckleMetalOverflowTex" OutName="iron_knuckle_metal_overflow_tex" Format="i8" Width="32" Height="64" Offset="0xF79F"/>
<Texture Name="object_ik_Tex_00FBA0" OutName="tex_00FBA0" Format="ia8" Width="32" Height="32" Offset="0xFBA0"/>
<Texture Name="object_ik_Tex_00FFA0" OutName="tex_00FFA0" Format="rgba16" Width="16" Height="16" Offset="0xFFA0"/>
<Texture Name="object_ik_Tex_0101A0" OutName="tex_0101A0" Format="rgba16" Width="16" Height="16" Offset="0x101A0"/>

View File

@ -7,6 +7,10 @@
<Texture Name="gOcarinaofTimeDesignTex" OutName="ocarina_of_time_design" Format="rgba16" Width="32" Height="16" Offset="0x1400"/>
<Texture Name="gBottleGlassTex" OutName="bottle_glass" Format="rgba16" Width="16" Height="16" Offset="0x1800"/>
<Texture Name="gDekuStickTex" OutName="deku_stick" Format="i8" Width="16" Height="16" Offset="0x1A00"/>
<!-- This is a duplicate texture to accound for authentic texture overflowing -->
<!-- ZAPDTODO: It is set to an offset position -1 of the actual value as ZAPD does not permit
duplicate offset values -->
<Texture Name="gDekuStickOverflowTex" OutName="deku_stick_overflow" Format="i8" Width="16" Height="16" Offset="0x19FF"/>
<Texture Name="gLinkHairTex" OutName="link_hair" Format="rgba16" Width="16" Height="16" Offset="0x1A40"/>
<Texture Name="gLinkTunic1Tex" OutName="link_tunic_1" Format="i8" Width="16" Height="16" Offset="0x1C40"/>
<Texture Name="gLinkTunic2Tex" OutName="link_tunic_2" Format="i8" Width="16" Height="32" Offset="0x1D40"/>
@ -806,6 +810,10 @@
<Texture Name="gEffUnknown10Tex" OutName="eff_unknown_10" Format="i8" Width="32" Height="32" Offset="0x32490"/>
<Texture Name="gEffUnknown11Tex" OutName="eff_unknown_11" Format="i8" Width="32" Height="32" Offset="0x32890"/>
<Texture Name="gEffUnknown12Tex" OutName="eff_unknown_12" Format="i8" Width="32" Height="32" Offset="0x32C90"/>
<!-- This is a duplicate texture to accound for authentic texture overflowing -->
<!-- ZAPDTODO: It is set to an offset position -2 of the actual value as ZAPD does not permit
duplicate offset values -->
<Texture Name="gEffUnknown12OverflowTex" OutName="eff_unknown_12_overflow" Format="ia16" Width="32" Height="32" Offset="0x32C8E"/>
<Texture Name="gUnknownWoodBoardTex" OutName="unknown_wood_board" Format="i8" Width="32" Height="32" Offset="0x33090"/>
<DList Name="gEffIceFragment1DL" Offset="0x33720"/>
<DList Name="gEffIceFragment2DL" Offset="0x33818"/>

View File

@ -38,6 +38,10 @@
<Texture Name="object_ik_Tlut_00F630" OutName="tlut_00F630" Format="rgba16" Width="23" Height="8" Offset="0xf630"/>
<Texture Name="object_ik_Tex_00F7A0" OutName="tex_00F7A0" Format="i4" Width="32" Height="64" Offset="0xF7A0"/>
<!-- This is a duplicate texture to accound for authentic texture overflowing -->
<!-- ZAPDTODO: It is set to an offset position -1 of the actual value as ZAPD does not permit
duplicate offset values -->
<Texture Name="gIronKnuckleMetalOverflowTex" OutName="iron_knuckle_metal_overflow_tex" Format="i8" Width="32" Height="64" Offset="0xF79F"/>
<Texture Name="object_ik_Tex_00FBA0" OutName="tex_00FBA0" Format="ia8" Width="32" Height="32" Offset="0xFBA0"/>
<Texture Name="object_ik_Tex_00FFA0" OutName="tex_00FFA0" Format="rgba16" Width="16" Height="16" Offset="0xFFA0"/>
<Texture Name="object_ik_Tex_0101A0" OutName="tex_0101A0" Format="rgba16" Width="16" Height="16" Offset="0x101A0"/>

View File

@ -1,4 +1,5 @@
#include "CosmeticsEditor.h"
#include "authenticGfxPatches.h"
#include <ImGuiImpl.h>
#include "soh/Enhancements/game-interactor/GameInteractor.h"
@ -1817,6 +1818,7 @@ void InitCosmeticsEditor() {
}
SohImGui::RequestCvarSaveOnNextTick();
ApplyOrResetCustomGfxPatches();
ApplyAuthenticGfxPatches();
RegisterOnLoadGameHook();
}

View File

@ -0,0 +1,191 @@
#include <libultraship/bridge.h>
#include <string>
extern "C" {
#include <libultraship/libultra.h>
#include "objects/gameplay_keep/gameplay_keep.h"
#include "objects/object_fz/object_fz.h"
#include "objects/object_ik/object_ik.h"
#include "objects/object_link_child/object_link_child.h"
void ResourceMgr_PatchGfxByName(const char* path, const char* patchName, int index, Gfx instruction);
void ResourceMgr_UnpatchGfxByName(const char* path, const char* patchName);
}
typedef struct {
const char* dlist;
int startInstruction;
} DListPatchInfo;
static DListPatchInfo freezardEffectDListPatchInfos[] = {
{ gFreezardIntactDL, 5 },
{ gFreezardTopRightHornChippedDL, 5 },
{ gFreezardHeadChippedDL, 5 },
{ gFreezardIceTriangleDL, 5 },
{ gFreezardIceRockDL, 5 },
};
static DListPatchInfo ironKnuckleDListPatchInfos[] = {
{ object_ik_DL_01BE98, 39 },
{ object_ik_DL_01BE98, 59 },
{ object_ik_DL_01C130, 38 },
{ object_ik_DL_01C2B8, 39 },
{ object_ik_DL_01C2B8, 59 },
{ object_ik_DL_01C550, 38 },
{ object_ik_DL_01C7B8, 8 },
{ object_ik_DL_01C7B8, 28 },
{ object_ik_DL_01CB58, 8 },
{ object_ik_DL_01CB58, 31 },
{ object_ik_DL_01CCA0, 15 },
{ object_ik_DL_01CCA0, 37 },
{ object_ik_DL_01CCA0, 52 },
{ object_ik_DL_01CCA0, 68 },
{ object_ik_DL_01CEE0, 27 },
{ object_ik_DL_01CEE0, 46 },
{ object_ik_DL_01CEE0, 125 },
{ object_ik_DL_01D2B0, 8 },
{ object_ik_DL_01D2B0, 32 },
{ object_ik_DL_01D3F8, 15 },
{ object_ik_DL_01D3F8, 37 },
{ object_ik_DL_01D3F8, 52 },
{ object_ik_DL_01D3F8, 68 },
{ object_ik_DL_01D638, 23 },
{ object_ik_DL_01D638, 42 },
{ object_ik_DL_01D638, 110 },
};
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 instructions to fix authentic vanilla bug where the Deku Stick texture is read as the wrong size
Gfx gDekuStickTexFix[] = {
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)
};
const char* dlist = gLinkChildLinkDekuStickDL;
int start = 5;
if (!CVarGetInteger("gFixTexturesOOB", 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);
ResourceMgr_UnpatchGfxByName(dlist, unpatchName.c_str());
}
std::string patchName = "DekuStickOverflow" + std::to_string(start);
ResourceMgr_PatchGfxByName(dlist, patchName.c_str(), start, gDekuStickOverflowTexFix);
} else {
// Unpatch the other texture fix
std::string unpatchName = "DekuStickOverflow" + std::to_string(start);
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]);
}
}
}
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 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)
};
for (const auto& patchInfo : freezardEffectDListPatchInfos) {
const char* dlist = patchInfo.dlist;
int start = patchInfo.startInstruction;
char patchNameBuf[24];
// Patch using custom overflowed texture
if (!CVarGetInteger("gFixTexturesOOB", 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 = "gEffUnknown12Fix" + 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
// Unpatch the other texture fix
std::string unpatchName = "gEffUnknown12Overflow" + std::to_string(start);
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 = "gEffUnknown12Fix" + std::to_string(instruction);
ResourceMgr_PatchGfxByName(dlist, patchName.c_str(), instruction, gEffUnknown12TexFix[i]);
}
}
}
}
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 instructions to fix authentic vanilla bug where the Iron Knuckle texture is read as the wrong format
Gfx gIronKnuckleMetalTexFix[] = {
gsDPLoadTextureBlock(object_ik_Tex_00F7A0, 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)
};
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("gFixTexturesOOB", 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 = "MetalTexFix" + 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());
// // 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]);
// }
// }
}
}
void ApplyAuthenticGfxPatches() {
PatchDekuStickTextureOverflow();
PatchFreezardTextureOverflow();
PatchIronKnuckleTextureOverflow();
}

View File

@ -0,0 +1,3 @@
#pragma once
void ApplyAuthenticGfxPatches();

View File

@ -34,6 +34,7 @@
#endif
#include "Enhancements/game-interactor/GameInteractor.h"
#include "Enhancements/cosmetics/authenticGfxPatches.h"
bool isBetaQuestEnabled = false;
@ -909,6 +910,10 @@ namespace GameMenuBar {
UIWidgets::Tooltip(
"Adds 5 higher pitches for the Silver Rupee Jingle for the rooms with more than 5 Silver Rupees. "
"Currently only relevant in Master Quest.");
if (UIWidgets::PaddedEnhancementCheckbox("Fix out of bounds textures", "gFixTexturesOOB", true, false)) {
ApplyAuthenticGfxPatches();
}
UIWidgets::Tooltip("Fixes authentic out of bounds texture reads, instead loading textures with the correct size");
ImGui::EndMenu();
}