Changeset - r14211:4e802fe0c855
[Not reviewed]
master
0 1 0
rubidium - 14 years ago 2010-01-10 15:35:13
rubidium@openttd.org
(svn r18772) -Feature-ish: allow user customisable compression levels for the zlib compression
1 file changed with 53 insertions and 22 deletions:
0 comments (0 inline, 0 general)
src/saveload/saveload.cpp
Show inline comments
 
@@ -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);
 
}
 

	
 
static bool InitLZO()
 
static bool InitLZO(byte compression)
 
{
 
	_sl.bufsize = 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);
 
}
 

	
 
static bool InitNoComp()
 
static bool InitNoComp(byte compression)
 
{
 
	_sl.bufsize = LZO_SIZE;
 
	_sl.buf = _sl.buf_ori = MallocT<byte>(LZO_SIZE);
 
@@ -1386,7 +1386,7 @@ static bool InitMem()
 

	
 
static z_stream _z;
 

	
 
static bool InitReadZlib()
 
static bool InitReadZlib(byte compression)
 
{
 
	memset(&_z, 0, sizeof(_z));
 
	if (inflateInit(&_z) != Z_OK) return false;
 
@@ -1426,10 +1426,10 @@ static void UninitReadZlib()
 
	free(_sl.buf_ori);
 
}
 

	
 
static bool InitWriteZlib()
 
static bool InitWriteZlib(byte compression)
 
{
 
	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.buf = _sl.buf_ori = MallocT<byte>(4096);
 
@@ -1586,29 +1586,33 @@ static void *IntToReference(size_t index
 

	
 
/** The format for a reader/writer type of a savegame */
 
struct SaveLoadFormat {
 
	const char *name;           ///< name of the compressor/decompressor (debug-only)
 
	uint32 tag;                 ///< the 4-letter tag by which it is identified in the savegame
 
	const char *name;                     ///< name of the compressor/decompressor (debug-only)
 
	uint32 tag;                           ///< the 4-letter tag by which it is identified in the savegame
 

	
 
	bool (*init_read)(byte compression);  ///< function executed upon initalization of the loader
 
	ReaderProc *reader;                   ///< function that loads the data from the file
 
	void (*uninit_read)();                ///< function executed when reading is finished
 

	
 
	bool (*init_read)();        ///< function executed upon initalization of the loader
 
	ReaderProc *reader;         ///< function that loads the data from the file
 
	void (*uninit_read)();      ///< function executed when reading is finished
 
	bool (*init_write)(byte compression); ///< function executed upon intialization of the saver
 
	WriterProc *writer;                   ///< function that saves the data to the file
 
	void (*uninit_write)();               ///< function executed when writing is done
 

	
 
	bool (*init_write)();       ///< function executed upon intialization of the saver
 
	WriterProc *writer;         ///< function that saves the data to the file
 
	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[] = {
 
#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
 
	{"lzo",    TO_BE32X('OTTD'), NULL,         NULL,       NULL,           NULL,          NULL,        NULL},
 
	{"lzo",    TO_BE32X('OTTD'), NULL,         NULL,       NULL,           NULL,          NULL,        NULL,            0, 0, 0},
 
#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)
 
	{"zlib",   TO_BE32X('OTTZ'), InitReadZlib, ReadZlib,   UninitReadZlib, InitWriteZlib, WriteZlib,   UninitWriteZlib},
 
	{"zlib",   TO_BE32X('OTTZ'), InitReadZlib, ReadZlib,   UninitReadZlib, InitWriteZlib, WriteZlib,   UninitWriteZlib, 0, 6, 9},
 
#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
 
};
 

	
 
@@ -1616,9 +1620,10 @@ static const SaveLoadFormat _saveload_fo
 
 * Return the savegameformat of the game. Whether it was created with ZLIB compression
 
 * uncompressed, or another type
 
 * @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
 
 */
 
static const SaveLoadFormat *GetSavegameFormat(const char *s)
 
static const SaveLoadFormat *GetSavegameFormat(char *s, byte *compression_level)
 
{
 
	const SaveLoadFormat *def = lastof(_saveload_formats);
 

	
 
@@ -1626,14 +1631,39 @@ static const SaveLoadFormat *GetSavegame
 
	while (!def->init_write) def--;
 

	
 
	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++) {
 
			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;
 
			}
 
		}
 

	
 
		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;
 
}
 

	
 
@@ -1707,13 +1737,14 @@ static SaveOrLoadResult SaveFileToDisk(b
 
{
 
	_sl.excpt_uninit = NULL;
 
	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! */
 
		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 (!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;
 
@@ -1901,7 +1932,7 @@ SaveOrLoadResult SaveOrLoad(const char *
 
				SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, err_str);
 
			}
 

	
 
			if (!fmt->init_read()) {
 
			if (!fmt->init_read(0)) {
 
				char err_str[64];
 
				snprintf(err_str, lengthof(err_str), "Initializing loader '%s' failed", fmt->name);
 
				SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, err_str);
0 comments (0 inline, 0 general)