1
0
Fork 0

(svn r18772) -Feature-ish: allow user customisable compression levels for the zlib compression

release/1.0
rubidium 2010-01-10 15:35:13 +00:00
parent 188c8ebd5c
commit aca2daf841
1 changed files with 53 additions and 22 deletions

View File

@ -1295,7 +1295,7 @@ static void WriteLZO(size_t size)
if (fwrite(out, outlen + sizeof(uint32) * 2, 1, _sl.fh) != 1) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE); if (fwrite(out, outlen + sizeof(uint32) * 2, 1, _sl.fh) != 1) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE);
} }
static bool InitLZO() static bool InitLZO(byte compression)
{ {
_sl.bufsize = LZO_SIZE; _sl.bufsize = LZO_SIZE;
_sl.buf = _sl.buf_ori = MallocT<byte>(LZO_SIZE); _sl.buf = _sl.buf_ori = MallocT<byte>(LZO_SIZE);
@ -1322,7 +1322,7 @@ static void WriteNoComp(size_t size)
if (fwrite(_sl.buf, 1, size, _sl.fh) != size) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE); if (fwrite(_sl.buf, 1, size, _sl.fh) != size) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE);
} }
static bool InitNoComp() static bool InitNoComp(byte compression)
{ {
_sl.bufsize = LZO_SIZE; _sl.bufsize = LZO_SIZE;
_sl.buf = _sl.buf_ori = MallocT<byte>(LZO_SIZE); _sl.buf = _sl.buf_ori = MallocT<byte>(LZO_SIZE);
@ -1386,7 +1386,7 @@ static bool InitMem()
static z_stream _z; static z_stream _z;
static bool InitReadZlib() static bool InitReadZlib(byte compression)
{ {
memset(&_z, 0, sizeof(_z)); memset(&_z, 0, sizeof(_z));
if (inflateInit(&_z) != Z_OK) return false; if (inflateInit(&_z) != Z_OK) return false;
@ -1426,10 +1426,10 @@ static void UninitReadZlib()
free(_sl.buf_ori); free(_sl.buf_ori);
} }
static bool InitWriteZlib() static bool InitWriteZlib(byte compression)
{ {
memset(&_z, 0, sizeof(_z)); memset(&_z, 0, sizeof(_z));
if (deflateInit(&_z, 6) != Z_OK) return false; if (deflateInit(&_z, compression) != Z_OK) return false;
_sl.bufsize = 4096; _sl.bufsize = 4096;
_sl.buf = _sl.buf_ori = MallocT<byte>(4096); _sl.buf = _sl.buf_ori = MallocT<byte>(4096);
@ -1589,26 +1589,30 @@ struct SaveLoadFormat {
const char *name; ///< name of the compressor/decompressor (debug-only) const char *name; ///< name of the compressor/decompressor (debug-only)
uint32 tag; ///< the 4-letter tag by which it is identified in the savegame uint32 tag; ///< the 4-letter tag by which it is identified in the savegame
bool (*init_read)(); ///< function executed upon initalization of the loader bool (*init_read)(byte compression); ///< function executed upon initalization of the loader
ReaderProc *reader; ///< function that loads the data from the file ReaderProc *reader; ///< function that loads the data from the file
void (*uninit_read)(); ///< function executed when reading is finished void (*uninit_read)(); ///< function executed when reading is finished
bool (*init_write)(); ///< function executed upon intialization of the saver bool (*init_write)(byte compression); ///< function executed upon intialization of the saver
WriterProc *writer; ///< function that saves the data to the file WriterProc *writer; ///< function that saves the data to the file
void (*uninit_write)(); ///< function executed when writing is done void (*uninit_write)(); ///< function executed when writing is done
byte min_compression; ///< the minimum compression level of this format
byte default_compression; ///< the default compression level of this format
byte max_compression; ///< the maximum compression level of this format
}; };
static const SaveLoadFormat _saveload_formats[] = { static const SaveLoadFormat _saveload_formats[] = {
#if defined(WITH_LZO) #if defined(WITH_LZO)
{"lzo", TO_BE32X('OTTD'), InitLZO, ReadLZO, UninitLZO, InitLZO, WriteLZO, UninitLZO}, {"lzo", TO_BE32X('OTTD'), InitLZO, ReadLZO, UninitLZO, InitLZO, WriteLZO, UninitLZO, 0, 0, 0},
#else #else
{"lzo", TO_BE32X('OTTD'), NULL, NULL, NULL, NULL, NULL, NULL}, {"lzo", TO_BE32X('OTTD'), NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0},
#endif #endif
{"none", TO_BE32X('OTTN'), InitNoComp, ReadNoComp, UninitNoComp, InitNoComp, WriteNoComp, UninitNoComp}, {"none", TO_BE32X('OTTN'), InitNoComp, ReadNoComp, UninitNoComp, InitNoComp, WriteNoComp, UninitNoComp, 0, 0, 0},
#if defined(WITH_ZLIB) #if defined(WITH_ZLIB)
{"zlib", TO_BE32X('OTTZ'), InitReadZlib, ReadZlib, UninitReadZlib, InitWriteZlib, WriteZlib, UninitWriteZlib}, {"zlib", TO_BE32X('OTTZ'), InitReadZlib, ReadZlib, UninitReadZlib, InitWriteZlib, WriteZlib, UninitWriteZlib, 0, 6, 9},
#else #else
{"zlib", TO_BE32X('OTTZ'), NULL, NULL, NULL, NULL, NULL, NULL}, {"zlib", TO_BE32X('OTTZ'), NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0},
#endif #endif
}; };
@ -1616,9 +1620,10 @@ static const SaveLoadFormat _saveload_formats[] = {
* Return the savegameformat of the game. Whether it was created with ZLIB compression * Return the savegameformat of the game. Whether it was created with ZLIB compression
* uncompressed, or another type * uncompressed, or another type
* @param s Name of the savegame format. If NULL it picks the first available one * @param s Name of the savegame format. If NULL it picks the first available one
* @param compression_level Output for telling what compression level we want.
* @return Pointer to SaveLoadFormat struct giving all characteristics of this type of savegame * @return Pointer to SaveLoadFormat struct giving all characteristics of this type of savegame
*/ */
static const SaveLoadFormat *GetSavegameFormat(const char *s) static const SaveLoadFormat *GetSavegameFormat(char *s, byte *compression_level)
{ {
const SaveLoadFormat *def = lastof(_saveload_formats); const SaveLoadFormat *def = lastof(_saveload_formats);
@ -1626,14 +1631,39 @@ static const SaveLoadFormat *GetSavegameFormat(const char *s)
while (!def->init_write) def--; while (!def->init_write) def--;
if (!StrEmpty(s)) { if (!StrEmpty(s)) {
/* Get the ":..." of the compression level out of the way */
char *complevel = strrchr(s, ':');
if (complevel != NULL) *complevel = '\0';
for (const SaveLoadFormat *slf = &_saveload_formats[0]; slf != endof(_saveload_formats); slf++) { for (const SaveLoadFormat *slf = &_saveload_formats[0]; slf != endof(_saveload_formats); slf++) {
if (slf->init_write != NULL && strcmp(s, slf->name) == 0) { if (slf->init_write != NULL && strcmp(s, slf->name) == 0) {
*compression_level = slf->default_compression;
if (complevel != NULL) {
/* There is a compression level in the string.
* First restore the : we removed to do proper name matching,
* then move the the begin of the actual version. */
*complevel = ':';
complevel++;
/* Get the version and determine whether all went fine. */
char *end;
long level = strtol(complevel, &end, 10);
if (end == complevel || level != Clamp(level, slf->min_compression, slf->max_compression)) {
ShowInfoF("Compression level '%s' is not valid.", complevel);
} else {
*compression_level = level;
}
}
return slf; return slf;
} }
} }
ShowInfoF("Savegame format '%s' is not available. Reverting to '%s'.", s, def->name); ShowInfoF("Savegame format '%s' is not available. Reverting to '%s'.", s, def->name);
/* Restore the string by adding the : back */
if (complevel != NULL) *complevel = ':';
} }
*compression_level = def->default_compression;
return def; return def;
} }
@ -1707,13 +1737,14 @@ static SaveOrLoadResult SaveFileToDisk(bool threaded)
{ {
_sl.excpt_uninit = NULL; _sl.excpt_uninit = NULL;
try { try {
const SaveLoadFormat *fmt = GetSavegameFormat(_savegame_format); byte compression;
const SaveLoadFormat *fmt = GetSavegameFormat(_savegame_format, &compression);
/* We have written our stuff to memory, now write it to file! */ /* We have written our stuff to memory, now write it to file! */
uint32 hdr[2] = { fmt->tag, TO_BE32(SAVEGAME_VERSION << 16) }; uint32 hdr[2] = { fmt->tag, TO_BE32(SAVEGAME_VERSION << 16) };
if (fwrite(hdr, sizeof(hdr), 1, _sl.fh) != 1) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE); if (fwrite(hdr, sizeof(hdr), 1, _sl.fh) != 1) SlError(STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE);
if (!fmt->init_write()) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize compressor"); if (!fmt->init_write(compression)) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize compressor");
{ {
uint i; uint i;
@ -1901,7 +1932,7 @@ SaveOrLoadResult SaveOrLoad(const char *filename, int mode, Subdirectory sb, boo
SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, err_str); SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, err_str);
} }
if (!fmt->init_read()) { if (!fmt->init_read(0)) {
char err_str[64]; char err_str[64];
snprintf(err_str, lengthof(err_str), "Initializing loader '%s' failed", fmt->name); snprintf(err_str, lengthof(err_str), "Initializing loader '%s' failed", fmt->name);
SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, err_str); SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, err_str);