mirror of
https://github.com/ZDoom/raze-gles.git
synced 2024-12-24 02:30:46 +00:00
Move the LZW compression functions out of cache1d.cpp into their own object, klzw.cpp.
This eliminates the hackiness of libcache1d.so (now libkzlw.so) and CACHE1D_COMPRESS_ONLY. git-svn-id: https://svn.eduke32.com/eduke32@7140 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
parent
de5d358d32
commit
fd175086a3
7 changed files with 411 additions and 362 deletions
|
@ -165,6 +165,7 @@ engine_objs := \
|
|||
rev.cpp \
|
||||
baselayer.cpp \
|
||||
cache1d.cpp \
|
||||
klzw.cpp \
|
||||
common.cpp \
|
||||
compat.cpp \
|
||||
crc32.cpp \
|
||||
|
@ -211,6 +212,7 @@ engine_tools_objs := \
|
|||
pragmas.cpp \
|
||||
kplib.cpp \
|
||||
cache1d.cpp \
|
||||
klzw.cpp \
|
||||
crc32.cpp \
|
||||
colmatch.cpp \
|
||||
lz4.cpp \
|
||||
|
@ -890,9 +892,9 @@ $(ebacktrace_dll): platform/Windows/src/backtrace.c
|
|||
$(COMPILE_STATUS)
|
||||
$(RECIPE_IF) $(CC) $(CONLYFLAGS) -O2 -ggdb -shared -Wall -Wextra -static-libgcc -I$(engine_inc) -o $@ $^ -lbfd -liberty -limagehlp $(RECIPE_RESULT_COMPILE)
|
||||
|
||||
libcache1d$(DLLSUFFIX): $(engine_src)/cache1d.cpp
|
||||
libklzw$(DLLSUFFIX): $(engine_src)/klzw.cpp
|
||||
$(COMPILE_STATUS)
|
||||
$(RECIPE_IF) $(COMPILER_C) -DCACHE1D_COMPRESS_ONLY -shared -fPIC $< -o $@ $(RECIPE_RESULT_COMPILE)
|
||||
$(RECIPE_IF) $(COMPILER_C) -shared -fPIC $< -o $@ $(RECIPE_RESULT_COMPILE)
|
||||
|
||||
# to debug the tools link phase, make a copy of this rule explicitly replacing % with the name of a tool, such as kextract
|
||||
%$(EXESUFFIX): $(tools_obj)/%.$o $(foreach i,tools $(tools_deps),$(call expandobjs,$i))
|
||||
|
|
|
@ -225,6 +225,7 @@
|
|||
<ClCompile Include="..\..\source\build\src\hash.cpp" />
|
||||
<ClCompile Include="..\..\source\build\src\hightile.cpp" />
|
||||
<ClCompile Include="..\..\source\build\src\jwzgles.c" />
|
||||
<ClCompile Include="..\..\source\build\src\klzw.cpp" />
|
||||
<ClCompile Include="..\..\source\build\src\kplib.cpp" />
|
||||
<ClCompile Include="..\..\source\build\src\lunatic.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
|
@ -334,6 +335,7 @@
|
|||
<ClInclude Include="..\..\source\build\include\hightile.h" />
|
||||
<ClInclude Include="..\..\source\build\include\jwzgles.h" />
|
||||
<ClInclude Include="..\..\source\build\include\jwzglesI.h" />
|
||||
<ClInclude Include="..\..\source\build\include\klzw.h" />
|
||||
<ClInclude Include="..\..\source\build\include\kplib.h" />
|
||||
<ClInclude Include="..\..\source\build\include\libdivide.h" />
|
||||
<ClInclude Include="..\..\source\build\include\lz4.h" />
|
||||
|
|
|
@ -77,6 +77,9 @@
|
|||
<ClCompile Include="..\..\source\build\src\jwzgles.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\build\src\klzw.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\source\build\src\kplib.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
@ -274,6 +277,9 @@
|
|||
<ClInclude Include="..\..\source\build\include\jwzglesI.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\source\build\include\klzw.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\source\build\include\kplib.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
|
|
|
@ -149,6 +149,7 @@ ENGINE_OBJS= \
|
|||
$(ENGINE_OBJ)\animvpx.$o \
|
||||
$(ENGINE_OBJ)\baselayer.$o \
|
||||
$(ENGINE_OBJ)\cache1d.$o \
|
||||
$(ENGINE_OBJ)\klzw.$o \
|
||||
$(ENGINE_OBJ)\common.$o \
|
||||
$(ENGINE_OBJ)\compat.$o \
|
||||
$(ENGINE_OBJ)\crc32.$o \
|
||||
|
|
30
source/build/include/klzw.h
Normal file
30
source/build/include/klzw.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
// "Build Engine & Tools" Copyright (c) 1993-1997 Ken Silverman
|
||||
// Ken Silverman's official web site: "http://www.advsys.net/ken"
|
||||
// See the included license file "BUILDLIC.TXT" for license info.
|
||||
//
|
||||
// This file has been modified from Ken Silverman's original release
|
||||
// by Jonathon Fowler (jf@jonof.id.au)
|
||||
// by the EDuke32 team (development@voidpoint.com)
|
||||
|
||||
#ifndef klzw_h_
|
||||
#define klzw_h_
|
||||
|
||||
#include "compat.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// These two follow the argument order of the C functions "read" and "write":
|
||||
// handle, buffer, length.
|
||||
typedef int32_t (*klzw_readfunc)(intptr_t, void *, int32_t);
|
||||
typedef void (*klzw_writefunc)(intptr_t, void const *, int32_t);
|
||||
|
||||
int32_t klzw_read_compressed(void *buffer, bsize_t dasizeof, bsize_t count, intptr_t f, klzw_readfunc readfunc);
|
||||
void klzw_write_compressed(const void *buffer, bsize_t dasizeof, bsize_t count, intptr_t f, klzw_writefunc writefunc);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // klzw_h_
|
|
@ -8,14 +8,6 @@
|
|||
|
||||
#include "compat.h"
|
||||
|
||||
#ifdef CACHE1D_COMPRESS_ONLY
|
||||
// Standalone libcache1d.so containing only the compression/decompression
|
||||
// functions.
|
||||
# define C1D_STATIC
|
||||
#else
|
||||
// cache1d.o for EDuke32
|
||||
# define C1D_STATIC static
|
||||
|
||||
#ifdef _WIN32
|
||||
// for FILENAME_CASE_CHECK
|
||||
# define NEED_SHELLAPI_H
|
||||
|
@ -25,6 +17,7 @@
|
|||
#include "pragmas.h"
|
||||
#include "baselayer.h"
|
||||
#include "lz4.h"
|
||||
#include "klzw.h"
|
||||
|
||||
#ifdef WITHKPLIB
|
||||
#include "kplib.h"
|
||||
|
@ -1595,22 +1588,6 @@ failure:
|
|||
}
|
||||
|
||||
|
||||
#endif // #ifdef CACHE1D_COMPRESS_ONLY / else
|
||||
|
||||
|
||||
//Internal LZW variables
|
||||
#define LZWSIZE 16384 //Watch out for shorts!
|
||||
#define LZWSIZEPAD (LZWSIZE+(LZWSIZE>>4))
|
||||
|
||||
// lzwrawbuf LZWSIZE+1 (formerly): see (*) below
|
||||
// XXX: lzwrawbuf size increased again :-/
|
||||
static char lzwtmpbuf[LZWSIZEPAD], lzwrawbuf[LZWSIZEPAD], lzwcompbuf[LZWSIZEPAD];
|
||||
static int16_t lzwbuf2[LZWSIZEPAD], lzwbuf3[LZWSIZEPAD];
|
||||
|
||||
static int32_t lzwcompress(const char *lzwinbuf, int32_t uncompleng, char *lzwoutbuf);
|
||||
static int32_t lzwuncompress(const char *lzwinbuf, int32_t compleng, char *lzwoutbuf);
|
||||
|
||||
#ifndef CACHE1D_COMPRESS_ONLY
|
||||
static int32_t kdfread_func(intptr_t fil, void *outbuf, int32_t length)
|
||||
{
|
||||
return kread((int32_t)fil, outbuf, length);
|
||||
|
@ -1620,89 +1597,11 @@ static void dfwrite_func(intptr_t fp, const void *inbuf, int32_t length)
|
|||
{
|
||||
Bfwrite(inbuf, length, 1, (BFILE *)fp);
|
||||
}
|
||||
#else
|
||||
# define kdfread_func NULL
|
||||
# define dfwrite_func NULL
|
||||
#endif
|
||||
|
||||
// These two follow the argument order of the C functions "read" and "write":
|
||||
// handle, buffer, length.
|
||||
C1D_STATIC int32_t (*c1d_readfunc)(intptr_t, void *, int32_t) = kdfread_func;
|
||||
C1D_STATIC void (*c1d_writefunc)(intptr_t, const void *, int32_t) = dfwrite_func;
|
||||
|
||||
|
||||
////////// COMPRESSED READ //////////
|
||||
|
||||
static uint32_t decompress_part(intptr_t f, uint32_t *kgoalptr)
|
||||
{
|
||||
int16_t leng;
|
||||
|
||||
// Read compressed length first.
|
||||
if (c1d_readfunc(f, &leng, 2) != 2)
|
||||
return 1;
|
||||
leng = B_LITTLE16(leng);
|
||||
|
||||
if (c1d_readfunc(f,lzwcompbuf, leng) != leng)
|
||||
return 1;
|
||||
|
||||
*kgoalptr = lzwuncompress(lzwcompbuf, leng, lzwrawbuf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Read from 'f' into 'buffer'.
|
||||
C1D_STATIC int32_t c1d_read_compressed(void *buffer, bsize_t dasizeof, bsize_t count, intptr_t f)
|
||||
{
|
||||
char *ptr = (char *)buffer;
|
||||
|
||||
if (dasizeof > LZWSIZE)
|
||||
{
|
||||
count *= dasizeof;
|
||||
dasizeof = 1;
|
||||
}
|
||||
|
||||
uint32_t kgoal;
|
||||
|
||||
if (decompress_part(f, &kgoal))
|
||||
return -1;
|
||||
|
||||
Bmemcpy(ptr, lzwrawbuf, (int32_t)dasizeof);
|
||||
|
||||
uint32_t k = (int32_t)dasizeof;
|
||||
|
||||
for (uint32_t i=1; i<count; i++)
|
||||
{
|
||||
if (k >= kgoal)
|
||||
{
|
||||
k = decompress_part(f, &kgoal);
|
||||
if (k) return -1;
|
||||
}
|
||||
|
||||
uint32_t j = 0;
|
||||
|
||||
if (dasizeof >= 4)
|
||||
{
|
||||
for (; j<dasizeof-4; j+=4)
|
||||
{
|
||||
ptr[j+dasizeof] = ((ptr[j]+lzwrawbuf[j+k])&255);
|
||||
ptr[j+1+dasizeof] = ((ptr[j+1]+lzwrawbuf[j+1+k])&255);
|
||||
ptr[j+2+dasizeof] = ((ptr[j+2]+lzwrawbuf[j+2+k])&255);
|
||||
ptr[j+3+dasizeof] = ((ptr[j+3]+lzwrawbuf[j+3+k])&255);
|
||||
}
|
||||
}
|
||||
|
||||
for (; j<dasizeof; j++)
|
||||
ptr[j+dasizeof] = ((ptr[j]+lzwrawbuf[j+k])&255);
|
||||
|
||||
k += dasizeof;
|
||||
ptr += dasizeof;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
int32_t kdfread(void *buffer, bsize_t dasizeof, bsize_t count, int32_t fil)
|
||||
{
|
||||
return c1d_read_compressed(buffer, dasizeof, count, (intptr_t)fil);
|
||||
return klzw_read_compressed(buffer, dasizeof, count, (intptr_t)fil, kdfread_func);
|
||||
}
|
||||
|
||||
// LZ4_COMPRESSION_ACCELERATION_VALUE can be tuned for performance/space trade-off
|
||||
|
@ -1712,13 +1611,12 @@ int32_t kdfread(void *buffer, bsize_t dasizeof, bsize_t count, int32_t fil)
|
|||
static char compressedDataStackBuf[131072];
|
||||
int32_t lz4CompressionLevel = LZ4_COMPRESSION_ACCELERATION_VALUE;
|
||||
|
||||
|
||||
int32_t kdfread_LZ4(void *buffer, bsize_t dasizeof, bsize_t count, int32_t fil)
|
||||
{
|
||||
int32_t leng;
|
||||
|
||||
// read compressed data length
|
||||
if (c1d_readfunc(fil, &leng, 4) != 4)
|
||||
if (kread(fil, &leng, sizeof(leng)) != sizeof(leng))
|
||||
return -1;
|
||||
|
||||
leng = B_LITTLE32(leng);
|
||||
|
@ -1728,7 +1626,7 @@ int32_t kdfread_LZ4(void *buffer, bsize_t dasizeof, bsize_t count, int32_t fil)
|
|||
if (leng > ARRAY_SSIZE(compressedDataStackBuf))
|
||||
pCompressedData = (char *)Xaligned_alloc(16, leng);
|
||||
|
||||
if (c1d_readfunc(fil, pCompressedData, leng) != leng)
|
||||
if (kread(fil, pCompressedData, leng) != leng)
|
||||
return -1;
|
||||
|
||||
int32_t decompressedLength = LZ4_decompress_safe(pCompressedData, (char*) buffer, leng, dasizeof*count);
|
||||
|
@ -1740,68 +1638,9 @@ int32_t kdfread_LZ4(void *buffer, bsize_t dasizeof, bsize_t count, int32_t fil)
|
|||
}
|
||||
|
||||
|
||||
////////// COMPRESSED WRITE //////////
|
||||
|
||||
static uint32_t compress_part(uint32_t k, intptr_t f)
|
||||
{
|
||||
const int16_t leng = (int16_t)lzwcompress(lzwrawbuf, k, lzwcompbuf);
|
||||
const int16_t swleng = B_LITTLE16(leng);
|
||||
|
||||
c1d_writefunc(f, &swleng, 2);
|
||||
c1d_writefunc(f, lzwcompbuf, leng);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Write from 'buffer' to 'f'.
|
||||
C1D_STATIC void c1d_write_compressed(const void *buffer, bsize_t dasizeof, bsize_t count, intptr_t f)
|
||||
{
|
||||
char const *ptr = (char const *)buffer;
|
||||
|
||||
if (dasizeof > LZWSIZE)
|
||||
{
|
||||
count *= dasizeof;
|
||||
dasizeof = 1;
|
||||
}
|
||||
|
||||
Bmemcpy(lzwrawbuf, ptr, (int32_t)dasizeof);
|
||||
|
||||
uint32_t k = dasizeof;
|
||||
if (k > LZWSIZE-dasizeof)
|
||||
k = compress_part(k, f);
|
||||
|
||||
for (uint32_t i=1; i<count; i++)
|
||||
{
|
||||
uint32_t j = 0;
|
||||
|
||||
if (dasizeof >= 4)
|
||||
{
|
||||
for (; j<dasizeof-4; j+=4)
|
||||
{
|
||||
lzwrawbuf[j+k] = ((ptr[j+dasizeof]-ptr[j])&255);
|
||||
lzwrawbuf[j+1+k] = ((ptr[j+1+dasizeof]-ptr[j+1])&255);
|
||||
lzwrawbuf[j+2+k] = ((ptr[j+2+dasizeof]-ptr[j+2])&255);
|
||||
lzwrawbuf[j+3+k] = ((ptr[j+3+dasizeof]-ptr[j+3])&255);
|
||||
}
|
||||
}
|
||||
|
||||
for (; j<dasizeof; j++)
|
||||
lzwrawbuf[j+k] = ((ptr[j+dasizeof]-ptr[j])&255);
|
||||
|
||||
k += dasizeof;
|
||||
if (k > LZWSIZE-dasizeof)
|
||||
k = compress_part(k, f);
|
||||
|
||||
ptr += dasizeof;
|
||||
}
|
||||
|
||||
if (k > 0)
|
||||
compress_part(k, f);
|
||||
}
|
||||
|
||||
void dfwrite(const void *buffer, bsize_t dasizeof, bsize_t count, BFILE *fil)
|
||||
{
|
||||
c1d_write_compressed(buffer, dasizeof, count, (intptr_t)fil);
|
||||
klzw_write_compressed(buffer, dasizeof, count, (intptr_t)fil, dfwrite_func);
|
||||
}
|
||||
|
||||
void dfwrite_LZ4(const void *buffer, bsize_t dasizeof, bsize_t count, BFILE *fil)
|
||||
|
@ -1815,201 +1654,9 @@ void dfwrite_LZ4(const void *buffer, bsize_t dasizeof, bsize_t count, BFILE *fil
|
|||
int32_t const leng = LZ4_compress_fast((const char*) buffer, pCompressedData, dasizeof*count, maxCompressedSize, lz4CompressionLevel);
|
||||
int32_t const swleng = B_LITTLE32(leng);
|
||||
|
||||
c1d_writefunc((intptr_t) fil, &swleng, 4);
|
||||
c1d_writefunc((intptr_t) fil, pCompressedData, leng);
|
||||
Bfwrite(&swleng, sizeof(swleng), 1, fil);
|
||||
Bfwrite(pCompressedData, leng, 1, fil);
|
||||
|
||||
if (pCompressedData != compressedDataStackBuf)
|
||||
Baligned_free(pCompressedData);
|
||||
}
|
||||
|
||||
|
||||
////////// CORE COMPRESSION FUNCTIONS //////////
|
||||
|
||||
static int32_t lzwcompress(const char *lzwinbuf, int32_t uncompleng, char *lzwoutbuf)
|
||||
{
|
||||
int32_t i, addr, addrcnt, *intptr;
|
||||
int32_t bytecnt1, bitcnt, numbits, oneupnumbits;
|
||||
int16_t *shortptr;
|
||||
|
||||
int16_t *const lzwcodehead = lzwbuf2;
|
||||
int16_t *const lzwcodenext = lzwbuf3;
|
||||
|
||||
for (i=255; i>=4; i-=4)
|
||||
{
|
||||
lzwtmpbuf[i] = i, lzwcodenext[i] = (i+1)&255;
|
||||
lzwtmpbuf[i-1] = i-1, lzwcodenext[i-1] = (i) &255;
|
||||
lzwtmpbuf[i-2] = i-2, lzwcodenext[i-2] = (i-1)&255;
|
||||
lzwtmpbuf[i-3] = i-3, lzwcodenext[i-3] = (i-2)&255;
|
||||
lzwcodehead[i] = lzwcodehead[i-1] = lzwcodehead[i-2] = lzwcodehead[i-3] = -1;
|
||||
}
|
||||
|
||||
for (; i>=0; i--)
|
||||
{
|
||||
lzwtmpbuf[i] = i;
|
||||
lzwcodenext[i] = (i+1)&255;
|
||||
lzwcodehead[i] = -1;
|
||||
}
|
||||
|
||||
Bmemset(lzwoutbuf, 0, 4+uncompleng+1);
|
||||
// clearbuf(lzwoutbuf,((uncompleng+15)+3)>>2,0L);
|
||||
|
||||
addrcnt = 256; bytecnt1 = 0; bitcnt = (4<<3);
|
||||
numbits = 8; oneupnumbits = (1<<8);
|
||||
do
|
||||
{
|
||||
addr = lzwinbuf[bytecnt1];
|
||||
do
|
||||
{
|
||||
int32_t newaddr;
|
||||
|
||||
if (++bytecnt1 == uncompleng)
|
||||
break; // (*) see XXX below
|
||||
|
||||
if (lzwcodehead[addr] < 0)
|
||||
{
|
||||
lzwcodehead[addr] = addrcnt;
|
||||
break;
|
||||
}
|
||||
|
||||
newaddr = lzwcodehead[addr];
|
||||
while (lzwtmpbuf[newaddr] != lzwinbuf[bytecnt1])
|
||||
{
|
||||
if (lzwcodenext[newaddr] < 0)
|
||||
{
|
||||
lzwcodenext[newaddr] = addrcnt;
|
||||
break;
|
||||
}
|
||||
newaddr = lzwcodenext[newaddr];
|
||||
}
|
||||
|
||||
if (lzwcodenext[newaddr] == addrcnt)
|
||||
break;
|
||||
addr = newaddr;
|
||||
}
|
||||
while (addr >= 0);
|
||||
|
||||
lzwtmpbuf[addrcnt] = lzwinbuf[bytecnt1]; // XXX: potential oob access of lzwinbuf via (*) above
|
||||
lzwcodehead[addrcnt] = -1;
|
||||
lzwcodenext[addrcnt] = -1;
|
||||
|
||||
intptr = (int32_t *)&lzwoutbuf[bitcnt>>3];
|
||||
intptr[0] |= B_LITTLE32(addr<<(bitcnt&7));
|
||||
bitcnt += numbits;
|
||||
if ((addr&((oneupnumbits>>1)-1)) > ((addrcnt-1)&((oneupnumbits>>1)-1)))
|
||||
bitcnt--;
|
||||
|
||||
addrcnt++;
|
||||
if (addrcnt > oneupnumbits)
|
||||
{ numbits++; oneupnumbits <<= 1; }
|
||||
}
|
||||
while ((bytecnt1 < uncompleng) && (bitcnt < (uncompleng<<3)));
|
||||
|
||||
intptr = (int32_t *)&lzwoutbuf[bitcnt>>3];
|
||||
intptr[0] |= B_LITTLE32(addr<<(bitcnt&7));
|
||||
bitcnt += numbits;
|
||||
if ((addr&((oneupnumbits>>1)-1)) > ((addrcnt-1)&((oneupnumbits>>1)-1)))
|
||||
bitcnt--;
|
||||
|
||||
shortptr = (int16_t *)lzwoutbuf;
|
||||
shortptr[0] = B_LITTLE16((int16_t)uncompleng);
|
||||
|
||||
if (((bitcnt+7)>>3) < uncompleng)
|
||||
{
|
||||
shortptr[1] = B_LITTLE16((int16_t)addrcnt);
|
||||
return (bitcnt+7)>>3;
|
||||
}
|
||||
|
||||
// Failed compressing, mark this in the stream.
|
||||
shortptr[1] = 0;
|
||||
|
||||
for (i=0; i<uncompleng-4; i+=4)
|
||||
{
|
||||
lzwoutbuf[i+4] = lzwinbuf[i];
|
||||
lzwoutbuf[i+5] = lzwinbuf[i+1];
|
||||
lzwoutbuf[i+6] = lzwinbuf[i+2];
|
||||
lzwoutbuf[i+7] = lzwinbuf[i+3];
|
||||
}
|
||||
|
||||
for (; i<uncompleng; i++)
|
||||
lzwoutbuf[i+4] = lzwinbuf[i];
|
||||
|
||||
return uncompleng+4;
|
||||
}
|
||||
|
||||
static int32_t lzwuncompress(const char *lzwinbuf, int32_t compleng, char *lzwoutbuf)
|
||||
{
|
||||
int32_t currstr, numbits, oneupnumbits;
|
||||
int32_t i, bitcnt, outbytecnt;
|
||||
|
||||
const int16_t *const shortptr = (const int16_t *)lzwinbuf;
|
||||
const int32_t strtot = B_LITTLE16(shortptr[1]);
|
||||
const int32_t uncompleng = B_LITTLE16(shortptr[0]);
|
||||
|
||||
if (strtot == 0)
|
||||
{
|
||||
if (lzwoutbuf==lzwrawbuf && lzwinbuf==lzwcompbuf)
|
||||
{
|
||||
Bassert((compleng-4)+3+0u < sizeof(lzwrawbuf));
|
||||
Bassert((compleng-4)+3+0u < sizeof(lzwcompbuf)-4);
|
||||
}
|
||||
|
||||
Bmemcpy(lzwoutbuf, lzwinbuf+4, (compleng-4)+3);
|
||||
return uncompleng;
|
||||
}
|
||||
|
||||
for (i=255; i>=4; i-=4)
|
||||
{
|
||||
lzwbuf2[i] = lzwbuf3[i] = i;
|
||||
lzwbuf2[i-1] = lzwbuf3[i-1] = i-1;
|
||||
lzwbuf2[i-2] = lzwbuf3[i-2] = i-2;
|
||||
lzwbuf2[i-3] = lzwbuf3[i-3] = i-3;
|
||||
}
|
||||
|
||||
lzwbuf2[i] = lzwbuf3[i] = i;
|
||||
lzwbuf2[i-1] = lzwbuf3[i-1] = i-1;
|
||||
lzwbuf2[i-2] = lzwbuf3[i-2] = i-2;
|
||||
|
||||
currstr = 256; bitcnt = (4<<3); outbytecnt = 0;
|
||||
numbits = 8; oneupnumbits = (1<<8);
|
||||
do
|
||||
{
|
||||
const int32_t *const intptr = (const int32_t *)&lzwinbuf[bitcnt>>3];
|
||||
|
||||
int32_t dat = ((B_LITTLE32(intptr[0])>>(bitcnt&7)) & (oneupnumbits-1));
|
||||
int32_t leng;
|
||||
|
||||
bitcnt += numbits;
|
||||
if ((dat&((oneupnumbits>>1)-1)) > ((currstr-1)&((oneupnumbits>>1)-1)))
|
||||
{ dat &= ((oneupnumbits>>1)-1); bitcnt--; }
|
||||
|
||||
lzwbuf3[currstr] = dat;
|
||||
|
||||
for (leng=0; dat>=256; leng++,dat=lzwbuf3[dat])
|
||||
lzwtmpbuf[leng] = lzwbuf2[dat];
|
||||
|
||||
lzwoutbuf[outbytecnt++] = dat;
|
||||
|
||||
for (i=leng-1; i>=4; i-=4, outbytecnt+=4)
|
||||
{
|
||||
lzwoutbuf[outbytecnt] = lzwtmpbuf[i];
|
||||
lzwoutbuf[outbytecnt+1] = lzwtmpbuf[i-1];
|
||||
lzwoutbuf[outbytecnt+2] = lzwtmpbuf[i-2];
|
||||
lzwoutbuf[outbytecnt+3] = lzwtmpbuf[i-3];
|
||||
}
|
||||
|
||||
for (; i>=0; i--)
|
||||
lzwoutbuf[outbytecnt++] = lzwtmpbuf[i];
|
||||
|
||||
lzwbuf2[currstr-1] = dat; lzwbuf2[currstr] = dat;
|
||||
currstr++;
|
||||
if (currstr > oneupnumbits)
|
||||
{ numbits++; oneupnumbits <<= 1; }
|
||||
}
|
||||
while (currstr < strtot);
|
||||
|
||||
return uncompleng;
|
||||
}
|
||||
|
||||
/*
|
||||
* vim:ts=4:sw=4:
|
||||
*/
|
||||
|
|
361
source/build/src/klzw.cpp
Normal file
361
source/build/src/klzw.cpp
Normal file
|
@ -0,0 +1,361 @@
|
|||
// "Build Engine & Tools" Copyright (c) 1993-1997 Ken Silverman
|
||||
// Ken Silverman's official web site: "http://www.advsys.net/ken"
|
||||
// See the included license file "BUILDLIC.TXT" for license info.
|
||||
//
|
||||
// This file has been modified from Ken Silverman's original release
|
||||
// by Jonathon Fowler (jf@jonof.id.au)
|
||||
// by the EDuke32 team (development@voidpoint.com)
|
||||
|
||||
#include "compat.h"
|
||||
#include "klzw.h"
|
||||
|
||||
//Internal LZW variables
|
||||
#define LZWSIZE 16384 //Watch out for shorts!
|
||||
#define LZWSIZEPAD (LZWSIZE+(LZWSIZE>>4))
|
||||
|
||||
// lzwrawbuf LZWSIZE+1 (formerly): see (*) below
|
||||
// XXX: lzwrawbuf size increased again :-/
|
||||
static char lzwtmpbuf[LZWSIZEPAD], lzwrawbuf[LZWSIZEPAD], lzwcompbuf[LZWSIZEPAD];
|
||||
static int16_t lzwbuf2[LZWSIZEPAD], lzwbuf3[LZWSIZEPAD];
|
||||
|
||||
|
||||
////////// CORE COMPRESSION FUNCTIONS //////////
|
||||
|
||||
static int32_t lzwcompress(const char *lzwinbuf, int32_t uncompleng, char *lzwoutbuf)
|
||||
{
|
||||
int32_t i, addr, addrcnt, *intptr;
|
||||
int32_t bytecnt1, bitcnt, numbits, oneupnumbits;
|
||||
int16_t *shortptr;
|
||||
|
||||
int16_t *const lzwcodehead = lzwbuf2;
|
||||
int16_t *const lzwcodenext = lzwbuf3;
|
||||
|
||||
for (i=255; i>=4; i-=4)
|
||||
{
|
||||
lzwtmpbuf[i] = i, lzwcodenext[i] = (i+1)&255;
|
||||
lzwtmpbuf[i-1] = i-1, lzwcodenext[i-1] = (i) &255;
|
||||
lzwtmpbuf[i-2] = i-2, lzwcodenext[i-2] = (i-1)&255;
|
||||
lzwtmpbuf[i-3] = i-3, lzwcodenext[i-3] = (i-2)&255;
|
||||
lzwcodehead[i] = lzwcodehead[i-1] = lzwcodehead[i-2] = lzwcodehead[i-3] = -1;
|
||||
}
|
||||
|
||||
for (; i>=0; i--)
|
||||
{
|
||||
lzwtmpbuf[i] = i;
|
||||
lzwcodenext[i] = (i+1)&255;
|
||||
lzwcodehead[i] = -1;
|
||||
}
|
||||
|
||||
Bmemset(lzwoutbuf, 0, 4+uncompleng+1);
|
||||
// clearbuf(lzwoutbuf,((uncompleng+15)+3)>>2,0L);
|
||||
|
||||
addrcnt = 256; bytecnt1 = 0; bitcnt = (4<<3);
|
||||
numbits = 8; oneupnumbits = (1<<8);
|
||||
do
|
||||
{
|
||||
addr = lzwinbuf[bytecnt1];
|
||||
do
|
||||
{
|
||||
int32_t newaddr;
|
||||
|
||||
if (++bytecnt1 == uncompleng)
|
||||
break; // (*) see XXX below
|
||||
|
||||
if (lzwcodehead[addr] < 0)
|
||||
{
|
||||
lzwcodehead[addr] = addrcnt;
|
||||
break;
|
||||
}
|
||||
|
||||
newaddr = lzwcodehead[addr];
|
||||
while (lzwtmpbuf[newaddr] != lzwinbuf[bytecnt1])
|
||||
{
|
||||
if (lzwcodenext[newaddr] < 0)
|
||||
{
|
||||
lzwcodenext[newaddr] = addrcnt;
|
||||
break;
|
||||
}
|
||||
newaddr = lzwcodenext[newaddr];
|
||||
}
|
||||
|
||||
if (lzwcodenext[newaddr] == addrcnt)
|
||||
break;
|
||||
addr = newaddr;
|
||||
}
|
||||
while (addr >= 0);
|
||||
|
||||
lzwtmpbuf[addrcnt] = lzwinbuf[bytecnt1]; // XXX: potential oob access of lzwinbuf via (*) above
|
||||
lzwcodehead[addrcnt] = -1;
|
||||
lzwcodenext[addrcnt] = -1;
|
||||
|
||||
intptr = (int32_t *)&lzwoutbuf[bitcnt>>3];
|
||||
intptr[0] |= B_LITTLE32(addr<<(bitcnt&7));
|
||||
bitcnt += numbits;
|
||||
if ((addr&((oneupnumbits>>1)-1)) > ((addrcnt-1)&((oneupnumbits>>1)-1)))
|
||||
bitcnt--;
|
||||
|
||||
addrcnt++;
|
||||
if (addrcnt > oneupnumbits)
|
||||
{ numbits++; oneupnumbits <<= 1; }
|
||||
}
|
||||
while ((bytecnt1 < uncompleng) && (bitcnt < (uncompleng<<3)));
|
||||
|
||||
intptr = (int32_t *)&lzwoutbuf[bitcnt>>3];
|
||||
intptr[0] |= B_LITTLE32(addr<<(bitcnt&7));
|
||||
bitcnt += numbits;
|
||||
if ((addr&((oneupnumbits>>1)-1)) > ((addrcnt-1)&((oneupnumbits>>1)-1)))
|
||||
bitcnt--;
|
||||
|
||||
shortptr = (int16_t *)lzwoutbuf;
|
||||
shortptr[0] = B_LITTLE16((int16_t)uncompleng);
|
||||
|
||||
if (((bitcnt+7)>>3) < uncompleng)
|
||||
{
|
||||
shortptr[1] = B_LITTLE16((int16_t)addrcnt);
|
||||
return (bitcnt+7)>>3;
|
||||
}
|
||||
|
||||
// Failed compressing, mark this in the stream.
|
||||
shortptr[1] = 0;
|
||||
|
||||
for (i=0; i<uncompleng-4; i+=4)
|
||||
{
|
||||
lzwoutbuf[i+4] = lzwinbuf[i];
|
||||
lzwoutbuf[i+5] = lzwinbuf[i+1];
|
||||
lzwoutbuf[i+6] = lzwinbuf[i+2];
|
||||
lzwoutbuf[i+7] = lzwinbuf[i+3];
|
||||
}
|
||||
|
||||
for (; i<uncompleng; i++)
|
||||
lzwoutbuf[i+4] = lzwinbuf[i];
|
||||
|
||||
return uncompleng+4;
|
||||
}
|
||||
|
||||
static int32_t lzwuncompress(const char *lzwinbuf, int32_t compleng, char *lzwoutbuf)
|
||||
{
|
||||
int32_t currstr, numbits, oneupnumbits;
|
||||
int32_t i, bitcnt, outbytecnt;
|
||||
|
||||
const int16_t *const shortptr = (const int16_t *)lzwinbuf;
|
||||
const int32_t strtot = B_LITTLE16(shortptr[1]);
|
||||
const int32_t uncompleng = B_LITTLE16(shortptr[0]);
|
||||
|
||||
if (strtot == 0)
|
||||
{
|
||||
if (lzwoutbuf==lzwrawbuf && lzwinbuf==lzwcompbuf)
|
||||
{
|
||||
Bassert((compleng-4)+3+0u < sizeof(lzwrawbuf));
|
||||
Bassert((compleng-4)+3+0u < sizeof(lzwcompbuf)-4);
|
||||
}
|
||||
|
||||
Bmemcpy(lzwoutbuf, lzwinbuf+4, (compleng-4)+3);
|
||||
return uncompleng;
|
||||
}
|
||||
|
||||
for (i=255; i>=4; i-=4)
|
||||
{
|
||||
lzwbuf2[i] = lzwbuf3[i] = i;
|
||||
lzwbuf2[i-1] = lzwbuf3[i-1] = i-1;
|
||||
lzwbuf2[i-2] = lzwbuf3[i-2] = i-2;
|
||||
lzwbuf2[i-3] = lzwbuf3[i-3] = i-3;
|
||||
}
|
||||
|
||||
lzwbuf2[i] = lzwbuf3[i] = i;
|
||||
lzwbuf2[i-1] = lzwbuf3[i-1] = i-1;
|
||||
lzwbuf2[i-2] = lzwbuf3[i-2] = i-2;
|
||||
|
||||
currstr = 256; bitcnt = (4<<3); outbytecnt = 0;
|
||||
numbits = 8; oneupnumbits = (1<<8);
|
||||
do
|
||||
{
|
||||
const int32_t *const intptr = (const int32_t *)&lzwinbuf[bitcnt>>3];
|
||||
|
||||
int32_t dat = ((B_LITTLE32(intptr[0])>>(bitcnt&7)) & (oneupnumbits-1));
|
||||
int32_t leng;
|
||||
|
||||
bitcnt += numbits;
|
||||
if ((dat&((oneupnumbits>>1)-1)) > ((currstr-1)&((oneupnumbits>>1)-1)))
|
||||
{ dat &= ((oneupnumbits>>1)-1); bitcnt--; }
|
||||
|
||||
lzwbuf3[currstr] = dat;
|
||||
|
||||
for (leng=0; dat>=256; leng++,dat=lzwbuf3[dat])
|
||||
lzwtmpbuf[leng] = lzwbuf2[dat];
|
||||
|
||||
lzwoutbuf[outbytecnt++] = dat;
|
||||
|
||||
for (i=leng-1; i>=4; i-=4, outbytecnt+=4)
|
||||
{
|
||||
lzwoutbuf[outbytecnt] = lzwtmpbuf[i];
|
||||
lzwoutbuf[outbytecnt+1] = lzwtmpbuf[i-1];
|
||||
lzwoutbuf[outbytecnt+2] = lzwtmpbuf[i-2];
|
||||
lzwoutbuf[outbytecnt+3] = lzwtmpbuf[i-3];
|
||||
}
|
||||
|
||||
for (; i>=0; i--)
|
||||
lzwoutbuf[outbytecnt++] = lzwtmpbuf[i];
|
||||
|
||||
lzwbuf2[currstr-1] = dat; lzwbuf2[currstr] = dat;
|
||||
currstr++;
|
||||
if (currstr > oneupnumbits)
|
||||
{ numbits++; oneupnumbits <<= 1; }
|
||||
}
|
||||
while (currstr < strtot);
|
||||
|
||||
return uncompleng;
|
||||
}
|
||||
|
||||
|
||||
////////// COMPRESSED READ //////////
|
||||
|
||||
struct decompress_info
|
||||
{
|
||||
klzw_readfunc readfunc;
|
||||
intptr_t f;
|
||||
uint32_t kgoal;
|
||||
};
|
||||
|
||||
static uint32_t decompress_part(struct decompress_info * x)
|
||||
{
|
||||
intptr_t const f = x->f;
|
||||
auto readfunc = x->readfunc;
|
||||
|
||||
// Read compressed length first.
|
||||
int16_t leng;
|
||||
if (readfunc(f, &leng, sizeof(leng)) != sizeof(leng))
|
||||
return 1;
|
||||
leng = B_LITTLE16(leng);
|
||||
|
||||
if (readfunc(f, lzwcompbuf, leng) != leng)
|
||||
return 1;
|
||||
|
||||
x->kgoal = lzwuncompress(lzwcompbuf, leng, lzwrawbuf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Read from 'f' into 'buffer'.
|
||||
int32_t klzw_read_compressed(void *buffer, bsize_t dasizeof, bsize_t count, intptr_t f, klzw_readfunc readfunc)
|
||||
{
|
||||
char *ptr = (char *)buffer;
|
||||
|
||||
if (dasizeof > LZWSIZE)
|
||||
{
|
||||
count *= dasizeof;
|
||||
dasizeof = 1;
|
||||
}
|
||||
|
||||
struct decompress_info x;
|
||||
x.readfunc = readfunc;
|
||||
x.f = f;
|
||||
|
||||
if (decompress_part(&x))
|
||||
return -1;
|
||||
|
||||
Bmemcpy(ptr, lzwrawbuf, (int32_t)dasizeof);
|
||||
|
||||
uint32_t k = (int32_t)dasizeof;
|
||||
|
||||
for (uint32_t i=1; i<count; i++)
|
||||
{
|
||||
if (k >= x.kgoal)
|
||||
{
|
||||
k = decompress_part(&x);
|
||||
if (k) return -1;
|
||||
}
|
||||
|
||||
uint32_t j = 0;
|
||||
|
||||
if (dasizeof >= 4)
|
||||
{
|
||||
for (; j<dasizeof-4; j+=4)
|
||||
{
|
||||
ptr[j+dasizeof] = ((ptr[j]+lzwrawbuf[j+k])&255);
|
||||
ptr[j+1+dasizeof] = ((ptr[j+1]+lzwrawbuf[j+1+k])&255);
|
||||
ptr[j+2+dasizeof] = ((ptr[j+2]+lzwrawbuf[j+2+k])&255);
|
||||
ptr[j+3+dasizeof] = ((ptr[j+3]+lzwrawbuf[j+3+k])&255);
|
||||
}
|
||||
}
|
||||
|
||||
for (; j<dasizeof; j++)
|
||||
ptr[j+dasizeof] = ((ptr[j]+lzwrawbuf[j+k])&255);
|
||||
|
||||
k += dasizeof;
|
||||
ptr += dasizeof;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
////////// COMPRESSED WRITE //////////
|
||||
|
||||
struct compress_info
|
||||
{
|
||||
klzw_writefunc writefunc;
|
||||
intptr_t f;
|
||||
uint32_t k;
|
||||
};
|
||||
|
||||
static void compress_part(struct compress_info * x)
|
||||
{
|
||||
const int16_t leng = (int16_t)lzwcompress(lzwrawbuf, x->k, lzwcompbuf);
|
||||
const int16_t swleng = B_LITTLE16(leng);
|
||||
|
||||
intptr_t const f = x->f;
|
||||
auto writefunc = x->writefunc;
|
||||
|
||||
x->k = 0;
|
||||
|
||||
writefunc(f, &swleng, sizeof(swleng));
|
||||
writefunc(f, lzwcompbuf, leng);
|
||||
}
|
||||
|
||||
// Write from 'buffer' to 'f'.
|
||||
void klzw_write_compressed(const void *buffer, bsize_t dasizeof, bsize_t count, intptr_t f, klzw_writefunc writefunc)
|
||||
{
|
||||
char const *ptr = (char const *)buffer;
|
||||
|
||||
if (dasizeof > LZWSIZE)
|
||||
{
|
||||
count *= dasizeof;
|
||||
dasizeof = 1;
|
||||
}
|
||||
|
||||
Bmemcpy(lzwrawbuf, ptr, (int32_t)dasizeof);
|
||||
|
||||
struct compress_info x;
|
||||
x.writefunc = writefunc;
|
||||
x.f = f;
|
||||
|
||||
if ((x.k = dasizeof) > LZWSIZE-dasizeof)
|
||||
compress_part(&x);
|
||||
|
||||
for (uint32_t i=1; i<count; i++)
|
||||
{
|
||||
uint32_t j = 0;
|
||||
|
||||
if (dasizeof >= 4)
|
||||
{
|
||||
for (; j<dasizeof-4; j+=4)
|
||||
{
|
||||
lzwrawbuf[j+x.k] = ((ptr[j+dasizeof]-ptr[j])&255);
|
||||
lzwrawbuf[j+1+x.k] = ((ptr[j+1+dasizeof]-ptr[j+1])&255);
|
||||
lzwrawbuf[j+2+x.k] = ((ptr[j+2+dasizeof]-ptr[j+2])&255);
|
||||
lzwrawbuf[j+3+x.k] = ((ptr[j+3+dasizeof]-ptr[j+3])&255);
|
||||
}
|
||||
}
|
||||
|
||||
for (; j<dasizeof; j++)
|
||||
lzwrawbuf[j+x.k] = ((ptr[j+dasizeof]-ptr[j])&255);
|
||||
|
||||
if ((x.k += dasizeof) > LZWSIZE-dasizeof)
|
||||
compress_part(&x);
|
||||
|
||||
ptr += dasizeof;
|
||||
}
|
||||
|
||||
if (x.k > 0)
|
||||
compress_part(&x);
|
||||
}
|
Loading…
Reference in a new issue