diff options
Diffstat (limited to 'engines/cine/anim.cpp')
-rw-r--r-- | engines/cine/anim.cpp | 74 |
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 |