mirror of
https://github.com/perfect-dark-pc-port/perfect_dark.git
synced 2026-10-23 15:52:41 +02:00
portx64: added pd-extract source
This commit is contained in:
1 parent
7c6508af28
commit
3242105ef8
17 files changed
+3557
No files matched your search
@@ -0,0 +1,71 @@
|
||||
#ifndef _COMMON_H
|
||||
#define _COMMON_H
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define srctoh16(value) be16toh(value)
|
||||
#define srctoh32(value) be32toh(value)
|
||||
#define srctoh64(value) be64toh(value)
|
||||
|
||||
#ifdef FORCE_BE32
|
||||
#define htodst16(value) htobe16(value)
|
||||
#define htodst32(value) htobe32(value)
|
||||
#define htodst64(value) htobe64(value)
|
||||
#define dsttoh16(value) be16toh(value)
|
||||
#define dsttoh32(value) be32toh(value)
|
||||
#define dsttoh64(value) be64toh(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 uint32_t
|
||||
#endif
|
||||
|
||||
enum romversion {
|
||||
ROMVERSION_NTSC10,
|
||||
ROMVERSION_NTSCFINAL,
|
||||
ROMVERSION_PALFINAL,
|
||||
ROMVERSION_JPNFINAL,
|
||||
ROMVERSION_NTSCBETA,
|
||||
ROMVERSION_PALBETA,
|
||||
ROMVERSION_UNKNOWN,
|
||||
};
|
||||
|
||||
extern uint8_t *g_Rom;
|
||||
extern enum romversion g_RomVersion;
|
||||
extern char g_OutPath[1024];
|
||||
|
||||
typedef uint32_t n64ptr_t;
|
||||
|
||||
#define ALIGN(val, size) ((val + (size - 1)) & ~(size - 1))
|
||||
#define ALIGN16(val) ((val + 0xf) & ~0xf)
|
||||
#define ALIGN8(val) ((val + 0x7) & ~0x7)
|
||||
#define ALIGN4(val) ((val + 0x3) & ~0x3)
|
||||
|
||||
#define ARRAYCOUNT(arr) (int) (sizeof(arr) / sizeof(arr[0]))
|
||||
|
||||
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||
|
||||
FILE *openfile(char *filename);
|
||||
size_t rzip_get_infsize(uint8_t *src);
|
||||
int rzip_inflate(uint8_t *dst, size_t dstlen, uint8_t *src, size_t srclen);
|
||||
int rzip_deflate(uint8_t *dst, size_t *dstlen, uint8_t *src, size_t srclen);
|
||||
|
||||
void gbi_reset(void);
|
||||
void gbi_set_segment(int segment, uint32_t offset);
|
||||
void gbi_set_vtx(uint32_t src_offset, uint32_t dst_offset);
|
||||
uint32_t gbi_convert_gdl(uint8_t *dst, uint32_t dstpos, uint8_t *src, uint32_t srcpos);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,77 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "common.h"
|
||||
|
||||
struct animtableentry {
|
||||
uint16_t numframes;
|
||||
uint16_t bytesperframe;
|
||||
uint32_t data;
|
||||
uint16_t headerlen;
|
||||
uint8_t framelen;
|
||||
uint8_t flags;
|
||||
};
|
||||
|
||||
static void extract_anims_data(uint32_t romoffset, size_t len)
|
||||
{
|
||||
char outfilename[1024];
|
||||
sprintf(outfilename, "%s/anims_data.bin", g_OutPath);
|
||||
|
||||
FILE *fp = openfile(outfilename);
|
||||
fwrite(&g_Rom[romoffset], len, 1, fp);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
static void extract_anims_table(uint32_t romoffset)
|
||||
{
|
||||
int num_anims = srctoh32(*(uint32_t *) &g_Rom[romoffset]);
|
||||
struct animtableentry *srcanims = (struct animtableentry *) &g_Rom[romoffset + 4];
|
||||
|
||||
size_t dstlen = ALIGN16(4 + num_anims * sizeof(struct animtableentry));
|
||||
uint8_t *dst = calloc(1, dstlen);
|
||||
*(uint32_t *) dst = htodst32(num_anims);
|
||||
struct animtableentry *dstanims = (struct animtableentry *) (dst + 4);
|
||||
|
||||
for (int i = 0; i < num_anims; i++) {
|
||||
dstanims[i].numframes = srctodst16(srcanims[i].numframes);
|
||||
dstanims[i].bytesperframe = srctodst16(srcanims[i].bytesperframe);
|
||||
dstanims[i].data = srctodst32(srcanims[i].data);
|
||||
dstanims[i].headerlen = srctodst16(srcanims[i].headerlen);
|
||||
dstanims[i].framelen = srcanims[i].framelen;
|
||||
dstanims[i].flags = srcanims[i].flags;
|
||||
}
|
||||
|
||||
char outfilename[1024];
|
||||
sprintf(outfilename, "%s/anims_table.bin", g_OutPath);
|
||||
|
||||
FILE *fp = openfile(outfilename);
|
||||
fwrite(dst, dstlen, 1, fp);
|
||||
fclose(fp);
|
||||
|
||||
free(dst);
|
||||
}
|
||||
|
||||
void extract_anims(void)
|
||||
{
|
||||
uint32_t table_offset = 0;
|
||||
uint32_t data_offset = 0;
|
||||
|
||||
switch (g_RomVersion) {
|
||||
case ROMVERSION_NTSC10:
|
||||
case ROMVERSION_NTSCFINAL:
|
||||
data_offset = 0x1a15c0;
|
||||
table_offset = 0x7cd1a0;
|
||||
break;
|
||||
case ROMVERSION_PALFINAL:
|
||||
data_offset = 0x18cdc0;
|
||||
table_offset = 0x7b89a0;
|
||||
break;
|
||||
case ROMVERSION_JPNFINAL:
|
||||
data_offset = 0x190c50;
|
||||
table_offset = 0x7bc830;
|
||||
break;
|
||||
}
|
||||
|
||||
extract_anims_data(data_offset, table_offset - data_offset);
|
||||
extract_anims_table(table_offset);
|
||||
}
|
||||
@@ -0,0 +1,485 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "common.h"
|
||||
|
||||
enum {
|
||||
AL_ADPCM_WAVE = 0,
|
||||
AL_RAW16_WAVE
|
||||
};
|
||||
|
||||
struct generic_adpcm_book {
|
||||
int32_t order;
|
||||
int32_t npredictors;
|
||||
int16_t book[128];
|
||||
};
|
||||
|
||||
struct generic_adpcm_loop {
|
||||
uint32_t start;
|
||||
uint32_t end;
|
||||
uint32_t count;
|
||||
int16_t state[16];
|
||||
};
|
||||
|
||||
struct generic_raw_loop {
|
||||
uint32_t start;
|
||||
uint32_t end;
|
||||
uint32_t count;
|
||||
};
|
||||
|
||||
struct generic_envelope {
|
||||
int32_t attackTime;
|
||||
int32_t decayTime;
|
||||
int32_t releaseTime;
|
||||
uint8_t attackVolume;
|
||||
uint8_t decayVolume;
|
||||
};
|
||||
|
||||
struct generic_keymap {
|
||||
uint8_t velocityMin;
|
||||
uint8_t velocityMax;
|
||||
uint8_t keyMin;
|
||||
uint8_t keyMax;
|
||||
uint8_t keyBase;
|
||||
int8_t detune;
|
||||
};
|
||||
|
||||
struct n64_adpcm_waveinfo {
|
||||
uint32_t loop; // ptr to struct generic_adpcm_loop
|
||||
uint32_t 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 {
|
||||
uint32_t loop; // ptr to struct generic_raw_loop
|
||||
};
|
||||
|
||||
struct host_raw_waveinfo {
|
||||
uintptr_t loop; // ptr to struct generic_raw_loop
|
||||
};
|
||||
|
||||
struct n64_wavetable {
|
||||
uint32_t base;
|
||||
int32_t len;
|
||||
uint8_t type;
|
||||
uint8_t flags;
|
||||
union {
|
||||
struct n64_adpcm_waveinfo adpcmWave;
|
||||
struct n64_raw_waveinfo rawWave;
|
||||
} waveInfo;
|
||||
};
|
||||
|
||||
struct host_wavetable {
|
||||
uintptr_t base;
|
||||
int32_t len;
|
||||
uint8_t type;
|
||||
uint8_t flags;
|
||||
union {
|
||||
struct host_adpcm_waveinfo adpcmWave;
|
||||
struct host_raw_waveinfo rawWave;
|
||||
} waveInfo;
|
||||
};
|
||||
|
||||
struct n64_sound {
|
||||
uint32_t envelope; // ptr to struct generic_envelope
|
||||
uint32_t keyMap; // ptr to struct generic_keymap
|
||||
uint32_t wavetable; // ptr to struct n64_wavetable
|
||||
uint8_t samplePan;
|
||||
uint8_t sampleVolume;
|
||||
uint8_t 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
|
||||
uint8_t samplePan;
|
||||
uint8_t sampleVolume;
|
||||
uint8_t flags;
|
||||
};
|
||||
|
||||
struct n64_instrument {
|
||||
uint8_t volume;
|
||||
uint8_t pan;
|
||||
uint8_t priority;
|
||||
uint8_t flags;
|
||||
uint8_t tremType;
|
||||
uint8_t tremRate;
|
||||
uint8_t tremDepth;
|
||||
uint8_t tremDelay;
|
||||
uint8_t vibType;
|
||||
uint8_t vibRate;
|
||||
uint8_t vibDepth;
|
||||
uint8_t vibDelay;
|
||||
int16_t bendRange;
|
||||
int16_t soundCount;
|
||||
uint32_t soundArray[1]; // ptr to struct n64_sound
|
||||
};
|
||||
|
||||
struct host_instrument {
|
||||
uint8_t volume;
|
||||
uint8_t pan;
|
||||
uint8_t priority;
|
||||
uint8_t flags;
|
||||
uint8_t tremType;
|
||||
uint8_t tremRate;
|
||||
uint8_t tremDepth;
|
||||
uint8_t tremDelay;
|
||||
uint8_t vibType;
|
||||
uint8_t vibRate;
|
||||
uint8_t vibDepth;
|
||||
uint8_t vibDelay;
|
||||
int16_t bendRange;
|
||||
int16_t soundCount;
|
||||
uintptr_t soundArray[1]; // ptr to struct host_sound
|
||||
};
|
||||
|
||||
struct n64_bank {
|
||||
int16_t instCount;
|
||||
uint8_t flags;
|
||||
uint8_t pad;
|
||||
int32_t sampleRate;
|
||||
uint32_t percussion; // ptr to struct n64_instrument
|
||||
uint32_t instArray[1]; // ptr to struct n64_instrument
|
||||
};
|
||||
|
||||
struct host_bank {
|
||||
int16_t instCount;
|
||||
uint8_t flags;
|
||||
uint8_t pad;
|
||||
int32_t sampleRate;
|
||||
uintptr_t percussion; // ptr to struct host_instrument
|
||||
uintptr_t instArray[1]; // ptr to struct host_instrument
|
||||
};
|
||||
|
||||
struct n64_bankfile {
|
||||
int16_t revision;
|
||||
int16_t bankCount;
|
||||
uint32_t bankArray[1]; // ptr to struct n64_bank
|
||||
};
|
||||
|
||||
struct host_bankfile {
|
||||
int16_t revision;
|
||||
int16_t bankCount;
|
||||
uintptr_t bankArray[1]; // ptr to struct host_bank
|
||||
};
|
||||
|
||||
static int convert_audio_envelope(uint8_t *dst, int dstpos, uint8_t *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 convert_audio_keymap(uint8_t *dst, int dstpos, uint8_t *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 convert_audio_adpcm_loop(uint8_t *dst, int dstpos, uint8_t *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 convert_audio_adpcm_book(uint8_t *dst, int dstpos, uint8_t *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 convert_audio_raw_loop(uint8_t *dst, int dstpos, uint8_t *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 convert_audio_wavetable(uint8_t *dst, int dstpos, uint8_t *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) {
|
||||
host_wavetable->waveInfo.adpcmWave.loop = htodst32(dstpos);
|
||||
srcpos = srctoh32(n64_wavetable->waveInfo.adpcmWave.loop);
|
||||
dstpos = convert_audio_adpcm_loop(dst, dstpos, src, srcpos);
|
||||
} else {
|
||||
host_wavetable->waveInfo.adpcmWave.loop = 0;
|
||||
}
|
||||
|
||||
if (n64_wavetable->waveInfo.adpcmWave.book) {
|
||||
host_wavetable->waveInfo.adpcmWave.book = htodst32(dstpos);
|
||||
srcpos = srctoh32(n64_wavetable->waveInfo.adpcmWave.book);
|
||||
dstpos = convert_audio_adpcm_book(dst, dstpos, src, srcpos);
|
||||
} else {
|
||||
host_wavetable->waveInfo.adpcmWave.book = 0;
|
||||
}
|
||||
} else if (host_wavetable->type == AL_RAW16_WAVE) {
|
||||
if (n64_wavetable->waveInfo.rawWave.loop) {
|
||||
host_wavetable->waveInfo.rawWave.loop = htodst32(dstpos);
|
||||
srcpos = srctoh32(n64_wavetable->waveInfo.rawWave.loop);
|
||||
dstpos = convert_audio_raw_loop(dst, dstpos, src, srcpos);
|
||||
} else {
|
||||
host_wavetable->waveInfo.rawWave.loop = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return dstpos;
|
||||
}
|
||||
|
||||
static int convert_audio_sound(uint8_t *dst, int dstpos, uint8_t *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) {
|
||||
host_sound->envelope = htodst32(dstpos);
|
||||
srcpos = srctoh32(n64_sound->envelope);
|
||||
dstpos = convert_audio_envelope(dst, dstpos, src, srcpos);
|
||||
} else {
|
||||
host_sound->envelope = 0;
|
||||
}
|
||||
|
||||
if (n64_sound->keyMap) {
|
||||
host_sound->keyMap = htodst32(dstpos);
|
||||
srcpos = srctoh32(n64_sound->keyMap);
|
||||
dstpos = convert_audio_keymap(dst, dstpos, src, srcpos);
|
||||
} else {
|
||||
host_sound->keyMap = 0;
|
||||
}
|
||||
|
||||
if (n64_sound->wavetable) {
|
||||
host_sound->wavetable = htodst32(dstpos);
|
||||
srcpos = srctoh32(n64_sound->wavetable);
|
||||
dstpos = convert_audio_wavetable(dst, dstpos, src, srcpos);
|
||||
} 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 convert_audio_instrument(uint8_t *dst, int dstpos, uint8_t *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++) {
|
||||
host_instrument->soundArray[i] = htodst32(dstpos);
|
||||
srcpos = srctoh32(n64_instrument->soundArray[i]);
|
||||
dstpos = convert_audio_sound(dst, dstpos, src, srcpos);
|
||||
}
|
||||
|
||||
return dstpos;
|
||||
}
|
||||
|
||||
static int convert_audio_bank(uint8_t *dst, int dstpos, uint8_t *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) {
|
||||
host_bank->percussion = htodst32(dstpos);
|
||||
srcpos = srctoh32(n64_bank->percussion);
|
||||
dstpos = convert_audio_instrument(dst, dstpos, src, srcpos);
|
||||
} else {
|
||||
host_bank->percussion = 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < instCount; i++) {
|
||||
host_bank->instArray[i] = htodst32(dstpos);
|
||||
srcpos = srctoh32(n64_bank->instArray[i]);
|
||||
dstpos = convert_audio_instrument(dst, dstpos, src, srcpos);
|
||||
}
|
||||
|
||||
return dstpos;
|
||||
}
|
||||
|
||||
static int convert_audio_bankfile(uint8_t *dst, int dstpos, uint8_t *src, int srcpos)
|
||||
{
|
||||
struct n64_bankfile *n64_bankfile = (struct n64_bankfile *) &src[srcpos];
|
||||
struct host_bankfile *host_bankfile = (struct host_bankfile *) &dst[dstpos];
|
||||
int bankCount = srctoh16(n64_bankfile->bankCount);
|
||||
|
||||
host_bankfile->revision = srctodst16(n64_bankfile->revision);
|
||||
host_bankfile->bankCount = htodst16(bankCount);
|
||||
|
||||
dstpos = dstpos + sizeof(struct host_bankfile) + sizeof(uintptr_t) * (bankCount - 1);
|
||||
|
||||
for (int i = 0; i < bankCount; i++) {
|
||||
host_bankfile->bankArray[i] = htodst32(dstpos);
|
||||
srcpos = srctoh32(n64_bankfile->bankArray[i]);
|
||||
dstpos = convert_audio_bank(dst, dstpos, src, srcpos);
|
||||
}
|
||||
|
||||
return dstpos;
|
||||
}
|
||||
|
||||
static void extract_audio_ctl(const char *filename, uint32_t romoffset, size_t srclen)
|
||||
{
|
||||
size_t dstlen = srclen * 4;
|
||||
uint8_t *src = &g_Rom[romoffset];
|
||||
uint8_t *dst = calloc(1, dstlen);
|
||||
int dstpos = 0;
|
||||
|
||||
dstpos = convert_audio_bankfile(dst, dstpos, src, 0);
|
||||
|
||||
char outfilename[1024];
|
||||
sprintf(outfilename, "%s/%s.ctl", g_OutPath, filename);
|
||||
|
||||
FILE *fp = openfile(outfilename);
|
||||
fwrite(dst, ALIGN16(dstpos), 1, fp);
|
||||
fclose(fp);
|
||||
|
||||
free(dst);
|
||||
}
|
||||
|
||||
static void extract_audio_tbl(const char *filename, uint32_t romoffset, size_t len)
|
||||
{
|
||||
char outfilename[1024];
|
||||
sprintf(outfilename, "%s/%s.tbl", g_OutPath, filename);
|
||||
|
||||
FILE *fp = openfile(outfilename);
|
||||
fwrite(&g_Rom[romoffset], len, 1, fp);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
void extract_audio(void)
|
||||
{
|
||||
uint32_t sfx_ctl = 0;
|
||||
uint32_t sfx_tbl = 0;
|
||||
uint32_t sfx_end = 0;
|
||||
|
||||
uint32_t seq_ctl = 0;
|
||||
uint32_t seq_tbl = 0;
|
||||
uint32_t seq_end = 0;
|
||||
|
||||
switch (g_RomVersion) {
|
||||
case ROMVERSION_NTSC10:
|
||||
case ROMVERSION_NTSCFINAL:
|
||||
sfx_ctl = 0x80a250;
|
||||
sfx_tbl = 0x839dd0;
|
||||
sfx_end = 0xcfbf30;
|
||||
seq_ctl = 0xcfbf30;
|
||||
seq_tbl = 0xd05f90;
|
||||
seq_end = 0xe82000;
|
||||
break;
|
||||
case ROMVERSION_PALFINAL:
|
||||
sfx_ctl = 0x7f87e0;
|
||||
sfx_tbl = 0x828360;
|
||||
sfx_end = 0xcea4c0;
|
||||
seq_ctl = 0xcea4c0;
|
||||
seq_tbl = 0xcf4520;
|
||||
seq_end = 0xe70590;
|
||||
break;
|
||||
case ROMVERSION_JPNFINAL:
|
||||
sfx_ctl = 0x7fc670;
|
||||
sfx_tbl = 0x82c1f0;
|
||||
sfx_end = 0xcee350;
|
||||
seq_ctl = 0xcee350;
|
||||
seq_tbl = 0xcf83b0;
|
||||
seq_end = 0xe74420;
|
||||
break;
|
||||
}
|
||||
|
||||
extract_audio_ctl("sfx", sfx_ctl, sfx_tbl - sfx_ctl);
|
||||
extract_audio_tbl("sfx", sfx_tbl, sfx_end - sfx_tbl);
|
||||
extract_audio_ctl("seq", seq_ctl, seq_tbl - seq_ctl);
|
||||
extract_audio_tbl("seq", seq_tbl, seq_end - seq_tbl);
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "common.h"
|
||||
|
||||
void extract_banner(const char *filename, uint32_t romoffset, size_t len)
|
||||
{
|
||||
char outfilename[1024];
|
||||
sprintf(outfilename, "%s/%s.bin", g_OutPath, filename);
|
||||
|
||||
FILE *fp = openfile(outfilename);
|
||||
fwrite(&g_Rom[romoffset], len, 1, fp);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
void extract_banners(void)
|
||||
{
|
||||
uint32_t accessingpak = 0;
|
||||
uint32_t copyright = 0;
|
||||
|
||||
switch (g_RomVersion) {
|
||||
case ROMVERSION_NTSC10:
|
||||
case ROMVERSION_NTSCFINAL:
|
||||
copyright = 0x1ffea20;
|
||||
accessingpak = 0x1fff550;
|
||||
break;
|
||||
case ROMVERSION_PALFINAL:
|
||||
copyright = 0x1ff5500;
|
||||
accessingpak = 0x1ff6030;
|
||||
break;
|
||||
case ROMVERSION_JPNFINAL:
|
||||
copyright = 0x1ffd6b0;
|
||||
accessingpak = 0x1ffe1e0;
|
||||
break;
|
||||
}
|
||||
|
||||
extract_banner("copyright", copyright, 0xb30);
|
||||
extract_banner("accessingpak", accessingpak, 0x8b0);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "common.h"
|
||||
|
||||
void extract_file_audio(char *filename, uint32_t romoffset, size_t len)
|
||||
{
|
||||
char outfilename[1024];
|
||||
sprintf(outfilename, "%s/files/%s", g_OutPath, filename);
|
||||
|
||||
FILE *fp = openfile(outfilename);
|
||||
fwrite(&g_Rom[romoffset], len, 1, fp);
|
||||
fclose(fp);
|
||||
}
|
||||
@@ -0,0 +1,500 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "common.h"
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
uint32_t primary_infsize;
|
||||
uint32_t section1_cmpsize;
|
||||
uint32_t primary_cmpsize;
|
||||
};
|
||||
|
||||
struct sectionheader {
|
||||
uint16_t infsize;
|
||||
uint16_t cmpsize;
|
||||
};
|
||||
|
||||
struct n64_primaryheader {
|
||||
uint32_t unused1;
|
||||
uint32_t ptr_rooms;
|
||||
uint32_t ptr_portals;
|
||||
uint32_t ptr_bgcmds;
|
||||
uint32_t ptr_lights;
|
||||
uint32_t 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 {
|
||||
uint32_t ptr_gfxdata;
|
||||
uint32_t pos[3];
|
||||
uint8_t br_light_min;
|
||||
uint8_t br_light_max;
|
||||
};
|
||||
|
||||
struct host_room {
|
||||
uintptr_t ptr_gfxdata;
|
||||
uint32_t pos[3];
|
||||
uint8_t br_light_min;
|
||||
uint8_t br_light_max;
|
||||
};
|
||||
|
||||
struct portal {
|
||||
uint16_t verticesoffset;
|
||||
int16_t roomnum1;
|
||||
int16_t roomnum2;
|
||||
uint8_t flags;
|
||||
};
|
||||
|
||||
struct portalvertices {
|
||||
uint8_t count;
|
||||
uint32_t vertices[1][3];
|
||||
};
|
||||
|
||||
struct bgcmd {
|
||||
uint8_t type;
|
||||
uint8_t len;
|
||||
int32_t param;
|
||||
};
|
||||
|
||||
struct light {
|
||||
uint16_t roomnum;
|
||||
uint16_t colour;
|
||||
uint8_t brightness;
|
||||
uint8_t sparkable : 1;
|
||||
uint8_t healthy : 1;
|
||||
uint8_t on : 1;
|
||||
uint8_t sparking : 1;
|
||||
uint8_t vulnerable : 1;
|
||||
uint8_t brightnessmult;
|
||||
int8_t dirx;
|
||||
int8_t diry;
|
||||
int8_t dirz;
|
||||
int16_t bbox[4][3];
|
||||
};
|
||||
|
||||
int m_NumRooms;
|
||||
|
||||
uint16_t m_AllocSizes[512];
|
||||
|
||||
static void convert_primary_rooms(uint8_t *dst, uint32_t *dstpos, uint8_t *src, uint32_t *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 = 0; // Not known at this point
|
||||
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 + 1);
|
||||
*dstpos += sizeof(*host_rooms) * (m_NumRooms + 1);
|
||||
}
|
||||
|
||||
static void convert_primary_portals(uint8_t *dst, uint32_t *dstpos, uint8_t *src, uint32_t *srcpos)
|
||||
{
|
||||
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);
|
||||
|
||||
// Convert portal vertices
|
||||
uint8_t *n64_vtxdata = &src[*srcpos];
|
||||
uint8_t *host_vtxdata = &dst[*dstpos];
|
||||
|
||||
for (int i = 0; i < numportals; i++) {
|
||||
struct portalvertices *n64_pvertices = (struct portalvertices*) &n64_vtxdata[*srcpos];
|
||||
struct portalvertices *host_pvertices = (struct portalvertices*) &host_vtxdata[*dstpos];
|
||||
|
||||
host_pvertices->count = n64_pvertices->count;
|
||||
|
||||
for (int j = 0; j < host_pvertices->count; j++) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
static void convert_primary_bgcmds(uint8_t *dst, uint32_t *dstpos, uint8_t *src, uint32_t *srcpos)
|
||||
{
|
||||
struct bgcmd *n64_cmds = (struct bgcmd *) &src[*srcpos];
|
||||
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);
|
||||
}
|
||||
|
||||
*srcpos += sizeof(*n64_cmds) * num_cmds;
|
||||
*dstpos += sizeof(*host_cmds) * num_cmds;
|
||||
}
|
||||
|
||||
static void convert_primary_lights(uint8_t *dst, uint32_t *dstpos, uint8_t *src, uint32_t *srcpos, uint32_t 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][0] = srctodst16(n64_lights[i].bbox[j][0]);
|
||||
host_lights[i].bbox[j][1] = srctodst16(n64_lights[i].bbox[j][1]);
|
||||
host_lights[i].bbox[j][2] = srctodst16(n64_lights[i].bbox[j][2]);
|
||||
}
|
||||
}
|
||||
|
||||
*srcpos += sizeof(*n64_lights) * num_lights;
|
||||
*dstpos += sizeof(*host_lights) * num_lights;
|
||||
}
|
||||
|
||||
static uint32_t convert_section1_roomgfxdata(uint8_t *dst, uint32_t dstpos, uint8_t *src, uint32_t srcpos)
|
||||
{
|
||||
return dstpos;
|
||||
}
|
||||
|
||||
static size_t sum(uint8_t *ptr, uint8_t *end)
|
||||
{
|
||||
size_t sum = 0;
|
||||
|
||||
while (ptr < end) {
|
||||
sum = (sum + *ptr) & 0xffffffff;
|
||||
ptr++;
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
static uint32_t convert_section1(uint8_t *dst, uint32_t dstpos, uint8_t *src, uint32_t srcpos, struct fileheader *n64_header)
|
||||
{
|
||||
struct fileheader *host_header = (struct fileheader *) &dst[dstpos];
|
||||
dstpos += sizeof(*host_header);
|
||||
|
||||
// Unzip primary
|
||||
size_t infsize = srctoh32(n64_header->primary_infsize);
|
||||
uint8_t *srcbin = calloc(1, infsize);
|
||||
uint8_t *dstbin = calloc(1, infsize * 2);
|
||||
uint32_t srcbinpos = 0;
|
||||
uint32_t dstbinpos = 0;
|
||||
|
||||
int ret = rzip_inflate(srcbin, infsize, &src[srcpos], srctoh32(n64_header->primary_cmpsize));
|
||||
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Unable to inflate BG primary data: %d\n", ret);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// Convert primary
|
||||
struct host_primaryheader *host_primary_header = (struct host_primaryheader *) &dstbin[dstbinpos];
|
||||
srcbinpos += sizeof(struct n64_primaryheader);
|
||||
dstbinpos += sizeof(*host_primary_header);
|
||||
|
||||
host_primary_header->unused1 = 0;
|
||||
host_primary_header->unused2 = 0;
|
||||
|
||||
host_primary_header->ptr_rooms = dstbinpos;
|
||||
convert_primary_rooms(dstbin, &dstbinpos, srcbin, &srcbinpos);
|
||||
|
||||
host_primary_header->ptr_portals = dstbinpos;
|
||||
convert_primary_portals(dstbin, &dstbinpos, srcbin, &srcbinpos);
|
||||
|
||||
host_primary_header->ptr_bgcmds = dstbinpos;
|
||||
convert_primary_bgcmds(dstbin, &dstbinpos, srcbin, &srcbinpos);
|
||||
|
||||
host_primary_header->ptr_lights = dstbinpos;
|
||||
convert_primary_lights(dstbin, &dstbinpos, srcbin, &srcbinpos, infsize);
|
||||
|
||||
// Convert room gfxdata
|
||||
uint32_t n64_primary_diff = n64_header->primary_infsize - n64_header->primary_cmpsize;
|
||||
struct n64_room *n64_rooms = (struct n64_room *) &src[sizeof(*n64_header)];
|
||||
struct host_room *host_rooms = (struct host_room *) &dst[dstbinpos];
|
||||
|
||||
uint8_t *roomgfxbuf = calloc(1, 1024 * 1024);
|
||||
uint8_t *allcmp = calloc(1, 1024 * 1024);
|
||||
int roomgfxbufpos = 0;
|
||||
int cmppos = 0;
|
||||
|
||||
//for (int i = 0; i < m_NumRooms; i++) {
|
||||
// host_rooms[i].ptr_gfxdata = dstbinpos + cmppos;
|
||||
|
||||
// srcpos = srctoh32(n64_rooms[i].ptr_gfxdata) - n64_primary_diff;
|
||||
// roomgfxbufpos = convert_section1_roomgfxdata(roomgfxbuf, 0, src, srcpos);
|
||||
|
||||
// size_t ziplen = 0;
|
||||
// ret = rzip_deflate(&allcmp[cmppos], &ziplen, roomgfxbuf, roomgfxbufpos);
|
||||
|
||||
// if (ret < 0) {
|
||||
// fprintf(stderr, "Unable to compress BG roomgfxdata for room 0x%x: %d\n", i, ret);
|
||||
// exit(EXIT_FAILURE);
|
||||
// }
|
||||
|
||||
// ziplen = ALIGN16(ziplen);
|
||||
// cmppos += ziplen;
|
||||
//}
|
||||
|
||||
// Zip primary
|
||||
size_t ziplen = 0;
|
||||
|
||||
printf("dstbin:%d = %p\n", __LINE__, dstbin);
|
||||
printf("dstpos:%d = %d\n", __LINE__, dstpos);
|
||||
printf("dstbinpos:%d = %d\n", __LINE__, dstbinpos);
|
||||
ret = rzip_deflate(&dst[dstpos], &ziplen, dstbin, dstbinpos);
|
||||
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Unable to compress BG primary data: %d\n", ret);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
printf("ziplen:%d = %d\n", __LINE__, ziplen);
|
||||
ziplen = ALIGN16(ziplen);
|
||||
dstpos += ziplen;
|
||||
|
||||
// Paste compressed roomgfxdata after it
|
||||
memcpy(&dst[dstpos], allcmp, cmppos);
|
||||
dstpos += cmppos;
|
||||
|
||||
free(roomgfxbuf);
|
||||
free(allcmp);
|
||||
free(srcbin);
|
||||
free(dstbin);
|
||||
|
||||
host_header->primary_infsize = dstbinpos;
|
||||
host_header->section1_cmpsize = ziplen + cmppos;
|
||||
host_header->primary_cmpsize = ziplen;
|
||||
|
||||
return dstpos;
|
||||
}
|
||||
|
||||
static void convert_section2_texturenums(uint8_t *dst, uint32_t *dstpos, uint8_t *src, uint32_t *srcpos, uint32_t srclen)
|
||||
{
|
||||
uint16_t *src_ids = (uint16_t *) &src[*srcpos];
|
||||
uint16_t *dst_ids = (uint16_t *) &dst[*dstpos];
|
||||
int count = srclen / sizeof(uint16_t);
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
dst_ids[i] = srctodst16(src_ids[i]);
|
||||
}
|
||||
|
||||
*srcpos += srclen;
|
||||
*dstpos += srclen;
|
||||
}
|
||||
|
||||
static void convert_section3_bboxes(uint8_t *dst, uint32_t *dstpos, uint8_t *src, uint32_t *srcpos)
|
||||
{
|
||||
int16_t *src_bboxes = (int16_t *) &src[*srcpos];
|
||||
int16_t *dst_bboxes = (int16_t *) &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(int16_t) * 6 * (m_NumRooms - 1);
|
||||
*dstpos += sizeof(int16_t) * 6 * (m_NumRooms - 1);
|
||||
}
|
||||
|
||||
static void convert_section3_allocsizes(uint8_t *dst, uint32_t *dstpos, uint8_t *src, uint32_t *srcpos)
|
||||
{
|
||||
uint16_t *dst_sizes = (uint16_t *) &dst[*dstpos];
|
||||
|
||||
for (int i = 0; i < m_NumRooms; i++) {
|
||||
dst_sizes[i] = m_AllocSizes[i];
|
||||
}
|
||||
|
||||
*srcpos += sizeof(uint16_t) * (m_NumRooms - 1);
|
||||
*dstpos += sizeof(uint16_t) * (m_NumRooms - 1);
|
||||
}
|
||||
|
||||
static void convert_section3_lightcounts(uint8_t *dst, uint32_t *dstpos, uint8_t *src, uint32_t *srcpos)
|
||||
{
|
||||
memcpy(&dst[*dstpos], &src[*srcpos], m_NumRooms);
|
||||
|
||||
*srcpos += (m_NumRooms - 1);
|
||||
*dstpos += (m_NumRooms - 1);
|
||||
}
|
||||
|
||||
static uint32_t convert_zipped_section(int section_num, uint8_t *dst, uint32_t dstpos, uint8_t *src, uint32_t srcpos, struct sectionheader *n64_header)
|
||||
{
|
||||
struct sectionheader *host_header = (struct sectionheader *) &dst[dstpos];
|
||||
dstpos += sizeof(*host_header);
|
||||
|
||||
// Unzip
|
||||
size_t infsize = rzip_get_infsize(&src[srcpos]);
|
||||
uint8_t *srcbin = calloc(1, infsize);
|
||||
uint8_t *dstbin = calloc(1, infsize);
|
||||
uint32_t srcbinpos = 0;
|
||||
uint32_t dstbinpos = 0;
|
||||
|
||||
int ret = rzip_inflate(srcbin, infsize, &src[srcpos], srctoh16(n64_header->cmpsize));
|
||||
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Unable to inflate BG section %d: %d\n", section_num, ret);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// Convert
|
||||
if (section_num == 2) {
|
||||
convert_section2_texturenums(dstbin, &dstbinpos, srcbin, &srcbinpos, infsize);
|
||||
} else if (section_num == 3) {
|
||||
convert_section3_bboxes(dstbin, &dstbinpos, srcbin, &srcbinpos);
|
||||
convert_section3_allocsizes(dstbin, &dstbinpos, srcbin, &srcbinpos);
|
||||
convert_section3_lightcounts(dstbin, &dstbinpos, srcbin, &srcbinpos);
|
||||
}
|
||||
|
||||
// Zip
|
||||
size_t ziplen = 0;
|
||||
|
||||
ret = rzip_deflate(&dst[dstpos], &ziplen, dstbin, dstbinpos);
|
||||
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Unable to compress BG section %d: %d\n", section_num, ret);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ziplen = ALIGN16(ziplen);
|
||||
|
||||
host_header->infsize = dstbinpos;
|
||||
host_header->cmpsize = ziplen;
|
||||
|
||||
dstpos += ziplen;
|
||||
|
||||
free(srcbin);
|
||||
free(dstbin);
|
||||
|
||||
return dstpos;
|
||||
}
|
||||
|
||||
void extract_file_bg(char *filename, uint32_t romoffset, size_t len)
|
||||
{
|
||||
if (0) {
|
||||
if (strcmp(filename, "bgdata/bg_mp5.seg") != 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
||||
size_t dstlen = len * 2;
|
||||
uint8_t *dst = calloc(1, dstlen);
|
||||
uint32_t dstpos = 0;
|
||||
|
||||
printf("--------------------------------------------------------------------------------\n");
|
||||
printf("-- %s\n", filename);
|
||||
|
||||
uint8_t *src = &g_Rom[romoffset];
|
||||
struct fileheader *n64_fileheader = (struct fileheader *) src;
|
||||
uint32_t n64_section2_start = sizeof(*n64_fileheader) + srctoh32(n64_fileheader->section1_cmpsize);
|
||||
struct sectionheader *n64_section2header = (struct sectionheader *) &src[n64_section2_start];
|
||||
uint32_t n64_section3_start = n64_section2_start + sizeof(*n64_section2header) + (srctoh16(n64_section2header->cmpsize) & 0x7fff);
|
||||
struct sectionheader *n64_section3header = (struct sectionheader *) &src[n64_section3_start];
|
||||
|
||||
printf("section2_start 0x%x\n", n64_section2_start);
|
||||
printf("section3_start 0x%x\n", n64_section3_start);
|
||||
|
||||
dstpos = convert_section1(dst, dstpos, src, sizeof(*n64_fileheader), n64_fileheader);
|
||||
dstpos = convert_zipped_section(2, dst, dstpos, src, n64_section2_start + sizeof(*n64_section2header), n64_section2header);
|
||||
dstpos = convert_zipped_section(3, dst, dstpos, src, n64_section3_start + sizeof(*n64_section3header), n64_section3header);
|
||||
dstpos = ALIGN16(dstpos);
|
||||
|
||||
char outfilename[1024];
|
||||
sprintf(outfilename, "%s/files/%s", g_OutPath, filename);
|
||||
|
||||
FILE *fp = openfile(outfilename);
|
||||
fwrite(dst, dstpos, 1, fp);
|
||||
fclose(fp);
|
||||
|
||||
free(dst);
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "common.h"
|
||||
|
||||
static int get_next_nonzero(uint8_t *src, uint32_t offset, size_t len)
|
||||
{
|
||||
uint32_t *ptr = (uint32_t *) &src[offset];
|
||||
uint32_t *end = (uint32_t *) &src[len];
|
||||
|
||||
while (ptr < end) {
|
||||
if (*ptr != 0) {
|
||||
return srctoh32(*ptr);
|
||||
}
|
||||
|
||||
ptr++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_num_strings(uint8_t *src, size_t len)
|
||||
{
|
||||
uint32_t ptr_table_len = get_next_nonzero(src, 0, len);
|
||||
|
||||
if (ptr_table_len) {
|
||||
return ptr_table_len / sizeof(uint32_t);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void extract_file_lang(char *filename, uint32_t romoffset, size_t srclen)
|
||||
{
|
||||
// Unzip it
|
||||
size_t infsize = rzip_get_infsize(&g_Rom[romoffset]);
|
||||
uint8_t *src = malloc(infsize);
|
||||
|
||||
int ret = rzip_inflate(src, infsize, &g_Rom[romoffset], srclen);
|
||||
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "%s: Unable to inflate file: %d\n", filename, ret);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// Convert it
|
||||
uint32_t *src_offsets = (uint32_t *) src;
|
||||
size_t src_ptr_table_len = srctoh32(src_offsets[0]);
|
||||
size_t src_str_table_len = infsize - src_ptr_table_len;
|
||||
int num_strings = get_num_strings(src, srclen);
|
||||
size_t dst_ptr_table_len = num_strings * sizeof(uintptr_t);
|
||||
size_t dst_str_table_len = src_str_table_len;
|
||||
|
||||
uint8_t *dst = calloc(1, dst_ptr_table_len + dst_str_table_len + 0x20);
|
||||
int cur_dst_offset = dst_ptr_table_len;
|
||||
|
||||
uintptr_t *dst_offsets = (uintptr_t *) dst;
|
||||
|
||||
for (int i = 0; i < num_strings; i++) {
|
||||
uint32_t src_offset = srctoh32(src_offsets[i]);
|
||||
|
||||
if (src_offset) {
|
||||
// Write pointer
|
||||
dst_offsets[i] = htodst32(cur_dst_offset);
|
||||
|
||||
// Write string
|
||||
uint32_t end = get_next_nonzero(src, (i + 1) * 4, num_strings * 4);
|
||||
|
||||
if (!end) {
|
||||
end = infsize;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
cur_dst_offset = ALIGN16(cur_dst_offset);
|
||||
|
||||
// Zip it
|
||||
uint8_t *zipped = calloc(1, cur_dst_offset);
|
||||
size_t ziplen = cur_dst_offset;
|
||||
|
||||
ret = rzip_deflate(zipped, &ziplen, dst, cur_dst_offset);
|
||||
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "%s: Unable to compress file: %d\n", filename, ret);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ziplen = ALIGN16(ziplen);
|
||||
|
||||
// Write it
|
||||
char outfilename[1024];
|
||||
sprintf(outfilename, "%s/files/%s", g_OutPath, filename);
|
||||
|
||||
FILE *fp = openfile(outfilename);
|
||||
fwrite(zipped, ziplen, 1, fp);
|
||||
fclose(fp);
|
||||
|
||||
free(zipped);
|
||||
free(dst);
|
||||
free(src);
|
||||
}
|
||||
@@ -0,0 +1,952 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "common.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,
|
||||
};
|
||||
|
||||
struct marker {
|
||||
uint32_t src_offset;
|
||||
uint32_t dst_offset;
|
||||
uint32_t 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 },
|
||||
/* 4*/ { 4, 4 },
|
||||
/* 5*/ { 4, 8 },
|
||||
/* 6*/ { 8, 8 },
|
||||
/* 7*/ { 4, 4 },
|
||||
/* 8*/ { 4, 4 },
|
||||
/* 9*/ { 8, 4 },
|
||||
/*10*/ { 4, 8 },
|
||||
/*11*/ { 4, 4 },
|
||||
/*12*/ { 4, 4 },
|
||||
/*13*/ { 4, 4 },
|
||||
/*14*/ { 4, 4 },
|
||||
/*15*/ { 4, 4 },
|
||||
/*16*/ { 4, 4 },
|
||||
/*17*/ { 8, 8 },
|
||||
/*18*/ { 4, 4 },
|
||||
/*19*/ { 8, 8 },
|
||||
/*20*/ { 4, 4 },
|
||||
};
|
||||
|
||||
struct marker m_Markers[1024];
|
||||
int m_NumMarkers;
|
||||
|
||||
#define MODELNODETYPE_CHRINFO 0x01
|
||||
#define MODELNODETYPE_POSITION 0x02
|
||||
#define MODELNODETYPE_GUNDL 0x04
|
||||
#define MODELNODETYPE_05 0x05
|
||||
#define MODELNODETYPE_DISTANCE 0x08
|
||||
#define MODELNODETYPE_REORDER 0x09
|
||||
#define MODELNODETYPE_BBOX 0x0a
|
||||
#define MODELNODETYPE_0B 0x0b
|
||||
#define MODELNODETYPE_CHRGUNFIRE 0x0c
|
||||
#define MODELNODETYPE_0D 0x0d
|
||||
#define MODELNODETYPE_0E 0x0e
|
||||
#define MODELNODETYPE_0F 0x0f
|
||||
#define MODELNODETYPE_11 0x11
|
||||
#define MODELNODETYPE_TOGGLE 0x12
|
||||
#define MODELNODETYPE_POSITIONHELD 0x15
|
||||
#define MODELNODETYPE_STARGUNFIRE 0x16
|
||||
#define MODELNODETYPE_HEADSPOT 0x17
|
||||
#define MODELNODETYPE_DL 0x18
|
||||
#define MODELNODETYPE_19 0x19
|
||||
#define MODELNODETYPE_0100 0x0100
|
||||
#define MODELNODETYPE_0200 0x0200
|
||||
|
||||
struct src_modeldef {
|
||||
uint32_t ptr_rootnode;
|
||||
uint32_t ptr_skel;
|
||||
uint32_t ptr_parts;
|
||||
int16_t numparts;
|
||||
int16_t nummatrices;
|
||||
uint32_t scale;
|
||||
uint16_t rwdatalen;
|
||||
uint16_t numtexconfigs;
|
||||
uint32_t ptr_texconfigs;
|
||||
};
|
||||
|
||||
struct dst_modeldef {
|
||||
uintptr_t ptr_rootnode;
|
||||
uintptr_t ptr_skel;
|
||||
uintptr_t ptr_parts;
|
||||
int16_t numparts;
|
||||
int16_t nummatrices;
|
||||
uint32_t scale;
|
||||
uint16_t rwdatalen;
|
||||
uint16_t numtexconfigs;
|
||||
uintptr_t ptr_texconfigs;
|
||||
};
|
||||
|
||||
struct src_modelnode {
|
||||
uint16_t type;
|
||||
uint32_t ptr_rodata;
|
||||
uint32_t ptr_parent;
|
||||
uint32_t ptr_next;
|
||||
uint32_t ptr_prev;
|
||||
uint32_t ptr_child;
|
||||
};
|
||||
|
||||
struct dst_modelnode {
|
||||
uint16_t 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 {
|
||||
uint16_t animpart;
|
||||
int16_t mtxindex;
|
||||
uint32_t unk04;
|
||||
uint16_t rwdataindex;
|
||||
};
|
||||
|
||||
struct generic_rodata_position {
|
||||
uint32_t pos[3];
|
||||
uint16_t part;
|
||||
int16_t mtxindexes[3];
|
||||
uint32_t drawdist;
|
||||
};
|
||||
|
||||
struct src_rodata_gundl {
|
||||
uint32_t ptr_opagdl;
|
||||
uint32_t ptr_xlugdl;
|
||||
uint32_t ptr_baseaddr;
|
||||
uint32_t ptr_vertices;
|
||||
int16_t numvertices;
|
||||
int16_t unk12;
|
||||
};
|
||||
|
||||
struct dst_rodata_gundl {
|
||||
uintptr_t ptr_opagdl;
|
||||
uintptr_t ptr_xlugdl;
|
||||
uintptr_t ptr_baseaddr;
|
||||
uintptr_t ptr_vertices;
|
||||
int16_t numvertices;
|
||||
int16_t unk12;
|
||||
};
|
||||
|
||||
struct src_rodata_distance {
|
||||
uint32_t near;
|
||||
uint32_t far;
|
||||
uint32_t ptr_target;
|
||||
uint16_t rwdataindex;
|
||||
};
|
||||
|
||||
struct dst_rodata_distance {
|
||||
uint32_t near;
|
||||
uint32_t far;
|
||||
uintptr_t ptr_target;
|
||||
uint16_t rwdataindex;
|
||||
};
|
||||
|
||||
struct src_rodata_reorder {
|
||||
uint32_t unk00;
|
||||
uint32_t unk04;
|
||||
uint32_t unk08;
|
||||
uint32_t unk0c[3];
|
||||
uint32_t ptr_node_unk18;
|
||||
uint32_t ptr_node_unk1c;
|
||||
int16_t side;
|
||||
uint16_t rwdataindex;
|
||||
};
|
||||
|
||||
struct dst_rodata_reorder {
|
||||
uint32_t unk00;
|
||||
uint32_t unk04;
|
||||
uint32_t unk08;
|
||||
uint32_t unk0c[3];
|
||||
uintptr_t ptr_node_unk18;
|
||||
uintptr_t ptr_node_unk1c;
|
||||
int16_t side;
|
||||
uint16_t rwdataindex;
|
||||
};
|
||||
|
||||
struct generic_rodata_bbox {
|
||||
int32_t hitpart;
|
||||
uint32_t bbox[6];
|
||||
};
|
||||
|
||||
struct src_rodata_chrgunfire {
|
||||
uint32_t pos[3];
|
||||
uint32_t dim[3];
|
||||
uint32_t ptr_texture;
|
||||
uint32_t unk1c;
|
||||
uint16_t rwdataindex;
|
||||
uint32_t ptr_baseaddr;
|
||||
};
|
||||
|
||||
struct dst_rodata_chrgunfire {
|
||||
uint32_t pos[3];
|
||||
uint32_t dim[3];
|
||||
uintptr_t ptr_texture;
|
||||
uint32_t unk1c;
|
||||
uint16_t rwdataindex;
|
||||
uintptr_t ptr_baseaddr;
|
||||
};
|
||||
|
||||
struct src_rodata_type11 {
|
||||
uint32_t unk00;
|
||||
uint32_t unk04;
|
||||
uint32_t unk08;
|
||||
uint32_t unk0c;
|
||||
uint32_t unk10;
|
||||
uint32_t ptr_unk14;
|
||||
};
|
||||
|
||||
struct dst_rodata_type11 {
|
||||
uint32_t unk00;
|
||||
uint32_t unk04;
|
||||
uint32_t unk08;
|
||||
uint32_t unk0c;
|
||||
uint32_t unk10;
|
||||
uintptr_t ptr_unk14;
|
||||
};
|
||||
|
||||
struct src_rodata_toggle {
|
||||
uint32_t ptr_target;
|
||||
uint16_t rwdataindex;
|
||||
};
|
||||
|
||||
struct dst_rodata_toggle {
|
||||
uintptr_t ptr_target;
|
||||
uint16_t rwdataindex;
|
||||
};
|
||||
|
||||
struct generic_rodata_positionheld {
|
||||
uint32_t pos[3];
|
||||
int16_t mtxindex;
|
||||
uint32_t unk10;
|
||||
};
|
||||
|
||||
struct src_rodata_stargunfire {
|
||||
uint32_t unk00;
|
||||
uint32_t ptr_vertices;
|
||||
uint32_t ptr_gdl;
|
||||
uint32_t ptr_baseaddr;
|
||||
};
|
||||
|
||||
struct dst_rodata_stargunfire {
|
||||
uint32_t unk00;
|
||||
uintptr_t ptr_vertices;
|
||||
uintptr_t ptr_gdl;
|
||||
uintptr_t ptr_baseaddr;
|
||||
};
|
||||
|
||||
struct generic_rodata_headspot {
|
||||
uint16_t rwdataindex;
|
||||
};
|
||||
|
||||
struct src_rodata_dl {
|
||||
uint32_t ptr_opagdl;
|
||||
uint32_t ptr_xlugdl;
|
||||
uint32_t ptr_colours;
|
||||
uint32_t ptr_vertices; // colours follow this array
|
||||
int16_t numvertices;
|
||||
int16_t mcount;
|
||||
uint16_t rwdataindex;
|
||||
uint16_t 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
|
||||
int16_t numvertices;
|
||||
int16_t mcount;
|
||||
uint16_t rwdataindex;
|
||||
uint16_t numcolours;
|
||||
};
|
||||
|
||||
struct generic_rodata_type19 {
|
||||
uint32_t numvertices;
|
||||
uint32_t vertices[3];
|
||||
};
|
||||
|
||||
struct src_texconfig {
|
||||
uint32_t ptr;
|
||||
uint8_t width;
|
||||
uint8_t height;
|
||||
uint8_t level;
|
||||
uint8_t format;
|
||||
uint8_t depth;
|
||||
uint8_t s;
|
||||
uint8_t t;
|
||||
uint8_t unk0b;
|
||||
};
|
||||
|
||||
struct dst_texconfig {
|
||||
uintptr_t ptr;
|
||||
uint8_t width;
|
||||
uint8_t height;
|
||||
uint8_t level;
|
||||
uint8_t format;
|
||||
uint8_t depth;
|
||||
uint8_t s;
|
||||
uint8_t t;
|
||||
uint8_t unk0b;
|
||||
};
|
||||
|
||||
static struct marker *find_marker(uint32_t 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(uint32_t src_offset, enum contenttype type, uint32_t 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 populate_markers(uint8_t *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];
|
||||
|
||||
switch (marker->type) {
|
||||
case CT_MODELDEF:
|
||||
struct src_modeldef *src_modeldef = src_thing;
|
||||
int num_texconfigs = srctoh16(src_modeldef->numtexconfigs);
|
||||
uint32_t 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;
|
||||
uint32_t 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;
|
||||
uint32_t *src_parts = (uint32_t *) 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;
|
||||
set_marker(srctoh32(src_stargunfire->ptr_vertices), CT_VTXCOL, 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 sort_markers(void)
|
||||
{
|
||||
for (int i = 0; i < m_NumMarkers - 1; i++) {
|
||||
uint32_t 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 uint32_t convert_content(uint8_t *dst, uint8_t *src, uint32_t src_file_len)
|
||||
{
|
||||
uint32_t dstpos = 0;
|
||||
|
||||
for (int i = 0; i < m_NumMarkers; i++) {
|
||||
struct marker *marker = &m_Markers[i];
|
||||
void *src_thing = &src[marker->src_offset];
|
||||
uint32_t src_end = i < m_NumMarkers - 1 ? m_Markers[i + 1].src_offset : src_file_len;
|
||||
uint32_t 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;
|
||||
uint32_t *src_parts = (uint32_t *) src_thing;
|
||||
uintptr_t *dst_parts = (uintptr_t *) dst_thing;
|
||||
int num_parts = srctoh16(src_modeldef2->numparts);
|
||||
uint16_t *src_nums = (uint16_t *) &src_parts[num_parts];
|
||||
uint16_t *dst_nums = (uint16_t *) &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(uint16_t);
|
||||
if (num_parts) {
|
||||
dstpos = ALIGN8(dstpos);
|
||||
}
|
||||
break;
|
||||
case CT_VTXCOL:
|
||||
memcpy(dst_thing, src_thing, src_len);
|
||||
dstpos += src_len;
|
||||
break;
|
||||
case CT_GDL:
|
||||
struct marker *parent = find_marker(marker->parent_src_offset);
|
||||
uint32_t src_vtx;
|
||||
uint32_t 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;
|
||||
}
|
||||
|
||||
gbi_set_vtx(src_vtx, dst_vtx);
|
||||
gbi_set_segment(0x04, dst_vtx);
|
||||
gbi_set_segment(0x05, 0);
|
||||
dstpos = gbi_convert_gdl(dst, dstpos, src, marker->src_offset);
|
||||
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->ptr_unk14 = srctodst32(src_type11->ptr_unk14); // Not read by game engine
|
||||
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;
|
||||
uint32_t *src_vertices = src_thing + sizeof(uint32_t);
|
||||
uint32_t *dst_vertices = dst_thing + sizeof(uint32_t);
|
||||
int num_vertices = srctoh32(src_type19->numvertices);
|
||||
|
||||
dst_type19->numvertices = htodst32(num_vertices);
|
||||
dstpos += sizeof(uint32_t);
|
||||
|
||||
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(uint32_t) * 3;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
dstpos = ALIGN(dstpos, m_AlignConfigs[marker->type].after);
|
||||
}
|
||||
|
||||
return dstpos;
|
||||
}
|
||||
|
||||
static uint32_t resolve_pointer(uint32_t src_offset)
|
||||
{
|
||||
if (src_offset == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct marker *marker = find_marker(src_offset & 0x00ffffff);
|
||||
return marker ? (0x05000000 | marker->dst_offset) : 0;
|
||||
}
|
||||
|
||||
static void relink_pointers(uint8_t *dst, uint8_t *src)
|
||||
{
|
||||
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];
|
||||
|
||||
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(resolve_pointer(srctoh32(src_modeldef->ptr_rootnode)));
|
||||
dst_modeldef->ptr_parts = htodst32(resolve_pointer(srctoh32(src_modeldef->ptr_parts)));
|
||||
dst_modeldef->ptr_texconfigs = htodst32(resolve_pointer(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(resolve_pointer(srctoh32(src_node->ptr_rodata)));
|
||||
dst_node->ptr_parent = htodst32(resolve_pointer(srctoh32(src_node->ptr_parent)));
|
||||
dst_node->ptr_next = htodst32(resolve_pointer(srctoh32(src_node->ptr_next)));
|
||||
dst_node->ptr_prev = htodst32(resolve_pointer(srctoh32(src_node->ptr_prev)));
|
||||
dst_node->ptr_child = htodst32(resolve_pointer(srctoh32(src_node->ptr_child)));
|
||||
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(resolve_pointer(srctoh32(src_texconfig->ptr)));
|
||||
}
|
||||
break;
|
||||
case CT_PARTS:
|
||||
struct src_modeldef *src_modeldef2 = (struct src_modeldef *) src;
|
||||
uint32_t *src_parts = (uint32_t *) 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(resolve_pointer(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(resolve_pointer(srctoh32(src_gundl->ptr_opagdl)));
|
||||
dst_gundl->ptr_xlugdl = htodst32(resolve_pointer(srctoh32(src_gundl->ptr_xlugdl)));
|
||||
dst_gundl->ptr_vertices = htodst32(resolve_pointer(srctoh32(src_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(resolve_pointer(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(resolve_pointer(srctoh32(src_reorder->ptr_node_unk18)));
|
||||
dst_reorder->ptr_node_unk1c = htodst32(resolve_pointer(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(resolve_pointer(srctoh32(src_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(resolve_pointer(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(resolve_pointer(srctoh32(src_stargunfire->ptr_vertices)));
|
||||
dst_stargunfire->ptr_gdl = htodst32(resolve_pointer(srctoh32(src_stargunfire->ptr_gdl)));
|
||||
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(resolve_pointer(srctoh32(src_dl->ptr_opagdl)));
|
||||
dst_dl->ptr_xlugdl = htodst32(resolve_pointer(srctoh32(src_dl->ptr_xlugdl)));
|
||||
dst_dl->ptr_colours = htodst32(resolve_pointer(srctoh32(src_dl->ptr_colours)));
|
||||
dst_dl->ptr_vertices = htodst32(resolve_pointer(srctoh32(src_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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int calc_align(uint32_t value)
|
||||
{
|
||||
if ((value % 16) == 0) {
|
||||
return 16;
|
||||
} else if ((value % 8) == 0) {
|
||||
return 8;
|
||||
} else if ((value % 4) == 0) {
|
||||
return 4;
|
||||
} else if ((value % 2) == 0) {
|
||||
return 2;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
static int convert_model(uint8_t *dst, uint8_t *src, uint32_t srclen)
|
||||
{
|
||||
uint32_t dstpos;
|
||||
|
||||
populate_markers(src);
|
||||
sort_markers();
|
||||
|
||||
dstpos = convert_content(dst, src, srclen);
|
||||
relink_pointers(dst, src);
|
||||
|
||||
return dstpos;
|
||||
}
|
||||
|
||||
void extract_file_model(char *filename, uint32_t romoffset, size_t len)
|
||||
{
|
||||
// Unzip it
|
||||
size_t infsize = rzip_get_infsize(&g_Rom[romoffset]);
|
||||
uint8_t *src = malloc(infsize);
|
||||
|
||||
int ret = rzip_inflate(src, infsize, &g_Rom[romoffset], len);
|
||||
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "%s: Unable to inflate file: %d\n", filename, ret);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// Convert it
|
||||
uint8_t *dst = calloc(1, infsize * 4);
|
||||
|
||||
int dstpos = convert_model(dst, src, infsize);
|
||||
|
||||
if (dstpos > infsize * 2) {
|
||||
fprintf(stderr, "%s: overflow\n", filename);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// Zip it
|
||||
uint8_t *zipped = calloc(1, dstpos);
|
||||
size_t ziplen = dstpos;
|
||||
|
||||
ret = rzip_deflate(zipped, &ziplen, dst, dstpos);
|
||||
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "%s: Unable to compress file: %d\n", filename, ret);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ziplen = ALIGN16(ziplen);
|
||||
|
||||
// Write it
|
||||
char outfilename[1024];
|
||||
sprintf(outfilename, "%s/files/%s", g_OutPath, filename);
|
||||
|
||||
FILE *fp = openfile(outfilename);
|
||||
fwrite(zipped, ziplen, 1, fp);
|
||||
fclose(fp);
|
||||
|
||||
free(zipped);
|
||||
free(dst);
|
||||
free(src);
|
||||
}
|
||||
@@ -0,0 +1,357 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "common.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 {
|
||||
int32_t num_pads;
|
||||
int32_t num_covers;
|
||||
uint32_t ptr_waypoints;
|
||||
uint32_t ptr_waygroups;
|
||||
uint32_t ptr_cover;
|
||||
};
|
||||
|
||||
struct host_header {
|
||||
int32_t num_pads;
|
||||
int32_t num_covers;
|
||||
uintptr_t ptr_waypoints;
|
||||
uintptr_t ptr_waygroups;
|
||||
uintptr_t ptr_cover;
|
||||
};
|
||||
|
||||
struct padheader {
|
||||
uint32_t flags : 18;
|
||||
uint32_t room : 10;
|
||||
uint32_t liftnum : 4;
|
||||
};
|
||||
|
||||
struct n64_waypoint {
|
||||
int32_t padnum;
|
||||
uint32_t ptr_neighbours;
|
||||
int32_t groupnum;
|
||||
int32_t step;
|
||||
};
|
||||
|
||||
struct host_waypoint {
|
||||
int32_t padnum;
|
||||
uintptr_t ptr_neighbours;
|
||||
int32_t groupnum;
|
||||
int32_t step;
|
||||
};
|
||||
|
||||
struct n64_waygroup {
|
||||
uint32_t ptr_neighbours;
|
||||
uint32_t ptr_waypoints;
|
||||
int32_t step;
|
||||
};
|
||||
|
||||
struct host_waygroup {
|
||||
uintptr_t ptr_neighbours;
|
||||
uintptr_t ptr_waypoints;
|
||||
int32_t step;
|
||||
};
|
||||
|
||||
struct coverdefinition {
|
||||
uint32_t pos[3];
|
||||
uint32_t dir[3];
|
||||
uint16_t flags;
|
||||
uint16_t unk1a;
|
||||
};
|
||||
|
||||
static int convert_pads(uint8_t *dst, int dstpos, uint8_t *src, int srcpos, int num_pads)
|
||||
{
|
||||
uint16_t *src_offsets = (uint16_t *) &src[srcpos];
|
||||
uint16_t *dst_offsets = (uint16_t *) &dst[dstpos];
|
||||
|
||||
dstpos += num_pads * sizeof(uint16_t);
|
||||
|
||||
for (int i = 0; i < num_pads; i++) {
|
||||
dstpos = ALIGN4(dstpos);
|
||||
srcpos = srctoh16(src_offsets[i]);
|
||||
|
||||
dst_offsets[i] = htodst16(dstpos);
|
||||
|
||||
// Header
|
||||
uint32_t n64_padheader = srctoh32(*(uint32_t *) &src[srcpos]);
|
||||
struct padheader *host_padheader = (struct padheader *) &dst[dstpos];
|
||||
uint32_t flags = (n64_padheader >> 14) & 0x3ffff;
|
||||
|
||||
#ifdef FORCE_BE32
|
||||
*(uint32_t *) host_padheader = htodst32(n64_padheader);
|
||||
#else
|
||||
host_padheader->flags = flags;
|
||||
host_padheader->room = (n64_padheader >> 4) & 0x3ff;
|
||||
host_padheader->liftnum = n64_padheader & 0xf;
|
||||
#endif
|
||||
|
||||
srcpos += sizeof(struct padheader);
|
||||
dstpos += sizeof(struct padheader);
|
||||
|
||||
// Position
|
||||
if (flags & PADFLAG_INTPOS) {
|
||||
int16_t *srcptr = (int16_t *) &src[srcpos];
|
||||
int16_t *dstptr = (int16_t *) &dst[dstpos];
|
||||
|
||||
dstptr[0] = srctodst16(srcptr[0]);
|
||||
dstptr[1] = srctodst16(srcptr[1]);
|
||||
dstptr[2] = srctodst16(srcptr[2]);
|
||||
|
||||
srcpos += 8;
|
||||
dstpos += 8;
|
||||
} else {
|
||||
uint32_t *srcptr = (uint32_t *) &src[srcpos];
|
||||
uint32_t *dstptr = (uint32_t *) &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) {
|
||||
uint32_t *srcptr = (uint32_t *) &src[srcpos];
|
||||
uint32_t *dstptr = (uint32_t *) &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) {
|
||||
uint32_t *srcptr = (uint32_t *) &src[srcpos];
|
||||
uint32_t *dstptr = (uint32_t *) &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) {
|
||||
uint32_t *srcptr = (uint32_t *) &src[srcpos];
|
||||
uint32_t *dstptr = (uint32_t *) &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 convert_waypoints(uint8_t *dst, int dstpos, uint8_t *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);
|
||||
|
||||
uint32_t *host_neighbours = (uint32_t *) &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;
|
||||
|
||||
uint32_t *n64_neighbours = (uint32_t *) &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 convert_waygroups(uint8_t *dst, int dstpos, uint8_t *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
|
||||
uint32_t *host_waypoints = (uint32_t *) &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;
|
||||
|
||||
uint32_t *n64_waypoints = (uint32_t *) &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
|
||||
uint32_t *host_neighbours = (uint32_t *) &dst[dstpos];
|
||||
n = 0;
|
||||
|
||||
for (int i = 0; i < num_waygroups; i++) {
|
||||
host_waygroups[i].ptr_neighbours = htodst32(dstpos);
|
||||
|
||||
uint32_t *n64_neighbours = (uint32_t *) &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 convert_cover(uint8_t *dst, int dstpos, uint8_t *src, int srcpos, int num_covers)
|
||||
{
|
||||
struct coverdefinition *n64_covers = (struct coverdefinition *) &src[srcpos];
|
||||
struct coverdefinition *host_covers = (struct 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 coverdefinition);
|
||||
|
||||
return dstpos;
|
||||
}
|
||||
|
||||
static int convert_binary(uint8_t *dst, uint8_t *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 = convert_pads(dst, dstpos, src, sizeof(struct n64_header), num_pads);
|
||||
|
||||
// Waypoints
|
||||
host_header->ptr_waypoints = htodst32(dstpos);
|
||||
dstpos = convert_waypoints(dst, dstpos, src, srctoh32(n64_header->ptr_waypoints));
|
||||
|
||||
// Waygroups
|
||||
host_header->ptr_waygroups = htodst32(dstpos);
|
||||
dstpos = convert_waygroups(dst, dstpos, src, srctoh32(n64_header->ptr_waygroups));
|
||||
|
||||
// Cover
|
||||
host_header->ptr_cover = htodst32(dstpos);
|
||||
dstpos = convert_cover(dst, dstpos, src, srctoh32(n64_header->ptr_cover), num_covers);
|
||||
|
||||
return dstpos;
|
||||
}
|
||||
|
||||
void extract_file_pads(char *filename, uint32_t romoffset, size_t len)
|
||||
{
|
||||
// Unzip it
|
||||
size_t infsize = rzip_get_infsize(&g_Rom[romoffset]);
|
||||
uint8_t *src = malloc(infsize);
|
||||
|
||||
int ret = rzip_inflate(src, infsize, &g_Rom[romoffset], len);
|
||||
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "%s: Unable to inflate file: %d\n", filename, ret);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// Convert it
|
||||
uint8_t *dst = calloc(1, infsize * 2);
|
||||
int dstpos = convert_binary(dst, src);
|
||||
|
||||
dstpos = ALIGN16(dstpos);
|
||||
|
||||
// Zip it
|
||||
uint8_t *zipped = calloc(1, dstpos);
|
||||
size_t ziplen = dstpos;
|
||||
|
||||
ret = rzip_deflate(zipped, &ziplen, dst, dstpos);
|
||||
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "%s: Unable to compress file: %d\n", filename, ret);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// Write it
|
||||
char outfilename[1024];
|
||||
sprintf(outfilename, "%s/files/%s", g_OutPath, filename);
|
||||
|
||||
FILE *fp = openfile(outfilename);
|
||||
fwrite(zipped, ALIGN16(ziplen), 1, fp);
|
||||
fclose(fp);
|
||||
|
||||
free(src);
|
||||
free(dst);
|
||||
free(zipped);
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "common.h"
|
||||
|
||||
struct tile {
|
||||
uint8_t type;
|
||||
uint8_t numvertices;
|
||||
uint16_t flags;
|
||||
uint16_t floortype;
|
||||
uint8_t xmin;
|
||||
uint8_t ymin;
|
||||
uint8_t zmin;
|
||||
uint8_t xmax;
|
||||
uint8_t ymax;
|
||||
uint8_t zmax;
|
||||
uint16_t floorcol;
|
||||
};
|
||||
|
||||
void extract_file_tiles(char *filename, uint32_t romoffset, size_t len)
|
||||
{
|
||||
// Unzip it
|
||||
size_t infsize = rzip_get_infsize(&g_Rom[romoffset]);
|
||||
uint8_t *src = malloc(infsize);
|
||||
|
||||
int ret = rzip_inflate(src, infsize, &g_Rom[romoffset], len);
|
||||
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "%s: Unable to inflate file: %d\n", filename, ret);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
int num_rooms = srctoh32(*(uint32_t *) src);
|
||||
|
||||
size_t src_ptr_table_len = (num_rooms + 1) * 4;
|
||||
size_t dst_ptr_table_len = (num_rooms + 1) * sizeof(uintptr_t);
|
||||
|
||||
uint32_t *src_offsets = (uint32_t *) &src[4];
|
||||
|
||||
size_t data_len = infsize - src_ptr_table_len - 4;
|
||||
|
||||
uint8_t *dst = calloc(1, dst_ptr_table_len + data_len + 0x20);
|
||||
|
||||
*(uint32_t *) dst = htodst32(num_rooms);
|
||||
|
||||
uintptr_t *dst_offsets = (uintptr_t *) (dst + ALIGN(4, sizeof(uintptr_t)));
|
||||
uint32_t cur_dst_offset = ALIGN(4, sizeof(uintptr_t)) + dst_ptr_table_len;
|
||||
|
||||
uint32_t cur_src_offset = srctoh32(src_offsets[0]);
|
||||
uint32_t 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++) {
|
||||
*(int16_t *) &dst[cur_dst_offset + 0] = srctodst16(*(int16_t *) &src[cur_src_offset + 0]);
|
||||
*(int16_t *) &dst[cur_dst_offset + 2] = srctodst16(*(int16_t *) &src[cur_src_offset + 2]);
|
||||
*(int16_t *) &dst[cur_dst_offset + 4] = srctodst16(*(int16_t *) &src[cur_src_offset + 4]);
|
||||
cur_dst_offset += 6;
|
||||
cur_src_offset += 6;
|
||||
}
|
||||
}
|
||||
|
||||
cur_dst_offset = ALIGN16(cur_dst_offset);
|
||||
|
||||
// Zip it
|
||||
uint8_t *zipped = calloc(1, cur_dst_offset);
|
||||
size_t ziplen = cur_dst_offset;
|
||||
|
||||
ret = rzip_deflate(zipped, &ziplen, dst, cur_dst_offset);
|
||||
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "%s: Unable to compress file: %d\n", filename, ret);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ziplen = ALIGN16(ziplen);
|
||||
|
||||
// Write it
|
||||
char outfilename[1024];
|
||||
|
||||
sprintf(outfilename, "%s/files/%s", g_OutPath, filename);
|
||||
|
||||
FILE *fp = openfile(outfilename);
|
||||
fwrite(zipped, ziplen, 1, fp);
|
||||
fclose(fp);
|
||||
|
||||
free(zipped);
|
||||
free(dst);
|
||||
free(src);
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "common.h"
|
||||
|
||||
void extract_file_audio(char *filename, uint32_t romoffset, size_t len);
|
||||
void extract_file_bg(char *filename, uint32_t romoffset, size_t len);
|
||||
void extract_file_lang(char *filename, uint32_t romoffset, size_t len);
|
||||
void extract_file_model(char *filename, uint32_t romoffset, size_t len);
|
||||
void extract_file_pads(char *filename, uint32_t romoffset, size_t len);
|
||||
void extract_file_tiles(char *filename, uint32_t romoffset, size_t len);
|
||||
|
||||
static void extract_file(int filenum, uint32_t romoffset, size_t len)
|
||||
{
|
||||
uint32_t name_uint32_table = 0;
|
||||
|
||||
switch (g_RomVersion) {
|
||||
case ROMVERSION_NTSC10:
|
||||
case ROMVERSION_NTSCFINAL:
|
||||
name_uint32_table = 0x1d5ca00;
|
||||
break;
|
||||
case ROMVERSION_PALFINAL:
|
||||
name_uint32_table = 0x1d534e0;
|
||||
break;
|
||||
case ROMVERSION_JPNFINAL:
|
||||
name_uint32_table = 0x1d58a20;
|
||||
break;
|
||||
}
|
||||
|
||||
uint32_t name_offset = name_uint32_table + srctoh32(*(uint32_t *) &g_Rom[name_uint32_table + filenum * 4]);
|
||||
|
||||
char *filename = (char *) &g_Rom[name_offset];
|
||||
|
||||
if (strstr(filename, ".seg")) {
|
||||
extract_file_bg(filename, romoffset, len);
|
||||
} else if (strstr(filename, "padsZ")) {
|
||||
extract_file_pads(filename, romoffset, len);
|
||||
} else if (strstr(filename, "tilesZ")) {
|
||||
extract_file_tiles(filename, romoffset, len);
|
||||
} else if (filename[0] == 'A') {
|
||||
extract_file_audio(filename, romoffset, len);
|
||||
} else if (filename[0] == 'C' || filename[0] == 'G' || filename[0] == 'P') {
|
||||
extract_file_model(filename, romoffset, len);
|
||||
} else if (filename[0] == 'L') {
|
||||
extract_file_lang(filename, romoffset, len);
|
||||
} else if (filename[0] == 'U') {
|
||||
// Setup file - don't extract
|
||||
} else {
|
||||
fprintf(stderr, "Unrecognised file type: '%s'\n", filename);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
void extract_files(void)
|
||||
{
|
||||
size_t infsize = rzip_get_infsize(&g_Rom[0x39850]);
|
||||
uint8_t *data = malloc(infsize);
|
||||
|
||||
int ret = rzip_inflate(data, infsize, &g_Rom[0x39850], infsize);
|
||||
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Unable to inflate data segment: %d\n", ret);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
uint32_t offset = 0;
|
||||
|
||||
switch (g_RomVersion) {
|
||||
case ROMVERSION_NTSC10:
|
||||
case ROMVERSION_NTSCFINAL:
|
||||
offset = 0x28080;
|
||||
break;
|
||||
case ROMVERSION_PALFINAL:
|
||||
offset = 0x28910;
|
||||
break;
|
||||
case ROMVERSION_JPNFINAL:
|
||||
offset = 0x28800;
|
||||
break;
|
||||
}
|
||||
|
||||
uint32_t *offsets = (uint32_t *) &data[offset];
|
||||
int i = 0;
|
||||
|
||||
while (1) {
|
||||
uint32_t curr = srctoh32(offsets[i]);
|
||||
uint32_t next = srctoh32(offsets[i + 1]);
|
||||
|
||||
if (next == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (curr) {
|
||||
extract_file(i, curr, next - curr);
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
free(data);
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "common.h"
|
||||
|
||||
struct n64fontchar {
|
||||
uint8_t index;
|
||||
int8_t baseline;
|
||||
uint8_t height;
|
||||
uint8_t width;
|
||||
int32_t kerningindex;
|
||||
uint32_t pixeldata;
|
||||
};
|
||||
|
||||
struct hostfontchar {
|
||||
uint8_t index;
|
||||
int8_t baseline;
|
||||
uint8_t height;
|
||||
uint8_t width;
|
||||
int32_t kerningindex;
|
||||
uintptr_t pixeldata;
|
||||
};
|
||||
|
||||
struct n64fontcharjpn {
|
||||
uint16_t index;
|
||||
int8_t baseline;
|
||||
uint8_t height;
|
||||
uint8_t width;
|
||||
int16_t kerningindex;
|
||||
uint32_t pixeldata;
|
||||
};
|
||||
|
||||
struct hostfontcharjpn {
|
||||
uint16_t index;
|
||||
int8_t baseline;
|
||||
uint8_t height;
|
||||
uint8_t width;
|
||||
int16_t kerningindex;
|
||||
uintptr_t pixeldata;
|
||||
};
|
||||
|
||||
static void extract_font(const char *filename, uint32_t romoffset, size_t srclen, int num_chars)
|
||||
{
|
||||
size_t dstlen = srclen - (num_chars * sizeof(struct n64fontchar)) + (num_chars * sizeof(struct hostfontchar)) + 0x20;
|
||||
uint8_t *src = &g_Rom[romoffset];
|
||||
uint8_t *dst = calloc(1, dstlen);
|
||||
|
||||
// Kerning table
|
||||
int32_t *src_kerning_table = (int32_t *) src;
|
||||
int32_t *dst_kerning_table = (int32_t *) dst;
|
||||
|
||||
for (int i = 0; i < 13 * 13; i++) {
|
||||
dst_kerning_table[i] = srctodst32(src_kerning_table[i]);
|
||||
}
|
||||
|
||||
uint32_t src_offset = ALIGN(13 * 13 * 4, sizeof(uint32_t));
|
||||
uint32_t dst_offset = ALIGN(13 * 13 * 4, sizeof(uintptr_t));
|
||||
|
||||
// Character table
|
||||
if (g_RomVersion == ROMVERSION_JPNFINAL) {
|
||||
struct n64fontcharjpn *src_char_table = (struct n64fontcharjpn *) &src[src_offset];
|
||||
struct hostfontcharjpn *dst_char_table = (struct hostfontcharjpn *) &dst[dst_offset];
|
||||
uint32_t 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];
|
||||
uint32_t 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);
|
||||
}
|
||||
|
||||
// Pixel data
|
||||
size_t len = srclen - src_offset;
|
||||
|
||||
memcpy(&dst[dst_offset], &src[src_offset], len);
|
||||
|
||||
dst_offset = ALIGN16(dst_offset + len);
|
||||
|
||||
// Write it
|
||||
char outfilename[1024];
|
||||
sprintf(outfilename, "%s/fonts/%s.bin", g_OutPath, filename);
|
||||
|
||||
FILE *fp = openfile(outfilename);
|
||||
fwrite(dst, dst_offset, 1, fp);
|
||||
fclose(fp);
|
||||
|
||||
free(dst);
|
||||
}
|
||||
|
||||
struct fontdef {
|
||||
const char *name;
|
||||
uint32_t offsets[3];
|
||||
int pal_extra_chars;
|
||||
};
|
||||
|
||||
void extract_fonts(void)
|
||||
{
|
||||
struct fontdef defs[] = {
|
||||
// ntsc pal jpn
|
||||
{"bankgothic", {0x7f2390, 0x7ddb90, 0x7e1a20}, 0},
|
||||
{"zurich", {0x7f4930, 0x7e0130, 0x7e3fc0}, 0},
|
||||
{"tahoma", {0x7f7860, 0x7e3060, 0x7e6ef0}, 0},
|
||||
{"numeric", {0x7f8b20, 0x7e4320, 0x7e81b0}, 0},
|
||||
{"handelgothicsm", {0x7f9d30, 0x7e5530, 0x7e93c0}, 1},
|
||||
{"handelgothicxs", {0x7fbfb0, 0x7e87b0, 0x7ec640}, 1},
|
||||
{"handelgothicmd", {0x7fdd80, 0x7eae20, 0x7eecb0}, 1},
|
||||
{"handelgothiclg", {0x8008e0, 0x7eee70, 0x7f2d00}, 0},
|
||||
{"ocramd", {0x803da0, 0x7f2330, 0x7f61c0}, 0},
|
||||
{"ocralg", {0x806ac0, 0x7f5050, 0x7f8ee0}, 0},
|
||||
{"end", {0x80a250, 0x7f87e0, 0x7fc670}, 0},
|
||||
};
|
||||
|
||||
int index = 0;
|
||||
|
||||
switch (g_RomVersion) {
|
||||
case ROMVERSION_NTSC10:
|
||||
case ROMVERSION_NTSCFINAL:
|
||||
index = 0;
|
||||
break;
|
||||
case ROMVERSION_PALFINAL:
|
||||
index = 1;
|
||||
break;
|
||||
case ROMVERSION_JPNFINAL:
|
||||
index = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
for (int i = 0; i < ARRAYCOUNT(defs) - 1; i++) {
|
||||
int num_chars = g_RomVersion == ROMVERSION_PALFINAL && defs[i].pal_extra_chars ? 135 : 94;
|
||||
size_t len = defs[i + 1].offsets[index] - defs[i].offsets[index];
|
||||
extract_font(defs[i].name, defs[i].offsets[index], len, num_chars);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "common.h"
|
||||
|
||||
static void extract_jpnfont(const char *filename, uint32_t romoffset, size_t len)
|
||||
{
|
||||
char outfilename[1024];
|
||||
sprintf(outfilename, "%s/%s.bin", g_OutPath, filename);
|
||||
|
||||
FILE *fp = openfile(outfilename);
|
||||
fwrite(&g_Rom[romoffset], len, 1, fp);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
void extract_jpnfonts(void)
|
||||
{
|
||||
switch (g_RomVersion) {
|
||||
case ROMVERSION_NTSC10:
|
||||
case ROMVERSION_NTSCFINAL:
|
||||
extract_jpnfont("fontjpnsingle", 0x194440, 0xb020);
|
||||
extract_jpnfont("fontjpnmulti", 0x19fb40, 0x1a80);
|
||||
break;
|
||||
case ROMVERSION_PALFINAL:
|
||||
extract_jpnfont("fontjpnsingle", 0x17fc40, 0xb010);
|
||||
extract_jpnfont("fontjpnmulti", 0x18b340, 0x1a80);
|
||||
break;
|
||||
case ROMVERSION_JPNFINAL:
|
||||
extract_jpnfont("fontjpn", 0x178c40, 0x17920);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "common.h"
|
||||
|
||||
struct texture {
|
||||
uint32_t soundsurfacetype : 4;
|
||||
uint32_t surfacetype : 4;
|
||||
uint32_t dataoffset : 24;
|
||||
uint32_t unk04;
|
||||
};
|
||||
|
||||
static void extract_textures_data(uint32_t romoffset, size_t len)
|
||||
{
|
||||
char outfilename[1024];
|
||||
sprintf(outfilename, "%s/textures_data.bin", g_OutPath);
|
||||
|
||||
FILE *fp = openfile(outfilename);
|
||||
fwrite(&g_Rom[romoffset], len, 1, fp);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
static void extract_textures_table(uint32_t romoffset, size_t len)
|
||||
{
|
||||
int num_textures = len / sizeof(struct texture);
|
||||
uint8_t *dst = calloc(1, len);
|
||||
|
||||
struct texture *n64texes = (struct texture *) &g_Rom[romoffset];
|
||||
struct texture *hosttexes = (struct texture *) dst;
|
||||
|
||||
for (int i = 0; i < num_textures; i++) {
|
||||
hosttexes[i].soundsurfacetype = n64texes[i].soundsurfacetype;
|
||||
hosttexes[i].surfacetype = n64texes[i].surfacetype;
|
||||
hosttexes[i].dataoffset = srctodst32(n64texes[i].dataoffset);
|
||||
hosttexes[i].unk04 = 0;
|
||||
}
|
||||
|
||||
// Write it
|
||||
char outfilename[1024];
|
||||
sprintf(outfilename, "%s/textures_table.bin", g_OutPath);
|
||||
|
||||
FILE *fp = openfile(outfilename);
|
||||
fwrite(dst, len, 1, fp);
|
||||
fclose(fp);
|
||||
|
||||
free(dst);
|
||||
}
|
||||
|
||||
void extract_textures(void)
|
||||
{
|
||||
uint32_t data_offset = 0;
|
||||
uint32_t table_offset = 0;
|
||||
uint32_t end = 0;
|
||||
|
||||
switch (g_RomVersion) {
|
||||
case ROMVERSION_NTSC10:
|
||||
case ROMVERSION_NTSCFINAL:
|
||||
data_offset = 0x1d65f40;
|
||||
table_offset = 0x1ff7ca0;
|
||||
end = 0x1ffea20;
|
||||
break;
|
||||
case ROMVERSION_PALFINAL:
|
||||
data_offset = 0x1d5ca20;
|
||||
table_offset = 0x1fee780;
|
||||
end = 0x1ff5500;
|
||||
break;
|
||||
case ROMVERSION_JPNFINAL:
|
||||
data_offset = 0x1d61f90;
|
||||
table_offset = 0x1ff68f0;
|
||||
end = 0x1ffd6b0;
|
||||
break;
|
||||
}
|
||||
|
||||
extract_textures_data(data_offset, table_offset - data_offset);
|
||||
extract_textures_table(table_offset, end - table_offset);
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "common.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 {
|
||||
int16_t x;
|
||||
int16_t y;
|
||||
int16_t z;
|
||||
uint8_t flags;
|
||||
uint8_t colour;
|
||||
int16_t s;
|
||||
int16_t t;
|
||||
};
|
||||
|
||||
uint32_t m_Segments[16];
|
||||
uint8_t m_Seen[1024];
|
||||
uint32_t m_SrcVtxOffset;
|
||||
uint32_t m_DstVtxOffset;
|
||||
|
||||
void gbi_reset(void)
|
||||
{
|
||||
for (int i = 0; i < ARRAYCOUNT(m_Segments); i++) {
|
||||
m_Segments[i] = 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < ARRAYCOUNT(m_Seen); i++) {
|
||||
m_Seen[i] = 0;
|
||||
}
|
||||
|
||||
m_SrcVtxOffset = 0;
|
||||
m_DstVtxOffset = 0;
|
||||
}
|
||||
|
||||
void gbi_set_segment(int segment, uint32_t offset)
|
||||
{
|
||||
m_Segments[segment] = offset;
|
||||
}
|
||||
|
||||
void gbi_set_vtx(uint32_t src_offset, uint32_t dst_offset)
|
||||
{
|
||||
m_SrcVtxOffset = src_offset;
|
||||
m_DstVtxOffset = dst_offset;
|
||||
}
|
||||
|
||||
static void gbi_convert_col(uint8_t *dst, uint32_t dstpos, int count)
|
||||
{
|
||||
for (int i = 0; i < count; i++) {
|
||||
int index = dstpos / 4;
|
||||
|
||||
if (!m_Seen[index]) {
|
||||
uint32_t *col = (uint32_t *) &dst[dstpos];
|
||||
|
||||
*col = srctodst32(*col);
|
||||
|
||||
m_Seen[index] = 1;
|
||||
}
|
||||
|
||||
dstpos += sizeof(uint32_t);
|
||||
}
|
||||
}
|
||||
|
||||
static void gbi_convert_vtx(uint8_t *dst, uint32_t dstpos, int count)
|
||||
{
|
||||
for (int i = 0; i < count; i++) {
|
||||
int index = dstpos / 4;
|
||||
|
||||
if (!m_Seen[index]) {
|
||||
struct vtx *vtx = (struct vtx *) &dst[dstpos];
|
||||
|
||||
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);
|
||||
|
||||
m_Seen[index] = 1;
|
||||
}
|
||||
|
||||
dstpos += 12;
|
||||
}
|
||||
}
|
||||
|
||||
#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_HAS_ADDR(cmd) CMD_IS_VTX(cmd) \
|
||||
|| CMD_IS_COL(cmd) \
|
||||
|| CMD_IS_MOVEWORD(cmd)
|
||||
|
||||
static void gbi_convert_vtx_by_cmd(uint64_t cmd, uint8_t *dst)
|
||||
{
|
||||
uint8_t segment = cmd & 0xff000000;
|
||||
uint8_t offset = cmd & 0x00ffffff;
|
||||
uint32_t num_bytes = (cmd >> 32) & 0xffff;
|
||||
int num_vertices = num_bytes / 12;
|
||||
|
||||
if (segment == 5) {
|
||||
uint32_t dst_offset = offset - m_SrcVtxOffset + m_DstVtxOffset;
|
||||
gbi_convert_vtx(dst, dst_offset, num_vertices);
|
||||
} else {
|
||||
gbi_convert_vtx(dst, m_Segments[segment] + offset, num_vertices);
|
||||
}
|
||||
}
|
||||
|
||||
static void gbi_convert_col_by_cmd(uint64_t cmd, uint8_t *dst)
|
||||
{
|
||||
uint8_t segment = cmd & 0xff000000;
|
||||
uint8_t offset = cmd & 0x00ffffff;
|
||||
uint32_t num_bytes = (cmd >> 32) & 0xffff;
|
||||
int num_colours = num_bytes / 4;
|
||||
|
||||
if (segment == 5) {
|
||||
uint32_t dst_offset = offset - m_SrcVtxOffset + m_DstVtxOffset;
|
||||
gbi_convert_col(dst, dst_offset, num_colours);
|
||||
} else {
|
||||
gbi_convert_col(dst, m_Segments[segment] + offset, num_colours);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 uint64_t gbi_rewrite_addr(uint64_t cmd)
|
||||
{
|
||||
uint8_t segment = cmd & 0xff000000;
|
||||
uint8_t offset = cmd & 0x00ffffff;
|
||||
|
||||
if (segment == 5) {
|
||||
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;
|
||||
}
|
||||
|
||||
uint32_t gbi_convert_gdl(uint8_t *dst, uint32_t dstpos, uint8_t *src, uint32_t srcpos)
|
||||
{
|
||||
dstpos = ALIGN8(dstpos);
|
||||
|
||||
uint64_t *n64_cmd = (uint64_t *) &src[srcpos];
|
||||
uint64_t *host_cmd = (uint64_t *) &dst[dstpos];
|
||||
uint64_t cmd;
|
||||
|
||||
do {
|
||||
cmd = srctoh64(*n64_cmd);
|
||||
|
||||
#if HOST_DWORDS_PER_CMD == 2
|
||||
if (CMD_HAS_ADDR(cmd)) {
|
||||
cmd = gbi_rewrite_addr(cmd);
|
||||
host_cmd[0] = htodst64(cmd & 0xffffffff00000000);
|
||||
host_cmd[1] = htodst64(cmd & 0x00000000ffffffff);
|
||||
} else {
|
||||
host_cmd[0] = htodst64(cmd);
|
||||
host_cmd[1] = 0;
|
||||
}
|
||||
#else
|
||||
host_cmd[0] = htodst64(cmd);
|
||||
#endif
|
||||
dstpos += sizeof(*host_cmd) * HOST_DWORDS_PER_CMD;
|
||||
|
||||
if (CMD_IS_VTX(cmd)) {
|
||||
gbi_convert_vtx_by_cmd(cmd, dst);
|
||||
} else if (CMD_IS_COL(cmd)) {
|
||||
gbi_convert_col_by_cmd(cmd, dst);
|
||||
}
|
||||
|
||||
host_cmd += HOST_DWORDS_PER_CMD;
|
||||
n64_cmd++;
|
||||
} while (!CMD_IS_ENDDL(cmd));
|
||||
|
||||
return dstpos;
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "common.h"
|
||||
|
||||
#define ROM_SIZE (1024 * 1024 * 32)
|
||||
|
||||
uint8_t *g_Rom = NULL;
|
||||
enum romversion g_RomVersion = 0;
|
||||
char g_OutPath[1024] = {'\0'};
|
||||
|
||||
void extract_anims(void);
|
||||
void extract_audio(void);
|
||||
void extract_banners(void);
|
||||
void extract_files(void);
|
||||
void extract_fonts(void);
|
||||
void extract_jpnfonts(void);
|
||||
void extract_textures(void);
|
||||
|
||||
/**
|
||||
* We allow modded ROMs to be used, so we can't simply compare the ROM checksum.
|
||||
*/
|
||||
static enum romversion identify_rom_version(uint8_t *rom)
|
||||
{
|
||||
char game_code[5];
|
||||
game_code[0] = rom[0x3b];
|
||||
game_code[1] = rom[0x3c];
|
||||
game_code[2] = rom[0x3d];
|
||||
game_code[3] = rom[0x3e];
|
||||
game_code[4] = '\0';
|
||||
|
||||
char version_byte = rom[0x3f];
|
||||
|
||||
if (strncmp((char *) &rom[0x20], "Perfect Dark DBGNTSC", 20) == 0) {
|
||||
return ROMVERSION_NTSCBETA;
|
||||
}
|
||||
|
||||
if (strcmp(game_code, "NPDJ") == 0) {
|
||||
return ROMVERSION_JPNFINAL;
|
||||
}
|
||||
|
||||
if (strcmp(game_code, "NPDE") == 0) {
|
||||
if (version_byte == 1) {
|
||||
return ROMVERSION_NTSCFINAL;
|
||||
}
|
||||
|
||||
if (version_byte == 0) {
|
||||
return ROMVERSION_NTSC10;
|
||||
}
|
||||
}
|
||||
|
||||
if (strcmp(game_code, "NPDP") == 0) {
|
||||
if (rom[0x100f] == 0xe0) {
|
||||
return ROMVERSION_PALBETA;
|
||||
}
|
||||
|
||||
if (rom[0x100f] == 0xf0) {
|
||||
return ROMVERSION_PALFINAL;
|
||||
}
|
||||
}
|
||||
|
||||
return ROMVERSION_UNKNOWN;
|
||||
}
|
||||
|
||||
static void flip_pairs(uint8_t *rom)
|
||||
{
|
||||
uint16_t *ptr = (uint16_t *) rom;
|
||||
|
||||
for (int i = 0; i < ROM_SIZE / 2; i++) {
|
||||
ptr[i] = __bswap_16(ptr[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void flip_words(uint8_t *rom)
|
||||
{
|
||||
uint32_t *ptr = (uint32_t *) rom;
|
||||
|
||||
for (int i = 0; i < ROM_SIZE / 4; i++) {
|
||||
ptr[i] = __bswap_32(ptr[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void extract_rom(char *romfile)
|
||||
{
|
||||
FILE *fp = fopen(romfile, "rb");
|
||||
|
||||
if (fp == NULL) {
|
||||
fprintf(stderr, "Unable to open '%s' for reading.\n", romfile);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
fseek(fp, 0, SEEK_END);
|
||||
|
||||
if (ftell(fp) != ROM_SIZE) {
|
||||
fprintf(stderr, "The ROM size is not 32MB. Is this a Perfect Dark ROM?\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
fseek(fp, 0, SEEK_SET);
|
||||
|
||||
g_Rom = malloc(ROM_SIZE);
|
||||
fread(g_Rom, 1, ROM_SIZE, fp);
|
||||
fclose(fp);
|
||||
|
||||
uint32_t magic = (g_Rom[0] << 24) | (g_Rom[1] << 16) | (g_Rom[2] << 8) | g_Rom[3];
|
||||
|
||||
switch (magic) {
|
||||
case 0x80371240:
|
||||
break;
|
||||
case 0x37804012:
|
||||
flip_pairs(g_Rom);
|
||||
break;
|
||||
case 0x40123780:
|
||||
flip_words(g_Rom);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Unable to detect ROM header. Is this an N64 ROM?\n");
|
||||
exit(EXIT_FAILURE);
|
||||
break;
|
||||
}
|
||||
|
||||
g_RomVersion = identify_rom_version(g_Rom);
|
||||
|
||||
if (g_RomVersion == ROMVERSION_NTSCBETA || g_RomVersion == ROMVERSION_PALBETA) {
|
||||
fprintf(stderr, "The beta versions are not supported.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (g_RomVersion == ROMVERSION_UNKNOWN) {
|
||||
fprintf(stderr, "Unable to determine your Perfect Dark version. Is this a Perfect Dark ROM?\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
extract_anims();
|
||||
extract_audio();
|
||||
extract_files();
|
||||
extract_fonts();
|
||||
extract_jpnfonts();
|
||||
extract_textures();
|
||||
extract_banners();
|
||||
|
||||
free(g_Rom);
|
||||
g_Rom = NULL;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char *romfile = NULL;
|
||||
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, "Usage: pd-extract <ROMFILE> [PATH]\n");
|
||||
fprintf(stderr, "Read ROMFILE, writing assets to PATH.\n");
|
||||
fprintf(stderr, "With no PATH, assume \"extracted/\".\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
romfile = argv[1];
|
||||
|
||||
if (argc > 2) {
|
||||
strcpy(g_OutPath, argv[2]);
|
||||
} else {
|
||||
strcpy(g_OutPath, "extracted");
|
||||
}
|
||||
|
||||
if (g_OutPath[strlen(g_OutPath) - 1] == '/') {
|
||||
g_OutPath[strlen(g_OutPath) - 1] = '\0';
|
||||
}
|
||||
|
||||
extract_rom(romfile);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
#include <libgen.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <zlib.h>
|
||||
|
||||
FILE *openfile(char *filename)
|
||||
{
|
||||
char path[1024];
|
||||
struct stat status;
|
||||
|
||||
memcpy(path, filename, strlen(filename));
|
||||
dirname(path);
|
||||
|
||||
while (stat(path, &status) == -1) {
|
||||
// while (mkdir(path, 0755) == -1) {
|
||||
while (mkdir(path) == -1) {
|
||||
dirname(path);
|
||||
}
|
||||
|
||||
memcpy(path, filename, strlen(filename));
|
||||
dirname(path);
|
||||
}
|
||||
|
||||
FILE *fp = fopen(filename, "wb");
|
||||
|
||||
if (fp == NULL) {
|
||||
fprintf(stderr, "Unable to open '%s' for writing\n", filename);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return fp;
|
||||
}
|
||||
|
||||
size_t rzip_get_infsize(uint8_t *src)
|
||||
{
|
||||
if (src[0] != 0x11 || src[1] != 0x73) {
|
||||
fprintf(stderr, "rzip_get_infsize: 1173 not found\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return src[2] << 16 | (src[3] << 8) | src[4];
|
||||
}
|
||||
|
||||
int rzip_inflate(uint8_t *dst, size_t dstlen, uint8_t *src, size_t srclen)
|
||||
{
|
||||
if (src[0] != 0x11 || src[1] != 0x73) {
|
||||
fprintf(stderr, "rzip_inflate: 1173 not found\n");
|
||||
|
||||
for (int i = 0; i < 16; i++) {
|
||||
fprintf(stderr, "%02x ", src[i]);
|
||||
}
|
||||
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
z_stream stream;
|
||||
stream.zalloc = Z_NULL;
|
||||
stream.zfree = Z_NULL;
|
||||
stream.opaque = Z_NULL;
|
||||
stream.avail_in = srclen - 5;
|
||||
stream.next_in = &src[5];
|
||||
stream.avail_out = dstlen;
|
||||
stream.next_out = dst;
|
||||
|
||||
inflateInit2(&stream, -15);
|
||||
int ret = inflate(&stream, Z_FINISH);
|
||||
inflateEnd(&stream);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int rzip_deflate(uint8_t *dst, size_t *dstlen, uint8_t *src, size_t srclen)
|
||||
{
|
||||
dst[0] = 0x11;
|
||||
dst[1] = 0x73;
|
||||
dst[2] = (srclen >> 16) & 0xff;
|
||||
dst[3] = (srclen >> 8) & 0xff;
|
||||
dst[4] = srclen & 0xff;
|
||||
|
||||
*dstlen = *dstlen - 5;
|
||||
|
||||
z_stream stream;
|
||||
stream.zalloc = Z_NULL;
|
||||
stream.zfree = Z_NULL;
|
||||
stream.opaque = Z_NULL;
|
||||
stream.avail_in = srclen;
|
||||
stream.next_in = src;
|
||||
stream.avail_out = *dstlen;
|
||||
stream.next_out = &dst[5];
|
||||
|
||||
deflateInit2(&stream, 9, Z_DEFLATED, -15, 9, Z_DEFAULT_STRATEGY);
|
||||
int ret = deflate(&stream, Z_FINISH);
|
||||
deflateEnd(&stream);
|
||||
|
||||
*dstlen = stream.next_out - dst;
|
||||
|
||||
return ret;
|
||||
}
|
||||
Reference in new issue
Block a user