diff --git a/engines/toltecs/animation.cpp b/engines/toltecs/animation.cpp index bd8fd7f46f4..5d601441f72 100644 --- a/engines/toltecs/animation.cpp +++ b/engines/toltecs/animation.cpp @@ -154,6 +154,20 @@ void AnimationPlayer::saveState(Common::WriteStream *out) { } void AnimationPlayer::loadState(Common::ReadStream *in) { + + _resIndex = in->readUint16LE(); + _width = in->readUint16LE(); + _height = in->readUint16LE(); + _frameCount = in->readUint16LE(); + _frameNumber = in->readUint16LE(); + _keepFrameCounter = in->readUint32LE(); + _curFrameSize = in->readUint32LE(); + _nextFrameSize = in->readUint32LE(); + _nextFrameOffset = in->readUint32LE(); + _firstCurFrameSize = in->readUint32LE(); + _firstNextFrameSize = in->readUint32LE(); + _firstNextFrameOffset = in->readUint32LE(); + } } // End of namespace Toltecs diff --git a/engines/toltecs/palette.cpp b/engines/toltecs/palette.cpp index 0f08694db0f..9692538169a 100644 --- a/engines/toltecs/palette.cpp +++ b/engines/toltecs/palette.cpp @@ -187,10 +187,30 @@ void Palette::saveState(Common::WriteStream *out) { } out->writeByte(_fragmentIndex); - } void Palette::loadState(Common::ReadStream *in) { + + // Save currently active palette + byte palette[768]; + in->read(palette, 768); + setFullPalette(palette); + + in->read(_mainPalette, 768); + in->read(_animPalette, 768); + in->read(_colorTransTable, 256); + + uint16 fragmentCount = in->readUint16LE(); + _fragments.clear(); + for (uint16 i = 0; i < fragmentCount; i++) { + PaletteFragment fragment; + fragment.id = in->readUint16LE(); + fragment.index = in->readByte(); + fragment.count = in->readByte(); + _fragments.push_back(fragment); + } + _fragmentIndex = in->readByte(); + } diff --git a/engines/toltecs/saveload.cpp b/engines/toltecs/saveload.cpp index 52325b9ab38..42ef4a33fb5 100644 --- a/engines/toltecs/saveload.cpp +++ b/engines/toltecs/saveload.cpp @@ -43,64 +43,61 @@ namespace Toltecs { -// TODO: Saveload is not working yet +/* TODO: + - Saveload is working so far but only one slot is supported until the game menu is implemented + - Save with F6; Load with F9 + - Saving during an animation (AnimationPlayer) is not working correctly yet + - Maybe switch to SCUMM/Tinsel serialization approach? +*/ + +#define SAVEGAME_VERSION 0 // 0 is dev version until in official SVN void ToltecsEngine::savegame(const char *filename) { Common::OutSaveFile *out; if (!(out = g_system->getSavefileManager()->openForSaving(filename))) { warning("Can't create file '%s', game not saved", filename); + return; } - // Save game variables - for (uint variable = 0; variable < 22; variable++) { - int16 value = _script->getGameVar(variable); - out->writeUint16LE(value); - } + out->writeUint32LE(SAVEGAME_VERSION); + + out->writeUint16LE(_cameraX); + out->writeUint16LE(_cameraY); + out->writeUint16LE(_cameraHeight); + + out->writeUint16LE(_guiHeight); + + out->writeUint16LE(_sceneWidth); + out->writeUint16LE(_sceneHeight); + out->writeUint32LE(_sceneResIndex); + + out->writeUint16LE(_walkSpeedX); + out->writeUint16LE(_walkSpeedY); + + out->writeUint32LE(_counter01); + out->writeUint32LE(_counter02); + out->writeByte(_movieSceneFlag ? 1 : 0); + out->writeByte(_flag01); _palette->saveState(out); _script->saveState(out); _anim->saveState(out); - - // Save GUI - { - - } + _screen->saveState(out); /* case 0: return "mouseDisabled"; case 1: return "mouseY"; case 2: return "mouseX"; case 3: return "mouseButton"; -case 4: return "verbLineY"; -case 5: return "verbLineX"; -case 6: return "verbLineWidth"; -case 7: return "verbLineCount"; -case 8: return "verbLineNum"; -case 9: return "talkTextItemNum"; -case 10: return "talkTextY"; -case 11: return "talkTextX"; -case 12: return "talkTextFontColor"; -case 13: return "cameraY"; -case 14: return "cameraX"; -case 15: return "walkSpeedY"; -case 16: return "walkSpeedX"; -case 17: return "flag01"; -case 18: return "sceneResIndex"; -case 19: return "cameraTop"; -case 20: return "sceneHeight"; -case 21: return "sceneWidth"; */ /* -PersistentGameVarRef -PersistentGameVarRef PersistentGameVarRef PersistentGameVarRef PersistentGameVarRef PersistentGameVarRef PersistentGameVarRef -PersistentGameVarRef */ delete out; @@ -108,7 +105,50 @@ PersistentGameVarRef } void ToltecsEngine::loadgame(const char *filename) { + + Common::InSaveFile *in; + if (!(in = g_system->getSavefileManager()->openForLoading(filename))) { + warning("Can't open file '%s', game not loaded", filename); + return; + } + + uint32 version = in->readUint32LE(); + if (version != SAVEGAME_VERSION) { + warning("Savegame '%s' too old, game not loaded (got v%d, need v%d)", filename, version, SAVEGAME_VERSION); + return; + } + + _cameraX = in->readUint16LE(); + _cameraY = in->readUint16LE(); + _cameraHeight = in->readUint16LE(); + + _guiHeight = in->readUint16LE(); + + _sceneWidth = in->readUint16LE(); + _sceneHeight = in->readUint16LE(); + _sceneResIndex = in->readUint32LE(); + + _walkSpeedX = in->readUint16LE(); + _walkSpeedY = in->readUint16LE(); + + _counter01 = in->readUint32LE(); + _counter02 = in->readUint32LE(); + _movieSceneFlag = in->readByte() != 0; + _flag01 = in->readByte(); + + _palette->loadState(in); + _script->loadState(in); + _anim->loadState(in); + _screen->loadState(in); + + delete in; + + loadScene(_sceneResIndex); + _screen->clearSprites(); + + _newCameraX = _cameraX; + _newCameraY = _cameraY; + } - } // End of namespace Toltecs diff --git a/engines/toltecs/screen.cpp b/engines/toltecs/screen.cpp index a11022cb13c..2ef4040fe8d 100644 --- a/engines/toltecs/screen.cpp +++ b/engines/toltecs/screen.cpp @@ -964,13 +964,105 @@ void Screen::drawChar2(const Font &font, byte *dest, int16 x, int16 y, byte ch, } void Screen::saveState(Common::WriteStream *out) { + + // Save verb line + out->writeUint16LE(_verbLineNum); + out->writeUint16LE(_verbLineX); + out->writeUint16LE(_verbLineY); + out->writeUint16LE(_verbLineWidth); + out->writeUint16LE(_verbLineCount); for (int i = 0; i < 8; i++) { out->writeUint16LE(_verbLineItems[i].slotIndex); out->writeUint16LE(_verbLineItems[i].slotOffset); } + + // Save talk text items + out->writeUint16LE(_talkTextX); + out->writeUint16LE(_talkTextY); + out->writeUint16LE(_talkTextMaxWidth); + out->writeByte(_talkTextFontColor); + out->writeUint16LE(_talkTextItemNum); + for (int i = 0; i < 5; i++) { + out->writeUint16LE(_talkTextItems[i].duration); + out->writeUint16LE(_talkTextItems[i].slotIndex); + out->writeUint16LE(_talkTextItems[i].slotOffset); + out->writeUint16LE(_talkTextItems[i].fontNum); + out->writeByte(_talkTextItems[i].color); + out->writeByte(_talkTextItems[i].rectCount); + for (int j = 0; j < _talkTextItems[i].rectCount; j++) { + out->writeUint16LE(_talkTextItems[i].rects[j].x); + out->writeUint16LE(_talkTextItems[i].rects[j].y); + out->writeUint16LE(_talkTextItems[i].rects[j].width); + out->writeUint16LE(_talkTextItems[i].rects[j].length); + } + } + + // Save GUI bitmap + { + byte *gui = _frontScreen + _vm->_cameraHeight * 640; + for (int i = 0; i < _vm->_guiHeight; i++) { + out->write(gui, 640); + gui += 640; + } + } + + // Save fonts + for (int i = 0; i < 10; i++) + out->writeUint32LE(_fontResIndexArray[i]); + out->writeByte(_fontColor1); + out->writeByte(_fontColor2); + } void Screen::loadState(Common::ReadStream *in) { + + // Load verb line + _verbLineNum = in->readUint16LE(); + _verbLineX = in->readUint16LE(); + _verbLineY = in->readUint16LE(); + _verbLineWidth = in->readUint16LE(); + _verbLineCount = in->readUint16LE(); + for (int i = 0; i < 8; i++) { + _verbLineItems[i].slotIndex = in->readUint16LE(); + _verbLineItems[i].slotOffset = in->readUint16LE(); + } + + // Load talk text items + _talkTextX = in->readUint16LE(); + _talkTextY = in->readUint16LE(); + _talkTextMaxWidth = in->readUint16LE(); + _talkTextFontColor = in->readByte(); + _talkTextItemNum = in->readUint16LE(); + for (int i = 0; i < 5; i++) { + _talkTextItems[i].duration = in->readUint16LE(); + _talkTextItems[i].slotIndex = in->readUint16LE(); + _talkTextItems[i].slotOffset = in->readUint16LE(); + _talkTextItems[i].fontNum = in->readUint16LE(); + _talkTextItems[i].color = in->readByte(); + _talkTextItems[i].rectCount = in->readByte(); + for (int j = 0; j < _talkTextItems[i].rectCount; j++) { + _talkTextItems[i].rects[j].x = in->readUint16LE(); + _talkTextItems[i].rects[j].y = in->readUint16LE(); + _talkTextItems[i].rects[j].width = in->readUint16LE(); + _talkTextItems[i].rects[j].length = in->readUint16LE(); + } + } + + // Load GUI bitmap + { + byte *gui = _frontScreen + _vm->_cameraHeight * 640; + for (int i = 0; i < _vm->_guiHeight; i++) { + in->read(gui, 640); + gui += 640; + } + } + + // Load fonts + for (int i = 0; i < 10; i++) + _fontResIndexArray[i] = in->readUint32LE(); + _fontColor1 = in->readByte(); + _fontColor2 = in->readByte(); + } diff --git a/engines/toltecs/script.cpp b/engines/toltecs/script.cpp index fa382194f86..c71d5d235bc 100644 --- a/engines/toltecs/script.cpp +++ b/engines/toltecs/script.cpp @@ -1243,10 +1243,43 @@ void ScriptInterpreter::saveState(Common::WriteStream *out) { // Save stack out->write(_stack, kScriptStackSize); out->writeUint16LE(_savedSp); + + // Save IP + out->writeUint16LE((int16)(_code - getSlotData(_regs.reg4))); } void ScriptInterpreter::loadState(Common::ReadStream *in) { + + // Load registers + _regs.reg0 = in->readUint16LE(); + _regs.reg1 = in->readUint16LE(); + _regs.reg2 = in->readUint16LE(); + _regs.reg3 = in->readUint16LE(); + _regs.reg4 = in->readUint16LE(); + _regs.reg5 = in->readUint16LE(); + _regs.reg6 = in->readUint16LE(); + _regs.sp = in->readUint16LE(); + _regs.reg8 = in->readUint16LE(); + + // Load slots + for (int slot = 0; slot < kMaxScriptSlots; slot++) { + _slots[slot].size = in->readUint32LE(); + _slots[slot].resIndex = in->readUint16LE(); + _slots[slot].data = NULL; + if (_slots[slot].size > 0) { + _slots[slot].data = new byte[_slots[slot].size]; + in->read(_slots[slot].data, _slots[slot].size); + } + } + + // Load stack + in->read(_stack, kScriptStackSize); + _savedSp = in->readUint16LE(); + + // Load IP + _code = getSlotData(_regs.reg4) + in->readUint16LE(); + } } // End of namespace Toltecs