Load DS icons (#251)

* Start loading DS icon

* Cart is never cached

* Handle positioning and fix log

* Center icon on the bottom screen as well

* allocate dsIcon in main thread

* fix ds icons
This commit is contained in:
Bernardo Giordano 2019-10-07 22:09:21 +02:00 committed by GitHub
parent 31e9f6ba8a
commit d5c5949f65
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 74 additions and 21 deletions

View file

@ -2,5 +2,4 @@
checkbox.png
checkpoint.png
noicon.png
twlcart.png
star.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 265 B

View file

@ -47,7 +47,6 @@ namespace Gui {
void drawPulsingOutline(u32 x, u32 y, u16 w, u16 h, u8 size, u32 color);
void drawOutline(u32 x, u32 y, u16 w, u16 h, u8 size, u32 color);
C2D_Image TWLIcon(void);
C2D_Image noIcon(void);
}

View file

@ -49,6 +49,8 @@ extern "C" {
class Title {
public:
~Title(void);
bool accessibleSave(void);
bool accessibleExtdata(void);
FS_CardType cardType(void);

View file

@ -112,7 +112,13 @@ void MainScreen::drawTop(void) const
C2D_DrawText(&timeText, C2D_WithColor, 4.0f, 3.0f, 0.5f, 0.45f, 0.45f, COLOR_GREY_LIGHT);
for (size_t k = hid.page() * entries; k < hid.page() * entries + max; k++) {
C2D_DrawImageAt(icon(k), selectorX(k) + 1, selectorY(k) + 1, 0.5f, NULL, 1.0f, 1.0f);
C2D_Image titleIcon = icon(k);
if (titleIcon.subtex->width == 48) {
C2D_DrawImageAt(titleIcon, selectorX(k) + 1, selectorY(k) + 1, 0.5f, NULL, 1.0f, 1.0f);
}
else {
C2D_DrawImageAt(titleIcon, selectorX(k) + 9, selectorY(k) + 9, 0.5f, NULL, 1.0f, 1.0f);
}
}
if (getTitleCount() > 0) {
@ -224,7 +230,12 @@ void MainScreen::drawBottom(void) const
C2D_DrawText(&media, C2D_WithColor, 75, 47 + longDescHeight, 0.5f, 0.5f, 0.5f, COLOR_WHITE);
C2D_DrawRectSolid(260, 27, 0.5f, 52, 52, COLOR_BLACK);
C2D_DrawImageAt(title.icon(), 262, 29, 0.5f, NULL, 1.0f, 1.0f);
if (title.icon().subtex->width == 48) {
C2D_DrawImageAt(title.icon(), 262, 29, 0.5f, NULL, 1.0f, 1.0f);
}
else {
C2D_DrawImageAt(title.icon(), 262 + 8, 29 + 8, 0.5f, NULL, 1.0f, 1.0f);
}
C2D_DrawRectSolid(4, 100, 0.5f, 312, 114, COLOR_GREY_DARK);
directoryList->draw(g_bottomScrollEnabled);

View file

@ -26,11 +26,6 @@
#include "gui.hpp"
C2D_Image Gui::TWLIcon(void)
{
return C2D_SpriteSheetGetImage(spritesheet, sprites_twlcart_idx);
}
C2D_Image Gui::noIcon(void)
{
return C2D_SpriteSheetGetImage(spritesheet, sprites_noicon_idx);

View file

@ -35,6 +35,49 @@ static std::vector<Title> titleExtdatas;
static void exportTitleListCache(std::vector<Title>& list, const std::u16string& path);
static void importTitleListCache(void);
static constexpr Tex3DS_SubTexture dsIconSubt3x = {32, 32, 0.0f, 1.0f, 1.0f, 0.0f};
static C2D_Image dsIcon = {nullptr, &dsIconSubt3x};
static void loadDSIcon(u8* banner)
{
static constexpr int WIDTH_POW2 = 32;
static constexpr int HEIGHT_POW2 = 32;
if (!dsIcon.tex) {
dsIcon.tex = new C3D_Tex;
C3D_TexInit(dsIcon.tex, WIDTH_POW2, HEIGHT_POW2, GPU_RGB565);
}
struct bannerData {
u16 version;
u16 crc;
u8 reserved[28];
u8 data[512];
u16 palette[16];
};
bannerData* iconData = (bannerData*)banner;
u16* output = (u16*)dsIcon.tex->data;
for (size_t x = 0; x < 32; x++) {
for (size_t y = 0; y < 32; y++) {
u32 srcOff = (((y >> 3) * 4 + (x >> 3)) * 8 + (y & 7)) * 4 + ((x & 7) >> 1);
u32 srcShift = (x & 1) * 4;
u16 pIndex = (iconData->data[srcOff] >> srcShift) & 0xF;
u16 color = 0xFFFF;
if (pIndex != 0) {
u16 r = iconData->palette[pIndex] & 0x1F;
u16 g = (iconData->palette[pIndex] >> 5) & 0x1F;
u16 b = (iconData->palette[pIndex] >> 10) & 0x1F;
color = (r << 11) | (g << 6) | (g >> 4) | (b);
}
u32 dst = ((((y >> 3) * (32 >> 3) + (x >> 3)) << 6) +
((x & 1) | ((y & 1) << 1) | ((x & 2) << 1) | ((y & 2) << 2) | ((x & 4) << 2) | ((y & 4) << 3)));
output[dst] = color;
}
}
}
void Title::load(void)
{
mId = 0xFFFFFFFFFFFFFFFF;
@ -45,7 +88,6 @@ void Title::load(void)
mLongDescription = StringUtils::UTF8toUTF16("");
mSavePath = StringUtils::UTF8toUTF16("");
mExtdataPath = StringUtils::UTF8toUTF16("");
mIcon = Gui::noIcon();
mAccessibleSave = false;
mAccessibleExtdata = false;
mSaves.clear();
@ -65,7 +107,6 @@ void Title::load(u64 id, u8* _productCode, bool accessibleSave, bool accessibleE
mMedia = media;
mCard = cardType;
mCardType = card;
mIcon = Gui::noIcon();
memcpy(productCode, _productCode, 16);
}
@ -147,15 +188,19 @@ bool Title::load(u64 _id, FS_MediaType _media, FS_CardType _card)
_cardTitle[13] = '\0';
_gameCode[5] = '\0';
delete[] headerData;
headerData = new u8[0x23C0];
FSUSER_GetLegacyBannerData(mMedia, 0LL, headerData);
loadDSIcon(headerData);
mIcon = dsIcon;
delete[] headerData;
res = SPIGetCardType(&mCardType, (_gameCode[0] == 'I') ? 1 : 0);
if (R_FAILED(res)) {
delete[] headerData;
Logger::getInstance().log(Logger::ERROR, "Failed get SPI Card Type with result 0x%08lX.", res);
return false;
}
delete[] headerData;
mShortDescription = StringUtils::removeForbiddenCharacters(StringUtils::UTF8toUTF16(_cardTitle));
mLongDescription = mShortDescription;
mSavePath = StringUtils::UTF8toUTF16("/3ds/Checkpoint/saves/") + StringUtils::UTF8toUTF16(_gameCode) + StringUtils::UTF8toUTF16(" ") +
@ -171,17 +216,17 @@ bool Title::load(u64 _id, FS_MediaType _media, FS_CardType _card)
res = io::createDirectory(Archive::sdmc(), mSavePath);
if (R_FAILED(res)) {
loadTitle = false;
Logger::getInstance().log(Logger::ERROR, "Failed to create backup with result 0x%08lX.", res);
Logger::getInstance().log(Logger::ERROR, "Failed to create backup directory with result 0x%08lX.", res);
}
}
mIcon = Gui::TWLIcon();
}
refreshDirectories();
return loadTitle;
}
Title::~Title(void) {}
bool Title::accessibleSave(void)
{
return mAccessibleSave;
@ -446,8 +491,8 @@ static bool validId(u64 id)
void loadTitles(bool forceRefresh)
{
std::u16string savecachePath = StringUtils::UTF8toUTF16("/3ds/Checkpoint/fullsavecache");
std::u16string extdatacachePath = StringUtils::UTF8toUTF16("/3ds/Checkpoint/fullextdatacache");
static const std::u16string savecachePath = StringUtils::UTF8toUTF16("/3ds/Checkpoint/fullsavecache");
static const std::u16string extdatacachePath = StringUtils::UTF8toUTF16("/3ds/Checkpoint/fullextdatacache");
// on refreshing
titleSaves.clear();
@ -814,7 +859,8 @@ static void importTitleListCache(void)
title.setIcon(smallIcon);
}
else {
title.setIcon(Gui::TWLIcon());
// this cannot happen
title.setIcon(Gui::noIcon());
}
titleSaves.at(i) = title;
@ -860,7 +906,8 @@ static void importTitleListCache(void)
title.setIcon(smallIcon);
}
else {
title.setIcon(Gui::TWLIcon());
// this cannot happen
title.setIcon(Gui::noIcon());
}
titleExtdatas.at(i) = title;