summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorultima-soul <akshayjhanji@hotmail.com>2019-08-04 15:23:09 -0700
committerultima-soul <akshayjhanji@hotmail.com>2019-08-04 15:23:09 -0700
commited90bf2430290853bd9376d53c70055fa07634be (patch)
tree39f67b5cbd0c0ef9e1a4763a052fd07924349940 /src
parentbbc7c6ccfc7d59f61f406849f752fdd5038a6a80 (diff)
parentd58bf398b2b83a326d23d14d531de7f45a1058bb (diff)
Merge branch 'master' into pokedex_2
Diffstat (limited to 'src')
-rw-r--r--src/battle_transition.c3728
-rw-r--r--src/diploma.c8
-rw-r--r--src/pokemon.c4
-rw-r--r--src/slot_machine.c2886
-rw-r--r--src/teachy_tv.c4
-rw-r--r--src/title_screen.c1056
-rw-r--r--src/trainer_tower.c4
-rw-r--r--src/vs_seeker.c2
8 files changed, 7681 insertions, 11 deletions
diff --git a/src/battle_transition.c b/src/battle_transition.c
new file mode 100644
index 000000000..0fd92d631
--- /dev/null
+++ b/src/battle_transition.c
@@ -0,0 +1,3728 @@
+#include "global.h"
+#include "sprite.h"
+#include "task.h"
+#include "overworld.h"
+#include "malloc.h"
+#include "palette.h"
+#include "trig.h"
+#include "random.h"
+#include "sound.h"
+#include "decompress.h"
+#include "gpu_regs.h"
+#include "battle_transition.h"
+#include "field_effect.h"
+#include "field_weather.h"
+#include "field_camera.h"
+#include "trainer_pokemon_sprites.h"
+#include "scanline_effect.h"
+#include "constants/songs.h"
+
+typedef bool8 (*TransitionStateFunc)(struct Task *task);
+typedef bool8 (*TransitionSpriteCallback)(struct Sprite *sprite);
+
+struct TransitionData
+{
+ vu8 vblankDma;
+ u16 winIn;
+ u16 winOut;
+ u16 win0H;
+ u16 win0V;
+ u16 unused_A;
+ u16 win1V;
+ u16 bldCnt;
+ u16 bldAlpha;
+ u16 bldY;
+ s16 bg123HOfs;
+ s16 bg123VOfs;
+ s16 bg0HOfsOpponent;
+ s16 bg0HOfsPlayer;
+ s16 bg0VOfs;
+ s16 unused_1E;
+ s16 counter;
+ s16 unused_22;
+ s16 data[11]; // for multiple purposes
+};
+
+static EWRAM_DATA struct TransitionData *sTransitionStructPtr = NULL;
+
+// TODO: Move this declaration to include/event_object_movement.h
+extern const struct OamData gEventObjectBaseOam_32x32;
+
+static bool8 BT_Phase1_FadeOut(struct Task *task);
+static bool8 BT_Phase1_FadeIn(struct Task *task);
+static bool8 BT_Phase2BlackDoodles_Init(struct Task *task);
+static bool8 BT_Phase2BlackDoodles_InitSingleBrush(struct Task *task);
+static bool8 BT_Phase2BlackDoodles_DrawSingleBrush(struct Task *task);
+static bool8 BT_Phase2BlackDoodles_IsDone(struct Task *task);
+static bool8 BT_Phase2BlackDoodles_NextBrush(struct Task *task);
+static bool8 BT_Phase2GridSquares_LoadGfx(struct Task *task);
+static bool8 BT_Phase2GridSquares_UpdateTileset(struct Task *task);
+static bool8 BT_Phase2GridSquares_IsDone(struct Task *task);
+static bool8 BT_Phase2WhiteFadeInStripes_Init(struct Task *task);
+static bool8 BT_Phase2WhiteFadeInStripes_SetupSprites(struct Task *task);
+static bool8 BT_Phase2WhiteFadeInStripes_IsWhiteFadeDone(struct Task *task);
+static bool8 BT_Phase2WhiteFadeInStripes_Stop(struct Task *task);
+static bool8 BT_Phase2WhiteFadeInStripes_IsDone(struct Task *task);
+static bool8 BT_Phase2SlicedScreen_Init(struct Task *task);
+static bool8 BT_Phase2SlicedScreen_UpdateOffsets(struct Task *task);
+static bool8 BT_Phase2SlicedScreen_End(struct Task *task);
+static bool8 BT_Phase2Mugshot_Init(struct Task *task);
+static bool8 BT_Phase2Mugshot_LoadGfx(struct Task *task);
+static bool8 BT_Phase2Mugshot_VsBarsSlideIn(struct Task *task);
+static bool8 BT_Phase2Mugshot_StartSpriteSlide(struct Task *task);
+static bool8 BT_Phase2Mugshot_WaitForOpponentInPlace(struct Task *task);
+static bool8 BT_Phase2Mugshot_WaitForPlayerInPlace(struct Task *task);
+static bool8 BT_Phase2Mugshot_ExpandWhiteBand(struct Task *task);
+static bool8 BT_Phase2Mugshot_StartBlackFade(struct Task *task);
+static bool8 BT_Phase2Mugshot_WaitForBlackFade(struct Task *task);
+static bool8 BT_Phase2Mugshot_End(struct Task *task);
+static bool8 BT_Phase2AntiClockwiseSpiral_Init(struct Task *task);
+static bool8 BT_Phase2AntiClockwiseSpiral_Update(struct Task *task);
+static bool8 BT_Phase2BlackWaveToRight_Init(struct Task *task);
+static bool8 BT_Phase2BlackWaveToRight_UpdateWave(struct Task *task);
+static bool8 BT_Phase2BlackWaveToRight_End(struct Task *task);
+static bool8 BT_Phase2FullScreenWave_Init(struct Task *task);
+static bool8 BT_Phase2FullScreenWave_UpdateWave(struct Task *task);
+static bool8 BT_Phase2ClockwiseBlackFade_Init(struct Task *task);
+static bool8 BT_Phase2ClockwiseBlackFade_Step1(struct Task *task);
+static bool8 BT_Phase2ClockwiseBlackFade_Step2(struct Task *task);
+static bool8 BT_Phase2ClockwiseBlackFade_Step3(struct Task *task);
+static bool8 BT_Phase2ClockwiseBlackFade_Step4(struct Task *task);
+static bool8 BT_Phase2ClockwiseBlackFade_Step5(struct Task *task);
+static bool8 BT_Phase2ClockwiseBlackFade_End(struct Task *task);
+static bool8 BT_Phase2SlidingPokeballs_LoadBgGfx(struct Task *task);
+static bool8 BT_Phase2SlidingPokeballs_SetupFldeffArgs(struct Task *task);
+static bool8 BT_Phase2SlidingPokeballs_IsDone(struct Task *task);
+static bool8 BT_Phase2BigPokeball_Init(struct Task *task);
+static bool8 BT_Phase2BigPokeball_LoadTilemapAndWave(struct Task *task);
+static bool8 BT_Phase2BigPokeball_UpdateWave1IncEva(struct Task *task);
+static bool8 BT_Phase2BigPokeball_UpdateWave2DecEvb(struct Task *task);
+static bool8 BT_Phase2BigPokeball_UpdateWave3(struct Task *task);
+static bool8 BT_Phase2BigPokeball_CircleEffect(struct Task *task);
+static bool8 BT_Phase2HorizontalCorrugate_Init(struct Task *task);
+static bool8 BT_Phase2HorizontalCorrugate_UpdateWave(struct Task *task);
+static bool8 BT_Phase2DistortedWave_InitWave(struct Task *task);
+static bool8 BT_Phase2DistortedWave_UpdateWave(struct Task *task);
+static bool8 BT_Phase2Blur_InitBgMosaic(struct Task *task);
+static bool8 BT_Phase2Blur_Anim(struct Task *task);
+static bool8 BT_Phase2Blur_IsDone(struct Task *task);
+static bool8 BT_Phase1Blink(struct Task *task);
+static bool8 BT_WaitForPhase1(struct Task *task);
+static bool8 BT_Phase2LaunchAnimTask(struct Task *task);
+static bool8 BT_WaitForPhase2(struct Task *task);
+
+static void BT_Phase2Blur(u8 taskId);
+static void BT_Phase2DistortedWave(u8 taskId);
+static void BT_Phase2HorizontalCorrugate(u8 taskId);
+static void BT_Phase2BigPokeball(u8 taskId);
+static void BT_Phase2SlidingPokeballs(u8 taskId);
+static void BT_Phase2ClockwiseBlackFade(u8 taskId);
+static void BT_Phase2FullScreenWave(u8 taskId);
+static void BT_Phase2BlackWaveToRight(u8 taskId);
+static void BT_Phase2SlicedScreen(u8 taskId);
+static void BT_Phase2WhiteFadeInStripes(u8 taskId);
+static void BT_Phase2GridSquares(u8 taskId);
+static void BT_Phase2BlackDoodles(u8 taskId);
+static void BT_Phase2StartLoreleiMugshot(u8 taskId);
+static void BT_Phase2StartBrunoMugshot(u8 taskId);
+static void BT_Phase2StartAgathaMugshot(u8 taskId);
+static void BT_Phase2StartLanceMugshot(u8 taskId);
+static void BT_Phase2StartBlueMugshot(u8 taskId);
+static void BT_Phase2AntiClockwiseSpiral(u8 taskId);
+static void BT_Phase1Task(u8 taskId);
+static void BT_Phase2Mugshot(u8 taskId);
+static void BT_Phase1SubTask(u8 taskId);
+
+static void SpriteCB_BT_Phase2Mugshots(struct Sprite *sprite);
+static void SpriteCB_BT_Phase2SlidingPokeballs(struct Sprite *sprite);
+static void SpriteCB_BT_Phase2WhiteFadeInStripes(struct Sprite *sprite);
+
+static bool8 BT_Phase2MugshotsSpriteFuncs_Wait(struct Sprite *sprite);
+static bool8 BT_Phase2MugshotsSpriteFuncs_InitParams(struct Sprite *sprite);
+static bool8 BT_Phase2MugshotsSpriteFuncs_SlideSpriteIn(struct Sprite *sprite);
+static bool8 BT_Phase2MugshotsSpriteFuncs_DecelerateSprite(struct Sprite *sprite);
+static bool8 BT_Phase2MugshotsSpriteFuncs_DecelerateSprite2(struct Sprite *sprite);
+
+static void VBCB_BT_Phase2DistortedWave(void);
+static void HBCB_BT_Phase2DistortedWave(void);
+static void VBCB_BT_Phase2HorizontalCorrugate(void);
+static void HBCB_BT_Phase2HorizontalCorrugate(void);
+static void VBCB_BT_Phase2BigPokeball1(void);
+static void VBCB_BT_Phase2BigPokeball2(void);
+static void HBCB_BT_Phase2BigPokeball(void);
+static void VBCB_BT_Phase2ClockwiseBlackFade(void);
+static void VBCB_BT_Phase2FullScreenWave(void);
+static void HBCB_BT_Phase2FullScreenWave(void);
+static void VBCB_BT_Phase2BlackWaveToRight(void);
+static void VBCB_BT_Phase2AntiClockwiseBlackFade(void);
+static void VBCB_BT_Phase2Mugshot1_Slide(void);
+static void VBCB_BT_Phase2Mugshot2_WhiteFade(void);
+static void HBCB_BT_Phase2Mugshot(void);
+static void VBCB_BT_Phase2SlicedScreen(void);
+static void HBCB_BT_Phase2SlicedScreen(void);
+static void VBCB_BT_Phase2WhiteFadeInStripes1(void);
+static void VBCB_BT_Phase2WhiteFadeInStripes2(void);
+static void HBCB_BT_Phase2WhiteFadeInStripes(void);
+static void VBCB_BT_Phase2BlackDoodles(void);
+
+static void BT_LaunchTask(u8 transitionId);
+static void BT_TaskMain(u8 taskId);
+static void BT_InitCtrlBlk(void);
+static void BT_CreatePhase1SubTask(s16 fadeOutDelay, s16 fadeInDelay, s16 blinkTimes, s16 fadeOutSpeed, s16 fadeInSpeed);
+static bool8 BT_IsPhase1Done(void);
+static void BT_VBSyncOamAndPltt(void);
+static void BT_GetBg0TilesetBase(u16 **tilesetPtr);
+static void BT_GetBg0TilemapAndTilesetBase(u16 **tilemapPtr, u16 **tilesetPtr);
+static void BT_LoadWaveIntoBuffer(s16 *buffer, s16 offset, s16 theta, s16 frequency, s16 amplitude, s16 bufSize);
+static void BT_GenerateCircle(s16 *buffer, s16 x, s16 y, s16 radius);
+static void BT_BlendPalettesToBlack(void);
+static void BT_DiagonalSegment_InitParams(s16 *data, s16 startPtX, s16 startPtY, s16 endPtX, s16 endPtY, s16 stepX, s16 stepY);
+static bool8 BT_DiagonalSegment_ComputePointOnSegment(s16 *data, bool8 checkBoundary1, bool8 checkBoundary2);
+static void BT_SetSpriteAsOpponentOrPlayer(s16 spriteId, bool16 value);
+static void BT_StartSpriteSlide(s16 spriteId);
+static s16 BT_IsSpriteSlideFinished(s16 spriteId);
+static void BT_Phase2Mugshots_CreateSprites(struct Task *task);
+
+static const u32 sBigPokeballTileset[] = INCBIN_U32("graphics/battle_transitions/big_pokeball_tileset.4bpp");
+static const u32 sSlidingPokeballTilemap[] = INCBIN_U32("graphics/battle_transitions/sliding_pokeball_tilemap.bin");
+static const u8 sSpriteImage_SlidingPokeball[] = INCBIN_U8("graphics/battle_transitions/sliding_pokeball.4bpp");
+static const u32 sVsBarTileset[] = INCBIN_U32("graphics/battle_transitions/vsbar_tileset.4bpp");
+static const u8 sSpriteImage_UnusedBrendan[] = INCBIN_U8("graphics/battle_transitions/unused_brendan.4bpp");
+static const u8 sSpriteImage_UnusedLass[] = INCBIN_U8("graphics/battle_transitions/unused_lass.4bpp");
+static const u32 sGridSquareTileset[] = INCBIN_U32("graphics/battle_transitions/grid_square_tileset.4bpp");
+
+static const TaskFunc sBT_Phase1Tasks[] =
+{
+ BT_Phase1Task,
+ BT_Phase1Task,
+ BT_Phase1Task,
+ BT_Phase1Task,
+ BT_Phase1Task,
+ BT_Phase1Task,
+ BT_Phase1Task,
+ BT_Phase1Task,
+ BT_Phase1Task,
+ BT_Phase1Task,
+ BT_Phase1Task,
+ BT_Phase1Task,
+ BT_Phase1Task,
+ BT_Phase1Task,
+ BT_Phase1Task,
+ BT_Phase1Task,
+ BT_Phase1Task,
+ BT_Phase1Task,
+};
+
+static const TaskFunc sBT_Phase2Tasks[] =
+{
+ BT_Phase2Blur,
+ BT_Phase2DistortedWave,
+ BT_Phase2HorizontalCorrugate,
+ BT_Phase2BigPokeball,
+ BT_Phase2SlidingPokeballs,
+ BT_Phase2ClockwiseBlackFade,
+ BT_Phase2FullScreenWave,
+ BT_Phase2BlackWaveToRight,
+ BT_Phase2SlicedScreen,
+ BT_Phase2WhiteFadeInStripes,
+ BT_Phase2GridSquares,
+ BT_Phase2BlackDoodles,
+ BT_Phase2StartLoreleiMugshot,
+ BT_Phase2StartBrunoMugshot,
+ BT_Phase2StartAgathaMugshot,
+ BT_Phase2StartLanceMugshot,
+ BT_Phase2StartBlueMugshot,
+ BT_Phase2AntiClockwiseSpiral,
+};
+
+static const TransitionStateFunc sBT_MainPhases[] =
+{
+ BT_Phase1Blink,
+ BT_WaitForPhase1,
+ BT_Phase2LaunchAnimTask,
+ BT_WaitForPhase2,
+};
+
+static const TransitionStateFunc sBT_Phase2BlurFuncs[] =
+{
+ BT_Phase2Blur_InitBgMosaic,
+ BT_Phase2Blur_Anim,
+ BT_Phase2Blur_IsDone,
+};
+
+static const TransitionStateFunc sBT_Phase2DistortedWaveFuncs[] =
+{
+ BT_Phase2DistortedWave_InitWave,
+ BT_Phase2DistortedWave_UpdateWave,
+};
+
+static const TransitionStateFunc sBT_Phase2HorizontalCorrugateFuncs[] =
+{
+ BT_Phase2HorizontalCorrugate_Init,
+ BT_Phase2HorizontalCorrugate_UpdateWave,
+};
+
+static const TransitionStateFunc sBT_Phase2BigPokeballFuncs[] =
+{
+ BT_Phase2BigPokeball_Init,
+ BT_Phase2BigPokeball_LoadTilemapAndWave,
+ BT_Phase2BigPokeball_UpdateWave1IncEva,
+ BT_Phase2BigPokeball_UpdateWave2DecEvb,
+ BT_Phase2BigPokeball_UpdateWave3,
+ BT_Phase2BigPokeball_CircleEffect,
+};
+
+static const TransitionStateFunc sBT_Phase2SlidingPokeballsFuncs[] =
+{
+ BT_Phase2SlidingPokeballs_LoadBgGfx,
+ BT_Phase2SlidingPokeballs_SetupFldeffArgs,
+ BT_Phase2SlidingPokeballs_IsDone,
+};
+
+static const s16 gUnknown_83FA400[] = { -16, 256 };
+
+static const s16 gUnknown_83FA404[] = { 0, 16, 32, 8, 24 };
+
+static const s16 gUnknown_83FA40E[] = { 8, -8 };
+
+static const TransitionStateFunc sBT_Phase2ClockwiseBlackFadeFuncs[] =
+{
+ BT_Phase2ClockwiseBlackFade_Init,
+ BT_Phase2ClockwiseBlackFade_Step1,
+ BT_Phase2ClockwiseBlackFade_Step2,
+ BT_Phase2ClockwiseBlackFade_Step3,
+ BT_Phase2ClockwiseBlackFade_Step4,
+ BT_Phase2ClockwiseBlackFade_Step5,
+ BT_Phase2ClockwiseBlackFade_End,
+};
+
+static const TransitionStateFunc sBT_Phase2FullScreenWaveFuncs[] =
+{
+ BT_Phase2FullScreenWave_Init,
+ BT_Phase2FullScreenWave_UpdateWave,
+};
+
+static const TransitionStateFunc sBT_Phase2BlackWaveToRightFuncs[] =
+{
+ BT_Phase2BlackWaveToRight_Init,
+ BT_Phase2BlackWaveToRight_UpdateWave,
+ BT_Phase2BlackWaveToRight_End,
+};
+static const s16 gUnknown_83FA444[] =
+{
+ 0x0, 0x26E,
+ 0x100, 0x69,
+ 0x0, -0x69,
+ -0x100, -0x266E,
+ 0x0, 0x26E,
+ 0x100, 0x69,
+ 0x0, -0x69,
+ -0x100, -0x266E,
+};
+
+static const TransitionStateFunc sBT_Phase2AntiClockwiseSpiralFuncs[] =
+{
+ BT_Phase2AntiClockwiseSpiral_Init,
+ BT_Phase2AntiClockwiseSpiral_Update,
+};
+
+static const TransitionStateFunc sBT_Phase2MugshotFuncs[] =
+{
+ BT_Phase2Mugshot_Init,
+ BT_Phase2Mugshot_LoadGfx,
+ BT_Phase2Mugshot_VsBarsSlideIn,
+ BT_Phase2Mugshot_StartSpriteSlide,
+ BT_Phase2Mugshot_WaitForOpponentInPlace,
+ BT_Phase2Mugshot_WaitForPlayerInPlace,
+ BT_Phase2Mugshot_ExpandWhiteBand,
+ BT_Phase2Mugshot_StartBlackFade,
+ BT_Phase2Mugshot_WaitForBlackFade,
+ BT_Phase2Mugshot_End,
+};
+
+static const u8 sMugshotsTrainerPicIDsTable[MUGSHOTS_COUNT] =
+{
+ // TODO: document these with macro
+ 0x70, 0x71, 0x72, 0x73, 0x7D
+};
+
+static const s16 sMugshotsOpponentRotationScales[MUGSHOTS_COUNT][2] =
+{
+ {0x200, 0x200},
+ {0x200, 0x200},
+ {0x200, 0x200},
+ {0x200, 0x200},
+ {0x200, 0x200},
+};
+
+static const s16 sMugshotsOpponentCoords[MUGSHOTS_COUNT][2] =
+{
+ { -8, 0 },
+ { -10, 0 },
+ { 0, 0 },
+ { -32, 0 },
+ { 0, 0 },
+};
+
+static const TransitionSpriteCallback sBT_Phase2MugshotSpriteFuncs[] =
+{
+ BT_Phase2MugshotsSpriteFuncs_Wait,
+ BT_Phase2MugshotsSpriteFuncs_InitParams,
+ BT_Phase2MugshotsSpriteFuncs_SlideSpriteIn,
+ BT_Phase2MugshotsSpriteFuncs_DecelerateSprite,
+ BT_Phase2MugshotsSpriteFuncs_Wait,
+ BT_Phase2MugshotsSpriteFuncs_DecelerateSprite2, // not used
+ BT_Phase2MugshotsSpriteFuncs_Wait,
+};
+
+static const s16 sMugShotSlideVelocity[] = { 12, -12 };
+
+static const s16 sMugShotSlideDeceleration[] = { -1, 1 };
+
+static const TransitionStateFunc sBT_Phase2SlicedScreenFuncs[] =
+{
+ BT_Phase2SlicedScreen_Init,
+ BT_Phase2SlicedScreen_UpdateOffsets,
+ BT_Phase2SlicedScreen_End,
+};
+
+static const TransitionStateFunc sBT_Phase2WhiteFadeInStripesFuncs[] =
+{
+ BT_Phase2WhiteFadeInStripes_Init,
+ BT_Phase2WhiteFadeInStripes_SetupSprites,
+ BT_Phase2WhiteFadeInStripes_IsWhiteFadeDone,
+ BT_Phase2WhiteFadeInStripes_Stop,
+ BT_Phase2WhiteFadeInStripes_IsDone,
+};
+
+static const u16 sWhiteStripeDelay[] = { 0, 9, 15, 6, 12, 3 };
+
+static const TransitionStateFunc sBT_Phase2GridSquaresFuncs[] =
+{
+ BT_Phase2GridSquares_LoadGfx,
+ BT_Phase2GridSquares_UpdateTileset,
+ BT_Phase2GridSquares_IsDone,
+};
+
+static const TransitionStateFunc sBT_Phase2BlackDoodlesFuncs[] =
+{
+ BT_Phase2BlackDoodles_Init,
+ BT_Phase2BlackDoodles_InitSingleBrush,
+ BT_Phase2BlackDoodles_DrawSingleBrush,
+ BT_Phase2BlackDoodles_IsDone,
+ BT_Phase2BlackDoodles_NextBrush,
+};
+
+static const s16 sBlackDoodlesSegments[][5] =
+{
+ { 0x38, 0x00, 0x00, 0xA0, 0 },
+ { 0x68, 0xA0, 0xF0, 0x58, 1 },
+ { 0xF0, 0x48, 0x38, 0x00, 1 },
+ { 0x00, 0x20, 0x90, 0xA0, 0 },
+ { 0x90, 0xA0, 0xB8, 0x00, 1 },
+ { 0x38, 0x00, 0xA8, 0xA0, 0 },
+ { 0xA8, 0xA0, 0x30, 0x00, 1 },
+};
+
+static const s16 sBlackDoodlesDelay[] = { 1, 1, 1, 1, 1, 1, 0 };
+
+static const TransitionStateFunc sBT_Phase1FadeFuncs[] =
+{
+ BT_Phase1_FadeOut,
+ BT_Phase1_FadeIn,
+};
+
+static const struct SpriteFrameImage sSpriteImageTable_SlidingPokeball[] =
+{
+ {
+ .data = sSpriteImage_SlidingPokeball,
+ .size = 0x200,
+ },
+};
+
+static const union AnimCmd sSpriteAnim_SlidingPokeball[] =
+{
+ ANIMCMD_FRAME(0, 1),
+ ANIMCMD_END,
+};
+
+static const union AnimCmd *const sSpriteAnimTable_SlidingPokeball[] = { sSpriteAnim_SlidingPokeball };
+
+static const union AffineAnimCmd sSpriteAffineAnim_SlidingPokeball1[] =
+{
+ AFFINEANIMCMD_FRAME(0, 0, -4, 1),
+ AFFINEANIMCMD_JUMP(0),
+};
+
+static const union AffineAnimCmd sSpriteAffineAnim_SlidingPokeball2[] =
+{
+ AFFINEANIMCMD_FRAME(0, 0, 4, 1),
+ AFFINEANIMCMD_JUMP(0),
+};
+
+static const union AffineAnimCmd *const sSpriteAffineAnimTable_SlidingPokeball[] =
+{
+ sSpriteAffineAnim_SlidingPokeball1,
+ sSpriteAffineAnim_SlidingPokeball2,
+};
+
+static const struct SpriteTemplate sSpriteTemplate_SlidingPokeball =
+{
+ .tileTag = SPRITE_INVALID_TAG,
+ .paletteTag = 0x1009,
+ .oam = &gEventObjectBaseOam_32x32,
+ .anims = sSpriteAnimTable_SlidingPokeball,
+ .images = sSpriteImageTable_SlidingPokeball,
+ .affineAnims = sSpriteAffineAnimTable_SlidingPokeball,
+ .callback = SpriteCB_BT_Phase2SlidingPokeballs,
+};
+
+static const struct OamData sOamData_Unused =
+{
+ .y = 0,
+ .affineMode = 0,
+ .objMode = 0,
+ .mosaic = 0,
+ .bpp = 0,
+ .shape = SPRITE_SHAPE(64x64),
+ .x = 0,
+ .matrixNum = 0,
+ .size = SPRITE_SIZE(64x64),
+ .tileNum = 0,
+ .priority = 0,
+ .paletteNum = 0,
+ .affineParam = 0,
+};
+
+static const struct SpriteFrameImage sSpriteImageTable_UnusedBrendan[] =
+{
+ {
+ .data = sSpriteImage_UnusedBrendan,
+ .size = 0x800,
+ },
+};
+
+static const struct SpriteFrameImage sSpriteImageTable_UnusedLass[] =
+{
+ {
+ .data = sSpriteImage_UnusedLass,
+ .size = 0x800,
+ },
+};
+
+static const union AnimCmd sSpriteAnim_Unused[] =
+{
+ ANIMCMD_FRAME(0, 1),
+ ANIMCMD_END,
+};
+
+static const union AnimCmd *const sSpriteAnimTable_Unused[] = { sSpriteAnim_Unused };
+
+static const struct SpriteTemplate sSpriteTemplateTable_Unused[] =
+{
+ {
+ .tileTag = SPRITE_INVALID_TAG,
+ .paletteTag = 0x100A,
+ .oam = &sOamData_Unused,
+ .anims = sSpriteAnimTable_Unused,
+ .images = sSpriteImageTable_UnusedBrendan,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = SpriteCB_BT_Phase2Mugshots,
+ },
+ {
+ .tileTag = SPRITE_INVALID_TAG,
+ .paletteTag = 0x100A,
+ .oam = &sOamData_Unused,
+ .anims = sSpriteAnimTable_Unused,
+ .images = sSpriteImageTable_UnusedLass,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = SpriteCB_BT_Phase2Mugshots,
+ },
+};
+
+// this palette is shared by big pokeball and sliding pokeball
+static const u16 sSlidingPokeballBigPokeballPalette[] = INCBIN_U16("graphics/battle_transitions/sliding_pokeball.gbapal");
+
+static const struct SpritePalette sSpritePalette_SlidingPokeball =
+{
+ .data = sSlidingPokeballBigPokeballPalette,
+ .tag = 0x1009,
+};
+
+static const u16 sVsBarLoreleiPalette[] = INCBIN_U16("graphics/battle_transitions/lorelei_bg.gbapal");
+static const u16 sVsBarBrunoPalette[] = INCBIN_U16("graphics/battle_transitions/bruno_bg.gbapal");
+static const u16 sVsBarAgathaPalette[] = INCBIN_U16("graphics/battle_transitions/agatha_bg.gbapal");
+static const u16 sVsBarLancePalette[] = INCBIN_U16("graphics/battle_transitions/lance_bg.gbapal");
+static const u16 sVsBarBluePalette[] = INCBIN_U16("graphics/battle_transitions/blue_bg.gbapal");
+static const u16 sVsBarMalePlayerPalette[] = INCBIN_U16("graphics/battle_transitions/red_bg.gbapal");
+static const u16 sVsBarFemalePlayerPalette[] = INCBIN_U16("graphics/battle_transitions/green_bg.gbapal");
+
+static const u16 *const sVsBarOpponentPalettes[MUGSHOTS_COUNT] =
+{
+ sVsBarLoreleiPalette,
+ sVsBarBrunoPalette,
+ sVsBarAgathaPalette,
+ sVsBarLancePalette,
+ sVsBarBluePalette,
+};
+
+static const u16 *const sVsBarPlayerPalettes[] =
+{
+ sVsBarMalePlayerPalette,
+ sVsBarFemalePlayerPalette,
+};
+
+static const u16 sUnusedTrainerPalette[] = INCBIN_U16("graphics/battle_transitions/unused_trainer.gbapal");
+
+static const struct SpritePalette sSpritePalette_UnusedTrainer =
+{
+ .data = sUnusedTrainerPalette,
+ .tag = 0x100A,
+};
+
+static const u16 sBigPokeballTilemap[] = INCBIN_U16("graphics/battle_transitions/big_pokeball_tilemap.bin");
+static const u16 sVsBarTilemap[] = INCBIN_U16("graphics/battle_transitions/vsbar_tilemap.bin");
+
+void BT_StartOnField(u8 transitionId)
+{
+ sTransitionStructPtr = AllocZeroed(sizeof(struct TransitionData));
+ gMain.callback2 = CB2_OverworldBasic;
+ BT_LaunchTask(transitionId);
+}
+
+// not used
+static void BT_StartWithoutAlloc(u8 transitionId)
+{
+ BT_LaunchTask(transitionId);
+}
+
+#define tState data[0]
+#define tTransitionId data[1]
+#define tTransitionDone data[15]
+
+bool8 BT_IsDone(void)
+{
+ u8 taskId = FindTaskIdByFunc(BT_TaskMain);
+ if (gTasks[taskId].tTransitionDone)
+ {
+ BT_InitCtrlBlk();
+ FREE_AND_SET_NULL(sTransitionStructPtr);
+ DestroyTask(taskId);
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+static void BT_LaunchTask(u8 transitionId)
+{
+ u8 taskId = CreateTask(BT_TaskMain, 2);
+ gTasks[taskId].tTransitionId = transitionId;
+}
+
+static void BT_TaskMain(u8 taskId)
+{
+ while (sBT_MainPhases[gTasks[taskId].tState](&gTasks[taskId]));
+}
+
+static bool8 BT_Phase1Blink(struct Task *task)
+{
+ SetWeatherScreenFadeOut();
+ CpuCopy32(gPlttBufferFaded, gPlttBufferUnfaded, 0x400);
+ if (sBT_Phase1Tasks[task->tTransitionId] != NULL)
+ {
+ CreateTask(sBT_Phase1Tasks[task->tTransitionId], 4);
+ ++task->tState;
+ return FALSE;
+ }
+ else
+ {
+ task->tState = 2;
+ return TRUE;
+ }
+}
+
+static bool8 BT_WaitForPhase1(struct Task *task)
+{
+ if (FindTaskIdByFunc(sBT_Phase1Tasks[task->tTransitionId]) == TASK_NONE)
+ {
+ ++task->tState;
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+static bool8 BT_Phase2LaunchAnimTask(struct Task *task)
+{
+ CreateTask(sBT_Phase2Tasks[task->tTransitionId], 0);
+ ++task->tState;
+ return FALSE;
+}
+
+static bool8 BT_WaitForPhase2(struct Task *task)
+{
+ task->tTransitionDone = FALSE;
+ if (FindTaskIdByFunc(sBT_Phase2Tasks[task->tTransitionId]) == TASK_NONE)
+ task->tTransitionDone = TRUE;
+ return FALSE;
+}
+
+static void BT_Phase1Task(u8 taskId)
+{
+ if (!gTasks[taskId].tState)
+ {
+ ++gTasks[taskId].tState;
+ BT_CreatePhase1SubTask(0, 0, 2, 2, 2);
+ }
+ else if (BT_IsPhase1Done())
+ {
+ DestroyTask(taskId);
+ }
+}
+
+#define tInterval data[1]
+#define tMosaicSize data[2]
+
+static void BT_Phase2Blur(u8 taskId)
+{
+ while (sBT_Phase2BlurFuncs[gTasks[taskId].tState](&gTasks[taskId]));
+}
+
+static bool8 BT_Phase2Blur_InitBgMosaic(struct Task *task)
+{
+ SetGpuReg(REG_OFFSET_MOSAIC, 0);
+ SetGpuRegBits(REG_OFFSET_BG1CNT, BGCNT_MOSAIC);
+ SetGpuRegBits(REG_OFFSET_BG2CNT, BGCNT_MOSAIC);
+ SetGpuRegBits(REG_OFFSET_BG3CNT, BGCNT_MOSAIC);
+ ++task->tState;
+ return TRUE;
+}
+
+static bool8 BT_Phase2Blur_Anim(struct Task *task)
+{
+ if (task->tInterval)
+ {
+ --task->tInterval;
+ }
+ else
+ {
+ task->tInterval = 2;
+ if (++task->tMosaicSize == 10)
+ BeginNormalPaletteFade(0xFFFFFFFF, -1, 0, 0x10, RGB_BLACK);
+ // The mosaic size argument is shared by HSIZE and VSIZE
+ SetGpuReg(REG_OFFSET_MOSAIC, (task->tMosaicSize & 0xF) + ((task->tMosaicSize & 0xF) << 4));
+ if (task->tMosaicSize > 14)
+ ++task->tState;
+ }
+ return FALSE;
+}
+
+static bool8 BT_Phase2Blur_IsDone(struct Task *task)
+{
+ if (!gPaletteFade.active)
+ DestroyTask(FindTaskIdByFunc(BT_Phase2Blur));
+ return FALSE;
+}
+
+#undef tInterval
+#undef tMosaicSize
+
+#define tTheta data[1]
+#define tAmplitude data[2]
+
+static void BT_Phase2DistortedWave(u8 taskId)
+{
+ while (sBT_Phase2DistortedWaveFuncs[gTasks[taskId].tState](&gTasks[taskId]));
+}
+
+static bool8 BT_Phase2DistortedWave_InitWave(struct Task *task)
+{
+ BT_InitCtrlBlk();
+ ScanlineEffect_Clear();
+ BeginNormalPaletteFade(0xFFFFFFFF, 4, 0, 0x10, RGB_BLACK);
+ BT_LoadWaveIntoBuffer(gScanlineEffectRegBuffers[1], sTransitionStructPtr->bg123HOfs, 0, 2, 0, 160);
+ SetVBlankCallback(VBCB_BT_Phase2DistortedWave);
+ SetHBlankCallback(HBCB_BT_Phase2DistortedWave);
+ EnableInterrupts(INTR_FLAG_VBLANK | INTR_FLAG_HBLANK);
+ ++task->tState;
+ return FALSE;
+}
+
+static bool8 BT_Phase2DistortedWave_UpdateWave(struct Task *task)
+{
+ sTransitionStructPtr->vblankDma = FALSE;
+ task->tTheta += 4;
+ task->tAmplitude += 8;
+ BT_LoadWaveIntoBuffer(gScanlineEffectRegBuffers[0], sTransitionStructPtr->bg123HOfs, task->tTheta, 2, task->tAmplitude, 160);
+ if (!gPaletteFade.active)
+ DestroyTask(FindTaskIdByFunc(BT_Phase2DistortedWave));
+ ++sTransitionStructPtr->vblankDma;
+ return FALSE;
+}
+
+static void VBCB_BT_Phase2DistortedWave(void)
+{
+ BT_VBSyncOamAndPltt();
+ if (sTransitionStructPtr->vblankDma)
+ DmaCopy16(3, gScanlineEffectRegBuffers[0], gScanlineEffectRegBuffers[1], 320);
+}
+
+static void HBCB_BT_Phase2DistortedWave(void)
+{
+ s16 offset = gScanlineEffectRegBuffers[1][REG_VCOUNT];
+
+ REG_BG1HOFS = offset;
+ REG_BG2HOFS = offset;
+ REG_BG3HOFS = offset;
+}
+
+static void BT_Phase2HorizontalCorrugate(u8 taskId)
+{
+ while (sBT_Phase2HorizontalCorrugateFuncs[gTasks[taskId].tState](&gTasks[taskId]));
+}
+
+static bool8 BT_Phase2HorizontalCorrugate_Init(struct Task *task)
+{
+ BT_InitCtrlBlk();
+ ScanlineEffect_Clear();
+ BeginNormalPaletteFade(0xFFFFFFFF, 4, 0, 0x10, RGB_BLACK);
+ memset(gScanlineEffectRegBuffers[1], sTransitionStructPtr->bg123VOfs, 320);
+ SetVBlankCallback(VBCB_BT_Phase2HorizontalCorrugate);
+ SetHBlankCallback(HBCB_BT_Phase2HorizontalCorrugate);
+ EnableInterrupts(INTR_FLAG_VBLANK | INTR_FLAG_HBLANK);
+ ++task->tState;
+ return FALSE;
+}
+
+static bool8 BT_Phase2HorizontalCorrugate_UpdateWave(struct Task *task)
+{
+ u8 i;
+ u16 theta, amplitude;
+
+ sTransitionStructPtr->vblankDma = FALSE;
+ theta = task->tTheta;
+ amplitude = task->tAmplitude >> 8;
+ task->tTheta += 4224;
+ task->tAmplitude += 384;
+ for (i = 0; i < 160; ++i, theta += 4224)
+ gScanlineEffectRegBuffers[0][i] = sTransitionStructPtr->bg123VOfs + Sin(theta / 256, amplitude);
+ if (!gPaletteFade.active)
+ DestroyTask(FindTaskIdByFunc(BT_Phase2HorizontalCorrugate));
+ ++sTransitionStructPtr->vblankDma;
+ return FALSE;
+}
+
+static void VBCB_BT_Phase2HorizontalCorrugate(void)
+{
+ BT_VBSyncOamAndPltt();
+ if (sTransitionStructPtr->vblankDma)
+ DmaCopy16(3, gScanlineEffectRegBuffers[0], gScanlineEffectRegBuffers[1], 320);
+}
+
+static void HBCB_BT_Phase2HorizontalCorrugate(void)
+{
+ s16 offset = gScanlineEffectRegBuffers[1][REG_VCOUNT];
+
+ REG_BG1VOFS = offset;
+ REG_BG2VOFS = offset;
+ REG_BG3VOFS = offset;
+}
+
+#undef tTheta
+#undef tAmplitude
+
+#define tEvb data[1]
+#define tEva data[2]
+#define tInterval data[3]
+#define tTheta data[4]
+#define tAmplitude data[5]
+
+static void BT_Phase2BigPokeball(u8 taskId)
+{
+ while (sBT_Phase2BigPokeballFuncs[gTasks[taskId].tState](&gTasks[taskId]));
+}
+
+static bool8 BT_Phase2BigPokeball_Init(struct Task *task)
+{
+ u16 i, *tilemapAddr, *tilesetAddr;
+
+ BT_InitCtrlBlk();
+ ScanlineEffect_Clear();
+ task->tEvb = 16;
+ task->tEva = 0;
+ task-> tTheta = 0;
+ task-> tAmplitude = 0x4000;
+ sTransitionStructPtr->winIn = 0x3F;
+ sTransitionStructPtr->winOut = 0;
+ sTransitionStructPtr->win0H = 240;
+ sTransitionStructPtr->win0V = 160;
+ sTransitionStructPtr->bldCnt = BLDCNT_TGT1_BG0 | BLDCNT_EFFECT_BLEND | BLDCNT_TGT2_BG0 | BLDCNT_TGT2_BG1 | BLDCNT_TGT2_BG2 | BLDCNT_TGT2_BG3 | BLDCNT_TGT2_OBJ | BLDCNT_TGT2_BD;
+ sTransitionStructPtr->bldAlpha = (task->tEvb << 8) | task->tEva;
+ for (i = 0; i < 160; ++i)
+ gScanlineEffectRegBuffers[1][i] = 240;
+ SetVBlankCallback(VBCB_BT_Phase2BigPokeball1);
+ BT_GetBg0TilemapAndTilesetBase(&tilemapAddr, &tilesetAddr);
+ CpuFill16(0, tilemapAddr, 0x800);
+ CpuCopy16(sBigPokeballTileset, tilesetAddr, 0x580);
+ LoadPalette(sSlidingPokeballBigPokeballPalette, 0xF0, 0x20);
+ ++task->tState;
+ return FALSE;
+}
+
+static bool8 BT_Phase2BigPokeball_LoadTilemapAndWave(struct Task *task)
+{
+ s16 i, j;
+ u16 *tilemapAddr, *tilesetAddr;
+ const u16 *BigPokeballMap = sBigPokeballTilemap;
+
+ BT_GetBg0TilemapAndTilesetBase(&tilemapAddr, &tilesetAddr);
+ for (i = 0; i < 20; ++i)
+ for (j = 0; j < 30; ++j, ++BigPokeballMap)
+ tilemapAddr[i * 32 + j] = *BigPokeballMap | 0xF000; // use palette #15
+ BT_LoadWaveIntoBuffer(gScanlineEffectRegBuffers[0], 0, task->tTheta, 132, task->tAmplitude, 160);
+ ++task->tState;
+ return TRUE;
+}
+
+static bool8 BT_Phase2BigPokeball_UpdateWave1IncEva(struct Task *task)
+{
+ sTransitionStructPtr->vblankDma = FALSE;
+ if (task->tInterval == 0 || --task->tInterval == 0)
+ {
+ ++task->tEva;
+ task->tInterval = 1; // Broken logic. This makes the condition always TRUE.
+ }
+ sTransitionStructPtr->bldAlpha = (task->tEvb << 8) | task->tEva;
+ // Increment eva until it reaches 50% coeff
+ if (task->tEva > 15)
+ ++task->tState;
+ task->tTheta += 12;
+ task->tAmplitude -= 384;
+ // Assign a very high frequency value so that 2 adjacent values in gScanlineEffectRegBuffers[0] will have different sign.
+ BT_LoadWaveIntoBuffer(gScanlineEffectRegBuffers[0], 0, task->tTheta, 132, task->tAmplitude >> 8, 160);
+ ++sTransitionStructPtr->vblankDma;
+ return FALSE;
+}
+
+static bool8 BT_Phase2BigPokeball_UpdateWave2DecEvb(struct Task *task)
+{
+ sTransitionStructPtr->vblankDma = FALSE;
+ if (task->tInterval == 0 || --task->tInterval == 0)
+ {
+ --task->tEvb;
+ task->tInterval = 2;
+ }
+ sTransitionStructPtr->bldAlpha = (task->tEvb << 8) | task->tEva;
+ if (!task->tEvb)
+ ++task->tState;
+ if (task->tAmplitude > 0)
+ {
+ task->tTheta += 12;
+ task->tAmplitude -= 384;
+ }
+ else
+ {
+ task->tAmplitude = 0;
+ }
+ BT_LoadWaveIntoBuffer(gScanlineEffectRegBuffers[0], 0, task->tTheta, 132, task->tAmplitude >> 8, 160);
+ ++sTransitionStructPtr->vblankDma;
+ return FALSE;
+}
+
+#undef tEvb
+#undef tEva
+#undef tInterval
+
+#define tRadius data[1]
+#define tDeltaRadius data[2]
+#define tKeepVBCB data[3]
+
+static bool8 BT_Phase2BigPokeball_UpdateWave3(struct Task *task)
+{
+ sTransitionStructPtr->vblankDma = FALSE;
+ if (task->tAmplitude > 0)
+ {
+ task->tTheta += 12;
+ task->tAmplitude -= 384;
+ }
+ else
+ {
+ task->tAmplitude = 0;
+ }
+ BT_LoadWaveIntoBuffer(gScanlineEffectRegBuffers[0], 0, task->tTheta, 132, task->tAmplitude >> 8, 160);
+ if (task->tAmplitude <= 0)
+ {
+ ++task->tState;
+ task->tRadius = 160;
+ task->tDeltaRadius = 256;
+ task->tKeepVBCB = 0;
+ }
+ ++sTransitionStructPtr->vblankDma;
+ return FALSE;
+}
+
+static bool8 BT_Phase2BigPokeball_CircleEffect(struct Task *task)
+{
+ sTransitionStructPtr->vblankDma = FALSE;
+ if (task->tDeltaRadius < 2048)
+ task->tDeltaRadius += 256;
+ if (task->tRadius)
+ {
+ task->tRadius -= (task->tDeltaRadius >> 8);
+ if (task->tRadius < 0)
+ task->tRadius = 0;
+ }
+ BT_GenerateCircle(gScanlineEffectRegBuffers[0], 120, 80, task->tRadius);
+ if (task->tRadius == 0)
+ {
+ DmaStop(0);
+ BT_BlendPalettesToBlack();
+ DestroyTask(FindTaskIdByFunc(BT_Phase2BigPokeball));
+ }
+ if (task->tKeepVBCB == 0)
+ {
+ ++task->tKeepVBCB;
+ SetVBlankCallback(VBCB_BT_Phase2BigPokeball2);
+ }
+ ++sTransitionStructPtr->vblankDma;
+ return FALSE;
+}
+
+static void BT_VBStopDma0SyncSrcBufferSetLcdRegs(void)
+{
+ DmaStop(0);
+ BT_VBSyncOamAndPltt();
+ if (sTransitionStructPtr->vblankDma)
+ DmaCopy16(3, gScanlineEffectRegBuffers[0], gScanlineEffectRegBuffers[1], 320);
+ SetGpuReg(REG_OFFSET_WININ, sTransitionStructPtr->winIn);
+ SetGpuReg(REG_OFFSET_WINOUT, sTransitionStructPtr->winOut);
+ SetGpuReg(REG_OFFSET_WIN0V, sTransitionStructPtr->win0V);
+ SetGpuReg(REG_OFFSET_BLDCNT, sTransitionStructPtr->bldCnt);
+ SetGpuReg(REG_OFFSET_BLDALPHA, sTransitionStructPtr->bldAlpha);
+}
+
+static void VBCB_BT_Phase2BigPokeball1(void)
+{
+ BT_VBStopDma0SyncSrcBufferSetLcdRegs();
+ DmaSet(0, gScanlineEffectRegBuffers[1], &REG_BG0HOFS, ((DMA_ENABLE | DMA_START_HBLANK | DMA_REPEAT | DMA_16BIT | DMA_SRC_INC | DMA_DEST_FIXED) << 16) | 1);
+}
+
+static void VBCB_BT_Phase2BigPokeball2(void)
+{
+ BT_VBStopDma0SyncSrcBufferSetLcdRegs();
+ DmaSet(0, gScanlineEffectRegBuffers[1], &REG_WIN0H, ((DMA_ENABLE | DMA_START_HBLANK | DMA_REPEAT | DMA_16BIT | DMA_SRC_INC | DMA_DEST_FIXED) << 16) | 1);
+}
+
+#undef tRadius
+#undef tDeltaRadius
+#undef tKeepVBCB
+#undef tTheta
+#undef tAmplitude
+
+// TODO: Document this effect after knowing more about field effects.
+static void BT_Phase2SlidingPokeballs(u8 taskId)
+{
+ while (sBT_Phase2SlidingPokeballsFuncs[gTasks[taskId].tState](&gTasks[taskId]));
+}
+
+static bool8 BT_Phase2SlidingPokeballs_LoadBgGfx(struct Task *task)
+{
+ u16 *tilemapAddr, *tilesetAddr;
+
+ BT_GetBg0TilemapAndTilesetBase(&tilemapAddr, &tilesetAddr);
+ CpuSet(sSlidingPokeballTilemap, tilesetAddr, 0x20);
+ CpuFill32(0, tilemapAddr, 0x800);
+ LoadPalette(sSlidingPokeballBigPokeballPalette, 0xF0, 0x20);
+ ++task->tState;
+ return FALSE;
+}
+
+static bool8 BT_Phase2SlidingPokeballs_SetupFldeffArgs(struct Task *task)
+{
+ s16 i, rand;
+ s16 arr0[NELEMS(gUnknown_83FA400)];
+ s16 arr1[NELEMS(gUnknown_83FA404)];
+
+ memcpy(arr0, gUnknown_83FA400, sizeof(gUnknown_83FA400));
+ memcpy(arr1, gUnknown_83FA404, sizeof(gUnknown_83FA404));
+ rand = Random() & 1;
+ for (i = 0; i <= 4; ++i, rand ^= 1)
+ {
+ gFieldEffectArguments[0] = arr0[rand]; // x
+ gFieldEffectArguments[1] = (i * 32) + 16; // y
+ gFieldEffectArguments[2] = rand;
+ gFieldEffectArguments[3] = arr1[i];
+ FieldEffectStart(FLDEFF_POKEBALL);
+ }
+ ++task->tState;
+ return FALSE;
+}
+
+static bool8 BT_Phase2SlidingPokeballs_IsDone(struct Task *task)
+{
+ if (!FieldEffectActiveListContains(FLDEFF_POKEBALL))
+ {
+ BT_BlendPalettesToBlack();
+ DestroyTask(FindTaskIdByFunc(BT_Phase2SlidingPokeballs));
+ }
+ return FALSE;
+}
+
+bool8 FldEff_Pokeball(void)
+{
+ u8 spriteId = CreateSpriteAtEnd(&sSpriteTemplate_SlidingPokeball, gFieldEffectArguments[0], gFieldEffectArguments[1], 0);
+
+ gSprites[spriteId].oam.priority = 0;
+ gSprites[spriteId].oam.affineMode = 1;
+ gSprites[spriteId].data[0] = gFieldEffectArguments[2];
+ gSprites[spriteId].data[1] = gFieldEffectArguments[3];
+ gSprites[spriteId].data[2] = -1;
+ InitSpriteAffineAnim(&gSprites[spriteId]);
+ StartSpriteAffineAnim(&gSprites[spriteId], gFieldEffectArguments[2]);
+ return FALSE;
+}
+
+#define SOME_VRAM_STORE(ptr, posY, posX, toStore) \
+{ \
+ u32 index = (posY) * 32 + posX; \
+ ptr[index] = toStore; \
+}
+
+static void SpriteCB_BT_Phase2SlidingPokeballs(struct Sprite *sprite)
+{
+ s16 arr0[NELEMS(gUnknown_83FA40E)];
+
+ memcpy(arr0, gUnknown_83FA40E, sizeof(gUnknown_83FA40E));
+ if (sprite->data[1])
+ {
+ --sprite->data[1];
+ }
+ else
+ {
+ if ((u16)sprite->pos1.x <= 240)
+ {
+ s16 posX = sprite->pos1.x >> 3;
+ s16 posY = sprite->pos1.y >> 3;
+
+ if (posX != sprite->data[2])
+ {
+ u32 var;
+ u16 *ptr;
+
+ sprite->data[2] = posX;
+ var = (((GetGpuReg(REG_OFFSET_BG0CNT) >> 8) & 0x1F) << 11);
+ ptr = (u16 *)(VRAM + var);
+ SOME_VRAM_STORE(ptr, posY - 2, posX, 0xF001);
+ SOME_VRAM_STORE(ptr, posY - 1, posX, 0xF001);
+ SOME_VRAM_STORE(ptr, posY - 0, posX, 0xF001);
+ SOME_VRAM_STORE(ptr, posY + 1, posX, 0xF001);
+ }
+ }
+ sprite->pos1.x += arr0[sprite->data[0]];
+ if (sprite->pos1.x < -15 || sprite->pos1.x > 255)
+ FieldEffectStop(sprite, FLDEFF_POKEBALL);
+ }
+}
+
+#define trStartPtX data[0]
+#define trStartPtY data[1]
+#define trCurrentPtX data[2]
+#define trCurrentPtY data[3]
+#define trEndPtX data[4]
+#define trEndPtY data[5]
+
+static void BT_Phase2ClockwiseBlackFade(u8 taskId)
+{
+ while (sBT_Phase2ClockwiseBlackFadeFuncs[gTasks[taskId].tState](&gTasks[taskId]));
+}
+
+static bool8 BT_Phase2ClockwiseBlackFade_Init(struct Task *task)
+{
+ u16 i;
+
+ BT_InitCtrlBlk();
+ ScanlineEffect_Clear();
+ sTransitionStructPtr->winIn = 0;
+ sTransitionStructPtr->winOut = 0x3F;
+ sTransitionStructPtr->win0H = 0xF0F1;
+ sTransitionStructPtr->win0V = 0x00A0;
+ for (i = 0; i < 160; ++i)
+ {
+ gScanlineEffectRegBuffers[1][i] = 0xF3F4;
+ }
+ SetVBlankCallback(VBCB_BT_Phase2ClockwiseBlackFade);
+ sTransitionStructPtr->trEndPtX = 120;
+ ++task->tState;
+ return TRUE;
+}
+
+static bool8 BT_Phase2ClockwiseBlackFade_Step1(struct Task *task)
+{
+ sTransitionStructPtr->vblankDma = FALSE;
+ BT_DiagonalSegment_InitParams(sTransitionStructPtr->data, 120, 80, sTransitionStructPtr->trEndPtX, -1, 1, 1);
+ do
+ {
+ gScanlineEffectRegBuffers[0][sTransitionStructPtr->trCurrentPtY] = (sTransitionStructPtr->trCurrentPtX + 1) | 0x7800;
+ }
+ while (!BT_DiagonalSegment_ComputePointOnSegment(sTransitionStructPtr->data, TRUE, TRUE));
+
+ sTransitionStructPtr->trEndPtX += 32;
+ if (sTransitionStructPtr->trEndPtX >= 240)
+ {
+ sTransitionStructPtr->trEndPtY = 0;
+ ++task->tState;
+ }
+ ++sTransitionStructPtr->vblankDma;
+ return FALSE;
+}
+
+static bool8 BT_Phase2ClockwiseBlackFade_Step2(struct Task *task)
+{
+ s16 left, right;
+ vu8 finished = FALSE;
+
+ sTransitionStructPtr->vblankDma = FALSE;
+ BT_DiagonalSegment_InitParams(sTransitionStructPtr->data, 120, 80, 240, sTransitionStructPtr->trEndPtY, 1, 1);
+ while (TRUE)
+ {
+ left = 120;
+ right = sTransitionStructPtr->trCurrentPtX + 1;
+ if (sTransitionStructPtr->trEndPtY >= 80)
+ {
+ left = sTransitionStructPtr->trCurrentPtX;
+ right = 240;
+ }
+ gScanlineEffectRegBuffers[0][sTransitionStructPtr->trCurrentPtY] = right | (left << 8);
+ if (finished)
+ break;
+ finished = BT_DiagonalSegment_ComputePointOnSegment(sTransitionStructPtr->data, TRUE, TRUE);
+ }
+ sTransitionStructPtr->trEndPtY += 16;
+ if (sTransitionStructPtr->trEndPtY >= 160)
+ {
+ sTransitionStructPtr->trEndPtX = 240;
+ ++task->tState;
+ }
+ else
+ {
+ while (sTransitionStructPtr->trCurrentPtY < sTransitionStructPtr->trEndPtY)
+ gScanlineEffectRegBuffers[0][++sTransitionStructPtr->trCurrentPtY] = right | (left << 8);
+ }
+ ++sTransitionStructPtr->vblankDma;
+ return FALSE;
+}
+
+static bool8 BT_Phase2ClockwiseBlackFade_Step3(struct Task *task)
+{
+ sTransitionStructPtr->vblankDma = FALSE;
+ BT_DiagonalSegment_InitParams(sTransitionStructPtr->data, 120, 80, sTransitionStructPtr->trEndPtX, 160, 1, 1);
+ do
+ {
+ gScanlineEffectRegBuffers[0][sTransitionStructPtr->trCurrentPtY] = (sTransitionStructPtr->trCurrentPtX << 8) | 0xF0;
+ }
+ while (!BT_DiagonalSegment_ComputePointOnSegment(sTransitionStructPtr->data, TRUE, TRUE));
+ sTransitionStructPtr->trEndPtX -= 32;
+ if (sTransitionStructPtr->trEndPtX <= 0)
+ {
+ sTransitionStructPtr->trEndPtY = 160;
+ ++task->tState;
+ }
+ ++sTransitionStructPtr->vblankDma;
+ return FALSE;
+}
+
+/*
+ * BUG: The following 2 functions are incorrect. The animation after
+ * the rotation angle reaches 1.5π will not be displayed.
+ *
+ * There're 2 problems which need to be solved in order to correct the logic.
+ * 1. With current setup, nothing is displayed inside WIN0 and everything
+ * is displayed outside WIN0. Thus, if the rotation angle is > 1.5π, it
+ * won't be able to handle the situation.
+ * 2. The programmer sometimes swapped the place of left and right boundary
+ * of WIN0 (see variables left and right), which will sometimes cause right
+ * to be smaller than left. In this way, garbage data will be written to WIN0H.
+ */
+static bool8 BT_Phase2ClockwiseBlackFade_Step4(struct Task *task)
+{
+ s16 right, left;
+ u16 win0H;
+ vu8 finished = FALSE;
+
+ sTransitionStructPtr->vblankDma = FALSE;
+ BT_DiagonalSegment_InitParams(sTransitionStructPtr->data, 120, 80, 0, sTransitionStructPtr->trEndPtY, 1, 1);
+ while (TRUE)
+ {
+ right = (gScanlineEffectRegBuffers[0][sTransitionStructPtr->trCurrentPtY]) & 0xFF;
+ left = sTransitionStructPtr->trCurrentPtX;
+ if (sTransitionStructPtr->trEndPtY <= 80)
+ {
+ left = 120;
+ right = sTransitionStructPtr->trCurrentPtX;
+ }
+ win0H = right | (left << 8);
+ gScanlineEffectRegBuffers[0][sTransitionStructPtr->trCurrentPtY] = win0H;
+ if (finished)
+ break;
+ finished = BT_DiagonalSegment_ComputePointOnSegment(sTransitionStructPtr->data, TRUE, TRUE);
+ }
+ sTransitionStructPtr->trEndPtY -= 16;
+ if (sTransitionStructPtr->trEndPtY <= 0)
+ {
+ sTransitionStructPtr->trEndPtX = 0;
+ ++task->tState;
+ }
+ else
+ {
+ while (sTransitionStructPtr->trCurrentPtY > sTransitionStructPtr->trEndPtY)
+ gScanlineEffectRegBuffers[0][--sTransitionStructPtr->trCurrentPtY] = right | (left << 8);
+ }
+ ++sTransitionStructPtr->vblankDma;
+ return FALSE;
+}
+
+static bool8 BT_Phase2ClockwiseBlackFade_Step5(struct Task *task)
+{
+ s16 left, right;
+
+ sTransitionStructPtr->vblankDma = FALSE;
+ BT_DiagonalSegment_InitParams(sTransitionStructPtr->data, 120, 80, sTransitionStructPtr->trEndPtX, 0, 1, 1);
+ do
+ {
+ left = 120;
+ right = sTransitionStructPtr->trCurrentPtX;
+ if (sTransitionStructPtr->trCurrentPtX >= 120)
+ {
+ left = 0;
+ right = 240;
+ }
+ gScanlineEffectRegBuffers[0][sTransitionStructPtr->trCurrentPtY] = right | (left << 8);
+ }
+ while (!BT_DiagonalSegment_ComputePointOnSegment(sTransitionStructPtr->data, TRUE, TRUE));
+ sTransitionStructPtr->trEndPtX += 32;
+ if (sTransitionStructPtr->trCurrentPtX > 120)
+ ++task->tState;
+ ++sTransitionStructPtr->vblankDma;
+ return FALSE;
+}
+
+static bool8 BT_Phase2ClockwiseBlackFade_End(struct Task *task)
+{
+ DmaStop(0);
+ BT_BlendPalettesToBlack();
+ DestroyTask(FindTaskIdByFunc(BT_Phase2ClockwiseBlackFade));
+ return FALSE;
+}
+
+static void VBCB_BT_Phase2ClockwiseBlackFade(void)
+{
+ DmaStop(0);
+ BT_VBSyncOamAndPltt();
+ if (sTransitionStructPtr->vblankDma)
+ DmaCopy16(3, gScanlineEffectRegBuffers[0], gScanlineEffectRegBuffers[1], 320);
+ SetGpuReg(REG_OFFSET_WININ, sTransitionStructPtr->winIn);
+ SetGpuReg(REG_OFFSET_WINOUT, sTransitionStructPtr->winOut);
+ SetGpuReg(REG_OFFSET_WIN0V, sTransitionStructPtr->win0V);
+ SetGpuReg(REG_OFFSET_WIN0H, gScanlineEffectRegBuffers[1][0]);
+ DmaSet(0, gScanlineEffectRegBuffers[1], &REG_WIN0H, ((DMA_ENABLE | DMA_START_HBLANK | DMA_REPEAT | DMA_16BIT | DMA_SRC_INC | DMA_DEST_FIXED) << 16) | 1);
+}
+
+#undef trStartPtX
+#undef trStartPtY
+#undef trCurrentPtX
+#undef trCurrentPtY
+#undef trEndPtX
+#undef trEndPtY
+
+#define tTheta data[1]
+#define tAmplitude data[2]
+#define tDelayForFade data[3]
+#define tStartFade data[4]
+
+static void BT_Phase2FullScreenWave(u8 taskId)
+{
+ while (sBT_Phase2FullScreenWaveFuncs[gTasks[taskId].tState](&gTasks[taskId]));
+}
+
+static bool8 BT_Phase2FullScreenWave_Init(struct Task *task)
+{
+ u8 i;
+
+ BT_InitCtrlBlk();
+ ScanlineEffect_Clear();
+ for (i = 0; i < 160; ++i)
+ gScanlineEffectRegBuffers[1][i] = sTransitionStructPtr->bg123VOfs;
+ SetVBlankCallback(VBCB_BT_Phase2FullScreenWave);
+ SetHBlankCallback(HBCB_BT_Phase2FullScreenWave);
+ EnableInterrupts(INTR_FLAG_HBLANK);
+ ++task->tState;
+ return TRUE;
+}
+
+static bool8 BT_Phase2FullScreenWave_UpdateWave(struct Task *task)
+{
+ u8 i;
+ s16 amplitude;
+ u16 theta, frequency;
+
+ sTransitionStructPtr->vblankDma = FALSE;
+ amplitude = task->tAmplitude >> 8;
+ theta = task->tTheta;
+ frequency = 384;
+ task->tTheta += 0x400;
+ if (task->tAmplitude <= 0x1FFF)
+ task->tAmplitude += 384;
+ for (i = 0; i < 160; ++i, theta += frequency)
+ {
+ s16 var = theta >> 8;
+
+ #ifndef NONMATCHING
+ asm("");
+ #endif
+ gScanlineEffectRegBuffers[0][i] = sTransitionStructPtr->bg123VOfs + Sin(var, amplitude);
+ }
+ if (++task->tDelayForFade == 41)
+ {
+ ++task->tStartFade;
+ BeginNormalPaletteFade(0xFFFFFFFF, -8, 0, 0x10, RGB_BLACK);
+ }
+ if (task->tStartFade && !gPaletteFade.active)
+ DestroyTask(FindTaskIdByFunc(BT_Phase2FullScreenWave));
+ ++sTransitionStructPtr->vblankDma;
+ return FALSE;
+}
+
+static void VBCB_BT_Phase2FullScreenWave(void)
+{
+ BT_VBSyncOamAndPltt();
+ if (sTransitionStructPtr->vblankDma)
+ DmaCopy16(3, gScanlineEffectRegBuffers[0], gScanlineEffectRegBuffers[1], 320);
+}
+
+static void HBCB_BT_Phase2FullScreenWave(void)
+{
+ s16 offset = gScanlineEffectRegBuffers[1][REG_VCOUNT];
+
+ REG_BG1VOFS = offset;
+ REG_BG2VOFS = offset;
+ REG_BG3VOFS = offset;
+}
+
+#undef tTheta
+#undef tAmplitude
+#undef tDelayForFade
+#undef tStartFade
+
+#define tOffset data[1]
+#define tTheta data[2]
+
+static void BT_Phase2BlackWaveToRight(u8 taskId)
+{
+ while (sBT_Phase2BlackWaveToRightFuncs[gTasks[taskId].tState](&gTasks[taskId]));
+}
+
+static bool8 BT_Phase2BlackWaveToRight_Init(struct Task *task)
+{
+ u8 i;
+
+ BT_InitCtrlBlk();
+ ScanlineEffect_Clear();
+ sTransitionStructPtr->winIn = 0x3F;
+ sTransitionStructPtr->winOut = 0;
+ sTransitionStructPtr->win0H = 240;
+ sTransitionStructPtr->win0V = 160;
+ for (i = 0; i < 160; ++i)
+ gScanlineEffectRegBuffers[1][i] = 242;
+ SetVBlankCallback(VBCB_BT_Phase2BlackWaveToRight);
+ ++task->tState;
+ return TRUE;
+}
+
+static bool8 BT_Phase2BlackWaveToRight_UpdateWave(struct Task *task)
+{
+ u8 i, theta;
+ u16 *winVal;
+ bool8 nextFunc;
+
+ sTransitionStructPtr->vblankDma = FALSE;
+ winVal = gScanlineEffectRegBuffers[0];
+ theta = task->tTheta;
+ task->tTheta += 16;
+ task->tOffset += 8;
+ for (i = 0, nextFunc = TRUE; i < 160; ++i, theta += 4, ++winVal)
+ {
+ s16 left = task->tOffset + Sin(theta, 40);
+ if (left < 0)
+ left = 0;
+ if (left > 240)
+ left = 240;
+ *winVal = (left << 8) | (0xF1);
+ if (left < 240)
+ nextFunc = FALSE;
+ }
+ if (nextFunc)
+ ++task->tState;
+ ++sTransitionStructPtr->vblankDma;
+ return FALSE;
+}
+
+static bool8 BT_Phase2BlackWaveToRight_End(struct Task *task)
+{
+ DmaStop(0);
+ BT_BlendPalettesToBlack();
+ DestroyTask(FindTaskIdByFunc(BT_Phase2BlackWaveToRight));
+ return FALSE;
+}
+
+static void VBCB_BT_Phase2BlackWaveToRight(void)
+{
+ DmaStop(0);
+ BT_VBSyncOamAndPltt();
+ if (sTransitionStructPtr->vblankDma)
+ DmaCopy16(3, gScanlineEffectRegBuffers[0], gScanlineEffectRegBuffers[1], 320);
+ SetGpuReg(REG_OFFSET_WININ, sTransitionStructPtr->winIn);
+ SetGpuReg(REG_OFFSET_WINOUT, sTransitionStructPtr->winOut);
+ SetGpuReg(REG_OFFSET_WIN0V, sTransitionStructPtr->win0V);
+ DmaSet(0, gScanlineEffectRegBuffers[1], &REG_WIN0H, ((DMA_ENABLE | DMA_START_HBLANK | DMA_REPEAT | DMA_SRC_INC | DMA_DEST_FIXED) << 16) | 1);
+}
+
+#undef tOffset
+#undef tTheta
+
+static void BT_Phase2AntiClockwiseSpiral(u8 taskId)
+{
+ while (sBT_Phase2AntiClockwiseSpiralFuncs[gTasks[taskId].tState](&gTasks[taskId]));
+}
+
+#ifdef NONMATCHING
+static void sub_80D1F64(s16 a1, s16 a2, u8 a3)
+{
+ s16 i, j;
+
+ u8 theta = 0;
+ for (i = 320; i < 960; ++i)
+ gScanlineEffectRegBuffers[1][i] = 120;
+ for (i = 0; i < (a2 << 4); ++i, ++theta)
+ {
+ s16 res1, res2, res3, res4, diff, r8, r0;
+
+ // PROBLEM #1:
+ // (around line 50 in ASM)
+ // This part completely doesn't match.
+ // It's also not tail merge.
+ if ((theta >> 3) != ((theta + 1) >> 3))
+ {
+ r8 = (theta >> 3) + a1;
+ ++r8;
+ r0 = (theta >> 3) + a1;
+ }
+ else
+ {
+ r0 = (theta >> 3) + a1;
+ r8 = (theta >> 3) + a1;
+ }
+ res1 = 80 - Sin(theta, r0);
+ res2 = Cos(theta, r0) + 120;
+ res3 = 80 - Sin(theta + 1, r8);
+ res4 = Cos(theta + 1, r8) + 120;
+ if ((res1 >= 0 || res3 >= 0) && (res1 <= 159 || res3 <= 159))
+ {
+ if (res1 < 0)
+ res1 = 0;
+ if (res1 > 159)
+ res1 = 159;
+ if (res2 < 0)
+ res2 = 0;
+ if (res2 > 255)
+ res2 = 255;
+ if (res3 < 0)
+ res3 = 0;
+ if (res3 > 159)
+ res3 = 159;
+ if (res4 < 0)
+ res4 = 0;
+ if (res4 > 255)
+ res4 = 255;
+ diff = res3 - res1;
+ if (theta - 64 >= 0)
+ {
+ gScanlineEffectRegBuffers[1][res1 + 320] = res2;
+ if (diff)
+ {
+ s16 diff2 = res4 - res2;
+
+ if (diff2 < -1 && res2 > 1)
+ --res2;
+ else if (diff2 > 1 && res2 <= 254)
+ ++res2;
+ // PROBLEM #2:
+ // (around line 300 in ASM)
+ // The current version matched the control flow,
+ // but it looks too weird and some shift doesn't match
+
+ // functional equivalent:
+ // for (j = diff; j < 0; ++j)
+ // gScanlineEffectRegBuffers[1][res1 + j + 480] = res2;
+ // for (j = diff; j > 0; --j)
+ // gScanlineEffectRegBuffers[1][res1 + j + 480] = res2;
+ if ((j = diff) < 0)
+ do
+ gScanlineEffectRegBuffers[1][res1 + j + 320] = res2;
+ while (++j < 0);
+ else
+ while (j > 0)
+ {
+ gScanlineEffectRegBuffers[1][res1 + j + 320] = res2;
+ ++j;
+ }
+ }
+ }
+ else
+ {
+ gScanlineEffectRegBuffers[1][res1 + 480] = res2;
+ if (diff)
+ {
+ s16 diff2 = res4 - res2;
+
+ if (diff2 < -1 && res2 > 1)
+ --res2;
+ else if (diff2 > 1 && res2 <= 254)
+ ++res2;
+ // same as PROBLEM #2
+ for (j = diff; j < 0; ++j)
+ gScanlineEffectRegBuffers[1][res1 + j + 480] = res2;
+ for (j = diff; j > 0; --j)
+ gScanlineEffectRegBuffers[1][res1 + j + 480] = res2;
+ }
+ }
+ }
+ }
+ // PROBLEM #3: We need (a2 << 16) & 0x30000 here.
+ // Is it because the programmer declared a s32 var to
+ // hold the value of a2 and then cast the result to s16?
+ // Currently I have to write it explicitly.
+ // (around line 460 in ASM)
+ if (!a3 || !((a2 << 16) & 0x30000))
+ {
+ for (i = 0; i < 160; ++i)
+ gScanlineEffectRegBuffers[1][i * 2 + a3] = (gScanlineEffectRegBuffers[1][i + 320] << 8) | gScanlineEffectRegBuffers[1][i + 480];
+ }
+ else
+ {
+ s16 res = Sin(a2 * 16, a1 + a2 * 2);
+
+ switch (a2 / 4)
+ {
+ case 0:
+ if (res > 80)
+ res = 80;
+ // PROBLEM #4:
+ // (around line 550 in ASM)
+ // Case 0-3 are very similar, so it's very likely
+ // that they have the same problem.
+ // The code is definitely functional equivalent,
+ // but the vanilla game used some extra shifts and
+ // used unsigned comparison. Another difference is
+ // that I can't figure out a way to make gUnknown_83FA444[a2]
+ // happen outside the loop body.
+ // It seems that sTransitionStructPtr->data[2] need
+ // to be used in the first statement so that the
+ // struct pointer sTransitionStructPtr will be loaded
+ // early enough.
+ //
+ // Logically the generated code is following if + do-while structure.
+ // But it seems that it can only make the situation even worse.
+ /*
+ i = res;
+ if (i > 0)
+ {
+ // This happens before loop body.
+ s16 unk = gUnknown_83FA444[a2];
+
+ do
+ {
+ sTransitionStructPtr->data[2] = ((i * unk) >> 8) + 120;
+ if (sTransitionStructPtr->data[2] <= 255)
+ {
+ sTransitionStructPtr->bg123HOfs = 400 - i;
+ sTransitionStructPtr->data[10] = gScanlineEffectRegBuffers[1][400 - i];
+ if (gScanlineEffectRegBuffers[1][560 - i] < sTransitionStructPtr->data[2])
+ gScanlineEffectRegBuffers[1][560 - i] = 120;
+ else if (gScanlineEffectRegBuffers[1][400 - i] < sTransitionStructPtr->data[2])
+ gScanlineEffectRegBuffers[1][400 - i] = sTransitionStructPtr->data[2];
+ }
+ }
+ while (--i > 0);
+ }
+ */
+ for (i = res; i > 0; --i)
+ {
+ sTransitionStructPtr->data[2] = ((i * gUnknown_83FA444[a2]) >> 8) + 120;
+ if (sTransitionStructPtr->data[2] <= 255)
+ {
+ sTransitionStructPtr->bg123HOfs = 400 - i;
+ sTransitionStructPtr->data[10] = gScanlineEffectRegBuffers[1][400 - i];
+ if (gScanlineEffectRegBuffers[1][560 - i] < sTransitionStructPtr->data[2])
+ gScanlineEffectRegBuffers[1][560 - i] = 120;
+ else if (gScanlineEffectRegBuffers[1][400 - i] < sTransitionStructPtr->data[2])
+ gScanlineEffectRegBuffers[1][400 - i] = sTransitionStructPtr->data[2];
+ }
+ }
+ break;
+ case 1:
+ if (res > 80)
+ res = 80;
+ // same as PROBLEM #4
+ for (i = res; i > 0; --i)
+ {
+ s16 unkVal;
+
+ sTransitionStructPtr->data[2] = ((i * gUnknown_83FA444[a2]) >> 8) + 120;
+ if (sTransitionStructPtr->data[2] <= 255)
+ {
+ sTransitionStructPtr->bg123HOfs = 400 - i;
+ sTransitionStructPtr->data[10] = gScanlineEffectRegBuffers[1][400 - i];
+ if (gScanlineEffectRegBuffers[1][400 - i] < sTransitionStructPtr->data[2])
+ gScanlineEffectRegBuffers[1][400 - i] = sTransitionStructPtr->data[2];
+ }
+ }
+ break;
+ case 2:
+ if (res < -79)
+ res = -79;
+ // same as PROBLEM #4
+ for (i = res; i <= 0; ++i)
+ {
+ sTransitionStructPtr->data[2] = ((i * gUnknown_83FA444[a2]) >> 8) + 120;
+ if (sTransitionStructPtr->data[2] <= 255)
+ {
+ sTransitionStructPtr->bg123HOfs = 560 - i;
+ sTransitionStructPtr->data[10] = gScanlineEffectRegBuffers[1][560 - i];
+ if (gScanlineEffectRegBuffers[1][400 - i] >= sTransitionStructPtr->data[2])
+ gScanlineEffectRegBuffers[1][400 - i] = 120;
+ else if (gScanlineEffectRegBuffers[1][560 - i] > sTransitionStructPtr->data[2])
+ gScanlineEffectRegBuffers[1][560 - i] = sTransitionStructPtr->data[2];
+ }
+ }
+ break;
+ case 3:
+ if (res < -79)
+ res = -79;
+ // same as PROBLEM #4
+ for (i = res; i <= 0; ++i)
+ {
+ sTransitionStructPtr->data[2] = ((i * gUnknown_83FA444[a2]) >> 8) + 120;
+ if (sTransitionStructPtr->data[2] <= 255)
+ {
+ sTransitionStructPtr->bg123HOfs = 560 - i;
+ sTransitionStructPtr->data[10] = gScanlineEffectRegBuffers[1][560 - i];
+ if (gScanlineEffectRegBuffers[1][560 - i] > sTransitionStructPtr->data[2])
+ gScanlineEffectRegBuffers[1][560 - i] = sTransitionStructPtr->data[2];
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ for (i = 0; i < 160; ++i)
+ gScanlineEffectRegBuffers[1][2 * i + a3] = (gScanlineEffectRegBuffers[1][i + 320] << 8) | gScanlineEffectRegBuffers[1][i + 480];
+ }
+}
+#else
+NAKED
+static void sub_80D1F64(s16 a1, s16 a2, u8 a3)
+{
+ asm_unified("\n\
+ push {r4-r7,lr}\n\
+ mov r7, r10\n\
+ mov r6, r9\n\
+ mov r5, r8\n\
+ push {r5-r7}\n\
+ sub sp, 0x14\n\
+ lsls r0, 16\n\
+ lsrs r0, 16\n\
+ str r0, [sp]\n\
+ lsls r1, 16\n\
+ lsrs r5, r1, 16\n\
+ lsls r2, 24\n\
+ lsrs r2, 24\n\
+ str r2, [sp, 0x4]\n\
+ movs r0, 0\n\
+ mov r10, r0\n\
+ movs r1, 0xA0\n\
+ lsls r1, 17\n\
+ ldr r4, _080D1FD8 @ =gScanlineEffectRegBuffers + 0x780\n\
+ ldr r3, _080D1FDC @ =0x000003bf\n\
+ movs r2, 0x78\n\
+ _080D1F8E:\n\
+ asrs r0, r1, 16\n\
+ lsls r1, r0, 1\n\
+ adds r1, r4\n\
+ strh r2, [r1]\n\
+ adds r0, 0x1\n\
+ lsls r1, r0, 16\n\
+ asrs r0, r1, 16\n\
+ cmp r0, r3\n\
+ ble _080D1F8E\n\
+ lsls r0, r5, 16\n\
+ movs r1, 0\n\
+ mov r9, r1\n\
+ str r0, [sp, 0xC]\n\
+ cmp r0, 0\n\
+ bgt _080D1FAE\n\
+ b _080D221A\n\
+ _080D1FAE:\n\
+ mov r3, r10\n\
+ lsrs r2, r3, 3\n\
+ ldr r4, [sp]\n\
+ adds r0, r2, r4\n\
+ lsls r0, 16\n\
+ lsrs r3, r0, 16\n\
+ mov r0, r10\n\
+ adds r0, 0x1\n\
+ asrs r1, r0, 3\n\
+ str r0, [sp, 0x8]\n\
+ cmp r2, r1\n\
+ beq _080D1FE0\n\
+ lsls r1, r3, 16\n\
+ movs r6, 0x80\n\
+ lsls r6, 9\n\
+ adds r0, r1, r6\n\
+ lsrs r0, 16\n\
+ mov r8, r0\n\
+ adds r0, r1, 0\n\
+ b _080D1FE6\n\
+ .align 2, 0\n\
+ _080D1FD8: .4byte gScanlineEffectRegBuffers + 0x780\n\
+ _080D1FDC: .4byte 0x000003bf\n\
+ _080D1FE0:\n\
+ lsls r0, r3, 16\n\
+ lsrs r1, r0, 16\n\
+ mov r8, r1\n\
+ _080D1FE6:\n\
+ asrs r4, r0, 16\n\
+ mov r0, r10\n\
+ adds r1, r4, 0\n\
+ bl Sin\n\
+ movs r5, 0x50\n\
+ subs r0, r5, r0\n\
+ lsls r0, 16\n\
+ lsrs r2, r0, 16\n\
+ mov r0, r10\n\
+ adds r1, r4, 0\n\
+ str r2, [sp, 0x10]\n\
+ bl Cos\n\
+ adds r0, 0x78\n\
+ lsls r0, 16\n\
+ lsrs r7, r0, 16\n\
+ ldr r6, [sp, 0x8]\n\
+ mov r3, r8\n\
+ lsls r4, r3, 16\n\
+ asrs r4, 16\n\
+ adds r0, r6, 0\n\
+ adds r1, r4, 0\n\
+ bl Sin\n\
+ subs r5, r0\n\
+ lsls r5, 16\n\
+ lsrs r5, 16\n\
+ adds r0, r6, 0\n\
+ adds r1, r4, 0\n\
+ bl Cos\n\
+ adds r0, 0x78\n\
+ lsls r0, 16\n\
+ lsrs r3, r0, 16\n\
+ ldr r2, [sp, 0x10]\n\
+ lsls r0, r2, 16\n\
+ asrs r1, r0, 16\n\
+ cmp r1, 0\n\
+ bge _080D203E\n\
+ lsls r0, r5, 16\n\
+ cmp r0, 0\n\
+ bge _080D203E\n\
+ b _080D21F8\n\
+ _080D203E:\n\
+ cmp r1, 0x9F\n\
+ ble _080D204C\n\
+ lsls r0, r5, 16\n\
+ asrs r0, 16\n\
+ cmp r0, 0x9F\n\
+ ble _080D204C\n\
+ b _080D21F8\n\
+ _080D204C:\n\
+ cmp r1, 0\n\
+ bge _080D2052\n\
+ movs r2, 0\n\
+ _080D2052:\n\
+ lsls r0, r2, 16\n\
+ asrs r0, 16\n\
+ cmp r0, 0x9F\n\
+ ble _080D205C\n\
+ movs r2, 0x9F\n\
+ _080D205C:\n\
+ lsls r0, r7, 16\n\
+ cmp r0, 0\n\
+ bge _080D2064\n\
+ movs r7, 0\n\
+ _080D2064:\n\
+ lsls r0, r7, 16\n\
+ asrs r0, 16\n\
+ cmp r0, 0xFF\n\
+ ble _080D206E\n\
+ movs r7, 0xFF\n\
+ _080D206E:\n\
+ lsls r0, r5, 16\n\
+ cmp r0, 0\n\
+ bge _080D2076\n\
+ movs r5, 0\n\
+ _080D2076:\n\
+ lsls r0, r5, 16\n\
+ asrs r0, 16\n\
+ cmp r0, 0x9F\n\
+ ble _080D2080\n\
+ movs r5, 0x9F\n\
+ _080D2080:\n\
+ lsls r0, r3, 16\n\
+ cmp r0, 0\n\
+ bge _080D2088\n\
+ movs r3, 0\n\
+ _080D2088:\n\
+ lsls r0, r3, 16\n\
+ asrs r0, 16\n\
+ cmp r0, 0xFF\n\
+ ble _080D2092\n\
+ movs r3, 0xFF\n\
+ _080D2092:\n\
+ lsls r0, r5, 16\n\
+ asrs r0, 16\n\
+ lsls r1, r2, 16\n\
+ asrs r2, r1, 16\n\
+ subs r0, r2\n\
+ lsls r0, 16\n\
+ lsrs r5, r0, 16\n\
+ mov r0, r10\n\
+ subs r0, 0x40\n\
+ lsls r0, 24\n\
+ adds r6, r1, 0\n\
+ cmp r0, 0\n\
+ blt _080D2158\n\
+ movs r4, 0xA0\n\
+ lsls r4, 1\n\
+ adds r0, r2, r4\n\
+ lsls r0, 1\n\
+ ldr r1, _080D20E8 @ =gScanlineEffectRegBuffers + 0x780\n\
+ adds r0, r1\n\
+ strh r7, [r0]\n\
+ lsls r0, r5, 16\n\
+ adds r4, r0, 0\n\
+ cmp r4, 0\n\
+ bne _080D20C4\n\
+ b _080D21F8\n\
+ _080D20C4:\n\
+ lsls r0, r3, 16\n\
+ asrs r0, 16\n\
+ lsls r1, r7, 16\n\
+ asrs r2, r1, 16\n\
+ subs r0, r2\n\
+ lsls r0, 16\n\
+ lsrs r3, r0, 16\n\
+ asrs r0, 16\n\
+ mov r8, r0\n\
+ movs r0, 0x1\n\
+ negs r0, r0\n\
+ cmp r8, r0\n\
+ bge _080D20EC\n\
+ cmp r2, 0x1\n\
+ ble _080D20EC\n\
+ subs r0, r2, 0x1\n\
+ b _080D20FC\n\
+ .align 2, 0\n\
+ _080D20E8: .4byte gScanlineEffectRegBuffers + 0x780\n\
+ _080D20EC:\n\
+ lsls r0, r3, 16\n\
+ asrs r0, 16\n\
+ cmp r0, 0x1\n\
+ ble _080D2100\n\
+ asrs r0, r1, 16\n\
+ cmp r0, 0xFE\n\
+ bgt _080D2100\n\
+ adds r0, 0x1\n\
+ _080D20FC:\n\
+ lsls r0, 16\n\
+ lsrs r7, r0, 16\n\
+ _080D2100:\n\
+ adds r0, r4, 0\n\
+ asrs r1, r0, 16\n\
+ cmp r1, 0\n\
+ bge _080D212C\n\
+ asrs r2, r6, 16\n\
+ ldr r3, _080D2128 @ =gScanlineEffectRegBuffers + 0x780\n\
+ _080D210C:\n\
+ asrs r1, r0, 16\n\
+ adds r0, r2, r1\n\
+ movs r4, 0xA0\n\
+ lsls r4, 1\n\
+ adds r0, r4\n\
+ lsls r0, 1\n\
+ adds r0, r3\n\
+ strh r7, [r0]\n\
+ adds r1, 0x1\n\
+ lsls r0, r1, 16\n\
+ cmp r0, 0\n\
+ blt _080D210C\n\
+ b _080D21F8\n\
+ .align 2, 0\n\
+ _080D2128: .4byte gScanlineEffectRegBuffers + 0x780\n\
+ _080D212C:\n\
+ cmp r1, 0\n\
+ ble _080D21F8\n\
+ asrs r2, r6, 16\n\
+ ldr r3, _080D2154 @ =gScanlineEffectRegBuffers + 0x780\n\
+ _080D2134:\n\
+ lsls r1, r5, 16\n\
+ asrs r1, 16\n\
+ adds r0, r2, r1\n\
+ movs r6, 0xA0\n\
+ lsls r6, 1\n\
+ adds r0, r6\n\
+ lsls r0, 1\n\
+ adds r0, r3\n\
+ strh r7, [r0]\n\
+ subs r1, 0x1\n\
+ lsls r1, 16\n\
+ lsrs r5, r1, 16\n\
+ cmp r1, 0\n\
+ bgt _080D2134\n\
+ b _080D21F8\n\
+ .align 2, 0\n\
+ _080D2154: .4byte gScanlineEffectRegBuffers + 0x780\n\
+ _080D2158:\n\
+ movs r1, 0xF0\n\
+ lsls r1, 1\n\
+ adds r0, r2, r1\n\
+ lsls r0, 1\n\
+ ldr r2, _080D2190 @ =gScanlineEffectRegBuffers + 0x780\n\
+ adds r0, r2\n\
+ strh r7, [r0]\n\
+ lsls r0, r5, 16\n\
+ adds r4, r0, 0\n\
+ cmp r4, 0\n\
+ beq _080D21F8\n\
+ lsls r0, r3, 16\n\
+ asrs r0, 16\n\
+ lsls r1, r7, 16\n\
+ asrs r2, r1, 16\n\
+ subs r0, r2\n\
+ lsls r0, 16\n\
+ lsrs r3, r0, 16\n\
+ asrs r0, 16\n\
+ mov r8, r0\n\
+ movs r0, 0x1\n\
+ negs r0, r0\n\
+ cmp r8, r0\n\
+ bge _080D2194\n\
+ cmp r2, 0x1\n\
+ ble _080D2194\n\
+ subs r0, r2, 0x1\n\
+ b _080D21A4\n\
+ .align 2, 0\n\
+ _080D2190: .4byte gScanlineEffectRegBuffers + 0x780\n\
+ _080D2194:\n\
+ lsls r0, r3, 16\n\
+ asrs r0, 16\n\
+ cmp r0, 0x1\n\
+ ble _080D21A8\n\
+ asrs r0, r1, 16\n\
+ cmp r0, 0xFE\n\
+ bgt _080D21A8\n\
+ adds r0, 0x1\n\
+ _080D21A4:\n\
+ lsls r0, 16\n\
+ lsrs r7, r0, 16\n\
+ _080D21A8:\n\
+ adds r0, r4, 0\n\
+ asrs r1, r0, 16\n\
+ cmp r1, 0\n\
+ bge _080D21D4\n\
+ asrs r2, r6, 16\n\
+ ldr r3, _080D21D0 @ =gScanlineEffectRegBuffers + 0x780\n\
+ _080D21B4:\n\
+ asrs r1, r0, 16\n\
+ adds r0, r2, r1\n\
+ movs r4, 0xF0\n\
+ lsls r4, 1\n\
+ adds r0, r4\n\
+ lsls r0, 1\n\
+ adds r0, r3\n\
+ strh r7, [r0]\n\
+ adds r1, 0x1\n\
+ lsls r0, r1, 16\n\
+ cmp r0, 0\n\
+ blt _080D21B4\n\
+ b _080D21F8\n\
+ .align 2, 0\n\
+ _080D21D0: .4byte gScanlineEffectRegBuffers + 0x780\n\
+ _080D21D4:\n\
+ cmp r1, 0\n\
+ ble _080D21F8\n\
+ asrs r2, r6, 16\n\
+ ldr r3, _080D2270 @ =gScanlineEffectRegBuffers + 0x780\n\
+ _080D21DC:\n\
+ lsls r1, r5, 16\n\
+ asrs r1, 16\n\
+ adds r0, r2, r1\n\
+ movs r6, 0xF0\n\
+ lsls r6, 1\n\
+ adds r0, r6\n\
+ lsls r0, 1\n\
+ adds r0, r3\n\
+ strh r7, [r0]\n\
+ subs r1, 0x1\n\
+ lsls r1, 16\n\
+ lsrs r5, r1, 16\n\
+ cmp r1, 0\n\
+ bgt _080D21DC\n\
+ _080D21F8:\n\
+ mov r1, r9\n\
+ lsls r0, r1, 16\n\
+ movs r2, 0x80\n\
+ lsls r2, 9\n\
+ adds r0, r2\n\
+ ldr r3, [sp, 0x8]\n\
+ lsls r1, r3, 24\n\
+ lsrs r1, 24\n\
+ mov r10, r1\n\
+ lsrs r4, r0, 16\n\
+ mov r9, r4\n\
+ asrs r0, 16\n\
+ ldr r6, [sp, 0xC]\n\
+ asrs r1, r6, 12\n\
+ cmp r0, r1\n\
+ bge _080D221A\n\
+ b _080D1FAE\n\
+ _080D221A:\n\
+ ldr r0, [sp, 0x4]\n\
+ cmp r0, 0\n\
+ beq _080D222C\n\
+ movs r0, 0xC0\n\
+ lsls r0, 10\n\
+ ldr r1, [sp, 0xC]\n\
+ ands r0, r1\n\
+ cmp r0, 0\n\
+ bne _080D2274\n\
+ _080D222C:\n\
+ movs r2, 0\n\
+ mov r9, r2\n\
+ ldr r4, _080D2270 @ =gScanlineEffectRegBuffers + 0x780\n\
+ movs r5, 0xA0\n\
+ lsls r5, 1\n\
+ _080D2236:\n\
+ mov r3, r9\n\
+ lsls r1, r3, 16\n\
+ asrs r1, 16\n\
+ lsls r3, r1, 1\n\
+ ldr r6, [sp, 0x4]\n\
+ adds r3, r6\n\
+ lsls r3, 1\n\
+ adds r3, r4\n\
+ adds r0, r1, r5\n\
+ lsls r0, 1\n\
+ adds r0, r4\n\
+ ldrh r2, [r0]\n\
+ lsls r2, 8\n\
+ movs r6, 0xF0\n\
+ lsls r6, 1\n\
+ adds r0, r1, r6\n\
+ lsls r0, 1\n\
+ adds r0, r4\n\
+ ldrh r0, [r0]\n\
+ orrs r2, r0\n\
+ strh r2, [r3]\n\
+ adds r1, 0x1\n\
+ lsls r1, 16\n\
+ lsrs r0, r1, 16\n\
+ mov r9, r0\n\
+ asrs r1, 16\n\
+ cmp r1, 0x9F\n\
+ ble _080D2236\n\
+ b _080D251C\n\
+ .align 2, 0\n\
+ _080D2270: .4byte gScanlineEffectRegBuffers + 0x780\n\
+ _080D2274:\n\
+ ldr r1, [sp, 0xC]\n\
+ asrs r4, r1, 16\n\
+ lsls r0, r4, 20\n\
+ asrs r0, 16\n\
+ lsls r5, r4, 1\n\
+ ldr r2, [sp]\n\
+ lsls r1, r2, 16\n\
+ asrs r1, 16\n\
+ adds r1, r5\n\
+ lsls r1, 16\n\
+ asrs r1, 16\n\
+ bl Sin\n\
+ lsls r0, 16\n\
+ lsrs r2, r0, 16\n\
+ cmp r4, 0\n\
+ bge _080D2298\n\
+ adds r4, 0x3\n\
+ _080D2298:\n\
+ asrs r0, r4, 2\n\
+ cmp r0, 0x1\n\
+ beq _080D234C\n\
+ cmp r0, 0x1\n\
+ bgt _080D22A8\n\
+ cmp r0, 0\n\
+ beq _080D22B6\n\
+ b _080D24DA\n\
+ _080D22A8:\n\
+ cmp r0, 0x2\n\
+ bne _080D22AE\n\
+ b _080D23CC\n\
+ _080D22AE:\n\
+ cmp r0, 0x3\n\
+ bne _080D22B4\n\
+ b _080D2466\n\
+ _080D22B4:\n\
+ b _080D24DA\n\
+ _080D22B6:\n\
+ lsls r0, r2, 16\n\
+ asrs r0, 16\n\
+ cmp r0, 0x50\n\
+ ble _080D22C0\n\
+ movs r2, 0x50\n\
+ _080D22C0:\n\
+ mov r9, r2\n\
+ lsls r1, r2, 16\n\
+ cmp r1, 0\n\
+ bgt _080D22CA\n\
+ b _080D24DA\n\
+ _080D22CA:\n\
+ ldr r0, _080D2320 @ =gUnknown_83FA444\n\
+ adds r0, r5, r0\n\
+ movs r3, 0\n\
+ ldrsh r4, [r0, r3]\n\
+ ldr r6, _080D2324 @ =gScanlineEffectRegBuffers + 0x780\n\
+ _080D22D4:\n\
+ ldr r0, _080D2328 @ =sTransitionStructPtr\n\
+ ldr r5, [r0]\n\
+ asrs r2, r1, 16\n\
+ adds r0, r2, 0\n\
+ muls r0, r4\n\
+ asrs r0, 8\n\
+ adds r0, 0x78\n\
+ lsls r1, r0, 16\n\
+ lsrs r7, r1, 16\n\
+ strh r0, [r5, 0x28]\n\
+ lsls r1, r7, 16\n\
+ lsrs r0, r1, 16\n\
+ cmp r0, 0xFF\n\
+ bhi _080D2334\n\
+ movs r3, 0xC8\n\
+ lsls r3, 1\n\
+ adds r0, r3, 0\n\
+ subs r0, r2\n\
+ strh r0, [r5, 0x14]\n\
+ adds r0, r3, 0\n\
+ subs r0, r2\n\
+ lsls r0, 1\n\
+ adds r3, r0, r6\n\
+ ldrh r0, [r3]\n\
+ strh r0, [r5, 0x38]\n\
+ movs r0, 0x8C\n\
+ lsls r0, 2\n\
+ subs r0, r2\n\
+ lsls r0, 1\n\
+ adds r2, r0, r6\n\
+ ldrh r0, [r2]\n\
+ asrs r1, 16\n\
+ cmp r0, r1\n\
+ bge _080D232C\n\
+ movs r0, 0x78\n\
+ strh r0, [r2]\n\
+ b _080D2334\n\
+ .align 2, 0\n\
+ _080D2320: .4byte gUnknown_83FA444\n\
+ _080D2324: .4byte gScanlineEffectRegBuffers + 0x780\n\
+ _080D2328: .4byte sTransitionStructPtr\n\
+ _080D232C:\n\
+ ldrh r0, [r3]\n\
+ cmp r0, r1\n\
+ bge _080D2334\n\
+ strh r7, [r3]\n\
+ _080D2334:\n\
+ mov r1, r9\n\
+ lsls r0, r1, 16\n\
+ ldr r2, _080D2348 @ =0xffff0000\n\
+ adds r0, r2\n\
+ lsrs r0, 16\n\
+ mov r9, r0\n\
+ lsls r1, r0, 16\n\
+ cmp r1, 0\n\
+ bgt _080D22D4\n\
+ b _080D24DA\n\
+ .align 2, 0\n\
+ _080D2348: .4byte 0xffff0000\n\
+ _080D234C:\n\
+ lsls r0, r2, 16\n\
+ asrs r0, 16\n\
+ cmp r0, 0x50\n\
+ ble _080D2356\n\
+ movs r2, 0x50\n\
+ _080D2356:\n\
+ mov r9, r2\n\
+ lsls r1, r2, 16\n\
+ cmp r1, 0\n\
+ bgt _080D2360\n\
+ b _080D24DA\n\
+ _080D2360:\n\
+ ldr r0, _080D23BC @ =gUnknown_83FA444\n\
+ adds r0, r5, r0\n\
+ movs r3, 0\n\
+ ldrsh r4, [r0, r3]\n\
+ ldr r6, _080D23C0 @ =gScanlineEffectRegBuffers + 0x780\n\
+ _080D236A:\n\
+ ldr r0, _080D23C4 @ =sTransitionStructPtr\n\
+ ldr r3, [r0]\n\
+ asrs r2, r1, 16\n\
+ adds r0, r2, 0\n\
+ muls r0, r4\n\
+ asrs r0, 8\n\
+ adds r0, 0x78\n\
+ lsls r1, r0, 16\n\
+ lsrs r7, r1, 16\n\
+ strh r0, [r3, 0x28]\n\
+ lsls r5, r7, 16\n\
+ lsrs r0, r5, 16\n\
+ cmp r0, 0xFF\n\
+ bhi _080D23A6\n\
+ movs r1, 0xC8\n\
+ lsls r1, 1\n\
+ adds r0, r1, 0\n\
+ subs r0, r2\n\
+ strh r0, [r3, 0x14]\n\
+ adds r0, r1, 0\n\
+ subs r0, r2\n\
+ lsls r0, 1\n\
+ adds r2, r0, r6\n\
+ ldrh r0, [r2]\n\
+ strh r0, [r3, 0x38]\n\
+ ldrh r1, [r2]\n\
+ asrs r0, r5, 16\n\
+ cmp r1, r0\n\
+ bge _080D23A6\n\
+ strh r7, [r2]\n\
+ _080D23A6:\n\
+ mov r2, r9\n\
+ lsls r0, r2, 16\n\
+ ldr r3, _080D23C8 @ =0xffff0000\n\
+ adds r0, r3\n\
+ lsrs r0, 16\n\
+ mov r9, r0\n\
+ lsls r1, r0, 16\n\
+ cmp r1, 0\n\
+ bgt _080D236A\n\
+ b _080D24DA\n\
+ .align 2, 0\n\
+ _080D23BC: .4byte gUnknown_83FA444\n\
+ _080D23C0: .4byte gScanlineEffectRegBuffers + 0x780\n\
+ _080D23C4: .4byte sTransitionStructPtr\n\
+ _080D23C8: .4byte 0xffff0000\n\
+ _080D23CC:\n\
+ lsls r0, r2, 16\n\
+ asrs r0, 16\n\
+ movs r1, 0x4F\n\
+ negs r1, r1\n\
+ cmp r0, r1\n\
+ bge _080D23DA\n\
+ ldr r2, _080D2438 @ =0x0000ffb1\n\
+ _080D23DA:\n\
+ mov r9, r2\n\
+ lsls r1, r2, 16\n\
+ cmp r1, 0\n\
+ bgt _080D24DA\n\
+ ldr r0, _080D243C @ =gUnknown_83FA444\n\
+ adds r0, r5, r0\n\
+ movs r6, 0\n\
+ ldrsh r4, [r0, r6]\n\
+ ldr r6, _080D2440 @ =gScanlineEffectRegBuffers + 0x780\n\
+ _080D23EC:\n\
+ ldr r0, _080D2444 @ =sTransitionStructPtr\n\
+ ldr r5, [r0]\n\
+ asrs r2, r1, 16\n\
+ adds r0, r2, 0\n\
+ muls r0, r4\n\
+ asrs r0, 8\n\
+ adds r0, 0x78\n\
+ lsls r1, r0, 16\n\
+ lsrs r7, r1, 16\n\
+ strh r0, [r5, 0x28]\n\
+ lsls r1, r7, 16\n\
+ lsrs r0, r1, 16\n\
+ cmp r0, 0xFF\n\
+ bhi _080D2450\n\
+ movs r3, 0x8C\n\
+ lsls r3, 2\n\
+ adds r0, r3, 0\n\
+ subs r0, r2\n\
+ strh r0, [r5, 0x14]\n\
+ adds r0, r3, 0\n\
+ subs r0, r2\n\
+ lsls r0, 1\n\
+ adds r3, r0, r6\n\
+ ldrh r0, [r3]\n\
+ strh r0, [r5, 0x38]\n\
+ movs r0, 0xC8\n\
+ lsls r0, 1\n\
+ subs r0, r2\n\
+ lsls r0, 1\n\
+ adds r2, r0, r6\n\
+ ldrh r0, [r2]\n\
+ asrs r1, 16\n\
+ cmp r0, r1\n\
+ blt _080D2448\n\
+ movs r0, 0x78\n\
+ strh r0, [r2]\n\
+ b _080D2450\n\
+ .align 2, 0\n\
+ _080D2438: .4byte 0x0000ffb1\n\
+ _080D243C: .4byte gUnknown_83FA444\n\
+ _080D2440: .4byte gScanlineEffectRegBuffers + 0x780\n\
+ _080D2444: .4byte sTransitionStructPtr\n\
+ _080D2448:\n\
+ ldrh r0, [r3]\n\
+ cmp r0, r1\n\
+ ble _080D2450\n\
+ strh r7, [r3]\n\
+ _080D2450:\n\
+ mov r1, r9\n\
+ lsls r0, r1, 16\n\
+ movs r2, 0x80\n\
+ lsls r2, 9\n\
+ adds r0, r2\n\
+ lsrs r0, 16\n\
+ mov r9, r0\n\
+ lsls r1, r0, 16\n\
+ cmp r1, 0\n\
+ ble _080D23EC\n\
+ b _080D24DA\n\
+ _080D2466:\n\
+ lsls r0, r2, 16\n\
+ asrs r0, 16\n\
+ movs r1, 0x4F\n\
+ negs r1, r1\n\
+ cmp r0, r1\n\
+ bge _080D2474\n\
+ ldr r2, _080D252C @ =0x0000ffb1\n\
+ _080D2474:\n\
+ mov r9, r2\n\
+ lsls r1, r2, 16\n\
+ cmp r1, 0\n\
+ bgt _080D24DA\n\
+ ldr r0, _080D2530 @ =gUnknown_83FA444\n\
+ adds r0, r5, r0\n\
+ movs r3, 0\n\
+ ldrsh r4, [r0, r3]\n\
+ ldr r6, _080D2534 @ =sTransitionStructPtr\n\
+ mov r8, r6\n\
+ ldr r6, _080D2538 @ =gScanlineEffectRegBuffers + 0x780\n\
+ _080D248A:\n\
+ mov r0, r8\n\
+ ldr r3, [r0]\n\
+ asrs r2, r1, 16\n\
+ adds r0, r2, 0\n\
+ muls r0, r4\n\
+ asrs r0, 8\n\
+ adds r0, 0x78\n\
+ lsls r1, r0, 16\n\
+ lsrs r7, r1, 16\n\
+ strh r0, [r3, 0x28]\n\
+ lsls r5, r7, 16\n\
+ lsrs r0, r5, 16\n\
+ cmp r0, 0xFF\n\
+ bhi _080D24C6\n\
+ movs r1, 0x8C\n\
+ lsls r1, 2\n\
+ adds r0, r1, 0\n\
+ subs r0, r2\n\
+ strh r0, [r3, 0x14]\n\
+ adds r0, r1, 0\n\
+ subs r0, r2\n\
+ lsls r0, 1\n\
+ adds r2, r0, r6\n\
+ ldrh r0, [r2]\n\
+ strh r0, [r3, 0x38]\n\
+ ldrh r1, [r2]\n\
+ asrs r0, r5, 16\n\
+ cmp r1, r0\n\
+ ble _080D24C6\n\
+ strh r7, [r2]\n\
+ _080D24C6:\n\
+ mov r2, r9\n\
+ lsls r0, r2, 16\n\
+ movs r3, 0x80\n\
+ lsls r3, 9\n\
+ adds r0, r3\n\
+ lsrs r0, 16\n\
+ mov r9, r0\n\
+ lsls r1, r0, 16\n\
+ cmp r1, 0\n\
+ ble _080D248A\n\
+ _080D24DA:\n\
+ movs r4, 0\n\
+ mov r9, r4\n\
+ ldr r4, _080D2538 @ =gScanlineEffectRegBuffers + 0x780\n\
+ movs r5, 0xA0\n\
+ lsls r5, 1\n\
+ _080D24E4:\n\
+ mov r6, r9\n\
+ lsls r1, r6, 16\n\
+ asrs r1, 16\n\
+ lsls r3, r1, 1\n\
+ ldr r0, [sp, 0x4]\n\
+ adds r3, r0\n\
+ lsls r3, 1\n\
+ adds r3, r4\n\
+ adds r0, r1, r5\n\
+ lsls r0, 1\n\
+ adds r0, r4\n\
+ ldrh r2, [r0]\n\
+ lsls r2, 8\n\
+ movs r6, 0xF0\n\
+ lsls r6, 1\n\
+ adds r0, r1, r6\n\
+ lsls r0, 1\n\
+ adds r0, r4\n\
+ ldrh r0, [r0]\n\
+ orrs r2, r0\n\
+ strh r2, [r3]\n\
+ adds r1, 0x1\n\
+ lsls r1, 16\n\
+ lsrs r0, r1, 16\n\
+ mov r9, r0\n\
+ asrs r1, 16\n\
+ cmp r1, 0x9F\n\
+ ble _080D24E4\n\
+ _080D251C:\n\
+ add sp, 0x14\n\
+ pop {r3-r5}\n\
+ mov r8, r3\n\
+ mov r9, r4\n\
+ mov r10, r5\n\
+ pop {r4-r7}\n\
+ pop {r0}\n\
+ bx r0\n\
+ .align 2, 0\n\
+ _080D252C: .4byte 0x0000ffb1\n\
+ _080D2530: .4byte gUnknown_83FA444\n\
+ _080D2534: .4byte sTransitionStructPtr\n\
+ _080D2538: .4byte gScanlineEffectRegBuffers + 0x780\n\
+ ");
+}
+#endif
+
+static bool8 BT_Phase2AntiClockwiseSpiral_Init(struct Task *task)
+{
+ BT_InitCtrlBlk();
+ ScanlineEffect_Clear();
+ sTransitionStructPtr->winIn = 0;
+ sTransitionStructPtr->winOut = 0x3F;
+ sTransitionStructPtr->win0H = 0x7878;
+ sTransitionStructPtr->win0V = 0x3070;
+ sTransitionStructPtr->win1V = 0x1090;
+ sTransitionStructPtr->counter = 0;
+ sub_80D1F64(0, 0, FALSE);
+ sub_80D1F64(0, 0, TRUE);
+ DmaCopy16(3, gScanlineEffectRegBuffers[1], gScanlineEffectRegBuffers[0], 640);
+ SetVBlankCallback(VBCB_BT_Phase2AntiClockwiseBlackFade);
+ ++task->tState;
+ task->data[1] = 0;
+ task->data[2] = 0;
+ return FALSE;
+}
+
+static bool8 BT_Phase2AntiClockwiseSpiral_Update(struct Task *task)
+{
+ s16 v0, v1;
+
+ sub_80D1F64(task->data[2], task->data[1], TRUE);
+ sTransitionStructPtr->vblankDma |= TRUE;
+ if (++task->data[1] == 17)
+ {
+ sub_80D1F64(task->data[2], 16, FALSE);
+ v0 = 48 - task->data[2];
+ if (v0 < 0)
+ v0 = 0;
+ v1 = task->data[2] + 112;
+ if (v1 > 255)
+ v1 = 255;
+ sTransitionStructPtr->win0V = v0 | v1;
+ task->data[2] += 32;
+ task->data[1] = 0;
+ sub_80D1F64(task->data[2], 0, TRUE);
+ v0 = 48 - task->data[2];
+ if (v0 < 0)
+ v0 = 0;
+ v1 = task->data[2] + 112;
+ if (v1 > 255)
+ v1 = 255;
+ sTransitionStructPtr->win1V = v0 | v1;
+ sTransitionStructPtr->vblankDma |= TRUE;
+ if (task->data[2] > 159)
+ {
+ sTransitionStructPtr->counter = 1;
+ BT_BlendPalettesToBlack();
+ }
+ }
+ return FALSE;
+}
+
+static void VBCB_BT_Phase2AntiClockwiseBlackFade(void)
+{
+ DmaStop(0);
+ BT_VBSyncOamAndPltt();
+ if (sTransitionStructPtr->counter)
+ {
+ DestroyTask(FindTaskIdByFunc(BT_Phase2AntiClockwiseSpiral));
+ }
+ else
+ {
+ if (sTransitionStructPtr->vblankDma)
+ {
+ DmaCopy16(3, gScanlineEffectRegBuffers[1], gScanlineEffectRegBuffers[0], 640);
+ sTransitionStructPtr->vblankDma = FALSE;
+ }
+ SetGpuReg(REG_OFFSET_WININ, sTransitionStructPtr->winIn);
+ SetGpuReg(REG_OFFSET_WINOUT, sTransitionStructPtr->winOut);
+ SetGpuReg(REG_OFFSET_WIN0V, sTransitionStructPtr->win0V);
+ SetGpuReg(REG_OFFSET_WIN1V, sTransitionStructPtr->win1V);
+ SetGpuReg(REG_OFFSET_WIN0H, gScanlineEffectRegBuffers[0][0]);
+ SetGpuReg(REG_OFFSET_WIN1H, gScanlineEffectRegBuffers[0][1]);
+ DmaSet(0, gScanlineEffectRegBuffers[0], &REG_WIN0H, ((DMA_ENABLE | DMA_START_HBLANK | DMA_REPEAT | DMA_32BIT | DMA_SRC_INC | DMA_DEST_FIXED) << 16) | 1);
+ }
+}
+
+#define tTheta data[1]
+#define tbg0HOfsOpponent data[2]
+#define tbg0HOfsPlayer data[3]
+#define tCounter data[3]
+#define tHalfBandwidth data[4]
+#define tOpponentSpriteId data[13]
+#define tPlayerSpriteId data[14]
+#define tWhichMugshot data[15]
+
+#define spState data[0]
+#define spSpeed data[1]
+#define spAbsAcc data[2]
+#define sphasSlideFinished data[6]
+#define spOpponentOrPlayer data[7]
+
+static void BT_Phase2StartLoreleiMugshot(u8 taskId)
+{
+ gTasks[taskId].tWhichMugshot = MUGSHOT_LORELEI;
+ BT_Phase2Mugshot(taskId);
+}
+
+static void BT_Phase2StartBrunoMugshot(u8 taskId)
+{
+ gTasks[taskId].tWhichMugshot = MUGSHOT_BRUNO;
+ BT_Phase2Mugshot(taskId);
+}
+
+static void BT_Phase2StartAgathaMugshot(u8 taskId)
+{
+ gTasks[taskId].tWhichMugshot = MUGSHOT_AGATHA;
+ BT_Phase2Mugshot(taskId);
+}
+
+static void BT_Phase2StartLanceMugshot(u8 taskId)
+{
+ gTasks[taskId].tWhichMugshot = MUGSHOT_LANCE;
+ BT_Phase2Mugshot(taskId);
+}
+
+static void BT_Phase2StartBlueMugshot(u8 taskId)
+{
+ gTasks[taskId].tWhichMugshot = MUGSHOT_BLUE;
+ BT_Phase2Mugshot(taskId);
+}
+
+static void BT_Phase2Mugshot(u8 taskId)
+{
+ while (sBT_Phase2MugshotFuncs[gTasks[taskId].tState](&gTasks[taskId]));
+}
+
+static bool8 BT_Phase2Mugshot_Init(struct Task *task)
+{
+ u8 i;
+
+ BT_InitCtrlBlk();
+ ScanlineEffect_Clear();
+ BT_Phase2Mugshots_CreateSprites(task);
+ task->tTheta = 0;
+ task->tbg0HOfsOpponent = 1;
+ task->tbg0HOfsPlayer = 239;
+ sTransitionStructPtr->winIn = 0x3F;
+ sTransitionStructPtr->winOut = 0x3E;
+ sTransitionStructPtr->win0V = 160;
+ for (i = 0; i < 160; ++i)
+ gScanlineEffectRegBuffers[1][i] = 0xF0F1;
+ SetVBlankCallback(VBCB_BT_Phase2Mugshot1_Slide);
+ ++task->tState;
+ return FALSE;
+}
+
+static bool8 BT_Phase2Mugshot_LoadGfx(struct Task *task)
+{
+ s16 i, j;
+ u16 *tilemapAddr, *tilesetAddr;
+ const u16 *mugshotsMap = sVsBarTilemap;
+
+ BT_GetBg0TilemapAndTilesetBase(&tilemapAddr, &tilesetAddr);
+ CpuSet(sVsBarTileset, tilesetAddr, 0xF0);
+ LoadPalette(sVsBarOpponentPalettes[task->tWhichMugshot], 0xF0, 0x20);
+ LoadPalette(sVsBarPlayerPalettes[gSaveBlock2Ptr->playerGender], 0xFA, 0xC);
+ for (i = 0; i < 20; ++i)
+ for (j = 0; j < 32; ++j, ++mugshotsMap)
+ tilemapAddr[i * 32 + j] = *mugshotsMap | 0xF000; // use palette #15
+ EnableInterrupts(INTR_FLAG_HBLANK);
+ SetHBlankCallback(HBCB_BT_Phase2Mugshot);
+ ++task->tState;
+ return FALSE;
+}
+
+static bool8 BT_Phase2Mugshot_VsBarsSlideIn(struct Task *task)
+{
+ u8 i, theta;
+ u16 *winVal;
+ s16 value;
+ s32 mergedBg0hOfs;
+
+ sTransitionStructPtr->vblankDma = FALSE;
+
+ winVal = gScanlineEffectRegBuffers[0];
+ theta = task->tTheta;
+ task->tTheta += 0x10;
+ for (i = 0; i < 80; ++i, ++winVal, theta += 0x10)
+ {
+ value = task->tbg0HOfsOpponent + Sin(theta, 0x10);
+ if (value < 0)
+ value = 1;
+ if (value > 0xF0)
+ value = 0xF0;
+ *winVal = value;
+ }
+ for (; i < 160; ++i, ++winVal, theta += 0x10)
+ {
+ value = task->tCounter - Sin(theta, 0x10);
+ if (value < 0)
+ value = 0;
+ if (value > 0xEF)
+ value = 0xEF;
+ *winVal = (value << 8) | (0xF0);
+ }
+ task->tbg0HOfsOpponent += 8;
+ task->tCounter -= 8;
+ if (task->tbg0HOfsOpponent > 0xF0)
+ task->tbg0HOfsOpponent = 0xF0;
+ if (task->tCounter < 0)
+ task->tCounter = 0;
+ mergedBg0hOfs = *(s32 *)(&task->tbg0HOfsOpponent);
+ if (mergedBg0hOfs == 0x00F0)
+ ++task->tState;
+ sTransitionStructPtr->bg0HOfsOpponent -= 8;
+ sTransitionStructPtr->bg0HOfsPlayer += 8;
+ ++sTransitionStructPtr->vblankDma;
+ return FALSE;
+}
+
+static bool8 BT_Phase2Mugshot_StartSpriteSlide(struct Task *task)
+{
+ u8 i;
+ u16 *winVal;
+
+ sTransitionStructPtr->vblankDma = FALSE;
+ for (i = 0, winVal = gScanlineEffectRegBuffers[0]; i < 160; ++i, ++winVal)
+ *winVal = 0xF0;
+ ++task->tState;
+ task->tTheta = 0;
+ task->tbg0HOfsOpponent = 0;
+ task->tbg0HOfsPlayer = 0;
+ sTransitionStructPtr->bg0HOfsOpponent -= 8;
+ sTransitionStructPtr->bg0HOfsPlayer += 8;
+ BT_SetSpriteAsOpponentOrPlayer(task->tOpponentSpriteId, FALSE);
+ BT_SetSpriteAsOpponentOrPlayer(task->tPlayerSpriteId, TRUE);
+ BT_StartSpriteSlide(task->tOpponentSpriteId);
+ PlaySE(SE_C_MAKU_U);
+ ++sTransitionStructPtr->vblankDma;
+ return FALSE;
+}
+
+static bool8 BT_Phase2Mugshot_WaitForOpponentInPlace(struct Task *task)
+{
+ sTransitionStructPtr->bg0HOfsOpponent -= 8;
+ sTransitionStructPtr->bg0HOfsPlayer += 8;
+ if (BT_IsSpriteSlideFinished(task->tOpponentSpriteId))
+ {
+ ++task->tState;
+ BT_StartSpriteSlide(task->tPlayerSpriteId);
+ }
+ return FALSE;
+}
+
+static bool8 BT_Phase2Mugshot_WaitForPlayerInPlace(struct Task *task)
+{
+ sTransitionStructPtr->bg0HOfsOpponent -= 8;
+ sTransitionStructPtr->bg0HOfsPlayer += 8;
+ if (BT_IsSpriteSlideFinished(task->tPlayerSpriteId))
+ {
+ sTransitionStructPtr->vblankDma = FALSE;
+ SetVBlankCallback(NULL);
+ DmaStop(0);
+ memset(gScanlineEffectRegBuffers[0], 0, 320);
+ memset(gScanlineEffectRegBuffers[1], 0, 320);
+ SetGpuReg(REG_OFFSET_WIN0H, 0xF0);
+ SetGpuReg(REG_OFFSET_BLDY, 0);
+ ++task->tState;
+ task->tCounter = 0;
+ task->tHalfBandwidth = 0;
+ sTransitionStructPtr->bldCnt = BLDCNT_TGT1_BG0 | BLDCNT_TGT1_BG1 | BLDCNT_TGT1_BG2 | BLDCNT_TGT1_BG3 | BLDCNT_TGT1_OBJ | BLDCNT_TGT1_BD | BLDCNT_EFFECT_LIGHTEN;
+ SetVBlankCallback(VBCB_BT_Phase2Mugshot2_WhiteFade);
+ }
+ return FALSE;
+}
+
+static bool8 BT_Phase2Mugshot_ExpandWhiteBand(struct Task *task)
+{
+ bool32 nextFunc;
+
+ sTransitionStructPtr->vblankDma = FALSE;
+ nextFunc = TRUE;
+ sTransitionStructPtr->bg0HOfsOpponent -= 8;
+ sTransitionStructPtr->bg0HOfsPlayer += 8;
+ if (task->tHalfBandwidth < 80)
+ task->tHalfBandwidth += 2;
+ if (task->tHalfBandwidth > 80)
+ task->tHalfBandwidth = 80;
+ if (++task->tCounter & 1)
+ {
+ s16 i;
+
+ for (i = 0, nextFunc = FALSE; i <= task->tHalfBandwidth; ++i)
+ {
+ s16 y1 = 80 - i;
+ s16 y2 = 80 + i;
+
+ if (gScanlineEffectRegBuffers[0][y1] <= 15)
+ {
+ nextFunc = TRUE;
+ ++gScanlineEffectRegBuffers[0][y1];
+ }
+ if (gScanlineEffectRegBuffers[0][y2] <= 15)
+ {
+ nextFunc = TRUE;
+ ++gScanlineEffectRegBuffers[0][y2];
+ }
+ }
+ }
+ if (task->tHalfBandwidth == 80 && !nextFunc)
+ ++task->tState;
+ ++sTransitionStructPtr->vblankDma;
+ return FALSE;
+}
+
+static bool8 BT_Phase2Mugshot_StartBlackFade(struct Task *task)
+{
+ sTransitionStructPtr->vblankDma = FALSE;
+ BlendPalettes(0xFFFFFFFF, 0x10, RGB_WHITE);
+ sTransitionStructPtr->bldCnt = BLDCNT_TGT1_BG0 | BLDCNT_TGT1_BG1 | BLDCNT_TGT1_BG2 | BLDCNT_TGT1_BG3 | BLDCNT_TGT1_OBJ | BLDCNT_TGT1_BD | BLDCNT_EFFECT_DARKEN;
+ task->tCounter = 0;
+ ++task->tState;
+ return TRUE;
+}
+
+static bool8 BT_Phase2Mugshot_WaitForBlackFade(struct Task *task)
+{
+ sTransitionStructPtr->vblankDma = FALSE;
+ ++task->tCounter;
+ memset(gScanlineEffectRegBuffers[0], task->tCounter, 320);
+ if (task->tCounter > 15)
+ ++task->tState;
+ ++sTransitionStructPtr->vblankDma;
+ return FALSE;
+}
+
+static bool8 BT_Phase2Mugshot_End(struct Task *task)
+{
+ DmaStop(0);
+ BT_BlendPalettesToBlack();
+ DestroyTask(FindTaskIdByFunc(task->func));
+ return FALSE;
+}
+
+static void VBCB_BT_Phase2Mugshot1_Slide(void)
+{
+ DmaStop(0);
+ BT_VBSyncOamAndPltt();
+ if (sTransitionStructPtr->vblankDma)
+ DmaCopy16(3, gScanlineEffectRegBuffers[0], gScanlineEffectRegBuffers[1], 320);
+ SetGpuReg(REG_OFFSET_BG0VOFS, sTransitionStructPtr->bg0VOfs);
+ SetGpuReg(REG_OFFSET_WININ, sTransitionStructPtr->winIn);
+ SetGpuReg(REG_OFFSET_WINOUT, sTransitionStructPtr->winOut);
+ SetGpuReg(REG_OFFSET_WIN0V, sTransitionStructPtr->win0V);
+ DmaSet(0, gScanlineEffectRegBuffers[1], &REG_WIN0H, ((DMA_ENABLE | DMA_START_HBLANK | DMA_REPEAT | DMA_SRC_INC | DMA_DEST_FIXED) << 16) | 1);
+}
+
+static void VBCB_BT_Phase2Mugshot2_WhiteFade(void)
+{
+ DmaStop(0);
+ BT_VBSyncOamAndPltt();
+ if (sTransitionStructPtr->vblankDma)
+ DmaCopy16(3, gScanlineEffectRegBuffers[0], gScanlineEffectRegBuffers[1], 320);
+ SetGpuReg(REG_OFFSET_BLDCNT, sTransitionStructPtr->bldCnt);
+ DmaSet(0, gScanlineEffectRegBuffers[1], &REG_BLDY, ((DMA_ENABLE | DMA_START_HBLANK | DMA_REPEAT | DMA_SRC_INC | DMA_DEST_FIXED) << 16) | 1);
+}
+
+static void HBCB_BT_Phase2Mugshot(void)
+{
+ if (REG_VCOUNT < 80)
+ REG_BG0HOFS = sTransitionStructPtr->bg0HOfsOpponent;
+ else
+ REG_BG0HOFS = sTransitionStructPtr->bg0HOfsPlayer;
+}
+
+
+static void BT_Phase2Mugshots_CreateSprites(struct Task *task)
+{
+ struct Sprite *opponentSprite, *playerSprite;
+ s16 mugshotId;
+
+ gReservedSpritePaletteCount = 10;
+ mugshotId = task->tWhichMugshot;
+ task->tOpponentSpriteId = CreateTrainerSprite(sMugshotsTrainerPicIDsTable[mugshotId], sMugshotsOpponentCoords[mugshotId][0] - 32, sMugshotsOpponentCoords[mugshotId][1] + 42, 0, gDecompressionBuffer);
+ task->tPlayerSpriteId = CreateTrainerSprite(PlayerGenderToFrontTrainerPicId_Debug(gSaveBlock2Ptr->playerGender, TRUE), 272, 106, 0, gDecompressionBuffer);
+ gReservedSpritePaletteCount = 12;
+ opponentSprite = &gSprites[task->tOpponentSpriteId];
+ playerSprite = &gSprites[task->tPlayerSpriteId];
+ opponentSprite->callback = SpriteCB_BT_Phase2Mugshots;
+ playerSprite->callback = SpriteCB_BT_Phase2Mugshots;
+ opponentSprite->oam.affineMode = 3;
+ playerSprite->oam.affineMode = 3;
+ opponentSprite->oam.matrixNum = AllocOamMatrix();
+ playerSprite->oam.matrixNum = AllocOamMatrix();
+ opponentSprite->oam.shape = 1;
+ playerSprite->oam.shape = 1;
+ opponentSprite->oam.size = 3;
+ playerSprite->oam.size = 3;
+ CalcCenterToCornerVec(opponentSprite, 1, 3, 3);
+ CalcCenterToCornerVec(playerSprite, 1, 3, 3);
+ SetOamMatrixRotationScaling(opponentSprite->oam.matrixNum, sMugshotsOpponentRotationScales[mugshotId][0], sMugshotsOpponentRotationScales[mugshotId][1], 0);
+ SetOamMatrixRotationScaling(playerSprite->oam.matrixNum, -512, 512, 0);
+}
+
+static void SpriteCB_BT_Phase2Mugshots(struct Sprite *sprite)
+{
+ while (sBT_Phase2MugshotSpriteFuncs[sprite->spState](sprite));
+}
+
+static bool8 BT_Phase2MugshotsSpriteFuncs_Wait(struct Sprite *sprite)
+{
+ return FALSE;
+}
+
+static bool8 BT_Phase2MugshotsSpriteFuncs_InitParams(struct Sprite *sprite)
+{
+ s16 arr0[2];
+ s16 arr1[2];
+
+ memcpy(arr0, sMugShotSlideVelocity, sizeof(sMugShotSlideVelocity));
+ memcpy(arr1, sMugShotSlideDeceleration, sizeof(sMugShotSlideDeceleration));
+ ++sprite->spState;
+ sprite->spSpeed = arr0[sprite->spOpponentOrPlayer];
+ sprite->spAbsAcc = arr1[sprite->spOpponentOrPlayer];
+ return TRUE;
+}
+
+static bool8 BT_Phase2MugshotsSpriteFuncs_SlideSpriteIn(struct Sprite *sprite)
+{
+ sprite->pos1.x += sprite->spSpeed;
+ if (sprite->spOpponentOrPlayer && sprite->pos1.x < 133)
+ ++sprite->spState;
+ else if (!sprite->spOpponentOrPlayer && sprite->pos1.x > 103)
+ ++sprite->spState;
+ return FALSE;
+}
+
+static bool8 BT_Phase2MugshotsSpriteFuncs_DecelerateSprite(struct Sprite *sprite)
+{
+ sprite->spSpeed += sprite->spAbsAcc;
+ sprite->pos1.x += sprite->spSpeed;
+ if (sprite->spSpeed == 0)
+ {
+ ++sprite->spState;
+ sprite->spAbsAcc = -sprite->spAbsAcc;
+ sprite->sphasSlideFinished = 1;
+ }
+ return FALSE;
+}
+
+// not used
+static bool8 BT_Phase2MugshotsSpriteFuncs_DecelerateSprite2(struct Sprite *sprite)
+{
+ sprite->spSpeed += sprite->spAbsAcc;
+ sprite->pos1.x += sprite->spSpeed;
+ if (sprite->pos1.x < -31 || sprite->pos1.x > 271)
+ ++sprite->spState;
+ return FALSE;
+}
+
+static void BT_SetSpriteAsOpponentOrPlayer(s16 spriteId, bool16 value)
+{
+ gSprites[spriteId].spOpponentOrPlayer = value;
+}
+
+static void BT_StartSpriteSlide(s16 spriteId)
+{
+ ++gSprites[spriteId].spState;
+}
+
+static s16 BT_IsSpriteSlideFinished(s16 spriteId)
+{
+ return gSprites[spriteId].sphasSlideFinished;
+}
+
+#undef tTheta
+#undef tbg0HOfsOpponent
+#undef tbg0HOfsPlayer
+#undef tCounter
+#undef tHalfBandwidth
+#undef tOpponentSpriteId
+#undef tPlayerSpriteId
+#undef tWhichMugshot
+
+#undef spState
+#undef spSpeed
+#undef spAbsAcc
+#undef sphasSlideFinished
+#undef spOpponentOrPlayer
+
+#define tSpeed data[1]
+#define tAcc data[2]
+#define tJerk data[3]
+
+static void BT_Phase2SlicedScreen(u8 taskId)
+{
+ while (sBT_Phase2SlicedScreenFuncs[gTasks[taskId].tState](&gTasks[taskId]));
+}
+
+static bool8 BT_Phase2SlicedScreen_Init(struct Task *task)
+{
+ u16 i;
+
+ BT_InitCtrlBlk();
+ ScanlineEffect_Clear();
+ task->tAcc = 256;
+ task->tJerk = 1;
+ sTransitionStructPtr->winIn = 0x3F;
+ sTransitionStructPtr->winOut = 0;
+ sTransitionStructPtr->win0V = 160;
+ for (i = 0; i < 160; ++i)
+ {
+ gScanlineEffectRegBuffers[1][i] = sTransitionStructPtr->bg123HOfs;
+ gScanlineEffectRegBuffers[1][160 + i] = 0xF0;
+ }
+ EnableInterrupts(INTR_FLAG_HBLANK);
+ SetVBlankCallback(VBCB_BT_Phase2SlicedScreen);
+ SetHBlankCallback(HBCB_BT_Phase2SlicedScreen);
+ ++task->tState;
+ return TRUE;
+}
+
+static bool8 BT_Phase2SlicedScreen_UpdateOffsets(struct Task *task)
+{
+ u16 i;
+
+ sTransitionStructPtr->vblankDma = FALSE;
+ task->tSpeed += (task->tAcc >> 8);
+ if (task->tSpeed > 0xF0)
+ task->tSpeed = 0xF0;
+ if (task->tAcc <= 0xFFF)
+ task->tAcc += task->tJerk;
+ if (task->tJerk < 128)
+ task->tJerk <<= 1;
+ for (i = 0; i < 160; ++i)
+ {
+ u16 *ofsBuffer = &gScanlineEffectRegBuffers[0][i];
+ u16 *win0HBuffer = &gScanlineEffectRegBuffers[0][i + 160];
+ if (i & 1)
+ {
+ *ofsBuffer = sTransitionStructPtr->bg123HOfs + task->tSpeed;
+ *win0HBuffer = 0xF0 - task->tSpeed;
+ }
+ else
+ {
+ *ofsBuffer = sTransitionStructPtr->bg123HOfs - task->tSpeed;
+ *win0HBuffer = (task->tSpeed << 8) | 0xF1;
+ }
+ }
+ if (task->tSpeed > 0xEF)
+ ++task->tState;
+ ++sTransitionStructPtr->vblankDma;
+ return FALSE;
+}
+
+static bool8 BT_Phase2SlicedScreen_End(struct Task *task)
+{
+ DmaStop(0);
+ BT_BlendPalettesToBlack();
+ DestroyTask(FindTaskIdByFunc(BT_Phase2SlicedScreen));
+ return FALSE;
+}
+
+static void VBCB_BT_Phase2SlicedScreen(void)
+{
+ DmaStop(0);
+ BT_VBSyncOamAndPltt();
+ SetGpuReg(REG_OFFSET_WININ, sTransitionStructPtr->winIn);
+ SetGpuReg(REG_OFFSET_WINOUT, sTransitionStructPtr->winOut);
+ SetGpuReg(REG_OFFSET_WIN0V, sTransitionStructPtr->win0V);
+ if (sTransitionStructPtr->vblankDma)
+ DmaCopy16(3, gScanlineEffectRegBuffers[0], gScanlineEffectRegBuffers[1], 640);
+ DmaSet(0, &gScanlineEffectRegBuffers[1][160], &REG_WIN0H, ((DMA_ENABLE | DMA_START_HBLANK | DMA_REPEAT | DMA_16BIT | DMA_SRC_INC | DMA_DEST_FIXED) << 16) | 1);
+}
+
+static void HBCB_BT_Phase2SlicedScreen(void)
+{
+ s16 offset = gScanlineEffectRegBuffers[1][REG_VCOUNT];
+
+ REG_BG1HOFS = offset;
+ REG_BG2HOFS = offset;
+ REG_BG3HOFS = offset;
+}
+
+#undef tSpeed
+#undef tAcc
+#undef tJerk
+
+#define spBldyCounter data[0]
+#define spFinished data[1]
+#define spAltDelay data[2]
+#define spDelay data[5]
+#define spLastSprite data[6]
+
+static void BT_Phase2WhiteFadeInStripes(u8 taskId)
+{
+ while (sBT_Phase2WhiteFadeInStripesFuncs[gTasks[taskId].tState](&gTasks[taskId]));
+}
+
+static bool8 BT_Phase2WhiteFadeInStripes_Init(struct Task *task)
+{
+ u16 i;
+
+ BT_InitCtrlBlk();
+ ScanlineEffect_Clear();
+ sTransitionStructPtr->bldCnt = BLDCNT_TGT1_BG0 | BLDCNT_TGT1_BG1 | BLDCNT_TGT1_BG2 | BLDCNT_TGT1_BG3 | BLDCNT_TGT1_OBJ | BLDCNT_TGT1_BD | BLDCNT_EFFECT_LIGHTEN;
+ sTransitionStructPtr->bldY = 0;
+ sTransitionStructPtr->winIn = 0x1E;
+ sTransitionStructPtr->winOut = 0x3F;
+ sTransitionStructPtr->win0V = 160;
+ for (i = 0; i < 160; ++i)
+ {
+ gScanlineEffectRegBuffers[1][i] = 0;
+ gScanlineEffectRegBuffers[1][i + 160] = 0xF0;
+ }
+ EnableInterrupts(INTR_FLAG_HBLANK);
+ SetHBlankCallback(HBCB_BT_Phase2WhiteFadeInStripes);
+ SetVBlankCallback(VBCB_BT_Phase2WhiteFadeInStripes1);
+ ++task->tState;
+ return FALSE;
+}
+
+static bool8 BT_Phase2WhiteFadeInStripes_SetupSprites(struct Task *task)
+{
+ s16 i, posY;
+ s16 buffer[NELEMS(sWhiteStripeDelay)];
+ struct Sprite *sprite;
+
+ memcpy(buffer, sWhiteStripeDelay, sizeof(sWhiteStripeDelay));
+ for (i = 0, posY = 0; i < 6; ++i, posY += 0x1B)
+ {
+ sprite = &gSprites[CreateInvisibleSprite(SpriteCB_BT_Phase2WhiteFadeInStripes)];
+ sprite->pos1.x = 0xF0;
+ sprite->pos1.y = posY;
+ sprite->spDelay = buffer[i];
+ }
+ ++sprite->spLastSprite;
+ ++task->tState;
+ return FALSE;
+}
+
+static bool8 BT_Phase2WhiteFadeInStripes_IsWhiteFadeDone(struct Task *task)
+{
+ sTransitionStructPtr->vblankDma = FALSE;
+ if (sTransitionStructPtr->counter > 5)
+ {
+ BlendPalettes(0xFFFFFFFF, 0x10, RGB_WHITE);
+ ++task->tState;
+ }
+ return FALSE;
+}
+
+static bool8 BT_Phase2WhiteFadeInStripes_Stop(struct Task *task)
+{
+ sTransitionStructPtr->vblankDma = FALSE;
+ DmaStop(0);
+ SetVBlankCallback(NULL);
+ SetHBlankCallback(NULL);
+ sTransitionStructPtr->win0H = 240;
+ sTransitionStructPtr->bldY = 0;
+ sTransitionStructPtr->bldCnt = BLDCNT_TGT1_BG0 | BLDCNT_TGT1_BG1 | BLDCNT_TGT1_BG2 | BLDCNT_TGT1_BG3 | BLDCNT_TGT1_OBJ | BLDCNT_TGT1_BD | BLDCNT_EFFECT_DARKEN;
+ sTransitionStructPtr->winIn = 0x3F;
+ sTransitionStructPtr->counter = 0;
+ SetVBlankCallback(VBCB_BT_Phase2WhiteFadeInStripes2);
+ ++task->tState;
+ return FALSE;
+}
+
+static bool8 BT_Phase2WhiteFadeInStripes_IsDone(struct Task *task)
+{
+ sTransitionStructPtr->counter += 480;
+ sTransitionStructPtr->bldY = sTransitionStructPtr->counter >> 8;
+ if (sTransitionStructPtr->bldY > 16)
+ {
+ BT_BlendPalettesToBlack();
+ DestroyTask(FindTaskIdByFunc(BT_Phase2WhiteFadeInStripes));
+ }
+ return FALSE;
+}
+
+static void VBCB_BT_Phase2WhiteFadeInStripes1(void)
+{
+ DmaStop(0);
+ BT_VBSyncOamAndPltt();
+ SetGpuReg(REG_OFFSET_BLDCNT, sTransitionStructPtr->bldCnt);
+ SetGpuReg(REG_OFFSET_WININ, sTransitionStructPtr->winIn);
+ SetGpuReg(REG_OFFSET_WINOUT, sTransitionStructPtr->winOut);
+ SetGpuReg(REG_OFFSET_WIN0V, sTransitionStructPtr->win0H); // BUG: This should obviously be sTransitionStructPtr->win0V
+ if (sTransitionStructPtr->vblankDma)
+ DmaCopy16(3, gScanlineEffectRegBuffers[0], gScanlineEffectRegBuffers[1], 640);
+ DmaSet(0, &gScanlineEffectRegBuffers[1][160], &REG_WIN0H, ((DMA_ENABLE | DMA_START_HBLANK | DMA_REPEAT | DMA_16BIT | DMA_SRC_INC | DMA_DEST_FIXED) << 16) | 1);
+}
+
+static void VBCB_BT_Phase2WhiteFadeInStripes2(void)
+{
+ BT_VBSyncOamAndPltt();
+ SetGpuReg(REG_OFFSET_BLDY, sTransitionStructPtr->bldY);
+ SetGpuReg(REG_OFFSET_BLDCNT, sTransitionStructPtr->bldCnt);
+ SetGpuReg(REG_OFFSET_WININ, sTransitionStructPtr->winIn);
+ SetGpuReg(REG_OFFSET_WINOUT, sTransitionStructPtr->winOut);
+ SetGpuReg(REG_OFFSET_WIN0H, sTransitionStructPtr->win0H);
+ SetGpuReg(REG_OFFSET_WIN0V, sTransitionStructPtr->win0V);
+}
+
+
+static void HBCB_BT_Phase2WhiteFadeInStripes(void)
+{
+ vu16 index = REG_VCOUNT;
+
+ if (index == 227)
+ index = 0;
+ REG_BLDY = gScanlineEffectRegBuffers[1][index];
+}
+
+static void SpriteCB_BT_Phase2WhiteFadeInStripes(struct Sprite *sprite)
+{
+ if (sprite->spDelay)
+ {
+ --sprite->spDelay;
+ if (sprite->spLastSprite)
+ sTransitionStructPtr->vblankDma = TRUE;
+ }
+ else
+ {
+ u16 i;
+ u16 *bldY = &gScanlineEffectRegBuffers[0][sprite->pos1.y];
+ u16 *win0H = &gScanlineEffectRegBuffers[0][sprite->pos1.y + 160];
+ u32 stripeWidth = sprite->spLastSprite ? 0x19 : 0x1B;
+
+ for (i = 0; i < stripeWidth; ++i)
+ {
+ bldY[i] = sprite->spBldyCounter >> 8;
+ win0H[i] = (u8)(sprite->pos1.x);
+ }
+ if (sprite->pos1.x == 0 && sprite->spBldyCounter == 0x1000)
+ sprite->spFinished = 1;
+ sprite->pos1.x -= 24;
+ sprite->spBldyCounter += 192;
+ if (sprite->pos1.x < 0)
+ sprite->pos1.x = 0;
+ if (sprite->spBldyCounter > 0x1000)
+ sprite->spBldyCounter = 0x1000;
+ if (sprite->spLastSprite)
+ sTransitionStructPtr->vblankDma = TRUE;
+ if (sprite->spFinished)
+ {
+ if (sprite->spLastSprite == FALSE || (sTransitionStructPtr->counter > 4))
+ {
+ ++sTransitionStructPtr->counter;
+ DestroySprite(sprite);
+ }
+ }
+ }
+}
+
+#undef spBldyCounter
+#undef spFinished
+#undef spAltDelay
+#undef spDelay
+#undef spLastSprite
+
+#define tDelay data[1]
+#define tWhichGrid data[2]
+
+static void BT_Phase2GridSquares(u8 taskId)
+{
+ while (sBT_Phase2GridSquaresFuncs[gTasks[taskId].tState](&gTasks[taskId]));
+}
+
+static bool8 BT_Phase2GridSquares_LoadGfx(struct Task *task)
+{
+ u16 *tilemapAddr, *tilesetAddr;
+
+ BT_GetBg0TilemapAndTilesetBase(&tilemapAddr, &tilesetAddr);
+ CpuSet(sGridSquareTileset, tilesetAddr, 0x10);
+ CpuFill16(0xF000, tilemapAddr, 0x800);
+ LoadPalette(sSlidingPokeballBigPokeballPalette, 0xF0, 0x20);
+ ++task->tState;
+ return FALSE;
+}
+
+static bool8 BT_Phase2GridSquares_UpdateTileset(struct Task *task)
+{
+ u16 *tilesetAddr;
+
+ if (task->tDelay == 0)
+ {
+ BT_GetBg0TilesetBase(&tilesetAddr);
+ task->tDelay = 3;
+ ++task->tWhichGrid;
+ CpuSet(sGridSquareTileset + (task->tWhichGrid * 8), tilesetAddr, 0x10);
+ if (task->tWhichGrid > 0xD)
+ {
+ ++task->tState;
+ task->tDelay = 16;
+ }
+ }
+ --task->tDelay;
+ return FALSE;
+}
+
+static bool8 BT_Phase2GridSquares_IsDone(struct Task *task)
+{
+ if (--task->tDelay == 0)
+ {
+ BT_BlendPalettesToBlack();
+ DestroyTask(FindTaskIdByFunc(BT_Phase2GridSquares));
+ }
+ return FALSE;
+}
+
+#undef tDelay
+#undef tWhichGrid
+
+#define tWhichBrush data[1]
+#define tWhichSide data[2]
+#define tDelay data[3]
+
+#define trCurrentPtX data[2]
+#define trCurrentPtY data[3]
+
+static void BT_Phase2BlackDoodles(u8 taskId)
+{
+ while (sBT_Phase2BlackDoodlesFuncs[gTasks[taskId].tState](&gTasks[taskId]));
+}
+
+static bool8 BT_Phase2BlackDoodles_Init(struct Task *task)
+{
+ u16 i;
+
+ BT_InitCtrlBlk();
+ ScanlineEffect_Clear();
+ sTransitionStructPtr->winIn = 0x3F;
+ sTransitionStructPtr->winOut = 0;
+ sTransitionStructPtr->win0V = 0xA0;
+ for (i = 0; i < 160; ++i)
+ gScanlineEffectRegBuffers[0][i] = 0x00F0;
+ CpuSet(gScanlineEffectRegBuffers[0], gScanlineEffectRegBuffers[1], 160);
+ SetVBlankCallback(VBCB_BT_Phase2BlackDoodles);
+ ++task->tState;
+ return TRUE;
+}
+
+static bool8 BT_Phase2BlackDoodles_InitSingleBrush(struct Task *task)
+{
+ BT_DiagonalSegment_InitParams(sTransitionStructPtr->data, sBlackDoodlesSegments[task->tWhichBrush][0], sBlackDoodlesSegments[task->tWhichBrush][1], sBlackDoodlesSegments[task->tWhichBrush][2], sBlackDoodlesSegments[task->tWhichBrush][3], 1, 1);
+ task->tWhichSide = sBlackDoodlesSegments[task->tWhichBrush][4];
+ ++task->tState;
+ return TRUE;
+}
+
+static bool8 BT_Phase2BlackDoodles_DrawSingleBrush(struct Task *task)
+{
+ s16 i;
+ bool8 nextFunc;
+
+ sTransitionStructPtr->vblankDma = FALSE;
+ for (i = 0, nextFunc = FALSE; i < 16; ++i)
+ {
+ s16 left = gScanlineEffectRegBuffers[0][sTransitionStructPtr->trCurrentPtY] >> 8;
+ s16 right = gScanlineEffectRegBuffers[0][sTransitionStructPtr->trCurrentPtY] & 0xFF;
+ if (task->tWhichSide == 0)
+ {
+ if (left < sTransitionStructPtr->trCurrentPtX)
+ left = sTransitionStructPtr->trCurrentPtX;
+ if (left > right)
+ left = right;
+ }
+ else
+ {
+ if (right > sTransitionStructPtr->trCurrentPtX)
+ right = sTransitionStructPtr->trCurrentPtX;
+ if (right <= left)
+ right = left;
+ }
+ gScanlineEffectRegBuffers[0][sTransitionStructPtr->trCurrentPtY] = right | (left << 8);
+ if (nextFunc)
+ {
+ ++task->tState;
+ break;
+ }
+ else
+ nextFunc = BT_DiagonalSegment_ComputePointOnSegment(sTransitionStructPtr->data, TRUE, TRUE);
+ }
+ ++sTransitionStructPtr->vblankDma;
+ return FALSE;
+}
+
+static bool8 BT_Phase2BlackDoodles_IsDone(struct Task *task)
+{
+ if (++task->tWhichBrush < 7)
+ {
+ ++task->tState;
+ task->tDelay = sBlackDoodlesDelay[task->tWhichBrush - 1];
+ return TRUE;
+ }
+ else
+ {
+ DmaStop(0);
+ BT_BlendPalettesToBlack();
+ DestroyTask(FindTaskIdByFunc(BT_Phase2BlackDoodles));
+ return FALSE;
+ }
+}
+
+static bool8 BT_Phase2BlackDoodles_NextBrush(struct Task *task)
+{
+ if (--task->tDelay == 0)
+ {
+ task->tState = 1;
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+static void VBCB_BT_Phase2BlackDoodles(void)
+{
+ DmaStop(0);
+ BT_VBSyncOamAndPltt();
+ if (sTransitionStructPtr->vblankDma)
+ DmaCopy16(3, gScanlineEffectRegBuffers[0], gScanlineEffectRegBuffers[1], 320);
+ SetGpuReg(REG_OFFSET_WININ, sTransitionStructPtr->winIn);
+ SetGpuReg(REG_OFFSET_WINOUT, sTransitionStructPtr->winOut);
+ SetGpuReg(REG_OFFSET_WIN0V, sTransitionStructPtr->win0V);
+ SetGpuReg(REG_OFFSET_WIN0H, gScanlineEffectRegBuffers[1][0]);
+ DmaSet(0, gScanlineEffectRegBuffers[1], &REG_WIN0H, ((DMA_ENABLE | DMA_START_HBLANK | DMA_REPEAT | DMA_16BIT | DMA_SRC_INC | DMA_DEST_FIXED) << 16) | 1);
+}
+
+#undef tWhichBrush
+#undef tWhichSide
+#undef tDelay
+
+#undef trCurrentPtX
+#undef trCurrentPtY
+
+#define tFadeOutDelay data[1]
+#define tFadeInDelay data[2]
+#define tBlinkTimes data[3]
+#define tFadeOutSpeed data[4]
+#define tFadeInSpeed data[5]
+#define tDelayCounter data[6]
+#define tCoeff data[7]
+
+static void BT_CreatePhase1SubTask(s16 fadeOutDelay, s16 fadeInDelay, s16 blinkTimes, s16 fadeOutSpeed, s16 fadeInSpeed)
+{
+ u8 taskId = CreateTask(BT_Phase1SubTask, 3);
+ gTasks[taskId].tFadeOutDelay = fadeOutDelay;
+ gTasks[taskId].tFadeInDelay = fadeInDelay;
+ gTasks[taskId].tBlinkTimes = blinkTimes;
+ gTasks[taskId].tFadeOutSpeed = fadeOutSpeed;
+ gTasks[taskId].tFadeInSpeed = fadeInSpeed;
+ gTasks[taskId].tDelayCounter = fadeOutDelay;
+}
+
+static bool8 BT_IsPhase1Done(void)
+{
+ if (FindTaskIdByFunc(BT_Phase1SubTask) == TASK_NONE)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+static void BT_Phase1SubTask(u8 taskId)
+{
+ while (sBT_Phase1FadeFuncs[gTasks[taskId].tState](&gTasks[taskId]));
+}
+
+static bool8 BT_Phase1_FadeOut(struct Task *task)
+{
+ if (task->tDelayCounter == 0 || --task->tDelayCounter == 0)
+ {
+ task->tDelayCounter = task->tFadeOutDelay;
+ task->tCoeff += task->tFadeOutSpeed;
+ if (task->tCoeff > 16)
+ task->tCoeff = 16;
+ BlendPalettes(-1, task->tCoeff, RGB(11, 11, 11));
+ }
+ if (task->tCoeff > 15)
+ {
+ ++task->tState;
+ task->tDelayCounter = task->tFadeInDelay;
+ }
+ return FALSE;
+}
+
+static bool8 BT_Phase1_FadeIn(struct Task *task)
+{
+ if (task->tDelayCounter == 0 || --task->tDelayCounter == 0)
+ {
+ task->tDelayCounter = task->tFadeInDelay;
+ task->tCoeff -= task->tFadeInSpeed;
+ if (task->tCoeff < 0)
+ task->tCoeff = 0;
+ BlendPalettes(0xFFFFFFFF, task->tCoeff, RGB(11, 11, 11));
+ }
+ if (task->tCoeff == 0)
+ {
+ if (--task->tBlinkTimes == 0)
+ {
+ DestroyTask(FindTaskIdByFunc(BT_Phase1SubTask));
+ }
+ else
+ {
+ task->tDelayCounter = task->tFadeOutDelay;
+ task->tState = 0;
+ }
+ }
+ return FALSE;
+}
+
+#undef tFadeOutDelay
+#undef tFadeInDelay
+#undef tBlinkTimes
+#undef tFadeOutSpeed
+#undef tFadeInSpeed
+#undef tDelayCounter
+#undef tCoeff
+
+static void BT_InitCtrlBlk(void)
+{
+ memset(sTransitionStructPtr, 0, sizeof(*sTransitionStructPtr));
+ sub_805A658(&sTransitionStructPtr->bg123HOfs, &sTransitionStructPtr->bg123VOfs);
+}
+
+static void BT_VBSyncOamAndPltt(void)
+{
+ LoadOam();
+ ProcessSpriteCopyRequests();
+ TransferPlttBuffer();
+}
+
+static void BT_GetBg0TilesetBase(u16 **tilesetPtr)
+{
+ u16 charBase;
+
+ charBase = GetGpuReg(REG_OFFSET_BG0CNT) >> 2;
+ charBase <<= 0xE;
+ *tilesetPtr = (u16 *)(VRAM + charBase);
+}
+
+static void BT_GetBg0TilemapAndTilesetBase(u16 **tilemapPtr, u16 **tilesetPtr)
+{
+ u16 screenBase, charBase;
+
+ screenBase = (GetGpuReg(REG_OFFSET_BG0CNT) >> 8) & 0x1F;
+ charBase = GetGpuReg(REG_OFFSET_BG0CNT) >> 2;
+ screenBase <<= 0xB;
+ charBase <<= 0xE;
+ *tilemapPtr = (u16 *)(VRAM + screenBase);
+ *tilesetPtr = (u16 *)(VRAM + charBase);
+}
+
+static void BT_BlendPalettesToBlack(void)
+{
+ BlendPalettes(0xFFFFFFFF, 0x10, RGB_BLACK);
+}
+
+static void BT_LoadWaveIntoBuffer(s16 *buffer, s16 offset, s16 theta, s16 frequency, s16 amplitude, s16 bufSize)
+{
+ u8 i;
+
+ for (i = 0; bufSize > 0; --bufSize, ++i, theta += frequency)
+ buffer[i] = offset + Sin(0xFF & theta, amplitude);
+}
+
+static void BT_GenerateCircle(s16 *buffer, s16 x, s16 y, s16 radius)
+{
+ s16 i;
+
+ memset(buffer, 0xA, 320);
+ // 64 iterations because we only want to cover [0, π/2) discretely.
+ for (i = 0; i < 64; ++i)
+ {
+ s16 sinResult, cosResult, leftX, topY, bottomY, nextTopY, nextBottomY, winVal;
+
+ // The loop variable i here does not stand for rotation angle,
+ // but is the angle between segment (center, pointOnCircle)
+ // and vertical line.
+ sinResult = Sin(i, radius);
+ cosResult = Cos(i, radius);
+ leftX = x - sinResult;
+ winVal = x + sinResult;
+ topY = y - cosResult;
+ bottomY = y + cosResult;
+ if (leftX < 0)
+ leftX = 0;
+ if (winVal > 240)
+ winVal = 240;
+ if (topY < 0)
+ topY = 0;
+ if (bottomY > 159)
+ bottomY = 159;
+ winVal |= (leftX << 8);
+ buffer[topY] = winVal;
+ buffer[bottomY] = winVal;
+ cosResult = Cos(i + 1, radius);
+ nextTopY = y - cosResult;
+ nextBottomY = y + cosResult;
+ if (nextTopY < 0)
+ nextTopY = 0;
+ if (nextBottomY > 159)
+ nextBottomY = 159;
+ // fill everything in between with the same WIN0H value
+ while (topY > nextTopY)
+ buffer[--topY] = winVal;
+ while (topY < nextTopY)
+ buffer[++topY] = winVal;
+ while (bottomY > nextBottomY)
+ buffer[--bottomY] = winVal;
+ while (bottomY < nextBottomY)
+ buffer[++bottomY] = winVal;
+ }
+}
+
+#define trStartPtX data[0]
+#define trStartPtY data[1]
+#define trCurrentPtX data[2]
+#define trCurrentPtY data[3]
+#define trEndPtX data[4]
+#define trEndPtY data[5]
+#define trStepX data[6]
+#define trStepY data[7]
+#define trAbsDeltaX data[8]
+#define trAbsDeltaY data[9]
+#define trAccum data[10] // track one dimension based on slope
+
+static void BT_DiagonalSegment_InitParams(s16 *data, s16 startPtX, s16 startPtY, s16 endPtX, s16 endPtY, s16 stepX, s16 stepY)
+{
+ trStartPtX = startPtX;
+ trStartPtY = startPtY;
+ trCurrentPtX = startPtX;
+ trCurrentPtY = startPtY;
+ trEndPtX = endPtX;
+ trEndPtY = endPtY;
+ trStepX = stepX;
+ trStepY = stepY;
+ trAbsDeltaX = endPtX - startPtX;
+ if (trAbsDeltaX < 0)
+ {
+ trAbsDeltaX = -trAbsDeltaX;
+ trStepX = -stepX;
+ }
+ trAbsDeltaY = endPtY - startPtY;
+ if (trAbsDeltaY < 0)
+ {
+ trAbsDeltaY = -trAbsDeltaY;
+ trStepY = -stepY;
+ }
+ trAccum = 0;
+}
+
+static bool8 BT_DiagonalSegment_ComputePointOnSegment(s16 *data, bool8 checkBoundary1, bool8 checkBoundary2)
+{
+ u8 finish;
+
+ if (trAbsDeltaX > trAbsDeltaY)
+ {
+ trCurrentPtX += trStepX;
+ trAccum += trAbsDeltaY;
+ if (trAccum > trAbsDeltaX)
+ {
+ trCurrentPtY += trStepY;
+ trAccum -= trAbsDeltaX;
+ }
+ }
+ else
+ {
+ trCurrentPtY += trStepY;
+ trAccum += trAbsDeltaX;
+ if (trAccum > trAbsDeltaY)
+ {
+ trCurrentPtX += trStepX;
+ trAccum -= trAbsDeltaY;
+ }
+ }
+ finish = 0;
+ if ((trStepX > 0 && trCurrentPtX >= trEndPtX) || (trStepX < 0 && trCurrentPtX <= trEndPtX))
+ {
+ ++finish;
+ if (checkBoundary1)
+ trCurrentPtX = trEndPtX;
+ }
+ if ((trStepY > 0 && trCurrentPtY >= trEndPtY) || (trStepY < 0 && trCurrentPtY <= trEndPtY))
+ {
+ ++finish;
+ if (checkBoundary2)
+ trCurrentPtY = trEndPtY;
+ }
+ if (finish == 2)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+#undef trStartPtX
+#undef trStartPtY
+#undef trCurrentPtX
+#undef trCurrentPtY
+#undef trEndPtX
+#undef trEndPtY
+#undef trStepX
+#undef trStepY
+#undef trAbsDeltaX
+#undef trAbsDeltaY
+#undef trAccum
diff --git a/src/diploma.c b/src/diploma.c
index e32d7592f..7fa140430 100644
--- a/src/diploma.c
+++ b/src/diploma.c
@@ -35,7 +35,7 @@ static void DiplomaBgInit(void);
static void DiplomaPrintText(void);
static u8 DiplomaLoadGfx(void);
static void DiplomaVblankHandler(void);
-static void CB2_DiplomaInit(void);
+static void CB2_Diploma(void);
static void Task_WaitForExit(u8);
static void Task_DiplomaInit(u8);
static void Task_DiplomaReturnToOverworld(u8);
@@ -101,10 +101,10 @@ void CB2_ShowDiploma(void)
gDiploma->callbackStep = 0;
DiplomaBgInit();
CreateTask(Task_DiplomaInit, 0);
- SetMainCallback2(CB2_DiplomaInit);
+ SetMainCallback2(CB2_Diploma);
}
-static void CB2_DiplomaInit(void)
+static void CB2_Diploma(void)
{
RunTasks();
AnimateSprites();
@@ -134,7 +134,7 @@ static void Task_DiplomaInit(u8 taskId)
case 4:
if (HasAllMons())
{
- SetGpuReg(REG_OFFSET_BG1HOFS, 0x80 << 1);
+ SetGpuReg(REG_OFFSET_BG1HOFS, 0x100);
}
else
{
diff --git a/src/pokemon.c b/src/pokemon.c
index b948e4033..6f1df249f 100644
--- a/src/pokemon.c
+++ b/src/pokemon.c
@@ -1621,7 +1621,7 @@ const u16 gLinkPlayerFacilityClasses[] =
FACILITY_CLASS_BEAUTY_2, FACILITY_CLASS_AQUA_LEADER,
};
-const static struct OamData sOakSpeechNidoranFDummyOamData =
+static const struct OamData sOakSpeechNidoranFDummyOamData =
{
.y = 0,
.affineMode = 0,
@@ -1637,7 +1637,7 @@ const static struct OamData sOakSpeechNidoranFDummyOamData =
.paletteNum = 0,
};
-const struct SpriteTemplate sOakSpeechNidoranFDummyTemplate =
+static const struct SpriteTemplate sOakSpeechNidoranFDummyTemplate =
{
.tileTag = SPRITE_INVALID_TAG,
.paletteTag = SPRITE_INVALID_TAG,
diff --git a/src/slot_machine.c b/src/slot_machine.c
new file mode 100644
index 000000000..740234d95
--- /dev/null
+++ b/src/slot_machine.c
@@ -0,0 +1,2886 @@
+#include "global.h"
+#include "gpu_regs.h"
+#include "dma3.h"
+#include "bg.h"
+#include "palette.h"
+#include "decompress.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 "new_menu_helpers.h"
+#include "text_window.h"
+#include "random.h"
+#include "trig.h"
+#include "strings.h"
+#include "constants/songs.h"
+
+struct SlotMachineState
+{
+ MainCallback savedCallback;
+ u16 machineidx;
+ u16 field_06;
+ u16 field_08;
+ u16 slotRewardClass;
+ u16 field_0C;
+ 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;
+ u32 field_3C[5];
+ u16 payout;
+};
+
+struct SlotMachineGfxManager
+{
+ u32 field_00[3];
+ struct Sprite * field_0C[3][5];
+ struct Sprite * field_48[4];
+ struct Sprite * field_58[4];
+ struct Sprite * field_68[2];
+ vu16 * field_70;
+};
+
+struct SlotMachineSetupTaskDataSub_0000
+{
+ u16 unk0;
+ u8 unk2;
+ u8 unk3;
+};
+
+struct SlotMachineSetupTaskData
+{
+ struct SlotMachineSetupTaskDataSub_0000 field_0000[8];
+ u8 field_0020;
+ // align 2
+ s32 field_0024;
+ u32 field_0028;
+ u16 field_002C[3][4];
+ u16 field_0044[3][4];
+ u8 field_005C[0x800];
+ u8 field_085C[0x800];
+ u8 field_105C[0x800];
+ u8 field_185C[0x800];
+ u8 field_205C[0x800];
+}; // size: 285C
+
+struct UnkStruct_8466C0C
+{
+ const u16 * tiles;
+ u32 count;
+};
+
+static EWRAM_DATA struct SlotMachineState * sSlotMachineState = NULL;
+static EWRAM_DATA struct SlotMachineGfxManager * sSlotMachineGfxManager = NULL;
+
+static void sub_813F84C(struct SlotMachineState * ptr);
+static void sub_813F898(void);
+static void sub_813F92C(void);
+static void sub_813F94C(void);
+static void MainTask_SlotsGameLoop(u8 taskId);
+static void MainTask_NoCoinsGameOver(u8 taskId);
+static void MainTask_ShowHelp(u8 taskId);
+static void MainTask_ConfirmExitGame(u8 taskId);
+static void MainTask_DarnNoPayout(u8 taskId);
+static void MainTask_WinHandlePayout(u8 taskId);
+static void MainTask_ExitSlots(u8 taskId);
+static void SetMainTask(TaskFunc taskFunc);
+static void sub_8140060(u8 taskId);
+static void sub_8140148(void);
+static void sub_814016C(u16 whichReel, u16 whichReel2);
+static bool32 sub_81401A0(u16);
+static void sub_81401F0(u16 whichReel);
+static void sub_81403BC(u16 whichReel);
+static void sub_81404B8(u16 whichReel);
+static bool32 sub_814054C(s32, s32, s32, s32, s32);
+static bool32 sub_81406E8(s32, s32, s32);
+static bool32 sub_81408F4(s32, s32);
+static void sub_81409B4(void);
+static void sub_8140A70(void);
+static u16 sub_8140A80(void);
+static void sub_8140C6C(struct SlotMachineGfxManager * manager);
+static void sub_8140D7C(const s16 *, const s16 *);
+static bool32 sub_814104C(void);
+static void sub_8141094(void);
+static struct SlotMachineSetupTaskData * sub_814112C(void);
+static void sub_81410CC(u8 taskId);
+static void sub_8141148(u16 a0, u8 a1);
+static bool32 sub_8141180(u8 a0);
+static bool8 sub_8141198(u8 *, struct SlotMachineSetupTaskData *);
+static bool8 sub_8141460(u8 *, struct SlotMachineSetupTaskData *);
+static bool8 sub_81414AC(u8 *, struct SlotMachineSetupTaskData *);
+static bool8 sub_81414EC(u8 *, struct SlotMachineSetupTaskData *);
+static bool8 sub_81414FC(u8 *, struct SlotMachineSetupTaskData *);
+static bool8 sub_8141518(u8 *, struct SlotMachineSetupTaskData *);
+static bool8 sub_8141558(u8 *, struct SlotMachineSetupTaskData *);
+static bool8 sub_8141568(u8 *, struct SlotMachineSetupTaskData *);
+static bool8 sub_8141578(u8 *, struct SlotMachineSetupTaskData *);
+static bool8 sub_8141584(u8 *, struct SlotMachineSetupTaskData *);
+static bool8 sub_81415C8(u8 *, struct SlotMachineSetupTaskData *);
+static bool8 sub_8141610(u8 *, struct SlotMachineSetupTaskData *);
+static bool8 sub_8141650(u8 *, struct SlotMachineSetupTaskData *);
+static bool8 sub_8141690(u8 *, struct SlotMachineSetupTaskData *);
+static bool8 sub_81416C8(u8 *, struct SlotMachineSetupTaskData *);
+static bool8 sub_8141764(u8 *, struct SlotMachineSetupTaskData *);
+static void sub_81417E4(const u8 * str);
+static void sub_8141828(void);
+static void sub_8141834(u16 * bgTilemapBuffer);
+static void sub_81418C4(u16 * bgTilemapBuffer, u16 a0, u16 a1);
+static void sub_814191C(u8 taskId);
+static void sub_8141AB0(void);
+static void sub_8141AD8(u8 a0);
+static void sub_8141B18(void);
+static void sub_8141B34(void);
+static void sub_8141BA0(u8 a0);
+static void sub_8141BE4(void);
+static void sub_8141C30(u8, u8);
+
+static const u8 gUnknown_8464890[][2] = {
+ {0x00, 0x03},
+ {0x00, 0x06},
+ {0x03, 0x06},
+
+ {0x01, 0x04},
+ {0x01, 0x07},
+ {0x04, 0x07},
+
+ {0x02, 0x05},
+ {0x02, 0x08},
+ {0x05, 0x08},
+
+ {0x00, 0x04},
+ {0x00, 0x08},
+ {0x04, 0x08},
+
+ {0x02, 0x04},
+ {0x02, 0x06},
+ {0x04, 0x06}
+};
+
+static const u8 gUnknown_84648AE[][3] = {
+ {0x00, 0x03, 0x06}, // top row
+ {0x01, 0x04, 0x07}, // middle row
+ {0x02, 0x05, 0x08}, // bottom row
+ {0x00, 0x04, 0x08}, // tl-br
+ {0x02, 0x04, 0x06} // bl-tr
+};
+
+static const u8 gUnknown_84648BD[][4] = {
+ {0x00, 0x04, 0x08, 0x03}, // tl-br
+ {0x00, 0x03, 0x06, 0x02}, // top row
+ {0x01, 0x04, 0x07, 0x01}, // middle row
+ {0x02, 0x05, 0x08, 0x02}, // bottom row
+ {0x02, 0x04, 0x06, 0x03} // bl-tr
+};
+
+static const u16 gUnknown_84648D2[][7] = {
+ {0x1fa1, 0x2eab, 0x3630, 0x39f3, 0x3bd4, 0x3bfc, 0x0049},
+ {0x1f97, 0x2ea2, 0x3627, 0x39e9, 0x3bca, 0x3bf8, 0x0049},
+ {0x1f91, 0x2e9b, 0x3620, 0x39e3, 0x3bc4, 0x3bf4, 0x0049},
+ {0x1f87, 0x2e92, 0x3617, 0x39d9, 0x3bba, 0x3bef, 0x0050},
+ {0x1f7f, 0x2e89, 0x360e, 0x39d1, 0x3bb2, 0x3bea, 0x0050},
+ {0x1fc9, 0x2efc, 0x3696, 0x3a63, 0x3c49, 0x3c8b, 0x0073},
+};
+
+static const u8 gUnknown_8464926[][21] = {
+ {0x00, 0x03, 0x04, 0x01, 0x02, 0x06, 0x02, 0x05, 0x00, 0x06, 0x03, 0x01, 0x04, 0x02, 0x06, 0x00, 0x05, 0x02, 0x01, 0x06, 0x02},
+ {0x00, 0x05, 0x04, 0x03, 0x01, 0x05, 0x04, 0x03, 0x02, 0x05, 0x04, 0x03, 0x00, 0x05, 0x04, 0x01, 0x03, 0x06, 0x05, 0x03, 0x04},
+ {0x00, 0x03, 0x06, 0x05, 0x02, 0x03, 0x06, 0x05, 0x02, 0x03, 0x05, 0x06, 0x02, 0x03, 0x05, 0x06, 0x02, 0x03, 0x05, 0x06, 0x01},
+};
+
+static const u16 gUnknown_8464966[] = {
+ 0,
+ 2,
+ 6,
+ 8,
+ 15,
+ 100,
+ 300
+};
+
+static const u16 gUnknown_8464974[] = INCBIN_U16("graphics/slot_machine/unk_8464974.gbapal");
+static const u16 gUnknown_8464994[] = INCBIN_U16("graphics/slot_machine/unk_8464994.gbapal");
+static const u16 gUnknown_84649B4[] = INCBIN_U16("graphics/slot_machine/unk_84649b4.gbapal");
+static const u16 gUnknown_84649D4[] = INCBIN_U16("graphics/slot_machine/unk_84649d4.gbapal");
+static const u16 gUnknown_84649F4[] = INCBIN_U16("graphics/slot_machine/unk_84649f4.gbapal");
+static const u32 gUnknown_8464A14[] = INCBIN_U32("graphics/slot_machine/unk_8464a14.4bpp.lz");
+static const u16 gUnknown_846504C[] = INCBIN_U16("graphics/slot_machine/unk_846504c.gbapal");
+static const u32 gUnknown_846506C[] = INCBIN_U32("graphics/slot_machine/unk_846506c.4bpp.lz");
+static const u16 gUnknown_8465524[] = INCBIN_U16("graphics/slot_machine/unk_8465524.gbapal");
+static const u32 gUnknown_8465544[] = INCBIN_U32("graphics/slot_machine/unk_8465544.4bpp.lz");
+
+static const struct CompressedSpriteSheet gUnknown_84655B0[] = {
+ {(const void *)gUnknown_8464A14, 0xe00, 0},
+ {(const void *)gUnknown_846506C, 0xc00, 1},
+ {(const void *)gUnknown_8465544, 0x280, 2},
+};
+
+static const struct SpritePalette gUnknown_84655C8[] = {
+ {gUnknown_8464974, 0},
+ {gUnknown_8464994, 1},
+ {gUnknown_84649B4, 2},
+ {gUnknown_84649D4, 3},
+ {gUnknown_84649F4, 4},
+ {gUnknown_846504C, 5},
+ {gUnknown_8465524, 6},
+ {NULL}
+};
+
+static const u16 gUnknown_8465608[] = {
+ 2,
+ 2,
+ 0,
+ 0,
+ 2,
+ 4,
+ 3
+};
+
+static const u16 gUnknown_8465616[] = {
+ 0x0120, 0x011f, 0x011e, 0x011d, 0x011c, 0x011b, 0x011a, 0x0119, 0x0118, 0x0117, 0x0116, 0x0115, 0x0114, 0x0113, 0x0112, 0x0111,
+ 0x0110, 0x010f, 0x010e, 0x010d, 0x010c, 0x010b, 0x010a, 0x0109, 0x0108, 0x0107, 0x0106, 0x0105, 0x0104, 0x0103, 0x0102, 0x0101,
+ 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
+ 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
+ 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106, 0x0107, 0x0108, 0x0109, 0x010a, 0x010b, 0x010c, 0x010d, 0x010e, 0x010f, 0x0110,
+ 0x0111, 0x0112, 0x0113, 0x0114, 0x0115, 0x0116, 0x0117, 0x0118, 0x0119, 0x011a, 0x011b, 0x011c, 0x011d, 0x011e, 0x011f, 0x0120
+};
+
+static const u8 gUnknown_84656D6[] = {
+ 0x10, 0x10, 0x10, 0x10, 0x0f, 0x0e, 0x0d, 0x0d, 0x0c, 0x0b, 0x0a, 0x0a, 0x09, 0x08, 0x07, 0x07, 0x06, 0x05, 0x04, 0x04, 0x03, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x03, 0x04, 0x05, 0x06, 0x06, 0x07, 0x08, 0x09, 0x09, 0x0a, 0x0b, 0x0c, 0x0c, 0x0d, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f
+};
+
+static const struct OamData gUnknown_8465738 = {
+ .y = 0,
+ .affineMode = ST_OAM_AFFINE_NORMAL,
+ .objMode = ST_OAM_OBJ_NORMAL,
+ .mosaic = FALSE,
+ .bpp = ST_OAM_4BPP,
+ .shape = ST_OAM_SQUARE,
+ .x = 0,
+ .matrixNum = 0,
+ .size = ST_OAM_SIZE_2,
+ .tileNum = 0,
+ .priority = 3,
+ .paletteNum = 0,
+ .affineParam = 0
+};
+
+static const union AnimCmd gUnknown_8465740[] = {
+ ANIMCMD_FRAME(0x00, 4),
+ ANIMCMD_END
+};
+
+static const union AnimCmd gUnknown_8465748[] = {
+ ANIMCMD_FRAME(0x10, 4),
+ ANIMCMD_END
+};
+
+static const union AnimCmd gUnknown_8465750[] = {
+ ANIMCMD_FRAME(0x20, 4),
+ ANIMCMD_END
+};
+
+static const union AnimCmd gUnknown_8465758[] = {
+ ANIMCMD_FRAME(0x30, 4),
+ ANIMCMD_END
+};
+
+static const union AnimCmd gUnknown_8465760[] = {
+ ANIMCMD_FRAME(0x40, 4),
+ ANIMCMD_END
+};
+
+static const union AnimCmd gUnknown_8465768[] = {
+ ANIMCMD_FRAME(0x50, 4),
+ ANIMCMD_END
+};
+
+static const union AnimCmd gUnknown_8465770[] = {
+ ANIMCMD_FRAME(0x60, 4),
+ ANIMCMD_END
+};
+
+static const union AnimCmd gUnknown_8465778[] = {
+ ANIMCMD_FRAME(0x20, 4),
+ ANIMCMD_END
+};
+
+static const union AnimCmd gUnknown_8465780[] = {
+ ANIMCMD_FRAME(0x30, 4),
+ ANIMCMD_END
+};
+
+static const union AnimCmd gUnknown_8465788[] = {
+ ANIMCMD_FRAME(0x40, 4),
+ ANIMCMD_END
+};
+
+static const union AnimCmd gUnknown_8465790[] = {
+ ANIMCMD_FRAME(0x50, 4),
+ ANIMCMD_END
+};
+
+static const union AnimCmd gUnknown_8465798[] = {
+ ANIMCMD_FRAME(0x60, 4),
+ ANIMCMD_END
+};
+
+static const union AnimCmd *const gUnknown_84657A0[] = {
+ gUnknown_8465740,
+ gUnknown_8465748,
+ gUnknown_8465750,
+ gUnknown_8465758,
+ gUnknown_8465760,
+ gUnknown_8465768,
+ gUnknown_8465770,
+ gUnknown_8465778,
+ gUnknown_8465780,
+ gUnknown_8465788,
+ gUnknown_8465790,
+ gUnknown_8465798
+};
+
+static const union AffineAnimCmd gUnknown_84657D0[] = {
+ AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 1),
+ AFFINEANIMCMD_END
+};
+
+static const union AffineAnimCmd *const gUnknown_84657E0[] = {
+ gUnknown_84657D0
+};
+
+static const struct SpriteTemplate gUnknown_84657E4 = {
+ 0, 0, &gUnknown_8465738, gUnknown_84657A0, NULL, gDummySpriteAffineAnimTable, SpriteCallbackDummy
+};
+
+static const struct OamData gUnknown_84657FC = {
+ .y = 0,
+ .affineMode = ST_OAM_AFFINE_OFF,
+ .objMode = ST_OAM_OBJ_NORMAL,
+ .mosaic = FALSE,
+ .bpp = ST_OAM_4BPP,
+ .shape = ST_OAM_V_RECTANGLE,
+ .x = 0,
+ .matrixNum = 0,
+ .size = ST_OAM_SIZE_0,
+ .tileNum = 0,
+ .priority = 1,
+ .paletteNum = 0,
+ .affineParam = 0
+};
+
+static const union AnimCmd gUnknown_8465804[] = {
+ ANIMCMD_FRAME(0x00, 4),
+ ANIMCMD_END
+};
+
+static const union AnimCmd gUnknown_846580C[] = {
+ ANIMCMD_FRAME(0x02, 4),
+ ANIMCMD_END
+};
+
+static const union AnimCmd gUnknown_8465814[] = {
+ ANIMCMD_FRAME(0x04, 4),
+ ANIMCMD_END
+};
+
+static const union AnimCmd gUnknown_846581C[] = {
+ ANIMCMD_FRAME(0x06, 4),
+ ANIMCMD_END
+};
+
+static const union AnimCmd gUnknown_8465824[] = {
+ ANIMCMD_FRAME(0x08, 4),
+ ANIMCMD_END
+};
+
+static const union AnimCmd gUnknown_846582C[] = {
+ ANIMCMD_FRAME(0x0a, 4),
+ ANIMCMD_END
+};
+
+static const union AnimCmd gUnknown_8465834[] = {
+ ANIMCMD_FRAME(0x0c, 4),
+ ANIMCMD_END
+};
+
+static const union AnimCmd gUnknown_846583C[] = {
+ ANIMCMD_FRAME(0x0e, 4),
+ ANIMCMD_END
+};
+
+static const union AnimCmd gUnknown_8465844[] = {
+ ANIMCMD_FRAME(0x10, 4),
+ ANIMCMD_END
+};
+
+static const union AnimCmd gUnknown_846584C[] = {
+ ANIMCMD_FRAME(0x12, 4),
+ ANIMCMD_END
+};
+
+static const union AnimCmd *const gUnknown_8465854[] = {
+ gUnknown_8465804,
+ gUnknown_846580C,
+ gUnknown_8465814,
+ gUnknown_846581C,
+ gUnknown_8465824,
+ gUnknown_846582C,
+ gUnknown_8465834,
+ gUnknown_846583C,
+ gUnknown_8465844,
+ gUnknown_846584C
+};
+
+static const struct SpriteTemplate gUnknown_846587C = {
+ 2, 6, &gUnknown_84657FC, gUnknown_8465854, NULL, gDummySpriteAffineAnimTable, SpriteCallbackDummy
+};
+
+static const struct OamData gUnknown_8465894 = {
+ .y = 0,
+ .affineMode = ST_OAM_AFFINE_OFF,
+ .objMode = ST_OAM_OBJ_NORMAL,
+ .mosaic = FALSE,
+ .bpp = ST_OAM_4BPP,
+ .shape = ST_OAM_SQUARE,
+ .x = 0,
+ .matrixNum = 0,
+ .size = ST_OAM_SIZE_2,
+ .tileNum = 0,
+ .priority = 1,
+ .paletteNum = 0,
+ .affineParam = 0
+};
+
+static const union AnimCmd gUnknown_846589C[] = {
+ ANIMCMD_FRAME(0, 4),
+ ANIMCMD_END
+};
+
+static const union AnimCmd gUnknown_84658A4[] = {
+ ANIMCMD_FRAME( 0, 24),
+ ANIMCMD_FRAME(16, 24),
+ ANIMCMD_JUMP(0)
+};
+
+static const union AnimCmd gUnknown_84658B0[] = {
+ ANIMCMD_FRAME(32, 28),
+ ANIMCMD_FRAME(48, 28),
+ ANIMCMD_JUMP(0)
+};
+
+static const union AnimCmd gUnknown_84658BC[] = {
+ ANIMCMD_FRAME(64, 12),
+ ANIMCMD_FRAME(80, 12),
+ ANIMCMD_JUMP(0)
+};
+
+static const union AnimCmd *const gUnknown_84658C8[] = {
+ gUnknown_846589C,
+ gUnknown_84658A4,
+ gUnknown_84658B0,
+ gUnknown_84658BC
+};
+
+static const struct SpriteTemplate gUnknown_84658D8 = {
+ 1, 5, &gUnknown_8465894, gUnknown_84658C8, NULL, gDummySpriteAffineAnimTable, SpriteCallbackDummy
+};
+
+bool8 (*const gUnknown_84658F0[])(u8 *, struct SlotMachineSetupTaskData *) = {
+ sub_8141198,
+ sub_8141460,
+ sub_81414AC,
+ sub_81414EC,
+ sub_81414FC,
+ sub_8141518,
+ sub_8141558,
+ sub_8141568,
+ sub_8141578,
+ sub_8141584,
+ sub_81415C8,
+ sub_8141610,
+ sub_8141650,
+ sub_8141690,
+ sub_81416C8,
+ sub_8141764
+};
+
+static const u16 gUnknown_8465930[] = INCBIN_U16("graphics/slot_machine/unk_8465930.gbapal");
+static const u16 gUnknown_8465950[] = INCBIN_U16("graphics/slot_machine/unk_8465950.gbapal");
+static const u16 gUnknown_8465970[] = INCBIN_U16("graphics/slot_machine/unk_8465970.gbapal");
+static const u16 gUnknown_8465990[] = INCBIN_U16("graphics/slot_machine/unk_8465990.gbapal");
+static const u16 gUnknown_84659B0[] = INCBIN_U16("graphics/slot_machine/unk_84659b0.gbapal");
+static const u32 gUnknown_84659D0[] = INCBIN_U32("graphics/slot_machine/unk_84659d0.4bpp.lz");
+static const u32 gUnknown_84661D4[] = INCBIN_U32("graphics/slot_machine/unk_84661d4.bin.lz");
+static const u16 gUnknown_84664BC[] = INCBIN_U16("graphics/slot_machine/unk_84664bc.gbapal");
+static const u16 gUnknown_84664DC[] = INCBIN_U16("graphics/slot_machine/unk_84664dc.gbapal","graphics/slot_machine/unk_84664fc.gbapal", "graphics/slot_machine/unk_846651c.gbapal");
+static const u32 gUnknown_846653C[] = INCBIN_U32("graphics/slot_machine/unk_846653c.4bpp.lz");
+static const u16 gUnknown_84665C0[] = INCBIN_U16("graphics/slot_machine/unk_84665c0.gbapal");
+static const u16 gUnknown_84665E0[] = INCBIN_U16("graphics/slot_machine/unk_84665e0.gbapal");
+static const u16 gUnknown_8466600[] = INCBIN_U16("graphics/slot_machine/unk_8466600.gbapal");
+static const u32 gUnknown_8466620[] = INCBIN_U32("graphics/slot_machine/unk_8466620.4bpp.lz");
+static const u32 gUnknown_8466998[] = INCBIN_U32("graphics/slot_machine/unk_8466998.bin.lz");
+
+static const struct BgTemplate gUnknown_8466B10[] = {
+ {
+ .bg = 0,
+ .charBaseIndex = 0,
+ .mapBaseIndex = 29,
+ .screenSize = 0,
+ .paletteMode = 0,
+ .priority = 0,
+ .baseTile = 0x000
+ }, {
+ .bg = 3,
+ .charBaseIndex = 3,
+ .mapBaseIndex = 31,
+ .screenSize = 0,
+ .paletteMode = 0,
+ .priority = 3,
+ .baseTile = 0x000
+ }, {
+ .bg = 2,
+ .charBaseIndex = 2,
+ .mapBaseIndex = 30,
+ .screenSize = 0,
+ .paletteMode = 0,
+ .priority = 2,
+ .baseTile = 0x000
+ }, {
+ .bg = 1,
+ .charBaseIndex = 1,
+ .mapBaseIndex = 28,
+ .screenSize = 0,
+ .paletteMode = 0,
+ .priority = 0,
+ .baseTile = 0x000
+ }
+};
+
+static const struct WindowTemplate gUnknown_8466B20[] = {
+ {
+ .bg = 0,
+ .tilemapLeft = 5,
+ .tilemapTop = 15,
+ .width = 20,
+ .height = 4,
+ .paletteNum = 0x0f,
+ .baseBlock = 0x04f
+ }, {
+ .bg = 0,
+ .tilemapLeft = 0,
+ .tilemapTop = 0,
+ .width = 30,
+ .height = 2,
+ .paletteNum = 0x0e,
+ .baseBlock = 0x013
+ },
+ DUMMY_WIN_TEMPLATE
+};
+
+static const u16 gUnknown_8466B38[] = {
+ 0x00a4, 0x00a5, 0x00a6, 0x00c4, 0x00c5, 0x00c6, 0x00c7, 0x00e7, 0x012c, 0x014c, 0x0191, 0x01b1, 0x01f6, 0x0216, 0x0217, 0x0218, 0x0219, 0x0237, 0x0238, 0x0239
+};
+
+static const u16 gUnknown_8466B60[] = {
+ 0x00e4, 0x00e5, 0x00e6, 0x00f7, 0x00f8, 0x00f9, 0x0104, 0x0105, 0x0106, 0x0107, 0x010c, 0x0111, 0x0116, 0x0117, 0x0118, 0x0119, 0x0124, 0x0125, 0x0126, 0x0137, 0x0138, 0x0139
+};
+
+static const u16 gUnknown_8466B8C[] = {
+ 0x0144, 0x0145, 0x0146, 0x0157, 0x0158, 0x0159, 0x0164, 0x0165, 0x0166, 0x0167, 0x016c, 0x0171, 0x0176, 0x0177, 0x0178, 0x0179, 0x0184, 0x0185, 0x0186, 0x0197, 0x0198, 0x0199
+};
+
+static const u16 gUnknown_8466BB8[] = {
+ 0x01a4, 0x01a5, 0x01a6, 0x01b7, 0x01b8, 0x01b9, 0x01c4, 0x01c5, 0x01c6, 0x01c7, 0x01cc, 0x01d1, 0x01d6, 0x01d7, 0x01d8, 0x01d9, 0x01e4, 0x01e5, 0x01e6, 0x01f7, 0x01f8, 0x01f9
+};
+
+static const u16 gUnknown_8466BE4[] = {
+ 0x0204, 0x0205, 0x0206, 0x0224, 0x0225, 0x0226, 0x01e7, 0x0207, 0x018c, 0x01ac, 0x0131, 0x0151, 0x00d6, 0x00f6, 0x00b7, 0x00b8, 0x00b9, 0x00d7, 0x00d8, 0x00d9
+};
+
+static const struct UnkStruct_8466C0C gUnknown_8466C0C[] = {
+ { gUnknown_8466B38, NELEMS(gUnknown_8466B38) },
+ { gUnknown_8466B60, NELEMS(gUnknown_8466B60) },
+ { gUnknown_8466B8C, NELEMS(gUnknown_8466B8C) },
+ { gUnknown_8466BB8, NELEMS(gUnknown_8466BB8) },
+ { gUnknown_8466BE4, NELEMS(gUnknown_8466BE4) }
+};
+
+static const u8 gUnknown_8466C34[2] = {2, 4};
+
+static const struct WindowTemplate gUnknown_8466C38 = {
+ .bg = 0,
+ .tilemapLeft = 19,
+ .tilemapTop = 9,
+ .width = 6,
+ .height = 4,
+ .paletteNum = 15,
+ .baseBlock = 0x9F
+};
+
+static const u16 gUnknown_8466C40[][4] = {
+ {0x0229, 0x022a, 0x0249, 0x024a},
+ {0x022e, 0x022f, 0x024e, 0x024f},
+ {0x0233, 0x0234, 0x0253, 0x0254}
+};
+
+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);
+ }
+}
+
+static 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;
+ }
+}
+
+static 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;
+ }
+}
+
+static void sub_813F92C(void)
+{
+ sub_8141094();
+ if (sSlotMachineState != NULL)
+ {
+ Free(sSlotMachineState);
+ sSlotMachineState = NULL;
+ }
+}
+
+static void sub_813F94C(void)
+{
+ RunTasks();
+ AnimateSprites();
+ BuildOamBuffer();
+ UpdatePaletteFade();
+}
+
+static 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;
+ }
+}
+
+static 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;
+ }
+}
+
+static 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;
+ }
+}
+
+static 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;
+ }
+}
+
+static 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;
+ }
+}
+
+static 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;
+ }
+}
+
+static 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;
+}
+
+static 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);
+}
+
+static void sub_8140148(void)
+{
+ s32 i;
+
+ for (i = 0; i < 3; i++)
+ {
+ sSlotMachineState->field_14[i] = TRUE;
+ }
+}
+
+static 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;
+ }
+}
+
+static bool32 sub_81401A0(u16 whichReel)
+{
+ return sSlotMachineState->field_14[whichReel];
+}
+
+static 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;
+}
+
+static 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;
+}
+
+static 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;
+}
+
+static 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;
+}
+
+static 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;
+}
+
+#ifdef NONMATCHING
+static bool32 sub_81406E8(s32 a0, s32 a1, s32 a2)
+{
+ u8 sp0[9];
+ s32 r3, r6;
+ s32 i;
+
+ r6 = sSlotMachineState->field_20[sSlotMachineState->field_32[0]] + 1;
+ r3 = sSlotMachineState->field_20[sSlotMachineState->field_32[1]] + 1;
+ a1++;
+ if (r6 >= 21)
+ r6 = 0;
+ if (r3 >= 21)
+ r3 = 0;
+ if (a1 >= 21)
+ a1 = 0;
+ for (i = 0; i < 3; i++)
+ {
+ sp0[sSlotMachineState->field_32[0] * 3 + i] = gUnknown_8464926[sSlotMachineState->field_32[0]][r6];
+ sp0[sSlotMachineState->field_32[1] * 3 + i] = gUnknown_8464926[sSlotMachineState->field_32[1]][r3];
+ sp0[a0 * 3 + i] = gUnknown_8464926[a0][a1];
+ r6++;
+ if (r6 >= 21)
+ r6 = 0;
+ r3++;
+ if (r3 >= 21)
+ r3 = 0;
+ a1++;
+ if (a1 >= 21)
+ a1++;
+ }
+ switch (a2)
+ {
+ case 0:
+ for (i = 0; i < 3; i++)
+ {
+ if (sub_81408F4(1, sp0[i]))
+ return FALSE;
+ }
+ for (i = 0; i < 5; i++)
+ {
+ if (sp0[gUnknown_84648AE[i][0]] == sp0[gUnknown_84648AE[i][1]] && sp0[gUnknown_84648AE[i][0]] == sp0[gUnknown_84648AE[i][2]])
+ return FALSE;
+ }
+ return TRUE;
+ case 1:
+ for (i = 0; i < 5; i++)
+ {
+ if (sp0[gUnknown_84648AE[i][0]] == sp0[gUnknown_84648AE[i][1]] && sub_81408F4(a2, sp0[gUnknown_84648AE[i][0]]))
+ return FALSE;
+ }
+ for (i = 0; i < 3; i++)
+ {
+ if (sub_81408F4(a2, sp0[i]))
+ return TRUE;
+ }
+ return FALSE;
+ case 2:
+ for (i = 0; i < 5; i++)
+ {
+ if (sp0[gUnknown_84648AE[i][0]] == sp0[gUnknown_84648AE[i][1]] && sub_81408F4(a2, sp0[gUnknown_84648AE[i][0]]))
+ return TRUE;
+ }
+ return FALSE;
+ }
+ for (i = 0; i < 5; i++)
+ {
+ if (sp0[gUnknown_84648AE[i][0]] == sp0[gUnknown_84648AE[i][1]] && sp0[gUnknown_84648AE[i][0]] == sp0[gUnknown_84648AE[i][2]] && sub_81408F4(a2, sp0[gUnknown_84648AE[i][0]]))
+ return TRUE;
+ }
+ return FALSE;
+}
+#else
+NAKED
+static bool32 sub_81406E8(s32 a0, s32 a1, s32 a2)
+{
+ asm_unified("\tpush {r4-r7,lr}\n"
+ "\tmov r7, r10\n"
+ "\tmov r6, r9\n"
+ "\tmov r5, r8\n"
+ "\tpush {r5-r7}\n"
+ "\tsub sp, 0x10\n"
+ "\tadds r7, r0, 0\n"
+ "\tadds r5, r1, 0\n"
+ "\tmov r8, r2\n"
+ "\tldr r0, _081407C8 @ =sSlotMachineState\n"
+ "\tldr r2, [r0]\n"
+ "\tmovs r1, 0x32\n"
+ "\tldrsh r0, [r2, r1]\n"
+ "\tlsls r0, 1\n"
+ "\tadds r1, r2, 0\n"
+ "\tadds r1, 0x20\n"
+ "\tadds r0, r1, r0\n"
+ "\tmovs r3, 0\n"
+ "\tldrsh r0, [r0, r3]\n"
+ "\tadds r6, r0, 0x1\n"
+ "\tmovs r3, 0x34\n"
+ "\tldrsh r0, [r2, r3]\n"
+ "\tlsls r0, 1\n"
+ "\tadds r1, r0\n"
+ "\tmovs r3, 0\n"
+ "\tldrsh r0, [r1, r3]\n"
+ "\tadds r3, r0, 0x1\n"
+ "\tadds r5, 0x1\n"
+ "\tcmp r6, 0x14\n"
+ "\tble _08140726\n"
+ "\tmovs r6, 0\n"
+ "_08140726:\n"
+ "\tcmp r3, 0x14\n"
+ "\tble _0814072C\n"
+ "\tmovs r3, 0\n"
+ "_0814072C:\n"
+ "\tcmp r5, 0x14\n"
+ "\tble _08140732\n"
+ "\tmovs r5, 0\n"
+ "_08140732:\n"
+ "\tmovs r4, 0\n"
+ "\tlsls r1, r7, 1\n"
+ "\tlsls r0, r7, 2\n"
+ "\tmov r9, r2\n"
+ "\tldr r2, _081407CC @ =gUnknown_8464926\n"
+ "\tmov r10, r2\n"
+ "\tadds r1, r7\n"
+ "\tadd r1, sp\n"
+ "\tmov r12, r1\n"
+ "\tadds r0, r7\n"
+ "\tlsls r0, 2\n"
+ "\tadds r0, r7\n"
+ "\tstr r0, [sp, 0xC]\n"
+ "_0814074C:\n"
+ "\tmov r7, r9\n"
+ "\tmovs r0, 0x32\n"
+ "\tldrsh r1, [r7, r0]\n"
+ "\tlsls r0, r1, 1\n"
+ "\tadds r0, r1\n"
+ "\tadds r0, r4\n"
+ "\tmov r7, sp\n"
+ "\tadds r2, r7, r0\n"
+ "\tlsls r0, r1, 2\n"
+ "\tadds r0, r1\n"
+ "\tlsls r0, 2\n"
+ "\tadds r0, r1\n"
+ "\tadds r0, r6, r0\n"
+ "\tadd r0, r10\n"
+ "\tldrb r0, [r0]\n"
+ "\tstrb r0, [r2]\n"
+ "\tmov r0, r9\n"
+ "\tmovs r2, 0x34\n"
+ "\tldrsh r1, [r0, r2]\n"
+ "\tlsls r0, r1, 1\n"
+ "\tadds r0, r1\n"
+ "\tadds r0, r4\n"
+ "\tadds r2, r7, r0\n"
+ "\tlsls r0, r1, 2\n"
+ "\tadds r0, r1\n"
+ "\tlsls r0, 2\n"
+ "\tadds r0, r1\n"
+ "\tadds r0, r3, r0\n"
+ "\tadd r0, r10\n"
+ "\tldrb r0, [r0]\n"
+ "\tstrb r0, [r2]\n"
+ "\tldr r7, [sp, 0xC]\n"
+ "\tadds r0, r5, r7\n"
+ "\tadd r0, r10\n"
+ "\tldrb r0, [r0]\n"
+ "\tmov r1, r12\n"
+ "\tstrb r0, [r1]\n"
+ "\tadds r6, 0x1\n"
+ "\tcmp r6, 0x14\n"
+ "\tble _0814079E\n"
+ "\tmovs r6, 0\n"
+ "_0814079E:\n"
+ "\tadds r3, 0x1\n"
+ "\tcmp r3, 0x14\n"
+ "\tble _081407A6\n"
+ "\tmovs r3, 0\n"
+ "_081407A6:\n"
+ "\tadds r5, 0x1\n"
+ "\tcmp r5, 0x14\n"
+ "\tble _081407AE\n"
+ "\tmovs r5, 0\n"
+ "_081407AE:\n"
+ "\tmovs r2, 0x1\n"
+ "\tadd r12, r2\n"
+ "\tadds r4, 0x1\n"
+ "\tcmp r4, 0x2\n"
+ "\tble _0814074C\n"
+ "\tmov r3, r8\n"
+ "\tcmp r3, 0x1\n"
+ "\tbeq _08140828\n"
+ "\tcmp r3, 0x1\n"
+ "\tbgt _081407D0\n"
+ "\tcmp r3, 0\n"
+ "\tbeq _081407D8\n"
+ "\tb _081408A0\n"
+ "\t.align 2, 0\n"
+ "_081407C8: .4byte sSlotMachineState\n"
+ "_081407CC: .4byte gUnknown_8464926\n"
+ "_081407D0:\n"
+ "\tmov r6, r8\n"
+ "\tcmp r6, 0x2\n"
+ "\tbeq _08140870\n"
+ "\tb _081408A0\n"
+ "_081407D8:\n"
+ "\tmovs r4, 0\n"
+ "_081407DA:\n"
+ "\tmov r7, sp\n"
+ "\tadds r0, r7, r4\n"
+ "\tldrb r1, [r0]\n"
+ "\tmovs r0, 0x1\n"
+ "\tbl sub_81408F4\n"
+ "\tcmp r0, 0\n"
+ "\tbne _081408DC_return_false\n"
+ "\tadds r4, 0x1\n"
+ "\tcmp r4, 0x2\n"
+ "\tble _081407DA\n"
+ "\tmovs r4, 0\n"
+ "\tldr r2, _08140824 @ =gUnknown_84648AE\n"
+ "\tmovs r3, 0\n"
+ "\tadds r5, r2, 0x2\n"
+ "_081407F8:\n"
+ "\tldrb r0, [r2]\n"
+ "\tmov r6, sp\n"
+ "\tadds r1, r6, r0\n"
+ "\tldrb r0, [r2, 0x1]\n"
+ "\tadd r0, sp\n"
+ "\tldrb r1, [r1]\n"
+ "\tldrb r0, [r0]\n"
+ "\tcmp r1, r0\n"
+ "\tbne _08140816\n"
+ "\tadds r0, r3, r5\n"
+ "\tldrb r0, [r0]\n"
+ "\tadd r0, sp\n"
+ "\tldrb r0, [r0]\n"
+ "\tcmp r1, r0\n"
+ "\tbeq _081408DC_return_false\n"
+ "_08140816:\n"
+ "\tadds r2, 0x3\n"
+ "\tadds r3, 0x3\n"
+ "\tadds r4, 0x1\n"
+ "\tcmp r4, 0x4\n"
+ "\tble _081407F8\n"
+ "_08140820_return_true:\n"
+ "\tmovs r0, 0x1\n"
+ "\tb _081408DE\n"
+ "\t.align 2, 0\n"
+ "_08140824: .4byte gUnknown_84648AE\n"
+ "_08140828:\n"
+ "\tmovs r4, 0\n"
+ "\tldr r5, _0814086C @ =gUnknown_84648AE\n"
+ "_0814082C:\n"
+ "\tldrb r0, [r5]\n"
+ "\tmov r7, sp\n"
+ "\tadds r2, r7, r0\n"
+ "\tldrb r0, [r5, 0x1]\n"
+ "\tadds r1, r7, r0\n"
+ "\tldrb r0, [r2]\n"
+ "\tldrb r1, [r1]\n"
+ "\tcmp r0, r1\n"
+ "\tbne _0814084A\n"
+ "\tadds r1, r0, 0\n"
+ "\tmov r0, r8\n"
+ "\tbl sub_81408F4\n"
+ "\tcmp r0, 0\n"
+ "\tbne _081408DC_return_false\n"
+ "_0814084A:\n"
+ "\tadds r5, 0x3\n"
+ "\tadds r4, 0x1\n"
+ "\tcmp r4, 0x4\n"
+ "\tble _0814082C\n"
+ "\tmovs r4, 0\n"
+ "_08140854:\n"
+ "\tmov r1, sp\n"
+ "\tadds r0, r1, r4\n"
+ "\tldrb r1, [r0]\n"
+ "\tmov r0, r8\n"
+ "\tbl sub_81408F4\n"
+ "\tcmp r0, 0\n"
+ "\tbne _08140820_return_true\n"
+ "\tadds r4, 0x1\n"
+ "\tcmp r4, 0x2\n"
+ "\tble _08140854\n"
+ "\tb _081408DC_return_false\n"
+ "\t.align 2, 0\n"
+ "_0814086C: .4byte gUnknown_84648AE\n"
+ "_08140870:\n"
+ "\tmovs r4, 0\n"
+ "\tldr r5, _0814089C @ =gUnknown_84648AE\n"
+ "_08140874:\n"
+ "\tldrb r0, [r5]\n"
+ "\tmov r3, sp\n"
+ "\tadds r2, r3, r0\n"
+ "\tldrb r0, [r5, 0x1]\n"
+ "\tadds r1, r3, r0\n"
+ "\tldrb r0, [r2]\n"
+ "\tldrb r1, [r1]\n"
+ "\tcmp r0, r1\n"
+ "\tbne _08140892\n"
+ "\tadds r1, r0, 0\n"
+ "\tmov r0, r8\n"
+ "\tbl sub_81408F4\n"
+ "\tcmp r0, 0\n"
+ "\tbne _08140820_return_true\n"
+ "_08140892:\n"
+ "\tadds r5, 0x3\n"
+ "\tadds r4, 0x1\n"
+ "\tcmp r4, 0x4\n"
+ "\tble _08140874\n"
+ "\tb _081408DC_return_false\n"
+ "\t.align 2, 0\n"
+ "_0814089C: .4byte gUnknown_84648AE\n"
+ "_081408A0:\n"
+ "\tmovs r4, 0\n"
+ "\tldr r5, _081408F0 @ =gUnknown_84648AE\n"
+ "\tadds r7, r5, 0\n"
+ "\tmovs r6, 0\n"
+ "_081408A8:\n"
+ "\tldrb r0, [r5]\n"
+ "\tmov r1, sp\n"
+ "\tadds r2, r1, r0\n"
+ "\tadds r0, r7, 0x1\n"
+ "\tadds r0, r6, r0\n"
+ "\tldrb r0, [r0]\n"
+ "\tadd r0, sp\n"
+ "\tldrb r1, [r2]\n"
+ "\tldrb r0, [r0]\n"
+ "\tcmp r1, r0\n"
+ "\tbne _081408D2\n"
+ "\tldrb r0, [r5, 0x2]\n"
+ "\tadd r0, sp\n"
+ "\tldrb r0, [r0]\n"
+ "\tcmp r1, r0\n"
+ "\tbne _081408D2\n"
+ "\tmov r0, r8\n"
+ "\tbl sub_81408F4\n"
+ "\tcmp r0, 0\n"
+ "\tbne _08140820_return_true\n"
+ "_081408D2:\n"
+ "\tadds r5, 0x3\n"
+ "\tadds r6, 0x3\n"
+ "\tadds r4, 0x1\n"
+ "\tcmp r4, 0x4\n"
+ "\tble _081408A8\n"
+ "_081408DC_return_false:\n"
+ "\tmovs r0, 0\n"
+ "_081408DE:\n"
+ "\tadd sp, 0x10\n"
+ "\tpop {r3-r5}\n"
+ "\tmov r8, r3\n"
+ "\tmov r9, r4\n"
+ "\tmov r10, r5\n"
+ "\tpop {r4-r7}\n"
+ "\tpop {r1}\n"
+ "\tbx r1\n"
+ "\t.align 2, 0\n"
+ "_081408F0: .4byte gUnknown_84648AE");
+}
+#endif //NONMATCHING
+
+static bool32 sub_81408F4(s32 a0, s32 a1)
+{
+ switch (a0)
+ {
+ case 0:
+ return a1 ^ 4 ? TRUE : FALSE;
+ case 1:
+ case 2:
+ return a1 == 4 ? TRUE : FALSE;
+ case 3:
+ return a1 == 5 || a1 == 6 ? TRUE : FALSE;
+ case 4:
+ return a1 == 2 || a1 == 3 ? TRUE : FALSE;
+ case 5:
+ return a1 == 1 ? TRUE : FALSE;
+ case 6:
+ return a1 == 0 ? TRUE : FALSE;
+ default:
+ return FALSE;
+ }
+}
+
+static u8 sub_814096C(s32 a0)
+{
+ switch (a0)
+ {
+ default:
+ case 4:
+ return 1;
+ case 5:
+ case 6:
+ return 3;
+ case 2:
+ case 3:
+ return 4;
+ case 1:
+ return 5;
+ case 0:
+ return 6;
+ }
+}
+
+static void sub_81409B4(void)
+{
+ u16 r2 = Random() / 4;
+ s32 i;
+ const u16 * r4 = gUnknown_84648D2[sSlotMachineState->machineidx];
+ for (i = 0; i < 6; i++)
+ {
+ if (r2 < r4[i])
+ break;
+ }
+ if (sSlotMachineState->field_08 < 5)
+ {
+ if (sSlotMachineState->field_0C == 0)
+ {
+ if ((Random() & 0x3FFF) < r4[6])
+ sSlotMachineState->field_0C = (Random() & 1) ? 5 : 60;
+ }
+ if (sSlotMachineState->field_0C != 0)
+ {
+ if (i == 0 && (Random() & 0x3FFF) < 0x2CCC)
+ sSlotMachineState->field_0C = (Random() & 1) ? 5 : 60;
+ sSlotMachineState->field_0C--;
+ }
+ sSlotMachineState->field_08 = i;
+ }
+}
+
+static void sub_8140A70(void)
+{
+ sSlotMachineState->field_08 = 0;
+}
+
+static u16 sub_8140A80(void)
+{
+ u8 sp0[9] = {};
+ s32 i;
+ s32 r4, r3, r2;
+ s32 r9;
+
+ for (i = 0; i < 5; i++)
+ sSlotMachineState->field_3C[i] = 0;
+
+ r9 = 0;
+ r4 = sSlotMachineState->field_20[0];
+ r3 = sSlotMachineState->field_20[1];
+ r2 = sSlotMachineState->field_20[2];
+
+ for (i = 0; i < 3; i++)
+ {
+ r4++;
+ if (r4 >= 21)
+ r4 = 0;
+ r3++;
+ if (r3 >= 21)
+ r3 = 0;
+ r2++;
+ if (r2 >= 21)
+ r2 = 0;
+ sp0[0 * 3 + i] = gUnknown_8464926[0][r4];
+ sp0[1 * 3 + i] = gUnknown_8464926[1][r3];
+ sp0[2 * 3 + i] = gUnknown_8464926[2][r2];
+ }
+ sSlotMachineState->payout = 0;
+ for (i = 0; i < 5; i++)
+ {
+ if (sSlotMachineState->bet >= gUnknown_84648BD[i][3])
+ {
+ if (sub_81408F4(1, sp0[gUnknown_84648BD[i][0]]))
+ r3 = sub_81408F4(2, sp0[gUnknown_84648BD[i][1]]) ? 2 : 1;
+ else if (sp0[gUnknown_84648BD[i][0]] == sp0[gUnknown_84648BD[i][1]] && sp0[gUnknown_84648BD[i][0]] == sp0[gUnknown_84648BD[i][2]])
+ r3 = sub_814096C(sp0[gUnknown_84648BD[i][0]]);
+ else
+ r3 = 0;
+ if (r3 != 0)
+ {
+ sSlotMachineState->field_3C[i] = 1;
+ sSlotMachineState->payout += gUnknown_8464966[r3];
+ }
+ if (r3 > r9)
+ r9 = r3;
+ }
+ }
+ return r9;
+}
+
+static u16 sub_8140BDC(void)
+{
+ return sSlotMachineState->payout;
+}
+
+static u8 sub_8140BEC(void)
+{
+ return sSlotMachineState->bet;
+}
+
+static bool32 sub_8140BF8(s32 a0)
+{
+ return sSlotMachineState->field_3C[a0];
+}
+
+static bool32 sub_8140C0C(void)
+{
+ s32 i;
+
+ for (i = 0; i < NELEMS(gUnknown_84655B0); i++)
+ LoadCompressedSpriteSheet(&gUnknown_84655B0[i]);
+ LoadSpritePalettes(gUnknown_84655C8);
+ sSlotMachineGfxManager = Alloc(sizeof(*sSlotMachineGfxManager));
+ if (sSlotMachineGfxManager == NULL)
+ return FALSE;
+ sub_8140C6C(sSlotMachineGfxManager);
+ return TRUE;
+}
+
+static void sub_8140C50(void)
+{
+ if (sSlotMachineGfxManager != NULL)
+ {
+ Free(sSlotMachineGfxManager);
+ sSlotMachineGfxManager = NULL;
+ }
+}
+
+static void sub_8140C6C(struct SlotMachineGfxManager * manager)
+{
+ s32 i, j;
+
+ for (i = 0; i < 3; i++)
+ {
+ manager->field_00[i] = 0;
+ for (j = 0; j < 5; j++)
+ {
+ manager->field_0C[i][j] = NULL;
+ }
+ }
+}
+
+static void sub_8140CA0(void)
+{
+ struct Sprite * sprite;
+ s32 i, j;
+ s32 spriteId;
+ s32 animId;
+ for (i = 0; i < 3; i++)
+ {
+ for (j = 0; j < 5; j++)
+ {
+ spriteId = CreateSprite(&gUnknown_84657E4, 80 + 40 * i, 44 + 24 * j, 2);
+ animId = gUnknown_8464926[i][j];
+ sprite = &gSprites[spriteId];
+ StartSpriteAnim(sprite, animId);
+ sprite->oam.paletteNum = IndexOfSpritePaletteTag(gUnknown_8465608[animId]);
+ sprite->data[0] = i;
+ sprite->data[1] = j;
+ sprite->data[2] = j;
+ sprite->data[3] = 0;
+ sprite->oam.matrixNum = 0;
+ sSlotMachineGfxManager->field_0C[i][j] = sprite;
+ sSlotMachineGfxManager->field_70 = (vu16 *)(OAM + 0 * sizeof(struct OamData) + offsetof(struct OamData, affineParam));
+ }
+ }
+}
+
+static void sub_8140D7C(const s16 * a0, const s16 * a1)
+{
+ s32 i, j;
+ s32 r6, r10;
+
+ for (i = 0; i < 3; i++)
+ {
+ r6 = *a0;
+ r10 = *a1 * 8;
+ for (j = 0; j < 5; j++)
+ {
+ sSlotMachineGfxManager->field_0C[i][j]->pos2.y = r10;
+ {
+ s32 r4 = gUnknown_8464926[i][r6];
+ struct Sprite * sprite = sSlotMachineGfxManager->field_0C[i][j];
+ StartSpriteAnim(sprite, r4);
+ }
+ {
+ s32 r4 = gUnknown_8464926[i][r6];
+ struct Sprite * sprite = sSlotMachineGfxManager->field_0C[i][j];
+ StartSpriteAnim(sprite, r4);
+ }
+ sSlotMachineGfxManager->field_0C[i][j]->oam.paletteNum = IndexOfSpritePaletteTag(gUnknown_8465608[gUnknown_8464926[i][r6]]);
+ r6++;
+ if (r6 >= 21)
+ r6 = 0;
+ }
+ a0++;
+ a1++;
+ }
+}
+
+static void sub_8140E40(void)
+{
+ s32 vcount = REG_VCOUNT - 0x2B;
+ if (vcount >= 0 && vcount < 0x54)
+ {
+ *sSlotMachineGfxManager->field_70 = gUnknown_8465616[vcount];
+ REG_BLDY = gUnknown_84656D6[vcount];
+ }
+ else
+ {
+ *sSlotMachineGfxManager->field_70 = 0x100;
+ REG_BLDY = 0;
+ }
+}
+
+static void sub_8140E9C(void)
+{
+ s32 i;
+ s32 spriteId;
+
+ for (i = 0; i < 4; i++)
+ {
+ spriteId = CreateSprite(&gUnknown_846587C, 0x55 + 7 * i, 30, 0);
+ sSlotMachineGfxManager->field_48[i] = &gSprites[spriteId];
+ spriteId = CreateSprite(&gUnknown_846587C, 0x85 + 7 * i, 30, 0);
+ sSlotMachineGfxManager->field_58[i] = &gSprites[spriteId];
+ }
+}
+
+static void sub_8140F2C(void)
+{
+ s32 coins = GetCoins();
+ s32 payout = sub_8140BDC();
+ s32 i;
+ s32 divisor = 1000;
+ s32 quotient;
+
+ for (i = 0; i < 4; i++)
+ {
+ quotient = coins / divisor;
+ StartSpriteAnim(sSlotMachineGfxManager->field_48[i], quotient);
+ coins -= quotient * divisor;
+ quotient = payout / divisor;
+ StartSpriteAnim(sSlotMachineGfxManager->field_58[i], quotient);
+ payout -= quotient * divisor;
+ divisor /= 10;
+ }
+}
+
+static void sub_8140FC4(void)
+{
+ s32 spriteId;
+
+ spriteId = CreateSprite(&gUnknown_84658D8, 0x10, 0x88, 1);
+ sSlotMachineGfxManager->field_68[0] = &gSprites[spriteId];
+ spriteId = CreateSprite(&gUnknown_84658D8, 0xE0, 0x88, 1);
+ sSlotMachineGfxManager->field_68[1] = &gSprites[spriteId];
+ sSlotMachineGfxManager->field_68[1]->hFlip = TRUE;
+}
+
+static void sub_8141020(u8 a0)
+{
+ s32 i;
+ for (i = 0; i < 2; i++)
+ {
+ StartSpriteAnim(sSlotMachineGfxManager->field_68[i], a0);
+ }
+}
+
+static bool32 sub_814104C(void)
+{
+ s32 i;
+
+ struct SlotMachineSetupTaskData * ptr = Alloc(sizeof(struct SlotMachineSetupTaskData));
+ if (ptr == NULL)
+ return FALSE;
+ for (i = 0; i < 8; i++)
+ ptr->field_0000[i].unk3 = 0;
+ ptr->field_0028 = 0;
+ SetWordTaskArg(CreateTask(sub_81410CC, 2), 0, (uintptr_t)ptr);
+ return FALSE;
+}
+
+static void sub_8141094(void)
+{
+ if (FuncIsActiveTask(sub_81410CC))
+ {
+ Free(sub_814112C());
+ DestroyTask(FindTaskIdByFunc(sub_81410CC));
+ }
+ sub_8140C50();
+ FreeAllWindowBuffers();
+}
+
+static void sub_81410CC(u8 taskId)
+{
+ struct SlotMachineSetupTaskData * ptr = (void *)GetWordTaskArg(taskId, 0);
+ s32 i;
+
+ for (i = 0; i < 8; i++)
+ {
+ if (ptr->field_0000[i].unk3)
+ ptr->field_0000[i].unk3 = gUnknown_84658F0[ptr->field_0000[i].unk0](&ptr->field_0000[i].unk2, ptr);
+ }
+}
+
+static void sub_8141118(void)
+{
+ TransferPlttBuffer();
+ LoadOam();
+ ProcessSpriteCopyRequests();
+}
+
+static struct SlotMachineSetupTaskData * sub_814112C(void)
+{
+ return (void *)GetWordTaskArg(FindTaskIdByFunc(sub_81410CC), 0);
+}
+
+static void sub_8141148(u16 a0, u8 a1)
+{
+ struct SlotMachineSetupTaskData * ptr = sub_814112C();
+ ptr->field_0000[a1].unk0 = a0;
+ ptr->field_0000[a1].unk2 = 0;
+ ptr->field_0000[a1].unk3 = gUnknown_84658F0[a0](&ptr->field_0000[a1].unk2, ptr);
+}
+
+static bool32 sub_8141180(u8 a0)
+{
+ return sub_814112C()->field_0000[a0].unk3;
+}
+
+#ifdef NONMATCHING
+static bool8 sub_8141198(u8 * state, struct SlotMachineSetupTaskData * ptr)
+{
+ u16 pal;
+ struct TextColor textColor;
+ u32 x;
+
+ switch (*state)
+ {
+ case 0:
+ BlendPalettes(0xFFFFFFFF, 16, RGB_BLACK);
+ (*state)++;
+ break;
+ case 1:
+ SetVBlankCallback(NULL);
+ ResetSpriteData();
+ FreeAllSpritePalettes();
+ RequestDma3Fill(0, (void *)OAM, OAM_SIZE, 1);
+ RequestDma3Fill(0, (void *)VRAM, 0x20, 1);
+ RequestDma3Fill(0, (void *)(VRAM + 0xC000), 0x20, 1);
+ SetGpuReg(REG_OFFSET_DISPCNT, 0);
+ ResetBgPositions();
+ ResetBgsAndClearDma3BusyFlags(0);
+ InitBgsFromTemplates(0, gUnknown_8466B10, NELEMS(gUnknown_8466B10));
+ InitWindows(gUnknown_8466B20);
+
+ SetBgTilemapBuffer(3, ptr->field_205C);
+ FillBgTilemapBufferRect_Palette0(3, 0, 0, 0, 32, 32);
+ CopyBgTilemapBufferToVram(3);
+
+ ResetTempTileDataBuffers();
+ DecompressAndCopyTileDataToVram(2, gUnknown_84659D0, 0, 0x00, 0);
+ DecompressAndCopyTileDataToVram(2, gUnknown_846653C, 0, 0xC0, 0);
+ SetBgTilemapBuffer(2, ptr->field_185C);
+ CopyToBgTilemapBuffer(2, gUnknown_84661D4, 0, 0x00);
+ CopyBgTilemapBufferToVram(2);
+ LoadPalette(gUnknown_8465930, 0x00, 0xA0);
+ LoadPalette(gUnknown_84664BC, 0x50, 0x20);
+ LoadPalette(gUnknown_84665C0, 0x70, 0x60);
+ pal = RGB(30, 30, 31);
+ LoadPalette(&pal, 0x00, 0x02);
+ LoadUserWindowBorderGfx(0, 0x00A, 0xD0);
+ sub_814FDA0(0, 0x001, 0xF0);
+
+ SetBgTilemapBuffer(0, ptr->field_085C);
+ FillBgTilemapBufferRect_Palette0(0, 0, 0, 2, 32, 30);
+ DecompressAndCopyTileDataToVram(1, gUnknown_8466620, 0, 0, 0);
+ DecompressAndCopyTileDataToVram(1, gUnknown_8466998, 0, 0, 1);
+ CopyBgTilemapBufferToVram(1);
+
+ LoadPalette(stdpal_get(2), 0xE0, 0x20);
+ FillWindowPixelBuffer(1, 0xFF);
+ PutWindowTilemap(1);
+
+ x = 0xEC - GetStringWidth(0, gString_SlotMachineControls, 0);
+ textColor.fgColor = 15;
+ textColor.bgColor = 1;
+ textColor.shadowColor = 2;
+ AddTextPrinterParameterized3(1, 0, x, 0, &textColor, 0, gString_SlotMachineControls);
+ CopyBgTilemapBufferToVram(0);
+
+ SetGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_MODE_0 | 0x20 | DISPCNT_OBJ_1D_MAP | DISPCNT_OBJ_ON);
+ SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG3 | BLDCNT_TGT1_OBJ | BLDCNT_TGT1_BD | BLDCNT_EFFECT_DARKEN);
+ sub_8140C0C();
+ sub_8140CA0();
+ sub_8140E9C();
+ sub_8140FC4();
+ sub_8140F2C();
+ BlendPalettes(0xFFFFFFFF, 0x10, RGB_BLACK);
+ SetVBlankCallback(sub_8141118);
+ SetHBlankCallback(sub_8140E40);
+ (*state)++;
+ break;
+ case 2:
+ if (!FreeTempTileDataBuffersIfPossible())
+ {
+ ShowBg(0);
+ ShowBg(3);
+ ShowBg(2);
+ HideBg(1);
+ sub_8141B34();
+ BlendPalettes(0xFFFFFFFF, 0x10, RGB_BLACK);
+ BeginNormalPaletteFade(0xFFFFFFFF, -1, 16, 0, RGB_BLACK);
+ EnableInterrupts(INTR_FLAG_VBLANK | INTR_FLAG_HBLANK);
+ (*state)++;
+ }
+ break;
+ case 3:
+ UpdatePaletteFade();
+ if (!gPaletteFade.active)
+ return FALSE;
+ break;
+ }
+ return TRUE;
+}
+#else
+NAKED
+static bool8 sub_8141198(u8 * state, struct SlotMachineSetupTaskData * ptr)
+{
+ asm_unified("\tpush {r4-r7,lr}\n"
+ "\tmov r7, r8\n"
+ "\tpush {r7}\n"
+ "\tsub sp, 0x14\n"
+ "\tadds r7, r0, 0\n"
+ "\tmov r8, r1\n"
+ "\tldrb r6, [r7]\n"
+ "\tcmp r6, 0x1\n"
+ "\tbeq _081411D0\n"
+ "\tcmp r6, 0x1\n"
+ "\tbgt _081411B4\n"
+ "\tcmp r6, 0\n"
+ "\tbeq _081411C2\n"
+ "\tb _08141450\n"
+ "_081411B4:\n"
+ "\tcmp r6, 0x2\n"
+ "\tbne _081411BA\n"
+ "\tb _081413E4\n"
+ "_081411BA:\n"
+ "\tcmp r6, 0x3\n"
+ "\tbne _081411C0\n"
+ "\tb _08141436\n"
+ "_081411C0:\n"
+ "\tb _08141450\n"
+ "_081411C2:\n"
+ "\tmovs r0, 0x1\n"
+ "\tnegs r0, r0\n"
+ "\tmovs r1, 0x10\n"
+ "\tmovs r2, 0\n"
+ "\tbl BlendPalettes\n"
+ "\tb _0814142E\n"
+ "_081411D0:\n"
+ "\tmovs r0, 0\n"
+ "\tbl SetVBlankCallback\n"
+ "\tbl ResetSpriteData\n"
+ "\tbl FreeAllSpritePalettes\n"
+ "\tmovs r1, 0xE0\n"
+ "\tlsls r1, 19\n"
+ "\tmovs r2, 0x80\n"
+ "\tlsls r2, 3\n"
+ "\tmovs r0, 0\n"
+ "\tmovs r3, 0x1\n"
+ "\tbl RequestDma3Fill\n"
+ "\tmovs r1, 0xC0\n"
+ "\tlsls r1, 19\n"
+ "\tmovs r0, 0\n"
+ "\tmovs r2, 0x20\n"
+ "\tmovs r3, 0x1\n"
+ "\tbl RequestDma3Fill\n"
+ "\tldr r1, _0814139C @ =0x0600c000\n"
+ "\tmovs r0, 0\n"
+ "\tmovs r2, 0x20\n"
+ "\tmovs r3, 0x1\n"
+ "\tbl RequestDma3Fill\n"
+ "\tmovs r0, 0\n"
+ "\tmovs r1, 0\n"
+ "\tbl SetGpuReg\n"
+ "\tbl ResetBgPositions\n"
+ "\tmovs r0, 0\n"
+ "\tbl ResetBgsAndClearDma3BusyFlags\n"
+ "\tldr r1, _081413A0 @ =gUnknown_8466B10\n"
+ "\tmovs r0, 0\n"
+ "\tmovs r2, 0x4\n"
+ "\tbl InitBgsFromTemplates\n"
+ "\tldr r0, _081413A4 @ =gUnknown_8466B20\n"
+ "\tbl InitWindows\n"
+ "\tldr r1, _081413A8 @ =0x0000205c\n"
+ "\tadd r1, r8\n"
+ "\tmovs r0, 0x3\n"
+ "\tbl SetBgTilemapBuffer\n"
+ "\tmovs r4, 0x20\n"
+ "\tstr r4, [sp]\n"
+ "\tstr r4, [sp, 0x4]\n"
+ "\tmovs r0, 0x3\n"
+ "\tmovs r1, 0\n"
+ "\tmovs r2, 0\n"
+ "\tmovs r3, 0\n"
+ "\tbl FillBgTilemapBufferRect_Palette0\n"
+ "\tmovs r0, 0x3\n"
+ "\tbl CopyBgTilemapBufferToVram\n"
+ "\tbl ResetTempTileDataBuffers\n"
+ "\tldr r1, _081413AC @ =gUnknown_84659D0\n"
+ "\tmovs r5, 0\n"
+ "\tstr r5, [sp]\n"
+ "\tmovs r0, 0x2\n"
+ "\tmovs r2, 0\n"
+ "\tmovs r3, 0\n"
+ "\tbl DecompressAndCopyTileDataToVram\n"
+ "\tldr r1, _081413B0 @ =gUnknown_846653C\n"
+ "\tstr r5, [sp]\n"
+ "\tmovs r0, 0x2\n"
+ "\tmovs r2, 0\n"
+ "\tmovs r3, 0xC0\n"
+ "\tbl DecompressAndCopyTileDataToVram\n"
+ "\tldr r1, _081413B4 @ =0x0000185c\n"
+ "\tadd r1, r8\n"
+ "\tmovs r0, 0x2\n"
+ "\tbl SetBgTilemapBuffer\n"
+ "\tldr r1, _081413B8 @ =gUnknown_84661D4\n"
+ "\tmovs r0, 0x2\n"
+ "\tmovs r2, 0\n"
+ "\tmovs r3, 0\n"
+ "\tbl CopyToBgTilemapBuffer\n"
+ "\tmovs r0, 0x2\n"
+ "\tbl CopyBgTilemapBufferToVram\n"
+ "\tldr r0, _081413BC @ =gUnknown_8465930\n"
+ "\tmovs r1, 0\n"
+ "\tmovs r2, 0xA0\n"
+ "\tbl LoadPalette\n"
+ "\tldr r0, _081413C0 @ =gUnknown_84664BC\n"
+ "\tmovs r1, 0x50\n"
+ "\tmovs r2, 0x20\n"
+ "\tbl LoadPalette\n"
+ "\tldr r0, _081413C4 @ =gUnknown_84665C0\n"
+ "\tmovs r1, 0x70\n"
+ "\tmovs r2, 0x60\n"
+ "\tbl LoadPalette\n"
+ "\tldr r1, _081413C8 @ =0x00007fde\n"
+ "\tadd r0, sp, 0xC\n"
+ "\tstrh r1, [r0]\n"
+ "\tmovs r1, 0\n"
+ "\tmovs r2, 0x2\n"
+ "\tbl LoadPalette\n"
+ "\tmovs r0, 0\n"
+ "\tmovs r1, 0xA\n"
+ "\tmovs r2, 0xD0\n"
+ "\tbl LoadUserWindowBorderGfx\n"
+ "\tmovs r0, 0\n"
+ "\tmovs r1, 0x1\n"
+ "\tmovs r2, 0xF0\n"
+ "\tbl sub_814FDA0\n"
+ "\tldr r1, _081413CC @ =0x0000085c\n"
+ "\tadd r1, r8\n"
+ "\tmovs r0, 0\n"
+ "\tbl SetBgTilemapBuffer\n"
+ "\tstr r4, [sp]\n"
+ "\tmovs r0, 0x1E\n"
+ "\tstr r0, [sp, 0x4]\n"
+ "\tmovs r0, 0\n"
+ "\tmovs r1, 0\n"
+ "\tmovs r2, 0\n"
+ "\tmovs r3, 0x2\n"
+ "\tbl FillBgTilemapBufferRect_Palette0\n"
+ "\tldr r1, _081413D0 @ =gUnknown_8466620\n"
+ "\tstr r5, [sp]\n"
+ "\tmovs r0, 0x1\n"
+ "\tmovs r2, 0\n"
+ "\tmovs r3, 0\n"
+ "\tbl DecompressAndCopyTileDataToVram\n"
+ "\tldr r1, _081413D4 @ =gUnknown_8466998\n"
+ "\tstr r6, [sp]\n"
+ "\tmovs r0, 0x1\n"
+ "\tmovs r2, 0\n"
+ "\tmovs r3, 0\n"
+ "\tbl DecompressAndCopyTileDataToVram\n"
+ "\tmovs r0, 0x1\n"
+ "\tbl CopyBgTilemapBufferToVram\n"
+ "\tmovs r0, 0x2\n"
+ "\tbl stdpal_get\n"
+ "\tmovs r1, 0xE0\n"
+ "\tmovs r2, 0x20\n"
+ "\tbl LoadPalette\n"
+ "\tmovs r0, 0x1\n"
+ "\tmovs r1, 0xFF\n"
+ "\tbl FillWindowPixelBuffer\n"
+ "\tmovs r0, 0x1\n"
+ "\tbl PutWindowTilemap\n"
+ "\tldr r4, _081413D8 @ =gString_SlotMachineControls\n"
+ "\tmovs r0, 0\n"
+ "\tadds r1, r4, 0\n"
+ "\tmovs r2, 0\n"
+ "\tbl GetStringWidth\n"
+ "\tmovs r2, 0xEC\n"
+ "\tsubs r2, r0\n"
+ "\tadd r1, sp, 0x10\n"
+ "\tmovs r0, 0xF\n"
+ "\tstrb r0, [r1]\n"
+ "\tstrb r6, [r1, 0x1]\n"
+ "\tmovs r0, 0x2\n"
+ "\tstrb r0, [r1, 0x2]\n"
+ "\tlsls r2, 24\n"
+ "\tlsrs r2, 24\n"
+ "\tstr r1, [sp]\n"
+ "\tstr r5, [sp, 0x4]\n"
+ "\tstr r4, [sp, 0x8]\n"
+ "\tmovs r0, 0x1\n"
+ "\tmovs r1, 0\n"
+ "\tmovs r3, 0\n"
+ "\tbl AddTextPrinterParameterized3\n"
+ "\tmovs r0, 0\n"
+ "\tbl CopyBgTilemapBufferToVram\n"
+ "\tmovs r1, 0x83\n"
+ "\tlsls r1, 5\n"
+ "\tmovs r0, 0\n"
+ "\tbl SetGpuRegBits\n"
+ "\tmovs r0, 0x50\n"
+ "\tmovs r1, 0xF8\n"
+ "\tbl SetGpuReg\n"
+ "\tbl sub_8140C0C\n"
+ "\tbl sub_8140CA0\n"
+ "\tbl sub_8140E9C\n"
+ "\tbl sub_8140FC4\n"
+ "\tbl sub_8140F2C\n"
+ "\tmovs r0, 0x1\n"
+ "\tnegs r0, r0\n"
+ "\tmovs r1, 0x10\n"
+ "\tmovs r2, 0\n"
+ "\tbl BlendPalettes\n"
+ "\tldr r0, _081413DC @ =sub_8141118\n"
+ "\tbl SetVBlankCallback\n"
+ "\tldr r0, _081413E0 @ =sub_8140E40\n"
+ "\tbl SetHBlankCallback\n"
+ "\tb _0814142E\n"
+ "\t.align 2, 0\n"
+ "_0814139C: .4byte 0x0600c000\n"
+ "_081413A0: .4byte gUnknown_8466B10\n"
+ "_081413A4: .4byte gUnknown_8466B20\n"
+ "_081413A8: .4byte 0x0000205c\n"
+ "_081413AC: .4byte gUnknown_84659D0\n"
+ "_081413B0: .4byte gUnknown_846653C\n"
+ "_081413B4: .4byte 0x0000185c\n"
+ "_081413B8: .4byte gUnknown_84661D4\n"
+ "_081413BC: .4byte gUnknown_8465930\n"
+ "_081413C0: .4byte gUnknown_84664BC\n"
+ "_081413C4: .4byte gUnknown_84665C0\n"
+ "_081413C8: .4byte 0x00007fde\n"
+ "_081413CC: .4byte 0x0000085c\n"
+ "_081413D0: .4byte gUnknown_8466620\n"
+ "_081413D4: .4byte gUnknown_8466998\n"
+ "_081413D8: .4byte gString_SlotMachineControls\n"
+ "_081413DC: .4byte sub_8141118\n"
+ "_081413E0: .4byte sub_8140E40\n"
+ "_081413E4:\n"
+ "\tbl FreeTempTileDataBuffersIfPossible\n"
+ "\tlsls r0, 24\n"
+ "\tlsrs r5, r0, 24\n"
+ "\tcmp r5, 0\n"
+ "\tbne _08141450\n"
+ "\tmovs r0, 0\n"
+ "\tbl ShowBg\n"
+ "\tmovs r0, 0x3\n"
+ "\tbl ShowBg\n"
+ "\tmovs r0, 0x2\n"
+ "\tbl ShowBg\n"
+ "\tmovs r0, 0x1\n"
+ "\tbl HideBg\n"
+ "\tbl sub_8141B34\n"
+ "\tmovs r4, 0x1\n"
+ "\tnegs r4, r4\n"
+ "\tadds r0, r4, 0\n"
+ "\tmovs r1, 0x10\n"
+ "\tmovs r2, 0\n"
+ "\tbl BlendPalettes\n"
+ "\tstr r5, [sp]\n"
+ "\tadds r0, r4, 0\n"
+ "\tadds r1, r4, 0\n"
+ "\tmovs r2, 0x10\n"
+ "\tmovs r3, 0\n"
+ "\tbl BeginNormalPaletteFade\n"
+ "\tmovs r0, 0x3\n"
+ "\tbl EnableInterrupts\n"
+ "_0814142E:\n"
+ "\tldrb r0, [r7]\n"
+ "\tadds r0, 0x1\n"
+ "\tstrb r0, [r7]\n"
+ "\tb _08141450\n"
+ "_08141436:\n"
+ "\tbl UpdatePaletteFade\n"
+ "\tldr r0, _0814144C @ =gPaletteFade\n"
+ "\tldrb r1, [r0, 0x7]\n"
+ "\tmovs r0, 0x80\n"
+ "\tands r0, r1\n"
+ "\tcmp r0, 0\n"
+ "\tbne _08141450\n"
+ "\tmovs r0, 0\n"
+ "\tb _08141452\n"
+ "\t.align 2, 0\n"
+ "_0814144C: .4byte gPaletteFade\n"
+ "_08141450:\n"
+ "\tmovs r0, 0x1\n"
+ "_08141452:\n"
+ "\tadd sp, 0x14\n"
+ "\tpop {r3}\n"
+ "\tmov r8, r3\n"
+ "\tpop {r4-r7}\n"
+ "\tpop {r1}\n"
+ "\tbx r1");
+}
+#endif //NONMATCHING
+
+static bool8 sub_8141460(u8 * state, struct SlotMachineSetupTaskData * ptr)
+{
+ switch (*state)
+ {
+ case 0:
+ BeginNormalPaletteFade(0xFFFFFFFF, -1, 0, 16, 0);
+ (*state)++;
+ break;
+ case 1:
+ if (!gPaletteFade.active)
+ return FALSE;
+ break;
+ }
+ return TRUE;
+}
+
+static bool8 sub_81414AC(u8 * state, struct SlotMachineSetupTaskData * ptr)
+{
+ switch (*state)
+ {
+ case 0:
+ sub_8141834(GetBgTilemapBuffer(2));
+ CopyBgTilemapBufferToVram(2);
+ (*state)++;
+ break;
+ case 1:
+ if (!IsDma3ManagerBusyWithBgCopy())
+ return FALSE;
+ break;
+ }
+ return TRUE;
+}
+
+static bool8 sub_81414EC(u8 * state, struct SlotMachineSetupTaskData * ptr)
+{
+ sub_8141020(1);
+ return FALSE;
+}
+
+static bool8 sub_81414FC(u8 * state, struct SlotMachineSetupTaskData * ptr)
+{
+ sub_8141020(2);
+ CreateTask(sub_814191C, 3);
+ return FALSE;
+}
+
+static bool8 sub_8141518(u8 * state, struct SlotMachineSetupTaskData * ptr)
+{
+ switch (*state)
+ {
+ case 0:
+ sub_8141AB0();
+ (*state)++;
+ break;
+ case 1:
+ if (!FuncIsActiveTask(sub_814191C))
+ {
+ sub_8141020(0);
+ return FALSE;
+ }
+ break;
+ }
+ return TRUE;
+}
+
+static bool8 sub_8141558(u8 * state, struct SlotMachineSetupTaskData * ptr)
+{
+ sub_8141020(3);
+ return FALSE;
+}
+
+static bool8 sub_8141568(u8 * state, struct SlotMachineSetupTaskData * ptr)
+{
+ sub_8141020(FALSE);
+ return FALSE;
+}
+
+static bool8 sub_8141578(u8 * state, struct SlotMachineSetupTaskData * ptr)
+{
+ sub_8140F2C();
+ return FALSE;
+}
+
+static bool8 sub_8141584(u8 * state, struct SlotMachineSetupTaskData * ptr)
+{
+ switch (*state)
+ {
+ case 0:
+ sub_81417E4(gString_OutOfCoins);
+ CopyWindowToVram(0, 3);
+ (*state)++;
+ break;
+ case 1:
+ if (!IsDma3ManagerBusyWithBgCopy())
+ return FALSE;
+ break;
+ }
+ return TRUE;
+}
+
+static bool8 sub_81415C8(u8 * state, struct SlotMachineSetupTaskData * ptr)
+{
+ switch (*state)
+ {
+ case 0:
+ sub_81417E4(gString_QuitPlaying);
+ sub_8141AD8(0);
+ CopyWindowToVram(0, 3);
+ (*state)++;
+ break;
+ case 1:
+ if (!IsDma3ManagerBusyWithBgCopy())
+ return FALSE;
+ break;
+ }
+ return TRUE;
+}
+
+static bool8 sub_8141610(u8 * state, struct SlotMachineSetupTaskData * ptr)
+{
+ switch (*state)
+ {
+ case 0:
+ sub_8141828();
+ sub_8141B18();
+ CopyWindowToVram(0, 3);
+ (*state)++;
+ break;
+ case 1:
+ if (!IsDma3ManagerBusyWithBgCopy())
+ return FALSE;
+ break;
+ }
+ return TRUE;
+}
+
+static bool8 sub_8141650(u8 * state, struct SlotMachineSetupTaskData * ptr)
+{
+ switch (*state)
+ {
+ case 0:
+ sub_8141BA0(ptr->field_0020);
+ CopyBgTilemapBufferToVram(2);
+ (*state)++;
+ break;
+ case 1:
+ if (!IsDma3ManagerBusyWithBgCopy())
+ return FALSE;
+ break;
+ }
+ return TRUE;
+}
+
+static bool8 sub_8141690(u8 * state, struct SlotMachineSetupTaskData * ptr)
+{
+ switch (*state)
+ {
+ case 0:
+ sub_8141BE4();
+ CopyBgTilemapBufferToVram(2);
+ (*state)++;
+ break;
+ case 1:
+ if (!IsDma3ManagerBusyWithBgCopy())
+ return FALSE;
+ break;
+ }
+ return TRUE;
+}
+
+static bool8 sub_81416C8(u8 * state, struct SlotMachineSetupTaskData * ptr)
+{
+ switch (*state)
+ {
+ case 0:
+ SetGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_WIN0_ON);
+ SetGpuReg(REG_OFFSET_WININ, 0x3F);
+ SetGpuReg(REG_OFFSET_WINOUT, 0x3D);
+ SetGpuReg(REG_OFFSET_WIN0H, 0x00);
+ SetGpuReg(REG_OFFSET_WIN1H, 0xA0);
+ ShowBg(1);
+ PlaySE(SE_WIN_OPEN);
+ ptr->field_0024 = 0;
+ (*state)++;
+ break;
+ case 1:
+ ptr->field_0024 += 16;
+ if (ptr->field_0024 >= 256)
+ {
+ ptr->field_0024 = 256;
+ (*state)++;
+ }
+ ChangeBgX(1, 256 * (256 - ptr->field_0024), 0);
+ SetGpuReg(REG_OFFSET_WIN0H, ptr->field_0024);
+ break;
+ case 2:
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static bool8 sub_8141764(u8 * state, struct SlotMachineSetupTaskData * ptr)
+{
+ switch (*state)
+ {
+ case 0:
+ PlaySE(SE_WIN_OPEN);
+ (*state)++;
+ // fallthrough
+ case 1:
+ ptr->field_0024 -= 16;
+ if (ptr->field_0024 <= 0)
+ {
+ ptr->field_0024 = 0;
+ (*state)++;
+ }
+ ChangeBgX(1, 256 * (256 - ptr->field_0024), 0);
+ SetGpuReg(REG_OFFSET_WIN0H, ptr->field_0024);
+ break;
+ case 2:
+ HideBg(1);
+ ClearGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_WIN0_ON);
+ (*state)++;
+ break;
+ case 3:
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static void sub_81417E4(const u8 * str)
+{
+ FillWindowPixelBuffer(0, 0x11);
+ PutWindowTilemap(0);
+ DrawTextBorderOuter(0, 0x001, 15);
+ AddTextPrinterParameterized5(0, 2, str, 1, 2, -1, NULL, 1, 2);
+}
+
+static void sub_8141828(void)
+{
+ rbox_fill_rectangle(0);
+}
+
+static void sub_8141834(u16 * bgTilemapBuffer)
+{
+ switch (sub_8140BEC())
+ {
+ case 0:
+ sub_81418C4(bgTilemapBuffer, 0, 4);
+ sub_81418C4(bgTilemapBuffer, 1, 4);
+ sub_81418C4(bgTilemapBuffer, 2, 4);
+ sub_81418C4(bgTilemapBuffer, 3, 4);
+ sub_81418C4(bgTilemapBuffer, 4, 4);
+ break;
+ case 3:
+ sub_81418C4(bgTilemapBuffer, 0, 5);
+ sub_81418C4(bgTilemapBuffer, 4, 5);
+ case 2:
+ sub_81418C4(bgTilemapBuffer, 1, 5);
+ sub_81418C4(bgTilemapBuffer, 3, 5);
+ case 1:
+ sub_81418C4(bgTilemapBuffer, 2, 5);
+ break;
+ }
+}
+
+static void sub_81418C4(u16 * bgTilemapBuffer, u16 whichLine, u16 paletteNum)
+{
+ s32 i;
+ const u16 * tileIdxs = gUnknown_8466C0C[whichLine].tiles;
+ u16 palMask = (paletteNum & 0xF) << 12;
+
+ for (i = 0; i < gUnknown_8466C0C[whichLine].count; i++)
+ {
+ bgTilemapBuffer[*tileIdxs] &= 0x0FFF;
+ bgTilemapBuffer[*tileIdxs] |= palMask;
+ tileIdxs++;
+ }
+}
+
+static void sub_814191C(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+ s32 i;
+
+ switch (data[0])
+ {
+ case 0:
+ LoadPalette(gUnknown_84664BC, 0x60, 0x20);
+ for (i = 0; i < 5; i++)
+ {
+ if (sub_8140BF8(i))
+ sub_81418C4(GetBgTilemapBuffer(2), i, 6);
+ }
+ CopyBgTilemapBufferToVram(2);
+ data[0]++;
+ break;
+ case 1:
+ if (data[1] == 0)
+ {
+ u16 y = gSineTable[data[2]] >> 7;
+ LoadPalette(&gUnknown_84664DC[16 * y], 0x10, 0x20);
+ data[2] += 32;
+ data[2] &= 0x7F;
+ data[1] = 8;
+ }
+ else
+ data[1]--;
+
+ if (data[3] == 0)
+ {
+ data[4] += 8;
+ data[4] &= 0x7F;
+ data[5] = gSineTable[data[4]] >> 5;
+ BlendPalettes(0x00000040, data[5], RGB_BLACK);
+ }
+ else
+ {
+ data[4]++;
+ if (data[4] > 1)
+ {
+ data[4] = 0;
+ data[5]++;
+ data[5] &= 1;
+ BlendPalettes(0x00000040, data[5] * 8, RGB_BLACK);
+ }
+ }
+
+ for (i = 0; i < NELEMS(gUnknown_8466C34); i++)
+ {
+ gPlttBufferFaded[gUnknown_8466C34[i] + 0x60] = gPlttBufferUnfaded[gUnknown_8466C34[i] + 0x60];
+ }
+ break;
+ case 2:
+ for (i = 0; i < 5; i++)
+ {
+ if (sub_8140BF8(i))
+ sub_81418C4(GetBgTilemapBuffer(2), i, 4);
+ }
+ LoadPalette(gUnknown_8465950, 0x10, 0x20);
+ CopyBgTilemapBufferToVram(2);
+ data[0]++;
+ break;
+ case 3:
+ if (!IsDma3ManagerBusyWithBgCopy())
+ DestroyTask(taskId);
+ break;
+ }
+}
+
+static void sub_8141AB0(void)
+{
+ gTasks[FindTaskIdByFunc(sub_814191C)].data[0] = 2;
+}
+
+static void sub_8141AD8(u8 cursorPos)
+{
+ CreateYesNoMenu(&gUnknown_8466C38, 2, 0, 2, 10, 13, cursorPos);
+ Menu_MoveCursorNoWrapAround(cursorPos);
+ sub_814112C()->field_0028 = TRUE;
+}
+
+static void sub_8141B18(void)
+{
+ struct SlotMachineSetupTaskData * data = sub_814112C();
+ if (data->field_0028)
+ {
+ DestroyYesNoMenu();
+ data->field_0028 = FALSE;
+ }
+}
+
+static void sub_8141B34(void)
+{
+ s32 i, j;
+ struct SlotMachineSetupTaskData * data = sub_814112C();
+ u16 * buffer = GetBgTilemapBuffer(2);
+
+ for (i = 0; i < 3; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ u16 idx = gUnknown_8466C40[i][j];
+ data->field_0044[i][j] = buffer[idx];
+ data->field_002C[i][j] = j + 0xC0;
+ }
+ }
+}
+
+static void sub_8141BA0(u8 reel)
+{
+ if (reel < 3)
+ {
+ s32 i;
+ struct SlotMachineSetupTaskData * data = sub_814112C();
+ u16 * buffer = GetBgTilemapBuffer(2);
+ for (i = 0; i < 4; i++)
+ {
+ u16 idx = gUnknown_8466C40[reel][i];
+ buffer[idx] = data->field_002C[reel][i];
+ }
+ }
+}
+
+static void sub_8141BE4(void)
+{
+ s32 i, j;
+ struct SlotMachineSetupTaskData * data = sub_814112C();
+ u16 * buffer = GetBgTilemapBuffer(2);
+
+ for (i = 0; i < 3; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ u16 idx = gUnknown_8466C40[i][j];
+ buffer[idx] = data->field_0044[i][j];
+ }
+ }
+}
+
+static void sub_8141C30(u8 a0, u8 a1)
+{
+ sub_814112C()->field_0020 = a0;
+ sub_8141148(12, a1);
+}
diff --git a/src/teachy_tv.c b/src/teachy_tv.c
index 0b0e7b932..3594c79a2 100644
--- a/src/teachy_tv.c
+++ b/src/teachy_tv.c
@@ -1208,11 +1208,11 @@ static void TeachyTvPreBattleAnimAndSetBattleCallback(u8 taskId)
switch (data[7])
{
case 0:
- sub_80D08B8(data[6]);
+ BT_StartOnField(data[6]);
++data[7];
break;
case 1:
- if (sub_80D08F8())
+ if (BT_IsDone())
{
SetMainCallback2(sub_800FD9C);
DestroyTask(taskId);
diff --git a/src/title_screen.c b/src/title_screen.c
new file mode 100644
index 000000000..f4086b2ff
--- /dev/null
+++ b/src/title_screen.c
@@ -0,0 +1,1056 @@
+#include "global.h"
+#include "malloc.h"
+#include "palette.h"
+#include "gpu_regs.h"
+#include "bg.h"
+#include "task.h"
+#include "main.h"
+#include "new_menu_helpers.h"
+#include "m4a.h"
+#include "scanline_effect.h"
+#include "graphics.h"
+#include "help_system.h"
+#include "intro.h"
+#include "load_save.h"
+#include "sound.h"
+#include "new_game.h"
+#include "save.h"
+#include "main_menu.h"
+#include "clear_save_data_screen.h"
+#include "berry_fix_program.h"
+#include "decompress.h"
+#include "constants/songs.h"
+#include "constants/species.h"
+
+enum TitleScreenScene
+{
+ TITLESCREENSCENE_INIT = 0,
+ TITLESCREENSCENE_FLASHSPRITE,
+ TITLESCREENSCENE_FADEIN,
+ TITLESCREENSCENE_RUN,
+ TITLESCREENSCEEN_RESTART,
+ TITLESCREENSCENE_CRY
+};
+
+#if defined(FIRERED)
+#define TITLE_SPECIES SPECIES_CHARIZARD
+#elif defined(LEAFGREEN)
+#define TITLE_SPECIES SPECIES_VENUSAUR
+#endif
+
+static EWRAM_DATA u8 sTitleScreenTimerTaskId = 0;
+
+static void ResetGpuRegs(void);
+static void CB2_TitleScreenRun(void);
+static void VBlankCB(void);
+static void Task_TitleScreenTimer(u8 taskId);
+static void Task_TitleScreenMain(u8 taskId);
+static void SetTitleScreenScene(s16 * data, u8 a1);
+static void SetTitleScreenScene_Init(s16 * data);
+static void SetTitleScreenScene_FlashSprite(s16 * data);
+static void SetTitleScreenScene_FadeIn(s16 * data);
+static void SetTitleScreenScene_Run(s16 * data);
+static void SetGpuRegsForTitleScreenRun(void);
+static void SetTitleScreenScene_Restart(s16 * data);
+static void SetTitleScreenScene_Cry(s16 * data);
+static void Task_TitleScreen_SlideWin0(u8 taskId);
+static void Task_TitleScreen_PaletteSomething(u8 taskId);
+static void SignalEndTitleScreenPaletteSomethingTask(void);
+static void UpdateScanlineEffectRegBuffer(s16 a0);
+static void ScheduleStopScanlineEffect(void);
+static void LoadMainTitleScreenPalsAndResetBgs(void);
+static void CB2_FadeOutTransitionToSaveClearScreen(void);
+static void CB2_FadeOutTransitionToBerryFix(void);
+static void LoadSpriteGfxAndPals(void);
+static void Task_FlameOrLeafSpawner(u8 taskId);
+static void TitleScreen_srand(u8 taskId, u8 field, u16 seed);
+static u16 TitleScreen_rand(u8 taskId, u8 field);
+static u32 CreateBlankSprite(void);
+static void SetPalOnOrCreateBlankSprite(bool32 a0);
+static u8 CreateSlashSprite(void);
+static void ScheduleHideSlashSprite(u8 spriteId);
+static bool32 IsSlashSpriteHidden(u8 spriteId);
+static void SpriteCallback_Slash(struct Sprite * sprite);
+
+// bg3
+static const u8 sBorderBgTiles[] = INCBIN_U8("data/graphics/title_screen/unk_83BF58C.4bpp.lz");
+static const u8 sBorderBgMap[] = INCBIN_U8("data/graphics/title_screen/unk_83BF5A8.bin.lz");
+
+//sprites
+static const u8 sSlashSpriteTiles[] = INCBIN_U8("data/graphics/title_screen/unk_83bf64c.4bpp.lz");
+static const u16 sSlashSpritePals[] = INCBIN_U16("data/graphics/title_screen/unk_83bf77c.gbapal");
+static const u8 sFireSpriteTiles[] = INCBIN_U8("data/graphics/title_screen/unk_83bf79c.4bpp.lz");
+static const u8 sBlankFireSpriteTiles[] = INCBIN_U8("data/graphics/title_screen/unk_83bfa14.4bpp.lz");
+
+static const struct OamData sOamData_FlameOrLeaf = {
+ .objMode = ST_OAM_OBJ_NORMAL,
+ .shape = ST_OAM_SQUARE,
+ .size = ST_OAM_SIZE_1,
+ .tileNum = 0,
+ .priority = 3,
+ .paletteNum = 0
+};
+
+static const union AnimCmd sSpriteAnims_FlameOrLeaf_0[] = {
+ ANIMCMD_FRAME(0x00, 3),
+ ANIMCMD_FRAME(0x04, 6),
+ ANIMCMD_FRAME(0x08, 6),
+ ANIMCMD_FRAME(0x0c, 6),
+ ANIMCMD_FRAME(0x10, 6),
+ ANIMCMD_FRAME(0x14, 6),
+ ANIMCMD_FRAME(0x18, 6),
+ ANIMCMD_FRAME(0x1c, 6),
+ ANIMCMD_FRAME(0x20, 6),
+ ANIMCMD_FRAME(0x24, 6),
+ ANIMCMD_END
+};
+
+static const union AnimCmd sSpriteAnims_FlameOrLeaf_1[] = {
+ ANIMCMD_FRAME(0x18, 6),
+ ANIMCMD_FRAME(0x1c, 6),
+ ANIMCMD_FRAME(0x20, 6),
+ ANIMCMD_FRAME(0x24, 6),
+ ANIMCMD_END
+};
+
+static const union AnimCmd *const sSpriteAnimTable_FlameOrLeaf[] = {
+ sSpriteAnims_FlameOrLeaf_0,
+ sSpriteAnims_FlameOrLeaf_1
+};
+
+static const struct SpriteTemplate sSpriteTemplate_FlameOrLeaf_State1 = {
+ .tileTag = 0,
+ .paletteTag = 0,
+ .oam = &sOamData_FlameOrLeaf,
+ .anims = sSpriteAnimTable_FlameOrLeaf,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = SpriteCallbackDummy
+};
+
+static const struct SpriteTemplate sSpriteTemplate_FlameOrLeaf_State0 = {
+ .tileTag = 1,
+ .paletteTag = 0,
+ .oam = &sOamData_FlameOrLeaf,
+ .anims = sSpriteAnimTable_FlameOrLeaf,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = SpriteCallbackDummy
+};
+
+static const struct OamData sOamData_UnknownTemptySprite = {
+ .objMode = ST_OAM_OBJ_NORMAL,
+ .shape = ST_OAM_V_RECTANGLE,
+ .size = ST_OAM_SIZE_3,
+ .tileNum = 0,
+ .priority = 0,
+ .paletteNum = 0
+};
+
+static const struct SpriteTemplate sUnknownEmptySprite = {
+ .tileTag = 2,
+ .paletteTag = 2,
+ .oam = &sOamData_UnknownTemptySprite,
+ .anims = gDummySpriteAnimTable,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = SpriteCallbackDummy
+};
+
+static const struct OamData sOamData_SlashSprite = {
+ .objMode = ST_OAM_OBJ_WINDOW,
+ .shape = ST_OAM_SQUARE,
+ .size = ST_OAM_SIZE_3,
+ .tileNum = 0,
+ .priority = 0,
+ .paletteNum = 0
+};
+
+static const struct SpriteTemplate sSlashSpriteTemplate = {
+ .tileTag = 3,
+ .paletteTag = 2,
+ .oam = &sOamData_SlashSprite,
+ .anims = gDummySpriteAnimTable,
+ .images = NULL,
+ .affineAnims = gDummySpriteAffineAnimTable,
+ .callback = SpriteCallbackDummy
+};
+
+static const struct BgTemplate sBgTemplates[] = {
+ {
+ .bg = 0,
+ .charBaseIndex = 0,
+ .mapBaseIndex = 31,
+ .screenSize = 0,
+ .paletteMode = 1, // 8bpp
+ .priority = 0,
+ .baseTile = 0
+ }, {
+ .bg = 1,
+ .charBaseIndex = 1,
+ .mapBaseIndex = 30,
+ .screenSize = 0,
+ .paletteMode = 0, // 4bpp
+ .priority = 1,
+ .baseTile = 0
+ }, {
+ .bg = 2,
+ .charBaseIndex = 2,
+ .mapBaseIndex = 29,
+ .screenSize = 0,
+ .paletteMode = 0, // 4bpp
+ .priority = 2,
+ .baseTile = 0
+ }, {
+ .bg = 3,
+ .charBaseIndex = 3,
+ .mapBaseIndex = 28,
+ .screenSize = 0,
+ .paletteMode = 0, // 4bpp
+ .priority = 3,
+ .baseTile = 0
+ }
+};
+
+static void (*const sSceneFuncs[])(s16 * data) = {
+ SetTitleScreenScene_Init,
+ SetTitleScreenScene_FlashSprite,
+ SetTitleScreenScene_FadeIn,
+ SetTitleScreenScene_Run,
+ SetTitleScreenScene_Restart,
+ SetTitleScreenScene_Cry
+};
+
+static const struct CompressedSpriteSheet sSpriteSheets[] = {
+ {(const void *)sFireSpriteTiles, 0x500, 0},
+ {(const void *)sBlankFireSpriteTiles, 0x500, 1},
+ {(const void *)gGraphics_TitleScreen_BlankObjTiles, 0x400, 2},
+ {(const void *)sSlashSpriteTiles, 0x800, 3}
+};
+
+static const struct SpritePalette sSpritePals[] = {
+ {sSlashSpritePals, 0},
+ {gGraphics_TitleScreen_FirePals, 2},
+ {}
+};
+
+static const u8 gUnknown_83BFBD4[] = {
+ 0x04, 0x10, 0x1a, 0x20, 0x30, 0xc8, 0xd8, 0xe0, 0xe8, 0x3c, 0x4c, 0x5c, 0x6c, 0x80, 0x90
+};
+
+void CB2_InitTitleScreen(void)
+{
+ switch (gMain.state)
+ {
+ default:
+ gMain.state = 0;
+ // fallthrough
+ case 0:
+ SetVBlankCallback(NULL);
+ StartTimer1();
+ InitHeap(gHeap, HEAP_SIZE);
+ ResetTasks();
+ ResetSpriteData();
+ FreeAllSpritePalettes();
+ ResetPaletteFade();
+ ResetGpuRegs();
+ DmaFill16(3, 0, (void *)VRAM, VRAM_SIZE);
+ DmaFill32(3, 0, (void *)OAM, OAM_SIZE);
+ DmaFill16(3, 0, (void *)PLTT, PLTT_SIZE);
+ ResetBgsAndClearDma3BusyFlags(FALSE);
+ InitBgsFromTemplates(0, sBgTemplates, NELEMS(sBgTemplates));
+ SetGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_OBJ_1D_MAP | DISPCNT_OBJ_ON);
+ sTitleScreenTimerTaskId = 0xFF;
+ break;
+ case 1:
+ LoadPalette(gGraphics_TitleScreen_PokemonFireRedLogoPals, 0, 0x1A0);
+ DecompressAndCopyTileDataToVram(0, gGraphics_TitleScreen_PokemonFireRedLogoTiles, 0, 0, 0);
+ DecompressAndCopyTileDataToVram(0, gGraphics_TitleScreen_PokemonFireRedLogoMap, 0, 0, 1);
+ LoadPalette(gGraphics_TitleScreen_CharizardPals, 0xD0, 0x20);
+ DecompressAndCopyTileDataToVram(1, gGraphics_TitleScreen_CharizardTiles, 0, 0, 0);
+ DecompressAndCopyTileDataToVram(1, gGraphics_TitleScreen_CharizardMap, 0, 0, 1);
+ LoadPalette(gGraphics_TitleScreen_BackgroundPals, 0xF0, 0x20);
+ DecompressAndCopyTileDataToVram(2, gGraphics_TitleScreen_CopyrightPressStartTiles, 0, 0, 0);
+ DecompressAndCopyTileDataToVram(2, gGraphics_TitleScreen_CopyrightPressStartMap, 0, 0, 1);
+ LoadPalette(gGraphics_TitleScreen_BackgroundPals, 0xE0, 0x20);
+ DecompressAndCopyTileDataToVram(3, sBorderBgTiles, 0, 0, 0);
+ DecompressAndCopyTileDataToVram(3, sBorderBgMap, 0, 0, 1);
+ LoadSpriteGfxAndPals();
+ break;
+ case 2:
+ if (!FreeTempTileDataBuffersIfPossible())
+ {
+ BlendPalettes(0x0000FFFF, 0x10, RGB_BLACK);
+ CreateTask(Task_TitleScreenMain, 4);
+ sTitleScreenTimerTaskId = CreateTask(Task_TitleScreenTimer, 2);
+ SetVBlankCallback(VBlankCB);
+ SetMainCallback2(CB2_TitleScreenRun);
+ m4aSongNumStart(BGM_FRLG_TITLE);
+ }
+ return;
+ }
+ gMain.state++;
+}
+
+static void ResetGpuRegs(void)
+{
+ SetGpuReg(REG_OFFSET_DISPCNT, 0);
+ SetGpuReg(REG_OFFSET_BLDCNT, 0);
+ SetGpuReg(REG_OFFSET_BLDALPHA, 0);
+ SetGpuReg(REG_OFFSET_BLDY, 0);
+ SetGpuReg(REG_OFFSET_BG0HOFS, 0);
+ SetGpuReg(REG_OFFSET_BG0VOFS, 0);
+ SetGpuReg(REG_OFFSET_BG1HOFS, 0);
+ SetGpuReg(REG_OFFSET_BG1VOFS, 0);
+ SetGpuReg(REG_OFFSET_BG2HOFS, 0);
+ SetGpuReg(REG_OFFSET_BG2VOFS, 0);
+ SetGpuReg(REG_OFFSET_BG3HOFS, 0);
+ SetGpuReg(REG_OFFSET_BG3VOFS, 0);
+}
+
+static void CB2_TitleScreenRun(void)
+{
+ RunTasks();
+ AnimateSprites();
+ BuildOamBuffer();
+ UpdatePaletteFade();
+}
+
+static void VBlankCB(void)
+{
+ LoadOam();
+ ProcessSpriteCopyRequests();
+ TransferPlttBuffer();
+ ScanlineEffect_InitHBlankDmaTransfer();
+
+ if (sTitleScreenTimerTaskId != 0xFF)
+ gTasks[sTitleScreenTimerTaskId].data[0]++;
+}
+
+static void Task_TitleScreenTimer(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+
+ if (data[0] >= 2700)
+ {
+ sTitleScreenTimerTaskId = 0xFF;
+ DestroyTask(taskId);
+ }
+}
+
+static void Task_TitleScreenMain(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+
+ if (JOY_NEW(A_BUTTON | B_BUTTON | START_BUTTON)
+ && data[0] != 3 && data[0] != 4 && data[0] != 5)
+ {
+ ScheduleStopScanlineEffect();
+ LoadMainTitleScreenPalsAndResetBgs();
+ SetPalOnOrCreateBlankSprite(data[5]);
+ SetTitleScreenScene(data, TITLESCREENSCENE_RUN);
+ }
+ else
+ {
+ sSceneFuncs[data[0]](data);
+ }
+}
+
+static void SetTitleScreenScene(s16 * data, u8 a1)
+{
+ data[1] = 0;
+ data[0] = a1;
+}
+
+static void SetTitleScreenScene_Init(s16 * data)
+{
+ struct ScanlineEffectParams params;
+
+ HideBg(0);
+ ShowBg(1);
+ ShowBg(2);
+ ShowBg(3);
+
+ params.dmaDest = (volatile void *)REG_ADDR_BLDY;
+ params.dmaControl = SCANLINE_EFFECT_DMACNT_16BIT;
+ params.initState = 1;
+ params.unused9 = 0;
+
+ CpuFill16(0, gScanlineEffectRegBuffers[0], 0x140);
+ CpuFill16(0, gScanlineEffectRegBuffers[1], 0x140);
+
+ ScanlineEffect_SetParams(params);
+
+ SetTitleScreenScene(data, TITLESCREENSCENE_FLASHSPRITE);
+}
+
+static void SetTitleScreenScene_FlashSprite(s16 * data)
+{
+ switch (data[1])
+ {
+ case 0:
+ SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG1 | BLDCNT_EFFECT_LIGHTEN);
+ SetGpuReg(REG_OFFSET_BLDY, 0);
+ data[2] = 0x80;
+ UpdateScanlineEffectRegBuffer(data[2]);
+ data[1]++;
+ break;
+ case 1:
+ data[2] -= 4;
+ UpdateScanlineEffectRegBuffer(data[2]);
+ if (data[2] < 0)
+ {
+ gScanlineEffect.state = 3;
+ data[1]++;
+ }
+ break;
+ case 2:
+ SetGpuReg(REG_OFFSET_BLDCNT, 0);
+ SetGpuReg(REG_OFFSET_BLDY, 0);
+ SetTitleScreenScene(data, TITLESCREENSCENE_FADEIN);
+ }
+}
+
+static void SetTitleScreenScene_FadeIn(s16 * data)
+{
+ u32 r4;
+ switch (data[1])
+ {
+ case 0:
+ data[2] = 0;
+ data[1]++;
+ break;
+ case 1:
+ data[2]++;
+ if (data[2] > 10)
+ {
+ TintPalette_GrayScale2(gPlttBufferUnfaded + 0xD0, 0x10);
+ BeginNormalPaletteFade(0x00002000, 9, 0x10, 0, RGB_BLACK);
+ data[1]++;
+ }
+ break;
+ case 2:
+ if (!gPaletteFade.active)
+ {
+ data[2] = 0;
+ data[1]++;
+ }
+ break;
+ case 3:
+ data[2]++;
+ if (data[2] > 36)
+ {
+ CreateTask(Task_TitleScreen_SlideWin0, 3);
+ sub_80717A8(0x2000, -4, 0x01, 0x10, RGB(30, 30, 31), 0, 0);
+ data[2] = 0;
+ data[1]++;
+ }
+ break;
+ case 4:
+ if (!sub_807185C(0))
+ {
+ sub_80717A8(0x2000, -4, 0x0F, 0x00, RGB(30, 30, 31), 0, 0);
+ data[1]++;
+ }
+ break;
+ case 5:
+ data[2]++;
+ if (data[2] > 20)
+ {
+ data[2] = 0;
+ sub_80717A8(0x2000, -4, 0x01, 0x10, RGB(30, 30, 31), 0, 0);
+ data[1]++;
+ }
+ break;
+ case 6:
+ if (!sub_807185C(0))
+ {
+ sub_80717A8(0x2000, -4, 0x0F, 0x00, RGB(30, 30, 31), 0, 0);
+ data[1]++;
+ }
+ break;
+ case 7:
+ data[2]++;
+ if (data[2] > 20)
+ {
+ data[2] = 0;
+ sub_80717A8(0x2000, -3, 0x00, 0x10, RGB(30, 30, 31), 0, 0);
+ data[1]++;
+ }
+ break;
+ case 8:
+ if (!sub_807185C(0))
+ {
+ data[5] = 1;
+ r4 = (0x10000 << CreateBlankSprite()) | 0x00001FFF;
+ BlendPalettes(r4, 0x10, RGB(30, 30, 31));
+ BeginNormalPaletteFade(r4, 1, 0x10, 0x00, RGB(30, 30, 31));
+ ShowBg(0);
+ CpuCopy16(gGraphics_TitleScreen_CharizardPals, gPlttBufferUnfaded + 0xD0, 0x20);
+ sub_80717A8(0x2000, 1, 0x0F, 0x00, RGB(30, 30, 31), 0, 0);
+ data[1]++;
+ }
+ break;
+ case 9:
+ if (!sub_807185C(0) && !gPaletteFade.active)
+ {
+ SetTitleScreenScene(data, TITLESCREENSCENE_RUN);
+ }
+ break;
+ }
+}
+
+#define KEYSTROKE_DELSAVE (B_BUTTON | SELECT_BUTTON | DPAD_UP)
+#define KEYSTROKE_BERRY_FIX (B_BUTTON | SELECT_BUTTON)
+
+static void SetTitleScreenScene_Run(s16 * data)
+{
+ switch (data[1])
+ {
+ case 0:
+ HelpSystem_SetSomeVariable2(1);
+ CreateTask(Task_TitleScreen_PaletteSomething, 0);
+ CreateTask(Task_FlameOrLeafSpawner, 5);
+ SetGpuRegsForTitleScreenRun();
+ data[6] = CreateSlashSprite();
+ sub_812B484();
+ data[1]++;
+ // fallthrough
+ case 1:
+ if (JOY_HELD(KEYSTROKE_DELSAVE) == KEYSTROKE_DELSAVE)
+ {
+ ScheduleHideSlashSprite(data[6]);
+ DestroyTask(FindTaskIdByFunc(Task_TitleScreenMain));
+ SetMainCallback2(CB2_FadeOutTransitionToSaveClearScreen);
+ }
+ else if (JOY_HELD(KEYSTROKE_BERRY_FIX) == KEYSTROKE_BERRY_FIX)
+ {
+ ScheduleHideSlashSprite(data[6]);
+ DestroyTask(FindTaskIdByFunc(Task_TitleScreenMain));
+ SetMainCallback2(CB2_FadeOutTransitionToBerryFix);
+ }
+ else if (JOY_NEW(A_BUTTON | START_BUTTON))
+ {
+ SetTitleScreenScene(data, TITLESCREENSCENE_CRY);
+ }
+ else if (!FuncIsActiveTask(Task_TitleScreenTimer))
+ {
+ SetTitleScreenScene(data, TITLESCREENSCEEN_RESTART);
+ }
+ break;
+ }
+}
+
+static void SetGpuRegsForTitleScreenRun(void)
+{
+ SetGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_OBJWIN_ON);
+ SetGpuReg(REG_OFFSET_WINOUT, WIN_RANGE(0x3F, 0x1F));
+ SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG0 | BLDCNT_EFFECT_LIGHTEN);
+ SetGpuReg(REG_OFFSET_BLDY, 13);
+}
+
+static void SetTitleScreenScene_Restart(s16 * data)
+{
+ switch (data[1])
+ {
+ case 0:
+ ScheduleHideSlashSprite(data[6]);
+ data[1]++;
+ break;
+ case 1:
+ if (!gPaletteFade.active && !IsSlashSpriteHidden(data[6]))
+ {
+ FadeOutMapMusic(10);
+ BeginNormalPaletteFade(0xFFFFFFFF, 3, 0, 0x10, RGB_BLACK);
+ SignalEndTitleScreenPaletteSomethingTask();
+ data[1]++;
+ }
+ break;
+ case 2:
+ if (IsNotWaitingForBGMStop() && !gPaletteFade.active)
+ {
+ DestroyTask(FindTaskIdByFunc(Task_TitleScreen_PaletteSomething));
+ data[2] = 0;
+ data[1]++;
+ }
+ break;
+ case 3:
+ data[2]++;
+ if (data[2] >= 20)
+ {
+ DestroyTask(FindTaskIdByFunc(Task_TitleScreen_PaletteSomething));
+ data[1]++;
+ }
+ break;
+ case 4:
+ sub_812B478();
+ DestroyTask(FindTaskIdByFunc(Task_TitleScreenMain));
+ SetMainCallback2(sub_80EC864);
+ break;
+ }
+}
+
+static void SetTitleScreenScene_Cry(s16 * data)
+{
+ switch (data[1])
+ {
+ case 0:
+ if (!gPaletteFade.active)
+ {
+ PlayCry1(TITLE_SPECIES, 0);
+ ScheduleHideSlashSprite(data[6]);
+ data[2] = 0;
+ data[1]++;
+ }
+ break;
+ case 1:
+ if (data[2] < 90)
+ data[2]++;
+ else if (!IsSlashSpriteHidden(data[6]))
+ {
+ BeginNormalPaletteFade(0x0FFFFFFF, 0, 0, 0x10, RGB_WHITE);
+ SignalEndTitleScreenPaletteSomethingTask();
+ FadeOutBGM(4);
+ data[1]++;
+ }
+ break;
+ case 2:
+ if (!gPaletteFade.active)
+ {
+ SeedRngAndSetTrainerId();
+ SetSaveBlocksPointers();
+ ResetMenuAndMonGlobals();
+ Save_ResetSaveCounters();
+ Save_LoadGameData(0);
+ if (gSaveFileStatus == SAVE_STATUS_EMPTY || gSaveFileStatus == SAVE_STATUS_INVALID)
+ Sav2_ClearSetDefault();
+ SetPokemonCryStereo(gSaveBlock2Ptr->optionsSound);
+ InitHeap(gHeap, HEAP_SIZE);
+ SetMainCallback2(sub_800C300);
+ DestroyTask(FindTaskIdByFunc(Task_TitleScreenMain));
+ }
+ break;
+ }
+}
+
+static void Task_TitleScreen_SlideWin0(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+
+ switch (data[0])
+ {
+ case 0:
+ SetGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_WIN0_ON);
+ SetGpuReg(REG_OFFSET_WININ, WIN_RANGE(0x00, 0x3F));
+ SetGpuReg(REG_OFFSET_WINOUT, WIN_RANGE(0x00, 0x37));
+ SetGpuReg(REG_OFFSET_WIN0V, 0xA0);
+ SetGpuReg(REG_OFFSET_WIN0H, 0x00);
+ BlendPalettes(0x00004000, 0, RGB_BLACK);
+ data[0]++;
+ break;
+ case 1:
+ data[1] += 0x180;
+ data[2] = data[1] >> 4;
+ if (data[2] >= 0xF0)
+ {
+ data[2] = 0xF0;
+ data[0]++;
+ }
+ SetGpuReg(REG_OFFSET_WIN0H, data[2]);
+ break;
+ case 2:
+ data[3]++;
+ if (data[3] >= 10)
+ {
+ data[3] = 0;
+ data[0]++;
+ }
+ break;
+ case 3:
+ SetGpuReg(REG_OFFSET_WINOUT, WIN_RANGE(0, 0x3B));
+ SetGpuReg(REG_OFFSET_WIN0H, 0xF0F0);
+ ChangeBgX(2, -0xF000, 0);
+ BlendPalettes(0x00008000, 0, RGB_BLACK);
+ data[1] = 0xF00;
+ data[0]++;
+ break;
+ case 4:
+ data[1] -= 0x180;
+ data[2] = data[1] >> 4;
+ if (data[2] <= 0)
+ {
+ data[2] = 0;
+ data[0]++;
+ }
+ ChangeBgX(2, -data[2] << 8, 0);
+ SetGpuReg(REG_OFFSET_WIN0H, (data[2] << 8) | 0xF0);
+ break;
+ case 5:
+ ClearGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_WIN0_ON);
+ DestroyTask(taskId);
+ break;
+ }
+}
+
+static void Task_TitleScreen_PaletteSomething(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+ s32 i;
+
+ if (data[15] && gPaletteFade.active)
+ data[14] = 1;
+ if (data[14] && !gPaletteFade.active)
+ DestroyTask(taskId);
+ else
+ {
+ if (!data[1])
+ data[2] = 60;
+ else
+ data[2] = 30;
+ data[0]++;
+ if (data[0] >= data[2])
+ {
+ data[0] = 0;
+ data[1] ^= 1;
+ if (data[1])
+ {
+ for (i = 0; i < 5; i++)
+ {
+ gPlttBufferUnfaded[0xF1 + i] = gGraphics_TitleScreen_BackgroundPals[6];
+ gPlttBufferFaded[0xF1 + i] = gGraphics_TitleScreen_BackgroundPals[6];
+ }
+ }
+ else
+ {
+ for (i = 0; i < 5; i++)
+ {
+ gPlttBufferUnfaded[0xF1 + i] = gGraphics_TitleScreen_BackgroundPals[1 + i];
+ gPlttBufferFaded[0xF1 + i] = gGraphics_TitleScreen_BackgroundPals[1 + i];
+ }
+ }
+ if (data[14])
+ {
+ BlendPalettes(0x00008000, gPaletteFade.y, gPaletteFade.blendColor);
+ }
+ }
+ }
+}
+
+static void SignalEndTitleScreenPaletteSomethingTask(void)
+{
+ u8 taskId = FindTaskIdByFunc(Task_TitleScreen_PaletteSomething);
+ gTasks[taskId].data[15] = TRUE;
+}
+
+static void UpdateScanlineEffectRegBuffer(s16 a0)
+{
+ s32 i;
+
+ if (a0 >= 0)
+ {
+ gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer][a0] = 16;
+ }
+
+ for (i = 0; i < 16; i++)
+ {
+ if (a0 + i >= 0)
+ {
+ gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer][a0 + i] = 15 - i;
+ }
+ if (a0 - i >= 0)
+ {
+ gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer][a0 - i] = 15 - i;
+ }
+ }
+ for (i = a0 + 16; i < 160; i++)
+ {
+ if (i >= 0)
+ {
+ gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer][i] = 0;
+ }
+ }
+ for (i = a0 - 16; i >= 0; i--)
+ {
+ if (i >= 0)
+ {
+ gScanlineEffectRegBuffers[gScanlineEffect.srcBuffer][i] = 0;
+ }
+ }
+}
+
+static void ScheduleStopScanlineEffect(void)
+{
+ if (gScanlineEffect.state)
+ gScanlineEffect.state = 3;
+ SetGpuReg(REG_OFFSET_BLDCNT, 0);
+ SetGpuReg(REG_OFFSET_BLDY, 0);
+}
+
+static void LoadMainTitleScreenPalsAndResetBgs(void)
+{
+ u8 taskId;
+
+ taskId = FindTaskIdByFunc(Task_TitleScreen_SlideWin0);
+ if (taskId != 0xFF)
+ DestroyTask(taskId);
+
+ sub_8071898();
+ ResetPaletteFadeControl();
+ LoadPalette(gGraphics_TitleScreen_PokemonFireRedLogoPals, 0x00, 0x1A0);
+ LoadPalette(gGraphics_TitleScreen_CharizardPals, 0xD0, 0x20);
+ LoadPalette(gGraphics_TitleScreen_BackgroundPals, 0xF0, 0x20);
+ LoadPalette(gGraphics_TitleScreen_BackgroundPals, 0xE0, 0x20);
+ ResetBgPositions();
+ ClearGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_WIN0_ON | DISPCNT_WIN1_ON | DISPCNT_OBJWIN_ON);
+ ShowBg(1);
+ ShowBg(2);
+ ShowBg(0);
+ ShowBg(3);
+}
+
+static void CB2_FadeOutTransitionToSaveClearScreen(void)
+{
+ if (!UpdatePaletteFade())
+ SetMainCallback2(CB2_SaveClearScreen_Init);
+}
+
+static void CB2_FadeOutTransitionToBerryFix(void)
+{
+ if (!UpdatePaletteFade())
+ {
+ m4aMPlayAllStop();
+ SetMainCallback2(mb_berry_fix_serve);
+ }
+}
+
+static void LoadSpriteGfxAndPals(void)
+{
+ s32 i;
+
+ for (i = 0; i < NELEMS(sSpriteSheets); i++)
+ LoadCompressedSpriteSheet(&sSpriteSheets[i]);
+ LoadSpritePalettes(sSpritePals);
+}
+
+static void SpriteCallback_TitleScreenFlameOrLeaf(struct Sprite * sprite)
+{
+ s16 * data = sprite->data;
+ sprite->data[0] -= data[1];
+ sprite->pos1.x = sprite->data[0] >> 4;
+ if (sprite->pos1.x < -8)
+ {
+ DestroySprite(sprite);
+ return;
+ }
+ data[2] += data[3];
+ sprite->pos1.y = data[2] >> 4;
+ if (sprite->pos1.y < 0x10 || sprite->pos1.y > 0xc8)
+ {
+ DestroySprite(sprite);
+ return;
+ }
+#if defined(FIRERED)
+ if (sprite->animEnded)
+ {
+ DestroySprite(sprite);
+ return;
+ }
+ if (data[7] != 0 && --data[7] == 0)
+ {
+ StartSpriteAnim(sprite, 0);
+ sprite->invisible = FALSE;
+ }
+#elif defined(LEAFGREEN)
+ if (!data[5])
+ {
+ s32 r2;
+ s32 r1;
+ data[6]++;
+ r2 = data[1] * data[6];
+ r1 = data[6] * data[3];
+ r2 = (r2 * r2) >> 4;
+ r1 = (r1 * r1) >> 4;
+ if (r2 + r1 >= 0x510)
+ data[5] = TRUE;
+ }
+#endif
+}
+
+static bool32 CreateFlameOrLeafSprite(s32 x, s32 y, s32 xspeed, s32 yspeed, bool32 templateId)
+{
+ u8 spriteId;
+ if (templateId)
+ {
+ spriteId = CreateSprite(&sSpriteTemplate_FlameOrLeaf_State1, x, y, 0);
+ }
+ else
+ {
+ spriteId = CreateSprite(&sSpriteTemplate_FlameOrLeaf_State0, x, y, 0);
+ }
+ if (spriteId != MAX_SPRITES)
+ {
+ gSprites[spriteId].data[0] = x << 4;
+ gSprites[spriteId].data[1] = xspeed;
+ gSprites[spriteId].data[2] = y << 4;
+ gSprites[spriteId].data[3] = yspeed;
+ gSprites[spriteId].data[4] = 0;
+ gSprites[spriteId].data[5] = (xspeed * yspeed) % 16;
+ gSprites[spriteId].data[6] = templateId;
+ gSprites[spriteId].callback = SpriteCallback_TitleScreenFlameOrLeaf;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static void Task_FlameOrLeafSpawner(u8 taskId)
+{
+ s16 * data = gTasks[taskId].data;
+ s32 x, y, xspeed, yspeed, templateId;
+ s32 i;
+
+ switch (data[0])
+ {
+ case 0:
+ TitleScreen_srand(taskId, 3, 30840);
+ data[0]++;
+ break;
+ case 1:
+ data[1]++;
+ if (data[1] >= data[2])
+ {
+ data[1] = 0;
+ TitleScreen_rand(taskId, 3);
+ data[2] = 18;
+ xspeed = (TitleScreen_rand(taskId, 3) % 4) - 2;
+ yspeed = (TitleScreen_rand(taskId, 3) % 8) - 16;
+ y = (TitleScreen_rand(taskId, 3) % 3) + 0x74;
+ x = TitleScreen_rand(taskId, 3) % 240;
+ CreateFlameOrLeafSprite(
+ x,
+ y,
+ xspeed,
+ yspeed,
+ (TitleScreen_rand(taskId, 3) % 16) < 8 ? 0 : 1
+ );
+ for (i = 0; i < 15; i++)
+ {
+ CreateFlameOrLeafSprite(
+ data[5] + gUnknown_83BFBD4[i],
+ y,
+ xspeed,
+ yspeed,
+ 1
+ );
+ xspeed = (TitleScreen_rand(taskId, 3) % 4) - 2;
+ yspeed = (TitleScreen_rand(taskId, 3) % 8) - 16;
+ }
+ data[5]++;
+ if (data[5] > 3)
+ data[5] = 0;
+ }
+ }
+}
+
+static void TitleScreen_srand(u8 taskId, u8 field, u16 seed)
+{
+ SetWordTaskArg(taskId, field, seed);
+}
+
+static u16 TitleScreen_rand(u8 taskId, u8 field)
+{
+ u32 rngval;
+
+ rngval = GetWordTaskArg(taskId, field);
+ rngval = rngval * 1103515245 + 24691;
+ SetWordTaskArg(taskId, field, rngval);
+ return rngval >> 16;
+}
+
+static u32 CreateBlankSprite(void)
+{
+ CreateSprite(&sUnknownEmptySprite, 0x18, 0x90, 0);
+ return IndexOfSpritePaletteTag(2);
+}
+
+static void SetPalOnOrCreateBlankSprite(bool32 mode)
+{
+ u32 palIdx;
+
+ if (mode)
+ {
+ palIdx = IndexOfSpritePaletteTag(2);
+ LoadPalette(gGraphics_TitleScreen_FirePals, palIdx * 16 + 0x100, 0x20);
+ }
+ else
+ CreateBlankSprite();
+}
+
+static u8 CreateSlashSprite(void)
+{
+ u8 spriteId = CreateSprite(&sSlashSpriteTemplate, -0x20, 0x1B, 1);
+ if (spriteId != MAX_SPRITES)
+ {
+ gSprites[spriteId].callback = SpriteCallback_Slash;
+ gSprites[spriteId].data[1] = 540;
+ }
+ return spriteId;
+}
+
+static void ScheduleHideSlashSprite(u8 spriteId)
+{
+ if (spriteId != MAX_SPRITES)
+ gSprites[spriteId].data[2] = TRUE;
+}
+
+static bool32 IsSlashSpriteHidden(u8 spriteId)
+{
+ if (spriteId != MAX_SPRITES)
+ return gSprites[spriteId].data[0] ^ 2 ? TRUE : FALSE;
+ else
+ return FALSE;
+}
+
+static void SpriteCallback_Slash(struct Sprite * sprite)
+{
+ switch (sprite->data[0])
+ {
+ case 0:
+ if (sprite->data[2])
+ {
+ sprite->invisible = TRUE;
+ sprite->data[0] = 2;
+ }
+ sprite->data[1]--;
+ if (sprite->data[1] == 0)
+ {
+ sprite->invisible = FALSE;
+ sprite->data[0] = 1;
+ }
+ break;
+ case 1:
+ sprite->pos1.x += 9;
+ if (sprite->pos1.x == 67)
+ {
+ sprite->pos1.y -= 7;
+ }
+ if (sprite->pos1.x == 148)
+ {
+ sprite->pos1.y += 7;
+ }
+ if (sprite->pos1.x > 272)
+ {
+ sprite->invisible = TRUE;
+ if (sprite->data[2])
+ sprite->data[0] = 2;
+ else
+ {
+ sprite->pos1.x = -0x20;
+ sprite->data[1] = 540;
+ sprite->data[0] = 0;
+ }
+ }
+ break;
+ case 2:
+ break;
+ }
+}
diff --git a/src/trainer_tower.c b/src/trainer_tower.c
index f1ae2d4e5..d80be781d 100644
--- a/src/trainer_tower.c
+++ b/src/trainer_tower.c
@@ -1111,7 +1111,7 @@ void sub_815E114(void)
void sub_815E124(u8 taskId)
{
- if (sub_80D08F8() == TRUE)
+ if (BT_IsDone() == TRUE)
{
gMain.savedCallback = sub_815E114;
CleanupOverworldWindowsAndTilemaps();
@@ -1129,7 +1129,7 @@ void sub_815E160(void)
sub_815E9FC();
CreateTask(sub_815E124, 1);
PlayMapChosenOrBattleBGM(0);
- sub_80D08B8(sub_8080060());
+ BT_StartOnField(sub_8080060());
}
void sub_815E1C0(void)
diff --git a/src/vs_seeker.c b/src/vs_seeker.c
index e3df77242..f7b29292a 100644
--- a/src/vs_seeker.c
+++ b/src/vs_seeker.c
@@ -1,4 +1,5 @@
#include "global.h"
+#include "constants/songs.h"
#include "sound.h"
#include "task.h"
#include "malloc.h"
@@ -22,7 +23,6 @@
#include "map_obj_8097404.h"
#include "unk_810c3a4.h"
#include "constants/movement_commands.h"
-#include "constants/songs.h"
#include "vs_seeker.h"
typedef enum