home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 9 Archive / 09-Archive.zip / unzip511.zip / amiga / flate.a < prev    next >
Text File  |  1994-06-20  |  9KB  |  363 lines

  1. ; Not copyrighted by Paul Kienitz, 20 Jun 94.
  2. ;
  3. ; Assembly language version of inflate_codes(), for Amiga.  Prototype:
  4. ;
  5. ;   int flate_codes(struct huft *tl, struct huft *td, int bl, int bd,
  6. ;                   unsigned char *slide);
  7. ;
  8. ; It is called by defining inflate_codes(tl, td, bl, bd) as
  9. ; flate_codes(tl, td, bl, bd, slide).
  10. ;
  11. ; Define the symbol FUNZIP if this is for fUnZip.  Define CRYPT if this is
  12. ; for fUnZip with decryption enabled.  Define AZTEC to use the Aztec C
  13. ; buffered input macro instead of the library getc() with FUNZIP.
  14. ;
  15. ; => int MUST BE 16 BITS!!! <=                    => WSIZE MUST BE 32K! <=
  16. ;
  17. ; struct huft is defined as follows:
  18. ;
  19. ;   struct huft {
  20. ;     uch e;                /* number of extra bits or operation */
  21. ;     uch b;                /* number of bits in this code or subcode */
  22. ;     union {
  23. ;       ush n;              /* literal, length base, or distance base */
  24. ;       struct huft *t;     /* pointer to next level of table */
  25. ;     } v;
  26. ;   };                      /* sizeof(struct huft) == 6 */
  27. ;
  28. ; so here we define the offsets of the various members of this struct:
  29.  
  30. h_e        equ    0
  31. h_b        equ    1
  32. h_n        equ    2
  33. h_t        equ    2
  34. SIZEOF_HUFT    equ    6
  35.  
  36. ; There are several global variables we need to access.  Their definitions:
  37. ;
  38. ;   unsigned long bb;
  39. ;   unsigned int bk, wp;
  40. ;   unsigned short mask[17];
  41. ;   FILE *in;
  42. ;   int encrypted;            /* FUNZIP CRYPT only */
  43. ;
  44. ;   int incnt, mem_mode;        /* non-FUNZIP only */
  45. ;   long csize;                /* non-FUNZIP only */
  46. ;   unsigned long outcnt;        /* non-FUNZIP only */
  47. ;   unsigned char *inptr;        /* non-FUNZIP only */
  48. ;
  49. ; bb is the global buffer that holds bits from the huffman code stream, which
  50. ; we cache in the register variable b.  bk is the number of valid bits in it,
  51. ; which we cache in k.  The macros NEEDBITS(n) and DUMPBITS(n) have side effects
  52. ; on b and k.
  53.  
  54.     xref    _bb
  55.     xref    _bk
  56.     xref    _mask
  57.     xref    _wp
  58.         IFD    FUNZIP
  59.          IFD    CRYPT
  60.     xref    _encrypted
  61.     xref    _update_keys    ; int update_keys(int)
  62.     xref    _decrypt_byte    ; int decrypt_byte(void)
  63.          ENDC    ; CRYPT
  64.     xref    _in
  65.     xref    _getc        ; int getc(FILE *)
  66.         ELSE    ; !FUNZIP
  67.     xref    _csize
  68.     xref    _incnt
  69.     xref    _mem_mode
  70.     xref    _inptr
  71.     xref    _readbyte    ; int readbyte(void)
  72.         ENDC
  73.     xref    _flush        ; if FUNZIP:  int flush(unsigned long)
  74.     ; ...if !FUNZIP:  int flush(unsigned char *, unsigned long *, int)
  75.  
  76. ; Here are our register variables.  Remember that int == short!
  77.  
  78. b    equr    d2        ; unsigned long
  79. k    equr    d3        ; unsigned int <= 32
  80. e    equr    d4        ; unsigned int < 256 for most use
  81. w    equr    d5        ; unsigned int
  82. n    equr    d6        ; unsigned int
  83. d    equr    d7        ; unsigned int
  84.  
  85. ; assert: we always maintain w and d as valid unsigned longs.
  86.  
  87. t    equr    a2        ; struct huft *
  88. slide    equr    a3        ; unsigned char *
  89. mask    equr    a6        ; unsigned short *
  90.  
  91. ; Couple other items we need:
  92.  
  93. savregs    reg    d2-d7/a2/a3/a6
  94.  
  95. WSIZE    equ    $8000        ; 32k... be careful not to treat as negative!
  96.  
  97.         IFD    FUNZIP
  98. ; This does getc(in).  Aztec version is based on #define getc(fp) in stdio.h
  99.  
  100.          IFD    AZTEC
  101.     xref    __filbuf
  102. GETC          MACRO
  103.     move.l        _in,a0
  104.     move.l        (a0),a1        ; in->_bp
  105.     cmp.l        4(a0),a1    ; in->_bend
  106.     blo.s        gci\@
  107.     move.l        a0,-(sp)
  108.     jsr        __filbuf
  109.     addq        #4,sp
  110.     bra.s        gce\@
  111. gci\@:    moveq        #0,d0        ; must be valid as longword
  112.     move.b        (a1)+,d0
  113.     move.l        a1,(a0)
  114. gce\@:
  115.           ENDM
  116.          ELSE    ; !AZTEC
  117. GETC          MACRO
  118.     move.l        _in,-(sp)
  119.     jsr        _getc
  120.     addq        #4,sp
  121.           ENDM
  122.          ENDC    ; AZTEC
  123.         ENDC    ; FUNZIP
  124.  
  125. ; Input depends on the NEXTBYTE macro.  This exists in three different forms.
  126. ; The first two are for fUnZip, with and without decryption.  The last is for
  127. ; regular UnZip with or without decryption.  The resulting byte is returned
  128. ; in d0 as a longword, and d1, a0, and a1 are clobbered.
  129.  
  130.         IFD    FUNZIP
  131.          IFD    CRYPT
  132. NEXTBYTE      MACRO
  133.     GETC
  134.     tst.w        _encrypted
  135.     beq.s        nbe\@
  136.     move.w        d0,-(sp)    ; save thru next call
  137.     jsr        _decrypt_byte
  138.     eor.w        d0,(sp)        ; becomes arg to update_keys
  139.     jsr        _update_keys
  140.     addq        #2,sp
  141. nbe\@:    ext.l        d0        ; assert -1 <= d0 <= 255
  142.           ENDM
  143.          ELSE    ; !CRYPT
  144. NEXTBYTE      MACRO
  145.     GETC            ; nothing else in this case
  146.           ENDM
  147.          ENDC
  148.         ELSE    ; !FUNZIP
  149. NEXTBYTE     MACRO
  150.     subq.l        #1,_csize
  151.     bge.s        nbg\@
  152.     moveq        #-1,d0        ; return EOF
  153.     bra.s        nbe\@
  154. nbg\@:    subq.w        #1,_incnt
  155.     bge.s        nbs\@
  156.     jsr        _readbyte
  157.     bra.s        nbe\@
  158. nbs\@:    moveq        #0,d0
  159.     move.l        _inptr,a0
  160.     move.b        (a0)+,d0
  161.     move.l        a0,_inptr
  162. nbe\@:
  163.          ENDM
  164.         ENDC
  165.  
  166. ; FLUSH has different versions for fUnZip and UnZip.  Arg must be a longword.
  167.  
  168.         IFD    FUNZIP
  169. FLUSH         MACRO
  170.     move.l        \1,-(sp)
  171.     jsr        _flush
  172.     addq        #4,sp
  173.          ENDM
  174.         ELSE    ; !FUNZIP
  175.     xref    _mem_mode
  176.     xref    _outcnt
  177. FLUSH         MACRO
  178.     tst.w        _mem_mode
  179.     bne.s        fm\@
  180.     move.w        #0,-(sp)    ; unshrink flag: always false
  181.     move.l        \1,-(sp)        ; length
  182.     move.l        slide,-(sp)    ; buffer to flush
  183.     jsr        _flush
  184.     lea        10(sp),sp
  185.     bra.s        fe\@
  186. fm\@:    move.l        w,_outcnt
  187. fe\@:
  188.          ENDM
  189.         ENDC    ; FUNZIP
  190.  
  191. ; Here are the two bit-grabbing macros, defined in their non-CHECK_EOF form:
  192. ;
  193. ;   define NEEDBITS(n) {while(k<(n)){b|=((ulg)NEXTBYTE)<<k;k+=8;}}
  194. ;   define DUMPBITS(n) {b>>=(n);k-=(n);}
  195. ;
  196. ; NEEDBITS clobbers d0, d1, a0, and a1, none of which can be used as the arg
  197. ; to the macro specifying the number of bits.  The arg can be a shortword memory
  198. ; address, or d2-d7.  The result is copied into d1 as a word ready for masking.
  199. ; DUMPBITS has no side effects; the arg must be a d-register (or immediate in the
  200. ; range 1-8?) and only the lower byte is significant.
  201.  
  202. NEEDBITS    MACRO
  203. nb\@:    cmp.w        \1,k        ; assert 0 < k <= 32 ... arg may be 0
  204.     bhs.s        ne\@
  205.     NEXTBYTE            ; returns in d0.l
  206.     lsl.l        k,d0
  207.     or.l        d0,b
  208.     addq.w        #8,k
  209.     bra.s        nb\@
  210. ne\@:    move.w        b,d1
  211.         ENDM
  212.  
  213. DUMPBITS    MACRO
  214.     lsr.l        \1,b        ; upper bits of \1 are ignored??
  215.     sub.b        \1,k
  216.         ENDM
  217.  
  218.  
  219. ; ******************************************************************************
  220. ; Here we go, finally:
  221.  
  222.     xdef    _flate_codes    ; (pointer, pointer, int, int, pointer)
  223.  
  224. _flate_codes:
  225.     link        a5,#-4
  226.     movem.l        savregs,-(sp)
  227. ; 8(a5) = tl, 12(a5) = td, 16(a5) = bl, 18(a5) = bd, 20(a5) = slide,
  228. ; -2(a5) = ml, -4(a5) = md.  Here we cache some globals and args:
  229.     move.l        20(a5),slide
  230.     lea        _mask,mask
  231.     move.l        _bb,b
  232.     move.w        _bk,k
  233.     moveq        #0,w        ; keep this usable as longword
  234.     move.w        _wp,w
  235.     moveq        #0,e        ; keep this usable as longword too
  236.     move.w        16(a5),d0
  237.     add.w        d0,d0
  238.     move.w        (mask,d0.w),-2(a5)    ; ml = mask[bl]
  239.     move.w        18(a5),d0
  240.     add.w        d0,d0
  241.     move.w        (mask,d0.w),-4(a5)    ; md = mask[bd]
  242.  
  243. main_loop:
  244.     NEEDBITS    16(a5)        ; bl
  245.     and.w        -2(a5),d1    ; ml
  246.     mulu        #SIZEOF_HUFT,d1
  247.     move.l        8(a5),a0    ; tl
  248.     lea        (a0,d1.l),t
  249.     move.b        h_e(t),e
  250.     cmp.w        #16,e
  251.     bls.s        topdmp
  252. intop:     moveq        #1,d0
  253.      cmp.w        #99,e
  254.      beq        return        ; error in zipfile
  255.      move.b        h_b(t),d0
  256.      DUMPBITS    d0
  257.      sub.w        #16,e
  258.      NEEDBITS    e
  259.      move.w        e,d0
  260.      add.w        d0,d0
  261.      and.w        (mask,d0.w),d1
  262.      mulu        #SIZEOF_HUFT,d1
  263.      move.l        h_t(t),a0
  264.      lea        (a0,d1.l),t
  265.      move.b        h_e(t),e
  266.      cmp.w        #16,e
  267.      bgt.s        intop
  268. topdmp:    move.b        h_b(t),d0
  269.     DUMPBITS    d0
  270.  
  271.     cmp.w        #16,e        ; is this huffman code a literal?
  272.     bne        lenchk        ; no
  273.     move.w        h_n(t),d0    ; yes
  274.     move.b        d0,(slide,w.l)    ; stick in the decoded byte
  275.     addq.w        #1,w
  276.     cmp.w        #WSIZE,w
  277.     blo        main_loop
  278.     FLUSH        w
  279.     moveq        #0,w
  280.     bra        main_loop    ; do some more
  281.  
  282. lenchk:    cmp.w        #15,e        ; is it an end-of-block code?
  283.     beq        finish        ; if yes, we're done
  284.     NEEDBITS    e        ; no: we have a duplicate string
  285.     move.w        e,d0
  286.     add.w        d0,d0
  287.     and.w        (mask,d0.w),d1
  288.     move.w        h_n(t),n
  289.     add.w        d1,n        ; length of block to copy
  290.     DUMPBITS    e
  291.     NEEDBITS    18(a5)        ; bd
  292.     and.w        -4(a5),d1    ; md
  293.     mulu        #SIZEOF_HUFT,d1
  294.     move.l        12(a5),a0    ; td
  295.     lea        (a0,d1.l),t
  296.     move.b        h_e(t),e
  297.     cmp.w        #16,e
  298.     bls.s        middmp
  299. inmid:     moveq        #1,d0
  300.      cmp.w        #99,e
  301.      beq        return        ; error in zipfile
  302.      move.b        h_b(t),d0
  303.      DUMPBITS    d0
  304.      sub.w        #16,e
  305.      NEEDBITS    e
  306.      move.w        e,d0
  307.      add.w        d0,d0
  308.      and.w        (mask,d0.w),d1
  309.      mulu        #SIZEOF_HUFT,d1
  310.      move.l        h_t(t),a0
  311.      lea        (a0,d1.l),t
  312.      move.b        h_e(t),e
  313.      cmp.w        #16,e
  314.      bgt.s        inmid
  315. middmp:    move.b        h_b(t),d0
  316.     DUMPBITS    d0
  317.     NEEDBITS    e
  318.     move.w        e,d0
  319.     add.w        d0,d0
  320.     and.w        (mask,d0.w),d1
  321.     move.l        w,d
  322.     sub.w        h_n(t),d
  323.     sub.w        d1,d        ; distance back to block to copy
  324.     DUMPBITS    e
  325.  
  326. indup:     move.w        #WSIZE,e    ; violate the e < 256 rule
  327.      and.w        #WSIZE-1,d
  328.      cmp.w        d,w
  329.      blo.s        ddgw
  330.       sub.w        w,e
  331.      bra.s        dadw
  332. ddgw:      sub.w        d,e
  333. dadw:     cmp.w        n,e
  334.      bls.s        delen
  335.       move.w    n,e
  336. delen:     sub.w        e,n        ; size of sub-block to copy
  337.      move.l        slide,a0
  338.      move.l        a0,a1
  339.      add.l        w,a0        ; w and d are valid longwords
  340.      add.l        d,a1
  341.      move.w        e,d0
  342.      subq        #1,d0        ; assert >= 0 if sign extended
  343. dspin:      move.b    (a1)+,(a0)+    ; string is probably short, so
  344.       dbra        d0,dspin    ; don't use any fancier copy method
  345.      add.w        e,w
  346.      add.w        e,d
  347.      cmp.w        #WSIZE,w
  348.      blo.s        dnfl
  349.      FLUSH        w
  350.      moveq        #0,w
  351. dnfl:     tst.w        n        ; need to do more sub-blocks?
  352.      bne        indup        ; yes
  353.     moveq        #0,e        ; restore zeroness in upper bytes
  354.     bra        main_loop    ; do some more
  355.  
  356. finish:    move.w        w,_wp        ; restore cached globals
  357.     move.w        k,_bk
  358.     move.l        b,_bb
  359.     moveq        #0,d0            ; return "no error"
  360. return:    movem.l        (sp)+,savregs
  361.     unlk        a5
  362.     rts
  363.