summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/slot_machine.c778
-rw-r--r--src/vs_seeker.c2
2 files changed, 779 insertions, 1 deletions
diff --git a/src/slot_machine.c b/src/slot_machine.c
new file mode 100644
index 000000000..41271b425
--- /dev/null
+++ b/src/slot_machine.c
@@ -0,0 +1,778 @@
+#include "global.h"
+#include "palette.h"
+#include "task.h"
+#include "main.h"
+#include "malloc.h"
+#include "sound.h"
+#include "coins.h"
+#include "quest_log.h"
+#include "overworld.h"
+#include "slot_machine.h"
+#include "menu.h"
+#include "random.h"
+#include "constants/songs.h"
+
+struct SlotMachineState
+{
+ MainCallback savedCallback;
+ u16 machineidx;
+ u16 field_06;
+ u16 field_08;
+ u16 slotRewardClass;
+ u8 filler_0C[2];
+ u16 bet;
+ u8 field_10;
+ u8 field_11;
+ bool32 field_14[3];
+ s16 field_20[3];
+ s16 field_26[3];
+ s16 field_2C[3];
+ s16 field_32[3];
+ u32 field_38;
+ u8 filler_3C[0x14];
+ u16 payout;
+};
+
+EWRAM_DATA struct SlotMachineState * sSlotMachineState = NULL;
+
+void sub_813F84C(struct SlotMachineState * ptr);
+void sub_813F898(void);
+void sub_813F92C(void);
+void sub_813F94C(void);
+void MainTask_SlotsGameLoop(u8 taskId);
+void MainTask_NoCoinsGameOver(u8 taskId);
+void MainTask_ShowHelp(u8 taskId);
+void MainTask_ConfirmExitGame(u8 taskId);
+void MainTask_DarnNoPayout(u8 taskId);
+void MainTask_WinHandlePayout(u8 taskId);
+void MainTask_ExitSlots(u8 taskId);
+static void SetMainTask(TaskFunc taskFunc);
+void sub_8140060(u8 taskId);
+void sub_8140148(void);
+void sub_814016C(u16 whichReel, u16 whichReel2);
+bool32 sub_81401A0(u16);
+void sub_81401F0(u16 whichReel);
+void sub_81403BC(u16 whichReel);
+void sub_81404B8(u16 whichReel);
+bool32 sub_814054C(s32, s32, s32, s32, s32);
+bool32 sub_81406E8(s32, s32, s32);
+bool32 sub_81408F4(s32, s32);
+void sub_81409B4(void);
+void sub_8140A70(void);
+u16 sub_8140A80(void);
+void sub_8140D7C(s16 *, s16 *);
+bool32 sub_814104C(void);
+void sub_8141094(void);
+void sub_8141148(u16 a0, u8 a1);
+bool32 sub_8141180(u8 a0);
+void sub_8141C30(u8, u8);
+
+extern const u8 gUnknown_8464890[][2];
+extern const u8 gUnknown_8464926[][21];
+
+void PlaySlotMachine(u16 machineIdx, MainCallback savedCallback)
+{
+ ResetTasks();
+ sSlotMachineState = Alloc(sizeof(*sSlotMachineState));
+ if (sSlotMachineState == NULL)
+ SetMainCallback2(savedCallback);
+ else
+ {
+ if (machineIdx > 5)
+ machineIdx = 0;
+ sSlotMachineState->machineidx = machineIdx;
+ sSlotMachineState->savedCallback = savedCallback;
+ sub_813F84C(sSlotMachineState);
+ SetMainCallback2(sub_813F898);
+ }
+}
+
+void sub_813F84C(struct SlotMachineState * ptr)
+{
+ s32 i;
+
+ ptr->field_06 = 0;
+ ptr->bet = 0;
+ ptr->payout = 0;
+ // for whatever reason, the loop does not use the ptr param
+ for (i = 0; i < 3; i++)
+ {
+ sSlotMachineState->field_14[i] = FALSE;
+ sSlotMachineState->field_20[i] = 0;
+ sSlotMachineState->field_26[i] = 0;
+ sSlotMachineState->field_2C[i] = 21;
+ }
+}
+
+void sub_813F898(void)
+{
+ RunTasks();
+ AnimateSprites();
+ BuildOamBuffer();
+
+ switch (gMain.state)
+ {
+ case 0:
+ if (sub_814104C())
+ {
+ SetMainCallback2(sSlotMachineState->savedCallback);
+ sub_813F92C();
+ }
+ else
+ {
+ sub_8141148(0, 0);
+ gMain.state++;
+ }
+ break;
+ case 1:
+ if (!sub_8141180(0))
+ {
+ sSlotMachineState->field_10 = CreateTask(MainTask_SlotsGameLoop, 0);
+ sSlotMachineState->field_11 = CreateTask(sub_8140060, 1);
+ SetMainCallback2(sub_813F94C);
+ }
+ break;
+ }
+}
+
+void sub_813F92C(void)
+{
+ sub_8141094();
+ if (sSlotMachineState != NULL)
+ {
+ Free(sSlotMachineState);
+ sSlotMachineState = NULL;
+ }
+}
+
+void sub_813F94C(void)
+{
+ RunTasks();
+ AnimateSprites();
+ BuildOamBuffer();
+ UpdatePaletteFade();
+}
+
+void MainTask_SlotsGameLoop(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+
+ switch (data[0])
+ {
+ case 0:
+ if (GetCoins() == 0)
+ {
+ SetMainTask(MainTask_NoCoinsGameOver);
+ }
+ else if (JOY_NEW(DPAD_DOWN))
+ {
+ sSlotMachineState->bet++;
+ TakeCoins(1);
+ PlaySE(SE_T_KAMI2);
+ sub_8141148(8, 0);
+ sub_8141148(2, 1);
+ data[0] = 1;
+ }
+ else if (JOY_NEW(R_BUTTON))
+ {
+ s32 toAdd = 3 - sSlotMachineState->bet;
+ if (GetCoins() >= toAdd)
+ {
+ sSlotMachineState->bet = 3;
+ TakeCoins(toAdd);
+ }
+ else
+ {
+ sSlotMachineState->bet += GetCoins();
+ SetCoins(0);
+ }
+ PlaySE(SE_T_KAMI2);
+ sub_8141148(8, 0);
+ sub_8141148(2, 1);
+ data[0] = 1;
+ }
+ else if (JOY_NEW(A_BUTTON) && sSlotMachineState->bet != 0)
+ {
+ data[0] = 2;
+ }
+ else if (JOY_NEW(B_BUTTON))
+ {
+ SetMainTask(MainTask_ConfirmExitGame);
+ }
+ else if (JOY_NEW(DPAD_RIGHT))
+ {
+ SetMainTask(MainTask_ShowHelp);
+ }
+ break;
+ case 1:
+ if (!sub_8141180(0) && !sub_8141180(1))
+ {
+ if (sSlotMachineState->bet == 3 || GetCoins() == 0)
+ data[0] = 2;
+ else
+ data[0] = 0;
+ }
+ break;
+ case 2:
+ sub_811539C();
+ sub_81409B4();
+ sub_8140148();
+ sSlotMachineState->field_06 = 0;
+ sub_8141148(3, 0);
+ data[0] = 3;
+ break;
+ case 3:
+ if (!sub_8141180(0))
+ {
+ if (JOY_NEW(A_BUTTON))
+ {
+ PlaySE(SE_JYUNI);
+ sub_814016C(sSlotMachineState->field_06, sSlotMachineState->field_06);
+ sub_8141C30(sSlotMachineState->field_06, 0);
+ data[0] = 4;
+ }
+ }
+ break;
+ case 4:
+ if (sub_81401A0(sSlotMachineState->field_06) == 0 && !sub_8141180(0))
+ {
+ sSlotMachineState->field_06++;
+ if (sSlotMachineState->field_06 >= 3)
+ {
+ sSlotMachineState->slotRewardClass = sub_8140A80();
+ sSlotMachineState->bet = 0;
+ sSlotMachineState->field_06 = 0;
+ if (sSlotMachineState->slotRewardClass == 0)
+ SetMainTask(MainTask_DarnNoPayout);
+ else
+ {
+ if (sSlotMachineState->slotRewardClass == 6)
+ IncrementGameStat(GAME_STAT_SLOT_JACKPOTS);
+ sub_8140A70();
+ SetMainTask(MainTask_WinHandlePayout);
+ }
+ }
+ else
+ data[0] = 3;
+ }
+ break;
+ }
+}
+
+void MainTask_NoCoinsGameOver(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+
+ switch (data[0])
+ {
+ case 0:
+ sub_8141148(9, 0);
+ data[0]++;
+ break;
+ case 1:
+ if (!sub_8141180(0))
+ data[0]++;
+ break;
+ case 2:
+ if (JOY_NEW(A_BUTTON | B_BUTTON | DPAD_ANY))
+ SetMainTask(MainTask_ExitSlots);
+ break;
+ }
+}
+
+void MainTask_ShowHelp(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+
+ switch (data[0])
+ {
+ case 0:
+ sub_8141148(14, 0);
+ data[0]++;
+ break;
+ case 1:
+ if (!sub_8141180(0))
+ data[0]++;
+ break;
+ case 2:
+ if (JOY_NEW(DPAD_LEFT))
+ {
+ sub_8141148(15, 0);
+ data[0]++;
+ }
+ break;
+ case 3:
+ if (!sub_8141180(0))
+ SetMainTask(MainTask_SlotsGameLoop);
+ break;
+ }
+}
+
+void MainTask_ConfirmExitGame(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+
+ switch (data[0])
+ {
+ case 0:
+ sub_8141148(10, 0);
+ data[0]++;
+ break;
+ case 1:
+ if (!sub_8141180(0))
+ data[0]++;
+ break;
+ case 2:
+ switch (Menu_ProcessInputNoWrapClearOnChoose())
+ {
+ case 0:
+ GiveCoins(sSlotMachineState->bet);
+ sub_8141148(8, 0);
+ data[0] = 3;
+ break;
+ case 1:
+ case -1:
+ sub_8141148(11, 0);
+ data[0] = 4;
+ break;
+ }
+ break;
+ case 3:
+ if (!sub_8141180(0))
+ SetMainTask(MainTask_ExitSlots);
+ break;
+ case 4:
+ if (!sub_8141180(0))
+ SetMainTask(MainTask_SlotsGameLoop);
+ break;
+ }
+}
+
+void MainTask_DarnNoPayout(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+
+ switch (data[0])
+ {
+ case 0:
+ sub_8141148(6, 0);
+ data[1] = 0;
+ data[0]++;
+ break;
+ case 1:
+ data[1]++;
+ if (data[1] > 60)
+ {
+ sub_8141148(7, 0);
+ sub_8141148(2, 1);
+ sub_8141148(13, 2);
+ data[0]++;
+ }
+ break;
+ case 2:
+ if (!sub_8141180(0) && !sub_8141180(1) && !sub_8141180(2))
+ SetMainTask(MainTask_SlotsGameLoop);
+ break;
+ }
+}
+
+void MainTask_WinHandlePayout(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+
+ switch (data[0])
+ {
+ case 0:
+ if (sSlotMachineState->slotRewardClass == 5 || sSlotMachineState->slotRewardClass == 6)
+ PlayFanfare(MUS_ME_B_BIG);
+ else
+ PlayFanfare(MUS_ME_B_SMALL);
+ sub_8141148(8, 0);
+ sub_8141148(4, 1);
+ data[1] = 8;
+ data[0]++;
+ break;
+ case 1:
+ data[1]++;
+ if (data[1] > 120)
+ {
+ data[1] = 8;
+ if (JOY_HELD(A_BUTTON))
+ data[1] = 2;
+ data[0]++;
+ }
+ break;
+ case 2:
+ if (!sub_8141180(0))
+ {
+ if (IsFanfareTaskInactive() && JOY_NEW(START_BUTTON))
+ {
+ GiveCoins(sSlotMachineState->payout);
+ sSlotMachineState->payout = 0;
+ }
+ else
+ {
+ data[1]--;
+ if (data[1] == 0)
+ {
+ if (IsFanfareTaskInactive())
+ PlaySE(SE_PIN);
+ if (sSlotMachineState->payout != 0)
+ {
+ GiveCoins(1);
+ sSlotMachineState->payout--;
+ }
+ data[1] = 8;
+ if (JOY_HELD(A_BUTTON))
+ data[1] = 2;
+ }
+ }
+ sub_8141148(8, 0);
+ if (sSlotMachineState->payout == 0)
+ data[0]++;
+ }
+ break;
+ case 3:
+ if (IsFanfareTaskInactive() && !sub_8141180(0))
+ {
+ sub_8141148(5, 0);
+ data[0]++;
+ }
+ break;
+ case 4:
+ if (!sub_8141180(0))
+ {
+ sub_8141148(2, 0);
+ sub_8141148(13, 1);
+ data[0]++;
+ }
+ break;
+ case 5:
+ if (!sub_8141180(0) && !sub_8141180(1))
+ SetMainTask(MainTask_SlotsGameLoop);
+ break;
+ }
+}
+
+void MainTask_ExitSlots(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+
+ switch (data[0])
+ {
+ case 0:
+ sub_8141148(1, 0);
+ data[0]++;
+ break;
+ case 1:
+ if (!sub_8141180(0))
+ {
+ SetMainCallback2(sSlotMachineState->savedCallback);
+ sub_813F92C();
+ }
+ break;
+ }
+}
+
+static void SetMainTask(TaskFunc taskFunc)
+{
+ gTasks[sSlotMachineState->field_10].func = taskFunc;
+ gTasks[sSlotMachineState->field_10].data[0] = 0;
+}
+
+void sub_8140060(u8 taskId)
+{
+ // taskId is never used
+
+ s32 i;
+
+ for (i = 0; i < 3; i++)
+ {
+ if (sSlotMachineState->field_14[i] || sSlotMachineState->field_26[i] != 0)
+ {
+ if (sSlotMachineState->field_26[i] != 0 || sSlotMachineState->field_20[i] != sSlotMachineState->field_2C[i])
+ {
+ sSlotMachineState->field_26[i]++;
+ if (sSlotMachineState->field_26[i] > 2)
+ {
+ sSlotMachineState->field_26[i] = 0;
+ sSlotMachineState->field_20[i]--;
+ if (sSlotMachineState->field_20[i] < 0)
+ sSlotMachineState->field_20[i] = 20;
+ }
+ if (sSlotMachineState->field_20[i] != sSlotMachineState->field_2C[i])
+ continue;
+ }
+ sSlotMachineState->field_2C[i] = 21;
+ sSlotMachineState->field_14[i] = FALSE;
+ }
+ }
+ sub_8140D7C(sSlotMachineState->field_20, sSlotMachineState->field_26);
+}
+
+void sub_8140148(void)
+{
+ s32 i;
+
+ for (i = 0; i < 3; i++)
+ {
+ sSlotMachineState->field_14[i] = TRUE;
+ }
+}
+
+void sub_814016C(u16 whichReel, u16 whichReel2)
+{
+ switch (whichReel2)
+ {
+ case 0:
+ sub_81401F0(whichReel);
+ break;
+ case 1:
+ sub_81403BC(whichReel);
+ break;
+ case 2:
+ sub_81404B8(whichReel);
+ break;
+ }
+}
+
+bool32 sub_81401A0(u16 whichReel)
+{
+ return sSlotMachineState->field_14[whichReel];
+}
+
+s16 sub_81401B4(u16 whichReel)
+{
+ s16 position = sSlotMachineState->field_20[whichReel];
+ if (sSlotMachineState->field_26[whichReel] != 0)
+ {
+ position--;
+ if (position < 0)
+ position = 20;
+ }
+ return position;
+}
+
+void sub_81401F0(u16 whichReel)
+{
+ s32 i, j;
+ s16 r2;
+ u8 sp0[5];
+ s16 sp0C = sub_81401B4(whichReel);
+ s32 r8 = 0;
+
+ if (sSlotMachineState->field_08 == 0 && whichReel == 0)
+ {
+ for (i = 0; i < 5; i++)
+ {
+ for (j = 0, r2 = sp0C - i + 1; j < 3; j++, r2++)
+ {
+ if (r2 >= 21)
+ r2 = 0;
+ if (sub_81408F4(1, gUnknown_8464926[whichReel][r2]))
+ break;
+ }
+ if (j == 3)
+ {
+ sp0[r8] = i;
+ r8++;
+ }
+ }
+ }
+ else if (sSlotMachineState->field_08 != 1 || whichReel == 0)
+ {
+ for (i = 0, r2 = sp0C + 1; i < 3; i++, r2++)
+ {
+ if (r2 >= 21)
+ r2 = 0;
+ if (sub_81408F4(sSlotMachineState->field_08, gUnknown_8464926[whichReel][r2]))
+ {
+ sp0[0] = 0;
+ r8 = 1;
+ break;
+ }
+ }
+ for (i = 0, r2 = sp0C; i < 4; i++, r2--)
+ {
+ if (r2 < 0)
+ r2 = 20;
+ if (sub_81408F4(sSlotMachineState->field_08, gUnknown_8464926[whichReel][r2]))
+ {
+ sp0[r8] = i + 1;
+ r8++;
+ }
+ }
+ }
+ if (r8 == 0)
+ {
+ r2 = Random() % 5;
+ }
+ else
+ {
+ r2 = sp0[Random() % r8];
+ }
+ r2 = sp0C - r2;
+ if (r2 < 0)
+ r2 += 21;
+ sSlotMachineState->field_32[0] = whichReel;
+ sSlotMachineState->field_2C[whichReel] = r2;
+}
+
+void sub_81403BC(u16 whichReel)
+{
+ s16 r2, r4, r7, sp10;
+ s32 i;
+ s32 r6;
+ u8 sp4[5];
+
+ r7 = sSlotMachineState->field_32[0];
+ r4 = sSlotMachineState->field_20[r7] + 1;
+ if (r4 >= 21)
+ r4 = 0;
+ sp10 = sub_81401B4(whichReel);
+ r2 = sp10 + 1;
+ if (r2 >= 21)
+ r2 = 0;
+ r6 = 0;
+ for (i = 0; i < 5; i++)
+ {
+ if (sub_814054C(r7, r4, whichReel, r2, sSlotMachineState->field_08))
+ {
+ sp4[r6] = i;
+ r6++;
+ }
+ r2--;
+ if (r2 < 0)
+ r2 = 20;
+ }
+ if (r6 == 0)
+ {
+ sSlotMachineState->field_38 = 0;
+ if (sSlotMachineState->field_08 == 5 || sSlotMachineState->field_08 == 6)
+ r2 = 4;
+ else
+ r2 = 0;
+ }
+ else
+ {
+ sSlotMachineState->field_38 = 1;
+ r2 = sp4[0];
+ }
+ r2 = sp10 - r2;
+ if (r2 < 0)
+ r2 += 21;
+ sSlotMachineState->field_32[1] = whichReel;
+ sSlotMachineState->field_2C[whichReel] = r2;
+}
+
+void sub_81404B8(u16 whichReel)
+{
+ s32 i;
+ s32 r6;
+ s32 r9;
+ s32 r4;
+ s32 r2;
+ u8 sp0[5];
+
+ r9 = sub_81401B4(whichReel);
+ r4 = r9;
+ r6 = 0;
+ for (i = 0; i < 5; i++)
+ {
+ if (sub_81406E8(whichReel, r4, sSlotMachineState->field_08))
+ {
+ sp0[r6] = i;
+ r6++;
+ }
+ r4--;
+ if (r4 < 0)
+ r4 = 20;
+ }
+ if (r6 == 0)
+ {
+ if (sSlotMachineState->field_08 == 5 || sSlotMachineState->field_08 == 6)
+ r2 = 4;
+ else
+ r2 = 0;
+ }
+ else
+ r2 = sp0[0];
+ r2 = r9 - r2;
+ if (r2 < 0)
+ r2 += 21;
+ sSlotMachineState->field_2C[whichReel] = r2;
+}
+
+bool32 sub_814054C(s32 a0, s32 a1, s32 a2, s32 a3, s32 a4)
+{
+ s32 i;
+ s32 r5;
+ u8 sp0[9] = {};
+
+ for (i = 0; i < 9; i++)
+ sp0[i] = 7;
+
+ for (i = 0; i < 3; i++)
+ {
+ sp0[3 * a0 + i] = gUnknown_8464926[a0][a1];
+ sp0[3 * a2 + i] = gUnknown_8464926[a2][a3];
+ a1++;
+ if (a1 >= 21)
+ a1 = 0;
+ a3++;
+ if (a3 >= 21)
+ a3 = 0;
+ }
+
+ switch (a4)
+ {
+ case 0:
+ for (i = 0; i < 3; i++)
+ {
+ if (sub_81408F4(1, sp0[i]))
+ return FALSE;
+ }
+ for (i = 0; i < 15; i++)
+ {
+ if (sp0[gUnknown_8464890[i][0]] == sp0[gUnknown_8464890[i][1]])
+ return TRUE;
+ }
+ return FALSE;
+ case 1:
+ if (a0 == 0 || a2 == 0)
+ {
+ if (a0 == 1 || a2 == 1)
+ {
+ for (i = 0; i < 15; i += 3)
+ {
+ if (sp0[gUnknown_8464890[i][0]] == sp0[gUnknown_8464890[i][1]])
+ return FALSE;
+ }
+ }
+ for (i = 0; i < 3; i++)
+ {
+ if (sub_81408F4(a4, sp0[i]))
+ return TRUE;
+ }
+ return FALSE;
+ }
+ else
+ return TRUE;
+ case 2:
+ if (a0 == 2 || a2 == 2)
+ {
+ for (i = 0; i < 9; i++)
+ {
+ if (sub_81408F4(a4, sp0[i]))
+ return TRUE;
+ }
+ return FALSE; // wrong level
+ }
+ }
+ for (i = 0; i < 15; i++)
+ {
+ if (sp0[gUnknown_8464890[i][0]] == sp0[gUnknown_8464890[i][1]] && sub_81408F4(a4, sp0[gUnknown_8464890[i][0]]))
+ return TRUE;
+ }
+ return FALSE;
+}
diff --git a/src/vs_seeker.c b/src/vs_seeker.c
index bd5b9c7ea..6c6daf803 100644
--- a/src/vs_seeker.c
+++ b/src/vs_seeker.c
@@ -1,5 +1,5 @@
#include "global.h"
-#include "songs.h"
+#include "constants/songs.h"
#include "sound.h"
#include "task.h"
#include "malloc.h"