mirror of
https://github.com/zeldaret/oot.git
synced 2024-12-25 06:06:05 +00:00
Delete unused yaz0tool (#1959)
This commit is contained in:
parent
44ca32168a
commit
7332e8ee76
4 changed files with 1 additions and 451 deletions
|
@ -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 =
|
||||
|
|
238
tools/yaz0.c
238
tools/yaz0.c
|
@ -1,238 +0,0 @@
|
|||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#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;
|
||||
}
|
10
tools/yaz0.h
10
tools/yaz0.h
|
@ -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_
|
201
tools/yaz0tool.c
201
tools/yaz0tool.c
|
@ -1,201 +0,0 @@
|
|||
#ifdef __linux__
|
||||
#define _POSIX_C_SOURCE 199309L
|
||||
#endif
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#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;
|
||||
}
|
Loading…
Reference in a new issue