List DS cartridges.

This commit is contained in:
Steven Smith 2016-04-10 20:49:33 -07:00
parent 78b85d0bf0
commit 56b0879f8f
4 changed files with 233 additions and 140 deletions

View File

@ -4,6 +4,7 @@
#include "../../error.h" #include "../../error.h"
#include "../../progressbar.h" #include "../../progressbar.h"
#include "../../prompt.h" #include "../../prompt.h"
#include "../task/task.h"
static void action_launch_title_update(ui_view* view, void* data, float* progress, char* progressText) { static void action_launch_title_update(ui_view* view, void* data, float* progress, char* progressText) {
title_info* info = (title_info*) data; title_info* info = (title_info*) data;
@ -11,10 +12,11 @@ static void action_launch_title_update(ui_view* view, void* data, float* progres
u8 buf0[0x300]; u8 buf0[0x300];
u8 buf1[0x20]; u8 buf1[0x20];
Result res = 0;
aptOpenSession(); aptOpenSession();
Result res = APT_PrepareToDoAppJump(0, info->titleId, info->mediaType); if(R_SUCCEEDED(res = APT_PrepareToDoAppJump(0, info->titleId, info->mediaType))) {
if(R_SUCCEEDED(res)) {
res = APT_DoAppJump(0x300, 0x20, buf0, buf1); res = APT_DoAppJump(0x300, 0x20, buf0, buf1);
} }

View File

@ -23,12 +23,13 @@ typedef struct {
static Result task_populate_titles_from(populate_titles_data* data, FS_MediaType mediaType, bool useDSiWare) { static Result task_populate_titles_from(populate_titles_data* data, FS_MediaType mediaType, bool useDSiWare) {
bool inserted; bool inserted;
FS_CardType type; FS_CardType type;
if(mediaType == MEDIATYPE_GAME_CARD && ((R_FAILED(FSUSER_CardSlotIsInserted(&inserted)) || !inserted) || (R_FAILED(FSUSER_GetCardType(&type)) || type != CARD_CTR))) { if(mediaType == MEDIATYPE_GAME_CARD && (R_FAILED(FSUSER_CardSlotIsInserted(&inserted)) || !inserted || R_FAILED(FSUSER_GetCardType(&type)))) {
return 0; return 0;
} }
Result res = 0; Result res = 0;
if(mediaType != MEDIATYPE_GAME_CARD || type == CARD_CTR) {
u32 titleCount = 0; u32 titleCount = 0;
if(R_SUCCEEDED(res = AM_GetTitleCount(mediaType, &titleCount))) { if(R_SUCCEEDED(res = AM_GetTitleCount(mediaType, &titleCount))) {
u64* titleIds = (u64*) calloc(titleCount, sizeof(u64)); u64* titleIds = (u64*) calloc(titleCount, sizeof(u64));
@ -58,6 +59,7 @@ static Result task_populate_titles_from(populate_titles_data* data, FS_MediaType
AM_GetTitleProductCode(mediaType, titleIds[i], titleInfo->productCode); AM_GetTitleProductCode(mediaType, titleIds[i], titleInfo->productCode);
titleInfo->version = titleInfos[i].version; titleInfo->version = titleInfos[i].version;
titleInfo->installedSize = titleInfos[i].size; titleInfo->installedSize = titleInfos[i].size;
titleInfo->twl = dsiWare;
titleInfo->hasSmdh = false; titleInfo->hasSmdh = false;
list_item* item = &data->items[*data->count]; list_item* item = &data->items[*data->count];
@ -73,7 +75,13 @@ static Result task_populate_titles_from(populate_titles_data* data, FS_MediaType
utf16_to_utf8((uint8_t*) title, bnr->titles[systemLanguage], 0x100); utf16_to_utf8((uint8_t*) title, bnr->titles[systemLanguage], 0x100);
char* nameEnd = strchr(title, '\n'); char* nameEnd = strchr(title, '\n');
if(nameEnd == NULL) { if(nameEnd != NULL) {
char* curr = NULL;
while((curr = strchr(nameEnd + 1, '\n')) != NULL) {
*nameEnd = ' ';
nameEnd = curr;
}
} else {
nameEnd = title + strlen(title); nameEnd = title + strlen(title);
} }
@ -182,6 +190,76 @@ static Result task_populate_titles_from(populate_titles_data* data, FS_MediaType
res = MAKERESULT(RL_PERMANENT, RS_INVALIDSTATE, 254, RD_OUT_OF_MEMORY); res = MAKERESULT(RL_PERMANENT, RS_INVALIDSTATE, 254, RD_OUT_OF_MEMORY);
} }
} }
} else {
u8* header = (u8*) calloc(1, 0x3B4);
BNR* bnr = (BNR*) calloc(1, sizeof(BNR));
if(R_SUCCEEDED(res = FSUSER_GetLegacyRomHeader(MEDIATYPE_GAME_CARD, 0, header)) && R_SUCCEEDED(res = FSUSER_GetLegacyBannerData(MEDIATYPE_GAME_CARD, 0, (u8*) bnr))) {
title_info* titleInfo = (title_info*) calloc(1, sizeof(title_info));
if(titleInfo != NULL) {
titleInfo->mediaType = MEDIATYPE_GAME_CARD;
titleInfo->titleId = *(u64*) &header[0x230];
memcpy(titleInfo->productCode, header, 0x00C);
titleInfo->version = header[0x01E];
titleInfo->installedSize = *(u32*) &header[0x080];
titleInfo->twl = true;
titleInfo->hasSmdh = true;
list_item* item = &data->items[*data->count];
u8 systemLanguage = CFG_LANGUAGE_EN;
CFGU_GetSystemLanguage(&systemLanguage);
char title[0x100] = {'\0'};
utf16_to_utf8((uint8_t*) title, bnr->titles[systemLanguage], 0x100);
char* nameEnd = strchr(title, '\n');
if(nameEnd != NULL) {
char* curr = NULL;
while((curr = strchr(nameEnd + 1, '\n')) != NULL) {
*nameEnd = ' ';
nameEnd = curr;
}
} else {
nameEnd = title + strlen(title);
}
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);
item->rgba = 0xFFFF0000;
item->data = titleInfo;
(*data->count)++;
}
}
free(header);
free(bnr);
}
return res; return res;
} }

View File

@ -37,6 +37,7 @@ typedef struct {
char productCode[0x10]; char productCode[0x10];
u16 version; u16 version;
u64 installedSize; u64 installedSize;
bool twl;
bool hasSmdh; bool hasSmdh;
smdh_info smdhInfo; smdh_info smdhInfo;
} title_info; } title_info;

View File

@ -43,6 +43,13 @@ static list_item dsiware_titles_action_items[DSIWARE_TITLES_ACTION_COUNT] = {
{"Delete Title", 0xFF000000, action_delete_title}, {"Delete Title", 0xFF000000, action_delete_title},
}; };
#define DSIWARE_CARD_TITLES_ACTION_COUNT 1
static u32 dsiware_card_titles_action_count = DSIWARE_CARD_TITLES_ACTION_COUNT;
static list_item dsiware_card_titles_action_items[DSIWARE_CARD_TITLES_ACTION_COUNT] = {
{"Launch Title", 0xFF000000, action_launch_title},
};
typedef struct { typedef struct {
title_info* info; title_info* info;
bool* populated; bool* populated;
@ -77,12 +84,17 @@ static void titles_action_update(ui_view* view, void* data, list_item** items, u
return; return;
} }
if(actionData->info->mediaType == MEDIATYPE_GAME_CARD) { if(actionData->info->mediaType == MEDIATYPE_GAME_CARD && actionData->info->twl) {
if(*itemCount != &dsiware_card_titles_action_count || *items != dsiware_card_titles_action_items) {
*itemCount = &dsiware_card_titles_action_count;
*items = dsiware_card_titles_action_items;
}
} else if(actionData->info->mediaType == MEDIATYPE_GAME_CARD) {
if(*itemCount != &card_titles_action_count || *items != card_titles_action_items) { if(*itemCount != &card_titles_action_count || *items != card_titles_action_items) {
*itemCount = &card_titles_action_count; *itemCount = &card_titles_action_count;
*items = card_titles_action_items; *items = card_titles_action_items;
} }
} else if(((actionData->info->titleId >> 32) & 0x8000) != 0) { } else if(actionData->info->twl) {
if(*itemCount != &dsiware_titles_action_count || *items != dsiware_titles_action_items) { if(*itemCount != &dsiware_titles_action_count || *items != dsiware_titles_action_items) {
*itemCount = &dsiware_titles_action_count; *itemCount = &dsiware_titles_action_count;
*items = dsiware_titles_action_items; *items = dsiware_titles_action_items;