mirror of
https://github.com/zeldaret/mm.git
synced 2026-06-26 17:51:53 -04:00
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:
+127
-102
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user