MYST3: Add save support

This commit is contained in:
Bastien Bouclet 2012-01-13 14:11:09 +01:00
parent 931db3668a
commit 9b229d3eb1
6 changed files with 74 additions and 7 deletions

View File

@ -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

View File

@ -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);

View File

@ -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();

View File

@ -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;

View File

@ -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<uint16> GameState::getInventory() {
Common::Array<uint16> items;

View File

@ -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)