> CPMFiler 1.27 > 27-Nov-1998 v1.20 Selects DFS before Osword to reset FDC 0 04-Dec-1998 v1.21 Displays file attributes ,( 27-Nov-1999 v1.22 Accesses disk images $2 28-Nov-1999 v1.23 FREE and MAP < v1.24 AmsDOS, Einstein !F v1.25 Uppercase, long files DP v1.26 Try generalising, need to commands to specify disk shape UZ 28-Apr-2007 v1.27 Physical disk access on RISC OS, TYPE handles LF/CR/LFCR/CRLF d: Qnos%=fx(0,1)&FF:arc%=os%=6 >&8000:8:A%=:9,11:A%<80:&80:>&4000:&80 xos%<32:arc%:=fx(132,0) :init:"CPMFiler v"ver$" by J.G.Harston"': err: :X%=ctrl%:Y%=X%256 8drv$="":(D%+65);pmt$,type%,1); "[";drv$;"] "; ""A$:do(A$) 0 : !init:pmt$=">)]":ver$="1.27" Zcom$="DIR CAT STAT INFO TYPE DUMP DISS COPY FREE MAP USER BLOCKHELP QUIT FILE EXAM" qhelp$=":::: [CTRLS]: [RAW]:: ::::::::::" A ctrl% 32,name% 20,store% 256,data% &1000:X%=ctrl%:Y%=X%256 1OSWORD=&FFF1:D%=D%15(D%>-1):drv$="":user%=0 /fs%=fs:d$=".":s$="/":os%=32:d$="\":s$="." >DFS%=4:HADFS%=3:CPN%=2:CPM%=1:BBC%=-1:type%=CPM%:AmsDOS%=0 : !stp%=0: Directory entry size 6res%=0: Reserved area - (offset to directory)/256 0"dir%=0: (Offset to directory from res%)/256 &,: Directory is at (res%+dir%)*256 <6dsz%=0: Directory size - number of entries in directory @exm%=0: Extent mask Jbsz%=0: Block (extent) size /Tbmx%=0: Block max - disk size is bsz%*bmx% 1^alz%=0: Allocation entry size - 1 or 2 bytes hskew%=1: Sector skew $rflip%=0: Does size 2 go 79...0? |:  : 0ݤerr:"FX229"::fs<>fs%:"FX143,18,"+fs% 2CloseAll:" "+Þ,<128 <>17):=-1 <>17 -CloseAll:in%=in%:in%:A%=in%:in%=0:#A% 'out%=out%:out%:A%=out%:out%=0:#A%  : do(A$):A$="?":A$="HELP" ( A$,1)=" ":A$=A$,2):A$,1)<>" "  A$,1)=";" A$="":  A$,1)="*" A$: ! A$,1)="." A$="CAT "+A$,2) M A$=2 A$,1)=":" uc(A$)>"@" uc(A$)<"Q":D%=uc(A$)-65:drv$="": 8com%=0::B$=com$,com%*5+1,5):B$=B$,A$+" "," ")-1) 1com%=com%+1:uc(A$,B$))=B$ com%*5>=com$ '&uc(A$,B$))<>B$ "Bad command": )0z%=("FN_"+B$+"(MID$(A$,2+LENB$))"): :: D: N Commands X ======== b: lݤ_QUIT(A$):"Quit" v *QUIT  : ݤ_HELP(A$):ptr%=1:com%=0: T" "com$,com%*5+1,5);:A$=help$,ptr%):A$=A$,A$,":")-1):ptr%=ptr%+A$:" "A$; /:ptr%=ptr%+1:com%=com%+1:com%*5>=com$:=0 : 'ݤ_FILE(A$):drv$=A$:D%=-1:bsz%=0:=0 ݤ_USER(A$):user%=A$:=0 ݤ_CPM(A$):type%=CPM%:=0 ݤ_CPN(A$):type%=CPN%:=0 : ݤ_CAT(A$):LstDir(0):=0 ݤ_DIR(A$):LstDir(1):=0  ݤ_INFO(A$):LstDir(2):=0 ݤ_STAT(A$):LstDir(3):=0  : ,*ݤ_DUMP(A$): ln%,p%,ptr%,cols%:cols%=16 4 DUMP [COLS] N> IF LEFT$(A$,1)="-" cols%=VAL(MID$(A$,2)):A$=MID$(A$,INSTR(A$+" "," ")+1) HA$="":"?":= 4Rsrc$=A$:ptr%=find(src$):ptr%=0:"Not found":= !\ln%=len(ptr%):open:dump:=0 f: pdump:extent%=0:M%=bsz%-1: z P%=0 ln%-1 cols%:B$="" (h0(P%,6);" ";: Q%=P% P%+cols%-1 /(Q%M%)=0:ReadData(Q%bsz%,ptr%):O%=data% Kh0(?O%,2);" ";:A$=(?O%&7F): A$>=" " A$<="~" B$=B$+A$ B$=B$+"." O%=O%+1:: B$: cCPM%:ln%=bsz%*16:extent%=extent%+1:ptr%=find(src$+";"+extent%):ptr%:ln%=len(ptr%) ln%=0 ln%=0: : 2ݤ_TYPE(A$): ln%,p%,ptr%,last%:A$="":"?":= )msk%=A$," [")<>0:msk%=(msk%&80)&7F 4src$=A$:ptr%=find(src$):ptr%=0:"Not found":= 4ln%=len(ptr%):open:extent%=0:M%=bsz%-1:last%=0 ;P%=0ln%-1:(P%M%)=0:ReadData(P%bsz%,ptr%):O%=data% #Q%=?O%msk%:?O%=26:P%=ln%:Q%=0 2msk%=&FF:Q% Q%>31 Q%<>127:Q%:last%=Q% =msk%=&7F: Q%=10 Q%=13: last%<>23-Q%: 10,13:last%=Q% ,msk%=&7F: Q%=9:(8-( 8));:last%=Q% $O%=O%+1::: .=0 8: )Bݤ_DISS(A$): p%,ptr%: A$="" "?":= 0 start%=("&"+A$,p%+1)) start%=&100 9Vsrc$=A$:ptr%=find(src$):ptr%=0:src$" not found":= `len%=len(ptr%):open MjA%=190:!X%=&50200C:X%!4=0: OSWORD: X%!4=0 "No Z80 DisAssem routine":= taddr%=&100:p%=0: (~(p%2047)<4:ReadData(p%2048,ptr%) 8addr%CPM%:"Not yet done.":=0 !ptr%=data%:size%=bmx%:used%=2  L ?ptr%<128:p%=ptr%+16: used%=used%-(?p%<>0):p%=p%+1:?p%=0 p%>ptr%+31 )ptr%=ptr%+stp%:ptr%>=data%+dsz%*stp% free%=size%-used% :(h0(free%,4)" Blocks = "d(free%*bsz%,9)" bytes free" :2h0(used%,4)" Blocks = "d(used%*bsz%,9)" bytes used" <=0 F: /Pݤ_MAP(A$):"FREE SPACE MAP ON "(D%+65)":" ZRdDir: $dtype%<>CPM%:"Not yet done.":=0 Dn p%=0 31:data%!(p%*32+8)=0:data%!(p%*32+12)=0::data%!8=&FFFF xptr%=data%: `?ptr%<128:p%=ptr%+16::q%=?p%:data%?(8+(q% 7)+32*(q% 8))=-1:p%=p%+1:?p%=0 p%>ptr%+31 -ptr%=ptr%+stp%:ptr%>=data%+dsz%*stp%:11 . q%=0 bmx%-1: (q% 31)=0:'h0(q%,2); 332: data%?(8+(q% 7)+32*(q% 8)):35 46 : =0 : ݤ_EXAM(A$) RdDir: "Disk Information:" M"res= "d(res%,3)" stp="d(stp%, 4)" dir="d(dir%,3)" dsz="d(dsz%,3) M"exm= "d(exm%,3)" bsz="h0(bsz%,4)" bmx="d(bmx%,3)" alz="d(alz%,3) "skew="d(skew%,3)  ."Directory starts at &";~(res%+dir%)*256 '"Directory size: ";dsz%*stp% 7""Directory entries: ";dsz%;" of ";stp%;" bytes" #,"Block size: &";~bsz% T6"Disk size: ";bmx%*bsz%+res%*256;" (";(bmx%*bsz%+res%*256)1024;"K)" @=0 J: 9Tݤ_BLOCK(A$):cols%=16:sect%=0:A$<>"":sect%=("&"+A$) ^bsz%=0:RdDir: 1hptr%=store%:store%!16=sect%:ln%=bsz%:dump:=0 r: $|ݤ_COPY(A$):src%,dst%,src$,dst$ A$=uc(A$,4))+A$,5) A$,4)="BBC:":src%=BBC% A$,4)="CPM:":src%=CPM% A$,4)="CPN:":src%=CPN% Msrc%=0:"Bad syntax - use BBC:filename, CPM:filename or CPN:filename":= 5A$=A$,5):p%=A$," "):src$=A$,p%-1):A$=A$,p%+1) A$=uc(A$,4))+A$,5) A$,4)="BBC:":dst%=BBC% A$,4)="CPM:":dst%=CPM% A$,4)="CPN:":dst%=CPN% =src%=dst% (src%<>BBC% dst%<>BBC%):"Bad transfer":= -dst$=A$,5):src%<>BBC%:FromCPM ToCPM =0 : :  File copying code & ================= 0: :FromCPM /D src$<>"*" src$<>"*.*":FromCPMOneFile: NRdDir: X from%=0 dsz%-1 &bptr%=data%+from%*stp%:A$="":A%=1: 0lptr%?A%<>32:A$=A$+(ptr%?A%):A%=A%+1 A%=9 vA%>8:A$=A$+".": 1ptr%?A%<>32:A$=A$+(ptr%?A%):A%=A%+1 A%=12 A%>11:src$=A$:dst$=A$ " A%=1 dst$:A$=dst$,A%,1) Xos%<>32:p%="#$%^&*~\|:.",A$):p%:dst$=dst$,A%-1)+"=dpu+stb!c/",p%,1)+dst$,A%+1) *:?ptr%<128:FromCPMOneFile:A%=RdDir : : FromCPMOneFile )"Copying CPM:";src$;" to BBC:";dst$; .ptr%=find(src$):ptr%=0:" - Not found": 2ln%=len(ptr%):open:"Save "+dst$+" 0+"+~ln% ln%=0: 0out%=(dst$):out%=0:" - Can't open dest": "extent%=0:M%=bsz%-1:" **%";:  P%=0ln%-1 O(P%M%)=0:ReadData(P%bsz%,ptr%):O%=data%:8;8;8;d(100*P%ln%,2);"%";  #out%,?O%:O%=O%+1: c*CPM%:ln%=bsz%*16:extent%=extent%+1:ptr%=find(src$+";"+extent%):ptr%:ln%=len(ptr%) ln%=0 4ln%=0 #>#out%:out%=0:127;127;127: H: 1RToCPM:"Copying BBC:";src$;" to CPM:";dst$; \" - Can't save yet": f: p: z Object display routines  ======================= : % DIR/CAT - short list, all files 8 STAT/INFO [filename] - long list, one or all files  cflg% -> xxxx-FULL-CPM : )LstDir(cflg%):x%=0:A$="":RdDir: <ptr%=data%:A$<>"":ptr%=find(A$):ptr%=0:"Not found": &(cflg%3)=2:"Filename... etc..." (cflg%3)=3:"D:FILENAME.EXT U LENGTH ""EX ",type%=CPM%)"RSA ""<- -- -- -- -- -- ALLOCATION -- -- -- -- -- ->",type%=CPM%);"Sect",type%=CPN%);8 9"|FX229,1"::type%=CPM%:PrCPM type%=CPN%:PrCPN . IFADVAL(-1):IFGET=27:OSCLI"FX229":*FX125 7ptr%=ptr%+stp%:ptr%>=data%+dsz%*stp% A$<>""::  "FX229":  : : PrN(ptr%):p%=ptr% ptr%+10:?p%&7F:p%=ptr%+7:46 $ :x%=x%+1: . : I8 PrCPN:?ptr%+ptr%?1=0 ?ptr%+ptr%?1=510: (cflg%1)=0:PrCPNb: B x%=0:(65+D%)":"; 8L PrN(ptr%+5):x%>4::x%=0: (cflg%2)=0:" : ";: IV " "h0(ptr%?4,1)" "d(len(ptr%),6)" "attr(ptr%+5)" "h0(!ptr%,4); ` x%<2:4;: x%=0:: j : t PrCPNb ~  : 1 PrCPM:?ptr%>127: (cflg%1)=0:PrCPMb:  cflg%=1:(ptr%?12)exm%:  x%=0:(65+D%)":"; 8 PrN(ptr%+1):x%>4::x%=0: (cflg%2)=0:" : ";: d(?ptr%,3);d(len(ptr%),7);" "h0(ptr%?12,2)" "attr(ptr%);:p%=ptr%+16:" ";h0(!p%,2*alz%);:p%=p%+alz%:?p%=0 ?(p%+alz%-1)=0 p%>ptr%+31:p%>ptr%+31:8 :x%=0:  : PrCPMb: b l%=0:p%=ptr%::l%=l%+1:?p%&7F:p%=p%+1:(?p%&7F)=32 p%=ptr%+7-2*((ptr%!9 &FFFFFF)=&4D4F43) K (ptr%!9 &FFFFFF)<>&4D4F43 47:p%=ptr%+9 ptr%+11:?p%&7F::l%=l%+4  (cflg%2)::  (21-l%);:  : Z ݤattr(ptr%)="-R",1-(ptr%?9>127),1)+"-S",1-(ptr%?10>127),1)+"-A",1-(ptr%?11>127),1)  : ( : %2 Catalogue manipulation routines %< =============================== F : P ݤfind(A$): p%,ptr% -Z A$,2,1)=":":D%=(A$,1)15)-1:A$=A$,3) d ptr%=data%:RdDir:=0 9n p%=A$+".","."):p%<9:A$=A$,p%-1)+9-p%," ")+A$,p%) %x A$=A$,8)+A$,10,3)+" ",11)+A$ J p%=1 11:A$,p%,1)>"`":name%?p%=A$,p%,1)-32 name%?p%=A$,p%,1)  :type%=CPN%:ptr%=ptr%+4 ; name%?12=0:p%=A$,";"):p%:name%?12=A$,p%+1)*(1+exm%)  name%?0=user%:p%=0: (ptr%!0 &7F7F7F7F)=name%!0 (ptr%!4 &7F7F7F7F)=name%!4 (ptr%!8 &7F7F7F7F)=name%!8 ((ptr%?12 exm%)=name%?12 type%=CPN%):p%=  p%:ptr%=ptr%+stp% 2 ptr%>=data%+&A00 p%:type%=CPN%:ptr%=ptr%-4 n p%:p%=0 31 4:store%!p%=ptr%!p%:: IFtype%=CPN% store%!16=!(ptr%-4):len%=(store%!18 AND&FFFF)*128+128  p%:=store% =0  : ? DEFFNlen(p%):IFtype%=CPM%:=p%?15*128-128*(p%?13<>0)+p%?13 ` ݤlen(p%):type%=CPM%:=p%?15*128-128*(p%?13<>0)+p%?13+16384*(p%?12 exm%)-16384*(p%?15>127) - type%=CPN%:=(ptr%!2 &FFFF)*128+128 =0  :  open:type%<>CPN%:  link%=ptr%!0 &FFFF -" (link% &C0)=0: L3block sector number 0, (link% &C0)=&80: L2 block sector number (6 ReadOneBlock(store%,cpn(link%),D%) @ J : -T ݤcpn(A%):A%=A%&3FFF:=(A%15)+10*(A%16) ^ : h : r Disk access routines | ====================  : 6 ݤRdDir:ptr%=data%:FDCrd(data%,0,D%,1):data%?8=13 U type%=CPN%:AmsDOS%=0:stp%=16:res%=0:dir%=0:dsz%=256:exm%=1:bsz%=256:bmx%=0:alz%=1  skew%=1:flip%=0 r $data%="Acorn CP":type%=CPM%:stp%=32:res%=30:dir%=0:dsz%=128:exm%=1:bsz%=2048:bmx%=&C4:alz%=1:skew%=2:flip%=1 i $data%="HADFS"+0+" D":type%=HADFS%:stp%=24:res%=0:dir%=71:dsz%=32:bsz%=256:bmx%=1600:alz%=1:skew%=1 r !data%=&E5E5E5E5:type%=CPM%:AmsDOS%=:stp%=32:res%=36:dir%=0:dsz%=64:exm%=1:bsz%=1024:bmx%=&AB:alz%=1:skew%=1 x (!data% &F0FF)=&E000:type%=CPM%:AmsDOS%=:stp%=32:res%=40:dir%=0:dsz%=64:exm%=1:bsz%=2048:bmx%=&AB:alz%=2:skew%=1 r !data%=&0E008031:stp%=32:res%=&28:dir%=0:dsz%=128:exm%=1:bsz%=&800:bmx%=&C0:alz%=1:skew%=1:type%=CPM%:flip%=0 / ReadBlocks(data%,0,D%,(stp%*dsz%)/bsz%):=0  =0  :  ReadData(q%,ptr%) & ptr%->file info block (cpm only) < q%=(PTR within file)DIVbsz% - ie block number to fetch  p%,r% 6& type%=CPM%:ReadOneBlock(data%,ptr%?(q%+16),D%): 0 type%<>CPN%: 1: ReadOneBlock(data%,cpn(store%!(q%*2)),D%): D Read from CPN: {N ptr%=!ptr% &FFFF:ptr%=(ptr%15)+10*(ptr%16):ptr%=ptr%+q%*8: p%=0 7:FDCrd(data%+p%*256,conv(ptr%+p%),drv%,1):: \X ptr%=!ptr% &FFFF:ptr%=ptr%+q%*8: p%=0 7:rd(data%+p%*256,conv(ptr%+p%),drv%,1):: b : -l ReadBlocks(addr%,block%,drive%,number%) v p%=0 number%-1 1 ReadOneBlock(addr%+p%*bsz%,block%+p%,drive%)  :  : ' ReadOneBlock(addr%,block%,drive%) " type%=CPM%:ReadOneCPMBlock: " type%=CPN%:ReadOneCPNBlock:   :  ReadOneCPNBlock: p% 2 Read a block of &100 bytes -> 1xSmallSectors G sectors go: 0:0:0-0:0:9, 1:0:0-1:0:9, 0:1:0-0:1:9, 1:1:0-1:1:9...  Sector%=block% 10  Cylinder%=(block% 10) 2  Track%=block% 20 ( sec%=Sector%+Track%*10+Cylinder%*800 , PRINT;Cylinder%;":";Track%;":";Sector%  FDCrd(addr%,sec%,drive%,1) * 4 : > ReadOneCPMBlock: p% BH Read a block of &800 bytes -> 4xBigSectors -> 8xSmallSectors ,R p%=0 3: Do each chunk of &200 bytes M\ AmsDOS%:FDCrd(addr%+p%*512,2*(block%*(bsz%512)+p%)+res%,drive%,2):: f sector512%=block%*4+p% p sector256%=sector512%*2 (z Track%=(sector256% 10)+(res% 10)  Sector%=sector256% 10  Sector%=Sector%*skew%  Sector%=Sector% 10  Cylinder%=Track% 80  Track%=Track% 80 - flip%: (Cylinder% 1):Track%=79-Track% ( sec%=Sector%+Track%*10+Cylinder%*800 , PRINT;Cylinder%;":";Track%;":";Sector% & FDCrd(addr%+p%*512,sec%,drive%,2)    :  :  FDC routines  ============ : %$FDCrd(ad%,sc%,dv%,nm%):dv%>1: 8.drv$<>"":in%=(drv$):in%=0:in%=(drv$+s$):in%=0: <8drv$<>"":gbpb(3,in%,ad%,nm%*256,sc%*256):#in%:in%=0: Bos%<6:FDCbbc: Los%=6:FDCarc: Vos%=32:FDCdos: `"Unsupported": j: tFDCbbc:fs%<>4:*FX143,18,4 )~A%=&7F:sc%>799:sc%=sc%-800:dv%=dv%+2 -try%=5::?X%=dv%:X%!1=ad%:X%?5=3:X%?6=&53 X%?8=sc%10:X%?7=sc%10 6X%!9=nm%32: OSWORD:try%=try%-1:X%?10=0 try%=0 ?X%?10:"Disk error &";~X%?10" at ";dv%":";sc%10"/";sc%10 fs%<>4:"FX143,18,"+fs%  : =FDCarc:trk%=sc%10:hd%=trk%80:trk%=trk%80:sec%=sc%10 L "XADFS_DiscOp",,1,((trk%*2+hd%)*10+sec%)*256+(dv%<<29),ad%,256*nm% r%  : FDCdos:"Unsupported": :  :  I/O routines  ============ %(ݤh0(A%,N%):="00000000"+~A%,N%) $2ݤd(A%,N%):=" "+A%,N%) <ݤuc(A$):A$="":="" EFA%=1A$:A$,A%,1)>"_":A$=A$,A%-1)+(A$,A%,1)&5F)+A$,A%+1) P:=A$ 6Zݤfx(A%,X%): Y%:Y%=X%256:=(&FFF4 &FFFF00)256 d: n File routines x ============= .ݤfs:A%,X%,Y%:os%<32:=(&FFDA)&FF =29 :gbpb(A%,ch%,X%!1,X%!5,X%!9):?X%=ch%:os%<32:&FFD1: (A%1):#?X%=X%!9 @A%=1 A%=2:#?X%,?X%!1:X%!1=X%!1+1:X%!5=X%!5-1: X%!5<1: HA%=3 A%=4:?X%!1=#?X%:X%!1=X%!1+1:X%!5=X%!5-1: #?X% X%!5<1:  :