diff options
| author | hachem <im@hachem.wtf> | 2026-09-13 01:04:01 +0200 |
|---|---|---|
| committer | hachem <im@hachem.wtf> | 2026-09-13 01:04:01 +0200 |
| commit | 61ef54dd242d26f3668e306750e623d337978307 (patch) | |
| tree | 8c61219eac5133660f962fc43da1fdffbdd38793 /src/core/application.cpp | |
| parent | 1fa69b34a0968cf79461f37b8d9fdadba745b4d3 (diff) | |
chore: capture tool and dev env hooks
Diffstat (limited to 'src/core/application.cpp')
| -rw-r--r-- | src/core/application.cpp | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/src/core/application.cpp b/src/core/application.cpp index d04cde8..e02edb6 100644 --- a/src/core/application.cpp +++ b/src/core/application.cpp @@ -9,7 +9,12 @@ #include <glad/gl.h> +#include <algorithm> +#include <charconv> #include <chrono> +#include <cstdlib> +#include <fstream> +#include <vector> namespace Hsdbg { @@ -19,6 +24,38 @@ namespace Hsdbg constexpr float MAX_DELTA_TIME = 0.25f; constexpr double MINIMIZED_WAIT_TIMEOUT = 0.1; + + auto capture_frame(uint64_t frame, uint32_t width, uint32_t height) -> bool + { + static const char* path = std::getenv("HSDBG_CAPTURE"); + if (path == nullptr) + return false; + + static const uint64_t target = [] { + uint64_t value = 240; + if (const char* text = std::getenv("HSDBG_CAPTURE_FRAME")) + std::from_chars(text, text + std::char_traits<char>::length(text), value); + return value; + }(); + + if (frame != target) + return false; + + const size_t stride = static_cast<size_t>(width) * 3; + std::vector<unsigned char> pixels(stride * height); + glPixelStorei(GL_PACK_ALIGNMENT, 1); + glReadPixels(0, 0, static_cast<GLsizei>(width), static_cast<GLsizei>(height), + GL_RGB, GL_UNSIGNED_BYTE, pixels.data()); + + std::ofstream out(path, std::ios::binary); + out << "P6\n" << width << ' ' << height << "\n255\n"; + for (uint32_t y = height; y-- > 0;) + out.write(reinterpret_cast<const char*>(pixels.data() + y * stride), + static_cast<std::streamsize>(stride)); + + Log::info("capture: wrote '{}' ({}x{})", path, width, height); + return true; + } } Application* Application::s_instance = nullptr; @@ -109,6 +146,24 @@ namespace Hsdbg auto Application::update() -> void { m_debugger->update(); + + static const std::vector<uint64_t> step_frames = [] { + std::vector<uint64_t> frames; + const char* text = std::getenv("HSDBG_STEP_AT"); + for (const char* at = text; at != nullptr && *at != '\0';) + { + uint64_t value = 0; + const auto [next, error] = std::from_chars(at, at + std::char_traits<char>::length(at), value); + if (error != std::errc{}) + break; + frames.push_back(value); + at = *next == ',' ? next + 1 : next; + } + return frames; + }(); + + if (std::ranges::find(step_frames, m_frame_count) != step_frames.end() && m_debugger->is_stopped()) + (void)m_debugger->step_over(); } auto Application::render() -> void @@ -123,5 +178,8 @@ namespace Hsdbg m_ui->begin_frame(); m_ui->draw(*m_debugger); m_ui->end_frame(); + + if (capture_frame(m_frame_count, m_window->framebuffer_width(), m_window->framebuffer_height())) + close(); } } |
