1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-17 12:03:07 +01:00

Create strong enum+Flagholder for G1 flags

This commit is contained in:
Gymnasiast
2025-12-27 14:56:15 +01:00
parent e6fa262b9e
commit 7236631db5
13 changed files with 62 additions and 60 deletions

View File

@@ -878,7 +878,7 @@ void OpenGLDrawingContext::DrawSprite(RenderTarget& rt, const ImageId imageId, c
if (rt.zoom_level > ZoomLevel{ 0 })
{
if (g1Element->flags & G1_FLAG_HAS_ZOOM_SPRITE)
if (g1Element->flags.has(G1Flag::hasZoomSprite))
{
RenderTarget zoomedRT;
zoomedRT.bits = rt.bits;
@@ -891,7 +891,7 @@ void OpenGLDrawingContext::DrawSprite(RenderTarget& rt, const ImageId imageId, c
DrawSprite(zoomedRT, imageId.WithIndex(imageId.GetIndex() - g1Element->zoomedOffset), x >> 1, y >> 1);
return;
}
if (g1Element->flags & G1_FLAG_NO_ZOOM_DRAW)
if (g1Element->flags.has(G1Flag::noZoomDraw))
{
return;
}

View File

@@ -155,12 +155,12 @@ namespace OpenRCT2::Scripting
obj.Set("width", g1->width);
obj.Set("height", g1->height);
obj.Set("hasTransparent", (g1->flags & G1_FLAG_HAS_TRANSPARENCY) != 0);
obj.Set("isRLE", (g1->flags & G1_FLAG_RLE_COMPRESSION) != 0);
obj.Set("isPalette", (g1->flags & G1_FLAG_PALETTE) != 0);
obj.Set("noZoom", (g1->flags & G1_FLAG_NO_ZOOM_DRAW) != 0);
obj.Set("hasTransparent", g1->flags.has(G1Flag::hasTransparency));
obj.Set("isRLE", g1->flags.has(G1Flag::hasRLECompression));
obj.Set("isPalette", g1->flags.has(G1Flag::isPalette));
obj.Set("noZoom", g1->flags.has(G1Flag::noZoomDraw));
if (g1->flags & G1_FLAG_HAS_ZOOM_SPRITE)
if (g1->flags.has(G1Flag::hasZoomSprite))
{
obj.Set("nextZoomId", id - g1->zoomedOffset);
}
@@ -173,9 +173,9 @@ namespace OpenRCT2::Scripting
static const char* GetPixelDataTypeForG1(const G1Element& g1)
{
if (g1.flags & G1_FLAG_RLE_COMPRESSION)
if (g1.flags.has(G1Flag::hasRLECompression))
return "rle";
else if (g1.flags & G1_FLAG_PALETTE)
else if (g1.flags.has(G1Flag::isPalette))
return "palette";
return "raw";
}
@@ -405,10 +405,10 @@ namespace OpenRCT2::Scripting
el.offset = newData;
el.width = pixelData.Width;
el.height = pixelData.Height;
el.flags = 0;
el.flags = {};
if (pixelData.Type == PixelDataKind::Rle)
{
el.flags |= G1_FLAG_RLE_COMPRESSION;
el.flags.set(G1Flag::hasRLECompression);
}
GfxSetG1Element(id, &el);
DrawingEngineInvalidateImage(id);
@@ -441,7 +441,7 @@ namespace OpenRCT2::Scripting
auto createNewImage = false;
auto g1 = GfxGetG1Element(id);
if (g1 == nullptr || g1->width != size.width || g1->height != size.height || (g1->flags & G1_FLAG_RLE_COMPRESSION))
if (g1 == nullptr || g1->width != size.width || g1->height != size.height || g1->flags.has(G1Flag::hasRLECompression))
{
createNewImage = true;
}
@@ -478,7 +478,7 @@ namespace OpenRCT2::Scripting
newg1.offset = rt.bits;
newg1.width = size.width;
newg1.height = size.height;
newg1.flags = 0;
newg1.flags = {};
GfxSetG1Element(id, &newg1);
}

View File

@@ -163,7 +163,7 @@ namespace OpenRCT2::Ui::Windows
g1temp.offset = _trackDesignPreviewPixels.data() + (_currentTrackPieceDirection * kTrackPreviewImageSize);
g1temp.width = 370;
g1temp.height = 217;
g1temp.flags = G1_FLAG_HAS_TRANSPARENCY;
g1temp.flags = { G1Flag::hasTransparency };
GfxSetG1Element(SPR_TEMP, &g1temp);
DrawingEngineInvalidateImage(SPR_TEMP);
GfxDrawSprite(rt, ImageId(SPR_TEMP), screenPos);

View File

@@ -511,7 +511,7 @@ namespace OpenRCT2::Ui::Windows
g1temp.offset = _trackDesignPreviewPixels.data() + (_currentTrackPieceDirection * kTrackPreviewImageSize);
g1temp.width = 370;
g1temp.height = 217;
g1temp.flags = G1_FLAG_HAS_TRANSPARENCY;
g1temp.flags = { G1Flag::hasTransparency };
GfxSetG1Element(SPR_TEMP, &g1temp);
DrawingEngineInvalidateImage(SPR_TEMP);
GfxDrawSprite(rt, ImageId(SPR_TEMP), trackPreview);

View File

@@ -45,7 +45,7 @@ namespace OpenRCT2::CommandLine::Sprite
for (uint32_t i = 0; i < numEntries; i++)
{
// RCT1 used zoomed offsets that counted from the beginning of the file, rather than from the current sprite.
if (g1Elements32[i].flags & G1_FLAG_HAS_ZOOM_SPRITE)
if (g1Elements32[i].flags.has(G1Flag::hasZoomSprite))
{
g1Elements32[i].zoomed_offset = i - g1Elements32[i].zoomed_offset;
}

View File

@@ -106,7 +106,7 @@ void FASTCALL GfxBmpSpriteToBuffer(RenderTarget& rt, const DrawSpriteArgs& args)
// Used for glass.
DrawBMPSprite<kBlendTransparent | kBlendDst>(rt, args);
}
else if (!(args.SourceImage.flags & G1_FLAG_HAS_TRANSPARENCY))
else if (!args.SourceImage.flags.has(G1Flag::hasTransparency))
{
// Copy raw bitmap data to target
DrawBMPSprite<kBlendNone>(rt, args);

View File

@@ -345,7 +345,7 @@ static void ReadAndConvertGxDat(IStream* stream, size_t count, bool is_rctc, G1E
elements[i].yOffset = src.y_offset;
elements[i].flags = src.flags;
if (src.flags & G1_FLAG_HAS_ZOOM_SPRITE)
if (src.flags.has(G1Flag::hasZoomSprite))
{
elements[i].zoomedOffset = static_cast<int32_t>(i - rctc_to_rct2_index(rctc - src.zoomed_offset));
}
@@ -650,7 +650,7 @@ bool GfxLoadCsg()
_csg.elements[i].offset += reinterpret_cast<uintptr_t>(_csg.data.get());
}
// RCT1 used zoomed offsets that counted from the beginning of the file, rather than from the current sprite.
if (_csg.elements[i].flags & G1_FLAG_HAS_ZOOM_SPRITE)
if (_csg.elements[i].flags.has(G1Flag::hasZoomSprite))
{
_csg.elements[i].zoomedOffset = i - _csg.elements[i].zoomedOffset;
}
@@ -768,7 +768,7 @@ void FASTCALL GfxDrawSpritePaletteSetSoftware(
return;
}
if (zoomLevel > ZoomLevel{ 0 } && (g1->flags & G1_FLAG_HAS_ZOOM_SPRITE))
if (zoomLevel > ZoomLevel{ 0 } && g1->flags.has(G1Flag::hasZoomSprite))
{
RenderTarget zoomedRT = rt;
zoomedRT.bits = rt.bits;
@@ -785,7 +785,7 @@ void FASTCALL GfxDrawSpritePaletteSetSoftware(
return;
}
if (zoomLevel > ZoomLevel{ 0 } && (g1->flags & G1_FLAG_NO_ZOOM_DRAW))
if (zoomLevel > ZoomLevel{ 0 } && g1->flags.has(G1Flag::noZoomDraw))
{
return;
}
@@ -820,7 +820,7 @@ void FASTCALL GfxDrawSpritePaletteSetSoftware(
const int32_t zoom_mask = zoomLevel > ZoomLevel{ 0 } ? zoomLevel.ApplyTo(0xFFFFFFFF) : 0xFFFFFFFF;
if (zoomLevel > ZoomLevel{ 0 } && g1->flags & G1_FLAG_RLE_COMPRESSION)
if (zoomLevel > ZoomLevel{ 0 } && g1->flags.has(G1Flag::hasRLECompression))
{
x -= ~zoom_mask;
y -= ~zoom_mask;
@@ -834,7 +834,7 @@ void FASTCALL GfxDrawSpritePaletteSetSoftware(
// For whatever reason the RLE version does not use
// the zoom mask on the y coordinate but does on x.
if (g1->flags & G1_FLAG_RLE_COMPRESSION)
if (g1->flags.has(G1Flag::hasRLECompression))
{
dest_start_y -= rt.WorldY();
}
@@ -862,7 +862,7 @@ void FASTCALL GfxDrawSpritePaletteSetSoftware(
}
else
{
if ((g1->flags & G1_FLAG_RLE_COMPRESSION) && zoomLevel > ZoomLevel{ 0 })
if (g1->flags.has(G1Flag::hasRLECompression) && zoomLevel > ZoomLevel{ 0 })
{
source_start_y -= dest_start_y & ~zoom_mask;
height += dest_start_y & ~zoom_mask;
@@ -908,7 +908,7 @@ void FASTCALL GfxDrawSpritePaletteSetSoftware(
}
else
{
if ((g1->flags & G1_FLAG_RLE_COMPRESSION) && zoomLevel > ZoomLevel{ 0 })
if (g1->flags.has(G1Flag::hasRLECompression) && zoomLevel > ZoomLevel{ 0 })
{
source_start_x -= dest_start_x & ~zoom_mask;
}
@@ -938,11 +938,11 @@ void FASTCALL GfxDrawSpritePaletteSetSoftware(
void FASTCALL GfxSpriteToBuffer(RenderTarget& rt, const DrawSpriteArgs& args)
{
if (args.SourceImage.flags & G1_FLAG_RLE_COMPRESSION)
if (args.SourceImage.flags.has(G1Flag::hasRLECompression))
{
GfxRleSpriteToBuffer(rt, args);
}
else if (!(args.SourceImage.flags & G1_FLAG_1))
else if (!args.SourceImage.flags.has(G1Flag::one))
{
GfxBmpSpriteToBuffer(rt, args);
}
@@ -966,7 +966,7 @@ void FASTCALL GfxDrawSpriteRawMaskedSoftware(
}
// Must have transparency in order to pass check
if (!(imgMask->flags & G1_FLAG_HAS_TRANSPARENCY) || !(imgColour->flags & G1_FLAG_HAS_TRANSPARENCY))
if (!imgMask->flags.has(G1Flag::hasTransparency) || !imgColour->flags.has(G1Flag::hasTransparency))
{
GfxDrawSpriteSoftware(rt, colourImage, scrCoords);
return;
@@ -1161,12 +1161,12 @@ bool IsCsgLoaded()
size_t G1CalculateDataSize(const G1Element* g1)
{
if (g1->flags & G1_FLAG_PALETTE)
if (g1->flags.has(G1Flag::isPalette))
{
return g1->numColours * 3;
}
if (g1->flags & G1_FLAG_RLE_COMPRESSION)
if (g1->flags.has(G1Flag::hasRLECompression))
{
if (g1->offset == nullptr)
{

View File

@@ -10,6 +10,7 @@
#pragma once
#include "../core/CallingConventions.h"
#include "../core/FlagHolder.hpp"
#include "../core/StringTypes.h"
#include "../interface/Colour.h"
#include "../interface/ZoomLevel.h"
@@ -45,23 +46,34 @@ namespace OpenRCT2::Drawing
struct IDrawingEngine;
}
enum class G1Flag : uint8_t
{
hasTransparency, // Image data contains transparent pixels (0XFF) which will not be rendered
one,
hasRLECompression, // Image data is encoded using RCT2's form of run length encoding
isPalette, // Image data is a sequence of palette entries R8G8B8
hasZoomSprite, // Use a different sprite for higher zoom levels
noZoomDraw, // Does not get drawn at higher zoom levels (only zoom 0)
};
using G1Flags = FlagHolder<uint16_t, G1Flag>;
struct G1Element
{
uint8_t* offset = nullptr; // 0x00
union
{
int16_t width = 0; // 0x04
int16_t numColours; // If G1_FLAG_PALETTE is set
int16_t numColours; // If G1Flag::isPalette is set
};
int16_t height = 0; // 0x06
union
{
int16_t xOffset = 0; // 0x08
int16_t startIndex; // If G1_FLAG_PALETTE is set
int16_t startIndex; // If G1Flag::isPalette is set
};
int16_t yOffset = 0; // 0x0A
uint16_t flags = 0; // 0x0C
int32_t zoomedOffset = 0; // 0x0E
int16_t yOffset = 0; // 0x0A
G1Flags flags = {}; // 0x0C
int32_t zoomedOffset = 0; // 0x0E
};
#pragma pack(push, 1)
@@ -87,21 +99,11 @@ struct RCTG1Element
int16_t height; // 0x06
int16_t x_offset; // 0x08
int16_t y_offset; // 0x0A
uint16_t flags; // 0x0C
G1Flags flags; // 0x0C
uint16_t zoomed_offset; // 0x0E
};
static_assert(sizeof(RCTG1Element) == 0x10);
enum
{
G1_FLAG_HAS_TRANSPARENCY = (1 << 0), // Image data contains transparent pixels (0XFF) which will not be rendered
G1_FLAG_1 = (1 << 1),
G1_FLAG_RLE_COMPRESSION = (1 << 2), // Image data is encoded using RCT2's form of run length encoding
G1_FLAG_PALETTE = (1 << 3), // Image data is a sequence of palette entries R8G8B8
G1_FLAG_HAS_ZOOM_SPRITE = (1 << 4), // Use a different sprite for higher zoom levels
G1_FLAG_NO_ZOOM_DRAW = (1 << 5), // Does not get drawn at higher zoom levels (only zoom 0)
};
using DrawBlendOp = uint8_t;
constexpr DrawBlendOp kBlendNone = 0;

View File

@@ -45,12 +45,12 @@ namespace OpenRCT2::Drawing
G1Element outElement;
outElement.width = meta.srcSize.width;
outElement.height = meta.srcSize.height;
outElement.flags = isRLE ? G1_FLAG_RLE_COMPRESSION : G1_FLAG_HAS_TRANSPARENCY;
outElement.flags = { isRLE ? G1Flag::hasRLECompression : G1Flag::hasTransparency };
outElement.xOffset = meta.offset.x;
outElement.yOffset = meta.offset.y;
outElement.zoomedOffset = meta.zoomedOffset;
if (HasFlag(meta.importFlags, ImportFlags::NoDrawOnZoom))
outElement.flags |= G1_FLAG_NO_ZOOM_DRAW;
outElement.flags.set(G1Flag::noZoomDraw);
ImageImporter::ImportResult result;
result.Element = outElement;

View File

@@ -91,7 +91,7 @@ namespace OpenRCT2::Drawing::ScrollingText
g1.offset = _drawScrollTextList[i].bitmap;
g1.xOffset = -32;
g1.yOffset = 0;
g1.flags = G1_FLAG_HAS_TRANSPARENCY;
g1.flags = { G1Flag::hasTransparency };
g1.width = 64;
g1.height = 40;
g1.offset[0] = 0xFF;

View File

@@ -1498,7 +1498,7 @@ namespace OpenRCT2
uint8_t* index = g1->offset + (y * g1->width) + x;
// Needs investigation as it has no consideration for pure BMP maps.
if (!(g1->flags & G1_FLAG_HAS_TRANSPARENCY))
if (!g1->flags.has(G1Flag::hasTransparency))
{
return false;
}
@@ -1560,16 +1560,16 @@ namespace OpenRCT2
if (rt.zoom_level > ZoomLevel{ 0 })
{
if (g1->flags & G1_FLAG_NO_ZOOM_DRAW)
if (g1->flags.has(G1Flag::noZoomDraw))
{
return false;
}
while (g1->flags & G1_FLAG_HAS_ZOOM_SPRITE && zoomLevel > ZoomLevel{ 0 })
while (g1->flags.has(G1Flag::hasZoomSprite) && zoomLevel > ZoomLevel{ 0 })
{
imageId = imageId.WithIndex(imageId.GetIndex() - g1->zoomedOffset);
g1 = GfxGetG1Element(imageId);
if (g1 == nullptr || g1->flags & G1_FLAG_NO_ZOOM_DRAW)
if (g1 == nullptr || g1->flags.has(G1Flag::noZoomDraw))
{
return false;
}
@@ -1591,12 +1591,12 @@ namespace OpenRCT2
return false;
}
if (g1->flags & G1_FLAG_RLE_COMPRESSION)
if (g1->flags.has(G1Flag::hasRLECompression))
{
return IsPixelPresentRLE(g1->offset, interactionPoint.x, interactionPoint.y);
}
if (!(g1->flags & G1_FLAG_1))
if (!g1->flags.has(G1Flag::one))
{
return IsPixelPresentBMP(imageType, g1, interactionPoint.x, interactionPoint.y, paletteMap);
}

View File

@@ -51,7 +51,7 @@ namespace OpenRCT2
g1 = orig;
g1.offset = new uint8_t[length];
std::memcpy(g1.offset, orig.offset, length);
g1.flags &= ~G1_FLAG_HAS_ZOOM_SPRITE;
g1.flags.unset(G1Flag::hasZoomSprite);
}
RequiredImage(uint32_t idx, std::function<const G1Element*(uint32_t)> getter)
@@ -63,14 +63,14 @@ namespace OpenRCT2
g1 = *orig;
g1.offset = new uint8_t[length];
std::memcpy(g1.offset, orig->offset, length);
if ((g1.flags & G1_FLAG_HAS_ZOOM_SPRITE) && g1.zoomedOffset != 0)
if (g1.flags.has(G1Flag::hasZoomSprite) && g1.zoomedOffset != 0)
{
// Fetch image for next zoom level
next_zoom = std::make_unique<RequiredImage>(static_cast<uint32_t>(idx - g1.zoomedOffset), getter);
if (!next_zoom->HasData())
{
next_zoom = nullptr;
g1.flags &= ~G1_FLAG_HAS_ZOOM_SPRITE;
g1.flags.unset(G1Flag::hasZoomSprite);
}
}
}
@@ -471,7 +471,7 @@ namespace OpenRCT2
g1Element.height = stream->ReadValue<int16_t>();
g1Element.xOffset = stream->ReadValue<int16_t>();
g1Element.yOffset = stream->ReadValue<int16_t>();
g1Element.flags = stream->ReadValue<uint16_t>();
g1Element.flags = stream->ReadValue<G1Flags>();
g1Element.zoomedOffset = stream->ReadValue<uint16_t>();
newEntries.push_back(std::move(g1Element));

View File

@@ -125,7 +125,7 @@ namespace OpenRCT2
g1.offset = data.get();
g1.numColours = static_cast<int16_t>(numColours);
g1.startIndex = Json::GetNumber<int16_t>(jPalette["index"]);
g1.flags = G1_FLAG_PALETTE;
g1.flags = { G1Flag::isPalette };
auto& imageTable = GetImageTable();
imageTable.AddImage(&g1);