tmc/src/room.c

380 lines
9.7 KiB
C

#include "global.h"
#include "area.h"
#include "room.h"
#include "flags.h"
#include "functions.h"
#include "common.h"
#include "object.h"
#include "game.h"
extern void sub_0804B058(EntityData* dat);
extern void sub_0801AC98(void);
extern u32 sub_08049D1C(u32);
extern Entity* LoadRoomEntity(EntityData*);
extern void* GetRoomProperty(u32, u32, u32);
extern void** gCurrentRoomProperties;
extern void*** gAreaTable[];
extern u8 gUnk_081091E4[];
extern void sub_080186EC(void);
extern void sub_0804B16C(void);
extern void ClearSmallChests(void);
extern Entity* GetEmptyEntityByKind(u32 kind);
void RegisterRoomEntity(Entity*, EntityData*);
void sub_0804AF0C(Entity*, EntityData*);
void sub_0804AFB0(void** properties);
void sub_08054524(void);
void sub_0806F704(Entity*, u32);
void sub_0805BB00(u32, u32);
static void LoadRoomVisitTile(TileEntity*);
static void LoadSmallChestTile(TileEntity*);
static void LoadBombableWallTile(TileEntity*);
static void LoadDarknessTile(TileEntity*);
static void LoadDestructibleTile(TileEntity*);
static void LoadGrassDropTile(TileEntity*);
static void LoadLocationTile(TileEntity*);
typedef struct {
u8 filler[0x20];
} VarStruct;
extern VarStruct gDroptablesAreas[];
void LoadRoomEntityList(EntityData* listPtr) {
if (listPtr != NULL) {
while (listPtr->kind != 0xFF) {
LoadRoomEntity(listPtr++);
}
}
}
NONMATCH("asm/non_matching/LoadRoomEntity.inc", Entity* LoadRoomEntity(EntityData* dat)) {
int kind;
Entity* v4;
Entity* v5;
kind = dat->kind & 0xF;
if ((dat->flags & 0xF0) == 0x50 && DeepFindEntityByID(kind, dat->id))
return NULL;
v4 = GetEmptyEntityByKind(kind);
v5 = v4;
if (v4 != NULL) {
v4->kind = kind;
v4->id = dat->id;
v4->type = dat->type;
RegisterRoomEntity(v4, dat);
if ((dat->flags & 0xF0) != 16) {
v5->type2 = dat->type2;
v5->actionDelay = (dat->type2 & 0xFF00) >> 8;
if (kind == 9)
return v5;
sub_0804AF0C(v5, dat);
if (!v5->next)
return v5;
if ((dat->kind & 0x10) == 0) {
if ((dat->kind & 0x20) != 0) {
v5->collisionLayer = 2;
return v5;
}
if ((gRoomControls.scroll_flags & 2) == 0) {
ResolveCollisionLayer(v5);
}
}
v5->collisionLayer = 1;
}
}
return v5;
}
END_NONMATCH
void RegisterRoomEntity(Entity* ent, EntityData* dat) {
u32 list;
u32 kind;
void* offset;
list = dat->flags & 0xF;
kind = dat->kind & 0xF;
if (ent->prev == NULL) {
if (list == 0xF) {
AppendEntityToList(ent, gUnk_081091E4[kind]);
} else if (list == 8) {
AppendEntityToList(ent, 8);
} else {
AppendEntityToList(ent, list);
}
}
offset = &ent->field_0x78;
if (kind == MANAGER)
offset = &ent->y;
MemCopy(dat, offset, sizeof(EntityData));
}
void sub_0804AF0C(Entity* ent, EntityData* dat) {
switch (dat->flags & 0xf0) {
case 0x0:
ent->x.HALF.HI = dat->xPos + gRoomControls.origin_x;
ent->y.HALF.HI = dat->yPos + gRoomControls.origin_y;
break;
case 0x20:
ent->field_0x6c.HALF.HI |= 0x20;
ent->x.HALF.HI = dat->xPos + gRoomControls.origin_x;
ent->y.HALF.HI = dat->yPos + gRoomControls.origin_y;
break;
case 0x40:
ent->x.HALF.HI = dat->xPos + gRoomControls.origin_x;
ent->y.HALF.HI = dat->yPos + gRoomControls.origin_y;
if (!StartCutscene(ent, (u16*)dat->spritePtr))
DeleteEntity(ent);
break;
}
}
void sub_0804AF90(void) {
sub_0804AFB0(gArea.pCurrentRoomInfo->properties);
ClearSmallChests();
}
void sub_0804AFB0(void** properties) {
u32 i;
gCurrentRoomProperties = properties;
for (i = 0; i < 8; ++i) {
gRoomVars.field_0x6c[i] = gCurrentRoomProperties[i];
}
}
u32 CallRoomProp6(void) {
u32 result;
u32 (*func)(void);
result = 1;
func = (u32(*)())GetCurrentRoomProperty(6);
if (func != NULL)
result = func();
return result;
}
void CallRoomProp5And7(void) {
void (*func)(void);
sub_080186EC();
func = (void (*)())GetCurrentRoomProperty(5);
if (func) {
func();
}
func = (void (*)())GetCurrentRoomProperty(7);
if (func) {
func();
}
sub_0804B16C();
}
void LoadRoom(void) {
LoadRoomEntityList(GetCurrentRoomProperty(1));
LoadRoomEntityList(GetCurrentRoomProperty(0));
if (CheckGlobalFlag(TABIDACHI))
sub_0804B058(GetCurrentRoomProperty(2));
LoadRoomTileEntities(GetCurrentRoomProperty(3));
sub_0801AC98();
}
void sub_0804B058(EntityData* dat) {
Entity* ent;
u32 uVar2;
if ((dat != NULL) && dat->kind != 0xff) {
uVar2 = 0;
do {
if ((uVar2 < 0x20) && ((dat->kind & 0xF) == 3)) {
if (sub_08049D1C(uVar2) != 0) {
ent = LoadRoomEntity(dat);
if ((ent != NULL) && (ent->kind == ENEMY)) {
ent->field_0x6c.HALF.LO = uVar2 | 0x80;
}
}
} else {
LoadRoomEntity(dat);
}
uVar2++;
dat++;
} while (dat->kind != 0xff);
}
}
void sub_0804B0B0(u32 arg0, u32 arg1) {
LoadRoomEntityList(GetRoomProperty(arg0, arg1, 1));
}
void SetCurrentRoomPropertyList(u32 area, u32 room) {
gCurrentRoomProperties = NULL;
if (gAreaTable[area] != NULL) {
gCurrentRoomProperties = gAreaTable[area][room];
}
}
void sub_0804B0E8(u32 arg0, u32 arg1) {
void (*func)(void);
// init function at index 4 of room data
func = (void (*)())GetRoomProperty(arg0, arg1, 4);
if (func != NULL) {
func();
}
}
void* GetRoomProperty(u32 area, u32 room, u32 property) {
void** temp;
temp = NULL;
if (gAreaTable[area] != NULL) {
temp = gAreaTable[area][room];
if (temp != NULL) {
temp = temp[property];
}
}
return temp;
}
void* GetCurrentRoomProperty(u32 idx) {
if (gCurrentRoomProperties == NULL)
return NULL;
if (idx >= 0x80) {
return gRoomVars.field_0x8c[idx & 7];
} else if (idx <= 7) {
return gRoomVars.field_0x6c[idx];
} else {
return gCurrentRoomProperties[idx];
}
}
void sub_0804B16C(void) {
TileEntity* tile = gSmallChests;
do {
if (tile->_4 != 0 && CheckLocalFlag(tile->_1)) {
SetTileType(0x74, tile->_4, tile->_6 & 1 ? 2 : 1);
}
} while (++tile < gSmallChests + 8);
}
void LoadRoomTileEntities(TileEntity* list) {
TileEntity* t = list;
if (t == NULL)
return;
for (t; t->type != 0; ++t) {
switch (t->type) {
case ROOM_VISIT_MARKER:
LoadRoomVisitTile(t);
break;
case SMALL_CHEST:
LoadSmallChestTile(t);
break;
case BOMBABLE_WALL:
LoadBombableWallTile(t);
break;
case MUSIC_SETTER:
gArea.queued_bgm = t->_3;
break;
case DARKNESS:
LoadDarknessTile(t);
break;
case DESTRUCTIBLE_TILE:
LoadDestructibleTile(t);
break;
case GRASS_DROP_CHANGER:
LoadGrassDropTile(t);
break;
case LOCATION_CHANGER:
LoadLocationTile(t);
break;
case TILE_ENTITY_D:
gRoomVars.field_0x9 = t->_3;
break;
}
}
}
static void LoadGrassDropTile(TileEntity* tile) {
MemCopy(&gDroptablesAreas[tile->_1], &gRoomVars.filler4[44], 0x20);
}
static void LoadLocationTile(TileEntity* tile) {
gArea.locationIndex = tile->_1;
sub_08054524();
}
static void LoadRoomVisitTile(TileEntity* tile) {
SetLocalFlag(tile->_1);
}
static void LoadSmallChestTile(TileEntity* tile) {
TileEntity* t = gSmallChests;
u32 i = 0;
for (i = 0; i < 8; ++i, ++t) {
if (!t->_4) {
MemCopy(tile, t, sizeof(TileEntity));
if ((t->_6 & 1) && (gRoomControls.scroll_flags & 2) && !CheckLocalFlag(t->_1)) {
Entity* e = CreateObject(OBJECT_52, t->_1, 0);
if (e != NULL) {
sub_0806F704(e, t->_4);
}
}
return;
}
}
}
static void LoadBombableWallTile(TileEntity* tile) {
Manager24* mgr = (Manager24*)GetEmptyManager();
if (mgr != NULL) {
mgr->manager.type = 9;
mgr->manager.subtype = 0x24;
mgr->x = tile->_4;
mgr->y = *(u16*)&tile->_6;
mgr->field_0x35 = tile->_2;
mgr->field_0x3e = tile->_1;
AppendEntityToList((Entity*)mgr, 6);
}
}
static void LoadDarknessTile(TileEntity* tile) {
sub_0805BB00(tile->_3, 1);
}
static void LoadDestructibleTile(TileEntity* tile) {
if (CheckLocalFlag(*(u16*)&tile->_2)) {
SetTileType(*(u16*)&tile->_6, tile->_4, tile->_1);
} else if (!gRoomVars.filler_0x1) {
Manager* mgr;
gRoomVars.filler_0x1 = 1;
mgr = GetEmptyManager();
if (mgr != NULL) {
mgr->type = 9;
mgr->subtype = 0x2a;
AppendEntityToList((Entity*)mgr, 6);
}
}
}
void sub_0804B388(u32 a1, u32 a2) {
Entity* e;
SetTileType(a2 == 1 ? 38 : 52, a1, a2);
e = CreateObject(SPECIAL_FX, 2, 0);
if (e != NULL) {
e->collisionLayer = a2;
sub_0806F704(e, a1);
}
sub_080526F8(-1);
}
void sub_0804B3C4(void* arg0) {
LoadSmallChestTile(arg0);
}