z_map decompiled (#1032)

* First batch of functions

* more ok

* z_map_data OK

* More OKs, MinimapList ZAPD breaking change

* func_80103A58 improvements, more OK

* func_80106D5C and func_801091F0 decomped

* func_801031D0 decomped and some fixes

* house cleaning, more OKs more decomp

* Even more OKs

* func_80105C40 almost OK, more OKs

* func_80108AF8 OK and more

* All functions attempted

* func_8010534C OK

* Start documentation, rename DoorCtx

* More OKs, split map_data.data, more doc

* incremental clean-up, more function names

* more function names

* func_801068FC OK

* old uncommitted changes

* minor tweaks

* implement easy fixes

* more fixes

* z_map_disp OK, implement more suggestions

* delete utility program

* migrate data

* TransiActor ->TransitionActor

* Major documentation pass

* first pass of changes

* warning fix attempt, revert ZFile.cpp

* Fix FAKE match

* Easy fixes

* implement gDPLoadTextureBlock_Runtime

* z_demo bss patch

* Extract white square texture

* Implement more suggestions

* rework MapIndex/DungeonIndex

* revert dungeonSceneIndex -> mapIndex in some spots, implement suggestions

* more suggestions

* minor nits

* fix #include
This commit is contained in:
mzxrules
2024-06-20 21:21:37 -04:00
committed by GitHub
parent b55f8ffe6e
commit 2c680efa91
46 changed files with 3309 additions and 880 deletions
+127 -102
View File
@@ -1,19 +1,26 @@
#include "global.h"
s16 sMinimapInitPosX = 0;
s16 sMinimapInitPosZ = 0;
s16 sMinimapInitDir = 0;
s32 sDungeonAndBossSceneIds[] = {
SCENE_MITURIN, SCENE_HAKUGIN, SCENE_SEA, SCENE_INISIE_N, SCENE_INISIE_R,
SCENE_MITURIN_BS, SCENE_HAKUGIN_BS, SCENE_SEA_BS, SCENE_INISIE_BS,
};
s16 sPlayerInitPosX = 0;
s16 sPlayerInitPosZ = 0;
s16 sPlayerInitDir = 0;
/**
* If the current scene is a dungeon or boss scene, this function returns an index
* indicating which one it is. Otherwise, it returns -1.
* Gets the mapIndex for the current dungeon scene
* @return the current scene's DungeonSceneIndex, or -1 if it isn't a dungeon or boss scene.
*/
s32 Map_GetDungeonOrBossAreaIndex(PlayState* play) {
s32 Map_GetDungeonSceneIndex(PlayState* play) {
static s32 sDungeonAndBossSceneIds[] = {
SCENE_MITURIN, // DUNGEON_SCENE_INDEX_WOODFALL_TEMPLE
SCENE_HAKUGIN, // DUNGEON_SCENE_INDEX_SNOWHEAD_TEMPLE
SCENE_SEA, // DUNGEON_SCENE_INDEX_GREAT_BAY_TEMPLE
SCENE_INISIE_N, // DUNGEON_SCENE_INDEX_STONE_TOWER_TEMPLE
SCENE_INISIE_R, // Play_GetOriginalSceneId converts play->sceneId to SCENE_INISIE_N, returning
// DUNGEON_SCENE_INDEX_STONE_TOWER_TEMPLE
SCENE_MITURIN_BS, // DUNGEON_SCENE_INDEX_WOODFALL_TEMPLE_BOSS
SCENE_HAKUGIN_BS, // DUNGEON_SCENE_INDEX_SNOWHEAD_TEMPLE_BOSS
SCENE_SEA_BS, // DUNGEON_SCENE_INDEX_GREAT_BAY_TEMPLE_BOSS
SCENE_INISIE_BS, // DUNGEON_SCENE_INDEX_STONE_TOWER_TEMPLE_BOSS
};
s32 i;
for (i = 0; i < ARRAY_COUNT(sDungeonAndBossSceneIds); i++) {
@@ -26,33 +33,38 @@ s32 Map_GetDungeonOrBossAreaIndex(PlayState* play) {
}
/**
* Returns true if the current scene is a dungeon or boss scene, false otherwise.
* Tests if the current scene is in a dungeon or boss scene.
* @return true if the current scene is a dungeon or boss scene, false otherwise.
*/
s32 Map_IsInDungeonOrBossArea(PlayState* play) {
if (Map_GetDungeonOrBossAreaIndex(play) == -1) {
s32 Map_IsInDungeonOrBossScene(PlayState* play) {
if (Map_GetDungeonSceneIndex(play) == -1) {
return false;
}
return true;
}
s32 func_8010A0A4(PlayState* play) {
if ((Map_GetDungeonOrBossAreaIndex(play) == -1) || !func_80102EF0(play)) {
s32 Map_CurRoomHasMapI(PlayState* play) {
if ((Map_GetDungeonSceneIndex(play) == -1) || !MapDisp_CurRoomHasMapI(play)) {
return false;
}
return true;
}
s32 sDungeonSceneIds[] = {
SCENE_MITURIN, SCENE_HAKUGIN, SCENE_SEA, SCENE_INISIE_N, SCENE_INISIE_R,
};
/**
* If the current scene is a dungeon scene, this function returns an index
* indicating which one it is. Otherwise, it returns -1.
* Tests if the current scene is a dungeon scene, excluding boss scenes.
* @return -1 if not a dungeon scene, else returns the DungeonSceneIndex of the dungeon scene
*/
s32 Map_GetDungeonAreaIndex(PlayState* play) {
s32 Map_GetDungeonSceneIndexForDungeon(PlayState* play) {
static s32 sDungeonSceneIds[] = {
SCENE_MITURIN, // DUNGEON_SCENE_INDEX_WOODFALL_TEMPLE
SCENE_HAKUGIN, // DUNGEON_SCENE_INDEX_SNOWHEAD_TEMPLE
SCENE_SEA, // DUNGEON_SCENE_INDEX_GREAT_BAY_TEMPLE
SCENE_INISIE_N, // DUNGEON_SCENE_INDEX_STONE_TOWER_TEMPLE
SCENE_INISIE_R, // Play_GetOriginalSceneId converts play->sceneId to SCENE_INISIE_N, returning
// DUNGEON_SCENE_INDEX_STONE_TOWER_TEMPLE
};
s32 i;
for (i = 0; i < ARRAY_COUNT(sDungeonSceneIds); i++) {
@@ -65,28 +77,29 @@ s32 Map_GetDungeonAreaIndex(PlayState* play) {
}
/**
* Returns true if the current scene is a dungeon scene, false otherwise.
* Test if the current scene is a dungeon scene, excluding boss rooms
* @return true if the current scene is a dungeon scene, false otherwise.
*/
s32 Map_IsInDungeonArea(PlayState* play) {
if (Map_GetDungeonAreaIndex(play) == -1) {
s32 Map_IsInDungeonScene(PlayState* play) {
if (Map_GetDungeonSceneIndexForDungeon(play) == -1) {
return false;
}
return true;
}
s32 sBossSceneIds[] = {
SCENE_MITURIN_BS, // DUNGEON_INDEX_WOODFALL_TEMPLE
SCENE_HAKUGIN_BS, // DUNGEON_INDEX_SNOWHEAD_TEMPLE
SCENE_SEA_BS, // DUNGEON_INDEX_GREAT_BAY_TEMPLE
SCENE_INISIE_BS, // DUNGEON_INDEX_STONE_TOWER_TEMPLE
};
/**
* If the current scene is a boss scene, this function returns an index
* indicating which one it is. Otherwise, it returns -1.
* Tests if the current scene is a boss scene.
* @return -1 if not a boss scene, else returns the DungeonSceneIndex corresponding to that boss scene's primary dungeon
* scene
*/
s32 Map_GetBossAreaIndex(PlayState* play) {
s32 Map_GetDungeonSceneIndexForBoss(PlayState* play) {
static s32 sBossSceneIds[] = {
SCENE_MITURIN_BS, // DUNGEON_SCENE_INDEX_WOODFALL_TEMPLE
SCENE_HAKUGIN_BS, // DUNGEON_SCENE_INDEX_SNOWHEAD_TEMPLE
SCENE_SEA_BS, // DUNGEON_SCENE_INDEX_GREAT_BAY_TEMPLE
SCENE_INISIE_BS, // DUNGEON_SCENE_INDEX_STONE_TOWER_TEMPLE
};
s32 i;
for (i = 0; i < ARRAY_COUNT(sBossSceneIds); i++) {
@@ -99,36 +112,11 @@ s32 Map_GetBossAreaIndex(PlayState* play) {
}
/**
* Returns true if the current scene is a boss scene, false otherwise.
* Checks if the current scene is a boss scene.
* @return true if the current scene is a boss scene, false otherwise.
*/
s32 Map_IsInBossArea(PlayState* play) {
if (Map_GetBossAreaIndex(play) == -1) {
return false;
}
return true;
}
s32 D_801BF5A4[] = {
SCENE_22DEKUCITY,
SCENE_KOEPONARACE,
SCENE_F01,
};
s32 func_8010A238(PlayState* play) {
s32 i;
for (i = 0; i < ARRAY_COUNT(D_801BF5A4); i++) {
if (Play_GetOriginalSceneId(play->sceneId) == D_801BF5A4[i]) {
return i;
}
}
return -1;
}
s32 func_8010A2AC(PlayState* play) {
if (func_8010A238(play) == -1) {
s32 Map_IsInBossScene(PlayState* play) {
if (Map_GetDungeonSceneIndexForBoss(play) == -1) {
return false;
}
@@ -136,29 +124,65 @@ s32 func_8010A2AC(PlayState* play) {
}
/**
* When a room is loaded, this function is used to save the player's position and rotation
* so that the red arrow on the minimap can be drawn correctly.
* Intended to check if the current scene is an overworld scene with a minimap.
* The implementation is incomplete due to a complete rewrite of z_map_exp.c and other map systems, making the function
* obsolete.
* @return -1 if not in the list, else returns the MapIndex for the overworld scene
*/
void Minimap_SavePlayerRoomInitInfo(PlayState* play) {
s32 Map_GetMapIndexForOverworld(PlayState* play) {
static s32 sSceneIds[] = {
SCENE_22DEKUCITY,
SCENE_KOEPONARACE,
SCENE_F01,
};
s32 i;
for (i = 0; i < ARRAY_COUNT(sSceneIds); i++) {
if (Play_GetOriginalSceneId(play->sceneId) == sSceneIds[i]) {
return i;
}
}
return -1;
}
/**
* Intended to check if the current scene is an overworld scene with a minimap.
* The implementation is incomplete due to a complete rewrite of z_map_exp.c and other map systems, making the function
* obsolete.
* @return true if the current scene is in the set, false otherwise.
*/
s32 Map_IsInOverworldSceneWithMapIndex(PlayState* play) {
if (Map_GetMapIndexForOverworld(play) == -1) {
return false;
}
return true;
}
/**
* Sets the position and rotation of where the player has entered the area.
* Used to draw the red marker on the minimap.
*/
void Map_SetAreaEntrypoint(PlayState* play) {
Player* player = GET_PLAYER(play);
sMinimapInitPosX = player->actor.world.pos.x;
sMinimapInitPosZ = player->actor.world.pos.z;
sMinimapInitDir = (0x7FFF - player->actor.shape.rot.y) / 0x400;
sPlayerInitPosX = player->actor.world.pos.x;
sPlayerInitPosZ = player->actor.world.pos.z;
sPlayerInitDir = (0x7FFF - player->actor.shape.rot.y) / 0x400;
}
void Map_InitRoomData(PlayState* play, s16 room) {
s32 mapIndex = gSaveContext.mapIndex;
InterfaceContext* interfaceCtx = &play->interfaceCtx;
func_80105C40(room);
MapDisp_SwapRooms(room);
if (room >= 0) {
if (Map_IsInDungeonOrBossArea(play)) {
gSaveContext.save.saveInfo.permanentSceneFlags[Play_GetOriginalSceneId(play->sceneId)].rooms |=
gBitFlags[room];
if (Map_IsInDungeonOrBossScene(play)) {
SET_ROOM_VISITED(Play_GetOriginalSceneId(play->sceneId), room);
interfaceCtx->mapRoomNum = room;
interfaceCtx->dungeonOrBossAreaMapIndex = mapIndex;
interfaceCtx->dungeonSceneIndex = mapIndex;
}
} else {
interfaceCtx->mapRoomNum = 0;
@@ -170,50 +194,52 @@ void Map_InitRoomData(PlayState* play, s16 room) {
}
void Map_Destroy(PlayState* play) {
func_80105A40(play);
MapDisp_Destroy(play);
}
void Map_Init(PlayState* play) {
InterfaceContext* interfaceCtx = &play->interfaceCtx;
s32 dungeonIndex;
s32 dungeonSceneSharedIndex;
func_80105C40(play->roomCtx.curRoom.num);
MapDisp_SwapRooms(play->roomCtx.curRoom.num);
interfaceCtx->unk_278 = -1;
interfaceCtx->dungeonOrBossAreaMapIndex = -1;
interfaceCtx->dungeonSceneIndex = -1;
interfaceCtx->mapSegment = THA_AllocTailAlign16(&play->state.tha, 0x1000);
if (func_8010A2AC(play)) {
gSaveContext.mapIndex = func_8010A238(play);
//! This block does pretty much nothing, as z_map_exp.c and other map systems were heavily rewritten after OoT to no
//! longer need mapIndex to retrieve minimap data.
if (Map_IsInOverworldSceneWithMapIndex(play)) {
gSaveContext.mapIndex = Map_GetMapIndexForOverworld(play);
return;
}
if (Map_IsInDungeonOrBossArea(play)) {
dungeonIndex = Map_GetDungeonOrBossAreaIndex(play);
gSaveContext.mapIndex = dungeonIndex;
if (Map_IsInDungeonOrBossScene(play)) {
gSaveContext.mapIndex = dungeonSceneSharedIndex = Map_GetDungeonSceneIndex(play);
switch (play->sceneId) {
case SCENE_MITURIN_BS:
dungeonIndex = DUNGEON_INDEX_WOODFALL_TEMPLE;
dungeonSceneSharedIndex = DUNGEON_SCENE_INDEX_WOODFALL_TEMPLE;
break;
case SCENE_HAKUGIN_BS:
dungeonIndex = DUNGEON_INDEX_SNOWHEAD_TEMPLE;
dungeonSceneSharedIndex = DUNGEON_SCENE_INDEX_SNOWHEAD_TEMPLE;
break;
case SCENE_SEA_BS:
dungeonIndex = DUNGEON_INDEX_GREAT_BAY_TEMPLE;
dungeonSceneSharedIndex = DUNGEON_SCENE_INDEX_GREAT_BAY_TEMPLE;
break;
case SCENE_INISIE_BS:
dungeonIndex = DUNGEON_INDEX_STONE_TOWER_TEMPLE;
dungeonSceneSharedIndex = DUNGEON_SCENE_INDEX_STONE_TOWER_TEMPLE;
break;
}
gSaveContext.dungeonIndex = dungeonIndex;
gSaveContext.dungeonSceneSharedIndex = dungeonSceneSharedIndex;
Map_InitRoomData(play, play->roomCtx.curRoom.num);
}
}
void Minimap_Draw(PlayState* play) {
func_80106644(play, sMinimapInitPosX, sMinimapInitPosZ, sMinimapInitDir);
void Map_DrawMinimap(PlayState* play) {
MapDisp_DrawMinimap(play, sPlayerInitPosX, sPlayerInitPosZ, sPlayerInitDir);
}
s16 sLastRoomNum = 99;
@@ -227,7 +253,7 @@ void Map_Update(PlayState* play) {
s32 pad2;
if ((play->pauseCtx.state <= PAUSE_STATE_OPENING_2) && (CHECK_BTN_ALL(controller->press.button, BTN_L)) &&
!Play_InCsMode(play) && !func_80106530(play)) {
!Play_InCsMode(play) && !MapDisp_IsMinimapToggleBlocked(play)) {
if (!R_MINIMAP_DISABLED) {
Audio_PlaySfx(NA_SE_SY_CAMERA_ZOOM_UP);
} else {
@@ -237,22 +263,21 @@ void Map_Update(PlayState* play) {
R_MINIMAP_DISABLED ^= 1;
}
func_80105B34(play);
MapDisp_Update(play);
if (!IS_PAUSED(&play->pauseCtx)) {
if (Map_IsInDungeonArea(play)) {
floor = func_80109124(player->actor.world.pos.y);
if (Map_IsInDungeonScene(play)) {
floor = MapDisp_GetPlayerStorey(player->actor.world.pos.y);
if (floor != -1) {
gSaveContext.save.saveInfo.permanentSceneFlags[Play_GetOriginalSceneId(play->sceneId)].unk_14 |=
gBitFlags[FLOOR_INDEX_MAX - floor];
R_REVERSE_FLOOR_INDEX = FLOOR_INDEX_MAX - floor;
SET_DUNGEON_FLOOR_VISITED(Play_GetOriginalSceneId(play->sceneId), FLOOR_INDEX_MAX - floor);
R_PLAYER_FLOOR_REVERSE_INDEX = FLOOR_INDEX_MAX - floor;
if (interfaceCtx->mapRoomNum != sLastRoomNum) {
sLastRoomNum = interfaceCtx->mapRoomNum;
}
}
} else if (Map_IsInBossArea(play)) {
func_80105294();
R_REVERSE_FLOOR_INDEX = FLOOR_INDEX_MAX - func_80105318();
} else if (Map_IsInBossScene(play)) {
MapDisp_GetBossIconY();
R_PLAYER_FLOOR_REVERSE_INDEX = FLOOR_INDEX_MAX - MapDisp_GetBossRoomStorey();
}
}
}