diff --git a/tools/Makefile b/tools/Makefile index 4d342e2485..c4688f6646 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -1,5 +1,5 @@ CFLAGS := -Wall -Wextra -pedantic -std=c99 -g -O2 -PROGRAMS := elf2rom makeromfs mkdmadata mkldscript reloc_prereq vtxdis yaz0 +PROGRAMS := elf2rom makeromfs mkdmadata mkldscript reloc_prereq vtxdis ifeq ($(shell command -v clang >/dev/null 2>&1; echo $$?),0) CC := clang @@ -36,7 +36,6 @@ mkdmadata_SOURCES := mkdmadata.c spec.c util.c mkldscript_SOURCES := mkldscript.c spec.c util.c reloc_prereq_SOURCES := reloc_prereq.c spec.c util.c vtxdis_SOURCES := vtxdis.c -yaz0_SOURCES := yaz0tool.c yaz0.c util.c define COMPILE = diff --git a/tools/yaz0.c b/tools/yaz0.c deleted file mode 100644 index 5b3156e443..0000000000 --- a/tools/yaz0.c +++ /dev/null @@ -1,238 +0,0 @@ -#include -#include -#include -#include - -#include "yaz0.h" - -// decoder implementation by thakis of http://www.amnoid.de - -// 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 - - unsigned int validBitCount = 0; // number of valid bits left in "code" byte - uint8_t currCodeByte; - while (dstPlace < uncompressedSize) - { - // read new "code" byte if the current one is used up - if (validBitCount == 0) - { - currCodeByte = src[srcPlace]; - ++srcPlace; - validBitCount = 8; - } - - if ((currCodeByte & 0x80) != 0) - { - // straight copy - dst[dstPlace] = src[srcPlace]; - dstPlace++; - srcPlace++; - } - else - { - // RLE part - uint8_t byte1 = src[srcPlace]; - uint8_t byte2 = src[srcPlace + 1]; - srcPlace += 2; - - unsigned int dist = ((byte1 & 0xF) << 8) | byte2; - unsigned int copySource = dstPlace - (dist + 1); - - unsigned int numBytes = byte1 >> 4; - if (numBytes == 0) - { - numBytes = src[srcPlace] + 0x12; - srcPlace++; - } - else - { - numBytes += 2; - } - - // copy run - for (unsigned int i = 0; i < numBytes; ++i) - { - dst[dstPlace] = dst[copySource]; - copySource++; - dstPlace++; - } - } - - // use next bit from "code" byte - currCodeByte <<= 1; - validBitCount -= 1; - } -} - -// encoder implementation by shevious, with bug fixes by notwa - -typedef uint32_t uint32_t; -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) -{ - int numBytes = 1; - int matchPos = 0; - - int startPos = pos - 0x1000; - int end = size - pos; - - if (startPos < 0) - startPos = 0; - - // maximum runlength for 3 byte encoding - if (end > MAX_RUNLEN) - end = MAX_RUNLEN; - - for (int i = startPos; i < pos; i++) - { - int j; - - for (j = 0; j < end; j++) - { - if (src[i + j] != src[j + pos]) - break; - } - if (j > numBytes) - { - numBytes = j; - matchPos = i; - } - } - - *pMatchPos = matchPos; - - if (numBytes == 2) - numBytes = 1; - - return numBytes; -} - -// a lookahead encoding scheme for ngc Yaz0 -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; - static int prevFlag = 0; - - // if prevFlag is set, it means that the previous position - // 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) - { - *pMatchPos = matchPos; - prevFlag = 0; - return numBytes1; - } - - prevFlag = 0; - numBytes = simpleEnc(src, size, pos, &matchPos); - *pMatchPos = matchPos; - - // if this position is RLE encoded, then compare to copying 1 byte and next position(pos+1) encoding - 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) - { - numBytes = 1; - prevFlag = 1; - } - } - return numBytes; -} - -int yaz0_encode(uint8_t *src, uint8_t *dst, int srcSize) -{ - int srcPos = 0; - int dstPos = 0; - int bufPos = 0; - - 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 - - while (srcPos < srcSize) - { - uint32_t numBytes; - uint32_t matchPos; - - numBytes = nintendoEnc(src, srcSize, srcPos, &matchPos); - if (numBytes < 3) - { - // straight copy - buf[bufPos] = src[srcPos]; - bufPos++; - srcPos++; - //set flag for straight copy - currCodeByte |= (0x80 >> validBitCount); - } - else - { - //RLE part - uint32_t dist = srcPos - matchPos - 1; - uint8_t byte1, byte2, byte3; - - if (numBytes >= 0x12) // 3 byte encoding - { - byte1 = 0 | (dist >> 8); - byte2 = dist & 0xFF; - buf[bufPos++] = byte1; - buf[bufPos++] = byte2; - // maximum runlength for 3 byte encoding - if (numBytes > MAX_RUNLEN) - numBytes = MAX_RUNLEN; - byte3 = numBytes - 0x12; - buf[bufPos++] = byte3; - } - else // 2 byte encoding - { - byte1 = ((numBytes - 2) << 4) | (dist >> 8); - byte2 = dist & 0xFF; - buf[bufPos++] = byte1; - buf[bufPos++] = byte2; - } - srcPos += numBytes; - } - - validBitCount++; - - // write eight codes - if (validBitCount == 8) - { - dst[dstPos++] = currCodeByte; - for (int j = 0; j < bufPos; j++) - dst[dstPos++] = buf[j]; - - currCodeByte = 0; - validBitCount = 0; - bufPos = 0; - } - } - - if (validBitCount > 0) - { - dst[dstPos++] = currCodeByte; - for (int j = 0; j < bufPos; j++) - dst[dstPos++] = buf[j]; - - currCodeByte = 0; - validBitCount = 0; - bufPos = 0; - } - - return dstPos; -} diff --git a/tools/yaz0.h b/tools/yaz0.h deleted file mode 100644 index 0cc3703ec9..0000000000 --- a/tools/yaz0.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef _YAZ0_H_ -#define _YAZ0_H_ - -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); - -#endif // _YAZ0_H_ diff --git a/tools/yaz0tool.c b/tools/yaz0tool.c deleted file mode 100644 index b21468fa20..0000000000 --- a/tools/yaz0tool.c +++ /dev/null @@ -1,201 +0,0 @@ -#ifdef __linux__ -#define _POSIX_C_SOURCE 199309L -#endif - -#include -#include -#include -#include -#include -#include -#include - -#include "yaz0.h" -#include "util.h" - -// TODO: Windows support -static unsigned long int get_time_milliseconds(void) -{ -#ifdef __linux__ - struct timespec tspec; - - clock_gettime(CLOCK_MONOTONIC, &tspec); - return (tspec.tv_sec * 1000) + tspec.tv_nsec / 1000000; -#else - // dummy - return 0; -#endif -} - -static void print_report(unsigned long int time, size_t compSize, size_t uncompSize) -{ - unsigned int minutes = time / (1000 * 60); - float seconds = (float)(time % (1000 * 60)) / 1000; - - printf("compression ratio: %.2fKiB / %.2fKiB (%.2f%%)\n" - "time: %um %.3fs\n", - (float)compSize / 1024, (float)uncompSize / 1024, - (float)compSize * 100 / (float)uncompSize, - minutes, seconds); -} - -static void compress_file(const char *inputFileName, const char *outputFileName, bool verbose) -{ - size_t uncompSize; - uint8_t *input = util_read_whole_file(inputFileName, &uncompSize); - uint8_t *output = malloc(uncompSize * 2); // TODO: figure out how much space we need - unsigned long int time; - - if (verbose) - { - printf("decompressing %s\n", inputFileName); - time = get_time_milliseconds(); - } - - // compress data - size_t compSize = yaz0_encode(input, output, uncompSize); - - if (verbose) - time = get_time_milliseconds() - time; - - // make Yaz0 header - uint8_t header[16] = {0}; - header[0] = 'Y'; - header[1] = 'a'; - header[2] = 'z'; - header[3] = '0'; - util_write_uint32_be(header + 4, uncompSize); - - // write output file - FILE *outFile = fopen(outputFileName, "wb"); - if (outFile == NULL) - util_fatal_error("failed to open file '%s' for writing", outputFileName); - fwrite(header, sizeof(header), 1, outFile); - fwrite(output, compSize, 1, outFile); - fclose(outFile); - - free(input); - free(output); - - if (verbose) - print_report(time, compSize, uncompSize); -} - -static void decompress_file(const char *inputFileName, const char *outputFileName, bool verbose) -{ - size_t compSize; - uint8_t *input = util_read_whole_file(inputFileName, &compSize); - size_t uncompSize; - uint8_t *output; - unsigned long int time = 0; - - // read header - if (input[0] != 'Y' || input[1] != 'a' || input[2] != 'z' || input[3] != '0') - util_fatal_error("file '%s' does not have a valid Yaz0 header", inputFileName); - uncompSize = util_read_uint32_be(input + 4); - - // decompress data - output = malloc(uncompSize); - - if (verbose) - { - printf("decompressing %s\n", inputFileName); - time = get_time_milliseconds(); - } - - yaz0_decode(input + 16, output, uncompSize); - - if (verbose) - time = get_time_milliseconds() - time; - - // write output file - FILE *outFile = fopen(outputFileName, "wb"); - fwrite(output, uncompSize, 1, outFile); - fclose(outFile); - - free(input); - free(output); - - if (verbose) - print_report(time, compSize, uncompSize); -} - -static void usage(const char *execName) -{ - printf("Yaz0 compressor/decompressor\n" - "usage: %s [-d] [-h] [-v] INPUT_FILE OUTPUT_FILE\n" - "compresses INPUT_FILE using Yaz0 encoding and writes output to OUTPUT_FILE\n" - "Available options:\n" - "-d: decompresses INPUT_FILE, a Yaz0 compressed file, and writes decompressed\n" - " output to OUTPUT_FILE\n" - "-v: prints verbose output (compression ratio and time)\n" - "-h: shows this help message\n", - execName); -} - -int main(int argc, char **argv) -{ - int i; - const char *inputFileName = NULL; - const char *outputFileName = NULL; - bool decompress = false; - bool verbose = false; - - // parse arguments - for (i = 1; i < argc; i++) - { - char *arg = argv[i]; - - if (arg[0] == '-') - { - if (strcmp(arg, "-d") == 0) - decompress = true; - else if (strcmp(arg, "-v") == 0) - verbose = true; - else if (strcmp(arg, "-h") == 0) - { - usage(argv[0]); - return 0; - } - else - { - printf("unknown option %s\n", arg); - usage(argv[0]); - return 1; - } - } - else - { - if (inputFileName == NULL) - inputFileName = arg; - else if (outputFileName == NULL) - outputFileName = arg; - else - { - puts("too many files specified"); - usage(argv[0]); - return 1; - } - } - } - - if (inputFileName == NULL) - { - puts("no input file specified"); - usage(argv[0]); - return 1; - } - if (outputFileName == NULL) - { - puts("no output file specified"); - usage(argv[0]); - return 1; - } - - if (decompress) - decompress_file(inputFileName, outputFileName, verbose); - else - compress_file(inputFileName, outputFileName, verbose); - - return 0; -}