summaryrefslogtreecommitdiff
path: root/src/subtask
diff options
context:
space:
mode:
Diffstat (limited to 'src/subtask')
-rw-r--r--src/subtask/subtaskAuxCutscene.c157
-rw-r--r--src/subtask/subtaskFastTravel.c191
-rw-r--r--src/subtask/subtaskLocalMapHint.c96
-rw-r--r--src/subtask/subtaskMapHint.c71
-rw-r--r--src/subtask/subtaskWorldEvent.c103
5 files changed, 618 insertions, 0 deletions
diff --git a/src/subtask/subtaskAuxCutscene.c b/src/subtask/subtaskAuxCutscene.c
new file mode 100644
index 00000000..f916ae62
--- /dev/null
+++ b/src/subtask/subtaskAuxCutscene.c
@@ -0,0 +1,157 @@
+/**
+ * @file subtaskAuxCutscene.c
+ *
+ * @brief Aux Cutscene Subtask
+ */
+#include "area.h"
+#include "asm.h"
+#include "common.h"
+#include "fileselect.h"
+#include "flags.h"
+#include "functions.h"
+#include "game.h"
+#include "main.h"
+#include "menu.h"
+#include "message.h"
+#include "room.h"
+#include "screen.h"
+#include "sound.h"
+#include "subtask.h"
+
+typedef void(AuxCutsceneState)(void);
+typedef void(CutsceneMainState)(void);
+
+static AuxCutsceneState AuxCutscene_Init;
+static AuxCutsceneState AuxCutscene_Main;
+static AuxCutsceneState AuxCutscene_Exit;
+
+CutsceneMainState CutsceneMain_Init;
+CutsceneMainState CutsceneMain_Update;
+CutsceneMainState CutsceneMain_Exit;
+
+typedef struct {
+ u8 area;
+ RoomID room : 8;
+ u8 _2;
+ u8 _3;
+ u16 x;
+ u16 y;
+} CutsceneData;
+static const CutsceneData sCutsceneData[];
+
+void Subtask_AuxCutscene(void) {
+ static AuxCutsceneState* const sStates[] = {
+ AuxCutscene_Init,
+ AuxCutscene_Main,
+ AuxCutscene_Exit,
+ };
+
+ sStates[gMenu.menuType]();
+}
+
+static void AuxCutscene_Init(void) {
+ const CutsceneData* p = &sCutsceneData[gUI.field_0x3];
+ gRoomControls.area = p->area;
+ gRoomControls.room = p->room;
+ LoadGfxGroups();
+ gArea.localFlagOffset = GetFlagBankOffset(gRoomControls.area);
+ SetCurrentRoomPropertyList(p->area, p->room);
+ LoadAuxiliaryRoom(p->area, p->room);
+ gRoomControls.scroll_x = gRoomControls.origin_x + p->x;
+ gRoomControls.scroll_y = gRoomControls.origin_y + p->y;
+ gMenu.field_0x0 = p->_2;
+ gMenu.field_0x3 = p->_3 & 0xf;
+ gMenu.field_0xc = (void*)p;
+ gMenu.menuType++;
+ gMenu.overlayType = 0;
+ gMenu.transitionTimer = 300;
+ AuxCutscene_Main(); // init
+}
+
+static void AuxCutscene_Main(void) {
+ static CutsceneMainState* const sStates[] = {
+ CutsceneMain_Init,
+ CutsceneMain_Update,
+ CutsceneMain_Exit,
+ };
+
+ sStates[gMenu.field_0x0]();
+ FlushSprites();
+ UpdateEntities();
+ DrawEntities();
+ CopyOAM();
+ UpdateScroll();
+ UpdateBgAnimations();
+ UpdateManagers();
+ UpdateScrollVram();
+}
+
+static const CutsceneData sCutsceneData[] = {
+ { AREA_MINISH_WOODS, 0, 0, 0, 336, 528 },
+ { AREA_HYRULE_FIELD, 1, 1, 0, 472, 312 },
+ { AREA_HYRULE_CASTLE, 2, 1, 1, 16, 16 },
+ { AREA_SANCTUARY, 2, 1, 2, 0, 0 },
+ { AREA_EZLO_CUTSCENE, 0, 1, 3, 0, 0 },
+ { AREA_HOUSE_INTERIORS_2, 16, 1, 4, 0, 0 },
+ { AREA_DARK_HYRULE_CASTLE_OUTSIDE, 0, 1, 5, 0, 40 },
+ { AREA_FORTRESS_OF_WINDS, 28, 2, 0, 0, 0 },
+ { AREA_FORTRESS_OF_WINDS, 29, 2, 1, 0, 0 },
+ { AREA_DARK_HYRULE_CASTLE, 14, 2, 2, 16, 16 },
+};
+
+static void AuxCutscene_Exit(void) {
+ u32 flag = sCutsceneData[gUI.field_0x3]._3;
+ if (flag & 0xF0) {
+ MenuFadeIn(2, flag >> 4);
+ } else {
+ gUI.nextToLoad = 3; // Subtask_FadeOut
+ SetFadeInverted(0x10);
+ MessageInitialize();
+ }
+}
+
+// end of auxCutscene?
+
+void sub_08051F78(void) {
+ u32 idx = gUI.field_0x3;
+ const CutsceneData* p = &sCutsceneData[idx];
+ sub_08051F9C(p->area, p->room, p->x, p->y);
+}
+
+void sub_08051F9C(u32 a1, u32 a2, u32 a3, u32 a4) {
+ u32 tmp = gScreen.lcd.displayControl & (DISPCNT_WIN0_ON | DISPCNT_WIN1_ON);
+ sub_08052FF4(a1, a2);
+ gRoomControls.scroll_x = gRoomControls.origin_x + a3;
+ gRoomControls.scroll_y = gRoomControls.origin_y + a4;
+ InitializeCamera();
+ gUpdateVisibleTiles = 1;
+ gUsedPalettes = 0;
+ gScreen.lcd.displayControl |= tmp;
+}
+
+void sub_08051FF0(void) {
+ sub_0804B0B0(gMenu.field_0xc[0], gMenu.field_0xc[1]);
+}
+
+void sub_08052004(void) {
+ gMenu.menuType = 2;
+}
+
+void sub_08052010(void) {
+ InitSoundPlayingInfo();
+ MessageInitialize();
+ DispReset(1);
+ MemClear(gBG1Buffer, sizeof(gBG1Buffer));
+ MemClear(gBG2Buffer, sizeof(gBG2Buffer));
+ sub_080A4D34();
+ LoadPaletteGroup(0xA);
+ SetColor(0, 0);
+ LoadGfxGroup(4);
+ MemClear((void*)0x06000000, 0x20);
+ MemClear(&gGenericMenu, sizeof(gGenericMenu));
+ gScreen.lcd.displayControl |= DISPCNT_OBJ_ON;
+ gScreen.bg1.control = BGCNT_PRIORITY(1) | BGCNT_SCREENBASE(28) | BGCNT_CHARBASE(0);
+ gScreen.bg2.control = BGCNT_PRIORITY(1) | BGCNT_SCREENBASE(29) | BGCNT_CHARBASE(1);
+ gScreen.bg1.updated = 1;
+ gScreen.bg2.updated = 1;
+}
diff --git a/src/subtask/subtaskFastTravel.c b/src/subtask/subtaskFastTravel.c
new file mode 100644
index 00000000..0f657cb7
--- /dev/null
+++ b/src/subtask/subtaskFastTravel.c
@@ -0,0 +1,191 @@
+/**
+ * @file subtaskFastTravel.c
+ * @ingroup Subtasks
+ *
+ * @brief Fast Travel Subtask
+ */
+#include "subtask.h"
+#include "common.h"
+#include "menu.h"
+#include "functions.h"
+#include "message.h"
+#include "sound.h"
+#include "save.h"
+
+extern void (*const Subtask_FastTravel_Functions[])(void);
+void sub_080A6E70(void);
+u32 sub_080A6D74(u32);
+void sub_080A6EE0(u32 param_1);
+
+extern const ScreenTransitionData gUnk_08128024[];
+
+void Subtask_FastTravel(void) {
+ FlushSprites();
+ Subtask_FastTravel_Functions[gMenu.menuType]();
+ if (gMenu.field_0x0 != 0) {
+ sub_080A6E70();
+ }
+ sub_080A6498();
+ CopyOAM();
+}
+
+void Subtask_FastTravel_0(void) {
+ sub_080A4D34();
+ sub_080A4DB8(0xd);
+ sub_080A6290();
+ gMenu.field_0x3 = sub_080A6D74(0);
+ SetMenuType(1);
+ SetFade(FADE_INSTANT, 8);
+}
+
+void Subtask_FastTravel_1(void) {
+ u32 uVar1;
+ u32 uVar2;
+
+ if (gFadeControl.active) {
+ return;
+ }
+
+ gMenu.field_0x0 = 1;
+ uVar2 = 0;
+
+ switch (gInput.newKeys) {
+ case DPAD_LEFT:
+ case DPAD_UP:
+ uVar2 = -1;
+ break;
+ case DPAD_RIGHT:
+ case DPAD_DOWN:
+ uVar2 = 1;
+ break;
+ case A_BUTTON:
+ case START_BUTTON:
+ gMenu.field_0x0 = 2;
+ SetMenuType(2);
+ MessageFromTarget(TEXT_INDEX(TEXT_WINDCRESTS, 0x04));
+ break;
+ case B_BUTTON:
+ gMenu.field_0x0 = 3;
+ SetMenuType(3);
+ break;
+ }
+
+ if (uVar2) {
+ uVar1 = sub_080A6D74(uVar2);
+ if (uVar1 != gMenu.field_0x3) {
+ gMenu.field_0x3 = uVar1;
+ SoundReq(SFX_TEXTBOX_CHOICE);
+ }
+ }
+}
+
+u32 sub_080A6D74(u32 param_1) {
+ u32 uVar1;
+ u32 uVar2;
+ u32 uVar3;
+
+ uVar3 = gSave.windcrests >> 0x18;
+ uVar2 = gMenu.field_0x3;
+ if (param_1 == 0) {
+ uVar2 = 0;
+ if ((uVar3 & 1) == 0) {
+ while (++uVar2 < 8 && ((1 << uVar2) & uVar3) == 0) {}
+ }
+ } else if (uVar3 != 0) {
+ do {
+ uVar2 = (uVar2 + param_1 + 8) & 7;
+ } while ((1 << uVar2 & uVar3) == 0);
+ }
+ return uVar2 & 7;
+}
+
+void Subtask_FastTravel_2(void) {
+ u32 tmp;
+ switch (sub_08056338()) {
+#ifdef EU
+ case 0:
+ gMenu.field_0x0 = 2;
+ break;
+ case 1:
+ gMenu.field_0x0 = 3;
+ tmp = 1;
+ break;
+ default:
+ return;
+ }
+
+ if (tmp) {
+ SetMenuType(3);
+ }
+#else
+ case 0:
+ gMenu.field_0x0 = 2;
+ tmp = 3;
+ break;
+ case 1:
+ tmp = 1;
+ break;
+ default:
+ return;
+ }
+ SetMenuType(tmp);
+#endif
+}
+
+void Subtask_FastTravel_3(void) {
+ if (gMenu.field_0x0 == 2) {
+ SetMenuType(4);
+ SetFade(FADE_IN_OUT | FADE_INSTANT, 8);
+ } else {
+ ResetPlayerAnimationAndAction();
+ sub_080042D0(&gPlayerEntity, (u32)gPlayerEntity.animIndex, gPlayerEntity.spriteIndex);
+ Subtask_Exit();
+ gPauseMenuOptions.disabled = 0;
+ SoundReq(SFX_MENU_CANCEL);
+ }
+}
+
+void Subtask_FastTravel_4(void) {
+ if (gFadeControl.active == 0) {
+ sub_080A71F4(&gUnk_08128024[gMenu.field_0x3]);
+ }
+}
+
+void sub_080A6E70(void) {
+ u32 frameIndex;
+ u32 i;
+
+ gOamCmd._4 = 0;
+ gOamCmd._6 = 0;
+ gOamCmd._8 = 0x400;
+ gGenericMenu.unk2c++;
+ sub_080A6EE0(gMenu.field_0x3);
+ if ((gGenericMenu.unk2c & 0x10) != 0) {
+ frameIndex = 0x5d;
+ } else {
+ frameIndex = 0x5e;
+ }
+
+ DrawDirect(DRAW_DIRECT_SPRITE_INDEX, frameIndex);
+ for (i = 0; i < 8; i++) {
+ if ((gSave.windcrests & (1 << (i + 0x18))) != 0) {
+ sub_080A6EE0(i);
+ DrawDirect(DRAW_DIRECT_SPRITE_INDEX, 0x5c);
+ }
+ }
+}
+
+void sub_080A6EE0(u32 param_1) {
+ u32 x;
+ u32 y;
+ RoomHeader* roomHeader;
+ const ScreenTransitionData* ptr = &gUnk_08128024[param_1];
+
+ x = (u16)ptr->playerXPos;
+ y = (u16)ptr->playerYPos;
+ roomHeader = &gAreaRoomHeaders[ptr->area][ptr->room];
+ x += roomHeader->map_x;
+ y += roomHeader->map_y;
+ gOamCmd.x = (s32)(x * DISPLAY_HEIGHT) / 0xf90 + 0x28;
+ gOamCmd.y = (s32)(y * DISPLAY_HEIGHT) / 0xf90 + 0xc;
+}
diff --git a/src/subtask/subtaskLocalMapHint.c b/src/subtask/subtaskLocalMapHint.c
new file mode 100644
index 00000000..8f9bb133
--- /dev/null
+++ b/src/subtask/subtaskLocalMapHint.c
@@ -0,0 +1,96 @@
+/**
+ * @file subtaskLocalMapHint.c
+ * @ingroup Subtasks
+ *
+ * @brief Local Map Hint Subtask
+ */
+#include "menu.h"
+#include "subtask.h"
+#include "kinstone.h"
+#include "functions.h"
+#include "screen.h"
+#include "sound.h"
+#include "common.h"
+
+void Subtask_LocalMapHint() {
+ extern void (*const gUnk_08128F1C[])(void);
+ const struct_gUnk_08128E94* ptr;
+ FlushSprites();
+ gUnk_08128F1C[gMenu.menuType]();
+ ptr = &gUnk_08128E94[gMenu.field_0x3];
+ gScreen.bg1.yOffset = -ptr->unk5;
+ gScreen.bg2.yOffset = gMenu.field_0xa - (s8)ptr->unk6;
+ CopyOAM();
+}
+
+void sub_080A6B04(void) {
+ u32 bVar1;
+ u32 uVar2;
+ u32 uVar3;
+ u32 uVar4;
+ int uVar6;
+ u32 uVar7;
+ const KinstoneWorldEvent* ptr;
+ const WorldEvent* ptr2;
+ const struct_gUnk_08128E94* ptr3;
+
+ sub_080A4D34();
+ sub_080A4DB8(6);
+ ptr = &gKinstoneWorldEvents[gFuseInfo.kinstoneId];
+ ptr2 = &gWorldEvents[ptr->worldEventId];
+ bVar1 = ptr->unk7;
+ uVar3 = ptr2->_c;
+ uVar4 = ptr2->_e;
+ uVar2 = sub_080A6A80(uVar3, uVar4)->_4;
+ gMenu.field_0x3 = uVar2;
+ gGenericMenu.unk2b = 1;
+ sub_080A67C4(uVar2);
+ sub_080A6FB4(uVar2, 2);
+ SetColor(0, 0x475f);
+ SetColor(0x5f, 0x475f);
+ MemFill16(0x5001, &gBG3Buffer, sizeof(gBG3Buffer));
+ if ((gPlayerState.flags & PL_NO_CAP) != 0) {
+ uVar7 = 101;
+ } else {
+ uVar7 = 100;
+ }
+ sub_080A698C(gRoomTransition.player_status.overworld_map_x, gRoomTransition.player_status.overworld_map_y,
+ DRAW_DIRECT_SPRITE_INDEX, uVar7 + 0x100);
+ sub_080A698C(uVar3, uVar4, DRAW_DIRECT_SPRITE_INDEX, bVar1 + 100);
+ uVar4 = sub_080A69E0(uVar3, uVar4) >> 0x10;
+ ptr3 = &gUnk_08128E94[gMenu.field_0x3];
+ gMenu.field_0xa = 0;
+ if (ptr3->unk2 != 0) {
+ uVar6 = uVar4 - 0x3c;
+ if (uVar6 > 0) {
+ if (ptr3->unk2 < uVar6) {
+ uVar6 = ptr3->unk2;
+ }
+ gMenu.field_0xa = uVar6;
+ }
+ }
+ gMenu.transitionTimer = 30;
+ SetMenuType(1);
+ SetFade(FADE_INSTANT, 8);
+}
+
+void sub_080A6C1C(void) {
+ if (!gFadeControl.active) {
+ switch (gMenu.transitionTimer) {
+ case 0:
+ sub_080A66D0();
+ switch (gInput.newKeys) {
+ case A_BUTTON:
+ case B_BUTTON:
+ case START_BUTTON:
+ Subtask_Exit();
+ break;
+ }
+ return;
+ case 1:
+ SoundReq(SFX_103);
+ break;
+ }
+ gMenu.transitionTimer--;
+ }
+}
diff --git a/src/subtask/subtaskMapHint.c b/src/subtask/subtaskMapHint.c
new file mode 100644
index 00000000..2a802f2b
--- /dev/null
+++ b/src/subtask/subtaskMapHint.c
@@ -0,0 +1,71 @@
+/**
+ * @file subtask.c
+ * @ingroup Subtasks
+ *
+ * @brief Map Hint Subtask
+ */
+#include "menu.h"
+#include "functions.h"
+#include "subtask.h"
+#include "common.h"
+#include "main.h"
+#include "sound.h"
+#include "save.h"
+#include "flags.h"
+#include "fileselect.h"
+#include "kinstone.h"
+#include "game.h"
+
+void sub_080A6438();
+
+void Subtask_MapHint(void) {
+ extern void (*const Subtask_MapHint_Functions[])(void);
+ FlushSprites();
+ Subtask_MapHint_Functions[gMenu.menuType]();
+ if ((gGenericMenu.unk2c & 0x20) != 0) {
+ sub_080A6438();
+ }
+ sub_080A6498();
+ CopyOAM();
+}
+
+void Subtask_MapHint_0(void) {
+ extern const u16 gUnk_08128F4C[];
+ u32 val;
+ sub_080A4D34();
+ sub_080A4DB8(4);
+ sub_080A6290();
+ gScreen.lcd.displayControl = gScreen.lcd.displayControl & 0xf7ff;
+ SetColor(0, gPaletteBuffer[0x51]);
+ val = gUnk_08128F4C[gUI.field_0x3];
+ gSave.field_0x20 |= val;
+ gGenericMenu.unk10.h[1] = val & gGenericMenu.unk10.h[0];
+ gGenericMenu.unk10.h[0] = 0;
+ gMenu.transitionTimer = 60;
+ SetMenuType(1);
+ SetFade(FADE_INSTANT, 8);
+}
+
+void Subtask_MapHint_1(void) {
+ if (!gFadeControl.active) {
+ gGenericMenu.unk2c++;
+ switch (gMenu.transitionTimer) {
+ case 0x1e:
+ gGenericMenu.unk10.h[0] = gGenericMenu.unk10.h[1];
+ gGenericMenu.unk2c = 0x20;
+ SoundReq(SFX_103);
+ default:
+ gMenu.transitionTimer--;
+ break;
+ case 0:
+ switch (gInput.newKeys) {
+ case A_BUTTON:
+ case B_BUTTON:
+ case START_BUTTON:
+ Subtask_Exit();
+ break;
+ }
+ break;
+ }
+ }
+}
diff --git a/src/subtask/subtaskWorldEvent.c b/src/subtask/subtaskWorldEvent.c
new file mode 100644
index 00000000..bae3e921
--- /dev/null
+++ b/src/subtask/subtaskWorldEvent.c
@@ -0,0 +1,103 @@
+/**
+ * @file subtaskWorldEvent.c
+ *
+ * @brief World Event Subtask
+ */
+#include "area.h"
+#include "asm.h"
+#include "common.h"
+#include "flags.h"
+#include "functions.h"
+#include "game.h"
+#include "kinstone.h"
+#include "main.h"
+#include "menu.h"
+#include "message.h"
+#include "room.h"
+#include "screen.h"
+#include "subtask.h"
+
+void Subtask_WorldEvent_Update(void);
+
+extern void (*const gUnk_080FE2A0[])(void);
+void Subtask_WorldEvent(void) {
+#if !(defined(DEMO_USA) || defined(DEMO_JP))
+ gUnk_080FE2A0[gMenu.menuType]();
+#endif
+}
+
+void Subtask_WorldEvent_Init(void) {
+ const WorldEvent* ptr = &gWorldEvents[gUI.field_0x3];
+ gMenu.field_0x0 = ptr->type;
+ gMenu.field_0x3 = ptr->entity_idx;
+ gMenu.field_0x4 = gUI.field_0x3;
+ gMenu.field_0xc = (u8*)ptr;
+ gMenu.menuType++;
+ gMenu.overlayType = 0;
+ gMenu.transitionTimer = 300;
+ DispReset(0);
+ sub_08054974(gUI.field_0x3, 1);
+ sub_0806F364();
+ ClearRoomFlag(0xff);
+ Subtask_WorldEvent_Update();
+}
+
+extern void (*const gWorldEventFunctions[])(void);
+
+void Subtask_WorldEvent_Update(void) {
+ gWorldEventFunctions[gMenu.field_0x0]();
+ FlushSprites();
+ UpdateEntities();
+ DrawEntities();
+ CopyOAM();
+ UpdateScroll();
+ UpdateBgAnimations();
+ UpdateScrollVram();
+}
+
+void Subtask_WorldEvent_End(void) {
+ MessageInitialize();
+ sub_0806F38C();
+ if (gKinstoneWorldEvents[gFuseInfo.kinstoneId].unk7 != 0) {
+ // Show the map hint.
+ MenuFadeIn(SUBTASK_LOCALMAPHINT, gUI.field_0x3);
+ } else {
+ gUI.nextToLoad = 3; // Subtask_FadeOut
+ SetFade(FADE_IN_OUT | FADE_BLACK_WHITE | FADE_INSTANT, 0x10);
+ }
+}
+
+void sub_08054968(void) {
+ gMenu.menuType = 2;
+}
+
+// Controls showing the world event cutscene?
+void sub_08054974(u32 worldEventId, bool32 param_2) {
+ const WorldEvent* ptr = &gWorldEvents[worldEventId];
+ SetCurrentRoomPropertyList(ptr->area, ptr->room);
+ gRoomControls.area = ptr->area;
+ gRoomControls.room = ptr->room;
+ LoadGfxGroups();
+ gArea.localFlagOffset = GetFlagBankOffset(gRoomControls.area);
+ if (param_2) {
+ LoadAuxiliaryRoom(ptr->area, ptr->room);
+ } else {
+ sub_08052FF4(ptr->area, ptr->room);
+ InitializeCamera();
+ gUpdateVisibleTiles = 1;
+ }
+ gScreen.lcd.displayControl &= 0x1fff;
+ gRoomControls.scroll_x = gRoomControls.origin_x + ptr->offsetX;
+ gRoomControls.scroll_y = gRoomControls.origin_y + ptr->offsetY;
+ if (ptr->area == AREA_HYRULE_TOWN) {
+ TryLoadPrologueHyruleTown();
+ }
+ sub_08018710(gUI.field_0x3);
+}
+
+void sub_08054A14(s32 worldEventId) {
+ const WorldEvent* ptr = &gWorldEvents[worldEventId];
+ if (ptr->bank < 0xe) {
+ SetLocalFlagByBank(gLocalFlagBanks[ptr->bank], ptr->flag);
+ }
+}