mirror of
https://github.com/libretro/scummvm.git
synced 2025-03-01 07:46:11 +00:00
KYRA: add more metadata to savegames
(creation date/time and playing time)
This commit is contained in:
parent
34007cb7c2
commit
d8004bebba
@ -213,6 +213,8 @@ bool CharacterGenerator::start(EoBCharacter *characters, const uint8 ***faceShap
|
||||
_vm->snd_stopSound();
|
||||
_vm->delay(_vm->_tickLength);
|
||||
|
||||
_vm->restartPlayTimerAt(0);
|
||||
|
||||
init(defaultParty);
|
||||
|
||||
if (defaultParty)
|
||||
|
@ -1019,7 +1019,6 @@ void EoBEngine::displayParchment(int id) {
|
||||
if (id < 46 || id > 50)
|
||||
return;
|
||||
|
||||
uint32 startTime = _system->getMillis();
|
||||
disableSysTimer(2);
|
||||
|
||||
_screen->sega_fadeToBlack(2);
|
||||
@ -1077,7 +1076,6 @@ void EoBEngine::displayParchment(int id) {
|
||||
snd_playLevelScore();
|
||||
|
||||
enableSysTimer(2);
|
||||
_totalPlaySecs += ((_system->getMillis() - startTime) / 1000);
|
||||
}
|
||||
|
||||
const uint8 **EoBEngine::makePortalShapes() {
|
||||
|
@ -242,7 +242,7 @@ EoBCoreEngine::EoBCoreEngine(OSystem *system, const GameFlags &flags) : KyraRpgE
|
||||
_amigaSoundMap = 0;
|
||||
_amigaCurSoundFile = -1;
|
||||
_prefMenuPlatformOffset = 0;
|
||||
_lastVIntTick = _lastSecTick = _totalPlaySecs = _totalEnemiesKilled = _totalSteps = 0;
|
||||
_lastVIntTick = _totalEnemiesKilled = _totalSteps = 0;
|
||||
_levelMaps = 0;
|
||||
_closeSpellbookAfterUse = false;
|
||||
_wndBackgrnd = 0;
|
||||
@ -734,7 +734,8 @@ void EoBCoreEngine::runLoop() {
|
||||
if (_sceneUpdateRequired && !_sceneShakeCountdown)
|
||||
drawScene(1);
|
||||
|
||||
updateAnimTimers();
|
||||
updatePlayTimer();
|
||||
updateAnimations();
|
||||
|
||||
uint32 curTime = _system->getMillis();
|
||||
if (_envAudioTimer < curTime && !(_flags.gameID == GI_EOB1 && (_flags.platform == Common::kPlatformSegaCD || _flags.platform == Common::kPlatformAmiga || _currentLevel == 0 || _currentLevel > 3))) {
|
||||
@ -786,13 +787,8 @@ bool EoBCoreEngine::checkPartyStatus(bool handleDeath) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void EoBCoreEngine::updateAnimTimers() {
|
||||
void EoBCoreEngine::updateAnimations() {
|
||||
uint32 curTime = _system->getMillis();
|
||||
if (_lastSecTick + 1000 <= curTime) {
|
||||
_lastSecTick = curTime;
|
||||
_totalPlaySecs++;
|
||||
}
|
||||
|
||||
if (_lastVIntTick + 16 <= curTime) {
|
||||
_lastVIntTick = curTime;
|
||||
gui_updateAnimations();
|
||||
|
@ -343,7 +343,7 @@ protected:
|
||||
void runLoop();
|
||||
void update() override { screen()->updateScreen(); }
|
||||
bool checkPartyStatus(bool handleDeath);
|
||||
void updateAnimTimers();
|
||||
void updateAnimations();
|
||||
|
||||
bool _runFlag;
|
||||
|
||||
@ -389,8 +389,6 @@ protected:
|
||||
uint32 _restPartyElapsedTime;
|
||||
|
||||
uint32 _lastVIntTick;
|
||||
uint32 _lastSecTick;
|
||||
uint32 _totalPlaySecs;
|
||||
uint32 _totalEnemiesKilled;
|
||||
uint32 _totalSteps;
|
||||
|
||||
|
@ -377,6 +377,7 @@ void KyraEngine_HoF::startup() {
|
||||
loadNPCScript();
|
||||
|
||||
if (_gameToLoad == -1) {
|
||||
restartPlayTimerAt(0);
|
||||
snd_playWanderScoreViaMap(52, 1);
|
||||
enterNewScene(_mainCharacter.sceneId, _mainCharacter.facing, 0, 0, 1);
|
||||
saveGameStateIntern(0, "New Game", nullptr);
|
||||
@ -446,6 +447,7 @@ void KyraEngine_HoF::runLoop() {
|
||||
removeInputTop();
|
||||
|
||||
update();
|
||||
updatePlayTimer();
|
||||
|
||||
if (inputFlag == 198 || inputFlag == 199) {
|
||||
_savedMouseState = _mouseState;
|
||||
|
@ -428,6 +428,7 @@ void KyraEngine_LoK::startup() {
|
||||
_gui->buttonMenuCallback(nullptr);
|
||||
_menuDirectlyToLoad = false;
|
||||
} else if (!shouldQuit()) {
|
||||
restartPlayTimerAt(0);
|
||||
saveGameStateIntern(0, "New game", nullptr);
|
||||
}
|
||||
} else {
|
||||
@ -484,6 +485,7 @@ void KyraEngine_LoK::mainLoop() {
|
||||
_timer->update();
|
||||
_sound->process();
|
||||
updateTextFade();
|
||||
updatePlayTimer();
|
||||
|
||||
if (inputFlag == 198 || inputFlag == 199)
|
||||
processInput(_mouseX, _mouseY);
|
||||
|
@ -613,6 +613,7 @@ void KyraEngine_MR::startup() {
|
||||
assert(_invWsa);
|
||||
_invWsa->open("MOODOMTR.WSA", 1, nullptr);
|
||||
_invWsaFrame = 6;
|
||||
restartPlayTimerAt(0);
|
||||
saveGameStateIntern(0, "New Game", nullptr);
|
||||
if (_gameToLoad == -1)
|
||||
enterNewScene(_mainCharacter.sceneId, _mainCharacter.facing, 0, 0, 1);
|
||||
@ -926,6 +927,7 @@ void KyraEngine_MR::runLoop() {
|
||||
|
||||
update();
|
||||
_timer->update();
|
||||
updatePlayTimer();
|
||||
|
||||
if (inputFlag == 198 || inputFlag == 199) {
|
||||
_savedMouseState = _mouseState;
|
||||
|
@ -63,6 +63,7 @@ KyraEngine_v1::KyraEngine_v1(OSystem *system, const GameFlags &flags)
|
||||
memset(_flagsTable, 0, sizeof(_flagsTable));
|
||||
|
||||
_isSaveAllowed = false;
|
||||
_totalPlaySecs = _lastSecTick = _lastSecTickAtPauseStart = 0;
|
||||
|
||||
_mouseX = _mouseY = 0;
|
||||
_transOffsY = 0;
|
||||
@ -75,6 +76,7 @@ void KyraEngine_v1::pauseEngineIntern(bool pause) {
|
||||
_sound->pause(pause);
|
||||
if (_timer)
|
||||
_timer->pause(pause);
|
||||
pausePlayTimer(pause);
|
||||
}
|
||||
|
||||
Common::Error KyraEngine_v1::init() {
|
||||
@ -706,4 +708,24 @@ void KyraEngine_v1::syncSoundSettings() {
|
||||
_sound->updateVolumeSettings();
|
||||
}
|
||||
|
||||
void KyraEngine_v1::updatePlayTimer() {
|
||||
uint32 curTime = _system->getMillis();
|
||||
while (_lastSecTick + 1000 <= curTime) {
|
||||
_lastSecTick += 1000;
|
||||
_totalPlaySecs++;
|
||||
}
|
||||
}
|
||||
|
||||
void KyraEngine_v1::restartPlayTimerAt(uint32 totalPlaySecs) {
|
||||
_lastSecTick = _system->getMillis();
|
||||
_totalPlaySecs = totalPlaySecs;
|
||||
}
|
||||
|
||||
void KyraEngine_v1::pausePlayTimer(bool pause) {
|
||||
if (pause)
|
||||
_lastSecTickAtPauseStart = _lastSecTick;
|
||||
else
|
||||
_lastSecTick += (_system->getMillis() - _lastSecTickAtPauseStart);
|
||||
}
|
||||
|
||||
} // End of namespace Kyra
|
||||
|
@ -904,6 +904,8 @@ void LoLEngine::runLoop() {
|
||||
|
||||
update();
|
||||
|
||||
updatePlayTimer();
|
||||
|
||||
if (_sceneUpdateRequired)
|
||||
gui_drawScene(0);
|
||||
else
|
||||
|
@ -427,7 +427,7 @@ void EoBCoreEngine::sparkEffectDefensive(int charIndex) {
|
||||
_screen->drawShape(0, _sparkShapes[shpIndex - 1], x, y, 0);
|
||||
}
|
||||
}
|
||||
updateAnimTimers();
|
||||
updateAnimations();
|
||||
_screen->updateScreen();
|
||||
delay(_tickLength >> 1);
|
||||
}
|
||||
@ -446,7 +446,7 @@ void EoBCoreEngine::sparkEffectOffensive() {
|
||||
|
||||
for (int i = 0; i < 44; i++) {
|
||||
bool sceneShake = _sceneShakeCountdown;
|
||||
updateAnimTimers();
|
||||
updateAnimations();
|
||||
if (sceneShake) {
|
||||
_screen->copyRegion(0, 0, 0, 0, 176, 120, 0, 2, Screen::CR_NO_P_CHECK);
|
||||
if (!_sceneShakeCountdown) {
|
||||
|
@ -578,7 +578,7 @@ void EoBCoreEngine::drawScene(int refresh) {
|
||||
int diff = _flashShapeTimer - ct;
|
||||
while ((diff > 0) && !shouldQuit()) {
|
||||
updateInput();
|
||||
updateAnimTimers();
|
||||
updateAnimations();
|
||||
uint32 step = MIN<uint32>(diff, _tickLength / 5);
|
||||
_system->delayMillis(step);
|
||||
diff -= step;
|
||||
|
@ -3192,6 +3192,7 @@ bool GUI_EoB::runSaveMenu(int x, int y) {
|
||||
// does not survive this conversion. And the rest of the characters in these descriptions do not require it.
|
||||
if (!(_vm->gameFlags().platform == Common::kPlatformSegaCD && _vm->gameFlags().lang == Common::JA_JPN && Common::String(temp).contains('\r')))
|
||||
Util::convertDOSToUTF8(temp, 26);
|
||||
_vm->updatePlayTimer();
|
||||
Common::Error err = _vm->saveGameStateIntern(_savegameOffset + slot, temp, &thumb);
|
||||
thumb.free();
|
||||
|
||||
|
@ -34,7 +34,6 @@
|
||||
namespace Kyra {
|
||||
|
||||
int EoBEngine::clickedCamp(Button *button) {
|
||||
uint32 startTime = _system->getMillis();
|
||||
gui_resetAnimations();
|
||||
|
||||
if (_flags.platform == Common::kPlatformSegaCD)
|
||||
@ -46,7 +45,6 @@ int EoBEngine::clickedCamp(Button *button) {
|
||||
return button->arg;
|
||||
|
||||
gui_resetAnimations();
|
||||
_totalPlaySecs += ((_system->getMillis() - startTime) / 1000);
|
||||
|
||||
return button->arg;
|
||||
}
|
||||
@ -231,7 +229,6 @@ void EoBEngine::gui_drawCharacterStatsPage() {
|
||||
}
|
||||
|
||||
void EoBEngine::gui_displayMap() {
|
||||
uint32 startTime = _system->getMillis();
|
||||
disableSysTimer(2);
|
||||
|
||||
_screen->sega_fadeToBlack(2);
|
||||
@ -322,7 +319,6 @@ void EoBEngine::gui_displayMap() {
|
||||
snd_playLevelScore();
|
||||
|
||||
enableSysTimer(2);
|
||||
_totalPlaySecs += ((_system->getMillis() - startTime) / 1000);
|
||||
}
|
||||
|
||||
void EoBEngine::gui_drawSpellbook() {
|
||||
|
@ -791,7 +791,7 @@ int GUI_LoK::saveGame(Button *button) {
|
||||
_vm->_gameToLoad = getNextSavegameSlot();
|
||||
if (_vm->_gameToLoad > 0) {
|
||||
Util::convertDOSToUTF8(_savegameName, 35);
|
||||
|
||||
_vm->updatePlayTimer();
|
||||
Graphics::Surface thumb;
|
||||
createScreenThumbnail(thumb);
|
||||
_vm->saveGameStateIntern(_vm->_gameToLoad, _savegameName, &thumb);
|
||||
|
@ -2848,6 +2848,7 @@ int GUI_LoL::clickedSavenameMenu(Button *button) {
|
||||
int slot = _menuResult == -2 ? getNextSavegameSlot() : _menuResult - 1;
|
||||
Graphics::Surface thumb;
|
||||
createScreenThumbnail(thumb);
|
||||
_vm->updatePlayTimer();
|
||||
_vm->saveGameStateIntern(slot, _saveDescription, &thumb);
|
||||
thumb.free();
|
||||
|
||||
|
@ -638,6 +638,7 @@ int GUI_v2::saveMenu(Button *caller) {
|
||||
|
||||
Graphics::Surface thumb;
|
||||
createScreenThumbnail(thumb);
|
||||
_vm->updatePlayTimer();
|
||||
Util::convertDOSToUTF8(_saveDescription, 81);
|
||||
_vm->saveGameStateIntern(_saveSlot, _saveDescription, &thumb);
|
||||
thumb.free();
|
||||
|
@ -28,7 +28,7 @@
|
||||
#include "graphics/thumbnail.h"
|
||||
#include "graphics/surface.h"
|
||||
|
||||
#define CURRENT_SAVE_VERSION 20
|
||||
#define CURRENT_SAVE_VERSION 21
|
||||
|
||||
#define GF_FLOPPY (1 << 0)
|
||||
#define GF_TALKIE (1 << 1)
|
||||
@ -134,6 +134,20 @@ WARN_UNUSED_RESULT KyraEngine_v1::ReadSaveHeaderError KyraEngine_v1::readSaveHea
|
||||
header.thumbnail = nullptr;
|
||||
}
|
||||
|
||||
if (header.version >= 21) {
|
||||
header.timeDate.tm_sec = in->readSint32BE();
|
||||
header.timeDate.tm_min = in->readSint32BE();
|
||||
header.timeDate.tm_hour = in->readSint32BE();
|
||||
header.timeDate.tm_mday = in->readSint32BE();
|
||||
header.timeDate.tm_mon = in->readSint32BE();
|
||||
header.timeDate.tm_year = in->readSint32BE();
|
||||
header.timeDate.tm_wday = in->readSint32BE();
|
||||
header.totalPlaySecs = in->readUint32BE();
|
||||
} else {
|
||||
header.totalPlaySecs = 0;
|
||||
memset(&header.timeDate, 0, sizeof(TimeDate));
|
||||
}
|
||||
|
||||
return ((in->err() || in->eos()) ? kRSHEIoError : kRSHENoError);
|
||||
}
|
||||
|
||||
@ -228,6 +242,19 @@ Common::OutSaveFile *KyraEngine_v1::openSaveForWriting(const char *filename, con
|
||||
delete genThumbnail;
|
||||
}
|
||||
|
||||
TimeDate td;
|
||||
_system->getTimeAndDate(td);
|
||||
|
||||
out->writeSint32BE(td.tm_sec);
|
||||
out->writeSint32BE(td.tm_min);
|
||||
out->writeSint32BE(td.tm_hour);
|
||||
out->writeSint32BE(td.tm_mday);
|
||||
out->writeSint32BE(td.tm_mon);
|
||||
out->writeSint32BE(td.tm_year);
|
||||
out->writeSint32BE(td.tm_wday);
|
||||
|
||||
out->writeUint32BE(_totalPlaySecs);
|
||||
|
||||
return new Common::OutSaveFile(out);
|
||||
}
|
||||
|
||||
|
@ -140,7 +140,8 @@ Common::Error EoBCoreEngine::loadGameState(int slot) {
|
||||
_returnAfterSpellCallback = in.readByte() ? true : false;
|
||||
|
||||
if (_flags.platform == Common::kPlatformSegaCD || header.version > 18) {
|
||||
_totalPlaySecs = in.readUint32BE();
|
||||
if (header.version < 21)
|
||||
header.totalPlaySecs = in.readUint32BE();
|
||||
_totalEnemiesKilled = in.readUint32BE();
|
||||
_totalSteps = in.readUint32BE();
|
||||
_levelMaps = in.readUint32BE();
|
||||
@ -312,6 +313,8 @@ Common::Error EoBCoreEngine::loadGameState(int slot) {
|
||||
if (_flags.platform != Common::kPlatformSegaCD)
|
||||
_screen->fadeFromBlack(20);
|
||||
|
||||
restartPlayTimerAt(header.totalPlaySecs);
|
||||
|
||||
_loading = false;
|
||||
removeInputTop();
|
||||
|
||||
@ -419,7 +422,6 @@ Common::Error EoBCoreEngine::saveGameStateIntern(int slot, const char *saveName,
|
||||
out->writeByte(_returnAfterSpellCallback ? 1 : 0);
|
||||
|
||||
// SegaCD specific
|
||||
out->writeUint32BE(_totalPlaySecs);
|
||||
out->writeUint32BE(_totalEnemiesKilled);
|
||||
out->writeUint32BE(_totalSteps);
|
||||
out->writeUint32BE(_levelMaps);
|
||||
|
@ -304,6 +304,8 @@ Common::Error KyraEngine_HoF::loadGameState(int slot) {
|
||||
_mainCharY = _mainCharacter.y2 = _mainCharacter.y1;
|
||||
_mainCharacter.facing = 4;
|
||||
|
||||
restartPlayTimerAt(header.totalPlaySecs);
|
||||
|
||||
enterNewScene(_mainCharacter.sceneId, _mainCharacter.facing, 0, 0, 1);
|
||||
setHandItem(_itemInHand);
|
||||
|
||||
|
@ -211,6 +211,8 @@ Common::Error KyraEngine_LoK::loadGameState(int slot) {
|
||||
// #4625 "KYRA1: Invisible Brandon" for an example of this.
|
||||
_animator->_noDrawShapesFlag = 0;
|
||||
|
||||
restartPlayTimerAt(header.totalPlaySecs);
|
||||
|
||||
enterNewScene(_currentCharacter->sceneId, _currentCharacter->facing, 0, 0, 1);
|
||||
|
||||
_animator->animRefreshNPC(0);
|
||||
|
@ -322,6 +322,8 @@ Common::Error LoLEngine::loadGameState(int slot) {
|
||||
setHandItem(_itemInHand);
|
||||
loadLevel(_currentLevel);
|
||||
gui_drawPlayField();
|
||||
restartPlayTimerAt(header.totalPlaySecs);
|
||||
|
||||
timerSpecialCharacterUpdate(0);
|
||||
_flagsTable[73] |= 0x08;
|
||||
|
||||
|
@ -303,6 +303,8 @@ Common::Error KyraEngine_MR::loadGameState(int slot) {
|
||||
_goodConscienceShown = false;
|
||||
_goodConsciencePosition = false;
|
||||
|
||||
restartPlayTimerAt(header.totalPlaySecs);
|
||||
|
||||
enterNewScene(_mainCharacter.sceneId, _mainCharacter.facing, 0, 0, 1);
|
||||
setHandItem(_itemInHand);
|
||||
|
||||
|
@ -69,7 +69,6 @@ class KyraMetaEngine;
|
||||
* Some execeptions:
|
||||
* - The PC-98 version of Eye of the Beholder II is not yet supported.
|
||||
* - We don't support NES or Gameboy versions of Eye of the Beholder.
|
||||
* - The Macintosh version of Kyrandia 1 lacks sound effects and music.
|
||||
*
|
||||
* The official translations of the games of which we are aware are mostly
|
||||
* supported. Some of the more rare versions (of which we don't even know
|
||||
@ -376,6 +375,9 @@ protected:
|
||||
bool oldHeader; // old scummvm save header
|
||||
|
||||
Graphics::Surface *thumbnail;
|
||||
|
||||
TimeDate timeDate;
|
||||
uint32 totalPlaySecs;
|
||||
};
|
||||
|
||||
enum ReadSaveHeaderError {
|
||||
@ -399,6 +401,15 @@ protected:
|
||||
|
||||
// TODO: Consider moving this to Screen
|
||||
virtual Graphics::Surface *generateSaveThumbnail() const { return 0; }
|
||||
|
||||
// Officially used in EOB SegaCD (appears in the final stats), but we also use this for the savegame metadata for all games.
|
||||
void updatePlayTimer();
|
||||
void restartPlayTimerAt(uint32 totalPlaySecs);
|
||||
void pausePlayTimer(bool pause);
|
||||
|
||||
uint32 _lastSecTick;
|
||||
uint32 _lastSecTickAtPauseStart;
|
||||
uint32 _totalPlaySecs;
|
||||
};
|
||||
|
||||
} // End of namespace Kyra
|
||||
|
@ -62,6 +62,8 @@ bool KyraMetaEngine::hasFeature(MetaEngineFeature f) const {
|
||||
(f == kSupportsDeleteSave) ||
|
||||
(f == kSavesSupportMetaInfo) ||
|
||||
(f == kSavesSupportThumbnail) ||
|
||||
(f == kSavesSupportCreationDate) ||
|
||||
(f == kSavesSupportPlayTime) ||
|
||||
(f == kSimpleSavesNames);
|
||||
}
|
||||
|
||||
@ -217,6 +219,12 @@ SaveStateDescriptor KyraMetaEngine::querySaveMetaInfos(const char *target, int s
|
||||
desc.setAutosave(true);
|
||||
desc.setThumbnail(header.thumbnail);
|
||||
|
||||
if (header.version >= 21) {
|
||||
desc.setPlayTime(header.totalPlaySecs * 1000);
|
||||
desc.setSaveDate(header.timeDate.tm_year + 1900, header.timeDate.tm_mon + 1, header.timeDate.tm_mday);
|
||||
desc.setSaveTime(header.timeDate.tm_hour, header.timeDate.tm_min);
|
||||
}
|
||||
|
||||
return desc;
|
||||
}
|
||||
}
|
||||
|
@ -2379,10 +2379,10 @@ void EoBEngine::seq_xdeath() {
|
||||
_screen->copyRegion(0, 0, 0, 0, 176, 120, 2, 0, Screen::CR_NO_P_CHECK);
|
||||
_screen->drawShape(0, shapes2, 32, 10, 0);
|
||||
_screen->updateScreen();
|
||||
updateAnimTimers();
|
||||
updateAnimations();
|
||||
delete[] shapes2;
|
||||
for (uint32 cur = _system->getMillis(); cur < del; cur = _system->getMillis()) {
|
||||
updateAnimTimers();
|
||||
updateAnimations();
|
||||
delay(MIN<uint32>(8, del - cur));
|
||||
}
|
||||
}
|
||||
@ -2817,7 +2817,6 @@ bool EoBEngine::seq_segaPlaySequence(int sequenceId, bool setupScreen) {
|
||||
if (_flags.platform != Common::kPlatformSegaCD)
|
||||
return true;
|
||||
|
||||
uint32 startTime = _system->getMillis();
|
||||
_allowSkip = true;
|
||||
resetSkipFlag();
|
||||
|
||||
@ -2832,8 +2831,6 @@ bool EoBEngine::seq_segaPlaySequence(int sequenceId, bool setupScreen) {
|
||||
if (setupScreen)
|
||||
seq_segaRestoreAfterSequence();
|
||||
|
||||
_totalPlaySecs += ((_system->getMillis() - startTime) / 1000);
|
||||
|
||||
if (!res)
|
||||
error("EoBEngine::seq_segaPlaySequence(): Failed to play cutscene no. %d", sequenceId);
|
||||
|
||||
|
@ -124,6 +124,7 @@ int LoLEngine::processPrologue() {
|
||||
}
|
||||
|
||||
if (processSelection == 0) {
|
||||
restartPlayTimerAt(0);
|
||||
if (_flags.isDemo) {
|
||||
_charSelection = 0;
|
||||
_screen->loadBitmap("ITEMICN.SHP", 3, 3, 0);
|
||||
|
Loading…
x
Reference in New Issue
Block a user