@@ -528,9 +528,11 @@ struct AttrmapEntry {
528
528
bool xFlip;
529
529
530
530
static constexpr decltype (protoPaletteID) transparent = SIZE_MAX;
531
+ static constexpr decltype (protoPaletteID) background = transparent - 1;
531
532
533
+ bool isBackgroundTile () const { return protoPaletteID == background; }
532
534
size_t getPalID (DefaultInitVec<size_t > const &mappings) const {
533
- return protoPaletteID == transparent ? 0 : mappings[ protoPaletteID];
535
+ return isBackgroundTile () ? 0xFF : mappings[ protoPaletteID == transparent ? 0 : protoPaletteID];
534
536
}
535
537
};
536
538
@@ -851,13 +853,16 @@ static void outputUnoptimizedTileData(
851
853
remainingTiles -= options.trim ;
852
854
853
855
for (auto [tile, attr] : zip (png.visitAsTiles (), attrmap)) {
854
- // If the tile is fully transparent, default to palette 0
855
- Palette const &palette = palettes[attr.getPalID (mappings)];
856
- for (uint32_t y = 0 ; y < 8 ; ++y) {
857
- uint16_t bitplanes = TileData::rowBitplanes (tile, palette, y);
858
- output->sputc (bitplanes & 0xFF );
859
- if (options.bitDepth == 2 ) {
860
- output->sputc (bitplanes >> 8 );
856
+ // Do not emit fully-background tiles.
857
+ if (!attr.isBackgroundTile ()) {
858
+ // If the tile is fully transparent, this defaults to palette 0.
859
+ Palette const &palette = palettes[attr.getPalID (mappings)];
860
+ for (uint32_t y = 0 ; y < 8 ; ++y) {
861
+ uint16_t bitplanes = TileData::rowBitplanes (tile, palette, y);
862
+ output->sputc (bitplanes & 0xFF );
863
+ if (options.bitDepth == 2 ) {
864
+ output->sputc (bitplanes >> 8 );
865
+ }
861
866
}
862
867
}
863
868
@@ -897,14 +902,18 @@ static void outputUnoptimizedMaps(
897
902
if (tilemapOutput.has_value ()) {
898
903
(*tilemapOutput)->sputc (tileID + options.baseTileIDs [bank]);
899
904
}
905
+ uint8_t palID = attr.getPalID (mappings);
900
906
if (attrmapOutput.has_value ()) {
901
- uint8_t palID = attr.getPalID (mappings) & 7 ;
902
- (*attrmapOutput)->sputc (palID | bank << 3 ); // The other flags are all 0
907
+ (*attrmapOutput)->sputc ((palID & 7 ) | bank << 3 ); // The other flags are all 0
903
908
}
904
909
if (palmapOutput.has_value ()) {
905
- (*palmapOutput)->sputc (attr.getPalID (mappings));
910
+ (*palmapOutput)->sputc (palID);
911
+ }
912
+
913
+ // Background tiles are skipped in the tile data, so they should be skipped in the maps too.
914
+ if (!attr.isBackgroundTile ()) {
915
+ ++tileID;
906
916
}
907
- ++tileID;
908
917
}
909
918
}
910
919
@@ -1000,7 +1009,7 @@ static UniqueTiles dedupTiles(
1000
1009
}
1001
1010
1002
1011
for (auto [tile, attr] : zip (png.visitAsTiles (), attrmap)) {
1003
- auto [tileID, matchType] = tiles.addTile ({tile, palettes[mappings[attr.protoPaletteID ]]});
1012
+ auto [tileID, matchType] = attr. isBackgroundTile () ? std::tuple{ uint16_t ( 0 ), TileData::EXACT} : tiles.addTile ({tile, palettes[mappings[attr.protoPaletteID ]]});
1004
1013
1005
1014
if (matchType == TileData::NOPE && options.output .empty ()) {
1006
1015
error (
@@ -1121,6 +1130,10 @@ void process() {
1121
1130
// output (with the exception of an un-duplicated tilemap, but that's an acceptable loss.)
1122
1131
std::vector<ProtoPalette> protoPalettes;
1123
1132
DefaultInitVec<AttrmapEntry> attrmap{};
1133
+ ProtoPalette bgPal;
1134
+ if (options.bgColor .has_value ()) {
1135
+ bgPal.add (options.bgColor ->cgbColor ());
1136
+ }
1124
1137
1125
1138
for (auto tile : png.visitAsTiles ()) {
1126
1139
AttrmapEntry &attrs = attrmap.emplace_back ();
@@ -1156,6 +1169,28 @@ void process() {
1156
1169
protoPalette.add (cgbColor);
1157
1170
}
1158
1171
1172
+ if (options.bgColor .has_value ()) {
1173
+ switch (protoPalette.compare (bgPal)) {
1174
+ case ProtoPalette::THEY_BIGGER: // Note that ties are resolved as `THEY_BIGGER`.
1175
+ // The tile contains just the background color, skip it.
1176
+ attrs.protoPaletteID = AttrmapEntry::background;
1177
+ continue ;
1178
+ case ProtoPalette::WE_BIGGER:
1179
+ if (options.bgColorStrict ) {
1180
+ warning (
1181
+ " Tile (%" PRIu32 " , %" PRIu32 " ) contains the background color (#%06" PRIx32
1182
+ " )!" ,
1183
+ tile.x ,
1184
+ tile.y ,
1185
+ options.bgColor ->toCSS () >> 8
1186
+ );
1187
+ }
1188
+ break ;
1189
+ case ProtoPalette::NEITHER:
1190
+ break ;
1191
+ }
1192
+ }
1193
+
1159
1194
// Insert the proto-palette, making sure to avoid overlaps
1160
1195
for (size_t n = 0 ; n < protoPalettes.size (); ++n) {
1161
1196
switch (protoPalette.compare (protoPalettes[n])) {
@@ -1188,7 +1223,7 @@ void process() {
1188
1223
}
1189
1224
1190
1225
attrs.protoPaletteID = protoPalettes.size ();
1191
- if (protoPalettes.size () == AttrmapEntry::transparent ) { // Check for overflow
1226
+ if (protoPalettes.size () == AttrmapEntry::background ) { // Check for overflow
1192
1227
fatal (
1193
1228
" Reached %zu proto-palettes... sorry, this image is too much for me to handle :(" ,
1194
1229
AttrmapEntry::transparent
0 commit comments