diff --git a/src/gui/gui.cc b/src/gui/gui.cc index a30a26dd2..711659fc0 100644 --- a/src/gui/gui.cc +++ b/src/gui/gui.cc @@ -1426,6 +1426,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(); @@ -3102,3 +3105,60 @@ void PCSX::GUI::changeScale(float scale) { } } } + +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 a0ce60a01..ef981970d 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -28,6 +28,8 @@ #include #include #include +#include +#include #include #include #include @@ -458,6 +460,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); @@ -465,6 +468,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};