naomi: save printer output as a screenshot
Use hostfs::saveScreenshot()
This commit is contained in:
parent
e270621a03
commit
49ad2b6864
|
@ -341,6 +341,11 @@ public:
|
|||
{
|
||||
if (page.empty())
|
||||
return false;
|
||||
const auto& appendData = [](void *context, void *data, int size) {
|
||||
std::vector<u8>& v = *(std::vector<u8> *)context;
|
||||
v.insert(v.end(), (u8 *)data, (u8 *)data + size);
|
||||
};
|
||||
stbi_flip_vertically_on_write(0);
|
||||
if (settings.content.gameId.substr(0, 4) == "F355")
|
||||
{
|
||||
u8 *data = nullptr;
|
||||
|
@ -383,15 +388,29 @@ public:
|
|||
*p = 0xff000000;
|
||||
p++;
|
||||
}
|
||||
stbi_write_png(filename.c_str(), printerWidth, lines, 4, data, printerWidth * 4);
|
||||
std::vector<u8> pngData;
|
||||
stbi_write_png_to_func(appendData, &pngData, printerWidth, lines, 4, data, printerWidth * 4);
|
||||
stbi_image_free(data);
|
||||
try {
|
||||
hostfs::saveScreenshot(filename, pngData);
|
||||
} catch (const FlycastException& e) {
|
||||
ERROR_LOG(NAOMI, "Error saving print out: %s", e.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (u8& b : page)
|
||||
b = 0xff - b;
|
||||
stbi_write_png(filename.c_str(), printerWidth, lines, 1, &page[0], printerWidth);
|
||||
std::vector<u8> pngData;
|
||||
stbi_write_png_to_func(appendData, &pngData, printerWidth, lines, 1, &page[0], printerWidth);
|
||||
try {
|
||||
hostfs::saveScreenshot(filename, pngData);
|
||||
} catch (const FlycastException& e) {
|
||||
ERROR_LOG(NAOMI, "Error saving print out: %s", e.what());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -827,12 +846,16 @@ private:
|
|||
state = Default;
|
||||
if (bitmapWriter && bitmapWriter->isDirty())
|
||||
{
|
||||
// TODO save to ~/Pictures instead
|
||||
std::string s = get_writable_data_path(settings.content.gameId + "-results.png");
|
||||
bitmapWriter->save(s);
|
||||
std::string date = timeToISO8601(time(nullptr));
|
||||
std::replace(date.begin(), date.end(), '/', '-');
|
||||
std::replace(date.begin(), date.end(), ':', '-');
|
||||
std::string s = settings.content.gameId + " - " + date + ".png";
|
||||
const bool success = bitmapWriter->save(s);
|
||||
bitmapWriter.reset();
|
||||
os_notify("Print out saved", 5000, s.c_str());
|
||||
NOTICE_LOG(NAOMI, "%s", s.c_str());
|
||||
if (success) {
|
||||
os_notify("Print out saved", 5000, s.c_str());
|
||||
NOTICE_LOG(NAOMI, "%s", s.c_str());
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'K': // Set Kanji mode
|
||||
|
|
|
@ -221,3 +221,20 @@ u64 getTimeMs()
|
|||
|
||||
return std::chrono::duration_cast<std::chrono::milliseconds>(now - start).count();
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
static struct tm *localtime_r(const time_t *_clock, struct tm *_result)
|
||||
{
|
||||
return localtime_s(_result, _clock) ? nullptr : _result;
|
||||
}
|
||||
#endif
|
||||
|
||||
std::string timeToISO8601(time_t time)
|
||||
{
|
||||
tm t;
|
||||
if (localtime_r(&time, &t) == nullptr)
|
||||
return {};
|
||||
std::string s(32, '\0');
|
||||
s.resize(snprintf(s.data(), 32, "%04d/%02d/%02d %02d:%02d:%02d", t.tm_year + 1900, t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec));
|
||||
return s;
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <vector>
|
||||
#include <functional>
|
||||
#include <cassert>
|
||||
#include <time.h>
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include <sys/mman.h>
|
||||
|
@ -201,6 +202,7 @@ public:
|
|||
};
|
||||
|
||||
u64 getTimeMs();
|
||||
std::string timeToISO8601(time_t time);
|
||||
|
||||
class ThreadRunner
|
||||
{
|
||||
|
|
|
@ -604,23 +604,6 @@ static void getScreenshot(std::vector<u8>& data, int width = 0)
|
|||
stbi_write_png_to_func(appendVectorData, &data, width, height, 3, &rawData[0], 0);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
static struct tm *localtime_r(const time_t *_clock, struct tm *_result)
|
||||
{
|
||||
return localtime_s(_result, _clock) ? nullptr : _result;
|
||||
}
|
||||
#endif
|
||||
|
||||
static std::string timeToString(time_t time)
|
||||
{
|
||||
tm t;
|
||||
if (localtime_r(&time, &t) == nullptr)
|
||||
return {};
|
||||
std::string s(32, '\0');
|
||||
s.resize(snprintf(s.data(), 32, "%04d/%02d/%02d %02d:%02d:%02d", t.tm_year + 1900, t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec));
|
||||
return s;
|
||||
}
|
||||
|
||||
static void savestate()
|
||||
{
|
||||
// TODO save state async: png compression, savestate file compression/write
|
||||
|
@ -795,7 +778,7 @@ static void gui_display_commands()
|
|||
if (savestateDate == 0)
|
||||
ImGui::TextColored(gray, "Empty");
|
||||
else
|
||||
ImGui::TextColored(gray, "%s", timeToString(savestateDate).c_str());
|
||||
ImGui::TextColored(gray, "%s", timeToISO8601(savestateDate).c_str());
|
||||
}
|
||||
savestatePic.draw(ScaledVec2(buttonWidth, 0.f));
|
||||
}
|
||||
|
@ -3764,7 +3747,7 @@ void gui_takeScreenshot()
|
|||
if (!game_started)
|
||||
return;
|
||||
uiThreadRunner.runOnThread([]() {
|
||||
std::string date = timeToString(time(nullptr));
|
||||
std::string date = timeToISO8601(time(nullptr));
|
||||
std::replace(date.begin(), date.end(), '/', '-');
|
||||
std::replace(date.begin(), date.end(), ':', '-');
|
||||
std::string name = "Flycast-" + date + ".png";
|
||||
|
|
|
@ -19,6 +19,9 @@
|
|||
#include "oslib/oslib.h"
|
||||
#include "stdclass.h"
|
||||
#include "file/file_path.h"
|
||||
#ifndef _WIN32
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
const char *retro_get_system_directory();
|
||||
|
||||
|
@ -128,6 +131,27 @@ std::string getTextureDumpPath()
|
|||
+ "texdump" + std::string(path_default_slash());
|
||||
}
|
||||
|
||||
std::string getScreenshotsPath()
|
||||
{
|
||||
// Unfortunately retroarch doesn't expose its "screenshots" path
|
||||
return std::string(retro_get_system_directory()) + "/dc";
|
||||
}
|
||||
|
||||
void saveScreenshot(const std::string& name, const std::vector<u8>& data)
|
||||
{
|
||||
std::string path = getScreenshotsPath();
|
||||
path += "/" + name;
|
||||
FILE *f = nowide::fopen(path.c_str(), "wb");
|
||||
if (f == nullptr)
|
||||
throw FlycastException(path);
|
||||
if (std::fwrite(&data[0], data.size(), 1, f) != 1) {
|
||||
std::fclose(f);
|
||||
unlink(path.c_str());
|
||||
throw FlycastException(path);
|
||||
}
|
||||
std::fclose(f);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#if defined(_WIN32) || defined(__APPLE__)
|
||||
|
|
Loading…
Reference in New Issue