10
20
30
40
50
60 :
70 os%=FNfx(0,1)AND&FF:IFos%<6:IFFNfx(130,0)=&FFFF ELSE PRINT"Must run on BBC I/O processor":END
80 VDU10,8:A%=POS:VDU13:IFA%<50:MODE&87:IFHIMEM>&7C00:MODE&83:IFHIMEM>&4000:MODE&80
90 IF HIMEM<&FFFF:HIMEM=FNfx(132,0)
100 PROCinit:PRINT"USBFiler v"ver$" by J.G.Harston"':ON ERROR IF FNerr:END
110 REPEAT:X%=ctrl%:Y%=X%DIV256:D%=37:IFpath$="":path$="\"
120 IFdrv$="":PRINTCHR$(D%+48)"> "; ELSE PRINT"["drv$"] ";
130 INPUTLINE""A$:PROCdo(FNs(A$))
140 UNTIL0
150 :
160 DEFPROCinit:ver$="1.31"
170 DIM ctrl% 127,name% 255,result% 63,data% &1FF:X%=ctrl%:Y%=X%DIV256
180 DIM fn$(255):D%=0:drv$="":path$="\":title$="USB"
190 fs%=FNfs:d$=".":s$="/":IFos%=32:d$="\":s$="."
200 cmd$=":DIR:CD:TYPE:DUMP:COPY:INFO:BYE:HELP:QUIT:"
210 hlp$="::<dir>:<file> [CTRLS]:<file> [7BIT]:<usb source> <dest>:<file>::::"
220 PROCusb_Init:PROCusb_Sync:PROCusb_Flush:ENDPROC
230 :
240 DEFFNerr:OSCLI"FX229":REPORT:PROCusb_Flush
250 PROCCloseAll:PRINTLEFT$(" "+STR$ERL,ERR<128 AND ERR<>17):=INKEY-1 AND ERR<>17
260 DEFPROCCloseAll:in%=in%:IFin%:A%=in%:in%=0:CLOSE#A%
270 out%=out%:IFout%:A%=out%:out%=0:CLOSE#A%
280 ENDPROC
290 :
300 DEFPROCdo(A$):IFA$="?":A$="HELP"
310 IF LEFT$(A$,1)=";" OR A$="":ENDPROC
320 IF LEFT$(A$,1)="*" OSCLIA$:ENDPROC
330 IF LEFT$(A$,1)="." A$="CAT "+MID$(A$,2)
340 A%=INSTR(A$+" "," "):B$=FNuc(LEFT$(A$,A%-1)):A$=FNs(MID$(A$,A%+1))
350 IF LENB$=1 AND INSTR("0123",B$):drv$="":D%=VALB$:csd%=-1:ENDPROC
360 A%=INSTR(cmd$,":"+B$+":"):IF A%=0:PRINT"Bad command":ENDPROC
370 A%=EVAL("FN_"+B$+"(A$)"):ENDPROC
380 :
390 DEFFNsyn(S$):IF A$="":PRINT "Syntax: "B$" "S$:=TRUE ELSE =FALSE
400 :
410
420
430 :
440 DEFFN_QUIT(A$):PRINT"Quit":A%=FN_BYE("")
450 ON ERROR END
460 IF os%>5:*QUIT
470 END
480 :
490 DEFFN_HELP(A$):p%=2:q%=2:REPEAT
500 A%=INSTR(cmd$,":",p%):PRINT SPC2MID$(cmd$,p%,A%-p%);:p%=A%+1
510 A%=INSTR(hlp$,":",q%):PRINT TAB(8)MID$(hlp$,q%,A%-q%):q%=A%+1
520 UNTIL p%>LENcmd$:=0
530 :
540 DEFFN_DIR(A$):PROCLstDir(0):=0
550 DEFFN_EX(A$):PROCLstDir(1):=0
560 :
570 DEFFN_CD(A$):IFA$=".":=0
580 IFA$="\":REPEATPROCusb_Cmd("CD .."):UNTILresult%?1<>ASC":":path$="\":=0
590 A$=FNcl("",0):PROCusb_Cmd("CD "+A$):IFFNusb_Err:=TRUE
600 IFA$<>"..":path$=path$+A$+"\":=0
610 REPEATpath$=LEFT$(path$,LENpath$-1):UNTILRIGHT$("\"+path$,1)="\":=0
620 :
630 DEFFN_DUMP(A$):LOCAL ln%,p%,ptr%,cols%:cols%=16:IF FNsyn("<fsp>"):=TRUE
640 A$=FNcl("",0):PROCusb_Sync:ln%=FNusb_Size(A$):IFln%=0 OR FNusb_Err:=TRUE
650 PROCusb_WrStr("RD "+A$+CHR$13)
660 FOR P%=0 TO ln%-1 STEP cols%:B$=""
670 PRINTFNh0(P%,6)" ";:IF(P%AND&1FF)=0:PROCReadData(P%,ln%):O%=data%
680 FOR Q%=P% TO P%+cols%-1
690 IF Q%<ln%:PRINTFNh0(?O%,2)" "; ELSE ?O%=32:PRINTSPC3;
700 A$=CHR$(?O%AND&7F):IF A$>=" " AND A$<="~" B$=B$+A$ ELSE B$=B$+"."
710 O%=O%+1:NEXT:PRINT B$:NEXT
720 =0
730 :
740 DEFFN_TYPE(A$):LOCAL ln%,p%,ptr%:IF FNsyn("<fsp>"):=TRUE
750 msk%=INSTR(A$," [")<>0:msk%=(msk%AND&80)OR&7F
760 A$=FNcl("",0):PROCusb_Sync:ln%=FNusb_Size(A$):IFFNusb_Err:=TRUE
770 PROCusb_WrStr("RD "+A$+CHR$13)
780 last%=0:FOR P%=0 TO ln%-1:IF(P%AND&1FF)=0:PROCReadData(P%,ln%):O%=data%
790 Q%=?O%ANDmsk%:IFmsk%=255:VDUQ% ELSE IFQ%=10 OR Q%=13 OR Q%>31 VDUQ%
800 IF(Q%=10 OR Q%=13) AND Q%<>last%:VDU23-Q%
810 IFQ%=9:PRINTSPC(8-(POS MOD 8));
820 last%=?O%:O%=O%+1:NEXT:IFPOS:PRINT
830 =0
840 :
850 DEFFN_INFO(A$):IF FNsyn("<fsp>"):=TRUE
860 A$=FNcl("",0):PROCusb_Sync:A%=FNusb_Info(A$):IFX%!10=0 OR FNusb_Err:=TRUE
870 PRINTA$;SPC(15-LENA$);FNh0(X%!2,8)" "FNh0(X%!6,8)" "FNh0(X%!10,8)
880 =0
890 :
900 DEFFN_BYE(A$):PROCusb_Cmd("SUD"):PROCusb_Sync:PROCusb_Flush:=0
910 :
920 DEFFN_COPY(A$):IF FNsyn("<usb source> <dest>"):=TRUE
930 src$=FNcl("",0):dst$=FNcl("",0)
940 IFFNuc(LEFT$(dst$,4))="USB:":dst$=MID$(dst$,5):PROCCopyBBCtoUSB:=0
950 IFFNuc(LEFT$(src$,4))="USB:":src$=MID$(src$,5)
960 IFINSTR(dst$,"::")ORLEFT$(dst$,1)="-":PRINT"FS prefix unsupported":=TRUE
970 PROCCopyUSBtoBBC:=0
980 :
990
1000
1010
1020
1030 :
1040 DEFPROCCopyUSBtoBBC:IFsrc$="\":A%=FN_CD("\"):src$=""
1050 IFsrc$<>"":IFFNusb_Info(src$)=1:PROCCopyOneFile(src$,dst$):ENDPROC
1060 IFsrc$<>"":IFFN_CD(src$):ENDPROC
1070 IFdst$<>"":PROCcdir(dst$):dst$=dst$+d$
1080 PROCCopyDirectory(dst$)
1090 ENDPROC
1100 :
1110 DEFPROCCopyBBCtoUSB:PRINT"BBCtoUSB: not implemented":ENDPROC
1120 :
1130 :
1140
1150
1160 :
1170 DEFPROCCopyDirectory(dst$):LOCAL fn%,n%:PROCusb_RdDir:IFfn%<2:ENDPROC
1180 FOR n%=0 TO fn%-2:PROCCopyObject:NEXT:ENDPROC
1190 :
1200 DEFPROCCopyObject:leaf$=fn$(n%):IFleaf$=". DIR" OR leaf$=".. DIR":ENDPROC
1210 fname$=LEFT$(FNundos(leaf$),10)
1220 A%=INSTR(leaf$," "):IFA%=0:A%=FN_INFO(leaf$):PRINTCHR$11;STRING$(42,CHR$9);:PROCCopyOneFile(leaf$,dst$+fname$):ENDPROC
1230 leaf$=LEFT$(leaf$,A%-1):fname$=LEFT$(fname$,A%-1)
1240 IFFNfile(dst$+fname$,5)=0:OSCLI"CDir "+dst$+fname$
1250 A%=FN_CD(leaf$):PROCCopyDirectory(dst$+fname$+d$):A%=FN_CD("..")
1260 PROCusb_RdDir:ENDPROC
1270 :
1280 DEFPROCCopyOneFile(src$,dst$)
1290 IFdst$="":PRINT"<dest> missing":ENDPROC
1300 PRINT"Copying "src$" to "dst$" ";
1310 load%=X%!2:exec%=X%!6:ln%=X%!10:attr%=X%!14
1320 IFFNfile(dst$,5):X%!14=&33:A%=FNfile(dst$,4)
1330 X%!2=load%:X%!6=exec%:X%!10=0:X%!14=ln%:A%=FNfile(dst$,7)
1340 IFln%:PROCCopyData:
1350 PROCSetInfo(dst$):PRINTSTRING$(3,CHR$127):ENDPROC
1360 :
1370 DEFPROCCopyData
1380 PROCusb_Sync:PROCusb_WrStr("RD "+src$+CHR$13)
1390 out%=OPENOUT(dst$):P%=0:REPEAT
1400 PROCReadData(P%,ln%):IF(P%AND1023)=0:PRINTSTRING$(3,CHR$8)FNd(100*P%DIVln%,2)"%";
1410 num%=512:IFP%+num%>ln%:num%=ln%-P%
1420 PROCgbpb(2,out%,data%,num%,0):P%=P%+512:UNTILP%>ln%
1430 CLOSE#out%:out%=0:ENDPROC
1440 :
1450 DEFPROCSetInfo(dst$):X%!2=load%:X%!6=exec%:X%!10=ln%:X%!14=attr%:A%=FNfile(dst$,1)
1460 ENDPROC
1470 :
1480 :
1490
1500
1510 :
1520 DEFPROCLstDir(cflg%):
1530 PRINT "Path: "title$":"path$'
1540 PROCusb_Sync:PROCusb_Cmd("DIR"):IFFNusb_Err:ENDPROC
1550 x%=0:REPEATREPEATUNTIL(?usbS AND 128)=0
1560 A%=?usbD:IF A%=13 PRINTSPC(20-(POS MOD 20)); ELSE VDUA%
1570 IFA%=ASC":":x%=1
1580 UNTILA%=13 AND x%=1:PRINTSTRING$(20,CHR$127);:IFPOS:PRINT
1590 ENDPROC
1600 :
1610 DEFPROCReadData(ptr%,ext%):LOCAL p%
1620 IFptr%+512<=ext%:CALL usbRdData:ENDPROC
1630 REPEAT:data%?p%=USRusbRd:p%=p%+1:UNTILptr%+p%>=ext%ORp%>511
1640 IFp%<512:REPEATdata%?p%=0:p%=p%+1:UNTILp%>511
1650 ENDPROC
1660 :
1670 :
1680
1690
1700 :
1710 DEFPROCusb_Sync:REPEATA%=?usbD:UNTIL(?usbS AND 128):ENDPROC
1720 :
1730 DEFPROCusb_Flush:IF(?usbS AND 128):ENDPROC
1740 PRINT'"Flushing USB";:REPEAT:REPEATA%=?usbD:UNTIL(?usbS AND 128)
1750 A%=TIME+20:REPEATUNTILTIME>A%:UNTIL(?usbS AND 128):ENDPROC
1760 :
1770 DEFFNusb_Err:IF?result%=13 OR result%?1=ASC":":=0 ELSE PRINT"USB Error: "$result%:=TRUE
1780 :
1790 DEFPROCusb_Cmd(A$):PROCusb_WrStr(A$+CHR$13):PROCusb_RdStr:ENDPROC
1800 :
1810 DEFFNusb_Size(A$):PROCusb_Cmd("IPH"):PROCusb_Cmd("DIR "+A$)
1820 REPEATUNTIL(?usbS AND 128)=0
1830 A%=result%-1:REPEATA%=A%+1:?A%=?usbD:UNTIL(?usbS AND 128):IFA%?-1<>62:=0
1840 A%=INSTR($result%," "):?result%=13:=result%!A%
1850 :
1860 DEFFNusb_Info(A$):LOCAL L%,X$:X%!2=0:X%!6=0:X%!14=&33:X%!10=FNusb_Size(A$)
1870 IFINSTR(A$,".") OR ?result%<>13:=1
1880 L%=FNusb_Size(A$+".INF"):IFL%>512 OR ?result%<>13:?result%=13:=1
1890 PROCusb_WrStr("RD "+A$+".INF"+CHR$13)
1900 PROCReadData(0,L%):data%?L%=13:A$=$data%:X$=FNcl("",0)
1910 X$=FNcl("",0):IFX$<>"":X%!2=EVAL("&"+X$):X%!6=X%!2
1920 X$=FNcl("",0):IFX$<>"":X%!6=EVAL("&"+X$)
1930 =1
1940 :
1950 DEFPROCusb_RdDir:fn%=0:PROCusb_Sync:PROCusb_Cmd("DIR"):IFFNusb_Err:ENDPROC
1960 REPEAT:REPEATPROCusb_RdStr:fn$(fn%)=$result%:fn%=fn%+1:UNTIL(?usbS AND 128)
1970 A%=TIME+20:REPEATUNTILTIME>A%:UNTIL(?usbS AND 128):ENDPROC
1980 :
1990 DEFPROCusb_WrStr(A$):FOR A%=1 TO LEN A$:REPEATUNTIL(?usbS AND 64)=0
2000 ?usbD=ASCMID$(A$,A%,1):NEXT:ENDPROC
2010 :
2020 DEFPROCusb_RdStr:A%=result%-1:REPEATA%=A%+1:?A%=FNusb_Rd:UNTIL?A%=13:ENDPROC
2030 :
2040 DEFFNusb_Rd:REPEATUNTIL(?usbS AND 128)=0:=?usbD
2050 :
2060 DEFPROCusb_Init
2070 usbD=&FCF8:usbS=&FCF9:OSASCI=&FFE3:OSBPUT=&FFD4
2080 DIM mc% 39:FOR P=0 TO 1:P%=mc%:[OPT P*2
2090 .usbRdData:LDX #0:.usbRdLp1:JSR usbRd:STA data%,X:INX:BNE usbRdLp1
2100 .usbRdLp2:JSR usbRd:STA data%+256,X:INX:BNE usbRdLp2:RTS
2110 .usbRd:BIT usbS:BPL usbRd2:BIT &FF:BPL usbRd
2120 .usbRd2:LDA usbD:RTS:]NEXT
2130 ENDPROC
2140 :
2150 :
2160
2170
2180
2190 DEFFNfn_undos(A$):LOCALB%:IF(os%AND-32):=A$
2200 FORA%=1TOLEN A$:B%=INSTR("#$^&@%~",MID$(A$,A%,1)):IFB%:A$=LEFT$(A$,A%-1)+MID$("?<>+=;\",B%,1)+MID$(A$,A%+1)
2210 NEXT:=A$
2220 :
2230 :
2240
2250
2260 DEFFNh0(A%,N%):=RIGHT$("00000000"+STR$~A%,N%)
2270 DEFFNd(A%,N%):=RIGHT$(" "+STR$A%,N%)
2280 DEFFNd0(A%,N%):=RIGHT$("00000000"+STR$A%,N%)
2290 DEFFNuc(A$):IFA$="":=""
2300 FORA%=1TOLENA$:IFMID$(A$,A%,1)>"_":A$=LEFT$(A$,A%-1)+CHR$(ASCMID$(A$,A%,1)AND&5F)+MID$(A$,A%+1)
2310 NEXT:=A$
2320 DEFFNfx(A%,X%):LOCAL Y%:Y%=X%DIV256:=(USR&FFF4 AND &FFFF00)DIV256
2330 :
2340
2350
2360 DEFFNfs:LOCAL A%,Y%,E%:=(USR&FFDA)AND&FF
2370 DEFPROCgbpb(A%,chn%,addr%,num%,ptr%):?X%=chn%
2380 X%!1=addr%:X%!5=num%:X%!9=ptr%:CALL &FFD1:ENDPROC
2390 DEFPROCcdir(A$):IFFNfile(A$,5)=0:OSCLI"CDIR "+A$
2400 ENDPROC
2410 DEFFNfile(A$,A%):$name%=A$:?X%=name%:X%?1=name%DIV256:=(USR&FFDD)AND&FF
2420 :
2430 :
2520
2530
2540 DEFFNcl(l$,n%):IFl$="":A$=FNs(A$):IFASCA$=34:A%=INSTR(A$+" "" ",""" ",2):l$=MID$(A$,2,A%-2):A$=FNs(MID$(A$,A%+1)):=l$
2550 IFl$="":A%=INSTR(A$+" "," "):l$=LEFT$(A$,A%-1):A$=FNs(MID$(A$,A%+1)):=l$
2560 IFn%=0:IFl$<>"":A%=INSTR(A$,l$):IFA%:A$=FNs(LEFT$(A$,A%-1)+MID$(A$,INSTR(A$," ",A%)+1)):=TRUE
2570 IFn%=0:IFl$<>"":=FALSE
2580 A%=INSTR(LEFT$(" ",ASCl$=32)+A$,l$):IFA%=0:=""
2590 A$=LEFT$(A$,A%-1)+FNs(MID$(A$,INSTR(A$," ",A%)+1))
2600 IFASCl$=32:l$=MID$(A$,A%):A$=LEFT$(A$,A%-1):=MID$(l$,1-(ASCl$=34),LENl$+2*(ASCl$=34))
2610 IFASCMID$(A$,A%,1)<>34:l$=MID$(A$,A%,INSTR(A$+" "," ",A%)-A%):A$=LEFT$(A$,A%-1)+MID$(A$,A%+LENl$+1):=l$
2620 l$=MID$(A$,A%+1,INSTR(A$+""" ",""" ",A%+1)-A%-1):A$=LEFT$(A$,A%-1)+MID$(A$,A%+LENl$+3):=l$
2630 DEFFNs(A$):IFLEFT$(A$,1)=" ":REPEATA$=MID$(A$,2):UNTILLEFT$(A$,1)<>" "
2640 IFRIGHT$(A$,1)=" ":REPEATA$=LEFT$(A$,LENA$-1):UNTILRIGHT$(A$,1)<>" "
2650 =A$