Warn when tile or palette IDs cannot fit in the tilemap or attrmap respectively (#2077)

Co-authored-by: Eldred Habert <[email protected]>
This commit is contained in:
Rangi
2026-09-13 19:18:24 +02:00
committed by GitHub
co-authored by Eldred Habert
parent 47bbd30f2c
commit e9fc7b3135
18 changed files with 42 additions and 23 deletions
+4
View File
@@ -299,6 +299,10 @@ static void parseArg(int ch, char *arg) {
break;
case 'N':
// Explicit numbers for either tile bank cannot be greater than 256.
// If they were greater than 256, it would permit tile IDs to be truncated in the tilemap.
// We do warn that tile IDs may be truncated for the implicit/default unlimited number of
// tiles in bank 0.
options.maxNbTiles[0] = readNumber(argPtr, "Number of tiles in bank 0", 256);
if (options.maxNbTiles[0] > 256) {
error("Bank 0 cannot contain more than 256 tiles");
+33 -23
View File
@@ -502,14 +502,14 @@ static void outputPalettes(std::vector<Palette> const &palettes) {
});
// LCOV_EXCL_STOP
if (palettes.size() > options.nbPalettes) {
if (size_t nbPals = palettes.size(); nbPals > options.nbPalettes) {
// If the palette generation is wrong, other (dependee) operations are likely to be
// nonsensical, so fatal-error outright
fatal(
"Generated %zu palettes, over the maximum of %" PRIu16,
palettes.size(),
options.nbPalettes
);
fatal("Generated %zu palettes, over the maximum of %" PRIu16, nbPals, options.nbPalettes);
} else if (nbPals > 8 && !options.attrmap.empty() && options.palmap.empty()) {
// With `-n/--nb-palettes` greater than 8, palette IDs may be truncated in the attrmap
// (though not in the palmap), so warn about that.
warnx("Generated %zu palettes, of which only 8 are representable in the attrmap", nbPals);
}
if (!options.palettes.empty()) {
@@ -745,6 +745,8 @@ static void outputUnoptimizedMaps(
for (AttrmapEntry const &attr : attrmap) {
// A non-zero base ID may make this addition overflow, wrapping around the available
// palette IDs. Since the operands are unsigned, this won't cause undefined behavior.
// With `-n/--nb-palettes` greater than 8, palette IDs may be truncated in the attrmap
// (though not in the palmap), which was already warned about.
uint8_t palID = attr.getPalID(mappings) + options.basePalID;
if (attr.isBackgroundTile()) {
// The tile bank may be 2 here, which is fine since background tiles are emitted as
@@ -761,6 +763,8 @@ static void outputUnoptimizedMaps(
// A non-zero base ID may make this addition overflow, wrapping around the available
// tile IDs. Since the operands are unsigned, this won't cause undefined behavior.
// With `-N/--nb-tiles` unlimited (by default) for bank 0, tile IDs may be truncated in
// the tilemap, which was already warned about.
uint8_t tileID = tileIdx + options.baseTileIDs[bank];
emit(tilemapOutput, tileID);
emit(attrmapOutput, (palID & 0b111) | bank << 3); // The other flags are all zeros.
@@ -940,6 +944,8 @@ static void outputTilemap(std::vector<AttrmapEntry> const &attrmap) {
// LCOV_EXCL_STOP
}
// With `-N/--nb-tiles` unlimited (by default) for bank 0, tile IDs may be truncated in the
// tilemap, which was already warned about.
for (AttrmapEntry const &entry : attrmap) {
output->sputc(entry.tileID); // The tile ID has already been converted
}
@@ -959,6 +965,8 @@ static void
attr |= entry.bank << 3;
// The unsigned underflow for the palette ID is intentional, since a
// nonzero base palette ID may overflow and continue with IDs from 0.
// With `-n/--nb-palettes` greater than 8, palette IDs may be truncated in the attrmap
// (though not in the palmap), which was already warned about.
attr |= (entry.getPalID(mappings) + options.basePalID) & 0b111;
output->sputc(attr);
}
@@ -1191,20 +1199,31 @@ continue_visiting_tiles:;
: makePalsAsSpecified(colorSets);
outputPalettes(palettes);
// If deduplication is not happening, we just need to output the tile data and/or maps as-is
if (!options.allowDedup) {
// Check the tile count
if (size_t nbTiles = std::count_if(
RANGE(attrmap), [](AttrmapEntry const &attr) { return !attr.isBackgroundTile(); }
);
nbTiles > options.maxNbTiles[0] + options.maxNbTiles[1]) {
auto checkTileCountLimit = [](size_t nbTiles) {
if (nbTiles > options.maxNbTiles[0] + options.maxNbTiles[1]) {
fatal(
"Image contains %zu tiles, exceeding the limit of %" PRIu16 " + %" PRIu16,
nbTiles,
options.maxNbTiles[0],
options.maxNbTiles[1]
);
} else if (((nbTiles > 256 && options.maxNbTiles[0] > 256)
|| (nbTiles > options.maxNbTiles[0] + 256u && options.maxNbTiles[1] > 256))
&& !options.tilemap.empty()) {
// With `-N/--nb-tiles` unlimited (by default) for bank 0, tile IDs may be truncated in
// the tilemap, so warn about that.
warnx(
"Image contains %zu tiles, of which only 256 are representable in the tilemap",
nbTiles
);
}
};
// If deduplication is not happening, we just need to output the tile data and/or maps as-is
if (!options.allowDedup) {
checkTileCountLimit(std::count_if(RANGE(attrmap), [](AttrmapEntry const &attr) {
return !attr.isBackgroundTile();
}));
// I currently cannot figure out useful semantics for this combination of flags.
if (!options.inputTileset.empty()) {
@@ -1227,16 +1246,7 @@ continue_visiting_tiles:;
verbosePrint(VERB_NOTICE, "Deduplicating tiles...\n");
UniqueTiles tiles = dedupTiles(image, attrmap, palettes, mappings);
// Check the tile count
if (size_t nbTiles = tiles.size();
nbTiles > options.maxNbTiles[0] + options.maxNbTiles[1]) {
fatal(
"Image contains %zu tiles, exceeding the limit of %" PRIu16 " + %" PRIu16,
nbTiles,
options.maxNbTiles[0],
options.maxNbTiles[1]
);
}
checkTileCountLimit(tiles.size());
if (!options.output.empty()) {
verbosePrint(VERB_NOTICE, "Generating optimized tile data...\n");
+1
View File
@@ -0,0 +1 @@
warning: Generated 9 palettes, of which only 8 are representable in the attrmap
+1
View File
@@ -0,0 +1 @@
-n 9
+1
View File
@@ -0,0 +1 @@
Binary file not shown.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 470 B

+1
View File
@@ -0,0 +1 @@
warning: Image contains 320 tiles, of which only 256 are representable in the tilemap
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 997 B

+1
View File
@@ -0,0 +1 @@
warning: Image contains 320 tiles, of which only 256 are representable in the tilemap
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 512 B