📄 flate.a
字号:
ENDMFLUSH MACRO MOVINT #0,-(sp) ; unshrink flag: always false move.l \1,-(sp) ; length IFGT SIZEOF_slide-4 pea slide(G) ; buffer to flush ELSE move.l slide(G),-(sp) ENDC G_PUSH tst.w mem_mode+INTSIZE-2(G) ; test lower word if long beq.s fm\@ jsr _memflush ; ignores the unshrink flag bra.s fe\@fm\@: jsr _flushfe\@: lea 8+INTSIZE+G_SIZE(sp),sp ENDM ENDC ; ?FUNZIP; Here are the two bit-grabbing macros, defined in their NO_CHECK_EOF form:;; #define NEEDBITS(n) {while(k<(n)){b|=((ulg)NEXTBYTE)<<k;k+=8;}}; #define DUMPBITS(n) {b>>=(n);k-=(n);};; Without NO_CHECK_EOF, NEEDBITS reads like this:;; {while(k<(n)){int c=NEXTBYTE;if(c==EOF)return 1;b|=((ulg)c)<<k;k+=8;}};; NEEDBITS clobbers d0, d1, a0, and a1, none of which can be used as the arg; to the macro specifying the number of bits. The arg can be a shortword memory; address, or d2-d7. The result is copied into d1 as a word ready for masking.; DUMPBITS has no side effects; the arg must be a d-register (or immediate in the; range 1-8?) and only the lower byte is significant.NEEDBITS MACROnb\@: cmp.w \1,k ; assert 0 < k <= 32 ... arg may be 0 bhs.s ne\@ NEXTBYTE ; returns in d0.l IFND NO_CHECK_EOF cmp.w #EOF,d0 bne.s nok\@ moveq #1,d0 ; PK_WARN? bra return ENDC ; !NO_CHECK_EOFnok\@: lsl.l k,d0 or.l d0,b addq.w #8,k bra.s nb\@ne\@: move.w b,d1 ENDMDUMPBITS MACRO lsr.l \1,b ; upper bits of \1 are ignored?? sub.b \1,k ENDM; ******************************************************************************; Here we go, finally: xdef _inflate_codes_inflate_codes: link a5,#-4 movem.l savregs,-(sp); 8(a5) = tl, 12(a5) = td, 16(a5) = bl, 18|20(a5) = bd... add 4 for REENT_G; -2(a5) = ml, -4(a5) = md. Here we cache some globals and args: IFD REENT_G move.l 8(a5),G ELSE;; move.l _G,G ; old global pointer version lea _G,G ; G is now a global instance ENDC lea _mask_bits,mask move.l bb(G),b MOVINT bk(G),k IFD INT16 moveq #0,w ; keep this usable as longword ENDC MOVINT wp(G),w moveq #0,e ; keep this usable as longword too MOVINT 16+G_SIZE(a5),d0 add.w d0,d0 move.w (mask,d0.w),-2(a5) ; ml = mask_bits[bl] MOVINT 16+INTSIZE+G_SIZE(a5),d0 add.w d0,d0 move.w (mask,d0.w),-4(a5) ; md = mask_bits[bd]main_loop: NEEDBITS 14+INTSIZE+G_SIZE(a5) ; bl, lower word if long and.w -2(a5),d1 ; ml mulu #SIZEOF_HUFT,d1 move.l 8+G_SIZE(a5),a0 ; tl lea (a0,d1.l),t move.b h_e(t),e cmp.w #16,e bls.s topdmpintop: moveq #1,d0 cmp.w #99,e beq return ; error in zipfile move.b h_b(t),d0 DUMPBITS d0 sub.w #16,e NEEDBITS e move.w e,d0 add.w d0,d0 and.w (mask,d0.w),d1 mulu #SIZEOF_HUFT,d1 move.l h_t(t),a0 lea (a0,d1.l),t move.b h_e(t),e cmp.w #16,e bgt.s intoptopdmp: move.b h_b(t),d0 DUMPBITS d0 cmp.w #16,e ; is this huffman code a literal? bne lenchk ; no move.w h_n(t),d0 ; yes IFGT SIZEOF_slide-4 lea slide(G),a0 ELSE move.l slide(G),a0 ENDC move.b d0,(a0,w.l) ; stick in the decoded byte addq.w #1,w cmp.w #WSIZE,w blo main_loop FLUSH w moveq #0,w bra main_loop ; do some morelenchk: cmp.w #15,e ; is it an end-of-block code? beq finish ; if yes, we're done NEEDBITS e ; no: we have a duplicate string move.w e,d0 add.w d0,d0 and.w (mask,d0.w),d1 move.w h_n(t),n add.w d1,n ; length of block to copy DUMPBITS e NEEDBITS 14+(2*INTSIZE)+G_SIZE(a5) ; bd, lower word if long and.w -4(a5),d1 ; md mulu #SIZEOF_HUFT,d1 move.l 12+G_SIZE(a5),a0 ; td lea (a0,d1.l),t move.b h_e(t),e cmp.w #16,e bls.s middmpinmid: moveq #1,d0 cmp.w #99,e beq return ; error in zipfile move.b h_b(t),d0 DUMPBITS d0 sub.w #16,e NEEDBITS e move.w e,d0 add.w d0,d0 and.w (mask,d0.w),d1 mulu #SIZEOF_HUFT,d1 move.l h_t(t),a0 lea (a0,d1.l),t move.b h_e(t),e cmp.w #16,e bgt.s inmidmiddmp: move.b h_b(t),d0 DUMPBITS d0 NEEDBITS e move.w e,d0 add.w d0,d0 and.w (mask,d0.w),d1 move.l w,d sub.w h_n(t),d sub.w d1,d ; distance back to block to copy DUMPBITS eindup: move.w #WSIZE,e ; violate the e < 256 rule and.w #WSIZE-1,d cmp.w d,w blo.s ddgw sub.w w,e bra.s dadwddgw: sub.w d,edadw: cmp.w n,e bls.s delen move.w n,edelen: sub.w e,n ; size of sub-block to copy IFGT SIZEOF_slide-4 lea slide(G),a0 ELSE move.l slide(G),a0 ENDC move.l a0,a1 add.l w,a0 ; w and d are valid longwords add.l d,a1 move.w e,d0 subq #1,d0 ; assert >= 0 if sign extendeddspin: move.b (a1)+,(a0)+ ; string is probably short, so dbra d0,dspin ; don't use any fancier copy method add.w e,w add.w e,d cmp.w #WSIZE,w blo.s dnfl FLUSH w moveq #0,wdnfl: tst.w n ; need to do more sub-blocks? bne indup ; yes moveq #0,e ; restore zeroness in upper bytes bra main_loop ; do some morefinish: MOVINT w,wp(G) ; restore cached globals MOVINT k,bk(G) move.l b,bb(G) moveq #0,d0 ; return "no error"return: movem.l (sp)+,savregs unlk a5 rts
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -