|
|
|
@@ -215,10 +215,10 @@ bool DecodeSingleSprite(SpriteLoader::Sprite *sprite, SpriteFile &file, size_t f
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint8_t LoadSpriteV1(SpriteLoader::SpriteCollection &sprite, SpriteFile &file, size_t file_pos, SpriteType sprite_type, bool load_32bpp, uint8_t &avail_8bpp)
|
|
|
|
|
static ZoomLevels LoadSpriteV1(SpriteLoader::SpriteCollection &sprite, SpriteFile &file, size_t file_pos, SpriteType sprite_type, bool load_32bpp, ZoomLevels &avail_8bpp)
|
|
|
|
|
{
|
|
|
|
|
/* Check the requested colour depth. */
|
|
|
|
|
if (load_32bpp) return 0;
|
|
|
|
|
if (load_32bpp) return {};
|
|
|
|
|
|
|
|
|
|
/* Open the right file and go to the correct position */
|
|
|
|
|
file.SeekTo(file_pos, SEEK_SET);
|
|
|
|
@@ -228,7 +228,7 @@ uint8_t LoadSpriteV1(SpriteLoader::SpriteCollection &sprite, SpriteFile &file, s
|
|
|
|
|
uint8_t type = file.ReadByte();
|
|
|
|
|
|
|
|
|
|
/* Type 0xFF indicates either a colourmap or some other non-sprite info; we do not handle them here */
|
|
|
|
|
if (type == 0xFF) return 0;
|
|
|
|
|
if (type == 0xFF) return {};
|
|
|
|
|
|
|
|
|
|
ZoomLevel zoom_lvl = (sprite_type != SpriteType::MapGen) ? ZOOM_LVL_NORMAL : ZOOM_LVL_MIN;
|
|
|
|
|
auto &dest_sprite = sprite[zoom_lvl];
|
|
|
|
@@ -241,7 +241,7 @@ uint8_t LoadSpriteV1(SpriteLoader::SpriteCollection &sprite, SpriteFile &file, s
|
|
|
|
|
|
|
|
|
|
if (dest_sprite.width > INT16_MAX) {
|
|
|
|
|
WarnCorruptSprite(file, file_pos, __LINE__);
|
|
|
|
|
return 0;
|
|
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 0x02 indicates it is a compressed sprite, so we can't rely on 'num' to be valid.
|
|
|
|
@@ -249,33 +249,33 @@ uint8_t LoadSpriteV1(SpriteLoader::SpriteCollection &sprite, SpriteFile &file, s
|
|
|
|
|
num = (type & 0x02) ? dest_sprite.width * dest_sprite.height : num - 8;
|
|
|
|
|
|
|
|
|
|
if (DecodeSingleSprite(&dest_sprite, file, file_pos, sprite_type, num, type, zoom_lvl, SpriteComponent::Palette, 1)) {
|
|
|
|
|
SetBit(avail_8bpp, zoom_lvl);
|
|
|
|
|
avail_8bpp.Set(zoom_lvl);
|
|
|
|
|
return avail_8bpp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint8_t LoadSpriteV2(SpriteLoader::SpriteCollection &sprite, SpriteFile &file, size_t file_pos, SpriteType sprite_type, bool load_32bpp, uint8_t control_flags, uint8_t &avail_8bpp, uint8_t &avail_32bpp)
|
|
|
|
|
static ZoomLevels LoadSpriteV2(SpriteLoader::SpriteCollection &sprite, SpriteFile &file, size_t file_pos, SpriteType sprite_type, bool load_32bpp, uint8_t control_flags, ZoomLevels &avail_8bpp, ZoomLevels &avail_32bpp)
|
|
|
|
|
{
|
|
|
|
|
static const ZoomLevel zoom_lvl_map[6] = {ZOOM_LVL_NORMAL, ZOOM_LVL_IN_4X, ZOOM_LVL_IN_2X, ZOOM_LVL_OUT_2X, ZOOM_LVL_OUT_4X, ZOOM_LVL_OUT_8X};
|
|
|
|
|
|
|
|
|
|
/* Is the sprite not present/stripped in the GRF? */
|
|
|
|
|
if (file_pos == SIZE_MAX) return 0;
|
|
|
|
|
if (file_pos == SIZE_MAX) return {};
|
|
|
|
|
|
|
|
|
|
/* Open the right file and go to the correct position */
|
|
|
|
|
file.SeekTo(file_pos, SEEK_SET);
|
|
|
|
|
|
|
|
|
|
uint32_t id = file.ReadDword();
|
|
|
|
|
|
|
|
|
|
uint8_t loaded_sprites = 0;
|
|
|
|
|
ZoomLevels loaded_sprites;
|
|
|
|
|
do {
|
|
|
|
|
int64_t num = file.ReadDword();
|
|
|
|
|
size_t start_pos = file.GetPos();
|
|
|
|
|
uint8_t type = file.ReadByte();
|
|
|
|
|
|
|
|
|
|
/* Type 0xFF indicates either a colourmap or some other non-sprite info; we do not handle them here. */
|
|
|
|
|
if (type == 0xFF) return 0;
|
|
|
|
|
if (type == 0xFF) return {};
|
|
|
|
|
|
|
|
|
|
SpriteComponents colour{type};
|
|
|
|
|
/* Mask out colour component information from type. */
|
|
|
|
@@ -288,17 +288,18 @@ uint8_t LoadSpriteV2(SpriteLoader::SpriteCollection &sprite, SpriteFile &file, s
|
|
|
|
|
|
|
|
|
|
if (sprite_type != SpriteType::MapGen) {
|
|
|
|
|
if (zoom < lengthof(zoom_lvl_map)) {
|
|
|
|
|
if (colour == SpriteComponent::Palette) SetBit(avail_8bpp, zoom_lvl_map[zoom]);
|
|
|
|
|
if (colour != SpriteComponent::Palette) SetBit(avail_32bpp, zoom_lvl_map[zoom]);
|
|
|
|
|
ZoomLevel zoom_lvl = zoom_lvl_map[zoom];
|
|
|
|
|
if (colour == SpriteComponent::Palette) avail_8bpp.Set(zoom_lvl);
|
|
|
|
|
if (colour != SpriteComponent::Palette) avail_32bpp.Set(zoom_lvl);
|
|
|
|
|
|
|
|
|
|
is_wanted_zoom_lvl = true;
|
|
|
|
|
ZoomLevel zoom_min = sprite_type == SpriteType::Font ? ZOOM_LVL_MIN : _settings_client.gui.sprite_zoom_min;
|
|
|
|
|
if (zoom_min >= ZOOM_LVL_IN_2X &&
|
|
|
|
|
HasBit(control_flags, load_32bpp ? SCCF_ALLOW_ZOOM_MIN_2X_32BPP : SCCF_ALLOW_ZOOM_MIN_2X_PAL) && zoom_lvl_map[zoom] < ZOOM_LVL_IN_2X) {
|
|
|
|
|
HasBit(control_flags, load_32bpp ? SCCF_ALLOW_ZOOM_MIN_2X_32BPP : SCCF_ALLOW_ZOOM_MIN_2X_PAL) && zoom_lvl < ZOOM_LVL_IN_2X) {
|
|
|
|
|
is_wanted_zoom_lvl = false;
|
|
|
|
|
}
|
|
|
|
|
if (zoom_min >= ZOOM_LVL_NORMAL &&
|
|
|
|
|
HasBit(control_flags, load_32bpp ? SCCF_ALLOW_ZOOM_MIN_1X_32BPP : SCCF_ALLOW_ZOOM_MIN_1X_PAL) && zoom_lvl_map[zoom] < ZOOM_LVL_NORMAL) {
|
|
|
|
|
HasBit(control_flags, load_32bpp ? SCCF_ALLOW_ZOOM_MIN_1X_32BPP : SCCF_ALLOW_ZOOM_MIN_1X_PAL) && zoom_lvl < ZOOM_LVL_NORMAL) {
|
|
|
|
|
is_wanted_zoom_lvl = false;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
@@ -311,7 +312,7 @@ uint8_t LoadSpriteV2(SpriteLoader::SpriteCollection &sprite, SpriteFile &file, s
|
|
|
|
|
if (is_wanted_colour_depth && is_wanted_zoom_lvl) {
|
|
|
|
|
ZoomLevel zoom_lvl = (sprite_type != SpriteType::MapGen) ? zoom_lvl_map[zoom] : ZOOM_LVL_MIN;
|
|
|
|
|
|
|
|
|
|
if (HasBit(loaded_sprites, zoom_lvl)) {
|
|
|
|
|
if (loaded_sprites.Test(zoom_lvl)) {
|
|
|
|
|
/* We already have this zoom level, skip sprite. */
|
|
|
|
|
Debug(sprite, 1, "Ignoring duplicate zoom level sprite {} from {}", id, file.GetSimplifiedFilename());
|
|
|
|
|
file.SkipBytes(num - 2);
|
|
|
|
@@ -326,7 +327,7 @@ uint8_t LoadSpriteV2(SpriteLoader::SpriteCollection &sprite, SpriteFile &file, s
|
|
|
|
|
|
|
|
|
|
if (dest_sprite.width > INT16_MAX || dest_sprite.height > INT16_MAX) {
|
|
|
|
|
WarnCorruptSprite(file, file_pos, __LINE__);
|
|
|
|
|
return 0;
|
|
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Convert colour components to pixel size. */
|
|
|
|
@@ -344,10 +345,10 @@ uint8_t LoadSpriteV2(SpriteLoader::SpriteCollection &sprite, SpriteFile &file, s
|
|
|
|
|
bool valid = DecodeSingleSprite(&dest_sprite, file, file_pos, sprite_type, decomp_size, type, zoom_lvl, colour, 2);
|
|
|
|
|
if (file.GetPos() != start_pos + num) {
|
|
|
|
|
WarnCorruptSprite(file, file_pos, __LINE__);
|
|
|
|
|
return 0;
|
|
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (valid) SetBit(loaded_sprites, zoom_lvl);
|
|
|
|
|
if (valid) loaded_sprites.Set(zoom_lvl);
|
|
|
|
|
} else {
|
|
|
|
|
/* Not the wanted zoom level or colour depth, continue searching. */
|
|
|
|
|
file.SkipBytes(num - 2);
|
|
|
|
@@ -358,7 +359,7 @@ uint8_t LoadSpriteV2(SpriteLoader::SpriteCollection &sprite, SpriteFile &file, s
|
|
|
|
|
return loaded_sprites;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint8_t SpriteLoaderGrf::LoadSprite(SpriteLoader::SpriteCollection &sprite, SpriteFile &file, size_t file_pos, SpriteType sprite_type, bool load_32bpp, uint8_t control_flags, uint8_t &avail_8bpp, uint8_t &avail_32bpp)
|
|
|
|
|
ZoomLevels SpriteLoaderGrf::LoadSprite(SpriteLoader::SpriteCollection &sprite, SpriteFile &file, size_t file_pos, SpriteType sprite_type, bool load_32bpp, uint8_t control_flags, ZoomLevels &avail_8bpp, ZoomLevels &avail_32bpp)
|
|
|
|
|
{
|
|
|
|
|
if (this->container_ver >= 2) {
|
|
|
|
|
return LoadSpriteV2(sprite, file, file_pos, sprite_type, load_32bpp, control_flags, avail_8bpp, avail_32bpp);
|
|
|
|
|