From 0ca27863020d5849d75ce1f2df66c664a73c5c71 Mon Sep 17 00:00:00 2001 From: Phillip Stephens Date: Fri, 13 May 2022 23:47:29 -0700 Subject: [PATCH] Initial CTextRenderBuffer rewrite --- Runtime/CToken.hpp | 1 + Runtime/Graphics/CCubeRenderer.cpp | 56 +-- Runtime/Graphics/CGraphicsPalette.cpp | 2 - Runtime/Graphics/CGraphicsPalette.hpp | 4 +- Runtime/GuiSys/CGuiTextSupport.cpp | 123 ++++--- Runtime/GuiSys/CRasterFont.cpp | 43 ++- Runtime/GuiSys/CRasterFont.hpp | 2 + Runtime/GuiSys/CTextExecuteBuffer.cpp | 6 +- Runtime/GuiSys/CTextRenderBuffer.cpp | 468 +++++++++++--------------- Runtime/GuiSys/CTextRenderBuffer.hpp | 31 +- Runtime/Streams/CMemoryInStream.hpp | 2 +- Runtime/Streams/CMemoryStreamOut.hpp | 2 +- Runtime/Streams/COutputStream.hpp | 1 + extern/zeus | 2 +- 14 files changed, 360 insertions(+), 383 deletions(-) diff --git a/Runtime/CToken.hpp b/Runtime/CToken.hpp index e0dca4519..0ddd01a83 100644 --- a/Runtime/CToken.hpp +++ b/Runtime/CToken.hpp @@ -91,6 +91,7 @@ public: CToken(IObj* obj); CToken(std::unique_ptr&& obj); const SObjectTag* GetObjectTag() const; + const CObjectReference* GetObjectReference() const { return x0_objRef; } ~CToken(); }; diff --git a/Runtime/Graphics/CCubeRenderer.cpp b/Runtime/Graphics/CCubeRenderer.cpp index 258e97110..9c43b673e 100644 --- a/Runtime/Graphics/CCubeRenderer.cpp +++ b/Runtime/Graphics/CCubeRenderer.cpp @@ -19,8 +19,11 @@ namespace metaforce { static logvisor::Module Log("CCubeRenderer"); +/* TODO: This is to fix some areas exceeding the max drawable count, the proper number is 128 drawables per bucket */ +// using BucketHolderType = rstl::reserved_vector; +using BucketHolderType = rstl::reserved_vector; static rstl::reserved_vector sDataHolder; -static rstl::reserved_vector, 50> sBucketsHolder; +static rstl::reserved_vector sBucketsHolder; static rstl::reserved_vector sPlaneObjectDataHolder; static rstl::reserved_vector sPlaneObjectBucketHolder; @@ -29,11 +32,11 @@ class Buckets { static inline rstl::reserved_vector sBucketIndex; static inline rstl::reserved_vector* sData = nullptr; - static inline rstl::reserved_vector, 50>* sBuckets = nullptr; + static inline rstl::reserved_vector* sBuckets = nullptr; static inline rstl::reserved_vector* sPlaneObjectData = nullptr; static inline rstl::reserved_vector* sPlaneObjectBucket = nullptr; static constexpr std::array skWorstMinMaxDistance{99999.0f, -99999.0f}; - static inline std::array sMinMaxDistance{0.0f, 0.0f}; + static inline std::array sMinMaxDistance{99999.0f, -99999.0f}; public: static void Clear(); @@ -51,7 +54,7 @@ void Buckets::Clear() { sBucketIndex.clear(); sPlaneObjectData->clear(); sPlaneObjectBucket->clear(); - for (rstl::reserved_vector& bucket : *sBuckets) { + for (BucketHolderType& bucket : *sBuckets) { bucket.clear(); } sMinMaxDistance = skWorstMinMaxDistance; @@ -60,12 +63,14 @@ void Buckets::Clear() { void Buckets::Sort() { float delta = std::max(1.f, sMinMaxDistance[1] - sMinMaxDistance[0]); float pitch = 49.f / delta; - for (auto it = sPlaneObjectData->begin(); it != sPlaneObjectData->end(); ++it) - if (sPlaneObjectBucket->size() != sPlaneObjectBucket->capacity()) + for (auto it = sPlaneObjectData->begin(); it != sPlaneObjectData->end(); ++it) { + if (sPlaneObjectBucket->size() != sPlaneObjectBucket->capacity()) { sPlaneObjectBucket->push_back(s16(it - sPlaneObjectData->begin())); + } + } u32 precision = 50; - if (sPlaneObjectBucket->size()) { + if (!sPlaneObjectBucket->empty()) { std::sort(sPlaneObjectBucket->begin(), sPlaneObjectBucket->end(), [](u16 a, u16 b) { return (*sPlaneObjectData)[a].GetDistance() < (*sPlaneObjectData)[b].GetDistance(); }); precision = 50 / u32(sPlaneObjectBucket->size() + 1); @@ -80,7 +85,7 @@ void Buckets::Sort() { } for (CDrawable& drawable : *sData) { - s32 slot; + s32 slot = -1; float relDist = drawable.GetDistance() - sMinMaxDistance[0]; if (sPlaneObjectBucket->empty()) { slot = zeus::clamp(1, s32(relDist * pitch), 49); @@ -88,7 +93,8 @@ void Buckets::Sort() { slot = zeus::clamp(0, s32(relDist * pitch), s32(precision) - 2); for (u16 idx : *sPlaneObjectBucket) { CDrawablePlaneObject& planeObj = (*sPlaneObjectData)[idx]; - bool partial, full; + bool partial = false; + bool full = false; if (planeObj.x3c_25_zOnly) { partial = drawable.GetBounds().max.z() > planeObj.GetPlane().d(); full = drawable.GetBounds().min.z() > planeObj.GetPlane().d(); @@ -98,22 +104,26 @@ void Buckets::Sort() { full = planeObj.GetPlane().pointToPlaneDist( drawable.GetBounds().furthestPointAlongVector(planeObj.GetPlane().normal())) > 0.f; } - bool cont; - if (drawable.GetType() == EDrawableType::Particle) + bool cont = false; + if (drawable.GetType() == EDrawableType::Particle) { cont = planeObj.x3c_24_invertTest ? !partial : full; - else + } else { cont = planeObj.x3c_24_invertTest ? (!partial || !full) : (partial || full); - if (!cont) + } + if (!cont) { break; - slot += precision; + } + slot += s32(precision); } } - if (slot == -1) + if (slot == -1) { slot = 49; - rstl::reserved_vector& bucket = (*sBuckets)[slot]; - if (bucket.size() < bucket.capacity()) + } + BucketHolderType& bucket = (*sBuckets)[slot]; + if (bucket.size() < bucket.capacity()) { bucket.push_back(&drawable); + } // else // Log.report(logvisor::Fatal, FMT_STRING("Full bucket!!!")); } @@ -122,7 +132,7 @@ void Buckets::Sort() { for (auto it = sBuckets->rbegin(); it != sBuckets->rend(); ++it) { --bucketIdx; sBucketIndex.push_back(bucketIdx); - rstl::reserved_vector& bucket = *it; + BucketHolderType& bucket = *it; if (bucket.size()) { std::sort(bucket.begin(), bucket.end(), [](CDrawable* a, CDrawable* b) { if (a->GetDistance() == b->GetDistance()) @@ -134,7 +144,7 @@ void Buckets::Sort() { for (auto it = sPlaneObjectBucket->rbegin(); it != sPlaneObjectBucket->rend(); ++it) { CDrawablePlaneObject& planeObj = (*sPlaneObjectData)[*it]; - rstl::reserved_vector& bucket = (*sBuckets)[planeObj.x24_targetBucket]; + BucketHolderType& bucket = (*sBuckets)[planeObj.x24_targetBucket]; bucket.push_back(&planeObj); } } @@ -394,7 +404,8 @@ void CCubeRenderer::DrawUnsortedGeometry(s32 areaIdx, s32 mask, s32 targetMask) void CCubeRenderer::DrawSortedGeometry(s32 areaIdx, s32 mask, s32 targetMask) { SCOPED_GRAPHICS_DEBUG_GROUP( fmt::format(FMT_STRING("CCubeRenderer::DrawSortedGeometry areaIdx={} mask={} targetMask={}"), areaIdx, mask, - targetMask).c_str(), + targetMask) + .c_str(), zeus::skBlue); SetupRendererStates(true); @@ -427,7 +438,8 @@ void CCubeRenderer::DrawStaticGeometry(s32 areaIdx, s32 mask, s32 targetMask) { void CCubeRenderer::DrawAreaGeometry(s32 areaIdx, s32 mask, s32 targetMask) { SCOPED_GRAPHICS_DEBUG_GROUP( fmt::format(FMT_STRING("CCubeRenderer::DrawAreaGeometry areaIdx={} mask={} targetMask={}"), areaIdx, mask, - targetMask).c_str(), + targetMask) + .c_str(), zeus::skBlue); x318_30_inAreaDraw = true; @@ -476,7 +488,7 @@ void CCubeRenderer::RenderBucketItems(const CAreaListItem* item) { CCubeModel* lastModel = nullptr; EDrawableType lastDrawableType = EDrawableType::Invalid; for (u16 idx : Buckets::sBucketIndex) { - rstl::reserved_vector& bucket = (*Buckets::sBuckets)[idx]; + BucketHolderType& bucket = (*Buckets::sBuckets)[idx]; for (CDrawable* drawable : bucket) { EDrawableType type = drawable->GetType(); switch (type) { diff --git a/Runtime/Graphics/CGraphicsPalette.cpp b/Runtime/Graphics/CGraphicsPalette.cpp index 1a3d4e318..0ab098345 100644 --- a/Runtime/Graphics/CGraphicsPalette.cpp +++ b/Runtime/Graphics/CGraphicsPalette.cpp @@ -24,8 +24,6 @@ void CGraphicsPalette::Load() { x4_frameLoaded = sCurrentFrameCount; } -void CGraphicsPalette::Lock() { x1c_locked = true; } - void CGraphicsPalette::UnLock() { // DCStoreRange(xc_lut, x8_numEntries << 1); GXInitTlutObj(&x10_tlutObj, xc_entries.get(), static_cast(x0_fmt), x8_entryCount); diff --git a/Runtime/Graphics/CGraphicsPalette.hpp b/Runtime/Graphics/CGraphicsPalette.hpp index e7703f73d..f847155f5 100644 --- a/Runtime/Graphics/CGraphicsPalette.hpp +++ b/Runtime/Graphics/CGraphicsPalette.hpp @@ -28,9 +28,9 @@ public: explicit CGraphicsPalette(EPaletteFormat fmt, int count); explicit CGraphicsPalette(CInputStream& in); - void Load(); - void Lock(); + void Lock() { x1c_locked = true; } void UnLock(); + void Load(); [[nodiscard]] u8* GetPaletteData() { return xc_entries.get(); } [[nodiscard]] const u8* GetPaletteData() const { return xc_entries.get(); } diff --git a/Runtime/GuiSys/CGuiTextSupport.cpp b/Runtime/GuiSys/CGuiTextSupport.cpp index 71de6db27..fa1b5fab9 100644 --- a/Runtime/GuiSys/CGuiTextSupport.cpp +++ b/Runtime/GuiSys/CGuiTextSupport.cpp @@ -68,48 +68,44 @@ const CTextRenderBuffer* CGuiTextSupport::GetCurrentPageRenderBuffer() const { float CGuiTextSupport::GetCurrentAnimationOverAge() const { float ret = 0.f; - // TODO -// if (const CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) { -// if (x50_typeEnable) { -// if (x40_primStartTimes.size()) { -// const auto& lastTime = x40_primStartTimes.back(); -// ret = std::max(ret, (buf->GetPrimitiveCount() - lastTime.second) / x58_chRate + lastTime.first); -// } else { -// ret = std::max(ret, buf->GetPrimitiveCount() / x58_chRate); -// } -// } -// } + if (const CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) { + if (x50_typeEnable) { + if (!x40_primStartTimes.empty()) { + const auto& lastTime = x40_primStartTimes.back(); + ret = std::max(ret, (buf->GetPrimitiveCount() - lastTime.second) / x58_chRate + lastTime.first); + } else { + ret = std::max(ret, buf->GetPrimitiveCount() / x58_chRate); + } + } + } return ret; } float CGuiTextSupport::GetNumCharsTotal() const { - // TODO -// if (const CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) { -// if (x50_typeEnable) { -// return buf->GetPrimitiveCount(); -// } -// } + if (const CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) { + if (x50_typeEnable) { + return buf->GetPrimitiveCount(); + } + } return 0.f; } float CGuiTextSupport::GetNumCharsPrinted() const { - // TODO -// if (const CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) { -// if (x50_typeEnable) { -// const float charsPrinted = x3c_curTime * x58_chRate; -// return std::min(charsPrinted, float(buf->GetPrimitiveCount())); -// } -// } + if (const CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) { + if (x50_typeEnable) { + const float charsPrinted = x3c_curTime * x58_chRate; + return std::min(charsPrinted, float(buf->GetPrimitiveCount())); + } + } return 0.f; } float CGuiTextSupport::GetTotalAnimationTime() const { - // TODO -// if (const CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) { -// if (x50_typeEnable) { -// return buf->GetPrimitiveCount() / x58_chRate; -// } -// } + if (const CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) { + if (x50_typeEnable) { + return buf->GetPrimitiveCount() / x58_chRate; + } + } return 0.f; } @@ -121,21 +117,20 @@ void CGuiTextSupport::SetTypeWriteEffectOptions(bool enable, float chFadeTime, f x58_chRate = std::max(chRate, 1.f); if (enable) { if (CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) { - // TODO -// float chStartTime = 0.f; -// for (u32 i = 0; i < buf->GetPrimitiveCount(); ++i) { -// for (const std::pair& p : x40_primStartTimes) { -// if (p.second < i) -// continue; -// if (p.second != i) -// break; -// chStartTime = p.first; -// break; -// } -// -// buf->SetPrimitiveOpacity(i, std::min(std::max(0.f, (x3c_curTime - chStartTime) / x54_chFadeTime), 1.f)); -// chStartTime += 1.f / x58_chRate; -// } + float chStartTime = 0.f; + for (u32 i = 0; i < buf->GetPrimitiveCount(); ++i) { + for (const std::pair& p : x40_primStartTimes) { + if (p.second < i) + continue; + if (p.second != i) + break; + chStartTime = p.first; + break; + } + + //buf->SetPrimitiveOpacity(i, std::min(std::max(0.f, (x3c_curTime - chStartTime) / x54_chFadeTime), 1.f)); + chStartTime += 1.f / x58_chRate; + } } } } @@ -143,21 +138,20 @@ void CGuiTextSupport::SetTypeWriteEffectOptions(bool enable, float chFadeTime, f void CGuiTextSupport::Update(float dt) { if (x50_typeEnable) { if (CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) { - // TODO -// float chStartTime = 0.f; -// for (u32 i = 0; i < buf->GetPrimitiveCount(); ++i) { -// for (const std::pair& p : x40_primStartTimes) { -// if (p.second < i) -// continue; -// if (p.second != i) -// break; -// chStartTime = p.first; -// break; -// } -// -// buf->SetPrimitiveOpacity(i, std::min(std::max(0.f, (x3c_curTime - chStartTime) / x54_chFadeTime), 1.f)); -// chStartTime += 1.f / x58_chRate; -// } + float chStartTime = 0.f; + for (u32 i = 0; i < buf->GetPrimitiveCount(); ++i) { + for (const std::pair& p : x40_primStartTimes) { + if (p.second < i) + continue; + if (p.second != i) + break; + chStartTime = p.first; + break; + } + + //buf->SetPrimitiveOpacity(i, std::min(std::max(0.f, (x3c_curTime - chStartTime) / x54_chFadeTime), 1.f)); + chStartTime += 1.f / x58_chRate; + } } x3c_curTime += dt; } @@ -190,9 +184,11 @@ void CGuiTextSupport::CheckAndRebuildTextBuffer() { } bool CGuiTextSupport::CheckAndRebuildRenderBuffer() { - if (x308_multipageFlag || x60_renderBuf) - if (!x308_multipageFlag || x2ec_renderBufferPages.size()) + if (x308_multipageFlag || x60_renderBuf) { + if (!x308_multipageFlag || x2ec_renderBufferPages.size()) { return true; + } + } CheckAndRebuildTextBuffer(); x2bc_assets = g_TextExecuteBuf->GetAssets(); @@ -259,8 +255,7 @@ void CGuiTextSupport::SetFontColor(const zeus::CColor& col) { void CGuiTextSupport::AddText(std::u16string_view str) { if (x60_renderBuf) { const float t = GetCurrentAnimationOverAge(); - // TODO -// x40_primStartTimes.emplace_back(std::max(t, x3c_curTime), x60_renderBuf->GetPrimitiveCount()); + x40_primStartTimes.emplace_back(std::max(t, x3c_curTime), x60_renderBuf->GetPrimitiveCount()); } x0_string += str; ClearRenderBuffer(); diff --git a/Runtime/GuiSys/CRasterFont.cpp b/Runtime/GuiSys/CRasterFont.cpp index e04114745..dddd9b007 100644 --- a/Runtime/GuiSys/CRasterFont.cpp +++ b/Runtime/GuiSys/CRasterFont.cpp @@ -3,6 +3,7 @@ #include #include "Runtime/CSimplePool.hpp" +#include "Runtime/Graphics/CGX.hpp" #include "Runtime/Graphics/CTexture.hpp" #include "Runtime/GuiSys/CDrawStringOptions.hpp" #include "Runtime/GuiSys/CTextRenderBuffer.hpp" @@ -151,17 +152,15 @@ void CRasterFont::DrawString(const CDrawStringOptions& opts, int x, int y, int& if (!x0_initialized) return; - if (renderBuf) { - /* CGraphicsPalette pal = CGraphicsPalette::CGraphcisPalette(2, 4); */ - /* zeus::CColor color = zeus::CColor(0.f, 0.f, 0.f, 0.f) */ - /* tmp = color.ToRGB5A3(); */ - /* tmp2 = opts.x8_.ToRGB5A3(); */ - /* tmp3 = opts.xc_.ToRGB5A3(); */ - /* tmp4 = zeus::CColor(0.f, 0.f, 0.f, 0.f); */ - /* tmp5 = tmp4.ToRGBA5A3(); */ - /* pal.UnLock(); */ - /* renderBuf->AddPaletteChange(pal); */ - renderBuf->AddPaletteChange(opts.x4_colors[0], opts.x4_colors[1]); + if (renderBuf != nullptr) { + CGraphicsPalette pal(EPaletteFormat::RGB5A3, 4); + pal.Lock(); + *reinterpret_cast(pal.GetPaletteData() + 0) = SBIG(zeus::CColor(0.f, 0.f, 0.f, 0.f).toRGB5A3()); + *reinterpret_cast(pal.GetPaletteData() + 2) = SBIG(opts.x4_colors[0].toRGB5A3()); + *reinterpret_cast(pal.GetPaletteData() + 4) = SBIG(opts.x4_colors[1].toRGB5A3()); + *reinterpret_cast(pal.GetPaletteData() + 6) = SBIG(zeus::CColor(0.f, 0.f, 0.f, 0.f).toRGB5A3()); + pal.UnLock(); + renderBuf->AddPaletteChange(pal); } SinglePassDrawString(opts, x, y, xout, yout, renderBuf, str, len); @@ -210,6 +209,28 @@ bool CRasterFont::IsFinishedLoading() const { return true; } +void CRasterFont::SetupRenderState() { + static const GX::VtxDescList skDescList[3] = { + {GX::VA_POS, GX::DIRECT}, + {GX::VA_TEX0, GX::DIRECT}, + {GX::VA_NULL, GX::NONE} + }; + + x80_texture->Load(GX::TEXMAP0, EClampMode::Clamp); + CGX::SetTevKAlphaSel(GX::TEVSTAGE0, GX::TEV_KASEL_K0_A); + CGX::SetTevKColorSel(GX::TEVSTAGE0, GX::TEV_KCSEL_K0); + 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); + CGX::SetTevDirect(GX::TEVSTAGE0); + CGX::SetVtxDescv(skDescList); + CGX::SetNumChans(0); + CGX::SetNumTexGens(1); + CGX::SetNumTevStages(1); + CGX::SetNumIndStages(0); + CGX::SetTevOrder(GX::TEVSTAGE0, GX::TEXCOORD0, GX::TEXMAP0, GX::COLOR_NULL); + CGX::SetTexCoordGen(GX::TEXCOORD0, GX::TG_MTX2x4, GX::TG_TEX0, GX::IDENTITY, false, GX::PTIDENTITY); +} std::unique_ptr FRasterFontFactory([[maybe_unused]] const SObjectTag& tag, CInputStream& in, const CVParamTransfer& vparms, [[maybe_unused]] CObjectReference* selfRef) { CSimplePool* sp = vparms.GetOwnedObj(); diff --git a/Runtime/GuiSys/CRasterFont.hpp b/Runtime/GuiSys/CRasterFont.hpp index 248360963..990dcd5e5 100644 --- a/Runtime/GuiSys/CRasterFont.hpp +++ b/Runtime/GuiSys/CRasterFont.hpp @@ -151,6 +151,8 @@ public: CTexture& GetTexture() { return *x80_texture; } bool IsFinishedLoading() const; + + void SetupRenderState(); }; std::unique_ptr FRasterFontFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& vparms, diff --git a/Runtime/GuiSys/CTextExecuteBuffer.cpp b/Runtime/GuiSys/CTextExecuteBuffer.cpp index bf40e7ea9..3e2ebf0ee 100644 --- a/Runtime/GuiSys/CTextExecuteBuffer.cpp +++ b/Runtime/GuiSys/CTextExecuteBuffer.cpp @@ -12,7 +12,7 @@ namespace metaforce { CTextRenderBuffer CTextExecuteBuffer::BuildRenderBuffer(CGuiWidget::EGuiModelDrawFlags df) const { - CTextRenderBuffer ret(CTextRenderBuffer::EMode::AllocTally, df); + CTextRenderBuffer ret(CTextRenderBuffer::EMode::AllocTally);//, df); { CFontRenderState rendState; @@ -35,7 +35,7 @@ CTextRenderBuffer CTextExecuteBuffer::BuildRenderBufferPage(InstList::const_iter InstList::const_iterator pgStart, InstList::const_iterator pgEnd, CGuiWidget::EGuiModelDrawFlags df) const { - CTextRenderBuffer ret(CTextRenderBuffer::EMode::AllocTally, df); + CTextRenderBuffer ret(CTextRenderBuffer::EMode::AllocTally);//, df); { CFontRenderState rendState; @@ -71,7 +71,7 @@ std::list CTextExecuteBuffer::BuildRenderBufferPages(const ze std::list ret; for (auto it = x0_instList.begin(); it != x0_instList.end();) { - CTextRenderBuffer rbuf(CTextRenderBuffer::EMode::AllocTally, df); + CTextRenderBuffer rbuf(CTextRenderBuffer::EMode::AllocTally);//, df); { CFontRenderState rstate; diff --git a/Runtime/GuiSys/CTextRenderBuffer.cpp b/Runtime/GuiSys/CTextRenderBuffer.cpp index 966784137..5ceb05010 100644 --- a/Runtime/GuiSys/CTextRenderBuffer.cpp +++ b/Runtime/GuiSys/CTextRenderBuffer.cpp @@ -12,285 +12,29 @@ namespace metaforce { -//struct CTextRenderBuffer::BooFontCharacters { -// TLockedToken m_font; -// hecl::VertexBufferPool::Token m_instBuf; -// boo::ObjToken m_dataBinding; -// boo::ObjToken m_dataBinding2; -// std::vector m_charData; -// u32 m_charCount = 0; -// bool m_dirty = true; -// -// BooFontCharacters(const CToken& token) : m_font(token) {} -//}; -// -//struct CTextRenderBuffer::BooImage { -// CFontImageDef m_imageDef; -// hecl::VertexBufferPool::Token m_instBuf; -// std::vector> m_dataBinding; -// std::vector> m_dataBinding2; -// CTextSupportShader::ImageInstance m_imageData; -// bool m_dirty = true; -// -// BooImage(const CFontImageDef& imgDef, const zeus::CVector2i& offset) : m_imageDef(imgDef) { -// m_imageData.SetMetrics(imgDef, offset); -// } -//}; -// -//struct CTextRenderBuffer::BooPrimitiveMark { -// Command m_cmd; -// u32 m_bindIdx; -// u32 m_instIdx; -// -// void SetOpacity(CTextRenderBuffer& rb, float opacity) { -// switch (m_cmd) { -// case Command::CharacterRender: { -// BooFontCharacters& fc = rb.m_fontCharacters[m_bindIdx]; -// CTextSupportShader::CharacterInstance& inst = fc.m_charData[m_instIdx]; -// inst.m_mulColor.a() = opacity; -// fc.m_dirty = true; -// break; -// } -// case Command::ImageRender: { -// BooImage& img = rb.m_images[m_bindIdx]; -// img.m_imageData.m_color.a() = opacity; -// img.m_dirty = true; -// break; -// } -// default: -// break; -// } -// } -//}; - CTextRenderBuffer::CTextRenderBuffer(CTextRenderBuffer&&) noexcept = default; -CTextRenderBuffer::CTextRenderBuffer(EMode mode, CGuiWidget::EGuiModelDrawFlags df) : x0_mode(mode)/*, m_drawFlags(df)*/ {} +CTextRenderBuffer::CTextRenderBuffer(EMode mode) : x0_mode(mode) {} CTextRenderBuffer::~CTextRenderBuffer() = default; CTextRenderBuffer& CTextRenderBuffer::operator=(CTextRenderBuffer&&) noexcept = default; -//void CTextRenderBuffer::CommitResources() { -// if (m_committed) -// return; -// m_committed = true; -// -// /* Ensure font textures are ready outside transaction */ -// for (BooFontCharacters& chs : m_fontCharacters) -// chs.m_font->GetTexture(); -// -// CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) { -// m_uniBuf = CTextSupportShader::s_Uniforms.allocateBlock(CGraphics::g_BooFactory); -// auto uBufInfo = m_uniBuf.getBufferInfo(); -// decltype(uBufInfo) uBufInfo2; -// if (m_drawFlags == CGuiWidget::EGuiModelDrawFlags::AlphaAdditiveOverdraw) { -// m_uniBuf2 = CTextSupportShader::s_Uniforms.allocateBlock(CGraphics::g_BooFactory); -// uBufInfo2 = m_uniBuf2.getBufferInfo(); -// } -// -// for (BooFontCharacters& chs : m_fontCharacters) { -// chs.m_instBuf = CTextSupportShader::s_CharInsts.allocateBlock(CGraphics::g_BooFactory, chs.m_charCount); -// auto iBufInfo = chs.m_instBuf.getBufferInfo(); -// -// boo::ObjToken uniforms[] = {uBufInfo.first.get()}; -// boo::PipelineStage unistages[] = {boo::PipelineStage::Vertex}; -// size_t unioffs[] = {size_t(uBufInfo.second)}; -// size_t unisizes[] = {sizeof(CTextSupportShader::Uniform)}; -// boo::ObjToken texs[] = {chs.m_font->GetTexture()}; -// chs.m_dataBinding = ctx.newShaderDataBinding(CTextSupportShader::SelectTextPipeline(m_drawFlags), nullptr, -// iBufInfo.first.get(), nullptr, 1, uniforms, unistages, unioffs, -// unisizes, 1, texs, nullptr, nullptr, 0, iBufInfo.second); -// -// if (m_drawFlags == CGuiWidget::EGuiModelDrawFlags::AlphaAdditiveOverdraw) { -// uniforms[0] = uBufInfo2.first.get(); -// unioffs[0] = size_t(uBufInfo2.second); -// chs.m_dataBinding2 = ctx.newShaderDataBinding(CTextSupportShader::GetTextAdditiveOverdrawPipeline(), nullptr, -// iBufInfo.first.get(), nullptr, 1, uniforms, unistages, unioffs, -// unisizes, 1, texs, nullptr, nullptr, 0, iBufInfo.second); -// } -// } -// -// for (BooImage& img : m_images) { -// img.m_instBuf = CTextSupportShader::s_ImgInsts.allocateBlock(CGraphics::g_BooFactory, 1); -// auto iBufInfo = img.m_instBuf.getBufferInfo(); -// -// boo::ObjToken uniforms[] = {uBufInfo.first.get()}; -// boo::PipelineStage unistages[] = {boo::PipelineStage::Vertex}; -// size_t unioffs[] = {size_t(uBufInfo.second)}; -// size_t unisizes[] = {sizeof(CTextSupportShader::Uniform)}; -// img.m_dataBinding.reserve(img.m_imageDef.x4_texs.size()); -// for (TToken& tex : img.m_imageDef.x4_texs) { -// boo::ObjToken texs[] = {tex->GetBooTexture()}; -// texs[0]->setClampMode(boo::TextureClampMode::ClampToEdge); -// img.m_dataBinding.push_back(ctx.newShaderDataBinding( -// CTextSupportShader::SelectImagePipeline(m_drawFlags), nullptr, iBufInfo.first.get(), nullptr, 1, uniforms, -// unistages, unioffs, unisizes, 1, texs, nullptr, nullptr, 0, iBufInfo.second)); -// } -// -// if (m_drawFlags == CGuiWidget::EGuiModelDrawFlags::AlphaAdditiveOverdraw) { -// uniforms[0] = uBufInfo2.first.get(); -// unioffs[0] = size_t(uBufInfo2.second); -// img.m_dataBinding2.reserve(img.m_imageDef.x4_texs.size()); -// for (TToken& tex : img.m_imageDef.x4_texs) { -// boo::ObjToken texs[] = {tex->GetBooTexture()}; -// img.m_dataBinding2.push_back(ctx.newShaderDataBinding( -// CTextSupportShader::GetImageAdditiveOverdrawPipeline(), nullptr, iBufInfo.first.get(), nullptr, 1, -// uniforms, unistages, unioffs, unisizes, 1, texs, nullptr, nullptr, 0, iBufInfo.second)); -// } -// } -// } -// return true; -// } BooTrace); -//} - -void CTextRenderBuffer::SetMode(EMode mode) { - x0_mode = mode; -} - -//void CTextRenderBuffer::SetPrimitiveOpacity(int idx, float opacity) { -// m_primitiveMarks[idx].SetOpacity(*this, opacity); -//} -// -//u32 CTextRenderBuffer::GetPrimitiveCount() const { return m_primitiveMarks.size(); } - -void CTextRenderBuffer::Render(const zeus::CColor& col, float time) { -// CommitResources(); - -// const zeus::CMatrix4f mv = CGraphics::g_GXModelView.toMatrix4f(); -// const zeus::CMatrix4f proj = CGraphics::GetPerspectiveProjectionMatrix(true); -// const zeus::CMatrix4f mat = proj * mv; - -// m_uniBuf.access() = CTextSupportShader::Uniform{mat, col}; -// if (m_drawFlags == CGuiWidget::EGuiModelDrawFlags::AlphaAdditiveOverdraw) { -// zeus::CColor colPremul = col * col.a(); -// colPremul.a() = col.a(); -// m_uniBuf2.access() = CTextSupportShader::Uniform{mat, colPremul}; -// } - -// for (BooFontCharacters& chs : m_fontCharacters) { -// if (chs.m_charData.size()) { -// if (chs.m_dirty) { -// std::memmove(chs.m_instBuf.access(), chs.m_charData.data(), -// sizeof(CTextSupportShader::CharacterInstance) * chs.m_charData.size()); -// chs.m_dirty = false; -// } -// CGraphics::SetShaderDataBinding(chs.m_dataBinding); -// CGraphics::DrawInstances(0, 4, chs.m_charData.size()); -// if (m_drawFlags == CGuiWidget::EGuiModelDrawFlags::AlphaAdditiveOverdraw) { -// CGraphics::SetShaderDataBinding(chs.m_dataBinding2); -// CGraphics::DrawInstances(0, 4, chs.m_charData.size()); -// } -// } -// } - -// for (BooImage& img : m_images) { -// if (img.m_dirty) { -// *img.m_instBuf.access() = img.m_imageData; -// img.m_dirty = false; -// } -// const int idx = int(img.m_imageDef.x0_fps * time) % img.m_dataBinding.size(); -// CGraphics::SetShaderDataBinding(img.m_dataBinding[idx]); -// CGraphics::DrawInstances(0, 4, 1); -// if (m_drawFlags == CGuiWidget::EGuiModelDrawFlags::AlphaAdditiveOverdraw) { -// CGraphics::SetShaderDataBinding(img.m_dataBinding2[idx]); -// CGraphics::DrawInstances(0, 4, 1); -// } -// } -} - -void CTextRenderBuffer::AddImage(const zeus::CVector2i& offset, const CFontImageDef& image) { -// if (x0_mode == EMode::AllocTally) -// m_primitiveMarks.push_back({Command::ImageRender, m_imagesCount++, 0}); -// else -// m_images.emplace_back(image, offset); -} - -void CTextRenderBuffer::AddCharacter(const zeus::CVector2i& offset, char16_t ch, const zeus::CColor& color) { -// if (m_activeFontCh == UINT32_MAX) -// return; -// BooFontCharacters& chs = m_fontCharacters[m_activeFontCh]; -// if (x0_mode == EMode::AllocTally) -// m_primitiveMarks.push_back({Command::CharacterRender, m_activeFontCh, chs.m_charCount++}); -// else { -// const CGlyph* glyph = chs.m_font.GetObj()->GetGlyph(ch); -// -// CTextSupportShader::CharacterInstance& inst = chs.m_charData.emplace_back(); -// inst.SetMetrics(*glyph, offset); -// inst.m_fontColor = m_main * color; -// inst.m_outlineColor = m_outline * color; -// inst.m_mulColor = zeus::skWhite; -// } -} - -void CTextRenderBuffer::AddPaletteChange(const zeus::CColor& main, const zeus::CColor& outline) { -// m_main = main; -// m_outline = outline; -} - -void CTextRenderBuffer::AddFontChange(const TToken& font) { -// for (size_t i = 0; i < m_fontCharacters.size(); ++i) { -// BooFontCharacters& chs = m_fontCharacters[i]; -// if (*chs.m_font.GetObjectTag() == *font.GetObjectTag()) { -// m_activeFontCh = i; -// return; -// } -// } -// -// m_activeFontCh = m_fontCharacters.size(); -// m_fontCharacters.emplace_back(font); -} - -bool CTextRenderBuffer::HasSpaceAvailable(const zeus::CVector2i& origin, const zeus::CVector2i& extent) const { - std::pair bounds = AccumulateTextBounds(); - if (bounds.first.x > bounds.second.x) - return true; - - if (0 < origin.y) - return false; - - zeus::CVector2i size = bounds.second - bounds.first; - return size.y <= extent.y; -} - -std::pair CTextRenderBuffer::AccumulateTextBounds() const { - std::pair ret = - std::make_pair(zeus::CVector2i{INT_MAX, INT_MAX}, zeus::CVector2i{INT_MIN, INT_MIN}); - -// for (const BooFontCharacters& chars : m_fontCharacters) { -// for (const CTextSupportShader::CharacterInstance& charInst : chars.m_charData) { -// ret.first.x = std::min(ret.first.x, int(charInst.m_pos[0].x())); -// ret.first.y = std::min(ret.first.y, int(charInst.m_pos[0].z())); -// ret.second.x = std::max(ret.second.x, int(charInst.m_pos[3].x())); -// ret.second.y = std::max(ret.second.y, int(charInst.m_pos[3].z())); -// } -// } -// -// for (const BooImage& imgs : m_images) { -// ret.first.x = std::min(ret.first.x, int(imgs.m_imageData.m_pos[0].x())); -// ret.first.y = std::min(ret.first.y, int(imgs.m_imageData.m_pos[0].z())); -// ret.second.x = std::max(ret.second.x, int(imgs.m_imageData.m_pos[3].x())); -// ret.second.y = std::max(ret.second.y, int(imgs.m_imageData.m_pos[3].z())); -// } - - return ret; -} - void CTextRenderBuffer::SetPrimitive(const Primitive& prim, s32 idx) { CMemoryStreamOut out(reinterpret_cast(x34_bytecode.data() + x24_primOffsets[idx]), x44_blobSize - x24_primOffsets[idx]); if (prim.x4_command == Command::ImageRender) { - out.WriteUint8(1); + out.WriteUint8(static_cast(Command::ImageRender)); out.Put(prim.x8_xPos); out.Put(prim.xa_zPos); out.Put(prim.xe_imageIndex); -// out.Put(prim.x0_color1.toRGBA()); + out.Put(prim.x0_color1.toRGBA()); } else if (prim.x4_command == Command::CharacterRender) { - out.WriteUint8(0); + out.WriteUint8(static_cast(Command::CharacterRender)); out.Put(prim.x8_xPos); out.Put(prim.xa_zPos); out.Put(u16(prim.xc_glyph)); -// out.Put(prim.x0_color1.toRGBA()); + out.Put(prim.x0_color1.toRGBA()); } } @@ -303,7 +47,7 @@ CTextRenderBuffer::Primitive CTextRenderBuffer::GetPrimitive(s32 idx) const { u16 zPos = in.ReadShort(); u8 imageIndex = in.ReadChar(); CTextColor color(in.ReadUint32()); - return {color, Command::ImageRender, xPos, zPos, u'\0', imageIndex }; + return {color, Command::ImageRender, xPos, zPos, u'\0', imageIndex}; } if (cmd == Command::CharacterRender) { @@ -315,7 +59,205 @@ CTextRenderBuffer::Primitive CTextRenderBuffer::GetPrimitive(s32 idx) const { return {color, Command::CharacterRender, xPos, zPos, glyph, 0}; } - return {CTextColor(zeus::Comp32(0)), Command::Invalid, 0, 0, u'\0', 0 }; + return {CTextColor(zeus::Comp32(0)), Command::Invalid, 0, 0, u'\0', 0}; +} + +u8* CTextRenderBuffer::GetOutStream() { + VerifyBuffer(); + return reinterpret_cast(x34_bytecode.data()) + x48_curBytecodeOffset; +} + +void CTextRenderBuffer::VerifyBuffer() { + if (x34_bytecode.empty()) { + x34_bytecode.resize(x44_blobSize); + } +} + +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) { + return i; + } + } + + return -1; +} + +CGraphicsPalette* CTextRenderBuffer::GetNextAvailablePalette() { + if (x254_nextPalette < 64) { + x50_palettes.push_back(std::make_unique(EPaletteFormat::RGB5A3, 4)); + } else { + x254_nextPalette = 0; + } + ++x254_nextPalette; + return x50_palettes[x254_nextPalette - 1].get(); +} + +u32 CTextRenderBuffer::GetCurLen() { + VerifyBuffer(); + return x44_blobSize - x48_curBytecodeOffset; +} + +void CTextRenderBuffer::Render(const zeus::CColor& col, float time) { + // TODO +} + +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(); + destPalette->Lock(); + memcpy(destPalette->GetPaletteData(), palette.GetPaletteData(), 8); + destPalette->UnLock(); + } + out.WriteUint8(static_cast(Command::PaletteChange)); + out.WriteUint8(paletteIndex); + x48_curBytecodeOffset += out.GetNumWrites(); + } + } else { + x44_blobSize += 2; + } +} + +void CTextRenderBuffer::AddImage(const zeus::CVector2i& offset, const CFontImageDef& image) { + if (x0_mode == EMode::BufferFill) { + CMemoryStreamOut out(GetOutStream(), GetCurLen()); + x24_primOffsets.reserve(x24_primOffsets.size() + 1); + u32 primCap = x24_primOffsets.capacity(); + if (x24_primOffsets.capacity() <= x24_primOffsets.size()) { + x24_primOffsets.reserve(primCap != 0 ? primCap * 2 : 4); + } + x24_primOffsets.push_back(x48_curBytecodeOffset); + x14_images.reserve(x14_images.size() + 1); + u32 imgIdx = x14_images.size(); + x14_images.push_back(image); + out.WriteUint8(static_cast(Command::ImageRender)); + out.WriteShort(offset.x); + out.WriteShort(offset.y); + out.WriteUint8(imgIdx); + out.WriteLong(zeus::skWhite.toRGBA()); + x48_curBytecodeOffset += out.GetNumWrites(); + } else { + x44_blobSize += 10; + } +} + +void CTextRenderBuffer::AddCharacter(const zeus::CVector2i& offset, char16_t ch, const CTextColor& color) { + if (x0_mode == EMode::BufferFill) { + CMemoryStreamOut out(GetOutStream(), GetCurLen()); + x24_primOffsets.reserve(x24_primOffsets.size() + 1); + u32 primCap = x24_primOffsets.capacity(); + if (x24_primOffsets.capacity() <= x24_primOffsets.size()) { + x24_primOffsets.reserve(primCap != 0 ? primCap * 2 : 4); + } + x24_primOffsets.push_back(x48_curBytecodeOffset); + out.WriteUint8(u32(Command::CharacterRender)); + out.WriteShort(offset.x); + out.WriteShort(offset.y); + out.WriteShort(ch); + out.WriteUint32(color.toRGBA()); + x48_curBytecodeOffset += out.GetNumWrites(); + } else { + x44_blobSize += 11; + } +} + +void CTextRenderBuffer::AddFontChange(const TToken& font) { + if (x0_mode == EMode::BufferFill) { + CMemoryStreamOut out(GetOutStream(), GetCurLen()); + u32 fontCount = x4_fonts.size(); + bool found = false; + u8 fontIndex = 0; + if (fontCount > 0) { + for (const auto& tok : x4_fonts) { + if (tok.GetObjectReference() == font.GetObjectReference()) { + out.WriteUint8(static_cast(Command::FontChange)); + out.WriteUint8(fontIndex); + found = true; + break; + } + ++fontIndex; + } + } + + if (!found) { + x4_fonts.reserve(x4_fonts.size() + 1); + u32 fontIdx = x4_fonts.size(); + x4_fonts.push_back(font); + out.WriteUint8(static_cast(Command::FontChange)); + out.WriteUint8(fontIdx); + } + x48_curBytecodeOffset += out.GetNumWrites(); + } else { + x44_blobSize += 2; + } +} + +bool CTextRenderBuffer::HasSpaceAvailable(const zeus::CVector2i& origin, const zeus::CVector2i& extent) { + std::pair bounds = AccumulateTextBounds(); + if (bounds.first.x > bounds.second.x) { + return true; + } + + if (0 < origin.y) { + return false; + } + + zeus::CVector2i size = bounds.second - bounds.first; + return size.y <= extent.y; +} + +std::pair CTextRenderBuffer::AccumulateTextBounds() { + zeus::CVector2i min{INT_MAX, INT_MAX}; + zeus::CVector2i max{INT_MIN, INT_MIN}; + CMemoryInStream in(x34_bytecode.data(), x44_blobSize); + + while (in.GetReadPosition() < x48_curBytecodeOffset) { + auto cmd = static_cast(in.ReadChar()); + if (cmd == Command::FontChange) { + x4c_activeFont = in.ReadChar(); + } else if (cmd == Command::CharacterRender) { + u16 offX = in.ReadShort(); + u16 offY = in.ReadShort(); + char16_t chr = in.ReadShort(); + in.ReadLong(); + if (x4c_activeFont != -1) { + auto font = x4_fonts[x4c_activeFont]; + if (font) { + const auto* glyph = font->GetGlyph(chr); + if (glyph != nullptr) { + max.x = std::max(max.x, offX + glyph->GetCellWidth()); + max.y = std::max(max.y, offY + glyph->GetCellHeight()); + min.x = std::min(min.x, offX); + min.y = std::min(min.y, offY); + } + } + } + } else if (cmd == Command::ImageRender) { + u16 offX = in.ReadShort(); + u16 offY = in.ReadShort(); + u8 imageIdx = in.ReadChar(); + in.ReadLong(); + const auto& image = x14_images[imageIdx]; + max.x = std::max(max.x, offX + static_cast(static_cast(image.x4_texs.front()->GetWidth()) * + image.x14_cropFactor.x())); + max.y = std::max(max.y, offY + static_cast(static_cast(image.x4_texs.front()->GetHeight()) * + image.x14_cropFactor.y())); + min.x = std::min(min.x, offX); + min.y = std::min(min.y, offY); + } else if (cmd == Command::PaletteChange) { + in.ReadChar(); + } + } + return {min, max}; } } // namespace metaforce diff --git a/Runtime/GuiSys/CTextRenderBuffer.hpp b/Runtime/GuiSys/CTextRenderBuffer.hpp index b94f646de..502eea495 100644 --- a/Runtime/GuiSys/CTextRenderBuffer.hpp +++ b/Runtime/GuiSys/CTextRenderBuffer.hpp @@ -27,7 +27,8 @@ class CTextRenderBuffer { friend class CTextSupportShader; public: - enum class Command { CharacterRender, ImageRender, FontChange, PaletteChange, Invalid }; + enum class Command { CharacterRender, ImageRender, FontChange, PaletteChange, Invalid = -1 }; +#if 1 struct Primitive { CTextColor x0_color1; Command x4_command; @@ -36,6 +37,7 @@ public: char16_t xc_glyph; u8 xe_imageIndex; }; +#endif enum class EMode { AllocTally, BufferFill }; private: @@ -46,34 +48,37 @@ private: std::vector x34_bytecode; u32 x44_blobSize = 0; u32 x48_curBytecodeOffset = 0; - u8 x4c_activeFont; - u32 x50_paletteCount = 0; - std::array, 64> x54_palettes; - u32 x254_nextPalette = 0; + s8 x4c_activeFont = -1; + s8 x4d_ = -1; + s8 x4e_ = -1; + s8 x4f_curPalette = -1; + rstl::reserved_vector, 64> x50_palettes; + s32 x254_nextPalette = 0; public: CTextRenderBuffer(CTextRenderBuffer&& other) noexcept; - CTextRenderBuffer(EMode mode, CGuiWidget::EGuiModelDrawFlags df); + CTextRenderBuffer(EMode mode); ~CTextRenderBuffer(); CTextRenderBuffer& operator=(CTextRenderBuffer&& other) noexcept; void SetPrimitive(const Primitive&, int); [[nodiscard]] Primitive GetPrimitive(int) const; - void GetOutStream(); + [[nodiscard]] u32 GetPrimitiveCount() const { return x24_primOffsets.size(); } + [[nodiscard]] u8* GetOutStream(); + [[nodiscard]] u32 GetCurLen(); void VerifyBuffer(); int GetMatchingPaletteIndex(const CGraphicsPalette& palette); - CGraphicsPalette* GetNextAvailablePalette(); + [[nodiscard]] CGraphicsPalette* GetNextAvailablePalette(); void AddPaletteChange(const CGraphicsPalette& palette); void SetMode(EMode mode); - void Render(const zeus::CColor& col, float time); + void Render(const CTextColor& col, float time); void AddImage(const zeus::CVector2i& offset, const CFontImageDef& image); - void AddCharacter(const zeus::CVector2i& offset, char16_t ch, const zeus::CColor& color); - void AddPaletteChange(const zeus::CColor& main, const zeus::CColor& outline); + void AddCharacter(const zeus::CVector2i& offset, char16_t ch, const CTextColor& color); void AddFontChange(const TToken& font); - bool HasSpaceAvailable(const zeus::CVector2i& origin, const zeus::CVector2i& extent) const; - std::pair AccumulateTextBounds() const; + [[nodiscard]] bool HasSpaceAvailable(const zeus::CVector2i& origin, const zeus::CVector2i& extent); + [[nodiscard]] std::pair AccumulateTextBounds(); }; } // namespace metaforce diff --git a/Runtime/Streams/CMemoryInStream.hpp b/Runtime/Streams/CMemoryInStream.hpp index 5ece7aadb..d65f64e62 100644 --- a/Runtime/Streams/CMemoryInStream.hpp +++ b/Runtime/Streams/CMemoryInStream.hpp @@ -5,8 +5,8 @@ namespace metaforce { class CMemoryInStream final : public CInputStream { public: enum class EOwnerShip { - NotOwned, Owned, + NotOwned, }; CMemoryInStream(const void* ptr, u32 len) : CInputStream(ptr, len, false) {} diff --git a/Runtime/Streams/CMemoryStreamOut.hpp b/Runtime/Streams/CMemoryStreamOut.hpp index 75698982f..7e578137e 100644 --- a/Runtime/Streams/CMemoryStreamOut.hpp +++ b/Runtime/Streams/CMemoryStreamOut.hpp @@ -5,8 +5,8 @@ namespace metaforce { class CMemoryStreamOut final : public COutputStream { public: enum class EOwnerShip { - NotOwned, Owned, + NotOwned, }; private: diff --git a/Runtime/Streams/COutputStream.hpp b/Runtime/Streams/COutputStream.hpp index d8c0c833a..8a633e976 100644 --- a/Runtime/Streams/COutputStream.hpp +++ b/Runtime/Streams/COutputStream.hpp @@ -24,6 +24,7 @@ public: COutputStream(s32 unk); virtual ~COutputStream(); + u32 GetNumWrites() const { return x10_numWrites; } void WriteBits(u32 val, u32 bitCount); void WriteChar(u8 c); void WriteShort(u16 s); diff --git a/extern/zeus b/extern/zeus index 8e4dfb022..8410394d4 160000 --- a/extern/zeus +++ b/extern/zeus @@ -1 +1 @@ -Subproject commit 8e4dfb022a97aee2c245d8a2ec9b92ce3d865fbd +Subproject commit 8410394d4bd90f8783b68ab064b13d838e29d6a1