diff options
| -rw-r--r-- | engines/cine/anim.cpp | 74 | ||||
| -rw-r--r-- | engines/cine/anim.h | 2 | ||||
| -rw-r--r-- | engines/cine/bg_list.cpp | 2 | ||||
| -rw-r--r-- | engines/cine/bg_list.h | 2 | ||||
| -rw-r--r-- | engines/cine/gfx.cpp | 2 | ||||
| -rw-r--r-- | engines/cine/gfx.h | 2 | ||||
| -rw-r--r-- | engines/cine/script.h | 6 | ||||
| -rw-r--r-- | engines/cine/script_fw.cpp | 6 | ||||
| -rw-r--r-- | engines/cine/various.cpp | 276 | ||||
| -rw-r--r-- | engines/cine/various.h | 33 | 
10 files changed, 256 insertions, 149 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 diff --git a/engines/cine/anim.h b/engines/cine/anim.h index d63033e670..f32a146e35 100644 --- a/engines/cine/anim.h +++ b/engines/cine/anim.h @@ -101,7 +101,7 @@ void freeAnimDataTable(void);  void freeAnimDataRange(byte startIdx, byte numIdx);  void loadResource(const char *resourceName);  void loadAbs(const char *resourceName, uint16 idx); -void loadResourcesFromSave(Common::InSaveFile &fHandle, bool broken); +void loadResourcesFromSave(Common::SeekableReadStream &fHandle, enum CineSaveGameFormat saveGameFormat);  void generateMask(const byte *sprite, byte *mask, uint16 size, byte transparency);  } // End of namespace Cine diff --git a/engines/cine/bg_list.cpp b/engines/cine/bg_list.cpp index b10211282f..fddca078e5 100644 --- a/engines/cine/bg_list.cpp +++ b/engines/cine/bg_list.cpp @@ -83,7 +83,7 @@ void resetBgIncrustList(void) {  /*! \brief Restore incrust list from savefile   * \param fHandle Savefile open for reading   */ -void loadBgIncrustFromSave(Common::InSaveFile &fHandle) { +void loadBgIncrustFromSave(Common::SeekableReadStream &fHandle) {  	BGIncrust tmp;  	int size = fHandle.readSint16BE(); diff --git a/engines/cine/bg_list.h b/engines/cine/bg_list.h index 1849d6ec3d..9a402baee8 100644 --- a/engines/cine/bg_list.h +++ b/engines/cine/bg_list.h @@ -51,7 +51,7 @@ void addSpriteFilledToBGList(int16 idx);  void createBgIncrustListElement(int16 objIdx, int16 param);  void resetBgIncrustList(void); -void loadBgIncrustFromSave(Common::InSaveFile &fHandle); +void loadBgIncrustFromSave(Common::SeekableReadStream &fHandle);  } // End of namespace Cine diff --git a/engines/cine/gfx.cpp b/engines/cine/gfx.cpp index 1f868ccb75..f95794a409 100644 --- a/engines/cine/gfx.cpp +++ b/engines/cine/gfx.cpp @@ -614,7 +614,7 @@ void FWRenderer::saveBg(Common::OutSaveFile &fHandle) {  /*! \brief Restore active and backup palette from save   * \param fHandle Savefile open for reading   */ -void FWRenderer::restorePalette(Common::InSaveFile &fHandle) { +void FWRenderer::restorePalette(Common::SeekableReadStream &fHandle) {  	int i;  	if (!_palette) { diff --git a/engines/cine/gfx.h b/engines/cine/gfx.h index c63c79ac82..910a4326e9 100644 --- a/engines/cine/gfx.h +++ b/engines/cine/gfx.h @@ -113,7 +113,7 @@ public:  	virtual void refreshPalette();  	virtual void reloadPalette(); -	void restorePalette(Common::InSaveFile &fHandle); +	void restorePalette(Common::SeekableReadStream &fHandle);  	void savePalette(Common::OutSaveFile &fHandle);  	virtual void rotatePalette(int a, int b, int c);  	virtual void transformPalette(int first, int last, int r, int g, int b); diff --git a/engines/cine/script.h b/engines/cine/script.h index fcd21990fa..fe39272c4c 100644 --- a/engines/cine/script.h +++ b/engines/cine/script.h @@ -61,7 +61,7 @@ private:  public:  	// Explicit to prevent var=0 instead of var[i]=0 typos.  	explicit ScriptVars(unsigned int len = 50); -	ScriptVars(Common::InSaveFile &fHandle, unsigned int len = 50); +	ScriptVars(Common::SeekableReadStream &fHandle, unsigned int len = 50);  	ScriptVars(const ScriptVars &src);  	~ScriptVars(void); @@ -71,8 +71,8 @@ public:  	void save(Common::OutSaveFile &fHandle) const;  	void save(Common::OutSaveFile &fHandle, unsigned int len) const; -	void load(Common::InSaveFile &fHandle); -	void load(Common::InSaveFile &fHandle, unsigned int len); +	void load(Common::SeekableReadStream &fHandle); +	void load(Common::SeekableReadStream &fHandle, unsigned int len);  	void reset(void);  }; diff --git a/engines/cine/script_fw.cpp b/engines/cine/script_fw.cpp index 54a4976000..57b1e8f7b4 100644 --- a/engines/cine/script_fw.cpp +++ b/engines/cine/script_fw.cpp @@ -230,7 +230,7 @@ ScriptVars::ScriptVars(unsigned int len) : _size(len), _vars(new int16[len]) {   * \param fHandle Savefile open for reading   * \param len Size of array   */ -ScriptVars::ScriptVars(Common::InSaveFile &fHandle, unsigned int len) +ScriptVars::ScriptVars(Common::SeekableReadStream &fHandle, unsigned int len)  	: _size(len), _vars(new int16[len]) {  	assert(_vars); @@ -306,7 +306,7 @@ void ScriptVars::save(Common::OutSaveFile &fHandle, unsigned int len) const {  /*! \brief Restore array from savefile   * \param fHandle Savefile open for reading   */ -void ScriptVars::load(Common::InSaveFile &fHandle) { +void ScriptVars::load(Common::SeekableReadStream &fHandle) {  	load(fHandle, _size);  } @@ -314,7 +314,7 @@ void ScriptVars::load(Common::InSaveFile &fHandle) {   * \param fHandle Savefile open for reading   * \param len Length of data to be read   */ -void ScriptVars::load(Common::InSaveFile &fHandle, unsigned int len) { +void ScriptVars::load(Common::SeekableReadStream &fHandle, unsigned int len) {  	debug(6, "assert(%d <= %d)", len, _size);  	assert(len <= _size);  	for (unsigned int i = 0; i < len; i++) { diff --git a/engines/cine/various.cpp b/engines/cine/various.cpp index ab2fa645c7..8e6f3fce76 100644 --- a/engines/cine/various.cpp +++ b/engines/cine/various.cpp @@ -246,21 +246,130 @@ bool CineEngine::loadSaveDirectory(void) {  	return true;  } +/*! \brief Savegame format detector + * \param fHandle Savefile to check + * \return Savegame format on success, ANIMSIZE_UNKNOWN on failure + * + * This function seeks through the savefile and tries to determine the + * savegame format it uses. There's a miniscule chance that the detection + * algorithm could get confused and think that the file uses both the older + * and the newer format but that is such a remote possibility that I wouldn't + * worry about it at all. + */ +enum CineSaveGameFormat detectSaveGameFormat(Common::SeekableReadStream &fHandle) { +	// The animDataTable begins at savefile position 0x2315. +	// Each animDataTable entry takes 23 bytes in older saves (Revisions 21772-31443) +	// and 30 bytes in the save format after that (Revision 31444 and onwards). +	// There are 255 entries in the animDataTable in both of the savefile formats. +	static const uint animDataTableStart = 0x2315; +	static const uint animEntriesCount = 255; +	static const uint oldAnimEntrySize = 23; +	static const uint newAnimEntrySize = 30; +	static const uint defaultAnimEntrySize = newAnimEntrySize; +	static const uint animEntrySizeChoices[] = {oldAnimEntrySize, newAnimEntrySize}; +	Common::Array<uint> animEntrySizeMatches; +	const uint32 prevStreamPos = fHandle.pos(); + +	// Try to walk through the savefile using different animDataTable entry sizes +	// and make a list of all the successful entry sizes. +	for (uint i = 0; i < ARRAYSIZE(animEntrySizeChoices); i++) { +		// 206 = 2 * 50 * 2 + 2 * 3 (Size of global and object script entries) +		// 20 = 4 * 2 + 2 * 6 (Size of overlay and background incrust entries) +		static const uint sizeofScreenParams = 2 * 6; +		static const uint globalScriptEntrySize = 206; +		static const uint objectScriptEntrySize = 206; +		static const uint overlayEntrySize = 20; +		static const uint bgIncrustEntrySize = 20; +		static const uint chainEntrySizes[] = { +			globalScriptEntrySize, +			objectScriptEntrySize, +			overlayEntrySize, +			bgIncrustEntrySize +		}; +		 +		uint animEntrySize = animEntrySizeChoices[i]; +		// Jump over the animDataTable entries and the screen parameters +		uint32 newPos = animDataTableStart + animEntrySize * animEntriesCount + sizeofScreenParams; +		// Check that there's data left after the point we're going to jump to +		if (newPos >= fHandle.size()) { +			continue; +		} +		fHandle.seek(newPos); + +		// Jump over the remaining items in the savegame file +		// (i.e. the global scripts, object scripts, overlays and background incrusts). +		bool chainWalkSuccess = true; +		for (uint chainIndex = 0; chainIndex < ARRAYSIZE(chainEntrySizes); chainIndex++) { +			// Read entry count and jump over the entries +			int entryCount = fHandle.readSint16BE(); +			newPos = fHandle.pos() + chainEntrySizes[chainIndex] * entryCount; +			// Check that we didn't go past the end of file. +			// Note that getting exactly to the end of file is acceptable. +			if (newPos > fHandle.size()) { +				chainWalkSuccess = false; +				break; +			} +			fHandle.seek(newPos); +		} +		 +		// If we could walk the chain successfully and +		// got exactly to the end of file then we've got a match. +		if (chainWalkSuccess && fHandle.pos() == fHandle.size()) { +			// We found a match, let's save it +			animEntrySizeMatches.push_back(animEntrySize); +		} +	} + +	// Check that we got only one entry size match. +	// If we didn't, then return an error. +	enum CineSaveGameFormat result = ANIMSIZE_UNKNOWN; +	if (animEntrySizeMatches.size() == 1) { +		const uint animEntrySize = animEntrySizeMatches[0]; +		assert(animEntrySize == oldAnimEntrySize || animEntrySize == newAnimEntrySize); +		if (animEntrySize == oldAnimEntrySize) { +			result = ANIMSIZE_23; +		} else { // animEntrySize == newAnimEntrySize		 +			// Check data and mask pointers in all of the animDataTable entries +			// to see whether we've got the version with the broken data and mask pointers or not. +			// In the broken format all data and mask pointers were always zero. +			static const uint relativeDataPos = 2 * 4; +			bool pointersIntact = false; +			for (uint i = 0; i < animEntriesCount; i++) { +				fHandle.seek(animDataTableStart + i * animEntrySize + relativeDataPos); +				uint32 data = fHandle.readUint32BE(); +				uint32 mask = fHandle.readUint32BE(); +				if (data != NULL || mask != NULL) { +					pointersIntact = true; +					break; +				} +			} +			result = (pointersIntact ? ANIMSIZE_30_PTRS_INTACT : ANIMSIZE_30_PTRS_BROKEN); +		} +	} else if (animEntrySizeMatches.size() > 1) { +		warning("Savegame format detector got confused by input data. Detecting savegame to be using an unknown format"); +	} else { // animEtrySizeMatches.size() == 0 +		debug(3, "Savegame format detector was unable to detect savegame's format"); +	} + +	fHandle.seek(prevStreamPos); +	return result; +} +  /*! \brief Restore script list item from savefile - * \param fHandle Savefile handlem open for reading + * \param fHandle Savefile handle open for reading   * \param isGlobal Restore object or global script?   */ -void loadScriptFromSave(Common::InSaveFile *fHandle, bool isGlobal) { +void loadScriptFromSave(Common::SeekableReadStream &fHandle, bool isGlobal) {  	ScriptVars localVars, labels;  	uint16 compare, pos;  	int16 idx; -	labels.load(*fHandle); -	localVars.load(*fHandle); +	labels.load(fHandle); +	localVars.load(fHandle); -	compare = fHandle->readUint16BE(); -	pos = fHandle->readUint16BE(); -	idx = fHandle->readUint16BE(); +	compare = fHandle.readUint16BE(); +	pos = fHandle.readUint16BE(); +	idx = fHandle.readUint16BE();  	// no way to reinitialize these  	if (idx < 0) { @@ -283,7 +392,7 @@ void loadScriptFromSave(Common::InSaveFile *fHandle, bool isGlobal) {  /*! \brief Restore overlay sprites from savefile   * \param fHandle Savefile open for reading   */ -void loadOverlayFromSave(Common::InSaveFile &fHandle) { +void loadOverlayFromSave(Common::SeekableReadStream &fHandle) {  	overlay tmp;  	fHandle.readUint32BE(); @@ -299,115 +408,17 @@ void loadOverlayFromSave(Common::InSaveFile &fHandle) {  	overlayList.push_back(tmp);  } -/*! \brief Savefile format tester - * \param fHandle Savefile to check - * - * This function seeks through savefile and tries to guess if it's the original - * savegame format or broken format from ScummVM 0.10/0.11 - * The test is incomplete but this should cover 99.99% of cases. - * If anyone makes a savefile which could confuse this test, assert will - * report it - */ -bool brokenSave(Common::InSaveFile &fHandle) { -	// Backward seeking not supported in compressed savefiles -	// if you really want it, finish it yourself -	return false; - -	// fixed size part: 14093 bytes (12308 bytes in broken save) -	// animDataTable begins at byte 6431 - -	int filesize = fHandle.size(); -	int startpos = fHandle.pos(); -	int pos, tmp; -	bool correct = false, broken = false; - -	// check for correct format -	while (filesize > 14093) { -		pos = 14093; - -		fHandle.seek(pos); -		tmp = fHandle.readUint16BE(); -		pos += 2 + tmp * 206; -		if (pos >= filesize) break; - -		fHandle.seek(pos); -		tmp = fHandle.readUint16BE(); -		pos += 2 + tmp * 206; -		if (pos >= filesize) break; - -		fHandle.seek(pos); -		tmp = fHandle.readUint16BE(); -		pos += 2 + tmp * 20; -		if (pos >= filesize) break; - -		fHandle.seek(pos); -		tmp = fHandle.readUint16BE(); -		pos += 2 + tmp * 20; - -		if (pos == filesize) correct = true; -		break; -	} -	debug(5, "brokenSave: correct format check %s: size=%d, pos=%d", -		correct ? "passed" : "failed", filesize, pos); - -	// check for broken format -	while (filesize > 12308) { -		pos = 12308; - -		fHandle.seek(pos); -		tmp = fHandle.readUint16BE(); -		pos += 2 + tmp * 206; -		if (pos >= filesize) break; - -		fHandle.seek(pos); -		tmp = fHandle.readUint16BE(); -		pos += 2 + tmp * 206; -		if (pos >= filesize) break; - -		fHandle.seek(pos); -		tmp = fHandle.readUint16BE(); -		pos += 2 + tmp * 20; -		if (pos >= filesize) break; - -		fHandle.seek(pos); -		tmp = fHandle.readUint16BE(); -		pos += 2 + tmp * 20; - -		if (pos == filesize) broken = true; -		break; -	} -	debug(5, "brokenSave: broken format check %s: size=%d, pos=%d", -		broken ? "passed" : "failed", filesize, pos); - -	// there's a very small chance that both cases will match -	// if anyone runs into it, you'll have to walk through -	// the animDataTable and try to open part file for each entry -	if (!correct && !broken) { -		error("brokenSave: file format check failed"); -	} else if (correct && broken) { -		error("brokenSave: both file formats seem to apply"); -	} - -	fHandle.seek(startpos); -	debug(5, "brokenSave: detected %s file format", -		correct ? "correct" : "broken"); - -	return broken; -} -  /*! \todo Implement Operation Stealth loading, this is obviously Future Wars only   * \todo Add support for loading the zoneQuery table (Operation Stealth specific)   */  bool CineEngine::makeLoad(char *saveName) {  	int16 i;  	int16 size; -	bool broken; -	Common::InSaveFile *fHandle;  	char bgName[13]; -	fHandle = g_saveFileMan->openForLoading(saveName); +	Common::SharedPtr<Common::InSaveFile> saveFile(g_saveFileMan->openForLoading(saveName)); -	if (!fHandle) { +	if (!saveFile) {  		drawString(otherMessages[0], 0);  		waitPlayerInput();  		// restoreScreen(); @@ -415,6 +426,46 @@ bool CineEngine::makeLoad(char *saveName) {  		return false;  	} +	uint32 saveSize = saveFile->size(); +	if (saveSize == 0) { // Savefile's compressed using zlib format can't tell their unpacked size, test for it +		// Can't get information about the savefile's size so let's try +		// reading as much as we can from the file up to a predefined upper limit. +		// +		// Some estimates for maximum savefile sizes (All with 255 animDataTable entries of 30 bytes each): +		// With 256 global scripts, object scripts, overlays and background incrusts: +		// 0x2315 + (255 * 30) + (2 * 6) + (206 + 206 + 20 + 20) * 256 = ~129kB +		// With 512 global scripts, object scripts, overlays and background incrusts: +		// 0x2315 + (255 * 30) + (2 * 6) + (206 + 206 + 20 + 20) * 512 = ~242kB +		// +		// I think it extremely unlikely that there would be over 512 global scripts, object scripts, +		// overlays and background incrusts so 256kB seems like quite a safe upper limit.		 +		// NOTE: If the savegame format is changed then this value might have to be re-evaluated! +		// Hopefully devices with more limited memory can also cope with this memory allocation. +		saveSize = 256 * 1024; +	} +	Common::SharedPtr<Common::MemoryReadStream> fHandle(saveFile->readStream(saveSize)); + +	// Try to detect the used savegame format +	enum CineSaveGameFormat saveGameFormat = detectSaveGameFormat(*fHandle); + +	// Handle problematic savegame formats +	if (saveGameFormat == ANIMSIZE_30_PTRS_BROKEN) { +		// One might be able to load the ANIMSIZE_30_PTRS_BROKEN format but +		// that's not implemented here because it was never used in a stable +		// release of ScummVM but only during development (From revision 31453, +		// which introduced the problem, until revision 32073, which fixed it). +		// Therefore be bail out if we detect this particular savegame format. +		warning("Detected a known broken savegame format, not loading savegame"); +		return false; +	} else if (saveGameFormat == ANIMSIZE_UNKNOWN) { +		// If we can't detect the savegame format +		// then let's try the default format and hope for the best. +		warning("Couldn't detect the used savegame format, trying default savegame format. Things may break"); +		saveGameFormat = ANIMSIZE_30_PTRS_INTACT; +	} +	// Now we should have either of these formats +	assert(saveGameFormat == ANIMSIZE_23 || saveGameFormat == ANIMSIZE_30_PTRS_INTACT); +  	g_sound->stopMusic();  	freeAnimDataTable();  	overlayList.clear(); @@ -464,7 +515,6 @@ bool CineEngine::makeLoad(char *saveName) {  	checkForPendingDataLoadSwitch = 0; -	broken = brokenSave(*fHandle);  	// At savefile position 0x0000:  	currentDisk = fHandle->readUint16BE(); @@ -588,7 +638,7 @@ bool CineEngine::makeLoad(char *saveName) {  	fHandle->readUint16BE();  	// At 0x2315: -	loadResourcesFromSave(*fHandle, broken); +	loadResourcesFromSave(*fHandle, saveGameFormat);  	// TODO: handle screen params (really required ?)  	fHandle->readUint16BE(); @@ -600,12 +650,12 @@ bool CineEngine::makeLoad(char *saveName) {  	size = fHandle->readSint16BE();  	for (i = 0; i < size; i++) { -		loadScriptFromSave(fHandle, true); +		loadScriptFromSave(*fHandle, true);  	}  	size = fHandle->readSint16BE();  	for (i = 0; i < size; i++) { -		loadScriptFromSave(fHandle, false); +		loadScriptFromSave(*fHandle, false);  	}  	size = fHandle->readSint16BE(); @@ -615,8 +665,6 @@ bool CineEngine::makeLoad(char *saveName) {  	loadBgIncrustFromSave(*fHandle); -	delete fHandle; -  	if (strlen(currentMsgName)) {  		loadMsg(currentMsgName);  	} diff --git a/engines/cine/various.h b/engines/cine/various.h index 840f1674a2..9507876307 100644 --- a/engines/cine/various.h +++ b/engines/cine/various.h @@ -33,6 +33,39 @@  namespace Cine { +/** + * Cine engine's save game formats. + * Enumeration entries (Excluding the one used as an error) + * are sorted according to age (i.e. top one is oldest, last one newest etc). + * + * ANIMSIZE_UNKNOWN: + * - Animation data entry size is unknown (Used as an error). + * + * ANIMSIZE_23: + * - Animation data entry size is 23 bytes. + * - Used at least by 0.11.0 and 0.11.1 releases of ScummVM. + * - Introduced in revision 21772, stopped using in revision 31444. + * + * ANIMSIZE_30_PTRS_BROKEN: + * - Animation data entry size is 30 bytes. + * - Data and mask pointers in the saved structs are always NULL. + * - Introduced in revision 31453, stopped using in revision 32073. + * + * ANIMSIZE_30_PTRS_INTACT: + * - Animation data entry size is 30 bytes. + * - Data and mask pointers in the saved structs are intact, + *   so you can test them for equality or inequality with NULL + *   but don't try using them for anything else, it won't work. + * - Introduced in revision 31444, got broken in revision 31453, + *   got fixed in revision 32073 and used after that. + */ +enum CineSaveGameFormat { +	ANIMSIZE_UNKNOWN, +	ANIMSIZE_23, +	ANIMSIZE_30_PTRS_BROKEN, +	ANIMSIZE_30_PTRS_INTACT +}; +  void initLanguage(Common::Language lang);  int16 makeMenuChoice(const CommandeType commandList[], uint16 height, uint16 X, uint16 Y, uint16 width, bool recheckValue = false);  | 
