mirror of https://github.com/zeldaret/tmc.git
367 lines
10 KiB
C
367 lines
10 KiB
C
#include "global.h"
|
|
#include "menu.h"
|
|
#include "main.h"
|
|
#include "entity.h"
|
|
#include "functions.h"
|
|
#include "readKeyInput.h"
|
|
#include "screen.h"
|
|
#include "structures.h"
|
|
|
|
typedef struct {
|
|
u8 filler0[0x4];
|
|
u8 gameLanguage;
|
|
u8 state;
|
|
u8 subState;
|
|
u8 filler7[0x1];
|
|
u16 timer;
|
|
u8 fillerA[0x6];
|
|
u8 lightRaysPaletteGroup;
|
|
u8 lightRaysAlphaBlendIndex;
|
|
u8 counter;
|
|
u8 filler13[0x19];
|
|
int swordBgScaleRatio;
|
|
} IntroState;
|
|
|
|
// TODO: This occupies the same memory region as gMenu
|
|
extern IntroState gIntroState;
|
|
|
|
enum {
|
|
ADVANCE_NONE,
|
|
ADVANCE_TIMER_EXPIRED,
|
|
ADVANCE_KEY_PRESSED,
|
|
};
|
|
|
|
static void HandleNintendoCapcomLogos(void);
|
|
static void HandleTitlescreen(void);
|
|
static void UpdateSwordBgAffineData(void);
|
|
static void ExitTitlescreen(void);
|
|
static void HandleJapaneseTitlescreenAnimationIntro(void);
|
|
static void HandleTitlescreenAnimationIntro(void);
|
|
static u32 GetAdvanceState(void);
|
|
static void UpdateLightRays(void);
|
|
static void UpdatePressStartIcon(void);
|
|
|
|
static void (*const sIntroSequenceHandlers[])(void) = {
|
|
HandleNintendoCapcomLogos,
|
|
HandleTitlescreen,
|
|
ExitTitlescreen,
|
|
};
|
|
|
|
static const u16 sLightRaysAlphaBlends[] = {
|
|
BLDALPHA_BLEND(9, 9),
|
|
BLDALPHA_BLEND(8, 10),
|
|
BLDALPHA_BLEND(7, 11),
|
|
BLDALPHA_BLEND(6, 12),
|
|
BLDALPHA_BLEND(5, 13),
|
|
BLDALPHA_BLEND(6, 12),
|
|
BLDALPHA_BLEND(7, 11),
|
|
BLDALPHA_BLEND(8, 10),
|
|
};
|
|
|
|
static u32 AdvanceIntroSequence(u32 transition)
|
|
{
|
|
gUnk_02032EC0.transitionType = transition;
|
|
gUnk_03001000.funcIndex = 2;
|
|
_DmaZero(&gIntroState, sizeof(gIntroState));
|
|
DoFade(7, 8);
|
|
}
|
|
|
|
void HandleIntroScreen(void)
|
|
{
|
|
sub_080AD90C();
|
|
switch (gUnk_03001000.funcIndex) {
|
|
case 0:
|
|
sub_08056418();
|
|
_DmaZero(&gUnk_02032EC0, 0x3b4);
|
|
AdvanceIntroSequence(0);
|
|
break;
|
|
case 1:
|
|
sIntroSequenceHandlers[gUnk_02032EC0.transitionType]();
|
|
break;
|
|
case 2:
|
|
if (gFadeControl.active) {
|
|
return;
|
|
}
|
|
sub_0801DA90(1);
|
|
gUnk_03001000.funcIndex = 1;
|
|
break;
|
|
}
|
|
sub_080AD918();
|
|
}
|
|
|
|
static void HandleNintendoCapcomLogos(void)
|
|
{
|
|
u32 advance;
|
|
u32 paletteGroup;
|
|
|
|
advance = GetAdvanceState();
|
|
if (gIntroState.state == 0) {
|
|
sub_0801DA90(1);
|
|
gIntroState.state = 1;
|
|
gIntroState.timer = 120;
|
|
LoadGfxGroup(16);
|
|
LoadGfxGroup(1);
|
|
if (((struct_02000000 *)0x2000000)->gameLanguage == 0) {
|
|
paletteGroup = 1;
|
|
}
|
|
else {
|
|
paletteGroup = 2;
|
|
}
|
|
LoadPaletteGroup(paletteGroup);
|
|
gScreen.lcd.displayControl |= 0x400;
|
|
gScreen.bg.bg2yOffset = 1;
|
|
DoFade(6, 8);
|
|
advance = ADVANCE_NONE;
|
|
} else {
|
|
if (advance == ADVANCE_TIMER_EXPIRED) {
|
|
advance = ADVANCE_KEY_PRESSED;
|
|
}
|
|
}
|
|
|
|
if (advance == ADVANCE_KEY_PRESSED) {
|
|
gUnk_02000010.listenForKeyPresses = 1;
|
|
AdvanceIntroSequence(1);
|
|
}
|
|
}
|
|
|
|
extern u16 gUnk_03001010[5];
|
|
|
|
static void HandleTitlescreen(void)
|
|
{
|
|
int advance;
|
|
u32 paletteGroup;
|
|
|
|
gIntroState.counter++;
|
|
switch (gIntroState.state) {
|
|
case 0:
|
|
gIntroState.state = 1;
|
|
gIntroState.subState = 0;
|
|
gIntroState.timer = 30;
|
|
gIntroState.gameLanguage = 7;
|
|
EraseAllEntities();
|
|
sub_0801CFA8(0);
|
|
sub_080ADD30();
|
|
gUnk_02024490.unk0 = 1;
|
|
LoadGfxGroup(2);
|
|
if (((struct_02000000*)0x2000000)->gameLanguage == 0) {
|
|
paletteGroup = 3;
|
|
}
|
|
else {
|
|
paletteGroup = 4;
|
|
}
|
|
LoadPaletteGroup(paletteGroup);
|
|
if (((struct_02000000*)0x2000000)->gameLanguage == 0) {
|
|
gScreen.controls.layerFXControl = 0x844;
|
|
gScreen.controls.alphaBlend = BLDALPHA_BLEND(9, 9);
|
|
gScreen.bg.bg1xOffset = 0x1c09;
|
|
gScreen.affine.bg2Control = 0x1d02;
|
|
gScreen.affine.bg3Control = 0x1e03;
|
|
gScreen.lcd.displayControl |= 0x1e00;
|
|
gScreen.bg.bg2xOffset = 0xff60;
|
|
}
|
|
else {
|
|
gScreen.controls.layerFXControl = 0x241;
|
|
gScreen.controls.alphaBlend = BLDALPHA_BLEND(9, 9);
|
|
gScreen.bg.bg0Control = 0x1d02;
|
|
gScreen.bg.bg1xOffset = 0x1E03;
|
|
gScreen.affine.bg2Control = 0x7C89;
|
|
gScreen.lcd.displayControl |= 1;
|
|
gScreen.lcd.displayControl |= 0x1300;
|
|
gIntroState.swordBgScaleRatio = 0x10;
|
|
UpdateSwordBgAffineData();
|
|
}
|
|
sub_080A3210();
|
|
PlaySFX(3); //fanfare
|
|
DoFade(6, 8);
|
|
break;
|
|
case 1:
|
|
if (gFadeControl.active) {
|
|
return;
|
|
}
|
|
if (((struct_02000000*)0x2000000)->gameLanguage == 0) {
|
|
HandleJapaneseTitlescreenAnimationIntro();
|
|
}
|
|
else {
|
|
HandleTitlescreenAnimationIntro();
|
|
}
|
|
break;
|
|
case 2:
|
|
if (--gIntroState.timer == 0) {
|
|
gIntroState.timer = 3600;
|
|
gIntroState.state++;
|
|
}
|
|
UpdatePressStartIcon();
|
|
break;
|
|
default:
|
|
advance = GetAdvanceState();
|
|
if (advance != ADVANCE_NONE) {
|
|
if (advance == ADVANCE_KEY_PRESSED) {
|
|
PlaySFX(0x6a);
|
|
}
|
|
else {
|
|
advance = ADVANCE_NONE;
|
|
}
|
|
AdvanceIntroSequence(advance);
|
|
PlaySFX(0x80080000);
|
|
}
|
|
UpdatePressStartIcon();
|
|
if ((gIntroState.timer & 0x20) == 0) {
|
|
gUnk_03001010[4] = 0xe000;
|
|
gUnk_03001010[1] = 0x84;
|
|
sub_080ADA14(0x1ff,0);
|
|
}
|
|
}
|
|
if (gIntroState.gameLanguage != ((struct_02000000*)0x2000000)->gameLanguage) {
|
|
gIntroState.gameLanguage = ((struct_02000000*)0x2000000)->gameLanguage;
|
|
LoadGfxGroup(3);
|
|
}
|
|
UpdateLightRays();
|
|
sub_0805E5C0();
|
|
sub_080AD9B0();
|
|
}
|
|
|
|
static void UpdatePressStartIcon(void) {
|
|
gUnk_03001010[2] = 0;
|
|
gUnk_03001010[3] = 0;
|
|
gUnk_03001010[4] = 0xE020;
|
|
gUnk_03001010[0] = 120;
|
|
gUnk_03001010[1] = 152;
|
|
sub_080ADA14(511, 1);
|
|
return;
|
|
}
|
|
|
|
static void UpdateSwordBgAffineData(void)
|
|
{
|
|
struct BgAffineSrcData aff;
|
|
aff.texY = 0x8000;
|
|
aff.texX = 0x8000;
|
|
aff.scrX = 0x78;
|
|
aff.scrY = 0x48;
|
|
aff.alpha = 0;
|
|
aff.sy = aff.sx = gIntroState.swordBgScaleRatio;
|
|
BgAffineSet(&aff, (struct BgAffineDstData*)&gBgControls, 1);
|
|
}
|
|
|
|
static void HandleJapaneseTitlescreenAnimationIntro(void)
|
|
{
|
|
Entity *pEVar2;
|
|
|
|
switch (gIntroState.subState) {
|
|
case 0:
|
|
if (!gFadeControl.active) {
|
|
if ((gIntroState.counter & 1) == 0) {
|
|
gScreen.bg.bg2xOffset++;
|
|
}
|
|
|
|
if (GetAdvanceState() == ADVANCE_KEY_PRESSED || gScreen.bg.bg2xOffset == 0) {
|
|
gIntroState.subState++;
|
|
gScreen.bg.bg2xOffset = 0;
|
|
gScreen.bg.bg1xOffset = 0xc09;
|
|
gFadeControl.field_0x4 = 0x40;
|
|
DoFade(6, 0x10);
|
|
PlaySFX(0xf8);
|
|
}
|
|
}
|
|
break;
|
|
case 1:
|
|
if (!gFadeControl.active) {
|
|
gFadeControl.field_0x4 = -1;
|
|
gIntroState.subState++;
|
|
gIntroState.timer = 90;
|
|
pEVar2 = CreateObject(0xb4,0,0);
|
|
if (pEVar2 != NULL) {
|
|
pEVar2->x.HALF.HI = 0;
|
|
pEVar2->y.HALF.HI = 0x48;
|
|
}
|
|
}
|
|
break;
|
|
case 2:
|
|
if (GetAdvanceState() != ADVANCE_NONE) {
|
|
gIntroState.state++;
|
|
gIntroState.timer = 60;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void HandleTitlescreenAnimationIntro(void) {
|
|
switch (gIntroState.subState) {
|
|
case 0:
|
|
if (!gFadeControl.active) {
|
|
gIntroState.subState = 1;
|
|
gScreen.lcd.displayControl |= 0x400;
|
|
PlaySFX(0xF6);
|
|
}
|
|
break;
|
|
case 1:
|
|
gIntroState.swordBgScaleRatio += 0x10;
|
|
if (gIntroState.swordBgScaleRatio > 0x100) {
|
|
gIntroState.swordBgScaleRatio = 0x100;
|
|
gIntroState.timer = 40;
|
|
gIntroState.subState++;
|
|
DoFade(6, 16);
|
|
}
|
|
UpdateSwordBgAffineData();
|
|
break;
|
|
case 2:
|
|
if (--gIntroState.timer == 0) {
|
|
gIntroState.timer = 300;
|
|
gIntroState.subState++;
|
|
CreateObject(0xBD, 0, 0);
|
|
DoFade(6, 16);
|
|
PlaySFX(0xF8);
|
|
}
|
|
break;
|
|
default:
|
|
if (!gFadeControl.active && GetAdvanceState() != ADVANCE_NONE) {
|
|
gIntroState.state++;
|
|
gIntroState.timer = 60;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void ExitTitlescreen(void) {
|
|
if (!gFadeControl.active) {
|
|
InitScreen(SCREEN_CHOOSE_FILE);
|
|
}
|
|
}
|
|
|
|
static u32 GetAdvanceState(void) {
|
|
u32 newKeys;
|
|
|
|
if (gFadeControl.active) {
|
|
return ADVANCE_NONE;
|
|
}
|
|
|
|
if (!gUnk_02000010.listenForKeyPresses) {
|
|
newKeys = 0;
|
|
} else {
|
|
newKeys = gUnk_03000FF0.newKeys & (A_BUTTON | START_BUTTON);
|
|
}
|
|
|
|
if (--gIntroState.timer == 0) {
|
|
return ADVANCE_TIMER_EXPIRED;
|
|
}
|
|
|
|
if (newKeys) {
|
|
return ADVANCE_KEY_PRESSED;
|
|
}
|
|
|
|
return ADVANCE_NONE;
|
|
}
|
|
|
|
static void UpdateLightRays(void) {
|
|
// Periodically rotate the palette to give a shimmeriming effect.
|
|
if ((gIntroState.counter & 0x7) == 0) {
|
|
gIntroState.lightRaysPaletteGroup++;
|
|
gIntroState.lightRaysPaletteGroup &= 0x3;
|
|
LoadPaletteGroup(5 + gIntroState.lightRaysPaletteGroup);
|
|
}
|
|
|
|
// Periodiccally update the transparency of the light rays.
|
|
if ((gIntroState.counter & 0x1F) == 0) {
|
|
gIntroState.lightRaysAlphaBlendIndex = (gIntroState.lightRaysAlphaBlendIndex + 1) & 0x7;
|
|
gScreen.controls.alphaBlend = sLightRaysAlphaBlends[gIntroState.lightRaysAlphaBlendIndex];
|
|
}
|
|
}
|