diff --git a/port/src/preprocess/common.c b/port/src/preprocess/common.c new file mode 100644 index 000000000..542b9d8dc --- /dev/null +++ b/port/src/preprocess/common.c @@ -0,0 +1,33 @@ +#include "common.h" +#include "system.h" + +struct ptrmarker m_PtrMarkers[1024*8]; +int m_NumPtrMarkers; + +void addMarker(u32 ptr_src, uintptr_t ptr_host) +{ + if (m_NumPtrMarkers >= ARRAYCOUNT(m_PtrMarkers)) { + sysLogPrintf(LOG_ERROR, "Marker limit exceeded"); + exit(EXIT_FAILURE); + } + + m_PtrMarkers[m_NumPtrMarkers].ptr_src = ptr_src; + m_PtrMarkers[m_NumPtrMarkers].ptr_host = ptr_host; + m_NumPtrMarkers++; +} + +struct ptrmarker* findPtrMarker(uintptr_t ptr_src) +{ + for (int i = 0; i < m_NumPtrMarkers; i++) { + if (m_PtrMarkers[i].ptr_src == ptr_src) { + return &m_PtrMarkers[i]; + } + } + + return NULL; +} + +void resetMarkers() +{ + m_NumPtrMarkers = 0; +} diff --git a/port/src/preprocess/common.h b/port/src/preprocess/common.h new file mode 100644 index 000000000..0f9930d94 --- /dev/null +++ b/port/src/preprocess/common.h @@ -0,0 +1,119 @@ +#ifndef _PDE_COMMON_H +#define _PDE_COMMON_H + +#include +#include +#include + +#include +// this BS comes from windows.h +#undef near +#undef far + +#include + +#include + +#include "types.h" +#include "constants.h" + + +#if __BIG_ENDIAN__ + #define htonll(x) (x) + #define ntohll(x) (x) +#else + #define htonll(x) ((((uint64_t)htonl(x&0xFFFFFFFF)) << 32) + htonl(x >> 32)) + #define ntohll(x) ((((uint64_t)ntohl(x&0xFFFFFFFF)) << 32) + ntohl(x >> 32)) +#endif + +#define htobe16(x) htons(x) +#define htole16(x) (x) +#define be16toh(x) ntohs(x) +#define le16toh(x) (x) + +#define htobe32(x) htonl(x) +#define htole32(x) (x) +#define be32toh(x) ntohl(x) +#define le32toh(x) (x) + +#define htobe64(x) htonll(x) +#define htole64(x) (x) +#define be64toh(x) ntohll(x) +#define le64toh(x) (x) + + +#define srctoh16(value) ntohs(value) +#define srctoh32(value) ntohl(value) +#define srctoh64(value) ntohll(value) + +#ifdef FORCE_BE32 +#define htodst16(value) htons(value) +#define htodst32(value) htonl(value) +#define htodst64(value) htonll(value) +#define dsttoh16(value) ntohs(value) +#define dsttoh32(value) ntohl(value) +#define dsttoh64(value) ntohll(value) +#else +#define htodst16(value) (value) +#define htodst32(value) (value) +#define htodst64(value) (value) +#define dsttoh16(value) (value) +#define dsttoh32(value) (value) +#define dsttoh64(value) (value) +#endif + +#define srctodst16(value) htodst16(srctoh16(value)) +#define srctodst32(value) htodst32(srctoh32(value)) +#define srctodst64(value) htodst64(srctoh64(value)) + +#ifdef FORCE_BE32 +#define uintptr_t u32 +#endif + +#define ALIGN(val, size) ((val + (size - 1)) & ~(size - 1)) + +#define PD_PTR_BASE(x, b) (void *)((u8 *)b + (uintptr_t)x) +#define PD_PTR_BASEOFS(x, b, d) (void *)((u8 *)b - d + (uintptr_t)x) + + +static inline f32 swapF32(f32 x) { *(u32*)&x = PD_BE32(*(u32*)&x); return x; } +static inline u32 swapU32(u32 x) { return PD_BE32(x); } +static inline s32 swapS32(s32 x) { return PD_BE32(x); } +static inline u16 swapU16(u16 x) { return PD_BE16(x); } +static inline s16 swapS16(s16 x) { return PD_BE16(x); } +static inline void* swapPtr(void** x) { return (void*)PD_BEPTR((uintptr_t)x); } +static inline struct coord swapCrd(struct coord crd) { crd.x = swapF32(crd.x); crd.y = swapF32(crd.y); crd.z = swapF32(crd.z); return crd; } +static inline u32 swapUnk(u32 x) { assert(0 && "unknown type"); return x; } + +#define PD_SWAP_VAL(x) x = _Generic((x), \ + f32: swapF32, \ + u32: swapU32, \ + s32: swapS32, \ + u16: swapU16, \ + s16: swapS16, \ + struct coord: swapCrd, \ + default: swapUnk \ +)(x) + +#define PD_SWAP_PTR(x) x = swapPtr((void *)(x)) + +// gbi related functions +void gbiReset(void); +void gbiSetSegment(int segment, u32 offset); +void gbiSetVtx(u32 src_offset, u32 dst_offset); +u32 gbiConvertGdl(u8 *dst, u32 dstpos, u8 *src, u32 srcpos, int segment_cmds); +void gbiConvertVtx(u8* dst, u32 dstpos, int count); +void gbiGdlRewriteAddrs(u8* dst, u32 offset); +void gbiAddTexAddr(u32 src_offset, u32 dst_offset); + +// ptr marker functions +struct ptrmarker { + u32 ptr_src; + uintptr_t ptr_host; +}; + +void addMarker(u32 ptr_src, uintptr_t ptr_host); +struct ptrmarker* findPtrMarker(uintptr_t ptr_src); +void resetMarkers(); + +#endif diff --git a/port/src/preprocess/filebg.c b/port/src/preprocess/filebg.c new file mode 100644 index 000000000..b592e1e18 --- /dev/null +++ b/port/src/preprocess/filebg.c @@ -0,0 +1,651 @@ +#include +#include +#include +#include + +#include "data.h" +#include "bss.h" +#include "platform.h" + +#include "common.h" +#include "system.h" + +int m_SizeGDLs; + +/** + * 4 bytes decompressed size of primary data + * 4 bytes compressed size of section 1 in its entirety + * 4 bytes compressed size of primary data + * Section 1: + * Primary: (zipped) + * 4 bytes null + * 4 bytes pointer to room table + * 4 bytes pointer to portal table + * 4 bytes pointer to bgcmds + * 4 bytes pointer to lights table + * 4 bytes null + * (room table) + * (portal table) + * (bgcmds) + * (lights table) + * room 1 (zipped) + * room 2 (zipped) + * ... + * Section 2: + * 2 bytes decompressed size of section (mask with 0x7fff) + * 2 bytes compressed size of section + * Texture ID list (zipped) + * Section 3: + * 2 bytes decompressed size of section (mask with 0x7fff) + * 2 bytes compressed size of section + * Zipped: + * (room bbox table) + * (list of roomgfxdata sizes) + * (list of light counts per room) + */ + +struct fileheader { + u32 primary_infsize; + u32 section1_cmpsize; + u32 primary_cmpsize; +}; + +struct sectionheader { + u16 infsize; + u16 cmpsize; +}; + +struct n64_primaryheader { + u32 unused1; + u32 ptr_rooms; + u32 ptr_portals; + u32 ptr_bgcmds; + u32 ptr_lights; + u32 unused2; +}; + +struct host_primaryheader { + uintptr_t unused1; + uintptr_t ptr_rooms; + uintptr_t ptr_portals; + uintptr_t ptr_bgcmds; + uintptr_t ptr_lights; + uintptr_t unused2; +}; + +struct n64_room { + u32 ptr_gfxdata; + u32 pos[3]; + u8 br_light_min; + u8 br_light_max; +}; + +struct host_room { + uintptr_t ptr_gfxdata; + u32 pos[3]; + u8 br_light_min; + u8 br_light_max; +}; + +struct portal { + u16 verticesoffset; + s16 roomnum1; + s16 roomnum2; + u8 flags; +}; + +struct generic_portalvertices { + u8 count; + u32 vertices[1][3]; +}; + +/* +struct light { + u16 roomnum; + u16 colour; + u8 brightness; + u8 sparkable : 1; + u8 healthy : 1; + u8 on : 1; + u8 sparking : 1; + u8 vulnerable : 1; + u8 brightnessmult; + s8 dirx; + s8 diry; + s8 dirz; + s16 bbox[4][3]; +};*/ + +struct n64_roomblock { + u8 type; + u32 ptr_next; + u32 ptr_gdl; + u32 ptr_vertices; + u32 ptr_colours; +}; + +struct host_roomblock { + u8 type; + uintptr_t ptr_next; + uintptr_t ptr_gdl; + uintptr_t ptr_vertices; + uintptr_t ptr_colours; +}; + +struct n64_roomgfxdata { + u32 ptr_vertices; + u32 ptr_colours; + u32 ptr_opablocks; + u32 ptr_xlublocks; + s16 lightsindex; + s16 numlights; + s16 numvertices; + s16 numcolours; + // roomblocks[] +}; + +struct host_roomgfxdata { + uintptr_t ptr_vertices; + uintptr_t ptr_colours; + uintptr_t ptr_opablocks; + uintptr_t ptr_xlublocks; + s16 lightsindex; + s16 numlights; + s16 numvertices; + s16 numcolours; + // roomblocks[] +}; + +struct vtx { + s16 coord[3]; + u8 flag; + u8 color; + u16 s; + u16 t; +}; + +int m_NumRooms; + +u32 m_AllocSizes[512]; + +static void convertPrimaryRooms(u8 *dst, u32 *dstpos, u8 *src, u32 *srcpos) +{ + struct n64_room *n64_rooms = (struct n64_room *) &src[*srcpos]; + struct host_room *host_rooms = (struct host_room *) &dst[*dstpos]; + + m_NumRooms = 0; + + for (int i = 1; n64_rooms[i].ptr_gfxdata != 0; i++) { + m_NumRooms++; + } + + for (int i = 0; i < m_NumRooms + 1; i++) { + host_rooms[i].ptr_gfxdata = srctodst32(n64_rooms[i].ptr_gfxdata); + host_rooms[i].pos[0] = srctodst32(n64_rooms[i].pos[0]); + host_rooms[i].pos[1] = srctodst32(n64_rooms[i].pos[1]); + host_rooms[i].pos[2] = srctodst32(n64_rooms[i].pos[2]); + host_rooms[i].br_light_min = n64_rooms[i].br_light_min; + host_rooms[i].br_light_max = n64_rooms[i].br_light_max; + } + + *srcpos += sizeof(*n64_rooms) * (m_NumRooms + 2); + *dstpos += sizeof(*host_rooms) * (m_NumRooms +2); +} + +static void convertPrimaryPortals(u8 *dst, u32 *dstpos, u8 *src, u32 *srcpos, u32 *src_portalvtxs, u32 *dst_portalvtxs) +{ + struct portal *n64_portals = (struct portal *) &src[*srcpos]; + struct portal *host_portals = (struct portal *) &dst[*dstpos]; + + // Count portals + int numportals = 0; + + for (int i = 0; n64_portals[i].verticesoffset != 0; i++) { + numportals++; + } + + // Convert portals + for (int i = 0; i < numportals; i++) { + host_portals[i].verticesoffset = srctodst16(n64_portals[i].verticesoffset); + host_portals[i].roomnum1 = srctodst16(n64_portals[i].roomnum1); + host_portals[i].roomnum2 = srctodst16(n64_portals[i].roomnum2); + host_portals[i].flags = n64_portals[i].flags; + } + + *srcpos += sizeof(*n64_portals) * (numportals + 1); + *dstpos += sizeof(*host_portals) * (numportals + 1); + + *src_portalvtxs = *srcpos; + *dst_portalvtxs = *dstpos; + + while (1) { + struct generic_portalvertices *n64_pvertices = (struct generic_portalvertices*)&src[*srcpos]; + struct generic_portalvertices*host_pvertices = (struct generic_portalvertices*)&dst[*dstpos]; + + host_pvertices->count = n64_pvertices->count; + + for (int j = 0; j < host_pvertices->count; j++) { + //host_pvertices->vertices[j].x = srctodst32(n64_pvertices->vertices[j].x); + //host_pvertices->vertices[j].y = srctodst32(n64_pvertices->vertices[j].y); + //host_pvertices->vertices[j].z = srctodst32(n64_pvertices->vertices[j].z); + host_pvertices->vertices[j][0] = srctodst32(n64_pvertices->vertices[j][0]); + host_pvertices->vertices[j][1] = srctodst32(n64_pvertices->vertices[j][1]); + host_pvertices->vertices[j][2] = srctodst32(n64_pvertices->vertices[j][2]); + } + + *srcpos += 4 + host_pvertices->count * 12; + *dstpos += 4 + host_pvertices->count * 12; + + if (host_pvertices->count == 0) break; + } +} + +static void convertPrimaryBgCmds(u8 *dst, u32 *dstpos, u8 *src, u32 dst_portalvtxs, u32 src_portalvtxs) +{ + struct bgcmd *n64_cmds = (struct bgcmd *) src; + struct bgcmd *host_cmds = (struct bgcmd *) &dst[*dstpos]; + int num_cmds = 0; + + for (int i = 0; n64_cmds[i].type != 0; i++) { + num_cmds++; + } + + num_cmds++; + + for (int i = 0; i < num_cmds; i++) { + host_cmds[i].type = n64_cmds[i].type; + host_cmds[i].len = n64_cmds[i].len; + host_cmds[i].param = srctodst32(n64_cmds[i].param); + + if (host_cmds[i].type == 0x64) { + u32 offset = host_cmds[i].param - src_portalvtxs; + host_cmds[i].param = dst_portalvtxs + offset; + } + } + + *dstpos += sizeof(*host_cmds) * num_cmds; +} + +static void convertPrimaryLights(u8 *dst, u32 *dstpos, u8 *src, u32 *srcpos, u32 end) +{ + struct light *n64_lights = (struct light *) &src[*srcpos]; + struct light *host_lights = (struct light *) &dst[*dstpos]; + int num_lights = (end - *srcpos) / sizeof(struct light); + + for (int i = 0; i < num_lights; i++) { + host_lights[i].roomnum = srctodst16(n64_lights[i].roomnum); + host_lights[i].colour = srctodst16(n64_lights[i].colour); + host_lights[i].brightness = n64_lights[i].brightness; + host_lights[i].sparkable = n64_lights[i].sparkable; + host_lights[i].healthy = n64_lights[i].healthy; + host_lights[i].on = n64_lights[i].on; + host_lights[i].sparking = n64_lights[i].sparking; + host_lights[i].vulnerable = n64_lights[i].vulnerable; + host_lights[i].brightnessmult = n64_lights[i].brightnessmult; + host_lights[i].dirx = n64_lights[i].dirx; + host_lights[i].diry = n64_lights[i].diry; + host_lights[i].dirz = n64_lights[i].dirz; + + for (int j = 0; j < 4; j++) { + host_lights[i].bbox[j].x = srctodst16(n64_lights[i].bbox[j].x); + host_lights[i].bbox[j].y = srctodst16(n64_lights[i].bbox[j].y); + host_lights[i].bbox[j].z = srctodst16(n64_lights[i].bbox[j].z); + } + } + + *srcpos += sizeof(*n64_lights) * num_lights; + *dstpos += sizeof(*host_lights) * num_lights; +} + +#define BLOCK_LEAF 0 +#define BLOCK_PARENT 1 + +void relinkPtr(uintptr_t** ptr) +{ + if (!*ptr) return; + + struct ptrmarker* marker = findPtrMarker(*ptr); + if (!marker) { + fprintf(stderr, "[BG] WARNING: Unable to relink pointer: %p\n", ptr); + exit(EXIT_FAILURE); + } + + *ptr = marker->ptr_host; +} + +static u32 convertRoomGfxData(u8 *dst, u8 *src, u32 infsize, u32 src_ofs) +{ + resetMarkers(); + gbiReset(); + + u32 dst_roomoffset = src_ofs; + + uintptr_t gdls_addr[64]; + int numgdls = 0; + + struct n64_roomgfxdata *src_header = (struct n64_roomgfxdata*)src; + struct host_roomgfxdata *dst_header = (struct host_roomgfxdata*)dst; + + dst_header->ptr_vertices = srctoh32(src_header->ptr_vertices); + dst_header->ptr_colours = srctoh32(src_header->ptr_colours); + dst_header->ptr_opablocks = srctoh32(src_header->ptr_opablocks); + dst_header->ptr_xlublocks = srctoh32(src_header->ptr_xlublocks); + dst_header->lightsindex = srctoh16(src_header->lightsindex); + dst_header->numlights = srctoh16(src_header->numlights); + dst_header->numvertices = srctoh16(src_header->numvertices); + dst_header->numcolours = srctoh16(src_header->numcolours); + + intptr_t endpos = dst_header->ptr_vertices - src_ofs; + uintptr_t curpos_src = sizeof(struct n64_roomgfxdata); + uintptr_t curpos_dst = sizeof(struct host_roomgfxdata); + + // roomblocks + int ncoords = 0; + + // save the ptr to roomblocks here to iterate later to fix the pointers + struct host_roomblock *ptr_dst_roomblocks = (struct host_roomblock*)&dst[curpos_dst]; + + int numblocks = 0; + while ((intptr_t)(curpos_src + sizeof(struct n64_roomblock)) <= endpos) { + struct n64_roomblock *src_roomblock = (struct n64_roomblock*)&src[curpos_src]; + struct host_roomblock *dest_roomblock = (struct host_roomblock*)&dst[curpos_dst]; + + dest_roomblock->type = src_roomblock->type; + dest_roomblock->ptr_next = srctoh32(src_roomblock->ptr_next); + dest_roomblock->ptr_gdl = srctoh32(src_roomblock->ptr_gdl); + dest_roomblock->ptr_vertices = srctoh32(src_roomblock->ptr_vertices); + dest_roomblock->ptr_colours = srctoh32(src_roomblock->ptr_colours); + + addMarker(curpos_src + src_ofs, curpos_dst + dst_roomoffset); + + if (src_roomblock->type == BLOCK_PARENT) { + ncoords++; + uintptr_t vtx_ptr = dest_roomblock->ptr_vertices - src_ofs; + if (vtx_ptr < endpos) endpos = vtx_ptr; + } + else if (src_roomblock->ptr_gdl) { + gdls_addr[numgdls++] = srctoh32(src_roomblock->ptr_gdl) - src_ofs; + } + + curpos_src += sizeof(struct n64_roomblock); + curpos_dst += sizeof(struct host_roomblock); + numblocks++; + } + + // block coords + for (size_t i = 0; i < ncoords; i++) { + u32 *src_coord = (u32*)(src + curpos_src); + u32 *dst_coord = (u32*)(dst + curpos_dst); + + dst_coord[0] = srctoh32(src_coord[0]); + dst_coord[1] = srctoh32(src_coord[1]); + dst_coord[2] = srctoh32(src_coord[2]); + + dst_coord[3] = srctoh32(src_coord[3]); + dst_coord[4] = srctoh32(src_coord[4]); + dst_coord[5] = srctoh32(src_coord[5]); + + addMarker(curpos_src + src_ofs, curpos_dst + dst_roomoffset); + + curpos_src += 6 * sizeof(u32); + curpos_dst += 6 * sizeof(u32); + } + + curpos_dst = ALIGN8(curpos_dst); + + // vertices + uintptr_t ptr_src_vertices = curpos_src = ALIGN8(dst_header->ptr_vertices - src_ofs); + uintptr_t ptr_dst_vertices = curpos_dst + dst_roomoffset; + + addMarker(curpos_src + src_ofs, curpos_dst + dst_roomoffset); + + uintptr_t vtx_end = dst_header->ptr_colours - src_ofs; + + while (dst_header->ptr_colours && curpos_src < vtx_end) { + struct vtx *src_vtx = (struct vtx*)(src + curpos_src); + struct vtx *dst_vtx = (struct vtx*)(dst + curpos_dst); + + dst_vtx->coord[0] = srctoh16(src_vtx->coord[0]); + dst_vtx->coord[1] = srctoh16(src_vtx->coord[1]); + dst_vtx->coord[2] = srctoh16(src_vtx->coord[2]); + + dst_vtx->flag = src_vtx->flag; + dst_vtx->color = src_vtx->color; + + dst_vtx->s = srctoh16(src_vtx->s); + dst_vtx->t = srctoh16(src_vtx->t); + + curpos_src += sizeof(struct vtx); + curpos_dst += sizeof(struct vtx); + } + + curpos_dst = ALIGN8(curpos_dst); + + // colors + uintptr_t ptr_src_colors = 0; + uintptr_t ptr_dst_colors = 0; + + if (dst_header->ptr_colours) { + ptr_src_colors = curpos_src = ALIGN8(dst_header->ptr_colours - src_ofs); + ptr_dst_colors = curpos_dst + dst_roomoffset; + + addMarker(curpos_src + src_ofs, curpos_dst + dst_roomoffset); + + uintptr_t col_end = numgdls > 0 != 0 ? gdls_addr[0] : infsize; + size_t col_len = col_end - curpos_src; + + memcpy(dst + curpos_dst, src + curpos_src, col_len); + curpos_src += col_len; + curpos_dst += col_len; + } + + // gdls + gbiSetVtx(src_header->ptr_vertices, ptr_src_vertices); + gbiSetSegment(0x0e, dst_header->ptr_vertices); + + m_SizeGDLs = 0; + uintptr_t gdlstart = curpos_dst; + for (size_t i = 0; i < numgdls; i++) { + addMarker(gdls_addr[i] + src_ofs, curpos_dst + dst_roomoffset); + curpos_dst = gbiConvertGdl(dst, curpos_dst, src, gdls_addr[i], 1); + } + m_SizeGDLs = curpos_dst - gdlstart; + + // relink ptrs: roomblocks + for (size_t i = 0; i < numblocks; i++) { + struct host_roomblock *block = (struct host_roomblock*)&ptr_dst_roomblocks[i]; + + relinkPtr(&block->ptr_next); + + if (block->type == BLOCK_LEAF) { + relinkPtr(&block->ptr_gdl); + u32 offset_vtx = block->ptr_vertices - ptr_src_vertices - src_ofs; + u32 offset_col = block->ptr_colours - ptr_src_colors - src_ofs; + + block->ptr_vertices = ptr_dst_vertices + offset_vtx; + block->ptr_colours = ptr_dst_colors + offset_col; + } + else { + relinkPtr(&block->ptr_gdl); // child + relinkPtr(&block->ptr_vertices); // coord + } + } + + // relink ptrs: header + relinkPtr(&dst_header->ptr_vertices); + relinkPtr(&dst_header->ptr_colours); + relinkPtr(&dst_header->ptr_opablocks); + relinkPtr(&dst_header->ptr_xlublocks); + + return curpos_dst; +} + +static u32 convertSection1(u8 *dst, u8 *src, u32 ofs) +{ + // Convert primary + u32 srcpos = 0; + u32 dstpos = 0; + struct host_primaryheader *host_primary_header = (struct host_primaryheader *) dst; + struct n64_primaryheader *n64_primary_header = (struct n64_primaryheader *) src; + srcpos += sizeof(struct n64_primaryheader); + dstpos += sizeof(*host_primary_header); + + u32 src_bgcmds = srctodst32(n64_primary_header->ptr_bgcmds) - ofs; + + host_primary_header->unused1 = 0; + host_primary_header->unused2 = 0; + + host_primary_header->ptr_rooms = dstpos + ofs; + convertPrimaryRooms(dst, &dstpos, src, &srcpos); + + if (n64_primary_header->ptr_lights) { + host_primary_header->ptr_lights = dstpos + ofs; + srcpos = srctodst32(n64_primary_header->ptr_lights) - ofs; + convertPrimaryLights(dst, &dstpos, src, &srcpos, src_bgcmds); + } + + host_primary_header->ptr_portals = dstpos + ofs; + srcpos = srctodst32(n64_primary_header->ptr_portals) - ofs; + u32 src_portalvtxs, dst_portalvtxs; + convertPrimaryPortals(dst, &dstpos, src, &srcpos, &src_portalvtxs, &dst_portalvtxs); + + host_primary_header->ptr_bgcmds = dstpos + ofs; + convertPrimaryBgCmds(dst, &dstpos, &src[src_bgcmds], dst_portalvtxs, src_portalvtxs); + + return dstpos; +} + +static void convert_section2_texturenums(u8 *dst, u32 *dstpos, u8 *src, u32 *srcpos, u32 srclen) +{ + u16 *src_ids = (u16 *) &src[*srcpos]; + u16 *dst_ids = (u16 *) &dst[*dstpos]; + int count = srclen / sizeof(u16); + + for (int i = 0; i < count; i++) { + dst_ids[i] = srctodst16(src_ids[i]); + } + + *srcpos += srclen; + *dstpos += srclen; +} + +static void convert_section3_bboxes(u8 *dst, u32 *dstpos, u8 *src, u32 *srcpos) +{ + s16 *src_bboxes = (s16 *) &src[*srcpos]; + s16 *dst_bboxes = (s16 *) &dst[*dstpos]; + + for (int i = 0; i < m_NumRooms; i++) { + dst_bboxes[i * 6 + 0] = srctodst16(src_bboxes[i * 6 + 0]); + dst_bboxes[i * 6 + 1] = srctodst16(src_bboxes[i * 6 + 1]); + dst_bboxes[i * 6 + 2] = srctodst16(src_bboxes[i * 6 + 2]); + dst_bboxes[i * 6 + 3] = srctodst16(src_bboxes[i * 6 + 3]); + dst_bboxes[i * 6 + 4] = srctodst16(src_bboxes[i * 6 + 4]); + dst_bboxes[i * 6 + 5] = srctodst16(src_bboxes[i * 6 + 5]); + } + + *srcpos += sizeof(s16) * 6 * (m_NumRooms - 1); + *dstpos += sizeof(s16) * 6 * (m_NumRooms - 1); +} + +static void convert_section3_allocsizes(u8 *dst, u32 *dstpos, u8 *src, u32 *srcpos) +{ + u16 *dst_sizes = (u16 *) &dst[*dstpos]; + + for (int i = 0; i < m_NumRooms; i++) { + dst_sizes[i] = (m_AllocSizes[i] - 0x100) / 0x10; + } + + *srcpos += sizeof(u16) * (m_NumRooms - 1); + *dstpos += sizeof(u16) * (m_NumRooms - 1); +} + +static void convert_section3_lightcounts(u8 *dst, u32 *dstpos, u8 *src, u32 *srcpos) +{ + memcpy(&dst[*dstpos], &src[*srcpos], m_NumRooms); + + *srcpos += (m_NumRooms - 1); + *dstpos += (m_NumRooms - 1); +} + +void preprocessBgSection1(u8 *data, u32 size, u32 ofs) +{ + u8 *dst = sysMemZeroAlloc(size); + + u32 newSize = convertSection1(dst, data, ofs); + + if (newSize > size) { + sysLogPrintf(LOG_ERROR, "overflow when trying to preprocess a bg file, size %d newsize %d", size, newSize); + exit(EXIT_FAILURE); + } + + memcpy(data, dst, newSize); + sysMemFree(dst); +} + +u32 preprocessBgRoom(u8 *data, u32 size, u32 room_ofs) +{ + size *= 2; + u8 *dst = sysMemZeroAlloc(size); + u32 newSize = convertRoomGfxData(dst, data, size, room_ofs); + + if (newSize > size) { + sysLogPrintf(LOG_ERROR, "overflow when trying to preprocess a bg room, size %d newsize %d", size, newSize); + exit(EXIT_FAILURE); + } + + memcpy(data, dst, newSize); + sysMemFree(dst); + + return newSize; +} + +void preprocessBgSection1Header(u8* data, u32 size) +{ + u32* header = (u32*)data; + PD_SWAP_VAL(header[0]); // inflatedsize + PD_SWAP_VAL(header[1]); // section1size + PD_SWAP_VAL(header[2]); // primcompsize +} + +void preprocessBgSection2Header(u8* data, u32 size) +{ + u16* header = (u16*)data; + PD_SWAP_VAL(header[0]); // inflatedsize + PD_SWAP_VAL(header[1]); // section2compsize +} + +void preprocessBgSection2(u8* data, u32 size) +{ + // section2 is a texture id list + u16* section2 = (u16*)data; + for (s32 i = 0; i < size; ++i) { + PD_SWAP_VAL(section2[i]); + } +} + +void preprocessBgSection3Header(u8* data, u32 size) +{ + u16* header = (u16*)data; + PD_SWAP_VAL(header[0]); + PD_SWAP_VAL(header[1]); +} + +void preprocessBgSection3(u8* data, u32 size) +{ + // room bounding boxes, 6x s16 per room + s16* bbox = (s16*)data; + for (s32 i = 1; i < g_Vars.roomcount; ++i) { + PD_SWAP_VAL(*bbox); ++bbox; + PD_SWAP_VAL(*bbox); ++bbox; + PD_SWAP_VAL(*bbox); ++bbox; + PD_SWAP_VAL(*bbox); ++bbox; + PD_SWAP_VAL(*bbox); ++bbox; + PD_SWAP_VAL(*bbox); ++bbox; + } + + // gfxdatalen list + u16* gfxdatalen = (u16*)bbox; + for (s32 i = 1; i < g_Vars.roomcount; ++i) { + PD_SWAP_VAL(*gfxdatalen); ++gfxdatalen; + } +} diff --git a/port/src/preprocess/filelang.c b/port/src/preprocess/filelang.c new file mode 100644 index 000000000..46abe902c --- /dev/null +++ b/port/src/preprocess/filelang.c @@ -0,0 +1,95 @@ +#include +#include +#include + +#include "common.h" +#include "romdata.h" +#include "system.h" + +static int getNextNonZero(u8 *src, u32 offset, size_t len) +{ + u32 *ptr = (u32 *) &src[offset]; + u32 *end = (u32 *) &src[len]; + + while (ptr < end) { + if (*ptr != 0) { + return srctoh32(*ptr); + } + + ptr++; + } + + return 0; +} + +static int getNumStrings(u8 *src, size_t len) +{ + u32 ptr_table_len = getNextNonZero(src, 0, len); + + if (ptr_table_len) { + return ptr_table_len / sizeof(u32); + } + + return 1; +} + +u32 convertLangFile(u8 *dst, u8 *src, size_t srclen) +{ + // Convert it + u32 *src_offsets = (u32 *) src; + size_t src_ptr_table_len = srctoh32(src_offsets[0]); + size_t src_str_table_len = srclen - src_ptr_table_len; + int num_strings = getNumStrings(src, srclen); + size_t dst_ptr_table_len = num_strings * sizeof(uintptr_t); + size_t dst_str_table_len = src_str_table_len; + + int cur_dst_offset = dst_ptr_table_len; + + uintptr_t *dst_offsets = (uintptr_t *) dst; + + for (int i = 0; i < num_strings; i++) { + u32 src_offset = srctoh32(src_offsets[i]); + + if (src_offset) { + // Write pointer + dst_offsets[i] = htodst32(cur_dst_offset); + + // Write string + u32 end = getNextNonZero(src, (i + 1) * 4, num_strings * 4); + + if (!end) { + end = srclen; + } + + size_t len = end - src_offset; + len = ALIGN4(len); + memcpy(&dst[cur_dst_offset], &src[src_offset], len); + + cur_dst_offset += len; + } else { + // Write pointer + dst_offsets[i] = 0; + } + } + + return ALIGN16(cur_dst_offset); +} + +u8 *preprocessLangFile(u8 *data, u32 size, u32 *outSize) { + u32 newSizeEstimated = romdataFileGetEstimatedSize(size, FT_LANG); + u8 *dst = sysMemZeroAlloc(newSizeEstimated); + + u32 newSize = convertLangFile(dst, data, size); + + if (newSize > newSizeEstimated) { + sysLogPrintf(LOG_ERROR, "overflow when trying to preprocess a lang file, size %d newsize %d", size, newSize); + exit(EXIT_FAILURE); + } + + memcpy(data, dst, newSize); + sysMemFree(dst); + + *outSize = newSize; + + return 0; +} diff --git a/port/src/preprocess/filemodel.c b/port/src/preprocess/filemodel.c new file mode 100644 index 000000000..5edece56e --- /dev/null +++ b/port/src/preprocess/filemodel.c @@ -0,0 +1,1021 @@ +#include +#include +#include + +#include "types.h" +#include "gbi.h" +#include "game/texdecompress.h" + +#include "common.h" +#include "romdata.h" +#include "system.h" + +enum contenttype { + /* 0*/ CT_MODELDEF, + /* 1*/ CT_NODE, + /* 2*/ CT_TEXCONFIG, + /* 3*/ CT_TEXDATA, + /* 4*/ CT_PARTS, + /* 5*/ CT_VTXCOL, + /* 6*/ CT_GDL, + /* 7*/ CT_RODATA_CHRINFO, + /* 8*/ CT_RODATA_POSITION, + /* 9*/ CT_RODATA_GUNDL, + /*10*/ CT_RODATA_DISTANCE, + /*11*/ CT_RODATA_REORDER, + /*12*/ CT_RODATA_BBOX, + /*13*/ CT_RODATA_CHRGUNFIRE, + /*14*/ CT_RODATA_11, + /*15*/ CT_RODATA_TOGGLE, + /*16*/ CT_RODATA_POSITIONHELD, + /*17*/ CT_RODATA_STARGUNFIRE, + /*18*/ CT_RODATA_HEADSPOT, + /*19*/ CT_RODATA_DL, + /*20*/ CT_RODATA_19, + /*21*/ CT_VTXCOL4, // CT_VTXCOL but aligned to 4 bytes instead of 8 +}; + +struct marker { + u32 src_offset; + u32 dst_offset; + u32 parent_src_offset; + enum contenttype type; +}; + +struct alignconfig { + int before; + int after; +}; + +struct alignconfig m_AlignConfigs[] = { + /* 0*/ { 16, 4 }, + /* 1*/ { 4, 4 }, + /* 2*/ { 4, 4 }, + /* 3*/ { 8, 8 }, // CT_TEXDATA + /* 4*/ { 4, 4 }, + /* 5*/ { 8, 4 }, // CT_VTXCOL + /* 6*/ { 8, 8 }, // CT_GDL + /* 7*/ { 4, 4 }, + /* 8*/ { 4, 4 }, + /* 9*/ { 8, 4 }, // CT_GUNDL + /*10*/ { 4, 4 }, + /*11*/ { 4, 4 }, + /*12*/ { 4, 4 }, + /*13*/ { 4, 4 }, + /*14*/ { 4, 4 }, + /*15*/ { 4, 4 }, + /*16*/ { 4, 4 }, + /*17*/ { 8, 4 }, // CT_STARGUNFIRE + /*18*/ { 4, 4 }, + /*19*/ { 8, 4 }, // CT_RODATA_DL + /*20*/ { 4, 4 }, + /*21*/ { 4, 4 }, +}; + +struct marker m_Markers[1024]; +int m_NumMarkers; + +struct src_modeldef { + u32 ptr_rootnode; + u32 ptr_skel; + u32 ptr_parts; + s16 numparts; + s16 nummatrices; + u32 scale; + u16 rwdatalen; + u16 numtexconfigs; + u32 ptr_texconfigs; +}; + +struct dst_modeldef { + uintptr_t ptr_rootnode; + uintptr_t ptr_skel; + uintptr_t ptr_parts; + s16 numparts; + s16 nummatrices; + u32 scale; + u16 rwdatalen; + u16 numtexconfigs; + uintptr_t ptr_texconfigs; +}; + +struct src_modelnode { + u16 type; + u32 ptr_rodata; + u32 ptr_parent; + u32 ptr_next; + u32 ptr_prev; + u32 ptr_child; +}; + +struct dst_modelnode { + u16 type; + uintptr_t ptr_rodata; + uintptr_t ptr_parent; + uintptr_t ptr_next; + uintptr_t ptr_prev; + uintptr_t ptr_child; +}; + +struct generic_rodata_chrinfo { + u16 animpart; + s16 mtxindex; + u32 unk04; + u16 rwdataindex; +}; + +struct generic_rodata_position { + u32 pos[3]; + u16 part; + s16 mtxindexes[3]; + u32 drawdist; +}; + +struct src_rodata_gundl { + u32 ptr_opagdl; + u32 ptr_xlugdl; + u32 ptr_baseaddr; + u32 ptr_vertices; + s16 numvertices; + s16 unk12; +}; + +struct dst_rodata_gundl { + uintptr_t ptr_opagdl; + uintptr_t ptr_xlugdl; + uintptr_t ptr_baseaddr; + uintptr_t ptr_vertices; + s16 numvertices; + s16 unk12; +}; + +struct src_rodata_distance { + u32 near; + u32 far; + u32 ptr_target; + u16 rwdataindex; +}; + +struct dst_rodata_distance { + u32 near; + u32 far; + uintptr_t ptr_target; + u16 rwdataindex; +}; + +struct src_rodata_reorder { + u32 unk00; + u32 unk04; + u32 unk08; + u32 unk0c[3]; + u32 ptr_node_unk18; + u32 ptr_node_unk1c; + s16 side; + u16 rwdataindex; +}; + +struct dst_rodata_reorder { + u32 unk00; + u32 unk04; + u32 unk08; + u32 unk0c[3]; + uintptr_t ptr_node_unk18; + uintptr_t ptr_node_unk1c; + s16 side; + u16 rwdataindex; +}; + +struct generic_rodata_bbox { + s32 hitpart; + u32 bbox[6]; +}; + +struct src_rodata_chrgunfire { + u32 pos[3]; + u32 dim[3]; + u32 ptr_texture; + u32 unk1c; + u16 rwdataindex; + u32 ptr_baseaddr; +}; + +struct dst_rodata_chrgunfire { + u32 pos[3]; + u32 dim[3]; + uintptr_t ptr_texture; + u32 unk1c; + u16 rwdataindex; + uintptr_t ptr_baseaddr; +}; + +struct src_rodata_type11 { + u32 unk00; + u32 unk04; + u32 unk08; + u32 unk0c; + u32 unk10; + u32 ptr_unk14; // not used + u32 extra1; + u32 extra2; +}; + +struct dst_rodata_type11 { + u32 unk00; + u32 unk04; + u32 unk08; + u32 unk0c; + u32 unk10; + u32 unk14; + u32 extra1; + u32 extra2; +}; + +struct src_rodata_toggle { + u32 ptr_target; + u16 rwdataindex; +}; + +struct dst_rodata_toggle { + uintptr_t ptr_target; + u16 rwdataindex; +}; + +struct generic_rodata_positionheld { + u32 pos[3]; + s16 mtxindex; + u32 unk10; +}; + +struct src_rodata_stargunfire { + u32 unk00; + u32 ptr_vertices; + u32 ptr_gdl; + u32 ptr_baseaddr; +}; + +struct dst_rodata_stargunfire { + u32 unk00; + uintptr_t ptr_vertices; + uintptr_t ptr_gdl; + uintptr_t ptr_baseaddr; +}; + +struct generic_rodata_headspot { + u16 rwdataindex; +}; + +struct src_rodata_dl { + u32 ptr_opagdl; + u32 ptr_xlugdl; + u32 ptr_colours; + u32 ptr_vertices; // colours follow this array + s16 numvertices; + s16 mcount; + u16 rwdataindex; + u16 numcolours; +}; + +struct dst_rodata_dl { + uintptr_t ptr_opagdl; + uintptr_t ptr_xlugdl; + uintptr_t ptr_colours; + uintptr_t ptr_vertices; // colours follow this array + s16 numvertices; + s16 mcount; + u16 rwdataindex; + u16 numcolours; +}; + +struct generic_rodata_type19 { + u32 numvertices; + u32 vertices[3]; +}; + +struct src_texconfig { + u32 ptr; + u8 width; + u8 height; + u8 level; + u8 format; + u8 depth; + u8 s; + u8 t; + u8 unk0b; +}; + +struct dst_texconfig { + uintptr_t ptr; + u8 width; + u8 height; + u8 level; + u8 format; + u8 depth; + u8 s; + u8 t; + u8 unk0b; +}; + +static inline void *minPtr(void *a, void *b) { + return (a && (a < b || !b)) ? a : b; +} + +static inline void *minPtr3(void *a, void *b, void *c) { + return minPtr(minPtr(a, b), c); +} + +static struct marker *find_marker(u32 src_offset) +{ + for (int i = 0; i < m_NumMarkers; i++) { + if (m_Markers[i].src_offset == src_offset) { + return &m_Markers[i]; + } + } + + return NULL; +} + +static void set_marker(u32 src_offset, enum contenttype type, u32 parent_src_offset) +{ + if (src_offset == 0) { + return; + } + + src_offset &= 0x00ffffff; + + if (find_marker(src_offset)) { + return; + } + + if (m_NumMarkers >= ARRAYCOUNT(m_Markers)) { + fprintf(stderr, "Marker limit exceeded\n"); + exit(EXIT_FAILURE); + } + + m_Markers[m_NumMarkers].src_offset = src_offset; + m_Markers[m_NumMarkers].type = type; + m_Markers[m_NumMarkers].parent_src_offset = parent_src_offset; + m_NumMarkers++; +} + +enum contenttype m_NodeTypeToContentType[] = { + /*0x00*/ -1, + /*0x01*/ CT_RODATA_CHRINFO, + /*0x02*/ CT_RODATA_POSITION, + /*0x03*/ -1, + /*0x04*/ CT_RODATA_GUNDL, + /*0x05*/ -1, + /*0x06*/ -1, + /*0x07*/ -1, + /*0x08*/ CT_RODATA_DISTANCE, + /*0x09*/ CT_RODATA_REORDER, + /*0x0a*/ CT_RODATA_BBOX, + /*0x0b*/ -1, + /*0x0c*/ CT_RODATA_CHRGUNFIRE, + /*0x0d*/ -1, + /*0x0e*/ -1, + /*0x0f*/ -1, + /*0x10*/ -1, + /*0x11*/ CT_RODATA_11, + /*0x12*/ CT_RODATA_TOGGLE, + /*0x13*/ -1, + /*0x14*/ -1, + /*0x15*/ CT_RODATA_POSITIONHELD, + /*0x16*/ CT_RODATA_STARGUNFIRE, + /*0x17*/ CT_RODATA_HEADSPOT, + /*0x18*/ CT_RODATA_DL, + /*0x19*/ CT_RODATA_19, +}; + +static void populateMarkers(u8 *src) +{ + m_NumMarkers = 0; + + set_marker(0x05000000, CT_MODELDEF, 0); + + for (int i = 0; i < m_NumMarkers; i++) { + struct marker *marker = &m_Markers[i]; + void *src_thing = &src[marker->src_offset]; + int numvtx = 0; + u32 colstart = 0; + + switch (marker->type) { + case CT_MODELDEF: + struct src_modeldef *src_modeldef = src_thing; + int num_texconfigs = srctoh16(src_modeldef->numtexconfigs); + u32 texconfigpos = srctoh32(src_modeldef->ptr_texconfigs); + set_marker(srctoh32(src_modeldef->ptr_rootnode), CT_NODE, marker->src_offset); + set_marker(srctoh32(src_modeldef->ptr_parts), CT_PARTS, marker->src_offset); + + for (int i = 0; i < num_texconfigs; i++) { + set_marker(texconfigpos + sizeof(struct src_texconfig) * i, CT_TEXCONFIG, marker->src_offset); + } + break; + case CT_NODE: + struct src_modelnode *src_node = src_thing; + u32 node_type = srctoh16(src_node->type) & 0xff; + set_marker(srctoh32(src_node->ptr_rodata), m_NodeTypeToContentType[node_type], marker->src_offset); + set_marker(srctoh32(src_node->ptr_parent), CT_NODE, marker->src_offset); + set_marker(srctoh32(src_node->ptr_next), CT_NODE, marker->src_offset); + set_marker(srctoh32(src_node->ptr_prev), CT_NODE, marker->src_offset); + set_marker(srctoh32(src_node->ptr_child), CT_NODE, marker->src_offset); + break; + case CT_TEXCONFIG: + struct src_texconfig *src_texconfig = src_thing; + if ((srctoh32(src_texconfig->ptr) & 0xff000000) == 0x05000000) { + set_marker(srctoh32(src_texconfig->ptr), CT_TEXDATA, marker->src_offset); + } + break; + case CT_PARTS: + struct src_modeldef *src_modeldef2 = (struct src_modeldef *) src; + u32 *src_parts = (u32 *) src_thing; + int num_parts = srctoh16(src_modeldef2->numparts); + + for (int i = 0; i < num_parts; i++) { + set_marker(srctoh32(src_parts[i]), CT_NODE, marker->src_offset); + } + break; + case CT_RODATA_CHRINFO: + break; + case CT_RODATA_POSITION: + break; + case CT_RODATA_GUNDL: + struct src_rodata_gundl *src_gundl = src_thing; + set_marker(srctoh32(src_gundl->ptr_opagdl), CT_GDL, marker->src_offset); + set_marker(srctoh32(src_gundl->ptr_xlugdl), CT_GDL, marker->src_offset); + set_marker(srctoh32(src_gundl->ptr_vertices), CT_VTXCOL, marker->src_offset); + break; + case CT_RODATA_DISTANCE: + struct src_rodata_distance *src_dist = src_thing; + set_marker(srctoh32(src_dist->ptr_target), CT_NODE, marker->src_offset); + break; + case CT_RODATA_REORDER: + struct src_rodata_reorder *src_reorder = src_thing; + set_marker(srctoh32(src_reorder->ptr_node_unk18), CT_NODE, marker->src_offset); + set_marker(srctoh32(src_reorder->ptr_node_unk1c), CT_NODE, marker->src_offset); + break; + case CT_RODATA_CHRGUNFIRE: + struct src_rodata_chrgunfire *src_chrgunfire = src_thing; + set_marker(srctoh32(src_chrgunfire->ptr_texture), CT_TEXCONFIG, marker->src_offset); + break; + case CT_RODATA_TOGGLE: + struct src_rodata_toggle *src_toggle = src_thing; + set_marker(srctoh32(src_toggle->ptr_target), CT_NODE, marker->src_offset); + break; + case CT_RODATA_STARGUNFIRE: + struct src_rodata_stargunfire *src_stargunfire = src_thing; + colstart = srctoh32(src_stargunfire->unk00)*4*12; + u32 vtxstart = srctoh32(src_stargunfire->ptr_vertices); + colstart = ALIGN(vtxstart + colstart, 8); + + set_marker(srctoh32(src_stargunfire->ptr_vertices), CT_VTXCOL4, marker->src_offset); + set_marker(colstart, CT_VTXCOL4, marker->src_offset); + set_marker(srctoh32(src_stargunfire->ptr_gdl), CT_GDL, marker->src_offset); + break; + case CT_RODATA_DL: + struct src_rodata_dl *src_dl = src_thing; + set_marker(srctoh32(src_dl->ptr_opagdl), CT_GDL, marker->src_offset); + set_marker(srctoh32(src_dl->ptr_xlugdl), CT_GDL, marker->src_offset); + set_marker(srctoh32(src_dl->ptr_colours), CT_VTXCOL, marker->src_offset); + set_marker(srctoh32(src_dl->ptr_vertices), CT_VTXCOL, marker->src_offset); + break; + case CT_TEXDATA: + case CT_VTXCOL: + case CT_GDL: + case CT_RODATA_BBOX: + case CT_RODATA_11: + case CT_RODATA_POSITIONHELD: + case CT_RODATA_HEADSPOT: + case CT_RODATA_19: + break; + } + } +} + +static void sortMarkers(void) +{ + for (int i = 0; i < m_NumMarkers - 1; i++) { + u32 min_offset = 0xffffffff; + int min_index = -1; + + for (int j = i + 1; j < m_NumMarkers; j++) { + if (m_Markers[j].src_offset < min_offset) { + min_offset = m_Markers[j].src_offset; + min_index = j; + } + } + + if (min_index >= 0 && m_Markers[min_index].src_offset < m_Markers[i].src_offset) { + struct marker tmp = m_Markers[i]; + m_Markers[i] = m_Markers[min_index]; + m_Markers[min_index] = tmp; + } + } +} + +static u32 convertContent(u8 *dst, u8 *src, u32 src_file_len) +{ + u32 dstpos = 0; + + for (int i = 0; i < m_NumMarkers; i++) { + struct marker *marker = &m_Markers[i]; + void *src_thing = &src[marker->src_offset]; + u32 src_end = i < m_NumMarkers - 1 ? m_Markers[i + 1].src_offset : src_file_len; + u32 src_len = src_end - marker->src_offset; + + dstpos = ALIGN(dstpos, m_AlignConfigs[marker->type].before); + + marker->dst_offset = dstpos; + void *dst_thing = &dst[dstpos]; + + switch (marker->type) { + case CT_MODELDEF: + struct src_modeldef *src_modeldef = src_thing; + struct dst_modeldef *dst_modeldef = dst_thing; + dst_modeldef->ptr_skel = srctodst32(src_modeldef->ptr_skel); + dst_modeldef->numparts = srctodst16(src_modeldef->numparts); + dst_modeldef->nummatrices = srctodst16(src_modeldef->nummatrices); + dst_modeldef->scale = srctodst32(src_modeldef->scale); + dst_modeldef->rwdatalen = srctodst16(src_modeldef->rwdatalen); + dst_modeldef->numtexconfigs = srctodst16(src_modeldef->numtexconfigs); + dstpos += sizeof(*dst_modeldef); + break; + case CT_NODE: + struct src_modelnode *src_node = src_thing; + struct dst_modelnode *dst_node = dst_thing; + dst_node->type = srctodst16(src_node->type); + dstpos += sizeof(*dst_node); + break; + case CT_TEXCONFIG: + struct src_texconfig *src_texconfig = src_thing; + struct dst_texconfig *dst_texconfig = dst_thing; + + while (src_len >= sizeof(*src_texconfig)) { + if ((srctoh32(src_texconfig->ptr) & 0xff000000) != 0x05000000) { + dst_texconfig->ptr = srctodst32(src_texconfig->ptr); + } + + dst_texconfig->width = src_texconfig->width; + dst_texconfig->height = src_texconfig->height; + dst_texconfig->level = src_texconfig->level; + dst_texconfig->format = src_texconfig->format; + dst_texconfig->depth = src_texconfig->depth; + dst_texconfig->s = src_texconfig->s; + dst_texconfig->t = src_texconfig->t; + dst_texconfig->unk0b = src_texconfig->unk0b; + + dstpos += sizeof(*dst_texconfig); + src_len -= sizeof(*src_texconfig); + src_texconfig++; + dst_texconfig++; + } + break; + case CT_TEXDATA: + memcpy(dst_thing, src_thing, src_len); + dstpos += src_len; + break; + case CT_PARTS: + struct src_modeldef *src_modeldef2 = (struct src_modeldef *) src; + u32 *src_parts = (u32 *) src_thing; + uintptr_t *dst_parts = (uintptr_t *) dst_thing; + int num_parts = srctoh16(src_modeldef2->numparts); + u16 *src_nums = (u16 *) &src_parts[num_parts]; + u16 *dst_nums = (u16 *) &dst_parts[num_parts]; + + for (int i = 0; i < num_parts; i++) { + dst_nums[i] = srctodst16(src_nums[i]); + } + dstpos += num_parts * sizeof(uintptr_t) + num_parts * sizeof(u16); + if (num_parts) { + dstpos = ALIGN8(dstpos); + } + break; + case CT_VTXCOL: + case CT_VTXCOL4: + memcpy(dst_thing, src_thing, src_len); + dstpos += src_len; + break; + case CT_GDL: + struct marker *parent = find_marker(marker->parent_src_offset); + u32 src_vtx; + u32 dst_vtx; + + if (parent->type == CT_RODATA_GUNDL) { + struct src_rodata_gundl *src_rodata = (struct src_rodata_gundl *) &src[parent->src_offset]; + struct dst_rodata_gundl *dst_rodata = (struct dst_rodata_gundl *) &dst[parent->dst_offset]; + src_vtx = srctoh32(src_rodata->ptr_vertices) & 0x00ffffff; + dst_vtx = dsttoh32(dst_rodata->ptr_vertices) & 0x00ffffff; + } else if (parent->type == CT_RODATA_STARGUNFIRE) { + struct src_rodata_stargunfire *src_rodata = (struct src_rodata_stargunfire *) &src[parent->src_offset]; + struct dst_rodata_stargunfire *dst_rodata = (struct dst_rodata_stargunfire *) &dst[parent->dst_offset]; + src_vtx = srctoh32(src_rodata->ptr_vertices) & 0x00ffffff; + dst_vtx = dsttoh32(dst_rodata->ptr_vertices) & 0x00ffffff; + } else if (parent->type == CT_RODATA_DL) { + struct src_rodata_dl *src_rodata = (struct src_rodata_dl *) &src[parent->src_offset]; + struct dst_rodata_dl *dst_rodata = (struct dst_rodata_dl *) &dst[parent->dst_offset]; + src_vtx = srctoh32(src_rodata->ptr_vertices) & 0x00ffffff; + dst_vtx = dsttoh32(dst_rodata->ptr_vertices) & 0x00ffffff; + } + + dstpos = gbiConvertGdl(dst, dstpos, src, marker->src_offset, 0); + break; + case CT_RODATA_CHRINFO: + struct generic_rodata_chrinfo *src_chrinfo = src_thing; + struct generic_rodata_chrinfo *dst_chrinfo = dst_thing; + dst_chrinfo->animpart = srctodst16(src_chrinfo->animpart); + dst_chrinfo->mtxindex = srctodst16(src_chrinfo->mtxindex); + dst_chrinfo->unk04 = srctodst32(src_chrinfo->unk04); + dst_chrinfo->rwdataindex = srctodst16(src_chrinfo->rwdataindex); + dstpos += sizeof(*dst_chrinfo); + break; + case CT_RODATA_POSITION: + struct generic_rodata_position *src_position = src_thing; + struct generic_rodata_position *dst_position = dst_thing; + dst_position->pos[0] = srctodst32(src_position->pos[0]); + dst_position->pos[1] = srctodst32(src_position->pos[1]); + dst_position->pos[2] = srctodst32(src_position->pos[2]); + dst_position->part = srctodst16(src_position->part); + dst_position->mtxindexes[0] = srctodst16(src_position->mtxindexes[0]); + dst_position->mtxindexes[1] = srctodst16(src_position->mtxindexes[1]); + dst_position->mtxindexes[2] = srctodst16(src_position->mtxindexes[2]); + dst_position->drawdist = srctodst32(src_position->drawdist); + dstpos += sizeof(*dst_position); + break; + case CT_RODATA_GUNDL: + struct src_rodata_gundl *src_gundl = src_thing; + struct dst_rodata_gundl *dst_gundl = dst_thing; + dst_gundl->ptr_vertices = 0; + dst_gundl->numvertices = srctodst16(src_gundl->numvertices); + dst_gundl->unk12 = srctodst16(src_gundl->unk12); + dstpos += sizeof(*dst_gundl); + break; + case CT_RODATA_DISTANCE: + struct src_rodata_distance *src_dist = src_thing; + struct dst_rodata_distance *dst_dist = dst_thing; + dst_dist->near = srctodst32(src_dist->near); + dst_dist->far = srctodst32(src_dist->far); + dst_dist->rwdataindex = srctodst16(src_dist->rwdataindex); + dstpos += sizeof(*dst_dist); + break; + case CT_RODATA_REORDER: + struct src_rodata_reorder *src_reorder = src_thing; + struct dst_rodata_reorder *dst_reorder = dst_thing; + dst_reorder->unk00 = srctodst32(src_reorder->unk00); + dst_reorder->unk04 = srctodst32(src_reorder->unk04); + dst_reorder->unk08 = srctodst32(src_reorder->unk08); + dst_reorder->unk0c[0] = srctodst32(src_reorder->unk0c[0]); + dst_reorder->unk0c[1] = srctodst32(src_reorder->unk0c[1]); + dst_reorder->unk0c[2] = srctodst32(src_reorder->unk0c[2]); + dst_reorder->side = srctodst16(src_reorder->side); + dst_reorder->rwdataindex = srctodst16(src_reorder->rwdataindex); + dstpos += sizeof(*dst_reorder); + break; + case CT_RODATA_BBOX: + struct generic_rodata_bbox *src_bbox = src_thing; + struct generic_rodata_bbox *dst_bbox = dst_thing; + dst_bbox->hitpart = srctodst32(src_bbox->hitpart); + dst_bbox->bbox[0] = srctodst32(src_bbox->bbox[0]); + dst_bbox->bbox[1] = srctodst32(src_bbox->bbox[1]); + dst_bbox->bbox[2] = srctodst32(src_bbox->bbox[2]); + dst_bbox->bbox[3] = srctodst32(src_bbox->bbox[3]); + dst_bbox->bbox[4] = srctodst32(src_bbox->bbox[4]); + dst_bbox->bbox[5] = srctodst32(src_bbox->bbox[5]); + dstpos += sizeof(*dst_bbox); + break; + case CT_RODATA_CHRGUNFIRE: + struct src_rodata_chrgunfire *src_chrgunfire = src_thing; + struct dst_rodata_chrgunfire *dst_chrgunfire = dst_thing; + dst_chrgunfire->pos[0] = srctodst32(src_chrgunfire->pos[0]); + dst_chrgunfire->pos[1] = srctodst32(src_chrgunfire->pos[1]); + dst_chrgunfire->pos[2] = srctodst32(src_chrgunfire->pos[2]); + dst_chrgunfire->dim[0] = srctodst32(src_chrgunfire->dim[0]); + dst_chrgunfire->dim[1] = srctodst32(src_chrgunfire->dim[1]); + dst_chrgunfire->dim[2] = srctodst32(src_chrgunfire->dim[2]); + dst_chrgunfire->unk1c = srctodst32(src_chrgunfire->unk1c); + dst_chrgunfire->rwdataindex = srctodst16(src_chrgunfire->rwdataindex); + dst_chrgunfire->ptr_baseaddr = 0; + dstpos += sizeof(*dst_chrgunfire); + break; + case CT_RODATA_11: + struct src_rodata_type11 *src_type11 = src_thing; + struct dst_rodata_type11 *dst_type11 = dst_thing; + dst_type11->unk00 = srctodst32(src_type11->unk00); + dst_type11->unk04 = srctodst32(src_type11->unk04); + dst_type11->unk08 = srctodst32(src_type11->unk08); + dst_type11->unk0c = srctodst32(src_type11->unk0c); + dst_type11->unk10 = srctodst32(src_type11->unk10); + dst_type11->extra1 = srctodst32(src_type11->extra1); + dst_type11->extra2 = srctodst32(src_type11->extra2); + dstpos += sizeof(*dst_type11); + break; + case CT_RODATA_TOGGLE: + struct src_rodata_toggle *src_toggle = src_thing; + struct dst_rodata_toggle *dst_toggle = dst_thing; + dst_toggle->rwdataindex = srctodst16(src_toggle->rwdataindex); + dstpos += sizeof(*dst_toggle); + break; + case CT_RODATA_POSITIONHELD: + struct generic_rodata_positionheld *src_posheld = src_thing; + struct generic_rodata_positionheld *dst_posheld = dst_thing; + dst_posheld->pos[0] = srctodst32(src_posheld->pos[0]); + dst_posheld->pos[1] = srctodst32(src_posheld->pos[1]); + dst_posheld->pos[2] = srctodst32(src_posheld->pos[2]); + dst_posheld->mtxindex = srctodst16(src_posheld->mtxindex); + dst_posheld->unk10 = srctodst32(src_posheld->unk10); + dstpos += sizeof(*dst_posheld); + break; + case CT_RODATA_STARGUNFIRE: + struct src_rodata_stargunfire *src_stargunfire = src_thing; + struct dst_rodata_stargunfire *dst_stargunfire = dst_thing; + dst_stargunfire->unk00 = srctodst32(src_stargunfire->unk00); + dstpos += sizeof(*dst_stargunfire); + break; + case CT_RODATA_HEADSPOT: + struct generic_rodata_headspot *src_headspot = src_thing; + struct generic_rodata_headspot *dst_headspot = dst_thing; + dst_headspot->rwdataindex = srctodst16(src_headspot->rwdataindex); + dstpos += sizeof(*dst_headspot); + break; + case CT_RODATA_DL: + struct src_rodata_dl *src_dl = src_thing; + struct dst_rodata_dl *dst_dl = dst_thing; + dst_dl->numvertices = srctodst16(src_dl->numvertices); + dst_dl->mcount = srctodst16(src_dl->mcount); + dst_dl->rwdataindex = srctodst16(src_dl->rwdataindex); + dst_dl->numcolours = srctodst16(src_dl->numcolours); + dstpos += sizeof(*dst_dl); + break; + case CT_RODATA_19: + struct generic_rodata_type19 *src_type19 = src_thing; + struct generic_rodata_type19 *dst_type19 = dst_thing; + u32 *src_vertices = src_thing + sizeof(u32); + u32 *dst_vertices = dst_thing + sizeof(u32); + int num_vertices = srctoh32(src_type19->numvertices); + + dst_type19->numvertices = htodst32(num_vertices); + dstpos += sizeof(u32); + + for (int i = 0; i < num_vertices; i++) { + dst_vertices[i * 3 + 0] = srctodst32(src_vertices[i * 3 + 0]); + dst_vertices[i * 3 + 1] = srctodst32(src_vertices[i * 3 + 1]); + dst_vertices[i * 3 + 2] = srctodst32(src_vertices[i * 3 + 2]); + dstpos += sizeof(u32) * 3; + } + break; + } + + dstpos = ALIGN(dstpos, m_AlignConfigs[marker->type].after); + } + + return dstpos; +} + +static u32 resolvePointer(u32 src_offset) +{ + if (src_offset == 0) { + return 0; + } + + struct marker *marker = find_marker(src_offset & 0x00ffffff); + return marker ? (0x05000000 | marker->dst_offset) : 0; +} + +static u8 *relinkPointers(u8 *dst, u8 *src) +{ + u8 *textures_end = 0; + + for (int i = 0; i < m_NumMarkers; i++) { + struct marker *marker = &m_Markers[i]; + void *src_thing = &src[marker->src_offset]; + void *dst_thing = &dst[marker->dst_offset]; + + u8 *lowestptr = 0; + + switch (marker->type) { + case CT_MODELDEF: + struct src_modeldef *src_modeldef = src_thing; + struct dst_modeldef *dst_modeldef = dst_thing; + dst_modeldef->ptr_rootnode = htodst32(resolvePointer(srctoh32(src_modeldef->ptr_rootnode))); + dst_modeldef->ptr_parts = htodst32(resolvePointer(srctoh32(src_modeldef->ptr_parts))); + dst_modeldef->ptr_texconfigs = htodst32(resolvePointer(srctoh32(src_modeldef->ptr_texconfigs))); + break; + case CT_NODE: + struct src_modelnode *src_node = src_thing; + struct dst_modelnode *dst_node = dst_thing; + dst_node->ptr_rodata = htodst32(resolvePointer(srctoh32(src_node->ptr_rodata))); + dst_node->ptr_parent = htodst32(resolvePointer(srctoh32(src_node->ptr_parent))); + dst_node->ptr_next = htodst32(resolvePointer(srctoh32(src_node->ptr_next))); + dst_node->ptr_prev = htodst32(resolvePointer(srctoh32(src_node->ptr_prev))); + dst_node->ptr_child = htodst32(resolvePointer(srctoh32(src_node->ptr_child))); + + lowestptr = dst_node->ptr_rodata; + break; + case CT_TEXCONFIG: + struct src_texconfig *src_texconfig = src_thing; + struct dst_texconfig *dst_texconfig = dst_thing; + if ((srctoh32(src_texconfig->ptr) & 0xff000000) == 0x05000000) { + dst_texconfig->ptr = htodst32(resolvePointer(srctoh32(src_texconfig->ptr))); + gbiAddTexAddr(srctoh32(src_texconfig->ptr), dst_texconfig->ptr); + } + break; + case CT_PARTS: + struct src_modeldef *src_modeldef2 = (struct src_modeldef *) src; + u32 *src_parts = (u32 *) src_thing; + uintptr_t *dst_parts = (uintptr_t *) dst_thing; + int num_parts = srctoh16(src_modeldef2->numparts); + + for (int i = 0; i < num_parts; i++) { + dst_parts[i] = htodst32(resolvePointer(srctoh32(src_parts[i]))); + } + break; + case CT_RODATA_CHRINFO: + break; + case CT_RODATA_POSITION: + break; + case CT_RODATA_GUNDL: + struct src_rodata_gundl *src_gundl = src_thing; + struct dst_rodata_gundl *dst_gundl = dst_thing; + dst_gundl->ptr_opagdl = htodst32(resolvePointer(srctoh32(src_gundl->ptr_opagdl))); + dst_gundl->ptr_xlugdl = htodst32(resolvePointer(srctoh32(src_gundl->ptr_xlugdl))); + dst_gundl->ptr_vertices = htodst32(resolvePointer(srctoh32(src_gundl->ptr_vertices))); + + gbiConvertVtx(dst, dst_gundl->ptr_vertices & 0x00ffffff, dst_gundl->numvertices); + + gbiSetVtx(srctoh32(src_gundl->ptr_vertices), dst_gundl->ptr_vertices); + gbiSetSegment(0x04, dst_gundl->ptr_vertices); + + gbiGdlRewriteAddrs(dst, dst_gundl->ptr_opagdl); + gbiGdlRewriteAddrs(dst, dst_gundl->ptr_xlugdl); + + if (dst_gundl->ptr_opagdl) dst_gundl->ptr_opagdl |= 1; + if (dst_gundl->ptr_xlugdl) dst_gundl->ptr_xlugdl |= 1; + + lowestptr = minPtr3(dst_gundl->ptr_opagdl, dst_gundl->ptr_xlugdl, dst_gundl->ptr_vertices); + break; + case CT_RODATA_DISTANCE: + struct src_rodata_distance *src_dist = src_thing; + struct dst_rodata_distance *dst_dist = dst_thing; + dst_dist->ptr_target = htodst32(resolvePointer(srctoh32(src_dist->ptr_target))); + break; + case CT_RODATA_REORDER: + struct src_rodata_reorder *src_reorder = src_thing; + struct dst_rodata_reorder *dst_reorder = dst_thing; + dst_reorder->ptr_node_unk18 = htodst32(resolvePointer(srctoh32(src_reorder->ptr_node_unk18))); + dst_reorder->ptr_node_unk1c = htodst32(resolvePointer(srctoh32(src_reorder->ptr_node_unk1c))); + break; + case CT_RODATA_CHRGUNFIRE: + struct src_rodata_chrgunfire *src_chrgunfire = src_thing; + struct dst_rodata_chrgunfire *dst_chrgunfire = dst_thing; + dst_chrgunfire->ptr_texture = htodst32(resolvePointer(srctoh32(src_chrgunfire->ptr_texture))); + if ((srctoh32(dst_chrgunfire->ptr_texture) & 0xff000000) == 0x05000000) { + gbiAddTexAddr(srctoh32(dst_chrgunfire->ptr_texture), dst_chrgunfire->ptr_texture); + } + break; + case CT_RODATA_TOGGLE: + struct src_rodata_toggle *src_toggle = src_thing; + struct dst_rodata_toggle *dst_toggle = dst_thing; + dst_toggle->ptr_target = htodst32(resolvePointer(srctoh32(src_toggle->ptr_target))); + break; + case CT_RODATA_STARGUNFIRE: + struct src_rodata_stargunfire *src_stargunfire = src_thing; + struct dst_rodata_stargunfire *dst_stargunfire = dst_thing; + dst_stargunfire->ptr_vertices = htodst32(resolvePointer(srctoh32(src_stargunfire->ptr_vertices))); + dst_stargunfire->ptr_gdl = htodst32(resolvePointer(srctoh32(src_stargunfire->ptr_gdl))); + + gbiConvertVtx(dst, dst_stargunfire->ptr_vertices & 0x00ffffff, dst_stargunfire->unk00*4); + + gbiSetVtx(srctoh32(src_stargunfire->ptr_vertices), dst_stargunfire->ptr_vertices); + gbiSetSegment(0x04, dst_stargunfire->ptr_vertices); + gbiGdlRewriteAddrs(dst, dst_stargunfire->ptr_gdl); + if (dst_stargunfire->ptr_gdl) dst_stargunfire->ptr_gdl |= 1; + + lowestptr = minPtr(dst_stargunfire->ptr_gdl, dst_stargunfire->ptr_vertices); + break; + case CT_RODATA_DL: + struct src_rodata_dl *src_dl = src_thing; + struct dst_rodata_dl *dst_dl = dst_thing; + dst_dl->ptr_opagdl = htodst32(resolvePointer(srctoh32(src_dl->ptr_opagdl))); + dst_dl->ptr_xlugdl = htodst32(resolvePointer(srctoh32(src_dl->ptr_xlugdl))); + dst_dl->ptr_colours = htodst32(resolvePointer(srctoh32(src_dl->ptr_colours))); + dst_dl->ptr_vertices = htodst32(resolvePointer(srctoh32(src_dl->ptr_vertices))); + + gbiConvertVtx(dst, dst_dl->ptr_vertices & 0x00ffffff, dst_dl->numvertices); + + gbiSetVtx(srctoh32(src_dl->ptr_vertices), dst_dl->ptr_vertices); + gbiSetSegment(0x04, dst_dl->ptr_vertices); + gbiGdlRewriteAddrs(dst, dst_dl->ptr_opagdl); + gbiGdlRewriteAddrs(dst, dst_dl->ptr_xlugdl); + + if (dst_dl->ptr_opagdl) dst_dl->ptr_opagdl |= 1; + if (dst_dl->ptr_xlugdl) dst_dl->ptr_xlugdl |= 1; + + lowestptr = minPtr3(dst_dl->ptr_opagdl, dst_dl->ptr_xlugdl, dst_dl->ptr_colours); + lowestptr = minPtr(lowestptr, dst_dl->ptr_vertices); + break; + case CT_TEXDATA: + case CT_VTXCOL: + case CT_GDL: + case CT_RODATA_BBOX: + case CT_RODATA_11: + case CT_RODATA_POSITIONHELD: + case CT_RODATA_HEADSPOT: + case CT_RODATA_19: + break; + } + + textures_end = minPtr(textures_end, lowestptr); + } + + return textures_end; +} + +static int convertModel(u8 *dst, u8 *src, u32 srclen) +{ + u32 dstpos; + + populateMarkers(src); + sortMarkers(); + + dstpos = convertContent(dst, src, srclen); + u8 *tex_end = relinkPointers(dst, src); + preprocessModelTextures(dst, tex_end); + + return dstpos; +} + +void preprocessTextureRGBA32Embedded(u32* dest, u32 size_bytes) +{ + for (uint32_t i = 0; i < size_bytes; i += 4, ++dest) { + *dest = PD_BE32(*dest); + } +} + +void preprocessModelTextures(u8 *base, u8 *textures_end) +{ + struct modeldef* mdl = (struct modeldef*)base; + if (!mdl->texconfigs) return; + + u32 ofs = 0x5000000; + struct textureconfig* texconfigs = PD_PTR_BASEOFS(mdl->texconfigs, base, ofs); + for (s16 i = 0; i < mdl->numtexconfigs; ++i) { + if ((texconfigs[i].texturenum & 0xf000000) == 0x5000000) { + // embedded texture; we need to unswizzle this + u8* texdata = PD_PTR_BASEOFS(texconfigs[i].textureptr, base, ofs); + // figure out the max possible size the texture can have, because sometimes the texconfig is wrong + const u32 maxSize = (textures_end > texconfigs[i].textureptr) ? (textures_end - texconfigs[i].textureptr) : 0; + // figure out the format and unswizzle + const s32 format = texConfigToFormat(&texconfigs[i]); + texSwizzleInternal(texdata, texconfigs[i].width, texconfigs[i].height, format, maxSize); + + if (format == TEXFORMAT_RGBA32) { + // for some reason, RGBA32 embedded textures don't need to be byte-swapped, + // so we byte-swap them here, which will be undone when the renderer imports it + u32 size_bytes = texconfigs[i].width * texconfigs[i].height * 4; + preprocessTextureRGBA32Embedded((u32*)texdata, size_bytes); + } + } + } +} + +u8 *preprocessModelFile(u8 *data, u32 size, u32 *outSize) +{ + gbiReset(); + + u32 newSizeEstimated = romdataFileGetEstimatedSize(size, FT_MODEL); + u8 *dst = sysMemZeroAlloc(newSizeEstimated); + + u32 newSize = convertModel(dst, data, size); + + if (newSize > newSizeEstimated) { + sysLogPrintf(LOG_ERROR, "overflow when trying to preprocess model, size %d newsize %d", size, newSize); + exit(EXIT_FAILURE); + } + + memcpy(data, dst, newSize); + sysMemFree(dst); + + *outSize = newSize; + + return 0; +} + +u8 *preprocessGunFile(u8 *data, u32 size, u32 *outSize) +{ + gbiReset(); + + u32 newSizeEstimated = romdataFileGetEstimatedSize(size, FT_MODEL); + u8 *dst = sysMemZeroAlloc(newSizeEstimated+128); + + u32 newSize = convertModel(dst, data, size); + + if (newSize > newSizeEstimated) { + sysLogPrintf(LOG_ERROR, "overflow when trying to preprocess model, size %d newsize %d", size, newSize); + exit(EXIT_FAILURE); + } + + memcpy(data, dst, newSize); + sysMemFree(dst); + + *outSize = newSize; + + return 0; +} diff --git a/port/src/preprocess/filepads.c b/port/src/preprocess/filepads.c new file mode 100644 index 000000000..f1f42ee52 --- /dev/null +++ b/port/src/preprocess/filepads.c @@ -0,0 +1,330 @@ +#include +#include +#include + +#include "common.h" +#include "romdata.h" +#include "system.h" + +#define PADFLAG_INTPOS 0x0001 +#define PADFLAG_UPALIGNTOX 0x0002 +#define PADFLAG_UPALIGNTOY 0x0004 +#define PADFLAG_UPALIGNTOZ 0x0008 +#define PADFLAG_UPALIGNINVERT 0x0010 +#define PADFLAG_LOOKALIGNTOX 0x0020 +#define PADFLAG_LOOKALIGNTOY 0x0040 +#define PADFLAG_LOOKALIGNTOZ 0x0080 +#define PADFLAG_LOOKALIGNINVERT 0x0100 +#define PADFLAG_HASBBOXDATA 0x0200 + +struct n64_header { + s32 num_pads; + s32 num_covers; + u32 ptr_waypoints; + u32 ptr_waygroups; + u32 ptr_cover; +}; + +struct host_header { + s32 num_pads; + s32 num_covers; + uintptr_t ptr_waypoints; + uintptr_t ptr_waygroups; + uintptr_t ptr_cover; +}; + +struct padheader { + u32 flags : 18; + u32 room : 10; + u32 liftnum : 4; +}; + +struct n64_waypoint { + s32 padnum; + u32 ptr_neighbours; + s32 groupnum; + s32 step; +}; + +struct host_waypoint { + s32 padnum; + uintptr_t ptr_neighbours; + s32 groupnum; + s32 step; +}; + +struct n64_waygroup { + u32 ptr_neighbours; + u32 ptr_waypoints; + s32 step; +}; + +struct host_waygroup { + uintptr_t ptr_neighbours; + uintptr_t ptr_waypoints; + s32 step; +}; + +struct generic_coverdefinition { + u32 pos[3]; + u32 dir[3]; + u16 flags; + u16 unk1a; +}; + +static int convertPads(u8 *dst, int dstpos, u8 *src, int srcpos, int num_pads) +{ + u16 *src_offsets = (u16 *) &src[srcpos]; + u16 *dst_offsets = (u16 *) &dst[dstpos]; + + dstpos += num_pads * sizeof(u16); + + for (int i = 0; i < num_pads; i++) { + dstpos = ALIGN4(dstpos); + srcpos = srctoh16(src_offsets[i]); + + dst_offsets[i] = htodst16(dstpos); + + // Header + u32 n64_padheader = srctoh32(*(u32 *) &src[srcpos]); + struct padheader *host_padheader = (struct padheader *) &dst[dstpos]; + u32 flags = (n64_padheader >> 14) & 0x3ffff; + + *(u32*)host_padheader = htodst32(n64_padheader); + + srcpos += sizeof(struct padheader); + dstpos += sizeof(struct padheader); + + // Position + if (flags & PADFLAG_INTPOS) { + s16 *srcptr = (s16 *) &src[srcpos]; + s16 *dstptr = (s16 *) &dst[dstpos]; + + dstptr[0] = srctodst16(srcptr[0]); + dstptr[1] = srctodst16(srcptr[1]); + dstptr[2] = srctodst16(srcptr[2]); + + srcpos += 8; + dstpos += 8; + } else { + u32 *srcptr = (u32 *) &src[srcpos]; + u32 *dstptr = (u32 *) &dst[dstpos]; + + dstptr[0] = srctodst32(srcptr[0]); + dstptr[1] = srctodst32(srcptr[1]); + dstptr[2] = srctodst32(srcptr[2]); + + srcpos += 12; + dstpos += 12; + } + + // Up + if ((flags & (PADFLAG_UPALIGNTOX | PADFLAG_UPALIGNTOY | PADFLAG_UPALIGNTOZ)) == 0) { + u32 *srcptr = (u32 *) &src[srcpos]; + u32 *dstptr = (u32 *) &dst[dstpos]; + + dstptr[0] = srctodst32(srcptr[0]); + dstptr[1] = srctodst32(srcptr[1]); + dstptr[2] = srctodst32(srcptr[2]); + + srcpos += 12; + dstpos += 12; + } + + // Look + if ((flags & (PADFLAG_LOOKALIGNTOX | PADFLAG_LOOKALIGNTOY | PADFLAG_LOOKALIGNTOZ)) == 0) { + u32 *srcptr = (u32 *) &src[srcpos]; + u32 *dstptr = (u32 *) &dst[dstpos]; + + dstptr[0] = srctodst32(srcptr[0]); + dstptr[1] = srctodst32(srcptr[1]); + dstptr[2] = srctodst32(srcptr[2]); + + srcpos += 12; + dstpos += 12; + } + + // Bbox + if (flags & PADFLAG_HASBBOXDATA) { + u32 *srcptr = (u32 *) &src[srcpos]; + u32 *dstptr = (u32 *) &dst[dstpos]; + + dstptr[0] = srctodst32(srcptr[0]); + dstptr[1] = srctodst32(srcptr[1]); + dstptr[2] = srctodst32(srcptr[2]); + dstptr[3] = srctodst32(srcptr[3]); + dstptr[4] = srctodst32(srcptr[4]); + dstptr[5] = srctodst32(srcptr[5]); + + srcpos += 4 * 6; + dstpos += 4 * 6; + } + } + + return dstpos; +} + +static int convertWayPoints(u8 *dst, int dstpos, u8 *src, int srcpos) +{ + struct n64_waypoint *n64_waypoints = (struct n64_waypoint *) &src[srcpos]; + struct host_waypoint *host_waypoints = (struct host_waypoint *) &dst[dstpos]; + int num_waypoints; + + for (num_waypoints = 0; n64_waypoints[num_waypoints].padnum != -1; num_waypoints++); + + dstpos += (num_waypoints + 1) * sizeof(struct host_waypoint); + + u32 *host_neighbours = (u32 *) &dst[dstpos]; + int n = 0; + + for (int i = 0; i < num_waypoints; i++) { + host_waypoints[i].padnum = srctodst32(n64_waypoints[i].padnum); + host_waypoints[i].ptr_neighbours = htodst32(dstpos); + host_waypoints[i].groupnum = srctodst32(n64_waypoints[i].groupnum); + host_waypoints[i].step = 0; + + u32 *n64_neighbours = (u32 *) &src[srctoh32(n64_waypoints[i].ptr_neighbours)]; + + for (int j = 0; n64_neighbours[j] != 0xffffffff; j++) { + host_neighbours[n++] = srctodst32(n64_neighbours[j]); + dstpos += 4; + } + + host_neighbours[n++] = 0xffffffff; + dstpos += 4; + } + + // Terminator + host_waypoints[num_waypoints].padnum = 0xffffffff; + host_waypoints[num_waypoints].ptr_neighbours = 0; + host_waypoints[num_waypoints].groupnum = 0; + host_waypoints[num_waypoints].step = 0; + + return dstpos; +} + +static int convertWayGroups(u8 *dst, int dstpos, u8 *src, int srcpos) +{ + struct n64_waygroup *n64_waygroups = (struct n64_waygroup *) &src[srcpos]; + struct host_waygroup *host_waygroups = (struct host_waygroup *) &dst[dstpos]; + int num_waygroups; + + for (num_waygroups = 0; n64_waygroups[num_waygroups].ptr_neighbours != 0; num_waygroups++); + + dstpos += (num_waygroups + 1) * sizeof(struct host_waygroup); + + // Waygroups and child waypoints + u32 *host_waypoints = (u32 *) &dst[dstpos]; + int n = 0; + + for (int i = 0; i < num_waygroups; i++) { + host_waygroups[i].ptr_waypoints = htodst32(dstpos); + host_waygroups[i].step = 0; + + u32 *n64_waypoints = (u32 *) &src[srctoh32(n64_waygroups[i].ptr_waypoints)]; + + for (int j = 0; n64_waypoints[j] != 0xffffffff; j++) { + host_waypoints[n++] = srctodst32(n64_waypoints[j]); + dstpos += 4; + } + + host_waypoints[n++] = 0xffffffff; + dstpos += 4; + } + + // Terminator + host_waygroups[num_waygroups].ptr_neighbours = 0; + host_waygroups[num_waygroups].ptr_waypoints = 0; + host_waygroups[num_waygroups].step = 0; + + // Waygroup neighbours + u32 *host_neighbours = (u32 *) &dst[dstpos]; + n = 0; + + for (int i = 0; i < num_waygroups; i++) { + host_waygroups[i].ptr_neighbours = htodst32(dstpos); + + u32 *n64_neighbours = (u32 *) &src[srctoh32(n64_waygroups[i].ptr_neighbours)]; + + for (int j = 0; n64_neighbours[j] != 0xffffffff; j++) { + host_neighbours[n++] = srctodst32(n64_neighbours[j]); + dstpos += 4; + } + + host_neighbours[n++] = 0xffffffff; + dstpos += 4; + } + + return dstpos; +} + +static int convertCover(u8 *dst, int dstpos, u8 *src, int srcpos, int num_covers) +{ + struct generic_coverdefinition *n64_covers = (struct generic_coverdefinition *) &src[srcpos]; + struct generic_coverdefinition *host_covers = (struct generic_coverdefinition *) &dst[dstpos]; + + for (int i = 0; i < num_covers; i++) { + host_covers[i].pos[0] = srctodst32(n64_covers[i].pos[0]); + host_covers[i].pos[1] = srctodst32(n64_covers[i].pos[1]); + host_covers[i].pos[2] = srctodst32(n64_covers[i].pos[2]); + host_covers[i].dir[0] = srctodst32(n64_covers[i].dir[0]); + host_covers[i].dir[1] = srctodst32(n64_covers[i].dir[1]); + host_covers[i].dir[2] = srctodst32(n64_covers[i].dir[2]); + host_covers[i].flags = srctodst16(n64_covers[i].flags); + host_covers[i].unk1a = srctodst16(n64_covers[i].unk1a); + } + + dstpos += num_covers * sizeof(struct generic_coverdefinition); + + return dstpos; +} + +static int convertPadsFile(u8 *dst, u8 *src) +{ + int dstpos = 0; + struct n64_header *n64_header = (struct n64_header *) src; + struct host_header *host_header = (struct host_header *) dst; + + int num_pads = srctoh32(n64_header->num_pads); + int num_covers = srctoh32(n64_header->num_covers); + host_header->num_pads = htodst32(num_pads); + host_header->num_covers = htodst32(num_covers); + + dstpos += sizeof(struct host_header); + + // Pads + dstpos = convertPads(dst, dstpos, src, sizeof(struct n64_header), num_pads); + + // Waypoints + host_header->ptr_waypoints = htodst32(dstpos); + dstpos = convertWayPoints(dst, dstpos, src, srctoh32(n64_header->ptr_waypoints)); + + // Waygroups + host_header->ptr_waygroups = htodst32(dstpos); + dstpos = convertWayGroups(dst, dstpos, src, srctoh32(n64_header->ptr_waygroups)); + + // Cover + host_header->ptr_cover = htodst32(dstpos); + dstpos = convertCover(dst, dstpos, src, srctoh32(n64_header->ptr_cover), num_covers); + + return dstpos; +} + +u8* preprocessPadsFile(u8 *data, u32 size, u32 *outSize) { + u32 newSizeEstimated = romdataFileGetEstimatedSize(size, FT_PADS); + u8* dst = sysMemZeroAlloc(newSizeEstimated); + + u32 newSize = convertPadsFile(dst, data); + + if (newSize > newSizeEstimated) { + sysLogPrintf(LOG_ERROR, "overflow when trying to preprocess a pads file, size %d newsize %d", size, newSize); + exit(EXIT_FAILURE); + } + + memcpy(data, dst, newSize); + sysMemFree(dst); + + *outSize = newSize; + + return 0; +} diff --git a/port/src/preprocess/filesetup.c b/port/src/preprocess/filesetup.c new file mode 100644 index 000000000..9d4c9c7b2 --- /dev/null +++ b/port/src/preprocess/filesetup.c @@ -0,0 +1,1202 @@ +#include +#include +#include + +#include "types.h" + +#include "assert.h" + +#include "common.h" +#include "setups_decl.h" + +#include "romdata.h" +#include "system.h" + + +static inline void convF32(f32 *dst, f32 src) { *(u32*)dst = srctoh32(*(u32*)&src); } +static inline void convU32(u32 *dst, u32 src) { *dst = srctoh32(src); } +static inline void convS32(s32 *dst, s32 src) { *dst = srctoh32(src); } +static inline void convU16(u16 *dst, u32 src) { *dst = srctoh16(src); } +static inline void convS16(s16 *dst, s32 src) { *dst = srctoh16(src); } +static inline void cpyByte(u8 *dst, u8 src) { *dst = src; } +static inline void convCoord(struct coord* dst, struct n64_coord src) { convF32(&dst->x, src.x); convF32(&dst->y, src.y); convF32(&dst->z, src.z); } +static u32 convUnk(void* x, u32 y) { __debugbreak(); } + +#define PD_CONV_VAL(dst, src) _Generic((dst), \ + f32: convF32, \ + u32: convU32, \ + s32: convS32, \ + u16: convU16, \ + s16: convS16, \ + u8: cpyByte, \ + s8: cpyByte, \ + struct coord: convCoord, \ + default: convUnk \ +)(&dst, src) + +#define PD_CONV_ARRAY(dst, src) { for (int i = 0; i < ARRAYCOUNT(dst); i++) PD_CONV_VAL(dst[i], src[i]); } +#define PD_CONV_ARRAY2D(dst, src) { \ + for (int i = 0; i < ARRAYCOUNT(dst); i++) \ + for (int j = 0; j < ARRAYCOUNT(dst); j++) PD_CONV_VAL(dst[i][j], src[i][j]); \ +} + +#define PD_CONV_PTR(dst, src) dst = srctoh32(src) + +static u32 obj_size(struct n64_defaultobj *obj) +{ + switch (obj->type) { + case OBJTYPE_CHR: return sizeof(struct n64_packedchr) / sizeof(u32); + case OBJTYPE_DOOR: return sizeof(struct n64_doorobj) / sizeof(u32); + case OBJTYPE_DOORSCALE: return sizeof(struct n64_doorscaleobj) / sizeof(u32); + case OBJTYPE_BASIC: return sizeof(struct n64_defaultobj) / sizeof(u32); + case OBJTYPE_DEBRIS: return sizeof(struct n64_debrisobj) / sizeof(u32); + case OBJTYPE_GLASS: return sizeof(struct n64_glassobj) / sizeof(u32); + case OBJTYPE_TINTEDGLASS: return sizeof(struct n64_tintedglassobj) / sizeof(u32); + case OBJTYPE_SAFE: return sizeof(struct n64_safeobj) / sizeof(u32); + case OBJTYPE_GASBOTTLE: return sizeof(struct gasbottleobj) / sizeof(u32); + case OBJTYPE_KEY: return sizeof(struct n64_keyobj) / sizeof(u32); + case OBJTYPE_ALARM: return sizeof(struct n64_alarmobj) / sizeof(u32); + case OBJTYPE_CCTV: return sizeof(struct n64_cctvobj) / sizeof(u32); + case OBJTYPE_AMMOCRATE: return sizeof(struct n64_ammocrateobj) / sizeof(u32); + case OBJTYPE_WEAPON: return sizeof(struct n64_weaponobj) / sizeof(u32); + case OBJTYPE_SINGLEMONITOR: return sizeof(struct n64_singlemonitorobj) / sizeof(u32); + case OBJTYPE_MULTIMONITOR: return sizeof(struct n64_multimonitorobj) / sizeof(u32); + case OBJTYPE_HANGINGMONITORS: return sizeof(struct n64_hangingmonitorsobj) / sizeof(u32); + case OBJTYPE_AUTOGUN: return sizeof(struct n64_autogunobj) / sizeof(u32); + case OBJTYPE_LINKGUNS: return sizeof(struct linkgunsobj) / sizeof(u32); + case OBJTYPE_HAT: return sizeof(struct n64_hatobj) / sizeof(u32); + case OBJTYPE_GRENADEPROB: return sizeof(struct grenadeprobobj) / sizeof(u32); + case OBJTYPE_LINKLIFTDOOR: return sizeof(struct n64_linkliftdoorobj) / sizeof(u32); + case OBJTYPE_SAFEITEM: return sizeof(struct n64_safeitemobj) / sizeof(u32); + case OBJTYPE_MULTIAMMOCRATE: return sizeof(struct n64_multiammocrateobj) / sizeof(u32); + case OBJTYPE_SHIELD: return sizeof(struct n64_shieldobj) / sizeof(u32); + case OBJTYPE_TAG: return sizeof(struct n64_tag) / sizeof(u32); + case OBJTYPE_RENAMEOBJ: return sizeof(struct n64_textoverride) / sizeof(u32); + case OBJTYPE_BEGINOBJECTIVE: return sizeof(struct n64_objective) / sizeof(u32); + case OBJTYPE_ENDOBJECTIVE: return 1; + case OBJECTIVETYPE_DESTROYOBJ: return 2; + case OBJECTIVETYPE_COMPFLAGS: return 2; + case OBJECTIVETYPE_FAILFLAGS: return 2; + case OBJECTIVETYPE_COLLECTOBJ: return 2; + case OBJECTIVETYPE_THROWOBJ: return 2; + case OBJECTIVETYPE_HOLOGRAPH: return sizeof(struct n64_criteria_holograph) / sizeof(u32); + case OBJECTIVETYPE_1F: return 1; + case OBJECTIVETYPE_ENTERROOM: return sizeof(struct n64_criteria_roomentered) / sizeof(u32); + case OBJECTIVETYPE_THROWINROOM: return sizeof(struct n64_criteria_throwinroom) / sizeof(u32); + case OBJTYPE_22: return 1; + case OBJTYPE_BRIEFING: return sizeof(struct n64_briefingobj) / sizeof(u32); + case OBJTYPE_PADLOCKEDDOOR: return sizeof(struct n64_padlockeddoorobj) / sizeof(u32); + case OBJTYPE_TRUCK: return sizeof(struct n64_truckobj) / sizeof(u32); + case OBJTYPE_HELI: return sizeof(struct n64_heliobj) / sizeof(u32); + case OBJTYPE_TANK: return 32; + case OBJTYPE_CAMERAPOS: return sizeof(struct n64_cameraposobj) / sizeof(u32); + case OBJTYPE_LIFT: return sizeof(struct n64_liftobj) / sizeof(u32); + case OBJTYPE_CONDITIONALSCENERY: return sizeof(struct n64_linksceneryobj) / sizeof(u32); + case OBJTYPE_BLOCKEDPATH: return sizeof(struct n64_blockedpathobj) / sizeof(u32); + case OBJTYPE_HOVERBIKE: return sizeof(struct n64_hoverbikeobj) / sizeof(u32); + case OBJTYPE_HOVERPROP: return sizeof(struct n64_hoverpropobj) / sizeof(u32); + case OBJTYPE_FAN: return sizeof(struct n64_fanobj) / sizeof(u32); + case OBJTYPE_HOVERCAR: return sizeof(struct n64_hovercarobj) / sizeof(u32); + case OBJTYPE_CHOPPER: return sizeof(struct n64_chopperobj) / sizeof(u32); + case OBJTYPE_PADEFFECT: return sizeof(struct padeffectobj) / sizeof(u32); + case OBJTYPE_MINE: return sizeof(struct n64_weaponobj) / sizeof(u32); + case OBJTYPE_ESCASTEP: return sizeof(struct n64_escalatorobj) / sizeof(u32); + } + + return 1; +} + + +void conv_tvscreen(struct tvscreen* dstobj, struct n64_tvscreen* srcobj) +{ + PD_CONV_PTR(dstobj->cmdlist, srcobj->ptr_cmdlist); + PD_CONV_VAL(dstobj->offset, srcobj->offset); + PD_CONV_VAL(dstobj->pause60, srcobj->pause60); + PD_CONV_PTR(dstobj->tconfig, srcobj->ptr_tconfig); + PD_CONV_VAL(dstobj->rot, srcobj->rot); + PD_CONV_VAL(dstobj->xscale, srcobj->xscale); + PD_CONV_VAL(dstobj->xscalefrac, srcobj->xscalefrac); + PD_CONV_VAL(dstobj->xscaleinc, srcobj->xscaleinc); + PD_CONV_VAL(dstobj->xscaleold, srcobj->xscaleold); + PD_CONV_VAL(dstobj->xscalenew, srcobj->xscalenew); + PD_CONV_VAL(dstobj->yscale, srcobj->yscale); + PD_CONV_VAL(dstobj->yscalefrac, srcobj->yscalefrac); + PD_CONV_VAL(dstobj->yscaleinc, srcobj->yscaleinc); + PD_CONV_VAL(dstobj->yscaleold, srcobj->yscaleold); + PD_CONV_VAL(dstobj->yscalenew, srcobj->yscalenew); + PD_CONV_VAL(dstobj->xmid, srcobj->xmid); + PD_CONV_VAL(dstobj->xmidfrac, srcobj->xmidfrac); + PD_CONV_VAL(dstobj->xmidinc, srcobj->xmidinc); + PD_CONV_VAL(dstobj->xmidold, srcobj->xmidold); + PD_CONV_VAL(dstobj->xmidnew, srcobj->xmidnew); + PD_CONV_VAL(dstobj->ymid, srcobj->ymid); + PD_CONV_VAL(dstobj->ymidfrac, srcobj->ymidfrac); + PD_CONV_VAL(dstobj->ymidinc, srcobj->ymidinc); + PD_CONV_VAL(dstobj->ymidold, srcobj->ymidold); + PD_CONV_VAL(dstobj->ymidnew, srcobj->ymidnew); + PD_CONV_VAL(dstobj->red, srcobj->red); + PD_CONV_VAL(dstobj->redold, srcobj->redold); + PD_CONV_VAL(dstobj->rednew, srcobj->rednew); + PD_CONV_VAL(dstobj->green, srcobj->green); + PD_CONV_VAL(dstobj->greenold, srcobj->greenold); + PD_CONV_VAL(dstobj->greennew, srcobj->greennew); + PD_CONV_VAL(dstobj->blue, srcobj->blue); + PD_CONV_VAL(dstobj->blueold, srcobj->blueold); + PD_CONV_VAL(dstobj->bluenew, srcobj->bluenew); + PD_CONV_VAL(dstobj->alpha, srcobj->alpha); + PD_CONV_VAL(dstobj->alphaold, srcobj->alphaold); + PD_CONV_VAL(dstobj->alphanew, srcobj->alphanew); + PD_CONV_VAL(dstobj->colfrac, srcobj->colfrac); + PD_CONV_VAL(dstobj->colinc, srcobj->colinc); +} + +void convertDefaultObjHdr(struct defaultobj* dstobj, struct n64_defaultobj* srcobj) +{ + PD_CONV_VAL(dstobj->extrascale, srcobj->extrascale); + + /* 'header' is like this inside a u32: + u16 unk00_1, + u8 unk00_2, + u8 type, + */ + u16 *dst_unk00_1 = (u16*)&dstobj->extrascale; + u8 *dst_unk00_2 = (u8*)(dst_unk00_1 + 1); + + u16 *src_unk00_1 = (u16*)&srcobj->extrascale; + u8 *src_unk00_2 = (u8*)(src_unk00_1 + 1); + + *dst_unk00_1 = srctoh16(*src_unk00_1); + dst_unk00_2[0] = src_unk00_2[0]; + dst_unk00_2[1] = src_unk00_2[1]; +} + +void convertDefaultObj(struct defaultobj* dstobj, struct n64_defaultobj* srcobj) +{ + PD_CONV_VAL(dstobj->extrascale, srcobj->extrascale); + PD_CONV_VAL(dstobj->hidden2, srcobj->hidden2); + PD_CONV_VAL(dstobj->type, srcobj->type); + PD_CONV_VAL(dstobj->modelnum, srcobj->modelnum); + PD_CONV_VAL(dstobj->pad, srcobj->pad); + PD_CONV_VAL(dstobj->flags, srcobj->flags); + PD_CONV_VAL(dstobj->flags2, srcobj->flags2); + PD_CONV_VAL(dstobj->flags3, srcobj->flags3); + PD_CONV_PTR(dstobj->prop, srcobj->ptr_prop); + PD_CONV_PTR(dstobj->model, srcobj->ptr_model); + PD_CONV_ARRAY2D(dstobj->realrot, srcobj->realrot); + PD_CONV_VAL(dstobj->hidden, srcobj->hidden); + PD_CONV_PTR(dstobj->unkgeo, srcobj->ptr_unkgeo); + PD_CONV_PTR(dstobj->embedment, srcobj->ptr_embedment); + PD_CONV_VAL(dstobj->damage, srcobj->damage); + PD_CONV_VAL(dstobj->maxdamage, srcobj->maxdamage); + PD_CONV_ARRAY(dstobj->shadecol, srcobj->shadecol); + PD_CONV_ARRAY(dstobj->nextcol, srcobj->nextcol); + PD_CONV_VAL(dstobj->floorcol, srcobj->floorcol); + PD_CONV_VAL(dstobj->geocount, srcobj->geocount); +} + +u32 convertProps(u8* dst, u8* src) +{ + u8* start = dst; + struct n64_defaultobj* cmd = (struct n64_defaultobj*)src; + + int i = 0; + u8 type = cmd->type; + + while (type != OBJTYPE_END) { + //sysLogPrintf(LOG_NOTE, "#%03d obj 0x%02x (%s)", ++i, type, objName(cmd)); + switch (type) { + case OBJTYPE_DOOR: + { + struct n64_doorobj* srcobj = (struct n64_doorobj*)cmd; + struct doorobj* dstobj = (struct doorobj*)dst; + + convertDefaultObj(&dstobj->base, cmd); + + PD_CONV_VAL(dstobj->maxfrac, srcobj->maxfrac); + PD_CONV_VAL(dstobj->perimfrac, srcobj->perimfrac); + PD_CONV_VAL(dstobj->accel, srcobj->accel); + PD_CONV_VAL(dstobj->decel, srcobj->decel); + PD_CONV_VAL(dstobj->maxspeed, srcobj->maxspeed); + PD_CONV_VAL(dstobj->doorflags, srcobj->doorflags); + PD_CONV_VAL(dstobj->doortype, srcobj->doortype); + PD_CONV_VAL(dstobj->keyflags, srcobj->keyflags); + PD_CONV_VAL(dstobj->autoclosetime, srcobj->autoclosetime); + PD_CONV_VAL(dstobj->frac, srcobj->frac); + PD_CONV_VAL(dstobj->fracspeed, srcobj->fracspeed); + PD_CONV_VAL(dstobj->mode, srcobj->mode); + PD_CONV_VAL(dstobj->glasshits, srcobj->glasshits); + PD_CONV_VAL(dstobj->fadealpha, srcobj->fadealpha); + PD_CONV_VAL(dstobj->xludist, srcobj->xludist); + PD_CONV_VAL(dstobj->opadist, srcobj->opadist); + PD_CONV_VAL(dstobj->startpos, srcobj->startpos); + PD_CONV_ARRAY2D(dstobj->mtx98, srcobj->mtx98); + PD_CONV_PTR(dstobj->sibling, srcobj->ptr_sibling); + PD_CONV_VAL(dstobj->lastopen60, srcobj->lastopen60); + PD_CONV_VAL(dstobj->portalnum, srcobj->portalnum); + PD_CONV_VAL(dstobj->soundtype, srcobj->soundtype); + PD_CONV_VAL(dstobj->fadetime60, srcobj->fadetime60); + PD_CONV_VAL(dstobj->lastcalc60, srcobj->lastcalc60); + PD_CONV_VAL(dstobj->laserfade, srcobj->laserfade); + PD_CONV_ARRAY(dstobj->unusedmaybe, srcobj->unusedmaybe); + PD_CONV_ARRAY(dstobj->shadeinfo1, srcobj->shadeinfo1); + PD_CONV_ARRAY(dstobj->shadeinfo2, srcobj->shadeinfo2); + + PD_CONV_VAL(dstobj->actual1, srcobj->actual1); + PD_CONV_VAL(dstobj->actual2, srcobj->actual2); + PD_CONV_VAL(dstobj->extra1, srcobj->extra1); + PD_CONV_VAL(dstobj->extra2, srcobj->extra2); + + dst += sizeof(struct doorobj); + break; + } + case OBJTYPE_DOORSCALE: + { + struct n64_doorscaleobj* srcobj = (struct n64_doorscaleobj*)cmd; + struct doorscaleobj* dstobj = (struct doorscaleobj*)dst; + + convertDefaultObjHdr((struct defaultobj*)dstobj, cmd); + PD_CONV_VAL(dstobj->scale, srcobj->scale); + + dst += sizeof(struct doorscaleobj); + break; + } + case OBJTYPE_BASIC: + case OBJTYPE_HANGINGMONITORS: + case OBJTYPE_DEBRIS: + case OBJTYPE_HAT: + case OBJTYPE_ALARM: + { + struct n64_defaultobj* srcobj = (struct n64_defaultobj*)cmd; + struct defaultobj* dstobj = (struct defaultobj*)dst; + + convertDefaultObj(dstobj, cmd); + + dst += sizeof(struct defaultobj); + break; + } + case OBJTYPE_KEY: + { + struct n64_keyobj* srcobj = (struct n64_keyobj*)cmd; + struct keyobj* dstobj = (struct keyobj*)dst; + + convertDefaultObj(&dstobj->base, cmd); + PD_CONV_VAL(dstobj->keyflags, srcobj->keyflags); + + dst += sizeof(struct keyobj); + src += sizeof(struct n64_keyobj); + break; + } + case OBJTYPE_CCTV: + { + struct n64_cctvobj* srcobj = (struct n64_cctvobj*)cmd; + struct cctvobj* dstobj = (struct cctvobj*)dst; + + convertDefaultObj(&dstobj->base, cmd); + + PD_CONV_VAL(dstobj->lookatpadnum, srcobj->lookatpadnum); + PD_CONV_VAL(dstobj->toleft, srcobj->toleft); + PD_CONV_VAL(dstobj->yzero, srcobj->yzero); + PD_CONV_VAL(dstobj->yrot, srcobj->yrot); + PD_CONV_VAL(dstobj->yleft, srcobj->yleft); + PD_CONV_VAL(dstobj->yright, srcobj->yright); + PD_CONV_VAL(dstobj->yspeed, srcobj->yspeed); + PD_CONV_VAL(dstobj->ymaxspeed, srcobj->ymaxspeed); + PD_CONV_VAL(dstobj->seebondtime60, srcobj->seebondtime60); + PD_CONV_VAL(dstobj->maxdist, srcobj->maxdist); + PD_CONV_VAL(dstobj->xzero, srcobj->xzero); + + dst += sizeof(struct cctvobj); + break; + } + case OBJTYPE_AMMOCRATE: + { + struct n64_ammocrateobj* srcobj = (struct n64_ammocrateobj*)cmd; + struct ammocrateobj* dstobj = (struct ammocrateobj*)dst; + + convertDefaultObj(&dstobj->base, cmd); + PD_CONV_VAL(dstobj->ammotype, srcobj->ammotype); + + dst += sizeof(struct ammocrateobj); + break; + } + case OBJTYPE_WEAPON: + case OBJTYPE_MINE: + { + struct n64_weaponobj* srcobj = (struct n64_weaponobj*)cmd; + struct weaponobj* dstobj = (struct weaponobj*)dst; + + convertDefaultObj(&dstobj->base, cmd); + + PD_CONV_VAL(dstobj->weaponnum, srcobj->weaponnum); + PD_CONV_VAL(dstobj->unk5d, srcobj->unk5d); + PD_CONV_VAL(dstobj->unk5e, srcobj->unk5e); + PD_CONV_VAL(dstobj->gunfunc, srcobj->gunfunc); + + PD_CONV_VAL(dstobj->fadeouttimer60, srcobj->fadeouttimer60); + PD_CONV_VAL(dstobj->dualweaponnum, srcobj->dualweaponnum); + + PD_CONV_VAL(dstobj->team, srcobj->team); + + PD_CONV_PTR(dstobj->dualweapon, srcobj->ptr_dualweapon); + + dst += sizeof(struct weaponobj); + break; + } + case OBJTYPE_CHR: + { + struct n64_packedchr* srcobj = (struct n64_packedchr*)cmd; + struct packedchr* dstobj = (struct packedchr*)dst; + + PD_CONV_VAL(dstobj->chrindex, srcobj->chrindex); + PD_CONV_VAL(dstobj->unk02, srcobj->unk02); + PD_CONV_VAL(dstobj->typenum, srcobj->typenum); + PD_CONV_VAL(dstobj->spawnflags, srcobj->spawnflags); + PD_CONV_VAL(dstobj->chrnum, srcobj->chrnum); + PD_CONV_VAL(dstobj->padnum, srcobj->padnum); + PD_CONV_VAL(dstobj->bodynum, srcobj->bodynum); + PD_CONV_VAL(dstobj->headnum, srcobj->headnum); + PD_CONV_VAL(dstobj->ailistnum, srcobj->ailistnum); + PD_CONV_VAL(dstobj->padpreset, srcobj->padpreset); + PD_CONV_VAL(dstobj->chrpreset, srcobj->chrpreset); + PD_CONV_VAL(dstobj->hearscale, srcobj->hearscale); + PD_CONV_VAL(dstobj->viewdist, srcobj->viewdist); + PD_CONV_VAL(dstobj->flags, srcobj->flags); + PD_CONV_VAL(dstobj->flags2, srcobj->flags2); + PD_CONV_VAL(dstobj->team, srcobj->team); + PD_CONV_VAL(dstobj->squadron, srcobj->squadron); + PD_CONV_VAL(dstobj->chair, srcobj->chair); + PD_CONV_VAL(dstobj->convtalk, srcobj->convtalk); + PD_CONV_VAL(dstobj->tude, srcobj->tude); + PD_CONV_VAL(dstobj->naturalanim, srcobj->naturalanim); + PD_CONV_VAL(dstobj->yvisang, srcobj->yvisang); + PD_CONV_VAL(dstobj->teamscandist, srcobj->teamscandist); + + dst += sizeof(struct packedchr); + break; + } + case OBJTYPE_SINGLEMONITOR: + { + struct n64_singlemonitorobj* srcobj = (struct n64_singlemonitorobj*)cmd; + struct singlemonitorobj* dstobj = (struct singlemonitorobj*)dst; + + convertDefaultObj(&dstobj->base, cmd); + conv_tvscreen(&dstobj->screen, &srcobj->screen); + + PD_CONV_VAL(dstobj->owneroffset, srcobj->owneroffset); + PD_CONV_VAL(dstobj->ownerpart, srcobj->ownerpart); + PD_CONV_VAL(dstobj->imagenum, srcobj->imagenum); + + dst += sizeof(struct singlemonitorobj); + break; + } + case OBJTYPE_MULTIMONITOR: + { + struct n64_multimonitorobj* srcobj = (struct n64_multimonitorobj*)cmd; + struct multimonitorobj* dstobj = (struct multimonitorobj*)dst; + + convertDefaultObj(&dstobj->base, cmd); + + for (size_t i = 0; i < 4; i++) + conv_tvscreen(&dstobj->screens[i], &srcobj->screens[i]); + + PD_CONV_ARRAY(dstobj->imagenums, srcobj->imagenums); + dst += sizeof(struct multimonitorobj); + break; + } + case OBJTYPE_AUTOGUN: + { + struct n64_autogunobj* srcobj = (struct n64_autogunobj*)cmd; + struct autogunobj* dstobj = (struct autogunobj*)dst; + + convertDefaultObj(&dstobj->base, cmd); + + PD_CONV_VAL(dstobj->targetpad, srcobj->targetpad); + PD_CONV_VAL(dstobj->firing, srcobj->firing); + PD_CONV_VAL(dstobj->firecount, srcobj->firecount); + PD_CONV_VAL(dstobj->yzero, srcobj->yzero); + PD_CONV_VAL(dstobj->ymaxleft, srcobj->ymaxleft); + PD_CONV_VAL(dstobj->ymaxright, srcobj->ymaxright); + PD_CONV_VAL(dstobj->yrot, srcobj->yrot); + PD_CONV_VAL(dstobj->yspeed, srcobj->yspeed); + PD_CONV_VAL(dstobj->xzero, srcobj->xzero); + PD_CONV_VAL(dstobj->xrot, srcobj->xrot); + PD_CONV_VAL(dstobj->xspeed, srcobj->xspeed); + PD_CONV_VAL(dstobj->maxspeed, srcobj->maxspeed); + PD_CONV_VAL(dstobj->aimdist, srcobj->aimdist); + PD_CONV_VAL(dstobj->barrelspeed, srcobj->barrelspeed); + PD_CONV_VAL(dstobj->barrelrot, srcobj->barrelrot); + PD_CONV_VAL(dstobj->lastseebond60, srcobj->lastseebond60); + PD_CONV_VAL(dstobj->lastaimbond60, srcobj->lastaimbond60); + PD_CONV_VAL(dstobj->allowsoundframe, srcobj->allowsoundframe); + PD_CONV_PTR(dstobj->beam, srcobj->ptr_beam); + PD_CONV_VAL(dstobj->shotbondsum, srcobj->shotbondsum); + PD_CONV_PTR(dstobj->target, srcobj->ptr_target); + PD_CONV_VAL(dstobj->targetteam, srcobj->targetteam); + PD_CONV_VAL(dstobj->ammoquantity, srcobj->ammoquantity); + PD_CONV_VAL(dstobj->nextchrtest, srcobj->nextchrtest); + + dst += sizeof(struct autogunobj); + break; + } + case OBJTYPE_LINKGUNS: + { + struct n64_linkgunsobj* srcobj = (struct n64_linkgunsobj*)cmd; + struct linkgunsobj* dstobj = (struct linkgunsobj*)dst; + + convertDefaultObjHdr((struct defaultobj*)dstobj, cmd); + PD_CONV_VAL(dstobj->offset1, srcobj->offset1); + PD_CONV_VAL(dstobj->offset2, srcobj->offset2); + + dst += sizeof(struct linkgunsobj); + break; + } + case OBJTYPE_GRENADEPROB: + { + struct n64_grenadeprobobj* srcobj = (struct n64_grenadeprobobj*)cmd; + struct grenadeprobobj* dstobj = (struct grenadeprobobj*)dst; + + convertDefaultObjHdr((struct defaultobj*)dstobj, cmd); + PD_CONV_VAL(dstobj->chrnum, srcobj->chrnum); + PD_CONV_VAL(dstobj->probability, srcobj->probability); + + dst += sizeof(struct grenadeprobobj); + break; + } + case OBJTYPE_LINKLIFTDOOR: + { + struct n64_linkliftdoorobj* srcobj = (struct n64_linkliftdoorobj*)cmd; + struct linkliftdoorobj* dstobj = (struct linkliftdoorobj*)dst; + + convertDefaultObjHdr((struct defaultobj*)dstobj, cmd); + PD_CONV_PTR(dstobj->door, srcobj->ptr_door); + PD_CONV_PTR(dstobj->lift, srcobj->ptr_lift); + PD_CONV_PTR(dstobj->next, srcobj->ptr_next); + PD_CONV_VAL(dstobj->stopnum, srcobj->stopnum); + + dst += sizeof(struct linkliftdoorobj); + break; + } + case OBJTYPE_MULTIAMMOCRATE: + { + struct n64_multiammocrateobj* srcobj = (struct n64_multiammocrateobj*)cmd; + struct multiammocrateobj* dstobj = (struct multiammocrateobj*)dst; + + convertDefaultObj(&dstobj->base, cmd); + + for (size_t i = 0; i < 19; i++) { + PD_CONV_VAL(dstobj->slots[i].modelnum, srcobj->slots[i].modelnum); + PD_CONV_VAL(dstobj->slots[i].quantity, srcobj->slots[i].quantity); + } + + dst += sizeof(struct multiammocrateobj); + break; + } + case OBJTYPE_SHIELD: + { + struct n64_shieldobj* srcobj = (struct n64_shieldobj*)cmd; + struct shieldobj* dstobj = (struct shieldobj*)dst; + + convertDefaultObj(&dstobj->base, cmd); + + PD_CONV_VAL(dstobj->initialamount, srcobj->initialamount); + PD_CONV_VAL(dstobj->amount, srcobj->amount); + PD_CONV_VAL(dstobj->unk64, srcobj->unk64); + + dst += sizeof(struct shieldobj); + break; + } + case OBJTYPE_TAG: + { + struct n64_tag* srcobj = (struct n64_tag*)cmd; + struct tag* dstobj = (struct tag*)dst; + + convertDefaultObjHdr((struct defaultobj*)dstobj, cmd); + PD_CONV_VAL(dstobj->tagnum, srcobj->tagnum); + PD_CONV_VAL(dstobj->cmdoffset, srcobj->cmdoffset); + PD_CONV_PTR(dstobj->next, srcobj->ptr_next); + PD_CONV_PTR(dstobj->obj, srcobj->ptr_obj); + + dst += sizeof(struct tag); + break; + } + case OBJTYPE_BEGINOBJECTIVE: + { + struct n64_objective* srcobj = (struct n64_objective*)cmd; + struct objective* dstobj = (struct objective*)dst; + + convertDefaultObjHdr((struct defaultobj*)dstobj, cmd); + PD_CONV_VAL(dstobj->index, srcobj->index); + PD_CONV_VAL(dstobj->text, srcobj->text); + PD_CONV_VAL(dstobj->unk0c, srcobj->unk0c); + PD_CONV_VAL(dstobj->flags, srcobj->flags); + PD_CONV_VAL(dstobj->difficulties, srcobj->difficulties); + + dst += sizeof(struct objective); + break; + } + case OBJTYPE_ENDOBJECTIVE: + case OBJECTIVETYPE_1F: + case OBJTYPE_22: + case OBJTYPE_GASBOTTLE: + case OBJTYPE_29: + case OBJTYPE_SAFE: + { + struct n64_stdobjective* srcobj = (struct n64_stdobjective*)cmd; + struct n64_stdobjective* dstobj = (struct n64_stdobjective*)dst; + + convertDefaultObjHdr((struct defaultobj*)dstobj, cmd); + + dst += sizeof(struct n64_stdobjective); + break; + } + case OBJECTIVETYPE_DESTROYOBJ: + case OBJECTIVETYPE_COMPFLAGS: + case OBJECTIVETYPE_FAILFLAGS: + case OBJECTIVETYPE_COLLECTOBJ: + case OBJECTIVETYPE_THROWOBJ: + { + struct n64_objectivecmd* srcobj = (struct n64_objectivecmd*)cmd; + struct n64_objectivecmd* dstobj = (struct n64_objectivecmd*)dst; + + PD_CONV_ARRAY(dstobj->cmd0, srcobj->cmd0); + PD_CONV_VAL(dstobj->cmd1, srcobj->cmd1); + + dst += sizeof(struct n64_objectivecmd); + break; + } + case OBJECTIVETYPE_HOLOGRAPH: + { + struct n64_criteria_holograph* srcobj = (struct n64_criteria_holograph*)cmd; + struct criteria_holograph* dstobj = (struct criteria_holograph*)dst; + + convertDefaultObjHdr((struct defaultobj*)dstobj, cmd); + PD_CONV_VAL(dstobj->obj, srcobj->obj); + PD_CONV_VAL(dstobj->status, srcobj->status); + PD_CONV_PTR(dstobj->next, srcobj->ptr_next); + + dst += sizeof(struct criteria_holograph); + break; + } + case OBJECTIVETYPE_ENTERROOM: + { + struct n64_criteria_roomentered* srcobj = (struct n64_criteria_roomentered*)cmd; + struct criteria_roomentered* dstobj = (struct criteria_roomentered*)dst; + + convertDefaultObjHdr((struct defaultobj*)dstobj, cmd); + PD_CONV_VAL(dstobj->pad, srcobj->pad); + PD_CONV_VAL(dstobj->status, srcobj->status); + PD_CONV_PTR(dstobj->next, srcobj->ptr_next); + + dst += sizeof(struct criteria_roomentered); + break; + } + case OBJECTIVETYPE_THROWINROOM: + { + struct n64_criteria_throwinroom* srcobj = (struct n64_criteria_throwinroom*)cmd; + struct criteria_throwinroom* dstobj = (struct criteria_throwinroom*)dst; + + convertDefaultObjHdr((struct defaultobj*)dstobj, cmd); + PD_CONV_VAL(dstobj->pad, srcobj->pad); + PD_CONV_VAL(dstobj->status, srcobj->status); + PD_CONV_PTR(dstobj->next, srcobj->ptr_next); + + dst += sizeof(struct criteria_throwinroom); + break; + } + case OBJTYPE_BRIEFING: + { + struct n64_briefingobj* srcobj = (struct n64_briefingobj*)cmd; + struct briefingobj* dstobj = (struct briefingobj*)dst; + + convertDefaultObjHdr((struct defaultobj*)dstobj, cmd); + PD_CONV_VAL(dstobj->type, srcobj->type); + PD_CONV_VAL(dstobj->text, srcobj->text); + PD_CONV_PTR(dstobj->next, srcobj->ptr_next); + + dst += sizeof(struct briefingobj); + break; + } + case OBJTYPE_RENAMEOBJ: + { + struct n64_textoverride* srcobj = (struct n64_textoverride*)cmd; + struct textoverride* dstobj = (struct textoverride*)dst; + + convertDefaultObjHdr((struct defaultobj*)dstobj, cmd); + PD_CONV_VAL(dstobj->objoffset, srcobj->objoffset); + PD_CONV_VAL(dstobj->weapon, srcobj->weapon); + PD_CONV_VAL(dstobj->obtaintext, srcobj->obtaintext); + PD_CONV_VAL(dstobj->ownertext, srcobj->ownertext); + PD_CONV_VAL(dstobj->inventorytext, srcobj->inventorytext); + PD_CONV_VAL(dstobj->inventory2text, srcobj->inventory2text); + PD_CONV_VAL(dstobj->pickuptext, srcobj->pickuptext); + PD_CONV_PTR(dstobj->next, srcobj->ptr_next); + PD_CONV_PTR(dstobj->obj, srcobj->ptr_obj); + + dst += sizeof(struct textoverride); + break; + } + case OBJTYPE_PADLOCKEDDOOR: + { + struct n64_padlockeddoorobj* srcobj = (struct n64_padlockeddoorobj*)cmd; + struct padlockeddoorobj* dstobj = (struct padlockeddoorobj*)dst; + + convertDefaultObjHdr((struct defaultobj*)dstobj, cmd); + PD_CONV_PTR(dstobj->door, srcobj->ptr_door); + PD_CONV_PTR(dstobj->lock, srcobj->ptr_lock); + PD_CONV_PTR(dstobj->next, srcobj->ptr_next); + + dst += sizeof(struct padlockeddoorobj); + break; + } + case OBJTYPE_TRUCK: + { + struct n64_truckobj* srcobj = (struct n64_truckobj*)cmd; + struct truckobj* dstobj = (struct truckobj*)dst; + + convertDefaultObj(&dstobj->base, cmd); + + PD_CONV_PTR(dstobj->ailist, srcobj->ptr_ailist); + PD_CONV_VAL(dstobj->aioffset, srcobj->aioffset); + PD_CONV_VAL(dstobj->aireturnlist, srcobj->aireturnlist); + PD_CONV_VAL(dstobj->speed, srcobj->speed); + PD_CONV_VAL(dstobj->wheelxrot, srcobj->wheelxrot); + PD_CONV_VAL(dstobj->wheelyrot, srcobj->wheelyrot); + PD_CONV_VAL(dstobj->speedaim, srcobj->speedaim); + PD_CONV_VAL(dstobj->speedtime60, srcobj->speedtime60); + PD_CONV_VAL(dstobj->turnrot60, srcobj->turnrot60); + PD_CONV_VAL(dstobj->roty, srcobj->roty); + PD_CONV_PTR(dstobj->path, srcobj->ptr_path); + PD_CONV_VAL(dstobj->nextstep, srcobj->nextstep); + + dst += sizeof(struct truckobj); + break; + } + case OBJTYPE_HELI: + { + struct n64_heliobj* srcobj = (struct n64_heliobj*)cmd; + struct heliobj* dstobj = (struct heliobj*)dst; + + convertDefaultObj(&dstobj->base, cmd); + + PD_CONV_PTR(dstobj->ailist, srcobj->ptr_ailist); + PD_CONV_VAL(dstobj->aioffset, srcobj->aioffset); + PD_CONV_VAL(dstobj->aireturnlist, srcobj->aireturnlist); + PD_CONV_VAL(dstobj->rotoryrot, srcobj->rotoryrot); + PD_CONV_VAL(dstobj->rotoryspeed, srcobj->rotoryspeed); + PD_CONV_VAL(dstobj->rotoryspeedaim, srcobj->rotoryspeedaim); + PD_CONV_VAL(dstobj->rotoryspeedtime, srcobj->rotoryspeedtime); + PD_CONV_VAL(dstobj->speed, srcobj->speed); + PD_CONV_VAL(dstobj->speedaim, srcobj->speedaim); + PD_CONV_VAL(dstobj->speedtime60, srcobj->speedtime60); + PD_CONV_VAL(dstobj->yrot, srcobj->yrot); + PD_CONV_PTR(dstobj->path, srcobj->ptr_path); + PD_CONV_VAL(dstobj->nextstep, srcobj->nextstep); + + dst += sizeof(struct heliobj); + break; + } + case OBJTYPE_GLASS: + { + struct n64_glassobj* srcobj = (struct n64_glassobj*)cmd; + struct glassobj* dstobj = (struct glassobj*)dst; + + convertDefaultObj(&dstobj->base, cmd); + PD_CONV_VAL(dstobj->portalnum, srcobj->portalnum); + + dst += sizeof(struct glassobj); + break; + } + case OBJTYPE_SAFEITEM: + { + struct n64_safeitemobj* srcobj = (struct n64_safeitemobj*)cmd; + struct safeitemobj* dstobj = (struct safeitemobj*)dst; + + convertDefaultObjHdr((struct defaultobj*)dstobj, cmd); + PD_CONV_PTR(dstobj->item, srcobj->ptr_item); + PD_CONV_PTR(dstobj->safe, srcobj->ptr_safe); + PD_CONV_PTR(dstobj->door, srcobj->ptr_door); + PD_CONV_PTR(dstobj->next, srcobj->ptr_next); + + dst += sizeof(struct safeitemobj); + break; + } + case OBJTYPE_TANK: + { + dst += sizeof(struct n64_tankobj); + break; + } + case OBJTYPE_CAMERAPOS: + { + struct n64_cameraposobj* srcobj = (struct n64_cameraposobj*)cmd; + struct cameraposobj* dstobj = (struct cameraposobj*)dst; + + convertDefaultObjHdr((struct defaultobj*)dstobj, cmd); + PD_CONV_VAL(dstobj->x, srcobj->x); + PD_CONV_VAL(dstobj->y, srcobj->y); + PD_CONV_VAL(dstobj->z, srcobj->z); + PD_CONV_VAL(dstobj->theta, srcobj->theta); + PD_CONV_VAL(dstobj->verta, srcobj->verta); + PD_CONV_VAL(dstobj->pad, srcobj->pad); + + dst += sizeof(struct cameraposobj); + break; + } + case OBJTYPE_TINTEDGLASS: + { + struct n64_tintedglassobj* srcobj = (struct n64_tintedglassobj*)cmd; + struct tintedglassobj* dstobj = (struct tintedglassobj*)dst; + + convertDefaultObj(&dstobj->base, cmd); + + PD_CONV_VAL(dstobj->xludist, srcobj->xludist); + PD_CONV_VAL(dstobj->opadist, srcobj->opadist); + PD_CONV_VAL(dstobj->opacity, srcobj->opacity); + PD_CONV_VAL(dstobj->portalnum, srcobj->portalnum); + PD_CONV_VAL(dstobj->unk64, srcobj->unk64); + + dst += sizeof(struct tintedglassobj); + break; + } + case OBJTYPE_LIFT: + { + struct n64_liftobj* srcobj = (struct n64_liftobj*)cmd; + struct liftobj* dstobj = (struct liftobj*)dst; + + convertDefaultObj(&dstobj->base, cmd); + + PD_CONV_ARRAY(dstobj->pads, srcobj->pads); + for (int k = 0; k < 4; k++) + PD_CONV_PTR(dstobj->doors[k], srcobj->ptr_doors[k]); + PD_CONV_VAL(dstobj->dist, srcobj->dist); + PD_CONV_VAL(dstobj->speed, srcobj->speed); + PD_CONV_VAL(dstobj->accel, srcobj->accel); + PD_CONV_VAL(dstobj->maxspeed, srcobj->maxspeed); + PD_CONV_VAL(dstobj->soundtype, srcobj->soundtype); + PD_CONV_VAL(dstobj->levelcur, srcobj->levelcur); + PD_CONV_VAL(dstobj->levelaim, srcobj->levelaim); + PD_CONV_VAL(dstobj->prevpos, srcobj->prevpos); + + dst += sizeof(struct liftobj); + break; + } + case OBJTYPE_CONDITIONALSCENERY: + { + struct n64_linksceneryobj* srcobj = (struct n64_linksceneryobj*)cmd; + struct linksceneryobj* dstobj = (struct linksceneryobj*)dst; + + convertDefaultObjHdr((struct defaultobj*)dstobj, cmd); + PD_CONV_PTR(dstobj->trigger, srcobj->ptr_trigger); + PD_CONV_PTR(dstobj->unexp, srcobj->ptr_unexp); + PD_CONV_PTR(dstobj->exp, srcobj->ptr_exp); + PD_CONV_PTR(dstobj->next, srcobj->ptr_next); + + dst += sizeof(struct linksceneryobj); + break; + } + case OBJTYPE_BLOCKEDPATH: + { + struct n64_blockedpathobj* srcobj = (struct n64_blockedpathobj*)cmd; + struct blockedpathobj* dstobj = (struct blockedpathobj*)dst; + + convertDefaultObjHdr((struct defaultobj*)dstobj, cmd); + PD_CONV_PTR(dstobj->blocker, srcobj->ptr_blocker); + PD_CONV_VAL(dstobj->waypoint1, srcobj->waypoint1); + PD_CONV_VAL(dstobj->waypoint2, srcobj->waypoint2); + PD_CONV_PTR(dstobj->next, srcobj->ptr_next); + + dst += sizeof(struct blockedpathobj); + break; + } + case OBJTYPE_HOVERBIKE: { + struct n64_hoverbikeobj* srcobj = (struct n64_hoverbikeobj*)cmd; + struct hoverbikeobj* dstobj = (struct hoverbikeobj*)dst; + + convertDefaultObj(&dstobj->base, cmd); + + PD_CONV_VAL(dstobj->hov.type, srcobj->hov.type); + PD_CONV_VAL(dstobj->hov.flags, srcobj->hov.flags); + PD_CONV_VAL(dstobj->hov.bobycur, srcobj->hov.bobycur); + PD_CONV_VAL(dstobj->hov.bobytarget, srcobj->hov.bobytarget); + PD_CONV_VAL(dstobj->hov.bobyspeed, srcobj->hov.bobyspeed); + PD_CONV_VAL(dstobj->hov.yrot, srcobj->hov.yrot); + PD_CONV_VAL(dstobj->hov.bobpitchcur, srcobj->hov.bobpitchcur); + PD_CONV_VAL(dstobj->hov.bobpitchtarget, srcobj->hov.bobpitchtarget); + PD_CONV_VAL(dstobj->hov.bobpitchspeed, srcobj->hov.bobpitchspeed); + PD_CONV_VAL(dstobj->hov.bobrollcur, srcobj->hov.bobrollcur); + PD_CONV_VAL(dstobj->hov.bobrolltarget, srcobj->hov.bobrolltarget); + PD_CONV_VAL(dstobj->hov.bobrollspeed, srcobj->hov.bobrollspeed); + PD_CONV_VAL(dstobj->hov.groundpitch, srcobj->hov.groundpitch); + PD_CONV_VAL(dstobj->hov.y, srcobj->hov.y); + PD_CONV_VAL(dstobj->hov.ground, srcobj->hov.ground); + PD_CONV_VAL(dstobj->hov.prevframe60, srcobj->hov.prevframe60); + PD_CONV_VAL(dstobj->hov.prevgroundframe60, srcobj->hov.prevgroundframe60); + + PD_CONV_ARRAY(dstobj->speed, srcobj->speed); + PD_CONV_VAL(dstobj->exreal, srcobj->exreal); + PD_CONV_VAL(dstobj->ezreal, srcobj->ezreal); + PD_CONV_VAL(dstobj->ezreal2, srcobj->ezreal2); + PD_CONV_VAL(dstobj->leanspeed, srcobj->leanspeed); + PD_CONV_VAL(dstobj->leandiff, srcobj->leandiff); + PD_CONV_VAL(dstobj->maxspeedtime240, srcobj->maxspeedtime240); + PD_CONV_ARRAY(dstobj->prevpos, srcobj->prevpos); + PD_CONV_ARRAY(dstobj->rels, srcobj->rels); + PD_CONV_ARRAY(dstobj->speedabs, srcobj->speedabs); + PD_CONV_ARRAY(dstobj->speedrel, srcobj->speedrel); + + dst += sizeof(struct hoverbikeobj); + break; + } + case OBJTYPE_HOVERPROP: + { + struct n64_hoverpropobj* srcobj = (struct n64_hoverpropobj*)cmd; + struct hoverpropobj* dstobj = (struct hoverpropobj*)dst; + + convertDefaultObj(&dstobj->base, cmd); + + PD_CONV_VAL(dstobj->hov.type, srcobj->hov.type); + PD_CONV_VAL(dstobj->hov.flags, srcobj->hov.flags); + PD_CONV_VAL(dstobj->hov.bobycur, srcobj->hov.bobycur); + PD_CONV_VAL(dstobj->hov.bobytarget, srcobj->hov.bobytarget); + PD_CONV_VAL(dstobj->hov.bobyspeed, srcobj->hov.bobyspeed); + PD_CONV_VAL(dstobj->hov.yrot, srcobj->hov.yrot); + PD_CONV_VAL(dstobj->hov.bobpitchcur, srcobj->hov.bobpitchcur); + PD_CONV_VAL(dstobj->hov.bobpitchtarget, srcobj->hov.bobpitchtarget); + PD_CONV_VAL(dstobj->hov.bobpitchspeed, srcobj->hov.bobpitchspeed); + PD_CONV_VAL(dstobj->hov.bobrollcur, srcobj->hov.bobrollcur); + PD_CONV_VAL(dstobj->hov.bobrolltarget, srcobj->hov.bobrolltarget); + PD_CONV_VAL(dstobj->hov.bobrollspeed, srcobj->hov.bobrollspeed); + PD_CONV_VAL(dstobj->hov.groundpitch, srcobj->hov.groundpitch); + PD_CONV_VAL(dstobj->hov.y, srcobj->hov.y); + PD_CONV_VAL(dstobj->hov.ground, srcobj->hov.ground); + PD_CONV_VAL(dstobj->hov.prevframe60, srcobj->hov.prevframe60); + PD_CONV_VAL(dstobj->hov.prevgroundframe60, srcobj->hov.prevgroundframe60); + + dst += sizeof(struct hoverpropobj); + break; + } + case OBJTYPE_FAN: + { + struct n64_fanobj* srcobj = (struct n64_fanobj*)cmd; + struct fanobj* dstobj = (struct fanobj*)dst; + + convertDefaultObj(&dstobj->base, cmd); + + PD_CONV_VAL(dstobj->yrot, srcobj->yrot); + PD_CONV_VAL(dstobj->yrotprev, srcobj->yrotprev); + PD_CONV_VAL(dstobj->ymaxspeed, srcobj->ymaxspeed); + PD_CONV_VAL(dstobj->yspeed, srcobj->yspeed); + PD_CONV_VAL(dstobj->yaccel, srcobj->yaccel); + PD_CONV_VAL(dstobj->on, srcobj->on); + + dst += sizeof(struct fanobj); + break; + } + case OBJTYPE_HOVERCAR: + { + struct n64_hovercarobj* srcobj = (struct n64_hovercarobj*)cmd; + struct hovercarobj* dstobj = (struct hovercarobj*)dst; + + convertDefaultObj(&dstobj->base, cmd); + + PD_CONV_PTR(dstobj->ailist, srcobj->ptr_ailist); + PD_CONV_VAL(dstobj->aioffset, srcobj->aioffset); + PD_CONV_VAL(dstobj->aireturnlist, srcobj->aireturnlist); + PD_CONV_VAL(dstobj->speed, srcobj->speed); + PD_CONV_VAL(dstobj->speedaim, srcobj->speedaim); + PD_CONV_VAL(dstobj->speedtime60, srcobj->speedtime60); + PD_CONV_VAL(dstobj->turnyspeed60, srcobj->turnyspeed60); + PD_CONV_VAL(dstobj->turnxspeed60, srcobj->turnxspeed60); + PD_CONV_VAL(dstobj->turnrot60, srcobj->turnrot60); + PD_CONV_VAL(dstobj->roty, srcobj->roty); + PD_CONV_VAL(dstobj->rotx, srcobj->rotx); + PD_CONV_VAL(dstobj->rotz, srcobj->rotz); + PD_CONV_PTR(dstobj->path, srcobj->ptr_path); + PD_CONV_VAL(dstobj->nextstep, srcobj->nextstep); + PD_CONV_VAL(dstobj->status, srcobj->status); + PD_CONV_VAL(dstobj->dead, srcobj->dead); + PD_CONV_VAL(dstobj->deadtimer60, srcobj->deadtimer60); + PD_CONV_VAL(dstobj->sparkstimer60, srcobj->sparkstimer60); + + dst += sizeof(struct hovercarobj); + break; + } + case OBJTYPE_PADEFFECT: + { + struct padeffectobj* srcobj = (struct padeffectobj*)cmd; + struct padeffectobj* dstobj = (struct padeffectobj*)dst; + + convertDefaultObjHdr((struct defaultobj*)dstobj, cmd); + PD_CONV_VAL(dstobj->effect, srcobj->effect); + PD_CONV_VAL(dstobj->pad, srcobj->pad); + + dst += sizeof(struct padeffectobj); + break; + } + case OBJTYPE_CHOPPER: + { + struct n64_chopperobj* srcobj = (struct n64_chopperobj*)cmd; + struct chopperobj* dstobj = (struct chopperobj*)dst; + + convertDefaultObj(&dstobj->base, cmd); + + PD_CONV_PTR(dstobj->ailist, srcobj->ptr_ailist); + PD_CONV_VAL(dstobj->aioffset, srcobj->aioffset); + PD_CONV_VAL(dstobj->aireturnlist, srcobj->aireturnlist); + PD_CONV_VAL(dstobj->speed, srcobj->speed); + PD_CONV_VAL(dstobj->speedaim, srcobj->speedaim); + PD_CONV_VAL(dstobj->speedtime60, srcobj->speedtime60); + PD_CONV_VAL(dstobj->turnyspeed60, srcobj->turnyspeed60); + PD_CONV_VAL(dstobj->turnxspeed60, srcobj->turnxspeed60); + PD_CONV_VAL(dstobj->turnrot60, srcobj->turnrot60); + PD_CONV_VAL(dstobj->roty, srcobj->roty); + PD_CONV_VAL(dstobj->rotx, srcobj->rotx); + PD_CONV_VAL(dstobj->rotz, srcobj->rotz); + PD_CONV_PTR(dstobj->path, srcobj->ptr_path); + PD_CONV_VAL(dstobj->nextstep, srcobj->nextstep); + PD_CONV_VAL(dstobj->weaponsarmed, srcobj->weaponsarmed); + PD_CONV_VAL(dstobj->ontarget, srcobj->ontarget); + PD_CONV_VAL(dstobj->target, srcobj->target); + PD_CONV_VAL(dstobj->attackmode, srcobj->attackmode); + PD_CONV_VAL(dstobj->cw, srcobj->cw); + PD_CONV_VAL(dstobj->vx, srcobj->vx); + PD_CONV_VAL(dstobj->vy, srcobj->vy); + PD_CONV_VAL(dstobj->vz, srcobj->vz); + PD_CONV_VAL(dstobj->power, srcobj->power); + PD_CONV_VAL(dstobj->otx, srcobj->otx); + PD_CONV_VAL(dstobj->oty, srcobj->oty); + PD_CONV_VAL(dstobj->otz, srcobj->otz); + PD_CONV_VAL(dstobj->bob, srcobj->bob); + PD_CONV_VAL(dstobj->bobstrength, srcobj->bobstrength); + PD_CONV_VAL(dstobj->targetvisible, srcobj->targetvisible); + PD_CONV_VAL(dstobj->timer60, srcobj->timer60); + PD_CONV_VAL(dstobj->patroltimer60, srcobj->patroltimer60); + PD_CONV_VAL(dstobj->gunturnyspeed60, srcobj->gunturnyspeed60); + PD_CONV_VAL(dstobj->gunturnxspeed60, srcobj->gunturnxspeed60); + PD_CONV_VAL(dstobj->gunroty, srcobj->gunroty); + PD_CONV_VAL(dstobj->gunrotx, srcobj->gunrotx); + PD_CONV_VAL(dstobj->barrelrotspeed, srcobj->barrelrotspeed); + PD_CONV_VAL(dstobj->barrelrot, srcobj->barrelrot); + PD_CONV_PTR(dstobj->fireslotthing, srcobj->ptr_fireslotthing); + PD_CONV_VAL(dstobj->dead, srcobj->dead); + + dst += sizeof(struct chopperobj); + break; + } + case OBJTYPE_ESCASTEP: + { + struct n64_escalatorobj* srcobj = (struct n64_escalatorobj*)cmd; + struct escalatorobj* dstobj = (struct escalatorobj*)dst; + + convertDefaultObj(&dstobj->base, cmd); + + PD_CONV_VAL(dstobj->frame, srcobj->frame); + PD_CONV_VAL(dstobj->prevpos, srcobj->prevpos); + + dst += sizeof(struct escalatorobj); + break; + } + } + + cmd = (struct n64_defaultobj*)((u32*)cmd + obj_size(cmd)); + type = cmd->type; + } + + *(u32*)(dst) = htobe32(OBJTYPE_END); + dst += sizeof(u32); + + return (u32)(dst - start); +} + +static uintptr_t convertIntro(u8 *dst, u8 *src) +{ + u8 cmd_size[] = { + 3, // INTROCMD_SPAWN + 4, // INTROCMD_WEAPON + 4, // INTROCMD_AMMO + 8, // INTROCMD_3 + 2, // INTROCMD_4 + 2, // INTROCMD_OUTFIT + 10, // INTROCMD_6 + 3, // INTROCMD_WATCHTIME + 2, // INTROCMD_CREDITOFFSET + 3, // INTROCMD_CASE + 3, // INTROCMD_CASERESPAWN + 2, // INTROCMD_HILL + 1, // the INTROCMD_END constant itself + }; + + s32* dstintro = (s32*)dst; + s32* srcintro = (s32*)src; + + while (true) { + s32 cmd = dstintro[0] = srctodst32(srcintro[0]); + u8 size = cmd_size[*dstintro]; + for (int i = 1; i < size; i++) { + dstintro[i] = srctodst32(srcintro[i]); + } + + dstintro += size; + srcintro += size; + + if (cmd == INTROCMD_END) break; + } + + return (u32)((u8*)dstintro - dst); +} + +static u32 convertPaths(u8 *dst, u8 *src) +{ + struct n64_path* srcpath = (struct n64_path*)src; + struct path* dstpath = (struct path*)dst; + + while (true) { + PD_CONV_PTR(dstpath->pads, srcpath->ptr_pads); + PD_CONV_VAL(dstpath->id, srcpath->id); + PD_CONV_VAL(dstpath->flags, srcpath->flags); + PD_CONV_VAL(dstpath->len, srcpath->len); + + if (srcpath->ptr_pads == 0) break; + + dstpath++; + srcpath++; + } + + // extra pointer for the end marker + return (u32)((u8*)dstpath - dst + sizeof(uintptr_t)); +} + +static u32 convertPads(struct path *dstpaths, u8 *dst, u8 *src, u32 dstpos) +{ + u32 start = dstpos; + s32 *dstpads = (s32*)&dst[dstpos]; + while (dstpaths->pads) { + s32 *pads = (s32*)&src[(uintptr_t)dstpaths->pads]; + dstpaths->pads = (s32*)dstpos; + + while (*pads) { + s32 p = srctoh32(*pads++); + *dstpads++ = p; + dstpos += sizeof(s32); + if (p == -1) break; + } + + dstpaths++; + } + + return dstpos - start; +} + +static u32 convertAiLists(u8* dst, u8* src) +{ + struct n64_ailist* srcailist = (struct n64_ailist*)src; + struct ailist* dstailist = (struct ailist*)dst; + + while (true) { + // at this point these fields are already converted, so we just assign + dstailist->list = srcailist->ptr_list; + dstailist->id = srcailist->id; + + + if (srcailist->ptr_list == 0) break; + + dstailist++; + srcailist++; + } + + return (u32)((u8*)dstailist - dst + sizeof(uintptr_t)); +} + +u32 chraiGetAilistLength(u8 *list); + +static u32 convertLists(u8 *dst, u8 *src, u32 dstpos, u32 src_ofs) +{ + resetMarkers(); + struct n64_ailist *src_ailists = (struct n64_ailist*)&src[src_ofs]; + + // count the lists and pre-convert the fields + int nlists = 0; + for (struct n64_ailist *tmp = src_ailists; tmp->ptr_list; tmp++, nlists++) { + tmp->ptr_list = srctodst32(tmp->ptr_list); + tmp->id = srctodst32(tmp->id); + } + + for (struct n64_ailist *ailist = src_ailists; ailist->ptr_list; ailist++) { + // update the src list pointers here + uintptr_t src_ptr_list = (uintptr_t) ailist->ptr_list; + ailist->ptr_list = (u8*)dstpos; + + // multiple ailists can point to the same list, so we need to check if it was already copied + struct ptrmarker *marker = findPtrMarker(src_ptr_list); + if (marker) { + ailist->ptr_list = marker->ptr_host; + continue; + } + + addMarker(src_ptr_list, dstpos); + + u8 *list = &src[src_ptr_list]; + u32 listsize = chraiGetAilistLength(list); + memcpy(dst + dstpos, list, listsize); + + // align to the next multiple of 4 + dstpos += ((listsize + 3) >> 2) << 2; + } + + return dstpos; +} + +static int convertSetup(u8 *dst, u8 *src, u32 srclen) +{ + struct n64_stagesetup *src_header = (struct n64_stagesetup*)src; + struct stagesetup *dst_header = (struct stagesetup*)dst; + + src_header->ptr_props = srctodst32(src_header->ptr_props); + src_header->ptr_intro = srctodst32(src_header->ptr_intro); + src_header->ptr_ailists = srctodst32(src_header->ptr_ailists); + src_header->ptr_paths = srctodst32(src_header->ptr_paths); + + u32 srcpos = sizeof(*src_header); + u32 dstpos = sizeof(*dst_header); + + srcpos = src_header->ptr_props; + dst_header->props = (u32*) dstpos; + dstpos += convertProps(&dst[dstpos], &src[srcpos]); + + srcpos = src_header->ptr_intro; + dst_header->intro = (s32*)dstpos; + dstpos += convertIntro(&dst[dstpos], &src[srcpos]); + + // write the lists bytecodes before the ailists entries + dstpos = convertLists(dst, src, dstpos, src_header->ptr_ailists); + + srcpos = src_header->ptr_ailists; + dst_header->ailists = (struct ailist*)dstpos; + dstpos += convertAiLists(&dst[dstpos], &src[srcpos]); + + srcpos = src_header->ptr_paths; + dst_header->paths = (struct path*) dstpos; + dstpos += convertPaths(&dst[dstpos], &src[srcpos]); + + dstpos += convertPads(&dst[(uintptr_t)dst_header->paths], dst, src, dstpos); + + return dstpos; +} + +u8 *preprocessSetupFile(u8 *data, u32 size, u32 *outSize) { + u32 newSizeEstimated = romdataFileGetEstimatedSize(size, FT_SETUP); + u8 *dst = sysMemZeroAlloc(newSizeEstimated); + + u32 newSize = convertSetup(dst, data, size); + + if (newSize > newSizeEstimated) { + sysLogPrintf(LOG_ERROR, "overflow when trying to preprocess a model file, size %d newsize %d", size, newSize); + exit(EXIT_FAILURE); + } + + memcpy(data, dst, newSize); + sysMemFree(dst); + + *outSize = newSize; + + return 0; +} diff --git a/port/src/preprocess/filetiles.c b/port/src/preprocess/filetiles.c new file mode 100644 index 000000000..ed63c416a --- /dev/null +++ b/port/src/preprocess/filetiles.c @@ -0,0 +1,107 @@ +#include +#include +#include + +#include "common.h" +#include "romdata.h" +#include "system.h" + + +struct tile { + u8 type; + u8 numvertices; + u16 flags; + u16 floortype; + u8 xmin; + u8 ymin; + u8 zmin; + u8 xmax; + u8 ymax; + u8 zmax; + u16 floorcol; +}; + +u32 convertTiles(u8 *dst, u8 *src, size_t srclen) +{ + int num_rooms = srctoh32(*(u32 *) src); + + size_t src_ptr_table_len = (num_rooms + 1) * 4; + size_t dst_ptr_table_len = (num_rooms + 1) * sizeof(u32); + + u32 *src_offsets = (u32 *) &src[4]; + + size_t data_len = srclen - src_ptr_table_len - 4; + + *(u32 *) dst = htodst32(num_rooms); + + u32 *dst_offsets = (u32 *) (dst + sizeof(u32)); + u32 cur_dst_offset = dst_ptr_table_len + sizeof(u32); + + u32 cur_src_offset = srctoh32(src_offsets[0]); + u32 end_src_offset = srctoh32(src_offsets[num_rooms]); + int room = 0; + + while (1) { + // Check if this is a new room and write the pointer offset if so + while (room < (num_rooms + 1) && srctoh32(src_offsets[room]) == cur_src_offset) { + dst_offsets[room] = htodst32(cur_dst_offset); + room++; + } + + if (cur_src_offset >= end_src_offset) { + break; + } + + // Write tile data + struct tile *n64tile = (struct tile *) &src[cur_src_offset]; + struct tile hosttile; + + hosttile.type = n64tile->type; + hosttile.numvertices = n64tile->numvertices; + hosttile.flags = srctodst16(n64tile->flags); + hosttile.floortype = srctodst16(n64tile->floortype); + hosttile.xmin = n64tile->xmin; + hosttile.ymin = n64tile->ymin; + hosttile.zmin = n64tile->zmin; + hosttile.xmax = n64tile->xmax; + hosttile.ymax = n64tile->ymax; + hosttile.zmax = n64tile->zmax; + hosttile.floorcol = srctodst16(n64tile->floorcol); + + memcpy(&dst[cur_dst_offset], &hosttile, sizeof(struct tile)); + + cur_dst_offset += sizeof(struct tile); + cur_src_offset += sizeof(struct tile); + + // Write tile vertices + for (int i = 0; i < hosttile.numvertices; i++) { + *(s16 *) &dst[cur_dst_offset + 0] = srctodst16(*(s16 *) &src[cur_src_offset + 0]); + *(s16 *) &dst[cur_dst_offset + 2] = srctodst16(*(s16 *) &src[cur_src_offset + 2]); + *(s16 *) &dst[cur_dst_offset + 4] = srctodst16(*(s16 *) &src[cur_src_offset + 4]); + cur_dst_offset += 6; + cur_src_offset += 6; + } + } + + return ALIGN16(cur_dst_offset); +} + +u8 *preprocessTilesFile(u8 *data, u32 size, u32 *outSize) +{ + u32 newSizeEstimated = romdataFileGetEstimatedSize(size, FT_TILES); + u8 *dst = sysMemZeroAlloc(newSizeEstimated); + + u32 newSize = convertTiles(dst, data, size); + + if (newSize > newSizeEstimated) { + sysLogPrintf(LOG_ERROR, "overflow when trying to preprocess a tiles file, size %d newsize %d", size, newSize); + exit(EXIT_FAILURE); + } + + memcpy(data, dst, newSize); + sysMemFree(dst); + + *outSize = newSize; + + return 0; +} diff --git a/port/src/preprocess.c b/port/src/preprocess/preprocess.c similarity index 72% rename from port/src/preprocess.c rename to port/src/preprocess/preprocess.c index 791008ca3..d27d398e8 100644 --- a/port/src/preprocess.c +++ b/port/src/preprocess/preprocess.c @@ -14,30 +14,7 @@ #include "romdata.h" #include "mod.h" #include "system.h" - -static inline f32 swapF32(f32 x) { *(u32 *)&x = PD_BE32(*(u32 *)&x); return x; } -static inline u32 swapU32(u32 x) { return PD_BE32(x); } -static inline s32 swapS32(s32 x) { return PD_BE32(x); } -static inline u16 swapU16(u16 x) { return PD_BE16(x); } -static inline s16 swapS16(s16 x) { return PD_BE16(x); } -static inline void *swapPtr(void **x) { return (void *)PD_BEPTR((uintptr_t)x); } -static inline struct coord swapCrd(struct coord crd) { crd.x = swapF32(crd.x); crd.y = swapF32(crd.y); crd.z = swapF32(crd.z); return crd; } -static inline u32 swapUnk(u32 x) { assert(0 && "unknown type"); return x; } - -#define PD_SWAP_VAL(x) x = _Generic((x), \ - f32: swapF32, \ - u32: swapU32, \ - s32: swapS32, \ - u16: swapU16, \ - s16: swapS16, \ - struct coord: swapCrd, \ - default: swapUnk \ -)(x) - -#define PD_SWAP_PTR(x) x = swapPtr((void *)(x)) - -#define PD_PTR_BASE(x, b) (void *)((u8 *)b + (uintptr_t)x) -#define PD_PTR_BASEOFS(x, b, d) (void *)((u8 *)b - d + (uintptr_t)x) +#include "common.h" // HACK: to prevent double-swapping stuff, flag swapped offsets in a bitmap @@ -275,77 +252,3 @@ u8* preprocessTexturesList(u8* data, u32 size, u32* outSize) } return 0; } - -void preprocessBgSection1Header(u8 *data, u32 size) -{ - u32 *header = (u32 *)data; - PD_SWAP_VAL(header[0]); // inflatedsize - PD_SWAP_VAL(header[1]); // section1size - PD_SWAP_VAL(header[2]); // primcompsize -} - -void preprocessBgSection2Header(u8 *data, u32 size) -{ - u16 *header = (u16 *)data; - PD_SWAP_VAL(header[0]); // inflatedsize - PD_SWAP_VAL(header[1]); // section2compsize -} - -void preprocessBgSection2(u8 *data, u32 size) -{ - // section2 is a texture id list - u16 *section2 = (u16 *)data; - for (s32 i = 0; i < size; ++i) { - PD_SWAP_VAL(section2[i]); - } -} - -void preprocessBgSection3Header(u8 *data, u32 size) -{ - u16 *header = (u16 *)data; - PD_SWAP_VAL(header[0]); - PD_SWAP_VAL(header[1]); -} - -void preprocessBgSection3(u8 *data, u32 size) -{ - // room bounding boxes, 6x s16 per room - s16 *bbox = (s16 *)data; - for (s32 i = 1; i < g_Vars.roomcount; ++i) { - PD_SWAP_VAL(*bbox); ++bbox; - PD_SWAP_VAL(*bbox); ++bbox; - PD_SWAP_VAL(*bbox); ++bbox; - PD_SWAP_VAL(*bbox); ++bbox; - PD_SWAP_VAL(*bbox); ++bbox; - PD_SWAP_VAL(*bbox); ++bbox; - } - - // gfxdatalen list - u16 *gfxdatalen = (u16 *)bbox; - for (s32 i = 1; i < g_Vars.roomcount; ++i) { - PD_SWAP_VAL(*gfxdatalen); ++gfxdatalen; - } -} - -void preprocessBgLights(u8 *data, u32 ofs) -{ - struct light *lbase = (void *)data; - if (!lbase) { - return; - } - - for (s32 i = 0; i < g_Vars.roomcount; ++i) { - if (g_Rooms[i].numlights) { - struct light *lit = &lbase[g_Rooms[i].lightindex]; - for (s32 j = 0; j < g_Rooms[i].numlights; ++j, ++lit) { - PD_SWAP_VAL(lit->colour); - PD_SWAP_VAL(lit->roomnum); - for (s32 k = 0; k < ARRAYCOUNT(lit->bbox); ++k) { - PD_SWAP_VAL(lit->bbox[k].x); - PD_SWAP_VAL(lit->bbox[k].y); - PD_SWAP_VAL(lit->bbox[k].z); - } - } - } - } -} diff --git a/port/src/preprocess/segaudio.c b/port/src/preprocess/segaudio.c new file mode 100644 index 000000000..2e03f2f00 --- /dev/null +++ b/port/src/preprocess/segaudio.c @@ -0,0 +1,426 @@ +#include +#include +#include + +#include "libaudio.h" + +#include "common.h" +#include "system.h" + +struct generic_adpcm_book { + s32 order; + s32 npredictors; + s16 book[128]; +}; + +struct generic_adpcm_loop { + u32 start; + u32 end; + u32 count; + s16 state[16]; +}; + +struct generic_raw_loop { + u32 start; + u32 end; + u32 count; +}; + +struct generic_envelope { + s32 attackTime; + s32 decayTime; + s32 releaseTime; + u8 attackVolume; + u8 decayVolume; +}; + +struct generic_keymap { + u8 velocityMin; + u8 velocityMax; + u8 keyMin; + u8 keyMax; + u8 keyBase; + s8 detune; +}; + +struct n64_adpcm_waveinfo { + u32 loop; // ptr to struct generic_adpcm_loop + u32 book; // ptr to struct generic_adpcm_book +}; + +struct host_adpcm_waveinfo { + uintptr_t loop; // ptr to struct generic_adpcm_loop + uintptr_t book; // ptr to struct generic_adpcm_book +}; + +struct n64_raw_waveinfo { + u32 loop; // ptr to struct generic_raw_loop +}; + +struct host_raw_waveinfo { + uintptr_t loop; // ptr to struct generic_raw_loop +}; + +struct n64_wavetable { + u32 base; + s32 len; + u8 type; + u8 flags; + union { + struct n64_adpcm_waveinfo adpcmWave; + struct n64_raw_waveinfo rawWave; + } waveInfo; +}; + +struct host_wavetable { + uintptr_t base; + s32 len; + u8 type; + u8 flags; + union { + struct host_adpcm_waveinfo adpcmWave; + struct host_raw_waveinfo rawWave; + } waveInfo; +}; + +struct n64_sound { + u32 envelope; // ptr to struct generic_envelope + u32 keyMap; // ptr to struct generic_keymap + u32 wavetable; // ptr to struct n64_wavetable + u8 samplePan; + u8 sampleVolume; + u8 flags; +}; + +struct host_sound { + uintptr_t envelope; // ptr to struct generic_envelope + uintptr_t keyMap; // ptr to struct generic_keymap + uintptr_t wavetable; // ptr to struct host_wavetable + u8 samplePan; + u8 sampleVolume; + u8 flags; +}; + +struct n64_instrument { + u8 volume; + u8 pan; + u8 priority; + u8 flags; + u8 tremType; + u8 tremRate; + u8 tremDepth; + u8 tremDelay; + u8 vibType; + u8 vibRate; + u8 vibDepth; + u8 vibDelay; + s16 bendRange; + s16 soundCount; + u32 soundArray[1]; // ptr to struct n64_sound +}; + +struct host_instrument { + u8 volume; + u8 pan; + u8 priority; + u8 flags; + u8 tremType; + u8 tremRate; + u8 tremDepth; + u8 tremDelay; + u8 vibType; + u8 vibRate; + u8 vibDepth; + u8 vibDelay; + s16 bendRange; + s16 soundCount; + uintptr_t soundArray[1]; // ptr to struct host_sound +}; + +struct n64_bank { + s16 instCount; + u8 flags; + u8 pad; + s32 sampleRate; + u32 percussion; // ptr to struct n64_instrument + u32 instArray[1]; // ptr to struct n64_instrument +}; + +struct host_bank { + s16 instCount; + u8 flags; + u8 pad; + s32 sampleRate; + uintptr_t percussion; // ptr to struct host_instrument + uintptr_t instArray[1]; // ptr to struct host_instrument +}; + +struct n64_bankfile { + s16 revision; + s16 bankCount; + u32 bankArray[1]; // ptr to struct n64_bank +}; + +struct host_bankfile { + s16 revision; + s16 bankCount; + uintptr_t bankArray[1]; // ptr to struct host_bank +}; + +// only proceeds to convert the next item if it's not already converted +#define AL_NEXT_ITEM(field, func) { \ + struct ptrmarker *marker = findPtrMarker(srcpos); \ + if (marker == NULL) { \ + field = htodst32(dstpos); \ + addMarker(srcpos, field); \ + dstpos = func(dst, dstpos, src, srcpos); \ + } else { \ + field = marker->ptr_host; } \ +} + +static int convertAudioEnvelope(u8 *dst, int dstpos, u8 *src, int srcpos) +{ + struct generic_envelope *n64_envelope = (struct generic_envelope *) &src[srcpos]; + struct generic_envelope *host_envelope = (struct generic_envelope *) &dst[dstpos]; + + dstpos += sizeof(struct generic_envelope); + + host_envelope->attackTime = srctodst32(n64_envelope->attackTime); + host_envelope->decayTime = srctodst32(n64_envelope->decayTime); + host_envelope->releaseTime = srctodst32(n64_envelope->releaseTime); + host_envelope->attackVolume = n64_envelope->attackVolume; + host_envelope->decayVolume = n64_envelope->decayVolume; + + return dstpos; +} + +static int convertAudioKeyMap(u8 *dst, int dstpos, u8 *src, int srcpos) +{ + struct generic_keymap *n64_keymap = (struct generic_keymap *) &src[srcpos]; + struct generic_keymap *host_keymap = (struct generic_keymap *) &dst[dstpos]; + + dstpos += sizeof(struct generic_keymap); + + host_keymap->velocityMin = n64_keymap->velocityMin; + host_keymap->velocityMax = n64_keymap->velocityMax; + host_keymap->keyMin = n64_keymap->keyMin; + host_keymap->keyMax = n64_keymap->keyMax; + host_keymap->keyBase = n64_keymap->keyBase; + host_keymap->detune = n64_keymap->detune; + + return dstpos; +} + +static int convertAudioAdpcmLoop(u8 *dst, int dstpos, u8 *src, int srcpos) +{ + struct generic_adpcm_loop *n64_loop = (struct generic_adpcm_loop *) &src[srcpos]; + struct generic_adpcm_loop *host_loop = (struct generic_adpcm_loop *) &dst[dstpos]; + + dstpos += sizeof(struct generic_adpcm_loop); + + host_loop->start = srctodst32(n64_loop->start); + host_loop->end = srctodst32(n64_loop->end); + host_loop->count = srctodst32(n64_loop->count); + + for (int i = 0; i < ARRAYCOUNT(host_loop->state); i++) { + host_loop->state[i] = srctodst16(n64_loop->state[i]); + } + + return dstpos; +} + +static int convertAudioAdpcmBook(u8 *dst, int dstpos, u8 *src, int srcpos) +{ + struct generic_adpcm_book *n64_book = (struct generic_adpcm_book *) &src[srcpos]; + struct generic_adpcm_book *host_book = (struct generic_adpcm_book *) &dst[dstpos]; + + dstpos += sizeof(struct generic_adpcm_book); + + host_book->order = srctodst32(n64_book->order); + host_book->npredictors = srctodst32(n64_book->npredictors); + + for (int i = 0; i < ARRAYCOUNT(host_book->book); i++) { + host_book->book[i] = srctodst16(n64_book->book[i]); + } + + return dstpos; +} + +static int convertAudioRawLoop(u8 *dst, int dstpos, u8 *src, int srcpos) +{ + struct generic_raw_loop *n64_loop = (struct generic_raw_loop *) &src[srcpos]; + struct generic_raw_loop *host_loop = (struct generic_raw_loop *) &dst[dstpos]; + + dstpos += sizeof(struct generic_raw_loop); + + host_loop->start = srctodst32(n64_loop->start); + host_loop->end = srctodst32(n64_loop->end); + host_loop->count = srctodst32(n64_loop->count); + + return dstpos; +} + +static int convertAudioWaveTable(u8 *dst, int dstpos, u8 *src, int srcpos) +{ + struct n64_wavetable *n64_wavetable = (struct n64_wavetable *) &src[srcpos]; + struct host_wavetable *host_wavetable = (struct host_wavetable *) &dst[dstpos]; + + dstpos += sizeof(struct host_wavetable); + + host_wavetable->base = srctodst32(n64_wavetable->base); + host_wavetable->len = srctodst32(n64_wavetable->len); + host_wavetable->type = n64_wavetable->type; + host_wavetable->flags = n64_wavetable->flags; + + if (host_wavetable->type == AL_ADPCM_WAVE) { + if (n64_wavetable->waveInfo.adpcmWave.loop) { + srcpos = srctoh32(n64_wavetable->waveInfo.adpcmWave.loop); + AL_NEXT_ITEM(host_wavetable->waveInfo.adpcmWave.loop, convertAudioAdpcmLoop); + } else { + host_wavetable->waveInfo.adpcmWave.loop = 0; + } + + if (n64_wavetable->waveInfo.adpcmWave.book) { + srcpos = srctoh32(n64_wavetable->waveInfo.adpcmWave.book); + AL_NEXT_ITEM(host_wavetable->waveInfo.adpcmWave.book, convertAudioAdpcmBook); + } else { + host_wavetable->waveInfo.adpcmWave.book = 0; + } + } else if (host_wavetable->type == AL_RAW16_WAVE) { + if (n64_wavetable->waveInfo.rawWave.loop) { + srcpos = srctoh32(n64_wavetable->waveInfo.rawWave.loop); + AL_NEXT_ITEM(host_wavetable->waveInfo.rawWave.loop, convertAudioRawLoop); + } else { + host_wavetable->waveInfo.rawWave.loop = 0; + } + } + + return dstpos; +} + +static int convertAudioSound(u8 *dst, int dstpos, u8 *src, int srcpos) +{ + struct n64_sound *n64_sound = (struct n64_sound *) &src[srcpos]; + struct host_sound *host_sound = (struct host_sound *) &dst[dstpos]; + + dstpos += sizeof(struct host_sound); + + if (n64_sound->envelope) { + srcpos = srctoh32(n64_sound->envelope); + AL_NEXT_ITEM(host_sound->envelope, convertAudioEnvelope); + } else { + host_sound->envelope = 0; + } + + if (n64_sound->keyMap) { + srcpos = srctoh32(n64_sound->keyMap); + AL_NEXT_ITEM(host_sound->keyMap, convertAudioKeyMap); + } else { + host_sound->keyMap = 0; + } + + if (n64_sound->wavetable) { + srcpos = srctoh32(n64_sound->wavetable); + AL_NEXT_ITEM(host_sound->wavetable, convertAudioWaveTable); + } else { + host_sound->wavetable = 0; + } + + host_sound->samplePan = n64_sound->samplePan; + host_sound->sampleVolume = n64_sound->sampleVolume; + host_sound->flags = n64_sound->flags; + + return dstpos; +} + +static int convertAudioInstrument(u8 *dst, int dstpos, u8 *src, int srcpos) +{ + struct n64_instrument *n64_instrument = (struct n64_instrument *) &src[srcpos]; + struct host_instrument *host_instrument = (struct host_instrument *) &dst[dstpos]; + int soundCount = srctoh16(n64_instrument->soundCount); + + host_instrument->volume = n64_instrument->volume; + host_instrument->pan = n64_instrument->pan; + host_instrument->priority = n64_instrument->priority; + host_instrument->flags = n64_instrument->flags; + host_instrument->tremType = n64_instrument->tremType; + host_instrument->tremRate = n64_instrument->tremRate; + host_instrument->tremDepth = n64_instrument->tremDepth; + host_instrument->tremDelay = n64_instrument->tremDelay; + host_instrument->vibType = n64_instrument->vibType; + host_instrument->vibRate = n64_instrument->vibRate; + host_instrument->vibDepth = n64_instrument->vibDepth; + host_instrument->vibDelay = n64_instrument->vibDelay; + host_instrument->bendRange = srctodst16(n64_instrument->bendRange); + host_instrument->soundCount = htodst16(soundCount); + + dstpos = dstpos + sizeof(struct host_instrument) + sizeof(uintptr_t) * (soundCount - 1); + + for (int i = 0; i < soundCount; i++) { + srcpos = srctoh32(n64_instrument->soundArray[i]); + AL_NEXT_ITEM(host_instrument->soundArray[i], convertAudioSound); + } + + return dstpos; +} + +static int convertAudioBank(u8 *dst, int dstpos, u8 *src, int srcpos) +{ + struct n64_bank *n64_bank = (struct n64_bank *) &src[srcpos]; + struct host_bank *host_bank = (struct host_bank *) &dst[dstpos]; + int instCount = srctoh16(n64_bank->instCount); + + host_bank->instCount = htodst16(instCount); + host_bank->flags = n64_bank->flags; + host_bank->pad = n64_bank->pad; + host_bank->sampleRate = srctodst32(n64_bank->sampleRate); + + dstpos = dstpos + sizeof(struct host_bank) + sizeof(uintptr_t) * (instCount - 1); + + if (n64_bank->percussion) { + srcpos = srctoh32(n64_bank->percussion); + AL_NEXT_ITEM(host_bank->percussion, convertAudioInstrument); + } else { + host_bank->percussion = 0; + } + + for (int i = 0; i < instCount; i++) { + srcpos = srctoh32(n64_bank->instArray[i]); + AL_NEXT_ITEM(host_bank->instArray[i], convertAudioInstrument); + } + + return dstpos; +} + +static int convertAudioBankFile(u8 *dst, u8 *src) +{ + struct n64_bankfile *n64_bankfile = (struct n64_bankfile *)src; + struct host_bankfile *host_bankfile = (struct host_bankfile *)dst; + int bankCount = srctoh16(n64_bankfile->bankCount); + + host_bankfile->revision = srctodst16(n64_bankfile->revision); + host_bankfile->bankCount = htodst16(bankCount); + + + u32 dstpos = sizeof(struct host_bankfile) + sizeof(uintptr_t) * (bankCount - 1); + + for (int i = 0; i < bankCount; i++) { + host_bankfile->bankArray[i] = htodst32(dstpos); + u32 srcpos = srctoh32(n64_bankfile->bankArray[i]); + dstpos = convertAudioBank(dst, dstpos, src, srcpos); + } + + return dstpos; +} + +u8 *preprocessALBankFile(u8 *src, u32 size, u32 *outSize) +{ + resetMarkers(); + u32 dstlen = size * 3; + u8 *dst = sysMemZeroAlloc(dstlen); + + *outSize = convertAudioBankFile(dst, src); + *outSize = ALIGN16(*outSize); + + return dst; +} diff --git a/port/src/preprocess/segfonts.c b/port/src/preprocess/segfonts.c new file mode 100644 index 000000000..b2f9ab1b8 --- /dev/null +++ b/port/src/preprocess/segfonts.c @@ -0,0 +1,122 @@ +#include +#include +#include +#include +#include +#include "common.h" +#include "system.h" + +struct n64fontchar { + u8 index; + s8 baseline; + u8 height; + u8 width; + s32 kerningindex; + u32 pixeldata; +}; + +struct hostfontchar { + u8 index; + s8 baseline; + u8 height; + u8 width; + s32 kerningindex; + uintptr_t pixeldata; +}; + +struct n64fontcharjpn { + u16 index; + s8 baseline; + u8 height; + u8 width; + s16 kerningindex; + u32 pixeldata; +}; + +struct hostfontcharjpn { + u16 index; + s8 baseline; + u8 height; + u8 width; + s16 kerningindex; + uintptr_t pixeldata; +}; + +struct fontdef { + const char *name; + u32 offsets[3]; + int pal_extra_chars; +}; + +u8 *preprocessFont(u8 *src, u32 srclen, u32 *outSize) +{ + int num_chars = 94; +#if VERSION == VERSION_PAL_FINAL + // PAL has more characters in these fonts + extern u8* _fonthandelgothicsmSegmentRomStart; + extern u8* _fonthandelgothicxsSegmentRomStart; + extern u8* _fonthandelgothicmdSegmentRomStart; + if (src == _fonthandelgothicsmSegmentRomStart + || src == _fonthandelgothicxsSegmentRomStart + || src == _fonthandelgothicmdSegmentRomStart) { + numchars = 135; + } +#endif + + size_t dstlen = srclen - (num_chars * sizeof(struct n64fontchar)) + (num_chars * sizeof(struct hostfontchar)) + 0x20; + u8* dst = sysMemZeroAlloc(dstlen); + + // Kerning table + s32 *src_kerning_table = (s32 *)src; + s32 *dst_kerning_table = (s32 *)dst; + + for (int i = 0; i < 13 * 13; i++) { + dst_kerning_table[i] = srctodst32(src_kerning_table[i]); + } + + u32 src_offset = ALIGN(13 * 13 * 4, sizeof(u32)); + u32 dst_offset = ALIGN(13 * 13 * 4, sizeof(uintptr_t)); + + // Character table +#if VERSION == VERSION_JPN_FINAL + struct n64fontcharjpn *src_char_table = (struct n64fontcharjpn *) &src[src_offset]; + struct hostfontcharjpn *dst_char_table = (struct hostfontcharjpn *) &dst[dst_offset]; + u32 diff = (dst_offset + num_chars * sizeof(struct hostfontcharjpn)) - (src_offset + num_chars * sizeof(struct n64fontcharjpn)); + + for (int i = 0; i < num_chars; i++) { + dst_char_table[i].index = srctodst16(src_char_table[i].index); + dst_char_table[i].baseline = src_char_table[i].baseline; + dst_char_table[i].height = src_char_table[i].height; + dst_char_table[i].width = src_char_table[i].width; + dst_char_table[i].kerningindex = srctodst16(src_char_table[i].kerningindex); + dst_char_table[i].pixeldata = src_char_table[i].pixeldata ? srctodst32(src_char_table[i].pixeldata) + diff : 0; + } + + src_offset += num_chars * sizeof(struct n64fontcharjpn); + dst_offset += num_chars * sizeof(struct hostfontcharjpn); +#else + struct n64fontchar *src_char_table = (struct n64fontchar *) &src[src_offset]; + struct hostfontchar *dst_char_table = (struct hostfontchar *) &dst[dst_offset]; + u32 diff = (dst_offset + num_chars * sizeof(struct hostfontchar)) - (src_offset + num_chars * sizeof(struct n64fontchar)); + + for (int i = 0; i < num_chars; i++) { + dst_char_table[i].index = src_char_table[i].index; + dst_char_table[i].baseline = src_char_table[i].baseline; + dst_char_table[i].height = src_char_table[i].height; + dst_char_table[i].width = src_char_table[i].width; + dst_char_table[i].kerningindex = srctodst32(src_char_table[i].kerningindex); + dst_char_table[i].pixeldata = src_char_table[i].pixeldata ? srctodst32(src_char_table[i].pixeldata) + diff : 0; + } + + src_offset += num_chars * sizeof(struct n64fontchar); + dst_offset += num_chars * sizeof(struct hostfontchar); +#endif + + // Pixel data + u32 len = srclen - src_offset; + memcpy(&dst[dst_offset], &src[src_offset], len); + + if (outSize) *outSize = ALIGN16(dst_offset + len); + + return dst; +} diff --git a/port/src/preprocess/setups_decl.h b/port/src/preprocess/setups_decl.h new file mode 100644 index 000000000..e78afd62b --- /dev/null +++ b/port/src/preprocess/setups_decl.h @@ -0,0 +1,642 @@ +#ifndef _IN_SETUP_DECL +#define _IN_SETUP_DECL + +#include "common.h" + + +struct n64_stagesetup { + u32 ptr_waypoints; + u32 ptr_waygroups; + u32 ptr_cover; + u32 ptr_intro; + u32 ptr_props; + u32 ptr_paths; + u32 ptr_ailists; + u32 ptr_padfiledata; +}; + + +struct n64_coord { + f32 x; + f32 y; + f32 z; +}; + +struct n64_defaultobj { + u16 extrascale; + u8 hidden2; + u8 type; + s16 modelnum; + s16 pad; + u32 flags; + u32 flags2; + u32 flags3; + u32 ptr_prop; + u32 ptr_model; + f32 realrot[3][3]; + u32 hidden; + union { + u32 ptr_geotilef; + u32 ptr_geoblock; + u32 ptr_geocyl; + u32 ptr_unkgeo; + }; + union { + u32 ptr_projectile; + u32 ptr_embedment; + }; + s16 damage; + s16 maxdamage; + u8 shadecol[4]; + u8 nextcol[4]; + u16 floorcol; + s8 geocount; + s8 _pad_; +}; + +struct n64_doorobj { + struct n64_defaultobj base; + f32 maxfrac; + f32 perimfrac; + f32 accel; + f32 decel; + f32 maxspeed; + u16 doorflags; + u16 doortype; + u32 keyflags; + s32 autoclosetime; + f32 frac; + f32 fracspeed; + s8 mode; + s8 glasshits; + s16 fadealpha; + s16 xludist; + s16 opadist; + struct n64_coord startpos; + f32 mtx98[3][3]; + u32 ptr_sibling; + s32 lastopen60; + s16 portalnum; + s8 soundtype; + s8 fadetime60; + s32 lastcalc60; + u8 laserfade; + u8 unusedmaybe[3]; + u8 shadeinfo1[4]; + u8 shadeinfo2[4]; + u8 actual1; + u8 actual2; + u8 extra1; + u8 extra2; +}; + +struct n64_doorscaleobj { + u32 unk00; + s32 scale; +}; + +struct n64_keyobj { + struct n64_defaultobj base; + u32 keyflags; +}; + +struct n64_alarmobj { + struct n64_defaultobj base; +}; + +struct n64_cctvobj { + struct n64_defaultobj base; + + s16 lookatpadnum; + s16 toleft; + //Mtxf camrotm; + f32 m[4][4]; + f32 yzero; + f32 yrot; + f32 yleft; + f32 yright; + f32 yspeed; + f32 ymaxspeed; + s32 seebondtime60; + f32 maxdist; + f32 xzero; +}; + +struct n64_ammocrateobj { + struct n64_defaultobj base; + s32 ammotype; +}; + +struct n64_gset { + u8 weaponnum; + u8 unk0639; + u8 unk063a; + u8 weaponfunc; +}; + +struct n64_weaponobj { + struct n64_defaultobj base; + + union { + struct n64_gset gset; + struct { + u8 weaponnum; + s8 unk5d; + s8 unk5e; + u8 gunfunc; + }; + }; + + s8 fadeouttimer60; + s8 dualweaponnum; + + union { + s16 timer240; + s16 team; + }; + + u32 ptr_dualweapon; +}; + +struct n64_packedchr { + s16 chrindex; + s8 unk02; + s8 typenum; + u32 spawnflags; + s16 chrnum; + u16 padnum; + u8 bodynum; + s8 headnum; + u16 ailistnum; + u16 padpreset; + u16 chrpreset; + u16 hearscale; + u16 viewdist; + u32 flags; + u32 flags2; + u8 team; + u8 squadron; + s16 chair; + u32 convtalk; + u8 tude; + u8 naturalanim; + u8 yvisang; + u8 teamscandist; +}; + +struct n64_tvscreen { + u32 ptr_cmdlist; + u16 offset; + s16 pause60; + u32 ptr_tconfig; + f32 rot; + f32 xscale; + f32 xscalefrac; + f32 xscaleinc; + f32 xscaleold; + f32 xscalenew; + f32 yscale; + f32 yscalefrac; + f32 yscaleinc; + f32 yscaleold; + f32 yscalenew; + f32 xmid; + f32 xmidfrac; + f32 xmidinc; + f32 xmidold; + f32 xmidnew; + f32 ymid; + f32 ymidfrac; + f32 ymidinc; + f32 ymidold; + f32 ymidnew; + u8 red; + u8 redold; + u8 rednew; + u8 green; + u8 greenold; + u8 greennew; + u8 blue; + u8 blueold; + u8 bluenew; + u8 alpha; + u8 alphaold; + u8 alphanew; + f32 colfrac; + f32 colinc; +}; + +struct n64_singlemonitorobj { + struct n64_defaultobj base; + struct n64_tvscreen screen; + s16 owneroffset; + s8 ownerpart; + u8 imagenum; +}; + +struct n64_multimonitorobj { + struct n64_defaultobj base; + struct n64_tvscreen screens[4]; + u8 imagenums[4]; +}; + +struct n64_hangingmonitorsobj { + struct n64_defaultobj base; +}; + +struct n64_autogunobj { + struct n64_defaultobj base; + s16 targetpad; + s8 firing; + u8 firecount; + f32 yzero; + f32 ymaxleft; + f32 ymaxright; + f32 yrot; + f32 yspeed; + f32 xzero; + f32 xrot; + f32 xspeed; + f32 maxspeed; + f32 aimdist; + f32 barrelspeed; + f32 barrelrot; + s32 lastseebond60; + s32 lastaimbond60; + s32 allowsoundframe; + u32 ptr_beam; + f32 shotbondsum; + u32 ptr_target; + u8 targetteam; + u8 ammoquantity; + s16 nextchrtest; +}; + +struct n64_linkgunsobj { + u32 unk00; + s16 offset1; + s16 offset2; +}; + +struct n64_debrisobj { + struct n64_defaultobj base; +}; + +struct n64_hatobj { + struct n64_defaultobj base; +}; + +struct n64_grenadeprobobj { // objtype 0x12 + u32 unk00; + s16 chrnum; + u16 probability; +}; + +struct n64_linkliftdoorobj { + u32 unk00; + u32 ptr_door; + u32 ptr_lift; + u32 ptr_next; + s32 stopnum; +}; + +struct n64_multiammocrateslot { + u16 modelnum; + u16 quantity; +}; + +struct n64_multiammocrateobj { + struct n64_defaultobj base; + struct n64_multiammocrateslot slots[19]; +}; + +struct n64_shieldobj { + struct n64_defaultobj base; + f32 initialamount; + f32 amount; + u32 unk64; +}; + +struct n64_tag { + u32 identifier; + u16 tagnum; + s16 cmdoffset; + u32 ptr_next; + u32 ptr_obj; +}; + +struct n64_objective { + u32 unk00; + s32 index; + u32 text; + u16 unk0c; + u8 flags; + s8 difficulties; +}; + +struct n64_stdobjective { + u32 cmd; +}; + +struct n64_objectivecmd { + u8 cmd0[4]; + u32 cmd1; +}; + +struct n64_briefingobj { + u32 unk00; + u32 type; + u32 text; + u32 ptr_next; +}; + +struct n64_padlockeddoorobj { + u32 unk00; + u32 ptr_door; + u32 ptr_lock; + u32 ptr_next; +}; + +struct n64_truckobj { + struct n64_defaultobj base; + u32 ptr_ailist; + u16 aioffset; + s16 aireturnlist; + f32 speed; + f32 wheelxrot; + f32 wheelyrot; + f32 speedaim; + f32 speedtime60; + f32 turnrot60; + f32 roty; + u32 ptr_path; + s32 nextstep; +}; + +struct n64_tankobj { + u8 _pad_[128]; +}; + +struct n64_heliobj { + struct n64_defaultobj base; + u32 ptr_ailist; + u16 aioffset; + s16 aireturnlist; + f32 rotoryrot; + f32 rotoryspeed; + f32 rotoryspeedaim; + f32 rotoryspeedtime; + f32 speed; + f32 speedaim; + f32 speedtime60; + f32 yrot; + u32 ptr_path; + s32 nextstep; +}; + +struct n64_glassobj { + struct n64_defaultobj base; + s16 portalnum; + s16 _pad_; +}; + +struct n64_safeobj { + struct n64_defaultobj base; +}; + +struct n64_safeitemobj { + u32 unk00; + u32 ptr_item; + u32 ptr_safe; + u32 ptr_door; + u32 ptr_next; +}; + +struct n64_cameraposobj { + s32 type; + f32 x; + f32 y; + f32 z; + f32 theta; + f32 verta; + s32 pad; +}; + +struct n64_tintedglassobj { + struct n64_defaultobj base; + s16 xludist; + s16 opadist; + s16 opacity; + s16 portalnum; + f32 unk64; +}; + +struct n64_liftobj { + struct n64_defaultobj base; + s16 pads[4]; + u32 ptr_doors[4]; + f32 dist; + f32 speed; + f32 accel; + f32 maxspeed; + s8 soundtype; + s8 levelcur; + s8 levelaim; + s8 _pad_; + struct n64_coord prevpos; +}; + +struct n64_linksceneryobj { + u32 unk00; + u32 ptr_trigger; + u32 ptr_unexp; + u32 ptr_exp; + u32 ptr_next; +}; + +struct n64_blockedpathobj { + u32 unk00; + u32 ptr_blocker; + s16 waypoint1; + s16 waypoint2; + u32 ptr_next; +}; + +struct n64_hov { + u8 type; + u8 flags; + s16 _pad_; + f32 bobycur; + f32 bobytarget; + f32 bobyspeed; + f32 yrot; + f32 bobpitchcur; + f32 bobpitchtarget; + f32 bobpitchspeed; + f32 bobrollcur; + f32 bobrolltarget; + f32 bobrollspeed; + f32 groundpitch; + f32 y; + f32 ground; + s32 prevframe60; + s32 prevgroundframe60; +}; + +struct n64_hoverbikeobj { + struct n64_defaultobj base; + struct n64_hov hov; + f32 speed[2]; + f32 prevpos[2]; + f32 w; + f32 rels[2]; + f32 exreal; + f32 ezreal; + f32 ezreal2; + f32 leanspeed; + f32 leandiff; + s32 maxspeedtime240; + f32 speedabs[2]; + f32 speedrel[2]; +}; + +struct n64_hoverpropobj { + struct n64_defaultobj base; + struct n64_hov hov; +}; + +struct n64_fanobj { + struct n64_defaultobj base; + f32 yrot; + f32 yrotprev; + f32 ymaxspeed; + f32 yspeed; + f32 yaccel; + s8 on; + u8 _pad_[3]; +}; + +struct n64_hovercarobj { + struct n64_defaultobj base; + u32 ptr_ailist; + u16 aioffset; + s16 aireturnlist; + f32 speed; + f32 speedaim; + f32 speedtime60; + f32 turnyspeed60; + f32 turnxspeed60; + f32 turnrot60; + f32 roty; + f32 rotx; + f32 rotz; + u32 ptr_path; + s32 nextstep; + s16 status; + s16 dead; + s16 deadtimer60; + s16 sparkstimer60; +}; + +struct n64_chopperobj { + struct n64_defaultobj base; + u32 ptr_ailist; + u16 aioffset; + s16 aireturnlist; + union { + struct { + f32 speed; + f32 speedaim; + f32 speedtime60; + }; + struct n64_coord fall; + }; + f32 turnyspeed60; + f32 turnxspeed60; + f32 turnrot60; + f32 roty; + f32 rotx; + f32 rotz; + u32 ptr_path; + s32 nextstep;// + s16 weaponsarmed; + s16 ontarget; + s16 target; + u8 attackmode; + u8 cw; + f32 vx; + f32 vy; + f32 vz; + f32 power; + f32 otx; + f32 oty; + f32 otz; + f32 bob; + f32 bobstrength; + s32 targetvisible; + s32 timer60; + s32 patroltimer60; + f32 gunturnyspeed60; + f32 gunturnxspeed60; + f32 gunroty; + f32 gunrotx; + f32 barrelrotspeed; + f32 barrelrot; + u32 ptr_fireslotthing; + s32 dead; +}; + +struct n64_escalatorobj { + struct n64_defaultobj base; + s32 frame; + struct n64_coord prevpos; +}; + +struct n64_textoverride { + u32 unk00; + s32 objoffset; + s32 weapon; + u32 obtaintext; + u32 ownertext; + u32 inventorytext; + u32 inventory2text; + u32 pickuptext; + u32 ptr_next; + u32 ptr_obj; +}; + +struct n64_criteria_roomentered { + u32 unk00; + u32 pad; + u32 status; + u32 ptr_next; +}; + +struct n64_criteria_throwinroom { + u32 unk00; + u32 unk04; + u32 pad; + u32 status; + u32 ptr_next; +}; + +struct n64_criteria_holograph { + u32 unk00; + u32 obj; + u32 status; + u32 ptr_next; +}; + +struct n64_ailist { + u32 ptr_list; + s32 id; +}; + +struct n64_path { + u32 ptr_pads; + u8 id; + u8 flags; + u16 len; +}; + +#endif \ No newline at end of file diff --git a/port/src/preprocess/util_gbi.c b/port/src/preprocess/util_gbi.c new file mode 100644 index 000000000..75b4a621a --- /dev/null +++ b/port/src/preprocess/util_gbi.c @@ -0,0 +1,209 @@ +#include +#include +#include +#include "common.h" +#include "gbi.h" + +#ifdef FORCE_BE32 +#define HOST_DWORDS_PER_CMD 1 +#elif UINTPTR_MAX == 0xFFFFFFFFFFFFFFFFu +#define HOST_DWORDS_PER_CMD 2 +#else +#define HOST_DWORDS_PER_CMD 1 +#endif + +struct vtx { + s16 x; + s16 y; + s16 z; + u8 flags; + u8 colour; + s16 s; + s16 t; +}; + +struct texaddr { + u32 src; + u32 dst; +}; + +u32 m_Segments[16]; +u32 m_SrcVtxOffset; +u32 m_DstVtxOffset; + +struct texaddr m_TexAddrs[64]; +int m_NumTexAddr; + +void gbiReset(void) +{ + for (int i = 0; i < ARRAYCOUNT(m_Segments); i++) { + m_Segments[i] = 0; + } + + m_SrcVtxOffset = 0; + m_DstVtxOffset = 0; + m_NumTexAddr = 0; +} + +void gbiSetSegment(int segment, u32 offset) +{ + m_Segments[segment] = offset & 0x00ffffff; +} + +void gbiSetVtx(u32 src_offset, u32 dst_offset) +{ + m_SrcVtxOffset = src_offset & 0x00ffffff; + m_DstVtxOffset = dst_offset & 0x00ffffff; +} + +void gbiAddTexAddr(u32 src_offset, u32 dst_offset) +{ + m_TexAddrs[m_NumTexAddr].src = src_offset & 0x00ffffff; + m_TexAddrs[m_NumTexAddr++].dst = dst_offset & 0x00ffffff; +} + +u32 gbiFindTexAddr(u32 src_offset) +{ + for (int i = 0; i < m_NumTexAddr; i++) { + if (m_TexAddrs[i].src == src_offset) + return m_TexAddrs[i].dst; + } + + return 0; +} + +void gbiConvertVtx(u8 *dst, u32 offset, int count) +{ + if (!offset) return; + struct vtx* vtxs = (struct vtx*)(dst + offset); + + for (int i = 0; i < count; i++) { + struct vtx* vtx = &vtxs[i]; + + vtx->x = srctodst16(vtx->x); + vtx->y = srctodst16(vtx->y); + vtx->z = srctodst16(vtx->z); + vtx->s = srctodst16(vtx->s); + vtx->t = srctodst16(vtx->t); + } +} + +#define CMD_IS_VTX(cmd) ((cmd & 0xff00000000000000) == 0x0400000000000000) +#define CMD_IS_DL(cmd) ((cmd & 0xff00000000000000) == 0x0600000000000000) +#define CMD_IS_COL(cmd) ((cmd & 0xff00000000000000) == 0x0700000000000000) +#define CMD_IS_ENDDL(cmd) ((cmd & 0xff00000000000000) == 0xb800000000000000) +#define CMD_IS_MOVEWORD(cmd) ((cmd & 0xff00000000000000) == 0xbc00000000000000) +#define CMD_IS_MOVEMEM(cmd) ((cmd & 0xff00000000000000) == 0x0300000000000000) +#define CMD_IS_MTX(cmd) ((cmd & 0xff00000000000000) == 0x0100000000000000) +#define CMD_IS_SETTIMG(cmd) ((cmd & 0xff00000000000000) == 0xfd00000000000000) +#define CMD_IS_SETZIMG(cmd) ((cmd & 0xff00000000000000) == 0xfe00000000000000) +#define CMD_IS_SETCIMG(cmd) ((cmd & 0xff00000000000000) == 0xff00000000000000) + +#define CMD_HAS_ADDR(cmd) CMD_IS_VTX(cmd) \ + || CMD_IS_COL(cmd) \ + || CMD_IS_MOVEWORD(cmd) \ + || CMD_IS_SETTIMG(cmd) + + +#define CMD_IS_SEGMENTED(cmd) ( CMD_IS_MOVEMEM(cmd) \ + || CMD_IS_MTX(cmd) \ + || CMD_IS_VTX(cmd) \ + || CMD_IS_COL(cmd) \ + || CMD_IS_DL(cmd) \ + || CMD_IS_SETTIMG(cmd) \ + || CMD_IS_SETCIMG(cmd) \ + || CMD_IS_SETZIMG(cmd)) + +/** + * Segment 5 is the start of the model file. The data in these files shifts + * depending on the pointer size, so this function adjusts the offset accordingly. + */ +static u64 gbiRewriteAddr(u64 cmd, u8 opcode) +{ + u8 segment = (cmd & 0x0f000000) >> 24; + u32 offset = cmd & 0x00ffffff; + + if (segment == 5) { + if (opcode == 0xfd) { + offset = gbiFindTexAddr(offset); + } + else { + if (offset < m_SrcVtxOffset) { + printf("Tried to load data from offset 0x%x but segment starts at 0x%x\n", offset, m_SrcVtxOffset); + exit(EXIT_FAILURE); + } + + offset = offset - m_SrcVtxOffset + m_DstVtxOffset; + } + } + + return (cmd & 0xffffffffff000000) | offset; +} + +void gbiGdlRewriteAddrs(u8 *dst, u32 offset) +{ + if (!offset) return; + + u64 *cmds = (u64 *)(dst + (offset & 0x00ffffff)); + if (!cmds) return; + + u64 cmd; + + do { + cmd = *cmds; + Gfx* gfxcmd = cmds; + int idx = 0; + u8 opcode = (cmd >> 24) & 0xff; + +#if HOST_DWORDS_PER_CMD == 2 + idx = 1; + opcode = (cmd >> 24) & 0xff; +#endif + cmd = (u64)opcode << 56; + + if (CMD_HAS_ADDR(cmd)) { + cmds[idx] = gbiRewriteAddr(cmds[idx], opcode); + } + + if (CMD_IS_SEGMENTED(cmd)) { + gfxcmd->words.w1 |= 1; + } + + cmds += HOST_DWORDS_PER_CMD; + } while (!CMD_IS_ENDDL(cmd)); +} + +u32 gbiConvertGdl(u8 *dst, u32 dstpos, u8 *src, u32 srcpos, int segment_cmds) +{ + dstpos = ALIGN8(dstpos); + + u64 *n64_cmd = (u64*)&src[srcpos]; + u64 *host_cmd = (u64*)&dst[dstpos]; + u64 cmd; + + do { + cmd = srctoh64(*n64_cmd); + +#if HOST_DWORDS_PER_CMD == 2 + host_cmd[0] = htodst64((cmd & 0xffffffff00000000) >> 32); + host_cmd[1] = htodst64(cmd & 0xffffffff); + + if (segment_cmds && CMD_IS_SEGMENTED(cmd)) { + host_cmd[1] |= 1; + } +#else + host_cmd[0] = (cmd >> 32) | ((cmd & 0xffffffff) << 32); + + if (segment_cmds && CMD_IS_SEGMENTED(cmd)) { + Gfx* gfxcmd = (Gfx*)host_cmd; + gfxcmd->words.w1 |= 1; + } +#endif + + dstpos += sizeof(*host_cmd) * HOST_DWORDS_PER_CMD; + host_cmd += HOST_DWORDS_PER_CMD; + n64_cmd++; + } while (!CMD_IS_ENDDL(cmd)); + + return dstpos; +}