From 85eb7e59d9df4002200a6c3c6da3674803f7cdb1 Mon Sep 17 00:00:00 2001 From: Jan Racek Date: Fri, 27 Mar 2026 19:30:01 +0100 Subject: [PATCH] memory reports --- Makefile | 8 +++- src/memoverlay.cpp | 96 ++++++++++++++++++++++++++++++++++++++++++++ src/memoverlay.hh | 47 ++++++++++++++++++++++ src/renderer.cpp | 21 ++++++++++ src/renderer.hh | 9 +++++ src/scenemanager.cpp | 7 ++++ src/scenemanager.hh | 6 +++ 7 files changed, 193 insertions(+), 1 deletion(-) create mode 100644 src/memoverlay.cpp create mode 100644 src/memoverlay.hh diff --git a/Makefile b/Makefile index 1899fbd..568c725 100644 --- a/Makefile +++ b/Makefile @@ -22,7 +22,8 @@ src/collision.cpp \ src/bvh.cpp \ src/cutscene.cpp \ src/uisystem.cpp \ -src/loadingscreen.cpp +src/loadingscreen.cpp \ +src/memoverlay.cpp # LOADER=cdrom → CD-ROM backend (for ISO builds on real hardware) # LOADER=pcdrv → PCdrv backend (default, emulator + SIO1) @@ -32,5 +33,10 @@ else CPPFLAGS += -DPCDRV_SUPPORT=1 endif +# MEMOVERLAY=1 → Enable runtime heap/RAM usage overlay +ifeq ($(MEMOVERLAY),1) +CPPFLAGS += -DPSXSPLASH_MEMOVERLAY +endif + include third_party/nugget/psyqo-lua/psyqo-lua.mk include third_party/nugget/psyqo/psyqo.mk diff --git a/src/memoverlay.cpp b/src/memoverlay.cpp new file mode 100644 index 0000000..c2b1042 --- /dev/null +++ b/src/memoverlay.cpp @@ -0,0 +1,96 @@ +#ifdef PSXSPLASH_MEMOVERLAY + +#include "memoverlay.hh" + +#include +#include + +#include "vram_config.h" + +// Linker symbols +extern "C" { +extern char __heap_start; +extern char __stack_start; +} + +namespace psxsplash { + +void MemOverlay::init(psyqo::Font<>* font) { + m_font = font; + m_heapBase = reinterpret_cast(&__heap_start); + m_stackTop = reinterpret_cast(&__stack_start); + m_totalAvail = (uint32_t)(m_stackTop - m_heapBase); +} + +void MemOverlay::renderOT(psyqo::OrderingTable& ot, + psyqo::BumpAllocator& balloc) { + if (!m_font || m_totalAvail == 0) return; + + // Measure current heap usage + void* heapEnd = psyqo_heap_end(); + uint32_t heapUsed = 0; + if (heapEnd != nullptr) { + heapUsed = (uint32_t)(reinterpret_cast(heapEnd) - m_heapBase); + } + + m_lastPct = (heapUsed * 100) / m_totalAvail; + if (m_lastPct > 100) m_lastPct = 100; + m_lastUsedKB = heapUsed / 1024; + m_lastTotalKB = m_totalAvail / 1024; + + // Bar dimensions - top-right corner + static constexpr int16_t BAR_W = 80; + static constexpr int16_t BAR_H = 6; + static constexpr int16_t BAR_X = VRAM_RES_WIDTH - BAR_W - 4; + static constexpr int16_t BAR_Y = 4; + + // Need room for two rectangles + size_t needed = sizeof(psyqo::Fragments::SimpleFragment) * 2 + 32; + if (balloc.remaining() < needed) return; + + // Fill bar first (OT is LIFO, so first insert renders last / on top) + int16_t fillW = (int16_t)((uint32_t)BAR_W * m_lastPct / 100); + if (fillW > 0) { + uint8_t r, g; + if (m_lastPct < 50) { + r = (uint8_t)(m_lastPct * 5); + g = 200; + } else { + r = 250; + g = (uint8_t)((100 - m_lastPct) * 4); + } + + auto& fillFrag = balloc.allocateFragment(); + fillFrag.primitive.setColor(psyqo::Color{.r = r, .g = g, .b = 20}); + fillFrag.primitive.position = {.x = BAR_X, .y = BAR_Y}; + fillFrag.primitive.size = {.x = fillW, .y = BAR_H}; + fillFrag.primitive.setOpaque(); + ot.insert(fillFrag, 0); + } + + // Background bar (inserted second, so renders first / behind fill) + auto& bgFrag = balloc.allocateFragment(); + bgFrag.primitive.setColor(psyqo::Color{.r = 40, .g = 40, .b = 40}); + bgFrag.primitive.position = {.x = BAR_X, .y = BAR_Y}; + bgFrag.primitive.size = {.x = BAR_W, .y = BAR_H}; + bgFrag.primitive.setOpaque(); + ot.insert(bgFrag, 0); +} + +void MemOverlay::renderText(psyqo::GPU& gpu) { + if (!m_font || m_totalAvail == 0) return; + + static constexpr int16_t BAR_H = 6; + static constexpr int16_t BAR_X = VRAM_RES_WIDTH - 80 - 4; + static constexpr int16_t BAR_Y = 4; + static constexpr int16_t TEXT_Y = BAR_Y + BAR_H + 2; + + m_font->chainprintf(gpu, + {{.x = BAR_X - 20, .y = TEXT_Y}}, + {{.r = 0xcc, .g = 0xcc, .b = 0xcc}}, + "%luK/%luK", m_lastUsedKB, m_lastTotalKB); +} + +} // namespace psxsplash + +#endif // PSXSPLASH_MEMOVERLAY diff --git a/src/memoverlay.hh b/src/memoverlay.hh new file mode 100644 index 0000000..a69415c --- /dev/null +++ b/src/memoverlay.hh @@ -0,0 +1,47 @@ +#pragma once + +// Runtime memory overlay - shows heap/RAM usage as a progress bar + text. +// Compiled only when PSXSPLASH_MEMOVERLAY is defined (set from SplashEdit build flag). + +#ifdef PSXSPLASH_MEMOVERLAY + +#include +#include +#include +#include + +#include "renderer.hh" + +namespace psxsplash { + +class MemOverlay { +public: + /// Call once at startup to cache linker symbol addresses. + void init(psyqo::Font<>* font); + + /// Phase 1: Insert progress bar rectangles into the OT. + /// Call BEFORE gpu.chain(ot). + void renderOT(psyqo::OrderingTable& ot, + psyqo::BumpAllocator& balloc); + + /// Phase 2: Emit text via chainprintf. + /// Call AFTER gpu.chain(ot). + void renderText(psyqo::GPU& gpu); + +private: + psyqo::Font<>* m_font = nullptr; + + // Cached addresses from linker symbols + uintptr_t m_heapBase = 0; + uintptr_t m_stackTop = 0; + uint32_t m_totalAvail = 0; + + // Cached each frame for text phase + uint32_t m_lastUsedKB = 0; + uint32_t m_lastTotalKB = 0; + uint32_t m_lastPct = 0; +}; + +} // namespace psxsplash + +#endif // PSXSPLASH_MEMOVERLAY diff --git a/src/renderer.cpp b/src/renderer.cpp index 9864ff4..1bc71bb 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp @@ -17,6 +17,9 @@ #include "gtemath.hh" #include "uisystem.hh" +#ifdef PSXSPLASH_MEMOVERLAY +#include "memoverlay.hh" +#endif using namespace psyqo::fixed_point_literals; using namespace psyqo::trig_literals; @@ -277,9 +280,15 @@ void psxsplash::Renderer::Render(eastl::vector& objects) { processTriangle(obj->polygons[i], fogFarSZ, ot, balloc); } if (m_uiSystem) m_uiSystem->renderOT(m_gpu, ot, balloc); +#ifdef PSXSPLASH_MEMOVERLAY + if (m_memOverlay) m_memOverlay->renderOT(ot, balloc); +#endif m_gpu.getNextClear(clear.primitive, m_clearcolor); m_gpu.chain(clear); m_gpu.chain(ot); if (m_uiSystem) m_uiSystem->renderText(m_gpu); +#ifdef PSXSPLASH_MEMOVERLAY + if (m_memOverlay) m_memOverlay->renderText(m_gpu); +#endif m_frameCount++; } @@ -311,9 +320,15 @@ void psxsplash::Renderer::RenderWithBVH(eastl::vector& objects, con processTriangle(obj->polygons[ref.triangleIndex], fogFarSZ, ot, balloc); } if (m_uiSystem) m_uiSystem->renderOT(m_gpu, ot, balloc); +#ifdef PSXSPLASH_MEMOVERLAY + if (m_memOverlay) m_memOverlay->renderOT(ot, balloc); +#endif m_gpu.getNextClear(clear.primitive, m_clearcolor); m_gpu.chain(clear); m_gpu.chain(ot); if (m_uiSystem) m_uiSystem->renderText(m_gpu); +#ifdef PSXSPLASH_MEMOVERLAY + if (m_memOverlay) m_memOverlay->renderText(m_gpu); +#endif m_frameCount++; } @@ -756,9 +771,15 @@ void psxsplash::Renderer::RenderWithRooms(eastl::vector& objects, #endif if (m_uiSystem) m_uiSystem->renderOT(m_gpu, ot, balloc); +#ifdef PSXSPLASH_MEMOVERLAY + if (m_memOverlay) m_memOverlay->renderOT(ot, balloc); +#endif m_gpu.getNextClear(clear.primitive, m_clearcolor); m_gpu.chain(clear); m_gpu.chain(ot); if (m_uiSystem) m_uiSystem->renderText(m_gpu); +#ifdef PSXSPLASH_MEMOVERLAY + if (m_memOverlay) m_memOverlay->renderText(m_gpu); +#endif m_frameCount++; } diff --git a/src/renderer.hh b/src/renderer.hh index ab220ee..86e5402 100644 --- a/src/renderer.hh +++ b/src/renderer.hh @@ -21,6 +21,9 @@ namespace psxsplash { class UISystem; // Forward declaration +#ifdef PSXSPLASH_MEMOVERLAY +class MemOverlay; // Forward declaration +#endif struct FogConfig { bool enabled = false; @@ -58,6 +61,9 @@ class Renderer final { int16_t width, int16_t height); void SetUISystem(UISystem* ui) { m_uiSystem = ui; } +#ifdef PSXSPLASH_MEMOVERLAY + void SetMemOverlay(MemOverlay* overlay) { m_memOverlay = overlay; } +#endif psyqo::GPU& getGPU() { return m_gpu; } static Renderer& GetInstance() { @@ -84,6 +90,9 @@ class Renderer final { psyqo::Color m_clearcolor = {.r = 0, .g = 0, .b = 0}; UISystem* m_uiSystem = nullptr; +#ifdef PSXSPLASH_MEMOVERLAY + MemOverlay* m_memOverlay = nullptr; +#endif TriangleRef m_visibleRefs[MAX_VISIBLE_TRIANGLES]; int m_frameCount = 0; diff --git a/src/scenemanager.cpp b/src/scenemanager.cpp index c765dff..20e7921 100644 --- a/src/scenemanager.cpp +++ b/src/scenemanager.cpp @@ -148,6 +148,13 @@ void psxsplash::SceneManager::InitializeScene(uint8_t* splashpackData, LoadingSc Renderer::GetInstance().SetUISystem(nullptr); } +#ifdef PSXSPLASH_MEMOVERLAY + if (s_font != nullptr) { + m_memOverlay.init(s_font); + Renderer::GetInstance().SetMemOverlay(&m_memOverlay); + } +#endif + m_playerPosition = sceneSetup.playerStartPosition; playerRotationX = 0.0_pi; diff --git a/src/scenemanager.hh b/src/scenemanager.hh index 8c038a4..cc2f83f 100644 --- a/src/scenemanager.hh +++ b/src/scenemanager.hh @@ -21,6 +21,9 @@ #include "fileloader.hh" #include "cutscene.hh" #include "uisystem.hh" +#ifdef PSXSPLASH_MEMOVERLAY +#include "memoverlay.hh" +#endif namespace psxsplash { @@ -138,6 +141,9 @@ class SceneManager { // UI system (v13+) UISystem m_uiSystem; +#ifdef PSXSPLASH_MEMOVERLAY + MemOverlay m_memOverlay; +#endif psxsplash::Controls m_controls;