aboutsummaryrefslogtreecommitdiff
path: root/engines/cine/anim.cpp
diff options
context:
space:
mode:
authorKari Salminen2008-07-22 10:15:58 +0000
committerKari Salminen2008-07-22 10:15:58 +0000
commit2a90435e5dccc0085613e35cc7177d1766cea6d0 (patch)
treef803f0d048754e9733925a63ab345cab7d05ce14 /engines/cine/anim.cpp
parent446a0406de97dba9417df8f82c4363cd3542a64b (diff)
downloadscummvm-rg350-2a90435e5dccc0085613e35cc7177d1766cea6d0.tar.gz
scummvm-rg350-2a90435e5dccc0085613e35cc7177d1766cea6d0.tar.bz2
scummvm-rg350-2a90435e5dccc0085613e35cc7177d1766cea6d0.zip
Fix for bug #2019355 (FW: broken compatibility with 0.11.1 saves):
- Changed savegame loading related functions to use SeekableReadStream rather than InSaveFile so MemoryReadStream can be used transparently. - Fixed loadResourcesFromSave to load multiframe animations correctly and to load 0.11.0/0.11.1 Future Wars savegames which used a slightly different format. - Added a savegame format detector that tries to detect between the old Future Wars savegame format, the new one and a broken revision of the new one. - Changed makeLoad to first load the savegame fully into memory and only then handle it (If the savegame's packed then it's unpacked first). If the packed savegame can't tell its unpacked size (i.e. it's using zlib format) then we'll try to load up to 256kB of the savegame data. Thanks to wjp for his help with nailing this release critical bug. svn-id: r33192
Diffstat (limited to 'engines/cine/anim.cpp')
-rw-r--r--engines/cine/anim.cpp74
1 files changed, 50 insertions, 24 deletions
diff --git a/engines/cine/anim.cpp b/engines/cine/anim.cpp
index 055eb733c3..8dbccebedf 100644
--- a/engines/cine/anim.cpp
+++ b/engines/cine/anim.cpp
@@ -769,19 +769,18 @@ void loadAbs(const char *resourceName, uint16 idx) {
/*! \brief Load animDataTable from save
* \param fHandle Savefile open for reading
- * \param broken Broken/correct file format switch
+ * \param saveGameFormat The used savegame format
* \todo Add Operation Stealth savefile support
*
* Unlike the old code, this one actually rebuilds the table one frame
* at a time.
*/
-void loadResourcesFromSave(Common::InSaveFile &fHandle, bool broken) {
+void loadResourcesFromSave(Common::SeekableReadStream &fHandle, enum CineSaveGameFormat saveGameFormat) {
int16 currentAnim, foundFileIdx;
int8 isMask = 0, isSpl = 0;
byte *dataPtr, *ptr;
char *animName, part[256];
byte transparentColor = 0;
- AnimData *currentPtr;
AnimHeaderStruct animHeader;
uint16 width, height, bpp, var1;
@@ -791,30 +790,46 @@ void loadResourcesFromSave(Common::InSaveFile &fHandle, bool broken) {
strcpy(part, currentPartName);
- for (currentAnim = 0; currentAnim < NUM_MAX_ANIMDATA; currentAnim++) {
- currentPtr = &animDataTable[currentAnim];
+ // We only support these variations of the savegame format at the moment.
+ assert(saveGameFormat == ANIMSIZE_23 || saveGameFormat == ANIMSIZE_30_PTRS_INTACT);
+ const int entrySize = ((saveGameFormat == ANIMSIZE_23) ? 23 : 30);
+ const int fileStartPos = fHandle.pos();
+ for (currentAnim = 0; currentAnim < NUM_MAX_ANIMDATA; currentAnim += animHeader.numFrames) {
+ // Initialize the number of frames variable to a sane number.
+ // This is needed when using continue later in this function.
+ animHeader.numFrames = 1;
+
+ // Seek to the start of the current animation's entry
+ fHandle.seek(fileStartPos + currentAnim * entrySize);
+ // Read in the current animation entry
width = fHandle.readUint16BE();
var1 = fHandle.readUint16BE();
bpp = fHandle.readUint16BE();
height = fHandle.readUint16BE();
- if (!broken) {
- if (!fHandle.readUint32BE()) {
- fHandle.skip(18);
- continue;
- }
- fHandle.readUint32BE();
+ bool validPtr = false;
+ // Handle variables only present in animation entries of size 30
+ if (entrySize == 30) {
+ validPtr = (fHandle.readUint32BE() != 0); // Read data pointer
+ fHandle.readUint32BE(); // Discard mask pointer
}
foundFileIdx = fHandle.readSint16BE();
frame = fHandle.readSint16BE();
fHandle.read(name, 10);
- if (foundFileIdx < 0 || (broken && !fHandle.readByte())) {
+ // Handle variables only present in animation entries of size 23
+ if (entrySize == 23) {
+ validPtr = (fHandle.readByte() != 0);
+ }
+
+ // Don't try to load invalid entries.
+ if (foundFileIdx < 0 || !validPtr) {
continue;
}
+ // Alright, the animation entry looks to be valid so let's start handling it...
if (strcmp(currentPartName, name)) {
closePart();
loadPart(name);
@@ -823,13 +838,14 @@ void loadResourcesFromSave(Common::InSaveFile &fHandle, bool broken) {
animName = partBuffer[foundFileIdx].partName;
ptr = dataPtr = readBundleFile(foundFileIdx);
+ // isSpl and isMask are mutually exclusive cases
isSpl = (strstr(animName, ".SPL")) ? 1 : 0;
isMask = (strstr(animName, ".MSK")) ? 1 : 0;
if (isSpl) {
width = (uint16) partBuffer[foundFileIdx].unpackedSize;
height = 1;
- frame = 0;
+ animHeader.numFrames = 1;
type = ANIM_RAW;
} else {
Common::MemoryReadStream readS(ptr, 0x16);
@@ -843,25 +859,35 @@ void loadResourcesFromSave(Common::InSaveFile &fHandle, bool broken) {
type = ANIM_MASK;
} else {
type = ANIM_MASKSPRITE;
+ }
+ }
- loadRelatedPalette(animName);
- transparentColor = getAnimTransparentColor(animName);
-
- // special case transparency handling
- if (!strcmp(animName, "L2202.ANI")) {
- transparentColor = (frame < 2) ? 0 : 7;
- } else if (!strcmp(animName, "L4601.ANI")) {
- transparentColor = (frame < 1) ? 0xE : 0;
- }
+ loadRelatedPalette(animName);
+ transparentColor = getAnimTransparentColor(animName);
+ // Make sure we load at least one frame and also that we
+ // don't overflow the animDataTable by writing beyond its end.
+ animHeader.numFrames = CLIP<uint16>(animHeader.numFrames, 1, NUM_MAX_ANIMDATA - currentAnim);
+
+ // Load the frames
+ for (frame = 0; frame < animHeader.numFrames; frame++) {
+ // special case transparency handling
+ if (!strcmp(animName, "L2202.ANI")) {
+ transparentColor = (frame < 2) ? 0 : 7;
+ } else if (!strcmp(animName, "L4601.ANI")) {
+ transparentColor = (frame < 1) ? 0xE : 0;
}
+
+ // Load a single frame
+ animDataTable[currentAnim + frame].load(ptr + frame * width * height, type, width, height, foundFileIdx, frame, name, transparentColor);
}
- ptr += frame * width * height;
- currentPtr->load(ptr, type, width, height, foundFileIdx, frame, name, transparentColor);
free(dataPtr);
}
loadPart(part);
+
+ // Make sure we jump over all the animation entries
+ fHandle.seek(fileStartPos + NUM_MAX_ANIMDATA * entrySize);
}
} // End of namespace Cine