1
0
Fork 0
mirror of https://github.com/DarkMatterCore/nxdumptool.git synced 2024-11-10 04:31:44 +00:00

List titles from the inserted gamecard.

This commit is contained in:
Pablo Curiel 2020-07-25 14:50:42 -04:00
parent e4a6e0e77a
commit 2521ac3f15
3 changed files with 213 additions and 16 deletions

View file

@ -529,8 +529,11 @@ static int gamecardDetectionThreadFunc(void *arg)
/* Retrieve initial gamecard insertion status. */
/* Load gamecard info right away if a gamecard is inserted, then signal the user mode gamecard status change event. */
mutexLock(&g_gamecardMutex);
g_gameCardInserted = gamecardIsInserted();
if (g_gameCardInserted) gamecardLoadInfo();
mutexUnlock(&g_gamecardMutex);
ueventSignal(&g_gameCardStatusChangeEvent);
while(true)

View file

@ -38,7 +38,7 @@ static NcmContentMetaDatabase g_ncmDbGameCard = {0}, g_ncmDbEmmcSystem = {0}, g_
static NcmContentStorage g_ncmStorageGameCard = {0}, g_ncmStorageEmmcSystem = {0}, g_ncmStorageEmmcUser = {0}, g_ncmStorageSdCard = {0};
static TitleInfo *g_titleInfo = NULL;
static u32 g_titleInfoCount = 0;
static u32 g_titleInfoCount = 0, g_titleInfoGameCardStartIndex = 0, g_titleInfoGameCardCount = 0;
/* Function prototypes. */
@ -51,9 +51,15 @@ static void titleCloseNcmDatabases(void);
static bool titleOpenNcmStorages(void);
static void titleCloseNcmStorages(void);
static bool titleOpenNcmDatabaseAndStorageFromGameCard(void);
static void titleCloseNcmDatabaseAndStorageFromGameCard(void);
static bool titleLoadTitleInfo(void);
static bool titleRetrieveContentMetaKeysFromDatabase(u8 storage_id, NcmContentMetaDatabase *ncm_db);
static bool _titleRefreshGameCardTitleInfo(bool lock);
static void titleRemoveGameCardTitleInfoEntries(void);
NX_INLINE TitleApplicationMetadata *titleFindApplicationMetadataByTitleId(u64 title_id);
bool titleInitialize(void)
@ -63,15 +69,6 @@ bool titleInitialize(void)
bool ret = g_titleInterfaceInit;
if (ret) goto end;
while(!gamecardGetStatusChangeUserEvent());
/* Allocate memory for the ns application control data. */
/* This will be used each time we need to retrieve application metadata. */
g_nsAppControlData = calloc(1, sizeof(NsApplicationControlData));
@ -111,8 +108,8 @@ bool titleInitialize(void)
goto end;
}
/* Initial gamecard title info retrieval. */
_titleRefreshGameCardTitleInfo(false);
@ -210,9 +207,14 @@ void titleExit(void)
/* Close gamecard ncm database and storage. */
titleCloseNcmDatabaseAndStorageFromGameCard();
/* Free title info. */
if (g_titleInfo) free(g_titleInfo);
g_titleInfoCount = 0;
g_titleInfoCount = g_titleInfoGameCardStartIndex = g_titleInfoGameCardCount = 0;
/* Close eMMC System, eMMC User and SD card ncm storages. */
titleCloseNcmStorages();
@ -282,7 +284,10 @@ NcmContentStorage *titleGetNcmStorageByStorageId(u8 storage_id)
return ncm_storage;
}
bool titleRefreshGameCardTitleInfo(void)
{
return _titleRefreshGameCardTitleInfo(true);
}
@ -361,7 +366,7 @@ static bool titleRetrieveApplicationMetadataFromNsRecords(void)
goto end;
}
/* Decrease buffer size if needed. */
/* Decrease application metadata buffer size if needed. */
if (g_appMetadataCount < app_records_count)
{
TitleApplicationMetadata *tmp_app_metadata = realloc(g_appMetadata, g_appMetadataCount * sizeof(TitleApplicationMetadata));
@ -537,6 +542,44 @@ static void titleCloseNcmStorages(void)
}
}
static bool titleOpenNcmDatabaseAndStorageFromGameCard(void)
{
Result rc = 0;
NcmContentMetaDatabase *ncm_db = &g_ncmDbGameCard;
NcmContentStorage *ncm_storage = &g_ncmStorageGameCard;
/* Open ncm database. */
rc = ncmOpenContentMetaDatabase(ncm_db, NcmStorageId_GameCard);
if (R_FAILED(rc))
{
LOGFILE("ncmOpenContentMetaDatabase failed! (0x%08X).", rc);
goto end;
}
/* Open ncm storage. */
rc = ncmOpenContentStorage(ncm_storage, NcmStorageId_GameCard);
if (R_FAILED(rc))
{
LOGFILE("ncmOpenContentStorage failed! (0x%08X).", rc);
goto end;
}
end:
return R_SUCCEEDED(rc);
}
static void titleCloseNcmDatabaseAndStorageFromGameCard(void)
{
NcmContentMetaDatabase *ncm_db = &g_ncmDbGameCard;
NcmContentStorage *ncm_storage = &g_ncmStorageGameCard;
/* Check if the ncm database handle has already been retrieved. */
if (serviceIsActive(&(ncm_db->s))) ncmContentMetaDatabaseClose(ncm_db);
/* Check if the ncm storage handle has already been retrieved. */
if (serviceIsActive(&(ncm_storage->s))) ncmContentStorageClose(ncm_storage);
}
static bool titleLoadTitleInfo(void)
{
/* Return right away if title info has already been retrieved. */
@ -679,6 +722,155 @@ end:
return success;
}
static bool _titleRefreshGameCardTitleInfo(bool lock)
{
if (lock) mutexLock(&g_titleMutex);
TitleApplicationMetadata *tmp_app_metadata = NULL;
u32 orig_app_count = g_appMetadataCount, cur_app_count = g_appMetadataCount, gamecard_app_count = 0, gamecard_metadata_count = 0;
bool status = false, success = false, cleanup = true;
/* Retrieve current gamecard status. */
status = (gamecardGetStatus() == GameCardStatus_InsertedAndInfoLoaded);
if (status == g_titleGameCardAvailable || !status)
{
cleanup = (status != g_titleGameCardAvailable);
goto end;
}
/* Open gamecard ncm database and storage handles. */
if (!titleOpenNcmDatabaseAndStorageFromGameCard())
{
LOGFILE("Failed to open gamecard ncm database and storage handles.");
goto end;
}
/* Update start index for the gamecard title info entries. */
g_titleInfoGameCardStartIndex = g_titleInfoCount;
/* Retrieve content meta keys from the gamecard ncm database. */
if (!titleRetrieveContentMetaKeysFromDatabase(NcmStorageId_GameCard, &g_ncmDbGameCard))
{
LOGFILE("Failed to retrieve content meta keys from gamecard!");
goto end;
}
/* Update gamecard title info count. */
g_titleInfoGameCardCount = (g_titleInfoCount - g_titleInfoGameCardStartIndex);
if (!g_titleInfoGameCardCount)
{
LOGFILE("Empty content meta key count from gamecard!");
goto end;
}
/* Retrieve gamecard application metadata. */
for(u32 i = g_titleInfoGameCardStartIndex; i < g_titleInfoCount; i++)
{
TitleInfo *cur_title_info = &(g_titleInfo[i]);
/* Skip current title if it's not an application. */
if (cur_title_info->meta_key.type != NcmContentMetaType_Application) continue;
gamecard_app_count++;
/* Check if we already have an application metadata entry for this title ID. */
if ((cur_title_info->app_metadata = titleFindApplicationMetadataByTitleId(cur_title_info->meta_key.id)) != NULL)
{
gamecard_metadata_count++;
continue;
}
/* Reallocate application metadata buffer (if needed). */
if (cur_app_count < (g_appMetadataCount + 1))
{
tmp_app_metadata = realloc(g_appMetadata, (g_appMetadataCount + 1) * sizeof(TitleApplicationMetadata));
if (!tmp_app_metadata)
{
LOGFILE("Failed to reallocate application metadata buffer! (additional entry).");
goto end;
}
g_appMetadata = tmp_app_metadata;
tmp_app_metadata = NULL;
cur_app_count++;
}
/* Retrieve application metadata. */
if (!titleRetrieveApplicationMetadataByTitleId(cur_title_info->meta_key.id, &(g_appMetadata[g_appMetadataCount]))) continue;
cur_title_info->app_metadata = &(g_appMetadata[g_appMetadataCount]);
g_appMetadataCount++;
gamecard_metadata_count++;
}
/* Check gamecard application count. */
if (!gamecard_app_count)
{
LOGFILE("Gamecard application count is zero!");
goto end;
}
/* Check retrieved application metadata count. */
if (!gamecard_metadata_count)
{
LOGFILE("Unable to retrieve application metadata from gamecard! (%u %s).", gamecard_app_count, gamecard_app_count > 1 ? "entries" : "entry");
goto end;
}
success = true;
cleanup = false;
end:
/* Update gamecard status. */
g_titleGameCardAvailable = status;
/* Decrease application metadata buffer size if needed. */
if ((success && g_appMetadataCount < cur_app_count) || (!success && g_appMetadataCount > orig_app_count))
{
if (!success) g_appMetadataCount = orig_app_count;
tmp_app_metadata = realloc(g_appMetadata, g_appMetadataCount * sizeof(TitleApplicationMetadata));
if (tmp_app_metadata)
{
g_appMetadata = tmp_app_metadata;
tmp_app_metadata = NULL;
}
}
if (cleanup)
{
titleRemoveGameCardTitleInfoEntries();
titleCloseNcmDatabaseAndStorageFromGameCard();
}
if (lock) mutexUnlock(&g_titleMutex);
return success;
}
static void titleRemoveGameCardTitleInfoEntries(void)
{
if (!g_titleInfo || !g_titleInfoCount || !g_titleInfoGameCardCount || g_titleInfoGameCardCount > g_titleInfoCount || \
g_titleInfoGameCardStartIndex != (g_titleInfoCount - g_titleInfoGameCardCount)) return;
if (g_titleInfoGameCardCount == g_titleInfoCount)
{
free(g_titleInfo);
g_titleInfo = NULL;
} else {
TitleInfo *tmp_title_info = realloc(g_titleInfo, (g_titleInfoCount - g_titleInfoGameCardCount) * sizeof(TitleInfo));
if (tmp_title_info)
{
g_titleInfo = tmp_title_info;
tmp_title_info = NULL;
}
}
g_titleInfoCount = (g_titleInfoCount - g_titleInfoGameCardCount);
g_titleInfoGameCardStartIndex = g_titleInfoGameCardCount = 0;
}
NX_INLINE TitleApplicationMetadata *titleFindApplicationMetadataByTitleId(u64 title_id)
{
if (!g_appMetadata || !g_appMetadataCount || !title_id) return NULL;

View file

@ -64,7 +64,9 @@ void titleExit(void);
NcmContentMetaDatabase *titleGetNcmDatabaseByStorageId(u8 storage_id);
NcmContentStorage *titleGetNcmStorageByStorageId(u8 storage_id);
/// Returns true if gamecard title info could be loaded.
/// Suitable for being called between UI updates.
bool titleRefreshGameCardTitleInfo(void);