📄 fileio.c
字号:
* PreCondition: FILEopen in the read mode has been executed
*
* Input: fo - File to be read
* pDest - Destination buffer for read bytes
* count - Number of bytes to be read
* pBytesRead - Number of bytes read
*
* Output: CE_GOOD - my_fread successful
* CE_EOF - End of file reached
*
*
* Side Effects: None
*
* Overview: Reads data from a file into destination buffer
*
* Note: None
*****************************************************************************/
CETYPE __fread( MYFILE *fo, BYTE *pDest, WORD count, WORD *pBytesRead )
{
DISK *dsk; // Disk structure
DWORD seek, sec_sel;
WORD pos; //position within sector
CETYPE error = CE_GOOD;
dsk = (DISK *)fo->dsk;
pos = fo->pos;
seek = fo->seek;
*pBytesRead = 0;
if( fo->Flags.write )
return CE_WRITEONLY;
// if it not my buffer, then get it from the disk.
if( gBufferOwner != fo &&
pos != MEDIA_SECTOR_SIZE )
{
gBufferOwner = fo;
sec_sel = Cluster2Sector(dsk,fo->ccls);
sec_sel += (WORD)fo->sec; // add the sector number to it
if( !SECTORread( sec_sel, dsk->buffer) )
return CE_BAD_SECTOR_READ;
}
//loop reading (count) bytes
while( count )
{
if( seek == fo->size )
{ error = CE_EOF;
break; }
// In my_fopen, pos is init to 0 and the sect is loaded
if( pos == MEDIA_SECTOR_SIZE )
{
// reset position
pos = 0;
// point to the next sector
fo->sec++;
// get a new cluster if necessary
if( fo->sec == dsk->SecPerClus )
{
fo->sec = 0;
if( (error = FILEget_next_cluster( fo, 1)) != CE_GOOD )
break;
}
sec_sel = Cluster2Sector(dsk,fo->ccls);
sec_sel += (WORD)fo->sec; // add the sector number to it
gBufferOwner = fo;
if( !SECTORread( sec_sel, dsk->buffer) )
{ error = CE_BAD_SECTOR_READ;
break; }
}
// copy one byte at a time
*pDest = RAMread( dsk->buffer, pos++ );
pDest++;
seek++;
(*pBytesRead)++;
count--;
}
// save off the positon
fo->pos = pos;
// save off the seek
fo->seek = seek;
return(error);
} // my_fread
/******************************************************************************
* Function: BYTE FILEget_next_cluster(FILEOBJ fo, WORD n)
*
* PreCondition: Disk mounted, fo contains valid file data
*
* Input: fo - File structure
* n - number of links in the FAT cluster chain to jump
* through; n == 1 - next cluster in the chain
*
* Output: CE_GOOD - Operation successful
* CE_BAD_SECTOR_READ - A bad read occured of a sector
* CE_INVALID_CLUSTER - Invalid cluster value > maxcls
* CE_FAT_EOF - Fat attempt to read beyond EOF
*
*
* Side Effects: None
*
* Overview: Steps through a chain of clusters
*
* Note: None
*****************************************************************************/
BYTE FILEget_next_cluster(FILEOBJ fo, WORD n)
{
WORD c, c2;
BYTE error = CE_GOOD;
DISK * disk;
disk = fo->dsk;
// loop n times
do {
// get the next cluster link from FAT
c2 = fo->ccls;
if ( (c = FATread( disk, c2)) == FAIL)
error = CE_BAD_SECTOR_READ;
else
{
// check if cluster value is valid
if ( c >= disk->maxcls)
{
error = CE_INVALID_CLUSTER;
}
// compare against max value of a cluster in FAT
c2 = LAST_CLUSTER;
// return if eof
if ( c >= c2) // check against eof
{
error = CE_FAT_EOF;
}
}
// update the MYFILE structure
fo->ccls = c;
} while (--n > 0 && error == CE_GOOD);// loop end
return(error);
} // get next cluster
/******************************************************************************
* Function: BYTE Write_File_Entry( FILEOBJ fo, WORD * curEntry)
*
* PreCondition: Disk mounted, fo contains valid file data
*
* Input: fo - File structure
* curEntry - Write destination
*
* Output: TRUE - Operation successful
* FALSE - Operation failed
*
* Side Effects: None
*
* Overview: Write the buffer into the current entry
*
* Note: None
*****************************************************************************/
BYTE Write_File_Entry( FILEOBJ fo, WORD * curEntry)
{
DISK *dsk;
BYTE status;
BYTE offset2;
DWORD sector;
WORD ccls;
dsk = fo->dsk;
// get the cluster of this entry
ccls = fo->dirccls;
offset2 = (*curEntry >> 4);
// if its not the root, it works cluster based
if(ccls != 0)
offset2 = offset2 % (dsk->SecPerClus);
sector = Cluster2Sector(dsk,ccls);
// Now write it
if ( !SECTORwrite( sector + offset2, dsk->buffer))
status = FALSE;
else
status = TRUE;
return(status);
} // Write_File_Entry
/******************************************************************************
* Function: WORD FATwrite( DISK *dsk, WORD cls, WORD v)
*
* PreCondition: Disk mounted, fo contains valid file data
*
* Input: dsk - Disk structure
* cls - Current cluster
* v - New value
*
* Output: c - Cluster value
* FAIL - Operation failed
*
* Side Effects: None
*
* Overview: Write a cluster link in all FAT copies
*
* Note: None
*****************************************************************************/
WORD FATwrite( DISK *dsk, WORD cls, WORD v)
{
BYTE i;
WORD p, c;
DWORD l, li;
if ( dsk->type != FAT16)
return FAIL;
gBufferOwner = NULL;
// get address of current cluster in fat
p = cls * 2; // always even
// cluster = 0xabcd
// packed as: 0 | 1 | 2 | 3 |
// word p 0 1 | 2 3 | 4 5 | 6 7 |..
// cd ab| cd ab| cd ab| cd ab|
// load the fat sector containing the cluster
l = dsk->fat + (p >> 9 );
p &= 0x1ff;
if( !SECTORread( l, dsk->buffer) )
return FAIL;
// get the next cluster value
RAMwrite( dsk->buffer, p, v); // lsb
RAMwrite( dsk->buffer, p+1, (v>>8));// msb
// update all FAT copies
for ( i = 0, li = l; i < dsk->fatcopy; i++, li += dsk->fatsize)
if ( !SECTORwrite( l, dsk->buffer) )
return FAIL;
// Normalize it so 0xFFFF is an error
if(c >= LAST_CLUSTER_FAT16)
c = LAST_CLUSTER;
return c;
} // FATwrite
/******************************************************************************
* Function: BYTE FAT_erase_cluster_chain (WORD cluster, DISK * dsk)
*
* PreCondition: Disk mounted, should be called from FILEerase
*
* Input: cluster - The cluster number
* dsk - The disk structure
*
* Output: TRUE - Operation successful
* FALSE - Operation failed
*
*
* Side Effects: None
*
* Overview: Erase the cluster chain
*
* Note: None
*****************************************************************************/
BYTE FAT_erase_cluster_chain (WORD cluster, DISK * dsk)
{
WORD c,c2;
enum _status {Good, Fail, Exit}status;
status = Good;
// Make sure there is actually a cluster assigned
if(cluster == 0 || cluster == 1)
{
status = Exit;
}
else
{
while(status == Good)
{
// Get the FAT entry
if((c = FATread( dsk, cluster)) == FAIL)
status = Fail;
else
{
if(c == 0 || c == 1)
{
status = Exit;
}
else
{
// compare against max value of a cluster in FATxx
c2 = LAST_CLUSTER;
// look for the last cluster in the chain
if ( c >= c2)
status = Exit;
// Now erase this FAT entry
if(FATwrite(dsk, cluster, CLUSTER_EMPTY) == FAIL)
status = Fail;
// now update what the current cluster is
cluster = c;
}
}
}// while status
}// cluster == 0
if(status == Exit)
return(TRUE);
else
return(FALSE);
} // Erase cluster
/******************************************************************************
* Function: DIRENTRY Cache_File_Entry( FILEOBJ fo, WORD * curEntry, BYTE ForceRead)
*
* PreCondition: Disk mounted
*
* Input: fo - File information
* curEntry - Location of the sector
* ForceRead - Forces loading of a new sector of the root
*
* Output: DIRENTRY - Sector loaded
*
* Side Effects: None
*
* Overview: Get the sector loaded as pointed to by curEntry
*
* Note: Should not be called by user
*****************************************************************************/
DIRENTRY Cache_File_Entry( FILEOBJ fo, WORD * curEntry, BYTE ForceRead)
{
DIRENTRY dir;
DISK *dsk;
DWORD sector;
WORD cluster;
WORD ccls;
BYTE offset2;
BYTE numofclus;
dsk = fo->dsk;
// get the base sector of this directory
cluster = fo->dirclus;
ccls = fo->dirccls;
// figure out the offset from the base sector
offset2 = (*curEntry >> 4);
offset2 = offset2; // emulator issue
// if its the root its not cluster based
if(cluster != 0)
offset2 = offset2 % (dsk->SecPerClus); // figure out the offset
// check if a new sector of the root must be loaded
if (ForceRead || (*curEntry & 0xf) == 0) // only 16 entries per sector
{
// see if we have to load a new cluster
if((offset2 == 0 && (*curEntry) > DIRENTRIES_PER_SECTOR) || ForceRead)
{
if(cluster == 0)
{
ccls = 0;
}
else
{
if(ForceRead)
numofclus = ((WORD)(*curEntry) / (WORD)(((WORD)DIRENTRIES_PER_SECTOR) * (WORD)dsk->SecPerClus));
else
numofclus = 1;
// move to the correct cluster
while(numofclus)
{
ccls = FATread(dsk, ccls);
if(ccls >= LAST_CLUSTER)
break;
else
numofclus--;
}
}
}
// see if that we have a valid cluster number
if(ccls < LAST_CLUSTER)
{
fo->dirccls = ccls; // write it back
sector = Cluster2Sector(dsk,ccls);
// see if we are root and about to go pass our boundaries
if(ccls == 0 && (sector + offset2) >= dsk->data)
{
dir = ((DIRENTRY)NULL); // reached the end of the root!
}
else
{
gBufferOwner = NULL;
if ( SECTORread( sector + offset2, dsk->buffer) != TRUE)
dir = ((DIRENTRY)NULL);
else
{
// now figure out the pointer if its a forced read
if(ForceRead)
dir = (DIRENTRY)((DIRENTRY)dsk->buffer) + ((*curEntry)%DIRENTRIES_PER_SECTOR);
else
dir = (DIRENTRY)dsk->buffer;
}
}
}
else
dir = ((DIRENTRY)NULL);
}
else
dir = (DIRENTRY)((DIRENTRY)dsk->buffer) + ((*curEntry)%DIRENTRIES_PER_SECTOR);
return(dir);
} // Cache_File_Entry
/******************************************************************************
* Function: CETYPE __fwrite( MYFILE* fo, void * src, WORD count, WORD* pBytesWritten )
*
* PreCondition: File opened in WRITE mode
*
* Input: fo - Pointer to file structure
* src - Pointer to source buffer
* count - Number of bytes to transfer
* pBytesWritten - The number of bytes that have been written
*
* Output: CE_GOOD - Write successful
* CE_WRITE_ERROR - Write failed
* Default - Number of bytes that could not be written
*
* Side Effects: None
*
* Overview: Write file
*
* Note: None
*****************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -