mirror of https://github.com/zeldaret/tmc.git
334 lines
9.1 KiB
C
334 lines
9.1 KiB
C
#include "global.h"
|
|
#include "audio.h"
|
|
#include "main.h"
|
|
#include "player.h"
|
|
#include "structures.h"
|
|
#include "save.h"
|
|
#include "textbox.h"
|
|
#include "functions.h"
|
|
#include "object.h"
|
|
#include "utils.h"
|
|
#include "npc.h"
|
|
#include "effects.h"
|
|
#include "screen.h"
|
|
#include "gba/m4a.h"
|
|
|
|
extern u8 gUnk_03003DE0;
|
|
extern u8 gUnk_03000C30;
|
|
|
|
extern u16* gUnk_02025EB0;
|
|
extern u16* gUnk_0200B650;
|
|
extern u8 gUpdateVisibleTiles;
|
|
extern u8 gUnk_03003DF0[];
|
|
extern u8 gUnk_03003BE0;
|
|
extern Entity* gUnk_03004040[3];
|
|
extern u16 gUnk_080B2CD8[];
|
|
extern u32 gUnk_03000FBC;
|
|
|
|
extern void sub_080ADD70();
|
|
extern void sub_0801C25C();
|
|
extern void UpdateDisplayControls();
|
|
extern void LoadResources();
|
|
extern void FadeVBlank();
|
|
extern void HandlePlayerLife();
|
|
extern void DoPlayerAction();
|
|
extern void sub_080171F0();
|
|
extern void sub_08078FB0();
|
|
extern u32 CheckDontUpdate();
|
|
extern void DrawEntity();
|
|
extern void sub_0807A050();
|
|
extern u32 sub_08079B24();
|
|
extern void sub_08079708();
|
|
extern void CreateSparkle();
|
|
extern void sub_080028E0(Entity*);
|
|
extern void sub_08078180(void);
|
|
extern void sub_0807B0C8(void);
|
|
extern void sub_0807A8D8(Entity*);
|
|
extern void sub_08077FEC(u32);
|
|
|
|
void gIntrMain(void);
|
|
|
|
struct {
|
|
u8 update;
|
|
u8 _0[0x1c];
|
|
struct OamData oam[0x80];
|
|
} extern gUnk_03000000;
|
|
|
|
struct {
|
|
u8 ready;
|
|
u16* src;
|
|
u16* dest;
|
|
u32 size;
|
|
} extern gUnk_02022730;
|
|
|
|
void sub_08016CA8(BgSettings* bg);
|
|
void sub_08016BF8(void);
|
|
void DispCtrlSet(void);
|
|
|
|
void DummyIntr(void) {
|
|
/* .. */
|
|
}
|
|
|
|
void EnableVBlankIntr(void) {
|
|
INTR_VECTOR = gIntrMain;
|
|
REG_DISPSTAT = DISPSTAT_VCOUNT_INTR | DISPSTAT_VBLANK_INTR | (80 << 8);
|
|
REG_IE = INTR_FLAG_VBLANK | INTR_FLAG_VCOUNT | INTR_FLAG_GAMEPAK;
|
|
REG_IME = 1;
|
|
}
|
|
|
|
void VBlankIntr(void) {
|
|
DmaStop(0);
|
|
m4aSoundVSync();
|
|
if (gMain.interruptFlag == 0) {
|
|
DispCtrlSet();
|
|
DmaCopy32(0, &gUnk_03000FBC, &gUnk_02022730, 16);
|
|
gMain.interruptFlag = 1;
|
|
}
|
|
sub_08016BF8();
|
|
INTR_CHECK |= 1;
|
|
}
|
|
|
|
void HBlankIntr(void) {
|
|
REG_DISPSTAT = DISPSTAT_VCOUNT_INTR | DISPSTAT_VBLANK_INTR | (80 << 8);
|
|
m4aSoundMain();
|
|
}
|
|
|
|
void sub_08016BF8(void) {
|
|
if (gUnk_02022730.ready) {
|
|
const u16* src = gUnk_02022730.src;
|
|
u16* dest = gUnk_02022730.dest;
|
|
s32 size, i = size = gUnk_02022730.size;
|
|
DmaSet(0, src, dest, size);
|
|
|
|
i = size & 0x3fff;
|
|
if (i == 0) {
|
|
i = 0x4000;
|
|
}
|
|
do {
|
|
*dest++ = *src++;
|
|
} while (--i > 0);
|
|
}
|
|
}
|
|
|
|
void UpdateDisplayControls(void) {
|
|
if (gUnk_03000000.update && (gScreen.lcd.displayControl & DISPCNT_OBJ_ON)) {
|
|
gUnk_03000000.update = 0;
|
|
DmaCopy32(3, &gUnk_03000000.oam, OAM, OAM_SIZE);
|
|
}
|
|
sub_08016CA8(&gScreen.bg0);
|
|
sub_08016CA8(&gScreen.bg1);
|
|
sub_08016CA8((BgSettings*)&gScreen.bg2);
|
|
sub_08016CA8((BgSettings*)&gScreen.bg3);
|
|
}
|
|
|
|
void sub_08016CA8(BgSettings* bg) {
|
|
if (bg->updated && bg->tilemap != NULL) {
|
|
u32 dest;
|
|
bg->updated = 0;
|
|
dest = bg->control;
|
|
DmaCopy32(3, bg->tilemap, ((dest << 3) & 0xF800) + VRAM, gUnk_080B2CD8[dest >> 14]);
|
|
}
|
|
}
|
|
|
|
ASM_FUNC("asm/dispCtrlSet.s", void DispCtrlSet(void));
|
|
|
|
// Load any resources that were requested with LoadResourceAsync
|
|
void LoadResources(void) {
|
|
if (gUnk_03003DE0 != 0) {
|
|
u8* buf = &gUnk_03000C30;
|
|
s32 i = gUnk_03003DE0;
|
|
gUnk_03003DE0 = 0;
|
|
do {
|
|
switch (*buf) {
|
|
case 0:
|
|
DmaCopy32(3, *(u32*)(buf + 4), *(u32*)(buf + 8), *(u16*)(buf + 2));
|
|
break;
|
|
case 1:
|
|
LZ77UnCompVram(*(void**)(buf + 4), *(u8**)(buf + 8));
|
|
break;
|
|
case 2:
|
|
DmaFill32(3, *(u32*)(buf + 4), *(u32*)(buf + 8), *(u16*)(buf + 2));
|
|
break;
|
|
}
|
|
buf += 12;
|
|
i--;
|
|
} while (0 < i);
|
|
}
|
|
}
|
|
|
|
void WaitForNextFrame(void) {
|
|
gMain.interruptFlag = 0;
|
|
VBlankIntrWait();
|
|
do {
|
|
// Our VBlankIntr will set this flag
|
|
} while (gMain.interruptFlag == 0);
|
|
|
|
sub_080ADD70();
|
|
sub_0801C25C();
|
|
UpdateDisplayControls();
|
|
LoadResources();
|
|
|
|
if (gUpdateVisibleTiles) {
|
|
gUpdateVisibleTiles = 0;
|
|
if (gUnk_02025EB0 != NULL)
|
|
// sizeof(BGBuffer) = 0x800, what are we omitting?
|
|
DmaCopy32(3, &gBG1Buffer, VRAM + (*gUnk_02025EB0 & 0x1f00) * 8, 0x5C0);
|
|
if (gUnk_0200B650 != NULL)
|
|
DmaCopy32(3, &gBG2Buffer, VRAM + (*gUnk_0200B650 & 0x1f00) * 8, 0x5C0);
|
|
}
|
|
FadeVBlank();
|
|
}
|
|
|
|
void PlayerUpdate(Entity* this) {
|
|
if (gSave.stats.effect != 0)
|
|
gPlayerState.flags |= 0x4000;
|
|
else
|
|
gPlayerState.flags &= ~0x4000;
|
|
|
|
if (CheckDontUpdate(this) == 0) {
|
|
if ((gPlayerState.flags & 0x80000) != 0) {
|
|
sub_08077B20();
|
|
if ((gPlayerState.flags & 0x200000) != 0) {
|
|
gPlayerState.playerAction = PLAYER_ROLL;
|
|
gPlayerState.flags &= ~0x80000;
|
|
gPlayerState.hurtBlinkSpeed = 240;
|
|
COLLISION_ON(this);
|
|
} else {
|
|
COLLISION_OFF(this);
|
|
gPlayerState.field_0xa8 = 0xf;
|
|
}
|
|
}
|
|
HandlePlayerLife(this);
|
|
DoPlayerAction(this);
|
|
if ((this->z.WORD == 0) && (this->action == 1 || this->action == 9))
|
|
sub_08008790(this, 8);
|
|
sub_080171F0();
|
|
}
|
|
sub_08078FB0(this);
|
|
DrawEntity(this);
|
|
sub_0807A050();
|
|
}
|
|
|
|
// Responsible for some life things like low health beep and initiating the death sequence
|
|
#ifdef EU
|
|
ASM_FUNC("asm/non_matching/eu/HandlePlayerLife.inc", void HandlePlayerLife(Entity* this));
|
|
#else
|
|
void HandlePlayerLife(Entity* this) {
|
|
u32 temp;
|
|
|
|
gUnk_0200AF00.filler25[10] = 0;
|
|
gUnk_0200AF00.filler25[8] = 0;
|
|
gUnk_0200AF00.filler25[9] = 0;
|
|
|
|
if ((gPlayerEntity.bitfield & 0x80) && (gPlayerEntity.iframes > 0))
|
|
SoundReq(SFX_86);
|
|
|
|
gPlayerState.flags &= ~(0x2000000 | 0x200);
|
|
if (gPlayerState.flags & PL_BURNING)
|
|
ResetPlayer();
|
|
if ((gPlayerState.flags & 0x400000) && !gPlayerState.field_0xa0[0])
|
|
sub_0807A108();
|
|
if (sub_08079B24() == 0)
|
|
sub_08079708(this);
|
|
|
|
gUnk_03003DF0[0] = 0;
|
|
if (gPlayerState.field_0x27[0] != 0)
|
|
gPlayerState.field_0x27[0]--;
|
|
|
|
gPlayerState.field_0xa9 = gPlayerState.field_0xa8;
|
|
gPlayerState.field_0xa8 = 0;
|
|
if (gPlayerState.hurtType[0x4a] != 0) {
|
|
gPlayerState.hurtType[0x4a]--;
|
|
return;
|
|
}
|
|
|
|
if ((gPlayerState.controlMode != CONTROL_ENABLED) || (gMessage.doTextBox & 0x7f))
|
|
return;
|
|
|
|
gRoomVars.unk2 = gMessage.doTextBox & 0x7f;
|
|
temp = gSave.stats.maxHealth / 4;
|
|
if (temp > 24)
|
|
temp = 24;
|
|
if (temp < 8)
|
|
temp = 8;
|
|
|
|
if (gSave.stats.health <= temp) {
|
|
gRoomVars.unk2 = 1;
|
|
if ((gUnk_0200AF00.filler0[1] == 0) && gScreenTransition.frameCount % 90 == 0) {
|
|
EnqueueSFX(SFX_LOW_HEALTH);
|
|
}
|
|
}
|
|
|
|
if (gSave.stats.charm == 0) {
|
|
gSave.stats.charmTimer = 0;
|
|
} else if ((gSave.stats.charmTimer == 0) || --gSave.stats.charmTimer == 0) {
|
|
gSave.stats.charm = 0;
|
|
SoundReq(SFX_ICE_BLOCK_MELT);
|
|
}
|
|
|
|
if (gSave.stats.unkB == 0) {
|
|
gSave.stats.unkTimer = 0;
|
|
} else if ((gSave.stats.unkTimer == 0) || (--gSave.stats.unkTimer == 0)) {
|
|
gSave.stats.unkB = 0;
|
|
SoundReq(SFX_140);
|
|
} else if ((gSave.stats.unkTimer & 0xf) == 0) {
|
|
CreateSparkle(this);
|
|
}
|
|
|
|
if (gSave.stats.effect == 0) {
|
|
gSave.stats.effectTimer = 0;
|
|
} else if ((gSave.stats.effectTimer == 0) || --gSave.stats.effectTimer == 0) {
|
|
gSave.stats.effect = 0;
|
|
} else if ((gSave.stats.effectTimer & 0x3f) == 0) {
|
|
CreateFx(this, (FX_RED_AURA - 1) + gSave.stats.effect, 0);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
void sub_080171F0(void) {
|
|
if (gPlayerState.field_0x1a[0] != 0)
|
|
ResetPlayer();
|
|
if (gPlayerState.field_0x14 != 0)
|
|
gPlayerState.field_0x14--;
|
|
if (gPlayerEntity.field_0x7a.HWORD != 0)
|
|
gPlayerEntity.field_0x7a.HWORD--;
|
|
|
|
gPlayerEntity.bitfield &= ~0x80;
|
|
if (gPlayerEntity.action != PLAYER_DROWN)
|
|
COPY_FLAG_FROM_TO(gPlayerState.flags, 0x2, 0x10000);
|
|
|
|
gPlayerState.flags &= ~2;
|
|
sub_080028E0(&gPlayerEntity);
|
|
|
|
if (gPlayerState.flags & 0x400000)
|
|
gUnk_0200AF00.filler25[10] = 1;
|
|
|
|
sub_08078180();
|
|
gPlayerState.field_0x7 &= ~0x80;
|
|
gPlayerState.field_0xa &= 0xf;
|
|
gPlayerState.keepFacing &= ~0x80;
|
|
gPlayerState.field_0x1a[0] = 0;
|
|
gPlayerState.field_0x80 = 0;
|
|
gPlayerState.field_0xaa = 0;
|
|
MemClear(&gUnk_03003BE0, 0x8c);
|
|
gPlayerEntity.spriteOffsetY = gPlayerState.field_0x3f;
|
|
gPlayerState.field_0x3f = 0;
|
|
sub_0807B0C8();
|
|
|
|
if (gPlayerState.flags & 0x400000)
|
|
gUnk_03004040[0]->spriteOffsetY = gUnk_03004040[1]->spriteOffsetY = gUnk_03004040[2]->spriteOffsetY = 0;
|
|
|
|
if (gPlayerEntity.action == PLAYER_08072F34)
|
|
gPlayerState.flags |= 0x20000000;
|
|
else
|
|
gPlayerState.flags &= ~0x20000000;
|
|
|
|
sub_0807A8D8(&gPlayerEntity);
|
|
if (gPlayerState.jumpStatus & 0xc0)
|
|
gPlayerEntity.iframes = 0xfe;
|
|
|
|
if (gPlayerEntity.action != PLAYER_ROOMTRANSITION) {
|
|
sub_08077FEC(gPlayerEntity.action);
|
|
}
|
|
}
|