10 REM > FileToDisk 0.43 04-Jun-2018 J.G.Harston
   20 REM Copy image file to physical disk
   30 :
   40 PRINT "Copy disk image to whole disk"
   50 PRINT "***WARNING*** THIS WILL COMPLETELY OVERWRITE YOUR DISK"'
   60 max%=(HIMEM-LOMEM-1024)DIV256:oldfs%=FNfs:IF max%<2:MODE &87:RUN
   70 DIM ctrl% 31,data% 256*max%-1:X%=ctrl%:Y%=X%DIV256
   80 ON ERROR REPORT:PROCend:END
   90 :
  100 INPUTLINE"Source image file:   "in$
  110 INPUTLINE"Dest. filing system: "type$
  120 INPUTLINE"Dest. drive:         "drv%
  130 OSCLI type$:thisfs%=FNfs
  140 REPEAT:READ fs$,fn$,A$,retry%
  150 UNTIL fs$="*" OR fs$=STR$thisfs%
  160 IF fs$="*":PRINT "Unsupported filing system":PROColdfs:END
  170 DATA 4,disk,7F,3, 8,adfs,72,1, 10,adfs,62,1, 16,hadfs,5A,1, 29,disk,77,1
  180 REM     DISK         ADFS         LVFS          HADFS           RAM
  190 DATA *,*,*,*
  200 :
  210 REM Should check image size
  220 osw%=EVAL("&"+A$):dsize%=FNsize
  230 PRINT"Total disk sectors (&";~dsize%;"): &";:INPUT""A$:IFA$<>"":dsize%=EVAL("&"+A$)
  240 IFdsize%>&FFF:INPUT"This is a hard drive - continue? "A$:A$=CHR$(ASCA$AND&DF):IF A$<>"Y":PROCend:END
  250 PROColdfs:in%=OPENIN(in$):IFin%=0:PRINT"File '"in$"' not found":PROCend:END
  260 :
  270 sect%=0:thisnum%=max%
  280 REPEAT
  290   num%=max%:IF sect%+num%>dsize%:num%=dsize%-sect%
  300   IF thisnum%<num%:num%=thisnum%
  310   VDU13:PRINT"Reading   ";FNh0(sect%,6);"+";FNh0(thisnum%,2);
  320   PROCgbpb(4,in%,data%,num%*256,0)
  330   thisnum%=FNwrite(sect%,thisnum%)
  340   sect%=sect%+thisnum%
  350   IF num%=thisnum%:thisnum%=thisnum%*2:IF thisnum%>max%:thisnum%=max%
  360 UNTILsect%>=dsize%
  370 :
  380 VDU13:PRINT"Closing";SPC14;
  390 PROColdfs:CLOSE#in%
  400 VDU13:PRINT"Done";SPC17
  410 REM Needs fixup to match image size with disk size
  420 END
  430 :
  440 DEFPROColdfs
  450 IFoldfs%:OSCLI"FX143,18,"+STR$oldfs%:oldfs%=0
  460 ENDPROC
  470 :
  480 DEFPROCend
  490 PROColdfs:PRINT
  500 ENDPROC
  510 :
  520 DEFFNwrite(sect%,num%)
  530 REPEAT
  540   try%=retry%
  550   REPEAT
  560     VDU13:PRINT"Writing ";FNh0(drv%,1);":";FNh0(sect%,6);"+";FNh0(num%,2);
  570     err%=FNattempt(num%):try%=try%-1
  580   UNTIL try%<1 OR err%=0
  590   IF err%:num%=(num%+2)DIV4
  600 UNTIL err%=0 OR num%<1
  610 =num%-(num%<1)
  620 :
  630 DEFFNattempt(num%)
  640 IFfn$="disk":err%=FNdisk(data%,&4B,drv%,sect%,num%,osw%)
  650 IFfn$="adfs":err%=FNadfs(data%,10,drv%,sect%,num%,osw%)
  660 IFfn$="hadfs":err%=FNhadfs(data%,&81,drv%,sect%,num%,osw%)
  670 VDU13:A%=FNdisk_err(err%,drv%,sect%,num%)
  680 =err%
  690 :
  700 DEFFNsize
  710 LOCAL size%
  720 IFfn$="disk":err%=FNdisk(data%,&53,drv%,1,1,osw%):size%=data%?7+256*(data%?6 AND 3):sect%=1
  730 IFfn$="adfs":err%=FNadfs(data%,8,drv%,0,1,osw%):size%=data%!&FC AND &FFFFFF:sect%=0
  740 IFfn$="hadfs":err%=FNhadfs(data%,&80,drv%,&46,1,osw%):size%=data%!28 AND &FFFFFF:sect=&46
  750 VDU13:A%=FNdisk_err(err%,drv%,sect%,1)
  760 =size%
  770 :
  780 REM Disk access routines
  790 REM ====================
  800 DEFFNfs:LOCALA%,E%,Y%:=(USR&FFDA)AND&FF
  810 DEFFNdisk(addr%,cmd%,drv%,trk%,sec%,num%,osw%):LOCALn%:den%=1
  820 REPEAT:n%=num%:IFsec%+n%>10:n%=10-sec%
  830   REPEAT:X%?0=drv%+den%*24+8+2*(trk%DIV80):X%!1=addr%:X%?5=3-7*(cmd%>127)
  840     X%?6=cmd%:X%?7=trk%MOD80:X%?8=sec%:X%!9=n%OR&1E20:A%=osw%:CALL&FFF1
  850   A%=X%?(7+X%?5):UNTILA%<>&10:addr%=addr%+n%*256:num%=num%-n%:sec%=(sec%+n%)MOD10:trk%=trk%+1
  860 UNTILA%<>0ORnum%<1:=A%
  870 DEFFNadfs(addr%,cmd%,drv%,sect%,num%,osw%)
  880 LOCAL fs%:fs%=FNfs:IF fs%<>8:*FADFS
  890 X%?0=1:X%!1=addr%:X%?5=cmd%:X%?6=drv%*32+((sect%AND&1F0000)DIV65536)
  900 X%?7=((sect%AND&FF00)DIV256):X%?8=sect%:X%!9=num%:X%!11=0
  910 A%=osw%:CALL&FFF1
  920 IF fs%<>8:OSCLI"DISMOUNT":OSCLI"FX143,18,"+STR$fs%
  930 =?X%
  940 DEFFNhadfs(addr%,cmd%,drv%,sect%,num%,osw%)
  950 !X%=&600:X%!2=addr%:X%!6=sect%:X%?9=drv%:X%?10=num%:X%?11=cmd%
  960 A%=osw%:CALL&FFF1:=X%?12
  970 DEFFNdisk_err(A%,D%,S%,N%)
  980 IFA%:PRINT"Disk error ";FNh0(A%,2);" at ";FNh0(D%,1);":";FNh0(S%,6);"+";FNh0(N%,2)
  990 =A%
 1000 :
 1010 REM I/O routines
 1020 REM ============
 1030 DEFFNh0(A%,N%):=RIGHT$("00000000"+STR$~A%,N%)
 1040 DEFFNfx(A%,X%):LOCAL Y%:Y%=X%DIV256:=(USR&FFF4 AND &FFFF00)DIV256
 1050 DEFPROCgbpb(A%,chn%,addr%,num%,ptr%)
 1060 REM Test code
 1070 IFFNfs<>17:?X%=chn%:X%!1=addr%:X%!5=num%:X%!9=ptr%:CALL&FFD1:ENDPROC
 1080 REPEAT?addr%=BGET#chn%:addr%=addr%+1:num%=num%-1:UNTILnum%<1:ENDPROC