@@ 42,9 42,8 @@ here const )fnbuf
c@+ ( a len ) fnbuf( swap move exit then
c@+ swap >r fnbuf( swap for ( dst ) \ V1=a
8b to@+ V1 dup '.' = if
- 2drop fnbuf( DirEntry EXTIDX + else
- upcase swap c!+ then ( dst+1 )
- dup )fnbuf = if 1 to i then next drop rdrop ;
+ 2drop fnbuf( DirEntry EXTIDX + else upcase swap c!+ then ( dst+1 )
+ dup )fnbuf = if break then next then drop rdrop ;
\ The FAT struct in this unit is split in 2. The first part contains code needed
\ by FATFile, and the second part contains the rest of the code for FAT. This
@@ 62,28 61,26 @@ SZ $0e + &+w@ reservedseccnt \ number of sectors reserved before FAT starts
SZ $10 + &+c@ FATcnt \ >1 means backup FATs
SZ $11 + &+w@ rootentcnt \ count of 32b entries
SZ $13 + &+w@ seccnt
-SZ $16 + &+w@ FATsz \ in bytes
+SZ $16 + &+w@ FATsz \ in sectors
$18 const HDRSZ
\ buffer for reading FAT tables and dir entries. one sector in length.
SZ HDRSZ + &+ :buf(
: :)buf bi :buf( | secsz + ;
-: :RootDirSectors ( self -- n )
-bi rootentcnt 32 * | secsz /mod ( r q ) swap bool + ;
-: :FirstDataSector ( self -- n ) >r
-r@ reservedseccnt r@ FATcnt r@ FATsz * + r> :RootDirSectors + ;
-: :FirstSectorOfCluster ( n self -- sec ) >r
-dup << r@ secsz r@ FATsz * >= if abort" cluster out of range" then
-1- 1- r@ secpercluster * r> :FirstDataSector + ;
-: :FirstRootDirSecNum ( self -- n ) >r
-r@ reservedseccnt r@ FATcnt r> FATsz * + ;
-: :ClusterSize bi secpercluster | secsz * ;
-: :DataSec ( self -- n ) >r
-r@ seccnt r@ FATsz r@ FATcnt *
-r@ reservedseccnt + r> :RootDirSectors + - ;
+\ These words have the same sig: fat -- n
+: :RootDirSectors bi rootentcnt 32 * | secsz /mod ( r q ) swap bool + ;
+: :totsec bi FATcnt | FATsz * ;
+: :FirstRootDirSecNum bi reservedseccnt | :totsec + ;
+: :FirstDataSector bi :FirstRootDirSecNum | :RootDirSectors + ;
+: :DataSec bi seccnt | :FirstDataSector - ;
: :CountOfClusters bi :DataSec | secpercluster / ;
+: :ClusterSize bi secpercluster | secsz * ;
: :FAT12? :CountOfClusters 4085 < ;
+: :FirstSectorOfCluster ( n self -- sec ) >r
+ dup << r@ secsz r@ FATsz * >= if abort" cluster out of range" then
+ 1- 1- r@ secpercluster * r> :FirstDataSector + ;
+
\ Read specified sector into buffer if it's not already there.
\ "cnt" is the total number of sectors ahead of "sec" that are available for a
\ sequential read, *including this sector*. For example, "2" means that we're
@@ 92,36 89,30 @@ r@ reservedseccnt + r> :RootDirSectors + - ;
1 max 1- to r@ bufseccnt dup r@ bufsec = if rdrop drop else
dup to r@ bufsec ( sec ) r@ :buf( r> :drv :sec@ then ;
+: :sec+( ( off sec self -- a ) tuck 1 swap :readsector :buf( + ;
: :FAT12' ( cluster self -- 'entry ) >r
- dup >> + ( cl offset ) r@ secsz /mod ( cl secoff sec )
- r@ reservedseccnt +
+ dup >> + ( offset ) r@ secsz /mod r@ reservedseccnt + ( secoff sec )
over 1+ r@ secsz = if \ end-of-sector cross-over!
- dup 1+ 0 r@ :readsector r@ :buf( c@ r@ :)buf c! then
- 0 r@ :readsector ( cl secoff )
- r> :buf( + ;
+ dup 1+ 1 r@ :readsector r@ :buf( c@ r@ :)buf c! then
+ r> :sec+( ;
: :FAT12@ ( cluster self -- entry )
over swap :FAT12' w@ swap 1 and if 4 rshift else $fff and then ;
: :FAT16' ( cluster self -- 'entry ) >r
- << ( offset ) r@ secsz /mod ( secoff sec )
- r@ reservedseccnt + 0 r@ :readsector ( secoff )
- r> :buf( + ;
+ << ( offset ) r@ secsz /mod r@ reservedseccnt + ( secoff sec ) r> :sec+( ;
: :FAT16@ ( cluster self -- entry ) :FAT16' w@ ;
: :FAT@ ( cluster self -- entry )
- over 2 < if 2drop EOC else
- dup :FAT12? if :FAT12@ else :FAT16@ then then ;
+ over 2 < if 2drop EOC else dup :FAT12? if :FAT12@ else :FAT16@ then then ;
-: :EOC? ( cluster self -- f )
- :FAT12? if $ff8 else $fff8 then tuck and = ;
+: :EOC? ( cluster self -- f ) :FAT12? if $ff8 else $fff8 then tuck and = ;
\ Read next sector if a sequential read is available, else return false.
-: :nextsector? ( self -- f ) >r
- r@ bufseccnt if \ still on a sector streak
- r@ bufsec 1+ r@ bufseccnt 1- r> :readsector 1
+: :nextsector? ( self -- f )
+ dup bufseccnt if \ still on a sector streak
+ bi+ bufsec 1+ | bufseccnt 1- rot :readsector 1
else \ out of sector, try next cluster
- r@ bufcluster r@ :FAT@ dup r@ :EOC? if rdrop drop 0 else
- dup to r@ bufcluster r@ :FirstSectorOfCluster
- r@ secpercluster r> :readsector 1 then
- then ;
+ bi+ bufcluster | :FAT@ swap 2dup :EOC? if 2drop 0 else ( cl self )
+ 2dup to bufcluster tuck :FirstSectorOfCluster ( self sec )
+ over secpercluster rot :readsector 1 then then ;
\ Find current fnbuf( in current dir buffer and return a dir entry.
: :findindir ( self -- direntry-or-0 ) >r
@@ 143,12 134,11 @@ r@ reservedseccnt + r> :RootDirSectors + - ;
\ Get DirEntry address from FS ID "id"
: :getdirentry ( id self -- direntry )
over if
- dup >r secsz /mod ( offset sec ) 1 r@ :readsector ( off ) r> :buf( +
+ r! secsz /mod ( offset sec ) 1 r@ :readsector ( off ) r> :buf( +
else 2drop rootdirentry( then ;
\ Get ID for direntry
-: :getid ( direntry self -- id )
- dup >r :buf( - r@ bufsec r> secsz * + ;
+: :getid ( direntry self -- id ) r! :buf( - r@ bufsec r> secsz * + ;
\ read multiple sectors in buf
: :readsectors ( sec u buf self -- ) >r \ V1=self
@@ 222,8 212,8 @@ extends File struct[ FATFile
0 align4 dup to' FAT lastcursor lladd ( fat newll )
swap :cursorsize allot ( newll ) CELLSZ + ( hdl ) dup :release ;
- : :findfreecursor ( fat -- hdl ) >r \ V1=fat
- r@ FAT lastcursor begin ( ll )
+ : :findfreecursor ( fat -- hdl )
+ r! FAT lastcursor begin ( ll ) \ V1=fat
?dup while dup CELLSZ + :free? not while llnext repeat
CELLSZ + else r@ :createcursor then
EmptyCursor over SZ move ( hdl )
@@ 236,10 226,9 @@ struct+[ FAT
\ This is the "low" part. Complete open is finalized in fs/fat
: :fatopen ( id self -- hdl ) >r \ V1=self
V1 :getdirentry
- V1 FATFile :findfreecursor >r ( dirent ) r@ FATFile :hold \ V2=hdl
+ V1 FATFile :findfreecursor ( dirent hdl ) r! FATFile :hold \ V2=hdl
\ write the rest
- dup V1 :buf( -
- V1 bufsec V1 secsz * + ( dirent doffset )
+ dup V1 :buf( - V1 bufsec V1 secsz * + ( dirent doffset )
r@ to FATFile entryoff DirEntry filesize r@ to FATFile size ( ) r> rdrop ;
: :mountvolume ( drv -- fs )