mirror of
https://github.com/DarkMatterCore/nxdumptool.git
synced 2024-11-22 18:26:39 +00:00
poc: add NCA FS section menu
Other changes include: * nca: add content_size_str field to NcaContext struct. * nxdt_utils: modify utilsGenerateFormattedSizeString() to avoid displaying decimal places if dealing with plain bytes.
This commit is contained in:
parent
54e7c0e9be
commit
8e2b0a74b8
4 changed files with 204 additions and 82 deletions
|
@ -77,7 +77,7 @@ typedef enum {
|
||||||
MenuId_Ticket = 9,
|
MenuId_Ticket = 9,
|
||||||
MenuId_NCATitleTypes = 10,
|
MenuId_NCATitleTypes = 10,
|
||||||
MenuId_NCA = 11,
|
MenuId_NCA = 11,
|
||||||
MenuId_NCAFsSection = 12,
|
MenuId_NCAFsSections = 12,
|
||||||
MenuId_Count = 13
|
MenuId_Count = 13
|
||||||
} MenuId;
|
} MenuId;
|
||||||
|
|
||||||
|
@ -141,6 +141,10 @@ void updateTitleList(void);
|
||||||
|
|
||||||
void freeNcaList(void);
|
void freeNcaList(void);
|
||||||
void updateNcaList(TitleInfo *title_info);
|
void updateNcaList(TitleInfo *title_info);
|
||||||
|
static void switchNcaListTitle(Menu *cur_menu, u32 *element_count, TitleInfo *title_info);
|
||||||
|
|
||||||
|
void freeNcaFsSectionsList(void);
|
||||||
|
void updateNcaFsSectionsList(NcaUserData *nca_user_data);
|
||||||
|
|
||||||
NX_INLINE bool useUsbHost(void);
|
NX_INLINE bool useUsbHost(void);
|
||||||
|
|
||||||
|
@ -250,6 +254,14 @@ static MenuElementOption g_storageMenuElementOption = {
|
||||||
.options = NULL
|
.options = NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static MenuElement g_storageMenuElement = {
|
||||||
|
.str = "output storage",
|
||||||
|
.child_menu = NULL,
|
||||||
|
.task_func = NULL,
|
||||||
|
.element_options = &g_storageMenuElementOption,
|
||||||
|
.userdata = NULL
|
||||||
|
};
|
||||||
|
|
||||||
static MenuElement *g_xciMenuElements[] = {
|
static MenuElement *g_xciMenuElements[] = {
|
||||||
&(MenuElement){
|
&(MenuElement){
|
||||||
.str = "start xci dump",
|
.str = "start xci dump",
|
||||||
|
@ -306,13 +318,7 @@ static MenuElement *g_xciMenuElements[] = {
|
||||||
},
|
},
|
||||||
.userdata = NULL
|
.userdata = NULL
|
||||||
},
|
},
|
||||||
&(MenuElement){
|
&g_storageMenuElement,
|
||||||
.str = "output storage",
|
|
||||||
.child_menu = NULL,
|
|
||||||
.task_func = NULL,
|
|
||||||
.element_options = &g_storageMenuElementOption,
|
|
||||||
.userdata = NULL
|
|
||||||
},
|
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -370,13 +376,7 @@ static MenuElement *g_gameCardHfsMenuElements[] = {
|
||||||
},
|
},
|
||||||
.userdata = NULL
|
.userdata = NULL
|
||||||
},
|
},
|
||||||
&(MenuElement){
|
&g_storageMenuElement,
|
||||||
.str = "output storage",
|
|
||||||
.child_menu = NULL,
|
|
||||||
.task_func = NULL,
|
|
||||||
.element_options = &g_storageMenuElementOption,
|
|
||||||
.userdata = NULL
|
|
||||||
},
|
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -456,13 +456,7 @@ static MenuElement *g_gameCardMenuElements[] = {
|
||||||
.element_options = NULL,
|
.element_options = NULL,
|
||||||
.userdata = NULL
|
.userdata = NULL
|
||||||
},
|
},
|
||||||
&(MenuElement){
|
&g_storageMenuElement,
|
||||||
.str = "output storage",
|
|
||||||
.child_menu = NULL,
|
|
||||||
.task_func = NULL,
|
|
||||||
.element_options = &g_storageMenuElementOption,
|
|
||||||
.userdata = NULL
|
|
||||||
},
|
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -570,13 +564,7 @@ static MenuElement *g_nspMenuElements[] = {
|
||||||
},
|
},
|
||||||
.userdata = NULL
|
.userdata = NULL
|
||||||
},
|
},
|
||||||
&(MenuElement){
|
&g_storageMenuElement,
|
||||||
.str = "output storage",
|
|
||||||
.child_menu = NULL,
|
|
||||||
.task_func = NULL,
|
|
||||||
.element_options = &g_storageMenuElementOption,
|
|
||||||
.userdata = NULL
|
|
||||||
},
|
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -608,13 +596,7 @@ static MenuElement *g_ticketMenuElements[] = {
|
||||||
},
|
},
|
||||||
.userdata = NULL
|
.userdata = NULL
|
||||||
},
|
},
|
||||||
&(MenuElement){
|
&g_storageMenuElement,
|
||||||
.str = "output storage",
|
|
||||||
.child_menu = NULL,
|
|
||||||
.task_func = NULL,
|
|
||||||
.element_options = &g_storageMenuElementOption,
|
|
||||||
.userdata = NULL
|
|
||||||
},
|
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -626,6 +608,20 @@ static Menu g_ticketMenu = {
|
||||||
.elements = g_ticketMenuElements
|
.elements = g_ticketMenuElements
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static bool g_ncaMenuRawMode = false;
|
||||||
|
static NcaContext *g_ncaFsSectionsMenuCtx = NULL;
|
||||||
|
|
||||||
|
static MenuElement **g_ncaFsSectionsMenuElements = NULL;
|
||||||
|
|
||||||
|
// Dynamically populated using g_ncaFsSectionsMenuElements.
|
||||||
|
static Menu g_ncaFsSectionsMenu = {
|
||||||
|
.id = MenuId_NCAFsSections,
|
||||||
|
.parent = NULL,
|
||||||
|
.selected = 0,
|
||||||
|
.scroll = 0,
|
||||||
|
.elements = NULL
|
||||||
|
};
|
||||||
|
|
||||||
static MenuElement **g_ncaMenuElements = NULL;
|
static MenuElement **g_ncaMenuElements = NULL;
|
||||||
|
|
||||||
// Dynamically populated using g_ncaMenuElements.
|
// Dynamically populated using g_ncaMenuElements.
|
||||||
|
@ -702,7 +698,7 @@ static MenuElement *g_userTitlesSubMenuElements[] = {
|
||||||
.userdata = NULL
|
.userdata = NULL
|
||||||
},
|
},
|
||||||
&(MenuElement){
|
&(MenuElement){
|
||||||
.str = "nca dump options",
|
.str = "nca / nca fs dump options",
|
||||||
.child_menu = &(Menu){
|
.child_menu = &(Menu){
|
||||||
.id = MenuId_NCATitleTypes,
|
.id = MenuId_NCATitleTypes,
|
||||||
.parent = NULL,
|
.parent = NULL,
|
||||||
|
@ -831,8 +827,9 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
consoleClear();
|
consoleClear();
|
||||||
consolePrint("______________________________\n\n");
|
consolePrint("______________________________\n\n");
|
||||||
consolePrint("press b to %s.\n", cur_menu->parent ? "go back" : "exit");
|
if (cur_menu->parent) consolePrint("press b to go back\n");
|
||||||
if (g_umsDeviceCount) consolePrint("press x to safely remove all ums devices\n");
|
if (g_umsDeviceCount) consolePrint("press x to safely remove all ums devices\n");
|
||||||
|
consolePrint("press + to exit\n");
|
||||||
consolePrint("______________________________\n\n");
|
consolePrint("______________________________\n\n");
|
||||||
|
|
||||||
if (cur_menu->id == MenuId_UserTitles)
|
if (cur_menu->id == MenuId_UserTitles)
|
||||||
|
@ -848,12 +845,12 @@ int main(int argc, char *argv[])
|
||||||
consolePrint("title info:\n\n");
|
consolePrint("title info:\n\n");
|
||||||
consolePrint("name: %s\n", app_metadata->lang_entry.name);
|
consolePrint("name: %s\n", app_metadata->lang_entry.name);
|
||||||
consolePrint("publisher: %s\n", app_metadata->lang_entry.author);
|
consolePrint("publisher: %s\n", app_metadata->lang_entry.author);
|
||||||
consolePrint("title id: %016lX\n", app_metadata->title_id);
|
if (cur_menu->id == MenuId_UserTitlesSubMenu) consolePrint("title id: %016lX\n", app_metadata->title_id);
|
||||||
consolePrint("______________________________\n\n");
|
consolePrint("______________________________\n\n");
|
||||||
|
|
||||||
if (cur_menu->id == MenuId_NSP || cur_menu->id == MenuId_Ticket || cur_menu->id == MenuId_NCA)
|
if (cur_menu->id == MenuId_NSP || cur_menu->id == MenuId_Ticket || cur_menu->id == MenuId_NCA || cur_menu->id == MenuId_NCAFsSections)
|
||||||
{
|
{
|
||||||
if (title_info->previous || title_info->next)
|
if (cur_menu->id != MenuId_NCAFsSections && (title_info->previous || title_info->next))
|
||||||
{
|
{
|
||||||
consolePrint("press l/zl and/or r/zr to change the selected title\n");
|
consolePrint("press l/zl and/or r/zr to change the selected title\n");
|
||||||
consolePrint("title: %u / %u\n", title_info_idx, title_info_count);
|
consolePrint("title: %u / %u\n", title_info_idx, title_info_count);
|
||||||
|
@ -873,6 +870,22 @@ int main(int argc, char *argv[])
|
||||||
if (cur_menu->id == MenuId_NSP) g_nspMenuElements[0]->userdata = title_info;
|
if (cur_menu->id == MenuId_NSP) g_nspMenuElements[0]->userdata = title_info;
|
||||||
|
|
||||||
if (cur_menu->id == MenuId_Ticket) g_ticketMenuElements[0]->userdata = title_info;
|
if (cur_menu->id == MenuId_Ticket) g_ticketMenuElements[0]->userdata = title_info;
|
||||||
|
|
||||||
|
if (cur_menu->id == MenuId_NCA)
|
||||||
|
{
|
||||||
|
consolePrint("press y to switch to %s mode\n", g_ncaMenuRawMode ? "nca fs section" : "raw nca");
|
||||||
|
consolePrint("______________________________\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cur_menu->id == MenuId_NCAFsSections)
|
||||||
|
{
|
||||||
|
consolePrint("selected nca info:\n\n");
|
||||||
|
consolePrint("content id: %s\n", g_ncaFsSectionsMenuCtx->content_id_str);
|
||||||
|
consolePrint("content type: %s\n", titleGetNcmContentTypeName(g_ncaFsSectionsMenuCtx->content_type));
|
||||||
|
consolePrint("id offset: %u\n", g_ncaFsSectionsMenuCtx->id_offset);
|
||||||
|
consolePrint("size: %s\n", g_ncaFsSectionsMenuCtx->content_size_str);
|
||||||
|
consolePrint("______________________________\n\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1007,6 +1020,16 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
error = true;
|
error = true;
|
||||||
}
|
}
|
||||||
|
} else
|
||||||
|
if (child_menu->id == MenuId_NCAFsSections)
|
||||||
|
{
|
||||||
|
updateNcaFsSectionsList((NcaUserData*)selected_element->userdata);
|
||||||
|
|
||||||
|
if (!g_ncaFsSectionsMenuElements || !g_ncaFsSectionsMenuElements[0])
|
||||||
|
{
|
||||||
|
consolePrint("failed to generate nca fs sections list\n");
|
||||||
|
error = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!error)
|
if (!error)
|
||||||
|
@ -1135,6 +1158,10 @@ int main(int argc, char *argv[])
|
||||||
if (cur_menu->id == MenuId_NCA)
|
if (cur_menu->id == MenuId_NCA)
|
||||||
{
|
{
|
||||||
freeNcaList();
|
freeNcaList();
|
||||||
|
} else
|
||||||
|
if (cur_menu->id == MenuId_NCAFsSections)
|
||||||
|
{
|
||||||
|
freeNcaFsSectionsList();
|
||||||
}
|
}
|
||||||
|
|
||||||
cur_menu->selected = 0;
|
cur_menu->selected = 0;
|
||||||
|
@ -1152,54 +1179,35 @@ int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
title_info = title_info->previous;
|
title_info = title_info->previous;
|
||||||
title_info_idx--;
|
title_info_idx--;
|
||||||
|
switchNcaListTitle(cur_menu, &element_count, title_info);
|
||||||
if (cur_menu->id == MenuId_NCA)
|
|
||||||
{
|
|
||||||
updateNcaList(title_info);
|
|
||||||
if (!g_ncaMenuElements || !g_ncaMenuElements[0])
|
|
||||||
{
|
|
||||||
freeNcaList();
|
|
||||||
consolePrint("\nfailed to generate nca list for newly selected title\npress any button to go back\n");
|
|
||||||
consoleRefresh();
|
|
||||||
utilsWaitForButtonPress(0);
|
|
||||||
|
|
||||||
cur_menu->selected = 0;
|
|
||||||
cur_menu->scroll = 0;
|
|
||||||
|
|
||||||
cur_menu = cur_menu->parent;
|
|
||||||
element_count = menuGetElementCount(cur_menu);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else
|
} else
|
||||||
if (((btn_down & (HidNpadButton_R)) || (btn_held & HidNpadButton_ZR)) && (cur_menu->id == MenuId_NSP || cur_menu->id == MenuId_Ticket || cur_menu->id == MenuId_NCA) && title_info->next)
|
if (((btn_down & (HidNpadButton_R)) || (btn_held & HidNpadButton_ZR)) && (cur_menu->id == MenuId_NSP || cur_menu->id == MenuId_Ticket || cur_menu->id == MenuId_NCA) && title_info->next)
|
||||||
{
|
{
|
||||||
title_info = title_info->next;
|
title_info = title_info->next;
|
||||||
title_info_idx++;
|
title_info_idx++;
|
||||||
|
switchNcaListTitle(cur_menu, &element_count, title_info);
|
||||||
|
} else
|
||||||
|
if ((btn_down & HidNpadButton_Y) && cur_menu->id == MenuId_NCA)
|
||||||
|
{
|
||||||
|
/* Change NCA menu element properties. */
|
||||||
|
g_ncaMenuRawMode ^= 1;
|
||||||
|
|
||||||
if (cur_menu->id == MenuId_NCA)
|
for(u32 i = 0; g_ncaMenuElements[i]; i++)
|
||||||
{
|
{
|
||||||
updateNcaList(title_info);
|
g_ncaMenuElements[i]->child_menu = (g_ncaMenuRawMode ? NULL : &g_ncaFsSectionsMenu);
|
||||||
if (!g_ncaMenuElements || !g_ncaMenuElements[0])
|
g_ncaMenuElements[i]->task_func = (g_ncaMenuRawMode ? &saveNintendoContentArchive : NULL);
|
||||||
{
|
|
||||||
freeNcaList();
|
|
||||||
consolePrint("\nfailed to generate nca list for newly selected title\npress any button to go back\n");
|
|
||||||
consoleRefresh();
|
|
||||||
utilsWaitForButtonPress(0);
|
|
||||||
|
|
||||||
cur_menu->selected = 0;
|
|
||||||
cur_menu->scroll = 0;
|
|
||||||
|
|
||||||
cur_menu = cur_menu->parent;
|
|
||||||
element_count = menuGetElementCount(cur_menu);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} else
|
||||||
|
if (btn_down & HidNpadButton_Plus)
|
||||||
|
{
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
svcSleepThread(50000000); // 50 ms
|
if (btn_held & (HidNpadButton_StickLDown | HidNpadButton_StickRDown | HidNpadButton_StickLUp | HidNpadButton_StickRUp | HidNpadButton_ZL | HidNpadButton_ZR)) svcSleepThread(50000000); // 50 ms
|
||||||
}
|
}
|
||||||
|
|
||||||
end:
|
end:
|
||||||
titleFreeUserApplicationData(&user_app_data);
|
freeNcaFsSectionsList();
|
||||||
|
|
||||||
freeNcaList();
|
freeNcaList();
|
||||||
|
|
||||||
|
@ -1207,6 +1215,8 @@ end:
|
||||||
|
|
||||||
freeStorageList();
|
freeStorageList();
|
||||||
|
|
||||||
|
titleFreeUserApplicationData(&user_app_data);
|
||||||
|
|
||||||
utilsCloseResources();
|
utilsCloseResources();
|
||||||
|
|
||||||
consoleExit(NULL);
|
consoleExit(NULL);
|
||||||
|
@ -1429,7 +1439,11 @@ void freeNcaList(void)
|
||||||
/* Free all previously allocated data. */
|
/* Free all previously allocated data. */
|
||||||
if (g_ncaMenuElements)
|
if (g_ncaMenuElements)
|
||||||
{
|
{
|
||||||
for(u32 i = 0; g_ncaMenuElements[i] != NULL; i++)
|
u32 count = 0;
|
||||||
|
|
||||||
|
for(count = 0; g_ncaMenuElements[count]; count++);
|
||||||
|
|
||||||
|
for(u32 i = 0; count > 0 && i < (count - 1); i++) // Don't free output storage element
|
||||||
{
|
{
|
||||||
if (g_ncaMenuElements[i]->str) free(g_ncaMenuElements[i]->str);
|
if (g_ncaMenuElements[i]->str) free(g_ncaMenuElements[i]->str);
|
||||||
if (g_ncaMenuElements[i]->userdata) free(g_ncaMenuElements[i]->userdata);
|
if (g_ncaMenuElements[i]->userdata) free(g_ncaMenuElements[i]->userdata);
|
||||||
|
@ -1456,12 +1470,12 @@ void updateNcaList(TitleInfo *title_info)
|
||||||
freeNcaList();
|
freeNcaList();
|
||||||
|
|
||||||
/* Reallocate buffer. */
|
/* Reallocate buffer. */
|
||||||
tmp = realloc(g_ncaMenuElements, (content_count + 1) * sizeof(MenuElement*)); // NULL terminator
|
tmp = realloc(g_ncaMenuElements, (content_count + 2) * sizeof(MenuElement*)); // Output storage, NULL terminator
|
||||||
|
|
||||||
g_ncaMenuElements = tmp;
|
g_ncaMenuElements = tmp;
|
||||||
tmp = NULL;
|
tmp = NULL;
|
||||||
|
|
||||||
memset(g_ncaMenuElements, 0, (content_count + 1) * sizeof(MenuElement*)); // NULL terminator
|
memset(g_ncaMenuElements, 0, (content_count + 2) * sizeof(MenuElement*)); // Output storage, NULL terminator
|
||||||
|
|
||||||
/* Generate menu elements. */
|
/* Generate menu elements. */
|
||||||
for(u32 i = 0; i < content_count; i++)
|
for(u32 i = 0; i < content_count; i++)
|
||||||
|
@ -1495,16 +1509,113 @@ void updateNcaList(TitleInfo *title_info)
|
||||||
nca_user_data->content_idx = i;
|
nca_user_data->content_idx = i;
|
||||||
|
|
||||||
g_ncaMenuElements[idx]->str = nca_info_str;
|
g_ncaMenuElements[idx]->str = nca_info_str;
|
||||||
//g_ncaMenuElements[idx]->child_menu = NULL;
|
g_ncaMenuElements[idx]->child_menu = (g_ncaMenuRawMode ? NULL : &g_ncaFsSectionsMenu);
|
||||||
g_ncaMenuElements[idx]->task_func = &saveNintendoContentArchive;
|
g_ncaMenuElements[idx]->task_func = (g_ncaMenuRawMode ? &saveNintendoContentArchive : NULL);
|
||||||
g_ncaMenuElements[idx]->userdata = nca_user_data;
|
g_ncaMenuElements[idx]->userdata = nca_user_data;
|
||||||
|
|
||||||
idx++;
|
idx++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_ncaMenuElements[content_count] = &g_storageMenuElement;
|
||||||
|
|
||||||
g_ncaMenu.elements = g_ncaMenuElements;
|
g_ncaMenu.elements = g_ncaMenuElements;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void switchNcaListTitle(Menu *cur_menu, u32 *element_count, TitleInfo *title_info)
|
||||||
|
{
|
||||||
|
if (!cur_menu || cur_menu->id != MenuId_NCA || !element_count) return;
|
||||||
|
|
||||||
|
updateNcaList(title_info);
|
||||||
|
|
||||||
|
if (!g_ncaMenuElements || !g_ncaMenuElements[0])
|
||||||
|
{
|
||||||
|
freeNcaList();
|
||||||
|
consolePrint("\nfailed to generate nca list for newly selected title\npress any button to go back\n");
|
||||||
|
consoleRefresh();
|
||||||
|
utilsWaitForButtonPress(0);
|
||||||
|
|
||||||
|
cur_menu->selected = 0;
|
||||||
|
cur_menu->scroll = 0;
|
||||||
|
|
||||||
|
cur_menu = cur_menu->parent;
|
||||||
|
*element_count = menuGetElementCount(cur_menu);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void freeNcaFsSectionsList(void)
|
||||||
|
{
|
||||||
|
/* Free all previously allocated data. */
|
||||||
|
if (g_ncaFsSectionsMenuCtx)
|
||||||
|
{
|
||||||
|
free(g_ncaFsSectionsMenuCtx);
|
||||||
|
g_ncaFsSectionsMenuCtx = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_ncaFsSectionsMenuElements)
|
||||||
|
{
|
||||||
|
for(u32 i = 0; g_ncaFsSectionsMenuElements[i] != NULL; i++)
|
||||||
|
{
|
||||||
|
if (g_ncaFsSectionsMenuElements[i]->str) free(g_ncaFsSectionsMenuElements[i]->str);
|
||||||
|
free(g_ncaFsSectionsMenuElements[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(g_ncaFsSectionsMenuElements);
|
||||||
|
g_ncaFsSectionsMenuElements = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_ncaFsSectionsMenu.scroll = 0;
|
||||||
|
g_ncaFsSectionsMenu.selected = 0;
|
||||||
|
g_ncaFsSectionsMenu.elements = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateNcaFsSectionsList(NcaUserData *nca_user_data)
|
||||||
|
{
|
||||||
|
TitleInfo *title_info = nca_user_data->title_info;
|
||||||
|
NcmContentInfo *content_info = &(title_info->content_infos[nca_user_data->content_idx]);
|
||||||
|
MenuElement **tmp = NULL;
|
||||||
|
u32 idx = 0;
|
||||||
|
|
||||||
|
/* Free all previously allocated data. */
|
||||||
|
freeNcaFsSectionsList();
|
||||||
|
|
||||||
|
/* Reallocate buffer. */
|
||||||
|
tmp = realloc(g_ncaFsSectionsMenuElements, (NCA_FS_HEADER_COUNT + 1) * sizeof(MenuElement*)); // NULL terminator
|
||||||
|
|
||||||
|
g_ncaFsSectionsMenuElements = tmp;
|
||||||
|
tmp = NULL;
|
||||||
|
|
||||||
|
memset(g_ncaFsSectionsMenuElements, 0, (NCA_FS_HEADER_COUNT + 1) * sizeof(MenuElement*)); // NULL terminator
|
||||||
|
|
||||||
|
/* Initialize NCA context. */
|
||||||
|
g_ncaFsSectionsMenuCtx = calloc(1, sizeof(NcaContext));
|
||||||
|
if (!ncaInitializeContext(g_ncaFsSectionsMenuCtx, title_info->storage_id, (title_info->storage_id == NcmStorageId_GameCard ? HashFileSystemPartitionType_Secure : 0), \
|
||||||
|
content_info, title_info->version.value, NULL)) return;
|
||||||
|
|
||||||
|
/* Generate menu elements. */
|
||||||
|
for(u32 i = 0; i < NCA_FS_HEADER_COUNT; i++)
|
||||||
|
{
|
||||||
|
NcaFsSectionContext *cur_nca_fs_ctx = &(g_ncaFsSectionsMenuCtx->fs_ctx[i]);
|
||||||
|
char *nca_fs_info_str = NULL, nca_fs_size_str[16] = {0};
|
||||||
|
|
||||||
|
g_ncaFsSectionsMenuElements[idx] = calloc(1, sizeof(MenuElement));
|
||||||
|
if (!g_ncaFsSectionsMenuElements[idx]) continue;
|
||||||
|
|
||||||
|
nca_fs_info_str = calloc(128, sizeof(char));
|
||||||
|
if (!nca_fs_info_str) continue;
|
||||||
|
|
||||||
|
utilsGenerateFormattedSizeString((double)cur_nca_fs_ctx->section_size, nca_fs_size_str, sizeof(nca_fs_size_str));
|
||||||
|
sprintf(nca_fs_info_str, "FS section #%u: %s (%s)", i + 1, ncaGetFsSectionTypeName(cur_nca_fs_ctx), nca_fs_size_str);
|
||||||
|
|
||||||
|
g_ncaFsSectionsMenuElements[idx]->str = nca_fs_info_str;
|
||||||
|
g_ncaFsSectionsMenuElements[idx]->child_menu = NULL;
|
||||||
|
g_ncaFsSectionsMenuElements[idx]->userdata = cur_nca_fs_ctx;
|
||||||
|
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_ncaFsSectionsMenu.elements = g_ncaFsSectionsMenuElements;
|
||||||
|
}
|
||||||
|
|
||||||
NX_INLINE bool useUsbHost(void)
|
NX_INLINE bool useUsbHost(void)
|
||||||
{
|
{
|
||||||
return (g_storageMenuElementOption.selected == 1);
|
return (g_storageMenuElementOption.selected == 1);
|
||||||
|
|
|
@ -436,6 +436,7 @@ struct _NcaContext {
|
||||||
u8 format_version; ///< NcaVersion.
|
u8 format_version; ///< NcaVersion.
|
||||||
u8 content_type; ///< NcmContentType. Retrieved from NcmContentInfo.
|
u8 content_type; ///< NcmContentType. Retrieved from NcmContentInfo.
|
||||||
u64 content_size; ///< Retrieved from NcmContentInfo.
|
u64 content_size; ///< Retrieved from NcmContentInfo.
|
||||||
|
char content_size_str[0x10];
|
||||||
u8 key_generation; ///< NcaKeyGeneration. Retrieved from the decrypted header.
|
u8 key_generation; ///< NcaKeyGeneration. Retrieved from the decrypted header.
|
||||||
u8 id_offset; ///< Retrieved from NcmContentInfo.
|
u8 id_offset; ///< Retrieved from NcmContentInfo.
|
||||||
u32 title_version;
|
u32 title_version;
|
||||||
|
|
|
@ -203,7 +203,9 @@ bool ncaInitializeContext(NcaContext *out, u8 storage_id, u8 hfs_partition_type,
|
||||||
out->content_type = content_info->content_type;
|
out->content_type = content_info->content_type;
|
||||||
out->id_offset = content_info->id_offset;
|
out->id_offset = content_info->id_offset;
|
||||||
out->title_version = title_version;
|
out->title_version = title_version;
|
||||||
|
|
||||||
ncmContentInfoSizeToU64(content_info, &(out->content_size));
|
ncmContentInfoSizeToU64(content_info, &(out->content_size));
|
||||||
|
utilsGenerateFormattedSizeString((double)out->content_size, out->content_size_str, sizeof(out->content_size_str));
|
||||||
|
|
||||||
if (out->content_size < NCA_FULL_HEADER_LENGTH)
|
if (out->content_size < NCA_FULL_HEADER_LENGTH)
|
||||||
{
|
{
|
||||||
|
|
|
@ -651,7 +651,15 @@ void utilsGenerateFormattedSizeString(double size, char *dst, size_t dst_size)
|
||||||
if (size >= pow(1024.0, i + 1) && (i + 1) < g_sizeSuffixesCount) continue;
|
if (size >= pow(1024.0, i + 1) && (i + 1) < g_sizeSuffixesCount) continue;
|
||||||
|
|
||||||
size /= pow(1024.0, i);
|
size /= pow(1024.0, i);
|
||||||
snprintf(dst, dst_size, "%.2F %s", size, g_sizeSuffixes[i]);
|
|
||||||
|
if (i == 0)
|
||||||
|
{
|
||||||
|
/* Don't display decimal places if we're dealing with plain bytes. */
|
||||||
|
snprintf(dst, dst_size, "%.0f %s", size, g_sizeSuffixes[i]);
|
||||||
|
} else {
|
||||||
|
snprintf(dst, dst_size, "%.2f %s", size, g_sizeSuffixes[i]);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue