[Add] A simple rle packer.
-- Code may be ugly.
This commit is contained in:
parent
29fc8f875c
commit
0b6e0cf094
@ -10,6 +10,7 @@ LIBS += -lGL \
|
|||||||
-lSDL_mixer \
|
-lSDL_mixer \
|
||||||
-lSDL_ttf \
|
-lSDL_ttf \
|
||||||
-lminizip
|
-lminizip
|
||||||
|
|
||||||
win32: {
|
win32: {
|
||||||
LIBS -= -lGL \
|
LIBS -= -lGL \
|
||||||
-lGLU
|
-lGLU
|
||||||
@ -41,6 +42,7 @@ HEADERS += ../src/Actor/Player.h \
|
|||||||
../src/System/Debug.h \
|
../src/System/Debug.h \
|
||||||
../src/System/ResourceManager.h \
|
../src/System/ResourceManager.h \
|
||||||
../src/System/Convert/str2int.h \
|
../src/System/Convert/str2int.h \
|
||||||
|
../src/System/Filesystem/SCpak.h \
|
||||||
../src/System/Filesystem/IOapi.h \
|
../src/System/Filesystem/IOapi.h \
|
||||||
../src/System/Filesystem/FileTimestampChecker.h \
|
../src/System/Filesystem/FileTimestampChecker.h \
|
||||||
../src/System/Convert/ConvertType.h \
|
../src/System/Convert/ConvertType.h \
|
||||||
@ -109,6 +111,7 @@ SOURCES += ../src/Actor/Player.cpp \
|
|||||||
../src/Sprite/Sprite.cpp \
|
../src/Sprite/Sprite.cpp \
|
||||||
../src/System/Debug.cpp \
|
../src/System/Debug.cpp \
|
||||||
../src/System/Convert/str2int.cpp \
|
../src/System/Convert/str2int.cpp \
|
||||||
|
../src/System/Filesystem/SCpak.cpp \
|
||||||
../src/System/Filesystem/FileTimestampChecker.cpp \
|
../src/System/Filesystem/FileTimestampChecker.cpp \
|
||||||
../src/System/Filesystem/OutputCompressedFileStream.cpp \
|
../src/System/Filesystem/OutputCompressedFileStream.cpp \
|
||||||
../src/System/Filesystem/InputCompressedFileStream.cpp \
|
../src/System/Filesystem/InputCompressedFileStream.cpp \
|
||||||
|
327
src/System/Filesystem/SCpak.cpp
Normal file
327
src/System/Filesystem/SCpak.cpp
Normal file
@ -0,0 +1,327 @@
|
|||||||
|
#include <assert.h>
|
||||||
|
#include "SCpak.h"
|
||||||
|
|
||||||
|
unsigned char scpak_bits = 8;
|
||||||
|
|
||||||
|
// These mark values 1-3 must be incremental!!!
|
||||||
|
unsigned char scpak_mark8_1 = 0xFA;
|
||||||
|
unsigned char scpak_mark8_2 = 0xFB;
|
||||||
|
unsigned char scpak_mark8_3 = 0xFC;
|
||||||
|
|
||||||
|
unsigned short scpak_mark16_1 = 0xA0EA;
|
||||||
|
unsigned short scpak_mark16_2 = 0xA0EB;
|
||||||
|
unsigned short scpak_mark16_3 = 0xA0EC;
|
||||||
|
|
||||||
|
void scpak_set_bits(unsigned char bits) {
|
||||||
|
if(bits == 8 || bits == 16) {
|
||||||
|
scpak_bits = bits;
|
||||||
|
} else {
|
||||||
|
// An error accured.
|
||||||
|
assert("scpak_set_bits - invalid parameter.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void scpak_set_8bit_params(unsigned char mark1, unsigned char mark2, unsigned char mark3) {
|
||||||
|
if(mark1 != mark2 && mark1 != mark3 && mark2 != mark3
|
||||||
|
&& mark2 == mark1 + 1 && mark3 == mark2 + 1) {
|
||||||
|
|
||||||
|
scpak_mark8_1 = mark1;
|
||||||
|
scpak_mark8_2 = mark2;
|
||||||
|
scpak_mark8_3 = mark3;
|
||||||
|
} else {
|
||||||
|
// Error!
|
||||||
|
assert(!"scpak_set_8bit_params - invalid parameter.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void scpak_set_16bit_params(unsigned short mark1, unsigned short mark2, unsigned short mark3) {
|
||||||
|
if(mark1 != mark2 && mark1 != mark3 && mark2 != mark3
|
||||||
|
&& mark2 == mark1 + 1 && mark3 == mark2 + 1) {
|
||||||
|
scpak_mark16_1 = mark1;
|
||||||
|
scpak_mark16_2 = mark2;
|
||||||
|
scpak_mark16_3 - mark3;
|
||||||
|
} else {
|
||||||
|
// Error!
|
||||||
|
assert(!"scpak_set_16bit_params - invalid parameter.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int scpak_pack_8b(int size, unsigned const char* src, unsigned char* dest) {
|
||||||
|
int s;
|
||||||
|
int d = 0;
|
||||||
|
short count = 0;
|
||||||
|
unsigned char prev;
|
||||||
|
|
||||||
|
if(size < 1) return 0;
|
||||||
|
|
||||||
|
prev = src[0];
|
||||||
|
|
||||||
|
for(s = 1; s < size; s++) {
|
||||||
|
if(src[s] == prev && count < 255) {
|
||||||
|
count++;
|
||||||
|
} else {
|
||||||
|
if(count <= 1 && (prev < scpak_mark8_1 || prev > scpak_mark8_3)) {
|
||||||
|
if(count == 0) {
|
||||||
|
dest[d] = prev;
|
||||||
|
d++;
|
||||||
|
} else {
|
||||||
|
dest[d] = prev;
|
||||||
|
dest[d+1] = prev;
|
||||||
|
d+=2;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(prev == 0) {
|
||||||
|
dest[d] = scpak_mark8_3;
|
||||||
|
dest[d+1] = (unsigned char)count;
|
||||||
|
d+=2;
|
||||||
|
} else {
|
||||||
|
if(count <= 15 && prev <=15) {
|
||||||
|
dest[d] = scpak_mark8_2;
|
||||||
|
dest[d+1] = prev | (count << 4);
|
||||||
|
d+=2;
|
||||||
|
} else {
|
||||||
|
dest[d] = scpak_mark8_1;
|
||||||
|
dest[d+1] = prev;
|
||||||
|
dest[d+2] = (unsigned char)count;
|
||||||
|
d+=3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
count = 0;
|
||||||
|
prev = src[s];
|
||||||
|
if(d >= size - 3) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(count <= 1 && (prev < scpak_mark8_1 || prev > scpak_mark8_3)) {
|
||||||
|
if(count == 0) {
|
||||||
|
dest[d] = prev;
|
||||||
|
d++;
|
||||||
|
} else {
|
||||||
|
dest[d] = prev;
|
||||||
|
dest[d+1] = prev;
|
||||||
|
d+=2;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(prev == 0) {
|
||||||
|
dest[d] = scpak_mark8_3;
|
||||||
|
dest[d+1] = (unsigned char)count;
|
||||||
|
d+=2;
|
||||||
|
} else {
|
||||||
|
if(count <= 15 && prev <= 15) {
|
||||||
|
dest[d] = scpak_mark8_2;
|
||||||
|
dest[d+1] = prev | (count << 4);
|
||||||
|
d+=2;
|
||||||
|
} else {
|
||||||
|
dest[d] = scpak_mark8_1;
|
||||||
|
dest[d+1] = prev;
|
||||||
|
dest[d+2] = (unsigned char) count;
|
||||||
|
d+=3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(d > size - 3) return 0;
|
||||||
|
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
int scpak_unpack_8b(int size, unsigned const char* src, unsigned char* dest, int maxDestSize) {
|
||||||
|
int s;
|
||||||
|
int d = 0;
|
||||||
|
short count = 0;
|
||||||
|
unsigned char rep;
|
||||||
|
|
||||||
|
if(size < 1) return 0;
|
||||||
|
|
||||||
|
if(maxDestSize == 0)
|
||||||
|
maxDestSize = 0x7fffffff - 256; // Should really be INT_MAX - 256. (This ok for 32 bit.)
|
||||||
|
|
||||||
|
for(s = 0; s < size; s++) {
|
||||||
|
rep = src[s];
|
||||||
|
if(rep < scpak_mark8_1 || rep > scpak_mark8_3) {
|
||||||
|
if(d >= maxDestSize) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
dest[d] = rep;
|
||||||
|
d++;
|
||||||
|
} else {
|
||||||
|
if(rep == scpak_mark8_1) {
|
||||||
|
rep = src[s+1];
|
||||||
|
count = src[s+2];
|
||||||
|
s+=2;
|
||||||
|
} else {
|
||||||
|
if(rep == scpak_mark8_3) {
|
||||||
|
rep = 0;
|
||||||
|
count = src[s+1];
|
||||||
|
s++;
|
||||||
|
} else {
|
||||||
|
rep = src[s+1] & 15;
|
||||||
|
count = src[s+1] >> 4;
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(d + count + 1 > maxDestSize) {
|
||||||
|
/*count = maxDestSize - d - 1;
|
||||||
|
for( ; count >= 0; count--) {
|
||||||
|
dest[d] = rep;
|
||||||
|
d++;
|
||||||
|
}
|
||||||
|
assert(d == maxDestSize);
|
||||||
|
break;*/
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
for( ; count >= 0; count--) {
|
||||||
|
dest[d] = rep;
|
||||||
|
d++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
int scpak_pack_16b(int size, unsigned const short* src, unsigned short* dest) {
|
||||||
|
int s;
|
||||||
|
int d = 0;
|
||||||
|
short count = 0;
|
||||||
|
unsigned short prev;
|
||||||
|
|
||||||
|
if(size < 1) return 0;
|
||||||
|
|
||||||
|
size = ((size+1) >> 1);
|
||||||
|
prev = src[0];
|
||||||
|
|
||||||
|
for(s = 1; s < size; s++) {
|
||||||
|
if(src[s] == prev && count < 255) {
|
||||||
|
count++;
|
||||||
|
} else {
|
||||||
|
if(count <= 1 && (prev < scpak_mark16_1 || prev > scpak_mark16_3)) {
|
||||||
|
if(count == 0) {
|
||||||
|
dest[d] = prev;
|
||||||
|
d++;
|
||||||
|
} else {
|
||||||
|
dest[d] = prev;
|
||||||
|
dest[d+1] = prev;
|
||||||
|
d+=2;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(prev == 0) {
|
||||||
|
dest[d] = scpak_mark16_3;
|
||||||
|
dest[d+1] = count;
|
||||||
|
d+=2;
|
||||||
|
} else {
|
||||||
|
if(count <= 255 && prev <= 255) {
|
||||||
|
dest[d] = scpak_mark16_2;
|
||||||
|
dest[d+1] = prev | (count << 8);
|
||||||
|
d+=2;
|
||||||
|
} else {
|
||||||
|
dest[d] = scpak_mark16_1;
|
||||||
|
dest[d+1] = prev;
|
||||||
|
dest[d+2] = count;
|
||||||
|
d+=3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
count = 0;
|
||||||
|
prev = src[s];
|
||||||
|
if(d >= size-3) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(count <= 1 && (prev < scpak_mark16_1 || prev > scpak_mark16_3)) {
|
||||||
|
if(count == 0) {
|
||||||
|
dest[d] = prev;
|
||||||
|
d++;
|
||||||
|
} else {
|
||||||
|
dest[d] = prev;
|
||||||
|
dest[d+1] = prev;
|
||||||
|
d+=2;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(prev == 0) {
|
||||||
|
dest[d] = scpak_mark16_3;
|
||||||
|
dest[d+1] = count;
|
||||||
|
d+=2;
|
||||||
|
} else {
|
||||||
|
if(count <= 255 && prev <= 255) {
|
||||||
|
dest[d] = scpak_mark16_2;
|
||||||
|
dest[d+1] = prev | (count << 8);
|
||||||
|
d+=2;
|
||||||
|
} else {
|
||||||
|
dest[d] = scpak_mark16_1;
|
||||||
|
dest[d+1] = prev;
|
||||||
|
dest[d+2] = count;
|
||||||
|
d+=3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(d > size-3) return 0;
|
||||||
|
|
||||||
|
return d*2;
|
||||||
|
}
|
||||||
|
|
||||||
|
int scpak_unpack_16b(int size, unsigned const short* src, unsigned short* dest, int maxDestSize) {
|
||||||
|
int s;
|
||||||
|
int d = 0;
|
||||||
|
short count = 0;
|
||||||
|
unsigned short rep;
|
||||||
|
|
||||||
|
if(size < 1) return 0;
|
||||||
|
|
||||||
|
assert((maxDestSize & 1) == 0);
|
||||||
|
|
||||||
|
maxDestSize = (maxDestSize >> 1);
|
||||||
|
if(maxDestSize == 0)
|
||||||
|
maxDestSize = 0x7fffffff - 256; // This should be INT_MAX - 256. (This is ok for 32 bit.)
|
||||||
|
|
||||||
|
size = ((size+1) >> 1);
|
||||||
|
|
||||||
|
for(s = 0; s < size; s++) {
|
||||||
|
rep = src[s];
|
||||||
|
if(rep < scpak_mark16_1 || rep > scpak_mark16_3) {
|
||||||
|
if(d > maxDestSize) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
dest[d] = rep;
|
||||||
|
d++;
|
||||||
|
} else {
|
||||||
|
if(rep == scpak_mark16_1) {
|
||||||
|
rep = src[s+1];
|
||||||
|
count = src[s+2];
|
||||||
|
s+=2;
|
||||||
|
} else {
|
||||||
|
if(rep == scpak_mark16_3) {
|
||||||
|
rep = 0;
|
||||||
|
count = src[s+1];
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(d + count + 1 > maxDestSize) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
for( ; count >= 0; count--) {
|
||||||
|
dest[d] = rep;
|
||||||
|
d++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return d*2;
|
||||||
|
}
|
||||||
|
|
||||||
|
int scpak_pack(int size, unsigned const char* src, unsigned char* dest) {
|
||||||
|
if(scpak_bits == 8) {
|
||||||
|
return scpak_pack_8b(size, src, dest);
|
||||||
|
} else {
|
||||||
|
if(scpak_bits == 16)
|
||||||
|
return scpak_pack_16b(size, (unsigned const short*)src, (unsigned short*)dest);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int scpak_unpack(int size, unsigned const char* src, unsigned char* dest, int maxDestSize) {
|
||||||
|
if(scpak_bits == 8) {
|
||||||
|
return scpak_unpack_8b(size, src, dest, maxDestSize);
|
||||||
|
} else {
|
||||||
|
if(scpak_bits == 16)
|
||||||
|
return scpak_unpack_16b(size, (unsigned const short*)src, (unsigned short*)dest, maxDestSize);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
23
src/System/Filesystem/SCpak.h
Normal file
23
src/System/Filesystem/SCpak.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// Size reflects the size of the unpacked source buffer. Destination should be
|
||||||
|
// slightly over allocated to be save. There is no predefined rule for the destination
|
||||||
|
// buffer over allocation, +16 bytes will be nice ;)
|
||||||
|
//
|
||||||
|
// If using 16 bit packing, buffer sizes must be padded to 2 byte size (pas source with zeroes!)
|
||||||
|
// returns 0 if packed data would have been larger than source, in which case you need to handle it
|
||||||
|
// differently..
|
||||||
|
extern int scpak_pack(int size, unsigned const char* src, unsigned char* dest);
|
||||||
|
|
||||||
|
// Size reflects the size of the unpacked source buffer, destination buffer should be large
|
||||||
|
// enough to fin the unpacked data (size of unpacked data should be written in the
|
||||||
|
// packfile or somewhere...) maxDestSize gives the maximum allowed size for unpacked data
|
||||||
|
// or if 0, no limit (could cause a buffer overflow...)
|
||||||
|
extern int scpak_unpack(int size, unsigned const char* src, unsigned char* dest, int maxDestSize = 0);
|
||||||
|
|
||||||
|
// 8 or 16 bit supported.
|
||||||
|
extern void scpak_set_bits(unsigned char bits);
|
||||||
|
|
||||||
|
extern void scpak_set_8bit_params(unsigned char mark1, unsigned char mark2, unsigned char mark3);
|
||||||
|
extern void scpak_set_16bit_params(unsigned short mark1, unsigned short mark2, unsigned short mark3);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user