diff --git a/Runtime/Graphics/CTexture.hpp b/Runtime/Graphics/CTexture.hpp index 972844bfd..662463c3d 100644 --- a/Runtime/Graphics/CTexture.hpp +++ b/Runtime/Graphics/CTexture.hpp @@ -34,16 +34,6 @@ public: enum class EBlackKey { Zero, One }; - enum class EFontType { - None = -1, - OneLayer = 0, /* Fill bit0 */ - OneLayerOutline = 1, /* Fill bit0, Outline bit1 */ - FourLayers = 2, - TwoLayersOutlines = 3, /* Fill bit0/2, Outline bit1/3 */ - TwoLayers = 4, /* Fill bit0/1 and copied to bit2/3 */ - TwoLayersOutlines2 = 8 /* Fill bit2/3, Outline bit0/1 */ - }; - private: static bool sMangleMips; static u32 sCurrentFrameCount; diff --git a/Runtime/GuiSys/CFontRenderState.cpp b/Runtime/GuiSys/CFontRenderState.cpp index ebe70893c..efb410df8 100644 --- a/Runtime/GuiSys/CFontRenderState.cpp +++ b/Runtime/GuiSys/CFontRenderState.cpp @@ -43,41 +43,25 @@ void CFontRenderState::RefreshPalette() { RefreshColor(EColorType::Background); } -void CFontRenderState::RefreshColor(EColorType tp) { - switch (tp) { - case EColorType::Main: - if (!x48_font) - return; - switch (x48_font->GetMode()) { - case EColorType::Main: - case EColorType::Outline: - if (!x64_colorOverrides[0]) { - x0_drawStrOpts.x4_colors[0] = ConvertToTextureSpace(x54_colors[0]); - } - break; - default: - break; +void CFontRenderState::RefreshColor(EColorType color) { + if (color == EColorType::Geometry && !x64_colorOverrides[2]) { + x0_drawStrOpts.x4_colors[2] = ConvertToTextureSpace(x54_colors[2]); + } else if (color == EColorType::Main && IsFinishedLoading() && !x48_font.IsNull()) { + const auto mode = x48_font->GetMode(); + if (mode == EFontMode::OneLayerOutline && !x64_colorOverrides[0]) { + x0_drawStrOpts.x4_colors[0] = ConvertToTextureSpace(x54_colors[0]); + } else if (mode == EFontMode::OneLayer && !x64_colorOverrides[0]) { + x0_drawStrOpts.x4_colors[0] = ConvertToTextureSpace(x54_colors[0]); } - break; - case EColorType::Outline: - if (!x48_font) - return; - if (x64_colorOverrides[1]) - return; - if (x48_font->GetMode() == EColorType::Outline) + } else if (color == EColorType::Outline && IsFinishedLoading() && !x48_font.IsNull() && !x64_colorOverrides[1]) { + if (x48_font->GetMode() == EFontMode::OneLayerOutline) { x0_drawStrOpts.x4_colors[1] = ConvertToTextureSpace(x54_colors[1]); - break; - case EColorType::Geometry: - if (!x64_colorOverrides[2]) - x0_drawStrOpts.x4_colors[2] = ConvertToTextureSpace(x54_colors[2]); - break; - case EColorType::Foreground: + } + } else if (color == EColorType::Background) { + RefreshColor(EColorType::Outline); + } else if (color == EColorType::Foreground) { RefreshColor(EColorType::Main); RefreshColor(EColorType::Geometry); - break; - case EColorType::Background: - RefreshColor(EColorType::Outline); - break; } } diff --git a/Runtime/GuiSys/CGuiTextSupport.cpp b/Runtime/GuiSys/CGuiTextSupport.cpp index 3feda7dab..be2639630 100644 --- a/Runtime/GuiSys/CGuiTextSupport.cpp +++ b/Runtime/GuiSys/CGuiTextSupport.cpp @@ -175,6 +175,8 @@ void CGuiTextSupport::CheckAndRebuildTextBuffer() { x14_props.x8_vertJustification); g_TextExecuteBuf->AddColor(EColorType::Main, x24_fontColor); g_TextExecuteBuf->AddColor(EColorType::Outline, x28_outlineColor); + g_TextExecuteBuf->AddCharacterExtraSpace(x34_characterExtraSpace); + g_TextExecuteBuf->AddLineExtraSpace(x38_lineExtraSpace); std::u16string initStr; if (x5c_fontId.IsValid()) diff --git a/Runtime/GuiSys/CGuiTextSupport.hpp b/Runtime/GuiSys/CGuiTextSupport.hpp index 34254908a..0c3fcbe99 100644 --- a/Runtime/GuiSys/CGuiTextSupport.hpp +++ b/Runtime/GuiSys/CGuiTextSupport.hpp @@ -78,8 +78,9 @@ class CGuiTextSupport { zeus::CColor x28_outlineColor; zeus::CColor x2c_geometryColor; bool x30_imageBaseline = false; - s32 x30_; // new in PAL/JP - s32 x34_; // "" + s32 x30_; // new in PAL/JP + s32 x34_characterExtraSpace; // "" + s32 x38_lineExtraSpace; // "" s32 x34_extentX; s32 x38_extentY; float x3c_curTime = 0.f; diff --git a/Runtime/GuiSys/CInstruction.cpp b/Runtime/GuiSys/CInstruction.cpp index f134ce695..70e2fd540 100644 --- a/Runtime/GuiSys/CInstruction.cpp +++ b/Runtime/GuiSys/CInstruction.cpp @@ -49,12 +49,22 @@ void CLineExtraSpaceInstruction::PageInvoke(CFontRenderState& state, CTextRender Invoke(state, buf); } -void CLineInstruction::TestLargestFont(s32 w, s32 h, s32 b) { - if (!x18_largestMonoBaseline) - x18_largestMonoBaseline = b; +void CCharacterExtraSpaceInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const { + state.x48_extraCharacterSpace = x4_extraSpace; +} - if (x14_largestMonoWidth < w) +void CCharacterExtraSpaceInstruction::PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const { + Invoke(state, buf); +} + +void CLineInstruction::TestLargestFont(s32 w, s32 h, s32 b) { + if (!x18_largestMonoBaseline) { + x18_largestMonoBaseline = b; + } + + if (x14_largestMonoWidth < w) { x14_largestMonoWidth = w; + } if (x10_largestMonoHeight < h) { x10_largestMonoHeight = h; diff --git a/Runtime/GuiSys/CInstruction.hpp b/Runtime/GuiSys/CInstruction.hpp index 175e8c994..ba1594c13 100644 --- a/Runtime/GuiSys/CInstruction.hpp +++ b/Runtime/GuiSys/CInstruction.hpp @@ -60,6 +60,13 @@ public: void PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const override; }; +class CCharacterExtraSpaceInstruction : public CInstruction { + s32 x4_extraSpace; +public: + explicit CCharacterExtraSpaceInstruction(s32 extraSpace) : x4_extraSpace(extraSpace) {} + void Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const override; + void PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const override; +}; class CLineInstruction : public CInstruction { friend class CTextExecuteBuffer; friend class CTextInstruction; diff --git a/Runtime/GuiSys/CRasterFont.cpp b/Runtime/GuiSys/CRasterFont.cpp index a9902fa38..fb59a898d 100644 --- a/Runtime/GuiSys/CRasterFont.cpp +++ b/Runtime/GuiSys/CRasterFont.cpp @@ -36,7 +36,7 @@ CRasterFont::CRasterFont(metaforce::CInputStream& in, metaforce::IObjectStore& s u32 txtrId = (version == 5 ? in.ReadLongLong() : in.ReadLong()); x30_fontInfo = CFontInfo(tmp1, tmp2, tmp3, tmp4, name.c_str()); x80_texture = store.GetObj({FOURCC('TXTR'), txtrId}); - x2c_mode = CTexture::EFontType(in.ReadLong()); + x2c_mode = EFontMode(in.ReadLong()); u32 glyphCount = in.ReadLong(); xc_glyphs.reserve(glyphCount); @@ -160,7 +160,7 @@ void CRasterFont::DrawString(const CDrawStringOptions& opts, int x, int y, int& data[2] = bswap16(opts.x4_colors[1].toRGB5A3()); data[3] = bswap16(zeus::CColor(0.f, 0.f, 0.f, 0.f).toRGB5A3()); pal.UnLock(); - renderBuf->AddPaletteChange(pal); + renderBuf->AddPaletteChange(pal, GetMode()); } SinglePassDrawString(opts, x, y, xout, yout, renderBuf, str, len); diff --git a/Runtime/GuiSys/CRasterFont.hpp b/Runtime/GuiSys/CRasterFont.hpp index 990dcd5e5..c4f2d1d09 100644 --- a/Runtime/GuiSys/CRasterFont.hpp +++ b/Runtime/GuiSys/CRasterFont.hpp @@ -16,7 +16,23 @@ class CDrawStringOptions; class CTextRenderBuffer; class IObjectStore; -enum class EColorType { Main, Outline, Geometry, Foreground, Background }; +enum class EFontMode { + None = -1, + OneLayer = 0, /* Fill bit0 */ + OneLayerOutline = 1, /* Fill bit0, Outline bit1 */ + FourLayers = 2, + TwoLayersOutlines = 3, /* Fill bit0/2, Outline bit1/3 */ + TwoLayers = 4, /* Fill bit0/1 and copied to bit2/3 */ + TwoLayersOutlines2 = 8 /* Fill bit2/3, Outline bit0/1 */ +}; + +enum class EColorType { + Main, + Outline, + Geometry, + Foreground, + Background, +}; /* NOTE: Is this a good place for CGlyph and CKernPair? */ class CGlyph { @@ -100,7 +116,7 @@ class CRasterFont { s32 x8_monoHeight = 16; std::vector> xc_glyphs; std::vector x1c_kerning; - CTexture::EFontType x2c_mode = CTexture::EFontType::OneLayer; + EFontMode x2c_mode = EFontMode::OneLayer; CFontInfo x30_fontInfo; TLockedToken x80_texture; s32 x8c_baseline; @@ -113,20 +129,8 @@ public: s32 GetMonoWidth() const { return x4_monoWidth; } s32 GetMonoHeight() const { return x8_monoHeight; } - EColorType GetMode() const { - switch (x2c_mode) { - case CTexture::EFontType::OneLayer: - case CTexture::EFontType::TwoLayers: - case CTexture::EFontType::FourLayers: - return EColorType::Main; - case CTexture::EFontType::OneLayerOutline: - case CTexture::EFontType::TwoLayersOutlines: - case CTexture::EFontType::TwoLayersOutlines2: - return EColorType::Outline; - default: - return EColorType::Main; - } - } + EFontMode GetMode() const { return x2c_mode; } + s32 GetLineMargin() const { return x90_lineMargin; } s32 GetCarriageAdvance() const { return GetLineMargin() + GetMonoHeight(); } diff --git a/Runtime/GuiSys/CSaveableState.hpp b/Runtime/GuiSys/CSaveableState.hpp index a7eb1c130..1f2a6ab91 100644 --- a/Runtime/GuiSys/CSaveableState.hpp +++ b/Runtime/GuiSys/CSaveableState.hpp @@ -16,6 +16,7 @@ class CSaveableState { friend class CFontInstruction; friend class CGuiTextSupport; friend class CLineExtraSpaceInstruction; + friend class CCharacterExtraSpaceInstruction; friend class CLineSpacingInstruction; friend class CRemoveColorOverrideInstruction; friend class CTextExecuteBuffer; @@ -24,6 +25,7 @@ class CSaveableState { protected: CDrawStringOptions x0_drawStrOpts; + s32 x48_extraCharacterSpace; TLockedToken x48_font; std::vector x54_colors; std::vector x64_colorOverrides; diff --git a/Runtime/GuiSys/CTextExecuteBuffer.cpp b/Runtime/GuiSys/CTextExecuteBuffer.cpp index 3e2ebf0ee..ca61097d7 100644 --- a/Runtime/GuiSys/CTextExecuteBuffer.cpp +++ b/Runtime/GuiSys/CTextExecuteBuffer.cpp @@ -314,6 +314,11 @@ void CTextExecuteBuffer::AddLineExtraSpace(s32 space) { x18_textState.x78_extraLineSpace = space; } +void CTextExecuteBuffer::AddCharacterExtraSpace(s32 space) { + x0_instList.emplace(x0_instList.cend(), std::make_shared(space)); + x18_textState.x48_extraCharacterSpace = space; +} + void CTextExecuteBuffer::AddLineSpacing(float spacing) { x0_instList.emplace(x0_instList.cend(), std::make_shared(spacing)); x18_textState.x74_lineSpacing = spacing; diff --git a/Runtime/GuiSys/CTextExecuteBuffer.hpp b/Runtime/GuiSys/CTextExecuteBuffer.hpp index c27c2e66e..1ef9315c5 100644 --- a/Runtime/GuiSys/CTextExecuteBuffer.hpp +++ b/Runtime/GuiSys/CTextExecuteBuffer.hpp @@ -58,6 +58,7 @@ public: void AddVerticalJustification(EVerticalJustification vjust); void AddJustification(EJustification just); void AddLineExtraSpace(s32 space); + void AddCharacterExtraSpace(s32 space); void AddLineSpacing(float spacing); void AddRemoveColorOverride(int idx); void AddColorOverride(int idx, const CTextColor& color); diff --git a/Runtime/GuiSys/CTextParser.cpp b/Runtime/GuiSys/CTextParser.cpp index 39d0e034b..cfec8d131 100644 --- a/Runtime/GuiSys/CTextParser.cpp +++ b/Runtime/GuiSys/CTextParser.cpp @@ -117,6 +117,8 @@ void CTextParser::ParseTag(CTextExecuteBuffer& out, const char16_t* str, int len out.AddLineSpacing(ParseInt(str + 13, len - 13, true) / 100.0f); } else if (BeginsWith(str, len, u"line-extra-space=")) { out.AddLineExtraSpace(ParseInt(str + 17, len - 17, true)); + } else if (BeginsWith(str, len, u"character-extra-space")) { + out.AddCharacterExtraSpace(ParseInt(str + 22, len - 22, true)); } else if (BeginsWith(str, len, u"just=")) { if (Equals(str + 5, len - 5, u"left")) out.AddJustification(EJustification::Left); diff --git a/Runtime/GuiSys/CTextRenderBuffer.cpp b/Runtime/GuiSys/CTextRenderBuffer.cpp index 47a83970d..842e0a458 100644 --- a/Runtime/GuiSys/CTextRenderBuffer.cpp +++ b/Runtime/GuiSys/CTextRenderBuffer.cpp @@ -78,7 +78,7 @@ void CTextRenderBuffer::SetMode(EMode mode) { x0_mode = mode; } int CTextRenderBuffer::GetMatchingPaletteIndex(const CGraphicsPalette& palette) { for (int i = 0; i < x50_palettes.size(); ++i) { - if (memcmp(x50_palettes[i]->GetPaletteData(), palette.GetPaletteData(), 8) == 0) { + if (memcmp(x50_palettes[i].x4_colorPal.data(), palette.GetPaletteData(), 8) == 0) { return i; } } @@ -86,14 +86,17 @@ int CTextRenderBuffer::GetMatchingPaletteIndex(const CGraphicsPalette& palette) return -1; } -CGraphicsPalette* CTextRenderBuffer::GetNextAvailablePalette() { +CTextRenderBuffer::SFontPalette* CTextRenderBuffer::GetNextAvailablePalette() { if (x254_nextPalette < 64) { - x50_palettes.push_back(std::make_unique(EPaletteFormat::RGB5A3, 4)); + x50_palettes.emplace_back(EFontMode::None, std::make_unique(EPaletteFormat::RGB5A3, 16), + std::make_unique(EPaletteFormat::RGB5A3, 16), + std::make_unique(EPaletteFormat::RGB5A3, 16), + std::make_unique(EPaletteFormat::RGB5A3, 16)); } else { x254_nextPalette = 0; } ++x254_nextPalette; - return x50_palettes[x254_nextPalette - 1].get(); + return &x50_palettes[x254_nextPalette - 1]; } u32 CTextRenderBuffer::GetCurLen() { @@ -102,6 +105,12 @@ u32 CTextRenderBuffer::GetCurLen() { } void CTextRenderBuffer::Render(const zeus::CColor& color, float time) { + constexpr std::array skVtxDesc{ + GX::VtxDescList{GX::VA_POS, GX::DIRECT}, + GX::VtxDescList{GX::VA_TEX0, GX::DIRECT}, + GX::VtxDescList{}, + }; + x4c_activeFont = -1; x4d_activePalette = -1; CMemoryInStream in(x34_bytecode.data(), x44_blobSize); @@ -117,20 +126,41 @@ void CTextRenderBuffer::Render(const zeus::CColor& color, float time) { x4e_queuedFont = -1; } } - if (x4f_queuedPalette != -1) { - x50_palettes[x4f_queuedPalette]->Load(); - x4f_queuedPalette = -1; - } - s16 offX = in.ReadShort(); s16 offY = in.ReadShort(); char16_t chr = in.ReadShort(); zeus::CColor chrColor(static_cast(in.ReadLong())); if (x4c_activeFont != -1) { auto font = x4_fonts[x4c_activeFont]; - if (font && font->GetGlyph(chr) != nullptr) { + if (font) { const auto* glyph = font->GetGlyph(chr); + if (glyph == nullptr) { + continue; + } + const auto layer = glyph->GetLayer(); + s32 paletteIdx = x4f_queuedPalette; + if (paletteIdx != -1 || layer != -1) { + if (paletteIdx == -1) { + paletteIdx = x4d_activePalette; + } + if (paletteIdx != -1) { + if (layer == 0) { + x50_palettes[paletteIdx].xc_layer1Pal->Load(); + } else if (glyph->GetLayer() == 1) { + x50_palettes[paletteIdx].x14_layer2Pal->Load(); + } else if (glyph->GetLayer() == 2) { + x50_palettes[paletteIdx].x1c_layer3Pal->Load(); + } else if (glyph->GetLayer() == 3) { + x50_palettes[paletteIdx].x24_layer4Pal->Load(); + } + x4f_queuedPalette = -1; + } + } + CGX::SetTevKColor(GX::KCOLOR0, chrColor * color); + CGX::SetVtxDescv(skVtxDesc.data()); + CGX::SetNumChans(0); + CGX::SetNumTexGens(1); CGX::Begin(GX::TRIANGLESTRIP, GX::VTXFMT0, 4); { GXPosition3f32(offX, 0.f, offY); @@ -164,11 +194,6 @@ void CTextRenderBuffer::Render(const zeus::CColor& color, float time) { CGX::SetTevColorIn(GX::TEVSTAGE0, GX::CC_ZERO, GX::CC_TEXC, GX::CC_KONST, GX::CC_ZERO); CGX::SetTevAlphaIn(GX::TEVSTAGE0, GX::CA_ZERO, GX::CA_TEXA, GX::CA_KONST, GX::CA_ZERO); CGX::SetStandardTevColorAlphaOp(GX::TEVSTAGE0); - constexpr std::array skVtxDesc{ - GX::VtxDescList{GX::VA_POS, GX::DIRECT}, - GX::VtxDescList{GX::VA_TEX0, GX::DIRECT}, - GX::VtxDescList{}, - }; CGX::SetVtxDescv(skVtxDesc.data()); CGX::SetNumChans(0); CGX::SetNumTexGens(1); @@ -197,24 +222,57 @@ void CTextRenderBuffer::Render(const zeus::CColor& color, float time) { } } -void CTextRenderBuffer::AddPaletteChange(const CGraphicsPalette& palette) { - if (x0_mode == EMode::BufferFill) { - { - u8* buf = GetOutStream(); - CMemoryStreamOut out(buf, GetCurLen()); - s32 paletteIndex = GetMatchingPaletteIndex(palette); - if (paletteIndex == -1) { - GetNextAvailablePalette(); - paletteIndex = x254_nextPalette - 1; - CGraphicsPalette* destPalette = x50_palettes[x254_nextPalette - 1].get(); - u16* data = destPalette->Lock(); - memcpy(data, palette.GetPaletteData(), 8); - destPalette->UnLock(); +void SetFontPalette(EFontMode mode, u32 layer, CGraphicsPalette& layerPal, const CGraphicsPalette& colorPal) { + u16* layerLut = layerPal.Lock(); + const u16* colorLut = colorPal.GetPaletteData(); + if (mode == EFontMode::OneLayer || mode == EFontMode::OneLayerOutline) { + memcpy(layerLut, colorLut, 8); + } else { + u32 layerOffset = layer * 2; + for (u32 i = 0; i < 16; ++i) { + if (mode == EFontMode::TwoLayersOutlines) { + u32 uVar1 = (i & 2) << layerOffset; + if ((i & 1) << layerOffset == 0) { + if ((-uVar1 | uVar1) < 0) { + *layerLut = colorLut[2]; + } else { + *layerLut = colorLut[0]; + } + } else { + *layerLut = colorLut[1]; + } + } else if (mode == EFontMode::FourLayers) { + if ((i >> (layer & 0x3f) & 1) == 0) { + *layerLut = colorLut[0]; + } else { + *layerLut = colorLut[1]; + } } - out.WriteUint8(static_cast(Command::PaletteChange)); - out.WriteUint8(paletteIndex); - x48_curBytecodeOffset += out.GetNumWrites(); + ++layerLut; } + } + + layerPal.UnLock(); +} + +void CTextRenderBuffer::AddPaletteChange(const CGraphicsPalette& palette, EFontMode mode) { + if (x0_mode == EMode::BufferFill) { + CMemoryStreamOut out(GetOutStream(), GetCurLen(), CMemoryStreamOut::EOwnerShip::NotOwned, 64); + s32 paletteIndex = GetMatchingPaletteIndex(palette); + if (paletteIndex == -1) { + GetNextAvailablePalette(); + paletteIndex = x254_nextPalette - 1; + x50_palettes[paletteIndex].x0_mode = mode; + auto& destPalette = x50_palettes[x254_nextPalette - 1]; + memcpy(destPalette.x4_colorPal.data(), palette.GetPaletteData(), 8); + SetFontPalette(mode, 0, *destPalette.xc_layer1Pal, palette); + SetFontPalette(mode, 1, *destPalette.x14_layer2Pal, palette); + SetFontPalette(mode, 2, *destPalette.x1c_layer3Pal, palette); + SetFontPalette(mode, 3, *destPalette.x24_layer4Pal, palette); + } + out.WriteUint8(static_cast(Command::PaletteChange)); + out.WriteUint8(paletteIndex); + x48_curBytecodeOffset += out.GetNumWrites(); } else { x44_blobSize += 2; } @@ -245,7 +303,7 @@ void CTextRenderBuffer::AddImage(const zeus::CVector2i& offset, const CFontImage void CTextRenderBuffer::AddCharacter(const zeus::CVector2i& offset, char16_t ch, const CTextColor& color) { if (x0_mode == EMode::BufferFill) { - CMemoryStreamOut out(GetOutStream(), GetCurLen()); + CMemoryStreamOut out(GetOutStream(), GetCurLen(), CMemoryStreamOut::EOwnerShip::NotOwned, 64); x24_primOffsets.reserve(x24_primOffsets.size() + 1); u32 primCap = x24_primOffsets.capacity(); if (x24_primOffsets.capacity() <= x24_primOffsets.size()) { @@ -265,7 +323,7 @@ void CTextRenderBuffer::AddCharacter(const zeus::CVector2i& offset, char16_t ch, void CTextRenderBuffer::AddFontChange(const TToken& font) { if (x0_mode == EMode::BufferFill) { - CMemoryStreamOut out(GetOutStream(), GetCurLen()); + CMemoryStreamOut out(GetOutStream(), GetCurLen(), CMemoryStreamOut::EOwnerShip::NotOwned, 64); u32 fontCount = x4_fonts.size(); bool found = false; u8 fontIndex = 0; diff --git a/Runtime/GuiSys/CTextRenderBuffer.hpp b/Runtime/GuiSys/CTextRenderBuffer.hpp index d2f08d2c1..245765225 100644 --- a/Runtime/GuiSys/CTextRenderBuffer.hpp +++ b/Runtime/GuiSys/CTextRenderBuffer.hpp @@ -5,9 +5,9 @@ #include "Runtime/CToken.hpp" #include "Runtime/RetroTypes.hpp" -#include "Runtime/Graphics/Shaders/CTextSupportShader.hpp" #include "Runtime/GuiSys/CFontImageDef.hpp" #include "Runtime/GuiSys/CGuiWidget.hpp" +#include "Runtime/GuiSys/CRasterFont.hpp" #include #include @@ -15,9 +15,7 @@ #include namespace metaforce { -class CGlyph; class CGraphicsPalette; -class CRasterFont; class CTextExecuteBuffer; using CTextColor = zeus::CColor; @@ -38,6 +36,23 @@ public: }; enum class EMode { AllocTally, BufferFill }; + struct SFontPalette { + EFontMode x0_mode; + std::array x4_colorPal; + std::unique_ptr xc_layer1Pal; + std::unique_ptr x14_layer2Pal; + std::unique_ptr x1c_layer3Pal; + std::unique_ptr x24_layer4Pal; + + SFontPalette(EFontMode mode, std::unique_ptr&& pal1, std::unique_ptr&& pal2, + std::unique_ptr&& pal3, std::unique_ptr&& pal4) + : x0_mode(mode) + , xc_layer1Pal(std::move(pal1)) + , x14_layer2Pal(std::move(pal2)) + , x1c_layer3Pal(std::move(pal3)) + , x24_layer4Pal(std::move(pal4)) {} + }; + private: EMode x0_mode; std::vector> x4_fonts; @@ -50,7 +65,7 @@ private: s8 x4d_activePalette = -1; s8 x4e_queuedFont = -1; s8 x4f_queuedPalette = -1; - rstl::reserved_vector, 64> x50_palettes; + rstl::reserved_vector x50_palettes; s32 x254_nextPalette = 0; public: @@ -67,8 +82,8 @@ public: [[nodiscard]] u32 GetCurLen(); void VerifyBuffer(); int GetMatchingPaletteIndex(const CGraphicsPalette& palette); - [[nodiscard]] CGraphicsPalette* GetNextAvailablePalette(); - void AddPaletteChange(const CGraphicsPalette& palette); + [[nodiscard]] SFontPalette* GetNextAvailablePalette(); + void AddPaletteChange(const CGraphicsPalette& palette, EFontMode mode); void SetMode(EMode mode); void Render(const CTextColor& col, float time); void AddImage(const zeus::CVector2i& offset, const CFontImageDef& image);