* xpkBLZW - XPK interface to LZW compressor/decompressor
* Copyright (C) 1992 Bryan Ford
*
* This file is part of BLZW, Bryan's LZW compressor.
*
* BLZW is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* BLZW is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

	INCLUDE	AINCLUDE:IncDirs.i *sets all includedirs, needed for my ASM
	INCLUDE	xpkLibBLZW.i
	include	"xpk/xpk.i"
	include	"xpk/xpksub.i"

SOURCEBITS      equ     8               ; Number of bits per byte (duhh)
STARTBITS       equ     SOURCEBITS+1    ; Starting compression bits
MINBITS         equ     STARTBITS       ; Minimum number of compression bits
MAXBITS         equ     15              ; Max compression bits
BYTESPERTABENT	EQU	4       	; Bytes required per table entry

	INCLUDE	gencomp.a
	INCLUDE	gendecomp.a

                rsreset
xsp_blah        rs.b    xsp_Sub
xsp_CompTab     rs.l    1
xsp_CompTabSize rs.l    1

*** packerinfo - Return pointer to packer info structure
_XpksPackerInfo:
        lea     (1$,pc),a0
        move.l  a0,d0
        rts

1$      dc.w    1                       ; XpkInfo version
        dc.w    VERSION
        dc.w    0
        dc.w    1                       ; XpkMode version
        dc.l    shortname
        dc.l    longname
        dc.l    descr
        dc.b    'BLZW'
        dc.l    XPKIF_PK_CHUNK!XPKIF_UP_CHUNK!XPKIF_MODES
        dc.l    $7fffffff               ; Max chunk size
        dc.l    $80                     ; Min chunk size
        dc.l    $20000                  ; Default chunk size (128K)
        dc.l    packname
        dc.l    unpackname
        dc.l    packedname
        dc.l    unpackedname
        dc.w    60                      ; Default mode
        dc.w    0
        dc.l    9$                      ; First mode
        ds.l    6

9$      dc.l    10$                     ; Next mode
        dc.l    14
        dc.l    XPKMF_A3000SPEED
        dc.l    3846
        dc.l    2048
        dc.l    159;013
        dc.l    303;424
        dc.w    244
        dc.w    0
        dc.b    "9 bits",0,0

10$     dc.l    11$
        dc.l    28
        dc.l    XPKMF_A3000SPEED
        dc.l    7698
        dc.l    4096
        dc.l    141;598
        dc.l    328;570
        dc.w    294
        dc.w    0
        dc.b    "10 bits",0

11$     dc.l    12$
        dc.l    42
        dc.l    XPKMF_A3000SPEED
        dc.l    15474
        dc.l    8192
        dc.l    135;469
        dc.l    343;764
        dc.w    317
        dc.w    0
        dc.b    "11 bits",0

12$     dc.l    13$
        dc.l    57
        dc.l    XPKMF_A3000SPEED
        dc.l    30882
        dc.l    16384
        dc.l    134;550
        dc.l    356;114
        dc.w    324
        dc.w    0
        dc.b    "12 bits",0

13$     dc.l    14$
        dc.l    71
        dc.l    XPKMF_A3000SPEED
        dc.l    61458
        dc.l    32768
        dc.l    139;276
        dc.l    364;853
        dc.w    329
        dc.w    0
        dc.b    "13 bits",0

14$     dc.l    15$
        dc.l    85
        dc.l    XPKMF_A3000SPEED
        dc.l    122898
        dc.l    65536
        dc.l    143;998
        dc.l    374;032
        dc.w    331
        dc.w    0
        dc.b    "14 bits",0

15$     dc.l    0
        dc.l    100
        dc.l    XPKMF_A3000SPEED
        dc.l    245766
        dc.l    131072
        dc.l    157;748
        dc.l    381;225
        dc.w    337
        dc.w    0
        dc.b    "15 bits",0

*** freebuf - Free the compression table if it's been allocated
* a0 = xbuf
_XpksPackFree
_XpksUnpackFree
        move.l  (xsp_CompTab,a0),d0
        beq.s   9$
        clr.l   (xsp_CompTab,a0)
        move.l  a6,-(sp)
        move.l  4,a6
        move.l  d0,a1
        move.l  (xsp_CompTabSize,a0),d0
        jsr     (_LVOFreeMem,a6)
        move.l  (sp)+,a6
        moveq   #0,d0
9$      rts

*** getcomptable - Allocate a compression table (if not allocated already or not big enough)
* a3 = xbuf
* d0 = table size needed
* Returns: Z if not enough memory
* a2 = table
getcomptab:
        move.l  (xsp_CompTab,a3),d1
        beq.s   1$
        cmp.l   (xsp_CompTabSize,a3),d0
        bls.s   9$
        move.l  d0,-(sp)
        move.l  a3,a0
	BSR.B	_XpksUnpackFree
        move.l  (sp)+,d0
1$      move.l  d0,(xsp_CompTabSize,a3)
        moveq   #0,d1
        move.l  a6,-(sp)
        move.l  4,a6
        jsr     (_LVOAllocMem,a6)
        move.l  (sp)+,a6
        move.l  d0,(xsp_CompTab,a3)
        move.l  d0,a2
        rts
9$      move.l  d1,a2
        moveq   #1,d0
        rts

*** packchunk
* a0 = xbuf
* a1 = lochdr
_XpksPackChunk:
        movem.l d2/a2-a3,-(sp)
        move.l  a0,a3

        move.l  (xsp_Mode,a3),d2        ; Find the compression mode

        mulu.w  #7,d2
        divu.w  #100,d2
        add.w   #9,d2
        ext.l   d2

        moveq   #9,d0
        cmp.l   d0,d2
        bhs.b   .oklow
        move.l  d0,d2
.oklow
        moveq   #15,d0
        cmp.l   d0,d2
        bls.b   .okhigh
        move.l  d0,d2
.okhigh

        move.l  d2,d0                   ; Find a compression table
        bsr     GenCompTableSize
        bsr     getcomptab
        BEQ.B    .nomem

        move.l  (xsp_InBuf,a3),a0       ; Compress the data
        move.l  (xsp_OutBuf,a3),a1
        move.l  (xsp_InLen,a3),d0
        move.l  d2,d1
        bsr     GenCompress
        move.l  d0,(xsp_OutLen,a3)
        BEQ.B    .nocomp

        moveq   #0,d0
9$      movem.l (sp)+,d2/a2-a3
        rts

.nomem:
        moveq   #XPKERR_NOMEM,d0
        bra.b   9$

.nocomp:
        moveq   #XPKERR_EXPANSION,d0
        bra.b   9$

*** unpackchunk
* a0 = xbuf
_XpksUnpackChunk:
        movem.l a2-a3,-(sp)
        move.l  a0,a3

        move.l  (xsp_InBuf,a3),a0       ; Find required table size
        bsr     GenDecompTableSize
        bsr     getcomptab
        BEQ.B    .nomem

        move.l  (xsp_InBuf,a3),a0       ; Decompress the data
        move.l  (xsp_OutBuf,a3),a1
        bsr     GenDecompress
        sub.l   (xsp_OutBuf,a3),a1
        cmp.l   (xsp_OutLen,a3),a1
        bne.b   .corr

        moveq   #0,d0
9$      movem.l (sp)+,a2-a3
        rts

.nomem:
        moveq   #XPKERR_NOMEM,d0
        bra.b   9$

.corr:
        moveq   #XPKERR_CORRUPTPKD,d0
        bra.b   9$

shortname       dc.b    "BLZW",0
longname        dc.b    "Bryan's turbo-charged LZW",0
descr           dc.b    "Fast compression and decompression, ratio much like 'compress' or 'zoo'",0
packname        dc.b    "Compressing",0
unpackname      dc.b    "Decompressing",0
packedname      dc.b    "Compressed",0
unpackedname    dc.b    "Decompressed",0
        end
