📄 dos.c
字号:
//###########################################################
// File: dos.c
//
// Using fopen() and fread() is very slow because a lot
// of calculations have to be done.
// Using ReadFileRaw() is up to 7 times faster.
//#########################################################################
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "dos.h"
//#include "lcd.h"
#ifdef DOS_WRITE
#ifdef DOS_DELETE
//###########################################################
// delete a file
unsigned char remove(char *name)
//###########################################################
{
#ifdef USE_FAT32
unsigned long tmp,tmp1;
#else
unsigned int tmp,tmp1;
#endif
if(FileFlag!=0) return F_ERROR; // don't delete if a file is open
FileAttr=0xFF; // test if we really find a file and not a directory
// FileAttr then must be ATTR_FILE
if(FindName(name)==FULL_MATCH) // Look if file exists
{
if(FileAttr!=ATTR_FILE) return F_ERROR; // this was not a file !
tmp=FileFirstCluster;
// free clusters in FAT cluster chain (make zero)
do
{
tmp1=GetNextClusterNumber(tmp); // save next cluster number
WriteClusterNumber(tmp,0); // free cluster
tmp=tmp1; // restore next cluster number
}while(tmp<endofclusterchain);
#ifdef USE_FATBUFFER
if(FATStatus>0)
{
WriteSector(FATCurrentSector,fatbuf); // write the FAT buffer
FATStatus=0;
}
#endif
FileName[0]=0xE5; //mark file as deleted. does not affect long filename entrys !
FileSize=0; //make filesize 0
FileFirstCluster=0; //delete first cluster
FileAttr=0; //is this necessary ?
UpdateFileEntry();
}
return F_OK;
}
#endif //DOS_DELETE
#endif //DOS_WRITE
#ifdef DOS_WRITE
//###########################################################
// write count bytes from buffer to file
// returns number of bytes written
//
// fwrite() does not write to CF until a sector is completely
// filled. you can force writing with fflush() when file should
// keep open, or close the file with fclose().
//
//###########################################################
unsigned int fwrite(unsigned char *buf, unsigned int count)
//###########################################################
{
unsigned char *p, secoffset;
unsigned long tmp;
unsigned int buffoffset, bytecount;
if(FileFlag==0) return 0; //don't write if file is closed
//written bytes are zero
p=buf; //pointer to write buffer
bytecount=0;
do
{
tmp=FileSize; //next write position
tmp-= FileClusterCount; //calc byte position in cluster
if(tmp >= FileBytePerCluster)//is position in new cluster ?
{
WriteSector(FileCurrentSector,iob); //write last sector
FileCurrentCluster=AllocCluster(FileCurrentCluster); //alloc new cluster
if(FileCurrentCluster==DISK_FULL)
{
return bytecount; //return number of bytes written before disk full
}
File1stClusterSector=GetFirstSectorOfCluster(FileCurrentCluster);//set new 1st sector of cluster
FileCurrentSector=File1stClusterSector; //set new current sector
// FileClusterCount++; //update cluster count
FileClusterCount+=FileBytePerCluster; //update cluster count
tmp-= FileBytePerCluster; //calc new byte position in cluster
}
secoffset=(unsigned char)(tmp / BYTE_PER_SEC); //calc offset from first sector in cluster
if(File1stClusterSector+secoffset != FileCurrentSector)
{
WriteSector(FileCurrentSector,iob); //write last sector used
FileCurrentSector=File1stClusterSector+secoffset;
}
buffoffset=(unsigned int)(tmp % BYTE_PER_SEC); //calc offset in sector
iob[buffoffset]=*p++; //put byte in write buffer
FileSize++; //update Filesize
bytecount++; //one byte written to buffer
}while(bytecount<count);
return bytecount;
}
#endif //DOS_WRITE
#ifdef DOS_READ
//###########################################################
// read count bytes into buffer
// returns number of bytes read
unsigned int fread(unsigned char *buf, unsigned int count)
//###########################################################
{
unsigned char *p, secoffset;
unsigned long tmp;
unsigned int buffoffset, bytecount;
if(FileFlag==0) return 0; //don't read if file is closed
//read bytes are zero
p=buf; //pointer to read buffer
bytecount=0;
do
{
tmp = FilePosition;
if(tmp<FileSize) //end of file reached ?
{
// tmp-= FileClusterCount * FileBytePerCluster; //calc byte position in cluster
tmp -= FileClusterCount; //calc byte position in cluster
//maybe its faster to count cluster and sectorbytes
if(tmp >= FileBytePerCluster)//is position in current cluster ?
{
FileCurrentCluster = GetNextClusterNumber(FileCurrentCluster); //if not get next cluster
File1stClusterSector = GetFirstSectorOfCluster(FileCurrentCluster);//set new 1st sector of cluster
ReadSector(File1stClusterSector,iob); //read new sector
FileCurrentSector = File1stClusterSector; //set new current sector
// FileClusterCount++; //update cluster count
FileClusterCount += FileBytePerCluster; //update cluster count
tmp -= FileBytePerCluster; //calc new byte position in cluster
}
secoffset=(unsigned char)(tmp / BYTE_PER_SEC); //calc sector offset from first sector in cluster
if(File1stClusterSector+secoffset != FileCurrentSector) //new sector ?
{
FileCurrentSector=File1stClusterSector+secoffset;
ReadSector(FileCurrentSector,iob); //read new sector
}
buffoffset=(unsigned int)(tmp % BYTE_PER_SEC); //calc offset in sector
*p++=iob[buffoffset];
FilePosition++; //update file position
bytecount++; //one byte read into buffer
} //if(tmp<FileSize)
else return bytecount; //return bytes read til end of file
} while(bytecount<count);
return bytecount;
}
#endif //DOS_READ
#ifdef DOS_READ
//------------------------------------------------------------//
// read count bytes into buffer in Position
// returns number of bytes read
#ifdef USE_FAT32
unsigned int fread_InPosition(unsigned char *buf, unsigned int count,unsigned long Position)
#else
unsigned int fread_InPosition(unsigned char *buf, unsigned int count,unsigned int Position)
#endif
//----------------zhangbao 06.05.24 创建---------------------//
{
unsigned char *p, secoffset;
unsigned long tmp;
unsigned int buffoffset, bytecount;
unsigned long cluster_No;
if(FileFlag==0) return 0; //don't read if file is closed
//read bytes are zero
p=buf; //pointer to read buffer
bytecount=0;
FilePosition = Position;
if(Position < FileSize) //end of file reached ?
{
cluster_No = Position / FileBytePerCluster;
tmp = Position % FileBytePerCluster;
GoToNoCluster(cluster_No);
secoffset = (unsigned char)(tmp / BYTE_PER_SEC); //calc sector offset from first sector in cluster
FileCurrentSector = File1stClusterSector + secoffset;
ReadSector(FileCurrentSector,iob); //read new sector
buffoffset = (unsigned int)(tmp % BYTE_PER_SEC); //calc offset in sector
//bytecount = 0;
do
{
for(; buffoffset<BYTE_PER_SEC; buffoffset++)
{
*p++ = iob[buffoffset];
bytecount++;
FilePosition++;
if(FilePosition >= FileSize)
{
return(bytecount);
}
if(bytecount >= count)
{
return(bytecount);
}
}
FileCurrentSector++;
if(FileCurrentSector > secPerCluster)
{
GoToNoCluster(++cluster_No);
}
ReadSector(FileCurrentSector,iob); //read new sector
buffoffset = 0;
}while(bytecount < count);
return(count);
}
else return(0);
}
#endif //DOS_READ
//###########################################################
//open a file for reading OR writing, NOT both !
unsigned char fopen(char *name, unsigned char flag)
//###########################################################
{
#ifdef DOS_WRITE
unsigned long tmp;
#endif //DOS_WRITE
FileBytePerCluster = BYTE_PER_SEC * secPerCluster; //bytes per cluster
FileClusterCount = 0;
#ifdef DOS_READ
if(flag==F_READ)
{
if(FindName(name)==FULL_MATCH) //file MUST exist for reading
{
FilePosition = 0; //actual read position
FileCurrentCluster = FileFirstCluster;
FileFlag = flag; //needed for fclose
File1stClusterSector = GetFirstSectorOfCluster(FileFirstCluster);
FileCurrentSector = File1stClusterSector;
ReadSector(FileCurrentSector,iob); //read first sector of file
return F_OK; //give back something above zero
}
}
#endif //DOS_READ
#ifdef DOS_WRITE
if(flag==F_WRITE)
{
//if file exists, open it and spool to end of file to append data
if(FindName(name)==FULL_MATCH)
{
tmp=FileFirstCluster;
while(tmp<endofclusterchain) //go to end of cluster chain
{
tmp=GetNextClusterNumber(tmp);
if(tmp<endofclusterchain)
{
FileCurrentCluster=tmp;
FileClusterCount+=FileBytePerCluster;
}
}
tmp=FileSize-FileClusterCount;
File1stClusterSector=GetFirstSectorOfCluster(FileCurrentCluster);
FileCurrentSector=File1stClusterSector;
FileCurrentSector+= tmp / BYTE_PER_SEC;
ReadSector(FileCurrentSector,iob); //read first sector of file
}
else //make a new file
{
MakeFileName(name,FileName,FileExt); //Split into name and extension
if(MakeNewFileEntry()) //file does not exist, try to make new file in currentdir
{
FileCurrentCluster=FileFirstCluster;
File1stClusterSector=GetFirstSectorOfCluster(FileFirstCluster);
FileCurrentSector=File1stClusterSector;
ReadSector(FileCurrentSector,iob); //read first sector of file
}
else
{
FileFlag=0; //needed for fclose
return F_ERROR; //new file could not be made
}
}
FileFlag=flag; //needed for fclose
return F_OK; //file is open for writing
}//if(flag==F_WRITE)
#endif //DOS_WRITE
return F_ERROR; //something went wrong
}
//###########################################################
// close the file
// no error codes
void fclose(void)
//###########################################################
{
#ifdef DOS_READ
if(FileFlag==F_READ)
{
}
#endif //DOS_READ
#ifdef DOS_WRITE
if(FileFlag==F_WRITE)
{
fflush(); //write last sector used to CF and update filesize, filetime
}
#endif //DOS_WRITE
FileFlag=0; //a second fclose should do nothing
//reading and writing disabled
}
#ifdef DOS_WRITE
//###########################################################
// force writing last data written into sectorbuffer to be
// stored into CF without fclose(). direntry will also be
// updated.
void fflush(void)
//###########################################################
{
if(FileFlag==0) return; //don't write if file is closed
#ifdef USE_FATBUFFER
if(FATStatus>0)
{
WriteSector(FATCurrentSector,fatbuf); // write the FAT buffer
FATStatus=0;
}
#endif
WriteSector(FileCurrentSector,iob); //write last sector used
//update file entry filesize and date/time
UpdateFileEntry();
}
#endif //DOS_WRITE
//############################################################
// search for a filename or directoryname in current directory
unsigned char FindName(char *name)
//############################################################
{
unsigned char result;
if(FileFlag>0) return NO_MATCH; //don't search if a file is open
if(FirstDirCluster<2)
{
result=ScanRootDir(name);
}
else
{
result=ScanSubDir(FirstDirCluster,name);
}
return result;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -