10 REM > UnImg/s v1.12
   20 REM v1.12:
   30 REM  -i forces creation of INF file
   40 REM  -X long INF file
   50 REM  -s extract DFS files to subdirectories
   60 REM  -e extract DFS files with extensions
   70 REM To do:
   80 REM  Option to select drive(s) within dfs image
   90 REM  Second catalog of DFS62 disks
  100 :
  110 DIMctrl%127,name%79,zp%9:A$=FNOS_GetEnv+" ":IFos%=32:PROCWin_TextIO
  120 quit$=FNcl(" -qu",1):debug%=FNcl("-de",0):ON ERROR REPORT:PRINT:PROCexit(ERR)
  130 IFFNcl("-help",0):PRINT"UnImg v1.12 (C)J.G.Harston 2017";:A$="-?":PRINT" Single disk only"
  140 IFFNcl("-?",0):PRINT"Syntax: UnImg infile -d outdir -fs type -dsd -s -e -i -X -q -quit command":PROCexit(0)
  150 dsd%=FNcl("-ds",0):dst$=FNcl("-d",1):type$=FNcl("-f",1):sub%=FNcl("-s",0):ext%=FNcl("-e",0)
  160 vb%=NOTFNcl("-q",0):inf%=FNcl("-i",0):full%=FNcl("-X",0)
  170 in$=FNcl("",0):drv$=FNcl("",0)
  180 d$=".":s$="/":IFos%AND-24:d$="/":s$=".":IFos%AND-32:d$="\"
  190 :
  200 ON ERROR REPORT:PRINTLEFT$(" at line "+STR$ERL,ERR<128 AND ERR<>17):PROCClose_All:PROCexit(ERR)
  210 X%=ctrl%:Y%=X%DIV256:fln%=11:fmx%=-1:IF(os%AND-24):fln%=256
  220 DIMA%-1:max%=HIMEM-A%-2048+4096*(HIMEM>&FFFF):DIM mem% max%:wr%=2:rd%=4
  230 IFin$="":INPUT"File to extract from: "in$:INPUT"Image type:"SPC11type$:IFdst$="":INPUT"Destination path:"SPC5dst$
  240 in%=FNf_openin(in$):IFin%=0:PRINT"File '"in$"' not found":PROCexit(214)
  250 IFtype$="":fstype%=FNchkdisk ELSE fstype%=INSTR("HADFS",FNuc(type$))
  260 IFfstype%=0:CLOSE#in%:in%=0:PRINT"Unrecognised disk image":PROCexit(225)
  270 IFfstype%<2:tsz%=10:dsz%=&300:root%=&47:REM HADFS
  280 IFfstype%=2:tsz%=16:dsz%=&500:root%=&02:REM ADFS
  290 IFfstype%>2:tsz%=10:dsz%=&200:root%=&00:REM DFS
  300 DIM dir% dsz%-1
  310 :
  320 IFdebug%:PRINT" run$='"run$"'"'"quit$='"quit$"'"'"  in$='"in$"'"'" dst$='"dst$"'"'" drv$='"drv$"'"
  330 IFdebug%:PRINT" dsd=";dsd%;" verbose=";vb%;" inf%=";inf%;" full%=";full%
  340 IFdebug%:PRINT" fstype%=";fstype%
  350 IFdebug%:PRINT" tsz=";tsz%;" dsz=";dsz%;" root=&";~root%
  360 :
  370 PROCsavedir(root%,dst$):CLOSE#in%:in%=0:PROCexit(0):END
  380 :
  390 DEFFNchkdisk
  400 PROCf_gbpb(rd%-1,in%,mem%,4,&201):IF!mem%=&6F677548:=2:REM ADFS
  410 PROCf_gbpb(rd%-1,in%,mem%,8,&4610):IF!mem%=&29432800:=1:REM HADFS
  420 =3:REM DFS
  430 :
  440 DEFPROCmkdir:IFdst$<>"":PROCf_cdir(dst$):dst$=dst$+d$
  450 ENDPROC
  460 :
  470 DEFPROCsavedir(csd%,dst$)
  480 LOCAL num%,r0%,f%:PROCmkdir:REPEAT:PROCRdDir(csd%)
  490   IFnum%:f%=fn0%:REPEAT:num%=num%-FNsaveobject(f%):f%=f%+fsz%:UNTIL num%<1
  500   csd%=0:IFfstype%<2:csd%=dir%!14 AND &FFFF:IF(dir%?12)>127:csd%=dir%!23 AND &FFFFFF
  510 UNTIL csd%=0:ENDPROC
  520 :
  530 DEFFNsaveobject(fptr%)
  540 LOCAL fn$,lf$,ld%,ex%,nm%
  550 N%=0:REPEAT:A%=dir%?(fptr%+N%)AND127:IFA%>32:lf$=lf$+CHR$A%
  560 N%=N%+1:UNTIL N%=10 OR A%<33
  570 IFlf$="":IFfstype%<2:=0
  580 IFlf$="":=num%
  590 IFfstype%>2:lf$=CHR$(dir%?(fptr%+7)AND127)+"/"+LEFT$(lf$,7):IF(ASClf$AND-5)=32:lf$=MID$(lf$,3)
  600 A%=(fstype%>2)AND(MID$(lf$,2,1)="/")
  610 IFA%:IFsub%:lf$=LEFT$(lf$,1)+"."+MID$(lf$,3)
  620 IFA%:IFext%:lf$=MID$(lf$,3)+"/"+LEFT$(lf$,1)
  630 PROCgetattrs:fn$=FNf_name(FNfn_unbbc(lf$))
  640 IFvb%:PRINTlf$SPC(11-LENlf$)FNh0(ld%,8)" "FNh0(ex%,8)" "FNh0(nm%,6):REM " "FNh0(attr%,3)" "FNh0(sec%,6)
  650 IFattr%AND256:PROCsavedir(sec%,dst$+fn$):PROCRdDir(csd%) ELSE PROCsavefile
  660 PROCsetattrs:=1
  670 :
  680 DEFPROCsavefile
  690 A%=INSTR(fn$,d$):IFA%:PROCf_cdir(dst$+LEFT$(fn$,A%-1))
  700 X%!2=ld%:X%!6=ex%:X%!10=0:X%!14=nm%:A%=FNfile(dst$+fn$,7):len%=nm%
  710 out%=OPENOUT(dst$+fn$):REPEAT:cnt%=len%:IFlen%>max%:cnt%=max%AND-256
  720   PROCRdData(mem%,sec%,(cnt%+255)DIV256):PROCf_gbpb(wr%,out%,mem%,cnt%,0)
  730 sec%=sec%+(cnt%+255)DIV256:len%=len%-cnt%:UNTIL len%<1:CLOSE#out%:out%=0
  740 ENDPROC
  750 :
  760 DEFPROCgetattrs
  770 cdate%=0:mdate%=0:mtime%=0:usr%=0:IFfstype%>2:PROCdfsattrs:ENDPROC
  780 ld%=dir%!(fptr%+10):ex%=dir%!(fptr%+14):nm%=dir%!(fptr%+18)
  790 sec%=dir%!(fptr%+22)AND&FFFFFF:attr%=FNattr(fptr%)
  800 IFfstype%=2:attr%=(attr%AND3)+(attr%AND4)*2+(attr%AND8)*32+(attr%AND&1E0)DIV2:ENDPROC
  810 attr%=attr%EOR&33:usr%=dir%?19 OR (dir%?18DIV16) OR (dir%!20 AND &FFFF0000)
  820 mdate%=dir%!(fptr%+26):mtime%=dir%!(fptr%+28):cdate%=dir%!(fptr%+30)
  830 IFdir%?12>127:ENDPROC:REM Large directory
  840 nm%=nm%AND&7FFFF     :REM Small directory, 19-bit file length
  850 sec%=sec%AND&FFFF    :REM Small directory, 16-bit sector number
  860 mdate%=dir%!(fptr%+20)AND&FFF8
  870 mdate%=mdate%OR((dir%?(fptr%+9)AND&80)DIV128)
  880 mdate%=mdate%OR((dir%?(fptr%+13)AND&C0)DIV32)
  890 cdate%=mdate%:ld%=(ld%AND&3FFFFFFF):IF(ld%AND&20000000):ld%=ld%OR&C0000000
  900 ENDPROC
  910 :
  920 DEFPROCdfsattrs
  930 ld%=dir%!(fptr%+256)AND&FFFF:ex%=dir%!(fptr%+258)AND&FFFF
  940 nm%=dir%!(fptr%+260)AND&FFFF:sec%=dir%?(fptr%+263)
  950 A%=dir%!(fptr%+261)AND&FF00
  960 ld%=ld%OR((A%AND&0C00)*64):IFld%>&2FFFF:ld%=ld%OR&FFFF0000
  970 ex%=ex%OR((A%AND&C000)*4):IFex%>&2FFFF:ex%=ex%OR&FFFF0000
  980 nm%=nm%OR((A%AND&3000)*16):sec%=sec%OR(A%AND&0300)
  990 attr%=&33:IFdir%?(fptr%+7)>127:attr%=&19
 1000 ENDPROC
 1010 :
 1020 DEFPROCsetattrs
 1030 X%!2=ld%:X%!6=ex%:X%!14=attr%AND&7F:X%!15=mdate%:A%=FNfile(dst$+fn$,1)
 1040 IFinf%=0:IF(os%AND-24)=0:ENDPROC
 1050 inf$=FNfn_unbbc(lf$)+s$+"inf":IF(os%AND-24)=0:inf$=LEFT$(LEFT$(lf$,8)+s$+"inf",10)
 1060 inf$=dst$+inf$:IF(os%AND-24)=0:IFASCinf$=45:inf$="@."+inf$
 1070 IFfstype%>2:IFASCMID$(lf$,2,1)=47:lf$=LEFT$(lf$,1)+"."+MID$(lf$,3)
 1080 A$=lf$+" ":IFLENA$<11:A$=A$+STRING$(10-LENlf$," ")
 1090 A$=A$+FNh0(ld%,8)+" "+FNh0(ex%,8)+" "+FNh0(nm%,6)+" "+FNh0(attr%,2)
 1100 IF full%:IF fstype%<2:A$=A$+" "+FNh0(mdate%,4):IF dir%?12>127:A$=A$+" "+FNh0(mtime%,6)+" "+FNh0(cdate%,4)+" "+FNh0(cdate%,6)+" "+FNh0(acc%,4)+" "+FNh0(aux%,4)
 1110 A$=A$+CHR$13+CHR$10:out%=FNf_openout(inf$):FOR A%=1 TO LEN A$:BPUT#out%,ASCMID$(A$,A%,1):NEXT:CLOSE#out%:out%=0
 1120 A%=FNfile(inf$,5):X%!3=X%!3 OR &FFFFFF:A%=FNfile(inf$,2)
 1130 ENDPROC
 1140 :
 1150 DEFFNattr(f%):LOCAL a%,n%:FOR n%=0 TO 7:a%=a%DIV2+(dir%?(f%+n%)AND&80):NEXT:=a%OR((dir%?(f%+8)*2)AND&100)
 1160 :
 1170 DEFPROCRdDir(sect%)
 1180 PROCRdData(dir%,sect%,dsz%DIV256)
 1190 IFfstype%>2:fn0%=8:fsz%=8:num%=(dir%?&105)DIV8:ENDPROC
 1200 IFfstype%=2:fn0%=5:fsz%=26:num%=47:ENDPROC
 1210 IFfstype%<2:fn0%=24:fsz%=24:num%=(dir%?12)AND31:IFdir%?12>127:fn0%=32:fsz%=32
 1220 ENDPROC
 1230 :
 1240 DEFPROCRdData(ad%,sc%,nm%):LOCAL n%
 1250 FOR n%=0 TO nm%-1:PROCrd(ad%+256*n%,sc%+n%):NEXT:ENDPROC
 1260 :
 1270 DEFPROCrd(ad%,sc%):LOCAL t%,s%,h%
 1280 IFdsd%:t%=sc%DIVtsz%:s%=sc%MODtsz%:h%=t%DIV80:t%=t%MOD80:sc%=s%+h%*tsz%+t%*tsz%*2
 1290 PROCf_gbpb(rd%-1,in%,ad%,256,sc%*256)
 1300 ENDPROC
 1310 :