aboutsummaryrefslogtreecommitdiff
path: root/engines/lastexpress/game
diff options
context:
space:
mode:
authorLittleboy2012-07-31 00:58:37 -0400
committerLittleboy2012-07-31 01:19:05 -0400
commitacd4cf82e23493e357261eea564a5eaafb6e2647 (patch)
treec0d548ab0b472a52fbbdb7ee77a3f395bd2d561f /engines/lastexpress/game
parent4728505db288b8aa55453ada19fadde76d61ddb8 (diff)
downloadscummvm-rg350-acd4cf82e23493e357261eea564a5eaafb6e2647.tar.gz
scummvm-rg350-acd4cf82e23493e357261eea564a5eaafb6e2647.tar.bz2
scummvm-rg350-acd4cf82e23493e357261eea564a5eaafb6e2647.zip
LASTEXPRESS: Implement savegame write compression
Diffstat (limited to 'engines/lastexpress/game')
-rw-r--r--engines/lastexpress/game/savegame.cpp174
-rw-r--r--engines/lastexpress/game/savegame.h30
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];
};