diff options
Diffstat (limited to 'engines/bladerunner')
49 files changed, 693 insertions, 188 deletions
diff --git a/engines/bladerunner/actor.cpp b/engines/bladerunner/actor.cpp index 4899ea9527..26a7a80d6e 100644 --- a/engines/bladerunner/actor.cpp +++ b/engines/bladerunner/actor.cpp @@ -51,7 +51,8 @@ Actor::Actor(BladeRunnerEngine *vm, int actorId) { _walkInfo = new ActorWalk(vm); _movementTrack = new MovementTrack(); - _clues = new ActorClues(vm, (actorId && actorId != 99) ? 2 : 4); + _cluesLimit = (actorId == 0 || actorId == 99) ? 4 : 2; + _clues = new ActorClues(vm, _cluesLimit); _combatInfo = new ActorCombat(vm); _friendlinessToOther.resize(_vm->_gameInfo->getActorCount()); @@ -1105,6 +1106,10 @@ void Actor::addClueToDatabase(int clueId, int weight, bool clueAcquired, bool un _clues->add(_id, clueId, weight, clueAcquired, unknownFlag, fromActorId); } +bool Actor::canAcquireClue(int clueId) const { + return _clues->exists(clueId); +} + void Actor::acquireClue(int clueId, bool unknownFlag, int fromActorId) { bool hasAlready = hasClue(clueId); _clues->acquire(clueId, unknownFlag, fromActorId); @@ -1124,7 +1129,7 @@ bool Actor::hasClue(int clueId) const { void Actor::copyClues(int actorId) { Actor *otherActor = _vm->_actors[actorId]; for (int i = 0; i < (int)_vm->_gameInfo->getClueCount(); i++) { - if (hasClue(i) && !_clues->isPrivate(i) && !otherActor->hasClue(i)) { + if (hasClue(i) && !_clues->isPrivate(i) && otherActor->canAcquireClue(i) && !otherActor->hasClue(i)) { int fromActorId = _id; if (_id == BladeRunnerEngine::kActorVoiceOver) { fromActorId = _clues->getFromActorId(i); @@ -1258,8 +1263,9 @@ void Actor::save(SaveFileWriteStream &f) { f.writeInt(_honesty); f.writeInt(_intelligence); - f.writeInt(_stability); f.writeInt(_combatAggressiveness); + f.writeInt(_stability); + f.writeInt(_goalNumber); f.writeInt(_currentHP); @@ -1271,7 +1277,8 @@ void Actor::save(SaveFileWriteStream &f) { f.writeInt(_movementTrackNextAngle); f.writeBool(_movementTrackNextRunning); - f.writeInt(0); // TODO: _clueType + f.writeInt(_cluesLimit); + f.writeBool(_isMoving); f.writeBool(_isTarget); f.writeBool(_inCombat); @@ -1302,7 +1309,7 @@ void Actor::save(SaveFileWriteStream &f) { uint32 now = _vm->getTotalPlayTime(); // TODO: should be last lock time for (int i = 0; i < 7; ++i) { - f.writeInt(_timersLast[i] - now); + f.writeInt(now - _timersLast[i]); } int actorCount = _vm->_gameInfo->getActorCount(); @@ -1316,9 +1323,10 @@ void Actor::save(SaveFileWriteStream &f) { _walkInfo->save(f); - f.writeBoundingBox(_bbox); + f.writeBoundingBox(_bbox, false); _combatInfo->save(f); + f.writeInt(_animationModeCombatIdle); f.writeInt(_animationModeCombatWalk); f.writeInt(_animationModeCombatRun); @@ -1334,8 +1342,9 @@ void Actor::load(SaveFileReadStream &f) { _honesty = f.readInt(); _intelligence = f.readInt(); - _stability = f.readInt(); _combatAggressiveness = f.readInt(); + _stability = f.readInt(); + _goalNumber = f.readInt(); _currentHP = f.readInt(); @@ -1347,7 +1356,8 @@ void Actor::load(SaveFileReadStream &f) { _movementTrackNextAngle = f.readInt(); _movementTrackNextRunning = f.readBool(); - f.skip(4); // TODO: _clueType + _cluesLimit = f.readInt(); + _isMoving = f.readBool(); _isTarget = f.readBool(); _inCombat = f.readBool(); @@ -1378,7 +1388,7 @@ void Actor::load(SaveFileReadStream &f) { uint32 now = _vm->getTotalPlayTime(); // TODO: should be last lock time for (int i = 0; i < 7; ++i) { - _timersLast[i] = f.readInt() + now; + _timersLast[i] = now - f.readInt(); } int actorCount = _vm->_gameInfo->getActorCount(); @@ -1392,7 +1402,7 @@ void Actor::load(SaveFileReadStream &f) { _walkInfo->load(f); - _bbox = f.readBoundingBox(); + _bbox = f.readBoundingBox(false); _combatInfo->load(f); diff --git a/engines/bladerunner/actor.h b/engines/bladerunner/actor.h index 6540c0593a..896f3a2e52 100644 --- a/engines/bladerunner/actor.h +++ b/engines/bladerunner/actor.h @@ -70,6 +70,7 @@ private: int _targetFacing; int _walkboxId; + int _cluesLimit; int _timer4RemainDefault; // Flags @@ -242,9 +243,10 @@ public: bool isSpeeching(); void addClueToDatabase(int clueId, int unknown, bool clueAcquired, bool unknownFlag, int fromActorId); + bool canAcquireClue(int clueId) const; void acquireClue(int clueId, bool unknownFlag, int fromActorId); void loseClue(int clueId); - bool hasClue(int clueId) const; + bool hasClue(int clueId) const; void copyClues(int actorId); void acquireCluesByRelations(); diff --git a/engines/bladerunner/actor_clues.cpp b/engines/bladerunner/actor_clues.cpp index 70d3ad50c9..07df81e823 100644 --- a/engines/bladerunner/actor_clues.cpp +++ b/engines/bladerunner/actor_clues.cpp @@ -33,11 +33,11 @@ namespace BladeRunner { -ActorClues::ActorClues(BladeRunnerEngine *vm, int cluesType) { +ActorClues::ActorClues(BladeRunnerEngine *vm, int cluesLimit) { _vm = vm; _count = 0; _maxCount = 0; - switch (cluesType) { + switch (cluesLimit) { case 4: _maxCount = _vm->_gameInfo->getClueCount(); break; @@ -83,11 +83,11 @@ bool ActorClues::isAcquired(int clueId) const { if (clueIndex == -1) { return false; } -#if BLADERUNNER_DEBUG_GAME - return true; -#else +// #if BLADERUNNER_DEBUG_GAME +// return true; +// #else return _clues[clueIndex].flags & 0x01; -#endif +// #endif } int ActorClues::getWeight(int clueId) const { @@ -346,6 +346,10 @@ void ActorClues::add(int actorId, int clueId, int weight, bool acquired, bool un ++_count; } +bool ActorClues::exists(int clueId) const { + return findClueIndex(clueId) != -1; +} + void ActorClues::remove(int index) { if (_vm->_crimesDatabase) { debug("Actor removed clue: \"%s\"", _vm->_crimesDatabase->getClueText(_clues[index].clueId)); @@ -367,7 +371,7 @@ void ActorClues::remove(int index) { void ActorClues::save(SaveFileWriteStream &f) { f.writeInt(_count); f.writeInt(_maxCount); - for (int i = 0; i < _count; ++i) { + for (int i = 0; i < _maxCount; ++i) { Clue &c = _clues[i]; f.writeInt(c.clueId); f.writeInt(c.weight); @@ -387,7 +391,7 @@ void ActorClues::load(SaveFileReadStream &f) { _maxCount = f.readInt(); _clues.clear(); _clues.resize(_maxCount); - for (int i = 0; i < _count; ++i) { + for (int i = 0; i < _maxCount; ++i) { Clue &c = _clues[i]; c.clueId = f.readInt(); c.weight = f.readInt(); @@ -402,8 +406,4 @@ void ActorClues::load(SaveFileReadStream &f) { } } -bool ActorClues::exists(int clueId) const { - return findClueIndex(clueId) != -1; -} - } // End of namespace BladeRunner diff --git a/engines/bladerunner/actor_clues.h b/engines/bladerunner/actor_clues.h index 76690329d3..88af222724 100644 --- a/engines/bladerunner/actor_clues.h +++ b/engines/bladerunner/actor_clues.h @@ -60,9 +60,10 @@ public: }; public: - ActorClues(BladeRunnerEngine *_vm, int cluesType); + ActorClues(BladeRunnerEngine *_vm, int cluesLimit); void add(int actorId, int clueId, int unknown, bool acquired, bool unknownFlag, int fromActorId); + bool exists(int clueId) const; void acquire(int clueId, bool flag2, int fromActorId); void lose(int clueId); @@ -95,7 +96,6 @@ public: void load(SaveFileReadStream &f); private: - bool exists(int clueId) const; int findClueIndex(int clueId) const; void remove(int clueIndex); }; diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp index 362e0c4b6c..1c08b793b8 100644 --- a/engines/bladerunner/bladerunner.cpp +++ b/engines/bladerunner/bladerunner.cpp @@ -203,7 +203,80 @@ BladeRunnerEngine::~BladeRunnerEngine() { } bool BladeRunnerEngine::hasFeature(EngineFeature f) const { - return f == kSupportsRTL; + return + f == kSupportsRTL || + f == kSupportsLoadingDuringRuntime || + f == kSupportsSavingDuringRuntime; +} + +bool BladeRunnerEngine::canLoadGameStateCurrently() { + return + playerHasControl() && + !_sceneScript->isInsideScript() && + !_aiScripts->isInsideScript() && + !_kia->isOpen() && + !_spinner->isOpen() && + !_vk->isOpen() && + !_elevator->isOpen(); +} + +Common::Error BladeRunnerEngine::loadGameState(int slot) { + const Common::String saveName = Common::String::format("%s.%03d", _targetName.c_str(), slot); + + Common::InSaveFile *saveFile = getSaveFileManager()->openForLoading(saveName); + if (saveFile == nullptr || saveFile->err()) { + delete saveFile; + return Common::kReadingFailed; + } + + BladeRunner::SaveFileHeader header; + if (!BladeRunner::SaveFile::readHeader(*saveFile, header)) { + error("Invalid savegame"); + } + + loadGame(*saveFile); + + delete saveFile; + + return Common::kNoError; +} + +bool BladeRunnerEngine::canSaveGameStateCurrently() { + return + playerHasControl() && + !_sceneScript->isInsideScript() && + !_aiScripts->isInsideScript() && + !_kia->isOpen() && + !_spinner->isOpen() && + !_vk->isOpen() && + !_elevator->isOpen(); +} + +Common::Error BladeRunnerEngine::saveGameState(int slot, const Common::String &desc) { + const Common::String saveName = Common::String::format("%s.%03d", _targetName.c_str(), slot); + + Common::OutSaveFile *saveFile = g_system->getSavefileManager()->openForSaving(saveName); + if (saveFile == nullptr || saveFile->err()) { + delete saveFile; + return Common::kReadingFailed; + } + + byte *thumbnail = new byte[SaveFile::kThumbnailSize]; + generateThumbnail(thumbnail); + + BladeRunner::SaveFileHeader header; + header._name = desc; + BladeRunner::SaveFile::writeHeader(*saveFile, header); + + saveGame(*saveFile, thumbnail); + + saveFile->finalize(); + + delete[] thumbnail; + + delete saveFile; + + return Common::kNoError; } Common::Error BladeRunnerEngine::run() { @@ -315,8 +388,8 @@ bool BladeRunnerEngine::startup(bool hasSavegames) { // Seed rand // TODO: Sine and cosine lookup tables for intervals of 1.0, 4.0, and 12.0 - _cosTable1024 = new Common::CosineTable(1024); // 10-bits = 1024 points for 2*PI; - _sinTable1024 = new Common::SineTable(1024); + _cosTable1024 = new Common::CosineTable(1024); // 10-bits = 1024 points for 2*PI; + _sinTable1024 = new Common::SineTable(1024); _view = new View(); @@ -1640,22 +1713,16 @@ void BladeRunnerEngine::playerGainsControl() { } } -bool BladeRunnerEngine::saveGame(const Common::String &filename, byte *thumbnail) { - warning("BladeRunnerEngine::saveGame not finished"); - +bool BladeRunnerEngine::saveGame(Common::WriteStream &stream, const void *thumbnail) { if (!playerHasControl() || _sceneScript->isInsideScript() || _aiScripts->isInsideScript()) { return false; } - Common::OutSaveFile *commonSaveFile = getSaveFileManager()->openForSaving(filename, false); - if (commonSaveFile->err()) { - return false; - } - - SaveFileWriteStream s; + Common::MemoryWriteStreamDynamic memoryStream(DisposeAfterUse::Flag::YES); + SaveFileWriteStream s(memoryStream); - s.padBytes(9600); // TODO: thumbnail - s.writeFloat(-1.0f); + s.write(thumbnail, SaveFile::kThumbnailSize); + s.writeFloat(1.0f); _settings->save(s); _scene->save(s); _scene->_exits->save(s); @@ -1691,49 +1758,43 @@ bool BladeRunnerEngine::saveGame(const Common::String &filename, byte *thumbnail s.writeInt(nextAnimation); } _actors[kActorVoiceOver]->save(s); - _policeMaze->save(s); _crimesDatabase->save(s); s.finalize(); - assert(0 && "ok"); - commonSaveFile->writeUint32LE(s.size() + 4); - commonSaveFile->write(s.getData(), s.size()); + stream.writeUint32LE(memoryStream.size() + 4); + stream.write(memoryStream.getData(), memoryStream.size()); + stream.flush(); - return !commonSaveFile->err(); + return true; } -void BladeRunnerEngine::loadGame(const Common::String &filename, byte *thumbnail) { - warning("BladeRunnerEngine::loadGame not finished"); - +bool BladeRunnerEngine::loadGame(Common::SeekableReadStream &stream) { if (!playerHasControl() || _sceneScript->isInsideScript() || _aiScripts->isInsideScript()) { - return; - } - - Common::InSaveFile *commonSaveFile = getSaveFileManager()->openForLoading(filename); - if (commonSaveFile->err()) { - return; + return false; } - void *buf = malloc(commonSaveFile->size()); - int dataSize = commonSaveFile->read(buf, commonSaveFile->size()); - - SaveFileReadStream s((const byte*)buf, dataSize); + SaveFileReadStream s(stream); _ambientSounds->removeAllNonLoopingSounds(true); _ambientSounds->removeAllLoopingSounds(1); _music->stop(2); _audioSpeech->stopSpeech(); _actorDialogueQueue->flush(true, false); + _screenEffects->_entries.clear(); int size = s.readInt(); - if (size != dataSize) { - return; + if (size != s.size() - s.pos() + 4) { + _gameIsLoading = false; + return false; } - s.skip(9600); // thumbnail + _gameIsLoading = true; + _settings->setLoadingGame(); + s.skip(SaveFile::kThumbnailSize); // skip the thumbnail + s.skip(4);// always float 1.0, but never used _settings->load(s); _scene->load(s); _scene->_exits->load(s); @@ -1757,7 +1818,6 @@ void BladeRunnerEngine::loadGame(const Common::String &filename, byte *thumbnail _obstacles->load(s); _actorDialogueQueue->load(s); _waypoints->load(s); - for (uint i = 0; i != _gameInfo->getActorCount(); ++i) { _actors[i]->load(s); @@ -1768,23 +1828,71 @@ void BladeRunnerEngine::loadGame(const Common::String &filename, byte *thumbnail _aiScripts->setAnimationState(i, animationState, animationFrame, animationStateNext, nextAnimation); } _actors[kActorVoiceOver]->load(s); - _policeMaze->load(s); _crimesDatabase->load(s); + _gameIsLoading = false; + _settings->setNewSetAndScene(_settings->getSet(), _settings->getScene()); _settings->setChapter(_settings->getChapter()); + + return true; +} + +void BladeRunnerEngine::newGame(int difficulty) { + _settings->reset(); + _combat->reset(); + + for (uint i = 0; i < _gameInfo->getActorCount(); ++i) { + _actors[i]->setup(i); + } + _actors[kActorVoiceOver]->setup(99); + + for (uint i = 0; i < _gameInfo->getSuspectCount(); ++i) { + _suspectsDatabase->get(i)->reset(); + } + + _gameFlags->clear(); + + _gameInfo->getGlobalVarCount(); + + for (uint i = 0; i < _gameInfo->getGlobalVarCount(); ++i) { + _gameVars[i] = 0; + } + + _items->reset(); + _scores->reset(); + _kia->reset(); + _dialogueMenu->clear(); + _scene->_exits->enable(); + + if (difficulty >= 0 && difficulty < 3) { + _settings->setDifficulty(difficulty); + } + + _settings->setStartingGame(); } void BladeRunnerEngine::ISez(const Common::String &str) { debug("\t%s", str.c_str()); } -void BladeRunnerEngine::blitToScreen(const Graphics::Surface &src) { +void BladeRunnerEngine::blitToScreen(const Graphics::Surface &src) const { _system->copyRectToScreen(src.getPixels(), src.pitch, 0, 0, src.w, src.h); _system->updateScreen(); } +void BladeRunnerEngine::generateThumbnail(void *thumbnail) const { + uint16 *dstPixels = (uint16*)thumbnail; + + for (int y = 0; y < 480; y += 8) { + for (int x = 0; x < 640; x += 8) { + *dstPixels = *(const uint16 *)_surfaceFront.getBasePtr(x, y); + ++dstPixels; + } + } +} + GUI::Debugger *BladeRunnerEngine::getDebugger() { return _debugger; } diff --git a/engines/bladerunner/bladerunner.h b/engines/bladerunner/bladerunner.h index 8d45d6a806..817c3066e0 100644 --- a/engines/bladerunner/bladerunner.h +++ b/engines/bladerunner/bladerunner.h @@ -24,6 +24,7 @@ #define BLADERUNNER_BLADERUNNER_H #include "bladerunner/archive.h" +#include "bladerunner/savefile.h" #include "common/array.h" #include "common/cosinetables.h" @@ -37,7 +38,7 @@ //TODO: remove these when game is playable #define BLADERUNNER_DEBUG_CONSOLE 0 -#define BLADERUNNER_DEBUG_GAME 0 +#define BLADERUNNER_DEBUG_GAME 1 namespace Common { struct Event; @@ -224,7 +225,11 @@ public: BladeRunnerEngine(OSystem *syst, const ADGameDescription *desc); ~BladeRunnerEngine(); - bool hasFeature(EngineFeature f) const; + bool hasFeature(EngineFeature f) const override; + bool canLoadGameStateCurrently() override; + Common::Error loadGameState(int slot) override; + bool canSaveGameStateCurrently() override; + Common::Error saveGameState(int slot, const Common::String &desc) override; Common::Error run(); @@ -271,14 +276,15 @@ public: void playerLosesControl(); void playerGainsControl(); - bool saveGame(const Common::String &filename, byte *thumbnail); - void loadGame(const Common::String &filename, byte *thumbnail); - void newGame(); + bool saveGame(Common::WriteStream &stream, const void *thumbnail); + bool loadGame(Common::SeekableReadStream &stream); + void newGame(int difficulty); void autoSaveGame(); void ISez(const Common::String &str); - void blitToScreen(const Graphics::Surface &src); + void blitToScreen(const Graphics::Surface &src) const; + void generateThumbnail(void *thumbnail) const; GUI::Debugger *getDebugger(); }; diff --git a/engines/bladerunner/crimes_database.cpp b/engines/bladerunner/crimes_database.cpp index e9faa22b41..91def98aba 100644 --- a/engines/bladerunner/crimes_database.cpp +++ b/engines/bladerunner/crimes_database.cpp @@ -73,14 +73,14 @@ const char *CrimesDatabase::getClueText(int clueId) const { void CrimesDatabase::save(SaveFileWriteStream &f) { for (int i = 0; i < _crimeCount; ++i) { - uint8 c = _crimes[i]; - f.writeByte(c); + int8 c = _crimes[i]; + f.writeSByte(c); } } void CrimesDatabase::load(SaveFileReadStream &f) { for (int i = 0; i < _crimeCount; ++i) { - _crimes[i] = f.readByte(); + _crimes[i] = f.readSByte(); } } diff --git a/engines/bladerunner/debugger.cpp b/engines/bladerunner/debugger.cpp index 0355f9d0f5..6f7e5d14a2 100644 --- a/engines/bladerunner/debugger.cpp +++ b/engines/bladerunner/debugger.cpp @@ -71,6 +71,8 @@ Debugger::Debugger(BladeRunnerEngine *vm) : GUI::Debugger() { registerCmd("say", WRAP_METHOD(Debugger, cmdSay)); registerCmd("scene", WRAP_METHOD(Debugger, cmdScene)); registerCmd("var", WRAP_METHOD(Debugger, cmdVariable)); + registerCmd("load", WRAP_METHOD(Debugger, cmdLoad)); + registerCmd("save", WRAP_METHOD(Debugger, cmdSave)); } Debugger::~Debugger() { @@ -358,6 +360,59 @@ bool Debugger::cmdVariable(int argc, const char **argv) { return true; } +bool Debugger::cmdLoad(int argc, const char **argv) { + if (argc != 2) { + debugPrintf("Loads a save game from original format.\n"); + debugPrintf("Usage: %s <file path>\n", argv[0]); + return true; + } + + Common::FSNode fs(argv[1]); + + if (!fs.isReadable()) { + debugPrintf("Warning: File %s does not exist or is not readable\n", argv[1]); + return true; + } + + Common::SeekableReadStream *saveFile = fs.createReadStream(); + + _vm->loadGame(*saveFile); + + delete saveFile; + + return false; +} + +bool Debugger::cmdSave(int argc, const char **argv) { + if (argc != 2) { + debugPrintf("Saves game to original format.\n"); + debugPrintf("Usage: %s <file path>\n", argv[0]); + return true; + } + + Common::FSNode fs(argv[1]); + + if (fs.exists() && !fs.isWritable()) { + debugPrintf("Warning: File %s is not writable\n", argv[1]); + return true; + } + + Common::WriteStream *saveFile = fs.createWriteStream(); + + uint16 *thumbnail = new uint16[SaveFile::kThumbnailSize]; + _vm->generateThumbnail(thumbnail); + + _vm->saveGame(*saveFile, thumbnail); + + saveFile->finalize(); + + delete[] thumbnail; + + delete saveFile; + + return true; +} + void Debugger::drawBBox(Vector3 start, Vector3 end, View *view, Graphics::Surface *surface, int color) { Vector3 bfl = view->calculateScreenPosition(Vector3(start.x, start.y, start.z)); Vector3 bfr = view->calculateScreenPosition(Vector3(start.x, end.y, start.z)); diff --git a/engines/bladerunner/debugger.h b/engines/bladerunner/debugger.h index 64e312ae20..fef545eda1 100644 --- a/engines/bladerunner/debugger.h +++ b/engines/bladerunner/debugger.h @@ -59,6 +59,8 @@ public: bool cmdSay(int argc, const char **argv); bool cmdScene(int argc, const char **argv); bool cmdVariable(int argc, const char **argv); + bool cmdLoad(int argc, const char **argv); + bool cmdSave(int argc, const char **argv); void drawBBox(Vector3 start, Vector3 end, View *view, Graphics::Surface *surface, int color); void drawSceneObjects(); diff --git a/engines/bladerunner/detection.cpp b/engines/bladerunner/detection.cpp index 934eea7759..8cd4288a0d 100644 --- a/engines/bladerunner/detection.cpp +++ b/engines/bladerunner/detection.cpp @@ -20,12 +20,17 @@ * */ -#include "base/plugins.h" - -#include "engines/advancedDetector.h" #include "bladerunner/bladerunner.h" #include "bladerunner/detection_tables.h" +#include "bladerunner/savefile.h" + +#include "common/config-manager.h" +#include "common/system.h" +#include "common/savefile.h" +#include "common/serializer.h" + +#include "engines/advancedDetector.h" namespace BladeRunner { @@ -38,19 +43,32 @@ static const PlainGameDescriptor bladeRunnerGames[] = { class BladeRunnerMetaEngine : public AdvancedMetaEngine { public: - BladeRunnerMetaEngine() : AdvancedMetaEngine(BladeRunner::gameDescriptions, sizeof(BladeRunner::gameDescriptions[0]), BladeRunner::bladeRunnerGames) { - } + BladeRunnerMetaEngine(); - virtual const char *getName() const { - return "Blade Runner Engine"; - } + const char *getName() const override; + const char *getOriginalCopyright() const override; + bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override; + bool hasFeature(MetaEngineFeature f) const override; + SaveStateList listSaves(const char *target) const override; + int getMaximumSaveSlot() const override; + void removeSaveState(const char *target, int slot) const override; + SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const override; +}; - virtual const char *getOriginalCopyright() const { - return "Blade Runner (C) Westwood Studios."; - } +BladeRunnerMetaEngine::BladeRunnerMetaEngine() + : AdvancedMetaEngine( + BladeRunner::gameDescriptions, + sizeof(BladeRunner::gameDescriptions[0]), + BladeRunner::bladeRunnerGames) {} - virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const; -}; + +const char *BladeRunnerMetaEngine::getName() const { + return "Blade Runner Engine"; +} + +const char *BladeRunnerMetaEngine::getOriginalCopyright() const { + return "Blade Runner (C) 1997 Westwood Studios"; +} bool BladeRunnerMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const { *engine = new BladeRunner::BladeRunnerEngine(syst, desc); @@ -58,6 +76,71 @@ bool BladeRunnerMetaEngine::createInstance(OSystem *syst, Engine **engine, const return true; } +bool BladeRunnerMetaEngine::hasFeature(MetaEngineFeature f) const { + return + f == kSupportsListSaves || + f == kSupportsLoadingDuringStartup || + f == kSupportsDeleteSave || + f == kSavesSupportMetaInfo || + f == kSavesSupportThumbnail || + f == kSimpleSavesNames; +} + +SaveStateList BladeRunnerMetaEngine::listSaves(const char *target) const { + Common::SaveFileManager *saveFileMan = g_system->getSavefileManager(); + Common::StringArray files = saveFileMan->listSavefiles(Common::String::format("%s.###", target)); + + SaveStateList saveList; + for (Common::StringArray::const_iterator fileName = files.begin(); fileName != files.end(); ++fileName) { + Common::InSaveFile *saveFile = saveFileMan->openForLoading(*fileName); + if (saveFile == nullptr || saveFile->err()) { + warning("Cannot open save file '%s'", fileName->c_str()); + continue; + } + + BladeRunner::SaveFileHeader header; + BladeRunner::SaveFile::readHeader(*saveFile, header); + + int slotNum = atoi(fileName->c_str() + fileName->size() - 3); + saveList.push_back(SaveStateDescriptor(slotNum, header._name)); + } + + // Sort saves based on slot number. + Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator()); + return saveList; +} + +int BladeRunnerMetaEngine::getMaximumSaveSlot() const { + return 999; +} + +void BladeRunnerMetaEngine::removeSaveState(const char *target, int slot) const { + Common::String filename = Common::String::format("%s.%03d", target, slot); + g_system->getSavefileManager()->removeSavefile(filename); +} + +SaveStateDescriptor BladeRunnerMetaEngine::querySaveMetaInfos(const char *target, int slot) const { + Common::String filename = Common::String::format("%s.%03d", target, slot); + Common::InSaveFile *saveFile = g_system->getSavefileManager()->openForLoading(filename); + + if (saveFile == nullptr || saveFile->err()) { + return SaveStateDescriptor(); + } + + BladeRunner::SaveFileHeader header; + if (!BladeRunner::SaveFile::readHeader(*saveFile, header, false)) { + delete saveFile; + return SaveStateDescriptor(); + } + delete saveFile; + + SaveStateDescriptor desc(slot, header._name); + desc.setThumbnail(header._thumbnail); + desc.setSaveDate(header._year, header._month, header._day); + desc.setSaveTime(header._hour, header._minute); + return desc; +} + #if PLUGIN_ENABLED_DYNAMIC(BLADERUNNER) REGISTER_PLUGIN_DYNAMIC(BLADERUNNER, PLUGIN_TYPE_ENGINE, BladeRunnerMetaEngine); #else diff --git a/engines/bladerunner/detection_tables.h b/engines/bladerunner/detection_tables.h index 3c509f4314..5d1a851598 100644 --- a/engines/bladerunner/detection_tables.h +++ b/engines/bladerunner/detection_tables.h @@ -23,6 +23,8 @@ #ifndef BLADERUNNER_DETECTION_TABLES_H #define BLADERUNNER_DETECTION_TABLES_H +#include "engines/advancedDetector.h" + namespace BladeRunner { static const ADGameDescription gameDescriptions[] = { diff --git a/engines/bladerunner/dialogue_menu.cpp b/engines/bladerunner/dialogue_menu.cpp index d9a7c62866..4f82326564 100644 --- a/engines/bladerunner/dialogue_menu.cpp +++ b/engines/bladerunner/dialogue_menu.cpp @@ -183,7 +183,7 @@ int DialogueMenu::queryInput() { } _vm->gameTick(); - } while (_waitingForInput); + } while (_vm->_gameIsRunning && _waitingForInput); } else if (agenda == kPlayerAgendaErratic) { int tries = 0; bool searching = true; diff --git a/engines/bladerunner/dialogue_menu.h b/engines/bladerunner/dialogue_menu.h index 6dfd3efdc6..4029fe465b 100644 --- a/engines/bladerunner/dialogue_menu.h +++ b/engines/bladerunner/dialogue_menu.h @@ -81,6 +81,8 @@ public: DialogueMenu(BladeRunnerEngine *vm); ~DialogueMenu(); + void clear(); + bool loadText(const Common::String &name); bool show(); @@ -106,7 +108,6 @@ private: int getAnswerIndex(int answer) const; const char *getText(int id) const; void calculatePosition(int unusedX = 0, int unusedY = 0); - void clear(); void reset(); static void darkenRect(Graphics::Surface &s, int x1, int y1, int x2, int y2); diff --git a/engines/bladerunner/game_flags.cpp b/engines/bladerunner/game_flags.cpp index 6fdcb89363..e2ae3c3259 100644 --- a/engines/bladerunner/game_flags.cpp +++ b/engines/bladerunner/game_flags.cpp @@ -36,14 +36,19 @@ GameFlags::~GameFlags() { delete[] _flags; } +void GameFlags::clear() { + for (int i = 0; i <= _flagCount; ++i) { + reset(i); + } +} + void GameFlags::setFlagCount(int count) { assert(count > 0); _flagCount = count; _flags = new uint32[count / 32 + 1](); - for (int i = 0; i <= _flagCount; ++i) - reset(i); + clear(); } void GameFlags::set(int flag) { diff --git a/engines/bladerunner/game_flags.h b/engines/bladerunner/game_flags.h index 837537f689..3b0d93f8c8 100644 --- a/engines/bladerunner/game_flags.h +++ b/engines/bladerunner/game_flags.h @@ -38,6 +38,7 @@ public: GameFlags(); ~GameFlags(); + void clear(); void setFlagCount(int count); void set(int flag); diff --git a/engines/bladerunner/item.cpp b/engines/bladerunner/item.cpp index 2f82fc0b35..751978bfd3 100644 --- a/engines/bladerunner/item.cpp +++ b/engines/bladerunner/item.cpp @@ -177,7 +177,7 @@ bool Item::isUnderMouse(int mouseX, int mouseY) const { void Item::save(SaveFileWriteStream &f) { f.writeInt(_setId); f.writeInt(_itemId); - f.writeBoundingBox(_boundingBox); + f.writeBoundingBox(_boundingBox, false); f.writeRect(_screenRectangle); f.writeInt(_animationId); f.writeVector3(_position); @@ -199,7 +199,7 @@ void Item::save(SaveFileWriteStream &f) { void Item::load(SaveFileReadStream &f) { _setId = f.readInt(); _itemId = f.readInt(); - _boundingBox = f.readBoundingBox(); + _boundingBox = f.readBoundingBox(false); _screenRectangle = f.readRect(); _animationId = f.readInt(); _position = f.readVector3(); diff --git a/engines/bladerunner/items.cpp b/engines/bladerunner/items.cpp index a2cb9da194..32594515e6 100644 --- a/engines/bladerunner/items.cpp +++ b/engines/bladerunner/items.cpp @@ -35,6 +35,10 @@ Items::Items(BladeRunnerEngine *vm) { } Items::~Items() { + reset(); +} + +void Items::reset() { for (int i = _items.size() - 1; i >= 0; i--) { delete _items.remove_at(i); } diff --git a/engines/bladerunner/items.h b/engines/bladerunner/items.h index ce29a77787..a2c7720b62 100644 --- a/engines/bladerunner/items.h +++ b/engines/bladerunner/items.h @@ -42,6 +42,8 @@ public: Items(BladeRunnerEngine *vm); ~Items(); + void reset(); + void getXYZ(int itemId, float *x, float *y, float *z) const; void setXYZ(int itemId, Vector3 position); void getWidthHeight(int itemId, int *width, int *height) const; diff --git a/engines/bladerunner/outtake.cpp b/engines/bladerunner/outtake.cpp index 6d76162dd9..187f46c0bd 100644 --- a/engines/bladerunner/outtake.cpp +++ b/engines/bladerunner/outtake.cpp @@ -44,9 +44,9 @@ void OuttakePlayer::play(const Common::String &name, bool noLocalization, int co resName = resName + ".VQA"; - VQAPlayer vqa_player(_vm, &_vm->_surfaceFront); + VQAPlayer vqa_player(_vm, &_vm->_surfaceFront, resName); - vqa_player.open(resName); + vqa_player.open(); _vm->_mixer->stopAll(); while (!_vm->shouldQuit()) { diff --git a/engines/bladerunner/overlays.cpp b/engines/bladerunner/overlays.cpp index 65ba83f15d..5bbac87c36 100644 --- a/engines/bladerunner/overlays.cpp +++ b/engines/bladerunner/overlays.cpp @@ -69,14 +69,15 @@ int Overlays::play(const Common::String &name, int loopId, bool loopForever, boo _videos[index].loaded = true; _videos[index].name = name; _videos[index].hash = hash; - _videos[index].vqaPlayer = new VQAPlayer(_vm, &_vm->_surfaceFront); + _videos[index].loopId = loopId; + _videos[index].loopForever = loopForever; + _videos[index].vqaPlayer = new VQAPlayer(_vm, &_vm->_surfaceFront, Common::String::format("%s.VQA", name.c_str())); // repeat forever _videos[index].vqaPlayer->setBeginAndEndFrame(0, 0, -1, kLoopSetModeJustStart, nullptr, nullptr); } - Common::String resourceName = Common::String::format("%s.VQA", name.c_str()); - _videos[index].vqaPlayer->open(resourceName); + _videos[index].vqaPlayer->open(); _videos[index].vqaPlayer->setLoop( loopId, loopForever ? -1 : 0, @@ -86,6 +87,29 @@ int Overlays::play(const Common::String &name, int loopId, bool loopForever, boo return index; } +void Overlays::resume(bool isLoadingGame) { + + for (int i = 0; i < kOverlayVideos; ++i) { + if (_videos[i].loaded && isLoadingGame) { + _videos[i].vqaPlayer = new VQAPlayer(_vm, &_vm->_surfaceFront, Common::String::format("%s.VQA", _videos[i].name.c_str())); + if (!_videos[i].vqaPlayer) { + resetSingle(i); + continue; + } + + _videos[i].vqaPlayer->open(); + _videos[i].vqaPlayer->setLoop( + _videos[i].loopId, + _videos[i].loopForever ? -1 : 0, + kLoopSetModeImmediate, + nullptr, nullptr); + + _videos[i].vqaPlayer->seekToFrame(_videos[i].frame); + _videos[i].vqaPlayer->update(true); + } + } +} + void Overlays::remove(const Common::String &name) { int index = findByHash(MIXArchive::getHash(name)); if (index >= 0) { @@ -104,8 +128,8 @@ void Overlays::removeAll() { void Overlays::tick() { for (int i = 0; i < kOverlayVideos; ++i) { if (_videos[i].loaded) { - int frame = _videos[i].vqaPlayer->update(true); - if (frame < 0) { + _videos[i].frame = _videos[i].vqaPlayer->update(true); + if (_videos[i].frame < 0) { resetSingle(i); } } @@ -138,7 +162,7 @@ void Overlays::resetSingle(int i) { } _videos[i].loaded = false; _videos[i].hash = 0; - _videos[i].field2 = -1; + _videos[i].frame = -1; _videos[i].name.clear(); } @@ -155,9 +179,9 @@ void Overlays::save(SaveFileWriteStream &f) { f.writeInt(0); // vqaPlayer pointer f.writeStringSz(ov.name, 13); f.writeSint32LE(ov.hash); - f.writeInt(ov.field0); - f.writeInt(ov.field1); - f.writeInt(ov.field2); + f.writeInt(ov.loopId); + f.writeBool(ov.loopForever); + f.writeInt(ov.frame); } } @@ -171,9 +195,9 @@ void Overlays::load(SaveFileReadStream &f) { ov.vqaPlayer = nullptr; ov.name = f.readStringSz(13); ov.hash = f.readSint32LE(); - ov.field0 = f.readInt(); - ov.field1 = f.readInt(); - ov.field2 = f.readInt(); + ov.loopId = f.readInt(); + ov.loopForever = f.readBool(); + ov.frame = f.readInt(); } } diff --git a/engines/bladerunner/overlays.h b/engines/bladerunner/overlays.h index 405acbc264..e250db9810 100644 --- a/engines/bladerunner/overlays.h +++ b/engines/bladerunner/overlays.h @@ -45,9 +45,9 @@ class Overlays { VQAPlayer *vqaPlayer; Common::String name; int32 hash; - int field0; - int field1; - int field2; + int loopId; + bool loopForever; + int frame; }; BladeRunnerEngine *_vm; @@ -59,6 +59,7 @@ public: ~Overlays(); int play(const Common::String &name, int loopId, bool loopForever, bool startNow, int a6); + void resume(bool isLoadingGame); void remove(const Common::String &name); void removeAll(); void tick(); diff --git a/engines/bladerunner/savefile.cpp b/engines/bladerunner/savefile.cpp index 3528a6bb82..b0fb1e7fd6 100644 --- a/engines/bladerunner/savefile.cpp +++ b/engines/bladerunner/savefile.cpp @@ -27,13 +27,76 @@ #include "common/rect.h" #include "common/savefile.h" +#include "common/system.h" + +#include "graphics/thumbnail.h" namespace BladeRunner { -SaveFileWriteStream::SaveFileWriteStream() - : MemoryWriteStreamDynamic(DisposeAfterUse::YES) { +bool SaveFile::readHeader(Common::SeekableReadStream &in, SaveFileHeader &header, bool skipThumbnail) { + SaveFileReadStream s(in); + + if (s.readUint32BE() != kTag) { + warning("No header found in save file"); + return false; + } + + header._version = s.readByte(); + if (header._version != kVersion) { + warning("Unsupported version of save file %u, supported is %u", header._version, kVersion); + return false; + } + + header._name = s.readStringSz(kNameLength); + + header._year = s.readUint16LE(); + header._month = s.readUint16LE(); + header._day = s.readUint16LE(); + header._hour = s.readUint16LE(); + header._minute = s.readUint16LE(); + + header._thumbnail = nullptr; + + if (!skipThumbnail) { + header._thumbnail = new Graphics::Surface(); + + int32 pos = s.pos(); + + s.skip(4); //skip size; + + void *thumbnailData = new byte[kThumbnailSize]; + s.read(thumbnailData, kThumbnailSize); + + // TODO: cleanup - remove magic constants + header._thumbnail->init(80, 60, 160, thumbnailData, Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0)); + + s.seek(pos); + } + + return true; +} + +bool SaveFile::writeHeader(Common::WriteStream &out, SaveFileHeader &header) { + SaveFileWriteStream s(out); + + s.writeUint32BE(kTag); + s.writeByte(kVersion); + + s.writeStringSz(header._name, kNameLength); + + TimeDate td; + g_system->getTimeAndDate(td); + s.writeUint16LE(td.tm_year + 1900); + s.writeUint16LE(td.tm_mon + 1); + s.writeUint16LE(td.tm_mday); + s.writeUint16LE(td.tm_hour); + s.writeUint16LE(td.tm_min); + + return true; } +SaveFileWriteStream::SaveFileWriteStream(Common::WriteStream &s) : _s(s) {} + void SaveFileWriteStream::debug(char *p) { write(p, strlen(p) + 1); } @@ -48,7 +111,7 @@ void SaveFileWriteStream::writeInt(int v) { writeUint32LE(v); } -void SaveFileWriteStream::writeFloat(int v) { +void SaveFileWriteStream::writeFloat(float v) { writeFloatLE(v); } @@ -80,7 +143,7 @@ void SaveFileWriteStream::writeRect(const Common::Rect &v) { writeUint32LE(v.bottom); } -void SaveFileWriteStream::writeBoundingBox(const BoundingBox &v) { +void SaveFileWriteStream::writeBoundingBox(const BoundingBox &v, bool serialized) { float x0, y0, z0, x1, y1, z1; v.getXYZ(&x0, &y0, &z0, &x1, &y1, &z1); @@ -92,14 +155,13 @@ void SaveFileWriteStream::writeBoundingBox(const BoundingBox &v) { writeFloatLE(z1); // Bounding boxes have a lot of extra data that's never actually used - for (int i = 0; i != 96; ++i) { + int count = serialized ? 96 : 64; + for (int i = 0; i < count; ++i) { writeFloatLE(0.0f); } } -SaveFileReadStream::SaveFileReadStream(const byte *dataPtr, uint32 dataSize) - : MemoryReadStream(dataPtr, dataSize, DisposeAfterUse::YES) { -} +SaveFileReadStream::SaveFileReadStream(Common::SeekableReadStream &s) : _s(s) {} int SaveFileReadStream::readInt() { return readUint32LE(); @@ -114,10 +176,10 @@ bool SaveFileReadStream::readBool() { } Common::String SaveFileReadStream::readStringSz(int sz) { - char *buf = (char *)malloc(sz); + char *buf = new char[sz]; read(buf, sz); Common::String result = buf; - free(buf); + delete[] buf; return result; } @@ -145,18 +207,22 @@ Common::Rect SaveFileReadStream::readRect() { return result; } -BoundingBox SaveFileReadStream::readBoundingBox() { +BoundingBox SaveFileReadStream::readBoundingBox(bool serialized) { float x0, y0, z0, x1, y1, z1; x0 = readFloatLE(); y0 = readFloatLE(); z0 = readFloatLE(); + x1 = readFloatLE(); y1 = readFloatLE(); z1 = readFloatLE(); - // Bounding boxes have a lot of extra data that's never actually used - skip(384); + // Bounding boxes have a lot of extra data that's never actually used, and there two formats for storing bounding boxes. + int count = serialized ? 96 : 64; + for (int i = 0; i < count; ++i) { + readFloatLE(); + } return BoundingBox(x0, y0, z0, x1, y1, z1); } diff --git a/engines/bladerunner/savefile.h b/engines/bladerunner/savefile.h index 4dfdb20bd4..bcd1619496 100644 --- a/engines/bladerunner/savefile.h +++ b/engines/bladerunner/savefile.h @@ -26,6 +26,8 @@ #include "common/memstream.h" #include "common/types.h" +#include "graphics/surface.h" + namespace Common { class OutSaveFile; class String; @@ -38,27 +40,67 @@ class Vector2; class Vector3; class BoundingBox; -class SaveFileWriteStream : public Common::MemoryWriteStreamDynamic { +struct SaveFileHeader { + uint8 _version; + Common::String _name; + int _year; + int _month; + int _day; + int _hour; + int _minute; + Graphics::Surface *_thumbnail; +}; + +class SaveFile { +private: + static const uint32 kTag = MKTAG('B', 'R', 'S', 'V'); + static const uint32 kVersion = 1; + static const uint32 kNameLength = 32; + +public: + static const uint32 kThumbnailSize = 9600; // 80x60x16bpp + + static bool readHeader(Common::SeekableReadStream &in, SaveFileHeader &header, bool skipThumbnail = true); + static bool writeHeader(Common::WriteStream &out, SaveFileHeader &header); +}; + +class SaveFileWriteStream : public Common::WriteStream { +private: + Common::WriteStream &_s; + public: - SaveFileWriteStream(); + SaveFileWriteStream(Common::WriteStream &s); + + uint32 write(const void *dataPtr, uint32 dataSize) override { return _s.write(dataPtr, dataSize); } + bool flush() override { return _s.flush(); } + int32 pos() const override { return _s.pos(); } void debug(char *p); void padBytes(int count); void writeInt(int v); - void writeFloat(int v); + void writeFloat(float v); void writeBool(bool v); void writeStringSz(const Common::String &s, int sz); void writeVector2(const Vector2 &v); void writeVector3(const Vector3 &v); void writeRect(const Common::Rect &v); - void writeBoundingBox(const BoundingBox &v); + void writeBoundingBox(const BoundingBox &v, bool serialized); }; -class SaveFileReadStream : public Common::MemoryReadStream { +class SaveFileReadStream : public Common::SeekableReadStream { +private: + Common::SeekableReadStream &_s; + public: - SaveFileReadStream(const byte *dataPtr, uint32 dataSize); + SaveFileReadStream(Common::SeekableReadStream &s); + + bool eos() const override { return _s.eos(); } + uint32 read(void *dataPtr, uint32 dataSize) override { return _s.read(dataPtr, dataSize); } + int32 pos() const override { return _s.pos(); } + int32 size() const override { return _s.size(); } + bool seek(int32 offset, int whence = SEEK_SET) override { return _s.seek(offset, whence); } int readInt(); float readFloat(); @@ -67,7 +109,7 @@ public: Vector2 readVector2(); Vector3 readVector3(); Common::Rect readRect(); - BoundingBox readBoundingBox(); + BoundingBox readBoundingBox(bool serialized); }; } // End of namespace BladeRunner diff --git a/engines/bladerunner/scene.cpp b/engines/bladerunner/scene.cpp index fe8dbc7b61..09764c9e50 100644 --- a/engines/bladerunner/scene.cpp +++ b/engines/bladerunner/scene.cpp @@ -87,7 +87,7 @@ bool Scene::open(int setId, int sceneId, bool isLoadingGame) { const Common::String sceneName = _vm->_gameInfo->getSceneName(_sceneId); if (isLoadingGame) { - // TODO: _vm->overlays->resume() + _vm->_overlays->resume(true); } else { _regions->clear(); _exits->clear(); @@ -113,7 +113,7 @@ bool Scene::open(int setId, int sceneId, bool isLoadingGame) { delete _vqaPlayer; } - _vqaPlayer = new VQAPlayer(_vm, &_vm->_surfaceBack); + _vqaPlayer = new VQAPlayer(_vm, &_vm->_surfaceBack, vqaName); if (!_vm->_sceneScript->open(sceneName)) { return false; @@ -138,7 +138,7 @@ bool Scene::open(int setId, int sceneId, bool isLoadingGame) { return true; } - if (!_vqaPlayer->open(vqaName)) { + if (!_vqaPlayer->open()) { return false; } @@ -253,7 +253,9 @@ void Scene::resume(bool isLoadingGame) { int targetFrame = _frame; - if (!isLoadingGame) { + if (isLoadingGame) { + _vqaPlayer->open(); + } else { _vm->_zbuffer->disable(); } diff --git a/engines/bladerunner/scene_objects.cpp b/engines/bladerunner/scene_objects.cpp index 30802a8d64..51538cd6fc 100644 --- a/engines/bladerunner/scene_objects.cpp +++ b/engines/bladerunner/scene_objects.cpp @@ -331,7 +331,7 @@ void SceneObjects::save(SaveFileWriteStream &f) { for (int i = 0; i < kSceneObjectCount; ++i) { f.writeInt(_sceneObjects[i].id); f.writeInt(_sceneObjects[i].type); - f.writeBoundingBox(_sceneObjects[i].boundingBox); + f.writeBoundingBox(_sceneObjects[i].boundingBox, true); f.writeRect(_sceneObjects[i].screenRectangle); f.writeFloat(_sceneObjects[i].distanceToCamera); f.writeBool(_sceneObjects[i].isPresent); @@ -352,7 +352,8 @@ void SceneObjects::load(SaveFileReadStream &f) { for (int i = 0; i < kSceneObjectCount; ++i) { _sceneObjects[i].id = f.readInt(); _sceneObjects[i].type = (SceneObjectType)f.readInt(); - _sceneObjects[i].boundingBox = f.readBoundingBox(); + _sceneObjects[i].boundingBox = f.readBoundingBox(true); + debug("screenRectangle[%i]: %08x", i, f.pos()); _sceneObjects[i].screenRectangle = f.readRect(); _sceneObjects[i].distanceToCamera = f.readFloat(); _sceneObjects[i].isPresent = f.readBool(); diff --git a/engines/bladerunner/script/ai_script.cpp b/engines/bladerunner/script/ai_script.cpp index b328824de1..6addc4382b 100644 --- a/engines/bladerunner/script/ai_script.cpp +++ b/engines/bladerunner/script/ai_script.cpp @@ -364,7 +364,6 @@ void AIScripts::queryAnimationState(int actor, int *animationState, int *animati _inScriptCounter++; if (_AIScripts[actor]) { - _AIScripts[actor]->FledCombat(); _AIScripts[actor]->QueryAnimationState(animationState, animationFrame, animationStateNext, animationNext); } _inScriptCounter--; diff --git a/engines/bladerunner/script/police_maze.cpp b/engines/bladerunner/script/police_maze.cpp index a85fa07451..284b55dcb0 100644 --- a/engines/bladerunner/script/police_maze.cpp +++ b/engines/bladerunner/script/police_maze.cpp @@ -175,7 +175,7 @@ void PoliceMazeTargetTrack::clear(bool isLoadingGame) { void PoliceMazeTargetTrack::add(int trackId, float startX, float startY, float startZ, float endX, float endY, float endZ, int steps, const int *instructions, bool isActive) { _data = (const int *)instructions; - if (true /* !GameIsLoading */) { // TODO: FIXME + if (!_vm->_gameIsLoading) { _itemId = trackId; _pointCount = steps; _dataIndex = 0; diff --git a/engines/bladerunner/script/scene/rc01.cpp b/engines/bladerunner/script/scene/rc01.cpp index db89807022..b217d030f9 100644 --- a/engines/bladerunner/script/scene/rc01.cpp +++ b/engines/bladerunner/script/scene/rc01.cpp @@ -50,7 +50,7 @@ void SceneScriptRC01::InitializeScene() { #if BLADERUNNER_DEBUG_GAME //TODO: not part of game, remove Game_Flag_Set(kFlagIntroPlayed); // force skip intro - Game_Flag_Set(kFlagRC02toRC01); // no landing + Game_Flag_Set(kFlagRC02toRC01); // no landing // Game_Flag_Set(kFlagRC01PoliceDone); // Game_Flag_Set(kFlagKIAPrivacyAddon); // Game_Flag_Set(kFlagZubenRetired); @@ -74,7 +74,7 @@ void SceneScriptRC01::InitializeScene() { // Global_Variable_Set(kVariableChapter, 2); // Chapter_Enter(2, kSetRC03, kSceneRC03); - Set_Enter(14, 73); + // Set_Enter(14, 73); #endif diff --git a/engines/bladerunner/script/script.cpp b/engines/bladerunner/script/script.cpp index 92fbc2b4a0..9d9243afa5 100644 --- a/engines/bladerunner/script/script.cpp +++ b/engines/bladerunner/script/script.cpp @@ -589,7 +589,7 @@ void ScriptBase::Loop_Actor_Travel_Stairs(int actorId, int stepCount, bool up, i break; } } - } while (true); + } while (_vm->_gameIsRunning); actor->setImmunityToObstacles(immunityToObstacles); actor->setAtXYZ(Vector3(actor->getX(), targetY, actor->getZ()), actor->getFacing(), true, false, false); @@ -632,7 +632,7 @@ void ScriptBase::Loop_Actor_Travel_Ladder(int actorId, int stepCount, bool up, i break; } } - } while (true); + } while (_vm->_gameIsRunning); actor->setImmunityToObstacles(immunityToObstacles); actor->setAtXYZ(Vector3(actor->getX(), targetY, actor->getZ()), actor->getFacing(), true, false, false); @@ -730,7 +730,7 @@ int ScriptBase::Animation_Skip_To_Frame() { void ScriptBase::Delay(int miliseconds) { Player_Loses_Control(); int endTime = _vm->getTotalPlayTime() + miliseconds; - while ((int)_vm->getTotalPlayTime() < endTime) { + while (_vm->_gameIsRunning && (int)_vm->getTotalPlayTime() < endTime) { _vm->gameTick(); } Player_Gains_Control(); diff --git a/engines/bladerunner/set.cpp b/engines/bladerunner/set.cpp index ac026a4d76..8111d0b38c 100644 --- a/engines/bladerunner/set.cpp +++ b/engines/bladerunner/set.cpp @@ -340,7 +340,7 @@ void Set::save(SaveFileWriteStream &f) { for (int i = 0; i != _objectCount; ++i) { f.writeStringSz(_objects[i].name, 20); - f.writeBoundingBox(_objects[i].bbox); + f.writeBoundingBox(_objects[i].bbox, true); f.writeBool(_objects[i].isObstacle); f.writeBool(_objects[i].isClickable); f.writeBool(_objects[i].isHotMouse); @@ -375,7 +375,7 @@ void Set::load(SaveFileReadStream &f) { for (int i = 0; i != _objectCount; ++i) { _objects[i].name = f.readStringSz(20); - _objects[i].bbox = f.readBoundingBox(); + _objects[i].bbox = f.readBoundingBox(true); _objects[i].isObstacle = f.readBool(); _objects[i].isClickable = f.readBool(); _objects[i].isHotMouse = f.readBool(); diff --git a/engines/bladerunner/settings.cpp b/engines/bladerunner/settings.cpp index 071adf6dd5..6c3e5a7e33 100644 --- a/engines/bladerunner/settings.cpp +++ b/engines/bladerunner/settings.cpp @@ -73,6 +73,13 @@ Settings::Settings(BladeRunnerEngine *vm) { _learyMode = false; } +void Settings::reset() { + _ammoType = 0; + _ammoAmounts[0] = 1; + _ammoAmounts[1] = 0; + _ammoAmounts[2] = 0; +} + bool Settings::openNewScene() { if (_newSet == -1) { assert(_newScene == -1); @@ -108,8 +115,9 @@ bool Settings::openNewScene() { return false; } _chapter = newChapter; - if (_startingGame) + if (_startingGame) { _startingGame = false; + } } if (!_vm->_scene->open(newSet, newScene, _loadingGame)) { @@ -184,6 +192,10 @@ int Settings::getDifficulty() const { return _difficulty; } +void Settings::setDifficulty(int difficulty) { + _difficulty = difficulty; +} + int Settings::getPlayerAgenda() const { return _playerAgenda; } diff --git a/engines/bladerunner/settings.h b/engines/bladerunner/settings.h index 413786e2e5..3c7048f02b 100644 --- a/engines/bladerunner/settings.h +++ b/engines/bladerunner/settings.h @@ -70,6 +70,8 @@ class Settings { public: Settings(BladeRunnerEngine *vm); + void reset(); + void setGamma(float gamma) { _gamma = gamma; } @@ -109,16 +111,16 @@ public: _newChapter = newChapter; } - void setLoadingGame(bool loadingGame) { - _loadingGame = loadingGame; + void setLoadingGame() { + _loadingGame = true; } - bool getLoadingGame() const { + bool isLoadingGame() const { return _loadingGame; } - void setStartingGame(bool startingGame) { - _startingGame = startingGame; + void setStartingGame() { + _startingGame = true; } bool openNewScene(); @@ -130,6 +132,7 @@ public: void decreaseAmmo(); int getDifficulty() const; + void setDifficulty(int difficulty); int getPlayerAgenda() const; void setPlayerAgenda(int agenda); diff --git a/engines/bladerunner/slice_renderer.cpp b/engines/bladerunner/slice_renderer.cpp index 932e02bee8..5cf818c1ff 100644 --- a/engines/bladerunner/slice_renderer.cpp +++ b/engines/bladerunner/slice_renderer.cpp @@ -207,15 +207,13 @@ void SliceRenderer::calculateBoundingRect() { * Calculate min and max X */ - /* TODO, there is something off with X scaling when Y is high like in rc02, on sides, x seems to be ofsetted a bit more than it should. Start/top vector is doing that */ - Matrix3x2 facingRotation = calculateFacingRotationMatrix(); Matrix3x2 mProjection(_view->_viewportPosition.z / bottom.z, 0.0f, 0.0f, 0.0f, 25.5f, 0.0f); Matrix3x2 mOffset(1.0f, 0.0f, _framePos.x, - 0.0f, 1.0f, _framePos.y); + 0.0f, 1.0f, _framePos.y); Matrix3x2 mScale(_frameScale.x, 0.0f, 0.0f, 0.0f, _frameScale.y, 0.0f); @@ -281,7 +279,6 @@ void SliceRenderer::loadFrame(int animation, int frame) { } struct SliceLineIterator { - // int _sliceMatrix[2][3]; Matrix3x2 _sliceMatrix; int _startY; int _endY; diff --git a/engines/bladerunner/suspects_database.h b/engines/bladerunner/suspects_database.h index c4ed08998e..3eff7a7ba3 100644 --- a/engines/bladerunner/suspects_database.h +++ b/engines/bladerunner/suspects_database.h @@ -96,7 +96,6 @@ public: int getPhotoShapeId(int photoId) const; int getPhotoNotUsed(int photoId) const; -private: void reset(); }; diff --git a/engines/bladerunner/ui/elevator.cpp b/engines/bladerunner/ui/elevator.cpp index 7a6ab3ca35..c7432368f2 100644 --- a/engines/bladerunner/ui/elevator.cpp +++ b/engines/bladerunner/ui/elevator.cpp @@ -66,8 +66,8 @@ int Elevator::activate(int elevatorId) { return 0; } - _vqaPlayer = new VQAPlayer(_vm, &_vm->_surfaceBack); - if (!_vqaPlayer->open(vqaName)) { + _vqaPlayer = new VQAPlayer(_vm, &_vm->_surfaceBack, vqaName); + if (!_vqaPlayer->open()) { return 0; } @@ -161,7 +161,7 @@ int Elevator::activate(int elevatorId) { _buttonClicked = -1; do { _vm->gameTick(); - } while (_buttonClicked == -1); + } while (_vm->_gameIsRunning && _buttonClicked == -1); _imagePicker->deactivate(); diff --git a/engines/bladerunner/ui/esper.cpp b/engines/bladerunner/ui/esper.cpp index 338ee148f3..6803ce5c5c 100644 --- a/engines/bladerunner/ui/esper.cpp +++ b/engines/bladerunner/ui/esper.cpp @@ -107,8 +107,8 @@ void ESPER::open(Graphics::Surface *surface) { _shapesPhotos.resize(10); - _vqaPlayerMain = new VQAPlayer(_vm, &_vm->_surfaceBack); - if (!_vqaPlayerMain->open("ESPER.VQA")) { + _vqaPlayerMain = new VQAPlayer(_vm, &_vm->_surfaceBack, "ESPER.VQA"); + if (!_vqaPlayerMain->open()) { return; } _vqaPlayerMain->setLoop(2, -1, kLoopSetModeJustStart, nullptr, nullptr); @@ -534,7 +534,7 @@ void ESPER::wait(int timeout) { if (!_isWaiting) { _isWaiting = true; uint timeEnd = timeout + _vm->getTotalPlayTime(); - while (_vm->getTotalPlayTime() < timeEnd) { + while (_vm->_gameIsRunning && _vm->getTotalPlayTime() < timeEnd) { _vm->gameTick(); } _isWaiting = false; @@ -866,8 +866,8 @@ void ESPER::drawPhotoZoomOut(Graphics::Surface &surface) { void ESPER::drawVideoZooming(Graphics::Surface &surface) { if (_vqaPlayerPhoto == nullptr) { - _vqaPlayerPhoto = new VQAPlayer(_vm, &_surfaceViewport); - if (!_vqaPlayerPhoto->open(Common::String(_regions[_regionSelected].name) + ".VQA")) { + _vqaPlayerPhoto = new VQAPlayer(_vm, &_surfaceViewport, Common::String(_regions[_regionSelected].name) + ".VQA"); + if (!_vqaPlayerPhoto->open()) { setStatePhoto(kEsperPhotoStateShow); _vm->_mouse->enable(); diff --git a/engines/bladerunner/ui/kia.cpp b/engines/bladerunner/ui/kia.cpp index 756f1bd2cd..4b95607541 100644 --- a/engines/bladerunner/ui/kia.cpp +++ b/engines/bladerunner/ui/kia.cpp @@ -88,6 +88,8 @@ KIA::KIA(BladeRunnerEngine *vm) { _pogoPos = 0; + _thumbnail = nullptr; + _buttons = new UIImagePicker(_vm, 22); _crimesSection = new KIASectionCrimes(_vm, _vm->_playerActor->_clues); @@ -124,6 +126,18 @@ KIA::~KIA() { delete _script; } +void KIA::reset() { + _lastSectionIdKIA = kKIASectionCrimes; + _lastSectionIdOptions = kKIASectionSettings; + _playerVqaFrame = 0; + _playerVisualizerState = 0; + _playerSliceModelAngle = 0.0f; + + _crimesSection->reset(); + _suspectsSection->reset(); + _cluesSection->reset(); +} + void KIA::openLastOpened() { open(_lastSectionIdKIA); } @@ -169,8 +183,8 @@ void KIA::open(KIASections sectionId) { _mainVqaPlayer = nullptr; } - _mainVqaPlayer = new VQAPlayer(_vm, &_vm->_surfaceBack); - _mainVqaPlayer->open(name); + _mainVqaPlayer = new VQAPlayer(_vm, &_vm->_surfaceBack, name); + _mainVqaPlayer->open(); } if (_transitionId) { @@ -621,6 +635,9 @@ void KIA::loopEnded(void *callbackData, int frame, int loopId) { } void KIA::init() { + _thumbnail = new byte[SaveFile::kThumbnailSize]; + _vm->generateThumbnail(_thumbnail); + if (!_vm->openArchive("MODE.MIX")) { return; } @@ -640,8 +657,8 @@ void KIA::init() { _vm->_mouse->setCursor(0); if (_playerVqaPlayer == nullptr) { - _playerVqaPlayer = new VQAPlayer(_vm, &_vm->_surfaceFront); - _playerVqaPlayer->open("kiaover.vqa"); + _playerVqaPlayer = new VQAPlayer(_vm, &_vm->_surfaceFront, "kiaover.vqa"); + _playerVqaPlayer->open(); _playerVqaPlayer->setLoop(0, -1, kLoopSetModeJustStart, nullptr, nullptr); } _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(501), 70, 0, 0, 50, 0); @@ -650,6 +667,9 @@ void KIA::init() { } void KIA::unload() { + delete[] _thumbnail; + _thumbnail = nullptr; + if (!isOpen()) { return; } @@ -684,7 +704,7 @@ void KIA::unload() { // TODO: Unfreeze game time - if (!_vm->_settings->getLoadingGame() && _vm->_gameIsRunning) { + if (!_vm->_settings->isLoadingGame() && _vm->_gameIsRunning) { _vm->_scene->resume(); } } diff --git a/engines/bladerunner/ui/kia.h b/engines/bladerunner/ui/kia.h index 1c2dc19d9f..0612234db1 100644 --- a/engines/bladerunner/ui/kia.h +++ b/engines/bladerunner/ui/kia.h @@ -117,6 +117,8 @@ class KIA { int _pogoPos; + byte *_thumbnail; + public: KIALog *_log; KIAScript *_script; @@ -126,6 +128,8 @@ public: KIA(BladeRunnerEngine *vm); ~KIA(); + void reset(); + void openLastOpened(); void open(KIASections sectionId); bool isOpen() const; diff --git a/engines/bladerunner/ui/kia_section_clues.cpp b/engines/bladerunner/ui/kia_section_clues.cpp index e003e9bb28..7485d8ebcb 100644 --- a/engines/bladerunner/ui/kia_section_clues.cpp +++ b/engines/bladerunner/ui/kia_section_clues.cpp @@ -80,6 +80,18 @@ KIASectionClues::~KIASectionClues() { delete _uiContainer; } +void KIASectionClues::reset() { + _debugIntangible = false; + _debugNop = 0; + + _mouseX = 0; + _mouseY = 0; + + for (int i = 0; i < _filterCount; ++i) { + _filters[i] = true; + } +} + void KIASectionClues::open() { _isOpen = true; diff --git a/engines/bladerunner/ui/kia_section_clues.h b/engines/bladerunner/ui/kia_section_clues.h index 3f6a13d135..afd8b67433 100644 --- a/engines/bladerunner/ui/kia_section_clues.h +++ b/engines/bladerunner/ui/kia_section_clues.h @@ -67,6 +67,8 @@ public: KIASectionClues(BladeRunnerEngine *vm, ActorClues *clues); ~KIASectionClues(); + void reset(); + void open(); void close(); diff --git a/engines/bladerunner/ui/kia_section_crimes.cpp b/engines/bladerunner/ui/kia_section_crimes.cpp index 96075fbc22..ff6352b3e0 100644 --- a/engines/bladerunner/ui/kia_section_crimes.cpp +++ b/engines/bladerunner/ui/kia_section_crimes.cpp @@ -41,7 +41,6 @@ #include "bladerunner/ui/ui_image_picker.h" #include "bladerunner/ui/ui_scroll_box.h" - #include "graphics/surface.h" namespace BladeRunner { @@ -71,6 +70,7 @@ KIASectionCrimes::KIASectionCrimes(BladeRunnerEngine *vm, ActorClues *clues) : K _suspectSelected = -1; _suspectPhotoShapeId = -1; + _suspectPhotoNotUsed = -1; _suspectPhotoShape = nullptr; _suspectsFoundCount = 0; _suspectsFound.resize(_vm->_gameInfo->getSuspectCount()); @@ -87,6 +87,18 @@ KIASectionCrimes::~KIASectionCrimes() { delete _uiContainer; } +void KIASectionCrimes::reset() { + _acquiredClueCount = 0; + _crimesFoundCount = 0; + _suspectsFoundCount = 0; + _mouseX = 0; + _mouseY = 0; + _suspectSelected = -1; + _crimeSelected = -1; + _suspectPhotoShapeId = -1; + _suspectPhotoNotUsed = -1; +} + void KIASectionCrimes::open() { _scheduledSwitch = false; @@ -277,7 +289,7 @@ void KIASectionCrimes::populateAcquiredClues() { ++_acquiredClueCount; } } - // sort clues by name, is it necessary + // sort clues by name, is it necessary? } void KIASectionCrimes::populateCrimes() { @@ -391,18 +403,20 @@ void KIASectionCrimes::updateSuspectPhoto() { SuspectDatabaseEntry *suspect = _vm->_suspectsDatabase->get(_suspectSelected); _suspectPhotoShapeId = -1; + _suspectPhotoNotUsed = -1; int photoCluesCount = suspect->getPhotoCount(); if (photoCluesCount > 0) { for (int i = 0 ; i < photoCluesCount; i++) { - //TODO: weird stuff going on here... it's using index instead id, also some field is used but its always -1 + //TODO: weird stuff going on here... original game is using internal clue index instead id if (_clues->isAcquired(suspect->getPhotoClueId(i))) { _suspectPhotoShapeId = suspect->getPhotoShapeId(i); + _suspectPhotoNotUsed = suspect->getPhotoNotUsed(i); break; } } } - if (_suspectPhotoShapeId == -1) { + if (_suspectPhotoShapeId == -1 && _suspectPhotoNotUsed == -1) { if (suspect->getSex()) { _suspectPhotoShapeId = 14; } else { diff --git a/engines/bladerunner/ui/kia_section_crimes.h b/engines/bladerunner/ui/kia_section_crimes.h index 23983b8d39..bd2a2f2d80 100644 --- a/engines/bladerunner/ui/kia_section_crimes.h +++ b/engines/bladerunner/ui/kia_section_crimes.h @@ -69,6 +69,7 @@ class KIASectionCrimes : public KIASectionBase { int _mouseY; int _suspectPhotoShapeId; + int _suspectPhotoNotUsed; Shape *_suspectPhotoShape; public: @@ -78,6 +79,8 @@ public: KIASectionCrimes(BladeRunnerEngine *vm, ActorClues *clues); ~KIASectionCrimes(); + void reset(); + void open(); void close(); diff --git a/engines/bladerunner/ui/kia_section_suspects.cpp b/engines/bladerunner/ui/kia_section_suspects.cpp index 54e33cb62b..460f744a2a 100644 --- a/engines/bladerunner/ui/kia_section_suspects.cpp +++ b/engines/bladerunner/ui/kia_section_suspects.cpp @@ -86,6 +86,7 @@ KIASectionSuspects::KIASectionSuspects(BladeRunnerEngine *vm, ActorClues *clues) _suspectSelected = -1; _suspectPhotoShapeId = -1; + _suspectPhotoNotUsed = -1; _suspectPhotoShape = nullptr; _suspectsFoundCount = 0; _suspectsFound.resize(_vm->_gameInfo->getSuspectCount()); @@ -108,6 +109,22 @@ KIASectionSuspects::~KIASectionSuspects() { delete _uiContainer; } +void KIASectionSuspects::reset() { + _acquiredClueCount = 0; + _suspectsFoundCount = 0; + _mouseX = 0; + _mouseY = 0; + _suspectSelected = -1; + _crimeSelected = -1; + _suspectPhotoShapeId = -1; + _suspectPhotoNotUsed = -1; + _whereaboutsFilter = true; + _MOFilter = true; + _replicantFilter = true; + _nonReplicantFilter = true; + _othersFilter = true; +} + void KIASectionSuspects::open() { _scheduledSwitch = false; @@ -169,7 +186,6 @@ void KIASectionSuspects::draw(Graphics::Surface &surface) { _uiContainer->draw(surface); - _vm->_mainFont->drawColor(_vm->_textKIA->getText(0), surface, 300, 162, 0x77DF); _vm->_mainFont->drawColor(_vm->_textKIA->getText(46), surface, 142, 248, 0x77DF); _vm->_mainFont->drawColor(_vm->_textKIA->getText(47), surface, 142, 308, 0x77DF); @@ -479,18 +495,20 @@ void KIASectionSuspects::updateSuspectPhoto() { SuspectDatabaseEntry *suspect = _vm->_suspectsDatabase->get(_suspectSelected); _suspectPhotoShapeId = -1; + _suspectPhotoNotUsed = -1; int photoCluesCount = suspect->getPhotoCount(); if (photoCluesCount > 0) { for (int i = 0 ; i < photoCluesCount; i++) { - //TODO: weird stuff going on here... it's using index instead id, also some field is used but its always -1 + //TODO: weird stuff going on here... original game is using internal clue index instead id if (_clues->isAcquired(suspect->getPhotoClueId(i))) { _suspectPhotoShapeId = suspect->getPhotoShapeId(i); + _suspectPhotoNotUsed = suspect->getPhotoNotUsed(i); break; } } } - if (_suspectPhotoShapeId == -1) { + if (_suspectPhotoShapeId == -1 && _suspectPhotoNotUsed == -1) { if (suspect->getSex()) { _suspectPhotoShapeId = 14; } else { diff --git a/engines/bladerunner/ui/kia_section_suspects.h b/engines/bladerunner/ui/kia_section_suspects.h index 0cc957f609..22a3accbee 100644 --- a/engines/bladerunner/ui/kia_section_suspects.h +++ b/engines/bladerunner/ui/kia_section_suspects.h @@ -78,6 +78,7 @@ class KIASectionSuspects : public KIASectionBase { int _mouseY; int _suspectPhotoShapeId; + int _suspectPhotoNotUsed; Shape *_suspectPhotoShape; public: @@ -87,6 +88,8 @@ public: KIASectionSuspects(BladeRunnerEngine *vm, ActorClues *clues); ~KIASectionSuspects(); + void reset(); + void open(); void close(); diff --git a/engines/bladerunner/ui/scores.cpp b/engines/bladerunner/ui/scores.cpp index c4a7df778c..8fc3378207 100644 --- a/engines/bladerunner/ui/scores.cpp +++ b/engines/bladerunner/ui/scores.cpp @@ -50,9 +50,9 @@ void Scores::open() { return; } - _vqaPlayer = new VQAPlayer(_vm, &_vm->_surfaceBack); + _vqaPlayer = new VQAPlayer(_vm, &_vm->_surfaceBack, "SCORE.VQA"); - if (!_vqaPlayer->open("SCORE.VQA")) { + if (!_vqaPlayer->open()) { return; } diff --git a/engines/bladerunner/ui/spinner.cpp b/engines/bladerunner/ui/spinner.cpp index 9e491f719c..32809e8740 100644 --- a/engines/bladerunner/ui/spinner.cpp +++ b/engines/bladerunner/ui/spinner.cpp @@ -74,14 +74,14 @@ int Spinner::chooseDestination(int loopId, bool immediately) { } else { _vm->playerLosesControl(); _vm->_scene->loopStartSpecial(kSceneLoopModeSpinner, loopId, immediately); - while (!_isOpen) { + while (_vm->_gameIsRunning && !_isOpen) { _vm->gameTick(); } _vm->playerGainsControl(); } - _vqaPlayer = new VQAPlayer(_vm, &_vm->_surfaceBack); - if (!_vqaPlayer->open("SPINNER.VQA")) { + _vqaPlayer = new VQAPlayer(_vm, &_vm->_surfaceBack, "SPINNER.VQA"); + if (!_vqaPlayer->open()) { return 0; } @@ -159,7 +159,7 @@ int Spinner::chooseDestination(int loopId, bool immediately) { _selectedDestination = -1; do { _vm->gameTick(); - } while (_selectedDestination == -1); + } while (_vm->_gameIsRunning && _selectedDestination == -1); _imagePicker->deactivate(); diff --git a/engines/bladerunner/ui/vk.cpp b/engines/bladerunner/ui/vk.cpp index ec5013ca4c..ae776b7e55 100644 --- a/engines/bladerunner/ui/vk.cpp +++ b/engines/bladerunner/ui/vk.cpp @@ -87,8 +87,8 @@ void VK::open(int actorId, int calibrationRatio) { _shapes[i]->open("VK.SHP", i); } - _vqaPlayerMain = new VQAPlayer(_vm, &_vm->_surfaceBack); - if (!_vqaPlayerMain->open("VK.VQA")) { + _vqaPlayerMain = new VQAPlayer(_vm, &_vm->_surfaceBack, "VK.VQA"); + if (!_vqaPlayerMain->open()) { return; } @@ -114,8 +114,8 @@ void VK::open(int actorId, int calibrationRatio) { } _surfaceEye.create(172, 116, createRGB555()); - _vqaPlayerEye = new VQAPlayer(_vm, &_surfaceEye); - if (!_vqaPlayerEye->open(eyeVqa)) { + _vqaPlayerEye = new VQAPlayer(_vm, &_surfaceEye, eyeVqa); + if (!_vqaPlayerEye->open()) { return; } if (!_vqaPlayerEye->setLoop(0, -1, kLoopSetModeEnqueue, nullptr, nullptr)) { diff --git a/engines/bladerunner/vqa_player.cpp b/engines/bladerunner/vqa_player.cpp index 5f25a6387c..68a4e9491d 100644 --- a/engines/bladerunner/vqa_player.cpp +++ b/engines/bladerunner/vqa_player.cpp @@ -30,8 +30,8 @@ namespace BladeRunner { -bool VQAPlayer::open(const Common::String &name) { - _s = _vm->getResourceStream(name); +bool VQAPlayer::open() { + _s = _vm->getResourceStream(_name); if (!_s) { return false; } diff --git a/engines/bladerunner/vqa_player.h b/engines/bladerunner/vqa_player.h index b2c6ff2d4d..c4dd182697 100644 --- a/engines/bladerunner/vqa_player.h +++ b/engines/bladerunner/vqa_player.h @@ -49,6 +49,7 @@ class VQAPlayer { friend class Debugger; BladeRunnerEngine *_vm; + Common::String _name; Common::SeekableReadStream *_s; VQADecoder _decoder; Audio::QueuingAudioStream *_audioStream; @@ -77,8 +78,9 @@ class VQAPlayer { public: - VQAPlayer(BladeRunnerEngine *vm, Graphics::Surface *surface) + VQAPlayer(BladeRunnerEngine *vm, Graphics::Surface *surface, const Common::String &name) : _vm(vm), + _name(name), _s(nullptr), _surface(surface), _decoder(), @@ -103,7 +105,7 @@ public: close(); } - bool open(const Common::String &name); + bool open(); void close(); int update(bool forceDraw = false, bool advanceFrame = true, Graphics::Surface *customSurface = nullptr); |