403 lines
9.4 KiB
C
403 lines
9.4 KiB
C
#include <ultra64.h>
|
|
#include "constants.h"
|
|
#include "game/pad.h"
|
|
#include "bss.h"
|
|
#include "data.h"
|
|
#include "types.h"
|
|
|
|
struct padsfileheader *g_PadsFile;
|
|
u16 *g_PadOffsets;
|
|
u32 var800a2358;
|
|
u32 var800a235c;
|
|
u16 *g_CoverFlags;
|
|
s32 *g_CoverRooms;
|
|
struct covercandidate *g_CoverCandidates;
|
|
u16 g_NumSpecialCovers;
|
|
u16 *g_SpecialCoverNums;
|
|
|
|
void padUnpack(s32 padnum, u32 fields, struct pad *pad)
|
|
{
|
|
s32 offset;
|
|
u32 *header;
|
|
f32 *fbuffer;
|
|
u8 *ptr;
|
|
|
|
if (pad);
|
|
|
|
offset = g_PadOffsets[padnum];
|
|
ptr = (u8 *) &g_StageSetup.padfiledata[offset];
|
|
header = (u32 *) ptr;
|
|
|
|
// Header format:
|
|
// flags, room and liftnum
|
|
// ffffffff ffffffff ffrrrrrr rrrrllll
|
|
|
|
if (fields & PADFIELD_ROOM) {
|
|
pad->room = (s32)(*header << 18) >> 22;
|
|
}
|
|
|
|
if (fields & PADFIELD_LIFT) {
|
|
pad->liftnum = *header & 0x0000000f;
|
|
}
|
|
|
|
ptr += 4;
|
|
|
|
if ((*header >> 14) & PADFLAG_INTPOS) {
|
|
if (fields & PADFIELD_POS) {
|
|
s16 *sbuffer = (s16 *) ptr;
|
|
pad->pos.x = sbuffer[0];
|
|
pad->pos.y = sbuffer[1];
|
|
pad->pos.z = sbuffer[2];
|
|
}
|
|
ptr += 8;
|
|
} else {
|
|
if (fields & PADFIELD_POS) {
|
|
fbuffer = (f32 *) ptr;
|
|
pad->pos.x = fbuffer[0];
|
|
pad->pos.y = fbuffer[1];
|
|
pad->pos.z = fbuffer[2];
|
|
}
|
|
ptr += 12;
|
|
}
|
|
|
|
if ((*header >> 14) & (PADFLAG_UPALIGNTOX | PADFLAG_UPALIGNTOY | PADFLAG_UPALIGNTOZ)) {
|
|
if (fields & (PADFIELD_UP | PADFIELD_NORMAL)) {
|
|
if ((*header >> 14) & PADFLAG_UPALIGNTOX) {
|
|
pad->up.x = ((*header >> 14) & PADFLAG_UPALIGNINVERT) ? -1 : 1;
|
|
pad->up.y = 0;
|
|
pad->up.z = 0;
|
|
} else if ((*header >> 14) & PADFLAG_UPALIGNTOY) {
|
|
pad->up.x = 0;
|
|
pad->up.y = ((*header >> 14) & PADFLAG_UPALIGNINVERT) ? -1 : 1;
|
|
pad->up.z = 0;
|
|
} else {
|
|
pad->up.x = 0;
|
|
pad->up.y = 0;
|
|
pad->up.z = ((*header >> 14) & PADFLAG_UPALIGNINVERT) ? -1 : 1;
|
|
}
|
|
}
|
|
} else {
|
|
if (fields & (PADFIELD_UP | PADFIELD_NORMAL)) {
|
|
fbuffer = (f32 *) ptr;
|
|
pad->up.x = fbuffer[0];
|
|
pad->up.y = fbuffer[1];
|
|
pad->up.z = fbuffer[2];
|
|
}
|
|
ptr += 12;
|
|
}
|
|
|
|
if ((*header >> 14) & (PADFLAG_LOOKALIGNTOX | PADFLAG_LOOKALIGNTOY | PADFLAG_LOOKALIGNTOZ)) {
|
|
if (fields & (PADFIELD_LOOK | PADFIELD_NORMAL)) {
|
|
if ((*header >> 14) & PADFLAG_LOOKALIGNTOX) {
|
|
pad->look.x = ((*header >> 14) & PADFLAG_LOOKALIGNINVERT) ? -1 : 1;
|
|
pad->look.y = 0;
|
|
pad->look.z = 0;
|
|
} else if ((*header >> 14) & PADFLAG_LOOKALIGNTOY) {
|
|
pad->look.x = 0;
|
|
pad->look.y = ((*header >> 14) & PADFLAG_LOOKALIGNINVERT) ? -1 : 1;
|
|
pad->look.z = 0;
|
|
} else {
|
|
pad->look.x = 0;
|
|
pad->look.y = 0;
|
|
pad->look.z = ((*header >> 14) & PADFLAG_LOOKALIGNINVERT) ? -1 : 1;
|
|
}
|
|
}
|
|
} else {
|
|
if (fields & (PADFIELD_LOOK | PADFIELD_NORMAL)) {
|
|
fbuffer = (f32 *) ptr;
|
|
pad->look.x = fbuffer[0];
|
|
pad->look.y = fbuffer[1];
|
|
pad->look.z = fbuffer[2];
|
|
}
|
|
ptr += 12;
|
|
}
|
|
|
|
if (fields & PADFIELD_NORMAL) {
|
|
pad->normal.x = pad->up.y * pad->look.z - pad->look.y * pad->up.z;
|
|
pad->normal.y = pad->up.z * pad->look.x - pad->look.z * pad->up.x;
|
|
pad->normal.z = pad->up.x * pad->look.y - pad->look.x * pad->up.y;
|
|
}
|
|
|
|
if ((*header >> 14) & PADFLAG_HASBBOXDATA) {
|
|
if (fields & PADFIELD_BBOX) {
|
|
fbuffer = (f32 *) ptr;
|
|
pad->bbox.xmin = fbuffer[0];
|
|
pad->bbox.xmax = fbuffer[1];
|
|
pad->bbox.ymin = fbuffer[2];
|
|
pad->bbox.ymax = fbuffer[3];
|
|
pad->bbox.zmin = fbuffer[4];
|
|
pad->bbox.zmax = fbuffer[5];
|
|
}
|
|
ptr += 4 * 6;
|
|
} else {
|
|
if (fields & PADFIELD_BBOX) {
|
|
pad->bbox.xmin = -100;
|
|
pad->bbox.ymin = -100;
|
|
pad->bbox.zmin = -100;
|
|
pad->bbox.xmax = 100;
|
|
pad->bbox.ymax = 100;
|
|
pad->bbox.zmax = 100;
|
|
}
|
|
}
|
|
|
|
if (fields & PADFIELD_FLAGS) {
|
|
pad->flags = (*header >> 14);
|
|
}
|
|
}
|
|
|
|
bool padHasBboxData(s32 padnum)
|
|
{
|
|
u32 offset = g_PadOffsets[padnum];
|
|
u32 *header = (u32 *)&g_StageSetup.padfiledata[offset];
|
|
|
|
return ((*header >> 14) & PADFLAG_HASBBOXDATA) != 0;
|
|
}
|
|
|
|
void padGetCentre(s32 padnum, struct coord *coord)
|
|
{
|
|
struct pad pad;
|
|
|
|
padUnpack(padnum, PADFIELD_POS | PADFIELD_LOOK | PADFIELD_UP | PADFIELD_NORMAL | PADFIELD_BBOX, &pad);
|
|
|
|
coord->x = pad.pos.f[0] + (
|
|
(pad.bbox.xmin + pad.bbox.xmax) * pad.normal.f[0] +
|
|
(pad.bbox.ymin + pad.bbox.ymax) * pad.up.f[0] +
|
|
(pad.bbox.zmin + pad.bbox.zmax) * pad.look.f[0]) * 0.5f;
|
|
|
|
coord->y = pad.pos.f[1] + (
|
|
(pad.bbox.xmin + pad.bbox.xmax) * pad.normal.f[1] +
|
|
(pad.bbox.ymin + pad.bbox.ymax) * pad.up.f[1] +
|
|
(pad.bbox.zmin + pad.bbox.zmax) * pad.look.f[1]) * 0.5f;
|
|
|
|
coord->z = pad.pos.f[2] + (
|
|
(pad.bbox.xmin + pad.bbox.xmax) * pad.normal.f[2] +
|
|
(pad.bbox.ymin + pad.bbox.ymax) * pad.up.f[2] +
|
|
(pad.bbox.zmin + pad.bbox.zmax) * pad.look.f[2]) * 0.5f;
|
|
}
|
|
|
|
/**
|
|
* Some door models are rotated weirdly - suspected to be designed using the
|
|
* wrong coordinate system, then the developers implemented a fix here in the
|
|
* code rather than fixing the models.
|
|
*
|
|
* When such a door is placed on a pad, this function is called. It adjusts the
|
|
* pad's orientation to compensate for the model.
|
|
*/
|
|
void padRotateForDoor(s32 padnum)
|
|
{
|
|
u32 stack;
|
|
u32 *ptr;
|
|
u32 *header;
|
|
struct coord *look;
|
|
struct coord *up;
|
|
f32 scale;
|
|
s32 offset;
|
|
|
|
offset = g_PadOffsets[padnum];
|
|
ptr = (u32 *) &g_StageSetup.padfiledata[offset];
|
|
header = ptr;
|
|
|
|
ptr++;
|
|
|
|
if ((*header >> 14) & PADFLAG_INTPOS) {
|
|
ptr += 2;
|
|
} else {
|
|
ptr += 3;
|
|
}
|
|
|
|
if (((*header >> 14) & (PADFLAG_UPALIGNTOX | PADFLAG_UPALIGNTOY | PADFLAG_UPALIGNTOZ)) == 0) {
|
|
up = (struct coord *) ptr;
|
|
up->y = 0;
|
|
|
|
scale = 1 / sqrtf(up->f[0] * up->f[0] + up->f[2] * up->f[2]);
|
|
|
|
up->x *= scale;
|
|
up->z *= scale;
|
|
|
|
ptr += 3;
|
|
}
|
|
|
|
if ((*header >> 14) & (PADFLAG_LOOKALIGNTOX | PADFLAG_LOOKALIGNTOY | PADFLAG_LOOKALIGNTOZ)) {
|
|
// Unset the LOOKALIGN flags, then set LOOKALIGNTOY
|
|
*header = *header ^ (((*header >> 14) ^ ((*header >> 14) & ~(PADFLAG_LOOKALIGNTOX | PADFLAG_LOOKALIGNTOY | PADFLAG_LOOKALIGNTOZ | PADFLAG_LOOKALIGNINVERT))) << 14);
|
|
*header = *header ^ (((*header >> 14) ^ ((*header >> 14) | PADFLAG_LOOKALIGNTOY)) << 14);
|
|
} else {
|
|
look = (struct coord *) ptr;
|
|
|
|
look->x = 0.0f;
|
|
look->y = 1.0f;
|
|
look->z = 0.0f;
|
|
}
|
|
}
|
|
|
|
void padCopyBboxFromPad(s32 padnum, struct pad *src)
|
|
{
|
|
u32 offset = g_PadOffsets[padnum];
|
|
f32 *fbuffer = (f32 *)&g_StageSetup.padfiledata[offset];
|
|
u32 *header = (u32 *)fbuffer;
|
|
|
|
if ((*header >> 14) & PADFLAG_HASBBOXDATA) {
|
|
fbuffer++;
|
|
|
|
if ((*header >> 14) & PADFLAG_INTPOS) {
|
|
fbuffer += 2;
|
|
} else {
|
|
fbuffer += 3;
|
|
}
|
|
|
|
if (((*header >> 14) & (PADFLAG_UPALIGNTOX | PADFLAG_UPALIGNTOY | PADFLAG_UPALIGNTOZ)) == 0) {
|
|
fbuffer += 3;
|
|
}
|
|
|
|
if (((*header >> 14) & (PADFLAG_LOOKALIGNTOX | PADFLAG_LOOKALIGNTOY | PADFLAG_LOOKALIGNTOZ)) == 0) {
|
|
fbuffer += 3;
|
|
}
|
|
|
|
fbuffer[0] = src->bbox.xmin;
|
|
fbuffer[1] = src->bbox.xmax;
|
|
fbuffer[2] = src->bbox.ymin;
|
|
fbuffer[3] = src->bbox.ymax;
|
|
fbuffer[4] = src->bbox.zmin;
|
|
fbuffer[5] = src->bbox.zmax;
|
|
}
|
|
}
|
|
|
|
void padSetFlag(s32 padnum, u32 flag)
|
|
{
|
|
u32 offset = g_PadOffsets[padnum];
|
|
u32 *header = (u32 *)&g_StageSetup.padfiledata[offset];
|
|
|
|
*header = *header ^ ((*header >> 14) ^ ((*header >> 14) | flag)) << 14;
|
|
}
|
|
|
|
void padUnsetFlag(s32 padnum, u32 flag)
|
|
{
|
|
u32 offset = g_PadOffsets[padnum];
|
|
u32 *header = (u32 *)&g_StageSetup.padfiledata[offset];
|
|
|
|
*header = *header ^ ((*header >> 14) ^ ((*header >> 14) & ~flag)) << 14;
|
|
}
|
|
|
|
bool func0f1162c4(s32 padnum, s32 arg1)
|
|
{
|
|
return padnum;
|
|
}
|
|
|
|
s32 coverGetCount(void)
|
|
{
|
|
return g_PadsFile->numcovers;
|
|
}
|
|
|
|
bool coverUnpack(s32 covernum, struct cover *cover)
|
|
{
|
|
struct coverdefinition *def;
|
|
|
|
if (covernum >= g_PadsFile->numcovers || covernum < 0 || !g_StageSetup.cover) {
|
|
return false;
|
|
}
|
|
|
|
// @bug: Cast to u8 means it loads the pos, look and flags
|
|
// from an incorrect cover if covernum is greater than 255.
|
|
def = g_StageSetup.cover;
|
|
def += (u8)covernum;
|
|
|
|
cover->pos = &def->pos;
|
|
cover->look = &def->look;
|
|
|
|
g_CoverFlags[covernum] |= def->flags;
|
|
|
|
cover->flags = g_CoverFlags[covernum];
|
|
cover->rooms[0] = g_CoverRooms[covernum];
|
|
cover->rooms[1] = -1;
|
|
|
|
return true;
|
|
}
|
|
|
|
u16 getNumSpecialCovers(void)
|
|
{
|
|
return g_NumSpecialCovers;
|
|
}
|
|
|
|
bool coverUnpackBySpecialNum(s32 index, struct cover *cover)
|
|
{
|
|
// Probable @bug: last check should be index >= g_NumSpecialCovers
|
|
// This function is never called though.
|
|
if (!g_SpecialCoverNums || index < 0 || index > g_NumSpecialCovers) {
|
|
return false;
|
|
}
|
|
|
|
if (coverUnpack(g_SpecialCoverNums[index], cover)) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
s32 coverGetNumBySpecialNum(s32 index)
|
|
{
|
|
// Probable @bug: last check should be index >= g_NumSpecialCovers
|
|
// This function is never called though.
|
|
if (!g_SpecialCoverNums || index < 0 || index > g_NumSpecialCovers) {
|
|
return -1;
|
|
}
|
|
|
|
return g_SpecialCoverNums[index];
|
|
}
|
|
|
|
s32 func0f116450(s32 arg0, s32 arg1)
|
|
{
|
|
return arg0;
|
|
}
|
|
|
|
bool coverIsInUse(s32 covernum)
|
|
{
|
|
// @bug: Second condition should be >=
|
|
if (covernum < 0 || covernum > g_PadsFile->numcovers) {
|
|
return false;
|
|
}
|
|
|
|
return g_CoverFlags[covernum] & COVERFLAG_INUSE;
|
|
}
|
|
|
|
void coverSetInUse(s32 covernum, bool enable)
|
|
{
|
|
if (covernum >= 0 && covernum < g_PadsFile->numcovers) {
|
|
if (enable) {
|
|
g_CoverFlags[covernum] |= COVERFLAG_INUSE;
|
|
} else {
|
|
g_CoverFlags[covernum] &= ~COVERFLAG_INUSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
void coverSetFlag(s32 covernum, u32 flag)
|
|
{
|
|
g_CoverFlags[covernum] |= flag;
|
|
}
|
|
|
|
void coverUnsetFlag(s32 covernum, u32 flag)
|
|
{
|
|
g_CoverFlags[covernum] &= ~flag;
|
|
}
|
|
|
|
void coverSetFlag0001(s32 covernum, bool enable)
|
|
{
|
|
if (covernum >= 0 && covernum < g_PadsFile->numcovers) {
|
|
if (enable) {
|
|
g_CoverFlags[covernum] |= COVERFLAG_0001;
|
|
} else {
|
|
g_CoverFlags[covernum] &= ~COVERFLAG_0001;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool coverIsSpecial(struct cover *cover)
|
|
{
|
|
return (cover->flags & (COVERFLAG_0080 | COVERFLAG_0040 | COVERFLAG_0020)) != 0;
|
|
}
|
|
|
|
s32 func0f1165c0(s32 arg0, s32 arg1)
|
|
{
|
|
return arg0;
|
|
}
|