Code:
#include "stdafx.h"
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#define EOF_CODE 0x101
#define HASH_SIZE 0x2405
#define RESET_CODE 0x100
#define SYMBOL_BASE 0x102
struct LZWEntry {
int16_t Prefix;
int16_t Suffix;
};
uint8_t Buffer[0x1000];
int32_t DictionaryIndex = 0x0;
LZWEntry DictionaryO[0x1000];
int16_t Table[HASH_SIZE];
void AddEntry(const int32_t Prefix, const int32_t Suffix, const int32_t Offset = -1) {
if (Prefix == -1 || Prefix >= DictionaryIndex || DictionaryIndex >= 0x1000 || Offset >= 0x0) return;
DictionaryO[DictionaryIndex].Prefix = Prefix;
DictionaryO[DictionaryIndex].Suffix = Suffix;
Table[-Offset - 0x1] = DictionaryIndex;
if (DictionaryIndex < 0x1000) DictionaryIndex += 0x1;
}
int32_t FindEntry(const int32_t Prefix, const int32_t Suffix) {
int32_t i = (Prefix & 0x3FF) + (Suffix << 0x4) + ((Suffix & 0xF) << 0x8);
int32_t Offset = (i > 0x0) ? HASH_SIZE - i : 0x1;
while (true) {
if (Table[i] < 0x0) { //FREE_SLOT?
return -i - 0x1;
} else if (DictionaryO[Table[i]].Prefix == Prefix && DictionaryO[Table[i]].Suffix == Suffix) {//DESIRED_ENTRY?
return Table[i];
}
i -= Offset;
if (i < 0x0) i += HASH_SIZE;
//return ...; // DEFAULT_RETURN_VALUE?
}
}
void Reset() {
memset(&DictionaryO, -1, sizeof(DictionaryO));
memset(&Table, -1, sizeof(Table));
for (int32_t i = 0x0; i < RESET_CODE; i++) {
Table[-FindEntry(-1, i) - 1] = (int16_t)i;
DictionaryO[i].Suffix = i;
}
DictionaryIndex = SYMBOL_BASE;
}
void WriteCode(FILE *Output, int32_t *Buffer, int32_t *BitsUsed, int32_t BitsPerCode, int32_t Code) {
(*Buffer) = (*Buffer) | (Code << (*BitsUsed));
(*BitsUsed) += BitsPerCode;
while ((*BitsUsed) > 0x7) {
putc((*Buffer) & 0xFF, Output);
(*Buffer) = (*Buffer) >> 0x8;
(*BitsUsed) -= 0x8;
}
}
int main(int argc, char** argv) {
int32_t BitsPerCode = 0x9;
int32_t BitsUsed = 0x0;
int32_t Buffer = 0x0;
int32_t Code = 0x0;
int32_t FoundIndex = -1;
FILE *Input = NULL;
FILE *Output = NULL;
int32_t Parent = -1;
printf("Compressing to file: %s\n", argv[2]);
Reset();
fopen_s(&Input, argv[1], "rb");
fopen_s(&Output, argv[2], "wb");
fseek(Input, 0, SEEK_SET);
WriteCode(Output, &Buffer, &BitsUsed, BitsPerCode, RESET_CODE);
while (true) {
Code = getc(Input);
if (Code < 0x0) break;
FoundIndex = FindEntry(Parent, Code);
if (FoundIndex < 0x0) { // NO_ENTRY
WriteCode(Output, &Buffer, &BitsUsed, BitsPerCode, Parent);
if (DictionaryIndex >= 0x1000) {
WriteCode(Output, &Buffer, &BitsUsed, BitsPerCode, RESET_CODE);
Reset();
BitsPerCode = 0x9;
} else {
AddEntry(Parent, Code, FoundIndex);
if (DictionaryIndex > (0x1 << BitsPerCode)) BitsPerCode += 0x1;
}
Parent = Code;
} else {
Parent = FoundIndex;
}
}
if (Parent >= 0x0) WriteCode(Output, &Buffer, &BitsUsed, BitsPerCode, Parent);
WriteCode(Output, &Buffer, &BitsUsed, BitsPerCode, EOF_CODE);
if (BitsUsed > 0x0) putc(Buffer & 0xFF, Output); // FLUSH_BUFFER
fclose(Input);
fclose(Output);
return 0x0;
}
I also made some minor adjustments that should make converting this to vb.net easier. As far I can tell the above code produces valid compressed data which I can decompress without issues. If I understand you correctly the the Table related code can be removed, right?