portx64: added pd-extract source

This commit is contained in:
Raf committed 2024-05-26 16:10:24 +08:00
1 parent 7c6508af28
commit 3242105ef8
17 files changed
+3557

No files matched your search

+71
View File
@@ -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
+77
View File
@@ -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);
}
+485
View File
@@ -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);
}
+39
View File
@@ -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);
}
+14
View File
@@ -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);
}
+500
View File
@@ -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);
}
+110
View File
@@ -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);
}
+952
View File
@@ -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);
}
+357
View File
@@ -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);
}
+122
View File
@@ -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);
}
+100
View File
@@ -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);
}
+157
View File
@@ -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);
}
}
+32
View File
@@ -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;
}
}
+76
View File
@@ -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);
}
+189
View File
@@ -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;
}
+173
View File
@@ -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;
}
+103
View File
@@ -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;
}