diff --git a/include/PICA/gpu.hpp b/include/PICA/gpu.hpp index 5f74bdcc..2de48c01 100644 --- a/include/PICA/gpu.hpp +++ b/include/PICA/gpu.hpp @@ -88,6 +88,7 @@ class GPU { void initGraphicsContext() { renderer.initGraphicsContext(); } void getGraphicsContext() { renderer.getGraphicsContext(); } void display() { renderer.display(); } + void screenshot(const std::string& name) { renderer.screenshot(name); } void fireDMA(u32 dest, u32 source, u32 size); void reset(); diff --git a/include/emulator.hpp b/include/emulator.hpp index 27c23bad..3985c613 100644 --- a/include/emulator.hpp +++ b/include/emulator.hpp @@ -69,7 +69,6 @@ class Emulator { void reset(); void run(); void runFrame(); - void screenshot(const std::string& name); bool loadROM(const std::filesystem::path& path); bool loadNCSD(const std::filesystem::path& path, ROMType type); diff --git a/include/renderer_gl/renderer_gl.hpp b/include/renderer_gl/renderer_gl.hpp index 8258c4c7..07f8a63c 100644 --- a/include/renderer_gl/renderer_gl.hpp +++ b/include/renderer_gl/renderer_gl.hpp @@ -1,6 +1,7 @@ #pragma once #include #include +#include #include "PICA/float_types.hpp" #include "gl_state.hpp" @@ -88,6 +89,9 @@ class Renderer { void displayTransfer(u32 inputAddr, u32 outputAddr, u32 inputSize, u32 outputSize, u32 flags); // Perform display transfer void drawVertices(PICA::PrimType primType, std::span vertices); // Draw the given vertices + // Take a screenshot of the screen and store it in a file + void screenshot(const std::string& name); + void setFBSize(u32 width, u32 height) { fbSize.x() = width; fbSize.y() = height; diff --git a/src/core/renderer_gl/renderer_gl.cpp b/src/core/renderer_gl/renderer_gl.cpp index 72f346bc..73fb0919 100644 --- a/src/core/renderer_gl/renderer_gl.cpp +++ b/src/core/renderer_gl/renderer_gl.cpp @@ -669,7 +669,7 @@ void Renderer::initGraphicsContext() { dummyVAO.create(); // Create texture and framebuffer for the 3DS screen - const u32 screenTextureWidth = 2 * 400; // Top screen is 400 pixels wide, bottom is 320 + const u32 screenTextureWidth = 400; // Top screen is 400 pixels wide, bottom is 320 const u32 screenTextureHeight = 2 * 240; // Both screens are 240 pixels tall glGenTextures(1,&lightLUTTextureArray); @@ -1028,4 +1028,29 @@ void Renderer::displayTransfer(u32 inputAddr, u32 outputAddr, u32 inputSize, u32 } OpenGL::draw(OpenGL::TriangleStrip, 4); // Actually draw our 3DS screen +} + +void Renderer::screenshot(const std::string& name) { + constexpr uint width = 400; + constexpr uint height = 2 * 240; + + std::vector pixels, flippedPixels; + pixels.resize(width * height * 4); + flippedPixels.resize(pixels.size());; + + OpenGL::bindScreenFramebuffer(); + glReadPixels(0, 0, width, height, GL_BGRA, GL_UNSIGNED_BYTE, pixels.data()); + + // Flip the image vertically + for (int y = 0; y < height; y++) { + memcpy(&flippedPixels[y * width * 4], &pixels[(height - y - 1) * width * 4], width * 4); + // Swap R and B channels + for (int x = 0; x < width; x++) { + std::swap(flippedPixels[y * width * 4 + x * 4 + 0], flippedPixels[y * width * 4 + x * 4 + 2]); + // Set alpha to 0xFF + flippedPixels[y * width * 4 + x * 4 + 3] = 0xFF; + } + } + + stbi_write_png(name.c_str(), width, height, 4, flippedPixels.data(), 0); } \ No newline at end of file diff --git a/src/emulator.cpp b/src/emulator.cpp index ef30088f..1e30e073 100644 --- a/src/emulator.cpp +++ b/src/emulator.cpp @@ -82,27 +82,6 @@ void Emulator::reset() { } } -void Emulator::screenshot(const std::string& name) { - std::vector pixels, flippedPixels; - pixels.resize(width * height * 4); - flippedPixels.resize(width * height * 4); - - glReadPixels(0, 0, width, height, GL_BGRA, GL_UNSIGNED_BYTE, pixels.data()); - - // Flip the image vertically - for (int y = 0; y < height; y++) { - memcpy(&flippedPixels[y * width * 4], &pixels[(height - y - 1) * width * 4], width * 4); - // Swap R and B channels - for (int x = 0; x < width; x++) { - std::swap(flippedPixels[y * width * 4 + x * 4 + 0], flippedPixels[y * width * 4 + x * 4 + 2]); - // Set alpha to 0xFF - flippedPixels[y * width * 4 + x * 4 + 3] = 0xFF; - } - } - - stbi_write_png(name.c_str(), width, height, 4, flippedPixels.data(), 0); -} - void Emulator::step() {} void Emulator::render() {} @@ -428,28 +407,27 @@ void Emulator::pollHttpServer() { if (httpServer.pendingAction) { switch (httpServer.action) { - case HttpAction::Screenshot: { - screenshot(HttpServer::httpServerScreenshotPath); + case HttpAction::Screenshot: + gpu.screenshot(HttpServer::httpServerScreenshotPath); break; - } - case HttpAction::PressKey: { + + case HttpAction::PressKey: if (httpServer.pendingKey != 0) { srv.pressKey(httpServer.pendingKey); httpServer.pendingKey = 0; } break; - } - case HttpAction::ReleaseKey: { + + case HttpAction::ReleaseKey: if (httpServer.pendingKey != 0) { srv.releaseKey(httpServer.pendingKey); httpServer.pendingKey = 0; } break; - } - case HttpAction::None: { - break; - } + + case HttpAction::None: break; } + httpServer.action = HttpAction::None; httpServer.pendingAction = false; httpServer.pendingAction.notify_all(); diff --git a/src/httpserver.cpp b/src/httpserver.cpp index 570a3987..fa7ad763 100644 --- a/src/httpserver.cpp +++ b/src/httpserver.cpp @@ -1,11 +1,11 @@ #ifdef PANDA3DS_ENABLE_HTTP_SERVER #include "httpserver.hpp" -#include -#include -#include #include +#include #include +#include +#include #include "httplib.h" #include "services/hid.hpp" @@ -42,9 +42,7 @@ void HttpServer::startHttpServer() { std::thread http_thread([this]() { httplib::Server server; - server.Get("/ping", [](const httplib::Request&, httplib::Response& response) { - response.set_content("pong", "text/plain"); - }); + server.Get("/ping", [](const httplib::Request&, httplib::Response& response) { response.set_content("pong", "text/plain"); }); server.Get("/screen", [this](const httplib::Request&, httplib::Response& response) { { @@ -61,9 +59,10 @@ void HttpServer::startHttpServer() { server.Get("/input", [this](const httplib::Request& request, httplib::Response& response) { bool ok = false; - for (auto& [keyStr, value]: request.params) { + for (auto& [keyStr, value] : request.params) { auto key = stringToKey(keyStr); printf("Param: %s\n", keyStr.c_str()); + if (key != 0) { std::scoped_lock lock(actionMutex); pendingAction = true; @@ -97,6 +96,7 @@ void HttpServer::startHttpServer() { printf("Starting HTTP server on port 1234\n"); server.listen("localhost", 1234); }); + http_thread.detach(); }