tmc/src/arm_proxy.c

548 lines
15 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 "manager.h"
#include "npc.h"
extern u8 gUnk_03003DE0;
extern u8 gUnk_03000C30;
extern u16* gUnk_02025EB0;
extern u16* gUnk_0200B650;
extern u8 gUnk_02000070;
extern u8 gUnk_03003DF0[];
extern u8 gUnk_03003BE0;
extern Entity* gUnk_03004040[3];
extern u8 gUnk_020342F8;
extern u8 gUnk_03003DB8;
extern void gUnk_030059F0(void);
extern void sub_080ADD70();
extern void sub_0801C25C();
extern void sub_08016C3C();
extern void sub_08016DF8();
extern void sub_0804FF98();
extern u32 sub_0805E3B0();
extern void sub_08016FF4();
extern void sub_08070680();
extern void sub_080171F0();
extern void sub_08078FB0();
extern void sub_0800404C();
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);
extern void sub_080173A4(Entity*);
extern void sub_080A2838(Entity*);
extern u32 ReadBit(void*, u32);
extern void sub_0806EC78(Entity*);
typedef struct {
u8 unk0;
u8 unk1;
u8 unk2;
u8 unk3;
u8 unk4;
u8 unk5;
u16 unk6;
} ItemFrame;
extern ItemFrame gUnk_08126DA8[];
extern ItemFrame* gUnk_08126ED8[3];
typedef struct {
u16 unk0;
u16 unk1;
u16 x;
u16 y;
} NPCStruct;
extern NPCStruct gUnk_02031EC0[100];
typedef struct {
u8 unk0;
u8 unk1;
u8 unk2;
u8 unk3;
u8 freezeTime;
u8 unk9;
} EntityHandler;
extern EntityHandler gUnk_03003DC0;
typedef struct {
void* last;
void* first;
void* node;
u8 flags;
} LinkedList2;
extern LinkedList2 gUnk_03003C70[16];
extern LinkedList2* gUnk_02018EA0;
void sub_08016DF8(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 sub_08016E78(void) {
gUnk_03001000.interruptFlag = 0;
VBlankIntrWait();
do {
} while (gUnk_03001000.interruptFlag == 0);
sub_080ADD70();
sub_0801C25C();
sub_08016C3C();
sub_08016DF8();
if (gUnk_02000070) {
gUnk_02000070 = 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);
}
}
sub_0804FF98();
}
void sub_08016F28(Entity* this) {
if (gSave.stats.floorType != 0)
gPlayerState.flags.all |= 0x4000;
else
gPlayerState.flags.all &= ~0x4000;
if (sub_0805E3B0(this) == 0) {
if ((gPlayerState.flags.all & 0x80000) != 0) {
sub_08077B20();
if ((gPlayerState.flags.all & 0x200000) != 0) {
gPlayerState.playerAction = 0x18;
gPlayerState.flags.all &= 0xfff7ffff;
gPlayerState.hurtBlinkSpeed = 0xf0;
this->flags |= 0x80;
} else {
this->flags &= 0x7f;
gPlayerState.field_0xa8 = 0xf;
}
}
sub_08016FF4(this);
sub_08070680(this);
if ((this->height.WORD == 0) && (this->action == 1 || this->action == 9)) {
sub_08008790(this, 8);
}
sub_080171F0();
}
sub_08078FB0(this);
sub_0800404C(this);
sub_0807A050();
}
void sub_08016FF4(Entity* this) {
u32 temp;
gUnk_0200AF00.filler25[10] = 0;
gUnk_0200AF00.filler25[8] = 0;
gUnk_0200AF00.filler25[9] = 0;
if ((gPlayerEntity.bitfield & 0x80) && (gPlayerEntity.hurtBlinkTime > 0))
PlaySFX(SFX_86);
gPlayerState.flags.all &= ~(0x2000000 | 0x200);
if (gPlayerState.flags.all & 0x400)
ResetPlayer();
if ((gPlayerState.flags.all & 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.field_0x40[0x4a] != 0) {
gPlayerState.field_0x40[0x4a]--;
return;
}
if ((gPlayerState.field_0x8b != 0) || (gTextBox.doTextBox & 0x7f))
return;
gRoomVars.unk2 = gTextBox.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.filler[2] == 0) {
gSave.stats.field_0x1c = 0;
} else if ((gSave.stats.field_0x1c == 0) || --gSave.stats.field_0x1c == 0) {
gSave.stats.filler[2] = 0;
PlaySFX(SFX_ICE_BLOCK_MELT);
}
if (gSave.stats.filler[3] == 0) {
gSave.stats.field_0x1e = 0;
} else if ((gSave.stats.field_0x1e == 0) || (--gSave.stats.field_0x1e == 0)) {
gSave.stats.filler[3] = 0;
PlaySFX(SFX_140);
} else if ((gSave.stats.field_0x1e & 0xf) == 0) {
CreateSparkle(this);
}
if (gSave.stats.floorType == 0) {
gSave.stats.field_0x20 = 0;
} else if ((gSave.stats.field_0x20 == 0) || --gSave.stats.field_0x20 == 0) {
gSave.stats.floorType = 0;
} else if ((gSave.stats.field_0x20 & 0x3f) == 0) {
// lava or water splash FX
CreateFx(this, 0x55 + gSave.stats.floorType, 0);
}
}
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 != 0x14)
gPlayerState.flags.all = (gPlayerState.flags.all & ~0x10000) | (0x8000 * (gPlayerState.flags.all & 2));
gPlayerState.flags.all &= ~2;
sub_080028E0(&gPlayerEntity);
if (gPlayerState.flags.all & 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;
_DmaZero(&gUnk_03003BE0, 0x8c);
gPlayerEntity.spriteOffsetY = gPlayerState.field_0x3f;
gPlayerState.field_0x3f = 0;
sub_0807B0C8();
if (gPlayerState.flags.all & 0x400000)
gUnk_03004040[0]->spriteOffsetY = gUnk_03004040[1]->spriteOffsetY = gUnk_03004040[2]->spriteOffsetY = 0;
if (gPlayerEntity.action == 0x1d)
gPlayerState.flags.all |= 0x20000000;
else
gPlayerState.flags.all &= ~0x20000000;
sub_0807A8D8(&gPlayerEntity);
if (gPlayerState.jumpStatus & 0xc0)
gPlayerEntity.hurtBlinkTime = 0xfe;
if (gPlayerEntity.action != 0x17) {
sub_08077FEC(gPlayerEntity.action);
}
}
void sub_08017338(Entity *this) {
if (!(this->flags & 1) && !this->action && !this->previousActionFlag)
sub_080173A4(this);
if (!sub_0805E3B0(this)) {
gPlayerItemFunctions[this->entityType.subtype](this);
this->bitfield &= ~0x80;
if (this->hurtBlinkTime != 0) {
if (this->hurtBlinkTime > 0)
this->hurtBlinkTime--;
else
this->hurtBlinkTime++;
}
}
sub_0800404C(this);
}
// tiny regalloc
NONMATCH("asm/non_matching/sub_080173A4.inc", void sub_080173A4(Entity* this)) {
ItemFrame* entry;
entry = &gUnk_08126DA8[this->entityType.subtype];
if (entry->unk0 == 0xff) {
u32 temp = entry->unk2;
ItemFrame* temp2 = gUnk_08126ED8[entry->unk1];
entry = &temp2[this->field_0x68.HALF.LO - temp];
}
this->palette.raw = ((entry->unk0 & 0xf) << 4) | entry->unk0;
this->field_0x44 = entry->unk1;
this->field_0x40 = entry->unk3;
this->damageType = entry->unk4;
this->spriteIndex = entry->unk5;
if (entry->unk6 == 0)
this->spriteVramOffset = gPlayerEntity.spriteVramOffset;
else
this->spriteVramOffset = entry->unk6 & 0x3ff;
if (this->animationState == 0)
this->animationState = gPlayerEntity.animationState & 6;
this->collisionLayer = gPlayerEntity.collisionLayer;
this->spriteRendering.b3 = gPlayerEntity.spriteRendering.b3;
this->spritePriority.b0 = gPlayerEntity.spritePriority.b0;
this->spriteOrientation.flipY = gPlayerEntity.spriteOrientation.flipY;
this->currentHealth = 1;
this->flags |= 1;
}
END_NONMATCH
void sub_080174A4(Entity* this) {
int iVar1;
if (((this->flags & 1) == 0) && (this->action == 0)) {
sub_080A2838(this);
}
if (this->hurtBlinkTime != 0) {
this->hurtBlinkTime++;
}
if (!sub_0805E3B0(this)) {
gObjectFunctions[this->entityType.subtype](this);
this->bitfield &= ~0x80;
}
sub_0800404C(this);
}
void sub_08017508(Entity* this) {
if (!sub_0805E3B0(this))
gManagerFunctions[this->entityType.subtype](this);
}
// regalloc
NONMATCH("asm/non_matching/sub_08017530.inc", void sub_08017530(Entity* this)) {
if ((this->currentHealth & 0x7f) &&
!ReadBit(&gUnk_020342F8, this->currentHealth - 1)) {
DeleteThisEntity();
}
if ((this->action == 0) && ((this->flags & 1) == 0)) {
sub_0806EC78(this);
}
if (!sub_0805E3B0(this)) {
gNPCFunctions[this->entityType.subtype][0](this);
}
if (this->next != NULL) {
if (gNPCFunctions[this->entityType.subtype][1] != NULL) {
gNPCFunctions[this->entityType.subtype][1](this);
}
if ((this->currentHealth & 0x7f) != 0) {
u32 temp = this->currentHealth & 0x7f;
gUnk_02031EC0[temp * 2 - 2].x = this->x.HALF.HI - gRoomControls.roomOriginX;
gUnk_02031EC0[temp * 2 - 2].y = this->y.HALF.HI - gRoomControls.roomOriginY;
}
sub_0800404C(this);
}
}
END_NONMATCH
void sub_080175E8(void) {
gUnk_03003DB8 = 0;
}
void sub_080175F4(void) {
u32 flags;
u32 temp;
void (*func)(void);
temp = gUnk_03003DC0.unk0;
if (gUnk_03003DC0.unk0 <= gUnk_03003DC0.unk1)
temp = gUnk_03003DC0.unk1;
if (temp != 0)
return;
func = &gUnk_030059F0;
if (gPlayerState.field_0x8b != 0) {
u32 temp = gPlayerEntity.flags;
gPlayerEntity.flags &= 0x7f;
func();
gPlayerEntity.flags = temp;
} else {
func();
}
}
void sub_08017640(void) {
_DmaZero(&gUnk_03003C70,0x100);
gUnk_02018EA0 = (LinkedList2*)&gUnk_03003C70[0].last;
gUnk_03003C70[0].last = &gUnk_03003C70[0].last;
gUnk_03003C70[0].first = &gUnk_03003C70[0].last;
gUnk_03003C70[0].node = &gPlayerEntity;
}
// Loop declaration seems wrong
NONMATCH("asm/non_matching/sub_0801766C.inc", u32 sub_0801766C(Entity* this)) {
u32 uVar1;
LinkedList2* puVar3;
LinkedList2* puVar2;
LinkedList2* pLVar2;
LinkedList2* i;
u8* pbVar4;
if (this->spritePriority.b2 != 0) {
return 1;
} else {
for (i = &gUnk_03003C70[0]; i < &gUnk_03003C70[16]; ++i) {
if (i->node == NULL) {
i->node = this;
i->flags = 0;
this->spritePriority.b2 = 1;
pLVar2 = gUnk_02018EA0;
if (gUnk_02018EA0->flags != 0) {
do {
pLVar2 = pLVar2->first;
} while (pLVar2->flags != 0);
i->first = pLVar2;
puVar3 = pLVar2->last;
i->last = puVar3;
puVar3->first = i;
pLVar2->last = i;
} else {
i->first = gUnk_02018EA0;
puVar2 = gUnk_02018EA0->last;
i->last = puVar2;
puVar2->first = i;
gUnk_02018EA0->last = i;
gUnk_02018EA0 = i;
}
return 1;
}
}
return 0;
}
}
END_NONMATCH
// same loop issue
NONMATCH("asm/non_matching/sub_080176E4.inc", u32 sub_080176E4(Entity* this)) {
u32 uVar1;
LinkedList2* j;
LinkedList2* i;
u8* pbVar4;
if (this->spritePriority.b2 != 0) {
return 1;
} else {
for (i = &gUnk_03003C70[0]; i < &gUnk_03003C70[16]; ++i) {
if (i->node == NULL) {
i->node = this;
i->flags = 1;
this->spritePriority.b2 = 1;
i->first = gUnk_02018EA0;
j = gUnk_02018EA0->last;
i->last = j;
j->first = i;
gUnk_02018EA0->last = i;
gUnk_02018EA0 = i;
return 1;
}
}
return 0;
}
}
END_NONMATCH
// you guessed it
NONMATCH("asm/non_matching/sub_08016DF8.inc", void sub_08017744(Entity* this)) {
LinkedList2* i;
for (i = &gUnk_03003C70[0]; i < &gUnk_03003C70[16]; ++i) {
if (i->node == this) {
if (this->spritePriority.b2 != 0) {
this->spritePriority.b2 = 0;
i->node = NULL;
((LinkedList2*)i->last)->first = i->first;
((LinkedList2*)i->first)->last = i->last;
if (i != gUnk_02018EA0)
return;
gUnk_02018EA0 = i->first;
}
}
}
}
END_NONMATCH
// regalloc
NONMATCH("asm/non_matching/sub_080177A0.inc", bool32 sub_080177A0(Entity* this, Entity* that)) {
u32 this_d;
u32 depth;
if ((that->collisionLayer & this->collisionLayer) != 0) {
BoundingBox* bb_this = this->boundingBox;
BoundingBox* bb_that = that->boundingBox;
u32 this_w = bb_this->width;
u32 that_w = bb_that->width;
if ((((this->x.HALF.HI - that->x.HALF.HI) + bb_this->offset_x) - bb_that->offset_x) + this_w + that_w <= (this_w + that_w) * 2) {
u32 this_h = bb_this->height;
u32 that_h = bb_that->height;
if ((((this->y.HALF.HI - that->y.HALF.HI) + bb_this->offset_y) - bb_that->offset_y) + this_h + that_h <= (this_h + that_h) * 2) {
if ((this->field_0x3c & 0x10) != 0)
this_d = ((BoundingBox3D*)bb_this)->depth;
else
this_d = 5;
if ((that->field_0x3c & 0x10) != 0)
depth = this_d + ((BoundingBox3D*)bb_that)->depth;
else
depth = this_d + 5;
if ((this->height.HALF.HI - that->height.HALF.HI) + depth <= depth * 2)
return TRUE;
}
}
}
return FALSE;
}
END_NONMATCH
bool32 sub_08017850(Entity* this) {
if (sub_08079F8C())
return sub_080177A0(this, &gPlayerEntity);
return FALSE;
}