home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / mac / developm / source / mpwtools.cpt / misc src / compstream.a < prev    next >
Encoding:
Text File  |  1990-04-24  |  18.7 KB  |  891 lines

  1. ;; Copyright 1988, Gail Zacharias.  All rights reserved.
  2. ;; Permission is hereby granted to copy, reproduce, redistribute or
  3. ;; otherwise use this software provided there is no monetary profit
  4. ;; gained specifically from its use or reproduction, it is not sold,
  5. ;; rented, traded or otherwise marketed, and this copyright notice 
  6. ;; and the software version number is included prominently in any copy
  7. ;; made.
  8. ;; This is compstream version 1.1.
  9. ;;
  10. ;; Send comments, suggestions, bug reports (not bloody likely), feature
  11. ;; requests, etc. to gz@entity.com.
  12. ;;
  13.  
  14.     load 'FlowCtlMacs.d'
  15.     case object
  16.  
  17.     export    (compinit, compwrite, compclose):code
  18.     export    (uncompinit, uncompread, uncompclose):code
  19.  
  20. ; This is a library for use with MPW C programs.  It implements compression
  21. ; and uncompression compatible with the unix compress/uncompress programs.
  22. ; (But note that the unix programs create files with a 3 byte header which
  23. ; is NOT handled by this library.  It's up to the caller to take care of
  24. ; any headers).
  25. ;
  26. ;The compress module consists of three functions:
  27. ;(1) long compinit (maxbits, block_compress, outputfn, param)
  28. ;   int maxbits, block_compress;
  29. ;   int (*outputfn)();
  30. ;   long param;
  31. ;This function allocates and initializes a compress stream and returns a
  32. ;'stream handle', or 0 if it can't allocate enough memory for its data
  33. ;structures (in which case MemErr contains the error code).
  34. ;maxbits must be an integer between 9 and 16.  Larger values result in
  35. ;  better compression but require more memory.
  36. ;block_compress should be non-zero to do 'block compression'.  This is
  37. ; almost always a win, so use it.  It requires no extra memory.
  38. ;outputfn should be the function to do actual I/O.  It must be a function
  39. ; of 3 arguments:
  40. ;    int outputfn(param, size, buffer)
  41. ;       long param;
  42. ;       int size;
  43. ;       char *buffer;
  44. ;  param will be the same param argument that was passed to compinit.
  45. ;  The function should output the size bytes in buffer, and return a
  46. ;  non-negative value if successful, or a negative value if an error
  47. ;  occured.  The outputfn will not be called again after it returns
  48. ;  an error.
  49. ;(2) int compwrite (cstream, size, buffer)
  50. ;      long cstream;
  51. ;      int size;
  52. ;      char *buffer;
  53. ; This function adds the size bytes in buffer to the compress stream.  cstream
  54. ; is the stream handle returned by compinit.  compwrite returns a non-negative
  55. ; value if successful or a negative value if an error occured.  The value is
  56. ; actually the same as the value of last call to outputfn.  Note that compwrite
  57. ; does buffering and so the calls to compwrite and outputfn are not precisely
  58. ; synchronized - a given call to compwrite might call outputfn several times or
  59. ; it might not call it at all.  Once outputfn returns an error, compwrite will
  60. ; continue to return that error and never call outputfn again.
  61. ;(3) int compclose (cstream)
  62. ;      long cstream;
  63. ; This function writes out any remaining characters in the stream buffer and
  64. ; frees its data structures.  It returns an error code like compwrite.
  65.  
  66. ;The uncompress module consists of three functions:
  67. ;(1) long uncompinit (maxbits, block_compress, inputfn, param)
  68. ;   int maxbits, block_compress;
  69. ;   int (*inputfn)();
  70. ;   long param;
  71. ;This function allocates and initializes an uncompress stream and returns a
  72. ;'stream handle', or 0 if it can't allocate enough memory for its data
  73. ;structures (in which case MemErr contains the error code).
  74. ;maxbits and block_compress must be the values which were used by compress.
  75. ;inputfn should be the function to do actual I/O.  It must be a function
  76. ; of 3 arguments:
  77. ;    int inputfn(param, size, buffer)
  78. ;       long param;
  79. ;       int size;
  80. ;       char *buffer;
  81. ;  param will be the same param argument that was passed to compinit.
  82. ;  The function should try to read size bytes into buffer, and return
  83. ;  the number of bytes actually read.  A negative value means an error
  84. ;  occured, zero means end of file (no more bytes to be read).  The inputfn
  85. ;  will not be called again after it returns a non-positive value.
  86. ;(2) int uncompread (cstream, size, buffer)
  87. ;      long cstream;
  88. ;      int size;
  89. ;      char *buffer;
  90. ; This function stores (at most) size bytes into buffer.  cstream is the
  91. ; stream handle returned by uncompinit.  uncompread returns the number of
  92. ; bytes read, or a non-positive value if there are no more bytes (in which case
  93. ; the value is actually the value returned by the last call to the inputfn).
  94. ; Note that uncompread does buffering and so the calls to uncompread and
  95. ; inputfn are not precisely synchronized - a given call to uncompread might
  96. ; call inputfn several times or it might not call it at all.  Once inputfn
  97. ; returns a non-positive value, uncompread will continue to return that value
  98. ; and never call inputfn again.
  99. ;(3) int uncompclose (cstream)
  100. ;      long cstream;
  101. ; This function frees the data structures used by the stream.  It currently
  102. ; always returns 0 (no errors are possible).
  103.  
  104. ; Edit history
  105. ; 6/3/88 gz    1.1 Started edit history.  Fix in < 16 bit compression.
  106.  
  107. MemErr       equ    $220
  108. _NewPtr    opword $A100+30
  109. _DisposPtr opword $A000+31
  110. _Debugger  opword $A9FF
  111.  
  112.  
  113. compress proc
  114.  
  115. BUFSIZE    equ    512        ;Output buffer size.
  116.  
  117. CHECK_DIST equ    10000
  118.  
  119. h        equ    d2
  120. h2        equ    d3
  121. ch        equ    d4
  122. lastcode    equ    d5
  123. ncodes        equ    d6
  124. inpos        equ    d7
  125.  
  126. codeptr        equ    a1    ;must be a1 (see write8codes)
  127. chtab        equ    a2
  128. lasttab        equ    a3
  129. codetab        equ    a4
  130.  
  131. myregs        reg    d2-d7/a0-a4
  132. myregsz        equ    44
  133. hisregs        reg    d2-d7/a2-a4/a6
  134. hisregsz    equ    40    
  135.  
  136. fprec    record    0
  137. hsize        ds.l    1
  138. hshift        ds.w    1
  139. rd_cnt        ds.l    1
  140. rd_ptr        ds.l    1
  141. wr_cnt        ds.w    1
  142. wr_ptr        ds.l    1
  143. wr_param    ds.l    1
  144. wr_fn        ds.l    1
  145. wr_error    ds.l    1
  146. outpos        ds.l    1
  147. cd_cnt        ds.w    1
  148. cd_buf        ds.w    9
  149. checkpos    ds.l    1
  150. ratio        ds.l    1
  151. codesz        ds.w    1
  152. codelim        ds.l    1
  153. maxcodelim    ds.l    1
  154. savedregs    ds.b    myregsz
  155. wr_buf        ds.b    BUFSIZE
  156. fprecsz        equ    *
  157.     endr
  158.  
  159.     macro
  160.     writecode.&sz &code
  161.     subq.w #1,cd_cnt(a6)
  162.     if# mi then.s
  163.       bsr.&default(&sz,'w') write8codes
  164.     endif#
  165.     move.w &code,-(codeptr)
  166.     endm
  167.  
  168.     macro
  169.     getchar.&sz &ch,&eoflab
  170.     subq.l #1,rd_cnt(a6)
  171.     if# ge then.s
  172.       move.l rd_ptr(a6),a0
  173.       moveq #0,&ch
  174.       move.b (a0)+,&ch
  175.       move.l a0,rd_ptr(a6)
  176.     else#.s
  177.       bsr filbuf
  178.       move.l d0,&ch
  179.       bmi.&default(&sz,'w') &eoflab
  180.     endif#
  181.     addq.l #1,inpos
  182.     endm
  183.  
  184.     with fprec
  185.  
  186. ;compinit (maxbits, block_compress, outputfn, param)
  187.     entry compinit
  188. compinit
  189.     move.l #fprecsz,d0
  190.     _NewPtr
  191.     if# ne then.s
  192.       moveq #0,d0
  193.       rts
  194.     endif#
  195.     movem.l hisregs,-(sp)
  196.     move.l a0,a6
  197.     move.l hisregsz+16(sp),wr_param(a6)
  198.     move.l hisregsz+12(sp),wr_fn(a6)
  199.     clr.l wr_error(a6)
  200.     lea wr_buf(a6),a0
  201.     move.l a0,wr_ptr(a6)
  202.     move.w #BUFSIZE,wr_cnt(a6)
  203.     move.l hisregsz+4(sp),d0    ;maxbits
  204.     moveq #9,d1
  205.     if# d0 lt.l d1 then.s
  206.       move.l d1,d0
  207.     endif#
  208.     moveq #16,d1
  209.     if# d0 gt.l d1 then.s
  210.       move.l d1,d0
  211.     endif#
  212.     moveq #1,d1
  213.     lsl.l d0,d1
  214.     move.l d1,maxcodelim(a6)
  215.     subq.w #8,d0
  216.     move.w d0,hshift(a6)
  217.     lsl.w #2,d0
  218.     lea hsizes(pc),a0
  219.     move.l -4(a0,d0.w),hsize(a6)
  220.     move.l hsize(a6),d1
  221.     move.l d1,d0
  222.     _NewPtr
  223.     bne @memer1
  224.     move.l a0,chtab
  225.     add.l d1,d1
  226.     move.l d1,d0
  227.     _NewPtr
  228.     bne @memer2
  229.     move.l a0,lasttab
  230.     move.l d1,d0
  231.     _NewPtr
  232.     bne @memer3
  233.     move.l a0,codetab
  234.     clr.l ratio(a6)
  235.     moveq #0,inpos
  236.     move.l #3,outpos(a6)
  237.     move.l #CHECK_DIST,checkpos(a6)
  238.     move.w #9,codesz(a6)
  239.     move.l #$200,codelim(a6)
  240.     move.l #257,ncodes
  241.     tst.l hisregsz+8(sp)        ;block_compress
  242.     if# eq then.s
  243.       subq.l #1,ncodes
  244.       move.l #-1,checkpos(a6)
  245.     endif#
  246.     move.l codetab,a0
  247.     moveq #0,d0
  248.     move.l hsize(a6),d1
  249.     lsr.l #1,d1
  250.     bra.s *+4
  251.     move.l d0,(a0)+
  252.     dbf d1,*-2
  253.     move.w d0,(a0)
  254.     move.w #8,cd_cnt(a6)
  255.     lea cd_buf+16(a6),codeptr
  256.  
  257.     move.l a6,d0
  258.     bsr filret
  259.     move.l d0,lastcode
  260.     bmi @done
  261.     addq.l #1,inpos
  262.  
  263. @loop    getchar ch,@done
  264.     move.l ch,h
  265.     move.w hshift(a6),d0
  266.     lsl.w d0,h
  267.     eor.w lastcode,h
  268.     move.l h,h2
  269.     add.l h2,h2
  270.     move.w 0(codetab,h2.l),d0
  271.     if# ne then.s
  272.       if# ch eq.b 0(chtab,h.l) then.s
  273.        if# lastcode eq.w 0(lasttab,h2.l) then.s
  274.         move.w d0,lastcode
  275.         bra.s @loop
  276.        endif#
  277.       endif#
  278.       moveq #1,d1
  279.       tst.l h
  280.       if# ne then.s
  281.         move.l hsize(a6),d1
  282.         sub.l h,d1
  283.       endif#
  284. @search      sub.l d1,h
  285.       if# mi then.s
  286.         add.l hsize(a6),h
  287.       endif#
  288.       move.l h,h2
  289.       add.l h2,h2
  290.       move.w 0(codetab,h2.l),d0
  291.       if# ne then.s
  292.         if# ch eq.b 0(chtab,h.l) then.s
  293.          if# lastcode eq.w 0(lasttab,h2.l) then.s
  294.           move.w d0,lastcode
  295.           bra.s @loop
  296.          endif#
  297.         endif#
  298.         ;;This imitates what looks to me like bug in unix compress,
  299.         ;;just to stay exactly compatible...
  300.         tst.b 0(chtab,h.l)
  301.         bne.s @search
  302.         tst.w 0(lasttab,h2.l)
  303.         bne.s @search
  304.       endif#
  305.     endif#
  306.     writecode lastcode
  307.     if# ncodes eq.l codelim(a6) then.s
  308.        bsr write8codes
  309.        addq.w #1,cd_cnt(a6)
  310.        addq.w #1,codesz(a6)
  311.        move.l codelim(a6),d0
  312.        add.l d0,d0
  313.        if# d0 eq.l maxcodelim(a6) then.s
  314.          addq.l #1,d0
  315.        endif#
  316.        move.l d0,codelim(a6)
  317.     endif#
  318.     if# ncodes lt.l maxcodelim(a6) then.s
  319.       move.w ncodes,0(codetab,h2.l)
  320.       move.b ch,0(chtab,h.l)
  321.       move.w lastcode,0(lasttab,h2.l)
  322.       addq.l #1,ncodes
  323.     else#.s
  324.       if# inpos cc.l checkpos(a6) then.s
  325.         move.l inpos,d0
  326.         add.l #CHECK_DIST,d0
  327.         move.l d0,checkpos(a6)
  328.         move.l inpos,d1
  329.         moveq #8,d2
  330.         sub.w cd_cnt(a6),d2
  331.         mulu codesz(a6),d2
  332.         lsr.w #3,d2
  333.         add.l outpos(a6),d2
  334.         bsr ScaledQuo
  335.         if# d0 hi.l ratio(a6) then.s
  336.           move.l d0,ratio(a6)
  337.         else#.s
  338.           writecode #256
  339.           bsr write8codes
  340.           addq.w #1,cd_cnt(a6)
  341.           clr.l ratio(a6)
  342.           move.l codetab,a0
  343.           moveq #0,d0
  344.           move.l hsize(a6),d1
  345.           lsr.l #1,d1
  346.           bra.s *+4
  347.           move.l d0,(a0)+
  348.           dbf d1,*-2
  349.           move.w d0,(a0)
  350.           move.l #257,ncodes
  351.           move.w #9,codesz(a6)
  352.           move.l #$200,codelim(a6)
  353.         endif#
  354.       endif#
  355.     endif#
  356.     move.l ch,lastcode
  357.     bra @loop
  358.  
  359. @done    writecode lastcode
  360.     bsr forcebuf
  361.     move.l codetab,a0
  362.     _DisposPtr
  363. @memer3    move.w MemErr,-(sp)
  364.     move.l lasttab,a0
  365.     _DisposPtr
  366.     move.w (sp)+,MemErr
  367. @memer2    move.w MemErr,-(sp)
  368.     move.l chtab,a0
  369.     _DisposPtr
  370.     move.w (sp)+,MemErr
  371. @memer1    move.l wr_error(a6),-(sp)
  372.     move.w MemErr,-(sp)
  373.     move.l a6,a0
  374.     _DisposPtr
  375.     move.w (sp)+,MemErr
  376.     move.l (sp)+,d0
  377.     movem.l (sp)+,hisregs
  378.     rts
  379.  
  380. hsizes:
  381.     dc.l    887        ;9
  382.     dc.l    1559        ;10
  383.     dc.l    2801        ;11
  384.     dc.l    5003        ;12
  385.     dc.l    9001        ;13
  386.     dc.l    18013        ;14
  387.     dc.l    35023        ;15
  388.     dc.l    69001        ;16
  389.  
  390. ;256*(D1/D2) -> D0
  391. ScaledQuo:
  392.     if# d1 ls.l #$FFFFFF then.s
  393.       lsl.l #8,d1
  394.     else#.s
  395.       lsr.l #8,d2
  396.       if# eq then.s
  397.         moveq #-1,d0
  398.         rts
  399.       endif#
  400.     endif#
  401.     if# d2 ls.l #$FFFF then.s
  402.       swap d1
  403.       moveq #0,d0
  404.       move.w d1,d0
  405.       divu d2,d0
  406.       swap d0
  407.       move.w d0,d1
  408.       swap d1
  409.       divu d2,d1
  410.       move.w d1,d0
  411.       rts
  412.     endif#
  413.     moveq #0,d0
  414.     move.w d1,d0
  415.     swap d0
  416.     clr.w d1
  417.     swap d1
  418.     move.l d2,a0
  419.     moveq #16-1,d2
  420. @next    add.l d0,d0
  421.     addx.l d1,d1
  422.     if# a0 ls.l d1 then.s
  423.       sub.l a0,d1
  424.       addq.w #1,d0
  425.     endif#
  426.     dbf d2,@next
  427.     rts
  428.  
  429. forcebuf:  ;clobbers codeptr(=a1) and ncodes
  430.     move.w cd_cnt(a6),ncodes
  431.     cmp.w #8,ncodes
  432.     if# ne then.s
  433.       subq.w #1,cd_cnt(a6)
  434.       if# pl then.s
  435.         clr.w -(codeptr)
  436.       endif#
  437.       bsr.s write8codes
  438.       mulu codesz(a6),ncodes    ;Correction for really < 8 codes...
  439.       lsr.w #3,ncodes
  440.       sub.l ncodes,outpos(a6)
  441.       add.w ncodes,wr_cnt(a6)
  442.       sub.l ncodes,wr_ptr(a6)
  443.     endif#
  444.     tst.l wr_error(a6)
  445.     if# pl then.s
  446.       pea wr_buf(a6)
  447.       move.l wr_ptr(a6),d0
  448.       sub.l (sp),d0
  449.       move.l d0,-(sp)
  450.       move.l wr_param(a6),-(sp)
  451.       move.l wr_fn(a6),a0
  452.       jsr (a0)
  453.       lea 12(sp),sp
  454.       move.l d0,wr_error(a6)
  455.     endif#
  456.     rts
  457.  
  458. ;assumes codeptr = a1
  459. write8codes:
  460.     movem.l d2-d4,-(sp)
  461. @rewr    moveq #0,d3
  462.     move.w codesz(a6),d3
  463.     move.l wr_ptr(a6),a0
  464.     add.l d3,wr_ptr(a6)
  465.     sub.w d3,wr_cnt(a6)
  466.     if# mi then.s
  467.       add.w wr_cnt(a6),d3
  468.       pea wr_buf(a6)
  469.       move.l (sp),wr_ptr(a6)
  470.       lea BUFSIZE,a0
  471.       move.w a0,wr_cnt(a6)
  472.       sub.w d3,a0
  473.       move.l a0,-(sp)
  474.       move.l wr_param(a6),-(sp)
  475.       tst.l wr_error(a6)
  476.       if# pl then.s
  477.         move.l wr_fn(a6),a0
  478.         jsr (a0)
  479.         move.l d0,wr_error(a6)
  480.       endif#
  481.       lea 12(sp),sp
  482.       bra.s @rewr
  483.     endif#
  484.     add.l d3,outpos(a6)
  485.     moveq #0,d1        ;d1 = leftover byte
  486.     moveq #0,d2        ;d2 = # bits in this byte
  487.     subq.w #8,d3        ;d3 = codesz - 8
  488.     moveq #8-1,d4        ;d4 = count
  489.     lea cd_buf+16(a6),codeptr
  490. @loop    moveq #0,d0
  491.     move.w -(codeptr),d0
  492.     lsl.l d2,d0
  493.     or.b d1,d0
  494.     add.w d3,d2
  495.     subq.w #8,d2
  496.     if# mi then.s
  497.       addq.w #8,d2
  498.       move.w d0,(codeptr)+
  499.       move.b -(codeptr),(a0)+
  500.       move.b -(codeptr),d1
  501.     else#.s
  502.       move.l d0,(codeptr)+
  503.       move.b -(codeptr),(a0)+
  504.       move.b -(codeptr),(a0)+
  505.       move.b -(codeptr),d1
  506.       subq #1,codeptr
  507.     endif#
  508.     dbf d4,@loop
  509.     lea cd_buf+16(a6),codeptr
  510.     move.w #8-1,cd_cnt(a6)
  511.     movem.l (sp)+,d2-d4
  512.     rts
  513.  
  514. ;compwrite(cstream, size, buf)
  515.     entry compwrite
  516. compwrite:
  517.     movem.l hisregs,-(sp)
  518.     move.l hisregsz+4(sp),a6        ;cstream
  519.     movem.l savedregs(a6),myregs
  520.     move.l a0,-(sp)
  521.     move.l wr_error(a6),d0
  522.     bmi.s filret
  523.     move.l hisregsz+4+12(sp),a0        ;buf
  524.     move.l hisregsz+4+8(sp),d0        ;size
  525.     subq.l #1,d0
  526.     blt.s filbuf
  527.     move.l d0,rd_cnt(a6)
  528.     moveq #0,d0
  529.     move.b (a0)+,d0
  530.     move.l a0,rd_ptr(a6)
  531.     rts
  532. filbuf    move.l wr_error(a6),d0
  533. filret    move.l (sp)+,a0
  534.     movem.l myregs,savedregs(a6)
  535.     movem.l (sp)+,hisregs
  536.     rts
  537.  
  538. ;compclose(cstream)
  539.     export compclose
  540. compclose:
  541.     move.l 4(sp),d0
  542.     if# eq then.s
  543.       rts
  544.     endif#
  545.     movem.l hisregs,-(sp)
  546.     move.l d0,a6
  547.     movem.l savedregs(a6),myregs
  548.     moveq #-1,d0
  549.     jmp (a0)
  550.  
  551.     endwith
  552.     endproc
  553.  
  554. uncompress proc
  555.  
  556. BUFSIZE    equ    512
  557.  
  558. STRSIZE    equ    8000
  559.  
  560. lastchar    equ    d2
  561. lastcode    equ    d3
  562. ncodes        equ    d4
  563. codelim        equ    d5
  564. codesz        equ    d6
  565. readcnt        equ    d7
  566. codeptr        equ    a1
  567. strptr        equ    a2
  568. chartab        equ    a3
  569. codetab        equ    a4
  570.  
  571. myregs        reg    d1-d7/a0-a4
  572. myregsz        equ    48
  573. hisregs        reg    d2-d7/a2-a4/a6
  574. hisregsz    equ    40    
  575.  
  576. fprec    record    0
  577. codebuf        ds.w    9
  578. strend        ds.l    1
  579. maxcodelim    ds.l    1
  580. rd_param    ds.l    1
  581. rd_fn        ds.l    1
  582. rd_ptr        ds.l    1
  583. rd_cnt        ds.w    1
  584. rd_error    ds.l    1
  585. wr_cnt        ds.l    1
  586. wr_ptr        ds.l    1
  587. tempbuf        ds.b    16
  588. savedregs    ds.b    myregsz
  589. rd_buf        ds.b    BUFSIZE
  590. fprecsz        equ    *
  591.     endr
  592.  
  593.     with fprec
  594.  
  595.     macro
  596.     readcode.&sz &dreg,&eoflab
  597.     sub.w codesz,readcnt
  598.     if# mi then.s
  599.       bsr.&default(&sz,'w') read8codes
  600.       bmi.&default(&sz,'w') &eoflab
  601.     endif#
  602.     moveq #0,&dreg
  603.     move.w -(codeptr),&dreg
  604.     endm
  605.  
  606.     macro
  607.     putchar
  608.     subq.l #1,wr_cnt(a6)
  609.     if# ge then.s
  610.       move.l wr_ptr(a6),a0
  611.       move.b d1,(a0)+
  612.       move.l a0,wr_ptr(a6)
  613.     else#.s
  614.       bsr flsbuf
  615.     endif#
  616.     endm
  617.  
  618.  
  619. ;uncompinit (maxbits, block_compress, inputfn, param)
  620.     export uncompinit
  621. uncompinit
  622.     move.l #fprecsz,d0
  623.     _NewPtr
  624.     if# ne then.s
  625.       moveq #0,d0
  626.       rts
  627.     endif#
  628.     movem.l hisregs,-(sp)
  629.     move.l a0,a6
  630.     move.l hisregsz+16(sp),rd_param(a6)
  631.     move.l hisregsz+12(sp),rd_fn(a6)
  632.     clr.w rd_cnt(a6)
  633.     move.l #1,rd_error(a6)
  634.     move.l hisregsz+4(sp),d0    ;maxbits
  635.     moveq #9,d1
  636.     if# d0 lt.l d1 then.s
  637.       move.l d1,d0
  638.     endif#
  639.     moveq #16,d1
  640.     if# d0 gt.l d1 then.s
  641.       move.l d1,d0
  642.     endif#
  643.     moveq #1,d1
  644.     lsl.l d0,d1
  645.     move.l d1,maxcodelim(a6)
  646.     sub.l #256,d1
  647.     move.l d1,d0
  648.     _NewPtr
  649.     bne memer1
  650.     lea -256(a0),chartab
  651.     move.l d1,d0
  652.     add.l d0,d0
  653.     _NewPtr
  654.     bne memer2
  655.     lea -512(a0),codetab
  656.     move.l #STRSIZE,d0
  657.     _NewPtr
  658.     bne memer3
  659.     lea STRSIZE(a0),strptr
  660.     move.l strptr,strend(a6)
  661.  
  662.     moveq #9,codesz
  663.     move.l #$200,codelim
  664.     moveq #0,readcnt
  665.  
  666.     move.l #256,ncodes
  667.     tst.l hisregsz+8(sp)        ;block_compress
  668.     if# ne then.s
  669.       addq.l #1,ncodes
  670.       bset #31,readcnt        ;use high word for flag...
  671.     endif#
  672.  
  673.     move.l a6,d0
  674.     moveq #-1,d1
  675.     bsr flsret            ;Init wr_cnt and wr_ptr.
  676.  
  677.     readcode lastcode,@done
  678.     move.b lastcode,lastchar
  679.  
  680.     move.l lastcode,d1
  681.     putchar
  682.  
  683. @loop    readcode d0,@done
  684.     if# d0 eq.w #256 then.s
  685.      tst.l readcnt
  686.      if# mi then.s
  687.       move.l d0,ncodes
  688.       moveq #9,codesz
  689.       move.l #$200,codelim
  690.       clr.w readcnt
  691.       readcode.s d0,@done
  692.      endif#
  693.     endif#
  694.     move.l d0,d1
  695.     if# d0 cc.l ncodes then.s
  696.       move.b lastchar,-(strptr)
  697.       move.l lastcode,d0
  698.     endif#
  699.     move.l d0,lastchar
  700.     bra.s @get
  701. @getlp    move.l lastchar,d0
  702.     move.b 0(chartab,d0.l),-(strptr)
  703.     add.l d0,d0
  704.     move.w 0(codetab,d0.l),lastchar
  705. @get    cmp.w #256,lastchar
  706.     bcc.s @getlp
  707.  
  708.     if# ncodes lt.l maxcodelim(a6) then.s
  709.       move.l ncodes,d0
  710.       move.b lastchar,0(chartab,d0.l)
  711.       add.l d0,d0
  712.       move.w lastcode,0(codetab,d0.l)
  713.       addq.l #1,ncodes
  714.     endif#
  715.     move.l d1,lastcode
  716.     if# ncodes eq.l codelim then.s
  717.       addq.w #1,codesz
  718.       add.l codelim,codelim
  719.       if# codelim eq.l maxcodelim(a6) then.s
  720.         addq.l #1,codelim        ;make it so this never triggers again
  721.       endif#
  722.       clr.w readcnt
  723.     endif#
  724.     move.b lastchar,d1
  725.     bra.s @put
  726. @putlp    move.b (strptr)+,d1
  727. @put    putchar
  728.     cmp.l strend(a6),strptr
  729.     bne.s @putlp
  730.     bra @loop
  731.  
  732. @done    bsr flush
  733.     _debugger        ;Shouldn't return
  734.  
  735. ;Read 8 codes into codebuf
  736. ;Input: codesz
  737. ;Output: readcnt, codeptr or MI flag set if end of file.
  738. read8codes:
  739.     movem.l d2-d5,-(sp)
  740.     move.l rd_ptr(a6),a0
  741.     move.l codesz,d0
  742.     sub.w d0,rd_cnt(a6)
  743.     if# lt then.s
  744.       bsr.s fillbuf
  745.     else#.s
  746.       add.l d0,rd_ptr(a6)
  747.     endif#
  748.     lsl.w #3,d0
  749.     sub.w codesz,d0
  750.     bmi.s @ret
  751.     move.w d0,readcnt
  752.     moveq #1,d2        ;d2 = mask
  753.     lsl.w codesz,d2
  754.     subq.w #1,d2
  755.     move.w codesz,d3    ;d3 = codesz - 8
  756.     subq.w #8,d3
  757.     lea codebuf+18(a6),codeptr
  758.     move.w codesz,d4    ;d4 = byte count
  759.     moveq #0,d5        ;d5 = # used bits in this byte
  760. @loop    move.w d5,d1        ;save bit count
  761.     add.w d3,d5
  762.     move.b (a0)+,-(codeptr)
  763.     subq #1,d4
  764.     subq.w #8,d5
  765.     if# lt then.s
  766.       addq.w #8,d5
  767.       move.b (a0),-(codeptr)
  768.       move.w (codeptr)+,d0
  769.       lsr.w d1,d0
  770.       and.w d2,d0
  771.       move.w d0,-(codeptr)
  772.       bra.s @loop
  773.     endif#
  774.     move.b (a0)+,-(codeptr)
  775.     move.b (a0),-(codeptr)
  776.     subq #1,codeptr
  777.     move.l (codeptr)+,d0
  778.     lsr.l d1,d0
  779.     and.w d2,d0
  780.     move.w d0,-(codeptr)
  781.     subq #1,d4
  782.     bne.s @loop
  783.     lea codebuf+18(a6),codeptr
  784. @ret    movem.l (sp)+,d2-d5
  785.     rts
  786.  
  787. fillbuf:
  788.     lea tempbuf(a6),codeptr        ;handy areg....
  789.     move.w rd_cnt(a6),d1
  790.     add.w d1,d0
  791.     bra.s @more
  792.      move.b (a0)+,(codeptr)+
  793. @more    dbf d0,*-2
  794.     move.l rd_error(a6),d0
  795.     if# gt then.s
  796.       movem.l d1/a1,-(sp)
  797.       pea rd_buf(a6)
  798.       pea BUFSIZE
  799.       move.l rd_param(a6),-(sp)
  800.       move.l rd_fn(a6),a0
  801.       jsr (a0)
  802.       lea 12(sp),sp
  803.       movem.l (sp)+,d1/a1
  804.       move.l d0,rd_error(a6)
  805.     endif#
  806.     if# gt then.s
  807.       lea rd_buf(a6),a0
  808.       add.w d0,d1
  809.       bmi.s @more
  810.       sub.w d1,d0
  811.       bra.s *+4
  812.        move.b (a0)+,(codeptr)+
  813.       dbf d0,*-2
  814.       move.w d1,rd_cnt(a6)
  815.       move.l a0,rd_ptr(a6)
  816.     else#.s
  817.       clr.w rd_cnt(a6)
  818.     endif#
  819.     move.l codeptr,d0
  820.     lea tempbuf(a6),a0
  821.     sub.l a0,d0
  822.     rts
  823.  
  824. ;uncompread(cstream, size, buf)
  825.     export uncompread
  826. uncompread:
  827.     movem.l hisregs,-(sp)
  828.     move.l hisregsz+4(sp),a6        ;cstream
  829.     movem.l savedregs(a6),myregs
  830.     move.l a0,-(sp)
  831.     move.l hisregsz+4+12(sp),a0        ;buf
  832.     move.l hisregsz+4+8(sp),d0        ;size
  833.     tst.l d1                ;we doing flush or flsbuf?
  834.     if# mi then.s
  835.       tst.l rd_error(a6)
  836.       ble.s flseof
  837.     else#.s
  838.       subq.l #1,d0
  839.       blt.s flsbuf
  840.       move.b d1,(a0)+
  841.     endif#
  842.     move.l a0,wr_ptr(a6)
  843.     move.l d0,wr_cnt(a6)
  844.     rts
  845. flsbuf:    move.l hisregsz+4+8(sp),d0        ;size
  846. flsret:    move.l (sp)+,a0
  847.     movem.l myregs,savedregs(a6)
  848.     movem.l (sp)+,hisregs
  849.     rts
  850.  
  851. flush    moveq #-1,d1
  852.     move.l hisregsz+4+8(sp),d0
  853.     sub.l wr_cnt(a6),d0
  854.     bne.s flsret
  855. flseof:    move.l rd_error(a6),d0
  856.     bra.s flsret
  857.  
  858. ;uncompclose(cstream)
  859.     export uncompclose
  860. uncompclose:
  861.     move.l 4(sp),d0
  862.     if# eq then.s
  863.       rts
  864.     endif#
  865.     movem.l hisregs,-(sp)
  866.     move.l d0,a6
  867.     movem.l savedregs(a6),myregs
  868.     move.l strend(a6),a0
  869.     lea -STRSIZE(a0),a0
  870.     _DisposPtr
  871. memer3    move.w MemErr,-(sp)
  872.     lea 512(codetab),a0
  873.     _DisposPtr
  874.     move.w (sp)+,MemErr
  875. memer2    move.w MemErr,-(sp)
  876.     lea 256(chartab),a0
  877.     _DisposPtr
  878.     move.w (sp)+,MemErr
  879. memer1    move.w MemErr,-(sp)
  880.     move.l a6,a0
  881.     _DisposPtr
  882.     move.w (sp)+,MemErr
  883.     moveq #0,d0
  884.     movem.l (sp)+,hisregs
  885.     rts
  886.     endwith
  887.     endproc
  888.  
  889.  
  890.     end
  891.