This commit is contained in:
parent
13a2191670
commit
d8dc188f90
2 changed files with 420 additions and 0 deletions
359
source/utils/pak.cpp
Normal file
359
source/utils/pak.cpp
Normal file
|
@ -0,0 +1,359 @@
|
|||
/*=========================================================================
|
||||
|
||||
PAK.CPP
|
||||
|
||||
Author: Gary Liddon @ Climax (from work by Nick Pelling && Carl Muller)
|
||||
Created:
|
||||
Project: Diablo PSX
|
||||
Purpose: PAK decompress \ compress code
|
||||
|
||||
Copyright (c) 1997 Climax Development Ltd
|
||||
|
||||
===========================================================================*/
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Includes
|
||||
-------- */
|
||||
|
||||
/* Std Lib
|
||||
------- */
|
||||
|
||||
/* Glib
|
||||
---- */
|
||||
|
||||
/* Local
|
||||
----- */
|
||||
#include <string.h>
|
||||
#include "pak.h"
|
||||
|
||||
/* Graphics
|
||||
-------- */
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Tyepdefs && Defines
|
||||
------------------- */
|
||||
#define UNPAKBUFFERSIZE 4096
|
||||
#define STRMAX 80
|
||||
#define BUFFERSIZE 30000
|
||||
#define TRIGGER 20000
|
||||
#define MAXUNIQUE 127
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Structure defintions
|
||||
-------------------- */
|
||||
struct Block
|
||||
{
|
||||
int data[128];
|
||||
BOOL blockrep;
|
||||
int blocksize;
|
||||
int blockoffset;
|
||||
|
||||
u8 * Dest;
|
||||
int outsize;
|
||||
|
||||
virtual void fputc(u8 Val)
|
||||
{
|
||||
*Dest=Val;
|
||||
Dest++;
|
||||
outsize++;
|
||||
}
|
||||
|
||||
void writeBlock(void);
|
||||
};
|
||||
|
||||
struct CountBlock : Block
|
||||
{
|
||||
virtual void fputc(u8 Val)
|
||||
{
|
||||
Dest++;
|
||||
outsize++;
|
||||
}
|
||||
};
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Vars
|
||||
---- */
|
||||
static int s_lastAmountOfCompressedData;
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Function Prototypes
|
||||
------------------- */
|
||||
static void writeblock(struct block *theblock);
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Vars
|
||||
---- */
|
||||
/*----------------------------------------------------------------------
|
||||
Data
|
||||
---- */
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Function:
|
||||
Purpose:
|
||||
Params:
|
||||
Returns:
|
||||
---------------------------------------------------------------------- */
|
||||
void Block::writeBlock(void)
|
||||
{
|
||||
if ((blockrep) && (blocksize == 0))
|
||||
{
|
||||
/* Terminator */
|
||||
fputc(128);
|
||||
fputc(0);
|
||||
}
|
||||
else if (blockrep)
|
||||
{
|
||||
fputc(blockoffset);
|
||||
fputc(blocksize);
|
||||
}
|
||||
else /* Unique bytes */
|
||||
{
|
||||
fputc(blocksize & 127);
|
||||
|
||||
for (int i = 0; i <= blocksize; i++)
|
||||
fputc(data[i]);
|
||||
}
|
||||
|
||||
// Get ready for next block
|
||||
blockrep = FALSE;
|
||||
blockoffset = 0;
|
||||
blocksize = -1;
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Function:
|
||||
Purpose:
|
||||
Params:
|
||||
Returns:
|
||||
---------------------------------------------------------------------- */
|
||||
static bool memequ(u8 const * p1,u8 const * p2,int size)
|
||||
{
|
||||
bool same;
|
||||
|
||||
same=true;
|
||||
|
||||
for (int f=0;f<size && same;f++)
|
||||
same=p1[f]==p2[f];
|
||||
|
||||
return(same);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Function:
|
||||
Purpose:
|
||||
Params:
|
||||
Returns:
|
||||
---------------------------------------------------------------------- */
|
||||
int lowLevelPak(u8 * Dest,u8 const * buffer,int insize,Block & theblock)
|
||||
{
|
||||
long begin, end, bestlength;
|
||||
int offset, bestoffset;
|
||||
unsigned char const * theptr;
|
||||
unsigned char const * ptr1;
|
||||
unsigned char const * ptr2;
|
||||
unsigned char const * ptr3;
|
||||
long BACKDIST, FORWARDDIST, MINBLOCK;
|
||||
|
||||
theblock.Dest=Dest;
|
||||
theblock.outsize=0;
|
||||
theblock.blockrep=FALSE;
|
||||
|
||||
BACKDIST = -128;
|
||||
FORWARDDIST = 255;
|
||||
MINBLOCK = 3;
|
||||
|
||||
int inpos = 0;
|
||||
|
||||
theblock.blocksize = -1;
|
||||
theblock.data[++theblock.blocksize] = buffer[inpos++];
|
||||
theblock.data[++theblock.blocksize] = buffer[inpos++];
|
||||
|
||||
while (inpos < insize)
|
||||
{
|
||||
/* See if we should load new data into the buffer */
|
||||
|
||||
begin = -inpos;
|
||||
end = insize - inpos;
|
||||
|
||||
if (begin < BACKDIST)
|
||||
begin = BACKDIST;
|
||||
|
||||
if (end > FORWARDDIST)
|
||||
end = FORWARDDIST;
|
||||
|
||||
bestoffset = begin;
|
||||
bestlength = 1;
|
||||
theptr = buffer + (inpos);
|
||||
|
||||
ptr1 = buffer + (inpos + begin);
|
||||
|
||||
for (offset = begin; offset < 0; offset++)
|
||||
{
|
||||
if (*ptr1 == *theptr)
|
||||
{
|
||||
if (memequ(ptr1, theptr, bestlength + 1))
|
||||
{
|
||||
bestlength++;
|
||||
bestoffset = offset;
|
||||
ptr2 = ptr1 + bestlength;
|
||||
ptr3 = theptr + bestlength;
|
||||
|
||||
while (*ptr2 == *ptr3)
|
||||
{
|
||||
ptr2++;
|
||||
ptr3++;
|
||||
bestlength++;
|
||||
if (bestlength >= end)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bestlength >= end)
|
||||
{
|
||||
bestlength = end;
|
||||
break;
|
||||
}
|
||||
|
||||
ptr1++;
|
||||
}
|
||||
|
||||
|
||||
if (bestlength < MINBLOCK)
|
||||
{
|
||||
/* See if last block is unique */
|
||||
|
||||
if (theblock.blockrep) /* Flush previous special block */
|
||||
{
|
||||
theblock.writeBlock();
|
||||
theblock.data[++theblock.blocksize] = buffer[inpos++];
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Add to it */
|
||||
|
||||
if (theblock.blocksize >= MAXUNIQUE)
|
||||
theblock.writeBlock();
|
||||
|
||||
theblock.data[++theblock.blocksize] = buffer[inpos++];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We have found a match */
|
||||
theblock.writeBlock();
|
||||
theblock.blockrep = TRUE;
|
||||
theblock.blocksize = bestlength;
|
||||
theblock.blockoffset = bestoffset;
|
||||
inpos += bestlength;
|
||||
}
|
||||
}
|
||||
|
||||
/* Flush buffer */
|
||||
|
||||
theblock.writeBlock();
|
||||
|
||||
/* Terminate file */
|
||||
|
||||
theblock.blockrep = TRUE;
|
||||
theblock.blocksize = 0;
|
||||
theblock.blockoffset = 0;
|
||||
theblock.writeBlock();
|
||||
|
||||
return(theblock.outsize);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Function:
|
||||
Purpose:
|
||||
Params:
|
||||
Returns:
|
||||
---------------------------------------------------------------------- */
|
||||
int PAK_doPak(u8 * Dest,u8 const * buffer,int insize)
|
||||
{
|
||||
Block outBlock;
|
||||
return(lowLevelPak(Dest,buffer,insize,outBlock));
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Function:
|
||||
Purpose:
|
||||
Params:
|
||||
Returns:
|
||||
---------------------------------------------------------------------- */
|
||||
int PAK_findPakSize(u8 const * buffer,int insize)
|
||||
{
|
||||
CountBlock outBlock;
|
||||
return(lowLevelPak(NULL,buffer,insize,outBlock));
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Function:
|
||||
Purpose:
|
||||
Params:
|
||||
Returns:
|
||||
---------------------------------------------------------------------- */
|
||||
int PAK_doUnpak(u8 * Dest,u8 const * Source)
|
||||
{
|
||||
int outsize = 0;
|
||||
u8 const * originalSource;
|
||||
|
||||
originalSource=Source;
|
||||
|
||||
while (1) /* ie, continue until end mark */
|
||||
{
|
||||
u8 const * From;
|
||||
|
||||
int size;
|
||||
int ch;
|
||||
|
||||
ch = *Source++;
|
||||
|
||||
if (ch < 128) /* if it is in range {0..127} then */
|
||||
{
|
||||
size = (ch + 1);
|
||||
From=Source;
|
||||
Source+=size;
|
||||
}
|
||||
else
|
||||
{
|
||||
size = *Source++;
|
||||
|
||||
if (size == 0) /* distance == 0 => end of file */
|
||||
break;
|
||||
|
||||
From=Dest+(s8)ch;
|
||||
}
|
||||
|
||||
u8 * endAddr;
|
||||
endAddr=(u8*)(u32(From)+size);
|
||||
|
||||
outsize += size;
|
||||
|
||||
while (From!=endAddr)
|
||||
{
|
||||
*Dest=*From;
|
||||
Dest++;
|
||||
From++;
|
||||
}
|
||||
}
|
||||
|
||||
s_lastAmountOfCompressedData=Source-originalSource;
|
||||
|
||||
return(outsize);
|
||||
}
|
||||
|
||||
int PAK_getLastAmountOfDataRead(void)
|
||||
{
|
||||
return(s_lastAmountOfCompressedData);
|
||||
}
|
||||
|
||||
/*===========================================================================
|
||||
end */
|
||||
|
||||
|
||||
|
||||
|
61
source/utils/pak.h
Normal file
61
source/utils/pak.h
Normal file
|
@ -0,0 +1,61 @@
|
|||
/*=========================================================================
|
||||
|
||||
PAK.H
|
||||
|
||||
Author: Carl Muller (algorithm Nick Pelling && Carl Muller)
|
||||
Created:
|
||||
Project:
|
||||
Purpose:
|
||||
|
||||
Copyright (c) 1997 Climax Development Ltd
|
||||
|
||||
===========================================================================*/
|
||||
|
||||
#ifndef __PAK_PAK_H__
|
||||
#define __PAK_PAK_H__
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Includes
|
||||
-------- */
|
||||
|
||||
/* Std Lib
|
||||
------- */
|
||||
|
||||
/* Glib
|
||||
---- */
|
||||
#include <gtypes.h>
|
||||
|
||||
/* Local
|
||||
----- */
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Tyepdefs && Defines
|
||||
------------------- */
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Structure defintions
|
||||
-------------------- */
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
Globals
|
||||
------- */
|
||||
|
||||
/* Vars
|
||||
---- */
|
||||
|
||||
/* Data
|
||||
---- */
|
||||
|
||||
/* Functions
|
||||
--------- */
|
||||
int PAK_doPak(u8 * Dest,u8 const * source,int insize);
|
||||
int PAK_doUnpak(u8 * Dest,u8 const * Source);
|
||||
int PAK_findPakSize(u8 const * souce,int insize);
|
||||
int PAK_getLastAmountOfDataRead(void);
|
||||
|
||||
/*---------------------------------------------------------------------- */
|
||||
|
||||
#endif /* __PAK_PAK_H__ */
|
||||
|
||||
/*===========================================================================
|
||||
end */
|
Loading…
Add table
Reference in a new issue