decompile title screen

This commit is contained in:
DizzyEggg 2018-02-04 16:11:00 +01:00
parent eb6aed50e5
commit 0c60ffe22a
16 changed files with 836 additions and 1496 deletions

View File

@ -59,7 +59,7 @@ sub_816CC54: @ 816CC54
lsls r0, 24
cmp r0, 0
bne _0816CC66
ldr r0, =c2_title_screen_1
ldr r0, =CB2_InitTitleScreen
bl SetMainCallback2
_0816CC66:
pop {r0}
@ -337,13 +337,13 @@ _0816CEFA:
.pool
thumb_func_end c2_copyright_1
thumb_func_start c2_show_copyright_and_intro_again_2
c2_show_copyright_and_intro_again_2: @ 816CF0C
thumb_func_start CB2_InitCopyrightScreenAfterTitleScreen
CB2_InitCopyrightScreenAfterTitleScreen: @ 816CF0C
push {lr}
bl do_copyright_screen
pop {r0}
bx r0
thumb_func_end c2_show_copyright_and_intro_again_2
thumb_func_end CB2_InitCopyrightScreenAfterTitleScreen
thumb_func_start task_intro_1
@ void task_intro_1(int task_id)

View File

@ -28867,7 +28867,7 @@ sub_80186A4: @ 80186A4
movs r0, 0x3
bl GetBgTilemapBuffer
bl Free
ldr r0, =c2_title_screen_1
ldr r0, =CB2_InitTitleScreen
bl SetMainCallback2
pop {r0}
bx r0

View File

@ -1608,7 +1608,7 @@ _08030578:
ldr r0, =gUnknown_02022D06
strh r4, [r0]
bl FreeAllWindowBuffers
ldr r0, =c2_title_screen_1
ldr r0, =CB2_InitTitleScreen
bl SetMainCallback2
adds r0, r5, 0
bl DestroyTask

View File

@ -830,8 +830,8 @@ sub_809EF00: @ 809EF00
.pool
thumb_func_end sub_809EF00
thumb_func_start sub_809EF88
sub_809EF88: @ 809EF88
thumb_func_start CB2_InitResetRtcScreen
CB2_InitResetRtcScreen: @ 809EF88
push {r4-r7,lr}
sub sp, 0x4
movs r0, 0
@ -905,7 +905,7 @@ _0809EFCA:
pop {r0}
bx r0
.pool
thumb_func_end sub_809EF88
thumb_func_end CB2_InitResetRtcScreen
thumb_func_start sub_809F048
sub_809F048: @ 809F048

File diff suppressed because it is too large Load Diff

View File

@ -1,163 +0,0 @@
.include "asm/macros.inc"
.include "constants/constants.inc"
.section .rodata
.align 2, 0
.incbin "graphics/title_screen/unk_853EF78.gbapal"
.align 2
gTitleScreenRayquazaGfx:: @ 853F058
.incbin "graphics/title_screen/rayquaza.4bpp.lz"
.align 2
gTitleScreenRayquazaTilemap:: @ 853F83C
.incbin "graphics/title_screen/rayquaza.bin.lz"
.align 2
gTitleScreenLogoShineGfx:: @ 853FB3C
.incbin "graphics/title_screen/logo_shine.4bpp.lz"
.align 2
gTitleScreenCloudsGfx:: @ 853FC8C
.incbin "graphics/title_screen/clouds.4bpp.lz"
.align 2
gUnknown_0853FF70:: @ 853FF70
.2byte 0x0010, 0x0110, 0x0210, 0x0310, 0x0410, 0x0510, 0x0610, 0x0710
.2byte 0x0810, 0x0910, 0x0a10, 0x0b10, 0x0c10, 0x0d10, 0x0e10, 0x0f10
.2byte 0x100f, 0x100e, 0x100d, 0x100c, 0x100b, 0x100a, 0x1009, 0x1008
.2byte 0x1007, 0x1006, 0x1005, 0x1004, 0x1003, 0x1002, 0x1001, 0x1000
.2byte 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000
.2byte 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000
.2byte 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000
.2byte 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000
.align 2
gUnknown_0853FFF0:: @ 853FFF0
.byte 0xa0, 0x60, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00
.align 2
gUnknown_0853FFF8:: @ 853FFF8
.byte 0xa0, 0x60, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00
.align 2
gUnknown_08540000:: @ 8540000
.2byte 0x0000, 0x001e, 0xffff, 0x0000
.align 2
gUnknown_08540008:: @ 8540008
.2byte 0x0040, 0x001e, 0xffff, 0x0000
.align 2
gUnknown_08540010:: @ 8540010
.4byte gUnknown_08540000
.align 2
gUnknown_08540014:: @ 8540014
.4byte gUnknown_08540008
.align 2
gUnknown_08540018:: @ 8540018
spr_template 0x03e8, 0x03e8, gUnknown_0853FFF0, gUnknown_08540010, NULL, gDummySpriteAffineAnimTable, sub_80AA40C
.align 2
gUnknown_08540030:: @ 8540030
spr_template 0x03e8, 0x03e8, gUnknown_0853FFF8, gUnknown_08540014, NULL, gDummySpriteAffineAnimTable, sub_80AA474
.align 2
gUnknown_08540048:: @ 8540048
obj_tiles gTitleScreenEmeraldVersionGfx, 0x1000, 0x03e8
null_obj_tiles
.align 2
gUnknown_08540058:: @ 8540058
.byte 0xa0, 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00
.align 2
gUnknown_08540060:: @ 8540060
.2byte 0x0001, 0x0004, 0xffff, 0x0000
.align 2
gUnknown_08540068:: @ 8540068
.2byte 0x0005, 0x0004, 0xffff, 0x0000
.align 2
gUnknown_08540070:: @ 8540070
.2byte 0x0009, 0x0004, 0xffff, 0x0000
.align 2
gUnknown_08540078:: @ 8540078
.2byte 0x000d, 0x0004, 0xffff, 0x0000
.align 2
gUnknown_08540080:: @ 8540080
.2byte 0x0011, 0x0004, 0xffff, 0x0000
.align 2
gUnknown_08540088:: @ 8540088
.2byte 0x0015, 0x0004, 0xffff, 0x0000
.align 2
gUnknown_08540090:: @ 8540090
.2byte 0x0019, 0x0004, 0xffff, 0x0000
.align 2
gUnknown_08540098:: @ 8540098
.2byte 0x001d, 0x0004, 0xffff, 0x0000
.align 2
gUnknown_085400A0:: @ 85400A0
.2byte 0x0021, 0x0004, 0xffff, 0x0000
.align 2
gUnknown_085400A8:: @ 85400A8
.2byte 0x0025, 0x0004, 0xffff, 0x0000
.align 2
gUnknown_085400B0:: @ 85400B0
.4byte gUnknown_08540060
.4byte gUnknown_08540068
.4byte gUnknown_08540070
.4byte gUnknown_08540078
.4byte gUnknown_08540080
.4byte gUnknown_08540088
.4byte gUnknown_08540090
.4byte gUnknown_08540098
.4byte gUnknown_085400A0
.4byte gUnknown_085400A8
.align 2
gUnknown_085400D8:: @ 85400D8
spr_template 0x03e9, 0x03e9, gUnknown_08540058, gUnknown_085400B0, NULL, gDummySpriteAffineAnimTable, sub_80AA4B4
.align 2
gUnknown_085400F0:: @ 85400F0
obj_tiles gTitleScreenPressStartGfx, 0x0520, 0x03e9
null_obj_tiles
.align 2
gUnknown_08540100:: @ 8540100
obj_pal gTitleScreenPressStartPal, 0x03e9
null_obj_pal
.align 2
gUnknown_08540110:: @ 8540110
.byte 0xa0, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00
.align 2
gUnknown_08540118:: @ 8540118
.2byte 0x0000, 0x0004, 0xffff, 0x0000
.align 2
gUnknown_08540120:: @ 8540120
.4byte gUnknown_08540118
.align 2
gUnknown_08540124:: @ 8540124
spr_template 0x03ea, 0x03e9, gUnknown_08540110, gUnknown_08540120, NULL, gDummySpriteAffineAnimTable, title_screen_logo_shine_obj_callback_type1
.align 2
gUnknown_0854013C:: @ 854013C
obj_tiles gTitleScreenLogoShineGfx, 0x0800, 0x03ea
null_obj_tiles

View File

@ -0,0 +1,6 @@
#ifndef GUARD_BERRY_FIX_PROGRAM_H
#define GUARD_BERRY_FIX_PROGRAM_H
void CB2_InitBerryFixProgram(void);
#endif // GUARD_BERRY_FIX_PROGRAM_H

View File

@ -0,0 +1,6 @@
#ifndef GUARD_CLEAR_SAVE_DATA_MENU_H
#define GUARD_CLEAR_SAVE_DATA_MENU_H
void CB2_InitClearSaveDataScreen(void);
#endif // GUARD_CLEAR_SAVE_DATA_MENU_H

View File

@ -2,6 +2,7 @@
#define GUARD_RGB_H
#define RGB(r, g, b) ((r) | ((g) << 5) | ((b) << 10))
#define _RGB(r, g, b) ((((b) & 0x1F) << 10) + (((g) & 0x1F) << 5) + ((r) & 0x1F))
#define RGB_BLACK RGB(0, 0, 0)
#define RGB_WHITE RGB(31, 31, 31)

8
include/intro.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef GUARD_INTRO_H
#define GUARD_INTRO_H
void CB2_InitCopyrightScreenAfterBootup(void);
void CB2_InitCopyrightScreenAfterTitleScreen(void);
void sub_816F2A8(u16, u16, u16, u16);
#endif // GUARD_INTRO_H

6
include/main_menu.h Normal file
View File

@ -0,0 +1,6 @@
#ifndef GUARD_MAIN_MENU_H
#define GUARD_MAIN_MENU_H
void CB2_InitMainMenu(void);
#endif // GUARD_MAIN_MENU_H

View File

@ -0,0 +1,6 @@
#ifndef GUARD_RESET_RTC_SCREEN_H
#define GUARD_RESET_RTC_SCREEN_H
void CB2_InitResetRtcScreen(void);
#endif // GUARD_RESET_RTC_SCREEN_H

8
include/title_screen.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef GUARD_TITLE_SCREEN_H
#define GUARD_TITLE_SCREEN_H
extern const u16 gUnknown_0853FF70[];
void CB2_InitTitleScreen(void);
#endif // GUARD_TITLE_SCREEN_H

View File

@ -119,7 +119,7 @@ SECTIONS {
src/task.o(.text);
src/reshow_battle_screen.o(.text);
asm/battle_anim_80A9C70.o(.text);
asm/title_screen.o(.text);
src/title_screen.o(.text);
asm/field_screen.o(.text);
src/battle_setup.o(.text);
asm/cable_club.o(.text);
@ -419,7 +419,7 @@ SECTIONS {
data/rom_8525F58.o(.rodata);
data/map_events.o(.rodata);
data/battle_anim_80A9C70.o(.rodata);
data/title_screen.o(.rodata);
src/title_screen.o(.rodata);
data/field_screen.o(.rodata);
src/battle_setup.o(.rodata);
data/cable_club.o(.rodata);

View File

@ -133,7 +133,7 @@ extern const u8 gMultiBootProgram_BerryGlitchFix_End[];
// .text
void InitBerryFixProgram(void)
void CB2_InitBerryFixProgram(void)
{
DisableInterrupts(0xFFFF);
EnableInterrupts(0x0001);

783
src/title_screen.c Normal file
View File

@ -0,0 +1,783 @@
#include "global.h"
#include "title_screen.h"
#include "sprite.h"
#include "gba/m4a_internal.h"
#include "clear_save_data_menu.h"
#include "decompress.h"
#include "event_data.h"
#include "intro.h"
#include "m4a.h"
#include "main.h"
#include "main_menu.h"
#include "palette.h"
#include "reset_rtc_screen.h"
#include "berry_fix_program.h"
#include "sound.h"
#include "sprite.h"
#include "task.h"
#include "scanline_effect.h"
#include "gpu_regs.h"
#include "trig.h"
#include "constants/rgb.h"
#define VERSION_BANNER_SHAPE 1
#define VERSION_BANNER_RIGHT_TILEOFFSET 64
#define VERSION_BANNER_BYTES 0x1000
#define VERSION_BANNER_LEFT_X 98
#define VERSION_BANNER_RIGHT_X 162
#define VERSION_BANNER_Y 2
#define VERSION_BANNER_Y_GOAL 66
#define START_BANNER_X 128
#define CLEAR_SAVE_BUTTON_COMBO (B_BUTTON | SELECT_BUTTON | DPAD_UP)
#define RESET_RTC_BUTTON_COMBO (B_BUTTON | SELECT_BUTTON | DPAD_LEFT)
#define BERRY_UPDATE_BUTTON_COMBO (B_BUTTON | SELECT_BUTTON)
#define A_B_START_SELECT (A_BUTTON | B_BUTTON | START_BUTTON | SELECT_BUTTON)
extern struct MusicPlayerInfo gMPlayInfo_BGM;
extern u16 gBattle_BG1_X;
extern u16 gBattle_BG1_Y;
extern const u8 gTitleScreenEmeraldVersionGfx[];
extern const u8 gTitleScreenPressStartGfx[];
extern const u8 gTitleScreenPokemonLogoGfx[];
extern const u8 gUnknown_08DE0644[];
extern const u8 gUnknown_08DDE458[];
extern const u16 gTitleScreenBgPalettes[];
extern const u16 gTitleScreenPressStartPal[];
extern const u16 gTitleScreenEmeraldVersionPal[];
// this file's functions
static void MainCB2(void);
static void Task_TitleScreenPhase1(u8);
static void Task_TitleScreenPhase2(u8);
static void Task_TitleScreenPhase3(u8);
static void CB2_GoToMainMenu(void);
static void CB2_GoToClearSaveDataScreen(void);
static void CB2_GoToResetRtcScreen(void);
static void CB2_GoToBerryFixScreen(void);
static void CB2_GoToCopyrightScreen(void);
static void UpdateLegendaryMarkingColor(u8);
static void SpriteCB_VersionBannerLeft(struct Sprite *sprite);
static void SpriteCB_VersionBannerRight(struct Sprite *sprite);
static void SpriteCB_PressStartCopyrightBanner(struct Sprite *sprite);
static void SpriteCB_PokemonLogoShine(struct Sprite *sprite);
// const rom data
static const u16 sUnusedUnknownPal[] = INCBIN_U16("graphics/title_screen/unk_853EF78.gbapal");
static const u8 sTitleScreenRayquazaGfx[] = INCBIN_U8("graphics/title_screen/rayquaza.4bpp.lz");
static const u8 sTitleScreenRayquazaTilemap[] = INCBIN_U8("graphics/title_screen/rayquaza.bin.lz");
static const u8 sTitleScreenLogoShineGfx[] = INCBIN_U8("graphics/title_screen/logo_shine.4bpp.lz");
static const u8 sTitleScreenCloudsGfx[] = INCBIN_U8("graphics/title_screen/clouds.4bpp.lz");
const u16 gUnknown_0853FF70[] =
{
0x0010, 0x0110, 0x0210, 0x0310, 0x0410, 0x0510, 0x0610, 0x0710,
0x0810, 0x0910, 0x0a10, 0x0b10, 0x0c10, 0x0d10, 0x0e10, 0x0f10,
0x100f, 0x100e, 0x100d, 0x100c, 0x100b, 0x100a, 0x1009, 0x1008,
0x1007, 0x1006, 0x1005, 0x1004, 0x1003, 0x1002, 0x1001, 0x1000,
0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
};
static const struct OamData sVersionBannerLeftOamData =
{
.y = 160,
.affineMode = 0,
.objMode = 0,
.mosaic = 0,
.bpp = 1,
.shape = VERSION_BANNER_SHAPE,
.x = 0,
.matrixNum = 0,
.size = 3,
.tileNum = 0,
.priority = 0,
.paletteNum = 0,
.affineParam = 0,
};
static const struct OamData sVersionBannerRightOamData =
{
.y = 160,
.affineMode = 0,
.objMode = 0,
.mosaic = 0,
.bpp = 1,
.shape = VERSION_BANNER_SHAPE,
.x = 0,
.matrixNum = 0,
.size = 3,
.tileNum = 0,
.priority = 0,
.paletteNum = 0,
.affineParam = 0,
};
static const union AnimCmd sVersionBannerLeftAnimSequence[] =
{
ANIMCMD_FRAME(0, 30),
ANIMCMD_END,
};
static const union AnimCmd sVersionBannerRightAnimSequence[] =
{
ANIMCMD_FRAME(VERSION_BANNER_RIGHT_TILEOFFSET, 30),
ANIMCMD_END,
};
static const union AnimCmd *const sVersionBannerLeftAnimTable[] =
{
sVersionBannerLeftAnimSequence,
};
static const union AnimCmd *const sVersionBannerRightAnimTable[] =
{
sVersionBannerRightAnimSequence,
};
static const struct SpriteTemplate sVersionBannerLeftSpriteTemplate =
{
.tileTag = 1000,
.paletteTag = 1000,
.oam = &sVersionBannerLeftOamData,
.anims = sVersionBannerLeftAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = SpriteCB_VersionBannerLeft,
};
static const struct SpriteTemplate sVersionBannerRightSpriteTemplate =
{
.tileTag = 1000,
.paletteTag = 1000,
.oam = &sVersionBannerRightOamData,
.anims = sVersionBannerRightAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = SpriteCB_VersionBannerRight,
};
static const struct CompressedSpriteSheet sSpriteSheet_EmeraldVersion[] =
{
{gTitleScreenEmeraldVersionGfx, VERSION_BANNER_BYTES, 1000},
{NULL},
};
static const struct OamData sOamData_CopyrightBanner =
{
.y = 160,
.affineMode = 0,
.objMode = 0,
.mosaic = 0,
.bpp = 0,
.shape = 1,
.x = 0,
.matrixNum = 0,
.size = 1,
.tileNum = 0,
.priority = 0,
.paletteNum = 0,
.affineParam = 0,
};
static const union AnimCmd sCopyrightBannerAnim0[] =
{
ANIMCMD_FRAME(1, 4),
ANIMCMD_END,
};
static const union AnimCmd sCopyrightBannerAnim1[] =
{
ANIMCMD_FRAME(5, 4),
ANIMCMD_END,
};
static const union AnimCmd sCopyrightBannerAnim2[] =
{
ANIMCMD_FRAME(9, 4),
ANIMCMD_END,
};
static const union AnimCmd sCopyrightBannerAnim3[] =
{
ANIMCMD_FRAME(13, 4),
ANIMCMD_END,
};
static const union AnimCmd sCopyrightBannerAnim4[] =
{
ANIMCMD_FRAME(17, 4),
ANIMCMD_END,
};
static const union AnimCmd sCopyrightBannerAnim5[] =
{
ANIMCMD_FRAME(21, 4),
ANIMCMD_END,
};
static const union AnimCmd sCopyrightBannerAnim6[] =
{
ANIMCMD_FRAME(25, 4),
ANIMCMD_END,
};
static const union AnimCmd sCopyrightBannerAnim7[] =
{
ANIMCMD_FRAME(29, 4),
ANIMCMD_END,
};
static const union AnimCmd sCopyrightBannerAnim8[] =
{
ANIMCMD_FRAME(33, 4),
ANIMCMD_END,
};
static const union AnimCmd sCopyrightBannerAnim9[] =
{
ANIMCMD_FRAME(37, 4),
ANIMCMD_END,
};
static const union AnimCmd *const sStartCopyrightBannerAnimTable[] =
{
sCopyrightBannerAnim0,
sCopyrightBannerAnim1,
sCopyrightBannerAnim2,
sCopyrightBannerAnim3,
sCopyrightBannerAnim4,
sCopyrightBannerAnim5,
sCopyrightBannerAnim6,
sCopyrightBannerAnim7,
sCopyrightBannerAnim8,
sCopyrightBannerAnim9,
};
static const struct SpriteTemplate sStartCopyrightBannerSpriteTemplate =
{
.tileTag = 1001,
.paletteTag = 1001,
.oam = &sOamData_CopyrightBanner,
.anims = sStartCopyrightBannerAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = SpriteCB_PressStartCopyrightBanner,
};
static const struct CompressedSpriteSheet sSpriteSheet_PressStart[] =
{
{gTitleScreenPressStartGfx, 0x520, 1001},
{NULL},
};
static const struct SpritePalette sSpritePalette_PressStart[] =
{
{gTitleScreenPressStartPal, 1001},
{NULL},
};
static const struct OamData sPokemonLogoShineOamData =
{
.y = 160,
.affineMode = 0,
.objMode = 0,
.mosaic = 0,
.bpp = 0,
.shape = 0,
.x = 0,
.matrixNum = 0,
.size = 3,
.tileNum = 0,
.priority = 0,
.paletteNum = 0,
.affineParam = 0,
};
static const union AnimCmd sPokemonLogoShineAnimSequence[] =
{
ANIMCMD_FRAME(0, 4),
ANIMCMD_END,
};
static const union AnimCmd *const sPokemonLogoShineAnimTable[] =
{
sPokemonLogoShineAnimSequence,
};
static const struct SpriteTemplate sPokemonLogoShineSpriteTemplate =
{
.tileTag = 1002,
.paletteTag = 1001,
.oam = &sPokemonLogoShineOamData,
.anims = sPokemonLogoShineAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = SpriteCB_PokemonLogoShine,
};
static const struct CompressedSpriteSheet sPokemonLogoShineSpriteSheet[] =
{
{sTitleScreenLogoShineGfx, 0x800, 1002},
{NULL},
};
// code
static void SpriteCB_VersionBannerLeft(struct Sprite *sprite)
{
if (gTasks[sprite->data[1]].data[1] != 0)
{
sprite->oam.objMode = 0;
sprite->pos1.y = VERSION_BANNER_Y_GOAL;
}
else
{
if (sprite->pos1.y != VERSION_BANNER_Y_GOAL)
sprite->pos1.y++;
if (sprite->data[0] != 0)
sprite->data[0]--;
SetGpuReg(REG_OFFSET_BLDALPHA, gUnknown_0853FF70[sprite->data[0]]);
}
}
static void SpriteCB_VersionBannerRight(struct Sprite *sprite)
{
if (gTasks[sprite->data[1]].data[1] != 0)
{
sprite->oam.objMode = 0;
sprite->pos1.y = VERSION_BANNER_Y_GOAL;
}
else
{
if (sprite->pos1.y != VERSION_BANNER_Y_GOAL)
sprite->pos1.y++;
}
}
static void SpriteCB_PressStartCopyrightBanner(struct Sprite *sprite)
{
if (sprite->data[0] == 1)
{
sprite->data[1]++;
// Alternate between hidden and shown every 16th frame
if (sprite->data[1] & 0x10)
sprite->invisible = FALSE;
else
sprite->invisible = TRUE;
}
else
{
sprite->invisible = FALSE;
}
}
static void CreatePressStartBanner(s16 x, s16 y)
{
u8 i;
u8 spriteId;
x -= 64;
for (i = 0; i < 5; i++, x += 32)
{
spriteId = CreateSprite(&sStartCopyrightBannerSpriteTemplate, x, y, 0);
StartSpriteAnim(&gSprites[spriteId], i);
gSprites[spriteId].data[0] = 1;
}
}
static void CreateCopyrightBanner(s16 x, s16 y)
{
u8 i;
u8 spriteId;
x -= 64;
for (i = 0; i < 5; i++, x += 32)
{
spriteId = CreateSprite(&sStartCopyrightBannerSpriteTemplate, x, y, 0);
StartSpriteAnim(&gSprites[spriteId], i + 5);
}
}
static void SpriteCB_PokemonLogoShine(struct Sprite *sprite)
{
if (sprite->pos1.x < 272)
{
if (sprite->data[0]) // Flash background
{
u16 backgroundColor;
if (sprite->pos1.x < DISPLAY_WIDTH / 2)
{
// Brighten background color
if (sprite->data[1] < 31)
sprite->data[1]++;
if (sprite->data[1] < 31)
sprite->data[1]++;
}
else
{
// Darken background color
if (sprite->data[1] != 0)
sprite->data[1]--;
if (sprite->data[1] != 0)
sprite->data[1]--;
}
backgroundColor = _RGB(sprite->data[1], sprite->data[1], sprite->data[1]);
if (sprite->pos1.x == DISPLAY_WIDTH / 2 + 12
|| sprite->pos1.x == DISPLAY_WIDTH / 2 + 16
|| sprite->pos1.x == DISPLAY_WIDTH / 2 + 20
|| sprite->pos1.x == DISPLAY_WIDTH / 2 + 24)
gPlttBufferFaded[0] = RGB(24, 31, 12);
else
gPlttBufferFaded[0] = backgroundColor;
}
sprite->pos1.x += 4;
}
else
{
gPlttBufferFaded[0] = RGB_BLACK;
DestroySprite(sprite);
}
}
static void SpriteCB_PokemonLogoShine2(struct Sprite *sprite)
{
if (sprite->pos1.x < 272)
sprite->pos1.x += 8;
else
DestroySprite(sprite);
}
static void StartPokemonLogoShine(u8 flashBg)
{
u8 spriteId;
switch (flashBg)
{
case 0:
case 2:
spriteId = CreateSprite(&sPokemonLogoShineSpriteTemplate, 0, 68, 0);
gSprites[spriteId].oam.objMode = 2;
gSprites[spriteId].data[0] = flashBg;
break;
case 1:
spriteId = CreateSprite(&sPokemonLogoShineSpriteTemplate, 0, 68, 0);
gSprites[spriteId].oam.objMode = 2;
gSprites[spriteId].data[0] = flashBg;
gSprites[spriteId].invisible = TRUE;
spriteId = CreateSprite(&sPokemonLogoShineSpriteTemplate, 0, 68, 0);
gSprites[spriteId].callback = SpriteCB_PokemonLogoShine2;
gSprites[spriteId].oam.objMode = 2;
spriteId = CreateSprite(&sPokemonLogoShineSpriteTemplate, -80, 68, 0);
gSprites[spriteId].callback = SpriteCB_PokemonLogoShine2;
gSprites[spriteId].oam.objMode = 2;
break;
}
}
static void VBlankCB(void)
{
ScanlineEffect_InitHBlankDmaTransfer();
LoadOam();
ProcessSpriteCopyRequests();
TransferPlttBuffer();
SetGpuReg(REG_OFFSET_BG1VOFS, gBattle_BG1_Y);
}
#define tCounter data[0]
#define tSkipToNext data[1]
void CB2_InitTitleScreen(void)
{
switch (gMain.state)
{
default:
case 0:
SetVBlankCallback(NULL);
SetGpuReg(REG_OFFSET_BLDCNT, 0);
SetGpuReg(REG_OFFSET_BLDALPHA, 0);
SetGpuReg(REG_OFFSET_BLDY, 0);
*((u16 *)PLTT) = RGB_WHITE;
SetGpuReg(REG_OFFSET_DISPCNT, 0);
SetGpuReg(REG_OFFSET_BG2CNT, 0);
SetGpuReg(REG_OFFSET_BG1CNT, 0);
SetGpuReg(REG_OFFSET_BG0CNT, 0);
SetGpuReg(REG_OFFSET_BG2HOFS, 0);
SetGpuReg(REG_OFFSET_BG2VOFS, 0);
SetGpuReg(REG_OFFSET_BG1HOFS, 0);
SetGpuReg(REG_OFFSET_BG1VOFS, 0);
SetGpuReg(REG_OFFSET_BG0HOFS, 0);
SetGpuReg(REG_OFFSET_BG0VOFS, 0);
DmaFill16(3, 0, (void *)VRAM, VRAM_SIZE);
DmaFill32(3, 0, (void *)OAM, OAM_SIZE);
DmaFill16(3, 0, (void *)(PLTT + 2), PLTT_SIZE - 2);
ResetPaletteFade();
gMain.state = 1;
break;
case 1:
LZ77UnCompVram(gTitleScreenPokemonLogoGfx, (void *)VRAM);
LZ77UnCompVram(gUnknown_08DE0644, (void *)(VRAM + 0x4800));
LoadPalette(gTitleScreenBgPalettes, 0, 0x1E0);
LZ77UnCompVram(sTitleScreenRayquazaGfx, (void *)(VRAM + 0x8000));
LZ77UnCompVram(sTitleScreenRayquazaTilemap, (void *)(VRAM + 0xD000));
LZ77UnCompVram(sTitleScreenCloudsGfx, (void *)(VRAM + 0xC000));
LZ77UnCompVram(gUnknown_08DDE458, (void *)(VRAM + 0xD800));
ScanlineEffect_Stop();
ResetTasks();
ResetSpriteData();
FreeAllSpritePalettes();
gReservedSpritePaletteCount = 9;
LoadCompressedObjectPic(&sSpriteSheet_EmeraldVersion[0]);
LoadCompressedObjectPic(&sSpriteSheet_PressStart[0]);
LoadCompressedObjectPic(&sPokemonLogoShineSpriteSheet[0]);
LoadPalette(gTitleScreenEmeraldVersionPal, 0x100, 0x20);
LoadSpritePalette(&sSpritePalette_PressStart[0]);
gMain.state = 2;
break;
case 2:
{
u8 taskId = CreateTask(Task_TitleScreenPhase1, 0);
gTasks[taskId].tCounter = 256;
gTasks[taskId].tSkipToNext = FALSE;
gTasks[taskId].data[2] = -16;
gTasks[taskId].data[3] = -32;
gMain.state = 3;
break;
}
case 3:
BeginNormalPaletteFade(-1, 1, 0x10, 0, 0xFFFF);
SetVBlankCallback(VBlankCB);
gMain.state = 4;
break;
case 4:
sub_816F2A8(0x78, 0x50, 0x100, 0);
SetGpuReg(REG_OFFSET_BG2X_L, -29 * 256);
SetGpuReg(REG_OFFSET_BG2X_H, -1);
SetGpuReg(REG_OFFSET_BG2Y_L, -32 * 256);
SetGpuReg(REG_OFFSET_BG2Y_H, -1);
SetGpuReg(REG_OFFSET_WIN0H, 0);
SetGpuReg(REG_OFFSET_WIN0V, 0);
SetGpuReg(REG_OFFSET_WIN1H, 0);
SetGpuReg(REG_OFFSET_WIN1V, 0);
SetGpuReg(REG_OFFSET_WININ, 0x1F1F);
SetGpuReg(REG_OFFSET_WINOUT, 0x3F1F);
SetGpuReg(REG_OFFSET_BLDCNT, 0x84);
SetGpuReg(REG_OFFSET_BLDALPHA, 0);
SetGpuReg(REG_OFFSET_BLDY, 0xC);
SetGpuReg(REG_OFFSET_BG0CNT, BGCNT_PRIORITY(3) | BGCNT_CHARBASE(2) | BGCNT_SCREENBASE(26) | BGCNT_16COLOR | BGCNT_TXT256x256);
SetGpuReg(REG_OFFSET_BG1CNT, BGCNT_PRIORITY(2) | BGCNT_CHARBASE(3) | BGCNT_SCREENBASE(27) | BGCNT_16COLOR | BGCNT_TXT256x256);
SetGpuReg(REG_OFFSET_BG2CNT, BGCNT_PRIORITY(1) | BGCNT_CHARBASE(0) | BGCNT_SCREENBASE(9) | BGCNT_256COLOR | BGCNT_AFF256x256);
EnableInterrupts(INTR_FLAG_VBLANK);
SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_MODE_1
| DISPCNT_OBJ_1D_MAP
| DISPCNT_BG2_ON
| DISPCNT_OBJ_ON
| DISPCNT_WIN0_ON
| DISPCNT_OBJWIN_ON);
m4aSongNumStart(0x19D);
gMain.state = 5;
break;
case 5:
if (!UpdatePaletteFade())
{
StartPokemonLogoShine(0);
ScanlineEffect_InitWave(0, DISPLAY_HEIGHT, 4, 4, 0, SCANLINE_EFFECT_REG_BG1HOFS, TRUE);
SetMainCallback2(MainCB2);
}
break;
}
}
static void MainCB2(void)
{
RunTasks();
AnimateSprites();
BuildOamBuffer();
UpdatePaletteFade();
}
// Shine the Pokemon logo two more times, and fade in the version banner
static void Task_TitleScreenPhase1(u8 taskId)
{
// Skip to next phase when A, B, Start, or Select is pressed
if ((gMain.newKeys & A_B_START_SELECT) || gTasks[taskId].data[1] != 0)
{
gTasks[taskId].tSkipToNext = TRUE;
gTasks[taskId].tCounter = 0;
}
if (gTasks[taskId].tCounter != 0)
{
u16 frameNum = gTasks[taskId].tCounter;
if (frameNum == 176)
StartPokemonLogoShine(1);
else if (frameNum == 64)
StartPokemonLogoShine(2);
gTasks[taskId].tCounter--;
}
else
{
u8 spriteId;
SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_MODE_1 | DISPCNT_OBJ_1D_MAP | DISPCNT_BG2_ON | DISPCNT_OBJ_ON);
SetGpuReg(REG_OFFSET_WININ, 0);
SetGpuReg(REG_OFFSET_WINOUT, 0);
SetGpuReg(REG_OFFSET_BLDCNT, 0x3F50);
SetGpuReg(REG_OFFSET_BLDALPHA, 0x10);
SetGpuReg(REG_OFFSET_BLDY, 0);
// Create left side of version banner
spriteId = CreateSprite(&sVersionBannerLeftSpriteTemplate, VERSION_BANNER_LEFT_X, VERSION_BANNER_Y, 0);
gSprites[spriteId].data[0] = 64;
gSprites[spriteId].data[1] = taskId;
// Create right side of version banner
spriteId = CreateSprite(&sVersionBannerRightSpriteTemplate, VERSION_BANNER_RIGHT_X, VERSION_BANNER_Y, 0);
gSprites[spriteId].data[1] = taskId;
gTasks[taskId].tCounter = 144;
gTasks[taskId].func = Task_TitleScreenPhase2;
}
}
// Create "Press Start" and copyright banners, and slide Pokemon logo up
static void Task_TitleScreenPhase2(u8 taskId)
{
u32 yPos;
// Skip to next phase when A, B, Start, or Select is pressed
if ((gMain.newKeys & A_B_START_SELECT) || gTasks[taskId].tSkipToNext)
{
gTasks[taskId].tSkipToNext = TRUE;
gTasks[taskId].tCounter = 0;
}
if (gTasks[taskId].tCounter != 0)
{
gTasks[taskId].tCounter--;
}
else
{
gTasks[taskId].tSkipToNext = TRUE;
SetGpuReg(REG_OFFSET_BLDCNT, 0x2142);
SetGpuReg(REG_OFFSET_BLDALPHA, 0xF06);
SetGpuReg(REG_OFFSET_BLDY, 0);
SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_MODE_1
| DISPCNT_OBJ_1D_MAP
| DISPCNT_BG0_ON
| DISPCNT_BG1_ON
| DISPCNT_BG2_ON
| DISPCNT_OBJ_ON);
CreatePressStartBanner(START_BANNER_X, 108);
CreateCopyrightBanner(START_BANNER_X, 148);
gTasks[taskId].data[4] = 0;
gTasks[taskId].func = Task_TitleScreenPhase3;
}
if (!(gTasks[taskId].tCounter & 3) && gTasks[taskId].data[2] != 0)
gTasks[taskId].data[2]++;
if (!(gTasks[taskId].tCounter & 1) && gTasks[taskId].data[3] != 0)
gTasks[taskId].data[3]++;
// Slide Pokemon logo up
yPos = gTasks[taskId].data[3] * 256;
SetGpuReg(REG_OFFSET_BG2Y_L, yPos);
SetGpuReg(REG_OFFSET_BG2Y_H, yPos / 0x10000);
gTasks[taskId].data[5] = 15;
gTasks[taskId].data[6] = 6;
}
// Show Rayquaza silhouette and process main title screen input
static void Task_TitleScreenPhase3(u8 taskId)
{
if ((gMain.newKeys & A_BUTTON) || (gMain.newKeys & START_BUTTON))
{
FadeOutBGM(4);
BeginNormalPaletteFade(-1, 0, 0, 0x10, 0xFFFF);
SetMainCallback2(CB2_GoToMainMenu);
}
else if ((gMain.heldKeys & CLEAR_SAVE_BUTTON_COMBO) == CLEAR_SAVE_BUTTON_COMBO)
{
SetMainCallback2(CB2_GoToClearSaveDataScreen);
}
else if ((gMain.heldKeys & RESET_RTC_BUTTON_COMBO) == RESET_RTC_BUTTON_COMBO
&& CanResetRTC() == TRUE)
{
FadeOutBGM(4);
BeginNormalPaletteFade(-1, 0, 0, 0x10, 0);
SetMainCallback2(CB2_GoToResetRtcScreen);
}
else if ((gMain.heldKeys & BERRY_UPDATE_BUTTON_COMBO) == BERRY_UPDATE_BUTTON_COMBO)
{
FadeOutBGM(4);
BeginNormalPaletteFade(-1, 0, 0, 0x10, 0);
SetMainCallback2(CB2_GoToBerryFixScreen);
}
else
{
SetGpuReg(REG_OFFSET_BG2Y_L, 0);
SetGpuReg(REG_OFFSET_BG2Y_H, 0);
gTasks[taskId].tCounter++;
if (gTasks[taskId].tCounter & 1)
{
gTasks[taskId].data[4]++;
gBattle_BG1_Y = gTasks[taskId].data[4] / 2;
gBattle_BG1_X = 0;
}
UpdateLegendaryMarkingColor(gTasks[taskId].tCounter);
if ((gMPlayInfo_BGM.status & 0xFFFF) == 0)
{
BeginNormalPaletteFade(-1, 0, 0, 0x10, 0xFFFF);
SetMainCallback2(CB2_GoToCopyrightScreen);
}
}
}
static void CB2_GoToMainMenu(void)
{
if (!UpdatePaletteFade())
SetMainCallback2(CB2_InitMainMenu);
}
static void CB2_GoToCopyrightScreen(void)
{
if (!UpdatePaletteFade())
SetMainCallback2(CB2_InitCopyrightScreenAfterTitleScreen);
}
static void CB2_GoToClearSaveDataScreen(void)
{
if (!UpdatePaletteFade())
SetMainCallback2(CB2_InitClearSaveDataScreen);
}
static void CB2_GoToResetRtcScreen(void)
{
if (!UpdatePaletteFade())
SetMainCallback2(CB2_InitResetRtcScreen);
}
static void CB2_GoToBerryFixScreen(void)
{
if (!UpdatePaletteFade())
{
m4aMPlayAllStop();
SetMainCallback2(CB2_InitBerryFixProgram);
}
}
static void UpdateLegendaryMarkingColor(u8 frameNum)
{
if ((frameNum % 4) == 0) // Change color every 4th frame
{
s32 intensity = Cos(frameNum, 128) + 128;
s32 r = 31 - ((intensity * 32 - intensity) / 256);
s32 g = 31 - (intensity * 22 / 256);
s32 b = 12;
u16 color = RGB(r, g, b);
LoadPalette(&color, 0xEF, sizeof(color));
}
}