summaryrefslogtreecommitdiff
path: root/src/object
diff options
context:
space:
mode:
authortheo3 <arisstephenson2@gmail.com>2020-07-13 15:27:20 -0700
committertheo3 <arisstephenson2@gmail.com>2020-07-13 15:27:20 -0700
commit62ddaaa5f6fe2dc2aaa2dd002d4ce0b1d61a3cc9 (patch)
treed625ad1b183fc6aa5b56c00ce6573ef850679731 /src/object
parentc47f16e5e7b0abb010133b3ee1a58099d8b8915d (diff)
add subdirs
Diffstat (limited to 'src/object')
-rw-r--r--src/object/archway.c27
-rw-r--r--src/object/bell.c21
-rw-r--r--src/object/chestSpawner.c35
-rw-r--r--src/object/cloud.c212
-rw-r--r--src/object/fan.c86
-rw-r--r--src/object/giantLeaf.c35
-rw-r--r--src/object/greatFairy.c582
-rw-r--r--src/object/heartContainer.c36
-rw-r--r--src/object/lightableSwitch.c145
-rw-r--r--src/object/mask.c140
-rw-r--r--src/object/metalDoor.c115
-rw-r--r--src/object/mineralWaterSource.c47
-rw-r--r--src/object/minishSizedEntrance.c27
-rw-r--r--src/object/object1A.c64
-rw-r--r--src/object/object1C.c19
-rw-r--r--src/object/object1D.c18
-rw-r--r--src/object/object49.c155
-rw-r--r--src/object/object86.c81
-rw-r--r--src/object/object9E.c45
-rw-r--r--src/object/objectA8.c36
-rw-r--r--src/object/railtrack.c148
-rw-r--r--src/object/smoke.c60
-rw-r--r--src/object/swordsmanNewsletter.c31
-rw-r--r--src/object/thoughtBubble.c43
-rw-r--r--src/object/treeHidingPortal.c88
-rw-r--r--src/object/well.c36
-rw-r--r--src/object/windTribeFlag.c25
-rw-r--r--src/object/windcrest.c41
28 files changed, 2398 insertions, 0 deletions
diff --git a/src/object/archway.c b/src/object/archway.c
new file mode 100644
index 00000000..ff6c7b14
--- /dev/null
+++ b/src/object/archway.c
@@ -0,0 +1,27 @@
+#include "global.h"
+#include "entity.h"
+#include "sprite.h"
+
+extern u32 CheckIsDungeon();
+
+void Archway(Entity *this)
+{
+ u32 v1;
+ u32 v2;
+ u32 v3;
+
+ if (this->action == 0) {
+ v1 = this->action = 1;
+ v2 = this->spriteSettings.raw;
+ v1 = v1 - 0x5;
+ v1 = v1 & v2;
+ this->spriteSettings.raw = v1 | 1;
+ this->frameIndex = this->entityType.parameter;
+ this->collisionLayer = 2;
+ UpdateSpriteForCollisionLayer(this);
+ v3 = CheckIsDungeon();
+ if (v3 != 0) {
+ this->spritePriority.b0 = (this->spritePriority.b0 & 0xf8) | 1;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/object/bell.c b/src/object/bell.c
new file mode 100644
index 00000000..072b0798
--- /dev/null
+++ b/src/object/bell.c
@@ -0,0 +1,21 @@
+#include "entity.h"
+#include "global.h"
+
+extern void (*gUnk_08123384[])(Entity*);
+
+void Bell(Entity* ent) {
+ gUnk_08123384[ent->action](ent);
+}
+
+void sub_08097D90(Entity* ent) {
+ ent->action = 1;
+ ent->spriteSettings.b.draw = 1;
+ ent->collisionLayer = 1;
+ ent->spritePriority.b0 = 0;
+ UpdateSpriteForCollisionLayer(ent);
+ InitAnimationForceUpdate(ent, 0);
+}
+
+void sub_08097DCC(Entity* ent) {
+ UpdateAnimationSingleFrame(ent);
+}
diff --git a/src/object/chestSpawner.c b/src/object/chestSpawner.c
new file mode 100644
index 00000000..8af7769d
--- /dev/null
+++ b/src/object/chestSpawner.c
@@ -0,0 +1,35 @@
+#include "global.h"
+#include "entity.h"
+#include "flags.h"
+
+extern void sub_080842D8(Entity*);
+extern void sub_08078828(Entity*);
+extern void sub_08083E20(Entity*);
+
+extern void (*const gUnk_0811F7E8[])(Entity*);
+extern void (*const gUnk_0811F808[])(Entity*);
+extern void (*const gUnk_0811F818[])(Entity*);
+
+extern u32 gUnk_0811F8B0;
+void ChestSpawner(Entity* this)
+{
+ gUnk_0811F7E8[this->entityType.form](this);
+}
+
+void sub_08083DF0(Entity* this) {
+ gUnk_0811F808[this->action](this);
+}
+
+void sub_08083E08(Entity *this)
+{
+ gUnk_0811F818[this->action](this);
+}
+
+void sub_08083E20(Entity *this)
+{
+ this->action = 3;
+ this->spriteSettings.b.draw = 1;
+ this->spriteRendering.alphaBlend = 0;
+ sub_080842D8(this);
+ sub_08078828(this);
+}
diff --git a/src/object/cloud.c b/src/object/cloud.c
new file mode 100644
index 00000000..734559c4
--- /dev/null
+++ b/src/object/cloud.c
@@ -0,0 +1,212 @@
+#include "global.h"
+#include "entity.h"
+#include "room.h"
+#include "link.h"
+#include "flags.h"
+
+extern void sub_0809F7BC(Entity*);
+extern void PlaySFX(u32);
+extern void sub_0809F814(u32);
+extern void sub_0809F7F4(Entity*);
+extern void LoadRoomEntityList();
+extern void DeleteThisEntity();
+extern u32 CheckRoomFlag(u32);
+extern void sub_08078A90(u32);
+extern void sub_08078B48(void);
+extern u32 Random(void);
+extern void sub_0806F69C(Entity*);
+extern void (*gUnk_08124798[])(Entity*);
+extern void (*gUnk_081247A0[])(Entity*);
+extern void (*gUnk_081247AC[])(Entity*);
+extern Entity* CreateObject(u32, u32, u32);
+extern void PositionEntityOnTop(Entity*, Entity*);
+extern void sub_0807BB68(u32*, u32, u32);
+
+extern u8 gUnk_02034490;
+extern u32 gUnk_030010A0;
+extern void* gUnk_080DD750;
+extern Entity gLinkEntity;
+extern LinkState gLinkState;
+extern u8 gUnk_081247C0[];
+extern u16 gUnk_081247C8[];
+extern u32 gUnk_081247D0;
+
+void Cloud(Entity* this) {
+ gUnk_08124798[(this->entityType).form](this);
+}
+
+void sub_0809F4DC(Entity* this) {
+ if ((this->entityType).parameter == 0) {
+ gUnk_081247A0[this->action](this);
+ } else {
+ gUnk_081247AC[this->action](this);
+ }
+}
+
+void sub_0809F514(Entity* this) {
+ this->action = 1;
+ this->actionDelay = 120;
+ this->spriteSettings.b.draw = 0;
+ *(u8*)&this->field_0x68 = 12;
+ gRoomControls.cameraTarget = this;
+ gUnk_02034490 = 255;
+ sub_0809F7BC(this);
+}
+
+void sub_0809F548(Entity* this) {
+
+ if (--this->actionDelay == 0) {
+ this->action = 2;
+ this->actionDelay = 90;
+ PlaySFX(285);
+ sub_0809F814((((this->x.HALF.HI - gRoomControls.roomOriginX) >> 4) & 63) |
+ (((this->y.HALF.HI - gRoomControls.roomOriginY) >> 4) & 63) << 6);
+ } else {
+ if ((gUnk_030010A0 & 7) == 0) {
+ sub_0809F7BC(this);
+ }
+ sub_0809F7F4(this);
+ }
+}
+
+void sub_0809F5B0(Entity* this) {
+ if (--this->actionDelay == 0) {
+ PlaySFX(115);
+ SetGlobalFlag(36);
+ LoadRoomEntityList(&gUnk_080DD750);
+ DeleteThisEntity();
+ }
+}
+
+void sub_0809F5DC(Entity* this) {
+ this->action = 1;
+ this->spriteSettings.b.draw = 0;
+ *(u8*)&this->field_0x68 = 12;
+}
+
+void sub_0809F5F0(Entity* this) {
+ u32 iVar1;
+
+ iVar1 = CheckRoomFlag(this->actionDelay);
+ if (iVar1 != 0) {
+ this->action = 2;
+ this->actionDelay = 120;
+ sub_08078A90(3);
+ sub_08078B48();
+ gRoomControls.cameraTarget = this;
+ }
+}
+
+void sub_0809F61C(Entity* this) {
+
+ if ((gRoomControls.unk6 & 4) == 0) {
+ if (this->actionDelay == 30) {
+ SetLocalFlag(this->entityType.parameter);
+ }
+ if (--this->actionDelay == 0) {
+ this->action = 3;
+ this->actionDelay = 120;
+ PlaySFX(285);
+ sub_0809F814((((this->x.HALF.HI - gRoomControls.roomOriginX) >> 4) & 63) |
+ (((this->y.HALF.HI - gRoomControls.roomOriginY) >> 4) & 63) << 6);
+ } else {
+ if ((gUnk_030010A0 & 7) == 0) {
+ sub_0809F7BC(this);
+ }
+ sub_0809F7F4(this);
+ }
+ }
+}
+
+void sub_0809F69C(Entity* this) {
+
+ if (--this->actionDelay == 0) {
+ this->actionDelay = 30;
+ this->action = 4;
+ gRoomControls.cameraTarget = &gLinkEntity;
+ PlaySFX(115);
+ }
+}
+
+void sub_0809F6CC(Entity* this) {
+
+ if (((gRoomControls.unk6 & 4) == 0) && (--this->actionDelay == 0)) {
+ gLinkState.unk7 = 1;
+ DeleteThisEntity();
+ }
+}
+
+void sub_0809F700(Entity* this) {
+ u8 bVar1;
+ u32 uVar2;
+
+ if (this->action == 0) {
+ this->action = 1;
+ this->actionDelay = (Random() & 30) + 8;
+ this->flags = this->flags | 12;
+ }
+ if ((gUnk_030010A0 & 3) == 0) {
+ uVar2 = Random();
+ this->spriteOffsetX = gUnk_081247C0[uVar2 & 7];
+ this->spriteOffsetY = gUnk_081247C0[uVar2 >> 4 & 7];
+ }
+ sub_0806F69C(this);
+ if (--this->actionDelay == 0) {
+ DeleteThisEntity();
+ }
+}
+
+#ifdef NON_MATCHING
+Entity* sub_0809F770(Entity* this) {
+ Entity* cloud;
+ s32 uVar1;
+
+ cloud = CreateObject(163, 1, 0);
+ if (cloud != NULL) {
+ PositionEntityOnTop(this, cloud);
+ uVar1 = Random();
+ cloud->x.HALF.HI = ((cloud->x.HALF.HI - 16) + (uVar1 >> 0)) & 31;
+ cloud->y.HALF.HI = ((cloud->y.HALF.HI - 16) + (uVar1 >> 8)) & 31;
+ cloud->animationList = (u8)(uVar1 >> 16) & 3;
+ cloud->direction = 255;
+ }
+ return cloud;
+}
+#else
+NAKED
+Entity* sub_0809F770(Entity* this) {
+ asm(".include \"asm/non_matching/cloud/sub_0809F770.inc\"");
+}
+#endif
+
+void sub_0809F7BC(Entity* this) {
+ Entity* cloud;
+ u32 uVar1;
+ u32 uVar2;
+
+ for (uVar2 = 0; uVar2 < 8; uVar2++) {
+ cloud = sub_0809F770(this);
+ if (cloud != NULL) {
+ uVar1 = Random();
+ cloud->nonPlanarMovement = gUnk_081247C8[uVar1 & 3];
+ cloud->direction = (u8)(uVar1 >> 8) & 31;
+ }
+ }
+}
+
+void sub_0809F7F4(Entity* this) {
+ u8 cVar1;
+ u8* puVar2;
+
+ puVar2 = (u8*)&this->field_0x68;
+ *puVar2 -= 1;
+
+ if (*puVar2 == 0) {
+ *puVar2 = 12;
+ PlaySFX(388);
+ }
+}
+
+void sub_0809F814(u32 r0) {
+ sub_0807BB68(&gUnk_081247D0, r0, 1);
+}
diff --git a/src/object/fan.c b/src/object/fan.c
new file mode 100644
index 00000000..481e3887
--- /dev/null
+++ b/src/object/fan.c
@@ -0,0 +1,86 @@
+#include "global.h"
+#include "entity.h"
+#include "flags.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*);
+
+extern void (*const gUnk_081243D4[])(Entity*);
+
+void Fan(Entity *this)
+{
+ gUnk_081243D4[this->action](this);
+}
+
+void sub_0809ED30(Entity *this)
+{
+ this->direction = (this->entityType.form ^ 2) << 3;
+ sub_0809EE34(this);
+ sub_0809EFB0(this);
+ InitializeAnimation(this, this->entityType.form);
+}
+
+void sub_0809ED54(Entity *this)
+{
+ u16 uVar1;
+ u32 iVar2;
+
+ if (((this->cutsceneBeh.HWORD == 0) || CheckFlags(this->cutsceneBeh.HWORD)) &&
+ ((this->entityType.parameter != 1 ||
+ (--this->field_0x74 == 0)))) {
+ sub_0809EE08(this);
+ }
+}
+
+void sub_0809ED88(Entity *this)
+{
+ sub_0809F08C();
+ sub_0809EE44(this);
+ if (this->field_0x86 != 0) {
+ if (this->cutsceneBeh.HWORD == this->field_0x86) {
+ if (CheckFlags(this->cutsceneBeh.HWORD)) {
+ return;
+ }
+ }
+ else if (!CheckFlags(this->cutsceneBeh.HWORD)) {
+ return;
+ }
+ sub_0809EE24(this);
+ }
+ else if (((this->entityType).parameter == 1) &&
+ (--this->field_0x74 == 0)) {
+ sub_0809EE24(this);
+ }
+}
+
+void sub_0809EDE4(Entity *this)
+{
+ sub_0809F08C();
+ sub_0809EE44(this);
+ if (this->frames.b.f3) {
+ sub_0809EE34(this);
+ }
+}
+
+void sub_0809EE08(Entity *this)
+{
+ this->action = 2;
+ this->field_0x74 = *((u8 *)&this->field_0x7c + 3) << 2;
+ InitializeAnimation(this, this->entityType.form);
+}
+
+void sub_0809EE24(Entity *this)
+{
+ this->action = 3;
+ InitializeAnimation(this, this->entityType.form + 4);
+}
+
+void sub_0809EE34(Entity *this)
+{
+ this->action = 1;
+ this->field_0x74 = this->actionDelay << 2;
+} \ No newline at end of file
diff --git a/src/object/giantLeaf.c b/src/object/giantLeaf.c
new file mode 100644
index 00000000..9003f28b
--- /dev/null
+++ b/src/object/giantLeaf.c
@@ -0,0 +1,35 @@
+#include "global.h"
+#include "entity.h"
+#include "room.h"
+
+void SetTile(u32 tileIndex, s32 tilePosition, s32 layerIndex);
+void sub_0808D618(Entity* ent);
+
+extern RoomControls gRoomControls;
+extern s16 gUnk_08121750[];
+extern s16 gUnk_0812176A[];
+
+void GiantLeaf(Entity* ent) {
+ if (ent->action == 0) {
+ ent->action = 1;
+ ent->spriteSettings.b.draw = 1;
+ ent->spriteRendering.b3 = 3;
+ ent->spritePriority.b0 = 7;
+ ent->frameIndex = ent->entityType.form;
+ sub_0808D618(ent);
+ }
+}
+
+void sub_0808D618(Entity* ent) {
+ u32 tilePos;
+ s16* arr;
+ u32 i;
+
+ arr = (ent->entityType.form != 0) ? gUnk_0812176A : gUnk_08121750;
+ tilePos = (((ent->x.HALF.HI - gRoomControls.roomOriginX) >> 4) & 0x3F) |
+ ((((ent->y.HALF.HI - gRoomControls.roomOriginY) >> 4) & 0x3F) * 64);
+
+ for (i = 0; i < 13; i++) {
+ SetTile(16500, tilePos + arr[i], 1);
+ }
+}
diff --git a/src/object/greatFairy.c b/src/object/greatFairy.c
new file mode 100644
index 00000000..2f3276b9
--- /dev/null
+++ b/src/object/greatFairy.c
@@ -0,0 +1,582 @@
+#include "global.h"
+#include "entity.h"
+#include "room.h"
+#include "screen.h"
+#include "greatFairy.h"
+
+// Main
+void GreatFairy(Entity* this) {
+ u8 bVar1;
+
+ if (this->action == 0) {
+ bVar1 = __modsi3(this->entityType.form, 11);
+ this->entityType.parameter = bVar1;
+ }
+ GreatFairy_Main[(this->entityType).parameter](this);
+}
+
+// Behaviors
+void GreatFairy_CallBehavior(Entity* this) {
+ GreatFairy_Behaviors[this->action](this);
+
+ if ((gLinkEntity.y.HALF.HI - gRoomControls.roomOriginY) < 168) {
+
+ gRoomControls.cameraTarget = this;
+ gRoomControls.unk5 = 2;
+ } else {
+ gRoomControls.cameraTarget = &gLinkEntity;
+ gRoomControls.unk5 = 2;
+ }
+}
+
+// Init
+void GreatFairy_Init(Entity* this) {
+ GreatFairy_InitializeAnimation(this);
+ this->actionDelay = 0;
+ this->cutsceneBeh.HWORD = 290;
+}
+
+// TODO: turn this into a switch statement
+void GreatFairy_DormantUpdate(Entity* this) {
+ u16* pFrame; // r1@2
+ s32 frame; // r1@4
+ Entity* ripple; // r5@16
+
+ if (!CheckRoomFlag(0)) return;
+
+ pFrame = &this->cutsceneBeh.HWORD;
+ if (*pFrame != 0) {
+ --*pFrame;
+ }
+ frame = *pFrame;
+
+ if (frame == 0x96) {
+ goto LABEL_16;
+ }
+
+ if (frame < 0x97) {
+ if (frame != 0) {
+ if (frame == 0x82) {
+ goto LABEL_16;
+ } else {
+ return;
+ }
+ }
+ goto LABEL_17;
+ } else {
+ if (frame == 0xd2) {
+ goto LABEL_16;
+ }
+ if (frame < 0xd3) {
+ if (frame == 0xaa) {
+ goto LABEL_16;
+ } else
+ return;
+ }
+ if (frame == 289) {
+ goto LABEL_16;
+ } else {
+ return;
+ }
+ }
+
+LABEL_17:
+ this->action = 2;
+ return;
+LABEL_16:
+ ripple = GreatFairy_CreateForm(this, RIPPLE, 0);
+ if (ripple) {
+ PositionRelative(this, ripple, (s32)GreatFairy_RippleOffsets[this->actionDelay] << 16,
+ (s32)GreatFairy_RippleOffsets[this->actionDelay + 1] << 16);
+ this->actionDelay += 2;
+ }
+}
+
+void GreatFairy_CreateBigRipple(Entity* this) {
+ Entity* ripple;
+
+ ripple = GreatFairy_CreateForm(this, BIGRIPPLE, 0);
+ if (ripple != NULL) {
+ PositionRelative(this, ripple, 0, 0x80000);
+ this->action = 3;
+ }
+}
+
+// Great Fairy spawning in update
+void GreatFairy_SpawningUpdate(Entity* this) {
+ Entity* mini;
+ u32 var;
+
+ if (gRoomVars.greatFairyState & 1) {
+ mini = GreatFairy_CreateForm(this, WAKE, 0); //???
+ if (mini != NULL) {
+ CopyPosition(this, mini);
+ DoFade(6, 4);
+ PlaySFX(325);
+ this->action = 4;
+ this->actionDelay = 0x3c;
+ var = this->spriteSettings.raw & ~0x3;
+ this->spriteSettings.raw = (this->spriteSettings.raw & var) | 1;
+ }
+ }
+}
+
+void GreatFairy_MiniUpdate(Entity* this) {
+ Entity* target;
+
+ GetNextFrame(this);
+ if (this->actionDelay != 0) {
+ --this->actionDelay;
+ } else {
+ target = GreatFairy_CreateForm(this, WINGS, 0);
+ if (target != NULL) {
+ PositionRelative(this, target, 0, -0x140000);
+ this->action = 5;
+ this->actionDelay = 120;
+ this->field_0xf = 0;
+ }
+ }
+}
+
+// This is the great fairy's "normal" form
+void GreatFairy_FinalUpdate(Entity* this) {
+ Entity* target;
+
+ if (this->actionDelay != 0) {
+ --this->actionDelay;
+ } else {
+ if ((this->field_0xf == 0) && (target = GreatFairy_CreateForm(this, FORM9, 0), target != NULL)) {
+ PositionRelative(this, target, 0, -0x4C0000);
+ target->parent = this;
+ this->field_0xf = 1;
+ }
+ }
+ GetNextFrame(this);
+}
+
+void GreatFairy_WingsCallBehavior(Entity* this) {
+ GreatFairy_WingsBehaviors[this->action](this);
+}
+
+void GreatFairy_WingsInit(Entity* this) {
+ GreatFairy_InitializeAnimation(this);
+ this->spritePriority.b0 = 5;
+ this->spriteSettings.b.draw = 1;
+ this->spriteRendering.alphaBlend = 1;
+ gScreen.controls.windowOutsideControl = 3904;
+ gScreen.controls.mosaicSize = 2057;
+ this->nonPlanarMovement = 1024;
+ sub_0805EC9C(this, 1024, 256, 0);
+}
+
+void GreatFairy_WingsUpdate(Entity* this) {
+ s32 iVar1;
+
+ iVar1 = this->nonPlanarMovement -= 32;
+ if (iVar1 * 65536 >> 16 == 256) {
+ this->action = 2;
+ sub_0805EC60(this);
+ gRoomVars.greatFairyState |= 32;
+ gUnk_02033280 |= 4;
+ } else {
+ sub_0805EC9C(this, this->nonPlanarMovement, 256, 0);
+ }
+}
+
+void nullsub_116(Entity* this) {}
+
+//The wake that appears beneath the Great Fairy as she stands in the water
+void GreatFairy_WakeCallBehavior(Entity* this) {
+ GreatFairy_WakeBehaviors[this->action](this);
+}
+
+void GreatFairy_WakeInit(Entity* this) {
+ GreatFairy_InitializeAnimation(this);
+ this->spriteSettings.b.draw = 1;
+ this->spritePriority.b0 = 6;
+}
+
+void GreatFairy_WakeUpdate(Entity* this) {
+ GetNextFrame(this);
+}
+
+//The miniature sprite that emerges from the water when Great Fairy is spawned
+void GreatFairy_MiniCallBehavior(Entity* this) {
+ GreatFairy_MiniBehaviors[this->action](this);
+}
+
+void GreatFairy_MiniInit(Entity* this) {
+ Entity* aff;
+
+ aff = GreatFairy_CreateForm(this, MINIAFFINE, 0);
+ if (aff != NULL) {
+ CopyPosition(this, aff);
+ aff->parent = this;
+ GreatFairy_InitializeAnimation(this);
+ this->spriteSettings.b.draw = 1;
+ this->field_0xf = 0;
+ }
+}
+
+// Spawns a droplet of water once it reaches a certain height
+void GreatFairy_MiniRisingUpdate(Entity* this) {
+ Entity* target;
+
+ GetNextFrame(this);
+ this->height.WORD -= 0x8000;
+ if (this->height.HALF.HI == -20) {
+ this->action = 2;
+ PlaySFX(321);
+ } else {
+ if (((this->height.HALF.HI == -10) && (this->field_0xf == 0)) &&
+ (target = GreatFairy_CreateForm(this, DROPLET, 0), target != NULL)) {
+ PositionRelative(this, target, 0, 0x40000);
+ this->field_0xf = 1;
+ }
+ }
+}
+
+// Deletes itself
+void GreatFairy_MiniRemoveMe(Entity* this) {
+ GetNextFrame(this);
+ sub_080873D0(this);
+ if ((gRoomVars.greatFairyState & 1) != 0) {
+ DeleteEntity(this);
+ }
+}
+
+//Same as mini Great Fairy except it is able to stretch
+void GreatFairy_MiniAffineCallBehavior(Entity* this) {
+ GreatFairy_MiniAffineBehaviors[this->action](this);
+}
+
+void GreatFairy_MiniAffineInit(Entity* this) {
+ GreatFairy_InitializeAnimation(this);
+ this->spritePriority.b0 = 6;
+ this->spriteSettings.b.draw = 1;
+}
+
+// Getting ready for affine transformation
+void GreatFairy_MiniAffineInit2(Entity* this) {
+ Entity* parent = this->parent;
+
+ CopyPosition(parent, this);
+
+ if (this->height.HALF.HI == -20) {
+ this->action = 2;
+ this->actionDelay = 90;
+ this->nonPlanarMovement = 4096;
+ this->spriteRendering.b0 = 3;
+ sub_0805EC9C(this, 256, 256, 0);
+ }
+}
+
+// Mini great fairy stretch
+void GreatFairy_MiniAffineUpdate(Entity* this) {
+ s32 iVar2;
+
+ if (--this->actionDelay == 0) {
+ gRoomVars.greatFairyState |= 1;
+ this->action = 3;
+ sub_0805EC60(this);
+ } else {
+ iVar2 = this->nonPlanarMovement -= 24;
+ sub_0805EC9C(this, 256, iVar2 * 0x10000 >> 20, 0);
+ }
+}
+
+//The droplet that falls off of the mini Great Fairy emerging from the water
+void GreatFairy_DropletCallBehavior(Entity* this) {
+ GreatFairy_DropletBehaviors[this->action](this);
+}
+
+
+void GreatFairy_DropletInit(Entity* this) {
+ GreatFairy_InitializeAnimation(this);
+ this->spriteSettings.b.draw = 1;
+ this->height.HALF.HI = 0;
+ this->spritePriority.b0 = 5;
+ PlaySFX(320);
+}
+
+void GreatFairy_DropletUpdate(Entity* this) {
+ GetNextFrame(this);
+ if (this->frames.b.f3) {
+ DeleteEntity(this);
+ }
+}
+
+// Ripples that appear before the great fairy emerges
+void GreatFairy_RippleCallBehavior(Entity* this) {
+ GreatFairy_RippleBehaviors[this->action](this);
+}
+
+void GreatFairy_RippleInit(Entity* this) {
+ GreatFairy_InitializeAnimation(this);
+ this->spriteSettings.b.draw = 1;
+ this->spritePriority.b0 = 6;
+}
+
+void GreatFairy_RippleUpdate(Entity* this) {
+ if ((gRoomVars.greatFairyState & 2) != 0) {
+ DeleteEntity(this);
+ } else {
+ GetNextFrame(this);
+ }
+}
+
+// Big ripple that appears in the spot where the fairy emerges from
+void GreatFairy_BigRippleCallBehavior(Entity* this) {
+ GreatFairy_BigRippleBehaviors[this->action](this);
+}
+
+void GreatFairy_BigRippleInit(Entity* this) {
+ GreatFairy_InitializeAnimation(this);
+ this->actionDelay = 120;
+ this->spriteSettings.b.draw = 1;
+ this->spritePriority.b0 = 5;
+ PlaySFX(249);
+}
+
+void GreatFairy_BigRippleUpdate(Entity* this) {
+ Entity* target;
+
+ GetNextFrame(this);
+ if (this->actionDelay != 0) {
+ --this->actionDelay;
+ } else {
+ target = GreatFairy_CreateForm(this, MINI, 0);
+ if (target != NULL) {
+ PositionRelative(this, target, 0, -0x80000);
+ gRoomVars.greatFairyState |= 2;
+ DeleteEntity(this);
+ }
+ }
+}
+
+// Energy bands that surround the mini Great Fairy as it is transforming
+void GreatFairy_EnergyCallBehavior(Entity* this) {
+ GreatFairy_EnergyBehaviors[this->action](this);
+}
+
+void GreatFairy_EnergyInit(Entity* this) {
+ GreatFairy_InitializeAnimation(this);
+ this->spriteSettings.b.draw = 1;
+ this->spritePriority.b0 = 5;
+}
+
+void GreatFairy_EnergyUpdate(Entity* this) {
+ GetNextFrame(this);
+ if (this->frames.b.f3) {
+ DeleteEntity(this);
+ }
+}
+
+void sub_08087114(Entity* this) {
+ if ((this->entityType).parameter == 0) {
+ GreatFairy_Form1Behaviors[this->action](this);
+ } else {
+ GreatFairy_Form2Behaviors[this->action](this);
+ GetNextFrame(this);
+ }
+}
+
+#ifdef NON_MATCHING
+void sub_08087150(Entity* this) {
+ u8 var;
+ u32 var2;
+
+ GreatFairy_InitializeAnimation(this);
+ this->spriteSettings.b.draw = 1;
+ this->spriteOrientation &= 63;
+ this->spriteRendering.b0 = 0;
+ this->spritePriority.b0 = 3;
+ this->nonPlanarMovement = 128;
+ this->direction = 16;
+ var = gUnk_0812079C[0];
+ this->palette = ((var & 15) * 16) | this->direction;
+}
+#else
+NAKED
+void sub_08087150(Entity* this) {
+ asm(".include \"asm/greatFairy/sub_08087150.inc\"");
+}
+#endif
+
+void nullsub_516(Entity* this) {}
+
+void sub_080871A8(Entity* this) {
+ u32 bVar1;
+
+ if (--this->actionDelay == 0) {
+ this->action = 3;
+ this->actionDelay = 60;
+ gRoomVars.greatFairyState |= 4;
+ }
+}
+
+void sub_080871D0(Entity* this) {
+
+ if (--this->actionDelay == 0) {
+ gRoomVars.greatFairyState |= 8;
+ DeleteEntity(this);
+ }
+}
+
+#ifdef NON_MATCHING
+void sub_080871F8(Entity* this) {
+ s32 bVar1;
+
+ if (((this->attachedEntity->x.HALF.HI == (this->x).HALF.HI) &&
+ ((Entity*)this->attachedEntity)->y.HALF.HI + -32 == (this->y).HALF.HI)) {
+ this->action = 2;
+ } else {
+ bVar1 = (this->x).HALF.HI;
+ sub_080045D4();
+ this->direction = bVar1;
+ sub_0806F69C(this);
+ }
+}
+#else
+NAKED
+void sub_080871F8(Entity* this) {
+ asm(".include \"asm/greatFairy/sub_080871F8.inc\"");
+}
+#endif
+
+void sub_08087240(Entity* this) {
+ if ((gRoomVars.greatFairyState & 4) != 0) {
+ this->action = 3;
+ this->actionDelay = 20;
+ this->direction = 16;
+ }
+}
+
+void sub_08087264(Entity* this) {
+ if (this->actionDelay != 0) {
+ this->actionDelay--;
+ sub_0806F69C(this);
+ }
+}
+
+void sub_0808727C(Entity* this) {
+
+ if (--this->actionDelay == 0) {
+ DeleteEntity(this);
+ }
+}
+
+void sub_08087294(Entity* this) {
+ gUnk_081207A4[this->action](this);
+}
+
+#ifdef NON_MATCHING
+void sub_080872AC(Entity* this) {
+ this->spriteSettings.b.draw = 1;
+ this->spriteOrientation.flipY = 1;
+ this->spriteRendering.b0 = 0;
+ this->field_0x68 = (u16)(this->x).HALF.HI;
+ this->field_0x6a = (u16)(this->y).HALF.HI;
+ this->direction = (u8)Random() & 0x1F;
+ this->nonPlanarMovement = 32;
+ GreatFairy_InitializeAnimation(this);
+}
+#else
+NAKED
+void sub_080872AC(Entity* this) {
+ asm(".include \"asm/greatFairy/sub_080872AC.inc\"");
+}
+#endif
+
+//clang-format off
+void (*const GreatFairy_Main[])(Entity*) = {
+ GreatFairy_CallBehavior,
+ GreatFairy_WingsCallBehavior,
+ GreatFairy_WakeCallBehavior,
+ GreatFairy_MiniCallBehavior,
+ GreatFairy_MiniAffineCallBehavior,
+ GreatFairy_DropletCallBehavior,
+ GreatFairy_RippleCallBehavior,
+ GreatFairy_BigRippleCallBehavior,
+ GreatFairy_EnergyCallBehavior,
+ sub_08087114,
+ sub_08087294
+};
+
+void (*const GreatFairy_Behaviors[])(Entity*) = {
+ GreatFairy_Init,
+ GreatFairy_DormantUpdate,
+ GreatFairy_CreateBigRipple,
+ GreatFairy_SpawningUpdate,
+ GreatFairy_MiniUpdate,
+ GreatFairy_FinalUpdate
+};
+
+const s16 GreatFairy_RippleOffsets[10] = {
+ 0, 0,
+ -32, -8,
+ 16, 20,
+ 24, -12,
+ -16, 24
+};
+
+
+void (*const GreatFairy_WingsBehaviors[])(Entity*) = {
+ GreatFairy_WingsInit,
+ GreatFairy_WingsUpdate,
+ nullsub_116
+};
+
+void (*const GreatFairy_WakeBehaviors[])(Entity*) = {
+ GreatFairy_WakeInit,
+ GreatFairy_WakeUpdate
+};
+
+void (*const GreatFairy_MiniBehaviors[])(Entity*) = {
+ GreatFairy_MiniInit,
+ GreatFairy_MiniRisingUpdate,
+ GreatFairy_MiniRemoveMe
+};
+
+void (*const GreatFairy_MiniAffineBehaviors[])(Entity*) = {
+ GreatFairy_MiniAffineInit,
+ GreatFairy_MiniAffineInit2,
+ GreatFairy_MiniAffineUpdate,
+ DeleteEntity
+};
+
+void (*const GreatFairy_DropletBehaviors[])(Entity*) = {
+ GreatFairy_DropletInit,
+ GreatFairy_DropletUpdate
+};
+
+void (*const GreatFairy_RippleBehaviors[])(Entity*) = {
+ GreatFairy_RippleInit,
+ GreatFairy_RippleUpdate
+};
+
+void (*const GreatFairy_BigRippleBehaviors[])(Entity*) = {
+ GreatFairy_BigRippleInit,
+ GreatFairy_BigRippleUpdate
+};
+
+void (*const GreatFairy_EnergyBehaviors[])(Entity*) = {
+ GreatFairy_EnergyInit,
+ GreatFairy_EnergyUpdate
+};
+void (*const GreatFairy_Form1Behaviors[])(Entity*) = {
+ sub_08087150,
+ nullsub_516,
+ sub_080871A8,
+ sub_080871D0
+};
+
+void (*const GreatFairy_Form2Behaviors[])(Entity*) = {
+ sub_08087150,
+ sub_080871F8,
+ sub_08087240,
+ sub_08087264,
+ sub_0808727C
+};
+
+//clang-format on
diff --git a/src/object/heartContainer.c b/src/object/heartContainer.c
new file mode 100644
index 00000000..10714a8e
--- /dev/null
+++ b/src/object/heartContainer.c
@@ -0,0 +1,36 @@
+#include "global.h"
+#include "entity.h"
+#include "flags.h"
+
+extern void DeleteThisEntity();
+extern void sub_0808E714(Entity*);
+
+extern void (*const gUnk_08121C48[])(Entity*);
+
+extern BoundingBox gUnk_08121C58;
+
+void HeartContainer(Entity* this) {
+ gUnk_08121C48[this->action](this);
+}
+
+void sub_0808E6A0(Entity* this) {
+
+ if (CheckFlags(*(u16*)&this->cutsceneBeh)) {
+ DeleteThisEntity();
+ }
+ this->action = 1;
+ this->entityType.form = 0x62;
+ this->spriteSettings.b.draw = 0;
+ this->boundingBox = &gUnk_08121C58;
+ this->collisionLayer = 3;
+ this->scriptedScene = 3;
+}
+
+void sub_0808E6E4(Entity* this) {
+ if (CheckFlags(this->field_0x86)) {
+ this->action = 2;
+ this->spriteSettings.b.draw = 1;
+ this->spriteRendering.b0 = 3;
+ sub_0808E714(this);
+ }
+}
diff --git a/src/object/lightableSwitch.c b/src/object/lightableSwitch.c
new file mode 100644
index 00000000..2368da04
--- /dev/null
+++ b/src/object/lightableSwitch.c
@@ -0,0 +1,145 @@
+#include "global.h"
+#include "entity.h"
+#include "room.h"
+#include "flags.h"
+#include "functions.h"
+
+extern void sub_0809EB30(Entity*);
+extern void sub_0809EAD8(Entity*);
+extern void sub_0809EABC(Entity*);
+extern void sub_08004488(u32);
+extern void sub_080A2CC0(Entity*, Entity**, u16*);
+extern Entity* GetCurrentRoomProperty(u32);
+extern void SetTile(u32, u32, u32);
+extern void sub_0806F69C(Entity*);
+
+extern void (*const gUnk_081243B4[])(Entity*);
+extern void (*const gUnk_081243BC[])(Entity*);
+extern void (*const gUnk_081243C4[])(Entity*);
+
+extern BoundingBox gUnk_080FD150;
+
+void LightableSwitch(Entity* this) {
+ gUnk_081243B4[this->entityType.form](this);
+ sub_0809EB30(this);
+}
+
+void sub_0809EA1C(Entity* this) {
+ gUnk_081243BC[this->action](this);
+}
+
+void sub_0809EA34(Entity* this) {
+ this->action = 1;
+ this->flags = this->flags | 0x80;
+ this->frameIndex = 0;
+ this->field_0x3c = 7;
+ this->field_0x40 = 0x48;
+ this->damageType = 0x28;
+ this->flags2 = 10;
+ this->boundingBox = &gUnk_080FD150;
+ sub_0809EAD8(this);
+ UpdateSpriteForCollisionLayer(this);
+ sub_0809EABC(this);
+}
+
+void sub_0809EA80(Entity* this) {
+
+ if ((this->bitfield & 0x80) != 0) {
+ if (CheckFlags(this->field_0x86) != 0) {
+ ClearFlag(this->field_0x86);
+ } else {
+ SetFlag(this->field_0x86);
+ }
+ sub_08004488(0x110);
+ }
+ sub_0809EABC(this);
+}
+
+void sub_0809EABC(Entity* this) {
+ bool32 anySet;
+ u32 f;
+
+ f = CheckFlags(this->field_0x86);
+ anySet = (-f | f) >> 0x1F;
+ if (this->frameIndex != anySet) {
+ this->frameIndex = anySet;
+ }
+}
+
+void sub_0809EAD8(Entity* this) {
+ u8 bVar1;
+ Entity* pEVar2;
+
+ if (this->entityType.parameter != 0) {
+
+ this->attachedEntity = GetCurrentRoomProperty(this->entityType.parameter);
+ sub_080A2CC0(this, &this->attachedEntity, &this->field_0x74);
+
+ } else {
+ SetTile(0x4050, COORD_TO_TILE(this), this->collisionLayer);
+ }
+}
+
+void sub_0809EB30(Entity* this) {
+ u16 uVar1;
+ u16* puVar2;
+
+ if (this->entityType.parameter != 0) {
+ if ((this->direction & 0x80) == 0) {
+ sub_0806F69C(this);
+ }
+ puVar2 = &this->field_0x74;
+ if (!--*puVar2) {
+ sub_080A2CC0(this, &this->attachedEntity, puVar2);
+ }
+ }
+}
+
+void sub_0809EB68(Entity* this) {
+ gUnk_081243C4[this->action](this);
+}
+
+void sub_0809EB80(Entity* this) {
+
+ this->action = 1;
+ this->flags = this->flags | 0x80;
+ this->frameIndex = 3;
+ this->field_0x3c = 7;
+ this->field_0x40 = 0x48;
+ this->damageType = 0x28;
+ this->flags2 = 10;
+ this->boundingBox = &gUnk_080FD150;
+ sub_0809EAD8(this);
+ UpdateSpriteForCollisionLayer(this);
+ if (CheckFlags(this->cutsceneBeh.HWORD) != 0) {
+ this->action = 3;
+ this->frameIndex = 2;
+ }
+}
+
+void sub_0809EBD8(Entity* this) {
+ if ((this->bitfield & 0x80) != 0) {
+ this->action = 2;
+ this->actionDelay = 0x10;
+ this->frameIndex = 2;
+ SetFlag(this->field_0x86);
+ sub_08004488(0x110);
+ }
+}
+
+void sub_0809EC08(Entity* this) {
+
+ if (CheckFlags(this->cutsceneBeh.HWORD) != 0) {
+ this->action = 3;
+
+ } else {
+ if (--this->actionDelay == 0) {
+ this->action = 1;
+ this->frameIndex = 3;
+ ClearFlag(this->field_0x86);
+ sub_08004488(0x110);
+ }
+ }
+}
+
+void nullsub_126(Entity* this) { } \ No newline at end of file
diff --git a/src/object/mask.c b/src/object/mask.c
new file mode 100644
index 00000000..6dd866c9
--- /dev/null
+++ b/src/object/mask.c
@@ -0,0 +1,140 @@
+#include "global.h"
+#include "entity.h"
+#include "room.h"
+#include "random.h"
+
+extern Entity gLinkEntity;
+extern u16 gUnk_030010A0[];
+
+extern void (*MaskActionFuncs[])(Entity *);
+
+extern void DeleteThisEntity();
+
+extern bool32 CheckFlags(u16);
+extern void SetFlag(u16);
+extern void ClearFlag(u16);
+
+extern void SetTile(u32, u16, u32);
+
+extern void sub_08000148(u16, u16, u32);
+extern s16 sub_080001DA(u16, u32);
+extern u16 sub_080002E0(u16, u32);
+
+extern void sub_08004488(u32);
+extern void sub_080044EC(Entity *, u16);
+extern void sub_0805457C(Entity *, s32);
+
+
+void Mask(Entity *this) {
+ MaskActionFuncs[this->action](this);
+}
+
+void sub_080929A4(Entity *this) {
+ if (this->entityType.parameter & 0xC0) {
+ if (CheckFlags(this->field_0x86)) {
+ s32 field_0x0a;
+
+ switch (this->entityType.parameter & 0xC0) {
+ case 0x40:
+ field_0x0a = gUnk_030010A0[0x5];
+
+ switch (field_0x0a) {
+ case 0x44D ... 0x44F:
+ case 0x182:
+ DeleteThisEntity();
+ goto switchEnd;
+ }
+
+ ClearFlag(this->field_0x86);
+ break;
+ case 0x80:
+ DeleteThisEntity();
+ break;
+ }
+ switchEnd:
+ }
+ }
+
+ this->action = 1;
+ this->field_0x20 = 0x18000;
+
+ this->field_0x78.HWORD = ((Random() & 7) << 10) | 0x2000;
+
+ this->field_0xf = this->actionDelay >> 1;
+ this->actionDelay = 0;
+
+ this->frameIndex = this->entityType.parameter & 0x3f;
+
+ this->field_0x7c.HALF.HI = COORD_TO_TILE(this);
+ this->field_0x7c.HALF.LO = sub_080001DA(this->field_0x7c.HALF.HI, 1);
+
+ this->field_0x7a = sub_080002E0(this->field_0x7c.HALF.HI, 1);
+
+ SetTile(0x4022, this->field_0x7c.HALF.HI, 1);
+}
+
+// Probably related to knocking it down
+void sub_08092A94(Entity *this) {
+ // Check for the first frame of bonking animation
+ if (gLinkEntity.action != 6) {
+ return;
+ }
+
+ if (gLinkEntity.animationState != 0) {
+ return;
+ }
+
+ // Check if link is close enough to the mask
+ if (this->y.HALF.HI + 40 < gLinkEntity.y.HALF.HI) {
+ return;
+ }
+
+ if (this->x.HALF.HI - gLinkEntity.x.HALF.HI >= this->field_0xf || this->x.HALF.HI - gLinkEntity.x.HALF.HI <= -this->field_0xf) {
+ return;
+ }
+
+ // Presumably, make the mask fall
+ SetTile((u16)this->field_0x7c.HALF.LO, this->field_0x7c.HALF.HI, 1);
+
+ sub_08000148(this->field_0x7a, this->field_0x7c.HALF.HI, 1);
+
+ this->action = 2;
+
+ this->height.HALF.HI -= 0x20;
+ this->y.HALF.HI += 0x20;
+
+ this->spriteRendering.b3 = 2;
+}
+
+// Probably falling down
+void sub_08092B0C(Entity *this) {
+ if (this->actionDelay == 1) {
+ this->action = 3;
+
+ this->actionDelay = 0;
+ switch (this->entityType.parameter & 0xC0)
+ {
+ case 0x80:
+ sub_08004488(0x72);
+ case 0x40:
+ SetFlag(this->field_0x86);
+ break;
+
+ }
+
+ CreateFx(this, 5, 0);
+
+ sub_0805457C(this, 3);
+ }
+ else {
+ sub_080044EC(this, this->field_0x78.HWORD);
+
+ if (this->height.HALF.HI == 0) {
+ this->actionDelay++;
+ }
+ }
+}
+
+void Mask_Delete(Entity *this) {
+ DeleteThisEntity();
+}
diff --git a/src/object/metalDoor.c b/src/object/metalDoor.c
new file mode 100644
index 00000000..1f18a272
--- /dev/null
+++ b/src/object/metalDoor.c
@@ -0,0 +1,115 @@
+#include "global.h"
+#include "entity.h"
+#include "room.h"
+#include "flags.h"
+
+extern u32 sub_08083734(Entity*, u32);
+extern void sub_080A080C(Entity*);
+extern void sub_0806F69C(Entity*);
+extern void sub_08004488(u32);
+extern void sub_080A0870(Entity*);
+extern void PlaySFX(u32);
+extern u32 sub_080001DA(u32, u32);
+extern void SetTile(u32, u32, u32);
+
+extern void (*const gUnk_0812493C[])(Entity*);
+
+extern BoundingBox gUnk_080FD180;
+
+void MetalDoor(Entity* this) {
+ gUnk_0812493C[this->action](this);
+}
+
+void sub_080A0684(Entity *this)
+{
+ if ((this->cutsceneBeh.HWORD != 0xffff) && CheckFlags(this->cutsceneBeh.HWORD)) {
+ DeleteThisEntity();
+ }
+ this->action = 1;
+ this->nonPlanarMovement = 0x300;
+ this->spriteSettings.b.draw = 0;
+ this->frameIndex = 0;
+ this->spriteSettings.b.flipY = 1;
+ this->boundingBox = &gUnk_080FD180;
+ this->spritePriority.b0 = 5;
+ this->field_0x70.HALF.LO = this->x.HALF.HI;
+ this->field_0x70.HALF.HI = this->y.HALF.HI;
+ this->field_0x74 = COORD_TO_TILE(this);
+}
+
+void sub_080A0718(Entity *this)
+{
+ if (sub_08083734(this, 2) != 0) {
+ this->action = 2;
+ this->actionDelay = 0xc;
+ this->spriteSettings.b.draw = TRUE;
+ this->direction = 0;
+ this->y.HALF.HI += 0x24;
+ sub_080A080C(this);
+ }
+}
+
+void sub_080A074C(Entity *this)
+{
+ u8 bVar1;
+ Entity *ent;
+
+ sub_0806F69C(this);
+
+ if (--this->actionDelay == 0) {
+ this->action = 3;
+ this->height.HALF.HI = 0;
+ this->x.HALF.HI = this->field_0x70.HALF.LO;
+ this->y.HALF.HI = this->field_0x70.HALF.HI;
+ ent = CreateFx(this, 0x11, 0x40);
+ if (ent != NULL) {
+ ent->x.HALF.HI += 0xc;
+ ent->y.HALF.HI -= 0xc;
+ }
+ ent = CreateFx(this, 0x11, 0x40);
+ if (ent != NULL) {
+ ent->x.HALF.HI -= 0xc;
+ ent->y.HALF.HI -= 0xc;
+ }
+ sub_08004488(0x10b);
+ }
+}
+
+void sub_080A07BC(Entity *this)
+{
+ if (CheckFlags(this->field_0x86)) {
+ this->action = 4;
+ this->actionDelay = 0xc;
+ this->direction = 0x10;
+ this->y.HALF.HI += 2;
+ sub_080A0870(this);
+ PlaySFX(0x10b);
+ }
+}
+
+void sub_080A07F0(Entity *this)
+{
+
+ sub_0806F69C(this);
+
+ if (--this->actionDelay == 0) {
+ DeleteThisEntity();
+ }
+}
+
+void sub_080A080C(Entity *this)
+{
+ this->field_0x76 = sub_080001DA(this->field_0x74 - 1, this->collisionLayer);
+ this->field_0x78.HWORD = sub_080001DA(this->field_0x74, this->collisionLayer);
+ this->field_0x7a = sub_080001DA(this->field_0x74 + 1, this->collisionLayer);
+ SetTile(0x4022, this->field_0x74 - 1, this->collisionLayer);
+ SetTile(0x4022, this->field_0x74, this->collisionLayer);
+ SetTile(0x4022, this->field_0x74 + 1, this->collisionLayer);
+}
+
+void sub_080A0870(Entity *this)
+{
+ SetTile(this->field_0x76, this->field_0x74 - 1, this->collisionLayer);
+ SetTile(this->field_0x78.HWORD, this->field_0x74, this->collisionLayer);
+ SetTile(this->field_0x7a, this->field_0x74 + 1, this->collisionLayer);
+} \ No newline at end of file
diff --git a/src/object/mineralWaterSource.c b/src/object/mineralWaterSource.c
new file mode 100644
index 00000000..c874530b
--- /dev/null
+++ b/src/object/mineralWaterSource.c
@@ -0,0 +1,47 @@
+#include "global.h"
+#include "entity.h"
+
+extern void (*MineralWaterSourceActionFuncs[])(Entity *);
+
+typedef struct {
+ u8 field_0x00;
+ u8 field_0x01;
+ u8 field_0x02;
+ u8 field_0x03;
+} UnkStruct_MineralWater;
+
+extern UnkStruct_MineralWater MineralWaterSourceParameters[];
+
+extern bool32 sub_0806FBD8(Entity *);
+
+void MineralWaterSource(Entity *this) {
+ MineralWaterSourceActionFuncs[this->action](this);
+}
+
+void MineralWaterSource_Init(Entity *this) {
+ UnkStruct_MineralWater *unknownParameters;
+
+ if (!sub_0806FBD8(this)) {
+ return;
+ }
+
+ unknownParameters = &MineralWaterSourceParameters[this->entityType.form];
+
+ this->entityType.parameter = unknownParameters->field_0x00;
+ this->field_0x40 = unknownParameters->field_0x03;
+
+ this->boundingBox->field_0x6 = unknownParameters->field_0x01;
+ this->boundingBox->field_0x7 = unknownParameters->field_0x02;
+
+ this->flags |= 0x80;
+
+ this->field_0x3c = 7;
+ this->damageType = 145;
+ this->flags2 = 2;
+
+ this->action = 1;
+}
+
+void sub_080973DC(Entity *this) {
+ this->bitfield = 0;
+} \ No newline at end of file
diff --git a/src/object/minishSizedEntrance.c b/src/object/minishSizedEntrance.c
new file mode 100644
index 00000000..ca261d35
--- /dev/null
+++ b/src/object/minishSizedEntrance.c
@@ -0,0 +1,27 @@
+#include "global.h"
+#include "entity.h"
+
+extern u32 Random();
+extern bool32 CheckIsDungeon();
+extern void sub_080AE068(Entity*);
+extern void LoadFixedGFX(Entity*, u32);
+
+extern void (*const gUnk_08122254[])(Entity*);
+
+void MinishSizedEntrance(Entity* this)
+{
+ gUnk_08122254[this->action](this);
+}
+
+void sub_08090EC0(Entity *this)
+{
+ this->action = 1;
+ this->spriteRendering.b3 = 3;
+ this->spritePriority.b0 = 7;
+ this->frameIndex = (this->entityType).parameter;
+ if (CheckIsDungeon()) {
+ this->frameIndex += 4;
+ sub_080AE068(this);
+ LoadFixedGFX(this, 0x184);
+ }
+}
diff --git a/src/object/object1A.c b/src/object/object1A.c
new file mode 100644
index 00000000..f7d9e469
--- /dev/null
+++ b/src/object/object1A.c
@@ -0,0 +1,64 @@
+#include "global.h"
+#include "entity.h"
+
+extern void CopyPosition();
+extern void sub_08086A6C();
+extern s32 sub_080044EC();
+extern void sub_080AEF88();
+extern void DeleteThisEntity();
+extern u32 Random(void);
+
+extern void (*gUnk_081206C4[99])(Entity*);
+
+extern BoundingBox gUnk_080FD1A8;
+
+// Main
+void Object1A(Entity* ent) {
+ gUnk_081206C4[ent->action](ent);
+}
+
+void sub_080869DC(Entity* ent) {
+ Entity* itemEntity;
+
+ ent->action = 1;
+ ent->spriteSettings.b.draw = 0;
+ ent->boundingBox = &gUnk_080FD1A8;
+ ent->field_0x3c |= 16;
+ itemEntity = CreateObject(0, ent->entityType.form, 0);
+ if (itemEntity != NULL) {
+ itemEntity->actionDelay = 10;
+ itemEntity->parent = ent;
+ ent->attachedEntity = itemEntity;
+ CopyPosition(ent, itemEntity);
+ sub_08086A6C(ent);
+ }
+}
+
+void sub_08086A28(Entity* ent) {
+ s32 iVar1;
+
+ if (ent->attachedEntity->field_0x4 == NULL) {
+ ent->action = 2;
+ } else {
+ iVar1 = sub_080044EC(ent, 10240);
+ if (iVar1 == 0) {
+ ent->action = 2;
+ }
+ sub_080AEF88(ent);
+ CopyPosition(ent, ent->attachedEntity);
+ }
+}
+
+void sub_08086A5C(Entity* ent) {
+ ent->attachedEntity->parent = NULL;
+ DeleteThisEntity();
+}
+
+void sub_08086A6C(Entity* ent) {
+ u32 uVar1;
+
+ uVar1 = Random();
+ ent->field_0x20 = 163840;
+ ent->direction = (uVar1 >> 16) & 31;
+ ent->nonPlanarMovement = uVar1 & 480;
+}
diff --git a/src/object/object1C.c b/src/object/object1C.c
new file mode 100644
index 00000000..16c20816
--- /dev/null
+++ b/src/object/object1C.c
@@ -0,0 +1,19 @@
+#include "global.h"
+#include "entity.h"
+
+extern u32 CheckRectOnScreen(s16, s16, u32, u32);
+extern void DeleteThisEntity();
+
+void Object1C(Entity *this)
+{
+ s32 iVar1;
+
+ if (this->action == 0) {
+ this->action = 1;
+ }
+ iVar1 = CheckRectOnScreen(this->field_0x80, this->field_0x82, 0x10, 0x10);
+ if (iVar1 == 0) {
+ this->parent->field_0x20 &= ~(1 << this->entityType.parameter);
+ DeleteThisEntity();
+ }
+}
diff --git a/src/object/object1D.c b/src/object/object1D.c
new file mode 100644
index 00000000..1912facb
--- /dev/null
+++ b/src/object/object1D.c
@@ -0,0 +1,18 @@
+#include "global.h"
+#include "entity.h"
+
+void DeleteThisEntity();
+
+extern void (*gUnk_081208A0[])(Entity*);
+
+void Object1D(Entity *this)
+{
+ gUnk_081208A0[this->action](this);
+}
+
+void sub_080874F8(Entity* this)
+{
+ DeleteThisEntity();
+}
+
+void nullsub_117(Entity* this){}
diff --git a/src/object/object49.c b/src/object/object49.c
new file mode 100644
index 00000000..d9551953
--- /dev/null
+++ b/src/object/object49.c
@@ -0,0 +1,155 @@
+#include "global.h"
+#include "entity.h"
+
+extern u32 Random(void);
+extern void sub_0808F2B0(Entity*);
+extern u32 sub_08003FC4(Entity*, u32);
+void sub_0808F14C(Entity*);
+extern void PlaySFX(u32);
+extern void sub_0806FCF4(Entity*, u32, u32, u32);
+extern void sub_0808F244(Entity*);
+extern void sub_0805EC9C(Entity*, u32, u32, u32);
+
+extern void (*const gUnk_08121E5C[])(Entity*);
+extern void (*const gUnk_08121E88[])(Entity*);
+extern void (*const gUnk_08121E98[])(Entity*);
+
+
+void Object49(Entity* this) {
+ gUnk_08121E5C[this->entityType.form](this);
+}
+
+void sub_0808F0B8(Entity* this) {
+ gUnk_08121E88[this->action](this);
+}
+
+void sub_0808F0D0(Entity* this) {
+ u32 offsetX;
+ u32 offsetY;
+ Entity* ent;
+ u32 uVar3;
+
+ ent = CreateObjectWithParent(this, 0x49, 2, 0);
+ this->attachedEntity = ent;
+ if (ent == NULL) {
+ DeleteThisEntity();
+ }
+ this->action = 1;
+ this->height.HALF.HI = -0xc0;
+ offsetX = Random() % 64;
+ if ((Random() & 1) != 0) {
+ offsetX = -offsetX;
+ }
+ this->x.HALF.HI = this->parent->x.HALF.HI + offsetX;
+ offsetY = Random() % 32;
+ if ((Random() & 1) != 0) {
+ offsetY = -offsetY;
+ }
+ this->y.HALF.HI = this->parent->y.HALF.HI + offsetY;
+ *(u32*)&this->field_0x74 = 0x240;
+ *(u32*)&this->field_0x78 = 0x140;
+ InitializeAnimation(this, 3);
+ sub_0808F14C(this);
+}
+
+void sub_0808F14C(Entity* this) {
+ sub_0808F2B0(this);
+ if (sub_08003FC4(this, 0x2000) == 0) {
+ this->action++;
+ PlaySFX(0x84);
+ }
+}
+
+void sub_0808F170(Entity *this)
+{
+ *(u32 *)&this->field_0x74 -= 0x20;
+ *(u32 *)&this->field_0x78 += 0x20;
+ sub_0806FCF4(this, *(u32 *)&this->field_0x78, 8, 2);
+ if (*(u32 *)&this->field_0x78 > 0x1ff) {
+ this->action++;
+ }
+ sub_0808F2B0(this);
+}
+
+void sub_0808F1A4(Entity *this)
+{
+ *(u32 *)&this->field_0x78 += 0x10;
+ *(u32 *)&this->field_0x74 += 0x10;
+ sub_0806FCF4(this, *(u32 *)&this->field_0x78, 8, 2);
+ if (*(u32 *)&this->field_0x78 > 0x3ff) {
+ this->attachedEntity->action = 0xff;
+ DeleteThisEntity();
+ }
+ else {
+ sub_0808F2B0(this);
+ }
+}
+
+void sub_0808F1E0(Entity *this)
+{
+ gUnk_08121E98[this->action](this);
+}
+
+void sub_0808F1F8(Entity *this)
+{
+ u8 bVar1;
+
+ this->spriteRendering.b0 = 3;
+ this->action++;
+ this->spriteRendering.b3 = this->parent->spriteRendering.b3;
+ this->spriteOrientation.flipY = this->parent->spriteOrientation.flipY;
+ this->spritePriority.b0 = 7;
+ InitializeAnimation(this, 1);
+ sub_0808F244(this);
+}
+
+void sub_0808F244(Entity *this)
+{
+
+ this->spriteSettings.b.draw = this->parent->spriteSettings.b.draw;
+ this->y.HALF.HI = this->parent->y.HALF.HI + 3;
+ this->x.HALF.HI = (*(s8*)&this->attachedEntity->spriteOffsetX + this->attachedEntity->x.HALF.HI);
+ this->height.WORD = 0;
+ *(u32 *)&this->field_0x74 = 0x80 - this->parent->height.HALF.HI;
+ *(u32 *)&this->field_0x78 = 0x100 - this->parent->height.HALF.HI;
+ *(u32 *)&this->field_0x70.WORD = *((u8 *)&this->parent->field_0x7c + 3);
+ sub_0808F2B0(this);
+ if ((this->parent->field_0x6d & 2) != 0) {
+ DeleteThisEntity();
+ }
+}
+
+void sub_0808F2B0(Entity *this)
+{
+ sub_0805EC9C(this, *(u32 *)&this->field_0x74, *(u32 *)&this->field_0x78, this->field_0x70.WORD);
+}
+
+void sub_0808F2C0(Entity *this)
+{
+ if (this->action == 0) {
+ this->action++;
+ this->spriteRendering.b3 = this->parent->spriteRendering.b3;
+ this->spriteOrientation.flipY = this->parent->spriteOrientation.flipY;
+ this->spriteSettings.b.draw = 1;
+ this->spritePriority.b0 = 7;
+ this->height.WORD = 0;
+
+ this->y.HALF.HI = this->parent->y.HALF.HI + 3;
+ this->x.HALF.HI = this->parent->x.HALF.HI;
+ InitializeAnimation(this,3);
+ }
+ if (this->parent->height.HALF.HI == 0) {
+ *(u32 *)&this->field_0x74 = *(u32 *)&this->parent->field_0x74;
+ *(u32 *)&this->field_0x78 = *(u32 *)&this->parent->field_0x78;
+ }
+ else {
+ *(u32 *)&this->field_0x74 = 0x200 - this->parent->height.HALF.HI;
+ *(u32 *)&this->field_0x78 = this->parent->height.HALF.HI * -2 + 0x300;
+ }
+ *(u32 *)&this->field_0x70 = 0;
+ sub_0808F2B0(this);
+ sub_0806FCF4(this,*(u32 *)&this->field_0x78,8,2);
+ if (this->action == 0xff) {
+ DeleteThisEntity();
+ }
+} \ No newline at end of file
diff --git a/src/object/object86.c b/src/object/object86.c
new file mode 100644
index 00000000..979ab47a
--- /dev/null
+++ b/src/object/object86.c
@@ -0,0 +1,81 @@
+#include "global.h"
+#include "entity.h"
+#include "link.h"
+#include "flags.h"
+
+extern u32 sub_080041A0(Entity*, Entity*, u32, u32);
+void sub_08099ECC(Entity*);
+extern void sub_0805E4E0(Entity*, u32);
+extern void sub_0805B390(u32);
+extern void CopyPosition(Entity*, Entity*);
+
+extern void (*const gUnk_081237F8[])(Entity*);
+
+void Object86(Entity* this) {
+ gUnk_081237F8[this->action](this);
+}
+
+void sub_08099DD0(Entity* this) {
+ this->collisionLayer = 1;
+ this->spriteRendering.b3 = 3;
+ this->spritePriority.b0 = 7;
+ this->previousActionFlag = 0;
+ if (GetInventoryValue(0x46)) {
+ this->action = 4;
+ this->frameIndex = 0;
+ } else {
+ this->action = 1;
+ InitializeAnimation(this, 0);
+ }
+}
+
+void sub_08099E10(Entity* this) {
+ if (CheckLocalFlag(0x74)) {
+ GetNextFrame(this);
+ if ((this->frames.all == 1) && (this->previousActionFlag == 0)) {
+ this->frames.all = 0;
+ sub_08099ECC(this);
+ }
+ if (this->frames.b.f3) {
+ this->action = 2;
+ InitializeAnimation(this, 1);
+ }
+ }
+}
+
+void sub_08099E58(Entity *this)
+{
+ GetNextFrame(this);
+ if (this->frames.b.f3) {
+ this->frames.b.f3 = 0;
+ this->actionDelay++;
+ if (this->actionDelay == 3) {
+ this->action = 3;
+ this->frameIndex = 4;
+ }
+ }
+}
+
+void sub_08099E8C(Entity *this)
+{
+ if (sub_080041A0(this, &gLinkEntity, 0xc, 0xc)) {
+ if (this->previousActionFlag == 0) {
+ sub_08099ECC(this);
+ sub_0805E4E0(this, 0x1e);
+ }
+ if (CheckLocalFlag(0x75)) {
+ sub_0805B390(0x7);
+ }
+ }
+}
+
+void nullsub_534(Entity* this) {}
+
+void sub_08099ECC(Entity *this)
+{
+ this->previousActionFlag = 1;
+ CopyPosition(this, &gLinkEntity);
+ gLinkState.linkAction = 3;
+ gLinkState.filler12[4] = 0;
+ gLinkState.flags.all |= 0x8000;
+}
diff --git a/src/object/object9E.c b/src/object/object9E.c
new file mode 100644
index 00000000..4c770e82
--- /dev/null
+++ b/src/object/object9E.c
@@ -0,0 +1,45 @@
+#include "global.h"
+#include "entity.h"
+#include "room.h"
+
+extern BoundingBox gUnk_080FD168;
+
+extern void SetTile(u32, u32, u32);
+extern void CopyPosition(Entity*, Entity*);
+
+void Object9E(Entity *this)
+{
+ Entity *ent;
+ u32 tilePos;
+ u8 *layer;
+
+ if (this->action == 0) {
+ this->action = 1;
+ this->spritePriority.b0 = 6;
+ if ((this->entityType).form == 0) {
+ this->flags = this->flags | 0x80;
+ this->frameIndex = 1;
+ layer = &this->collisionLayer;
+ *layer = 1;
+ this->field_0x3c = 7;
+ this->field_0x40 = 0x48;
+ this->damageType = 0x7a;
+ this->flags2 = 1;
+ this->boundingBox = &gUnk_080FD168;
+ tilePos = COORD_TO_TILE(this);
+ SetTile(0x4066, tilePos - 1, *layer);
+ SetTile(0x4065, tilePos, *layer);
+ UpdateSpriteForCollisionLayer(this);
+ ent = CreateObject(0x9e,1,0);
+ if (ent != NULL) {
+ this->attachedEntity = ent;
+ CopyPosition(this, ent);
+ }
+ }
+ else {
+ this->frameIndex = 0;
+ this->collisionLayer = 2;
+ UpdateSpriteForCollisionLayer(this);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/object/objectA8.c b/src/object/objectA8.c
new file mode 100644
index 00000000..b68a141a
--- /dev/null
+++ b/src/object/objectA8.c
@@ -0,0 +1,36 @@
+#include "global.h"
+#include "entity.h"
+
+extern void CreateItemEntity(u32, u32, u32);
+extern void DeleteThisEntity();
+extern void sub_08080CB4(Entity*);
+
+extern void (*gUnk_08124824[])(Entity*);
+
+extern Entity gLinkEntity;
+
+void ObjectA8(Entity *this)
+{
+ if ((this->bitfield & 0x80) != 0) {
+ switch(this->bitfield & 0x7f) {
+ case 0:
+ case 1:
+ case 4:
+ case 5:
+ case 6:
+ case 8:
+ case 9:
+ case 10:
+ case 0xb:
+ case 0xc:
+ case 0x1e:
+ case 0x1f:
+ this->action = 5;
+ this->attachedEntity = &gLinkEntity;
+ CreateItemEntity((this->entityType).form, 0, 0);
+ DeleteThisEntity();
+ }
+ }
+ gUnk_08124824[this->action](this);
+ sub_08080CB4(this);
+}
diff --git a/src/object/railtrack.c b/src/object/railtrack.c
new file mode 100644
index 00000000..95c418f4
--- /dev/null
+++ b/src/object/railtrack.c
@@ -0,0 +1,148 @@
+#include "global.h"
+#include "entity.h"
+#include "room.h"
+#include "flags.h"
+
+extern u32* GetLayerByIndex(u32);
+extern void sub_08085394(Entity*);
+extern void sub_0808543C(Entity*);
+extern void sub_08004488(u32);
+extern u32 sub_080854A8(Entity*);
+extern void SetTile(u32, u32, u32);
+
+extern void (*const gUnk_081205D0[])(Entity*);
+
+extern u16 gUnk_081205E0[];
+extern s8 gUnk_080B4488[];
+
+void Railtrack(Entity* this) {
+ gUnk_081205D0[this->action](this);
+}
+
+void sub_080851AC(Entity* this) {
+ u32 uVar1;
+
+ this->action = 1;
+ this->spriteSettings.b.draw = 1;
+ this->spritePriority.b0 = 7;
+ if ((this->entityType.parameter & 1) != 0) {
+ this->field_0x7c.HALF.LO = -1;
+ } else {
+ this->field_0x7c.HALF.LO = 1;
+ }
+ this->animationState = this->entityType.parameter & 2;
+ if ((this->entityType).form == 3) {
+ uVar1 = CheckFlags(this->field_0x86);
+ this->field_0x7a = uVar1;
+ if ((u16)(uVar1 & -1) != 0) {
+ this->animationState = (this->animationState + 2) & 3;
+ this->action = 3;
+ }
+ }
+ InitializeAnimation(this, this->animationState);
+ this->field_0x70.WORD = (u32)GetLayerByIndex(this->collisionLayer) + 4 + (COORD_TO_TILE(this) * 2);
+ sub_08085394(this);
+}
+
+void sub_08085264(Entity* this) {
+ if (CheckFlags(this->field_0x86)) {
+ this->action = 2;
+ this->field_0xf = 8;
+ if (this->entityType.form == 1) {
+ ClearFlag(this->field_0x86);
+ }
+ this->animationState = (this->animationState + *(u8*)&this->field_0x7c) & 3;
+ InitializeAnimation(this, this->animationState);
+ sub_0808543C(this);
+ sub_08004488(0x151);
+ }
+}
+
+void sub_080852B4(Entity* this) {
+ if (--this->field_0xf == 0) {
+ this->action = 3;
+ this->field_0xf = this->actionDelay;
+ this->field_0x7a = CheckFlags(this->field_0x86);
+ this->animationState = (this->animationState + *(u8*)&this->field_0x7c) & 3;
+ InitializeAnimation(this, this->animationState);
+ sub_08085394(this);
+ sub_08004488(0x151);
+ }
+}
+
+void sub_08085308(Entity* this) {
+ if (sub_080854A8(this) == 0) {
+ switch (this->entityType.form) {
+ case 0:
+ case 1:
+ break;
+ case 2:
+ if (CheckFlags(this->field_0x86) == 0) {
+ this->action = 1;
+ return;
+ }
+ break;
+ case 3:
+ if (CheckFlags(this->field_0x86) == *(u16*)&this->field_0x7a) {
+ this->field_0xf = 0xff;
+ } else {
+ this->field_0xf = 1;
+ }
+ }
+
+ if (--this->field_0xf == 0) {
+ this->action = 2;
+ this->field_0xf = 8;
+ this->animationState = (this->animationState + *(u8*)&this->field_0x7c) & 3;
+ InitializeAnimation(this, this->animationState);
+ sub_0808543C(this);
+ sub_08004488(0x151);
+ }
+ }
+}
+
+#if 0
+void sub_08085394(Entity *this)
+{
+ u32 uVar1;
+ u16 *layerData;
+ u32 iVar3;
+ u32 uVar4;
+ u8 *pbVar5;
+
+ uVar1 = gUnk_081205E0[this->animationState / 2];
+ iVar3 = this->animationState / 2;
+ layerData = *(u16 **)&this->field_0x70;
+ uVar4 = COORD_TO_TILE(this);
+ this->field_0x74 = layerData[gUnk_080B4488[iVar3]];
+ pbVar5 = &this->collisionLayer;
+ SetTile(uVar1, uVar4 - iVar3, *pbVar5);
+ this->field_0x76 = layerData[0];
+ SetTile(uVar1,uVar4, *pbVar5);
+ *(u16 *)&this->field_0x78 = layerData[iVar3];
+ SetTile(uVar1,uVar4 + iVar3, *pbVar5);
+}
+#endif
+
+NAKED
+void sub_08085394(Entity* this) {
+ asm(".include \"asm/non_matching/railtrack/sub_08085394.inc\"");
+}
+
+void sub_0808543C(Entity *this)
+{
+ s8 *cVar1;
+ u32 uVar2;
+ s8 temp;
+
+ temp = gUnk_080B4488[(this->animationState >> 1) << 1];
+ uVar2 = COORD_TO_TILE(this);
+ SetTile(this->field_0x74, uVar2 - temp, this->collisionLayer);
+ SetTile(this->field_0x76, uVar2, this->collisionLayer);
+ SetTile(this->field_0x78.HWORD, uVar2 + temp, this->collisionLayer);
+}
+
+NAKED
+u32 sub_080854A8(Entity *this) {
+ asm(".include \"asm/non_matching/railtrack/sub_080854A8.inc\"");
+} \ No newline at end of file
diff --git a/src/object/smoke.c b/src/object/smoke.c
new file mode 100644
index 00000000..b4c83115
--- /dev/null
+++ b/src/object/smoke.c
@@ -0,0 +1,60 @@
+#include "global.h"
+#include "entity.h"
+
+extern u32 Random(void);
+extern void CopyPosition(Entity*, Entity*);
+extern void sub_0806F69C(Entity*);
+extern void DeleteEntity(Entity*);
+
+extern void (*const gUnk_08121060[])(Entity*);
+extern void (*const gUnk_08121070[])(Entity*);
+
+extern s8 gUnk_08121068[];
+
+void Smoke(Entity* this) {
+ gUnk_08121060[this->entityType.form](this);
+}
+
+void sub_0808A40C(Entity *this)
+{
+ Entity *ent;
+
+ if (this->action == 0) {
+ this->action = 1;
+ this->actionDelay = 0x28;
+ }
+ if (--this->actionDelay == 0) {
+ this->actionDelay = 0x40 - (Random() & 0x1f);
+ ent = CreateObject(0x2d, 1, 0);
+ if (ent != NULL) {
+ CopyPosition(this,ent);
+ ent->x.HALF.HI += gUnk_08121068[(Random() & 7)];
+ }
+ }
+}
+
+void sub_0808A46C(Entity *this)
+{
+ gUnk_08121070[this->action](this);
+}
+
+void sub_0808A484(Entity *this)
+{
+ this->action = 1;
+ this->spriteSettings.b.draw = TRUE;
+ this->nonPlanarMovement = 0x40;
+ this->direction = 6;
+ this->spriteRendering.b3 = 1;
+ this->spritePriority.b0 = 0;
+ this->spriteOrientation.flipY = 1;
+ InitializeAnimation(this, 0x28);
+}
+
+void sub_0808A4D0(Entity *this)
+{
+ GetNextFrame(this);
+ sub_0806F69C(this);
+ if (this->frames.b.f3) {
+ DeleteEntity(this);
+ }
+} \ No newline at end of file
diff --git a/src/object/swordsmanNewsletter.c b/src/object/swordsmanNewsletter.c
new file mode 100644
index 00000000..414ac180
--- /dev/null
+++ b/src/object/swordsmanNewsletter.c
@@ -0,0 +1,31 @@
+#include "global.h"
+#include "entity.h"
+#include "textbox.h"
+
+extern void sub_080787B4(Entity*);
+
+extern void (*const gUnk_081228B0[])(Entity*);
+
+extern BoundingBox gUnk_081228A8;
+extern u16 gUnk_081228B8[];
+
+void SwordsmanNewsletter(Entity* this) {
+ gUnk_081228B0[this->action](this);
+}
+
+void sub_080933D8(Entity *this)
+{
+ this->action = 1;
+ this->frameIndex = this->entityType.form;
+ UpdateSpriteForCollisionLayer(this);
+ this->boundingBox = &gUnk_081228A8;
+ sub_080787B4(this);
+}
+
+void sub_080933FC(Entity *this)
+{
+ if (this->interactType != 0) {
+ this->interactType = 0;
+ TextboxNoOverlap(gUnk_081228B8[this->entityType.form], this);
+ }
+} \ No newline at end of file
diff --git a/src/object/thoughtBubble.c b/src/object/thoughtBubble.c
new file mode 100644
index 00000000..73316eca
--- /dev/null
+++ b/src/object/thoughtBubble.c
@@ -0,0 +1,43 @@
+#include "global.h"
+#include "entity.h"
+
+extern void InitializeAnimation(Entity*, u32);
+extern void PlaySFX(u32);
+extern void DeleteThisEntity();
+extern void GetNextFrame(Entity*);
+
+extern void (*const ThoughtBubble_Behaviors[])(Entity*);
+
+extern u16 ThoughtBubble_SFX[];
+
+void ThoughtBubble(Entity* this)
+{
+ ThoughtBubble_Behaviors[this->action](this);
+}
+
+void ThoughtBubble_Init(Entity *this)
+{
+ this->action = 1;
+ this->spriteSettings.b.draw = 1;
+ if (this->actionDelay == 0) {
+ this->actionDelay = 0x2d;
+ }
+ this->spriteOrientation.flipY = 1;
+ InitializeAnimation(this, this->entityType.parameter);
+ PlaySFX(ThoughtBubble_SFX[this->entityType.parameter]);
+}
+
+void ThoughtBubble_Update(Entity *this)
+{
+ if (this->parent != NULL) {
+ this->x.HALF.HI = this->parent->x.HALF.HI;
+ this->y.HALF.HI = this->parent->y.HALF.HI;
+ this->height.HALF.HI = this->parent->height.HALF.HI;
+ }
+ if ((this->entityType).parameter != 2) {
+ if (--this->actionDelay == 0) {
+ DeleteThisEntity();
+ }
+ }
+ GetNextFrame(this);
+}
diff --git a/src/object/treeHidingPortal.c b/src/object/treeHidingPortal.c
new file mode 100644
index 00000000..8ea54861
--- /dev/null
+++ b/src/object/treeHidingPortal.c
@@ -0,0 +1,88 @@
+#include "global.h"
+#include "entity.h"
+#include "flags.h"
+#include "link.h"
+#include "room.h"
+
+extern void sub_0809E96C(Entity*);
+extern u32 sub_0800419C(Entity*, Entity*, u32, u32);
+extern void sub_080A2B80(Entity*);
+extern u32 sub_0809E9A0(void);
+extern void sub_08078A90(u32);
+extern void sub_0809E918(Entity*);
+extern void PlaySFX(u32);
+extern void CreateMinishEntrance(u32 tile);
+
+extern void (*const gUnk_08124354[])(Entity*);
+
+extern u32 gUnk_030010A0;
+extern s16 gUnk_08124364[];
+
+void TreeHidingPortal(Entity* this) {
+ gUnk_08124354[this->action](this);
+}
+
+void sub_0809E83C(Entity* this) {
+ if (CheckFlags(this->field_0x86)) {
+ sub_0809E96C(this);
+ DeleteThisEntity();
+ }
+ this->action = 1;
+ this->collisionLayer = 2;
+ UpdateSpriteForCollisionLayer(this);
+}
+
+void sub_0809E86C(Entity* this) {
+
+ if (sub_0800419C(this, &gLinkEntity, 0x30, 0x30)) {
+ if (CheckGlobalFlag(0x14)) {
+ if (((gUnk_030010A0 & 3) == 0)) {
+ sub_080A2B80(this);
+ }
+ }
+ }
+ if (sub_0809E9A0() == 0x54) {
+ this->action = 2;
+ this->actionDelay = 0xf;
+ sub_08078A90(1);
+ }
+}
+
+void sub_0809E8BC(Entity* this) {
+ if (--this->actionDelay == 0) {
+ this->action = 3;
+ this->actionDelay = 0x3c;
+ this->spriteSettings.b.draw = 0;
+ sub_0809E96C(this);
+ sub_0809E918(this);
+ }
+}
+
+void sub_0809E8EC(Entity* this) {
+ if (--this->actionDelay == 0) {
+ SetFlag(this->field_0x86);
+ sub_08078A90(0);
+ PlaySFX(0x73);
+ DeleteThisEntity();
+ }
+}
+
+void sub_0809E918(Entity* this) {
+ Entity* fx;
+ s16* i = gUnk_08124364;
+ while (*i != -1000) {
+ fx = CreateFx(this, 3, 0);
+ if (fx != NULL) {
+ fx->x.HALF.HI += i[0];
+ fx->y.HALF.HI += i[1];
+ fx->collisionLayer = 2;
+ UpdateSpriteForCollisionLayer(fx);
+ }
+ i += sizeof(s16);
+ }
+}
+
+void sub_0809E96C(Entity *this)
+{
+ CreateMinishEntrance(COORD_TO_TILE_OFFSET(this, 0x20, 0x8));
+} \ No newline at end of file
diff --git a/src/object/well.c b/src/object/well.c
new file mode 100644
index 00000000..9efcd750
--- /dev/null
+++ b/src/object/well.c
@@ -0,0 +1,36 @@
+#include "global.h"
+#include "entity.h"
+#include "room.h"
+#include "link.h"
+
+void SetTile(u32 tileIndex, s32 tilePosition, s32 layerIndex);
+s32 GetTileType(s32 tilePosition, s32 layerIndex);
+void sub_08078B48();
+void DeleteThisEntity();
+
+extern void (*gUnk_08124C08[])(Entity*);
+
+void Well(Entity* ent) {
+ gUnk_08124C08[ent->action](ent);
+}
+
+void sub_080A0EB0(Entity* ent) {
+ u32 tilePos;
+
+ ent->action = 1;
+ tilePos = COORD_TO_TILE(ent);
+ ent->field_0x80 = tilePos;
+ SetTile(16509, ent->field_0x80, 1);
+}
+
+void sub_080A0EF0(Entity* ent) {
+ s32 tileIndex;
+
+ tileIndex = GetTileType(ent->field_0x80, 1);
+ if (tileIndex != 0x407D) {
+ sub_08078B48();
+ gLinkEntity.x.WORD = ent->x.WORD;
+ gLinkEntity.y.HALF.HI = ent->y.HALF.HI + 4;
+ DeleteThisEntity();
+ }
+}
diff --git a/src/object/windTribeFlag.c b/src/object/windTribeFlag.c
new file mode 100644
index 00000000..f9c82da8
--- /dev/null
+++ b/src/object/windTribeFlag.c
@@ -0,0 +1,25 @@
+#include "global.h"
+#include "entity.h"
+#include "functions.h"
+
+void WindTribeFlag(Entity *this)
+{
+ if (this->action == 0) {
+ this->action++;
+ this->collisionLayer = 2;
+ if ((this->entityType).form == 0) {
+ this->spriteSettings.b.flipX = 0;
+ }
+ else {
+ this->spriteSettings.b.flipX = 1;
+ }
+ UpdateSpriteForCollisionLayer(this);
+ InitializeAnimation(this,0);
+ }
+ else {
+ GetNextFrame(this);
+ }
+ if (this->frameDuration == 0xff) {
+ this->frameDuration = (Random() & 0xf) + 0x10;
+ }
+}
diff --git a/src/object/windcrest.c b/src/object/windcrest.c
new file mode 100644
index 00000000..231eb425
--- /dev/null
+++ b/src/object/windcrest.c
@@ -0,0 +1,41 @@
+#include "global.h"
+#include "entity.h"
+#include "functions.h"
+
+typedef struct {
+ u8 filler[64];
+ u32 windcrests;
+} struct_02002A40;
+
+extern void sub_0807DD64(Entity*);
+extern void sub_0807DDAC(Entity*, u32);
+extern void sub_0807DDE4(Entity*);
+extern void sub_08078850(Entity*, u32, u32, u8*);
+extern void PlaySFX(u32);
+extern Entity* CreateFx (Entity*, u32, u32);
+
+extern u8 gUnk_08125010;
+extern struct_02002A40 gUnk_02002A40;
+
+void Windcrest(Entity *this)
+{
+ if (this->action == 0) {
+ this->action++;
+ this->frameIndex = 0;
+ sub_0807DD64(this);
+ }
+ sub_0807DDAC(this, 0);
+ sub_0807DDE4(this);
+}
+
+void sub_080A2124(Entity *this)
+{
+ sub_08078850(this, 1, 0xe, &gUnk_08125010);
+}
+
+void Windcrest_Unlock(Entity *this)
+{
+ PlaySFX(0x72);
+ gUnk_02002A40.windcrests = gUnk_02002A40.windcrests | 1 << (this->entityType.parameter + 0x18);
+ CreateFx(this, 0x46, 0);
+}