You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
447 lines
9.9 KiB
447 lines
9.9 KiB
/* File: C:\WACKER\xfer\cmprs2.c (Created: 20-Jan-1994)
|
|
* created from HAWIN source file
|
|
* cmprs2.c -- Routines to implement data decompression
|
|
*
|
|
* Copyright 1989,1994 by Hilgraeve Inc. -- Monroe, MI
|
|
* All rights reserved
|
|
*
|
|
* $Revision: 1 $
|
|
* $Date: 10/05/98 1:16p $
|
|
*/
|
|
#include <windows.h>
|
|
|
|
#include <tdll\stdtyp.h>
|
|
|
|
#if !defined(BYTE)
|
|
#define BYTE unsigned char
|
|
#endif
|
|
|
|
#include "cmprs.h"
|
|
#include "cmprs.hh"
|
|
|
|
#if SHOW
|
|
// #include <stdio.h>
|
|
#endif
|
|
|
|
/* * * * * * * * * * * * * *
|
|
* Decompression routines *
|
|
* * * * * * * * * * * * * */
|
|
|
|
typedef struct s_dcmp_node DCMP_NODE;
|
|
struct s_dcmp_node
|
|
{
|
|
DCMP_NODE *pstLinkBack;
|
|
DCMP_NODE *pstLinkFwd;
|
|
BYTE ucChar;
|
|
};
|
|
|
|
#define NODE_CAST DCMP_NODE *
|
|
|
|
DCMP_NODE *pstDcmpTbl; // pointer to lookup table
|
|
DCMP_NODE *pstCode = NULL; // used to scan table for output
|
|
|
|
int (**ppfDcmpPutfunc)(void *, int); /* ptr. to ptr. to function used
|
|
by calling func */
|
|
int (*pfDcmpPutChar)(void *, int); /* ptr. to function used
|
|
internally to get data */
|
|
|
|
void *pPsave;
|
|
|
|
DCMP_NODE *pstTblLimit = NULL; /* pointer to table beyond 1st 256 nodes */
|
|
DCMP_NODE *pstExtraNode = NULL; /* pointer to additional node used in spec. case */
|
|
int fDcmpError; /* set TRUE if illegal code is received */
|
|
int fStartFresh = FALSE;
|
|
unsigned int usCodeMask; /* mask to isolate varible sized codes */
|
|
unsigned int usOldCode; /* last code received */
|
|
int mcFirstChar; /* final character of pattern readout, actually,
|
|
the FIRST character of pattern (characters
|
|
are read out in reverse order */
|
|
|
|
// #pragma optimize("lgea",on)
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION: decompress_start
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
*
|
|
* ARGUMENTS:
|
|
*
|
|
*
|
|
* RETURNS:
|
|
*
|
|
*/
|
|
int decompress_start(int (**put_func)(void *, int),
|
|
void *pP,
|
|
int fPauses)
|
|
{
|
|
unsigned int usCount;
|
|
DCMP_NODE *pstTmp;
|
|
|
|
if (!compress_enable())
|
|
return(FALSE);
|
|
|
|
pPsave = pP;
|
|
|
|
fFlushable = fPauses;
|
|
|
|
// Due to the use of based pointers, we must use compress_tblspace + 1
|
|
// in the following code. Otherwise, node 0 (which could have an offset
|
|
// of 0 looks like a NULL pointer.
|
|
// pstDcmpTbl = (DCMP_NODE *)(OFFSETOF(compress_tblspace) + 1);
|
|
pstDcmpTbl = (DCMP_NODE *)(compress_tblspace);
|
|
|
|
pstCode = NULL;
|
|
pstExtraNode = (NODE_CAST)&pstDcmpTbl[MAXNODES]; /* last node */
|
|
pstExtraNode->pstLinkFwd = NULL;
|
|
pstTblLimit = (NODE_CAST)&pstDcmpTbl[256];
|
|
for (usCount = 0, pstTmp = pstDcmpTbl; usCount < 256; ++usCount)
|
|
{
|
|
pstTmp->ucChar = (BYTE)usCount;
|
|
++pstTmp;
|
|
}
|
|
|
|
ulHoldReg = 0;
|
|
sBitsLeft = 0;
|
|
sCodeBits = 9;
|
|
usMaxCode = 512;
|
|
usCodeMask = (1 << sCodeBits) - 1;
|
|
usFreeCode = FIRSTFREE;
|
|
fDcmpError = FALSE;
|
|
fStartFresh = FALSE;
|
|
ppfDcmpPutfunc = put_func;
|
|
pfDcmpPutChar = *ppfDcmpPutfunc;
|
|
*ppfDcmpPutfunc = dcmp_putc;
|
|
usxCmprsStatus = COMPRESS_ACTIVE;
|
|
#if SHOW
|
|
printf("D decompress_start, sCodeBits=%d\n",
|
|
sCodeBits);
|
|
#endif
|
|
return(TRUE);
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION: decompress_error
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
*
|
|
* ARGUMENTS:
|
|
*
|
|
*
|
|
* RETURNS:
|
|
*
|
|
*/
|
|
int decompress_error(void)
|
|
{
|
|
return(fDcmpError);
|
|
}
|
|
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION: dcmp_start
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
*
|
|
* ARGUMENTS:
|
|
*
|
|
*
|
|
* RETURNS:
|
|
*
|
|
*/
|
|
int dcmp_start(void *pX, int mcStartChar)
|
|
{
|
|
unsigned int usCode;
|
|
|
|
ulHoldReg |= ((unsigned long)mcStartChar << sBitsLeft);
|
|
sBitsLeft += 8;
|
|
#if SHOW
|
|
printf("D %02X %08lX,%2d dcmp_start\n", mcStartChar,
|
|
ulHoldReg, sBitsLeft);
|
|
#endif
|
|
if (sBitsLeft >= sCodeBits)
|
|
{
|
|
usCode = (unsigned int)ulHoldReg & usCodeMask;
|
|
ulHoldReg >>= sCodeBits;
|
|
sBitsLeft -= sCodeBits;
|
|
#if SHOW
|
|
printf("D >> %03X %08lX,%2d sCodeBits=%d dcmp_start\n",
|
|
usCode, ulHoldReg, sBitsLeft, sCodeBits);
|
|
#endif
|
|
/* Table has just been cleared, code must be in range of 0 - 255 */
|
|
if (!IN_RANGE((INT)usCode, 0, 255))
|
|
{
|
|
#if SHOW
|
|
printf("D >> %03X ERROR: out of range\n",
|
|
usCode);
|
|
#endif
|
|
return(dcmp_abort());
|
|
}
|
|
else
|
|
{
|
|
#if SHOW
|
|
printf("D %02X dcmp_start\n", usCode);
|
|
#endif
|
|
mcStartChar = (*pfDcmpPutChar)(pPsave, mcFirstChar =
|
|
(INT)(usOldCode = usCode));
|
|
*ppfDcmpPutfunc = dcmp_putc;
|
|
}
|
|
}
|
|
return(mcStartChar);
|
|
}
|
|
|
|
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION: dcmp_putc
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
*
|
|
* ARGUMENTS:
|
|
*
|
|
*
|
|
* RETURNS:
|
|
*
|
|
*/
|
|
int dcmp_putc(void *pX, int mcInput)
|
|
{
|
|
unsigned int usCode;
|
|
unsigned int usInCode;
|
|
int mcPutResult;
|
|
DCMP_NODE *pstTmp;
|
|
|
|
ulHoldReg |= ((unsigned long)mcInput << sBitsLeft);
|
|
sBitsLeft += 8;
|
|
#if SHOW
|
|
printf("D %02X %08lX,%2d\n", mcInput, ulHoldReg, sBitsLeft);
|
|
#endif
|
|
if (sBitsLeft >= sCodeBits)
|
|
{
|
|
usCode = (unsigned int)ulHoldReg & usCodeMask;
|
|
ulHoldReg >>= sCodeBits;
|
|
sBitsLeft -= sCodeBits;
|
|
#if SHOW
|
|
printf("D >> %03X %08lX,%2d sCodeBits=%d\n",
|
|
usCode, ulHoldReg, sBitsLeft, sCodeBits);
|
|
#endif
|
|
if (usCode == STOPCODE)
|
|
{
|
|
if (!fFlushable)
|
|
decompress_stop();
|
|
else
|
|
{
|
|
// Pause in the data, leave lookup table intact but start
|
|
// receiving a fresh stream.
|
|
sBitsLeft = 0;
|
|
ulHoldReg = 0L;
|
|
fStartFresh = TRUE;
|
|
#if SHOW
|
|
printf("D %08lX,%2d setting fFreshStart\n",
|
|
ulHoldReg, sBitsLeft);
|
|
#endif
|
|
}
|
|
}
|
|
else if (usCode == CLEARCODE)
|
|
{
|
|
sCodeBits = 9;
|
|
usMaxCode = 512;
|
|
usCodeMask = (1 << sCodeBits) - 1;
|
|
usFreeCode = FIRSTFREE;
|
|
*ppfDcmpPutfunc = dcmp_start;
|
|
#if SHOW
|
|
printf("D CLEARCODE, sCodeBits=%d\n",
|
|
sCodeBits);
|
|
#endif
|
|
}
|
|
else if (usCode > (unsigned int)usFreeCode)
|
|
{
|
|
#if SHOW
|
|
printf("D ERROR: usCode > usFreeCode of %03X\n",
|
|
usFreeCode);
|
|
#endif
|
|
return(dcmp_abort());
|
|
}
|
|
else
|
|
{
|
|
pstCode = (NODE_CAST)&pstDcmpTbl[usInCode = usCode];
|
|
if (usCode == usFreeCode) /* spec. case k<w>k<w>k */
|
|
{
|
|
pstCode = (NODE_CAST)&pstDcmpTbl[usCode = usOldCode];
|
|
pstExtraNode->ucChar = (BYTE)mcFirstChar;
|
|
pstCode->pstLinkFwd = pstExtraNode;
|
|
#if SHOW
|
|
printf("D Special case: k<w>k<w>k\n");
|
|
#endif
|
|
}
|
|
else
|
|
pstCode->pstLinkFwd = NULL;
|
|
while(pstCode > pstTblLimit)
|
|
{
|
|
pstCode->pstLinkBack->pstLinkFwd = pstCode;
|
|
pstCode = pstCode->pstLinkBack;
|
|
}
|
|
mcFirstChar = pstCode->ucChar;
|
|
|
|
if (!fStartFresh)
|
|
{
|
|
#if SHOW
|
|
printf("D D Added %03X = %03X + %02X\n",
|
|
usFreeCode, usOldCode, mcFirstChar);
|
|
#endif
|
|
if (usFreeCode < MAXNODES)
|
|
{
|
|
pstTmp = (NODE_CAST)&pstDcmpTbl[usFreeCode++];
|
|
pstTmp->ucChar = (BYTE)mcFirstChar;
|
|
pstTmp->pstLinkBack = (NODE_CAST)&pstDcmpTbl[usOldCode];
|
|
}
|
|
}
|
|
fStartFresh = FALSE;
|
|
|
|
usOldCode = usInCode;
|
|
if (usFreeCode >= usMaxCode && sCodeBits < MAXCODEBITS)
|
|
{
|
|
++sCodeBits;
|
|
usCodeMask = (1 << sCodeBits) - 1;
|
|
usMaxCode *= 2;
|
|
#if SHOW
|
|
printf("D D New sCodeBits = %d\n",
|
|
sCodeBits);
|
|
#endif
|
|
}
|
|
|
|
while (pstCode != NULL)
|
|
{
|
|
#if SHOW
|
|
printf("D %02X ", pstCode->ucChar);
|
|
#endif
|
|
if ((mcPutResult = (*pfDcmpPutChar)(pPsave, pstCode->ucChar)) < 0)
|
|
{
|
|
if (mcPutResult == DCMP_UNFINISHED)
|
|
{
|
|
#if SHOW
|
|
printf("Interrupted");
|
|
#endif
|
|
pstCode = pstCode->pstLinkFwd; // to pick up later
|
|
mcInput = DCMP_UNFINISHED;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
#if SHOW
|
|
printf("ERROR: putc returned -1");
|
|
#endif
|
|
pstCode = NULL;
|
|
mcInput = ERROR;
|
|
break;
|
|
}
|
|
}
|
|
#if SHOW
|
|
printf("\n");
|
|
#endif
|
|
pstCode = pstCode->pstLinkFwd;
|
|
}
|
|
}
|
|
}
|
|
return(mcInput);
|
|
}
|
|
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION: decompress_continue
|
|
*
|
|
* DESCRIPTION:
|
|
* Needed for compression in remote control. Picks up expansion of an
|
|
* output string after it has been interrupted.
|
|
*
|
|
* ARGUMENTS:
|
|
*
|
|
*
|
|
* RETURNS:
|
|
*
|
|
*/
|
|
int decompress_continue(void)
|
|
{
|
|
int mcPutResult;
|
|
int mcRetCode;
|
|
|
|
// Deliver an initial unfinished code so routines downstream can pick
|
|
// up midstream if necessary
|
|
if ((*pfDcmpPutChar)(pPsave, DCMP_UNFINISHED) == DCMP_UNFINISHED)
|
|
return DCMP_UNFINISHED;
|
|
|
|
// Now continue delivering any remaining expansion codes unless
|
|
// interrupted again
|
|
while (pstCode != NULL)
|
|
{
|
|
if ((mcPutResult = (*pfDcmpPutChar)(pPsave, pstCode->ucChar)) < 0)
|
|
{
|
|
if (mcPutResult == DCMP_UNFINISHED)
|
|
{
|
|
pstCode = pstCode->pstLinkFwd; // to pick up later
|
|
mcRetCode = DCMP_UNFINISHED;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
pstCode = NULL;
|
|
mcRetCode = ERROR;
|
|
break;
|
|
}
|
|
}
|
|
pstCode = pstCode->pstLinkFwd;
|
|
}
|
|
|
|
return mcRetCode;
|
|
}
|
|
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION: dcmp_abort
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
*
|
|
* ARGUMENTS:
|
|
*
|
|
*
|
|
* RETURNS:
|
|
*
|
|
*/
|
|
int dcmp_abort(void)
|
|
{
|
|
/* print error message or whatever */
|
|
fDcmpError = TRUE;
|
|
decompress_stop();
|
|
return(ERROR);
|
|
}
|
|
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION: decompress_stop
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
*
|
|
* ARGUMENTS:
|
|
*
|
|
*
|
|
* RETURNS:
|
|
*
|
|
*/
|
|
void decompress_stop(void)
|
|
{
|
|
#if SHOW
|
|
printf("D Decompress_stop\n");
|
|
#endif
|
|
if (ppfDcmpPutfunc != NULL)
|
|
{
|
|
*ppfDcmpPutfunc = pfDcmpPutChar;
|
|
ppfDcmpPutfunc = NULL;
|
|
}
|
|
usxCmprsStatus = COMPRESS_IDLE;
|
|
}
|
|
|
|
|
|
/* end of cmprs2.c */
|