aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohannes Schickel2008-03-26 21:17:07 +0000
committerJohannes Schickel2008-03-26 21:17:07 +0000
commit7c33605761fe6a1a0282b454ac36c37464e7f753 (patch)
tree479211eeb6da070ccdaa6f6c580602ba206b3e0b
parent6412c82bf7a88cd7262baf82707263a11932ce11 (diff)
downloadscummvm-rg350-7c33605761fe6a1a0282b454ac36c37464e7f753.tar.gz
scummvm-rg350-7c33605761fe6a1a0282b454ac36c37464e7f753.tar.bz2
scummvm-rg350-7c33605761fe6a1a0282b454ac36c37464e7f753.zip
Added support for HoF savefile from the original interpreter.
svn-id: r31249
-rw-r--r--engines/kyra/saveload.cpp2
-rw-r--r--engines/kyra/saveload_v2.cpp288
-rw-r--r--engines/kyra/timer.cpp12
-rw-r--r--engines/kyra/timer.h5
4 files changed, 228 insertions, 79 deletions
diff --git a/engines/kyra/saveload.cpp b/engines/kyra/saveload.cpp
index a0aaa05ba6..7d6fcaa0c1 100644
--- a/engines/kyra/saveload.cpp
+++ b/engines/kyra/saveload.cpp
@@ -52,7 +52,7 @@ Common::InSaveFile *KyraEngine::openSaveForReading(const char *filename, uint32
// following line to graciously handle old savegames from LE machines.
// if (type != MKID_BE('KYRA') && type != MKID_BE('ARYK')) {
if (type != MKID_BE(saveGameID())) {
- warning("No Kyrandia savefile header.");
+ warning("No ScummVM Kyra engine savefile header.");
delete in;
return 0;
}
diff --git a/engines/kyra/saveload_v2.cpp b/engines/kyra/saveload_v2.cpp
index add9c0638f..62cc11ca82 100644
--- a/engines/kyra/saveload_v2.cpp
+++ b/engines/kyra/saveload_v2.cpp
@@ -134,8 +134,45 @@ void KyraEngine_v2::loadGame(const char *fileName) {
uint32 version = 0;
char saveName[31];
Common::InSaveFile *in = openSaveForReading(fileName, version, saveName);
- if (!in)
- return;
+ if (!in) {
+ // check for original savefile
+ if (in = _saveFileMan->openForLoading(fileName)) {
+ in->seek(0x50, SEEK_CUR);
+
+ uint8 type[4];
+ uint8 acceptedType[4] = { 0x4D, 0x42, 0x4C, 0x33 }; // 'MBL3'
+ in->read(type, sizeof(type));
+ uint16 origVersion = in->readUint16LE();
+
+ debug(1, "Savegame type: '%c%c%c%c' version: %d", type[0], type[1], type[2], type[3], version);
+
+ if (!memcmp(type, acceptedType, 4) && origVersion == 100) {
+ warning("Trying to load savegame from original interpreter, while this is possible, it is not officially supported.");
+
+ in->seek(0, SEEK_SET);
+
+ // read first 31 bytes of original description
+ in->read(saveName, 30);
+ saveName[30] = 0;
+ // skip last part of original description
+ in->seek(0x50-30, SEEK_CUR);
+ version = 0xF000 + origVersion;
+ // skip type
+ in->seek(4, SEEK_CUR);
+ // skip version
+ in->seek(2, SEEK_CUR);
+ } else {
+ delete in;
+ in = 0;
+ }
+ }
+
+ if (!in) {
+ showMessageFromCCode(0x35, 0x84, 0);
+ snd_playSoundEffect(0x0D);
+ return;
+ }
+ }
bool setFlag1EE = (queryGameFlag(0x1EE) != 0);
@@ -150,82 +187,181 @@ void KyraEngine_v2::loadGame(const char *fileName) {
_screen->hideMouse();
- _timer->loadDataFromFile(in, version);
-
- uint32 flagsSize = in->readUint32BE();
- assert(flagsSize <= sizeof(_flagsTable));
- in->read(_flagsTable, flagsSize);
-
- // usually we have to save the flag set by opcode 10 here
- //word_2AB05 = in->readUint16BE();
- _lastMusicCommand = in->readSint16BE();
- _newChapterFile = in->readByte();
- _loadedZTable = in->readByte();
- _cauldronState = in->readByte();
- _colorCodeFlag1 = in->readByte();
- _colorCodeFlag2 = in->readByte();
- _bookCurPage = in->readByte();
- _bookMaxPage = in->readByte();
- for (int i = 0; i < 7; ++i)
- _presetColorCode[i] = in->readByte();
- for (int i = 0; i < 7; ++i)
- _inputColorCode[i] = in->readByte();
- for (int i = 0; i < 25; ++i)
- _cauldronTable[i] = in->readSint16BE();
- for (int i = 0; i < 20; ++i)
- _hiddenItems[i] = in->readUint16BE();
- for (int i = 0; i < 19; ++i)
- in->read(_conversationState[i], 14);
- in->read(_newSceneDlgState, 32);
- _cauldronUseCount = in->readSint16BE();
-
- _mainCharacter.sceneId = in->readUint16BE();
- _mainCharacter.dlgIndex = in->readUint16BE();
- _mainCharacter.height = in->readByte();
- _mainCharacter.facing = in->readByte();
- _mainCharacter.animFrame = in->readUint16BE();
- _mainCharacter.unk8 = in->readByte();
- _mainCharacter.unk9 = in->readByte();
- _mainCharacter.unkA = in->readByte();
- for (int i = 0; i < 20; ++i)
- _mainCharacter.inventory[i] = in->readUint16BE();
- _mainCharacter.x1 = in->readSint16BE();
- _mainCharacter.y1 = in->readSint16BE();
- _mainCharacter.x2 = in->readSint16BE();
- _mainCharacter.y2 = in->readSint16BE();
-
- for (int i = 0; i < 30; ++i) {
- _itemList[i].id = in->readUint16BE();
- _itemList[i].sceneId = in->readUint16BE();
- _itemList[i].x = in->readSint16BE();
- _itemList[i].y = in->readByte();
- _itemList[i].unk7 = in->readUint16BE();
- }
-
- for (int i = 0; i < 72; ++i) {
- in->read(_talkObjectList[i].filename, 13);
- _talkObjectList[i].scriptId = in->readByte();
- _talkObjectList[i].x = in->readSint16BE();
- _talkObjectList[i].y = in->readSint16BE();
- _talkObjectList[i].color = in->readByte();
+ if (version < 0xF000) {
+ _timer->loadDataFromFile(in, version);
+
+ uint32 flagsSize = in->readUint32BE();
+ assert(flagsSize <= sizeof(_flagsTable));
+ in->read(_flagsTable, flagsSize);
+
+ // usually we have to save the flag set by opcode 10 here
+ //word_2AB05 = in->readUint16BE();
+ _lastMusicCommand = in->readSint16BE();
+ _newChapterFile = in->readByte();
+ _loadedZTable = in->readByte();
+ _cauldronState = in->readByte();
+ _colorCodeFlag1 = in->readByte();
+ _colorCodeFlag2 = in->readByte();
+ _bookCurPage = in->readByte();
+ _bookMaxPage = in->readByte();
+ for (int i = 0; i < 7; ++i)
+ _presetColorCode[i] = in->readByte();
+ for (int i = 0; i < 7; ++i)
+ _inputColorCode[i] = in->readByte();
+ for (int i = 0; i < 25; ++i)
+ _cauldronTable[i] = in->readSint16BE();
+ for (int i = 0; i < 20; ++i)
+ _hiddenItems[i] = in->readUint16BE();
+ for (int i = 0; i < 19; ++i)
+ in->read(_conversationState[i], 14);
+ in->read(_newSceneDlgState, 32);
+ _cauldronUseCount = in->readSint16BE();
+
+ _mainCharacter.sceneId = in->readUint16BE();
+ _mainCharacter.dlgIndex = in->readUint16BE();
+ _mainCharacter.height = in->readByte();
+ _mainCharacter.facing = in->readByte();
+ _mainCharacter.animFrame = in->readUint16BE();
+ _mainCharacter.unk8 = in->readByte();
+ _mainCharacter.unk9 = in->readByte();
+ _mainCharacter.unkA = in->readByte();
+ for (int i = 0; i < 20; ++i)
+ _mainCharacter.inventory[i] = in->readUint16BE();
+ _mainCharacter.x1 = in->readSint16BE();
+ _mainCharacter.y1 = in->readSint16BE();
+ _mainCharacter.x2 = in->readSint16BE();
+ _mainCharacter.y2 = in->readSint16BE();
+
+ for (int i = 0; i < 30; ++i) {
+ _itemList[i].id = in->readUint16BE();
+ _itemList[i].sceneId = in->readUint16BE();
+ _itemList[i].x = in->readSint16BE();
+ _itemList[i].y = in->readByte();
+ _itemList[i].unk7 = in->readUint16BE();
+ }
+
+ for (int i = 0; i < 72; ++i) {
+ in->read(_talkObjectList[i].filename, 13);
+ _talkObjectList[i].scriptId = in->readByte();
+ _talkObjectList[i].x = in->readSint16BE();
+ _talkObjectList[i].y = in->readSint16BE();
+ _talkObjectList[i].color = in->readByte();
+ }
+
+ for (int i = 0; i < 86; ++i) {
+ in->read(_sceneList[i].filename, 10);
+ _sceneList[i].exit1 = in->readUint16BE();
+ _sceneList[i].exit2 = in->readUint16BE();
+ _sceneList[i].exit3 = in->readUint16BE();
+ _sceneList[i].exit4 = in->readUint16BE();
+ _sceneList[i].flags = in->readByte();
+ _sceneList[i].sound = in->readByte();
+ }
+
+ _itemInHand = in->readSint16BE();
+ _sceneExit1 = in->readUint16BE();
+ _sceneExit2 = in->readUint16BE();
+ _sceneExit3 = in->readUint16BE();
+ _sceneExit4 = in->readUint16BE();
+ } else {
+ version -= 0xF000;
+
+ /*word_2AB05 = */in->readUint16LE();
+ _lastMusicCommand = in->readSint16LE();
+ _newChapterFile = in->readByte();
+ _loadedZTable = in->readByte();
+ _cauldronState = in->readByte();
+ _colorCodeFlag1 = in->readByte();
+ _colorCodeFlag2 = in->readByte();
+ _bookCurPage = in->readByte();
+ _bookMaxPage = in->readByte();
+
+ for (int i = 0; i < 7; ++i)
+ _presetColorCode[i] = in->readByte();
+ for (int i = 0; i < 7; ++i)
+ _inputColorCode[i] = in->readByte();
+ for (int i = 0; i < 25; ++i)
+ _cauldronTable[i] = in->readSint16LE();
+ for (int i = 0; i < 20; ++i)
+ _hiddenItems[i] = in->readUint16LE();
+
+ assert(sizeof(_flagsTable) >= 0x41);
+ in->read(_flagsTable, 0x41);
+
+ for (int i = 0; i < 19; ++i)
+ in->read(_conversationState[i], 14);
+ for (int i = 0; i < 31; ++i)
+ _newSceneDlgState[i] = in->readUint16LE();
+ _cauldronUseCount = in->readSint16LE();
+ in->seek(6, SEEK_CUR);
+
+ _mainCharacter.sceneId = in->readUint16LE();
+ _mainCharacter.dlgIndex = in->readUint16LE();
+ _mainCharacter.height = in->readByte();
+ _mainCharacter.facing = in->readByte();
+ _mainCharacter.animFrame = in->readUint16LE();
+ _mainCharacter.unk8 = in->readByte();
+ _mainCharacter.unk9 = in->readByte();
+ _mainCharacter.unkA = in->readByte();
+ for (int i = 0; i < 20; ++i)
+ _mainCharacter.inventory[i] = in->readUint16LE();
+ _mainCharacter.x1 = in->readSint16LE();
+ _mainCharacter.y1 = in->readSint16LE();
+ _mainCharacter.x2 = in->readSint16LE();
+ _mainCharacter.y2 = in->readSint16LE();
+
+ for (int i = 0; i < 30; ++i) {
+ _itemList[i].id = in->readUint16LE();
+ _itemList[i].sceneId = in->readUint16LE();
+ _itemList[i].x = in->readSint16LE();
+ _itemList[i].y = in->readByte();
+ _itemList[i].unk7 = in->readUint16LE();
+ }
+
+ for (int i = 0; i < 72; ++i) {
+ in->read(_talkObjectList[i].filename, 13);
+ _talkObjectList[i].scriptId = in->readByte();
+ _talkObjectList[i].x = in->readSint16LE();
+ _talkObjectList[i].y = in->readSint16LE();
+ _talkObjectList[i].color = in->readByte();
+ }
+
+ for (int i = 0; i < 86; ++i) {
+ in->read(_sceneList[i].filename, 9);
+ _sceneList[i].filename[9] = 0;
+ _sceneList[i].exit1 = in->readUint16LE();
+ _sceneList[i].exit2 = in->readUint16LE();
+ _sceneList[i].exit3 = in->readUint16LE();
+ _sceneList[i].exit4 = in->readUint16LE();
+ _sceneList[i].flags = in->readByte();
+ _sceneList[i].sound = in->readByte();
+ }
+
+ _itemInHand = in->readSint16LE();
+
+ uint32 currentTime = _system->getMillis();
+
+ for (int i = 0; i < 6; ++i)
+ _timer->setDelay(i, in->readSint32LE());
+
+ for (int i = 0; i < 6; ++i) {
+ if (in->readUint16LE())
+ _timer->enable(i);
+ else
+ _timer->disable(i);
+ }
+
+ for (int i = 0; i < 6; ++i)
+ _timer->setNextRun(i, currentTime + (in->readUint32LE() * _tickLength));
+
+ _timer->resetNextRun();
+
+ _sceneExit1 = in->readUint16LE();
+ _sceneExit2 = in->readUint16LE();
+ _sceneExit3 = in->readUint16LE();
+ _sceneExit4 = in->readUint16LE();
}
- for (int i = 0; i < 86; ++i) {
- in->read(_sceneList[i].filename, 10);
- _sceneList[i].exit1 = in->readUint16BE();
- _sceneList[i].exit2 = in->readUint16BE();
- _sceneList[i].exit3 = in->readUint16BE();
- _sceneList[i].exit4 = in->readUint16BE();
- _sceneList[i].flags = in->readByte();
- _sceneList[i].sound = in->readByte();
- }
-
- _itemInHand = in->readSint16BE();
- _sceneExit1 = in->readUint16BE();
- _sceneExit2 = in->readUint16BE();
- _sceneExit3 = in->readUint16BE();
- _sceneExit4 = in->readUint16BE();
-
if (in->ioFailed())
error("Load failed ('%s', '%s').", fileName, saveName);
else
diff --git a/engines/kyra/timer.cpp b/engines/kyra/timer.cpp
index d14b22ef11..a2d5a0c7d9 100644
--- a/engines/kyra/timer.cpp
+++ b/engines/kyra/timer.cpp
@@ -164,6 +164,18 @@ int32 TimerManager::getDelay(uint8 id) const {
return -1;
}
+void TimerManager::setNextRun(uint8 id, uint32 nextRun) {
+ debugC(9, kDebugLevelTimer, "TimerManager::setNextRun(%d, %u)", id, nextRun);
+
+ Iterator timer = Common::find_if(_timers.begin(), _timers.end(), TimerEqual(id));
+ if (timer != _timers.end()) {
+ timer->nextRun = nextRun;
+ return;
+ }
+
+ warning("TimerManager::getNextRun: No timer %d", id);
+}
+
uint32 TimerManager::getNextRun(uint8 id) const {
debugC(9, kDebugLevelTimer, "TimerManager::getNextRun(%d)", id);
diff --git a/engines/kyra/timer.h b/engines/kyra/timer.h
index d3d6f6834d..d943ec5cb0 100644
--- a/engines/kyra/timer.h
+++ b/engines/kyra/timer.h
@@ -69,17 +69,18 @@ public:
void setCountdown(uint8 id, int32 countdown);
void setDelay(uint8 id, int32 countdown);
int32 getDelay(uint8 id) const;
+ void setNextRun(uint8 id, uint32 nextRun);
uint32 getNextRun(uint8 id) const;
bool isEnabled(uint8 id) const;
void enable(uint8 id);
void disable(uint8 id);
- void resync();
-
void loadDataFromFile(Common::InSaveFile *file, int version);
void saveDataToFile(Common::OutSaveFile *file) const;
private:
+ void resync();
+
KyraEngine *_vm;
OSystem *_system;
Common::List<TimerEntry> _timers;