summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/msgenc/.gitignore1
-rw-r--r--tools/nitrogfx/gfx.c68
-rw-r--r--tools/nitrogfx/gfx.h1
-rw-r--r--tools/nitrogfx/main.c101
4 files changed, 170 insertions, 1 deletions
diff --git a/tools/msgenc/.gitignore b/tools/msgenc/.gitignore
new file mode 100644
index 00000000..48de3992
--- /dev/null
+++ b/tools/msgenc/.gitignore
@@ -0,0 +1 @@
+msgenc \ No newline at end of file
diff --git a/tools/nitrogfx/gfx.c b/tools/nitrogfx/gfx.c
index ac156575..31ebf64b 100644
--- a/tools/nitrogfx/gfx.c
+++ b/tools/nitrogfx/gfx.c
@@ -246,6 +246,68 @@ void ReadImage(char *path, int tilesWidth, int bitDepth, int metatileWidth, int
free(buffer);
}
+void ReadNtrImage(char *path, int tilesWidth, int bitDepth, int metatileWidth, int metatileHeight, struct Image *image, bool invertColors)
+{
+ int fileSize;
+ unsigned char *buffer = ReadWholeFile(path, &fileSize);
+
+ if (memcmp(buffer, "RGCN", 4) != 0)
+ {
+ FATAL_ERROR("Not a valid NCGR character file.\n");
+ }
+
+ unsigned char *charHeader = buffer + 0x10;
+
+ if (memcmp(charHeader, "RAHC", 4) != 0)
+ {
+ FATAL_ERROR("No valid CHAR file after NCLR header.\n");
+ }
+
+ bitDepth = bitDepth ? bitDepth : (charHeader[0xC] == 3 ? 4 : 8);
+
+ if (bitDepth == 4)
+ {
+ image->palette.numColors = 16;
+ }
+
+ unsigned char *imageData = charHeader + 0x20;
+
+ int tileSize = bitDepth * 8;
+
+ int numTiles = (charHeader[0x18] + (charHeader[0x19] << 8) + (charHeader[0x1A] << 16) + (charHeader[0x1B] << 24))
+ / (64 / (8 / bitDepth));
+
+ int tilesHeight = (numTiles + tilesWidth - 1) / tilesWidth;
+
+ if (tilesWidth % metatileWidth != 0)
+ FATAL_ERROR("The width in tiles (%d) isn't a multiple of the specified metatile width (%d)", tilesWidth, metatileWidth);
+
+ if (tilesHeight % metatileHeight != 0)
+ FATAL_ERROR("The height in tiles (%d) isn't a multiple of the specified metatile height (%d)", tilesHeight, metatileHeight);
+
+
+ image->width = tilesWidth * 8;
+ image->height = tilesHeight * 8;
+ image->bitDepth = bitDepth;
+ image->pixels = calloc(tilesWidth * tilesHeight, tileSize);
+
+ if (image->pixels == NULL)
+ FATAL_ERROR("Failed to allocate memory for pixels.\n");
+
+ int metatilesWide = tilesWidth / metatileWidth;
+
+ switch (bitDepth) {
+ case 4:
+ ConvertFromTiles4Bpp(imageData, image->pixels, numTiles, metatilesWide, metatileWidth, metatileHeight, invertColors);
+ break;
+ case 8:
+ ConvertFromTiles8Bpp(imageData, image->pixels, numTiles, metatilesWide, metatileWidth, metatileHeight, invertColors);
+ break;
+ }
+
+ free(buffer);
+}
+
void WriteImage(char *path, int numTiles, int bitDepth, int metatileWidth, int metatileHeight, struct Image *image, bool invertColors)
{
int tileSize = bitDepth * 8;
@@ -343,7 +405,9 @@ void ReadNtrPalette(char *path, struct Palette *palette)
if ((fileSize - 0x28) % 2 != 0)
FATAL_ERROR("The file size (%d) is not a multiple of 2.\n", fileSize);
- palette->numColors = (fileSize - 0x28) / 2; //remove header and divide by 2
+ palette->bitDepth = paletteHeader[0x8] == 3 ? 4 : 8;
+
+ palette->numColors = palette->bitDepth == 4 ? 16 : 256; //remove header and divide by 2
unsigned char *paletteData = paletteHeader + 0x18;
@@ -404,6 +468,8 @@ void WriteNtrPalette(char *path, struct Palette *palette, bool ncpr)
palHeader[6] = (extSize >> 16) & 0xFF;
palHeader[7] = (extSize >> 24) & 0xFF;
+ if (!palette->bitDepth)
+ palette->bitDepth = 4;
//bit depth
palHeader[8] = palette->bitDepth == 4 ? 0x03: 0x04;
diff --git a/tools/nitrogfx/gfx.h b/tools/nitrogfx/gfx.h
index fc57380e..9835021e 100644
--- a/tools/nitrogfx/gfx.h
+++ b/tools/nitrogfx/gfx.h
@@ -29,6 +29,7 @@ struct Image {
};
void ReadImage(char *path, int tilesWidth, int bitDepth, int metatileWidth, int metatileHeight, struct Image *image, bool invertColors);
+void ReadNtrImage(char *path, int tilesWidth, int bitDepth, int metatileWidth, int metatileHeight, struct Image *image, bool invertColors);
void WriteImage(char *path, int numTiles, int bitDepth, int metatileWidth, int metatileHeight, struct Image *image, bool invertColors);
void FreeImage(struct Image *image);
void ReadGbaPalette(char *path, struct Palette *palette);
diff --git a/tools/nitrogfx/main.c b/tools/nitrogfx/main.c
index 7365cf39..aa46d7b0 100644
--- a/tools/nitrogfx/main.c
+++ b/tools/nitrogfx/main.c
@@ -44,6 +44,29 @@ void ConvertGbaToPng(char *inputPath, char *outputPath, struct GbaToPngOptions *
FreeImage(&image);
}
+void ConvertNtrToPng(char *inputPath, char *outputPath, struct GbaToPngOptions *options)
+{
+ struct Image image;
+
+ if (options->paletteFilePath != NULL)
+ {
+ ReadNtrPalette(options->paletteFilePath, &image.palette);
+ image.hasPalette = true;
+ }
+ else
+ {
+ image.hasPalette = false;
+ }
+
+ ReadNtrImage(inputPath, options->width, 0, options->metatileWidth, options->metatileHeight, &image, !image.hasPalette);
+
+ image.hasTransparency = options->hasTransparency;
+
+ WritePng(outputPath, &image);
+
+ FreeImage(&image);
+}
+
void ConvertPngToGba(char *inputPath, char *outputPath, struct PngToGbaOptions *options)
{
struct Image image;
@@ -136,6 +159,83 @@ void HandleGbaToPngCommand(char *inputPath, char *outputPath, int argc, char **a
ConvertGbaToPng(inputPath, outputPath, &options);
}
+void HandleNtrToPngCommand(char *inputPath, char *outputPath, int argc, char **argv)
+{
+ struct GbaToPngOptions options;
+ options.paletteFilePath = NULL;
+ options.hasTransparency = false;
+ options.width = 1;
+ options.metatileWidth = 1;
+ options.metatileHeight = 1;
+
+ for (int i = 3; i < argc; i++)
+ {
+ char *option = argv[i];
+
+ if (strcmp(option, "-palette") == 0)
+ {
+ if (i + 1 >= argc)
+ FATAL_ERROR("No palette file path following \"-palette\".\n");
+
+ i++;
+
+ options.paletteFilePath = argv[i];
+ }
+ else if (strcmp(option, "-object") == 0)
+ {
+ options.hasTransparency = true;
+ }
+ else if (strcmp(option, "-width") == 0)
+ {
+ if (i + 1 >= argc)
+ FATAL_ERROR("No width following \"-width\".\n");
+
+ i++;
+
+ if (!ParseNumber(argv[i], NULL, 10, &options.width))
+ FATAL_ERROR("Failed to parse width.\n");
+
+ if (options.width < 1)
+ FATAL_ERROR("Width must be positive.\n");
+ }
+ else if (strcmp(option, "-mwidth") == 0)
+ {
+ if (i + 1 >= argc)
+ FATAL_ERROR("No metatile width value following \"-mwidth\".\n");
+
+ i++;
+
+ if (!ParseNumber(argv[i], NULL, 10, &options.metatileWidth))
+ FATAL_ERROR("Failed to parse metatile width.\n");
+
+ if (options.metatileWidth < 1)
+ FATAL_ERROR("metatile width must be positive.\n");
+ }
+ else if (strcmp(option, "-mheight") == 0)
+ {
+ if (i + 1 >= argc)
+ FATAL_ERROR("No metatile height value following \"-mheight\".\n");
+
+ i++;
+
+ if (!ParseNumber(argv[i], NULL, 10, &options.metatileHeight))
+ FATAL_ERROR("Failed to parse metatile height.\n");
+
+ if (options.metatileHeight < 1)
+ FATAL_ERROR("metatile height must be positive.\n");
+ }
+ else
+ {
+ FATAL_ERROR("Unrecognized option \"%s\".\n", option);
+ }
+ }
+
+ if (options.metatileWidth > options.width)
+ options.width = options.metatileWidth;
+
+ ConvertNtrToPng(inputPath, outputPath, &options);
+}
+
void HandlePngToGbaCommand(char *inputPath, char *outputPath, int argc, char **argv)
{
char *outputFileExtension = GetFileExtension(outputPath);
@@ -541,6 +641,7 @@ int main(int argc, char **argv)
{ "1bpp", "png", HandleGbaToPngCommand },
{ "4bpp", "png", HandleGbaToPngCommand },
{ "8bpp", "png", HandleGbaToPngCommand },
+ { "NCGR", "png", HandleNtrToPngCommand },
{ "png", "1bpp", HandlePngToGbaCommand },
{ "png", "4bpp", HandlePngToGbaCommand },
{ "png", "8bpp", HandlePngToGbaCommand },