diff --git a/src/openrct2-ui/drawing/engines/opengl/TextureCache.cpp b/src/openrct2-ui/drawing/engines/opengl/TextureCache.cpp index af63ac516c..5e7bbdf04e 100644 --- a/src/openrct2-ui/drawing/engines/opengl/TextureCache.cpp +++ b/src/openrct2-ui/drawing/engines/opengl/TextureCache.cpp @@ -176,7 +176,7 @@ void TextureCache::GeneratePaletteTexture() GLint y = PaletteToY(i); uint16_t image = palette_to_g1_offset[i]; auto element = gfx_get_g1_element(image); - gfx_draw_sprite_software(&dpi, image, -element->x_offset, y - element->y_offset, 0); + gfx_draw_sprite_software(&dpi, ImageId(image), -element->x_offset, y - element->y_offset, 0); } glBindTexture(GL_TEXTURE_RECTANGLE, _paletteTexture); @@ -299,7 +299,7 @@ rct_drawpixelinfo TextureCache::GetImageAsDPI(uint32_t image, uint32_t tertiaryC int32_t height = g1Element->height; rct_drawpixelinfo dpi = CreateDPI(width, height); - gfx_draw_sprite_software(&dpi, image, -g1Element->x_offset, -g1Element->y_offset, tertiaryColour); + gfx_draw_sprite_software(&dpi, ImageId::FromUInt32(image), -g1Element->x_offset, -g1Element->y_offset, tertiaryColour); return dpi; } @@ -310,7 +310,7 @@ rct_drawpixelinfo TextureCache::GetGlyphAsDPI(uint32_t image, uint8_t* palette) int32_t height = g1Element->height; rct_drawpixelinfo dpi = CreateDPI(width, height); - gfx_draw_sprite_palette_set_software(&dpi, image, -g1Element->x_offset, -g1Element->y_offset, palette, nullptr); + gfx_draw_sprite_palette_set_software(&dpi, ImageId::FromUInt32(image), -g1Element->x_offset, -g1Element->y_offset, palette, nullptr); return dpi; } diff --git a/src/openrct2/CmdlineSprite.cpp b/src/openrct2/CmdlineSprite.cpp index 3a3f52f204..e99f1b13df 100644 --- a/src/openrct2/CmdlineSprite.cpp +++ b/src/openrct2/CmdlineSprite.cpp @@ -238,14 +238,14 @@ static bool sprite_file_export(int32_t spriteIndex, const char* outPath) if (spriteHeader->flags & G1_FLAG_RLE_COMPRESSION) { gfx_rle_sprite_to_buffer( - spriteHeader->offset, pixels, (uint8_t*)spriteFilePalette, &dpi, IMAGE_TYPE_DEFAULT, 0, spriteHeader->height, 0, + spriteHeader->offset, pixels, (uint8_t*)spriteFilePalette, &dpi, ImageId(), 0, spriteHeader->height, 0, spriteHeader->width); } else { gfx_bmp_sprite_to_buffer( (uint8_t*)spriteFilePalette, spriteHeader->offset, pixels, spriteHeader, &dpi, spriteHeader->height, - spriteHeader->width, IMAGE_TYPE_DEFAULT); + spriteHeader->width, ImageId()); } auto const pixels8 = dpi.bits; diff --git a/src/openrct2/drawing/Drawing.Sprite.cpp b/src/openrct2/drawing/Drawing.Sprite.cpp index c86574cf90..d58e3186db 100644 --- a/src/openrct2/drawing/Drawing.Sprite.cpp +++ b/src/openrct2/drawing/Drawing.Sprite.cpp @@ -402,10 +402,11 @@ bool gfx_load_csg() * Copies a sprite onto the buffer. There is no compression used on the sprite * image. * rct2: 0x0067A690 + * @param imageId Only flags are used. */ void FASTCALL gfx_bmp_sprite_to_buffer( const uint8_t* palette_pointer, uint8_t* source_pointer, uint8_t* dest_pointer, const rct_g1_element* source_image, - rct_drawpixelinfo* dest_dpi, int32_t height, int32_t width, int32_t image_type) + rct_drawpixelinfo* dest_dpi, int32_t height, int32_t width, ImageId imageId) { uint16_t zoom_level = dest_dpi->zoom_level; uint8_t zoom_amount = 1 << zoom_level; @@ -413,7 +414,7 @@ void FASTCALL gfx_bmp_sprite_to_buffer( uint32_t source_line_width = source_image->width * zoom_amount; // Image uses the palette pointer to remap the colours of the image - if (image_type & IMAGE_TYPE_REMAP) + if (imageId.HasPrimary()) { assert(palette_pointer != nullptr); @@ -442,7 +443,7 @@ void FASTCALL gfx_bmp_sprite_to_buffer( // Image is transparent. It only uses source pointer for // telling if it needs to be drawn not for colour. Colour provided // by the palette pointer. - if (image_type & IMAGE_TYPE_TRANSPARENT) + if (imageId.IsBlended()) { // Not tested assert(palette_pointer != nullptr); for (; height > 0; height -= zoom_amount) @@ -507,16 +508,15 @@ void FASTCALL gfx_bmp_sprite_to_buffer( } } -uint8_t* FASTCALL gfx_draw_sprite_get_palette(int32_t image_id, uint32_t tertiary_colour) +uint8_t* FASTCALL gfx_draw_sprite_get_palette(ImageId imageId, uint32_t tertiary_colour) { - int32_t image_type = (image_id & 0xE0000000); - if (image_type == 0) + if (!imageId.HasPrimary() && !imageId.HasSecondary() && !imageId.IsBlended()) return nullptr; - if (!(image_type & IMAGE_TYPE_REMAP_2_PLUS)) + if (!imageId.HasSecondary()) { - uint8_t palette_ref = (image_id >> 19) & 0xFF; - if (!(image_type & IMAGE_TYPE_TRANSPARENT)) + uint8_t palette_ref = imageId.GetRemap(); + if (!imageId.IsBlended()) { palette_ref &= 0x7F; } @@ -536,10 +536,10 @@ uint8_t* FASTCALL gfx_draw_sprite_get_palette(int32_t image_id, uint32_t tertiar { uint8_t* palette_pointer = gPeepPalette; - uint32_t primary_offset = palette_to_g1_offset[(image_id >> 19) & 0x1F]; - uint32_t secondary_offset = palette_to_g1_offset[(image_id >> 24) & 0x1F]; + uint32_t primary_offset = palette_to_g1_offset[imageId.GetPrimary()]; + uint32_t secondary_offset = palette_to_g1_offset[imageId.GetSecondary()]; - if (!(image_type & IMAGE_TYPE_REMAP)) + if (!imageId.HasPrimary()) { palette_pointer = gOtherPalette; #if defined(DEBUG_LEVEL_2) && DEBUG_LEVEL_2 @@ -583,17 +583,17 @@ uint8_t* FASTCALL gfx_draw_sprite_get_palette(int32_t image_id, uint32_t tertiar * dpi (esi) * tertiary_colour (ebp) */ -void FASTCALL gfx_draw_sprite_software(rct_drawpixelinfo* dpi, int32_t image_id, int32_t x, int32_t y, uint32_t tertiary_colour) +void FASTCALL gfx_draw_sprite_software(rct_drawpixelinfo* dpi, ImageId imageId, int32_t x, int32_t y, uint32_t tertiary_colour) { - if (image_id != -1) + if (imageId.HasValue()) { - uint8_t* palette_pointer = gfx_draw_sprite_get_palette(image_id, tertiary_colour); - if (image_id & IMAGE_TYPE_REMAP_2_PLUS) + uint8_t* palette_pointer = gfx_draw_sprite_get_palette(imageId, tertiary_colour); + if (imageId.HasSecondary()) { - image_id |= IMAGE_TYPE_REMAP; + imageId = imageId.WithPrimary(imageId.GetPrimary()); } - gfx_draw_sprite_palette_set_software(dpi, image_id, x, y, palette_pointer, nullptr); + gfx_draw_sprite_palette_set_software(dpi, imageId, x, y, palette_pointer, nullptr); } } @@ -607,12 +607,9 @@ void FASTCALL gfx_draw_sprite_software(rct_drawpixelinfo* dpi, int32_t image_id, * y (dx) */ void FASTCALL gfx_draw_sprite_palette_set_software( - rct_drawpixelinfo* dpi, int32_t image_id, int32_t x, int32_t y, uint8_t* palette_pointer, uint8_t* unknown_pointer) + rct_drawpixelinfo* dpi, ImageId imageId, int32_t x, int32_t y, uint8_t* palette_pointer, uint8_t* unknown_pointer) { - int32_t image_element = image_id & 0x7FFFF; - int32_t image_type = image_id & 0xE0000000; - - const rct_g1_element* g1 = gfx_get_g1_element(image_element); + const auto* g1 = gfx_get_g1_element(imageId); if (g1 == nullptr) { return; @@ -629,7 +626,8 @@ void FASTCALL gfx_draw_sprite_palette_set_software( zoomed_dpi.pitch = dpi->pitch; zoomed_dpi.zoom_level = dpi->zoom_level - 1; gfx_draw_sprite_palette_set_software( - &zoomed_dpi, image_type | (image_element - g1->zoomed_offset), x >> 1, y >> 1, palette_pointer, unknown_pointer); + &zoomed_dpi, imageId.WithIndex(imageId.GetIndex() - g1->zoomed_offset), x >> 1, y >> 1, palette_pointer, + unknown_pointer); return; } @@ -757,16 +755,14 @@ void FASTCALL gfx_draw_sprite_palette_set_software( // We have to use a different method to move the source pointer for // rle encoded sprites so that will be handled within this function gfx_rle_sprite_to_buffer( - g1->offset, dest_pointer, palette_pointer, dpi, image_type, source_start_y, height, source_start_x, width); + g1->offset, dest_pointer, palette_pointer, dpi, imageId, source_start_y, height, source_start_x, width); return; } - uint8_t* source_pointer = g1->offset; - // Move the pointer to the start point of the source - source_pointer += g1->width * source_start_y + source_start_x; - - if (!(g1->flags & G1_FLAG_1)) + else if (!(g1->flags & G1_FLAG_1)) { - gfx_bmp_sprite_to_buffer(palette_pointer, source_pointer, dest_pointer, g1, dpi, height, width, image_type); + // Move the pointer to the start point of the source + auto source_pointer = g1->offset + (((size_t)g1->width * source_start_y) + source_start_x); + gfx_bmp_sprite_to_buffer(palette_pointer, source_pointer, dest_pointer, g1, dpi, height, width, imageId); } } @@ -790,7 +786,7 @@ void FASTCALL // Only BMP format is supported for masking if (!(imgMask->flags & G1_FLAG_BMP) || !(imgColour->flags & G1_FLAG_BMP)) { - gfx_draw_sprite_software(dpi, colourImage, x, y, 0); + gfx_draw_sprite_software(dpi, ImageId::FromUInt32(colourImage), x, y, 0); return; } @@ -831,6 +827,11 @@ void FASTCALL mask_fn(width, height, maskSrc, colourSrc, dst, maskWrap, colourWrap, dstWrap); } +const rct_g1_element* gfx_get_g1_element(ImageId imageId) +{ + return gfx_get_g1_element(imageId.GetIndex()); +} + const rct_g1_element* gfx_get_g1_element(int32_t image_id) { openrct2_assert(!gOpenRCT2NoGraphics, "gfx_get_g1_element called on headless instance"); diff --git a/src/openrct2/drawing/Drawing.h b/src/openrct2/drawing/Drawing.h index d949c08526..2d24c6983e 100644 --- a/src/openrct2/drawing/Drawing.h +++ b/src/openrct2/drawing/Drawing.h @@ -252,19 +252,32 @@ struct ImageId private: // clang-format off static constexpr uint32_t MASK_INDEX = 0b00000000000001111111111111111111; + static constexpr uint32_t MASK_REMAP = 0b00000111111110000000000000000000; static constexpr uint32_t MASK_PRIMARY = 0b00000000111110000000000000000000; static constexpr uint32_t MASK_SECONDARY = 0b00011111000000000000000000000000; static constexpr uint32_t FLAG_PRIMARY = 0b00100000000000000000000000000000; - static constexpr uint32_t FLAG_TRANSPARENT = 0b01000000000000000000000000000000; + static constexpr uint32_t FLAG_BLEND = 0b01000000000000000000000000000000; static constexpr uint32_t FLAG_SECONDARY = 0b10000000000000000000000000000000; + static constexpr uint32_t SHIFT_REMAP = 19; static constexpr uint32_t SHIFT_PRIMARY = 19; static constexpr uint32_t SHIFT_SECONDARY = 24; + static constexpr uint32_t INDEX_UNDEFINED = 0b00000000000001111111111111111111; + static constexpr uint32_t VALUE_UNDEFINED = INDEX_UNDEFINED; // clang-format on - uint32_t _value; + uint32_t _value = VALUE_UNDEFINED; public: - ImageId(uint32_t index) + static ImageId FromUInt32(uint32_t value) + { + ImageId result; + result._value = value; + return result; + } + + ImageId() = default; + + explicit ImageId(uint32_t index) : _value(index & MASK_INDEX) { } @@ -284,23 +297,55 @@ public: return _value; } + bool HasValue() const + { + return GetIndex() != INDEX_UNDEFINED; + } + + bool HasPrimary() const + { + return _value & FLAG_PRIMARY; + } + + bool HasSecondary() const + { + return _value & FLAG_SECONDARY; + } + + bool IsBlended() const + { + return _value & FLAG_BLEND; + } + uint32_t GetIndex() const { return _value & MASK_INDEX; } + uint8_t GetRemap() const + { + return (_value & MASK_REMAP) >> SHIFT_REMAP; + } + colour_t GetPrimary() const { - return _value & MASK_PRIMARY; + return (_value & MASK_PRIMARY) >> SHIFT_PRIMARY; } colour_t GetSecondary() const { - return _value & MASK_SECONDARY; + return (_value & MASK_SECONDARY) >> SHIFT_SECONDARY; } ImageCatalogue GetCatalogue() const; + ImageId WithIndex(uint32_t index) + { + ImageId result = *this; + result._value = (_value & ~MASK_INDEX) | (index & MASK_INDEX); + return result; + } + ImageId WithPrimary(colour_t colour) { ImageId result = *this; @@ -390,6 +435,7 @@ bool gfx_load_csg(); void gfx_unload_g1(); void gfx_unload_g2(); void gfx_unload_csg(); +const rct_g1_element* gfx_get_g1_element(ImageId imageId); const rct_g1_element* gfx_get_g1_element(int32_t image_id); void gfx_set_g1_element(int32_t imageId, const rct_g1_element* g1); bool is_csg_loaded(); @@ -398,21 +444,20 @@ void gfx_object_free_images(uint32_t baseImageId, uint32_t count); void gfx_object_check_all_images_freed(); void FASTCALL gfx_bmp_sprite_to_buffer( const uint8_t* palette_pointer, uint8_t* source_pointer, uint8_t* dest_pointer, const rct_g1_element* source_image, - rct_drawpixelinfo* dest_dpi, int32_t height, int32_t width, int32_t image_type); + rct_drawpixelinfo* dest_dpi, int32_t height, int32_t width, ImageId imageId); void FASTCALL gfx_rle_sprite_to_buffer( const uint8_t* RESTRICT source_bits_pointer, uint8_t* RESTRICT dest_bits_pointer, const uint8_t* RESTRICT palette_pointer, - const rct_drawpixelinfo* RESTRICT dpi, int32_t image_type, int32_t source_y_start, int32_t height, int32_t source_x_start, + const rct_drawpixelinfo* RESTRICT dpi, ImageId imageId, int32_t source_y_start, int32_t height, int32_t source_x_start, int32_t width); void FASTCALL gfx_draw_sprite(rct_drawpixelinfo* dpi, int32_t image_id, int32_t x, int32_t y, uint32_t tertiary_colour); void FASTCALL gfx_draw_glpyh(rct_drawpixelinfo* dpi, int32_t image_id, int32_t x, int32_t y, uint8_t* palette); void FASTCALL gfx_draw_sprite_raw_masked(rct_drawpixelinfo* dpi, int32_t x, int32_t y, int32_t maskImage, int32_t colourImage); void FASTCALL gfx_draw_sprite_solid(rct_drawpixelinfo* dpi, int32_t image, int32_t x, int32_t y, uint8_t colour); -void FASTCALL - gfx_draw_sprite_software(rct_drawpixelinfo* dpi, int32_t image_id, int32_t x, int32_t y, uint32_t tertiary_colour); -uint8_t* FASTCALL gfx_draw_sprite_get_palette(int32_t image_id, uint32_t tertiary_colour); +void FASTCALL gfx_draw_sprite_software(rct_drawpixelinfo* dpi, ImageId imageId, int32_t x, int32_t y, uint32_t tertiary_colour); +uint8_t* FASTCALL gfx_draw_sprite_get_palette(ImageId imageId, uint32_t tertiary_colour); void FASTCALL gfx_draw_sprite_palette_set_software( - rct_drawpixelinfo* dpi, int32_t image_id, int32_t x, int32_t y, uint8_t* palette_pointer, uint8_t* unknown_pointer); + rct_drawpixelinfo* dpi, ImageId imageId, int32_t x, int32_t y, uint8_t* palette_pointer, uint8_t* unknown_pointer); void FASTCALL gfx_draw_sprite_raw_masked_software(rct_drawpixelinfo* dpi, int32_t x, int32_t y, int32_t maskImage, int32_t colourImage); diff --git a/src/openrct2/drawing/DrawingFast.cpp b/src/openrct2/drawing/DrawingFast.cpp index 3b2d977f85..9db5e4fbe0 100644 --- a/src/openrct2/drawing/DrawingFast.cpp +++ b/src/openrct2/drawing/DrawingFast.cpp @@ -176,15 +176,16 @@ static void FASTCALL DrawRLESprite1( * Transfers readied images onto buffers * This function copies the sprite data onto the screen * rct2: 0x0067AA18 + * @param imageId Only flags are used. */ void FASTCALL gfx_rle_sprite_to_buffer( const uint8_t* RESTRICT source_bits_pointer, uint8_t* RESTRICT dest_bits_pointer, const uint8_t* RESTRICT palette_pointer, - const rct_drawpixelinfo* RESTRICT dpi, int32_t image_type, int32_t source_y_start, int32_t height, int32_t source_x_start, + const rct_drawpixelinfo* RESTRICT dpi, ImageId imageId, int32_t source_y_start, int32_t height, int32_t source_x_start, int32_t width) { - if (image_type & IMAGE_TYPE_REMAP) + if (imageId.HasPrimary()) { - if (image_type & IMAGE_TYPE_TRANSPARENT) + if (imageId.IsBlended()) { DrawRLESpriteHelper1(IMAGE_TYPE_REMAP | IMAGE_TYPE_TRANSPARENT); } @@ -193,7 +194,7 @@ void FASTCALL gfx_rle_sprite_to_buffer( DrawRLESpriteHelper1(IMAGE_TYPE_REMAP); } } - else if (image_type & IMAGE_TYPE_TRANSPARENT) + else if (imageId.IsBlended()) { DrawRLESpriteHelper1(IMAGE_TYPE_TRANSPARENT); } diff --git a/src/openrct2/drawing/ScrollingText.cpp b/src/openrct2/drawing/ScrollingText.cpp index 680442849d..e6ba629473 100644 --- a/src/openrct2/drawing/ScrollingText.cpp +++ b/src/openrct2/drawing/ScrollingText.cpp @@ -53,7 +53,7 @@ void scrolling_text_initialise_bitmaps() for (int32_t i = 0; i < FONT_SPRITE_GLYPH_COUNT; i++) { std::fill_n(drawingSurface, sizeof(drawingSurface), 0x00); - gfx_draw_sprite_software(&dpi, SPR_CHAR_START + FONT_SPRITE_BASE_TINY + i, -1, 0, 0); + gfx_draw_sprite_software(&dpi, ImageId::FromUInt32(SPR_CHAR_START + FONT_SPRITE_BASE_TINY + i), -1, 0, 0); for (int32_t x = 0; x < 8; x++) { @@ -74,7 +74,8 @@ void scrolling_text_initialise_bitmaps() for (int32_t i = 0; i < SPR_G2_GLYPH_COUNT; i++) { std::fill_n(drawingSurface, sizeof(drawingSurface), 0x00); - gfx_draw_sprite_software(&dpi, SPR_G2_CHAR_BEGIN + (FONT_SIZE_TINY * SPR_G2_GLYPH_COUNT) + i, -1, 0, 0); + gfx_draw_sprite_software( + &dpi, ImageId::FromUInt32(SPR_G2_CHAR_BEGIN + (FONT_SIZE_TINY * SPR_G2_GLYPH_COUNT) + i), -1, 0, 0); for (int32_t x = 0; x < 8; x++) { diff --git a/src/openrct2/drawing/X8DrawingEngine.cpp b/src/openrct2/drawing/X8DrawingEngine.cpp index 555cc548e3..774a6a58bb 100644 --- a/src/openrct2/drawing/X8DrawingEngine.cpp +++ b/src/openrct2/drawing/X8DrawingEngine.cpp @@ -730,7 +730,7 @@ void X8DrawingContext::DrawLine(uint32_t colour, int32_t x1, int32_t y1, int32_t void X8DrawingContext::DrawSprite(uint32_t image, int32_t x, int32_t y, uint32_t tertiaryColour) { - gfx_draw_sprite_software(_dpi, image, x, y, tertiaryColour); + gfx_draw_sprite_software(_dpi, ImageId::FromUInt32(image), x, y, tertiaryColour); } void X8DrawingContext::DrawSpriteRawMasked(int32_t x, int32_t y, uint32_t maskImage, uint32_t colourImage) @@ -743,14 +743,12 @@ void X8DrawingContext::DrawSpriteSolid(uint32_t image, int32_t x, int32_t y, uin uint8_t palette[256]; std::fill_n(palette, sizeof(palette), colour); palette[0] = 0; - - image &= 0x7FFFF; - gfx_draw_sprite_palette_set_software(_dpi, image | IMAGE_TYPE_REMAP, x, y, palette, nullptr); + gfx_draw_sprite_palette_set_software(_dpi, ImageId::FromUInt32((image & 0x7FFFF) | IMAGE_TYPE_REMAP), x, y, palette, nullptr); } void X8DrawingContext::DrawGlyph(uint32_t image, int32_t x, int32_t y, uint8_t* palette) { - gfx_draw_sprite_palette_set_software(_dpi, image, x, y, palette, nullptr); + gfx_draw_sprite_palette_set_software(_dpi, ImageId::FromUInt32(image), x, y, palette, nullptr); } void X8DrawingContext::SetDPI(rct_drawpixelinfo* dpi) diff --git a/src/openrct2/ride/Ride.cpp b/src/openrct2/ride/Ride.cpp index 206ea629f6..e8a6f3806e 100644 --- a/src/openrct2/ride/Ride.cpp +++ b/src/openrct2/ride/Ride.cpp @@ -6072,7 +6072,7 @@ void set_vehicle_type_image_max_sizes(rct_ride_entry_vehicle* vehicle_type, int3 for (int32_t i = 0; i < num_images; ++i) { - gfx_draw_sprite_software(&dpi, vehicle_type->base_image_id + i, 0, 0, 0); + gfx_draw_sprite_software(&dpi, ImageId::FromUInt32(vehicle_type->base_image_id + i), 0, 0, 0); } int32_t al = -1; for (int32_t i = 99; i != 0; --i)