📄 f34x_msd_file_system.c
字号:
return (n0==(char)0xE5) || (n0=='\0');
}
return (n0!=(char)0xE5) && (n0>' ') && (findinfo->direntry->sfn.attrib!=0x0F);
}
BYTE findfirst(find_info* findinfo,BYTE empty)
{
Sect_Read(findinfo->block = Current_Dir_Block);
findinfo->findempty=empty;
findinfo->direntry=(dir_entry*)(Scratch+(findinfo->offset=0));
if(findvalid(findinfo))
return 1;
return findnext(findinfo);
}
BYTE findnext(find_info* findinfo)
{
xdata BYTE bRoot = (Current_Dir_Block == Sect_Root_Dir());
do {
if((findinfo->offset+=sizeof(dir_entry))>=Sect_Block_Size()) {
xdata unsigned long dir_next_cluster_block =
Get_First_Block_Directory_Cluster(findinfo->block);
if(bRoot && (findinfo->block>=Sect_Root_Dir_Last()))
{
// printf("NOT FOUND\r\n");
return 0;
}
else if((!bRoot) && (dir_next_cluster_block != 0xffffffff) &&
(findinfo->block>=(dir_next_cluster_block + MBR.sectors_per_cluster-1)))
{
// read next cluster occupied by directory
xdata unsigned long next_next_block = Get_First_Block_Of_Next_Cluster(
Get_Cluster_From_Sector(dir_next_cluster_block));
if(next_next_block == (0xFFFFFFFF))
{
if(!findinfo->findempty)
return 0;
else
{
xdata new_cluster =
fat_chain_alloc(Get_Cluster_From_Sector(dir_next_cluster_block),1);
if(new_cluster == 0xFFFF)
return 0;
next_next_block = Get_First_Sector(new_cluster);
Clear_Cluster(new_cluster);
}
}
dir_next_cluster_block = next_next_block;
findinfo->offset=0;
Sect_Read(findinfo->block = dir_next_cluster_block);
}
else {
findinfo->offset=0;
Sect_Read(++findinfo->block);
}
}
findinfo->direntry=(dir_entry*)(Scratch+findinfo->offset);
} while(!findvalid(findinfo));
return 1;
}
#else
//---------------------------------------------------------
/* Copy of functions for devices different then F340*/
//---------------------------------------------------------
static BYTE fcreate(find_info* findinfo,char* filename)
{
BYTE i,j;
// Find the first empty directory entry
if(!findfirst(findinfo,1)) return 0;
// Fill in the direntry
for( i = 0; i < 10; i++)
findinfo->direntry->sfn.reserved[i] = 0;
findinfo->direntry->sfn.time.i = findinfo->direntry->sfn.date.i = 0;
findinfo->direntry->sfn.starting_cluster = findinfo->direntry->sfn.filesize = 0;
// Fill in the filename
for( i = 0; i < 11; i++ )
findinfo->direntry->sfn.name[i] = ' ';
for( j = 0; j < 20; j++ ) {
if(!filename[j] || filename[j] == '.')
break;
if( j < 8 )
findinfo->direntry->sfn.name[j] = toupper(filename[j]);
}
if( filename[j] == '.' ) {
for( i = 0; i < 3; i++ ) {
if(!filename[j+i+1] || filename[j+i+1]=='.')
break;
findinfo->direntry->sfn.name[8+i] = toupper(filename[j+i+1]);
}
}
//for(i=0;i<11;i++) findinfo->direntry->sfn.name[i]=
//toupper(findinfo->direntry->sfn.name[i]);
// Don't forget to set the attrib:
findinfo->direntry->sfn.attrib = ATTRIB_ARCHIVE;
// Write the new data to MMC
Sect_Write(findinfo->block);
return 1;
}
static find_info xdata findinfo; // Shared find_info for fopen() and fdelete()
int fopen(FILE* f,char* filename,char* mode)
{
f->isopen = 0;
if( mode[0] == 'w' ) {
fdelete(filename);
} // This is the most memory-efficient solution, not the most time-efficient solution.
findfirst(&findinfo, 0);
while(!file_name_match(filename,findinfo.direntry->sfn.name)) {
if(!findnext(&findinfo)) {
if(mode[0] == 'r') {
return 0; // File not found.
}
if( mode[0] == 'w' || mode[0] == 'a' ) {
if(!fcreate(&findinfo, filename)) {
return 0; // File cannot be created.
} else {
break;
}
}
}
}
f->sector_direntry=findinfo.block;
f->offset_direntry=findinfo.offset;
f->cluster_start=f->sector_current=
ntohs(findinfo.direntry->sfn.starting_cluster);//*MBR.sectors_per_cluster;
f->attrib=findinfo.direntry->sfn.attrib;
f->size=ntohl(findinfo.direntry->sfn.filesize);
if(mode[0]=='a') f->pos=f->size; else f->pos=0;
// Print_File(f);
return f->isopen=1;
}
/*
int fexists(char* filename) {
FILE xdata f;
if(fopen(&f,filename,"r")) {
fclose(&f);
return 1;
}
return 0;
}
*/
/*
int fseek(FILE* f,long offset,int origin) {
if(!f->isopen) return 0;
switch(origin) {
case SEEK_SET:default:
if(offset>=0)
f->pos=offset;
else
return 0;
break;
case SEEK_END:
f->pos=f->size+offset;
break;
case SEEK_CUR:
f->pos+=offset;
break;
}
return 1;
}
*/
/*
DWORD ftell(FILE* f) {
if(!f->isopen) return 0;
return f->pos;
}
*/
int feof(FILE* f)
{
if(!f->isopen) return 1;
return f->pos >= f->size;
}
// Find the 'nr'-th sector in the fat chain starting at 'from'
static unsigned long fat_chain(unsigned long from,unsigned nr)
{
unsigned* xdata fat_table=Scratch;
unsigned xdata sect,sect_prev=0;
unsigned xdata cluster = nr/MBR.sectors_per_cluster;
while(cluster) {
sect = Sect_Fat1() + from/(Sect_Block_Size()/2);
if(sect!=sect_prev) {
Sect_Read(sect_prev=sect);
}
from=ntohs(fat_table[from%(Sect_Block_Size()/2)]);
if(!(from>=2 && from<=0xFFEF)) {
return 0xFFFFu;
}
cluster--;
}
from *= MBR.sectors_per_cluster;
from += nr%MBR.sectors_per_cluster;
return from;
}
// Free an entire fat chain, starting at 'from' until the end of the chain
static void fat_chain_free(unsigned from)
{
unsigned* xdata fat_table=Scratch;
unsigned xdata sect,sect_prev=0;
unsigned xdata index;
if(from<2) return;
sect = Sect_Fat1() + from/(Sect_Block_Size()/2);
while(1) {
if(sect!=sect_prev) {
Sect_Read(sect_prev=sect);
}
index = from%(Sect_Block_Size()/2);
from=ntohs(fat_table[index]);
fat_table[index]=0x0000; // Free it
if(!(from>=2 && from<=0xFFEF)) {
Sect_Write_Multi_Fat(sect_prev);
break;
}
sect = Sect_Fat1() + from/(Sect_Block_Size()/2);
if(sect!=sect_prev) {
Sect_Write_Multi_Fat(sect_prev);
}
}
}
// Allocate 'nr' extra FAT blocks at the end of the chain that starts at 'from':
static unsigned fat_chain_alloc(unsigned from,unsigned nr)
{
unsigned* xdata fat_table=Scratch;
unsigned xdata sect,sect_prev=0;
unsigned xdata index;
unsigned xdata alloced=0xFFFF;
// Find free FAT entries, allocate them, and link them together.
for(sect=Sect_Fat1();nr && sect<Sect_Fat2();sect++) {
Sect_Read(sect);
// (Skip first two FAT entries when looking for free blocks)
for(index=((sect==Sect_Fat1())?2:0);index<Sect_Block_Size()/2;index++) {
if(fat_table[index]==0x0000) { // It's free
fat_table[index]=ntohs(alloced);// Allocate it (refer to previously alloc'ed FAT entry).
alloced = // Remember which FAT entry was alloc'ed
(sect-Sect_Fat1()) * (Sect_Block_Size()/2) + index;
if(!--nr) break;
}
}
if(alloced!=0xFFFF) Sect_Write_Multi_Fat(sect); // Write all FAT copies
}
// When we get here, 'alloced' contains the first FAT block in the alloc'ed chain
// Find the end of the current FAT chain.
// Make the end of the current FAT chain refer to the newly allocated FAT chain
while(from>=2 && from<=0xFFEF && alloced!=0xFFFF) {
sect = Sect_Fat1() + from/(Sect_Block_Size()/2);
if(sect!=sect_prev) {
Sect_Read(sect_prev=sect);
}
index = from%(Sect_Block_Size()/2);
from=ntohs(fat_table[index]);
if(from>=0xFFF8) {
fat_table[index]=ntohs(alloced);
Sect_Write_Multi_Fat(sect);
}
}
return alloced;
}
unsigned fread(FILE* f,BYTE* buffer,unsigned count)
{
unsigned xdata cnt,total_cnt=0;
if(!f->isopen || !count) return 0;
// If you use the Scratch buffer as fread buffer, then
// we cannot possibly support transfers consisting of
// multiple Sect_Read() operations. The second Sect_Read
// would overwrite the stored bytes from the first one.
if(buffer>=Scratch && buffer<Scratch+Sect_Block_Size())
count=min(count,Sect_Block_Size()-f->pos%Sect_Block_Size());
while(count && !feof(f)) {
f->sector_current = fat_chain(f->cluster_start,f->pos/Sect_Block_Size());
Sect_Read(Sect_File_Data() + f->sector_current);
cnt=min(Sect_Block_Size()-f->pos%Sect_Block_Size(),count);
cnt=min(cnt,f->size-f->pos);
memmove(buffer,Scratch+f->pos%Sect_Block_Size(),cnt); // MUST be overlap-safe copy operation!
total_cnt+=cnt;
f->pos+=cnt;
count-=cnt;
buffer+=cnt;
}
return total_cnt;
}
unsigned fwrite(FILE* f,BYTE* buffer,unsigned count)
{
unsigned cnt,total_cnt=0,xtra,alloced;
dir_entry* entry;
if(!f->isopen || !count) return 0;
// First, extend the file so it can hold all the data:
if(f->pos+count>f->size) {
// If the new EOF ends up in the next FAT block, an extra block must be
// allocated.
// The number of blocks needed to store X bytes = 1+(X-1)/512 if X!=0,
// or =0 if X==0.
// We will need to store 'pos+count' bytes after the write operation
// This means we need 1+(pos+count-1)/512 blocks after the write operation
// We currently have 'size' bytes in the file, or 1+(size-1)/512 blocks
// (or 0 if size==0).
// So, we need to allocate (1+(pos+count-1)/512) - (1+(size-1)/512)
// extra blocks
xtra=(1+((f->pos+count-1)/Sect_Block_Size())/MBR.sectors_per_cluster);
if ( f->size )
xtra -=
( 1 +(( f->size - 1 ) / Sect_Block_Size() ) / MBR.sectors_per_cluster );
if(xtra) {
if(0xFFFF==
(alloced=fat_chain_alloc(f->sector_current/MBR.sectors_per_cluster,xtra)))
return 0;
}
// Modify the direntry for this file:
Sect_Read(f->sector_direntry);
entry = (dir_entry*)(Scratch+f->offset_direntry);
if((entry->sfn.filesize==0) && (entry->sfn.starting_cluster<2 ||
entry->sfn.starting_cluster>=0xFFF0)) {
entry->sfn.starting_cluster=ntohs(f->cluster_start=alloced);
}
entry->sfn.filesize=ntohl(f->size=f->pos+count);
f->attrib=(entry->sfn.attrib|=ATTRIB_ARCHIVE);
Sect_Write(f->sector_direntry);
}
// Now we are sure the fwrite() operation can be performed
// in the existing file data blocks. Either because the file
// was big enough to start with, or because we have just
// allocated extra blocks for the new data.
while(count && !feof(f)) {
f->sector_current = fat_chain(f->cluster_start,f->pos/Sect_Block_Size());
Sect_Read(Sect_File_Data() + f->sector_current);
// Print_File(f);
// print_scratch();
cnt=min(Sect_Block_Size()-f->pos%Sect_Block_Size(),count);
cnt=min(cnt,f->size-f->pos);
memmove(Scratch+f->pos%Sect_Block_Size(),buffer,cnt);
// print_scratch();
Sect_Write(Sect_File_Data() + f->sector_current);
total_cnt+=cnt;
f->pos+=cnt;
count-=cnt;
buffer+=cnt;
}
return total_cnt;
}
void fclose(FILE* f)
{
f->isopen=0;
}
int fdelete(char* name)
{
findfirst(&findinfo,0);
while(!file_name_match(name,findinfo.direntry->sfn.name)) {
if(!findnext(&findinfo)) {
return 0;
}
}
// Do not delete subdirectories or labels:
if(findinfo.direntry->sfn.attrib & (ATTRIB_SUBDIR|ATTRIB_LABEL)) return 0;
// Mark the direntry as "deleted" before freeing the fat chain.
// At this point, the findinfo is still valid in the 'Scratch' buffer.
// fat_chain_free() would overwrite the Scratch buffer.
findinfo.direntry->sfn.name[0]=0xE5; // Mark as "deleted"
Sect_Write(findinfo.block);
fat_chain_free(ntohs(findinfo.direntry->sfn.starting_cluster));
return 1;
}
//--------- findfirst, findnext directory functions ---------
static BYTE findvalid(find_info* findinfo)
{
char n0 = findinfo->direntry->sfn.name[0];
if(findinfo->findempty) {
return (n0==(char)0xE5) || (n0=='\0');
}
return (n0!=(char)0xE5) && (n0>' ') && (findinfo->direntry->sfn.attrib!=0x0F);
}
BYTE findfirst(find_info* findinfo,BYTE empty)
{
Sect_Read(findinfo->block = Sect_Root_Dir());
findinfo->findempty=empty;
findinfo->direntry=(dir_entry*)(Scratch+(findinfo->offset=0));
if(findvalid(findinfo))
return 1;
return findnext(findinfo);
}
void print_info(find_info* info);
BYTE findnext(find_info* findinfo)
{
do {
if((findinfo->offset+=sizeof(dir_entry))>=Sect_Block_Size()) {
if(findinfo->block>=Sect_Root_Dir_Last())
{
// printf("NOT FOUND\r\n");
return 0;
}
else {
findinfo->offset=0;
Sect_Read(++findinfo->block);
}
}
findinfo->direntry=(dir_entry*)(Scratch+findinfo->offset);
} while(!findvalid(findinfo));
return 1;
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -