diff --git a/Makefile b/Makefile index 12eef0b..4239400 100755 --- a/Makefile +++ b/Makefile @@ -39,7 +39,7 @@ OBJS = $(addprefix $(BUILD)/, \ uart.o \ ini.o \ ) -OBJS += $(addprefix $(BUILD)/, diskio.o ff.o ffunicode.o) +OBJS += $(addprefix $(BUILD)/, diskio.o ff.o ffunicode.o ffsystem.o) ARCH := -march=armv4t -mtune=arm7tdmi -mthumb -mthumb-interwork CUSTOMDEFINES = -DMENU_LOGO_ENABLE diff --git a/ipl/ff.c b/ipl/ff.c index e4cd9bb..3305790 100755 --- a/ipl/ff.c +++ b/ipl/ff.c @@ -1,8 +1,8 @@ /*----------------------------------------------------------------------------/ -/ FatFs - Generic FAT Filesystem Module R0.13a / +/ FatFs - Generic FAT Filesystem Module R0.13b / /-----------------------------------------------------------------------------/ / -/ Copyright (C) 2017, ChaN, all right reserved. +/ Copyright (C) 2018, ChaN, all right reserved. / Copyright (c) 2018 naehrwert / Copyright (C) 2018 CTCaer / @@ -36,7 +36,7 @@ extern gfx_con_t gfx_con; ---------------------------------------------------------------------------*/ -#if FF_DEFINED != 89352 /* Revision ID */ +#if FF_DEFINED != 63463 /* Revision ID */ #error Wrong include file (ff.h). #endif @@ -433,10 +433,10 @@ typedef struct { #if FF_VOLUMES < 1 || FF_VOLUMES > 10 #error Wrong FF_VOLUMES setting #endif -static FATFS *FatFs[FF_VOLUMES]; /* Pointer to the filesystem objects (logical drives) */ -static WORD Fsid; /* File system mount ID */ +static FATFS* FatFs[FF_VOLUMES]; /* Pointer to the filesystem objects (logical drives) */ +static WORD Fsid; /* Filesystem mount ID */ -#if FF_FS_RPATH != 0 && FF_VOLUMES >= 2 +#if FF_FS_RPATH != 0 static BYTE CurrVol; /* Current drive */ #endif @@ -444,6 +444,11 @@ static BYTE CurrVol; /* Current drive */ static FILESEM Files[FF_FS_LOCK]; /* Open object lock semaphores */ #endif +#if FF_STR_VOLUME_ID +#ifdef FF_VOLUME_STRS +static const char* const VolumeStr[FF_VOLUMES] = {FF_VOLUME_STRS}; /* Pre-defined volume ID */ +#endif +#endif /*--------------------------------*/ @@ -463,10 +468,10 @@ static FILESEM Files[FF_FS_LOCK]; /* Open object lock semaphores */ #if FF_MAX_LFN < 12 || FF_MAX_LFN > 255 #error Wrong setting of FF_MAX_LFN #endif -#if FF_LFN_BUF < 12 || FF_SFN_BUF < 12 || FF_LFN_BUF < FF_SFN_BUF +#if FF_LFN_BUF < FF_SFN_BUF || FF_SFN_BUF < 12 #error Wrong setting of FF_LFN_BUF or FF_SFN_BUF #endif -#if FF_LFN_UNICODE < 0 || FF_LFN_UNICODE > 2 +#if FF_LFN_UNICODE < 0 || FF_LFN_UNICODE > 3 #error Wrong setting of FF_LFN_UNICODE #endif static const BYTE LfnOfs[] = {1,3,5,7,9,14,16,18,20,22,24,28,30}; /* FAT: Offset of LFN characters in the directory entry */ @@ -505,7 +510,7 @@ static WCHAR LfnBuf[FF_MAX_LFN + 1]; /* LFN working buffer */ #define FREE_NAMBUF() ff_memfree(lfn) #endif #define LEAVE_MKFS(res) { if (!work) ff_memfree(buf); return res; } -#define MAX_MALLOC 0x8000 +#define MAX_MALLOC 0x8000 /* Must be >=FF_MAX_SS */ #else #error Wrong setting of FF_USE_LFN @@ -569,8 +574,7 @@ static const BYTE DbcTbl[] = MKCVTBL(TBL_DC, FF_CODE_PAGE); /* Load/Store multi-byte word in the FAT structure */ /*-----------------------------------------------------------------------*/ -static -WORD ld_word (const BYTE* ptr) /* Load a 2-byte little-endian word */ +static WORD ld_word (const BYTE* ptr) /* Load a 2-byte little-endian word */ { WORD rv; @@ -579,8 +583,7 @@ WORD ld_word (const BYTE* ptr) /* Load a 2-byte little-endian word */ return rv; } -static -DWORD ld_dword (const BYTE* ptr) /* Load a 4-byte little-endian word */ +static DWORD ld_dword (const BYTE* ptr) /* Load a 4-byte little-endian word */ { DWORD rv; @@ -592,8 +595,7 @@ DWORD ld_dword (const BYTE* ptr) /* Load a 4-byte little-endian word */ } #if FF_FS_EXFAT -static -QWORD ld_qword (const BYTE* ptr) /* Load an 8-byte little-endian word */ +static QWORD ld_qword (const BYTE* ptr) /* Load an 8-byte little-endian word */ { QWORD rv; @@ -610,15 +612,13 @@ QWORD ld_qword (const BYTE* ptr) /* Load an 8-byte little-endian word */ #endif #if !FF_FS_READONLY -static -void st_word (BYTE* ptr, WORD val) /* Store a 2-byte word in little-endian */ +static void st_word (BYTE* ptr, WORD val) /* Store a 2-byte word in little-endian */ { *ptr++ = (BYTE)val; val >>= 8; *ptr++ = (BYTE)val; } -static -void st_dword (BYTE* ptr, DWORD val) /* Store a 4-byte word in little-endian */ +static void st_dword (BYTE* ptr, DWORD val) /* Store a 4-byte word in little-endian */ { *ptr++ = (BYTE)val; val >>= 8; *ptr++ = (BYTE)val; val >>= 8; @@ -627,8 +627,7 @@ void st_dword (BYTE* ptr, DWORD val) /* Store a 4-byte word in little-endian */ } #if FF_FS_EXFAT -static -void st_qword (BYTE* ptr, QWORD val) /* Store an 8-byte word in little-endian */ +static void st_qword (BYTE* ptr, QWORD val) /* Store an 8-byte word in little-endian */ { *ptr++ = (BYTE)val; val >>= 8; *ptr++ = (BYTE)val; val >>= 8; @@ -649,8 +648,7 @@ void st_qword (BYTE* ptr, QWORD val) /* Store an 8-byte word in little-endian */ /*-----------------------------------------------------------------------*/ /* Copy memory to memory */ -static -void mem_cpy (void* dst, const void* src, UINT cnt) +static void mem_cpy (void* dst, const void* src, UINT cnt) { BYTE *d = (BYTE*)dst; const BYTE *s = (const BYTE*)src; @@ -664,8 +662,7 @@ void mem_cpy (void* dst, const void* src, UINT cnt) /* Fill memory block */ -static -void mem_set (void* dst, int val, UINT cnt) +static void mem_set (void* dst, int val, UINT cnt) { BYTE *d = (BYTE*)dst; @@ -676,8 +673,7 @@ void mem_set (void* dst, int val, UINT cnt) /* Compare memory block */ -static -int mem_cmp (const void* dst, const void* src, UINT cnt) /* ZR:same, NZ:different */ +static int mem_cmp (const void* dst, const void* src, UINT cnt) /* ZR:same, NZ:different */ { const BYTE *d = (const BYTE *)dst, *s = (const BYTE *)src; int r = 0; @@ -691,8 +687,7 @@ int mem_cmp (const void* dst, const void* src, UINT cnt) /* ZR:same, NZ:differen /* Check if chr is contained in the string */ -static -int chk_chr (const char* str, int chr) /* NZ:contained, ZR:not contained */ +static int chk_chr (const char* str, int chr) /* NZ:contained, ZR:not contained */ { while (*str && *str != chr) str++; return *str; @@ -700,8 +695,7 @@ int chk_chr (const char* str, int chr) /* NZ:contained, ZR:not contained */ /* Test if the character is DBC 1st byte */ -static -int dbc_1st (BYTE c) +static int dbc_1st (BYTE c) { #if FF_CODE_PAGE == 0 /* Variable code page */ if (DbcTbl && c >= DbcTbl[0]) { @@ -721,8 +715,7 @@ int dbc_1st (BYTE c) /* Test if the character is DBC 2nd byte */ -static -int dbc_2nd (BYTE c) +static int dbc_2nd (BYTE c) { #if FF_CODE_PAGE == 0 /* Variable code page */ if (DbcTbl && c >= DbcTbl[4]) { @@ -746,9 +739,8 @@ int dbc_2nd (BYTE c) #if FF_USE_LFN /* Get a character from TCHAR string in defined API encodeing */ -static -DWORD tchar2uni ( /* Returns character in UTF-16 encoding (>=0x10000 on double encoding unit, 0xFFFFFFFF on decode error) */ - const TCHAR** str /* Pointer to pointer to TCHAR string in configured encoding */ +static DWORD tchar2uni ( /* Returns character in UTF-16 encoding (>=0x10000 on double encoding unit, 0xFFFFFFFF on decode error) */ + const TCHAR** str /* Pointer to pointer to TCHAR string in configured encoding */ ) { DWORD uc; @@ -757,7 +749,7 @@ DWORD tchar2uni ( /* Returns character in UTF-16 encoding (>=0x10000 on double #if FF_LFN_UNICODE == 1 /* UTF-16 input */ WCHAR wc; - uc = *p++; + uc = *p++; /* Get a unit */ if (IsSurrogate(uc)) { /* Surrogate? */ wc = *p++; /* Get low surrogate */ if (!IsSurrogateH(uc) || !IsSurrogateL(wc)) return 0xFFFFFFFF; /* Wrong surrogate? */ @@ -768,7 +760,7 @@ DWORD tchar2uni ( /* Returns character in UTF-16 encoding (>=0x10000 on double BYTE b; int nf; - uc = (BYTE)*p++; /* Get a byte */ + uc = (BYTE)*p++; /* Get a unit */ if (uc & 0x80) { /* Multiple byte code? */ if ((uc & 0xE0) == 0xC0) { /* 2-byte sequence? */ uc &= 0x1F; nf = 1; @@ -789,9 +781,14 @@ DWORD tchar2uni ( /* Returns character in UTF-16 encoding (>=0x10000 on double uc = uc << 6 | (b & 0x3F); } while (--nf != 0); if (uc < 0x80 || IsSurrogate(uc) || uc >= 0x110000) return 0xFFFFFFFF; /* Wrong code? */ - if (uc >= 0x10000) uc = 0xD800DC00 | ((uc - 0x10000) << 6 & 0x3FF0000) | (uc & 0x3FF); /* Make a surrogate pair if needed */ + if (uc >= 0x010000) uc = 0xD800DC00 | ((uc - 0x10000) << 6 & 0x3FF0000) | (uc & 0x3FF); /* Make a surrogate pair if needed */ } +#elif FF_LFN_UNICODE == 3 /* UTF-32 input */ + uc = (TCHAR)*p++; /* Get a unit */ + if (uc >= 0x110000) return 0xFFFFFFFF; /* Wrong code? */ + if (uc >= 0x010000) uc = 0xD800DC00 | ((uc - 0x10000) << 6 & 0x3FF0000) | (uc & 0x3FF); /* Make a surrogate pair if needed */ + #else /* ANSI/OEM input */ BYTE b; WCHAR wc; @@ -815,8 +812,7 @@ DWORD tchar2uni ( /* Returns character in UTF-16 encoding (>=0x10000 on double /* Output a TCHAR string in defined API encoding */ -static -BYTE put_utf ( /* Returns number of encoding units written (0:buffer overflow or wrong encoding) */ +static BYTE put_utf ( /* Returns number of encoding units written (0:buffer overflow or wrong encoding) */ DWORD chr, /* UTF-16 encoded character (Double encoding unit char if >=0x10000) */ TCHAR* buf, /* Output buffer */ UINT szb /* Size of the buffer */ @@ -870,6 +866,19 @@ BYTE put_utf ( /* Returns number of encoding units written (0:buffer overflow or *buf++ = (TCHAR)(0x80 | (chr >> 0 & 0x3F)); return 4; +#elif FF_LFN_UNICODE == 3 /* UTF-32 output */ + DWORD hc; + + if (szb < 1) return 0; /* Buffer overflow? */ + if (chr >= 0x10000) { /* Out of BMP? */ + hc = ((chr & 0xFFFF0000) - 0xD8000000) >> 6; /* Get high 10 bits */ + chr = (chr & 0xFFFF) - 0xDC00; /* Get low 10 bits */ + if (hc >= 0x100000 || chr >= 0x400) return 0; /* Wrong surrogate? */ + chr = (hc | chr) + 0x10000; + } + *buf++ = (TCHAR)chr; + return 1; + #else /* ANSI/OEM output */ WCHAR wc; @@ -892,8 +901,7 @@ BYTE put_utf ( /* Returns number of encoding units written (0:buffer overflow or /*-----------------------------------------------------------------------*/ /* Request/Release grant to access the volume */ /*-----------------------------------------------------------------------*/ -static -int lock_fs ( /* 1:Ok, 0:timeout */ +static int lock_fs ( /* 1:Ok, 0:timeout */ FATFS* fs /* Filesystem object */ ) { @@ -901,8 +909,7 @@ int lock_fs ( /* 1:Ok, 0:timeout */ } -static -void unlock_fs ( +static void unlock_fs ( FATFS* fs, /* Filesystem object */ FRESULT res /* Result code to be returned */ ) @@ -921,8 +928,7 @@ void unlock_fs ( /* File lock control functions */ /*-----------------------------------------------------------------------*/ -static -FRESULT chk_lock ( /* Check if the file can be accessed */ +static FRESULT chk_lock ( /* Check if the file can be accessed */ DIR* dp, /* Directory object pointing the file to be checked */ int acc /* Desired access type (0:Read mode open, 1:Write mode open, 2:Delete or rename) */ ) @@ -949,8 +955,7 @@ FRESULT chk_lock ( /* Check if the file can be accessed */ } -static -int enq_lock (void) /* Check if an entry is available for a new object */ +static int enq_lock (void) /* Check if an entry is available for a new object */ { UINT i; @@ -959,8 +964,7 @@ int enq_lock (void) /* Check if an entry is available for a new object */ } -static -UINT inc_lock ( /* Increment object open counter and returns its index (0:Internal error) */ +static UINT inc_lock ( /* Increment object open counter and returns its index (0:Internal error) */ DIR* dp, /* Directory object pointing the file to register or increment */ int acc /* Desired access (0:Read, 1:Write, 2:Delete/Rename) */ ) @@ -991,8 +995,7 @@ UINT inc_lock ( /* Increment object open counter and returns its index (0:Intern } -static -FRESULT dec_lock ( /* Decrement object open counter */ +static FRESULT dec_lock ( /* Decrement object open counter */ UINT i /* Semaphore index (1..) */ ) { @@ -1014,8 +1017,7 @@ FRESULT dec_lock ( /* Decrement object open counter */ } -static -void clear_lock ( /* Clear lock entries of the volume */ +static void clear_lock ( /* Clear lock entries of the volume */ FATFS *fs ) { @@ -1034,8 +1036,7 @@ void clear_lock ( /* Clear lock entries of the volume */ /* Move/Flush disk access window in the filesystem object */ /*-----------------------------------------------------------------------*/ #if !FF_FS_READONLY -static -FRESULT sync_window ( /* Returns FR_OK or FR_DISK_ERR */ +static FRESULT sync_window ( /* Returns FR_OK or FR_DISK_ERR */ FATFS* fs /* Filesystem object */ ) { @@ -1057,8 +1058,7 @@ FRESULT sync_window ( /* Returns FR_OK or FR_DISK_ERR */ #endif -static -FRESULT move_window ( /* Returns FR_OK or FR_DISK_ERR */ +static FRESULT move_window ( /* Returns FR_OK or FR_DISK_ERR */ FATFS* fs, /* Filesystem object */ DWORD sector /* Sector number to make appearance in the fs->win[] */ ) @@ -1089,8 +1089,7 @@ FRESULT move_window ( /* Returns FR_OK or FR_DISK_ERR */ /* Synchronize filesystem and data on the storage */ /*-----------------------------------------------------------------------*/ -static -FRESULT sync_fs ( /* Returns FR_OK or FR_DISK_ERR */ +static FRESULT sync_fs ( /* Returns FR_OK or FR_DISK_ERR */ FATFS* fs /* Filesystem object */ ) { @@ -1127,8 +1126,7 @@ FRESULT sync_fs ( /* Returns FR_OK or FR_DISK_ERR */ /* Get physical sector number from cluster number */ /*-----------------------------------------------------------------------*/ -static -DWORD clst2sect ( /* !=0:Sector number, 0:Failed (invalid cluster#) */ +static DWORD clst2sect ( /* !=0:Sector number, 0:Failed (invalid cluster#) */ FATFS* fs, /* Filesystem object */ DWORD clst /* Cluster# to be converted */ ) @@ -1145,8 +1143,7 @@ DWORD clst2sect ( /* !=0:Sector number, 0:Failed (invalid cluster#) */ /* FAT access - Read value of a FAT entry */ /*-----------------------------------------------------------------------*/ -static -DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, 2..0x7FFFFFFF:Cluster status */ +static DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, 2..0x7FFFFFFF:Cluster status */ FFOBJID* obj, /* Corresponding object */ DWORD clst /* Cluster number to get the value */ ) @@ -1183,7 +1180,7 @@ DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, 2..0x7FFFFFFF:Clust break; #if FF_FS_EXFAT case FS_EXFAT : - if (obj->objsize != 0) { + if ((obj->objsize != 0 && obj->sclust != 0) || obj->stat == 0) { /* Object except root dir must have valid data length */ DWORD cofs = clst - obj->sclust; /* Offset from start cluster */ DWORD clen = (DWORD)((obj->objsize - 1) / SS(fs)) / fs->csize; /* Number of clusters - 1 */ @@ -1223,8 +1220,7 @@ DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, 2..0x7FFFFFFF:Clust /* FAT access - Change value of a FAT entry */ /*-----------------------------------------------------------------------*/ -static -FRESULT put_fat ( /* FR_OK(0):succeeded, !=0:error */ +static FRESULT put_fat ( /* FR_OK(0):succeeded, !=0:error */ FATFS* fs, /* Corresponding filesystem object */ DWORD clst, /* FAT index number (cluster number) to be changed */ DWORD val /* New value to be set to the entry */ @@ -1289,8 +1285,7 @@ FRESULT put_fat ( /* FR_OK(0):succeeded, !=0:error */ /* Find a contiguous free cluster block */ /*--------------------------------------*/ -static -DWORD find_bitmap ( /* 0:Not found, 2..:Cluster block found, 0xFFFFFFFF:Disk error */ +static DWORD find_bitmap ( /* 0:Not found, 2..:Cluster block found, 0xFFFFFFFF:Disk error */ FATFS* fs, /* Filesystem object */ DWORD clst, /* Cluster number to scan from */ DWORD ncl /* Number of contiguous clusters to find (1..) */ @@ -1330,8 +1325,7 @@ DWORD find_bitmap ( /* 0:Not found, 2..:Cluster block found, 0xFFFFFFFF:Disk err /* Set/Clear a block of allocation bitmap */ /*----------------------------------------*/ -static -FRESULT change_bitmap ( +static FRESULT change_bitmap ( FATFS* fs, /* Filesystem object */ DWORD clst, /* Cluster number to change from */ DWORD ncl, /* Number of clusters to be changed */ @@ -1367,8 +1361,7 @@ FRESULT change_bitmap ( /* Fill the first fragment of the FAT chain */ /*---------------------------------------------*/ -static -FRESULT fill_first_frag ( +static FRESULT fill_first_frag ( FFOBJID* obj /* Pointer to the corresponding object */ ) { @@ -1391,8 +1384,7 @@ FRESULT fill_first_frag ( /* Fill the last fragment of the FAT chain */ /*---------------------------------------------*/ -static -FRESULT fill_last_frag ( +static FRESULT fill_last_frag ( FFOBJID* obj, /* Pointer to the corresponding object */ DWORD lcl, /* Last cluster of the fragment */ DWORD term /* Value to set the last FAT entry */ @@ -1417,8 +1409,8 @@ FRESULT fill_last_frag ( /*-----------------------------------------------------------------------*/ /* FAT handling - Remove a cluster chain */ /*-----------------------------------------------------------------------*/ -static -FRESULT remove_chain ( /* FR_OK(0):succeeded, !=0:error */ + +static FRESULT remove_chain ( /* FR_OK(0):succeeded, !=0:error */ FFOBJID* obj, /* Corresponding object */ DWORD clst, /* Cluster to remove a chain from */ DWORD pclst /* Previous cluster of clst (0:entire chain) */ @@ -1512,8 +1504,8 @@ FRESULT remove_chain ( /* FR_OK(0):succeeded, !=0:error */ /*-----------------------------------------------------------------------*/ /* FAT handling - Stretch a chain or Create a new chain */ /*-----------------------------------------------------------------------*/ -static -DWORD create_chain ( /* 0:No free cluster, 1:Internal error, 0xFFFFFFFF:Disk error, >=2:New cluster# */ + +static DWORD create_chain ( /* 0:No free cluster, 1:Internal error, 0xFFFFFFFF:Disk error, >=2:New cluster# */ FFOBJID* obj, /* Corresponding object */ DWORD clst /* Cluster# to stretch, 0:Create a new chain */ ) @@ -1616,8 +1608,7 @@ DWORD create_chain ( /* 0:No free cluster, 1:Internal error, 0xFFFFFFFF:Disk err /* FAT handling - Convert offset into cluster with link map table */ /*-----------------------------------------------------------------------*/ -static -DWORD clmt_clust ( /* <2:Error, >=2:Cluster number */ +static DWORD clmt_clust ( /* <2:Error, >=2:Cluster number */ FIL* fp, /* Pointer to the file object */ FSIZE_t ofs /* File offset to be converted to cluster# */ ) @@ -1647,8 +1638,7 @@ DWORD clmt_clust ( /* <2:Error, >=2:Cluster number */ /*-----------------------------------------------------------------------*/ #if !FF_FS_READONLY -static -FRESULT dir_clear ( /* Returns FR_OK or FR_DISK_ERR */ +static FRESULT dir_clear ( /* Returns FR_OK or FR_DISK_ERR */ FATFS *fs, /* Filesystem object */ DWORD clst /* Directory table to clear */ ) @@ -1664,7 +1654,7 @@ FRESULT dir_clear ( /* Returns FR_OK or FR_DISK_ERR */ mem_set(fs->win, 0, SS(fs)); /* Clear window buffer */ #if FF_USE_LFN == 3 /* Quick table clear by using multi-secter write */ /* Allocate a temporary buffer */ - for (szb = ((DWORD)fs->csize * SS(fs) >= MAX_MALLOC) ? MAX_MALLOC : fs->csize * SS(fs); szb > SS(fs) && !(ibuf = ff_memalloc(szb)); szb /= 2) ; + for (szb = ((DWORD)fs->csize * SS(fs) >= MAX_MALLOC) ? MAX_MALLOC : fs->csize * SS(fs), ibuf = 0; szb > SS(fs) && (ibuf = ff_memalloc(szb)) == 0; szb /= 2) ; if (szb > SS(fs)) { /* Buffer allocated? */ mem_set(ibuf, 0, szb); szb /= SS(fs); /* Bytes -> Sectors */ @@ -1673,7 +1663,7 @@ FRESULT dir_clear ( /* Returns FR_OK or FR_DISK_ERR */ } else #endif { - ibuf = fs->win; szb = 1; /* Use window buffer (single-sector writes may take a time) */ + ibuf = fs->win; szb = 1; /* Use window buffer (many single-sector writes may take a time) */ for (n = 0; n < fs->csize && disk_write(fs->pdrv, ibuf, sect + n, szb) == RES_OK; n += szb) ; /* Fill the cluster with 0 */ } return (n == fs->csize) ? FR_OK : FR_DISK_ERR; @@ -1687,8 +1677,7 @@ FRESULT dir_clear ( /* Returns FR_OK or FR_DISK_ERR */ /* Directory handling - Set directory index */ /*-----------------------------------------------------------------------*/ -static -FRESULT dir_sdi ( /* FR_OK(0):succeeded, !=0:error */ +static FRESULT dir_sdi ( /* FR_OK(0):succeeded, !=0:error */ DIR* dp, /* Pointer to directory object */ DWORD ofs /* Offset of directory table */ ) @@ -1736,10 +1725,9 @@ FRESULT dir_sdi ( /* FR_OK(0):succeeded, !=0:error */ /* Directory handling - Move directory table index next */ /*-----------------------------------------------------------------------*/ -static -FRESULT dir_next ( /* FR_OK(0):succeeded, FR_NO_FILE:End of table, FR_DENIED:Could not stretch */ - DIR* dp, /* Pointer to the directory object */ - int stretch /* 0: Do not stretch table, 1: Stretch table if needed */ +static FRESULT dir_next ( /* FR_OK(0):succeeded, FR_NO_FILE:End of table, FR_DENIED:Could not stretch */ + DIR* dp, /* Pointer to the directory object */ + int stretch /* 0: Do not stretch table, 1: Stretch table if needed */ ) { DWORD ofs, clst; @@ -1747,7 +1735,8 @@ FRESULT dir_next ( /* FR_OK(0):succeeded, FR_NO_FILE:End of table, FR_DENIED:Cou ofs = dp->dptr + SZDIRE; /* Next entry */ - if (dp->sect == 0 || ofs >= (DWORD)((FF_FS_EXFAT && fs->fs_type == FS_EXFAT) ? MAX_DIR_EX : MAX_DIR)) return FR_NO_FILE; /* Report EOT when offset has reached max value */ + if (ofs >= (DWORD)((FF_FS_EXFAT && fs->fs_type == FS_EXFAT) ? MAX_DIR_EX : MAX_DIR)) dp->sect = 0; /* Disable it if the offset reached the max value */ + if (dp->sect == 0) return FR_NO_FILE; /* Report EOT if it has been disabled */ if (ofs % SS(fs) == 0) { /* Sector changed? */ dp->sect++; /* Next sector */ @@ -1797,10 +1786,9 @@ FRESULT dir_next ( /* FR_OK(0):succeeded, FR_NO_FILE:End of table, FR_DENIED:Cou /* Directory handling - Reserve a block of directory entries */ /*-----------------------------------------------------------------------*/ -static -FRESULT dir_alloc ( /* FR_OK(0):succeeded, !=0:error */ - DIR* dp, /* Pointer to the directory object */ - UINT nent /* Number of contiguous entries to allocate */ +static FRESULT dir_alloc ( /* FR_OK(0):succeeded, !=0:error */ + DIR* dp, /* Pointer to the directory object */ + UINT nent /* Number of contiguous entries to allocate */ ) { FRESULT res; @@ -1840,10 +1828,9 @@ FRESULT dir_alloc ( /* FR_OK(0):succeeded, !=0:error */ /* FAT: Directory handling - Load/Store start cluster number */ /*-----------------------------------------------------------------------*/ -static -DWORD ld_clust ( /* Returns the top cluster value of the SFN entry */ - FATFS* fs, /* Pointer to the fs object */ - const BYTE* dir /* Pointer to the key entry */ +static DWORD ld_clust ( /* Returns the top cluster value of the SFN entry */ + FATFS* fs, /* Pointer to the fs object */ + const BYTE* dir /* Pointer to the key entry */ ) { DWORD cl; @@ -1858,8 +1845,7 @@ DWORD ld_clust ( /* Returns the top cluster value of the SFN entry */ #if !FF_FS_READONLY -static -void st_clust ( +static void st_clust ( FATFS* fs, /* Pointer to the fs object */ BYTE* dir, /* Pointer to the key entry */ DWORD cl /* Value to be set */ @@ -1878,8 +1864,8 @@ void st_clust ( /*--------------------------------------------------------*/ /* FAT-LFN: Compare a part of file name with an LFN entry */ /*--------------------------------------------------------*/ -static -int cmp_lfn ( /* 1:matched, 0:not matched */ + +static int cmp_lfn ( /* 1:matched, 0:not matched */ const WCHAR* lfnbuf, /* Pointer to the LFN working buffer to be compared */ BYTE* dir /* Pointer to the directory entry containing the part of LFN */ ) @@ -1914,8 +1900,8 @@ int cmp_lfn ( /* 1:matched, 0:not matched */ /*-----------------------------------------------------*/ /* FAT-LFN: Pick a part of file name from an LFN entry */ /*-----------------------------------------------------*/ -static -int pick_lfn ( /* 1:succeeded, 0:buffer overflow or invalid LFN entry */ + +static int pick_lfn ( /* 1:succeeded, 0:buffer overflow or invalid LFN entry */ WCHAR* lfnbuf, /* Pointer to the LFN working buffer */ BYTE* dir /* Pointer to the LFN entry */ ) @@ -1952,8 +1938,8 @@ int pick_lfn ( /* 1:succeeded, 0:buffer overflow or invalid LFN entry */ /*-----------------------------------------*/ /* FAT-LFN: Create an entry of LFN entries */ /*-----------------------------------------*/ -static -void put_lfn ( + +static void put_lfn ( const WCHAR* lfn, /* Pointer to the LFN */ BYTE* dir, /* Pointer to the LFN entry to be created */ BYTE ord, /* LFN order (1-20) */ @@ -1990,8 +1976,7 @@ void put_lfn ( /* FAT-LFN: Create a Numbered SFN */ /*-----------------------------------------------------------------------*/ -static -void gen_numname ( +static void gen_numname ( BYTE* dst, /* Pointer to the buffer to store numbered SFN */ const BYTE* src, /* Pointer to SFN */ const WCHAR* lfn, /* Pointer to LFN */ @@ -2008,7 +1993,7 @@ void gen_numname ( if (seq > 5) { /* In case of many collisions, generate a hash number instead of sequential number */ sr = seq; - while (*lfn) { /* Create a CRC */ + while (*lfn) { /* Create a CRC as hash value */ wc = *lfn++; for (i = 0; i < 16; i++) { sr = (sr << 1) + (wc & 1); @@ -2049,8 +2034,7 @@ void gen_numname ( /* FAT-LFN: Calculate checksum of an SFN entry */ /*-----------------------------------------------------------------------*/ -static -BYTE sum_sfn ( +static BYTE sum_sfn ( const BYTE* dir /* Pointer to the SFN entry */ ) { @@ -2072,8 +2056,7 @@ BYTE sum_sfn ( /* exFAT: Checksum */ /*-----------------------------------------------------------------------*/ -static -WORD xdir_sum ( /* Get checksum of the directoly entry block */ +static WORD xdir_sum ( /* Get checksum of the directoly entry block */ const BYTE* dir /* Directory entry block to be calculated */ ) { @@ -2081,9 +2064,9 @@ WORD xdir_sum ( /* Get checksum of the directoly entry block */ WORD sum; - szblk = (dir[XDIR_NumSec] + 1) * SZDIRE; + szblk = (dir[XDIR_NumSec] + 1) * SZDIRE; /* Number of bytes of the entry block */ for (i = sum = 0; i < szblk; i++) { - if (i == XDIR_SetSum) { /* Skip sum field */ + if (i == XDIR_SetSum) { /* Skip 2-byte sum field */ i++; } else { sum = ((sum & 1) ? 0x8000 : 0) + (sum >> 1) + dir[i]; @@ -2094,8 +2077,7 @@ WORD xdir_sum ( /* Get checksum of the directoly entry block */ -static -WORD xname_sum ( /* Get check sum (to be used as hash) of the name */ +static WORD xname_sum ( /* Get check sum (to be used as hash) of the file name */ const WCHAR* name /* File name to be calculated */ ) { @@ -2104,7 +2086,7 @@ WORD xname_sum ( /* Get check sum (to be used as hash) of the name */ while ((chr = *name++) != 0) { - chr = (WCHAR)ff_wtoupper(chr); /* File name needs to be upper-case converted */ + chr = (WCHAR)ff_wtoupper(chr); /* File name needs to be up-case converted */ sum = ((sum & 1) ? 0x8000 : 0) + (sum >> 1) + (chr & 0xFF); sum = ((sum & 1) ? 0x8000 : 0) + (sum >> 1) + (chr >> 8); } @@ -2113,10 +2095,9 @@ WORD xname_sum ( /* Get check sum (to be used as hash) of the name */ #if !FF_FS_READONLY && FF_USE_MKFS -static -DWORD xsum32 ( - BYTE dat, /* Byte to be calculated */ - DWORD sum /* Previous sum */ +static DWORD xsum32 ( /* Returns 32-bit checksum */ + BYTE dat, /* Byte to be calculated (byte-by-byte processing) */ + DWORD sum /* Previous sum value */ ) { sum = ((sum & 1) ? 0x80000000 : 0) + (sum >> 1) + dat; @@ -2130,8 +2111,7 @@ DWORD xsum32 ( /* exFAT: Get object information from a directory block */ /*------------------------------------------------------*/ -static -void get_xfileinfo ( +static void get_xfileinfo ( BYTE* dirb, /* Pointer to the direcotry entry block 85+C0+C1s */ FILINFO* fno /* Buffer to store the extracted file information */ ) @@ -2141,7 +2121,7 @@ void get_xfileinfo ( /* Get file name from the entry block */ si = SZDIRE * 2; /* 1st C1 entry */ - nc = hs = di = 0; + nc = 0; hs = 0; di = 0; while (nc < dirb[XDIR_NumName]) { if (si >= MAXDIRB(FF_MAX_LFN)) { di = 0; break; } /* Truncated directory block? */ if ((si % SZDIRE) == 0) si += 2; /* Skip entry type field */ @@ -2149,7 +2129,7 @@ void get_xfileinfo ( if (hs == 0 && IsSurrogate(wc)) { /* Is it a surrogate? */ hs = wc; continue; /* Get low surrogate */ } - wc = put_utf((DWORD)hs << 16 | wc, &fno->fname[di], FF_LFN_BUF - di); /* Store it in UTF-16 or UTF-8 encoding */ + wc = put_utf((DWORD)hs << 16 | wc, &fno->fname[di], FF_LFN_BUF - di); /* Store it in API encoding */ if (wc == 0) { di = 0; break; } /* Buffer overflow or wrong encoding? */ di += wc; hs = 0; @@ -2157,7 +2137,7 @@ void get_xfileinfo ( if (hs != 0) di = 0; /* Broken surrogate pair? */ if (di == 0) fno->fname[di++] = '?'; /* Inaccessible object name? */ fno->fname[di] = 0; /* Terminate the name */ - fno->altname[0] = 0; /* exFAT does not have SFN */ + fno->altname[0] = 0; /* exFAT does not support SFN */ fno->fattrib = dirb[XDIR_Attr]; /* Attribute */ fno->fsize = (fno->fattrib & AM_DIR) ? 0 : ld_qword(dirb + XDIR_FileSize); /* Size */ @@ -2172,9 +2152,8 @@ void get_xfileinfo ( /* exFAT: Get a directry entry block */ /*-----------------------------------*/ -static -FRESULT load_xdir ( /* FR_INT_ERR: invalid entry block */ - DIR* dp /* Reading direcotry object pointing top of the entry block to load */ +static FRESULT load_xdir ( /* FR_INT_ERR: invalid entry block */ + DIR* dp /* Reading direcotry object pointing top of the entry block to load */ ) { FRESULT res; @@ -2224,8 +2203,7 @@ FRESULT load_xdir ( /* FR_INT_ERR: invalid entry block */ /* exFAT: Initialize object allocation info with loaded entry block */ /*------------------------------------------------------------------*/ -static -void init_alloc_info ( +static void init_alloc_info ( FATFS* fs, /* Filesystem object */ FFOBJID* obj /* Object allocation information to be initialized */ ) @@ -2242,8 +2220,8 @@ void init_alloc_info ( /*------------------------------------------------*/ /* exFAT: Load the object's directory entry block */ /*------------------------------------------------*/ -static -FRESULT load_obj_xdir ( + +static FRESULT load_obj_xdir ( DIR* dp, /* Blank directory object to be used to access containing direcotry */ const FFOBJID* obj /* Object with its containing directory information */ ) @@ -2271,8 +2249,8 @@ FRESULT load_obj_xdir ( /*----------------------------------------*/ /* exFAT: Store the directory entry block */ /*----------------------------------------*/ -static -FRESULT store_xdir ( + +static FRESULT store_xdir ( DIR* dp /* Pointer to the direcotry object */ ) { @@ -2304,8 +2282,7 @@ FRESULT store_xdir ( /* exFAT: Create a new directory enrty block */ /*-------------------------------------------*/ -static -void create_xdir ( +static void create_xdir ( BYTE* dirb, /* Pointer to the direcotry entry block buffer */ const WCHAR* lfn /* Pointer to the object name */ ) @@ -2351,8 +2328,7 @@ void create_xdir ( #define dir_read_file(dp) dir_read(dp, 0) #define dir_read_label(dp) dir_read(dp, 1) -static -FRESULT dir_read ( +static FRESULT dir_read ( DIR* dp, /* Pointer to the directory object */ int vol /* Filtered by 0:file/directory or 1:volume label */ ) @@ -2430,9 +2406,8 @@ FRESULT dir_read ( /* Directory handling - Find an object in the directory */ /*-----------------------------------------------------------------------*/ -static -FRESULT dir_find ( /* FR_OK(0):succeeded, !=0:error */ - DIR* dp /* Pointer to the directory object with the file name */ +static FRESULT dir_find ( /* FR_OK(0):succeeded, !=0:error */ + DIR* dp /* Pointer to the directory object with the file name */ ) { FRESULT res; @@ -2512,9 +2487,8 @@ FRESULT dir_find ( /* FR_OK(0):succeeded, !=0:error */ /* Register an object to the directory */ /*-----------------------------------------------------------------------*/ -static -FRESULT dir_register ( /* FR_OK:succeeded, FR_DENIED:no free entry or too many SFN collision, FR_DISK_ERR:disk error */ - DIR* dp /* Target directory with object name to be created */ +static FRESULT dir_register ( /* FR_OK:succeeded, FR_DENIED:no free entry or too many SFN collision, FR_DISK_ERR:disk error */ + DIR* dp /* Target directory with object name to be created */ ) { FRESULT res; @@ -2619,9 +2593,8 @@ FRESULT dir_register ( /* FR_OK:succeeded, FR_DENIED:no free entry or too many S /* Remove an object from the directory */ /*-----------------------------------------------------------------------*/ -static -FRESULT dir_remove ( /* FR_OK:Succeeded, FR_DISK_ERR:A disk error */ - DIR* dp /* Directory object pointing the entry to be removed */ +static FRESULT dir_remove ( /* FR_OK:Succeeded, FR_DISK_ERR:A disk error */ + DIR* dp /* Directory object pointing the entry to be removed */ ) { FRESULT res; @@ -2666,10 +2639,9 @@ FRESULT dir_remove ( /* FR_OK:Succeeded, FR_DISK_ERR:A disk error */ /* Get file information from directory entry */ /*-----------------------------------------------------------------------*/ -static -void get_fileinfo ( - DIR* dp, /* Pointer to the directory object */ - FILINFO* fno /* Pointer to the file information to be filled */ +static void get_fileinfo ( + DIR* dp, /* Pointer to the directory object */ + FILINFO* fno /* Pointer to the file information to be filled */ ) { UINT si, di; @@ -2721,7 +2693,7 @@ void get_fileinfo ( } wc = ff_oem2uni(wc, CODEPAGE); /* ANSI/OEM -> Unicode */ if (wc == 0) { di = 0; break; } /* Wrong char in the current code page? */ - wc = put_utf(wc, &fno->altname[di], FF_SFN_BUF - di); /* Store it in UTF-16 or UTF-8 */ + wc = put_utf(wc, &fno->altname[di], FF_SFN_BUF - di); /* Store it in Unicode */ if (wc == 0) { di = 0; break; } /* Buffer overflow? */ di += wc; #else /* ANSI/OEM output */ @@ -2771,9 +2743,8 @@ void get_fileinfo ( /* Pattern matching */ /*-----------------------------------------------------------------------*/ -static -DWORD get_achar ( /* Get a character and advances ptr */ - const TCHAR** ptr /* Pointer to pointer to the ANSI/OEM or Unicode string */ +static DWORD get_achar ( /* Get a character and advances ptr */ + const TCHAR** ptr /* Pointer to pointer to the ANSI/OEM or Unicode string */ ) { DWORD chr; @@ -2803,8 +2774,7 @@ DWORD get_achar ( /* Get a character and advances ptr */ } -static -int pattern_matching ( /* 0:not matched, 1:matched */ +static int pattern_matching ( /* 0:not matched, 1:matched */ const TCHAR* pat, /* Matching pattern */ const TCHAR* nam, /* String to be tested */ int skip, /* Number of pre-skip chars (number of ?s) */ @@ -2851,10 +2821,9 @@ int pattern_matching ( /* 0:not matched, 1:matched */ /* Pick a top segment and create the object name in directory form */ /*-----------------------------------------------------------------------*/ -static -FRESULT create_name ( /* FR_OK: successful, FR_INVALID_NAME: could not create */ - DIR* dp, /* Pointer to the directory object */ - const TCHAR** path /* Pointer to pointer to the segment in the path string */ +static FRESULT create_name ( /* FR_OK: successful, FR_INVALID_NAME: could not create */ + DIR* dp, /* Pointer to the directory object */ + const TCHAR** path /* Pointer to pointer to the segment in the path string */ ) { #if FF_USE_LFN /* LFN configuration */ @@ -3049,10 +3018,9 @@ FRESULT create_name ( /* FR_OK: successful, FR_INVALID_NAME: could not create */ /* Follow a file path */ /*-----------------------------------------------------------------------*/ -static -FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */ - DIR* dp, /* Directory object to return last directory and found object */ - const TCHAR* path /* Full-path string to find a file or directory */ +static FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */ + DIR* dp, /* Directory object to return last directory and found object */ + const TCHAR* path /* Full-path string to find a file or directory */ ) { FRESULT res; @@ -3137,58 +3105,71 @@ FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */ /* Get logical drive number from path name */ /*-----------------------------------------------------------------------*/ -static -int get_ldnumber ( /* Returns logical drive number (-1:invalid drive) */ - const TCHAR** path /* Pointer to pointer to the path name */ +static int get_ldnumber ( /* Returns logical drive number (-1:invalid drive number or null pointer) */ + const TCHAR** path /* Pointer to pointer to the path name */ ) { const TCHAR *tp, *tt; - UINT i; - int vol = -1; -#if FF_STR_VOLUME_ID /* Find string drive id */ - static const char* const volid[] = {FF_VOLUME_STRS}; + TCHAR tc; + int i, vol = -1; +#if FF_STR_VOLUME_ID /* Find string volume ID */ const char *sp; char c; - TCHAR tc; #endif + tt = tp = *path; + if (!tp) return vol; /* Invalid path name? */ + do tc = *tt++; while ((UINT)tc >= (FF_USE_LFN ? ' ' : '!') && tc != ':'); /* Find a colon in the path */ - if (*path != 0) { /* If the pointer is not a null */ - for (tt = *path; (UINT)*tt >= (FF_USE_LFN ? ' ' : '!') && *tt != ':'; tt++) ; /* Find a colon in the path */ - if (*tt == ':') { /* If a colon is exist in the path name */ - tp = *path; - i = *tp++; - if (IsDigit(i) && tp == tt) { /* Is there a numeric drive id + colon? */ - if ((i -= '0') < FF_VOLUMES) { /* If drive id is found, get the value and strip it */ - vol = (int)i; - *path = ++tt; - } - } -#if FF_STR_VOLUME_ID - else { /* No numeric drive number, find string drive id */ - i = 0; tt++; - do { - sp = volid[i]; tp = *path; - do { /* Compare a string drive id with path name */ - c = *sp++; tc = *tp++; - if (IsLower(tc)) tc -= 0x20; - } while (c && (TCHAR)c == tc); - } while ((c || tp != tt) && ++i < FF_VOLUMES); /* Repeat for each id until pattern match */ - if (i < FF_VOLUMES) { /* If a drive id is found, get the value and strip it */ - vol = (int)i; - *path = tt; - } - } -#endif - } else { /* No volume id and use default drive */ -#if FF_FS_RPATH != 0 && FF_VOLUMES >= 2 - vol = CurrVol; /* Current drive */ -#else - vol = 0; /* Drive 0 */ + if (tc == ':') { /* DOS/Windows style volume ID? */ + i = FF_VOLUMES; + if (IsDigit(*tp) && tp + 2 == tt) { /* Is there a numeric volume ID + colon? */ + i = (int)*tp - '0'; /* Get the LD number */ + } +#if FF_STR_VOLUME_ID == 1 /* Arbitrary string is enabled */ + else { + i = 0; + do { + sp = VolumeStr[i]; tp = *path; /* This string volume ID and path name */ + do { /* Compare the volume ID with path name */ + c = *sp++; tc = *tp++; + if (IsLower(c)) c -= 0x20; + if (IsLower(tc)) tc -= 0x20; + } while (c && (TCHAR)c == tc); + } while ((c || tp != tt) && ++i < FF_VOLUMES); /* Repeat for each id until pattern match */ + } #endif + if (i < FF_VOLUMES) { /* If a volume ID is found, get the drive number and strip it */ + vol = i; /* Drive number */ + *path = tt; /* Snip the drive prefix off */ + } + return vol; + } +#if FF_STR_VOLUME_ID == 2 /* Unix style volume ID is enabled */ + if (*tp == '/') { + i = 0; + do { + sp = VolumeStr[i]; tp = *path; /* This string volume ID and path name */ + do { /* Compare the volume ID with path name */ + c = *sp++; tc = *(++tp); + if (IsLower(c)) c -= 0x20; + if (IsLower(tc)) tc -= 0x20; + } while (c && (TCHAR)c == tc); + } while ((c || (tc != '/' && (UINT)tc >= (FF_USE_LFN ? ' ' : '!'))) && ++i < FF_VOLUMES); /* Repeat for each ID until pattern match */ + if (i < FF_VOLUMES) { /* If a volume ID is found, get the drive number and strip it */ + vol = i; /* Drive number */ + *path = tp; /* Snip the drive prefix off */ + return vol; } } - return vol; +#endif + /* No drive prefix is found */ +#if FF_FS_RPATH != 0 + vol = CurrVol; /* Default drive is current drive */ +#else + vol = 0; /* Default drive is 0 */ +#endif + return vol; /* Return the default drive */ } @@ -3198,16 +3179,15 @@ int get_ldnumber ( /* Returns logical drive number (-1:invalid drive) */ /* Load a sector and check if it is an FAT VBR */ /*-----------------------------------------------------------------------*/ -static -BYTE check_fs ( /* 0:FAT, 1:exFAT, 2:Valid BS but not FAT, 3:Not a BS, 4:Disk error */ - FATFS* fs, /* Filesystem object */ - DWORD sect /* Sector# (lba) to load and check if it is an FAT-VBR or not */ +static BYTE check_fs ( /* 0:FAT, 1:exFAT, 2:Valid BS but not FAT, 3:Not a BS, 4:Disk error */ + FATFS* fs, /* Filesystem object */ + DWORD sect /* Sector# (lba) to load and check if it is an FAT-VBR or not */ ) { fs->wflag = 0; fs->winsect = 0xFFFFFFFF; /* Invaidate window */ if (move_window(fs, sect) != FR_OK) return 4; /* Load boot record */ - if (ld_word(fs->win + BS_55AA) != 0xAA55) return 3; /* Check boot record signature (always placed here even if the sector size is >512) */ + if (ld_word(fs->win + BS_55AA) != 0xAA55) return 3; /* Check boot record signature (always here regardless of the sector size) */ #if FF_FS_EXFAT if (!mem_cmp(fs->win + BS_JmpBoot, "\xEB\x76\x90" "EXFAT ", 11)) return 1; /* Check if exFAT VBR */ @@ -3226,11 +3206,10 @@ BYTE check_fs ( /* 0:FAT, 1:exFAT, 2:Valid BS but not FAT, 3:Not a BS, 4:Disk er /* Determine logical drive number and mount the volume if needed */ /*-----------------------------------------------------------------------*/ -static -FRESULT find_volume ( /* FR_OK(0): successful, !=0: any error occurred */ - const TCHAR** path, /* Pointer to pointer to the path name (drive number) */ - FATFS** rfs, /* Pointer to pointer to the found filesystem object */ - BYTE mode /* !=0: Check write protection for write access */ +static FRESULT find_volume ( /* FR_OK(0): successful, !=0: an error occurred */ + const TCHAR** path, /* Pointer to pointer to the path name (drive number) */ + FATFS** rfs, /* Pointer to pointer to the found filesystem object */ + BYTE mode /* !=0: Check write protection for write access */ ) { BYTE fmt, *pt; @@ -3506,7 +3485,7 @@ FRESULT find_volume ( /* FR_OK(0): successful, !=0: any error occurred */ #if FF_USE_LFN == 1 fs->lfnbuf = LfnBuf; /* Static LFN working buffer */ #if FF_FS_EXFAT - fs->dirbuf = DirBuf; /* Static directory block scratch-pad buffer */ + fs->dirbuf = DirBuf; /* Static directory block scratchpad buffer */ #endif #endif #if FF_FS_RPATH != 0 @@ -3525,10 +3504,9 @@ FRESULT find_volume ( /* FR_OK(0): successful, !=0: any error occurred */ /* Check if the file/directory object is valid or not */ /*-----------------------------------------------------------------------*/ -static -FRESULT validate ( /* Returns FR_OK or FR_INVALID_OBJECT */ - FFOBJID* obj, /* Pointer to the FFOBJID, the 1st member in the FIL/DIR object, to check validity */ - FATFS** rfs /* Pointer to pointer to the owner filesystem object to return */ +static FRESULT validate ( /* Returns FR_OK or FR_INVALID_OBJECT */ + FFOBJID* obj, /* Pointer to the FFOBJID, the 1st member in the FIL/DIR object, to check validity */ + FATFS** rfs /* Pointer to pointer to the owner filesystem object to return */ ) { FRESULT res = FR_INVALID_OBJECT; @@ -3639,7 +3617,7 @@ FRESULT f_open ( if (!fp) return FR_INVALID_OBJECT; - /* Get logical drive */ + /* Get logical drive number */ mode &= FF_FS_READONLY ? FA_READ : FA_READ | FA_WRITE | FA_CREATE_ALWAYS | FA_CREATE_NEW | FA_OPEN_ALWAYS | FA_OPEN_APPEND; res = find_volume(&path, &fs, mode); if (res == FR_OK) { @@ -3839,7 +3817,7 @@ FRESULT f_read ( remain = fp->obj.objsize - fp->fptr; if (btr > remain) btr = (UINT)remain; /* Truncate btr by remaining bytes */ - for ( ; btr; /* Repeat until all data read */ + for ( ; btr; /* Repeat until btr bytes read */ btr -= rcnt, *br += rcnt, rbuff += rcnt, fp->fptr += rcnt) { if (fp->fptr % SS(fs) == 0) { /* On the sector boundary? */ csect = (UINT)(fp->fptr / SS(fs) & (fs->csize - 1)); /* Sector offset in the cluster */ @@ -4198,9 +4176,8 @@ FRESULT f_close ( /* Change Current Directory or Current Drive, Get Current Directory */ /*-----------------------------------------------------------------------*/ -#if FF_VOLUMES >= 2 FRESULT f_chdrive ( - const TCHAR* path /* Drive number */ + const TCHAR* path /* Drive number to set */ ) { int vol; @@ -4209,23 +4186,26 @@ FRESULT f_chdrive ( /* Get logical drive number */ vol = get_ldnumber(&path); if (vol < 0) return FR_INVALID_DRIVE; - CurrVol = (BYTE)vol; /* Set it as current volume */ return FR_OK; } -#endif + FRESULT f_chdir ( const TCHAR* path /* Pointer to the directory path */ ) { +#if FF_STR_VOLUME_ID == 2 + UINT i; +#endif FRESULT res; DIR dj; FATFS *fs; DEF_NAMBUF + /* Get logical drive */ res = find_volume(&path, &fs, 0); if (res == FR_OK) { @@ -4233,8 +4213,8 @@ FRESULT f_chdir ( INIT_NAMBUF(fs); res = follow_path(&dj, path); /* Follow the path */ if (res == FR_OK) { /* Follow completed */ - if (dj.fn[NSFLAG] & NS_NONAME) { - fs->cdir = dj.obj.sclust; /* It is the start directory itself */ + if (dj.fn[NSFLAG] & NS_NONAME) { /* Is it the start directory itself? */ + fs->cdir = dj.obj.sclust; #if FF_FS_EXFAT if (fs->fs_type == FS_EXFAT) { fs->cdc_scl = dj.obj.c_scl; @@ -4262,6 +4242,12 @@ FRESULT f_chdir ( } FREE_NAMBUF(); if (res == FR_NO_FILE) res = FR_NO_PATH; +#if FF_STR_VOLUME_ID == 2 /* Also current drive is changed at Unix style volume ID */ + if (res == FR_OK) { + for (i = FF_VOLUMES - 1; i && fs != FatFs[i]; i--) ; /* Set current drive */ + CurrVol = (BYTE)i; + } +#endif } LEAVE_FF(fs, res); @@ -4271,7 +4257,7 @@ FRESULT f_chdir ( #if FF_FS_RPATH >= 2 FRESULT f_getcwd ( TCHAR* buff, /* Pointer to the directory path */ - UINT len /* Size of path */ + UINT len /* Size of buff in unit of TCHAR */ ) { FRESULT res; @@ -4279,17 +4265,24 @@ FRESULT f_getcwd ( FATFS *fs; UINT i, n; DWORD ccl; - TCHAR *tp; + TCHAR *tp = buff; +#if FF_VOLUMES >= 2 + UINT vl; +#endif +#if FF_STR_VOLUME_ID + const char *vp; +#endif FILINFO fno; DEF_NAMBUF - *buff = 0; /* Get logical drive */ res = find_volume((const TCHAR**)&buff, &fs, 0); /* Get current volume */ if (res == FR_OK) { dj.obj.fs = fs; INIT_NAMBUF(fs); + + /* Follow parent directories and create the path */ i = len; /* Bottom of buffer (directory stack base) */ if (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) { /* (Cannot do getcwd on exFAT and returns root path) */ dj.obj.sclust = fs->cdir; /* Start to follow upper directory from current directory */ @@ -4310,32 +4303,44 @@ FRESULT f_getcwd ( if (res == FR_NO_FILE) res = FR_INT_ERR;/* It cannot be 'not found'. */ if (res != FR_OK) break; get_fileinfo(&dj, &fno); /* Get the directory name and push it to the buffer */ - for (n = 0; fno.fname[n]; n++) ; - if (i < n + 3) { + for (n = 0; fno.fname[n]; n++) ; /* Name length */ + if (i < n + 1) { /* Insufficient space to store the path name? */ res = FR_NOT_ENOUGH_CORE; break; } - while (n) buff[--i] = fno.fname[--n]; + while (n) buff[--i] = fno.fname[--n]; /* Stack the name */ buff[--i] = '/'; } } - tp = buff; if (res == FR_OK) { -#if FF_VOLUMES >= 2 - *tp++ = '0' + CurrVol; /* Put drive number */ - *tp++ = ':'; + if (i == len) buff[--i] = '/'; /* Is it the root-directory? */ +#if FF_VOLUMES >= 2 /* Put drive prefix */ + vl = 0; +#if FF_STR_VOLUME_ID >= 1 /* String volume ID */ + for (n = 0, vp = (const char*)VolumeStr[CurrVol]; vp[n]; n++) ; + if (i >= n + 2) { + if (FF_STR_VOLUME_ID == 2) *tp++ = (TCHAR)'/'; + for (vl = 0; vl < n; *tp++ = (TCHAR)vp[vl], vl++) ; + if (FF_STR_VOLUME_ID == 1) *tp++ = (TCHAR)':'; + vl++; + } +#else /* Numeric volume ID */ + if (i >= 3) { + *tp++ = (TCHAR)'0' + CurrVol; + *tp++ = (TCHAR)':'; + vl = 2; + } #endif - if (i == len) { /* Root-directory */ - *tp++ = '/'; - } else { /* Sub-directroy */ - do /* Add stacked path str */ - *tp++ = buff[i++]; - while (i < len); + if (vl == 0) res = FR_NOT_ENOUGH_CORE; +#endif + /* Add current directory path */ + if (res == FR_OK) { + do *tp++ = buff[i++]; while (i < len); /* Copy stacked path string */ } } - *tp = 0; FREE_NAMBUF(); } + *tp = 0; LEAVE_FF(fs, res); } @@ -5300,8 +5305,8 @@ FRESULT f_getlabel ( wc = dj.dir[si++]; #if FF_USE_LFN && FF_LFN_UNICODE >= 1 /* Unicode output */ if (dbc_1st((BYTE)wc) && si < 11) wc = wc << 8 | dj.dir[si++]; /* Is it a DBC? */ - wc = ff_oem2uni(wc, CODEPAGE); - if (wc != 0) wc = put_utf(wc, &label[di], 4); + wc = ff_oem2uni(wc, CODEPAGE); /* Convert it into Unicode */ + if (wc != 0) wc = put_utf(wc, &label[di], 4); /* Put it in Unicode */ if (wc == 0) { di = 0; break; } di += wc; #else /* ANSI/OEM output */ @@ -5359,7 +5364,7 @@ FRESULT f_setlabel ( BYTE dirvn[22]; UINT di; WCHAR wc; - static const char badchr[] = "+.,;=[]\"*:<>\?|\x7F"; /* [0..] for FAT, [7..] for exFAT */ + static const char badchr[] = "+.,;=[]/\\\"*:<>\?|\x7F"; /* [0..] for FAT, [7..] for exFAT */ #if FF_USE_LFN DWORD dc; #endif @@ -5372,7 +5377,7 @@ FRESULT f_setlabel ( if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */ mem_set(dirvn, 0, 22); di = 0; - while (*label) { /* Create volume label in directory form */ + while ((UINT)*label >= ' ') { /* Create volume label */ dc = tchar2uni(&label); /* Get a Unicode character */ if (dc >= 0x10000) { if (dc == 0xFFFFFFFF || di >= 10) { /* Wrong surrogate or buffer overflow */ @@ -5391,7 +5396,7 @@ FRESULT f_setlabel ( { /* On the FAT/FAT32 volume */ mem_set(dirvn, ' ', 11); di = 0; - while (*label) { /* Create volume label in directory form */ + while ((UINT)*label >= ' ') { /* Create volume label */ #if FF_USE_LFN dc = tchar2uni(&label); wc = (dc < 0x10000) ? ff_uni2oem(ff_wtoupper(dc), CODEPAGE) : 0; @@ -5679,7 +5684,7 @@ FRESULT f_mkfs ( /* Get working buffer */ #if FF_USE_LFN == 3 if (!work) { /* Use heap memory for working buffer */ - for (szb_buf = MAX_MALLOC, buf = 0; szb_buf >= ss && !(buf = ff_memalloc(szb_buf)); szb_buf /= 2) ; + for (szb_buf = MAX_MALLOC, buf = 0; szb_buf >= ss && (buf = ff_memalloc(szb_buf)) == 0; szb_buf /= 2) ; sz_buf = szb_buf / ss; /* Size of working buffer (sector) */ } else #endif @@ -5757,7 +5762,7 @@ FRESULT f_mkfs ( /* Create a compressed up-case table */ sect = b_data + au * tbl[0]; /* Table start sector */ sum = 0; /* Table checksum to be stored in the 82 entry */ - st = si = i = j = szb_case = 0; + st = 0; si = 0; i = 0; j = 0; szb_case = 0; do { switch (st) { case 0: @@ -5777,7 +5782,7 @@ FRESULT f_mkfs ( break; default: - ch = (WCHAR)j; si += j; /* Number of chars to skip */ + ch = (WCHAR)j; si += (WCHAR)j; /* Number of chars to skip */ st = 0; } sum = xsum32(buf[i + 0] = (BYTE)ch, sum); /* Put it into the write buffer */ @@ -5829,12 +5834,12 @@ FRESULT f_mkfs ( mem_set(buf, 0, szb_buf); buf[SZDIRE * 0 + 0] = 0x83; /* 83 entry (volume label) */ buf[SZDIRE * 1 + 0] = 0x81; /* 81 entry (allocation bitmap) */ - st_dword(buf + SZDIRE * 1 + 20, 2); - st_dword(buf + SZDIRE * 1 + 24, szb_bit); + st_dword(buf + SZDIRE * 1 + 20, 2); /* cluster */ + st_dword(buf + SZDIRE * 1 + 24, szb_bit); /* size */ buf[SZDIRE * 2 + 0] = 0x82; /* 82 entry (up-case table) */ - st_dword(buf + SZDIRE * 2 + 4, sum); - st_dword(buf + SZDIRE * 2 + 20, 2 + tbl[0]); - st_dword(buf + SZDIRE * 2 + 24, szb_case); + st_dword(buf + SZDIRE * 2 + 4, sum); /* sum */ + st_dword(buf + SZDIRE * 2 + 20, 2 + tbl[0]); /* cluster */ + st_dword(buf + SZDIRE * 2 + 24, szb_case); /* size */ sect = b_data + au * (tbl[0] + tbl[1]); nsect = au; /* Start of the root directory and number of sectors */ do { /* Fill root directory sectors */ n = (nsect > sz_buf) ? sz_buf : nsect; @@ -6102,7 +6107,7 @@ FRESULT f_fdisk ( ) { UINT i, n, sz_cyl, tot_cyl, b_cyl, e_cyl, p_cyl; - BYTE s_hd, e_hd, *p, *buf; = (BYTE*)work; + BYTE s_hd, e_hd, *p, *buf = (BYTE*)work; DSTATUS stat; DWORD sz_disk, sz_part, s_part; FRESULT res; @@ -6122,7 +6127,7 @@ FRESULT f_fdisk ( /* Determine the CHS without any consideration of the drive geometry */ for (n = 16; n < 256 && sz_disk / n / 63 > 1024; n *= 2) ; if (n == 256) n--; - e_hd = n - 1; + e_hd = (BYTE)(n - 1); sz_cyl = 63 * n; tot_cyl = sz_disk / sz_cyl; @@ -6186,68 +6191,22 @@ TCHAR* f_gets ( { int nc = 0; TCHAR *p = buff; - BYTE s[2]; + BYTE s[4]; UINT rc; - WCHAR wc; -#if FF_USE_LFN && ((FF_LFN_UNICODE == 1 && FF_STRF_ENCODE == 3) || (FF_LFN_UNICODE == 2 && FF_STRF_ENCODE != 3)) DWORD dc; +#if FF_USE_LFN && FF_LFN_UNICODE && FF_STRF_ENCODE <= 2 + WCHAR wc; #endif -#if FF_USE_LFN && FF_LFN_UNICODE == 1 && FF_STRF_ENCODE == 3 +#if FF_USE_LFN && FF_LFN_UNICODE && FF_STRF_ENCODE == 3 UINT ct; #endif -#if FF_USE_LFN && FF_LFN_UNICODE == 1 /* UTF-16 output */ -#if FF_STRF_ENCODE == 0 /* Read a character in ANSI/OEM */ - while (nc < len - 1) { - f_read(fp, s, 1, &rc); - if (rc != 1) break; - wc = s[0]; - if (dbc_1st((BYTE)wc)) { - f_read(fp, s, 1, &rc); - if (rc != 1 || !dbc_2nd(s[0])) continue; - wc = wc << 8 | s[0]; - } - wc = ff_oem2uni(wc, CODEPAGE); - if (wc == 0) continue; -#elif FF_STRF_ENCODE == 1 || FF_STRF_ENCODE == 2 /* Read a character in UTF-16LE/BE */ - while (nc < len - 1) { - f_read(fp, s, 2, &rc); - if (rc != 2) break; - wc = (FF_STRF_ENCODE == 1) ? s[1] << 8 | s[0] : s[0] << 8 | s[1]; -#elif FF_STRF_ENCODE == 3 /* Read a character in UTF-8 */ - while (nc < len - 2) { - f_read(fp, s, 1, &rc); - if (rc != 1) break; - dc = s[0]; - if (dc >= 0x80) { - ct = 0; - if ((dc & 0xE0) == 0xC0) { dc &= 0x1F; ct = 1; } - if ((dc & 0xF0) == 0xE0) { dc &= 0x0F; ct = 2; } - if ((dc & 0xF8) == 0xF0) { dc &= 0x07; ct = 3; } - if (ct == 0) continue; - do { - f_read(fp, s, 1, &rc); - if (rc != 1 || (s[0] & 0xC0) != 0x80) break; - dc = dc << 6 | (s[0] & 0x3F); - } while (--ct); - if (ct || dc < 0x80 || dc >= 0x110000) continue; - } - if (dc >= 0x10000) { - wc = (WCHAR)(0xD800 | ((dc >> 10) - 0x40)); - *p++ = wc; nc++; - wc = (WCHAR)(0xDC00 | (dc & 0x3FF)); - } else { - wc = (WCHAR)dc; - } -#endif - /* Output it in UTF-16 encoding */ - if (FF_USE_STRFUNC == 2 && wc == '\r') continue; - *p++ = wc; nc++; - if (wc == '\n') break; - } - -#elif FF_USE_LFN && FF_LFN_UNICODE == 2 && FF_STRF_ENCODE != 3 /* UTF-8 output */ - while (nc < len - 4) { +#if FF_USE_LFN && FF_LFN_UNICODE /* With code conversion (Unicode API) */ + /* Make a room for the character and terminator */ + if (FF_LFN_UNICODE == 1) len -= (FF_STRF_ENCODE == 0) ? 1 : 2; + if (FF_LFN_UNICODE == 2) len -= (FF_STRF_ENCODE == 0) ? 3 : 4; + if (FF_LFN_UNICODE == 3) len -= 1; + while (nc < len) { #if FF_STRF_ENCODE == 0 /* Read a character in ANSI/OEM */ f_read(fp, s, 1, &rc); if (rc != 1) break; @@ -6259,26 +6218,53 @@ TCHAR* f_gets ( } dc = ff_oem2uni(wc, CODEPAGE); if (dc == 0) continue; -#else /* Read a character in UTF-16LE/BE */ +#elif FF_STRF_ENCODE == 1 || FF_STRF_ENCODE == 2 /* Read a character in UTF-16LE/BE */ f_read(fp, s, 2, &rc); if (rc != 2) break; - dc = (FF_STRF_ENCODE == 1) ? s[1] << 8 | s[0] : s[0] << 8 | s[1]; - if (IsSurrogate(dc)) { + dc = (FF_STRF_ENCODE == 1) ? ld_word(s) : s[0] << 8 | s[1]; + if (IsSurrogateL(dc)) continue; + if (IsSurrogateH(dc)) { f_read(fp, s, 2, &rc); if (rc != 2) break; - wc = (FF_STRF_ENCODE == 1) ? s[1] << 8 | s[0] : s[0] << 8 | s[1]; - if (!IsSurrogateH(dc) || !IsSurrogateL(wc)) continue; + wc = (FF_STRF_ENCODE == 1) ? ld_word(s) : s[0] << 8 | s[1]; + if (!IsSurrogateL(wc)) continue; dc = ((dc & 0x3FF) + 0x40) << 10 | (wc & 0x3FF); } +#else /* Read a character in UTF-8 */ + f_read(fp, s, 1, &rc); + if (rc != 1) break; + dc = s[0]; + if (dc >= 0x80) { /* Multi-byte character? */ + ct = 0; + if ((dc & 0xE0) == 0xC0) { dc &= 0x1F; ct = 1; } /* 2-byte? */ + if ((dc & 0xF0) == 0xE0) { dc &= 0x0F; ct = 2; } /* 3-byte? */ + if ((dc & 0xF8) == 0xF0) { dc &= 0x07; ct = 3; } /* 4-byte? */ + if (ct == 0) continue; + f_read(fp, s, ct, &rc); /* Get trailing bytes */ + if (rc != ct) break; + rc = 0; + do { /* Merge trailing bytes */ + if ((s[rc] & 0xC0) != 0x80) break; + dc = dc << 6 | (s[rc] & 0x3F); + } while (++rc < ct); + if (rc != ct || dc < 0x80 || IsSurrogate(dc) || dc >= 0x110000) continue; /* Wrong encoding? */ + } #endif - /* Output it in UTF-8 encoding */ - if (FF_USE_STRFUNC == 2 && dc == '\r') continue; + if (FF_USE_STRFUNC == 2 && dc == '\r') continue; /* Strip \r off if needed */ +#if FF_LFN_UNICODE == 1 || FF_LFN_UNICODE == 3 /* Output it in UTF-16/32 encoding */ + if (FF_LFN_UNICODE == 1 && dc >= 0x10000) { /* Out of BMP at UTF-16? */ + *p++ = (TCHAR)(0xD800 | ((dc >> 10) - 0x40)); nc++; /* Make and output high surrogate */ + dc = 0xDC00 | (dc & 0x3FF); /* Make low surrogate */ + } + *p++ = (TCHAR)dc; nc++; + if (dc == '\n') break; /* End of line? */ +#elif FF_LFN_UNICODE == 2 /* Output it in UTF-8 encoding */ if (dc < 0x80) { /* 1-byte */ *p++ = (TCHAR)dc; nc++; - if (dc == '\n') break; + if (dc == '\n') break; /* End of line? */ } else { - if (dc < 0x800) { /* 2-byte */ + if (dc < 0x800) { /* 2-byte */ *p++ = (TCHAR)(0xC0 | (dc >> 6 & 0x1F)); *p++ = (TCHAR)(0x80 | (dc >> 0 & 0x3F)); nc += 2; @@ -6297,21 +6283,23 @@ TCHAR* f_gets ( } } } +#endif } -#else /* Byte-by-byte without any conversion (ANSI/OEM API or UTF-8 to UTF-8) */ - while (nc < len - 1) { +#else /* Byte-by-byte without any conversion (ANSI/OEM API) */ + len -= 1; /* Make a room for the terminator */ + while (nc < len) { f_read(fp, s, 1, &rc); if (rc != 1) break; - wc = s[0]; - if (FF_USE_STRFUNC == 2 && wc == '\r') continue; - *p++ = (TCHAR)wc; nc++; - if (wc == '\n') break; + dc = s[0]; + if (FF_USE_STRFUNC == 2 && dc == '\r') continue; + *p++ = (TCHAR)dc; nc++; + if (dc == '\n') break; } #endif - *p = 0; - return nc ? buff : 0; /* When no data read (EOF or error), return with error. */ + *p = 0; /* Terminate the string */ + return nc ? buff : 0; /* When no data read due to EOF or error, return with error. */ } @@ -6344,12 +6332,12 @@ void putc_bfd ( /* Buffered write with code conversion */ { UINT n; int i, nc; -#if FF_USE_LFN && (FF_LFN_UNICODE == 1 || (FF_LFN_UNICODE == 2 && (FF_STRF_ENCODE != 3))) +#if FF_USE_LFN && FF_LFN_UNICODE WCHAR hs, wc; -#endif -#if FF_USE_LFN && FF_LFN_UNICODE == 2 && FF_STRF_ENCODE != 3 +#if FF_LFN_UNICODE == 2 DWORD dc; TCHAR *tp; +#endif #endif if (FF_USE_STRFUNC == 2 && c == '\n') { /* LF -> CRLF conversion */ @@ -6358,45 +6346,21 @@ void putc_bfd ( /* Buffered write with code conversion */ i = pb->idx; /* Write index of pb->buf[] */ if (i < 0) return; - nc = pb->nchr; /* Write unit count */ + nc = pb->nchr; /* Write unit counter */ -#if FF_USE_LFN && FF_LFN_UNICODE >= 1 -#if FF_USE_LFN && FF_LFN_UNICODE == 1 /* UTF-16 input */ +#if FF_USE_LFN && FF_LFN_UNICODE +#if FF_LFN_UNICODE == 1 /* UTF-16 input */ if (IsSurrogateH(c)) { pb->hs = c; return; } - wc = c; hs = pb->hs; pb->hs = 0; + hs = pb->hs; pb->hs = 0; if (hs != 0) { - if (!IsSurrogateL(wc)) hs = 0; + if (!IsSurrogateL(c)) hs = 0; } else { - if (IsSurrogateL(wc)) return; + if (IsSurrogateL(c)) return; } -#if FF_STRF_ENCODE == 3 /* Write it in UTF-8 */ - if (hs != 0) { /* 4-byte */ - nc += 4; - hs = (hs & 0x3FF) + 0x40; - pb->buf[i++] = (BYTE)(0xF0 | hs >> 8); - pb->buf[i++] = (BYTE)(0x80 | (hs >> 2 & 0x3F)); - pb->buf[i++] = (BYTE)(0x80 | (hs & 3) << 4 | (wc >> 6 & 0x0F)); - pb->buf[i++] = (BYTE)(0x80 | (wc & 0x3F)); - } else { - if (wc < 0x80) { /* 1-byte */ - nc++; - pb->buf[i++] = (BYTE)wc; - } else { - if (wc < 0x800) { /* 2-byte */ - nc += 2; - pb->buf[i++] = (BYTE)(0xC0 | wc >> 6); - } else { /* 3-byte */ - nc += 3; - pb->buf[i++] = (BYTE)(0xE0 | wc >> 12); - pb->buf[i++] = (BYTE)(0x80 | (wc >> 6 & 0x3F)); - } - pb->buf[i++] = (BYTE)(0x80 | (wc & 0x3F)); - } - } -#endif -#else /* UTF-8 input */ + wc = c; +#elif FF_LFN_UNICODE == 2 /* UTF-8 input */ for (;;) { if (pb->ct == 0) { /* Out of multi-byte sequence? */ pb->bs[pb->wi = 0] = (BYTE)c; /* Save 1st byte */ @@ -6405,36 +6369,40 @@ void putc_bfd ( /* Buffered write with code conversion */ if (((BYTE)c & 0xF0) == 0xE0) pb->ct = 2; /* 3-byte? */ if (((BYTE)c & 0xF1) == 0xF0) pb->ct = 3; /* 4-byte? */ return; - } else { /* In the multi-byte sequence */ + } else { /* In the multi-byte sequence */ if (((BYTE)c & 0xC0) != 0x80) { /* Broken sequence? */ pb->ct = 0; continue; } pb->bs[++pb->wi] = (BYTE)c; /* Save the trailing byte */ - if (--pb->ct == 0) break; /* End of sequence? */ + if (--pb->ct == 0) break; /* End of multi-byte sequence? */ return; } } -#if FF_STRF_ENCODE == 3 /* Write it in UTF-8 */ - pb->buf[i++] = pb->bs[0]; nc++; - if (pb->bs[0] >= 0xC0) { - pb->buf[i++] = pb->bs[1]; nc++; - } - if (pb->bs[0] >= 0xE0) { - pb->buf[i++] = pb->bs[2]; nc++; - } - if (pb->bs[0] >= 0xF0) { - pb->buf[i++] = pb->bs[3]; nc++; - } -#else /* Write it in UTF-16 or ANSI/OEM */ tp = (TCHAR*)pb->bs; dc = tchar2uni(&tp); /* UTF-8 ==> UTF-16 */ if (dc == 0xFFFFFFFF) return; wc = (WCHAR)dc; hs = (WCHAR)(dc >> 16); +#elif FF_LFN_UNICODE == 3 /* UTF-32 input */ + if (IsSurrogate(c) || c >= 0x110000) return; + if (c >= 0x10000) { + hs = (WCHAR)(0xD800 | ((c >> 10) - 0x40)); /* Make high surrogate */ + wc = 0xDC00 | (c & 0x3FF); /* Make low surrogate */ + } else { + hs = 0; + wc = (WCHAR)c; + } #endif -#endif -#if FF_USE_LFN && FF_LFN_UNICODE >= 1 && FF_STRF_ENCODE != 3 -#if FF_STRF_ENCODE == 2 /* Write a character in UTF-16BE */ + +#if FF_STRF_ENCODE == 1 /* Write a character in UTF-16LE */ + if (hs != 0) { + st_word(&pb->buf[i], hs); + i += 2; + nc++; + } + st_word(&pb->buf[i], wc); + i += 2; +#elif FF_STRF_ENCODE == 2 /* Write a character in UTF-16BE */ if (hs != 0) { pb->buf[i++] = (BYTE)(hs >> 8); pb->buf[i++] = (BYTE)hs; @@ -6442,30 +6410,41 @@ void putc_bfd ( /* Buffered write with code conversion */ } pb->buf[i++] = (BYTE)(wc >> 8); pb->buf[i++] = (BYTE)wc; - nc++; -#elif FF_STRF_ENCODE == 1 /* Write a character in UTF-16LE */ - if (hs != 0) { - pb->buf[i++] = (BYTE)hs; - pb->buf[i++] = (BYTE)(hs >> 8); - nc++; +#elif FF_STRF_ENCODE == 3 /* Write it in UTF-8 */ + if (hs != 0) { /* 4-byte */ + nc += 3; + hs = (hs & 0x3FF) + 0x40; + pb->buf[i++] = (BYTE)(0xF0 | hs >> 8); + pb->buf[i++] = (BYTE)(0x80 | (hs >> 2 & 0x3F)); + pb->buf[i++] = (BYTE)(0x80 | (hs & 3) << 4 | (wc >> 6 & 0x0F)); + pb->buf[i++] = (BYTE)(0x80 | (wc & 0x3F)); + } else { + if (wc < 0x80) { /* 1-byte */ + pb->buf[i++] = (BYTE)wc; + } else { + if (wc < 0x800) { /* 2-byte */ + nc += 1; + pb->buf[i++] = (BYTE)(0xC0 | wc >> 6); + } else { /* 3-byte */ + nc += 2; + pb->buf[i++] = (BYTE)(0xE0 | wc >> 12); + pb->buf[i++] = (BYTE)(0x80 | (wc >> 6 & 0x3F)); + } + pb->buf[i++] = (BYTE)(0x80 | (wc & 0x3F)); + } } - pb->buf[i++] = (BYTE)wc; - pb->buf[i++] = (BYTE)(wc >> 8); - nc++; -#else /* Write a character in ANSI/OEM */ +#else /* Write it in ANSI/OEM */ if (hs != 0) return; wc = ff_uni2oem(wc, CODEPAGE); /* UTF-16 ==> ANSI/OEM */ if (wc == 0) return;; if (wc >= 0x100) { pb->buf[i++] = (BYTE)(wc >> 8); nc++; } - pb->buf[i++] = (BYTE)wc; nc++; -#endif + pb->buf[i++] = (BYTE)wc; #endif -#else /* ANSI/OEM input */ +#else /* ANSI/OEM input (without re-encode) */ pb->buf[i++] = (BYTE)c; - nc++; #endif if (i >= (int)(sizeof pb->buf) - 4) { /* Write buffered characters to the file */ @@ -6473,7 +6452,7 @@ void putc_bfd ( /* Buffered write with code conversion */ i = (n == (UINT)i) ? 0 : -1; } pb->idx = i; - pb->nchr = nc; + pb->nchr = nc + 1; } @@ -6666,7 +6645,7 @@ FRESULT f_setcp ( ) { static const WORD validcp[] = { 437, 720, 737, 771, 775, 850, 852, 857, 860, 861, 862, 863, 864, 865, 866, 869, 932, 936, 949, 950, 0}; - static const BYTE *const tables[] = {Ct437, Ct720, Ct737, Ct771, Ct775, Ct850, Ct852, Ct857, Ct860, Ct861, Ct862, Ct863, Ct864, Ct865, Ct866, Ct869, Dc932, Dc936, Dc949, Dc950, 0}; + static const BYTE* const tables[] = {Ct437, Ct720, Ct737, Ct771, Ct775, Ct850, Ct852, Ct857, Ct860, Ct861, Ct862, Ct863, Ct864, Ct865, Ct866, Ct869, Dc932, Dc936, Dc949, Dc950, 0}; UINT i; diff --git a/ipl/ff.h b/ipl/ff.h index da57ca8..cd90d6d 100755 --- a/ipl/ff.h +++ b/ipl/ff.h @@ -1,8 +1,8 @@ /*----------------------------------------------------------------------------/ -/ FatFs - Generic FAT Filesystem module R0.13a / +/ FatFs - Generic FAT Filesystem module R0.13b / /-----------------------------------------------------------------------------/ / -/ Copyright (C) 2017, ChaN, all right reserved. +/ Copyright (C) 2018, ChaN, all right reserved. / / FatFs module is an open source software. Redistribution and use of FatFs in / source and binary forms, with or without modification, are permitted provided @@ -20,7 +20,7 @@ #ifndef FF_DEFINED -#define FF_DEFINED 89352 /* Revision ID */ +#define FF_DEFINED 63463 /* Revision ID */ #ifdef __cplusplus extern "C" { @@ -45,6 +45,12 @@ typedef struct { extern PARTITION VolToPart[]; /* Volume - Partition resolution table */ #endif +#if FF_STR_VOLUME_ID +#ifndef FF_VOLUME_STRS +extern const char* VolumeStr[FF_VOLUMES]; /* User defied volume ID */ +#endif +#endif + /* Type of path name strings on FatFs API */ @@ -60,7 +66,11 @@ typedef WCHAR TCHAR; typedef char TCHAR; #define _T(x) u8 ## x #define _TEXT(x) u8 ## x -#elif FF_USE_LFN && (FF_LFN_UNICODE < 0 || FF_LFN_UNICODE > 2) +#elif FF_USE_LFN && FF_LFN_UNICODE == 3 /* Unicode in UTF-32 encoding */ +typedef DWORD TCHAR; +#define _T(x) U ## x +#define _TEXT(x) U ## x +#elif FF_USE_LFN && (FF_LFN_UNICODE < 0 || FF_LFN_UNICODE > 3) #error Wrong FF_LFN_UNICODE setting #else /* ANSI/OEM code in SBCS/DBCS */ typedef char TCHAR; diff --git a/ipl/ffconf.h b/ipl/ffconf.h index c5511ae..8f56632 100755 --- a/ipl/ffconf.h +++ b/ipl/ffconf.h @@ -2,7 +2,7 @@ / FatFs - Configuration file /---------------------------------------------------------------------------*/ -#define FFCONF_DEF 89352 /* Revision ID */ +#define FFCONF_DEF 63463 /* Revision ID */ /*---------------------------------------------------------------------------/ / Function Configurations @@ -123,6 +123,7 @@ / 0: ANSI/OEM in current CP (TCHAR = char) / 1: Unicode in UTF-16 (TCHAR = WCHAR) / 2: Unicode in UTF-8 (TCHAR = char) +/ 3: Unicode in UTF-32 (TCHAR = DWORD) / / Also behavior of string I/O functions will be affected by this option. / When LFN is not enabled, this option has no effect. */ @@ -168,11 +169,16 @@ #define FF_STR_VOLUME_ID 0 #define FF_VOLUME_STRS "sd" -/* FF_STR_VOLUME_ID switches string support for volume ID. -/ When FF_STR_VOLUME_ID is set to 1, also pre-defined strings can be used as drive -/ number in the path name. FF_VOLUME_STRS defines the drive ID strings for each -/ logical drives. Number of items must be equal to FF_VOLUMES. Valid characters for -/ the drive ID strings are: A-Z and 0-9. */ +/* FF_STR_VOLUME_ID switches support for volume ID in arbitrary strings. +/ When FF_STR_VOLUME_ID is set to 1 or 2, arbitrary strings can be used as drive +/ number in the path name. FF_VOLUME_STRS defines the volume ID strings for each +/ logical drives. Number of items must not be less than FF_VOLUMES. Valid +/ characters for the volume ID strings are A-Z, a-z and 0-9, however, they are +/ compared in case-insensitive. If FF_STR_VOLUME_ID >= 1 and FF_VOLUME_STRS is +/ not defined, a user defined volume string table needs to be defined as: +/ +/ const char* VolumeStr[FF_VOLUMES] = {"ram","flash","sd","usb",... +*/ #define FF_MULTI_PARTITION 0 @@ -226,7 +232,7 @@ #define FF_FS_EXFAT 1 /* This option switches support for exFAT filesystem. (0:Disable or 1:Enable) -/ When enable exFAT, also LFN needs to be enabled. +/ To enable exFAT, also LFN needs to be enabled. / Note that enabling exFAT discards ANSI C (C89) compatibility. */ @@ -234,9 +240,9 @@ #define FF_NORTC_MON 1 #define FF_NORTC_MDAY 1 #define FF_NORTC_YEAR 2018 -/* The option FF_FS_NORTC switches timestamp functiton. If the system does not have +/* The option FF_FS_NORTC switches timestamp function. If the system does not have / any RTC function or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable -/ the timestamp function. All objects modified by FatFs will have a fixed timestamp +/ the timestamp function. Every object modified by FatFs will have a fixed timestamp / defined by FF_NORTC_MON, FF_NORTC_MDAY and FF_NORTC_YEAR in local time. / To enable timestamp function (FF_FS_NORTC = 0), get_fattime() function need to be / added to the project to read current time form real-time clock. FF_NORTC_MON, diff --git a/ipl/ffsystem.c b/ipl/ffsystem.c new file mode 100644 index 0000000..36a61ca --- /dev/null +++ b/ipl/ffsystem.c @@ -0,0 +1,39 @@ +/*------------------------------------------------------------------------*/ +/* Sample Code of OS Dependent Functions for FatFs */ +/* (C) ChaN, 2017 */ +/* (C) CTCaer, 2018 */ +/*------------------------------------------------------------------------*/ + + +#include "ff.h" +#include "heap.h" + + + +#if FF_USE_LFN == 3 /* Dynamic memory allocation */ + +/*------------------------------------------------------------------------*/ +/* Allocate a memory block */ +/*------------------------------------------------------------------------*/ + +void* ff_memalloc ( /* Returns pointer to the allocated memory block (null on not enough core) */ + UINT msize /* Number of bytes to allocate */ +) +{ + return malloc(msize); /* Allocate a new memory block with POSIX API */ +} + + +/*------------------------------------------------------------------------*/ +/* Free a memory block */ +/*------------------------------------------------------------------------*/ + +void ff_memfree ( + void* mblock /* Pointer to the memory block to free (nothing to do for null) */ +) +{ + free(mblock); /* Free the memory block with POSIX API */ +} + +#endif + diff --git a/ipl/ffunicode.c b/ipl/ffunicode.c index e1f68a9..a57b4aa 100755 --- a/ipl/ffunicode.c +++ b/ipl/ffunicode.c @@ -27,7 +27,7 @@ #if FF_USE_LFN /* This module is blanked when non-LFN configuration */ -#if FF_DEFINED != 89352 /* Revision ID */ +#if FF_DEFINED != 63463 /* Revision ID */ #error Wrong include file (ff.h). #endif @@ -40,8 +40,7 @@ /*------------------------------------------------------------------------*/ #if FF_CODE_PAGE == 437 || FF_CODE_PAGE == 0 -static -const WCHAR uc437[] = { /* CP437(U.S.) to Unicode conversion table */ +static const WCHAR uc437[] = { /* CP437(U.S.) to Unicode conversion table */ 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192, 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, @@ -53,8 +52,7 @@ const WCHAR uc437[] = { /* CP437(U.S.) to Unicode conversion table */ }; #endif #if FF_CODE_PAGE == 720 || FF_CODE_PAGE == 0 -static -const WCHAR uc720[] = { /* CP720(Arabic) to Unicode conversion table */ +static const WCHAR uc720[] = { /* CP720(Arabic) to Unicode conversion table */ 0x0000, 0x0000, 0x00E9, 0x00E2, 0x0000, 0x00E0, 0x0000, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0000, 0x0000, 0x0000, 0x0000, 0x0651, 0x0652, 0x00F4, 0x00A4, 0x0640, 0x00FB, 0x00F9, 0x0621, 0x0622, 0x0623, 0x0624, 0x00A3, 0x0625, 0x0626, 0x0627, 0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F, 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x00AB, 0x00BB, @@ -66,8 +64,7 @@ const WCHAR uc720[] = { /* CP720(Arabic) to Unicode conversion table */ }; #endif #if FF_CODE_PAGE == 737 || FF_CODE_PAGE == 0 -static -const WCHAR uc737[] = { /* CP737(Greek) to Unicode conversion table */ +static const WCHAR uc737[] = { /* CP737(Greek) to Unicode conversion table */ 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, 0x03A0, 0x03A1, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0, 0x03C1, 0x03C3, 0x03C2, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8, @@ -79,8 +76,7 @@ const WCHAR uc737[] = { /* CP737(Greek) to Unicode conversion table */ }; #endif #if FF_CODE_PAGE == 771 || FF_CODE_PAGE == 0 -static -const WCHAR uc771[] = { /* CP771(KBL) to Unicode conversion table */ +static const WCHAR uc771[] = { /* CP771(KBL) to Unicode conversion table */ 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F, 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, @@ -92,8 +88,7 @@ const WCHAR uc771[] = { /* CP771(KBL) to Unicode conversion table */ }; #endif #if FF_CODE_PAGE == 775 || FF_CODE_PAGE == 0 -static -const WCHAR uc775[] = { /* CP775(Baltic) to Unicode conversion table */ +static const WCHAR uc775[] = { /* CP775(Baltic) to Unicode conversion table */ 0x0106, 0x00FC, 0x00E9, 0x0101, 0x00E4, 0x0123, 0x00E5, 0x0107, 0x0142, 0x0113, 0x0156, 0x0157, 0x012B, 0x0179, 0x00C4, 0x00C5, 0x00C9, 0x00E6, 0x00C6, 0x014D, 0x00F6, 0x0122, 0x00A2, 0x015A, 0x015B, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x00A4, 0x0100, 0x012A, 0x00F3, 0x017B, 0x017C, 0x017A, 0x201D, 0x00A6, 0x00A9, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x0141, 0x00AB, 0x00BB, @@ -105,8 +100,7 @@ const WCHAR uc775[] = { /* CP775(Baltic) to Unicode conversion table */ }; #endif #if FF_CODE_PAGE == 850 || FF_CODE_PAGE == 0 -static -const WCHAR uc850[] = { /* CP850(Latin 1) to Unicode conversion table */ +static const WCHAR uc850[] = { /* CP850(Latin 1) to Unicode conversion table */ 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x0192, 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, @@ -118,8 +112,7 @@ const WCHAR uc850[] = { /* CP850(Latin 1) to Unicode conversion table */ }; #endif #if FF_CODE_PAGE == 852 || FF_CODE_PAGE == 0 -static -const WCHAR uc852[] = { /* CP852(Latin 2) to Unicode conversion table */ +static const WCHAR uc852[] = { /* CP852(Latin 2) to Unicode conversion table */ 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x016F, 0x0107, 0x00E7, 0x0142, 0x00EB, 0x0150, 0x0151, 0x00EE, 0x0179, 0x00C4, 0x0106, 0x00C9, 0x0139, 0x013A, 0x00F4, 0x00F6, 0x013D, 0x013E, 0x015A, 0x015B, 0x00D6, 0x00DC, 0x0164, 0x0165, 0x0141, 0x00D7, 0x010D, 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x0104, 0x0105, 0x017D, 0x017E, 0x0118, 0x0119, 0x00AC, 0x017A, 0x010C, 0x015F, 0x00AB, 0x00BB, @@ -131,8 +124,7 @@ const WCHAR uc852[] = { /* CP852(Latin 2) to Unicode conversion table */ }; #endif #if FF_CODE_PAGE == 855 || FF_CODE_PAGE == 0 -static -const WCHAR uc855[] = { /* CP855(Cyrillic) to Unicode conversion table */ +static const WCHAR uc855[] = { /* CP855(Cyrillic) to Unicode conversion table */ 0x0452, 0x0402, 0x0453, 0x0403, 0x0451, 0x0401, 0x0454, 0x0404, 0x0455, 0x0405, 0x0456, 0x0406, 0x0457, 0x0407, 0x0458, 0x0408, 0x0459, 0x0409, 0x045A, 0x040A, 0x045B, 0x040B, 0x045C, 0x040C, 0x045E, 0x040E, 0x045F, 0x040F, 0x044E, 0x042E, 0x044A, 0x042A, 0x0430, 0x0410, 0x0431, 0x0411, 0x0446, 0x0426, 0x0434, 0x0414, 0x0435, 0x0415, 0x0444, 0x0424, 0x0433, 0x0413, 0x00AB, 0x00BB, @@ -144,8 +136,7 @@ const WCHAR uc855[] = { /* CP855(Cyrillic) to Unicode conversion table */ }; #endif #if FF_CODE_PAGE == 857 || FF_CODE_PAGE == 0 -static -const WCHAR uc857[] = { /* CP857(Turkish) to Unicode conversion table */ +static const WCHAR uc857[] = { /* CP857(Turkish) to Unicode conversion table */ 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0131, 0x00C4, 0x00C5, 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x0130, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x015E, 0x015F, 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x011E, 0x011F, 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, @@ -157,8 +148,7 @@ const WCHAR uc857[] = { /* CP857(Turkish) to Unicode conversion table */ }; #endif #if FF_CODE_PAGE == 860 || FF_CODE_PAGE == 0 -static -const WCHAR uc860[] = { /* CP860(Portuguese) to Unicode conversion table */ +static const WCHAR uc860[] = { /* CP860(Portuguese) to Unicode conversion table */ 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E3, 0x00E0, 0x00C1, 0x00E7, 0x00EA, 0x00CA, 0x00E8, 0x00CD, 0x00D4, 0x00EC, 0x00C3, 0x00C2, 0x00C9, 0x00C0, 0x00C8, 0x00F4, 0x00F5, 0x00F2, 0x00DA, 0x00F9, 0x00CC, 0x00D5, 0x00DC, 0x00A2, 0x00A3, 0x00D9, 0x20A7, 0x00D3, 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x00D2, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, @@ -170,8 +160,7 @@ const WCHAR uc860[] = { /* CP860(Portuguese) to Unicode conversion table */ }; #endif #if FF_CODE_PAGE == 861 || FF_CODE_PAGE == 0 -static -const WCHAR uc861[] = { /* CP861(Icelandic) to Unicode conversion table */ +static const WCHAR uc861[] = { /* CP861(Icelandic) to Unicode conversion table */ 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E6, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00D0, 0x00F0, 0x00DE, 0x00C4, 0x00C5, 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00FE, 0x00FB, 0x00DD, 0x00FD, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x20A7, 0x0192, 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00C1, 0x00CD, 0x00D3, 0x00DA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, @@ -183,8 +172,7 @@ const WCHAR uc861[] = { /* CP861(Icelandic) to Unicode conversion table */ }; #endif #if FF_CODE_PAGE == 862 || FF_CODE_PAGE == 0 -static -const WCHAR uc862[] = { /* CP862(Hebrew) to Unicode conversion table */ +static const WCHAR uc862[] = { /* CP862(Hebrew) to Unicode conversion table */ 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF, 0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7, 0x05E8, 0x05E9, 0x05EA, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192, 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, @@ -196,8 +184,7 @@ const WCHAR uc862[] = { /* CP862(Hebrew) to Unicode conversion table */ }; #endif #if FF_CODE_PAGE == 863 || FF_CODE_PAGE == 0 -static -const WCHAR uc863[] = { /* CP863(Canadian French) to Unicode conversion table */ +static const WCHAR uc863[] = { /* CP863(Canadian French) to Unicode conversion table */ 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00C2, 0x00E0, 0x00B6, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x2017, 0x00C0, 0x00C9, 0x00C8, 0x00CA, 0x00F4, 0x00CB, 0x00CF, 0x00FB, 0x00F9, 0x00A4, 0x00D4, 0x00DC, 0x00A2, 0x00A3, 0x00D9, 0x00DB, 0x0192, 0x00A6, 0x00B4, 0x00F3, 0x00FA, 0x00A8, 0x00BB, 0x00B3, 0x00AF, 0x00CE, 0x3210, 0x00AC, 0x00BD, 0x00BC, 0x00BE, 0x00AB, 0x00BB, @@ -209,8 +196,7 @@ const WCHAR uc863[] = { /* CP863(Canadian French) to Unicode conversion table * }; #endif #if FF_CODE_PAGE == 864 || FF_CODE_PAGE == 0 -static -const WCHAR uc864[] = { /* CP864(Arabic) to Unicode conversion table */ +static const WCHAR uc864[] = { /* CP864(Arabic) to Unicode conversion table */ 0x00B0, 0x00B7, 0x2219, 0x221A, 0x2592, 0x2500, 0x2502, 0x253C, 0x2524, 0x252C, 0x251C, 0x2534, 0x2510, 0x250C, 0x2514, 0x2518, 0x03B2, 0x221E, 0x03C6, 0x00B1, 0x00BD, 0x00BC, 0x2248, 0x00AB, 0x00BB, 0xFEF7, 0xFEF8, 0x0000, 0x0000, 0xFEFB, 0xFEFC, 0x0000, 0x00A0, 0x00AD, 0xFE82, 0x00A3, 0x00A4, 0xFE84, 0x0000, 0x20AC, 0xFE8E, 0xFE8F, 0xFE95, 0xFE99, 0x060C, 0xFE9D, 0xFEA1, 0xFEA5, @@ -222,8 +208,7 @@ const WCHAR uc864[] = { /* CP864(Arabic) to Unicode conversion table */ }; #endif #if FF_CODE_PAGE == 865 || FF_CODE_PAGE == 0 -static -const WCHAR uc865[] = { /* CP865(Nordic) to Unicode conversion table */ +static const WCHAR uc865[] = { /* CP865(Nordic) to Unicode conversion table */ 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, 0x00C5, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x20A7, 0x0192, 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00A4, @@ -235,8 +220,7 @@ const WCHAR uc865[] = { /* CP865(Nordic) to Unicode conversion table */ }; #endif #if FF_CODE_PAGE == 866 || FF_CODE_PAGE == 0 -static -const WCHAR uc866[] = { /* CP866(Russian) to Unicode conversion table */ +static const WCHAR uc866[] = { /* CP866(Russian) to Unicode conversion table */ 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F, 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, @@ -248,8 +232,7 @@ const WCHAR uc866[] = { /* CP866(Russian) to Unicode conversion table */ }; #endif #if FF_CODE_PAGE == 869 || FF_CODE_PAGE == 0 -static -const WCHAR uc869[] = { /* CP869(Greek 2) to Unicode conversion table */ +static const WCHAR uc869[] = { /* CP869(Greek 2) to Unicode conversion table */ 0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x0386, 0x00B7, 0x00B7, 0x00AC, 0x00A6, 0x2018, 0x2019, 0x0388, 0x2015, 0x0389, 0x038A, 0x03AA, 0x038C, 0x00B7, 0x00B7, 0x038E, 0x03AB, 0x00A9, 0x038F, 0x00B2, 0x00B3, 0x03AC, 0x00A3, 0x03AD, 0x03AE, 0x03AF, 0x03CA, 0x0390, 0x03CC, 0x03CD, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x00BD, 0x0398, 0x0399, 0x00AB, 0x00BB, @@ -283,7 +266,7 @@ WCHAR ff_uni2oem ( /* Returns OEM code character, zero on error */ c = (WCHAR)uni; } else { /* Non-ASCII */ - if (uni < 0x10000 && cp == FF_CODE_PAGE) { /* Is it a valid code? */ + if (uni < 0x10000 && cp == FF_CODE_PAGE) { /* Is it in BMP and valid code page? */ for (c = 0; c < 0x80 && uni != p[c]; c++) ; c = (c + 0x80) & 0xFF; } @@ -330,30 +313,28 @@ WCHAR ff_uni2oem ( /* Returns OEM code character, zero on error */ { const WCHAR *p; WCHAR c = 0, uc; - UINT i, n, li, hi; + UINT i = 0, n, li, hi; if (uni < 0x80) { /* ASCII? */ c = (WCHAR)uni; } else { /* Non-ASCII */ - if (uni < 0x10000) { /* Is it in BMP? */ - if (cp == FF_CODE_PAGE) { /* Is it a valid code? */ - uc = (WCHAR)uni; - p = CVTBL(uni2oem, FF_CODE_PAGE); - hi = sizeof CVTBL(uni2oem, FF_CODE_PAGE) / 4 - 1; - li = 0; - for (n = 16; n; n--) { - i = li + (hi - li) / 2; - if (uc == p[i * 2]) break; - if (uc > p[i * 2]) { - li = i; - } else { - hi = i; - } + if (uni < 0x10000 && cp == FF_CODE_PAGE) { /* Is it in BMP and valid code page? */ + uc = (WCHAR)uni; + p = CVTBL(uni2oem, FF_CODE_PAGE); + hi = sizeof CVTBL(uni2oem, FF_CODE_PAGE) / 4 - 1; + li = 0; + for (n = 16; n; n--) { + i = li + (hi - li) / 2; + if (uc == p[i * 2]) break; + if (uc > p[i * 2]) { + li = i; + } else { + hi = i; } - if (n != 0) c = p[i * 2 + 1]; } + if (n != 0) c = p[i * 2 + 1]; } } @@ -368,14 +349,14 @@ WCHAR ff_oem2uni ( /* Returns Unicode character, zero on error */ { const WCHAR *p; WCHAR c = 0; - UINT i, n, li, hi; + UINT i = 0, n, li, hi; if (oem < 0x80) { /* ASCII? */ c = oem; } else { /* Extended char */ - if (cp == FF_CODE_PAGE) { /* Is it a valid code page? */ + if (cp == FF_CODE_PAGE) { /* Is it valid code page? */ p = CVTBL(oem2uni, FF_CODE_PAGE); hi = sizeof CVTBL(oem2uni, FF_CODE_PAGE) / 4 - 1; li = 0; @@ -405,7 +386,7 @@ WCHAR ff_oem2uni ( /* Returns Unicode character, zero on error */ #if FF_CODE_PAGE == 0 static const WORD cp_code[] = { 437, 720, 737, 771, 775, 850, 852, 855, 857, 860, 861, 862, 863, 864, 865, 866, 869, 0}; -static const WCHAR *const cp_table[] = {uc437, uc720, uc737, uc771, uc775, uc850, uc852, uc855, uc857, uc860, uc861, uc862, uc863, uc864, uc865, uc866, uc869, 0}; +static const WCHAR* const cp_table[] = {uc437, uc720, uc737, uc771, uc775, uc850, uc852, uc855, uc857, uc860, uc861, uc862, uc863, uc864, uc865, uc866, uc869, 0}; WCHAR ff_uni2oem ( /* Returns OEM code character, zero on error */ @@ -426,20 +407,20 @@ WCHAR ff_uni2oem ( /* Returns OEM code character, zero on error */ uc = (WCHAR)uni; p = 0; if (cp < 900) { /* SBCS */ - for (i = 0; cp_code[i] != 0 && cp_code[i] != cp; i++) ; /* Get table */ + for (i = 0; cp_code[i] != 0 && cp_code[i] != cp; i++) ; /* Get conversion table */ p = cp_table[i]; - if (p) { /* Is it a valid CP ? */ + if (p) { /* Is it valid code page ? */ for (c = 0; c < 0x80 && uc != p[c]; c++) ; /* Find OEM code in the table */ c = (c + 0x80) & 0xFF; } } else { /* DBCS */ - switch (cp) { + switch (cp) { /* Get conversion table */ case 932 : p = uni2oem932; hi = sizeof uni2oem932 / 4 - 1; break; case 936 : p = uni2oem936; hi = sizeof uni2oem936 / 4 - 1; break; case 949 : p = uni2oem949; hi = sizeof uni2oem949 / 4 - 1; break; case 950 : p = uni2oem950; hi = sizeof uni2oem950 / 4 - 1; break; } - if (p) { /* Is it a valid code page? */ + if (p) { /* Is it valid code page? */ li = 0; for (n = 16; n; n--) { /* Find OEM code */ i = li + (hi - li) / 2; @@ -518,50 +499,90 @@ DWORD ff_wtoupper ( /* Returns up-converted code point */ DWORD uni /* Unicode code point to be up-converted */ ) { - /* Compressed upper conversion table */ - static const WORD cvt1[] = { /* U+0000 - U+0FFF */ + const WORD *p; + WORD uc, bc, nc, cmd; + static const WORD cvt1[] = { /* Compressed up conversion table for U+0000 - U+0FFF */ /* Basic Latin */ 0x0061,0x031A, /* Latin-1 Supplement */ - 0x00E0,0x0317, 0x00F8,0x0307, 0x00FF,0x0001,0x0178, + 0x00E0,0x0317, + 0x00F8,0x0307, + 0x00FF,0x0001,0x0178, /* Latin Extended-A */ - 0x0100,0x0130, 0x0132,0x0106, 0x0139,0x0110, 0x014A,0x012E, 0x0179,0x0106, + 0x0100,0x0130, + 0x0132,0x0106, + 0x0139,0x0110, + 0x014A,0x012E, + 0x0179,0x0106, /* Latin Extended-B */ 0x0180,0x004D,0x0243,0x0181,0x0182,0x0182,0x0184,0x0184,0x0186,0x0187,0x0187,0x0189,0x018A,0x018B,0x018B,0x018D,0x018E,0x018F,0x0190,0x0191,0x0191,0x0193,0x0194,0x01F6,0x0196,0x0197,0x0198,0x0198,0x023D,0x019B,0x019C,0x019D,0x0220,0x019F,0x01A0,0x01A0,0x01A2,0x01A2,0x01A4,0x01A4,0x01A6,0x01A7,0x01A7,0x01A9,0x01AA,0x01AB,0x01AC,0x01AC,0x01AE,0x01AF,0x01AF,0x01B1,0x01B2,0x01B3,0x01B3,0x01B5,0x01B5,0x01B7,0x01B8,0x01B8,0x01BA,0x01BB,0x01BC,0x01BC,0x01BE,0x01F7,0x01C0,0x01C1,0x01C2,0x01C3,0x01C4,0x01C5,0x01C4,0x01C7,0x01C8,0x01C7,0x01CA,0x01CB,0x01CA, - 0x01CD,0x0110, 0x01DD,0x0001,0x018E, 0x01DE,0x0112, 0x01F3,0x0003,0x01F1,0x01F4,0x01F4, 0x01F8,0x0128, - 0x0222,0x0112, 0x023A,0x0009,0x2C65,0x023B,0x023B,0x023D,0x2C66,0x023F,0x0240,0x0241,0x0241, 0x0246,0x010A, + 0x01CD,0x0110, + 0x01DD,0x0001,0x018E, + 0x01DE,0x0112, + 0x01F3,0x0003,0x01F1,0x01F4,0x01F4, + 0x01F8,0x0128, + 0x0222,0x0112, + 0x023A,0x0009,0x2C65,0x023B,0x023B,0x023D,0x2C66,0x023F,0x0240,0x0241,0x0241, + 0x0246,0x010A, /* IPA Extensions */ 0x0253,0x0040,0x0181,0x0186,0x0255,0x0189,0x018A,0x0258,0x018F,0x025A,0x0190,0x025C,0x025D,0x025E,0x025F,0x0193,0x0261,0x0262,0x0194,0x0264,0x0265,0x0266,0x0267,0x0197,0x0196,0x026A,0x2C62,0x026C,0x026D,0x026E,0x019C,0x0270,0x0271,0x019D,0x0273,0x0274,0x019F,0x0276,0x0277,0x0278,0x0279,0x027A,0x027B,0x027C,0x2C64,0x027E,0x027F,0x01A6,0x0281,0x0282,0x01A9,0x0284,0x0285,0x0286,0x0287,0x01AE,0x0244,0x01B1,0x01B2,0x0245,0x028D,0x028E,0x028F,0x0290,0x0291,0x01B7, /* Greek, Coptic */ - 0x037B,0x0003,0x03FD,0x03FE,0x03FF, 0x03AC,0x0004,0x0386,0x0388,0x0389,0x038A, 0x03B1,0x0311, - 0x03C2,0x0002,0x03A3,0x03A3, 0x03C4,0x0308, 0x03CC,0x0003,0x038C,0x038E,0x038F, 0x03D8,0x0118, + 0x037B,0x0003,0x03FD,0x03FE,0x03FF, + 0x03AC,0x0004,0x0386,0x0388,0x0389,0x038A, + 0x03B1,0x0311, + 0x03C2,0x0002,0x03A3,0x03A3, + 0x03C4,0x0308, + 0x03CC,0x0003,0x038C,0x038E,0x038F, + 0x03D8,0x0118, 0x03F2,0x000A,0x03F9,0x03F3,0x03F4,0x03F5,0x03F6,0x03F7,0x03F7,0x03F9,0x03FA,0x03FA, /* Cyrillic */ - 0x0430,0x0320, 0x0450,0x0710, 0x0460,0x0122, 0x048A,0x0136, 0x04C1,0x010E, 0x04CF,0x0001,0x04C0, 0x04D0,0x0144, + 0x0430,0x0320, + 0x0450,0x0710, + 0x0460,0x0122, + 0x048A,0x0136, + 0x04C1,0x010E, + 0x04CF,0x0001,0x04C0, + 0x04D0,0x0144, /* Armenian */ 0x0561,0x0426, - 0x0000 + 0x0000 /* EOT */ }; - static const WORD cvt2[] = { /* U+1000 - U+FFFF */ + static const WORD cvt2[] = { /* Compressed up conversion table for U+1000 - U+FFFF */ /* Phonetic Extensions */ 0x1D7D,0x0001,0x2C63, /* Latin Extended Additional */ - 0x1E00,0x0196, 0x1EA0,0x015A, + 0x1E00,0x0196, + 0x1EA0,0x015A, /* Greek Extended */ - 0x1F00,0x0608, 0x1F10,0x0606, 0x1F20,0x0608, 0x1F30,0x0608, 0x1F40,0x0606, - 0x1F51,0x0007,0x1F59,0x1F52,0x1F5B,0x1F54,0x1F5D,0x1F56,0x1F5F, 0x1F60,0x0608, + 0x1F00,0x0608, + 0x1F10,0x0606, + 0x1F20,0x0608, + 0x1F30,0x0608, + 0x1F40,0x0606, + 0x1F51,0x0007,0x1F59,0x1F52,0x1F5B,0x1F54,0x1F5D,0x1F56,0x1F5F, + 0x1F60,0x0608, 0x1F70,0x000E,0x1FBA,0x1FBB,0x1FC8,0x1FC9,0x1FCA,0x1FCB,0x1FDA,0x1FDB,0x1FF8,0x1FF9,0x1FEA,0x1FEB,0x1FFA,0x1FFB, - 0x1F80,0x0608, 0x1F90,0x0608, 0x1FA0,0x0608, 0x1FB0,0x0004,0x1FB8,0x1FB9,0x1FB2,0x1FBC, - 0x1FCC,0x0001,0x1FC3, 0x1FD0,0x0602, 0x1FE0,0x0602, 0x1FE5,0x0001,0x1FEC, 0x1FF3,0x0001,0x1FFC, + 0x1F80,0x0608, + 0x1F90,0x0608, + 0x1FA0,0x0608, + 0x1FB0,0x0004,0x1FB8,0x1FB9,0x1FB2,0x1FBC, + 0x1FCC,0x0001,0x1FC3, + 0x1FD0,0x0602, + 0x1FE0,0x0602, + 0x1FE5,0x0001,0x1FEC, + 0x1FF3,0x0001,0x1FFC, /* Letterlike Symbols */ 0x214E,0x0001,0x2132, /* Number forms */ - 0x2170,0x0210, 0x2184,0x0001,0x2183, + 0x2170,0x0210, + 0x2184,0x0001,0x2183, /* Enclosed Alphanumerics */ - 0x24D0,0x051A, 0x2C30,0x042F, + 0x24D0,0x051A, + 0x2C30,0x042F, /* Latin Extended-C */ - 0x2C60,0x0102, 0x2C67,0x0106, 0x2C75,0x0102, + 0x2C60,0x0102, + 0x2C67,0x0106, 0x2C75,0x0102, /* Coptic */ 0x2C80,0x0164, /* Georgian Supplement */ @@ -569,18 +590,16 @@ DWORD ff_wtoupper ( /* Returns up-converted code point */ /* Full-width */ 0xFF41,0x031A, - 0x0000 + 0x0000 /* EOT */ }; - const WORD *p; - WORD uc, bc, nc, cmd; if (uni < 0x10000) { /* Is it in BMP? */ uc = (WORD)uni; p = uc < 0x1000 ? cvt1 : cvt2; for (;;) { - bc = *p++; /* Get block base */ - if (!bc || uc < bc) break; + bc = *p++; /* Get the block base */ + if (bc == 0 || uc < bc) break; /* Not matched? */ nc = *p++; cmd = nc >> 8; nc &= 0xFF; /* Get processing command and block size */ if (uc < bc + nc) { /* In the block? */ switch (cmd) { @@ -596,7 +615,7 @@ DWORD ff_wtoupper ( /* Returns up-converted code point */ } break; } - if (!cmd) p += nc; + if (cmd == 0) p += nc; /* Skip table if needed */ } uni = uc; }