Store pads in their full unpacked format

This commit is contained in:
Ryan Dwyer
2022-10-23 23:21:33 +10:00
parent 0bd58592c4
commit 0b87a5af75
5 changed files with 54 additions and 259 deletions
+1 -1
View File
@@ -57,7 +57,7 @@ PAL = 0
ROMALLOCATION_DATA = 0x015000
ROMALLOCATION_LIB = 0x038800
ROMALLOCATION_GAME = 0x144ee0
ROMALLOCATION_GAME = 0x100000
# ROM_SIZE - The desired ROM size in megabytes.
#
+17 -195
View File
@@ -6,7 +6,7 @@
#include "types.h"
struct padsfileheader *g_PadsFile;
u16 *g_PadOffsets;
struct pad *g_Pads;
u32 var800a2358;
u32 var800a235c;
u16 *g_CoverFlags;
@@ -17,140 +17,12 @@ 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);
}
*pad = g_Pads[padnum];
}
bool padHasBboxData(s32 padnum)
{
u32 offset = g_PadOffsets[padnum];
u32 *header = (u32 *)&g_StageSetup.padfiledata[offset];
return ((*header >> 14) & PADFLAG_HASBBOXDATA) != 0;
return (g_Pads[padnum].flags & PADFLAG_HASBBOXDATA) != 0;
}
void padGetCentre(s32 padnum, struct coord *coord)
@@ -185,97 +57,47 @@ void padGetCentre(s32 padnum, struct coord *coord)
*/
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;
if ((g_Pads[padnum].flags & (PADFLAG_UPALIGNTOX | PADFLAG_UPALIGNTOY | PADFLAG_UPALIGNTOZ)) == 0) {
up = &g_Pads[padnum].up;
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)) {
if (g_Pads[padnum].flags & (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);
g_Pads[padnum].flags &= ~PADFLAG_LOOKALIGNTOX;
g_Pads[padnum].flags &= ~PADFLAG_LOOKALIGNTOZ;
g_Pads[padnum].flags &= ~PADFLAG_LOOKALIGNINVERT;
g_Pads[padnum].flags |= PADFLAG_LOOKALIGNTOY;
} else {
look = (struct coord *) ptr;
look->x = 0.0f;
look->y = 1.0f;
look->z = 0.0f;
g_Pads[padnum].look.x = 0.0f;
g_Pads[padnum].look.y = 1.0f;
g_Pads[padnum].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;
if (g_Pads[padnum].flags & PADFLAG_HASBBOXDATA) {
g_Pads[padnum].bbox = src->bbox;
}
}
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;
g_Pads[padnum].flags |= flag;
}
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;
g_Pads[padnum].flags &= ~flag;
}
bool func0f1162c4(s32 padnum, s32 arg1)
+4 -21
View File
@@ -40,17 +40,15 @@ void setupPreparePads(void)
s32 offset;
g_PadsFile = (struct padsfileheader *)g_StageSetup.padfiledata;
g_PadOffsets = (u16 *)(g_StageSetup.padfiledata + 0x14);
g_Pads = (struct pad *)(g_StageSetup.padfiledata + 0x14);
padnum = 0;
numpads = g_PadsFile->numpads;
for (; padnum < numpads; padnum++) {
offset = g_PadOffsets[padnum];
packedpad = (struct packedpad *) &g_StageSetup.padfiledata[offset];
padUnpack(padnum, PADFIELD_POS | PADFIELD_BBOX, &pad);
// If room is negative (ie. not specified)
if (packedpad->room < 0) {
if (g_Pads[padnum].room < 0) {
roomsptr = NULL;
bgFindRoomsByPos(&pad.pos, inrooms, aboverooms, 20, NULL);
@@ -64,27 +62,12 @@ void setupPreparePads(void)
roomnum = cdFindFloorRoomAtPos(&pad.pos, roomsptr);
if (roomnum > 0) {
packedpad->room = roomnum;
g_Pads[padnum].room = roomnum;
} else {
packedpad->room = roomsptr[0];
g_Pads[padnum].room = roomsptr[0];
}
}
}
// Scale the bbox by 1 and save it back into the packed pad data.
// Yeah, this is effectively doing nothing.
if ((*(u32 *) packedpad >> 14) & PADFLAG_HASBBOXDATA) {
f32 scale = 1;
pad.bbox.xmin *= scale;
pad.bbox.xmax *= scale;
pad.bbox.ymin *= scale;
pad.bbox.ymax *= scale;
pad.bbox.zmin *= scale;
pad.bbox.zmax *= scale;
padCopyBboxFromPad(padnum, &pad);
}
}
g_StageSetup.waypoints = (struct waypoint *) ((u32)g_StageSetup.padfiledata + g_PadsFile->waypointsoffset);
+1 -1
View File
@@ -185,7 +185,7 @@ extern struct fileguid g_GameFileGuid;
extern u8 g_AltTitleUnlocked;
extern u8 g_AltTitleEnabled;
extern struct padsfileheader *g_PadsFile;
extern u16 *g_PadOffsets;
extern struct pad *g_Pads;
extern u16 *g_CoverFlags;
extern s32 *g_CoverRooms;
extern struct covercandidate *g_CoverCandidates;
+31 -41
View File
@@ -102,54 +102,44 @@ class App():
def make_pads(self):
output = bytes()
offsets = bytes()
start = pos = assetmgr.align4(0x14 + len(self.json['pads']) * 2)
for pad in self.json['pads']:
# flags, room and liftnum
# ffffffff ffffffff ffrrrrrr rrrrllll
output += self.make_float(pad['pos'][0])
output += self.make_float(pad['pos'][1])
output += self.make_float(pad['pos'][2])
output += self.make_float(pad['dir'][0])
output += self.make_float(pad['dir'][1])
output += self.make_float(pad['dir'][2])
output += self.make_float(pad['up'][0])
output += self.make_float(pad['up'][1])
output += self.make_float(pad['up'][2])
# normal
output += self.make_float(pad['up'][1] * pad['dir'][2] - pad['dir'][1] * pad['up'][2]);
output += self.make_float(pad['up'][2] * pad['dir'][0] - pad['dir'][2] * pad['up'][0]);
output += self.make_float(pad['up'][0] * pad['dir'][1] - pad['dir'][0] * pad['up'][1]);
output += self.make_float(pad['xmin'])
output += self.make_float(pad['xmax'])
output += self.make_float(pad['ymin'])
output += self.make_float(pad['ymax'])
output += self.make_float(pad['zmin'])
output += self.make_float(pad['zmax'])
# room is filled in at runtime
room = 0xffffffff
output += room.to_bytes(4, 'big')
flags = self.make_pad_flags(pad)
output += flags.to_bytes(4, 'big')
word = (flags << 14) | 0x3ff0 | (pad['liftnum'] & 0x0f)
output += word.to_bytes(4, 'big')
if flags & PADFLAG_INTPOS:
output += self.make_unsigned(pad['pos'][0]).to_bytes(2, 'big')
output += self.make_unsigned(pad['pos'][1]).to_bytes(2, 'big')
output += self.make_unsigned(pad['pos'][2]).to_bytes(2, 'big')
output += b'\x00\x00'
else:
output += self.make_float(pad['pos'][0])
output += self.make_float(pad['pos'][1])
output += self.make_float(pad['pos'][2])
if (flags & 0x0e) == 0:
output += self.make_float(pad['up'][0])
output += self.make_float(pad['up'][1])
output += self.make_float(pad['up'][2])
if (flags & 0xe0) == 0:
output += self.make_float(pad['dir'][0])
output += self.make_float(pad['dir'][1])
output += self.make_float(pad['dir'][2])
if flags & PADFLAG_HASBBOXDATA:
output += self.make_float(pad['xmin'])
output += self.make_float(pad['xmax'])
output += self.make_float(pad['ymin'])
output += self.make_float(pad['ymax'])
output += self.make_float(pad['zmin'])
output += self.make_float(pad['zmax'])
output += pad['liftnum'].to_bytes(1, 'big')
output = assetmgr.pad4(output)
offsets += pos.to_bytes(2, 'big')
pos = start + len(output)
offsets = assetmgr.pad4(offsets)
return offsets + output
return output
# Some pads need to store 0x80000000 (negative 0), but this isn't supported
# in JSON, nor does it appear to be a thing in Python, hence this hack.