mirror of
https://gitlab.com/Theopse/fbi-i18n-zh.git
synced 2025-04-06 03:58:02 +08:00
Add filter options.
This commit is contained in:
parent
e73b07bbd8
commit
b87332ff68
@ -5,3 +5,5 @@ gamecard=FFFF0000
|
|||||||
dstitle=FF82004B
|
dstitle=FF82004B
|
||||||
file=FF000000
|
file=FF000000
|
||||||
directory=FF0000FF
|
directory=FF0000FF
|
||||||
|
enabled=FF00FF00
|
||||||
|
disabled=FF0000FF
|
@ -203,6 +203,10 @@ void screen_init() {
|
|||||||
colorConfig[COLOR_FILE] = color;
|
colorConfig[COLOR_FILE] = color;
|
||||||
} else if(strcasecmp(key, "directory") == 0) {
|
} else if(strcasecmp(key, "directory") == 0) {
|
||||||
colorConfig[COLOR_DIRECTORY] = color;
|
colorConfig[COLOR_DIRECTORY] = color;
|
||||||
|
} else if(strcasecmp(key, "enabled") == 0) {
|
||||||
|
colorConfig[COLOR_ENABLED] = color;
|
||||||
|
} else if(strcasecmp(key, "disabled") == 0) {
|
||||||
|
colorConfig[COLOR_DISABLED] = color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@
|
|||||||
#define TEXTURE_WIFI_3 30
|
#define TEXTURE_WIFI_3 30
|
||||||
#define TEXTURE_AUTO_START 31
|
#define TEXTURE_AUTO_START 31
|
||||||
|
|
||||||
#define NUM_COLORS 7
|
#define NUM_COLORS 9
|
||||||
|
|
||||||
#define COLOR_TEXT 0
|
#define COLOR_TEXT 0
|
||||||
#define COLOR_NAND 1
|
#define COLOR_NAND 1
|
||||||
@ -50,6 +50,8 @@
|
|||||||
#define COLOR_DS_TITLE 4
|
#define COLOR_DS_TITLE 4
|
||||||
#define COLOR_FILE 5
|
#define COLOR_FILE 5
|
||||||
#define COLOR_DIRECTORY 6
|
#define COLOR_DIRECTORY 6
|
||||||
|
#define COLOR_ENABLED 7
|
||||||
|
#define COLOR_DISABLED 8
|
||||||
|
|
||||||
void screen_init();
|
void screen_init();
|
||||||
void screen_exit();
|
void screen_exit();
|
||||||
|
@ -19,6 +19,9 @@ static list_item delete_save_data = {"Delete Save Data", COLOR_TEXT, action_dele
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
populate_ext_save_data_data populateData;
|
populate_ext_save_data_data populateData;
|
||||||
|
|
||||||
|
bool showSD;
|
||||||
|
bool showNAND;
|
||||||
|
|
||||||
bool populated;
|
bool populated;
|
||||||
} extsavedata_data;
|
} extsavedata_data;
|
||||||
|
|
||||||
@ -77,6 +80,54 @@ static void extsavedata_action_open(linked_list* items, list_item* selected) {
|
|||||||
list_display("Ext Save Data Action", "A: Select, B: Return", data, extsavedata_action_update, extsavedata_action_draw_top);
|
list_display("Ext Save Data Action", "A: Select, B: Return", data, extsavedata_action_update, extsavedata_action_draw_top);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void extsavedata_filters_add_entry(linked_list* items, const char* name, bool* val) {
|
||||||
|
list_item* item = (list_item*) calloc(1, sizeof(list_item));
|
||||||
|
if(item != NULL) {
|
||||||
|
snprintf(item->name, LIST_ITEM_NAME_MAX, "%s", name);
|
||||||
|
item->color = *val ? COLOR_ENABLED : COLOR_DISABLED;
|
||||||
|
item->data = val;
|
||||||
|
|
||||||
|
linked_list_add(items, item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void extsavedata_filters_update(ui_view* view, void* data, linked_list* items, list_item* selected, bool selectedTouched) {
|
||||||
|
extsavedata_data* listData = (extsavedata_data*) data;
|
||||||
|
|
||||||
|
if(hidKeysDown() & KEY_B) {
|
||||||
|
linked_list_iter iter;
|
||||||
|
linked_list_iterate(items, &iter);
|
||||||
|
|
||||||
|
while(linked_list_iter_has_next(&iter)) {
|
||||||
|
free(linked_list_iter_next(&iter));
|
||||||
|
linked_list_iter_remove(&iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
ui_pop();
|
||||||
|
list_destroy(view);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(selected != NULL && selected->data != NULL && (selectedTouched || (hidKeysDown() & KEY_A))) {
|
||||||
|
bool* val = (bool*) selected->data;
|
||||||
|
*val = !(*val);
|
||||||
|
|
||||||
|
selected->color = *val ? COLOR_ENABLED : COLOR_DISABLED;
|
||||||
|
|
||||||
|
listData->populated = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(linked_list_size(items) == 0) {
|
||||||
|
extsavedata_filters_add_entry(items, "Show SD", &listData->showSD);
|
||||||
|
extsavedata_filters_add_entry(items, "Show NAND", &listData->showNAND);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void extsavedata_filters_open(extsavedata_data* data) {
|
||||||
|
list_display("Filters", "A: Toggle, B: Return", data, extsavedata_filters_update, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static void extsavedata_draw_top(ui_view* view, void* data, float x1, float y1, float x2, float y2, list_item* selected) {
|
static void extsavedata_draw_top(ui_view* view, void* data, float x1, float y1, float x2, float y2, list_item* selected) {
|
||||||
if(selected != NULL && selected->data != NULL) {
|
if(selected != NULL && selected->data != NULL) {
|
||||||
ui_draw_ext_save_data_info(view, selected->data, x1, y1, x2, y2);
|
ui_draw_ext_save_data_info(view, selected->data, x1, y1, x2, y2);
|
||||||
@ -103,6 +154,11 @@ static void extsavedata_update(ui_view* view, void* data, linked_list* items, li
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(hidKeysDown() & KEY_SELECT) {
|
||||||
|
extsavedata_filters_open(listData);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(!listData->populated || (hidKeysDown() & KEY_X)) {
|
if(!listData->populated || (hidKeysDown() & KEY_X)) {
|
||||||
if(!listData->populateData.finished) {
|
if(!listData->populateData.finished) {
|
||||||
svcSignalEvent(listData->populateData.cancelEvent);
|
svcSignalEvent(listData->populateData.cancelEvent);
|
||||||
@ -132,6 +188,16 @@ static void extsavedata_update(ui_view* view, void* data, linked_list* items, li
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool extsavedata_filter(void* data, u64 titleId, FS_MediaType mediaType) {
|
||||||
|
extsavedata_data* listData = (extsavedata_data*) data;
|
||||||
|
|
||||||
|
if(mediaType == MEDIATYPE_SD) {
|
||||||
|
return listData->showSD;
|
||||||
|
} else {
|
||||||
|
return listData->showNAND;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void extsavedata_open() {
|
void extsavedata_open() {
|
||||||
extsavedata_data* data = (extsavedata_data*) calloc(1, sizeof(extsavedata_data));
|
extsavedata_data* data = (extsavedata_data*) calloc(1, sizeof(extsavedata_data));
|
||||||
if(data == NULL) {
|
if(data == NULL) {
|
||||||
@ -140,7 +206,13 @@ void extsavedata_open() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data->populateData.filter = extsavedata_filter;
|
||||||
|
data->populateData.filterData = data;
|
||||||
|
|
||||||
data->populateData.finished = true;
|
data->populateData.finished = true;
|
||||||
|
|
||||||
list_display("Ext Save Data", "A: Select, B: Return, X: Refresh", data, extsavedata_update, extsavedata_draw_top);
|
data->showSD = true;
|
||||||
|
data->showNAND = true;
|
||||||
|
|
||||||
|
list_display("Ext Save Data", "A: Select, B: Return, X: Refresh, Select: Filter", data, extsavedata_update, extsavedata_draw_top);
|
||||||
}
|
}
|
@ -48,6 +48,11 @@ typedef struct {
|
|||||||
FS_Path archivePath;
|
FS_Path archivePath;
|
||||||
FS_Archive archive;
|
FS_Archive archive;
|
||||||
|
|
||||||
|
bool showDirectories;
|
||||||
|
bool showCias;
|
||||||
|
bool showTickets;
|
||||||
|
bool showMisc;
|
||||||
|
|
||||||
char currDir[FILE_PATH_MAX];
|
char currDir[FILE_PATH_MAX];
|
||||||
list_item* dirItem;
|
list_item* dirItem;
|
||||||
} files_data;
|
} files_data;
|
||||||
@ -152,6 +157,56 @@ static void files_action_open(linked_list* items, list_item* selected, files_dat
|
|||||||
list_display(((file_info*) selected->data)->isDirectory ? "Directory Action" : "File Action", "A: Select, B: Return", data, files_action_update, files_action_draw_top);
|
list_display(((file_info*) selected->data)->isDirectory ? "Directory Action" : "File Action", "A: Select, B: Return", data, files_action_update, files_action_draw_top);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void files_filters_add_entry(linked_list* items, const char* name, bool* val) {
|
||||||
|
list_item* item = (list_item*) calloc(1, sizeof(list_item));
|
||||||
|
if(item != NULL) {
|
||||||
|
snprintf(item->name, LIST_ITEM_NAME_MAX, "%s", name);
|
||||||
|
item->color = *val ? COLOR_ENABLED : COLOR_DISABLED;
|
||||||
|
item->data = val;
|
||||||
|
|
||||||
|
linked_list_add(items, item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void files_filters_update(ui_view* view, void* data, linked_list* items, list_item* selected, bool selectedTouched) {
|
||||||
|
files_data* listData = (files_data*) data;
|
||||||
|
|
||||||
|
if(hidKeysDown() & KEY_B) {
|
||||||
|
linked_list_iter iter;
|
||||||
|
linked_list_iterate(items, &iter);
|
||||||
|
|
||||||
|
while(linked_list_iter_has_next(&iter)) {
|
||||||
|
free(linked_list_iter_next(&iter));
|
||||||
|
linked_list_iter_remove(&iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
ui_pop();
|
||||||
|
list_destroy(view);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(selected != NULL && selected->data != NULL && (selectedTouched || (hidKeysDown() & KEY_A))) {
|
||||||
|
bool* val = (bool*) selected->data;
|
||||||
|
*val = !(*val);
|
||||||
|
|
||||||
|
selected->color = *val ? COLOR_ENABLED : COLOR_DISABLED;
|
||||||
|
|
||||||
|
listData->populated = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(linked_list_size(items) == 0) {
|
||||||
|
files_filters_add_entry(items, "Show directories", &listData->showDirectories);
|
||||||
|
files_filters_add_entry(items, "Show CIAs", &listData->showCias);
|
||||||
|
files_filters_add_entry(items, "Show tickets", &listData->showTickets);
|
||||||
|
files_filters_add_entry(items, "Show miscellaneous", &listData->showMisc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void files_filters_open(files_data* data) {
|
||||||
|
list_display("Filters", "A: Toggle, B: Return", data, files_filters_update, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static void files_draw_top(ui_view* view, void* data, float x1, float y1, float x2, float y2, list_item* selected) {
|
static void files_draw_top(ui_view* view, void* data, float x1, float y1, float x2, float y2, list_item* selected) {
|
||||||
if(selected != NULL && selected->data != NULL) {
|
if(selected != NULL && selected->data != NULL) {
|
||||||
ui_draw_file_info(view, selected->data, x1, y1, x2, y2);
|
ui_draw_file_info(view, selected->data, x1, y1, x2, y2);
|
||||||
@ -246,6 +301,11 @@ static void files_update(ui_view* view, void* data, linked_list* items, list_ite
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(hidKeysDown() & KEY_SELECT) {
|
||||||
|
files_filters_open(listData);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if((hidKeysDown() & KEY_Y) && listData->dirItem != NULL) {
|
if((hidKeysDown() & KEY_Y) && listData->dirItem != NULL) {
|
||||||
files_action_open(items, listData->dirItem, listData);
|
files_action_open(items, listData->dirItem, listData);
|
||||||
return;
|
return;
|
||||||
@ -273,6 +333,26 @@ static void files_update(ui_view* view, void* data, linked_list* items, list_ite
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool files_filter(void* data, const char* name, u32 attributes) {
|
||||||
|
files_data* listData = (files_data*) data;
|
||||||
|
|
||||||
|
if((attributes & FS_ATTRIBUTE_DIRECTORY) != 0) {
|
||||||
|
return listData->showDirectories;
|
||||||
|
} else {
|
||||||
|
size_t len = strlen(name);
|
||||||
|
if(len >= 4) {
|
||||||
|
const char* extension = name + len - 4;
|
||||||
|
if(strncmp(extension, ".cia", 4) == 0) {
|
||||||
|
return listData->showCias;
|
||||||
|
} else if(strncmp(extension, ".tik", 4) == 0) {
|
||||||
|
return listData->showTickets;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return listData->showMisc;
|
||||||
|
}
|
||||||
|
|
||||||
void files_open(FS_ArchiveID archiveId, FS_Path archivePath) {
|
void files_open(FS_ArchiveID archiveId, FS_Path archivePath) {
|
||||||
files_data* data = (files_data*) calloc(1, sizeof(files_data));
|
files_data* data = (files_data*) calloc(1, sizeof(files_data));
|
||||||
if(data == NULL) {
|
if(data == NULL) {
|
||||||
@ -285,10 +365,18 @@ void files_open(FS_ArchiveID archiveId, FS_Path archivePath) {
|
|||||||
data->populateData.includeBase = false;
|
data->populateData.includeBase = false;
|
||||||
data->populateData.dirsFirst = true;
|
data->populateData.dirsFirst = true;
|
||||||
|
|
||||||
|
data->populateData.filter = files_filter;
|
||||||
|
data->populateData.filterData = data;
|
||||||
|
|
||||||
data->populateData.finished = true;
|
data->populateData.finished = true;
|
||||||
|
|
||||||
data->populated = false;
|
data->populated = false;
|
||||||
|
|
||||||
|
data->showDirectories = true;
|
||||||
|
data->showCias = true;
|
||||||
|
data->showTickets = true;
|
||||||
|
data->showMisc = true;
|
||||||
|
|
||||||
data->archiveId = archiveId;
|
data->archiveId = archiveId;
|
||||||
data->archivePath.type = archivePath.type;
|
data->archivePath.type = archivePath.type;
|
||||||
data->archivePath.size = archivePath.size;
|
data->archivePath.size = archivePath.size;
|
||||||
@ -317,7 +405,7 @@ void files_open(FS_ArchiveID archiveId, FS_Path archivePath) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
list_display("Files", "A: Select, B: Back, X: Refresh, Y: Directory Action", data, files_update, files_draw_top);
|
list_display("Files", "A: Select, B: Back, X: Refresh, Y: Dir, Select: Filter", data, files_update, files_draw_top);
|
||||||
}
|
}
|
||||||
|
|
||||||
void files_open_sd() {
|
void files_open_sd() {
|
||||||
|
@ -35,73 +35,75 @@ static Result task_populate_ext_save_data_from(populate_ext_save_data_data* data
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
list_item* item = (list_item*) calloc(1, sizeof(list_item));
|
if(data->filter == NULL || data->filter(data->filterData, extSaveDataIds[i], mediaType)) {
|
||||||
if(item != NULL) {
|
list_item* item = (list_item*) calloc(1, sizeof(list_item));
|
||||||
ext_save_data_info* extSaveDataInfo = (ext_save_data_info*) calloc(1, sizeof(ext_save_data_info));
|
if(item != NULL) {
|
||||||
if(extSaveDataInfo != NULL) {
|
ext_save_data_info* extSaveDataInfo = (ext_save_data_info*) calloc(1, sizeof(ext_save_data_info));
|
||||||
extSaveDataInfo->mediaType = mediaType;
|
if(extSaveDataInfo != NULL) {
|
||||||
extSaveDataInfo->extSaveDataId = extSaveDataIds[i];
|
extSaveDataInfo->mediaType = mediaType;
|
||||||
extSaveDataInfo->shared = mediaType == MEDIATYPE_NAND;
|
extSaveDataInfo->extSaveDataId = extSaveDataIds[i];
|
||||||
extSaveDataInfo->hasMeta = false;
|
extSaveDataInfo->shared = mediaType == MEDIATYPE_NAND;
|
||||||
|
extSaveDataInfo->hasMeta = false;
|
||||||
|
|
||||||
FS_ExtSaveDataInfo info = {.mediaType = mediaType, .saveId = extSaveDataIds[i]};
|
FS_ExtSaveDataInfo info = {.mediaType = mediaType, .saveId = extSaveDataIds[i]};
|
||||||
|
|
||||||
SMDH* smdh = (SMDH*) calloc(1, sizeof(SMDH));
|
SMDH* smdh = (SMDH*) calloc(1, sizeof(SMDH));
|
||||||
if(smdh != NULL) {
|
if(smdh != NULL) {
|
||||||
u32 smdhBytesRead = 0;
|
u32 smdhBytesRead = 0;
|
||||||
if(R_SUCCEEDED(FSUSER_ReadExtSaveDataIcon(&smdhBytesRead, info, sizeof(SMDH), (u8*) smdh)) && smdhBytesRead == sizeof(SMDH)) {
|
if(R_SUCCEEDED(FSUSER_ReadExtSaveDataIcon(&smdhBytesRead, info, sizeof(SMDH), (u8*) smdh)) && smdhBytesRead == sizeof(SMDH)) {
|
||||||
if(smdh->magic[0] == 'S' && smdh->magic[1] == 'M' && smdh->magic[2] == 'D' && smdh->magic[3] == 'H') {
|
if(smdh->magic[0] == 'S' && smdh->magic[1] == 'M' && smdh->magic[2] == 'D' && smdh->magic[3] == 'H') {
|
||||||
u8 systemLanguage = CFG_LANGUAGE_EN;
|
u8 systemLanguage = CFG_LANGUAGE_EN;
|
||||||
CFGU_GetSystemLanguage(&systemLanguage);
|
CFGU_GetSystemLanguage(&systemLanguage);
|
||||||
|
|
||||||
utf16_to_utf8((uint8_t*) item->name, smdh->titles[systemLanguage].shortDescription, LIST_ITEM_NAME_MAX - 1);
|
utf16_to_utf8((uint8_t*) item->name, smdh->titles[systemLanguage].shortDescription, LIST_ITEM_NAME_MAX - 1);
|
||||||
|
|
||||||
extSaveDataInfo->hasMeta = true;
|
extSaveDataInfo->hasMeta = true;
|
||||||
utf16_to_utf8((uint8_t*) extSaveDataInfo->meta.shortDescription, smdh->titles[systemLanguage].shortDescription, sizeof(extSaveDataInfo->meta.shortDescription) - 1);
|
utf16_to_utf8((uint8_t*) extSaveDataInfo->meta.shortDescription, smdh->titles[systemLanguage].shortDescription, sizeof(extSaveDataInfo->meta.shortDescription) - 1);
|
||||||
utf16_to_utf8((uint8_t*) extSaveDataInfo->meta.longDescription, smdh->titles[systemLanguage].longDescription, sizeof(extSaveDataInfo->meta.longDescription) - 1);
|
utf16_to_utf8((uint8_t*) extSaveDataInfo->meta.longDescription, smdh->titles[systemLanguage].longDescription, sizeof(extSaveDataInfo->meta.longDescription) - 1);
|
||||||
utf16_to_utf8((uint8_t*) extSaveDataInfo->meta.publisher, smdh->titles[systemLanguage].publisher, sizeof(extSaveDataInfo->meta.publisher) - 1);
|
utf16_to_utf8((uint8_t*) extSaveDataInfo->meta.publisher, smdh->titles[systemLanguage].publisher, sizeof(extSaveDataInfo->meta.publisher) - 1);
|
||||||
extSaveDataInfo->meta.texture = screen_load_texture_tiled_auto(smdh->largeIcon, sizeof(smdh->largeIcon), 48, 48, GPU_RGB565, false);
|
extSaveDataInfo->meta.texture = screen_load_texture_tiled_auto(smdh->largeIcon, sizeof(smdh->largeIcon), 48, 48, GPU_RGB565, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(smdh);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool empty = strlen(item->name) == 0;
|
||||||
|
if(!empty) {
|
||||||
|
empty = true;
|
||||||
|
|
||||||
|
char* curr = item->name;
|
||||||
|
while(*curr) {
|
||||||
|
if(*curr != ' ') {
|
||||||
|
empty = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
curr++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free(smdh);
|
if(empty) {
|
||||||
}
|
snprintf(item->name, LIST_ITEM_NAME_MAX, "%016llX", extSaveDataIds[i]);
|
||||||
|
|
||||||
bool empty = strlen(item->name) == 0;
|
|
||||||
if(!empty) {
|
|
||||||
empty = true;
|
|
||||||
|
|
||||||
char* curr = item->name;
|
|
||||||
while(*curr) {
|
|
||||||
if(*curr != ' ') {
|
|
||||||
empty = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
curr++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(mediaType == MEDIATYPE_NAND) {
|
||||||
|
item->color = COLOR_NAND;
|
||||||
|
} else if(mediaType == MEDIATYPE_SD) {
|
||||||
|
item->color = COLOR_SD;
|
||||||
|
}
|
||||||
|
|
||||||
|
item->data = extSaveDataInfo;
|
||||||
|
|
||||||
|
linked_list_add(data->items, item);
|
||||||
|
} else {
|
||||||
|
free(item);
|
||||||
|
|
||||||
|
res = R_FBI_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(empty) {
|
|
||||||
snprintf(item->name, LIST_ITEM_NAME_MAX, "%016llX", extSaveDataIds[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(mediaType == MEDIATYPE_NAND) {
|
|
||||||
item->color = COLOR_NAND;
|
|
||||||
} else if(mediaType == MEDIATYPE_SD) {
|
|
||||||
item->color = COLOR_SD;
|
|
||||||
}
|
|
||||||
|
|
||||||
item->data = extSaveDataInfo;
|
|
||||||
|
|
||||||
linked_list_add(data->items, item);
|
|
||||||
} else {
|
} else {
|
||||||
free(item);
|
|
||||||
|
|
||||||
res = R_FBI_OUT_OF_MEMORY;
|
res = R_FBI_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
res = R_FBI_OUT_OF_MEMORY;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <3ds.h>
|
#include <3ds.h>
|
||||||
|
#include <3ds/services/fs.h>
|
||||||
|
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
#include "../../list.h"
|
#include "../../list.h"
|
||||||
@ -192,25 +193,27 @@ static void task_populate_files_thread(void* arg) {
|
|||||||
char name[FILE_NAME_MAX] = {'\0'};
|
char name[FILE_NAME_MAX] = {'\0'};
|
||||||
utf16_to_utf8((uint8_t*) name, entries[i].name, FILE_NAME_MAX - 1);
|
utf16_to_utf8((uint8_t*) name, entries[i].name, FILE_NAME_MAX - 1);
|
||||||
|
|
||||||
char path[FILE_PATH_MAX] = {'\0'};
|
if(data->filter == NULL || data->filter(data->filterData, name, entries[i].attributes)) {
|
||||||
snprintf(path, FILE_PATH_MAX, "%s%s", curr->path, name);
|
char path[FILE_PATH_MAX] = {'\0'};
|
||||||
|
snprintf(path, FILE_PATH_MAX, "%s%s", curr->path, name);
|
||||||
|
|
||||||
list_item* item = NULL;
|
list_item* item = NULL;
|
||||||
if(R_SUCCEEDED(res = task_create_file_item(&item, curr->archive, path))) {
|
if(R_SUCCEEDED(res = task_create_file_item(&item, curr->archive, path))) {
|
||||||
if(curr->isDirectory && strncmp(curr->path, data->base->path, FILE_PATH_MAX) == 0) {
|
if(curr->isDirectory && strncmp(curr->path, data->base->path, FILE_PATH_MAX) == 0) {
|
||||||
file_info* info = (file_info*) item->data;
|
file_info* info = (file_info*) item->data;
|
||||||
|
|
||||||
if(info->isCia) {
|
if(info->isCia) {
|
||||||
data->base->containsCias = true;
|
data->base->containsCias = true;
|
||||||
} else if(info->isTicket) {
|
} else if(info->isTicket) {
|
||||||
data->base->containsTickets = true;
|
data->base->containsTickets = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if(data->recursive && ((file_info*) item->data)->isDirectory) {
|
if(data->recursive && ((file_info*) item->data)->isDirectory) {
|
||||||
linked_list_add(&queue, item);
|
linked_list_add(&queue, item);
|
||||||
} else {
|
} else {
|
||||||
linked_list_add(data->items, item);
|
linked_list_add(data->items, item);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -273,12 +273,14 @@ static Result task_populate_titles_from(populate_titles_data* data, FS_MediaType
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool dsiWare = ((titleIds[i] >> 32) & 0x8000) != 0;
|
if(data->filter == NULL || data->filter(data->filterData, titleIds[i], mediaType)) {
|
||||||
if(dsiWare != useDSiWare) {
|
bool dsiWare = ((titleIds[i] >> 32) & 0x8000) != 0;
|
||||||
continue;
|
if(dsiWare != useDSiWare) {
|
||||||
}
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
res = dsiWare ? task_populate_titles_add_twl(data, mediaType, titleIds[i]) : task_populate_titles_add_ctr(data, mediaType, titleIds[i]);
|
res = dsiWare ? task_populate_titles_add_twl(data, mediaType, titleIds[i]) : task_populate_titles_add_ctr(data, mediaType, titleIds[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,6 +130,9 @@ typedef struct data_op_info_s {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
linked_list* items;
|
linked_list* items;
|
||||||
|
|
||||||
|
bool (*filter)(void* data, u64 extSaveDataId, FS_MediaType mediaType);
|
||||||
|
void* filterData;
|
||||||
|
|
||||||
volatile bool finished;
|
volatile bool finished;
|
||||||
Result result;
|
Result result;
|
||||||
Handle cancelEvent;
|
Handle cancelEvent;
|
||||||
@ -144,6 +147,9 @@ typedef struct {
|
|||||||
bool includeBase;
|
bool includeBase;
|
||||||
bool dirsFirst;
|
bool dirsFirst;
|
||||||
|
|
||||||
|
bool (*filter)(void* data, const char* name, u32 attributes);
|
||||||
|
void* filterData;
|
||||||
|
|
||||||
volatile bool finished;
|
volatile bool finished;
|
||||||
Result result;
|
Result result;
|
||||||
Handle cancelEvent;
|
Handle cancelEvent;
|
||||||
@ -176,6 +182,9 @@ typedef struct {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
linked_list* items;
|
linked_list* items;
|
||||||
|
|
||||||
|
bool (*filter)(void* data, u64 titleId, FS_MediaType mediaType);
|
||||||
|
void* filterData;
|
||||||
|
|
||||||
volatile bool finished;
|
volatile bool finished;
|
||||||
Result result;
|
Result result;
|
||||||
Handle cancelEvent;
|
Handle cancelEvent;
|
||||||
|
@ -24,6 +24,10 @@ static list_item delete_secure_value = {"Delete Secure Value", COLOR_TEXT, actio
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
populate_titles_data populateData;
|
populate_titles_data populateData;
|
||||||
|
|
||||||
|
bool showGameCard;
|
||||||
|
bool showSD;
|
||||||
|
bool showNAND;
|
||||||
|
|
||||||
bool populated;
|
bool populated;
|
||||||
} titles_data;
|
} titles_data;
|
||||||
|
|
||||||
@ -102,6 +106,55 @@ static void titles_action_open(linked_list* items, list_item* selected) {
|
|||||||
list_display("Title Action", "A: Select, B: Return", data, titles_action_update, titles_action_draw_top);
|
list_display("Title Action", "A: Select, B: Return", data, titles_action_update, titles_action_draw_top);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void titles_filters_add_entry(linked_list* items, const char* name, bool* val) {
|
||||||
|
list_item* item = (list_item*) calloc(1, sizeof(list_item));
|
||||||
|
if(item != NULL) {
|
||||||
|
snprintf(item->name, LIST_ITEM_NAME_MAX, "%s", name);
|
||||||
|
item->color = *val ? COLOR_ENABLED : COLOR_DISABLED;
|
||||||
|
item->data = val;
|
||||||
|
|
||||||
|
linked_list_add(items, item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void titles_filters_update(ui_view* view, void* data, linked_list* items, list_item* selected, bool selectedTouched) {
|
||||||
|
titles_data* listData = (titles_data*) data;
|
||||||
|
|
||||||
|
if(hidKeysDown() & KEY_B) {
|
||||||
|
linked_list_iter iter;
|
||||||
|
linked_list_iterate(items, &iter);
|
||||||
|
|
||||||
|
while(linked_list_iter_has_next(&iter)) {
|
||||||
|
free(linked_list_iter_next(&iter));
|
||||||
|
linked_list_iter_remove(&iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
ui_pop();
|
||||||
|
list_destroy(view);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(selected != NULL && selected->data != NULL && (selectedTouched || (hidKeysDown() & KEY_A))) {
|
||||||
|
bool* val = (bool*) selected->data;
|
||||||
|
*val = !(*val);
|
||||||
|
|
||||||
|
selected->color = *val ? COLOR_ENABLED : COLOR_DISABLED;
|
||||||
|
|
||||||
|
listData->populated = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(linked_list_size(items) == 0) {
|
||||||
|
titles_filters_add_entry(items, "Show game card", &listData->showGameCard);
|
||||||
|
titles_filters_add_entry(items, "Show SD", &listData->showSD);
|
||||||
|
titles_filters_add_entry(items, "Show NAND", &listData->showNAND);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void titles_filters_open(titles_data* data) {
|
||||||
|
list_display("Filters", "A: Toggle, B: Return", data, titles_filters_update, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static void titles_draw_top(ui_view* view, void* data, float x1, float y1, float x2, float y2, list_item* selected) {
|
static void titles_draw_top(ui_view* view, void* data, float x1, float y1, float x2, float y2, list_item* selected) {
|
||||||
if(selected != NULL && selected->data != NULL) {
|
if(selected != NULL && selected->data != NULL) {
|
||||||
ui_draw_title_info(view, selected->data, x1, y1, x2, y2);
|
ui_draw_title_info(view, selected->data, x1, y1, x2, y2);
|
||||||
@ -128,6 +181,11 @@ static void titles_update(ui_view* view, void* data, linked_list* items, list_it
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(hidKeysDown() & KEY_SELECT) {
|
||||||
|
titles_filters_open(listData);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(!listData->populated || (hidKeysDown() & KEY_X)) {
|
if(!listData->populated || (hidKeysDown() & KEY_X)) {
|
||||||
if(!listData->populateData.finished) {
|
if(!listData->populateData.finished) {
|
||||||
svcSignalEvent(listData->populateData.cancelEvent);
|
svcSignalEvent(listData->populateData.cancelEvent);
|
||||||
@ -157,6 +215,18 @@ static void titles_update(ui_view* view, void* data, linked_list* items, list_it
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool titles_filter(void* data, u64 titleId, FS_MediaType mediaType) {
|
||||||
|
titles_data* listData = (titles_data*) data;
|
||||||
|
|
||||||
|
if(mediaType == MEDIATYPE_GAME_CARD) {
|
||||||
|
return listData->showGameCard;
|
||||||
|
} else if(mediaType == MEDIATYPE_SD) {
|
||||||
|
return listData->showSD;
|
||||||
|
} else {
|
||||||
|
return listData->showNAND;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void titles_open() {
|
void titles_open() {
|
||||||
titles_data* data = (titles_data*) calloc(1, sizeof(titles_data));
|
titles_data* data = (titles_data*) calloc(1, sizeof(titles_data));
|
||||||
if(data == NULL) {
|
if(data == NULL) {
|
||||||
@ -165,7 +235,14 @@ void titles_open() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data->populateData.filter = titles_filter;
|
||||||
|
data->populateData.filterData = data;
|
||||||
|
|
||||||
data->populateData.finished = true;
|
data->populateData.finished = true;
|
||||||
|
|
||||||
list_display("Titles", "A: Select, B: Return, X: Refresh", data, titles_update, titles_draw_top);
|
data->showGameCard = true;
|
||||||
|
data->showSD = true;
|
||||||
|
data->showNAND = true;
|
||||||
|
|
||||||
|
list_display("Titles", "A: Select, B: Return, X: Refresh, Select: Filter", data, titles_update, titles_draw_top);
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user