#include "global.h" #include "rayquaza_scene.h" #include "sprite.h" #include "task.h" #include "graphics.h" #include "bg.h" #include "main.h" #include "malloc.h" #include "palette.h" #include "scanline_effect.h" #include "menu.h" #include "menu_helpers.h" #include "gpu_regs.h" #include "decompress.h" #include "sound.h" #include "constants/songs.h" #include "constants/species.h" #include "constants/rgb.h" #include "random.h" struct RaySceneStruct { MainCallback callback; u8 tilemapBuffers[4][0x800]; u16 field_2004; // set but unused u8 animId; bool8 onlyOneAnim; s16 field_2008; s16 field_200A; u8 unusedFields[12]; // completely unused }; // EWRAM vars static EWRAM_DATA struct RaySceneStruct *sRayScene = NULL; // this file's functions static void Task_DuoFightAnim(u8 taskId); static void Task_RayTakesFlightAnim(u8 taskId); static void Task_RayDescendsAnim(u8 taskId); static void Task_RayChargesAnim(u8 taskId); static void Task_RayChasesAwayAnim(u8 taskId); static void Task_HandleRayDescends(u8 taskId); static void Task_RayDescendsEnd(u8 taskId); static void Task_HandleRayCharges(u8 taskId); static void sub_81D8AD8(u8 taskId); static void sub_81D8B2C(u8 taskId); static void Task_RayChargesEnd(u8 taskId); static void Task_HandleRayChasesAway(u8 taskId); static void sub_81D8FB0(u8 taskId); static void sub_81D7228(u8 taskId); static void Task_HandleDuoFight(u8 taskId); static void sub_81D752C(u8 taskId); static void Task_DuoFightEnd(u8 taskId); static void Task_HandleRayTakesFlight(u8 taskId); static void sub_81D81A4(u8 taskId); static void Task_RayTakesFlightEnd(u8 taskId); static void sub_81D94D4(u8 taskId); static void sub_81D93D8(u8 taskId); static void Task_RayChasesAwayEnd(u8 taskId); static void sub_81D90A8(u8 taskId); static void sub_81D98B4(u8 taskId); static void Task_EndAfterFadeScreen(u8 taskId); static void CB2_InitRayquazaScene(void); static void CB2_RayquazaScene(void); static void sub_81D750C(void); static void sub_81D7438(void); static void sub_81D7480(void); static void sub_81D74C8(void); static void sub_81D8BB4(void); static void sub_81D6A20(struct Sprite *sprite); static void sub_81D6D20(struct Sprite *sprite); static void sub_81D7860(struct Sprite *sprite); static void sub_81D7D14(struct Sprite *sprite); static void sub_81D7700(struct Sprite *sprite); static void sub_81D7A60(struct Sprite *sprite); static void sub_81D874C(struct Sprite *sprite); static void sub_81D9338(struct Sprite *sprite); static void sub_81D9420(struct Sprite *sprite); static void sub_81D8260(struct Sprite *sprite); static void sub_81D961C(struct Sprite *sprite); static void sub_81D97E0(struct Sprite *sprite); static void sub_81D9528(struct Sprite *sprite); static u8 sub_81D7664(void); static u8 sub_81D78BC(void); static u8 sub_81D86CC(void); static void DuoFightEnd(u8 taskId, s8 palDelay); static void sub_81D9868(struct Sprite *sprite, u8 animNum, s16 x, s16 y); // const rom data static const TaskFunc sTasksForAnimations[] = { Task_DuoFightAnim, // RAY_ANIM_DUO_FIGHT_PRE Task_DuoFightAnim, // RAY_ANIM_DUO_FIGHT Task_RayTakesFlightAnim, // RAY_ANIM_TAKES_FLIGHT Task_RayDescendsAnim, // RAY_ANIM_DESCENDS Task_RayChargesAnim, // RAY_ANIM_CHARGES Task_RayChasesAwayAnim, // RAY_ANIM_CHACES_AWAY Task_EndAfterFadeScreen // RAY_ANIM_END }; static const struct OamData sOamData_862A6BC = { .y = 0, .affineMode = 0, .objMode = 0, .mosaic = 0, .bpp = 0, .shape = 0, .x = 0, .matrixNum = 0, .size = 3, .tileNum = 0, .priority = 2, .paletteNum = 0, .affineParam = 0 }; static const struct OamData sOamData_862A6C4 = { .y = 0, .affineMode = 0, .objMode = 0, .mosaic = 0, .bpp = 0, .shape = 0, .x = 0, .matrixNum = 0, .size = 2, .tileNum = 0, .priority = 2, .paletteNum = 0, .affineParam = 0 }; static const struct OamData sOamData_862A6CC = { .y = 0, .affineMode = 0, .objMode = 0, .mosaic = 0, .bpp = 0, .shape = 1, .x = 0, .matrixNum = 0, .size = 3, .tileNum = 0, .priority = 2, .paletteNum = 0, .affineParam = 0 }; static const struct OamData sOamData_862A6D4 = { .y = 0, .affineMode = 0, .objMode = 0, .mosaic = 0, .bpp = 0, .shape = 1, .x = 0, .matrixNum = 0, .size = 2, .tileNum = 0, .priority = 2, .paletteNum = 0, .affineParam = 0 }; static const struct OamData sOamData_862A6DC = { .y = 0, .affineMode = 0, .objMode = 0, .mosaic = 0, .bpp = 0, .shape = 1, .x = 0, .matrixNum = 0, .size = 0, .tileNum = 0, .priority = 2, .paletteNum = 0, .affineParam = 0 }; static const struct OamData sOamData_862A6E4 = { .y = 0, .affineMode = 0, .objMode = 0, .mosaic = 0, .bpp = 0, .shape = 2, .x = 0, .matrixNum = 0, .size = 2, .tileNum = 0, .priority = 2, .paletteNum = 0, .affineParam = 0 }; static const struct OamData sOamData_862A6EC = { .y = 0, .affineMode = 0, .objMode = 0, .mosaic = 0, .bpp = 0, .shape = 0, .x = 0, .matrixNum = 0, .size = 1, .tileNum = 0, .priority = 2, .paletteNum = 0, .affineParam = 0 }; static const struct OamData sOamData_862A6F4 = { .y = 0, .affineMode = 0, .objMode = 0, .mosaic = 0, .bpp = 0, .shape = 1, .x = 0, .matrixNum = 0, .size = 1, .tileNum = 0, .priority = 2, .paletteNum = 0, .affineParam = 0 }; static const union AnimCmd sSpriteAnim_862A6FC[] = { ANIMCMD_FRAME(0, 30), ANIMCMD_FRAME(64, 30), ANIMCMD_FRAME(128, 30), ANIMCMD_FRAME(64, 30), ANIMCMD_JUMP(0), }; static const union AnimCmd sSpriteAnim_862A710[] = { ANIMCMD_FRAME(192, 30), ANIMCMD_FRAME(256, 30), ANIMCMD_FRAME(320, 30), ANIMCMD_FRAME(256, 30), ANIMCMD_JUMP(0), }; static const union AnimCmd *const sSpriteAnimTable_862A724[] = { sSpriteAnim_862A6FC, sSpriteAnim_862A710 }; static const struct SpriteTemplate sUnknown_0862A72C = { .tileTag = 30505, .paletteTag = 30505, .oam = &sOamData_862A6BC, .anims = sSpriteAnimTable_862A724, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = SpriteCallbackDummy, }; static const union AnimCmd sSpriteAnim_862A744[] = { ANIMCMD_FRAME(0, 1), ANIMCMD_END }; static const union AnimCmd *const sSpriteAnimTable_862A74C[] = { sSpriteAnim_862A744 }; static const struct SpriteTemplate sUnknown_0862A750 = { .tileTag = 30506, .paletteTag = 30505, .oam = &sOamData_862A6C4, .anims = sSpriteAnimTable_862A74C, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = SpriteCallbackDummy, }; static const union AnimCmd sSpriteAnim_862A768[] = { ANIMCMD_FRAME(0, 1), ANIMCMD_END }; static const union AnimCmd *const sSpriteAnimTable_862A770[] = { sSpriteAnim_862A768 }; static const struct SpriteTemplate sUnknown_0862A774 = { .tileTag = 30507, .paletteTag = 30505, .oam = &sOamData_862A6CC, .anims = sSpriteAnimTable_862A770, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = SpriteCallbackDummy, }; static const union AnimCmd sSpriteAnim_862A78C[] = { ANIMCMD_FRAME(0, 1), ANIMCMD_END }; static const union AnimCmd sSpriteAnim_862A794[] = { ANIMCMD_FRAME(8, 1), ANIMCMD_END }; static const union AnimCmd sSpriteAnim_862A79C[] = { ANIMCMD_FRAME(16, 1), ANIMCMD_END }; static const union AnimCmd sSpriteAnim_862A7A4[] = { ANIMCMD_FRAME(24, 1), ANIMCMD_END }; static const union AnimCmd sSpriteAnim_862A7AC[] = { ANIMCMD_FRAME(32, 1), ANIMCMD_END }; static const union AnimCmd sSpriteAnim_862A7B4[] = { ANIMCMD_FRAME(40, 1), ANIMCMD_END }; static const union AnimCmd sSpriteAnim_862A7BC[] = { ANIMCMD_FRAME(48, 36), ANIMCMD_FRAME(64, 36), ANIMCMD_FRAME(80, 36), ANIMCMD_FRAME(64, 36), ANIMCMD_JUMP(0), }; static const union AnimCmd sSpriteAnim_862A7D0[] = { ANIMCMD_FRAME(56, 36), ANIMCMD_FRAME(72, 36), ANIMCMD_FRAME(88, 36), ANIMCMD_FRAME(72, 36), ANIMCMD_JUMP(0), }; static const union AnimCmd sSpriteAnim_862A7E4[] = { ANIMCMD_FRAME(96, 36), ANIMCMD_FRAME(104, 36), ANIMCMD_FRAME(112, 36), ANIMCMD_FRAME(104, 36), ANIMCMD_JUMP(0), }; static const union AnimCmd *const sSpriteAnimTable_862A7F8[] = { sSpriteAnim_862A78C, sSpriteAnim_862A794, sSpriteAnim_862A79C, sSpriteAnim_862A7A4, sSpriteAnim_862A7AC, sSpriteAnim_862A7B4, sSpriteAnim_862A7BC, sSpriteAnim_862A7D0, sSpriteAnim_862A7E4 }; static const struct SpriteTemplate sUnknown_0862A81C = { .tileTag = 30508, .paletteTag = 30508, .oam = &sOamData_862A6D4, .anims = sSpriteAnimTable_862A7F8, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = SpriteCallbackDummy, }; static const union AnimCmd sSpriteAnim_862A834[] = { ANIMCMD_FRAME(0, 36), ANIMCMD_FRAME(2, 36), ANIMCMD_FRAME(4, 36), ANIMCMD_FRAME(2, 36), ANIMCMD_JUMP(0), }; static const union AnimCmd *const sSpriteAnimTable_862A848[] = { sSpriteAnim_862A834 }; static const struct SpriteTemplate sUnknown_0862A84C = { .tileTag = 30509, .paletteTag = 30508, .oam = &sOamData_862A6DC, .anims = sSpriteAnimTable_862A848, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = SpriteCallbackDummy, }; static const struct SpriteTemplate sUnknown_0862A864 = { .tileTag = 30510, .paletteTag = 30508, .oam = &sOamData_862A6C4, .anims = sSpriteAnimTable_862A74C, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = SpriteCallbackDummy, }; static const struct ScanlineEffectParams sUnknown_0862A87C = { .dmaDest = (vu16 *)REG_ADDR_BG1HOFS, .dmaControl = 0xA2600001, .initState = 1 }; static const struct BgTemplate sUnknown_0862A888[] = { { .bg = 0, .charBaseIndex = 0, .mapBaseIndex = 31, .screenSize = 0, .paletteMode = 0, .priority = 0, .baseTile = 0 }, { .bg = 1, .charBaseIndex = 0, .mapBaseIndex = 30, .screenSize = 0, .paletteMode = 0, .priority = 2, .baseTile = 0 }, { .bg = 2, .charBaseIndex = 0, .mapBaseIndex = 29, .screenSize = 0, .paletteMode = 0, .priority = 1, .baseTile = 0 }, }; static const union AnimCmd sSpriteAnim_862A894[] = { ANIMCMD_FRAME(0, 20), ANIMCMD_FRAME(64, 20), ANIMCMD_FRAME(128, 20), ANIMCMD_FRAME(64, 20), ANIMCMD_JUMP(0), }; static const union AnimCmd sSpriteAnim_862A8A8[] = { ANIMCMD_FRAME(192, 20), ANIMCMD_FRAME(256, 20), ANIMCMD_FRAME(320, 20), ANIMCMD_FRAME(256, 20), ANIMCMD_JUMP(0), }; static const union AnimCmd *const sSpriteAnimTable_862A8BC[] = { sSpriteAnim_862A894, sSpriteAnim_862A8A8 }; static const struct CompressedSpriteSheet sUnknown_0862A8C4 = { gRaySceneGroudon_Gfx, 0x3000, 30505 }; static const struct CompressedSpritePalette sUnknown_0862A8CC = { gRaySceneGroudon_Pal, 30505 }; static const struct SpriteTemplate sUnknown_0862A8D4 = { .tileTag = 30505, .paletteTag = 30505, .oam = &sOamData_862A6BC, .anims = sSpriteAnimTable_862A8BC, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = SpriteCallbackDummy, }; static const union AnimCmd sSpriteAnim_862A8EC[] = { ANIMCMD_FRAME(0, 1), ANIMCMD_END }; static const union AnimCmd *const sSpriteAnimTable_862A8F4[] = { sSpriteAnim_862A8EC }; static const struct CompressedSpriteSheet sUnknown_0862A8F8 = { gRaySceneGroudon2_Gfx, 0x200, 30506 }; static const struct SpriteTemplate sUnknown_0862A900 = { .tileTag = 30506, .paletteTag = 30505, .oam = &sOamData_862A6C4, .anims = sSpriteAnimTable_862A8F4, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = SpriteCallbackDummy, }; static const union AnimCmd sSpriteAnim_862A918[] = { ANIMCMD_FRAME(0, 1), ANIMCMD_END }; static const union AnimCmd *const sSpriteAnimTable_862A920[] = { sSpriteAnim_862A918 }; static const struct CompressedSpriteSheet sUnknown_0862A924 = { gRaySceneGroudon3_Gfx, 0x400, 30507 }; static const struct SpriteTemplate sUnknown_0862A92C = { .tileTag = 30507, .paletteTag = 30505, .oam = &sOamData_862A6CC, .anims = sSpriteAnimTable_862A920, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = SpriteCallbackDummy, }; static const union AnimCmd sSpriteAnim_862A944[] = { ANIMCMD_FRAME(0, 1), ANIMCMD_END }; static const union AnimCmd sSpriteAnim_862A94C[] = { ANIMCMD_FRAME(8, 1), ANIMCMD_END }; static const union AnimCmd sSpriteAnim_862A954[] = { ANIMCMD_FRAME(16, 1), ANIMCMD_END }; static const union AnimCmd sSpriteAnim_862A95C[] = { ANIMCMD_FRAME(24, 1), ANIMCMD_END }; static const union AnimCmd sSpriteAnim_862A964[] = { ANIMCMD_FRAME(32, 1), ANIMCMD_END }; static const union AnimCmd sSpriteAnim_862A96C[] = { ANIMCMD_FRAME(40, 1), ANIMCMD_END }; static const union AnimCmd sSpriteAnim_862A974[] = { ANIMCMD_FRAME(48, 24), ANIMCMD_FRAME(64, 24), ANIMCMD_FRAME(80, 24), ANIMCMD_FRAME(64, 24), ANIMCMD_JUMP(0), }; static const union AnimCmd sSpriteAnim_862A988[] = { ANIMCMD_FRAME(56, 24), ANIMCMD_FRAME(72, 24), ANIMCMD_FRAME(88, 24), ANIMCMD_FRAME(72, 24), ANIMCMD_JUMP(0), }; static const union AnimCmd sSpriteAnim_862A99C[] = { ANIMCMD_FRAME(96, 24), ANIMCMD_FRAME(104, 24), ANIMCMD_FRAME(112, 24), ANIMCMD_FRAME(104, 24), ANIMCMD_JUMP(0), }; static const union AnimCmd *const sSpriteAnimTable_862A9B0[] = { sSpriteAnim_862A944, sSpriteAnim_862A94C, sSpriteAnim_862A954, sSpriteAnim_862A95C, sSpriteAnim_862A964, sSpriteAnim_862A96C, sSpriteAnim_862A974, sSpriteAnim_862A988, sSpriteAnim_862A99C }; static const struct CompressedSpriteSheet sUnknown_0862A9D4 = { gRaySceneKyogre_Gfx, 0xF00, 30508 }; static const struct CompressedSpritePalette sUnknown_0862A9DC = { gRaySceneKyogre_Pal, 30508 }; static const struct SpriteTemplate sUnknown_0862A9E4 = { .tileTag = 30508, .paletteTag = 30508, .oam = &sOamData_862A6D4, .anims = sSpriteAnimTable_862A9B0, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = SpriteCallbackDummy, }; static const union AnimCmd sSpriteAnim_862A9FC[] = { ANIMCMD_FRAME(0, 24), ANIMCMD_FRAME(2, 24), ANIMCMD_FRAME(4, 24), ANIMCMD_FRAME(2, 24), ANIMCMD_JUMP(0), }; static const union AnimCmd *const sSpriteAnimTable_862AA10[] = { sSpriteAnim_862A9FC }; static const struct CompressedSpriteSheet sUnknown_0862AA14 = { gRaySceneKyogre2_Gfx, 0xC0, 30509 }; static const struct SpriteTemplate sUnknown_0862AA1C = { .tileTag = 30509, .paletteTag = 30508, .oam = &sOamData_862A6DC, .anims = sSpriteAnimTable_862AA10, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = SpriteCallbackDummy, }; static const struct CompressedSpriteSheet sUnknown_0862AA34 = { gRaySceneKyogre3_Gfx, 0x200, 30510 }; static const struct SpriteTemplate sUnknown_0862AA3C = { .tileTag = 30510, .paletteTag = 30508, .oam = &sOamData_862A6C4, .anims = sSpriteAnimTable_862A8F4, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = SpriteCallbackDummy, }; static const struct BgTemplate sUnknown_0862AA54[] = { { .bg = 0, .charBaseIndex = 2, .mapBaseIndex = 31, .screenSize = 0, .paletteMode = 0, .priority = 0, .baseTile = 0 }, { .bg = 1, .charBaseIndex = 0, .mapBaseIndex = 30, .screenSize = 0, .paletteMode = 0, .priority = 2, .baseTile = 0 }, { .bg = 2, .charBaseIndex = 1, .mapBaseIndex = 29, .screenSize = 1, .paletteMode = 0, .priority = 1, .baseTile = 0 } }; static const union AnimCmd sSpriteAnim_862AA60[] = { ANIMCMD_FRAME(0, 1), ANIMCMD_END }; static const union AnimCmd *const sSpriteAnimTable_862AA68[] = { sSpriteAnim_862AA60 }; static const union AffineAnimCmd sSpriteAffineAnim_862AA6C[] = { AFFINEANIMCMD_FRAME(-64, -64, 0, 1), AFFINEANIMCMD_FRAME(32, 32, 0, 14), AFFINEANIMCMD_FRAME(256, 256, 0, 0), AFFINEANIMCMD_JUMP(0) }; static const union AffineAnimCmd *const sSpriteAffineAnimTable_862AA8C[] = { sSpriteAffineAnim_862AA6C }; static const struct CompressedSpriteSheet sUnknown_0862AA90 = { gRaySceneSmoke_Gfx, 0x100, 30555 }; static const struct CompressedSpritePalette sUnknown_0862AA98 = { gRaySceneSmoke_Pal, 30555 }; static const struct SpriteTemplate sUnknown_0862AAA0 = { .tileTag = 30555, .paletteTag = 30555, .oam = &sOamData_862A6D4, .anims = sSpriteAnimTable_862AA68, .images = NULL, .affineAnims = sSpriteAffineAnimTable_862AA8C, .callback = sub_81D8260, }; static const s8 sUnknown_0862AAB8[][2] = { {-1, 5}, {-3, -4}, {5, -3}, {-7, 2}, {-9, -1}, {1, -5}, {3, 4}, {-5, 3}, {7, -2}, {9, 1} }; static const struct BgTemplate sUnknown_0862AACC[] = { { .bg = 0, .charBaseIndex = 0, .mapBaseIndex = 31, .screenSize = 0, .paletteMode = 0, .priority = 0, .baseTile = 0 }, { .bg = 1, .charBaseIndex = 1, .mapBaseIndex = 30, .screenSize = 0, .paletteMode = 0, .priority = 1, .baseTile = 0 }, { .bg = 2, .charBaseIndex = 2, .mapBaseIndex = 29, .screenSize = 0, .paletteMode = 0, .priority = 2, .baseTile = 0 }, { .bg = 3, .charBaseIndex = 1, .mapBaseIndex = 28, .screenSize = 0, .paletteMode = 0, .priority = 3, .baseTile = 0 } }; static const union AnimCmd sSpriteAnim_862AADC[] = { ANIMCMD_FRAME(0, 32), ANIMCMD_FRAME(64, 32), ANIMCMD_JUMP(0), }; static const union AnimCmd *const sSpriteAnimTable_862AAE8[] = { sSpriteAnim_862AADC }; static const union AnimCmd sSpriteAnim_862AAEC[] = { ANIMCMD_FRAME(0, 32), ANIMCMD_FRAME(8, 32), ANIMCMD_JUMP(0), }; static const union AnimCmd *const sSpriteAnimTable_862AAF8[] = { sSpriteAnim_862AAEC }; static const struct CompressedSpriteSheet sUnknown_0862AAFC = { gRaySceneRayquazaFly1_Gfx, 0x1000, 30556 }; static const struct CompressedSpriteSheet sUnknown_0862AB04 = { gRaySceneRayquazaTail_Gfx, 0x200, 30557 }; static const struct CompressedSpritePalette sUnknown_0862AB0C = { gRaySceneRayquaza_Pal, 30556 }; static const struct SpriteTemplate sUnknown_0862AB14 = { .tileTag = 30556, .paletteTag = 30556, .oam = &sOamData_862A6BC, .anims = sSpriteAnimTable_862AAE8, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = SpriteCallbackDummy, }; static const struct SpriteTemplate sUnknown_0862AB2C = { .tileTag = 30557, .paletteTag = 30556, .oam = &sOamData_862A6E4, .anims = sSpriteAnimTable_862AAF8, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = SpriteCallbackDummy, }; static const struct BgTemplate sUnknown_0862AB44[] = { { .bg = 0, .charBaseIndex = 2, .mapBaseIndex = 31, .screenSize = 0, .paletteMode = 0, .priority = 0, .baseTile = 0 }, { .bg = 1, .charBaseIndex = 1, .mapBaseIndex = 30, .screenSize = 0, .paletteMode = 0, .priority = 1, .baseTile = 0 }, { .bg = 2, .charBaseIndex = 2, .mapBaseIndex = 29, .screenSize = 0, .paletteMode = 0, .priority = 2, .baseTile = 0 }, { .bg = 3, .charBaseIndex = 3, .mapBaseIndex = 28, .screenSize = 0, .paletteMode = 0, .priority = 3, .baseTile = 0 } }; static const union AnimCmd sSpriteAnim_862AB54[] = { ANIMCMD_FRAME(0, 1), ANIMCMD_END }; static const union AnimCmd sSpriteAnim_862AB5C[] = { ANIMCMD_FRAME(0, 48), ANIMCMD_FRAME(64, 32), ANIMCMD_FRAME(0, 48), ANIMCMD_FRAME(128, 32), ANIMCMD_JUMP(0) }; static const union AnimCmd *const sSpriteAnimTable_862AB70[] = { sSpriteAnim_862AB54, sSpriteAnim_862AB5C }; static const union AnimCmd sSpriteAnim_862AB78[] = { ANIMCMD_FRAME(0, 1), ANIMCMD_END }; static const union AnimCmd *const sSpriteAnimTable_862AB80[] = { sSpriteAnim_862AB78, }; static const union AnimCmd sSpriteAnim_862AB84[] = { ANIMCMD_FRAME(0, 1), ANIMCMD_END }; static const union AnimCmd sSpriteAnim_862AB8C[] = { ANIMCMD_FRAME(16, 1), ANIMCMD_END }; static const union AnimCmd sSpriteAnim_862AB94[] = { ANIMCMD_FRAME(32, 1), ANIMCMD_END }; static const union AnimCmd *const sSpriteAnimTable_862AB9C[] = { sSpriteAnim_862AB84, sSpriteAnim_862AB8C, sSpriteAnim_862AB94 }; static const union AnimCmd sSpriteAnim_862ABA8[] = { ANIMCMD_FRAME(0, 1), ANIMCMD_END }; static const union AnimCmd sSpriteAnim_862ABB0[] = { ANIMCMD_FRAME(64, 1), ANIMCMD_END }; static const union AnimCmd sSpriteAnim_862ABB8[] = { ANIMCMD_FRAME(128, 1), ANIMCMD_END }; static const union AnimCmd sSpriteAnim_862ABC0[] = { ANIMCMD_FRAME(192, 1), ANIMCMD_END }; static const union AnimCmd *const sSpriteAnimTable_862ABC8[] = { sSpriteAnim_862ABA8, sSpriteAnim_862ABB0, sSpriteAnim_862ABB8, sSpriteAnim_862ABC0 }; static const union AnimCmd sSpriteAnim_862ABD8[] = { ANIMCMD_FRAME(0, 1), ANIMCMD_END }; static const union AnimCmd sSpriteAnim_862ABE0[] = { ANIMCMD_FRAME(16, 1), ANIMCMD_END }; static const union AnimCmd sSpriteAnim_862ABE8[] = { ANIMCMD_FRAME(32, 1), ANIMCMD_END }; static const union AnimCmd sSpriteAnim_862ABF0[] = { ANIMCMD_FRAME(48, 1), ANIMCMD_END }; static const union AnimCmd *const sSpriteAnimTable_862ABF8[] = { sSpriteAnim_862ABD8, sSpriteAnim_862ABE0, sSpriteAnim_862ABE8, sSpriteAnim_862ABF0 }; static const union AnimCmd sSpriteAnim_862AC08[] = { ANIMCMD_FRAME(0, 8), ANIMCMD_FRAME(4, 8), ANIMCMD_FRAME(8, 8), ANIMCMD_FRAME(12, 8), ANIMCMD_FRAME(16, 8), ANIMCMD_FRAME(20, 8), ANIMCMD_JUMP(0) }; static const union AnimCmd *const sSpriteAnimTable_862AC24[] = { sSpriteAnim_862AC08 }; static const struct CompressedSpriteSheet sUnknown_0862AC28 = { gRaySceneGroudonLeft_Gfx, 0x1800, 30565 }; static const struct CompressedSpriteSheet sUnknown_0862AC30 = { gRaySceneGroudonTail_Gfx, 0x80, 30566 }; static const struct CompressedSpriteSheet sUnknown_0862AC38 = { gRaySceneKyogreRight_Gfx, 0x600, 30568 }; static const struct CompressedSpriteSheet sUnknown_0862AC40 = { gRaySceneRayquazaHover_Gfx, 0x2000, 30569 }; static const struct CompressedSpriteSheet sUnknown_0862AC48 = { gRaySceneRayquazaFlyIn_Gfx, 0x800, 30570 }; static const struct CompressedSpriteSheet sUnknown_0862AC50 = { gRaySceneSplash_Gfx, 0x300, 30571 }; static const struct CompressedSpritePalette sUnknown_0862AC58 = { gRaySceneGroudonLeft_Pal, 30565 }; static const struct CompressedSpritePalette sUnknown_0862AC60 = { gRaySceneKyogreRight_Pal, 30568 }; static const struct CompressedSpritePalette sUnknown_0862AC68 = { gRaySceneRayquazaHover_Pal, 30569 }; static const struct CompressedSpritePalette sUnknown_0862AC70 = { gRaySceneSplash_Pal, 30571 }; static const struct SpriteTemplate sUnknown_0862AC78 = { .tileTag = 30565, .paletteTag = 30565, .oam = &sOamData_862A6BC, .anims = sSpriteAnimTable_862AB70, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = SpriteCallbackDummy, }; static const struct SpriteTemplate sUnknown_0862AC90 = { .tileTag = 30566, .paletteTag = 30565, .oam = &sOamData_862A6EC, .anims = sSpriteAnimTable_862AB80, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = SpriteCallbackDummy, }; static const struct SpriteTemplate sUnknown_0862ACA8 = { .tileTag = 30568, .paletteTag = 30568, .oam = &sOamData_862A6C4, .anims = sSpriteAnimTable_862AB9C, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = SpriteCallbackDummy, }; static const struct SpriteTemplate sUnknown_0862ACC0 = { .tileTag = 30569, .paletteTag = 30569, .oam = &sOamData_862A6BC, .anims = sSpriteAnimTable_862ABC8, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = sub_81D961C, }; static const struct SpriteTemplate sUnknown_0862ACD8 = { .tileTag = 30570, .paletteTag = 30569, .oam = &sOamData_862A6C4, .anims = sSpriteAnimTable_862ABF8, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = SpriteCallbackDummy, }; static const struct SpriteTemplate sUnknown_0862ACF0 = { .tileTag = 30571, .paletteTag = 30571, .oam = &sOamData_862A6F4, .anims = sSpriteAnimTable_862AC24, .images = NULL, .affineAnims = gDummySpriteAffineAnimTable, .callback = SpriteCallbackDummy, }; static const struct BgTemplate sUnknown_0862AD08[] = { { .bg = 0, .charBaseIndex = 1, .mapBaseIndex = 31, .screenSize = 0, .paletteMode = 0, .priority = 1, .baseTile = 0 }, { .bg = 1, .charBaseIndex = 1, .mapBaseIndex = 30, .screenSize = 0, .paletteMode = 0, .priority = 2, .baseTile = 0 }, { .bg = 2, .charBaseIndex = 0, .mapBaseIndex = 29, .screenSize = 0, .paletteMode = 0, .priority = 0, .baseTile = 0 } }; // code void DoRayquazaScene(u8 animId, bool8 onlyOneAnim, void (*callback)(void)) { sRayScene = AllocZeroed(sizeof(*sRayScene)); sRayScene->animId = animId; sRayScene->callback = callback; sRayScene->onlyOneAnim = onlyOneAnim; SetMainCallback2(CB2_InitRayquazaScene); } static void CB2_InitRayquazaScene(void) { SetVBlankHBlankCallbacksToNull(); clear_scheduled_bg_copies_to_vram(); ScanlineEffect_Stop(); FreeAllSpritePalettes(); ResetPaletteFade(); ResetSpriteData(); ResetTasks(); FillPalette(0, 0xF0, 0x20); CreateTask(sTasksForAnimations[sRayScene->animId], 0); SetMainCallback2(CB2_RayquazaScene); } static void CB2_RayquazaScene(void) { RunTasks(); AnimateSprites(); BuildOamBuffer(); do_scheduled_bg_tilemap_copies_to_vram(); UpdatePaletteFade(); } static void VBlankCB_RayquazaScene(void) { LoadOam(); ProcessSpriteCopyRequests(); TransferPlttBuffer(); } static void Task_EndAfterFadeScreen(u8 taskId) { if (!gPaletteFade.active) { ResetSpriteData(); FreeAllSpritePalettes(); SetMainCallback2(sRayScene->callback); Free(sRayScene); DestroyTask(taskId); } } static void Task_SetNextAnim(u8 taskId) { if (!gPaletteFade.active) { if (sRayScene->onlyOneAnim == TRUE) { gTasks[taskId].func = Task_EndAfterFadeScreen; } else { sRayScene->animId++; sRayScene->field_2004 = 0; gTasks[taskId].func = sTasksForAnimations[sRayScene->animId]; } } } static void sub_81D68C8(void) { SetGpuReg(REG_OFFSET_WININ, 0x3F); SetGpuReg(REG_OFFSET_WINOUT, 0); SetGpuReg(REG_OFFSET_WIN0H, 0xF0); SetGpuReg(REG_OFFSET_WIN0V, 0x1888); gPlttBufferUnfaded[0] = 0; gPlttBufferFaded[0] = 0; } static void sub_81D6904(void) { SetGpuReg(REG_OFFSET_WININ, 0x3F); SetGpuReg(REG_OFFSET_WINOUT, 0x3F); } static void Task_HandleDuoFightPre(u8 taskId) { s16 *data = gTasks[taskId].data; sub_81D750C(); if (!gPaletteFade.active) { s16 counter = data[0]; if (counter == 64) { sub_81D7438(); } else if (counter == 144) { sub_81D7480(); } else { switch (counter) { case 328: DuoFightEnd(taskId, 0); return; case 148: sub_81D74C8(); break; } } data[0]++; } } static u8 sub_81D6984(void) { u8 spriteId; s16 *data; spriteId = CreateSprite(&sUnknown_0862A72C, 88, 72, 3); gSprites[spriteId].callback = sub_81D6A20; data = gSprites[spriteId].data; data[0] = CreateSprite(&sUnknown_0862A72C, 56, 104, 3); data[1] = CreateSprite(&sUnknown_0862A750, 75, 101, 0); data[2] = CreateSprite(&sUnknown_0862A774, 109, 114, 1); StartSpriteAnim(&gSprites[data[0]], 1); return spriteId; } static void sub_81D6A20(struct Sprite *sprite) { s16 *data = sprite->data; data[5]++; data[5] &= 0x1F; if (data[5] == 0 && sprite->pos1.x != 72) { sprite->pos1.x--; gSprites[sprite->data[0]].pos1.x--; gSprites[data[1]].pos1.x--; gSprites[data[2]].pos1.x--; } switch (sprite->animCmdIndex) { case 0: gSprites[data[1]].pos2.x = 0; gSprites[data[1]].pos2.y = 0; gSprites[data[2]].pos2.x = 0; gSprites[data[2]].pos2.y = 0; break; case 1: case 3: gSprites[data[1]].pos2.x = -1; gSprites[data[1]].pos2.y = 0; gSprites[data[2]].pos2.x = -1; gSprites[data[2]].pos2.y = 0; break; case 2: gSprites[data[1]].pos2.x = -1; gSprites[data[1]].pos2.y = 1; gSprites[data[2]].pos2.x = -2; gSprites[data[2]].pos2.y = 1; break; } } static u8 sub_81D6B7C(void) { u8 spriteId; s16 *data; spriteId = CreateSprite(&sUnknown_0862A81C, 136, 96, 1); gSprites[spriteId].callback = sub_81D6D20; data = gSprites[spriteId].data; data[0] = CreateSprite(&sUnknown_0862A81C, 168, 96, 1) << 8; data[0] |= CreateSprite(&sUnknown_0862A81C, 136, 112, 1); data[1] = CreateSprite(&sUnknown_0862A81C, 168, 112, 1) << 8; data[1] |= CreateSprite(&sUnknown_0862A81C, 136, 128, 1); data[2] = CreateSprite(&sUnknown_0862A81C, 168, 128, 1) << 8; data[2] |= CreateSprite(&sUnknown_0862A81C, 104, 128, 2); data[3] = CreateSprite(&sUnknown_0862A81C, 136, 128, 2) << 8; data[3] |= CreateSprite(&sUnknown_0862A81C, 184, 128, 0); data[4] = CreateSprite(&sUnknown_0862A84C, 208, 132, 0) << 8; data[4] |= CreateSprite(&sUnknown_0862A864, 200, 120, 1); StartSpriteAnim(&gSprites[data[0] >> 8], 1); StartSpriteAnim(&gSprites[data[0] & 0xFF], 2); StartSpriteAnim(&gSprites[data[1] >> 8], 3); StartSpriteAnim(&gSprites[data[1] & 0xFF], 4); StartSpriteAnim(&gSprites[data[2] >> 8], 5); StartSpriteAnim(&gSprites[data[2] & 0xFF], 6); StartSpriteAnim(&gSprites[data[3] >> 8], 7); StartSpriteAnim(&gSprites[data[3] & 0xFF], 8); return spriteId; } static void sub_81D6D20(struct Sprite *sprite) { s16 *data = sprite->data; data[5]++; data[5] &= 0x1F; if (data[5] == 0 && sprite->pos1.x != 152) { sprite->pos1.x++; gSprites[sprite->data[0] >> 8].pos1.x++; gSprites[sprite->data[0] & 0xFF].pos1.x++; gSprites[data[1] >> 8].pos1.x++; gSprites[data[1] & 0xFF].pos1.x++; gSprites[data[2] >> 8].pos1.x++; gSprites[data[2] & 0xFF].pos1.x++; gSprites[data[3] >> 8].pos1.x++; gSprites[data[3] & 0xFF].pos1.x++; gSprites[data[4] >> 8].pos1.x++; gSprites[data[4] & 0xFF].pos1.x++; } switch (gSprites[data[2] & 0xFF].animCmdIndex) { case 0: sprite->pos2.y = 0; gSprites[data[0] >> 8].pos2.y = 0; gSprites[data[0] & 0xFF].pos2.y = 0; gSprites[data[1] >> 8].pos2.y = 0; gSprites[data[1] & 0xFF].pos2.y = 0; gSprites[data[2] >> 8].pos2.y = 0; gSprites[data[2] & 0xFF].pos2.y = 0; gSprites[data[3] >> 8].pos2.y = 0; gSprites[data[3] & 0xFF].pos2.y = 0; gSprites[data[4] >> 8].pos2.y = 0; gSprites[data[4] & 0xFF].pos2.y = 0; break; case 1: case 3: sprite->pos2.y = 1; gSprites[data[0] >> 8].pos2.y = 1; gSprites[data[0] & 0xFF].pos2.y = 1; gSprites[data[1] >> 8].pos2.y = 1; gSprites[data[1] & 0xFF].pos2.y = 1; gSprites[data[2] >> 8].pos2.y = 1; gSprites[data[2] & 0xFF].pos2.y = 1; gSprites[data[3] >> 8].pos2.y = 1; gSprites[data[3] & 0xFF].pos2.y = 1; gSprites[data[4] >> 8].pos2.y = 1; gSprites[data[4] & 0xFF].pos2.y = 1; break; case 2: sprite->pos2.y = 2; gSprites[data[0] >> 8].pos2.y = 2; gSprites[data[0] & 0xFF].pos2.y = 2; gSprites[data[1] >> 8].pos2.y = 2; gSprites[data[1] & 0xFF].pos2.y = 2; gSprites[data[2] >> 8].pos2.y = 2; gSprites[data[4] & 0xFF].pos2.y = 2; break; } } static void VBlankCB_DuoFight(void) { VBlankCB_RayquazaScene(); ScanlineEffect_InitHBlankDmaTransfer(); } static void sub_81D6FE0(void) { ResetVramOamAndBgCntRegs(); ResetBgsAndClearDma3BusyFlags(0); InitBgsFromTemplates(0, sUnknown_0862A888, ARRAY_COUNT(sUnknown_0862A888)); SetBgTilemapBuffer(0, sRayScene->tilemapBuffers[0]); SetBgTilemapBuffer(1, sRayScene->tilemapBuffers[1]); SetBgTilemapBuffer(2, sRayScene->tilemapBuffers[2]); ResetAllBgsCoordinates(); schedule_bg_copy_tilemap_to_vram(0); schedule_bg_copy_tilemap_to_vram(1); schedule_bg_copy_tilemap_to_vram(2); SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_OBJ_ON | DISPCNT_OBJ_1D_MAP); ShowBg(0); ShowBg(1); ShowBg(2); SetGpuReg(REG_OFFSET_BLDCNT, 0); } static void sub_81D706C(void) { reset_temp_tile_data_buffers(); decompress_and_copy_tile_data_to_vram(0, gRaySceneClouds_Gfx, 0, 0, 0); while (free_temp_tile_data_buffers_if_possible()); LZDecompressWram(gRaySceneClouds2_Tilemap, sRayScene->tilemapBuffers[0]); LZDecompressWram(gRaySceneClouds1_Tilemap, sRayScene->tilemapBuffers[1]); LZDecompressWram(gRaySceneClouds3_Tilemap, sRayScene->tilemapBuffers[2]); LoadCompressedPalette(gRaySceneClouds_Pal, 0, 0x40); LoadCompressedObjectPic(&sUnknown_0862A8C4); LoadCompressedObjectPic(&sUnknown_0862A8F8); LoadCompressedObjectPic(&sUnknown_0862A924); LoadCompressedObjectPic(&sUnknown_0862A9D4); LoadCompressedObjectPic(&sUnknown_0862AA14); LoadCompressedObjectPic(&sUnknown_0862AA34); LoadCompressedObjectPalette(&sUnknown_0862A8CC); LoadCompressedObjectPalette(&sUnknown_0862A9DC); } static void Task_DuoFightAnim(u8 taskId) { s16 *data = gTasks[taskId].data; ScanlineEffect_Clear(); sub_81D6FE0(); sub_81D706C(); CpuFastFill16(0, gScanlineEffectRegBuffers, sizeof(gScanlineEffectRegBuffers)); ScanlineEffect_SetParams(sUnknown_0862A87C); data[0] = 0; data[1] = CreateTask(sub_81D7228, 0); if (sRayScene->animId == RAY_ANIM_DUO_FIGHT_PRE) { data[2] = sub_81D6984(); data[3] = sub_81D6B7C(); gTasks[taskId].func = Task_HandleDuoFightPre; } else { data[2] = sub_81D7664(); data[3] = sub_81D78BC(); gTasks[taskId].func = Task_HandleDuoFight; StopMapMusic(); } BlendPalettes(-1, 0x10, 0); BeginNormalPaletteFade(0xFFFFFFFF, 0, 0x10, 0, 0); SetVBlankCallback(VBlankCB_DuoFight); PlaySE(SE_T_OOAME); } static void sub_81D7228(u8 taskId) { s16 i; u16 *data = gTasks[taskId].data; for (i = 24; i < 92; i++) { if (i <= 47) { gScanlineEffectRegBuffers[0][i] = data[0] >> 8; gScanlineEffectRegBuffers[1][i] = data[0] >> 8; } else if (i <= 63) { gScanlineEffectRegBuffers[0][i] = data[1] >> 8; gScanlineEffectRegBuffers[1][i] = data[1] >> 8; } else if (i <= 75) { gScanlineEffectRegBuffers[0][i] = data[2] >> 8; gScanlineEffectRegBuffers[1][i] = data[2] >> 8; } else if (i <= 83) { gScanlineEffectRegBuffers[0][i] = data[3] >> 8; gScanlineEffectRegBuffers[1][i] = data[3] >> 8; } else if (i <= 87) { gScanlineEffectRegBuffers[0][i] = data[4] >> 8; gScanlineEffectRegBuffers[1][i] = data[4] >> 8; } else { gScanlineEffectRegBuffers[0][i] = data[5] >> 8; gScanlineEffectRegBuffers[1][i] = data[5] >> 8; } } if (sRayScene->animId == RAY_ANIM_DUO_FIGHT_PRE) { data[0] += 448; data[1] += 384; data[2] += 320; data[3] += 256; data[4] += 192; data[5] += 128; } else { data[0] += 768; data[1] += 640; data[2] += 512; data[3] += 384; data[4] += 256; data[5] += 128; } } static void Task_HandleDuoFight(u8 taskId) { s16 *data = gTasks[taskId].data; sub_81D750C(); if (!gPaletteFade.active) { s16 counter = data[0]; if (counter == 32 || counter == 112) { sub_81D7438(); } else if (counter == 216) { sub_81D7480(); } else if (counter == 220) { sub_81D74C8(); } else { switch (counter) { case 412: DuoFightEnd(taskId, 2); return; case 380: SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG2 | BLDCNT_TGT2_BG1 | BLDCNT_EFFECT_BLEND); gTasks[data[1]].func = sub_81D752C; gTasks[data[1]].data[0] = 0; gTasks[data[1]].data[2] = data[2]; gTasks[data[1]].data[3] = data[3]; ScanlineEffect_Stop(); break; } } data[0]++; } } static void sub_81D7438(void) { PlaySE(SE_T_KAMI); sub_80A2C44(0x7FFF, 0, 0x10, 0, -1, 0, 0); sub_80A2C44(0xFFFF0000, 0, 0x10, 0, 0, 0, 1); } static void sub_81D7480(void) { PlaySE(SE_T_KAMI); sub_80A2C44(0x7FFF, 0, 0x10, 0x10, -1, 0, 0); sub_80A2C44(0xFFFF0000, 0, 0x10, 0x10, 0, 0, 1); } static void sub_81D74C8(void) { sub_80A2C44(0x7FFF, 4, 0x10, 0, -1, 0, 0); sub_80A2C44(0xFFFF0000, 4, 0x10, 0, 0, 0, 1); } static void sub_81D750C(void) { ChangeBgX(2, 0x400, 1); ChangeBgY(2, 0x800, 2); } static void sub_81D752C(u8 taskId) { u16 bgY; s16 *data = gTasks[taskId].data; sub_81D7860(&gSprites[data[2]]); sub_81D7D14(&gSprites[data[3]]); bgY = GetBgY(1); if (GetBgY(1) == 0 || bgY > 0x8000) ChangeBgY(1, 0x400, 2); if (data[0] != 16) { data[0]++; SetGpuReg(REG_OFFSET_BLDALPHA, (data[0] << 8) | (16 - data[0])); } } static void DuoFightEnd(u8 taskId, s8 palDelay) { PlaySE(SE_T_OOAME_E); BeginNormalPaletteFade(0xFFFFFFFF, palDelay, 0, 0x10, 0); gTasks[taskId].func = Task_DuoFightEnd; } static void Task_DuoFightEnd(u8 taskId) { s16 *data = gTasks[taskId].data; sub_81D750C(); if (!gPaletteFade.active) { DestroyTask(data[1]); ChangeBgY(1, 0, 0); SetVBlankCallback(NULL); ScanlineEffect_Stop(); ResetSpriteData(); FreeAllSpritePalettes(); data[0] = 0; gTasks[taskId].func = Task_SetNextAnim; } } static u8 sub_81D7664(void) { u8 spriteId; s16 *data; spriteId = CreateSprite(&sUnknown_0862A8D4, 98, 72, 3); gSprites[spriteId].callback = sub_81D7700; data = gSprites[spriteId].data; data[0] = CreateSprite(&sUnknown_0862A8D4, 66, 104, 3); data[1] = CreateSprite(&sUnknown_0862A900, 85, 101, 0); data[2] = CreateSprite(&sUnknown_0862A92C, 119, 114, 1); StartSpriteAnim(&gSprites[data[0]], 1); return spriteId; } static void sub_81D7700(struct Sprite *sprite) { s16 *data = sprite->data; data[5]++; data[5] &= 0xF; if (!(data[5] & 7) && sprite->pos1.x != 72) { sprite->pos1.x--; gSprites[sprite->data[0]].pos1.x--; gSprites[data[1]].pos1.x--; gSprites[data[2]].pos1.x--; } switch (sprite->animCmdIndex) { case 0: gSprites[data[1]].pos2.x = 0; gSprites[data[1]].pos2.y = 0; gSprites[data[2]].pos2.x = 0; gSprites[data[2]].pos2.y = 0; break; case 1: case 3: gSprites[data[1]].pos2.x = -1; gSprites[data[1]].pos2.y = 0; gSprites[data[2]].pos2.x = -1; gSprites[data[2]].pos2.y = 0; break; case 2: gSprites[data[1]].pos2.x = -1; gSprites[data[1]].pos2.y = 1; gSprites[data[2]].pos2.x = -2; gSprites[data[2]].pos2.y = 1; break; } } static void sub_81D7860(struct Sprite *sprite) { s16 *data = sprite->data; if (sprite->pos1.y <= 160) { sprite->pos1.y += 8; gSprites[sprite->data[0]].pos1.y += 8; gSprites[data[1]].pos1.y += 8; gSprites[data[2]].pos1.y += 8; } } static u8 sub_81D78BC(void) { u8 spriteId; s16 *data; spriteId = CreateSprite(&sUnknown_0862A9E4, 126, 96, 1); gSprites[spriteId].callback = sub_81D7A60; data = gSprites[spriteId].data; data[0] = CreateSprite(&sUnknown_0862A9E4, 158, 96, 1) << 8; data[0] |= CreateSprite(&sUnknown_0862A9E4, 126, 112, 1); data[1] = CreateSprite(&sUnknown_0862A9E4, 158, 112, 1) << 8; data[1] |= CreateSprite(&sUnknown_0862A9E4, 126, 128, 1); data[2] = CreateSprite(&sUnknown_0862A9E4, 158, 128, 1) << 8; data[2] |= CreateSprite(&sUnknown_0862A9E4, 94, 128, 2); data[3] = CreateSprite(&sUnknown_0862A9E4, 126, 128, 2) << 8; data[3] |= CreateSprite(&sUnknown_0862A9E4, 174, 128, 0); data[4] = CreateSprite(&sUnknown_0862AA1C, 198, 132, 0) << 8; data[4] |= CreateSprite(&sUnknown_0862AA3C, 190, 120, 1); StartSpriteAnim(&gSprites[data[0] >> 8], 1); StartSpriteAnim(&gSprites[data[0] & 0xFF], 2); StartSpriteAnim(&gSprites[data[1] >> 8], 3); StartSpriteAnim(&gSprites[data[1] & 0xFF], 4); StartSpriteAnim(&gSprites[data[2] >> 8], 5); StartSpriteAnim(&gSprites[data[2] & 0xFF], 6); StartSpriteAnim(&gSprites[data[3] >> 8], 7); StartSpriteAnim(&gSprites[data[3] & 0xFF], 8); return spriteId; } static void sub_81D7A60(struct Sprite *sprite) { s16 *data = sprite->data; data[5]++; data[5] &= 0xF; if (!(data[5] & 7) && sprite->pos1.x != 152) { sprite->pos1.x++; gSprites[sprite->data[0] >> 8].pos1.x++; gSprites[sprite->data[0] & 0xFF].pos1.x++; gSprites[data[1] >> 8].pos1.x++; gSprites[data[1] & 0xFF].pos1.x++; gSprites[data[2] >> 8].pos1.x++; gSprites[data[2] & 0xFF].pos1.x++; gSprites[data[3] >> 8].pos1.x++; gSprites[data[3] & 0xFF].pos1.x++; gSprites[data[4] >> 8].pos1.x++; gSprites[data[4] & 0xFF].pos1.x++; } switch (gSprites[data[2] & 0xFF].animCmdIndex) { case 0: sprite->pos2.y = 0; gSprites[data[0] >> 8].pos2.y = 0; gSprites[data[0] & 0xFF].pos2.y = 0; gSprites[data[1] >> 8].pos2.y = 0; gSprites[data[1] & 0xFF].pos2.y = 0; gSprites[data[2] >> 8].pos2.y = 0; gSprites[data[2] & 0xFF].pos2.y = 0; gSprites[data[3] >> 8].pos2.y = 0; gSprites[data[3] & 0xFF].pos2.y = 0; gSprites[data[4] >> 8].pos2.y = 0; gSprites[data[4] & 0xFF].pos2.y = 0; break; case 1: case 3: sprite->pos2.y = 1; gSprites[data[0] >> 8].pos2.y = 1; gSprites[data[0] & 0xFF].pos2.y = 1; gSprites[data[1] >> 8].pos2.y = 1; gSprites[data[1] & 0xFF].pos2.y = 1; gSprites[data[2] >> 8].pos2.y = 1; gSprites[data[2] & 0xFF].pos2.y = 1; gSprites[data[3] >> 8].pos2.y = 1; gSprites[data[3] & 0xFF].pos2.y = 1; gSprites[data[4] >> 8].pos2.y = 1; gSprites[data[4] & 0xFF].pos2.y = 1; break; case 2: sprite->pos2.y = 2; gSprites[data[0] >> 8].pos2.y = 2; gSprites[data[0] & 0xFF].pos2.y = 2; gSprites[data[1] >> 8].pos2.y = 2; gSprites[data[1] & 0xFF].pos2.y = 2; gSprites[data[2] >> 8].pos2.y = 2; gSprites[data[4] & 0xFF].pos2.y = 2; break; } } static void sub_81D7D14(struct Sprite *sprite) { s16 *data = sprite->data; if (sprite->pos1.y <= 160) { sprite->pos1.y += 8; gSprites[sprite->data[0] >> 8].pos1.y += 8; gSprites[sprite->data[0] & 0xFF].pos1.y += 8; gSprites[data[1] >> 8].pos1.y += 8; gSprites[data[1] & 0xFF].pos1.y += 8; gSprites[data[2] >> 8].pos1.y += 8; gSprites[data[2] & 0xFF].pos1.y += 8; gSprites[data[3] >> 8].pos1.y += 8; gSprites[data[3] & 0xFF].pos1.y += 8; gSprites[data[4] >> 8].pos1.y += 8; gSprites[data[4] & 0xFF].pos1.y += 8; } } static void sub_81D7E10(void) { ResetVramOamAndBgCntRegs(); ResetBgsAndClearDma3BusyFlags(0); InitBgsFromTemplates(1, sUnknown_0862AA54, ARRAY_COUNT(sUnknown_0862AA54)); SetBgTilemapBuffer(0, sRayScene->tilemapBuffers[0]); SetBgTilemapBuffer(1, sRayScene->tilemapBuffers[1]); SetBgTilemapBuffer(2, sRayScene->tilemapBuffers[2]); ResetAllBgsCoordinates(); schedule_bg_copy_tilemap_to_vram(0); schedule_bg_copy_tilemap_to_vram(1); schedule_bg_copy_tilemap_to_vram(2); SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_OBJ_ON | DISPCNT_OBJ_1D_MAP); ShowBg(0); ShowBg(1); ShowBg(2); SetGpuReg(REG_OFFSET_BLDCNT, 0); } static void sub_81D7E9C(void) { reset_temp_tile_data_buffers(); decompress_and_copy_tile_data_to_vram(0, gRaySceneClouds_Gfx, 0, 0, 0); decompress_and_copy_tile_data_to_vram(1, gRaySceneOvercast_Gfx, 0, 0, 0); decompress_and_copy_tile_data_to_vram(2, gRaySceneRayquaza_Gfx, 0, 0, 0); while (free_temp_tile_data_buffers_if_possible()); LZDecompressWram(gRaySceneClouds2_Tilemap, sRayScene->tilemapBuffers[0]); LZDecompressWram(gRaySceneOvercast_Tilemap, sRayScene->tilemapBuffers[1]); LZDecompressWram(gRaySceneRayquaza_Tilemap, sRayScene->tilemapBuffers[2]); LoadCompressedPalette(gRaySceneRayquaza_Pal, 0, 0x40); LoadCompressedObjectPic(&sUnknown_0862AA90); LoadCompressedObjectPalette(&sUnknown_0862AA98); } static void Task_RayTakesFlightAnim(u8 taskId) { s16 *data = gTasks[taskId].data; PlayNewMapMusic(MUS_REKKUU_KOURIN); sub_81D7E10(); sub_81D7E9C(); SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_OBJ | BLDCNT_TGT2_BG1 | BLDCNT_EFFECT_BLEND); SetGpuReg(REG_OFFSET_BLDALPHA, 0x808); BlendPalettes(-1, 0x10, 0); SetVBlankCallback(VBlankCB_RayquazaScene); CreateTask(sub_81D81A4, 0); data[0] = 0; data[1] = 0; gTasks[taskId].func = Task_HandleRayTakesFlight; } static void Task_HandleRayTakesFlight(u8 taskId) { s16 *data = gTasks[taskId].data; switch (data[0]) { case 0: if (data[1] == 8) { BeginNormalPaletteFade(0xFFFFFFFF, 0, 0x10, 0, 0); data[2] = 0; data[3] = 30; data[4] = 0; data[5] = 7; data[1] = 0; data[0]++; } else { data[1]++; } break; case 1: data[2] += data[3]; data[4] += data[5]; if (data[3] > 3) data[3] -= 3; if (data[5] != 0) data[5]--; if (data[2] > 255) { data[2] = 256; data[3] = 0; data[6] = 12; data[7] = -1; data[1] = 0; data[0]++; } SetBgAffine(2, 0x7800, 0x1800, 0x78, data[4] + 32, data[2], data[2], 0); break; case 2: data[1]++; SetBgAffine(2, 0x7800, 0x1800, 0x78, data[4] + 32 + (data[6] >> 2), data[2], data[2], 0); data[6] += data[7]; if (data[6] == 12 || data[6] == -12) { data[7] *= -1; if (data[1] > 295) { data[0]++; BeginNormalPaletteFade(0xFFFFFFFF, 6, 0, 0x10, 0); } } break; case 3: data[2] += 16; SetBgAffine(2, 0x7800, 0x1800, 0x78, data[4] + 32, data[2], data[2], 0); Task_RayTakesFlightEnd(taskId); break; } } static void Task_RayTakesFlightEnd(u8 taskId) { if (!gPaletteFade.active) { SetVBlankCallback(NULL); ResetSpriteData(); FreeAllSpritePalettes(); gTasks[taskId].func = Task_SetNextAnim; } } static void sub_81D81A4(u8 taskId) { s16 *data = gTasks[taskId].data; if ((data[1] & 3) == 0) { u8 spriteId = CreateSprite(&sUnknown_0862AAA0, (sUnknown_0862AAB8[data[0]][0] * 4) + 120, (sUnknown_0862AAB8[data[0]][1] * 4) + 80, 0); gSprites[spriteId].data[0] = (s8)(data[0]); gSprites[spriteId].oam.objMode = 1; gSprites[spriteId].oam.affineMode = 3; gSprites[spriteId].oam.priority = 2; InitSpriteAffineAnim(&gSprites[spriteId]); if (data[0] == 9) { DestroyTask(taskId); return; } else { data[0]++; } } data[1]++; } static void sub_81D8260(struct Sprite *sprite) { if (sprite->data[1] == 0) { sprite->pos2.x = 0; sprite->pos2.y = 0; } else { sprite->pos2.x += sUnknown_0862AAB8[sprite->data[0]][0]; sprite->pos2.y += sUnknown_0862AAB8[sprite->data[0]][1]; } sprite->data[1]++; sprite->data[1] &= 0xF; } static void sub_81D82B0(void) { ResetVramOamAndBgCntRegs(); ResetBgsAndClearDma3BusyFlags(0); InitBgsFromTemplates(0, sUnknown_0862AACC, ARRAY_COUNT(sUnknown_0862AACC)); SetBgTilemapBuffer(0, sRayScene->tilemapBuffers[0]); SetBgTilemapBuffer(1, sRayScene->tilemapBuffers[1]); SetBgTilemapBuffer(2, sRayScene->tilemapBuffers[2]); SetBgTilemapBuffer(3, sRayScene->tilemapBuffers[3]); ResetAllBgsCoordinates(); schedule_bg_copy_tilemap_to_vram(0); schedule_bg_copy_tilemap_to_vram(1); schedule_bg_copy_tilemap_to_vram(2); schedule_bg_copy_tilemap_to_vram(3); SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_OBJ_ON | DISPCNT_OBJ_1D_MAP); ShowBg(0); ShowBg(1); ShowBg(2); ShowBg(3); SetGpuReg(REG_OFFSET_BLDCNT, 0); } static void sub_81D8358(void) { reset_temp_tile_data_buffers(); decompress_and_copy_tile_data_to_vram(0, gRaySceneRayquazaLight_Gfx, 0, 0, 0); decompress_and_copy_tile_data_to_vram(1, gRaySceneOvercast2_Gfx, 0, 0, 0); while (free_temp_tile_data_buffers_if_possible()); LZDecompressWram(gRaySceneRayquazaLight_Tilemap, sRayScene->tilemapBuffers[0]); LZDecompressWram(gRaySceneOvercast2_Tilemap, sRayScene->tilemapBuffers[3]); CpuFastFill16(0, sRayScene->tilemapBuffers[2], 0x800); CpuFastCopy(sRayScene->tilemapBuffers[3], sRayScene->tilemapBuffers[1], 0x800); CpuFastFill16(0, &sRayScene->tilemapBuffers[1][0x100], 0x340); LoadCompressedPalette(gRaySceneOvercast2_Pal, 0, 0x40); gPlttBufferUnfaded[0] = RGB_WHITE; gPlttBufferFaded[0] = RGB_WHITE; LoadCompressedObjectPic(&sUnknown_0862AAFC); LoadCompressedObjectPic(&sUnknown_0862AB04); LoadCompressedObjectPalette(&sUnknown_0862AB0C); } static void sub_81D844C(void) { u16 VCOUNT = GetGpuReg(REG_OFFSET_VCOUNT); if (VCOUNT >= 24 && VCOUNT <= 135 && VCOUNT - 24 <= sRayScene->field_2008) REG_BLDALPHA = 0xD08; else REG_BLDALPHA = 0x1000; if (VCOUNT == 0) { if (sRayScene->field_2008 <= 0x1FFF) { if (sRayScene->field_2008 <= 39) sRayScene->field_2008 += 4; else if (sRayScene->field_2008 <= 79) sRayScene->field_2008 += 2; else sRayScene->field_2008 += 1; } sRayScene->field_200A++; } } static void Task_RayDescendsAnim(u8 taskId) { s16 *data = gTasks[taskId].data; sub_81D82B0(); sub_81D8358(); SetGpuRegBits(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG0 | BLDCNT_TGT2_BG1 | BLDCNT_TGT2_BG2 | BLDCNT_TGT2_BG3 | BLDCNT_TGT2_OBJ | BLDCNT_EFFECT_BLEND); SetGpuReg(REG_OFFSET_BLDALPHA, 0x1000); BlendPalettes(-1, 0x10, 0); SetVBlankCallback(VBlankCB_RayquazaScene); sRayScene->field_2008 = 0; sRayScene->field_200A = 0; data[0] = 0; data[1] = 0; data[2] = 0; data[3] = 0; data[4] = 0x1000; gTasks[taskId].func = Task_HandleRayDescends; } static void Task_HandleRayDescends(u8 taskId) { s16 *data = gTasks[taskId].data; switch (data[0]) { case 0: if (data[1] == 8) { BeginNormalPaletteFade(0xFFFFFFFF, 0, 0x10, 0, 0); data[1] = 0; data[0]++; } else { data[1]++; } break; case 1: if (!gPaletteFade.active) { if (data[1] == 10) { data[1] = 0; data[0]++; SetHBlankCallback(sub_81D844C); EnableInterrupts(INTR_FLAG_HBLANK | INTR_FLAG_VBLANK); } else { data[1]++; } } break; case 2: if (data[1] == 80) { data[1] = 0; data[0]++; sub_81D86CC(); } else { data[1]++; } break; case 3: if (++data[1] == 368) { data[1] = 0; data[0]++; } break; case 4: BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 0x10, 0); gTasks[taskId].func = Task_RayDescendsEnd; break; } } static void Task_RayDescendsEnd(u8 taskId) { if (!gPaletteFade.active) { SetVBlankCallback(NULL); SetHBlankCallback(NULL); ResetSpriteData(); FreeAllSpritePalettes(); gTasks[taskId].func = Task_SetNextAnim; } } static u8 sub_81D86CC(void) { u8 spriteId = CreateSprite(&sUnknown_0862AB14, 160, 0, 0); s16 *data = gSprites[spriteId].data; data[0] = CreateSprite(&sUnknown_0862AB2C, 184, -48, 0); gSprites[spriteId].callback = sub_81D874C; gSprites[spriteId].oam.priority = 3; gSprites[data[0]].oam.priority = 3; return spriteId; } static void sub_81D874C(struct Sprite *sprite) { s16 *data = sprite->data; s16 counter = data[2]; if (counter == 0) { data[3] = 12; data[4] = 8; } else if (counter == 256) { data[3] = 9; data[4] = 7; } else if (counter == 268) { data[3] = 8; data[4] = 6; } else if (counter == 280) { data[3] = 7; data[4] = 5; } else if (counter == 292) { data[3] = 6; data[4] = 4; } else if (counter == 304) { data[3] = 5; data[4] = 3; } else if (counter == 320) { data[3] = 4; data[4] = 2; } if (data[2] % data[3] == 0) { sprite->pos2.x--; gSprites[data[0]].pos2.x--; } if (data[2] % data[4] == 0) { sprite->pos2.y++; gSprites[data[0]].pos2.y++; } data[2]++; } static void sub_81D8828(void) { ResetVramOamAndBgCntRegs(); ResetBgsAndClearDma3BusyFlags(0); InitBgsFromTemplates(0, sUnknown_0862AB44, ARRAY_COUNT(sUnknown_0862AB44)); SetBgTilemapBuffer(0, sRayScene->tilemapBuffers[0]); SetBgTilemapBuffer(1, sRayScene->tilemapBuffers[1]); SetBgTilemapBuffer(2, sRayScene->tilemapBuffers[2]); SetBgTilemapBuffer(3, sRayScene->tilemapBuffers[3]); ResetAllBgsCoordinates(); schedule_bg_copy_tilemap_to_vram(0); schedule_bg_copy_tilemap_to_vram(1); schedule_bg_copy_tilemap_to_vram(2); schedule_bg_copy_tilemap_to_vram(3); SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_OBJ_ON | DISPCNT_OBJ_1D_MAP | DISPCNT_WIN0_ON); ShowBg(0); ShowBg(1); ShowBg(2); ShowBg(3); SetGpuReg(REG_OFFSET_BLDCNT, 0); } static void sub_81D88D0(void) { reset_temp_tile_data_buffers(); decompress_and_copy_tile_data_to_vram(1, gRaySceneRayquazaChase_Gfx, 0, 0, 0); decompress_and_copy_tile_data_to_vram(2, gRaySceneChaseStreaks_Gfx, 0, 0, 0); decompress_and_copy_tile_data_to_vram(3, gRaySceneChaseBg_Gfx, 0, 0, 0); while (free_temp_tile_data_buffers_if_possible()); LZDecompressWram(gRayChaseRayquazaChase2_Tilemap, sRayScene->tilemapBuffers[0]); LZDecompressWram(gRayChaseRayquazaChase_Tilemap, sRayScene->tilemapBuffers[1]); LZDecompressWram(gRaySceneChaseStreaks_Tilemap, sRayScene->tilemapBuffers[2]); LZDecompressWram(gRaySceneChaseBg_Tilemap, sRayScene->tilemapBuffers[3]); LoadCompressedPalette(gRaySceneChase_Pal, 0, 0x80); } static void Task_RayChargesAnim(u8 taskId) { s16 *data = gTasks[taskId].data; sub_81D8828(); sub_81D88D0(); sub_81D68C8(); BlendPalettes(-1, 0x10, 0); SetVBlankCallback(VBlankCB_RayquazaScene); data[0] = 0; data[1] = 0; data[2] = CreateTask(sub_81D8AD8, 0); gTasks[taskId].func = Task_HandleRayCharges; } static void Task_HandleRayCharges(u8 taskId) { s16 *data = gTasks[taskId].data; sub_81D8BB4(); if ((data[3] & 7) == 0 && data[0] <= 1 && data[1] <= 89) PlaySE(SE_OP_BASYU); data[3]++; switch (data[0]) { case 0: if (data[1] == 8) { BeginNormalPaletteFade(0xFFFFFFFF, 0, 0x10, 0, 0); data[1] = 0; data[0]++; } else { data[1]++; } break; case 1: if (data[1] == 127) { data[1] = 0; data[0]++; gTasks[data[2]].func = sub_81D8B2C; } else { data[1]++; } break; case 2: if (data[1] == 12) { data[1] = 0; data[0]++; } else { data[1]++; } break; case 3: BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 0x10, 0); gTasks[taskId].func = Task_RayChargesEnd; break; } } static void sub_81D8AD8(u8 taskId) { s16 *data = gTasks[taskId].data; if ((data[15] & 3) == 0) { ChangeBgX(1, (Random() % 8 - 4) << 8, 0); ChangeBgY(1, (Random() % 8 - 4) << 8, 0); } data[15]++; } static void sub_81D8B2C(u8 taskId) { s16 *data = gTasks[taskId].data; if (data[0] == 0) { ChangeBgX(1, 0, 0); ChangeBgY(1, 0, 0); data[0]++; data[1] = 10; data[2] = -1; } else if (data[0] == 1) { ChangeBgX(1, data[1] << 8, 2); ChangeBgY(1, data[1] << 8, 1); data[1] += data[2]; if (data[1] == -10) data[2] *= -1; } } static void sub_81D8BB4(void) { ChangeBgX(2, 0x400, 2); ChangeBgY(2, 0x400, 1); ChangeBgX(0, 0x800, 2); ChangeBgY(0, 0x800, 1); } static void Task_RayChargesEnd(u8 taskId) { s16 *data = gTasks[taskId].data; sub_81D8BB4(); if (!gPaletteFade.active) { SetVBlankCallback(NULL); sub_81D6904(); DestroyTask(data[2]); gTasks[taskId].func = Task_SetNextAnim; } } static void sub_81D8C38(void) { ResetVramOamAndBgCntRegs(); ResetBgsAndClearDma3BusyFlags(0); InitBgsFromTemplates(1, sUnknown_0862AD08, ARRAY_COUNT(sUnknown_0862AD08)); SetBgTilemapBuffer(0, sRayScene->tilemapBuffers[0]); SetBgTilemapBuffer(1, sRayScene->tilemapBuffers[1]); SetBgTilemapBuffer(2, sRayScene->tilemapBuffers[2]); ResetAllBgsCoordinates(); schedule_bg_copy_tilemap_to_vram(0); schedule_bg_copy_tilemap_to_vram(1); schedule_bg_copy_tilemap_to_vram(2); SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_OBJ_ON | DISPCNT_OBJ_1D_MAP | DISPCNT_WIN0_ON); ShowBg(0); ShowBg(1); ShowBg(2); SetGpuReg(REG_OFFSET_BLDCNT, 0); } static void sub_81D8CC4(void) { reset_temp_tile_data_buffers(); decompress_and_copy_tile_data_to_vram(2, gRaySceneHushRing_Gfx, 0, 0, 0); decompress_and_copy_tile_data_to_vram(0, gRaySceneHushBg_Gfx, 0, 0, 0); while (free_temp_tile_data_buffers_if_possible()); LZDecompressWram(gRaySceneHushRing_Tilemap, sRayScene->tilemapBuffers[1]); LZDecompressWram(gRaySceneHushBg_Tilemap, sRayScene->tilemapBuffers[0]); LZDecompressWram(gRaySceneHushRing_Map, sRayScene->tilemapBuffers[2]); LoadCompressedPalette(gRaySceneHushBg_Pal, 0, 0x60); LoadCompressedObjectPic(&sUnknown_0862AC28); LoadCompressedObjectPic(&sUnknown_0862AC30); LoadCompressedObjectPic(&sUnknown_0862AC38); LoadCompressedObjectPic(&sUnknown_0862AC40); LoadCompressedObjectPic(&sUnknown_0862AC48); LoadCompressedObjectPic(&sUnknown_0862AC50); LoadCompressedObjectPalette(&sUnknown_0862AC58); LoadCompressedObjectPalette(&sUnknown_0862AC60); LoadCompressedObjectPalette(&sUnknown_0862AC68); LoadCompressedObjectPalette(&sUnknown_0862AC70); } static void Task_RayChasesAwayAnim(u8 taskId) { s16 *data = gTasks[taskId].data; sub_81D8C38(); sub_81D8CC4(); sub_81D68C8(); ClearGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_BG2_ON); SetGpuReg(REG_OFFSET_BLDCNT, BLDCNT_TGT1_BG0 | BLDCNT_TGT2_BG1 | BLDCNT_EFFECT_BLEND); SetGpuReg(REG_OFFSET_BLDALPHA, 0xE09); BlendPalettes(-1, 0x10, 0); SetVBlankCallback(VBlankCB_RayquazaScene); data[0] = 0; data[1] = 0; gTasks[taskId].func = Task_HandleRayChasesAway; data[2] = CreateTask(sub_81D8FB0, 0); gTasks[data[2]].data[0] = 0; gTasks[data[2]].data[1] = 0; gTasks[data[2]].data[2] = 0; gTasks[data[2]].data[3] = 1; gTasks[data[2]].data[4] = 1; } static void Task_HandleRayChasesAway(u8 taskId) { s16 *data = gTasks[taskId].data; switch (data[0]) { case 0: if (data[1] == 8) { sub_81D90A8(taskId); BeginNormalPaletteFade(0xFFFFFFFF, 0, 0x10, 0, 0); data[1] = 0; data[0]++; } else { data[1]++; } break; case 1: if (gSprites[data[5]].callback == sub_81D97E0) { if (data[1] == 64) { sub_81D94D4(taskId); sub_81D93D8(taskId); data[1] = 0; data[0]++; } else { data[1]++; } } break; case 2: if (data[1] == 448) { data[1] = 0; data[0]++; } else { data[1]++; if (data[1] % 144 == 0) { sub_80A2C44(0xFFFE, 0, 0x10, 0, -1, 0, 0); sub_80A2C44(0xFFFF0000, 0, 0x10, 0, 0, 0, 1); } } break; case 3: BeginNormalPaletteFade(0xFFFFFFFF, 4, 0, 0x10, 0); gTasks[taskId].func = Task_RayChasesAwayEnd; break; } } static void sub_81D8FB0(u8 taskId) { s16 *data = gTasks[taskId].data; if ((data[0] & 0xF) == 0) { SetGpuReg(REG_OFFSET_BLDALPHA, ((data[1] + 14) << 8 & 0x1F00) | ((data[2] + 9) & 0xF)); data[1] -= data[3]; data[2] += data[4]; if (data[1] == -3 || data[1] == 0) data[3] *= -1; if (data[2] == 3 || data[2] == 0) data[4] *= -1; } data[0]++; } static void Task_RayChasesAwayEnd(u8 taskId) { s16 *data = gTasks[taskId].data; if (!gPaletteFade.active) { StopMapMusic(); if (data[1] == 0) { SetVBlankCallback(NULL); sub_81D6904(); ResetSpriteData(); FreeAllSpritePalettes(); DestroyTask(data[2]); } if (data[1] == 32) { data[1] = 0; gTasks[taskId].func = Task_SetNextAnim; } else { data[1]++; } } } static void sub_81D90A8(u8 taskId) { s16 *taskData, *spriteData; taskData = gTasks[taskId].data; taskData[3] = CreateSprite(&sUnknown_0862AC78, 64, 120, 0); spriteData = gSprites[taskData[3]].data; spriteData[0] = CreateSprite(&sUnknown_0862AC90, 16, 130, 0); gSprites[taskData[3]].oam.priority = 1; gSprites[spriteData[0]].oam.priority = 1; taskData[4] = CreateSprite(&sUnknown_0862ACA8, 160, 128, 1); spriteData = gSprites[taskData[4]].data; spriteData[0] = CreateSprite(&sUnknown_0862ACA8, 192, 128, 1); spriteData[1] = CreateSprite(&sUnknown_0862ACA8, 224, 128, 1); gSprites[taskData[4]].oam.priority = 1; gSprites[spriteData[0]].oam.priority = 1; gSprites[spriteData[1]].oam.priority = 1; StartSpriteAnim(&gSprites[spriteData[0]], 1); StartSpriteAnim(&gSprites[spriteData[1]], 2); taskData[5] = CreateSprite(&sUnknown_0862ACC0, 120, -65, 0); spriteData = gSprites[taskData[5]].data; spriteData[0] = CreateSprite(&sUnknown_0862ACD8, 120, -113, 0); gSprites[taskData[5]].oam.priority = 1; gSprites[spriteData[0]].oam.priority = 1; } static void sub_81D9274(u8 taskId) { s16 *taskData = gTasks[taskId].data; gSprites[taskData[3]].callback = sub_81D9338; gSprites[taskData[3]].data[4] = 0; gSprites[taskData[3]].data[5] = 0; gSprites[taskData[3]].data[6] = 4; gSprites[taskData[3]].data[7] = 0; gSprites[taskData[4]].callback = sub_81D9338; gSprites[taskData[4]].data[4] = 0; gSprites[taskData[4]].data[5] = 0; gSprites[taskData[4]].data[6] = 4; gSprites[taskData[4]].data[7] = 1; } static void sub_81D9338(struct Sprite *sprite) { if ((sprite->data[4] & 7) == 0) { if (sprite->data[7] == 0) { sprite->pos1.x -= sprite->data[6]; gSprites[sprite->data[0]].pos1.x -= sprite->data[6]; } else { sprite->pos1.x += sprite->data[6]; gSprites[sprite->data[0]].pos1.x += sprite->data[6]; gSprites[sprite->data[1]].pos1.x += sprite->data[6]; } sprite->data[5]++; sprite->data[6] -= sprite->data[5]; if (sprite->data[5] == 3) { sprite->data[4] = 0; sprite->data[5] = 0; sprite->data[6] = 0; sprite->callback = SpriteCallbackDummy; return; } } sprite->data[4]++; } static void sub_81D93D8(u8 taskId) { s16 *taskData = gTasks[taskId].data; gSprites[taskData[3]].callback = sub_81D9420; StartSpriteAnim(&gSprites[taskData[3]], 1); } static void sub_81D9420(struct Sprite *sprite) { switch (sprite->animCmdIndex) { case 0: case 2: if (sprite->animDelayCounter % 12 == 0) { sprite->pos1.x -= 2; gSprites[sprite->data[0]].pos1.x -=2; } gSprites[sprite->data[0]].pos2.y = 0; break; case 1: case 3: gSprites[sprite->data[0]].pos2.y = -2; if ((sprite->animDelayCounter & 15) == 0) { sprite->pos1.y++; gSprites[sprite->data[0]].pos1.y++; } break; } } static void sub_81D94D4(u8 taskId) { s16 *taskData, *spriteData; taskData = gTasks[taskId].data; spriteData = gSprites[taskData[4]].data; gSprites[taskData[4]].callback = sub_81D9528; gSprites[spriteData[0]].callback = sub_81D9528; gSprites[spriteData[1]].callback = sub_81D9528; } static void sub_81D9528(struct Sprite *sprite) { if ((sprite->data[4] & 3) == 0) { if (sprite->pos2.x == 1) sprite->pos2.x = -1; else sprite->pos2.x = 1; } if (sprite->data[5] == 128) { sprite->data[7] = CreateSprite(&sUnknown_0862ACF0, 152, 132, 0); gSprites[sprite->data[7]].oam.priority = 1; sprite->data[7] = CreateSprite(&sUnknown_0862ACF0, 224, 132, 0); gSprites[sprite->data[7]].oam.priority = 1; gSprites[sprite->data[7]].hFlip = 1; sprite->data[5]++; } if (sprite->data[5] > 127) { if (sprite->pos2.y != 32) { sprite->data[6]++; sprite->pos2.y = sprite->data[6] >> 4; } } else { sprite->data[5]++; } if (sprite->data[4] % 64 == 0) PlaySE(SE_W250); sprite->data[4]++; } static void sub_81D961C(struct Sprite *sprite) { s16 counter = sprite->data[7]; if (counter <= 64) { sprite->pos2.y += 2; gSprites[sprite->data[0]].pos2.y += 2; if (sprite->data[7] == 64) { sub_81D9868(sprite, 1, 0, -48); sprite->data[4] = 5; sprite->data[5] = -1; gSprites[sprite->data[0]].data[4] = 3; gSprites[sprite->data[0]].data[5] = 5; } } else if (counter <= 111) { sub_81D97E0(sprite); if (sprite->data[4] == 0) PlaySE(SE_BT_START); if (sprite->data[4] == -3) sub_81D9868(sprite, 2, 48, 16); } else if (counter == 112) { gSprites[sprite->data[0]].data[4] = 7; gSprites[sprite->data[0]].data[5] = 3; sub_81D97E0(sprite); } else if (counter <= 327) { sub_81D97E0(sprite); } else if (counter == 328) { sub_81D97E0(sprite); sub_81D9868(sprite, 3, 48, 16); sprite->pos2.x = 1; gSprites[sprite->data[0]].pos2.x = 1; PlayCry1(SPECIES_RAYQUAZA, 0); CreateTask(sub_81D98B4, 0); } else { switch (counter) { case 376: sprite->pos2.x = 0; gSprites[sprite->data[0]].pos2.x = 0; sub_81D97E0(sprite); sub_81D9868(sprite, 2, 48, 16); sprite->callback = sub_81D97E0; return; case 352: sub_81D9274(FindTaskIdByFunc(Task_HandleRayChasesAway)); break; } } if (sprite->data[7] > 328 && (sprite->data[7] & 1) == 0) { sprite->pos2.x *= -1; gSprites[sprite->data[0]].pos2.x = sprite->pos2.x; } sprite->data[7]++; } static void sub_81D97E0(struct Sprite *sprite) { struct Sprite *sprite2 = &gSprites[sprite->data[0]]; if (!(sprite->data[6] & sprite2->data[4])) { sprite->pos2.y += sprite->data[4]; gSprites[sprite->data[0]].pos2.y += sprite->data[4]; sprite->data[4] += sprite->data[5]; if (sprite->data[4] >= sprite2->data[5] || sprite->data[4] <= -sprite2->data[5]) { if (sprite->data[4] > sprite2->data[5]) sprite->data[4] = sprite2->data[5]; else if (sprite->data[4] < -sprite2->data[5]) sprite->data[4] = -sprite2->data[5]; sprite->data[5] *= -1; } } sprite->data[6]++; } static void sub_81D9868(struct Sprite *sprite, u8 animNum, s16 x, s16 y) { struct Sprite *sprite2 = &gSprites[sprite->data[0]]; sprite2->pos1.x = sprite->pos1.x + x; sprite2->pos1.y = sprite->pos1.y + y; sprite2->pos2.x = sprite->pos2.x; sprite2->pos2.y = sprite->pos2.y; StartSpriteAnim(sprite, animNum); StartSpriteAnim(sprite2, animNum); } static void sub_81D98B4(u8 taskId) { s16 *data = gTasks[taskId].data; switch (data[0]) { case 0: SetBgAffine(2, 0x4000, 0x4000, 0x78, 0x40, 0x100, 0x100, 0); SetGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_BG2_ON); data[4] = 16; data[0]++; break; case 1: if (data[5] == 8) PlaySE(SE_JIDO_DOA); if (data[2] == 2) { data[0]++; } else { data[1] += data[4]; data[5]++; if (data[3] % 3 == 0 && data[4] != 4) data[4] -= 2; data[3]++; SetBgAffine(2, 0x4000, 0x4000, 0x78, 0x40, 0x100 - data[1], 0x100 - data[1], 0); if (data[1] > 255) { data[1] = 0; data[3] = 0; data[5] = 0; data[4] = 16; data[2]++; } } break; case 2: ClearGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_BG2_ON); DestroyTask(taskId); break; } }