diff --git a/GNUmakefile b/GNUmakefile index c81e4e559..d9ef931ad 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -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)) diff --git a/platform/Windows/build.vcxproj b/platform/Windows/build.vcxproj index b55d1b9ae..da1b581a9 100644 --- a/platform/Windows/build.vcxproj +++ b/platform/Windows/build.vcxproj @@ -225,6 +225,7 @@ + true @@ -334,6 +335,7 @@ + diff --git a/platform/Windows/build.vcxproj.filters b/platform/Windows/build.vcxproj.filters index eab604702..36bb52b15 100644 --- a/platform/Windows/build.vcxproj.filters +++ b/platform/Windows/build.vcxproj.filters @@ -77,6 +77,9 @@ Source Files + + Source Files + Source Files @@ -274,6 +277,9 @@ Header Files + + Header Files + Header Files diff --git a/platform/Windows/msvc.mak b/platform/Windows/msvc.mak index 7f844a3aa..e31809002 100644 --- a/platform/Windows/msvc.mak +++ b/platform/Windows/msvc.mak @@ -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 \ diff --git a/source/build/include/klzw.h b/source/build/include/klzw.h new file mode 100644 index 000000000..76939c185 --- /dev/null +++ b/source/build/include/klzw.h @@ -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_ diff --git a/source/build/src/cache1d.cpp b/source/build/src/cache1d.cpp index 4c28fe409..d68402d9b 100644 --- a/source/build/src/cache1d.cpp +++ b/source/build/src/cache1d.cpp @@ -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= kgoal) - { - k = decompress_part(f, &kgoal); - if (k) return -1; - } - - uint32_t j = 0; - - if (dasizeof >= 4) - { - for (; j 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= 4) - { - for (; j 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=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: - */ diff --git a/source/build/src/klzw.cpp b/source/build/src/klzw.cpp new file mode 100644 index 000000000..ca385c75b --- /dev/null +++ b/source/build/src/klzw.cpp @@ -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=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= x.kgoal) + { + k = decompress_part(&x); + if (k) return -1; + } + + uint32_t j = 0; + + if (dasizeof >= 4) + { + for (; jk, 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= 4) + { + for (; j LZWSIZE-dasizeof) + compress_part(&x); + + ptr += dasizeof; + } + + if (x.k > 0) + compress_part(&x); +}