1
0
Fork 0
mirror of https://github.com/DarkMatterCore/nxdumptool.git synced 2024-11-22 18:26:39 +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. */
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);
/* Get first patch title info. */
@ -653,9 +653,6 @@ bool titleGetUserApplicationData(u64 app_id, TitleUserApplicationData *out)
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:
mutexUnlock(&g_titleMutex);
@ -1219,46 +1216,51 @@ static bool titleRetrieveContentMetaKeysFromDatabase(u8 storage_id)
/* Update title info count. */
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;
for(u32 i = 0; i < g_titleInfoCount; 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. */
/* 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++)
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)
{
TitleInfo *parent_info = &(g_titleInfo[j]);
if (parent_info->meta_key.type == NcmContentMetaType_Application && \
((child_info->meta_key.type == NcmContentMetaType_Patch && titleCheckIfPatchIdBelongsToApplicationId(parent_info->meta_key.id, child_info->meta_key.id)) || \
(child_info->meta_key.type == NcmContentMetaType_AddOnContent && titleCheckIfAddOnContentIdBelongsToApplicationId(parent_info->meta_key.id, child_info->meta_key.id))))
/* 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). */
for(u32 j = 0; j < g_titleInfoCount; j++)
{
child_info->parent = parent_info;
break;
TitleInfo *parent_info = &(g_titleInfo[j]);
if (parent_info->meta_key.type == NcmContentMetaType_Application && \
((child_info->meta_key.type == NcmContentMetaType_Patch && titleCheckIfPatchIdBelongsToApplicationId(parent_info->meta_key.id, child_info->meta_key.id)) || \
(child_info->meta_key.type == NcmContentMetaType_AddOnContent && titleCheckIfAddOnContentIdBelongsToApplicationId(parent_info->meta_key.id, child_info->meta_key.id))))
{
child_info->parent = parent_info;
break;
}
}
/* Increase orphan title count if we couldn't find the parent user application. */
if (!child_info->parent)
{
g_titleInfoOrphanCount++;
continue;
}
}
/* Increase orphan title count if we couldn't find the parent user application. */
if (!child_info->parent)
{
g_titleInfoOrphanCount++;
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. */
/* We will also update its parent entry pointer. */
for(u32 j = i; j > 0; j--)
{
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) || \
(child_info->meta_key.type == NcmContentMetaType_AddOnContent && titleCheckIfAddOnContentIdsAreSiblings(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) && \
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;
child_info->previous = previous_info;
break;

View file

@ -59,15 +59,15 @@ typedef struct _TitleInfo {
u64 title_size; ///< Total title size.
char title_size_str[32]; ///< Total title size string.
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;
/// 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 {
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 for this application.
TitleInfo *patch_info; ///< Pointer to a TitleInfo element for the first detected patch.
TitleInfo *aoc_info; ///< Pointer to a TitleInfo element for the first detected add-on content.
TitleInfo *app_info; ///< Pointer to a TitleInfo element holding info for the first detected user application entry matching the provided application ID.
TitleInfo *patch_info; ///< Pointer to a TitleInfo element holding info for the first detected patch entry matching the provided application ID.
TitleInfo *aoc_info; ///< Pointer to a TitleInfo element holding info for the first detected add-on content entry matching the provided application ID.
} TitleUserApplicationData;
/// Initializes the title interface.
@ -97,7 +97,7 @@ TitleInfo *titleGetInfoFromStorageByTitleId(u8 storage_id, u64 title_id);
bool titleGetUserApplicationData(u64 app_id, TitleUserApplicationData *out);
/// 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);
/// 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.