summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tools/aif2pcm/Makefile2
-rwxr-xr-xtools/aif2pcm/aif2pcm.exebin335699 -> 335699 bytes
-rw-r--r--tools/bin2c/Makefile2
-rwxr-xr-xtools/bin2c/bin2c.exebin326713 -> 326713 bytes
-rw-r--r--tools/gbafix/Makefile2
-rwxr-xr-xtools/gbafix/gbafix.exebin329850 -> 329850 bytes
-rw-r--r--tools/gbagfx/Makefile5
-rwxr-xr-xtools/gbagfx/gbagfx.exebin1685933 -> 1691545 bytes
-rw-r--r--tools/gbagfx/huff.c398
-rw-r--r--tools/gbagfx/huff.h38
-rw-r--r--tools/gbagfx/lz.c4
-rw-r--r--tools/gbagfx/lz.h2
-rw-r--r--tools/gbagfx/main.c74
-rw-r--r--tools/jsonproc/Makefile2
-rwxr-xr-xtools/jsonproc/jsonproc.exebin3150147 -> 3150147 bytes
-rw-r--r--tools/mapjson/Makefile2
-rwxr-xr-xtools/mapjson/mapjson.exebin2951145 -> 2951145 bytes
-rw-r--r--tools/mid2agb/Makefile2
-rwxr-xr-xtools/mid2agb/mid2agb.exebin939850 -> 939850 bytes
-rw-r--r--tools/preproc/Makefile2
-rw-r--r--tools/preproc/asm_file.cpp6
-rwxr-xr-xtools/preproc/preproc.exebin908180 -> 908692 bytes
-rw-r--r--tools/ramscrgen/Makefile2
-rw-r--r--tools/ramscrgen/elf.cpp101
-rw-r--r--tools/ramscrgen/elf.h2
-rw-r--r--tools/ramscrgen/main.cpp24
-rwxr-xr-xtools/ramscrgen/ramscrgen.exebin878765 -> 884649 bytes
-rw-r--r--tools/rsfont/Makefile2
-rwxr-xr-xtools/rsfont/rsfont.exebin1666987 -> 1666987 bytes
-rw-r--r--tools/scaninc/Makefile2
-rw-r--r--tools/scaninc/scaninc.cpp19
-rwxr-xr-xtools/scaninc/scaninc.exebin881797 -> 881843 bytes
-rw-r--r--tools/scaninc/source_file.cpp5
-rw-r--r--tools/scaninc/source_file.h1
34 files changed, 657 insertions, 42 deletions
diff --git a/tools/aif2pcm/Makefile b/tools/aif2pcm/Makefile
index af7d19f..77df291 100644
--- a/tools/aif2pcm/Makefile
+++ b/tools/aif2pcm/Makefile
@@ -1,4 +1,4 @@
-CC = gcc
+CC ?= gcc
CFLAGS = -Wall -Wextra -Wno-switch -Werror -std=c11 -O2
diff --git a/tools/aif2pcm/aif2pcm.exe b/tools/aif2pcm/aif2pcm.exe
index 3ff7ba7..1ea8ef6 100755
--- a/tools/aif2pcm/aif2pcm.exe
+++ b/tools/aif2pcm/aif2pcm.exe
Binary files differ
diff --git a/tools/bin2c/Makefile b/tools/bin2c/Makefile
index ab11e1b..52806e3 100644
--- a/tools/bin2c/Makefile
+++ b/tools/bin2c/Makefile
@@ -1,4 +1,4 @@
-CC = gcc
+CC ?= gcc
CFLAGS = -Wall -Wextra -Werror -std=c11 -O2
diff --git a/tools/bin2c/bin2c.exe b/tools/bin2c/bin2c.exe
index 077208c..fb6892f 100755
--- a/tools/bin2c/bin2c.exe
+++ b/tools/bin2c/bin2c.exe
Binary files differ
diff --git a/tools/gbafix/Makefile b/tools/gbafix/Makefile
index 5b410da..91a60a9 100644
--- a/tools/gbafix/Makefile
+++ b/tools/gbafix/Makefile
@@ -1,4 +1,4 @@
-CC = gcc
+CC ?= gcc
.PHONY: all clean
SRCS = gbafix.c
diff --git a/tools/gbafix/gbafix.exe b/tools/gbafix/gbafix.exe
index 4f2f39e..678f854 100755
--- a/tools/gbafix/gbafix.exe
+++ b/tools/gbafix/gbafix.exe
Binary files differ
diff --git a/tools/gbagfx/Makefile b/tools/gbagfx/Makefile
index 339585b..8b75d87 100644
--- a/tools/gbagfx/Makefile
+++ b/tools/gbagfx/Makefile
@@ -4,13 +4,16 @@ CFLAGS = -Wall -Wextra -Werror -std=c11 -O2 -DPNG_SKIP_SETJMP_CHECK
LIBS = -lpng -lz
-SRCS = main.c convert_png.c gfx.c jasc_pal.c lz.c rl.c util.c font.c
+SRCS = main.c convert_png.c gfx.c jasc_pal.c lz.c rl.c util.c font.c huff.c
.PHONY: all clean
all: gbagfx
@:
+gbagfx-debug: $(SRCS) convert_png.h gfx.h global.h jasc_pal.h lz.h rl.h util.h font.h
+ $(CC) $(CFLAGS) -DDEBUG $(SRCS) -o $@ $(LDFLAGS) $(LIBS)
+
gbagfx: $(SRCS) convert_png.h gfx.h global.h jasc_pal.h lz.h rl.h util.h font.h
$(CC) $(CFLAGS) $(SRCS) -o $@ $(LDFLAGS) $(LIBS)
diff --git a/tools/gbagfx/gbagfx.exe b/tools/gbagfx/gbagfx.exe
index a8efff4..d5def1d 100755
--- a/tools/gbagfx/gbagfx.exe
+++ b/tools/gbagfx/gbagfx.exe
Binary files differ
diff --git a/tools/gbagfx/huff.c b/tools/gbagfx/huff.c
new file mode 100644
index 0000000..9d807b0
--- /dev/null
+++ b/tools/gbagfx/huff.c
@@ -0,0 +1,398 @@
+#include <stdbool.h>
+#include <string.h>
+#include <assert.h>
+#include <stdio.h>
+#include <stdint.h>
+#include "global.h"
+#include "huff.h"
+
+static int cmp_tree(const void * a0, const void * b0) {
+ return ((struct HuffData *)a0)->value - ((struct HuffData *)b0)->value;
+}
+
+typedef int (*cmpfun)(const void *, const void *);
+
+int msort_r(void * data, size_t count, size_t size, cmpfun cmp, void * buffer) {
+ /*
+ * Out-of-place mergesort (stable sort)
+ * Returns 1 on success, 0 on failure
+ */
+ void * leftPtr;
+ void * rightPtr;
+ void * leftEnd;
+ void * rightEnd;
+ unsigned int i;
+
+ switch (count) {
+ case 0:
+ // Should never be here
+ return 0;
+
+ case 1:
+ // Nothing to do here
+ break;
+
+ case 2:
+ // Swap the two entries if the right one compares higher.
+ if (cmp(data, data + size) > 0) {
+ memcpy(buffer, data, size);
+ memcpy(data, data + size, size);
+ memcpy(data + size, buffer, size);
+ }
+ break;
+ default:
+ // Merge sort out-of-place.
+ leftPtr = data;
+ leftEnd = rightPtr = data + count / 2 * size;
+ rightEnd = data + count * size;
+
+ // Sort the left half
+ if (!msort_r(leftPtr, count / 2, size, cmp, buffer))
+ return 0;
+
+ // Sort the right half
+ if (!msort_r(rightPtr, count / 2 + (count & 1), size, cmp, buffer))
+ return 0;
+
+ // Merge the sorted halves out of place
+ i = 0;
+ do {
+ if (cmp(leftPtr, rightPtr) <= 0) {
+ memcpy(buffer + i * size, leftPtr, size);
+ leftPtr += size;
+ } else {
+ memcpy(buffer + i * size, rightPtr, size);
+ rightPtr += size;
+ }
+
+ } while (++i < count && leftPtr < leftEnd && rightPtr < rightEnd);
+
+ // Copy the remainder
+ if (i < count) {
+ if (leftPtr < leftEnd) {
+ memcpy(buffer + i * size, leftPtr, leftEnd - leftPtr);
+ }
+ else {
+ memcpy(buffer + i * size, rightPtr, rightEnd - rightPtr);
+ }
+ }
+
+ // Copy the merged data back
+ memcpy(data, buffer, count * size);
+ break;
+ }
+
+ return 1;
+}
+
+int msort(void * data, size_t count, size_t size, cmpfun cmp) {
+ void * buffer = malloc(count * size);
+ if (buffer == NULL) return 0;
+ int result = msort_r(data, count, size, cmp, buffer);
+ free(buffer);
+ return result;
+}
+
+static void write_tree(unsigned char * dest, HuffNode_t * tree, int nitems, struct BitEncoding * encoding) {
+ /*
+ * The example used to guide this function encodes the tree in a
+ * breadth-first manner. We attempt to emulate that here.
+ */
+
+ int i, j, k;
+
+ // There are (2 * nitems - 1) nodes in the binary tree. Allocate that.
+ HuffNode_t * traversal = calloc(2 * nitems - 1, sizeof(HuffNode_t));
+ if (traversal == NULL)
+ FATAL_ERROR("Fatal error while compressing Huff file.\n");
+
+ // The first node is the root of the tree.
+ traversal[0] = *tree;
+ i = 1;
+
+ // Copy the tree into a breadth-first ordering using brute force.
+ for (int depth = 1; i < 2 * nitems - 1; depth++) {
+ // Consider every possible path up to the current depth.
+ for (j = 0; i < 2 * nitems - 1 && j < 1 << depth; j++) {
+ // The index of the path is used to encode the path itself.
+ // Start from the most significant relevant bit and work our way down.
+ // Keep track of the current and previous nodes.
+ HuffNode_t * currNode = traversal;
+ HuffNode_t * parent = NULL;
+ for (k = 0; k < depth; k++) {
+ if (currNode->header.isLeaf)
+ break;
+ parent = currNode;
+ if ((j >> (depth - k - 1)) & 1)
+ currNode = currNode->branch.right;
+ else
+ currNode = currNode->branch.left;
+ }
+ // Check that the length of the current path equals the current depth.
+ if (k == depth) {
+ // Make sure we can encode the current branch.
+ // Bail here if we cannot.
+ // This is only applicable for 8-bit encodings.
+ if (traversal + i - parent > 128)
+ FATAL_ERROR("Fatal error while compressing Huff file: unable to encode binary tree.\n");
+ // Copy the current node, and update its parent.
+ traversal[i] = *currNode;
+ if (parent != NULL) {
+ if ((j & 1) == 1)
+ parent->branch.right = traversal + i;
+ else
+ parent->branch.left = traversal + i;
+ }
+ // Encode the path through the tree in the lookup table
+ if (traversal[i].header.isLeaf) {
+ encoding[traversal[i].leaf.key].nbits = depth;
+ encoding[traversal[i].leaf.key].bitstring = j;
+ }
+ i++;
+ }
+ }
+ }
+
+ // Encode the size of the tree.
+ // This is used by the decompressor to skip the tree.
+ dest[4] = nitems - 1;
+
+ // Encode each node in the tree.
+ for (i = 0; i < 2 * nitems - 1; i++) {
+ HuffNode_t * currNode = traversal + i;
+ if (currNode->header.isLeaf) {
+ dest[5 + i] = traversal[i].leaf.key;
+ } else {
+ dest[5 + i] = (((currNode->branch.right - traversal - i) / 2) - 1);
+ if (currNode->branch.left->header.isLeaf)
+ dest[5 + i] |= 0x80;
+ if (currNode->branch.right->header.isLeaf)
+ dest[5 + i] |= 0x40;
+ }
+ }
+
+ free(traversal);
+}
+
+static inline void write_32_le(unsigned char * dest, int * destPos, uint32_t * buff, int * buffPos) {
+ dest[*destPos] = *buff;
+ dest[*destPos + 1] = *buff >> 8;
+ dest[*destPos + 2] = *buff >> 16;
+ dest[*destPos + 3] = *buff >> 24;
+ *destPos += 4;
+ *buff = 0;
+ *buffPos = 0;
+}
+
+static inline void read_32_le(unsigned char * src, int * srcPos, uint32_t * buff) {
+ uint32_t tmp = src[*srcPos];
+ tmp |= src[*srcPos + 1] << 8;
+ tmp |= src[*srcPos + 2] << 16;
+ tmp |= src[*srcPos + 3] << 24;
+ *srcPos += 4;
+ *buff = tmp;
+}
+
+static void write_bits(unsigned char * dest, int * destPos, struct BitEncoding * encoding, int value, uint32_t * buff, int * buffBits) {
+ int nbits = encoding[value].nbits;
+ uint32_t bitstring = encoding[value].bitstring;
+
+ if (*buffBits + nbits >= 32) {
+ int diff = *buffBits + nbits - 32;
+ *buff <<= nbits - diff;
+ *buff |= bitstring >> diff;
+ bitstring &= ~(1 << diff);
+ nbits = diff;
+ write_32_le(dest, destPos, buff, buffBits);
+ }
+ if (nbits != 0) {
+ *buff <<= nbits;
+ *buff |= bitstring;
+ *buffBits += nbits;
+ }
+}
+
+/*
+=======================================
+MAIN COMPRESSION/DECOMPRESSION ROUTINES
+=======================================
+ */
+
+unsigned char * HuffCompress(unsigned char * src, int srcSize, int * compressedSize_p, int bitDepth) {
+ if (srcSize <= 0)
+ goto fail;
+
+ int worstCaseDestSize = 4 + (2 << bitDepth) + srcSize * 3;
+
+ unsigned char *dest = malloc(worstCaseDestSize);
+ if (dest == NULL)
+ goto fail;
+
+ int nitems = 1 << bitDepth;
+
+ HuffNode_t * freqs = calloc(nitems, sizeof(HuffNode_t));
+ if (freqs == NULL)
+ goto fail;
+
+ struct BitEncoding * encoding = calloc(nitems, sizeof(struct BitEncoding));
+ if (encoding == NULL)
+ goto fail;
+
+ // Set up the frequencies table. This will inform the tree.
+ for (int i = 0; i < nitems; i++) {
+ freqs[i].header.isLeaf = 1;
+ freqs[i].header.value = 0;
+ freqs[i].leaf.key = i;
+ }
+
+ // Count each nybble or byte.
+ for (int i = 0; i < srcSize; i++) {
+ if (bitDepth == 8) {
+ freqs[src[i]].header.value++;
+ } else {
+ freqs[src[i] >> 4].header.value++;
+ freqs[src[i] & 0xF].header.value++;
+ }
+ }
+
+#ifdef DEBUG
+ for (int i = 0; i < nitems; i++) {
+ fprintf(stderr, "%d: %d\n", i, freqs[i].header.value);
+ }
+#endif // DEBUG
+
+ // Sort the frequency table.
+ if (!msort(freqs, nitems, sizeof(HuffNode_t), cmp_tree))
+ goto fail;
+
+ // Prune zero-frequency values.
+ for (int i = 0; i < nitems; i++) {
+ if (freqs[i].header.value != 0) {
+ if (i > 0) {
+ for (int j = i; j < nitems; j++) {
+ freqs[j - i] = freqs[j];
+ }
+ nitems -= i;
+ }
+ break;
+ }
+ // This should never happen:
+ if (i == nitems - 1)
+ goto fail;
+ }
+
+ HuffNode_t * tree = calloc(nitems * 2 - 1, sizeof(HuffNode_t));
+ if (tree == NULL)
+ goto fail;
+
+ // Iteratively collapse the two least frequent nodes.
+ HuffNode_t * endptr = freqs + nitems - 2;
+
+ for (int i = 0; i < nitems - 1; i++) {
+ HuffNode_t * left = freqs;
+ HuffNode_t * right = freqs + 1;
+ tree[i * 2] = *right;
+ tree[i * 2 + 1] = *left;
+ for (int j = 0; j < nitems - i - 2; j++)
+ freqs[j] = freqs[j + 2];
+ endptr->header.isLeaf = 0;
+ endptr->header.value = tree[i * 2].header.value + tree[i * 2 + 1].header.value;
+ endptr->branch.left = tree + i * 2;
+ endptr->branch.right = tree + i * 2 + 1;
+ endptr--;
+ if (i < nitems - 2 && !msort(freqs, nitems - i - 1, sizeof(HuffNode_t), cmp_tree))
+ goto fail;
+ }
+
+ // Write the tree breadth-first, and create the path lookup table.
+ write_tree(dest, freqs, nitems, encoding);
+
+ free(tree);
+ free(freqs);
+
+ // Encode the data itself.
+ int destPos = 4 + nitems * 2;
+ uint32_t destBuf = 0;
+ uint32_t srcBuf = 0;
+ int destBitPos = 0;
+
+ for (int srcPos = 0; srcPos < srcSize;) {
+ read_32_le(src, &srcPos, &srcBuf);
+ for (int i = 0; i < 32 / bitDepth; i++) {
+ write_bits(dest, &destPos, encoding, srcBuf & (0xFF >> (8 - bitDepth)), &destBuf, &destBitPos);
+ srcBuf >>= bitDepth;
+ }
+ }
+
+ if (destBitPos != 0) {
+ write_32_le(dest, &destPos, &destBuf, &destBitPos);
+ }
+
+ free(encoding);
+
+ // Write the header.
+ dest[0] = bitDepth | 0x20;
+ dest[1] = srcSize;
+ dest[2] = srcSize >> 8;
+ dest[3] = srcSize >> 16;
+ *compressedSize_p = (destPos + 3) & ~3;
+ return dest;
+
+fail:
+ FATAL_ERROR("Fatal error while compressing Huff file.\n");
+}
+
+unsigned char * HuffDecompress(unsigned char * src, int srcSize, int * uncompressedSize_p) {
+ if (srcSize < 4)
+ goto fail;
+
+ int bitDepth = *src & 15;
+ if (bitDepth != 4 && bitDepth != 8)
+ goto fail;
+
+ int destSize = (src[3] << 16) | (src[2] << 8) | src[1];
+
+ unsigned char *dest = malloc(destSize);
+
+ if (dest == NULL)
+ goto fail;
+
+ int treePos = 5;
+ int treeSize = (src[4] + 1) * 2;
+ int srcPos = 4 + treeSize;
+ int destPos = 0;
+ int curValPos = 0;
+ uint32_t destTmp = 0;
+ uint32_t window;
+
+ for (;;)
+ {
+ if (srcPos >= srcSize)
+ goto fail;
+ read_32_le(src, &srcPos, &window);
+ for (int i = 0; i < 32; i++) {
+ int curBit = (window >> 31) & 1;
+ unsigned char treeView = src[treePos];
+ bool isLeaf = ((treeView << curBit) & 0x80) != 0;
+ treePos &= ~1; // align
+ treePos += ((treeView & 0x3F) + 1) * 2 + curBit;
+ if (isLeaf) {
+ destTmp >>= bitDepth;
+ destTmp |= (src[treePos] << (32 - bitDepth));
+ curValPos++;
+ if (curValPos == 32 / bitDepth) {
+ write_32_le(dest, &destPos, &destTmp, &curValPos);
+ if (destPos == destSize) {
+ *uncompressedSize_p = destSize;
+ return dest;
+ }
+ }
+ treePos = 5;
+ }
+ window <<= 1;
+ }
+ }
+
+fail:
+ FATAL_ERROR("Fatal error while decompressing Huff file.\n");
+}
diff --git a/tools/gbagfx/huff.h b/tools/gbagfx/huff.h
new file mode 100644
index 0000000..6002fe9
--- /dev/null
+++ b/tools/gbagfx/huff.h
@@ -0,0 +1,38 @@
+#ifndef HUFF_H
+#define HUFF_H
+
+union HuffNode;
+
+struct HuffData {
+ unsigned value:31;
+ unsigned isLeaf:1;
+};
+
+struct HuffLeaf {
+ struct HuffData header;
+ unsigned char key;
+};
+
+struct HuffBranch {
+ struct HuffData header;
+ union HuffNode * left;
+ union HuffNode * right;
+};
+
+union HuffNode {
+ struct HuffData header;
+ struct HuffLeaf leaf;
+ struct HuffBranch branch;
+};
+
+typedef union HuffNode HuffNode_t;
+
+struct BitEncoding {
+ unsigned long long nbits:6;
+ unsigned long long bitstring:58;
+};
+
+unsigned char * HuffCompress(unsigned char * buffer, int srcSize, int * compressedSize_p, int bitDepth);
+unsigned char * HuffDecompress(unsigned char * buffer, int srcSize, int * uncompressedSize_p);
+
+#endif //HUFF_H
diff --git a/tools/gbagfx/lz.c b/tools/gbagfx/lz.c
index c2ba3e3..97434ce 100644
--- a/tools/gbagfx/lz.c
+++ b/tools/gbagfx/lz.c
@@ -69,10 +69,8 @@ fail:
FATAL_ERROR("Fatal error while decompressing LZ file.\n");
}
-unsigned char *LZCompress(unsigned char *src, int srcSize, int *compressedSize)
+unsigned char *LZCompress(unsigned char *src, int srcSize, int *compressedSize, const int minDistance)
{
- const int minDistance = 2; // for compatibility with LZ77UnCompVram()
-
if (srcSize <= 0)
goto fail;
diff --git a/tools/gbagfx/lz.h b/tools/gbagfx/lz.h
index 164d622..90f56b6 100644
--- a/tools/gbagfx/lz.h
+++ b/tools/gbagfx/lz.h
@@ -4,6 +4,6 @@
#define LZ_H
unsigned char *LZDecompress(unsigned char *src, int srcSize, int *uncompressedSize);
-unsigned char *LZCompress(unsigned char *src, int srcSize, int *compressedSize);
+unsigned char *LZCompress(unsigned char *src, int srcSize, int *compressedSize, const int minDistance);
#endif // LZ_H
diff --git a/tools/gbagfx/main.c b/tools/gbagfx/main.c
index 86b0afa..aa0681f 100644
--- a/tools/gbagfx/main.c
+++ b/tools/gbagfx/main.c
@@ -12,6 +12,7 @@
#include "lz.h"
#include "rl.h"
#include "font.h"
+#include "huff.h"
struct CommandHandler
{
@@ -319,6 +320,7 @@ void HandlePngToFullwidthJapaneseFontCommand(char *inputPath, char *outputPath,
void HandleLZCompressCommand(char *inputPath, char *outputPath, int argc, char **argv)
{
int overflowSize = 0;
+ int minDistance = 2; // default, for compatibility with LZ77UnCompVram()
for (int i = 3; i < argc; i++)
{
@@ -337,6 +339,19 @@ void HandleLZCompressCommand(char *inputPath, char *outputPath, int argc, char *
if (overflowSize < 1)
FATAL_ERROR("Overflow size must be positive.\n");
}
+ else if (strcmp(option, "-search") == 0)
+ {
+ if (i + 1 >= argc)
+ FATAL_ERROR("No size following \"-overflow\".\n");
+
+ i++;
+
+ if (!ParseNumber(argv[i], NULL, 10, &minDistance))
+ FATAL_ERROR("Failed to parse LZ min search distance.\n");
+
+ if (minDistance < 1)
+ FATAL_ERROR("LZ min search distance must be positive.\n");
+ }
else
{
FATAL_ERROR("Unrecognized option \"%s\".\n", option);
@@ -353,7 +368,7 @@ void HandleLZCompressCommand(char *inputPath, char *outputPath, int argc, char *
unsigned char *buffer = ReadWholeFileZeroPadded(inputPath, &fileSize, overflowSize);
int compressedSize;
- unsigned char *compressedData = LZCompress(buffer, fileSize + overflowSize, &compressedSize);
+ unsigned char *compressedData = LZCompress(buffer, fileSize + overflowSize, &compressedSize, minDistance);
compressedData[1] = (unsigned char)fileSize;
compressedData[2] = (unsigned char)(fileSize >> 8);
@@ -411,6 +426,61 @@ void HandleRLDecompressCommand(char *inputPath, char *outputPath, int argc UNUSE
free(uncompressedData);
}
+void HandleHuffCompressCommand(char *inputPath, char *outputPath, int argc, char **argv)
+{
+ int fileSize;
+ int bitDepth = 4;
+
+ for (int i = 3; i < argc; i++)
+ {
+ char *option = argv[i];
+
+ if (strcmp(option, "-depth") == 0)
+ {
+ if (i + 1 >= argc)
+ FATAL_ERROR("No size following \"-depth\".\n");
+
+ i++;
+
+ if (!ParseNumber(argv[i], NULL, 10, &bitDepth))
+ FATAL_ERROR("Failed to parse bit depth.\n");
+
+ if (bitDepth != 4 && bitDepth != 8)
+ FATAL_ERROR("GBA only supports bit depth of 4 or 8.\n");
+ }
+ else
+ {
+ FATAL_ERROR("Unrecognized option \"%s\".\n", option);
+ }
+ }
+
+ unsigned char *buffer = ReadWholeFile(inputPath, &fileSize);
+
+ int compressedSize;
+ unsigned char *compressedData = HuffCompress(buffer, fileSize, &compressedSize, bitDepth);
+
+ free(buffer);
+
+ WriteWholeFile(outputPath, compressedData, compressedSize);
+
+ free(compressedData);
+}
+
+void HandleHuffDecompressCommand(char *inputPath, char *outputPath, int argc UNUSED, char **argv UNUSED)
+{
+ int fileSize;
+ unsigned char *buffer = ReadWholeFile(inputPath, &fileSize);
+
+ int uncompressedSize;
+ unsigned char *uncompressedData = HuffDecompress(buffer, fileSize, &uncompressedSize);
+
+ free(buffer);
+
+ WriteWholeFile(outputPath, uncompressedData, uncompressedSize);
+
+ free(uncompressedData);
+}
+
int main(int argc, char **argv)
{
if (argc < 3)
@@ -433,7 +503,9 @@ int main(int argc, char **argv)
{ "png", "hwjpnfont", HandlePngToHalfwidthJapaneseFontCommand },
{ "fwjpnfont", "png", HandleFullwidthJapaneseFontToPngCommand },
{ "png", "fwjpnfont", HandlePngToFullwidthJapaneseFontCommand },
+ { NULL, "huff", HandleHuffCompressCommand },
{ NULL, "lz", HandleLZCompressCommand },
+ { "huff", NULL, HandleHuffDecompressCommand },
{ "lz", NULL, HandleLZDecompressCommand },
{ NULL, "rl", HandleRLCompressCommand },
{ "rl", NULL, HandleRLDecompressCommand },
diff --git a/tools/jsonproc/Makefile b/tools/jsonproc/Makefile
index 721da10..47198b1 100644
--- a/tools/jsonproc/Makefile
+++ b/tools/jsonproc/Makefile
@@ -1,4 +1,4 @@
-CXX := g++
+CXX ?= g++
CXXFLAGS := -Wall -std=c++11 -O2
diff --git a/tools/jsonproc/jsonproc.exe b/tools/jsonproc/jsonproc.exe
index d127aa0..ba0a931 100755
--- a/tools/jsonproc/jsonproc.exe
+++ b/tools/jsonproc/jsonproc.exe
Binary files differ
diff --git a/tools/mapjson/Makefile b/tools/mapjson/Makefile
index 9a49be5..c1f703f 100644
--- a/tools/mapjson/Makefile
+++ b/tools/mapjson/Makefile
@@ -1,4 +1,4 @@
-CXX := g++
+CXX ?= g++
CXXFLAGS := -Wall -std=c++11 -O2
diff --git a/tools/mapjson/mapjson.exe b/tools/mapjson/mapjson.exe
index b49d5c6..d1af7cb 100755
--- a/tools/mapjson/mapjson.exe
+++ b/tools/mapjson/mapjson.exe
Binary files differ
diff --git a/tools/mid2agb/Makefile b/tools/mid2agb/Makefile
index 77f96db..451d4b3 100644
--- a/tools/mid2agb/Makefile
+++ b/tools/mid2agb/Makefile
@@ -1,4 +1,4 @@
-CXX := g++
+CXX ?= g++
CXXFLAGS := -std=c++11 -O2 -Wall -Wno-switch -Werror
diff --git a/tools/mid2agb/mid2agb.exe b/tools/mid2agb/mid2agb.exe
index 95472ec..48752d5 100755
--- a/tools/mid2agb/mid2agb.exe
+++ b/tools/mid2agb/mid2agb.exe
Binary files differ
diff --git a/tools/preproc/Makefile b/tools/preproc/Makefile
index 63dedda..8c48afe 100644
--- a/tools/preproc/Makefile
+++ b/tools/preproc/Makefile
@@ -1,4 +1,4 @@
-CXX := g++
+CXX ?= g++
CXXFLAGS := -std=c++11 -O2 -Wall -Wno-switch -Werror
diff --git a/tools/preproc/asm_file.cpp b/tools/preproc/asm_file.cpp
index 383010a..98805c9 100644
--- a/tools/preproc/asm_file.cpp
+++ b/tools/preproc/asm_file.cpp
@@ -475,9 +475,11 @@ void AsmFile::ExpectEmptyRestOfLine()
m_lineStart = m_pos;
m_lineNum++;
}
- else if (m_buffer[m_pos] == '\r')
+ else if (m_buffer[m_pos] == '\r' && m_buffer[m_pos + 1] == '\n')
{
- RaiseError("only Unix-style LF newlines are supported");
+ m_pos += 2;
+ m_lineStart = m_pos;
+ m_lineNum++;
}
else
{
diff --git a/tools/preproc/preproc.exe b/tools/preproc/preproc.exe
index 92f0f63..4ed5198 100755
--- a/tools/preproc/preproc.exe
+++ b/tools/preproc/preproc.exe
Binary files differ
diff --git a/tools/ramscrgen/Makefile b/tools/ramscrgen/Makefile
index 858db1a..4e901a2 100644
--- a/tools/ramscrgen/Makefile
+++ b/tools/ramscrgen/Makefile
@@ -1,4 +1,4 @@
-CXX := g++
+CXX ?= g++
CXXFLAGS := -std=c++11 -O2 -Wall -Wno-switch -Werror
diff --git a/tools/ramscrgen/elf.cpp b/tools/ramscrgen/elf.cpp
index 7599fe0..7e78704 100644
--- a/tools/ramscrgen/elf.cpp
+++ b/tools/ramscrgen/elf.cpp
@@ -10,6 +10,8 @@
#define SHN_COMMON 0xFFF2
static std::string s_elfPath;
+static std::string s_archiveFilePath;
+static std::string s_archiveObjectPath;
static FILE *s_file;
@@ -22,6 +24,7 @@ static std::uint32_t s_symtabOffset;
static std::uint32_t s_strtabOffset;
static std::uint32_t s_symbolCount;
+static std::uint32_t s_elfFileOffset;
struct Symbol
{
@@ -31,7 +34,7 @@ struct Symbol
static void Seek(long offset)
{
- if (std::fseek(s_file, offset, SEEK_SET) != 0)
+ if (std::fseek(s_file, s_elfFileOffset + offset, SEEK_SET) != 0)
FATAL_ERROR("error: failed to seek to %ld in \"%s\"", offset, s_elfPath.c_str());
}
@@ -98,6 +101,18 @@ static void VerifyElfIdent()
FATAL_ERROR("error: \"%s\" not little-endian ELF\n", s_elfPath.c_str());
}
+static void VerifyAr()
+{
+ char expectedMagic[8] = {'!', '<', 'a', 'r', 'c', 'h', '>', '\n'};
+ char magic[8];
+
+ if (std::fread(magic, 8, 1, s_file) != 1)
+ FATAL_ERROR("error: failed to read AR magic from \"%s\"\n", s_archiveFilePath.c_str());
+
+ if (std::memcmp(magic, expectedMagic, 8) != 0)
+ FATAL_ERROR("error: AR magic did not match in \"%s\"\n", s_archiveFilePath.c_str());
+}
+
static void ReadElfHeader()
{
Seek(0x20);
@@ -108,6 +123,40 @@ static void ReadElfHeader()
s_shstrtabIndex = ReadInt16();
}
+static void FindArObj()
+{
+ char file_ident[17] = {0};
+ char filesize_s[11] = {0};
+ char expectedEndMagic[2] = { 0x60, 0x0a };
+ char end_magic[2];
+ std::size_t filesize;
+
+ Seek(8);
+ while (!std::feof(s_file)) {
+ if (std::fread(file_ident, 16, 1, s_file) != 1)
+ FATAL_ERROR("error: failed to read file ident in \"%s\"\n", s_archiveFilePath.c_str());
+ Skip(32);
+ if (std::fread(filesize_s, 10, 1, s_file) != 1)
+ FATAL_ERROR("error: failed to read filesize in \"%s\"\n", s_archiveFilePath.c_str());
+ if (std::fread(end_magic, 2, 1, s_file) != 1)
+ FATAL_ERROR("error: failed to read end sentinel in \"%s\"\n", s_archiveFilePath.c_str());
+ if (std::memcmp(end_magic, expectedEndMagic, 2) != 0)
+ FATAL_ERROR("error: corrupted archive header in \"%s\" at \"%s\"\n", s_archiveFilePath.c_str(), file_ident);
+
+ char * ptr = std::strchr(file_ident, '/');
+ if (ptr != nullptr)
+ *ptr = 0;
+ filesize = std::strtoul(filesize_s, nullptr, 10);
+ if (std::strncmp(s_archiveObjectPath.c_str(), file_ident, 16) == 0) {
+ s_elfFileOffset = std::ftell(s_file);
+ return;
+ }
+ Skip(filesize);
+ }
+
+ FATAL_ERROR("error: could not find object \"%s\" in archive \"%s\"\n", s_archiveObjectPath.c_str(), s_archiveFilePath.c_str());
+}
+
static std::string GetSectionName(std::uint32_t shstrtabOffset, int index)
{
Seek(s_sectionHeaderOffset + s_sectionHeaderEntrySize * index);
@@ -153,21 +202,14 @@ static void FindTableOffsets()
FATAL_ERROR("error: couldn't find .strtab section in \"%s\"\n", s_elfPath.c_str());
}
-std::map<std::string, std::uint32_t> GetCommonSymbols(std::string path)
+static std::map<std::string, std::uint32_t> GetCommonSymbols_Shared()
{
- s_elfPath = path;
-
- std::map<std::string, std::uint32_t> commonSymbols;
-
- s_file = std::fopen(s_elfPath.c_str(), "rb");
-
- if (s_file == NULL)
- FATAL_ERROR("error: failed to open \"%s\" for reading\n", path.c_str());
-
VerifyElfIdent();
ReadElfHeader();
FindTableOffsets();
-
+
+ std::map<std::string, std::uint32_t> commonSymbols;
+
std::vector<Symbol> commonSymbolVec;
Seek(s_symtabOffset);
@@ -193,3 +235,38 @@ std::map<std::string, std::uint32_t> GetCommonSymbols(std::string path)
return commonSymbols;
}
+
+std::map<std::string, std::uint32_t> GetCommonSymbolsFromLib(std::string sourcePath, std::string libpath)
+{
+ std::size_t colonPos = libpath.find(':');
+ if (colonPos == std::string::npos)
+ FATAL_ERROR("error: missing colon separator in libfile \"%s\"\n", s_elfPath.c_str());
+
+ s_archiveObjectPath = libpath.substr(colonPos + 1);
+ s_archiveFilePath = sourcePath + "/" + libpath.substr(1, colonPos - 1);
+ s_elfPath = sourcePath + "/" + libpath.substr(1);
+
+ s_file = std::fopen(s_archiveFilePath.c_str(), "rb");
+
+ if (s_file == NULL)
+ FATAL_ERROR("error: failed to open \"%s\" for reading\n", s_archiveFilePath.c_str());
+
+ VerifyAr();
+ FindArObj();
+ return GetCommonSymbols_Shared();
+}
+
+std::map<std::string, std::uint32_t> GetCommonSymbols(std::string sourcePath, std::string path)
+{
+ s_elfFileOffset = 0;
+ if (path[0] == '*')
+ return GetCommonSymbolsFromLib(sourcePath, path);
+
+ s_elfPath = sourcePath + "/" + path;
+ s_file = std::fopen(s_elfPath.c_str(), "rb");
+
+ if (s_file == NULL)
+ FATAL_ERROR("error: failed to open \"%s\" for reading\n", path.c_str());
+
+ return GetCommonSymbols_Shared();
+}
diff --git a/tools/ramscrgen/elf.h b/tools/ramscrgen/elf.h
index 0bfdd69..3704860 100644
--- a/tools/ramscrgen/elf.h
+++ b/tools/ramscrgen/elf.h
@@ -25,6 +25,6 @@
#include <map>
#include <string>
-std::map<std::string, std::uint32_t> GetCommonSymbols(std::string path);
+std::map<std::string, std::uint32_t> GetCommonSymbols(std::string sourcePath, std::string path);
#endif // ELF_H
diff --git a/tools/ramscrgen/main.cpp b/tools/ramscrgen/main.cpp
index 6c4f4bb..5e5894f 100644
--- a/tools/ramscrgen/main.cpp
+++ b/tools/ramscrgen/main.cpp
@@ -27,9 +27,15 @@
void HandleCommonInclude(std::string filename, std::string sourcePath, std::string symOrderPath, std::string lang)
{
- auto commonSymbols = GetCommonSymbols(sourcePath + "/" + filename);
+ auto commonSymbols = GetCommonSymbols(sourcePath, filename);
+ std::size_t dotIndex;
- std::size_t dotIndex = filename.find_last_of('.');
+ if (filename[0] == '*') {
+ dotIndex = filename.find_last_of(':');
+ filename = filename.substr(dotIndex + 1);
+ }
+
+ dotIndex = filename.find_last_of('.');
if (dotIndex == std::string::npos)
FATAL_ERROR("error: \"%s\" doesn't have a file extension\n", filename.c_str());
@@ -73,7 +79,7 @@ void HandleCommonInclude(std::string filename, std::string sourcePath, std::stri
}
}
-void ConvertSymFile(std::string filename, std::string sectionName, std::string lang, bool common, std::string sourcePath, std::string commonSymPath)
+void ConvertSymFile(std::string filename, std::string sectionName, std::string lang, bool common, std::string sourcePath, std::string commonSymPath, std::string libSourcePath)
{
SymFile symFile(filename);
@@ -91,7 +97,7 @@ void ConvertSymFile(std::string filename, std::string sectionName, std::string l
symFile.ExpectEmptyRestOfLine();
printf(". = ALIGN(4);\n");
if (common)
- HandleCommonInclude(incFilename, sourcePath, commonSymPath, lang);
+ HandleCommonInclude(incFilename, incFilename[0] == '*' ? libSourcePath : sourcePath, commonSymPath, lang);
else
printf("%s(%s);\n", incFilename.c_str(), sectionName.c_str());
break;
@@ -148,6 +154,7 @@ int main(int argc, char **argv)
std::string lang = std::string(argv[3]);
std::string sourcePath;
std::string commonSymPath;
+ std::string libSourcePath;
if (argc > 4)
{
@@ -166,8 +173,15 @@ int main(int argc, char **argv)
sourcePath = paths.substr(0, commaPos);
commonSymPath = paths.substr(commaPos + 1);
+ commaPos = commonSymPath.find(',');
+ if (commaPos == std::string::npos) {
+ libSourcePath = "tools/agbcc/lib";
+ } else {
+ libSourcePath = commonSymPath.substr(commaPos + 1);
+ commonSymPath = commonSymPath.substr(0, commaPos);
+ }
}
- ConvertSymFile(symFileName, sectionName, lang, common, sourcePath, commonSymPath);
+ ConvertSymFile(symFileName, sectionName, lang, common, sourcePath, commonSymPath, libSourcePath);
return 0;
}
diff --git a/tools/ramscrgen/ramscrgen.exe b/tools/ramscrgen/ramscrgen.exe
index 9897131..a05a068 100755
--- a/tools/ramscrgen/ramscrgen.exe
+++ b/tools/ramscrgen/ramscrgen.exe
Binary files differ
diff --git a/tools/rsfont/Makefile b/tools/rsfont/Makefile
index abe1cab..930a92b 100644
--- a/tools/rsfont/Makefile
+++ b/tools/rsfont/Makefile
@@ -1,4 +1,4 @@
-CC = gcc
+CC ?= gcc
CFLAGS = -Wall -Wextra -Werror -std=c11 -O2 -DPNG_SKIP_SETJMP_CHECK
diff --git a/tools/rsfont/rsfont.exe b/tools/rsfont/rsfont.exe
index fde65d1..ad8ffa5 100755
--- a/tools/rsfont/rsfont.exe
+++ b/tools/rsfont/rsfont.exe
Binary files differ
diff --git a/tools/scaninc/Makefile b/tools/scaninc/Makefile
index 1516f15..52e663d 100644
--- a/tools/scaninc/Makefile
+++ b/tools/scaninc/Makefile
@@ -1,4 +1,4 @@
-CXX = g++
+CXX ?= g++
CXXFLAGS = -Wall -Werror -std=c++11 -O2
diff --git a/tools/scaninc/scaninc.cpp b/tools/scaninc/scaninc.cpp
index b95cbd0..a3e40c5 100644
--- a/tools/scaninc/scaninc.cpp
+++ b/tools/scaninc/scaninc.cpp
@@ -97,19 +97,26 @@ int main(int argc, char **argv)
}
for (auto include : file.GetIncludes())
{
+ bool exists = false;
+ std::string path("");
for (auto includeDir : includeDirs)
{
- std::string path(includeDir + include);
+ path = includeDir + include;
if (CanOpenFile(path))
{
- bool inserted = dependencies.insert(path).second;
- if (inserted)
- {
- filesToProcess.push(path);
- }
+ exists = true;
break;
}
}
+ if (!exists && file.FileType() == SourceFileType::Asm)
+ {
+ path = include;
+ }
+ bool inserted = dependencies.insert(path).second;
+ if (inserted && exists)
+ {
+ filesToProcess.push(path);
+ }
}
includeDirs.pop_back();
}
diff --git a/tools/scaninc/scaninc.exe b/tools/scaninc/scaninc.exe
index dff1f03..0723291 100755
--- a/tools/scaninc/scaninc.exe
+++ b/tools/scaninc/scaninc.exe
Binary files differ
diff --git a/tools/scaninc/source_file.cpp b/tools/scaninc/source_file.cpp
index f23ff6d..df31282 100644
--- a/tools/scaninc/source_file.cpp
+++ b/tools/scaninc/source_file.cpp
@@ -89,6 +89,11 @@ SourceFile::SourceFile(std::string path)
}
}
+SourceFileType SourceFile::FileType()
+{
+ return m_file_type;
+}
+
SourceFile::~SourceFile()
{
if (m_file_type == SourceFileType::Cpp || m_file_type == SourceFileType::Header)
diff --git a/tools/scaninc/source_file.h b/tools/scaninc/source_file.h
index f7b6412..854b3f1 100644
--- a/tools/scaninc/source_file.h
+++ b/tools/scaninc/source_file.h
@@ -50,6 +50,7 @@ public:
const std::set<std::string>& GetIncbins();
const std::set<std::string>& GetIncludes();
std::string& GetSrcDir();
+ SourceFileType FileType();
private:
union InnerUnion {