scummvm/engines/parallaction/saveload.cpp

417 lines
9.5 KiB
C++
Raw Normal View History

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#include "common/savefile.h"
#include "gui/dialog.h"
2007-02-11 21:17:37 +00:00
#include "gui/widget.h"
#include "gui/ListWidget.h"
#include "gui/message.h"
#include "parallaction/parallaction.h"
#include "parallaction/sound.h"
2007-05-13 14:38:05 +00:00
2007-02-18 08:45:22 +00:00
/* Nippon Safes savefiles are called 'game.0' to 'game.9'. The game conventiently allows users to
2007-02-11 21:17:37 +00:00
* give meanigful name to savegames, and it uses an extra file 'savegame' to keep track of these
* names.
*
* This re-implementation disposes of the extra file to make moving of savefiles easier. Debugging
* will benefit from this, too. The savegame name is written as the first line of the savefile
* itself, thus breaking compatibility with the original version. Who cares anyway?
*/
namespace Parallaction {
class SaveLoadChooser : public GUI::Dialog {
typedef Common::String String;
typedef Common::StringList StringList;
protected:
GUI::ListWidget *_list;
GUI::ButtonWidget *_chooseButton;
GUI::GraphicsWidget *_gfxWidget;
GUI::StaticTextWidget *_date;
GUI::StaticTextWidget *_time;
GUI::StaticTextWidget *_playtime;
GUI::ContainerWidget *_container;
Parallaction_ns *_vm;
uint8 _fillR, _fillG, _fillB;
public:
SaveLoadChooser(const String &title, const String &buttonLabel, Parallaction_ns *engine);
~SaveLoadChooser();
virtual void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data);
const String &getResultString() const;
void setList(const StringList& list);
int runModal();
virtual void reflowLayout();
};
void Parallaction_ns::doLoadGame(uint16 slot) {
_soundMan->stopMusic();
_introSarcData3 = 200;
_introSarcData2 = 1;
char filename[PATH_LEN];
2007-02-11 21:17:37 +00:00
sprintf(filename, "game.%i", slot);
Common::InSaveFile *f = _saveFileMan->openForLoading(filename);
if (!f) return;
char s[30];
char n[16];
char l[16];
2007-02-11 21:17:37 +00:00
f->readLine(s, 29);
2007-02-11 21:17:37 +00:00
f->readLine(n, 15);
f->readLine(l, 15);
f->readLine(s, 15);
_location._startPosition.x = atoi(s);
f->readLine(s, 15);
_location._startPosition.y = atoi(s);
f->readLine(s, 15);
_score = atoi(s);
f->readLine(s, 15);
_commandFlags = atoi(s);
f->readLine(s, 15);
// TODO (LIST): unify (and parametrize) calls to freeZones.
// We aren't calling freeAnimations because it is not needed, since
// kChangeLocation will trigger a complete deletion. Anyway, we still
// need to invoke freeZones here with kEngineQuit set, because the
// call in changeLocation preserve certain zones.
_engineFlags |= kEngineQuit;
freeZones();
_engineFlags &= ~kEngineQuit;
_numLocations = atoi(s);
memset(_localFlags, 0, sizeof(_localFlags));
memset(_locationNames, 0, sizeof(_locationNames));
uint16 _si;
for (_si = 0; _si < _numLocations; _si++) {
f->readLine(s, 20);
s[strlen(s)] = '\0';
strcpy(_locationNames[_si], s);
f->readLine(s, 15);
_localFlags[_si] = atoi(s);
}
cleanInventory(false);
ItemName name;
uint32 value;
for (_si = 0; _si < 30; _si++) {
f->readLine(s, 15);
value = atoi(s);
f->readLine(s, 15);
name = atoi(s);
addInventoryItem(name, value);
}
delete f;
// force reload of character to solve inventory
// bugs, but it's a good maneuver anyway
strcpy(_characterName1, "null");
sprintf(_location._name, "%s.%s" , l, n);
_engineFlags |= kEngineChangeLocation;
return;
}
void Parallaction_ns::doSaveGame(uint16 slot, const char* name) {
char path[PATH_LEN];
2007-02-11 21:17:37 +00:00
sprintf(path, "game.%i", slot);
Common::OutSaveFile *f = _saveFileMan->openForSaving(path);
2007-02-11 21:17:37 +00:00
if (f == 0) {
char buf[32];
sprintf(buf, "Can't save game in slot %i\n\n(%s)", slot, path);
GUI::MessageDialog dialog(buf);
dialog.runModal();
return;
2007-02-11 21:17:37 +00:00
}
char s[30];
if (!name || name[0] == '\0') {
sprintf(s, "default_%i", slot);
} else {
strncpy(s, name, 29);
}
2007-02-11 21:17:37 +00:00
f->writeString(s);
f->writeString("\n");
2007-02-11 21:17:37 +00:00
sprintf(s, "%s\n", _char.getFullName());
f->writeString(s);
sprintf(s, "%s\n", _saveData1);
f->writeString(s);
2007-04-07 16:40:27 +00:00
sprintf(s, "%d\n", _char._ani._left);
f->writeString(s);
2007-04-07 16:40:27 +00:00
sprintf(s, "%d\n", _char._ani._top);
f->writeString(s);
sprintf(s, "%d\n", _score);
f->writeString(s);
sprintf(s, "%u\n", _commandFlags);
f->writeString(s);
sprintf(s, "%d\n", _numLocations);
f->writeString(s);
for (uint16 _si = 0; _si < _numLocations; _si++) {
sprintf(s, "%s\n%u\n", _locationNames[_si], _localFlags[_si]);
f->writeString(s);
}
const InventoryItem *item;
for (uint16 _si = 0; _si < 30; _si++) {
item = getInventoryItem(_si);
sprintf(s, "%u\n%d\n", item->_id, item->_index);
f->writeString(s);
}
delete f;
return;
}
2007-02-11 21:17:37 +00:00
enum {
kSaveCmd = 'SAVE',
kLoadCmd = 'LOAD',
kPlayCmd = 'PLAY',
kOptionsCmd = 'OPTN',
kHelpCmd = 'HELP',
kAboutCmd = 'ABOU',
kQuitCmd = 'QUIT',
kChooseCmd = 'CHOS'
};
SaveLoadChooser::SaveLoadChooser(const String &title, const String &buttonLabel, Parallaction_ns *engine)
2007-02-11 21:17:37 +00:00
: Dialog("scummsaveload"), _list(0), _chooseButton(0), _gfxWidget(0), _vm(engine) {
// _drawingHints |= GUI::THEME_HINT_SPECIAL_COLOR;
new GUI::StaticTextWidget(this, "scummsaveload_title", title);
// Add choice list
_list = new GUI::ListWidget(this, "scummsaveload_list");
_list->setEditable(true);
_list->setNumberingMode(GUI::kListNumberingOne);
_container = new GUI::ContainerWidget(this, 0, 0, 10, 10);
_container->setHints(GUI::THEME_HINT_USE_SHADOW);
_gfxWidget = new GUI::GraphicsWidget(this, 0, 0, 10, 10);
_date = new GUI::StaticTextWidget(this, 0, 0, 10, 10, "No date saved", GUI::kTextAlignCenter);
_time = new GUI::StaticTextWidget(this, 0, 0, 10, 10, "No time saved", GUI::kTextAlignCenter);
_playtime = new GUI::StaticTextWidget(this, 0, 0, 10, 10, "No playtime saved", GUI::kTextAlignCenter);
// Buttons
new GUI::ButtonWidget(this, "scummsaveload_cancel", "Cancel", GUI::kCloseCmd, 0);
_chooseButton = new GUI::ButtonWidget(this, "scummsaveload_choose", buttonLabel, kChooseCmd, 0);
_chooseButton->setEnabled(false);
}
SaveLoadChooser::~SaveLoadChooser() {
}
const Common::String &SaveLoadChooser::getResultString() const {
return _list->getSelectedString();
}
void SaveLoadChooser::setList(const StringList& list) {
_list->setList(list);
}
int SaveLoadChooser::runModal() {
if (_gfxWidget)
_gfxWidget->setGfx(0);
int ret = GUI::Dialog::runModal();
return ret;
}
void SaveLoadChooser::handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data) {
int selItem = _list->getSelected();
switch (cmd) {
case GUI::kListItemActivatedCmd:
case GUI::kListItemDoubleClickedCmd:
if (selItem >= 0) {
if (!getResultString().empty()) {
_list->endEditMode();
setResult(selItem);
close();
}
}
break;
case kChooseCmd:
_list->endEditMode();
setResult(selItem);
close();
break;
case GUI::kListSelectionChangedCmd: {
_list->startEditMode();
2007-02-11 21:17:37 +00:00
// Disable button if nothing is selected, or (in load mode) if an empty
// list item is selected. We allow choosing an empty item in save mode
// because we then just assign a default name.
_chooseButton->setEnabled(selItem >= 0 && (!getResultString().empty()));
_chooseButton->draw();
} break;
case GUI::kCloseCmd:
setResult(-1);
default:
Dialog::handleCommand(sender, cmd, data);
}
}
void SaveLoadChooser::reflowLayout() {
_container->setFlags(GUI::WIDGET_INVISIBLE);
_gfxWidget->setFlags(GUI::WIDGET_INVISIBLE);
_date->setFlags(GUI::WIDGET_INVISIBLE);
_time->setFlags(GUI::WIDGET_INVISIBLE);
_playtime->setFlags(GUI::WIDGET_INVISIBLE);
2007-02-11 21:17:37 +00:00
Dialog::reflowLayout();
}
int Parallaction_ns::buildSaveFileList(Common::StringList& l) {
2007-02-11 21:17:37 +00:00
char name[16];
char buf[30];
2007-02-11 21:17:37 +00:00
int count = 0;
2007-02-11 21:17:37 +00:00
for (int i = 0; i < 10; i++) {
sprintf(name, "game.%i", i);
2007-02-11 21:17:37 +00:00
buf[0] = '\0';
Common::InSaveFile *f = _saveFileMan->openForLoading(name);
2007-02-11 21:17:37 +00:00
if (f) {
f->readLine(buf, 29);
delete f;
2007-02-11 21:17:37 +00:00
count++;
}
2007-02-11 21:17:37 +00:00
l.push_back(buf);
}
2007-02-11 21:17:37 +00:00
return count;
2007-02-11 21:17:37 +00:00
}
int Parallaction_ns::selectSaveFile(uint16 arg_0, const char* caption, const char* button) {
2007-02-11 21:17:37 +00:00
2007-04-07 16:40:27 +00:00
SaveLoadChooser* slc = new SaveLoadChooser(caption, button, this);
2007-02-11 21:17:37 +00:00
Common::StringList l;
/*int count = */ buildSaveFileList(l);
slc->setList(l);
2007-02-11 21:17:37 +00:00
int idx = slc->runModal();
if (idx >= 0) {
_saveFileName = slc->getResultString();
}
delete slc;
2007-02-11 21:17:37 +00:00
return idx;
}
bool Parallaction_ns::loadGame() {
2007-02-11 21:17:37 +00:00
2007-02-13 21:06:13 +00:00
int _di = selectSaveFile( 0, "Load file", "Load" );
2007-02-11 21:17:37 +00:00
if (_di == -1) {
return false;
2007-02-11 21:17:37 +00:00
}
doLoadGame(_di);
GUI::TimedMessageDialog dialog("Loading game...", 1500);
dialog.runModal();
2007-02-11 21:17:37 +00:00
setArrowCursor();
2007-02-11 21:17:37 +00:00
return true;
2007-02-11 21:17:37 +00:00
}
bool Parallaction_ns::saveGame() {
2007-02-11 21:17:37 +00:00
if (!scumm_stricmp(_location._name, "caveau")) {
return false;
}
2007-02-11 21:17:37 +00:00
2007-02-13 21:06:13 +00:00
int slot = selectSaveFile( 1, "Save file", "Save" );
2007-02-11 21:17:37 +00:00
if (slot == -1) {
return false;
2007-02-11 21:17:37 +00:00
}
doSaveGame(slot, _saveFileName.c_str());
GUI::TimedMessageDialog dialog("Saving game...", 1500);
dialog.runModal();
2007-02-11 21:17:37 +00:00
return true;
2007-02-11 21:17:37 +00:00
}
} // namespace Parallaction