diff --git a/spec b/spec index 06fbe1e31e..bfce043991 100644 --- a/spec +++ b/spec @@ -4592,9 +4592,7 @@ beginseg name "ovl_Bg_F40_Switch" compress include "build/src/overlays/actors/ovl_Bg_F40_Switch/z_bg_f40_switch.o" - include "build/data/ovl_Bg_F40_Switch/ovl_Bg_F40_Switch.data.o" - include "build/data/ovl_Bg_F40_Switch/ovl_Bg_F40_Switch.bss.o" - include "build/data/ovl_Bg_F40_Switch/ovl_Bg_F40_Switch.reloc.o" + include "build/src/overlays/actors/ovl_Bg_F40_Switch/ovl_Bg_F40_Switch_reloc.o" endseg beginseg diff --git a/src/overlays/actors/ovl_Bg_F40_Switch/z_bg_f40_switch.c b/src/overlays/actors/ovl_Bg_F40_Switch/z_bg_f40_switch.c index 8bb351a97e..e44cb89d6b 100644 --- a/src/overlays/actors/ovl_Bg_F40_Switch/z_bg_f40_switch.c +++ b/src/overlays/actors/ovl_Bg_F40_Switch/z_bg_f40_switch.c @@ -5,6 +5,7 @@ */ #include "z_bg_f40_switch.h" +#include "objects/object_f40_switch/object_f40_switch.h" #define FLAGS (ACTOR_FLAG_10) @@ -15,13 +16,13 @@ void BgF40Switch_Destroy(Actor* thisx, GlobalContext* globalCtx); void BgF40Switch_Update(Actor* thisx, GlobalContext* globalCtx); void BgF40Switch_Draw(Actor* thisx, GlobalContext* globalCtx); -void func_80BC4B20(BgF40Switch* this, GlobalContext* globalCtx); -void func_80BC4B94(BgF40Switch* this, GlobalContext* globalCtx); -void func_80BC4BB8(BgF40Switch* this, GlobalContext* globalCtx); -void func_80BC4C68(BgF40Switch* this, GlobalContext* globalCtx); -void func_80BC4D30(BgF40Switch* this, GlobalContext* globalCtx); +void BgF40Switch_CheckAll(BgF40Switch* this, GlobalContext* globalCtx); +void BgF40Switch_Unpress(BgF40Switch* this, GlobalContext* globalCtx); +void BgF40Switch_IdlePressed(BgF40Switch* this, GlobalContext* globalCtx); +void BgF40Switch_Press(BgF40Switch* this, GlobalContext* globalCtx); +void BgF40Switch_WaitToPress(BgF40Switch* this, GlobalContext* globalCtx); +void BgF40Switch_IdleUnpressed(BgF40Switch* this, GlobalContext* globalCtx); -#if 0 const ActorInit Bg_F40_Switch_InitVars = { ACTOR_BG_F40_SWITCH, ACTORCAT_SWITCH, @@ -34,37 +35,159 @@ const ActorInit Bg_F40_Switch_InitVars = { (ActorFunc)BgF40Switch_Draw, }; -// static InitChainEntry sInitChain[] = { -static InitChainEntry D_80BC4E04[] = { +s32 sBgF40SwitchGlobalsInitialized = false; +u32 sBgF40SwitchLastUpdateFrame; + +/* + * Updates all instances of this actor in the current room, unless it's already been called this frame. + */ +void BgF40Switch_CheckAll(BgF40Switch* this, GlobalContext* globalCtx) { + if (globalCtx->gameplayFrames != sBgF40SwitchLastUpdateFrame) { + u32 pressedSwitchFlags[4] = { 0 }; + u32 pad; + s32 switchFlag; + s32 isPressed; + Actor* actor; + BgF40Switch* actorAsSwitch; + u32 inCsMode = Player_InCsMode(&globalCtx->state); + + for (actor = globalCtx->actorCtx.actorLists[ACTORCAT_SWITCH].first; actor != NULL; actor = actor->next) { + if (actor->id == ACTOR_BG_F40_SWITCH && actor->room == this->actor.actor.room && actor->update != NULL) { + actorAsSwitch = (BgF40Switch*)actor; + actorAsSwitch->wasPressed = actorAsSwitch->isPressed; + isPressed = DynaPolyActor_IsInSwitchPressedState(&actorAsSwitch->actor); + if (actorAsSwitch->isPressed && actorAsSwitch->actionFunc == BgF40Switch_IdlePressed) { + // Switch is fully pressed - if there's nothing keeping it pressed, wait a short time before + // reverting to unpressed state. + if (isPressed || inCsMode) { + actorAsSwitch->switchReleaseDelay = 6; + } else { + if (actorAsSwitch->switchReleaseDelay > 0) { + actorAsSwitch->switchReleaseDelay--; + } else { + actorAsSwitch->isPressed = isPressed; + } + } + } else { + // No delay when pressing switch, or releasing from a not-fully-pressed state. + actorAsSwitch->isPressed = isPressed; + } + if (actorAsSwitch->isPressed) { + switchFlag = BGF40SWITCH_GET_SWITCHFLAG(actorAsSwitch); + if (switchFlag >= 0 && switchFlag < 0x80) { + pressedSwitchFlags[(switchFlag & ~0x1F) >> 5] |= 1 << (switchFlag & 0x1F); + if (!actorAsSwitch->wasPressed && actorAsSwitch->actionFunc == BgF40Switch_IdleUnpressed && + !Flags_GetSwitch(globalCtx, switchFlag)) { + actorAsSwitch->isInitiator = true; + } + } + } + } + } + for (actor = globalCtx->actorCtx.actorLists[ACTORCAT_SWITCH].first; actor != NULL; actor = actor->next) { + if (actor->id == ACTOR_BG_F40_SWITCH && actor->room == this->actor.actor.room && actor->update != 0) { + switchFlag = BGF40SWITCH_GET_SWITCHFLAG((BgF40Switch*)actor); + if (switchFlag >= 0 && switchFlag < 0x80 && Flags_GetSwitch(globalCtx, switchFlag) && + !(pressedSwitchFlags[(switchFlag & ~0x1F) >> 5] & (1 << (switchFlag & 0x1F)))) { + Flags_UnsetSwitch(globalCtx, switchFlag); + } + } + } + sBgF40SwitchLastUpdateFrame = globalCtx->gameplayFrames; + } +} + +static InitChainEntry sInitChain[] = { ICHAIN_F32(uncullZoneForward, 4000, ICHAIN_CONTINUE), ICHAIN_F32(uncullZoneScale, 200, ICHAIN_CONTINUE), ICHAIN_F32(uncullZoneDownward, 200, ICHAIN_CONTINUE), ICHAIN_VEC3F_DIV1000(scale, 123, ICHAIN_STOP), }; -#endif +void BgF40Switch_Init(Actor* thisx, GlobalContext* globalCtx) { + BgF40Switch* this = THIS; -extern InitChainEntry D_80BC4E04[]; + Actor_ProcessInitChain(&this->actor.actor, sInitChain); + this->actor.actor.scale.y = 0.165f; + this->actionFunc = BgF40Switch_IdleUnpressed; + this->actor.actor.world.pos.y = this->actor.actor.home.pos.y + 1.0f; + DynaPolyActor_Init(&this->actor, 1); + DynaPolyActor_LoadMesh(globalCtx, &this->actor, &object_f40_switch_Colheader_000118); + if (!sBgF40SwitchGlobalsInitialized) { + sBgF40SwitchLastUpdateFrame = globalCtx->gameplayFrames; + sBgF40SwitchGlobalsInitialized = true; + } +} -extern UNK_TYPE D_06000118; -extern UNK_TYPE D_06000438; +void BgF40Switch_Destroy(Actor* thisx, GlobalContext* globalCtx) { + BgF40Switch* this = THIS; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_F40_Switch/func_80BC47B0.s") + DynaPoly_DeleteBgActor(globalCtx, &globalCtx->colCtx.dyna, this->actor.bgId); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_F40_Switch/BgF40Switch_Init.s") +void BgF40Switch_Unpress(BgF40Switch* this, GlobalContext* globalCtx) { + this->actor.actor.scale.y += 0.0495f; + if (this->actor.actor.scale.y >= 0.165f) { + Actor_PlaySfxAtPos(&this->actor.actor, NA_SE_EV_IKANA_BLOCK_SWITCH); + this->actionFunc = BgF40Switch_IdleUnpressed; + this->actor.actor.scale.y = 0.165f; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_F40_Switch/BgF40Switch_Destroy.s") +void BgF40Switch_IdlePressed(BgF40Switch* this, GlobalContext* globalCtx) { + if (!this->isPressed) { + this->actionFunc = BgF40Switch_Unpress; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_F40_Switch/func_80BC4B20.s") +void BgF40Switch_Press(BgF40Switch* this, GlobalContext* globalCtx) { + this->actor.actor.scale.y -= 0.0495f; + if (this->actor.actor.scale.y <= 0.0165f) { + Actor_PlaySfxAtPos(&this->actor.actor, NA_SE_EV_IKANA_BLOCK_SWITCH); + func_8013ECE0(this->actor.actor.xyzDistToPlayerSq, 120, 20, 10); + if (this->isInitiator) { + ActorCutscene_Stop(this->actor.actor.cutscene); + this->isInitiator = false; + } + this->actionFunc = BgF40Switch_IdlePressed; + this->actor.actor.scale.y = 0.0165f; + this->switchReleaseDelay = 6; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_F40_Switch/func_80BC4B94.s") +void BgF40Switch_WaitToPress(BgF40Switch* this, GlobalContext* globalCtx) { + if (!this->isInitiator || this->actor.actor.cutscene == -1) { + this->actionFunc = BgF40Switch_Press; + if (this->isInitiator) { + Flags_SetSwitch(globalCtx, BGF40SWITCH_GET_SWITCHFLAG(this)); + } + } else if (ActorCutscene_GetCanPlayNext(this->actor.actor.cutscene)) { + ActorCutscene_StartAndSetUnkLinkFields(this->actor.actor.cutscene, &this->actor.actor); + this->actionFunc = BgF40Switch_Press; + if (this->isInitiator) { + Flags_SetSwitch(globalCtx, BGF40SWITCH_GET_SWITCHFLAG(this)); + } + } else { + ActorCutscene_SetIntentToPlay(this->actor.actor.cutscene); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_F40_Switch/func_80BC4BB8.s") +void BgF40Switch_IdleUnpressed(BgF40Switch* this, GlobalContext* globalCtx) { + if (this->isPressed) { + this->actionFunc = BgF40Switch_WaitToPress; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_F40_Switch/func_80BC4C68.s") +void BgF40Switch_Update(Actor* thisx, GlobalContext* globalCtx) { + BgF40Switch* this = THIS; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_F40_Switch/func_80BC4D30.s") + BgF40Switch_CheckAll(this, globalCtx); + this->actionFunc(this, globalCtx); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_F40_Switch/BgF40Switch_Update.s") +void BgF40Switch_Draw(Actor* thisx, GlobalContext* globalCtx) { + BgF40Switch* this = THIS; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Bg_F40_Switch/BgF40Switch_Draw.s") + Gfx_DrawDListOpa(globalCtx, object_f40_switch_DL_000438); + Gfx_DrawDListOpa(globalCtx, object_f40_switch_DL_000390); +} diff --git a/src/overlays/actors/ovl_Bg_F40_Switch/z_bg_f40_switch.h b/src/overlays/actors/ovl_Bg_F40_Switch/z_bg_f40_switch.h index 8b4f2b679b..ec2b4dfeca 100644 --- a/src/overlays/actors/ovl_Bg_F40_Switch/z_bg_f40_switch.h +++ b/src/overlays/actors/ovl_Bg_F40_Switch/z_bg_f40_switch.h @@ -5,11 +5,18 @@ struct BgF40Switch; +#define BGF40SWITCH_GET_SWITCHFLAG(this) (((this)->actor.actor.params & 0xFE00) >> 9) + typedef void (*BgF40SwitchActionFunc)(struct BgF40Switch*, GlobalContext*); typedef struct BgF40Switch { - /* 0x0000 */ Actor actor; - /* 0x0144 */ char unk_144[0x20]; + /* 0x0000 */ DynaPolyActor actor; + /* 0x015C */ s16 switchReleaseDelay; // frames until a pressed switch becomes released if nothing is still pressing it + /* 0x015E */ s8 isPressed; // Logical state of the switch (pressed or unpressed). Animation state may lag behind this slightly. + /* 0x015F */ s8 wasPressed; // used as temporary during update function + // true if this switch is the one that initiated a state change; false if this switch is changing as a result of another switch tied to the same flag. + // this is a temporary flag related to something currently happening, not a permanent property of the switch. + /* 0x0160 */ s8 isInitiator; /* 0x0164 */ BgF40SwitchActionFunc actionFunc; } BgF40Switch; // size = 0x168 diff --git a/tools/disasm/functions.txt b/tools/disasm/functions.txt index 73b194c007..0205a83387 100644 --- a/tools/disasm/functions.txt +++ b/tools/disasm/functions.txt @@ -15531,14 +15531,14 @@ 0x80BC457C:("func_80BC457C",), 0x80BC458C:("BgF40Block_Update",), 0x80BC45CC:("BgF40Block_Draw",), - 0x80BC47B0:("func_80BC47B0",), + 0x80BC47B0:("BgF40Switch_CheckAll",), 0x80BC4A3C:("BgF40Switch_Init",), 0x80BC4AEC:("BgF40Switch_Destroy",), - 0x80BC4B20:("func_80BC4B20",), - 0x80BC4B94:("func_80BC4B94",), - 0x80BC4BB8:("func_80BC4BB8",), - 0x80BC4C68:("func_80BC4C68",), - 0x80BC4D30:("func_80BC4D30",), + 0x80BC4B20:("BgF40Switch_Unpress",), + 0x80BC4B94:("BgF40Switch_IdlePressed",), + 0x80BC4BB8:("BgF40Switch_Press",), + 0x80BC4C68:("BgF40Switch_WaitToPress",), + 0x80BC4D30:("BgF40Switch_IdleUnpressed",), 0x80BC4D54:("BgF40Switch_Update",), 0x80BC4D90:("BgF40Switch_Draw",), 0x80BC4F30:("EnPoComposer_Init",), diff --git a/tools/disasm/variables.txt b/tools/disasm/variables.txt index 71e653d2fd..83f8ac2e9e 100644 --- a/tools/disasm/variables.txt +++ b/tools/disasm/variables.txt @@ -15771,8 +15771,8 @@ 0x80BC4668:("D_80BC4668","UNK_TYPE1","",0x1), 0x80BC4680:("jtbl_80BC4680","UNK_PTR","",0x4), 0x80BC4DD0:("Bg_F40_Switch_InitVars","UNK_TYPE1","",0x1), - 0x80BC4DF0:("D_80BC4DF0","UNK_TYPE4","",0x4), - 0x80BC4DF4:("D_80BC4DF4","UNK_TYPE4","",0x4), + 0x80BC4DF0:("sBgF40SwitchGlobalsInitialized","s32","",0x4), + 0x80BC4DF4:("sBgF40SwitchGlobalFlags","BgF40SwitchGlobalFlags","",0x10), 0x80BC4E04:("D_80BC4E04","UNK_TYPE1","",0x1), 0x80BC4E20:("D_80BC4E20","f32","",0x4), 0x80BC4E24:("D_80BC4E24","f32","",0x4), @@ -15781,7 +15781,7 @@ 0x80BC4E30:("D_80BC4E30","f32","",0x4), 0x80BC4E34:("D_80BC4E34","f32","",0x4), 0x80BC4E38:("D_80BC4E38","f32","",0x4), - 0x80BC4F20:("D_80BC4F20","UNK_TYPE1","",0x1), + 0x80BC4F20:("sBgF40SwitchLastUpdateFrame","u32","",0x4), 0x80BC6760:("En_Po_Composer_InitVars","UNK_TYPE1","",0x1), 0x80BC6780:("D_80BC6780","UNK_TYPE1","",0x1), 0x80BC67AC:("D_80BC67AC","UNK_TYPE1","",0x1), diff --git a/undefined_syms.txt b/undefined_syms.txt index 704a352e32..f05a115c68 100644 --- a/undefined_syms.txt +++ b/undefined_syms.txt @@ -613,12 +613,6 @@ D_06004640 = 0x06004640; D_06004038 = 0x06004038; D_06004240 = 0x06004240; -// ovl_Bg_F40_Switch - -D_06000118 = 0x06000118; -D_06000390 = 0x06000390; -D_06000438 = 0x06000438; - // ovl_Bg_F40_Swlift D_06003B08 = 0x06003B08;