| 
						
						
							
								
							
						
						
					 | 
					 | 
					@ -24,7 +24,7 @@ uint16_t next_clu(const FAT16* fat, uint16_t cluster); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					uint32_t clu_offs(const FAT16* fat, uint16_t cluster, uint32_t addr); | 
					 | 
					 | 
					 | 
					uint32_t clu_offs(const FAT16* fat, uint16_t cluster, uint32_t addr); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					/** Read a file entry from directory (dir starting cluster, entry number) */ | 
					 | 
					 | 
					 | 
					/** Read a file entry from directory (dir starting cluster, entry number) */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					void open_file(const FAT16* fat, FAT16_FILE* file, const uint16_t dir_cluster, const uint16_t num); | 
					 | 
					 | 
					 | 
					void open_file(const FAT16* fat, FFILE* file, const uint16_t dir_cluster, const uint16_t num); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					/** Allocate and chain new cluster to a chain starting at given cluster */ | 
					 | 
					 | 
					 | 
					/** Allocate and chain new cluster to a chain starting at given cluster */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					bool append_cluster(const FAT16* fat, const uint16_t clu); | 
					 | 
					 | 
					 | 
					bool append_cluster(const FAT16* fat, const uint16_t clu); | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -42,7 +42,7 @@ bool free_cluster_chain(const FAT16* fat, uint16_t clu); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 * Check if there is already a file of given RAW name | 
					 | 
					 | 
					 | 
					 * Check if there is already a file of given RAW name | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 * Raw name - name as found on disk, not "display name". | 
					 | 
					 | 
					 | 
					 * Raw name - name as found on disk, not "display name". | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 */ | 
					 | 
					 | 
					 | 
					 */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					bool dir_find_file_raw(FAT16_FILE* dir, const char* fname); | 
					 | 
					 | 
					 | 
					bool dir_find_file_raw(FFILE* dir, const char* fname); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					/** Write a value into FAT */ | 
					 | 
					 | 
					 | 
					/** Write a value into FAT */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					void write_fat(const FAT16* fat, const uint16_t cluster, const uint16_t value); | 
					 | 
					 | 
					 | 
					void write_fat(const FAT16* fat, const uint16_t cluster, const uint16_t value); | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -103,7 +103,10 @@ uint32_t find_bs(const BLOCKDEV* dev) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								// Verify that the boot sector has a valid signature mark
 | 
					 | 
					 | 
					 | 
								// Verify that the boot sector has a valid signature mark
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								dev->seek(tmp + 510); | 
					 | 
					 | 
					 | 
								dev->seek(tmp + 510); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								dev->load(&tmp2, 2); | 
					 | 
					 | 
					 | 
								dev->load(&tmp2, 2); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								if (tmp2 != 0xAA55) continue; // continue to next entry
 | 
					 | 
					 | 
					 | 
								if (tmp2 != 0xAA55) | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
									continue; // continue to next entry
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								// return absolute MBR address
 | 
					 | 
					 | 
					 | 
								// return absolute MBR address
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								return tmp; | 
					 | 
					 | 
					 | 
								return tmp; | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -273,10 +276,10 @@ bool free_cluster_chain(const FAT16* fat, uint16_t clu) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 * Check if there is already a file of given RAW name | 
					 | 
					 | 
					 | 
					 * Check if there is already a file of given RAW name | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 * Raw name - name as found on disk, not "display name". | 
					 | 
					 | 
					 | 
					 * Raw name - name as found on disk, not "display name". | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 */ | 
					 | 
					 | 
					 | 
					 */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					bool dir_find_file_raw(FAT16_FILE* dir, const char* fname) | 
					 | 
					 | 
					 | 
					bool dir_find_file_raw(FFILE* dir, const char* fname) | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					{ | 
					 | 
					 | 
					 | 
					{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						// rewind
 | 
					 | 
					 | 
					 | 
						// rewind
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						fat16_first(dir); | 
					 | 
					 | 
					 | 
						ff_first(dir); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						do | 
					 | 
					 | 
					 | 
						do | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						{ | 
					 | 
					 | 
					 | 
						{ | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -296,7 +299,7 @@ bool dir_find_file_raw(FAT16_FILE* dir, const char* fname) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								return true; // file is already open.
 | 
					 | 
					 | 
					 | 
								return true; // file is already open.
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							} | 
					 | 
					 | 
					 | 
							} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						} | 
					 | 
					 | 
					 | 
						} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						while (fat16_next(dir)); | 
					 | 
					 | 
					 | 
						while (ff_next(dir)); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						return false; | 
					 | 
					 | 
					 | 
						return false; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -308,7 +311,7 @@ bool dir_find_file_raw(FAT16_FILE* dir, const char* fname) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 * dir_cluster ... directory start cluster | 
					 | 
					 | 
					 | 
					 * dir_cluster ... directory start cluster | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 * num ... entry number in the directory | 
					 | 
					 | 
					 | 
					 * num ... entry number in the directory | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 */ | 
					 | 
					 | 
					 | 
					 */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					void open_file(const FAT16* fat, FAT16_FILE* file, const uint16_t dir_cluster, const uint16_t num) | 
					 | 
					 | 
					 | 
					void open_file(const FAT16* fat, FFILE* file, const uint16_t dir_cluster, const uint16_t num) | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					{ | 
					 | 
					 | 
					 | 
					{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						// Resolve starting address
 | 
					 | 
					 | 
					 | 
						// Resolve starting address
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						uint32_t addr; | 
					 | 
					 | 
					 | 
						uint32_t addr; | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -394,7 +397,7 @@ void open_file(const FAT16* fat, FAT16_FILE* file, const uint16_t dir_cluster, c | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						} | 
					 | 
					 | 
					 | 
						} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						// Init cursors
 | 
					 | 
					 | 
					 | 
						// Init cursors
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						fat16_seek(file, 0); | 
					 | 
					 | 
					 | 
						ff_seek(file, 0); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -403,7 +406,7 @@ void open_file(const FAT16* fat, FAT16_FILE* file, const uint16_t dir_cluster, c | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 * Write information into a file header. | 
					 | 
					 | 
					 | 
					 * Write information into a file header. | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 * "file" is an open handle. | 
					 | 
					 | 
					 | 
					 * "file" is an open handle. | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 */ | 
					 | 
					 | 
					 | 
					 */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					void write_file_header(FAT16_FILE* file, const char* fname_raw, const uint8_t attribs, const uint16_t clu_start) | 
					 | 
					 | 
					 | 
					void write_file_header(FFILE* file, const char* fname_raw, const uint8_t attribs, const uint16_t clu_start) | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					{ | 
					 | 
					 | 
					 | 
					{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						const BLOCKDEV* dev = file->fat->dev; | 
					 | 
					 | 
					 | 
						const BLOCKDEV* dev = file->fat->dev; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -439,9 +442,12 @@ void write_file_header(FAT16_FILE* file, const char* fname_raw, const uint8_t at | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					// =============== PUBLIC FUNCTION IMPLEMENTATIONS =================
 | 
					 | 
					 | 
					 | 
					// =============== PUBLIC FUNCTION IMPLEMENTATIONS =================
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					/** Initialize a FAT16 handle */ | 
					 | 
					 | 
					 | 
					/** Initialize a FAT16 handle */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					void fat16_init(const BLOCKDEV* dev, FAT16* fat) | 
					 | 
					 | 
					 | 
					bool ff_init(const BLOCKDEV* dev, FAT16* fat) | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					{ | 
					 | 
					 | 
					 | 
					{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						const uint32_t bs_a = find_bs(dev); | 
					 | 
					 | 
					 | 
						const uint32_t bs_a = find_bs(dev); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						if (bs_a == 0) return false; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						fat->dev = dev; | 
					 | 
					 | 
					 | 
						fat->dev = dev; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						read_bs(dev, &(fat->bs), bs_a); | 
					 | 
					 | 
					 | 
						read_bs(dev, &(fat->bs), bs_a); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						fat->fat_addr = bs_a + (fat->bs.reserved_sectors * 512); | 
					 | 
					 | 
					 | 
						fat->fat_addr = bs_a + (fat->bs.reserved_sectors * 512); | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -449,6 +455,8 @@ void fat16_init(const BLOCKDEV* dev, FAT16* fat) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						fat->data_addr = fat->rd_addr + (fat->bs.root_entries * 32); // entry is 32B long
 | 
					 | 
					 | 
					 | 
						fat->data_addr = fat->rd_addr + (fat->bs.root_entries * 32); // entry is 32B long
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						fat->bs.bytes_per_cluster = (fat->bs.sectors_per_cluster * 512); | 
					 | 
					 | 
					 | 
						fat->bs.bytes_per_cluster = (fat->bs.sectors_per_cluster * 512); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						return true; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -456,7 +464,7 @@ void fat16_init(const BLOCKDEV* dev, FAT16* fat) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 * Move file cursor to a position relative to file start | 
					 | 
					 | 
					 | 
					 * Move file cursor to a position relative to file start | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 * Allows seek past end of file, will allocate new cluster if needed. | 
					 | 
					 | 
					 | 
					 * Allows seek past end of file, will allocate new cluster if needed. | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 */ | 
					 | 
					 | 
					 | 
					 */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					bool fat16_seek(FAT16_FILE* file, uint32_t addr) | 
					 | 
					 | 
					 | 
					bool ff_seek(FFILE* file, uint32_t addr) | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					{ | 
					 | 
					 | 
					 | 
					{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						const FAT16* fat = file->fat; | 
					 | 
					 | 
					 | 
						const FAT16* fat = file->fat; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -504,7 +512,7 @@ bool fat16_seek(FAT16_FILE* file, uint32_t addr) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 * Check if file is a regular file or directory entry. | 
					 | 
					 | 
					 | 
					 * Check if file is a regular file or directory entry. | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 * Those files can be shown to user. | 
					 | 
					 | 
					 | 
					 * Those files can be shown to user. | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 */ | 
					 | 
					 | 
					 | 
					 */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					bool fat16_is_regular(const FAT16_FILE* file) | 
					 | 
					 | 
					 | 
					bool ff_is_regular(const FFILE* file) | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					{ | 
					 | 
					 | 
					 | 
					{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						switch (file->type) | 
					 | 
					 | 
					 | 
						switch (file->type) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						{ | 
					 | 
					 | 
					 | 
						{ | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -522,13 +530,19 @@ bool fat16_is_regular(const FAT16_FILE* file) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#define MIN(a, b) (((a) < (b)) ? (a) : (b)) | 
					 | 
					 | 
					 | 
					#define MIN(a, b) (((a) < (b)) ? (a) : (b)) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					bool fat16_read(FAT16_FILE* file, void* target, uint32_t len) | 
					 | 
					 | 
					 | 
					uint16_t ff_read(FFILE* file, void* target, uint16_t len) | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					{ | 
					 | 
					 | 
					 | 
					{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						if (file->cur_abs == 0xFFFF) | 
					 | 
					 | 
					 | 
						if (file->cur_abs == 0xFFFF) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							return false; // file at the end already
 | 
					 | 
					 | 
					 | 
							return 0; // file at the end already
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						if (file->cur_rel + len > file->size) | 
					 | 
					 | 
					 | 
						if (file->cur_rel + len > file->size) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							return false; // Attempt to read more than what is available
 | 
					 | 
					 | 
					 | 
						{ | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							if (file->cur_rel > file->size) return 0; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							len = file->size - file->cur_rel; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							//return false; // Attempt to read more than what is available
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						const uint16_t len_orig = len; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						const FAT16* fat = file->fat; | 
					 | 
					 | 
					 | 
						const FAT16* fat = file->fat; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						const BLOCKDEV* dev = fat->dev; | 
					 | 
					 | 
					 | 
						const BLOCKDEV* dev = fat->dev; | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -562,18 +576,27 @@ bool fat16_read(FAT16_FILE* file, void* target, uint32_t len) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							len -= chunk; | 
					 | 
					 | 
					 | 
							len -= chunk; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						} | 
					 | 
					 | 
					 | 
						} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						return true; | 
					 | 
					 | 
					 | 
						return len_orig; | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					bool ff_write_str(FFILE* file, const char* source) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						uint16_t len = 0; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						for (; source[len] != 0; len++); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						return ff_write(file, source, len); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					bool fat16_write(FAT16_FILE* file, void* source, uint32_t len) | 
					 | 
					 | 
					 | 
					bool ff_write(FFILE* file, const void* source, uint32_t len) | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					{ | 
					 | 
					 | 
					 | 
					{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						const FAT16* fat = file->fat; | 
					 | 
					 | 
					 | 
						const FAT16* fat = file->fat; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						const BLOCKDEV* dev = fat->dev; | 
					 | 
					 | 
					 | 
						const BLOCKDEV* dev = fat->dev; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						if (file->cur_abs == 0xFFFF) | 
					 | 
					 | 
					 | 
						if (file->cur_abs == 0xFFFF) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							return false; // file at the end already
 | 
					 | 
					 | 
					 | 
							return false; // file past it's end (rare)
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						// Attempt to write past end of file
 | 
					 | 
					 | 
					 | 
						// Attempt to write past end of file
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						if (file->cur_rel + len >= file->size) | 
					 | 
					 | 
					 | 
						if (file->cur_rel + len >= file->size) | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -582,14 +605,14 @@ bool fat16_write(FAT16_FILE* file, void* source, uint32_t len) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							// Seek to the last position
 | 
					 | 
					 | 
					 | 
							// Seek to the last position
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							// -> fseek will allocate clusters
 | 
					 | 
					 | 
					 | 
							// -> fseek will allocate clusters
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							if (!fat16_seek(file, pos_start + len)) | 
					 | 
					 | 
					 | 
							if (!ff_seek(file, pos_start + len)) | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								return false; // error in seek
 | 
					 | 
					 | 
					 | 
								return false; // error in seek
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							// Write starts beyond EOF - creating a zero-filled "hole"
 | 
					 | 
					 | 
					 | 
							// Write starts beyond EOF - creating a zero-filled "hole"
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							if (file->cur_rel > file->size) | 
					 | 
					 | 
					 | 
							if (pos_start > file->size + 1) | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							{ | 
					 | 
					 | 
					 | 
							{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								// Seek to the end of valid data
 | 
					 | 
					 | 
					 | 
								// Seek to the end of valid data
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								fat16_seek(file, file->size); | 
					 | 
					 | 
					 | 
								ff_seek(file, file->size); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								// fill space between EOF and start-of-write with zeros
 | 
					 | 
					 | 
					 | 
								// fill space between EOF and start-of-write with zeros
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								uint32_t fill = pos_start - file->size; | 
					 | 
					 | 
					 | 
								uint32_t fill = pos_start - file->size; | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -617,31 +640,44 @@ bool fat16_write(FAT16_FILE* file, void* source, uint32_t len) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								} | 
					 | 
					 | 
					 | 
								} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							} | 
					 | 
					 | 
					 | 
							} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							// Save new size
 | 
					 | 
					 | 
					 | 
							// Store new size
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							fat16_resize(file, pos_start + len); | 
					 | 
					 | 
					 | 
							file->size = pos_start + len; | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							// Seek back to where it was before
 | 
					 | 
					 | 
					 | 
							// Seek back to where it was before
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							fat16_seek(file, pos_start); | 
					 | 
					 | 
					 | 
							ff_seek(file, pos_start); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						} // (end zerofill)
 | 
					 | 
					 | 
					 | 
						} // (end zerofill)
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						// write the data
 | 
					 | 
					 | 
					 | 
						// write the data
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						while (len > 0) | 
					 | 
					 | 
					 | 
						while (len > 0) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						{ | 
					 | 
					 | 
					 | 
						{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							// How much can be stored in this cluster
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							const uint16_t chunk = MIN(fat->bs.bytes_per_cluster - file->cur_ofs, len); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							// store the chunk
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							dev->seek(file->cur_abs); | 
					 | 
					 | 
					 | 
							dev->seek(file->cur_abs); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							dev->store(source, chunk); | 
					 | 
					 | 
					 | 
							uint16_t chunk; | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							// advance cursors
 | 
					 | 
					 | 
					 | 
							if (len == 1) | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							file->cur_abs += chunk; | 
					 | 
					 | 
					 | 
							{ | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							file->cur_rel += chunk; | 
					 | 
					 | 
					 | 
								dev->write(*((uint8_t*)source)); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							file->cur_ofs += chunk; | 
					 | 
					 | 
					 | 
								file->cur_abs++; | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								file->cur_rel++; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								file->cur_ofs++; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								chunk = 1; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							// Pointer arith!
 | 
					 | 
					 | 
					 | 
							} | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							source += chunk; // advance the source pointer
 | 
					 | 
					 | 
					 | 
							else | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								// How much can be stored in this cluster
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								chunk = MIN(fat->bs.bytes_per_cluster - file->cur_ofs, len); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								dev->store(source, chunk); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								// advance cursors
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								file->cur_abs += chunk; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								file->cur_rel += chunk; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								file->cur_ofs += chunk; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								// Pointer arith!
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								source += chunk; // advance the source pointer
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							// detect cluster overflow
 | 
					 | 
					 | 
					 | 
							// detect cluster overflow
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							if (file->cur_ofs >= fat->bs.bytes_per_cluster) | 
					 | 
					 | 
					 | 
							if (file->cur_ofs >= fat->bs.bytes_per_cluster) | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -662,7 +698,7 @@ bool fat16_write(FAT16_FILE* file, void* source, uint32_t len) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					/** Open next file in the directory */ | 
					 | 
					 | 
					 | 
					/** Open next file in the directory */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					bool fat16_next(FAT16_FILE* file) | 
					 | 
					 | 
					 | 
					bool ff_next(FFILE* file) | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					{ | 
					 | 
					 | 
					 | 
					{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						const FAT16* fat = file->fat; | 
					 | 
					 | 
					 | 
						const FAT16* fat = file->fat; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						const BLOCKDEV* dev = fat->dev; | 
					 | 
					 | 
					 | 
						const BLOCKDEV* dev = fat->dev; | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -686,7 +722,7 @@ bool fat16_next(FAT16_FILE* file) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					/** Open previous file in the directory */ | 
					 | 
					 | 
					 | 
					/** Open previous file in the directory */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					bool fat16_prev(FAT16_FILE* file) | 
					 | 
					 | 
					 | 
					bool ff_prev(FFILE* file) | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					{ | 
					 | 
					 | 
					 | 
					{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						if (file->num == 0) | 
					 | 
					 | 
					 | 
						if (file->num == 0) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							return false; // first file already
 | 
					 | 
					 | 
					 | 
							return false; // first file already
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -698,14 +734,14 @@ bool fat16_prev(FAT16_FILE* file) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					/** Rewind to first file in directory */ | 
					 | 
					 | 
					 | 
					/** Rewind to first file in directory */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					void fat16_first(FAT16_FILE* file) | 
					 | 
					 | 
					 | 
					void ff_first(FFILE* file) | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					{ | 
					 | 
					 | 
					 | 
					{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						open_file(file->fat, file, file->clu, 0); | 
					 | 
					 | 
					 | 
						open_file(file->fat, file, file->clu, 0); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					/** Open a directory denoted by the file. */ | 
					 | 
					 | 
					 | 
					/** Open a directory denoted by the file. */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					bool fat16_opendir(FAT16_FILE* dir) | 
					 | 
					 | 
					 | 
					bool ff_opendir(FFILE* dir) | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					{ | 
					 | 
					 | 
					 | 
					{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						// Don't open non-dirs and "." directory.
 | 
					 | 
					 | 
					 | 
						// Don't open non-dirs and "." directory.
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						if (!(dir->attribs & FA_DIR) || dir->type == FT_SELF) | 
					 | 
					 | 
					 | 
						if (!(dir->attribs & FA_DIR) || dir->type == FT_SELF) | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -716,7 +752,7 @@ bool fat16_opendir(FAT16_FILE* dir) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					void fat16_root(const FAT16* fat, FAT16_FILE* file) | 
					 | 
					 | 
					 | 
					void ff_root(const FAT16* fat, FFILE* file) | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					{ | 
					 | 
					 | 
					 | 
					{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						open_file(fat, file, 0, 0); | 
					 | 
					 | 
					 | 
						open_file(fat, file, 0, 0); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -727,16 +763,16 @@ void fat16_root(const FAT16* fat, FAT16_FILE* file) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 * If file is found, "dir" will contain it's handle. | 
					 | 
					 | 
					 | 
					 * If file is found, "dir" will contain it's handle. | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 * Either way, "dir" gets modified and you may need to rewind it afterwards. | 
					 | 
					 | 
					 | 
					 * Either way, "dir" gets modified and you may need to rewind it afterwards. | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 */ | 
					 | 
					 | 
					 | 
					 */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					bool fat16_find(FAT16_FILE* dir, const char* name) | 
					 | 
					 | 
					 | 
					bool ff_open(FFILE* dir, const char* name) | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					{ | 
					 | 
					 | 
					 | 
					{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						char fname[11]; | 
					 | 
					 | 
					 | 
						char fname[11]; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						fat16_rawname(name, fname); | 
					 | 
					 | 
					 | 
						ff_rawname(name, fname); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						return dir_find_file_raw(dir, fname); | 
					 | 
					 | 
					 | 
						return dir_find_file_raw(dir, fname); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					/** Go through a directory, and "open" first FT_NONE or FT_DELETED file entry. */ | 
					 | 
					 | 
					 | 
					/** Go through a directory, and "open" first FT_NONE or FT_DELETED file entry. */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					bool find_empty_file_slot(FAT16_FILE* file) | 
					 | 
					 | 
					 | 
					bool find_empty_file_slot(FFILE* file) | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					{ | 
					 | 
					 | 
					 | 
					{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						const uint16_t clu = file->clu; | 
					 | 
					 | 
					 | 
						const uint16_t clu = file->clu; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						const FAT16* fat = file->fat; | 
					 | 
					 | 
					 | 
						const FAT16* fat = file->fat; | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -781,15 +817,15 @@ bool find_empty_file_slot(FAT16_FILE* file) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					bool fat16_mkfile(FAT16_FILE* file, const char* name) | 
					 | 
					 | 
					 | 
					bool ff_newfile(FFILE* file, const char* name) | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					{ | 
					 | 
					 | 
					 | 
					{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						// Convert filename to zero padded raw string
 | 
					 | 
					 | 
					 | 
						// Convert filename to zero padded raw string
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						char fname[11]; | 
					 | 
					 | 
					 | 
						char fname[11]; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						fat16_rawname(name, fname); | 
					 | 
					 | 
					 | 
						ff_rawname(name, fname); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						// Abort if file already exists
 | 
					 | 
					 | 
					 | 
						// Abort if file already exists
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						bool exists = dir_find_file_raw(file, fname); | 
					 | 
					 | 
					 | 
						bool exists = dir_find_file_raw(file, fname); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						fat16_first(file); // rewind dir
 | 
					 | 
					 | 
					 | 
						ff_first(file); // rewind dir
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						if (exists) | 
					 | 
					 | 
					 | 
						if (exists) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							return false; // file already exists in the dir.
 | 
					 | 
					 | 
					 | 
							return false; // file already exists in the dir.
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -809,15 +845,15 @@ bool fat16_mkfile(FAT16_FILE* file, const char* name) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 * Create a sub-directory of given name. | 
					 | 
					 | 
					 | 
					 * Create a sub-directory of given name. | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 * Directory is allocated and populated with entries "." and ".." | 
					 | 
					 | 
					 | 
					 * Directory is allocated and populated with entries "." and ".." | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 */ | 
					 | 
					 | 
					 | 
					 */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					bool fat16_mkdir(FAT16_FILE* file, const char* name) | 
					 | 
					 | 
					 | 
					bool ff_mkdir(FFILE* file, const char* name) | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					{ | 
					 | 
					 | 
					 | 
					{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						// Convert filename to zero padded raw string
 | 
					 | 
					 | 
					 | 
						// Convert filename to zero padded raw string
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						char fname[11]; | 
					 | 
					 | 
					 | 
						char fname[11]; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						fat16_rawname(name, fname); | 
					 | 
					 | 
					 | 
						ff_rawname(name, fname); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						// Abort if file already exists
 | 
					 | 
					 | 
					 | 
						// Abort if file already exists
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						bool exists = dir_find_file_raw(file, fname); | 
					 | 
					 | 
					 | 
						bool exists = dir_find_file_raw(file, fname); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						fat16_first(file); // rewind dir
 | 
					 | 
					 | 
					 | 
						ff_first(file); // rewind dir
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						if (exists) | 
					 | 
					 | 
					 | 
						if (exists) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							return false; // file already exusts in the dir.
 | 
					 | 
					 | 
					 | 
							return false; // file already exusts in the dir.
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -840,20 +876,20 @@ bool fat16_mkdir(FAT16_FILE* file, const char* name) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						write_file_header(file, "..         ", FA_DIR, parent_clu); | 
					 | 
					 | 
					 | 
						write_file_header(file, "..         ", FA_DIR, parent_clu); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						// rewind.
 | 
					 | 
					 | 
					 | 
						// rewind.
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						fat16_first(file); | 
					 | 
					 | 
					 | 
						ff_first(file); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						return true; | 
					 | 
					 | 
					 | 
						return true; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					char* fat16_disk_label(const FAT16* fat, char* label_out) | 
					 | 
					 | 
					 | 
					char* ff_disk_label(const FAT16* fat, char* label_out) | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					{ | 
					 | 
					 | 
					 | 
					{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						FAT16_FILE first; | 
					 | 
					 | 
					 | 
						FFILE first; | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						fat16_root(fat, &first); | 
					 | 
					 | 
					 | 
						ff_root(fat, &first); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						if (first.type == FT_LABEL) | 
					 | 
					 | 
					 | 
						if (first.type == FT_LABEL) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						{ | 
					 | 
					 | 
					 | 
						{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							return fat16_dispname(&first, label_out); | 
					 | 
					 | 
					 | 
							return ff_dispname(&first, label_out); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						} | 
					 | 
					 | 
					 | 
						} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						// find where spaces end
 | 
					 | 
					 | 
					 | 
						// find where spaces end
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -876,7 +912,7 @@ char* fat16_disk_label(const FAT16* fat, char* label_out) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					char* fat16_dispname(const FAT16_FILE* file, char* disp_out) | 
					 | 
					 | 
					 | 
					char* ff_dispname(const FFILE* file, char* disp_out) | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					{ | 
					 | 
					 | 
					 | 
					{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						// Cannot get name for special files
 | 
					 | 
					 | 
					 | 
						// Cannot get name for special files
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						if (file->type == FT_NONE ||        // not-yet-used directory location
 | 
					 | 
					 | 
					 | 
						if (file->type == FT_NONE ||        // not-yet-used directory location
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -926,7 +962,7 @@ char* fat16_dispname(const FAT16_FILE* file, char* disp_out) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					char* fat16_rawname(const char* disp_in, char* raw_out) | 
					 | 
					 | 
					 | 
					char* ff_rawname(const char* disp_in, char* raw_out) | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					{ | 
					 | 
					 | 
					 | 
					{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						uint8_t name_c = 0, wr_c = 0; | 
					 | 
					 | 
					 | 
						uint8_t name_c = 0, wr_c = 0; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						bool filling = false; | 
					 | 
					 | 
					 | 
						bool filling = false; | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -1000,21 +1036,41 @@ char* fat16_rawname(const char* disp_in, char* raw_out) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					/** Write new file size (also to the disk). Does not allocate clusters. */ | 
					 | 
					 | 
					 | 
					FSAVEPOS ff_savepos(const FFILE* file) | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					void fat16_resize(FAT16_FILE* file, uint32_t size) | 
					 | 
					 | 
					 | 
					{ | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						FSAVEPOS fsp; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						fsp.clu = file->clu; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						fsp.num = file->num; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						fsp.cur_rel = file->cur_rel; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						return fsp; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					void ff_reopen(FFILE* file, const FSAVEPOS* pos) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						open_file(file->fat, file, pos->clu, pos->num); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						ff_seek(file, pos->cur_rel); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					void ff_flush_file(FFILE* file) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					{ | 
					 | 
					 | 
					 | 
					{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						const FAT16* fat = file->fat; | 
					 | 
					 | 
					 | 
						const FAT16* fat = file->fat; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						const BLOCKDEV* dev = file->fat->dev; | 
					 | 
					 | 
					 | 
						const BLOCKDEV* dev = file->fat->dev; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						// Store open page
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						dev->flush(); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						// Store file size
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						// Find address for storing the size
 | 
					 | 
					 | 
					 | 
						// Find address for storing the size
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						const uint32_t addr = clu_offs(fat, file->clu, file->num * 32 + 28); | 
					 | 
					 | 
					 | 
						const uint32_t addr = clu_offs(fat, file->clu, file->num * 32 + 28); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						file->size = size; | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						dev->seek(addr); | 
					 | 
					 | 
					 | 
						dev->seek(addr); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						dev->store(&size, 4); | 
					 | 
					 | 
					 | 
						dev->store(&(file->size), 4); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						// Seek to the end of the file, to make sure clusters are allocated
 | 
					 | 
					 | 
					 | 
						// Seek to the end of the file, to make sure clusters are allocated
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						fat16_seek(file, size - 1); | 
					 | 
					 | 
					 | 
						ff_seek(file, file->size - 1); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						const uint16_t next = next_clu(fat, file->cur_clu); | 
					 | 
					 | 
					 | 
						const uint16_t next = next_clu(fat, file->cur_clu); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						if (next != 0xFFFF) | 
					 | 
					 | 
					 | 
						if (next != 0xFFFF) | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -1026,8 +1082,10 @@ void fat16_resize(FAT16_FILE* file, uint32_t size) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						} | 
					 | 
					 | 
					 | 
						} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					/** Low level no-check file delete and free */ | 
					 | 
					 | 
					 | 
					/** Low level no-check file delete and free */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					void delete_file_do(FAT16_FILE* file) | 
					 | 
					 | 
					 | 
					void delete_file_do(FFILE* file) | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					{ | 
					 | 
					 | 
					 | 
					{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						const FAT16* fat = file->fat; | 
					 | 
					 | 
					 | 
						const FAT16* fat = file->fat; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -1049,7 +1107,7 @@ void delete_file_do(FAT16_FILE* file) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					/** Delete a simple file */ | 
					 | 
					 | 
					 | 
					/** Delete a simple file */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					bool fat16_rmfile(FAT16_FILE* file) | 
					 | 
					 | 
					 | 
					bool ff_rmfile(FFILE* file) | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					{ | 
					 | 
					 | 
					 | 
					{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						switch (file->type) | 
					 | 
					 | 
					 | 
						switch (file->type) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						{ | 
					 | 
					 | 
					 | 
						{ | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -1068,19 +1126,15 @@ bool fat16_rmfile(FAT16_FILE* file) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					/** Delete an empty directory */ | 
					 | 
					 | 
					 | 
					/** Delete an empty directory */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					bool fat16_rmdir(FAT16_FILE* file) | 
					 | 
					 | 
					 | 
					bool ff_rmdir(FFILE* file) | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					{ | 
					 | 
					 | 
					 | 
					{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						if (file->type != FT_SUBDIR) | 
					 | 
					 | 
					 | 
						if (file->type != FT_SUBDIR) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							return false; // not a subdirectory entry
 | 
					 | 
					 | 
					 | 
							return false; // not a subdirectory entry
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						const FAT16* fat = file->fat; | 
					 | 
					 | 
					 | 
						const FSAVEPOS orig = ff_savepos(file); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						const uint16_t clu1 = file->clu; | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						const uint16_t num1 = file->num; | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						// Open the subdir
 | 
					 | 
					 | 
					 | 
						// Open the subdir
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						if (!fat16_opendir(file)) | 
					 | 
					 | 
					 | 
						if (!ff_opendir(file)) | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							return false; // could not open
 | 
					 | 
					 | 
					 | 
							return false; // could not open
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						// Look for valid files and subdirs in the directory
 | 
					 | 
					 | 
					 | 
						// Look for valid files and subdirs in the directory
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -1097,16 +1151,16 @@ bool fat16_rmdir(FAT16_FILE* file) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							{ | 
					 | 
					 | 
					 | 
							{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								// Valid child file was found, aborting.
 | 
					 | 
					 | 
					 | 
								// Valid child file was found, aborting.
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								// reopen original file
 | 
					 | 
					 | 
					 | 
								// reopen original file
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								open_file(fat, file, clu1, num1); | 
					 | 
					 | 
					 | 
								ff_reopen(file, &orig); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								return false; | 
					 | 
					 | 
					 | 
								return false; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							} | 
					 | 
					 | 
					 | 
							} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							if (cnt < 2) cnt++; | 
					 | 
					 | 
					 | 
							if (cnt < 2) cnt++; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						} | 
					 | 
					 | 
					 | 
						} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						while (fat16_next(file)); | 
					 | 
					 | 
					 | 
						while (ff_next(file)); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						// reopen original file
 | 
					 | 
					 | 
					 | 
						// reopen original file
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						open_file(fat, file, clu1, num1); | 
					 | 
					 | 
					 | 
						ff_reopen(file, &orig); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						// and delete as ordinary file
 | 
					 | 
					 | 
					 | 
						// and delete as ordinary file
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						delete_file_do(file); | 
					 | 
					 | 
					 | 
						delete_file_do(file); | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -1115,7 +1169,7 @@ bool fat16_rmdir(FAT16_FILE* file) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					bool fat16_delete(FAT16_FILE* file) | 
					 | 
					 | 
					 | 
					bool ff_delete(FFILE* file) | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					{ | 
					 | 
					 | 
					 | 
					{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						switch (file->type) | 
					 | 
					 | 
					 | 
						switch (file->type) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						{ | 
					 | 
					 | 
					 | 
						{ | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -1126,8 +1180,7 @@ bool fat16_delete(FAT16_FILE* file) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							case FT_SUBDIR:; // semicolon needed to allow declaration after "case"
 | 
					 | 
					 | 
					 | 
							case FT_SUBDIR:; // semicolon needed to allow declaration after "case"
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								// store original file location
 | 
					 | 
					 | 
					 | 
								// store original file location
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								const uint16_t clu1 = file->clu; | 
					 | 
					 | 
					 | 
								const FSAVEPOS orig = ff_savepos(file); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								const uint16_t num1 = file->num; | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								// open the directory (skip "." and "..")
 | 
					 | 
					 | 
					 | 
								// open the directory (skip "." and "..")
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								open_file(file->fat, file, file->clu_start, 2); | 
					 | 
					 | 
					 | 
								open_file(file->fat, file, file->clu_start, 2); | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -1135,34 +1188,32 @@ bool fat16_delete(FAT16_FILE* file) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								// delete all children
 | 
					 | 
					 | 
					 | 
								// delete all children
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								do | 
					 | 
					 | 
					 | 
								do | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								{ | 
					 | 
					 | 
					 | 
								{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									if (!fat16_delete(file)) | 
					 | 
					 | 
					 | 
									if (!ff_delete(file)) | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									{ | 
					 | 
					 | 
					 | 
									{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
										// failure
 | 
					 | 
					 | 
					 | 
										// failure
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
										// reopen original file
 | 
					 | 
					 | 
					 | 
										// reopen original file
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
										open_file(file->fat, file, clu1, num1); | 
					 | 
					 | 
					 | 
										ff_reopen(file, &orig); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
										return false; | 
					 | 
					 | 
					 | 
										return false; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									} | 
					 | 
					 | 
					 | 
									} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								} | 
					 | 
					 | 
					 | 
								} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								while (fat16_next(file)); | 
					 | 
					 | 
					 | 
								while (ff_next(file)); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								// go up and delete the dir
 | 
					 | 
					 | 
					 | 
								// go up and delete the dir
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								open_file(file->fat, file, clu1, num1); | 
					 | 
					 | 
					 | 
								ff_reopen(file, &orig); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								return fat16_rmdir(file); | 
					 | 
					 | 
					 | 
								return ff_rmdir(file); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							default: | 
					 | 
					 | 
					 | 
							default: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								// try to delete as a regular file
 | 
					 | 
					 | 
					 | 
								// try to delete as a regular file
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								return fat16_rmfile(file); | 
					 | 
					 | 
					 | 
								return ff_rmfile(file); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						} | 
					 | 
					 | 
					 | 
						} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					bool fat16_parent(FAT16_FILE* file) | 
					 | 
					 | 
					 | 
					bool ff_parent(FFILE* file) | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					{ | 
					 | 
					 | 
					 | 
					{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						const uint16_t clu1 = file->clu; | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						const uint16_t num1 = file->num; | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						// open second entry of the directory
 | 
					 | 
					 | 
					 | 
						// open second entry of the directory
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						open_file(file->fat, file, file->clu, 1); | 
					 | 
					 | 
					 | 
						open_file(file->fat, file, file->clu, 1); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						const FSAVEPOS orig = ff_savepos(file); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						// if it's a valid PARENT link, follow it.
 | 
					 | 
					 | 
					 | 
						// if it's a valid PARENT link, follow it.
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						if (file->type == FT_PARENT) | 
					 | 
					 | 
					 | 
						if (file->type == FT_PARENT) | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -1174,7 +1225,7 @@ bool fat16_parent(FAT16_FILE* file) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						{ | 
					 | 
					 | 
					 | 
						{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							// in root already?
 | 
					 | 
					 | 
					 | 
							// in root already?
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							// reopen original file
 | 
					 | 
					 | 
					 | 
							// reopen original file
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							open_file(file->fat, file, clu1, num1); | 
					 | 
					 | 
					 | 
							ff_reopen(file, &orig); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							return false; | 
					 | 
					 | 
					 | 
							return false; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						} | 
					 | 
					 | 
					 | 
						} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
					 | 
					 | 
					
  |