diff --git a/engines/myst3/menu.cpp b/engines/myst3/menu.cpp index a32a9133a78..7cb6738768a 100644 --- a/engines/myst3/menu.cpp +++ b/engines/myst3/menu.cpp @@ -367,6 +367,38 @@ void Menu::saveMenuChangePage() { _vm->_state->setMenuSaveLoadSelectedItem(7); } +void Menu::saveMenuSave() { + if (_saveName.empty()) + return; + + Common::String fileName = _saveName; + if (!fileName.hasSuffix(".M3S") && !fileName.hasSuffix(".m3s")) + fileName += ".M3S"; + + // Check if file exists + bool fileExists = false; + for (uint i = 0; i < _saveLoadFiles.size(); i++) { + if (_saveLoadFiles[i].equalsIgnoreCase(fileName)) { + fileExists = true; + break; + } + } + + // Ask the user if he wants to overwrite the existing save + if (fileExists && _vm->openDialog(1040)) + return; + + // Save the state and the thumbnail + Common::OutSaveFile *save = _vm->getSaveFileManager()->openForSaving(fileName); + _vm->_state->save(save); + saveGameWriteThumbnail(save); + delete save; + + // Do next action + _vm->_state->setMenuNextAction(_vm->_state->getMenuSaveAction()); + _vm->runScriptsFromNode(88); +} + void Menu::draw() { uint16 node = _vm->_state->getLocationNode(); uint16 room = _vm->_state->getLocationRoom(); @@ -439,13 +471,12 @@ Common::String Menu::getAgeLabel(GameState *gameState) { } void Menu::saveGameReadThumbnail(Common::InSaveFile *save) { - // Start thumbnail data + // Start of thumbnail data save->seek(8580); - static const uint kMiniatureSize = 240 * 135; uint8 *thumbnail = new uint8[kMiniatureSize * 3]; - // The spot item expect RGB data instead of RGBA + // The spot item expects RGB data instead of RGBA uint8 *ptr = thumbnail; for (uint i = 0; i < kMiniatureSize; i++) { uint32 rgba = save->readUint32LE(); @@ -462,6 +493,21 @@ void Menu::saveGameReadThumbnail(Common::InSaveFile *save) { delete[] thumbnail; } +void Menu::saveGameWriteThumbnail(Common::OutSaveFile *save) { + // The file expects ARGB data instead of RGB + uint8 *src = (uint8 *)_saveThumb->pixels; + for (uint i = 0; i < kMiniatureSize; i++) { + uint8 r, g, b; + r = *src++; + g = *src++; + b = *src++; + save->writeByte(b); + save->writeByte(g); + save->writeByte(r); + save->writeByte(0xFF); // Alpha + } +} + Common::String Menu::prepareSaveNameForDisplay(const Common::String &name) { Common::String display = name; display.toUppercase(); @@ -482,11 +528,14 @@ void Menu::createThumbnail(Graphics::Surface *big, Graphics::Surface *small) { assert(big->format.bytesPerPixel == 3 && small->format.bytesPerPixel == 3); + uint bigHeight = big->h - Scene::kTopBorderHeight - Scene::kBottomBorderHeight; + uint bigYOffset = Scene::kBottomBorderHeight; + uint8 *dst = (uint8 *)small->pixels; for (uint i = 0; i < small->h; i++) { for (uint j = 0; j < small->w; j++) { uint32 srcX = big->w * j / small->w; - uint32 srcY = big->h - big->h * i / small->h; + uint32 srcY = bigYOffset + bigHeight - bigHeight * i / small->h; uint8 *src = (uint8 *)big->getBasePtr(srcX, srcY - 1); // Copy RGB bytes diff --git a/engines/myst3/menu.h b/engines/myst3/menu.h index e0dd2f23abf..00e5eac1fe6 100644 --- a/engines/myst3/menu.h +++ b/engines/myst3/menu.h @@ -55,6 +55,7 @@ public: void saveMenuOpen(); void saveMenuSelect(uint16 item); void saveMenuChangePage(); + void saveMenuSave(); void setSaveLoadSpotItem(SpotItemFace *spotItem) { _saveLoadSpotItem = spotItem; } private: @@ -69,11 +70,13 @@ private: Graphics::Surface *_saveThumb; static const uint kCaretSpeed = 25; + static const uint kMiniatureSize = 240 * 135; void saveLoadUpdateVars(); void createThumbnail(Graphics::Surface *big, Graphics::Surface *small); void saveGameReadThumbnail(Common::InSaveFile *save); + void saveGameWriteThumbnail(Common::OutSaveFile *save); Common::String getAgeLabel(GameState *gameState); Common::String prepareSaveNameForDisplay(const Common::String &name); diff --git a/engines/myst3/myst3.cpp b/engines/myst3/myst3.cpp index 1a099021a12..027f987c6c2 100644 --- a/engines/myst3/myst3.cpp +++ b/engines/myst3/myst3.cpp @@ -311,6 +311,10 @@ void Myst3Engine::drawFrame() { _movies[i]->draw(); } + if (_state->getViewType() == kMenu) { + _menu->draw(); + } + for (uint i = 0; i < _drawables.size(); i++) { _drawables[i]->draw(); } @@ -328,8 +332,6 @@ void Myst3Engine::drawFrame() { _scene->drawBlackBorders(); _inventory->draw(); - } else { - _menu->draw(); } _cursor->draw(); diff --git a/engines/myst3/puzzles.cpp b/engines/myst3/puzzles.cpp index e0514ed4758..675224f0f60 100644 --- a/engines/myst3/puzzles.cpp +++ b/engines/myst3/puzzles.cpp @@ -186,6 +186,9 @@ void Puzzles::saveLoadMenu(uint16 action, uint16 item) { case 4: _vm->_menu->saveMenuSelect(item); break; + case 5: + _vm->_menu->saveMenuSave(); + break; case 6: _vm->_menu->loadMenuChangePage(); break; diff --git a/engines/myst3/state.cpp b/engines/myst3/state.cpp index 6d363ddc8b3..62c52e2e5bd 100644 --- a/engines/myst3/state.cpp +++ b/engines/myst3/state.cpp @@ -95,6 +95,7 @@ GameState::GameState(Myst3Engine *vm): VAR(481, BookStateReleeshahn, false) VAR(1337, MenuEscapePressed, false) + VAR(1338, MenuNextAction, false) VAR(1339, MenuLoadBack, false) VAR(1340, MenuSaveBack, false) VAR(1341, MenuSaveAction, false) @@ -165,12 +166,18 @@ bool GameState::load(const Common::String &file) { Common::InSaveFile *save = _vm->getSaveFileManager()->openForLoading(file); Common::Serializer s = Common::Serializer(save, 0); syncWithSaveGame(s); - delete save; return true; } +bool GameState::save(Common::OutSaveFile *save) { + Common::Serializer s = Common::Serializer(0, save); + syncWithSaveGame(s); + + return true; +} + Common::Array GameState::getInventory() { Common::Array items; diff --git a/engines/myst3/state.h b/engines/myst3/state.h index 808361ebc15..a237c5b5287 100644 --- a/engines/myst3/state.h +++ b/engines/myst3/state.h @@ -24,6 +24,7 @@ #define VARIABLES_H_ #include "common/hashmap.h" +#include "common/savefile.h" #include "common/serializer.h" #include "engines/myst3/myst3.h" @@ -46,6 +47,7 @@ public: GameState(Myst3Engine *vm); virtual ~GameState(); bool load(const Common::String &file); + bool save(Common::OutSaveFile *save); int32 getVar(uint16 var); void setVar(uint16 var, int32 value); @@ -102,6 +104,7 @@ public: DECLARE_VAR(481, BookStateReleeshahn) DECLARE_VAR(1337, MenuEscapePressed) + DECLARE_VAR(1338, MenuNextAction) DECLARE_VAR(1339, MenuLoadBack) DECLARE_VAR(1340, MenuSaveBack) DECLARE_VAR(1341, MenuSaveAction)