C1541-III mbed edition

Dependencies:   mbed

Committer:
gertk
Date:
Mon Aug 22 21:11:59 2011 +0000
Revision:
1:0cbbb66a6100
Parent:
0:28557a4d2215
updated the nRESET pin to an interrupt capable pin (p29)

Who changed what in which revision?

UserRevisionLine numberNew contents of line
gertk 0:28557a4d2215 1 /*-----------------------------------------------------------------------------------*/
gertk 0:28557a4d2215 2 /* This is a simple FAT16 handler. It works on a sector basis to allow fastest acces */
gertk 0:28557a4d2215 3 /* on disk images. */
gertk 0:28557a4d2215 4 /* */
gertk 0:28557a4d2215 5 /* Attention: when using Roadkill sector editor, chose the physical disk, and not the*/
gertk 0:28557a4d2215 6 /* drive number, otherwise the calculated sectors will not allways be the identical */
gertk 0:28557a4d2215 7 /*-----------------------------------------------------------------------------------*/
gertk 0:28557a4d2215 8 /* History:
gertk 0:28557a4d2215 9 2008-02-08 fixed the problem regarding the backwards searching within subdirectories
gertk 0:28557a4d2215 10 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>
gertk 0:28557a4d2215 11 2008-02-01 improved filesearch routine for subdirectory support, it appears to work
gertk 0:28557a4d2215 12 2008-01-18 worked on opendirectory
gertk 0:28557a4d2215 13 2008-01-14 corrected a small bug, because of the ASCII to PETSCII conversiuon, the calculation of the 8.3 checksum was incorrect
gertk 0:28557a4d2215 14 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
gertk 0:28557a4d2215 15 2008-01-09 improved routine opensubdirectory(), suddenly it all works (hurray)
gertk 0:28557a4d2215 16 2008-01-07 added routine opensubdirectory(), this makes suport of subdirectories a fact
gertk 0:28557a4d2215 17 2007-12-20 added ASCII to PETSCII routines
gertk 0:28557a4d2215 18 2007-12-19 playing with longfilenames
gertk 0:28557a4d2215 19 2007-04-07 Mattias Olsson reported the following bugfix:
gertk 0:28557a4d2215 20 By changing every occurrence of: sb+=clustersize*(file->cluster-2);
gertk 0:28557a4d2215 21 to : sb+=(unsigned long)clustersize*(file->cluster-2);
gertk 0:28557a4d2215 22 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).
gertk 0:28557a4d2215 23 Thanks Mattias, this saved me a lot of work, these bugs are the worst to fix.
gertk 0:28557a4d2215 24 2006-12-15 fixed a small bug important bug in the FATSTART calculation (566 and 567 instead of 556 and 557)
gertk 0:28557a4d2215 25 depending on your card it should not cause to much trouble...
gertk 0:28557a4d2215 26 2006-09-03 renamed "databuffer" to "block_buffer" since this is a more appropriate name
gertk 0:28557a4d2215 27 2006-08-21 added more debugging info in order to find the problem regarding the problems with some card not being supported...
gertk 0:28557a4d2215 28 2006-04-11 improved 'FindDrive' routine to support cards without a partition table
gertk 0:28557a4d2215 29 2006-02-03 added filesize to file structure (userfull for simple and quick file type validation of fixedsize files (i.e. D64-files))
gertk 0:28557a4d2215 30 2006-02-02 improvements in code layout... i.o.w. making it more readable
gertk 0:28557a4d2215 31 2006-02-02 also the sector number is relevant... fixed it
gertk 0:28557a4d2215 32 2006-02-01 added cache-ing regarding sector locations
gertk 0:28557a4d2215 33 2006-01-31 worked out how to write the byte addressable read routine
gertk 0:28557a4d2215 34 2006-01-29 added first steps for byte addressable read routine (read X bytes from startaddress Y)
gertk 0:28557a4d2215 35 2005-12-23 added current file search option
gertk 0:28557a4d2215 36 2005-12-11 first version, ported from FAT1618.C
gertk 0:28557a4d2215 37 */
gertk 0:28557a4d2215 38
gertk 0:28557a4d2215 39 /* TO DO:
gertk 0:28557a4d2215 40 ------
gertk 0:28557a4d2215 41 - FileSectorScan(struct file2TYPE *file) routine iets aanpassen zodat we niet falen op de theoretisch laatste 'filenextsector'
gertk 0:28557a4d2215 42 */
gertk 0:28557a4d2215 43
gertk 0:28557a4d2215 44 /*----------------------------------------------------------------------------------*/
gertk 0:28557a4d2215 45
gertk 0:28557a4d2215 46 /*--------------------------------------------------------*/
gertk 0:28557a4d2215 47 /* includes */
gertk 0:28557a4d2215 48 /*--------------------------------------------------------*/
gertk 0:28557a4d2215 49 #include <stdio.h>
gertk 0:28557a4d2215 50 #include <main.h>
gertk 0:28557a4d2215 51 #include <ata.h>
gertk 0:28557a4d2215 52 #include <fat.h>
gertk 0:28557a4d2215 53
gertk 0:28557a4d2215 54 /*--------------------------------------------------------*/
gertk 0:28557a4d2215 55 /* constants */
gertk 0:28557a4d2215 56 /*--------------------------------------------------------*/
gertk 0:28557a4d2215 57 #define FALSE 0 /*FALSE*/
gertk 0:28557a4d2215 58 #define TRUE 1 /*TRUE*/
gertk 0:28557a4d2215 59
gertk 0:28557a4d2215 60 /*Since the size of a D64 file is fixed the number of sectors required for a D64 file is also fixed*/
gertk 0:28557a4d2215 61 /*In order to keep compatibillity with most of the .D64 formats we must be able to handle the biggest,*/
gertk 0:28557a4d2215 62 /*so thats 40tracks including error bytes*/
gertk 0:28557a4d2215 63 #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*/
gertk 0:28557a4d2215 64
gertk 0:28557a4d2215 65 /*--------------------------------------------------------*/
gertk 0:28557a4d2215 66 /* globals */
gertk 0:28557a4d2215 67 /*--------------------------------------------------------*/
gertk 0:28557a4d2215 68 static unsigned long fatstart; /*start LBA of first FAT table*/
gertk 0:28557a4d2215 69 static unsigned char fatno; /*number of FAT tables*/
gertk 0:28557a4d2215 70 static unsigned long datastart; /*start LBA of data field*/
gertk 0:28557a4d2215 71 static unsigned long rootstart; /*start LBA of rootdirectory table*/
gertk 0:28557a4d2215 72 static unsigned short direntrys; /*number of entry's in directory table*/
gertk 0:28557a4d2215 73 static unsigned short direntrys_root; /*number of entry's in directory table*/
gertk 0:28557a4d2215 74 static unsigned char clustersize; /*size of a cluster in blocks*/
gertk 0:28557a4d2215 75 static unsigned short subdircluster_start; /*starting cluster of subdirectory*/
gertk 0:28557a4d2215 76 static unsigned short subdirsec_start; /*starting cluster of subdirectory*/
gertk 0:28557a4d2215 77 #define bit bool
gertk 0:28557a4d2215 78 static bit root;
gertk 0:28557a4d2215 79
gertk 0:28557a4d2215 80
gertk 0:28557a4d2215 81 unsigned short clusterlocationcache[D64FileConsistsOfSectors]; /*cache for the sector locations within the D64 file as stored in the Fat16*/
gertk 0:28557a4d2215 82
gertk 0:28557a4d2215 83 /*--------------------------------------------------------*/
gertk 0:28557a4d2215 84 /* local functions */
gertk 0:28557a4d2215 85 /*--------------------------------------------------------*/
gertk 0:28557a4d2215 86
gertk 0:28557a4d2215 87 unsigned char ASCII_to_PETSCII(unsigned char ASCII);
gertk 0:28557a4d2215 88
gertk 0:28557a4d2215 89 /*****************************************************************************************************************/
gertk 0:28557a4d2215 90 /*****************************************************************************************************************/
gertk 0:28557a4d2215 91
gertk 0:28557a4d2215 92 /*FindDrive checks if a card is present. if a card is present it will check for
gertk 0:28557a4d2215 93 a valid FAT16 primary partition*/
gertk 0:28557a4d2215 94 unsigned char FindDrive(void)
gertk 0:28557a4d2215 95 {
gertk 0:28557a4d2215 96 unsigned char error_code;
gertk 0:28557a4d2215 97 unsigned long fatsize; /*size of fat*/
gertk 0:28557a4d2215 98 unsigned long dirsize; /*size of directory region in sectors*/
gertk 0:28557a4d2215 99
gertk 0:28557a4d2215 100 error_code = AtaReadSector(0,block_buffer); /*read partition sector*/
gertk 0:28557a4d2215 101 if (error_code != TRUE)
gertk 0:28557a4d2215 102 {
gertk 0:28557a4d2215 103 return(error_code);
gertk 0:28557a4d2215 104 }
gertk 0:28557a4d2215 105
gertk 0:28557a4d2215 106 /*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*/
gertk 0:28557a4d2215 107 if(block_buffer[450]!=0x04 && block_buffer[450]!=0x05 && block_buffer[450]!=0x06)/*check partition type*/
gertk 0:28557a4d2215 108 fatstart=0;
gertk 0:28557a4d2215 109 else if(block_buffer[510]!=0x55 || block_buffer[511]!=0xaa) /*check signature*/
gertk 0:28557a4d2215 110 fatstart=0;
gertk 0:28557a4d2215 111 else
gertk 0:28557a4d2215 112 {
gertk 0:28557a4d2215 113 fatstart=(unsigned long)block_buffer[454]; /*get start of first partition*/
gertk 0:28557a4d2215 114 fatstart+=(unsigned long)block_buffer[455]*256;
gertk 0:28557a4d2215 115 fatstart+=(unsigned long)block_buffer[456]*65536;
gertk 0:28557a4d2215 116 fatstart+=(unsigned long)block_buffer[457]*16777216;
gertk 0:28557a4d2215 117 }
gertk 0:28557a4d2215 118
gertk 0:28557a4d2215 119 if(!AtaReadSector(fatstart,block_buffer)) /*read boot sector*/
gertk 0:28557a4d2215 120 return(ERROR_FAT_READBOOTSECTOR);
gertk 0:28557a4d2215 121
gertk 0:28557a4d2215 122 if(block_buffer[0]!=0xe9 && block_buffer[0]!=0xeb) /*check for near-jump or short-jump opcode*/
gertk 0:28557a4d2215 123 return(ERROR_FAT_JUMPOPCODE);
gertk 0:28557a4d2215 124
gertk 0:28557a4d2215 125 if(block_buffer[11]!=0x00 || block_buffer[12]!=0x02) /*check if blocksize is really 512 bytes*/
gertk 0:28557a4d2215 126 return(ERROR_FAT_BLOCKSIZE);
gertk 0:28557a4d2215 127
gertk 0:28557a4d2215 128 if(block_buffer[21]!=0xf8) /*check medium descriptorbyte, must be 0xf8 for hard drive*/
gertk 0:28557a4d2215 129 return(ERROR_FAT_MEDIUM);
gertk 0:28557a4d2215 130
gertk 0:28557a4d2215 131 direntrys=block_buffer[17]+(block_buffer[18]*256); /*calculate drive's parameters from bootsector, first up is size of directory*/
gertk 0:28557a4d2215 132 direntrys_root = direntrys;
gertk 0:28557a4d2215 133 dirsize=((direntrys*32)+511)/512;
gertk 0:28557a4d2215 134
gertk 0:28557a4d2215 135 fatstart=fatstart+block_buffer[14]+(block_buffer[15]*256); /*calculate start of FAT,size of FAT and number of FAT's*/
gertk 0:28557a4d2215 136 fatsize=block_buffer[22]+(block_buffer[23]*256);
gertk 0:28557a4d2215 137 fatno=block_buffer[16];
gertk 0:28557a4d2215 138
gertk 0:28557a4d2215 139 rootstart=fatstart+(fatno*fatsize); /*calculate start of root-directory*/
gertk 0:28557a4d2215 140 clustersize=block_buffer[13]; /*get clustersize*/
gertk 0:28557a4d2215 141 datastart=rootstart+dirsize; /*calculate start of data*/
gertk 0:28557a4d2215 142 root=TRUE; /*raise flag to indicate we are in the root directory*/
gertk 0:28557a4d2215 143 return(TRUE);
gertk 0:28557a4d2215 144 }
gertk 0:28557a4d2215 145
gertk 0:28557a4d2215 146 /*this routine needs to be called when a subdirectory is entered*/
gertk 0:28557a4d2215 147 /*this routine re-calculates the current directroy pointers and registers to those of the (sub)directory to be opened*/
gertk 0:28557a4d2215 148 /*this routine returns TRUE when the subdirectory is a subdirectory and FALSE when it is root*/
gertk 0:28557a4d2215 149 unsigned char OpenSubDirectory(struct file2TYPE *file)
gertk 0:28557a4d2215 150 {
gertk 0:28557a4d2215 151 /*calculate the location of the first byte of the new (sub)directory*/
gertk 0:28557a4d2215 152 if(file->cluster == 0) /*check if the user requests the root directory*/
gertk 0:28557a4d2215 153 { /*---------------------------------------------*/
gertk 0:28557a4d2215 154 root=TRUE; /*raise flag to indicate we are in the root directory*/
gertk 0:28557a4d2215 155 direntrys = direntrys_root;
gertk 0:28557a4d2215 156 return(FALSE); /*we are now back in root*/
gertk 0:28557a4d2215 157 }
gertk 0:28557a4d2215 158 else
gertk 0:28557a4d2215 159 {
gertk 0:28557a4d2215 160 root=FALSE; /*lower flag to indicate we are NOT in the root directory*/
gertk 0:28557a4d2215 161 direntrys = 1000; /*a fixed value that is practically impossible to use on a CBM computer*/
gertk 0:28557a4d2215 162 subdircluster_start = file->cluster; /*starting cluster of subdirectory*/
gertk 0:28557a4d2215 163 subdirsec_start = file->sec; /*starting sector offset within cluster*/
gertk 0:28557a4d2215 164 return(TRUE); /*we are now in a subdirectory*/
gertk 0:28557a4d2215 165 }
gertk 0:28557a4d2215 166 }
gertk 0:28557a4d2215 167
gertk 0:28557a4d2215 168 /*scan directory, yout must pass a file handle to this function*/
gertk 0:28557a4d2215 169 /*search modes: 0=first,1=next(8.3 AND LFN),2=previous(8.3 only),3=current*/
gertk 0:28557a4d2215 170 unsigned char FileSearch(struct file2TYPE *file, unsigned char mode)
gertk 0:28557a4d2215 171 {
gertk 0:28557a4d2215 172 static unsigned short subdircluster_current; /*current cluster of subdirectory*/
gertk 0:28557a4d2215 173 static unsigned short subdirsec_current; /*current sector offset within cluster*/
gertk 0:28557a4d2215 174 static unsigned char sectorcounter; /*a relative counter, to keep track of how many sectors we've read regarding this subdirectory*/
gertk 0:28557a4d2215 175 /*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*/
gertk 0:28557a4d2215 176
gertk 0:28557a4d2215 177 unsigned long sf,sb;
gertk 0:28557a4d2215 178 unsigned short i;
gertk 0:28557a4d2215 179 unsigned char j;
gertk 0:28557a4d2215 180
gertk 0:28557a4d2215 181 unsigned short LFN_offset;
gertk 0:28557a4d2215 182 unsigned char LFN_seq_nmbr;
gertk 0:28557a4d2215 183 unsigned char LFN_string[27]; /*the length of the LFN name we use is max 26 characters (2 LFN entries)*/
gertk 0:28557a4d2215 184 unsigned char LFN_checksum[2]; /*since we use only two LFN entries, we only need to store 2 checksums*/
gertk 0:28557a4d2215 185 unsigned char REF_checksum; /*the checksum which is our reference*/
gertk 0:28557a4d2215 186
gertk 0:28557a4d2215 187 LFN_checksum[0] = 0; /*clear the checksum value of the 1st LFN sequence*/
gertk 0:28557a4d2215 188 LFN_checksum[1] = 0; /*clear the checksum value of the 2nd LFN sequence*/
gertk 0:28557a4d2215 189
gertk 0:28557a4d2215 190 sb=0; /*buffer is empty*/
gertk 0:28557a4d2215 191 if(mode==0) /*search for first entry*/
gertk 0:28557a4d2215 192 { /*----------------------*/
gertk 0:28557a4d2215 193 file->entry=0;
gertk 0:28557a4d2215 194 if (root == FALSE)
gertk 0:28557a4d2215 195 {
gertk 0:28557a4d2215 196 file->cluster = subdircluster_start; /*reset the cluster pointer back to the beginning of the directory, otherwise we fail with the filenextsector routine*/
gertk 0:28557a4d2215 197 file->sec = subdirsec_start; /*starting sector offset within cluster*/
gertk 0:28557a4d2215 198 subdircluster_current = file->cluster;
gertk 0:28557a4d2215 199 subdirsec_current = file->sec;
gertk 0:28557a4d2215 200 sectorcounter = 0;
gertk 0:28557a4d2215 201 }
gertk 0:28557a4d2215 202 }
gertk 0:28557a4d2215 203 else if(mode==1) /*search for next entry*/
gertk 0:28557a4d2215 204 { /*---------------------*/
gertk 0:28557a4d2215 205 file->entry++;
gertk 0:28557a4d2215 206 }
gertk 0:28557a4d2215 207 else if(mode==2) /*search for previous entry*/
gertk 0:28557a4d2215 208 { /*-------------------------*/
gertk 0:28557a4d2215 209 file->entry--;
gertk 0:28557a4d2215 210 }
gertk 0:28557a4d2215 211
gertk 0:28557a4d2215 212 while(file->entry<direntrys)
gertk 0:28557a4d2215 213 {
gertk 0:28557a4d2215 214 if (root == TRUE) /*the root directory is one continuos chunk of entries*/
gertk 0:28557a4d2215 215 { /*----------------------------------------------------*/
gertk 0:28557a4d2215 216 sf=rootstart; /*calculate sector and offset*/
gertk 0:28557a4d2215 217 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)*/
gertk 0:28557a4d2215 218
gertk 0:28557a4d2215 219 if(sb!=sf) /*when buffer is empty or needs to be changed*/
gertk 0:28557a4d2215 220 {
gertk 0:28557a4d2215 221 sb=sf;
gertk 0:28557a4d2215 222 if(!AtaReadSector(sb,block_buffer))
gertk 0:28557a4d2215 223 return(FALSE);
gertk 0:28557a4d2215 224 }
gertk 0:28557a4d2215 225 }
gertk 0:28557a4d2215 226 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*/
gertk 0:28557a4d2215 227 { /*--------------------------------------------------------------------------------------------------------------------------------------------------*/
gertk 0:28557a4d2215 228 if((mode==1) && (file->entry > 0) && (file->entry%16 == 0)) /*load sector if not in buffer*/
gertk 0:28557a4d2215 229 {
gertk 0:28557a4d2215 230 file->cluster = subdircluster_current; /*retrieve the latest cluster value*/
gertk 0:28557a4d2215 231 file->sec = subdirsec_current; /*retrieve the latest sector value*/
gertk 0:28557a4d2215 232 if (FileNextSector(file) == FALSE) /*attention: screws up block_buffer!!*/
gertk 0:28557a4d2215 233 return(FALSE);
gertk 0:28557a4d2215 234 sectorcounter++; /*another sector loaded, increment counter*/
gertk 0:28557a4d2215 235 subdircluster_current = file->cluster; /*save the new value for later*/
gertk 0:28557a4d2215 236 subdirsec_current = file->sec; /*save the new value for later*/
gertk 0:28557a4d2215 237
gertk 0:28557a4d2215 238 if ((file->cluster & 0xFFF8) == 0xFFF8) /*check if this is the last cluster*/
gertk 0:28557a4d2215 239 {
gertk 0:28557a4d2215 240 file->len=0;
gertk 0:28557a4d2215 241 return(FALSE);
gertk 0:28557a4d2215 242 }
gertk 0:28557a4d2215 243 }
gertk 0:28557a4d2215 244
gertk 0:28557a4d2215 245
gertk 0:28557a4d2215 246 if((mode==2) && ((file->entry + 1) > 0) && ((file->entry+1)%16 == 0)) /*load sector if not in buffer*/
gertk 0:28557a4d2215 247 {
gertk 0:28557a4d2215 248 /*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*/
gertk 0:28557a4d2215 249 /*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)*/
gertk 0:28557a4d2215 250 file->cluster = subdircluster_start; /*reset the cluster pointer back to the beginning of the directory, otherwise we fail with the filenextsector routine*/
gertk 0:28557a4d2215 251 file->sec = subdirsec_start; /*starting sector offset within cluster*/
gertk 0:28557a4d2215 252 if (sectorcounter > 0)
gertk 0:28557a4d2215 253 {
gertk 0:28557a4d2215 254 sectorcounter--; /*previous sector found, decrement counter*/
gertk 0:28557a4d2215 255 for(j=0;j<sectorcounter;j++)
gertk 0:28557a4d2215 256 {
gertk 0:28557a4d2215 257 if (FileNextSector(file) == FALSE) /*attention: screws up block_buffer!!*/
gertk 0:28557a4d2215 258 return(FALSE);
gertk 0:28557a4d2215 259 }
gertk 0:28557a4d2215 260 }
gertk 0:28557a4d2215 261 subdircluster_current = file->cluster; /*save the new value for later*/
gertk 0:28557a4d2215 262 subdirsec_current = file->sec; /*save the new value for later*/
gertk 0:28557a4d2215 263 }
gertk 0:28557a4d2215 264
gertk 0:28557a4d2215 265 sf=datastart; /*start of data in partition*/
gertk 0:28557a4d2215 266 sf+=(unsigned long)clustersize*(subdircluster_current-2); /*cluster offset*/
gertk 0:28557a4d2215 267 sf+=(subdirsec_current%clustersize); /*sector offset in cluster*/
gertk 0:28557a4d2215 268 if(sb!=sf) /*when buffer is empty or needs to be changed*/
gertk 0:28557a4d2215 269 {
gertk 0:28557a4d2215 270 sb=sf;
gertk 0:28557a4d2215 271 if(!AtaReadSector(sb,block_buffer))
gertk 0:28557a4d2215 272 return(FALSE);
gertk 0:28557a4d2215 273 }
gertk 0:28557a4d2215 274 }
gertk 0:28557a4d2215 275
gertk 0:28557a4d2215 276 i=(file->entry%16)*32; /*i is the pointer that points to the address of the entry within the loaded sector*/
gertk 0:28557a4d2215 277 if(block_buffer[i+0x0b]==0x0f) /*check if this entry is an LFN entry*/
gertk 0:28557a4d2215 278 {
gertk 0:28557a4d2215 279 //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)*/
gertk 0:28557a4d2215 280 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*/
gertk 0:28557a4d2215 281 {
gertk 0:28557a4d2215 282 LFN_seq_nmbr = block_buffer[i] & 0x3f; /*remove the possible 0x40 in order to keep the bare LFN sequence number*/
gertk 0:28557a4d2215 283 LFN_offset = (LFN_seq_nmbr * 13) - 13;
gertk 0:28557a4d2215 284
gertk 0:28557a4d2215 285 /*save the LFN characters to the correct location of our string*/
gertk 0:28557a4d2215 286 LFN_string[LFN_offset + 0] = block_buffer[i+0x01]; /*5 UTF characters of which we only use the first byte*/
gertk 0:28557a4d2215 287 LFN_string[LFN_offset + 1] = block_buffer[i+0x03];
gertk 0:28557a4d2215 288 LFN_string[LFN_offset + 2] = block_buffer[i+0x05];
gertk 0:28557a4d2215 289 LFN_string[LFN_offset + 3] = block_buffer[i+0x07];
gertk 0:28557a4d2215 290 LFN_string[LFN_offset + 4] = block_buffer[i+0x09];
gertk 0:28557a4d2215 291
gertk 0:28557a4d2215 292 LFN_checksum[LFN_seq_nmbr-1] = block_buffer[i+0x0d];/*save the checksum*/
gertk 0:28557a4d2215 293
gertk 0:28557a4d2215 294 LFN_string[LFN_offset + 5] = block_buffer[i+0x0e]; /*6 UTF characters of which we only use the first byte*/
gertk 0:28557a4d2215 295 LFN_string[LFN_offset + 6] = block_buffer[i+0x10];
gertk 0:28557a4d2215 296 LFN_string[LFN_offset + 7] = block_buffer[i+0x12];
gertk 0:28557a4d2215 297 LFN_string[LFN_offset + 8] = block_buffer[i+0x14];
gertk 0:28557a4d2215 298 LFN_string[LFN_offset + 9] = block_buffer[i+0x16];
gertk 0:28557a4d2215 299 LFN_string[LFN_offset + 10] = block_buffer[i+0x18];
gertk 0:28557a4d2215 300
gertk 0:28557a4d2215 301 LFN_string[LFN_offset + 11] = block_buffer[i+0x1c]; /*2 UTF characters of which we only use the first byte*/
gertk 0:28557a4d2215 302 LFN_string[LFN_offset + 12] = block_buffer[i+0x1e];
gertk 0:28557a4d2215 303
gertk 0:28557a4d2215 304 /*the following code is not required as we only use two LFN entries which we compare with a checksum later*/
gertk 0:28557a4d2215 305 /*the code below is left for reference for LFN filenames which must be longer then 26chars*/
gertk 0:28557a4d2215 306 // if(block_buffer[i]&0x40 == 0x40) /*check if this entry was the last LFN entry belonging to this file*/
gertk 0:28557a4d2215 307 // { /*we do this by checking if the 6st bit was set*/
gertk 0:28557a4d2215 308 // LFN_string[LFN_offset + 13] = 0; /*terminate string HERE*/
gertk 0:28557a4d2215 309 // }
gertk 0:28557a4d2215 310 }
gertk 0:28557a4d2215 311 }
gertk 0:28557a4d2215 312
gertk 0:28557a4d2215 313 if(block_buffer[i]!=0x00 && block_buffer[i]!=0xe5) /*check if valid file entry: 0x00 = entry is available*/
gertk 0:28557a4d2215 314 { /* 0xE5 = entry has been erased*/
gertk 0:28557a4d2215 315 if((block_buffer[i+0x0b]&0x0a)==0x00) /*check atributes: do not show hidden files, do not show volume labels, DO SHOW subdirectories*/
gertk 0:28557a4d2215 316 {
gertk 0:28557a4d2215 317 for(j=0;j<11;j++) /*copy name (8.3)*/
gertk 0:28557a4d2215 318 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*/
gertk 0:28557a4d2215 319 file->name[j]=0x00; /*terminate the string*/
gertk 0:28557a4d2215 320
gertk 0:28557a4d2215 321 file->len=(unsigned long)block_buffer[j+28]; /*get length of file in sectors, maximum is 16Mbytes*/
gertk 0:28557a4d2215 322 file->len+=(unsigned short)block_buffer[i+29]*256;
gertk 0:28557a4d2215 323 file->len+=511;
gertk 0:28557a4d2215 324 file->len/=512;
gertk 0:28557a4d2215 325 file->len+=(unsigned long)block_buffer[i+30]*128;
gertk 0:28557a4d2215 326
gertk 0:28557a4d2215 327 file->cluster=(unsigned long)block_buffer[i+26]+((unsigned long)block_buffer[i+27]*256); /*get first cluster of file*/
gertk 0:28557a4d2215 328 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);
gertk 0:28557a4d2215 329 file->sec=0; /*reset sector index*/
gertk 0:28557a4d2215 330
gertk 0:28557a4d2215 331 REF_checksum = 0; /*calculate the checksum of the 8.3 filename*/
gertk 0:28557a4d2215 332 for (j=0;j<11;j++) /*this checksum is our reference to which we compare the LFN checksum(s) with*/
gertk 0:28557a4d2215 333 REF_checksum = (((REF_checksum & 1) << 7) | ((REF_checksum & 0xfe) >> 1)) + block_buffer[i+j];
gertk 0:28557a4d2215 334
gertk 0:28557a4d2215 335 if(LFN_checksum[0] == REF_checksum) /*using the checksum we determine wether we use the gathered LFN information*/
gertk 0:28557a4d2215 336 {
gertk 0:28557a4d2215 337 for(j=0;j<13;j++) /*copy the first 13 characters of the LFN string (maintain case)*/
gertk 0:28557a4d2215 338 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*/
gertk 0:28557a4d2215 339
gertk 0:28557a4d2215 340 if(LFN_checksum[1] == REF_checksum)
gertk 0:28557a4d2215 341 {
gertk 0:28557a4d2215 342 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)*/
gertk 0:28557a4d2215 343 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*/
gertk 0:28557a4d2215 344 file->name_lfn[26]=0x00; /*terminate string*/
gertk 0:28557a4d2215 345 }
gertk 0:28557a4d2215 346 else
gertk 0:28557a4d2215 347 file->name_lfn[13]=0x00; /*terminate string*/
gertk 0:28557a4d2215 348 }
gertk 0:28557a4d2215 349 else
gertk 0:28557a4d2215 350 {
gertk 0:28557a4d2215 351 file->name_lfn[0]=0; /*clear the LFN string by terminating at the first char*/
gertk 0:28557a4d2215 352 }
gertk 0:28557a4d2215 353
gertk 0:28557a4d2215 354 return(TRUE);
gertk 0:28557a4d2215 355 }
gertk 0:28557a4d2215 356 }
gertk 0:28557a4d2215 357 if(mode==2)
gertk 0:28557a4d2215 358 file->entry--;
gertk 0:28557a4d2215 359 else
gertk 0:28557a4d2215 360 file->entry++;
gertk 0:28557a4d2215 361 }
gertk 0:28557a4d2215 362 file->len=0;
gertk 0:28557a4d2215 363 return(FALSE);
gertk 0:28557a4d2215 364 }
gertk 0:28557a4d2215 365
gertk 0:28557a4d2215 366
gertk 0:28557a4d2215 367 /*this routine will scan for the startaddress of all possible sectors that hold a D64 file*/
gertk 0:28557a4d2215 368 unsigned char FileSectorScan(struct file2TYPE *file)
gertk 0:28557a4d2215 369 {
gertk 0:28557a4d2215 370 unsigned int lp;
gertk 0:28557a4d2215 371
gertk 0:28557a4d2215 372 for(lp=0; lp<(D64FileConsistsOfSectors-1); lp++)
gertk 0:28557a4d2215 373 {
gertk 0:28557a4d2215 374 clusterlocationcache[lp] = file->cluster;
gertk 0:28557a4d2215 375 if (FileNextSector(file) == FALSE) /*attention: screws up block_buffer!!*/
gertk 0:28557a4d2215 376 return(FALSE);
gertk 0:28557a4d2215 377 }
gertk 0:28557a4d2215 378 clusterlocationcache[D64FileConsistsOfSectors-1] = file->cluster;
gertk 0:28557a4d2215 379
gertk 0:28557a4d2215 380 return(TRUE);
gertk 0:28557a4d2215 381 }
gertk 0:28557a4d2215 382
gertk 0:28557a4d2215 383
gertk 0:28557a4d2215 384 /*point to next sector in file*/
gertk 0:28557a4d2215 385 unsigned char FileNextSector(struct file2TYPE *file)
gertk 0:28557a4d2215 386 {
gertk 0:28557a4d2215 387 unsigned long sb;
gertk 0:28557a4d2215 388 unsigned short i;
gertk 0:28557a4d2215 389
gertk 0:28557a4d2215 390 file->sec++; /*increment sector index*/
gertk 0:28557a4d2215 391 if((file->sec%clustersize)==0) /*if we are now in another cluster, look up cluster*/
gertk 0:28557a4d2215 392 {
gertk 0:28557a4d2215 393 sb=fatstart; /*calculate sector that contains FAT-link*/
gertk 0:28557a4d2215 394 sb+=(file->cluster/256);
gertk 0:28557a4d2215 395 i=(file->cluster%256); /*calculate offset*/
gertk 0:28557a4d2215 396 i*=2;
gertk 0:28557a4d2215 397
gertk 0:28557a4d2215 398 if(!AtaReadSector(sb,block_buffer)) /*read sector of FAT*/
gertk 0:28557a4d2215 399 return(FALSE);
gertk 0:28557a4d2215 400
gertk 0:28557a4d2215 401 file->cluster=((unsigned short)block_buffer[i+1]*256)+(unsigned short)block_buffer[i]; /*get FAT-link*/
gertk 0:28557a4d2215 402 }
gertk 0:28557a4d2215 403 return(TRUE);
gertk 0:28557a4d2215 404 }
gertk 0:28557a4d2215 405
gertk 0:28557a4d2215 406 /*read current sector into buffer*/
gertk 0:28557a4d2215 407 unsigned char FileReadSector(struct file2TYPE *file)
gertk 0:28557a4d2215 408 {
gertk 0:28557a4d2215 409 unsigned long sb;
gertk 0:28557a4d2215 410
gertk 0:28557a4d2215 411 sb=datastart; /*start of data in partition*/
gertk 0:28557a4d2215 412 sb+=(unsigned long)clustersize*(file->cluster-2); /*cluster offset*/
gertk 0:28557a4d2215 413 sb+=(file->sec%clustersize); /*sector offset in cluster*/
gertk 0:28557a4d2215 414
gertk 0:28557a4d2215 415 if(!AtaReadSector(sb,block_buffer)) /*read the data from the sector*/
gertk 0:28557a4d2215 416 return(FALSE);
gertk 0:28557a4d2215 417 else
gertk 0:28557a4d2215 418 return(TRUE);
gertk 0:28557a4d2215 419 }
gertk 0:28557a4d2215 420
gertk 0:28557a4d2215 421 /*read specified sector into buffer*/
gertk 0:28557a4d2215 422 unsigned char FileReadSector_X(struct file2TYPE *file, unsigned long block)
gertk 0:28557a4d2215 423 {
gertk 0:28557a4d2215 424 unsigned long sb;
gertk 0:28557a4d2215 425
gertk 0:28557a4d2215 426 file->cluster = clusterlocationcache[block]; /*retrieve the sector address from the cache*/
gertk 0:28557a4d2215 427 file->sec = block; /*we need to indicate the exact sector number within this cluster*/
gertk 0:28557a4d2215 428
gertk 0:28557a4d2215 429 sb=datastart; /*start of data in partition*/
gertk 0:28557a4d2215 430 sb+=(unsigned long)clustersize*(file->cluster-2); /*cluster offset*/
gertk 0:28557a4d2215 431 sb+=(file->sec%clustersize); /*sector offset in cluster*/
gertk 0:28557a4d2215 432 // sb+=pt; /*add the pointer offset to the absolute address of the data position as stored on the card*/
gertk 0:28557a4d2215 433
gertk 0:28557a4d2215 434 if(!AtaReadSector(sb,block_buffer)) /*read the data from the sector*/
gertk 0:28557a4d2215 435 return(FALSE);
gertk 0:28557a4d2215 436 else
gertk 0:28557a4d2215 437 return(TRUE);
gertk 0:28557a4d2215 438 }
gertk 0:28557a4d2215 439
gertk 0:28557a4d2215 440 /*Read xxx bytes from a sector into a specified buffer*/
gertk 0:28557a4d2215 441 /*When only one or more bytes are required, then this routine comes in handy...*/
gertk 0:28557a4d2215 442 unsigned char FileRead_X_Bytes(struct file2TYPE *file, unsigned long startaddress, unsigned int NmbrOfBytes)
gertk 0:28557a4d2215 443 {
gertk 0:28557a4d2215 444 unsigned long lp, pt, bytesfromcurrentsector, bytesfromnextsector;
gertk 0:28557a4d2215 445 unsigned long sb;
gertk 0:28557a4d2215 446
gertk 0:28557a4d2215 447 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)*/
gertk 0:28557a4d2215 448 pt = startaddress%512L; /*the byte we are looking for is pointed to by "cardbuffer_pnt"*/
gertk 0:28557a4d2215 449
gertk 0:28557a4d2215 450 /*check if the bytes we want to read beyond the sector border*/
gertk 0:28557a4d2215 451 if ((pt + NmbrOfBytes) < 512L)
gertk 0:28557a4d2215 452 {
gertk 0:28557a4d2215 453 bytesfromcurrentsector = NmbrOfBytes; /*the number of bytes that can be read from the now selected sector*/
gertk 0:28557a4d2215 454 bytesfromnextsector = 0; /*the number of bytes that can cannot be read from the now selected sector and must be read from the next sector*/
gertk 0:28557a4d2215 455 }
gertk 0:28557a4d2215 456 else
gertk 0:28557a4d2215 457 {
gertk 0:28557a4d2215 458 bytesfromcurrentsector = 512L - pt;
gertk 0:28557a4d2215 459 bytesfromnextsector = NmbrOfBytes - bytesfromcurrentsector;
gertk 0:28557a4d2215 460 }
gertk 0:28557a4d2215 461
gertk 0:28557a4d2215 462 file->cluster = clusterlocationcache[lp]; /*retrieve the sector address from the cache*/
gertk 0:28557a4d2215 463 file->sec = lp; /*we need to indicate the exact sector number within this cluster*/
gertk 0:28557a4d2215 464
gertk 0:28557a4d2215 465 sb=datastart; /*start of data in partition*/
gertk 0:28557a4d2215 466 sb+=(unsigned long)clustersize*(file->cluster-2); /*cluster offset*/
gertk 0:28557a4d2215 467 sb+=(file->sec%clustersize); /*sector offset in cluster*/
gertk 0:28557a4d2215 468 // sb+=pt; /*add the pointer offset to the absolute address of the data position as stored on the card*/
gertk 0:28557a4d2215 469 if(!AtaRead_X_Bytes(sb, pt, block_buffer, bytesfromcurrentsector)) /*read data (a part of the current sector) from drive*/
gertk 0:28557a4d2215 470 return(FALSE);
gertk 0:28557a4d2215 471
gertk 0:28557a4d2215 472 if (bytesfromnextsector !=0)
gertk 0:28557a4d2215 473 {
gertk 0:28557a4d2215 474 file->cluster = clusterlocationcache[lp+1]; /*retrieve the sector address from the cache*/
gertk 0:28557a4d2215 475 file->sec = lp+1; /*we need to indicate the exact sector number within this cluster*/
gertk 0:28557a4d2215 476
gertk 0:28557a4d2215 477 sb=datastart; /*start of data in partition*/
gertk 0:28557a4d2215 478 sb+=(unsigned long)clustersize*(file->cluster-2); /*cluster offset*/
gertk 0:28557a4d2215 479 sb+=(file->sec%clustersize); /*sector offset in cluster*/
gertk 0:28557a4d2215 480 if(!AtaRead_X_Bytes(sb, 0, &block_buffer[bytesfromcurrentsector+1], bytesfromnextsector)) /*read data (a part of the current sector) from drive*/
gertk 0:28557a4d2215 481 return(FALSE);
gertk 0:28557a4d2215 482 }
gertk 0:28557a4d2215 483 return(TRUE);
gertk 0:28557a4d2215 484 }
gertk 0:28557a4d2215 485
gertk 0:28557a4d2215 486 /*Write the specified block to the card*/
gertk 0:28557a4d2215 487 unsigned char FileWriteSector_X(struct file2TYPE *file, unsigned long block)
gertk 0:28557a4d2215 488 {
gertk 0:28557a4d2215 489 unsigned long sb;
gertk 0:28557a4d2215 490
gertk 0:28557a4d2215 491 file->cluster = clusterlocationcache[block]; /*retrieve the sector address from the cache*/
gertk 0:28557a4d2215 492 file->sec = block; /*we need to indicate the exact sector number within this cluster*/
gertk 0:28557a4d2215 493
gertk 0:28557a4d2215 494 sb=datastart; /*start of data in partition*/
gertk 0:28557a4d2215 495 sb+=(unsigned long)clustersize*(file->cluster-2); /*cluster offset*/
gertk 0:28557a4d2215 496 sb+=(file->sec%clustersize); /*sector offset in cluster*/
gertk 0:28557a4d2215 497 // sb+=pt; /*add the pointer offset to the absolute address of the data position as stored on the card*/
gertk 0:28557a4d2215 498 if(!AtaWriteSector(sb,block_buffer)) /*write data to medium*/
gertk 0:28557a4d2215 499 return(FALSE);
gertk 0:28557a4d2215 500
gertk 0:28557a4d2215 501 return(TRUE);
gertk 0:28557a4d2215 502 }
gertk 0:28557a4d2215 503
gertk 0:28557a4d2215 504
gertk 0:28557a4d2215 505 /***************************************************************************************************************************************/
gertk 0:28557a4d2215 506
gertk 0:28557a4d2215 507 /*convert ASCII to PETSCII: substitute the following ASCII-chars to PETSCII alternatives*/
gertk 0:28557a4d2215 508 unsigned char ASCII_to_PETSCII(unsigned char ASCII)
gertk 0:28557a4d2215 509 {
gertk 0:28557a4d2215 510 unsigned char PETSCII;
gertk 0:28557a4d2215 511
gertk 0:28557a4d2215 512 if ((ASCII >= 'a') && (ASCII <= 'z')) /*check if the ASCII character is lowercase*/
gertk 0:28557a4d2215 513 {
gertk 0:28557a4d2215 514 ASCII = ASCII - 0x20; /*convert lowercase to UPPERCASE*/
gertk 0:28557a4d2215 515 }
gertk 0:28557a4d2215 516
gertk 0:28557a4d2215 517 switch (ASCII)
gertk 0:28557a4d2215 518 {
gertk 0:28557a4d2215 519 case 0x5e: /*^-sign (caret)*/
gertk 0:28557a4d2215 520 {
gertk 0:28557a4d2215 521 PETSCII = 0xb1; /*PETSCII small 4 pixel upsidedown T located at the top*/
gertk 0:28557a4d2215 522 break;
gertk 0:28557a4d2215 523 }
gertk 0:28557a4d2215 524
gertk 0:28557a4d2215 525 case 0x5F: /*_-sign (underscore)*/
gertk 0:28557a4d2215 526 {
gertk 0:28557a4d2215 527 PETSCII = 0xa4; /*PETSCII underscore*/
gertk 0:28557a4d2215 528 break;
gertk 0:28557a4d2215 529 }
gertk 0:28557a4d2215 530
gertk 0:28557a4d2215 531 case 0x60: /*'-sign (single quote)*/
gertk 0:28557a4d2215 532 {
gertk 0:28557a4d2215 533 PETSCII = 0xbe; /*PETSCII 4pixel square located top left*/
gertk 0:28557a4d2215 534 break;
gertk 0:28557a4d2215 535 }
gertk 0:28557a4d2215 536
gertk 0:28557a4d2215 537 case 0x7b: /*{-sign (bracket left)*/
gertk 0:28557a4d2215 538 {
gertk 0:28557a4d2215 539 PETSCII = 0x5b; /*PETSCII squared bracket left*/
gertk 0:28557a4d2215 540 break;
gertk 0:28557a4d2215 541 }
gertk 0:28557a4d2215 542
gertk 0:28557a4d2215 543 case 0x7d: /*}-sign (bracket right)*/
gertk 0:28557a4d2215 544 {
gertk 0:28557a4d2215 545 PETSCII = 0x5d; /*PETSCII squared bracket right*/
gertk 0:28557a4d2215 546 break;
gertk 0:28557a4d2215 547 }
gertk 0:28557a4d2215 548
gertk 0:28557a4d2215 549 case 0x7e: /*~-sign (tilde as we say in Dutch)*/
gertk 0:28557a4d2215 550 {
gertk 0:28557a4d2215 551 PETSCII = 0xA8; /*PETSCII tilde*/
gertk 0:28557a4d2215 552 break;
gertk 0:28557a4d2215 553 }
gertk 0:28557a4d2215 554
gertk 0:28557a4d2215 555 default: /*in all other undefined situations leave the character "as it was"*/
gertk 0:28557a4d2215 556 {
gertk 0:28557a4d2215 557 PETSCII = ASCII;
gertk 0:28557a4d2215 558 break;
gertk 0:28557a4d2215 559 }
gertk 0:28557a4d2215 560 }
gertk 0:28557a4d2215 561 return(PETSCII);
gertk 0:28557a4d2215 562 }
gertk 0:28557a4d2215 563
gertk 0:28557a4d2215 564 /***************************************************************************************************************************************/
gertk 0:28557a4d2215 565 /***************************************************************************************************************************************/
gertk 0:28557a4d2215 566 /***************************************************************************************************************************************/
gertk 0:28557a4d2215 567 /***************************************************************************************************************************************/
gertk 0:28557a4d2215 568
gertk 0:28557a4d2215 569