aboutsummaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/application.cpp63
1 files changed, 63 insertions, 0 deletions
diff --git a/src/core/application.cpp b/src/core/application.cpp
index 54ee788..8832499 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,41 @@ namespace Hsdbg
constexpr float MAX_DELTA_TIME = 0.25f;
constexpr double MINIMIZED_WAIT_TIMEOUT = 0.1;
+
+ // dev aid: HSDBG_CAPTURE=<file.ppm> writes the frame numbered
+ // HSDBG_CAPTURE_FRAME (default 240) as a binary ppm; returns true on
+ // that frame so the caller can quit
+ 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 +149,26 @@ namespace Hsdbg
auto Application::update() -> void
{
m_debugger->update();
+
+ // dev aid: HSDBG_STEP_AT=<frame>[,<frame>…] steps over a line on those
+ // frames while stopped, so a capture can show a target that has moved
+ 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
@@ -125,5 +185,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();
}
}