1
0
Fork 0
mirror of https://github.com/galaxyhaxz/devilution synced 2025-02-23 12:44:54 +00:00
devilution/2020_03_31/3rdParty/Pkware/Source/explode.c
PrisonOfMirrors b720183846 initial up
2020-11-28 18:24:54 -06:00

460 lines
11 KiB
C

#define EXPLODE
#include "tables.inc"
#include "implode.h"
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
#ifndef NULL
#define NULL ((void *)0)
#endif
//#define DEBUG_COPY
//#define DEBUG_LIT
//#include <stdio.h>
static char Copyright[] = { \
"PKWARE Data Compression Library for Win32\r\n" \
"Copyright 1989-1995 PKWARE Inc. All Rights Reserved.\r\n" \
"Patent No. 5,051,745\r\n" \
"PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off.\r\n" \
"Version 1.11" };
#define VOID void
#define CHAR char /* 8 bits, signed */
#define UCHAR unsigned char /* 8 bits, unsigned */
#define SHORT signed short /* 16 bits, signed */
#define USHORT unsigned short /* 16 bits, unsigned */
#define UINT unsigned int
#define INT int
#define LONG signed long /* 32 bits, signed */
#define ULONG unsigned long /* 32 bits, unsigned */
#define MAX_DICT_SIZE 4096
#define EXP_BUFSIZE 4096
#define OUT_SIZE 2048
#define FOO_SIZE 2304
#define MINREP 2
#define SIZE_DIST 64
#define SIZE_LEN 16
#define MAXREP (MINREP+(8*1)+2+4+8+16+32+64+128+256-4)
#define SIZE_LIT (256+MAXREP+2)
#define EOF_CODE (SIZE_LIT-1)
#define ABORT_CODE (EOF_CODE+1)
typedef struct EXP_DATA
{
UINT Distance;
UINT Mode;
UINT OutPtr;
UINT ExtDistBits;
UINT ExtDistMask;
UINT LookAhead;
UINT LookBits;
UINT InPtr;
UINT InBufCnt;
VOID *Param;
#ifdef SYSLINK
UINT (* _System GetBuf)(CHAR *buffer, UINT *size, VOID *Param);
VOID (* _System PutBuf)(CHAR *buffer, UINT *size, VOID *Param);
#else
UINT (*GetBuf)(CHAR *buffer, UINT *size, VOID *Param);
VOID (*PutBuf)(CHAR *buffer, UINT *size, VOID *Param);
#endif
UCHAR OutBuf[(EXP_BUFSIZE*2)+MAXREP];
UCHAR InBuf[OUT_SIZE];
UCHAR DistDecode[256];
UCHAR LenDecode[256];
UCHAR ChLow[256];
UCHAR ChMid1[256];
UCHAR ChMid2[128];
UCHAR ChHi[256];
UCHAR ChBits[256];
UCHAR DistBits[SIZE_DIST];
UCHAR LenBits[SIZE_LEN];
UCHAR ExLenBits[SIZE_LEN];
USHORT LenBase[SIZE_LEN];
};
/****************************************************
Function Declarations
****************************************************/
static UINT Expand(struct EXP_DATA *Exp);
static UINT DecodeLit(struct EXP_DATA *Exp);
static UINT DecodeDist(struct EXP_DATA *Exp, UINT Len);
static UINT WasteBits(struct EXP_DATA *Exp, UINT Bits);
static VOID GenDecodeTabs(UINT Len, UCHAR *Bits, UCHAR *Code, UCHAR *Decode);
static VOID GenAscTabs(struct EXP_DATA *Exp);
static VOID lmemcpy(VOID *Dest, VOID *Source, UINT Size);
/*************************************************
Function: explode
**************************************************
*/
#ifdef SYSLINK
UINT _System explode_sys(
UINT (* _System ReadBuf )(CHAR *Buf, UINT *Size, VOID *Param),
VOID (* _System WriteBuf)(CHAR *Buf, UINT *Size, VOID *Param),
#else
UINT explode(
UINT (*ReadBuf )(CHAR *Buf, UINT *Size, VOID *Param),
VOID (*WriteBuf)(CHAR *Buf, UINT *Size, VOID *Param),
#endif
CHAR *WorkBuf, VOID *Param)
{
struct EXP_DATA *Exp = (struct EXP_DATA *)WorkBuf;
Exp->GetBuf = ReadBuf;
Exp->PutBuf = WriteBuf;
Exp->Param = Param;
Exp->InPtr = OUT_SIZE;
if ((Exp->InBufCnt = (*Exp->GetBuf)((VOID *)(Exp->InBuf), &Exp->InPtr,
Exp->Param)) <= 4)
return CMP_BAD_DATA;
Exp->Mode = Exp->InBuf[0];
Exp->ExtDistBits = Exp->InBuf[1];
Exp->LookAhead = Exp->InBuf[2];
Exp->LookBits = 0;
Exp->InPtr = 3;
if (Exp->ExtDistBits < 4 || Exp->ExtDistBits > 6)
return CMP_INVALID_DICTSIZE;
Exp->ExtDistMask = 0xFFFF >> (16 - Exp->ExtDistBits);
switch (Exp->Mode)
{
case CMP_ASCII:
lmemcpy(Exp->ChBits,ChBitsAsc,sizeof(ChBitsAsc));
GenAscTabs(Exp);
break;
case CMP_BINARY:
break;
default:
return CMP_INVALID_MODE;
}
lmemcpy(Exp->LenBits,LenBits,sizeof(LenBits));
GenDecodeTabs(SIZE_LEN, Exp->LenBits, LenCode, Exp->LenDecode);
lmemcpy(Exp->ExLenBits,ExLenBits,sizeof(ExLenBits));
lmemcpy(Exp->LenBase,LenBase,sizeof(LenBase));
lmemcpy(Exp->DistBits,DistBits,sizeof(DistBits));
GenDecodeTabs(SIZE_DIST, Exp->DistBits, DistCode, Exp->DistDecode);
if (Expand(Exp) == ABORT_CODE)
return CMP_ABORT;
return CMP_NO_ERROR;
}
/**************************************************
Function: Expand
***************************************************
*/
static UINT Expand(struct EXP_DATA *Exp)
{
UINT Len, Dist, i;
CHAR *Src, *Dest;
Exp->OutPtr = EXP_BUFSIZE;
while ((Len = DecodeLit(Exp)) < EOF_CODE)
{
if (Len < 256)
{
#ifdef DEBUG_LIT
printf("Ch=%02x\n",Len);
#endif
Exp->OutBuf[Exp->OutPtr++] = (UCHAR)Len;
}
else
{
Len -= (256 - MINREP);
if ((Dist = DecodeDist(Exp, Len)) == 0)
{
Len = ABORT_CODE;
break;
}
#ifdef DEBUG_COPY
printf("Copy-%d %d\n",Len,Dist);
#endif
Dest = &Exp->OutBuf[Exp->OutPtr];
Src = Dest - Dist;
Exp->OutPtr += Len;
do {
*Dest++ = *Src++;
} while (--Len);
}
if (Exp->OutPtr >= EXP_BUFSIZE*2)
{
Len = EXP_BUFSIZE;
(* Exp->PutBuf)(&Exp->OutBuf[EXP_BUFSIZE], &Len, Exp->Param);
lmemcpy(Exp->OutBuf, &Exp->OutBuf[EXP_BUFSIZE],
Exp->OutPtr-EXP_BUFSIZE);
Exp->OutPtr -= EXP_BUFSIZE;
}
}
i = Exp->OutPtr - EXP_BUFSIZE;
(* Exp->PutBuf)(&Exp->OutBuf[EXP_BUFSIZE], &i, Exp->Param);
return Len;
}
/**************************************************
Function: DecodeLit
***************************************************
*/
static UINT DecodeLit(struct EXP_DATA *Exp)
{
UINT LitChar, i;
if (Exp->LookAhead & 1) /* Length found */
{
if (WasteBits(Exp, 1))
return ABORT_CODE;
LitChar = Exp->LenDecode[Exp->LookAhead & 0xFF];
if (WasteBits(Exp, Exp->LenBits[LitChar]))
return ABORT_CODE;
if (Exp->ExLenBits[LitChar])
{
i = Exp->LookAhead & ((1 << Exp->ExLenBits[LitChar]) - 1);
if (WasteBits(Exp, Exp->ExLenBits[LitChar]))
{
if (LitChar + i != 15 + 255) /* If not EOF */
return ABORT_CODE;
}
LitChar = Exp->LenBase[LitChar] + i;
}
LitChar += 256;
}
else /* Character found */
{
if (WasteBits(Exp, 1))
return ABORT_CODE;
if (Exp->Mode == CMP_BINARY)
{
LitChar = Exp->LookAhead & 0xFF;
if (WasteBits(Exp, 8))
return ABORT_CODE;
}
else
{
if (Exp->LookAhead & 0xFF) /* Low/Mid tab */
{
if ((LitChar = Exp->ChLow[Exp->LookAhead & 0xFF]) == 0xFF)
{
if (Exp->LookAhead & 0x3F) /* Mid tab 1 */
{
if (WasteBits(Exp, 4))
return ABORT_CODE;
LitChar = Exp->ChMid1[Exp->LookAhead & 0xFF];
}
else /* Mid tab 2 */
{
if (WasteBits(Exp, 6))
return ABORT_CODE;
LitChar = Exp->ChMid2[Exp->LookAhead & 0x7F];
}
}
}
else /* High tab */
{
if (WasteBits(Exp, 8))
return ABORT_CODE;
LitChar = Exp->ChHi[Exp->LookAhead & 0xFF];
}
if (WasteBits(Exp, Exp->ChBits[LitChar]))
return ABORT_CODE;
}
}
return LitChar;
}
/**************************************************
Function: DecodeDist
***************************************************
*/
static UINT DecodeDist(struct EXP_DATA *Exp, UINT Len)
{
UINT Dist;
Dist = Exp->DistDecode[Exp->LookAhead & 0xFF];
if (WasteBits(Exp, Exp->DistBits[Dist]))
return 0;
if (Len == MINREP)
{
Dist <<= 2;
Dist |= Exp->LookAhead & 3;
if (WasteBits(Exp, 2))
return 0;
}
else
{
Dist <<= Exp->ExtDistBits;
Dist |= Exp->LookAhead & Exp->ExtDistMask;
if (WasteBits(Exp, Exp->ExtDistBits))
return 0;
}
return Dist+1;
}
/**************************************************
Function: WasteBits
***************************************************
*/
static UINT WasteBits(struct EXP_DATA *Exp, UINT Bits)
{
if (Bits <= Exp->LookBits)
{
Exp->LookAhead >>= Bits;
Exp->LookBits -= Bits;
return 0;
}
Exp->LookAhead >>= Exp->LookBits;
if (Exp->InPtr == Exp->InBufCnt)
{
Exp->InPtr = OUT_SIZE;
if ((Exp->InBufCnt = (*Exp->GetBuf)((VOID *)(Exp->InBuf), &Exp->InPtr,
Exp->Param)) == 0)
return 1;
Exp->InPtr = 0;
}
Exp->LookAhead |= (Exp->InBuf[Exp->InPtr])<<8;
++Exp->InPtr;
Exp->LookAhead >>= (Bits - Exp->LookBits);
Exp->LookBits = 8-(Bits-Exp->LookBits);
return 0;
}
/*************************************************
Function: GenDecodeTabs
**************************************************
*/
static VOID GenDecodeTabs(UINT Len, UCHAR *Bits, UCHAR *Code, UCHAR *Decode)
{
UINT j, Incr;
INT i;
for (i=Len-1; i>=0; i--)
{
Incr = 1 << Bits[i];
j = Code[i];
do
{
Decode[j] = (UCHAR)i;
j += Incr;
} while (j<256);
}
}
/*#pragma optimize("z",off)*/
/**************************************************
Function: GenAscTabs
***************************************************
*/
static VOID GenAscTabs(struct EXP_DATA *Exp)
{
UINT j, Incr;
INT i;
for (i=255; i>=0; i--)
{
if (Exp->ChBits[i] <= 8)
{
Incr = 1 << Exp->ChBits[i];
j = ChCodeAsc[i];
do
{
Exp->ChLow[j] = (UCHAR)i;
j += Incr;
} while (j < 256);
}
else if (ChCodeAsc[i] & 0xFF)
{
Exp->ChLow[ChCodeAsc[i] & 0xFF] = 0xFF;
if (ChCodeAsc[i] & 0x3F)
{
Exp->ChBits[i] -= 4;
Incr= 1 << Exp->ChBits[i];
j = ChCodeAsc[i] >> 4;
do
{
Exp->ChMid1[j] = (UCHAR)i;
j += Incr;
} while (j < 256);
}
else
{
Exp->ChBits[i] -= 6;
Incr = 1 << Exp->ChBits[i];
j = ChCodeAsc[i] >> 6;
do
{
Exp->ChMid2[j] = (UCHAR)i;
j += Incr;
} while (j<128);
}
}
else
{
Exp->ChBits[i] -= 8;
Incr = 1 << Exp->ChBits[i];
j = ChCodeAsc[i] >> 8;
do
{
Exp->ChHi[j] = (UCHAR)i;
j += Incr;
} while (j < 256);
}
}
}
/***************************************************
Function: lmemcpy
****************************************************
*/
static VOID lmemcpy(VOID *Dest, VOID *Source, UINT Size)
{
UCHAR *s=(UCHAR *)Source, *t=(UCHAR *)Dest;
#ifndef _ALPHA
UINT count=Size/4;
if (count)
{ do
{ *(ULONG *)t = *(ULONG *)s;
s+=4;
t+=4;
}
while (--count);
}
if (Size %= 4)
#endif
do {
*t++=*s++;
} while (--Size);
}