diff options
| author | crueter <crueter@eden-emu.dev> | 2026-05-20 04:49:16 +0200 |
|---|---|---|
| committer | crueter <crueter@eden-emu.dev> | 2026-05-20 04:49:16 +0200 |
| commit | feb8c5f88eae046c1b76f46e4fa103a844fb0f23 (patch) | |
| tree | 70f71937a8930c1a5b562f69047e35491d6156b4 /src/qt_common/util/game.cpp | |
| parent | 300a646a34b6729879e3fb71d53e625a09683bb2 (diff) | |
[desktop] More qt_common reorganization (#3916)
Ported from QML branch.
Main "big" change is that EmuThread is now a shared state in QtCommon,
not individually managed/passed around by GRenderWindow and MainWindow.
Signed-off-by: crueter <crueter@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3916
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Diffstat (limited to 'src/qt_common/util/game.cpp')
| -rw-r--r-- | src/qt_common/util/game.cpp | 109 |
1 files changed, 108 insertions, 1 deletions
diff --git a/src/qt_common/util/game.cpp b/src/qt_common/util/game.cpp index e037fdae6c..ddbe979765 100644 --- a/src/qt_common/util/game.cpp +++ b/src/qt_common/util/game.cpp @@ -11,7 +11,6 @@ #include "qt_common/abstract/frontend.h" #include "qt_common/config/uisettings.h" #include "qt_common/qt_common.h" -#include "yuzu/util/util.h" #include <QDesktopServices> #include <QStandardPaths> @@ -22,6 +21,7 @@ #include <windows.h> #include "common/scope_exit.h" #include "common/string_util.h" +#include "common/fs/file.h" #else #include <fstream> #include "fmt/ostream.h" @@ -367,6 +367,7 @@ void ResetMetadata(bool show_message) { // Uhhh // +// TODO(crueter): Make QtCommon::Shortcut // Messages in pre-defined message boxes for less code spaghetti inline constexpr bool CreateShortcutMessagesGUI(ShortcutMessages imsg, const QString& game_title) { int result = 0; @@ -533,4 +534,110 @@ void CreateHomeMenuShortcut(ShortcutTarget target) { CreateShortcut(game_path, QLaunchId, "Switch Home Menu", target, "-qlaunch", false); } +bool SaveIconToFile(const std::filesystem::path& icon_path, const QImage& image) { +#if defined(WIN32) +#pragma pack(push, 2) + struct IconDir { + WORD id_reserved; + WORD id_type; + WORD id_count; + }; + + struct IconDirEntry { + BYTE width; + BYTE height; + BYTE color_count; + BYTE reserved; + WORD planes; + WORD bit_count; + DWORD bytes_in_res; + DWORD image_offset; + }; +#pragma pack(pop) + + const QImage source_image = image.convertToFormat(QImage::Format_RGB32); + constexpr std::array<int, 7> scale_sizes{256, 128, 64, 48, 32, 24, 16}; + constexpr int bytes_per_pixel = 4; + + const IconDir icon_dir{ + .id_reserved = 0, + .id_type = 1, + .id_count = static_cast<WORD>(scale_sizes.size()), + }; + + Common::FS::IOFile icon_file(icon_path.string(), Common::FS::FileAccessMode::Write, + Common::FS::FileType::BinaryFile); + if (!icon_file.IsOpen()) { + return false; + } + + if (!icon_file.Write(icon_dir)) { + return false; + } + + std::size_t image_offset = sizeof(IconDir) + (sizeof(IconDirEntry) * scale_sizes.size()); + for (std::size_t i = 0; i < scale_sizes.size(); i++) { + const int image_size = scale_sizes[i] * scale_sizes[i] * bytes_per_pixel; + const IconDirEntry icon_entry{ + .width = static_cast<BYTE>(scale_sizes[i]), + .height = static_cast<BYTE>(scale_sizes[i]), + .color_count = 0, + .reserved = 0, + .planes = 1, + .bit_count = bytes_per_pixel * 8, + .bytes_in_res = static_cast<DWORD>(sizeof(BITMAPINFOHEADER) + image_size), + .image_offset = static_cast<DWORD>(image_offset), + }; + image_offset += icon_entry.bytes_in_res; + if (!icon_file.Write(icon_entry)) { + return false; + } + } + + for (std::size_t i = 0; i < scale_sizes.size(); i++) { + const QImage scaled_image = source_image.scaled( + scale_sizes[i], scale_sizes[i], Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + const BITMAPINFOHEADER info_header{ + .biSize = sizeof(BITMAPINFOHEADER), + .biWidth = scaled_image.width(), + .biHeight = scaled_image.height() * 2, + .biPlanes = 1, + .biBitCount = bytes_per_pixel * 8, + .biCompression = BI_RGB, + .biSizeImage{}, + .biXPelsPerMeter{}, + .biYPelsPerMeter{}, + .biClrUsed{}, + .biClrImportant{}, + }; + + if (!icon_file.Write(info_header)) { + return false; + } + + for (int y = 0; y < scaled_image.height(); y++) { + const auto* line = scaled_image.scanLine(scaled_image.height() - 1 - y); + std::vector<u8> line_data(scaled_image.width() * bytes_per_pixel); + std::memcpy(line_data.data(), line, line_data.size()); + if (!icon_file.Write(line_data)) { + return false; + } + } + } + icon_file.Close(); + + return true; +#elif defined(__unix__) && !defined(__APPLE__) && !defined(__ANDROID__) + // Convert and write the icon as a PNG + if (!image.save(QString::fromStdString(icon_path.string()))) { + LOG_ERROR(Frontend, "Could not write icon as PNG to file"); + } else { + LOG_INFO(Frontend, "Wrote an icon to {}", icon_path.string()); + } + return true; +#else + return false; +#endif +} + } // namespace QtCommon::Game |
