Gert van der Knokke
/
C1541III
C1541-III mbed edition
Embed:
(wiki syntax)
Show/hide line numbers
fat.c
00001 /*-----------------------------------------------------------------------------------*/ 00002 /* This is a simple FAT16 handler. It works on a sector basis to allow fastest acces */ 00003 /* on disk images. */ 00004 /* */ 00005 /* Attention: when using Roadkill sector editor, chose the physical disk, and not the*/ 00006 /* drive number, otherwise the calculated sectors will not allways be the identical */ 00007 /*-----------------------------------------------------------------------------------*/ 00008 /* History: 00009 2008-02-08 fixed the problem regarding the backwards searching within subdirectories 00010 As this only is a problem with the use of the buttons... it was discovered at the last moment and now it is fixed. Subdirectories are now FULLY functional <hurray> 00011 2008-02-01 improved filesearch routine for subdirectory support, it appears to work 00012 2008-01-18 worked on opendirectory 00013 2008-01-14 corrected a small bug, because of the ASCII to PETSCII conversiuon, the calculation of the 8.3 checksum was incorrect 00014 by using the RAW-data (unconverted filename) the checksum can be calculated as it should and it all works while keeping readable characters on your retro computer 00015 2008-01-09 improved routine opensubdirectory(), suddenly it all works (hurray) 00016 2008-01-07 added routine opensubdirectory(), this makes suport of subdirectories a fact 00017 2007-12-20 added ASCII to PETSCII routines 00018 2007-12-19 playing with longfilenames 00019 2007-04-07 Mattias Olsson reported the following bugfix: 00020 By changing every occurrence of: sb+=clustersize*(file->cluster-2); 00021 to : sb+=(unsigned long)clustersize*(file->cluster-2); 00022 I can now load every file on the card. This bug caused problem when a lot of files were stored on the card (i.e. more then 340). 00023 Thanks Mattias, this saved me a lot of work, these bugs are the worst to fix. 00024 2006-12-15 fixed a small bug important bug in the FATSTART calculation (566 and 567 instead of 556 and 557) 00025 depending on your card it should not cause to much trouble... 00026 2006-09-03 renamed "databuffer" to "block_buffer" since this is a more appropriate name 00027 2006-08-21 added more debugging info in order to find the problem regarding the problems with some card not being supported... 00028 2006-04-11 improved 'FindDrive' routine to support cards without a partition table 00029 2006-02-03 added filesize to file structure (userfull for simple and quick file type validation of fixedsize files (i.e. D64-files)) 00030 2006-02-02 improvements in code layout... i.o.w. making it more readable 00031 2006-02-02 also the sector number is relevant... fixed it 00032 2006-02-01 added cache-ing regarding sector locations 00033 2006-01-31 worked out how to write the byte addressable read routine 00034 2006-01-29 added first steps for byte addressable read routine (read X bytes from startaddress Y) 00035 2005-12-23 added current file search option 00036 2005-12-11 first version, ported from FAT1618.C 00037 */ 00038 00039 /* TO DO: 00040 ------ 00041 - FileSectorScan(struct file2TYPE *file) routine iets aanpassen zodat we niet falen op de theoretisch laatste 'filenextsector' 00042 */ 00043 00044 /*----------------------------------------------------------------------------------*/ 00045 00046 /*--------------------------------------------------------*/ 00047 /* includes */ 00048 /*--------------------------------------------------------*/ 00049 #include <stdio.h> 00050 #include <main.h> 00051 #include <ata.h> 00052 #include <fat.h> 00053 00054 /*--------------------------------------------------------*/ 00055 /* constants */ 00056 /*--------------------------------------------------------*/ 00057 #define FALSE 0 /*FALSE*/ 00058 #define TRUE 1 /*TRUE*/ 00059 00060 /*Since the size of a D64 file is fixed the number of sectors required for a D64 file is also fixed*/ 00061 /*In order to keep compatibillity with most of the .D64 formats we must be able to handle the biggest,*/ 00062 /*so thats 40tracks including error bytes*/ 00063 #define D64FileConsistsOfSectors 386 /*(768(40tracks disk) * 256(bytes per block)) / 2 = 384 x 512(bytes per block), including the 768 error bytes (1.5x512) that would make a total of 386 blocks*/ 00064 00065 /*--------------------------------------------------------*/ 00066 /* globals */ 00067 /*--------------------------------------------------------*/ 00068 static unsigned long fatstart; /*start LBA of first FAT table*/ 00069 static unsigned char fatno; /*number of FAT tables*/ 00070 static unsigned long datastart; /*start LBA of data field*/ 00071 static unsigned long rootstart; /*start LBA of rootdirectory table*/ 00072 static unsigned short direntrys; /*number of entry's in directory table*/ 00073 static unsigned short direntrys_root; /*number of entry's in directory table*/ 00074 static unsigned char clustersize; /*size of a cluster in blocks*/ 00075 static unsigned short subdircluster_start; /*starting cluster of subdirectory*/ 00076 static unsigned short subdirsec_start; /*starting cluster of subdirectory*/ 00077 #define bit bool 00078 static bit root; 00079 00080 00081 unsigned short clusterlocationcache[D64FileConsistsOfSectors]; /*cache for the sector locations within the D64 file as stored in the Fat16*/ 00082 00083 /*--------------------------------------------------------*/ 00084 /* local functions */ 00085 /*--------------------------------------------------------*/ 00086 00087 unsigned char ASCII_to_PETSCII(unsigned char ASCII); 00088 00089 /*****************************************************************************************************************/ 00090 /*****************************************************************************************************************/ 00091 00092 /*FindDrive checks if a card is present. if a card is present it will check for 00093 a valid FAT16 primary partition*/ 00094 unsigned char FindDrive(void) 00095 { 00096 unsigned char error_code; 00097 unsigned long fatsize; /*size of fat*/ 00098 unsigned long dirsize; /*size of directory region in sectors*/ 00099 00100 error_code = AtaReadSector(0,block_buffer); /*read partition sector*/ 00101 if (error_code != TRUE) 00102 { 00103 return(error_code); 00104 } 00105 00106 /*Check for partition table, when this can not be found then set "fatstart=0" (to support cards (SUPERFLOPPY's) that have no partition table) and to support extended partitions*/ 00107 if(block_buffer[450]!=0x04 && block_buffer[450]!=0x05 && block_buffer[450]!=0x06)/*check partition type*/ 00108 fatstart=0; 00109 else if(block_buffer[510]!=0x55 || block_buffer[511]!=0xaa) /*check signature*/ 00110 fatstart=0; 00111 else 00112 { 00113 fatstart=(unsigned long)block_buffer[454]; /*get start of first partition*/ 00114 fatstart+=(unsigned long)block_buffer[455]*256; 00115 fatstart+=(unsigned long)block_buffer[456]*65536; 00116 fatstart+=(unsigned long)block_buffer[457]*16777216; 00117 } 00118 00119 if(!AtaReadSector(fatstart,block_buffer)) /*read boot sector*/ 00120 return(ERROR_FAT_READBOOTSECTOR); 00121 00122 if(block_buffer[0]!=0xe9 && block_buffer[0]!=0xeb) /*check for near-jump or short-jump opcode*/ 00123 return(ERROR_FAT_JUMPOPCODE); 00124 00125 if(block_buffer[11]!=0x00 || block_buffer[12]!=0x02) /*check if blocksize is really 512 bytes*/ 00126 return(ERROR_FAT_BLOCKSIZE); 00127 00128 if(block_buffer[21]!=0xf8) /*check medium descriptorbyte, must be 0xf8 for hard drive*/ 00129 return(ERROR_FAT_MEDIUM); 00130 00131 direntrys=block_buffer[17]+(block_buffer[18]*256); /*calculate drive's parameters from bootsector, first up is size of directory*/ 00132 direntrys_root = direntrys; 00133 dirsize=((direntrys*32)+511)/512; 00134 00135 fatstart=fatstart+block_buffer[14]+(block_buffer[15]*256); /*calculate start of FAT,size of FAT and number of FAT's*/ 00136 fatsize=block_buffer[22]+(block_buffer[23]*256); 00137 fatno=block_buffer[16]; 00138 00139 rootstart=fatstart+(fatno*fatsize); /*calculate start of root-directory*/ 00140 clustersize=block_buffer[13]; /*get clustersize*/ 00141 datastart=rootstart+dirsize; /*calculate start of data*/ 00142 root=TRUE; /*raise flag to indicate we are in the root directory*/ 00143 return(TRUE); 00144 } 00145 00146 /*this routine needs to be called when a subdirectory is entered*/ 00147 /*this routine re-calculates the current directroy pointers and registers to those of the (sub)directory to be opened*/ 00148 /*this routine returns TRUE when the subdirectory is a subdirectory and FALSE when it is root*/ 00149 unsigned char OpenSubDirectory(struct file2TYPE *file) 00150 { 00151 /*calculate the location of the first byte of the new (sub)directory*/ 00152 if(file->cluster == 0) /*check if the user requests the root directory*/ 00153 { /*---------------------------------------------*/ 00154 root=TRUE; /*raise flag to indicate we are in the root directory*/ 00155 direntrys = direntrys_root; 00156 return(FALSE); /*we are now back in root*/ 00157 } 00158 else 00159 { 00160 root=FALSE; /*lower flag to indicate we are NOT in the root directory*/ 00161 direntrys = 1000; /*a fixed value that is practically impossible to use on a CBM computer*/ 00162 subdircluster_start = file->cluster; /*starting cluster of subdirectory*/ 00163 subdirsec_start = file->sec; /*starting sector offset within cluster*/ 00164 return(TRUE); /*we are now in a subdirectory*/ 00165 } 00166 } 00167 00168 /*scan directory, yout must pass a file handle to this function*/ 00169 /*search modes: 0=first,1=next(8.3 AND LFN),2=previous(8.3 only),3=current*/ 00170 unsigned char FileSearch(struct file2TYPE *file, unsigned char mode) 00171 { 00172 static unsigned short subdircluster_current; /*current cluster of subdirectory*/ 00173 static unsigned short subdirsec_current; /*current sector offset within cluster*/ 00174 static unsigned char sectorcounter; /*a relative counter, to keep track of how many sectors we've read regarding this subdirectory*/ 00175 /*sectorcounter: this is an unsigned char, meaning that this limits a subdir to have "only" 255*16 8.3 file entries. Which is a lot for a retro computer*/ 00176 00177 unsigned long sf,sb; 00178 unsigned short i; 00179 unsigned char j; 00180 00181 unsigned short LFN_offset; 00182 unsigned char LFN_seq_nmbr; 00183 unsigned char LFN_string[27]; /*the length of the LFN name we use is max 26 characters (2 LFN entries)*/ 00184 unsigned char LFN_checksum[2]; /*since we use only two LFN entries, we only need to store 2 checksums*/ 00185 unsigned char REF_checksum; /*the checksum which is our reference*/ 00186 00187 LFN_checksum[0] = 0; /*clear the checksum value of the 1st LFN sequence*/ 00188 LFN_checksum[1] = 0; /*clear the checksum value of the 2nd LFN sequence*/ 00189 00190 sb=0; /*buffer is empty*/ 00191 if(mode==0) /*search for first entry*/ 00192 { /*----------------------*/ 00193 file->entry=0; 00194 if (root == FALSE) 00195 { 00196 file->cluster = subdircluster_start; /*reset the cluster pointer back to the beginning of the directory, otherwise we fail with the filenextsector routine*/ 00197 file->sec = subdirsec_start; /*starting sector offset within cluster*/ 00198 subdircluster_current = file->cluster; 00199 subdirsec_current = file->sec; 00200 sectorcounter = 0; 00201 } 00202 } 00203 else if(mode==1) /*search for next entry*/ 00204 { /*---------------------*/ 00205 file->entry++; 00206 } 00207 else if(mode==2) /*search for previous entry*/ 00208 { /*-------------------------*/ 00209 file->entry--; 00210 } 00211 00212 while(file->entry<direntrys) 00213 { 00214 if (root == TRUE) /*the root directory is one continuos chunk of entries*/ 00215 { /*----------------------------------------------------*/ 00216 sf=rootstart; /*calculate sector and offset*/ 00217 sf+=(file->entry)/16; /*16 entries fit into one sector, so when entry = 16 (or 32,48, etc), we need to load a new sector (indicated by SF incremented by one)*/ 00218 00219 if(sb!=sf) /*when buffer is empty or needs to be changed*/ 00220 { 00221 sb=sf; 00222 if(!AtaReadSector(sb,block_buffer)) 00223 return(FALSE); 00224 } 00225 } 00226 else /*subdirectory entries can be scattered all over the disk, so in order to determine where the next cluster is we need to lookup this info in the FAT*/ 00227 { /*--------------------------------------------------------------------------------------------------------------------------------------------------*/ 00228 if((mode==1) && (file->entry > 0) && (file->entry%16 == 0)) /*load sector if not in buffer*/ 00229 { 00230 file->cluster = subdircluster_current; /*retrieve the latest cluster value*/ 00231 file->sec = subdirsec_current; /*retrieve the latest sector value*/ 00232 if (FileNextSector(file) == FALSE) /*attention: screws up block_buffer!!*/ 00233 return(FALSE); 00234 sectorcounter++; /*another sector loaded, increment counter*/ 00235 subdircluster_current = file->cluster; /*save the new value for later*/ 00236 subdirsec_current = file->sec; /*save the new value for later*/ 00237 00238 if ((file->cluster & 0xFFF8) == 0xFFF8) /*check if this is the last cluster*/ 00239 { 00240 file->len=0; 00241 return(FALSE); 00242 } 00243 } 00244 00245 00246 if((mode==2) && ((file->entry + 1) > 0) && ((file->entry+1)%16 == 0)) /*load sector if not in buffer*/ 00247 { 00248 /*because directory are not designed to be read in a reverse direction, we need to rescan the previous clusterchain in order to find the previous cluster*/ 00249 /*this is the only way because FAT only stores the next cluster, which is useless if you want the previous. So we start at the first cluster and skip all cluster untill we reach the desired (previous from the current)*/ 00250 file->cluster = subdircluster_start; /*reset the cluster pointer back to the beginning of the directory, otherwise we fail with the filenextsector routine*/ 00251 file->sec = subdirsec_start; /*starting sector offset within cluster*/ 00252 if (sectorcounter > 0) 00253 { 00254 sectorcounter--; /*previous sector found, decrement counter*/ 00255 for(j=0;j<sectorcounter;j++) 00256 { 00257 if (FileNextSector(file) == FALSE) /*attention: screws up block_buffer!!*/ 00258 return(FALSE); 00259 } 00260 } 00261 subdircluster_current = file->cluster; /*save the new value for later*/ 00262 subdirsec_current = file->sec; /*save the new value for later*/ 00263 } 00264 00265 sf=datastart; /*start of data in partition*/ 00266 sf+=(unsigned long)clustersize*(subdircluster_current-2); /*cluster offset*/ 00267 sf+=(subdirsec_current%clustersize); /*sector offset in cluster*/ 00268 if(sb!=sf) /*when buffer is empty or needs to be changed*/ 00269 { 00270 sb=sf; 00271 if(!AtaReadSector(sb,block_buffer)) 00272 return(FALSE); 00273 } 00274 } 00275 00276 i=(file->entry%16)*32; /*i is the pointer that points to the address of the entry within the loaded sector*/ 00277 if(block_buffer[i+0x0b]==0x0f) /*check if this entry is an LFN entry*/ 00278 { 00279 //if(block_buffer[i]<=0x55) /*check the LFN sequence number the highest possible value would be 0x55 (20th entry which is the last entry (0x15 OR-ed with 0x40)*/ 00280 if(block_buffer[i]<=0x42) /*check the LFN sequence number. Although the highest possible value would be 0x55, this application only uses 2 LFN entries (26 chars), since we can only display 16 characters within a CBM directory*/ 00281 { 00282 LFN_seq_nmbr = block_buffer[i] & 0x3f; /*remove the possible 0x40 in order to keep the bare LFN sequence number*/ 00283 LFN_offset = (LFN_seq_nmbr * 13) - 13; 00284 00285 /*save the LFN characters to the correct location of our string*/ 00286 LFN_string[LFN_offset + 0] = block_buffer[i+0x01]; /*5 UTF characters of which we only use the first byte*/ 00287 LFN_string[LFN_offset + 1] = block_buffer[i+0x03]; 00288 LFN_string[LFN_offset + 2] = block_buffer[i+0x05]; 00289 LFN_string[LFN_offset + 3] = block_buffer[i+0x07]; 00290 LFN_string[LFN_offset + 4] = block_buffer[i+0x09]; 00291 00292 LFN_checksum[LFN_seq_nmbr-1] = block_buffer[i+0x0d];/*save the checksum*/ 00293 00294 LFN_string[LFN_offset + 5] = block_buffer[i+0x0e]; /*6 UTF characters of which we only use the first byte*/ 00295 LFN_string[LFN_offset + 6] = block_buffer[i+0x10]; 00296 LFN_string[LFN_offset + 7] = block_buffer[i+0x12]; 00297 LFN_string[LFN_offset + 8] = block_buffer[i+0x14]; 00298 LFN_string[LFN_offset + 9] = block_buffer[i+0x16]; 00299 LFN_string[LFN_offset + 10] = block_buffer[i+0x18]; 00300 00301 LFN_string[LFN_offset + 11] = block_buffer[i+0x1c]; /*2 UTF characters of which we only use the first byte*/ 00302 LFN_string[LFN_offset + 12] = block_buffer[i+0x1e]; 00303 00304 /*the following code is not required as we only use two LFN entries which we compare with a checksum later*/ 00305 /*the code below is left for reference for LFN filenames which must be longer then 26chars*/ 00306 // if(block_buffer[i]&0x40 == 0x40) /*check if this entry was the last LFN entry belonging to this file*/ 00307 // { /*we do this by checking if the 6st bit was set*/ 00308 // LFN_string[LFN_offset + 13] = 0; /*terminate string HERE*/ 00309 // } 00310 } 00311 } 00312 00313 if(block_buffer[i]!=0x00 && block_buffer[i]!=0xe5) /*check if valid file entry: 0x00 = entry is available*/ 00314 { /* 0xE5 = entry has been erased*/ 00315 if((block_buffer[i+0x0b]&0x0a)==0x00) /*check atributes: do not show hidden files, do not show volume labels, DO SHOW subdirectories*/ 00316 { 00317 for(j=0;j<11;j++) /*copy name (8.3)*/ 00318 file->name[j] = ASCII_to_PETSCII(block_buffer[i+j]); /*copy each character and substitute the following ASCII-chars to PETSCII alternatives. Because we convert it here, we do not have to convert it back in the file search routines which effectively results in simpler and (even better) shorter code*/ 00319 file->name[j]=0x00; /*terminate the string*/ 00320 00321 file->len=(unsigned long)block_buffer[j+28]; /*get length of file in sectors, maximum is 16Mbytes*/ 00322 file->len+=(unsigned short)block_buffer[i+29]*256; 00323 file->len+=511; 00324 file->len/=512; 00325 file->len+=(unsigned long)block_buffer[i+30]*128; 00326 00327 file->cluster=(unsigned long)block_buffer[i+26]+((unsigned long)block_buffer[i+27]*256); /*get first cluster of file*/ 00328 file->size = (unsigned long)block_buffer[i+28]+((unsigned long)block_buffer[i+29]*256)+((unsigned long)block_buffer[i+30]*65536)+((unsigned long)block_buffer[i+31]*16777216); 00329 file->sec=0; /*reset sector index*/ 00330 00331 REF_checksum = 0; /*calculate the checksum of the 8.3 filename*/ 00332 for (j=0;j<11;j++) /*this checksum is our reference to which we compare the LFN checksum(s) with*/ 00333 REF_checksum = (((REF_checksum & 1) << 7) | ((REF_checksum & 0xfe) >> 1)) + block_buffer[i+j]; 00334 00335 if(LFN_checksum[0] == REF_checksum) /*using the checksum we determine wether we use the gathered LFN information*/ 00336 { 00337 for(j=0;j<13;j++) /*copy the first 13 characters of the LFN string (maintain case)*/ 00338 file->name_lfn[j] = ASCII_to_PETSCII(LFN_string[j]); /*substitute the following ASCII-chars to PETSCII alternatives. Because we convert it here, we do not have to convert it back in the file search routines which effectively results in simpler and (even better) shorter code*/ 00339 00340 if(LFN_checksum[1] == REF_checksum) 00341 { 00342 for(j=12;j<26;j++) /*copy the last few characters of the LFN string so that we have a total of max. 16 characters (maintain case)*/ 00343 file->name_lfn[j] = ASCII_to_PETSCII(LFN_string[j]); /*substitute the following ASCII-chars to PETSCII alternatives. Because we convert it here, we do not have to convert it back in the file search routines which effectively results in simpler and (even better) shorter code*/ 00344 file->name_lfn[26]=0x00; /*terminate string*/ 00345 } 00346 else 00347 file->name_lfn[13]=0x00; /*terminate string*/ 00348 } 00349 else 00350 { 00351 file->name_lfn[0]=0; /*clear the LFN string by terminating at the first char*/ 00352 } 00353 00354 return(TRUE); 00355 } 00356 } 00357 if(mode==2) 00358 file->entry--; 00359 else 00360 file->entry++; 00361 } 00362 file->len=0; 00363 return(FALSE); 00364 } 00365 00366 00367 /*this routine will scan for the startaddress of all possible sectors that hold a D64 file*/ 00368 unsigned char FileSectorScan(struct file2TYPE *file) 00369 { 00370 unsigned int lp; 00371 00372 for(lp=0; lp<(D64FileConsistsOfSectors-1); lp++) 00373 { 00374 clusterlocationcache[lp] = file->cluster; 00375 if (FileNextSector(file) == FALSE) /*attention: screws up block_buffer!!*/ 00376 return(FALSE); 00377 } 00378 clusterlocationcache[D64FileConsistsOfSectors-1] = file->cluster; 00379 00380 return(TRUE); 00381 } 00382 00383 00384 /*point to next sector in file*/ 00385 unsigned char FileNextSector(struct file2TYPE *file) 00386 { 00387 unsigned long sb; 00388 unsigned short i; 00389 00390 file->sec++; /*increment sector index*/ 00391 if((file->sec%clustersize)==0) /*if we are now in another cluster, look up cluster*/ 00392 { 00393 sb=fatstart; /*calculate sector that contains FAT-link*/ 00394 sb+=(file->cluster/256); 00395 i=(file->cluster%256); /*calculate offset*/ 00396 i*=2; 00397 00398 if(!AtaReadSector(sb,block_buffer)) /*read sector of FAT*/ 00399 return(FALSE); 00400 00401 file->cluster=((unsigned short)block_buffer[i+1]*256)+(unsigned short)block_buffer[i]; /*get FAT-link*/ 00402 } 00403 return(TRUE); 00404 } 00405 00406 /*read current sector into buffer*/ 00407 unsigned char FileReadSector(struct file2TYPE *file) 00408 { 00409 unsigned long sb; 00410 00411 sb=datastart; /*start of data in partition*/ 00412 sb+=(unsigned long)clustersize*(file->cluster-2); /*cluster offset*/ 00413 sb+=(file->sec%clustersize); /*sector offset in cluster*/ 00414 00415 if(!AtaReadSector(sb,block_buffer)) /*read the data from the sector*/ 00416 return(FALSE); 00417 else 00418 return(TRUE); 00419 } 00420 00421 /*read specified sector into buffer*/ 00422 unsigned char FileReadSector_X(struct file2TYPE *file, unsigned long block) 00423 { 00424 unsigned long sb; 00425 00426 file->cluster = clusterlocationcache[block]; /*retrieve the sector address from the cache*/ 00427 file->sec = block; /*we need to indicate the exact sector number within this cluster*/ 00428 00429 sb=datastart; /*start of data in partition*/ 00430 sb+=(unsigned long)clustersize*(file->cluster-2); /*cluster offset*/ 00431 sb+=(file->sec%clustersize); /*sector offset in cluster*/ 00432 // sb+=pt; /*add the pointer offset to the absolute address of the data position as stored on the card*/ 00433 00434 if(!AtaReadSector(sb,block_buffer)) /*read the data from the sector*/ 00435 return(FALSE); 00436 else 00437 return(TRUE); 00438 } 00439 00440 /*Read xxx bytes from a sector into a specified buffer*/ 00441 /*When only one or more bytes are required, then this routine comes in handy...*/ 00442 unsigned char FileRead_X_Bytes(struct file2TYPE *file, unsigned long startaddress, unsigned int NmbrOfBytes) 00443 { 00444 unsigned long lp, pt, bytesfromcurrentsector, bytesfromnextsector; 00445 unsigned long sb; 00446 00447 lp = startaddress/512L; /*determine how many (512byte) sectors we must skip before we find our desired byte (512=size of a MMC and SD-card sector)*/ 00448 pt = startaddress%512L; /*the byte we are looking for is pointed to by "cardbuffer_pnt"*/ 00449 00450 /*check if the bytes we want to read beyond the sector border*/ 00451 if ((pt + NmbrOfBytes) < 512L) 00452 { 00453 bytesfromcurrentsector = NmbrOfBytes; /*the number of bytes that can be read from the now selected sector*/ 00454 bytesfromnextsector = 0; /*the number of bytes that can cannot be read from the now selected sector and must be read from the next sector*/ 00455 } 00456 else 00457 { 00458 bytesfromcurrentsector = 512L - pt; 00459 bytesfromnextsector = NmbrOfBytes - bytesfromcurrentsector; 00460 } 00461 00462 file->cluster = clusterlocationcache[lp]; /*retrieve the sector address from the cache*/ 00463 file->sec = lp; /*we need to indicate the exact sector number within this cluster*/ 00464 00465 sb=datastart; /*start of data in partition*/ 00466 sb+=(unsigned long)clustersize*(file->cluster-2); /*cluster offset*/ 00467 sb+=(file->sec%clustersize); /*sector offset in cluster*/ 00468 // sb+=pt; /*add the pointer offset to the absolute address of the data position as stored on the card*/ 00469 if(!AtaRead_X_Bytes(sb, pt, block_buffer, bytesfromcurrentsector)) /*read data (a part of the current sector) from drive*/ 00470 return(FALSE); 00471 00472 if (bytesfromnextsector !=0) 00473 { 00474 file->cluster = clusterlocationcache[lp+1]; /*retrieve the sector address from the cache*/ 00475 file->sec = lp+1; /*we need to indicate the exact sector number within this cluster*/ 00476 00477 sb=datastart; /*start of data in partition*/ 00478 sb+=(unsigned long)clustersize*(file->cluster-2); /*cluster offset*/ 00479 sb+=(file->sec%clustersize); /*sector offset in cluster*/ 00480 if(!AtaRead_X_Bytes(sb, 0, &block_buffer[bytesfromcurrentsector+1], bytesfromnextsector)) /*read data (a part of the current sector) from drive*/ 00481 return(FALSE); 00482 } 00483 return(TRUE); 00484 } 00485 00486 /*Write the specified block to the card*/ 00487 unsigned char FileWriteSector_X(struct file2TYPE *file, unsigned long block) 00488 { 00489 unsigned long sb; 00490 00491 file->cluster = clusterlocationcache[block]; /*retrieve the sector address from the cache*/ 00492 file->sec = block; /*we need to indicate the exact sector number within this cluster*/ 00493 00494 sb=datastart; /*start of data in partition*/ 00495 sb+=(unsigned long)clustersize*(file->cluster-2); /*cluster offset*/ 00496 sb+=(file->sec%clustersize); /*sector offset in cluster*/ 00497 // sb+=pt; /*add the pointer offset to the absolute address of the data position as stored on the card*/ 00498 if(!AtaWriteSector(sb,block_buffer)) /*write data to medium*/ 00499 return(FALSE); 00500 00501 return(TRUE); 00502 } 00503 00504 00505 /***************************************************************************************************************************************/ 00506 00507 /*convert ASCII to PETSCII: substitute the following ASCII-chars to PETSCII alternatives*/ 00508 unsigned char ASCII_to_PETSCII(unsigned char ASCII) 00509 { 00510 unsigned char PETSCII; 00511 00512 if ((ASCII >= 'a') && (ASCII <= 'z')) /*check if the ASCII character is lowercase*/ 00513 { 00514 ASCII = ASCII - 0x20; /*convert lowercase to UPPERCASE*/ 00515 } 00516 00517 switch (ASCII) 00518 { 00519 case 0x5e: /*^-sign (caret)*/ 00520 { 00521 PETSCII = 0xb1; /*PETSCII small 4 pixel upsidedown T located at the top*/ 00522 break; 00523 } 00524 00525 case 0x5F: /*_-sign (underscore)*/ 00526 { 00527 PETSCII = 0xa4; /*PETSCII underscore*/ 00528 break; 00529 } 00530 00531 case 0x60: /*'-sign (single quote)*/ 00532 { 00533 PETSCII = 0xbe; /*PETSCII 4pixel square located top left*/ 00534 break; 00535 } 00536 00537 case 0x7b: /*{-sign (bracket left)*/ 00538 { 00539 PETSCII = 0x5b; /*PETSCII squared bracket left*/ 00540 break; 00541 } 00542 00543 case 0x7d: /*}-sign (bracket right)*/ 00544 { 00545 PETSCII = 0x5d; /*PETSCII squared bracket right*/ 00546 break; 00547 } 00548 00549 case 0x7e: /*~-sign (tilde as we say in Dutch)*/ 00550 { 00551 PETSCII = 0xA8; /*PETSCII tilde*/ 00552 break; 00553 } 00554 00555 default: /*in all other undefined situations leave the character "as it was"*/ 00556 { 00557 PETSCII = ASCII; 00558 break; 00559 } 00560 } 00561 return(PETSCII); 00562 } 00563 00564 /***************************************************************************************************************************************/ 00565 /***************************************************************************************************************************************/ 00566 /***************************************************************************************************************************************/ 00567 /***************************************************************************************************************************************/ 00568 00569
Generated on Tue Jul 26 2022 04:14:07 by 1.7.2