diff --git a/source/screen.c b/source/screen.c index 69bfda5..31d511b 100644 --- a/source/screen.c +++ b/source/screen.c @@ -208,34 +208,18 @@ void screen_exit() { } } -u32 next_pow_2(u32 i) { - i--; - i |= i >> 1; - i |= i >> 2; - i |= i >> 4; - i |= i >> 8; - i |= i >> 16; - i++; - - return i; -} - -static u32 tiled_texture_index(u32 x, u32 y, u32 w, u32 h) { - return (((y >> 3) * (w >> 3) + (x >> 3)) << 6) + ((x & 1) | ((y & 1) << 1) | ((x & 2) << 1) | ((y & 2) << 2) | ((x & 4) << 2) | ((y & 4) << 3)); -} - void screen_load_texture(u32 id, void* data, u32 size, u32 width, u32 height, GPU_TEXCOLOR format, bool linearFilter) { if(id >= MAX_TEXTURES) { util_panic("Attempted to load buffer to invalid texture ID \"%lu\".", id); return; } - u32 pow2Width = next_pow_2(width); + u32 pow2Width = util_next_pow_2(width); if(pow2Width < 64) { pow2Width = 64; } - u32 pow2Height = next_pow_2(height); + u32 pow2Height = util_next_pow_2(height); if(pow2Height < 64) { pow2Height = 64; } @@ -384,7 +368,7 @@ void screen_load_texture_tiled(u32 id, void* tiledData, u32 size, u32 width, u32 u8* untiledData = (u8*) calloc(1, size); for(u32 x = 0; x < width; x++) { for(u32 y = 0; y < height; y++) { - u32 tiledDataPos = tiled_texture_index(x, y, width, height) * pixelSize; + u32 tiledDataPos = util_tiled_texture_index(x, y, width, height) * pixelSize; u32 untiledDataPos = (y * width + x) * pixelSize; for(u32 i = 0; i < pixelSize; i++) { diff --git a/source/screen.h b/source/screen.h index 553147f..5c8b913 100644 --- a/source/screen.h +++ b/source/screen.h @@ -42,6 +42,8 @@ void screen_init(); void screen_exit(); +void screen_load_texture(u32 id, void* tiledData, u32 size, u32 width, u32 height, GPU_TEXCOLOR format, bool linearFilter); +u32 screen_load_texture_auto(void* tiledData, u32 size, u32 width, u32 height, GPU_TEXCOLOR format, bool linearFilter); void screen_load_texture_file(u32 id, const char* path, bool linearFilter); u32 screen_load_texture_file_auto(const char* path, bool linearFilter); void screen_load_texture_tiled(u32 id, void* tiledData, u32 size, u32 width, u32 height, GPU_TEXCOLOR format, bool linearFilter); diff --git a/source/ui/section/task/listextsavedata.c b/source/ui/section/task/listextsavedata.c index 6245b36..73c94a8 100644 --- a/source/ui/section/task/listextsavedata.c +++ b/source/ui/section/task/listextsavedata.c @@ -49,12 +49,12 @@ static Result task_populate_ext_save_data_from(populate_ext_save_data_data* data u8 systemLanguage = CFG_LANGUAGE_EN; CFGU_GetSystemLanguage(&systemLanguage); - utf16_to_utf8((uint8_t*) item->name, smdh.titles[systemLanguage].shortDescription, NAME_MAX - 1); + utf16_to_utf8((uint8_t*) item->name, smdh.titles[systemLanguage].shortDescription, NAME_MAX); extSaveDataInfo->hasSmdh = true; - utf16_to_utf8((uint8_t*) extSaveDataInfo->smdhInfo.shortDescription, smdh.titles[systemLanguage].shortDescription, sizeof(extSaveDataInfo->smdhInfo.shortDescription) - 1); - utf16_to_utf8((uint8_t*) extSaveDataInfo->smdhInfo.longDescription, smdh.titles[systemLanguage].longDescription, sizeof(extSaveDataInfo->smdhInfo.longDescription) - 1); - utf16_to_utf8((uint8_t*) extSaveDataInfo->smdhInfo.publisher, smdh.titles[systemLanguage].publisher, sizeof(extSaveDataInfo->smdhInfo.publisher) - 1); + utf16_to_utf8((uint8_t*) extSaveDataInfo->smdhInfo.shortDescription, smdh.titles[systemLanguage].shortDescription, sizeof(extSaveDataInfo->smdhInfo.shortDescription)); + utf16_to_utf8((uint8_t*) extSaveDataInfo->smdhInfo.longDescription, smdh.titles[systemLanguage].longDescription, sizeof(extSaveDataInfo->smdhInfo.longDescription)); + utf16_to_utf8((uint8_t*) extSaveDataInfo->smdhInfo.publisher, smdh.titles[systemLanguage].publisher, sizeof(extSaveDataInfo->smdhInfo.publisher)); extSaveDataInfo->smdhInfo.texture = screen_load_texture_tiled_auto(smdh.largeIcon, sizeof(smdh.largeIcon), 48, 48, GPU_RGB565, false); } else { extSaveDataInfo->hasSmdh = false; diff --git a/source/ui/section/task/listfiles.c b/source/ui/section/task/listfiles.c index 1d6d12f..4f80529 100644 --- a/source/ui/section/task/listfiles.c +++ b/source/ui/section/task/listfiles.c @@ -146,9 +146,9 @@ static void task_populate_files_thread(void* arg) { CFGU_GetSystemLanguage(&systemLanguage); fileInfo->ciaInfo.hasSmdh = true; - utf16_to_utf8((uint8_t *) fileInfo->ciaInfo.smdhInfo.shortDescription, smdh.titles[systemLanguage].shortDescription, sizeof(fileInfo->ciaInfo.smdhInfo.shortDescription) - 1); - utf16_to_utf8((uint8_t *) fileInfo->ciaInfo.smdhInfo.longDescription, smdh.titles[systemLanguage].longDescription, sizeof(fileInfo->ciaInfo.smdhInfo.longDescription) - 1); - utf16_to_utf8((uint8_t *) fileInfo->ciaInfo.smdhInfo.publisher, smdh.titles[systemLanguage].publisher, sizeof(fileInfo->ciaInfo.smdhInfo.publisher) - 1); + utf16_to_utf8((uint8_t *) fileInfo->ciaInfo.smdhInfo.shortDescription, smdh.titles[systemLanguage].shortDescription, sizeof(fileInfo->ciaInfo.smdhInfo.shortDescription)); + utf16_to_utf8((uint8_t *) fileInfo->ciaInfo.smdhInfo.longDescription, smdh.titles[systemLanguage].longDescription, sizeof(fileInfo->ciaInfo.smdhInfo.longDescription)); + utf16_to_utf8((uint8_t *) fileInfo->ciaInfo.smdhInfo.publisher, smdh.titles[systemLanguage].publisher, sizeof(fileInfo->ciaInfo.smdhInfo.publisher)); fileInfo->ciaInfo.smdhInfo.texture = screen_load_texture_tiled_auto(smdh.largeIcon, sizeof(smdh.largeIcon), 48, 48, GPU_RGB565, false); } } diff --git a/source/ui/section/task/listtitles.c b/source/ui/section/task/listtitles.c index c5764f0..e89426a 100644 --- a/source/ui/section/task/listtitles.c +++ b/source/ui/section/task/listtitles.c @@ -39,7 +39,8 @@ static Result task_populate_titles_from(populate_titles_data* data, FS_MediaType AM_TitleEntry* titleInfos = (AM_TitleEntry*) calloc(titleCount, sizeof(AM_TitleEntry)); if(titleInfos != NULL) { if(R_SUCCEEDED(res = AM_GetTitleInfo(mediaType, titleCount, titleIds, titleInfos))) { - SMDH smdh; + SMDH* smdh = (SMDH*) calloc(1, sizeof(SMDH)); + BNR* bnr = (BNR*) calloc(1, sizeof(BNR)); for(u32 i = 0; i < titleCount && i < data->max; i++) { if(task_is_quit_all() || svcWaitSynchronization(data->cancelEvent, 0) == 0) { break; @@ -61,29 +62,72 @@ static Result task_populate_titles_from(populate_titles_data* data, FS_MediaType list_item* item = &data->items[*data->count]; - static const u32 filePathData[] = {0x00000000, 0x00000000, 0x00000002, 0x6E6F6369, 0x00000000}; - static const FS_Path filePath = (FS_Path) {PATH_BINARY, 0x14, (u8*) filePathData}; - u32 archivePath[] = {(u32) (titleIds[i] & 0xFFFFFFFF), (u32) ((titleIds[i] >> 32) & 0xFFFFFFFF), mediaType, 0x00000000}; - FS_Archive archive = {ARCHIVE_SAVEDATA_AND_CONTENT, (FS_Path) {PATH_BINARY, 0x10, (u8*) archivePath}}; - Handle fileHandle; - if(R_SUCCEEDED(FSUSER_OpenFileDirectly(&fileHandle, archive, filePath, FS_OPEN_READ, 0))) { - u32 bytesRead; - if(R_SUCCEEDED(FSFILE_Read(fileHandle, &bytesRead, 0, &smdh, sizeof(SMDH))) && bytesRead == sizeof(SMDH)) { - if(smdh.magic[0] == 'S' && smdh.magic[1] == 'M' && smdh.magic[2] == 'D' && smdh.magic[3] == 'H') { - u8 systemLanguage = CFG_LANGUAGE_EN; - CFGU_GetSystemLanguage(&systemLanguage); + if(dsiWare) { + if(R_SUCCEEDED(FSUSER_GetLegacyBannerData(mediaType, titleIds[i], (u8*) bnr))) { + titleInfo->hasSmdh = true; - utf16_to_utf8((uint8_t*) item->name, smdh.titles[systemLanguage].shortDescription, NAME_MAX - 1); + u8 systemLanguage = CFG_LANGUAGE_EN; + CFGU_GetSystemLanguage(&systemLanguage); - titleInfo->hasSmdh = true; - utf16_to_utf8((uint8_t*) titleInfo->smdhInfo.shortDescription, smdh.titles[systemLanguage].shortDescription, sizeof(titleInfo->smdhInfo.shortDescription) - 1); - utf16_to_utf8((uint8_t*) titleInfo->smdhInfo.longDescription, smdh.titles[systemLanguage].longDescription, sizeof(titleInfo->smdhInfo.longDescription) - 1); - utf16_to_utf8((uint8_t*) titleInfo->smdhInfo.publisher, smdh.titles[systemLanguage].publisher, sizeof(titleInfo->smdhInfo.publisher) - 1); - titleInfo->smdhInfo.texture = screen_load_texture_tiled_auto(smdh.largeIcon, sizeof(smdh.largeIcon), 48, 48, GPU_RGB565, false); + char title[0x100] = {'\0'}; + utf16_to_utf8((uint8_t*) title, bnr->titles[systemLanguage], 0x100); + + char* nameEnd = strchr(title, '\n'); + if(nameEnd == NULL) { + nameEnd = title + strlen(title); } - } - FSFILE_Close(fileHandle); + strncpy(item->name, title, nameEnd - title); + + strncpy(titleInfo->smdhInfo.shortDescription, title, nameEnd - title); + strncpy(titleInfo->smdhInfo.longDescription, nameEnd + 1, strlen(title) - (nameEnd - title) - 1); + + u8 icon[32 * 32 * 2]; + for(u32 x = 0; x < 32; x++) { + for(u32 y = 0; y < 32; y++) { + u32 srcPos = (((y >> 3) * 4 + (x >> 3)) * 8 + (y & 7)) * 4 + ((x & 7) >> 1); + u32 srcShift = (x & 1) * 4; + u16 srcPx = bnr->mainIconPalette[(bnr->mainIconBitmap[srcPos] >> srcShift) & 0xF]; + + u8 r = (u8) (srcPx & 0x1F); + u8 g = (u8) ((srcPx >> 5) & 0x1F); + u8 b = (u8) ((srcPx >> 10) & 0x1F); + + u16 reversedPx = (u16) ((r << 11) | (g << 6) | (b << 1) | 1); + + u32 dstPos = (y * 32 + x) * 2; + icon[dstPos + 0] = (u8) (reversedPx & 0xFF); + icon[dstPos + 1] = (u8) ((reversedPx >> 8) & 0xFF); + } + } + + titleInfo->smdhInfo.texture = screen_load_texture_auto(icon, sizeof(icon), 32, 32, GPU_RGBA5551, false); + } + } else { + static const u32 filePathData[] = {0x00000000, 0x00000000, 0x00000002, 0x6E6F6369, 0x00000000}; + static const FS_Path filePath = (FS_Path) {PATH_BINARY, 0x14, (u8*) filePathData}; + u32 archivePath[] = {(u32) (titleIds[i] & 0xFFFFFFFF), (u32) ((titleIds[i] >> 32) & 0xFFFFFFFF), mediaType, 0x00000000}; + FS_Archive archive = {ARCHIVE_SAVEDATA_AND_CONTENT, (FS_Path) {PATH_BINARY, 0x10, (u8*) archivePath}}; + Handle fileHandle; + if(R_SUCCEEDED(FSUSER_OpenFileDirectly(&fileHandle, archive, filePath, FS_OPEN_READ, 0))) { + u32 bytesRead; + if(R_SUCCEEDED(FSFILE_Read(fileHandle, &bytesRead, 0, smdh, sizeof(SMDH))) && bytesRead == sizeof(SMDH)) { + if(smdh->magic[0] == 'S' && smdh->magic[1] == 'M' && smdh->magic[2] == 'D' && smdh->magic[3] == 'H') { + u8 systemLanguage = CFG_LANGUAGE_EN; + CFGU_GetSystemLanguage(&systemLanguage); + + utf16_to_utf8((uint8_t*) item->name, smdh->titles[systemLanguage].shortDescription, NAME_MAX); + + titleInfo->hasSmdh = true; + utf16_to_utf8((uint8_t*) titleInfo->smdhInfo.shortDescription, smdh->titles[systemLanguage].shortDescription, sizeof(titleInfo->smdhInfo.shortDescription)); + utf16_to_utf8((uint8_t*) titleInfo->smdhInfo.longDescription, smdh->titles[systemLanguage].longDescription, sizeof(titleInfo->smdhInfo.longDescription)); + utf16_to_utf8((uint8_t*) titleInfo->smdhInfo.publisher, smdh->titles[systemLanguage].publisher, sizeof(titleInfo->smdhInfo.publisher)); + titleInfo->smdhInfo.texture = screen_load_texture_tiled_auto(smdh->largeIcon, sizeof(smdh->largeIcon), 48, 48, GPU_RGB565, false); + } + } + + FSFILE_Close(fileHandle); + } } bool empty = strlen(item->name) == 0; @@ -122,6 +166,9 @@ static Result task_populate_titles_from(populate_titles_data* data, FS_MediaType (*data->count)++; } } + + free(smdh); + free(bnr); } free(titleInfos); diff --git a/source/ui/section/task/task.h b/source/ui/section/task/task.h index 1656564..38604cc 100644 --- a/source/ui/section/task/task.h +++ b/source/ui/section/task/task.h @@ -5,9 +5,9 @@ #include "../../list.h" typedef struct { - char shortDescription[0x81]; - char longDescription[0x161]; - char publisher[0x81]; + char shortDescription[0x100]; + char longDescription[0x200]; + char publisher[0x100]; u32 texture; } smdh_info; diff --git a/source/ui/ui.c b/source/ui/ui.c index 2f1b193..b00f67b 100644 --- a/source/ui/ui.c +++ b/source/ui/ui.c @@ -240,13 +240,9 @@ void ui_draw_ext_save_data_info(ui_view* view, void* data, float x1, float y1, f float smdhInfoBoxY = y1 + (y2 - y1) / 4 - smdhInfoBoxHeight / 2; screen_draw_texture(TEXTURE_SMDH_INFO_BOX, smdhInfoBoxX, smdhInfoBoxY, smdhInfoBoxWidth, smdhInfoBoxHeight); - u32 smdhIconWidth; - u32 smdhIconHeight; - screen_get_texture_size(&smdhIconWidth, &smdhIconHeight, info->smdhInfo.texture); - float smdhIconX = smdhInfoBoxX + 8; float smdhIconY = smdhInfoBoxY + 8; - screen_draw_texture(info->smdhInfo.texture, smdhIconX, smdhIconY, smdhIconWidth, smdhIconHeight); + screen_draw_texture(info->smdhInfo.texture, smdhIconX, smdhIconY, 48, 48); float shortDescriptionHeight; screen_get_string_size(NULL, &shortDescriptionHeight, info->smdhInfo.shortDescription, 0.5f, 0.5f); @@ -257,9 +253,9 @@ void ui_draw_ext_save_data_info(ui_view* view, void* data, float x1, float y1, f float publisherHeight; screen_get_string_size(NULL, &publisherHeight, info->smdhInfo.publisher, 0.5f, 0.5f); - float smdhTextX = smdhIconX + smdhIconWidth + 8; + float smdhTextX = smdhIconX + 48 + 8; - float smdhShortDescriptionY = smdhIconY + (smdhIconHeight - shortDescriptionHeight - 2 - longDescriptionHeight - 2 - publisherHeight) / 2; + float smdhShortDescriptionY = smdhIconY + (48 - shortDescriptionHeight - 2 - longDescriptionHeight - 2 - publisherHeight) / 2; screen_draw_string(info->smdhInfo.shortDescription, smdhTextX, smdhShortDescriptionY, 0.5f, 0.5f, 0xFF000000, false); float smdhLongDescriptionY = smdhShortDescriptionY + shortDescriptionHeight + 2; @@ -338,13 +334,9 @@ void ui_draw_file_info(ui_view* view, void* data, float x1, float y1, float x2, float smdhInfoBoxY = y1 + (y2 - y1) / 4 - smdhInfoBoxHeight / 2; screen_draw_texture(TEXTURE_SMDH_INFO_BOX, smdhInfoBoxX, smdhInfoBoxY, smdhInfoBoxWidth, smdhInfoBoxHeight); - u32 smdhIconWidth; - u32 smdhIconHeight; - screen_get_texture_size(&smdhIconWidth, &smdhIconHeight, info->ciaInfo.smdhInfo.texture); - float smdhIconX = smdhInfoBoxX + 8; float smdhIconY = smdhInfoBoxY + 8; - screen_draw_texture(info->ciaInfo.smdhInfo.texture, smdhIconX, smdhIconY, smdhIconWidth, smdhIconHeight); + screen_draw_texture(info->ciaInfo.smdhInfo.texture, smdhIconX, smdhIconY, 48, 48); float shortDescriptionHeight; screen_get_string_size(NULL, &shortDescriptionHeight, info->ciaInfo.smdhInfo.shortDescription, 0.5f, 0.5f); @@ -355,9 +347,9 @@ void ui_draw_file_info(ui_view* view, void* data, float x1, float y1, float x2, float publisherHeight; screen_get_string_size(NULL, &publisherHeight, info->ciaInfo.smdhInfo.publisher, 0.5f, 0.5f); - float smdhTextX = smdhIconX + smdhIconWidth + 8; + float smdhTextX = smdhIconX + 48 + 8; - float smdhShortDescriptionY = smdhIconY + (smdhIconHeight - shortDescriptionHeight - 2 - longDescriptionHeight - 2 - publisherHeight) / 2; + float smdhShortDescriptionY = smdhIconY + (48 - shortDescriptionHeight - 2 - longDescriptionHeight - 2 - publisherHeight) / 2; screen_draw_string(info->ciaInfo.smdhInfo.shortDescription, smdhTextX, smdhShortDescriptionY, 0.5f, 0.5f, 0xFF000000, false); float smdhLongDescriptionY = smdhShortDescriptionY + shortDescriptionHeight + 2; @@ -510,13 +502,9 @@ void ui_draw_title_info(ui_view* view, void* data, float x1, float y1, float x2, float smdhInfoBoxY = y1 + (y2 - y1) / 4 - smdhInfoBoxHeight / 2; screen_draw_texture(TEXTURE_SMDH_INFO_BOX, smdhInfoBoxX, smdhInfoBoxY, smdhInfoBoxWidth, smdhInfoBoxHeight); - u32 smdhIconWidth; - u32 smdhIconHeight; - screen_get_texture_size(&smdhIconWidth, &smdhIconHeight, info->smdhInfo.texture); - float smdhIconX = smdhInfoBoxX + 8; float smdhIconY = smdhInfoBoxY + 8; - screen_draw_texture(info->smdhInfo.texture, smdhIconX, smdhIconY, smdhIconWidth, smdhIconHeight); + screen_draw_texture(info->smdhInfo.texture, smdhIconX, smdhIconY, 48, 48); float shortDescriptionHeight; screen_get_string_size(NULL, &shortDescriptionHeight, info->smdhInfo.shortDescription, 0.5f, 0.5f); @@ -527,9 +515,9 @@ void ui_draw_title_info(ui_view* view, void* data, float x1, float y1, float x2, float publisherHeight; screen_get_string_size(NULL, &publisherHeight, info->smdhInfo.publisher, 0.5f, 0.5f); - float smdhTextX = smdhIconX + smdhIconWidth + 8; + float smdhTextX = smdhIconX + 48 + 8; - float smdhShortDescriptionY = smdhIconY + (smdhIconHeight - shortDescriptionHeight - 2 - longDescriptionHeight - 2 - publisherHeight) / 2; + float smdhShortDescriptionY = smdhIconY + (48 - shortDescriptionHeight - 2 - longDescriptionHeight - 2 - publisherHeight) / 2; screen_draw_string(info->smdhInfo.shortDescription, smdhTextX, smdhShortDescriptionY, 0.5f, 0.5f, 0xFF000000, false); float smdhLongDescriptionY = smdhShortDescriptionY + shortDescriptionHeight + 2; diff --git a/source/util.c b/source/util.c index 7339e37..48e7ed8 100644 --- a/source/util.c +++ b/source/util.c @@ -435,4 +435,20 @@ int util_compare_directory_entries(const void* e1, const void* e2) { return strcasecmp(entryName1, entryName2); } +} + +u32 util_next_pow_2(u32 i) { + i--; + i |= i >> 1; + i |= i >> 2; + i |= i >> 4; + i |= i >> 8; + i |= i >> 16; + i++; + + return i; +} + +u32 util_tiled_texture_index(u32 x, u32 y, u32 w, u32 h) { + return (((y >> 3) * (w >> 3) + (x >> 3)) << 6) + ((x & 1) | ((y & 1) << 1) | ((x & 2) << 1) | ((y & 2) << 2) | ((x & 4) << 2) | ((y & 4) << 3)); } \ No newline at end of file diff --git a/source/util.h b/source/util.h index 24abdde..364d87d 100644 --- a/source/util.h +++ b/source/util.h @@ -25,6 +25,19 @@ typedef struct { u8 largeIcon[0x1200]; } SMDH; +typedef struct { + u8 version; + bool animated; + u16 crc16[4]; + u8 reserved[0x16]; + u8 mainIconBitmap[0x200]; + u16 mainIconPalette[0x10]; + u16 titles[16][0x80]; + u8 animatedFrameBitmaps[8][0x200]; + u16 animatedFramePalettes[8][0x10]; + u16 animationSequence[0x40]; +} BNR; + void util_panic(const char* s, ...); bool util_is_dir(FS_Archive* archive, const char* path); @@ -44,4 +57,7 @@ Result util_ensure_dir(FS_Archive* archive, const char* path); int util_compare_u32(const void* e1, const void* e2); int util_compare_u64(const void* e1, const void* e2); -int util_compare_directory_entries(const void* e1, const void* e2); \ No newline at end of file +int util_compare_directory_entries(const void* e1, const void* e2); + +u32 util_next_pow_2(u32 i); +u32 util_tiled_texture_index(u32 x, u32 y, u32 w, u32 h); \ No newline at end of file