diff options
| author | Littleboy | 2012-07-31 00:58:37 -0400 | 
|---|---|---|
| committer | Littleboy | 2012-07-31 01:19:05 -0400 | 
| commit | acd4cf82e23493e357261eea564a5eaafb6e2647 (patch) | |
| tree | c0d548ab0b472a52fbbdb7ee77a3f395bd2d561f | |
| parent | 4728505db288b8aa55453ada19fadde76d61ddb8 (diff) | |
| download | scummvm-rg350-acd4cf82e23493e357261eea564a5eaafb6e2647.tar.gz scummvm-rg350-acd4cf82e23493e357261eea564a5eaafb6e2647.tar.bz2 scummvm-rg350-acd4cf82e23493e357261eea564a5eaafb6e2647.zip  | |
LASTEXPRESS: Implement savegame write compression
| -rw-r--r-- | engines/lastexpress/game/savegame.cpp | 174 | ||||
| -rw-r--r-- | engines/lastexpress/game/savegame.h | 30 | 
2 files changed, 191 insertions, 13 deletions
diff --git a/engines/lastexpress/game/savegame.cpp b/engines/lastexpress/game/savegame.cpp index 8eda463f81..54ba45e25e 100644 --- a/engines/lastexpress/game/savegame.cpp +++ b/engines/lastexpress/game/savegame.cpp @@ -73,6 +73,10 @@ uint32 SavegameStream::read(void *dataPtr, uint32 dataSize) {  		return readCompressed(dataPtr, dataSize);  #endif +	return readUncompressed(dataPtr, dataSize); +} + +uint32 SavegameStream::readUncompressed(void *dataPtr, uint32 dataSize) {  	if ((int32)dataSize > size() - pos()) {  		dataSize = size() - pos();  		_eos = true; @@ -84,18 +88,182 @@ uint32 SavegameStream::read(void *dataPtr, uint32 dataSize) {  	return dataSize;  } -void SavegameStream::process() { +void SavegameStream::writeBuffer(uint8 value, bool onlyValue) { +	if (_bufferOffset == -1) +		_bufferOffset = 0; + +	if (_bufferOffset == 256) { +		_bufferOffset = 0; +		Common::MemoryWriteStreamDynamic::write(_buffer, 256); +	} + +	if (onlyValue || value < 0xFB) +		_buffer[_bufferOffset] = value; +	else +		_buffer[_bufferOffset] = 0xFE; + +	_offset++; +	_bufferOffset++; + +	if (!onlyValue && value >= 0xFB) +	{ +		if (_bufferOffset == 256) { +			_bufferOffset = 0; +			Common::MemoryWriteStreamDynamic::write(_buffer, 256); +		} + +		_buffer[_bufferOffset] = value; + +		_bufferOffset++; +		_offset++; +	} +} + +uint32 SavegameStream::process() {  	_enableCompression = !_enableCompression; -	// TODO Flush compression buffer +#if DISABLE_COMPRESSION +	return 0; +#else +	switch (_status) { +	default: +		break; + +	case kStatusReading: +		_status = kStatusReady; +		if (_bufferOffset != -1 && _bufferOffset != 256) { +			seek(_bufferOffset - 256, SEEK_CUR); +			_bufferOffset = -1; +		} +		break; + +	case kStatusWriting: +		switch (_valueCount) { +		default: +			break; + +		case 1: +			writeBuffer(_previousValue, false); +			break; + +		case 2: +			if (_previousValue) { +				writeBuffer(0xFF, true); +				writeBuffer(_repeatCount, true); +				writeBuffer(_previousValue, true); +				break; +			} + +			if (_repeatCount == 3) { +				writeBuffer(0xFB, true); +				break; +			} + +			if (_repeatCount == -1) { +				writeBuffer(0xFC, true); +				break; +			} + +			writeBuffer(0xFD, true); +			writeBuffer(_repeatCount, true); +			break; +		} + +		if (_bufferOffset != -1 && _bufferOffset != 0) { +			Common::MemoryWriteStreamDynamic::write(_buffer, _bufferOffset); +			_bufferOffset = -1; +		} +		break; +	} + +	_status = kStatusReady; +	_valueCount = 0; +	uint32 offset = _offset; +	_offset = 0; +	return offset; +#endif  }  uint32 SavegameStream::writeCompressed(const void *dataPtr, uint32 dataSize) { -	error("[SavegameStream::writeCompressed] Compression not implemented!"); +	if (_status == kStatusReading) +		error("[SavegameStream::writeCompressed] Error: Compression buffer is in read mode."); + +	_status = kStatusWriting; +	byte *data = (byte *)dataPtr; + +	while (dataSize) { +		switch (_valueCount) { +		default: +			error("[SavegameStream::writeCompressed] Invalid value count (%d)", _valueCount); + +		case 0: +			_previousValue = *data++; +			_valueCount = 1; +			break; + +		case 1: +			if (*data != _previousValue) { +				writeBuffer(_previousValue, false); +				_previousValue = *data; +			} else { +				_valueCount = 2; +				_repeatCount = 2; +			} + +			++data; +			break; + +		case 2: +			if (*data != _previousValue || _repeatCount >= 255) { +				if (_previousValue) { +					writeBuffer(0xFF, true); +					writeBuffer(_repeatCount, true); +					writeBuffer(_previousValue, true); + +					_previousValue = *data++; +					_valueCount = 1; +					break; +				} + +				if (_repeatCount == 3) { +					writeBuffer(0xFB, true); + +					_previousValue = *data++; +					_valueCount = 1; +					break; +				} + +				if (_repeatCount == -1) { +					writeBuffer(0xFC, true); + +					_previousValue = *data++; +					_valueCount = 1; +					break; +				} + +				writeBuffer(0xFD, true); +				writeBuffer(_repeatCount, true); + +				_previousValue = *data++; +				_valueCount = 1; +			} + +			++data; +			++_repeatCount; +			break; +		} + +		--dataSize; +	} + +	return _offset;  }  uint32 SavegameStream::readCompressed(void *dataPtr, uint32 dataSize) { +	if (_status == kStatusWriting) +		error("[SavegameStream::writeCompressed] Error: Compression buffer is in write mode."); +  	error("[SavegameStream::readCompressed] Compression not implemented!");  } diff --git a/engines/lastexpress/game/savegame.h b/engines/lastexpress/game/savegame.h index dc16a16728..8866fd330d 100644 --- a/engines/lastexpress/game/savegame.h +++ b/engines/lastexpress/game/savegame.h @@ -95,9 +95,9 @@ public:  		_bufferOffset = -1;  		_valueCount = 0;  		_previousValue = 0; -		_field_15F = 0; +		_repeatCount = 0;  		_offset = 0; -		_status = 0; +		_status = kStatusReady;  		memset(_buffer, 0, 256);  	} @@ -109,24 +109,34 @@ public:  	uint32 read(void *dataPtr, uint32 dataSize);  	uint32 write(const void *dataPtr, uint32 dataSize); -	void process(); +	uint32 process();  private: +	enum CompressedStreamStatus { +		kStatusReady, +		kStatusReading, +		kStatusWriting +	}; + +	uint32 readUncompressed(void *dataPtr, uint32 dataSize); +  	// Compressed data  	uint32 writeCompressed(const void *dataPtr, uint32 dataSize);  	uint32 readCompressed(void *dataPtr, uint32 dataSize); +	void writeBuffer(uint8 value, bool onlyValue); +  private:  	bool _eos;  	// Compression handling -	bool _enableCompression; -	int  _bufferOffset; -	int  _valueCount; -	byte _previousValue; -	byte _field_15F; -	int  _offset; -	int  _status; +	bool                   _enableCompression; +	int16                  _bufferOffset; +	byte                   _valueCount; +	byte                   _previousValue; +	int16                  _repeatCount; +	uint32                 _offset; +	CompressedStreamStatus _status;  	byte _buffer[256];  };  | 
