diff --git a/tools/nitrogfx/gfx.c b/tools/nitrogfx/gfx.c index 996f1761f5..9d56fac586 100644 --- a/tools/nitrogfx/gfx.c +++ b/tools/nitrogfx/gfx.c @@ -1316,9 +1316,12 @@ void ReadGbaPalette(char *path, struct Palette *palette) free(data); } -void ReadNtrPalette(char *path, struct Palette *palette, int bitdepth, int palIndex, bool inverted, bool convertTo8Bpp) +#define PLTT_HEADER_SIZE 0x18 + +void ReadNtrPalette(char *path, struct Palette *palette, int bitdepth, int palIndex, bool convertTo8Bpp, bool verbose) { int fileSize; + bool inverted = false; unsigned char *data = ReadWholeFile(path, &fileSize); if (memcmp(data, "RLCN", 4) != 0 && memcmp(data, "RPCN", 4) != 0) //NCLR / NCPR @@ -1340,8 +1343,16 @@ void ReadNtrPalette(char *path, struct Palette *palette, int bitdepth, int palIn bitdepth = bitdepth ? bitdepth : palette->bitDepth; + // Some NCLRs are known to exist which have an "inverted" palette size, which is represented as + // 0x200 minus the true size in bytes. So, we must verify the palette size stored in the header + // with the section size (which is authoritative and never inverted in this way). + size_t sectionSize = (paletteHeader[0x04]) | (paletteHeader[0x05] << 8) | (paletteHeader[0x06] << 16) | (paletteHeader[0x07] << 24); size_t paletteSize = (paletteHeader[0x10]) | (paletteHeader[0x11] << 8) | (paletteHeader[0x12] << 16) | (paletteHeader[0x13] << 24); - if (inverted) paletteSize = 0x200 - paletteSize; + if (sectionSize - PLTT_HEADER_SIZE != paletteSize) { + paletteSize = 0x200 - paletteSize; + inverted = true; + } + if (palIndex == 0) { palette->numColors = paletteSize / 2; } else { @@ -1349,7 +1360,7 @@ void ReadNtrPalette(char *path, struct Palette *palette, int bitdepth, int palIn --palIndex; } - unsigned char *paletteData = paletteHeader + 0x18; + unsigned char *paletteData = paletteHeader + PLTT_HEADER_SIZE; for (int i = 0; i < 256; i++) { @@ -1368,6 +1379,36 @@ void ReadNtrPalette(char *path, struct Palette *palette, int bitdepth, int palIn } } + if (verbose) { + printf("Suggested NCLR options: "); + + if (paletteHeader[0x0A]) { + printf("-comp %d ", paletteHeader[0x0A]); + } + + if (data[0x01] == 'P') { + printf("-ncpr "); + } + + if (palette->numColors < 256) { + printf("-nopad "); + } + + size_t truePaletteSize = paletteSize; + if (inverted) { + printf("-invertsize "); + truePaletteSize = 0x200 - truePaletteSize; + } + + uint16_t sectionCount = (data[0x0F] << 8) | data[0x0E]; + if (sectionCount == 2) { + printf("-pcmp "); + } + + printf("-bitdepth %d ", bitdepth); + puts(""); + } + free(data); } diff --git a/tools/nitrogfx/gfx.h b/tools/nitrogfx/gfx.h index 325e837467..f0390bf99e 100644 --- a/tools/nitrogfx/gfx.h +++ b/tools/nitrogfx/gfx.h @@ -59,7 +59,7 @@ void WriteNtrImage(char *path, int numTiles, int bitDepth, int colsPerChunk, int uint32_t encodeMode, uint32_t mappingType, uint32_t key, bool wrongSize, bool convertTo4Bpp, int rotate); void FreeImage(struct Image *image); void ReadGbaPalette(char *path, struct Palette *palette); -void ReadNtrPalette(char *path, struct Palette *palette, int bitdepth, int palIndex, bool inverted, bool convertTo8Bpp); +void ReadNtrPalette(char *path, struct Palette *palette, int bitdepth, int palIndex, bool convertTo8Bpp, bool verbose); void WriteGbaPalette(char *path, struct Palette *palette); void WriteNtrPalette(char *path, struct Palette *palette, bool ncpr, bool ir, int bitdepth, bool pad, int compNum, bool pcmp, int pcmpStartIndex, bool inverted, bool convertTo4Bpp); void ReadNtrCell(char *path, struct JsonToCellOptions *options); diff --git a/tools/nitrogfx/main.c b/tools/nitrogfx/main.c index f94645bb24..4e146d1e28 100644 --- a/tools/nitrogfx/main.c +++ b/tools/nitrogfx/main.c @@ -80,7 +80,7 @@ void ConvertNtrToPng(char *inputPath, char *outputPath, struct NtrToPngOptions * if (options->paletteFilePath != NULL) { - ReadNtrPalette(options->paletteFilePath, &image.palette, options->bitDepth, options->palIndex, false, options->convertTo8Bpp); + ReadNtrPalette(options->paletteFilePath, &image.palette, options->bitDepth, options->palIndex, options->convertTo8Bpp, options->verbose); image.hasPalette = true; } else @@ -824,7 +824,7 @@ void HandleNtrToJascPaletteCommand(char *inputPath, char *outputPath, int argc, { struct Palette palette; int bitdepth = 0; - bool inverted = false; + bool verbose = false; for (int i = 3; i < argc; i++) { @@ -843,9 +843,9 @@ void HandleNtrToJascPaletteCommand(char *inputPath, char *outputPath, int argc, if (bitdepth != 4 && bitdepth != 8) FATAL_ERROR("Bitdepth must be 4 or 8.\n"); } - else if (strcmp(option, "-invertsize") == 0) + else if (strcmp(option, "-verbose") == 0) { - inverted = true; + verbose = true; } else { @@ -853,7 +853,7 @@ void HandleNtrToJascPaletteCommand(char *inputPath, char *outputPath, int argc, } } - ReadNtrPalette(inputPath, &palette, bitdepth, 0, inverted, false); + ReadNtrPalette(inputPath, &palette, bitdepth, 0, false, verbose); WriteJascPalette(outputPath, &palette); }