diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/msgenc/.gitignore | 1 | ||||
-rw-r--r-- | tools/nitrogfx/gfx.c | 68 | ||||
-rw-r--r-- | tools/nitrogfx/gfx.h | 1 | ||||
-rw-r--r-- | tools/nitrogfx/main.c | 101 |
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 }, |