From ca9b1614af5b5613f1cd54413d0e180b69d3c796 Mon Sep 17 00:00:00 2001 From: Adam Bird Date: Mon, 12 Jun 2023 17:10:53 -0400 Subject: [PATCH] Fix: Minimap dungeon entrance placement (#2958) * use correct minimaps in randomizer * fix minimap dungeon entrance placement * rework topLeft0 check to be more readable * who needs topLeft0 anyways * move minimap hidden checks up higher --- soh/src/code/z_map_exp.c | 123 ++++++++++++++++----------------------- 1 file changed, 49 insertions(+), 74 deletions(-) diff --git a/soh/src/code/z_map_exp.c b/soh/src/code/z_map_exp.c index 5b23d6ed1..990f1b695 100644 --- a/soh/src/code/z_map_exp.c +++ b/soh/src/code/z_map_exp.c @@ -392,7 +392,9 @@ void Map_InitData(PlayState* play, s16 room) { extendedMapIndex = 0x14; } } else if (play->sceneNum == SCENE_SPOT06) { - if ((LINK_AGE_IN_YEARS == YEARS_ADULT) && !CHECK_QUEST_ITEM(QUEST_MEDALLION_WATER)) { + if ((LINK_AGE_IN_YEARS == YEARS_ADULT) && + ((!gSaveContext.n64ddFlag && !CHECK_QUEST_ITEM(QUEST_MEDALLION_WATER)) || + (gSaveContext.n64ddFlag && !Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_WATER_TEMPLE)))) { extendedMapIndex = 0x15; } } else if (play->sceneNum == SCENE_SPOT09) { @@ -400,7 +402,8 @@ void Map_InitData(PlayState* play, s16 room) { extendedMapIndex = 0x16; } } else if (play->sceneNum == SCENE_SPOT12) { - if ((gSaveContext.eventChkInf[9] & 0xF) == 0xF) { + if ((!gSaveContext.n64ddFlag && ((gSaveContext.eventChkInf[9] & 0xF) == 0xF)) || + (gSaveContext.n64ddFlag && CHECK_QUEST_ITEM(QUEST_GERUDO_CARD))) { extendedMapIndex = 0x17; } } @@ -651,10 +654,6 @@ void Minimap_DrawCompassIcons(PlayState* play) { Matrix_Translate( (R_COMPASS_OFFSET_X + tempX + (CVarGetInteger("gMinimapPosX", 0)*10) / 10.0f), (R_COMPASS_OFFSET_Y + ((Y_Margins_Minimap*10)*-1) - tempZ + ((CVarGetInteger("gMinimapPosY", 0)*10)*-1)) / 10.0f, 0.0f, MTXMODE_NEW); - } else if (CVarGetInteger("gMinimapPosType", 0) == 4) {//Hidden - Matrix_Translate( - (R_COMPASS_OFFSET_X+(9999*10) + tempX / 10.0f), - (R_COMPASS_OFFSET_Y+(9999*10) - tempZ) / 10.0f, 0.0f, MTXMODE_NEW); } } else { Matrix_Translate(OTRGetDimensionFromRightEdge((R_COMPASS_OFFSET_X+(X_Margins_Minimap*10) + tempX) / 10.0f), (R_COMPASS_OFFSET_Y+((Y_Margins_Minimap*10)*-1) - tempZ) / 10.0f, 0.0f, MTXMODE_NEW); @@ -689,10 +688,6 @@ void Minimap_DrawCompassIcons(PlayState* play) { Matrix_Translate( (R_COMPASS_OFFSET_X + tempX + (CVarGetInteger("gMinimapPosX", 0)*10) / 10.0f), (R_COMPASS_OFFSET_Y - tempZ + ((CVarGetInteger("gMinimapPosY", 0)*10)*-1)) / 10.0f, 0.0f, MTXMODE_NEW); - } else if (CVarGetInteger("gMinimapPosType", 0) == 4) {//Hidden - Matrix_Translate( - (R_COMPASS_OFFSET_X+(9999*10) + tempX / 10.0f), - (R_COMPASS_OFFSET_Y+(9999*10) - tempZ) / 10.0f, 0.0f, MTXMODE_NEW); } } else { Matrix_Translate(OTRGetDimensionFromRightEdge((R_COMPASS_OFFSET_X+(X_Margins_Minimap*10) + tempX) / 10.0f), (R_COMPASS_OFFSET_Y+((Y_Margins_Minimap*10)*-1) - tempZ) / 10.0f, 0.0f, MTXMODE_NEW); @@ -749,7 +744,7 @@ void Minimap_Draw(PlayState* play) { case SCENE_HAKADAN: case SCENE_HAKADANCH: case SCENE_ICE_DOUKUTO: - if (!R_MINIMAP_DISABLED) { + if (!R_MINIMAP_DISABLED && CVarGetInteger("gMinimapPosType", 0) != 4) { // Not Hidden Gfx_SetupDL_39Overlay(play->state.gfxCtx); gDPSetCombineLERP(OVERLAY_DISP++, 1, 0, PRIMITIVE, 0, TEXEL0, 0, PRIMITIVE, 0, 1, 0, PRIMITIVE, 0, TEXEL0, 0, PRIMITIVE, 0); @@ -773,8 +768,6 @@ void Minimap_Draw(PlayState* play) { dgnMiniMapX = OTRGetDimensionFromRightEdge(R_DGN_MINIMAP_X+CVarGetInteger("gMinimapPosX", 0)+X_Margins_Minimap); } else if (CVarGetInteger("gMinimapPosType", 0) == 3) {//Anchor None dgnMiniMapX = CVarGetInteger("gMinimapPosX", 0); - } else if (CVarGetInteger("gMinimapPosType", 0) == 4) {//Hidden - dgnMiniMapX = -9999; } } gSPWideTextureRectangle(OVERLAY_DISP++, dgnMiniMapX << 2, dgnMiniMapY << 2, @@ -821,7 +814,7 @@ void Minimap_Draw(PlayState* play) { case SCENE_SPOT18: case SCENE_SPOT20: case SCENE_GANON_TOU: - if (!R_MINIMAP_DISABLED) { + if (!R_MINIMAP_DISABLED && CVarGetInteger("gMinimapPosType", 0) != 4) { // Not Hidden Gfx_SetupDL_39Overlay(play->state.gfxCtx); gDPSetCombineMode(OVERLAY_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM); @@ -844,8 +837,6 @@ void Minimap_Draw(PlayState* play) { oWMiniMapX = OTRGetDimensionFromRightEdge(R_OW_MINIMAP_X+CVarGetInteger("gMinimapPosX", 0)+X_Margins_Minimap); } else if (CVarGetInteger("gMinimapPosType", 0) == 3) {//Anchor None oWMiniMapX = CVarGetInteger("gMinimapPosX", 0); - } else if (CVarGetInteger("gMinimapPosType", 0) == 4) {//Hidden - oWMiniMapX = -9999; } } gSPWideTextureRectangle(OVERLAY_DISP++, oWMiniMapX << 2, oWMiniMapY << 2, @@ -855,59 +846,51 @@ void Minimap_Draw(PlayState* play) { gDPSetPrimColor(OVERLAY_DISP++, 0, 0, minimapColor.r, minimapColor.g, minimapColor.b, interfaceCtx->minimapAlpha); + s16 iconSize = 8; + if (((play->sceneNum != SCENE_SPOT01) && (play->sceneNum != SCENE_SPOT04) && (play->sceneNum != SCENE_SPOT08)) || (LINK_AGE_IN_YEARS != YEARS_ADULT)) { - bool Map0 = gMapData->owEntranceIconPosY[sEntranceIconMapIndex] << 2 == 0; - s16 IconSize = 8; - s16 PosX = gMapData->owEntranceIconPosX[sEntranceIconMapIndex] + (Map0 ? 0 : X_Margins_Minimap); - s16 PosY = gMapData->owEntranceIconPosY[sEntranceIconMapIndex] + (Map0 ? 0 : Y_Margins_Minimap); - //gFixDungeonMinimapIcon fix both Y position of visible icon and hide these non needed. + // The game authentically uses larger negative values for the entrance icon Y pos value. Normally only the first 12 bits + // would be read when the final value is passed into `gSPTextureRectangle`, but our cosmetic hud placements requires using + // `gSPWideTextureRectangle` which reads the first 24 bits instead. This caused the icon to be placed off screen. + // To address this, we take only the first 10 bits (which are later left-shifted by 2 to get our final 12 bits) + // to fix the entrance icon position when used with `gSPWideTextureRectangle` + s16 newY = gMapData->owEntranceIconPosY[sEntranceIconMapIndex] & 0x3FF; + s16 PosX = gMapData->owEntranceIconPosX[sEntranceIconMapIndex] + X_Margins_Minimap; - s16 TopLeftX = (Map0 ? OTRGetRectDimensionFromLeftEdge(PosX) : OTRGetRectDimensionFromRightEdge(PosX)) << 2; - s16 TopLeftY = PosY << 2; - s16 TopLeftW = (Map0 ? OTRGetRectDimensionFromLeftEdge(PosX + IconSize) : OTRGetRectDimensionFromRightEdge(PosX + IconSize)) << 2; - s16 TopLeftH = (PosY + IconSize) << 2; + s16 entranceX = OTRGetRectDimensionFromRightEdge(PosX); + s16 entranceY = newY + Y_Margins_Minimap; if (CVarGetInteger("gMinimapPosType", 0) != 0) { - PosX = gMapData->owEntranceIconPosX[sEntranceIconMapIndex] + CVarGetInteger("gMinimapPosX", 0) + X_Margins_Minimap; - PosY = gMapData->owEntranceIconPosY[sEntranceIconMapIndex] + CVarGetInteger("gMinimapPosY", 0) + Y_Margins_Minimap; - if (CVarGetInteger("gMinimapPosType", 0) == 1) {//Anchor Left + entranceY = newY + CVarGetInteger("gMinimapPosY", 0) + Y_Margins_Minimap; + if (CVarGetInteger("gMinimapPosType", 0) == 1) { // Anchor Left if (CVarGetInteger("gMinimapUseMargins", 0) != 0) {X_Margins_Minimap = Left_MM_Margin;}; - TopLeftX = OTRGetRectDimensionFromLeftEdge(PosX) << 2; - TopLeftW = OTRGetRectDimensionFromLeftEdge(PosX + IconSize) << 2; - } else if (CVarGetInteger("gMinimapPosType", 0) == 2) {//Anchor Right + entranceX = OTRGetRectDimensionFromLeftEdge(PosX + CVarGetInteger("gMinimapPosX", 0)); + } else if (CVarGetInteger("gMinimapPosType", 0) == 2) { // Anchor Right if (CVarGetInteger("gMinimapUseMargins", 0) != 0) {X_Margins_Minimap = Right_MM_Margin;}; - TopLeftX = OTRGetRectDimensionFromRightEdge(PosX) << 2; - TopLeftW = OTRGetRectDimensionFromRightEdge(PosX + IconSize) << 2; - } else if (CVarGetInteger("gMinimapPosType", 0) == 3) {//Anchor None - TopLeftX = PosX << 2; - TopLeftW = PosX + IconSize << 2; - } else if (CVarGetInteger("gMinimapPosType", 0) == 4) {//Hidden - TopLeftX = -9999 << 2; - TopLeftW = -9999 + IconSize << 2; + entranceX = OTRGetRectDimensionFromRightEdge(PosX + CVarGetInteger("gMinimapPosX", 0)); + } else if (CVarGetInteger("gMinimapPosType", 0) == 3) { // Anchor None + entranceX = PosX + CVarGetInteger("gMinimapPosX", 0); } - if (!CVarGetInteger("gMinimapPosType", 0) != 4 && Map0 && !CVarGetInteger("gFixDungeonMinimapIcon", 0)) { //Force top left icon if fix not applied. - TopLeftX = OTRGetRectDimensionFromLeftEdge(gMapData->owEntranceIconPosX[sEntranceIconMapIndex]) << 2; - TopLeftY = gMapData->owEntranceIconPosY[sEntranceIconMapIndex] << 2; - TopLeftW = OTRGetRectDimensionFromLeftEdge(gMapData->owEntranceIconPosX[sEntranceIconMapIndex] + IconSize) << 2; - TopLeftH = (gMapData->owEntranceIconPosY[sEntranceIconMapIndex] + IconSize) << 2; - } - } - if (CVarGetInteger("gFixDungeonMinimapIcon", 0) != 0){ - //No idea why and how Original value work but this does actually fix them all. - PosY = PosY+1024; } - if (((gMapData->owEntranceFlag[sEntranceIconMapIndex] == 0xFFFF) || - ((gMapData->owEntranceFlag[sEntranceIconMapIndex] != 0xFFFF) && - (gSaveContext.infTable[26] & gBitFlags[gMapData->owEntranceFlag[mapIndex]]) - )) || CVarGetInteger("gAlwaysShowDungeonMinimapIcon", 0)) { - if (!Map0 || !CVarGetInteger("gFixDungeonMinimapIcon", 0)) { - gDPLoadTextureBlock(OVERLAY_DISP++, gMapDungeonEntranceIconTex, G_IM_FMT_RGBA, G_IM_SIZ_16b, - IconSize, IconSize, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, - G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); - gSPWideTextureRectangle(OVERLAY_DISP++, TopLeftX, TopLeftY, TopLeftW, TopLeftH, G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10); - } + // For icons that normally would be placed in 0,0 leave them there based on the left edge dimension + // or hide them entirely if the fix is applied + if (gMapData->owEntranceIconPosY[sEntranceIconMapIndex] == 0) { + entranceY = 0; + entranceX = CVarGetInteger("gFixDungeonMinimapIcon", 0) ? -9999 : OTRGetRectDimensionFromLeftEdge(0); + } + + //! @bug UB: sEntranceIconMapIndex can be up to 23 and is accessing owEntranceFlag which is size 20 + if ((gMapData->owEntranceFlag[sEntranceIconMapIndex] == 0xFFFF) || + ((gMapData->owEntranceFlag[sEntranceIconMapIndex] != 0xFFFF) && + ((gSaveContext.infTable[26] & gBitFlags[gMapData->owEntranceFlag[mapIndex]]) || + CVarGetInteger("gAlwaysShowDungeonMinimapIcon", 0)))) { + gDPLoadTextureBlock(OVERLAY_DISP++, gMapDungeonEntranceIconTex, G_IM_FMT_RGBA, G_IM_SIZ_16b, + iconSize, iconSize, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, + G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); + gSPWideTextureRectangle(OVERLAY_DISP++, entranceX << 2, entranceY << 2, (entranceX + iconSize) << 2, + (entranceY + iconSize) << 2, G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10); } } @@ -923,25 +906,17 @@ void Minimap_Draw(PlayState* play) { entranceX = OTRGetRectDimensionFromRightEdge(270 + X_Margins_Minimap + CVarGetInteger("gMinimapPosX", 0)); } else if (CVarGetInteger("gMinimapPosType", 0) == 3) {//Anchor None entranceX = 270 + X_Margins_Minimap + CVarGetInteger("gMinimapPosX", 0); - } else if (CVarGetInteger("gMinimapPosType", 0) == 4) {//Hidden - entranceX = -9999; } } - if ((play->sceneNum == SCENE_SPOT08) && (gSaveContext.infTable[26] & gBitFlags[9])) { - gDPLoadTextureBlock(OVERLAY_DISP++, gMapDungeonEntranceIconTex, G_IM_FMT_RGBA, G_IM_SIZ_16b, 8, - 8, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, + // Ice Cavern entrance icon + if ((play->sceneNum == SCENE_SPOT08) && ((gSaveContext.infTable[26] & gBitFlags[9]) || + CVarGetInteger("gAlwaysShowDungeonMinimapIcon", 0))) { + gDPLoadTextureBlock(OVERLAY_DISP++, gMapDungeonEntranceIconTex, G_IM_FMT_RGBA, G_IM_SIZ_16b, iconSize, + iconSize, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); - gSPWideTextureRectangle(OVERLAY_DISP++, entranceX << 2, entranceY << 2, (entranceX + 32) << 2, (entranceY + 8) << 2, - G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10); - } else if ((play->sceneNum == SCENE_SPOT08) && CVarGetInteger("gAlwaysShowDungeonMinimapIcon", 0) != 0){ - - gDPLoadTextureBlock(OVERLAY_DISP++, gMapDungeonEntranceIconTex, G_IM_FMT_RGBA, G_IM_SIZ_16b, 8, - 8, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, - G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); - - gSPWideTextureRectangle(OVERLAY_DISP++, entranceX << 2, entranceY << 2, (entranceX + 32) << 2, (entranceY + 8) << 2, - G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10); + gSPWideTextureRectangle(OVERLAY_DISP++, entranceX << 2, entranceY << 2, (entranceX + iconSize) << 2, + (entranceY + iconSize) << 2, G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10); } Minimap_DrawCompassIcons(play); // Draw icons for the player spawn and current position