PRINCE: Game saving - basic implementation
This commit is contained in:
parent
822d1786b0
commit
08d781b6ad
11 changed files with 729 additions and 148 deletions
|
@ -20,19 +20,10 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "base/plugins.h"
|
||||
#include "engines/advancedDetector.h"
|
||||
|
||||
#include "prince/prince.h"
|
||||
#include "prince/detection.h"
|
||||
|
||||
namespace Prince {
|
||||
|
||||
struct PrinceGameDescription {
|
||||
ADGameDescription desc;
|
||||
|
||||
int gameType;
|
||||
};
|
||||
|
||||
int PrinceEngine::getGameType() const {
|
||||
return _gameDescription->gameType;
|
||||
}
|
||||
|
@ -49,78 +40,6 @@ Common::Language PrinceEngine::getLanguage() const {
|
|||
return _gameDescription->desc.language;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static const PlainGameDescriptor princeGames[] = {
|
||||
{"prince", "Prince Game"},
|
||||
{0, 0}
|
||||
};
|
||||
|
||||
namespace Prince {
|
||||
|
||||
static const PrinceGameDescription gameDescriptions[] = {
|
||||
|
||||
// German
|
||||
{
|
||||
{
|
||||
"prince",
|
||||
"Galador",
|
||||
AD_ENTRY1s("databank.ptc", "5fa03833177331214ec1354761b1d2ee", 3565031),
|
||||
Common::DE_DEU,
|
||||
Common::kPlatformWindows,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO1(GUIO_NONE)
|
||||
},
|
||||
0
|
||||
},
|
||||
// Polish
|
||||
{
|
||||
{
|
||||
"prince",
|
||||
"Ksiaze i Tchorz",
|
||||
AD_ENTRY1s("databank.ptc", "48ec9806bda9d152acbea8ce31c93c49", 3435298),
|
||||
Common::PL_POL,
|
||||
Common::kPlatformWindows,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO1(GUIO_NONE)
|
||||
},
|
||||
1
|
||||
},
|
||||
|
||||
|
||||
{ AD_TABLE_END_MARKER, 0 }
|
||||
};
|
||||
|
||||
} // End of namespace Prince
|
||||
|
||||
using namespace Prince;
|
||||
|
||||
// we match from data too, to stop detection from a non-top-level directory
|
||||
const static char *directoryGlobs[] = {
|
||||
"all",
|
||||
0
|
||||
};
|
||||
|
||||
class PrinceMetaEngine : public AdvancedMetaEngine {
|
||||
public:
|
||||
PrinceMetaEngine() : AdvancedMetaEngine(Prince::gameDescriptions, sizeof(Prince::PrinceGameDescription), princeGames) {
|
||||
_singleid = "prince";
|
||||
_maxScanDepth = 2;
|
||||
_directoryGlobs = directoryGlobs;
|
||||
}
|
||||
|
||||
virtual const char *getName() const {
|
||||
return "Prince Engine";
|
||||
}
|
||||
|
||||
virtual const char *getOriginalCopyright() const {
|
||||
return "Copyright (C)";
|
||||
}
|
||||
|
||||
virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const;
|
||||
virtual bool hasFeature(MetaEngineFeature f) const;
|
||||
};
|
||||
|
||||
bool PrinceMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
|
||||
using namespace Prince;
|
||||
const PrinceGameDescription *gd = (const PrinceGameDescription *)desc;
|
||||
|
@ -131,17 +50,26 @@ bool PrinceMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGa
|
|||
}
|
||||
|
||||
bool PrinceMetaEngine::hasFeature(MetaEngineFeature f) const {
|
||||
return false;
|
||||
return
|
||||
(f == kSupportsDeleteSave) ||
|
||||
(f == kSavesSupportMetaInfo) ||
|
||||
(f == kSavesSupportThumbnail) ||
|
||||
(f == kSavesSupportCreationDate) ||
|
||||
(f == kSupportsListSaves);
|
||||
}
|
||||
|
||||
bool Prince::PrinceEngine::hasFeature(EngineFeature f) const {
|
||||
return false;//(f == kSupportsRTL);
|
||||
return
|
||||
(f == kSupportsLoadingDuringRuntime) ||
|
||||
(f == kSupportsSavingDuringRuntime);
|
||||
}
|
||||
|
||||
} // End of namespace Prince
|
||||
|
||||
#if PLUGIN_ENABLED_DYNAMIC(PRINCE)
|
||||
REGISTER_PLUGIN_DYNAMIC(PRINCE, PLUGIN_TYPE_ENGINE, PrinceMetaEngine);
|
||||
REGISTER_PLUGIN_DYNAMIC(PRINCE, PLUGIN_TYPE_ENGINE, Prince::PrinceMetaEngine);
|
||||
#else
|
||||
REGISTER_PLUGIN_STATIC(PRINCE, PLUGIN_TYPE_ENGINE, PrinceMetaEngine);
|
||||
REGISTER_PLUGIN_STATIC(PRINCE, PLUGIN_TYPE_ENGINE, Prince::PrinceMetaEngine);
|
||||
#endif
|
||||
|
||||
/* vim: set tabstop=4 noexpandtab: */
|
||||
|
|
101
engines/prince/detection.h
Normal file
101
engines/prince/detection.h
Normal file
|
@ -0,0 +1,101 @@
|
|||
/* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PRINCE_DETECTION_H
|
||||
#define PRINCE_DETECTION_H
|
||||
|
||||
#include "prince/prince.h"
|
||||
#include "engines/advancedDetector.h"
|
||||
|
||||
namespace Prince {
|
||||
|
||||
struct PrinceGameDescription {
|
||||
ADGameDescription desc;
|
||||
int gameType;
|
||||
};
|
||||
|
||||
static const PlainGameDescriptor princeGames[] = {
|
||||
{"prince", "Prince Game"},
|
||||
{0, 0}
|
||||
};
|
||||
|
||||
static const PrinceGameDescription gameDescriptions[] = {
|
||||
{
|
||||
{
|
||||
"prince",
|
||||
"Galador",
|
||||
AD_ENTRY1s("databank.ptc", "5fa03833177331214ec1354761b1d2ee", 3565031),
|
||||
Common::DE_DEU,
|
||||
Common::kPlatformWindows,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO1(GUIO_NONE)
|
||||
},
|
||||
0
|
||||
},
|
||||
{
|
||||
{
|
||||
"prince",
|
||||
"Ksiaze i Tchorz",
|
||||
AD_ENTRY1s("databank.ptc", "48ec9806bda9d152acbea8ce31c93c49", 3435298),
|
||||
Common::PL_POL,
|
||||
Common::kPlatformWindows,
|
||||
ADGF_NO_FLAGS,
|
||||
GUIO1(GUIO_NONE)
|
||||
},
|
||||
1
|
||||
},
|
||||
{ AD_TABLE_END_MARKER, 0 }
|
||||
};
|
||||
|
||||
// we match from data too, to stop detection from a non-top-level directory
|
||||
const static char *directoryGlobs[] = {
|
||||
"all",
|
||||
0
|
||||
};
|
||||
|
||||
class PrinceMetaEngine : public AdvancedMetaEngine {
|
||||
public:
|
||||
PrinceMetaEngine() : AdvancedMetaEngine(Prince::gameDescriptions, sizeof(Prince::PrinceGameDescription), princeGames) {
|
||||
_singleid = "prince";
|
||||
_maxScanDepth = 2;
|
||||
_directoryGlobs = directoryGlobs;
|
||||
}
|
||||
|
||||
virtual const char *getName() const {
|
||||
return "Prince Engine";
|
||||
}
|
||||
|
||||
virtual const char *getOriginalCopyright() const {
|
||||
return "Copyright (C)";
|
||||
}
|
||||
|
||||
virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const;
|
||||
virtual bool hasFeature(MetaEngineFeature f) const;
|
||||
virtual int getMaximumSaveSlot() const;
|
||||
virtual SaveStateList listSaves(const char *target) const;
|
||||
SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const;
|
||||
virtual void removeSaveState(const char *target, int slot) const;
|
||||
};
|
||||
|
||||
} // End of namespace Prince
|
||||
|
||||
#endif
|
|
@ -41,7 +41,7 @@ Hero::Hero(PrinceEngine *vm, GraphicsMan *graph) : _vm(vm), _graph(graph)
|
|||
, _shadZoomFactor(0), _shadScaleValue(0), _shadLineLen(0), _shadDrawX(0), _shadDrawY(0)
|
||||
, _frameXSize(0), _frameYSize(0), _scaledFrameXSize(0), _scaledFrameYSize(0), _color(0)
|
||||
, _coords(nullptr), _dirTab(nullptr), _currCoords(nullptr), _currDirTab(nullptr), _step(0)
|
||||
, _maxBoredom(200), _turnAnim(0), _leftRightMainDir(0), _upDownMainDir(0)
|
||||
, _maxBoredom(200), _turnAnim(0), _leftRightMainDir(0), _upDownMainDir(0), _animSetNr(0)
|
||||
{
|
||||
_zoomBitmap = (byte *)malloc(kZoomBitmapLen);
|
||||
_shadowBitmap = (byte *)malloc(2 * kShadowBitmapSize);
|
||||
|
@ -57,6 +57,8 @@ Hero::~Hero() {
|
|||
}
|
||||
|
||||
bool Hero::loadAnimSet(uint32 animSetNr) {
|
||||
_animSetNr = animSetNr;
|
||||
|
||||
if (animSetNr > sizeof(heroSetTable)) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -182,11 +182,11 @@ public:
|
|||
|
||||
uint16 _currHeight; // height of current anim phase
|
||||
|
||||
Common::Array<int> _inventory; // Inventory array of items
|
||||
Common::Array<int> _inventory2; // Inventory2 array of items
|
||||
Common::Array<byte> _inventory; // Inventory array of items
|
||||
Common::Array<byte> _inventory2; // Inventory2 array of items
|
||||
// Font subtitiles font
|
||||
int _color; // Color Subtitles color
|
||||
// AnimSet number of animation set
|
||||
int _color; // subtitles color
|
||||
uint32 _animSetNr; // number of animation set
|
||||
Common::Array<Animation *> _moveSet; // MoveAnims MoveSet
|
||||
int16 _turnAnim;
|
||||
byte *_zoomBitmap;
|
||||
|
|
|
@ -19,7 +19,8 @@ MODULE_OBJS = \
|
|||
hero.o \
|
||||
hero_set.o \
|
||||
cursor.o \
|
||||
pscr.o
|
||||
pscr.o \
|
||||
saveload.o
|
||||
|
||||
# This module can be built as a plugin
|
||||
ifeq ($(ENABLE_PRINCE), DYNAMIC_PLUGIN)
|
||||
|
|
|
@ -323,7 +323,7 @@ void PrinceEngine::init() {
|
|||
|
||||
_objSlot = new int[kMaxObjects];
|
||||
for (int i = 0; i < kMaxObjects; i++) {
|
||||
_objSlot[i] = -1;
|
||||
_objSlot[i] = 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -458,7 +458,7 @@ bool PrinceEngine::loadLocation(uint16 locationNr) {
|
|||
_mainHero->setShadowScale(_script->getShadowScale(_locationNr));
|
||||
|
||||
for (uint i = 0; i < _mobList.size(); i++) {
|
||||
_mobList[i]._visible = _script->getMobVisible(i);
|
||||
_mobList[i]._visible = _script->getMobVisible(_room->_mobs, i);
|
||||
}
|
||||
|
||||
freeDrawNodes();
|
||||
|
@ -992,7 +992,7 @@ int PrinceEngine::checkMob(Graphics::Surface *screen, Common::Array<Mob> &mobLis
|
|||
//mob_obj
|
||||
if (mob->_mask < kMaxObjects) {
|
||||
int nr = _objSlot[mob->_mask];
|
||||
if (nr != -1) {
|
||||
if (nr != 0xFF) {
|
||||
Object &obj = *_objList[nr];
|
||||
Common::Rect objectRect(obj._x, obj._y, obj._x + obj._width, obj._y + obj._height);
|
||||
if (objectRect.contains(mousePosCamera)) {
|
||||
|
@ -1682,7 +1682,7 @@ void PrinceEngine::freeZoomObject(int slot) {
|
|||
void PrinceEngine::showObjects() {
|
||||
for (int i = 0; i < kMaxObjects; i++) {
|
||||
int nr = _objSlot[i];
|
||||
if (nr != -1) {
|
||||
if (nr != 0xFF) {
|
||||
Graphics::Surface *objSurface = nullptr;
|
||||
if ((_objList[nr]->_flags & 0x8000)) {
|
||||
_objList[nr]->_zoomTime--;
|
||||
|
@ -4508,7 +4508,6 @@ void PrinceEngine::mainLoop() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_debugger->_locationNr != _locationNr)
|
||||
loadLocation(_debugger->_locationNr);
|
||||
if (_debugger->_cursorNr != _cursorNr)
|
||||
|
|
|
@ -31,6 +31,8 @@
|
|||
#include "common/rect.h"
|
||||
#include "common/events.h"
|
||||
#include "common/endian.h"
|
||||
#include "common/savefile.h"
|
||||
#include "common/serializer.h"
|
||||
|
||||
#include "image/bmp.h"
|
||||
|
||||
|
@ -51,6 +53,7 @@
|
|||
namespace Prince {
|
||||
|
||||
struct PrinceGameDescription;
|
||||
struct SavegameHeader;
|
||||
|
||||
class PrinceEngine;
|
||||
class GraphicsMan;
|
||||
|
@ -252,6 +255,17 @@ public:
|
|||
virtual ~PrinceEngine();
|
||||
|
||||
virtual bool hasFeature(EngineFeature f) const;
|
||||
virtual bool canSaveGameStateCurrently();
|
||||
virtual bool canLoadGameStateCurrently();
|
||||
virtual Common::Error saveGameState(int slot, const Common::String &desc);
|
||||
virtual Common::Error loadGameState(int slot);
|
||||
|
||||
static bool readSavegameHeader(Common::InSaveFile *in, SavegameHeader &header);
|
||||
Common::String generateSaveName(int slot);
|
||||
void writeSavegameHeader(Common::OutSaveFile *out, SavegameHeader &header);
|
||||
void syncGame(Common::SeekableReadStream *readStream, Common::WriteStream *writeStream);
|
||||
bool loadGame(int slotNumber);
|
||||
void resetGame();
|
||||
|
||||
int getGameType() const;
|
||||
const char *getGameId() const;
|
||||
|
@ -313,6 +327,7 @@ public:
|
|||
static const int kMaxNormAnims = 64;
|
||||
static const int kMaxBackAnims = 64;
|
||||
static const int kMaxObjects = 64;
|
||||
static const int kMaxMobs = 64;
|
||||
|
||||
Common::Array<AnimListItem> _animList;
|
||||
Common::Array<BackgroundAnim> _backAnimList;
|
||||
|
|
508
engines/prince/saveload.cpp
Normal file
508
engines/prince/saveload.cpp
Normal file
|
@ -0,0 +1,508 @@
|
|||
/* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "prince/prince.h"
|
||||
#include "prince/graphics.h"
|
||||
#include "prince/detection.h"
|
||||
#include "prince/flags.h"
|
||||
#include "prince/script.h"
|
||||
#include "prince/hero.h"
|
||||
#include "common/savefile.h"
|
||||
#include "common/system.h"
|
||||
#include "common/config-manager.h"
|
||||
#include "common/memstream.h"
|
||||
#include "graphics/thumbnail.h"
|
||||
#include "graphics/surface.h"
|
||||
#include "graphics/palette.h"
|
||||
#include "graphics/scaler.h"
|
||||
|
||||
namespace Prince {
|
||||
|
||||
#define kBadSVG 99
|
||||
#define kSavegameVersion 1
|
||||
#define kSavegameStrSize 14
|
||||
#define kSavegameStr "SCUMMVM_PRINCE"
|
||||
|
||||
class InterpreterFlags;
|
||||
class Interpreter;
|
||||
|
||||
struct SavegameHeader {
|
||||
uint8 version;
|
||||
Common::String saveName;
|
||||
Graphics::Surface *thumbnail;
|
||||
int saveYear, saveMonth, saveDay;
|
||||
int saveHour, saveMinutes;
|
||||
};
|
||||
|
||||
int PrinceMetaEngine::getMaximumSaveSlot() const {
|
||||
return 99;
|
||||
}
|
||||
|
||||
SaveStateList PrinceMetaEngine::listSaves(const char *target) const {
|
||||
Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
|
||||
Common::StringArray filenames;
|
||||
Common::String pattern = target;
|
||||
pattern += ".???";
|
||||
|
||||
filenames = saveFileMan->listSavefiles(pattern);
|
||||
sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..)
|
||||
|
||||
SaveStateList saveList;
|
||||
for (Common::StringArray::const_iterator filename = filenames.begin(); filename != filenames.end(); filename++) {
|
||||
// Obtain the last 3 digits of the filename, since they correspond to the save slot
|
||||
int slotNum = atoi(filename->c_str() + filename->size() - 3);
|
||||
|
||||
if (slotNum >= 0 && slotNum <= 99) {
|
||||
|
||||
Common::InSaveFile *file = saveFileMan->openForLoading(*filename);
|
||||
if (file) {
|
||||
Prince::SavegameHeader header;
|
||||
|
||||
// Check to see if it's a ScummVM savegame or not
|
||||
char buffer[kSavegameStrSize + 1];
|
||||
file->read(buffer, kSavegameStrSize + 1);
|
||||
|
||||
if (!strncmp(buffer, kSavegameStr, kSavegameStrSize + 1)) {
|
||||
// Valid savegame
|
||||
if (Prince::PrinceEngine::readSavegameHeader(file, header)) {
|
||||
saveList.push_back(SaveStateDescriptor(slotNum, header.saveName));
|
||||
if (header.thumbnail) {
|
||||
header.thumbnail->free();
|
||||
delete header.thumbnail;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Must be an original format savegame
|
||||
saveList.push_back(SaveStateDescriptor(slotNum, "Unknown"));
|
||||
}
|
||||
|
||||
delete file;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return saveList;
|
||||
}
|
||||
|
||||
SaveStateDescriptor PrinceMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
|
||||
Common::String fileName = Common::String::format("%s.%03d", target, slot);
|
||||
Common::InSaveFile *f = g_system->getSavefileManager()->openForLoading(fileName);
|
||||
|
||||
if (f) {
|
||||
Prince::SavegameHeader header;
|
||||
|
||||
// Check to see if it's a ScummVM savegame or not
|
||||
char buffer[kSavegameStrSize + 1];
|
||||
f->read(buffer, kSavegameStrSize + 1);
|
||||
|
||||
bool hasHeader = !strncmp(buffer, kSavegameStr, kSavegameStrSize + 1) &&
|
||||
Prince::PrinceEngine::readSavegameHeader(f, header);
|
||||
delete f;
|
||||
|
||||
if (!hasHeader) {
|
||||
// Original savegame perhaps?
|
||||
SaveStateDescriptor desc(slot, "Unknown");
|
||||
return desc;
|
||||
} else {
|
||||
// Create the return descriptor
|
||||
SaveStateDescriptor desc(slot, header.saveName);
|
||||
desc.setThumbnail(header.thumbnail);
|
||||
desc.setSaveDate(header.saveYear, header.saveMonth, header.saveDay);
|
||||
desc.setSaveTime(header.saveHour, header.saveMinutes);
|
||||
|
||||
return desc;
|
||||
}
|
||||
}
|
||||
|
||||
return SaveStateDescriptor();
|
||||
}
|
||||
|
||||
bool PrinceEngine::readSavegameHeader(Common::InSaveFile *in, SavegameHeader &header) {
|
||||
header.thumbnail = nullptr;
|
||||
|
||||
// Get the savegame version
|
||||
header.version = in->readByte();
|
||||
if (header.version > kSavegameVersion)
|
||||
return false;
|
||||
|
||||
// Read in the string
|
||||
header.saveName.clear();
|
||||
char ch;
|
||||
while ((ch = (char)in->readByte()) != '\0')
|
||||
header.saveName += ch;
|
||||
|
||||
// Get the thumbnail
|
||||
header.thumbnail = Graphics::loadThumbnail(*in);
|
||||
if (!header.thumbnail)
|
||||
return false;
|
||||
|
||||
// Read in save date/time
|
||||
header.saveYear = in->readSint16LE();
|
||||
header.saveMonth = in->readSint16LE();
|
||||
header.saveDay = in->readSint16LE();
|
||||
header.saveHour = in->readSint16LE();
|
||||
header.saveMinutes = in->readSint16LE();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PrinceMetaEngine::removeSaveState(const char *target, int slot) const {
|
||||
Common::String fileName = Common::String::format("%s.%03d", target, slot);
|
||||
g_system->getSavefileManager()->removeSavefile(fileName);
|
||||
}
|
||||
|
||||
// TODO
|
||||
bool PrinceEngine::canSaveGameStateCurrently() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO
|
||||
bool PrinceEngine::canLoadGameStateCurrently() {
|
||||
return true;
|
||||
}
|
||||
|
||||
Common::Error PrinceEngine::saveGameState(int slot, const Common::String &desc) {
|
||||
// Set up the serializer
|
||||
Common::String slotName = generateSaveName(slot);
|
||||
Common::OutSaveFile *saveFile = g_system->getSavefileManager()->openForSaving(slotName);
|
||||
|
||||
// Write out the ScummVM savegame header
|
||||
SavegameHeader header;
|
||||
header.saveName = desc;
|
||||
header.version = kSavegameVersion;
|
||||
writeSavegameHeader(saveFile, header);
|
||||
|
||||
// Write out the data of the savegame
|
||||
syncGame(nullptr, saveFile);
|
||||
|
||||
// Finish writing out game data
|
||||
saveFile->finalize();
|
||||
delete saveFile;
|
||||
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
Common::String PrinceEngine::generateSaveName(int slot) {
|
||||
return Common::String::format("%s.%03d", _targetName.c_str(), slot);
|
||||
}
|
||||
|
||||
void PrinceEngine::writeSavegameHeader(Common::OutSaveFile *out, SavegameHeader &header) {
|
||||
// Write out a savegame header
|
||||
out->write(kSavegameStr, kSavegameStrSize + 1);
|
||||
|
||||
out->writeByte(kSavegameVersion);
|
||||
|
||||
// Write savegame name
|
||||
out->write(header.saveName.c_str(), header.saveName.size() + 1);
|
||||
|
||||
// Get the active palette
|
||||
uint8 thumbPalette[256 * 3];
|
||||
_system->getPaletteManager()->grabPalette(thumbPalette, 0, 256);
|
||||
|
||||
// Create a thumbnail and save it
|
||||
Graphics::Surface *thumb = new Graphics::Surface();
|
||||
Graphics::Surface *s = _graph->_frontScreen; // check inventory / map etc..
|
||||
::createThumbnail(thumb, (const byte *)s->getPixels(), s->w, s->h, thumbPalette);
|
||||
Graphics::saveThumbnail(*out, *thumb);
|
||||
thumb->free();
|
||||
delete thumb;
|
||||
|
||||
// Write out the save date/time
|
||||
TimeDate td;
|
||||
g_system->getTimeAndDate(td);
|
||||
out->writeSint16LE(td.tm_year + 1900);
|
||||
out->writeSint16LE(td.tm_mon + 1);
|
||||
out->writeSint16LE(td.tm_mday);
|
||||
out->writeSint16LE(td.tm_hour);
|
||||
out->writeSint16LE(td.tm_min);
|
||||
}
|
||||
|
||||
void PrinceEngine::syncGame(Common::SeekableReadStream *readStream, Common::WriteStream *writeStream) {
|
||||
int emptyRoom = 0x00;
|
||||
int normRoom = 0xFF;
|
||||
byte endInv = 0xFF;
|
||||
|
||||
Common::Serializer s(readStream, writeStream);
|
||||
|
||||
if (s.isSaving()) {
|
||||
// Flag values
|
||||
for (int i = 0; i < _flags->kMaxFlags; i++) {
|
||||
uint32 value = _flags->getFlagValue((Flags::Id)(_flags->kFlagMask + i));
|
||||
s.syncAsUint32LE(value);
|
||||
}
|
||||
|
||||
// Dialog data
|
||||
for (uint32 i = 0; i < _dialogDatSize; i++) {
|
||||
byte value = _dialogDat[i];
|
||||
s.syncAsByte(value);
|
||||
}
|
||||
|
||||
// Location number
|
||||
s.syncAsUint16LE(_locationNr);
|
||||
|
||||
// Rooms
|
||||
for (int roomId = 0; roomId < _script->kMaxRooms; roomId++) {
|
||||
Room *room = new Room();
|
||||
room->loadRoom(_script->getRoomOffset(roomId));
|
||||
|
||||
if (room->_mobs) {
|
||||
s.syncAsByte(normRoom);
|
||||
} else {
|
||||
s.syncAsByte(emptyRoom);
|
||||
delete room;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Mobs
|
||||
for (int mobId = 0; mobId < kMaxMobs; mobId++) {
|
||||
byte value = _script->getMobVisible(room->_mobs, mobId);
|
||||
s.syncAsByte(value);
|
||||
}
|
||||
|
||||
// Background animations
|
||||
for (int backAnimSlot = 0; backAnimSlot < kMaxBackAnims; backAnimSlot++) {
|
||||
uint32 value = _script->getBackAnimId(_room->_backAnim, backAnimSlot);
|
||||
s.syncAsUint32LE(value);
|
||||
}
|
||||
|
||||
// Objects
|
||||
for (int objectSlot = 0; objectSlot < kMaxObjects; objectSlot++) {
|
||||
byte value = _script->getObjId(room->_obj, objectSlot);
|
||||
s.syncAsByte(value);
|
||||
}
|
||||
|
||||
delete room;
|
||||
}
|
||||
|
||||
// Main hero
|
||||
s.syncAsUint16LE(_mainHero->_visible);
|
||||
s.syncAsUint16LE(_mainHero->_middleX);
|
||||
s.syncAsUint16LE(_mainHero->_middleY);
|
||||
s.syncAsUint16LE(_mainHero->_lastDirection);
|
||||
s.syncAsUint32LE(_mainHero->_color);
|
||||
s.syncAsUint16LE(_mainHero->_maxBoredom);
|
||||
s.syncAsUint32LE(_mainHero->_animSetNr);
|
||||
|
||||
for (uint inv1Slot = 0; inv1Slot < _mainHero->_inventory.size(); inv1Slot++) {
|
||||
s.syncAsByte(_mainHero->_inventory[inv1Slot]);
|
||||
}
|
||||
s.syncAsByte(endInv);
|
||||
|
||||
for (uint inv2Slot = 0; inv2Slot < _mainHero->_inventory2.size(); inv2Slot++) {
|
||||
s.syncAsByte(_mainHero->_inventory2[inv2Slot]);
|
||||
}
|
||||
s.syncAsByte(endInv);
|
||||
|
||||
// Second hero
|
||||
s.syncAsUint16LE(_secondHero->_visible);
|
||||
s.syncAsUint16LE(_secondHero->_middleX);
|
||||
s.syncAsUint16LE(_secondHero->_middleY);
|
||||
s.syncAsUint16LE(_secondHero->_lastDirection);
|
||||
s.syncAsUint32LE(_secondHero->_color);
|
||||
s.syncAsUint16LE(_secondHero->_maxBoredom);
|
||||
s.syncAsUint32LE(_secondHero->_animSetNr);
|
||||
|
||||
for (uint inv1Slot = 0; inv1Slot < _secondHero->_inventory.size(); inv1Slot++) {
|
||||
s.syncAsByte(_secondHero->_inventory[inv1Slot]);
|
||||
}
|
||||
s.syncAsByte(endInv);
|
||||
|
||||
for (uint inv2Slot = 0; inv2Slot < _secondHero->_inventory2.size(); inv2Slot++) {
|
||||
s.syncAsByte(_secondHero->_inventory2[inv2Slot]);
|
||||
}
|
||||
s.syncAsByte(endInv);
|
||||
|
||||
} else {
|
||||
// Flag values
|
||||
for (int i = 0; i < _flags->kMaxFlags; i++) {
|
||||
uint32 value = 0;
|
||||
s.syncAsUint32LE(value);
|
||||
_flags->setFlagValue((Flags::Id)(_flags->kFlagMask + i), value);
|
||||
}
|
||||
|
||||
// Dialog data
|
||||
for (uint32 i = 0; i < _dialogDatSize; i++) {
|
||||
byte value = 0;
|
||||
s.syncAsByte(value);
|
||||
_dialogDat[i] = value;
|
||||
}
|
||||
|
||||
// Location number
|
||||
int restoreRoom = 0;
|
||||
s.syncAsUint16LE(restoreRoom);
|
||||
_flags->setFlagValue(Flags::RESTOREROOM, restoreRoom);
|
||||
|
||||
// Rooms
|
||||
for (int roomId = 0; roomId < _script->kMaxRooms; roomId++) {
|
||||
Room *room = new Room();
|
||||
room->loadRoom(_script->getRoomOffset(roomId));
|
||||
|
||||
byte roomType = emptyRoom;
|
||||
s.syncAsByte(roomType);
|
||||
if (roomType == emptyRoom) {
|
||||
delete room;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Mobs
|
||||
for (int mobId = 0; mobId < kMaxMobs; mobId++) {
|
||||
byte value = 0;
|
||||
s.syncAsByte(value);
|
||||
_script->setMobVisible(room->_mobs, mobId, value);
|
||||
}
|
||||
|
||||
// Background animations
|
||||
for (int backAnimSlot = 0; backAnimSlot < kMaxBackAnims; backAnimSlot++) {
|
||||
uint32 value = 0;
|
||||
s.syncAsUint32LE(value);
|
||||
_script->setBackAnimId(_room->_backAnim, backAnimSlot, value);
|
||||
}
|
||||
|
||||
// Objects
|
||||
for (int objectSlot = 0; objectSlot < kMaxObjects; objectSlot++) {
|
||||
byte value = 0;
|
||||
s.syncAsByte(value);
|
||||
_script->setObjId(room->_obj, objectSlot, value);
|
||||
}
|
||||
|
||||
delete room;
|
||||
}
|
||||
|
||||
// Main hero
|
||||
s.syncAsUint16LE(_mainHero->_visible);
|
||||
s.syncAsUint16LE(_mainHero->_middleX);
|
||||
s.syncAsUint16LE(_mainHero->_middleY);
|
||||
s.syncAsUint16LE(_mainHero->_lastDirection);
|
||||
s.syncAsUint32LE(_mainHero->_color);
|
||||
s.syncAsUint16LE(_mainHero->_maxBoredom);
|
||||
s.syncAsUint32LE(_mainHero->_animSetNr);
|
||||
_mainHero->loadAnimSet(_mainHero->_animSetNr);
|
||||
|
||||
_mainHero->_inventory.clear();
|
||||
byte invId = endInv;
|
||||
while (1) {
|
||||
s.syncAsByte(invId);
|
||||
if (invId == endInv) {
|
||||
break;
|
||||
}
|
||||
_mainHero->_inventory.push_back(invId);
|
||||
}
|
||||
|
||||
_mainHero->_inventory2.clear();
|
||||
invId = endInv;
|
||||
while (1) {
|
||||
s.syncAsByte(invId);
|
||||
if (invId == endInv) {
|
||||
break;
|
||||
}
|
||||
_mainHero->_inventory.push_back(invId);
|
||||
}
|
||||
|
||||
// Second hero
|
||||
s.syncAsUint16LE(_secondHero->_visible);
|
||||
s.syncAsUint16LE(_secondHero->_middleX);
|
||||
s.syncAsUint16LE(_secondHero->_middleY);
|
||||
s.syncAsUint16LE(_secondHero->_lastDirection);
|
||||
s.syncAsUint32LE(_secondHero->_color);
|
||||
s.syncAsUint16LE(_secondHero->_maxBoredom);
|
||||
s.syncAsUint32LE(_secondHero->_animSetNr);
|
||||
_secondHero->loadAnimSet(_secondHero->_animSetNr);
|
||||
|
||||
_secondHero->_inventory.clear();
|
||||
invId = endInv;
|
||||
while (1) {
|
||||
s.syncAsByte(invId);
|
||||
if (invId == endInv) {
|
||||
break;
|
||||
}
|
||||
_secondHero->_inventory.push_back(invId);
|
||||
}
|
||||
|
||||
_secondHero->_inventory2.clear();
|
||||
invId = endInv;
|
||||
while (1) {
|
||||
s.syncAsByte(invId);
|
||||
if (invId == endInv) {
|
||||
break;
|
||||
}
|
||||
_secondHero->_inventory.push_back(invId);
|
||||
}
|
||||
|
||||
// Script
|
||||
_interpreter->setBgOpcodePC(0);
|
||||
_interpreter->setFgOpcodePC(_script->_scriptInfo.restoreGame);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Common::Error PrinceEngine::loadGameState(int slot) {
|
||||
if (!loadGame(slot)) {
|
||||
return Common::kReadingFailed;
|
||||
}
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
bool PrinceEngine::loadGame(int slotNumber) {
|
||||
Common::MemoryReadStream *readStream;
|
||||
|
||||
// Open up the savegame file
|
||||
Common::String slotName = generateSaveName(slotNumber);
|
||||
Common::InSaveFile *saveFile = g_system->getSavefileManager()->openForLoading(slotName);
|
||||
|
||||
// Read the data into a data buffer
|
||||
int size = saveFile->size();
|
||||
byte *dataBuffer = (byte *)malloc(size);
|
||||
saveFile->read(dataBuffer, size);
|
||||
readStream = new Common::MemoryReadStream(dataBuffer, size, DisposeAfterUse::YES);
|
||||
delete saveFile;
|
||||
|
||||
// Check to see if it's a ScummVM savegame or not
|
||||
char buffer[kSavegameStrSize + 1];
|
||||
readStream->read(buffer, kSavegameStrSize + 1);
|
||||
|
||||
if (strncmp(buffer, kSavegameStr, kSavegameStrSize + 1) != 0) {
|
||||
delete readStream;
|
||||
return false;
|
||||
} else {
|
||||
SavegameHeader saveHeader;
|
||||
|
||||
if (!readSavegameHeader(readStream, saveHeader)) {
|
||||
delete readStream;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Delete the thumbnail
|
||||
saveHeader.thumbnail->free();
|
||||
delete saveHeader.thumbnail;
|
||||
}
|
||||
|
||||
// Get in the savegame
|
||||
syncGame(readStream, nullptr);
|
||||
delete readStream;
|
||||
|
||||
// TODO
|
||||
//syncSpeechSettings();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Prince
|
|
@ -148,12 +148,16 @@ uint32 Script::getStartGameOffset() {
|
|||
return _scriptInfo.startGame;
|
||||
}
|
||||
|
||||
bool Script::getMobVisible(int mob) {
|
||||
return _data[_vm->_room->_mobs + mob];
|
||||
uint32 Script::getLocationInitScript(int initRoomTableOffset, int roomNr) {
|
||||
return (uint32)READ_UINT32(&_data[initRoomTableOffset + roomNr * 4]);
|
||||
}
|
||||
|
||||
void Script::setMobVisible(int mob, int value) {
|
||||
_data[_vm->_room->_mobs + mob] = value;
|
||||
byte Script::getMobVisible(int roomMobOffset, uint16 mob) {
|
||||
return _data[roomMobOffset + mob];
|
||||
}
|
||||
|
||||
void Script::setMobVisible(int roomMobOffset, uint16 mob, byte value) {
|
||||
_data[roomMobOffset + mob] = value;
|
||||
}
|
||||
|
||||
uint8 *Script::getRoomOffset(int locationNr) {
|
||||
|
@ -185,12 +189,21 @@ uint8 *Script::getHeroAnimName(int offset) {
|
|||
return &_data[offset];
|
||||
}
|
||||
|
||||
void Script::setBackAnimId(int offset, int animId) {
|
||||
WRITE_UINT32(&_data[offset], animId);
|
||||
uint32 Script::getBackAnimId(int roomBackAnimOffset, int slot) {
|
||||
uint32 animId = READ_UINT32(&_data[roomBackAnimOffset + slot * 4]);
|
||||
return animId;
|
||||
}
|
||||
|
||||
void Script::setObjId(int offset, int objId) {
|
||||
_data[offset] = objId;
|
||||
void Script::setBackAnimId(int roomBackAnimOffset, int slot, int animId) {
|
||||
WRITE_UINT32(&_data[roomBackAnimOffset + slot * 4], animId);
|
||||
}
|
||||
|
||||
byte Script::getObjId(int roomObjOffset, int slot) {
|
||||
return _data[roomObjOffset + slot];
|
||||
}
|
||||
|
||||
void Script::setObjId(int roomObjOffset, int slot, byte objectId) {
|
||||
_data[roomObjOffset + slot] = objectId;
|
||||
}
|
||||
|
||||
int Script::scanMobEvents(int mobMask, int dataEventOffset) {
|
||||
|
@ -232,7 +245,9 @@ int Script::scanMobEventsWithItem(int mobMask, int dataEventOffset, int itemMask
|
|||
return -1;
|
||||
}
|
||||
|
||||
void Script::installSingleBackAnim(Common::Array<BackgroundAnim> &backAnimList, int slot, int offset) {
|
||||
void Script::installSingleBackAnim(Common::Array<BackgroundAnim> &backAnimList, int slot, int roomBackAnimOffset) {
|
||||
|
||||
int offset = roomBackAnimOffset + slot * 4;
|
||||
|
||||
BackgroundAnim newBackgroundAnim;
|
||||
|
||||
|
@ -311,20 +326,15 @@ void Script::installSingleBackAnim(Common::Array<BackgroundAnim> &backAnimList,
|
|||
}
|
||||
}
|
||||
|
||||
void Script::installBackAnims(Common::Array<BackgroundAnim> &backAnimList, int offset) {
|
||||
void Script::installBackAnims(Common::Array<BackgroundAnim> &backAnimList, int roomBackAnimOffset) {
|
||||
for (int i = 0; i < _vm->kMaxBackAnims; i++) {
|
||||
installSingleBackAnim(backAnimList, i, offset);
|
||||
offset += 4;
|
||||
installSingleBackAnim(backAnimList, i, roomBackAnimOffset);
|
||||
}
|
||||
}
|
||||
|
||||
void Script::installObjects(int offset) {
|
||||
for (int i = 0; i < _vm->kMaxObjects; i++) {
|
||||
if (_data[offset] != 0xFF) {
|
||||
_vm->_objSlot[i] = i;
|
||||
} else {
|
||||
_vm->_objSlot[i] = -1;
|
||||
}
|
||||
_vm->_objSlot[i] = _data[offset];
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
|
@ -382,11 +392,11 @@ void InterpreterFlags::resetAllFlags() {
|
|||
}
|
||||
|
||||
void InterpreterFlags::setFlagValue(Flags::Id flagId, uint32 value) {
|
||||
_flags[(uint32)flagId - FLAG_MASK] = value;
|
||||
_flags[(uint32)flagId - kFlagMask] = value;
|
||||
}
|
||||
|
||||
uint32 InterpreterFlags::getFlagValue(Flags::Id flagId) {
|
||||
return _flags[(uint32)flagId - FLAG_MASK];
|
||||
return _flags[(uint32)flagId - kFlagMask];
|
||||
}
|
||||
|
||||
Interpreter::Interpreter(PrinceEngine *vm, Script *script, InterpreterFlags *flags) :
|
||||
|
@ -497,6 +507,14 @@ void Interpreter::setResult(byte value) {
|
|||
_result = value;
|
||||
}
|
||||
|
||||
void Interpreter::setBgOpcodePC(uint32 value) {
|
||||
_bgOpcodePC = value;
|
||||
}
|
||||
|
||||
void Interpreter::setFgOpcodePC(uint32 value) {
|
||||
_fgOpcodePC = value;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T Interpreter::readScript() {
|
||||
T data = _script->read<T>(_currentInstruction);
|
||||
|
@ -506,7 +524,7 @@ T Interpreter::readScript() {
|
|||
|
||||
uint16 Interpreter::readScriptFlagValue() {
|
||||
uint16 value = readScript<uint16>();
|
||||
if (value & InterpreterFlags::FLAG_MASK) {
|
||||
if (value & InterpreterFlags::kFlagMask) {
|
||||
return _flags->getFlagValue((Flags::Id)value);
|
||||
}
|
||||
return value;
|
||||
|
@ -567,8 +585,7 @@ void Interpreter::O_PUTOBJECT() {
|
|||
uint16 objectId = readScriptFlagValue();
|
||||
Room *room = new Room();
|
||||
room->loadRoom(_script->getRoomOffset(roomId));
|
||||
int offset = room->_obj + slot;
|
||||
_vm->_script->setObjId(offset, objectId);
|
||||
_vm->_script->setObjId(room->_obj, slot, objectId);
|
||||
if (_vm->_locationNr == roomId) {
|
||||
_vm->_objSlot[slot] = objectId;
|
||||
}
|
||||
|
@ -581,10 +598,9 @@ void Interpreter::O_REMOBJECT() {
|
|||
uint16 slot = readScriptFlagValue();
|
||||
Room *room = new Room();
|
||||
room->loadRoom(_script->getRoomOffset(roomId));
|
||||
int offset = room->_obj + slot;
|
||||
_vm->_script->setObjId(offset, 0xFF);
|
||||
_vm->_script->setObjId(room->_obj, slot, 0xFF);
|
||||
if (_vm->_locationNr == roomId) {
|
||||
_vm->_objSlot[slot] = -1;
|
||||
_vm->_objSlot[slot] = 0xFF;
|
||||
}
|
||||
delete room;
|
||||
debugInterpreter("O_REMOBJECT roomId %d slot %d", roomId, slot);
|
||||
|
@ -653,10 +669,9 @@ void Interpreter::O_PUTBACKANIM() {
|
|||
int32 animId = readScript<uint32>();
|
||||
Room *room = new Room();
|
||||
room->loadRoom(_script->getRoomOffset(roomId));
|
||||
int offset = room->_backAnim + slot * 4;
|
||||
_vm->_script->setBackAnimId(offset, animId);
|
||||
_vm->_script->setBackAnimId(room->_backAnim, slot, animId);
|
||||
if (_vm->_locationNr == roomId) {
|
||||
_vm->_script->installSingleBackAnim(_vm->_backAnimList, slot, offset);
|
||||
_vm->_script->installSingleBackAnim(_vm->_backAnimList, slot, room->_backAnim);
|
||||
}
|
||||
delete room;
|
||||
debugInterpreter("O_PUTBACKANIM roomId %d, slot %d, animId %d", roomId, slot, animId);
|
||||
|
@ -670,8 +685,7 @@ void Interpreter::O_REMBACKANIM() {
|
|||
}
|
||||
Room *room = new Room();
|
||||
room->loadRoom(_script->getRoomOffset(roomId));
|
||||
int offset = room->_backAnim + slot * 4;
|
||||
_vm->_script->setBackAnimId(offset, 0);
|
||||
_vm->_script->setBackAnimId(room->_backAnim, slot, 0);
|
||||
delete room;
|
||||
debugInterpreter("O_REMBACKANIM roomId %d, slot %d", roomId, slot);
|
||||
}
|
||||
|
@ -1019,22 +1033,24 @@ void Interpreter::O_CLSTEXT() {
|
|||
debugInterpreter("O_CLSTEXT slot %d", slot);
|
||||
}
|
||||
|
||||
// TODO - check if need this for saving
|
||||
void Interpreter::O_CALLTABLE() {
|
||||
uint16 flag = readScript<uint16>();
|
||||
int32 table = readScript<uint32>();
|
||||
|
||||
debugInterpreter("O_CALLTABLE flag %d, table %d", flag, table);
|
||||
// makes a call from script function table
|
||||
// must read table pointer from _code and
|
||||
// use table entry as next opcode
|
||||
Flags::Id flagId = readScriptFlagId();
|
||||
int roomNr = _flags->getFlagValue(flagId);
|
||||
int32 tableOffset = readScript<uint32>();
|
||||
int initLocationScript = _script->getLocationInitScript(tableOffset, roomNr);
|
||||
if (initLocationScript) {
|
||||
_stack[_stacktop] = _currentInstruction;
|
||||
_stacktop++;
|
||||
_currentInstruction = initLocationScript;
|
||||
}
|
||||
debugInterpreter("O_CALLTABLE loc %d", roomNr);
|
||||
}
|
||||
|
||||
void Interpreter::O_CHANGEMOB() {
|
||||
uint16 mob = readScriptFlagValue();
|
||||
uint16 value = readScriptFlagValue();
|
||||
value ^= 1;
|
||||
_vm->_script->setMobVisible(mob, value);
|
||||
_vm->_script->setMobVisible(_vm->_room->_mobs, mob, value);
|
||||
_vm->_mobList[mob]._visible = value;
|
||||
debugInterpreter("O_CHANGEMOB mob %d, value %d", mob, value);
|
||||
}
|
||||
|
@ -1527,7 +1543,7 @@ void Interpreter::O_BACKANIMRANGE() {
|
|||
uint16 low = readScriptFlagValue();
|
||||
uint16 high = readScriptFlagValue();
|
||||
if (animId != 0xFFFF) {
|
||||
if (animId & InterpreterFlags::FLAG_MASK) {
|
||||
if (animId & InterpreterFlags::kFlagMask) {
|
||||
animId = _flags->getFlagValue((Flags::Id)animId);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -96,6 +96,8 @@ private:
|
|||
|
||||
class Script {
|
||||
public:
|
||||
static const int16 kMaxRooms = 60;
|
||||
|
||||
Script(PrinceEngine *vm);
|
||||
~Script();
|
||||
|
||||
|
@ -133,23 +135,30 @@ public:
|
|||
}
|
||||
|
||||
uint32 getStartGameOffset();
|
||||
uint32 getLocationInitScript(int initRoomTableOffset, int roomNr);
|
||||
int16 getLightX(int locationNr);
|
||||
int16 getLightY(int locationNr);
|
||||
int32 getShadowScale(int locationNr);
|
||||
uint8 *getRoomOffset(int locationNr);
|
||||
int32 getOptionStandardOffset(int option);
|
||||
uint8 *getHeroAnimName(int offset);
|
||||
void setBackAnimId(int offset, int animId);
|
||||
void setObjId(int offset, int objId);
|
||||
void installBackAnims(Common::Array<BackgroundAnim> &backAnimList, int offset);
|
||||
void installSingleBackAnim(Common::Array<BackgroundAnim> &backAnimList, int slot, int offset);
|
||||
|
||||
void installBackAnims(Common::Array<BackgroundAnim> &backAnimList, int roomBackAnimOffset);
|
||||
void installSingleBackAnim(Common::Array<BackgroundAnim> &backAnimList, int slot, int roomBackAnimOffset);
|
||||
void installObjects(int offset);
|
||||
bool loadAllMasks(Common::Array<Mask> &maskList, int offset);
|
||||
|
||||
int scanMobEvents(int mobMask, int dataEventOffset);
|
||||
int scanMobEventsWithItem(int mobMask, int dataEventOffset, int itemMask);
|
||||
bool getMobVisible(int mob);
|
||||
void setMobVisible(int mob, int value);
|
||||
|
||||
byte getMobVisible(int roomMobOffset, uint16 mob);
|
||||
void setMobVisible(int roomMobOffset, uint16 mob, byte value);
|
||||
|
||||
uint32 getBackAnimId(int roomBackAnimOffset, int slot);
|
||||
void setBackAnimId(int roomBackAnimOffset, int slot, int animId);
|
||||
|
||||
byte getObjId(int roomObjOffset, int slot);
|
||||
void setObjId(int roomObjOffset, int slot, byte objectId);
|
||||
|
||||
const char *getString(uint32 offset) {
|
||||
return (const char *)(&_data[offset]);
|
||||
|
@ -171,11 +180,10 @@ public:
|
|||
|
||||
void resetAllFlags();
|
||||
|
||||
static const uint16 FLAG_MASK = 0x8000;
|
||||
|
||||
static const uint16 kFlagMask = 0x8000;
|
||||
static const uint16 kMaxFlags = 2000;
|
||||
private:
|
||||
static const uint16 MAX_FLAGS = 2000;
|
||||
int32 _flags[MAX_FLAGS];
|
||||
int32 _flags[kMaxFlags];
|
||||
};
|
||||
|
||||
class Interpreter {
|
||||
|
@ -189,6 +197,9 @@ public:
|
|||
int getLastOPCode();
|
||||
int getFgOpcodePC();
|
||||
|
||||
void setBgOpcodePC(uint32 value);
|
||||
void setFgOpcodePC(uint32 value);
|
||||
|
||||
uint32 getCurrentString();
|
||||
void setCurrentString(uint32 value);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue