10
20
30
40
50
60
70
80
90
100
110 :
120 DIMctrl%127,name%79,zp%9:A$=FNOS_GetEnv+" ":IFos%=32:PROCWin_TextIO
130 quit$=FNcl(" -qu",1):debug%=FNcl("-de",0):ON ERROR REPORT:PRINT:PROCexit(ERR)
140 IFFNcl("-help",0):PRINT"UnImg v1.11a (C)J.G.Harston 2017";:A$="-?":PRINT" Single disk only"
150 IFFNcl("-?",0):PRINT"Syntax: UnImg infile -d outdir -fs type -dsd -s -e -i -X -q -quit command":PROCexit(0)
160 dsd%=FNcl("-ds",0):dst$=FNcl("-d",1):type$=FNcl("-f",1):sub%=FNcl("-s",0):ext%=FNcl("-e",0)
170 vb%=NOTFNcl("-q",0):inf%=FNcl("-i",0):full%=FNcl("-X",0)
180 in$=FNcl("",0):drv$=FNcl("",0)
190 d$=".":s$="/":IFos%AND-24:d$="/":s$=".":IFos%AND-32:d$="\"
200 :
210 ON ERROR REPORT:PRINTLEFT$(" at line "+STR$ERL,ERR<128 AND ERR<>17):PROCClose_All:PROCexit(ERR)
220 X%=ctrl%:Y%=X%DIV256:fln%=11:fmx%=-1:IF(os%AND-24):fln%=256
230 DIMA%-1:max%=HIMEM-A%-2048+4096*(HIMEM>&FFFF):DIM mem% max%:wr%=2:rd%=4
240 IFin$="":INPUT"File to extract from: "in$:INPUT"Image type:"SPC11type$:IFdst$="":INPUT"Destination path:"SPC5dst$
250 in%=FNf_openin(in$):IFin%=0:PRINT"File '"in$"' not found":PROCexit(214)
260 IFtype$="":fstype%=FNchkdisk ELSE fstype%=INSTR("HADFS",FNuc(type$))
270 IFfstype%=0:CLOSE#in%:in%=0:PRINT"Unrecognised disk image":PROCexit(225)
280 IFfstype%<2:tsz%=10:dsz%=&300:root%=&47:
290 IFfstype%=2:tsz%=16:dsz%=&500:root%=&02:
300 IFfstype%>2:tsz%=10:dsz%=&200:root%=&00:
310 DIM dir% dsz%-1
320 :
330 IFdebug%:PRINT" run$='"run$"'"'"quit$='"quit$"'"'" in$='"in$"'"'" dst$='"dst$"'"'" drv$='"drv$"'"
340 IFdebug%:PRINT" dsd=";dsd%;" verbose=";vb%;" inf%=";inf%;" full%=";full%
350 IFdebug%:PRINT" fstype%=";fstype%
360 IFdebug%:PRINT" tsz=";tsz%;" dsz=";dsz%;" root=&";~root%
370 :
380 PROCsavedir(root%,dst$):CLOSE#in%:in%=0:PROCexit(0):END
390 :
400 DEFFNchkdisk
410 PROCf_gbpb(rd%-1,in%,mem%,4,&201):IF!mem%=&6F677548:=2:
420 PROCf_gbpb(rd%-1,in%,mem%,8,&4610):IF!mem%=&29432800:=1:
430 =3:
440 :
450 DEFPROCmkdir:IFdst$<>"":PROCf_cdir(dst$):dst$=dst$+d$
460 ENDPROC
470 :
480 DEFPROCsavedir(csd%,dst$)
490 LOCAL num%,r0%,f%:PROCmkdir:REPEAT:PROCRdDir(csd%)
500 IFnum%:f%=fn0%:REPEAT:num%=num%-FNsaveobject(f%):f%=f%+fsz%:UNTIL num%<1
510 csd%=0:IFfstype%<2:csd%=dir%!14 AND &FFFF:IF(dir%?12)>127:csd%=dir%!23 AND &FFFFFF
520 UNTIL csd%=0:ENDPROC
530 :
540 DEFFNsaveobject(fptr%)
550 LOCAL fn$,lf$,ld%,ex%,nm%
560 N%=0:REPEAT:A%=dir%?(fptr%+N%)AND127:IFA%>32:lf$=lf$+CHR$A%
570 N%=N%+1:UNTIL N%=10 OR A%<33
580 IFlf$="":IFfstype%<2:=0
590 IFlf$="":=num%
600 IFfstype%>2:lf$=CHR$(dir%?(fptr%+7)AND127)+"/"+LEFT$(lf$,7):IF(ASClf$AND-5)=32:lf$=MID$(lf$,3)
610 A%=(fstype%>2)AND(MID$(lf$,2,1)="/")
620 IFA%:IFsub%:lf$=LEFT$(lf$,1)+"."+MID$(lf$,3)
630 IFA%:IFext%:lf$=MID$(lf$,3)+"/"+LEFT$(lf$,1)
640 PROCgetattrs:fn$=FNf_name(FNfn_unbbc(lf$))
650 IFvb%:PRINTlf$SPC(11-LENlf$)FNh0(ld%,8)" "FNh0(ex%,8)" "FNh0(nm%,6):
660 IFattr%AND256:PROCsavedir(sec%,dst$+fn$):PROCRdDir(csd%) ELSE PROCsavefile
670 PROCsetattrs:=1
680 :
690 DEFPROCsavefile
700 A%=INSTR(fn$,d$):IFA%:PROCf_cdir(dst$+LEFT$(fn$,A%-1))
710 X%!2=ld%:X%!6=ex%:X%!10=0:X%!14=nm%:A%=FNfile(dst$+fn$,7):len%=nm%
720 out%=OPENOUT(dst$+fn$):REPEAT:cnt%=len%:IFlen%>max%:cnt%=max%AND-256
730 PROCRdData(mem%,sec%,(cnt%+255)DIV256):PROCf_gbpb(wr%,out%,mem%,cnt%,0)
740 sec%=sec%+(cnt%+255)DIV256:len%=len%-cnt%:UNTIL len%<1:CLOSE#out%:out%=0
750 ENDPROC
760 :
770 DEFPROCgetattrs
780 cdate%=0:mdate%=0:mtime%=0:usr%=0:IFfstype%>2:PROCdfsattrs:ENDPROC
790 ld%=dir%!(fptr%+10):ex%=dir%!(fptr%+14):nm%=dir%!(fptr%+18)
800 sec%=dir%!(fptr%+22)AND&FFFFFF:attr%=FNattr(fptr%)
810 IFfstype%=2:attr%=(attr%AND3)+(attr%AND4)*2+(attr%AND8)*32+(attr%AND&1E0)DIV2:ENDPROC
820 attr%=attr%EOR&33:usr%=dir%?19 OR (dir%?18DIV16) OR (dir%!20 AND &FFFF0000)
830 mdate%=dir%!(fptr%+26):mtime%=dir%!(fptr%+28):cdate%=dir%!(fptr%+30)
840 IFdir%?12>127:ENDPROC:
850 nm%=nm%AND&7FFFF :
860 sec%=sec%AND&FFFF :
870 mdate%=dir%!(fptr%+20)AND&FFF8
880 mdate%=mdate%OR((dir%?(fptr%+9)AND&80)DIV128)
890 mdate%=mdate%OR((dir%?(fptr%+13)AND&C0)DIV32)
900 cdate%=mdate%:ld%=(ld%AND&3FFFFFFF):IF(ld%AND&20000000):ld%=ld%OR&C0000000
910 ENDPROC
920 :
930 DEFPROCdfsattrs
940 ld%=dir%!(fptr%+256)AND&FFFF:ex%=dir%!(fptr%+258)AND&FFFF
950 nm%=dir%!(fptr%+260)AND&FFFF:sec%=dir%?(fptr%+263)
960 A%=dir%!(fptr%+261)AND&FF00
970 ld%=ld%OR((A%AND&0C00)*64):IFld%>&2FFFF:ld%=ld%OR&FFFF0000
980 ex%=ex%OR((A%AND&C000)*4):IFex%>&2FFFF:ex%=ex%OR&FFFF0000
990 nm%=nm%OR((A%AND&3000)*16):sec%=sec%OR(A%AND&0300)
1000 attr%=&33:IFdir%?(fptr%+7)>127:attr%=&19
1010 ENDPROC
1020 :
1030 DEFPROCsetattrs
1040 X%!2=ld%:X%!6=ex%:X%!14=attr%AND&7F:X%!15=mdate%:A%=FNfile(dst$+fn$,1)
1050 IFinf%=0:IF(os%AND-24)=0:ENDPROC
1060 inf$=FNfn_unbbc(lf$)+s$+"inf":IF(os%AND-24)=0:inf$=LEFT$(LEFT$(lf$,8)+s$+"inf",10)
1070 inf$=dst$+inf$:IF(os%AND-24)=0:IFASCinf$=45:inf$="@."+inf$
1080 IFfstype%>2:IFASCMID$(lf$,2,1)=47:lf$=LEFT$(lf$,1)+"."+MID$(lf$,3)
1090 A$=lf$+" ":IFLENA$<11:A$=A$+STRING$(10-LENlf$," ")
1100 A$=A$+FNh0(ld%,8)+" "+FNh0(ex%,8)+" "+FNh0(nm%,6):IF full%:A$=A$+" "+FNh0(attr%,2)
1110 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)
1120 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
1130 A%=FNfile(inf$,5):X%!3=X%!3 OR &FFFFFF:A%=FNfile(inf$,2)
1140 ENDPROC
1150 :
1160 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)
1170 :
1180 DEFPROCRdDir(sect%)
1190 PROCRdData(dir%,sect%,dsz%DIV256)
1200 IFfstype%>2:fn0%=8:fsz%=8:num%=(dir%?&105)DIV8:ENDPROC
1210 IFfstype%=2:fn0%=5:fsz%=26:num%=47:ENDPROC
1220 IFfstype%<2:fn0%=24:fsz%=24:num%=(dir%?12)AND31:IFdir%?12>127:fn0%=32:fsz%=32
1230 ENDPROC
1240 :
1250 DEFPROCRdData(ad%,sc%,nm%):LOCAL n%
1260 FOR n%=0 TO nm%-1:PROCrd(ad%+256*n%,sc%+n%):NEXT:ENDPROC
1270 :
1280 DEFPROCrd(ad%,sc%):LOCAL t%,s%,h%
1290 IFdsd%:t%=sc%DIVtsz%:s%=sc%MODtsz%:h%=t%DIV80:t%=t%MOD80:sc%=s%+h%*tsz%+t%*tsz%*2
1300 PROCf_gbpb(rd%-1,in%,ad%,256,sc%*256)
1310 ENDPROC
1320 :
1330
1340
1350
1360 :
1370 DEFPROCcd(A$):IFA$="^":OSCLI"cd ..":ENDPROC ELSE OSCLI"cd "+A$:ENDPROC
1380 :
1390 DEFFNfn_zip(B$):LOCALB%:A$="#?./$<^>&+@=%; "
1400 FOR A%=1 TO LEN B$:B%=INSTR(A$,MID$(B$,A%,1))-1
1410 IF B%>TRUE:B$=LEFT$(B$,A%-1)+MID$(A$+"_",(B%EOR1)+1,1)+MID$(B$,A%+1)
1420 NEXT:=B$
1430 DEFFNfn_unbbc(B$):IF(os%AND-24)=0:=B$
1440 LOCALB%:A$="#?./$<^>&+@=%; "
1450 FOR A%=1 TO LEN B$:B%=INSTR(A$,MID$(B$,A%,1))-1
1460 IF B%>TRUE:B$=LEFT$(B$,A%-1)+MID$(A$+"_",(B%EOR1)+1,1)+MID$(B$,A%+1)
1470 NEXT:=B$
1480 :
1490 DEFFNd0(A%,N%):=RIGHT$("00000000"+STR$A%,N%)
1500 DEFFNh0(A%,N%):=RIGHT$("0000000"+STR$~A%,N%)
1510 DEFFNbyte(A%,X%,Y%)=((USR&FFF4)AND&FF00)DIV256
1520 DEFPROCClose_All:*EXEC
1530 in%=in%:IFin%:A%=in%:in%=0:CLOSE#A%
1540 out%=out%:IFout%:A%=out%:out%=0:CLOSE#A%
1550 ENDPROC
1560 :
1570 DEFFNOS_GetEnv:LOCALA$,A%,X%,Y%:X%=1:os%=((USR&FFF4)AND&FF00)DIV256
1580 IFos%>31:IFPAGE>&FFFFF:DIMX%LOCAL256:SYS"GetModuleFileName",0,X%,255:run$=$$X%:=@cmd$
1590 A%=(HIMEM>&FFFF)AND&900:IF?(TOP-3):A%=((PAGE>&9FFF)ANDA%)OR((&1400-PAGE)AND(A%=0))ELSEA%=((A%-&500)OR&200)AND&FFF
1600 A$=$(PAGE-&E00+A%):IFA%=0:run$=A$:SYS16TOA$,,A%:SYS72,"",A%:A$=MID$(A$,1+INSTR(A$+" "," ",1+INSTR(A$," "))):IFLENA$=0:A$=run$
1610 FORY%=-1TO0:A$=" "+A$:REPEATA$=MID$(A$,2):UNTILASCA$<>32
1620 IFY%:IFASCA$=34:A%=INSTR(A$,"""",2)+1 ELSEIFY%:A%=INSTR(A$+" "," ")
1630 IFY%:run$=MID$(A$,1-(ASCA$=34),A%-1+2*(ASCA$=34)):IFrun$<>"":A$=MID$(A$,A%+1)
1640 NEXT:=A$
1650 DEFPROCos(A$):IFASCA$=42:OSCLIA$ ELSE IFA$<>"":CHAINA$
1660 ENDPROC
1670 DEFPROCexit(A%):OSCLI"FX1,"+STR$(A%AND255):quit$=quit$:A$=quit$:quit$="":PROCos(A$)
1680 IFPAGE>&FFFFF:QUIT A%
1690 IFos%<6:END ELSE *Quit
1700 ENDPROC
1710 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$
1720 IFl$="":A%=INSTR(A$+" "," "):l$=LEFT$(A$,A%-1):A$=FNs(MID$(A$,A%+1)):=l$
1730 IFn%=0:IFl$<>"":A%=INSTR(A$,l$):IFA%:A$=FNs(LEFT$(A$,A%-1)+MID$(A$,INSTR(A$," ",A%)+1))+" ":=TRUE
1740 IFn%=0:IFl$<>"":=FALSE
1750 A%=INSTR(LEFT$(" ",ASCl$=32)+A$,l$):IFA%=0:=""
1760 A$=LEFT$(A$,A%-1)+FNs(MID$(A$,INSTR(A$," ",A%)+1))
1770 IFASCl$=32:l$=MID$(A$,A%):A$=LEFT$(A$,A%-1):=MID$(l$,1-(ASCl$=34),LENl$+2*(ASCl$=34))
1780 IFASCMID$(A$,A%,1)<>34:l$=MID$(A$,A%,INSTR(A$+" "," ",A%)-A%):A$=LEFT$(A$,A%-1)+MID$(A$,A%+LENl$+1):=l$
1790 l$=MID$(A$,A%+1,INSTR(A$+""" ",""" ",A%+1)-A%-1):A$=LEFT$(A$,A%-1)+MID$(A$,A%+LENl$+3):=l$
1800 DEFFNs(A$):IFLEFT$(A$,1)=" ":REPEATA$=MID$(A$,2):UNTILLEFT$(A$,1)<>" "
1810 IFRIGHT$(A$,1)=" ":REPEATA$=LEFT$(A$,LENA$-1):UNTILRIGHT$(A$,1)<>" "
1820 =A$
1830 DEFFNuc(A$):LOCAL B$:IFA$="":=""
1840 REPEATB$=B$+CHR$(ASCA$AND((A$<"@")OR&DF)):A$=MID$(A$,2):UNTILA$="":=B$
1850 :
1860 DEFFNfs:IFPAGE<&FFFF:LOCAL A%,Y%,E%:=(USR&FFDA)AND&FF
1870 =29
1880 DEFPROCf_gbpb(A%,chn%,addr%,num%,ptr%)
1890 ?X%=chn%:X%!1=addr%:X%!5=num%:X%!9=ptr%:IFPAGE<&FFFF:CALL&FFD1:ENDPROC
1900 IFA%=1ORA%=3:PTR#?X%=X%!9
1910 REPEAT:IFA%=1ORA%=2:BPUT#?X%,?X%!1 ELSE IFA%=3ORA%=4:?X%!1=BGET#?X%
1920 X%!1=X%!1+1:X%!5=X%!5-1:UNTIL(EOF#?X% AND A%>2)OR X%!5<1:ENDPROC
1930 DEFFNf_openin(A$)=OPENIN(FNf_name(A$))
1940 DEFFNf_openout(A$)=OPENOUT(FNf_name(A$))
1950 DEFFNf_openup(A$)=OPENUP(FNf_name(A$))
1960 DEFFNf_name(A$):IFos%>31:LOCALA%,B%:REPEATB%=A%:A%=INSTR(A$,"\",A%+1):UNTILA%=0:IFINSTR(A$,".",B%)=0:A$=A$+"."
1970 =A$
1980 DEFPROCf_cdir(A$):IF(os%AND-24):A$="mkdir "+A$ ELSE A$="cdir "+A$
1990 IF FALSE THEN
2000 OSCLIA$:ENDPROC
2010 ENDIF
2020 LOCAL ERROR:ON ERROR LOCAL:ENDPROC
2030 OSCLIA$:ENDPROC
2040 DEFFNf_scan(ptr%):X%!1=name%:X%!5=1:X%!9=ptr%
2050 IFPAGE<&FFFF:A%=8:CALL&FFD1:IFX%!5=1:=""
2060 IFPAGE<&FFFF:A%=name%+1:A%!(A%?-1)=&D20:A%?(INSTR($A%," ")-1)=13:=$A%
2070 LOCAL dir%,sh%:DIM dir% LOCAL 319:X%!9=ptr%+1
2080 SYS "FindFirstFile",".\*.*",dir% TO sh% :
2090 IF sh%<>-1 THEN
2100 REPEAT
2110 A$=$$(dir%+44) :
2120 IF A$="." OR A$=".." OR FNuc(RIGHT$(A$,4))=".INF":ptr%=ptr%+1:
2130 IF ptr%=0 THEN SYS "FindClose",sh%:=A$
2140 ptr%=ptr%-1 :
2150 SYS "FindNextFile",sh%,dir% TO res% :
2160 UNTIL res%=0 :
2170 SYS "FindClose",sh%
2180 ENDIF
2190 =""
2200 DEFFNfile(A$,A%):IFPAGE<&FFFF:$name%=A$:?X%=name%:X%?1=name%DIV256:=(USR&FFDD)AND&FF
2210 IFA%=5:X%!2=0:X%!6=0:=FNwin_finfo(A$)
2220 A$=FNf_name(A$):IFA%=255 OR A%=5:X%!14=OPENIN(A$):IFX%!14:X%!10=EXT#X%!14:CLOSE#X%!14
2230 IFA%=255:IFX%?6=0:OSCLI"LOAD """+A$+""" "+STR$~X%!2:=1
2240 IFA%=5:IFX%!14:=1 ELSE IFA%=5:=0
2250 IFA%=0:OSCLI"SAVE """+A$+""" "+STR$~X%!10+" "+STR$~X%!14:X%!10=X%!14-X%!10:=1
2260 IFA%=7:OSCLI"SAVE """+A$+""" "+STR$~PAGE+"+"+STR$~X%!10:X%!10=X%!14-X%!10:=1
2270 IFA%=8 THEN
2280 LOCAL ERROR:ON ERROR LOCAL:=2
2290 OSCLI"mkdir "+A$:=2
2300 ENDIF
2310 =0
2320 DEFFNf_info(A$):LOCAL T%,L%,E%,S%,F%,U%,P%:X%!14=0:T%=FNfile(A$,5):IFT%=0:=0
2330 X%!17=0:X%!21=0:X%!25=0:F%=FNfs:IFF%<>16:IFF%<>5:=T%
2340 L%=X%!2:E%=X%!6:S%=X%!10:P%=X%!14
2350 IFF%=16:A%=FNfile(A$,&FD):IFX%!6=E%:IFX%!10=S%:X%!6=0:X%!10=0:X%!8=P%:X%?8=0
2360 IFF%=16:X%!14=P%:X%!17=X%!6:X%!21=X%!10:X%!25=X%!2:X%!2=L%:X%!6=E%:X%!10=S%:=T%
2370 IFFNNetFS_Op(18,CHR$65+A$)=0:U%=X%!5
2380 IFFNNetFS_Op(18,CHR$64+A$)=0:X%!15=X%!10:X%?19=X%?14:X%!20=X%!5:X%?24=X%?9 ELSE X%!14=P%:X%!19=P%:X%?19=0:X%!22=0
2390 X%!2=L%:X%!6=E%:X%!10=S%:X%?14=P%:X%!25=U%:=T%
2400 DEFFNNetFS_Op(A%,A$):!X%=0:X%?1=8+LEN A$:IFos%<>6:X%!3=A%:$(X%+7)=A$:A%=&14:CALL&FFF1:=X%?3
2410 $(X%+4)=A$:SYS&60048,A%,X%+4,X%?1,124TOA%:IFA%:X%?3=?A%:SYS&2002B,A%+4TO$(X%+4)
2420 =X%?3
2430 DEFFNNetFS_OpN(A%,T%,O%,A$):!X%=0:X%?1=O%+1+LENA$:X%!3=A%:X%?7=T%:$(X%+O%)=A$:IFos%<>6:A%=&14:CALL&FFF1:=X%?3
2440 SYS&60048,A%,X%+7,X%?1,120TOA%:IFA%:X%?3=?A%:SYS&2002B,A%+4TO$(X%+4)
2450 =X%?3
2460 DEFPROCWin_TextIO
2470 SYS "GetStdHandle",-10 TO @hfile%(1):*INPUT 13
2480 SYS "GetStdHandle",-11 TO @hfile%(2):*OUTPUT 14
2490 SYS "SetConsoleMode",@hfile%(1),0:ENDPROC
2500 DEFFNwin_finfo(A$):IFos%<>32:=0
2510 LOCALdir%,sh%:DIMdir%LOCAL319:SYS"FindFirstFile",FNf_name(A$),dir%TOsh%
2520 IFsh%=-1:SYS"GetFileAttributes",FNf_name(A$)TOsh%:=((sh%AND16)DIV16+1)AND(sh%<>-1)
2530 SYS"FindClose",sh%:X%!10=dir%!32:IFdir%!28:X%!10=-1
2540 X%?14=(dir%?0AND1)*8+&33:SYS"FileTimeToSystemTime",dir%+20,X%+16
2550 A%=(X%!16AND&FFFF)-1981:X%?15=X%?22+(A%AND&70)*2:X%?16=X%?18+A%*16
2560 X%?17=X%?24:X%?18=X%?26:X%?19=X%?28:=(dir%?0AND16)DIV16+1