diff --git a/assets/xml/overlays/ovl_En_Holl.xml b/assets/xml/overlays/ovl_En_Holl.xml new file mode 100644 index 0000000000..5679e16059 --- /dev/null +++ b/assets/xml/overlays/ovl_En_Holl.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/include/variables.h b/include/variables.h index d5bbe17ac0..0e17c2daa1 100644 --- a/include/variables.h +++ b/include/variables.h @@ -427,7 +427,7 @@ extern s801AEC84 D_801AEC84[13]; extern f32 actorMovementScale; extern f32 D_801AECF0; extern f32 D_801AECF4; -// extern UNK_TYPE1 D_801AED48; +extern s16 D_801AED48[8]; // extern UNK_TYPE4 D_801AED58; extern Color_RGBA8 actorDefaultHitColor; // extern UNK_TYPE1 D_801AED8C; diff --git a/include/z64.h b/include/z64.h index e7f8b5382e..fd85a21a4a 100644 --- a/include/z64.h +++ b/include/z64.h @@ -1553,7 +1553,7 @@ struct GlobalContext { /* 0x18780 */ void (*func_18780)(Player* player, struct GlobalContext* globalCtx); /* 0x18784 */ s32 (*damagePlayer)(struct GlobalContext* globalCtx, s32 damage); /* 0x18788 */ void (*talkWithPlayer)(struct GlobalContext* globalCtx, Actor* actor); - /* 0x1878C */ void* unk_1878C; //! @TODO: Determine function prototype + /* 0x1878C */ void (*unk_1878C)(struct GlobalContext* globalCtx); /* 0x18790 */ void* unk_18790; //! @TODO: Determine function prototype /* 0x18794 */ void* unk_18794; //! @TODO: Determine function prototype /* 0x18798 */ s32 (*setPlayerTalkAnim)(struct GlobalContext* globalCtx, void* talkAnim, s32 arg2); @@ -1580,7 +1580,7 @@ struct GlobalContext { /* 0x18874 */ u8 skyboxId; /* 0x18875 */ s8 sceneLoadFlag; // "fade_direction" /* 0x18876 */ s16 unk_18876; - /* 0x18878 */ s16 unk_18878; + /* 0x18878 */ s16 bgCoverAlpha; /* 0x1887A */ u16 nextEntranceIndex; /* 0x1887C */ s8 unk_1887C; /* 0x1887D */ s8 unk_1887D; diff --git a/spec b/spec index 4e2b6841c5..2bb275eb5c 100644 --- a/spec +++ b/spec @@ -905,8 +905,7 @@ beginseg name "ovl_En_Holl" compress include "build/src/overlays/actors/ovl_En_Holl/z_en_holl.o" - include "build/data/ovl_En_Holl/ovl_En_Holl.data.o" - include "build/data/ovl_En_Holl/ovl_En_Holl.reloc.o" + include "build/src/overlays/actors/ovl_En_Holl/ovl_En_Holl_reloc.o" endseg beginseg diff --git a/src/code/z_actor.c b/src/code/z_actor.c index b13f220436..2f12770574 100644 --- a/src/code/z_actor.c +++ b/src/code/z_actor.c @@ -457,6 +457,12 @@ f32 Actor_XZDistanceToPoint(Actor* actor, Vec3f* point) { return Math_Vec3f_DistXZ(&actor->world.pos, point); } +/** Performs the affine (linear) transformation from world coordinates to actor coordinates + * + * @param[in] actor The actor whose coordinate system to transform to. + * @param[out] offset The transformed coordinates. + * @param[in] point The point to transform to actor coordinates. + */ void Actor_CalcOffsetOrientedToDrawRotation(Actor* actor, Vec3f* offset, Vec3f* point) { f32 cos_rot_y; f32 sin_rot_y; diff --git a/src/code/z_collision_check.c b/src/code/z_collision_check.c index 5c72947d97..40ea71ee01 100644 --- a/src/code/z_collision_check.c +++ b/src/code/z_collision_check.c @@ -38,10 +38,6 @@ TriNorm D_801EF5C8; TriNorm D_801EF600; TriNorm D_801EF638; -//! @TODO: These are fake bss symbols likely related to z_message_nes -UNK_TYPE1 D_801EF66C; -UNK_TYPE1 D_801EF66D; - /** * Gets the damage and effect that should be applied for the collision between * `at` and `ac`, referring to the ac actor's damage chart if applicable. diff --git a/src/code/z_quake.c b/src/code/z_quake.c index aabca85d52..b45e023812 100644 --- a/src/code/z_quake.c +++ b/src/code/z_quake.c @@ -1,3 +1,4 @@ +#include "prevent_bss_reordering.h" #include "global.h" QuakeRequest sQuakeRequest[4]; diff --git a/src/overlays/actors/ovl_En_Holl/z_en_holl.c b/src/overlays/actors/ovl_En_Holl/z_en_holl.c index 0b7accd486..d9e6e8ea13 100644 --- a/src/overlays/actors/ovl_En_Holl/z_en_holl.c +++ b/src/overlays/actors/ovl_En_Holl/z_en_holl.c @@ -1,3 +1,42 @@ +/** @file + * File: z_en_holl.c + * Overlay: ovl_En_Holl + * Description: Loading Halls/Holes + * + * This actor has several different types, which can be thought of as a bitfield of size 3: + * bit 0 = Orientation: Horizontal (Hall) or Vertical (Hole) + * bit 1 = Alpha: TRANSPARENT (alpha=0) or VISIBLE (alpha=[0,255]) + * bit 2 = Space to Load: Room or Scene + * Note: The meaning of bit 1 is slightly different for Halls than Holes. + * For Halls, bit 1 being set indicates the actor shall not draw. + * For Holes, bit 1 being set indicates the bgCover shall be applied. + * + * There are only 5 types instead of the expected 8, because the only "Scene changer" is horizontal and visible. + * + * Halls take the shape of a rectangular box, and Holes take the shape of a circular cylinder. + * + * Each En_Holl has a number of distinct planes inside, which, when intersected with the En_Holl itself, take the shape + * of either a rectangle or a circle, respectively. Being within this rectangle or circle is necessary to achieve the + * effect of the plane. + * + * Every En_Holl has pairs of at least the first two planes below. Only Visible Room-Changing Halls get pairs of the + * last two planes. All planes are ordered from greatest to smallest distance from the central plane, which determines + * the side the player is on. + * + * @sa sActivationPlaneDistance, EN_HOLL_ACTIVATION_PLANE_DISTANCE, and EN_HOLL_ACTIVATION_PLANE_DISTANCE_VERTICAL + * @sa sLoadingPlaneDistance, EN_HOLL_LOADING_PLANE_DISTANCE, and EN_HOLL_LOADING_PLANE_DISTANCE_VERTICAL + * @sa sTranslucencyPlaneDistance + * @sa sTransparencyPlaneDistance + * + * Since, all these planes except the central plane are duplicated on either side of the actor, this means that there + * are a total of 5 (or 9 for Type 0) planes that crossing will produce an effect. The most noticeable effect is the + * room/scene loading, which has historically led to this actor being erroneously referred to as a "loading plane". + * However, the loading plane(s) are only one of many planes in the actor, which is why "loading hall/hole" is a more + * accurate name for En_Holl. A given instance can be called either a "loading hall" if it is horizontal, or a "loading + * hole" if it is vertical. It is worth noting that "Holl" is a portmanteau of "hall" and "hole", though whether that + * was the origin of the actor name or not is unknown. + */ + #include "z_en_holl.h" #define FLAGS 0x00000010 @@ -9,9 +48,15 @@ void EnHoll_Destroy(Actor* thisx, GlobalContext* globalCtx); void EnHoll_Update(Actor* thisx, GlobalContext* globalCtx); void EnHoll_Draw(Actor* thisx, GlobalContext* globalCtx); -void func_8089A330(EnHoll* this, GlobalContext* globalCtx); +void EnHoll_SetupAction(EnHoll* this); +void EnHoll_SetPlayerSide(GlobalContext* globalCtx, EnHoll* this, Vec3f* transformedPlayerPos); +void EnHoll_ChangeRooms(GlobalContext* globalCtx); +void EnHoll_VisibleIdle(EnHoll* this, GlobalContext* globalCtx); +void EnHoll_VerticalIdle(EnHoll* this, GlobalContext* globalCtx); +void EnHoll_TransparentIdle(EnHoll* this, GlobalContext* globalCtx); +void EnHoll_VerticalBgCoverIdle(EnHoll* this, GlobalContext* globalCtx); +void EnHoll_RoomTransitionIdle(EnHoll* this, GlobalContext* globalCtx); -#if 0 const ActorInit En_Holl_InitVars = { ACTOR_EN_HOLL, ACTORCAT_DOOR, @@ -24,37 +69,277 @@ const ActorInit En_Holl_InitVars = { (ActorFunc)EnHoll_Draw, }; -// static InitChainEntry sInitChain[] = { -static InitChainEntry D_8089A5D0[] = { +#include "overlays/ovl_En_Holl/ovl_En_Holl.c" + +static EnHoll* sInstancePlayingSound = NULL; + +static EnHollActionFunc sActionFuncs[] = { + EnHoll_VisibleIdle, EnHoll_VerticalIdle, EnHoll_TransparentIdle, EnHoll_VerticalBgCoverIdle, EnHoll_VisibleIdle, +}; + +static InitChainEntry sInitChain[] = { ICHAIN_F32(uncullZoneForward, 4000, ICHAIN_CONTINUE), ICHAIN_F32(uncullZoneScale, 400, ICHAIN_CONTINUE), ICHAIN_F32(uncullZoneDownward, 400, ICHAIN_STOP), }; -#endif +//! Visible Halls: Being inside this plane enables the execution of more code within the actionFunc. +static f32 sActivationPlaneDistance = 200.0f; -extern InitChainEntry D_8089A5D0[]; +//! Visible Halls: Crossing this plane will change rooms/scenes. +static f32 sLoadingPlaneDistance = 150.0f; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Holl/func_80899960.s") +//! Visible Room Halls: Being inside this plane indicates the draw function will render using POLY_XLU. +static f32 sTranslucencyPlaneDistance = 100.0f; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Holl/func_808999B0.s") +//! Visible Room Halls: Being inside this plane indicates the draw function won't render. +static f32 sTransparencyPlaneDistance = 50.0f; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Holl/EnHoll_Init.s") +void EnHoll_SetupAction(EnHoll* this) { + this->type = EN_HOLL_GET_TYPE(this); + this->actionFunc = sActionFuncs[this->type]; + if (EN_HOLL_IS_VISIBLE(this)) { + this->alpha = 255; + } else { + this->actor.draw = NULL; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Holl/EnHoll_Destroy.s") +void EnHoll_SetPlayerSide(GlobalContext* globalCtx, EnHoll* this, Vec3f* transformedPlayerPos) { + Player* player = PLAYER; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Holl/func_80899ACC.s") + Actor_CalcOffsetOrientedToDrawRotation(&this->actor, transformedPlayerPos, &player->actor.world.pos); + this->playerSide = (transformedPlayerPos->z < 0.0f) ? EN_HOLL_BEHIND : EN_HOLL_BEFORE; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Holl/func_80899B88.s") +void EnHoll_Init(Actor* thisx, GlobalContext* globalCtx) { + EnHoll* this = THIS; + s32 pad; + Vec3f transformedPlayerPos; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Holl/func_80899F30.s") + Actor_ProcessInitChain(&this->actor, sInitChain); + EnHoll_SetupAction(this); + this->bgCoverAlphaActive = false; + this->alpha = 255; + EnHoll_SetPlayerSide(globalCtx, this, &transformedPlayerPos); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Holl/func_8089A0C0.s") +void EnHoll_Destroy(Actor* thisx, GlobalContext* globalCtx) { + EnHoll* this = THIS; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Holl/func_8089A238.s") + if (!EN_HOLL_IS_SCENE_CHANGER(this)) { + u32 enHollId = EN_HOLL_GET_ID_CAST(this); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Holl/func_8089A330.s") + globalCtx->doorCtx.transitionActorList[enHollId].id = -globalCtx->doorCtx.transitionActorList[enHollId].id; + if (this == sInstancePlayingSound) { + sInstancePlayingSound = NULL; + } + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Holl/EnHoll_Update.s") +void EnHoll_ChangeRooms(GlobalContext* globalCtx) { + Room tempRoom = globalCtx->roomCtx.currRoom; + + globalCtx->roomCtx.currRoom = globalCtx->roomCtx.prevRoom; + globalCtx->roomCtx.prevRoom = tempRoom; + globalCtx->roomCtx.activeMemPage ^= 1; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Holl/EnHoll_Draw.s") +void EnHoll_VisibleIdle(EnHoll* this, GlobalContext* globalCtx) { + s32 pad; + Vec3f transformedPlayerPos; + f32 playerDistFromCentralPlane; + + if (this->type == EN_HOLL_TYPE_DEFAULT) { + u32 actorCtxBitmask = (globalCtx->actorCtx.unkC & 0x2AA) >> 1 | (globalCtx->actorCtx.unkC & 0x155); + u32 zActorBitmask = D_801AED48[EN_HOLL_GET_Z_ACTOR_BITMASK_INDEX(this)]; + + if (!(actorCtxBitmask & zActorBitmask)) { + Actor_MarkForDeath(&this->actor); + return; + } + if (this == sInstancePlayingSound) { + func_800B9010(&this->actor, NA_SE_EV_INVISIBLE_MONKEY - SFX_FLAG); + } + } + if ((globalCtx->sceneLoadFlag != 0) || (globalCtx->unk_18B4A != 0)) { + this->alpha = 255; + } else { + f32 enHollBottom = EN_HOLL_BOTTOM_DEFAULT; + f32 enHollHalfwidth = EN_HOLL_HALFWIDTH_DEFAULT; + + EnHoll_SetPlayerSide(globalCtx, this, &transformedPlayerPos); + playerDistFromCentralPlane = fabsf(transformedPlayerPos.z); + if (globalCtx->sceneNum == SCENE_IKANA) { + enHollBottom = EN_HOLL_BOTTOM_IKANA; + enHollHalfwidth = EN_HOLL_HALFWIDTH_IKANA; + } + if ((enHollBottom < transformedPlayerPos.y) && (transformedPlayerPos.y < EN_HOLL_TOP_DEFAULT) && + (fabsf(transformedPlayerPos.x) < enHollHalfwidth) && + (playerDistFromCentralPlane < sActivationPlaneDistance)) { + u32 enHollId = EN_HOLL_GET_ID_AND(this); + + if (sLoadingPlaneDistance < playerDistFromCentralPlane) { + if ((globalCtx->roomCtx.prevRoom.num >= 0) && (globalCtx->roomCtx.unk31 == 0)) { + this->actor.room = globalCtx->doorCtx.transitionActorList[enHollId].sides[this->playerSide].room; + if (globalCtx->roomCtx.prevRoom.num == this->actor.room) { + EnHoll_ChangeRooms(globalCtx); + } + func_8012EBF8(globalCtx, &globalCtx->roomCtx); + } + } else if (this->type == EN_HOLL_TYPE_SCENE_CHANGER) { + globalCtx->nextEntranceIndex = globalCtx->setupExitList[EN_HOLL_GET_EXIT_LIST_INDEX(this)]; + gSaveContext.unk_3DBB = 1; + Scene_SetExitFade(globalCtx); + globalCtx->sceneLoadFlag = 0x14; + globalCtx->unk_1878C(globalCtx); + } else { + this->actor.room = globalCtx->doorCtx.transitionActorList[enHollId].sides[this->playerSide ^ 1].room; + if (globalCtx->roomCtx.prevRoom.num < 0) { + Room_StartRoomTransition(globalCtx, &globalCtx->roomCtx, this->actor.room); + if (this == sInstancePlayingSound) { + sInstancePlayingSound = NULL; + } + } else { + s32 unclampedAlpha = EN_HOLL_SCALE_ALPHA(playerDistFromCentralPlane); + + this->alpha = CLAMP(unclampedAlpha, 0, 255); + if (globalCtx->roomCtx.currRoom.num != this->actor.room) { + EnHoll_ChangeRooms(globalCtx); + } + } + } + } else if ((this->type == EN_HOLL_TYPE_DEFAULT) && (globalCtx->sceneNum == SCENE_26SARUNOMORI) && + (sInstancePlayingSound == NULL)) { + sInstancePlayingSound = this; + } + } +} + +void EnHoll_TransparentIdle(EnHoll* this, GlobalContext* globalCtx) { + Player* player = PLAYER; + s32 useViewEye = D_801D0D50 || globalCtx->csCtx.state != 0; + Vec3f transformedPlayerPos; + f32 enHollTop; + f32 playerDistFromCentralPlane; + + Actor_CalcOffsetOrientedToDrawRotation(&this->actor, &transformedPlayerPos, + useViewEye ? &globalCtx->view.eye : &player->actor.world.pos); + enHollTop = (globalCtx->sceneNum == SCENE_PIRATE) ? EN_HOLL_TOP_PIRATE : EN_HOLL_TOP_DEFAULT; + + if ((transformedPlayerPos.y > EN_HOLL_BOTTOM_DEFAULT) && (transformedPlayerPos.y < enHollTop) && + (fabsf(transformedPlayerPos.x) < EN_HOLL_HALFWIDTH_TRANSPARENT)) { + if (playerDistFromCentralPlane = fabsf(transformedPlayerPos.z), + playerDistFromCentralPlane < EN_HOLL_ACTIVATION_PLANE_DISTANCE && + playerDistFromCentralPlane > EN_HOLL_LOADING_PLANE_DISTANCE) { + s32 enHollId = EN_HOLL_GET_ID_CAST(this); + s32 playerSide = (transformedPlayerPos.z < 0.0f) ? EN_HOLL_BEHIND : EN_HOLL_BEFORE; + TransitionActorEntry* transitionActorEntry = &globalCtx->doorCtx.transitionActorList[enHollId]; + s8 room = transitionActorEntry->sides[playerSide].room; + + this->actor.room = room; + + if ((this->actor.room != globalCtx->roomCtx.currRoom.num) && + Room_StartRoomTransition(globalCtx, &globalCtx->roomCtx, this->actor.room)) { + this->actionFunc = EnHoll_RoomTransitionIdle; + } + } + } +} + +void EnHoll_VerticalBgCoverIdle(EnHoll* this, GlobalContext* globalCtx) { + f32 playerDistFromCentralPlane; + + if ((this->actor.xzDistToPlayer < EN_HOLL_RADIUS) && + (playerDistFromCentralPlane = fabsf(this->actor.yDistToPlayer), + playerDistFromCentralPlane < EN_HOLL_ACTIVATION_PLANE_DISTANCE_VERTICAL)) { + if (playerDistFromCentralPlane < EN_HOLL_LOADING_PLANE_DISTANCE_VERTICAL) { + globalCtx->bgCoverAlpha = 255; + } else { + globalCtx->bgCoverAlpha = EN_HOLL_SCALE_BG_COVER_ALPHA(playerDistFromCentralPlane); + } + if (playerDistFromCentralPlane > EN_HOLL_LOADING_PLANE_DISTANCE_VERTICAL) { + s32 enHollId = EN_HOLL_GET_ID_CAST(this); + s32 playerSide = (this->actor.yDistToPlayer > 0.0f) ? EN_HOLL_ABOVE : EN_HOLL_BELOW; + + this->actor.room = globalCtx->doorCtx.transitionActorList[enHollId].sides[playerSide].room; + + if ((this->actor.room != globalCtx->roomCtx.currRoom.num) && + Room_StartRoomTransition(globalCtx, &globalCtx->roomCtx, this->actor.room)) { + this->actionFunc = EnHoll_RoomTransitionIdle; + this->bgCoverAlphaActive = true; + } + } + } else if (this->bgCoverAlphaActive) { + this->bgCoverAlphaActive = false; + globalCtx->bgCoverAlpha = 0; + } +} + +void EnHoll_VerticalIdle(EnHoll* this, GlobalContext* globalCtx) { + + if (this->actor.xzDistToPlayer < EN_HOLL_RADIUS) { + f32 playerDistFromCentralPlane = fabsf(this->actor.yDistToPlayer); + + if (playerDistFromCentralPlane < EN_HOLL_ACTIVATION_PLANE_DISTANCE_VERTICAL && + playerDistFromCentralPlane > EN_HOLL_LOADING_PLANE_DISTANCE_VERTICAL) { + s32 enHollId = EN_HOLL_GET_ID_CAST(this); + s32 playerSide = (this->actor.yDistToPlayer > 0.0f) ? EN_HOLL_ABOVE : EN_HOLL_BELOW; + + this->actor.room = globalCtx->doorCtx.transitionActorList[enHollId].sides[playerSide].room; + if ((this->actor.room != globalCtx->roomCtx.currRoom.num) && + Room_StartRoomTransition(globalCtx, &globalCtx->roomCtx, this->actor.room)) { + this->actionFunc = EnHoll_RoomTransitionIdle; + } + } + } +} + +void EnHoll_RoomTransitionIdle(EnHoll* this, GlobalContext* globalCtx) { + if (globalCtx->roomCtx.unk31 == 0) { + func_8012EBF8(globalCtx, &globalCtx->roomCtx); + if (globalCtx->bgCoverAlpha == 0) { + this->bgCoverAlphaActive = false; + } + EnHoll_SetupAction(this); + } +} + +void EnHoll_Update(Actor* thisx, GlobalContext* globalCtx) { + EnHoll* this = THIS; + Player* player = PLAYER; + + if ((globalCtx->sceneLoadFlag == 0) && (globalCtx->unk_18B4A == 0) && !(player->stateFlags1 & 0x200)) { + this->actionFunc(this, globalCtx); + } +} + +void EnHoll_Draw(Actor* thisx, GlobalContext* globalCtx) { + EnHoll* this = THIS; + Gfx* dl; + u32 dlIndex; + + if (this->alpha != 0) { + OPEN_DISPS(globalCtx->state.gfxCtx); + if (this->alpha == 255) { + dl = POLY_OPA_DISP; + dlIndex = 37; + } else { + dl = POLY_XLU_DISP; + dlIndex = 0; + } + dl = Gfx_CallSetupDL(dl, dlIndex); + if (this->playerSide == EN_HOLL_BEHIND) { + SysMatrix_InsertYRotation_f(M_PI, MTXMODE_APPLY); + } + gSPMatrix(dl++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gDPSetPrimColor(dl++, 0, 0, 0, 0, 0, this->alpha); + gSPDisplayList(dl++, gEnHollCentralPlaneDL); + if (this->alpha == 255) { + POLY_OPA_DISP = dl; + } else { + POLY_XLU_DISP = dl; + } + CLOSE_DISPS(globalCtx->state.gfxCtx); + } +} diff --git a/src/overlays/actors/ovl_En_Holl/z_en_holl.h b/src/overlays/actors/ovl_En_Holl/z_en_holl.h index f19a8ad142..868798bb21 100644 --- a/src/overlays/actors/ovl_En_Holl/z_en_holl.h +++ b/src/overlays/actors/ovl_En_Holl/z_en_holl.h @@ -7,12 +7,71 @@ struct EnHoll; typedef void (*EnHollActionFunc)(struct EnHoll*, GlobalContext*); +typedef enum { + /* 0 */ EN_HOLL_TYPE_DEFAULT, + /* 1 */ EN_HOLL_TYPE_VERTICAL, + /* 2 */ EN_HOLL_TYPE_TRANSPARENT, + /* 3 */ EN_HOLL_TYPE_VERTICAL_BG_COVER, + /* 4 */ EN_HOLL_TYPE_SCENE_CHANGER +} EnHollTypes; + +typedef enum { + /* 0 */ EN_HOLL_BEHIND, + /* 1 */ EN_HOLL_BEFORE +} EnHollSides; + +typedef enum { + /* 0 */ EN_HOLL_ABOVE, + /* 1 */ EN_HOLL_BELOW +} EnHollSidesVertical; + typedef struct EnHoll { - /* 0x0000 */ Actor actor; - /* 0x0144 */ char unk_144[0x4]; - /* 0x0148 */ EnHollActionFunc actionFunc; + /* 0x000 */ Actor actor; + /* 0x144 */ s8 type; + /* 0x145 */ u8 alpha; + /* 0x146 */ u8 playerSide; + /* 0x147 */ u8 bgCoverAlphaActive; + /* 0x148 */ EnHollActionFunc actionFunc; } EnHoll; // size = 0x14C +// Horizontal +#define EN_HOLL_BOTTOM_DEFAULT -50.0f +#define EN_HOLL_BOTTOM_IKANA -90.0f +#define EN_HOLL_HALFWIDTH_DEFAULT 150.0f +#define EN_HOLL_HALFWIDTH_IKANA 280.0f +#define EN_HOLL_HALFWIDTH_TRANSPARENT 200.0f +#define EN_HOLL_TOP_DEFAULT 200.0f +#define EN_HOLL_TOP_PIRATE 280.0f + +//! Transparent Halls: Being inside this plane enables the execution of more code within the actionFunc. +#define EN_HOLL_ACTIVATION_PLANE_DISTANCE 100.0f + +//! Transparent Halls: Crossing this plane will change rooms/scenes. +#define EN_HOLL_LOADING_PLANE_DISTANCE 50.0f + + +// Vertical +#define EN_HOLL_RADIUS 120.0f + +//! Holes: Being inside this plane enables the execution of more code within the actionFunc. +#define EN_HOLL_ACTIVATION_PLANE_DISTANCE_VERTICAL 200.0f + +//! Holes: Crossing this plane will change rooms/scenes. +#define EN_HOLL_LOADING_PLANE_DISTANCE_VERTICAL 50.0f + + +#define EN_HOLL_GET_ID_AND(this) ((this->actor.params & 0xFFFF) >> 10) +#define EN_HOLL_GET_ID_CAST(this) ((u16) this->actor.params >> 10) +#define EN_HOLL_GET_TYPE(this) ((this->actor.params >> 7) & 0x7) +#define EN_HOLL_GET_EXIT_LIST_INDEX(this) (this->actor.params & 0x7F) +#define EN_HOLL_GET_Z_ACTOR_BITMASK_INDEX(this) (this->actor.params & 0x7) + +#define EN_HOLL_IS_VISIBLE(this) ((this->type == EN_HOLL_TYPE_DEFAULT) || (this->type == EN_HOLL_TYPE_SCENE_CHANGER)) +#define EN_HOLL_IS_SCENE_CHANGER(this) (this->type == EN_HOLL_TYPE_SCENE_CHANGER) + +#define EN_HOLL_SCALE_ALPHA(playerDistFromCentralPlane) ((playerDistFromCentralPlane - sTransparencyPlaneDistance) * (255 / (sTranslucencyPlaneDistance - sTransparencyPlaneDistance))) +#define EN_HOLL_SCALE_BG_COVER_ALPHA(playerDistFromCentralPlane) ((EN_HOLL_ACTIVATION_PLANE_DISTANCE_VERTICAL - playerDistFromCentralPlane) * (255 / (EN_HOLL_ACTIVATION_PLANE_DISTANCE_VERTICAL - EN_HOLL_LOADING_PLANE_DISTANCE_VERTICAL))) + extern const ActorInit En_Holl_InitVars; #endif // Z_EN_HOLL_H diff --git a/tools/disasm/disasm.py b/tools/disasm/disasm.py index 3ca68261e4..1cb68106a0 100644 --- a/tools/disasm/disasm.py +++ b/tools/disasm/disasm.py @@ -91,6 +91,8 @@ def proper_name(symbol, in_data=False, is_symbol=True): # hacks if symbol == 0x809C46F0: # ovl_En_Encount4 fake symbol at the very end of the data section return variables_ast[0x809C46DC][0] + " + 0x14" + elif symbol == 0x801EF66D: # z_message_nes constant-folding stray fairy array + return variables_ast[0x801EF670][0] + f" - 0x{0x801EF670 - 0x801EF66D:X}" elif symbol == 0x80A09740: # boss_07 symbol with large addend folded into %lo return variables_ast[0x80A09A60][0] + f" - 0x{0x80A09A60 - 0x80A09740:X}" elif symbol == 0x80B80248: # bg_ikana_mirror symbol with large addend folded into %lo diff --git a/tools/disasm/functions.txt b/tools/disasm/functions.txt index 71745a5821..465d7dbbc8 100644 --- a/tools/disasm/functions.txt +++ b/tools/disasm/functions.txt @@ -5534,16 +5534,16 @@ 0x80898E74:("func_80898E74",), 0x80899024:("func_80899024",), 0x80899218:("EnPeehat_Draw",), - 0x80899960:("func_80899960",), - 0x808999B0:("func_808999B0",), + 0x80899960:("EnHoll_SetupAction",), + 0x808999B0:("EnHoll_SetPlayerSide",), 0x80899A20:("EnHoll_Init",), 0x80899A78:("EnHoll_Destroy",), - 0x80899ACC:("func_80899ACC",), - 0x80899B88:("func_80899B88",), - 0x80899F30:("func_80899F30",), - 0x8089A0C0:("func_8089A0C0",), - 0x8089A238:("func_8089A238",), - 0x8089A330:("func_8089A330",), + 0x80899ACC:("EnHoll_ChangeRooms",), + 0x80899B88:("EnHoll_VisibleIdle",), + 0x80899F30:("EnHoll_TransparentIdle",), + 0x8089A0C0:("EnHoll_VerticalBgCoverIdle",), + 0x8089A238:("EnHoll_VerticalIdle",), + 0x8089A330:("EnHoll_RoomTransitionIdle",), 0x8089A3A0:("EnHoll_Update",), 0x8089A3FC:("EnHoll_Draw",), 0x8089A6E0:("EnDinofos_Init",), diff --git a/tools/disasm/variables.txt b/tools/disasm/variables.txt index 4b2db1d179..240d885936 100644 --- a/tools/disasm/variables.txt +++ b/tools/disasm/variables.txt @@ -6423,15 +6423,15 @@ 0x80899650:("D_80899650","f32","",0x4), 0x80899654:("D_80899654","f32","",0x4), 0x8089A530:("En_Holl_InitVars","UNK_TYPE1","",0x1), - 0x8089A550:("D_8089A550","UNK_TYPE1","",0x1), - 0x8089A590:("D_8089A590","UNK_TYPE1","",0x1), - 0x8089A5B8:("D_8089A5B8","UNK_TYPE4","",0x4), - 0x8089A5BC:("D_8089A5BC","UNK_PTR","",0x4), - 0x8089A5D0:("D_8089A5D0","UNK_TYPE1","",0x1), - 0x8089A5DC:("D_8089A5DC","f32","",0x4), - 0x8089A5E0:("D_8089A5E0","f32","",0x4), - 0x8089A5E4:("D_8089A5E4","f32","",0x4), - 0x8089A5E8:("D_8089A5E8","f32","",0x4), + 0x8089A550:("gEnHollCentralPlaneVtx","UNK_TYPE1","",0x1), + 0x8089A590:("gEnHollCentralPlaneDL","UNK_TYPE1","",0x1), + 0x8089A5B8:("sInstancePlayingSound","UNK_TYPE4","",0x4), + 0x8089A5BC:("sActionFuncs","UNK_PTR","",0x4), + 0x8089A5D0:("sInitChain","UNK_TYPE1","",0x1), + 0x8089A5DC:("sActivationPlaneDistance","f32","",0x4), + 0x8089A5E0:("sLoadingPlaneDistance","f32","",0x4), + 0x8089A5E4:("sTranslucencyPlaneDistance","f32","",0x4), + 0x8089A5E8:("sTransparencyPlaneDistance","f32","",0x4), 0x8089A5F0:("D_8089A5F0","f32","",0x4), 0x8089A5F4:("D_8089A5F4","f32","",0x4), 0x8089E150:("En_Dinofos_InitVars","UNK_TYPE1","",0x1),