mirror of
https://github.com/DarkMatterCore/nxdumptool.git
synced 2024-11-22 18:26:39 +00:00
bktr: perform binary search in bktrGetTreeNodeEntryIndex()
Other changes include: * poc: fix switching to a different title entry via L/R/ZL/ZR if the content counts don't match. Fixes issues with MGS Master Collection games.
This commit is contained in:
parent
5ffe06508e
commit
7b707509c7
4 changed files with 59 additions and 39 deletions
4
Makefile
4
Makefile
|
@ -86,8 +86,8 @@ ARCH := -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE
|
|||
|
||||
CFLAGS := -g -Wall -Werror -O2 -ffunction-sections $(ARCH) $(DEFINES) $(INCLUDE) -D__SWITCH__
|
||||
CFLAGS += -DVERSION_MAJOR=${VERSION_MAJOR} -DVERSION_MINOR=${VERSION_MINOR} -DVERSION_MICRO=${VERSION_MICRO}
|
||||
CFLAGS += -DAPP_TITLE=\"${APP_TITLE}\" -DAPP_AUTHOR=\"${APP_AUTHOR}\" -DAPP_VERSION=\"${APP_VERSION}\"
|
||||
CFLAGS += -DGIT_BRANCH=\"${GIT_BRANCH}\" -DGIT_COMMIT=\"${GIT_COMMIT}\" -DGIT_REV=\"${GIT_REV}\"
|
||||
CFLAGS += -DAPP_TITLE="\"${APP_TITLE}\"" -DAPP_AUTHOR="\"${APP_AUTHOR}\"" -DAPP_VERSION="\"${APP_VERSION}\""
|
||||
CFLAGS += -DGIT_BRANCH="\"${GIT_BRANCH}\"" -DGIT_COMMIT="\"${GIT_COMMIT}\"" -DGIT_REV="\"${GIT_REV}\""
|
||||
CFLAGS += -DBUILD_TIMESTAMP="\"${BUILD_TIMESTAMP}\"" -DBOREALIS_RESOURCES="\"${BOREALIS_RESOURCES}\"" -D_GNU_SOURCE
|
||||
CFLAGS += -fmacro-prefix-map=$(ROOTDIR)=
|
||||
|
||||
|
|
2
build.sh
2
build.sh
|
@ -31,3 +31,5 @@ make clean_all
|
|||
|
||||
rm -f ./source/main.c
|
||||
mv -f ./main.cpp ./source/main.cpp
|
||||
|
||||
read -rsp $'Press any key to continue...\n' -n 1 key
|
||||
|
|
|
@ -181,8 +181,8 @@ void updateTitleList(Menu *menu, Menu *submenu, bool is_system);
|
|||
static TitleInfo *getLatestTitleInfo(TitleInfo *title_info, u32 *out_idx, u32 *out_count);
|
||||
|
||||
void freeNcaList(void);
|
||||
void updateNcaList(TitleInfo *title_info);
|
||||
static void switchNcaListTitle(Menu *cur_menu, u32 *element_count, TitleInfo *title_info);
|
||||
void updateNcaList(TitleInfo *title_info, u32 *element_count);
|
||||
static void switchNcaListTitle(Menu **cur_menu, u32 *element_count, TitleInfo *title_info);
|
||||
|
||||
void freeNcaFsSectionsList(void);
|
||||
void updateNcaFsSectionsList(NcaUserData *nca_user_data);
|
||||
|
@ -1272,7 +1272,7 @@ int main(int argc, char *argv[])
|
|||
|
||||
if (child_menu->id == MenuId_Nca)
|
||||
{
|
||||
updateNcaList(title_info);
|
||||
updateNcaList(title_info, &element_count);
|
||||
|
||||
if (!g_ncaMenuElements || !g_ncaMenuElements[0])
|
||||
{
|
||||
|
@ -1516,13 +1516,13 @@ int main(int argc, char *argv[])
|
|||
{
|
||||
title_info = title_info->previous;
|
||||
title_info_idx--;
|
||||
switchNcaListTitle(cur_menu, &element_count, title_info);
|
||||
switchNcaListTitle(&cur_menu, &element_count, title_info);
|
||||
} 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)
|
||||
{
|
||||
title_info = title_info->next;
|
||||
title_info_idx++;
|
||||
switchNcaListTitle(cur_menu, &element_count, title_info);
|
||||
switchNcaListTitle(&cur_menu, &element_count, title_info);
|
||||
} else
|
||||
if ((btn_down & HidNpadButton_Y) && cur_menu->id == MenuId_Nca)
|
||||
{
|
||||
|
@ -1883,7 +1883,7 @@ void freeNcaList(void)
|
|||
g_ncaMenu.elements = NULL;
|
||||
}
|
||||
|
||||
void updateNcaList(TitleInfo *title_info)
|
||||
void updateNcaList(TitleInfo *title_info, u32 *element_count)
|
||||
{
|
||||
u32 content_count = title_info->content_count, idx = 0;
|
||||
NcmContentInfo *content_infos = title_info->content_infos;
|
||||
|
@ -1894,6 +1894,7 @@ void updateNcaList(TitleInfo *title_info)
|
|||
|
||||
/* Allocate buffer. */
|
||||
g_ncaMenuElements = calloc(content_count + 2, sizeof(MenuElement*)); // Output storage, NULL terminator
|
||||
if (!g_ncaMenuElements) return;
|
||||
|
||||
/* Generate menu elements. */
|
||||
for(u32 i = 0; i < content_count; i++)
|
||||
|
@ -1937,16 +1938,21 @@ void updateNcaList(TitleInfo *title_info)
|
|||
idx++;
|
||||
}
|
||||
|
||||
g_ncaMenuElements[content_count] = &g_storageMenuElement;
|
||||
if (idx > 0)
|
||||
{
|
||||
g_ncaMenuElements[idx] = &g_storageMenuElement;
|
||||
|
||||
g_ncaMenu.elements = g_ncaMenuElements;
|
||||
|
||||
if (element_count) *element_count = (idx + 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void switchNcaListTitle(Menu *cur_menu, u32 *element_count, TitleInfo *title_info)
|
||||
static void switchNcaListTitle(Menu **cur_menu, u32 *element_count, TitleInfo *title_info)
|
||||
{
|
||||
if (!cur_menu || cur_menu->id != MenuId_Nca || !element_count) return;
|
||||
if (!cur_menu || !*cur_menu || (*cur_menu)->id != MenuId_Nca || !element_count || !title_info) return;
|
||||
|
||||
updateNcaList(title_info);
|
||||
updateNcaList(title_info, element_count);
|
||||
|
||||
if (!g_ncaMenuElements || !g_ncaMenuElements[0])
|
||||
{
|
||||
|
@ -1955,11 +1961,11 @@ static void switchNcaListTitle(Menu *cur_menu, u32 *element_count, TitleInfo *ti
|
|||
consoleRefresh();
|
||||
utilsWaitForButtonPress(0);
|
||||
|
||||
cur_menu->selected = 0;
|
||||
cur_menu->scroll = 0;
|
||||
(*cur_menu)->selected = 0;
|
||||
(*cur_menu)->scroll = 0;
|
||||
|
||||
cur_menu = cur_menu->parent;
|
||||
*element_count = menuGetElementCount(cur_menu);
|
||||
*cur_menu = (*cur_menu)->parent;
|
||||
*element_count = menuGetElementCount(*cur_menu);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1253,10 +1253,12 @@ static bool bktrValidateTableOffsetNode(const BucketTreeTable *table, u64 node_s
|
|||
u32 offset_count = bktrGetOffsetCount(node_size);
|
||||
u32 entry_set_count = bktrGetEntrySetCount(node_size, entry_size, entry_count);
|
||||
|
||||
const u64 start_offset = ((offset_count < entry_set_count && node_header->count < offset_count) ? *bktrGetOffsetNodeEnd(offset_node) : *bktrGetOffsetNodeBegin(offset_node));
|
||||
u64 node_start_offset = *bktrGetOffsetNodeBegin(offset_node);
|
||||
|
||||
u64 start_offset = ((offset_count < entry_set_count && node_header->count < offset_count) ? *bktrGetOffsetNodeEnd(offset_node) : node_start_offset);
|
||||
u64 end_offset = node_header->offset;
|
||||
|
||||
if (start_offset > *bktrGetOffsetNodeBegin(offset_node) || start_offset >= end_offset || node_header->count != entry_set_count)
|
||||
if (start_offset > node_start_offset || start_offset >= end_offset || node_header->count != entry_set_count)
|
||||
{
|
||||
LOG_MSG_ERROR("Invalid Bucket Tree Offset Node!");
|
||||
return false;
|
||||
|
@ -1353,13 +1355,14 @@ static bool bktrFindStorageEntry(BucketTreeContext *ctx, u64 virtual_offset, Buc
|
|||
|
||||
/* Get the entry node index. */
|
||||
u32 entry_set_index = 0;
|
||||
const u64 *node_start_ptr = bktrGetOffsetNodeBegin(offset_node), *node_end_ptr = bktrGetOffsetNodeEnd(offset_node);
|
||||
const u64 *start_ptr = NULL, *end_ptr = NULL;
|
||||
bool success = false;
|
||||
|
||||
if (bktrIsExistOffsetL2OnL1(ctx) && virtual_offset < *bktrGetOffsetNodeBegin(offset_node))
|
||||
if (bktrIsExistOffsetL2OnL1(ctx) && virtual_offset < *node_start_ptr)
|
||||
{
|
||||
start_ptr = bktrGetOffsetNodeEnd(offset_node);
|
||||
end_ptr = (bktrGetOffsetNodeBegin(offset_node) + ctx->offset_count);
|
||||
start_ptr = node_end_ptr;
|
||||
end_ptr = (node_start_ptr + ctx->offset_count);
|
||||
|
||||
if (!bktrGetTreeNodeEntryIndex(start_ptr, end_ptr, virtual_offset, &entry_set_index))
|
||||
{
|
||||
|
@ -1367,8 +1370,8 @@ static bool bktrFindStorageEntry(BucketTreeContext *ctx, u64 virtual_offset, Buc
|
|||
goto end;
|
||||
}
|
||||
} else {
|
||||
start_ptr = bktrGetOffsetNodeBegin(offset_node);
|
||||
end_ptr = bktrGetOffsetNodeEnd(offset_node);
|
||||
start_ptr = node_start_ptr;
|
||||
end_ptr = node_end_ptr;
|
||||
|
||||
if (!bktrGetTreeNodeEntryIndex(start_ptr, end_ptr, virtual_offset, &entry_set_index))
|
||||
{
|
||||
|
@ -1410,28 +1413,37 @@ static bool bktrGetTreeNodeEntryIndex(const u64 *start_ptr, const u64 *end_ptr,
|
|||
return false;
|
||||
}
|
||||
|
||||
u64 *pos = (u64*)start_ptr;
|
||||
u32 index = 0;
|
||||
/* Perform a binary search. */
|
||||
u32 offset_count = (u32)(end_ptr - start_ptr), low = 0, high = (offset_count - 1);
|
||||
bool ret = false;
|
||||
|
||||
while(pos < end_ptr)
|
||||
while(low <= high)
|
||||
{
|
||||
if (start_ptr < pos)
|
||||
{
|
||||
/* Stop looking if we have found the right offset node. */
|
||||
if (*pos > virtual_offset) break;
|
||||
/* Get the index to the middle offset within our current lookup range. */
|
||||
u32 half = ((low + high) / 2);
|
||||
|
||||
/* Increment index. */
|
||||
index++;
|
||||
/* Check middle offset value. */
|
||||
const u64 *ptr = (start_ptr + half);
|
||||
if (*ptr > virtual_offset)
|
||||
{
|
||||
/* Update our upper limit. */
|
||||
high = (half - 1);
|
||||
} else {
|
||||
/* Check for success. */
|
||||
if (half == (offset_count - 1) || *(ptr + 1) > virtual_offset)
|
||||
{
|
||||
/* Update output. */
|
||||
*out_index = half;
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Increment offset node pointer. */
|
||||
pos++;
|
||||
/* Update our lower limit. */
|
||||
low = (half + 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Update output index. */
|
||||
*out_index = index;
|
||||
|
||||
return true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool bktrGetEntryNodeEntryIndex(const BucketTreeNodeHeader *node_header, u64 entry_size, u64 virtual_offset, u32 *out_index)
|
||||
|
|
Loading…
Reference in a new issue