diff options
| author | Max Horn | 2005-10-01 21:13:38 +0000 | 
|---|---|---|
| committer | Max Horn | 2005-10-01 21:13:38 +0000 | 
| commit | cc08602770717f29b0733533aeea42a2c185df4f (patch) | |
| tree | a9e22ac320823594de4e8df23081095159ff4929 | |
| parent | 5c30b3c8df57abf206429e0e153172755402ac8b (diff) | |
| download | scummvm-rg350-cc08602770717f29b0733533aeea42a2c185df4f.tar.gz scummvm-rg350-cc08602770717f29b0733533aeea42a2c185df4f.tar.bz2 scummvm-rg350-cc08602770717f29b0733533aeea42a2c185df4f.zip | |
Patch #1259034 (Scumm Savegame Informations)
svn-id: r18920
| -rw-r--r-- | scumm/dialogs.cpp | 78 | ||||
| -rw-r--r-- | scumm/saveload.cpp | 148 | ||||
| -rw-r--r-- | scumm/saveload.h | 2 | ||||
| -rw-r--r-- | scumm/scumm.cpp | 7 | ||||
| -rw-r--r-- | scumm/scumm.h | 14 | 
5 files changed, 247 insertions, 2 deletions
| diff --git a/scumm/dialogs.cpp b/scumm/dialogs.cpp index 17d92305e5..e6170bd495 100644 --- a/scumm/dialogs.cpp +++ b/scumm/dialogs.cpp @@ -21,6 +21,7 @@  #include "common/stdafx.h"  #include "common/config-manager.h" +#include "common/savefile.h"  #include "common/system.h"  #include "common/scaler.h" @@ -193,6 +194,8 @@ const Common::String ScummDialog::queryResString(int stringno) {  #pragma mark - +Common::StringList generateSavegameList(ScummEngine *scumm, bool saveMode); +  enum {  	kSaveCmd = 'SAVE',  	kLoadCmd = 'LOAD', @@ -271,6 +274,9 @@ protected:  	GUI::ListWidget		*_list;  	GUI::ButtonWidget	*_chooseButton;  	GUI::GraphicsWidget	*_gfxWidget; +	GUI::StaticTextWidget	*_date; +	GUI::StaticTextWidget	*_time; +	GUI::StaticTextWidget	*_playtime;  	ScummEngine			*_scumm;  public: @@ -300,6 +306,39 @@ SaveLoadChooserEx::SaveLoadChooserEx(const String &title, const String &buttonLa  			((_scumm->_system->getHeight() % 200 && _scumm->_system->getHeight() != 350) ? kThumbnailHeight2 : kThumbnailHeight1) + 8);  	_gfxWidget->setFlags(GUI::WIDGET_BORDER); +	int height = 18 + ((_scumm->_system->getHeight() % 200 && _scumm->_system->getHeight() != 350) ? kThumbnailHeight2 : kThumbnailHeight1) + 8; + +	_date = new StaticTextWidget(this, +					_w - (kThumbnailWidth + 22), +					height, +					kThumbnailWidth + 8, +					kLineHeight, +					"No date saved", +					kTextAlignCenter); +	_date->setFlags(GUI::WIDGET_CLEARBG); + +	height += kLineHeight; + +	_time = new StaticTextWidget(this, +					_w - (kThumbnailWidth + 22), +					height, +					kThumbnailWidth + 8, +					kLineHeight, +					"No time saved", +					kTextAlignCenter); +	_time->setFlags(GUI::WIDGET_CLEARBG); + +	height += kLineHeight; + +	_playtime = new StaticTextWidget(this, +					_w - (kThumbnailWidth + 22), +					height, +					kThumbnailWidth + 8, +					kLineHeight, +					"No playtime saved", +					kTextAlignCenter); +	_playtime->setFlags(GUI::WIDGET_CLEARBG); +  	// Buttons  	addButton(this, _w - 2 * (kBigButtonWidth + 10), _h - kBigButtonHeight - 8, "Cancel", kCloseCmd, 0, GUI::kBigWidgetSize);  	_chooseButton = addButton(this, _w - (kBigButtonWidth + 10), _h - kBigButtonHeight - 8, buttonLabel, kChooseCmd, 0, GUI::kBigWidgetSize); @@ -342,9 +381,48 @@ void SaveLoadChooserEx::handleCommand(CommandSender *sender, uint32 cmd, uint32  		Graphics::Surface *thumb;  		thumb = _scumm->loadThumbnailFromSlot(_saveMode ? selItem + 1 : selItem);  		_gfxWidget->setGfx(thumb); +		if (thumb) +			thumb->free();  		delete thumb;  		_gfxWidget->draw(); +		InfoStuff infos; +		memset(&infos, 0, sizeof(InfoStuff)); +		char buffer[32]; +		if (_scumm->loadInfosFromSlot(_saveMode ? selItem + 1 : selItem, &infos)) { +			snprintf(buffer, 32, "Date: %.2d.%.2d.%.4d", +				(infos.date >> 24) & 0xFF, (infos.date >> 16) & 0xFF, +				infos.date & 0xFFFF); +			_date->setLabel(buffer); +			_date->draw(); +			 +			snprintf(buffer, 32, "Time: %.2d:%.2d", +				(infos.time >> 8) & 0xFF, infos.time & 0xFF); +			_time->setLabel(buffer); +			_time->draw(); + +			int minutes = infos.playtime / 60; +			int hours = minutes / 60; +			minutes %= 60; + +			snprintf(buffer, 32, "Playtime: %.2d:%.2d", +				hours & 0xFF, minutes & 0xFF); +			_playtime->setLabel(buffer); +			_playtime->draw(); +		} else { +			snprintf(buffer, 32, "No date saved"); +			_date->setLabel(buffer); +			_date->draw(); +			 +			snprintf(buffer, 32, "No time saved"); +			_time->setLabel(buffer); +			_time->draw(); + +			snprintf(buffer, 32, "No playtime saved"); +			_playtime->setLabel(buffer); +			_playtime->draw(); +		} +  		if (_saveMode) {  			_list->startEditMode();  		} diff --git a/scumm/saveload.cpp b/scumm/saveload.cpp index 349fe5fd87..55481f76f9 100644 --- a/scumm/saveload.cpp +++ b/scumm/saveload.cpp @@ -51,6 +51,24 @@ struct SaveGameHeader {  	char name[32];  }; +#if !defined(__GNUC__) +	#pragma START_PACK_STRUCTS +#endif + +struct SaveInfoSection { +	uint32 type; +	uint32 version; +	uint32 size; +	 +	uint32 timeTValue; +	uint32 playtime; +} GCC_PACK; + +#if !defined(__GNUC__) +	#pragma END_PACK_STRUCTS +#endif + +#define INFOSECTION_VERSION 1  void ScummEngine::requestSave(int slot, const char *name, bool temporary) {  	_saveLoadSlot = slot; @@ -84,6 +102,7 @@ bool ScummEngine::saveState(int slot, bool compat) {  	out->write(&hdr, sizeof(hdr));  	saveThumbnail(out); +	saveInfos(out);  	Serializer ser(0, out, CURRENT_VER);  	saveOrLoad(&ser, CURRENT_VER); @@ -144,6 +163,23 @@ bool ScummEngine::loadState(int slot, bool compat) {  		in->skip(size - 8);  	} +	// Since version 56 we have informations about the creation of the save game and the save time here +	if (hdr.ver >= VER(56)) { +		InfoStuff infos; +		if (!loadInfos(in, &infos)) { +			warning("Info section could not be found"); +			delete in; +			return false; +		} + +		_engineStartTime = _system->getMillis() / 1000 - infos.playtime; +	} else { +		// start time counting +		_engineStartTime = _system->getMillis() / 1000; +	} + +	_dialogStartTime = _system->getMillis() / 1000; +  	// Due to a bug in scummvm up to and including 0.3.0, save games could be saved  	// in the V8/V9 format but were tagged with a V7 mark. Ouch. So we just pretend V7 == V8 here  	if (hdr.ver == VER(7)) @@ -359,6 +395,9 @@ bool ScummEngine::loadState(int slot, bool compat) {  	_sound->pauseSounds(false); +	_engineStartTime += _system->getMillis() / 1000 - _dialogStartTime; +	_dialogStartTime = 0; +  	return true;  } @@ -440,6 +479,115 @@ Graphics::Surface *ScummEngine::loadThumbnailFromSlot(int slot) {  	return thumb;  } +bool ScummEngine::loadInfosFromSlot(int slot, InfoStuff *stuff) { +	char filename[256]; +	Common::InSaveFile *in; +	SaveGameHeader hdr; +	int len; + +	makeSavegameName(filename, slot, false); +	if (!(in = _saveFileMan->openForLoading(filename))) { +		return false; +	} +	len = in->read(&hdr, sizeof(hdr)); + +	if (len != sizeof(hdr) || hdr.type != MKID('SCVM')) { +		delete in; +		return false; +	} + +	if (hdr.ver > CURRENT_VER) +		hdr.ver = TO_LE_32(hdr.ver); +	if (hdr.ver < VER(56)) { +		delete in; +		return false; +	} + +	uint32 type; +	in->read(&type, 4); + +	// Check for the THMB header. Also, work around a bug which caused +	// the chunk type (incorrectly) to be written in LE on LE machines. +	if (! (type == MKID('THMB') || (hdr.ver < VER(55) && type == MKID('BMHT')))){ +		delete in; +		return false; +	} +	uint32 size = in->readUint32BE(); +	in->skip(size - 8); + +	if (!loadInfos(in, stuff)) { +		delete in; +		return false; +	} +	 +	delete in;	 +	return true; +} + +bool ScummEngine::loadInfos(Common::InSaveFile *file, InfoStuff *stuff) { +	memset(stuff, 0, sizeof(InfoStuff)); + +	SaveInfoSection section; +	file->read(§ion.type, 4); +	if (section.type != MKID('INFO')) { +		return false; +	} + +	section.version = file->readUint32BE(); +	section.size = file->readUint32BE(); + +	// if we extend this we should add a table for the special sizes at the versions to check it +	if (section.version == INFOSECTION_VERSION && section.size != sizeof(SaveInfoSection)) { +		warning("Info section is corrupt"); +		file->skip(section.size); +		return false; +	} + +	section.timeTValue = file->readUint32BE(); +	section.playtime = file->readUint32BE(); + +	time_t curTime_ = section.timeTValue; +	tm *curTime = localtime(&curTime_);	 +	stuff->date = (curTime->tm_mday & 0xFF) << 24 | ((curTime->tm_mon + 1) & 0xFF) << 16 | (curTime->tm_year + 1900) & 0xFFFF; +	stuff->time = (curTime->tm_hour & 0xFF) << 8 | (curTime->tm_min) & 0xFF; +	stuff->playtime = section.playtime; + +	// if we extend the header we should check here for the version +	// e.g.: +	// if (header.version == 2) { +	//	// load some things here +	// } +	// +	// if (header.version == 3) { +	//	// ... +	// } +	// and so on... + +	// skip all newer features, this could make problems if some older version uses more space for +	// saving informations, but this should NOT happen +	if (section.size > sizeof(SaveInfoSection)) { +		file->skip(section.size - sizeof(SaveInfoSection)); +	} + +	return true; +} + +void ScummEngine::saveInfos(Common::OutSaveFile* file) { +	SaveInfoSection section; +	section.type = MKID('INFO'); +	section.version = INFOSECTION_VERSION; +	section.size = sizeof(SaveInfoSection); + +	section.timeTValue = time(0); +	section.playtime = _system->getMillis() / 1000 - _engineStartTime; + +	file->write(§ion.type, 4); +	file->writeUint32BE(section.version); +	file->writeUint32BE(section.size); +	file->writeUint32BE(section.timeTValue); +	file->writeUint32BE(section.playtime); +} +  void ScummEngine::saveOrLoad(Serializer *s, uint32 savegameVersion) {  	const SaveLoadEntry objectEntries[] = {  		MKLINE(ObjectData, OBIMoffset, sleUint32, VER(8)), diff --git a/scumm/saveload.h b/scumm/saveload.h index 8c9a6987c7..b495f1a6fd 100644 --- a/scumm/saveload.h +++ b/scumm/saveload.h @@ -45,7 +45,7 @@ namespace Scumm {   * only saves/loads those which are valid for the version of the savegame   * which is being loaded/saved currently.   */ -#define CURRENT_VER 55 +#define CURRENT_VER 56  /**   * An auxillary macro, used to specify savegame versions. We use this instead diff --git a/scumm/scumm.cpp b/scumm/scumm.cpp index 67aaa07d28..b8136dbd8e 100644 --- a/scumm/scumm.cpp +++ b/scumm/scumm.cpp @@ -2109,6 +2109,8 @@ void ScummEngine::setupVolumes() {  #pragma mark -  int ScummEngine::go() { +	_engineStartTime = _system->getMillis() / 1000; +  	// If requested, load a save game instead of running the boot script  	if (_saveLoadFlag != 2 || !loadState(_saveLoadSlot, _saveTemporaryState)) {  		int args[16]; @@ -2550,6 +2552,8 @@ void ScummEngine::startManiac() {  #pragma mark -  int ScummEngine::runDialog(Dialog &dialog) { +	_dialogStartTime = _system->getMillis() / 1000; +  	// Pause sound & video  	bool old_soundsPaused = _sound->_soundsPaused;  	_sound->pauseSounds(true); @@ -2566,6 +2570,9 @@ int ScummEngine::runDialog(Dialog &dialog) {  	_sound->pauseSounds(old_soundsPaused);  	_smushPaused = oldSmushPaused; +	_engineStartTime += (_system->getMillis() / 1000) - _dialogStartTime; +	_dialogStartTime = 0; +  	// Return the result  	return result;  } diff --git a/scumm/scumm.h b/scumm/scumm.h index 38753045a6..1d3b07cb72 100644 --- a/scumm/scumm.h +++ b/scumm/scumm.h @@ -309,6 +309,12 @@ struct AuxEntry {  	int subIndex;  }; +struct InfoStuff { +	uint32 date; +	uint16 time; +	uint32 playtime; +}; +  class ResourceManager {  	friend class ScummDebugger;  	friend class ScummEngine; @@ -583,13 +589,19 @@ public:  	void requestSave(int slot, const char *name, bool temporary = false);  	void requestLoad(int slot); -// thumbnail stuff +// thumbnail + info stuff  public:  	Graphics::Surface *loadThumbnailFromSlot(int slot); +	bool loadInfosFromSlot(int slot, InfoStuff *stuff);  protected:  	Graphics::Surface *loadThumbnail(Common::InSaveFile *file); +	bool loadInfos(Common::InSaveFile *file, InfoStuff *stuff);  	void saveThumbnail(Common::OutSaveFile *file); +	void saveInfos(Common::OutSaveFile* file); + +	int32 _engineStartTime; +	int32 _dialogStartTime;  protected:  	/* Script VM - should be in Script class */ | 
