* Patterns: * 1[MBITS][OBITS] Match * 0[NBITS] Literals * Notes: * - The bit count for offset is * determined by the max possible * offset, limited by traversed * size. * - The 1-bit id for matches is * unnecessary after a literal * ASSEMBLE sMNEXT EQU 9 Match expected? sGARB EQU 10 NBITS EQU 4 Literal length NMASK EQU 2^(NBITS)-1 NBITS2 EQU 6 NMASK2 EQU 2^(NBITS2)-1 MBITS EQU 5 Match length MMASK EQU 2^(MBITS)-1 MBITS2 EQU 7 MMASK2 EQU 2^(MBITS2)-1 =OffNoBlush EQU #01D44 =ABORT EQU #04EA4 =WIPEOUT EQU #0675C =GETPTREVALC EQU #15C77 =aATTNFLG EQU #4226C RPL :: CK1NOLASTWD DUPTYPECSTR? ITE :: DUP #1 #2 SUB$ "BZ" EQUAL ; FALSE case CODE TITLE JAZZ Uncompressor STITLE Preparation ST=0 sGARB reungz GOSBVL =SAVPTR A=DAT1 A D1=A D1=D1+ 10 A=DAT1 4 D1=D1+ 4 LCSTR 'BZ' P= 3 ?C=A WP GOYES upkok P= 0 LC(5) =SETTYPEERR GOVLNG =GETPTREVALC upkok P= 0 C=DAT1 A RSTK=C GOSBVL =CREATETEMP GONC ugzmemok ?ST=1 sGARB GOYES ugzmerr GOSUB PassGC CON(5) =DOCOL CON(5) =GARBAGE CON(5) =COLA CON(5) =DOCODE REL(5) UGZEND ST=1 sGARB GOTO reungz PassGC C=RSTK GOVLNG =GETPTREVALC ugzmerr GOVLNG =GPMEMERR ugzmemok C=RSTK AD0EX R0=A A C=C+A A R1=C A ->obend GOSBVL =D1=DSKTOP C=DAT1 A D0=C D0=D0+ 5+5 D0=D0+ 4+5 C=DAT0 A AD0EX D0=A D0=D0+ 5 ->pats C=C+A A R2=C.F A ->lits A=R0 A DAT1=A A ->stk1 R3=A.F A ->ob D1=A STITLE Uncompress Loop ST=0 sMNEXT A=0 S R3=A.F S bits UPKLOOP GOSUB Decod ?D#0 A GOYES upkpat * Safety: * AD1EX * C=R1.F A * C=C-A A * AD1EX * ?A<=C A * GOYES blaa * A=C A *blaa CD0EX CR2EX.F A CD0EX C=A A GOSBVL =MOVEDOWN CD0EX CR2EX.F A CD0EX upkcont AD1EX D1=A C=R1.F A ?A<C A GOYES UPKLOOP GOVLNG =GETPTRLOOP upkpat * Safety: * AD1EX * C=R1.F A * C=C-A A * AD1EX * ?D<=C A * GOYES buh * D=C A *buh CD1EX D1=C C=C-A A ->src CD0EX CDEX A A=0 P ?A=0 A GOYES upslow GOSBVL =MOVEDOWN uppcnt C=D A D0=C GOTO upkcont upslow C=C-1 A upkplp A=DAT0 B DAT1=A 1 D0=D0+ 1 D1=D1+ 1 C=C-1 A GONC upkplp GOC uppcnt UGZEND ENDCODE ZERO FOURTEEN BLANKIT ABUFF #42 #7 "BZ V1.2 (400)" MINUSONE CENTER$3x5 DROP DUP OSIZE SWAP SysTime 1LAMBIND GARBAGE SysTime 1PUTLAM CODE TITLE JAZZ Compressor * Effect of HSHSIZE: (sample file was an earlier BZ.S ) * * HSHSIZE Time MemNeed: * #1000 14.54 26624 * #800 15.77 16384 * #400 17.56 11264 !! * #200 21.26 8704 * #100 28.59 7424 * #80 42.78 6784 * #40 69.97 6464 HSHSIZE EQU #400 See source before changing! WINSIZE EQU #1000 RINGMEM EQU 3*(WINSIZE) HASHMEM EQU 10*(HSHSIZE) ALLMEM EQU (RINGMEM)+(HASHMEM) MINMEM EQU 200+(ALLMEM) MINADD EQU 100+(ALLMEM) MINMAT EQU 6 Minimum match lenght STITLE Startup ********************************* * For speed following registers * have priority over anything else * R0[A] ->out * R2[A] ->buffer * R3[A] ->ob * Assiging other improtant variables * to [A] fields we get: * R0 ->out ->$start * R1 free * R2 ->buffer * R3 ->ob bits * R4 ->obend ->obsave * D0 ->obptr * bits determines how many bits * are valid in current ->out * eg 0 <= bits <= 2 ********************************* GOSBVL =SAVPTR * GOSBVL =GARBAGECOL CLRST * ST=0 sMNEXT A=0 W R0=A R1=A R2=A R3=A R3[S]=0! R4=A GOSBVL =D1=DSKTOP A=DAT1 A R3=A.F A ->ob (temporary) D0=A GOSBVL =SKIPOB AD0EX R4=A.F A ->obend C=R3.F A ->ob A=A-C A obsize GOC argerr LC(5) 10 ?A>=C A GOYES argok argerr LC(5) =SETTYPEERR gpevalc GOVLNG =GETPTREVALC memerr GOSBVL =DispOn GOVLNG =GPMEMERR argok GOSBVL =ROOM A=C A LC(5) MINMEM A=A-C A GOC memerr LC(5) MINADD C=C+A A R1=C.F A free GOSBVL =MAKE$N A=R0.F A GOSBVL =ASLW5 AD0EX R0=A D1=A ->out C=R1.F A free GOSBVL =WIPEOUT AD1EX LC(5) HASHMEM A=A-C A R2=A.F A ->buffer A=R1.F A free LC(5) ALLMEM THIS WAS BUGGED! (only HASHMEM substracted) A=A-C A A=A-CON A,16 buffering safety! R1=A.F A GOSBVL =DisableIntr GOSBVL =OffNoBlush GOSBVL =AllowIntr GOTO packnow ********************************* * R0 ->out ->$start * R1 free (adjusted for buffer) * R2 ->buffer * R3 ->ob bits * R4 ->obend (->obsave) ********************************* packnow C=R1.F A C=C-CON A,4+5+5 "BZ" and oblen R1=C.F A * GOC memerr Never C=R0.F A D0=C LCSTR 'BZ' DAT0=C 4 D0=D0+ 4 A=R4.F A ->obend C=R3.F A ->ob A=A-C A obsize DAT0=A A D0=D0+ 10 CD0EX D0 = ->ob R0=C.F A ->out STITLE Compressor Loop ********************************* * R0 ->out ->$start * R1 free * R2 ->buffer * R3 ->ob bits * R4 ->obend (->obsave) ********************************* PackLoop GOSUB PackInfo GOSUB PackAbort? * Save start address of scan AD0EX D0=A GOSBVL =ASLW5 A=R4.F A R4=A GOSUB FindMax C=R4 GOSBVL =CSRW5 ->obsave AD0EX ->match D0=A A=A-C A skipped nibbles GOSUB Encod * Pattern is out, update history ?D=0 A GOYES packcont D0=D0+ 1 1st one is in already D=D-1 A 1st not included D=D-1 A GONC test patadd GOSUB RemoveOld GOSUB AddNew D0=D0+ 1 D=D-1 A GONC patadd * Prepare next loop packcont AD0EX D0=A C=R4.F A ->obend ?A>=C A GOYES PackNibs GOTO PackLoop ********************************* * Append literal nibbles * according to packed directives ********************************* PackNibs C=R0 A=R3.F S ?A=0 S GOYES outok! C=C+1 A R0=C outok! GOSBVL =CSRW5 D0=C D0=D0+ 5+5 D0=D0+ 4+5 C=R0.F A ->out AD0EX D0=A C=C-A A off to lit DAT0=C A D0=D0+ 5 ->pats C=R3.F A ->ob D1=C A=R1.F A free++ LC(5) ALLMEM A=A+C A R1=A.F A ST=0 sMNEXT A=0 S R3=A.F S bits NibsLoop GOSUB Decod ?D#0 A GOYES apppat CR1EX.F A C=C-A A CR1EX.F A GOC apperr C=R0.F A CD1EX CD0EX R0=C.F A C=A A GOSBVL =MOVEDOWN C=R0.F A CD0EX CD1EX R0=C.F A GONC appcont apperr GOTO memerr apppat CD1EX C=C+D A CD1EX appcont C=R4.F A ->obend AD1EX D1=A ?A<C A GOYES NibsLoop * Exit compressor PackDone GOSBVL =DispOn C=R0 D0=C GOSBVL =CSRW5 R0=C GOSBVL =Shrink$ GOVLNG =GPOverWrR0Lp STITLE Match Encoder ********************************* * Output match * D[A] = length * D[A1] = match loc * D0 = ->match * R0[A] = ->out * R3[A] = ->ob * R3[S] = bits * R1[A] = free * A[A] = skipped ********************************* Encod ?A#0 A GOYES outlit GOTO outmat? outlit ST=1 sMNEXT LC(5) NMASK ?A>C A GOYES outlit2 A=A+A A P= (NBITS)+1 GOSUB OutBits GOTO outmat? outlit2 A=A-C A B=A A A=0 A P= (NBITS)+1 GOSUB OutBits LC(5) NMASK2 ?B>C A GOYES outlit5 A=B A P= NBITS2 GOSUB OutBits GOTO outmat? outlit5 A=0 A P= NBITS2 GOSUB OutBits A=B A GOSUB OutA[A] ******** outmat? ?D=0 A RTNYES D=D-CON A,(MINMAT)-1 LC(5) MMASK ?D>C A GOYES outmat2 C=D A A=C A P= MBITS ?ST=1 sMNEXT GOYES otm1 A=A+A A A=A+1 A P= (MBITS)+1 otm1 GOSUB OutBits GOTO outoff outmat2 D=D-C A A=0 A P= MBITS ?ST=1 sMNEXT GOYES otm3 A=A+1 A P= (MBITS)+1 otm3 GOSUB OutBits LC(5) MMASK2 ?D>C A GOYES outmat5 C=D A A=C A P= MBITS2 GOSUB OutBits GOTO outfxm outmat5 A=0 A P= MBITS2 GOSUB OutBits C=D A A=C A GOSUB OutA[A] outfxm LC(5) MMASK D=D+C A outoff D=D+CON A,(MINMAT)-1 ST=0 sMNEXT C=D W GOSBVL =CSRW5 ->matchloc AD0EX D0=A A=A-C A offset C=R3.F A ->ob AD0EX C=A-C A maxoff AD0EX B=C A maxoff LC(5) #7FF P= 12 otoflp ?B>C A GOYES OutBits CSRB.F A P=P-1 GONC otoflp BET ********************************* OutA[A] B=A A P= 8 GOSUB OutBits A=B A ASR A ASR A P= 12 ********************************* OutBits A=R3.F S C=P 15 C=C+A S A=C S C=0 A P= 3 CPEX 15 CPEX 0 A=A&C S AR3EX.F S P= 0 CSRB.F P CSRB.F P AR1EX.F A A=A-C A AR1EX.F A GOC outerr AR0EX.F A D1=A A=A+C A AR0EX.F A A=A-1 S GOC noshf shflp A=A+A A A=A-1 S GONC shflp noshf C=0 A C=DAT1 P C=C!A A DAT1=C A RTN outerr GOTO memerr ********************************* STITLE Match Decoder ********************************* * Decode directive from stream * In: D0 = ->in * D1 = ->obptr * R3[S] = bits (used) * R3[A] = ->ob * Out: A[A]=nlen D[A]=0 * A[A]=offs D[A]=mlen ********************************* Decod ?ST=1 sMNEXT GOYES dcmat P= 1 GOSUB GetBits ?ABIT=1 0 GOYES dcmat ST=1 sMNEXT P= NBITS GOSUB GetBits D=0 A ?A#0 A RTNYES P= NBITS2 GOSUB GetBits ?A#0 A GOYES fxlit GOSUB GetA[A] fxlit LC(5) NMASK A=A+C A RTN dcmat ST=0 sMNEXT P= MBITS GOSUB GetBits ?A#0 A GOYES dcoff P= MBITS2 GOSUB GetBits ?A#0 A GOYES fxmat GOSUB GetA[A] fxmat LC(5) MMASK A=A+C A dcoff C=A A D=C A mlen D=D+CON A,(MINMAT)-1 AD1EX D1=A C=R3.F A ->ob A=A-C A maxoff LC(5) #7FF P= 12 dcoflp ?A>C A GOYES GetBits CSRB.F A P=P-1 GONC dcoflp BET ********************************* GetA[A] P= 12 GOSUB GetBits B=A X P= 8 GOSUB GetBits ASL A ASL A ASL A A=B X RTN ********************************* * Get P bits ********************************* GetBits A=DAT0 A A=R3.F S A=A-1 S GOC gb0 gbshf ASRB.F A A=A-1 S GONC gbshf gb0 C=P 15 C=C-1 S C=0 A gbmlp C=C+C A C=C+1 A C=C-1 S GONC gbmlp A=A&C A A=R3.F S C=P 15 C=C+A S A=C S C=0 A P= 3 CPEX 15 CPEX 0 A=A&C S R3=A.F S P= 0 CSRB.F P CSRB.F P AD0EX A=A+C A AD0EX RTN ********************************* STITLE Match Finder ********************************* * Find next match causing a pack * In: * D0 ->pos * R2[A] ->buffer * R3[A] ->ob * R4[A] ->obend * Out: * D0 ->newpos * D[A] matchlen * D[A1] matchpos * Uses: A[W] B[A] C[W] D[W] ********************************* FindMax GOSUB RemoveOld GOSUB AddNew GOC nxtmat GOSUB ScanThis ?D#0 A GOYES gotmax? nxtmat AD0EX A=A+1 A D0=A C=R4.F A ?C>A A GOYES FindMax D=0 W RTNSC gotmax? LC(5) MINMAT ?D<C A GOYES nxtmat AD0EX D0=A C=R4.F A C=C-A A ?D<=C A RTNYES D=C A LC(5) MINMAT ?D<C A GOYES nxtmat RTN STITLE Ring Buffer Match Finder ********************************* * Scan buffer for the longest * match for D0. Note that no * obend test is needed * In: * D0 ->pos * B[A] ->FLlink * R2[A] ->buffer * R3[A] ->ob * Out: D[A,A1] match * Uses: A[W] B[A] C[W] D[W] ********************************* ScanThis D=0 W C=B A D1=C ->FLlink A=DAT1 A scanloop D1=A GOSUB Count ?D>C A GOYES nextmat * ?C=0 A * GOYES nextmat CD1EX D=C A CD1EX P= 9 DSL WP DSL WP DSL WP DSL WP DSL WP P= 0 D=C A * Get next loc from buffer nextmat AD1EX B=0 A B=A X C=R2.F A C=C-B A C=C-B A C=C-B A ->slot D1=C D1=D1- 3 Nonzero! C=A A A=DAT1 X ?C<A A GOYES scaok LC(5) WINSIZE A=A+C A scaok CD0EX D0=C ?C>A A GOYES scanloop RTN STITLE Match Length Counter ********************************* * Compare nibbles * In: D0 D1 * Out: C[A] = match length * Uses: A[W] B[A] C[A] ********************************* Count B=0 A A=DAT0 W C=DAT1 W ?C#A W GOYES cntwp cntwlp D0=D0+ 16 D1=D1+ 16 B=B+1 A A=DAT0 W C=DAT1 W ?C=A W GOYES cntwlp BSL A CD0EX C=C-B A CD0EX CD1EX C=C-B A CD1EX cntwp P= 8-1 ?C=A WP GOYES cntP8 P= 4-1 ?C=A WP GOYES cntPlp P= 1-1 GONC cnpP+ cntP8 P= 12-1 ?C=A WP GOYES cntPlp P= 8-1 cntPlp P=P+1 cnpP+ ?C=A P GOYES cntPlp C=B A CPEX 0 RTNCC STITLE Ring Buffer Addition ********************************* * Add current location to ring * In: D0 * R2[A] ->buffer * Out: B[A] ->FLlink * CS: no previous ones * Uses: A[A] B[A] C[A] D1 ********************************* AddNew * Compute hash A=DAT0 A C=A A CSR A CSR A CSRB.F X CSRB.F X B=A X A=A!C X C=C&B X A=A-C X hash * Uncomment if less than 12 bits: LC(3) (HSHSIZE)-1 C=C&A X A=R2.F A C=C+C A 2* A=A+C A C=C+C A 4* C=C+C A 8* A=A+C A 10* B=A A ->FLlink D1=A D1=D1+ 5 A=DAT1 A LastAddr CD0EX DAT1=C A New LastAddr D0=C ?A=0 A GOYES add1st * Add to end addok C=0 A C=A X A=R2.F A A=A-C A A=A-C A A=A-C A ->lastslot D1=A D1=D1- 3 Nonzero! AD0EX DAT1=A X link it to D0 D0=A RTNCC * No previous ones add1st D1=D1- 5 DAT1=C A RTNSC STITLE Ring Buffer Remove ********************************* * Remove old location from buffer * In: D0 ->obptr * R3[A] ->ob * Uses: A[A] B[A] C[A] D1 ********************************* RemoveOld AD0EX D0=A LC(5) WINSIZE A=A-C A C=R3.F A ->ob ?C>A A RTNYES * Old one is in ring, remove it D1=A * Compute hash A=DAT1 A C=A A CSR A CSR A CSRB.F X CSRB.F X B=A X A=A!C X C=C&B X A=A-C X hash * Uncomment if less than 12 bits: LC(3) (HSHSIZE)-1 C=C&A X A=R2.F A C=C+C A 2* A=A+C A C=C+C A 4* C=C+C A 8* A=A+C A 10* AD1EX B=A A ->oldpos A=DAT1 A D1=D1+ 5 C=DAT1 A ?C<=A A GOYES removeall D1=D1- 5 C=0 A C=B X A=R2.F A ->buffer A=A-C A A=A-C A A=A-C A ->1stslot AD1EX D1=D1- 3 Nonzero! C=B A C=DAT1 X 1stlink D1=A ?B<C A GOYES remok B=C A LC(5) WINSIZE C=C+B A remok DAT1=C A RTNCC removeall C=0 A DAT1=C A D1=D1- 5 DAT1=C A RTN STITLE Annunciator Flash ********************************* PackInfo D1=(5) =ANNCTRL A=DAT1 B A=A+A B ABIT=0 6 ?A#0 B GOYES inf00 A=A+1 B inf00 ABIT=1 7 DAT1=A B RTNCC STITLE Abort Check ********************************* PackAbort? D1=(5) =aATTNFLG A=DAT1 A D1=A A=DAT1 A ?A=0 A RTNYES A=R0 GOSBVL =ASRW5 R0=A D0=A D0=D0+ 10 GOSBVL =Shrink$ GOSBVL =DispOn LC(5) =ABORT GOTO gpevalc ********************************* ENDCODE SysTime 1GETLAM bit- SysTime 1PUTLAM SysTime 1GETLAM bit- bit- ABND HXS>% % 8192 %/ %3 RNDXY UNROT DUP4UNROLL OSIZE ( $bz %time #len1 #len2 ) UNCOERCE2 2DUP %CH %2 RNDXY a%>$ "%CH: " !insert$ 4ROLL a%>$ " Time: " !insert$ !append$ ZERO FOURTEEN BLANKIT ABUFF #42 #A 4ROLL MINUSONE CENTER$3x5 DROP %2 %/ a%>$ SWAP %2 %/ a%>$ "Size: " !insert$ " \8D " !append$ !insert$ ABUFF #42 ZERO 4ROLL MINUSONE CENTER$3x5 DROP SetDA1Temp ;