Skip to content
Snippets Groups Projects
Commit 080a2d71 authored by Emmanuel Gil Peyrot's avatar Emmanuel Gil Peyrot
Browse files

Loader: Split SMDH into its own header and import helpers from QGameList

Also rewrite Qt wrappers to use those.
parent 314ce5e5
No related branches found
No related tags found
No related merge requests found
...@@ -15,52 +15,21 @@ ...@@ -15,52 +15,21 @@
#include "common/string_util.h" #include "common/string_util.h"
#include "common/color.h" #include "common/color.h"
#include "core/loader/loader.h" #include "core/loader/smdh.h"
#include "video_core/utils.h" #include "video_core/utils.h"
/**
* Tests if data is a valid SMDH by its length and magic number.
* @param smdh_data data buffer to test
* @return bool test result
*/
static bool IsValidSMDH(const std::vector<u8>& smdh_data) {
if (smdh_data.size() < sizeof(Loader::SMDH))
return false;
u32 magic;
memcpy(&magic, smdh_data.data(), 4);
return Loader::MakeMagic('S', 'M', 'D', 'H') == magic;
}
/** /**
* Gets game icon from SMDH * Gets game icon from SMDH
* @param sdmh SMDH data * @param sdmh SMDH data
* @param large If true, returns large icon (48x48), otherwise returns small icon (24x24) * @param large If true, returns large icon (48x48), otherwise returns small icon (24x24)
* @return QPixmap game icon * @return QPixmap game icon
*/ */
static QPixmap GetIconFromSMDH(const Loader::SMDH& smdh, bool large) { static QPixmap GetQPixmapFromSMDH(const Loader::SMDH& smdh, bool large) {
u32 size; std::vector<u16> icon_data = smdh.GetIcon(large);
const u8* icon_data; const uchar* data = reinterpret_cast<const uchar*>(icon_data.data());
int size = large ? 48 : 24;
if (large) { QImage icon(data, size, size, QImage::Format::Format_RGB16);
size = 48;
icon_data = smdh.large_icon.data();
} else {
size = 24;
icon_data = smdh.small_icon.data();
}
QImage icon(size, size, QImage::Format::Format_RGB888);
for (u32 x = 0; x < size; ++x) {
for (u32 y = 0; y < size; ++y) {
u32 coarse_y = y & ~7;
auto v = Color::DecodeRGB565(
icon_data + VideoCore::GetMortonOffset(x, y, 2) + coarse_y * size * 2);
icon.setPixel(x, y, qRgb(v.r(), v.g(), v.b()));
}
}
return QPixmap::fromImage(icon); return QPixmap::fromImage(icon);
} }
...@@ -82,8 +51,8 @@ static QPixmap GetDefaultIcon(bool large) { ...@@ -82,8 +51,8 @@ static QPixmap GetDefaultIcon(bool large) {
* @param language title language * @param language title language
* @return QString short title * @return QString short title
*/ */
static QString GetShortTitleFromSMDH(const Loader::SMDH& smdh, Loader::SMDH::TitleLanguage language) { static QString GetQStringShortTitleFromSMDH(const Loader::SMDH& smdh, Loader::SMDH::TitleLanguage language) {
return QString::fromUtf16(smdh.titles[static_cast<int>(language)].short_title.data()); return QString::fromUtf16(smdh.GetShortTitle(language).data());
} }
class GameListItem : public QStandardItem { class GameListItem : public QStandardItem {
...@@ -112,7 +81,7 @@ public: ...@@ -112,7 +81,7 @@ public:
{ {
setData(game_path, FullPathRole); setData(game_path, FullPathRole);
if (!IsValidSMDH(smdh_data)) { if (!Loader::IsValidSMDH(smdh_data)) {
// SMDH is not valid, set a default icon // SMDH is not valid, set a default icon
setData(GetDefaultIcon(true), Qt::DecorationRole); setData(GetDefaultIcon(true), Qt::DecorationRole);
return; return;
...@@ -122,10 +91,10 @@ public: ...@@ -122,10 +91,10 @@ public:
memcpy(&smdh, smdh_data.data(), sizeof(Loader::SMDH)); memcpy(&smdh, smdh_data.data(), sizeof(Loader::SMDH));
// Get icon from SMDH // Get icon from SMDH
setData(GetIconFromSMDH(smdh, true), Qt::DecorationRole); setData(GetQPixmapFromSMDH(smdh, true), Qt::DecorationRole);
// Get title form SMDH // Get title form SMDH
setData(GetShortTitleFromSMDH(smdh, Loader::SMDH::TitleLanguage::English), TitleRole); setData(GetQStringShortTitleFromSMDH(smdh, Loader::SMDH::TitleLanguage::English), TitleRole);
} }
QVariant data(int role) const override { QVariant data(int role) const override {
......
...@@ -121,6 +121,7 @@ set(SRCS ...@@ -121,6 +121,7 @@ set(SRCS
loader/elf.cpp loader/elf.cpp
loader/loader.cpp loader/loader.cpp
loader/ncch.cpp loader/ncch.cpp
loader/smdh.cpp
tracer/recorder.cpp tracer/recorder.cpp
memory.cpp memory.cpp
settings.cpp settings.cpp
...@@ -256,6 +257,7 @@ set(HEADERS ...@@ -256,6 +257,7 @@ set(HEADERS
loader/elf.h loader/elf.h
loader/loader.h loader/loader.h
loader/ncch.h loader/ncch.h
loader/smdh.h
tracer/recorder.h tracer/recorder.h
tracer/citrace.h tracer/citrace.h
memory.h memory.h
......
...@@ -10,10 +10,8 @@ ...@@ -10,10 +10,8 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "common/common_funcs.h"
#include "common/common_types.h" #include "common/common_types.h"
#include "common/file_util.h" #include "common/file_util.h"
#include "common/swap.h"
namespace Kernel { namespace Kernel {
struct AddressMapping; struct AddressMapping;
...@@ -80,51 +78,6 @@ constexpr u32 MakeMagic(char a, char b, char c, char d) { ...@@ -80,51 +78,6 @@ constexpr u32 MakeMagic(char a, char b, char c, char d) {
return a | b << 8 | c << 16 | d << 24; return a | b << 8 | c << 16 | d << 24;
} }
/// SMDH data structure that contains titles, icons etc. See https://www.3dbrew.org/wiki/SMDH
struct SMDH {
u32_le magic;
u16_le version;
INSERT_PADDING_BYTES(2);
struct Title {
std::array<u16, 0x40> short_title;
std::array<u16, 0x80> long_title;
std::array<u16, 0x40> publisher;
};
std::array<Title, 16> titles;
std::array<u8, 16> ratings;
u32_le region_lockout;
u32_le match_maker_id;
u64_le match_maker_bit_id;
u32_le flags;
u16_le eula_version;
INSERT_PADDING_BYTES(2);
float_le banner_animation_frame;
u32_le cec_id;
INSERT_PADDING_BYTES(8);
std::array<u8, 0x480> small_icon;
std::array<u8, 0x1200> large_icon;
/// indicates the language used for each title entry
enum class TitleLanguage {
Japanese = 0,
English = 1,
French = 2,
German = 3,
Italian = 4,
Spanish = 5,
SimplifiedChinese = 6,
Korean= 7,
Dutch = 8,
Portuguese = 9,
Russian = 10,
TraditionalChinese = 11
};
};
static_assert(sizeof(SMDH) == 0x36C0, "SMDH structure size is wrong");
/// Interface for loading an application /// Interface for loading an application
class AppLoader : NonCopyable { class AppLoader : NonCopyable {
public: public:
......
// Copyright 2016 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <cstring>
#include <vector>
#include "common/common_types.h"
#include "core/loader/loader.h"
#include "core/loader/smdh.h"
#include "video_core/utils.h"
namespace Loader {
bool IsValidSMDH(const std::vector<u8>& smdh_data) {
if (smdh_data.size() < sizeof(Loader::SMDH))
return false;
u32 magic;
memcpy(&magic, smdh_data.data(), sizeof(u32));
return Loader::MakeMagic('S', 'M', 'D', 'H') == magic;
}
std::vector<u16> SMDH::GetIcon(bool large) const {
u32 size;
const u8* icon_data;
if (large) {
size = 48;
icon_data = large_icon.data();
} else {
size = 24;
icon_data = small_icon.data();
}
std::vector<u16> icon(size * size);
for (u32 x = 0; x < size; ++x) {
for (u32 y = 0; y < size; ++y) {
u32 coarse_y = y & ~7;
const u8* pixel = icon_data + VideoCore::GetMortonOffset(x, y, 2) + coarse_y * size * 2;
icon[x + size * y] = (pixel[1] << 8) + pixel[0];
}
}
return icon;
}
std::array<u16, 0x40> SMDH::GetShortTitle(Loader::SMDH::TitleLanguage language) const {
return titles[static_cast<int>(language)].short_title;
}
} // namespace
// Copyright 2016 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <array>
#include <vector>
#include "common/common_funcs.h"
#include "common/common_types.h"
#include "common/swap.h"
namespace Loader {
/**
* Tests if data is a valid SMDH by its length and magic number.
* @param smdh_data data buffer to test
* @return bool test result
*/
bool IsValidSMDH(const std::vector<u8>& smdh_data);
/// SMDH data structure that contains titles, icons etc. See https://www.3dbrew.org/wiki/SMDH
struct SMDH {
u32_le magic;
u16_le version;
INSERT_PADDING_BYTES(2);
struct Title {
std::array<u16, 0x40> short_title;
std::array<u16, 0x80> long_title;
std::array<u16, 0x40> publisher;
};
std::array<Title, 16> titles;
std::array<u8, 16> ratings;
u32_le region_lockout;
u32_le match_maker_id;
u64_le match_maker_bit_id;
u32_le flags;
u16_le eula_version;
INSERT_PADDING_BYTES(2);
float_le banner_animation_frame;
u32_le cec_id;
INSERT_PADDING_BYTES(8);
std::array<u8, 0x480> small_icon;
std::array<u8, 0x1200> large_icon;
/// indicates the language used for each title entry
enum class TitleLanguage {
Japanese = 0,
English = 1,
French = 2,
German = 3,
Italian = 4,
Spanish = 5,
SimplifiedChinese = 6,
Korean= 7,
Dutch = 8,
Portuguese = 9,
Russian = 10,
TraditionalChinese = 11
};
/**
* Gets game icon from SMDH
* @param large If true, returns large icon (48x48), otherwise returns small icon (24x24)
* @return vector of RGB565 data
*/
std::vector<u16> GetIcon(bool large) const;
/**
* Gets the short game title from SMDH
* @param language title language
* @return UTF-16 array of the short title
*/
std::array<u16, 0x40> GetShortTitle(Loader::SMDH::TitleLanguage language) const;
};
static_assert(sizeof(SMDH) == 0x36C0, "SMDH structure size is wrong");
} // namespace
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment