From c3c08e944cc9548726b73a0d699ede34ba4e1017 Mon Sep 17 00:00:00 2001 From: Tom Overton Date: Sat, 1 Oct 2022 08:14:06 -0700 Subject: [PATCH 01/10] EnWiz (Wizrobe) OK and documented, EnWizFire (Wizrobe Magic) documented, object_wiz documented (#1054) * Good start * Limb draw stuff OK * A ton more functions * func_80A477E8 OK * func_80A456A0 OK * func_80A460A4 OK * func_80A46990 OK * func_80A46414 OK * EnWiz_Update OK * func_80A45CD8 OK Co-authored-by: petrie911 * EnWiz_Draw OK * Use generated reloc and object symbols * Document object stuff related to Wizzrobe itself * Some more names * A bunch more names * Name even more stuff (sensing a pattern?) * Document damage tables and damage effects * Bunch of stuff mostly related to ghosts * Name all struct vars and functions * Fix WizFire build issue * Split up dmgFlags * Apparently it's spelled "Wizrobe" in this game * Name all assets EXCEPT the ones used by wiz_fire * Apparently, the blob is vertices * Name all remaining variables * Some function comments * (Probably) the final touches on EnWiz docs before PR * Name a ton of stuff in EnWizFire * Finish naming everything in EnWizFire * Finish documentation * Respond to Engineer's clean-up review * Respond to Anghelo's first review * Use TATL_HINT_ID enum * Enum comments for animations, and better names for some damage effects * Fix build after merging master * Respond to Elliptic's review * Define INITIAL_CUR_PLATFORM_INDEX * Drop _CUR_ from the name * Rename one of the enum values * Respond to Elliptic's WizFire review * Every switch has a default --- assets/xml/objects/object_wiz.xml | 242 ++- spec | 3 +- src/overlays/actors/ovl_En_Fz/z_en_fz.c | 4 +- src/overlays/actors/ovl_En_Wiz/z_en_wiz.c | 1607 +++++++++++++++-- src/overlays/actors/ovl_En_Wiz/z_en_wiz.h | 73 +- .../actors/ovl_En_Wiz_Brock/z_en_wiz_brock.c | 33 +- .../actors/ovl_En_Wiz_Brock/z_en_wiz_brock.h | 11 +- .../actors/ovl_En_Wiz_Fire/z_en_wiz_fire.c | 716 ++++---- .../actors/ovl_En_Wiz_Fire/z_en_wiz_fire.h | 83 +- tools/disasm/functions.txt | 72 +- tools/disasm/variables.txt | 32 +- undefined_syms.txt | 8 - 12 files changed, 2178 insertions(+), 706 deletions(-) diff --git a/assets/xml/objects/object_wiz.xml b/assets/xml/objects/object_wiz.xml index 2928083aa..51fcae3a7 100644 --- a/assets/xml/objects/object_wiz.xml +++ b/assets/xml/objects/object_wiz.xml @@ -1,102 +1,148 @@  + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spec b/spec index b4a8a6108..9ad5e4cca 100644 --- a/spec +++ b/spec @@ -2715,8 +2715,7 @@ beginseg name "ovl_En_Wiz" compress include "build/src/overlays/actors/ovl_En_Wiz/z_en_wiz.o" - include "build/data/ovl_En_Wiz/ovl_En_Wiz.data.o" - include "build/data/ovl_En_Wiz/ovl_En_Wiz.reloc.o" + include "build/src/overlays/actors/ovl_En_Wiz/ovl_En_Wiz_reloc.o" endseg beginseg diff --git a/src/overlays/actors/ovl_En_Fz/z_en_fz.c b/src/overlays/actors/ovl_En_Fz/z_en_fz.c index 198166b00..58d5a6f5f 100644 --- a/src/overlays/actors/ovl_En_Fz/z_en_fz.c +++ b/src/overlays/actors/ovl_En_Fz/z_en_fz.c @@ -241,10 +241,10 @@ void EnFz_Destroy(Actor* thisx, PlayState* play) { Collider_DestroyCylinder(play, &this->collider3); if ((this->actor.parent != NULL) && (this->unk_BC4 == 0) && (this->actor.parent->id == ACTOR_EN_WIZ) && - (this->actor.parent->update != NULL) && (((EnWiz*)this->actor.parent)->unk_448 != 0)) { + (this->actor.parent->update != NULL) && (((EnWiz*)this->actor.parent)->freezard != NULL)) { EnWiz* wiz = (EnWiz*)this->actor.parent; - wiz->unk_448 = 0; + wiz->freezard = NULL; } } diff --git a/src/overlays/actors/ovl_En_Wiz/z_en_wiz.c b/src/overlays/actors/ovl_En_Wiz/z_en_wiz.c index 82cc5f2e2..0abf1fe56 100644 --- a/src/overlays/actors/ovl_En_Wiz/z_en_wiz.c +++ b/src/overlays/actors/ovl_En_Wiz/z_en_wiz.c @@ -1,10 +1,12 @@ /* * File: z_en_wiz.c * Overlay: ovl_En_Wiz - * Description: Wizzrobe + * Description: Wizrobe */ #include "z_en_wiz.h" +#include "objects/gameplay_keep/gameplay_keep.h" +#include "overlays/actors/ovl_En_Wiz_Brock/z_en_wiz_brock.h" #define FLAGS \ (ACTOR_FLAG_1 | ACTOR_FLAG_4 | ACTOR_FLAG_10 | ACTOR_FLAG_20 | ACTOR_FLAG_1000 | ACTOR_FLAG_100000 | \ @@ -17,7 +19,67 @@ void EnWiz_Destroy(Actor* thisx, PlayState* play); void EnWiz_Update(Actor* thisx, PlayState* play); void EnWiz_Draw(Actor* thisx, PlayState* play); -#if 0 +void EnWiz_StartIntroCutscene(EnWiz* this, PlayState* play); +void EnWiz_SetupAppear(EnWiz* this, PlayState* play); +void EnWiz_Appear(EnWiz* this, PlayState* play); +void EnWiz_SetupDance(EnWiz* this); +void EnWiz_Dance(EnWiz* this, PlayState* play); +void EnWiz_SetupSecondPhaseCutscene(EnWiz* this, PlayState* play); +void EnWiz_SecondPhaseCutscene(EnWiz* this, PlayState* play); +void EnWiz_SetupWindUp(EnWiz* this); +void EnWiz_WindUp(EnWiz* this, PlayState* play); +void EnWiz_SetupAttack(EnWiz* this); +void EnWiz_Attack(EnWiz* this, PlayState* play); +void EnWiz_SetupDisappear(EnWiz* this); +void EnWiz_Disappear(EnWiz* this, PlayState* play); +void EnWiz_Damaged(EnWiz* this, PlayState* play); +void EnWiz_SetupDead(EnWiz* this); +void EnWiz_Dead(EnWiz* this, PlayState* play); + +// This number is almost-entirely arbirary, with the only requirement being +// that cannot be a valid curPlatformIndex. Any negative number, or any number +// larger than 10, would work just as well. +#define INITIAL_PLATFORM_INDEX 777 + +typedef enum { + /* 1 */ EN_WIZ_ACTION_APPEAR = 1, + /* 2 */ EN_WIZ_ACTION_RUN_BETWEEN_PLATFORMS, + /* 3 */ EN_WIZ_ACTION_DISAPPEAR, + /* 4 */ EN_WIZ_ACTION_DAMAGED, + /* 5 */ EN_WIZ_ACTION_DEAD, + /* 6 */ EN_WIZ_ACTION_BURST_INTO_FLAMES, + /* 7 */ EN_WIZ_ACTION_RUN_IN_CIRCLES, + /* 8 */ EN_WIZ_ACTION_ATTACK, + /* 9 */ EN_WIZ_ACTION_DANCE, +} EnWizAction; + +typedef enum { + /* 0 */ EN_WIZ_INTRO_CS_NOT_STARTED, + /* 1 */ EN_WIZ_INTRO_CS_CAMERA_MOVE_TO_PLATFORM, + /* 2 */ EN_WIZ_INTRO_CS_APPEAR, + /* 3 */ EN_WIZ_INTRO_CS_CAMERA_SPIN_TO_FACE_WIZROBE, + /* 4 */ EN_WIZ_INTRO_CS_WAIT_BEFORE_RUN, + /* 5 */ EN_WIZ_INTRO_CS_RUN_IN_CIRCLES, + /* 6 */ EN_WIZ_INTRO_CS_DISAPPEAR, + /* 7 */ EN_WIZ_INTRO_CS_END +} EnWizIntroCutsceneState; + +typedef enum { + /* 0 */ EN_WIZ_FIGHT_STATE_FIRST_PHASE, + /* 1 */ EN_WIZ_FIGHT_STATE_SECOND_PHASE_CUTSCENE, + /* 2 */ EN_WIZ_FIGHT_STATE_SECOND_PHASE_GHOSTS_COPY_WIZROBE, + /* 3 */ EN_WIZ_FIGHT_STATE_SECOND_PHASE_GHOSTS_RUN_AROUND, +} EnWizFightState; + +typedef enum { + /* 0 */ EN_WIZ_ANIM_IDLE, + /* 1 */ EN_WIZ_ANIM_RUN, + /* 2 */ EN_WIZ_ANIM_DANCE, + /* 3 */ EN_WIZ_ANIM_WIND_UP, + /* 4 */ EN_WIZ_ANIM_ATTACK, + /* 5 */ EN_WIZ_ANIM_DAMAGE, +} EnWizAnimation; + const ActorInit En_Wiz_InitVars = { ACTOR_EN_WIZ, ACTORCAT_ENEMY, @@ -30,199 +92,1470 @@ const ActorInit En_Wiz_InitVars = { (ActorFunc)EnWiz_Draw, }; -// static ColliderJntSphElementInit sJntSphElementsInit[10] = { -static ColliderJntSphElementInit D_80A48B50[10] = { +static ColliderJntSphElementInit sJntSphElementsInit[10] = { { - { ELEMTYPE_UNK0, { 0xF7CFFFFF, 0x00, 0x00 }, { 0x01000202, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_NONE, OCELEM_NONE, }, - { 1, { { 0, 0, 0 }, 0 }, 1 }, + { + ELEMTYPE_UNK0, + { 0xF7CFFFFF, 0x00, 0x00 }, + { 0x01000202, 0x00, 0x00 }, + TOUCH_NONE | TOUCH_SFX_NORMAL, + BUMP_NONE, + OCELEM_NONE, + }, + { WIZROBE_LIMB_PELVIS, { { 0, 0, 0 }, 0 }, 1 }, }, { - { ELEMTYPE_UNK0, { 0xF7CFFFFF, 0x00, 0x00 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_NONE, }, - { 1, { { 0, 0, 0 }, 0 }, 0 }, + { + ELEMTYPE_UNK0, + { 0xF7CFFFFF, 0x00, 0x00 }, + { 0xF7CFFFFF, 0x00, 0x00 }, + TOUCH_NONE | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_NONE, + }, + { WIZROBE_LIMB_PELVIS, { { 0, 0, 0 }, 0 }, 0 }, }, { - { ELEMTYPE_UNK0, { 0xF7CFFFFF, 0x00, 0x00 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_NONE, }, - { 1, { { 0, 0, 0 }, 0 }, 0 }, + { + ELEMTYPE_UNK0, + { 0xF7CFFFFF, 0x00, 0x00 }, + { 0xF7CFFFFF, 0x00, 0x00 }, + TOUCH_NONE | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_NONE, + }, + { WIZROBE_LIMB_PELVIS, { { 0, 0, 0 }, 0 }, 0 }, }, { - { ELEMTYPE_UNK0, { 0xF7CFFFFF, 0x00, 0x00 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_NONE, }, - { 1, { { 0, 0, 0 }, 0 }, 0 }, + { + ELEMTYPE_UNK0, + { 0xF7CFFFFF, 0x00, 0x00 }, + { 0xF7CFFFFF, 0x00, 0x00 }, + TOUCH_NONE | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_NONE, + }, + { WIZROBE_LIMB_PELVIS, { { 0, 0, 0 }, 0 }, 0 }, }, { - { ELEMTYPE_UNK0, { 0xF7CFFFFF, 0x00, 0x00 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_NONE, }, - { 1, { { 0, 0, 0 }, 0 }, 0 }, + { + ELEMTYPE_UNK0, + { 0xF7CFFFFF, 0x00, 0x00 }, + { 0xF7CFFFFF, 0x00, 0x00 }, + TOUCH_NONE | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_NONE, + }, + { WIZROBE_LIMB_PELVIS, { { 0, 0, 0 }, 0 }, 0 }, }, { - { ELEMTYPE_UNK0, { 0xF7CFFFFF, 0x00, 0x00 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_NONE, }, - { 1, { { 0, 0, 0 }, 0 }, 0 }, + { + ELEMTYPE_UNK0, + { 0xF7CFFFFF, 0x00, 0x00 }, + { 0xF7CFFFFF, 0x00, 0x00 }, + TOUCH_NONE | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_NONE, + }, + { WIZROBE_LIMB_PELVIS, { { 0, 0, 0 }, 0 }, 0 }, }, { - { ELEMTYPE_UNK0, { 0xF7CFFFFF, 0x00, 0x00 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_NONE, }, - { 1, { { 0, 0, 0 }, 0 }, 0 }, + { + ELEMTYPE_UNK0, + { 0xF7CFFFFF, 0x00, 0x00 }, + { 0xF7CFFFFF, 0x00, 0x00 }, + TOUCH_NONE | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_NONE, + }, + { WIZROBE_LIMB_PELVIS, { { 0, 0, 0 }, 0 }, 0 }, }, { - { ELEMTYPE_UNK0, { 0xF7CFFFFF, 0x00, 0x00 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_NONE, }, - { 1, { { 0, 0, 0 }, 0 }, 0 }, + { + ELEMTYPE_UNK0, + { 0xF7CFFFFF, 0x00, 0x00 }, + { 0xF7CFFFFF, 0x00, 0x00 }, + TOUCH_NONE | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_NONE, + }, + { WIZROBE_LIMB_PELVIS, { { 0, 0, 0 }, 0 }, 0 }, }, { - { ELEMTYPE_UNK0, { 0xF7CFFFFF, 0x00, 0x00 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_NONE, }, - { 1, { { 0, 0, 0 }, 0 }, 0 }, + { + ELEMTYPE_UNK0, + { 0xF7CFFFFF, 0x00, 0x00 }, + { 0xF7CFFFFF, 0x00, 0x00 }, + TOUCH_NONE | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_NONE, + }, + { WIZROBE_LIMB_PELVIS, { { 0, 0, 0 }, 0 }, 0 }, }, { - { ELEMTYPE_UNK0, { 0xF7CFFFFF, 0x00, 0x00 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_NONE, }, - { 1, { { 0, 0, 0 }, 0 }, 0 }, + { + ELEMTYPE_UNK0, + { 0xF7CFFFFF, 0x00, 0x00 }, + { 0xF7CFFFFF, 0x00, 0x00 }, + TOUCH_NONE | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_NONE, + }, + { WIZROBE_LIMB_PELVIS, { { 0, 0, 0 }, 0 }, 0 }, }, }; -// static ColliderJntSphInit sJntSphInit = { -static ColliderJntSphInit D_80A48CB8 = { - { COLTYPE_HIT2, AT_NONE, AC_ON | AC_TYPE_PLAYER, OC1_NONE, OC2_TYPE_1, COLSHAPE_JNTSPH, }, - ARRAY_COUNT(sJntSphElementsInit), D_80A48B50, // sJntSphElementsInit, +static ColliderJntSphInit sJntSphInit = { + { + COLTYPE_HIT2, + AT_NONE, + AC_ON | AC_TYPE_PLAYER, + OC1_NONE, + OC2_TYPE_1, + COLSHAPE_JNTSPH, + }, + ARRAY_COUNT(sJntSphElementsInit), + sJntSphElementsInit, }; -// static ColliderCylinderInit sCylinderInit = { -static ColliderCylinderInit D_80A48CC8 = { - { COLTYPE_NONE, AT_NONE, AC_ON | AC_TYPE_PLAYER, OC1_ON | OC1_TYPE_ALL, OC2_TYPE_1, COLSHAPE_CYLINDER, }, - { ELEMTYPE_UNK1, { 0xF7CFFFFF, 0x08, 0x04 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, }, +static ColliderCylinderInit sCylinderInit = { + { + COLTYPE_NONE, + AT_NONE, + AC_ON | AC_TYPE_PLAYER, + OC1_ON | OC1_TYPE_ALL, + OC2_TYPE_1, + COLSHAPE_CYLINDER, + }, + { + ELEMTYPE_UNK1, + { 0xF7CFFFFF, 0x08, 0x04 }, + { 0xF7CFFFFF, 0x00, 0x00 }, + TOUCH_NONE | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_ON, + }, { 35, 130, 0, { 0, 0, 0 } }, }; -// static DamageTable sDamageTable = { -static DamageTable D_80A48CF4 = { - /* Deku Nut */ DMG_ENTRY(0, 0x1), - /* Deku Stick */ DMG_ENTRY(1, 0xF), - /* Horse trample */ DMG_ENTRY(0, 0x0), - /* Explosives */ DMG_ENTRY(1, 0xF), - /* Zora boomerang */ DMG_ENTRY(1, 0xF), - /* Normal arrow */ DMG_ENTRY(1, 0xF), - /* UNK_DMG_0x06 */ DMG_ENTRY(0, 0x0), - /* Hookshot */ DMG_ENTRY(1, 0xF), - /* Goron punch */ DMG_ENTRY(1, 0xF), - /* Sword */ DMG_ENTRY(1, 0xF), - /* Goron pound */ DMG_ENTRY(3, 0xF), - /* Fire arrow */ DMG_ENTRY(1, 0x2), - /* Ice arrow */ DMG_ENTRY(2, 0x3), - /* Light arrow */ DMG_ENTRY(2, 0x4), - /* Goron spikes */ DMG_ENTRY(0, 0x0), - /* Deku spin */ DMG_ENTRY(1, 0xF), - /* Deku bubble */ DMG_ENTRY(1, 0xF), - /* Deku launch */ DMG_ENTRY(0, 0x0), - /* UNK_DMG_0x12 */ DMG_ENTRY(0, 0x1), - /* Zora barrier */ DMG_ENTRY(0, 0x0), - /* Normal shield */ DMG_ENTRY(0, 0x0), - /* Light ray */ DMG_ENTRY(0, 0x0), - /* Thrown object */ DMG_ENTRY(1, 0xF), - /* Zora punch */ DMG_ENTRY(1, 0xF), - /* Spin attack */ DMG_ENTRY(1, 0xF), - /* Sword beam */ DMG_ENTRY(0, 0x0), - /* Normal Roll */ DMG_ENTRY(0, 0x0), - /* UNK_DMG_0x1B */ DMG_ENTRY(0, 0x0), - /* UNK_DMG_0x1C */ DMG_ENTRY(0, 0x0), - /* Unblockable */ DMG_ENTRY(0, 0x0), - /* UNK_DMG_0x1E */ DMG_ENTRY(0, 0x0), - /* Powder Keg */ DMG_ENTRY(1, 0xF), +typedef enum { + /* 0x0 */ EN_WIZ_DMGEFF_IMMUNE, // Deals no damage + /* 0x1 */ EN_WIZ_DMGEFF_UNK1, // Deals no damage. Was probably originally intended for destroying ghosts. + /* 0x2 */ EN_WIZ_DMGEFF_FIRE, // Damages and sets Ice Wizrobes on fire + /* 0x3 */ EN_WIZ_DMGEFF_FREEZE, // Damages and surrounds Fire Wizrobes with ice + /* 0x4 */ EN_WIZ_DMGEFF_LIGHT_ORB, // Damages and surrounds the Wizrobe with light orbs + /* 0xF */ EN_WIZ_DMGEFF_NONE = 0xF, // Deals regular damage and has no special effect +} EnWizDamageEffect; + +static DamageTable sFireWizrobeDamageTable = { + /* Deku Nut */ DMG_ENTRY(0, EN_WIZ_DMGEFF_UNK1), + /* Deku Stick */ DMG_ENTRY(1, EN_WIZ_DMGEFF_NONE), + /* Horse trample */ DMG_ENTRY(0, EN_WIZ_DMGEFF_IMMUNE), + /* Explosives */ DMG_ENTRY(1, EN_WIZ_DMGEFF_NONE), + /* Zora boomerang */ DMG_ENTRY(1, EN_WIZ_DMGEFF_NONE), + /* Normal arrow */ DMG_ENTRY(1, EN_WIZ_DMGEFF_NONE), + /* UNK_DMG_D_06 */ DMG_ENTRY(0, EN_WIZ_DMGEFF_IMMUNE), + /* Hookshot */ DMG_ENTRY(1, EN_WIZ_DMGEFF_NONE), + /* Goron punch */ DMG_ENTRY(1, EN_WIZ_DMGEFF_NONE), + /* Sword */ DMG_ENTRY(1, EN_WIZ_DMGEFF_NONE), + /* Goron pound */ DMG_ENTRY(3, EN_WIZ_DMGEFF_NONE), + /* Fire arrow */ DMG_ENTRY(1, EN_WIZ_DMGEFF_FIRE), + /* Ice arrow */ DMG_ENTRY(2, EN_WIZ_DMGEFF_FREEZE), + /* Light arrow */ DMG_ENTRY(2, EN_WIZ_DMGEFF_LIGHT_ORB), + /* Goron spikes */ DMG_ENTRY(0, EN_WIZ_DMGEFF_IMMUNE), + /* Deku spin */ DMG_ENTRY(1, EN_WIZ_DMGEFF_NONE), + /* Deku bubble */ DMG_ENTRY(1, EN_WIZ_DMGEFF_NONE), + /* Deku launch */ DMG_ENTRY(0, EN_WIZ_DMGEFF_IMMUNE), + /* UNK_DMG_0x12 */ DMG_ENTRY(0, EN_WIZ_DMGEFF_UNK1), + /* Zora barrier */ DMG_ENTRY(0, EN_WIZ_DMGEFF_IMMUNE), + /* Normal shield */ DMG_ENTRY(0, EN_WIZ_DMGEFF_IMMUNE), + /* Light ray */ DMG_ENTRY(0, EN_WIZ_DMGEFF_IMMUNE), + /* Thrown object */ DMG_ENTRY(1, EN_WIZ_DMGEFF_NONE), + /* Zora punch */ DMG_ENTRY(1, EN_WIZ_DMGEFF_NONE), + /* Spin attack */ DMG_ENTRY(1, EN_WIZ_DMGEFF_NONE), + /* Sword beam */ DMG_ENTRY(0, EN_WIZ_DMGEFF_IMMUNE), + /* Normal Roll */ DMG_ENTRY(0, EN_WIZ_DMGEFF_IMMUNE), + /* UNK_DMG_0x1B */ DMG_ENTRY(0, EN_WIZ_DMGEFF_IMMUNE), + /* UNK_DMG_0x1C */ DMG_ENTRY(0, EN_WIZ_DMGEFF_IMMUNE), + /* Unblockable */ DMG_ENTRY(0, EN_WIZ_DMGEFF_IMMUNE), + /* UNK_DMG_0x1E */ DMG_ENTRY(0, EN_WIZ_DMGEFF_IMMUNE), + /* Powder Keg */ DMG_ENTRY(1, EN_WIZ_DMGEFF_NONE), }; -// static DamageTable sDamageTable = { -static DamageTable D_80A48D14 = { - /* Deku Nut */ DMG_ENTRY(0, 0x1), - /* Deku Stick */ DMG_ENTRY(1, 0xF), - /* Horse trample */ DMG_ENTRY(0, 0x0), - /* Explosives */ DMG_ENTRY(1, 0xF), - /* Zora boomerang */ DMG_ENTRY(1, 0xF), - /* Normal arrow */ DMG_ENTRY(1, 0xF), - /* UNK_DMG_0x06 */ DMG_ENTRY(0, 0x0), - /* Hookshot */ DMG_ENTRY(1, 0xF), - /* Goron punch */ DMG_ENTRY(2, 0xF), - /* Sword */ DMG_ENTRY(1, 0xF), - /* Goron pound */ DMG_ENTRY(3, 0xF), - /* Fire arrow */ DMG_ENTRY(2, 0x2), - /* Ice arrow */ DMG_ENTRY(1, 0x3), - /* Light arrow */ DMG_ENTRY(2, 0x4), - /* Goron spikes */ DMG_ENTRY(0, 0x0), - /* Deku spin */ DMG_ENTRY(1, 0xF), - /* Deku bubble */ DMG_ENTRY(1, 0xF), - /* Deku launch */ DMG_ENTRY(0, 0x0), - /* UNK_DMG_0x12 */ DMG_ENTRY(0, 0x1), - /* Zora barrier */ DMG_ENTRY(0, 0x0), - /* Normal shield */ DMG_ENTRY(0, 0x0), - /* Light ray */ DMG_ENTRY(0, 0x0), - /* Thrown object */ DMG_ENTRY(1, 0xF), - /* Zora punch */ DMG_ENTRY(1, 0xF), - /* Spin attack */ DMG_ENTRY(1, 0xF), - /* Sword beam */ DMG_ENTRY(0, 0x0), - /* Normal Roll */ DMG_ENTRY(0, 0x0), - /* UNK_DMG_0x1B */ DMG_ENTRY(0, 0x0), - /* UNK_DMG_0x1C */ DMG_ENTRY(0, 0x0), - /* Unblockable */ DMG_ENTRY(0, 0x0), - /* UNK_DMG_0x1E */ DMG_ENTRY(0, 0x0), - /* Powder Keg */ DMG_ENTRY(1, 0xF), +static DamageTable sIceWizrobeDamageTable = { + /* Deku Nut */ DMG_ENTRY(0, EN_WIZ_DMGEFF_UNK1), + /* Deku Stick */ DMG_ENTRY(1, EN_WIZ_DMGEFF_NONE), + /* Horse trample */ DMG_ENTRY(0, EN_WIZ_DMGEFF_IMMUNE), + /* Explosives */ DMG_ENTRY(1, EN_WIZ_DMGEFF_NONE), + /* Zora boomerang */ DMG_ENTRY(1, EN_WIZ_DMGEFF_NONE), + /* Normal arrow */ DMG_ENTRY(1, EN_WIZ_DMGEFF_NONE), + /* UNK_DMG_D_06 */ DMG_ENTRY(0, EN_WIZ_DMGEFF_IMMUNE), + /* Hookshot */ DMG_ENTRY(1, EN_WIZ_DMGEFF_NONE), + /* Goron punch */ DMG_ENTRY(2, EN_WIZ_DMGEFF_NONE), + /* Sword */ DMG_ENTRY(1, EN_WIZ_DMGEFF_NONE), + /* Goron pound */ DMG_ENTRY(3, EN_WIZ_DMGEFF_NONE), + /* Fire arrow */ DMG_ENTRY(2, EN_WIZ_DMGEFF_FIRE), + /* Ice arrow */ DMG_ENTRY(1, EN_WIZ_DMGEFF_FREEZE), + /* Light arrow */ DMG_ENTRY(2, EN_WIZ_DMGEFF_LIGHT_ORB), + /* Goron spikes */ DMG_ENTRY(0, EN_WIZ_DMGEFF_IMMUNE), + /* Deku spin */ DMG_ENTRY(1, EN_WIZ_DMGEFF_NONE), + /* Deku bubble */ DMG_ENTRY(1, EN_WIZ_DMGEFF_NONE), + /* Deku launch */ DMG_ENTRY(0, EN_WIZ_DMGEFF_IMMUNE), + /* UNK_DMG_0x12 */ DMG_ENTRY(0, EN_WIZ_DMGEFF_UNK1), + /* Zora barrier */ DMG_ENTRY(0, EN_WIZ_DMGEFF_IMMUNE), + /* Normal shield */ DMG_ENTRY(0, EN_WIZ_DMGEFF_IMMUNE), + /* Light ray */ DMG_ENTRY(0, EN_WIZ_DMGEFF_IMMUNE), + /* Thrown object */ DMG_ENTRY(1, EN_WIZ_DMGEFF_NONE), + /* Zora punch */ DMG_ENTRY(1, EN_WIZ_DMGEFF_NONE), + /* Spin attack */ DMG_ENTRY(1, EN_WIZ_DMGEFF_NONE), + /* Sword beam */ DMG_ENTRY(0, EN_WIZ_DMGEFF_IMMUNE), + /* Normal Roll */ DMG_ENTRY(0, EN_WIZ_DMGEFF_IMMUNE), + /* UNK_DMG_0x1B */ DMG_ENTRY(0, EN_WIZ_DMGEFF_IMMUNE), + /* UNK_DMG_0x1C */ DMG_ENTRY(0, EN_WIZ_DMGEFF_IMMUNE), + /* Unblockable */ DMG_ENTRY(0, EN_WIZ_DMGEFF_IMMUNE), + /* UNK_DMG_0x1E */ DMG_ENTRY(0, EN_WIZ_DMGEFF_IMMUNE), + /* Powder Keg */ DMG_ENTRY(1, EN_WIZ_DMGEFF_NONE), }; -#endif +void EnWiz_Init(Actor* thisx, PlayState* play) { + s32 pad; + EnWiz* this = THIS; -extern ColliderJntSphElementInit D_80A48B50[10]; -extern ColliderJntSphInit D_80A48CB8; -extern ColliderCylinderInit D_80A48CC8; -extern DamageTable D_80A48CF4; -extern DamageTable D_80A48D14; + SkelAnime_InitFlex(play, &this->skelAnime, &gWizrobeSkel, &gWizrobeIdleAnim, this->jointTable, this->morphTable, + WIZROBE_LIMB_MAX); + SkelAnime_InitFlex(play, &this->ghostSkelAnime, &gWizrobeSkel, &gWizrobeIdleAnim, this->ghostBaseJointTable, + this->ghostMorphTable, WIZROBE_LIMB_MAX); + Actor_SetScale(&this->actor, 0.0f); + this->platformLightAlpha = 0; + this->alpha = 255; + this->actor.colChkInfo.mass = MASS_IMMOVABLE; + this->actor.targetMode = 3; + this->unk_450 = 1.0f; + this->actor.shape.yOffset = 700.0f; + Collider_InitAndSetJntSph(play, &this->ghostColliders, &this->actor, &sJntSphInit, this->ghostColliderElements); + Collider_InitAndSetCylinder(play, &this->collider, &this->actor, &sCylinderInit); + this->staffFlameScroll = Rand_S16Offset(0, 7); + this->switchFlag = EN_WIZ_GET_SWITCHFLAG(&this->actor); + this->type = EN_WIZ_GET_TYPE(&this->actor); -extern UNK_TYPE D_0600211C; -extern UNK_TYPE D_060025F0; -extern UNK_TYPE D_060066C0; + if (this->switchFlag == 0x7F) { + this->switchFlag = -1; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz/EnWiz_Init.s") + if ((this->type == EN_WIZ_TYPE_FIRE) || (this->type == EN_WIZ_TYPE_FIRE_NO_BGM)) { + this->actor.colChkInfo.damageTable = &sFireWizrobeDamageTable; + this->actor.colChkInfo.health = 8; + this->actor.flags &= ~ACTOR_FLAG_100000; + } else { + this->actor.colChkInfo.damageTable = &sIceWizrobeDamageTable; + this->actor.colChkInfo.health = 6; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz/EnWiz_Destroy.s") + if ((this->switchFlag >= 0) && (Flags_GetSwitch(play, this->switchFlag))) { + Actor_MarkForDeath(&this->actor); + return; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz/func_80A455C4.s") + this->actor.hintId = TATL_HINT_ID_WIZROBE; + this->curPlatformIndex = INITIAL_PLATFORM_INDEX; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz/func_80A456A0.s") + // Setting the radius and scale to zero here effectively disables all of the ghost colliders. + this->ghostColliders.elements[0].dim.modelSphere.radius = 0; + this->ghostColliders.elements[0].dim.scale = 0.0f; + this->ghostColliders.elements[0].dim.modelSphere.center.x = 0; + this->ghostColliders.elements[0].dim.modelSphere.center.y = 0; + this->ghostColliders.elements[0].dim.modelSphere.center.z = 0; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz/func_80A45CD8.s") + this->actionFunc = EnWiz_StartIntroCutscene; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz/func_80A460A4.s") +void EnWiz_Destroy(Actor* thisx, PlayState* play) { + s32 pad; + EnWiz* this = THIS; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz/func_80A46280.s") + Collider_DestroyCylinder(play, &this->collider); + Collider_DestroyJntSph(play, &this->ghostColliders); + if (this->type != EN_WIZ_TYPE_FIRE_NO_BGM) { + Audio_RestorePrevBgm(); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz/func_80A462F8.s") +static AnimationHeader* sAnimations[] = { + &gWizrobeIdleAnim, // EN_WIZ_ANIM_IDLE + &gWizrobeRunAnim, // EN_WIZ_ANIM_RUN + &gWizrobeDanceAnim, // EN_WIZ_ANIM_DANCE + &gWizrobeWindUpAnim, // EN_WIZ_ANIM_WIND_UP + &gWizrobeAttackAnim, // EN_WIZ_ANIM_ATTACK + &gWizrobeDamageAnim, // EN_WIZ_ANIM_DAMAGE +}; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz/func_80A46414.s") +static u8 sAnimationModes[] = { + ANIMMODE_LOOP, // EN_WIZ_ANIM_IDLE + ANIMMODE_LOOP, // EN_WIZ_ANIM_RUN + ANIMMODE_LOOP, // EN_WIZ_ANIM_DANCE + ANIMMODE_LOOP, // EN_WIZ_ANIM_WIND_UP + ANIMMODE_LOOP, // EN_WIZ_ANIM_ATTACK + ANIMMODE_ONCE, // EN_WIZ_ANIM_DAMAGE +}; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz/func_80A4668C.s") +void EnWiz_ChangeAnim(EnWiz* this, s32 animIndex, s32 updateGhostAnim) { + this->endFrame = Animation_GetLastFrame(sAnimations[animIndex]); + Animation_Change(&this->skelAnime, sAnimations[animIndex], 1.0f, 0.0f, this->endFrame, sAnimationModes[animIndex], + -2.0f); + if (updateGhostAnim) { + Animation_Change(&this->ghostSkelAnime, sAnimations[animIndex], 1.0f, 0.0f, this->endFrame, + sAnimationModes[animIndex], -2.0f); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz/func_80A46764.s") +/** + * Responsible for moving the camera around and making the Wizrobe run in circles during the intro cutscene. + */ +void EnWiz_HandleIntroCutscene(EnWiz* this, PlayState* play) { + Camera* subCam; + Vec3f eyeNext; + Vec3f atNext; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz/func_80A468CC.s") + if (this->introCutsceneState < EN_WIZ_INTRO_CS_DISAPPEAR) { + subCam = Play_GetCamera(play, this->subCamId); + switch (this->introCutsceneState) { + case EN_WIZ_INTRO_CS_NOT_STARTED: + this->introCutsceneTimer = 100; + this->introCutsceneCameraAngle = this->actor.world.rot.y; + this->introCutsceneState++; + break; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz/func_80A46990.s") + case EN_WIZ_INTRO_CS_CAMERA_MOVE_TO_PLATFORM: + Math_Vec3f_Copy(&eyeNext, &this->actor.world.pos); + Math_Vec3f_Copy(&atNext, &this->actor.world.pos); + eyeNext.x += Math_SinS(this->introCutsceneCameraAngle) * 200.0f; + eyeNext.y += 100.0f; + eyeNext.z += Math_CosS(this->introCutsceneCameraAngle) * 200.0f; + atNext.y += 80.0f; + Math_ApproachF(&subCam->eye.x, eyeNext.x, 0.3f, 30.0f); + Math_ApproachF(&subCam->eye.z, eyeNext.z, 0.3f, 30.0f); + Math_ApproachF(&subCam->at.x, atNext.x, 0.3f, 30.0f); + Math_ApproachF(&subCam->at.z, atNext.z, 0.3f, 30.0f); + subCam->eye.y = eyeNext.y; + subCam->at.y = atNext.y; + if ((fabsf(subCam->eye.x - eyeNext.x) < 2.0f) && (fabsf(subCam->eye.y - eyeNext.y) < 2.0f) && + (fabsf(subCam->eye.z - eyeNext.z) < 2.0f) && (fabsf(subCam->at.x - atNext.x) < 2.0f) && + (fabsf(subCam->at.y - atNext.y) < 2.0f) && (fabsf(subCam->at.z - atNext.z) < 2.0f)) { + Player* player = GET_PLAYER(play); + s32 i; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz/func_80A46C88.s") + this->actor.world.rot.y = this->actor.shape.rot.y = + Math_Vec3f_Yaw(&this->actor.world.pos, &player->actor.world.pos); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz/func_80A46CC4.s") + for (i = 0; i < this->platformCount; i++) { + this->ghostRot[i].y = Math_Vec3f_Yaw(&this->ghostPos[i], &player->actor.world.pos); + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz/func_80A46DDC.s") + EnWiz_ChangeAnim(this, EN_WIZ_ANIM_IDLE, true); + this->shouldStartTimer = false; + this->targetPlatformLightAlpha = 255; + Math_Vec3f_Copy(&this->platformLightPos, &this->actor.world.pos); + if (this->fightState == EN_WIZ_FIGHT_STATE_FIRST_PHASE) { + Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_WIZ_UNARI); + } else { + Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_WIZ_VOICE - SFX_FLAG); + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz/func_80A46E24.s") + this->introCutsceneTimer = 40; + this->introCutsceneState++; + } + break; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz/func_80A47000.s") + case EN_WIZ_INTRO_CS_APPEAR: + if (this->introCutsceneTimer == 0) { + this->introCutsceneTimer = 20; + this->introCutsceneState++; + } + break; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz/func_80A470D8.s") + case EN_WIZ_INTRO_CS_CAMERA_SPIN_TO_FACE_WIZROBE: + Math_Vec3f_Copy(&eyeNext, &this->actor.world.pos); + Math_Vec3f_Copy(&atNext, &this->actor.world.pos); + eyeNext.x += Math_SinS(this->actor.world.rot.y) * 160.0f; + eyeNext.y += 70.0f; + eyeNext.z += Math_CosS(this->actor.world.rot.y) * 140.0f; + atNext.x += -10.0f; + atNext.y += 100.0f; + Math_ApproachF(&subCam->eye.x, eyeNext.x, 0.3f, 30.0f); + Math_ApproachF(&subCam->eye.z, eyeNext.z, 0.3f, 30.0f); + Math_ApproachF(&subCam->at.x, atNext.x, 0.3f, 30.0f); + Math_ApproachF(&subCam->at.z, atNext.z, 0.3f, 30.0f); + subCam->eye.y = eyeNext.y; + subCam->at.y = atNext.y; + if (this->introCutsceneTimer == 0) { + this->introCutsceneTimer = 10; + this->introCutsceneState++; + this->introCutsceneCameraAngle = this->actor.world.rot.y; + } + break; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz/func_80A47298.s") + case EN_WIZ_INTRO_CS_WAIT_BEFORE_RUN: + if (this->introCutsceneTimer == 0) { + EnWiz_ChangeAnim(this, EN_WIZ_ANIM_RUN, false); + this->rotationalVelocity = 0; + this->introCutsceneTimer = 34; + this->introCutsceneState++; + } + break; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz/func_80A473B8.s") + case EN_WIZ_INTRO_CS_RUN_IN_CIRCLES: + Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_WIZ_RUN - SFX_FLAG); + if (this->introCutsceneTimer == 0) { + this->animLoopCounter = this->introCutsceneCameraAngle = 0; + this->introCutsceneState = EN_WIZ_INTRO_CS_DISAPPEAR; + } else { + Math_SmoothStepToS(&this->rotationalVelocity, 0x1388, 0x64, 0x3E8, 0x3E8); + this->actor.world.rot.y += this->rotationalVelocity; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz/func_80A4767C.s") + Math_Vec3f_Copy(&eyeNext, &this->actor.world.pos); + Math_Vec3f_Copy(&atNext, &this->actor.world.pos); + eyeNext.x += Math_SinS(this->introCutsceneCameraAngle) * 200.0f; + eyeNext.y += 100.0f; + eyeNext.z += Math_CosS(this->introCutsceneCameraAngle) * 200.0f; + atNext.y += 80.0f; + Math_ApproachF(&subCam->eye.x, eyeNext.x, 0.3f, 30.0f); + Math_ApproachF(&subCam->eye.z, eyeNext.z, 0.3f, 30.0f); + Math_ApproachF(&subCam->at.x, atNext.x, 0.3f, 30.0f); + Math_ApproachF(&subCam->at.z, atNext.z, 0.3f, 30.0f); + subCam->eye.y = eyeNext.y; + subCam->at.y = atNext.y; + break; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz/func_80A476C8.s") + default: + break; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz/func_80A477E8.s") + if (this->musicStartTimer < 11) { + this->musicStartTimer++; + if ((this->type != EN_WIZ_TYPE_FIRE_NO_BGM) && (this->musicStartTimer == 11)) { + Audio_PlayBgm_StorePrevBgm(NA_BGM_MINI_BOSS); + } + } + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz/EnWiz_Update.s") +/** + * Chooses which platform the Wizrobe should appear at, and updates its position accordingly. + * It also updates the position and alpha of all the ghosts. + */ +void EnWiz_SelectPlatform(EnWiz* this, PlayState* play) { + Actor* prop; + s32 i; + s32 j; + s16 ghostAlpha; + s16 type; + s16 curPlatformIndex; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz/func_80A47FCC.s") + for (i = 0; i < ARRAY_COUNT(this->platforms); i++) { + this->platforms[i] = NULL; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz/func_80A48138.s") + prop = play->actorCtx.actorLists[ACTORCAT_PROP].first; + i = 0; + while (prop != NULL) { + if (prop->id != ACTOR_EN_WIZ_BROCK) { + prop = prop->next; + continue; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz/EnWiz_Draw.s") + this->platforms[i] = prop; + i++; + if (this->action != EN_WIZ_ACTION_BURST_INTO_FLAMES) { + type = this->type; + if (type == EN_WIZ_TYPE_FIRE_NO_BGM) { + type = EN_WIZ_TYPE_FIRE; + } + + prop->colChkInfo.health = type + EN_WIZ_BROCK_PLATFORM_TYPE_FIRE; + prop = prop->next; + } else { + prop->colChkInfo.health = EN_WIZ_BROCK_PLATFORM_TYPE_INACTIVE; + prop = prop->next; + } + } + + if (this->action != EN_WIZ_ACTION_DEAD) { + this->platformCount = i; + if (i < 0) { + i = 0; + } else if (this->platformCount > 10) { + this->platformCount = 10; + } + + curPlatformIndex = Rand_ZeroFloat(i); + while ((this->curPlatformIndex == curPlatformIndex) || ((s16)i == curPlatformIndex)) { + curPlatformIndex = Rand_ZeroFloat(i); + if (1) {} + } + + this->curPlatformIndex = curPlatformIndex; + switch (this->fightState) { + case EN_WIZ_FIGHT_STATE_FIRST_PHASE: + Math_Vec3f_Copy(&this->actor.world.pos, &this->platforms[curPlatformIndex]->world.pos); + break; + + case EN_WIZ_FIGHT_STATE_SECOND_PHASE_CUTSCENE: + Math_Vec3f_Copy(&this->actor.world.pos, &this->platforms[0]->world.pos); + for (i = 0, ghostAlpha = 128; i < this->platformCount; i++, ghostAlpha -= 10) { + Math_Vec3f_Copy(&this->ghostPos[i], &this->actor.world.pos); + this->ghostAlpha[i] = ghostAlpha; + } + break; + + default: + Math_Vec3f_Copy(&this->actor.world.pos, &this->platforms[curPlatformIndex]->world.pos); + for (i--; i >= 0; i--) { + if (curPlatformIndex != i) { + Math_Vec3f_Copy(&this->ghostPos[i], &this->platforms[i]->world.pos); + this->ghostRot[i] = this->actor.world.rot; + this->ghostAlpha[i] = 100; + this->ghostNextPlatformIndex[i] = i; + for (j = 0; j < ARRAY_COUNT(this->jointTable); j++) { + this->ghostJointTables[i][j] = this->jointTable[j]; + } + } else { + Math_Vec3f_Copy(&this->ghostPos[i], &gZeroVec3f); + } + } + break; + } + } +} + +/** + * Makes the ghosts run around the room from platform to platform. + */ +void EnWiz_MoveGhosts(EnWiz* this) { + s32 i; + s32 ghostNextPlatformIndex; + s32 playSfx = false; + + for (i = 0; i < this->platformCount; i++) { + if (this->ghostPos[i].x != 0.0f && this->ghostPos[i].z != 0.0f) { + f32 diffX; + f32 diffZ; + + ghostNextPlatformIndex = this->ghostNextPlatformIndex[i]; + diffX = this->platforms[ghostNextPlatformIndex]->world.pos.x - this->ghostPos[i].x; + diffZ = this->platforms[ghostNextPlatformIndex]->world.pos.z - this->ghostPos[i].z; + playSfx++; + + if (sqrtf(SQ(diffX) + SQ(diffZ)) < 30.0f) { + this->ghostNextPlatformIndex[i]--; + if (this->ghostNextPlatformIndex[i] < 0) { + this->ghostNextPlatformIndex[i] = this->platformCount - 1; + } + } + + ghostNextPlatformIndex = this->ghostNextPlatformIndex[i]; + Math_ApproachF(&this->ghostPos[i].x, this->platforms[ghostNextPlatformIndex]->world.pos.x, 0.3f, 30.0f); + Math_ApproachF(&this->ghostPos[i].y, this->platforms[ghostNextPlatformIndex]->world.pos.y, 0.3f, 30.0f); + Math_ApproachF(&this->ghostPos[i].z, this->platforms[ghostNextPlatformIndex]->world.pos.z, 0.3f, 30.0f); + this->ghostRot[i].y = + Math_Vec3f_Yaw(&this->ghostPos[i], &this->platforms[ghostNextPlatformIndex]->world.pos); + } + } + + if (playSfx) { + Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_WIZ_RUN - SFX_FLAG); + } +} + +void EnWiz_StartIntroCutscene(EnWiz* this, PlayState* play) { + if (ActorCutscene_GetCanPlayNext(this->actor.cutscene)) { + ActorCutscene_StartAndSetFlag(this->actor.cutscene, &this->actor); + this->subCamId = ActorCutscene_GetCurrentSubCamId(this->actor.cutscene); + this->actor.flags |= ACTOR_FLAG_100000; + EnWiz_SetupAppear(this, play); + } else { + ActorCutscene_SetIntentToPlay(this->actor.cutscene); + } +} + +void EnWiz_SetupAppear(EnWiz* this, PlayState* play) { + Player* player = GET_PLAYER(play); + s32 i; + s16 angle; + + this->action = EN_WIZ_ACTION_APPEAR; + + if (this->timer == 0) { + EnWiz_SelectPlatform(this, play); + + if (this->introCutsceneState != EN_WIZ_INTRO_CS_NOT_STARTED) { + angle = Math_Vec3f_Yaw(&this->actor.world.pos, &player->actor.world.pos); + this->actor.shape.rot.y = angle; + this->actor.world.rot.y = angle; + for (i = 0; i < this->platformCount; i++) { + this->ghostRot[i].y = Math_Vec3f_Yaw(&this->ghostPos[i], &player->actor.world.pos); + } + + EnWiz_ChangeAnim(this, EN_WIZ_ANIM_IDLE, true); + this->shouldStartTimer = false; + this->targetPlatformLightAlpha = 255; + Math_Vec3f_Copy(&this->platformLightPos, &this->actor.world.pos); + + if (this->fightState == EN_WIZ_FIGHT_STATE_FIRST_PHASE) { + Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_WIZ_UNARI); + } else { + Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_WIZ_VOICE - SFX_FLAG); + } + } + + this->actionFunc = EnWiz_Appear; + } +} + +/** + * Makes the Wizrobe grow in scale and become more opaque. + * During the first phase, it also increases the alpha for the platform's light. + * If the player gets too close during the first phase, this will set up the Wizrobe to disappear. + */ +void EnWiz_Appear(EnWiz* this, PlayState* play) { + Vec3f staffTargetFlameScale = { 0.006f, 0.006f, 0.006f }; + Player* player = GET_PLAYER(play); + + EnWiz_HandleIntroCutscene(this, play); + + if (this->introCutsceneState >= EN_WIZ_INTRO_CS_APPEAR) { + SkelAnime_Update(&this->skelAnime); + + if ((this->fightState == EN_WIZ_FIGHT_STATE_FIRST_PHASE) && + (this->introCutsceneState >= EN_WIZ_INTRO_CS_DISAPPEAR) && + ((this->actor.xzDistToPlayer < 200.0f) || + ((player->unk_D57 != 0) && + ((ABS_ALT(BINANG_SUB(this->actor.yawTowardsPlayer, this->actor.shape.rot.y)) < 0x7D0)) && + (ABS_ALT(BINANG_SUB(this->actor.yawTowardsPlayer, BINANG_ADD(player->actor.shape.rot.y, 0x8000))) < + 0x7D0)))) { + EnWiz_SetupDisappear(this); + } else { + Math_SmoothStepToS(&this->actor.world.rot.y, this->actor.yawTowardsPlayer, 0xA, 0xBB8, 0); + + if (this->fightState == EN_WIZ_FIGHT_STATE_FIRST_PHASE) { + Math_SmoothStepToS(&this->platformLightAlpha, this->targetPlatformLightAlpha, 10, 10, 10); + if (!this->shouldStartTimer) { + this->timer = 20; + this->shouldStartTimer = true; + } + } else { + Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_WIZ_VOICE - SFX_FLAG); + } + + if (this->timer == 0) { + Math_ApproachF(&this->scale, 0.015f, 0.05f, 0.01f); + Math_SmoothStepToS(&this->alpha, 255, 1, 5, 0); + } + + if (this->scale < 0.0138f) { + return; + } else { + this->action = EN_WIZ_ACTION_RUN_IN_CIRCLES; + this->actor.flags &= ~ACTOR_FLAG_8000000; + this->ghostColliders.elements[0].info.bumper.dmgFlags = 0x1013A22; + Math_Vec3f_Copy(&this->staffTargetFlameScale, &staffTargetFlameScale); + this->targetPlatformLightAlpha = 0; + + if (this->introCutsceneState == EN_WIZ_INTRO_CS_DISAPPEAR) { + this->timer = 0; + this->introCutsceneTimer = 20; + EnWiz_SetupDisappear(this); + } else if (this->introCutsceneState >= EN_WIZ_INTRO_CS_END) { + if (this->fightState == EN_WIZ_FIGHT_STATE_SECOND_PHASE_CUTSCENE) { + this->actionFunc = EnWiz_SetupSecondPhaseCutscene; + } else { + EnWiz_SetupDance(this); + } + } + } + } + } +} + +void EnWiz_SetupDance(EnWiz* this) { + EnWiz_ChangeAnim(this, EN_WIZ_ANIM_DANCE, false); + Math_ApproachF(&this->scale, 0.015f, 0.05f, 0.001f); + this->rotationalVelocity = 0; + this->animLoopCounter = 0; + this->action = EN_WIZ_ACTION_DANCE; + if (this->fightState >= EN_WIZ_FIGHT_STATE_SECOND_PHASE_GHOSTS_COPY_WIZROBE) { + Animation_Change(&this->ghostSkelAnime, &gWizrobeRunAnim, 1.0f, 0.0f, Animation_GetLastFrame(&gWizrobeRunAnim), + ANIMMODE_LOOP, 0.0f); + this->fightState = EN_WIZ_FIGHT_STATE_SECOND_PHASE_GHOSTS_RUN_AROUND; + } + + Math_SmoothStepToS(&this->alpha, 255, 1, 5, 0); + this->actionFunc = EnWiz_Dance; +} + +/** + * Makes the Wizrobe spin around and dance until there are no active projectiles + * and it completes at least three loops of its dancing animation. + */ +void EnWiz_Dance(EnWiz* this, PlayState* play) { + f32 curFrame = this->skelAnime.curFrame; + s32 i; + + Math_SmoothStepToS(&this->alpha, 255, 1, 5, 0); + Math_ApproachF(&this->scale, 0.015f, 0.05f, 0.001f); + Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_WIZ_RUN - SFX_FLAG); + this->actor.world.rot.y += this->rotationalVelocity; + if (this->fightState >= EN_WIZ_FIGHT_STATE_SECOND_PHASE_GHOSTS_RUN_AROUND) { + EnWiz_MoveGhosts(this); + } else { + for (i = 0; i < this->platformCount; i++) { + this->ghostRot[i].y += this->rotationalVelocity; + } + } + + Math_SmoothStepToS(&this->rotationalVelocity, 0x1388, 0x64, 0x3E8, 0x3E8); + Math_SmoothStepToS(&this->platformLightAlpha, this->targetPlatformLightAlpha, 20, 50, 10); + if (this->endFrame <= curFrame) { + if (this->animLoopCounter < 10) { + this->animLoopCounter++; + } + } + + if ((this->animLoopCounter >= 3) && (!this->hasActiveProjectile)) { + this->targetPlatformLightAlpha = 0; + EnWiz_SetupWindUp(this); + } +} + +void EnWiz_SetupSecondPhaseCutscene(EnWiz* this, PlayState* play) { + s16 secondPhaseCutscene = ActorCutscene_GetAdditionalCutscene(this->actor.cutscene); + + if (!ActorCutscene_GetCanPlayNext(secondPhaseCutscene)) { + ActorCutscene_SetIntentToPlay(secondPhaseCutscene); + } else { + ActorCutscene_StartAndSetFlag(secondPhaseCutscene, &this->actor); + this->subCamId = ActorCutscene_GetCurrentSubCamId(secondPhaseCutscene); + this->actor.flags |= ACTOR_FLAG_100000; + EnWiz_ChangeAnim(this, EN_WIZ_ANIM_DANCE, false); + this->action = EN_WIZ_ACTION_RUN_BETWEEN_PLATFORMS; + this->nextPlatformIndex = 1; + this->hasRunToEveryPlatform = false; + Math_SmoothStepToS(&this->alpha, 255, 1, 5, 0); + this->actionFunc = EnWiz_SecondPhaseCutscene; + } +} + +/** + * Makes the Wizrobe run between every platform in the room once before returning to its + * original platform and disappearing. Ghosts trail behind the Wizrobe as it runs. + */ +void EnWiz_SecondPhaseCutscene(EnWiz* this, PlayState* play) { + Camera* subCam; + s32 i; + + Math_SmoothStepToS(&this->alpha, 255, 1, 5, 0); + subCam = Play_GetCamera(play, this->subCamId); + Math_Vec3f_Copy(&subCam->at, &this->actor.focus.pos); + Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_WIZ_RUN - SFX_FLAG); + if (this->platforms[this->nextPlatformIndex] != NULL) { + f32 diffX = this->actor.world.pos.x - this->platforms[this->nextPlatformIndex]->world.pos.x; + f32 diffZ = this->actor.world.pos.z - this->platforms[this->nextPlatformIndex]->world.pos.z; + s32 pad; + + if (sqrtf(SQ(diffX) + SQ(diffZ)) < 30.0f) { + if (!this->hasRunToEveryPlatform) { + this->nextPlatformIndex++; + if (this->nextPlatformIndex >= this->platformCount) { + this->hasRunToEveryPlatform = true; + this->nextPlatformIndex = 0; + } + } else { + f32 diffX = this->actor.world.pos.x - this->ghostPos[this->platformCount].x; + f32 diffZ = this->actor.world.pos.z - this->ghostPos[this->platformCount].z; + s32 pad; + s32 i; + + this->actor.flags |= ACTOR_FLAG_8000000; + if (sqrtf(SQ(diffX) + SQ(diffZ)) < 20.0f) { + for (i = 0; i < this->platformCount; i++) { + Math_Vec3f_Copy(&this->ghostPos[i], &gZeroVec3f); + } + + this->nextPlatformIndex = 0; + this->platformCount = 0; + this->fightState = EN_WIZ_FIGHT_STATE_SECOND_PHASE_GHOSTS_COPY_WIZROBE; + this->timer = 0; + ActorCutscene_Stop(ActorCutscene_GetAdditionalCutscene(this->actor.cutscene)); + this->actor.flags &= ~ACTOR_FLAG_100000; + EnWiz_SetupDisappear(this); + return; + } + } + } + } + + Math_Vec3f_Copy(this->ghostPos, &this->actor.world.pos); + this->ghostRot[0].y = this->actor.world.rot.y; + Math_ApproachF(&this->actor.world.pos.x, this->platforms[this->nextPlatformIndex]->world.pos.x, 0.3f, 30.0f); + Math_ApproachF(&this->actor.world.pos.y, this->platforms[this->nextPlatformIndex]->world.pos.y, 0.3f, 30.0f); + Math_ApproachF(&this->actor.world.pos.z, this->platforms[this->nextPlatformIndex]->world.pos.z, 0.3f, 30.0f); + for (i = this->platformCount; i > 0; i--) { + Math_Vec3f_Copy(&this->ghostPos[i], &this->ghostPos[i - 1]); + this->ghostRot[i].y = this->ghostRot[i - 1].y; + } + + this->actor.world.rot.y = + Math_Vec3f_Yaw(&this->actor.world.pos, &this->platforms[this->nextPlatformIndex]->world.pos); +} + +void EnWiz_SetupWindUp(EnWiz* this) { + EnWiz_ChangeAnim(this, EN_WIZ_ANIM_WIND_UP, false); + this->animLoopCounter = 0; + this->actionFunc = EnWiz_WindUp; +} + +/** + * Plays the wind up animation for at least two animation loops before attacking. + */ +void EnWiz_WindUp(EnWiz* this, PlayState* play) { + f32 curFrame = this->skelAnime.curFrame; + s32 i; + + Math_SmoothStepToS(&this->actor.world.rot.y, this->actor.yawTowardsPlayer, 0xC8, 0x1F40, 0x1388); + if (this->fightState >= EN_WIZ_FIGHT_STATE_SECOND_PHASE_GHOSTS_RUN_AROUND) { + EnWiz_MoveGhosts(this); + } else { + for (i = 0; i < this->platformCount; i++) { + Math_SmoothStepToS(&this->ghostRot[i].y, this->actor.yawTowardsPlayer, 0xC8, 0x1F40, 0x1388); + } + } + + if (this->endFrame <= curFrame) { + this->animLoopCounter++; + if (this->animLoopCounter >= 2) { + EnWiz_SetupAttack(this); + } + } + + Math_SmoothStepToS(&this->platformLightAlpha, this->targetPlatformLightAlpha, 10, 10, 10); +} + +void EnWiz_SetupAttack(EnWiz* this) { + EnWiz_ChangeAnim(this, EN_WIZ_ANIM_ATTACK, false); + this->timer = 0; + this->shouldStartTimer = false; + this->action = EN_WIZ_ACTION_ATTACK; + this->actionFunc = EnWiz_Attack; +} + +/** + * Spawns an EnWizFire projectile that is pointed at the player, then disappears. + */ +void EnWiz_Attack(EnWiz* this, PlayState* play) { + f32 curFrame = this->skelAnime.curFrame; + + if (this->fightState >= EN_WIZ_FIGHT_STATE_SECOND_PHASE_GHOSTS_RUN_AROUND) { + EnWiz_MoveGhosts(this); + } + + if (this->timer == 0) { + if ((Animation_OnFrame(&this->skelAnime, 6.0f)) && (!this->hasActiveProjectile)) { + Player* player = GET_PLAYER(play); + Vec3f pos; + s32 type = this->type; + + Math_Vec3f_Copy(&pos, &this->actor.world.pos); + pos.x += Math_SinS(this->actor.world.rot.y) * 40.0f; + pos.y += 60.0f; + pos.z += Math_CosS(this->actor.world.rot.y) * 40.0f; + if (type == EN_WIZ_TYPE_FIRE_NO_BGM) { + type = EN_WIZ_TYPE_FIRE; + } + + Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_EN_WIZ_FIRE, pos.x, pos.y, pos.z, + Math_Vec3f_Pitch(&pos, &player->actor.world.pos), + Math_Vec3f_Yaw(&pos, &player->actor.world.pos), 0, type * 4); + this->hasActiveProjectile = true; + Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_WIZ_ATTACK); + Actor_PlaySfxAtPos(&this->actor, NA_SE_PL_MAGIC_FIRE); + } + + if ((curFrame >= 8.0f) && !this->shouldStartTimer) { + this->timer = 3; + this->shouldStartTimer = true; + } + + if (this->endFrame <= curFrame) { + EnWiz_SetupDisappear(this); + } + } +} + +void EnWiz_SetupDisappear(EnWiz* this) { + if (this->action != EN_WIZ_ACTION_DAMAGED) { + this->rotationalVelocity = 0x2710; + this->timer = 0; + EnWiz_ChangeAnim(this, EN_WIZ_ANIM_IDLE, false); + this->action = EN_WIZ_ACTION_DISAPPEAR; + } else { + this->rotationalVelocity = 0x2710; + this->actor.world.rot.y += this->rotationalVelocity; + } + + this->targetPlatformLightAlpha = 0; + this->actor.flags |= ACTOR_FLAG_8000000; + Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_WIZ_DISAPPEAR); + Math_SmoothStepToS(&this->rotationalVelocity, 0x1388, 0x64, 0x3E8, 0x3E8); + this->actor.world.rot.y += this->rotationalVelocity; + this->actor.flags &= ~ACTOR_FLAG_1; + this->actionFunc = EnWiz_Disappear; +} + +/** + * Spin the Wizrobe around and shrink it so that it disappears into its platform. + * Afterwards, set it up to appear again. + */ +void EnWiz_Disappear(EnWiz* this, PlayState* play) { + s32 i; + + Math_SmoothStepToS(&this->rotationalVelocity, 0, 0xA, 0xBB8, 0x14); + this->actor.world.rot.y += this->rotationalVelocity; + if ((this->fightState == EN_WIZ_FIGHT_STATE_FIRST_PHASE) || (this->action == EN_WIZ_ACTION_DAMAGED)) { + Math_ApproachZeroF(&this->scale, 0.3f, 0.01f); + Math_SmoothStepToS(&this->platformLightAlpha, this->targetPlatformLightAlpha, 5, 50, 0); + } else { + Math_ApproachZeroF(&this->scale, 0.3f, 0.001f); + Math_SmoothStepToS(&this->platformLightAlpha, this->targetPlatformLightAlpha, 10, 50, 0); + for (i = 0; i < this->platformCount; i++) { + this->ghostRot[i].y += this->rotationalVelocity; + } + } + + Math_Vec3f_Copy(&this->staffTargetFlameScale, &gZeroVec3f); + if (this->scale < 0.001f) { + this->scale = 0.0f; + + if ((this->introCutsceneState == EN_WIZ_INTRO_CS_DISAPPEAR) && (this->introCutsceneTimer == 0)) { + this->introCutsceneState = EN_WIZ_INTRO_CS_END; + ActorCutscene_Stop(this->actor.cutscene); + this->actor.flags &= ~ACTOR_FLAG_100000; + } + + if (this->introCutsceneState != EN_WIZ_INTRO_CS_DISAPPEAR) { + this->alpha = 0; + if (this->fightState == EN_WIZ_FIGHT_STATE_FIRST_PHASE) { + this->ghostColliders.elements[0].info.bumper.dmgFlags = 0x1000202; + } + + this->actor.flags |= ACTOR_FLAG_1; + this->actionFunc = EnWiz_SetupAppear; + } + } +} + +void EnWiz_SetupDamaged(EnWiz* this, PlayState* play) { + EnWiz_ChangeAnim(this, EN_WIZ_ANIM_DAMAGE, false); + Actor_SetColorFilter(&this->actor, 0x4000, 255, 0, 8); + this->timer = 20; + + if ((this->fightState != EN_WIZ_FIGHT_STATE_FIRST_PHASE) && (this->actor.colChkInfo.health <= 0)) { + Enemy_StartFinishingBlow(play, &this->actor); + Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_WIZ_DEAD); + this->timer = 0; + this->actor.flags &= ~ACTOR_FLAG_1; + } else { + Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_WIZ_DAMAGE); + } + + this->scale = 0.015f; + this->platformCount = 0; + this->targetPlatformLightAlpha = 0; + if ((this->drawDmgEffTimer != 0) && + ((this->drawDmgEffType == ACTOR_DRAW_DMGEFF_FIRE) || (this->drawDmgEffType == ACTOR_DRAW_DMGEFF_LIGHT_ORBS))) { + this->timer = 0; + } + + this->rotationalVelocity = 0x4E20; + if ((this->drawDmgEffTimer != 0) && (this->drawDmgEffType == ACTOR_DRAW_DMGEFF_FROZEN_SFX)) { + this->rotationalVelocity = 0; + this->timer = 0; + } + + this->action = EN_WIZ_ACTION_DAMAGED; + this->actionFunc = EnWiz_Damaged; +} + +/** + * Spins the Wizrobe around quickly and makes it jump in the air if it was defeated or if + * it was damaged in a certain way. Afterwards, the Wizrobe either disappears or dies. + */ +void EnWiz_Damaged(EnWiz* this, PlayState* play) { + s32 i; + + if ((this->drawDmgEffTimer < 50) && (this->drawDmgEffType == ACTOR_DRAW_DMGEFF_FROZEN_SFX)) { + Actor_SpawnIceEffects(play, &this->actor, this->bodyPartsPos, ARRAY_COUNT(this->bodyPartsPos), 2, 1.0f, 0.7f); + this->drawDmgEffTimer = 0; + this->drawDmgEffType = ACTOR_DRAW_DMGEFF_FIRE; + this->rotationalVelocity = 0x4E20; + this->actor.velocity.y = 30.0f; + this->actor.gravity = -3.0f; + } + + if ((this->drawDmgEffTimer != 0) && (this->drawDmgEffTimer < 30) && + ((this->drawDmgEffType == ACTOR_DRAW_DMGEFF_FIRE) || (this->drawDmgEffType == ACTOR_DRAW_DMGEFF_LIGHT_ORBS))) { + this->actor.velocity.y = 30.0f; + this->actor.gravity = -3.0f; + this->drawDmgEffTimer = 0; + this->drawDmgEffType = ACTOR_DRAW_DMGEFF_FIRE; + } else if (!this->isDead && (this->fightState != EN_WIZ_FIGHT_STATE_FIRST_PHASE) && + (this->actor.colChkInfo.health <= 0)) { + this->actor.velocity.y = 30.0f; + this->actor.gravity = -3.0f; + this->isDead = true; + } + + this->actor.world.rot.y += this->rotationalVelocity; + Math_SmoothStepToS(&this->rotationalVelocity, 0, 0xA, 0xBB8, 0x14); + for (i = 0; i < this->platformCount; i++) { + this->ghostRot[i].y += this->rotationalVelocity; + } + + if ((this->timer == 1) || + ((this->actor.velocity.y < 0.0f) && + (this->actor.world.pos.y < (this->platforms[this->curPlatformIndex]->world.pos.y + 11.0f)))) { + this->timer = 0; + this->actor.velocity.y = 0.0f; + this->actor.gravity = 0.0f; + this->drawDmgEffTimer = this->timer; + this->drawDmgEffType = this->timer; + + if (this->actor.colChkInfo.health <= 0) { + if (this->fightState == EN_WIZ_FIGHT_STATE_FIRST_PHASE) { + this->fightState = EN_WIZ_FIGHT_STATE_SECOND_PHASE_CUTSCENE; + if ((this->type == EN_WIZ_TYPE_FIRE) || (this->type == EN_WIZ_TYPE_FIRE_NO_BGM)) { + this->actor.colChkInfo.health = 8; + } else { + this->actor.colChkInfo.health = 6; + } + + EnWiz_SetupDisappear(this); + } else { + EnWiz_SetupDead(this); + } + } else { + EnWiz_SetupDisappear(this); + } + + this->actor.flags |= ACTOR_FLAG_8000000; + } + + Math_SmoothStepToS(&this->platformLightAlpha, this->targetPlatformLightAlpha, 20, 50, 10); + Actor_MoveWithGravity(&this->actor); + Actor_UpdateBgCheckInfo(play, &this->actor, 35.0f, 40.0f, 40.0f, 0x1F); +} + +void EnWiz_SetupDead(EnWiz* this) { + EnWiz_ChangeAnim(this, EN_WIZ_ANIM_DAMAGE, false); + this->rotationalVelocity = 0x2710; + this->action = EN_WIZ_ACTION_DEAD; + this->timer = 0; + this->actionFunc = EnWiz_Dead; +} + +/** + * Slows the Wizrobe's rotation to a stop, then makes it burst into flames. + * If the Wizrobe has a switch flag, it will set that switch flag when it dies. + */ +void EnWiz_Dead(EnWiz* this, PlayState* play) { + s32 i; + + this->actor.world.rot.y += this->rotationalVelocity; + Math_SmoothStepToS(&this->rotationalVelocity, 0, 0xA, 0xBB8, 0x14); + if (this->rotationalVelocity < 0x1E) { + Math_SmoothStepToS(&this->alpha, 0, 10, 30, 20); + for (i = 0; i < this->platformCount; i++) { + Math_SmoothStepToS(&this->ghostAlpha[i], 0, 10, 30, 20); + } + + this->action = EN_WIZ_ACTION_BURST_INTO_FLAMES; + } + + if (this->alpha < 30) { + EnWiz_SelectPlatform(this, play); + SoundSource_PlaySfxAtFixedWorldPos(play, &this->actor.world.pos, 50, NA_SE_EN_EXTINCT); + Actor_MarkForDeath(&this->actor); + if (this->switchFlag >= 0) { + Flags_SetSwitch(play, this->switchFlag); + } + } +} + +static Color_RGBA8 sDustPrimColor = { 250, 250, 250, 255 }; +static Color_RGBA8 sDustEnvTimer = { 180, 180, 180, 255 }; + +void EnWiz_UpdateDamage(EnWiz* this, PlayState* play) { + s32 i; + s32 attackDealsDamage = false; + + if (this->collider.base.acFlags & AC_HIT) { + this->ghostColliders.base.acFlags &= ~AC_HIT; + if (this->action < EN_WIZ_ACTION_RUN_IN_CIRCLES) { + return; + } + + switch (this->actor.colChkInfo.damageEffect) { + case EN_WIZ_DMGEFF_NONE: + attackDealsDamage = true; + break; + + case EN_WIZ_DMGEFF_FIRE: + if (this->type == EN_WIZ_TYPE_ICE) { + this->drawDmgEffTimer = 40; + this->drawDmgEffType = ACTOR_DRAW_DMGEFF_FIRE; + } + + attackDealsDamage = true; + break; + + case EN_WIZ_DMGEFF_FREEZE: + if ((this->type == EN_WIZ_TYPE_FIRE) || (this->type == EN_WIZ_TYPE_FIRE_NO_BGM)) { + this->drawDmgEffTimer = 80; + this->drawDmgEffType = ACTOR_DRAW_DMGEFF_FROZEN_SFX; + this->drawDmgEffScale = 0.0f; + this->drawDmgEffFrozenSteamScale = 1.5f; + } + + Actor_ApplyDamage(&this->actor); + EnWiz_SetupDamaged(this, play); + break; + + case EN_WIZ_DMGEFF_LIGHT_ORB: + if (((this->drawDmgEffType != ACTOR_DRAW_DMGEFF_FROZEN_SFX) && + (this->drawDmgEffType != ACTOR_DRAW_DMGEFF_FROZEN_NO_SFX)) || + (this->drawDmgEffTimer == 0)) { + Actor_Spawn(&play->actorCtx, play, ACTOR_EN_CLEAR_TAG, this->actor.focus.pos.x, + this->actor.focus.pos.y, this->actor.focus.pos.z, 0, 0, 0, CLEAR_TAG_LARGE_LIGHT_RAYS); + this->drawDmgEffTimer = 40; + this->drawDmgEffType = ACTOR_DRAW_DMGEFF_LIGHT_ORBS; + attackDealsDamage = true; + } + break; + } + + this->alpha = 255; + if (attackDealsDamage) { + Actor_ApplyDamage(&this->actor); + EnWiz_SetupDamaged(this, play); + return; + } + } + + if ((this->platformCount != 0) && (this->fightState != EN_WIZ_FIGHT_STATE_SECOND_PHASE_CUTSCENE)) { + for (i = 0; i < this->platformCount; i++) { + Vec3f accel; + Vec3f velocity; + Vec3f pos; + f32 scaleStep; + s32 j; + + // If the player throws a Deku Nut or hits a ghost's collider (something that is impossible + // in the final game, since EnWiz_Init effectively disables them), then the below code will + // "destroy" the ghost by turning into a cloud of smoke. + if ((iREG(50) != 0) || (this->ghostColliders.elements[i + 1].info.bumperFlags & BUMP_HIT)) { + //! @bug: If a single ghost is destroyed, then changing the fight state here will cause + //! strange behavior; the ghosts will stand still and pretend to attack the player like + //! the real Wizrobe. Since Deku Nuts destroy all ghosts at once, and since the ghost + //! colliders are effectively disabled, this doesn't cause any problems in the final + //! game, but it becomes an issue if the ghost colliders are enabled. + this->fightState = EN_WIZ_FIGHT_STATE_SECOND_PHASE_GHOSTS_COPY_WIZROBE; + this->ghostColliders.base.acFlags &= ~BUMP_HIT; + if (this->ghostPos[i].x != .0f || this->ghostPos[i].z != .0f) { + for (j = 0; j < 9; j++) { + accel.x = 0.0f; + accel.y = 1.0f; + accel.z = 0.0f; + velocity.x = 0.0f; + velocity.y = 1.0f; + velocity.z = 0.0f; + scaleStep = Rand_S16Offset(20, 10); + Math_Vec3f_Copy(&pos, &this->ghostPos[i]); + pos.x += (f32)Rand_S16Offset(20, 20) * ((Rand_ZeroOne() < 0.5f) ? -1 : 1); + pos.y += 70.0f + randPlusMinusPoint5Scaled(30.0f); + pos.z += (f32)Rand_S16Offset(20, 20) * ((Rand_ZeroOne() < 0.5f) ? -1 : 1); + func_800B0DE0(play, &pos, &velocity, &accel, &sDustPrimColor, &sDustEnvTimer, + Rand_S16Offset(350, 100), scaleStep); + } + + SoundSource_PlaySfxAtFixedWorldPos(play, &this->ghostPos[i], 50, NA_SE_EN_WIZ_LAUGH); + Math_Vec3f_Copy(&this->ghostPos[i], &gZeroVec3f); + } + } + } + } +} + +void EnWiz_Update(Actor* thisx, PlayState* play) { + s32 pad; + EnWiz* this = THIS; + s32 i; + s32 j; + + if (this->action != EN_WIZ_ACTION_APPEAR) { + SkelAnime_Update(&this->skelAnime); + SkelAnime_Update(&this->ghostSkelAnime); + } + + Actor_SetFocus(&this->actor, 60.0f); + Actor_SetScale(&this->actor, this->scale); + EnWiz_UpdateDamage(this, play); + this->actionFunc(this, play); + + this->actor.shape.rot.y = this->actor.world.rot.y; + + DECR(this->timer); + DECR(this->introCutsceneTimer); + DECR(this->drawDmgEffTimer); + + this->collider.dim.radius = 35; + this->collider.dim.height = 130; + this->collider.dim.yShift = 0; + if (this->action >= EN_WIZ_ACTION_RUN_IN_CIRCLES) { + CollisionCheck_SetAC(play, &play->colChkCtx, &this->ghostColliders.base); + Collider_UpdateCylinder(&this->actor, &this->collider); + CollisionCheck_SetAC(play, &play->colChkCtx, &this->collider.base); + CollisionCheck_SetOC(play, &play->colChkCtx, &this->collider.base); + } + + Math_ApproachF(&this->staffFlameScale.x, this->staffTargetFlameScale.x, 0.3f, 0.002f); + Math_ApproachF(&this->staffFlameScale.y, this->staffTargetFlameScale.y, 0.3f, 0.002f); + Math_ApproachF(&this->staffFlameScale.z, this->staffTargetFlameScale.z, 0.3f, 0.002f); + + if (this->fightState == EN_WIZ_FIGHT_STATE_FIRST_PHASE) { + this->platformCount = 0; + } else if (this->fightState == EN_WIZ_FIGHT_STATE_SECOND_PHASE_GHOSTS_RUN_AROUND) { + for (i = 0; i < this->platformCount; i++) { + for (j = 0; j < ARRAY_COUNT(this->ghostBaseJointTable); j++) { + this->ghostJointTables[i][j] = this->ghostBaseJointTable[j]; + } + } + } else { + for (i = 0; i < this->platformCount; i++) { + for (j = 0; j < ARRAY_COUNT(this->jointTable); j++) { + this->ghostJointTables[i][j] = this->jointTable[j]; + } + } + } +} + +void EnWiz_PostLimbDrawOpa(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, Actor* thisx) { + Vec3f staffFlamePos = { 0.0f, 0.0f, 0.0f }; + EnWiz* this = THIS; + + if (limbIndex == WIZROBE_LIMB_STAFF) { + staffFlamePos.x = 7300.0f; + staffFlamePos.y = -1500.0f; + if (this->action != EN_WIZ_ACTION_DANCE) { + staffFlamePos.y = 0.0f; + staffFlamePos.x = 5300.0f; + } + + Matrix_Translate(0.0f, 0.0f, 0.0f, MTXMODE_APPLY); + Matrix_MultVec3f(&staffFlamePos, &this->staffFlamePos); + } + + Collider_UpdateSpheres(limbIndex, &this->ghostColliders); + + if ((limbIndex == WIZROBE_LIMB_PELVIS) || (limbIndex == WIZROBE_LIMB_TORSO) || + (limbIndex == WIZROBE_LIMB_LEFT_UPPER_ARM) || (limbIndex == WIZROBE_LIMB_LEFT_FOREARM) || + (limbIndex == WIZROBE_LIMB_RIGHT_UPPER_ARM) || (limbIndex == WIZROBE_LIMB_RIGHT_FOREARM) || + (limbIndex == WIZROBE_LIMB_NECK) || (limbIndex == WIZROBE_LIMB_HEAD) || (limbIndex == WIZROBE_LIMB_JAW) || + (limbIndex == WIZROBE_LIMB_LEFT_SHIN) || (limbIndex == WIZROBE_LIMB_RIGHT_SHIN) || + (limbIndex == WIZROBE_LIMB_LOINCLOTH)) { + Matrix_MultZero(&this->bodyPartsPos[this->bodyPartsPosIndex]); + this->bodyPartsPosIndex++; + if (this->bodyPartsPosIndex >= ARRAY_COUNT(this->bodyPartsPos)) { + this->bodyPartsPosIndex = 0; + } + } +} + +void EnWiz_PostLimbDrawXlu(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, Actor* thisx, Gfx** gfx) { + Vec3f staffFlamePos = { 0.0f, 0.0f, 0.0f }; + s32 pad; + EnWiz* this = THIS; + + if (this->action != EN_WIZ_ACTION_BURST_INTO_FLAMES) { + if (limbIndex == WIZROBE_LIMB_STAFF) { + staffFlamePos.x = 7300.0f; + staffFlamePos.y = -1500.0f; + if (this->action != EN_WIZ_ACTION_DANCE) { + staffFlamePos.y = 0.0f; + staffFlamePos.x = 5300.0f; + } + + Matrix_Translate(0.0f, 0.0f, 0.0f, MTXMODE_APPLY); + Matrix_MultVec3f(&staffFlamePos, &this->staffFlamePos); + } + } else { + if (this->timer == 0) { + Vec3f flamePos; + + Matrix_Translate(0.0f, 0.0f, 0.0f, MTXMODE_APPLY); + Matrix_MultVec3f(&staffFlamePos, &flamePos); + flamePos.x += randPlusMinusPoint5Scaled(4.0f); + flamePos.y += randPlusMinusPoint5Scaled(7.0f); + flamePos.z += randPlusMinusPoint5Scaled(5.0f); + func_800B3030(play, &flamePos, &gZeroVec3f, &gZeroVec3f, ((Rand_ZeroFloat(1.0f) * 50.0f) + 70.0f), 10, 1); + SoundSource_PlaySfxAtFixedWorldPos(play, &flamePos, 10, NA_SE_EN_EXTINCT); + } + + if ((limbIndex >= WIZROBE_LIMB_RIGHT_FOOT) && (this->timer == 0)) { + this->timer = 4; + } + } + + if ((limbIndex == WIZROBE_LIMB_PELVIS) || (limbIndex == WIZROBE_LIMB_TORSO) || + (limbIndex == WIZROBE_LIMB_LEFT_UPPER_ARM) || (limbIndex == WIZROBE_LIMB_LEFT_FOREARM) || + (limbIndex == WIZROBE_LIMB_RIGHT_UPPER_ARM) || (limbIndex == WIZROBE_LIMB_RIGHT_FOREARM) || + (limbIndex == WIZROBE_LIMB_NECK) || (limbIndex == WIZROBE_LIMB_HEAD) || (limbIndex == WIZROBE_LIMB_JAW) || + (limbIndex == WIZROBE_LIMB_LEFT_SHIN) || (limbIndex == WIZROBE_LIMB_RIGHT_SHIN) || + (limbIndex == WIZROBE_LIMB_LOINCLOTH)) { + Matrix_MultZero(&this->bodyPartsPos[this->bodyPartsPosIndex]); + this->bodyPartsPosIndex++; + if (this->bodyPartsPosIndex >= ARRAY_COUNT(this->bodyPartsPos)) { + this->bodyPartsPosIndex = 0; + } + } +} + +void EnWiz_Draw(Actor* thisx, PlayState* play) { + s32 pad; + EnWiz* this = THIS; + + OPEN_DISPS(play->state.gfxCtx); + + func_8012C28C(play->state.gfxCtx); + func_8012C2DC(play->state.gfxCtx); + + if ((this->action == EN_WIZ_ACTION_BURST_INTO_FLAMES) || (this->alpha != 255)) { + Scene_SetRenderModeXlu(play, 1, 2); + gDPPipeSync(POLY_XLU_DISP++); + gDPSetEnvColor(POLY_XLU_DISP++, 0, 0, 0, this->alpha); + POLY_XLU_DISP = + SkelAnime_DrawFlex(play, this->skelAnime.skeleton, this->skelAnime.jointTable, this->skelAnime.dListCount, + NULL, EnWiz_PostLimbDrawXlu, &this->actor, POLY_XLU_DISP); + } else { + Scene_SetRenderModeXlu(play, 0, 1); + gDPPipeSync(POLY_OPA_DISP++); + gDPSetEnvColor(POLY_OPA_DISP++, 255, 255, 255, this->alpha); + SkelAnime_DrawFlexOpa(play, this->skelAnime.skeleton, this->skelAnime.jointTable, this->skelAnime.dListCount, + NULL, EnWiz_PostLimbDrawOpa, &this->actor); + } + + if (this->drawDmgEffTimer != 0) { + f32 drawDmgEffAlpha = this->drawDmgEffTimer * 0.05f; + + if ((this->drawDmgEffType == ACTOR_DRAW_DMGEFF_FROZEN_SFX) || + (this->drawDmgEffType == ACTOR_DRAW_DMGEFF_FROZEN_NO_SFX)) { + this->drawDmgEffScale += 0.3f; + if (this->drawDmgEffScale > 0.5f) { + this->drawDmgEffScale = 0.5f; + } + + Math_ApproachF(&this->drawDmgEffFrozenSteamScale, this->drawDmgEffScale, 0.1f, 0.04f); + } else { + this->drawDmgEffScale = 0.8f; + this->drawDmgEffFrozenSteamScale = 0.8f; + } + + Actor_DrawDamageEffects(play, &this->actor, this->bodyPartsPos, ARRAY_COUNT(this->bodyPartsPos), + this->drawDmgEffScale, this->drawDmgEffFrozenSteamScale, drawDmgEffAlpha, + this->drawDmgEffType); + } + + if (this->platformCount > 0) { + s32 i; + s16 platformCount; + + Matrix_Push(); + + platformCount = this->platformCount; + if (this->fightState == EN_WIZ_FIGHT_STATE_SECOND_PHASE_CUTSCENE) { + platformCount = 10; + } + + for (i = 0; i < platformCount; i++) { + func_8012C28C(play->state.gfxCtx); + func_8012C2DC(play->state.gfxCtx); + + if ((this->ghostPos[i].x != 0.0f) && (this->ghostPos[i].z != 0.0f)) { + Matrix_Translate(this->ghostPos[i].x, this->ghostPos[i].y + 10.0f, this->ghostPos[i].z, MTXMODE_NEW); + Matrix_Scale(this->scale, this->scale, this->scale, MTXMODE_APPLY); + Matrix_RotateYS(this->ghostRot[i].y, MTXMODE_APPLY); + Matrix_RotateXS(this->ghostRot[i].x, MTXMODE_APPLY); + Matrix_RotateZS(this->ghostRot[i].z, MTXMODE_APPLY); + Scene_SetRenderModeXlu(play, 1, 2); + gDPPipeSync(POLY_XLU_DISP++); + gDPSetEnvColor(POLY_XLU_DISP++, 0, 0, 0, this->ghostAlpha[i]); + POLY_XLU_DISP = + SkelAnime_DrawFlex(play, this->ghostSkelAnime.skeleton, this->ghostJointTables[i], + this->ghostSkelAnime.dListCount, NULL, NULL, &this->actor, POLY_XLU_DISP); + this->ghostColliders.elements[i + 1].dim.worldSphere.center.x = this->ghostPos[i].x; + this->ghostColliders.elements[i + 1].dim.worldSphere.center.y = this->ghostPos[i].y + 50.0f; + this->ghostColliders.elements[i + 1].dim.worldSphere.center.z = this->ghostPos[i].z; + this->ghostColliders.elements[i + 1].dim.worldSphere.radius = + this->ghostColliders.elements[0].dim.modelSphere.radius; + this->ghostColliders.elements[i + 1].dim.scale = this->ghostColliders.elements[0].dim.scale; + } + } + + Matrix_Pop(); + } + + func_8012C2DC(play->state.gfxCtx); + func_8012C28C(play->state.gfxCtx); + + // Draw the light emanating from the Wizrobe's platform + if (this->fightState == EN_WIZ_FIGHT_STATE_FIRST_PHASE) { + Matrix_Push(); + + AnimatedMat_Draw(play, Lib_SegmentedToVirtual(&gWizrobePlatformLightTexAnim)); + Matrix_Translate(this->platformLightPos.x, this->platformLightPos.y, this->platformLightPos.z, MTXMODE_NEW); + Matrix_Scale(0.01f, 0.01f, 0.01f, MTXMODE_APPLY); + gDPPipeSync(POLY_XLU_DISP++); + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, 255, 255, 255, this->platformLightAlpha); + + if ((this->type == EN_WIZ_TYPE_FIRE) || (this->type == EN_WIZ_TYPE_FIRE_NO_BGM)) { + gDPSetEnvColor(POLY_XLU_DISP++, 255, 0, 100, 255); + } else { + gDPSetEnvColor(POLY_XLU_DISP++, 50, 0, 255, 255); + } + + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_XLU_DISP++, gWizrobePlatformLightDL); + + Matrix_Pop(); + } + + // Draw the flame at the tip of the Wizrobe's staff + Matrix_Translate(this->staffFlamePos.x, this->staffFlamePos.y, this->staffFlamePos.z, MTXMODE_NEW); + Matrix_Scale(this->staffFlameScale.x, this->staffFlameScale.y, this->staffFlameScale.z, MTXMODE_APPLY); + gSPSegment(POLY_XLU_DISP++, 0x08, + Gfx_TwoTexScroll(play->state.gfxCtx, 0, 0, 0, 32, 64, 1, 0, + ((this->staffFlameScroll * 10) - (play->state.frames * 20)) % 512, 32, 128)); + gDPPipeSync(POLY_XLU_DISP++); + + if ((this->type == EN_WIZ_TYPE_FIRE) || (this->type == EN_WIZ_TYPE_FIRE_NO_BGM)) { + gDPSetPrimColor(POLY_XLU_DISP++, 0x80, 0x80, 255, 255, 170, 255); + gDPSetEnvColor(POLY_XLU_DISP++, 255, 50, 0, 255); + } else { + gDPSetPrimColor(POLY_XLU_DISP++, 0x80, 0x80, 170, 255, 255, 255); + gDPSetEnvColor(POLY_XLU_DISP++, 0, 50, 255, 255); + } + + Matrix_Mult(&play->billboardMtxF, MTXMODE_APPLY); + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_XLU_DISP++, gEffFire1DL); + + CLOSE_DISPS(play->state.gfxCtx); +} diff --git a/src/overlays/actors/ovl_En_Wiz/z_en_wiz.h b/src/overlays/actors/ovl_En_Wiz/z_en_wiz.h index a1ae32032..3d18abab2 100644 --- a/src/overlays/actors/ovl_En_Wiz/z_en_wiz.h +++ b/src/overlays/actors/ovl_En_Wiz/z_en_wiz.h @@ -2,6 +2,16 @@ #define Z_EN_WIZ_H #include "global.h" +#include "objects/object_wiz/object_wiz.h" + +#define EN_WIZ_GET_SWITCHFLAG(thisx) ((thisx)->params & 0x7F) +#define EN_WIZ_GET_TYPE(thisx) (((thisx)->params >> 8) & 0xFF) + +typedef enum { + /* 0 */ EN_WIZ_TYPE_FIRE, + /* 1 */ EN_WIZ_TYPE_ICE, + /* 2 */ EN_WIZ_TYPE_FIRE_NO_BGM, // does not request the mini-boss BGM +} EnWizType; struct EnWiz; @@ -9,15 +19,62 @@ typedef void (*EnWizActionFunc)(struct EnWiz*, PlayState*); typedef struct EnWiz { /* 0x000 */ Actor actor; - /* 0x144 */ char unk_144[0x268]; + /* 0x144 */ SkelAnime skelAnime; + /* 0x188 */ Vec3s jointTable[WIZROBE_LIMB_MAX]; + /* 0x200 */ Vec3s morphTable[WIZROBE_LIMB_MAX]; + /* 0x278 */ SkelAnime ghostSkelAnime; + /* 0x2BC */ Vec3s ghostBaseJointTable[WIZROBE_LIMB_MAX]; + /* 0x334 */ Vec3s ghostMorphTable[WIZROBE_LIMB_MAX]; /* 0x3AC */ EnWizActionFunc actionFunc; - /* 0x3B0 */ char unk_3B0[0xA]; - /* 0x3BA */ s16 unk_3BA; - /* 0x3BC */ char unk_3BC[0x8C]; - /* 0x448 */ s32 unk_448; - /* 0x44C */ char unk_44C[0x2FE]; - /* 0x74A */ s16 unk_74A; - /* 0x74C */ char unk_74C[0x634]; + /* 0x3B0 */ s16 action; + /* 0x3B2 */ s16 timer; + /* 0x3B4 */ s16 introCutsceneTimer; + /* 0x3B6 */ s16 fightState; + /* 0x3B8 */ s16 staffFlameScroll; + /* 0x3BA */ s16 hasActiveProjectile; + /* 0x3BC */ s16 hasRunToEveryPlatform; // used for the second phase cutscene to make sure the Wizrobe visits every platform + /* 0x3BE */ s16 unk_3BE; // unused, inferred from surrounding members + /* 0x3C0 */ s16 rotationalVelocity; + /* 0x3C2 */ s16 alpha; + /* 0x3C4 */ s16 platformLightAlpha; + /* 0x3C6 */ s16 targetPlatformLightAlpha; + /* 0x3C8 */ s16 introCutsceneCameraAngle; + /* 0x3CA */ u8 shouldStartTimer; + /* 0x3CB */ u8 introCutsceneState; + /* 0x3CC */ s32 musicStartTimer; + /* 0x3D0 */ f32 endFrame; + /* 0x3D4 */ f32 scale; + /* 0x3D8 */ Vec3f staffFlamePos; + /* 0x3E4 */ Vec3f staffFlameScale; + /* 0x3F0 */ Vec3f staffTargetFlameScale; + /* 0x3FC */ Vec3f unk_3FC; // unused, inferred from surrounding members + /* 0x408 */ Vec3f unk_408; // unused, inferred from surrounding members + /* 0x414 */ Vec3f platformLightPos; + /* 0x420 */ Actor* platforms[10]; + /* 0x448 */ Actor* freezard; + /* 0x44C */ s16 animLoopCounter; + /* 0x450 */ f32 unk_450; // set to 1.0f, but never used + /* 0x454 */ ColliderJntSph ghostColliders; + /* 0x474 */ ColliderJntSphElement ghostColliderElements[10]; + /* 0x6F4 */ ColliderCylinder collider; + /* 0x740 */ s32 platformCount; + /* 0x744 */ s32 nextPlatformIndex; // used for the second phase cutscene to dictate where the Wizrobe should run to next + /* 0x748 */ s16 curPlatformIndex; + /* 0x74A */ s16 type; + /* 0x74C */ s16 switchFlag; + /* 0x74E */ s16 subCamId; + /* 0x750 */ s16 isDead; + /* 0x752 */ s16 drawDmgEffTimer; + /* 0x754 */ s16 drawDmgEffType; + /* 0x758 */ f32 drawDmgEffScale; + /* 0x75C */ f32 drawDmgEffFrozenSteamScale; + /* 0x760 */ Vec3f bodyPartsPos[12]; + /* 0x7F0 */ s16 bodyPartsPosIndex; + /* 0x7F2 */ s16 ghostAlpha[10]; + /* 0x806 */ s16 ghostNextPlatformIndex[10]; + /* 0x81C */ Vec3f ghostPos[10]; + /* 0x894 */ Vec3s ghostRot[10]; + /* 0x8D0 */ Vec3s ghostJointTables[10][WIZROBE_LIMB_MAX]; } EnWiz; // size = 0xD80 extern const ActorInit En_Wiz_InitVars; diff --git a/src/overlays/actors/ovl_En_Wiz_Brock/z_en_wiz_brock.c b/src/overlays/actors/ovl_En_Wiz_Brock/z_en_wiz_brock.c index d49e71c08..ce13687a7 100644 --- a/src/overlays/actors/ovl_En_Wiz_Brock/z_en_wiz_brock.c +++ b/src/overlays/actors/ovl_En_Wiz_Brock/z_en_wiz_brock.c @@ -1,7 +1,7 @@ /* * File: z_en_wiz_brock.c * Overlay: ovl_En_Wiz_Brock - * Description: Wizzrobe Warp Platform + * Description: Wizrobe Warp Platform */ #include "z_en_wiz_brock.h" @@ -11,13 +11,6 @@ #define THIS ((EnWizBrock*)thisx) -typedef enum { - PLATFORM_TYPE_INACTIVE, - PLATFORM_TYPE_FIRE, - PLATFORM_TYPE_ICE, - PLATFORM_TYPE_MAX, -} PlatformType; - void EnWizBrock_Init(Actor* thisx, PlayState* play); void EnWizBrock_Destroy(Actor* thisx, PlayState* play); void EnWizBrock_Update(Actor* thisx, PlayState* play); @@ -26,7 +19,7 @@ void EnWizBrock_Draw(Actor* thisx, PlayState* play); void EnWizBrock_SetupUpdateStatus(EnWizBrock* this, PlayState* play); void EnWizBrock_UpdateStatus(EnWizBrock* this, PlayState* play); -s16 platformCount = 0; +s16 sPlatformIndex = 0; const ActorInit En_Wiz_Brock_InitVars = { ACTOR_EN_WIZ_BROCK, @@ -45,13 +38,13 @@ void EnWizBrock_Init(Actor* thisx, PlayState* play) { CollisionHeader* colHeader = NULL; DynaPolyActor_Init(&this->dyna, 0); - CollisionHeader_GetVirtual(&object_wiz_Colheader_001690, &colHeader); + CollisionHeader_GetVirtual(&gWizrobePlatformCol, &colHeader); this->dyna.bgId = DynaPoly_SetBgActor(play, &play->colCtx.dyna, &this->dyna.actor, colHeader); this->dyna.actor.colChkInfo.mass = MASS_IMMOVABLE; this->dyna.actor.colChkInfo.health = 3; this->unk_1A6 = 0; Actor_SetScale(&this->dyna.actor, 0.01f); - this->platformNum = platformCount++; + this->platformIndex = sPlatformIndex++; this->actionFunc = EnWizBrock_SetupUpdateStatus; this->dyna.actor.scale.x = this->dyna.actor.scale.y = this->dyna.actor.scale.z = 0.01f; this->alpha = 255.0f; @@ -68,12 +61,12 @@ void EnWizBrock_SetupUpdateStatus(EnWizBrock* this, PlayState* play) { } /** - * @brief Checks the platform status, when the Wizzrobe is defeated, which triggers timer to + * @brief Checks the platform status, when the Wizrobe is defeated, which triggers timer to * count up to 30 at which point the platforms are despawned. */ void EnWizBrock_UpdateStatus(EnWizBrock* this, PlayState* play) { - if (this->platformType == PLATFORM_TYPE_INACTIVE) { - if (this->dyna.actor.colChkInfo.health != PLATFORM_TYPE_MAX) { + if (this->platformType == EN_WIZ_BROCK_PLATFORM_TYPE_INACTIVE) { + if (this->dyna.actor.colChkInfo.health != EN_WIZ_BROCK_PLATFORM_TYPE_MAX) { this->platformType = this->dyna.actor.colChkInfo.health; } } @@ -115,30 +108,30 @@ void EnWizBrock_Draw(Actor* thisx, PlayState* play) { Scene_SetRenderModeXlu(play, 0, 1); gDPPipeSync(POLY_OPA_DISP++); gDPSetEnvColor(POLY_OPA_DISP++, 255, 255, 255, 255); - Gfx_DrawDListOpa(play, gWizzrobePlatform); + Gfx_DrawDListOpa(play, gWizrobePlatformDL); } else { Scene_SetRenderModeXlu(play, 1, 2); gDPPipeSync(POLY_XLU_DISP++); gDPSetEnvColor(POLY_XLU_DISP++, 255, 255, 255, (s16)this->alpha); - Gfx_DrawDListXlu(play, gWizzrobePlatform); + Gfx_DrawDListXlu(play, gWizrobePlatformDL); } CLOSE_DISPS(play->state.gfxCtx); - if (this->platformType != PLATFORM_TYPE_INACTIVE) { + if (this->platformType != EN_WIZ_BROCK_PLATFORM_TYPE_INACTIVE) { OPEN_DISPS(play->state.gfxCtx); - AnimatedMat_Draw(play, Lib_SegmentedToVirtual(&gWizzrobePlatformTexAnim)); + AnimatedMat_Draw(play, Lib_SegmentedToVirtual(&gWizrobePlatformCenterTexAnim)); gDPPipeSync(POLY_XLU_DISP++); gDPSetPrimColor(POLY_XLU_DISP++, 0x80, 0x80, 255, 255, 255, 255); - if (this->platformType == PLATFORM_TYPE_FIRE) { + if (this->platformType == EN_WIZ_BROCK_PLATFORM_TYPE_FIRE) { gDPSetEnvColor(POLY_XLU_DISP++, 255, 00, 100, (s16)this->alpha); } else { gDPSetEnvColor(POLY_XLU_DISP++, 50, 00, 255, (s16)this->alpha); } gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); - gSPDisplayList(POLY_XLU_DISP++, &gWizzrobePlatformCenter); + gSPDisplayList(POLY_XLU_DISP++, &gWizrobePlatformCenterDL); CLOSE_DISPS(play->state.gfxCtx); } diff --git a/src/overlays/actors/ovl_En_Wiz_Brock/z_en_wiz_brock.h b/src/overlays/actors/ovl_En_Wiz_Brock/z_en_wiz_brock.h index 0f0150697..3b23d08b0 100644 --- a/src/overlays/actors/ovl_En_Wiz_Brock/z_en_wiz_brock.h +++ b/src/overlays/actors/ovl_En_Wiz_Brock/z_en_wiz_brock.h @@ -3,6 +3,13 @@ #include "global.h" +typedef enum { + /* 0 */ EN_WIZ_BROCK_PLATFORM_TYPE_INACTIVE, + /* 1 */ EN_WIZ_BROCK_PLATFORM_TYPE_FIRE, + /* 2 */ EN_WIZ_BROCK_PLATFORM_TYPE_ICE, + /* 3 */ EN_WIZ_BROCK_PLATFORM_TYPE_MAX, +} EnWizBrockPlatformType; + struct EnWizBrock; typedef void (*EnWizBrockActionFunc)(struct EnWizBrock*, PlayState*); @@ -12,8 +19,8 @@ typedef struct EnWizBrock { /* 0x15C */ UNK_TYPE1 unk_15C[0x44]; /* 0x1A0 */ EnWizBrockActionFunc actionFunc; /* 0x1A4 */ s16 timer; // Counter for despawing blocks (Max of 37) - /* 0x1A6 */ s16 unk_1A6; // TODO: set but not used maybe used in wizzrobe? - /* 0x1A8 */ s16 platformNum; // Numeric identifier for platform + /* 0x1A6 */ s16 unk_1A6; // set to 0, but never used + /* 0x1A8 */ s16 platformIndex; // Numeric identifier for platform /* 0x1AA */ s16 platformType; // Determines element type for platform (ice/fire) /* 0x1AC */ f32 alpha; } EnWizBrock; // size = 0x1B0 diff --git a/src/overlays/actors/ovl_En_Wiz_Fire/z_en_wiz_fire.c b/src/overlays/actors/ovl_En_Wiz_Fire/z_en_wiz_fire.c index 666a5156b..eea112f89 100644 --- a/src/overlays/actors/ovl_En_Wiz_Fire/z_en_wiz_fire.c +++ b/src/overlays/actors/ovl_En_Wiz_Fire/z_en_wiz_fire.c @@ -1,7 +1,7 @@ /* * File: z_en_wiz_fire.c * Overlay: ovl_En_Wiz_Fire - * Description: Wizzrobe Fire/Ice Attack + * Description: Wizrobe Fire/Ice Attack */ #include "z_en_wiz_fire.h" @@ -17,18 +17,25 @@ void EnWizFire_Destroy(Actor* thisx, PlayState* play); void EnWizFire_Update(Actor* thisx, PlayState* play); void EnWizFire_Draw(Actor* thisx, PlayState* play); -void func_80A4984C(EnWizFire* this, PlayState* play); -void func_80A49A44(EnWizFire* this, PlayState* play); -void func_80A49F38(EnWizFire* this, PlayState* play); -void func_80A49FD8(EnWizFire* this, PlayState* play); -void func_80A4A11C(EnWizFire* this, PlayState* play); -void func_80A4A608(EnWizFire* this, PlayState* play); -void func_80A4BAB4(Actor* thisx, PlayState* play); -void func_80A4BC74(EnWizFire* this, Vec3f* arg1, Vec3f* arg2); -void func_80A4BDDC(EnWizFire* this, PlayState* play); -void func_80A4BF78(EnWizFire* this, PlayState* play); +void EnWiz_SetupMoveMagicProjectile(EnWizFire* this, PlayState* play); +void EnWiz_MoveMagicProjectile(EnWizFire* this, PlayState* play); +void EnWiz_SetupSmallFlame(EnWizFire* this, PlayState* play); +void EnWiz_SmallFlame(EnWizFire* this, PlayState* play); +void EnWiz_Pool(EnWizFire* this, PlayState* play); +void EnWiz_KillMagicProjectile(EnWizFire* this, PlayState* play); +void EnWizFire_DrawSmallFlame(Actor* thisx, PlayState* play); +void EnWizFire_InitializeEffect(EnWizFire* this, Vec3f* pos, Vec3f* accel); +void EnWizFire_UpdateEffects(EnWizFire* this, PlayState* play); +void EnWizFire_DrawEffects(EnWizFire* this, PlayState* play); -static s32 D_80A4C1C0 = 0; +typedef enum { + /* 0 */ EN_WIZ_FIRE_ACTION_MOVE_MAGIC_PROJECTILE, + /* 1 */ EN_WIZ_FIRE_ACTION_SMALL_FLAME, + /* 2 */ EN_WIZ_FIRE_ACTION_POOL, + /* 3 */ EN_WIZ_FIRE_ACTION_KILL_MAGIC_PROJECTILE, +} EnWizFireAction; + +static s32 sPoolHitByIceArrow = false; const ActorInit En_Wiz_Fire_InitVars = { ACTOR_EN_WIZ_FIRE, @@ -66,48 +73,52 @@ void EnWizFire_Init(Actor* thisx, PlayState* play) { EnWizFire* this = THIS; Collider_InitAndSetCylinder(play, &this->collider, &this->actor, &sCylinderInit); - this->unk_162 = this->actor.params; + this->type = EN_WIZ_FIRE_GET_TYPE(&this->actor); this->actor.targetMode = 3; - this->unk_172 = 10; - this->unk_1FC = 255.0f; + this->wallCheckTimer = 10; + this->alpha = 255.0f; this->actor.flags &= ~ACTOR_FLAG_1; if (!Player_HasMirrorShieldEquipped(play)) { this->collider.info.toucher.dmgFlags = 0x20000000; } - switch (this->unk_162) { - case 4: - this->unk_166 = 1; + switch (this->type) { + case EN_WIZ_FIRE_TYPE_ICE_MAGIC_PROJECTILE: + this->isIceType = true; this->collider.info.toucher.damage = 8; this->collider.info.toucher.effect = 2; this->collider.info.bumper.dmgFlags = (0x1000000 | 0x800 | 0x200 | 0x2); - this->unk_162 = 0; - - case 0: - if (this->unk_162 == 4) { - this->unk_162 = 0; + this->type = EN_WIZ_FIRE_TYPE_MAGIC_PROJECTILE; + // fallthrough + case EN_WIZ_FIRE_TYPE_MAGIC_PROJECTILE: + if (this->type == EN_WIZ_FIRE_TYPE_ICE_MAGIC_PROJECTILE) { + this->type = EN_WIZ_FIRE_TYPE_MAGIC_PROJECTILE; this->collider.info.toucher.damage = 8; } - - case 1: - case 3: - this->actionFunc = func_80A4984C; + // fallthrough + case EN_WIZ_FIRE_TYPE_ARCING_MAGIC_PROJECTILE: + case EN_WIZ_FIRE_TYPE_REFLECTED_MAGIC_PROJECTILE: + this->actionFunc = EnWiz_SetupMoveMagicProjectile; break; - case 2: - this->actor.draw = func_80A4BAB4; - this->unk_170 = Rand_S16Offset(0, 10000); - this->unk_160 = 1; + case EN_WIZ_FIRE_TYPE_SMALL_FLAME: + this->actor.draw = EnWizFire_DrawSmallFlame; + this->smallFlameScroll = Rand_S16Offset(0, 10000); + this->action = EN_WIZ_FIRE_ACTION_SMALL_FLAME; this->collider.info.toucher.damage = 2; - this->actionFunc = func_80A49F38; + this->actionFunc = EnWiz_SetupSmallFlame; + break; + + default: + break; } } void EnWizFire_Destroy(Actor* thisx, PlayState* play) { EnWizFire* this = THIS; - if (this->unk_162 == 0) { + if (this->type == EN_WIZ_FIRE_TYPE_MAGIC_PROJECTILE) { play->envCtx.lightSettings.fogColor[2] = 0; play->envCtx.lightSettings.fogColor[1] = play->envCtx.lightSettings.fogColor[2]; play->envCtx.lightSettings.fogColor[0] = play->envCtx.lightSettings.fogColor[2]; @@ -122,146 +133,159 @@ void EnWizFire_Destroy(Actor* thisx, PlayState* play) { play->envCtx.lightSettings.ambientColor[0] = play->envCtx.lightSettings.fogColor[2]; play->envCtx.lightSettings.fogNear = play->envCtx.lightSettings.fogColor[2]; } + Collider_DestroyCylinder(play, &this->collider); } -void func_80A4984C(EnWizFire* this, PlayState* play) { - Vec3f sp44 = { 0.0f, 0.0f, 0.0f }; +void EnWiz_SetupMoveMagicProjectile(EnWizFire* this, PlayState* play) { + Vec3f velocity = { 0.0f, 0.0f, 0.0f }; s32 i; - for (i = 0; i < ARRAY_COUNT(this->unk_178); i++) { - this->unk_178[i] = this->actor.world.pos; + for (i = 0; i < ARRAY_COUNT(this->magicProjectilePos); i++) { + this->magicProjectilePos[i] = this->actor.world.pos; } - this->unk_16E = 0; + this->lowestUsedIndex = 0; + Matrix_Push(); Matrix_RotateYS(this->actor.world.rot.y, MTXMODE_NEW); Matrix_RotateXS(this->actor.world.rot.x, MTXMODE_APPLY); - if (this->unk_162 != 0) { - sp44.z = randPlusMinusPoint5Scaled(2.0f) + 8.0f; + if (this->type != EN_WIZ_FIRE_TYPE_MAGIC_PROJECTILE) { + velocity.z = randPlusMinusPoint5Scaled(2.0f) + 8.0f; } else { - sp44.z = 12.0f; + velocity.z = 12.0f; } - Matrix_MultVec3f(&sp44, &this->actor.velocity); + Matrix_MultVec3f(&velocity, &this->actor.velocity); Matrix_Pop(); + this->actor.world.rot.x = this->actor.world.rot.y = this->actor.world.rot.z = 0; - this->unk_168 = 50; - if (this->unk_162 != 0) { + this->timer = 50; + + if (this->type != EN_WIZ_FIRE_TYPE_MAGIC_PROJECTILE) { this->actor.velocity.y = 10.0f; this->actor.gravity = -1.0f; - this->unk_150 = 0.01f; + this->targetScale = 0.01f; } else { - this->unk_150 = 0.02f; - this->unk_168 = 100; + this->targetScale = 0.02f; + this->timer = 100; } - this->unk_160 = 0; - this->actionFunc = func_80A49A44; + + this->action = EN_WIZ_FIRE_ACTION_MOVE_MAGIC_PROJECTILE; + this->actionFunc = EnWiz_MoveMagicProjectile; } -void func_80A49A44(EnWizFire* this, PlayState* play) { - Vec3f sp54 = { 0.0f, 0.0f, 0.0f }; +/** + * Moves all types of magic projectiles around, including arcing ones created by the + * Fire Wizrobe's attack or ones reflected by the Mirror Shield. + */ +void EnWiz_MoveMagicProjectile(EnWizFire* this, PlayState* play) { + Vec3f velocity = { 0.0f, 0.0f, 0.0f }; this->actor.world.rot.z += 5000; - if (this->unk_162 != 0) { - this->unk_150 = 0.01f; + if (this->type != EN_WIZ_FIRE_TYPE_MAGIC_PROJECTILE) { + this->targetScale = 0.01f; } else { - this->unk_150 = 0.02f; + this->targetScale = 0.02f; } - if ((this->unk_168 == 0) && (this->unk_14C < 0.001f)) { + if ((this->timer == 0) && (this->scale < 0.001f)) { Math_Vec3f_Copy(&this->actor.velocity, &gZeroVec3f); - this->unk_160 = 3; - this->unk_16A = 0; - this->actionFunc = func_80A4A608; + this->action = EN_WIZ_FIRE_ACTION_KILL_MAGIC_PROJECTILE; + this->increaseLowestUsedIndexTimer = 0; + this->actionFunc = EnWiz_KillMagicProjectile; return; } - if (this->unk_168 == 0) { - this->unk_150 = 0.0f; + if (this->timer == 0) { + this->targetScale = 0.0f; } - Math_ApproachF(&this->unk_14C, this->unk_150, 0.2f, 0.01f); + Math_ApproachF(&this->scale, this->targetScale, 0.2f, 0.01f); - if (this->unk_172 == 0) { - if ((this->actor.bgCheckFlags & 8) && (this->unk_162 == 0) && (this->unk_168 != 0) && + if (this->wallCheckTimer == 0) { + if ((this->actor.bgCheckFlags & 8) && (this->type == EN_WIZ_FIRE_TYPE_MAGIC_PROJECTILE) && (this->timer != 0) && (this->actor.bgCheckFlags & 8)) { - D_80A4C1C0 = 0; - this->unk_168 = 0; - this->unk_150 = 0.0f; + sPoolHitByIceArrow = false; + this->timer = 0; + this->targetScale = 0.0f; } } - if ((this->actor.bgCheckFlags & 1) && (this->unk_16A == 0)) { + if ((this->actor.bgCheckFlags & 1) && (this->poolTimer == 0)) { s32 i; - s16 phi_s0; - s32 temp; + s16 arcingProjectileRotY; + s32 pad; - if (this->unk_162 == 1) { - this->unk_16A = 10; + if (this->type == EN_WIZ_FIRE_TYPE_ARCING_MAGIC_PROJECTILE) { + this->increaseLowestUsedIndexTimer = 10; Matrix_Push(); Matrix_RotateYS((s16)randPlusMinusPoint5Scaled(0x100) + this->actor.world.rot.y, MTXMODE_NEW); - sp54.z = randPlusMinusPoint5Scaled(2.0f) + 8.0f; - Matrix_MultVec3f(&sp54, &this->actor.velocity); + velocity.z = randPlusMinusPoint5Scaled(2.0f) + 8.0f; + Matrix_MultVec3f(&velocity, &this->actor.velocity); Matrix_Pop(); this->actor.velocity.y = 6.0f; this->actor.gravity = -0.7f; - if (this->unk_164 == 0) { + if (!this->hasSpawnedSmallFlame) { Actor_Spawn(&play->actorCtx, play, ACTOR_EN_WIZ_FIRE, this->actor.world.pos.x, - this->actor.world.pos.y - 10.0f, this->actor.world.pos.z, 0, 0, 0, 2); - this->unk_164 = 1; + this->actor.world.pos.y - 10.0f, this->actor.world.pos.z, 0, 0, 0, + EN_WIZ_FIRE_TYPE_SMALL_FLAME); + this->hasSpawnedSmallFlame = true; } - this->unk_168 = 0; - this->unk_14C = 0.0f; + this->timer = 0; + this->scale = 0.0f; Math_Vec3f_Copy(&this->actor.velocity, &gZeroVec3f); - this->unk_160 = 3; - this->unk_16A = 0; - this->actionFunc = func_80A4A608; + this->action = EN_WIZ_FIRE_ACTION_KILL_MAGIC_PROJECTILE; + this->increaseLowestUsedIndexTimer = 0; + this->actionFunc = EnWiz_KillMagicProjectile; return; } - if ((this->unk_162 == 0) && (this->unk_168 != 0)) { + if ((this->type == EN_WIZ_FIRE_TYPE_MAGIC_PROJECTILE) && (this->timer != 0)) { if (this->actor.floorBgId == BGCHECK_SCENE) { - this->unk_16A = 100; - if (this->unk_166 == 0) { - phi_s0 = 0; + this->poolTimer = 100; + if (!this->isIceType) { + arcingProjectileRotY = 0; for (i = 0; i < 5; i++) { Actor_Spawn(&play->actorCtx, play, ACTOR_EN_WIZ_FIRE, this->actor.world.pos.x, - this->actor.world.pos.y, this->actor.world.pos.z, 0, phi_s0, 0, 1); - phi_s0 += BINANG_ADD((s32)randPlusMinusPoint5Scaled(0x1000), 0x3333); + this->actor.world.pos.y, this->actor.world.pos.z, 0, arcingProjectileRotY, 0, + EN_WIZ_FIRE_TYPE_ARCING_MAGIC_PROJECTILE); + arcingProjectileRotY += BINANG_ADD((s32)randPlusMinusPoint5Scaled(0x1000), 0x3333); } Actor_PlaySfxAtPos(&this->actor, NA_SE_IT_BOMB_EXPLOSION); - this->unk_16A = Rand_S16Offset(70, 30); - if (this->unk_16A != 0) { + this->poolTimer = Rand_S16Offset(70, 30); + if (this->poolTimer != 0) { Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_WIZ_EXP - SFX_FLAG); } - } else if (this->unk_16A != 0) { + } else if (this->poolTimer != 0) { Actor_PlaySfxAtPos(&this->actor, NA_SE_EV_ICE_FREEZE - SFX_FLAG); } + Math_Vec3f_Copy(&this->actor.velocity, &gZeroVec3f); - this->unk_168 = 0; - this->unk_160 = 2; - this->unk_14C = 0.0f; - this->actionFunc = func_80A4A11C; + this->timer = 0; + this->action = EN_WIZ_FIRE_ACTION_POOL; + this->scale = 0.0f; + this->actionFunc = EnWiz_Pool; } + return; } } - if ((this->unk_162 != 3) && (this->unk_168 != 0)) { + if ((this->type != EN_WIZ_FIRE_TYPE_REFLECTED_MAGIC_PROJECTILE) && (this->timer != 0)) { if (this->collider.base.acFlags & AC_HIT) { this->collider.base.acFlags &= ~AC_HIT; if (this->collider.info.acHitInfo->toucher.dmgFlags == 0x1000) { - this->unk_168 = 0; - this->unk_148 = 1; + this->timer = 0; + this->hitByIceArrow = true; SoundSource_PlaySfxAtFixedWorldPos(play, &this->actor.world.pos, 50, NA_SE_EV_ICE_MELT); } } @@ -272,104 +296,111 @@ void func_80A49A44(EnWizFire* this, PlayState* play) { this->collider.base.atFlags |= AT_TYPE_PLAYER; this->collider.info.toucher.dmgFlags = 0x20; this->collider.info.toucher.damage = 2; - this->unk_168 = 100; - this->unk_162 = 3; + this->timer = 100; + this->type = EN_WIZ_FIRE_TYPE_REFLECTED_MAGIC_PROJECTILE; this->actor.velocity.x *= -1.0f; this->actor.velocity.y *= -0.5f; this->actor.velocity.z *= -1.0f; if ((this->actor.parent != NULL) && (this->actor.parent->id == ACTOR_EN_WIZ) && (this->actor.parent->update != NULL)) { - ((EnWiz*)this->actor.parent)->unk_3BA = 0; + ((EnWiz*)this->actor.parent)->hasActiveProjectile = false; } } } } -void func_80A49F38(EnWizFire* this, PlayState* play) { - this->unk_150 = 0.02f; - this->unk_168 = Rand_S16Offset(50, 50); - this->unk_154 = randPlusMinusPoint5Scaled(1.0f) * 0.007f; - this->unk_158 = randPlusMinusPoint5Scaled(1.0f) * 0.005f; - this->unk_15C = randPlusMinusPoint5Scaled(1.0f) * 0.007f; - this->actionFunc = func_80A49FD8; +void EnWiz_SetupSmallFlame(EnWizFire* this, PlayState* play) { + this->targetScale = 0.02f; + this->timer = Rand_S16Offset(50, 50); + this->scaleMod.x = randPlusMinusPoint5Scaled(1.0f) * 0.007f; + this->scaleMod.y = randPlusMinusPoint5Scaled(1.0f) * 0.005f; + this->scaleMod.z = randPlusMinusPoint5Scaled(1.0f) * 0.007f; + this->actionFunc = EnWiz_SmallFlame; } -void func_80A49FD8(EnWizFire* this, PlayState* play) { - if (this->unk_168 > 10) { - Math_ApproachF(&this->unk_14C, this->unk_150, 0.3f, 0.01f); +/** + * Manages the small flame that is created when the arcing projectiles from the Fire Wizrobe's + * attack hit the floor. + */ +void EnWiz_SmallFlame(EnWizFire* this, PlayState* play) { + if (this->timer > 10) { + Math_ApproachF(&this->scale, this->targetScale, 0.3f, 0.01f); } else { - Math_ApproachF(&this->unk_14C, 2.0f * this->unk_150, 0.2f, 0.002f); - Math_ApproachZeroF(&this->unk_1FC, 1.0f, 35.0f); - if ((this->unk_168 == 0) && (this->unk_1FC < 2.0f)) { + Math_ApproachF(&this->scale, 2.0f * this->targetScale, 0.2f, 0.002f); + Math_ApproachZeroF(&this->alpha, 1.0f, 35.0f); + if ((this->timer == 0) && (this->alpha < 2.0f)) { Actor_MarkForDeath(&this->actor); } return; } if (this->collider.base.acFlags & AC_HIT) { - if (this->unk_168 != 0) { + if (this->timer != 0) { this->collider.base.acFlags &= ~AC_HIT; - if (this->unk_168 > 10) { - this->unk_168 -= 10; + if (this->timer > 10) { + this->timer -= 10; } if (this->collider.info.acHitInfo->toucher.dmgFlags == 0x1000) { - this->unk_168 = 0; - this->unk_148 = 1; + this->timer = 0; + this->hitByIceArrow = true; SoundSource_PlaySfxAtFixedWorldPos(play, &this->actor.world.pos, 50, NA_SE_EV_ICE_MELT); } } } - if (this->unk_168 != 0) { + if (this->timer != 0) { Actor_PlaySfxAtPos(&this->actor, NA_SE_EV_BURN_OUT - SFX_FLAG); } } -void func_80A4A11C(EnWizFire* this, PlayState* play) { +/** + * Manages the pool of fire or ice that is created when a magic projectile hits the floor. + */ +void EnWiz_Pool(EnWizFire* this, PlayState* play) { s32 pad; if ((this->actor.parent != NULL) && (this->actor.parent->id == ACTOR_EN_WIZ) && (this->actor.parent->update != NULL) && (this->actor.parent->colChkInfo.health == 0)) { - this->unk_16A = 0; - this->unk_174 = 1; + this->poolTimer = 0; + this->playerHitByIceProjectile = true; } - this->unk_16E++; + this->lowestUsedIndex++; - if (this->unk_16E > 10) { - this->unk_16E = 10; + if (this->lowestUsedIndex > 10) { + this->lowestUsedIndex = 10; } - if (this->unk_16A != 0) { - Math_ApproachF(&this->unk_200, 60.0f, 0.5f, 10.0f); - if (this->unk_166 == 1) { - Vec3f sp40 = { 0.0f, 0.0f, 0.0f }; - Vec3f sp34; + if (this->poolTimer != 0) { + Math_ApproachF(&this->blendScale, 60.0f, 0.5f, 10.0f); + if (this->isIceType == true) { + Vec3f accel = { 0.0f, 0.0f, 0.0f }; + Vec3f pos; - sp40.x = randPlusMinusPoint5Scaled(3.0f) / 10.0f; - sp40.y = 0.23f; - sp40.z = randPlusMinusPoint5Scaled(3.0f) / 10.0f; + accel.x = randPlusMinusPoint5Scaled(3.0f) / 10.0f; + accel.y = 0.23f; + accel.z = randPlusMinusPoint5Scaled(3.0f) / 10.0f; - Math_Vec3f_Copy(&sp34, &this->actor.world.pos); - sp34.x += randPlusMinusPoint5Scaled(150.0f); - sp34.z += randPlusMinusPoint5Scaled(150.0f); + Math_Vec3f_Copy(&pos, &this->actor.world.pos); + pos.x += randPlusMinusPoint5Scaled(150.0f); + pos.z += randPlusMinusPoint5Scaled(150.0f); - Math_ApproachF(&this->unk_1F0, 0.022f, 0.3f, 0.01f); - this->collider.dim.radius = this->unk_1F0 * 4300.0f; + Math_ApproachF(&this->poolScale, 0.022f, 0.3f, 0.01f); + this->collider.dim.radius = this->poolScale * 4300.0f; this->collider.dim.height = 30; this->collider.dim.yShift = 15; - func_80A4BC74(this, &sp34, &sp40); + EnWizFire_InitializeEffect(this, &pos, &accel); Actor_PlaySfxAtPos(&this->actor, NA_SE_EV_ICE_FREEZE - SFX_FLAG); return; } - Math_ApproachF(&this->unk_1F0, 0.02f, 0.3f, 0.002f); - Math_ApproachF(&this->unk_1F8, 0.02f, 0.3f, 0.002f); - Math_ApproachF(&this->unk_1F4, 0.02f, 0.3f, 0.2f); - this->collider.dim.radius = this->unk_1F0 * 4000.0f; - this->collider.dim.height = this->unk_1F4 * 1850.0f; + Math_ApproachF(&this->poolScale, 0.02f, 0.3f, 0.002f); + Math_ApproachF(&this->fireSmokeScale, 0.02f, 0.3f, 0.002f); + Math_ApproachF(&this->bigFlameScale, 0.02f, 0.3f, 0.2f); + this->collider.dim.radius = this->poolScale * 4000.0f; + this->collider.dim.height = this->bigFlameScale * 1850.0f; this->collider.dim.yShift = -15; if (this->collider.dim.height < 2) { @@ -378,231 +409,228 @@ void func_80A4A11C(EnWizFire* this, PlayState* play) { if (this->collider.base.acFlags & AC_HIT) { this->collider.base.acFlags &= ~AC_HIT; - if ((D_80A4C1C0 == 0) && (this->collider.info.acHitInfo->toucher.dmgFlags == 0x1000)) { - D_80A4C1C0 = 1; - this->unk_148 = 1; - this->unk_16A = 0; + if (!sPoolHitByIceArrow && (this->collider.info.acHitInfo->toucher.dmgFlags == 0x1000)) { + sPoolHitByIceArrow = true; + this->hitByIceArrow = true; + this->poolTimer = 0; SoundSource_PlaySfxAtFixedWorldPos(play, &this->actor.world.pos, 50, NA_SE_EV_ICE_MELT); } } + this->actor.world.pos.y = this->actor.floorHeight + 10.0f; Actor_SetFocus(&this->actor, 0.0f); return; } - Math_ApproachZeroF(&this->unk_200, 0.2f, 3.0f); + Math_ApproachZeroF(&this->blendScale, 0.2f, 3.0f); - if (this->unk_166 == 1) { - Math_ApproachZeroF(&this->unk_1F0, 0.046f, 0.001f); + if (this->isIceType == true) { + Math_ApproachZeroF(&this->poolScale, 0.046f, 0.001f); Actor_PlaySfxAtPos(&this->actor, NA_SE_EV_ICE_FREEZE - SFX_FLAG); - if (this->unk_164 == 0) { - if ((this->actor.parent != NULL) && (this->actor.parent->id == ACTOR_EN_WIZ) && (this->unk_1F0 < 0.05f)) { + if (!this->shouldPoolFadeOut) { + if ((this->actor.parent != NULL) && (this->actor.parent->id == ACTOR_EN_WIZ) && (this->poolScale < 0.05f)) { EnWiz* wiz = (EnWiz*)this->actor.parent; this->collider.dim.yShift = -15; - this->unk_164 = 1; - wiz->unk_3BA = 0; + this->shouldPoolFadeOut = true; + wiz->hasActiveProjectile = false; } } - if ((this->unk_164 != 0) && (this->unk_1F0 < 0.05f)) { - Math_ApproachZeroF(&this->unk_1FC, 1.0f, 5.0f); + if (this->shouldPoolFadeOut && (this->poolScale < 0.05f)) { + Math_ApproachZeroF(&this->alpha, 1.0f, 5.0f); } - if ((this->unk_1F0 < 0.001f) && (this->unk_204 < 0.001f)) { - D_80A4C1C0 = 0; + if ((this->poolScale < 0.001f) && (this->blendScaleFrac < 0.001f)) { + sPoolHitByIceArrow = false; Actor_MarkForDeath(&this->actor); } + return; } - Math_ApproachZeroF(&this->unk_1F4, 0.1f, 0.01f); + Math_ApproachZeroF(&this->bigFlameScale, 0.1f, 0.01f); - if (this->unk_1F4 < 0.01f) { - Math_ApproachZeroF(&this->unk_1FC, 1.0f, 10.0f); - if ((this->unk_1FC < 10.0f) && (this->unk_204 < 0.001f)) { - D_80A4C1C0 = 0; - if ((this->actor.parent != NULL) && (this->unk_162 == 0) && (this->actor.parent->id == ACTOR_EN_WIZ) && - (this->actor.parent->update != NULL)) { + if (this->bigFlameScale < 0.01f) { + Math_ApproachZeroF(&this->alpha, 1.0f, 10.0f); + if ((this->alpha < 10.0f) && (this->blendScaleFrac < 0.001f)) { + sPoolHitByIceArrow = false; + if ((this->actor.parent != NULL) && (this->type == EN_WIZ_FIRE_TYPE_MAGIC_PROJECTILE) && + (this->actor.parent->id == ACTOR_EN_WIZ) && (this->actor.parent->update != NULL)) { EnWiz* wiz = (EnWiz*)this->actor.parent; - wiz->unk_3BA = 0; + wiz->hasActiveProjectile = false; } + Actor_MarkForDeath(&this->actor); } } } -void func_80A4A608(EnWizFire* this, PlayState* play) { - if (this->unk_16A == 0) { - this->unk_16A = 2; - this->unk_16E++; - if (this->unk_16E >= 6) { - if ((this->actor.parent != NULL) && (this->unk_162 == 0) && (this->actor.parent->id == ACTOR_EN_WIZ)) { +void EnWiz_KillMagicProjectile(EnWizFire* this, PlayState* play) { + if (this->increaseLowestUsedIndexTimer == 0) { + this->increaseLowestUsedIndexTimer = 2; + this->lowestUsedIndex++; + if (this->lowestUsedIndex >= 6) { + if ((this->actor.parent != NULL) && (this->type == EN_WIZ_FIRE_TYPE_MAGIC_PROJECTILE) && + (this->actor.parent->id == ACTOR_EN_WIZ)) { EnWiz* wiz = (EnWiz*)this->actor.parent; - D_80A4C1C0 = 0; + sPoolHitByIceArrow = false; if (wiz->actor.update != NULL) { - wiz->unk_3BA = 0; + wiz->hasActiveProjectile = false; } } + Actor_MarkForDeath(&this->actor); } } } void EnWizFire_Update(Actor* thisx, PlayState* play2) { - static Color_RGB8 D_80A4C234[] = { - { 100, 40, 40 }, { 180, 0x78, 80 }, { 155, 80, 80 }, { 125, 20, 0 }, - { 0, 0, 0 }, { 200, 250, 250 }, { 100, 250, 250 }, { 225, 255, 235 }, + // These are AmbientColor, DiffuseColor1, DiffuseColor2, and fogColor + static Color_RGB8 lightSettingsColors[] = { + { 100, 40, 40 }, { 180, 120, 80 }, { 155, 80, 80 }, { 125, 20, 0 }, // Fire + { 0, 0, 0 }, { 200, 250, 250 }, { 100, 250, 250 }, { 225, 255, 235 }, // Ice }; - static Color_RGBA8 D_80A4C24C = { 250, 250, 250, 255 }; - static Color_RGBA8 D_80A4C250 = { 180, 180, 180, 255 }; PlayState* play = play2; EnWizFire* this = THIS; Player* player = GET_PLAYER(play); s32 j; - s16 temp_s0; - s16 idx; + s16 randomScale; + s16 index; - Actor_SetScale(&this->actor, this->unk_14C); - func_80A4BDDC(this, play); - this->unk_204 = this->unk_200 / 60.0f; + Actor_SetScale(&this->actor, this->scale); + EnWizFire_UpdateEffects(this, play); + this->blendScaleFrac = this->blendScale / 60.0f; - if (this->unk_162 == 0) { + if (this->type == EN_WIZ_FIRE_TYPE_MAGIC_PROJECTILE) { Actor* wiz = this->actor.parent; - if ((wiz != NULL) && (wiz->id == ACTOR_EN_WIZ) && (wiz->update != NULL) && (((EnWiz*)wiz)->unk_74A != 2)) { - f32 phi_f0; + if ((wiz != NULL) && (wiz->id == ACTOR_EN_WIZ) && (wiz->update != NULL) && + (((EnWiz*)wiz)->type != EN_WIZ_TYPE_FIRE_NO_BGM)) { + f32 fogNear; - idx = this->unk_166 * 4; - - phi_f0 = 970.0f; - if (this->unk_166 == 0) { - phi_f0 = 968.0f; + index = this->isIceType * 4; + fogNear = 970.0f; + if (!this->isIceType) { + fogNear = 968.0f; } - play->envCtx.lightSettings.fogNear = (phi_f0 - (s16)play->envCtx.unk_C4.fogNear) * this->unk_204; + play->envCtx.lightSettings.fogNear = (fogNear - (s16)play->envCtx.unk_C4.fogNear) * this->blendScaleFrac; play->envCtx.lightSettings.ambientColor[0] = - ((f32)D_80A4C234[idx].r - play->envCtx.unk_C4.ambientColor[0]) * this->unk_204; + ((f32)lightSettingsColors[index].r - play->envCtx.unk_C4.ambientColor[0]) * this->blendScaleFrac; play->envCtx.lightSettings.ambientColor[1] = - ((f32)D_80A4C234[idx].g - play->envCtx.unk_C4.ambientColor[1]) * this->unk_204; + ((f32)lightSettingsColors[index].g - play->envCtx.unk_C4.ambientColor[1]) * this->blendScaleFrac; play->envCtx.lightSettings.ambientColor[2] = - ((f32)D_80A4C234[idx].b - play->envCtx.unk_C4.ambientColor[2]) * this->unk_204; + ((f32)lightSettingsColors[index].b - play->envCtx.unk_C4.ambientColor[2]) * this->blendScaleFrac; - idx++; + index++; play->envCtx.lightSettings.diffuseColor1[0] = - ((f32)D_80A4C234[idx].r - play->envCtx.unk_C4.diffuseColor1[0]) * this->unk_204; + ((f32)lightSettingsColors[index].r - play->envCtx.unk_C4.diffuseColor1[0]) * this->blendScaleFrac; play->envCtx.lightSettings.diffuseColor1[1] = - ((f32)D_80A4C234[idx].g - play->envCtx.unk_C4.diffuseColor1[1]) * this->unk_204; + ((f32)lightSettingsColors[index].g - play->envCtx.unk_C4.diffuseColor1[1]) * this->blendScaleFrac; play->envCtx.lightSettings.diffuseColor1[2] = - ((f32)D_80A4C234[idx].b - play->envCtx.unk_C4.diffuseColor1[2]) * this->unk_204; + ((f32)lightSettingsColors[index].b - play->envCtx.unk_C4.diffuseColor1[2]) * this->blendScaleFrac; - idx++; + index++; play->envCtx.lightSettings.diffuseColor2[0] = - ((f32)D_80A4C234[idx].r - play->envCtx.unk_C4.diffuseColor[0]) * this->unk_204; + ((f32)lightSettingsColors[index].r - play->envCtx.unk_C4.diffuseColor[0]) * this->blendScaleFrac; play->envCtx.lightSettings.diffuseColor2[1] = - ((f32)D_80A4C234[idx].g - play->envCtx.unk_C4.diffuseColor[1]) * this->unk_204; + ((f32)lightSettingsColors[index].g - play->envCtx.unk_C4.diffuseColor[1]) * this->blendScaleFrac; play->envCtx.lightSettings.diffuseColor2[2] = - ((f32)D_80A4C234[idx].b - play->envCtx.unk_C4.diffuseColor[2]) * this->unk_204; + ((f32)lightSettingsColors[index].b - play->envCtx.unk_C4.diffuseColor[2]) * this->blendScaleFrac; - idx++; + index++; play->envCtx.lightSettings.fogColor[0] = - ((f32)D_80A4C234[idx].r - play->envCtx.unk_C4.fogColor[0]) * this->unk_204; + ((f32)lightSettingsColors[index].r - play->envCtx.unk_C4.fogColor[0]) * this->blendScaleFrac; play->envCtx.lightSettings.fogColor[1] = - ((f32)D_80A4C234[idx].g - play->envCtx.unk_C4.fogColor[1]) * this->unk_204; + ((f32)lightSettingsColors[index].g - play->envCtx.unk_C4.fogColor[1]) * this->blendScaleFrac; play->envCtx.lightSettings.fogColor[2] = - ((f32)D_80A4C234[idx].b - play->envCtx.unk_C4.fogColor[2]) * this->unk_204; + ((f32)lightSettingsColors[index].b - play->envCtx.unk_C4.fogColor[2]) * this->blendScaleFrac; } } - this->unk_170++; + this->smallFlameScroll++; this->actionFunc(this, play); this->actor.shape.yOffset = 10.0f; Actor_UpdatePos(&this->actor); - this->unk_178[0] = this->actor.world.pos; + this->magicProjectilePos[0] = this->actor.world.pos; - for (j = 8; j >= 0; j--) { - this->unk_178[j + 1] = this->unk_178[j]; + for (j = ARRAY_COUNT(this->magicProjectilePos) - 2; j >= 0; j--) { + this->magicProjectilePos[j + 1] = this->magicProjectilePos[j]; } this->actor.velocity.y += this->actor.gravity; - if (this->unk_172 != 0) { - this->unk_172--; - } - - if (this->unk_168 != 0) { - this->unk_168--; - } - - if (this->unk_16C != 0) { - this->unk_16C--; - } - - if (this->unk_16A != 0) { - this->unk_16A--; - } + DECR(this->wallCheckTimer); + DECR(this->timer); + DECR(this->steamSpawnTimer); + DECR(this->poolTimer); Actor_UpdateBgCheckInfo(play, &this->actor, 20.0f, 5.0f, 10, 0x1D); - if (((this->unk_148 != 0) || (D_80A4C1C0 != 0)) && (this->unk_16C == 0)) { - Vec3f sp70; - Vec3f sp64; - Vec3f sp58; - f32 sp54; + if ((this->hitByIceArrow || sPoolHitByIceArrow) && (this->steamSpawnTimer == 0)) { + Vec3f accel; + Vec3f velocity; + Vec3f pos; + f32 scaleStep; s32 i; - sp70.x = 0.0f; - sp70.y = 1.0f; - sp70.z = 0.0f; - sp64.x = 0.0f; - sp64.y = 1.0f; - sp64.z = 0.0f; + accel.x = 0.0f; + accel.y = 1.0f; + accel.z = 0.0f; + velocity.x = 0.0f; + velocity.y = 1.0f; + velocity.z = 0.0f; - sp54 = Rand_S16Offset(20, 10); - if (this->unk_162 == 0) { - sp54 = Rand_S16Offset(40, 20); + scaleStep = Rand_S16Offset(20, 10); + if (this->type == EN_WIZ_FIRE_TYPE_MAGIC_PROJECTILE) { + scaleStep = Rand_S16Offset(40, 20); } - this->unk_16C = Rand_S16Offset(2, 2); + this->steamSpawnTimer = Rand_S16Offset(2, 2); for (i = 0; i < 2; i++) { - temp_s0 = Rand_S16Offset(20, 20); - sp58.x = ((f32)((Rand_ZeroOne() < 0.5f) ? -1 : 1) * temp_s0) + this->actor.world.pos.x; - sp58.y = (Rand_ZeroOne() * 20.0f) + this->actor.floorHeight; - temp_s0 = Rand_S16Offset(20, 20); - sp58.z = ((f32)((Rand_ZeroOne() < .5f) ? -1 : 1) * temp_s0) + this->actor.world.pos.z; - func_800B0DE0(play, &sp58, &sp64, &sp70, &D_80A4C24C, &D_80A4C250, Rand_S16Offset(350, 100), sp54); + static Color_RGBA8 sSteamPrimColor = { 250, 250, 250, 255 }; + static Color_RGBA8 sSteamEnvColor = { 180, 180, 180, 255 }; + + randomScale = Rand_S16Offset(20, 20); + pos.x = ((f32)((Rand_ZeroOne() < 0.5f) ? -1 : 1) * randomScale) + this->actor.world.pos.x; + pos.y = (Rand_ZeroOne() * 20.0f) + this->actor.floorHeight; + randomScale = Rand_S16Offset(20, 20); + pos.z = ((f32)((Rand_ZeroOne() < .5f) ? -1 : 1) * randomScale) + this->actor.world.pos.z; + func_800B0DE0(play, &pos, &velocity, &accel, &sSteamPrimColor, &sSteamEnvColor, Rand_S16Offset(350, 100), + scaleStep); } } - if (this->unk_160 < 2) { - this->collider.dim.radius = (this->unk_14C * 15.0f) + 25.0f; - this->collider.dim.height = (this->unk_14C * 15.0f) + 25.0f; - this->collider.dim.yShift = (this->unk_14C * -0.75f) - 5.0f; + if (this->action < EN_WIZ_FIRE_ACTION_POOL) { + this->collider.dim.radius = (this->scale * 15.0f) + 25.0f; + this->collider.dim.height = (this->scale * 15.0f) + 25.0f; + this->collider.dim.yShift = (this->scale * -0.75f) - 5.0f; } - if (this->unk_162 == 2) { + if (this->type == EN_WIZ_FIRE_TYPE_SMALL_FLAME) { this->collider.dim.radius = 10; - this->collider.dim.height = this->unk_14C * 5000.0f; + this->collider.dim.height = this->scale * 5000.0f; this->collider.dim.yShift = 0; } if (this->collider.base.atFlags & AT_HIT) { this->collider.base.atFlags &= ~AT_HIT; - if (this->unk_162 == 0) { + if (this->type == EN_WIZ_FIRE_TYPE_MAGIC_PROJECTILE) { Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_WIZ_LAUGH2); if (player->invincibilityTimer > 0) { player->invincibilityTimer += 40; - if (this->unk_166 != 0) { + if (this->isIceType) { player->invincibilityTimer += 50; - this->unk_174 = 1; + this->playerHitByIceProjectile = true; } } } @@ -612,7 +640,8 @@ void EnWizFire_Update(Actor* thisx, PlayState* play2) { player->unk_AE8 = 90; } - if ((this->unk_148 == 0) && (D_80A4C1C0 == 0) && ((this->unk_162 != 0) || (this->unk_1FC > 200.0f))) { + if (!this->hitByIceArrow && !sPoolHitByIceArrow && + ((this->type != EN_WIZ_FIRE_TYPE_MAGIC_PROJECTILE) || (this->alpha > 200.0f))) { Collider_UpdateCylinder(&this->actor, &this->collider); CollisionCheck_SetAC(play, &play->colChkCtx, &this->collider.base); if (player->invincibilityTimer == 0) { @@ -621,61 +650,63 @@ void EnWizFire_Update(Actor* thisx, PlayState* play2) { } } -void func_80A4B0C8(EnWizFire* this, PlayState* play) { +void EnWizFire_DrawIcePool(EnWizFire* this, PlayState* play) { s32 pad; OPEN_DISPS(play->state.gfxCtx); - if ((this->unk_162 == 0) && (this->unk_160 == 2)) { + if ((this->type == EN_WIZ_FIRE_TYPE_MAGIC_PROJECTILE) && (this->action == EN_WIZ_FIRE_ACTION_POOL)) { func_8012C28C(play->state.gfxCtx); func_8012C2DC(play->state.gfxCtx); Matrix_Translate(this->actor.world.pos.x, this->actor.floorHeight, this->actor.world.pos.z, MTXMODE_NEW); - Matrix_Scale(this->unk_1F0, this->unk_1F0, this->unk_1F0, MTXMODE_APPLY); + Matrix_Scale(this->poolScale, this->poolScale, this->poolScale, MTXMODE_APPLY); gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); gDPPipeSync(POLY_XLU_DISP++); - gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, (s8)this->unk_1FC); + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, (s8)this->alpha); gDPSetEnvColor(POLY_XLU_DISP++, 0, 40, 30, 80); - gSPDisplayList(POLY_XLU_DISP++, object_wiz_DL_005190); - gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 215, 215, 215, (s8)this->unk_1FC); + gSPDisplayList(POLY_XLU_DISP++, gWizrobeIcePoolDL); + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 215, 215, 215, (s8)this->alpha); gDPSetEnvColor(POLY_XLU_DISP++, 255, 255, 255, 128); gSPSegment(POLY_XLU_DISP++, 0x08, - Gfx_TwoTexScroll(play->state.gfxCtx, 0, -play->state.frames & 0x7F, -play->state.frames & 0x7F, 0x20, - 0x40, 1, play->state.frames & 0xFF, play->state.frames & 0xFF, 0x10, 0x10)); + Gfx_TwoTexScroll(play->state.gfxCtx, 0, -play->state.frames & 0x7F, -play->state.frames & 0x7F, 32, + 64, 1, play->state.frames & 0xFF, play->state.frames & 0xFF, 16, 16)); Matrix_RotateYS(0, MTXMODE_APPLY); gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); - gSPDisplayList(POLY_XLU_DISP++, object_wiz_DL_005750); + gSPDisplayList(POLY_XLU_DISP++, gWizrobeIcePoolShineDL); } - func_80A4BF78(this, play); + EnWizFire_DrawEffects(this, play); CLOSE_DISPS(play->state.gfxCtx); } -void func_80A4B33C(EnWizFire* this, PlayState* play2) { +void EnWizFire_DrawFirePoolAndFlame(EnWizFire* this, PlayState* play2) { PlayState* play = play2; OPEN_DISPS(play->state.gfxCtx); - if ((this->unk_162 == 0) && (this->unk_160 == 2)) { + if ((this->type == EN_WIZ_FIRE_TYPE_MAGIC_PROJECTILE) && (this->action == EN_WIZ_FIRE_ACTION_POOL)) { func_8012C28C(play->state.gfxCtx); func_8012C2DC(play->state.gfxCtx); + Matrix_Push(); Matrix_Translate(this->actor.world.pos.x, this->actor.floorHeight, this->actor.world.pos.z, MTXMODE_NEW); - Matrix_Scale(this->unk_1F0, this->unk_1F0, this->unk_1F0, MTXMODE_APPLY); + Matrix_Scale(this->poolScale, this->poolScale, this->poolScale, MTXMODE_APPLY); gSPSegment(POLY_XLU_DISP++, 0x08, Gfx_TwoTexScroll(play->state.gfxCtx, 0, -play->state.frames % 128, 0, 0x20, 0x20, 1, (play->state.frames * 2) % 128, 0, 0x20, 0x20)); gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); gDPPipeSync(POLY_XLU_DISP++); - gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 100, 40, 0, (s8)this->unk_1FC); + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 100, 40, 0, (s8)this->alpha); gDPSetEnvColor(POLY_XLU_DISP++, 255, 245, 255, 128); - gSPDisplayList(POLY_XLU_DISP++, object_wiz_DL_003120); + gSPDisplayList(POLY_XLU_DISP++, gWizrobeFirePoolDL); Matrix_Pop(); + Matrix_Push(); Matrix_Translate(this->actor.world.pos.x, this->actor.floorHeight, this->actor.world.pos.z, MTXMODE_NEW); Matrix_ReplaceRotation(&play->billboardMtxF); @@ -684,16 +715,17 @@ void func_80A4B33C(EnWizFire* this, PlayState* play2) { Gfx_TwoTexScroll(play->state.gfxCtx, 0, play->state.frames % 128, (-play->state.frames * 6) % 256, 0x20, 0x40, 1, (play->state.frames * 2) % 128, (-play->state.frames * 6) % 256, 0x20, 0x40)); - gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 80, 0, 0, (s8)this->unk_1FC); + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 80, 0, 0, (s8)this->alpha); gDPPipeSync(POLY_XLU_DISP++); gDPSetEnvColor(POLY_XLU_DISP++, 0, 0, 0, 100); - Matrix_Scale(this->unk_1F8, this->unk_1F8, this->unk_1F8, MTXMODE_APPLY); + Matrix_Scale(this->fireSmokeScale, this->fireSmokeScale, this->fireSmokeScale, MTXMODE_APPLY); gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); - gSPDisplayList(POLY_XLU_DISP++, object_wiz_DL_003640); + gSPDisplayList(POLY_XLU_DISP++, gWizrobeFireSmokeDL); Matrix_Pop(); + Matrix_Translate(this->actor.world.pos.x, this->actor.floorHeight, this->actor.world.pos.z, MTXMODE_NEW); Matrix_ReplaceRotation(&play->billboardMtxF); @@ -704,10 +736,10 @@ void func_80A4B33C(EnWizFire* this, PlayState* play2) { gDPPipeSync(POLY_XLU_DISP++); gDPSetEnvColor(POLY_XLU_DISP++, 200, 235, 240, 128); - Matrix_Scale(this->unk_1F4, this->unk_1F4, this->unk_1F4, MTXMODE_APPLY); + Matrix_Scale(this->bigFlameScale, this->bigFlameScale, this->bigFlameScale, MTXMODE_APPLY); gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); - gSPDisplayList(POLY_XLU_DISP++, object_wiz_DL_003FC0); + gSPDisplayList(POLY_XLU_DISP++, gWizrobeBigFlameDL); } CLOSE_DISPS(play->state.gfxCtx); @@ -724,11 +756,11 @@ void EnWizFire_Draw(Actor* thisx, PlayState* play2) { func_8012C2DC(play->state.gfxCtx); Matrix_Push(); - for (i = 9; i >= this->unk_16E; i--) { - f32 temp_f20 = this->actor.scale.x - (i * -0.0019f); + for (i = ARRAY_COUNT(this->magicProjectilePos) - 1; i >= this->lowestUsedIndex; i--) { + f32 scale = this->actor.scale.x - (i * -0.0019f); - if (temp_f20 > 0.0f) { - if (this->unk_166 == 0) { + if (scale > 0.0f) { + if (!this->isIceType) { gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255 - (i * 25), 0, 255 - (i * 25)); gDPSetEnvColor(POLY_XLU_DISP++, 255 - (i * 25), 0, 0, 0); } else { @@ -736,14 +768,14 @@ void EnWizFire_Draw(Actor* thisx, PlayState* play2) { gDPSetEnvColor(POLY_XLU_DISP++, 220, 255, 235, 0); } - Matrix_Translate(this->unk_178[i].x, this->unk_178[i].y + this->actor.shape.yOffset, this->unk_178[i].z, - MTXMODE_NEW); - Matrix_Scale(temp_f20, temp_f20, temp_f20, MTXMODE_APPLY); + Matrix_Translate(this->magicProjectilePos[i].x, this->magicProjectilePos[i].y + this->actor.shape.yOffset, + this->magicProjectilePos[i].z, MTXMODE_NEW); + Matrix_Scale(scale, scale, scale, MTXMODE_APPLY); Matrix_ReplaceRotation(&play->billboardMtxF); Matrix_RotateZS(this->actor.world.rot.z, MTXMODE_APPLY); gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); - gSPDisplayList(POLY_XLU_DISP++, object_wiz_DL_002B40); + gSPDisplayList(POLY_XLU_DISP++, gWizrobeMagicProjectileDL); } } @@ -751,92 +783,92 @@ void EnWizFire_Draw(Actor* thisx, PlayState* play2) { CLOSE_DISPS(play->state.gfxCtx); - if (this->unk_166 == 0) { - func_80A4B33C(this, play); + if (!this->isIceType) { + EnWizFire_DrawFirePoolAndFlame(this, play); } else { - func_80A4B0C8(this, play); + EnWizFire_DrawIcePool(this, play); } } -void func_80A4BAB4(Actor* thisx, PlayState* play) { +void EnWizFire_DrawSmallFlame(Actor* thisx, PlayState* play) { s32 pad; EnWizFire* this = THIS; OPEN_DISPS(play->state.gfxCtx); Matrix_Translate(this->actor.world.pos.x, this->actor.floorHeight + 20.0f, this->actor.world.pos.z, MTXMODE_NEW); - Matrix_Scale(this->unk_14C + this->unk_154, this->unk_14C + this->unk_158, this->unk_14C + this->unk_15C, + Matrix_Scale(this->scale + this->scaleMod.x, this->scale + this->scaleMod.y, this->scale + this->scaleMod.z, MTXMODE_APPLY); gSPSegment(POLY_XLU_DISP++, 0x08, - Gfx_TwoTexScroll(play->state.gfxCtx, 0, 0, 0, 0x20, 0x20, 1, this->unk_170 & 0x7F, - (-this->unk_170 * 10) & 0x7F, 0x20, 0x20)); - gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, 100, 50, 0, (s8)this->unk_1FC); + Gfx_TwoTexScroll(play->state.gfxCtx, 0, 0, 0, 32, 32, 1, this->smallFlameScroll & 0x7F, + (-this->smallFlameScroll * 10) & 0x7F, 32, 32)); + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, 100, 50, 0, (s8)this->alpha); gDPSetEnvColor(POLY_XLU_DISP++, 200, 235, 245, 255); Matrix_Mult(&play->billboardMtxF, MTXMODE_APPLY); gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); - gSPDisplayList(POLY_XLU_DISP++, object_wiz_DL_002630); + gSPDisplayList(POLY_XLU_DISP++, gWizrobeSmallFlameDL); CLOSE_DISPS(play->state.gfxCtx); } -void func_80A4BC74(EnWizFire* this, Vec3f* arg1, Vec3f* arg2) { +void EnWizFire_InitializeEffect(EnWizFire* this, Vec3f* pos, Vec3f* accel) { s16 i; - EnWizFireStruct* ptr = this->unk_254; + EnWizFireEffect* effect = &this->effects[0]; - for (i = 0; i < ARRAY_COUNT(this->unk_254); i++, ptr++) { - if (ptr->unk_00 == 0) { - ptr->unk_00 = 1; - Math_Vec3f_Copy(&ptr->unk_1C, &gZeroVec3f); - ptr->unk_01 = Rand_ZeroFloat(100.0f); - ptr->unk_10 = *arg1; - ptr->unk_28 = *arg2; - ptr->unk_0C = (Rand_ZeroFloat(5.0f) + 20.0f) * 0.001f; - ptr->unk_08 = 0; - ptr->unk_06 = 0; + for (i = 0; i < ARRAY_COUNT(this->effects); i++, effect++) { + if (!effect->isEnabled) { + effect->isEnabled = true; + Math_Vec3f_Copy(&effect->velocity, &gZeroVec3f); + effect->smokeScroll = Rand_ZeroFloat(100.0f); + effect->pos = *pos; + effect->accel = *accel; + effect->scale = (Rand_ZeroFloat(5.0f) + 20.0f) * 0.001f; + effect->shouldDecreaseAlpha = 0; + effect->alpha = 0; break; } } } -void func_80A4BDDC(EnWizFire* this, PlayState* play) { +void EnWizFire_UpdateEffects(EnWizFire* this, PlayState* play) { s32 i; - EnWizFireStruct* ptr = &this->unk_254[0]; + EnWizFireEffect* effect = &this->effects[0]; - for (i = 0; i < ARRAY_COUNT(this->unk_254); i++, ptr++) { - if (ptr->unk_00 != 0) { - ptr->unk_01++; + for (i = 0; i < ARRAY_COUNT(this->effects); i++, effect++) { + if (effect->isEnabled) { + effect->smokeScroll++; - ptr->unk_10.x += ptr->unk_1C.x; - ptr->unk_10.y += ptr->unk_1C.y; - ptr->unk_10.z += ptr->unk_1C.z; + effect->pos.x += effect->velocity.x; + effect->pos.y += effect->velocity.y; + effect->pos.z += effect->velocity.z; - ptr->unk_1C.x += ptr->unk_28.x; - ptr->unk_1C.y += ptr->unk_28.y; - ptr->unk_1C.z += ptr->unk_28.z; + effect->velocity.x += effect->accel.x; + effect->velocity.y += effect->accel.y; + effect->velocity.z += effect->accel.z; - if (ptr->unk_08 == 0) { - ptr->unk_06 += 10; - if (ptr->unk_06 >= 100) { - ptr->unk_08 = 1; + if (!effect->shouldDecreaseAlpha) { + effect->alpha += 10; + if (effect->alpha >= 100) { + effect->shouldDecreaseAlpha = true; } } else { - ptr->unk_06 -= 8; - if (ptr->unk_06 <= 0) { - ptr->unk_06 = 0; - ptr->unk_00 = 0; + effect->alpha -= 8; + if (effect->alpha <= 0) { + effect->alpha = 0; + effect->isEnabled = false; } } } } } -void func_80A4BF78(EnWizFire* this, PlayState* play) { +void EnWizFire_DrawEffects(EnWizFire* this, PlayState* play) { s16 i; - u8 flag; - EnWizFireStruct* ptr = &this->unk_254[0]; + u8 materialFlag; + EnWizFireEffect* effect = &this->effects[0]; GraphicsContext* gfxCtx = play->state.gfxCtx; OPEN_DISPS(gfxCtx); @@ -844,27 +876,27 @@ void func_80A4BF78(EnWizFire* this, PlayState* play) { func_8012C28C(play->state.gfxCtx); func_8012C2DC(play->state.gfxCtx); - flag = false; - for (i = 0; i < ARRAY_COUNT(this->unk_254); i++, ptr++) { - if (ptr->unk_00 != 0) { - if (!flag) { - gSPDisplayList(POLY_XLU_DISP++, object_wiz_DL_000E70); - flag++; + materialFlag = false; + for (i = 0; i < ARRAY_COUNT(this->effects); i++, effect++) { + if (effect->isEnabled) { + if (!materialFlag) { + gSPDisplayList(POLY_XLU_DISP++, gWizrobeIceSmokeMaterialDL); + materialFlag++; } - gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 195, 225, 235, ptr->unk_06); + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 195, 225, 235, effect->alpha); gSPSegment(POLY_XLU_DISP++, 0x08, - Gfx_TwoTexScroll(play->state.gfxCtx, 0, (ptr->unk_01 * 3) & 0x7F, (ptr->unk_01 * 0xF) & 0xFF, - 0x20, 0x40, 1, 0, 0, 0x20, 0x20)); + Gfx_TwoTexScroll(play->state.gfxCtx, 0, (effect->smokeScroll * 3) & 0x7F, + (effect->smokeScroll * 0xF) & 0xFF, 32, 64, 1, 0, 0, 32, 32)); - Matrix_Translate(ptr->unk_10.x, ptr->unk_10.y, ptr->unk_10.z, MTXMODE_NEW); + Matrix_Translate(effect->pos.x, effect->pos.y, effect->pos.z, MTXMODE_NEW); Matrix_ReplaceRotation(&play->billboardMtxF); - Matrix_Scale(ptr->unk_0C, ptr->unk_0C, 1.0f, MTXMODE_APPLY); + Matrix_Scale(effect->scale, effect->scale, 1.0f, MTXMODE_APPLY); gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); gDPSetRenderMode(POLY_XLU_DISP++, G_RM_PASS, G_RM_AA_ZB_XLU_SURF2); gSPClearGeometryMode(POLY_XLU_DISP++, G_CULL_BACK | G_FOG); - gSPDisplayList(POLY_XLU_DISP++, object_wiz_DL_000FD8); + gSPDisplayList(POLY_XLU_DISP++, gWizrobeIceSmokeModelDL); } } diff --git a/src/overlays/actors/ovl_En_Wiz_Fire/z_en_wiz_fire.h b/src/overlays/actors/ovl_En_Wiz_Fire/z_en_wiz_fire.h index b628404bb..180192d4c 100644 --- a/src/overlays/actors/ovl_En_Wiz_Fire/z_en_wiz_fire.h +++ b/src/overlays/actors/ovl_En_Wiz_Fire/z_en_wiz_fire.h @@ -3,52 +3,65 @@ #include "global.h" +typedef enum { + /* 0 */ EN_WIZ_FIRE_TYPE_MAGIC_PROJECTILE, + /* 1 */ EN_WIZ_FIRE_TYPE_ARCING_MAGIC_PROJECTILE, + /* 2 */ EN_WIZ_FIRE_TYPE_SMALL_FLAME, + /* 3 */ EN_WIZ_FIRE_TYPE_REFLECTED_MAGIC_PROJECTILE, + /* 4 */ EN_WIZ_FIRE_TYPE_ICE_MAGIC_PROJECTILE +} EnWizFireType; + +#define EN_WIZ_FIRE_GET_TYPE(thisx) ((thisx)->params) + struct EnWizFire; typedef void (*EnWizFireActionFunc)(struct EnWizFire*, PlayState*); typedef struct { - /* 0x00 */ u8 unk_00; - /* 0x01 */ u8 unk_01; + /* 0x00 */ u8 isEnabled; + /* 0x01 */ u8 smokeScroll; /* 0x02 */ UNK_TYPE1 unk02[0x4]; - /* 0x06 */ s16 unk_06; - /* 0x08 */ s16 unk_08; - /* 0x0A */ UNK_TYPE1 unk0A[0x2]; - /* 0x0C */ f32 unk_0C; - /* 0x10 */ Vec3f unk_10; - /* 0x1C */ Vec3f unk_1C; - /* 0x28 */ Vec3f unk_28; -} EnWizFireStruct; // size = 0x34 + /* 0x06 */ s16 alpha; + /* 0x08 */ s16 shouldDecreaseAlpha; + /* 0x0C */ f32 scale; + /* 0x10 */ Vec3f pos; + /* 0x1C */ Vec3f velocity; + /* 0x28 */ Vec3f accel; +} EnWizFireEffect; // size = 0x34 typedef struct EnWizFire { /* 0x0000 */ Actor actor; /* 0x0144 */ EnWizFireActionFunc actionFunc; - /* 0x0148 */ u8 unk_148; - /* 0x014C */ f32 unk_14C; - /* 0x0150 */ f32 unk_150; - /* 0x0154 */ f32 unk_154; - /* 0x0158 */ f32 unk_158; - /* 0x015C */ f32 unk_15C; - /* 0x0160 */ s16 unk_160; - /* 0x0162 */ s16 unk_162; - /* 0x0164 */ u8 unk_164; - /* 0x0166 */ s16 unk_166; - /* 0x0168 */ s16 unk_168; - /* 0x016A */ s16 unk_16A; - /* 0x016C */ s16 unk_16C; - /* 0x016E */ s16 unk_16E; - /* 0x0170 */ s16 unk_170; - /* 0x0172 */ s16 unk_172; - /* 0x0174 */ s8 unk_174; - /* 0x0178 */ Vec3f unk_178[10]; - /* 0x01F0 */ f32 unk_1F0; - /* 0x01F4 */ f32 unk_1F4; - /* 0x01F8 */ f32 unk_1F8; - /* 0x01FC */ f32 unk_1FC; - /* 0x0200 */ f32 unk_200; - /* 0x0204 */ f32 unk_204; + /* 0x0148 */ u8 hitByIceArrow; + /* 0x014C */ f32 scale; + /* 0x0150 */ f32 targetScale; + /* 0x0154 */ Vec3f scaleMod; + /* 0x0160 */ s16 action; + /* 0x0162 */ s16 type; + /* 0x0164 */ union { + u8 shouldPoolFadeOut; + u8 hasSpawnedSmallFlame; + }; + /* 0x0166 */ s16 isIceType; + /* 0x0168 */ s16 timer; + /* 0x016A */ union { + s16 poolTimer; + s16 increaseLowestUsedIndexTimer; + }; + /* 0x016C */ s16 steamSpawnTimer; + /* 0x016E */ s16 lowestUsedIndex; + /* 0x0170 */ s16 smallFlameScroll; + /* 0x0172 */ s16 wallCheckTimer; // The projectile won't check for impacts with walls until this is zero + /* 0x0174 */ s8 playerHitByIceProjectile; // Set, but never used + /* 0x0178 */ Vec3f magicProjectilePos[10]; + /* 0x01F0 */ f32 poolScale; + /* 0x01F4 */ f32 bigFlameScale; + /* 0x01F8 */ f32 fireSmokeScale; + /* 0x01FC */ f32 alpha; + /* 0x0200 */ f32 blendScale; + /* 0x0204 */ f32 blendScaleFrac; /* 0x0208 */ ColliderCylinder collider; - /* 0x0254 */ EnWizFireStruct unk_254[200]; + /* 0x0254 */ EnWizFireEffect effects[200]; } EnWizFire; // size = 0x2AF4 extern const ActorInit En_Wiz_Fire_InitVars; diff --git a/tools/disasm/functions.txt b/tools/disasm/functions.txt index 519550a83..ef47869a5 100644 --- a/tools/disasm/functions.txt +++ b/tools/disasm/functions.txt @@ -10441,31 +10441,31 @@ 0x80A45164:("EnSekihi_Draw",), 0x80A45360:("EnWiz_Init",), 0x80A45568:("EnWiz_Destroy",), - 0x80A455C4:("func_80A455C4",), - 0x80A456A0:("func_80A456A0",), - 0x80A45CD8:("func_80A45CD8",), - 0x80A460A4:("func_80A460A4",), - 0x80A46280:("func_80A46280",), - 0x80A462F8:("func_80A462F8",), - 0x80A46414:("func_80A46414",), - 0x80A4668C:("func_80A4668C",), - 0x80A46764:("func_80A46764",), - 0x80A468CC:("func_80A468CC",), - 0x80A46990:("func_80A46990",), - 0x80A46C88:("func_80A46C88",), - 0x80A46CC4:("func_80A46CC4",), - 0x80A46DDC:("func_80A46DDC",), - 0x80A46E24:("func_80A46E24",), - 0x80A47000:("func_80A47000",), - 0x80A470D8:("func_80A470D8",), - 0x80A47298:("func_80A47298",), - 0x80A473B8:("func_80A473B8",), - 0x80A4767C:("func_80A4767C",), - 0x80A476C8:("func_80A476C8",), - 0x80A477E8:("func_80A477E8",), + 0x80A455C4:("EnWiz_ChangeAnim",), + 0x80A456A0:("EnWiz_HandleIntroCutscene",), + 0x80A45CD8:("EnWiz_SelectPlatform",), + 0x80A460A4:("EnWiz_MoveGhosts",), + 0x80A46280:("EnWiz_StartIntroCutscene",), + 0x80A462F8:("EnWiz_SetupAppear",), + 0x80A46414:("EnWiz_Appear",), + 0x80A4668C:("EnWiz_SetupDance",), + 0x80A46764:("EnWiz_Dance",), + 0x80A468CC:("EnWiz_SetupSecondPhaseCutscene",), + 0x80A46990:("EnWiz_SecondPhaseCutscene",), + 0x80A46C88:("EnWiz_SetupWindUp",), + 0x80A46CC4:("EnWiz_WindUp",), + 0x80A46DDC:("EnWiz_SetupAttack",), + 0x80A46E24:("EnWiz_Attack",), + 0x80A47000:("EnWiz_SetupDisappear",), + 0x80A470D8:("EnWiz_Disappear",), + 0x80A47298:("EnWiz_SetupDamaged",), + 0x80A473B8:("EnWiz_Damaged",), + 0x80A4767C:("EnWiz_SetupDead",), + 0x80A476C8:("EnWiz_Dead",), + 0x80A477E8:("EnWiz_UpdateDamage",), 0x80A47C6C:("EnWiz_Update",), - 0x80A47FCC:("func_80A47FCC",), - 0x80A48138:("func_80A48138",), + 0x80A47FCC:("EnWiz_PostLimbDrawOpa",), + 0x80A48138:("EnWiz_PostLimbDrawXlu",), 0x80A483B4:("EnWiz_Draw",), 0x80A48FE0:("EnWizBrock_Init",), 0x80A490B0:("EnWizBrock_Destroy",), @@ -10475,20 +10475,20 @@ 0x80A49308:("EnWizBrock_Draw",), 0x80A496A0:("EnWizFire_Init",), 0x80A497D4:("EnWizFire_Destroy",), - 0x80A4984C:("func_80A4984C",), - 0x80A49A44:("func_80A49A44",), - 0x80A49F38:("func_80A49F38",), - 0x80A49FD8:("func_80A49FD8",), - 0x80A4A11C:("func_80A4A11C",), - 0x80A4A608:("func_80A4A608",), + 0x80A4984C:("EnWiz_SetupMoveMagicProjectile",), + 0x80A49A44:("EnWiz_MoveMagicProjectile",), + 0x80A49F38:("EnWiz_SetupSmallFlame",), + 0x80A49FD8:("EnWiz_SmallFlame",), + 0x80A4A11C:("EnWiz_Pool",), + 0x80A4A608:("EnWiz_KillMagicProjectile",), 0x80A4A698:("EnWizFire_Update",), - 0x80A4B0C8:("func_80A4B0C8",), - 0x80A4B33C:("func_80A4B33C",), + 0x80A4B0C8:("EnWizFire_DrawIcePool",), + 0x80A4B33C:("EnWizFire_DrawFirePoolAndFlame",), 0x80A4B804:("EnWizFire_Draw",), - 0x80A4BAB4:("func_80A4BAB4",), - 0x80A4BC74:("func_80A4BC74",), - 0x80A4BDDC:("func_80A4BDDC",), - 0x80A4BF78:("func_80A4BF78",), + 0x80A4BAB4:("EnWizFire_DrawSmallFlame",), + 0x80A4BC74:("EnWizFire_InitializeEffect",), + 0x80A4BDDC:("EnWizFire_UpdateEffects",), + 0x80A4BF78:("EnWizFire_DrawEffects",), 0x80A4C490:("EffChange_Init",), 0x80A4C54C:("EffChange_Destroy",), 0x80A4C578:("EffChange_SetColors",), diff --git a/tools/disasm/variables.txt b/tools/disasm/variables.txt index eac44b02d..57d876acb 100644 --- a/tools/disasm/variables.txt +++ b/tools/disasm/variables.txt @@ -11517,18 +11517,18 @@ 0x80A452A4:("D_80A452A4","UNK_TYPE1","",0x1), 0x80A452B0:("D_80A452B0","UNK_TYPE4","",0x4), 0x80A48B30:("En_Wiz_InitVars","UNK_TYPE1","",0x1), - 0x80A48B50:("D_80A48B50","UNK_TYPE1","",0x1), - 0x80A48CB8:("D_80A48CB8","UNK_PTR","",0x4), - 0x80A48CC8:("D_80A48CC8","UNK_TYPE1","",0x1), - 0x80A48CF4:("D_80A48CF4","UNK_TYPE1","",0x1), - 0x80A48D14:("D_80A48D14","UNK_TYPE1","",0x1), - 0x80A48D34:("D_80A48D34","UNK_TYPE1","",0x1), - 0x80A48D4C:("D_80A48D4C","UNK_TYPE1","",0x1), - 0x80A48D54:("D_80A48D54","UNK_TYPE4","",0x4), - 0x80A48D60:("D_80A48D60","UNK_TYPE1","",0x1), - 0x80A48D64:("D_80A48D64","UNK_TYPE1","",0x1), - 0x80A48D68:("D_80A48D68","UNK_TYPE4","",0x4), - 0x80A48D74:("D_80A48D74","UNK_TYPE4","",0x4), + 0x80A48B50:("sJntSphElementsInit","UNK_TYPE1","",0x1), + 0x80A48CB8:("sJntSphInit","UNK_PTR","",0x4), + 0x80A48CC8:("sCylinderInit","UNK_TYPE1","",0x1), + 0x80A48CF4:("sFireWizrobeDamageTable","UNK_TYPE1","",0x1), + 0x80A48D14:("sIceWizrobeDamageTable","UNK_TYPE1","",0x1), + 0x80A48D34:("sAnimations","UNK_TYPE1","",0x1), + 0x80A48D4C:("sAnimationModes","UNK_TYPE1","",0x1), + 0x80A48D54:("staffTargetFlameScale","UNK_TYPE4","",0x4), + 0x80A48D60:("sDustPrimColor","UNK_TYPE1","",0x1), + 0x80A48D64:("sDustEnvTimer","UNK_TYPE1","",0x1), + 0x80A48D68:("staffFlamePos","UNK_TYPE4","",0x4), + 0x80A48D74:("staffFlamePos","UNK_TYPE4","",0x4), 0x80A48D80:("jtbl_80A48D80","UNK_PTR","",0x4), 0x80A48D98:("D_80A48D98","f32","",0x4), 0x80A48D9C:("D_80A48D9C","f32","",0x4), @@ -11556,15 +11556,15 @@ 0x80A495F8:("D_80A495F8","f32","",0x4), 0x80A495FC:("D_80A495FC","f32","",0x4), 0x80A49600:("D_80A49600","f32","",0x4), - 0x80A4C1C0:("D_80A4C1C0","UNK_TYPE4","",0x4), + 0x80A4C1C0:("sPoolHitByIceArrow","UNK_TYPE4","",0x4), 0x80A4C1C4:("En_Wiz_Fire_InitVars","UNK_TYPE1","",0x1), 0x80A4C1E4:("D_80A4C1E4","UNK_TYPE1","",0x1), 0x80A4C210:("D_80A4C210","UNK_TYPE4","",0x4), 0x80A4C21C:("D_80A4C21C","UNK_TYPE4","",0x4), 0x80A4C228:("D_80A4C228","UNK_TYPE4","",0x4), - 0x80A4C234:("D_80A4C234","UNK_TYPE1","",0x1), - 0x80A4C24C:("D_80A4C24C","UNK_TYPE1","",0x1), - 0x80A4C250:("D_80A4C250","UNK_TYPE1","",0x1), + 0x80A4C234:("lightSettingsColors","UNK_TYPE1","",0x1), + 0x80A4C24C:("sSteamPrimColor","UNK_TYPE1","",0x1), + 0x80A4C250:("sSteamEnvColor","UNK_TYPE1","",0x1), 0x80A4C260:("jtbl_80A4C260","UNK_PTR","",0x4), 0x80A4C274:("D_80A4C274","f32","",0x4), 0x80A4C278:("D_80A4C278","f32","",0x4), diff --git a/undefined_syms.txt b/undefined_syms.txt index aae06790f..073840341 100644 --- a/undefined_syms.txt +++ b/undefined_syms.txt @@ -1375,14 +1375,6 @@ D_060014C0 = 0x060014C0; D_060015B0 = 0x060015B0; D_06001E20 = 0x06001E20; -// ovl_En_Wiz - -D_06001860 = 0x06001860; -D_0600211C = 0x0600211C; -D_060025F0 = 0x060025F0; -D_060066C0 = 0x060066C0; -D_0600B320 = 0x0600B320; - // ovl_En_Zl4 D_06013328 = 0x06013328; From 82afae675b47fbbd90bad9bcd6e38325158082dc Mon Sep 17 00:00:00 2001 From: Tom Overton Date: Sat, 1 Oct 2022 09:08:47 -0700 Subject: [PATCH 02/10] Replace player animation names with original names derived from OoT3D/MM3D (#1103) --- assets/xml/misc/link_animetion.xml | 1350 ++++++++--------- assets/xml/objects/gameplay_keep.xml | 1350 ++++++++--------- .../actors/ovl_En_Minifrog/z_en_minifrog.c | 6 +- src/overlays/actors/ovl_En_Tab/z_en_tab.c | 2 +- src/overlays/actors/ovl_En_Yb/z_en_yb.c | 2 +- 5 files changed, 1355 insertions(+), 1355 deletions(-) diff --git a/assets/xml/misc/link_animetion.xml b/assets/xml/misc/link_animetion.xml index 788e0a49d..2bb5826dd 100644 --- a/assets/xml/misc/link_animetion.xml +++ b/assets/xml/misc/link_animetion.xml @@ -1,699 +1,699 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + - - - - - + + + + + - + - - - - - - - - - - - + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/xml/objects/gameplay_keep.xml b/assets/xml/objects/gameplay_keep.xml index 03ed9eef5..354c710bb 100644 --- a/assets/xml/objects/gameplay_keep.xml +++ b/assets/xml/objects/gameplay_keep.xml @@ -71,701 +71,701 @@ - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - - + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - - - - + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + diff --git a/src/overlays/actors/ovl_En_Minifrog/z_en_minifrog.c b/src/overlays/actors/ovl_En_Minifrog/z_en_minifrog.c index 1e92e1f77..399a8f659 100644 --- a/src/overlays/actors/ovl_En_Minifrog/z_en_minifrog.c +++ b/src/overlays/actors/ovl_En_Minifrog/z_en_minifrog.c @@ -411,7 +411,7 @@ void EnMinifrog_NextFrogReturned(EnMinifrog* this, PlayState* play) { this->actionFunc = EnMinifrog_ContinueChoirCutscene; this->flags &= ~(0x2 << MINIFROG_YELLOW | 0x2 << MINIFROG_CYAN | 0x2 << MINIFROG_PINK | 0x2 << MINIFROG_BLUE | 0x2 << MINIFROG_WHITE); - play->setPlayerTalkAnim(play, &gameplay_keep_Linkanim_00DEA8, 0); + play->setPlayerTalkAnim(play, &gPlayerAnim_link_normal_talk_free_wait, 0); } } @@ -442,7 +442,7 @@ void EnMinifrog_SetupNextFrogChoir(EnMinifrog* this, PlayState* play) { this->flags &= ~0x100; this->flags &= ~(0x2 << MINIFROG_YELLOW | 0x2 << MINIFROG_CYAN | 0x2 << MINIFROG_PINK | 0x2 << MINIFROG_BLUE | 0x2 << MINIFROG_WHITE); - play->setPlayerTalkAnim(play, &gameplay_keep_Linkanim_00DEA8, 0); + play->setPlayerTalkAnim(play, &gPlayerAnim_link_normal_talk_free_wait, 0); } else if (this->timer <= 0) { this->actionFunc = EnMinifrog_NextFrogReturned; this->timer = 30; @@ -462,7 +462,7 @@ void EnMinifrog_BeginChoirCutscene(EnMinifrog* this, PlayState* play) { this->timer = 5; func_801A1F00(3, NA_BGM_FROG_SONG); this->flags |= 0x100; - play->setPlayerTalkAnim(play, &gameplay_keep_Linkanim_00E2A8, 0); + play->setPlayerTalkAnim(play, &gPlayerAnim_pn_gakkiplay, 0); } else { ActorCutscene_SetIntentToPlay(this->actor.cutscene); } diff --git a/src/overlays/actors/ovl_En_Tab/z_en_tab.c b/src/overlays/actors/ovl_En_Tab/z_en_tab.c index 860ad9d0c..ffa557746 100644 --- a/src/overlays/actors/ovl_En_Tab/z_en_tab.c +++ b/src/overlays/actors/ovl_En_Tab/z_en_tab.c @@ -323,7 +323,7 @@ s32 func_80BE0D60(EnTab* this, PlayState* play) { this->unk_320++; if (this->unk_320 == 1) { - play->setPlayerTalkAnim(play, &gameplay_keep_Linkanim_00D568, 2); + play->setPlayerTalkAnim(play, &gPlayerAnim_link_demo_bikkuri, 2); } else if (this->unk_320 > 20) { play->setPlayerTalkAnim(play, NULL, 0); this->unk_320 = 0; diff --git a/src/overlays/actors/ovl_En_Yb/z_en_yb.c b/src/overlays/actors/ovl_En_Yb/z_en_yb.c index d28a06fa0..11474f01e 100644 --- a/src/overlays/actors/ovl_En_Yb/z_en_yb.c +++ b/src/overlays/actors/ovl_En_Yb/z_en_yb.c @@ -68,7 +68,7 @@ static ColliderCylinderInit sCylinderInit = { // assumption: draw uses two different skeleton functions, might be incompatible static AnimationHeader* gYbUnusedAnimations[] = { &object_yb_Anim_000200 }; -static LinkAnimationHeader* gLinkAnimations[] = { &gameplay_keep_Linkanim_00DF28, &gameplay_keep_Linkanim_00CF98 }; +static LinkAnimationHeader* gLinkAnimations[] = { &gPlayerAnim_link_normal_wait_free, &gPlayerAnim_alink_dance_loop }; static Vec3f D_80BFB2E8 = { 0.0f, 0.5f, 0.0f }; From 84d77d5101f08433f14e15e1c5fd0e5e51b5f6c0 Mon Sep 17 00:00:00 2001 From: Derek Hensley Date: Sat, 1 Oct 2022 21:00:52 -0700 Subject: [PATCH 03/10] EnMThunder Ok with some docs (#1082) * Match EnMThunder_Init * Match func_808B53C0 * Match func_808B65BC * Match func_808B6310 * Match func_808B5EEC * Matched func_808B60D4 * Match func_808B5F68 * Match func_808B5984 * Matched func_808B58CC * Matched EnMThunder_Destroy * Matched EnMThunder_Update * Matched EnMThunder_Draw * Matched data * Doc WIP * Code docs * Assets * PR * Rename one more function from OoT WIP docs * Update src/overlays/actors/ovl_En_M_Thunder/z_en_m_thunder.c Co-authored-by: engineer124 <47598039+engineer124@users.noreply.github.com> * PR Co-authored-by: engineer124 <47598039+engineer124@users.noreply.github.com> --- assets/xml/objects/gameplay_keep.xml | 29 +- include/functions.h | 2 +- spec | 3 +- src/overlays/actors/ovl_Eff_Dust/z_eff_dust.c | 4 +- src/overlays/actors/ovl_Eff_Dust/z_eff_dust.h | 2 +- .../actors/ovl_En_M_Thunder/z_en_m_thunder.c | 546 +++++++++++++++++- .../actors/ovl_En_M_Thunder/z_en_m_thunder.h | 27 +- src/overlays/actors/ovl_En_St/z_en_st.c | 4 +- tools/disasm/functions.txt | 16 +- 9 files changed, 583 insertions(+), 50 deletions(-) diff --git a/assets/xml/objects/gameplay_keep.xml b/assets/xml/objects/gameplay_keep.xml index 354c710bb..ee2bed429 100644 --- a/assets/xml/objects/gameplay_keep.xml +++ b/assets/xml/objects/gameplay_keep.xml @@ -915,18 +915,23 @@ - - - - - - - - - - - - + + + + + + + + + + + + + + + + + diff --git a/include/functions.h b/include/functions.h index 99e030cde..41f3308eb 100644 --- a/include/functions.h +++ b/include/functions.h @@ -3146,7 +3146,7 @@ void AudioSfx_LowerSfxSettingsReverb(Vec3f* pos, s8 isReverbLowered); // void func_8019F7D8(void); // void func_8019F830(void); void func_8019F88C(Vec3f* arg0, u16 sfxId, UNK_TYPE arg2); -// void func_8019F900(void); +void func_8019F900(Vec3f* pos, u8 chargeLevel); // void func_8019FA18(void); void func_8019FAD8(Vec3f* param_1, u16 sfxId, f32 param_3); void func_8019FB0C(Vec3f* arg0, u16 sfxId, f32 arg2, s32 arg3); diff --git a/spec b/spec index 9ad5e4cca..e2ea0c1b3 100644 --- a/spec +++ b/spec @@ -984,8 +984,7 @@ beginseg name "ovl_En_M_Thunder" compress include "build/src/overlays/actors/ovl_En_M_Thunder/z_en_m_thunder.o" - include "build/data/ovl_En_M_Thunder/ovl_En_M_Thunder.data.o" - include "build/data/ovl_En_M_Thunder/ovl_En_M_Thunder.reloc.o" + include "build/src/overlays/actors/ovl_En_M_Thunder/ovl_En_M_Thunder_reloc.o" endseg beginseg diff --git a/src/overlays/actors/ovl_Eff_Dust/z_eff_dust.c b/src/overlays/actors/ovl_Eff_Dust/z_eff_dust.c index b2d896a14..c517ad007 100644 --- a/src/overlays/actors/ovl_Eff_Dust/z_eff_dust.c +++ b/src/overlays/actors/ovl_Eff_Dust/z_eff_dust.c @@ -71,7 +71,7 @@ void EffDust_Init(Actor* thisx, PlayState* play) { this->dz = 0.8f; this->scalingFactor = 0.5f; break; - case EFF_DUST_TYPE_2: + case EFF_DUST_TYPE_SPIN_ATTACK_CHARGE: case EFF_DUST_TYPE_3: this->actionFunc = func_80919230; this->actor.draw = func_809199FC; @@ -203,7 +203,7 @@ void func_80919230(EffDust* this, PlayState* play) { if (this->distanceTraveled[i] >= 1.0f) { theta = randPlusMinusPoint5Scaled(0x10000); switch (this->actor.params) { - case EFF_DUST_TYPE_2: + case EFF_DUST_TYPE_SPIN_ATTACK_CHARGE: this->initialPositions[i].x = (Rand_ZeroOne() * 4500.0f) + 700.0f; if (this->initialPositions[i].x > 3000.0f) { this->initialPositions[i].y = (3000.0f * Rand_ZeroOne()) * Math_SinS(theta); diff --git a/src/overlays/actors/ovl_Eff_Dust/z_eff_dust.h b/src/overlays/actors/ovl_Eff_Dust/z_eff_dust.h index ec864ea4d..d73b5ce0e 100644 --- a/src/overlays/actors/ovl_Eff_Dust/z_eff_dust.h +++ b/src/overlays/actors/ovl_Eff_Dust/z_eff_dust.h @@ -24,7 +24,7 @@ typedef struct EffDust { typedef enum { /* 0x0 */ EFF_DUST_TYPE_0, /* 0x1 */ EFF_DUST_TYPE_1, - /* 0x2 */ EFF_DUST_TYPE_2, + /* 0x2 */ EFF_DUST_TYPE_SPIN_ATTACK_CHARGE, /* 0x3 */ EFF_DUST_TYPE_3, /* 0x4 */ EFF_DUST_TYPE_4, /* 0x5 */ EFF_DUST_TYPE_5 diff --git a/src/overlays/actors/ovl_En_M_Thunder/z_en_m_thunder.c b/src/overlays/actors/ovl_En_M_Thunder/z_en_m_thunder.c index b509cf789..fbfb17040 100644 --- a/src/overlays/actors/ovl_En_M_Thunder/z_en_m_thunder.c +++ b/src/overlays/actors/ovl_En_M_Thunder/z_en_m_thunder.c @@ -6,6 +6,8 @@ #include "z_en_m_thunder.h" #include "z64rumble.h" +#include "overlays/actors/ovl_Eff_Dust/z_eff_dust.h" +#include "objects/gameplay_keep/gameplay_keep.h" #define FLAGS (ACTOR_FLAG_10) @@ -16,7 +18,17 @@ void EnMThunder_Destroy(Actor* thisx, PlayState* play); void EnMThunder_Update(Actor* thisx, PlayState* play); void EnMThunder_Draw(Actor* thisx, PlayState* play); -#if 0 +void EnMThunder_UnkType_Update(Actor* thisx, PlayState* play); + +void EnMThunder_AdjustLights(PlayState* play, f32 arg1); + +void EnMThunder_Charge(EnMThunder* this, PlayState* play); +void EnMThunder_Spin_Attack(EnMThunder* this, PlayState* play); +void EnMThunder_SwordBeam_Attack(EnMThunder* this, PlayState* play); +void EnMThunder_UnkType_Attack(EnMThunder* this, PlayState* play); + +#define ENMTHUNDER_TYPE_MAX 4 + const ActorInit En_M_Thunder_InitVars = { ACTOR_EN_M_THUNDER, ACTORCAT_ITEMACTION, @@ -29,39 +41,533 @@ const ActorInit En_M_Thunder_InitVars = { (ActorFunc)EnMThunder_Draw, }; -// static ColliderCylinderInit sCylinderInit = { -static ColliderCylinderInit D_808B7120 = { - { COLTYPE_NONE, AT_ON | AT_TYPE_PLAYER, AC_NONE, OC1_NONE, OC2_TYPE_1, COLSHAPE_CYLINDER, }, - { ELEMTYPE_UNK2, { 0x01000000, 0x00, 0x00 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_NONE, BUMP_ON, OCELEM_ON, }, +static ColliderCylinderInit sCylinderInit = { + { + COLTYPE_NONE, + AT_ON | AT_TYPE_PLAYER, + AC_NONE, + OC1_NONE, + OC2_TYPE_1, + COLSHAPE_CYLINDER, + }, + { + ELEMTYPE_UNK2, + { 0x01000000, 0x00, 0x00 }, + { 0xF7CFFFFF, 0x00, 0x00 }, + TOUCH_ON | TOUCH_SFX_NONE, + BUMP_ON, + OCELEM_ON, + }, { 200, 200, 0, { 0, 0, 0 } }, }; -#endif +static u8 sDamages[] = { + 1, 2, 3, 4, // Regular + 1, 2, 3, 4, // Great Spin +}; -extern ColliderCylinderInit D_808B7120; +static u16 sChargingSfxIds[] = { + NA_SE_IT_ROLLING_CUT_LV2, // ENMTHUNDER_SUBTYPE_SPIN_GREAT + NA_SE_IT_ROLLING_CUT_LV1, // ENMTHUNDER_SUBTYPE_SPIN_REGULAR + NA_SE_IT_ROLLING_CUT_LV2, // ENMTHUNDER_SUBTYPE_SWORDBEAM_GREAT + NA_SE_IT_ROLLING_CUT_LV1, // ENMTHUNDER_SUBTYPE_SWORDBEAM_REGULAR +}; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_M_Thunder/func_808B53C0.s") +static f32 sScales[] = { 0.1f, 0.15f, 0.2f, 0.25f, 0.3f, 0.25f, 0.2f, 0.15f, 0.0f }; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_M_Thunder/EnMThunder_Init.s") +typedef enum { + /* 0 */ ENMTHUNDER_SUBTYPE_SPIN_GREAT, + /* 1 */ ENMTHUNDER_SUBTYPE_SPIN_REGULAR, + /* 2 */ ENMTHUNDER_SUBTYPE_SWORDBEAM_GREAT, + /* 3 */ ENMTHUNDER_SUBTYPE_SWORDBEAM_REGULAR +} EnMThunderSubType; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_M_Thunder/EnMThunder_Destroy.s") +void EnMThunder_UnkType_Setup(EnMThunder* this, PlayState* play) { + Player* player = GET_PLAYER(play); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_M_Thunder/func_808B5890.s") + this->actor.update = EnMThunder_UnkType_Update; + this->isCharging = false; + this->subtype = ENMTHUNDER_SUBTYPE_SPIN_REGULAR; + this->scaleTarget = 2; + this->actionFunc = EnMThunder_UnkType_Attack; + this->timer = 8; + this->lightColorFrac = 1.0f; + AudioSfx_PlaySfx(NA_SE_IT_ROLLING_CUT_LV1, &player->actor.projectedPos, 4, &gSfxDefaultFreqAndVolScale, + &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); + this->actor.child = NULL; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_M_Thunder/func_808B58CC.s") +void EnMThunder_Init(Actor* thisx, PlayState* play) { + s32 pad; + EnMThunder* this = THIS; + Player* player = GET_PLAYER(play); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_M_Thunder/func_808B5984.s") + Collider_InitCylinder(play, &this->collider); + Collider_SetCylinder(play, &this->collider, &this->actor, &sCylinderInit); + this->type = ENMTHUNDER_GET_TYPE(&this->actor); + Lights_PointNoGlowSetInfo(&this->lightInfo, this->actor.world.pos.x, this->actor.world.pos.y, + this->actor.world.pos.z, 255, 255, 255, 0); + this->lightNode = LightContext_InsertLight(play, &play->lightCtx, &this->lightInfo); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_M_Thunder/func_808B5EEC.s") + if (this->type == ENMTHUNDER_TYPE_UNK) { + EnMThunder_UnkType_Setup(this, play); + return; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_M_Thunder/func_808B5F68.s") + this->collider.dim.radius = 0; + this->collider.dim.height = 40; + this->collider.dim.yShift = -20; + this->timer = 8; + this->scroll = 0.0f; + this->actor.world.pos = player->bodyPartsPos[0]; + this->lightColorFrac = 0.0f; + this->adjustLightsArg1 = 0.0f; + this->actor.shape.rot.y = player->actor.shape.rot.y + 0x8000; + this->actor.shape.rot.x = -this->actor.world.rot.x; + this->actor.room = -1; + Actor_SetScale(&this->actor, 0.1f); + this->isCharging = false; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_M_Thunder/func_808B60D4.s") + if (player->stateFlags2 & PLAYER_STATE2_20000) { + if (!gSaveContext.save.playerData.isMagicAcquired || (gSaveContext.magicState != MAGIC_STATE_IDLE) || + ((ENMTHUNDER_GET_MAGIC_COST(&this->actor) != 0) && + !Magic_Consume(play, ENMTHUNDER_GET_MAGIC_COST(&this->actor), MAGIC_CONSUME_NOW))) { + AudioSfx_PlaySfx(NA_SE_IT_ROLLING_CUT, &player->actor.projectedPos, 4, &gSfxDefaultFreqAndVolScale, + &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); + AudioSfx_PlaySfx(NA_SE_IT_SWORD_SWING_HARD, &player->actor.projectedPos, 4, &gSfxDefaultFreqAndVolScale, + &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); + Actor_MarkForDeath(&this->actor); + return; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_M_Thunder/func_808B6310.s") + player->stateFlags2 &= ~PLAYER_STATE2_20000; + this->isCharging = false; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_M_Thunder/EnMThunder_Update.s") + if (gSaveContext.save.weekEventReg[23] & 2) { + player->unk_B08[0] = 1.0f; + this->collider.info.toucher.damage = sDamages[this->type + ENMTHUNDER_TYPE_MAX]; + this->subtype = ENMTHUNDER_SUBTYPE_SPIN_GREAT; + if (this->type == ENMTHUNDER_TYPE_GREAT_FAIRY_SWORD) { + this->scaleTarget = 6; + } else if (this->type == ENMTHUNDER_TYPE_GILDED_SWORD) { + this->scaleTarget = 4; + } else { + this->scaleTarget = 3; + } + } else { + player->unk_B08[0] = 0.5f; + this->collider.info.toucher.damage = sDamages[this->type]; + this->subtype = ENMTHUNDER_SUBTYPE_SPIN_REGULAR; + if (this->type == ENMTHUNDER_TYPE_GREAT_FAIRY_SWORD) { + this->scaleTarget = 4; + } else if (this->type == ENMTHUNDER_TYPE_GILDED_SWORD) { + this->scaleTarget = 3; + } else { + this->scaleTarget = 2; + } + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_M_Thunder/func_808B65BC.s") + if (player->meleeWeaponAnimation < PLAYER_MWA_SPIN_ATTACK_1H) { + this->subtype += ENMTHUNDER_SUBTYPE_SWORDBEAM_GREAT; + this->actionFunc = EnMThunder_SwordBeam_Attack; + this->timer = 1; + this->scaleTarget = 12; + this->collider.info.toucher.dmgFlags = DMG_SWORD_BEAM; + this->collider.info.toucher.damage = 3; + } else { + this->actionFunc = EnMThunder_Spin_Attack; + this->timer = 8; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_M_Thunder/EnMThunder_Draw.s") + AudioSfx_PlaySfx(NA_SE_IT_ROLLING_CUT_LV1, &player->actor.projectedPos, 4, &gSfxDefaultFreqAndVolScale, + &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); + + this->lightColorFrac = 1.0f; + } else { + this->actionFunc = EnMThunder_Charge; + } + + this->actor.child = NULL; +} + +void EnMThunder_Destroy(Actor* thisx, PlayState* play) { + EnMThunder* this = THIS; + + if (this->isCharging) { + Magic_Reset(play); + } + + Collider_DestroyCylinder(play, &this->collider); + EnMThunder_AdjustLights(play, 0.0f); + LightContext_RemoveLight(play, &play->lightCtx, this->lightNode); +} + +void EnMThunder_AdjustLights(PlayState* play, f32 arg1) { + func_800FD2B4(play, arg1, 850.0f, 0.2f, 0.0f); +} + +void EnMThunder_Spin_AttackNoMagic(EnMThunder* this, PlayState* play) { + Player* player = GET_PLAYER(play); + + if (player->stateFlags2 & PLAYER_STATE2_20000) { + if (player->meleeWeaponAnimation >= PLAYER_MWA_SPIN_ATTACK_1H) { + AudioSfx_PlaySfx(NA_SE_IT_ROLLING_CUT, &player->actor.projectedPos, 4, &gSfxDefaultFreqAndVolScale, + &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); + AudioSfx_PlaySfx(NA_SE_IT_SWORD_SWING_HARD, &player->actor.projectedPos, 4, &gSfxDefaultFreqAndVolScale, + &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); + } + Actor_MarkForDeath(&this->actor); + } else if (!(player->stateFlags1 & PLAYER_STATE1_1000)) { + Actor_MarkForDeath(&this->actor); + } +} + +void EnMThunder_Charge(EnMThunder* this, PlayState* play) { + Player* player = GET_PLAYER(play); + Actor* child = this->actor.child; + + this->unk1B0 = player->unk_B08[0]; + this->actor.world.pos = player->bodyPartsPos[0]; + this->actor.shape.rot.y = player->actor.shape.rot.y + 0x8000; + + if (!this->isCharging && (player->unk_B08[0] >= 0.1f)) { + if ((gSaveContext.magicState != MAGIC_STATE_IDLE) || + ((ENMTHUNDER_GET_MAGIC_COST(&this->actor) != 0) && + !Magic_Consume(play, ENMTHUNDER_GET_MAGIC_COST(&this->actor), MAGIC_CONSUME_WAIT_PREVIEW))) { + EnMThunder_Spin_AttackNoMagic(this, play); + this->actionFunc = EnMThunder_Spin_AttackNoMagic; + this->chargingAlpha = 0; + this->adjustLightsArg1 = 0.0f; + this->lightColorFrac = 0.0f; + return; + } + this->isCharging = true; + } + + if (player->unk_B08[0] >= 0.1f) { + Rumble_Request(0.0f, (s32)(player->unk_B08[0] * 150.0f), 2, (s32)(player->unk_B08[0] * 150.0f)); + } + + if (player->stateFlags2 & PLAYER_STATE2_20000) { + if ((child != NULL) && (child->update != NULL)) { + child->parent = NULL; + } + + if (player->unk_B08[0] <= 0.15f) { + if ((player->unk_B08[0] >= 0.1f) && (player->meleeWeaponAnimation >= PLAYER_MWA_SPIN_ATTACK_1H)) { + AudioSfx_PlaySfx(NA_SE_IT_ROLLING_CUT, &player->actor.projectedPos, 4, &gSfxDefaultFreqAndVolScale, + &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); + AudioSfx_PlaySfx(NA_SE_IT_SWORD_SWING_HARD, &player->actor.projectedPos, 4, &gSfxDefaultFreqAndVolScale, + &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); + } + Actor_MarkForDeath(&this->actor); + return; + } + + player->stateFlags2 &= ~PLAYER_STATE2_20000; + + if (ENMTHUNDER_GET_MAGIC_COST(&this->actor) != 0) { + gSaveContext.magicState = MAGIC_STATE_CONSUME_SETUP; + } + + if (player->unk_B08[0] < 0.85f) { + this->collider.info.toucher.damage = sDamages[this->type]; + this->subtype = ENMTHUNDER_SUBTYPE_SPIN_REGULAR; + if (this->type == ENMTHUNDER_TYPE_GREAT_FAIRY_SWORD) { + this->scaleTarget = 4; + } else if (this->type == ENMTHUNDER_TYPE_GILDED_SWORD) { + this->scaleTarget = 3; + } else { + this->scaleTarget = 2; + } + } else { + this->collider.info.toucher.damage = sDamages[this->type + ENMTHUNDER_TYPE_MAX]; + this->subtype = ENMTHUNDER_SUBTYPE_SPIN_GREAT; + if (this->type == ENMTHUNDER_TYPE_GREAT_FAIRY_SWORD) { + this->scaleTarget = 6; + } else if (this->type == ENMTHUNDER_TYPE_GILDED_SWORD) { + this->scaleTarget = 4; + } else { + this->scaleTarget = 3; + } + } + + if (player->meleeWeaponAnimation < PLAYER_MWA_SPIN_ATTACK_1H) { + this->subtype += ENMTHUNDER_SUBTYPE_SWORDBEAM_GREAT; + this->actionFunc = EnMThunder_SwordBeam_Attack; + this->timer = 1; + } else { + this->actionFunc = EnMThunder_Spin_Attack; + this->timer = 8; + } + + AudioSfx_PlaySfx(sChargingSfxIds[this->subtype], &player->actor.projectedPos, 4, &gSfxDefaultFreqAndVolScale, + &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); + + this->lightColorFrac = 1.0f; + + return; + } + + if (!(player->stateFlags1 & PLAYER_STATE1_1000)) { + if (this->actor.child != NULL) { + this->actor.child->parent = NULL; + } + Actor_MarkForDeath(&this->actor); + return; + } + + if (player->unk_B08[0] > 0.15f) { + this->chargingAlpha = 255; + if (this->actor.child == NULL) { + Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_EFF_DUST, this->actor.world.pos.x, + this->actor.world.pos.y, this->actor.world.pos.z, 0, this->actor.shape.rot.y, 0, + EFF_DUST_TYPE_SPIN_ATTACK_CHARGE); + } + this->adjustLightsArg1 += (((player->unk_B08[0] - 0.15f) * 1.5f) - this->adjustLightsArg1) * 0.5f; + } else if (player->unk_B08[0] > .1f) { + this->chargingAlpha = (s32)((player->unk_B08[0] - .1f) * 255.0f * 20.0f); + this->lightColorFrac = (player->unk_B08[0] - .1f) * 10.0f; + } else { + this->chargingAlpha = 0; + } + + if (player->unk_B08[0] > 0.85f) { + func_8019F900(&player->actor.projectedPos, 2); + } else if (player->unk_B08[0] > 0.15f) { + func_8019F900(&player->actor.projectedPos, 1); + } else if (player->unk_B08[0] > 0.1f) { + func_8019F900(&player->actor.projectedPos, 0); + } + + if (Play_InCsMode(play)) { + Actor_MarkForDeath(&this->actor); + } +} + +void func_808B5EEC(EnMThunder* this, PlayState* play) { + if (this->timer < 2) { + if (this->chargingAlpha < 40) { + this->chargingAlpha = 0; + } else { + this->chargingAlpha -= 40; + } + } + + this->scroll += 2.0f * this->alphaFrac; + + if (this->adjustLightsArg1 < this->lightColorFrac) { + this->adjustLightsArg1 = F32_LERPIMP(this->adjustLightsArg1, this->lightColorFrac, 0.1f); + } else { + this->adjustLightsArg1 = this->lightColorFrac; + } +} + +void EnMThunder_Spin_Attack(EnMThunder* this, PlayState* play) { + Player* player = GET_PLAYER(play); + + if (Math_StepToF(&this->lightColorFrac, 0.0f, 0.0625f)) { + Actor_MarkForDeath(&this->actor); + } else { + Math_SmoothStepToF(&this->actor.scale.x, (s32)this->scaleTarget, 0.6f, 0.8f, 0.0f); + Actor_SetScale(&this->actor, this->actor.scale.x); + this->collider.dim.radius = this->actor.scale.x * 30.0f; + Collider_UpdateCylinder(&this->actor, &this->collider); + CollisionCheck_SetAT(play, &play->colChkCtx, &this->collider.base); + } + + if (this->timer > 0) { + this->actor.world.pos.x = player->bodyPartsPos[0].x; + this->actor.world.pos.z = player->bodyPartsPos[0].z; + this->timer--; + } + + if (this->lightColorFrac > (6.0f / 10.0f)) { + this->alphaFrac = 1.0f; + } else { + this->alphaFrac = this->lightColorFrac * (10.0f / 6.0f); + } + + func_808B5EEC(this, play); + + if (Play_InCsMode(play)) { + Actor_MarkForDeath(&this->actor); + } +} + +void EnMThunder_SwordBeam_Attack(EnMThunder* this, PlayState* play) { + s32 pad[2]; + f32 sp2C; + + if (this->lightColorFrac > (9.0f / 10.0f)) { + this->alphaFrac = 1.0f; + } else { + this->alphaFrac = this->lightColorFrac * (10.0f / 9.0f); + } + + if (Math_StepToF(&this->lightColorFrac, 0.0f, 0.05f)) { + Actor_MarkForDeath(&this->actor); + } else { + sp2C = -80.0f * Math_CosS(this->actor.world.rot.x); + + this->actor.world.pos.x += sp2C * Math_SinS(this->actor.shape.rot.y); + this->actor.world.pos.z += sp2C * Math_CosS(this->actor.shape.rot.y); + this->actor.world.pos.y += -80.0f * Math_SinS(this->actor.world.rot.x); + + Math_SmoothStepToF(&this->actor.scale.x, this->scaleTarget, 0.6f, 2.0f, 0.0f); + Actor_SetScale(&this->actor, this->actor.scale.x); + + this->collider.dim.radius = this->actor.scale.x * 5.0f; + + this->collider.dim.pos.x = this->actor.world.pos.x; + this->collider.dim.pos.y = this->actor.world.pos.y; + this->collider.dim.pos.z = this->actor.world.pos.z; + + this->collider.dim.pos.x = + (Math_SinS(this->actor.shape.rot.y) * -5.0f * this->actor.scale.x) + this->actor.world.pos.x; + this->collider.dim.pos.y = this->actor.world.pos.y; + this->collider.dim.pos.z = + (Math_CosS(this->actor.shape.rot.y) * -5.0f * this->actor.scale.z) + this->actor.world.pos.z; + + CollisionCheck_SetAT(play, &play->colChkCtx, &this->collider.base); + } + + if (this->timer > 0) { + this->timer--; + } + + func_808B5EEC(this, play); +} + +void EnMThunder_UnkType_Attack(EnMThunder* this, PlayState* play) { + if (Math_StepToF(&this->lightColorFrac, 0.0f, 0.0625f)) { + Actor_MarkForDeath(&this->actor); + } else { + Math_SmoothStepToF(&this->actor.scale.x, (s32)this->scaleTarget, 0.6f, 0.8f, 0.0f); + Actor_SetScale(&this->actor, this->actor.scale.x); + } + + if (this->lightColorFrac > (6.0f / 10.0f)) { + this->alphaFrac = 1.0f; + } else { + this->alphaFrac = this->lightColorFrac * (10.0f / 6.0f); + } + + func_808B5EEC(this, play); +} + +void EnMThunder_Update(Actor* thisx, PlayState* play) { + EnMThunder* this = THIS; + + this->actionFunc(this, play); + EnMThunder_AdjustLights(play, this->adjustLightsArg1); + Lights_PointNoGlowSetInfo(&this->lightInfo, this->actor.world.pos.x, this->actor.world.pos.y, + this->actor.world.pos.z, this->lightColorFrac * 255.0f, this->lightColorFrac * 255.0f, + this->lightColorFrac * 100.0f, this->lightColorFrac * 800.0f); +} + +void EnMThunder_UnkType_Update(Actor* thisx, PlayState* play) { + EnMThunder* this = THIS; + + this->actionFunc(this, play); + Lights_PointNoGlowSetInfo(&this->lightInfo, this->actor.world.pos.x, this->actor.world.pos.y, + this->actor.world.pos.z, this->lightColorFrac * 255.0f, this->lightColorFrac * 255.0f, + this->lightColorFrac * 100.0f, this->lightColorFrac * 800.0f); +} + +void EnMThunder_Draw(Actor* thisx, PlayState* play2) { + PlayState* play = play2; + EnMThunder* this = THIS; + Player* player = GET_PLAYER(play); + f32 scale; + s32 y2Scroll; + + OPEN_DISPS(play->state.gfxCtx); + + func_8012C2DC(play->state.gfxCtx); + Matrix_Scale(0.02f, 0.02f, 0.02f, MTXMODE_APPLY); + + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + + switch (this->subtype) { + case ENMTHUNDER_SUBTYPE_SPIN_GREAT: + case ENMTHUNDER_SUBTYPE_SPIN_REGULAR: + gSPSegment(POLY_XLU_DISP++, 0x08, + Gfx_TwoTexScroll(play->state.gfxCtx, 0, 0xFF - ((u16)(s32)(this->scroll * 30.0f) & 0xFF), 0, 64, + 32, 1, 0xFF - ((u16)(s32)(this->scroll * 20.0f) & 0xFF), 0, 8, 8)); + break; + + case ENMTHUNDER_SUBTYPE_SWORDBEAM_GREAT: + case ENMTHUNDER_SUBTYPE_SWORDBEAM_REGULAR: + gSPSegment(POLY_XLU_DISP++, 0x08, + Gfx_TwoTexScroll(play->state.gfxCtx, 0, 0, 0, 16, 64, 1, 0, + 0x1FF - ((u16)(s32)(this->scroll * 10.0f) & 0x1FF), 32, 128)); + break; + + default: + break; + } + + switch (this->subtype) { + case ENMTHUNDER_SUBTYPE_SPIN_GREAT: + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, 255, 255, 170, (u16)(this->alphaFrac * 255.0f)); + gSPDisplayList(POLY_XLU_DISP++, gGreatSpinAttackDiskDL); + gSPDisplayList(POLY_XLU_DISP++, gGreatSpinAttackCylinderDL); + break; + + case ENMTHUNDER_SUBTYPE_SPIN_REGULAR: + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, 170, 255, 255, (u16)(this->alphaFrac * 255.0f)); + gSPDisplayList(POLY_XLU_DISP++, gSpinAttackDiskDL); + gSPDisplayList(POLY_XLU_DISP++, gSpinAttackCylinderDL); + break; + + case ENMTHUNDER_SUBTYPE_SWORDBEAM_REGULAR: + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, 170, 255, 255, (u16)(this->alphaFrac * 255.0f)); + gDPSetEnvColor(POLY_XLU_DISP++, 0, 100, 255, 128); + gSPDisplayList(POLY_XLU_DISP++, gSwordBeamDL); + break; + + case ENMTHUNDER_SUBTYPE_SWORDBEAM_GREAT: + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, 0, 255, 255, (u16)(this->alphaFrac * 255.0f)); + gDPSetEnvColor(POLY_XLU_DISP++, 200, 200, 200, 128); + gSPDisplayList(POLY_XLU_DISP++, gSwordBeamDL); + break; + + default: + break; + } + + Matrix_Mult(&player->mf_CC4, MTXMODE_NEW); + + if (this->type == ENMTHUNDER_TYPE_GILDED_SWORD) { + Matrix_Translate(0.0f, 220.0f, 0.0f, MTXMODE_APPLY); + Matrix_Scale(-1.2f, -0.8f, -0.6f, MTXMODE_APPLY); + Matrix_RotateXS(0x4000, MTXMODE_APPLY); + } else { + Matrix_Translate(0.0f, 220.0f, 0.0f, MTXMODE_APPLY); + Matrix_Scale(-0.7f, -0.6f, -0.4f, MTXMODE_APPLY); + Matrix_RotateXS(0x4000, MTXMODE_APPLY); + } + + if (this->unk1B0 >= 0.85f) { + scale = (sScales[play->gameplayFrames & 7] * 6.0f) + 1.0f; + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, 255, 255, 170, this->chargingAlpha); + gDPSetEnvColor(POLY_XLU_DISP++, 255, 100, 0, 128); + y2Scroll = 40; + } else { + scale = (sScales[play->gameplayFrames & 7] * 2.0f) + 1.0f; + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, 170, 255, 255, this->chargingAlpha); + gDPSetEnvColor(POLY_XLU_DISP++, 0, 100, 255, 128); + y2Scroll = 20; + } + + Matrix_Scale(1.0f, scale, scale, MTXMODE_APPLY); + + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPSegment(POLY_XLU_DISP++, 0x09, + Gfx_TwoTexScroll(play->state.gfxCtx, 0, (play->gameplayFrames * 5) & 0xFF, 0, 32, 32, 1, + (play->gameplayFrames * 20) & 0xFF, (play->gameplayFrames * y2Scroll) & 0xFF, 8, 8)); + gSPDisplayList(POLY_XLU_DISP++, gSpinAttackChargingDL); + + CLOSE_DISPS(play->state.gfxCtx); +} diff --git a/src/overlays/actors/ovl_En_M_Thunder/z_en_m_thunder.h b/src/overlays/actors/ovl_En_M_Thunder/z_en_m_thunder.h index 14d022770..7ac851e92 100644 --- a/src/overlays/actors/ovl_En_M_Thunder/z_en_m_thunder.h +++ b/src/overlays/actors/ovl_En_M_Thunder/z_en_m_thunder.h @@ -5,13 +5,36 @@ struct EnMThunder; +#define ENMTHUNDER_GET_TYPE(thisx) ((thisx)->params & 0xFF) +#define ENMTHUNDER_GET_MAGIC_COST(thisx) (((thisx)->params & 0xFF00) >> 8) + +typedef enum { + /* 0x00 */ ENMTHUNDER_TYPE_KOKIRI_SWORD, + /* 0x01 */ ENMTHUNDER_TYPE_RAZOR_SWORD, + /* 0x02 */ ENMTHUNDER_TYPE_GILDED_SWORD, + /* 0x03 */ ENMTHUNDER_TYPE_GREAT_FAIRY_SWORD, + /* 0x80 */ ENMTHUNDER_TYPE_UNK = 0x80 +} EnMThunderType; + typedef void (*EnMThunderActionFunc)(struct EnMThunder*, PlayState*); typedef struct EnMThunder { /* 0x000 */ Actor actor; - /* 0x144 */ char unk_144[0x74]; + /* 0x144 */ ColliderCylinder collider; + /* 0x190 */ LightNode* lightNode; + /* 0x194 */ LightInfo lightInfo; + /* 0x1A4 */ f32 lightColorFrac; + /* 0x1A8 */ f32 alphaFrac; + /* 0x1AC */ f32 scroll; + /* 0x1B0 */ f32 unk1B0; + /* 0x1B4 */ f32 adjustLightsArg1; /* 0x1B8 */ EnMThunderActionFunc actionFunc; - /* 0x1BC */ char unk_1BC[0x8]; + /* 0x1BC */ u16 timer; + /* 0x1BE */ u8 subtype; + /* 0x1BF */ u8 type; + /* 0x1C0 */ u8 chargingAlpha; + /* 0x1C1 */ u8 scaleTarget; + /* 0x1C2 */ u8 isCharging; } EnMThunder; // size = 0x1C4 extern const ActorInit En_M_Thunder_InitVars; diff --git a/src/overlays/actors/ovl_En_St/z_en_st.c b/src/overlays/actors/ovl_En_St/z_en_st.c index 7d0dcbf11..ecc2b85b2 100644 --- a/src/overlays/actors/ovl_En_St/z_en_st.c +++ b/src/overlays/actors/ovl_En_St/z_en_st.c @@ -260,8 +260,8 @@ void func_808A54B0(EnSt* this, PlayState* play) { } gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, 170, 255, 255, (u8)(255 * temp_f0)); - gSPDisplayList(POLY_XLU_DISP++, gameplay_keep_DL_025850); - gSPDisplayList(POLY_XLU_DISP++, gameplay_keep_DL_025970); + gSPDisplayList(POLY_XLU_DISP++, gSpinAttackDiskDL); + gSPDisplayList(POLY_XLU_DISP++, gSpinAttackCylinderDL); CLOSE_DISPS(play->state.gfxCtx); } diff --git a/tools/disasm/functions.txt b/tools/disasm/functions.txt index ef47869a5..a465f7599 100644 --- a/tools/disasm/functions.txt +++ b/tools/disasm/functions.txt @@ -5947,18 +5947,18 @@ 0x808B5230:("EnMFire1_Init",), 0x808B5294:("EnMFire1_Destroy",), 0x808B52C0:("EnMFire1_Update",), - 0x808B53C0:("func_808B53C0",), + 0x808B53C0:("EnMThunder_UnkType_Setup",), 0x808B545C:("EnMThunder_Init",), 0x808B5820:("EnMThunder_Destroy",), - 0x808B5890:("func_808B5890",), - 0x808B58CC:("func_808B58CC",), - 0x808B5984:("func_808B5984",), + 0x808B5890:("EnMThunder_AdjustLights",), + 0x808B58CC:("EnMThunder_Spin_AttackNoMagic",), + 0x808B5984:("EnMThunder_Charge",), 0x808B5EEC:("func_808B5EEC",), - 0x808B5F68:("func_808B5F68",), - 0x808B60D4:("func_808B60D4",), - 0x808B6310:("func_808B6310",), + 0x808B5F68:("EnMThunder_Spin_Attack",), + 0x808B60D4:("EnMThunder_SwordBeam_Attack",), + 0x808B6310:("EnMThunder_UnkType_Attack",), 0x808B63E8:("EnMThunder_Update",), - 0x808B65BC:("func_808B65BC",), + 0x808B65BC:("EnMThunder_UnkType_Update",), 0x808B677C:("EnMThunder_Draw",), 0x808B7360:("BgBreakwall_SetupAction",), 0x808B736C:("func_808B736C",), From 063d24f491e137778bdd6c65f0942d8ce74a2a91 Mon Sep 17 00:00:00 2001 From: chloe!! <47910150+chloebangbang@users.noreply.github.com> Date: Sun, 2 Oct 2022 00:07:07 -0500 Subject: [PATCH 04/10] ovl_En_Door_Etc OK (#994) * ovl_En_Door_Etc OK * review fixes * more review fixes * name yawDiff variables * various vixes * Update src/overlays/actors/ovl_En_Door_Etc/z_en_door_etc.c Co-authored-by: Chloe <> Co-authored-by: EllipticEllipsis --- spec | 3 +- .../actors/ovl_En_Door_Etc/z_en_door_etc.c | 222 ++++++++++++++++-- .../actors/ovl_En_Door_Etc/z_en_door_etc.h | 11 +- tools/disasm/functions.txt | 6 +- tools/disasm/variables.txt | 6 +- 5 files changed, 219 insertions(+), 29 deletions(-) diff --git a/spec b/spec index e2ea0c1b3..80141af9c 100644 --- a/spec +++ b/spec @@ -3198,8 +3198,7 @@ beginseg name "ovl_En_Door_Etc" compress include "build/src/overlays/actors/ovl_En_Door_Etc/z_en_door_etc.o" - include "build/data/ovl_En_Door_Etc/ovl_En_Door_Etc.data.o" - include "build/data/ovl_En_Door_Etc/ovl_En_Door_Etc.reloc.o" + include "build/src/overlays/actors/ovl_En_Door_Etc/ovl_En_Door_Etc_reloc.o" endseg beginseg diff --git a/src/overlays/actors/ovl_En_Door_Etc/z_en_door_etc.c b/src/overlays/actors/ovl_En_Door_Etc/z_en_door_etc.c index 0d3612145..98e9d2b8f 100644 --- a/src/overlays/actors/ovl_En_Door_Etc/z_en_door_etc.c +++ b/src/overlays/actors/ovl_En_Door_Etc/z_en_door_etc.c @@ -5,6 +5,7 @@ */ #include "z_en_door_etc.h" +#include "objects/gameplay_keep/gameplay_keep.h" #define FLAGS (ACTOR_FLAG_10) @@ -14,7 +15,11 @@ void EnDoorEtc_Init(Actor* thisx, PlayState* play); void EnDoorEtc_Destroy(Actor* thisx, PlayState* play); void EnDoorEtc_Update(Actor* thisx, PlayState* play); -#if 0 +void EnDoorEtc_WaitForObject(EnDoorEtc* this, PlayState* play); +void func_80AC21A0(EnDoorEtc* this, PlayState* play); +void func_80AC2354(EnDoorEtc* this, PlayState* play); +void EnDoorEtc_Draw(Actor* thisx, PlayState* play); + const ActorInit En_Door_Etc_InitVars = { ACTOR_EN_DOOR_ETC, ACTORCAT_DOOR, @@ -27,42 +32,219 @@ const ActorInit En_Door_Etc_InitVars = { (ActorFunc)NULL, }; -// static ColliderCylinderInit sCylinderInit = { -static ColliderCylinderInit D_80AC25A0 = { - { COLTYPE_NONE, AT_NONE, AC_ON | AC_TYPE_PLAYER, OC1_ON | OC1_TYPE_ALL, OC2_TYPE_1, COLSHAPE_CYLINDER, }, - { ELEMTYPE_UNK0, { 0x00000000, 0x00, 0x00 }, { 0x00000000, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, }, +static ColliderCylinderInit sCylinderInit = { + { + COLTYPE_NONE, + AT_NONE, + AC_ON | AC_TYPE_PLAYER, + OC1_ON | OC1_TYPE_ALL, + OC2_TYPE_1, + COLSHAPE_CYLINDER, + }, + { + ELEMTYPE_UNK0, + { 0x00000000, 0x00, 0x00 }, + { 0x00000000, 0x00, 0x00 }, + TOUCH_NONE | TOUCH_SFX_NORMAL, + BUMP_ON, + OCELEM_ON, + }, { 100, 40, 0, { 0, 0, 0 } }, }; -// static InitChainEntry sInitChain[] = { -static InitChainEntry D_80AC2634[] = { +typedef struct { + /* 0x0 */ s16 sceneId; + /* 0x2 */ u8 dListIndex; + /* 0x4 */ s16 objectId; +} EnDoorEtcInfo; // size = 0x6 + +EnDoorEtcInfo sObjInfo[] = { + { SCENE_MITURIN, 1, OBJECT_NUMA_OBJ }, + { -1, 0, GAMEPLAY_KEEP }, + { -1, 13, GAMEPLAY_FIELD_KEEP }, + { 0, 0, OBJECT_UNSET_0 }, + { 0, 0, OBJECT_UNSET_0 }, + { 0, 0, OBJECT_UNSET_0 }, + { 0, 0, OBJECT_UNSET_0 }, + { 0, 0, OBJECT_UNSET_0 }, + { 0, 0, OBJECT_UNSET_0 }, + { 0, 0, OBJECT_UNSET_0 }, + { 0, 0, OBJECT_UNSET_0 }, + { 0, 0, OBJECT_UNSET_0 }, + { 0, 0, OBJECT_UNSET_0 }, + { 0, 0, OBJECT_UNSET_0 }, + { 0, 0, OBJECT_UNSET_0 }, + { 0, 0, OBJECT_UNSET_0 }, + { 0, 0, OBJECT_UNSET_0 }, +}; + +static InitChainEntry sInitChain[] = { ICHAIN_U8(targetMode, 0, ICHAIN_CONTINUE), ICHAIN_F32(uncullZoneForward, 4000, ICHAIN_CONTINUE), ICHAIN_U16(shape.rot.x, 0, ICHAIN_CONTINUE), ICHAIN_U16(shape.rot.z, 0, ICHAIN_STOP), }; -#endif +void EnDoorEtc_Init(Actor* thisx, PlayState* play2) { + PlayState* play = play2; + s32 objectIndex; + EnDoorEtcInfo* objectInfo = sObjInfo; + s32 i; + EnDoorEtc* this = THIS; -extern ColliderCylinderInit D_80AC25A0; -extern InitChainEntry D_80AC2634[]; + Actor_ProcessInitChain(&this->actor, sInitChain); + Actor_SetScale(&this->actor, 0.01f); + this->actor.shape.rot.x = -0x4000; + this->angle = 0; + for (i = 0; i < 15; i++, objectInfo++) { + if (play->sceneId == objectInfo->sceneId) { + break; + } + } + if ((i >= 15) && (Object_GetIndex(&play->objectCtx, GAMEPLAY_FIELD_KEEP) >= 0)) { + objectInfo++; + } + objectIndex = Object_GetIndex(&play->objectCtx, objectInfo->objectId); + if (objectIndex < 0) { + Actor_MarkForDeath(&this->actor); + } else { + this->objectIndex = objectIndex; + this->dListIndex = objectInfo->dListIndex; + if (this->actor.objBankIndex == this->objectIndex) { + EnDoorEtc_WaitForObject(this, play); + } else { + this->actionFunc = EnDoorEtc_WaitForObject; + } + } + Collider_InitCylinder(play, &this->collider); + Collider_SetCylinder(play, &this->collider, &this->actor, &sCylinderInit); + this->actor.colChkInfo.mass = MASS_IMMOVABLE; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Door_Etc/EnDoorEtc_Init.s") +void EnDoorEtc_Destroy(Actor* thisx, PlayState* play) { + EnDoorEtc* this = THIS; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Door_Etc/EnDoorEtc_Destroy.s") + Collider_DestroyCylinder(play, &this->collider); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Door_Etc/func_80AC2044.s") +/** + * Calculates if the distance between `a` and `b` is greater than distance `c` + */ +s32 EnDoorEtc_IsDistanceGreater(Vec3f* a, Vec3f* b, f32 c) { + f32 dx = b->x - a->x; + f32 dy = b->y - a->y; + f32 dz = b->z - a->z; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Door_Etc/func_80AC20A8.s") + return ((SQ(dx) + SQ(dy) + SQ(dz)) < SQ(c)); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Door_Etc/func_80AC2118.s") +void EnDoorEtc_WaitForObject(EnDoorEtc* this, PlayState* play) { + if (Object_IsLoaded(&play->objectCtx, this->objectIndex)) { + this->actor.flags &= ~ACTOR_FLAG_10; + this->actor.objBankIndex = this->objectIndex; + this->actionFunc = func_80AC2354; + this->actor.draw = EnDoorEtc_Draw; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Door_Etc/func_80AC2154.s") +void func_80AC2118(EnDoorEtc* this, PlayState* play) { + if (this->angle < 0) { + this->angle += 0x100; + } else { + this->angle = 0; + this->actionFunc = func_80AC21A0; + this->unk_1F4 &= ~1; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Door_Etc/func_80AC21A0.s") +void func_80AC2154(EnDoorEtc* this, PlayState* play) { + if (this->timer > 0) { + this->timer--; + } else if (this->angle > -0x4000) { + this->angle -= 0x800; + } else { + this->angle = -0x4000; + this->actionFunc = func_80AC2118; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Door_Etc/func_80AC2354.s") +void func_80AC21A0(EnDoorEtc* this, PlayState* play) { + Player* player = GET_PLAYER(play); + Vec3f playerOffsetFromDoor; + s32 pad; + s16 yawDiff; + s32 yawDiffAbs; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Door_Etc/EnDoorEtc_Update.s") + Actor_OffsetOfPointInActorCoords(&this->actor, &playerOffsetFromDoor, &player->actor.world.pos); + if (this->unk_1A1 == 0) { + if ((!Player_InCsMode(play)) && + ((fabsf(playerOffsetFromDoor.y) < 20.0f) && fabsf(playerOffsetFromDoor.x) < 20.0f) && + (fabsf(playerOffsetFromDoor.z) < 50.0f)) { + yawDiff = player->actor.shape.rot.y - this->actor.shape.rot.y; + if (playerOffsetFromDoor.z > 0.0f) { + yawDiff = 0x8000 - yawDiff; + } + yawDiffAbs = ABS_ALT(yawDiff); + if (yawDiffAbs < 0x3000) { + player->doorDirection = (playerOffsetFromDoor.z >= 0.0f) ? 1.0f : -1.0f; + player->doorActor = &this->actor; + player->doorType = -1; + } + } + } + if ((this->actor.textId == 0x239B) && Flags_GetSwitch(play, ENDOORETC_GET_SWITCHFLAG(&this->actor))) { + Flags_UnsetSwitch(play, ENDOORETC_GET_SWITCHFLAG(&this->actor)); + this->actionFunc = func_80AC2154; + this->actor.textId = 0x1800; // "It won't budge!" + this->unk_1F4 |= 1; + this->timer = 0x5A; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Door_Etc/func_80AC24A8.s") +void func_80AC2354(EnDoorEtc* this, PlayState* play) { + Actor* door = play->actorCtx.actorLists[ACTORCAT_DOOR].first; + + while (door != NULL) { + if ((door->id != ACTOR_EN_DOOR) || + !EnDoorEtc_IsDistanceGreater(&door->world.pos, &this->actor.world.pos, 10.0f)) { + door = door->next; + } else { + this->actor.world.pos.x = door->world.pos.x; + this->actor.world.pos.y = door->world.pos.y; + this->actor.world.pos.z = door->world.pos.z; + this->actor.shape.rot.y = door->shape.rot.y; + this->actor.world.rot.y = door->world.rot.y; + Actor_MarkForDeath(door); + this->actionFunc = func_80AC21A0; + this->actor.textId = 0x239B; + Actor_SetFocus(&this->actor, 70.0f); + break; + } + } +} + +void EnDoorEtc_Update(Actor* thisx, PlayState* play) { + s32 pad; + EnDoorEtc* this = THIS; + + this->actionFunc(this, play); + if (this->unk_1F4 & 1) { + Collider_UpdateCylinder(&this->actor, &this->collider); + CollisionCheck_SetOC(play, &play->colChkCtx, &this->collider.base); + } +} + +void EnDoorEtc_Draw(Actor* thisx, PlayState* play) { + EnDoorEtc* this = THIS; + + OPEN_DISPS(play->state.gfxCtx); + + func_8012C28C(play->state.gfxCtx); + Matrix_Translate(-2900.0f, 0.0f, 0.0f, MTXMODE_APPLY); + Matrix_RotateZS(this->angle, MTXMODE_APPLY); + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, gDoorLeftDL); + gSPDisplayList(POLY_OPA_DISP++, gDoorRightDL); + + CLOSE_DISPS(play->state.gfxCtx); +} diff --git a/src/overlays/actors/ovl_En_Door_Etc/z_en_door_etc.h b/src/overlays/actors/ovl_En_Door_Etc/z_en_door_etc.h index 18d525f44..cbcdf2f54 100644 --- a/src/overlays/actors/ovl_En_Door_Etc/z_en_door_etc.h +++ b/src/overlays/actors/ovl_En_Door_Etc/z_en_door_etc.h @@ -5,11 +5,20 @@ struct EnDoorEtc; +#define ENDOORETC_GET_SWITCHFLAG(thisx) ((thisx)->params & 0x7F) + typedef void (*EnDoorEtcActionFunc)(struct EnDoorEtc*, PlayState*); typedef struct EnDoorEtc { /* 0x000 */ Actor actor; - /* 0x144 */ char unk_144[0xB4]; + /* 0x144 */ char pad_144[0x5D]; + /* 0x1A1 */ u8 unk_1A1; + /* 0x1A2 */ s8 objectIndex; + /* 0x1A3 */ u8 dListIndex; // Never read, inferred from ovl_En_Door + /* 0x1A4 */ s16 angle; + /* 0x1A6 */ s16 timer; + /* 0x1A8 */ ColliderCylinder collider; + /* 0x1F4 */ u8 unk_1F4; /* 0x1F8 */ EnDoorEtcActionFunc actionFunc; } EnDoorEtc; // size = 0x1FC diff --git a/tools/disasm/functions.txt b/tools/disasm/functions.txt index a465f7599..594ce3427 100644 --- a/tools/disasm/functions.txt +++ b/tools/disasm/functions.txt @@ -11902,14 +11902,14 @@ 0x80AC1D14:("EnPoFusen_Draw",), 0x80AC1ED0:("EnDoorEtc_Init",), 0x80AC2018:("EnDoorEtc_Destroy",), - 0x80AC2044:("func_80AC2044",), - 0x80AC20A8:("func_80AC20A8",), + 0x80AC2044:("EnDoorEtc_IsDistanceGreater",), + 0x80AC20A8:("EnDoorEtc_WaitForObject",), 0x80AC2118:("func_80AC2118",), 0x80AC2154:("func_80AC2154",), 0x80AC21A0:("func_80AC21A0",), 0x80AC2354:("func_80AC2354",), 0x80AC2430:("EnDoorEtc_Update",), - 0x80AC24A8:("func_80AC24A8",), + 0x80AC24A8:("EnDoorEtc_Draw",), 0x80AC26F0:("EnBigokuta_Init",), 0x80AC2874:("EnBigokuta_Destroy",), 0x80AC28B4:("EnBigokuta_SetupCutsceneCamera",), diff --git a/tools/disasm/variables.txt b/tools/disasm/variables.txt index 57d876acb..97cf77e76 100644 --- a/tools/disasm/variables.txt +++ b/tools/disasm/variables.txt @@ -12869,9 +12869,9 @@ 0x80AC1E00:("D_80AC1E00","f32","",0x4), 0x80AC1E04:("D_80AC1E04","f32","",0x4), 0x80AC2580:("En_Door_Etc_InitVars","UNK_TYPE1","",0x1), - 0x80AC25A0:("D_80AC25A0","UNK_TYPE1","",0x1), - 0x80AC25CC:("D_80AC25CC","UNK_TYPE2","",0x2), - 0x80AC2634:("D_80AC2634","UNK_TYPE1","",0x1), + 0x80AC25A0:("sCylinderInit","UNK_TYPE1","",0x1), + 0x80AC25CC:("sObjInfo","UNK_TYPE2","",0x2), + 0x80AC2634:("sInitChain","UNK_TYPE1","",0x1), 0x80AC2650:("D_80AC2650","f32","",0x4), 0x80AC4510:("En_Bigokuta_InitVars","UNK_TYPE1","",0x1), 0x80AC4530:("D_80AC4530","UNK_TYPE1","",0x1), From 841da5f13818741c1a50cd16605ad4934b9de36e Mon Sep 17 00:00:00 2001 From: engineer124 <47598039+engineer124@users.noreply.github.com> Date: Sun, 2 Oct 2022 10:32:57 -0400 Subject: [PATCH 05/10] View & Shrink_Window Docs (#1049) * view and shrink_window docs * cleanup * move func declaration to header * move struct to local * PR Suggestions * g to s --- include/functions.h | 41 --- include/variables.h | 2 - include/z64.h | 7 - include/z64shrink_window.h | 23 ++ include/z64view.h | 41 ++- src/code/speed_meter.c | 1 + src/code/z_camera.c | 2 + src/code/z_demo.c | 9 +- src/code/z_eventmgr.c | 1 + src/code/z_game_over.c | 3 +- src/code/z_kaleido_scope_call.c | 3 +- src/code/z_kaleido_setup.c | 6 +- src/code/z_message.c | 4 +- src/code/z_parameter.c | 2 +- src/code/z_play.c | 2 + src/code/z_quake.c | 9 +- src/code/z_shrink_window.c | 93 ++++--- src/code/z_view.c | 247 ++++++++++-------- src/overlays/actors/ovl_Boss_01/z_boss_01.c | 1 + src/overlays/actors/ovl_Boss_02/z_boss_02.c | 5 +- src/overlays/actors/ovl_Boss_04/z_boss_04.c | 3 +- src/overlays/actors/ovl_Boss_06/z_boss_06.c | 3 +- src/overlays/actors/ovl_Boss_07/z_boss_07.c | 1 + src/overlays/actors/ovl_En_Bsb/z_en_bsb.c | 1 + .../actors/ovl_En_Fishing/z_en_fishing.c | 3 +- .../actors/ovl_En_Knight/z_en_knight.c | 1 + .../actors/ovl_player_actor/z_player.c | 1 + .../gamestates/ovl_daytelop/z_daytelop.c | 2 + .../ovl_file_choose/z_file_choose_NES.c | 2 + .../gamestates/ovl_opening/z_opening.c | 2 + src/overlays/gamestates/ovl_select/z_select.c | 4 +- src/overlays/gamestates/ovl_title/z_title.c | 8 +- .../ovl_kaleido_scope/z_kaleido_scope_NES.c | 1 + tools/disasm/functions.txt | 50 ++-- tools/disasm/variables.txt | 4 +- tools/sizes/code_functions.csv | 50 ++-- 36 files changed, 362 insertions(+), 276 deletions(-) create mode 100644 include/z64shrink_window.h diff --git a/include/functions.h b/include/functions.h index 41f3308eb..c79fc333f 100644 --- a/include/functions.h +++ b/include/functions.h @@ -2261,35 +2261,6 @@ void SkinMatrix_SetYRotation(MtxF* mf, s16 a); void SkinMatrix_MulYRotation(MtxF* mf, s16 a); void SkinMatrix_SetZRotation(MtxF* mf, s16 a); -void View_ViewportToVp(Vp* dest, Viewport* src); -void View_Init(View* view, GraphicsContext* gfxCtx); -void View_SetViewOrientation(View* view, Vec3f* eye, Vec3f* at, Vec3f* up); -void func_8013F050(View* view, Vec3f* eye, Vec3f* at, Vec3f* up); -void View_SetScale(View* view, f32 scale); -void View_GetScale(View* view, f32* scale); -void func_8013F0D0(View* view, f32 fovy, f32 zNear, f32 zFar); -void func_8013F100(View* view, f32* fovy, f32* zNear, f32* zFar); -void func_8013F120(View* view, f32 fovy, f32 zNear, f32 zFar); -void func_8013F15C(View* view, f32* fovy, f32* zNear, f32* zFar); -void View_SetViewport(View* view, Viewport* viewport); -void View_GetViewport(View* view, Viewport* viewport); -void View_WriteScissor(Gfx** gfx, s32 ulx, s32 uly, s32 lrx, s32 lry); -void View_SyncAndWriteScissor(View* view, Gfx** gfx); -void View_SetScissorForLetterbox(View* view); -s32 View_SetDistortionDirRot(View* view, f32 dirRotX, f32 dirRotY, f32 dirRotZ); -s32 View_SetDistortionScale(View* view, f32 scaleX, f32 scaleY, f32 scaleZ); -s32 View_SetDistortionSpeed(View* view, f32 speed); -s32 View_InitDistortion(View* view); -s32 View_ClearDistortion(View* view); -s32 View_SetDistortion(View* view, Vec3f dirRot, Vec3f scale, f32 speed); -s32 View_StepDistortion(View* view, Mtx* projectionMtx); -void View_RenderView(View* view, s32 uParm2); -s32 View_RenderToPerspectiveMatrix(View* view); -s32 View_RenderToOrthographicMatrix(View* view); -s32 func_8013FBC8(View* view); -s32 func_8013FD74(View* view); -s32 func_80140024(View* view); -s32 func_801400CC(View* view, Gfx** gfxp); void func_80140260(OSViMode* vimode); // void func_8014026C(OSViMode* param_1, UNK_TYPE1 param_2, s32 param_3, s32 param_4, s32 param_5, s32 param_6, s32 param_7, s32 param_8, UNK_TYPE4 param_9, s32 param_10, s16 param_11, u32 param_12, UNK_TYPE4 param_13); // void func_80140730(void); @@ -2399,18 +2370,6 @@ void Message_FindCreditsMessage(PlayState* play, u16 textId); void func_8015E7EC(PlayState* play, UNK_PTR puParm2); // void func_8015F8A8(UNK_TYPE4 ctxt); -void ShrinkWindow_SetLetterboxTarget(s32 target); -s32 ShrinkWindow_GetLetterboxTarget(void); -void ShrinkWindow_SetLetterboxMagnitude(s32 magnitude); -s32 ShrinkWindow_GetLetterboxMagnitude(void); -void ShrinkWindow_SetPillarboxTarget(s32 target); -s32 ShrinkWindow_GetPillarboxTarget(void); -void ShrinkWindow_SetPillarboxMagnitude(s32 magnitude); -s32 ShrinkWindow_GetPillarboxMagnitude(void); -void ShrinkWindow_Init(void); -void ShrinkWindow_Destroy(void); -void ShrinkWindow_Update(s32 framerateDivisor); -void ShrinkWindow_Draw(GraphicsContext* gfxCtx); // void func_80161180(void); s32 func_8016119C(Camera* camera, DbCameraUnkStruct* arg1); // void func_8016122C(void); diff --git a/include/variables.h b/include/variables.h index c7ea263f2..ae97a6c51 100644 --- a/include/variables.h +++ b/include/variables.h @@ -3181,8 +3181,6 @@ extern s16 D_801F4E7A; // extern UNK_TYPE1 D_801F6B1E; // extern UNK_TYPE1 D_801F6B20; // extern UNK_TYPE1 D_801F6B22; -extern ShrinkWindowContext gShrinkWindowContext; -extern ShrinkWindowContext* gShrinkWindowContextPtr; // extern UNK_TYPE4 D_801F6B50; // extern UNK_TYPE1 D_801F6B58; extern void (*sKaleidoScopeUpdateFunc)(PlayState* play); diff --git a/include/z64.h b/include/z64.h index ceb91bfb8..d03879072 100644 --- a/include/z64.h +++ b/include/z64.h @@ -286,13 +286,6 @@ typedef struct { /* 0x10 */ OSTime resetTime; } NmiBuff; // size >= 0x18 -typedef struct { - /* 0x0 */ s8 letterboxTarget; - /* 0x1 */ s8 letterboxMagnitude; - /* 0x2 */ s8 pillarboxTarget; - /* 0x3 */ s8 pillarboxMagnitude; -} ShrinkWindowContext; // size = 0x4 - typedef void(*osCreateThread_func)(void*); typedef enum { diff --git a/include/z64shrink_window.h b/include/z64shrink_window.h new file mode 100644 index 000000000..2742fb602 --- /dev/null +++ b/include/z64shrink_window.h @@ -0,0 +1,23 @@ +#ifndef Z64SHRINK_WINDOW_H +#define Z64SHRINK_WINDOW_H + +#include "PR/ultratypes.h" + +struct GraphicsContext; + +void ShrinkWindow_Letterbox_SetSizeTarget(s32 target); +s32 ShrinkWindow_Letterbox_GetSizeTarget(void); +void ShrinkWindow_Letterbox_SetSize(s32 size); +s32 ShrinkWindow_Letterbox_GetSize(void); + +void ShrinkWindow_Pillarbox_SetSizeTarget(s32 target); +s32 ShrinkWindow_Pillarbox_GetSizeTarget(void); +void ShrinkWindow_Pillarbox_SetSize(s32 size); +s32 ShrinkWindow_Pillarbox_GetSize(void); + +void ShrinkWindow_Init(void); +void ShrinkWindow_Destroy(void); +void ShrinkWindow_Update(s32 framerateDivisor); +void ShrinkWindow_Draw(GraphicsContext* gfxCtx); + +#endif diff --git a/include/z64view.h b/include/z64view.h index 98ca1ab19..f0661d947 100644 --- a/include/z64view.h +++ b/include/z64view.h @@ -33,16 +33,27 @@ typedef struct View { /* 0x0E0 */ Mtx unkE0; /* 0x120 */ Mtx* projectionPtr; /* 0x124 */ Mtx* viewingPtr; - /* 0x128 */ Vec3f distortionDirRot; + /* 0x128 */ Vec3f distortionOrientation; /* 0x134 */ Vec3f distortionScale; /* 0x140 */ f32 distortionSpeed; - /* 0x144 */ Vec3f curDistortionDirRot; + /* 0x144 */ Vec3f curDistortionOrientation; /* 0x150 */ Vec3f curDistortionScale; - /* 0x15C */ u16 normal; // used to normalize the projection matrix + /* 0x15C */ u16 perspNorm; // used to normalize the projection matrix /* 0x160 */ u32 flags; // bit 3: Render to an orthographic perspective /* 0x164 */ s32 unk164; } View; // size = 0x168 +#define VIEW_VIEWING (1 << 0) +#define VIEW_VIEWPORT (1 << 1) +#define VIEW_PROJECTION_PERSPECTIVE (1 << 2) +#define VIEW_PROJECTION_ORTHO (1 << 3) +#define VIEW_ALL (VIEW_VIEWING | VIEW_VIEWPORT | VIEW_PROJECTION_PERSPECTIVE | VIEW_PROJECTION_ORTHO) + +#define VIEW_FORCE_VIEWING (VIEW_VIEWING << 4) +#define VIEW_FORCE_VIEWPORT (VIEW_VIEWPORT << 4) +#define VIEW_FORCE_PROJECTION_PERSPECTIVE (VIEW_PROJECTION_PERSPECTIVE << 4) +#define VIEW_FORCE_PROJECTION_ORTHO (VIEW_PROJECTION_ORTHO << 4) + #define SET_FULLSCREEN_VIEWPORT(view) \ { \ Viewport viewport; \ @@ -54,4 +65,28 @@ typedef struct View { } \ (void)0 +void View_Init(View* view, struct GraphicsContext* gfxCtx); +void View_LookAt(View* view, Vec3f* eye, Vec3f* at, Vec3f* up); +void View_SetScale(View* view, f32 scale); +void View_GetScale(View* view, f32* scale); +void View_SetPerspective(View* view, f32 fovy, f32 zNear, f32 zFar); +void View_GetPerspective(View* view, f32* fovy, f32* zNear, f32* zFar); +void View_SetOrtho(View* view, f32 fovy, f32 zNear, f32 zFar); +void View_GetOrtho(View* view, f32* fovy, f32* zNear, f32* zFar); +void View_SetViewport(View* view, Viewport* viewport); +void View_GetViewport(View* view, Viewport* viewport); + +s32 View_SetDistortionOrientation(View* view, f32 rotX, f32 rotY, f32 rotZ); +s32 View_SetDistortionScale(View* view, f32 scaleX, f32 scaleY, f32 scaleZ); +s32 View_SetDistortionSpeed(View* view, f32 speed); +s32 View_InitDistortion(View* view); +s32 View_ClearDistortion(View* view); +s32 View_SetDistortion(View* view, Vec3f orientation, Vec3f scale, f32 speed); + +void View_Apply(View* view, s32 mask); +s32 View_ApplyOrthoToOverlay(View* view); +s32 View_ApplyPerspectiveToOverlay(View* view); +s32 View_UpdateViewingMatrix(View* view); +s32 View_ApplyTo(View* view, Gfx** gfxp); + #endif diff --git a/src/code/speed_meter.c b/src/code/speed_meter.c index 9f04de110..5ad1cdbe0 100644 --- a/src/code/speed_meter.c +++ b/src/code/speed_meter.c @@ -1,4 +1,5 @@ #include "global.h" +#include "z64view.h" #include "system_malloc.h" #pragma GLOBAL_ASM("asm/non_matchings/code/speed_meter/func_80177390.s") diff --git a/src/code/z_camera.c b/src/code/z_camera.c index c26947b21..da8a5f35a 100644 --- a/src/code/z_camera.c +++ b/src/code/z_camera.c @@ -1,5 +1,7 @@ #include "global.h" #include "z64quake.h" +#include "z64shrink_window.h" +#include "z64view.h" /** * Returns the absolute value for floats diff --git a/src/code/z_demo.c b/src/code/z_demo.c index 6c83e8391..1fa041be1 100644 --- a/src/code/z_demo.c +++ b/src/code/z_demo.c @@ -1,6 +1,7 @@ #include "global.h" #include "z64quake.h" #include "z64rumble.h" +#include "z64shrink_window.h" #include "overlays/gamestates/ovl_daytelop/z_daytelop.h" void Cutscene_DoNothing(PlayState* play, CutsceneContext* csCtx); @@ -107,7 +108,7 @@ s32 func_800EA220(PlayState* play, CutsceneContext* csCtx, f32 target) { void func_800EA258(PlayState* play, CutsceneContext* csCtx) { Interface_SetHudVisibility(HUD_VISIBILITY_NONE); - ShrinkWindow_SetLetterboxTarget(32); + ShrinkWindow_Letterbox_SetSizeTarget(32); if (func_800EA220(play, csCtx, 1.0f)) { Audio_SetCutsceneFlag(true); csCtx->state++; @@ -117,7 +118,7 @@ void func_800EA258(PlayState* play, CutsceneContext* csCtx) { void func_800EA2B8(PlayState* play, CutsceneContext* csCtx) { func_800ED980(play, csCtx); Interface_SetHudVisibility(HUD_VISIBILITY_NONE); - ShrinkWindow_SetLetterboxTarget(32); + ShrinkWindow_Letterbox_SetSizeTarget(32); if (func_800EA220(play, csCtx, 1.0f)) { Audio_SetCutsceneFlag(true); csCtx->state++; @@ -1449,8 +1450,8 @@ void func_800EDA84(PlayState* play, CutsceneContext* csCtx) { if (gSaveContext.cutsceneTrigger == 0) { Interface_SetHudVisibility(HUD_VISIBILITY_NONE); - ShrinkWindow_SetLetterboxTarget(32); - ShrinkWindow_SetLetterboxMagnitude(0x20); + ShrinkWindow_Letterbox_SetSizeTarget(32); + ShrinkWindow_Letterbox_SetSize(32); csCtx->state++; } diff --git a/src/code/z_eventmgr.c b/src/code/z_eventmgr.c index 7128368ac..5b8b8dce3 100644 --- a/src/code/z_eventmgr.c +++ b/src/code/z_eventmgr.c @@ -1,4 +1,5 @@ #include "global.h" +#include "z64shrink_window.h" #pragma GLOBAL_ASM("asm/non_matchings/code/z_eventmgr/func_800F1460.s") diff --git a/src/code/z_game_over.c b/src/code/z_game_over.c index 776dc75d7..857250eec 100644 --- a/src/code/z_game_over.c +++ b/src/code/z_game_over.c @@ -1,5 +1,6 @@ #include "global.h" #include "z64rumble.h" +#include "z64shrink_window.h" void GameOver_Init(PlayState* play) { play->gameOverCtx.state = GAMEOVER_INACTIVE; @@ -86,7 +87,7 @@ void GameOver_Update(PlayState* play) { gameOverCtx->state++; sGameOverTimer = 0; Kankyo_InitGameOverLights(play); - ShrinkWindow_SetLetterboxTarget(32); + ShrinkWindow_Letterbox_SetSizeTarget(32); break; case GAMEOVER_REVIVE_RUMBLE: sGameOverTimer = 50; diff --git a/src/code/z_kaleido_scope_call.c b/src/code/z_kaleido_scope_call.c index d7905e4dd..9cea42691 100644 --- a/src/code/z_kaleido_scope_call.c +++ b/src/code/z_kaleido_scope_call.c @@ -1,5 +1,6 @@ #include "prevent_bss_reordering.h" #include "global.h" +#include "z64shrink_window.h" #include "overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope.h" void (*sKaleidoScopeUpdateFunc)(PlayState* play); @@ -36,7 +37,7 @@ void KaleidoScopeCall_Update(PlayState* play) { if ((play->pauseCtx.state != 0) || (play->pauseCtx.debugEditor != DEBUG_EDITOR_NONE)) { if (pauseCtx->state == 1 || pauseCtx->state == 19) { - if (ShrinkWindow_GetLetterboxMagnitude() == 0) { + if (ShrinkWindow_Letterbox_GetSize() == 0) { R_PAUSE_MENU_MODE = 1; pauseCtx->unk_200 = 0; pauseCtx->unk_208 = 0; diff --git a/src/code/z_kaleido_setup.c b/src/code/z_kaleido_setup.c index 1135f2de9..0109dc4ab 100644 --- a/src/code/z_kaleido_setup.c +++ b/src/code/z_kaleido_setup.c @@ -1,5 +1,7 @@ #include "global.h" #include "z64rumble.h" +#include "z64shrink_window.h" +#include "z64view.h" #include "overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope.h" s16 D_801BDB00[] = { PAUSE_MAP, PAUSE_QUEST, PAUSE_MASK, PAUSE_ITEM }; @@ -91,8 +93,8 @@ void KaleidoSetup_Update(PlayState* play) { if (pauseCtx->state == 1) { Game_SetFramerateDivisor(&play->state, 2); - if (ShrinkWindow_GetLetterboxTarget() != 0) { - ShrinkWindow_SetLetterboxTarget(0); + if (ShrinkWindow_Letterbox_GetSizeTarget() != 0) { + ShrinkWindow_Letterbox_SetSizeTarget(0); } func_801A3AEC(1); } diff --git a/src/code/z_message.c b/src/code/z_message.c index cb00d8cd2..94f1e5992 100644 --- a/src/code/z_message.c +++ b/src/code/z_message.c @@ -1,4 +1,6 @@ #include "global.h" +#include "z64shrink_window.h" +#include "z64view.h" #include "message_data_static.h" #include "overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope.h" @@ -489,7 +491,7 @@ u8 Message_GetState(MessageContext* msgCtx) { void func_80152C64(View* view) { SET_FULLSCREEN_VIEWPORT(view); - func_8013FBC8(view); + View_ApplyOrthoToOverlay(view); } #pragma GLOBAL_ASM("asm/non_matchings/code/z_message/func_80152CAC.s") diff --git a/src/code/z_parameter.c b/src/code/z_parameter.c index 3a2da402c..4620dd816 100644 --- a/src/code/z_parameter.c +++ b/src/code/z_parameter.c @@ -1,5 +1,5 @@ #include "global.h" - +#include "z64view.h" #include "interface/parameter_static/parameter_static.h" #include "interface/do_action_static/do_action_static.h" #include "misc/story_static/story_static.h" diff --git a/src/code/z_play.c b/src/code/z_play.c index 06ec9c21e..47bb97a60 100644 --- a/src/code/z_play.c +++ b/src/code/z_play.c @@ -1,5 +1,7 @@ #include "global.h" #include "z64quake.h" +#include "z64shrink_window.h" +#include "z64view.h" #pragma GLOBAL_ASM("asm/non_matchings/code/z_play/func_80165460.s") diff --git a/src/code/z_quake.c b/src/code/z_quake.c index 2b66a39f8..964935ea1 100644 --- a/src/code/z_quake.c +++ b/src/code/z_quake.c @@ -1,5 +1,6 @@ #include "global.h" #include "z64quake.h" +#include "z64view.h" typedef struct { /* 0x00 */ s16 randIndex; @@ -823,10 +824,10 @@ void Distortion_Update(void) { depthPhase += CAM_DEG_TO_BINANG(depthPhaseStep); screenPlanePhase += CAM_DEG_TO_BINANG(screenPlanePhaseStep); - View_SetDistortionDirRot(&sDistortionRequest.play->view, - Math_CosS(depthPhase) * (DEGF_TO_RADF(rotX) * xyScaleFactor), - Math_SinS(depthPhase) * (DEGF_TO_RADF(rotY) * xyScaleFactor), - Math_SinS(screenPlanePhase) * (DEGF_TO_RADF(rotZ) * zScaleFactor)); + View_SetDistortionOrientation(&sDistortionRequest.play->view, + Math_CosS(depthPhase) * (DEGF_TO_RADF(rotX) * xyScaleFactor), + Math_SinS(depthPhase) * (DEGF_TO_RADF(rotY) * xyScaleFactor), + Math_SinS(screenPlanePhase) * (DEGF_TO_RADF(rotZ) * zScaleFactor)); View_SetDistortionScale(&sDistortionRequest.play->view, (Math_SinS(screenPlanePhase) * (xScale * xyScaleFactor)) + 1.0f, (Math_CosS(screenPlanePhase) * (yScale * xyScaleFactor)) + 1.0f, diff --git a/src/code/z_shrink_window.c b/src/code/z_shrink_window.c index 5bfca86d9..acbdb5c5b 100644 --- a/src/code/z_shrink_window.c +++ b/src/code/z_shrink_window.c @@ -4,70 +4,78 @@ */ #include "prevent_bss_reordering.h" #include "global.h" +#include "z64shrink_window.h" -ShrinkWindowContext gShrinkWindowContext; -ShrinkWindowContext* gShrinkWindowContextPtr; +typedef struct { + /* 0x0 */ s8 letterboxTarget; + /* 0x1 */ s8 letterboxSize; + /* 0x2 */ s8 pillarboxTarget; + /* 0x3 */ s8 pillarboxSize; +} ShrinkWindow; // size = 0x4 -void ShrinkWindow_SetLetterboxTarget(s32 target) { - gShrinkWindowContextPtr->letterboxTarget = target; +ShrinkWindow sShrinkWindow; +ShrinkWindow* sShrinkWindowPtr; + +void ShrinkWindow_Letterbox_SetSizeTarget(s32 target) { + sShrinkWindowPtr->letterboxTarget = target; } -s32 ShrinkWindow_GetLetterboxTarget(void) { - return gShrinkWindowContextPtr->letterboxTarget; +s32 ShrinkWindow_Letterbox_GetSizeTarget(void) { + return sShrinkWindowPtr->letterboxTarget; } -void ShrinkWindow_SetLetterboxMagnitude(s32 magnitude) { - gShrinkWindowContextPtr->letterboxMagnitude = magnitude; +void ShrinkWindow_Letterbox_SetSize(s32 size) { + sShrinkWindowPtr->letterboxSize = size; } -s32 ShrinkWindow_GetLetterboxMagnitude(void) { - return gShrinkWindowContextPtr->letterboxMagnitude; +s32 ShrinkWindow_Letterbox_GetSize(void) { + return sShrinkWindowPtr->letterboxSize; } -void ShrinkWindow_SetPillarboxTarget(s32 target) { - gShrinkWindowContextPtr->pillarboxTarget = target; +void ShrinkWindow_Pillarbox_SetSizeTarget(s32 target) { + sShrinkWindowPtr->pillarboxTarget = target; } -s32 ShrinkWindow_GetPillarboxTarget(void) { - return gShrinkWindowContextPtr->pillarboxTarget; +s32 ShrinkWindow_Pillarbox_GetSizeTarget(void) { + return sShrinkWindowPtr->pillarboxTarget; } -void ShrinkWindow_SetPillarboxMagnitude(s32 magnitude) { - gShrinkWindowContextPtr->pillarboxMagnitude = magnitude; +void ShrinkWindow_Pillarbox_SetSize(s32 size) { + sShrinkWindowPtr->pillarboxSize = size; } -s32 ShrinkWindow_GetPillarboxMagnitude(void) { - return gShrinkWindowContextPtr->pillarboxMagnitude; +s32 ShrinkWindow_Pillarbox_GetSize(void) { + return sShrinkWindowPtr->pillarboxSize; } void ShrinkWindow_Init(void) { - gShrinkWindowContextPtr = &gShrinkWindowContext; - bzero(gShrinkWindowContextPtr, sizeof(gShrinkWindowContext)); + sShrinkWindowPtr = &sShrinkWindow; + bzero(sShrinkWindowPtr, sizeof(sShrinkWindow)); } void ShrinkWindow_Destroy(void) { - gShrinkWindowContextPtr = NULL; + sShrinkWindowPtr = NULL; } void ShrinkWindow_Update(s32 framerateDivisor) { - s32 step = ((framerateDivisor == 3) ? 10 : 30 / framerateDivisor); - s32 nextMagnitude; + s32 step = (framerateDivisor == 3) ? 10 : (30 / framerateDivisor); + s32 nextSize; - nextMagnitude = gShrinkWindowContextPtr->letterboxMagnitude; - Math_StepToIGet(&nextMagnitude, gShrinkWindowContextPtr->letterboxTarget, step); - gShrinkWindowContextPtr->letterboxMagnitude = nextMagnitude; + nextSize = sShrinkWindowPtr->letterboxSize; + Math_StepToIGet(&nextSize, sShrinkWindowPtr->letterboxTarget, step); + sShrinkWindowPtr->letterboxSize = nextSize; - nextMagnitude = gShrinkWindowContextPtr->pillarboxMagnitude; - Math_StepToIGet(&nextMagnitude, gShrinkWindowContextPtr->pillarboxTarget, step); - gShrinkWindowContextPtr->pillarboxMagnitude = nextMagnitude; + nextSize = sShrinkWindowPtr->pillarboxSize; + Math_StepToIGet(&nextSize, sShrinkWindowPtr->pillarboxTarget, step); + sShrinkWindowPtr->pillarboxSize = nextSize; } void ShrinkWindow_Draw(GraphicsContext* gfxCtx) { Gfx* gfx; - s8 letterboxMagnitude = gShrinkWindowContextPtr->letterboxMagnitude; - s8 pillarboxMagnitude = gShrinkWindowContextPtr->pillarboxMagnitude; + s8 letterboxSize = sShrinkWindowPtr->letterboxSize; + s8 pillarboxSize = sShrinkWindowPtr->pillarboxSize; - if (letterboxMagnitude > 0) { + if (letterboxSize > 0) { OPEN_DISPS(gfxCtx); gfx = OVERLAY_DISP; @@ -76,23 +84,23 @@ void ShrinkWindow_Draw(GraphicsContext* gfxCtx) { gDPSetCycleType(gfx++, G_CYC_FILL); gDPSetRenderMode(gfx++, G_RM_NOOP, G_RM_NOOP2); gDPSetFillColor(gfx++, (GPACK_RGBA5551(0, 0, 0, 1) << 16) | GPACK_RGBA5551(0, 0, 0, 1)); - gDPFillRectangle(gfx++, 0, 0, gScreenWidth - 1, letterboxMagnitude - 1); - gDPFillRectangle(gfx++, 0, gScreenHeight - letterboxMagnitude, gScreenWidth - 1, gScreenHeight - 1); + gDPFillRectangle(gfx++, 0, 0, gScreenWidth - 1, letterboxSize - 1); + gDPFillRectangle(gfx++, 0, gScreenHeight - letterboxSize, gScreenWidth - 1, gScreenHeight - 1); gDPPipeSync(gfx++); gDPSetCycleType(gfx++, G_CYC_1CYCLE); gDPSetRenderMode(gfx++, G_RM_XLU_SURF, G_RM_XLU_SURF2); gDPSetPrimColor(gfx++, 0, 0, 0, 0, 0, 0); - gDPFillRectangle(gfx++, 0, letterboxMagnitude, gScreenWidth, letterboxMagnitude + 1); - gDPFillRectangle(gfx++, 0, gScreenHeight - letterboxMagnitude - 1, gScreenWidth, - gScreenHeight - letterboxMagnitude); + gDPFillRectangle(gfx++, 0, letterboxSize, gScreenWidth, letterboxSize + 1); + gDPFillRectangle(gfx++, 0, gScreenHeight - letterboxSize - 1, gScreenWidth, gScreenHeight - letterboxSize); gDPPipeSync(gfx++); OVERLAY_DISP = gfx++; CLOSE_DISPS(gfxCtx); } - if (pillarboxMagnitude > 0) { + + if (pillarboxSize > 0) { OPEN_DISPS(gfxCtx); gfx = OVERLAY_DISP; @@ -102,17 +110,16 @@ void ShrinkWindow_Draw(GraphicsContext* gfxCtx) { gDPSetRenderMode(gfx++, G_RM_NOOP, G_RM_NOOP2); gDPSetFillColor(gfx++, (GPACK_RGBA5551(0, 0, 0, 1) << 16) | GPACK_RGBA5551(0, 0, 0, 1)); - gDPFillRectangle(gfx++, 0, 0, pillarboxMagnitude - 1, gScreenHeight - 1); - gDPFillRectangle(gfx++, gScreenWidth - pillarboxMagnitude, 0, gScreenWidth - 1, gScreenHeight - 1); + gDPFillRectangle(gfx++, 0, 0, pillarboxSize - 1, gScreenHeight - 1); + gDPFillRectangle(gfx++, gScreenWidth - pillarboxSize, 0, gScreenWidth - 1, gScreenHeight - 1); gDPPipeSync(gfx++); gDPSetCycleType(gfx++, G_CYC_1CYCLE); gDPSetRenderMode(gfx++, G_RM_XLU_SURF, G_RM_XLU_SURF2); gDPSetPrimColor(gfx++, 0, 0, 0, 0, 0, 0); - gDPFillRectangle(gfx++, pillarboxMagnitude, 0, pillarboxMagnitude + 2, gScreenHeight); - gDPFillRectangle(gfx++, gScreenWidth - pillarboxMagnitude - 2, 0, gScreenWidth - pillarboxMagnitude, - gScreenHeight); + gDPFillRectangle(gfx++, pillarboxSize, 0, pillarboxSize + 2, gScreenHeight); + gDPFillRectangle(gfx++, gScreenWidth - pillarboxSize - 2, 0, gScreenWidth - pillarboxSize, gScreenHeight); gDPPipeSync(gfx++); OVERLAY_DISP = gfx++; diff --git a/src/code/z_view.c b/src/code/z_view.c index 915c196b7..105e6643a 100644 --- a/src/code/z_view.c +++ b/src/code/z_view.c @@ -1,4 +1,9 @@ #include "global.h" +#include "z64shrink_window.h" +#include "z64view.h" + +s32 View_ApplyPerspective(View* view); +s32 View_ApplyOrtho(View* view); void View_ViewportToVp(Vp* dest, Viewport* src) { s32 width = src->rightX - src->leftX; @@ -13,41 +18,45 @@ void View_ViewportToVp(Vp* dest, Viewport* src) { dest->vp.vtrans[2] = 0x01FF; dest->vp.vtrans[3] = 0; - if (src->leftX == 0 && src->rightX == 576 && src->topY == 0 && src->bottomY) {} + if ((src->leftX == 0) && (src->rightX == SCREEN_WIDTH_HIGH_RES) && (src->topY == 0) && + (src->bottomY == SCREEN_HEIGHT_HIGH_RES)) {} } void View_Init(View* view, GraphicsContext* gfxCtx) { view->gfxCtx = gfxCtx; + view->viewport.topY = 0; - view->viewport.bottomY = 240; + view->viewport.bottomY = SCREEN_HEIGHT; view->viewport.leftX = 0; - view->viewport.rightX = 320; + view->viewport.rightX = SCREEN_WIDTH; + view->magic = 0x56494557; // "VIEW" - view->unk164 = 0; - view->flags = 1 | 2 | 4; - - if (1) { - ; - } + if (1) {} view->scale = 1.0f; - view->up.y = 1.0f; view->fovy = 60.0f; - view->eye.x = 0.0f; - view->eye.y = 0.0f; - view->at.x = 0.0f; - view->up.x = 0.0f; - view->up.z = 0.0f; view->zNear = 10.0f; view->zFar = 12800.0f; + + view->eye.x = 0.0f; + view->eye.y = 0.0f; view->eye.z = -1.0f; + view->at.x = 0.0f; + + view->up.x = 0.0f; + view->up.y = 1.0f; + view->up.z = 0.0f; + + view->unk164 = 0; + view->flags = VIEW_VIEWING | VIEW_VIEWPORT | VIEW_PROJECTION_PERSPECTIVE; + View_InitDistortion(view); } -void View_SetViewOrientation(View* view, Vec3f* eye, Vec3f* at, Vec3f* up) { - if (eye->x == at->x && eye->z == at->z) { +void View_LookAt(View* view, Vec3f* eye, Vec3f* at, Vec3f* up) { + if ((eye->x == at->x) && (eye->z == at->z)) { eye->z += 0.1f; up->z = 0.0f; up->x = 0.0f; @@ -57,17 +66,21 @@ void View_SetViewOrientation(View* view, Vec3f* eye, Vec3f* at, Vec3f* up) { view->eye = *eye; view->at = *at; view->up = *up; - view->flags |= 1; + view->flags |= VIEW_VIEWING; } -void func_8013F050(View* view, Vec3f* eye, Vec3f* at, Vec3f* up) { +/* + * Unused. View_LookAt is always used instead. This version is similar but + * is missing the input sanitization and the update to the flags. + */ +void View_LookAtUnsafe(View* view, Vec3f* eye, Vec3f* at, Vec3f* up) { view->eye = *eye; view->at = *at; view->up = *up; } void View_SetScale(View* view, f32 scale) { - view->flags |= 4; + view->flags |= VIEW_PROJECTION_PERSPECTIVE; view->scale = scale; } @@ -75,28 +88,32 @@ void View_GetScale(View* view, f32* scale) { *scale = view->scale; } -void func_8013F0D0(View* view, f32 fovy, f32 zNear, f32 zFar) { +void View_SetPerspective(View* view, f32 fovy, f32 zNear, f32 zFar) { view->fovy = fovy; view->zNear = zNear; view->zFar = zFar; - view->flags |= 4; + view->flags |= VIEW_PROJECTION_PERSPECTIVE; } -void func_8013F100(View* view, f32* fovy, f32* zNear, f32* zFar) { +void View_GetPerspective(View* view, f32* fovy, f32* zNear, f32* zFar) { *fovy = view->fovy; *zNear = view->zNear; *zFar = view->zFar; } -void func_8013F120(View* view, f32 fovy, f32 zNear, f32 zFar) { +void View_SetOrtho(View* view, f32 fovy, f32 zNear, f32 zFar) { view->fovy = fovy; view->zNear = zNear; view->zFar = zFar; - view->flags |= 8; + view->flags |= VIEW_PROJECTION_ORTHO; view->scale = 1.0f; } -void func_8013F15C(View* view, f32* fovy, f32* zNear, f32* zFar) { +/* + * Identical to View_GetPerspective, and never called. + * Named as it seems to fit the "set, get" pattern. + */ +void View_GetOrtho(View* view, f32* fovy, f32* zNear, f32* zFar) { *fovy = view->fovy; *zNear = view->zNear; *zFar = view->zFar; @@ -104,14 +121,14 @@ void func_8013F15C(View* view, f32* fovy, f32* zNear, f32* zFar) { void View_SetViewport(View* view, Viewport* viewport) { view->viewport = *viewport; - view->flags |= 2; + view->flags |= VIEW_VIEWPORT; } void View_GetViewport(View* view, Viewport* viewport) { *viewport = view->viewport; } -void View_WriteScissor(Gfx** gfx, s32 ulx, s32 uly, s32 lrx, s32 lry) { +void View_SetScissor(Gfx** gfx, s32 ulx, s32 uly, s32 lrx, s32 lry) { Gfx* gfxp = *gfx; gDPSetScissor(gfxp++, G_SC_NON_INTERLACE, ulx, uly, lrx, lry); @@ -119,7 +136,7 @@ void View_WriteScissor(Gfx** gfx, s32 ulx, s32 uly, s32 lrx, s32 lry) { *gfx = gfxp; } -void View_SyncAndWriteScissor(View* view, Gfx** gfx) { +void View_ClearScissor(View* view, Gfx** gfx) { Gfx* gfxp = *gfx; s32 ulx = view->viewport.leftX; s32 uly = view->viewport.topY; @@ -127,12 +144,12 @@ void View_SyncAndWriteScissor(View* view, Gfx** gfx) { s32 lry = view->viewport.bottomY; gDPPipeSync(gfxp++); - View_WriteScissor(&gfxp, ulx, uly, lrx, lry); + View_SetScissor(&gfxp, ulx, uly, lrx, lry); *gfx = gfxp; } -void View_SetScissorForLetterbox(View* view) { +void View_ApplyLetterbox(View* view) { s32 letterboxY; s32 letterboxX; s32 pad1; @@ -143,20 +160,21 @@ void View_SetScissorForLetterbox(View* view) { OPEN_DISPS(view->gfxCtx); - letterboxY = ShrinkWindow_GetLetterboxMagnitude(); + letterboxY = ShrinkWindow_Letterbox_GetSize(); + letterboxX = -1; // The following is optimized to varX = 0 but affects codegen if (letterboxX < 0) { letterboxX = 0; } - if (letterboxX > 160) { - letterboxX = 160; + if (letterboxX > (SCREEN_WIDTH / 2)) { + letterboxX = SCREEN_WIDTH / 2; } if (letterboxY < 0) { letterboxY = 0; - } else if (letterboxY > 120) { - letterboxY = 120; + } else if (letterboxY > (SCREEN_HEIGHT / 2)) { + letterboxY = SCREEN_HEIGHT / 2; } ulx = view->viewport.leftX + letterboxX; @@ -166,31 +184,31 @@ void View_SetScissorForLetterbox(View* view) { gDPPipeSync(POLY_OPA_DISP++); { - s32 pad3; + s32 pad2; Gfx* polyOpa; polyOpa = POLY_OPA_DISP; - View_WriteScissor(&polyOpa, ulx, uly, lrx, lry); + View_SetScissor(&polyOpa, ulx, uly, lrx, lry); POLY_OPA_DISP = polyOpa; } gDPPipeSync(POLY_XLU_DISP++); { Gfx* polyXlu; - s32 pad4; + s32 pad3; polyXlu = POLY_XLU_DISP; - View_WriteScissor(&polyXlu, ulx, uly, lrx, lry); + View_SetScissor(&polyXlu, ulx, uly, lrx, lry); POLY_XLU_DISP = polyXlu; } CLOSE_DISPS(view->gfxCtx); } -s32 View_SetDistortionDirRot(View* view, f32 dirRotX, f32 dirRotY, f32 dirRotZ) { - view->distortionDirRot.x = dirRotX; - view->distortionDirRot.y = dirRotY; - view->distortionDirRot.z = dirRotZ; +s32 View_SetDistortionOrientation(View* view, f32 rotX, f32 rotY, f32 rotZ) { + view->distortionOrientation.x = rotX; + view->distortionOrientation.y = rotY; + view->distortionOrientation.z = rotZ; return 1; } @@ -207,22 +225,22 @@ s32 View_SetDistortionSpeed(View* view, f32 speed) { } s32 View_InitDistortion(View* view) { - view->distortionDirRot.x = 0.0f; - view->distortionDirRot.y = 0.0f; - view->distortionDirRot.z = 0.0f; + view->distortionOrientation.x = 0.0f; + view->distortionOrientation.y = 0.0f; + view->distortionOrientation.z = 0.0f; view->distortionScale.x = 1.0f; view->distortionScale.y = 1.0f; view->distortionScale.z = 1.0f; - view->curDistortionDirRot = view->distortionDirRot; + view->curDistortionOrientation = view->distortionOrientation; view->curDistortionScale = view->distortionScale; view->distortionSpeed = 0.0f; return 1; } s32 View_ClearDistortion(View* view) { - view->distortionDirRot.x = 0.0f; - view->distortionDirRot.y = 0.0f; - view->distortionDirRot.z = 0.0f; + view->distortionOrientation.x = 0.0f; + view->distortionOrientation.y = 0.0f; + view->distortionOrientation.z = 0.0f; view->distortionScale.x = 1.0f; view->distortionScale.y = 1.0f; view->distortionScale.z = 1.0f; @@ -230,8 +248,8 @@ s32 View_ClearDistortion(View* view) { return 1; } -s32 View_SetDistortion(View* view, Vec3f dirRot, Vec3f scale, f32 speed) { - view->distortionDirRot = dirRot; +s32 View_SetDistortion(View* view, Vec3f orientation, Vec3f scale, f32 speed) { + view->distortionOrientation = orientation; view->distortionScale = scale; view->distortionSpeed = speed; return 1; @@ -242,17 +260,19 @@ s32 View_StepDistortion(View* view, Mtx* projectionMtx) { if (view->distortionSpeed == 0.0f) { return false; - } else if (view->distortionSpeed == 1.0f) { - view->curDistortionDirRot = view->distortionDirRot; + } + + if (view->distortionSpeed == 1.0f) { + view->curDistortionOrientation = view->distortionOrientation; view->curDistortionScale = view->distortionScale; view->distortionSpeed = 0.0f; } else { - view->curDistortionDirRot.x = - F32_LERPIMP(view->curDistortionDirRot.x, view->distortionDirRot.x, view->distortionSpeed); - view->curDistortionDirRot.y = - F32_LERPIMP(view->curDistortionDirRot.y, view->distortionDirRot.y, view->distortionSpeed); - view->curDistortionDirRot.z = - F32_LERPIMP(view->curDistortionDirRot.z, view->distortionDirRot.z, view->distortionSpeed); + view->curDistortionOrientation.x = + F32_LERPIMP(view->curDistortionOrientation.x, view->distortionOrientation.x, view->distortionSpeed); + view->curDistortionOrientation.y = + F32_LERPIMP(view->curDistortionOrientation.y, view->distortionOrientation.y, view->distortionSpeed); + view->curDistortionOrientation.z = + F32_LERPIMP(view->curDistortionOrientation.z, view->distortionOrientation.z, view->distortionSpeed); view->curDistortionScale.x = F32_LERPIMP(view->curDistortionScale.x, view->distortionScale.x, view->distortionSpeed); @@ -264,29 +284,32 @@ s32 View_StepDistortion(View* view, Mtx* projectionMtx) { Matrix_MtxToMtxF(projectionMtx, &projectionMtxF); Matrix_Put(&projectionMtxF); - Matrix_RotateXFApply(view->curDistortionDirRot.x); - Matrix_RotateYF(view->curDistortionDirRot.y, MTXMODE_APPLY); - Matrix_RotateZF(view->curDistortionDirRot.z, MTXMODE_APPLY); + Matrix_RotateXFApply(view->curDistortionOrientation.x); + Matrix_RotateYF(view->curDistortionOrientation.y, MTXMODE_APPLY); + Matrix_RotateZF(view->curDistortionOrientation.z, MTXMODE_APPLY); Matrix_Scale(view->curDistortionScale.x, view->curDistortionScale.y, view->curDistortionScale.z, MTXMODE_APPLY); - Matrix_RotateZF(-view->curDistortionDirRot.z, MTXMODE_APPLY); - Matrix_RotateYF(-view->curDistortionDirRot.y, MTXMODE_APPLY); - Matrix_RotateXFApply(-view->curDistortionDirRot.x); + Matrix_RotateZF(-view->curDistortionOrientation.z, MTXMODE_APPLY); + Matrix_RotateYF(-view->curDistortionOrientation.y, MTXMODE_APPLY); + Matrix_RotateXFApply(-view->curDistortionOrientation.x); Matrix_ToMtx(projectionMtx); return true; } -void View_RenderView(View* view, s32 uParm2) { - uParm2 = (view->flags & uParm2) | uParm2 >> 4; +/** + * Apply view to POLY_OPA_DISP, POLY_XLU_DISP (and OVERLAY_DISP if ortho) + */ +void View_Apply(View* view, s32 mask) { + mask = (view->flags & mask) | (mask >> 4); - if (uParm2 & 8) { - View_RenderToOrthographicMatrix(view); + if (mask & VIEW_PROJECTION_ORTHO) { + View_ApplyOrtho(view); } else { - View_RenderToPerspectiveMatrix(view); + View_ApplyPerspective(view); } } -s32 View_RenderToPerspectiveMatrix(View* view) { +s32 View_ApplyPerspective(View* view) { f32 aspect; s32 width; s32 height; @@ -297,36 +320,39 @@ s32 View_RenderToPerspectiveMatrix(View* view) { OPEN_DISPS(gfxCtx); - vp = GRAPH_ALLOC(gfxCtx, sizeof(*vp)); + // Viewport + vp = GRAPH_ALLOC(gfxCtx, sizeof(Vp)); View_ViewportToVp(vp, &view->viewport); view->vp = *vp; - View_SetScissorForLetterbox(view); + View_ApplyLetterbox(view); gSPViewport(POLY_OPA_DISP++, vp); gSPViewport(POLY_XLU_DISP++, vp); - projection = GRAPH_ALLOC(gfxCtx, sizeof(*projection)); + // Perspective projection + projection = GRAPH_ALLOC(gfxCtx, sizeof(Mtx)); view->projectionPtr = projection; width = view->viewport.rightX - view->viewport.leftX; height = view->viewport.bottomY - view->viewport.topY; aspect = (f32)width / (f32)height; - guPerspective(projection, &view->normal, view->fovy, aspect, view->zNear, view->zFar, view->scale); + guPerspective(projection, &view->perspNorm, view->fovy, aspect, view->zNear, view->zFar, view->scale); view->projection = *projection; View_StepDistortion(view, projection); - gSPPerspNormalize(POLY_OPA_DISP++, view->normal); + gSPPerspNormalize(POLY_OPA_DISP++, view->perspNorm); gSPMatrix(POLY_OPA_DISP++, projection, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION); - gSPPerspNormalize(POLY_XLU_DISP++, view->normal); + gSPPerspNormalize(POLY_XLU_DISP++, view->perspNorm); gSPMatrix(POLY_XLU_DISP++, projection, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION); - viewing = GRAPH_ALLOC(gfxCtx, sizeof(*viewing)); + // View matrix (look-at) + viewing = GRAPH_ALLOC(gfxCtx, sizeof(Mtx)); view->viewingPtr = viewing; - if (view->eye.x == view->at.x && view->eye.y == view->at.y && view->eye.z == view->at.z) { + if ((view->eye.x == view->at.x) && (view->eye.y == view->at.y) && (view->eye.z == view->at.z)) { view->eye.z += 2.0f; } @@ -343,24 +369,24 @@ s32 View_RenderToPerspectiveMatrix(View* view) { return 1; } -s32 View_RenderToOrthographicMatrix(View* view) { +s32 View_ApplyOrtho(View* view) { Vp* vp; Mtx* projection; GraphicsContext* gfxCtx = view->gfxCtx; OPEN_DISPS(gfxCtx); - vp = GRAPH_ALLOC(gfxCtx, sizeof(*vp)); + vp = GRAPH_ALLOC(gfxCtx, sizeof(Vp)); View_ViewportToVp(vp, &view->viewport); view->vp = *vp; - View_SetScissorForLetterbox(view); + View_ApplyLetterbox(view); gSPViewport(POLY_OPA_DISP++, vp); gSPViewport(POLY_XLU_DISP++, vp); gSPViewport(OVERLAY_DISP++, vp); - projection = GRAPH_ALLOC(gfxCtx, sizeof(*projection)); + projection = GRAPH_ALLOC(gfxCtx, sizeof(Mtx)); view->projectionPtr = projection; guOrtho(projection, gScreenWidth * -0.5f, gScreenWidth * 0.5f, gScreenHeight * -0.5f, gScreenHeight * 0.5f, @@ -376,7 +402,10 @@ s32 View_RenderToOrthographicMatrix(View* view) { return 1; } -s32 func_8013FBC8(View* view) { +/** + * Apply scissor, viewport and projection (ortho) to OVERLAY_DISP. + */ +s32 View_ApplyOrthoToOverlay(View* view) { Vp* vp; Mtx* projection; GraphicsContext* gfxCtx; @@ -385,7 +414,7 @@ s32 func_8013FBC8(View* view) { OPEN_DISPS(gfxCtx); - vp = GRAPH_ALLOC(gfxCtx, sizeof(*vp)); + vp = GRAPH_ALLOC(gfxCtx, sizeof(Vp)); View_ViewportToVp(vp, &view->viewport); view->vp = *vp; @@ -395,26 +424,29 @@ s32 func_8013FBC8(View* view) { s32 pad; overlay = OVERLAY_DISP; - View_WriteScissor(&overlay, view->viewport.leftX, view->viewport.topY, view->viewport.rightX, - view->viewport.bottomY); + View_SetScissor(&overlay, view->viewport.leftX, view->viewport.topY, view->viewport.rightX, + view->viewport.bottomY); OVERLAY_DISP = overlay; } gSPViewport(OVERLAY_DISP++, vp); - projection = GRAPH_ALLOC(gfxCtx, sizeof(*projection)); + projection = GRAPH_ALLOC(gfxCtx, sizeof(Mtx)); view->projectionPtr = projection; guOrtho(projection, gScreenWidth * -0.5f, gScreenWidth * 0.5f, gScreenHeight * -0.5f, gScreenHeight * 0.5f, view->zNear, view->zFar, view->scale); view->projection = *projection; - gSPMatrix(OVERLAY_DISP++, projection, G_MTX_LOAD | G_MTX_PROJECTION); + gSPMatrix(OVERLAY_DISP++, projection, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION); CLOSE_DISPS(gfxCtx); return 1; } -s32 func_8013FD74(View* view) { +/** + * Apply scissor, viewport, view and projection (perspective) to OVERLAY_DISP. + */ +s32 View_ApplyPerspectiveToOverlay(View* view) { f32 aspect; s32 width; s32 height; @@ -428,7 +460,7 @@ s32 func_8013FD74(View* view) { OPEN_DISPS(gfxCtx); - vp = GRAPH_ALLOC(gfxCtx, sizeof(*vp)); + vp = GRAPH_ALLOC(gfxCtx, sizeof(Vp)); View_ViewportToVp(vp, &view->viewport); view->vp = *vp; @@ -438,28 +470,30 @@ s32 func_8013FD74(View* view) { Gfx* overlay; overlay = OVERLAY_DISP; - View_WriteScissor(&overlay, view->viewport.leftX, view->viewport.topY, view->viewport.rightX, - view->viewport.bottomY); + View_SetScissor(&overlay, view->viewport.leftX, view->viewport.topY, view->viewport.rightX, + view->viewport.bottomY); OVERLAY_DISP = overlay; } gSPViewport(OVERLAY_DISP++, vp); - projection = GRAPH_ALLOC(gfxCtx, sizeof(*projection)); + projection = GRAPH_ALLOC(gfxCtx, sizeof(Mtx)); view->projectionPtr = projection; width = view->viewport.rightX - view->viewport.leftX; height = view->viewport.bottomY - view->viewport.topY; aspect = (f32)width / (f32)height; - guPerspective(projection, &view->normal, view->fovy, aspect, view->zNear, view->zFar, view->scale); + guPerspective(projection, &view->perspNorm, view->fovy, aspect, view->zNear, view->zFar, view->scale); + view->projection = *projection; - gSPPerspNormalize(OVERLAY_DISP++, view->normal); + gSPPerspNormalize(OVERLAY_DISP++, view->perspNorm); gSPMatrix(OVERLAY_DISP++, projection, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION); - viewing = GRAPH_ALLOC(gfxCtx, sizeof(*viewing)); + viewing = GRAPH_ALLOC(gfxCtx, sizeof(Mtx)); view->viewingPtr = viewing; + // This check avoids a divide-by-zero in guLookAt if eye == at if (view->eye.x == view->at.x && view->eye.y == view->at.y && view->eye.z == view->at.z) { view->eye.z += 2.0f; } @@ -476,7 +510,10 @@ s32 func_8013FD74(View* view) { return 1; } -s32 func_80140024(View* view) { +/** + * Just updates view's view matrix from its eye/at/up vectors. + */ +s32 View_UpdateViewingMatrix(View* view) { guLookAt(view->viewingPtr, view->eye.x, view->eye.y, view->eye.z, view->at.x, view->at.y, view->at.z, view->up.x, view->up.y, view->up.z); @@ -486,22 +523,22 @@ s32 func_80140024(View* view) { return 1; } -s32 func_801400CC(View* view, Gfx** gfxp) { +s32 View_ApplyTo(View* view, Gfx** gfxp) { Gfx* gfx = *gfxp; GraphicsContext* gfxCtx = view->gfxCtx; Viewport* viewport = &view->viewport; Mtx* projection; Vp* vp; - vp = GRAPH_ALLOC(gfxCtx, sizeof(*vp)); + vp = GRAPH_ALLOC(gfxCtx, sizeof(Vp)); View_ViewportToVp(vp, viewport); view->vp = *vp; - View_SyncAndWriteScissor(view, &gfx); + View_ClearScissor(view, &gfx); gSPViewport(gfx++, vp); - projection = GRAPH_ALLOC(gfxCtx, sizeof(*projection)); + projection = GRAPH_ALLOC(gfxCtx, sizeof(Mtx)); view->projectionPtr = projection; guOrtho(projection, gScreenWidth * -0.5f, gScreenWidth * 0.5f, gScreenHeight * -0.5f, gScreenHeight * 0.5f, @@ -509,7 +546,7 @@ s32 func_801400CC(View* view, Gfx** gfxp) { view->projection = *projection; - gSPMatrix(gfx++, projection, G_MTX_LOAD | G_MTX_PROJECTION); + gSPMatrix(gfx++, projection, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION); *gfxp = gfx; return 1; diff --git a/src/overlays/actors/ovl_Boss_01/z_boss_01.c b/src/overlays/actors/ovl_Boss_01/z_boss_01.c index 11790f377..40800569f 100644 --- a/src/overlays/actors/ovl_Boss_01/z_boss_01.c +++ b/src/overlays/actors/ovl_Boss_01/z_boss_01.c @@ -6,6 +6,7 @@ #include "z_boss_01.h" #include "z64rumble.h" +#include "z64shrink_window.h" #define FLAGS (ACTOR_FLAG_1 | ACTOR_FLAG_4 | ACTOR_FLAG_10 | ACTOR_FLAG_20) diff --git a/src/overlays/actors/ovl_Boss_02/z_boss_02.c b/src/overlays/actors/ovl_Boss_02/z_boss_02.c index 9808e68a4..b3ab79b20 100644 --- a/src/overlays/actors/ovl_Boss_02/z_boss_02.c +++ b/src/overlays/actors/ovl_Boss_02/z_boss_02.c @@ -6,6 +6,7 @@ #include "z_boss_02.h" #include "z64rumble.h" +#include "z64shrink_window.h" #include "overlays/actors/ovl_Door_Warp1/z_door_warp1.h" #include "overlays/actors/ovl_Item_B_Heart/z_item_b_heart.h" #include "objects/gameplay_keep/gameplay_keep.h" @@ -2033,7 +2034,7 @@ void func_809DD934(Boss02* this, PlayState* play) { Matrix_RotateZF(this->unk_1D54, MTXMODE_APPLY); Matrix_MultVecY(1.0f, &this->subCamUp); Play_SetCameraAtEyeUp(play, this->subCamId, &this->subCamAt, &this->subCamEye, &this->subCamUp); - ShrinkWindow_SetLetterboxTarget(27); + ShrinkWindow_Letterbox_SetSizeTarget(27); } } @@ -2241,6 +2242,6 @@ void func_809DEAC4(Boss02* this, PlayState* play) { Play_SetCameraAtEyeUp(play, this->subCamId, &this->subCamAt, &subCamEye, &this->subCamUp); this->subCamUp.z = this->subCamUp.x = 0.0f; this->subCamUp.y = 1.0f; - ShrinkWindow_SetLetterboxTarget(27); + ShrinkWindow_Letterbox_SetSizeTarget(27); } } diff --git a/src/overlays/actors/ovl_Boss_04/z_boss_04.c b/src/overlays/actors/ovl_Boss_04/z_boss_04.c index f26bc505f..8eb73d84d 100644 --- a/src/overlays/actors/ovl_Boss_04/z_boss_04.c +++ b/src/overlays/actors/ovl_Boss_04/z_boss_04.c @@ -5,6 +5,7 @@ */ #include "z_boss_04.h" +#include "z64shrink_window.h" #define FLAGS (ACTOR_FLAG_1 | ACTOR_FLAG_4 | ACTOR_FLAG_10 | ACTOR_FLAG_20) @@ -399,7 +400,7 @@ void func_809EC568(Boss04* this, PlayState* play) { if (this->subCamId != SUB_CAM_ID_DONE) { Vec3f subCamAt; - ShrinkWindow_SetLetterboxTarget(27); + ShrinkWindow_Letterbox_SetSizeTarget(27); if (this->subCamAtOscillator != 0) { this->subCamAtOscillator--; } diff --git a/src/overlays/actors/ovl_Boss_06/z_boss_06.c b/src/overlays/actors/ovl_Boss_06/z_boss_06.c index 045a76995..3aadce42c 100644 --- a/src/overlays/actors/ovl_Boss_06/z_boss_06.c +++ b/src/overlays/actors/ovl_Boss_06/z_boss_06.c @@ -6,6 +6,7 @@ #include "prevent_bss_reordering.h" #include "z_boss_06.h" +#include "z64shrink_window.h" #include "overlays/actors/ovl_En_Knight/z_en_knight.h" #include "objects/gameplay_keep/gameplay_keep.h" #include "objects/object_knight/object_knight.h" @@ -339,7 +340,7 @@ void func_809F24C8(Boss06* this, PlayState* play) { } if (this->subCamId != SUB_CAM_ID_DONE) { - ShrinkWindow_SetLetterboxTarget(27); + ShrinkWindow_Letterbox_SetSizeTarget(27); Play_SetCameraAtEye(play, this->subCamId, &this->subCamAt, &this->subCamEye); } } diff --git a/src/overlays/actors/ovl_Boss_07/z_boss_07.c b/src/overlays/actors/ovl_Boss_07/z_boss_07.c index 9b988da18..923c838fc 100644 --- a/src/overlays/actors/ovl_Boss_07/z_boss_07.c +++ b/src/overlays/actors/ovl_Boss_07/z_boss_07.c @@ -5,6 +5,7 @@ */ #include "z_boss_07.h" +#include "z64shrink_window.h" #define FLAGS (ACTOR_FLAG_1 | ACTOR_FLAG_4 | ACTOR_FLAG_10 | ACTOR_FLAG_20) diff --git a/src/overlays/actors/ovl_En_Bsb/z_en_bsb.c b/src/overlays/actors/ovl_En_Bsb/z_en_bsb.c index 5a3ce9cf8..4ad558a0a 100644 --- a/src/overlays/actors/ovl_En_Bsb/z_en_bsb.c +++ b/src/overlays/actors/ovl_En_Bsb/z_en_bsb.c @@ -6,6 +6,7 @@ #include "z_en_bsb.h" #include "z64rumble.h" +#include "z64shrink_window.h" #define FLAGS (ACTOR_FLAG_1 | ACTOR_FLAG_4 | ACTOR_FLAG_10 | ACTOR_FLAG_20 | ACTOR_FLAG_2000000) diff --git a/src/overlays/actors/ovl_En_Fishing/z_en_fishing.c b/src/overlays/actors/ovl_En_Fishing/z_en_fishing.c index 8bd1b7e0e..baa65bfa3 100644 --- a/src/overlays/actors/ovl_En_Fishing/z_en_fishing.c +++ b/src/overlays/actors/ovl_En_Fishing/z_en_fishing.c @@ -6,6 +6,7 @@ #include "z_en_fishing.h" #include "z64rumble.h" +#include "z64shrink_window.h" #include "objects/object_fish/object_fish.h" #include "overlays/actors/ovl_En_Kanban/z_en_kanban.h" @@ -5170,7 +5171,7 @@ void EnFishing_UpdateOwner(Actor* thisx, PlayState* play2) { sSubCamVelFactor = 0.0f; // fallthrough case 2: - ShrinkWindow_SetLetterboxTarget(27); + ShrinkWindow_Letterbox_SetSizeTarget(27); spFC.x = sLurePos.x - player->actor.world.pos.x; spFC.z = sLurePos.z - player->actor.world.pos.z; diff --git a/src/overlays/actors/ovl_En_Knight/z_en_knight.c b/src/overlays/actors/ovl_En_Knight/z_en_knight.c index 095ca5a98..17d0e3752 100644 --- a/src/overlays/actors/ovl_En_Knight/z_en_knight.c +++ b/src/overlays/actors/ovl_En_Knight/z_en_knight.c @@ -5,6 +5,7 @@ */ #include "z_en_knight.h" +#include "z64shrink_window.h" #define FLAGS (ACTOR_FLAG_1 | ACTOR_FLAG_4 | ACTOR_FLAG_10 | ACTOR_FLAG_20) diff --git a/src/overlays/actors/ovl_player_actor/z_player.c b/src/overlays/actors/ovl_player_actor/z_player.c index 681438463..1f92e8825 100644 --- a/src/overlays/actors/ovl_player_actor/z_player.c +++ b/src/overlays/actors/ovl_player_actor/z_player.c @@ -7,6 +7,7 @@ #include "global.h" #include "z64quake.h" #include "z64rumble.h" +#include "z64shrink_window.h" #define THIS ((Player*)thisx) diff --git a/src/overlays/gamestates/ovl_daytelop/z_daytelop.c b/src/overlays/gamestates/ovl_daytelop/z_daytelop.c index ad5230253..201030862 100644 --- a/src/overlays/gamestates/ovl_daytelop/z_daytelop.c +++ b/src/overlays/gamestates/ovl_daytelop/z_daytelop.c @@ -5,6 +5,8 @@ */ #include "z_daytelop.h" +#include "z64shrink_window.h" +#include "z64view.h" #include "misc/daytelop_static/daytelop_static.h" #include "interface/icon_item_gameover_static/icon_item_gameover_static.h" diff --git a/src/overlays/gamestates/ovl_file_choose/z_file_choose_NES.c b/src/overlays/gamestates/ovl_file_choose/z_file_choose_NES.c index 657a2530f..da9144e7c 100644 --- a/src/overlays/gamestates/ovl_file_choose/z_file_choose_NES.c +++ b/src/overlays/gamestates/ovl_file_choose/z_file_choose_NES.c @@ -6,6 +6,8 @@ #include "z_file_choose.h" #include "z64rumble.h" +#include "z64shrink_window.h" +#include "z64view.h" extern UNK_TYPE D_01002800; extern UNK_TYPE D_01007980; diff --git a/src/overlays/gamestates/ovl_opening/z_opening.c b/src/overlays/gamestates/ovl_opening/z_opening.c index 42336b9bc..fc5d05be2 100644 --- a/src/overlays/gamestates/ovl_opening/z_opening.c +++ b/src/overlays/gamestates/ovl_opening/z_opening.c @@ -5,6 +5,8 @@ */ #include "z_opening.h" +#include "z64shrink_window.h" +#include "z64view.h" void TitleSetup_SetupTitleScreen(TitleSetupState* this) { static s32 sOpeningEntrances[] = { ENTRANCE(CUTSCENE, 0), ENTRANCE(CUTSCENE, 1) }; diff --git a/src/overlays/gamestates/ovl_select/z_select.c b/src/overlays/gamestates/ovl_select/z_select.c index 6ae0f5b6c..2e8bbb802 100644 --- a/src/overlays/gamestates/ovl_select/z_select.c +++ b/src/overlays/gamestates/ovl_select/z_select.c @@ -5,6 +5,8 @@ */ #include "z_select.h" +#include "z64shrink_window.h" +#include "z64view.h" #include "libc/alloca.h" #include "overlays/gamestates/ovl_title/z_title.h" @@ -1026,7 +1028,7 @@ void MapSelect_Draw(MapSelectState* this) { func_8012CF0C(gfxCtx, true, true, 0, 0, 0); SET_FULLSCREEN_VIEWPORT(&this->view); - View_RenderView(&this->view, 0xF); + View_Apply(&this->view, VIEW_ALL); if (!this->state.running) { MapSelect_DrawLoadingScreen(this); } else { diff --git a/src/overlays/gamestates/ovl_title/z_title.c b/src/overlays/gamestates/ovl_title/z_title.c index 62d2a36d0..2b23bf565 100644 --- a/src/overlays/gamestates/ovl_title/z_title.c +++ b/src/overlays/gamestates/ovl_title/z_title.c @@ -5,6 +5,8 @@ */ #include "z_title.h" +#include "z64shrink_window.h" +#include "z64view.h" #include "overlays/gamestates/ovl_opening/z_opening.h" #include "misc/nintendo_rogo_static/nintendo_rogo_static.h" @@ -44,9 +46,9 @@ void ConsoleLogo_RenderView(ConsoleLogoState* this, f32 x, f32 y, f32 z) { up.x = up.z = 0.0f; at.x = at.y = at.z = 0.0f; up.y = 1.0f; - func_8013F0D0(view, 30.0f, 10.0f, 12800.0f); - View_SetViewOrientation(view, &eye, &at, &up); - View_RenderView(view, 0xF); + View_SetPerspective(view, 30.0f, 10.0f, 12800.0f); + View_LookAt(view, &eye, &at, &up); + View_Apply(view, VIEW_ALL); } void ConsoleLogo_Draw(GameState* thisx) { diff --git a/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope_NES.c b/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope_NES.c index c02ebcad2..3b3de5937 100644 --- a/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope_NES.c +++ b/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope_NES.c @@ -5,6 +5,7 @@ */ #include "z_kaleido_scope.h" +#include "z64view.h" extern UNK_TYPE D_02001360; extern UNK_TYPE D_020044A0; diff --git a/tools/disasm/functions.txt b/tools/disasm/functions.txt index 594ce3427..8a146996d 100644 --- a/tools/disasm/functions.txt +++ b/tools/disasm/functions.txt @@ -2721,33 +2721,33 @@ 0x8013EE48:("Rumble_SetUpdateEnabled",), 0x8013EE60:("View_ViewportToVp",), 0x8013EEF4:("View_Init",), - 0x8013EF9C:("View_SetViewOrientation",), - 0x8013F050:("func_8013F050",), + 0x8013EF9C:("View_LookAt",), + 0x8013F050:("View_LookAtUnsafe",), 0x8013F0A0:("View_SetScale",), 0x8013F0C0:("View_GetScale",), - 0x8013F0D0:("func_8013F0D0",), - 0x8013F100:("func_8013F100",), - 0x8013F120:("func_8013F120",), - 0x8013F15C:("func_8013F15C",), + 0x8013F0D0:("View_SetPerspective",), + 0x8013F100:("View_GetPerspective",), + 0x8013F120:("View_SetOrtho",), + 0x8013F15C:("View_GetOrtho",), 0x8013F17C:("View_SetViewport",), 0x8013F1B0:("View_GetViewport",), - 0x8013F1D8:("View_WriteScissor",), - 0x8013F28C:("View_SyncAndWriteScissor",), - 0x8013F2F8:("View_SetScissorForLetterbox",), - 0x8013F3F8:("View_SetDistortionDirRot",), + 0x8013F1D8:("View_SetScissor",), + 0x8013F28C:("View_ClearScissor",), + 0x8013F2F8:("View_ApplyLetterbox",), + 0x8013F3F8:("View_SetDistortionOrientation",), 0x8013F420:("View_SetDistortionScale",), 0x8013F448:("View_SetDistortionSpeed",), 0x8013F45C:("View_InitDistortion",), 0x8013F4C0:("View_ClearDistortion",), 0x8013F4F4:("View_SetDistortion",), 0x8013F54C:("View_StepDistortion",), - 0x8013F6FC:("View_RenderView",), - 0x8013F748:("View_RenderToPerspectiveMatrix",), - 0x8013FA1C:("View_RenderToOrthographicMatrix",), - 0x8013FBC8:("func_8013FBC8",), - 0x8013FD74:("func_8013FD74",), - 0x80140024:("func_80140024",), - 0x801400CC:("func_801400CC",), + 0x8013F6FC:("View_Apply",), + 0x8013F748:("View_ApplyPerspective",), + 0x8013FA1C:("View_ApplyOrtho",), + 0x8013FBC8:("View_ApplyOrthoToOverlay",), + 0x8013FD74:("View_ApplyPerspectiveToOverlay",), + 0x80140024:("View_UpdateViewingMatrix",), + 0x801400CC:("View_ApplyTo",), 0x80140260:("func_80140260",), 0x8014026C:("func_8014026C",), 0x80140730:("func_80140730",), @@ -2892,14 +2892,14 @@ 0x80160B40:("PlayerCall_Destroy",), 0x80160B80:("PlayerCall_Update",), 0x80160BC0:("PlayerCall_Draw",), - 0x80160C00:("ShrinkWindow_SetLetterboxTarget",), - 0x80160C14:("ShrinkWindow_GetLetterboxTarget",), - 0x80160C28:("ShrinkWindow_SetLetterboxMagnitude",), - 0x80160C3C:("ShrinkWindow_GetLetterboxMagnitude",), - 0x80160C50:("ShrinkWindow_SetPillarboxTarget",), - 0x80160C64:("ShrinkWindow_GetPillarboxTarget",), - 0x80160C78:("ShrinkWindow_SetPillarboxMagnitude",), - 0x80160C8C:("ShrinkWindow_GetPillarboxMagnitude",), + 0x80160C00:("ShrinkWindow_Letterbox_SetSizeTarget",), + 0x80160C14:("ShrinkWindow_Letterbox_GetSizeTarget",), + 0x80160C28:("ShrinkWindow_Letterbox_SetSize",), + 0x80160C3C:("ShrinkWindow_Letterbox_GetSize",), + 0x80160C50:("ShrinkWindow_Pillarbox_SetSizeTarget",), + 0x80160C64:("ShrinkWindow_Pillarbox_GetSizeTarget",), + 0x80160C78:("ShrinkWindow_Pillarbox_SetSize",), + 0x80160C8C:("ShrinkWindow_Pillarbox_GetSize",), 0x80160CA0:("ShrinkWindow_Init",), 0x80160CD4:("ShrinkWindow_Destroy",), 0x80160CE4:("ShrinkWindow_Update",), diff --git a/tools/disasm/variables.txt b/tools/disasm/variables.txt index 97cf77e76..a0b369264 100644 --- a/tools/disasm/variables.txt +++ b/tools/disasm/variables.txt @@ -4046,8 +4046,8 @@ 0x801F6B34:("sPlayerCallDestroyFunc","UNK_TYPE1","",0x1), 0x801F6B38:("sPlayerCallUpdateFunc","UNK_TYPE1","",0x1), 0x801F6B3C:("sPlayerCallDrawFunc","UNK_TYPE1","",0x1), - 0x801F6B40:("gShrinkWindowContext","ShrinkWindowContext","",0x4), - 0x801F6B44:("gShrinkWindowContextPtr","ShrinkWindowContext*","",0x4), + 0x801F6B40:("sShrinkWindow","ShrinkWindow","",0x4), + 0x801F6B44:("sShrinkWindowPtr","ShrinkWindow*","",0x4), 0x801F6B50:("D_801F6B50","UNK_TYPE4","",0x4), 0x801F6B58:("D_801F6B58","UNK_TYPE1","",0x1), 0x801F6BF0:("sKaleidoAreaFaultClient","FaultAddrConvClient","",0xC), diff --git a/tools/sizes/code_functions.csv b/tools/sizes/code_functions.csv index 33b82cef0..f64c45241 100644 --- a/tools/sizes/code_functions.csv +++ b/tools/sizes/code_functions.csv @@ -2235,33 +2235,33 @@ asm/non_matchings/code/code_8013EC10/Rumble_StateWipeRequests.s,Rumble_StateWipe asm/non_matchings/code/code_8013EC10/Rumble_SetUpdateEnabled.s,Rumble_SetUpdateEnabled,0x8013EE48,0x6 asm/non_matchings/code/z_view/View_ViewportToVp.s,View_ViewportToVp,0x8013EE60,0x25 asm/non_matchings/code/z_view/View_Init.s,View_Init,0x8013EEF4,0x2A -asm/non_matchings/code/z_view/View_SetViewOrientation.s,View_SetViewOrientation,0x8013EF9C,0x2D -asm/non_matchings/code/z_view/func_8013F050.s,func_8013F050,0x8013F050,0x14 +asm/non_matchings/code/z_view/View_LookAt.s,View_LookAt,0x8013EF9C,0x2D +asm/non_matchings/code/z_view/View_LookAtUnsafe.s,View_LookAtUnsafe,0x8013F050,0x14 asm/non_matchings/code/z_view/View_SetScale.s,View_SetScale,0x8013F0A0,0x8 asm/non_matchings/code/z_view/View_GetScale.s,View_GetScale,0x8013F0C0,0x4 -asm/non_matchings/code/z_view/func_8013F0D0.s,func_8013F0D0,0x8013F0D0,0xC -asm/non_matchings/code/z_view/func_8013F100.s,func_8013F100,0x8013F100,0x8 -asm/non_matchings/code/z_view/func_8013F120.s,func_8013F120,0x8013F120,0xF -asm/non_matchings/code/z_view/func_8013F15C.s,func_8013F15C,0x8013F15C,0x8 +asm/non_matchings/code/z_view/View_SetPerspective.s,View_SetPerspective,0x8013F0D0,0xC +asm/non_matchings/code/z_view/View_GetPerspective.s,View_GetPerspective,0x8013F100,0x8 +asm/non_matchings/code/z_view/View_SetOrtho.s,View_SetOrtho,0x8013F120,0xF +asm/non_matchings/code/z_view/View_GetOrtho.s,View_GetOrtho,0x8013F15C,0x8 asm/non_matchings/code/z_view/View_SetViewport.s,View_SetViewport,0x8013F17C,0xD asm/non_matchings/code/z_view/View_GetViewport.s,View_GetViewport,0x8013F1B0,0xA -asm/non_matchings/code/z_view/View_WriteScissor.s,View_WriteScissor,0x8013F1D8,0x2D -asm/non_matchings/code/z_view/View_SyncAndWriteScissor.s,View_SyncAndWriteScissor,0x8013F28C,0x1B -asm/non_matchings/code/z_view/View_SetScissorForLetterbox.s,View_SetScissorForLetterbox,0x8013F2F8,0x40 -asm/non_matchings/code/z_view/View_SetDistortionDirRot.s,View_SetDistortionDirRot,0x8013F3F8,0xA +asm/non_matchings/code/z_view/View_SetScissor.s,View_SetScissor,0x8013F1D8,0x2D +asm/non_matchings/code/z_view/View_ClearScissor.s,View_ClearScissor,0x8013F28C,0x1B +asm/non_matchings/code/z_view/View_ApplyLetterbox.s,View_ApplyLetterbox,0x8013F2F8,0x40 +asm/non_matchings/code/z_view/View_SetDistortionOrientation.s,View_SetDistortionOrientation,0x8013F3F8,0xA asm/non_matchings/code/z_view/View_SetDistortionScale.s,View_SetDistortionScale,0x8013F420,0xA asm/non_matchings/code/z_view/View_SetDistortionSpeed.s,View_SetDistortionSpeed,0x8013F448,0x5 asm/non_matchings/code/z_view/View_InitDistortion.s,View_InitDistortion,0x8013F45C,0x19 asm/non_matchings/code/z_view/View_ClearDistortion.s,View_ClearDistortion,0x8013F4C0,0xD asm/non_matchings/code/z_view/View_SetDistortion.s,View_SetDistortion,0x8013F4F4,0x16 asm/non_matchings/code/z_view/View_StepDistortion.s,View_StepDistortion,0x8013F54C,0x6C -asm/non_matchings/code/z_view/View_RenderView.s,View_RenderView,0x8013F6FC,0x13 -asm/non_matchings/code/z_view/View_RenderToPerspectiveMatrix.s,View_RenderToPerspectiveMatrix,0x8013F748,0xB5 -asm/non_matchings/code/z_view/View_RenderToOrthographicMatrix.s,View_RenderToOrthographicMatrix,0x8013FA1C,0x6B -asm/non_matchings/code/z_view/func_8013FBC8.s,func_8013FBC8,0x8013FBC8,0x6B -asm/non_matchings/code/z_view/func_8013FD74.s,func_8013FD74,0x8013FD74,0xAC -asm/non_matchings/code/z_view/func_80140024.s,func_80140024,0x80140024,0x2A -asm/non_matchings/code/z_view/func_801400CC.s,func_801400CC,0x801400CC,0x65 +asm/non_matchings/code/z_view/View_Apply.s,View_Apply,0x8013F6FC,0x13 +asm/non_matchings/code/z_view/View_ApplyPerspective.s,View_ApplyPerspective,0x8013F748,0xB5 +asm/non_matchings/code/z_view/View_ApplyOrtho.s,View_ApplyOrtho,0x8013FA1C,0x6B +asm/non_matchings/code/z_view/View_ApplyOrthoToOverlay.s,View_ApplyOrthoToOverlay,0x8013FBC8,0x6B +asm/non_matchings/code/z_view/View_ApplyPerspectiveToOverlay.s,View_ApplyPerspectiveToOverlay,0x8013FD74,0xAC +asm/non_matchings/code/z_view/View_UpdateViewingMatrix.s,View_UpdateViewingMatrix,0x80140024,0x2A +asm/non_matchings/code/z_view/View_ApplyTo.s,View_ApplyTo,0x801400CC,0x65 asm/non_matchings/code/z_vimode/func_80140260.s,func_80140260,0x80140260,0x3 asm/non_matchings/code/z_vimode/func_8014026C.s,func_8014026C,0x8014026C,0x131 asm/non_matchings/code/z_vimode/func_80140730.s,func_80140730,0x80140730,0x38 @@ -2406,14 +2406,14 @@ asm/non_matchings/code/z_player_call/PlayerCall_Init.s,PlayerCall_Init,0x80160AF asm/non_matchings/code/z_player_call/PlayerCall_Destroy.s,PlayerCall_Destroy,0x80160B40,0x10 asm/non_matchings/code/z_player_call/PlayerCall_Update.s,PlayerCall_Update,0x80160B80,0x10 asm/non_matchings/code/z_player_call/PlayerCall_Draw.s,PlayerCall_Draw,0x80160BC0,0x10 -asm/non_matchings/code/z_shrink_window/ShrinkWindow_SetLetterboxTarget.s,ShrinkWindow_SetLetterboxTarget,0x80160C00,0x5 -asm/non_matchings/code/z_shrink_window/ShrinkWindow_GetLetterboxTarget.s,ShrinkWindow_GetLetterboxTarget,0x80160C14,0x5 -asm/non_matchings/code/z_shrink_window/ShrinkWindow_SetLetterboxMagnitude.s,ShrinkWindow_SetLetterboxMagnitude,0x80160C28,0x5 -asm/non_matchings/code/z_shrink_window/ShrinkWindow_GetLetterboxMagnitude.s,ShrinkWindow_GetLetterboxMagnitude,0x80160C3C,0x5 -asm/non_matchings/code/z_shrink_window/ShrinkWindow_SetPillarboxTarget.s,ShrinkWindow_SetPillarboxTarget,0x80160C50,0x5 -asm/non_matchings/code/z_shrink_window/ShrinkWindow_GetPillarboxTarget.s,ShrinkWindow_GetPillarboxTarget,0x80160C64,0x5 -asm/non_matchings/code/z_shrink_window/ShrinkWindow_SetPillarboxMagnitude.s,ShrinkWindow_SetPillarboxMagnitude,0x80160C78,0x5 -asm/non_matchings/code/z_shrink_window/ShrinkWindow_GetPillarboxMagnitude.s,ShrinkWindow_GetPillarboxMagnitude,0x80160C8C,0x5 +asm/non_matchings/code/z_shrink_window/ShrinkWindow_Letterbox_SetSizeTarget.s,ShrinkWindow_Letterbox_SetSizeTarget,0x80160C00,0x5 +asm/non_matchings/code/z_shrink_window/ShrinkWindow_Letterbox_GetSizeTarget.s,ShrinkWindow_Letterbox_GetSizeTarget,0x80160C14,0x5 +asm/non_matchings/code/z_shrink_window/ShrinkWindow_Letterbox_SetSize.s,ShrinkWindow_Letterbox_SetSize,0x80160C28,0x5 +asm/non_matchings/code/z_shrink_window/ShrinkWindow_Letterbox_GetSize.s,ShrinkWindow_Letterbox_GetSize,0x80160C3C,0x5 +asm/non_matchings/code/z_shrink_window/ShrinkWindow_Pillarbox_SetSizeTarget.s,ShrinkWindow_Pillarbox_SetSizeTarget,0x80160C50,0x5 +asm/non_matchings/code/z_shrink_window/ShrinkWindow_Pillarbox_GetSizeTarget.s,ShrinkWindow_Pillarbox_GetSizeTarget,0x80160C64,0x5 +asm/non_matchings/code/z_shrink_window/ShrinkWindow_Pillarbox_SetSize.s,ShrinkWindow_Pillarbox_SetSize,0x80160C78,0x5 +asm/non_matchings/code/z_shrink_window/ShrinkWindow_Pillarbox_GetSize.s,ShrinkWindow_Pillarbox_GetSize,0x80160C8C,0x5 asm/non_matchings/code/z_shrink_window/ShrinkWindow_Init.s,ShrinkWindow_Init,0x80160CA0,0xD asm/non_matchings/code/z_shrink_window/ShrinkWindow_Destroy.s,ShrinkWindow_Destroy,0x80160CD4,0x4 asm/non_matchings/code/z_shrink_window/ShrinkWindow_Update.s,ShrinkWindow_Update,0x80160CE4,0x2D From aa3f1be55e0409e032062cc6779a6d5710941b85 Mon Sep 17 00:00:00 2001 From: Derek Hensley Date: Sun, 2 Oct 2022 09:07:55 -0700 Subject: [PATCH 06/10] Object Tru Docs (Koume) (#1098) * Name everything in xml * Actor docs regarding assets * move header include * PR * Format * PR * MT animation enum * index () --- assets/xml/objects/object_trt.xml | 4 +- assets/xml/objects/object_tru.xml | 217 +++++++------- .../actors/ovl_En_Jc_Mato/z_en_jc_mato.c | 7 +- src/overlays/actors/ovl_En_Tru/z_en_tru.c | 266 ++++++++++-------- src/overlays/actors/ovl_En_Tru/z_en_tru.h | 13 +- .../actors/ovl_En_Tru_Mt/z_en_tru_mt.c | 113 ++++---- .../actors/ovl_En_Tru_Mt/z_en_tru_mt.h | 8 +- tools/disasm/functions.txt | 6 +- 8 files changed, 342 insertions(+), 292 deletions(-) diff --git a/assets/xml/objects/object_trt.xml b/assets/xml/objects/object_trt.xml index 826aa1ef0..9f024f9cb 100644 --- a/assets/xml/objects/object_trt.xml +++ b/assets/xml/objects/object_trt.xml @@ -51,10 +51,10 @@ - + - + -> diff --git a/assets/xml/objects/object_tru.xml b/assets/xml/objects/object_tru.xml index 138723ceb..db35ec604 100644 --- a/assets/xml/objects/object_tru.xml +++ b/assets/xml/objects/object_tru.xml @@ -1,108 +1,117 @@  + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/overlays/actors/ovl_En_Jc_Mato/z_en_jc_mato.c b/src/overlays/actors/ovl_En_Jc_Mato/z_en_jc_mato.c index 99c17772c..ced184e68 100644 --- a/src/overlays/actors/ovl_En_Jc_Mato/z_en_jc_mato.c +++ b/src/overlays/actors/ovl_En_Jc_Mato/z_en_jc_mato.c @@ -145,15 +145,14 @@ void EnJcMato_Update(Actor* thisx, PlayState* play) { } } -static Vec3f movement = { 0.0f, -2500.0f, 0.0f }; - void EnJcMato_Draw(Actor* thisx, PlayState* play) { + static Vec3f sOffset = { 0.0f, -2500.0f, 0.0f }; EnJcMato* this = THIS; OPEN_DISPS(play->state.gfxCtx); func_8012C28C(play->state.gfxCtx); gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); - gSPDisplayList(POLY_OPA_DISP++, object_tru_DL_000390); - Matrix_MultVec3f(&movement, &this->pos); + gSPDisplayList(POLY_OPA_DISP++, gKoumeTargetDL); + Matrix_MultVec3f(&sOffset, &this->pos); CLOSE_DISPS(play->state.gfxCtx); } diff --git a/src/overlays/actors/ovl_En_Tru/z_en_tru.c b/src/overlays/actors/ovl_En_Tru/z_en_tru.c index 42cbdc22a..c54d924df 100644 --- a/src/overlays/actors/ovl_En_Tru/z_en_tru.c +++ b/src/overlays/actors/ovl_En_Tru/z_en_tru.c @@ -5,7 +5,7 @@ */ #include "z_en_tru.h" -#include "objects/object_tru/object_tru.h" +#include "objects/gameplay_keep/gameplay_keep.h" #define FLAGS (ACTOR_FLAG_1 | ACTOR_FLAG_8 | ACTOR_FLAG_10 | ACTOR_FLAG_20) @@ -24,6 +24,26 @@ s32 func_80A87DC0(Actor* thisx, PlayState* play); void func_80A87FD0(EnTru* this, PlayState* play); void func_80A881E0(EnTru* this, PlayState* play); +typedef enum { + /* 0x00 */ KOUME_ANIM_INJURED_LYING_DOWN, + /* 0x01 */ KOUME_ANIM_INJURED_LYING_DOWN_MORPH, + /* 0x02 */ KOUME_ANIM_TRY_GET_UP, + /* 0x03 */ KOUME_ANIM_INJURED_RAISE_HEAD, + /* 0x04 */ KOUME_ANIM_INJURED_TALK, + /* 0x05 */ KOUME_ANIM_INJURED_HEAD_UP, + /* 0x06 */ KOUME_ANIM_INJURED_HEAD_UP_MORPH, + /* 0x07 */ KOUME_ANIM_TAKE, + /* 0x08 */ KOUME_ANIM_SHAKE, // Unused + /* 0x09 */ KOUME_ANIM_DRINK, + /* 0x0A */ KOUME_ANIM_FINISHED_DRINKING, + /* 0x0B */ KOUME_ANIM_HEALED, + /* 0x0C */ KOUME_ANIM_HOVER1, + /* 0x0D */ KOUME_ANIM_TAKE_OFF, + /* 0x0E */ KOUME_ANIM_FLY, + /* 0x0F */ KOUME_ANIM_HOVER2, + /* 0x10 */ KOUME_ANIM_MAX +} KoumeAnimation; + static UNK_TYPE D_80A88910[] = { 0x0E08520C, 0x16100000, @@ -69,7 +89,6 @@ const ActorInit En_Tru_InitVars = { }; #include "overlays/ovl_En_Tru/ovl_En_Tru.c" -#include "objects/gameplay_keep/gameplay_keep.h" static Vec3f D_80A8B250 = { 0.0f, 0.02f, 0.0f }; @@ -107,22 +126,22 @@ static ColliderSphereInit sSphereInit = { static CollisionCheckInfoInit2 sColChkInfoInit = { 1, 20, 0, 0, MASS_IMMOVABLE }; static AnimationInfoS sAnimationInfo[] = { - { &object_tru_Anim_00F9A0, 1.0f, 0, -1, ANIMMODE_LOOP, 0 }, - { &object_tru_Anim_00F9A0, 1.0f, 0, -1, ANIMMODE_LOOP, -4 }, - { &object_tru_Anim_0108AC, 1.0f, 0, -1, ANIMMODE_ONCE, -4 }, - { &object_tru_Anim_009348, 1.0f, 0, -1, ANIMMODE_ONCE, 0 }, - { &object_tru_Anim_00EEDC, 1.0f, 0, -1, ANIMMODE_LOOP, -4 }, - { &object_tru_Anim_015CA0, 1.0f, 0, -1, ANIMMODE_LOOP, 0 }, - { &object_tru_Anim_015CA0, 1.0f, 0, -1, ANIMMODE_LOOP, -4 }, - { &object_tru_Anim_014728, 1.0f, 0, -1, ANIMMODE_ONCE, 0 }, - { &object_tru_Anim_01B5C4, 1.0f, 0, -1, ANIMMODE_ONCE, 0 }, - { &object_tru_Anim_007FA0, 1.0f, 0, -1, ANIMMODE_ONCE, -4 }, - { &object_tru_Anim_016B4C, 1.0f, 0, -1, ANIMMODE_LOOP, -4 }, - { &object_tru_Anim_011F88, 1.0f, 0, -1, ANIMMODE_ONCE, -4 }, - { &object_tru_Anim_00446C, 1.0f, 0, -1, ANIMMODE_LOOP, 0 }, - { &object_tru_Anim_003698, 1.0f, 0, -1, ANIMMODE_ONCE, -4 }, - { &object_tru_Anim_002BD8, 1.0f, 0, -1, ANIMMODE_LOOP, 0 }, - { &object_tru_Anim_00446C, 1.0f, 0, -1, ANIMMODE_LOOP, 0 }, + { &gKoumeInjuredLyingDownAnim, 1.0f, 0, -1, ANIMMODE_LOOP, 0 }, + { &gKoumeInjuredLyingDownAnim, 1.0f, 0, -1, ANIMMODE_LOOP, -4 }, + { &gKoumeTryGetUpAnim, 1.0f, 0, -1, ANIMMODE_ONCE, -4 }, + { &gKoumeInjuredRaiseHeadAnim, 1.0f, 0, -1, ANIMMODE_ONCE, 0 }, + { &gKoumeInjuredTalkAnim, 1.0f, 0, -1, ANIMMODE_LOOP, -4 }, + { &gKoumeInjuredHeadUpAnim, 1.0f, 0, -1, ANIMMODE_LOOP, 0 }, + { &gKoumeInjuredHeadUpAnim, 1.0f, 0, -1, ANIMMODE_LOOP, -4 }, + { &gKoumeTakeAnim, 1.0f, 0, -1, ANIMMODE_ONCE, 0 }, + { &gKoumeShakeAnim, 1.0f, 0, -1, ANIMMODE_ONCE, 0 }, + { &gKoumeDrinkAnim, 1.0f, 0, -1, ANIMMODE_ONCE, -4 }, + { &gKoumeFinishedDrinkingAnim, 1.0f, 0, -1, ANIMMODE_LOOP, -4 }, + { &gKoumeHealedAnim, 1.0f, 0, -1, ANIMMODE_ONCE, -4 }, + { &gKoumeHoverAnim, 1.0f, 0, -1, ANIMMODE_LOOP, 0 }, + { &gKoumeTakeOffAnim, 1.0f, 0, -1, ANIMMODE_ONCE, -4 }, + { &gKoumeFlyAnim, 1.0f, 0, -1, ANIMMODE_LOOP, 0 }, + { &gKoumeHoverAnim, 1.0f, 0, -1, ANIMMODE_LOOP, 0 }, }; static Vec3f D_80A8B3D8 = { 0.0f, 24.0f, 16.0f }; @@ -275,12 +294,12 @@ void func_80A85F84(EnTruUnkStruct* arg0, PlayState* play) { for (i = 0; i < 30; i++, arg0++) { f32 alpha; - s32 idx; + s32 index; if ((arg0->unk_00 == 3) || (arg0->unk_00 == 4) || (arg0->unk_00 == 5)) { if (!flag) { - POLY_XLU_DISP = Gfx_CallSetupDL(POLY_XLU_DISP, sizeof(Gfx) * 0); - gSPDisplayList(POLY_XLU_DISP++, object_tru_DL_01A820); + POLY_XLU_DISP = Gfx_CallSetupDL(POLY_XLU_DISP, 0); + gSPDisplayList(POLY_XLU_DISP++, gKoumeDustMaterialDL); flag = true; } @@ -306,9 +325,9 @@ void func_80A85F84(EnTruUnkStruct* arg0, PlayState* play) { Matrix_ReplaceRotation(&play->billboardMtxF); gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); - idx = ((f32)arg0->unk_02 / arg0->unk_01) * 8.0f; - gSPSegment(POLY_XLU_DISP++, 0x08, Lib_SegmentedToVirtual(sDustTextures[idx])); - gSPDisplayList(POLY_XLU_DISP++, object_tru_DL_01A830); + index = ((f32)arg0->unk_02 / arg0->unk_01) * 8.0f; + gSPSegment(POLY_XLU_DISP++, 0x08, Lib_SegmentedToVirtual(sDustTextures[index])); + gSPDisplayList(POLY_XLU_DISP++, gKoumeDustModelDL); Matrix_Pop(); } @@ -414,21 +433,21 @@ s32 func_80A86770(EnTru* this) { return false; } -void func_80A868F8(EnTru* this) { - this->skelAnime.playSpeed = this->unk_358; +void EnTru_UpdateSkelAnime(EnTru* this) { + this->skelAnime.playSpeed = this->playSpeed; SkelAnime_Update(&this->skelAnime); } -s32 func_80A86924(EnTru* this, s32 arg1) { - s32 ret = false; +s32 EnTru_ChangeAnim(EnTru* this, s32 animIndex) { + s32 didChange = false; - if (arg1 != this->unk_37C) { - this->unk_37C = arg1; - ret = SubS_ChangeAnimationByInfoS(&this->skelAnime, sAnimationInfo, arg1); - this->unk_358 = this->skelAnime.playSpeed; + if (animIndex != this->animIndex) { + this->animIndex = animIndex; + didChange = SubS_ChangeAnimationByInfoS(&this->skelAnime, sAnimationInfo, animIndex); + this->playSpeed = this->skelAnime.playSpeed; } - return ret; + return didChange; } void func_80A8697C(EnTru* this, PlayState* play) { @@ -497,7 +516,7 @@ s32 func_80A86BAC(EnTru* this, PlayState* play) { Matrix_RotateXS(-0x4000, MTXMODE_APPLY); gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); - gSPDisplayList(POLY_OPA_DISP++, object_tru_DL_0020C8); + gSPDisplayList(POLY_OPA_DISP++, gKoumePotionDL); Matrix_Pop(); @@ -515,7 +534,7 @@ s32 func_80A86BAC(EnTru* this, PlayState* play) { Matrix_RotateXS(-0x4000, MTXMODE_APPLY); gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); - gSPDisplayList(POLY_XLU_DISP++, object_tru_DL_001F90); + gSPDisplayList(POLY_XLU_DISP++, gKoumeBottleDL); Matrix_Pop(); @@ -527,104 +546,105 @@ s32 func_80A86BAC(EnTru* this, PlayState* play) { s32 func_80A86DB8(EnTru* this) { if (this->unk_34E & 0x80) { - this->unk_36E = 2; + this->eyeTexIndex = 2; return false; } - switch (this->unk_37C) { - case 0: - case 1: - if (DECR(this->unk_36C) == 0) { + switch (this->animIndex) { + case KOUME_ANIM_INJURED_LYING_DOWN: + case KOUME_ANIM_INJURED_LYING_DOWN_MORPH: + if (DECR(this->blinkTimer) == 0) { s16 rand = Rand_S16Offset(40, 20); - if (this->unk_36E == 2) { - this->unk_36C = 8; + + if (this->eyeTexIndex == 2) { + this->blinkTimer = 8; } else { - this->unk_36C = rand; + this->blinkTimer = rand; } - if (this->unk_36E == 2) { - this->unk_36E = 1; + if (this->eyeTexIndex == 2) { + this->eyeTexIndex = 1; } else { - this->unk_36E = 2; + this->eyeTexIndex = 2; } } return false; - case 2: + case KOUME_ANIM_TRY_GET_UP: if (Animation_OnFrame(&this->skelAnime, 10.0f)) { - this->unk_36E = 1; + this->eyeTexIndex = 1; } else if ((this->skelAnime.curFrame >= 11.0f) && (this->skelAnime.curFrame <= 32.0f)) { - this->unk_36E = 0; + this->eyeTexIndex = 0; } else { - this->unk_36E = 2; + this->eyeTexIndex = 2; } return false; - case 3: + case KOUME_ANIM_INJURED_RAISE_HEAD: if (Animation_OnFrame(&this->skelAnime, 31.0f)) { - this->unk_36E = 1; + this->eyeTexIndex = 1; } else if (this->skelAnime.curFrame <= 32.0f) { - this->unk_36E = 2; + this->eyeTexIndex = 2; } else { - this->unk_36E = 0; + this->eyeTexIndex = 0; } return false; - case 9: + case KOUME_ANIM_DRINK: if (Animation_OnFrame(&this->skelAnime, 57.0f)) { - this->unk_36C = 0; - this->unk_36E = 0; + this->blinkTimer = 0; + this->eyeTexIndex = 0; } if (this->skelAnime.curFrame < 57.0f) { - if (DECR(this->unk_36C) == 0) { - this->unk_36C = Rand_S16Offset(8, 8); - this->unk_36E = 2; + if (DECR(this->blinkTimer) == 0) { + this->blinkTimer = Rand_S16Offset(8, 8); + this->eyeTexIndex = 2; } else { - this->unk_36E = 1; + this->eyeTexIndex = 1; } - } else if (DECR(this->unk_36C) == 0) { - this->unk_36E++; - if (this->unk_36E >= 4) { - this->unk_36C = Rand_S16Offset(20, 10); - this->unk_36E = 0; + } else if (DECR(this->blinkTimer) == 0) { + this->eyeTexIndex++; + if (this->eyeTexIndex >= 4) { + this->blinkTimer = Rand_S16Offset(20, 10); + this->eyeTexIndex = 0; } } return false; - case 10: - this->unk_36E = 0; + case KOUME_ANIM_FINISHED_DRINKING: + this->eyeTexIndex = 0; return false; - case 11: + case KOUME_ANIM_HEALED: if (Animation_OnFrame(&this->skelAnime, 19.0f) || Animation_OnFrame(&this->skelAnime, 45.0f)) { - this->unk_36E = 1; + this->eyeTexIndex = 1; } else if ((this->skelAnime.curFrame >= 19.0f) && (this->skelAnime.curFrame <= 45.0f)) { - this->unk_36E = 2; + this->eyeTexIndex = 2; } else { - this->unk_36E = 3; + this->eyeTexIndex = 3; } return false; - case 13: + case KOUME_ANIM_TAKE_OFF: if (Animation_OnFrame(&this->skelAnime, 19.0f)) { - this->unk_36E = 1; + this->eyeTexIndex = 1; } else if (this->skelAnime.curFrame >= 19.0f) { - this->unk_36E = 2; + this->eyeTexIndex = 2; } else { - this->unk_36E = 0; + this->eyeTexIndex = 0; } return false; default: - if (DECR(this->unk_36C) == 0) { - if ((this->unk_36E != 2) || !(this->unk_34E & 0x80)) { - this->unk_36E++; + if (DECR(this->blinkTimer) == 0) { + if ((this->eyeTexIndex != 2) || !(this->unk_34E & 0x80)) { + this->eyeTexIndex++; } - if (this->unk_36E >= 4) { - this->unk_36C = Rand_S16Offset(30, 30); - this->unk_36E = 0; + if (this->eyeTexIndex >= 4) { + this->blinkTimer = Rand_S16Offset(30, 30); + this->eyeTexIndex = 0; } } return false; @@ -772,11 +792,12 @@ s32 func_80A875AC(Actor* thisx, PlayState* play) { break; case 2: - if ((this->unk_37C != 5) && (this->unk_37C != 6)) { - func_80A86924(this, 3); + if ((this->animIndex != KOUME_ANIM_INJURED_HEAD_UP) && + (this->animIndex != KOUME_ANIM_INJURED_HEAD_UP_MORPH)) { + EnTru_ChangeAnim(this, KOUME_ANIM_INJURED_RAISE_HEAD); this->unk_364++; } else { - func_80A86924(this, 4); + EnTru_ChangeAnim(this, KOUME_ANIM_INJURED_TALK); ret = true; } break; @@ -784,7 +805,7 @@ s32 func_80A875AC(Actor* thisx, PlayState* play) { case 3: if (Animation_OnFrame(&this->skelAnime, this->skelAnime.endFrame)) { this->unk_364++; - func_80A86924(this, 4); + EnTru_ChangeAnim(this, KOUME_ANIM_INJURED_TALK); ret = true; } break; @@ -806,7 +827,7 @@ s32 func_80A875AC(Actor* thisx, PlayState* play) { s32 func_80A8777C(Actor* thisx, PlayState* play) { EnTru* this = THIS; s32 ret = 0; - s32 temp_v0; + s32 itemActionParam; switch (Message_GetState(&play->msgCtx)) { case TEXT_STATE_CHOICE: @@ -816,10 +837,10 @@ s32 func_80A8777C(Actor* thisx, PlayState* play) { } // Fallthrough case TEXT_STATE_16: - temp_v0 = func_80123810(play); - if ((temp_v0 == 35) || (temp_v0 == 36)) { + itemActionParam = func_80123810(play); + if ((itemActionParam == PLAYER_AP_BOTTLE_POTION_RED) || (itemActionParam == PLAYER_AP_BOTTLE_POTION_BLUE)) { this->unk_34E |= 8; - if (temp_v0 == 35) { + if (itemActionParam == PLAYER_AP_BOTTLE_POTION_RED) { this->unk_390 = 1; } else { this->unk_390 = 2; @@ -827,9 +848,9 @@ s32 func_80A8777C(Actor* thisx, PlayState* play) { this->unk_378 = func_80A87880; this->unk_364 = 0; ret = 1; - } else if (temp_v0 < 0) { + } else if (itemActionParam < PLAYER_AP_NONE) { ret = 3; - } else if (temp_v0 != 0) { + } else if (itemActionParam != PLAYER_AP_NONE) { ret = 2; } break; @@ -866,14 +887,14 @@ s32 func_80A87880(Actor* thisx, PlayState* play) { this->unk_34E &= ~0x8; this->actor.shape.rot.y = this->actor.yawTowardsPlayer; this->actor.world.rot.y = this->actor.yawTowardsPlayer; - func_80A86924(this, 7); + EnTru_ChangeAnim(this, KOUME_ANIM_TAKE); this->unk_364++; break; case 3: if (Animation_OnFrame(&this->skelAnime, this->skelAnime.endFrame)) { this->unk_364++; - func_80A86924(this, 9); + EnTru_ChangeAnim(this, KOUME_ANIM_DRINK); this->actor.world.rot.y += 0x4000; } else if (Animation_OnFrame(&this->skelAnime, 12.0f) && !(this->unk_34E & 0x800)) { this->unk_34E |= 0x400; @@ -885,7 +906,7 @@ s32 func_80A87880(Actor* thisx, PlayState* play) { case 4: if (Animation_OnFrame(&this->skelAnime, this->skelAnime.endFrame)) { this->unk_364++; - func_80A86924(this, 10); + EnTru_ChangeAnim(this, KOUME_ANIM_FINISHED_DRINKING); ret = true; } else if (Animation_OnFrame(&this->skelAnime, 18.0f) || Animation_OnFrame(&this->skelAnime, 32.0f) || Animation_OnFrame(&this->skelAnime, 52.0f)) { @@ -923,7 +944,7 @@ s32 func_80A87B48(Actor* thisx, PlayState* play) { switch (this->unk_364) { case 0: - func_80A86924(this, 11); + EnTru_ChangeAnim(this, KOUME_ANIM_HEALED); this->unk_364++; break; @@ -954,7 +975,7 @@ s32 func_80A87B48(Actor* thisx, PlayState* play) { if (player->exchangeItemId != 0) { player->exchangeItemId = 0; } - func_80A86924(this, 12); + EnTru_ChangeAnim(this, KOUME_ANIM_HOVER1); } } else { MREG(64) = 0; @@ -997,7 +1018,7 @@ s32 func_80A87DC0(Actor* thisx, PlayState* play) { AudioSfx_StopById(NA_SE_EN_KOUME_MAGIC); Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_KOUME_AWAY); Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_KOUME_LAUGH); - func_80A86924(this, 13); + EnTru_ChangeAnim(this, KOUME_ANIM_TAKE_OFF); this->skelAnime.baseTransl.y = 0; this->skelAnime.moveFlags = 2; this->unk_34E &= ~0x8; @@ -1010,7 +1031,7 @@ s32 func_80A87DC0(Actor* thisx, PlayState* play) { AnimationContext_SetMoveActor(play, &this->actor, &this->skelAnime, 1.0f); break; } else { - func_80A86924(this, 14); + EnTru_ChangeAnim(this, KOUME_ANIM_FLY); this->actor.shape.rot.y = this->actor.world.rot.y; this->unk_362 = 20; this->unk_364++; @@ -1049,13 +1070,14 @@ void func_80A87FD0(EnTru* this, PlayState* play) { SubS_UpdateFlags(&this->unk_34E, 0, 7); } - if ((this->unk_37C == 2) && Animation_OnFrame(&this->skelAnime, this->skelAnime.endFrame)) { + if ((this->animIndex == KOUME_ANIM_TRY_GET_UP) && + Animation_OnFrame(&this->skelAnime, this->skelAnime.endFrame)) { this->unk_362 = Rand_S16Offset(40, 20); - func_80A86924(this, 1); + EnTru_ChangeAnim(this, KOUME_ANIM_INJURED_LYING_DOWN_MORPH); func_80A86460(this); - } else if (this->unk_37C != 2) { + } else if (this->animIndex != KOUME_ANIM_TRY_GET_UP) { if (DECR(this->unk_362) == 0) { - func_80A86924(this, 2); + EnTru_ChangeAnim(this, KOUME_ANIM_TRY_GET_UP); } } } else if (!(gSaveContext.save.weekEventReg[16] & 0x10) && (fabsf(this->actor.playerHeightRel) < 10.0f) && @@ -1084,12 +1106,12 @@ void func_80A881E0(EnTru* this, PlayState* play) { } if (!(this->unk_34E & 0x40) && !(gSaveContext.save.weekEventReg[16] & 0x10)) { - func_80A86924(this, 0); + EnTru_ChangeAnim(this, KOUME_ANIM_INJURED_LYING_DOWN); } else if (this->unk_34E & 0x80) { - func_80A86924(this, 0); + EnTru_ChangeAnim(this, KOUME_ANIM_INJURED_LYING_DOWN); func_80A86460(this); } else if (gSaveContext.save.weekEventReg[16] & 0x10) { - func_80A86924(this, 6); + EnTru_ChangeAnim(this, KOUME_ANIM_INJURED_HEAD_UP_MORPH); } SubS_UpdateFlags(&this->unk_34E, 0, 7); @@ -1111,11 +1133,11 @@ void EnTru_Init(Actor* thisx, PlayState* play) { } ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, 24.0f); - SkelAnime_InitFlex(play, &this->skelAnime, &object_tru_Skel_01AA60, NULL, this->jointTable, this->morphTable, 27); + SkelAnime_InitFlex(play, &this->skelAnime, &gKoumeSkel, NULL, this->jointTable, this->morphTable, KOUME_LIMB_MAX); Collider_InitAndSetSphere(play, &this->collider, &this->actor, &sSphereInit); CollisionCheck_SetInfo2(&this->actor.colChkInfo, DamageTable_Get(0x16), &sColChkInfoInit); - this->unk_37C = -1; - func_80A86924(this, 0); + this->animIndex = -1; + EnTru_ChangeAnim(this, KOUME_ANIM_INJURED_LYING_DOWN); this->path = SubS_GetDayDependentPath(play, ENTRU_GET_PATH(&this->actor), 255, &this->unk_384); if (this->path != NULL) { this->unk_384 = 1; @@ -1126,7 +1148,7 @@ void EnTru_Init(Actor* thisx, PlayState* play) { this->unk_34E = 0; if (gSaveContext.save.weekEventReg[16] & 0x10) { - func_80A86924(this, 5); + EnTru_ChangeAnim(this, KOUME_ANIM_INJURED_HEAD_UP); } else { this->unk_388 = PLAYER_AP_NONE; } @@ -1149,7 +1171,7 @@ void EnTru_Update(Actor* thisx, PlayState* play) { this->actionFunc(this, play); - func_80A868F8(this); + EnTru_UpdateSkelAnime(this); func_80A86B0C(this, play); func_80A86DB8(this); @@ -1165,7 +1187,7 @@ s32 EnTru_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* p s32 pad; EnTru* this = THIS; - if (limbIndex == 21) { + if (limbIndex == KOUME_LIMB_HEAD) { Matrix_MultZero(&this->actor.focus.pos); Math_Vec3f_ToVec3s(&this->collider.dim.worldSphere.center, &this->actor.focus.pos); this->actor.focus.pos.x = (this->actor.focus.pos.x / 10.0f) * 10.0f; @@ -1175,7 +1197,7 @@ s32 EnTru_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* p Matrix_MultVec3f(&D_80A8B3FC, &this->unk_1F8); } - if (!(this->unk_34E & 0x200) && (limbIndex == 14)) { + if (!(this->unk_34E & 0x200) && (limbIndex == KOUME_LIMB_BROOM)) { *dList = NULL; } @@ -1185,7 +1207,7 @@ s32 EnTru_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* p void EnTru_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, Actor* thisx) { EnTru* this = THIS; - if (limbIndex == 19) { + if (limbIndex == KOUME_LIMB_RIGHT_HAND) { func_80A86BAC(this, play); } } @@ -1212,7 +1234,7 @@ void EnTru_TransformLimbDraw(PlayState* play, s32 limbIndex, Actor* thisx) { overrideRot = false; } - if (limbIndex == 21) { + if (limbIndex == KOUME_LIMB_HEAD) { SubS_UpdateLimb(this->unk_366, this->unk_368 + this->actor.shape.rot.y, &this->unk_1EC, &this->unk_204, stepRot, overrideRot); Matrix_Pop(); @@ -1232,11 +1254,11 @@ void EnTru_TransformLimbDraw(PlayState* play, s32 limbIndex, Actor* thisx) { } void EnTru_Draw(Actor* thisx, PlayState* play) { - static TexturePtr D_80A8B408[] = { - object_tru_Tex_018FA0, - object_tru_Tex_0197A0, - object_tru_Tex_019FA0, - object_tru_Tex_0197A0, + static TexturePtr sEyeTextures[] = { + gKoumeEyeOpenTex, + gKoumeEyeHalfTex, + gKoumeEyeClosedTex, + gKoumeEyeHalfTex, }; s32 pad; EnTru* this = THIS; @@ -1245,8 +1267,8 @@ void EnTru_Draw(Actor* thisx, PlayState* play) { func_8012C28C(play->state.gfxCtx); - gSPSegment(POLY_OPA_DISP++, 0x08, Lib_SegmentedToVirtual(D_80A8B408[this->unk_36E])); - gSPSegment(POLY_OPA_DISP++, 0x09, Lib_SegmentedToVirtual(D_80A8B408[this->unk_36E])); + gSPSegment(POLY_OPA_DISP++, 0x08, Lib_SegmentedToVirtual(sEyeTextures[this->eyeTexIndex])); + gSPSegment(POLY_OPA_DISP++, 0x09, Lib_SegmentedToVirtual(sEyeTextures[this->eyeTexIndex])); SkelAnime_DrawTransformFlexOpa(play, this->skelAnime.skeleton, this->skelAnime.jointTable, this->skelAnime.dListCount, EnTru_OverrideLimbDraw, EnTru_PostLimbDraw, diff --git a/src/overlays/actors/ovl_En_Tru/z_en_tru.h b/src/overlays/actors/ovl_En_Tru/z_en_tru.h index 7e1c23380..711d5aeb6 100644 --- a/src/overlays/actors/ovl_En_Tru/z_en_tru.h +++ b/src/overlays/actors/ovl_En_Tru/z_en_tru.h @@ -2,6 +2,7 @@ #define Z_EN_TRU_H #include "global.h" +#include "objects/object_tru/object_tru.h" struct EnTru; @@ -31,12 +32,12 @@ typedef struct EnTru { /* 0x1EC */ Vec3f unk_1EC; /* 0x1F8 */ Vec3f unk_1F8; /* 0x204 */ Vec3s unk_204; - /* 0x20A */ Vec3s jointTable[27]; - /* 0x2AC */ Vec3s morphTable[27]; + /* 0x20A */ Vec3s jointTable[KOUME_LIMB_MAX]; + /* 0x2AC */ Vec3s morphTable[KOUME_LIMB_MAX]; /* 0x34E */ u16 unk_34E; /* 0x350 */ UNK_TYPE1 unk350[0x4]; /* 0x354 */ s32* unk_354; - /* 0x358 */ f32 unk_358; + /* 0x358 */ f32 playSpeed; /* 0x35C */ f32 unk_35C; /* 0x360 */ s16 unk_360; /* 0x362 */ s16 unk_362; @@ -44,13 +45,13 @@ typedef struct EnTru { /* 0x366 */ s16 unk_366; /* 0x368 */ s16 unk_368; /* 0x36A */ s16 unk_36A; - /* 0x36C */ s16 unk_36C; - /* 0x36E */ s16 unk_36E; + /* 0x36C */ s16 blinkTimer; + /* 0x36E */ s16 eyeTexIndex; /* 0x370 */ s16 unk_370; /* 0x372 */ s16 unk_372; /* 0x374 */ s16 unk_374; /* 0x378 */ EnTruUnkFunc unk_378; - /* 0x37C */ s32 unk_37C; + /* 0x37C */ s32 animIndex; /* 0x380 */ UNK_TYPE1 unk380[0x4]; /* 0x384 */ s32 unk_384; /* 0x388 */ s32 unk_388; diff --git a/src/overlays/actors/ovl_En_Tru_Mt/z_en_tru_mt.c b/src/overlays/actors/ovl_En_Tru_Mt/z_en_tru_mt.c index ac772a940..69725414a 100644 --- a/src/overlays/actors/ovl_En_Tru_Mt/z_en_tru_mt.c +++ b/src/overlays/actors/ovl_En_Tru_Mt/z_en_tru_mt.c @@ -20,6 +20,26 @@ void func_80B76A64(EnTruMt* this, PlayState* play); void func_80B76BB8(EnTruMt* this, PlayState* play); void func_80B76C38(EnTruMt* this, PlayState* play); +typedef enum { + /* 0x00 */ KOUME_MT_ANIM_INJURED_LYING_DOWN, + /* 0x01 */ KOUME_MT_ANIM_INJURED_LYING_DOWN_MORPH, + /* 0x02 */ KOUME_MT_ANIM_TRY_GET_UP, + /* 0x03 */ KOUME_MT_ANIM_INJURED_RAISE_HEAD, + /* 0x04 */ KOUME_MT_ANIM_INJURED_TALK, + /* 0x05 */ KOUME_MT_ANIM_INJURED_HEAD_UP, + /* 0x06 */ KOUME_MT_ANIM_INJURED_HEAD_UP_MORPH, + /* 0x07 */ KOUME_MT_ANIM_TAKE, + /* 0x08 */ KOUME_MT_ANIM_SHAKE, // Unused + /* 0x09 */ KOUME_MT_ANIM_DRINK, + /* 0x0A */ KOUME_MT_ANIM_FINISHED_DRINKING, + /* 0x0B */ KOUME_MT_ANIM_HEALED, + /* 0x0C */ KOUME_MT_ANIM_HOVER1, + /* 0x0D */ KOUME_MT_ANIM_TAKE_OFF, + /* 0x0E */ KOUME_MT_ANIM_FLY, + /* 0x0F */ KOUME_MT_ANIM_HOVER2, + /* 0x10 */ KOUME_MT_ANIM_MAX +} KoumeMtAnimation; + const ActorInit En_Tru_Mt_InitVars = { ACTOR_EN_TRU_MT, ACTORCAT_NPC, @@ -88,57 +108,57 @@ static DamageTable sDamageTable = { }; static AnimationInfoS sAnimationInfo[] = { - { &object_tru_Anim_00F9A0, 1.0f, 0, -1, ANIMMODE_LOOP, 0 }, - { &object_tru_Anim_00F9A0, 1.0f, 0, -1, ANIMMODE_LOOP, -4 }, - { &object_tru_Anim_0108AC, 1.0f, 0, -1, ANIMMODE_ONCE, -4 }, - { &object_tru_Anim_009348, 1.0f, 0, -1, ANIMMODE_ONCE, -4 }, - { &object_tru_Anim_00EEDC, 1.0f, 0, -1, ANIMMODE_LOOP, -4 }, - { &object_tru_Anim_015CA0, 1.0f, 0, -1, ANIMMODE_LOOP, 0 }, - { &object_tru_Anim_015CA0, 1.0f, 0, -1, ANIMMODE_LOOP, -4 }, - { &object_tru_Anim_014728, 1.0f, 0, -1, ANIMMODE_ONCE, 0 }, - { &object_tru_Anim_01B5C4, 1.0f, 0, -1, ANIMMODE_ONCE, 0 }, - { &object_tru_Anim_007FA0, 1.0f, 0, -1, ANIMMODE_ONCE, -4 }, - { &object_tru_Anim_016B4C, 1.0f, 0, -1, ANIMMODE_LOOP, -4 }, - { &object_tru_Anim_011F88, 1.0f, 0, -1, ANIMMODE_ONCE, -4 }, - { &object_tru_Anim_00446C, 1.0f, 0, -1, ANIMMODE_LOOP, 0 }, - { &object_tru_Anim_003698, 1.0f, 0, -1, ANIMMODE_ONCE, -4 }, - { &object_tru_Anim_002BD8, 1.0f, 0, -1, ANIMMODE_LOOP, 0 }, - { &object_tru_Anim_00446C, 1.0f, 0, -1, ANIMMODE_LOOP, 0 }, + { &gKoumeInjuredLyingDownAnim, 1.0f, 0, -1, ANIMMODE_LOOP, 0 }, + { &gKoumeInjuredLyingDownAnim, 1.0f, 0, -1, ANIMMODE_LOOP, -4 }, + { &gKoumeTryGetUpAnim, 1.0f, 0, -1, ANIMMODE_ONCE, -4 }, + { &gKoumeInjuredRaiseHeadAnim, 1.0f, 0, -1, ANIMMODE_ONCE, -4 }, + { &gKoumeInjuredTalkAnim, 1.0f, 0, -1, ANIMMODE_LOOP, -4 }, + { &gKoumeInjuredHeadUpAnim, 1.0f, 0, -1, ANIMMODE_LOOP, 0 }, + { &gKoumeInjuredHeadUpAnim, 1.0f, 0, -1, ANIMMODE_LOOP, -4 }, + { &gKoumeTakeAnim, 1.0f, 0, -1, ANIMMODE_ONCE, 0 }, + { &gKoumeShakeAnim, 1.0f, 0, -1, ANIMMODE_ONCE, 0 }, + { &gKoumeDrinkAnim, 1.0f, 0, -1, ANIMMODE_ONCE, -4 }, + { &gKoumeFinishedDrinkingAnim, 1.0f, 0, -1, ANIMMODE_LOOP, -4 }, + { &gKoumeHealedAnim, 1.0f, 0, -1, ANIMMODE_ONCE, -4 }, + { &gKoumeHoverAnim, 1.0f, 0, -1, ANIMMODE_LOOP, 0 }, + { &gKoumeTakeOffAnim, 1.0f, 0, -1, ANIMMODE_ONCE, -4 }, + { &gKoumeFlyAnim, 1.0f, 0, -1, ANIMMODE_LOOP, 0 }, + { &gKoumeHoverAnim, 1.0f, 0, -1, ANIMMODE_LOOP, 0 }, }; Vec3f D_80B7765C = { 3000.0f, -800.0f, 0.0f }; Vec3f D_80B77668 = { 0.0f, 0.0f, -3000.0f }; -s32 func_80B76030(SkelAnime* skelAnime, s16 arg1) { +s32 EnTruMt_ChangeAnim(SkelAnime* skelAnime, s16 animIndex) { s16 endFrame; s16 startFrame; - s32 ret = false; + s32 didChange = false; - if ((arg1 >= 0) && (arg1 < ARRAY_COUNT(sAnimationInfo))) { - endFrame = sAnimationInfo[arg1].frameCount; + if ((animIndex >= KOUME_MT_ANIM_INJURED_LYING_DOWN) && (animIndex < KOUME_MT_ANIM_MAX)) { + endFrame = sAnimationInfo[animIndex].frameCount; if (endFrame < 0) { - endFrame = Animation_GetLastFrame(sAnimationInfo[arg1].animation); + endFrame = Animation_GetLastFrame(sAnimationInfo[animIndex].animation); } - startFrame = sAnimationInfo[arg1].startFrame; + startFrame = sAnimationInfo[animIndex].startFrame; if (startFrame < 0) { - startFrame = Animation_GetLastFrame(sAnimationInfo[arg1].animation); + startFrame = Animation_GetLastFrame(sAnimationInfo[animIndex].animation); } - Animation_Change(skelAnime, sAnimationInfo[arg1].animation, sAnimationInfo[arg1].playSpeed, startFrame, - endFrame, sAnimationInfo[arg1].mode, sAnimationInfo[arg1].morphFrames); - ret = true; + Animation_Change(skelAnime, sAnimationInfo[animIndex].animation, sAnimationInfo[animIndex].playSpeed, + startFrame, endFrame, sAnimationInfo[animIndex].mode, sAnimationInfo[animIndex].morphFrames); + didChange = true; } - return ret; + return didChange; } void func_80B76110(EnTruMt* this) { - if (DECR(this->unk_34E) == 0) { - this->unk_34C++; - if (this->unk_34C >= 3) { - this->unk_34E = Rand_S16Offset(30, 30); - this->unk_34C = 0; + if (DECR(this->blinkTimer) == 0) { + this->eyeTexIndex++; + if (this->eyeTexIndex >= 3) { + this->blinkTimer = Rand_S16Offset(30, 30); + this->eyeTexIndex = 0; } } } @@ -404,8 +424,7 @@ void EnTruMt_Init(Actor* thisx, PlayState* play) { } ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, 24.0f); - SkelAnime_InitFlex(play, &this->skelAnime, &object_tru_Skel_01AA60, NULL, this->jointTable, this->morphTable, - OBJECT_TRU_LIMB_MAX); + SkelAnime_InitFlex(play, &this->skelAnime, &gKoumeSkel, NULL, this->jointTable, this->morphTable, KOUME_LIMB_MAX); Collider_InitSphere(play, &this->collider); Collider_SetSphere(play, &this->collider, &this->actor, &sSphereInit); @@ -421,7 +440,7 @@ void EnTruMt_Init(Actor* thisx, PlayState* play) { this->unk_328 = 0; this->actor.room = -1; this->path = SubS_GetPathByIndex(play, ENTRUMT_GET_FC00(&this->actor), 0x3F); - func_80B76030(&this->skelAnime, 14); + EnTruMt_ChangeAnim(&this->skelAnime, KOUME_MT_ANIM_FLY); this->actionFunc = func_80B76A64; } @@ -477,11 +496,11 @@ void func_80B76ED4(s16 arg0, s16 arg1, Vec3f* arg2, Vec3s* arg3, s32 arg4) { s32 EnTruMt_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, Actor* thisx) { EnTruMt* this = THIS; - if (limbIndex == OBJECT_TRU_LIMB_15) { + if (limbIndex == KOUME_LIMB_HEAD) { Matrix_MultVec3f(&gZeroVec3f, &this->unk_35C); } - if (limbIndex == OBJECT_TRU_LIMB_15) { + if (limbIndex == KOUME_LIMB_HEAD) { Matrix_MultVec3f(&D_80B7765C, &this->unk_350); } return false; @@ -493,7 +512,7 @@ void EnTruMt_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* ro MtxF* sp54; s32 phi_v0; - if (limbIndex == OBJECT_TRU_LIMB_15) { + if (limbIndex == KOUME_LIMB_HEAD) { if (this->unk_328 & 0x10) { phi_v0 = 1; } else { @@ -507,7 +526,7 @@ void EnTruMt_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* ro Matrix_RotateZS(this->unk_336.z, MTXMODE_APPLY); } - if (limbIndex == OBJECT_TRU_LIMB_0E) { + if (limbIndex == KOUME_LIMB_BROOM) { func_8012C28C(play->state.gfxCtx); OPEN_DISPS(play->state.gfxCtx); @@ -520,7 +539,7 @@ void EnTruMt_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* ro Matrix_Scale(0.008f, 0.008f, 0.008f, MTXMODE_APPLY); gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); - gSPDisplayList(POLY_OPA_DISP++, object_tru_DL_0004C8); + gSPDisplayList(POLY_OPA_DISP++, gKoumeChainDL); CLOSE_DISPS(play->state.gfxCtx); @@ -545,7 +564,7 @@ void EnTruMt_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* ro void EnTruMt_TransformLimbDraw(PlayState* play, s32 limbIndex, Actor* thisx) { EnTruMt* this = THIS; - if (limbIndex == OBJECT_TRU_LIMB_15) { + if (limbIndex == KOUME_LIMB_HEAD) { Matrix_Translate(this->unk_33C.x, this->unk_33C.y, this->unk_33C.z, MTXMODE_NEW); Matrix_Scale(this->actor.scale.x, this->actor.scale.y, this->actor.scale.z, MTXMODE_APPLY); Matrix_RotateYS(this->unk_336.y, MTXMODE_APPLY); @@ -556,18 +575,18 @@ void EnTruMt_TransformLimbDraw(PlayState* play, s32 limbIndex, Actor* thisx) { void EnTruMt_Draw(Actor* thisx, PlayState* play) { EnTruMt* this = THIS; - TexturePtr sp48[] = { - object_tru_Tex_018FA0, - object_tru_Tex_0197A0, - object_tru_Tex_019FA0, + TexturePtr eyeTextures[] = { + gKoumeEyeOpenTex, + gKoumeEyeHalfTex, + gKoumeEyeClosedTex, }; OPEN_DISPS(play->state.gfxCtx); func_8012C28C(play->state.gfxCtx); - gSPSegment(POLY_OPA_DISP++, 0x08, Lib_SegmentedToVirtual(sp48[this->unk_34C])); - gSPSegment(POLY_OPA_DISP++, 0x09, Lib_SegmentedToVirtual(sp48[this->unk_34C])); + gSPSegment(POLY_OPA_DISP++, 0x08, Lib_SegmentedToVirtual(eyeTextures[this->eyeTexIndex])); + gSPSegment(POLY_OPA_DISP++, 0x09, Lib_SegmentedToVirtual(eyeTextures[this->eyeTexIndex])); SkelAnime_DrawTransformFlexOpa(play, this->skelAnime.skeleton, this->skelAnime.jointTable, this->skelAnime.dListCount, EnTruMt_OverrideLimbDraw, EnTruMt_PostLimbDraw, diff --git a/src/overlays/actors/ovl_En_Tru_Mt/z_en_tru_mt.h b/src/overlays/actors/ovl_En_Tru_Mt/z_en_tru_mt.h index 670d0d728..54d58326e 100644 --- a/src/overlays/actors/ovl_En_Tru_Mt/z_en_tru_mt.h +++ b/src/overlays/actors/ovl_En_Tru_Mt/z_en_tru_mt.h @@ -16,16 +16,16 @@ typedef struct EnTruMt { /* 0x144 */ EnTruMtActionFunc actionFunc; /* 0x148 */ SkelAnime skelAnime; /* 0x18C */ ColliderSphere collider; - /* 0x1E4 */ Vec3s jointTable[OBJECT_TRU_LIMB_MAX]; - /* 0x286 */ Vec3s morphTable[OBJECT_TRU_LIMB_MAX]; + /* 0x1E4 */ Vec3s jointTable[KOUME_LIMB_MAX]; + /* 0x286 */ Vec3s morphTable[KOUME_LIMB_MAX]; /* 0x328 */ u16 unk_328; /* 0x32A */ UNK_TYPE1 unk32A[0xC]; /* 0x336 */ Vec3s unk_336; /* 0x33C */ Vec3f unk_33C; /* 0x348 */ s16 unk_348; /* 0x34A */ s16 unk_34A; - /* 0x34C */ s16 unk_34C; - /* 0x34E */ s16 unk_34E; + /* 0x34C */ s16 eyeTexIndex; + /* 0x34E */ s16 blinkTimer; /* 0x350 */ Vec3f unk_350; /* 0x35C */ Vec3f unk_35C; /* 0x368 */ Path* path; diff --git a/tools/disasm/functions.txt b/tools/disasm/functions.txt index 8a146996d..057170442 100644 --- a/tools/disasm/functions.txt +++ b/tools/disasm/functions.txt @@ -11226,8 +11226,8 @@ 0x80A86460:("func_80A86460",), 0x80A86674:("func_80A86674",), 0x80A86770:("func_80A86770",), - 0x80A868F8:("func_80A868F8",), - 0x80A86924:("func_80A86924",), + 0x80A868F8:("EnTru_UpdateSkelAnime",), + 0x80A86924:("EnTru_ChangeAnim",), 0x80A8697C:("func_80A8697C",), 0x80A869DC:("func_80A869DC",), 0x80A86B0C:("func_80A86B0C",), @@ -14437,7 +14437,7 @@ 0x80B75658:("EnJg_OverrideLimbDraw",), 0x80B75708:("EnJg_PostLimbDraw",), 0x80B757AC:("EnJg_Draw",), - 0x80B76030:("func_80B76030",), + 0x80B76030:("EnTruMt_ChangeAnim",), 0x80B76110:("func_80B76110",), 0x80B76188:("func_80B76188",), 0x80B761FC:("func_80B761FC",), From 3d5d39e74d8eca94be52657bacf017de4e9962c2 Mon Sep 17 00:00:00 2001 From: Tom Overton Date: Sun, 2 Oct 2022 09:16:30 -0700 Subject: [PATCH 07/10] Document leftover pause joint tables (#1104) * Document leftover pause joint tables * Grab the other two joint tables * Document the deku stick thing * Add @bug to comment --- assets/xml/objects/gameplay_keep.xml | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/assets/xml/objects/gameplay_keep.xml b/assets/xml/objects/gameplay_keep.xml index ee2bed429..121dcfe5e 100644 --- a/assets/xml/objects/gameplay_keep.xml +++ b/assets/xml/objects/gameplay_keep.xml @@ -39,7 +39,7 @@ - + @@ -69,8 +69,26 @@ - - + + + + + + + + + + + + + + + + + + + + @@ -766,6 +784,7 @@ + From fdfe2842d9daf023c8ccdc8621489a44de3c1786 Mon Sep 17 00:00:00 2001 From: Derek Hensley Date: Sun, 2 Oct 2022 10:10:31 -0700 Subject: [PATCH 08/10] Eff Srchball OK (#1092) * OK * Some docs and cleanup * flags -> params * Remove todo * Small cleanup * Description and dls * Format * bug tag * Update bug comment * Update src/overlays/effects/ovl_Effect_Ss_Solder_Srch_Ball/z_eff_ss_solder_srch_ball.c Co-authored-by: EllipticEllipsis * Format Co-authored-by: EllipticEllipsis --- assets/xml/objects/gameplay_keep.xml | 4 +- include/functions.h | 2 +- include/z64effect.h | 1 - spec | 3 +- src/code/z_effect_soft_sprite_old_init.c | 10 +-- .../actors/ovl_Demo_Kankyo/z_demo_kankyo.c | 4 +- .../actors/ovl_En_Encount2/z_en_encount2.c | 4 +- .../actors/ovl_En_Hanabi/z_en_hanabi.c | 4 +- .../actors/ovl_En_Look_Nuts/z_en_look_nuts.c | 8 +- .../actors/ovl_En_Suttari/z_en_suttari.c | 19 +++-- .../actors/ovl_En_Suttari/z_en_suttari.h | 2 +- .../z_eff_ss_solder_srch_ball.c | 80 +++++++++++++++++-- .../z_eff_ss_solder_srch_ball.h | 9 ++- 13 files changed, 111 insertions(+), 39 deletions(-) diff --git a/assets/xml/objects/gameplay_keep.xml b/assets/xml/objects/gameplay_keep.xml index 121dcfe5e..ca0aaeb3c 100644 --- a/assets/xml/objects/gameplay_keep.xml +++ b/assets/xml/objects/gameplay_keep.xml @@ -1377,8 +1377,8 @@ - - + + diff --git a/include/functions.h b/include/functions.h index c79fc333f..9d21eca01 100644 --- a/include/functions.h +++ b/include/functions.h @@ -558,7 +558,7 @@ void EffectSsHitmark_SpawnFixedScale(PlayState* play, s32 type, Vec3f* pos); void EffectSsHitmark_SpawnCustomScale(PlayState* play, s32 type, s16 scale, Vec3f* pos); void EffectSsFhgFlash_SpawnShock(PlayState* play, Actor* actor, Vec3f* pos, s16 scale, u8 params); // void EffectSsKFire_Spawn(UNK_TYPE4 uParm1, Vec3f* pzParm2, Vec3f* pzParm3, Vec3f* pzParm4, UNK_TYPE2 param_5, UNK_TYPE1 param_6); -void EffectSsSolderSrchBall_Spawn(PlayState* play, Vec3f* pos, Vec3f* velocity, Vec3f* accel, s16 unused, s16* linkDetected, s16 drawFlag); +void EffectSsSolderSrchBall_Spawn(PlayState* play, Vec3f* pos, Vec3f* velocity, Vec3f* accel, s16 scale, s16* playerDetected, s16 params); void EffectSsKakera_Spawn(PlayState* play, Vec3f* pos, Vec3f* velocity, Vec3f* arg3, s16 gravity, s16 arg5, s16 arg6, s16 arg7, s16 arg8, s16 scale, s16 arg10, s16 arg11, s32 life, s16 colorIdx, s16 objId, Gfx* dList); // void EffectSsIcePiece_Spawn(UNK_TYPE4 uParm1, Vec3f* pzParm2, UNK_TYPE4 uParm3, Vec3f* pzParm4, Vec3f* param_5, UNK_TYPE4 param_6); // void EffectSsIcePiece_SpawnBurst(void); diff --git a/include/z64effect.h b/include/z64effect.h index dde996eb7..b4574592a 100644 --- a/include/z64effect.h +++ b/include/z64effect.h @@ -257,7 +257,6 @@ typedef struct { /* 0x18 */ u8 unk18; // Always 1? } EffectSsOverlay; // size = 0x1C -//! TODO: Review reuse of vec/gfx/actor fields across all effects typedef struct EffectSs { /* 0x00 */ Vec3f pos; /* 0x0C */ Vec3f velocity; diff --git a/spec b/spec index 80141af9c..2dce298d5 100644 --- a/spec +++ b/spec @@ -1869,8 +1869,7 @@ beginseg name "ovl_Effect_Ss_Solder_Srch_Ball" compress include "build/src/overlays/effects/ovl_Effect_Ss_Solder_Srch_Ball/z_eff_ss_solder_srch_ball.o" - include "build/data/ovl_Effect_Ss_Solder_Srch_Ball/ovl_Effect_Ss_Solder_Srch_Ball.data.o" - include "build/data/ovl_Effect_Ss_Solder_Srch_Ball/ovl_Effect_Ss_Solder_Srch_Ball.reloc.o" + include "build/src/overlays/effects/ovl_Effect_Ss_Solder_Srch_Ball/ovl_Effect_Ss_Solder_Srch_Ball_reloc.o" endseg beginseg diff --git a/src/code/z_effect_soft_sprite_old_init.c b/src/code/z_effect_soft_sprite_old_init.c index 5fc51b0c3..bbdd528a4 100644 --- a/src/code/z_effect_soft_sprite_old_init.c +++ b/src/code/z_effect_soft_sprite_old_init.c @@ -702,16 +702,16 @@ void EffectSsKFire_Spawn(PlayState* play, Vec3f* pos, Vec3f* velocity, Vec3f* ac // EffectSsSolderSrchBall Spawn Functions -void EffectSsSolderSrchBall_Spawn(PlayState* play, Vec3f* pos, Vec3f* velocity, Vec3f* accel, s16 unused, - s16* linkDetected, s16 drawFlag) { +void EffectSsSolderSrchBall_Spawn(PlayState* play, Vec3f* pos, Vec3f* velocity, Vec3f* accel, s16 scale, + s16* playerDetected, s16 flags) { EffectSsSolderSrchBallInitParams initParams; Math_Vec3f_Copy(&initParams.pos, pos); Math_Vec3f_Copy(&initParams.velocity, velocity); Math_Vec3f_Copy(&initParams.accel, accel); - initParams.unused = unused; - initParams.linkDetected = linkDetected; - initParams.drawFlag = drawFlag; + initParams.scale = scale; + initParams.playerDetected = playerDetected; + initParams.flags = flags; EffectSs_Spawn(play, EFFECT_SS_SOLDER_SRCH_BALL, 128, &initParams); } diff --git a/src/overlays/actors/ovl_Demo_Kankyo/z_demo_kankyo.c b/src/overlays/actors/ovl_Demo_Kankyo/z_demo_kankyo.c index 12da39288..10b72634a 100644 --- a/src/overlays/actors/ovl_Demo_Kankyo/z_demo_kankyo.c +++ b/src/overlays/actors/ovl_Demo_Kankyo/z_demo_kankyo.c @@ -508,7 +508,7 @@ void DemoKakyo_DrawLostWoodsSparkle(Actor* thisx, PlayState* play2) { POLY_XLU_DISP = Gfx_CallSetupDL(POLY_XLU_DISP, 20); gSPSegment(POLY_XLU_DISP++, 0x08, Lib_SegmentedToVirtual(gSun1Tex)); - gSPDisplayList(POLY_XLU_DISP++, gameplay_keep_DL_07AB10); + gSPDisplayList(POLY_XLU_DISP++, gSunSparkleMaterialDL); for (i = 0; i < play->envCtx.unk_F2[3]; i++) { worldPos.x = this->effects[i].posBase.x + this->effects[i].posOffset.x; @@ -575,7 +575,7 @@ void DemoKakyo_DrawLostWoodsSparkle(Actor* thisx, PlayState* play2) { gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); - gSPDisplayList(POLY_XLU_DISP++, gameplay_keep_DL_07AB58); + gSPDisplayList(POLY_XLU_DISP++, gSunSparkleModelDL); } } diff --git a/src/overlays/actors/ovl_En_Encount2/z_en_encount2.c b/src/overlays/actors/ovl_En_Encount2/z_en_encount2.c index d771f3511..b7c698376 100644 --- a/src/overlays/actors/ovl_En_Encount2/z_en_encount2.c +++ b/src/overlays/actors/ovl_En_Encount2/z_en_encount2.c @@ -279,14 +279,14 @@ void EnEncount2_DrawEffects(EnEncount2* this, PlayState* play) { Matrix_Scale(sPtr->scale, sPtr->scale, sPtr->scale, MTXMODE_APPLY); POLY_XLU_DISP = Gfx_CallSetupDL(POLY_XLU_DISP, 20); gSPSegment(POLY_XLU_DISP++, 0x08, Lib_SegmentedToVirtual(gSun1Tex)); - gSPDisplayList(POLY_XLU_DISP++, gameplay_keep_DL_07AB10); + gSPDisplayList(POLY_XLU_DISP++, gSunSparkleMaterialDL); gDPPipeSync(POLY_XLU_DISP++); gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, 255); gDPSetEnvColor(POLY_XLU_DISP++, 250, 180, 255, sPtr->alpha); Matrix_Mult(&play->billboardMtxF, MTXMODE_APPLY); Matrix_RotateZF(DEGF_TO_RADF(play->state.frames * 20.0f), MTXMODE_APPLY); gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); - gSPDisplayList(POLY_XLU_DISP++, gameplay_keep_DL_07AB58); + gSPDisplayList(POLY_XLU_DISP++, gSunSparkleModelDL); } } CLOSE_DISPS(gfxCtx); diff --git a/src/overlays/actors/ovl_En_Hanabi/z_en_hanabi.c b/src/overlays/actors/ovl_En_Hanabi/z_en_hanabi.c index f9085e825..0f016f300 100644 --- a/src/overlays/actors/ovl_En_Hanabi/z_en_hanabi.c +++ b/src/overlays/actors/ovl_En_Hanabi/z_en_hanabi.c @@ -146,7 +146,7 @@ void func_80B22FA8(EnHanabiStruct* arg0, PlayState* play2) { POLY_XLU_DISP = Gfx_CallSetupDL(POLY_XLU_DISP, 20); gSPSegment(POLY_XLU_DISP++, 0x08, Lib_SegmentedToVirtual(gSun1Tex)); - gSPDisplayList(POLY_XLU_DISP++, gameplay_keep_DL_07AB10); + gSPDisplayList(POLY_XLU_DISP++, gSunSparkleMaterialDL); sp53 = 0xFF; if (sp53) {} @@ -181,7 +181,7 @@ void func_80B22FA8(EnHanabiStruct* arg0, PlayState* play2) { D_80B23C2C[arg0->unk_02 + 2], 255); } - gSPDisplayList(POLY_XLU_DISP++, gameplay_keep_DL_07AB58); + gSPDisplayList(POLY_XLU_DISP++, gSunSparkleModelDL); } } diff --git a/src/overlays/actors/ovl_En_Look_Nuts/z_en_look_nuts.c b/src/overlays/actors/ovl_En_Look_Nuts/z_en_look_nuts.c index de053c46a..6fd949feb 100644 --- a/src/overlays/actors/ovl_En_Look_Nuts/z_en_look_nuts.c +++ b/src/overlays/actors/ovl_En_Look_Nuts/z_en_look_nuts.c @@ -5,6 +5,7 @@ */ #include "z_en_look_nuts.h" +#include "overlays/effects/ovl_Effect_Ss_Solder_Srch_Ball/z_eff_ss_solder_srch_ball.h" #define FLAGS (ACTOR_FLAG_80000000) @@ -340,13 +341,14 @@ void EnLookNuts_Update(Actor* thisx, PlayState* play) { Matrix_MultVec3f(&effectVelOffset, &effectVel); Matrix_Pop(); if (!this->isPlayerDetected) { - s16 drawFlag = 1; + s16 effectFlags = SOLDERSRCHBALL_INVISIBLE; + if (gSaveContext.save.isNight) { - drawFlag = 0; + effectFlags = 0; } if (Player_GetMask(play) != PLAYER_MASK_STONE) { EffectSsSolderSrchBall_Spawn(play, &effectPos, &effectVel, &gZeroVec3f, 50, &this->isPlayerDetected, - drawFlag); + effectFlags); } } diff --git a/src/overlays/actors/ovl_En_Suttari/z_en_suttari.c b/src/overlays/actors/ovl_En_Suttari/z_en_suttari.c index bbce2ee6c..4f3882aa7 100644 --- a/src/overlays/actors/ovl_En_Suttari/z_en_suttari.c +++ b/src/overlays/actors/ovl_En_Suttari/z_en_suttari.c @@ -7,6 +7,7 @@ #include "z_en_suttari.h" #include "overlays/actors/ovl_En_Elf/z_en_elf.h" #include "overlays/actors/ovl_En_Door/z_en_door.h" +#include "overlays/effects/ovl_Effect_Ss_Solder_Srch_Ball/z_eff_ss_solder_srch_ball.h" #include "objects/object_boj/object_boj.h" #define FLAGS (ACTOR_FLAG_1 | ACTOR_FLAG_8 | ACTOR_FLAG_10) @@ -444,12 +445,13 @@ void func_80BAAFDC(EnSuttari* this, PlayState* play) { effectVelOffset.z = 20.0f; Matrix_MultVec3f(&effectVelOffset, &effectVel); Matrix_Pop(); - if (this->unk3F0 == 0) { - EffectSsSolderSrchBall_Spawn(play, &effectPos, &effectVel, &gZeroVec3f, 50, &this->unk3F0, 1); + if (!this->playerDetected) { + EffectSsSolderSrchBall_Spawn(play, &effectPos, &effectVel, &gZeroVec3f, 50, &this->playerDetected, + SOLDERSRCHBALL_INVISIBLE); } - if (this->unk3F0 == 1) { + if (this->playerDetected == true) { play_sound(NA_SE_SY_FOUND); - this->unk3F0 = 0; + this->playerDetected = false; this->actor.speedXZ = 0.0f; if (this->unk1F4[0] != 0) { this->unk1F4[0]--; @@ -476,12 +478,13 @@ void func_80BAB1A0(EnSuttari* this, PlayState* play) { effectVelOffset.z = 20.0f; Matrix_MultVec3f(&effectVelOffset, &effectVel); Matrix_Pop(); - if (this->unk3F0 == 0) { - EffectSsSolderSrchBall_Spawn(play, &effectPos, &effectVel, &gZeroVec3f, 50, &this->unk3F0, 1); + if (!this->playerDetected) { + EffectSsSolderSrchBall_Spawn(play, &effectPos, &effectVel, &gZeroVec3f, 50, &this->playerDetected, + SOLDERSRCHBALL_INVISIBLE); } - if (this->unk3F0 == 1) { + if (this->playerDetected == true) { play_sound(NA_SE_SY_FOUND); - this->unk3F0 = 0; + this->playerDetected = false; this->actor.speedXZ = 0.0f; if (this->unk1F4[0] != 0) { this->unk1F4[0]--; diff --git a/src/overlays/actors/ovl_En_Suttari/z_en_suttari.h b/src/overlays/actors/ovl_En_Suttari/z_en_suttari.h index 35a9b6e2e..427f74988 100644 --- a/src/overlays/actors/ovl_En_Suttari/z_en_suttari.h +++ b/src/overlays/actors/ovl_En_Suttari/z_en_suttari.h @@ -34,7 +34,7 @@ typedef struct EnSuttari { /* 0x2FA */ s16 unk2FA[16]; /* 0x31A */ s16 unk31A[16]; /* 0x33A */ UNK_TYPE1 unk_33A[0xB6]; - /* 0x3F0 */ s16 unk3F0; + /* 0x3F0 */ s16 playerDetected; /* 0x3F2 */ s16 unk3F2; /* 0x3F4 */ s16 unk3F4; /* 0x3F6 */ s16 unk3F6; diff --git a/src/overlays/effects/ovl_Effect_Ss_Solder_Srch_Ball/z_eff_ss_solder_srch_ball.c b/src/overlays/effects/ovl_Effect_Ss_Solder_Srch_Ball/z_eff_ss_solder_srch_ball.c index 04afcba3f..01224dd32 100644 --- a/src/overlays/effects/ovl_Effect_Ss_Solder_Srch_Ball/z_eff_ss_solder_srch_ball.c +++ b/src/overlays/effects/ovl_Effect_Ss_Solder_Srch_Ball/z_eff_ss_solder_srch_ball.c @@ -1,27 +1,93 @@ /* * File: z_eff_ss_solder_srch_ball.c * Overlay: ovl_Effect_Ss_Solder_Srch_Ball - * Description: + * Description: Vision sphere */ #include "z_eff_ss_solder_srch_ball.h" +#include "objects/gameplay_keep/gameplay_keep.h" + +#define rFlags regs[0] #define PARAMS ((EffectSsSolderSrchBallInitParams*)initParamsx) -s32 EffectSsSolderSrchBall_Init(PlayState* play, u32 index, EffectSs* this, void* initParamsx); +u32 EffectSsSolderSrchBall_Init(PlayState* play, u32 index, EffectSs* this, void* initParamsx); void EffectSsSolderSrchBall_Update(PlayState* play, u32 index, EffectSs* this); void EffectSsSolderSrchBall_Draw(PlayState* play, u32 index, EffectSs* this); -#if 0 const EffectSsInit Effect_Ss_Solder_Srch_Ball_InitVars = { EFFECT_SS_SOLDER_SRCH_BALL, EffectSsSolderSrchBall_Init, }; -#endif +u32 EffectSsSolderSrchBall_Init(PlayState* play, u32 index, EffectSs* this, void* initParamsx) { + EffectSsSolderSrchBallInitParams* initParams = PARAMS; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Effect_Ss_Solder_Srch_Ball/EffectSsSolderSrchBall_Init.s") + this->pos = initParams->pos; + this->velocity = initParams->velocity; + this->accel = initParams->accel; + this->update = EffectSsSolderSrchBall_Update; + if (!(initParams->flags & SOLDERSRCHBALL_INVISIBLE)) { + this->draw = EffectSsSolderSrchBall_Draw; + } + this->life = 10; + this->rgScale = initParams->scale; + this->rFlags = initParams->flags; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Effect_Ss_Solder_Srch_Ball/EffectSsSolderSrchBall_Draw.s") + //! @bug actor field used to store an s16* + // This bug is purely cosmetic. Nothing external will ever read this as an Actor, so there are no unintended + // side-effects. + this->actor = (Actor*)initParams->playerDetected; + return 1; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Effect_Ss_Solder_Srch_Ball/EffectSsSolderSrchBall_Update.s") +void EffectSsSolderSrchBall_Draw(PlayState* play, u32 index, EffectSs* this) { + s32 pad; + GraphicsContext* gfxCtx = play->state.gfxCtx; + f32 scale = this->rgScale / 100.0f; + + func_8012C28C(gfxCtx); + func_8012C2DC(play->state.gfxCtx); + + OPEN_DISPS(gfxCtx); + + Matrix_Translate(this->pos.x, this->pos.y, this->pos.z, MTXMODE_NEW); + Matrix_Scale(scale, scale, scale, MTXMODE_APPLY); + POLY_XLU_DISP = Gfx_CallSetupDL(POLY_XLU_DISP, 20); + gSPSegment(POLY_XLU_DISP++, 0x08, Lib_SegmentedToVirtual(gSun1Tex)); + gSPDisplayList(POLY_XLU_DISP++, gSunSparkleMaterialDL); + gDPPipeSync(POLY_XLU_DISP++); + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, 255); + gDPSetEnvColor(POLY_XLU_DISP++, 250, 180, 255, 255); + Matrix_Mult(&play->billboardMtxF, MTXMODE_APPLY); + Matrix_RotateZF(DEGF_TO_RADF(20.0f * play->state.frames), MTXMODE_APPLY); + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_XLU_DISP++, gSunSparkleModelDL); + + CLOSE_DISPS(gfxCtx); +} + +void EffectSsSolderSrchBall_Update(PlayState* play, u32 index, EffectSs* this) { + s32 pad; + f32 diffX; + f32 diffY; + f32 diffZ; + s16* playerDetected = (s16*)this->actor; + Player* player = GET_PLAYER(play); + + diffX = player->actor.world.pos.x - this->pos.x; + diffY = player->actor.world.pos.y - this->pos.y; + diffZ = player->actor.world.pos.z - this->pos.z; + + if (this->rFlags >= SOLDERSRCHBALL_SMALL_DETECT_RADIUS) { + if ((sqrtf(SQ(diffX) + SQ(diffZ)) < 10.0f) && (sqrtf(SQ(diffY)) < 10.0f)) { + *playerDetected = true; + } + } else if (!BgCheck_SphVsFirstWall(&play->colCtx, &this->pos, 30.0f)) { + if ((sqrtf(SQ(diffX) + SQ(diffZ)) < 40.0f) && (sqrtf(SQ(diffY)) < 80.0f)) { + *playerDetected = true; + } + } else if (this->life > 1) { + this->life = 1; + } +} diff --git a/src/overlays/effects/ovl_Effect_Ss_Solder_Srch_Ball/z_eff_ss_solder_srch_ball.h b/src/overlays/effects/ovl_Effect_Ss_Solder_Srch_Ball/z_eff_ss_solder_srch_ball.h index 24b9f47fc..fb4fb4159 100644 --- a/src/overlays/effects/ovl_Effect_Ss_Solder_Srch_Ball/z_eff_ss_solder_srch_ball.h +++ b/src/overlays/effects/ovl_Effect_Ss_Solder_Srch_Ball/z_eff_ss_solder_srch_ball.h @@ -3,13 +3,16 @@ #include "global.h" +#define SOLDERSRCHBALL_INVISIBLE (1 << 0) +#define SOLDERSRCHBALL_SMALL_DETECT_RADIUS (1 << 1) + typedef struct { /* 0x00 */ Vec3f pos; /* 0x0C */ Vec3f velocity; /* 0x18 */ Vec3f accel; - /* 0x24 */ s16 unused; - /* 0x28 */ s16* linkDetected; - /* 0x2C */ s16 drawFlag; + /* 0x24 */ s16 scale; + /* 0x28 */ s16* playerDetected; + /* 0x2C */ s16 flags; } EffectSsSolderSrchBallInitParams; // size = 0x30 extern const EffectSsInit Effect_Ss_Solder_Srch_Ball_InitVars; From 0e2de439dd2882bb4e3585d918e040ba18b55b41 Mon Sep 17 00:00:00 2001 From: Maide <34639600+Kelebek1@users.noreply.github.com> Date: Sun, 2 Oct 2022 19:31:55 +0100 Subject: [PATCH 09/10] Dm_Tag (#922) * Dm_Tag * PR * Fix * PR * PR --- spec | 3 +- src/overlays/actors/ovl_Dm_Tag/z_dm_tag.c | 235 ++++++++++++++++++++-- src/overlays/actors/ovl_Dm_Tag/z_dm_tag.h | 11 +- 3 files changed, 230 insertions(+), 19 deletions(-) diff --git a/spec b/spec index 2dce298d5..4dec1f228 100644 --- a/spec +++ b/spec @@ -5029,8 +5029,7 @@ beginseg name "ovl_Dm_Tag" compress include "build/src/overlays/actors/ovl_Dm_Tag/z_dm_tag.o" - include "build/data/ovl_Dm_Tag/ovl_Dm_Tag.data.o" - include "build/data/ovl_Dm_Tag/ovl_Dm_Tag.reloc.o" + include "build/src/overlays/actors/ovl_Dm_Tag/ovl_Dm_Tag_reloc.o" endseg beginseg diff --git a/src/overlays/actors/ovl_Dm_Tag/z_dm_tag.c b/src/overlays/actors/ovl_Dm_Tag/z_dm_tag.c index b74c43940..2c8bf046f 100644 --- a/src/overlays/actors/ovl_Dm_Tag/z_dm_tag.c +++ b/src/overlays/actors/ovl_Dm_Tag/z_dm_tag.c @@ -18,7 +18,6 @@ void func_80C229AC(DmTag* this, PlayState* play); void func_80C229EC(DmTag* this, PlayState* play); void func_80C229FC(DmTag* this, PlayState* play); -#if 0 const ActorInit Dm_Tag_InitVars = { ACTOR_DM_TAG, ACTORCAT_ITEMACTION, @@ -31,30 +30,236 @@ const ActorInit Dm_Tag_InitVars = { (ActorFunc)NULL, }; -#endif +s32 D_80C22BF0[] = { + 0x0E28F00C, + 0x15090000, + 0x10000000, +}; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Dm_Tag/func_80C22350.s") +s32 D_80C22BFC[] = { + 0x0900000E, 0x28F10C09, 0x00000E28, 0xF20C0900, 0x000E28F3, 0x0C090000, 0x0E28F40C, + 0x0900000E, 0x28F50C09, 0x00000E28, 0xF60C1511, 0x55040900, 0x00100000, +}; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Dm_Tag/func_80C22400.s") +s32 D_80C22C30[] = { + 0x0E28EF0C, + 0x10000000, +}; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Dm_Tag/func_80C2247C.s") +Actor* func_80C22350(DmTag* this, PlayState* play, u8 actorCat, s16 actorId) { + Actor* foundActor = NULL; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Dm_Tag/func_80C224D8.s") + while (true) { + foundActor = SubS_FindActor(play, foundActor, actorCat, actorId); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Dm_Tag/func_80C227E8.s") + if ((foundActor == NULL) || (((this != (DmTag*)foundActor)) && (foundActor->update != NULL))) { + break; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Dm_Tag/func_80C22880.s") + if (foundActor->next == NULL) { + foundActor = NULL; + break; + } + foundActor = foundActor->next; + } + return foundActor; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Dm_Tag/func_80C2291C.s") +s32 func_80C22400(DmTag* this, s16 arg1) { + s32 ret = false; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Dm_Tag/func_80C229AC.s") + if (ActorCutscene_GetCurrentIndex() == 0x7C) { + ActorCutscene_Stop(0x7C); + ActorCutscene_SetIntentToPlay(arg1); + } else if (ActorCutscene_GetCanPlayNext(arg1)) { + ActorCutscene_StartAndSetUnkLinkFields(arg1, &this->actor); + ret = true; + } else { + ActorCutscene_SetIntentToPlay(arg1); + } + return ret; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Dm_Tag/func_80C229EC.s") +s16 func_80C2247C(DmTag* this, s32 arg1) { + s32 i; + s16 cs = this->actor.cutscene; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Dm_Tag/func_80C229FC.s") + for (i = 0; i < arg1; i++) { + cs = ActorCutscene_GetAdditionalCutscene(cs); + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Dm_Tag/DmTag_Init.s") + return cs; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Dm_Tag/DmTag_Destroy.s") +s32 func_80C224D8(DmTag* this, PlayState* play) { + s32 pad; + Actor* sp30; + Actor* sp2C; + s16 sp2A = this->actor.cutscene; + s32 ret = false; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Dm_Tag/DmTag_Update.s") + sp30 = func_80C22350(this, play, ACTORCAT_NPC, ACTOR_EN_AN); + sp2C = func_80C22350(this, play, ACTORCAT_NPC, ACTOR_EN_AH); + + switch (this->unk_1A4) { + case 0: + if (func_80C22400(this, sp2A)) { + if ((sp2C != NULL) && (sp2C->update != NULL)) { + Camera_SetTargetActor(Play_GetCamera(play, ActorCutscene_GetCurrentSubCamId(sp2A)), sp2C); + } + this->unk_1A4++; + ret = true; + } + break; + + case 1: + if ((sp30 != NULL) && (sp30->update != NULL)) { + Camera_SetTargetActor(Play_GetCamera(play, ActorCutscene_GetCurrentSubCamId(func_80C2247C(this, 0))), + sp30); + } + this->unk_1A4++; + ret = true; + break; + + case 2: + ActorCutscene_Stop(func_80C2247C(this, 0)); + if (func_80C22400(this, func_80C2247C(this, 1))) { + this->unk_1A4++; + ret = true; + } + break; + + case 3: + ActorCutscene_Stop(func_80C2247C(this, 1)); + if (func_80C22400(this, func_80C2247C(this, 2))) { + this->unk_1A4++; + ret = true; + } + break; + + case 4: + ActorCutscene_Stop(func_80C2247C(this, 2)); + if (func_80C22400(this, func_80C2247C(this, 3))) { + this->unk_1A4++; + ret = true; + } + break; + + case 5: + ActorCutscene_Stop(func_80C2247C(this, 3)); + if (func_80C22400(this, func_80C2247C(this, 4))) { + this->unk_1A4++; + ret = true; + } + break; + + case 6: + func_800B7298(play, &this->actor, 7); + play->nextEntrance = ENTRANCE(STOCK_POT_INN, 5); + gSaveContext.nextCutsceneIndex = 0; + play->transitionTrigger = TRANS_TRIGGER_START; + play->transitionType = TRANS_TYPE_02; + gSaveContext.nextTransitionType = TRANS_TYPE_06; + this->unk_1A4++; + break; + } + return ret; +} + +s32 func_80C227E8(DmTag* this, PlayState* play) { + if (this->unk_1A4 == 0) { + func_800B7298(play, &this->actor, 7); + play->nextEntrance = ENTRANCE(STOCK_POT_INN, 4); + gSaveContext.nextCutsceneIndex = 0; + play->transitionTrigger = TRANS_TRIGGER_START; + play->transitionType = TRANS_TYPE_02; + gSaveContext.nextTransitionType = TRANS_TYPE_06; + this->unk_1A4++; + } + return false; +} + +s32* func_80C22880(DmTag* this, PlayState* play) { + s32 time; + + switch (this->unk_18E) { + case 1: + time = gSaveContext.save.time - 0x3FFC; + if ((time >= 0xA54B) && (time < 0xB54A) && (gSaveContext.save.day == 2)) { + this->msgEventCallback = func_80C227E8; + return D_80C22BF0; + } + return D_80C22C30; + case 2: + this->msgEventCallback = func_80C224D8; + return D_80C22BFC; + } + return NULL; +} + +s32 func_80C2291C(DmTag* this, PlayState* play) { + s32 ret = false; + + if (this->unk_18C & 7) { + if (Actor_ProcessTalkRequest(&this->actor, &play->state)) { + this->unk_18C |= 8; + SubS_UpdateFlags(&this->unk_18C, 0, 7); + this->msgEventScript = func_80C22880(this, play); + this->actionFunc = func_80C229FC; + ret = true; + } + } + return ret; +} + +void func_80C229AC(DmTag* this, PlayState* play) { + SubS_UpdateFlags(&this->unk_18C, 3, 7); + this->actor.flags |= ACTOR_FLAG_1; +} + +void func_80C229EC(DmTag* this, PlayState* play) { +} + +void func_80C229FC(DmTag* this, PlayState* play) { + if (func_8010BF58(&this->actor, play, this->msgEventScript, this->msgEventCallback, &this->msgEventArg4)) { + this->actionFunc = func_80C229AC; + } +} + +void DmTag_Init(Actor* thisx, PlayState* play) { + DmTag* this = (DmTag*)thisx; + Player* player = GET_PLAYER(play); + + if (gSaveContext.save.weekEventReg[85] & 4) { + Actor_MarkForDeath(&this->actor); + return; + } + + if ((play->sceneId == SCENE_YADOYA) && (play->curSpawn == 4)) { + player->stateFlags1 |= PLAYER_STATE1_20; + this->unk_18E = 2; + this->unk_18C = 0; + SubS_UpdateFlags(&this->unk_18C, 4, 7); + this->actor.flags &= ~ACTOR_FLAG_1; + this->actionFunc = func_80C229EC; + } else if (this->actor.room == 2) { + Actor_MarkForDeath(&this->actor); + } else { + this->actor.targetMode = 1; + this->unk_18E = 1; + this->unk_18C = 0; + this->actionFunc = func_80C229AC; + } +} + +void DmTag_Destroy(Actor* thisx, PlayState* play) { +} + +void DmTag_Update(Actor* thisx, PlayState* play) { + DmTag* this = THIS; + + func_80C2291C(this, play); + this->actionFunc(this, play); + func_8013C964(&this->actor, play, 40.0f, fabsf(this->actor.playerHeightRel) + 1.0f, 0, this->unk_18C & 7); + Actor_SetFocus(&this->actor, 0.0f); +} diff --git a/src/overlays/actors/ovl_Dm_Tag/z_dm_tag.h b/src/overlays/actors/ovl_Dm_Tag/z_dm_tag.h index fda9397c7..d68cd38d4 100644 --- a/src/overlays/actors/ovl_Dm_Tag/z_dm_tag.h +++ b/src/overlays/actors/ovl_Dm_Tag/z_dm_tag.h @@ -6,12 +6,19 @@ struct DmTag; typedef void (*DmTagActionFunc)(struct DmTag*, PlayState*); +typedef s32 (*DmTagMsgEventFunc)(struct DmTag*, PlayState*); typedef struct DmTag { /* 0x000 */ Actor actor; - /* 0x144 */ char unk_144[0x44]; + /* 0x144 */ UNK_TYPE1 pad144[0x44]; /* 0x188 */ DmTagActionFunc actionFunc; - /* 0x18C */ char unk_18C[0x20]; + /* 0x18C */ u16 unk_18C; + /* 0x18E */ u8 unk_18E; + /* 0x190 */ s32* msgEventScript; + /* 0x194 */ s32 msgEventArg4; + /* 0x198 */ UNK_TYPE1 pad198[0xC]; + /* 0x1A4 */ s16 unk_1A4; + /* 0x1A8 */ DmTagMsgEventFunc msgEventCallback; } DmTag; // size = 0x1AC extern const ActorInit Dm_Tag_InitVars; From 3e32379c2bbce332dae9675954e28387480128f0 Mon Sep 17 00:00:00 2001 From: engineer124 <47598039+engineer124@users.noreply.github.com> Date: Sun, 2 Oct 2022 15:24:10 -0400 Subject: [PATCH 10/10] audio_synthesis.c OK and Documented (#1090) * import synth docs * cleanup * small followup cleanup * PR Suggestions, small cleanup * fix bss * PR suggestion * fix enum * PR Suggestions --- include/PR/abi.h | 91 +- include/functions.h | 43 +- include/variables.h | 34 +- include/z64audio.h | 312 +-- spec | 1 - src/code/audio/audio_data.c | 93 +- src/code/audio/audio_heap.c | 264 +-- src/code/audio/audio_init_params.c | 182 +- src/code/audio/audio_load.c | 6 +- src/code/audio/audio_playback.c | 202 +- src/code/audio/audio_seqplayer.c | 49 +- src/code/audio/audio_synthesis.c | 1807 +++++++++++++++-- src/code/audio/code_8019AF00.c | 2 +- src/overlays/actors/ovl_En_Kusa2/z_en_kusa2.c | 1 - tools/disasm/files.txt | 1 + tools/disasm/functions.txt | 138 +- tools/disasm/variables.txt | 18 +- tools/sizes/code_functions.csv | 138 +- 18 files changed, 2612 insertions(+), 770 deletions(-) diff --git a/include/PR/abi.h b/include/PR/abi.h index 49d539762..15ae5d911 100644 --- a/include/PR/abi.h +++ b/include/PR/abi.h @@ -53,6 +53,7 @@ #define A_INIT 0x01 #define A_CONTINUE 0x00 #define A_LOOP 0x02 +#define A_ADPCM_SHORT 0x04 #define A_OUT 0x02 #define A_LEFT 0x02 #define A_RIGHT 0x00 @@ -331,13 +332,20 @@ typedef short ENVMIX_STATE[40]; _a->words.w1 = (unsigned int)(a2); \ } -#define aClearBuffer(pkt, d, c) \ -{ \ - Acmd *_a = (Acmd *)pkt; \ - \ - _a->words.w0 = _SHIFTL(A_CLEARBUFF, 24, 8) | _SHIFTL(d, 0, 24); \ - _a->words.w1 = (unsigned int)(c); \ -} +/* + * Clears DMEM by writing zeros. + * + * @param pkt pointer to an Acmd buffer + * @param dmem DMEM address to clear + * @param size number of bytes to clear (rounded up to the next multiple of 16) + */ +#define aClearBuffer(pkt, dmem, size) \ + { \ + Acmd* _a = (Acmd*)pkt; \ + \ + _a->words.w0 = _SHIFTL(A_CLEARBUFF, 24, 8) | _SHIFTL(dmem, 0, 24); \ + _a->words.w1 = (uintptr_t)(size); \ + } #define aEnvMixer(pkt, dmemi, count, swapLR, x0, x1, x2, x3, m, bits) \ { \ @@ -368,14 +376,21 @@ typedef short ENVMIX_STATE[40]; _a->words.w1 = _SHIFTL(dmemi, 16, 16) | _SHIFTL(dmemo, 0, 16); \ } -#define aLoadBuffer(pkt, s, d, c) \ -{ \ - Acmd *_a = (Acmd *)pkt; \ - \ - _a->words.w0 = _SHIFTL(A_LOADBUFF, 24, 8) | \ - _SHIFTL((c) >> 4, 16, 8) | _SHIFTL(d, 0, 16); \ - _a->words.w1 = (unsigned int)(s); \ -} +/* + * Loads a buffer to DMEM from any physical source address, KSEG0, or KSEG1 + * + * @param pkt pointer to an Acmd buffer + * @param addrSrc Any physical source address, KSEG0, or KSEG1 + * @param dmemDest DMEM destination address + * @param size number of bytes to copy (rounded down to the next multiple of 16) + */ +#define aLoadBuffer(pkt, addrSrc, dmemDest, size) \ + { \ + Acmd* _a = (Acmd*)pkt; \ + \ + _a->words.w0 = (_SHIFTL(A_LOADBUFF, 24, 8) | _SHIFTL((size) >> 4, 16, 8) | _SHIFTL(dmemDest, 0, 16)); \ + _a->words.w1 = (uintptr_t)(addrSrc); \ + } #define aMix(pkt, f, g, i, o) \ { \ @@ -404,14 +419,21 @@ typedef short ENVMIX_STATE[40]; _a->words.w1 = (unsigned int)(s); \ } -#define aSaveBuffer(pkt, s, d, c) \ -{ \ - Acmd *_a = (Acmd *)pkt; \ - \ - _a->words.w0 = _SHIFTL(A_SAVEBUFF, 24, 8) | \ - _SHIFTL((c) >> 4, 16, 8) | _SHIFTL(s, 0, 16); \ - _a->words.w1 = (unsigned int)(d); \ -} +/* + * Stores a buffer from DMEM to any physical source address, KSEG0, or KSEG1 + * + * @param pkt pointer to an Acmd buffer + * @param dmemSrc DMEM source address + * @param addrDest Any physical source address, KSEG0, or KSEG1 + * @param size number of bytes to copy (rounded down to the next multiple of 16) + */ +#define aSaveBuffer(pkt, dmemSrc, addrDest, size) \ + { \ + Acmd* _a = (Acmd*)pkt; \ + \ + _a->words.w0 = (_SHIFTL(A_SAVEBUFF, 24, 8) | _SHIFTL((size) >> 4, 16, 8) | _SHIFTL(dmemSrc, 0, 16)); \ + _a->words.w1 = (uintptr_t)(addrDest); \ + } #define aSegment(pkt, s, b) \ { \ @@ -501,14 +523,21 @@ typedef short ENVMIX_STATE[40]; _a->words.w1 = (unsigned int)(addr); \ } -#define aDuplicate(pkt, count, dmemi, dmemo, a4) \ -{ \ - Acmd *_a = (Acmd *)pkt; \ - \ - _a->words.w0 = (_SHIFTL(A_DUPLICATE, 24, 8) | \ - _SHIFTL(count, 16, 8) | _SHIFTL(dmemi, 0, 16)); \ - _a->words.w1 = _SHIFTL(dmemo, 16, 16) | _SHIFTL(a4, 0, 16); \ -} +/* + * Duplicates 128 bytes of data a specified number of times. + * + * @param pkt pointer to an Acmd buffer + * @param numCopies number of times to duplicate 128 bytes from src + * @param dmemSrc DMEM source address + * @param dmemDest DMEM destination address for the duplicates, size 128 * numCopies + */ +#define aDuplicate(pkt, numCopies, dmemSrc, dmemDest) \ + { \ + Acmd* _a = (Acmd*)pkt; \ + \ + _a->words.w0 = (_SHIFTL(A_DUPLICATE, 24, 8) | _SHIFTL(numCopies, 16, 8) | _SHIFTL(dmemSrc, 0, 16)); \ + _a->words.w1 = _SHIFTL(dmemDest, 16, 16) | _SHIFTL(0x80, 0, 16); \ + } #define aAddMixer(pkt, count, dmemi, dmemo, a4) \ { \ diff --git a/include/functions.h b/include/functions.h index 9d21eca01..d42733a14 100644 --- a/include/functions.h +++ b/include/functions.h @@ -2897,48 +2897,7 @@ s32 osFlashWriteBuffer(OSIoMesg* mb, s32 priority, void* dramAddr, OSMesgQueue* s32 osFlashWriteArray(u32 pageNum); s32 osFlashReadArray(OSIoMesg* mb, s32 priority, u32 pageNum, void* dramAddr, u32 pageCount, OSMesgQueue* mq); -// void func_801877D0(void); -// void func_80187B64(void); -// void func_80187BEC(void); -// void func_80187DE8(void); -// void func_80187E58(void); -// void func_80187F00(void); -// void func_80187FB0(void); -// void func_80187FE8(UNK_TYPE1 param_1, UNK_TYPE1 param_2, UNK_TYPE1 param_3, UNK_TYPE1 param_4, UNK_TYPE4 param_5); -// void func_80188034(UNK_TYPE1 param_1, UNK_TYPE1 param_2, UNK_TYPE1 param_3, UNK_TYPE1 param_4, UNK_TYPE4 param_5); -// void func_80188078(void); -// void func_801880C4(void); -// void func_801880E8(UNK_TYPE1 param_1, UNK_TYPE1 param_2, UNK_TYPE1 param_3, UNK_TYPE1 param_4, UNK_TYPE4 param_5); -// void func_80188124(void); -// void func_8018814C(void); -// void func_80188174(void); -// void func_801881A8(void); -// void func_801881C4(UNK_TYPE1 param_1, UNK_TYPE1 param_2, UNK_TYPE1 param_3, UNK_TYPE1 param_4, UNK_TYPE4 param_5); -// void func_801881F8(UNK_TYPE1 param_1, UNK_TYPE1 param_2, UNK_TYPE1 param_3, UNK_TYPE1 param_4, UNK_TYPE4 param_5); -// void func_80188264(void); -// void func_80188288(void); -// void func_801882A0(void); -// void func_80188304(void); -// void func_801884A0(void); -// void func_80188698(void); -// void func_8018883C(void); -// void func_801888E4(void); -// void func_801889A4(void); -// void func_80188A50(void); -// void func_80188AFC(void); -// void func_80188C48(UNK_TYPE1 param_1, UNK_TYPE1 param_2, UNK_TYPE1 param_3, UNK_TYPE1 param_4, UNK_TYPE4 param_5); -// void func_80188CB4(UNK_TYPE1 param_1, UNK_TYPE1 param_2, UNK_TYPE1 param_3, UNK_TYPE1 param_4, UNK_TYPE4 param_5); -// void func_80188D28(void); -// void func_80188D68(void); -// void func_80188DDC(void); -// void func_80188FBC(void); -// void func_80189064(void); -// void func_80189620(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_TYPE4 param_7); -// void func_8018A4B4(UNK_TYPE1 param_1, UNK_TYPE1 param_2, UNK_TYPE1 param_3, UNK_TYPE1 param_4, UNK_TYPE4 param_5, UNK_TYPE4 param_6); -// void func_8018A768(UNK_TYPE1 param_1, UNK_TYPE1 param_2, UNK_TYPE1 param_3, UNK_TYPE1 param_4, UNK_TYPE2 param_5, UNK_TYPE4 param_6); -// void func_8018A808(UNK_TYPE1 param_1, UNK_TYPE1 param_2, UNK_TYPE1 param_3, UNK_TYPE1 param_4, UNK_TYPE2 param_5, UNK_TYPE4 param_6); -// void func_8018ACC4(void); -// void func_8018AE34(UNK_TYPE1 param_1, UNK_TYPE1 param_2, UNK_TYPE1 param_3, UNK_TYPE1 param_4, UNK_TYPE4 param_5, UNK_TYPE4 param_6); +Acmd* AudioSynth_Update(Acmd* cmdStart, s32* numAbiCmds, s16* aiStart, s32 aiBufLen); void AudioHeap_DiscardFont(s32 fontId); void* AudioHeap_WritebackDCache(void* addr, size_t size); diff --git a/include/variables.h b/include/variables.h index ae97a6c51..a4914a441 100644 --- a/include/variables.h +++ b/include/variables.h @@ -1557,11 +1557,11 @@ extern f32 gPitchFrequencies[]; extern u8 gDefaultShortNoteVelocityTable[]; extern u8 gDefaultShortNoteGateTimeTable[]; extern EnvelopePoint gDefaultEnvelope[]; -extern NoteSubEu gZeroNoteSub; -extern NoteSubEu gDefaultNoteSub; -extern u16 gHeadsetPanQuantization[]; -extern u16 gHeadsetPanQuantization[]; -extern s16 D_801D58A8[]; +extern NoteSampleState gZeroedSampleState; +extern NoteSampleState gDefaultSampleState; +extern u16 gHaasEffectDelaySize[]; +extern u16 gHaasEffectDelaySize[]; +extern s16 gInvalidAdpcmCodeBook[]; extern f32 gHeadsetPanVolume[]; extern f32 gStereoPanVolume[]; extern f32 gDefaultPanVolume[]; @@ -1721,21 +1721,7 @@ extern s8 gSfxDefaultReverb; extern u8 gAudioSpecId; // extern UNK_TYPE1 D_801DB4D8; // extern UNK_TYPE4 D_801DB4DC; -// extern UNK_TYPE1 D_801DB4E0; -// extern UNK_TYPE1 D_801DB528; -// extern UNK_TYPE1 D_801DB570; -// extern UNK_TYPE1 D_801DB5B8; -// extern UNK_TYPE1 D_801DB600; -// extern UNK_TYPE1 D_801DB648; -// extern UNK_TYPE1 D_801DB690; -// extern UNK_TYPE1 D_801DB6D8; -// extern UNK_TYPE1 D_801DB720; -// extern UNK_TYPE1 D_801DB750; -// extern UNK_TYPE1 D_801DB798; -// extern UNK_TYPE1 D_801DB870; -// extern UNK_TYPE1 D_801DB8B8; -// extern UNK_TYPE1 D_801DB900; -extern UNK_PTR D_801DB930; +extern ReverbSettings* gReverbSettingsTable[]; extern AudioSpec gAudioSpecs[21]; // rodata @@ -3483,10 +3469,10 @@ extern ActiveSequence gActiveSeqs[]; // extern UNK_TYPE1 D_80200BCE; // extern UNK_TYPE1 D_80200BD0; extern AudioContext gAudioContext; // at 0x80200C70 -extern void (*D_80208E68)(void); -extern u32 (*D_80208E6C)(s8 value, SequenceChannel* channel); -extern s32 (*D_80208E70)(Sample*, s32, s8, s32); -extern Acmd* (*D_80208E74)(Acmd*, s32, s32); +extern void (*gCustomAudioUpdateFunction)(void); +extern u32 (*gCustomAudioSeqFunction)(s8 value, SequenceChannel* channel); +extern s32 (*gCustomAudioReverbFunction)(Sample*, s32, s8, s32); +extern Acmd* (*gCustomAudioSynthFunction)(Acmd*, s32, s32); // post-code buffers extern u8 gGfxSPTaskYieldBuffer[OS_YIELD_DATA_SIZE]; diff --git a/include/z64audio.h b/include/z64audio.h index c5045e34f..264e8d9e3 100644 --- a/include/z64audio.h +++ b/include/z64audio.h @@ -1,7 +1,7 @@ #ifndef Z64_AUDIO_H #define Z64_AUDIO_H -#define MK_AUDIO_CMD(b0,b1,b2,b3) ((((b0) & 0xFF) << 0x18) | (((b1) & 0xFF) << 0x10) | (((b2) & 0xFF) << 0x8) | (((b3) & 0xFF) << 0)) +#define AUDIO_MK_CMD(b0,b1,b2,b3) ((((b0) & 0xFF) << 0x18) | (((b1) & 0xFF) << 0x10) | (((b2) & 0xFF) << 0x8) | (((b3) & 0xFF) << 0)) #define NO_LAYER ((SequenceLayer*)(-1)) @@ -32,13 +32,45 @@ typedef enum { #define ADSR_GOTO -2 #define ADSR_RESTART -3 -#define AIBUF_LEN 0x580 +// size of a single sample point +#define SAMPLE_SIZE sizeof(s16) + +// Samples are processed in groups of 16 called a "frame" +#define SAMPLES_PER_FRAME ADPCMFSIZE + +// The length of one left/right channel is 13 frames +#define DMEM_1CH_SIZE (13 * SAMPLES_PER_FRAME * SAMPLE_SIZE) +// Both left and right channels +#define DMEM_2CH_SIZE (2 * DMEM_1CH_SIZE) + +#define AIBUF_LEN (88 * SAMPLES_PER_FRAME) // number of samples +#define AIBUF_SIZE (AIBUF_LEN * SAMPLE_SIZE) // number of bytes + +// Filter sizes +#define FILTER_SIZE (8 * SAMPLE_SIZE) +#define FILTER_BUF_PART1 (8 * SAMPLE_SIZE) +#define FILTER_BUF_PART2 (8 * SAMPLE_SIZE) // Must be the same amount of samples as copied by aDuplicate() (audio microcode) #define WAVE_SAMPLE_COUNT 64 #define AUDIO_RELOCATED_ADDRESS_START K0BASE +#define REVERB_INDEX_NONE -1 + +typedef enum { + /* 0 */ REVERB_DATA_TYPE_SETTINGS, // Reverb Settings (Init) + /* 1 */ REVERB_DATA_TYPE_DELAY, // Reverb Delay (numSamples) + /* 2 */ REVERB_DATA_TYPE_DECAY, // Reverb Decay Ratio + /* 3 */ REVERB_DATA_TYPE_SUB_VOLUME, // Reverb Sub-Volume + /* 4 */ REVERB_DATA_TYPE_VOLUME, // Reverb Volume + /* 5 */ REVERB_DATA_TYPE_LEAK_RIGHT, // Reverb Leak Right Channel + /* 6 */ REVERB_DATA_TYPE_LEAK_LEFT, // Reverb Leak Left Channel + /* 7 */ REVERB_DATA_TYPE_FILTER_LEFT, // Reverb Left Filter + /* 8 */ REVERB_DATA_TYPE_FILTER_RIGHT, // Reverb Right Filter + /* 9 */ REVERB_DATA_TYPE_9 // Reverb Unk +} ReverbDataType; + typedef enum { /* 0x1 */ AUDIO_ERROR_NO_INST = 1, /* 0x3 */ AUDIO_ERROR_INVALID_INST_ID = 3, @@ -78,12 +110,14 @@ typedef enum { } SampleMedium; typedef enum { - /* 0 */ CODEC_ADPCM, - /* 1 */ CODEC_S8, + /* 0 */ CODEC_ADPCM, // 16 2-byte samples (32 bytes) compressed into 4-bit samples (8 bytes) + 1 header byte + /* 1 */ CODEC_S8, // 16 2-byte samples (32 bytes) compressed into 8-bit samples (16 bytes) /* 2 */ CODEC_S16_INMEMORY, - /* 3 */ CODEC_SMALL_ADPCM, + /* 3 */ CODEC_SMALL_ADPCM, // 16 2-byte samples (32 bytes) compressed into 2-bit samples (4 bytes) + 1 header byte /* 4 */ CODEC_REVERB, - /* 5 */ CODEC_S16 + /* 5 */ CODEC_S16, + /* 6 */ CODEC_UNK6, + /* 7 */ CODEC_UNK7 // processed as uncompressed samples } SampleCodec; typedef enum { @@ -165,24 +199,28 @@ typedef struct { typedef struct { /* 0x00 */ u32 start; - /* 0x04 */ u32 end; + /* 0x04 */ u32 loopEnd; // numSamples into the sample where the loop ends /* 0x08 */ u32 count; - /* 0x0C */ u32 unk_0C; - /* 0x10 */ s16 state[16]; // only exists if count != 0. 8-byte aligned + /* 0x0C */ u32 sampleEnd; // total number of s16-samples in the + /* 0x10 */ s16 predictorState[16]; // only exists if count != 0. 8-byte aligned } AdpcmLoop; // size = 0x30 (or 0x10) +/** + * The procedure used to design the codeBook is based on an adaptive clustering algorithm. + * The size of the codeBook is (8 * order * numPredictors) and is 8-byte aligned + */ typedef struct { /* 0x00 */ s32 order; - /* 0x04 */ s32 npredictors; - /* 0x08 */ s16 book[1]; // size 8 * order * npredictors. 8-byte aligned + /* 0x04 */ s32 numPredictors; + /* 0x08 */ s16 codeBook[1]; // a table of prediction coefficients that the coder selects from to optimize sound quality. } AdpcmBook; // size >= 0x8 typedef struct { /* 0x00 */ u32 unk_0 : 1; /* 0x00 */ u32 codec : 3; // The state of compression or decompression /* 0x00 */ u32 medium : 2; // Medium where sample is currently stored - /* 0x00 */ u32 unk_bit26 : 1; // Has the sample header been relocated (offsets to pointers) - /* 0x00 */ u32 isRelocated : 1; // Size of the sample + /* 0x00 */ u32 unk_bit26 : 1; + /* 0x00 */ u32 isRelocated : 1; // Has the sample header been relocated (offsets to pointers) /* 0x01 */ u32 size : 24; // Size of the sample /* 0x04 */ u8* sampleAddr; // Raw sample data. Offset from the start of the sample bank or absolute address to either rom or ram /* 0x08 */ AdpcmLoop* loop; // Adpcm loop parameters used by the sample. Offset from the start of the sound font / pointer to ram @@ -194,18 +232,23 @@ typedef struct { /* 0x04 */ f32 tuning; // frequency scale factor } TunedSample; // size = 0x8 +/** + * Stores an entry of decompressed samples in a reverb ring buffer. + * By storing the sample in a ring buffer, the time it takes to loop + * around back to the same sample acts as a delay, leading to an echo effect. + */ typedef struct { /* 0x00 */ s16 numSamplesAfterDownsampling; // never read - /* 0x02 */ s16 chunkLen; // never read + /* 0x02 */ s16 numSamples; // never read /* 0x04 */ s16* toDownsampleLeft; /* 0x08 */ s16* toDownsampleRight; // data pointed to by left and right are adjacent in memory /* 0x0C */ s32 startPos; // start pos in ring buffer - /* 0x10 */ s16 lengthA; // first length in ring buffer (from startPos, at most until end) - /* 0x12 */ s16 lengthB; // second length in ring buffer (from pos 0) - /* 0x14 */ u16 unk_14; - /* 0x16 */ u16 unk_16; - /* 0x18 */ u16 unk_18; -} ReverbRingBufferItem; // size = 0x1C + /* 0x10 */ s16 size; // first length in ring buffer (from startPos, at most until end) + /* 0x12 */ s16 wrappedSize; // second length in ring buffer (from pos 0) + /* 0x14 */ u16 loadResamplePitch; + /* 0x16 */ u16 saveResamplePitch; + /* 0x18 */ u16 saveResampleNumSamples; +} ReverbBufferEntry; // size = 0x1C typedef struct { /* 0x000 */ u8 resampleFlags; @@ -213,35 +256,35 @@ typedef struct { /* 0x002 */ u8 framesToIgnore; /* 0x003 */ u8 curFrame; /* 0x004 */ u8 downsampleRate; - /* 0x005 */ s8 unk_05; - /* 0x006 */ u16 windowSize; - /* 0x008 */ s16 unk_08; - /* 0x00A */ s16 unk_0A; - /* 0x00C */ u16 unk_0C; - /* 0x00E */ u16 unk_0E; + /* 0x005 */ s8 mixReverbIndex; // mix in reverb from this index. set to 0xFF to not mix any + /* 0x006 */ u16 delayNumSamples; // number of samples between echos + /* 0x008 */ s16 mixReverbStrength; // the gain/amount to mix in reverb from mixReverbIndex + /* 0x00A */ s16 volume; + /* 0x00C */ u16 decayRatio; // determines how fast reverb dissipate + /* 0x00E */ u16 downsamplePitch; /* 0x010 */ s16 leakRtl; /* 0x012 */ s16 leakLtr; - /* 0x014 */ u16 unk_14; - /* 0x016 */ s16 unk_16; - /* 0x018 */ u8 unk_18; - /* 0x019 */ s8 unk_19; - /* 0x01A */ u16 unk_1A; - /* 0x01C */ u16 unk_1C; - /* 0x01E */ u8 unk_1E; - /* 0x020 */ s32 nextRingBufPos; - /* 0x024 */ s32 unk_24; // May be bufSizePerChan - /* 0x028 */ s16* leftRingBuf; - /* 0x02C */ s16* rightRingBuf; - /* 0x030 */ void* unk_30; - /* 0x034 */ void* unk_34; - /* 0x038 */ void* unk_38; - /* 0x03C */ void* unk_3C; - /* 0x040 */ ReverbRingBufferItem items[2][5]; - /* 0x158 */ ReverbRingBufferItem items2[2][5]; + /* 0x014 */ u16 subDelay; // number of samples between sub echos + /* 0x016 */ s16 subVolume; // strength of the sub echos + /* 0x018 */ u8 resampleEffectOn; + /* 0x019 */ s8 resampleEffectExtraSamples; + /* 0x01A */ u16 resampleEffectLoadUnk; + /* 0x01C */ u16 resampleEffectSaveUnk; + /* 0x01E */ u8 delayNumSamplesAfterDownsampling; + /* 0x020 */ s32 nextReverbBufPos; + /* 0x024 */ s32 delayNumSamplesUnk; // May be bufSizePerChan + /* 0x028 */ s16* leftReverbBuf; + /* 0x02C */ s16* rightReverbBuf; + /* 0x030 */ s16* leftLoadResampleBuf; + /* 0x034 */ s16* rightLoadResampleBuf; + /* 0x038 */ s16* leftSaveResampleBuf; + /* 0x03C */ s16* rightSaveResampleBuf; + /* 0x040 */ ReverbBufferEntry bufEntry[2][5]; + /* 0x158 */ ReverbBufferEntry subBufEntry[2][5]; /* 0x270 */ s16* filterLeft; /* 0x274 */ s16* filterRight; - /* 0x278 */ s16* unk_278; - /* 0x27C */ s16* unk_27C; + /* 0x278 */ s16* filterLeftInit; + /* 0x27C */ s16* filterRightInit; /* 0x280 */ s16* filterLeftState; /* 0x284 */ s16* filterRightState; /* 0x288 */ TunedSample tunedSample; @@ -363,28 +406,26 @@ typedef struct { /* 0x1C */ EnvelopePoint* envelope; } AdsrState; // size = 0x20 -typedef struct { - /* 0x0 */ u8 unused : 2; - /* 0x0 */ u8 bit2 : 2; - /* 0x0 */ u8 strongRight : 1; - /* 0x0 */ u8 strongLeft : 1; - /* 0x0 */ u8 stereoHeadsetEffects : 1; - /* 0x0 */ u8 usesHeadsetPanEffects : 1; +typedef union { + struct { + /* 0x0 */ u8 unused : 2; + /* 0x0 */ u8 type : 2; + /* 0x0 */ u8 strongRight : 1; + /* 0x0 */ u8 strongLeft : 1; + /* 0x0 */ u8 strongReverbRight : 1; + /* 0x0 */ u8 strongReverbLeft : 1; + }; + /* 0x0 */ u8 asByte; } StereoData; // size = 0x1 -typedef union { - /* 0x0 */ StereoData s; - /* 0x0 */ u8 asByte; -} Stereo; // size = 0x1 - typedef struct { - /* 0x00 */ u8 reverb; + /* 0x00 */ u8 targetReverbVol; /* 0x01 */ u8 gain; // Increases volume by a multiplicative scaling factor. Represented as a UQ4.4 number /* 0x02 */ u8 pan; - /* 0x03 */ u8 unk_3; // Possibly part of stereo? - /* 0x04 */ Stereo stereo; - /* 0x05 */ u8 unk_4; - /* 0x06 */ u16 unk_6; + /* 0x03 */ u8 surroundEffectIndex; + /* 0x04 */ StereoData stereoData; + /* 0x05 */ u8 combFilterSize; + /* 0x06 */ u16 combFilterGain; /* 0x08 */ f32 freqScale; /* 0x0C */ f32 velocity; /* 0x10 */ s16* filter; @@ -421,7 +462,7 @@ typedef struct SequenceChannel { } changes; /* 0x02 */ u8 noteAllocPolicy; /* 0x03 */ u8 muteFlags; - /* 0x04 */ u8 reverb; // or dry/wet mix + /* 0x04 */ u8 targetReverbVol; // or dry/wet mix /* 0x05 */ u8 notePriority; // 0-3 /* 0x06 */ u8 someOtherPriority; /* 0x07 */ u8 fontId; @@ -432,12 +473,12 @@ typedef struct SequenceChannel { /* 0x0C */ u8 gain; // Increases volume by a multiplicative scaling factor. Represented as a UQ4.4 number /* 0x0D */ u8 velocityRandomVariance; /* 0x0E */ u8 gateTimeRandomVariance; - /* 0x0F */ u8 unk_0F; - /* 0x10 */ u8 unk_10; + /* 0x0F */ u8 combFilterSize; + /* 0x10 */ u8 surroundEffectIndex; /* 0x11 */ u8 unk_11; /* 0x12 */ VibratoSubStruct vibrato; /* 0x20 */ u16 delay; - /* 0x22 */ u16 unk_20; + /* 0x22 */ u16 combFilterGain; /* 0x24 */ u16 unk_22; // Used for indexing data /* 0x26 */ s16 instOrWave; // either 0 (none), instrument index + 1, or // 0x80..0x83 for sawtooth/triangle/sine/square waves. @@ -459,7 +500,7 @@ typedef struct SequenceChannel { /* 0xC8 */ s8 soundScriptIO[8]; // bridge between sound script and audio lib, "io ports" /* 0xD0 */ u8* sfxState; // SfxChannelState /* 0xD4 */ s16* filter; - /* 0xD8 */ Stereo stereo; + /* 0xD8 */ StereoData stereoData; /* 0xDC */ s32 startSamplePos; /* 0xE0 */ s32 unk_E0; } SequenceChannel; // size = 0xE4 @@ -474,15 +515,15 @@ typedef struct SequenceLayer { /* 0x00 */ u8 ignoreDrumPan : 1; /* 0x00 */ u8 bit1 : 1; // "has initialized continuous notes"? /* 0x00 */ u8 notePropertiesNeedInit : 1; - /* 0x01 */ Stereo stereo; + /* 0x01 */ StereoData stereoData; /* 0x02 */ u8 instOrWave; /* 0x03 */ u8 gateTime; /* 0x04 */ u8 semitone; /* 0x05 */ u8 portamentoTargetNote; /* 0x06 */ u8 pan; // 0..128 /* 0x07 */ u8 notePan; - /* 0x08 */ u8 unk_08; - /* 0x09 */ u8 unk_09; + /* 0x08 */ u8 surroundEffectIndex; + /* 0x09 */ u8 targetReverbVol; union { struct { /* 0x0A */ u16 bit_0 : 1; @@ -531,45 +572,37 @@ typedef struct SequenceLayer { } SequenceLayer; // size = 0x90 typedef struct { - /* 0x00 */ s16 adpcmdecState[0x10]; - /* 0x20 */ s16 finalResampleState[0x10]; - /* 0x40 */ s16 mixEnvelopeState[0x28]; - /* 0x90 */ s16 panResampleState[0x10]; - /* 0xB0 */ s16 panSamplesBuffer[0x20]; - /* 0xF0 */ s16 dummyResampleState[0x10]; -} NoteSynthesisBuffers; // size = 0x110 + /* 0x000 */ s16 adpcmState[16]; + /* 0x020 */ s16 finalResampleState[16]; + /* 0x040 */ s16 filterState[32]; + /* 0x080 */ s16 unusedState[16]; + /* 0x0A0 */ s16 haasEffectDelayState[32]; + /* 0x0E0 */ s16 combFilterState[128]; + /* 0x1E0 */ s16 surroundEffectState[128]; +} NoteSynthesisBuffers; // size = 0x2E0 typedef struct { - /* 0x00 */ u8 restart_bit0 : 1; - /* 0x00 */ u8 restart_bit1 : 1; - /* 0x00 */ u8 restart_bit2 : 1; - /* 0x00 */ u8 restart_bit3 : 1; - /* 0x00 */ u8 restart_bit4 : 1; - /* 0x00 */ u8 restart_bit5 : 1; - /* 0x00 */ u8 restart_bit6 : 1; - /* 0x00 */ u8 restart_bit7 : 1; + /* 0x00 */ u8 atLoopPoint : 1; + /* 0x00 */ u8 stopLoop : 1; /* 0x01 */ u8 sampleDmaIndex; - /* 0x02 */ u8 prevHeadsetPanRight; - /* 0x03 */ u8 prevHeadsetPanLeft; - /* 0x04 */ u8 reverbVol; + /* 0x02 */ u8 prevHaasEffectLeftDelaySize; + /* 0x03 */ u8 prevHaasEffectRightDelaySize; + /* 0x04 */ u8 curReverbVol; /* 0x05 */ u8 numParts; - /* 0x06 */ u16 samplePosFrac; - /* 0x08 */ u16 unk_08; - /* 0x0C */ s32 samplePosInt; + /* 0x06 */ u16 samplePosFrac; // Fractional part of the sample position + /* 0x08 */ u16 surroundEffectGain; + /* 0x0C */ s32 samplePosInt; // Integer part of the sample position /* 0x10 */ NoteSynthesisBuffers* synthesisBuffers; /* 0x14 */ s16 curVolLeft; /* 0x16 */ s16 curVolRight; - /* 0x18 */ u16 unk_14; - /* 0x1A */ u16 unk_16; - /* 0x1C */ u16 unk_18; - /* 0x1E */ u8 unk_1A; + /* 0x18 */ UNK_TYPE1 unk_14[0x6]; + /* 0x1E */ u8 combFilterNeedsInit; /* 0x1F */ u8 unk_1F; - /* 0x20 */ u16 unk_1C; - /* 0x22 */ u16 unk_1E; + /* 0x20 */ UNK_TYPE1 unk_20[0x4]; } NoteSynthesisState; // size = 0x24 typedef struct { - /* 0x00 */ struct VibratoSubStruct* vibSubStruct; // MM Something else? + /* 0x00 */ struct VibratoSubStruct* vibSubStruct; // Something else? /* 0x04 */ u32 time; /* 0x08 */ s16* curve; /* 0x0C */ f32 extent; @@ -603,67 +636,68 @@ typedef struct { /* 0x34 */ AdsrState adsr; /* 0x54 */ Portamento portamento; /* 0x60 */ VibratoState vibratoState; - /* 0x7C */ char unk_7C[0x8]; + /* 0x7C */ UNK_TYPE1 pad7C[0x4]; + /* 0x80 */ u8 unk_80; /* 0x84 */ u32 startSamplePos; -} NotePlaybackState; // size = 0x88 + /* 0x88 */ UNK_TYPE1 unk_BC[0x1C]; +} NotePlaybackState; // size = 0xA4 typedef struct { struct { /* 0x00 */ volatile u8 enabled : 1; /* 0x00 */ u8 needsInit : 1; - /* 0x00 */ u8 finished : 1; // ? + /* 0x00 */ u8 finished : 1; /* 0x00 */ u8 unused : 1; - /* 0x00 */ u8 stereoStrongRight : 1; - /* 0x00 */ u8 stereoStrongLeft : 1; - /* 0x00 */ u8 stereoHeadsetEffects : 1; - /* 0x00 */ u8 usesHeadsetPanEffects : 1; // ? + /* 0x00 */ u8 strongRight : 1; + /* 0x00 */ u8 strongLeft : 1; + /* 0x00 */ u8 strongReverbRight : 1; + /* 0x00 */ u8 strongReverbLeft : 1; } bitField0; struct { /* 0x01 */ u8 reverbIndex : 3; /* 0x01 */ u8 bookOffset : 2; /* 0x01 */ u8 isSyntheticWave : 1; /* 0x01 */ u8 hasTwoParts : 1; - /* 0x01 */ u8 usesHeadsetPanEffects2 : 1; + /* 0x01 */ u8 useHaasEffect : 1; } bitField1; /* 0x02 */ u8 gain; // Increases volume by a multiplicative scaling factor. Represented as a UQ4.4 number - /* 0x03 */ u8 headsetPanRight; - /* 0x04 */ u8 headsetPanLeft; - /* 0x05 */ u8 reverbVol; + /* 0x03 */ u8 haasEffectLeftDelaySize; + /* 0x04 */ u8 haasEffectRightDelaySize; + /* 0x05 */ u8 targetReverbVol; /* 0x06 */ u8 harmonicIndexCurAndPrev; // bits 3..2 store curHarmonicIndex, bits 1..0 store prevHarmonicIndex - /* 0x07 */ u8 unk_07; + /* 0x07 */ u8 combFilterSize; /* 0x08 */ u16 targetVolLeft; /* 0x0A */ u16 targetVolRight; - /* 0x0C */ u16 resamplingRateFixedPoint; - /* 0x0E */ u16 unk_0E; + /* 0x0C */ u16 frequencyFixedPoint; + /* 0x0E */ u16 combFilterGain; union { /* 0x10 */ TunedSample* tunedSample; /* 0x10 */ s16* waveSampleAddr; // used for synthetic waves }; /* 0x14 */ s16* filter; - /* 0x18 */ u8 unk_18; - /* 0x19 */ u8 unk_19; - /* 0x1A */ UNK_TYPE1 pad_1A[0x6]; -} NoteSubEu; // size = 0x20 + /* 0x18 */ UNK_TYPE1 unk_18; + /* 0x19 */ u8 surroundEffectIndex; + /* 0x1A */ UNK_TYPE1 unk_1A[0x6]; +} NoteSampleState; // size = 0x20 typedef struct Note { /* 0x00 */ AudioListItem listItem; /* 0x10 */ NoteSynthesisState synthesisState; /* 0x34 */ NotePlaybackState playbackState; - /* 0xBC */ char unk_BC[0x1C]; - /* 0xD8 */ NoteSubEu noteSubEu; + /* 0xD8 */ NoteSampleState sampleState; } Note; // size = 0xF8 typedef struct { /* 0x00 */ u8 downsampleRate; - /* 0x02 */ u16 windowSize; - /* 0x04 */ u16 unk_4; - /* 0x06 */ u16 unk_6; - /* 0x08 */ u16 unk_8; - /* 0x0A */ u16 unk_A; + /* 0x02 */ u16 delayNumSamples; + /* 0x04 */ u16 decayRatio; // determines how fast reverb dissipates + /* 0x06 */ u16 subDelay; + /* 0x08 */ u16 subVolume; + /* 0x0A */ u16 volume; /* 0x0C */ u16 leakRtl; /* 0x0E */ u16 leakLtr; - /* 0x10 */ s8 unk_10; - /* 0x12 */ u16 unk_12; + /* 0x10 */ s8 mixReverbIndex; + /* 0x12 */ u16 mixReverbStrength; /* 0x14 */ s16 lowPassFilterCutoffLeft; /* 0x16 */ s16 lowPassFilterCutoffRight; } ReverbSettings; // size = 0x18 @@ -704,13 +738,13 @@ typedef struct { /* 0x00 */ s16 specUnk4; /* 0x02 */ u16 samplingFreq; // Target sampling rate in Hz /* 0x04 */ u16 aiSamplingFreq; // True sampling rate set to the audio interface (AI) for the audio digital-analog converter (DAC) - /* 0x06 */ s16 samplesPerFrameTarget; - /* 0x08 */ s16 maxAiBufNumSamples; - /* 0x0A */ s16 minAiBufNumSamples; + /* 0x06 */ s16 numSamplesPerFrameTarget; + /* 0x08 */ s16 numSamplesPerFrameMax; + /* 0x0A */ s16 numSamplesPerFrameMin; /* 0x0C */ s16 updatesPerFrame; // for each frame of the audio thread (default 60 fps), number of updates to process audio - /* 0x0E */ s16 samplesPerUpdate; - /* 0x10 */ s16 samplesPerUpdateMax; - /* 0x12 */ s16 samplesPerUpdateMin; + /* 0x0E */ s16 numSamplesPerUpdate; + /* 0x10 */ s16 numSamplesPerUpdateMax; + /* 0x12 */ s16 numSamplesPerUpdateMin; /* 0x14 */ s16 numSequencePlayers; /* 0x18 */ f32 resampleRate; /* 0x1C */ f32 updatesPerFrameInv; // inverse (reciprocal) of updatesPerFrame @@ -899,8 +933,8 @@ typedef struct { /* 0x0002 */ u16 unk_2; // reads from audio spec unk_14, never used, always set to 0x7FFF /* 0x0004 */ u16 unk_4; /* 0x0006 */ char unk_0006[0xA]; - /* 0x0010 */ s16* curLoadedBook; - /* 0x0014 */ NoteSubEu* noteSubsEu; + /* 0x0010 */ s16* adpcmCodeBook; + /* 0x0014 */ NoteSampleState* sampleStateList; /* 0x0018 */ SynthesisReverb synthesisReverbs[4]; /* 0x0B58 */ char unk_0B58[0x30]; /* 0x0B88 */ Sample* usedSamples[128]; @@ -1002,7 +1036,7 @@ typedef struct { /* 0x4460 */ SequencePlayer seqPlayers[5]; /* 0x4B40 */ SequenceLayer sequenceLayers[80]; /* 0x7840 */ SequenceChannel sequenceChannelNone; - /* 0x7924 */ s32 noteSubEuOffset; + /* 0x7924 */ s32 sampleStateOffset; // Start of the list of sample states for this update. Resets after each audio frame. /* 0x7928 */ AudioListItem layerFreeList; /* 0x7938 */ NotePool noteFreeLists; /* 0x7978 */ u8 cmdWritePos; @@ -1023,17 +1057,17 @@ typedef struct { } AudioContext; // size = 0x81F8 typedef struct { - /* 0x00 */ u8 reverbVol; + /* 0x00 */ u8 targetReverbVol; /* 0x01 */ u8 gain; // Increases volume by a multiplicative scaling factor. Represented as a UQ4.4 number /* 0x02 */ u8 pan; - /* 0x03 */ u8 unk_3; - /* 0x04 */ Stereo stereo; + /* 0x03 */ u8 surroundEffectIndex; + /* 0x04 */ StereoData stereoData; /* 0x08 */ f32 frequency; /* 0x0C */ f32 velocity; /* 0x10 */ char unk_0C[0x4]; /* 0x14 */ s16* filter; - /* 0x18 */ u8 unk_14; - /* 0x1A */ u16 unk_16; + /* 0x18 */ u8 combFilterSize; + /* 0x1A */ u16 combFilterGain; } NoteSubAttributes; // size = 0x1A typedef struct { diff --git a/spec b/spec index 4dec1f228..100e615cf 100644 --- a/spec +++ b/spec @@ -608,7 +608,6 @@ beginseg pad_text include "build/src/code/audio/audio_data.o" include "build/src/code/audio/audio_synthesis.o" - include "build/data/code/audio_synthesis.data.o" include "build/src/code/audio/audio_heap.o" include "build/data/code/audio_heap.bss.o" include "build/src/code/audio/audio_load.o" diff --git a/src/code/audio/audio_data.c b/src/code/audio/audio_data.c index 7238a4bfa..eb931262b 100644 --- a/src/code/audio/audio_data.c +++ b/src/code/audio/audio_data.c @@ -857,22 +857,99 @@ EnvelopePoint gDefaultEnvelope[] = { { ADSR_DISABLE, 0 }, }; -NoteSubEu gZeroNoteSub = { 0 }; +NoteSampleState gZeroedSampleState = { 0 }; -NoteSubEu gDefaultNoteSub = { - { 1, 1, 0, 0, 0, 0, 0, 0 }, { 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +NoteSampleState gDefaultSampleState = { + { true, true, false, false, false, false, false, false }, + { 0 }, + 0, // gain + 0, // haasEffectLeftDelaySize + 0, // haasEffectRightDelaySize + 0, // targetReverbVol + 0, // harmonicIndexCurAndPrev + 0, // combFilterSize + 0, // targetVolLeft + 0, // targetVolRight + 0, // frequencyFixedPoint + 0, // combFilterGain + NULL, // tunedSample + NULL, // filter + 0, // unk_18 + 0, // surroundEffectIndex + 0, // unk_1A }; -u16 gHeadsetPanQuantization[64] = { - 60, 58, 56, 54, 52, 50, 48, 46, 44, 42, 40, 38, 36, 34, 32, 30, 28, 26, 24, 22, 20, 18, - 16, 14, 12, 10, 8, 6, 4, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +u16 gHaasEffectDelaySize[64] = { + 30 * SAMPLE_SIZE, + 29 * SAMPLE_SIZE, + 28 * SAMPLE_SIZE, + 27 * SAMPLE_SIZE, + 26 * SAMPLE_SIZE, + 25 * SAMPLE_SIZE, + 24 * SAMPLE_SIZE, + 23 * SAMPLE_SIZE, + 22 * SAMPLE_SIZE, + 21 * SAMPLE_SIZE, + 20 * SAMPLE_SIZE, + 19 * SAMPLE_SIZE, + 18 * SAMPLE_SIZE, + 17 * SAMPLE_SIZE, + 16 * SAMPLE_SIZE, + 15 * SAMPLE_SIZE, + 14 * SAMPLE_SIZE, + 13 * SAMPLE_SIZE, + 12 * SAMPLE_SIZE, + 11 * SAMPLE_SIZE, + 10 * SAMPLE_SIZE, + 9 * SAMPLE_SIZE, + 8 * SAMPLE_SIZE, + 7 * SAMPLE_SIZE, + 6 * SAMPLE_SIZE, + 5 * SAMPLE_SIZE, + 4 * SAMPLE_SIZE, + 3 * SAMPLE_SIZE, + 2 * SAMPLE_SIZE, + 1 * SAMPLE_SIZE, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, }; s32 D_801D58A4 = 0; // clang-format off -s16 D_801D58A8[] = { +s16 gInvalidAdpcmCodeBook[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, diff --git a/src/code/audio/audio_heap.c b/src/code/audio/audio_heap.c index 667cd1c40..8412220a3 100644 --- a/src/code/audio/audio_heap.c +++ b/src/code/audio/audio_heap.c @@ -10,7 +10,7 @@ void AudioHeap_DiscardSampleCaches(void); void AudioHeap_DiscardSampleBank(s32 sampleBankId); void AudioHeap_ApplySampleBankCacheInternal(s32 apply, s32 sampleBankId); void AudioHeap_DiscardSampleBanks(void); -void AudioHeap_InitReverb(s32 reverbIndex, ReverbSettings* settings, s32 flags); +void AudioHeap_InitReverb(s32 reverbIndex, ReverbSettings* settings, s32 isFirstInit); #define gTatumsPerBeat (gAudioTatumInit[1]) @@ -421,7 +421,7 @@ void* AudioHeap_AllocCached(s32 tableType, size_t size, s32 cache, s32 id) { if (loadStatusEntry0 == LOAD_STATUS_MAYBE_DISCARDABLE) { for (i = 0; i < gAudioContext.numNotes; i++) { if ((gAudioContext.notes[i].playbackState.fontId == temporaryCache->entries[0].id) && - gAudioContext.notes[i].noteSubEu.bitField0.enabled) { + gAudioContext.notes[i].sampleState.bitField0.enabled) { break; } } @@ -435,7 +435,7 @@ void* AudioHeap_AllocCached(s32 tableType, size_t size, s32 cache, s32 id) { if (loadStatusEntry1 == LOAD_STATUS_MAYBE_DISCARDABLE) { for (i = 0; i < gAudioContext.numNotes; i++) { if ((gAudioContext.notes[i].playbackState.fontId == temporaryCache->entries[1].id) && - gAudioContext.notes[i].noteSubEu.bitField0.enabled) { + gAudioContext.notes[i].sampleState.bitField0.enabled) { break; } } @@ -491,7 +491,7 @@ void* AudioHeap_AllocCached(s32 tableType, size_t size, s32 cache, s32 id) { if (loadStatusEntry0 == LOAD_STATUS_COMPLETE) { for (i = 0; i < gAudioContext.numNotes; i++) { if ((gAudioContext.notes[i].playbackState.fontId == temporaryCache->entries[0].id) && - gAudioContext.notes[i].noteSubEu.bitField0.enabled) { + gAudioContext.notes[i].sampleState.bitField0.enabled) { break; } } @@ -504,7 +504,7 @@ void* AudioHeap_AllocCached(s32 tableType, size_t size, s32 cache, s32 id) { if (loadStatusEntry1 == LOAD_STATUS_COMPLETE) { for (i = 0; i < gAudioContext.numNotes; i++) { if ((gAudioContext.notes[i].playbackState.fontId == temporaryCache->entries[1].id) && - gAudioContext.notes[i].noteSubEu.bitField0.enabled) { + gAudioContext.notes[i].sampleState.bitField0.enabled) { break; } } @@ -814,7 +814,7 @@ void AudioHeap_UpdateReverb(SynthesisReverb* reverb) { void AudioHeap_UpdateReverbs(void) { s32 count; - s32 i; + s32 reverbIndex; s32 j; if (gAudioContext.audioBufferParameters.specUnk4 == 2) { @@ -823,9 +823,9 @@ void AudioHeap_UpdateReverbs(void) { count = 1; } - for (i = 0; i < gAudioContext.numSynthesisReverbs; i++) { + for (reverbIndex = 0; reverbIndex < gAudioContext.numSynthesisReverbs; reverbIndex++) { for (j = 0; j < count; j++) { - AudioHeap_UpdateReverb(&gAudioContext.synthesisReverbs[i]); + AudioHeap_UpdateReverb(&gAudioContext.synthesisReverbs[reverbIndex]); } } } @@ -837,7 +837,7 @@ void AudioHeap_ClearAiBuffers(void) { s32 curAiBufferIndex = gAudioContext.curAiBufferIndex; s32 i; - gAudioContext.aiBufNumSamples[curAiBufferIndex] = gAudioContext.audioBufferParameters.minAiBufNumSamples; + gAudioContext.aiBufNumSamples[curAiBufferIndex] = gAudioContext.audioBufferParameters.numSamplesPerFrameMin; for (i = 0; i < AIBUF_LEN; i++) { gAudioContext.aiBuffers[curAiBufferIndex][i] = 0; @@ -870,7 +870,7 @@ s32 AudioHeap_ResetStep(void) { AudioHeap_UpdateReverbs(); } else { for (i = 0; i < gAudioContext.numNotes; i++) { - if (gAudioContext.notes[i].noteSubEu.bitField0.enabled && + if (gAudioContext.notes[i].sampleState.bitField0.enabled && gAudioContext.notes[i].playbackState.adsr.action.s.state != ADSR_STATE_DISABLED) { gAudioContext.notes[i].playbackState.adsr.fadeOutVel = gAudioContext.audioBufferParameters.updatesPerFrameInv; @@ -907,7 +907,7 @@ s32 AudioHeap_ResetStep(void) { AudioHeap_Init(); gAudioContext.resetStatus = 0; for (i = 0; i < ARRAY_COUNT(gAudioContext.aiBufNumSamples); i++) { - gAudioContext.aiBufNumSamples[i] = gAudioContext.audioBufferParameters.maxAiBufNumSamples; + gAudioContext.aiBufNumSamples[i] = gAudioContext.audioBufferParameters.numSamplesPerFrameMax; for (j = 0; j < AIBUF_LEN; j++) { gAudioContext.aiBuffers[i][j] = 0; } @@ -930,8 +930,8 @@ void AudioHeap_Init(void) { size_t cachePoolSize; size_t miscPoolSize; u32 intMask; + s32 reverbIndex; s32 i; - s32 j; s32 pad2; AudioSpec* spec = &gAudioSpecs[gAudioContext.audioResetSpecIdToLoad]; // Audio Specifications @@ -942,19 +942,22 @@ void AudioHeap_Init(void) { gAudioContext.audioBufferParameters.aiSamplingFreq = osAiSetFrequency(gAudioContext.audioBufferParameters.samplingFreq); - gAudioContext.audioBufferParameters.samplesPerFrameTarget = + gAudioContext.audioBufferParameters.numSamplesPerFrameTarget = ALIGN16(gAudioContext.audioBufferParameters.samplingFreq / gAudioContext.refreshRate); - gAudioContext.audioBufferParameters.minAiBufNumSamples = - gAudioContext.audioBufferParameters.samplesPerFrameTarget - 0x10; - gAudioContext.audioBufferParameters.maxAiBufNumSamples = - gAudioContext.audioBufferParameters.samplesPerFrameTarget + 0x10; + gAudioContext.audioBufferParameters.numSamplesPerFrameMin = + gAudioContext.audioBufferParameters.numSamplesPerFrameTarget - 0x10; + gAudioContext.audioBufferParameters.numSamplesPerFrameMax = + gAudioContext.audioBufferParameters.numSamplesPerFrameTarget + 0x10; gAudioContext.audioBufferParameters.updatesPerFrame = - ((gAudioContext.audioBufferParameters.samplesPerFrameTarget + 0x10) / 0xD0) + 1; - gAudioContext.audioBufferParameters.samplesPerUpdate = (gAudioContext.audioBufferParameters.samplesPerFrameTarget / - gAudioContext.audioBufferParameters.updatesPerFrame) & - ~7; - gAudioContext.audioBufferParameters.samplesPerUpdateMax = gAudioContext.audioBufferParameters.samplesPerUpdate + 8; - gAudioContext.audioBufferParameters.samplesPerUpdateMin = gAudioContext.audioBufferParameters.samplesPerUpdate - 8; + ((gAudioContext.audioBufferParameters.numSamplesPerFrameTarget + 0x10) / 0xD0) + 1; + gAudioContext.audioBufferParameters.numSamplesPerUpdate = + (gAudioContext.audioBufferParameters.numSamplesPerFrameTarget / + gAudioContext.audioBufferParameters.updatesPerFrame) & + ~7; + gAudioContext.audioBufferParameters.numSamplesPerUpdateMax = + gAudioContext.audioBufferParameters.numSamplesPerUpdate + 8; + gAudioContext.audioBufferParameters.numSamplesPerUpdateMin = + gAudioContext.audioBufferParameters.numSamplesPerUpdate - 8; gAudioContext.audioBufferParameters.resampleRate = 32000.0f / (s32)gAudioContext.audioBufferParameters.samplingFreq; gAudioContext.audioBufferParameters.updatesPerFrameInvScaled = (1.0f / 256.0f) / gAudioContext.audioBufferParameters.updatesPerFrame; @@ -984,13 +987,13 @@ void AudioHeap_Init(void) { gAudioContext.unk_2870 /= gAudioContext.tempoInternalToExternal; gAudioContext.audioBufferParameters.specUnk4 = spec->unk_04; - gAudioContext.audioBufferParameters.samplesPerFrameTarget *= gAudioContext.audioBufferParameters.specUnk4; - gAudioContext.audioBufferParameters.maxAiBufNumSamples *= gAudioContext.audioBufferParameters.specUnk4; - gAudioContext.audioBufferParameters.minAiBufNumSamples *= gAudioContext.audioBufferParameters.specUnk4; + gAudioContext.audioBufferParameters.numSamplesPerFrameTarget *= gAudioContext.audioBufferParameters.specUnk4; + gAudioContext.audioBufferParameters.numSamplesPerFrameMax *= gAudioContext.audioBufferParameters.specUnk4; + gAudioContext.audioBufferParameters.numSamplesPerFrameMin *= gAudioContext.audioBufferParameters.specUnk4; gAudioContext.audioBufferParameters.updatesPerFrame *= gAudioContext.audioBufferParameters.specUnk4; if (gAudioContext.audioBufferParameters.specUnk4 >= 2) { - gAudioContext.audioBufferParameters.maxAiBufNumSamples -= 0x10; + gAudioContext.audioBufferParameters.numSamplesPerFrameMax -= 0x10; } // Determine the maximum allowable number of audio command list entries for the rsp microcode @@ -1037,13 +1040,13 @@ void AudioHeap_Init(void) { gAudioContext.notes = AudioHeap_AllocZeroed(&gAudioContext.miscPool, gAudioContext.numNotes * sizeof(Note)); AudioPlayback_NoteInitAll(); AudioPlayback_InitNoteFreeList(); - gAudioContext.noteSubsEu = + gAudioContext.sampleStateList = AudioHeap_AllocZeroed(&gAudioContext.miscPool, gAudioContext.audioBufferParameters.updatesPerFrame * - gAudioContext.numNotes * sizeof(NoteSubEu)); + gAudioContext.numNotes * sizeof(NoteSampleState)); // Initialize audio binary interface command list buffer - for (j = 0; j < ARRAY_COUNT(gAudioContext.abiCmdBufs); j++) { - gAudioContext.abiCmdBufs[j] = + for (i = 0; i < ARRAY_COUNT(gAudioContext.abiCmdBufs); i++) { + gAudioContext.abiCmdBufs[i] = AudioHeap_AllocDmaMemoryZeroed(&gAudioContext.miscPool, gAudioContext.maxAudioCmds * sizeof(Acmd)); } @@ -1052,20 +1055,20 @@ void AudioHeap_Init(void) { AudioHeap_InitAdsrDecayTable(); // Initialize reverbs - for (i = 0; i < ARRAY_COUNT(gAudioContext.synthesisReverbs); i++) { - gAudioContext.synthesisReverbs[i].useReverb = 0; + for (reverbIndex = 0; reverbIndex < ARRAY_COUNT(gAudioContext.synthesisReverbs); reverbIndex++) { + gAudioContext.synthesisReverbs[reverbIndex].useReverb = 0; } gAudioContext.numSynthesisReverbs = spec->numReverbs; - for (i = 0; i < gAudioContext.numSynthesisReverbs; i++) { - AudioHeap_InitReverb(i, &spec->reverbSettings[i], 1); + for (reverbIndex = 0; reverbIndex < gAudioContext.numSynthesisReverbs; reverbIndex++) { + AudioHeap_InitReverb(reverbIndex, &spec->reverbSettings[reverbIndex], true); } // Initialize sequence players AudioSeq_InitSequencePlayers(); - for (j = 0; j < gAudioContext.audioBufferParameters.numSequencePlayers; j++) { - AudioSeq_InitSequencePlayerChannels(j); - AudioSeq_ResetSequencePlayer(&gAudioContext.seqPlayers[j]); + for (i = 0; i < gAudioContext.audioBufferParameters.numSequencePlayers; i++) { + AudioSeq_InitSequencePlayerChannels(i); + AudioSeq_ResetSequencePlayer(&gAudioContext.seqPlayers[i]); } // Initialize two additional caches on the audio heap to store individual audio samples @@ -1529,149 +1532,165 @@ void AudioHeap_DiscardSampleBanks(void) { } } -void AudioHeap_SetReverbData(s32 reverbIndex, u32 dataType, s32 data, s32 flags) { - s32 windowSize; +void AudioHeap_SetReverbData(s32 reverbIndex, u32 dataType, s32 data, s32 isFirstInit) { + s32 delayNumSamples; SynthesisReverb* reverb = &gAudioContext.synthesisReverbs[reverbIndex]; switch (dataType) { - case 0: - AudioHeap_InitReverb(reverbIndex, (ReverbSettings*)data, 0); + case REVERB_DATA_TYPE_SETTINGS: + AudioHeap_InitReverb(reverbIndex, (ReverbSettings*)data, false); break; - case 1: + + case REVERB_DATA_TYPE_DELAY: if (data < 4) { data = 4; } - windowSize = data * 64; - if (windowSize < 0x100) { - windowSize = 0x100; + delayNumSamples = data * 64; + if (delayNumSamples < (16 * SAMPLES_PER_FRAME)) { + delayNumSamples = 16 * SAMPLES_PER_FRAME; } - windowSize /= reverb->downsampleRate; + delayNumSamples /= reverb->downsampleRate; - if (flags == 0) { - if (reverb->unk_1E >= (data / reverb->downsampleRate)) { - if ((reverb->nextRingBufPos >= windowSize) || (reverb->unk_24 >= windowSize)) { - reverb->nextRingBufPos = 0; - reverb->unk_24 = 0; - } - } else { + if (!isFirstInit) { + if (reverb->delayNumSamplesAfterDownsampling < (data / reverb->downsampleRate)) { break; } + if ((reverb->nextReverbBufPos >= delayNumSamples) || (reverb->delayNumSamplesUnk >= delayNumSamples)) { + reverb->nextReverbBufPos = 0; + reverb->delayNumSamplesUnk = 0; + } } - reverb->windowSize = windowSize; + reverb->delayNumSamples = delayNumSamples; - if ((reverb->downsampleRate != 1) || reverb->unk_18) { - reverb->unk_0E = 0x8000 / reverb->downsampleRate; - if (reverb->unk_30 == NULL) { - reverb->unk_30 = AudioHeap_AllocZeroed(&gAudioContext.miscPool, 0x20); - reverb->unk_34 = AudioHeap_AllocZeroed(&gAudioContext.miscPool, 0x20); - reverb->unk_38 = AudioHeap_AllocZeroed(&gAudioContext.miscPool, 0x20); - reverb->unk_3C = AudioHeap_AllocZeroed(&gAudioContext.miscPool, 0x20); - if (reverb->unk_3C == NULL) { + if ((reverb->downsampleRate != 1) || reverb->resampleEffectOn) { + reverb->downsamplePitch = 0x8000 / reverb->downsampleRate; + if (reverb->leftLoadResampleBuf == NULL) { + reverb->leftLoadResampleBuf = + AudioHeap_AllocZeroed(&gAudioContext.miscPool, sizeof(RESAMPLE_STATE)); + reverb->rightLoadResampleBuf = + AudioHeap_AllocZeroed(&gAudioContext.miscPool, sizeof(RESAMPLE_STATE)); + reverb->leftSaveResampleBuf = + AudioHeap_AllocZeroed(&gAudioContext.miscPool, sizeof(RESAMPLE_STATE)); + reverb->rightSaveResampleBuf = + AudioHeap_AllocZeroed(&gAudioContext.miscPool, sizeof(RESAMPLE_STATE)); + if (reverb->rightSaveResampleBuf == NULL) { reverb->downsampleRate = 1; } } } break; - case 2: - gAudioContext.synthesisReverbs[reverbIndex].unk_0C = data; + + case REVERB_DATA_TYPE_DECAY: + gAudioContext.synthesisReverbs[reverbIndex].decayRatio = data; break; - case 3: - gAudioContext.synthesisReverbs[reverbIndex].unk_16 = data; + + case REVERB_DATA_TYPE_SUB_VOLUME: + gAudioContext.synthesisReverbs[reverbIndex].subVolume = data; break; - case 4: - gAudioContext.synthesisReverbs[reverbIndex].unk_0A = data; + + case REVERB_DATA_TYPE_VOLUME: + gAudioContext.synthesisReverbs[reverbIndex].volume = data; break; - case 5: + + case REVERB_DATA_TYPE_LEAK_RIGHT: gAudioContext.synthesisReverbs[reverbIndex].leakRtl = data; break; - case 6: + + case REVERB_DATA_TYPE_LEAK_LEFT: gAudioContext.synthesisReverbs[reverbIndex].leakLtr = data; break; - case 7: + + case REVERB_DATA_TYPE_FILTER_LEFT: if (data != 0) { - if ((flags != 0) || (reverb->unk_278 == 0)) { - reverb->filterLeftState = AudioHeap_AllocDmaMemoryZeroed(&gAudioContext.miscPool, 0x40); - reverb->unk_278 = AudioHeap_AllocDmaMemory(&gAudioContext.miscPool, 0x10); + if (isFirstInit || (reverb->filterLeftInit == NULL)) { + reverb->filterLeftState = AudioHeap_AllocDmaMemoryZeroed(&gAudioContext.miscPool, + 2 * (FILTER_BUF_PART1 + FILTER_BUF_PART2)); + reverb->filterLeftInit = AudioHeap_AllocDmaMemory(&gAudioContext.miscPool, FILTER_SIZE); } - reverb->filterLeft = reverb->unk_278; - if (reverb->filterLeft != 0) { + reverb->filterLeft = reverb->filterLeftInit; + if (reverb->filterLeft != NULL) { AudioHeap_LoadLowPassFilter(reverb->filterLeft, data); } } else { - reverb->filterLeft = 0; + reverb->filterLeft = NULL; - if (flags != 0) { - reverb->unk_278 = 0; + if (isFirstInit) { + reverb->filterLeftInit = NULL; } } - break; - case 8: + + case REVERB_DATA_TYPE_FILTER_RIGHT: if (data != 0) { - if ((flags != 0) || (reverb->unk_27C == 0)) { - reverb->filterRightState = AudioHeap_AllocDmaMemoryZeroed(&gAudioContext.miscPool, 0x40); - reverb->unk_27C = AudioHeap_AllocDmaMemory(&gAudioContext.miscPool, 0x10); + if (isFirstInit || (reverb->filterRightInit == NULL)) { + reverb->filterRightState = AudioHeap_AllocDmaMemoryZeroed( + &gAudioContext.miscPool, 2 * (FILTER_BUF_PART1 + FILTER_BUF_PART2)); + reverb->filterRightInit = AudioHeap_AllocDmaMemory(&gAudioContext.miscPool, FILTER_SIZE); } - reverb->filterRight = reverb->unk_27C; - if (reverb->unk_27C != 0) { - AudioHeap_LoadLowPassFilter(reverb->unk_27C, data); + reverb->filterRight = reverb->filterRightInit; + if (reverb->filterRight != NULL) { + AudioHeap_LoadLowPassFilter(reverb->filterRight, data); } } else { - reverb->filterRight = 0; - if (flags != 0) { - reverb->unk_27C = 0; + reverb->filterRight = NULL; + if (isFirstInit) { + reverb->filterRightInit = NULL; } } break; - case 9: - reverb->unk_19 = data; + + case REVERB_DATA_TYPE_9: + reverb->resampleEffectExtraSamples = data; if (data == 0) { - reverb->unk_18 = false; + reverb->resampleEffectOn = false; } else { - reverb->unk_18 = true; + reverb->resampleEffectOn = true; } break; + default: break; } } -void AudioHeap_InitReverb(s32 reverbIndex, ReverbSettings* settings, s32 flags) { +void AudioHeap_InitReverb(s32 reverbIndex, ReverbSettings* settings, s32 isFirstInit) { SynthesisReverb* reverb = &gAudioContext.synthesisReverbs[reverbIndex]; - if (flags != 0) { - reverb->unk_1E = settings->windowSize / settings->downsampleRate; - reverb->unk_30 = 0; - } else if (reverb->unk_1E < (settings->windowSize / settings->downsampleRate)) { + if (isFirstInit) { + reverb->delayNumSamplesAfterDownsampling = settings->delayNumSamples / settings->downsampleRate; + reverb->leftLoadResampleBuf = NULL; + } else if (reverb->delayNumSamplesAfterDownsampling < (settings->delayNumSamples / settings->downsampleRate)) { return; } reverb->downsampleRate = settings->downsampleRate; - reverb->unk_18 = false; - reverb->unk_19 = 0; - reverb->unk_1A = 0; - reverb->unk_1C = 0; - AudioHeap_SetReverbData(reverbIndex, 1, settings->windowSize, flags); - reverb->unk_0C = settings->unk_4; - reverb->unk_0A = settings->unk_A; - reverb->unk_14 = settings->unk_6 << 6; - reverb->unk_16 = settings->unk_8; + reverb->resampleEffectOn = false; + reverb->resampleEffectExtraSamples = 0; + reverb->resampleEffectLoadUnk = 0; + reverb->resampleEffectSaveUnk = 0; + AudioHeap_SetReverbData(reverbIndex, REVERB_DATA_TYPE_DELAY, settings->delayNumSamples, isFirstInit); + reverb->decayRatio = settings->decayRatio; + reverb->volume = settings->volume; + reverb->subDelay = settings->subDelay * 64; + reverb->subVolume = settings->subVolume; reverb->leakRtl = settings->leakRtl; reverb->leakLtr = settings->leakLtr; - reverb->unk_05 = settings->unk_10; - reverb->unk_08 = settings->unk_12; - reverb->useReverb = 8; + reverb->mixReverbIndex = settings->mixReverbIndex; + reverb->mixReverbStrength = settings->mixReverbStrength; + reverb->useReverb = 8; // used as a boolean - if (flags != 0) { - reverb->leftRingBuf = AudioHeap_AllocZeroedAttemptExternal(&gAudioContext.miscPool, reverb->windowSize * 2); - reverb->rightRingBuf = AudioHeap_AllocZeroedAttemptExternal(&gAudioContext.miscPool, reverb->windowSize * 2); + if (isFirstInit) { + reverb->leftReverbBuf = + AudioHeap_AllocZeroedAttemptExternal(&gAudioContext.miscPool, reverb->delayNumSamples * 2); + reverb->rightReverbBuf = + AudioHeap_AllocZeroedAttemptExternal(&gAudioContext.miscPool, reverb->delayNumSamples * 2); reverb->resampleFlags = 1; - reverb->nextRingBufPos = 0; - reverb->unk_24 = 0; + reverb->nextReverbBufPos = 0; + reverb->delayNumSamplesUnk = 0; reverb->curFrame = 0; reverb->framesToIgnore = 2; } @@ -1681,12 +1700,13 @@ void AudioHeap_InitReverb(s32 reverbIndex, ReverbSettings* settings, s32 flags) reverb->tunedSample.tuning = 1.0f; reverb->sample.codec = CODEC_REVERB; reverb->sample.medium = MEDIUM_RAM; - reverb->sample.size = reverb->windowSize * 2; - reverb->sample.sampleAddr = (u8*)reverb->leftRingBuf; + reverb->sample.size = reverb->delayNumSamples * SAMPLE_SIZE; + reverb->sample.sampleAddr = (u8*)reverb->leftReverbBuf; reverb->loop.start = 0; reverb->loop.count = 1; - reverb->loop.end = reverb->windowSize; + reverb->loop.loopEnd = reverb->delayNumSamples; - AudioHeap_SetReverbData(reverbIndex, 7, settings->lowPassFilterCutoffLeft, flags); - AudioHeap_SetReverbData(reverbIndex, 8, settings->lowPassFilterCutoffRight, flags); + AudioHeap_SetReverbData(reverbIndex, REVERB_DATA_TYPE_FILTER_LEFT, settings->lowPassFilterCutoffLeft, isFirstInit); + AudioHeap_SetReverbData(reverbIndex, REVERB_DATA_TYPE_FILTER_RIGHT, settings->lowPassFilterCutoffRight, + isFirstInit); } diff --git a/src/code/audio/audio_init_params.c b/src/code/audio/audio_init_params.c index 81c49b30c..59c6658ac 100644 --- a/src/code/audio/audio_init_params.c +++ b/src/code/audio/audio_init_params.c @@ -1,12 +1,184 @@ #include "global.h" const s16 gAudioTatumInit[] = { - 0x1C00, // unused - 0x30, // gTatumsPerBeat + 0x1C00, // unused + TATUMS_PER_BEAT, // gTatumsPerBeat }; +// TODO: Extract from table? +#define NUM_SOUNDFONTS 41 +#define SFX_SEQ_SIZE 0xC6A0 +#define AMBIENCE_SEQ_SIZE 0xFC0 +#define SOUNDFONT_0_SIZE 0x81C0 +#define SOUNDFONT_1_SIZE 0x36D0 +#define SOUNDFONT_2_SIZE 0xCE0 + +// Sizes of everything on the init pool +#define AI_BUFFERS_SIZE (AIBUF_SIZE * ARRAY_COUNT(gAudioContext.aiBuffers)) +#define SOUNDFONT_LIST_SIZE (NUM_SOUNDFONTS * sizeof(SoundFont)) + +// 0x19BD0 +#define PERMANENT_POOL_SIZE \ + (SFX_SEQ_SIZE + AMBIENCE_SEQ_SIZE + SOUNDFONT_0_SIZE + SOUNDFONT_1_SIZE + SOUNDFONT_2_SIZE + 0x430) + const AudioHeapInitSizes gAudioHeapInitSizes = { - 0x137F00, // heapSize - 0x1C480, // initPoolSize - 0x1A000, // permanentPoolSize + ALIGN16(sizeof(gAudioHeap) - 0x100), // audio heap size + ALIGN16(PERMANENT_POOL_SIZE + AI_BUFFERS_SIZE + SOUNDFONT_LIST_SIZE + 0x40), // init pool size + ALIGN16(PERMANENT_POOL_SIZE), // permanent pool size +}; + +#define REVERB_INDEX_0_SETTINGS \ + { 1, 0x30, 0x3000, 0, 0, 0x7FFF, 0x0000, 0x0000, REVERB_INDEX_NONE, 0x3000, 0, 0 } + +ReverbSettings reverbSettings0[3] = { + REVERB_INDEX_0_SETTINGS, + { 1, 0x20, 0x0800, 0, 0, 0x7FFF, 0x0000, 0x0000, REVERB_INDEX_NONE, 0x0000, 0, 0 }, +}; + +ReverbSettings reverbSettings1[3] = { + REVERB_INDEX_0_SETTINGS, + { 1, 0x30, 0x1800, 0, 0, 0x7FFF, 0x0000, 0x0000, REVERB_INDEX_NONE, 0x0000, 11, 11 }, +}; + +ReverbSettings reverbSettings2[3] = { + REVERB_INDEX_0_SETTINGS, + { 1, 0x38, 0x2800, 0, 0, 0x7FFF, 0x0000, 0x0000, REVERB_INDEX_NONE, 0x0000, 7, 7 }, +}; + +ReverbSettings reverbSettings3[3] = { + REVERB_INDEX_0_SETTINGS, + { 1, 0x30, 0x6800, 0, 0, 0x7FFF, 0x1400, 0x1400, REVERB_INDEX_NONE, 0x3000, 6, 6 }, + { 2, 0x50, 0x6000, 0, 0, 0x7FFF, 0xD000, 0x3000, REVERB_INDEX_NONE, 0x3000, 0, 0 }, +}; + +ReverbSettings reverbSettings4[3] = { + REVERB_INDEX_0_SETTINGS, + { 1, 0x40, 0x5000, 0, 0, 0x7FFF, 0x1800, 0x1800, REVERB_INDEX_NONE, 0x3000, 7, 7 }, +}; + +ReverbSettings reverbSettings5[3] = { + REVERB_INDEX_0_SETTINGS, + { 1, 0x40, 0x5C00, 0, 0, 0x7FFF, 0x2000, 0x2000, REVERB_INDEX_NONE, 0x3000, 4, 4 }, +}; + +ReverbSettings reverbSettings6[3] = { + REVERB_INDEX_0_SETTINGS, + { 1, 0x30, 0x6000, 0, 0, 0x7FFF, 0x1000, 0x1000, REVERB_INDEX_NONE, 0x3000, 10, 10 }, +}; + +ReverbSettings reverbSettings7[3] = { + REVERB_INDEX_0_SETTINGS, + { 1, 0x30, 0x6800, 0, 0, 0x7FFF, 0x1400, 0x1400, REVERB_INDEX_NONE, 0x3000, 6, 6 }, +}; + +ReverbSettings reverbSettings8[2] = { + REVERB_INDEX_0_SETTINGS, + { 1, 0x50, 0x5000, 0, 0, 0x7FFF, 0xD000, 0x3000, REVERB_INDEX_NONE, 0x3000, 0, 0 }, +}; + +ReverbSettings reverbSettings9[3] = { + REVERB_INDEX_0_SETTINGS, + { 1, 0x20, 0x0000, 0, 0, 0x7FFF, 0x0000, 0x0000, REVERB_INDEX_NONE, 0x0000, 0, 0 }, +}; + +ReverbSettings reverbSettingsA[3] = { + REVERB_INDEX_0_SETTINGS, + { 1, 0x30, 0x1800, 0, 0, 0x7FFF, 0x0000, 0x0000, REVERB_INDEX_NONE, 0x0000, 11, 11 }, +}; + +ReverbSettings reverbSettingsB[3] = { + REVERB_INDEX_0_SETTINGS, +}; + +ReverbSettings reverbSettingsC[3] = { + REVERB_INDEX_0_SETTINGS, + { 1, 0x40, 0x5000, 0, 0, 0x7FFF, 0x0000, 0x0000, REVERB_INDEX_NONE, 0x3000, 0, 0 }, +}; + +ReverbSettings reverbSettingsD[3] = { + REVERB_INDEX_0_SETTINGS, + { 1, 0x30, 0x6800, 0, 0, 0x7FFF, 0x1400, 0x1400, REVERB_INDEX_NONE, 0x3000, 6, 6 }, + { 2, 0x50, 0x6000, 0, 0, 0x7FFF, 0xD000, 0x3000, REVERB_INDEX_NONE, 0x3000, 0, 0 }, +}; + +ReverbSettings reverbSettingsE[3] = { + REVERB_INDEX_0_SETTINGS, + { 1, 0x30, 0x1800, 0, 0, 0x7FFF, 0x0000, 0x0000, REVERB_INDEX_NONE, 0x0000, 11, 11 }, + { 1, 0x40, 0x5000, 0, 0, 0x7FFF, 0x1800, 0x1800, REVERB_INDEX_NONE, 0x3000, 7, 7 }, +}; + +ReverbSettings reverbSettingsF[2] = { + REVERB_INDEX_0_SETTINGS, + { 1, 0x50, 0x1800, 0, 0, 0x7FFF, 0x0000, 0x0000, REVERB_INDEX_NONE, 0x0000, 11, 11 }, +}; + +ReverbSettings* gReverbSettingsTable[] = { + reverbSettings0, reverbSettings1, reverbSettings2, reverbSettings4, reverbSettings5, + reverbSettings6, reverbSettings7, reverbSettings8, reverbSettings9, reverbSettings3, +}; + +AudioSpec gAudioSpecs[21] = { + /* 0x0 */ + { 32000, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0, + 0xDC800 }, + /* 0x1 */ + { 32000, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0, + 0xDC800 }, + /* 0x2 */ + { 32000, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0, + 0xDC800 }, + /* 0x3 */ + { 32000, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0, + 0xDC800 }, + /* 0x4 */ + { 32000, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0, + 0xDC800 }, + /* 0x5 */ + { 32000, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0, + 0xDC800 }, + /* 0x6 */ + { 32000, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0, + 0xDC800 }, + /* 0x7 */ + { 32000, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0, + 0xDC800 }, + /* 0x8 */ + { 32000, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0, + 0xDC800 }, + /* 0x9 */ + { 32000, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0, + 0xDC800 }, + /* 0xA */ + { 32000, 1, 28, 3, 0, 0, 2, reverbSettingsA, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x2800, 0x2D00, 0, 0, + 0xDC800 }, + /* 0xB */ + { 32000, 1, 28, 3, 0, 0, 2, reverbSettingsA, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0, + 0xDC800 }, + /* 0xC */ + { 32000, 1, 28, 5, 0, 0, 2, reverbSettingsA, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0, + 0xCC800 }, + /* 0xD */ + { 32000, 1, 24, 5, 0, 0, 3, reverbSettingsD, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0, + 0xDC800 }, + /* 0xE */ + { 32000, 1, 24, 5, 0, 0, 3, reverbSettingsE, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0, + 0xDC800 }, + /* 0xF */ + { 32000, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4000, 0x2D00, 0, 0, + 0xDC800 }, + /* 0x10 */ + { 32000, 1, 22, 5, 0, 0, 2, reverbSettings0, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0, + 0xDC800 }, + /* 0x11 */ + { 32000, 1, 22, 5, 0, 0, 2, reverbSettings8, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0, + 0xDC800 }, + /* 0x12 */ + { 32000, 1, 16, 5, 0, 0, 2, reverbSettings0, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0, + 0xDC800 }, + /* 0x13 */ + { 22050, 1, 24, 5, 0, 0, 2, reverbSettings0, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0, + 0xDC800 }, + /* 0x14 */ + { 32000, 1, 24, 5, 0, 0, 2, reverbSettings2, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x3600, 0x2600, 0, 0, + 0xDC800 }, }; diff --git a/src/code/audio/audio_load.c b/src/code/audio/audio_load.c index c8e5ac5d1..ccdc7488d 100644 --- a/src/code/audio/audio_load.c +++ b/src/code/audio/audio_load.c @@ -1218,9 +1218,9 @@ void AudioLoad_Init(void* heap, size_t heapSize) { s32 i; s32 j; - D_80208E68 = NULL; - D_80208E70 = NULL; - D_80208E74 = NULL; + gCustomAudioUpdateFunction = NULL; + gCustomAudioReverbFunction = NULL; + gCustomAudioSynthFunction = NULL; for (i = 0; i < ARRAY_COUNT(gAudioContext.unk_29A8); i++) { gAudioContext.unk_29A8[i] = NULL; diff --git a/src/code/audio/audio_playback.c b/src/code/audio/audio_playback.c index e1a42b1ed..a7cc9a588 100644 --- a/src/code/audio/audio_playback.c +++ b/src/code/audio/audio_playback.c @@ -1,10 +1,10 @@ #include "global.h" -void AudioPlayback_NoteSetResamplingRate(NoteSubEu* noteSubEu, f32 resamplingRateInput); +void AudioPlayback_NoteSetResamplingRate(NoteSampleState* sampleState, f32 resamplingRateInput); void AudioPlayback_AudioListPushFront(AudioListItem* list, AudioListItem* item); void AudioPlayback_NoteInitForLayer(Note* note, SequenceLayer* layer); -void AudioPlayback_InitNoteSub(Note* note, NoteSubEu* noteSubEu, NoteSubAttributes* subAttrs) { +void AudioPlayback_InitSampleState(Note* note, NoteSampleState* sampleState, NoteSubAttributes* subAttrs) { f32 volLeft; f32 volRight; s32 halfPanIndex; @@ -13,45 +13,45 @@ void AudioPlayback_InitNoteSub(Note* note, NoteSubEu* noteSubEu, NoteSubAttribut u8 strongRight; f32 vel; u8 pan; - u8 reverbVol; + u8 targetReverbVol; StereoData stereoData; s32 stereoHeadsetEffects = note->playbackState.stereoHeadsetEffects; vel = subAttrs->velocity; pan = subAttrs->pan; - reverbVol = subAttrs->reverbVol; - stereoData = subAttrs->stereo.s; + targetReverbVol = subAttrs->targetReverbVol; + stereoData = subAttrs->stereoData; - noteSubEu->bitField0 = note->noteSubEu.bitField0; - noteSubEu->bitField1 = note->noteSubEu.bitField1; - noteSubEu->waveSampleAddr = note->noteSubEu.waveSampleAddr; - noteSubEu->harmonicIndexCurAndPrev = note->noteSubEu.harmonicIndexCurAndPrev; + sampleState->bitField0 = note->sampleState.bitField0; + sampleState->bitField1 = note->sampleState.bitField1; + sampleState->waveSampleAddr = note->sampleState.waveSampleAddr; + sampleState->harmonicIndexCurAndPrev = note->sampleState.harmonicIndexCurAndPrev; - AudioPlayback_NoteSetResamplingRate(noteSubEu, subAttrs->frequency); + AudioPlayback_NoteSetResamplingRate(sampleState, subAttrs->frequency); pan &= 0x7F; - noteSubEu->bitField0.stereoStrongRight = false; - noteSubEu->bitField0.stereoStrongLeft = false; - noteSubEu->bitField0.stereoHeadsetEffects = stereoData.stereoHeadsetEffects; - noteSubEu->bitField0.usesHeadsetPanEffects = stereoData.usesHeadsetPanEffects; + sampleState->bitField0.strongRight = false; + sampleState->bitField0.strongLeft = false; + sampleState->bitField0.strongReverbRight = stereoData.strongReverbRight; + sampleState->bitField0.strongReverbLeft = stereoData.strongReverbLeft; if (stereoHeadsetEffects && (gAudioContext.soundMode == SOUNDMODE_HEADSET)) { halfPanIndex = pan >> 1; if (halfPanIndex > 0x3F) { halfPanIndex = 0x3F; } - noteSubEu->headsetPanLeft = gHeadsetPanQuantization[halfPanIndex]; - noteSubEu->headsetPanRight = gHeadsetPanQuantization[0x3F - halfPanIndex]; - noteSubEu->bitField1.usesHeadsetPanEffects2 = true; + sampleState->haasEffectRightDelaySize = gHaasEffectDelaySize[halfPanIndex]; + sampleState->haasEffectLeftDelaySize = gHaasEffectDelaySize[0x3F - halfPanIndex]; + sampleState->bitField1.useHaasEffect = true; volLeft = gHeadsetPanVolume[pan]; volRight = gHeadsetPanVolume[0x7F - pan]; } else if (stereoHeadsetEffects && (gAudioContext.soundMode == SOUNDMODE_STEREO)) { strongLeft = strongRight = false; - noteSubEu->headsetPanRight = 0; - noteSubEu->headsetPanLeft = 0; - noteSubEu->bitField1.usesHeadsetPanEffects2 = false; + sampleState->haasEffectLeftDelaySize = 0; + sampleState->haasEffectRightDelaySize = 0; + sampleState->bitField1.useHaasEffect = false; volLeft = gStereoPanVolume[pan]; volRight = gStereoPanVolume[0x7F - pan]; @@ -62,37 +62,37 @@ void AudioPlayback_InitNoteSub(Note* note, NoteSubEu* noteSubEu, NoteSubAttribut } // case 0: - noteSubEu->bitField0.stereoStrongRight = strongRight; - noteSubEu->bitField0.stereoStrongLeft = strongLeft; + sampleState->bitField0.strongRight = strongRight; + sampleState->bitField0.strongLeft = strongLeft; - switch (stereoData.bit2) { + switch (stereoData.type) { case 0: break; case 1: - noteSubEu->bitField0.stereoStrongRight = stereoData.strongRight; - noteSubEu->bitField0.stereoStrongLeft = stereoData.strongLeft; + sampleState->bitField0.strongRight = stereoData.strongRight; + sampleState->bitField0.strongLeft = stereoData.strongLeft; break; case 2: - noteSubEu->bitField0.stereoStrongRight = stereoData.strongRight | strongRight; - noteSubEu->bitField0.stereoStrongLeft = stereoData.strongLeft | strongLeft; + sampleState->bitField0.strongRight = stereoData.strongRight | strongRight; + sampleState->bitField0.strongLeft = stereoData.strongLeft | strongLeft; break; case 3: - noteSubEu->bitField0.stereoStrongRight = stereoData.strongRight ^ strongRight; - noteSubEu->bitField0.stereoStrongLeft = stereoData.strongLeft ^ strongLeft; + sampleState->bitField0.strongRight = stereoData.strongRight ^ strongRight; + sampleState->bitField0.strongLeft = stereoData.strongLeft ^ strongLeft; break; } } else if (gAudioContext.soundMode == SOUNDMODE_MONO) { - noteSubEu->bitField0.stereoHeadsetEffects = false; - noteSubEu->bitField0.usesHeadsetPanEffects = false; + sampleState->bitField0.strongReverbRight = false; + sampleState->bitField0.strongReverbLeft = false; volLeft = 0.707f; // approx 1/sqrt(2) volRight = 0.707f; } else { - noteSubEu->bitField0.stereoStrongRight = stereoData.strongRight; - noteSubEu->bitField0.stereoStrongLeft = stereoData.strongLeft; + sampleState->bitField0.strongRight = stereoData.strongRight; + sampleState->bitField0.strongLeft = stereoData.strongLeft; volLeft = gDefaultPanVolume[pan]; volRight = gDefaultPanVolume[0x7F - pan]; } @@ -100,33 +100,33 @@ void AudioPlayback_InitNoteSub(Note* note, NoteSubEu* noteSubEu, NoteSubAttribut vel = 0.0f > vel ? 0.0f : vel; vel = 1.0f < vel ? 1.0f : vel; - noteSubEu->targetVolLeft = (s32)((vel * volLeft) * (0x1000 - 0.001f)); - noteSubEu->targetVolRight = (s32)((vel * volRight) * (0x1000 - 0.001f)); + sampleState->targetVolLeft = (s32)((vel * volLeft) * (0x1000 - 0.001f)); + sampleState->targetVolRight = (s32)((vel * volRight) * (0x1000 - 0.001f)); - noteSubEu->gain = subAttrs->gain; - noteSubEu->filter = subAttrs->filter; - noteSubEu->unk_07 = subAttrs->unk_14; - noteSubEu->unk_0E = subAttrs->unk_16; - noteSubEu->reverbVol = reverbVol; - noteSubEu->unk_19 = subAttrs->unk_3; + sampleState->gain = subAttrs->gain; + sampleState->filter = subAttrs->filter; + sampleState->combFilterSize = subAttrs->combFilterSize; + sampleState->combFilterGain = subAttrs->combFilterGain; + sampleState->targetReverbVol = targetReverbVol; + sampleState->surroundEffectIndex = subAttrs->surroundEffectIndex; } -void AudioPlayback_NoteSetResamplingRate(NoteSubEu* noteSubEu, f32 resamplingRateInput) { +void AudioPlayback_NoteSetResamplingRate(NoteSampleState* sampleState, f32 resamplingRateInput) { f32 resamplingRate = 0.0f; if (resamplingRateInput < 2.0f) { - noteSubEu->bitField1.hasTwoParts = false; + sampleState->bitField1.hasTwoParts = false; resamplingRate = CLAMP_MAX(resamplingRateInput, 1.99998f); } else { - noteSubEu->bitField1.hasTwoParts = true; + sampleState->bitField1.hasTwoParts = true; if (resamplingRateInput > 3.99996f) { resamplingRate = 1.99998f; } else { resamplingRate = resamplingRateInput * 0.5f; } } - noteSubEu->resamplingRateFixedPoint = (s32)(resamplingRate * 32768.0f); + sampleState->frequencyFixedPoint = (s32)(resamplingRate * 32768.0f); } void AudioPlayback_NoteInit(Note* note) { @@ -140,17 +140,17 @@ void AudioPlayback_NoteInit(Note* note) { note->playbackState.status = PLAYBACK_STATUS_0; note->playbackState.adsr.action.s.state = ADSR_STATE_INITIAL; - note->noteSubEu = gDefaultNoteSub; + note->sampleState = gDefaultSampleState; } void AudioPlayback_NoteDisable(Note* note) { - if (note->noteSubEu.bitField0.needsInit == true) { - note->noteSubEu.bitField0.needsInit = false; + if (note->sampleState.bitField0.needsInit == true) { + note->sampleState.bitField0.needsInit = false; } note->playbackState.priority = 0; - note->noteSubEu.bitField0.enabled = false; + note->sampleState.bitField0.enabled = false; note->playbackState.status = PLAYBACK_STATUS_0; - note->noteSubEu.bitField0.finished = false; + note->sampleState.bitField0.finished = false; note->playbackState.parentLayer = NO_LAYER; note->playbackState.prevParentLayer = NO_LAYER; note->playbackState.adsr.action.s.state = ADSR_STATE_DISABLED; @@ -161,8 +161,8 @@ void AudioPlayback_ProcessNotes(void) { s32 pad; s32 playbackStatus; NoteAttributes* attrs; - NoteSubEu* noteSubEu2; - NoteSubEu* noteSubEu; + NoteSampleState* sampleState; + NoteSampleState* noteSampleState; Note* note; NotePlaybackState* playbackState; NoteSubAttributes subAttrs; @@ -172,7 +172,7 @@ void AudioPlayback_ProcessNotes(void) { for (i = 0; i < gAudioContext.numNotes; i++) { note = &gAudioContext.notes[i]; - noteSubEu2 = &gAudioContext.noteSubsEu[gAudioContext.noteSubEuOffset + i]; + sampleState = &gAudioContext.sampleStateList[gAudioContext.sampleStateOffset + i]; playbackState = ¬e->playbackState; if (playbackState->parentLayer != NO_LAYER) { if ((u32)playbackState->parentLayer < 0x7FFFFFFF) { @@ -211,10 +211,12 @@ void AudioPlayback_ProcessNotes(void) { out: if (playbackState->priority != 0) { + //! FAKE: if (1) {} - noteSubEu = ¬e->noteSubEu; - if ((playbackState->status >= 1) || noteSubEu->bitField0.finished) { - if ((playbackState->adsr.action.s.state == ADSR_STATE_DISABLED) || noteSubEu->bitField0.finished) { + noteSampleState = ¬e->sampleState; + if ((playbackState->status >= 1) || noteSampleState->bitField0.finished) { + if ((playbackState->adsr.action.s.state == ADSR_STATE_DISABLED) || + noteSampleState->bitField0.finished) { if (playbackState->wantedParentLayer != NO_LAYER) { AudioPlayback_NoteDisable(note); if (playbackState->wantedParentLayer->channel != NULL) { @@ -260,14 +262,14 @@ void AudioPlayback_ProcessNotes(void) { subAttrs.frequency = attrs->freqScale; subAttrs.velocity = attrs->velocity; subAttrs.pan = attrs->pan; - subAttrs.reverbVol = attrs->reverb; - subAttrs.stereo = attrs->stereo; + subAttrs.targetReverbVol = attrs->targetReverbVol; + subAttrs.stereoData = attrs->stereoData; subAttrs.gain = attrs->gain; subAttrs.filter = attrs->filter; - subAttrs.unk_14 = attrs->unk_4; - subAttrs.unk_16 = attrs->unk_6; - subAttrs.unk_3 = attrs->unk_3; - bookOffset = noteSubEu->bitField1.bookOffset; + subAttrs.combFilterSize = attrs->combFilterSize; + subAttrs.combFilterGain = attrs->combFilterGain; + subAttrs.surroundEffectIndex = attrs->surroundEffectIndex; + bookOffset = noteSampleState->bitField1.bookOffset; } else { SequenceLayer* layer = playbackState->parentLayer; SequenceChannel* channel = playbackState->parentLayer->channel; @@ -276,34 +278,35 @@ void AudioPlayback_ProcessNotes(void) { subAttrs.velocity = layer->noteVelocity; subAttrs.pan = layer->notePan; - if (layer->unk_08 == 0x80) { - subAttrs.unk_3 = channel->unk_10; + if (layer->surroundEffectIndex == 0x80) { + subAttrs.surroundEffectIndex = channel->surroundEffectIndex; } else { - subAttrs.unk_3 = layer->unk_08; + subAttrs.surroundEffectIndex = layer->surroundEffectIndex; } - if (layer->stereo.s.bit2 == 0) { - subAttrs.stereo = channel->stereo; + if (layer->stereoData.type == 0) { + subAttrs.stereoData = channel->stereoData; } else { - subAttrs.stereo = layer->stereo; + subAttrs.stereoData = layer->stereoData; } if (layer->unk_0A.s.bit_2 == 1) { - subAttrs.reverbVol = channel->reverb; + subAttrs.targetReverbVol = channel->targetReverbVol; } else { - subAttrs.reverbVol = layer->unk_09; + subAttrs.targetReverbVol = layer->targetReverbVol; } if (layer->unk_0A.s.bit_9 == 1) { subAttrs.gain = channel->gain; } else { subAttrs.gain = 0; + //! FAKE: if (1) {} } subAttrs.filter = channel->filter; - subAttrs.unk_14 = channel->unk_0F; - subAttrs.unk_16 = channel->unk_20; + subAttrs.combFilterSize = channel->combFilterSize; + subAttrs.combFilterGain = channel->combFilterGain; bookOffset = channel->bookOffset & 0x7; if (channel->seqPlayer->muted && (channel->muteFlags & MUTE_FLAGS_3)) { @@ -315,8 +318,8 @@ void AudioPlayback_ProcessNotes(void) { subAttrs.frequency *= playbackState->vibratoFreqScale * playbackState->portamentoFreqScale; subAttrs.frequency *= gAudioContext.audioBufferParameters.resampleRate; subAttrs.velocity *= scale; - AudioPlayback_InitNoteSub(note, noteSubEu2, &subAttrs); - noteSubEu->bitField1.bookOffset = bookOffset; + AudioPlayback_InitSampleState(note, sampleState, &subAttrs); + noteSampleState->bitField1.bookOffset = bookOffset; skip:; } } @@ -500,15 +503,15 @@ void AudioPlayback_SeqLayerDecayRelease(SequenceLayer* layer, s32 target) { channel = layer->channel; if (layer->unk_0A.s.bit_2 == 1) { - attrs->reverb = channel->reverb; + attrs->targetReverbVol = channel->targetReverbVol; } else { - attrs->reverb = layer->unk_09; + attrs->targetReverbVol = layer->targetReverbVol; } - if (layer->unk_08 == 0x80) { - attrs->unk_3 = channel->unk_10; + if (layer->surroundEffectIndex == 0x80) { + attrs->surroundEffectIndex = channel->surroundEffectIndex; } else { - attrs->unk_3 = layer->unk_08; + attrs->surroundEffectIndex = layer->surroundEffectIndex; } if (layer->unk_0A.s.bit_9 == 1) { @@ -526,20 +529,20 @@ void AudioPlayback_SeqLayerDecayRelease(SequenceLayer* layer, s32 target) { attrs->filter = attrs->filterBuf; } - attrs->unk_6 = channel->unk_20; - attrs->unk_4 = channel->unk_0F; + attrs->combFilterGain = channel->combFilterGain; + attrs->combFilterSize = channel->combFilterSize; if (channel->seqPlayer->muted && (channel->muteFlags & MUTE_FLAGS_3)) { - note->noteSubEu.bitField0.finished = true; + note->sampleState.bitField0.finished = true; } - if (layer->stereo.asByte == 0) { - attrs->stereo = channel->stereo; + if (layer->stereoData.asByte == 0) { + attrs->stereoData = channel->stereoData; } else { - attrs->stereo = layer->stereo; + attrs->stereoData = layer->stereoData; } note->playbackState.priority = channel->someOtherPriority; } else { - attrs->stereo = layer->stereo; + attrs->stereoData = layer->stereoData; note->playbackState.priority = 1; } @@ -620,7 +623,7 @@ s32 AudioPlayback_BuildSyntheticWave(Note* note, SequenceLayer* layer, s32 waveI // Save the pointer to the synthethic wave // waveId index starts at 128, there are WAVE_SAMPLE_COUNT samples to read from - note->noteSubEu.waveSampleAddr = &gWaveSamples[waveId - 128][harmonicIndex * WAVE_SAMPLE_COUNT]; + note->sampleState.waveSampleAddr = &gWaveSamples[waveId - 128][harmonicIndex * WAVE_SAMPLE_COUNT]; return harmonicIndex; } @@ -638,7 +641,7 @@ void AudioPlayback_InitSyntheticWave(Note* note, SequenceLayer* layer) { curHarmonicIndex = AudioPlayback_BuildSyntheticWave(note, layer, waveId); if (curHarmonicIndex != prevHarmonicIndex) { - note->noteSubEu.harmonicIndexCurAndPrev = (curHarmonicIndex << 2) + prevHarmonicIndex; + note->sampleState.harmonicIndexCurAndPrev = (curHarmonicIndex << 2) + prevHarmonicIndex; } } @@ -808,7 +811,7 @@ void AudioPlayback_NoteInitForLayer(Note* note, SequenceLayer* layer) { s16 instId; SequenceChannel* channel = layer->channel; NotePlaybackState* playbackState = ¬e->playbackState; - NoteSubEu* noteSubEu = ¬e->noteSubEu; + NoteSampleState* noteSampleState = ¬e->sampleState; playbackState->prevParentLayer = NO_LAYER; playbackState->parentLayer = layer; @@ -825,28 +828,28 @@ void AudioPlayback_NoteInitForLayer(Note* note, SequenceLayer* layer) { if (instId == 0xFF) { instId = channel->instOrWave; } - noteSubEu->tunedSample = layer->tunedSample; + noteSampleState->tunedSample = layer->tunedSample; if (instId >= 0x80 && instId < 0xC0) { - noteSubEu->bitField1.isSyntheticWave = true; + noteSampleState->bitField1.isSyntheticWave = true; } else { - noteSubEu->bitField1.isSyntheticWave = false; + noteSampleState->bitField1.isSyntheticWave = false; } - if (noteSubEu->bitField1.isSyntheticWave) { + if (noteSampleState->bitField1.isSyntheticWave) { AudioPlayback_BuildSyntheticWave(note, layer, instId); } else if (channel->startSamplePos == 1) { - playbackState->startSamplePos = noteSubEu->tunedSample->sample->loop->start; + playbackState->startSamplePos = noteSampleState->tunedSample->sample->loop->start; } else { playbackState->startSamplePos = channel->startSamplePos; - if (playbackState->startSamplePos >= noteSubEu->tunedSample->sample->loop->end) { + if (playbackState->startSamplePos >= noteSampleState->tunedSample->sample->loop->loopEnd) { playbackState->startSamplePos = 0; } } playbackState->fontId = channel->fontId; playbackState->stereoHeadsetEffects = channel->stereoHeadsetEffects; - noteSubEu->bitField1.reverbIndex = channel->reverbIndex & 3; + noteSampleState->bitField1.reverbIndex = channel->reverbIndex & 3; } void func_801963E8(Note* note, SequenceLayer* layer) { @@ -987,7 +990,7 @@ void AudioPlayback_NoteInitAll(void) { for (i = 0; i < gAudioContext.numNotes; i++) { note = &gAudioContext.notes[i]; - note->noteSubEu = gZeroNoteSub; + note->sampleState = gZeroedSampleState; note->playbackState.priority = 0; note->playbackState.status = PLAYBACK_STATUS_0; note->playbackState.parentLayer = NO_LAYER; @@ -1002,7 +1005,8 @@ void AudioPlayback_NoteInitAll(void) { note->playbackState.portamento.speed = 0; note->playbackState.stereoHeadsetEffects = false; note->playbackState.startSamplePos = 0; - note->synthesisState.synthesisBuffers = AudioHeap_AllocDmaMemory(&gAudioContext.miscPool, 0x2E0); - note->playbackState.attributes.filterBuf = AudioHeap_AllocDmaMemory(&gAudioContext.miscPool, 0x10); + note->synthesisState.synthesisBuffers = + AudioHeap_AllocDmaMemory(&gAudioContext.miscPool, sizeof(NoteSynthesisBuffers)); + note->playbackState.attributes.filterBuf = AudioHeap_AllocDmaMemory(&gAudioContext.miscPool, FILTER_SIZE); } } diff --git a/src/code/audio/audio_seqplayer.c b/src/code/audio/audio_seqplayer.c index a8573e33d..bc5115f8f 100644 --- a/src/code/audio/audio_seqplayer.c +++ b/src/code/audio/audio_seqplayer.c @@ -282,17 +282,17 @@ void AudioSeq_InitSequenceChannel(SequenceChannel* channel) { channel->transposition = 0; channel->largeNotes = false; channel->bookOffset = 0; - channel->stereo.asByte = 0; + channel->stereoData.asByte = 0; channel->changes.asByte = 0xFF; channel->scriptState.depth = 0; channel->newPan = 0x40; channel->panChannelWeight = 0x80; - channel->unk_10 = 0xFF; + channel->surroundEffectIndex = 0xFF; channel->velocityRandomVariance = 0; channel->gateTimeRandomVariance = 0; channel->noteUnused = NULL; channel->reverbIndex = 0; - channel->reverb = 0; + channel->targetReverbVol = 0; channel->gain = 0; channel->notePriority = 3; channel->someOtherPriority = 1; @@ -308,8 +308,8 @@ void AudioSeq_InitSequenceChannel(SequenceChannel* channel) { channel->vibrato.vibratoExtentChangeDelay = 0; channel->vibrato.vibratoDelay = 0; channel->filter = NULL; - channel->unk_20 = 0; - channel->unk_0F = 0; + channel->combFilterGain = 0; + channel->combFilterSize = 0; channel->volume = 1.0f; channel->volumeScale = 1.0f; channel->freqScale = 1.0f; @@ -345,7 +345,7 @@ s32 AudioSeq_SeqChannelSetLayer(SequenceChannel* channel, s32 layerIndex) { layer->channel = channel; layer->adsr = channel->adsr; layer->adsr.decayIndex = 0; - layer->unk_09 = channel->reverb; + layer->targetReverbVol = channel->targetReverbVol; layer->enabled = true; layer->finished = false; layer->stopSomething = false; @@ -355,8 +355,8 @@ s32 AudioSeq_SeqChannelSetLayer(SequenceChannel* channel, s32 layerIndex) { layer->bit1 = false; layer->notePropertiesNeedInit = false; layer->gateTime = 0x80; - layer->unk_08 = 0x80; - layer->stereo.asByte = 0; + layer->surroundEffectIndex = 0x80; + layer->stereoData.asByte = 0; layer->portamento.mode = PORTAMENTO_MODE_OFF; layer->scriptState.depth = 0; layer->pan = 0x40; @@ -782,7 +782,7 @@ s32 AudioSeq_SeqLayerProcessScriptStep2(SequenceLayer* layer) { break; case 0xCD: // layer: stereo effects - layer->stereo.asByte = AudioSeq_ScriptReadU8(state); + layer->stereoData.asByte = AudioSeq_ScriptReadU8(state); break; case 0xCE: // layer: bend pitch @@ -796,7 +796,7 @@ s32 AudioSeq_SeqLayerProcessScriptStep2(SequenceLayer* layer) { break; case 0xF1: // layer: - layer->unk_08 = AudioSeq_ScriptReadU8(state); + layer->surroundEffectIndex = AudioSeq_ScriptReadU8(state); break; default: @@ -991,13 +991,14 @@ s32 AudioSeq_SeqLayerProcessScriptStep4(SequenceLayer* layer, s32 cmd) { if (layer->delay == 0) { if (layer->tunedSample != NULL) { - time = layer->tunedSample->sample->loop->end; + time = layer->tunedSample->sample->loop->loopEnd; } else { time = 0.0f; } time *= seqPlayer->tempo; time *= gAudioContext.unk_2870; time /= layer->freqScale; + //! FAKE: if (1) {} if (time > 0x7FFE) { time = 0x7FFE; @@ -1416,9 +1417,9 @@ void AudioSeq_SequenceChannelProcessScript(SequenceChannel* channel) { channel->vibrato.vibratoDelay = cmd * 16; break; - case 0xD4: // channel: set reverb + case 0xD4: // channel: set reverb volume cmd = (u8)cmdArgs[0]; - channel->reverb = cmd; + channel->targetReverbVol = cmd; break; case 0xC6: // channel: set soundFont @@ -1491,7 +1492,7 @@ void AudioSeq_SequenceChannelProcessScript(SequenceChannel* channel) { } else { channel->stereoHeadsetEffects = false; } - channel->stereo.asByte = cmd & 0x7F; + channel->stereoData.asByte = cmd & 0x7F; break; case 0xD1: // channel: set note allocation policy @@ -1537,7 +1538,7 @@ void AudioSeq_SequenceChannelProcessScript(SequenceChannel* channel) { data += 4; channel->newPan = data[-3]; channel->panChannelWeight = data[-2]; - channel->reverb = data[-1]; + channel->targetReverbVol = data[-1]; channel->reverbIndex = data[0]; //! @bug: Not marking reverb state as changed channel->changes.s.pan = true; @@ -1551,7 +1552,7 @@ void AudioSeq_SequenceChannelProcessScript(SequenceChannel* channel) { channel->transposition = (s8)AudioSeq_ScriptReadU8(scriptState); channel->newPan = AudioSeq_ScriptReadU8(scriptState); channel->panChannelWeight = AudioSeq_ScriptReadU8(scriptState); - channel->reverb = AudioSeq_ScriptReadU8(scriptState); + channel->targetReverbVol = AudioSeq_ScriptReadU8(scriptState); channel->reverbIndex = AudioSeq_ScriptReadU8(scriptState); //! @bug: Not marking reverb state as changed channel->changes.s.pan = true; @@ -1569,8 +1570,8 @@ void AudioSeq_SequenceChannelProcessScript(SequenceChannel* channel) { channel->adsr.sustain = 0; channel->velocityRandomVariance = 0; channel->gateTimeRandomVariance = 0; - channel->unk_0F = 0; - channel->unk_20 = 0; + channel->combFilterSize = 0; + channel->combFilterGain = 0; channel->bookOffset = 0; channel->startSamplePos = 0; channel->unk_E0 = 0; @@ -1651,8 +1652,8 @@ void AudioSeq_SequenceChannelProcessScript(SequenceChannel* channel) { break; case 0xBB: // channel: - channel->unk_0F = cmdArgs[0]; - channel->unk_20 = cmdArgs[1]; + channel->combFilterSize = cmdArgs[0]; + channel->combFilterGain = cmdArgs[1]; break; case 0xBC: // channel: add large @@ -1667,8 +1668,8 @@ void AudioSeq_SequenceChannelProcessScript(SequenceChannel* channel) { if (cmdArgs[0] < 5) { if (1) {} if (gAudioContext.unk_29A8[cmdArgs[0]] != NULL) { - D_80208E6C = gAudioContext.unk_29A8[cmdArgs[0]]; - scriptState->value = D_80208E6C(scriptState->value, channel); + gCustomAudioSeqFunction = gAudioContext.unk_29A8[cmdArgs[0]]; + scriptState->value = gCustomAudioSeqFunction(scriptState->value, channel); } } break; @@ -1693,7 +1694,7 @@ void AudioSeq_SequenceChannelProcessScript(SequenceChannel* channel) { break; case 0xA4: // channel: - channel->unk_10 = cmdArgs[0]; + channel->surroundEffectIndex = cmdArgs[0]; break; case 0xA5: // channel: @@ -2197,7 +2198,7 @@ void AudioSeq_ProcessSequences(s32 arg0) { SequencePlayer* seqPlayer; u32 i; - gAudioContext.noteSubEuOffset = + gAudioContext.sampleStateOffset = (gAudioContext.audioBufferParameters.updatesPerFrame - arg0 - 1) * gAudioContext.numNotes; for (i = 0; i < (u32)gAudioContext.audioBufferParameters.numSequencePlayers; i++) { diff --git a/src/code/audio/audio_synthesis.c b/src/code/audio/audio_synthesis.c index 51842a33f..17b3ff4be 100644 --- a/src/code/audio/audio_synthesis.c +++ b/src/code/audio/audio_synthesis.c @@ -1,137 +1,1698 @@ #include "global.h" -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_801877D0.s") +// DMEM Addresses for the RSP +#define DMEM_TEMP 0x3B0 +#define DMEM_TEMP2 0x3C0 +#define DMEM_SURROUND_TEMP 0x4B0 +#define DMEM_UNCOMPRESSED_NOTE 0x570 +#define DMEM_HAAS_TEMP 0x5B0 +#define DMEM_COMB_TEMP 0x750 // = DMEM_TEMP + DMEM_2CH_SIZE + a bit more +#define DMEM_COMPRESSED_ADPCM_DATA 0x930 // = DMEM_LEFT_CH +#define DMEM_LEFT_CH 0x930 +#define DMEM_RIGHT_CH 0xAD0 +#define DMEM_WET_TEMP 0x3D0 +#define DMEM_WET_SCRATCH 0x710 // = DMEM_WET_TEMP + DMEM_2CH_SIZE +#define DMEM_WET_LEFT_CH 0xC70 +#define DMEM_WET_RIGHT_CH 0xE10 // = DMEM_WET_LEFT_CH + DMEM_1CH_SIZE + +typedef enum { + /* 0 */ HAAS_EFFECT_DELAY_NONE, + /* 1 */ HAAS_EFFECT_DELAY_LEFT, // Delay left channel so that right channel is heard first + /* 2 */ HAAS_EFFECT_DELAY_RIGHT // Delay right channel so that left channel is heard first +} HaasEffectDelaySide; + +Acmd* AudioSynth_SaveResampledReverbSamplesImpl(Acmd* cmd, u16 dmem, u16 arg2, uintptr_t arg3); +Acmd* AudioSynth_LoadReverbSamplesImpl(Acmd* cmd, u16 dmem, u16 startPos, s32 size, SynthesisReverb* reverb); +Acmd* AudioSynth_SaveReverbSamplesImpl(Acmd* cmd, u16 dmem, u16 startPos, s32 size, SynthesisReverb* reverb); +Acmd* AudioSynth_ProcessSamples(s16* aiBuf, s32 numSamplesPerUpdate, Acmd* cmd, s32 updateIndex); +Acmd* AudioSynth_ProcessSample(s32 noteIndex, NoteSampleState* sampleState, NoteSynthesisState* synthState, s16* aiBuf, + s32 numSamplesPerUpdate, Acmd* cmd, s32 updateIndex); +Acmd* AudioSynth_ApplySurroundEffect(Acmd* cmd, NoteSampleState* sampleState, NoteSynthesisState* synthState, s32 size, + s32 dmem, s32 flags); +Acmd* AudioSynth_FinalResample(Acmd* cmd, NoteSynthesisState* synthState, s32 size, u16 pitch, u16 inpDmem, + s32 resampleFlags); +Acmd* AudioSynth_ProcessEnvelope(Acmd* cmd, NoteSampleState* sampleState, NoteSynthesisState* synthState, + s32 numSamplesPerUpdate, u16 dmemSrc, s32 haasEffectDelaySide, s32 flags); +Acmd* AudioSynth_LoadWaveSamples(Acmd* cmd, NoteSampleState* sampleState, NoteSynthesisState* synthState, + s32 numSamplesToLoad); +Acmd* AudioSynth_ApplyHaasEffect(Acmd* cmd, NoteSampleState* sampleState, NoteSynthesisState* synthState, s32 size, + s32 flags, s32 haasEffectDelaySide); + +s32 D_801D5FB0 = 0; + +u32 sEnvMixerOp = _SHIFTL(A_ENVMIXER, 24, 8); + +// Store the left dry channel in a temp space to be delayed to produce the haas effect +u32 sEnvMixerLeftHaasDmemDests = + AUDIO_MK_CMD(DMEM_HAAS_TEMP >> 4, DMEM_RIGHT_CH >> 4, DMEM_WET_LEFT_CH >> 4, DMEM_WET_RIGHT_CH >> 4); + +// Store the right dry channel in a temp space to be delayed to produce the haas effect +u32 sEnvMixerRightHaasDmemDests = + AUDIO_MK_CMD(DMEM_LEFT_CH >> 4, DMEM_HAAS_TEMP >> 4, DMEM_WET_LEFT_CH >> 4, DMEM_WET_RIGHT_CH >> 4); + +u32 sEnvMixerDefaultDmemDests = + AUDIO_MK_CMD(DMEM_LEFT_CH >> 4, DMEM_RIGHT_CH >> 4, DMEM_WET_LEFT_CH >> 4, DMEM_WET_RIGHT_CH >> 4); + +// Unused Data +u16 D_801D5FC4[] = { + 0x7FFF, 0xD001, 0x3FFF, 0xF001, 0x5FFF, 0x9001, 0x7FFF, 0x8001, +}; + +u8 sNumSamplesPerWavePeriod[] = { + WAVE_SAMPLE_COUNT / 1, // 1st harmonic + WAVE_SAMPLE_COUNT / 2, // 2nd harmonic + WAVE_SAMPLE_COUNT / 4, // 4th harmonic + WAVE_SAMPLE_COUNT / 8, // 8th harmonic +}; + +/** + * Add a collection of s16-samples as a single entry to the reverb buffer + */ +void AudioSynth_AddReverbBufferEntry(s32 numSamples, s32 updateIndex, s32 reverbIndex) { + SynthesisReverb* reverb; + ReverbBufferEntry* entry; + s32 extraSamples; + s32 numSamplesAfterDownsampling; + s32 reverbBufPos; + s32 temp_t2; + s32 temp_t4; + s32 count1; + s32 count2; + s32 nextReverbSubBufPos; + + reverb = &gAudioContext.synthesisReverbs[reverbIndex]; + entry = &reverb->bufEntry[reverb->curFrame][updateIndex]; + + numSamplesAfterDownsampling = numSamples / gAudioContext.synthesisReverbs[reverbIndex].downsampleRate; + + // Apply resampling effect + if (gAudioContext.synthesisReverbs[reverbIndex].resampleEffectOn) { + if (reverb->downsampleRate == 1) { + count1 = 0; + count2 = 0; + + numSamplesAfterDownsampling += reverb->resampleEffectExtraSamples; + + entry->saveResampleNumSamples = numSamplesAfterDownsampling; + entry->loadResamplePitch = ((u16)numSamplesAfterDownsampling << 0xF) / numSamples; + entry->saveResamplePitch = (numSamples << 0xF) / (u16)numSamplesAfterDownsampling; + + while (true) { + temp_t2 = (entry->loadResamplePitch * numSamples * 2) + reverb->resampleEffectLoadUnk; + temp_t4 = temp_t2 >> 0x10; + + if ((temp_t4 != numSamplesAfterDownsampling) && (count1 == 0)) { + entry->loadResamplePitch = + ((numSamplesAfterDownsampling << 0x10) - reverb->resampleEffectLoadUnk) / (numSamples * 2); + count1++; + } else { + count1++; + if (temp_t4 > numSamplesAfterDownsampling) { + entry->loadResamplePitch--; + } else if (temp_t4 < numSamplesAfterDownsampling) { + entry->loadResamplePitch++; + } else { + break; + } + } + } + + reverb->resampleEffectLoadUnk = temp_t2 & 0xFFFF; + + while (true) { + temp_t2 = (entry->saveResamplePitch * numSamplesAfterDownsampling * 2) + reverb->resampleEffectSaveUnk; + temp_t4 = temp_t2 >> 0x10; + + if ((temp_t4 != numSamples) && (count2 == 0)) { + entry->saveResamplePitch = + ((numSamples << 0x10) - reverb->resampleEffectSaveUnk) / (numSamplesAfterDownsampling * 2); + count2++; + } else { + count2++; + if (temp_t4 > numSamples) { + entry->saveResamplePitch--; + } else if (temp_t4 < numSamples) { + entry->saveResamplePitch++; + } else { + break; + } + } + } + + reverb->resampleEffectSaveUnk = temp_t2 & 0xFFFF; + } + } + + extraSamples = (reverb->nextReverbBufPos + numSamplesAfterDownsampling) - reverb->delayNumSamples; + reverbBufPos = reverb->nextReverbBufPos; + + // Add a reverb entry + if (extraSamples < 0) { + entry->size = numSamplesAfterDownsampling * SAMPLE_SIZE; + entry->wrappedSize = 0; + entry->startPos = reverb->nextReverbBufPos; + reverb->nextReverbBufPos += numSamplesAfterDownsampling; + } else { + // End of the buffer is reached. Loop back around + entry->size = (numSamplesAfterDownsampling - extraSamples) * SAMPLE_SIZE; + entry->wrappedSize = extraSamples * SAMPLE_SIZE; + entry->startPos = reverb->nextReverbBufPos; + reverb->nextReverbBufPos = extraSamples; + } + + entry->numSamplesAfterDownsampling = numSamplesAfterDownsampling; + entry->numSamples = numSamples; + + // Add a sub-reverb entry + if (reverb->subDelay != 0) { + nextReverbSubBufPos = reverb->subDelay + reverbBufPos; + if (nextReverbSubBufPos >= reverb->delayNumSamples) { + nextReverbSubBufPos -= reverb->delayNumSamples; + } + + entry = &reverb->subBufEntry[reverb->curFrame][updateIndex]; + numSamplesAfterDownsampling = numSamples / reverb->downsampleRate; + extraSamples = (nextReverbSubBufPos + numSamplesAfterDownsampling) - reverb->delayNumSamples; + + if (extraSamples < 0) { + entry->size = numSamplesAfterDownsampling * SAMPLE_SIZE; + entry->wrappedSize = 0; + entry->startPos = nextReverbSubBufPos; + } else { + // End of the buffer is reached. Loop back around + entry->size = (numSamplesAfterDownsampling - extraSamples) * SAMPLE_SIZE; + entry->wrappedSize = extraSamples * SAMPLE_SIZE; + entry->startPos = nextReverbSubBufPos; + } + + entry->numSamplesAfterDownsampling = numSamplesAfterDownsampling; + entry->numSamples = numSamples; + } +} + +/** + * Sync the sample states between the notes and the list + */ +void AudioSynth_SyncSampleStates(s32 updateIndex) { + NoteSampleState* noteSampleState; + NoteSampleState* sampleState; + s32 sampleStateBaseIndex; + s32 i; + + sampleStateBaseIndex = gAudioContext.numNotes * updateIndex; + for (i = 0; i < gAudioContext.numNotes; i++) { + noteSampleState = &gAudioContext.notes[i].sampleState; + sampleState = &gAudioContext.sampleStateList[sampleStateBaseIndex + i]; + if (noteSampleState->bitField0.enabled) { + noteSampleState->bitField0.needsInit = false; + } else { + sampleState->bitField0.enabled = false; + } + + noteSampleState->harmonicIndexCurAndPrev = 0; + } +} + +Acmd* AudioSynth_Update(Acmd* abiCmdStart, s32* numAbiCmds, s16* aiBufStart, s32 numSamplesPerFrame) { + s32 numSamplesPerUpdate; + s16* curAiBufPos; + Acmd* curCmd = abiCmdStart; + s32 reverseUpdateIndex; + s32 reverbIndex; + SynthesisReverb* reverb; + + for (reverseUpdateIndex = gAudioContext.audioBufferParameters.updatesPerFrame; reverseUpdateIndex > 0; + reverseUpdateIndex--) { + AudioSeq_ProcessSequences(reverseUpdateIndex - 1); + AudioSynth_SyncSampleStates(gAudioContext.audioBufferParameters.updatesPerFrame - reverseUpdateIndex); + } + + curAiBufPos = aiBufStart; + gAudioContext.adpcmCodeBook = NULL; + + // Process/Update all samples multiple times in a single frame + for (reverseUpdateIndex = gAudioContext.audioBufferParameters.updatesPerFrame; reverseUpdateIndex > 0; + reverseUpdateIndex--) { + if (reverseUpdateIndex == 1) { + // Final Update + numSamplesPerUpdate = numSamplesPerFrame; + } else if ((numSamplesPerFrame / reverseUpdateIndex) >= + gAudioContext.audioBufferParameters.numSamplesPerUpdateMax) { + numSamplesPerUpdate = gAudioContext.audioBufferParameters.numSamplesPerUpdateMax; + } else if ((numSamplesPerFrame / reverseUpdateIndex) <= + gAudioContext.audioBufferParameters.numSamplesPerUpdateMin) { + numSamplesPerUpdate = gAudioContext.audioBufferParameters.numSamplesPerUpdateMin; + } else { + numSamplesPerUpdate = gAudioContext.audioBufferParameters.numSamplesPerUpdate; + } + + for (reverbIndex = 0; reverbIndex < gAudioContext.numSynthesisReverbs; reverbIndex++) { + if (gAudioContext.synthesisReverbs[reverbIndex].useReverb) { + AudioSynth_AddReverbBufferEntry( + numSamplesPerUpdate, gAudioContext.audioBufferParameters.updatesPerFrame - reverseUpdateIndex, + reverbIndex); + } + } + + curCmd = AudioSynth_ProcessSamples(curAiBufPos, numSamplesPerUpdate, curCmd, + gAudioContext.audioBufferParameters.updatesPerFrame - reverseUpdateIndex); + numSamplesPerFrame -= numSamplesPerUpdate; + curAiBufPos += numSamplesPerUpdate * SAMPLE_SIZE; + } + + // Update reverb frame info + for (reverbIndex = 0; reverbIndex < gAudioContext.numSynthesisReverbs; reverbIndex++) { + if (gAudioContext.synthesisReverbs[reverbIndex].framesToIgnore != 0) { + gAudioContext.synthesisReverbs[reverbIndex].framesToIgnore--; + } + gAudioContext.synthesisReverbs[reverbIndex].curFrame ^= 1; + } + + *numAbiCmds = curCmd - abiCmdStart; + return curCmd; +} + +void AudioSynth_DisableSampleStates(s32 updateIndex, s32 noteIndex) { + NoteSampleState* sampleState; + s32 i; + + for (i = updateIndex + 1; i < gAudioContext.audioBufferParameters.updatesPerFrame; i++) { + sampleState = &gAudioContext.sampleStateList[(gAudioContext.numNotes * i) + noteIndex]; + if (sampleState->bitField0.needsInit) { + break; + } + sampleState->bitField0.enabled = false; + } +} + +/** + * Load reverb samples from a different reverb index + */ +Acmd* AudioSynth_LoadMixedReverbSamples(Acmd* cmd, SynthesisReverb* reverb, s16 updateIndex) { + ReverbBufferEntry* entry = &reverb->bufEntry[reverb->curFrame][updateIndex]; + + cmd = AudioSynth_LoadReverbSamplesImpl(cmd, DMEM_WET_TEMP, entry->startPos, entry->size, reverb); + if (entry->wrappedSize != 0) { + // Ring buffer wrapped + cmd = AudioSynth_LoadReverbSamplesImpl(cmd, DMEM_WET_TEMP + entry->size, 0, entry->wrappedSize, reverb); + } + return cmd; +} + +/** + * Save reverb samples from a different reverb index + */ +Acmd* AudioSynth_SaveMixedReverbSamples(Acmd* cmd, SynthesisReverb* reverb, s16 updateIndex) { + ReverbBufferEntry* entry = &reverb->bufEntry[reverb->curFrame][updateIndex]; + + cmd = AudioSynth_SaveReverbSamplesImpl(cmd, DMEM_WET_TEMP, entry->startPos, entry->size, reverb); + if (entry->wrappedSize != 0) { + // Ring buffer wrapped + cmd = AudioSynth_SaveReverbSamplesImpl(cmd, DMEM_WET_TEMP + entry->size, 0, entry->wrappedSize, reverb); + } + return cmd; +} + +void AudioSynth_Noop1(void) { +} + +void AudioSynth_ClearBuffer(Acmd* cmd, s32 dmem, s32 size) { + aClearBuffer(cmd, dmem, size); +} + +void AudioSynth_Noop2(void) { +} + +void AudioSynth_Noop3(void) { +} + +void AudioSynth_Noop4(void) { +} + +void AudioSynth_Mix(Acmd* cmd, size_t size, s32 gain, s32 dmemIn, s32 dmemOut) { + aMix(cmd, size, gain, dmemIn, dmemOut); +} + +void AudioSynth_Noop5(void) { +} + +void AudioSynth_Noop6(void) { +} + +void AudioSynth_Noop7(void) { +} + +void AudioSynth_SetBuffer(Acmd* cmd, s32 flags, s32 dmemIn, s32 dmemOut, size_t size) { + aSetBuffer(cmd, flags, dmemIn, dmemOut, size); +} + +void AudioSynth_Noop8(void) { +} + +void AudioSynth_Noop9(void) { +} + +void AudioSynth_DMemMove(Acmd* cmd, s32 dmemIn, s32 dmemOut, size_t size) { + // aDMEMMove(cmd, dmemIn, dmemOut, size); + cmd->words.w0 = _SHIFTL(A_DMEMMOVE, 24, 8) | _SHIFTL(dmemIn, 0, 24); + cmd->words.w1 = _SHIFTL(dmemOut, 16, 16) | _SHIFTL(size, 0, 16); +} + +void AudioSynth_Noop10(void) { +} + +void AudioSynth_Noop11(void) { +} + +void AudioSynth_Noop12(void) { +} + +void AudioSynth_Noop13(void) { +} + +void AudioSynth_InterL(Acmd* cmd, s32 dmemIn, s32 dmemOut, s32 numSamples) { + // aInterl(cmd, dmemIn, dmemOut, numSamples); + cmd->words.w0 = _SHIFTL(A_INTERL, 24, 8) | _SHIFTL(numSamples, 0, 16); + cmd->words.w1 = _SHIFTL(dmemIn, 16, 16) | _SHIFTL(dmemOut, 0, 16); +} + +void AudioSynth_EnvSetup1(Acmd* cmd, s32 reverbVol, s32 rampReverb, s32 rampLeft, s32 rampRight) { + aEnvSetup1(cmd, reverbVol, rampReverb, rampLeft, rampRight); +} + +void AudioSynth_Noop14(void) { +} + +void AudioSynth_LoadBuffer(Acmd* cmd, s32 dmemDest, s32 size, void* addrSrc) { + aLoadBuffer(cmd, addrSrc, dmemDest, size); +} + +void AudioSynth_SaveBuffer(Acmd* cmd, s32 dmemSrc, s32 size, void* addrDest) { + aSaveBuffer(cmd, dmemSrc, addrDest, size); +} -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80187B64.s") +void AudioSynth_EnvSetup2(Acmd* cmd, s32 volLeft, s32 volRight) { + // aEnvSetup2(cmd, volLeft, volRight); + cmd->words.w0 = _SHIFTL(A_ENVSETUP2, 24, 8); + cmd->words.w1 = _SHIFTL(volLeft, 16, 16) | _SHIFTL(volRight, 0, 16); +} -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80187BEC.s") +void AudioSynth_Noop15(void) { +} -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80187DE8.s") +void AudioSynth_Noop16(void) { +} -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80187E58.s") +void AudioSynth_Noop17(void) { +} -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80187F00.s") +void AudioSynth_S8Dec(Acmd* cmd, s32 flags, s16* state) { + aS8Dec(cmd, flags, state); +} -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80187FA8.s") +void AudioSynth_HiLoGain(Acmd* cmd, s32 gain, s32 dmemIn, s32 dmemOut, s32 size) { + // aHiLoGain(cmd, gain, size, dmemIn, dmemOut); + cmd->words.w0 = _SHIFTL(A_HILOGAIN, 24, 8) | _SHIFTL(gain, 16, 8) | _SHIFTL(size, 0, 16); + cmd->words.w1 = _SHIFTL(dmemIn, 16, 16) | _SHIFTL(dmemOut, 0, 16); +} -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80187FB0.s") +// Remnant of OoT +void AudioSynth_UnkCmd19(Acmd* cmd, s32 dmem1, s32 dmem2, s32 size, s32 arg4) { + cmd->words.w0 = _SHIFTL(A_SPNOOP, 24, 8) | _SHIFTL(arg4, 16, 8) | _SHIFTL(size, 0, 16); + cmd->words.w1 = _SHIFTL(dmem1, 16, 16) | _SHIFTL(dmem2, 0, 16); +} -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80187FD0.s") +void AudioSynth_Noop18(void) { +} -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80187FD8.s") +void AudioSynth_Noop19(void) { +} -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80187FE0.s") +void AudioSynth_Noop20(void) { +} -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80187FE8.s") +void AudioSynth_Noop21(void) { +} -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_8018801C.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188024.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_8018802C.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188034.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188068.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188070.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188078.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_801880A4.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_801880AC.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_801880B4.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_801880BC.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_801880C4.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_801880E8.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_8018811C.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188124.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_8018814C.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188174.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188190.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188198.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_801881A0.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_801881A8.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_801881C4.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_801881F8.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188224.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_8018822C.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188234.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_8018823C.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188244.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_8018824C.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188254.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_8018825C.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188264.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188288.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_801882A0.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188304.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_801884A0.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188698.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_8018883C.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_801888E4.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_801889A4.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188A50.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188AFC.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188C48.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188CB4.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188D20.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188D28.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188D68.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188DDC.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188FBC.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80189064.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80189620.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_8018A4B4.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_8018A768.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_8018A808.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_8018ACC4.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_8018AE34.s") +void AudioSynth_Noop22(void) { +} + +void AudioSynth_Noop23(void) { +} + +void AudioSynth_Noop24(void) { +} + +void AudioSynth_Noop25(void) { +} + +void AudioSynth_LoadFilterBuffer(Acmd* cmd, s32 flags, s32 buf, s16* addr) { + aFilter(cmd, flags, buf, addr); +} + +void AudioSynth_LoadFilterSize(Acmd* cmd, size_t size, s16* addr) { + aFilter(cmd, 2, size, addr); +} + +/** + * Leak some audio from the left reverb channel into the right reverb channel and vice versa (pan) + */ +Acmd* AudioSynth_LeakReverb(Acmd* cmd, SynthesisReverb* reverb) { + aDMEMMove(cmd++, DMEM_WET_LEFT_CH, DMEM_WET_SCRATCH, DMEM_1CH_SIZE); + aMix(cmd++, DMEM_1CH_SIZE >> 4, reverb->leakRtl, DMEM_WET_RIGHT_CH, DMEM_WET_LEFT_CH); + aMix(cmd++, DMEM_1CH_SIZE >> 4, reverb->leakLtr, DMEM_WET_SCRATCH, DMEM_WET_RIGHT_CH); + + return cmd; +} + +Acmd* AudioSynth_LoadDownsampledReverbSamples(Acmd* cmd, s32 numSamplesPerUpdate, SynthesisReverb* reverb, + s16 updateIndex) { + ReverbBufferEntry* entry = &reverb->bufEntry[reverb->curFrame][updateIndex]; + s16 offsetSize = (entry->startPos & 7) * SAMPLE_SIZE; + s16 wrappedOffsetSize = ALIGN16(offsetSize + entry->size); + + cmd = AudioSynth_LoadReverbSamplesImpl(cmd, DMEM_WET_TEMP, entry->startPos - (offsetSize / (s32)SAMPLE_SIZE), + DMEM_1CH_SIZE, reverb); + + if (entry->wrappedSize != 0) { + // Ring buffer wrapped + cmd = AudioSynth_LoadReverbSamplesImpl(cmd, DMEM_WET_TEMP + wrappedOffsetSize, 0, + DMEM_1CH_SIZE - wrappedOffsetSize, reverb); + } + + aSetBuffer(cmd++, 0, DMEM_WET_TEMP + offsetSize, DMEM_WET_LEFT_CH, numSamplesPerUpdate * SAMPLE_SIZE); + aResample(cmd++, reverb->resampleFlags, reverb->downsamplePitch, reverb->leftLoadResampleBuf); + aSetBuffer(cmd++, 0, DMEM_WET_TEMP + DMEM_1CH_SIZE + offsetSize, DMEM_WET_RIGHT_CH, + numSamplesPerUpdate * SAMPLE_SIZE); + aResample(cmd++, reverb->resampleFlags, reverb->downsamplePitch, reverb->rightLoadResampleBuf); + + return cmd; +} + +Acmd* AudioSynth_SaveResampledReverbSamples(Acmd* cmd, SynthesisReverb* reverb, s16 updateIndex) { + ReverbBufferEntry* entry = &reverb->bufEntry[reverb->curFrame][updateIndex]; + s16 numSamples = entry->numSamples; + u32 size = numSamples * SAMPLE_SIZE; + + // Left Resample + aDMEMMove(cmd++, DMEM_WET_LEFT_CH, DMEM_WET_TEMP, size); + aSetBuffer(cmd++, 0, DMEM_WET_TEMP, DMEM_WET_SCRATCH, entry->saveResampleNumSamples * SAMPLE_SIZE); + aResample(cmd++, reverb->resampleFlags, entry->saveResamplePitch, reverb->leftSaveResampleBuf); + + cmd = AudioSynth_SaveResampledReverbSamplesImpl(cmd, DMEM_WET_SCRATCH, entry->size, + &reverb->leftReverbBuf[entry->startPos]); + + if (entry->wrappedSize != 0) { + // Ring buffer wrapped + cmd = AudioSynth_SaveResampledReverbSamplesImpl(cmd, entry->size + DMEM_WET_SCRATCH, entry->wrappedSize, + reverb->leftReverbBuf); + } + + // Right Resample + aDMEMMove(cmd++, DMEM_WET_RIGHT_CH, DMEM_WET_TEMP, size); + aSetBuffer(cmd++, 0, DMEM_WET_TEMP, DMEM_WET_SCRATCH, entry->saveResampleNumSamples * SAMPLE_SIZE); + aResample(cmd++, reverb->resampleFlags, entry->saveResamplePitch, reverb->rightSaveResampleBuf); + + cmd = AudioSynth_SaveResampledReverbSamplesImpl(cmd, DMEM_WET_SCRATCH, entry->size, + &reverb->rightReverbBuf[entry->startPos]); + + if (entry->wrappedSize != 0) { + // Ring buffer wrapped + cmd = AudioSynth_SaveResampledReverbSamplesImpl(cmd, entry->size + DMEM_WET_SCRATCH, entry->wrappedSize, + reverb->rightReverbBuf); + } + + return cmd; +} + +Acmd* AudioSynth_LoadResampledReverbSamples(Acmd* cmd, s32 numSamplesPerUpdate, SynthesisReverb* reverb, + s16 updateIndex) { + ReverbBufferEntry* entry = &reverb->bufEntry[reverb->curFrame][updateIndex]; + s16 offsetSize = (entry->startPos & 7) * SAMPLE_SIZE; + s16 wrappedOffsetSize = ALIGN16(offsetSize + entry->size); + + cmd = AudioSynth_LoadReverbSamplesImpl(cmd, DMEM_WET_TEMP, entry->startPos - (offsetSize / (s32)SAMPLE_SIZE), + DMEM_1CH_SIZE, reverb); + + if (entry->wrappedSize != 0) { + // Ring buffer wrapped + cmd = AudioSynth_LoadReverbSamplesImpl(cmd, wrappedOffsetSize + DMEM_WET_TEMP, 0, + DMEM_1CH_SIZE - wrappedOffsetSize, reverb); + } + + aSetBuffer(cmd++, 0, DMEM_WET_TEMP + offsetSize, DMEM_WET_LEFT_CH, numSamplesPerUpdate * SAMPLE_SIZE); + aResample(cmd++, reverb->resampleFlags, entry->loadResamplePitch, reverb->leftLoadResampleBuf); + aSetBuffer(cmd++, 0, DMEM_WET_TEMP + DMEM_1CH_SIZE + offsetSize, DMEM_WET_RIGHT_CH, + numSamplesPerUpdate * SAMPLE_SIZE); + aResample(cmd++, reverb->resampleFlags, entry->loadResamplePitch, reverb->rightLoadResampleBuf); + + return cmd; +} + +/** + * Apply a filter (convolution) to each reverb channel. + */ +Acmd* AudioSynth_FilterReverb(Acmd* cmd, s32 size, SynthesisReverb* reverb) { + if (reverb->filterLeft != NULL) { + aFilter(cmd++, 2, size, reverb->filterLeft); + aFilter(cmd++, reverb->resampleFlags, DMEM_WET_LEFT_CH, reverb->filterLeftState); + } + + if (reverb->filterRight != NULL) { + aFilter(cmd++, 2, size, reverb->filterRight); + aFilter(cmd++, reverb->resampleFlags, DMEM_WET_RIGHT_CH, reverb->filterRightState); + } + + return cmd; +} + +/** + * Mix in reverb from a different reverb index + */ +Acmd* AudioSynth_MixOtherReverbIndex(Acmd* cmd, SynthesisReverb* reverb, s32 updateIndex) { + SynthesisReverb* mixReverb; + + if (reverb->mixReverbIndex >= gAudioContext.numSynthesisReverbs) { + return cmd; + } + + mixReverb = &gAudioContext.synthesisReverbs[reverb->mixReverbIndex]; + if (mixReverb->downsampleRate == 1) { + cmd = AudioSynth_LoadMixedReverbSamples(cmd, mixReverb, updateIndex); + aMix(cmd++, DMEM_2CH_SIZE >> 4, reverb->mixReverbStrength, DMEM_WET_LEFT_CH, DMEM_WET_TEMP); + cmd = AudioSynth_SaveMixedReverbSamples(cmd, mixReverb, updateIndex); + } + + return cmd; +} + +Acmd* AudioSynth_LoadDefaultReverbSamples(Acmd* cmd, s32 numSamplesPerUpdate, SynthesisReverb* reverb, + s16 updateIndex) { + ReverbBufferEntry* entry = &reverb->bufEntry[reverb->curFrame][updateIndex]; + + cmd = AudioSynth_LoadReverbSamplesImpl(cmd, DMEM_WET_LEFT_CH, entry->startPos, entry->size, reverb); + if (entry->wrappedSize != 0) { + // Ring buffer wrapped + cmd = AudioSynth_LoadReverbSamplesImpl(cmd, DMEM_WET_LEFT_CH + entry->size, 0, entry->wrappedSize, reverb); + } + + return cmd; +} + +Acmd* AudioSynth_LoadSubReverbSamples(Acmd* cmd, s32 numSamplesPerUpdate, SynthesisReverb* reverb, s16 updateIndex) { + ReverbBufferEntry* subEntry = &reverb->subBufEntry[reverb->curFrame][updateIndex]; + + cmd = AudioSynth_LoadReverbSamplesImpl(cmd, DMEM_WET_LEFT_CH, subEntry->startPos, subEntry->size, reverb); + if (subEntry->wrappedSize != 0) { + // Ring buffer wrapped + cmd = + AudioSynth_LoadReverbSamplesImpl(cmd, DMEM_WET_LEFT_CH + subEntry->size, 0, subEntry->wrappedSize, reverb); + } + + return cmd; +} + +Acmd* AudioSynth_SaveResampledReverbSamplesImpl(Acmd* cmd, u16 dmem, u16 size, uintptr_t startAddr) { + s32 startAddrAlignDropped; + u32 endAddr; + s32 endAddrAlignDropped; + + endAddr = startAddr + size; + + endAddrAlignDropped = endAddr & 0xF; + if (endAddrAlignDropped != 0) { + aLoadBuffer(cmd++, (endAddr - endAddrAlignDropped), DMEM_TEMP, 0x10); + aDMEMMove(cmd++, dmem, DMEM_TEMP2, size); + aDMEMMove(cmd++, DMEM_TEMP + endAddrAlignDropped, size + DMEM_TEMP2, 0x10 - endAddrAlignDropped); + + size += (0x10 - endAddrAlignDropped); + dmem = DMEM_TEMP2; + } + + startAddrAlignDropped = startAddr & 0xF; + if (startAddrAlignDropped != 0) { + aLoadBuffer(cmd++, startAddr - startAddrAlignDropped, DMEM_TEMP, 0x10); + aDMEMMove(cmd++, dmem, startAddrAlignDropped + DMEM_TEMP, size); + + size += startAddrAlignDropped; + dmem = DMEM_TEMP; + } + + aSaveBuffer(cmd++, dmem, startAddr - startAddrAlignDropped, size); + + return cmd; +} + +Acmd* AudioSynth_LoadReverbSamplesImpl(Acmd* cmd, u16 dmem, u16 startPos, s32 size, SynthesisReverb* reverb) { + aLoadBuffer(cmd++, &reverb->leftReverbBuf[startPos], dmem, size); + aLoadBuffer(cmd++, &reverb->rightReverbBuf[startPos], dmem + DMEM_1CH_SIZE, size); + + return cmd; +} + +Acmd* AudioSynth_SaveReverbSamplesImpl(Acmd* cmd, u16 dmem, u16 startPos, s32 size, SynthesisReverb* reverb) { + aSaveBuffer(cmd++, dmem, &reverb->leftReverbBuf[startPos], size); + aSaveBuffer(cmd++, dmem + DMEM_1CH_SIZE, &reverb->rightReverbBuf[startPos], size); + + return cmd; +} + +void AudioSynth_Noop26(void) { +} + +Acmd* AudioSynth_LoadSubReverbSamplesWithoutDownsample(Acmd* cmd, s32 numSamplesPerUpdate, SynthesisReverb* reverb, + s16 updateIndex) { + if (reverb->downsampleRate == 1) { + cmd = AudioSynth_LoadSubReverbSamples(cmd, numSamplesPerUpdate, reverb, updateIndex); + } + + return cmd; +} + +Acmd* AudioSynth_LoadReverbSamples(Acmd* cmd, s32 numSamplesPerUpdate, SynthesisReverb* reverb, s16 updateIndex) { + if (reverb->downsampleRate == 1) { + if (reverb->resampleEffectOn) { + cmd = AudioSynth_LoadResampledReverbSamples(cmd, numSamplesPerUpdate, reverb, updateIndex); + } else { + cmd = AudioSynth_LoadDefaultReverbSamples(cmd, numSamplesPerUpdate, reverb, updateIndex); + } + } else { + cmd = AudioSynth_LoadDownsampledReverbSamples(cmd, numSamplesPerUpdate, reverb, updateIndex); + } + + return cmd; +} + +Acmd* AudioSynth_SaveReverbSamples(Acmd* cmd, SynthesisReverb* reverb, s16 updateIndex) { + ReverbBufferEntry* entry = &reverb->bufEntry[reverb->curFrame][updateIndex]; + s32 downsampleRate; + s32 numSamples; + + if (reverb->downsampleRate == 1) { + if (reverb->resampleEffectOn) { + cmd = AudioSynth_SaveResampledReverbSamples(cmd, reverb, updateIndex); + } else { + // Put the oldest samples in the ring buffer into the wet channels + cmd = AudioSynth_SaveReverbSamplesImpl(cmd, DMEM_WET_LEFT_CH, entry->startPos, entry->size, reverb); + if (entry->wrappedSize != 0) { + // Ring buffer wrapped + cmd = AudioSynth_SaveReverbSamplesImpl(cmd, DMEM_WET_LEFT_CH + entry->size, 0, entry->wrappedSize, + reverb); + } + } + } else { + //! FAKE: + if (1) {} + + downsampleRate = reverb->downsampleRate; + numSamples = 13 * SAMPLES_PER_FRAME; + + while (downsampleRate >= 2) { + aInterl(cmd++, DMEM_WET_LEFT_CH, DMEM_WET_LEFT_CH, numSamples); + aInterl(cmd++, DMEM_WET_RIGHT_CH, DMEM_WET_RIGHT_CH, numSamples); + downsampleRate >>= 1; + numSamples >>= 1; + } + + if (entry->size != 0) { + cmd = AudioSynth_SaveResampledReverbSamplesImpl(cmd, DMEM_WET_LEFT_CH, entry->size, + &reverb->leftReverbBuf[entry->startPos]); + cmd = AudioSynth_SaveResampledReverbSamplesImpl(cmd, DMEM_WET_RIGHT_CH, entry->size, + &reverb->rightReverbBuf[entry->startPos]); + } + + if (entry->wrappedSize != 0) { + cmd = AudioSynth_SaveResampledReverbSamplesImpl(cmd, entry->size + DMEM_WET_LEFT_CH, entry->wrappedSize, + reverb->leftReverbBuf); + cmd = AudioSynth_SaveResampledReverbSamplesImpl(cmd, entry->size + DMEM_WET_RIGHT_CH, entry->wrappedSize, + reverb->rightReverbBuf); + } + } + + reverb->resampleFlags = 0; + + return cmd; +} + +Acmd* AudioSynth_SaveSubReverbSamples(Acmd* cmd, SynthesisReverb* reverb, s16 updateIndex) { + ReverbBufferEntry* subEntry = &reverb->subBufEntry[reverb->curFrame][updateIndex]; + + cmd = AudioSynth_SaveReverbSamplesImpl(cmd, DMEM_WET_LEFT_CH, subEntry->startPos, subEntry->size, reverb); + if (subEntry->wrappedSize != 0) { + // Ring buffer wrapped + cmd = + AudioSynth_SaveReverbSamplesImpl(cmd, DMEM_WET_LEFT_CH + subEntry->size, 0, subEntry->wrappedSize, reverb); + } + + return cmd; +} + +/** + * Process all samples embedded in a note. Every sample has numSamplesPerUpdate processed, + * and each of those are mixed together into both DMEM_LEFT_CH and DMEM_RIGHT_CH + */ +Acmd* AudioSynth_ProcessSamples(s16* aiBuf, s32 numSamplesPerUpdate, Acmd* cmd, s32 updateIndex) { + s32 size; + u8 noteIndices[0x58]; + s16 noteCount = 0; + s16 reverbIndex; + SynthesisReverb* reverb; + s32 useReverb; + s32 sampleStateOffset = gAudioContext.numNotes * updateIndex; + s32 i; + + if (gAudioContext.numSynthesisReverbs == 0) { + for (i = 0; i < gAudioContext.numNotes; i++) { + if (gAudioContext.sampleStateList[sampleStateOffset + i].bitField0.enabled) { + noteIndices[noteCount++] = i; + } + } + } else { + NoteSampleState* sampleState; + + for (reverbIndex = 0; reverbIndex < gAudioContext.numSynthesisReverbs; reverbIndex++) { + for (i = 0; i < gAudioContext.numNotes; i++) { + sampleState = &gAudioContext.sampleStateList[sampleStateOffset + i]; + if (sampleState->bitField0.enabled && (sampleState->bitField1.reverbIndex == reverbIndex)) { + noteIndices[noteCount++] = i; + } + } + } + + for (i = 0; i < gAudioContext.numNotes; i++) { + sampleState = &gAudioContext.sampleStateList[sampleStateOffset + i]; + if (sampleState->bitField0.enabled && + (sampleState->bitField1.reverbIndex >= gAudioContext.numSynthesisReverbs)) { + noteIndices[noteCount++] = i; + } + } + } + + aClearBuffer(cmd++, DMEM_LEFT_CH, DMEM_2CH_SIZE); + + i = 0; + for (reverbIndex = 0; reverbIndex < gAudioContext.numSynthesisReverbs; reverbIndex++) { + s32 subDelay; + NoteSampleState* sampleState; + + reverb = &gAudioContext.synthesisReverbs[reverbIndex]; + useReverb = reverb->useReverb; + if (useReverb) { + + // Loads reverb samples from DRAM (ringBuffer) into DMEM (DMEM_WET_LEFT_CH) + cmd = AudioSynth_LoadReverbSamples(cmd, numSamplesPerUpdate, reverb, updateIndex); + + // Mixes reverb sample into the main dry channel + // reverb->volume is always set to 0x7FFF (audio spec), and DMEM_LEFT_CH is cleared before reverbs. + // So this is essentially a DMEMmove from DMEM_WET_LEFT_CH to DMEM_LEFT_CH + aMix(cmd++, DMEM_2CH_SIZE >> 4, reverb->volume, DMEM_WET_LEFT_CH, DMEM_LEFT_CH); + + subDelay = reverb->subDelay; + if (subDelay != 0) { + aDMEMMove(cmd++, DMEM_WET_LEFT_CH, DMEM_WET_TEMP, DMEM_2CH_SIZE); + } + + // Decays reverb over time. The (+ 0x8000) here is -100% + aMix(cmd++, DMEM_2CH_SIZE >> 4, reverb->decayRatio + 0x8000, DMEM_WET_LEFT_CH, DMEM_WET_LEFT_CH); + + if (((reverb->leakRtl != 0) || (reverb->leakLtr != 0)) && (gAudioContext.soundMode != SOUNDMODE_MONO)) { + cmd = AudioSynth_LeakReverb(cmd, reverb); + } + + if (subDelay != 0) { + if (reverb->mixReverbIndex != REVERB_INDEX_NONE) { + cmd = AudioSynth_MixOtherReverbIndex(cmd, reverb, updateIndex); + } + cmd = AudioSynth_SaveReverbSamples(cmd, reverb, updateIndex); + cmd = AudioSynth_LoadSubReverbSamplesWithoutDownsample(cmd, numSamplesPerUpdate, reverb, updateIndex); + aMix(cmd++, DMEM_2CH_SIZE >> 4, reverb->subVolume, DMEM_WET_TEMP, DMEM_WET_LEFT_CH); + } + } + + while (i < noteCount) { + sampleState = &gAudioContext.sampleStateList[sampleStateOffset + noteIndices[i]]; + if (sampleState->bitField1.reverbIndex != reverbIndex) { + break; + } + cmd = AudioSynth_ProcessSample(noteIndices[i], sampleState, + &gAudioContext.notes[noteIndices[i]].synthesisState, aiBuf, + numSamplesPerUpdate, cmd, updateIndex); + i++; + } + + if (useReverb) { + if ((reverb->filterLeft != NULL) || (reverb->filterRight != NULL)) { + cmd = AudioSynth_FilterReverb(cmd, numSamplesPerUpdate * SAMPLE_SIZE, reverb); + } + + // Saves the wet channel sample from DMEM (DMEM_WET_LEFT_CH) into (ringBuffer) DRAM for future use + if (subDelay != 0) { + cmd = AudioSynth_SaveSubReverbSamples(cmd, reverb, updateIndex); + } else { + if (reverb->mixReverbIndex != REVERB_INDEX_NONE) { + cmd = AudioSynth_MixOtherReverbIndex(cmd, reverb, updateIndex); + } + cmd = AudioSynth_SaveReverbSamples(cmd, reverb, updateIndex); + } + } + } + + while (i < noteCount) { + cmd = AudioSynth_ProcessSample( + noteIndices[i], &gAudioContext.sampleStateList[sampleStateOffset + noteIndices[i]], + &gAudioContext.notes[noteIndices[i]].synthesisState, aiBuf, numSamplesPerUpdate, cmd, updateIndex); + i++; + } + + size = numSamplesPerUpdate * SAMPLE_SIZE; + aInterleave(cmd++, DMEM_TEMP, DMEM_LEFT_CH, DMEM_RIGHT_CH, size); + + if (gCustomAudioSynthFunction != NULL) { + cmd = gCustomAudioSynthFunction(cmd, 2 * size, updateIndex); + } + aSaveBuffer(cmd++, DMEM_TEMP, aiBuf, 2 * size); + + return cmd; +} + +Acmd* AudioSynth_ProcessSample(s32 noteIndex, NoteSampleState* sampleState, NoteSynthesisState* synthState, s16* aiBuf, + s32 numSamplesPerUpdate, Acmd* cmd, s32 updateIndex) { + s32 pad1[2]; + void* reverbAddrSrc; + Sample* sample; + AdpcmLoop* loopInfo; + s32 numSamplesUntilEnd; + s32 numSamplesInThisIteration; + s32 sampleFinished; + s32 loopToPoint; + s32 flags; + u16 frequencyFixedPoint; + s32 gain; + s32 frameIndex; + s32 skipBytes; + void* combFilterState; + s32 numSamplesToDecode; + s32 numFirstFrameSamplesToIgnore; + u8* sampleAddr; + u32 numSamplesToLoadFixedPoint; + s32 numSamplesToLoadAdj; + s32 numSamplesProcessed; + s32 sampleEndPos; + s32 numSamplesToProcess; + s32 dmemUncompressedAddrOffset2; + s32 pad2[3]; + s32 numSamplesInFirstFrame; + s32 numTrailingSamplesToIgnore; + s32 pad3[3]; + s32 frameSize; + s32 numFramesToDecode; + s32 skipInitialSamples; + s32 zeroOffset; + u8* samplesToLoadAddr; + s32 numParts; + s32 curPart; + s32 sampleDataChunkAlignPad; + s32 haasEffectDelaySide; + s32 numSamplesToLoadFirstPart; + u16 sampleDmemBeforeResampling; + s32 sampleAddrOffset; + s32 combFilterDmem; + s32 dmemUncompressedAddrOffset1; + Note* note; + u32 numSamplesToLoad; + u16 combFilterSize; + u16 combFilterGain; + s16* filter; + s32 bookOffset = sampleState->bitField1.bookOffset; + s32 finished = sampleState->bitField0.finished; + s32 sampleDataChunkSize; + s16 sampleDataDmemAddr; + + note = &gAudioContext.notes[noteIndex]; + flags = A_CONTINUE; + + // Initialize the synthesis state + if (sampleState->bitField0.needsInit == true) { + flags = A_INIT; + synthState->atLoopPoint = false; + synthState->stopLoop = false; + synthState->samplePosInt = note->playbackState.startSamplePos; + synthState->samplePosFrac = 0; + synthState->curVolLeft = 0; + synthState->curVolRight = 0; + synthState->prevHaasEffectLeftDelaySize = 0; + synthState->prevHaasEffectRightDelaySize = 0; + synthState->curReverbVol = sampleState->targetReverbVol; + synthState->numParts = 0; + synthState->combFilterNeedsInit = true; + note->sampleState.bitField0.finished = false; + synthState->unk_1F = note->playbackState.unk_80; // Never set, never used + finished = false; + } + + // Process the sample in either one or two parts + numParts = sampleState->bitField1.hasTwoParts + 1; + + // Determine number of samples to load based on numSamplesPerUpdate and relative frequency + frequencyFixedPoint = sampleState->frequencyFixedPoint; + numSamplesToLoadFixedPoint = (frequencyFixedPoint * numSamplesPerUpdate * 2) + synthState->samplePosFrac; + numSamplesToLoad = numSamplesToLoadFixedPoint >> 16; + + if (numSamplesToLoad == 0) { + skipBytes = false; + } + + synthState->samplePosFrac = numSamplesToLoadFixedPoint & 0xFFFF; + + // Partially-optimized out no-op ifs required for matching. SM64 decomp + // makes it clear that this is how it should look. + if ((synthState->numParts == 1) && (numParts == 2)) { + } else if ((synthState->numParts == 2) && (numParts == 1)) { + } else { + } + + synthState->numParts = numParts; + + if (sampleState->bitField1.isSyntheticWave) { + cmd = AudioSynth_LoadWaveSamples(cmd, sampleState, synthState, numSamplesToLoad); + sampleDmemBeforeResampling = DMEM_UNCOMPRESSED_NOTE + (synthState->samplePosInt * 2); + synthState->samplePosInt += numSamplesToLoad; + } else { + sample = sampleState->tunedSample->sample; + loopInfo = sample->loop; + + if (note->playbackState.status != PLAYBACK_STATUS_0) { + synthState->stopLoop = true; + } + + if ((loopInfo->count == 2) && synthState->stopLoop) { + sampleEndPos = loopInfo->sampleEnd; + } else { + sampleEndPos = loopInfo->loopEnd; + } + + sampleAddr = sample->sampleAddr; + numSamplesToLoadFirstPart = 0; + + // If the frequency requested is more than double that of the raw sample, + // then the sample processing is split into two parts. + for (curPart = 0; curPart < numParts; curPart++) { + numSamplesProcessed = 0; + dmemUncompressedAddrOffset1 = 0; + + // Adjust the number of samples to load only if there are two parts and an odd number of samples + if (numParts == 1) { + numSamplesToLoadAdj = numSamplesToLoad; + } else if (numSamplesToLoad & 1) { + // round down for the first part + // round up for the second part + numSamplesToLoadAdj = (numSamplesToLoad & ~1) + (curPart * 2); + } else { + numSamplesToLoadAdj = numSamplesToLoad; + } + + // Load the ADPCM codeBook + if ((sample->codec == CODEC_ADPCM) || (sample->codec == CODEC_SMALL_ADPCM)) { + if (gAudioContext.adpcmCodeBook != sample->book->codeBook) { + u32 numEntries; + + switch (bookOffset) { + case 1: + gAudioContext.adpcmCodeBook = &gInvalidAdpcmCodeBook[1]; + break; + + case 2: + case 3: + default: + gAudioContext.adpcmCodeBook = sample->book->codeBook; + break; + } + + numEntries = SAMPLES_PER_FRAME * sample->book->order * sample->book->numPredictors; + aLoadADPCM(cmd++, numEntries, gAudioContext.adpcmCodeBook); + } + } + + // Continue processing samples until the number of samples needed to load is reached + while (numSamplesProcessed != numSamplesToLoadAdj) { + sampleFinished = false; + loopToPoint = false; + dmemUncompressedAddrOffset2 = 0; + + numFirstFrameSamplesToIgnore = synthState->samplePosInt & 0xF; + numSamplesUntilEnd = sampleEndPos - synthState->samplePosInt; + + // Calculate number of samples to process this loop + numSamplesToProcess = numSamplesToLoadAdj - numSamplesProcessed; + + if ((numFirstFrameSamplesToIgnore == 0) && !synthState->atLoopPoint) { + numFirstFrameSamplesToIgnore = SAMPLES_PER_FRAME; + } + numSamplesInFirstFrame = SAMPLES_PER_FRAME - numFirstFrameSamplesToIgnore; + + // Determine the number of samples to decode based on whether the end will be reached or not. + if (numSamplesToProcess < numSamplesUntilEnd) { + // The end will not be reached. + numFramesToDecode = + (s32)(numSamplesToProcess - numSamplesInFirstFrame + SAMPLES_PER_FRAME - 1) / SAMPLES_PER_FRAME; + numSamplesToDecode = numFramesToDecode * SAMPLES_PER_FRAME; + numTrailingSamplesToIgnore = numSamplesInFirstFrame + numSamplesToDecode - numSamplesToProcess; + } else { + // The end will be reached. + numSamplesToDecode = numSamplesUntilEnd - numSamplesInFirstFrame; + numTrailingSamplesToIgnore = 0; + if (numSamplesToDecode <= 0) { + numSamplesToDecode = 0; + numSamplesInFirstFrame = numSamplesUntilEnd; + } + numFramesToDecode = (numSamplesToDecode + SAMPLES_PER_FRAME - 1) / SAMPLES_PER_FRAME; + if (loopInfo->count != 0) { + if ((loopInfo->count == 2) && synthState->stopLoop) { + sampleFinished = true; + } else { + // Loop around and restart + loopToPoint = true; + } + } else { + sampleFinished = true; + } + } + + // Set parameters based on compression type + switch (sample->codec) { + case CODEC_ADPCM: + // 16 2-byte samples (32 bytes) compressed into 4-bit samples (8 bytes) + 1 header byte + frameSize = 9; + skipInitialSamples = SAMPLES_PER_FRAME; + zeroOffset = 0; + break; + + case CODEC_SMALL_ADPCM: + // 16 2-byte samples (32 bytes) compressed into 2-bit samples (4 bytes) + 1 header byte + frameSize = 5; + skipInitialSamples = SAMPLES_PER_FRAME; + zeroOffset = 0; + break; + + case CODEC_UNK7: + // 2 2-byte samples (4 bytes) processed without decompression + frameSize = 4; + skipInitialSamples = SAMPLES_PER_FRAME; + zeroOffset = 0; + break; + + case CODEC_S8: + // 16 2-byte samples (32 bytes) compressed into 8-bit samples (16 bytes) + frameSize = 16; + skipInitialSamples = SAMPLES_PER_FRAME; + zeroOffset = 0; + break; + + case CODEC_REVERB: + reverbAddrSrc = (void*)0xFFFFFFFF; + if (gCustomAudioReverbFunction != NULL) { + reverbAddrSrc = gCustomAudioReverbFunction(sample, numSamplesToLoadAdj, flags, noteIndex); + } + + if (reverbAddrSrc == (void*)0xFFFFFFFF) { + sampleFinished = true; + } else if (reverbAddrSrc == NULL) { + return cmd; + } else { + AudioSynth_LoadBuffer(cmd++, DMEM_UNCOMPRESSED_NOTE, + (numSamplesToLoadAdj + SAMPLES_PER_FRAME) * SAMPLE_SIZE, + reverbAddrSrc); + flags = A_CONTINUE; + skipBytes = 0; + numSamplesProcessed = numSamplesToLoadAdj; + dmemUncompressedAddrOffset1 = numSamplesToLoadAdj; + } + goto skip; + + case CODEC_S16_INMEMORY: + case CODEC_UNK6: + AudioSynth_ClearBuffer(cmd++, DMEM_UNCOMPRESSED_NOTE, + (numSamplesToLoadAdj + SAMPLES_PER_FRAME) * SAMPLE_SIZE); + flags = A_CONTINUE; + skipBytes = 0; + numSamplesProcessed = numSamplesToLoadAdj; + dmemUncompressedAddrOffset1 = numSamplesToLoadAdj; + goto skip; + + case CODEC_S16: + AudioSynth_ClearBuffer(cmd++, DMEM_UNCOMPRESSED_NOTE, + (numSamplesToLoadAdj + SAMPLES_PER_FRAME) * SAMPLE_SIZE); + flags = A_CONTINUE; + skipBytes = 0; + numSamplesProcessed = numSamplesToLoadAdj; + dmemUncompressedAddrOffset1 = numSamplesToLoadAdj; + goto skip; + + default: + break; + } + + // Move the compressed raw sample data from ram into the rsp (DMEM) + if (numFramesToDecode != 0) { + // Get the offset from the start of the sample to where the sample is currently playing from + frameIndex = (synthState->samplePosInt + skipInitialSamples - numFirstFrameSamplesToIgnore) / + SAMPLES_PER_FRAME; + sampleAddrOffset = frameIndex * frameSize; + + // Get the ram address of the requested sample chunk + if (sample->medium == MEDIUM_RAM) { + // Sample is already loaded into ram + samplesToLoadAddr = sampleAddr + (zeroOffset + sampleAddrOffset); + } else if (gAudioContext.unk_29B8) { // always false + return cmd; + } else if (sample->medium == MEDIUM_UNK) { + // This medium is unsupported so terminate processing this note + return cmd; + } else { + // This medium is not in ram, so dma the requested sample into ram + samplesToLoadAddr = + AudioLoad_DmaSampleData(sampleAddr + (zeroOffset + sampleAddrOffset), + ALIGN16((numFramesToDecode * frameSize) + SAMPLES_PER_FRAME), flags, + &synthState->sampleDmaIndex, sample->medium); + } + + if (samplesToLoadAddr == NULL) { + // The ram address was unsuccessfully allocated + return cmd; + } + + // Move the raw sample chunk from ram to the rsp + // DMEM at the addresses before DMEM_COMPRESSED_ADPCM_DATA + sampleDataChunkAlignPad = (u32)samplesToLoadAddr & 0xF; + sampleDataChunkSize = ALIGN16((numFramesToDecode * frameSize) + SAMPLES_PER_FRAME); + sampleDataDmemAddr = DMEM_COMPRESSED_ADPCM_DATA - sampleDataChunkSize; + aLoadBuffer(cmd++, samplesToLoadAddr - sampleDataChunkAlignPad, sampleDataDmemAddr, + sampleDataChunkSize); + } else { + numSamplesToDecode = 0; + sampleDataChunkAlignPad = 0; + } + + if (synthState->atLoopPoint) { + aSetLoop(cmd++, sample->loop->predictorState); + flags = A_LOOP; + synthState->atLoopPoint = false; + } + + numSamplesInThisIteration = numSamplesToDecode + numSamplesInFirstFrame - numTrailingSamplesToIgnore; + + if (numSamplesProcessed == 0) { + //! FAKE: + if (1) {} + skipBytes = numFirstFrameSamplesToIgnore * SAMPLE_SIZE; + } else { + dmemUncompressedAddrOffset2 = ALIGN16(dmemUncompressedAddrOffset1 + 8 * SAMPLE_SIZE); + } + + // Decompress the raw sample chunks in the rsp + // Goes from adpcm (compressed) sample data to pcm (uncompressed) sample data + switch (sample->codec) { + case CODEC_ADPCM: + sampleDataChunkSize = ALIGN16((numFramesToDecode * frameSize) + SAMPLES_PER_FRAME); + sampleDataDmemAddr = DMEM_COMPRESSED_ADPCM_DATA - sampleDataChunkSize; + aSetBuffer(cmd++, 0, sampleDataDmemAddr + sampleDataChunkAlignPad, + DMEM_UNCOMPRESSED_NOTE + dmemUncompressedAddrOffset2, + numSamplesToDecode * SAMPLE_SIZE); + aADPCMdec(cmd++, flags, synthState->synthesisBuffers->adpcmState); + break; + + case CODEC_SMALL_ADPCM: + sampleDataChunkSize = ALIGN16((numFramesToDecode * frameSize) + SAMPLES_PER_FRAME); + sampleDataDmemAddr = DMEM_COMPRESSED_ADPCM_DATA - sampleDataChunkSize; + aSetBuffer(cmd++, 0, sampleDataDmemAddr + sampleDataChunkAlignPad, + DMEM_UNCOMPRESSED_NOTE + dmemUncompressedAddrOffset2, + numSamplesToDecode * SAMPLE_SIZE); + aADPCMdec(cmd++, flags | A_ADPCM_SHORT, synthState->synthesisBuffers->adpcmState); + break; + + case CODEC_S8: + sampleDataChunkSize = ALIGN16((numFramesToDecode * frameSize) + SAMPLES_PER_FRAME); + sampleDataDmemAddr = DMEM_COMPRESSED_ADPCM_DATA - sampleDataChunkSize; + AudioSynth_SetBuffer(cmd++, 0, sampleDataDmemAddr + sampleDataChunkAlignPad, + DMEM_UNCOMPRESSED_NOTE + dmemUncompressedAddrOffset2, + numSamplesToDecode * SAMPLE_SIZE); + AudioSynth_S8Dec(cmd++, flags, synthState->synthesisBuffers->adpcmState); + break; + + case CODEC_UNK7: + default: + // No decompression + break; + } + + if (numSamplesProcessed != 0) { + aDMEMMove(cmd++, + DMEM_UNCOMPRESSED_NOTE + dmemUncompressedAddrOffset2 + + (numFirstFrameSamplesToIgnore * SAMPLE_SIZE), + DMEM_UNCOMPRESSED_NOTE + dmemUncompressedAddrOffset1, + numSamplesInThisIteration * SAMPLE_SIZE); + } + + numSamplesProcessed += numSamplesInThisIteration; + + switch (flags) { + case A_INIT: + skipBytes = SAMPLES_PER_FRAME * SAMPLE_SIZE; + dmemUncompressedAddrOffset1 = (numSamplesToDecode + SAMPLES_PER_FRAME) * SAMPLE_SIZE; + break; + + case A_LOOP: + dmemUncompressedAddrOffset1 = + numSamplesInThisIteration * SAMPLE_SIZE + dmemUncompressedAddrOffset1; + break; + + default: + if (dmemUncompressedAddrOffset1 != 0) { + dmemUncompressedAddrOffset1 = + numSamplesInThisIteration * SAMPLE_SIZE + dmemUncompressedAddrOffset1; + } else { + dmemUncompressedAddrOffset1 = + (numFirstFrameSamplesToIgnore + numSamplesInThisIteration) * SAMPLE_SIZE; + } + break; + } + + flags = A_CONTINUE; + + skip: + + // Update what to do with the samples next + if (sampleFinished) { + if ((numSamplesToLoadAdj - numSamplesProcessed) != 0) { + AudioSynth_ClearBuffer(cmd++, DMEM_UNCOMPRESSED_NOTE + dmemUncompressedAddrOffset1, + (numSamplesToLoadAdj - numSamplesProcessed) * SAMPLE_SIZE); + } + finished = true; + note->sampleState.bitField0.finished = true; + AudioSynth_DisableSampleStates(updateIndex, noteIndex); + break; // break out of the for-loop + } else if (loopToPoint) { + synthState->atLoopPoint = true; + synthState->samplePosInt = loopInfo->start; + } else { + synthState->samplePosInt += numSamplesToProcess; + } + } + + switch (numParts) { + case 1: + sampleDmemBeforeResampling = DMEM_UNCOMPRESSED_NOTE + skipBytes; + break; + + case 2: + switch (curPart) { + case 0: + AudioSynth_InterL(cmd++, DMEM_UNCOMPRESSED_NOTE + skipBytes, + DMEM_TEMP + (SAMPLES_PER_FRAME * SAMPLE_SIZE), + ALIGN8(numSamplesToLoadAdj / 2)); + numSamplesToLoadFirstPart = numSamplesToLoadAdj; + sampleDmemBeforeResampling = DMEM_TEMP + (SAMPLES_PER_FRAME * SAMPLE_SIZE); + if (finished) { + AudioSynth_ClearBuffer(cmd++, sampleDmemBeforeResampling + numSamplesToLoadFirstPart, + numSamplesToLoadAdj + SAMPLES_PER_FRAME); + } + break; + + case 1: + AudioSynth_InterL(cmd++, DMEM_UNCOMPRESSED_NOTE + skipBytes, + DMEM_TEMP + (SAMPLES_PER_FRAME * SAMPLE_SIZE) + numSamplesToLoadFirstPart, + ALIGN8(numSamplesToLoadAdj / 2)); + break; + + default: + break; + } + break; + + default: + break; + } + if (finished) { + break; + } + } + } + + // Update the flags for the signal processing below + flags = A_CONTINUE; + if (sampleState->bitField0.needsInit == true) { + sampleState->bitField0.needsInit = false; + flags = A_INIT; + } + + // Resample the decompressed mono-signal to the correct pitch + cmd = AudioSynth_FinalResample(cmd, synthState, numSamplesPerUpdate * SAMPLE_SIZE, frequencyFixedPoint, + sampleDmemBeforeResampling, flags); + + // UnkCmd19 was removed from the audio microcode + // This block performs no operation + if (bookOffset == 3) { + AudioSynth_UnkCmd19(cmd++, DMEM_TEMP, DMEM_TEMP, numSamplesPerUpdate * (s32)SAMPLE_SIZE, 0); + } + + // Apply the gain to the mono-signal to adjust the volume + gain = sampleState->gain; + if (gain != 0) { + // A gain of 0x10 (a UQ4.4 number) is equivalent to 1.0 and represents no volume change + if (gain < 0x10) { + gain = 0x10; + } + AudioSynth_HiLoGain(cmd++, gain, DMEM_TEMP, 0, (numSamplesPerUpdate + SAMPLES_PER_FRAME) * SAMPLE_SIZE); + } + + // Apply the filter to the mono-signal + filter = sampleState->filter; + if (filter != 0) { + AudioSynth_LoadFilterSize(cmd++, numSamplesPerUpdate * SAMPLE_SIZE, filter); + AudioSynth_LoadFilterBuffer(cmd++, flags, DMEM_TEMP, synthState->synthesisBuffers->filterState); + } + + // Apply the comb filter to the mono-signal by taking the signal with a small temporal offset, + // and adding it back to itself + combFilterSize = sampleState->combFilterSize; + combFilterGain = sampleState->combFilterGain; + combFilterState = synthState->synthesisBuffers->combFilterState; + if ((combFilterSize != 0) && (sampleState->combFilterGain != 0)) { + AudioSynth_DMemMove(cmd++, DMEM_TEMP, DMEM_COMB_TEMP, numSamplesPerUpdate * SAMPLE_SIZE); + combFilterDmem = DMEM_COMB_TEMP - combFilterSize; + if (synthState->combFilterNeedsInit) { + AudioSynth_ClearBuffer(cmd++, combFilterDmem, combFilterSize); + synthState->combFilterNeedsInit = false; + } else { + AudioSynth_LoadBuffer(cmd++, combFilterDmem, combFilterSize, combFilterState); + } + AudioSynth_SaveBuffer(cmd++, DMEM_TEMP + (numSamplesPerUpdate * SAMPLE_SIZE) - combFilterSize, combFilterSize, + combFilterState); + AudioSynth_Mix(cmd++, (numSamplesPerUpdate * (s32)SAMPLE_SIZE) >> 4, combFilterGain, DMEM_COMB_TEMP, + combFilterDmem); + AudioSynth_DMemMove(cmd++, combFilterDmem, DMEM_TEMP, numSamplesPerUpdate * SAMPLE_SIZE); + } else { + synthState->combFilterNeedsInit = true; + } + + // Determine the behavior of the audio processing that leads to the haas effect + if ((sampleState->haasEffectLeftDelaySize != 0) || (synthState->prevHaasEffectLeftDelaySize != 0)) { + haasEffectDelaySide = HAAS_EFFECT_DELAY_LEFT; + } else if ((sampleState->haasEffectRightDelaySize != 0) || (synthState->prevHaasEffectRightDelaySize != 0)) { + haasEffectDelaySide = HAAS_EFFECT_DELAY_RIGHT; + } else { + haasEffectDelaySide = HAAS_EFFECT_DELAY_NONE; + } + + // Apply an unknown effect based on the surround sound-mode + if (gAudioContext.soundMode == SOUNDMODE_SURROUND) { + sampleState->targetVolLeft = sampleState->targetVolLeft >> 1; + sampleState->targetVolRight = sampleState->targetVolRight >> 1; + if (sampleState->surroundEffectIndex != 0xFF) { + cmd = AudioSynth_ApplySurroundEffect(cmd, sampleState, synthState, numSamplesPerUpdate, DMEM_TEMP, flags); + } + } + + // Split the mono-signal into left and right channels: + // Both for dry signal (to go to the speakers now) + // and for wet signal (to go to a reverb buffer to be stored, and brought back later to produce an echo) + cmd = AudioSynth_ProcessEnvelope(cmd, sampleState, synthState, numSamplesPerUpdate, DMEM_TEMP, haasEffectDelaySide, + flags); + + // Apply the haas effect by delaying either the left or the right channel by a small amount + if (sampleState->bitField1.useHaasEffect) { + if (!(flags & A_INIT)) { + flags = A_CONTINUE; + } + cmd = AudioSynth_ApplyHaasEffect(cmd, sampleState, synthState, numSamplesPerUpdate * (s32)SAMPLE_SIZE, flags, + haasEffectDelaySide); + } + + return cmd; +} + +Acmd* AudioSynth_ApplySurroundEffect(Acmd* cmd, NoteSampleState* sampleState, NoteSynthesisState* synthState, + s32 numSamplesPerUpdate, s32 haasDmem, s32 flags) { + s32 wetGain; + u16 dryGain; + s64 dmem = DMEM_SURROUND_TEMP; + f32 decayGain; + + AudioSynth_DMemMove(cmd++, haasDmem, DMEM_HAAS_TEMP, numSamplesPerUpdate * SAMPLE_SIZE); + dryGain = synthState->surroundEffectGain; + + if (flags == A_INIT) { + aClearBuffer(cmd++, dmem, sizeof(synthState->synthesisBuffers->surroundEffectState)); + synthState->surroundEffectGain = 0; + } else { + aLoadBuffer(cmd++, synthState->synthesisBuffers->surroundEffectState, dmem, + sizeof(synthState->synthesisBuffers->surroundEffectState)); + aMix(cmd++, (numSamplesPerUpdate * (s32)SAMPLE_SIZE) >> 4, dryGain, dmem, DMEM_LEFT_CH); + aMix(cmd++, (numSamplesPerUpdate * (s32)SAMPLE_SIZE) >> 4, (dryGain ^ 0xFFFF), dmem, DMEM_RIGHT_CH); + + wetGain = (dryGain * synthState->curReverbVol) >> 7; + + aMix(cmd++, (numSamplesPerUpdate * (s32)SAMPLE_SIZE) >> 4, wetGain, dmem, DMEM_WET_LEFT_CH); + aMix(cmd++, (numSamplesPerUpdate * (s32)SAMPLE_SIZE) >> 4, (wetGain ^ 0xFFFF), dmem, DMEM_WET_RIGHT_CH); + } + + aSaveBuffer(cmd++, DMEM_SURROUND_TEMP + (numSamplesPerUpdate * SAMPLE_SIZE), + synthState->synthesisBuffers->surroundEffectState, + sizeof(synthState->synthesisBuffers->surroundEffectState)); + + decayGain = (sampleState->targetVolLeft + sampleState->targetVolRight) * (1.0f / 0x2000); + + if (decayGain > 1.0f) { + decayGain = 1.0f; + } + + decayGain = decayGain * gDefaultPanVolume[127 - sampleState->surroundEffectIndex]; + synthState->surroundEffectGain = ((decayGain * 0x7FFF) + synthState->surroundEffectGain) / 2; + + AudioSynth_DMemMove(cmd++, DMEM_HAAS_TEMP, haasDmem, numSamplesPerUpdate * SAMPLE_SIZE); + + return cmd; +} + +Acmd* AudioSynth_FinalResample(Acmd* cmd, NoteSynthesisState* synthState, s32 size, u16 pitch, u16 inpDmem, + s32 resampleFlags) { + if (pitch == 0) { + AudioSynth_ClearBuffer(cmd++, DMEM_TEMP, size); + } else { + aSetBuffer(cmd++, 0, inpDmem, DMEM_TEMP, size); + aResample(cmd++, resampleFlags, pitch, synthState->synthesisBuffers->finalResampleState); + } + + return cmd; +} + +Acmd* AudioSynth_ProcessEnvelope(Acmd* cmd, NoteSampleState* sampleState, NoteSynthesisState* synthState, + s32 numSamplesPerUpdate, u16 dmemSrc, s32 haasEffectDelaySide, s32 flags) { + u32 dmemDests; + u16 curVolLeft; + u16 targetVolLeft; + s32 curReverbVol; + u16 curVolRight; + s16 targetReverbVol; + s16 rampLeft; + s16 rampRight; + s16 rampReverb; + s16 curReverbVolAndFlags; + u16 targetVolRight; + f32 defaultPanVolume; + s32 pad; + + targetReverbVol = sampleState->targetReverbVol; + + curVolLeft = synthState->curVolLeft; + curVolRight = synthState->curVolRight; + + targetVolLeft = sampleState->targetVolLeft; + targetVolLeft <<= 4; + targetVolRight = sampleState->targetVolRight; + targetVolRight <<= 4; + + if ((gAudioContext.soundMode == SOUNDMODE_SURROUND) && (sampleState->surroundEffectIndex != 0xFF)) { + defaultPanVolume = gDefaultPanVolume[sampleState->surroundEffectIndex]; + targetVolLeft *= defaultPanVolume; + targetVolRight *= defaultPanVolume; + } + + if (targetVolLeft != curVolLeft) { + rampLeft = (targetVolLeft - curVolLeft) / (numSamplesPerUpdate >> 3); + } else { + rampLeft = 0; + } + + if (targetVolRight != curVolRight) { + rampRight = (targetVolRight - curVolRight) / (numSamplesPerUpdate >> 3); + } else { + rampRight = 0; + } + + curReverbVolAndFlags = synthState->curReverbVol; + curReverbVol = curReverbVolAndFlags & 0x7F; + + if (curReverbVolAndFlags != targetReverbVol) { + rampReverb = (((targetReverbVol & 0x7F) - curReverbVol) << 9) / (numSamplesPerUpdate >> 3); + synthState->curReverbVol = targetReverbVol; + } else { + rampReverb = 0; + } + + synthState->curVolLeft = curVolLeft + (rampLeft * (numSamplesPerUpdate >> 3)); + synthState->curVolRight = curVolRight + (rampRight * (numSamplesPerUpdate >> 3)); + + if (sampleState->bitField1.useHaasEffect) { + AudioSynth_ClearBuffer(cmd++, DMEM_HAAS_TEMP, DMEM_1CH_SIZE); + AudioSynth_EnvSetup1(cmd++, curReverbVol * 2, rampReverb, rampLeft, rampRight); + AudioSynth_EnvSetup2(cmd++, curVolLeft, curVolRight); + + switch (haasEffectDelaySide) { + case HAAS_EFFECT_DELAY_LEFT: + // Store the left dry channel in a temp space to be delayed to produce the haas effect + dmemDests = sEnvMixerLeftHaasDmemDests; + break; + + case HAAS_EFFECT_DELAY_RIGHT: + // Store the right dry channel in a temp space to be delayed to produce the haas effect + dmemDests = sEnvMixerRightHaasDmemDests; + break; + + default: // HAAS_EFFECT_DELAY_NONE + dmemDests = sEnvMixerDefaultDmemDests; + break; + } + } else { + aEnvSetup1(cmd++, curReverbVol * 2, rampReverb, rampLeft, rampRight); + aEnvSetup2(cmd++, curVolLeft, curVolRight); + dmemDests = sEnvMixerDefaultDmemDests; + } + + aEnvMixer(cmd++, dmemSrc, numSamplesPerUpdate, (curReverbVolAndFlags & 0x80) >> 7, + sampleState->bitField0.strongReverbRight, sampleState->bitField0.strongReverbLeft, + sampleState->bitField0.strongRight, sampleState->bitField0.strongLeft, dmemDests, sEnvMixerOp); + + return cmd; +} + +Acmd* AudioSynth_LoadWaveSamples(Acmd* cmd, NoteSampleState* sampleState, NoteSynthesisState* synthState, + s32 numSamplesToLoad) { + s32 numSamplesAvailable; + s32 harmonicIndexCurAndPrev = sampleState->harmonicIndexCurAndPrev; + s32 samplePosInt = synthState->samplePosInt; + s32 numDuplicates; + + if (sampleState->bitField1.bookOffset != 0) { + // Move the noise wave (that reads compiled assembly as samples) from ram to dmem + AudioSynth_LoadBuffer(cmd++, DMEM_UNCOMPRESSED_NOTE, ALIGN16(numSamplesToLoad * SAMPLE_SIZE), gWaveSamples[8]); + // Offset the address for the samples read by gWaveSamples[8] to the next set of samples + gWaveSamples[8] += numSamplesToLoad * SAMPLE_SIZE; + + return cmd; + } else { + // Move the synthetic wave from ram to dmem + aLoadBuffer(cmd++, sampleState->waveSampleAddr, DMEM_UNCOMPRESSED_NOTE, WAVE_SAMPLE_COUNT * SAMPLE_SIZE); + + // If the harmonic changes, map the offset in the wave from one harmonic to another for continuity + if (harmonicIndexCurAndPrev != 0) { + samplePosInt = (samplePosInt * sNumSamplesPerWavePeriod[harmonicIndexCurAndPrev >> 2]) / + sNumSamplesPerWavePeriod[harmonicIndexCurAndPrev & 3]; + } + + // Offset in the WAVE_SAMPLE_COUNT samples of gWaveSamples to start processing the wave for continuity + samplePosInt = (u32)samplePosInt % WAVE_SAMPLE_COUNT; + // Number of samples in the initial WAVE_SAMPLE_COUNT samples available to be used to process + numSamplesAvailable = WAVE_SAMPLE_COUNT - samplePosInt; + + // Require duplicates if there are more samples to load than available + if (numSamplesToLoad > numSamplesAvailable) { + // Duplicate (copy) the WAVE_SAMPLE_COUNT samples as many times as needed to reach numSamplesToLoad. + // (numSamplesToLoad - numSamplesAvailable) is the number of samples missing. + // Divide by WAVE_SAMPLE_COUNT, rounding up, to get the amount of duplicates + numDuplicates = ((numSamplesToLoad - numSamplesAvailable + WAVE_SAMPLE_COUNT - 1) / WAVE_SAMPLE_COUNT); + if (numDuplicates != 0) { + aDuplicate(cmd++, numDuplicates, DMEM_UNCOMPRESSED_NOTE, + DMEM_UNCOMPRESSED_NOTE + (WAVE_SAMPLE_COUNT * SAMPLE_SIZE)); + } + } + synthState->samplePosInt = samplePosInt; + } + + return cmd; +} + +/** + * The Haas Effect gives directionality to sound by applying a small (< 35ms) delay to either the left or right channel. + * The delay is small enough that the sound is still perceived as one sound, but the channel that is not delayed will + * reach our ear first and give a sense of directionality. The sound is directed towards the opposite side of the delay. + */ +Acmd* AudioSynth_ApplyHaasEffect(Acmd* cmd, NoteSampleState* sampleState, NoteSynthesisState* synthState, s32 size, + s32 flags, s32 haasEffectDelaySide) { + u16 dmemDest; + u16 pitch; + u8 prevHaasEffectDelaySize; + u8 haasEffectDelaySize; + + switch (haasEffectDelaySide) { + case HAAS_EFFECT_DELAY_LEFT: + // Delay the sample on the left channel + // This allows the right channel to be heard first + dmemDest = DMEM_LEFT_CH; + haasEffectDelaySize = sampleState->haasEffectLeftDelaySize; + prevHaasEffectDelaySize = synthState->prevHaasEffectLeftDelaySize; + synthState->prevHaasEffectRightDelaySize = 0; + synthState->prevHaasEffectLeftDelaySize = haasEffectDelaySize; + break; + + case HAAS_EFFECT_DELAY_RIGHT: + // Delay the sample on the right channel + // This allows the left channel to be heard first + dmemDest = DMEM_RIGHT_CH; + haasEffectDelaySize = sampleState->haasEffectRightDelaySize; + prevHaasEffectDelaySize = synthState->prevHaasEffectRightDelaySize; + synthState->prevHaasEffectRightDelaySize = haasEffectDelaySize; + synthState->prevHaasEffectLeftDelaySize = 0; + break; + + default: // HAAS_EFFECT_DELAY_NONE + return cmd; + } + + if (flags != A_INIT) { + // Slightly adjust the sample rate in order to fit a change in sample delay + if (haasEffectDelaySize != prevHaasEffectDelaySize) { + pitch = (((size << 0xF) / 2) - 1) / ((size + haasEffectDelaySize - prevHaasEffectDelaySize - 2) / 2); + aSetBuffer(cmd++, 0, DMEM_HAAS_TEMP, DMEM_TEMP, size + haasEffectDelaySize - prevHaasEffectDelaySize); + aResampleZoh(cmd++, pitch, 0); + } else { + aDMEMMove(cmd++, DMEM_HAAS_TEMP, DMEM_TEMP, size); + } + + if (prevHaasEffectDelaySize != 0) { + aLoadBuffer(cmd++, synthState->synthesisBuffers->haasEffectDelayState, DMEM_HAAS_TEMP, + ALIGN16(prevHaasEffectDelaySize)); + aDMEMMove(cmd++, DMEM_TEMP, DMEM_HAAS_TEMP + prevHaasEffectDelaySize, + size + haasEffectDelaySize - prevHaasEffectDelaySize); + } else { + aDMEMMove(cmd++, DMEM_TEMP, DMEM_HAAS_TEMP, size + haasEffectDelaySize); + } + } else { + // Just apply a delay directly + aDMEMMove(cmd++, DMEM_HAAS_TEMP, DMEM_TEMP, size); + if (haasEffectDelaySize) { // != 0 + aClearBuffer(cmd++, DMEM_HAAS_TEMP, haasEffectDelaySize); + } + aDMEMMove(cmd++, DMEM_TEMP, DMEM_HAAS_TEMP + haasEffectDelaySize, size); + } + + if (haasEffectDelaySize) { // != 0 + // Save excessive samples for next iteration + aSaveBuffer(cmd++, DMEM_HAAS_TEMP + size, synthState->synthesisBuffers->haasEffectDelayState, + ALIGN16(haasEffectDelaySize)); + } + + aAddMixer(cmd++, ALIGN64(size), DMEM_HAAS_TEMP, dmemDest, 0x7FFF); + + return cmd; +} diff --git a/src/code/audio/code_8019AF00.c b/src/code/audio/code_8019AF00.c index 007d7ca85..98be41397 100644 --- a/src/code/audio/code_8019AF00.c +++ b/src/code/audio/code_8019AF00.c @@ -4078,7 +4078,7 @@ void AudioSfx_SetProperties(u8 bankId, u8 entryIndex, u8 channelIndex) { } u32 AudioSfx_SetFreqAndStereoBits(u8 seqScriptValIn, SequenceChannel* channel) { - channel->stereo.asByte = sSfxChannelState[seqScriptValIn].stereoBits; + channel->stereoData.asByte = sSfxChannelState[seqScriptValIn].stereoBits; channel->freqScale = sSfxChannelState[seqScriptValIn].freqScale; channel->changes.s.freqScale = true; diff --git a/src/overlays/actors/ovl_En_Kusa2/z_en_kusa2.c b/src/overlays/actors/ovl_En_Kusa2/z_en_kusa2.c index 4ed5b82a0..fdf3cc9ac 100644 --- a/src/overlays/actors/ovl_En_Kusa2/z_en_kusa2.c +++ b/src/overlays/actors/ovl_En_Kusa2/z_en_kusa2.c @@ -4,7 +4,6 @@ * Description: Keaton grass */ -#include "prevent_bss_reordering.h" #include "z_en_kusa2.h" #include "objects/gameplay_field_keep/gameplay_field_keep.h" #include "objects/gameplay_keep/gameplay_keep.h" diff --git a/tools/disasm/files.txt b/tools/disasm/files.txt index ffa305cdd..c546c1f69 100644 --- a/tools/disasm/files.txt +++ b/tools/disasm/files.txt @@ -597,6 +597,7 @@ 0x801D9090 : "audio_sound_params", 0x801DB470 : "code_801A5BD0", 0x801DB4C0 : "code_801A7B10", + 0x801DB4E0 : "audio_init_params", # .rodata section 0x801DBDF0 : "z_en_item00", diff --git a/tools/disasm/functions.txt b/tools/disasm/functions.txt index 057170442..20fa0265c 100644 --- a/tools/disasm/functions.txt +++ b/tools/disasm/functions.txt @@ -3478,74 +3478,74 @@ 0x801872FC:("osFlashWriteBuffer",), 0x801873BC:("osFlashWriteArray",), 0x8018752C:("osFlashReadArray",), - 0x801877D0:("func_801877D0",), - 0x80187B64:("func_80187B64",), - 0x80187BEC:("func_80187BEC",), - 0x80187DE8:("func_80187DE8",), - 0x80187E58:("func_80187E58",), - 0x80187F00:("func_80187F00",), - 0x80187FA8:("func_80187FA8",), - 0x80187FB0:("func_80187FB0",), - 0x80187FD0:("func_80187FD0",), - 0x80187FD8:("func_80187FD8",), - 0x80187FE0:("func_80187FE0",), - 0x80187FE8:("func_80187FE8",), - 0x8018801C:("func_8018801C",), - 0x80188024:("func_80188024",), - 0x8018802C:("func_8018802C",), - 0x80188034:("func_80188034",), - 0x80188068:("func_80188068",), - 0x80188070:("func_80188070",), - 0x80188078:("func_80188078",), - 0x801880A4:("func_801880A4",), - 0x801880AC:("func_801880AC",), - 0x801880B4:("func_801880B4",), - 0x801880BC:("func_801880BC",), - 0x801880C4:("func_801880C4",), - 0x801880E8:("func_801880E8",), - 0x8018811C:("func_8018811C",), - 0x80188124:("func_80188124",), - 0x8018814C:("func_8018814C",), - 0x80188174:("func_80188174",), - 0x80188190:("func_80188190",), - 0x80188198:("func_80188198",), - 0x801881A0:("func_801881A0",), - 0x801881A8:("func_801881A8",), - 0x801881C4:("func_801881C4",), - 0x801881F8:("func_801881F8",), - 0x80188224:("func_80188224",), - 0x8018822C:("func_8018822C",), - 0x80188234:("func_80188234",), - 0x8018823C:("func_8018823C",), - 0x80188244:("func_80188244",), - 0x8018824C:("func_8018824C",), - 0x80188254:("func_80188254",), - 0x8018825C:("func_8018825C",), - 0x80188264:("func_80188264",), - 0x80188288:("func_80188288",), - 0x801882A0:("func_801882A0",), - 0x80188304:("func_80188304",), - 0x801884A0:("func_801884A0",), - 0x80188698:("func_80188698",), - 0x8018883C:("func_8018883C",), - 0x801888E4:("func_801888E4",), - 0x801889A4:("func_801889A4",), - 0x80188A50:("func_80188A50",), - 0x80188AFC:("func_80188AFC",), - 0x80188C48:("func_80188C48",), - 0x80188CB4:("func_80188CB4",), - 0x80188D20:("func_80188D20",), - 0x80188D28:("func_80188D28",), - 0x80188D68:("func_80188D68",), - 0x80188DDC:("func_80188DDC",), - 0x80188FBC:("func_80188FBC",), - 0x80189064:("func_80189064",), - 0x80189620:("func_80189620",), - 0x8018A4B4:("func_8018A4B4",), - 0x8018A768:("func_8018A768",), - 0x8018A808:("func_8018A808",), - 0x8018ACC4:("func_8018ACC4",), - 0x8018AE34:("func_8018AE34",), + 0x801877D0:("AudioSynth_AddReverbBufferEntry",), + 0x80187B64:("AudioSynth_SyncSampleStates",), + 0x80187BEC:("AudioSynth_Update",), + 0x80187DE8:("AudioSynth_DisableSampleStates",), + 0x80187E58:("AudioSynth_LoadMixedReverbSamples",), + 0x80187F00:("AudioSynth_SaveMixedReverbSamples",), + 0x80187FA8:("AudioSynth_Noop1",), + 0x80187FB0:("AudioSynth_ClearBuffer",), + 0x80187FD0:("AudioSynth_Noop2",), + 0x80187FD8:("AudioSynth_Noop3",), + 0x80187FE0:("AudioSynth_Noop4",), + 0x80187FE8:("AudioSynth_Mix",), + 0x8018801C:("AudioSynth_Noop5",), + 0x80188024:("AudioSynth_Noop6",), + 0x8018802C:("AudioSynth_Noop7",), + 0x80188034:("AudioSynth_SetBuffer",), + 0x80188068:("AudioSynth_Noop8",), + 0x80188070:("AudioSynth_Noop9",), + 0x80188078:("AudioSynth_DMemMove",), + 0x801880A4:("AudioSynth_Noop10",), + 0x801880AC:("AudioSynth_Noop11",), + 0x801880B4:("AudioSynth_Noop12",), + 0x801880BC:("AudioSynth_Noop13",), + 0x801880C4:("AudioSynth_InterL",), + 0x801880E8:("AudioSynth_EnvSetup1",), + 0x8018811C:("AudioSynth_Noop14",), + 0x80188124:("AudioSynth_LoadBuffer",), + 0x8018814C:("AudioSynth_SaveBuffer",), + 0x80188174:("AudioSynth_EnvSetup2",), + 0x80188190:("AudioSynth_Noop15",), + 0x80188198:("AudioSynth_Noop16",), + 0x801881A0:("AudioSynth_Noop17",), + 0x801881A8:("AudioSynth_S8Dec",), + 0x801881C4:("AudioSynth_HiLoGain",), + 0x801881F8:("AudioSynth_UnkCmd19",), + 0x80188224:("AudioSynth_Noop18",), + 0x8018822C:("AudioSynth_Noop19",), + 0x80188234:("AudioSynth_Noop20",), + 0x8018823C:("AudioSynth_Noop21",), + 0x80188244:("AudioSynth_Noop22",), + 0x8018824C:("AudioSynth_Noop23",), + 0x80188254:("AudioSynth_Noop24",), + 0x8018825C:("AudioSynth_Noop25",), + 0x80188264:("AudioSynth_LoadFilterBuffer",), + 0x80188288:("AudioSynth_LoadFilterSize",), + 0x801882A0:("AudioSynth_LeakReverb",), + 0x80188304:("AudioSynth_LoadDownsampledReverbSamples",), + 0x801884A0:("AudioSynth_SaveResampledReverbSamples",), + 0x80188698:("AudioSynth_LoadResampledReverbSamples",), + 0x8018883C:("AudioSynth_FilterReverb",), + 0x801888E4:("AudioSynth_MixOtherReverbIndex",), + 0x801889A4:("AudioSynth_LoadDefaultReverbSamples",), + 0x80188A50:("AudioSynth_LoadSubReverbSamples",), + 0x80188AFC:("AudioSynth_SaveResampledReverbSamplesImpl",), + 0x80188C48:("AudioSynth_LoadReverbSamplesImpl",), + 0x80188CB4:("AudioSynth_SaveReverbSamplesImpl",), + 0x80188D20:("AudioSynth_Noop26",), + 0x80188D28:("AudioSynth_LoadSubReverbSamplesWithoutDownsample",), + 0x80188D68:("AudioSynth_LoadReverbSamples",), + 0x80188DDC:("AudioSynth_SaveReverbSamples",), + 0x80188FBC:("AudioSynth_SaveSubReverbSamples",), + 0x80189064:("AudioSynth_ProcessSamples",), + 0x80189620:("AudioSynth_ProcessSample",), + 0x8018A4B4:("AudioSynth_ApplySurroundEffect",), + 0x8018A768:("AudioSynth_FinalResample",), + 0x8018A808:("AudioSynth_ProcessEnvelope",), + 0x8018ACC4:("AudioSynth_LoadWaveSamples",), + 0x8018AE34:("AudioSynth_ApplyHaasEffect",), 0x8018B0F0:("AudioHeap_CalculateAdsrDecay",), 0x8018B10C:("AudioHeap_InitAdsrDecayTable",), 0x8018B250:("AudioHeap_ResetLoadStatus",), @@ -3726,7 +3726,7 @@ 0x80194804:("func_80194804",), 0x80194840:("func_80194840",), 0x801948B0:("func_801948B0",), - 0x80194930:("AudioPlayback_InitNoteSub",), + 0x80194930:("AudioPlayback_InitSampleState",), 0x80194DB0:("AudioPlayback_NoteSetResamplingRate",), 0x80194E60:("AudioPlayback_NoteInit",), 0x80194F20:("AudioPlayback_NoteDisable",), diff --git a/tools/disasm/variables.txt b/tools/disasm/variables.txt index a0b369264..5c8147eef 100644 --- a/tools/disasm/variables.txt +++ b/tools/disasm/variables.txt @@ -2220,11 +2220,11 @@ 0x801D57B4:("gDefaultShortNoteVelocityTable","UNK_TYPE1","",0x1), 0x801D57C4:("gDefaultShortNoteGateTimeTable","UNK_TYPE1","",0x1), 0x801D57D4:("gDefaultEnvelope","UNK_TYPE1","",0x1), - 0x801D57E4:("gZeroNoteSub","UNK_TYPE4","",0x4), - 0x801D5804:("gDefaultNoteSub","UNK_TYPE4","",0x4), - 0x801D5824:("gHeadsetPanQuantization","u16","[64]",0x80), + 0x801D57E4:("gZeroedSampleState","UNK_TYPE4","",0x4), + 0x801D5804:("gDefaultSampleState","UNK_TYPE4","",0x4), + 0x801D5824:("gHaasEffectDelaySize","u16","[64]",0x80), 0x801D58A4:("D_801D58A4","s32","",0x4), - 0x801D58A8:("D_801D58A8","s16","[64]",0x80), + 0x801D58A8:("gInvalidAdpcmCodeBook","s16","[64]",0x80), 0x801D5928:("gHeadsetPanVolume","f32","[128]",0x200), 0x801D5B28:("gStereoPanVolume","f32","[128]",0x200), 0x801D5D28:("gDefaultPanVolume","f32","[128]",0x200), @@ -2411,7 +2411,7 @@ 0x801DB870:("D_801DB870","UNK_TYPE1","",0x1), 0x801DB8B8:("D_801DB8B8","UNK_TYPE1","",0x1), 0x801DB900:("D_801DB900","UNK_TYPE1","",0x1), - 0x801DB930:("D_801DB930","UNK_PTR","",0x4), + 0x801DB930:("gReverbSettingsTable","UNK_PTR","",0x4), 0x801DB958:("gAudioSpecs","AudioSpec","[21]",0x498), 0x801DBDF0:("D_801DBDF0","f32","",0x4), 0x801DBDF4:("jtbl_801DBDF4","UNK_PTR","",0x4), @@ -4354,10 +4354,10 @@ 0x80200BCE:("D_80200BCE","UNK_TYPE1","",0x1), 0x80200BD0:("D_80200BD0","UNK_TYPE1","",0x1), 0x80200C70:("gAudioContext","AudioContext","",0x81F8), - 0x80208E68:("D_80208E68","UNK_TYPE4","",0x4), - 0x80208E6C:("D_80208E6C","UNK_TYPE4","",0x4), - 0x80208E70:("D_80208E70","UNK_TYPE4","",0x4), - 0x80208E74:("D_80208E74","UNK_TYPE4","",0x4), + 0x80208E68:("gCustomAudioUpdateFunction","UNK_TYPE4","",0x4), + 0x80208E6C:("gCustomAudioSeqFunction","UNK_TYPE4","",0x4), + 0x80208E70:("gCustomAudioReverbFunction","UNK_TYPE4","",0x4), + 0x80208E74:("gCustomAudioSynthFunction","UNK_TYPE4","",0x4), 0x80208E90:("sJpegBitStreamPtr","UNK_TYPE1","",0x1), 0x80208E94:("sJpegBitStreamByteIdx","UNK_TYPE1","",0x1), 0x80208E98:("sJpegBitStreamBitIdx","UNK_TYPE1","",0x1), diff --git a/tools/sizes/code_functions.csv b/tools/sizes/code_functions.csv index f64c45241..9db0c0308 100644 --- a/tools/sizes/code_functions.csv +++ b/tools/sizes/code_functions.csv @@ -2996,74 +2996,74 @@ asm/non_matchings/code/osFlash/func_80187284.s,func_80187284,0x80187284,0x1E asm/non_matchings/code/osFlash/func_801872FC.s,func_801872FC,0x801872FC,0x30 asm/non_matchings/code/osFlash/func_801873BC.s,func_801873BC,0x801873BC,0x5C asm/non_matchings/code/osFlash/func_8018752C.s,func_8018752C,0x8018752C,0x9D -asm/non_matchings/code/audio_synthesis/func_801877D0.s,func_801877D0,0x801877D0,0xE5 -asm/non_matchings/code/audio_synthesis/func_80187B64.s,func_80187B64,0x80187B64,0x22 -asm/non_matchings/code/audio_synthesis/func_80187BEC.s,func_80187BEC,0x80187BEC,0x7F -asm/non_matchings/code/audio_synthesis/func_80187DE8.s,func_80187DE8,0x80187DE8,0x1C -asm/non_matchings/code/audio_synthesis/func_80187E58.s,func_80187E58,0x80187E58,0x2A -asm/non_matchings/code/audio_synthesis/func_80187F00.s,func_80187F00,0x80187F00,0x2A -asm/non_matchings/code/audio_synthesis/func_80187FA8.s,func_80187FA8,0x80187FA8,0x2 -asm/non_matchings/code/audio_synthesis/func_80187FB0.s,func_80187FB0,0x80187FB0,0x8 -asm/non_matchings/code/audio_synthesis/func_80187FD0.s,func_80187FD0,0x80187FD0,0x2 -asm/non_matchings/code/audio_synthesis/func_80187FD8.s,func_80187FD8,0x80187FD8,0x2 -asm/non_matchings/code/audio_synthesis/func_80187FE0.s,func_80187FE0,0x80187FE0,0x2 -asm/non_matchings/code/audio_synthesis/func_80187FE8.s,func_80187FE8,0x80187FE8,0xD -asm/non_matchings/code/audio_synthesis/func_8018801C.s,func_8018801C,0x8018801C,0x2 -asm/non_matchings/code/audio_synthesis/func_80188024.s,func_80188024,0x80188024,0x2 -asm/non_matchings/code/audio_synthesis/func_8018802C.s,func_8018802C,0x8018802C,0x2 -asm/non_matchings/code/audio_synthesis/func_80188034.s,func_80188034,0x80188034,0xD -asm/non_matchings/code/audio_synthesis/func_80188068.s,func_80188068,0x80188068,0x2 -asm/non_matchings/code/audio_synthesis/func_80188070.s,func_80188070,0x80188070,0x2 -asm/non_matchings/code/audio_synthesis/func_80188078.s,func_80188078,0x80188078,0xB -asm/non_matchings/code/audio_synthesis/func_801880A4.s,func_801880A4,0x801880A4,0x2 -asm/non_matchings/code/audio_synthesis/func_801880AC.s,func_801880AC,0x801880AC,0x2 -asm/non_matchings/code/audio_synthesis/func_801880B4.s,func_801880B4,0x801880B4,0x2 -asm/non_matchings/code/audio_synthesis/func_801880BC.s,func_801880BC,0x801880BC,0x2 -asm/non_matchings/code/audio_synthesis/func_801880C4.s,func_801880C4,0x801880C4,0x9 -asm/non_matchings/code/audio_synthesis/func_801880E8.s,func_801880E8,0x801880E8,0xD -asm/non_matchings/code/audio_synthesis/func_8018811C.s,func_8018811C,0x8018811C,0x2 -asm/non_matchings/code/audio_synthesis/func_80188124.s,func_80188124,0x80188124,0xA -asm/non_matchings/code/audio_synthesis/func_8018814C.s,func_8018814C,0x8018814C,0xA -asm/non_matchings/code/audio_synthesis/func_80188174.s,func_80188174,0x80188174,0x7 -asm/non_matchings/code/audio_synthesis/func_80188190.s,func_80188190,0x80188190,0x2 -asm/non_matchings/code/audio_synthesis/func_80188198.s,func_80188198,0x80188198,0x2 -asm/non_matchings/code/audio_synthesis/func_801881A0.s,func_801881A0,0x801881A0,0x2 -asm/non_matchings/code/audio_synthesis/func_801881A8.s,func_801881A8,0x801881A8,0x7 -asm/non_matchings/code/audio_synthesis/func_801881C4.s,func_801881C4,0x801881C4,0xD -asm/non_matchings/code/audio_synthesis/func_801881F8.s,func_801881F8,0x801881F8,0xB -asm/non_matchings/code/audio_synthesis/func_80188224.s,func_80188224,0x80188224,0x2 -asm/non_matchings/code/audio_synthesis/func_8018822C.s,func_8018822C,0x8018822C,0x2 -asm/non_matchings/code/audio_synthesis/func_80188234.s,func_80188234,0x80188234,0x2 -asm/non_matchings/code/audio_synthesis/func_8018823C.s,func_8018823C,0x8018823C,0x2 -asm/non_matchings/code/audio_synthesis/func_80188244.s,func_80188244,0x80188244,0x2 -asm/non_matchings/code/audio_synthesis/func_8018824C.s,func_8018824C,0x8018824C,0x2 -asm/non_matchings/code/audio_synthesis/func_80188254.s,func_80188254,0x80188254,0x2 -asm/non_matchings/code/audio_synthesis/func_8018825C.s,func_8018825C,0x8018825C,0x2 -asm/non_matchings/code/audio_synthesis/func_80188264.s,func_80188264,0x80188264,0x9 -asm/non_matchings/code/audio_synthesis/func_80188288.s,func_80188288,0x80188288,0x6 -asm/non_matchings/code/audio_synthesis/func_801882A0.s,func_801882A0,0x801882A0,0x19 -asm/non_matchings/code/audio_synthesis/func_80188304.s,func_80188304,0x80188304,0x67 -asm/non_matchings/code/audio_synthesis/func_801884A0.s,func_801884A0,0x801884A0,0x7E -asm/non_matchings/code/audio_synthesis/func_80188698.s,func_80188698,0x80188698,0x69 -asm/non_matchings/code/audio_synthesis/func_8018883C.s,func_8018883C,0x8018883C,0x2A -asm/non_matchings/code/audio_synthesis/func_801888E4.s,func_801888E4,0x801888E4,0x30 -asm/non_matchings/code/audio_synthesis/func_801889A4.s,func_801889A4,0x801889A4,0x2B -asm/non_matchings/code/audio_synthesis/func_80188A50.s,func_80188A50,0x80188A50,0x2B -asm/non_matchings/code/audio_synthesis/func_80188AFC.s,func_80188AFC,0x80188AFC,0x53 -asm/non_matchings/code/audio_synthesis/func_80188C48.s,func_80188C48,0x80188C48,0x1B -asm/non_matchings/code/audio_synthesis/func_80188CB4.s,func_80188CB4,0x80188CB4,0x1B -asm/non_matchings/code/audio_synthesis/func_80188D20.s,func_80188D20,0x80188D20,0x2 -asm/non_matchings/code/audio_synthesis/func_80188D28.s,func_80188D28,0x80188D28,0x10 -asm/non_matchings/code/audio_synthesis/func_80188D68.s,func_80188D68,0x80188D68,0x1D -asm/non_matchings/code/audio_synthesis/func_80188DDC.s,func_80188DDC,0x80188DDC,0x78 -asm/non_matchings/code/audio_synthesis/func_80188FBC.s,func_80188FBC,0x80188FBC,0x2A -asm/non_matchings/code/audio_synthesis/func_80189064.s,func_80189064,0x80189064,0x16F -asm/non_matchings/code/audio_synthesis/func_80189620.s,func_80189620,0x80189620,0x3A5 -asm/non_matchings/code/audio_synthesis/func_8018A4B4.s,func_8018A4B4,0x8018A4B4,0xAD -asm/non_matchings/code/audio_synthesis/func_8018A768.s,func_8018A768,0x8018A768,0x28 -asm/non_matchings/code/audio_synthesis/func_8018A808.s,func_8018A808,0x8018A808,0x12F -asm/non_matchings/code/audio_synthesis/func_8018ACC4.s,func_8018ACC4,0x8018ACC4,0x5C -asm/non_matchings/code/audio_synthesis/func_8018AE34.s,func_8018AE34,0x8018AE34,0xAF +asm/non_matchings/code/audio_synthesis/AudioSynth_AddReverbBufferEntry.s,AudioSynth_AddReverbBufferEntry,0x801877D0,0xE5 +asm/non_matchings/code/audio_synthesis/AudioSynth_SyncSampleStates.s,AudioSynth_SyncSampleStates,0x80187B64,0x22 +asm/non_matchings/code/audio_synthesis/AudioSynth_Update.s,AudioSynth_Update,0x80187BEC,0x7F +asm/non_matchings/code/audio_synthesis/AudioSynth_DisableSampleStates.s,AudioSynth_DisableSampleStates,0x80187DE8,0x1C +asm/non_matchings/code/audio_synthesis/AudioSynth_LoadMixedReverbSamples.s,AudioSynth_LoadMixedReverbSamples,0x80187E58,0x2A +asm/non_matchings/code/audio_synthesis/AudioSynth_SaveMixedReverbSamples.s,AudioSynth_SaveMixedReverbSamples,0x80187F00,0x2A +asm/non_matchings/code/audio_synthesis/AudioSynth_Noop1.s,AudioSynth_Noop1,0x80187FA8,0x2 +asm/non_matchings/code/audio_synthesis/AudioSynth_ClearBuffer.s,AudioSynth_ClearBuffer,0x80187FB0,0x8 +asm/non_matchings/code/audio_synthesis/AudioSynth_Noop2.s,AudioSynth_Noop2,0x80187FD0,0x2 +asm/non_matchings/code/audio_synthesis/AudioSynth_Noop3.s,AudioSynth_Noop3,0x80187FD8,0x2 +asm/non_matchings/code/audio_synthesis/AudioSynth_Noop4.s,AudioSynth_Noop4,0x80187FE0,0x2 +asm/non_matchings/code/audio_synthesis/AudioSynth_Mix.s,AudioSynth_Mix,0x80187FE8,0xD +asm/non_matchings/code/audio_synthesis/AudioSynth_Noop5.s,AudioSynth_Noop5,0x8018801C,0x2 +asm/non_matchings/code/audio_synthesis/AudioSynth_Noop6.s,AudioSynth_Noop6,0x80188024,0x2 +asm/non_matchings/code/audio_synthesis/AudioSynth_Noop7.s,AudioSynth_Noop7,0x8018802C,0x2 +asm/non_matchings/code/audio_synthesis/AudioSynth_SetBuffer.s,AudioSynth_SetBuffer,0x80188034,0xD +asm/non_matchings/code/audio_synthesis/AudioSynth_Noop8.s,AudioSynth_Noop8,0x80188068,0x2 +asm/non_matchings/code/audio_synthesis/AudioSynth_Noop9.s,AudioSynth_Noop9,0x80188070,0x2 +asm/non_matchings/code/audio_synthesis/AudioSynth_DMemMove.s,AudioSynth_DMemMove,0x80188078,0xB +asm/non_matchings/code/audio_synthesis/AudioSynth_Noop10.s,AudioSynth_Noop10,0x801880A4,0x2 +asm/non_matchings/code/audio_synthesis/AudioSynth_Noop11.s,AudioSynth_Noop11,0x801880AC,0x2 +asm/non_matchings/code/audio_synthesis/AudioSynth_Noop12.s,AudioSynth_Noop12,0x801880B4,0x2 +asm/non_matchings/code/audio_synthesis/AudioSynth_Noop13.s,AudioSynth_Noop13,0x801880BC,0x2 +asm/non_matchings/code/audio_synthesis/AudioSynth_InterL.s,AudioSynth_InterL,0x801880C4,0x9 +asm/non_matchings/code/audio_synthesis/AudioSynth_EnvSetup1.s,AudioSynth_EnvSetup1,0x801880E8,0xD +asm/non_matchings/code/audio_synthesis/AudioSynth_Noop14.s,AudioSynth_Noop14,0x8018811C,0x2 +asm/non_matchings/code/audio_synthesis/AudioSynth_LoadBuffer.s,AudioSynth_LoadBuffer,0x80188124,0xA +asm/non_matchings/code/audio_synthesis/AudioSynth_SaveBuffer.s,AudioSynth_SaveBuffer,0x8018814C,0xA +asm/non_matchings/code/audio_synthesis/AudioSynth_EnvSetup2.s,AudioSynth_EnvSetup2,0x80188174,0x7 +asm/non_matchings/code/audio_synthesis/AudioSynth_Noop15.s,AudioSynth_Noop15,0x80188190,0x2 +asm/non_matchings/code/audio_synthesis/AudioSynth_Noop16.s,AudioSynth_Noop16,0x80188198,0x2 +asm/non_matchings/code/audio_synthesis/AudioSynth_Noop17.s,AudioSynth_Noop17,0x801881A0,0x2 +asm/non_matchings/code/audio_synthesis/AudioSynth_S8Dec.s,AudioSynth_S8Dec,0x801881A8,0x7 +asm/non_matchings/code/audio_synthesis/AudioSynth_HiLoGain.s,AudioSynth_HiLoGain,0x801881C4,0xD +asm/non_matchings/code/audio_synthesis/AudioSynth_UnkCmd19.s,AudioSynth_UnkCmd19,0x801881F8,0xB +asm/non_matchings/code/audio_synthesis/AudioSynth_Noop18.s,AudioSynth_Noop18,0x80188224,0x2 +asm/non_matchings/code/audio_synthesis/AudioSynth_Noop19.s,AudioSynth_Noop19,0x8018822C,0x2 +asm/non_matchings/code/audio_synthesis/AudioSynth_Noop20.s,AudioSynth_Noop20,0x80188234,0x2 +asm/non_matchings/code/audio_synthesis/AudioSynth_Noop21.s,AudioSynth_Noop21,0x8018823C,0x2 +asm/non_matchings/code/audio_synthesis/AudioSynth_Noop22.s,AudioSynth_Noop22,0x80188244,0x2 +asm/non_matchings/code/audio_synthesis/AudioSynth_Noop23.s,AudioSynth_Noop23,0x8018824C,0x2 +asm/non_matchings/code/audio_synthesis/AudioSynth_Noop24.s,AudioSynth_Noop24,0x80188254,0x2 +asm/non_matchings/code/audio_synthesis/AudioSynth_Noop25.s,AudioSynth_Noop25,0x8018825C,0x2 +asm/non_matchings/code/audio_synthesis/AudioSynth_LoadFilterBuffer.s,AudioSynth_LoadFilterBuffer,0x80188264,0x9 +asm/non_matchings/code/audio_synthesis/AudioSynth_LoadFilterSize.s,AudioSynth_LoadFilterSize,0x80188288,0x6 +asm/non_matchings/code/audio_synthesis/AudioSynth_LeakReverb.s,AudioSynth_LeakReverb,0x801882A0,0x19 +asm/non_matchings/code/audio_synthesis/AudioSynth_LoadDownsampledReverbSamples.s,AudioSynth_LoadDownsampledReverbSamples,0x80188304,0x67 +asm/non_matchings/code/audio_synthesis/AudioSynth_SaveResampledReverbSamples.s,AudioSynth_SaveResampledReverbSamples,0x801884A0,0x7E +asm/non_matchings/code/audio_synthesis/AudioSynth_LoadResampledReverbSamples.s,AudioSynth_LoadResampledReverbSamples,0x80188698,0x69 +asm/non_matchings/code/audio_synthesis/AudioSynth_FilterReverb.s,AudioSynth_FilterReverb,0x8018883C,0x2A +asm/non_matchings/code/audio_synthesis/AudioSynth_MixOtherReverbIndex.s,AudioSynth_MixOtherReverbIndex,0x801888E4,0x30 +asm/non_matchings/code/audio_synthesis/AudioSynth_LoadDefaultReverbSamples.s,AudioSynth_LoadDefaultReverbSamples,0x801889A4,0x2B +asm/non_matchings/code/audio_synthesis/AudioSynth_LoadSubReverbSamples.s,AudioSynth_LoadSubReverbSamples,0x80188A50,0x2B +asm/non_matchings/code/audio_synthesis/AudioSynth_SaveResampledReverbSamplesImpl.s,AudioSynth_SaveResampledReverbSamplesImpl,0x80188AFC,0x53 +asm/non_matchings/code/audio_synthesis/AudioSynth_LoadReverbSamplesImpl.s,AudioSynth_LoadReverbSamplesImpl,0x80188C48,0x1B +asm/non_matchings/code/audio_synthesis/AudioSynth_SaveReverbSamplesImpl.s,AudioSynth_SaveReverbSamplesImpl,0x80188CB4,0x1B +asm/non_matchings/code/audio_synthesis/AudioSynth_Noop26.s,AudioSynth_Noop26,0x80188D20,0x2 +asm/non_matchings/code/audio_synthesis/AudioSynth_LoadSubReverbSamplesWithoutDownsample.s,AudioSynth_LoadSubReverbSamplesWithoutDownsample,0x80188D28,0x10 +asm/non_matchings/code/audio_synthesis/AudioSynth_LoadReverbSamples.s,AudioSynth_LoadReverbSamples,0x80188D68,0x1D +asm/non_matchings/code/audio_synthesis/AudioSynth_SaveReverbSamples.s,AudioSynth_SaveReverbSamples,0x80188DDC,0x78 +asm/non_matchings/code/audio_synthesis/AudioSynth_SaveSubReverbSamples.s,AudioSynth_SaveSubReverbSamples,0x80188FBC,0x2A +asm/non_matchings/code/audio_synthesis/AudioSynth_ProcessSamples.s,AudioSynth_ProcessSamples,0x80189064,0x16F +asm/non_matchings/code/audio_synthesis/AudioSynth_ProcessSample.s,AudioSynth_ProcessSample,0x80189620,0x3A5 +asm/non_matchings/code/audio_synthesis/AudioSynth_ApplySurroundEffect.s,AudioSynth_ApplySurroundEffect,0x8018A4B4,0xAD +asm/non_matchings/code/audio_synthesis/AudioSynth_FinalResample.s,AudioSynth_FinalResample,0x8018A768,0x28 +asm/non_matchings/code/audio_synthesis/AudioSynth_ProcessEnvelope.s,AudioSynth_ProcessEnvelope,0x8018A808,0x12F +asm/non_matchings/code/audio_synthesis/AudioSynth_LoadWaveSamples.s,AudioSynth_LoadWaveSamples,0x8018ACC4,0x5C +asm/non_matchings/code/audio_synthesis/AudioSynth_ApplyHaasEffect.s,AudioSynth_ApplyHaasEffect,0x8018AE34,0xAF asm/non_matchings/code/audio_heap/AudioHeap_ResetLoadStatus.s,AudioHeap_ResetLoadStatus,0x8018B250,0x32 asm/non_matchings/code/audio_heap/AudioHeap_DiscardFont.s,AudioHeap_DiscardFont,0x8018B318,0x39 asm/non_matchings/code/audio_heap/AudioHeap_ReleaseNotesForFont.s,AudioHeap_ReleaseNotesForFont,0x8018B3FC,0x1E @@ -3242,7 +3242,7 @@ asm/non_matchings/code/code_80194710/osAiSetNextBuffer.s,osAiSetNextBuffer,0x801 asm/non_matchings/code/code_80194710/func_80194804.s,func_80194804,0x80194804,0xF asm/non_matchings/code/code_80194710/func_80194840.s,func_80194840,0x80194840,0x1C asm/non_matchings/code/code_80194710/func_801948B0.s,func_801948B0,0x801948B0,0x20 -asm/non_matchings/code/audio_playback/AudioPlayback_InitNoteSub.s,AudioPlayback_InitNoteSub,0x80194930,0x120 +asm/non_matchings/code/audio_playback/AudioPlayback_InitSampleState.s,AudioPlayback_InitSampleState,0x80194930,0x120 asm/non_matchings/code/audio_playback/AudioPlayback_NoteSetResamplingRate.s,AudioPlayback_NoteSetResamplingRate,0x80194DB0,0x2C asm/non_matchings/code/audio_playback/AudioPlayback_NoteInit.s,AudioPlayback_NoteInit,0x80194E60,0x30 asm/non_matchings/code/audio_playback/AudioPlayback_NoteDisable.s,AudioPlayback_NoteDisable,0x80194F20,0x19