;
; Copyright © 1991, 1992 by Walter Rothe. You may freely use and modify this
; program, but not for commercial profit. A modest fee for distribution is
; allowed. Derivative works must be released with source along with the
; executable or provisions made to provide the user source, if requested.
; Uploading source to a major bulletin board system within 6 months of the
; time of the request satisfies this requirement. This copyright notice
; must not be deleted from the source.
;
;:ts=8
        far     data
        machine mc68020
;#include "lh5.h"
;
;int make_table(nchar, bitlen, tablebits, table)
;int nchar;
;uchar bitlen[];
;int tablebits;
;ushort table[];
;{
        xdef    _make_table
_make_table:
        link    a5,#.2
        movem.l .3,-(sp)
;        ushort count[17], weight[17], start[18], *p;
;        uint i, k, len, jutbits, avail, nextcode, mask;
;        register uint ch;
;        register ushort *nxtcptr, *endcptr;
;        register uchar *blp = &bitlen[0];
;        register uchar *blpend = &bitlen[nchar];
;
;        for (i = 1; i <= 16; i++) count[i] = 0;
        move.l  12(a5),d3
        move.l  8(a5),d4
        add.l   12(a5),d4
        move.l  #1,-112(a5)
.10003
        move.l  -112(a5),d0
        add.l   d0,d0
        lea     -34(a5),a0
        clr.w   (a0,d0.l)
.10001
        add.l   #1,-112(a5)
        cmp.l   #16,-112(a5)
        bls     .10003
.10002
;        for (; blp < blpend;) count[ *blp++ ]++;
        lea     -34(a5),a0
        move.l  #0,d0
        move.l  d3,a1
        bra     .10007
.10006
        move.b  (a1)+,d0
        add.l   d0,d0
        add.w   #1,(a0,d0.w)
.10004
.10007
        cmp.l   d4,a1
        bcs     .10006
.10005
;
;        start[1] = 0;
        clr.w   -102(a5)
;        for (i = 1; i <= 16; i++)
        move.l  #1,-112(a5)
.10010
;                start[i + 1] = start[i] + (count[i] << (16 - i));
        move.l  -112(a5),d0
        add.l   d0,d0
        lea     -34(a5),a0
        move.l  #0,d1
        move.w  (a0,d0.l),d1
        move.l  #16,d0
        sub.l   -112(a5),d0
        asl.l   d0,d1
        move.l  -112(a5),d0
        add.l   d0,d0
        lea     -104(a5),a0
        move.l  d1,-(sp)
        move.l  #0,d1
        move.w  (a0,d0.l),d1
        move.l  (sp)+,d0
        add.l   d1,d0
        move.l  -112(a5),d1
        add.l   d1,d1
        lea     -102(a5),a0
        move.w  d0,(a0,d1.l)
.10008
        add.l   #1,-112(a5)
        cmp.l   #16,-112(a5)
        bls     .10010
.10009
;        if (start[17] != (ushort)((unsigned) 1 << 16))
;                message( "Bad decode table\n","");
        tst.w   -70(a5)
        beq     .10011
        pea     .1+18
        pea     .1+0
        jsr     _message
;
;        jutbits = 16 - tablebits;
        add.w   #8,sp
.10011
        move.l  #16,d0
        sub.l   16(a5),d0
        move.l  d0,-124(a5)
;        for (i = 1; i <= tablebits; i++) {
        move.l  #1,-112(a5)
        bra     .10015
.10014
;                start[i] >>= jutbits;
        move.l  -112(a5),d0
        add.l   d0,d0
        lea     -104(a5),a0
        move.l  d0,a1
        add.l   a0,a1
        move.l  #0,d0
        move.w  (a1),d0
        move.l  -124(a5),d1
        asr.l   d1,d0
        move.w  d0,(a1)
;                weight[i] = (unsigned) 1 << (tablebits - i);
        move.l  16(a5),d0
        sub.l   -112(a5),d0
        move.l  #1,d1
        asl.l   d0,d1
        move.l  -112(a5),d0
        add.l   d0,d0
        lea     -68(a5),a0
        move.w  d1,(a0,d0.l)
;        }
.10012
        add.l   #1,-112(a5)
.10015
        move.l  -112(a5),d0
        cmp.l   16(a5),d0
        bls     .10014
.10013
;        while (i <= 16) {
.10016
        cmp.l   #16,-112(a5)
        bhi     .10017
;           weight[i] = (unsigned) 1 << (16 - i);
        move.l  #16,d0
        sub.l   -112(a5),d0
        move.l  #1,d1
        asl.l   d0,d1
        move.l  -112(a5),d0
        add.l   d0,d0
        lea     -68(a5),a0
        move.w  d1,(a0,d0.l)
;           i++;
        add.l   #1,-112(a5)
;        }
        bra     .10016
.10017
;
;        i = start[tablebits + 1] >> jutbits;
        move.l  16(a5),d0
        add.l   d0,d0
        lea     -102(a5),a0
        move.l  #0,d1
        move.w  (a0,d0.l),d1
        move.l  -124(a5),d0
        asr.l   d0,d1
        move.l  d1,-112(a5)
;        if (i != (ushort)((unsigned) 1 << 16)) {
        tst.l   -112(a5)
        beq     .10018
;                k = 1 << tablebits;
        move.l  #1,d0
        move.l  16(a5),d1
        asl.l   d1,d0
        move.l  d0,-116(a5)
;                while (i != k) table[i++] = 0;
.10019
        move.l  -112(a5),d0
        cmp.l   -116(a5),d0
        beq     .10020
        move.l  -112(a5),d0
        add.l   #1,-112(a5)
        add.l   d0,d0
        move.l  20(a5),a0
        clr.w   (a0,d0.l)
        bra     .10019
.10020
;        }
;
;        avail = nchar;
.10018
        move.l  8(a5),-128(a5)
;        mask = (unsigned) 1 << (15 - tablebits);
        move.l  #15,d0
        sub.l   16(a5),d0
        move.l  #1,d1
        asl.l   d0,d1
        move.l  d1,-136(a5)
;        for (ch = 0; ch < nchar; ch++) {
        move.l  #0,d2
        bra     .10024
.10023
;                if ((len = bitlen[ch]) == 0) continue;
        move.l  12(a5),a0
        move.l  #0,d0
        move.b  (a0,d2.l),d0
        move.l  d0,-120(a5)
        beq     .10021
;                nextcode = start[len] + weight[len];
        move.l  -120(a5),d0
        add.l   d0,d0
        lea     -104(a5),a0
        move.l  #0,d1
        move.w  (a0,d0.l),d1
        move.l  -120(a5),d0
        add.l   d0,d0
        lea     -68(a5),a0
        move.l  d1,-(sp)
        move.l  #0,d1
        move.w  (a0,d0.l),d1
        move.l  (sp)+,d0
        add.l   d1,d0
        move.l  d0,-132(a5)
;                if (len <= tablebits) {
        move.l  -120(a5),d0
        cmp.l   16(a5),d0
        bhi     .10025
;                        nxtcptr = table + start[len];
        move.l  -120(a5),d0
        add.l   d0,d0
        lea     -104(a5),a0
        move.l  #0,d1
        move.w  (a0,d0.l),d1
        add.l   d1,d1
        move.l  d1,a2
        add.l   20(a5),a2
;                        endcptr = table + nextcode;
        move.l  -132(a5),d0
        add.l   d0,d0
        move.l  d0,a3
        add.l   20(a5),a3
;                        for ( ; nxtcptr < endcptr;) *nxtcptr++ = ch;
        bra     .10029
.10028
        move.w  d2,(a2)+
.10026
.10029
        cmp.l   a3,a2
        bcs     .10028
.10027
;                } else {
        bra     .10030
.10025
;                        k = start[len];
        move.l  -120(a5),d0
        add.l   d0,d0
        lea     -104(a5),a0
        move.l  #0,d1
        move.w  (a0,d0.l),d1
        move.l  d1,-116(a5)
;                        p = &table[k >> jutbits];
        move.l  -116(a5),d0
        move.l  -124(a5),d1
        lsr.l   d1,d0
        add.l   d0,d0
        add.l   20(a5),d0
        move.l  d0,-108(a5)
;                        i = len - tablebits;
        move.l  -120(a5),d0
        sub.l   16(a5),d0
        move.l  d0,-112(a5)
;                        while (i != 0) {
.10031
        tst.l   -112(a5)
        beq     .10032
;                                if (*p == 0) {
        move.l  -108(a5),a0
        tst.w   (a0)
        bne     .10033
;                                        right[avail] = left[avail] = 0;
        move.l  -128(a5),d0
        add.l   d0,d0
        lea     _left,a0
        clr.w   (a0,d0.l)
        move.l  -128(a5),d0
        add.l   d0,d0
        lea     _right,a0
        clr.w   (a0,d0.l)
;                                        *p = avail++;
        move.l  -128(a5),d0
        add.l   #1,-128(a5)
        move.l  -108(a5),a0
        move.w  d0,(a0)
;                                }
;                                if (k & mask) p = &right[*p];
.10033
        move.l  -116(a5),d0
        and.l   -136(a5),d0
        beq     .10034
        move.l  -108(a5),a0
        move.l  #0,d0
        move.w  (a0),d0
        add.l   d0,d0
        lea     _right,a0
        add.l   a0,d0
        move.l  d0,-108(a5)
;                                else          p = &left[*p];
        bra     .10035
.10034
        move.l  -108(a5),a0
        move.l  #0,d0
        move.w  (a0),d0
        add.l   d0,d0
        lea     _left,a0
        add.l   a0,d0
        move.l  d0,-108(a5)
.10035
;                                k <<= 1;  i--;
        move.l  -116(a5),d0
        add.l   d0,d0
        move.l  d0,-116(a5)
        sub.l   #1,-112(a5)
;                        }
        bra     .10031
.10032
;                        *p = ch;
        move.l  -108(a5),a0
        move.w  d2,(a0)
;                }
.10030
;                start[len] = nextcode;
        move.l  -120(a5),d0
        add.l   d0,d0
        lea     -104(a5),a0
        move.w  -130(a5),(a0,d0.l)
;        }
.10021
        add.l   #1,d2
.10024
        cmp.l   8(a5),d2
        bcs     .10023
.10022
;}
.4
        movem.l (sp)+,.3
        unlk    a5
        rts
.2      equ     -136
.3      reg     d2/d3/d4/a2/a3
.1
        dc.b    66,97,100,32,100,101,99,111,100,101,32,116,97,98,108
        dc.b    101,10,0,0
        ds      0
;
        xref    _message
        xref    .begin
        dseg
        xref    _right
        xref    _left
        end
