> Zip/src v1.35  Zip up files : v1.24 15-Dec-2002 JGH: ct% localised, better InitZip (7 v1.25 12-Jan-2003 JGH: Doesn't crunch small files 2J v1.26 15-Sep-2005 JGH: Workaround for bug in raFS, fixed LongToShort <: v1.27 28-Mar-2007 JGH: Updated ProgEnv for ARM CoPro F? v1.28 07-Jan-2011 JGH: -g, -S, -resume, -p renamed to -pp PK v1.29 12-Jan-2011 JGH: start$ is last good entry, not first bad entry ZC v1.30 15-Mar-2011 JGH: Split into modules, updated NetFS code d; v1.31 28-May-2011 JGH: Replace BGETs/BPUTs with GBPBs nH v1.32 11-Jun-2011 JGH: Faster CRC, faster GBPB, tweeked -v1 option x8 v1.33 22-Jun-2011 JGH: Fuller filename translation Z v1.34 16-Jan-2014 JGH: 'StillOpen' header used with -resume, matches truncated names D v1.35 15-Oct-2017 JGH: Optimised FNfn_zip(), crunched CRC code : =ctrl%255,name%128,zp%9:A$=OS_GetEnv:in%=0:out%=0:inc%=0 Mquit$=cl(" -qu",1):debug%=cl("-de",0):hlp%=cl("-?",0): ::exit() Zrst%=cl("-re",0):rc%=cl("-r",0):vb%=cl("-q",0):pre$=cl("-pp",1):date$=cl("-t",1) eapd%=cl("-g",0):sfx$=cl("-S",1):di%=cl("-D",0): fc%=TRUE:f$=FNcl("-C",1):IFf$<>"":fc%=VAL f$ [mem%=1024*cl("-M",1):xtr%=cl("-X",0):nodir%=cl("-no",0):v1%=cl("-v1",0):v1%:vb%= >inc$="":A%=" "+A$," -i@"): These need to be last options ="0" f$<="9":ct%= f$:A%=cl("-"+f$,0) 8out$=cl("",0):in$=cl("",0):pre$<>"":pre$=pre$+"." Dout$="-help":"BBC"s($(+7))" (C)J.G.Harston 1999-2014":hlp%= e IFdebug%:PRINT" run$='"run$"'"TAB(39)" quit$='"quit$"'"'" out$='"out$"'"TAB(39)" in$='"in$"'" h IFdebug%:PRINT" pre$='"pre$"'"TAB(39)" inc$='"inc$"'"'"suffix$='"sfx$"'"TAB(39)" date$='"date$"'" "Q IFdebug%:PRINT"append=";apd%;" recurse=";rc%;" verbose=";vb%;TAB(39); ,` IFdebug%:PRINT" resume=";rst%;" extra info=";xtr%;" cmptype=";ct%:REM ;" CRCfast=";fc% 6hlp%:"Syntax: *Zip outfile inpath -# -D -g -i@file -M size -nodir -pp path -q -r -resume -S suffix -t dd/mm/yyyy -X -quit command":exit(0) @: J= :" at line "+Þ,<128 <>17):Close_All:exit() TAX%=ctrl%:Y%=X%256:InitCRC:InitZip:date%=0:start$="":sfx%=0 ^"":date%=date$,2)+32*date$,4,2)+512*(date$,7)-1980) rLsfx$<>"":file(sfx$,5)<>1:"Suffix file '"sfx$"' not found":exit(214) |Csfx$<>"": sfx% X%!10:sfx%?(X%!10)=13:"Load "+sfx$+" "+~sfx% C A%-1:max%=-A%-2500+5000*(>&FFFF):mem%:max%>mem%:max%=mem%  mem% max%:wr%=2:rd%=4 : &out$="":"Destination file: "out$ Oout$=fn(out$):in$=fn(in$):apd%+rst%=0:Output Append:rst%:start$="" Nptr0%=#out%:X%!2=&FFFDDC00:A%=file(out$,2):A%=0:in$<>"":A%=file(in$,5) Lin$="" inc$<>"":Enter:A%=2 A%2:"Dir "+in$:ChkFS:Scan(""):A%=2 3A%2:zipcatandeof "Dir. '"in$"' not found" E#out%:rst%:!mem%=&04034B50:mem%!4=0:gbpb(wr%-1,out%,mem%,8,0) #out%:out%=0:exit(0): :  ptr0%->last valid header ) ptr% ->current header being checked : +Append:out%=(out$):out%=0:Output: \ptr%=0:gbpb(rd%-1,out%,mem%,4,0):!mem%=&100F4B50:gbpb(rd%-1,out%,mem%,4,4):ptr%=!mem% &Nptr%=0:!mem%<>&04034B50:"'"out$"' not a ZIP file":Close_All:exit(214) 0!ext%=#out%:ptr%>ext%:ptr%=0 :Sptr0%=ptr%::ptr%+30>ext%::#out%=ptr0%: : Not enough zipfile for a header DU!mem%=0:gbpb(rd%-1,out%,mem%,4,ptr%) : Read this header ID N[ptr%=0:!mem%=&100F4B50:!mem%=&04034B50 : Replace StillOpen header XG!mem%<>&04034B50::#out%=ptr0%: : Not a local header b\gbpb(rd%-1,out%,mem%,12,ptr%+18) : Read this header's lengths lWmem%!12=0:esz%=mem%!10:mem%!10=0:fsz%=mem%!8:csz%=!mem% : Get header lengths vLfsz%>254esz%>127::#out%=ptr0%: : Filename/extras too long Yskip%=ptr%+csz%+fsz%+esz%+30 : Point to next header [skip%>ext%::#out%=ptr0%: : Not enough zipfile, use previous entry c IFv1%:PRINTSTRING$(LENstart$,CHR$127);CHR$13; :REM Delete previously-printed name Ogbpb(rd%-1,out%,name%,fsz%,ptr%+30):name%?fsz%=13 : Get this name Dstart$=fn_zip($name%):start$,1)=".":start$=start$,start$-1) Xvb%:"Skipping dest ";start$: ;:IFNOTv1%:PRINT :REM Print this header's name Uskip%=ext%::#out%=ptr%: : Final full entry, use this entry jptr0%=ptr%:ptr%=skip% : ptr0%->this header, ptr%->next header P: : Loop to check next header : COutput:out%=(out$):out%=0:"Can't open '"out$"'":exit(192) "#out%,0:#out%:out%=(out$): : Enter:p$=""  ]inc$="":"Enter files to include, end with RETURN" "Exec "+inc$:inc%=byte(198,0,255) in$<>"":"Dir "+in$  ChkFS:inc%:#inc%=0: *":inc%=0:"Enter filename: "; 4h""in$:t%=0:in$<>"":fn$="@.",in$=45)+in$:t%=f_info(fn$):name$=fn_sfx(in$,X%!3&FFF)::inc%:11 >6t%:zip(ct%) in$<>"":"File '"in$"' not found" HA%=0:inc%:A%=#inc% R in$="" A%:inc$<>"":*Exec \ f: pScan(p$): p%,r%: zefs%>127:ș12,9,"",name%,1,p%,32,,,r%,p%:r%=1-r%:ș70,name%in$ in$=gbpb8(p%):p%=X%!9:r%=X%!5 r%=0:RdName  r%=1: : RdName:in$=46: 6fn$=in$:fn$=45:fn$="@."+fn$: -name- -> @.-name- 8t%=f_info(fn$):name$=fn_sfx(in$,X%!3&FFF):skip%=0 'start$:start$=p$+name$:start$="" 9start$:start$,p$+name$+1)<>p$+name$+".":skip%= :skip%:vb%:13;"Skipping ";p$;in$: ;:IFNOTv1%:PRINT E IFskip%:IFv1%:PRINTSPC10;STRING$(10+LENp$+LENin$,CHR$8);CHR$13;  skip%: /start$=0:di%(t%1)=1:zip(ct%):t%<>2: 6rc%t%=2:"Dir "+fn$:Scan(p$+in$+"."):"Dir ^":  : zip(ct%):t%=2:rc%: $2 Transfer info, as X%... may get overwritten: .*addDate:date%:zdate(X%!15)2:ct%<>255:filesize%:in%=(fn$):in%=0:"Can't open '"in$"'.": j6name$=fn_zip(pre$+p$+name$):t%=2:name$=name$+"/" t)vb%:"Adding ";pre$;p$;in$;"... "; ~: B 0 local file header signature 4 bytes "PK",&03,&04 4 4 version needed to extract 2 bytes 4 6 general purpose bit flag 2 bytes 4 8 compression method 2 bytes 4 10 last modification time 2 bytes 4 12 last modification date 2 bytes 4 14 crc-32 4 bytes 4 18 compressed size 4 bytes 4 22 uncompressed size 4 bytes 4 26 filename length 2 bytes 4 28 extra field length 2 bytes ; 30 filename (variable size) ; 30+fsz extra field (variable size)  ; 30+fsz+esz data (variable size) : , Output object header and copy any data (>!mem%=&04034B50:mem%!4=0:mem%!8=ct%:mem%!10=ztime(mtime%) 2Cmem%!12=zdate(mdate%):mdt%=mem%!10:mem%!14=0:mem%!18=filesize% <>mem%!22=filesize%(t%<>2):mem%!26=name$:mem%!28=24-8*xtr% FAesz%=30+name$+mem%!28:$(mem%+30)=name$:extra%=mem%+30+name$ P7!extra%=&4341:extra%!2=20-8*xtr%:extra%!4=&30435241 Z>extra%!8=load%:extra%!12=exec%:extra%!16=attr%:extra%!20=0 dDextra%!24=ztime(ctime%):extra%!26=zdate(cdate%):extra%!28=acc% n=gbpb(wr%-1,out%,mem%,esz%,ptr0%):trans:in%:#in%:in%=0 x: E REM Now put correct compession type, CRC and compressed size in -!mem%=ct%(t%<>2):mem%!2=mdt%:mem%!6=crc% Jmem%!10=compsize%(t%<>2)(ct%<>255):gbpb(wr%-1,out%,mem%,14,ptr0%+8) :  Update 'StillOpen' header Hrst%:ptr0%:!mem%=&100F4B50:mem%!4=ptr0%:gbpb(wr%-1,out%,mem%,8,0) : 7ptr0%=ptr0%+esz%+compsize%:vb%:8,8,8:"Done.": ; T IFv1%:PRINTSTRING$(14+LENname$,CHR$127);CHR$13;CHR$32;CHR$13; ELSE IFvb%:PRINT  : 'zipcatandeof:#out%=0 nodir%: 4 Can't put EOF entry without counting catalogue :cp%=#out%:ep%=cp%:fp%=0:n%=0:vb%:"Finishing... "; $:lp%=fp%:vb%:sofar(lp%,ep%); : "B 0 central file header signature 4 bytes "PK",&01,&02 ,4 4 version made by 2 bytes 6> 6 version needed to extract 2 bytes ----+ @> 8 general purpose bit flag 2 bytes | J> 10 compression method 2 bytes | T> 12 last mod file time 2 bytes As in | ^> 14 last mod file date 2 bytes local | h> 16 crc-32 4 bytes header| r> 20 compressed size 4 bytes | |> 24 uncompressed size 4 bytes | > 28 filename length 2 bytes | > 30 extra field length 2 bytes ----+ 4 32 file comment length 2 bytes 4 34 disk number start 2 bytes 4 36 internal file attributes 2 bytes 4 38 external file attributes 4 bytes 4 42 relative offset of local header 4 bytes ; 46 filename (variable size) ; 46+fsz extra field (variable size) ; 36+fsz+esz file comment (variable size) : >gbpb(rd%-1,out%,mem%+10,22,fp%+8) : Header Dgbpb(rd%-1,out%,mem%+46,mem%?28+mem%?30,fp%+30) : Name, Extras Hfp%=fp%+30+mem%?28+mem%?30+mem%!20:!mem%=&02014B50:mem%!4=0:mem%!6=0 Fmem%!32=0:mem%!36=0:mem%!38=&20:mem%!42=lp% : was !38=&20 1gbpb(wr%-1,out%,mem%,46+mem%?28+mem%?30,ep%) &0n%=n%+1:ep%=ep%+46+mem%?28+mem%?30:fp%>=cp% 0: :B 0 end of central dir signature 4 bytes "PK",&05,&06 D4 4 number of this disk 2 bytes N( 6 number of the disk with the X4 start of the central directory 2 bytes b' 8 total number of entries in l4 the central dir on this disk 2 bytes v' 10 total number of entries in 4 the central dir 2 bytes 4 12 size of the central directory 4 bytes ' 16 offset of start of central ' directory with respect to 4 the starting disk 4 bytes 4 20 zipfile comment length 2 bytes ; 22 zipfile comment (variable size) : A!mem%=&06054B50:mem%!4=0:mem%!8=n%:mem%!10=n%:mem%!12=ep%-cp% 3mem%!16=cp%:mem%!20=0:gbpb(wr%,out%,mem%,22,0) Mvb%:8,8,8:"Done.": ;:IFv1%:PRINTSTRING$(17,CHR$127); ELSE IFvb%:PRINT  : *addDate:X%!15:: Already has mdate  V!zp%=X%!6:zp%!4=X%!2:Date_ToOrd(zp%):year%>1980:year%=(year%-1981)127 year%=0 7X%?15=day%+32*(year%16):X%?16=month%+16*(year%15)  EX%?17=hour%:X%?18=minute%:X%?19=second%:X%!20=X%!15:X%?24=X%?19: *: 4>trans:crc%=0:compsize%=0:filesize%=0 t%=2 ct%=255: >,compsize%=filesize%:filesize%<128:ct%=0 HDcopyend%=filesize%:crc%=-1:docrc%=:ptr%=0:os%=6:ct%:ArcTrans R":vb%:sofar(ptr%,copyend%); \4len%=max%:ptr%+len%>copyend%:len%=copyend%-ptr% f4gbpb(rd%-1,in%,mem%,len%,ptr%):docrc%:CalcCRC p>gbpb(wr%,out%,mem%,len%,0):ptr%=ptr%+len%:ptr%>=copyend% zcrc%=crc%: : ArcTrans:noZip%: Ofile("",5):"Access ":"Wipe ~CFR~V" B"ZipCompress "+in$+" ":*SetType Data %#in%:in%=0:in%=("") >gbpb(rd%-1,in%,zp%,4,#in%-8):crc%=!zp%:docrc%=:ptr%=44 4compsize%=#in%-52:copyend%=compsize%+44:ct%=8: : 2ChkFS:fs%=fs:sj%=((fs%=5)2)+((fs%=16)1): : ݤget16(A%):=#A%+256*#A% Aݤget32(A%):zp%?0=#A%:zp%?1=#A%:zp%?2=#A%:zp%?3=#A%:=!zp% Mput32(A%):!zp%=A%:#out%,zp%?0:#out%,zp%?1:#out%,zp%?2:#out%,zp%?3: 3put16(A%):!zp%=A%:#out%,zp%?0:#out%,zp%?1: : Qݤsofar(A%,B%):8,8,8: d0(A%/(B%+1)*100,2);"%";:="": Fixed 'Too big' error $: .InitZip:noZip%=:ct%=0: 8,os%<>6:ct%=0:: Force compression to 0 B;file("*.Resources.SparkFS",5)<>1:ct%=0: L<*RMEnsure SparkFS 0.00 Error SparkFS needs to be running V=*RMEnsure Zip 0.00 Error SparkFS needs to load Zip module `noZip%=: j: tInitCRC:CRC%=CRC%:CRC%: ~>&FFFF:crcARM: ?&FFF7=&6C:crc65: $ IF?&FFF7=&C3:PROCcrc80:ENDPROC  : @CalcCRC:CRC%:!ad=mem%:!nm=len%:!cc=crc%: CRC%:crc%=!cc: H IFfc%:IFCRC%:!ad=mem%:!nm=len%:!cc=crc%:CALL CRC%:crc%=!cc:ENDPROC mS%=crc%:A%=mem%mem%+len%-1:S%=S%?A%:Z%=18:B%=S%:S%=(((S%+(S%<0))2)&7FFFFFFF):B%1:S%=S%&EDB88320 5vb%:(A%1023)=0:sofar(ptr%+A%-mem%,copyend%); ::crc%=S%: : 0crc65: CRC%63:ad=&70:nm=&72:cc=&74:P=01 .P%=CRC%:[OPT P*2:.bl:LDX#8:LDA(ad-8,X):cc *.rl:LSRcc+3:RORcc+2:RORcc+1:RORA:BCCcl 3TAY:LDAcc+3:#&ED:STAcc+3:LDAcc+2:#&B8:STAcc+2 'LDAcc+1:#&83:STAcc+1:TYA:#&20:.cl +DEX:BNErl:INCad:BNEnx:INCad+1:.nx:STAcc ('LDAnm:BNEsk:DECnm+1:.sk:DECnm:BNEbl 2LDAnm+1:BNEbl:RTS:]:: <: FH DEFPROCcrc80:ENDPROC:REM DIM CRC%79:ad=&70:nm=&72:cc=&74:FORP=0TO1 P, P%=CRC%:[OPT P*2:LD IX,(ad):LD BC,(nm) Z LD DE,(cc):LD HL,(cc+2) d( .bl:PUSH BC:LD A,(IX):XOR E:LD B,8 n- .rl:SRL H:RR L:RR D:RRA:JP NC,cl:LD E,A x1 LD A,H:XOR &ED:LD H,A:LD A,L:XOR &B8:LD L,A * LD A,D:XOR &83:LD D,A:LD A,E:XOR &20 4 .cl:DEC B:JP NZ,rl:LD E,A:INC IX:POP BC:DEC BC % LD A,B:OR C:JP NZ,bl:LD (cc),DE % LD (cc+2),HL:RET:]:NEXT:ENDPROC : $crcARM: CRC%79:P=01:P%=CRC% 5[OPT P*2:LDR R0,ad:LDR R1,nm:LDR R2,cc:LDR R3,xor ..btlp:LDRB R4,[R0],#1: R2,R2,R4:MOV R4,#8 ?.rtlp:MOVS R2,R2,LSR #1:CS R2,R2,R3:SUBS R4,R4,#1:BNE rtlp 0SUBS R1,R1,#1:BNE btlp:STR R2,cc:MOV R15,R14 :.xor:EQUD&EDB88320:.ad:EQUD0:.nm:EQUD0:.cc:EQUD0:]:: : < DEFFNrev32(A%):B%=0:C%=0:IFA%<0:C%=1:A%=A%AND&7FFFFFFF = FORZ%=1TO32:B%=(B%+B%)OR(A%AND1):A%=A%DIV2:NEXT:=B%ORC% U DEFFNrev8(A%):B%=A%:A%=0:FORz%=1TO8:A%=A%+A%:A%=A%OR(B%AND1):B%=B%DIV2:NEXT:=A% : ", -------------------------------------- ,: 6, Convert fs date/time to zip date/time: @?ݤztime(A%):=(A%&1F)*&800+(A%&3F00)8+(A%&3F0000)&10000 JEݤzdate(A%):=(A%31)+(A%&F00)8+((A%&F000)8+(A%&E0)*256)+&200 T: ^, -------------------------------------- h: rDݤfn(A$):A$<>45:A%=A$,":",3):A%:="-"+A$,A%-1)+"-"+A$,A%+1) |=A$