From 782c80b5890bdb11712b9d27abbb7398bd4be08e Mon Sep 17 00:00:00 2001 From: dP Date: Sat, 17 Feb 2024 22:29:34 +0530 Subject: [PATCH] Fix #14: Don't recolour 32bpp sprites to 8bpp when not tinted --- src/blitter/32bpp_anim.cpp | 40 +++++++++ src/blitter/32bpp_anim_sse4.hpp | 2 +- src/blitter/32bpp_base.hpp | 27 ------- src/blitter/32bpp_optimized.cpp | 35 +++++++- src/blitter/32bpp_simple.cpp | 16 +++- src/blitter/32bpp_sse2.cpp | 4 +- src/blitter/32bpp_sse2.hpp | 4 +- src/blitter/40bpp_anim.cpp | 21 ++++- src/blitter/8bpp_optimized.cpp | 1 + src/blitter/8bpp_simple.cpp | 1 + src/blitter/base.cpp | 138 -------------------------------- src/blitter/base.hpp | 1 + src/citymania/CMakeLists.txt | 2 + src/gfx.cpp | 3 + 14 files changed, 117 insertions(+), 178 deletions(-) delete mode 100644 src/blitter/base.cpp diff --git a/src/blitter/32bpp_anim.cpp b/src/blitter/32bpp_anim.cpp index 0c2612fcde..1fbc5fd3f3 100644 --- a/src/blitter/32bpp_anim.cpp +++ b/src/blitter/32bpp_anim.cpp @@ -15,6 +15,8 @@ #include "../table/sprites.h" +#include "../citymania/cm_colour.hpp" + #include "../safeguards.h" /** Instantiation of the 32bpp with animation blitter factory. */ @@ -103,6 +105,43 @@ inline void Blitter_32bppAnim::Draw(const Blitter::BlitterParams *bp, ZoomLevel draw:; switch (mode) { + case CM_BM_TINT_REMAP: + if (src_px->a == 255) { + do { + uint m = *src_n; + /* In case the m-channel is zero, do not remap this pixel in any way */ + if (m == 0) { + *dst = citymania::Remap32RGB(src_px->r, src_px->g, src_px->b, remap); + *anim = 0; + } else { + uint r = remap[GB(m, 0, 8)]; + *anim = r | (m & 0xFF00); + if (r != 0) *dst = this->AdjustBrightness(this->LookupColourInPalette(r), GB(m, 8, 8)); + } + anim++; + dst++; + src_px++; + src_n++; + } while (--n != 0); + } else { + do { + uint m = *src_n; + if (m == 0) { + *dst = citymania::Remap32RGBANoCheck(src_px->r, src_px->g, src_px->b, src_px->a, *dst, remap); + *anim = 0; + } else { + uint r = remap[GB(m, 0, 8)]; + *anim = 0; + if (r != 0) *dst = ComposeColourPANoCheck(this->AdjustBrightness(this->LookupColourInPalette(r), GB(m, 8, 8)), src_px->a, *dst); + } + anim++; + dst++; + src_px++; + src_n++; + } while (--n != 0); + } + break; + case BM_COLOUR_REMAP: if (src_px->a == 255) { do { @@ -278,6 +317,7 @@ void Blitter_32bppAnim::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomL default: NOT_REACHED(); case BM_NORMAL: Draw (bp, zoom); return; case BM_COLOUR_REMAP: Draw(bp, zoom); return; + case CM_BM_TINT_REMAP: Draw(bp, zoom); return; case BM_TRANSPARENT: Draw (bp, zoom); return; case BM_TRANSPARENT_REMAP: Draw(bp, zoom); return; case BM_CRASH_REMAP: Draw (bp, zoom); return; diff --git a/src/blitter/32bpp_anim_sse4.hpp b/src/blitter/32bpp_anim_sse4.hpp index f84e55d0b6..d11c90d341 100644 --- a/src/blitter/32bpp_anim_sse4.hpp +++ b/src/blitter/32bpp_anim_sse4.hpp @@ -40,7 +40,7 @@ public: void Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom); void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom) override; Sprite *Encode(const SpriteLoader::SpriteCollection &sprite, AllocatorProc *allocator) override { - return Blitter_32bppSSE2::Encode(sprite, allocator); // CM FIXME 14.0-beta1 why SSE -> SSE2 + return Blitter_32bppSSE_Base::Encode(sprite, allocator); } const char *GetName() override { return "32bpp-sse4-anim"; } using Blitter_32bppSSE2_Anim::LookupColourInPalette; diff --git a/src/blitter/32bpp_base.hpp b/src/blitter/32bpp_base.hpp index b25ee58978..f5d8a30c4e 100644 --- a/src/blitter/32bpp_base.hpp +++ b/src/blitter/32bpp_base.hpp @@ -175,33 +175,6 @@ public: return rgb_max; } - - /* CM */ - uint8 cm_mdict[64*64*64] = {0}; - uint8 CM_GetMForRGB(uint8 r, uint8 g, uint8 b) { - if (r==0 && g==0 && b==0) return 0; - r &= 252; g &= 252; b &= 252; - auto key = (r << 10) | (g << 4) | (b >> 2); - auto m = this->cm_mdict[key]; - if (m != 0) return m; - uint md = UINT_MAX; - for (uint8 i = 1; i < 0xc0; i++) { - auto c = this->LookupColourInPalette(i); - auto rmean = (int)c.r + (int)r; - auto dr = (int)c.r - (int)r; - auto dg = (int)c.g - (int)g; - auto db = (int)c.b - (int)b; - auto dist = (1020 + rmean) * dr * dr + 2040 * dg * dg + (1530 - rmean) * db * db; - // auto dist = r * r + g * g + b * b; - if (dist < md) { - md = dist; - m = i; - } - } - this->cm_mdict[key] = m; - return m; - } - }; #endif /* BLITTER_32BPP_BASE_HPP */ diff --git a/src/blitter/32bpp_optimized.cpp b/src/blitter/32bpp_optimized.cpp index bbbfa16da4..575b99a047 100644 --- a/src/blitter/32bpp_optimized.cpp +++ b/src/blitter/32bpp_optimized.cpp @@ -13,6 +13,8 @@ #include "../palette_func.h" #include "32bpp_optimized.hpp" +#include "../citymania/cm_colour.hpp" + #include "../safeguards.h" /** Instantiation of the optimized 32bpp blitter factory. */ @@ -111,6 +113,37 @@ inline void Blitter_32bppOptimized::Draw(const Blitter::BlitterParams *bp, ZoomL draw:; switch (mode) { + case CM_BM_TINT_REMAP: + if (src_px->a == 255) { + do { + uint m = *src_n; + /* In case the m-channel is zero, do not remap this pixel in any way */ + if (m == 0) { + *dst = citymania::Remap32RGB(src_px->r, src_px->g, src_px->b, remap); + } else { + uint r = remap[GB(m, 0, 8)]; + if (r != 0) *dst = this->AdjustBrightness(this->LookupColourInPalette(r), GB(m, 8, 8)); + } + dst++; + src_px++; + src_n++; + } while (--n != 0); + } else { + do { + uint m = *src_n; + if (m == 0) { + *dst = citymania::Remap32RGBANoCheck(src_px->r, src_px->g, src_px->b, src_px->a, *dst, remap); + } else { + uint r = remap[GB(m, 0, 8)]; + if (r != 0) *dst = ComposeColourPANoCheck(this->AdjustBrightness(this->LookupColourInPalette(r), GB(m, 8, 8)), src_px->a, *dst); + } + dst++; + src_px++; + src_n++; + } while (--n != 0); + } + break; + case BM_COLOUR_REMAP: if (src_px->a == 255) { do { @@ -263,6 +296,7 @@ void Blitter_32bppOptimized::Draw(Blitter::BlitterParams *bp, BlitterMode mode, default: NOT_REACHED(); case BM_NORMAL: Draw(bp, zoom); return; case BM_COLOUR_REMAP: Draw(bp, zoom); return; + case CM_BM_TINT_REMAP: Draw(bp, zoom); return; case BM_TRANSPARENT: Draw(bp, zoom); return; case BM_TRANSPARENT_REMAP: Draw(bp, zoom); return; case BM_CRASH_REMAP: Draw(bp, zoom); return; @@ -379,7 +413,6 @@ template Sprite *Blitter_32bppOptimized::EncodeInternal(const dst_px->r = src->r; dst_px->g = src->g; dst_px->b = src->b; - if (Tpal_to_rgb) *dst_n = this->CM_GetMForRGB(src->r, src->g, src->b) | (DEFAULT_BRIGHTNESS << 8); } dst_px++; dst_n++; diff --git a/src/blitter/32bpp_simple.cpp b/src/blitter/32bpp_simple.cpp index 0f1ebe7d15..dffa2657c0 100644 --- a/src/blitter/32bpp_simple.cpp +++ b/src/blitter/32bpp_simple.cpp @@ -14,6 +14,8 @@ #include "../table/sprites.h" +#include "../citymania/cm_colour.hpp" + #include "../safeguards.h" /** Instantiation of the simple 32bpp blitter factory. */ @@ -37,6 +39,15 @@ void Blitter_32bppSimple::Draw(Blitter::BlitterParams *bp, BlitterMode mode, Zoo for (int x = 0; x < bp->width; x++) { switch (mode) { + case CM_BM_TINT_REMAP: + /* In case the m-channel is zero, do not remap this pixel in any way */ + if (src->m == 0) { + if (src->a != 0) *dst = citymania::Remap32RGBA(src->r, src->g, src->b, src->a, *dst, bp->remap); + } else { + if (bp->remap[src->m] != 0) *dst = ComposeColourPA(this->AdjustBrightness(this->LookupColourInPalette(bp->remap[src->m]), src->v), src->a, *dst); + } + break; + case BM_COLOUR_REMAP: /* In case the m-channel is zero, do not remap this pixel in any way */ if (src->m == 0) { @@ -90,6 +101,7 @@ void Blitter_32bppSimple::Draw(Blitter::BlitterParams *bp, BlitterMode mode, Zoo void Blitter_32bppSimple::DrawColourMappingRect(void *dst, int width, int height, PaletteID pal) { Colour *udst = (Colour *)dst; + if (pal == PALETTE_TO_TRANSPARENT) { do { for (int i = 0; i != width; i++) { @@ -133,8 +145,8 @@ Sprite *Blitter_32bppSimple::Encode(const SpriteLoader::SpriteCollection &sprite dst[i].g = src->g; dst[i].b = src->b; dst[i].a = src->a; - dst[i].m = this->CM_GetMForRGB(src->r, src->g, src->b); - dst[i].v = DEFAULT_BRIGHTNESS; + dst[i].m = 0; + dst[i].v = 0; } else { /* Get brightest value */ uint8_t rgb_max = std::max({src->r, src->g, src->b}); diff --git a/src/blitter/32bpp_sse2.cpp b/src/blitter/32bpp_sse2.cpp index bd6c61cc5c..1638127b56 100644 --- a/src/blitter/32bpp_sse2.cpp +++ b/src/blitter/32bpp_sse2.cpp @@ -20,7 +20,7 @@ /** Instantiation of the SSE2 32bpp blitter factory. */ static FBlitter_32bppSSE2 iFBlitter_32bppSSE2; -Sprite *Blitter_32bppSSE_Base::Encode(const SpriteLoader::SpriteCollection &sprite, AllocatorProc *allocator, Blitter_32bppSimple *base_blitter) +Sprite *Blitter_32bppSSE_Base::Encode(const SpriteLoader::SpriteCollection &sprite, AllocatorProc *allocator) { /* First uint32_t of a line = the number of transparent pixels from the left. * Second uint32_t of a line = the number of transparent pixels from the right. @@ -89,11 +89,9 @@ Sprite *Blitter_32bppSSE_Base::Encode(const SpriteLoader::SpriteCollection &spri dst_rgba->g = colour.g; dst_rgba->b = colour.b; } else { - has_remap = true; dst_rgba->r = src->r; dst_rgba->g = src->g; dst_rgba->b = src->b; - dst_mv->m = base_blitter->CM_GetMForRGB(src->r, src->g, src->b); dst_mv->v = Blitter_32bppBase::DEFAULT_BRIGHTNESS; } } else { diff --git a/src/blitter/32bpp_sse2.hpp b/src/blitter/32bpp_sse2.hpp index d6d44fea4a..fa643dd3cd 100644 --- a/src/blitter/32bpp_sse2.hpp +++ b/src/blitter/32bpp_sse2.hpp @@ -76,7 +76,7 @@ public: byte data[]; ///< Data, all zoomlevels. }; - Sprite *Encode(const SpriteLoader::SpriteCollection &sprite, AllocatorProc *allocator, Blitter_32bppSimple *base_blitter); + Sprite *Encode(const SpriteLoader::SpriteCollection &sprite, AllocatorProc *allocator); }; DECLARE_ENUM_AS_BIT_SET(Blitter_32bppSSE_Base::SpriteFlags); @@ -89,7 +89,7 @@ public: void Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom); Sprite *Encode(const SpriteLoader::SpriteCollection &sprite, AllocatorProc *allocator) override { - return Blitter_32bppSSE_Base::Encode(sprite, allocator, this); + return Blitter_32bppSSE_Base::Encode(sprite, allocator); } const char *GetName() override { return "32bpp-sse2"; } diff --git a/src/blitter/40bpp_anim.cpp b/src/blitter/40bpp_anim.cpp index be5492e6f1..6b9ca6b3d4 100644 --- a/src/blitter/40bpp_anim.cpp +++ b/src/blitter/40bpp_anim.cpp @@ -17,6 +17,8 @@ #include "../table/sprites.h" +#include "../citymania/cm_colour.hpp" + #include "../safeguards.h" @@ -182,14 +184,20 @@ inline void Blitter_40bppAnim::Draw(const Blitter::BlitterParams *bp, ZoomLevel switch (mode) { case BM_COLOUR_REMAP: + case CM_BM_TINT_REMAP: case BM_CRASH_REMAP: if (src_px->a == 255) { do { uint8_t m = GB(*src_n, 0, 8); /* In case the m-channel is zero, only apply the crash remap by darkening the RGB colour. */ if (m == 0) { - *dst = mode == BM_CRASH_REMAP ? this->MakeDark(*src_px) : *src_px; - *anim = mode == BM_CRASH_REMAP ? 0 : remap[this->CM_GetMForRGB(src_px->r, src_px->g, src_px->b)]; + switch (mode) { + case BM_COLOUR_REMAP: *dst = *src_px; break; + case CM_BM_TINT_REMAP: *dst = citymania::Remap32RGB(src_px->r, src_px->g, src_px->b, remap); break; + case BM_CRASH_REMAP: *dst = this->MakeDark(*src_px); break; + default: NOT_REACHED(); + } + *anim = 0; } else { uint r = remap[m]; if (r != 0) { @@ -207,8 +215,12 @@ inline void Blitter_40bppAnim::Draw(const Blitter::BlitterParams *bp, ZoomLevel uint8_t m = GB(*src_n, 0, 8); Colour b = this->RealizeBlendedColour(*anim, *dst); if (m == 0) { - Colour c = mode == BM_CRASH_REMAP ? this->MakeDark(*src_px) : *src_px; - *dst = this->ComposeColourRGBANoCheck(c.r, c.g, c.b, src_px->a, b); + switch (mode) { + case BM_COLOUR_REMAP: *dst = this->ComposeColourRGBANoCheck(src_px->r, src_px->g, src_px->b, src_px->a, b); break; + case CM_BM_TINT_REMAP: *dst = citymania::Remap32RGBANoCheck(src_px->r, src_px->g, src_px->b, src_px->a, b, remap); break; + case BM_CRASH_REMAP: *dst = this->ComposeColourPANoCheck(this->MakeDark(*src_px), src_px->a, b); break; + default: NOT_REACHED(); + } *anim = 0; } else { uint r = remap[m]; @@ -341,6 +353,7 @@ void Blitter_40bppAnim::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomL default: NOT_REACHED(); case BM_NORMAL: Draw (bp, zoom); return; case BM_COLOUR_REMAP: Draw(bp, zoom); return; + case CM_BM_TINT_REMAP: Draw(bp, zoom); return; case BM_TRANSPARENT: Draw (bp, zoom); return; case BM_TRANSPARENT_REMAP: Draw(bp, zoom); return; case BM_CRASH_REMAP: Draw (bp, zoom); return; diff --git a/src/blitter/8bpp_optimized.cpp b/src/blitter/8bpp_optimized.cpp index 3758e3a80a..6c45697e39 100644 --- a/src/blitter/8bpp_optimized.cpp +++ b/src/blitter/8bpp_optimized.cpp @@ -84,6 +84,7 @@ void Blitter_8bppOptimized::Draw(Blitter::BlitterParams *bp, BlitterMode mode, Z width -= pixels; switch (mode) { + case CM_BM_TINT_REMAP: case BM_COLOUR_REMAP: case BM_CRASH_REMAP: { const uint8_t *remap = bp->remap; diff --git a/src/blitter/8bpp_simple.cpp b/src/blitter/8bpp_simple.cpp index a80ceba115..8aca919a56 100644 --- a/src/blitter/8bpp_simple.cpp +++ b/src/blitter/8bpp_simple.cpp @@ -36,6 +36,7 @@ void Blitter_8bppSimple::Draw(Blitter::BlitterParams *bp, BlitterMode mode, Zoom uint colour = 0; switch (mode) { + case CM_BM_TINT_REMAP: case BM_COLOUR_REMAP: case BM_CRASH_REMAP: colour = bp->remap[*src]; diff --git a/src/blitter/base.cpp b/src/blitter/base.cpp deleted file mode 100644 index cbce0efa04..0000000000 --- a/src/blitter/base.cpp +++ /dev/null @@ -1,138 +0,0 @@ -/* $Id: base.cpp 26482 2014-04-23 20:13:33Z rubidium $ */ - -/* - * This file is part of OpenTTD. - * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. - * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . - */ - -/** @file base.cpp Implementation of the base for all blitters. */ - -#include "../stdafx.h" -#include "base.hpp" -#include "../core/math_func.hpp" - -#include "../safeguards.h" - -void Blitter::DrawLine(void *video, int x, int y, int x2, int y2, int screen_width, int screen_height, uint8 colour, int width, int dash) -{ - int dy; - int dx; - int stepx; - int stepy; - - dy = (y2 - y) * 2; - if (dy < 0) { - dy = -dy; - stepy = -1; - } else { - stepy = 1; - } - - dx = (x2 - x) * 2; - if (dx < 0) { - dx = -dx; - stepx = -1; - } else { - stepx = 1; - } - - if (dx == 0 && dy == 0) { - /* The algorithm below cannot handle this special case; make it work at least for line width 1 */ - if (x >= 0 && x < screen_width && y >= 0 && y < screen_height) this->SetPixel(video, x, y, colour); - return; - } - - int frac_diff = width * max(dx, dy); - if (width > 1) { - /* compute frac_diff = width * sqrt(dx*dx + dy*dy) - * Start interval: - * max(dx, dy) <= sqrt(dx*dx + dy*dy) <= sqrt(2) * max(dx, dy) <= 3/2 * max(dx, dy) */ - int frac_sq = width * width * (dx * dx + dy * dy); - int frac_max = 3 * frac_diff / 2; - while (frac_diff < frac_max) { - int frac_test = (frac_diff + frac_max) / 2; - if (frac_test * frac_test < frac_sq) { - frac_diff = frac_test + 1; - } else { - frac_max = frac_test - 1; - } - } - } - - int gap = dash; - if (dash == 0) dash = 1; - int dash_count = 0; - if (dx > dy) { - int y_low = y; - int y_high = y; - int frac_low = dy - frac_diff / 2; - int frac_high = dy + frac_diff / 2; - - while (frac_low + dx / 2 < 0) { - frac_low += dx; - y_low -= stepy; - } - while (frac_high - dx / 2 >= 0) { - frac_high -= dx; - y_high += stepy; - } - x2 += stepx; - - while (x != x2) { - if (dash_count < dash && x >= 0 && x < screen_width) { - for (int y = y_low; y != y_high; y += stepy) { - if (y >= 0 && y < screen_height) this->SetPixel(video, x, y, colour); - } - } - if (frac_low >= 0) { - y_low += stepy; - frac_low -= dx; - } - if (frac_high >= 0) { - y_high += stepy; - frac_high -= dx; - } - x += stepx; - frac_low += dy; - frac_high += dy; - if (++dash_count >= dash + gap) dash_count = 0; - } - } else { - int x_low = x; - int x_high = x; - int frac_low = dx - frac_diff / 2; - int frac_high = dx + frac_diff / 2; - - while (frac_low + dy / 2 < 0) { - frac_low += dy; - x_low -= stepx; - } - while (frac_high - dy / 2 >= 0) { - frac_high -= dy; - x_high += stepx; - } - y2 += stepy; - - while (y != y2) { - if (dash_count < dash && y >= 0 && y < screen_height) { - for (int x = x_low; x != x_high; x += stepx) { - if (x >= 0 && x < screen_width) this->SetPixel(video, x, y, colour); - } - } - if (frac_low >= 0) { - x_low += stepx; - frac_low -= dy; - } - if (frac_high >= 0) { - x_high += stepx; - frac_high -= dy; - } - y += stepy; - frac_low += dx; - frac_high += dx; - if (++dash_count >= dash + gap) dash_count = 0; - } - } -} diff --git a/src/blitter/base.hpp b/src/blitter/base.hpp index 26ed39eb6d..a7ba304a69 100644 --- a/src/blitter/base.hpp +++ b/src/blitter/base.hpp @@ -21,6 +21,7 @@ enum BlitterMode { BM_TRANSPARENT_REMAP, ///< Perform transparency colour remapping. BM_CRASH_REMAP, ///< Perform a crash remapping. BM_BLACK_REMAP, ///< Perform remapping to a completely blackened sprite + CM_BM_TINT_REMAP, ///< Perform tinting. }; /** diff --git a/src/citymania/CMakeLists.txt b/src/citymania/CMakeLists.txt index 54464a98db..362b5dc99a 100644 --- a/src/citymania/CMakeLists.txt +++ b/src/citymania/CMakeLists.txt @@ -27,6 +27,8 @@ add_files( cm_cargo_table_gui.cpp cm_client_list_gui.hpp cm_client_list_gui.cpp + cm_colour.hpp + cm_colour.cpp cm_commands.hpp cm_commands.cpp cm_commands_gui.hpp diff --git a/src/gfx.cpp b/src/gfx.cpp index 325b195a96..0ee15471e5 100644 --- a/src/gfx.cpp +++ b/src/gfx.cpp @@ -7,6 +7,7 @@ /** @file gfx.cpp Handling of drawing text and other gfx related stuff. */ +#include "blitter/base.hpp" #include "stdafx.h" #include "gfx_layout.h" #include "progress.h" @@ -978,6 +979,8 @@ static BlitterMode GetBlitterMode(PaletteID pal) case PAL_NONE: return BM_NORMAL; case PALETTE_CRASH: return BM_CRASH_REMAP; case PALETTE_ALL_BLACK: return BM_BLACK_REMAP; + case CM_PALETTE_TINT_BASE ... (CM_PALETTE_TINT_BASE + CM_PALETTE_TINT_COUNT - 1): + return CM_BM_TINT_REMAP; default: return BM_COLOUR_REMAP; } }