📄 f34x_msd_file_system.c
字号:
!file_name_match("..",findinfo.direntry->sfn.name))
{
prev_dir_block[dir_deep].block = findinfo.block;
prev_dir_block[dir_deep].offset = findinfo.offset;
Get_File_Name(findinfo.direntry->sfn.name,dir_tmp_name);
chngdir(dir_tmp_name);
findfirst(&findinfo,0);
dir_deep++;
}
}
else
{
// 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));
Sect_Read(findinfo.block);
}
}
}
if(!findnext(&findinfo))
{
if(dir_deep)
{
dir_deep--;
chngdir("..");
findinfo.block = prev_dir_block[dir_deep].block;
findinfo.offset = prev_dir_block[dir_deep].offset ;
Sect_Read(findinfo.block);
findinfo.direntry=(dir_entry*)(Scratch+findinfo.offset);
findinfo.direntry->sfn.name[0]=0xE5; // Mark as "deleted"
Sect_Write(findinfo.block);
fat_chain_free(ntohs(findinfo.direntry->sfn.starting_cluster));
Sect_Read(findinfo.block);
findinfo.direntry=(dir_entry*)(Scratch+findinfo.offset);
} else
{
chngdir("..");
break;
}
}
}
findfirst(&findinfo,0);
while(!file_name_match(first_part_of_dir,findinfo.direntry->sfn.name)) {
if(!findnext(&findinfo)) {
return 0;
}
}
findinfo.direntry->sfn.name[0]=0xE5; // Mark as "deleted"
Sect_Write(findinfo.block);
fat_chain_free(ntohs(findinfo.direntry->sfn.starting_cluster));
return 1;
}
//-----------------------------------------------------------------------------
// fcreate
//-----------------------------------------------------------------------------
//
// Return Value : If ok returns TRUE
// Parameters : find_info - pointer to info about file
// filename - pointer to file name
//
// This function creates file
//-----------------------------------------------------------------------------
static BYTE fcreate(find_info* findinfo,char* filename)
{
xdata 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;
}
//-----------------------------------------------------------------------------
// fopen
//-----------------------------------------------------------------------------
//
// Return Value : TRUE if file is open
// Parameters : f - pointer to file structure info
// filename - pointer to file name
// mode - pointer to opened file mode (read, write etc.)
//
// This function opens file
//-----------------------------------------------------------------------------
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;
}
//-----------------------------------------------------------------------------
// feof
//-----------------------------------------------------------------------------
//
// Return Value : End of file value
// Parameters : f - pointer to file info structure
//
// This function printout size of file
//-----------------------------------------------------------------------------
int feof(FILE* f)
{
if(!f->isopen) return 1;
return f->pos >= f->size;
}
//-----------------------------------------------------------------------------
// fat_chain
//-----------------------------------------------------------------------------
//
// Return Value : global number of sector
// Parameters : from - starting number of sector
// nr - relative number of sector
//
// 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 0xFFFFFFFF;
}
cluster--;
}
from *= MBR.sectors_per_cluster;
from += nr%MBR.sectors_per_cluster;
return from;
}
//-----------------------------------------------------------------------------
// fat_chain_free
//-----------------------------------------------------------------------------
//
// Return Value :
// Parameters : from - starting number of sector
//
// Function frees 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);
}
}
}
//-----------------------------------------------------------------------------
// fat_chain_alloc
//-----------------------------------------------------------------------------
//
// Return Value : numer of allocated sector
// Parameters : from - starting number of sector
// nr - relative number of sector
//
// Allocate 'nr' of 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;
}
//-----------------------------------------------------------------------------
// fread
//-----------------------------------------------------------------------------
//
// Return Value : amount of read bytes
// Parameters : f - pointer to file structure
// buffer - pinter to buffer
// count - number of bytes to read
//
// This function reads the file
//-----------------------------------------------------------------------------
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;
}
//-----------------------------------------------------------------------------
// fwrite
//-----------------------------------------------------------------------------
//
// Return Value : amount of written bytes
// Parameters : f - pointer to file structure
// buffer - pinter to buffer
// count - number of bytes to write
//
// This function writes the file
//-----------------------------------------------------------------------------
unsigned fwrite(FILE* f,BYTE* buffer,unsigned count)
{
xdata unsigned cnt,total_cnt=0,xtra,alloced;
xdata 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;
}
//-----------------------------------------------------------------------------
// fclose
//-----------------------------------------------------------------------------
//
// Return Value :
// Parameters : f - pointer to file structure
//
// This function closes the file
//-----------------------------------------------------------------------------
void fclose(FILE* f)
{
f->isopen=0;
}
//-----------------------------------------------------------------------------
// fdelete
//-----------------------------------------------------------------------------
//
// Return Value :TRUE if everything is ok
// Parameters : name - pointer to filename
//
//
// This function deletes the file
//-----------------------------------------------------------------------------
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;
}
//-------------------directory functions---------------------
//--------- findfirst, findnext directory functions ---------
static BYTE findvalid(find_info* findinfo)
{
xdata char n0 = findinfo->direntry->sfn.name[0];
if(findinfo->findempty) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -