From 8535b62aae29cf8b114712389afab8ee75969c95 Mon Sep 17 00:00:00 2001 From: Tal Hayon Date: Mon, 7 Mar 2022 21:30:36 +0200 Subject: [PATCH] Decompile fan --- asm/object/fan.s | 378 ---------------------------------------- assets/assets.json | 10 -- data/const/object/fan.s | 17 -- include/functions.h | 2 +- include/player.h | 1 + linker.ld | 3 +- src/movement.c | 4 +- src/object/fan.c | 248 ++++++++++++++++++++++---- 8 files changed, 216 insertions(+), 447 deletions(-) delete mode 100644 asm/object/fan.s delete mode 100644 data/const/object/fan.s diff --git a/asm/object/fan.s b/asm/object/fan.s deleted file mode 100644 index 83e95e44..00000000 --- a/asm/object/fan.s +++ /dev/null @@ -1,378 +0,0 @@ - .include "asm/macros.inc" - - .include "constants/constants.inc" - - .syntax unified - - .text - - thumb_func_start sub_0809EE44 -sub_0809EE44: @ 0x0809EE44 - push {r4, r5, r6, r7, lr} - adds r5, r0, #0 - adds r0, #0x5a - ldrb r0, [r0] - movs r1, #7 - ands r1, r0 - adds r0, r5, #0 - adds r0, #0x7e - ldrb r0, [r0] - lsls r0, r1 - strh r0, [r5, #0x24] - cmp r1, #0 - bne _0809EE60 - b _0809EF74 -_0809EE60: - ldr r4, _0809EEA4 @ =gPlayerEntity - adds r0, r5, #0 - adds r1, r4, #0 - bl sub_0809EF78 - cmp r0, #0 - beq _0809EE80 - bl sub_08079F8C - cmp r0, #0 - beq _0809EE80 - movs r1, #0x24 - ldrsh r0, [r5, r1] - ldrb r1, [r5, #0x15] - bl sub_08079E58 -_0809EE80: - ldr r6, _0809EEA8 @ =gEntityLists + 16 - ldr r4, [r6, #4] - cmp r6, r4 - beq _0809EF74 -_0809EE88: - ldrb r0, [r4, #8] - cmp r0, #8 - bne _0809EF6E - movs r3, #0 - ldrb r0, [r4, #9] - subs r0, #2 - cmp r0, #0x17 - bhi _0809EF52 - lsls r0, r0, #2 - ldr r1, _0809EEAC @ =_0809EEB0 - adds r0, r0, r1 - ldr r0, [r0] - mov pc, r0 - .align 2, 0 -_0809EEA4: .4byte gPlayerEntity -_0809EEA8: .4byte gEntityLists + 16 -_0809EEAC: .4byte _0809EEB0 -_0809EEB0: @ jump table - .4byte _0809EF1E @ case 0 - .4byte _0809EF26 @ case 1 - .4byte _0809EF48 @ case 2 - .4byte _0809EF52 @ case 3 - .4byte _0809EF52 @ case 4 - .4byte _0809EF52 @ case 5 - .4byte _0809EF52 @ case 6 - .4byte _0809EF52 @ case 7 - .4byte _0809EF52 @ case 8 - .4byte _0809EF52 @ case 9 - .4byte _0809EF52 @ case 10 - .4byte _0809EF52 @ case 11 - .4byte _0809EF52 @ case 12 - .4byte _0809EF52 @ case 13 - .4byte _0809EF52 @ case 14 - .4byte _0809EF50 @ case 15 - .4byte _0809EF52 @ case 16 - .4byte _0809EF10 @ case 17 - .4byte _0809EF52 @ case 18 - .4byte _0809EF52 @ case 19 - .4byte _0809EF52 @ case 20 - .4byte _0809EF52 @ case 21 - .4byte _0809EF52 @ case 22 - .4byte _0809EF50 @ case 23 -_0809EF10: - ldrb r0, [r4, #0xc] - cmp r0, #2 - bne _0809EF56 - ldrb r0, [r4, #0xd] - cmp r0, #1 - bls _0809EF52 - b _0809EF56 -_0809EF1E: - ldrb r0, [r4, #0xc] - cmp r0, #2 - beq _0809EF52 - b _0809EF56 -_0809EF26: - ldr r2, _0809EF44 @ =gPlayerEntity - movs r7, #0x2e - ldrsh r1, [r4, r7] - movs r7, #0x2e - ldrsh r0, [r2, r7] - cmp r1, r0 - bne _0809EF56 - movs r0, #0x32 - ldrsh r1, [r4, r0] - movs r7, #0x32 - ldrsh r0, [r2, r7] - cmp r1, r0 - beq _0809EF52 - b _0809EF56 - .align 2, 0 -_0809EF44: .4byte gPlayerEntity -_0809EF48: - ldrb r0, [r5, #0xf] - cmp r0, #0 - beq _0809EF52 - b _0809EF56 -_0809EF50: - movs r3, #1 -_0809EF52: - cmp r3, #0 - beq _0809EF6E -_0809EF56: - adds r0, r5, #0 - adds r1, r4, #0 - bl sub_0809EF78 - cmp r0, #0 - beq _0809EF6E - movs r0, #0x24 - ldrsh r1, [r5, r0] - ldrb r2, [r5, #0x15] - adds r0, r4, #0 - bl sub_080044AE -_0809EF6E: - ldr r4, [r4, #4] - cmp r6, r4 - bne _0809EE88 -_0809EF74: - pop {r4, r5, r6, r7, pc} - .align 2, 0 - - thumb_func_start sub_0809EF78 -sub_0809EF78: @ 0x0809EF78 - push {r4, r5, lr} - adds r3, r0, #0 - adds r4, r1, #0 - movs r5, #0 - adds r0, #0x70 - ldrh r2, [r0] - movs r1, #0x2e - ldrsh r0, [r4, r1] - adds r1, r3, #0 - adds r1, #0x6c - ldrh r1, [r1] - subs r0, r0, r1 - cmp r2, r0 - blo _0809EFAC - adds r0, r3, #0 - adds r0, #0x72 - ldrh r2, [r0] - movs r1, #0x32 - ldrsh r0, [r4, r1] - adds r1, r3, #0 - adds r1, #0x6e - ldrh r1, [r1] - subs r0, r0, r1 - cmp r2, r0 - blo _0809EFAC - movs r5, #1 -_0809EFAC: - adds r0, r5, #0 - pop {r4, r5, pc} - - thumb_func_start sub_0809EFB0 -sub_0809EFB0: @ 0x0809EFB0 - push {r4, r5, r6, r7, lr} - mov r7, sl - mov r6, sb - mov r5, r8 - push {r5, r6, r7} - adds r4, r0, #0 - ldr r0, _0809F010 @ =gUnk_081243E4 - ldrb r1, [r4, #0xa] - lsls r1, r1, #1 - adds r2, r1, r0 - ldrb r2, [r2] - lsls r2, r2, #0x18 - asrs r2, r2, #0x18 - mov sb, r2 - adds r1, #1 - adds r1, r1, r0 - ldrb r1, [r1] - lsls r1, r1, #0x18 - asrs r1, r1, #0x18 - mov r8, r1 - movs r0, #0x2e - ldrsh r6, [r4, r0] - movs r0, #0x32 - ldrsh r5, [r4, r0] - ldr r0, _0809F014 @ =gUnk_02027EB4 - mov sl, r0 - movs r7, #0 -_0809EFE6: - adds r7, #1 - add r6, sb - add r5, r8 - mov r0, sl - adds r1, r6, #0 - adds r2, r5, #0 - movs r3, #9 - bl IsTileCollision - cmp r0, #0 - beq _0809EFE6 - subs r0, r7, #1 - lsls r7, r0, #4 - ldrb r0, [r4, #0xa] - cmp r0, #1 - beq _0809F034 - cmp r0, #1 - bgt _0809F018 - cmp r0, #0 - beq _0809F022 - b _0809F082 - .align 2, 0 -_0809F010: .4byte gUnk_081243E4 -_0809F014: .4byte gUnk_02027EB4 -_0809F018: - cmp r0, #2 - beq _0809F03E - cmp r0, #3 - beq _0809F064 - b _0809F082 -_0809F022: - ldrh r0, [r4, #0x2e] - subs r0, #0x10 - adds r1, r4, #0 - adds r1, #0x6c - strh r0, [r1] - ldrh r0, [r4, #0x32] - adds r0, #8 - adds r1, #2 - b _0809F054 -_0809F034: - adds r1, r7, #0 - adds r1, #8 - ldrh r0, [r4, #0x2e] - subs r0, r0, r1 - b _0809F068 -_0809F03E: - ldrh r0, [r4, #0x2e] - subs r0, #0x10 - adds r1, r4, #0 - adds r1, #0x6c - strh r0, [r1] - adds r1, r7, #0 - adds r1, #8 - ldrh r0, [r4, #0x32] - subs r0, r0, r1 - adds r1, r4, #0 - adds r1, #0x6e -_0809F054: - strh r0, [r1] - adds r1, #2 - movs r0, #0x20 - strh r0, [r1] - adds r0, r4, #0 - adds r0, #0x72 - strh r7, [r0] - b _0809F082 -_0809F064: - ldrh r0, [r4, #0x2e] - adds r0, #8 -_0809F068: - adds r1, r4, #0 - adds r1, #0x6c - strh r0, [r1] - ldrh r0, [r4, #0x32] - subs r0, #0x10 - adds r1, #2 - strh r0, [r1] - adds r0, r4, #0 - adds r0, #0x70 - strh r7, [r0] - adds r1, #4 - movs r0, #0x20 - strh r0, [r1] -_0809F082: - pop {r3, r4, r5} - mov r8, r3 - mov sb, r4 - mov sl, r5 - pop {r4, r5, r6, r7, pc} - - thumb_func_start sub_0809F08C -sub_0809F08C: @ 0x0809F08C - push {r4, lr} - adds r4, r0, #0 - ldrb r0, [r4, #0xf] - cmp r0, #0 - beq _0809F09A - subs r0, #1 - strb r0, [r4, #0xf] -_0809F09A: - adds r0, r4, #0 - bl GetNextFrame - adds r2, r4, #0 - adds r2, #0x5a - ldrb r1, [r2] - movs r0, #0x20 - ands r0, r1 - cmp r0, #0 - beq _0809F0C0 - movs r0, #0xdf - ands r0, r1 - strb r0, [r2] - movs r0, #0x14 - strb r0, [r4, #0xf] - adds r0, r4, #0 - bl sub_0809F0E4 - b _0809F0E0 -_0809F0C0: - movs r0, #0x10 - ands r0, r1 - cmp r0, #0 - beq _0809F0E0 - ldrb r0, [r4, #0xf] - cmp r0, #0 - bne _0809F0E0 - movs r0, #0x14 - strb r0, [r4, #0xf] - ldrb r0, [r2] - movs r1, #0x10 - eors r0, r1 - strb r0, [r2] - adds r0, r4, #0 - bl sub_0809F0E4 -_0809F0E0: - pop {r4, pc} - .align 2, 0 - - thumb_func_start sub_0809F0E4 -sub_0809F0E4: @ 0x0809F0E4 - push {r4, r5, lr} - adds r5, r0, #0 - ldr r0, _0809F124 @ =0x00000183 - bl EnqueueSFX - ldrb r0, [r5, #0xa] - movs r1, #2 - eors r1, r0 - movs r0, #0xb2 - movs r2, #0 - bl CreateObject - adds r4, r0, #0 - cmp r4, #0 - beq _0809F120 - str r5, [r4, #0x50] - ldrb r0, [r5, #0xa] - lsls r0, r0, #1 - ldr r1, _0809F128 @ =gUnk_081243EC - adds r0, r0, r1 - movs r2, #0 - ldrsb r2, [r0, r2] - lsls r2, r2, #0x10 - movs r3, #1 - ldrsb r3, [r0, r3] - lsls r3, r3, #0x10 - adds r0, r5, #0 - adds r1, r4, #0 - bl PositionRelative -_0809F120: - pop {r4, r5, pc} - .align 2, 0 -_0809F124: .4byte 0x00000183 -_0809F128: .4byte gUnk_081243EC diff --git a/assets/assets.json b/assets/assets.json index ead7a083..bd03a55c 100644 --- a/assets/assets.json +++ b/assets/assets.json @@ -45064,16 +45064,6 @@ "size": 37, "type": "animation" }, - { - "path": "fan/gUnk_081243E4.bin", - "start": 1197028, - "size": 8 - }, - { - "path": "fan/gUnk_081243EC.bin", - "start": 1197036, - "size": 8 - }, { "path": "animations/gSpriteAnimations_AngryStatue_1.bin", "start": 1197708, diff --git a/data/const/object/fan.s b/data/const/object/fan.s deleted file mode 100644 index db9550e6..00000000 --- a/data/const/object/fan.s +++ /dev/null @@ -1,17 +0,0 @@ - .include "asm/macros.inc" - .include "constants/constants.inc" - - .section .rodata - .align 2 - -gUnk_081243D4:: @ 081243D4 - .4byte sub_0809ED30 - .4byte sub_0809ED54 - .4byte sub_0809ED88 - .4byte sub_0809EDE4 - -gUnk_081243E4:: @ 081243E4 - .incbin "fan/gUnk_081243E4.bin" - -gUnk_081243EC:: @ 081243EC - .incbin "fan/gUnk_081243EC.bin" diff --git a/include/functions.h b/include/functions.h index 4fdc5222..3e57b8ec 100644 --- a/include/functions.h +++ b/include/functions.h @@ -41,7 +41,7 @@ extern bool32 HasSwordEquipped(); extern bool32 IsColliding(Entity*, Entity*); extern bool32 IsCollidingPlayer(Entity*); extern bool32 IsProjectileOffScreen(Entity*); -extern bool32 IsTileCollision(u8*, s32, s32, u32); +extern bool32 IsTileCollision(const u8*, s32, s32, u32); extern void LinearMoveAngle(Entity*, u32, u32); extern void LinearMoveDirection(Entity*, u32, u32); extern bool32 LoadFixedGFX(Entity*, u32); diff --git a/include/player.h b/include/player.h index 4ff7bc59..ba4d4de6 100644 --- a/include/player.h +++ b/include/player.h @@ -343,6 +343,7 @@ void sub_08077728(); extern void sub_08077B20(); extern u32 sub_08008B22(); extern u32* sub_08008790(Entity*, u32); +extern void sub_08079E58(s32 speed, u32 direction); #define COPY_FLAG_FROM_TO(base, src, dest) (base) = ((base) & ~(dest)) | (((dest) * ((base) & (src))) / src) diff --git a/linker.ld b/linker.ld index 826528e2..8afc2cc7 100644 --- a/linker.ld +++ b/linker.ld @@ -785,7 +785,6 @@ SECTIONS { src/object/lightableSwitch.o(.text); src/object/treeThorns.o(.text); src/object/fan.o(.text); - asm/object/fan.o(.text); src/object/angryStatue.o(.text); src/object/palaceArchway.o(.text); src/object/objectA2.o(.text); @@ -1538,7 +1537,7 @@ SECTIONS { data/animations/object/object9B.o(.rodata); data/const/object/treeHidingPortal.o(.rodata); data/const/object/lightableSwitch.o(.rodata); - data/const/object/fan.o(.rodata); + src/object/fan.o(.rodata); data/animations/object/fan.o(.rodata); src/object/angryStatue.o(.rodata); data/animations/object/angryStatue.o(.rodata); diff --git a/src/movement.c b/src/movement.c index afe81525..58c97260 100644 --- a/src/movement.c +++ b/src/movement.c @@ -35,7 +35,7 @@ extern u8 gUnk_08134FBC[]; extern u8 gUnk_08135048[]; extern u8 gUnk_0813A76C[]; -bool32 IsTileCollision(u8*, s32, s32, u32); +bool32 IsTileCollision(const u8*, s32, s32, u32); void CalculateEntityTileCollisions(Entity*, u32, u32); bool32 ProcessMovementInternal(Entity*, s32, s32, u32); bool32 sub_080AF0C8(Entity*); @@ -306,7 +306,7 @@ bool32 TileCollisionFunction9(s32 x, s32 y) { return gUnk_081339F8[y & 0xf] >> (x & 0xf) & 1; } -bool32 IsTileCollision(u8* layer, s32 x, s32 y, u32 collisionType) { +bool32 IsTileCollision(const u8* layer, s32 x, s32 y, u32 collisionType) { static bool32 (*const tileCollisionFunctions[])(s32, s32) = { TileCollisionFunction0, TileCollisionFunction1, TileCollisionFunction2, TileCollisionFunction3, TileCollisionFunction4, TileCollisionFunction5, TileCollisionFunction6, TileCollisionFunction7, diff --git a/src/object/fan.c b/src/object/fan.c index 0642a17e..890689e9 100644 --- a/src/object/fan.c +++ b/src/object/fan.c @@ -1,74 +1,248 @@ +#define NENT_DEPRECATED #include "global.h" #include "entity.h" #include "flags.h" +#include "player.h" +#include "functions.h" +#include "sound.h" +#include "object.h" -extern void sub_0809EE34(Entity*); -extern void sub_0809EFB0(Entity*); -extern void sub_0809EE08(Entity*); -extern void sub_0809F08C(void); -extern void sub_0809EE44(Entity*); -extern void sub_0809EE24(Entity*); +typedef struct { + Entity base; + u8 filler[0x4]; + u16 unk6c; + u16 unk6e; + u16 unk70; + u16 unk72; + u16 unk74; + u8 filler2[0x8]; + u8 unk7e; + u8 unk7f; + u8 filler3[0x4]; + u16 fanFlags; + u16 unk86; +} FanEntity; -extern void (*const gUnk_081243D4[])(Entity*); +void sub_0809EFB0(FanEntity*); +void sub_0809EE44(FanEntity*); +void sub_0809F08C(FanEntity*); +void sub_0809EE24(FanEntity*); +void sub_0809EE08(FanEntity*); +void sub_0809EE34(FanEntity*); +void sub_0809F0E4(FanEntity*); +void Fan_Init(FanEntity* this); +void Fan_Action1(FanEntity* this); +void Fan_Action2(FanEntity* this); +void Fan_Action3(FanEntity* this); +bool32 sub_0809EF78(FanEntity*, Entity*); + +extern const u8 gUnk_02027EB4[]; void Fan(Entity* this) { - gUnk_081243D4[this->action](this); + static void (*const actionFuncs[])(FanEntity*) = { + Fan_Init, + Fan_Action1, + Fan_Action2, + Fan_Action3, + }; + actionFuncs[this->action]((FanEntity*)this); } -void sub_0809ED30(Entity* this) { - this->direction = (this->type ^ 2) << 3; +void Fan_Init(FanEntity* this) { + super->direction = (super->type ^ 2) << 3; sub_0809EE34(this); sub_0809EFB0(this); - InitializeAnimation(this, this->type); + InitializeAnimation(super, super->type); } -void sub_0809ED54(Entity* this) { - u16 uVar1; - u32 iVar2; - - if (((this->cutsceneBeh.HWORD == 0) || CheckFlags(this->cutsceneBeh.HWORD)) && - ((this->type2 != 1 || (--this->field_0x74.HWORD == 0)))) { +void Fan_Action1(FanEntity* this) { + if (((this->fanFlags == 0) || CheckFlags(this->fanFlags)) && ((super->type2 != 1 || (--this->unk74 == 0)))) { sub_0809EE08(this); } } -void sub_0809ED88(Entity* this) { - sub_0809F08C(); +void Fan_Action2(FanEntity* this) { + sub_0809F08C(this); sub_0809EE44(this); - if (this->field_0x86.HWORD != 0) { - if (this->cutsceneBeh.HWORD == this->field_0x86.HWORD) { - if (CheckFlags(this->cutsceneBeh.HWORD)) { + if (this->unk86 != 0) { + if (this->fanFlags == this->unk86) { + if (CheckFlags(this->fanFlags)) { return; } - } else if (!CheckFlags(this->cutsceneBeh.HWORD)) { + } else if (!CheckFlags(this->fanFlags)) { return; } sub_0809EE24(this); - } else if ((this->type2 == 1) && (--this->field_0x74.HWORD == 0)) { + } else if ((super->type2 == 1) && (--this->unk74 == 0)) { sub_0809EE24(this); } } -void sub_0809EDE4(Entity* this) { - sub_0809F08C(); +void Fan_Action3(FanEntity* this) { + sub_0809F08C(this); sub_0809EE44(this); - if (this->frame & 0x80) { + if (super->frame & 0x80) { sub_0809EE34(this); } } -void sub_0809EE08(Entity* this) { - this->action = 2; - this->field_0x74.HWORD = *((u8*)&this->field_0x7c + 3) << 2; - InitializeAnimation(this, this->type); +void sub_0809EE08(FanEntity* this) { + super->action = 2; + this->unk74 = this->unk7f << 2; + InitializeAnimation(super, super->type); } -void sub_0809EE24(Entity* this) { - this->action = 3; - InitializeAnimation(this, this->type + 4); +void sub_0809EE24(FanEntity* this) { + super->action = 3; + InitializeAnimation(super, super->type + 4); } -void sub_0809EE34(Entity* this) { - this->action = 1; - this->field_0x74.HWORD = this->actionDelay << 2; +void sub_0809EE34(FanEntity* this) { + super->action = 1; + this->unk74 = super->actionDelay << 2; +} + +void sub_0809EE44(FanEntity* this) { + Entity* pEVar1; + u32 bVar3; + u32 uVar4; + LinkedList* pList; + + uVar4 = (super->frame & 7); + super->speed = this->unk7e << uVar4; + if (uVar4 != 0) { + pEVar1 = &gPlayerEntity; + if (sub_0809EF78(this, pEVar1)) { + if (sub_08079F8C()) { + sub_08079E58(super->speed, super->direction); + } + } + pList = &gEntityLists[2]; + for (pEVar1 = pList->first; (Entity*)pList != pEVar1; pEVar1 = pEVar1->next) { + if (pEVar1->kind == PLAYER_ITEM) { + bVar3 = 0; + switch (pEVar1->id) { + case 0x13: + if ((pEVar1->action != 2) || (1 < pEVar1->subAction)) + bVar3 = 1; + break; + case 0x2: + if (pEVar1->action == 2) + break; + bVar3 = 1; + break; + case 0x3: + if (pEVar1->x.HALF.HI != gPlayerEntity.x.HALF.HI || + pEVar1->y.HALF.HI != gPlayerEntity.y.HALF.HI) + bVar3 = 1; + break; + break; + case 0x4: + if (super->field_0xf != 0) + bVar3 = 1; + break; + case 0x11: + case 0x19: + bVar3 = 1; + break; + } + if (bVar3) { + if (sub_0809EF78(this, pEVar1) != 0) { + sub_080044AE(pEVar1, super->speed, super->direction); + } + } + } + } + } +} + +bool32 sub_0809EF78(FanEntity* this, Entity* ent) { + bool32 rv = 0; + + if (((u32)this->unk70 >= ent->x.HALF.HI - this->unk6c) && ((u32)this->unk72 >= ent->y.HALF.HI - this->unk6e)) { + rv = 1; + } + return rv; +} + +void sub_0809EFB0(FanEntity* this) { + static const s8 tileTypeOffsets[] = { 0, 16, -16, 0, 0, -16, 16, 0 }; + u32 cVar1, cVar2; + s32 sVar4; + int iVar6; + int iVar7; + const u8* ptr; + + cVar1 = tileTypeOffsets[super->type * 2]; + cVar2 = tileTypeOffsets[super->type * 2 + 1]; + iVar7 = super->x.HALF.HI; + iVar6 = super->y.HALF.HI; + ptr = gUnk_02027EB4; + sVar4 = 0; + do { + sVar4++; + iVar7 = iVar7 + cVar1; + iVar6 = iVar6 + cVar2; + } while (!IsTileCollision(ptr, iVar7, iVar6, 9)); + sVar4 = (sVar4 - 1) << 4; + + switch (super->type) { + case 0: + this->unk6c = super->x.HALF.HI - 0x10; + this->unk6e = super->y.HALF.HI + 8; + this->unk70 = 0x20; + this->unk72 = sVar4; + break; + case 1: + this->unk6c = super->x.HALF.HI - (sVar4 + 8); + this->unk6e = super->y.HALF.HI - 0x10; + this->unk70 = sVar4; + this->unk72 = 0x20; + break; + case 2: + this->unk6c = super->x.HALF.HI - 0x10; + this->unk6e = super->y.HALF.HI - (sVar4 + 8); + this->unk70 = 0x20; + this->unk72 = sVar4; + break; + case 3: + this->unk6c = super->x.HALF.HI + 8; + this->unk6e = super->y.HALF.HI - 0x10; + this->unk70 = sVar4; + this->unk72 = 0x20; + break; + } +} + +void sub_0809F08C(FanEntity* this) { + if (super->field_0xf != 0) { + super->field_0xf--; + } + + GetNextFrame(super); + if (super->frame & 0x20) { + super->frame &= ~0x20; + super->field_0xf = 20; + sub_0809F0E4(this); + } else { + if ((super->frame & 0x10) && super->field_0xf == 0) { + super->field_0xf = 20; + super->frame ^= 0x10; + sub_0809F0E4(this); + } + } +} + +void sub_0809F0E4(FanEntity* this) { + static const s8 typeOffsets[] = { 0, 12, -12, 0, 0, -12, 12, 0 }; + Entity* pEVar1; + const s8* ptr; + + EnqueueSFX(SFX_183); + pEVar1 = CreateObject(OBJECT_B2, super->type ^ 2, 0); + if (pEVar1 != NULL) { + pEVar1->parent = super; + ptr = typeOffsets + super->type * 2; + PositionRelative(super, pEVar1, ptr[0] << 0x10, ptr[1] << 0x10); + } }