; ; 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 ;/* decodes up to 'count' chars (but no more than WinSiz) into supplied ;buffer; returns actual count. */ ; ;#include "lh5.h" ;#define NP (DICBIT + 1) ;#define NT (CODE_BIT + 3) ;extern BufRead(), read_pt_len(), read_c_len(); ;extern long BCount, HWinSiz, WinSiz; ;extern ulong bitbuf; ;extern int bitcount, decoded; ;extern uint jb, blocksize; ;extern ushort left[], right[], c_table[], pt_table[], LZBuf[]; ;extern uchar c_len[], pt_len[]; ; ;long decodeit( count, buffer) ;uint count; ;uchar buffer[]; ;{ xdef _decodeit _decodeit: link a5,#.2 movem.l .3,-(sp) ; static uchar *savepi; bss .10001,4 ; register uint i; ; register ulong bitbfr = bitbuf; ; register int ct = bitcount, n; ; uint mask; ; uchar *bstrt = &buffer[0], *bend = &buffer[count]; ; uchar *bguard = &buffer[WinSiz - 258], *blst = &buffer[WinSiz - 1]; ; register uchar *bufpi = savepi, *bufpr = bstrt; ; register uchar *bufend = bstrt + jb; ; register uint blksz = blocksize; ; register ushort *inbf = &LZBuf[ BCount ]; ; ushort *winend = &LZBuf[ HWinSiz ]; ; ; while (bufpr < bufend) { move.l _bitbuf,d3 move.l _bitcount,d4 move.l 12(a5),-8(a5) move.l 8(a5),d0 add.l 12(a5),d0 move.l d0,-12(a5) move.l 12(a5),-16(a5) move.l -16(a5),a0 add.l _WinSiz,a0 move.l a0,-16(a5) sub.l #258,-16(a5) move.l 12(a5),-20(a5) move.l -20(a5),a0 add.l _WinSiz,a0 move.l a0,-20(a5) sub.l #1,-20(a5) move.l .10001,a2 move.l -8(a5),a3 move.l _jb,d6 add.l -8(a5),d6 move.l _blocksize,d7 move.l _BCount,d0 add.l d0,d0 lea.l _LZBuf,a1 add.l d0,a1 move.l _HWinSiz,d0 add.l d0,d0 lea.l _LZBuf,a0 add.l a0,d0 move.l d0,-28(a5) ; Clear upper half of d2 and it should not be modified move.l #0,d2 move.l #0,d5 .10002 cmp.l d6,a3 bcc .10003 ; *bufpr++ = *bufpi++; move.b (a2)+,(a3)+ ; if( bufpi > blst ) bufpi = bstrt; cmp.l -20(a5),a2 bls .10004 move.l -8(a5),a2 ; if (bufpr == bend) goto savret; .10004 cmp.l -12(a5),a3 beq .10005 ; } bra .10002 .10003 ; for ( ; ; ) { .10006 ; /* decode character */ ; if (--blksz == 0) { sub.l #1,d7 bne .10008 ; bitbuf = bitbfr; bitcount = ct; BCount = (inbf - &LZBuf[0]); move.l d3,_bitbuf move.l d4,_bitcount sub.l #_LZBuf,a1 move.l a1,d0 lsr.l #1,d0 move.l d0,_BCount ; blksz = getbits(16); pea 16 jsr _getbits move.l d0,d7 ; if (blksz == 0) { tst.l d7 add.w #4,sp bne .10009 ; blocksize = blksz; savepi = bufpi; jb = bufend - bufpr; return 0; move.l d7,_blocksize move.l a2,.10001 move.l d6,d0 sub.l a3,d0 move.l d0,_jb move.l #0,d0 .4 movem.l (sp)+,.3 unlk a5 rts ; } ; read_pt_len(NT, 5, 3); /* 5=smallest int so that 1<<5 > NT */ .10009 pea 3 pea 5 pea 19 jsr _read_pt_len ; read_c_len(); jsr _read_c_len ; read_pt_len(NP, 4, -1); /* 4=smallest int so that 1<<4 > NP */ pea -1 pea 4 pea 14 jsr _read_pt_len ; bitbfr = bitbuf; ct = bitcount; inbf = &LZBuf[ BCount ]; move.l _bitbuf,d3 move.l _bitcount,d4 move.l _BCount,a1 add.l a1,a1 add.l #_LZBuf,a1 ; } ; i = c_table[bitbfr >> (BITBUFSIZ - 12)]; lea 24(sp),sp .10008 move.l d3,d0 move.l #20,d1 lsr.l d1,d0 add.l d0,d0 lea _c_table,a0 move.w (a0,d0.w),d2 ; if (i >= NC) { cmp.l #510,d2 bcs .10010 ; mask = (unsigned) 1 << (BITBUFSIZ - 1 - 12); move.l #524288,-4(a5) ; do { .10013 ; if (bitbfr & mask) i = right[i]; move.l d3,d0 and.l -4(a5),d0 beq .10014 move.l d2,d0 add.l d0,d0 lea _right,a0 move.l #0,d1 move.w (a0,d0.l),d1 move.l d1,d2 ; else i = left [i]; bra .10015 .10014 move.l d2,d0 add.l d0,d0 lea _left,a0 move.l #0,d1 move.w (a0,d0.l),d1 move.l d1,d2 .10015 ; mask >>= 1; move.l -4(a5),d0 lsr.l #1,d0 move.l d0,-4(a5) ; } while (i >= NC); .10011 cmp.l #510,d2 bcc .10013 .10012 ; } ; n = c_len[i]; .10010 lea _c_len,a0 move.b (a0,d2.w),d5 ; bitbfr <<= n; asl.l d5,d3 ; ct += n; add.l d5,d4 ; if ( ct >= 16) { cmp.l #16,d4 blt .10016 ; ct -= 16; sub.l #16,d4 ; if( inbf == winend ) { BufRead(); inbf = &LZBuf[0]; } cmp.l -28(a5),a1 bne .10017 jsr _BufRead lea.l _LZBuf,a1 ; bitbfr = ( *inbf++ | ((bitbfr >> ct) & 0xffff0000)) << ct; .10017 lsr.l d4,d3 move.w (a1)+,d3 asl.l d4,d3 ; } ; if (i <= UCHAR_MAX) { *bufpr++ = i; if( bufpr == bend) goto savret; } .10016 cmp.l #255,d2 bhi .10018 move.b d2,(a3)+ cmp.l -12(a5),a3 bne .10006 ; else { bra .10005 .10018 ; bufend = bufpr + i - (UCHAR_MAX + 1 - THRESHOLD); move.l d2,d6 add.l a3,d6 add.l #-253,d6 ; /* decode position */ ; i = pt_table[bitbfr >> (BITBUFSIZ - 8)]; move.l d3,d0 move.l #24,d1 lsr.l d1,d0 add.l d0,d0 lea _pt_table,a0 move.w (a0,d0.w),d2 ; if (i >= NP) { cmp.l #14,d2 bcs .10020 ; mask = (unsigned) 1 << (BITBUFSIZ - 1 - 8); move.l #8388608,-4(a5) ; do { .10023 ; if (bitbfr & mask) i = right[i]; move.l d3,d0 and.l -4(a5),d0 beq .10024 move.l d2,d0 add.l d0,d0 lea _right,a0 move.l #0,d1 move.w (a0,d0.l),d1 move.l d1,d2 ; else i = left [i]; bra .10025 .10024 move.l d2,d0 add.l d0,d0 lea _left,a0 move.l #0,d1 move.w (a0,d0.l),d1 move.l d1,d2 .10025 ; mask >>= 1; move.l -4(a5),d0 lsr.l #1,d0 move.l d0,-4(a5) ; } while (i >= NP); .10021 cmp.l #14,d2 bcc .10023 .10022 ; } ; n = pt_len[i]; .10020 lea _pt_len,a0 move.b (a0,d2.w),d5 ; bitbfr <<= n; asl.l d5,d3 ; ct += n; add.l d5,d4 ; if ( ct >= 16) { cmp.l #16,d4 blt .10026 ; ct -= 16; sub.l #16,d4 ; if( inbf == winend ) { BufRead(); inbf = &LZBuf[0]; } cmp.l -28(a5),a1 bne .10027 jsr _BufRead lea.l _LZBuf,a1 ; bitbfr = ( *inbf++ | ((bitbfr >> ct) & 0xffff0000)) << ct; .10027 lsr.l d4,d3 move.w (a1)+,d3 asl.l d4,d3 ; } ; if (i != 0) { .10026 tst.l d2 beq .10028 ; n = i - 1; move.l d2,d5 sub.l #1,d5 ; i = ((unsigned) 1 << n) + (bitbfr >> (BITBUFSIZ - n)); ; bitbfr <<= n; move.l d3,d2 rol.l d5,d2 lsl.l d5,d3 eor.l d3,d2 bset.l d5,d2 ; ct += n; add.l d5,d4 ; if ( ct >= 16) { cmp.l #16,d4 blt .10029 ; ct -= 16; sub.l #16,d4 ; if( inbf == winend ) { BufRead(); inbf = &LZBuf[0]; } cmp.l -28(a5),a1 bne .10030 jsr _BufRead lea.l _LZBuf,a1 ; bitbfr = ( *inbf++ | ((bitbfr >> ct) & 0xffff0000))<= bstrt ) { cmp.l -8(a5),a2 bcs .10031 ; if( bufend < bend ) { cmp.l -12(a5),d6 bcc .10032 ; *bufpr++ = *bufpi++; move.b (a2)+,(a3)+ ; *bufpr++ = *bufpi++; move.b (a2)+,(a3)+ ; do *bufpr++ = *bufpi++; while (bufpr < bufend); .10035 move.b (a2)+,(a3)+ cmp.l d6,a3 bcs .10035 ; } ; else { while( bufpr < bend ) *bufpr++ = *bufpi++; goto savret; } bra .10006 .10032 cmp.l -12(a5),a3 bcc .10005 move.b (a2)+,(a3)+ bra .10032 ; } ; else { .10031 ; bufpi += WinSiz; add.l _WinSiz,a2 ; if( bufpi < bguard ) { cmp.l -16(a5),a2 bcc .10040 ; if( bufend < bend ) { cmp.l -12(a5),d6 bcc .10041 ; *bufpr++ = *bufpi++; move.b (a2)+,(a3)+ ; *bufpr++ = *bufpi++; move.b (a2)+,(a3)+ ; do *bufpr++ = *bufpi++; while (bufpr < bufend); .10044 move.b (a2)+,(a3)+ cmp.l d6,a3 bcs .10044 ; } ; else { while( bufpr < bend ) *bufpr++ = *bufpi++; goto savret; } bra .10006 .10041 cmp.l -12(a5),a3 bcc .10005 move.b (a2)+,(a3)+ bra .10041 ; } ; else { .10040 ; while (bufpr < bufend) { .10049 cmp.l d6,a3 bcc .10006 ; *bufpr++ = *bufpi++; move.b (a2)+,(a3)+ ; if( bufpi > blst ) bufpi = bstrt; cmp.l -20(a5),a2 bls .10051 move.l -8(a5),a2 ; if (bufpr == bend) goto savret; .10051 cmp.l -12(a5),a3 beq .10005 ; } bra .10049 ; } ; } ; } ; } ; savret: bitbuf = bitbfr; bitcount = ct; jb = bufend - bufpr; .10005 move.l d3,_bitbuf move.l d4,_bitcount move.l d6,d0 sub.l a3,d0 move.l d0,_jb ; BCount = (inbf - &LZBuf[0]); sub.l #_LZBuf,a1 move.l a1,d0 asr.l #1,d0 move.l d0,_BCount ; savepi = bufpi; blocksize = blksz; move.l a2,.10001 move.l d7,_blocksize ; return (long)(bufpr - bstrt); move.l a3,d0 sub.l -8(a5),d0 bra .4 ;} .2 equ -28 .3 reg d2/d3/d4/d5/d6/d7/a2/a3 ; xref _read_c_len xref _read_pt_len xref _BufRead xref _getbits xref .begin dseg xref _pt_len xref _c_len xref _LZBuf xref _pt_table xref _c_table xref _blocksize xref _jb xref _bitcount xref _HWinSiz xref _WinSiz xref _BCount xref _right xref _left xref _bitbuf end