summaryrefslogtreecommitdiff
path: root/soh/src
diff options
context:
space:
mode:
authorAdam Bird <archez39@me.com>2023-12-18 00:34:59 -0500
committerAdam Bird <archez39@me.com>2023-12-18 00:34:59 -0500
commit03da69d7b745c4e6131555a2bfaa0c140a91f79e (patch)
tree1a109a21f8b5271bb0274fc8e168e3a94ac45889 /soh/src
parent86044a1c5071c9a0e00699939fa26946aeefbaff (diff)
parent60faf3f750e29643ffa688b9b5fe752a9d2162c0 (diff)
Merge tag '8.0.4' into HEAD
MacReady Echo
Diffstat (limited to 'soh/src')
-rw-r--r--soh/src/code/z_parameter.c14
-rw-r--r--soh/src/overlays/actors/ovl_Boss_Dodongo/z_boss_dodongo.c77
-rw-r--r--soh/src/overlays/actors/ovl_En_Box/z_en_box.c5
-rw-r--r--soh/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.c7
-rw-r--r--soh/src/overlays/actors/ovl_player_actor/z_player.c9
-rw-r--r--soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c14
-rw-r--r--soh/src/overlays/gamestates/ovl_file_choose/z_file_nameset_PAL.c1
-rw-r--r--soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_map_PAL.c13
-rw-r--r--soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope.h4
-rw-r--r--soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c133
-rw-r--r--soh/src/overlays/misc/ovl_map_mark_data/z_map_mark_data.c7
11 files changed, 235 insertions, 49 deletions
diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c
index 3bc7c9c6a..46a87d649 100644
--- a/soh/src/code/z_parameter.c
+++ b/soh/src/code/z_parameter.c
@@ -1521,6 +1521,13 @@ void Inventory_SwapAgeEquipment(void) {
}
}
+ // In Rando, when switching to adult for the second+ time, if a sword was not previously
+ // equiped in MS shuffle, then we need to set the swordless flag again
+ if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD) &&
+ gSaveContext.equips.buttonItems[0] == ITEM_NONE) {
+ Flags_SetInfTable(INFTABLE_SWORDLESS);
+ }
+
gSaveContext.equips.equipment = gSaveContext.adultEquips.equipment;
}
} else {
@@ -1589,6 +1596,13 @@ void Inventory_SwapAgeEquipment(void) {
}
}
+ // In Rando, when switching to child from a swordless adult, and child Link previously had a
+ // sword equiped, then we need to unset the swordless flag to match
+ if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_MASTER_SWORD) &&
+ gSaveContext.equips.buttonItems[0] != ITEM_NONE) {
+ Flags_UnsetInfTable(INFTABLE_SWORDLESS);
+ }
+
gSaveContext.equips.equipment = gSaveContext.childEquips.equipment;
gSaveContext.equips.equipment &= (u16) ~(0xF << (EQUIP_TYPE_SWORD * 4));
gSaveContext.equips.equipment |= EQUIP_VALUE_SWORD_KOKIRI << (EQUIP_TYPE_SWORD * 4);
diff --git a/soh/src/overlays/actors/ovl_Boss_Dodongo/z_boss_dodongo.c b/soh/src/overlays/actors/ovl_Boss_Dodongo/z_boss_dodongo.c
index f4c46d952..b077d8ef7 100644
--- a/soh/src/overlays/actors/ovl_Boss_Dodongo/z_boss_dodongo.c
+++ b/soh/src/overlays/actors/ovl_Boss_Dodongo/z_boss_dodongo.c
@@ -69,7 +69,7 @@ static u8 sMaskTex16x32[16 * 32] = { { 0 } };
static u8 sMaskTex32x16[32 * 16] = { { 0 } };
static u8 sMaskTex8x8[8 * 8] = { { 0 } };
static u8 sMaskTex8x32[8 * 32] = { { 0 } };
-static u8 sMaskTexLava[32 * 64] = { { 0 } };
+static u8 sMaskTexLava[LAVA_TEX_WIDTH * LAVA_TEX_HEIGHT] = { { 0 } };
static u32* sLavaFloorModifiedTexRaw = NULL;
static u32* sLavaWavyTexRaw = NULL;
@@ -112,6 +112,20 @@ void BossDodongo_RegisterBlendedLavaTextureUpdate() {
u32* lavaTex = ResourceGetDataByName(sLavaFloorLavaTex);
size_t lavaSize = ResourceGetSizeByName(sLavaFloorLavaTex);
size_t floorSize = ResourceGetSizeByName(gDodongosCavernBossLavaFloorTex);
+ size_t rockSize = ResourceGetSizeByName(sLavaFloorRockTex);
+
+ // If the sizes don't match, then don't bother with the blended effect to avoid crashing
+ if (floorSize != lavaSize || floorSize != rockSize) {
+ uint8_t maskVal = !!Flags_GetClear(gPlayState, gPlayState->roomCtx.curRoom.num);
+
+ if (sMaskTexLava[0] != maskVal) {
+ for (int i = 0; i < ARRAY_COUNT(sMaskTexLava); i++) {
+ sMaskTexLava[i] = maskVal;
+ }
+ }
+ Gfx_RegisterBlendedTexture(gDodongosCavernBossLavaFloorTex, sMaskTexLava, NULL);
+ return;
+ }
sLavaFloorModifiedTexRaw = malloc(lavaSize);
sLavaWavyTexRaw = malloc(floorSize);
@@ -121,7 +135,6 @@ void BossDodongo_RegisterBlendedLavaTextureUpdate() {
// When KD is dead, just immediately copy the rock texture
if (Flags_GetClear(gPlayState, gPlayState->roomCtx.curRoom.num)) {
u32* rockTex = ResourceGetDataByName(sLavaFloorRockTex);
- size_t rockSize = ResourceGetSizeByName(sLavaFloorRockTex);
memcpy(sLavaFloorModifiedTexRaw, rockTex, rockSize);
}
@@ -145,6 +158,13 @@ void BossDodongo_RegisterBlendedLavaTextureUpdate() {
Gfx_RegisterBlendedTexture(gDodongosCavernBossLavaFloorTex, sMaskTexLava, sLavaWavyTex);
}
+ // Set all true for the lava as it will always replace the scene texture
+ if (sMaskTexLava[0] == 0) {
+ for (int i = 0; i < ARRAY_COUNT(sMaskTexLava); i++) {
+ sMaskTexLava[i] = 1;
+ }
+ }
+
gfx_texture_cache_clear();
}
@@ -170,6 +190,11 @@ void func_808C12C4(u8* arg1, s16 arg2) {
// Same as func_808C1554 but works with u32 values for RGBA32 raw textures
void func_808C1554_Raw(void* arg0, void* floorTex, s32 arg2, f32 arg3) {
+ // Raw lava not registered, so abort the wave modification
+ if (sLavaWavyTexRaw == NULL || sLavaFloorModifiedTexRaw == NULL) {
+ return;
+ }
+
u16 width = ResourceGetTexWidthByName(arg0);
s32 size = ResourceGetTexHeightByName(arg0) * width;
@@ -203,9 +228,6 @@ void func_808C1554_Raw(void* arg0, void* floorTex, s32 arg2, f32 arg3) {
}
free(sp54);
-
- // Need to clear the cache after updating sLavaWavyTexRaw
- gfx_texture_cache_clear();
}
// Modified to support CPU modified texture with the resource system
@@ -233,9 +255,6 @@ void func_808C1554(void* arg0, void* floorTex, s32 arg2, f32 arg3) {
temp_s3[i + temp2] = sp54[i + i2];
}
}
-
- // Need to clear the cache after updating sLavaWavyTex
- gfx_texture_cache_clear();
}
void func_808C17C8(PlayState* play, Vec3f* arg1, Vec3f* arg2, Vec3f* arg3, f32 arg4, s16 arg5) {
@@ -325,7 +344,7 @@ void BossDodongo_Init(Actor* thisx, PlayState* play) {
this->actor.flags &= ~ACTOR_FLAG_TARGETABLE;
// #region SOH [General]
- // Init mask values for all blended textures
+ // Init mask values for all KD blended textures
for (int i = 0; i < ARRAY_COUNT(sMaskTex8x16); i++) {
sMaskTex8x16[i] = 0;
}
@@ -341,10 +360,6 @@ void BossDodongo_Init(Actor* thisx, PlayState* play) {
for (int i = 0; i < ARRAY_COUNT(sMaskTex32x16); i++) {
sMaskTex32x16[i] = 0;
}
- // Set all true for the lava as it will always replace the scene texture
- for (int i = 0; i < ARRAY_COUNT(sMaskTexLava); i++) {
- sMaskTexLava[i] = 1;
- }
// Register all blended textures
Gfx_RegisterBlendedTexture(object_kingdodongo_Tex_015890, sMaskTex8x16, NULL);
@@ -1174,15 +1189,23 @@ void BossDodongo_Update(Actor* thisx, PlayState* play2) {
for (i2 = 0; i2 < 20; i2++) {
s16 new_var = this->unk_1C2 & (LAVA_TEX_SIZE - 1);
- // Compute the index to a scaled position (scaling pseudo x,y as a 1D value)
- s32 indexStart = ((new_var % LAVA_TEX_WIDTH) * widthScale) + ((new_var / LAVA_TEX_WIDTH) * width * heightScale);
-
- // From the starting index, apply extra pixels right/down based on the scale
- for (size_t j = 0; j < heightScale; j++) {
- for (size_t i3 = 0; i3 < widthScale; i3++) {
- s32 scaledIndex = (indexStart + i3 + (j * width)) & (size - 1);
- ptr1[scaledIndex] = ptr2[scaledIndex];
+
+ // Raw lava must be registered, otherwise skip the effect for incompatible texture pack
+ // and instead set the mask to simulate the lava disappearing by turning black
+ if (sLavaFloorModifiedTexRaw != NULL) {
+ // Compute the index to a scaled position (scaling pseudo x,y as a 1D value)
+ s32 indexStart =
+ ((new_var % LAVA_TEX_WIDTH) * widthScale) + ((new_var / LAVA_TEX_WIDTH) * width * heightScale);
+
+ // From the starting index, apply extra pixels right/down based on the scale
+ for (size_t j = 0; j < heightScale; j++) {
+ for (size_t i3 = 0; i3 < widthScale; i3++) {
+ s32 scaledIndex = (indexStart + i3 + (j * width)) & (size - 1);
+ ptr1[scaledIndex] = ptr2[scaledIndex];
+ }
}
+ } else {
+ sMaskTexLava[new_var] = 1;
}
this->unk_1C2 += 37;
@@ -1322,8 +1345,16 @@ void BossDodongo_Draw(Actor* thisx, PlayState* play) {
gSPInvalidateTexCache(POLY_OPA_DISP++, sMaskTex32x16);
}
- if (this->unk_1C6 != 0) {
- gSPInvalidateTexCache(POLY_OPA_DISP++, sMaskTexLava);
+ gSPInvalidateTexCache(POLY_OPA_DISP++, sMaskTexLava);
+
+ // Using WORK_DISP to invalidate these textures as they are used in drawing the scene textures which happens
+ // before actors are drawn. WORK_DISP comes before POLAY_OPA_DISP. It is probably not meant for this, but it
+ // at least works for now.
+ // Alternatively, having a way to invalidate just these pointers from the Update func should be sufficient.
+ if (sLavaFloorModifiedTexRaw != NULL) {
+ gSPInvalidateTexCache(WORK_DISP++, sLavaWavyTexRaw);
+ } else {
+ gSPInvalidateTexCache(WORK_DISP++, sLavaWavyTex);
}
if ((this->unk_1C0 >= 2) && (this->unk_1C0 & 1)) {
diff --git a/soh/src/overlays/actors/ovl_En_Box/z_en_box.c b/soh/src/overlays/actors/ovl_En_Box/z_en_box.c
index e4cccb501..a4d86ff61 100644
--- a/soh/src/overlays/actors/ovl_En_Box/z_en_box.c
+++ b/soh/src/overlays/actors/ovl_En_Box/z_en_box.c
@@ -75,7 +75,6 @@ static InitChainEntry sInitChain[] = {
};
static UNK_TYPE sUnused;
-GetItemEntry sItem;
Gfx gSkullTreasureChestChestSideAndLidDL[116] = {0};
Gfx gGoldTreasureChestChestSideAndLidDL[116] = {0};
@@ -472,7 +471,7 @@ void EnBox_WaitOpen(EnBox* this, PlayState* play) {
func_8002DBD0(&this->dyna.actor, &sp4C, &player->actor.world.pos);
if (sp4C.z > -50.0f && sp4C.z < 0.0f && fabsf(sp4C.y) < 10.0f && fabsf(sp4C.x) < 20.0f &&
Player_IsFacingActor(&this->dyna.actor, 0x3000, play)) {
- sItem = Randomizer_GetItemFromActor(this->dyna.actor.id, play->sceneNum, this->dyna.actor.params, this->dyna.actor.params >> 5 & 0x7F);
+ GetItemEntry sItem = Randomizer_GetItemFromActor(this->dyna.actor.id, play->sceneNum, this->dyna.actor.params, this->dyna.actor.params >> 5 & 0x7F);
GetItemEntry blueRupee = ItemTable_RetrieveEntry(MOD_NONE, GI_RUPEE_BLUE);
// RANDOTODO treasure chest game rando
@@ -628,7 +627,7 @@ void EnBox_Update(Actor* thisx, PlayState* play) {
}
if (((!IS_RANDO && ((this->dyna.actor.params >> 5 & 0x7F) == 0x7C)) ||
- (IS_RANDO && ABS(sItem.getItemId) == RG_ICE_TRAP)) &&
+ (IS_RANDO && this->getItemEntry.getItemId == RG_ICE_TRAP)) &&
this->actionFunc == EnBox_Open && this->skelanime.curFrame > 45 && this->iceSmokeTimer < 100) {
if (!CVarGetInteger("gAddTraps.enabled", 0)) {
EnBox_SpawnIceSmoke(this, play);
diff --git a/soh/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.c b/soh/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.c
index 888b0ef34..6ab91ddc0 100644
--- a/soh/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.c
+++ b/soh/src/overlays/actors/ovl_En_Syateki_Man/z_en_syateki_man.c
@@ -3,6 +3,7 @@
#include "overlays/actors/ovl_En_Syateki_Itm/z_en_syateki_itm.h"
#include "objects/object_ossan/object_ossan.h"
#include "soh/Enhancements/randomizer/randomizer_entrance.h"
+#include "soh/Enhancements/custom-message/CustomMessageTypes.h"
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_WHILE_CULLED | ACTOR_FLAG_NO_LOCKON)
@@ -371,7 +372,8 @@ void EnSyatekiMan_EndGame(EnSyatekiMan* this, PlayState* play) {
this->getItemId = GI_RUPEE_PURPLE;
}
} else {
- if(IS_RANDO && !Flags_GetTreasure(play, 0x1F)) {
+ // Only give the adult rando reward when the player has a quiver
+ if (IS_RANDO && !Flags_GetTreasure(play, 0x1F) && CUR_UPG_VALUE(UPG_QUIVER) > 0) {
this->getItemEntry = Randomizer_GetItemFromKnownCheck(RC_KAK_SHOOTING_GALLERY_REWARD, GI_QUIVER_50);
this->getItemId = this->getItemEntry.getItemId;
Flags_SetTreasure(play, 0x1F);
@@ -448,6 +450,9 @@ void EnSyatekiMan_FinishPrize(EnSyatekiMan* this, PlayState* play) {
Flags_SetItemGetInf(ITEMGETINF_0D);
} else if ((this->getItemId == GI_QUIVER_40) || (this->getItemId == GI_QUIVER_50)) {
Flags_SetItemGetInf(ITEMGETINF_0E);
+ } else if (IS_RANDO && LINK_IS_ADULT && CUR_UPG_VALUE(UPG_QUIVER) == 0) {
+ // In Rando without a quiver, display a message reminding the player to come back with a bow
+ Message_StartTextbox(play, TEXT_SHOOTING_GALLERY_MAN_COME_BACK_WITH_BOW, NULL);
}
this->gameResult = SYATEKI_RESULT_NONE;
this->actor.parent = this->tempGallery;
diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c
index c0bb84212..64429ed03 100644
--- a/soh/src/overlays/actors/ovl_player_actor/z_player.c
+++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c
@@ -11003,7 +11003,14 @@ void Player_UseTunicBoots(Player* this, PlayState* play) {
s32 i;
s32 item;
s32 itemAction;
- if (!(this->stateFlags1 & PLAYER_STATE1_INPUT_DISABLED || this->stateFlags1 & PLAYER_STATE1_IN_ITEM_CS || this->stateFlags1 & PLAYER_STATE1_IN_CUTSCENE || this->stateFlags1 & PLAYER_STATE1_TEXT_ON_SCREEN || this->stateFlags2 & PLAYER_STATE2_OCARINA_PLAYING)) {
+ if (!(
+ this->stateFlags1 & PLAYER_STATE1_INPUT_DISABLED ||
+ this->stateFlags1 & PLAYER_STATE1_IN_ITEM_CS ||
+ this->stateFlags1 & PLAYER_STATE1_IN_CUTSCENE ||
+ this->stateFlags1 & PLAYER_STATE1_TEXT_ON_SCREEN ||
+ this->stateFlags1 & PLAYER_STATE1_DEAD ||
+ this->stateFlags2 & PLAYER_STATE2_OCARINA_PLAYING
+ )) {
for (i = 0; i < ARRAY_COUNT(sItemButtons); i++) {
if (CHECK_BTN_ALL(sControlInput->press.button, sItemButtons[i])) {
break;
diff --git a/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c b/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c
index 61645de1e..f50106291 100644
--- a/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c
+++ b/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c
@@ -1030,18 +1030,18 @@ void FileChoose_UpdateRandomizer() {
fileSelectSpoilerFileLoaded = false;
}
- if ((CVarGetInteger("gNewFileDropped", 0) != 0) || (CVarGetInteger("gNewSeedGenerated", 0) != 0) ||
+ if ((CVarGetInteger("gRandomizerNewFileDropped", 0) != 0) || (CVarGetInteger("gNewSeedGenerated", 0) != 0) ||
(!fileSelectSpoilerFileLoaded && SpoilerFileExists(CVarGetString("gSpoilerLog", "")))) {
- if (CVarGetInteger("gNewFileDropped", 0) != 0) {
- CVarSetString("gSpoilerLog", CVarGetString("gDroppedFile", "None"));
+ if (CVarGetInteger("gRandomizerNewFileDropped", 0) != 0) {
+ CVarSetString("gSpoilerLog", CVarGetString("gRandomizerDroppedFile", "None"));
}
bool silent = true;
- if ((CVarGetInteger("gNewFileDropped", 0) != 0) || (CVarGetInteger("gNewSeedGenerated", 0) != 0)) {
+ if ((CVarGetInteger("gRandomizerNewFileDropped", 0) != 0) || (CVarGetInteger("gNewSeedGenerated", 0) != 0)) {
silent = false;
}
CVarSetInteger("gNewSeedGenerated", 0);
- CVarSetInteger("gNewFileDropped", 0);
- CVarSetString("gDroppedFile", "");
+ CVarSetInteger("gRandomizerNewFileDropped", 0);
+ CVarSetString("gRandomizerDroppedFile", "");
fileSelectSpoilerFileLoaded = false;
const char* fileLoc = CVarGetString("gSpoilerLog", "");
Randomizer_LoadSettings(fileLoc);
@@ -1076,7 +1076,6 @@ void FileChoose_UpdateMainMenu(GameState* thisx) {
Input* input = &this->state.input[0];
bool dpad = CVarGetInteger("gDpadText", 0);
- SoH_ProcessDroppedFiles();
FileChoose_UpdateRandomizer();
if (CHECK_BTN_ALL(input->press.button, BTN_START) || CHECK_BTN_ALL(input->press.button, BTN_A)) {
@@ -1267,7 +1266,6 @@ void FileChoose_UpdateQuestMenu(GameState* thisx) {
s8 i = 0;
bool dpad = CVarGetInteger("gDpadText", 0);
- SoH_ProcessDroppedFiles();
FileChoose_UpdateRandomizer();
if (ABS(this->stickRelX) > 30 || (dpad && CHECK_BTN_ANY(input->press.button, BTN_DLEFT | BTN_DRIGHT))) {
diff --git a/soh/src/overlays/gamestates/ovl_file_choose/z_file_nameset_PAL.c b/soh/src/overlays/gamestates/ovl_file_choose/z_file_nameset_PAL.c
index 377c23eb3..5c5cb3e6d 100644
--- a/soh/src/overlays/gamestates/ovl_file_choose/z_file_nameset_PAL.c
+++ b/soh/src/overlays/gamestates/ovl_file_choose/z_file_nameset_PAL.c
@@ -456,7 +456,6 @@ void FileChoose_DrawNameEntry(GameState* thisx) {
this->prevConfigMode = CM_MAIN_MENU;
this->configMode = CM_NAME_ENTRY_TO_MAIN;
CVarSetInteger("gOnFileSelectNameEntry", 0);
- CVarSetInteger("gNewFileDropped", 0);
this->nameBoxAlpha[this->buttonIndex] = this->nameAlpha[this->buttonIndex] = 200;
this->connectorAlpha[this->buttonIndex] = 255;
func_800AA000(300.0f, 0xB4, 0x14, 0x64);
diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_map_PAL.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_map_PAL.c
index 238a1e4e2..28723d3d0 100644
--- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_map_PAL.c
+++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_map_PAL.c
@@ -343,7 +343,7 @@ void KaleidoScope_DrawDungeonMap(PlayState* play, GraphicsContext* gfxCtx) {
// Offset the U value of each vertex to be in the mirror boundary for the map textures
if (mirroredWorld) {
for (size_t i = 0; i < 8; i++) {
- pauseCtx->mapPageVtx[60 + i].v.tc[0] += 48 << 5;
+ pauseCtx->mapPageVtx[60 + i].v.tc[0] += MAP_48x85_TEX_WIDTH << 5;
}
}
@@ -353,8 +353,9 @@ void KaleidoScope_DrawDungeonMap(PlayState* play, GraphicsContext* gfxCtx) {
gSPInvalidateTexCache(POLY_KAL_DISP++, interfaceCtx->mapSegment[0]);
gSPInvalidateTexCache(POLY_KAL_DISP++, interfaceCtx->mapSegment[1]);
- gDPLoadTextureBlock_4b(POLY_KAL_DISP++, interfaceCtx->mapSegmentName[0], G_IM_FMT_CI, 48, 85, 0, G_TX_WRAP | mirrorMode,
- G_TX_WRAP | G_TX_NOMIRROR, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
+ gDPLoadTextureBlock_4b(POLY_KAL_DISP++, interfaceCtx->mapSegmentName[0], G_IM_FMT_CI, MAP_48x85_TEX_WIDTH,
+ MAP_48x85_TEX_HEIGHT, 0, G_TX_WRAP | mirrorMode, G_TX_WRAP | G_TX_NOMIRROR, G_TX_NOMASK,
+ G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
// Swap vertices to render left half on the right and vice-versa
if (mirroredWorld) {
@@ -363,9 +364,9 @@ void KaleidoScope_DrawDungeonMap(PlayState* play, GraphicsContext* gfxCtx) {
gSP1Quadrangle(POLY_KAL_DISP++, 0, 2, 3, 1, 0);
}
- gDPLoadTextureBlock_4b(POLY_KAL_DISP++, interfaceCtx->mapSegmentName[1], G_IM_FMT_CI, 48, 85, 0,
- G_TX_WRAP | mirrorMode, G_TX_WRAP | G_TX_NOMIRROR, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD,
- G_TX_NOLOD);
+ gDPLoadTextureBlock_4b(POLY_KAL_DISP++, interfaceCtx->mapSegmentName[1], G_IM_FMT_CI, MAP_48x85_TEX_WIDTH,
+ MAP_48x85_TEX_HEIGHT, 0, G_TX_WRAP | mirrorMode, G_TX_WRAP | G_TX_NOMIRROR, G_TX_NOMASK,
+ G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
if (mirroredWorld) {
gSP1Quadrangle(POLY_KAL_DISP++, 0, 2, 3, 1, 0);
diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope.h b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope.h
index 6f4ed7ad2..8c214d9b0 100644
--- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope.h
+++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope.h
@@ -13,6 +13,10 @@ extern u8 gItemAgeReqs[];
extern u8 gAreaGsFlags[];
extern bool gSelectingMask;
+#define MAP_48x85_TEX_WIDTH 48
+#define MAP_48x85_TEX_HEIGHT 85
+#define MAP_48x85_TEX_SIZE ((MAP_48x85_TEX_WIDTH * MAP_48x85_TEX_HEIGHT) / 2) // 48x85 CI4 texture
+
#define AGE_REQ_ADULT LINK_AGE_ADULT
#define AGE_REQ_CHILD LINK_AGE_CHILD
#define AGE_REQ_NONE 9
diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c
index 8fe817f2f..4167324d7 100644
--- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c
+++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c
@@ -1205,6 +1205,8 @@ Gfx* KaleidoScope_DrawPageSections(Gfx* gfx, Vtx* vertices, void** textures) {
return gfx;
}
+static uint8_t mapBlendMask[MAP_48x85_TEX_WIDTH * MAP_48x85_TEX_HEIGHT];
+
void KaleidoScope_DrawPages(PlayState* play, GraphicsContext* gfxCtx) {
static Color_RGB8 D_8082ACF4[12] = {
{ 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 255, 255, 0 }, { 0, 0, 0 },
@@ -1373,6 +1375,10 @@ void KaleidoScope_DrawPages(PlayState* play, GraphicsContext* gfxCtx) {
}
}
+ // Need to invalidate the blend mask every frame. Ideally this would be done in KaleidoScope_DrawDungeonMap
+ // but the reference is not shared between files
+ gSPInvalidateTexCache(POLY_KAL_DISP++, mapBlendMask);
+
if (pauseCtx->pageIndex) { // pageIndex != PAUSE_ITEM
gDPPipeSync(OVERLAY_DISP++);
gDPSetCombineMode(OVERLAY_DISP++, G_CC_MODULATEIA, G_CC_MODULATEIA);
@@ -3315,13 +3321,118 @@ void KaleidoScope_UpdateCursorSize(PauseContext* pauseCtx) {
pauseCtx->cursorVtx[14].v.ob[1] = pauseCtx->cursorVtx[15].v.ob[1] = pauseCtx->cursorVtx[12].v.ob[1] - 16;
}
+// Modifed map texture buffers for registered blend effects and the room indicator color
+static uint8_t mapLeftTexModified[MAP_48x85_TEX_SIZE];
+static uint8_t mapRightTexModified[MAP_48x85_TEX_SIZE];
+static uint8_t* mapLeftTexModifiedRaw = NULL;
+static uint8_t* mapRightTexModifiedRaw = NULL;
+
+// Load dungeon maps into the interface context
+// SoH [General] - Modified to account for our resource system and HD textures
void KaleidoScope_LoadDungeonMap(PlayState* play) {
InterfaceContext* interfaceCtx = &play->interfaceCtx;
+ // Free old textures
+ if (mapLeftTexModifiedRaw != NULL) {
+ free(mapLeftTexModifiedRaw);
+ mapLeftTexModifiedRaw = NULL;
+ }
+ if (mapRightTexModifiedRaw != NULL) {
+ free(mapRightTexModifiedRaw);
+ mapRightTexModifiedRaw = NULL;
+ }
+
+ // Unload original textures to bypass cache result for lookups
+ ResourceMgr_UnloadOriginalWhenAltExists(sDungeonMapTexs[R_MAP_TEX_INDEX]);
+ ResourceMgr_UnloadOriginalWhenAltExists(sDungeonMapTexs[R_MAP_TEX_INDEX + 1]);
+
interfaceCtx->mapSegmentName[0] = sDungeonMapTexs[R_MAP_TEX_INDEX];
interfaceCtx->mapSegmentName[1] = sDungeonMapTexs[R_MAP_TEX_INDEX + 1];
- interfaceCtx->mapSegment[0] = ResourceGetDataByName(sDungeonMapTexs[R_MAP_TEX_INDEX]);
- interfaceCtx->mapSegment[1] = ResourceGetDataByName(sDungeonMapTexs[R_MAP_TEX_INDEX + 1]);
+
+ // When the texture is HD (raw) we need to copy a dynamic amount of data
+ // Otherwise the original asset has a static size
+ if (ResourceMgr_TexIsRaw(interfaceCtx->mapSegmentName[0])) {
+ u32 width = ResourceGetTexWidthByName(interfaceCtx->mapSegmentName[0]);
+ u32 height = ResourceGetTexHeightByName(interfaceCtx->mapSegmentName[0]);
+ size_t size = (width * height) / 2; // account for CI4 size
+
+ // Resource size being larger than the calculated CI size means it is most likely not a CI4 texture
+ // Abort early end undo the blended effect by clearing the mask to avoid crashing
+ if (size < ResourceGetTexSizeByName(interfaceCtx->mapSegmentName[0])) {
+ if (mapBlendMask[0] != 0) {
+ for (size_t i = 0; i < ARRAY_COUNT(mapBlendMask); i++) {
+ mapBlendMask[i] = 0;
+ }
+ }
+
+ interfaceCtx->mapSegment[0] = NULL;
+ interfaceCtx->mapSegment[1] = NULL;
+
+ Gfx_RegisterBlendedTexture(interfaceCtx->mapSegmentName[0], mapBlendMask, NULL);
+ Gfx_RegisterBlendedTexture(interfaceCtx->mapSegmentName[1], mapBlendMask, NULL);
+ return;
+ }
+
+ u8* map1TexRaw = ResourceGetDataByName(interfaceCtx->mapSegmentName[0]);
+ u8* map2TexRaw = ResourceGetDataByName(interfaceCtx->mapSegmentName[1]);
+
+ mapLeftTexModifiedRaw = malloc(size);
+ mapRightTexModifiedRaw = malloc(size);
+
+ memcpy(mapLeftTexModifiedRaw, map1TexRaw, size);
+ memcpy(mapRightTexModifiedRaw, map2TexRaw, size);
+
+ interfaceCtx->mapSegment[0] = mapLeftTexModifiedRaw;
+ interfaceCtx->mapSegment[1] = mapRightTexModifiedRaw;
+ } else {
+ u8* map1Tex = ResourceGetDataByName(interfaceCtx->mapSegmentName[0]);
+ u8* map2Tex = ResourceGetDataByName(interfaceCtx->mapSegmentName[1]);
+
+ memcpy(mapLeftTexModified, map1Tex, MAP_48x85_TEX_SIZE);
+ memcpy(mapRightTexModified, map2Tex, MAP_48x85_TEX_SIZE);
+
+ interfaceCtx->mapSegment[0] = mapLeftTexModified;
+ interfaceCtx->mapSegment[1] = mapRightTexModified;
+ }
+
+ // Mark and register the blend mask for the copied textures
+ if (mapBlendMask[0] != 1) {
+ for (size_t i = 0; i < ARRAY_COUNT(mapBlendMask); i++) {
+ mapBlendMask[i] = 1;
+ }
+ }
+
+ Gfx_RegisterBlendedTexture(interfaceCtx->mapSegmentName[0], mapBlendMask, interfaceCtx->mapSegment[0]);
+ Gfx_RegisterBlendedTexture(interfaceCtx->mapSegmentName[1], mapBlendMask, interfaceCtx->mapSegment[1]);
+}
+
+static uint8_t registeredDungeonMapTextureHook = false;
+
+void KaleidoScope_RegisterUpdatedDungeonMapTexture() {
+ if (gPlayState == NULL) {
+ return;
+ }
+
+ PauseContext* pauseCtx = &gPlayState->pauseCtx;
+
+ // Kaleido is not open in a dungeon so there is nothing to do
+ if (R_PAUSE_MENU_MODE < 3 || pauseCtx->state < 4 || pauseCtx->state > 7 || !sInDungeonScene) {
+ return;
+ }
+
+ KaleidoScope_UpdateDungeonMap(gPlayState);
+
+ // KaleidoScope_UpdateDungeonMap will update the palette index for the current floor if the cursor is on the floor
+ // If the player toggles alt assets while the cursor is not in the floor level, then we handle the palette index here
+ if (gPlayState->sceneNum >= SCENE_DEKU_TREE && gPlayState->sceneNum <= SCENE_TREASURE_BOX_SHOP &&
+ (VREG(30) + 3) == pauseCtx->dungeonMapSlot && (VREG(30) + 3) != pauseCtx->cursorPoint[PAUSE_MAP]) {
+
+ InterfaceContext* interfaceCtx = &gPlayState->interfaceCtx;
+ int32_t size = ResourceGetTexSizeByName(interfaceCtx->mapSegmentName[0]);
+
+ KaleidoScope_OverridePalIndexCI4(interfaceCtx->mapSegment[0], size, interfaceCtx->mapPaletteIndex, 14);
+ KaleidoScope_OverridePalIndexCI4(interfaceCtx->mapSegment[1], size, interfaceCtx->mapPaletteIndex, 14);
+ }
}
void KaleidoScope_UpdateDungeonMap(PlayState* play) {
@@ -3333,19 +3444,29 @@ void KaleidoScope_UpdateDungeonMap(PlayState* play) {
KaleidoScope_LoadDungeonMap(play);
Map_SetFloorPalettesData(play, pauseCtx->dungeonMapSlot - 3);
+ s32 size = MAP_48x85_TEX_SIZE;
+
+ if (ResourceMgr_TexIsRaw(interfaceCtx->mapSegmentName[0])) {
+ size = ResourceGetTexSizeByName(interfaceCtx->mapSegmentName[0]);
+ }
+
if ((play->sceneNum >= SCENE_DEKU_TREE) && (play->sceneNum <= SCENE_TREASURE_BOX_SHOP)) {
if ((VREG(30) + 3) == pauseCtx->cursorPoint[PAUSE_MAP]) {
- // HDTODO: Handle Runtime Modified Textures (HD)
- KaleidoScope_OverridePalIndexCI4(interfaceCtx->mapSegment[0], 2040, interfaceCtx->mapPaletteIndex, 14);
+ KaleidoScope_OverridePalIndexCI4(interfaceCtx->mapSegment[0], size, interfaceCtx->mapPaletteIndex, 14);
}
}
if ((play->sceneNum >= SCENE_DEKU_TREE) && (play->sceneNum <= SCENE_TREASURE_BOX_SHOP)) {
if ((VREG(30) + 3) == pauseCtx->cursorPoint[PAUSE_MAP]) {
- // HDTODO: Handle Runtime Modified Textures (HD)
- KaleidoScope_OverridePalIndexCI4(interfaceCtx->mapSegment[1], 2040, interfaceCtx->mapPaletteIndex, 14);
+ KaleidoScope_OverridePalIndexCI4(interfaceCtx->mapSegment[1], size, interfaceCtx->mapPaletteIndex, 14);
}
}
+
+ // Register alt listener to update the blended dungeon map textures on alt toggle
+ if (!registeredDungeonMapTextureHook) {
+ registeredDungeonMapTextureHook = true;
+ GameInteractor_RegisterOnAssetAltChange(KaleidoScope_RegisterUpdatedDungeonMapTexture);
+ }
}
void KaleidoScope_Update(PlayState* play)
diff --git a/soh/src/overlays/misc/ovl_map_mark_data/z_map_mark_data.c b/soh/src/overlays/misc/ovl_map_mark_data/z_map_mark_data.c
index a73ca8265..fec1d8033 100644
--- a/soh/src/overlays/misc/ovl_map_mark_data/z_map_mark_data.c
+++ b/soh/src/overlays/misc/ovl_map_mark_data/z_map_mark_data.c
@@ -1762,6 +1762,13 @@ static MapMarkData sMapMarkJabuJabuBellyMq[] = {
} },
{ MAP_MARK_NONE, 0, { 0 } },
},
+ // Jabu-Jabu's Belly minimap 16
+ // SoH [General] - This entry corresponds to Big Octorok's room and is missing in the MQ game
+ // N64 hardware does an OoB read and lands on MQ Forest Temple room 0
+ // To avoid UB with OoB for SoH, the correct entry is now added below
+ {
+ { MAP_MARK_NONE, 0, { 0 } },
+ },
};
static MapMarkData sMapMarkForestTempleMq[] = {