summaryrefslogtreecommitdiff
path: root/src/beanstalkSubtask.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/beanstalkSubtask.c')
-rw-r--r--src/beanstalkSubtask.c603
1 files changed, 603 insertions, 0 deletions
diff --git a/src/beanstalkSubtask.c b/src/beanstalkSubtask.c
new file mode 100644
index 00000000..179c20d9
--- /dev/null
+++ b/src/beanstalkSubtask.c
@@ -0,0 +1,603 @@
+#include "beanstalkSubtask.h"
+#include "collision.h"
+#include "common.h"
+#include "fade.h"
+#include "functions.h"
+#include "game.h"
+#include "global.h"
+#include "item.h"
+#include "main.h"
+#include "manager.h"
+#include "menu.h"
+#include "object.h"
+#include "screen.h"
+#include "structures.h"
+
+extern void UpdateIsDiggingCave(void);
+extern void sub_0807C898(void);
+extern void sub_0805BB74(s32);
+extern void LoadRoomGfx(void);
+extern void sub_0807BFD0(void);
+extern void sub_0807C4F8(void);
+
+extern void gMapData;
+extern u8 gUpdateVisibleTiles;
+extern u16 gMapDataTopSpecial[];
+extern u16 gMapDataBottomSpecial[];
+
+extern const u8 gGlobalGfxAndPalettes[];
+extern const u8 gUnk_081091E4[];
+
+extern void (*const gUnk_080B4458[])(void);
+extern const u16 gUnk_080B44A0[];
+extern const u16 gUnk_080B4410[];
+extern const s16 gUnk_080B4488[];
+extern const s16 gUnk_080B44A8[];
+extern const u16 gUnk_080B44D0[];
+extern const u16* gUnk_080B4550[];
+extern const u16 gUnk_080B77C0[];
+extern BgAnimationFrame* gUnk_080B7278[];
+
+bool32 sub_0801A4F8(void);
+bool32 sub_0801AA58(Entity*, u32, u32);
+void sub_0801AB08(u16*, LayerStruct*);
+void LoadBgAnimationGfx(BgAnimationGfx*);
+u32 GetBgAnimationTimer(s32*);
+void ClearBgAnimations(void);
+
+void sub_0801967C(void) {
+ gUnk_080B4458[gMenu.overlayType]();
+}
+
+void sub_08019698(void) {
+ Entity* object;
+ const u16* ptr;
+ ptr = &gUnk_080B4410[gUI.field_0x3 * 7];
+ SetLocalFlagByBank(0x100, ptr[2]);
+ LoadAuxiliaryRoom(ptr[0], ptr[1]);
+ gRoomControls.scroll_x += ptr[3];
+ gRoomControls.scroll_y += ptr[4];
+ gUpdateVisibleTiles = 1;
+ UpdateScrollVram();
+ gScreen.lcd.displayControl &= 0xfeff;
+ object = CreateObject(BEANSTALK, 0, 0);
+ if (object != NULL) {
+ object->x.HALF.HI = gRoomControls.scroll_x + ptr[5];
+ object->y.HALF.HI = gRoomControls.scroll_y + ptr[6];
+ }
+ LoadGfxGroup(0x11);
+ FlushSprites();
+ DrawEntities();
+ CopyOAM();
+ SetFade(4, 8);
+ gUnk_02018EB0.unk_0++;
+}
+
+void sub_08019740(void) {
+ if (gFadeControl.active == 0) {
+ gUnk_02018EB0.unk_0++;
+ gUnk_02018EB0.unk_4 = 0x186;
+ }
+}
+
+void sub_08019764(void) {
+ FlushSprites();
+ UpdateEntities();
+ DrawEntities();
+ CopyOAM();
+ if ((--gUnk_02018EB0.unk_4 == 0) || ((gInput.newKeys & 10) != 0)) {
+ gUnk_02018EB0.unk_0++;
+ }
+}
+
+void sub_080197A0(void) {
+ MenuFadeIn(2, 0xb);
+}
+
+NONMATCH("asm/non_matching/beanstalkSubtask/SetBGDefaults.inc", void SetBGDefaults(void)) {
+ u16* ptr;
+ BgSettings* bg;
+
+ gMapBottom.bgControlPtr = (u16*)&gScreen.bg2;
+ gScreen.bg2.control = gUnk_080B77C0[0];
+ gMapTop.bgControlPtr = (u16*)&gScreen.bg1;
+ gScreen.bg1.control = gUnk_080B77C0[1];
+}
+END_NONMATCH
+
+NONMATCH("asm/non_matching/beanstalkSubtask/sub_080197D4.inc", void sub_080197D4(u32* param_1)) {
+ u32 uVar1;
+ u8* src;
+ void* dest;
+
+ do {
+ dest = (void*)param_1[1];
+ if (dest != NULL) {
+ src = &gMapData + (*param_1 & 0x7fffffff);
+ if ((param_1[2] & 0x80000000) != 0) {
+ if ((u32)dest >> 0x18 == 6) {
+ LZ77UnCompVram(src, dest);
+ } else {
+ LZ77UnCompWram(src, dest);
+ }
+ } else {
+ MemCopy(src, dest, param_1[2]);
+ }
+ } else {
+ LoadPaletteGroup((u32) * (u16*)param_1);
+ sub_080533CC();
+ }
+ uVar1 = *param_1;
+ param_1 += 3;
+ } while ((uVar1 & 0x80000000) != 0);
+}
+END_NONMATCH
+
+// Has ifdefs for other variants
+ASM_FUNC("asm/non_matching/beanstalkSubtask/UpdatePlayerCollision.inc", void UpdatePlayerCollision())
+
+NONMATCH("asm/non_matching/beanstalkSubtask/sub_0801A2B0.inc",
+ bool32 sub_0801A2B0(LayerStruct* layer, u32 position, u32 collisionType)) {
+ u16 uVar1;
+ u32 uVar2;
+ bool32 bVar3;
+ u32 pos;
+
+ uVar1 = gUnk_080B4488[gPlayerEntity.animationState >> 1];
+ if ((((gPlayerState.field_0x35 | gPlayerState.field_0xd) & 0x80) == 0) && ((gPlayerEntity.frame & 1) != 0)) {
+ switch ((s32)sub_080B1B54(GetTileType(position + uVar1, gPlayerEntity.collisionLayer))) {
+ case 0x52:
+ break;
+ case 0x26:
+ case 0x27:
+ return FALSE;
+ case 0x29:
+ return FALSE;
+ case 0x74:
+ return FALSE;
+ default:
+ if ((layer->collisionData[(position + uVar1)] != 0x28) &&
+ (!IsTileCollision(
+ layer->collisionData,
+ (s32)((((position + uVar1) & 0x3f) * 0x10 + (u32)gRoomControls.origin_x) * 0x10000) >> 0x10,
+ (s32)((((position + uVar1) >> 6) * 0x10 + (u32)gRoomControls.origin_y) * 0x10000) >> 0x10,
+ collisionType))) {
+ return TRUE;
+ }
+ break;
+ }
+ }
+ return FALSE;
+}
+END_NONMATCH
+
+NONMATCH("asm/non_matching/beanstalkSubtask/sub_0801A370.inc", bool32 sub_0801A370(LayerStruct* layer, u32 position)) {
+ LayerStruct* topLayer;
+ u32 tileType;
+ u32 pos;
+ s32 offset;
+
+ if ((gPlayerEntity.animationState & 2) == 0) {
+ return FALSE;
+ }
+ if (!sub_0801A4F8()) {
+ return FALSE;
+ }
+ topLayer = GetLayerByIndex(2);
+ offset = gUnk_080B4488[gPlayerEntity.animationState >> 1];
+ pos = position + offset;
+ tileType = GetTileType(pos, gPlayerEntity.collisionLayer);
+ switch (tileType) {
+ case 0x402b:
+ pos += offset;
+ break;
+ case 0x402c ... 0x402f:
+ return TRUE;
+ }
+ if (topLayer->collisionData[pos - 0x80] == 0x46) {
+ return FALSE;
+ }
+ switch ((u16)sub_080B1B54(GetTileType(pos, gPlayerEntity.collisionLayer))) {
+ case 0x52:
+ return FALSE;
+ case 0x26:
+ case 0x27:
+ return FALSE;
+ case 0x29:
+ return FALSE;
+ case 0x74:
+ return FALSE;
+ }
+ switch (layer->collisionData[pos]) {
+ case 0:
+ return TRUE;
+ case 5:
+ case 0x45:
+ if (offset == 1) {
+ return TRUE;
+ }
+ break;
+ case 0xa:
+ case 0x44:
+ if (offset == -1) {
+ return TRUE;
+ }
+ break;
+ }
+ return FALSE;
+}
+END_NONMATCH
+
+bool32 sub_0801A458(LayerStruct* layer, u32 position, u32 collisionType) {
+ u32 tileType;
+ u32 pos;
+ s32 offset = gUnk_080B4488[gPlayerEntity.animationState >> 1];
+ if (sub_0801A4F8()) {
+ pos = position + offset;
+ tileType = GetTileType(pos, gPlayerEntity.collisionLayer);
+ switch (sub_080B1B54(tileType)) {
+ case 0x52:
+ case 0x26:
+ case 0x27:
+ case 0x29:
+ case 0x74:
+ return FALSE;
+ default:
+ if (((layer->collisionData[pos] != 0x28) &&
+ (!IsTileCollision(layer->collisionData, (pos & 0x3f) * 0x10 + gRoomControls.origin_x,
+ (pos >> 6) * 0x10 + gRoomControls.origin_y, collisionType))) &&
+ (0xe < (u32)layer->collisionData[pos] - 1)) {
+ return TRUE;
+ }
+ break;
+ }
+ }
+ return FALSE;
+}
+
+NONMATCH("asm/non_matching/beanstalkSubtask/sub_0801A4F8.inc", bool32 sub_0801A4F8(void)) {
+ u32 uVar1;
+ u32 uVar3;
+
+ if ((gPlayerState.flags & PL_MINISH) != 0) {
+ if (GetInventoryValue(ITEM_POWER_BRACELETS) != 1) {
+ return FALSE;
+ }
+ if ((gPlayerState.field_0xd & 0x80) != 0) {
+ return FALSE;
+ }
+ if (gPlayerState.field_0xd != gPlayerEntity.direction) {
+ return FALSE;
+ }
+ if ((gPlayerEntity.collisions & gUnk_080B44A0[(((gPlayerEntity.direction + 4) & 0x18) >> 2)]) == 0) {
+ return FALSE;
+ }
+ } else {
+ if (((gPlayerState.field_0x35 | gPlayerState.field_0xd) & 0x80) != 0) {
+ return FALSE;
+ }
+ if ((gPlayerEntity.frame & 1) == 0) {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+END_NONMATCH
+
+ASM_FUNC("asm/non_matching/beanstalkSubtask/sub_0801A570.inc", void sub_0801A570())
+
+NONMATCH("asm/non_matching/beanstalkSubtask/sub_0801A8D0.inc", u32 sub_0801A8D0(Entity* this, u32 param_2)) {
+ u16* mapData;
+ u32 tile;
+ u32 position;
+
+ if (this != NULL) {
+ mapData = GetLayerByIndex(this->collisionLayer)->mapData;
+ if (param_2 == 0) {
+ position = COORD_TO_TILE_OFFSET(this, 0, 8);
+ tile = mapData[position];
+ if (tile == 0x4055) {
+ return position - 1;
+ }
+ if (tile == 0x4056) {
+ return position;
+ }
+ } else {
+ position = COORD_TO_TILE_OFFSET(this, 8, 0);
+ tile = mapData[position];
+ if (tile == 0x4057) {
+ return position - 0x40;
+ }
+ if (tile == 0x4058) {
+ return position;
+ }
+ }
+ }
+ return 0xffff;
+}
+END_NONMATCH
+
+bool32 sub_0801A980(void) {
+ u16 tileType;
+ const s16* ptr;
+ GetLayerByIndex(gPlayerEntity.collisionLayer);
+ ptr = &gUnk_080B44A8[gPlayerEntity.animationState & 6];
+ tileType = GetTileType(COORD_TO_TILE_OFFSET(&gPlayerEntity, -ptr[0], -ptr[1]), gPlayerEntity.collisionLayer);
+ if (tileType < 0x4000) {
+ sub_080B1B54(tileType);
+ }
+ return FALSE;
+}
+
+NONMATCH("asm/non_matching/beanstalkSubtask/sub_0801A9F0.inc",
+ bool32 sub_0801A9F0(u32 param_1, u32 param_2, u32 param_3)) {
+
+ switch (param_2) {
+ case 0x361:
+ if (param_1 == 0) {
+ goto result;
+ } else {
+ return FALSE;
+ }
+ break;
+ case 0x362:
+ if (param_1 == 0x10) {
+ goto result;
+ } else {
+ return FALSE;
+ }
+ break;
+ case 0x363:
+ if (param_1 == 0x18) {
+ goto result;
+ } else {
+ return FALSE;
+ }
+ break;
+ case 0x364:
+ if (param_1 == 8) {
+ goto result;
+ } else {
+ return FALSE;
+ }
+ break;
+ case 0x360:
+ result:
+ return sub_0801AA58(&gPlayerEntity, param_3, param_1);
+ default:
+ return FALSE;
+ }
+}
+END_NONMATCH
+
+NONMATCH("asm/non_matching/beanstalkSubtask/sub_0801AA58.inc",
+ bool32 sub_0801AA58(Entity* this, u32 param_2, u32 param_3)) {
+ LayerStruct* layer;
+ Entity* object;
+
+ layer = GetLayerByIndex(this->collisionLayer);
+ if (((layer->collisionData[param_2 + gUnk_080B4488[param_3 >> 3]] == 0) ||
+ ((u8)(layer->collisionData[param_2 + gUnk_080B4488[param_3 >> 3]] - 0x20) < 0x20))) {
+
+ object = CreateObject(PUSHED_BLOCK, 0, 0);
+ if (object != NULL) {
+ object->direction = param_3;
+ object->x.HALF.HI = ((param_2 & 0x3f) * 0x10 + 8) + gRoomControls.origin_x;
+ object->y.HALF.HI = (((param_2 & 0xfc0) >> 2) + 8) + gRoomControls.origin_y;
+ object->collisionLayer = this->collisionLayer;
+ gPlayerState.pushedObject = 0xa0;
+ gPlayerState.queued_action = 5;
+ gPlayerState.flags |= 1;
+ this->x.HALF.LO = 0;
+ this->y.HALF.LO = 0;
+ this->direction = param_3;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+END_NONMATCH
+
+ASM_FUNC("asm/non_matching/beanstalkSubtask/sub_0801AB08.inc", void sub_0801AB08(u16* a, LayerStruct* layer))
+
+NONMATCH("asm/non_matching/beanstalkSubtask/sub_0801AC68.inc", u32 sub_0801AC68(u32 position, u32 data)) {
+ u32 index;
+ struct_0200B240* ptr;
+ u32 end;
+
+ ptr = gUnk_0200B240;
+ end = gRoomVars.unk_0e;
+ for (index = 0; index < end; index++) {
+ if (position == ptr[index].position) {
+ return ptr[index].data << 2;
+ }
+ }
+ return data << 2;
+}
+END_NONMATCH
+
+ASM_FUNC("asm/non_matching/beanstalkSubtask/sub_0801AC98.inc", void sub_0801AC98())
+
+void sub_0801AD6C(u16* param_1, u32 param_2) {
+ Entity* entity;
+ Manager* manager;
+ s32 tmpX1;
+ s32 tmpY1;
+ s32 tmpX2;
+ s32 tmpY2;
+
+ if (param_1[1] != 9) {
+ entity = GetEmptyEntity();
+ if (entity != NULL) {
+ entity->kind = (u8)param_1[1];
+ entity->id = (u8)param_1[2];
+ entity->type = (u8)param_1[3];
+ entity->type2 = (u8)param_1[4];
+ tmpX1 = ((u16)param_2 & 0x3f) * 0x10 + 8;
+ entity->x.HALF.HI = tmpX1 + gRoomControls.origin_x;
+ tmpY1 = (s16)((param_2 & 0xfc0) >> 2) + 8;
+ entity->y.HALF.HI = tmpY1 + gRoomControls.origin_y;
+ entity->collisionLayer = 0;
+ ResolveCollisionLayer(entity);
+ AppendEntityToList(entity, gUnk_081091E4[entity->kind]);
+ }
+ } else {
+ manager = GetEmptyManager();
+ if (manager != NULL) {
+ manager->type = (u8)param_1[1];
+ manager->subtype = (u8)param_1[2];
+ manager->unk_0a = (u8)param_1[3];
+ manager->unk_0b = (u8)param_1[4];
+ tmpX2 = ((u16)param_2 & 0x3f) * 0x10 + 8;
+ *(u16*)(&manager[1].unk_0e + 10) = tmpX2 + gRoomControls.origin_x;
+ tmpY2 = (s16)((param_2 & 0xfc0) >> 2) + 8;
+ *(u16*)(&manager[1].unk_0e + 12) = tmpY2 + gRoomControls.origin_y;
+ AppendEntityToList((Entity*)manager, gUnk_081091E4[manager->type]);
+ }
+ }
+}
+
+bool32 sub_0801AE30(void) {
+ return TRUE;
+}
+
+u32 sub_0801AE34(void) {
+ return gRoomControls.scroll_flags >> 1 & 1;
+}
+
+void sub_0801AE44(s32 param_1) {
+ void (*func)(void);
+ gRoomControls.unk_34 = 0;
+ sub_0807BFD0();
+ if (param_1 != 0) {
+ LoadRoomGfx();
+ }
+ sub_080809D4();
+ UpdateIsDiggingCave();
+ if (gRoomTransition.field_0x2c[0] != 0) {
+ sub_0807C898();
+ }
+ if (gArea.lightType != 0) {
+ MemFill16(0xf, (void*)0x600f000, 0x800);
+ sub_0805BB74(-1);
+ }
+ func = GetCurrentRoomProperty(5);
+ if (func != NULL) {
+ func();
+ }
+ if ((gUnk_03004030.isDiggingCave == 0) && (gArea.onEnter != NULL)) {
+ gArea.onEnter(gArea.transitionManager);
+ }
+ if ((gRoomControls.scroll_flags & 1) == 0) {
+ if (gMapBottom.bgControlPtr != NULL) {
+ sub_0801AB08(gMapDataBottomSpecial, &gMapBottom);
+ }
+ if (gMapTop.bgControlPtr != NULL) {
+ sub_0801AB08(gMapDataTopSpecial, &gMapTop);
+ }
+ } else {
+ sub_0807C4F8();
+ }
+ UpdateScrollVram();
+}
+
+void SetMultipleTiles(TileData* tileData, u32 basePosition, u32 layer) {
+ while (tileData->tile != -1) {
+ SetTile((u16)tileData->tile, basePosition + tileData->position, layer);
+ tileData++;
+ }
+}
+
+// Add a new entry at the end of gUnk_0200B240
+void sub_0801AF48(u32 data, u32 position, u32 layer) {
+ u32 index;
+ if ((data < 0x4000) && (gRoomTransition.field_0x2c[3] == 0)) {
+ index = gRoomVars.unk_0e;
+ if (index < 0x100) {
+ gUnk_0200B240[index].data = data;
+ gUnk_0200B240[index].position = (layer << 0xc) | position;
+ gRoomVars.unk_0e = index + 1;
+ }
+ }
+}
+
+ASM_FUNC("asm/non_matching/beanstalkSubtask/DeleteLoadedTileEntity.inc",
+ void DeleteLoadedTileEntity(u32 position, u32 layer))
+
+ASM_FUNC("asm/non_matching/beanstalkSubtask/sub_0801AFE4.inc", void sub_0801AFE4(void))
+
+void UpdateBgAnimations(void) {
+ bool32 alreadyUploadedGfx = FALSE;
+ BgAnimation* animation = gBgAnimations;
+ s32 index = 8;
+ while (index != 0) {
+ if (animation->currentFrame == NULL) {
+ return;
+ }
+ if (--animation->timer == 0) {
+ if (!alreadyUploadedGfx) {
+ if (gFadeControl.active == 0) {
+ LoadBgAnimationGfx(animation->currentFrame->gfx);
+ }
+ animation->timer = GetBgAnimationTimer(&animation->currentFrame->unk_4);
+ animation->currentFrame++;
+ if (animation->currentFrame->gfx == NULL) {
+ animation->currentFrame -= animation->currentFrame->unk_4;
+ }
+ alreadyUploadedGfx = TRUE;
+ } else {
+ animation->timer++;
+ }
+ }
+ animation++;
+ index--;
+ }
+}
+
+u32 GetBgAnimationTimer(s32* param_1) {
+ if (param_1[0] < 0) {
+ return gUnk_080B4550[*(u8*)param_1][(Random() & 7)];
+ } else {
+ return param_1[0];
+ }
+}
+
+void LoadBgAnimationGfx(BgAnimationGfx* param_1) {
+ const u8* src;
+ u32 vramOffset;
+ u32 size;
+ while (TRUE) {
+ src = &gGlobalGfxAndPalettes[param_1->gfxOffset];
+ size = param_1->gfxSize;
+ vramOffset = param_1->vramOffset;
+ if ((*(u32*)param_1 >> 0x1c & 1) != 0) {
+ LoadPalettes(src, vramOffset >> 5, size);
+ } else {
+ MemCopy(src, (void*)(vramOffset + 0x6000000), size << 5);
+ }
+ if (*(int*)param_1 >= 0) {
+ return;
+ }
+ param_1++;
+ }
+}
+
+void LoadBgAnimations(u16* param_1) {
+ BgAnimation* animation;
+ ClearBgAnimations();
+ animation = gBgAnimations;
+ while (param_1[0] != 0xffff) {
+ animation->currentFrame = gUnk_080B7278[param_1[0]];
+ animation->timer = GetBgAnimationTimer(&animation->currentFrame->unk_4);
+ ;
+ animation++;
+ param_1++;
+ }
+}
+
+void ClearBgAnimations(void) {
+ u32 index;
+ for (index = 0; index < MAX_BG_ANIMATIONS; index++) {
+ gBgAnimations[index].currentFrame = NULL;
+ }
+}