void NES_LOADROMLIST() { Handle romHandle; FS_dirent dirStruct; FS_path dirPath = FS_makePath(PATH_CHAR, "/3DNES/ROMS"); // init SDMC archive sdmcArchive = (FS_archive){0x9, (FS_path){PATH_EMPTY, 1, (u8*)""}}; FSUSER_OpenArchive(NULL, &sdmcArchive); FSUSER_OpenDirectory(NULL, &romHandle, sdmcArchive, dirPath); // Get number of files in directory fileSystem.totalFiles = 0 while(1) { u32 dataRead = 0; FSDIR_Read(romHandle, &dataRead, 1, &dirStruct); if(dataRead == 0) break; fileSystem.totalFiles++; } fileSystem.fileList = linearAlloc(MAX_FILENAME_SIZE * fileSystem.totalFiles); FSUSER_OpenDirectory(NULL, &romHandle, sdmcArchive, dirPath); fileSystem.totalFiles = 0; while(1) { u32 dataRead = 0; FSDIR_Read(romHandle, &dataRead, 1, &dirStruct); if(dataRead == 0) break; unicodeToChar(&fileSystem.fileList[MAX_FILENAME_SIZE * fileSystem.totalFiles), dirStruct.name); fileSystem.totalFiles++; } FSDIR_Close(romHandle); }
void scanHomebrewDirectory(menu_s* m, char* path) { if(!path)return; Handle dirHandle; FS_path dirPath=FS_makePath(PATH_CHAR, path); FSUSER_OpenDirectory(NULL, &dirHandle, sdmcArchive, dirPath); static char fullPath[1024]; u32 entriesRead; do { static FS_dirent entry; memset(&entry,0,sizeof(FS_dirent)); entriesRead=0; FSDIR_Read(dirHandle, &entriesRead, 1, &entry); if(entriesRead) { strncpy(fullPath, path, 1024); int n=strlen(fullPath); unicodeToChar(&fullPath[n], entry.name, 1024-n); if(entry.isDirectory) //directories { addDirectoryToMenu(m, fullPath); }else{ //stray executables n=strlen(fullPath); if(n>5 && !strcmp(".3dsx", &fullPath[n-5]))addFileToMenu(m, fullPath); } } }while(entriesRead); FSDIR_Close(dirHandle); }
Directory::Directory(FS_Archive archive, const std::u16string& root) { load = false; err = 0; Handle handle; list.clear(); err = FSUSER_OpenDirectory(&handle, archive, fsMakePath(PATH_UTF16, root.c_str())); if (R_FAILED(err)) { return; } u32 result = 0; do { FS_DirectoryEntry item; err = FSDIR_Read(handle, &result, 1, &item); if (result == 1) { list.push_back(item); } } while(result); err = FSDIR_Close(handle); if (R_FAILED(err)) { list.clear(); return; } load = true; }
static struct VDirEntry* _vd3dListNext(struct VDir* vd) { struct VDir3DS* vd3d = (struct VDir3DS*) vd; u32 n = 0; memset(&vd3d->vde.ent, 0, sizeof(vd3d->vde.ent)); memset(vd3d->vde.utf8Name, 0, sizeof(vd3d->vde.utf8Name)); FSDIR_Read(vd3d->handle, &n, 1, &vd3d->vde.ent); if (!n) { return 0; } return &vd3d->vde.d; }
bool renameRecursive(const FS_Archive archive, const std::string source, const std::string target) { const FS_Path sourcePath = fsMakePath(PATH_ASCII, source.c_str()); const FS_Path targetPath = fsMakePath(PATH_ASCII, target.c_str()); // Open source directory Handle directory = NULL; if (FSUSER_OpenDirectory(&directory, archive, sourcePath) != 0) { std::printf("\nCould not open %s\n\n", source.c_str()); return false; } // Make target directory if (FSUSER_CreateDirectory(archive, targetPath, FS_ATTRIBUTE_DIRECTORY) != 0) { std::printf("\nCould not create %s\n\n", target.c_str()); return false; } u32 fileRead = 0; while (true) { FS_DirectoryEntry entry = {}; FSDIR_Read(directory, &fileRead, 1, &entry); if (!fileRead) { break; } // Convert name to ASCII (just cut the other bytes) char name8[262] = { 0 }; for (size_t i = 0; i < 262; i++) { name8[i] = entry.name[i] % 0xff; } std::string filePath = std::string("/") + name8; std::string from = source + filePath; std::string to = target + filePath; // Is a directory? Recurse rename if (entry.attributes & FS_ATTRIBUTE_DIRECTORY) { std::printf(" %s -> %s (DIR)\n", from.c_str(), to.c_str()); if (!renameRecursive(archive, source + filePath, target + filePath)) { return false; } } else { FS_Path sourceFilePath = fsMakePath(PATH_ASCII, from.c_str()); FS_Path targetFilePath = fsMakePath(PATH_ASCII, to.c_str()); if (FSUSER_RenameFile(archive, sourceFilePath, archive, targetFilePath) != 0) { std::printf("\nCould not rename %s\n\n", (char*)sourceFilePath.data); return false; } std::printf(" %s -> %s\n", (char*)sourceFilePath.data, (char*)targetFilePath.data); } } return true; }
void dumpTicket(void) { Result res = 0; Handle nandDir; u32 entryCount; FS_dirent dirent; printf("Opening NAND...\n"); res = FSUSER_OpenArchive(NULL, &nandArchive); if(res != 0) { printf("%sError opening NAND!\n%.8lX%s\n", TEXT_RED, res, TEXT_RESET); return; } printf("Opening /...\n"); nandPath.data = (u8 *)nandPathString; nandPath.size = (wcslen(nandPathString) + 1) * 2; res = FSUSER_OpenDirectory(NULL, &nandDir, nandArchive, nandPath); if(res != 0) { printf("%sError opening /!\n%.8lX%s\n", TEXT_RED, res, TEXT_RESET); return; } printf("Reading...\n"); for(;;) { res = FSDIR_Read(nandDir, &entryCount, 1, &dirent); if(res != 0) { printf("%sError reading dir!\n%.8lX%s\n", TEXT_RED, res, TEXT_RESET); return; } if(entryCount == 0) { break; } utf16_to_utf8(utf8, dirent.name, 0x106); printf("/%s\n", utf8); } printf("Closing /...\n"); res = FSDIR_Close(nandDir); if(res != 0) { printf("%sError closing /!\n%.8lX%s\n", TEXT_RED, res, TEXT_RESET); return; } printf("Closing NAND...\n"); res = FSUSER_CloseArchive(NULL, &nandArchive); if(res != 0) { printf("%sError closing NAND!\n%.8lX%s\n", TEXT_RED, res, TEXT_RESET); return; } }
int getNextFile(Handle dir, FS_DirectoryEntry *ent) { u32 count; if(R_FAILED(FSDIR_Read(dir, &count, 1, ent))) { return(-1); } if(count == 0) { return(0); } return(1); }
//same thing as contructor. can be used to reinit dirList too void dirList::reassign(const std::u16string p) { entry.clear(); FSUSER_OpenDirectory(&d, a, fsMakePath(PATH_UTF16, p.data())); u32 read = 0; do { FS_DirectoryEntry getEnt; FSDIR_Read(d, &read, 1, &getEnt); entry.push_back(getEnt); }while(read > 0); FSDIR_Close(d); }
void scanHomebrewDirectory(menu_s* m, char* path) { if(!path)return; Handle dirHandle; FS_path dirPath=FS_makePath(PATH_CHAR, path); FSUSER_OpenDirectory(&dirHandle, sdmcArchive, dirPath); static char fullPath[1024][1024]; u32 entriesRead; int totalentries = 0; do { static FS_dirent entry; memset(&entry,0,sizeof(FS_dirent)); entriesRead=0; FSDIR_Read(dirHandle, &entriesRead, 1, &entry); if(entriesRead) { strncpy(fullPath[totalentries], path, 1024); int n=strlen(fullPath[totalentries]); unicodeToChar(&fullPath[totalentries][n], entry.name, 1024-n); if(entry.isDirectory) //directories { //addDirectoryToMenu(m, fullPath[totalentries]); totalentries++; }else{ //stray executables n=strlen(fullPath[totalentries]); if(n>5 && !strcmp(".3dsx", &fullPath[totalentries][n-5])){ //addFileToMenu(m, fullPath[totalentries]); totalentries++; } if(n>4 && !strcmp(".xml", &fullPath[totalentries][n-4])) { //addFileToMenu(m, fullPath[totalentries]); totalentries++; } } } }while(entriesRead); FSDIR_Close(dirHandle); bool sortAlpha = getConfigBoolForKey("sortAlpha", false, configTypeMain); addMenuEntries(fullPath, totalentries, strlen(path), m, sortAlpha); updateMenuIconPositions(m); }
void dumpFolder(char *path, u32 lowpath_id, char *dumpfolder, u8 *filebuffer, size_t bufsize) { Handle extdata_dir; Result ret = FSUSER_OpenDirectory(NULL, &extdata_dir, extdata_archive, FS_makePath(PATH_CHAR, path)); if (ret!=0) { printf("could not open dir\n"); gfxFlushBuffers(); gfxSwapBuffers(); return; } char dirname[0x120]; sprintf(dirname, "%s/%08x%s", dumpfolder, (unsigned int) lowpath_id, path); mkdir(dirname, 0777); FS_dirent dirStruct; char fileName[0x106] = ""; int cont = 0; while(1) { u32 dataRead = 0; FSDIR_Read(extdata_dir, &dataRead, 1, &dirStruct); if(dataRead == 0) break; unicodeToChar(fileName, dirStruct.name); printf("name: %s%s%s\n", path, fileName, dirStruct.isDirectory ? " (DIRECTORY)" : ""); gfxFlushBuffers(); gfxSwapBuffers(); cont++; if (dirStruct.isDirectory) { char newpath[0x120]; sprintf(newpath, "%s%s/", path, fileName); dumpFolder(newpath, lowpath_id, dumpfolder, filebuffer, bufsize); } else { char file_inpath[0x120]; char file_outpath[0x120]; char file_display_path[0x120]; sprintf(file_inpath, "%s%s", path, fileName); sprintf(file_outpath, "%s/%08x%s%s", dumpfolder, (unsigned int) lowpath_id, path, fileName); sprintf(file_display_path, "%08x%s%s", (unsigned int) lowpath_id, path, fileName); archive_copyfile(Extdata_Archive, SDArchive, file_inpath, file_outpath, filebuffer, 0, bufsize, file_display_path); } } printf("total files in 0x%08x%s: %d\n", (unsigned int) lowpath_id, path, (unsigned int) cont); gfxFlushBuffers(); gfxSwapBuffers(); FSDIR_Close(extdata_dir); }
/*! Fetch the next entry of an open directory * * @param[in,out] r newlib reentrancy struct * @param[in] dirState Pointer to open directory state * @param[out] filename Buffer to store entry name * @param[out] filestat Buffer to store entry attributes * * @returns 0 for success * @returns -1 for error */ static int sdmc_dirnext(struct _reent *r, DIR_ITER *dirState, char *filename, struct stat *filestat) { Result rc; u32 entries; u16 *name; /* get pointer to our data */ sdmc_dir_t *dir = (sdmc_dir_t*)(dirState->dirStruct); /* fetch the next entry */ rc = FSDIR_Read(dir->fd, &entries, 1, &dir->entry_data); if(rc == 0) { if(entries == 0) { /* there are no more entries; ENOENT signals end-of-directory */ r->_errno = ENOENT; return -1; } /* fill in the stat info */ filestat->st_ino = 0; if(dir->entry_data.isDirectory) filestat->st_mode = S_IFDIR; else filestat->st_mode = S_IFREG; /* copy the name */ name = dir->entry_data.name; while(*name) *filename++ = *name++; *filename = 0; return 0; } r->_errno = rc; return -1; }
dirList::dirList(FS_Archive arch, const std::u16string p) { //keep archive data a = arch; //save path path = p; //open path given by p FSUSER_OpenDirectory(&d, a, fsMakePath(PATH_UTF16, p.data())); //loop until we stop reading anymore entries u32 read = 0; do { FS_DirectoryEntry getEnt; FSDIR_Read(d, &read, 1, &getEnt); entry.push_back(getEnt); }while(read > 0); FSDIR_Close(d); }
std::vector<std::string> listPayloads() { std::vector<std::string> files = {}; FS_Archive sdmcArchive; // Open SD card if (FSUSER_OpenArchive(&sdmcArchive, ARCHIVE_SDMC, fsMakePath(PATH_EMPTY, NULL)) != 0) { logPrintf("\nCould not access SD Card (?)\n\n"); return files; } // Open source directory Handle directory = 0; if (FSUSER_OpenDirectory(&directory, sdmcArchive, fsMakePath(PATH_ASCII, "/luma/payloads")) != 0) { logPrintf("\nCould not open /luma/payloads\n\n"); FSUSER_CloseArchive(sdmcArchive); return files; } u32 fileRead = 0; while (true) { FS_DirectoryEntry entry = {}; FSDIR_Read(directory, &fileRead, 1, &entry); if (!fileRead) { break; } // Convert name to ASCII (just cut the other bytes) and compare with prefix char name8[262] = { 0 }; for (size_t i = 0; i < 262; i++) { name8[i] = entry.name[i] % 0xff; } files.push_back(std::string(name8)); } FSUSER_CloseArchive(sdmcArchive); return files; }
directoryContents * contentsOfDirectoryAtPath(char * path, bool dirsOnly) { directoryContents * contents = malloc(sizeof(directoryContents)); int numPaths = 0; Handle dirHandle; FS_path dirPath=FS_makePath(PATH_CHAR, path); FSUSER_OpenDirectory(&dirHandle, sdmcArchive, dirPath); u32 entriesRead; do { static FS_dirent entry; memset(&entry,0,sizeof(FS_dirent)); entriesRead=0; FSDIR_Read(dirHandle, &entriesRead, 1, &entry); if(entriesRead) { if(!dirsOnly || (dirsOnly && entry.isDirectory)) { char fullPath[1024]; strncpy(fullPath, path, 1024); int n=strlen(path); unicodeToChar(&fullPath[n], entry.name, 1024-n); strcpy(contents->paths[numPaths], fullPath); numPaths++; } } }while(entriesRead); FSDIR_Close(dirHandle); // qsort(contents->paths, numPaths, 1024, compareStrings); contents->numPaths = numPaths; return contents; }
static void task_populate_files_thread(void* arg) { populate_files_data* data = (populate_files_data*) arg; Result res = 0; list_item* baseItem = NULL; if(R_SUCCEEDED(res = task_create_file_item(&baseItem, data->archive, data->path))) { file_info* baseInfo = (file_info*) baseItem->data; if(baseInfo->attributes & FS_ATTRIBUTE_DIRECTORY) { strncpy(baseItem->name, "<current directory>", LIST_ITEM_NAME_MAX); } else { strncpy(baseItem->name, "<current file>", LIST_ITEM_NAME_MAX); } linked_list queue; linked_list_init(&queue); linked_list_add(&queue, baseItem); bool quit = false; while(!quit && R_SUCCEEDED(res) && linked_list_size(&queue) > 0) { u32 tail = linked_list_size(&queue) - 1; list_item* currItem = (list_item*) linked_list_get(&queue, tail); file_info* curr = (file_info*) currItem->data; linked_list_remove_at(&queue, tail); if(data->includeBase || currItem != baseItem) { linked_list_add(data->items, currItem); } if(curr->attributes & FS_ATTRIBUTE_DIRECTORY) { FS_Path* fsPath = util_make_path_utf8(curr->path); if(fsPath != NULL) { Handle dirHandle = 0; if(R_SUCCEEDED(res = FSUSER_OpenDirectory(&dirHandle, curr->archive, *fsPath))) { u32 entryCount = 0; FS_DirectoryEntry* entries = (FS_DirectoryEntry*) calloc(MAX_FILES, sizeof(FS_DirectoryEntry)); if(entries != NULL) { if(R_SUCCEEDED(res = FSDIR_Read(dirHandle, &entryCount, MAX_FILES, entries)) && entryCount > 0) { qsort(entries, entryCount, sizeof(FS_DirectoryEntry), task_populate_files_compare_directory_entries); for(u32 i = 0; i < entryCount && R_SUCCEEDED(res); i++) { svcWaitSynchronization(task_get_pause_event(), U64_MAX); if(task_is_quit_all() || svcWaitSynchronization(data->cancelEvent, 0) == 0) { quit = true; break; } char name[FILE_NAME_MAX] = {'\0'}; utf16_to_utf8((uint8_t*) name, entries[i].name, FILE_NAME_MAX - 1); if(data->filter == NULL || data->filter(data->filterData, name, entries[i].attributes)) { char path[FILE_PATH_MAX] = {'\0'}; snprintf(path, FILE_PATH_MAX, "%s%s", curr->path, name); list_item* item = NULL; if(R_SUCCEEDED(res = task_create_file_item(&item, curr->archive, path))) { if(data->recursive && (((file_info*) item->data)->attributes & FS_ATTRIBUTE_DIRECTORY)) { linked_list_add(&queue, item); } else { linked_list_add(data->items, item); } } } } } free(entries); } else { res = R_FBI_OUT_OF_MEMORY; } FSDIR_Close(dirHandle); } util_free_path_utf8(fsPath); } else { res = R_FBI_OUT_OF_MEMORY; } } } if(!data->includeBase) { task_free_file(baseItem); } } svcCloseHandle(data->cancelEvent); data->result = res; data->finished = true; }
bool installTTP(char* path, u8 mediatype) { // Install a TTP file. (needs libzip and installCIA) Result res; FS_Archive archive = {ARCHIVE_SDMC, {PATH_EMPTY, 0, 0}}; FSUSER_OpenArchive(&archive); FSUSER_DeleteDirectoryRecursively(archive, fsMakePath(PATH_ASCII, "/tmp/cias")); FSUSER_CreateDirectory(archive, fsMakePath(PATH_ASCII, "/tmp/cias"), 0); FILE* ttp = fopen(path, "rb"); FILE* tmp = fopen("/tmp/cias/ttp.tmp", "wb"); u32 titlesAmount; AM_GetTitleCount(mediatype, &titlesAmount); u64* titleIDs = malloc(sizeof(u64) * titlesAmount); AM_GetTitleIdList(mediatype, titlesAmount, titleIDs); u32 size; fseek(ttp, 0x19, SEEK_SET); fread(&size, 0x4, 1, ttp); fseek(ttp, 0x1D, SEEK_SET); u32 blockAmount = size / 0x160000; // Finds how many blocks of 4MB you have in the file u32 i; char* block = malloc(0x160000); for (i = 0; i < blockAmount; i++) { fread(block, 1, 0x160000, ttp); fwrite(block, 1, 0x160000, tmp); } if (size % 0x160000 != 0) { fread(block, 1, size-0x160000*blockAmount, ttp); fwrite(block, 1, size-0x160000*blockAmount, tmp); } free(block); fclose(ttp); fclose(tmp); FSUSER_DeleteDirectoryRecursively(archive, fsMakePath(PATH_ASCII, "/tmp/cias")); FSUSER_CreateDirectory(archive, fsMakePath(PATH_ASCII, "/tmp/cias"), 0); Zip *zipHandle = ZipOpen("/tmp/cias/ttp.tmp"); ZipExtract(zipHandle, NULL); ZipClose(zipHandle); Handle ciaDir; FS_Archive fsarchive; u32 actualAmount; FS_DirectoryEntry* entries; FSUSER_DeleteFile(archive, fsMakePath(PATH_ASCII, "/tmp/cias/ttp.tmp")); res = FSUSER_OpenDirectory(&ciaDir, fsarchive, fsMakePath(PATH_ASCII, "/tmp/cias")); if (res != 0) { free(titleIDs); return false; } entries = malloc(256 * sizeof(FS_DirectoryEntry)); res = FSDIR_Read(ciaDir, &actualAmount, 256, entries); if (res != 0) { free(titleIDs); return false; } char* ciaPath; Handle ciaFileHandle; AM_TitleEntry ciaInfo; for (i = 0; i < actualAmount; i++) { ciaPath = malloc(14 + strlen(entries[i].shortName)); strcpy(ciaPath, "/tmp/cias/"); strcat(ciaPath, entries[i].shortName); strcat(ciaPath, ".cia"); FSUSER_OpenFile(&ciaFileHandle, archive, fsMakePath(PATH_ASCII, ciaPath), FS_OPEN_READ, 0); AM_GetCiaFileInfo(mediatype, &ciaInfo, ciaFileHandle); FSFILE_Close(ciaFileHandle); if (ciaInfo.titleID == 0x0004013800000002LL || ciaInfo.titleID == 0x0004013820000002LL) { if (!installCIA(ciaPath, mediatype, titleIDs, entries[i].shortName)) if (!installCIA(ciaPath, mediatype, titleIDs, entries[i].shortName)) // Tries to install the CIA 3 times then give up. If it has to give up, that probably means brick. if (!installCIA(ciaPath, mediatype, titleIDs, entries[i].shortName)) return false; break; } free(ciaPath); } for (i = 0; i < actualAmount; i++) { ciaPath = malloc(14 + strlen(entries[i].shortName)); strcpy(ciaPath, "/tmp/cias/"); strcat(ciaPath, entries[i].shortName); strcat(ciaPath, ".cia"); if (!installCIA(ciaPath, mediatype, titleIDs, entries[i].shortName)) if (!installCIA(ciaPath, mediatype, titleIDs, entries[i].shortName)) // Tries to install the CIA 3 times then give up. If it has to give up, that probably means brick. installCIA(ciaPath, mediatype, titleIDs, entries[i].shortName); free(ciaPath); } FSUSER_DeleteDirectoryRecursively(archive, fsMakePath(PATH_ASCII, "/tmp/cias")); FSUSER_CloseArchive(&archive); free(titleIDs); return true; }
int load_file(char **wildcards, char *result, bool startup) { Handle dirHandle; FS_DirectoryEntry entry; char current_dir_name[MAX__PATH]; char prev_dir_name[MAX__PATH]; char current_dir_short[81]; u32 current_dir_length; u32 total_filenames_allocated; u32 total_dirnames_allocated; char **file_list; char **dir_list; u32 num_files; u32 num_dirs; char *file_name; u32 file_name_length; u32 ext_pos = -1; s32 return_value = 1; u32 current_file_selection; u32 current_file_scroll_value; u32 current_dir_selection; u32 current_dir_scroll_value; u32 current_file_in_scroll; u32 current_dir_in_scroll; u32 current_file_number, current_dir_number; u32 current_column = 0; u32 repeat; u32 i; strcpy(current_dir_name, config_roms_path); strcpy(prev_dir_name, current_dir_name); while(return_value == 1) { current_file_selection = 0; current_file_scroll_value = 0; current_dir_selection = 0; current_dir_scroll_value = 0; current_file_in_scroll = 0; current_dir_in_scroll = 0; total_filenames_allocated = 32; total_dirnames_allocated = 32; file_list = (char **)malloc(sizeof(char *) * 32); dir_list = (char **)malloc(sizeof(char *) * 32); memset(file_list, 0, sizeof(char *) * 32); memset(dir_list, 0, sizeof(char *) * 32); num_files = 0; num_dirs = 0; file_name= (char*) malloc(0x105); FS_Path dirPath = (FS_Path){PATH_ASCII, strlen(current_dir_name)+1, (u8*)current_dir_name}; FSUSER_OpenDirectory(&dirHandle, sdmcArchive, dirPath); // DEBUG printf("Current directory: %s\n", current_dir_name); u32 nread = 0; do { if(dirHandle) FSDIR_Read(dirHandle, &nread, 1, &entry); if(nread) { //(current_file) { strncpy_u2a(file_name, entry.name, 0x105); //utf-16 to ascii function yoinked from blargSNES file_name_length = strlen(file_name); if(((file_name[0] != '.') || (file_name[1] == '.'))) { //if(S_ISDIR(file_info.st_mode)) { //!!!!!!!! if(entry.attributes & FS_ATTRIBUTE_DIRECTORY) { if((strcmp(file_name, "filer") != 0) && (strcmp(file_name, "Nintendo 3DS") != 0) && (strcmp(file_name, "private") != 0)) { dir_list[num_dirs] = (char *)malloc(file_name_length + 1); strcpy(dir_list[num_dirs], file_name); num_dirs++; } } else { // Must match one of the wildcards, also ignore the . if(file_name_length >= 4) { if(file_name[file_name_length - 4] == '.') ext_pos = file_name_length - 4; else if(file_name[file_name_length - 3] == '.') ext_pos = file_name_length - 3; else ext_pos = 0; for(i = 0; wildcards[i] != NULL; i++) { if(!strcasecmp((file_name + ext_pos), wildcards[i])) { file_list[num_files] = (char *)malloc(file_name_length + 1); strcpy(file_list[num_files], file_name); num_files++; break; } } } } } if(num_files == total_filenames_allocated) { file_list = (char **)realloc(file_list, sizeof(char *) * total_filenames_allocated * 2); memset(file_list + total_filenames_allocated, 0, sizeof(char *) * total_filenames_allocated); total_filenames_allocated *= 2; } if(num_dirs == total_dirnames_allocated) { dir_list = (char **)realloc(dir_list, sizeof(char *) * total_dirnames_allocated * 2); memset(dir_list + total_dirnames_allocated, 0, sizeof(char *) * total_dirnames_allocated); total_dirnames_allocated *= 2; } } } while(nread); qsort((void *)file_list, num_files, sizeof(char *), sort_function); qsort((void *)dir_list, num_dirs, sizeof(char *), sort_function); FSDIR_Close(dirHandle); current_dir_length = strlen(current_dir_name); if(current_dir_length > 80) { memcpy(current_dir_short, "...", 3); memcpy(current_dir_short + 3, current_dir_name + current_dir_length - 77, 77); current_dir_short[80] = 0; } else { memcpy(current_dir_short, current_dir_name, current_dir_length + 1); } repeat = 1; if(num_files == 0) current_column = 1; if(num_dirs == 0) current_column = 0; char print_buffer[81]; while(repeat) { sf2d_start_frame(GFX_BOTTOM, GFX_LEFT); //!! sftd_draw_text(font, 0, 4, COLOR_ACTIVE_ITEM, 10, current_dir_short); const char strMsg[] = "[A] Select Rom [X] Run BIOS [Y] Dir up [B] Back"; guitextwidth = sftd_get_text_width(font, 10, strMsg); sftd_draw_text(font, (320 - guitextwidth) / 2, 225, COLOR_HELP_TEXT, 10, strMsg); for(i = 0, current_file_number = i + current_file_scroll_value; i < FILE_LIST_ROWS; i++, current_file_number++) { if(current_file_number < num_files) { strncpy(print_buffer,file_list[current_file_number], 30); //38); print_buffer[30] = 0; //38] = 0; if((current_file_number == current_file_selection) && (current_column == 0)) { sftd_draw_text(font, FILE_LIST_POSITION, ((i + 2) * 10), COLOR_ACTIVE_ITEM, 10, print_buffer); } else { sftd_draw_text(font, FILE_LIST_POSITION, ((i + 2) * 10), COLOR_INACTIVE_ITEM, 10, print_buffer); } } } for(i = 0, current_dir_number = i + current_dir_scroll_value; i < FILE_LIST_ROWS; i++, current_dir_number++) { if(current_dir_number < num_dirs) { strncpy(print_buffer,dir_list[current_dir_number], 8); //13); print_buffer[9] = 0; //14] = 0; if((current_dir_number == current_dir_selection) && (current_column == 1)) { sftd_draw_text(font, DIR_LIST_POSITION, ((i + 2) * 10), COLOR_ACTIVE_ITEM, 10, print_buffer); } else { sftd_draw_text(font, DIR_LIST_POSITION, ((i + 2) * 10), COLOR_INACTIVE_ITEM, 10, print_buffer); } } } // Catch input // change to read key state later if (aptGetStatus() == APP_PREPARE_SLEEPMODE) { aptSignalReadyForSleep(); aptWaitStatusEvent(); } else if (aptGetStatus() == APP_SUSPENDING) { aptReturnToMenu(); } hidScanInput(); u32 keydown = hidKeysDown(); if (keydown & KEY_A) { if(current_column == 1) { if(num_dirs != 0) { repeat = 0; strcpy(prev_dir_name, current_dir_name); if (strlen(current_dir_name)>1) strcat(current_dir_name, "/"); strcat(current_dir_name, dir_list[current_dir_selection]); } } else { if(num_files != 0) { repeat = 0; return_value = 0; //strcpy(result, file_list[current_file_selection]); sprintf(result, "%s/%s", current_dir_name, file_list[current_file_selection]); break; } } } if (keydown & KEY_Y) { repeat = 0; char* findpath = strrchr(current_dir_name,'/'); if(findpath > current_dir_name) findpath[0] = '\0'; else findpath[1] = '\0'; } if (keydown & KEY_B ) { return_value = -1; repeat = 0; break; } if (keydown & KEY_X ) { return_value = 1; repeat = 0; break; } if (keydown & KEY_UP) { if(current_column == 0) { if(current_file_selection) { current_file_selection--; if(current_file_in_scroll == 0) { //clear_screen(COLOR_BG); current_file_scroll_value--; } else { current_file_in_scroll--; } } } else { if(current_dir_selection) { current_dir_selection--; if(current_dir_in_scroll == 0) { //clear_screen(COLOR_BG); current_dir_scroll_value--; } else { current_dir_in_scroll--; } } } } if (keydown & KEY_DOWN) { if(current_column == 0) { if(current_file_selection < (num_files - 1)) { current_file_selection++; if(current_file_in_scroll == (FILE_LIST_ROWS - 1)) { //clear_screen(COLOR_BG); current_file_scroll_value++; } else { current_file_in_scroll++; } } } else { if(current_dir_selection < (num_dirs - 1)) { current_dir_selection++; if(current_dir_in_scroll == (FILE_LIST_ROWS - 1)) { //clear_screen(COLOR_BG); current_dir_scroll_value++; } else { current_dir_in_scroll++; } } } } if (keydown & KEY_L) { if(current_column == 0) { if(current_file_selection>FILE_LIST_ROWS) { current_file_selection-=FILE_LIST_ROWS; current_file_scroll_value -= FILE_LIST_ROWS; if (current_file_in_scroll>current_file_selection){ //clear_screen(COLOR_BG); current_file_scroll_value=0; current_file_in_scroll=current_file_selection; } } else { current_file_selection=0; current_file_scroll_value=0; current_file_in_scroll=0; } } else { if(current_dir_selection) { current_dir_selection--; if(current_dir_in_scroll == 0) { //clear_screen(COLOR_BG); current_dir_scroll_value--; } else { current_dir_in_scroll--; } } } } if (keydown & KEY_R) { if(current_column == 0) { if(current_file_selection < (num_files - 1 - FILE_LIST_ROWS)) { current_file_selection+=FILE_LIST_ROWS; current_file_scroll_value+=FILE_LIST_ROWS; if (current_file_scroll_value>(num_files - FILE_LIST_ROWS)){ //clear_screen(COLOR_BG); current_file_scroll_value=num_files - FILE_LIST_ROWS; current_file_in_scroll= FILE_LIST_ROWS - (num_files - current_file_selection); } //clear_screen(COLOR_BG); } else { current_file_selection = num_files - 1; current_file_in_scroll = (num_files<=FILE_LIST_ROWS - 1)?num_files:FILE_LIST_ROWS - 1; current_file_scroll_value = (num_files > FILE_LIST_ROWS)?num_files - FILE_LIST_ROWS:0; } } else { if(current_dir_selection < (num_dirs - 1)) { current_dir_selection++; if(current_dir_in_scroll == (FILE_LIST_ROWS - 1)) { //clear_screen(COLOR_BG); current_dir_scroll_value++; } else { current_dir_in_scroll++; } } } } if (keydown & KEY_LEFT) { if(current_column == 1) { if(num_files != 0) current_column = 0; } } if (keydown & KEY_RIGHT) { if(current_column == 0) { if(num_dirs != 0) current_column = 1; } } sf2d_end_frame(); gui_DrawTopScreen(); sf2d_swapbuffers(); } // free pointers for(i = 0; i < num_files; i++) free(file_list[i]); free(file_list); for(i = 0; i < num_dirs; i++) free(dir_list[i]); free(dir_list); free(file_name); } return return_value; }