aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSven Hesse2011-01-21 19:15:10 +0000
committerSven Hesse2011-01-21 19:15:10 +0000
commit9e338a170f8253fea2accf2b95f44806dfdf24f8 (patch)
treee759a9c97e30fbe123112639a881ef0a3b6d1981
parent0e33dd91645bb26c51731cc79b2f142b3883047c (diff)
downloadscummvm-rg350-9e338a170f8253fea2accf2b95f44806dfdf24f8.tar.gz
scummvm-rg350-9e338a170f8253fea2accf2b95f44806dfdf24f8.tar.bz2
scummvm-rg350-9e338a170f8253fea2accf2b95f44806dfdf24f8.zip
GOB: Add support for saving true color sprites
Not exactly the "nice", since up-depthing the sprite data to 24bit happens after it has been adapted to the current system's color format, so we're going to gradually lose precision when the save gets passed around different systems. Still, this is the least headachy solution, I guess... svn-id: r55383
-rw-r--r--engines/gob/save/savefile.cpp104
-rw-r--r--engines/gob/save/savefile.h12
-rw-r--r--engines/gob/save/savehandler.cpp44
-rw-r--r--engines/gob/save/savehandler.h7
-rw-r--r--engines/gob/save/saveload_inca2.cpp2
-rw-r--r--engines/gob/save/saveload_v3.cpp2
6 files changed, 126 insertions, 45 deletions
diff --git a/engines/gob/save/savefile.cpp b/engines/gob/save/savefile.cpp
index 3869ea2def..d472ef600b 100644
--- a/engines/gob/save/savefile.cpp
+++ b/engines/gob/save/savefile.cpp
@@ -85,6 +85,16 @@ bool SaveHeader::verify(Common::ReadStream &stream) const {
return !stream.err();
}
+bool SaveHeader::operator==(const SaveHeader &header) const {
+ return (_type == header._type) &&
+ (_version == header._version) &&
+ (_size == header._size);
+}
+
+bool SaveHeader::operator!=(const SaveHeader &header) const {
+ return !(*this == header);
+}
+
bool SaveHeader::verifyReadSize(Common::ReadStream &stream) {
// Compare the header with the stream's content, expect for the size
@@ -263,21 +273,29 @@ bool SavePartVars::writeInto(uint32 var, uint32 offset, uint32 size) const {
return true;
}
-SavePartSprite::SavePartSprite(uint32 width, uint32 height) {
+SavePartSprite::SavePartSprite(uint32 width, uint32 height, bool trueColor) {
assert((width > 0) && (height > 0));
_width = width;
_height = height;
+ _oldFormat = false;
+ _trueColor = trueColor;
+
_header.setType(kID);
_header.setVersion(kVersion);
- // width + height + sprite + palette
- _header.setSize(4 + 4 + _width * _height + 768);
- _dataSprite = new byte[_width * _height];
+ _spriteSize = _width * _height;
+ if (_trueColor)
+ _spriteSize *= 3;
+
+ // width + height + color + sprite + palette
+ _header.setSize(4 + 4 + 1 + _spriteSize + 768);
+
+ _dataSprite = new byte[_spriteSize];
_dataPalette = new byte[768];
- memset(_dataSprite, 0, _width * _height);
+ memset(_dataSprite, 0, _spriteSize);
memset(_dataPalette, 0, 768);
}
@@ -287,8 +305,28 @@ SavePartSprite::~SavePartSprite() {
}
bool SavePartSprite::read(Common::ReadStream &stream) {
- if (!_header.verify(stream))
- return false;
+ SaveHeader header;
+ header.read(stream);
+
+ if (_header != header) {
+ if (!_trueColor) {
+ // Header validation failed, trying again with the old version
+
+ _header.setVersion(1);
+ _header.setSize(_header.getSize() - 1);
+
+ if (_header != header)
+ // Nope, isn't it either
+ return false;
+
+ _oldFormat = true;
+
+ _header.setVersion(kVersion);
+ _header.setSize(_header.getSize() + 1);
+
+ } else
+ return false;
+ }
// The sprite's dimensions have to fit
if (stream.readUint32LE() != _width)
@@ -296,8 +334,13 @@ bool SavePartSprite::read(Common::ReadStream &stream) {
if (stream.readUint32LE() != _height)
return false;
+ // If it's in the current format, the true color flag has to be the same too
+ if (!_oldFormat)
+ if (stream.readByte() != _trueColor)
+ return false;
+
// Sprite data
- if (stream.read(_dataSprite, _width * _height) != (_width * _height))
+ if (stream.read(_dataSprite, _spriteSize) != _spriteSize)
return false;
// Palette data
@@ -314,9 +357,10 @@ bool SavePartSprite::write(Common::WriteStream &stream) const {
// The sprite's dimensions
stream.writeUint32LE(_width);
stream.writeUint32LE(_height);
+ stream.writeByte(_trueColor);
// Sprite data
- if (stream.write(_dataSprite, _width * _height) != (_width * _height))
+ if (stream.write(_dataSprite, _spriteSize) != _spriteSize)
return false;
// Palette data
@@ -339,17 +383,29 @@ bool SavePartSprite::readSprite(const Surface &sprite) {
if (((uint32)sprite.getHeight()) != _height)
return false;
- // Only 8bit sprites supported for now
- if (sprite.getBPP() != 1)
- return false;
+ if (_trueColor) {
+ if (sprite.getBPP() <= 1)
+ return false;
- memcpy(_dataSprite, sprite.getData(), _width * _height);
+ Graphics::PixelFormat pixelFormat = g_system->getScreenFormat();
+
+ byte *data = _dataSprite;
+ ConstPixel pixel = sprite.get();
+ for (uint32 i = 0; i < (_width * _height); i++, ++pixel, data += 3)
+ pixelFormat.colorToRGB(pixel.get(), data[0], data[1], data[2]);
+
+ } else {
+ if (sprite.getBPP() != 1)
+ return false;
+
+ memcpy(_dataSprite, sprite.getData(), _width * _height);
+ }
return true;
}
bool SavePartSprite::readSpriteRaw(const byte *data, uint32 size) {
- if (size != (_width * _height))
+ if (size != _spriteSize)
return false;
memcpy(_dataSprite, data, size);
@@ -369,11 +425,23 @@ bool SavePartSprite::writeSprite(Surface &sprite) const {
if (((uint32)sprite.getHeight()) != _height)
return false;
- // Only 8bit sprites supported for now
- if (sprite.getBPP() != 1)
- return false;
+ if (_trueColor) {
+ if (sprite.getBPP() <= 1)
+ return false;
+
+ Graphics::PixelFormat pixelFormat = g_system->getScreenFormat();
- memcpy(sprite.getData(), _dataSprite, _width * _height);
+ const byte *data = _dataSprite;
+ Pixel pixel = sprite.get();
+ for (uint32 i = 0; i < (_width * _height); i++, ++pixel, data += 3)
+ pixel.set(pixelFormat.RGBToColor(data[0], data[1], data[2]));
+
+ } else {
+ if (sprite.getBPP() != 1)
+ return false;
+
+ memcpy(sprite.getData(), _dataSprite, _spriteSize);
+ }
return true;
}
diff --git a/engines/gob/save/savefile.h b/engines/gob/save/savefile.h
index 980616bb74..eeee03847a 100644
--- a/engines/gob/save/savefile.h
+++ b/engines/gob/save/savefile.h
@@ -53,6 +53,9 @@ public:
SaveHeader(uint32 type = 0, uint32 version = 0, uint32 size = 0);
+ bool operator==(const SaveHeader &header) const;
+ bool operator!=(const SaveHeader &header) const;
+
/** Read the header out of a stream into this class. */
bool read(Common::ReadStream &stream);
/** Read the header out of a stream and checks it against this class's contents. */
@@ -151,10 +154,10 @@ private:
/** A save part holding a sprite. */
class SavePartSprite : public SavePart {
public:
- static const uint32 kVersion = 1;
+ static const uint32 kVersion = 2;
static const uint32 kID = MKID_BE('SPRT');
- SavePartSprite(uint32 width, uint32 height);
+ SavePartSprite(uint32 width, uint32 height, bool trueColor = false);
~SavePartSprite();
bool read(Common::ReadStream &stream);
@@ -177,6 +180,11 @@ private:
uint32 _width;
uint32 _height;
+ uint32 _spriteSize;
+
+ bool _oldFormat;
+ bool _trueColor;
+
byte *_dataSprite;
byte *_dataPalette;
};
diff --git a/engines/gob/save/savehandler.cpp b/engines/gob/save/savehandler.cpp
index 8a20665140..848578abce 100644
--- a/engines/gob/save/savehandler.cpp
+++ b/engines/gob/save/savehandler.cpp
@@ -279,12 +279,11 @@ bool TempSpriteHandler::load(int16 dataVar, int32 size, int32 offset) {
}
bool TempSpriteHandler::save(int16 dataVar, int32 size, int32 offset) {
- SurfacePtr sprite;
-
if (isDummy(size))
return true;
- if (!createSprite(dataVar, size, offset, &sprite))
+ SurfacePtr sprite = createSprite(dataVar, size, offset);
+ if (!sprite)
return false;
// Save the sprite
@@ -292,42 +291,47 @@ bool TempSpriteHandler::save(int16 dataVar, int32 size, int32 offset) {
return false;
// Handle palette
- if (usesPalette(size)) {
+ if (usesPalette(size))
if (!_sprite->readPalette((const byte *)_vm->_global->_pPaletteDesc->vgaPal))
return false;
- }
return true;
}
-bool TempSpriteHandler::createSprite(int16 dataVar, int32 size,
- int32 offset, SurfacePtr *sprite) {
-
+bool TempSpriteHandler::create(uint32 width, uint32 height, bool trueColor) {
delete _sprite;
_sprite = 0;
+ // Create a new temporary sprite
+ _sprite = new SavePartSprite(width, height, trueColor);
+
+ return true;
+}
+
+bool TempSpriteHandler::createFromSprite(int16 dataVar, int32 size, int32 offset) {
+ return createSprite(dataVar, size, offset) != 0;
+}
+
+SurfacePtr TempSpriteHandler::createSprite(int16 dataVar, int32 size, int32 offset) {
+ SurfacePtr sprt;
+
// Sprite requested?
if (!isSprite(size))
- return false;
+ return sprt;
// Index sane?
int index = getIndex(size);
if ((index < 0) || (index >= SPRITES_COUNT))
- return false;
-
- SurfacePtr sprt = _vm->_draw->_spritesArray[index];
+ return sprt;
// Sprite exists?
- if (!sprt)
- return false;
+ if (!(sprt = _vm->_draw->_spritesArray[index]))
+ return sprt;
- // Create a new temporary sprite
- _sprite = new SavePartSprite(sprt->getWidth(), sprt->getHeight());
+ if (!create(sprt->getWidth(), sprt->getHeight(), sprt->getBPP() > 1))
+ sprt.reset();
- if (sprite)
- *sprite = sprt;
-
- return true;
+ return sprt;
}
// A size of 0 means no proper sprite should be saved/loaded,
diff --git a/engines/gob/save/savehandler.h b/engines/gob/save/savehandler.h
index c6370947e2..51fbad0b98 100644
--- a/engines/gob/save/savehandler.h
+++ b/engines/gob/save/savehandler.h
@@ -140,9 +140,8 @@ public:
bool load(int16 dataVar, int32 size, int32 offset);
bool save(int16 dataVar, int32 size, int32 offset);
- /** Create a fitting sprite. */
- bool createSprite(int16 dataVar, int32 size,
- int32 offset, SurfacePtr *sprite = 0);
+ bool create(uint32 width, uint32 height, bool trueColor);
+ bool createFromSprite(int16 dataVar, int32 size, int32 offset);
protected:
SavePartSprite *_sprite;
@@ -155,6 +154,8 @@ protected:
static int getIndex(int32 size);
/** Determine whether the palette should be used too. */
static bool usesPalette(int32 size);
+
+ SurfacePtr createSprite(int16 dataVar, int32 size, int32 offset);
};
/** A handler for notes. */
diff --git a/engines/gob/save/saveload_inca2.cpp b/engines/gob/save/saveload_inca2.cpp
index e32c4fd25c..68c76c3f2b 100644
--- a/engines/gob/save/saveload_inca2.cpp
+++ b/engines/gob/save/saveload_inca2.cpp
@@ -322,7 +322,7 @@ bool SaveLoad_Inca2::ScreenshotHandler::load(int16 dataVar, int32 size, int32 of
return false;
}
- if (!TempSpriteHandler::createSprite(dataVar, size, offset))
+ if (!TempSpriteHandler::createFromSprite(dataVar, size, offset))
return false;
if (!_gameHandler->loadScreenshot(slot, _sprite))
diff --git a/engines/gob/save/saveload_v3.cpp b/engines/gob/save/saveload_v3.cpp
index bb60f94725..098b8e1160 100644
--- a/engines/gob/save/saveload_v3.cpp
+++ b/engines/gob/save/saveload_v3.cpp
@@ -439,7 +439,7 @@ bool SaveLoad_v3::ScreenshotHandler::load(int16 dataVar, int32 size, int32 offse
if ((slot >= kSlotCount) || (slotRem != 0))
return false;
- if (!TempSpriteHandler::createSprite(dataVar, size, offset))
+ if (!TempSpriteHandler::createFromSprite(dataVar, size, offset))
return false;
if (!_gameHandler->loadScreenshot(slot, _sprite))