mirror of
https://github.com/izzy2lost/2ship2harkinian-Android.git
synced 2026-06-19 01:20:08 -07:00
Fado, part 2 (#1012)
* Makefile adjustments and additions to build fado * Fix typo in makefile * Fix it, maybe? * Update build tools * Update build tools * rm cfg files
This commit is contained in:
+53
-87
@@ -12,45 +12,41 @@
|
||||
#define ROM_SEG_START_SUFFIX ".rom_start"
|
||||
#define ROM_SEG_END_SUFFIX ".rom_end"
|
||||
|
||||
struct RomSegment
|
||||
{
|
||||
const char *name;
|
||||
const void *data;
|
||||
struct RomSegment {
|
||||
const char* name;
|
||||
const void* data;
|
||||
int size;
|
||||
int romStart;
|
||||
int romEnd;
|
||||
};
|
||||
|
||||
static struct RomSegment *g_romSegments = NULL;
|
||||
static struct RomSegment* g_romSegments = NULL;
|
||||
static int g_romSegmentsCount = 0;
|
||||
static int g_romSize;
|
||||
|
||||
static bool parse_number(const char *str, int *num)
|
||||
{
|
||||
char *endptr;
|
||||
static bool parse_number(const char* str, int* num) {
|
||||
char* endptr;
|
||||
long int n = strtol(str, &endptr, 0);
|
||||
*num = n;
|
||||
return endptr > str;
|
||||
}
|
||||
|
||||
static unsigned int round_up(unsigned int num, unsigned int multiple)
|
||||
{
|
||||
static unsigned int round_up(unsigned int num, unsigned int multiple) {
|
||||
num += multiple - 1;
|
||||
return num / multiple * multiple;
|
||||
}
|
||||
|
||||
static char *sprintf_alloc(const char *fmt, ...)
|
||||
{
|
||||
static char* sprintf_alloc(const char* fmt, ...) {
|
||||
va_list args;
|
||||
int size;
|
||||
char *buffer;
|
||||
char* buffer;
|
||||
|
||||
va_start(args, fmt);
|
||||
size = vsnprintf(NULL, 0, fmt, args) + 1;
|
||||
va_end(args);
|
||||
|
||||
buffer = malloc(size);
|
||||
|
||||
|
||||
va_start(args, fmt);
|
||||
vsprintf(buffer, fmt, args);
|
||||
va_end(args);
|
||||
@@ -58,8 +54,7 @@ static char *sprintf_alloc(const char *fmt, ...)
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static struct RomSegment *add_rom_segment(const char *name)
|
||||
{
|
||||
static struct RomSegment* add_rom_segment(const char* name) {
|
||||
int index = g_romSegmentsCount;
|
||||
|
||||
g_romSegmentsCount++;
|
||||
@@ -71,50 +66,44 @@ static struct RomSegment *add_rom_segment(const char *name)
|
||||
return &g_romSegments[index];
|
||||
}
|
||||
|
||||
static void find_segment_info(struct Elf32 *elf, struct RomSegment *segment)
|
||||
{
|
||||
static void find_segment_info(struct Elf32* elf, struct RomSegment* segment) {
|
||||
int i;
|
||||
char *romStartSymName = sprintf_alloc("_%sSegmentRomStart", segment->name);
|
||||
char *romEndSymName = sprintf_alloc("_%sSegmentRomEnd", segment->name);
|
||||
char* romStartSymName = sprintf_alloc("_%sSegmentRomStart", segment->name);
|
||||
char* romEndSymName = sprintf_alloc("_%sSegmentRomEnd", segment->name);
|
||||
|
||||
segment->romStart = -1;
|
||||
segment->romEnd = -1;
|
||||
|
||||
// TODO: use a hashmap for this instead of an O(n) loop
|
||||
for (i = 0; i < elf->numsymbols; i++)
|
||||
{
|
||||
for (i = 0; i < elf->numsymbols; i++) {
|
||||
struct Elf32_Symbol sym;
|
||||
|
||||
|
||||
if (!elf32_get_symbol(elf, &sym, i))
|
||||
util_fatal_error("invalid or corrupt ELF file");
|
||||
|
||||
if (strcmp(sym.name, romStartSymName) == 0)
|
||||
{
|
||||
if (strcmp(sym.name, romStartSymName) == 0) {
|
||||
segment->romStart = sym.value;
|
||||
if (segment->romEnd != -1)
|
||||
break;
|
||||
}
|
||||
else if (strcmp(sym.name, romEndSymName) == 0)
|
||||
{
|
||||
} else if (strcmp(sym.name, romEndSymName) == 0) {
|
||||
segment->romEnd = sym.value;
|
||||
if (segment->romStart != -1)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (segment->romStart == -1)
|
||||
util_fatal_error("ROM start address of %s is not defined\n", segment->name);
|
||||
if (segment->romEnd == -1)
|
||||
util_fatal_error("ROM end address of %s is not defined\n", segment->name);
|
||||
|
||||
|
||||
free(romStartSymName);
|
||||
free(romEndSymName);
|
||||
}
|
||||
|
||||
static void parse_input_file(const char *filename)
|
||||
{
|
||||
static void parse_input_file(const char* filename) {
|
||||
struct Elf32 elf;
|
||||
const void *data;
|
||||
const void* data;
|
||||
size_t size;
|
||||
int i;
|
||||
|
||||
@@ -125,45 +114,40 @@ static void parse_input_file(const char *filename)
|
||||
|
||||
// get ROM segments
|
||||
// sections of type SHT_PROGBITS and whose name is ..secname are considered ROM segments
|
||||
for (i = 0; i < elf.shnum; i++)
|
||||
{
|
||||
for (i = 0; i < elf.shnum; i++) {
|
||||
struct Elf32_Section sec;
|
||||
struct RomSegment *segment;
|
||||
struct RomSegment* segment;
|
||||
|
||||
if (!elf32_get_section(&elf, &sec, i))
|
||||
util_fatal_error("invalid or corrupt ELF file");
|
||||
if (sec.type == SHT_PROGBITS && sec.name[0] == '.' && sec.name[1] == '.'
|
||||
// HACK! ld sometimes marks NOLOAD sections as SHT_PROGBITS for no apparent reason,
|
||||
// so we must ignore the ..secname.bss sections explicitly
|
||||
&& strchr(sec.name + 2, '.') == NULL)
|
||||
{
|
||||
|
||||
if (sec.type == SHT_PROGBITS && sec.name[0] == '.' &&
|
||||
sec.name[1] == '.'
|
||||
// HACK! ld sometimes marks NOLOAD sections as SHT_PROGBITS for no apparent reason,
|
||||
// so we must ignore the ..secname.bss sections explicitly
|
||||
&& strchr(sec.name + 2, '.') == NULL) {
|
||||
|
||||
segment = add_rom_segment(sec.name + 2);
|
||||
find_segment_info(&elf, segment);
|
||||
segment->data = elf.data + sec.offset;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// find ROM size
|
||||
for (i = 0; i < elf.numsymbols; i++)
|
||||
{
|
||||
for (i = 0; i < elf.numsymbols; i++) {
|
||||
struct Elf32_Symbol sym;
|
||||
|
||||
if (!elf32_get_symbol(&elf, &sym, i))
|
||||
util_fatal_error("invalid or corrupt ELF file");
|
||||
if (strcmp(sym.name, "_RomSize") == 0)
|
||||
{
|
||||
if (strcmp(sym.name, "_RomSize") == 0) {
|
||||
g_romSize = sym.value;
|
||||
goto got_rom_size;
|
||||
}
|
||||
}
|
||||
util_fatal_error("could not find symbol _RomSize");
|
||||
got_rom_size:
|
||||
got_rom_size:
|
||||
|
||||
// verify segment info
|
||||
for (i = 0; i < g_romSegmentsCount; i++)
|
||||
{
|
||||
for (i = 0; i < g_romSegmentsCount; i++) {
|
||||
if (g_romSegments[i].romStart == -1)
|
||||
util_fatal_error("segment %s has no ROM start address defined.", g_romSegments[i].name);
|
||||
if (g_romSegments[i].romEnd == -1)
|
||||
@@ -172,23 +156,21 @@ static void parse_input_file(const char *filename)
|
||||
}
|
||||
|
||||
// Writes the N64 ROM, padding the file size to a multiple of 1 MiB
|
||||
static void write_rom_file(const char *filename, int cicType)
|
||||
{
|
||||
static void write_rom_file(const char* filename, int cicType) {
|
||||
size_t fileSize = round_up(g_romSize, 0x100000);
|
||||
uint8_t *buffer = calloc(fileSize, 1);
|
||||
uint8_t* buffer = calloc(fileSize, 1);
|
||||
int i;
|
||||
uint32_t chksum[2];
|
||||
|
||||
// write segments
|
||||
for (i = 0; i < g_romSegmentsCount; i++)
|
||||
{
|
||||
for (i = 0; i < g_romSegmentsCount; i++) {
|
||||
int size = g_romSegments[i].romEnd - g_romSegments[i].romStart;
|
||||
|
||||
memcpy(buffer + g_romSegments[i].romStart, g_romSegments[i].data, size);
|
||||
}
|
||||
|
||||
// pad the remaining space with 0xFF
|
||||
for (i = g_romSize; i < (int) fileSize; i++)
|
||||
for (i = g_romSize; i < (int)fileSize; i++)
|
||||
buffer[i] = 0xFF;
|
||||
|
||||
// write checksum
|
||||
@@ -201,67 +183,51 @@ static void write_rom_file(const char *filename, int cicType)
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
static void usage(const char *execname)
|
||||
{
|
||||
static void usage(const char* execname) {
|
||||
printf("usage: %s\n", execname);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int main(int argc, char** argv) {
|
||||
int i;
|
||||
const char *inputFileName = NULL;
|
||||
const char *outputFileName = NULL;
|
||||
const char* inputFileName = NULL;
|
||||
const char* outputFileName = NULL;
|
||||
int cicType = -1;
|
||||
|
||||
for (i = 1; i < argc; i++)
|
||||
{
|
||||
if (argv[i][0] == '-')
|
||||
{
|
||||
if (strcmp(argv[i], "-cic") == 0)
|
||||
{
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (argv[i][0] == '-') {
|
||||
if (strcmp(argv[i], "-cic") == 0) {
|
||||
i++;
|
||||
if (i >= argc || !parse_number(argv[i], &cicType))
|
||||
{
|
||||
if (i >= argc || !parse_number(argv[i], &cicType)) {
|
||||
fputs("error: expected number after -cic\n", stderr);
|
||||
goto bad_args;
|
||||
}
|
||||
}
|
||||
else if (strcmp(argv[i], "-help") == 0)
|
||||
{
|
||||
} else if (strcmp(argv[i], "-help") == 0) {
|
||||
usage(argv[0]);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
fprintf(stderr, "unknown option %s\n", argv[i]);
|
||||
goto bad_args;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
if (inputFileName == NULL)
|
||||
inputFileName = argv[i];
|
||||
else if (outputFileName == NULL)
|
||||
outputFileName = argv[i];
|
||||
else
|
||||
{
|
||||
else {
|
||||
fputs("error: too many parameters specified\n", stderr);
|
||||
goto bad_args;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (inputFileName == NULL)
|
||||
{
|
||||
if (inputFileName == NULL) {
|
||||
fputs("error: no input file specified\n", stderr);
|
||||
goto bad_args;
|
||||
}
|
||||
if (outputFileName == NULL)
|
||||
{
|
||||
if (outputFileName == NULL) {
|
||||
fputs("error: no output file specified\n", stderr);
|
||||
goto bad_args;
|
||||
}
|
||||
if (cicType == -1)
|
||||
{
|
||||
if (cicType == -1) {
|
||||
fputs("error: no CIC type specified\n", stderr);
|
||||
goto bad_args;
|
||||
}
|
||||
|
||||
+68
-93
@@ -5,36 +5,23 @@
|
||||
|
||||
#include "elf32.h"
|
||||
|
||||
static uint16_t read16_le(const uint8_t *data)
|
||||
{
|
||||
return data[0] << 0
|
||||
| data[1] << 8;
|
||||
static uint16_t read16_le(const uint8_t* data) {
|
||||
return data[0] << 0 | data[1] << 8;
|
||||
}
|
||||
|
||||
static uint32_t read32_le(const uint8_t *data)
|
||||
{
|
||||
return data[0] << 0
|
||||
| data[1] << 8
|
||||
| data[2] << 16
|
||||
| data[3] << 24;
|
||||
static uint32_t read32_le(const uint8_t* data) {
|
||||
return data[0] << 0 | data[1] << 8 | data[2] << 16 | data[3] << 24;
|
||||
}
|
||||
|
||||
static uint16_t read16_be(const uint8_t *data)
|
||||
{
|
||||
return data[0] << 8
|
||||
| data[1] << 0;
|
||||
static uint16_t read16_be(const uint8_t* data) {
|
||||
return data[0] << 8 | data[1] << 0;
|
||||
}
|
||||
|
||||
static uint32_t read32_be(const uint8_t *data)
|
||||
{
|
||||
return data[0] << 24
|
||||
| data[1] << 16
|
||||
| data[2] << 8
|
||||
| data[3] << 0;
|
||||
static uint32_t read32_be(const uint8_t* data) {
|
||||
return data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3] << 0;
|
||||
}
|
||||
|
||||
static const void *get_section_header(struct Elf32 *e, int secnum)
|
||||
{
|
||||
static const void* get_section_header(struct Elf32* e, int secnum) {
|
||||
size_t secoffset = e->shoff + secnum * 0x28;
|
||||
|
||||
if (secnum >= e->shnum || secoffset >= e->dataSize)
|
||||
@@ -42,76 +29,70 @@ static const void *get_section_header(struct Elf32 *e, int secnum)
|
||||
return e->data + secoffset;
|
||||
}
|
||||
|
||||
static const void *get_section_contents(struct Elf32 *e, int secnum)
|
||||
{
|
||||
static const void* get_section_contents(struct Elf32* e, int secnum) {
|
||||
size_t secoffset = e->shoff + secnum * 0x28;
|
||||
size_t dataoffset;
|
||||
|
||||
|
||||
if (secnum >= e->shnum || secoffset >= e->dataSize)
|
||||
return NULL;
|
||||
dataoffset = e->read32(e->data + secoffset + 0x10);
|
||||
return e->data + dataoffset;
|
||||
}
|
||||
|
||||
static bool verify_magic(const uint8_t *data)
|
||||
{
|
||||
static bool verify_magic(const uint8_t* data) {
|
||||
return (data[0] == 0x7F && data[1] == 'E' && data[2] == 'L' && data[3] == 'F');
|
||||
}
|
||||
|
||||
bool elf32_init(struct Elf32 *e, const void *data, size_t size)
|
||||
{
|
||||
bool elf32_init(struct Elf32* e, const void* data, size_t size) {
|
||||
unsigned int i;
|
||||
|
||||
e->data = data;
|
||||
e->dataSize = size;
|
||||
|
||||
if (size < 0x34)
|
||||
return false; // not big enough for header
|
||||
return false; // not big enough for header
|
||||
|
||||
if (!verify_magic(e->data))
|
||||
return false;
|
||||
|
||||
if (e->data[4] != 1)
|
||||
return false; // must be 32-bit
|
||||
return false; // must be 32-bit
|
||||
|
||||
e->endian = e->data[5];
|
||||
|
||||
switch (e->endian)
|
||||
{
|
||||
case 1:
|
||||
e->read16 = read16_le;
|
||||
e->read32 = read32_le;
|
||||
break;
|
||||
case 2:
|
||||
e->read16 = read16_be;
|
||||
e->read32 = read32_be;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
switch (e->endian) {
|
||||
case 1:
|
||||
e->read16 = read16_le;
|
||||
e->read32 = read32_le;
|
||||
break;
|
||||
case 2:
|
||||
e->read16 = read16_be;
|
||||
e->read32 = read32_be;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
e->type = e->read16(e->data + 0x10);
|
||||
e->machine = e->read16(e->data + 0x12);
|
||||
e->version = e->data[6];
|
||||
e->entry = e->read32(e->data + 0x18);
|
||||
e->phoff = e->read32(e->data + 0x1C);
|
||||
e->shoff = e->read32(e->data + 0x20);
|
||||
e->ehsize = e->read16(e->data + 0x28);
|
||||
e->type = e->read16(e->data + 0x10);
|
||||
e->machine = e->read16(e->data + 0x12);
|
||||
e->version = e->data[6];
|
||||
e->entry = e->read32(e->data + 0x18);
|
||||
e->phoff = e->read32(e->data + 0x1C);
|
||||
e->shoff = e->read32(e->data + 0x20);
|
||||
e->ehsize = e->read16(e->data + 0x28);
|
||||
e->phentsize = e->read16(e->data + 0x2A);
|
||||
e->phnum = e->read16(e->data + 0x2C);
|
||||
e->phnum = e->read16(e->data + 0x2C);
|
||||
e->shentsize = e->read16(e->data + 0x2E);
|
||||
e->shnum = e->read16(e->data + 0x30);
|
||||
e->shstrndx = e->read16(e->data + 0x32);
|
||||
|
||||
e->shnum = e->read16(e->data + 0x30);
|
||||
e->shstrndx = e->read16(e->data + 0x32);
|
||||
|
||||
// find symbol table section
|
||||
e->symtabndx = -1;
|
||||
for (i = 0; i < e->shnum; i++)
|
||||
{
|
||||
const uint8_t *sechdr = get_section_header(e, i);
|
||||
for (i = 0; i < e->shnum; i++) {
|
||||
const uint8_t* sechdr = get_section_header(e, i);
|
||||
uint32_t type = e->read32(sechdr + 0x04);
|
||||
|
||||
if (type == SHT_SYMTAB)
|
||||
{
|
||||
|
||||
if (type == SHT_SYMTAB) {
|
||||
e->symtabndx = i;
|
||||
break;
|
||||
}
|
||||
@@ -119,59 +100,53 @@ bool elf32_init(struct Elf32 *e, const void *data, size_t size)
|
||||
|
||||
// find .strtab section
|
||||
e->strtabndx = -1;
|
||||
for (i = 0; i < e->shnum; i++)
|
||||
{
|
||||
const uint8_t *sechdr = get_section_header(e, i);
|
||||
for (i = 0; i < e->shnum; i++) {
|
||||
const uint8_t* sechdr = get_section_header(e, i);
|
||||
uint32_t type = e->read32(sechdr + 0x04);
|
||||
|
||||
if (type == SHT_STRTAB)
|
||||
{
|
||||
const char *strings = get_section_contents(e, e->shstrndx);
|
||||
const char *secname = strings + e->read32(sechdr + 0);
|
||||
|
||||
if (strcmp(secname, ".strtab") == 0)
|
||||
{
|
||||
|
||||
if (type == SHT_STRTAB) {
|
||||
const char* strings = get_section_contents(e, e->shstrndx);
|
||||
const char* secname = strings + e->read32(sechdr + 0);
|
||||
|
||||
if (strcmp(secname, ".strtab") == 0) {
|
||||
e->strtabndx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
e->numsymbols = 0;
|
||||
if (e->symtabndx != -1)
|
||||
{
|
||||
const uint8_t *sechdr = get_section_header(e, e->symtabndx);
|
||||
//const uint8_t *symtab = get_section_contents(e, e->symtabndx);
|
||||
|
||||
if (e->symtabndx != -1) {
|
||||
const uint8_t* sechdr = get_section_header(e, e->symtabndx);
|
||||
// const uint8_t *symtab = get_section_contents(e, e->symtabndx);
|
||||
|
||||
e->numsymbols = e->read32(sechdr + 0x14) / e->read32(sechdr + 0x24);
|
||||
}
|
||||
|
||||
if (e->shoff + e->shstrndx * 0x28 >= e->dataSize)
|
||||
return false;
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool elf32_get_section(struct Elf32 *e, struct Elf32_Section *sec, int secnum)
|
||||
{
|
||||
const uint8_t *sechdr = get_section_header(e, secnum);
|
||||
const char *strings = get_section_contents(e, e->shstrndx);
|
||||
bool elf32_get_section(struct Elf32* e, struct Elf32_Section* sec, int secnum) {
|
||||
const uint8_t* sechdr = get_section_header(e, secnum);
|
||||
const char* strings = get_section_contents(e, e->shstrndx);
|
||||
|
||||
sec->name = strings + e->read32(sechdr + 0);
|
||||
sec->type = e->read32(sechdr + 0x04);
|
||||
sec->flags = e->read32(sechdr + 0x08);
|
||||
sec->addr = e->read32(sechdr + 0x0C);
|
||||
sec->offset = e->read32(sechdr + 0x10);
|
||||
sec->name = strings + e->read32(sechdr + 0);
|
||||
sec->type = e->read32(sechdr + 0x04);
|
||||
sec->flags = e->read32(sechdr + 0x08);
|
||||
sec->addr = e->read32(sechdr + 0x0C);
|
||||
sec->offset = e->read32(sechdr + 0x10);
|
||||
sec->addralign = e->read32(sechdr + 0x20);
|
||||
sec->entsize = e->read32(sechdr + 0x24);
|
||||
sec->entsize = e->read32(sechdr + 0x24);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool elf32_get_symbol(struct Elf32 *e, struct Elf32_Symbol *sym, int symnum)
|
||||
{
|
||||
const uint8_t *sechdr;
|
||||
const uint8_t *symtab;
|
||||
const char *strings;
|
||||
bool elf32_get_symbol(struct Elf32* e, struct Elf32_Symbol* sym, int symnum) {
|
||||
const uint8_t* sechdr;
|
||||
const uint8_t* symtab;
|
||||
const char* strings;
|
||||
int symcount;
|
||||
|
||||
if (e->symtabndx == -1)
|
||||
|
||||
+19
-22
@@ -1,22 +1,22 @@
|
||||
#ifndef _ELF_H_
|
||||
#define _ELF_H_
|
||||
#ifndef ELF32_H
|
||||
#define ELF32_H
|
||||
|
||||
enum
|
||||
{
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
enum {
|
||||
ELF_MACHINE_NONE = 0,
|
||||
ELF_MACHINE_MIPS = 8,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
enum {
|
||||
ELF_TYPE_RELOC = 1,
|
||||
ELF_TYPE_EXEC,
|
||||
ELF_TYPE_SHARED,
|
||||
ELF_TYPE_CORE,
|
||||
};
|
||||
|
||||
struct Elf32
|
||||
{
|
||||
struct Elf32 {
|
||||
uint8_t endian;
|
||||
uint16_t type;
|
||||
uint16_t machine;
|
||||
@@ -34,23 +34,21 @@ struct Elf32
|
||||
int strtabndx;
|
||||
int numsymbols;
|
||||
|
||||
const uint8_t *data;
|
||||
const uint8_t* data;
|
||||
size_t dataSize;
|
||||
uint16_t (*read16)(const uint8_t *);
|
||||
uint32_t (*read32)(const uint8_t *);
|
||||
uint16_t (*read16)(const uint8_t*);
|
||||
uint32_t (*read32)(const uint8_t*);
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
enum {
|
||||
SHT_NULL = 0,
|
||||
SHT_PROGBITS,
|
||||
SHT_SYMTAB,
|
||||
SHT_STRTAB,
|
||||
};
|
||||
|
||||
struct Elf32_Section
|
||||
{
|
||||
const char *name;
|
||||
struct Elf32_Section {
|
||||
const char* name;
|
||||
uint32_t type;
|
||||
uint32_t flags;
|
||||
uint32_t addr;
|
||||
@@ -59,14 +57,13 @@ struct Elf32_Section
|
||||
uint32_t entsize;
|
||||
};
|
||||
|
||||
struct Elf32_Symbol
|
||||
{
|
||||
const char *name;
|
||||
struct Elf32_Symbol {
|
||||
const char* name;
|
||||
uint32_t value;
|
||||
};
|
||||
|
||||
bool elf32_init(struct Elf32 *e, const void *data, size_t size);
|
||||
bool elf32_get_section(struct Elf32 *e, struct Elf32_Section *sec, int secnum);
|
||||
bool elf32_get_symbol(struct Elf32 *e, struct Elf32_Symbol *sym, int symnum);
|
||||
bool elf32_init(struct Elf32* e, const void* data, size_t size);
|
||||
bool elf32_get_section(struct Elf32* e, struct Elf32_Section* sec, int secnum);
|
||||
bool elf32_get_symbol(struct Elf32* e, struct Elf32_Symbol* sym, int symnum);
|
||||
|
||||
#endif
|
||||
|
||||
+103
-141
@@ -12,18 +12,16 @@
|
||||
|
||||
#define ROM_SIZE 0x02000000
|
||||
|
||||
enum InputObjType
|
||||
{
|
||||
enum InputObjType {
|
||||
OBJ_NULL,
|
||||
OBJ_FILE,
|
||||
OBJ_TABLE,
|
||||
};
|
||||
|
||||
struct InputFile
|
||||
{
|
||||
struct InputFile {
|
||||
enum InputObjType type;
|
||||
const char *name;
|
||||
uint8_t *data;
|
||||
const char* name;
|
||||
uint8_t* data;
|
||||
size_t size;
|
||||
unsigned int valign;
|
||||
|
||||
@@ -33,73 +31,58 @@ struct InputFile
|
||||
uint32_t physEnd;
|
||||
};
|
||||
|
||||
static struct InputFile *g_inputFiles = NULL;
|
||||
static struct InputFile* g_inputFiles = NULL;
|
||||
static int g_inputFilesCount = 0;
|
||||
|
||||
static unsigned int round_up(unsigned int num, unsigned int multiple)
|
||||
{
|
||||
static unsigned int round_up(unsigned int num, unsigned int multiple) {
|
||||
num += multiple - 1;
|
||||
return num / multiple * multiple;
|
||||
}
|
||||
|
||||
static bool is_yaz0_header(const uint8_t *data)
|
||||
{
|
||||
return data[0] == 'Y'
|
||||
&& data[1] == 'a'
|
||||
&& data[2] == 'z'
|
||||
&& data[3] == '0';
|
||||
static bool is_yaz0_header(const uint8_t* data) {
|
||||
return data[0] == 'Y' && data[1] == 'a' && data[2] == 'z' && data[3] == '0';
|
||||
}
|
||||
|
||||
static void compute_offsets(void)
|
||||
{
|
||||
static void compute_offsets(void) {
|
||||
size_t physOffset = 0;
|
||||
size_t virtOffset = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < g_inputFilesCount; i++)
|
||||
{
|
||||
for (i = 0; i < g_inputFilesCount; i++) {
|
||||
bool compressed = false;
|
||||
|
||||
if (g_inputFiles[i].type == OBJ_FILE)
|
||||
{
|
||||
if (g_inputFiles[i].type == OBJ_FILE) {
|
||||
if (is_yaz0_header(g_inputFiles[i].data))
|
||||
compressed = true;
|
||||
}
|
||||
else if (g_inputFiles[i].type == OBJ_TABLE)
|
||||
{
|
||||
} else if (g_inputFiles[i].type == OBJ_TABLE) {
|
||||
g_inputFiles[i].size = g_inputFilesCount * 16;
|
||||
}
|
||||
|
||||
virtOffset = round_up(virtOffset, g_inputFiles[i].valign);
|
||||
|
||||
if (g_inputFiles[i].type == OBJ_NULL)
|
||||
{
|
||||
if (g_inputFiles[i].type == OBJ_NULL) {
|
||||
g_inputFiles[i].virtStart = 0;
|
||||
g_inputFiles[i].virtEnd = 0;
|
||||
g_inputFiles[i].virtEnd = 0;
|
||||
g_inputFiles[i].physStart = 0;
|
||||
g_inputFiles[i].physEnd = 0;
|
||||
}
|
||||
else if (compressed)
|
||||
{
|
||||
g_inputFiles[i].physEnd = 0;
|
||||
} else if (compressed) {
|
||||
size_t compSize = round_up(g_inputFiles[i].size, 16);
|
||||
size_t uncompSize = util_read_uint32_be(g_inputFiles[i].data + 4);
|
||||
|
||||
g_inputFiles[i].virtStart = virtOffset;
|
||||
g_inputFiles[i].virtEnd = virtOffset + uncompSize;
|
||||
g_inputFiles[i].virtEnd = virtOffset + uncompSize;
|
||||
g_inputFiles[i].physStart = physOffset;
|
||||
g_inputFiles[i].physEnd = physOffset + compSize;
|
||||
g_inputFiles[i].physEnd = physOffset + compSize;
|
||||
|
||||
physOffset += compSize;
|
||||
virtOffset += uncompSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
size_t size = g_inputFiles[i].size;
|
||||
|
||||
g_inputFiles[i].virtStart = virtOffset;
|
||||
g_inputFiles[i].virtEnd = virtOffset + size;
|
||||
g_inputFiles[i].virtEnd = virtOffset + size;
|
||||
g_inputFiles[i].physStart = physOffset;
|
||||
g_inputFiles[i].physEnd = 0;
|
||||
g_inputFiles[i].physEnd = 0;
|
||||
|
||||
physOffset += size;
|
||||
virtOffset += size;
|
||||
@@ -107,17 +90,15 @@ static void compute_offsets(void)
|
||||
}
|
||||
}
|
||||
|
||||
static void build_rom(const char *filename)
|
||||
{
|
||||
uint8_t *romData = calloc(ROM_SIZE, 1);
|
||||
static void build_rom(const char* filename) {
|
||||
uint8_t* romData = calloc(ROM_SIZE, 1);
|
||||
size_t pos = 0;
|
||||
int i;
|
||||
int j;
|
||||
uint32_t chksum[2];
|
||||
FILE *outFile;
|
||||
FILE* outFile;
|
||||
|
||||
for (i = 0; i < g_inputFilesCount; i++)
|
||||
{
|
||||
for (i = 0; i < g_inputFilesCount; i++) {
|
||||
size_t size = g_inputFiles[i].size;
|
||||
|
||||
if (pos + round_up(size, 16) > ROM_SIZE)
|
||||
@@ -125,34 +106,31 @@ static void build_rom(const char *filename)
|
||||
|
||||
assert(pos % 16 == 0);
|
||||
|
||||
switch (g_inputFiles[i].type)
|
||||
{
|
||||
case OBJ_FILE:
|
||||
// write file data
|
||||
memcpy(romData + pos, g_inputFiles[i].data, size);
|
||||
pos += round_up(size, 16);
|
||||
switch (g_inputFiles[i].type) {
|
||||
case OBJ_FILE:
|
||||
// write file data
|
||||
memcpy(romData + pos, g_inputFiles[i].data, size);
|
||||
pos += round_up(size, 16);
|
||||
|
||||
free(g_inputFiles[i].data);
|
||||
break;
|
||||
case OBJ_TABLE:
|
||||
for (j = 0; j < g_inputFilesCount; j++)
|
||||
{
|
||||
util_write_uint32_be(romData + pos + 0, g_inputFiles[j].virtStart);
|
||||
util_write_uint32_be(romData + pos + 4, g_inputFiles[j].virtEnd);
|
||||
util_write_uint32_be(romData + pos + 8, g_inputFiles[j].physStart);
|
||||
util_write_uint32_be(romData + pos + 12, g_inputFiles[j].physEnd);
|
||||
free(g_inputFiles[i].data);
|
||||
break;
|
||||
case OBJ_TABLE:
|
||||
for (j = 0; j < g_inputFilesCount; j++) {
|
||||
util_write_uint32_be(romData + pos + 0, g_inputFiles[j].virtStart);
|
||||
util_write_uint32_be(romData + pos + 4, g_inputFiles[j].virtEnd);
|
||||
util_write_uint32_be(romData + pos + 8, g_inputFiles[j].physStart);
|
||||
util_write_uint32_be(romData + pos + 12, g_inputFiles[j].physEnd);
|
||||
|
||||
pos += 16;
|
||||
}
|
||||
break;
|
||||
case OBJ_NULL:
|
||||
break;
|
||||
pos += 16;
|
||||
}
|
||||
break;
|
||||
case OBJ_NULL:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Pad the rest of the ROM
|
||||
while (pos < ROM_SIZE)
|
||||
{
|
||||
while (pos < ROM_SIZE) {
|
||||
// This is such a weird thing to pad with. Whatever, Nintendo.
|
||||
romData[pos] = pos & 0xFF;
|
||||
pos++;
|
||||
@@ -173,8 +151,7 @@ static void build_rom(const char *filename)
|
||||
free(romData);
|
||||
}
|
||||
|
||||
static struct InputFile *new_file(void)
|
||||
{
|
||||
static struct InputFile* new_file(void) {
|
||||
int index = g_inputFilesCount;
|
||||
|
||||
g_inputFilesCount++;
|
||||
@@ -186,15 +163,13 @@ static struct InputFile *new_file(void)
|
||||
}
|
||||
|
||||
// null terminates the current token and returns a pointer to the next token
|
||||
static char *token_split(char *str)
|
||||
{
|
||||
while (!isspace(*str))
|
||||
{
|
||||
static char* token_split(char* str) {
|
||||
while (!isspace(*str)) {
|
||||
if (*str == 0)
|
||||
return str; // end of string
|
||||
return str; // end of string
|
||||
str++;
|
||||
}
|
||||
*str = 0; // terminate token
|
||||
*str = 0; // terminate token
|
||||
str++;
|
||||
|
||||
// skip remaining whitespace
|
||||
@@ -204,104 +179,94 @@ static char *token_split(char *str)
|
||||
}
|
||||
|
||||
// null terminates the current line and returns a pointer to the next line
|
||||
static char *line_split(char *str)
|
||||
{
|
||||
while (*str != '\n')
|
||||
{
|
||||
static char* line_split(char* str) {
|
||||
while (*str != '\n') {
|
||||
if (*str == 0)
|
||||
return str; // end of string
|
||||
return str; // end of string
|
||||
str++;
|
||||
}
|
||||
*str = 0; // terminate line
|
||||
*str = 0; // terminate line
|
||||
return str + 1;
|
||||
}
|
||||
|
||||
static void parse_line(char *line, int lineNum)
|
||||
{
|
||||
char *token = line;
|
||||
static void parse_line(char* line, int lineNum) {
|
||||
char* token = line;
|
||||
int i = 0;
|
||||
|
||||
char *filename = NULL;
|
||||
char* filename = NULL;
|
||||
enum InputObjType type = -1;
|
||||
int valign = 1;
|
||||
struct InputFile *file;
|
||||
struct InputFile* file;
|
||||
|
||||
// iterate through each token
|
||||
while (token[0] != 0)
|
||||
{
|
||||
char *nextToken = token_split(token);
|
||||
while (token[0] != 0) {
|
||||
char* nextToken = token_split(token);
|
||||
|
||||
if (token[0] == '#') // comment - ignore rest of line
|
||||
if (token[0] == '#') // comment - ignore rest of line
|
||||
return;
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
if (strcmp(token, "file") == 0)
|
||||
type = OBJ_FILE;
|
||||
else if (strcmp(token, "filetable") == 0)
|
||||
type = OBJ_TABLE;
|
||||
else if (strcmp(token, "null") == 0)
|
||||
type = OBJ_NULL;
|
||||
else
|
||||
util_fatal_error("unknown object type '%s' on line %i", token, lineNum);
|
||||
break;
|
||||
case 1:
|
||||
filename = token;
|
||||
break;
|
||||
case 2:
|
||||
{
|
||||
switch (i) {
|
||||
case 0:
|
||||
if (strcmp(token, "file") == 0)
|
||||
type = OBJ_FILE;
|
||||
else if (strcmp(token, "filetable") == 0)
|
||||
type = OBJ_TABLE;
|
||||
else if (strcmp(token, "null") == 0)
|
||||
type = OBJ_NULL;
|
||||
else
|
||||
util_fatal_error("unknown object type '%s' on line %i", token, lineNum);
|
||||
break;
|
||||
case 1:
|
||||
filename = token;
|
||||
break;
|
||||
case 2: {
|
||||
int n;
|
||||
|
||||
if (sscanf(token, "align(%i)", &n) == 1)
|
||||
valign = n;
|
||||
else
|
||||
goto junk;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
junk:
|
||||
util_fatal_error("junk '%s' on line %i", token, lineNum);
|
||||
break;
|
||||
} break;
|
||||
default:
|
||||
junk:
|
||||
util_fatal_error("junk '%s' on line %i", token, lineNum);
|
||||
break;
|
||||
}
|
||||
|
||||
token = nextToken;
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i == 0) // empty line
|
||||
if (i == 0) // empty line
|
||||
return;
|
||||
|
||||
file = new_file();
|
||||
file->valign = valign;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case OBJ_FILE:
|
||||
if (filename == NULL)
|
||||
util_fatal_error("no filename specified on line %i", lineNum);
|
||||
file->type = OBJ_FILE;
|
||||
file->data = util_read_whole_file(filename, &file->size);
|
||||
break;
|
||||
case OBJ_TABLE:
|
||||
file->type = OBJ_TABLE;
|
||||
break;
|
||||
case OBJ_NULL:
|
||||
file->type = OBJ_NULL;
|
||||
file->size = 0;
|
||||
break;
|
||||
switch (type) {
|
||||
case OBJ_FILE:
|
||||
if (filename == NULL)
|
||||
util_fatal_error("no filename specified on line %i", lineNum);
|
||||
file->type = OBJ_FILE;
|
||||
file->data = util_read_whole_file(filename, &file->size);
|
||||
break;
|
||||
case OBJ_TABLE:
|
||||
file->type = OBJ_TABLE;
|
||||
break;
|
||||
case OBJ_NULL:
|
||||
file->type = OBJ_NULL;
|
||||
file->size = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void parse_list(char *list)
|
||||
{
|
||||
char *line = list;
|
||||
static void parse_list(char* list) {
|
||||
char* line = list;
|
||||
int lineNum = 1;
|
||||
|
||||
// iterate through each line
|
||||
while (line[0] != 0)
|
||||
{
|
||||
char *nextLine = line_split(line);
|
||||
while (line[0] != 0) {
|
||||
char* nextLine = line_split(line);
|
||||
|
||||
parse_line(line, lineNum);
|
||||
|
||||
@@ -310,8 +275,7 @@ static void parse_list(char *list)
|
||||
}
|
||||
}
|
||||
|
||||
static void usage(const char *execName)
|
||||
{
|
||||
static void usage(const char* execName) {
|
||||
printf("usage: %s FILE_LIST OUTPUT_FILE\n"
|
||||
"where FILE_LIST is a list of files to include\n"
|
||||
"and OUTPUT_FILE is the name of the output ROM\n"
|
||||
@@ -319,12 +283,10 @@ static void usage(const char *execName)
|
||||
execName);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char *list;
|
||||
int main(int argc, char** argv) {
|
||||
char* list;
|
||||
|
||||
if (argc != 3)
|
||||
{
|
||||
if (argc != 3) {
|
||||
puts("invalid args");
|
||||
usage(argv[0]);
|
||||
return 1;
|
||||
|
||||
@@ -6,12 +6,11 @@
|
||||
#include "n64chksum.h"
|
||||
#include "util.h"
|
||||
|
||||
//Based on uCON64's N64 checksum algorithm by Andreas Sterbenz
|
||||
// Based on uCON64's N64 checksum algorithm by Andreas Sterbenz
|
||||
|
||||
#define ROL(i, b) (((i) << (b)) | ((i) >> (32 - (b))))
|
||||
|
||||
bool n64chksum_calculate(const uint8_t *romData, int cicType, uint32_t *chksum)
|
||||
{
|
||||
bool n64chksum_calculate(const uint8_t* romData, int cicType, uint32_t* chksum) {
|
||||
unsigned int seed;
|
||||
unsigned int t1, t2, t3, t4, t5, t6;
|
||||
size_t pos;
|
||||
@@ -20,29 +19,27 @@ bool n64chksum_calculate(const uint8_t *romData, int cicType, uint32_t *chksum)
|
||||
const size_t END = START + 0x100000;
|
||||
|
||||
// determine initial seed
|
||||
switch (cicType)
|
||||
{
|
||||
case 6101:
|
||||
case 6102:
|
||||
seed = 0xF8CA4DDC;
|
||||
break;
|
||||
case 6103:
|
||||
seed = 0xA3886759;
|
||||
break;
|
||||
case 6105:
|
||||
seed = 0xDF26F436;
|
||||
break;
|
||||
case 6106:
|
||||
seed = 0x1FEA617A;
|
||||
break;
|
||||
default:
|
||||
return false; // unknown CIC type
|
||||
switch (cicType) {
|
||||
case 6101:
|
||||
case 6102:
|
||||
seed = 0xF8CA4DDC;
|
||||
break;
|
||||
case 6103:
|
||||
seed = 0xA3886759;
|
||||
break;
|
||||
case 6105:
|
||||
seed = 0xDF26F436;
|
||||
break;
|
||||
case 6106:
|
||||
seed = 0x1FEA617A;
|
||||
break;
|
||||
default:
|
||||
return false; // unknown CIC type
|
||||
}
|
||||
|
||||
t1 = t2 = t3 = t4 = t5 = t6 = seed;
|
||||
|
||||
for (pos = START; pos < END; pos += 4)
|
||||
{
|
||||
for (pos = START; pos < END; pos += 4) {
|
||||
unsigned int d = util_read_uint32_be(romData + pos);
|
||||
unsigned int r = ROL(d, (d & 0x1F));
|
||||
|
||||
@@ -65,18 +62,13 @@ bool n64chksum_calculate(const uint8_t *romData, int cicType, uint32_t *chksum)
|
||||
t1 += t5 ^ d;
|
||||
}
|
||||
|
||||
if (cicType == 6103)
|
||||
{
|
||||
if (cicType == 6103) {
|
||||
chksum[0] = (t6 ^ t4) + t3;
|
||||
chksum[1] = (t5 ^ t2) + t1;
|
||||
}
|
||||
else if (cicType == 6106)
|
||||
{
|
||||
} else if (cicType == 6106) {
|
||||
chksum[0] = (t6 * t4) + t3;
|
||||
chksum[1] = (t5 * t2) + t1;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
chksum[0] = t6 ^ t4 ^ t3;
|
||||
chksum[1] = t5 ^ t2 ^ t1;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#ifndef _N64CHKSUM_H_
|
||||
#define _N64CHKSUM_H_
|
||||
#ifndef N64CHKSUM_H
|
||||
#define N64CHKSUM_H
|
||||
|
||||
bool n64chksum_calculate(const uint8_t *romData, int cicType, uint32_t *chksum);
|
||||
bool n64chksum_calculate(const uint8_t* romData, int cicType, uint32_t* chksum);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -55,9 +55,9 @@ typedef struct Segment {
|
||||
|
||||
void parse_rom_spec(char* spec, struct Segment** segments, int* segment_count);
|
||||
|
||||
bool get_single_segment_by_name(struct Segment* dstSegment, char *spec, const char *segmentName);
|
||||
bool get_single_segment_by_name(struct Segment* dstSegment, char* spec, const char* segmentName);
|
||||
|
||||
void free_single_segment_elements(struct Segment *segment);
|
||||
void free_single_segment_elements(struct Segment* segment);
|
||||
|
||||
void free_rom_spec(struct Segment* segments, int segment_count);
|
||||
|
||||
|
||||
+9
-17
@@ -8,8 +8,7 @@
|
||||
#include "util.h"
|
||||
|
||||
// displays an error message and exits
|
||||
void util_fatal_error(const char *msgfmt, ...)
|
||||
{
|
||||
void util_fatal_error(const char* msgfmt, ...) {
|
||||
va_list args;
|
||||
|
||||
fputs(ERRMSG_START, stderr);
|
||||
@@ -24,10 +23,9 @@ void util_fatal_error(const char *msgfmt, ...)
|
||||
}
|
||||
|
||||
// reads a whole file into memory, and returns a malloc'd pointer to the data.
|
||||
void *util_read_whole_file(const char *filename, size_t *pSize)
|
||||
{
|
||||
FILE *file = fopen(filename, "rb");
|
||||
uint8_t *buffer;
|
||||
void* util_read_whole_file(const char* filename, size_t* pSize) {
|
||||
FILE* file = fopen(filename, "rb");
|
||||
uint8_t* buffer;
|
||||
size_t size;
|
||||
|
||||
if (file == NULL)
|
||||
@@ -56,9 +54,8 @@ void *util_read_whole_file(const char *filename, size_t *pSize)
|
||||
}
|
||||
|
||||
// writes data to file
|
||||
void util_write_whole_file(const char *filename, const void *data, size_t size)
|
||||
{
|
||||
FILE *file = fopen(filename, "wb");
|
||||
void util_write_whole_file(const char* filename, const void* data, size_t size) {
|
||||
FILE* file = fopen(filename, "wb");
|
||||
|
||||
if (file == NULL)
|
||||
util_fatal_error("failed to open file '%s' for writing: %s", filename, strerror(errno));
|
||||
@@ -69,17 +66,12 @@ void util_write_whole_file(const char *filename, const void *data, size_t size)
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
uint32_t util_read_uint32_be(const uint8_t *data)
|
||||
{
|
||||
return data[0] << 24
|
||||
| data[1] << 16
|
||||
| data[2] << 8
|
||||
| data[3] << 0;
|
||||
uint32_t util_read_uint32_be(const uint8_t* data) {
|
||||
return data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3] << 0;
|
||||
}
|
||||
|
||||
// writes a big-endian 32-bit integer
|
||||
void util_write_uint32_be(uint8_t *data, uint32_t val)
|
||||
{
|
||||
void util_write_uint32_be(uint8_t* data, uint32_t val) {
|
||||
data[0] = val >> 24;
|
||||
data[1] = val >> 16;
|
||||
data[2] = val >> 8;
|
||||
|
||||
@@ -13,12 +13,12 @@ __attribute__((format(printf, 1, 2), noreturn))
|
||||
#endif
|
||||
void util_fatal_error(const char *msgfmt, ...);
|
||||
|
||||
void *util_read_whole_file(const char *filename, size_t *pSize);
|
||||
void* util_read_whole_file(const char* filename, size_t* pSize);
|
||||
|
||||
void util_write_whole_file(const char *filename, const void *data, size_t size);
|
||||
void util_write_whole_file(const char* filename, const void* data, size_t size);
|
||||
|
||||
uint32_t util_read_uint32_be(const uint8_t *data);
|
||||
uint32_t util_read_uint32_be(const uint8_t* data);
|
||||
|
||||
void util_write_uint32_be(uint8_t *data, uint32_t val);
|
||||
void util_write_uint32_be(uint8_t* data, uint32_t val);
|
||||
|
||||
#endif
|
||||
|
||||
+29
-55
@@ -10,31 +10,25 @@
|
||||
// src points to the yaz0 source data (to the "real" source data, not at the header!)
|
||||
// dst points to a buffer uncompressedSize bytes large (you get uncompressedSize from
|
||||
// the second 4 bytes in the Yaz0 header).
|
||||
void yaz0_decode(uint8_t* src, uint8_t* dst, int uncompressedSize)
|
||||
{
|
||||
int srcPlace = 0, dstPlace = 0; // current read/write positions
|
||||
void yaz0_decode(uint8_t* src, uint8_t* dst, int uncompressedSize) {
|
||||
int srcPlace = 0, dstPlace = 0; // current read/write positions
|
||||
|
||||
unsigned int validBitCount = 0; // number of valid bits left in "code" byte
|
||||
unsigned int validBitCount = 0; // number of valid bits left in "code" byte
|
||||
uint8_t currCodeByte;
|
||||
while (dstPlace < uncompressedSize)
|
||||
{
|
||||
while (dstPlace < uncompressedSize) {
|
||||
// read new "code" byte if the current one is used up
|
||||
if (validBitCount == 0)
|
||||
{
|
||||
if (validBitCount == 0) {
|
||||
currCodeByte = src[srcPlace];
|
||||
++srcPlace;
|
||||
validBitCount = 8;
|
||||
}
|
||||
|
||||
if ((currCodeByte & 0x80) != 0)
|
||||
{
|
||||
if ((currCodeByte & 0x80) != 0) {
|
||||
// straight copy
|
||||
dst[dstPlace] = src[srcPlace];
|
||||
dstPlace++;
|
||||
srcPlace++;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// RLE part
|
||||
uint8_t byte1 = src[srcPlace];
|
||||
uint8_t byte2 = src[srcPlace + 1];
|
||||
@@ -44,19 +38,15 @@ void yaz0_decode(uint8_t* src, uint8_t* dst, int uncompressedSize)
|
||||
unsigned int copySource = dstPlace - (dist + 1);
|
||||
|
||||
unsigned int numBytes = byte1 >> 4;
|
||||
if (numBytes == 0)
|
||||
{
|
||||
if (numBytes == 0) {
|
||||
numBytes = src[srcPlace] + 0x12;
|
||||
srcPlace++;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
numBytes += 2;
|
||||
}
|
||||
|
||||
// copy run
|
||||
for (unsigned int i = 0; i < numBytes; ++i)
|
||||
{
|
||||
for (unsigned int i = 0; i < numBytes; ++i) {
|
||||
dst[dstPlace] = dst[copySource];
|
||||
copySource++;
|
||||
dstPlace++;
|
||||
@@ -77,8 +67,7 @@ typedef uint8_t uint8_t;
|
||||
#define MAX_RUNLEN (0xFF + 0x12)
|
||||
|
||||
// simple and straight encoding scheme for Yaz0
|
||||
static uint32_t simpleEnc(uint8_t *src, int size, int pos, uint32_t *pMatchPos)
|
||||
{
|
||||
static uint32_t simpleEnc(uint8_t* src, int size, int pos, uint32_t* pMatchPos) {
|
||||
int numBytes = 1;
|
||||
int matchPos = 0;
|
||||
|
||||
@@ -92,17 +81,14 @@ static uint32_t simpleEnc(uint8_t *src, int size, int pos, uint32_t *pMatchPos)
|
||||
if (end > MAX_RUNLEN)
|
||||
end = MAX_RUNLEN;
|
||||
|
||||
for (int i = startPos; i < pos; i++)
|
||||
{
|
||||
for (int i = startPos; i < pos; i++) {
|
||||
int j;
|
||||
|
||||
for (j = 0; j < end; j++)
|
||||
{
|
||||
for (j = 0; j < end; j++) {
|
||||
if (src[i + j] != src[j + pos])
|
||||
break;
|
||||
}
|
||||
if (j > numBytes)
|
||||
{
|
||||
if (j > numBytes) {
|
||||
numBytes = j;
|
||||
matchPos = i;
|
||||
}
|
||||
@@ -117,8 +103,7 @@ static uint32_t simpleEnc(uint8_t *src, int size, int pos, uint32_t *pMatchPos)
|
||||
}
|
||||
|
||||
// a lookahead encoding scheme for ngc Yaz0
|
||||
static uint32_t nintendoEnc(uint8_t *src, int size, int pos, uint32_t *pMatchPos)
|
||||
{
|
||||
static uint32_t nintendoEnc(uint8_t* src, int size, int pos, uint32_t* pMatchPos) {
|
||||
uint32_t numBytes = 1;
|
||||
static uint32_t numBytes1;
|
||||
static uint32_t matchPos;
|
||||
@@ -128,8 +113,7 @@ static uint32_t nintendoEnc(uint8_t *src, int size, int pos, uint32_t *pMatchPos
|
||||
// was determined by look-ahead try.
|
||||
// so just use it. this is not the best optimization,
|
||||
// but nintendo's choice for speed.
|
||||
if (prevFlag == 1)
|
||||
{
|
||||
if (prevFlag == 1) {
|
||||
*pMatchPos = matchPos;
|
||||
prevFlag = 0;
|
||||
return numBytes1;
|
||||
@@ -140,13 +124,11 @@ static uint32_t nintendoEnc(uint8_t *src, int size, int pos, uint32_t *pMatchPos
|
||||
*pMatchPos = matchPos;
|
||||
|
||||
// if this position is RLE encoded, then compare to copying 1 byte and next position(pos+1) encoding
|
||||
if (numBytes >= 3)
|
||||
{
|
||||
if (numBytes >= 3) {
|
||||
numBytes1 = simpleEnc(src, size, pos + 1, &matchPos);
|
||||
// if the next position encoding is +2 longer than current position, choose it.
|
||||
// this does not guarantee the best optimization, but fairly good optimization with speed.
|
||||
if (numBytes1 >= numBytes + 2)
|
||||
{
|
||||
if (numBytes1 >= numBytes + 2) {
|
||||
numBytes = 1;
|
||||
prevFlag = 1;
|
||||
}
|
||||
@@ -154,8 +136,7 @@ static uint32_t nintendoEnc(uint8_t *src, int size, int pos, uint32_t *pMatchPos
|
||||
return numBytes;
|
||||
}
|
||||
|
||||
int yaz0_encode(uint8_t *src, uint8_t *dst, int srcSize)
|
||||
{
|
||||
int yaz0_encode(uint8_t* src, uint8_t* dst, int srcSize) {
|
||||
int srcPos = 0;
|
||||
int dstPos = 0;
|
||||
int bufPos = 0;
|
||||
@@ -163,30 +144,26 @@ int yaz0_encode(uint8_t *src, uint8_t *dst, int srcSize)
|
||||
uint8_t buf[24]; // 8 codes * 3 bytes maximum
|
||||
|
||||
uint32_t validBitCount = 0; // number of valid bits left in "code" byte
|
||||
uint8_t currCodeByte = 0; // a bitfield, set bits meaning copy, unset meaning RLE
|
||||
uint8_t currCodeByte = 0; // a bitfield, set bits meaning copy, unset meaning RLE
|
||||
|
||||
while (srcPos < srcSize)
|
||||
{
|
||||
while (srcPos < srcSize) {
|
||||
uint32_t numBytes;
|
||||
uint32_t matchPos;
|
||||
|
||||
numBytes = nintendoEnc(src, srcSize, srcPos, &matchPos);
|
||||
if (numBytes < 3)
|
||||
{
|
||||
if (numBytes < 3) {
|
||||
// straight copy
|
||||
buf[bufPos] = src[srcPos];
|
||||
bufPos++;
|
||||
srcPos++;
|
||||
//set flag for straight copy
|
||||
// set flag for straight copy
|
||||
currCodeByte |= (0x80 >> validBitCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
//RLE part
|
||||
} else {
|
||||
// RLE part
|
||||
uint32_t dist = srcPos - matchPos - 1;
|
||||
uint8_t byte1, byte2, byte3;
|
||||
|
||||
if (numBytes >= 0x12) // 3 byte encoding
|
||||
if (numBytes >= 0x12) // 3 byte encoding
|
||||
{
|
||||
byte1 = 0 | (dist >> 8);
|
||||
byte2 = dist & 0xFF;
|
||||
@@ -197,8 +174,7 @@ int yaz0_encode(uint8_t *src, uint8_t *dst, int srcSize)
|
||||
numBytes = MAX_RUNLEN;
|
||||
byte3 = numBytes - 0x12;
|
||||
buf[bufPos++] = byte3;
|
||||
}
|
||||
else // 2 byte encoding
|
||||
} else // 2 byte encoding
|
||||
{
|
||||
byte1 = ((numBytes - 2) << 4) | (dist >> 8);
|
||||
byte2 = dist & 0xFF;
|
||||
@@ -211,8 +187,7 @@ int yaz0_encode(uint8_t *src, uint8_t *dst, int srcSize)
|
||||
validBitCount++;
|
||||
|
||||
// write eight codes
|
||||
if (validBitCount == 8)
|
||||
{
|
||||
if (validBitCount == 8) {
|
||||
dst[dstPos++] = currCodeByte;
|
||||
for (int j = 0; j < bufPos; j++)
|
||||
dst[dstPos++] = buf[j];
|
||||
@@ -223,8 +198,7 @@ int yaz0_encode(uint8_t *src, uint8_t *dst, int srcSize)
|
||||
}
|
||||
}
|
||||
|
||||
if (validBitCount > 0)
|
||||
{
|
||||
if (validBitCount > 0) {
|
||||
dst[dstPos++] = currCodeByte;
|
||||
for (int j = 0; j < bufPos; j++)
|
||||
dst[dstPos++] = buf[j];
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#ifndef _YAZ0_H_
|
||||
#define _YAZ0_H_
|
||||
#ifndef YAZ0_H
|
||||
#define YAZ0_H
|
||||
|
||||
int yaz0_encode2(uint8_t *src, uint8_t *dest, int uncompressedSize);
|
||||
int yaz0_encode2(uint8_t* src, uint8_t* dest, int uncompressedSize);
|
||||
|
||||
void yaz0_decode(uint8_t* src, uint8_t* dst, int uncompressedSize);
|
||||
|
||||
int yaz0_encode(uint8_t *src, uint8_t *dest, int srcSize);
|
||||
int yaz0_encode(uint8_t* src, uint8_t* dest, int srcSize);
|
||||
|
||||
#endif // _YAZ0_H_
|
||||
#endif // YAZ0_H
|
||||
|
||||
Reference in New Issue
Block a user