1
0
Fork 0
mirror of https://github.com/DarkMatterCore/nxdumptool.git synced 2024-11-26 20:22:17 +00:00

Use linked lists to deal with user applications available in multiple storages at the same time.

This commit is contained in:
Pablo Curiel 2020-08-13 14:12:33 -04:00
parent ad401d559d
commit 90c6d8a9f8
2 changed files with 36 additions and 34 deletions

View file

@ -629,7 +629,7 @@ bool titleGetUserApplicationData(u64 app_id, TitleUserApplicationData *out)
/* Clear output. */ /* Clear output. */
memset(out, 0, sizeof(TitleUserApplicationData)); memset(out, 0, sizeof(TitleUserApplicationData));
/* Get user application title info. */ /* Get first user application title info. */
out->app_info = _titleGetInfoFromStorageByTitleId(NcmStorageId_Any, app_id, false); out->app_info = _titleGetInfoFromStorageByTitleId(NcmStorageId_Any, app_id, false);
/* Get first patch title info. */ /* Get first patch title info. */
@ -653,9 +653,6 @@ bool titleGetUserApplicationData(u64 app_id, TitleUserApplicationData *out)
goto end; goto end;
} }
/* Update 'gamecard_available' flag. */
out->gamecard_available = (out->app_info && (out->app_info->storage_id == NcmStorageId_GameCard || _titleGetInfoFromStorageByTitleId(NcmStorageId_GameCard, app_id, false) != NULL));
end: end:
mutexUnlock(&g_titleMutex); mutexUnlock(&g_titleMutex);
@ -1219,14 +1216,19 @@ static bool titleRetrieveContentMetaKeysFromDatabase(u8 storage_id)
/* Update title info count. */ /* Update title info count. */
g_titleInfoCount += total; g_titleInfoCount += total;
/* Fill patch / add-on content specific info. */ /* Update linked lists pointers for user applications, patches and add-on contents. */
g_titleInfoOrphanCount = 0; g_titleInfoOrphanCount = 0;
for(u32 i = 0; i < g_titleInfoCount; i++) for(u32 i = 0; i < g_titleInfoCount; i++)
{ {
TitleInfo *child_info = &(g_titleInfo[i]); TitleInfo *child_info = &(g_titleInfo[i]);
if (child_info->meta_key.type != NcmContentMetaType_Patch && child_info->meta_key.type != NcmContentMetaType_AddOnContent) continue; child_info->parent = child_info->previous = child_info->next = NULL;
/* Retrieve pointer to parent entry. */ if (child_info->meta_key.type != NcmContentMetaType_Application && child_info->meta_key.type != NcmContentMetaType_Patch && \
child_info->meta_key.type != NcmContentMetaType_AddOnContent) continue;
if (child_info->meta_key.type == NcmContentMetaType_Patch || child_info->meta_key.type == NcmContentMetaType_AddOnContent)
{
/* Retrieve pointer to parent user application entry for patches and add-on contents. */
/* Since gamecard title info entries are always appended to the end of the buffer, this guarantees we will first retrieve an eMMC / SD card entry (if available). */ /* Since gamecard title info entries are always appended to the end of the buffer, this guarantees we will first retrieve an eMMC / SD card entry (if available). */
for(u32 j = 0; j < g_titleInfoCount; j++) for(u32 j = 0; j < g_titleInfoCount; j++)
{ {
@ -1247,18 +1249,18 @@ static bool titleRetrieveContentMetaKeysFromDatabase(u8 storage_id)
g_titleInfoOrphanCount++; g_titleInfoOrphanCount++;
continue; continue;
} }
}
/* Locate previous patch / add-on content entry. */ /* Locate previous user application, patch or add-on content entry. */
/* If it's found, we will update both its next pointer and the previous pointer from the current entry. */ /* If it's found, we will update both its next pointer and the previous pointer from the current entry. */
/* We will also update its parent entry pointer. */
for(u32 j = i; j > 0; j--) for(u32 j = i; j > 0; j--)
{ {
TitleInfo *previous_info = &(g_titleInfo[j - 1]); TitleInfo *previous_info = &(g_titleInfo[j - 1]);
if (previous_info->meta_key.type == child_info->meta_key.type && ((child_info->meta_key.type == NcmContentMetaType_Patch && previous_info->meta_key.id == child_info->meta_key.id) || \ if (previous_info->meta_key.type == child_info->meta_key.type && (((child_info->meta_key.type == NcmContentMetaType_Application || child_info->meta_key.type == NcmContentMetaType_Patch) && \
(child_info->meta_key.type == NcmContentMetaType_AddOnContent && titleCheckIfAddOnContentIdsAreSiblings(previous_info->meta_key.id, child_info->meta_key.id)))) previous_info->meta_key.id == child_info->meta_key.id) || (child_info->meta_key.type == NcmContentMetaType_AddOnContent && \
titleCheckIfAddOnContentIdsAreSiblings(previous_info->meta_key.id, child_info->meta_key.id))))
{ {
previous_info->parent = child_info->parent;
previous_info->next = child_info; previous_info->next = child_info;
child_info->previous = previous_info; child_info->previous = previous_info;
break; break;

View file

@ -59,15 +59,15 @@ typedef struct _TitleInfo {
u64 title_size; ///< Total title size. u64 title_size; ///< Total title size.
char title_size_str[32]; ///< Total title size string. char title_size_str[32]; ///< Total title size string.
TitleApplicationMetadata *app_metadata; ///< Only available for system titles and applications. TitleApplicationMetadata *app_metadata; ///< Only available for system titles and applications.
struct _TitleInfo *parent, *previous, *next; ///< Used with TitleInfo entries from patches and add-on contents. struct _TitleInfo *parent, *previous, *next; ///< Used with TitleInfo entries from user applications, patches and add-on contents. The parent pointer is unused in user applications.
} TitleInfo; } TitleInfo;
/// Used to deal with user applications stored in the eMMC, SD card and/or gamecard. /// Used to deal with user applications stored in the eMMC, SD card and/or gamecard.
/// The parent, previous and next pointers from the TitleInfo elements are used to traverse through multiple user applications, patches and/or add-on contents.
typedef struct { typedef struct {
bool gamecard_available; ///< Set to true if one or more titles matching this user application are stored in the inserted gamecard. TitleInfo *app_info; ///< Pointer to a TitleInfo element holding info for the first detected user application entry matching the provided application ID.
TitleInfo *app_info; ///< Pointer to a TitleInfo element for this application. TitleInfo *patch_info; ///< Pointer to a TitleInfo element holding info for the first detected patch entry matching the provided application ID.
TitleInfo *patch_info; ///< Pointer to a TitleInfo element for the first detected patch. TitleInfo *aoc_info; ///< Pointer to a TitleInfo element holding info for the first detected add-on content entry matching the provided application ID.
TitleInfo *aoc_info; ///< Pointer to a TitleInfo element for the first detected add-on content.
} TitleUserApplicationData; } TitleUserApplicationData;
/// Initializes the title interface. /// Initializes the title interface.
@ -97,7 +97,7 @@ TitleInfo *titleGetInfoFromStorageByTitleId(u8 storage_id, u64 title_id);
bool titleGetUserApplicationData(u64 app_id, TitleUserApplicationData *out); bool titleGetUserApplicationData(u64 app_id, TitleUserApplicationData *out);
/// Returns true if orphan titles are available. /// Returns true if orphan titles are available.
/// Orphan titles are patches or add-on contents with no NsApplicationControlData available for its parent user application ID. /// Orphan titles are patches or add-on contents with no NsApplicationControlData available for their parent user application ID.
bool titleAreOrphanTitlesAvailable(void); bool titleAreOrphanTitlesAvailable(void);
/// Returns a pointer to a dynamically allocated buffer of pointers to TitleInfo entries from orphan titles, as well as their count. The allocated buffer must be freed by the calling function. /// Returns a pointer to a dynamically allocated buffer of pointers to TitleInfo entries from orphan titles, as well as their count. The allocated buffer must be freed by the calling function.