[Scummvm-cvs-logs] SF.net SVN: scummvm:[40707] tools/trunk/compress_gob.cpp
strangerke at users.sourceforge.net
strangerke at users.sourceforge.net
Tue May 19 00:03:44 CEST 2009
Revision: 40707
http://scummvm.svn.sourceforge.net/scummvm/?rev=40707&view=rev
Author: strangerke
Date: 2009-05-18 22:03:44 +0000 (Mon, 18 May 2009)
Log Message:
-----------
Tools / Gob - Very early implementation of the compression (STK10). Still not 100% OK as some files are 4 to 10 bytes different to the original...
Modified Paths:
--------------
tools/trunk/compress_gob.cpp
Modified: tools/trunk/compress_gob.cpp
===================================================================
--- tools/trunk/compress_gob.cpp 2009-05-18 21:56:09 UTC (rev 40706)
+++ tools/trunk/compress_gob.cpp 2009-05-18 22:03:44 UTC (rev 40707)
@@ -36,14 +36,15 @@
};
Chunk *readChunkConf (FILE *gobconf, uint16 &chunkCount);
-void *rewriteHeader (FILE *stk, uint16 chunkCount, Chunk *chunks);
-void *writeBody (FILE *stk, uint16 chunkcount, Chunk *chunks);
+void writeEmptyHeader (FILE *stk, uint16 chunkCount);
+void writeBody (FILE *stk, uint16 chunkcount, Chunk *chunks);
+uint32 writeBodyFile (FILE *stk, FILE *src);
+uint32 writeBodyPackFile (FILE *stk, FILE *src);
+void rewriteHeader (FILE *stk, uint16 chunkCount, Chunk *chunks);
+bool checkDico(byte *unpacked, uint32 unpackedIndex, int32 counter, byte *dico, uint16 &pos, uint8 &length);
-Chunk *readChunkList(FILE *stk, FILE *gobConf);
+byte *packData(byte *src, uint32 &size);
-void extractChunks(FILE *stk, Chunk *chunks);
-byte *unpackData(byte *src, uint32 &size);
-
int main(int argc, char **argv) {
char *outFilename;
char *tmpStr;
@@ -75,10 +76,12 @@
chunks = readChunkConf(gobConf, chunkCount);
fclose(gobConf);
-
+
+ writeEmptyHeader (stk, chunkCount);
writeBody(stk, chunkCount, chunks);
rewriteHeader(stk, chunkCount, chunks);
+ fflush(stk);
delete chunks;
fclose(stk);
return 0;
@@ -103,8 +106,8 @@
// first read (signature, not yet used)
fscanf(gobConf, "%s", buffer);
+
fscanf(gobConf, "%s", buffer);
-
while (!feof(gobConf)) {
strcpy(curChunk->name, buffer);
fscanf(gobConf, "%s", buffer);
@@ -123,37 +126,65 @@
return chunks;
}
-void *writeBody(FILE *stk, uint16 chunkCount, Chunk *chunks) {
- Chunk *curChunk = chunks;
- FILE *src;
- char buffer[4096];
+void writeEmptyHeader (FILE *stk, uint16 chunkCount) {
int count;
+// Write empty header
for (count = 0; count < 2 + (chunkCount * 22); count++)
fputc(0, stk);
- while (curChunk) {
+ return;
+}
+
+void writeBody (FILE *stk, uint16 chunkCount, Chunk *chunks) {
+ Chunk *curChunk = chunks;
+ FILE *src;
+ uint32 realSize;
+ int count;
+ char buffer[4096];
+ uint32 tmpSize;
+
+ while(curChunk) {
if (!(src = fopen(curChunk->name, "rb")))
error("Couldn't open conf file \"%s\"", curChunk->name);
- curChunk->size = 0;
+ realSize = fileSize(src);
- do {
- count = fread(buffer, 1, 4096, src);
- fwrite(buffer, 1, count, stk);
- curChunk->size += count;
- } while (count == 4096);
-
- printf("File: %s - Size: %d\n", curChunk->name, curChunk->size);
+ if (curChunk->packed)
+ curChunk->size = writeBodyPackFile(stk, src);
+ else {
+ tmpSize = 0;
+ do {
+ count = fread(buffer, 1, 4096, src);
+ fwrite(buffer, 1, count, stk);
+ tmpSize += count;
+ } while (count == 4096);
+ curChunk->size = tmpSize;
+ }
+
+// printf("File: %s inside STK size: %d original size: %d\n", curChunk->name, curChunk->size, realSize);
fclose(src);
-
curChunk = curChunk->next;
}
+ return;
+}
- return 0;
+uint32 writeBodyFile (FILE *stk, FILE *src) {
+ int count;
+ char buffer[4096];
+ uint32 tmpSize;
+
+ tmpSize = 0;
+ do {
+ count = fread(buffer, 1, 4096, src);
+ fwrite(buffer, 1, count, stk);
+ tmpSize += count;
+ } while (count == 4096);
+ return tmpSize;
}
-void *rewriteHeader(FILE *stk, uint16 chunkCount, Chunk *chunks) {
+
+void rewriteHeader (FILE *stk, uint16 chunkCount, Chunk *chunks) {
uint16 i;
char buffer[1024];
Chunk *curChunk = chunks;
@@ -174,7 +205,6 @@
buffer[0] = chunkCount & 0xFF;
buffer[1] = chunkCount >> 8;
fwrite(buffer, 1, 2, stk);
-
// TODO : Implement STK21
while (curChunk) {
for (i = 0; i < 13; i++)
@@ -193,14 +223,157 @@
buffer[6] = filPos >> 16;
buffer[7] = filPos >> 24;
-// Compression not yet implemented => always uncompressed
-// buffer[8]=curChunk->packed?'\1':'\0';
- buffer[8] = '\0';
+ buffer[8] = curChunk->packed ? 0x1 : 0x0;
+
fwrite(buffer, 1, 9, stk);
filPos += curChunk->size;
curChunk = curChunk->next;
}
+ return;
+}
- return 0;
+// Some LZ77-variant
+uint32 writeBodyPackFile (FILE *stk, FILE *src) {
+ byte dico[4114];
+ byte writeBuffer[17];
+ uint32 counter;
+ uint16 dicoIndex;
+ uint32 unpackedIndex, size;
+ uint8 cmd;
+ uint8 buffIndex, cpt, i;
+ uint16 resultcheckpos;
+ byte resultchecklength;
+
+ size = fileSize(src);
+
+ byte *unpacked = new byte [size + 1];
+ for (int i = 0; i < 4096 - 18; i++)
+ dico[i] = 0x20;
+
+ fread(unpacked, 1, size, src);
+
+ writeBuffer[0] = size & 0xFF;
+ writeBuffer[1] = size >> 8;
+ writeBuffer[2] = size >> 16;
+ writeBuffer[3] = size >> 24;
+ fwrite(writeBuffer, 1, 4, stk);
+
+// TODO : check size, if too small, handle correctly
+
+ dicoIndex = 4078;
+ dico[dicoIndex] = unpacked[0];
+ dico[dicoIndex+1] = unpacked[1];
+ dico[dicoIndex+2] = unpacked[2];
+ dicoIndex += 3;
+
+//writeBuffer[0] is reserved for the command byte
+ writeBuffer[1] = unpacked[0];
+ writeBuffer[2] = unpacked[1];
+ writeBuffer[3] = unpacked[2];
+
+ counter = size - 3;
+ unpackedIndex = 3;
+ cpt = 3;
+ buffIndex = 4;
+ cmd = (1 << 3) - 1;
+
+ size=4;
+ resultcheckpos = 0;
+ resultchecklength = 0;
+
+ while (counter>0) {
+ if (!checkDico(unpacked, unpackedIndex, counter, dico, resultcheckpos, resultchecklength)) {
+ dico[dicoIndex] = unpacked[unpackedIndex];
+ writeBuffer[buffIndex] = unpacked[unpackedIndex];
+ cmd |= (1 << cpt);
+ unpackedIndex++;
+ dicoIndex = (dicoIndex + 1) % 4096;
+ buffIndex++;
+ counter--;
+ } else {
+// Copy the string in the dictionary
+ for (i=0; i < resultchecklength; i++)
+ dico[((dicoIndex + i) % 4096)] = dico[((resultcheckpos + i) % 4096)];
+
+// Write the copy string command
+ writeBuffer[buffIndex] = resultcheckpos & 0xFF;
+ writeBuffer[buffIndex + 1] = ((resultcheckpos & 0x0F00) >> 4) + (resultchecklength - 3);
+// printf("ptr 0x%x cpt 0x%x -> 0x%x 0x%x\n", resultcheckpos, resultchecklength, (byte) writeBuffer[buffIndex], writeBuffer[buffIndex + 1]);
+
+ unpackedIndex += resultchecklength;
+ dicoIndex = (dicoIndex + resultchecklength) % 4096;
+ resultcheckpos = (resultcheckpos + resultchecklength) % 4096;
+
+ buffIndex += 2;
+ counter -= resultchecklength;
+ }
+
+
+ if ((cpt == 7) | (counter == 0)) {
+ writeBuffer[0] = cmd;
+ fwrite(writeBuffer, 1, buffIndex, stk);
+ size += buffIndex;
+ buffIndex = 1;
+ cmd = 0;
+ cpt = 0;
+ } else
+ cpt++;
+ }
+
+// filDico = fopen("dico.gob", "wb");
+// fwrite(dico, 1, 4114, filDico);
+// fclose(filDico);
+
+ delete[] unpacked;
+ return size;
}
+
+bool checkDico(byte *unpacked, uint32 unpackedIndex, int32 counter, byte *dico, uint16 &pos, uint8 &length) {
+ uint16 tmpPos, bestPos;
+ uint8 tmpLength, bestLength, i;
+// FILE *filDico;
+
+ bestPos = 0;
+ bestLength = 0;
+
+ if (counter < 3)
+ return false;
+
+ for (tmpPos = 0; tmpPos < 0x1000; tmpPos++) {
+ tmpLength = 0;
+ for (i = 0; ((i < 8) & (i < counter)); i++)
+ if (unpacked[unpackedIndex + i] == dico[(tmpPos + i) % 4096])
+ tmpLength++;
+ else
+ break;
+ if (tmpLength > bestLength) {
+ bestLength = tmpLength;
+ bestPos = tmpPos;
+ }
+
+ if (bestLength == 8)
+ break;
+ }
+
+ pos = bestPos;
+ length = bestLength;
+
+ if (bestLength > 2) {
+// filDico = fopen("dico.gob", "wb");
+// fwrite(dico, 1, 4114, filDico);
+// fclose(filDico);
+// printf("Found ");
+// for (i = 0; i < bestLength; i++)
+// printf("0x%x ", dico[(bestPos + i) % 4096]);
+//
+// printf("while looking for ");
+// for (i = 0; i < bestLength; i++)
+// printf("0x%x ", unpacked[unpackedIndex + i]);
+// printf("org pos 0x%x at dico pos 0x%x\n", unpackedIndex, bestPos);
+//
+ return true;
+ }
+ else
+ return false;
+}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
More information about the Scummvm-git-logs
mailing list