tmc/src/main.c

307 lines
7.1 KiB
C

#include "sound.h"
#include "functions.h"
#include "main.h"
#include "screen.h"
#include "common.h"
#include "save.h"
#include "message.h"
#include "interrupts.h"
extern u32 gRand;
extern void TitleTask(void);
extern void FileSelectTask(void);
extern void DemoTask(void);
extern void GameTask(void);
extern void GameOverTask(void);
extern void StaffrollTask(void);
extern void DebugTask(void);
static void InitOverlays(void);
static bool32 SoftResetKeysPressed(void);
static u32 CheckHeaderValid(void);
void (*const sTaskHandlers[])(void) = {
[TASK_TITLE] = TitleTask,
#ifdef DEMO_USA
[TASK_FILE_SELECT] = DemoTask,
#else
[TASK_FILE_SELECT] = FileSelectTask,
#endif
[TASK_GAME] = GameTask, [TASK_GAMEOVER] = GameOverTask,
[TASK_STAFFROLL] = StaffrollTask, [TASK_DEBUG] = DebugTask,
};
static void sub_080560B8(void);
void AgbMain(void) {
InitOverlays();
InitSound();
InitDMA();
InitSaveData();
sub_080560B8();
sub_08056208();
gUnk_02000010.field_0x4 = 193;
InitFade();
DmaCopy32(3, BG_PLTT, gPaletteBuffer, BG_PLTT_SIZE);
SetBrightness(1);
MessageInitialize();
ResetPalettes();
gRand = 0x1234567;
MemClear(&gMain, sizeof(gMain));
SetTask(TASK_TITLE);
while (1) {
ReadKeyInput();
if (SoftResetKeysPressed()) {
DoSoftReset();
}
switch (gMain.sleepStatus) {
case SLEEP:
SetSleepMode();
break;
case DEFAULT:
default:
if (gMain.pauseFrames != 0) {
do {
VBlankIntrWait();
} while (--gMain.pauseFrames);
}
if (gMain.pauseCount != 0) {
int cnt;
gMain.pauseCount--;
cnt = gMain.pauseInterval;
while (cnt-- > 0) {
VBlankIntrWait();
}
}
gMain.ticks.HWORD++;
sTaskHandlers[gMain.task]();
MessageMain();
FadeMain();
AudioMain();
break;
}
WaitForNextFrame();
}
}
// Interrupt handlers that are loaded into RAM.
extern u8 sub_080B197C[];
extern u8 gUnk_030056F0[];
extern u8 gUnk_02038560[];
extern u8 gUnk_080B2CD8[];
extern u8 gUnk_080B2CD8_2[];
extern u8 gUnk_080B2CD8_3[];
extern u8 gUnk_02000030[];
static void InitOverlays(void) {
u32 size;
DisableInterruptsAndDMA();
RegisterRamReset(RESET_ALL & ~RESET_EWRAM);
*(vu16*)BG_PLTT = 0x7FFF;
REG_WAITCNT = WAITCNT_PREFETCH_ENABLE | WAITCNT_WS0_S_1 | WAITCNT_WS0_N_3;
size = 0x3FFD0;
MemClear(gUnk_02000030, size);
size = (u32)gUnk_080B2CD8 - (u32)sub_080B197C;
if (size != 0) {
MemCopy(sub_080B197C, gUnk_030056F0, size);
}
size = (u32)gUnk_080B2CD8_2 - (u32)gUnk_080B2CD8_3;
if (size != 0) {
MemCopy(gUnk_080B2CD8_3, gUnk_02038560, size);
}
DispReset(0);
EnableVBlankIntr();
}
#define SOFT_RESET_KEYS (A_BUTTON | B_BUTTON | SELECT_BUTTON | START_BUTTON)
static bool32 SoftResetKeysPressed(void) {
return (gInput.heldKeys & SOFT_RESET_KEYS) == SOFT_RESET_KEYS;
}
void SetTask(u32 task) {
gMain.task = task;
gMain.state = 0;
gMain.substate = 0;
}
void DisableInterruptsAndDMA(void) {
REG_IME = 0;
REG_IE = 0;
REG_DISPSTAT = 0;
REG_IF = 0;
REG_IME = 0;
DmaStop(0);
DmaStop(1);
DmaStop(2);
DmaStop(3);
}
void DoSoftReset(void) {
DisableInterruptsAndDMA();
SoftReset(RESET_ALL & ~(RESET_EWRAM | RESET_SIO_REGS));
}
typedef struct {
int signature;
u8 saveFileId;
u8 msg_speed;
u8 brightness;
u8 language;
u8 name[6];
u8 invalid;
u8 initialized;
} Defaults;
const Defaults sDefaultSettings = {
.signature = SIGNATURE,
.saveFileId = 0,
.msg_speed = 1,
.brightness = 1,
#ifdef EU
.language = 2, // TODO in EU 2 is english?
#else
.language = GAME_LANGUAGE,
#endif
.name = "LINK",
.invalid = 0,
.initialized = 0,
};
// single misplaced ldr
NONMATCH("asm/non_matching/sub_080560B8.inc", static void sub_080560B8(void)) {
u32 temp;
u32 b;
if (!CheckHeaderValid()) {
switch ((s32)Read_02000000(gSaveHeader)) {
case 1:
if (CheckHeaderValid())
break;
case 0:
case -1:
default:
MemCopy(&sDefaultSettings, gSaveHeader, sizeof *gSaveHeader);
Write_02000000(gSaveHeader);
break;
}
}
temp = gUnk_02000010.signature ^ SIGNATURE;
b = BOOLCAST(temp);
if ((gUnk_02000010.field_0x4 != 0) && (gUnk_02000010.field_0x4 != 0xc1)) {
b = TRUE;
}
if (b) {
MemClear(&gUnk_02000010, sizeof gUnk_02000010);
gUnk_02000010.signature = SIGNATURE;
}
}
END_NONMATCH
static u32 CheckHeaderValid(void) {
if ((gSaveHeader->signature != SIGNATURE) || (gSaveHeader->saveFileId >= NUM_SAVE_SLOTS) ||
(gSaveHeader->msg_speed >= MAX_MSG_SPEED) || (gSaveHeader->brightness >= MAX_BRIGHTNESS)
#ifdef EU
|| (gSaveHeader->language <= GAME_LANGUAGE) || (gSaveHeader->language > NUM_LANGUAGES)
#else
|| (gSaveHeader->language != GAME_LANGUAGE)
#endif
|| (gSaveHeader->invalid))
return FALSE;
return TRUE;
}
void InitDMA(void) {
SoundReq(SONG_VSYNC_OFF);
gScreen._6d = gScreen._6c;
gScreen._6c = 0;
DmaStop(0);
DmaWait(0);
DmaWait(1);
DmaWait(2);
DmaWait(3);
}
void sub_08056208(void) {
SoundReq(SONG_VSYNC_ON);
gScreen._6c = gScreen._6d;
gScreen._6d = 0;
}
void sub_0805622C(void* a1, u32 a2, u32 a3) {
gScreen._70 = a1;
gScreen._74 = a2;
gScreen._78 = a3;
gScreen._6c = 1;
gUnk_03003DE4 ^= 1;
}
void sub_08056250(void) {
gScreen._6c = 0;
}
void SetSleepMode(void) {
u32 restore;
Main* m;
REG_DISPCNT = DISPCNT_FORCED_BLANK;
REG_KEYCNT = KEY_AND_INTR | L_BUTTON | R_BUTTON | SELECT_BUTTON;
REG_IME = 0;
restore = REG_IE;
REG_IE = INTR_FLAG_KEYPAD | INTR_FLAG_GAMEPAK;
REG_IME = 1;
Stop();
REG_IME = 0;
REG_IE = restore;
REG_IME = 1;
m = &gMain;
*(vu8*)&m->sleepStatus; // force a read
m->sleepStatus = 0;
}
// Convert AABB to screen coordinates and check if it's within the viewport
u32 CheckRegionOnScreen(u32 x0, u32 y0, u32 x1, u32 y1) {
u32 result;
u32 x = ((gRoomControls.scroll_x - gRoomControls.origin_x) - x0 + DISPLAY_WIDTH);
u32 y = ((gRoomControls.scroll_y - gRoomControls.origin_y) - y0 + DISPLAY_HEIGHT);
u32 a = x1 + DISPLAY_WIDTH;
u32 b = y1 + DISPLAY_HEIGHT;
if ((x < a) && (y < b))
result = TRUE;
else
result = FALSE;
return result;
}
// Iterate over array of AABBs and check if any fit on screen
u16 CheckRegionsOnScreen(u16* arr) {
u16* i;
for (i = arr; *i != 0xff; i += 5) {
if (CheckRegionOnScreen(i[1], i[2], i[3], i[4]))
return *i;
}
return 0xff;
}
void PlayerItemNulled2(void) {
DeleteThisEntity();
}
void PlayerItemNulled(void) {
DeleteThisEntity();
}