diff --git a/src/gui/gui.cc b/src/gui/gui.cc index 9d9c22432..92d0a263c 100644 --- a/src/gui/gui.cc +++ b/src/gui/gui.cc @@ -1318,6 +1318,9 @@ void PCSX::GUI::endFrame() { if (ImGui::MenuItem(_("Hard Reset"), "Shift+F8")) { g_system->hardReset(); } + if (ImGui::MenuItem(_("Take Screenshot"))) { + saveScreenShot(); + } ImGui::EndMenu(); } ImGui::Separator(); @@ -2891,3 +2894,60 @@ void PCSX::GUI::changeScale(float scale) { m_allScales.emplace(scale); ImGui::SetCurrentFont(getMainFont()); } + +clip::image PCSX::GUI::convertScreenshotToImage(PCSX::GPU::ScreenShot&& screenshot) { + clip::image_spec spec; + spec.width = screenshot.width; + spec.height = screenshot.height; + if (screenshot.bpp == PCSX::GPU::ScreenShot::BPP_16) { + spec.bits_per_pixel = 16; + spec.bytes_per_row = screenshot.width * 2; + spec.red_mask = 0x1f; // 0x7c00; + spec.green_mask = 0x3e0; + spec.blue_mask = 0x7c00; // 0x1f; + spec.alpha_mask = 0; + spec.red_shift = 0; // 10; + spec.green_shift = 5; + spec.blue_shift = 10; // 0; + spec.alpha_shift = 0; + } else { + spec.bits_per_pixel = 24; + spec.bytes_per_row = screenshot.width * 3; + spec.red_mask = 0xff0000; + spec.green_mask = 0xff00; + spec.blue_mask = 0xff; + spec.alpha_mask = 0; + spec.red_shift = 16; + spec.green_shift = 8; + spec.blue_shift = 0; + spec.alpha_shift = 0; + } + clip::image img(screenshot.data.data(), spec); + return img.to_rgba8888(); +} + +bool PCSX::GUI::writeImagePNG(std::string filename, clip::image&& img) { return img.export_to_png(filename); } + +std::string PCSX::GUI::getDateString() { + auto now = std::chrono::system_clock::now(); + auto in_time_t = std::chrono::system_clock::to_time_t(now); + + auto local_time = std::localtime(&in_time_t); + + std::stringstream ss; + ss << std::put_time(local_time, "%Y-%m-%d-%H-%M-%S"); + + std::string datetime_string = ss.str(); + + return datetime_string; +} + +bool PCSX::GUI::saveScreenShot() { + std::filesystem::path path = + g_system->getPersistentDir() / (getSaveStatePrefix(true) + getDateString() + ".png"); + auto screenshot = g_emulator->m_gpu->takeScreenShot(); + clip::image img = convertScreenshotToImage(std::move(screenshot)); + bool success = writeImagePNG(path.string(), std::move(img)); + + return success; +} diff --git a/src/gui/gui.h b/src/gui/gui.h index 29f73abd7..28c48f9f2 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include #include #include @@ -419,6 +421,7 @@ class GUI final : public UI { std::string buildSaveStateFilename(int i); std::string buildSaveStateFilename(std::string name); bool saveStateExists(std::filesystem::path filename); + bool saveScreenShot(); private: void applyTheme(int theme); @@ -426,6 +429,9 @@ class GUI final : public UI { void monoTheme(); void draculaTheme(); void oliveTheme(); + std::string getDateString(); + clip::image convertScreenshotToImage(PCSX::GPU::ScreenShot&& screenshot); + bool writeImagePNG(std::string filename, clip::image&& img); Notifier m_notifier = {l_("Notification")}; Widgets::Console m_luaConsole = {settings.get().value};