From 3284d0d54799fa701d1a4701a89c2a7dd39dd6e8 Mon Sep 17 00:00:00 2001 From: red031000 Date: Sat, 3 Feb 2024 01:28:26 +0000 Subject: [PATCH] add PMCP support and fix a few bugs --- LICENSE | 2 +- gfx.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++------ gfx.h | 4 ++-- json.c | 2 +- json.h | 2 +- main.c | 20 +++++++++++++++----- options.h | 2 +- 7 files changed, 71 insertions(+), 17 deletions(-) diff --git a/LICENSE b/LICENSE index 1575ad6..be4a599 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2015 YamaArashi, 2021-2023 red031000 +Copyright (c) 2015 YamaArashi, 2021-2024 red031000 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/gfx.c b/gfx.c index 9dd4bf3..b8e2be5 100644 --- a/gfx.c +++ b/gfx.c @@ -1,4 +1,4 @@ -// Copyright (c) 2015 YamaArashi, 2021-2023 red031000 +// Copyright (c) 2015 YamaArashi, 2021-2024 red031000 #include #include @@ -718,10 +718,17 @@ void ReadNtrPalette(char *path, struct Palette *palette, int bitdepth, int palIn bitdepth = bitdepth ? bitdepth : palette->bitDepth; - palette->numColors = bitdepth == 4 ? 16 : 256; //remove header and divide by 2 + size_t paletteSize = (paletteHeader[0x10]) | (paletteHeader[0x11] << 8) | (paletteHeader[0x12] << 16) | (paletteHeader[0x13] << 24); + if (palIndex == 0) + { + palette->numColors = paletteSize / 2; + } else + { + palette->numColors = bitdepth == 4 ? 16 : 256; //remove header and divide by 2 + --palIndex; + } unsigned char *paletteData = paletteHeader + 0x18; - palIndex = palIndex - 1; for (int i = 0; i < 256; i++) { @@ -764,20 +771,33 @@ void WriteGbaPalette(char *path, struct Palette *palette) fclose(fp); } -void WriteNtrPalette(char *path, struct Palette *palette, bool ncpr, bool ir, int bitdepth, bool pad, int compNum) +void WriteNtrPalette(char *path, struct Palette *palette, bool ncpr, bool ir, int bitdepth, bool pad, int compNum, bool pcmp) { FILE *fp = fopen(path, "wb"); if (fp == NULL) FATAL_ERROR("Failed to open \"%s\" for writing.\n", path); - int colourNum = pad ? 256 : 16; + int colourNum = pad ? 256 : palette->numColors; uint32_t size = colourNum * 2; //todo check if there's a better way to detect :/ uint32_t extSize = size + (ncpr ? 0x10 : 0x18); + int numSections = 1; + int pcmpColorNum = 0; + uint32_t pcmpSize = 0; + if (pcmp) + { + pcmpColorNum = colourNum / (bitdepth == 4 ? 16 : 256); + if (pcmpColorNum == 0) { + FATAL_ERROR("colourNum=%d palette->bitDepth=%d\n", colourNum, bitdepth); + } + pcmpSize = 16 + pcmpColorNum * 2; + ++numSections; + } + //NCLR header - WriteGenericNtrHeader(fp, (ncpr ? "RPCN" : "RLCN"), extSize, !ncpr, false, 1); + WriteGenericNtrHeader(fp, (ncpr ? "RPCN" : "RLCN"), extSize + pcmpSize, !ncpr, false, numSections); unsigned char palHeader[0x18] = { @@ -843,6 +863,30 @@ void WriteNtrPalette(char *path, struct Palette *palette, bool ncpr, bool ir, in fwrite(colours, 1, colourNum * 2, fp); free(colours); + if (pcmp) + { + uint8_t pcmp_header[16] = {0x50, 0x4D, 0x43, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEF, 0xBE, 0x08, 0x00, 0x00, 0x00}; + pcmp_header[4] = pcmpSize & 0xFF; + pcmp_header[5] = (pcmpSize >> 8) & 0xFF; + pcmp_header[6] = (pcmpSize >> 16) & 0xFF; + pcmp_header[7] = (pcmpSize >> 24) & 0xFF; + pcmp_header[8] = pcmpColorNum & 0xFF; + pcmp_header[9] = (pcmpColorNum >> 8) & 0xFF; + fwrite(pcmp_header, 1, 16, fp); + + uint8_t *pcmp_data = malloc(2 * pcmpColorNum); + if (pcmp_data == NULL) + { + FATAL_ERROR("failed to alloc pcmp_data\n"); + } + for (int i = 0; i < pcmpColorNum; ++i) { + pcmp_data[i * 2] = i & 0xFF; + pcmp_data[i * 2 + 1] = (i >> 8) & 0xFF; + } + fwrite(pcmp_data, 1, pcmpColorNum * 2, fp); + free(pcmp_data); + } + fclose(fp); } diff --git a/gfx.h b/gfx.h index c7f85bb..91f6978 100644 --- a/gfx.h +++ b/gfx.h @@ -1,4 +1,4 @@ -// Copyright (c) 2015 YamaArashi, 2021-2023 red031000 +// Copyright (c) 2015 YamaArashi, 2021-2024 red031000 #ifndef GFX_H #define GFX_H @@ -60,7 +60,7 @@ void FreeImage(struct Image *image); void ReadGbaPalette(char *path, struct Palette *palette); void ReadNtrPalette(char *path, struct Palette *palette, int bitdepth, int palIndex); void WriteGbaPalette(char *path, struct Palette *palette); -void WriteNtrPalette(char *path, struct Palette *palette, bool ncpr, bool ir, int bitdepth, bool pad, int compNum); +void WriteNtrPalette(char *path, struct Palette *palette, bool ncpr, bool ir, int bitdepth, bool pad, int compNum, bool pcmp); void ReadNtrCell(char *path, struct JsonToCellOptions *options); void WriteNtrCell(char *path, struct JsonToCellOptions *options); void WriteNtrScreen(char *path, struct JsonToScreenOptions *options); diff --git a/json.c b/json.c index ad40366..12bc8a9 100644 --- a/json.c +++ b/json.c @@ -1,4 +1,4 @@ -// Copyright (c) 2021-2023 red031000 +// Copyright (c) 2021-2024 red031000 #include "global.h" #include "cJSON.h" diff --git a/json.h b/json.h index 7e212a9..eb7e2ad 100644 --- a/json.h +++ b/json.h @@ -1,4 +1,4 @@ -// Copyright (c) 2021-2023 red031000 +// Copyright (c) 2021-2024 red031000 #ifndef JSON_H #define JSON_H diff --git a/main.c b/main.c index 0df1a08..1f94349 100644 --- a/main.c +++ b/main.c @@ -1,4 +1,4 @@ -// Copyright (c) 2015 YamaArashi, 2021-2023 red031000 +// Copyright (c) 2015 YamaArashi, 2021-2024 red031000 #include #include @@ -172,7 +172,7 @@ void HandleGbaToPngCommand(char *inputPath, char *outputPath, int argc, char **a char *inputFileExtension = GetFileExtension(inputPath); struct GbaToPngOptions options; options.paletteFilePath = NULL; - if (isdigit(inputFileExtension[0])) + if (isdigit((unsigned char)inputFileExtension[0])) options.bitDepth = inputFileExtension[0] - '0'; else options.bitDepth = 4; @@ -565,6 +565,7 @@ void HandlePngToNtrPaletteCommand(char *inputPath, char *outputPath, int argc, c bool nopad = false; int bitdepth = 0; int compNum = 0; + bool pcmp = false; for (int i = 3; i < argc; i++) { @@ -608,6 +609,10 @@ void HandlePngToNtrPaletteCommand(char *inputPath, char *outputPath, int argc, c if (compNum > 255) FATAL_ERROR("Compression value must be 255 or below.\n"); } + else if (strcmp(option, "-pcmp") == 0) + { + pcmp = true; + } else { FATAL_ERROR("Unrecognized option \"%s\".\n", option); @@ -615,7 +620,7 @@ void HandlePngToNtrPaletteCommand(char *inputPath, char *outputPath, int argc, c } ReadPngPalette(inputPath, &palette); - WriteNtrPalette(outputPath, &palette, ncpr, ir, bitdepth, !nopad, compNum); + WriteNtrPalette(outputPath, &palette, ncpr, ir, bitdepth, !nopad, compNum, pcmp); } void HandleGbaToJascPaletteCommand(char *inputPath, char *outputPath, int argc UNUSED, char **argv UNUSED) @@ -654,7 +659,7 @@ void HandleNtrToJascPaletteCommand(char *inputPath, char *outputPath, int argc, } } - ReadNtrPalette(inputPath, &palette, bitdepth, 1); + ReadNtrPalette(inputPath, &palette, bitdepth, 0); WriteJascPalette(outputPath, &palette); } @@ -703,6 +708,7 @@ void HandleJascToNtrPaletteCommand(char *inputPath, char *outputPath, int argc, bool nopad = false; int bitdepth = 0; int compNum = 0; + bool pcmp = false; for (int i = 3; i < argc; i++) { @@ -759,6 +765,10 @@ void HandleJascToNtrPaletteCommand(char *inputPath, char *outputPath, int argc, { nopad = true; } + else if (strcmp(option, "-pcmp") == 0) + { + pcmp = true; + } else { FATAL_ERROR("Unrecognized option \"%s\".\n", option); @@ -772,7 +782,7 @@ void HandleJascToNtrPaletteCommand(char *inputPath, char *outputPath, int argc, if (numColors != 0) palette.numColors = numColors; - WriteNtrPalette(outputPath, &palette, ncpr, ir, bitdepth, !nopad, compNum); + WriteNtrPalette(outputPath, &palette, ncpr, ir, bitdepth, !nopad, compNum, pcmp); } void HandleJsonToNtrCellCommand(char *inputPath, char *outputPath, int argc UNUSED, char **argv UNUSED) diff --git a/options.h b/options.h index 7a22f28..4304f1e 100644 --- a/options.h +++ b/options.h @@ -1,4 +1,4 @@ -// Copyright (c) 2018 huderlem, 2021-2023 red031000 +// Copyright (c) 2018 huderlem, 2021-2024 red031000 #ifndef OPTIONS_H #define OPTIONS_H