summaryrefslogtreecommitdiff
path: root/tools/gbagfx/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/gbagfx/main.c')
-rw-r--r--tools/gbagfx/main.c146
1 files changed, 134 insertions, 12 deletions
diff --git a/tools/gbagfx/main.c b/tools/gbagfx/main.c
index 86b0afa53..b02f4d9f5 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
{
@@ -26,7 +27,17 @@ void ConvertGbaToPng(char *inputPath, char *outputPath, struct GbaToPngOptions *
if (options->paletteFilePath != NULL)
{
- ReadGbaPalette(options->paletteFilePath, &image.palette);
+ char *paletteFileExtension = GetFileExtensionAfterDot(options->paletteFilePath);
+
+ if (strcmp(paletteFileExtension, "gbapal") == 0)
+ {
+ ReadGbaPalette(options->paletteFilePath, &image.palette);
+ }
+ else
+ {
+ ReadJascPalette(options->paletteFilePath, &image.palette);
+ }
+
image.hasPalette = true;
}
else
@@ -58,7 +69,7 @@ void ConvertPngToGba(char *inputPath, char *outputPath, struct PngToGbaOptions *
void HandleGbaToPngCommand(char *inputPath, char *outputPath, int argc, char **argv)
{
- char *inputFileExtension = GetFileExtension(inputPath);
+ char *inputFileExtension = GetFileExtensionAfterDot(inputPath);
struct GbaToPngOptions options;
options.paletteFilePath = NULL;
options.bitDepth = inputFileExtension[0] - '0';
@@ -137,7 +148,7 @@ void HandleGbaToPngCommand(char *inputPath, char *outputPath, int argc, char **a
void HandlePngToGbaCommand(char *inputPath, char *outputPath, int argc, char **argv)
{
- char *outputFileExtension = GetFileExtension(outputPath);
+ char *outputFileExtension = GetFileExtensionAfterDot(outputPath);
int bitDepth = outputFileExtension[0] - '0';
struct PngToGbaOptions options;
options.numTiles = 0;
@@ -197,9 +208,17 @@ void HandlePngToGbaCommand(char *inputPath, char *outputPath, int argc, char **a
ConvertPngToGba(inputPath, outputPath, &options);
}
+void HandlePngToJascPaletteCommand(char *inputPath, char *outputPath, int argc UNUSED, char **argv UNUSED)
+{
+ struct Palette palette = {0};
+
+ ReadPngPalette(inputPath, &palette);
+ WriteJascPalette(outputPath, &palette);
+}
+
void HandlePngToGbaPaletteCommand(char *inputPath, char *outputPath, int argc UNUSED, char **argv UNUSED)
{
- struct Palette palette;
+ struct Palette palette = {0};
ReadPngPalette(inputPath, &palette);
WriteGbaPalette(outputPath, &palette);
@@ -207,7 +226,7 @@ void HandlePngToGbaPaletteCommand(char *inputPath, char *outputPath, int argc UN
void HandleGbaToJascPaletteCommand(char *inputPath, char *outputPath, int argc UNUSED, char **argv UNUSED)
{
- struct Palette palette;
+ struct Palette palette = {0};
ReadGbaPalette(inputPath, &palette);
WriteJascPalette(outputPath, &palette);
@@ -240,7 +259,7 @@ void HandleJascToGbaPaletteCommand(char *inputPath, char *outputPath, int argc,
}
}
- struct Palette palette;
+ struct Palette palette = {0};
ReadJascPalette(inputPath, &palette);
@@ -319,6 +338,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 +357,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 +386,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,8 +444,65 @@ 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)
{
+ char converted = 0;
+
if (argc < 3)
FATAL_ERROR("Usage: gbagfx INPUT_PATH OUTPUT_PATH [options...]\n");
@@ -425,6 +515,7 @@ int main(int argc, char **argv)
{ "png", "4bpp", HandlePngToGbaCommand },
{ "png", "8bpp", HandlePngToGbaCommand },
{ "png", "gbapal", HandlePngToGbaPaletteCommand },
+ { "png", "pal", HandlePngToJascPaletteCommand },
{ "gbapal", "pal", HandleGbaToJascPaletteCommand },
{ "pal", "gbapal", HandleJascToGbaPaletteCommand },
{ "latfont", "png", HandleLatinFontToPngCommand },
@@ -433,7 +524,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 },
@@ -442,14 +535,36 @@ int main(int argc, char **argv)
char *inputPath = argv[1];
char *outputPath = argv[2];
- char *inputFileExtension = GetFileExtension(inputPath);
- char *outputFileExtension = GetFileExtension(outputPath);
+ char *inputFileExtension = GetFileExtensionAfterDot(inputPath);
+ char *outputFileExtension = GetFileExtensionAfterDot(outputPath);
if (inputFileExtension == NULL)
FATAL_ERROR("Input file \"%s\" has no extension.\n", inputPath);
if (outputFileExtension == NULL)
- FATAL_ERROR("Output file \"%s\" has no extension.\n", outputPath);
+ {
+ outputFileExtension = GetFileExtension(outputPath);
+
+ if (*outputFileExtension == '.')
+ outputFileExtension++;
+
+ if (*outputFileExtension == 0)
+ FATAL_ERROR("Output file \"%s\" has no extension.\n", outputPath);
+
+ size_t newOutputPathSize = strlen(inputPath) - strlen(inputFileExtension) + strlen(outputFileExtension);
+ outputPath = (char *)malloc(newOutputPathSize);
+
+ for (int i = 0; i < newOutputPathSize; i++)
+ {
+ outputPath[i] = inputPath[i];
+
+ if (outputPath[i] == '.')
+ {
+ strcpy(&outputPath[i + 1], outputFileExtension);
+ break;
+ }
+ }
+ }
for (int i = 0; handlers[i].function != NULL; i++)
{
@@ -457,9 +572,16 @@ int main(int argc, char **argv)
&& (handlers[i].outputFileExtension == NULL || strcmp(handlers[i].outputFileExtension, outputFileExtension) == 0))
{
handlers[i].function(inputPath, outputPath, argc, argv);
- return 0;
+ converted = 1;
+ break;
}
}
- FATAL_ERROR("Don't know how to convert \"%s\" to \"%s\".\n", inputPath, outputPath);
+ if (outputPath != argv[2])
+ free(outputPath);
+
+ if (!converted)
+ FATAL_ERROR("Don't know how to convert \"%s\" to \"%s\".\n", argv[1], argv[2]);
+
+ return 0;
}