mirror of
https://github.com/gbdk-2020/gbdk-2020.git
synced 2026-03-19 21:57:49 +01:00
* improve png2asset tile palette handling * revert to detecting palette by the corner pixel of the tile * detect palette by maximum on the tile * return zero tile result correctly * remove the last (?) usage of the corner pixel peeking, use tile.pal instead
161 lines
6.6 KiB
C++
161 lines
6.6 KiB
C++
#include <vector>
|
|
#include <string>
|
|
#include <algorithm>
|
|
#include <cstring>
|
|
#include <set>
|
|
#include <stdio.h>
|
|
#include <fstream>
|
|
#include <cstdint>
|
|
|
|
#include "lodepng.h"
|
|
#include "mttile.h"
|
|
#include "export.h"
|
|
|
|
#include "cmp_int_color.h"
|
|
#include "tiles.h"
|
|
|
|
using namespace std;
|
|
|
|
#include "png2asset.h"
|
|
#include "image_utils.h"
|
|
#include "map_attributes.h"
|
|
#include "process_arguments.h"
|
|
|
|
|
|
void ExtractTileset(PNG2AssetData* assetData, vector< Tile > & tileset, bool keep_duplicate_tiles) {
|
|
|
|
// Placeholder vars needed for function call, they get discarded
|
|
size_t idx;
|
|
unsigned char props;
|
|
|
|
for(int y = 0; y < (int)assetData->image.h; y += assetData->image.tile_h)
|
|
{
|
|
for(int x = 0; x < (int)assetData->image.w; x += assetData->image.tile_w)
|
|
{
|
|
// Get a tile from the image
|
|
Tile tile(assetData->image.tile_w * assetData->image.tile_h);
|
|
assetData->image.ExtractTile(x, y, tile, assetData->args->sprite_mode, assetData->args->export_as_map, assetData->args->use_map_attributes);
|
|
|
|
if (keep_duplicate_tiles)
|
|
tileset.push_back(tile);
|
|
else {
|
|
if (!FindTile(tile, idx, props, tileset, assetData))
|
|
tileset.push_back(tile);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
static void checkWarnMapTileLimits(PNG2AssetData* assetData) {
|
|
|
|
unsigned int maxUsedTileCount = (assetData->tiles.size() + assetData->args->tile_origin);
|
|
unsigned int maxTilesWarnLimit = 256; // 256 is default for GB, NES
|
|
|
|
// GB + Map Attributes implies GBC which has a secondary tile bank
|
|
if (((assetData->args->pack_mode == Tile::GB) && assetData->args->use_map_attributes) ||
|
|
(assetData->args->pack_mode == Tile::SMS)) {
|
|
maxTilesWarnLimit = 512;
|
|
}
|
|
|
|
if (maxUsedTileCount > maxTilesWarnLimit) {
|
|
printf("Warning: Tile count (%d) + tile origin (%d) = %d exceeds limit %d\n",
|
|
(unsigned int)assetData->tiles.size(), (unsigned int)assetData->args->tile_origin,
|
|
maxUsedTileCount, maxTilesWarnLimit);
|
|
}
|
|
|
|
// If using GBC, notify user about extra requirements to use > 256 tiles
|
|
if ((maxUsedTileCount > 256) && ((assetData->args->pack_mode == Tile::GB) && assetData->args->use_map_attributes)) {
|
|
printf("Warning: On GBC more then 256 tiles may require use of alternate tile bank. Tile count (%d) + tile origin (%d) = %d\n",
|
|
(unsigned int)assetData->tiles.size(), (unsigned int)assetData->args->tile_origin, maxUsedTileCount);
|
|
}
|
|
}
|
|
|
|
|
|
void GetMap(PNG2AssetData* assetData)
|
|
{
|
|
for(int y = 0; y < (int)assetData->image.h; y += assetData->image.tile_h)
|
|
{
|
|
for(int x = 0; x < (int)assetData->image.w; x += assetData->image.tile_w)
|
|
{
|
|
// Get a tile from the image
|
|
Tile tile(assetData->image.tile_w * assetData->image.tile_h);
|
|
assetData->image.ExtractTile(x, y, tile, assetData->args->sprite_mode, assetData->args->export_as_map, assetData->args->use_map_attributes);
|
|
|
|
size_t idx;
|
|
unsigned char props;
|
|
|
|
// If there is an entity tileset then always check that for a matching tile first
|
|
if (assetData->args->has_entity_tileset && FindTile(tile, idx, props, assetData->entity_tiles, assetData)) {
|
|
// Entity tilesets index counts from 255 down instead of 0 up,
|
|
// so invert the tile ID on the 8 bit boundary
|
|
idx = (256 - assetData->entity_tiles.size()) + idx;
|
|
props = assetData->args->props_default;
|
|
}
|
|
// When both -keep_duplicate_tiles and source tilesets are used then
|
|
// keep_duplicate_tiles should only apply to source tilesets, not the main image.
|
|
// (Since keeping duplicate tiles from the main image would
|
|
// cause the identical tiles in a source tileset to be ignored)
|
|
else if ((assetData->args->keep_duplicate_tiles) && (assetData->args->has_source_tilesets == false)) {
|
|
// Save tile pattern data, don't try to deduplicate it
|
|
assetData->tiles.push_back(tile);
|
|
idx = assetData->tiles.size() - 1;
|
|
props = assetData->args->props_default;
|
|
}
|
|
else {
|
|
// Otherwise if the tile pattern has not been encountered before then save it
|
|
if (!FindTile(tile, idx, props, assetData->tiles, assetData))
|
|
{
|
|
if (assetData->args->has_source_tilesets) {
|
|
printf("found a tile not in the source tileset at %d,%d\n", x, y);
|
|
assetData->args->includeTileData = true;
|
|
}
|
|
assetData->tiles.push_back(tile);
|
|
idx = assetData->tiles.size() - 1;
|
|
props = assetData->args->props_default;
|
|
}
|
|
}
|
|
|
|
|
|
// Creating map tile id and attributes entries is only when processing the the main image.
|
|
assetData->map.push_back((unsigned char)idx + assetData->args->tile_origin);
|
|
|
|
if(assetData->args->use_map_attributes)
|
|
{
|
|
unsigned char pal_idx = tile.pal;
|
|
if(assetData->args->pack_mode == Tile::SGB)
|
|
{
|
|
props = props << 1; //Mirror flags in SGB are on bit 7
|
|
props |= (pal_idx + 4) << 2; //Pals are in bits 2,3,4 and need to go from 4 to 7
|
|
assetData->map.push_back(props); //Also they are stored within the map tiles
|
|
}
|
|
else if(assetData->args->pack_mode == Tile::SMS)
|
|
{
|
|
props = (props >> 4) | ((pal_idx & 1) << 3);
|
|
if(idx > 255)
|
|
props |= 1;
|
|
if (assetData->args->use_structs) {
|
|
// put the attribute data in a separate array as with GBC
|
|
// for: -use_map_attributes + -use_structs[aka zgb] + SMS/GG
|
|
assetData->map_attributes.push_back(props);
|
|
} else {
|
|
assetData->map.push_back(props);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
props |= pal_idx;
|
|
// If GBC and more than 256 tiles then add in tile bank num
|
|
if ((idx > 255) && (assetData->args->pack_mode == Tile::GB))
|
|
props |= CGB_BKGF_BANK1;
|
|
assetData->map_attributes.push_back(props);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
checkWarnMapTileLimits(assetData);
|
|
HandleMapAttributes(assetData);
|
|
}
|
|
|