tmc/src/overworld.c

1158 lines
33 KiB
C

#include "global.h"
#include "audio.h"
#include "screen.h"
#include "entity.h"
#include "player.h"
#include "room.h"
#include "main.h"
#include "flags.h"
#include "save.h"
#include "utils.h"
#include "fileScreen.h"
#include "menu.h"
#include "functions.h"
#include "structures.h"
#include "area.h"
#include "textbox.h"
#include "overworld.h"
extern u32 gUnk_03003FC0;
extern u8 gUnk_080FCA84[];
extern u8 gUnk_080FCAC8[];
extern u32 gUsedPalettes;
extern u8 gUnk_02024090[];
extern u16 gUnk_080FCAD6[];
extern void** gAreaTilesets[];
extern void** gAreaRoomMaps[];
extern void* gAreaMetatiles[];
extern void* gUnk_080B755C[];
extern void** gExitLists[];
extern void** gAreaTable[];
extern u8 gUnk_080FCAF8[];
extern u16 gUnk_020178E0[];
void sub_080520C4();
void SetPopupState();
u32 sub_08052724();
void CleanUpGFXSlots();
void sub_080ADE24();
void sub_0801C370(u32);
void sub_0801AE44(u32);
void sub_0801862C(void);
void sub_08078160(u32);
void SetPlayerEventPriority(void);
RoomResInfo* GetCurrentRoomInfo(void);
void sub_08049D30(void);
void InitScriptData(void);
void sub_08054524(void);
void sub_080186D4(void);
void sub_0806F364(void);
void sub_08052FF4(u32 area, u32 room);
void sub_0807C860(void);
void sub_0807C740(void);
void sub_080197AC(void);
void sub_08053390(void);
static u32 StairsAreValid();
static void ClearFlagArray(const u16*);
static void DummyHandler(u32* a1);
static void sub_08053434(u32* a1);
static void sub_080534E4(u32* a1);
static void InitAllRoomResInfo(void);
static void InitRoomResInfo(RoomResInfo* info, RoomHeader* hdr, u32 area, u32 room);
static void sub_080532E4(void);
static void sub_08053460(void);
typedef struct {
u16* dest;
void* gfx_dest;
void* buffer_loc;
u32 _c;
u16 gfx_src;
u8 width;
u8 right_align : 1;
u8 sm_border : 1;
u8 unused : 1;
u8 draw_border : 1;
u8 border_type : 4;
u8 fill_type;
u8 _15;
u8 _16;
u8 stylized;
} Font;
typedef struct {
u8 dest_off[8];
u8 _8;
u8 right_align;
u16 _a;
} PopupOption;
extern void CreateDialogBox();
void sub_0805212C(void) {
if (gFadeControl.active)
return;
if (gMain.field_0x5 == 0) {
if (gMenu.focusCoords[0] >= 38) {
gMenu.focusCoords[0]--;
} else {
gMenu.transitionTimer--;
if (gMenu.transitionTimer == 0) {
sub_080520C4(2);
#if defined(DEMO_USA) || defined(DEMO_JP)
SoundReq(SONG_VOL_FADE_OUT);
DoFade(7, 4);
#else
SetPopupState(0, 0);
gScreen.lcd.displayControl |= DISPCNT_BG1_ON | DISPCNT_BG2_ON;
gFadeControl.mask = 0x0000ffff;
DoFade(4, 16);
#endif
}
}
} else {
gMain.field_0x5--;
}
}
#if defined(DEMO_USA) || defined(DEMO_JP)
void sub_080521A0(void) {
if (gFadeControl.active == 0) {
DoSoftReset();
}
}
#else
void sub_080521A0(void) {
s32 temp3;
u32 temp2;
if (gFadeControl.active)
return;
switch (gMenu.menuType) {
case 0:
gMenu.transitionTimer = 30;
gMenu.field_0x3 = 0;
sub_080A7114(1);
SetPopupState(0, 0);
gFadeControl.mask = 0xffffffff;
return;
case 1:
if (gMenu.transitionTimer == 0) {
u32 temp = gMenu.field_0x3;
switch (gInput.newKeys) {
case DPAD_UP:
temp = 0;
break;
case DPAD_DOWN:
temp = 1;
break;
case A_BUTTON:
if (gMenu.field_0x3 != 0) {
temp2 = 4;
} else {
CreateDialogBox(8, 0);
temp2 = 2;
}
gMenu.transitionTimer = 60;
sub_080A7114(temp2);
SoundReq(SFX_TEXTBOX_SELECT);
break;
}
if (gMenu.field_0x3 != temp) {
gMenu.field_0x3 = temp;
SetPopupState(0, temp);
SoundReq(SFX_TEXTBOX_CHOICE);
}
return;
}
gMenu.transitionTimer--;
return;
case 2:
temp3 = HandleSave(0);
gMenu.field_0x0 = temp3;
switch (temp3) {
case 1:
sub_080A7114(4);
break;
case -1:
gMenu.transitionTimer = 60;
CreateDialogBox(9, 0);
sub_080A7114(3);
break;
}
return;
case 3:
if (gMenu.transitionTimer != 0) {
gMenu.transitionTimer--;
} else if (gInput.newKeys & (A_BUTTON | B_BUTTON | START_BUTTON)) {
sub_080A7114(0);
}
return;
case 4:
default:
gScreen.lcd.displayControl &= ~DISPCNT_BG1_ON;
sub_08050384();
sub_080520C4(3);
return;
}
}
#endif
void sub_080522F4(void) {
switch (gMenu.menuType) {
case 0x0:
gMenu.transitionTimer = 0x1e;
gMenu.field_0x3 = 0;
sub_080A7114(1);
SetPopupState(1, 0);
return;
case 0x1:
gScreen.lcd.displayControl |= DISPCNT_BG1_ON;
if (gMenu.transitionTimer != 0) {
gMenu.transitionTimer--;
return;
} else {
u32 temp = gMenu.field_0x3;
switch (gInput.newKeys) {
case DPAD_UP:
temp = 0;
break;
case DPAD_DOWN:
temp = 1;
break;
case A_BUTTON:
sub_080A7114(2);
SoundReq(SFX_TEXTBOX_SELECT);
if (temp == 0) {
DoFade(5, 8);
} else {
DoFade(7, 8);
}
break;
}
if (gMenu.field_0x3 != temp) {
gMenu.field_0x3 = temp;
SetPopupState(1, temp);
SoundReq(SFX_TEXTBOX_CHOICE);
}
}
return;
case 0x2:
default:
if (gFadeControl.active == 0) {
if (gMenu.field_0x3 == 0) {
InitScreen(2);
} else {
DoSoftReset();
}
}
return;
}
}
void nullsub_107(void) {
}
void DrawGameOverText(void) {
static const u8 sOffsets[] = {
48, 68, 88, 108, 137, 156, 174, 192,
};
u32 i;
gOamCmd._4 = 0;
gOamCmd._6 = 0;
gOamCmd._8 = 0x8600;
gOamCmd.y = gMenu.focusCoords[0];
for (i = 0; i < 8; ++i) {
gOamCmd.x = sOffsets[i];
#ifdef EU
sub_080ADA14(0x1fc, i);
#else
sub_080ADA14(0x1fd, i);
#endif
}
}
void SetPopupState(u32 type, u32 choice_idx) {
static const Font sDefaultFont = {
.dest = gBG1Buffer,
.gfx_dest = (u16*)0x06006000,
.buffer_loc = gTextGfxBuffer,
._c = 0,
.gfx_src = 0xD300,
.width = 0xE0,
.right_align = 0,
.sm_border = 0,
.unused = 0,
.draw_border = 0,
.border_type = 0,
.fill_type = 6,
._15 = 4,
._16 = 1,
.stylized = 0,
};
static const PopupOption sPopupOptions[] = {
{ { 11, 11, 11, 10, 11, 10, 10, 0 }, 8, 0, 16 },
{ { 10, 11, 11, 9, 11, 9, 9, 0 }, 8, 0, 17 },
{ { 15, 15, 15, 15, 15, 15, 15, 0 }, 5, 1, 13 },
};
Font font;
const PopupOption* opt;
u32 fakematch;
MemClear(gBG1Buffer, sizeof gBG1Buffer);
gUnk_020227E8[0]._0.WORD = 0xf;
gUnk_020227E8[1]._0.WORD = 0xf;
gUnk_020227E8[2]._0.WORD = 0xf;
gUnk_020227E8[3]._0.WORD = 0xf;
*(&gUnk_020227E8[choice_idx]._0.BYTES.byte0 + 1) = fakematch = 1;
MemCopy(&sDefaultFont, &font, sizeof font);
opt = &sPopupOptions[type];
font.dest = sDefaultFont.dest + (opt->dest_off[gSaveHeader->gameLanguage] + opt->_8 * 32);
font.right_align = opt->right_align;
sub_0805F46C(opt->_a, &font);
gScreen.bg1.updated = fakematch;
}
void InitializePlayer(void) {
static const u8 sPlayerSpawnStates[] = {
[PL_SPAWN_DEFAULT] = PLAYER_INIT,
[PL_SPAWN_MINISH] = PLAYER_MINISH,
[PL_SPAWN_DROP] = PLAYER_INIT,
[PL_SPAWN_WALKING] = PLAYER_ROOMTRANSITION,
[PL_SPAWN_STEP_IN] = PLAYER_080720DC,
[PL_SPAWN_SPECIAL] = PLAYER_08074C44,
[PL_SPAWN_DROP_MINISH] = PLAYER_MINISH,
[PL_SPAWN_STAIRS_ASCEND] = PLAYER_USEENTRANCE,
[PL_SPAWN_STAIRS_DESCEND] = PLAYER_USEENTRANCE,
[PL_SPAWN_9] = PLAYER_MINISH,
[PL_SPAWN_PARACHUTE_FORWARD] = PLAYER_WARP,
[PL_SPAWN_PARACHUTE_UP] = PLAYER_WARP,
[PL_SPAWN_FAST_TRAVEL] = PLAYER_WARP,
};
Entity* pl;
sub_080784C8();
MemClear(&gUnk_03000B80, sizeof gUnk_03000B80);
MemClear(&gPlayerState, sizeof gPlayerState);
MemFill32(0xffffffff, &gPlayerState.hurtType, sizeof gPlayerState.hurtType);
MemClear(&gPlayerEntity, sizeof gPlayerEntity);
pl = &gPlayerEntity;
gRoomControls.cameraTarget = pl;
gPlayerState.playerAction = sPlayerSpawnStates[gScreenTransition.player_status.spawn_type];
if (!CheckGlobalFlag(EZERO_1ST)) {
gPlayerState.flags |= PL_NO_CAP;
}
switch (gScreenTransition.player_status.spawn_type) {
case PL_SPAWN_DROP:
case PL_SPAWN_DROP_MINISH:
pl->z.HALF.HI = -0xc0;
break;
case PL_SPAWN_STEP_IN:
gPlayerState.field_0x34[4] = 16;
pl->direction = Direction8FromAnimationState(gScreenTransition.player_status.start_anim);
case PL_SPAWN_WALKING:
pl->speed = 224;
break;
case PL_SPAWN_STAIRS_ASCEND:
case PL_SPAWN_STAIRS_DESCEND:
gPlayerState.field_0x34[4] = 1;
gPlayerState.field_0x34[5] = gScreenTransition.player_status.spawn_type;
break;
case PL_SPAWN_PARACHUTE_FORWARD:
gPlayerState.field_0x34[4] = 1;
break;
case PL_SPAWN_PARACHUTE_UP:
gPlayerState.field_0x34[4] = 3;
break;
case PL_SPAWN_FAST_TRAVEL:
gPlayerState.field_0x34[4] = 4;
}
pl->kind = PLAYER;
pl->flags |= ENT_COLLIDE | ENT_20;
pl->spritePriority.b0 = 4;
pl->health = gSave.stats.health;
pl->x.HALF.HI = gScreenTransition.player_status.start_pos.HALF.x;
pl->y.HALF.HI = gScreenTransition.player_status.start_pos.HALF.y;
pl->animationState = gScreenTransition.player_status.start_anim;
pl->collisionLayer = gScreenTransition.player_status.layer;
UpdateSpriteForCollisionLayer(pl);
AppendEntityToList(pl, 1);
RegisterPlayerHitbox();
}
bool32 CheckIsOverworld(void) {
#ifdef EU
return gArea.areaMetadata == 0x01;
#else
return gArea.areaMetadata == 0x81;
#endif
}
bool32 sub_08052638(u32 r0) {
#if EU
return gAreaMetadata[r0].flags == 0x01;
#else
return gAreaMetadata[r0].flags == 0x81;
#endif
}
#ifndef EU
u32 sub_08052654(void) {
return (gArea.areaMetadata >> 7) & 1;
}
#endif
u32 CheckIsDungeon(void) {
return (gArea.areaMetadata >> 2) & 1;
}
u32 CheckIsInteriorWithEnemies(void) {
return (gArea.areaMetadata >> 4) & 1;
}
u32 CheckIsInteriorNoEnemies(void) {
return (gArea.areaMetadata >> 6) & 1;
}
u32 CheckHasMap(void) {
return (gArea.areaMetadata >> 3) & 1;
}
s32 ModHealth(s32 deltaHealth) {
s32 newHealth;
newHealth = gStats.health + deltaHealth;
if (newHealth < 0) {
newHealth = 0;
}
if (gStats.maxHealth < newHealth) {
newHealth = (u32)gStats.maxHealth;
}
gStats.health = newHealth;
gPlayerEntity.health = newHealth;
return newHealth;
}
void ModRupees(s32 rupeeDelta) {
s32 newRupeeCount;
Stats* s = &gStats;
newRupeeCount = s->rupees + rupeeDelta;
if (newRupeeCount < 0) {
newRupeeCount = 0;
} else {
if (newRupeeCount > gWalletSizes[s->walletType * 2]) {
newRupeeCount = gWalletSizes[s->walletType * 2];
}
}
s->rupees = newRupeeCount;
}
void sub_080526F8(s32 a1) {
if (sub_08052724()) {
u8* p = &gSave.unk45C[gArea.dungeon_idx];
if (*p + a1 < 0)
*p = 0;
else
*p += a1;
}
}
u32 sub_08052724(void) {
return (gArea.areaMetadata >> 1) & 1;
}
u32 HasDungeonMap(void) {
u32 tmp;
if (sub_08052724())
tmp = gSave.unk45C[gArea.dungeon_idx];
return tmp ? 1 : 0;
}
u32 HasDungeonCompass(void) {
u32 tmp;
if (sub_08052724())
tmp = gSave.unk46C[gArea.dungeon_idx] & 4;
return tmp ? 1 : 0;
}
u32 HasDungeonBigKey(void) {
if (!sub_08052724())
return 0;
return (gSave.unk46C[gArea.dungeon_idx] >> 1) & 1;
}
u32 HasDungeonSmallKey(void) {
u32 tmp;
if (!sub_08052724())
return 0;
return gSave.unk46C[gArea.dungeon_idx] & 1;
}
void sub_080527FC(u32 a1, u32 a2) {
sub_08053320();
#ifndef EU
CleanUpGFXSlots();
#endif
sub_080ADE24();
sub_0801C370(1);
sub_0801AE44(a1);
MemCopy(gUnk_02024090, gPaletteBuffer, 1024);
gUsedPalettes = -1;
}
void sub_0805283C(void) {
gArea.pMusicIndex = gAreaMetadata[gRoomControls.areaID]._3;
if (CheckLocalFlagByBank(FLAG_BANK_10, LV6_KANE_START)) {
gArea.pMusicIndex = BGM_FIGHT_THEME2;
}
}
#ifndef EU
void sub_08052878(void) {
gArea.musicIndex = gArea.pMusicIndex;
SoundReq(SONG_STOP_ALL);
}
static void sub_0805289C(void) {
gArea.pMusicIndex = gArea.musicIndex;
}
#endif
u32 sub_080528B4(void) {
if (gScreenTransition.field_0x4[1]) {
InitFade();
gMain.funcIndex = 3;
gMain.transition = 0;
DoFade(5, 8);
SoundReq(SONG_STOP_BGM);
return 1;
}
return 0;
}
void RoomExitCallback(void) {
if (gArea.transitionManager != NULL && gArea.onExit != NULL)
gArea.onExit(gArea.transitionManager);
}
u32 HandleRoomExit(void) {
if (gScreenTransition.transitioningOut && gSave.stats.health != 0 && gPlayerState.framestate != PL_STATE_DIE) {
if (StairsAreValid()) {
gScreenTransition.transitioningOut = 0;
return 0;
}
switch (gScreenTransition.transitionType) {
case TRANSITION_CUT:
DoFade(13, 8);
break;
case TRANSITION_CUT_FAST:
DoFade(13, 3);
break;
case TRANSITION_FADE_WHITE_SLOW:
DoFade(7, 4);
break;
case TRANSITION_FADE_BLACK_SLOW:
DoFade(5, 4);
break;
case TRANSITION_FADE_BLACK:
DoFade(5, 16);
break;
case TRANSITION_FADE_BLACK_FAST:
DoFade(5, 256);
break;
case TRANSITION_7:
case TRANSITION_FADE_WHITE_FAST:
DoFade(7, 256);
break;
default:
DoFade(7, 16);
break;
}
RoomExitCallback();
gMain.transition = 3;
*(&gMain.pauseInterval + 1) = 1;
return 1;
}
return 0;
}
static u32 StairsAreValid(void) {
static const u16 sStairTypes[] = { 0x91, PL_SPAWN_STAIRS_ASCEND, 0x92, PL_SPAWN_STAIRS_DESCEND,
0x93, PL_SPAWN_STAIRS_ASCEND, 0x94, PL_SPAWN_STAIRS_DESCEND,
0x95, PL_SPAWN_STAIRS_ASCEND, 0x96, PL_SPAWN_STAIRS_DESCEND,
0x97, PL_SPAWN_STAIRS_ASCEND, 0x98, PL_SPAWN_STAIRS_DESCEND,
0 };
const u16* i;
u32 tgt = gScreenTransition.stairs_idx;
for (i = sStairTypes; i[0] != 0; i += 2) {
if (tgt == i[0]) {
gPlayerState.playerAction = 30;
gPlayerState.field_0x38 = 0;
gPlayerState.field_0x39 = i[1];
if (!gScreenTransition.player_status.spawn_type)
gScreenTransition.player_status.spawn_type = i[1];
return 1;
}
}
return 0;
}
void InitParachuteRoom(void) {
gScreenTransition.transitioningOut = 1;
gScreenTransition.player_status.start_pos.HALF.x = (gPlayerEntity.x.HALF.HI - gRoomControls.roomOriginX) & 0x3F8;
gScreenTransition.player_status.start_pos.HALF.y = (gPlayerEntity.y.HALF.HI - gRoomControls.roomOriginY) & 0x3F8;
gScreenTransition.player_status.start_anim = 4;
gScreenTransition.player_status.spawn_type = PL_SPAWN_PARACHUTE_FORWARD;
gScreenTransition.player_status.area_next = gRoomControls.areaID;
gScreenTransition.player_status.room_next = gRoomControls.roomID - 1;
}
static void HandleRoomEnter(void) {
switch (gScreenTransition.transitionType) {
case TRANSITION_CUT:
DoFade(12, 8);
break;
case TRANSITION_CUT_FAST:
DoFade(12, 3);
break;
case TRANSITION_FADE_WHITE_SLOW:
DoFade(6, 4);
break;
case TRANSITION_3:
break;
case TRANSITION_FADE_BLACK_FAST:
DoFade(5, 256);
break;
case TRANSITION_7:
DoFade(7, 256);
break;
case TRANSITION_FADE_BLACK:
DoFade(4, 16);
break;
case TRANSITION_FADE_WHITE_FAST:
DoFade(6, 8);
break;
default:
sub_080500F4(16);
break;
}
}
u32 sub_08052B24(void) {
s32 tmp = PL_STATE_WALK;
if (!(gInput.heldKeys & SELECT_BUTTON) || gPlayerState.controlMode != CONTROL_ENABLED || gUnk_02034490[0] ||
gUnk_0200AF00.filler0[1])
return 0;
if ((gPlayerState.flags & 0x118) || (gPlayerState.framestate_last > tmp) || gPlayerState.item ||
gPlayerEntity.field_0x7a.HWORD)
return 0;
if ((gPlayerEntity.z.HALF.HI & 0x8000) && !gPlayerState.field_0xa)
return 0;
sub_0801862C();
sub_08078160(19);
SetPlayerEventPriority();
return 1;
}
void DisplayEzloMessage(void) {
u32 height;
u32 idx;
#if defined(JP) || defined(EU)
idx = 0x10;
#else
idx = 0x11;
#endif
if (gScreenTransition.player_status.field_0x24[idx] == 0) {
height = gPlayerEntity.y.HALF.HI - gRoomControls.roomScrollY > 96 ? 1 : 13;
} else {
height = gScreenTransition.player_status.field_0x24[idx];
}
MessageAtHeight(gScreenTransition.hint_idx, height);
}
#if defined(USA) || defined(DEMO_USA) || defined(DEMO_JP)
void sub_08052BF8(void) {
Entity* e = NULL;
if (gScreenTransition.player_status.field_0x24[13])
return;
gScreenTransition.player_status.field_0x24[13] = 1;
#ifndef DEMO_JP
gScreenTransition.player_status.field_0x24[10] = gArea.locationIndex;
#endif
e = (Entity*)GetEmptyManager();
if (e == NULL)
return;
e->kind = MANAGER;
e->id = 15;
e->type = 15;
AppendEntityToList(e, 0);
}
#endif
void sub_08052C3C(void) {
if (gArea.field_0x18 == 0)
gArea.unk1A = gArea.field_0x18;
if (gArea.unk1A) {
gArea.unk1A--;
gArea.field_0x18 = 0;
}
}
void sub_08052C5C(void) {
if (!CheckIsInteriorNoEnemies()) {
if (CheckIsOverworld()) {
gScreenTransition.player_status.field_0x20 = gPlayerEntity.x.HALF_U.HI;
gScreenTransition.player_status.field_0x22 = gPlayerEntity.y.HALF_U.HI;
} else if (CheckIsDungeon()) {
gScreenTransition.player_status.field_0x1c = gPlayerEntity.x.HALF.HI;
gScreenTransition.player_status.field_0x1e = gPlayerEntity.y.HALF.HI;
}
}
}
void sub_08052CA4(u32 area, u32 room, u32 x, u32 y) {
RoomHeader* hdr = gAreaRoomHeaders[area] + room;
gScreenTransition.player_status.field_0x20 = hdr->map_x + x;
gScreenTransition.player_status.field_0x22 = hdr->map_y + y;
}
void sub_08052CD0(u32 area, u32 room, u32 x, u32 y) {
RoomHeader* hdr = gAreaRoomHeaders[area] + room;
gScreenTransition.player_status.field_0x1c = hdr->map_x + x;
gScreenTransition.player_status.field_0x1e = hdr->map_y + y;
}
void sub_08052CFC(void) {
AreaHeader* a_hdr = NULL;
MemClear(&gArea, sizeof gArea);
a_hdr = &gAreaMetadata[gRoomControls.areaID];
gArea.areaMetadata = a_hdr->flags;
gArea.locationIndex = a_hdr->location;
gArea.dungeon_idx = a_hdr->location - 23;
gArea.localFlagOffset = gLocalFlagBanks[a_hdr->flag_bank];
gArea.filler[0] = a_hdr->flag_bank;
gArea.unk1A = 180;
gArea.unk_0a = 256;
HandleRoomEnter();
InitAllRoomResInfo();
}
u32 GetFlagBankOffset(u32 idx) {
AreaHeader* a_hdr = &gAreaMetadata[idx];
return gLocalFlagBanks[a_hdr->flag_bank];
}
void RegisterTransitionManager(void* mgr, void (*onEnter)(), void (*onExit)()) {
if (gMain.transition != 7) {
gArea.transitionManager = mgr;
gArea.onEnter = onEnter;
gArea.onExit = onExit;
}
}
static void InitAllRoomResInfo(void) {
RoomHeader* r_hdr = gAreaRoomHeaders[gRoomControls.areaID];
RoomResInfo* info = gArea.roomResInfos;
u32 i;
for (i = 0; i < MAX_ROOMS && *(u16*)r_hdr != 0xFFFF; i++, r_hdr++) {
if (r_hdr->tileset_id != 0xFFFF)
InitRoomResInfo(info, r_hdr, gRoomControls.areaID, i);
info++;
}
gArea.pCurrentRoomInfo = GetCurrentRoomInfo();
}
static void InitRoomResInfo(RoomResInfo* info, RoomHeader* r_hdr, u32 area, u32 room) {
info->map_x = r_hdr->map_x;
info->map_y = r_hdr->map_y;
info->pixel_width = r_hdr->pixel_width;
info->pixel_height = r_hdr->pixel_height;
info->tileset = *(gAreaTilesets[area] + r_hdr->tileset_id);
info->map = *(gAreaRoomMaps[area] + room);
info->metatiles = gAreaMetatiles[area];
info->bg_anim = gUnk_080B755C[area];
info->exits = *(gExitLists[area] + room);
if (gAreaTable[area] != NULL) {
info->properties = *(gAreaTable[area] + room);
}
}
RoomResInfo* GetCurrentRoomInfo(void) {
return &gArea.roomResInfos[gRoomControls.roomID];
}
void sub_08052EA0(void) {
MemClear(&gRoomVars, sizeof gRoomVars);
gRoomVars.unk_10[0] = -1;
gRoomVars.unk_10[1] = gRoomVars.unk_10[0];
gRoomVars.unk_10[2] = gRoomVars.unk_10[0];
gRoomVars.unk_10[3] = gRoomVars.unk_10[0];
gRoomVars.lightLevel = 256;
gArea.locationIndex = gAreaMetadata[gRoomControls.areaID].location;
sub_08049D30();
InitScriptData();
sub_08054524();
sub_080186D4();
sub_0806F364();
UpdateGlobalProgress();
}
static u32 sub_08052EF4(s32 idx) {
AreaHeader* a_hdr = NULL;
u32 i = idx < 0 ? gRoomControls.areaID : idx;
a_hdr = &gAreaMetadata[i];
return gLocalFlagBanks[a_hdr->flag_bank];
}
void sub_08052F1C(void) {
u32 x, y;
LinkedList* ll;
Entity* e;
if ((gArea.filler3[1] & 1) == 0 || !gRoomVars.field_0x0)
return;
y = 0;
x = 0;
// WTF?
switch (gRoomControls.unk_10) {
case 0:
y = gArea.pCurrentRoomInfo->pixel_height;
case 1:
y = gArea.pCurrentRoomInfo->pixel_height;
case 2:
y = gArea.pCurrentRoomInfo->pixel_height;
case 3:
x = gArea.pCurrentRoomInfo->pixel_width;
}
gArea.pCurrentRoomInfo->map_x += x;
gArea.pCurrentRoomInfo->map_y += y;
gRoomControls.roomOriginX += x;
gRoomControls.roomOriginY += y;
gRoomControls.roomScrollX += x;
gRoomControls.roomScrollY += y;
ll = gEntityLists;
do {
for (e = ll->first; e != (Entity*)ll; e = e->next) {
if (e->kind != MANAGER) {
e->x.HALF.HI += x;
e->y.HALF.HI += y;
}
}
} while (++ll < gEntityLists + 9);
}
void sub_08052FD8(u32 area, u32 room) {
sub_08052FF4(area, room);
gRoomControls.cameraTarget = NULL;
sub_0807C860();
sub_0807C740();
}
void sub_08052FF4(u32 area, u32 room) {
RoomHeader* r_hdr = NULL;
sub_08080668();
sub_080197AC();
gRoomControls.areaID = area;
gRoomControls.roomID = room;
gScreen.lcd.displayControl = 0x1740;
MemClear(&gArea.currentRoomInfo, sizeof gArea.currentRoomInfo);
gArea.pCurrentRoomInfo = &gArea.currentRoomInfo;
r_hdr = gAreaRoomHeaders[area] + room;
gArea.currentRoomInfo.map_x = r_hdr->map_x;
gArea.currentRoomInfo.map_y = r_hdr->map_y;
gArea.currentRoomInfo.pixel_width = r_hdr->pixel_width;
gArea.currentRoomInfo.pixel_height = r_hdr->pixel_height;
gArea.currentRoomInfo.tileset = *(gAreaTilesets[area] + r_hdr->tileset_id);
gArea.currentRoomInfo.map = *(gAreaRoomMaps[area] + room);
gArea.currentRoomInfo.metatiles = gAreaMetatiles[area];
gArea.currentRoomInfo.bg_anim = gUnk_080B755C[area];
}
void ChangeLightLevel(s32 lightLevel) {
lightLevel += gRoomVars.lightLevel;
if (lightLevel < 0)
lightLevel = 0;
if (lightLevel > 256)
lightLevel = 256;
gRoomVars.lightLevel = lightLevel;
}
static void sub_080530B0(void) {
static const u16 sMinecartData[] = { 0x189, 0x0, 0x102, 0x4, 0x1af, 0x0, 0x204, 0x0,
0x1cf, 0x0, 0x10, 0x4, 0x0, 0x0, 0x0, 0x0 };
MemCopy(sMinecartData, gScreenTransition.minecart_data, sizeof sMinecartData);
}
void UpdateGlobalProgress(void) {
u8 pcnt = 1;
if (CheckLocalFlagByBank(FLAG_BANK_3, SEIIKI_STAINED_GLASS)) {
pcnt = 9;
} else if (CheckGlobalFlag(LV5_CLEAR)) {
pcnt = 8;
} else if (CheckLocalFlagByBank(FLAG_BANK_3, OUBO_KAKERA)) {
pcnt = 7;
} else if (CheckGlobalFlag(LV4_CLEAR)) {
pcnt = 6;
} else if (CheckGlobalFlag(LV3_CLEAR)) {
pcnt = 5;
} else if (CheckLocalFlagByBank(FLAG_BANK_1, SOUGEN_08_TORITSUKI)) {
pcnt = 4;
} else if (CheckGlobalFlag(LV1_CLEAR)) {
pcnt = 2;
}
gSave.global_progress = pcnt;
}
static u32 sub_08053144(void) {
u32 ret;
if (CheckGlobalFlag(ENDING))
return 0;
ret = 0;
if (gArea.locationIndex != 0)
ret = !!(gScreenTransition.player_status.field_0x24[10] ^ gArea.locationIndex);
return ret;
}
void sub_08053178(void) {
if (!sub_08053144())
return;
gScreenTransition.player_status.field_0x24[10] = gArea.locationIndex;
if (!CheckGlobalFlag(TABIDACHI))
return;
if (!CheckGlobalFlag(ENDING)) {
Entity* e = (Entity*)GetEmptyManager();
if (e != NULL) {
e->kind = MANAGER;
e->id = 0x39;
AppendEntityToList(e, 8);
if (!gRoomVars.field_0x0 && !ReadBit(gSave.areaVisitFlags, gArea.locationIndex)) {
e->type2 = 1;
SetPlayerControl(3);
SetInitializationPriority();
}
}
}
WriteBit(gSave.areaVisitFlags, gArea.locationIndex);
}
void sub_080531F8(void) {
gPlayerState.startPosX = gPlayerEntity.x.HALF.HI;
gPlayerState.startPosY = gPlayerEntity.y.HALF.HI;
if (sub_08053144()) {
MemCopy(&gScreenTransition.player_status, &gSave.saved_status, sizeof gScreenTransition.player_status);
if (CheckIsDungeon()) {
gScreenTransition.player_status.field_0x16 = gRoomControls.areaID;
gScreenTransition.player_status.field_0x17 = gRoomControls.roomID;
gScreenTransition.player_status.field_0x18 = gPlayerEntity.x.HALF.HI;
gScreenTransition.player_status.field_0x1a = gPlayerEntity.y.HALF.HI;
}
}
}
void sub_08053250(void) {
gScreenTransition.player_status.spawn_type = PL_SPAWN_DEFAULT;
gScreenTransition.player_status.start_pos.HALF.x = gPlayerEntity.x.HALF.HI - gRoomControls.roomOriginX;
gScreenTransition.player_status.start_pos.HALF.y = gPlayerEntity.y.HALF.HI - gRoomControls.roomOriginY;
gScreenTransition.player_status.start_anim = gPlayerEntity.animationState;
gScreenTransition.player_status.layer = gPlayerEntity.collisionLayer;
gScreenTransition.player_status.area_next = gRoomControls.areaID;
gScreenTransition.player_status.room_next = gRoomControls.roomID;
MemCopy(&gScreenTransition.player_status, &gSave.saved_status, sizeof gScreenTransition.player_status);
}
void sub_0805329C(void) {
if (sub_08053144()) {
switch (gRoomControls.areaID) {
case AREA_DEEPWOOD_SHRINE:
gSave.unk7 = 0;
break;
case AREA_CAVE_OF_FLAMES:
sub_080530B0();
break;
case AREA_OUTER_FORTRESS_OF_WINDS:
sub_080532E4();
break;
default:
sub_08053460();
break;
}
}
}
static void sub_080532E4(void) {
s32 x, y;
RoomHeader* r_hdr = gAreaRoomHeaders[AREA_FORTRESS_OF_WINDS] + 33;
gScreenTransition.player_status.field_0x16 = AREA_FORTRESS_OF_WINDS;
gScreenTransition.player_status.field_0x17 = 33;
gScreenTransition.player_status.field_0x18 = r_hdr->map_x + r_hdr->pixel_width / 2;
gScreenTransition.player_status.field_0x1c = gScreenTransition.player_status.field_0x18;
gScreenTransition.player_status.field_0x1a = r_hdr->map_y + r_hdr->pixel_height + 0xa0;
gScreenTransition.player_status.field_0x1e = gScreenTransition.player_status.field_0x1a;
}
void sub_08053320(void) {
MemClear(&gBG0Buffer, sizeof gBG0Buffer);
MemClear(&gBG1Buffer, sizeof gBG1Buffer);
MemClear(&gBG2Buffer, sizeof gBG2Buffer);
MemClear(&gBG3Buffer, sizeof gBG3Buffer);
LoadGfxGroup(16);
LoadGfxGroup(23);
if (gRoomControls.areaID == AREA_CASTOR_WILDS)
LoadGfxGroup(26);
sub_08053390();
LoadPaletteGroup(11);
LoadPaletteGroup(12);
SetColor(0, 0);
}
void sub_08053390(void) {
LoadGfxGroup(GetInventoryValue(8) ? 24 : 25);
if (GetInventoryValue(0xAu))
LoadGfxGroup(29);
LoadGfxGroup(GetInventoryValue(12) ? 28 : 27);
}
void sub_080533CC(void) {
u16* p1 = gUnk_020178E0;
u16* p2 = gUnk_020178E0 - 0x100;
*p2++ = *p1++;
*p2++ = *p1++;
*p2++ = *p1++;
*p2++ = *p1++;
*p2++ = *p1++;
gUsedPalettes |= 8;
}
void sub_0805340C(void) {
static void (*const sHandlers[])(u32*) = {
sub_08053434, DummyHandler, sub_080534E4, DummyHandler, DummyHandler, DummyHandler, DummyHandler, DummyHandler,
};
u32* p;
u32 i;
p = gSave.unk48C;
for (i = 0; i < 8; i++, p++) {
(sHandlers[i])(p);
}
}
static void DummyHandler(u32* a1) {
}
static void sub_08053434(u32* a1) {
if (gArea.locationIndex == 29 && *a1) {
if (!--*a1) {
sub_08053460();
MenuFadeIn(5, 6);
}
}
}
static void sub_08053460(void) {
static const u16 sClearFlags[] = { FLAG_BANK_10, LV6_GUFUU1_GISHIKI, FLAG_BANK_10, LV6_GUFUU1_DEMO,
FLAG_BANK_10, LV6_ZELDA_DISCURSE, FLAG_BANK_10, LV6_00_ESCAPE,
FLAG_BANK_10, LV6_GUFUU2_DEAD, FLAG_BANK_G, ENDING,
FLAG_BANK_10, LV6_KANE_START, FLAG_BANK_10, LV6_KANE_1ST,
FLAG_BANK_10, LV6_KANE_2ND, FLAG_BANK_10, LV6_SOTO_ENDING,
0xFFFF };
gSave.unk48C[0] = 0;
if (CheckLocalFlagByBank(FLAG_BANK_10, LV6_ZELDA_DISCURSE))
ClearGlobalFlag(ZELDA_CHASE);
ClearFlagArray(sClearFlags);
}
void sub_08053494(void) {
gSave.unk48C[0] = 10800;
}
void sub_080534AC(void) {
if (CheckLocalFlagByBank(FLAG_BANK_10, LV6_KANE_START)) {
ClearLocalFlagByBank(FLAG_BANK_10, LV6_KANE_START);
gSave.unk48C[0] = 0;
SoundReq(SONG_STOP_BGM);
}
}
static void sub_080534E4(u32* a1) {
if (gRoomControls.areaID != AREA_VEIL_FALLS_TOP) {
if (*a1)
--*a1;
}
}
void sub_08053500(void) {
gSave.unk48C[2] = 36000;
}
void sub_08053518(void) {
static const u16 sClearFlags[] = { FLAG_BANK_2, BILL00_SHICHOU_00, FLAG_BANK_2, BILL0A_YADO_TAKARA_00,
FLAG_BANK_2, BILL0C_SCHOOLR_00, FLAG_BANK_1, MACHI00_00,
FLAG_BANK_1, MACHI00_02, FLAG_BANK_2, MHOUSE06_00,
FLAG_BANK_2, MHOUSE14_00, FLAG_BANK_2, MHOUSE2_00_02,
FLAG_BANK_2, MHOUSE2_01_T0, FLAG_BANK_2, MHOUSE2_02_KAME,
FLAG_BANK_2, SHOP00_ITEM_01, FLAG_BANK_2, SHOP01_CAFE_01,
0xFFFF };
sub_08053460();
ClearFlagArray(sClearFlags);
if (!CheckGlobalFlag(WATERBEAN_PUT))
ClearGlobalFlag(WATERBEAN_OUT);
if (!GetInventoryValue(0x40u))
ClearGlobalFlag(LV1_CLEAR);
if (!GetInventoryValue(0x41u))
ClearGlobalFlag(LV2_CLEAR);
if (!GetInventoryValue(0x42u))
ClearGlobalFlag(LV4_CLEAR);
}
static void ClearFlagArray(const u16* p) {
const u16* i;
for (i = p; i[0] != 0xFFFF; i += 2)
ClearLocalFlagByBank(i[0], i[1]);
}