diff --git a/include/functions.h b/include/functions.h index 63ad4e1c1c..1f91e1cf97 100644 --- a/include/functions.h +++ b/include/functions.h @@ -815,7 +815,7 @@ UNK_TYPE4 func_800B8A1C(Actor* actor, GlobalContext* ctxt, s32 iParm3, f32 fParm // void func_800B8BD0(void); // void func_800B8BFC(void); // void func_800B8C20(void); -// void func_800B8C50(void); +void func_800B8C50(Actor* actor, GlobalContext* globalCtx); // void func_800B8C78(void); // void func_800B8C9C(void); // void func_800B8CEC(void); @@ -1654,7 +1654,7 @@ void func_800F0568(GlobalContext* ctxt, Vec3f* position, s32 param_3, s16 sfxId) void func_800F12D0(GlobalContext* ctxt); void func_800F1304(GlobalContext* ctxt, s16 param_2); void func_800F1374(s32 param_1, s16 param_2); -// void func_800F13E8(void); +s16 func_800F13E8(GlobalContext* ctxt, s16 param_2); s16 func_800F1460(s16 param_1); ActorCutscene* ActorCutscene_GetCutsceneImpl(s16 index); void ActorCutscene_Init(GlobalContext* ctxt, ActorCutscene* cutscenes, s32 num); @@ -3013,7 +3013,7 @@ void func_80167DE4(GlobalContext* ctxt); void func_80168090(GlobalContext* ctxt); void func_80168DAC(GlobalContext* ctxt); void Play_Update(GlobalContext* ctxt); -// void func_801690CC(void); +s32 func_801690CC(GlobalContext* gCtx); // void func_80169100(UNK_TYPE1 param_1, UNK_TYPE1 param_2, UNK_TYPE1 param_3, UNK_TYPE1 param_4, UNK_TYPE4 param_5); // void func_801691F0(void); void* Play_LoadScene(GlobalContext* ctxt, ObjectFileTableEntry* entry); @@ -3040,7 +3040,7 @@ void func_801699D4(GlobalContext* ctxt, s16 param_2, s16 param_3); // void convert_scene_number_among_shared_scenes(void); void func_80169D40(GlobalContext* ctxt); // void func_80169DCC(UNK_TYPE1 param_1, UNK_TYPE1 param_2, UNK_TYPE1 param_3, UNK_TYPE1 param_4, UNK_TYPE4 param_5, UNK_TYPE4 param_6, UNK_TYPE2 param_7); -// void func_80169E6C(void); +void func_80169E6C(GlobalContext* gCtx, s32 param_1, s32 param_2); // void func_80169ECC(void); // void func_80169EFC(void); // void func_80169F78(void); diff --git a/include/segment.h b/include/segment.h index ddea418e90..80367214dd 100644 --- a/include/segment.h +++ b/include/segment.h @@ -30,6 +30,7 @@ extern Gfx D_04075B30[]; extern Gfx D_04076BC0[]; extern Gfx D_04077480[]; +extern Gfx D_05000C40[]; extern Gfx D_05017EA0[]; // pot displaylist extern Gfx D_05018090[]; // pot break shard displaylist extern Gfx D_0501D980[]; diff --git a/include/z64.h b/include/z64.h index 4c7de52280..80d182faa4 100644 --- a/include/z64.h +++ b/include/z64.h @@ -329,7 +329,11 @@ typedef struct { /* 0x010 */ s32 unk10; /* 0x014 */ UNK_TYPE1 pad14[0x2E]; /* 0x042 */ s16 unk42; - /* 0x044 */ UNK_TYPE1 pad44[0x43]; + /* 0x044 */ UNK_TYPE1 pad44[0x34]; + /* 0x078 */ f32 unk78; + /* 0x07C */ UNK_TYPE1 pad7C[0x4]; + /* 0x080 */ s16 unk80; + /* 0x082 */ UNK_TYPE1 pad82[0x5]; /* 0x087 */ s8 unk87; /* 0x088 */ UNK_TYPE1 pad88[0x1EE]; /* 0x276 */ u8 unk276; @@ -1674,13 +1678,14 @@ struct GlobalContext { /* 0x18845 */ u8 unk18845; /* 0x18846 */ u16 sceneNumActorsToLoad; /* 0x18848 */ u8 numRooms; - /* 0x18849 */ UNK_TYPE1 pad18849[0x3]; + /* 0x18849 */ UNK_TYPE1 pad18849; + /* 0x1884A */ s16 unk1884A; /* 0x1884C */ RoomFileLocation* roomList; /* 0x18850 */ ActorEntry* linkActorEntry; /* 0x18854 */ ActorEntry* setupActorList; /* 0x18858 */ UNK_PTR unk18858; /* 0x1885C */ EntranceEntry* setupEntranceList; - /* 0x18860 */ void* setupExitList; + /* 0x18860 */ u16* setupExitList; /* 0x18864 */ void* setupPathList; /* 0x18868 */ UNK_PTR unk18868; /* 0x1886C */ AnimatedTexture* sceneTextureAnimations; @@ -1688,7 +1693,7 @@ struct GlobalContext { /* 0x18874 */ u8 unk18874; /* 0x18875 */ s8 unk18875; /* 0x18876 */ UNK_TYPE1 pad18876[0x4]; - /* 0x1887A */ u16 unk1887A; + /* 0x1887A */ u16 nextEntranceIndex; /* 0x1887C */ s8 unk1887C; /* 0x1887D */ UNK_TYPE1 pad1887D[0x2]; /* 0x1887F */ u8 unk1887F; diff --git a/include/z64actor.h b/include/z64actor.h index 58781a0575..ef474e3ec2 100644 --- a/include/z64actor.h +++ b/include/z64actor.h @@ -255,7 +255,9 @@ typedef struct { /* 0xADE */ u8 unkADE; /* 0xADF */ UNK_TYPE1 padADF[0x4]; /* 0xAE3 */ s8 unkAE3; - /* 0xAE4 */ UNK_TYPE1 padAE4[0x44]; + /* 0xAE4 */ UNK_TYPE1 padAE4[0x3]; + /* 0xAE7 */ s8 unkAE7; + /* 0xAE8 */ UNK_TYPE1 padAE8[0x40]; /* 0xB28 */ s16 unkB28; /* 0xB2A */ UNK_TYPE1 padB2A[0x72]; /* 0xB9C */ Vec3f unkB9C; diff --git a/linker_scripts/code_script.txt b/linker_scripts/code_script.txt index d884ea3340..22839accbb 100644 --- a/linker_scripts/code_script.txt +++ b/linker_scripts/code_script.txt @@ -1606,9 +1606,9 @@ SECTIONS ovl_Door_Ana : AT(RomLocation) { build/src/overlays/actors/ovl_Door_Ana/z_door_ana.o(.text) - build/asm/overlays/ovl_Door_Ana_data.o(.data) + build/src/overlays/actors/ovl_Door_Ana/z_door_ana.o(.data) build/src/overlays/actors/ovl_Door_Ana/z_door_ana.o(.rodata) - build/asm/overlays/ovl_Door_Ana_rodata.o(.rodata) + build/src/overlays/actors/ovl_Door_Ana/z_door_ana_overlay.o(.ovl) } SegmentEnd = .; SegmentSize = SegmentEnd - SegmentStart; diff --git a/linker_scripts/object_script.txt b/linker_scripts/object_script.txt index 6f5e676a17..37ca9a4ed3 100644 --- a/linker_scripts/object_script.txt +++ b/linker_scripts/object_script.txt @@ -31,6 +31,9 @@ D_05017EA0 = 0x05017EA0; D_0501D980 = 0x0501D980; D_050219E0 = 0x050219E0; +/* gameplay_field_keep */ +D_05000C40 = 0x05000C40; + object_ikana_obj_001100 = 0x06001100; object_ikana_obj_001228 = 0x06001228; diff --git a/src/code/z_scene.c b/src/code/z_scene.c index 496c8ca7ae..bd5b40d32a 100644 --- a/src/code/z_scene.c +++ b/src/code/z_scene.c @@ -525,7 +525,7 @@ void Scene_HeaderCommand1A(GlobalContext* ctxt, SceneCmd* entry) { } void func_801306A4(GlobalContext *ctxt) { - ctxt->unk1887F = func_801323A0(ctxt->unk1887A) & 0x7F; + ctxt->unk1887F = func_801323A0(ctxt->nextEntranceIndex) & 0x7F; } s32 Scene_ProcessHeader(GlobalContext* ctxt, SceneCmd* header) { diff --git a/src/overlays/actors/ovl_Door_Ana/z_door_ana.c b/src/overlays/actors/ovl_Door_Ana/z_door_ana.c index 1f965d1955..4e91e48bf4 100644 --- a/src/overlays/actors/ovl_Door_Ana/z_door_ana.c +++ b/src/overlays/actors/ovl_Door_Ana/z_door_ana.c @@ -9,7 +9,10 @@ void DoorAna_Destroy(Actor* thisx, GlobalContext* globalCtx); void DoorAna_Update(Actor* thisx, GlobalContext* globalCtx); void DoorAna_Draw(Actor* thisx, GlobalContext* globalCtx); -/* +void DoorAna_WaitClosed(DoorAna* this, GlobalContext* globalCtx); +void DoorAna_WaitOpen(DoorAna* this, GlobalContext* globalCtx); +void DoorAna_GrabLink(DoorAna* this, GlobalContext* globalCtx); + const ActorInit Door_Ana_InitVars = { ACTOR_DOOR_ANA, ACTORCAT_ITEMACTION, @@ -21,20 +24,168 @@ const ActorInit Door_Ana_InitVars = { (ActorFunc)DoorAna_Update, (ActorFunc)DoorAna_Draw }; -*/ -#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Door_Ana_0x808E01A0/func_808E01A0.asm") +static ColliderCylinderInit sCylinderInit = { + { COLTYPE_NONE, AT_NONE, AC_ON | AC_TYPE_PLAYER, OC1_NONE, OC2_NONE, COLSHAPE_CYLINDER, }, + { ELEMTYPE_UNK2, { 0x00000000, 0x00, 0x00 }, { 0x00000008, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_NONE, }, + { 50, 10, 0, { 0, 0, 0 } }, +}; -#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Door_Ana_0x808E01A0/DoorAna_Init.asm") +// entrances grottos can link to statically, type DOORANA_TYPE_ADJACENT uses scene exit addresses instead +static u16 entrances[] = { + 0x1A00, 0x1400, 0x1410, 0x1420, 0x1430, 0x1440, 0x1450, 0x1460, + 0x1470, 0x1480, 0x1490, 0x14A0, 0x14B0, 0x14C0, 0x14D0, +}; -#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Door_Ana_0x808E01A0/DoorAna_Destroy.asm") +void DoorAna_SetupAction(DoorAna* this, DoorAnaActionFunc actionFunction) { + this->actionFunc = actionFunction; +} -#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Door_Ana_0x808E01A0/func_808E02A4.asm") +void DoorAna_Init(Actor* thisx, GlobalContext* globalCtx) { + DoorAna* this = THIS; + s32 grottoType = GET_DOORANA_TYPE(this); + this->actor.shape.rot.y = this->actor.shape.rot.z = 0; -#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Door_Ana_0x808E01A0/func_808E03B8.asm") + if ((grottoType == DOORANA_TYPE_UNK) || (grottoType == DOORANA_TYPE_HIDDEN)) { + if (grottoType == DOORANA_TYPE_HIDDEN) { + Collider_InitAndSetCylinder(globalCtx, &this->bombCollider, &this->actor, &sCylinderInit); + } else { + this->actor.flags |= 0x10; // always update + } -#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Door_Ana_0x808E01A0/func_808E05C4.asm") + Actor_SetScale(&this->actor, 0); + DoorAna_SetupAction(this, DoorAna_WaitClosed); -#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Door_Ana_0x808E01A0/DoorAna_Update.asm") + } else { + DoorAna_SetupAction(this, DoorAna_WaitOpen); + } -#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Door_Ana_0x808E01A0/DoorAna_Draw.asm") + this->actor.targetMode = 0; +} + +void DoorAna_Destroy(Actor* thisx, GlobalContext* globalCtx) { + DoorAna* this = THIS; + s32 grottoType = GET_DOORANA_TYPE(this); + + if (grottoType == DOORANA_TYPE_HIDDEN) { + Collider_DestroyCylinder(globalCtx, &this->bombCollider); + } +} + +void DoorAna_WaitClosed(DoorAna* this, GlobalContext* globalCtx) { + s32 grottoIsOpen = 0; + u32 grottoType = GET_DOORANA_TYPE(this); + + if (grottoType == DOORANA_TYPE_UNK) { + // in OOT decomp its marked as open with storms, but does not seem to open with storms in MM + if ((this->actor.xyzDistToPlayerSq < 40000.0f) && (func_800F13E8(globalCtx, 5))) { + grottoIsOpen = 1; + this->actor.flags &= ~0x10; // always update OFF + } + + } else { + if (this->bombCollider.base.acFlags & AC_HIT) { // bomb collision + grottoIsOpen = 1; + Collider_DestroyCylinder(globalCtx, &this->bombCollider); + + } else { + Collider_UpdateCylinder(&this->actor, &this->bombCollider); + CollisionCheck_SetAC(globalCtx, &globalCtx->colCheckCtx, &this->bombCollider.base); + } + } + + if (grottoIsOpen) { + this->actor.params &= ~DOORANA_TYPE_BITRANGE; + DoorAna_SetupAction(this, DoorAna_WaitOpen); + play_sound(0x4802); // CORRECT_CHIME sfx + } + + func_800B8C50(&this->actor, globalCtx); +} + +void DoorAna_WaitOpen(DoorAna* this, GlobalContext* globalCtx) { + ActorPlayer* player = PLAYER; + s32 dooranaType = GET_DOORANA_TYPE(this); + s8 pad[4]; + s32 entranceIndex; + f32 yDist; + + if (Math_StepToF( &this->actor.scale, 0.01f, 0.001f) != 0) { + if ((this->actor.targetMode != 0) && (globalCtx->unk18875 == 0) && (globalCtx->unk18B4A == 0) && + (player->stateFlags1 & 0x80000000) && (player->unkAE7 == 0)) { + + if (dooranaType == DOORANA_TYPE_ADJACENT) { + // 300 uses scene exit addresses, not static DoorAna entrance addresses, + // eg. deku playground gets address in the NCT scene exit table + + entranceIndex = GET_DOORANA_ADJACENT_ENTRANCE(this); + globalCtx->nextEntranceIndex = globalCtx->setupExitList[entranceIndex]; + lblUnk_808E03B8: ; // required to convince compiler to not use delay slot + + } else { + // unused in vanilla, the highest params bits can directly index an address + entranceIndex = GET_DOORANA_DIRECT_ENTRANCE(this); + + func_80169E6C(globalCtx, 3, 0x4FF); + + gSaveContext.extra.unk78 = this->actor.world.pos.y; + gSaveContext.extra.unk80 = this->actor.home.rot.y; + + // save the params lower byte for En_Torch to decide what item to use in the grotto chest + gSaveContext.extra.unk87 = GET_DOORANA_ITEMFLAGS(this); + + // most grottos in the game use their zrotation as their entrance index, not params + if (DOORANA_TYPE_ROTATION_ENTRANCE(entranceIndex)) { + entranceIndex = GET_DOORANA_ROTATION_ENTRANCE(this); + } + + globalCtx->nextEntranceIndex = entrances[entranceIndex]; + } + + DoorAna_SetupAction(this, DoorAna_GrabLink); + + } else { + if ((func_801690CC(globalCtx) == 0) && ((player->stateFlags1 & 0x08800000) == 0) + && (this->actor.xzDistToPlayer <= 20.0f) + && (yDist = this->actor.yDistToPlayer, (yDist >= -50.0f)) && (yDist <= 15.0f)) { + player->stateFlags1 |= 0x80000000; + this->actor.targetMode = 1; + + } else { + this->actor.targetMode = 0; + } + } + } + + Actor_SetScale( &this->actor, this->actor.scale.x); +} + +void DoorAna_GrabLink(DoorAna* this, GlobalContext* globalCtx) { + Actor* player; + s8 pad[2]; + + if (ActorCutscene_GetCurrentIndex() != this->actor.cutscene) { + if (ActorCutscene_GetCanPlayNext(this->actor.cutscene)) { + ActorCutscene_StartAndSetUnkLinkFields(this->actor.cutscene, &this->actor); + } else { + ActorCutscene_SetIntentToPlay(this->actor.cutscene); + } + } + + if ((this->actor.yDistToPlayer <= 0.0f) && (this->actor.xzDistToPlayer > 20.0f)) { + player = PLAYER; + player->world.pos.x = (Math_SinS(this->actor.yawTowardsPlayer) * 20.0f) + this->actor.world.pos.x; + player->world.pos.z = (Math_CosS(this->actor.yawTowardsPlayer) * 20.0f) + this->actor.world.pos.z; + } +} + +void DoorAna_Update(Actor *thisx, GlobalContext *globalCtx) { + DoorAna* this = THIS; + this->actionFunc(this, globalCtx); + this->actor.shape.rot.y = func_800DFCDC(globalCtx->cameraPtrs[globalCtx->activeCamera]) + 0x8000; +} + +void DoorAna_Draw(Actor *thisx, GlobalContext *globalCtx) { + Gfx* doorAnaDL = D_05000C40; + func_800BE03C(globalCtx, doorAnaDL); +} diff --git a/src/overlays/actors/ovl_Door_Ana/z_door_ana.h b/src/overlays/actors/ovl_Door_Ana/z_door_ana.h index b307ce7fe0..df6286a69f 100644 --- a/src/overlays/actors/ovl_Door_Ana/z_door_ana.h +++ b/src/overlays/actors/ovl_Door_Ana/z_door_ana.h @@ -5,11 +5,28 @@ struct DoorAna; +typedef void (*DoorAnaActionFunc)(struct DoorAna*, GlobalContext*); + typedef struct DoorAna { /* 0x000 */ Actor actor; - /* 0x144 */ char unk_144[0x50]; + /* 0x144 */ ColliderCylinder bombCollider; + /* 0x190 */ DoorAnaActionFunc actionFunc; } DoorAna; // size = 0x194 extern const ActorInit Door_Ana_InitVars; +#define DOORANA_TYPE_REGULAR 0x000 +#define DOORANA_TYPE_UNK 0x100 +#define DOORANA_TYPE_HIDDEN 0x200 +#define DOORANA_TYPE_ADJACENT 0x300 +#define DOORANA_TYPE_BITRANGE 0x300 + +#define GET_DOORANA_TYPE(this)(this->actor.params & 0x300) + +#define DOORANA_TYPE_ROTATION_ENTRANCE(directEntrance)(directEntrance < 0) +#define GET_DOORANA_DIRECT_ENTRANCE(this) ((((this)->actor.params >> 0xC) & 0x7) - 1) +#define GET_DOORANA_ADJACENT_ENTRANCE(this) ((this)->actor.params & 0x1F) +#define GET_DOORANA_ROTATION_ENTRANCE(this) (this->actor.home.rot.z + 1) +#define GET_DOORANA_ITEMFLAGS(this) ((this)->actor.params & 0xFF) + #endif // Z_DOOR_ANA_H