gbdk-2020 | GameBoy Development Kit |
| download: https://git.y1.nz/archives/gbdk.tar.gz | |
| README | Files | Log | Refs | LICENSE |
commit 44515d106fbdcd3dacb15adbc449684bf700397a parent 55725d6810a3358d7d8254a83a7360ab9a53ff57 Author: bbbbbr <bbbbbr@users.noreply.github.com> Date: Wed, 17 Apr 2024 18:00:51 -0700 Merge pull request #638 from bbbbbr/tools/png2asset_entitytileset png2asset: add -entity_tileset feature (intended for maps only) Diffstat:
| M | gbdk-support/png2asset/image_data.cpp | 4 | ++-- |
| M | gbdk-support/png2asset/main.cpp | 16 | +++++++++++++++- |
| M | gbdk-support/png2asset/maps.cpp | 101 | +++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------- |
| M | gbdk-support/png2asset/maps.h | 5 | +++-- |
| M | gbdk-support/png2asset/metasprites.cpp | 31 | +++++++++++++------------------ |
| M | gbdk-support/png2asset/png2asset.cpp | 42 | +++++++++++++++++++++++++----------------- |
| M | gbdk-support/png2asset/png2asset.h | 5 | +++-- |
| M | gbdk-support/png2asset/png_image.h | 3 | ++- |
| M | gbdk-support/png2asset/process_arguments.cpp | 8 | ++++++++ |
| M | gbdk-support/png2asset/process_arguments.h | 4 | +++- |
10 files changed, 139 insertions(+), 80 deletions(-)
diff --git a/gbdk-support/png2asset/image_data.cpp b/gbdk-support/png2asset/image_data.cpp @@ -52,7 +52,7 @@ int ReadImageData_KeepPaletteOrder( PNG2AssetData* assetData, string input_file state.decoder.color_convert = false; // Clearing is needed to ensure loading the png works - // (in cases where a previous png was loaded for source tilesets) + // (in cases where a previous png was loaded for source or entity tilesets) assetData->image.data.clear(); unsigned error = lodepng::decode(assetData->image.data, assetData->image.w, assetData->image.h, state, buffer); @@ -146,7 +146,7 @@ int ReadImageData_Default(PNG2AssetData* assetData, string input_filename) { // Create the indexed image // Clearing is needed to ensure loading the png works - // (in cases where a previous png was loaded for source tilesets) + // (in cases where a previous png was loaded for source or entity tilesets) assetData->image.data.clear(); assetData->image.w = image32.w; assetData->image.h = image32.h; diff --git a/gbdk-support/png2asset/main.cpp b/gbdk-support/png2asset/main.cpp @@ -72,10 +72,24 @@ int main(int argc, char* argv[]) arguments.has_source_tilesets = true; printf("Got %d tiles from the source tileset.\n", (unsigned int)arguments.source_tileset_size); - printf("Got %d palettes from the source tileset.\n", (unsigned int)(arguments.source_total_color_count / png2AssetInstance.image.colors_per_pal)); + printf("Got %d palettes from the source tileset.\n", (unsigned int)(arguments.source_total_color_count / png2AssetInstance.image.colors_per_pal)); } + // If there is an entity tileset + if (!arguments.entity_tileset_filename.empty()) { + // Run with entity tileset filename + arguments.processing_mode = MODE_ENTITY_TILESET; + errorCode = png2AssetInstance.Execute(&arguments, arguments.entity_tileset_filename); + + // Return the error code if the function returns non-zero + if(errorCode != 0) { + return errorCode; + } + + arguments.has_entity_tileset = true; + printf("Got %d tiles from the entity tileset.\n", (unsigned int)(unsigned int)png2AssetInstance.entity_tiles.size()); + } // Run the primary input file // Return the error code if the function returns non-zero diff --git a/gbdk-support/png2asset/maps.cpp b/gbdk-support/png2asset/maps.cpp @@ -22,31 +22,66 @@ using namespace std; #include "process_arguments.h" -void GetMap( PNG2AssetData* assetData) +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, assetData->args->bpp); + + if (keep_duplicate_tiles) + tileset.push_back(tile); + else { + if (!FindTile(tile, idx, props, tileset, assetData)) + tileset.push_back(tile); + } + } + } +} + + +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, assetData->args->bpp); 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 = 255 - 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 - if ((assetData->args->keep_duplicate_tiles) && - ((assetData->args->has_source_tilesets == false) || (assetData->args->processing_mode == MODE_SOURCE_TILESET))) { + // 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 - { - if(!FindTile(tile, idx, props,assetData)) + 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->processing_mode == MODE_MAIN_IMAGE) && (assetData->args->has_source_tilesets)) { + if (assetData->args->has_source_tilesets) { printf("found a tile not in the source tileset at %d,%d. The target tileset has %d extra tiles.\n", x, y, (unsigned int)assetData->args->extra_tile_count + 1); assetData->args->extra_tile_count++; assetData->args->includeTileData = true; @@ -64,40 +99,34 @@ void GetMap( PNG2AssetData* assetData) } - // Don't add map tiles and attributes for source tilesets - if (assetData->args->processing_mode == MODE_MAIN_IMAGE) { - assetData->map.push_back((unsigned char)idx + assetData->args->tile_origin); + // 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) + if(assetData->args->use_map_attributes) + { + unsigned char pal_idx = assetData->image.data[y * assetData->image.w + x] >> assetData->args->bpp; //We can pick the palette from the first pixel of this tile + if(assetData->args->pack_mode == Tile::SGB) { - unsigned char pal_idx = assetData->image.data[y * assetData->image.w + x] >> assetData->args->bpp; //We can pick the palette from the first pixel of this tile - 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; - assetData->map.push_back(props); - } - else - { - props |= pal_idx; - assetData->map_attributes.push_back(props); - } + 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; + assetData->map.push_back(props); + } + else + { + props |= pal_idx; + assetData->map_attributes.push_back(props); } } } } - - // Don't add map tiles and attributes for source tilesets - if (assetData->args->processing_mode == MODE_MAIN_IMAGE) { - HandleMapAttributes( assetData); - } + HandleMapAttributes( assetData); } diff --git a/gbdk-support/png2asset/maps.h b/gbdk-support/png2asset/maps.h @@ -6,4 +6,5 @@ using namespace std; -void GetMap( PNG2AssetData* assetData); - +void GetMap( PNG2AssetData* assetData); +void ExtractTileset(PNG2AssetData* assetData, vector< Tile > & tileset, bool keep_duplicate_tiles); + diff --git a/gbdk-support/png2asset/metasprites.cpp b/gbdk-support/png2asset/metasprites.cpp @@ -31,7 +31,7 @@ void GetMetaSprite(int _x, int _y, int _w, int _h, int pivot_x, int pivot_y, PNG { Tile tile(assetData->image.tile_h * assetData->image.tile_w); // For sprites, unlike maps, Tiles are only kept and processed if NOT Empty - // This default behavior can be overridden with -spr_no_optimize (which sets keep_empty_sprite_tiles and keep_duplicate_tiles to TRUE) + // This default behavior can be overridden with -spr_no_optimize (which sets keep_empty_sprite_tiles and keep_duplicate_tiles to TRUE) bool tile_not_empty = (assetData->image.ExtractTile(x, y, tile, assetData->args->sprite_mode, assetData->args->export_as_map, assetData->args->use_map_attributes, assetData->args->bpp)); if (tile_not_empty || (assetData->args->keep_empty_sprite_tiles)) { @@ -41,17 +41,16 @@ void GetMetaSprite(int _x, int _y, int _w, int _h, int pivot_x, int pivot_y, PNG // When both -keep_duplicate_tiles and source tilesets are used then // keep_duplicate_tiles should only apply to source tilesets, not the main image - if ((assetData->args->keep_duplicate_tiles) && - ((assetData->args->has_source_tilesets == false) || (assetData->args->processing_mode == MODE_SOURCE_TILESET))) { + if ((assetData->args->keep_duplicate_tiles) && (assetData->args->has_source_tilesets == false)) { assetData->tiles.push_back(tile); idx = assetData->tiles.size() - 1; props = assetData->args->props_default; } else { - if(!FindTile(tile, idx, props, assetData)) + if(!FindTile(tile, idx, props, assetData->tiles, assetData)) { - if ((assetData->args->processing_mode == MODE_MAIN_IMAGE) && (assetData->args->has_source_tilesets)) { + if (assetData->args->has_source_tilesets) { printf("found a tile not in the source tileset at %d,%d. The target tileset has %d extra tiles.\n", x, y, (unsigned int)assetData->args->extra_tile_count + 1); assetData->args->extra_tile_count++; assetData->args->includeTileData = true; @@ -62,21 +61,17 @@ void GetMetaSprite(int _x, int _y, int _w, int _h, int pivot_x, int pivot_y, PNG } } - // Don't add metasprite tiles for source tilesets - if (assetData->args->processing_mode == MODE_MAIN_IMAGE) { + props |= pal_idx; - props |= pal_idx; + // Scale up index based on 8x8 tiles-per-hardware sprite + if(assetData->args->sprite_mode == SPR_8x16) + idx *= 2; + else if(assetData->args->sprite_mode == SPR_16x16_MSX) + idx *= 4; - // Scale up index based on 8x8 tiles-per-hardware sprite - if(assetData->args->sprite_mode == SPR_8x16) - idx *= 2; - else if(assetData->args->sprite_mode == SPR_16x16_MSX) - idx *= 4; - - mt_sprite.push_back(MTTile(x - last_x, y - last_y, (unsigned char)idx, props)); - last_x = x; - last_y = y; - } + mt_sprite.push_back(MTTile(x - last_x, y - last_y, (unsigned char)idx, props)); + last_x = x; + last_y = y; } } } diff --git a/gbdk-support/png2asset/png2asset.cpp b/gbdk-support/png2asset/png2asset.cpp @@ -54,9 +54,18 @@ int PNG2AssetData::Execute(PNG2AssetArguments* arguments, string input_filename return readImageDataValue; } - // Get the data depending on the type - if(this->args->export_as_map)GetMap(this); - else GetAllMetasprites(this); + // Extract the data depending on what type it is + if (this->args->processing_mode == MODE_ENTITY_TILESET) { + // Entity tileset extracts into a separate tileset + // For entity tilesets ALWAYS keep all of it's tiles, never deduplicate them + ExtractTileset(this, this->entity_tiles, true); + } else if (this->args->processing_mode == MODE_SOURCE_TILESET) { + // Source tileset extracts into the main shared tileset + ExtractTileset(this, this->tiles, this->args->keep_duplicate_tiles); + } else if (this->args->export_as_map) + GetMap(this); + else + GetAllMetasprites(this); return 0; } @@ -79,42 +88,41 @@ int PNG2AssetData::Export() { } -bool FindTile(const Tile& t, size_t& idx, unsigned char& props, PNG2AssetData* assetData) +bool FindTile(const Tile& t, size_t& idx, unsigned char& props, vector< Tile > & tileset, PNG2AssetData* assetData) { vector< Tile >::iterator it; - it = find(assetData->tiles.begin(), assetData->tiles.end(), t); - if(it != assetData->tiles.end()) + it = find(tileset.begin(), tileset.end(), t); + if(it != tileset.end()) { - idx = (size_t)(it - assetData->tiles.begin()); + idx = (size_t)(it - tileset.begin()); props = assetData->args->props_default; return true; } - if(assetData->args->flip_tiles) { Tile tile = FlipV(t); - it = find(assetData->tiles.begin(), assetData->tiles.end(), tile); - if(it != assetData->tiles.end()) + it = find(tileset.begin(), tileset.end(), tile); + if(it != tileset.end()) { - idx = (size_t)(it - assetData->tiles.begin()); + idx = (size_t)(it - tileset.begin()); props = assetData->args->props_default | (1 << 5); return true; } tile = FlipH(tile); - it = find(assetData->tiles.begin(), assetData->tiles.end(), tile); - if(it != assetData->tiles.end()) + it = find(tileset.begin(), tileset.end(), tile); + if(it != tileset.end()) { - idx = (size_t)(it - assetData->tiles.begin()); + idx = (size_t)(it - tileset.begin()); props = assetData->args->props_default | (1 << 5) | (1 << 6); return true; } tile = FlipV(tile); - it = find(assetData->tiles.begin(), assetData->tiles.end(), tile); - if(it != assetData->tiles.end()) + it = find(tileset.begin(), tileset.end(), tile); + if(it != tileset.end()) { - idx = (size_t)(it - assetData->tiles.begin()); + idx = (size_t)(it - tileset.begin()); props = assetData->args->props_default | (1 << 6); return true; } diff --git a/gbdk-support/png2asset/png2asset.h b/gbdk-support/png2asset/png2asset.h @@ -25,6 +25,7 @@ public: vector< SetPal > palettes; vector< Tile > tiles; + vector< Tile > entity_tiles; vector< MetaSprite > sprites; vector< unsigned char > map; vector< unsigned char > map_attributes; @@ -33,4 +34,4 @@ public: }; -bool FindTile(const Tile& t, size_t& idx, unsigned char& props, PNG2AssetData* assetData); - +bool FindTile(const Tile& t, size_t& idx, unsigned char& props, vector< Tile > & tiles, PNG2AssetData* assetData); + diff --git a/gbdk-support/png2asset/png_image.h b/gbdk-support/png2asset/png_image.h @@ -15,7 +15,8 @@ enum { // processing_mode states enum { MODE_MAIN_IMAGE, - MODE_SOURCE_TILESET + MODE_SOURCE_TILESET, + MODE_ENTITY_TILESET }; struct PNGImage diff --git a/gbdk-support/png2asset/process_arguments.cpp b/gbdk-support/png2asset/process_arguments.cpp @@ -73,6 +73,9 @@ int processPNG2AssetArguments(int argc, char* argv[], PNG2AssetArguments* args) args->source_total_color_count = 0; args->source_tileset_size = 0; args->has_source_tilesets = false; + + args->has_entity_tileset = false; + args->processing_mode = MODE_MAIN_IMAGE; args->pack_mode = Tile::GB; @@ -114,6 +117,7 @@ int processPNG2AssetArguments(int argc, char* argv[], PNG2AssetArguments* args) printf("-maps_only export map tilemap only\n"); printf("-metasprites_only export metasprite descriptors only\n"); printf("-source_tileset use source tileset (image with common tiles)\n"); + printf("-entity_tileset (maps only) mark matching tiles counting from 255 down, entity patterns not exported\n"); printf("-keep_duplicate_tiles do not remove duplicate tiles (default: not enabled)\n"); printf("-no_palettes do not export palette data\n"); @@ -287,6 +291,10 @@ int processPNG2AssetArguments(int argc, char* argv[], PNG2AssetArguments* args) args->includeTileData = false; args->source_tilesets.push_back(argv[++i]); } + else if(!strcmp(argv[i], "-entity_tileset")) + { + args->entity_tileset_filename = argv[++i]; + } else if(!strcmp(argv[i], "-bin")) { args->output_binary = true; diff --git a/gbdk-support/png2asset/process_arguments.h b/gbdk-support/png2asset/process_arguments.h @@ -30,6 +30,7 @@ struct PNG2AssetArguments { string output_filename; string input_filename; vector<string> source_tilesets; + string entity_tileset_filename; size_t max_palettes; @@ -61,7 +62,8 @@ struct PNG2AssetArguments { size_t source_total_color_count; // Total number of colors (palette_count x colors_per_palette) unsigned int source_tileset_size; bool has_source_tilesets; - int processing_mode; // Whether the current image being processed is a source tileset is (MODE_SOURCE_TILESET) or the main image (MODE_MAIN_IMAGE) + bool has_entity_tileset; + int processing_mode; // Whether the current image being processed is a source tileset (MODE_SOURCE_TILESET), entity_tileset (MODE_ENTITY_TILESET), or the main image (MODE_MAIN_IMAGE) Tile::PackMode pack_mode; int map_entry_size_bytes;
This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.