diff --git a/source/libs/fatfs/ff.c b/source/libs/fatfs/ff.c index 2464273..102343f 100644 --- a/source/libs/fatfs/ff.c +++ b/source/libs/fatfs/ff.c @@ -42,8 +42,8 @@ #include "../../storage/sdmmc.h" extern sdmmc_storage_t sd_storage; -#define EFSPRINTF(text, ...) print_error(); gfx_printf("%k"text"%k\n", 0xFFFFFF00, 0xFFFFFFFF); -//#define EFSPRINTF(...) +//#define EFSPRINTF(text, ...) print_error(); gfx_printf("%k"text"%k\n", 0xFFFFFF00, 0xFFFFFFFF); +#define EFSPRINTF(...) /*-------------------------------------------------------------------------- @@ -4056,7 +4056,216 @@ FRESULT f_write ( LEAVE_FF(fs, FR_OK); } +#ifdef FF_FASTFS +/*-----------------------------------------------------------------------*/ +/* Fast Read Aligned Sized File Without a Cache */ +/*-----------------------------------------------------------------------*/ +#if FF_USE_FASTSEEK +FRESULT f_read_fast ( + FIL* fp, /* Pointer to the file object */ + const void* buff, /* Pointer to the data to be written */ + UINT btr /* Number of bytes to read */ +) +{ + if (btr % 65536 != 0) + return f_read(fp, buff, btr, NULL); + FRESULT res; + FATFS *fs; + UINT csize_bytes; + DWORD clst; + UINT count = 0; + FSIZE_t work_sector = 0; + FSIZE_t sector_base = 0; + BYTE *wbuff = (BYTE*)buff; + + + // TODO support sector reading inside a cluster + + res = validate(&fp->obj, &fs); /* Check validity of the file object */ + if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) { + EFSPRINTF("FOV"); + LEAVE_FF(fs, res); /* Check validity */ + } + + if (!(fp->flag & FA_READ)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */ + FSIZE_t remain = fp->obj.objsize - fp->fptr; + if (btr > remain) btr = (UINT)remain; /* Truncate btr by remaining bytes */ + + csize_bytes = fs->csize * SS(fs); + + if (!fp->fptr) { /* On the top of the file? */ + clst = fp->obj.sclust; /* Follow from the origin */ + } else { + if (fp->cltbl) clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */ + else { EFSPRINTF("CLTBL"); ABORT(fs, FR_CLTBL_NO_INIT); } + } + if (clst < 2) { EFSPRINTF("CCHK"); ABORT(fs, FR_INT_ERR); } + else if (clst == 0xFFFFFFFF) { EFSPRINTF("DSKC"); ABORT(fs, FR_DISK_ERR); } + + fp->clust = clst; /* Set working cluster */ + + sector_base = clst2sect(fs, fp->clust); + count += fs->csize; + btr -= csize_bytes; + fp->fptr += csize_bytes; + + while (btr) { + clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */ + + if (clst < 2) { EFSPRINTF("CCHK2"); ABORT(fs, FR_INT_ERR); } + else if (clst == 0xFFFFFFFF) { EFSPRINTF("DSKC"); ABORT(fs, FR_DISK_ERR); } + + fp->clust = clst; + + work_sector = clst2sect(fs, fp->clust); + if ((work_sector - sector_base) == count) count += fs->csize; + else { + if (disk_read(fs->pdrv, wbuff, sector_base, count) != RES_OK) ABORT(fs, FR_DISK_ERR); + wbuff += count * SS(fs); + + sector_base = work_sector; + count = fs->csize; + } + + fp->fptr += MIN(btr, csize_bytes); + btr -= MIN(btr, csize_bytes); + + // TODO: what about if data is smaller than cluster? + // Must read-write back that cluster. + + if (!btr) { /* Final cluster/sectors read. */ + if (disk_read(fs->pdrv, wbuff, sector_base, count) != RES_OK) ABORT(fs, FR_DISK_ERR); + } + } + + LEAVE_FF(fs, FR_OK); +} +#endif +#endif + +#ifdef FF_FASTFS +/*-----------------------------------------------------------------------*/ +/* Fast Write Aligned Sized File Without a Cache */ +/*-----------------------------------------------------------------------*/ +#if FF_USE_FASTSEEK +FRESULT f_write_fast ( + FIL* fp, /* Pointer to the file object */ + const void* buff, /* Pointer to the data to be written */ + UINT btw /* Number of bytes to write */ +) +{ + if (btw % 65536 != 0) + return f_write(fp, buff, btw, NULL); + + FRESULT res; + FATFS *fs; + UINT csize_bytes; + DWORD clst; + UINT count = 0; + FSIZE_t work_sector = 0; + FSIZE_t sector_base = 0; + const BYTE *wbuff = (const BYTE*)buff; + + // TODO support sector writing inside a cluster + + res = validate(&fp->obj, &fs); /* Check validity of the file object */ + if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) { + EFSPRINTF("FOV"); + LEAVE_FF(fs, res); /* Check validity */ + } + + if (!(fp->flag & FA_WRITE)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */ + /* Check fptr wrap-around (file size cannot reach 4 GiB at FAT volume) */ + if ((!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) && (DWORD)(fp->fptr + btw) < (DWORD)fp->fptr) { + btw = (UINT)(0xFFFFFFFF - (DWORD)fp->fptr); + } + + csize_bytes = fs->csize * SS(fs); + + if (!fp->fptr) { /* On the top of the file? */ + clst = fp->obj.sclust; /* Follow from the origin */ + } else { + if (fp->cltbl) clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */ + else { EFSPRINTF("CLTBL"); ABORT(fs, FR_CLTBL_NO_INIT); } + } + + if (clst < 2) { EFSPRINTF("CCHK"); ABORT(fs, FR_INT_ERR); } + else if (clst == 0xFFFFFFFF) { EFSPRINTF("DERR"); ABORT(fs, FR_DISK_ERR); } + + fp->clust = clst; /* Set working cluster */ + + sector_base = clst2sect(fs, fp->clust); + count += fs->csize; + btw -= csize_bytes; + fp->fptr += csize_bytes; + + while (btw) { + clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */ + + if (clst < 2) { EFSPRINTF("CCHK2"); ABORT(fs, FR_INT_ERR); } + else if (clst == 0xFFFFFFFF) { EFSPRINTF("DERR"); ABORT(fs, FR_DISK_ERR); } + + fp->clust = clst; + + work_sector = clst2sect(fs, fp->clust); + if ((work_sector - sector_base) == count) count += fs->csize; + else { + if (disk_write(fs->pdrv, wbuff, sector_base, count) != RES_OK) ABORT(fs, FR_DISK_ERR); + wbuff += count * SS(fs); + + sector_base = work_sector; + count = fs->csize; + } + + fp->fptr += MIN(btw, csize_bytes); + btw -= MIN(btw, csize_bytes); + + // what about if data is smaller than cluster? + // Probably must read-write back that cluster. + if (!btw) { /* Final cluster/sectors write. */ + if (disk_write(fs->pdrv, wbuff, sector_base, count) != RES_OK) ABORT(fs, FR_DISK_ERR); + fp->flag &= (BYTE)~FA_DIRTY; + } + } + + fp->flag |= FA_MODIFIED; /* Set file change flag */ + + LEAVE_FF(fs, FR_OK); +} +#endif +#endif + + +#ifdef FF_FASTFS +#if FF_USE_FASTSEEK +/*-----------------------------------------------------------------------*/ +/* Seek File Read/Write Pointer */ +/*-----------------------------------------------------------------------*/ + +DWORD *f_expand_cltbl ( + FIL* fp, /* Pointer to the file object */ + UINT tblsz, /* Size of table */ + FSIZE_t ofs /* File pointer from top of file */ +) +{ + if (fp->flag & FA_WRITE) f_lseek(fp, ofs); /* Expand file if write is enabled */ + if (!fp->cltbl) { /* Allocate memory for cluster link table */ + fp->cltbl = (DWORD *)ff_memalloc(tblsz); + fp->cltbl[0] = tblsz; + } + if (f_lseek(fp, CREATE_LINKMAP)) { /* Create cluster link table */ + ff_memfree(fp->cltbl); + fp->cltbl = NULL; + EFSPRINTF("CLTBLSZ"); + return NULL; + } + f_lseek(fp, 0); + + return fp->cltbl; +} +#endif +#endif /*-----------------------------------------------------------------------*/ @@ -4169,6 +4378,13 @@ FRESULT f_close ( #endif } } + + if (fp->cltbl != NULL){ + ff_memfree(fp->cltbl); + fp->cltbl = NULL; + } + + return res; } diff --git a/source/libs/fatfs/ff.h b/source/libs/fatfs/ff.h index 471b10d..cdeaaeb 100644 --- a/source/libs/fatfs/ff.h +++ b/source/libs/fatfs/ff.h @@ -246,7 +246,10 @@ typedef enum { FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */ FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */ FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > FF_FS_LOCK */ - FR_INVALID_PARAMETER /* (19) Given parameter is invalid */ + FR_INVALID_PARAMETER, /* (19) Given parameter is invalid */ +#ifdef FF_FASTFS + FR_CLTBL_NO_INIT /* (20) The cluster table for fast seek/read/write was not created */ +#endif } FRESULT; @@ -288,6 +291,11 @@ int f_putc (TCHAR c, FIL* fp); /* Put a character to the file */ int f_puts (const TCHAR* str, FIL* cp); /* Put a string to the file */ int f_printf (FIL* fp, const TCHAR* str, ...); /* Put a formatted string to the file */ TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); /* Get a string from the file */ +#ifdef FF_FASTFS +FRESULT f_read_fast (FIL* fp, const void* buff, UINT btr); /* Fast read data from the file */ +FRESULT f_write_fast (FIL* fp, const void* buff, UINT btw); /* Fast write data to the file */ +DWORD *f_expand_cltbl (FIL* fp, UINT tblsz, FSIZE_t ofs); /* Expand file and populate cluster table */ +#endif #define f_eof(fp) ((int)((fp)->fptr == (fp)->obj.objsize)) #define f_error(fp) ((fp)->err) diff --git a/source/libs/fatfs/ffconf.h b/source/libs/fatfs/ffconf.h index cbe319a..5c5c4b0 100644 --- a/source/libs/fatfs/ffconf.h +++ b/source/libs/fatfs/ffconf.h @@ -42,7 +42,13 @@ /* This option switches f_mkfs() function. (0:Disable or 1:Enable) */ +#define FF_FASTFS 1 + +#ifdef FF_FASTFS +#define FF_USE_FASTSEEK 1 +#else #define FF_USE_FASTSEEK 0 +#endif /* This option switches fast seek function. (0:Disable or 1:Enable) */ @@ -287,3 +293,5 @@ /*--- End of configuration options ---*/ + + diff --git a/source/tegraexplorer/fs/filemenu.c b/source/tegraexplorer/fs/filemenu.c index 4e18fd8..8f19d68 100644 --- a/source/tegraexplorer/fs/filemenu.c +++ b/source/tegraexplorer/fs/filemenu.c @@ -191,7 +191,6 @@ int filemenu(menu_entry file){ break; } - fsreader_readfolder(currentpath); break; case FILE_PAYLOAD: launch_payload(fsutil_getnextloc(currentpath, file.name)); @@ -205,7 +204,6 @@ int filemenu(menu_entry file){ */ runScript(fsutil_getnextloc(currentpath, file.name)); - fsreader_readfolder(currentpath); break; case FILE_HEXVIEW: viewbytes(fsutil_getnextloc(currentpath, file.name)); @@ -213,7 +211,6 @@ int filemenu(menu_entry file){ case FILE_DUMPBIS: gfx_clearscreen(); extract_bis_file(fsutil_getnextloc(currentpath, file.name), currentpath); - fsreader_readfolder(currentpath); hidWait(); break; case FILE_SIGN: @@ -231,5 +228,6 @@ int filemenu(menu_entry file){ return -1; } + fsreader_readfolder(currentpath); return 0; } diff --git a/source/tegraexplorer/fs/fsactions.c b/source/tegraexplorer/fs/fsactions.c index 1edc6c2..f469d23 100644 --- a/source/tegraexplorer/fs/fsactions.c +++ b/source/tegraexplorer/fs/fsactions.c @@ -15,9 +15,8 @@ int fsact_copy(const char *locin, const char *locout, u8 options){ FIL in, out; FILINFO in_info; u64 sizeRemaining, toCopy; - UINT temp1, temp2; u8 *buff, toPrint = options & COPY_MODE_PRINT, toCancel = options & COPY_MODE_CANCEL; - u32 x, y, i = 11; + u32 x, y, i = 11, toSpeed; int res; gfx_con_getpos(&x, &y); @@ -53,22 +52,20 @@ int fsact_copy(const char *locin, const char *locout, u8 options){ sizeRemaining = f_size(&in); const u64 totalsize = sizeRemaining; + DWORD *clmt_in = f_expand_cltbl(&in, BUFSIZE / 4, 0); + DWORD *clmt_out = f_expand_cltbl(&out, BUFSIZE / 4, totalsize); + while (sizeRemaining > 0){ toCopy = MIN(sizeRemaining, BUFSIZE); - if ((res = f_read(&in, buff, toCopy, &temp1))){ + if ((res = f_read_fast(&in, buff, toCopy))){ gfx_errDisplay("copy", res, 5); - return 1; + break; } - - if ((res = f_write(&out, buff, toCopy, &temp2))){ + + if ((res = f_write_fast(&out, buff, toCopy))){ gfx_errDisplay("copy", res, 6); - return 1; - } - - if (temp1 != temp2){ - gfx_errDisplay("copy", ERR_DISK_WRITE_FAILED, 7); - return 1; + break; } sizeRemaining -= toCopy; @@ -100,13 +97,10 @@ int fsact_copy(const char *locin, const char *locout, u8 options){ f_close(&out); free(buff); - if ((res = f_chmod(locout, in_info.fattrib, 0x3A))){ - gfx_errDisplay("copy", res, 8); - return 1; - } + f_chmod(locout, in_info.fattrib, 0x3A); f_stat(locin, &in_info); //somehow stops fatfs from being weird - return 0; + return res; } int fsact_del_recursive(char *path){ diff --git a/source/tegraexplorer/script/parser.c b/source/tegraexplorer/script/parser.c index 8789c54..83e1b13 100644 --- a/source/tegraexplorer/script/parser.c +++ b/source/tegraexplorer/script/parser.c @@ -286,7 +286,9 @@ void runScript(char *path){ gfx_clearscreen(); utils_copystring(path, &path_local); + res = f_open(&scriptin, path, FA_READ | FA_OPEN_EXISTING); + DWORD *clmt_in = f_expand_cltbl(&scriptin, BUFSIZE / 4, 0); if (res != FR_OK){ gfx_errDisplay("ParseScript", res, 1); return;