diff options
Diffstat (limited to 'engines/bladerunner')
57 files changed, 1197 insertions, 31 deletions
diff --git a/engines/bladerunner/actor.cpp b/engines/bladerunner/actor.cpp index b45e6e2114..aae1085834 100644 --- a/engines/bladerunner/actor.cpp +++ b/engines/bladerunner/actor.cpp @@ -32,6 +32,7 @@ #include "bladerunner/items.h" #include "bladerunner/mouse.h" #include "bladerunner/movement_track.h" +#include "bladerunner/savefile.h" #include "bladerunner/scene.h" #include "bladerunner/scene_objects.h" #include "bladerunner/script/scene_script.h" @@ -1225,4 +1226,80 @@ bool Actor::walkToNearestPoint(const Vector3 &destination, float distance) { return false; } +void Actor::save(SaveFile &f) { + f.write(_id); + f.write(_setId); + f.write(_position); + f.write(_facing); + f.write(_targetFacing); + f.write(0); // TODO: _timer4RemainDefault + + f.write(_honesty); + f.write(_intelligence); + f.write(_stability); + f.write(_combatAggressiveness); + f.write(_goalNumber); + + f.write(_currentHP); + f.write(_maxHP); + + f.write(_movementTrackPaused); + f.write(_movementTrackNextWaypointId); + f.write(_movementTrackNextDelay); + f.write(_movementTrackNextAngle); + f.write(_movementTrackNextRunning); + + f.write(0); // TODO: _clueType + f.write(_isMoving); + f.write(_isTarget); + f.write(_inCombat); + f.write(_isInvisible); + f.write(_isRetired); + f.write(_isImmuneToObstacles); + + f.write(_animationMode); + f.write(_fps); + f.write(_frameMs); + f.write(_animationId); + f.write(_animationFrame); + + f.write(_movementTrackWalkingToWaypointId); + f.write(_movementTrackDelayOnNextWaypoint); + + f.write(_screenRectangle); + f.write(_retiredWidth); + f.write(_retiredHeight); + f.write(_damageAnimIfMoving); + f.write(0); // TODO: _actorFieldU6 + f.write(0); // TODO: _actorFieldU7 + f.write(_scale); + + for (int i = 0; i < 7; ++i) { + f.write(_timersLeft[i]); + } + + uint32 now = _vm->getTotalPlayTime(); // TODO: should be last lock time + for (int i = 0; i < 7; ++i) { + f.write(_timersLast[i] - now); + } + + int actorCount = _vm->_gameInfo->getActorCount(); + for (int i = 0; i != actorCount; ++i) { + f.write(_friendlinessToOther[i]); + } + + _clues->save(f); + + _movementTrack->save(f); + + _walkInfo->save(f); + + _bbox->save(f); + + _combatInfo->save(f); + f.write(_animationModeCombatIdle); + f.write(_animationModeCombatWalk); + f.write(_animationModeCombatRun); +} + } // End of namespace BladeRunner diff --git a/engines/bladerunner/actor.h b/engines/bladerunner/actor.h index e381f6818e..55ffc4f30e 100644 --- a/engines/bladerunner/actor.h +++ b/engines/bladerunner/actor.h @@ -36,6 +36,7 @@ class ActorWalk; class BladeRunnerEngine; class BoundingBox; class MovementTrack; +class SaveFile; class View; class Actor { @@ -256,6 +257,9 @@ private: bool walkFindU2(Vector3 *newDestination, float targetWidth, int destinationOffset, float targetSize, const Vector3 &startPosition, const Vector3 &targetPosition); bool walkToNearestPoint(const Vector3 &destination, float distance); //bool walkFindU3(int actorId, Vector3 from, int distance, Vector3 *out); + +public: + void save(SaveFile &f); }; } // End of namespace BladeRunner diff --git a/engines/bladerunner/actor_clues.cpp b/engines/bladerunner/actor_clues.cpp index 39fbc77d4e..89db6feb47 100644 --- a/engines/bladerunner/actor_clues.cpp +++ b/engines/bladerunner/actor_clues.cpp @@ -25,6 +25,7 @@ #include "bladerunner/bladerunner.h" #include "bladerunner/game_info.h" #include "bladerunner/crimes_database.h" +#include "bladerunner/savefile.h" #include "common/debug.h" @@ -216,6 +217,24 @@ void ActorClues::remove(int index) { _clues[index].field8 = 0; } +void ActorClues::save(SaveFile &f) { + f.write(_count); + f.write(_maxCount); + for (int i = 0; i < _count; ++i) { + Clue &c = _clues[i]; + f.write(c.clueId); + f.write(c.weight); + f.write(c.fromActorId); + f.write(c.field3); + f.write(c.field4); + f.write(c.field5); + f.write(c.field6); + f.write(c.field7); + f.write(c.field8); + f.write(c.flags); + } +} + bool ActorClues::exists(int clueId) const { return findClueIndex(clueId) != -1; } diff --git a/engines/bladerunner/actor_clues.h b/engines/bladerunner/actor_clues.h index b2b39d8b89..03ccff20fd 100644 --- a/engines/bladerunner/actor_clues.h +++ b/engines/bladerunner/actor_clues.h @@ -28,6 +28,7 @@ namespace BladeRunner { class BladeRunnerEngine; +class SaveFile; class ActorClues { struct Clue { @@ -74,7 +75,7 @@ public: void removeAll(); - //savegame + void save(SaveFile &f); //loadgame private: diff --git a/engines/bladerunner/actor_combat.cpp b/engines/bladerunner/actor_combat.cpp index aa8e55b28c..7a60d6d85a 100644 --- a/engines/bladerunner/actor_combat.cpp +++ b/engines/bladerunner/actor_combat.cpp @@ -29,6 +29,7 @@ #include "bladerunner/game_constants.h" #include "bladerunner/game_info.h" #include "bladerunner/movement_track.h" +#include "bladerunner/savefile.h" #include "bladerunner/scene.h" #include "bladerunner/scene_objects.h" #include "bladerunner/script/ai_script.h" @@ -49,6 +50,31 @@ void ActorCombat::setup() { reset(); } +void ActorCombat::save(SaveFile &f) { + // TODO + f.write(0); // _actorId + f.write(0); // _combatOn + f.write(0); // _field2 + f.write(0); // _field3 + f.write(0); // _otherActorId + f.write(0); // _field5 + f.write(0); // _field6 + f.write(0); // _field7 + f.write(0); // _field8 + f.write(0); // _field9 + f.write(0); // _field10 + f.write(0); // _field11 + f.write(0); // _field12 + f.write(0); // _actorHp + f.write(0); // _field14 + f.write(0); // _field15 + f.write(0); // _actorPosition + f.write(0); // _otherActorPosition + f.write(0); // _availableCoversCount + f.write(0); // _availableFleeWaypointsCount + f.write(0); // _field24 +} + void ActorCombat::combatOn(int actorId, int initialState, bool rangedAttackFlag, int enemyId, int waypointType, int fleeRatio, int coverRatio, int actionRatio, int damage, int range, bool unstoppable) { _actorId = actorId; _state = initialState; diff --git a/engines/bladerunner/actor_combat.h b/engines/bladerunner/actor_combat.h index 42ef7de9a6..a621c3d6ff 100644 --- a/engines/bladerunner/actor_combat.h +++ b/engines/bladerunner/actor_combat.h @@ -28,6 +28,7 @@ namespace BladeRunner { class BladeRunnerEngine; +class SaveFile; class ActorCombat { BladeRunnerEngine *_vm; @@ -64,6 +65,8 @@ public: void combatOff(); void tick(); + + void save(SaveFile &f); void hitAttempt(); diff --git a/engines/bladerunner/actor_dialogue_queue.cpp b/engines/bladerunner/actor_dialogue_queue.cpp index dbf5598a52..5f0ad60426 100644 --- a/engines/bladerunner/actor_dialogue_queue.cpp +++ b/engines/bladerunner/actor_dialogue_queue.cpp @@ -26,6 +26,7 @@ #include "bladerunner/actor.h" #include "bladerunner/audio_speech.h" +#include "bladerunner/savefile.h" #include "bladerunner/scene.h" #include "bladerunner/script/scene_script.h" @@ -159,6 +160,30 @@ void ActorDialogueQueue::tick() { } } +void ActorDialogueQueue::save(SaveFile &f) { + int count = (int)_entries.size(); + f.write(count); + for (int i = 0; i < count; ++i) { + Entry &e = _entries[i]; + f.write(e.isNotPause); + f.write(e.isPause); + f.write(e.actorId); + f.write(e.sentenceId); + f.write(e.animationMode); + f.write(e.delay); + } + f.padBytes((25 - count) * 24); + + f.write(_isNotPause); + f.write(_actorId); + f.write(_sentenceId); + f.write(_animationMode); + f.write(_animationModePrevious); + f.write(_isPause); + f.write(_delay); + // f.write(_timeLast); +} + void ActorDialogueQueue::clear() { _entries.clear(); _isNotPause = false; @@ -170,4 +195,5 @@ void ActorDialogueQueue::clear() { _delay = 0; _timeLast = 0; } + } // End of namespace BladeRunner diff --git a/engines/bladerunner/actor_dialogue_queue.h b/engines/bladerunner/actor_dialogue_queue.h index 841ca8a48e..e26b6cf1a1 100644 --- a/engines/bladerunner/actor_dialogue_queue.h +++ b/engines/bladerunner/actor_dialogue_queue.h @@ -22,11 +22,13 @@ #ifndef BLADERUNNER_ACTOR_DIALOGUE_QUEUE_H #define BLADERUNNER_ACTOR_DIALOGUE_QUEUE_H + #include "common/array.h" namespace BladeRunner { class BladeRunnerEngine; +class SaveFile; class ActorDialogueQueue { struct Entry { @@ -61,6 +63,8 @@ public: void flush(int a1, bool callScript); void tick(); + void save(SaveFile &f); + private: void clear(); }; diff --git a/engines/bladerunner/actor_walk.cpp b/engines/bladerunner/actor_walk.cpp index 16009aa65b..d376e36785 100644 --- a/engines/bladerunner/actor_walk.cpp +++ b/engines/bladerunner/actor_walk.cpp @@ -28,6 +28,7 @@ #include "bladerunner/game_constants.h" #include "bladerunner/game_info.h" #include "bladerunner/obstacles.h" +#include "bladerunner/savefile.h" #include "bladerunner/scene.h" #include "bladerunner/scene_objects.h" #include "bladerunner/set.h" @@ -238,6 +239,27 @@ void ActorWalk::run(int actorId) { _vm->_actors[actorId]->changeAnimationMode(animationMode, false); } +void ActorWalk::save(SaveFile &f) { + f.write(_walking); + f.write(_running); + f.write(_destination); + // _originalDestination is not saved + f.write(_current); + f.write(_next); + f.write(_facing); + + assert(_nearActors.size() <= 20); + for (Common::HashMap<int, bool>::const_iterator it = _nearActors.begin(); it != _nearActors.end(); ++it) { + f.write(it->_key); + f.write(it->_value); + } + f.padBytes(8 * (20 - _nearActors.size())); + f.write((int)_nearActors.size()); + + f.write(0); // _notUsed + f.write(_status); +} + bool ActorWalk::isXYZEmpty(float x, float y, float z, int actorId) const { if (_vm->_scene->_set->findWalkbox(x, z) == -1) { return true; diff --git a/engines/bladerunner/actor_walk.h b/engines/bladerunner/actor_walk.h index f4caa65453..265421458f 100644 --- a/engines/bladerunner/actor_walk.h +++ b/engines/bladerunner/actor_walk.h @@ -29,6 +29,7 @@ namespace BladeRunner { class BladeRunnerEngine; +class SaveFile; class ActorWalk { BladeRunnerEngine *_vm; @@ -60,6 +61,7 @@ public: void stop(int actorId, bool immediately, int combatAnimationMode, int animationMode); void run(int actorId); + void save(SaveFile &f); private: int nextOnPath(int actorId, const Vector3 &from, const Vector3 &to, Vector3 &next) const; diff --git a/engines/bladerunner/ambient_sounds.cpp b/engines/bladerunner/ambient_sounds.cpp index 64a85bc46c..6477f27c8e 100644 --- a/engines/bladerunner/ambient_sounds.cpp +++ b/engines/bladerunner/ambient_sounds.cpp @@ -25,6 +25,7 @@ #include "bladerunner/audio_player.h" #include "bladerunner/bladerunner.h" #include "bladerunner/game_info.h" +#include "bladerunner/savefile.h" #include "common/debug.h" #include "common/system.h" @@ -362,4 +363,40 @@ void AmbientSounds::removeLoopingSoundByIndex(int index, int delay) { track.pan = 0; } +void AmbientSounds::save(SaveFile &f) { + f.write(false); // TODO: _isDisabled + + for (int i = 0; i != kNonLoopingSounds; ++i) { + // 73 bytes per non-looping sound + NonLoopingSound &s = _nonLoopingSounds[i]; + f.write(s.isActive); + f.write(s.name, 13); + f.write(s.hash); + f.write(s.audioPlayerTrack); + f.write(s.timeMin); + f.write(s.timeMax); + f.write(s.nextPlayTime); + f.write(s.volumeMin); + f.write(s.volumeMax); + f.write(s.volume); + f.write(s.panStartMin); + f.write(s.panStartMax); + f.write(s.panEndMin); + f.write(s.panEndMax); + f.write(s.priority); + f.padBytes(4); // field_45 + } + + for (int i = 0; i != kLoopingSounds; ++i) { + // 33 bytes per looping sound + LoopingSound &s = _loopingSounds[i]; + f.write(s.isActive); + f.write(s.name, 13); + f.write(s.hash); + f.write(s.audioPlayerTrack); + f.write(s.volume); + f.write(s.pan); + } +} + } // End of namespace BladeRunner diff --git a/engines/bladerunner/ambient_sounds.h b/engines/bladerunner/ambient_sounds.h index e06726b183..6e14c56cec 100644 --- a/engines/bladerunner/ambient_sounds.h +++ b/engines/bladerunner/ambient_sounds.h @@ -28,6 +28,7 @@ namespace BladeRunner { class BladeRunnerEngine; +class SaveFile; class AmbientSounds { static const int kNonLoopingSounds = 25; @@ -103,6 +104,8 @@ public: int getVolume() const; void playSample(); + void save(SaveFile &f); + private: int findAvailableNonLoopingTrack() const; int findNonLoopingTrackByHash(int32 hash) const; diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp index 0fd7663271..805461ce3c 100644 --- a/engines/bladerunner/bladerunner.cpp +++ b/engines/bladerunner/bladerunner.cpp @@ -45,7 +45,9 @@ #include "bladerunner/outtake.h" #include "bladerunner/obstacles.h" #include "bladerunner/overlays.h" +#include "bladerunner/police_maze.h" #include "bladerunner/regions.h" +#include "bladerunner/savefile.h" #include "bladerunner/scene.h" #include "bladerunner/scene_objects.h" #include "bladerunner/screen_effects.h" @@ -74,6 +76,7 @@ #include "common/array.h" #include "common/error.h" #include "common/events.h" +#include "common/savefile.h" #include "common/system.h" #include "engines/util.h" @@ -290,7 +293,7 @@ bool BladeRunnerEngine::startup(bool hasSavegames) { // TODO: Flee waypoints - _gameVars = new int[_gameInfo->getGlobalVarCount()]; + _gameVars = new int[_gameInfo->getGlobalVarCount()](); // TODO: Actor AI DLL init @@ -352,7 +355,9 @@ bool BladeRunnerEngine::startup(bool hasSavegames) { // TODO: Set actor ids (redundant?) - // TODO: Police Maze + _policeMaze = new PoliceMaze(this); + if (!_policeMaze->init()) + return false; _textActorNames = new TextResource(this); if (!_textActorNames->open("ACTORS")) @@ -1580,6 +1585,91 @@ void BladeRunnerEngine::playerGainsControl() { } } +bool BladeRunnerEngine::saveGame(const Common::String &filename, byte *thumbnail) { + warning("BladeRunnerEngine::saveGame not finished"); + + if (!playerHasControl() || _sceneScript->isInsideScript() || _aiScripts->isInsideScript()) { + return false; + } + + Common::OutSaveFile *commonSaveFile = getSaveFileManager()->openForSaving(filename, false); + if (commonSaveFile->err()) { + return false; + } + + SaveFile s(commonSaveFile); + + s.padBytes(9600); // TODO: thumbnail + s.write(-1.0f); + + _settings->save(s); + // s.debug(" - SCENE - "); + _scene->save(s); + // s.debug(" - EXIST - "); + _scene->_exits->save(s); + // s.debug(" - REGIONS - "); + _scene->_regions->save(s); + // s.debug(" - SET - "); + _scene->_set->save(s); + + // s.debug(" - GAMEVARS - "); + for (uint i = 0; i != _gameInfo->getGlobalVarCount(); ++i) { + s.write(_gameVars[i]); + } + + // TODO + // _music->save(s); + // s.debug(" - MUSIC - "); + s.padBytes(0x56); + + // _audioPlayer->save(s) // zero func + // _audioSpeech->save(s) // zero func + + // s.debug(" - COMBAT - "); + _combat->save(s); + // s.debug(" - GAMEFLAGS - "); + _gameFlags->save(s); + // s.debug(" - ITEMS - "); + _items->save(s); + // s.debug(" - SCENEOBJECTS - "); + _sceneObjects->save(s); + // s.debug(" - AMBIENTSOUNDS - "); + _ambientSounds->save(s); + // s.debug(" - OVERLAYS - "); + _overlays->save(s); + // s.debug(" - SPINNER - "); + _spinner->save(s); + + // TODO + // _scores->save(s); + s.padBytes(0x28); + + _dialogueMenu->save(s); + _obstacles->save(s); + _actorDialogueQueue->save(s); + _waypoints->save(s); + + for (uint i = 0; i != _gameInfo->getActorCount(); ++i) { + _actors[i]->save(s); + + int animationState, animationFrame, a3, a4; + _aiScripts->queryAnimationState(i, &animationState, &animationFrame, &a3, &a4); + s.write(animationState); + s.write(animationFrame); + s.write(a3); + s.write(a4); + } + _actors[kActorVoiceOver]->save(s); + + _policeMaze->save(s); + _crimesDatabase->save(s); + + s.finalize(); + assert(0 && "ok"); + + return !commonSaveFile->err(); +} + void BladeRunnerEngine::ISez(const char *str) { debug("\t%s", str); } diff --git a/engines/bladerunner/bladerunner.h b/engines/bladerunner/bladerunner.h index 2c3b7c6a39..7561db2acf 100644 --- a/engines/bladerunner/bladerunner.h +++ b/engines/bladerunner/bladerunner.h @@ -260,6 +260,11 @@ public: void playerLosesControl(); void playerGainsControl(); + bool saveGame(const Common::String &filename, byte *thumbnail); + void loadGame(); + void newGame(); + void autoSaveGame(); + void ISez(const char *str); void blitToScreen(const Graphics::Surface &src); diff --git a/engines/bladerunner/boundingbox.cpp b/engines/bladerunner/boundingbox.cpp index a1c79a17e7..aea2dc0a24 100644 --- a/engines/bladerunner/boundingbox.cpp +++ b/engines/bladerunner/boundingbox.cpp @@ -22,6 +22,8 @@ #include "bladerunner/boundingbox.h" +#include "bladerunner/savefile.h" + namespace BladeRunner { BoundingBox::BoundingBox(float x0, float y0, float z0, float x1, float y1, float z1) { @@ -82,4 +84,16 @@ float BoundingBox::getZ1() const { return _vertices[1].z; } +void BoundingBox::save(SaveFile &f) { + f.write(_vertices[0].x); + f.write(_vertices[0].y); + f.write(_vertices[0].z); + f.write(_vertices[1].x); + f.write(_vertices[1].y); + f.write(_vertices[1].z); + + // Bounding boxes have a lot of extra data that's never actually used + f.padBytes(8*8*4); +} + } // End of namespace BladeRunner diff --git a/engines/bladerunner/boundingbox.h b/engines/bladerunner/boundingbox.h index 11922cbd14..0397a86266 100644 --- a/engines/bladerunner/boundingbox.h +++ b/engines/bladerunner/boundingbox.h @@ -27,6 +27,8 @@ namespace BladeRunner { +class SaveFile; + class BoundingBox { Vector3 _vertices[2]; @@ -43,6 +45,8 @@ public: float getZ0() const; float getZ1() const; + + void save(SaveFile &f); }; } // End of namespace BladeRunner diff --git a/engines/bladerunner/combat.cpp b/engines/bladerunner/combat.cpp index ef7a589456..eefcebccba 100644 --- a/engines/bladerunner/combat.cpp +++ b/engines/bladerunner/combat.cpp @@ -28,6 +28,7 @@ #include "bladerunner/game_constants.h" #include "bladerunner/game_info.h" #include "bladerunner/movement_track.h" +#include "bladerunner/savefile.h" #include "bladerunner/scene_objects.h" #include "bladerunner/settings.h" @@ -204,4 +205,15 @@ int Combat::findCoverWaypoint(int waypointType, int actorId, int enemyId) const return result; } +void Combat::save(SaveFile &f) { + f.write(_active); + f.write(_enabled); + for (int i = 0; i != 9; ++i) { + f.write(_hitSoundId[i]); + } + for (int i = 0; i != 9; ++i) { + f.write(_missSoundId[i]); + } +} + } // End of namespace BladeRunner diff --git a/engines/bladerunner/combat.h b/engines/bladerunner/combat.h index ab289cca5c..670f580011 100644 --- a/engines/bladerunner/combat.h +++ b/engines/bladerunner/combat.h @@ -30,6 +30,8 @@ namespace BladeRunner { class BladeRunnerEngine; +class SaveFile; +class Vector3; class Combat { static const int kSoundCount = 9; @@ -38,10 +40,10 @@ class Combat { bool _active; bool _enabled; - int _hitSoundId[kSoundCount]; - int _missSoundId[kSoundCount]; -// int _random1; -// int _random2; + int _hitSoundId[kSoundCount]; + int _missSoundId[kSoundCount]; + // int _random1; + // int _random2; public: int _ammoDamage[3]; @@ -87,6 +89,8 @@ public: int findFleeWaypoint(int setId, int enemyId, const Vector3& position) const; int findCoverWaypoint(int waypointType, int actorId, int enemyId) const; + + void save(SaveFile &f); }; } // End of namespace BladeRunner diff --git a/engines/bladerunner/crimes_database.cpp b/engines/bladerunner/crimes_database.cpp index febe408cd9..131c871654 100644 --- a/engines/bladerunner/crimes_database.cpp +++ b/engines/bladerunner/crimes_database.cpp @@ -24,6 +24,7 @@ #include "bladerunner/bladerunner.h" +#include "bladerunner/savefile.h" #include "bladerunner/text_resource.h" namespace BladeRunner { @@ -70,4 +71,11 @@ const char *CrimesDatabase::getClueText(int clueId) const { return _cluesText->getText(clueId); } +void CrimesDatabase::save(SaveFile &f) { + for (int i = 0; i < _crimeCount; ++i) { + uint8 c = _crimes[i]; + f.write(c); + } +} + } // End of namespace BladeRunner diff --git a/engines/bladerunner/crimes_database.h b/engines/bladerunner/crimes_database.h index 40e46cb356..1374d52424 100644 --- a/engines/bladerunner/crimes_database.h +++ b/engines/bladerunner/crimes_database.h @@ -28,6 +28,7 @@ namespace BladeRunner { class BladeRunnerEngine; +class SaveFile; class TextResource; class CrimesDatabase { @@ -47,6 +48,8 @@ public: int getAssetType(int clueId) const; const char *getClueText(int clueId) const; + + void save(SaveFile &f); }; } // End of namespace BladeRunner diff --git a/engines/bladerunner/dialogue_menu.cpp b/engines/bladerunner/dialogue_menu.cpp index 685c8459e0..7b7223fe94 100644 --- a/engines/bladerunner/dialogue_menu.cpp +++ b/engines/bladerunner/dialogue_menu.cpp @@ -25,6 +25,7 @@ #include "bladerunner/bladerunner.h" #include "bladerunner/font.h" #include "bladerunner/mouse.h" +#include "bladerunner/savefile.h" #include "bladerunner/settings.h" #include "bladerunner/shape.h" #include "bladerunner/text_resource.h" @@ -364,6 +365,30 @@ bool DialogueMenu::waitingForInput() const { return _waitingForInput; } +void DialogueMenu::save(SaveFile &f) { + f.write(_isVisible); + f.write(_waitingForInput); + f.write(_selectedItemIndex); + f.write(_listSize); + + f.write(_neverRepeatListSize); + for (int i = 0; i < 100; ++i) { + f.write(_neverRepeatValues[i]); + } + for (int i = 0; i < 100; ++i) { + f.write(_neverRepeatWasSelected[i]); + } + for (int i = 0; i < 10; ++i) { + f.write(_items[i].text, 50); + f.write(_items[i].answerValue); + f.write(_items[i].colorIntensity); + f.write(_items[i].priorityPolite); + f.write(_items[i].priorityNormal); + f.write(_items[i].prioritySurly); + f.write(_items[i].isDone); + } +} + void DialogueMenu::clear() { _isVisible = false; _waitingForInput = false; diff --git a/engines/bladerunner/dialogue_menu.h b/engines/bladerunner/dialogue_menu.h index 63e23d8ada..b06cf9dfb6 100644 --- a/engines/bladerunner/dialogue_menu.h +++ b/engines/bladerunner/dialogue_menu.h @@ -33,6 +33,7 @@ namespace BladeRunner { class BladeRunnerEngine; +class SaveFile; class TextResource; class DialogueMenu { @@ -102,6 +103,10 @@ private: const char *getText(int id) const; void calculatePosition(int unusedX = 0, int unusedY = 0); +public: + void save(SaveFile &f); + +private: void clear(); void reset(); diff --git a/engines/bladerunner/game_flags.cpp b/engines/bladerunner/game_flags.cpp index 81fe6a0a4f..1e0b58378e 100644 --- a/engines/bladerunner/game_flags.cpp +++ b/engines/bladerunner/game_flags.cpp @@ -22,6 +22,8 @@ #include "bladerunner/game_flags.h" +#include "bladerunner/savefile.h" + #include "common/debug.h" namespace BladeRunner { @@ -38,7 +40,7 @@ void GameFlags::setFlagCount(int count) { assert(count > 0); _flagCount = count; - _flags = new uint32[count / 32 + 1]; + _flags = new uint32[count / 32 + 1](); for (int i = 0; i <= _flagCount; ++i) reset(i); @@ -71,4 +73,10 @@ bool GameFlags::query(int flag) const { return !!(_flags[flag / 32] & (1 << (flag % 32))); } +void GameFlags::save(SaveFile &f) { + for (int i = 0; i != _flagCount / 32 + 1; ++i) { + f.write(_flags[i]); + } +} + } // End of namespace BladeRunner diff --git a/engines/bladerunner/game_flags.h b/engines/bladerunner/game_flags.h index 83cbdbc086..b409e858b0 100644 --- a/engines/bladerunner/game_flags.h +++ b/engines/bladerunner/game_flags.h @@ -27,6 +27,8 @@ namespace BladeRunner { +class SaveFile; + class GameFlags { uint32 *_flags; int _flagCount; @@ -40,6 +42,8 @@ public: void set(int flag); void reset(int flag); bool query(int flag) const; + + void save(SaveFile &f); }; } // End of namespace BladeRunner diff --git a/engines/bladerunner/item.cpp b/engines/bladerunner/item.cpp index 7fca4d108c..bf09efb0e6 100644 --- a/engines/bladerunner/item.cpp +++ b/engines/bladerunner/item.cpp @@ -24,6 +24,7 @@ #include "bladerunner/bladerunner.h" +#include "bladerunner/savefile.h" #include "bladerunner/slice_renderer.h" #include "bladerunner/zbuffer.h" @@ -173,4 +174,26 @@ bool Item::isUnderMouse(int mouseX, int mouseY) const { && mouseY <= _screenRectangle.bottom + 10; } +void Item::save(SaveFile &f) { + f.write(_setId); + f.write(_itemId); + _boundingBox.save(f); + f.write(_screenRectangle); + f.write(_animationId); + f.write(_position); + f.write(_facing); + f.write(_angle); + f.write(_width); + f.write(_height); + f.write(_screenX); + f.write(_screenY); + f.write(_depth); + f.write(_isTarget); + f.write(_isSpinning); + f.write(_facingChange); + f.write(0.0f); // _viewAngle + f.write(_isVisible); + f.write(_isPoliceMazeEnemy); +} + } // End of namespace BladeRunner diff --git a/engines/bladerunner/item.h b/engines/bladerunner/item.h index 3beca15dd9..bf07a118bd 100644 --- a/engines/bladerunner/item.h +++ b/engines/bladerunner/item.h @@ -32,6 +32,7 @@ namespace BladeRunner { class BladeRunnerEngine; class Items; +class SaveFile; class Item { friend class Items; @@ -84,6 +85,8 @@ public: void setup(int itemId, int setId, int animationId, Vector3 position, int facing, int height, int width, bool isTargetFlag, bool isVisible, bool isPoliceMazeEnemy); bool isUnderMouse(int mouseX, int mouseY) const; + + void save(SaveFile &f); }; } diff --git a/engines/bladerunner/items.cpp b/engines/bladerunner/items.cpp index 0348efc4fe..7fe769cb93 100644 --- a/engines/bladerunner/items.cpp +++ b/engines/bladerunner/items.cpp @@ -23,6 +23,7 @@ #include "bladerunner/items.h" #include "bladerunner/game_constants.h" +#include "bladerunner/savefile.h" #include "bladerunner/scene.h" #include "bladerunner/scene_objects.h" #include "bladerunner/zbuffer.h" @@ -242,4 +243,19 @@ int Items::findItem(int itemId) const { return -1; } +void Items::save(SaveFile &f) { + int size = (int)_items.size(); + + f.write(size); + int i; + for (i = 0; i != size; ++i) { + _items[i]->save(f); + } + + // Always write out 100 items + for (; i != 100; ++i) { + f.padBytes(0x174); // bbox + rect + 18 float fields + } +} + } // End of namespace BladeRunner diff --git a/engines/bladerunner/items.h b/engines/bladerunner/items.h index 6bbc99c59b..cc9af734b2 100644 --- a/engines/bladerunner/items.h +++ b/engines/bladerunner/items.h @@ -30,6 +30,8 @@ namespace BladeRunner { +class SaveFile; + class Items { BladeRunnerEngine *_vm; @@ -64,6 +66,7 @@ public: void spinInWorld(int itemId); + void save(SaveFile &f); private: int findItem(int itemId) const; }; diff --git a/engines/bladerunner/module.mk b/engines/bladerunner/module.mk index bf90922ebf..f4bf926aa0 100644 --- a/engines/bladerunner/module.mk +++ b/engines/bladerunner/module.mk @@ -40,7 +40,10 @@ MODULE_OBJS = \ obstacles.o \ outtake.o \ overlays.o \ + police_maze.o \ + police_maze_track.o \ regions.o \ + savefile.o \ scene.o \ scene_objects.o \ screen_effects.o \ diff --git a/engines/bladerunner/movement_track.cpp b/engines/bladerunner/movement_track.cpp index 47eb56a098..5a6407ed3a 100644 --- a/engines/bladerunner/movement_track.cpp +++ b/engines/bladerunner/movement_track.cpp @@ -22,6 +22,8 @@ #include "bladerunner/movement_track.h" +#include "bladerunner/savefile.h" + namespace BladeRunner { MovementTrack::MovementTrack() { @@ -107,4 +109,18 @@ bool MovementTrack::next(int *waypointId, int *delay, int *angle, bool *run) { } } +void MovementTrack::save(SaveFile &f) { + f.write(_currentIndex); + f.write(_lastIndex); + f.write(_hasNext); + f.write(_paused); + for (int i = 0; i < 100; ++i) { + Entry &e = _entries[i]; + f.write(e.waypointId); + f.write(e.delay); + f.write(e.angle); + f.write(e.run); + } +} + } // End of namespace BladeRunner diff --git a/engines/bladerunner/movement_track.h b/engines/bladerunner/movement_track.h index cba9b690ff..2d59fd98c7 100644 --- a/engines/bladerunner/movement_track.h +++ b/engines/bladerunner/movement_track.h @@ -29,6 +29,7 @@ namespace BladeRunner { class BladeRunnerEngine; class BoundingBox; +class SaveFile; class MovementTrack { static const int kSize = 100; @@ -59,8 +60,7 @@ public: bool hasNext() const; bool next(int *waypointId, int *delay, int *angle, bool *run); - //int saveGame(); - + void save(SaveFile &f); private: void reset(); }; diff --git a/engines/bladerunner/obstacles.cpp b/engines/bladerunner/obstacles.cpp index 8061e782f2..603d514513 100644 --- a/engines/bladerunner/obstacles.cpp +++ b/engines/bladerunner/obstacles.cpp @@ -24,11 +24,15 @@ #include "bladerunner/bladerunner.h" +#include "bladerunner/savefile.h" + namespace BladeRunner { Obstacles::Obstacles(BladeRunnerEngine *vm) { _vm = vm; - _vertices = new Vector2[150]; + _polygons = new Polygon[kPolygonCount]; + _polygonsBackup = new Polygon[kPolygonCount]; + _vertices = new Vector2[kVertexCount]; clear(); } @@ -40,7 +44,7 @@ void Obstacles::clear() { for (int i = 0; i < kPolygonCount; i++) { _polygons[i].isPresent = false; _polygons[i].verticeCount = 0; - for (int j = 0; j < kVertexCount; j++) { + for (int j = 0; j < kPolygonVertexCount; j++) { _polygons[i].vertices[j].x = 0.0f; _polygons[i].vertices[j].y = 0.0f; } @@ -64,5 +68,29 @@ void Obstacles::backup() { void Obstacles::restore() {} +void Obstacles::save(SaveFile &f) { + f.write(_backup); + f.write(_count); + for (int i = 0; i < _count; ++i) { + Polygon &p = _polygonsBackup[i]; + f.write(p.isPresent); + f.write(p.verticeCount); + f.write(p.left); + f.write(p.bottom); + f.write(p.right); + f.write(p.top); + for (int j = 0; j < kPolygonVertexCount; ++j) { + f.write(p.vertices[j]); + } + for (int j = 0; j < kPolygonVertexCount; ++j) { + f.write(p.vertexType[j]); + } + } + for (int i = 0; i < kVertexCount; ++i) { + f.write(_vertices[i]); + } + f.write(_verticeCount); +} + } // End of namespace BladeRunner diff --git a/engines/bladerunner/obstacles.h b/engines/bladerunner/obstacles.h index c2c84c3bfa..fc06fe6920 100644 --- a/engines/bladerunner/obstacles.h +++ b/engines/bladerunner/obstacles.h @@ -28,10 +28,12 @@ namespace BladeRunner { class BladeRunnerEngine; +class SaveFile; class Obstacles { - static const int kPolygonCount = 50; - static const int kVertexCount = 160; + static const int kVertexCount = 150; + static const int kPolygonCount = 50; + static const int kPolygonVertexCount = 160; struct Polygon { bool isPresent; @@ -40,14 +42,14 @@ class Obstacles { float bottom; float right; float top; - Vector2 vertices[kVertexCount]; - int vertexType[kVertexCount]; + Vector2 vertices[kPolygonVertexCount]; + int vertexType[kPolygonVertexCount]; }; BladeRunnerEngine *_vm; - Polygon _polygons[kPolygonCount]; - Polygon _polygonsBackup[kPolygonCount]; + Polygon *_polygons; + Polygon *_polygonsBackup; Vector2 *_vertices; int _verticeCount; int _count; @@ -62,6 +64,7 @@ public: bool find(const Vector3 &from, const Vector3 &to, Vector3 *next) const; void backup(); void restore(); + void save(SaveFile &f); }; } // End of namespace BladeRunner diff --git a/engines/bladerunner/overlays.cpp b/engines/bladerunner/overlays.cpp index b5cb130678..0f011ad4d1 100644 --- a/engines/bladerunner/overlays.cpp +++ b/engines/bladerunner/overlays.cpp @@ -25,6 +25,7 @@ #include "bladerunner/bladerunner.h" #include "bladerunner/archive.h" +#include "bladerunner/savefile.h" #include "bladerunner/vqa_player.h" #include "graphics/surface.h" @@ -56,6 +57,8 @@ Overlays::~Overlays() { } int Overlays::play(const Common::String &name, int loopId, bool loopForever, bool startNow, int a6) { + assert(name.size() <= 12); + int id = mix_id(name); int index = findById(id); if (index < 0) { @@ -63,12 +66,13 @@ int Overlays::play(const Common::String &name, int loopId, bool loopForever, boo if (index < 0) { return index; } + _videos[index].loaded = true; + _videos[index].name = name; _videos[index].id = id; _videos[index].vqaPlayer = new VQAPlayer(_vm, &_vm->_surfaceFront); // repeat forever _videos[index].vqaPlayer->setBeginAndEndFrame(0, 0, -1, kLoopSetModeJustStart, nullptr, nullptr); - _videos[index].loaded = true; } Common::String resourceName = Common::String::format("%s.VQA", name.c_str()); @@ -136,10 +140,26 @@ void Overlays::resetSingle(int i) { _videos[i].loaded = false; _videos[i].id = 0; _videos[i].field2 = -1; + _videos[i].name.clear(); } void Overlays::reset() { _videos.clear(); } +void Overlays::save(SaveFile &f) { + for (int i = 0; i < kOverlayVideos; ++i) { + // 37 bytes per overlay + Video &ov = _videos[i]; + + f.write(ov.loaded); + f.write(nullptr); + f.write(ov.name, 13); + f.write(ov.id); + f.write(ov.field0); + f.write(ov.field1); + f.write(ov.field2); + } +} + } // End of namespace BladeRunner diff --git a/engines/bladerunner/overlays.h b/engines/bladerunner/overlays.h index 38edf7459b..fc8dfa11d4 100644 --- a/engines/bladerunner/overlays.h +++ b/engines/bladerunner/overlays.h @@ -33,20 +33,20 @@ struct Surface; namespace BladeRunner { class BladeRunnerEngine; +class SaveFile; class VQAPlayer; - class Overlays { static const int kOverlayVideos = 5; struct Video { - bool loaded; - VQAPlayer *vqaPlayer; - // char name[13]; - int32 id; - int field0; - int field1; - int field2; + bool loaded; + VQAPlayer *vqaPlayer; + Common::String name; + int32 id; + int field0; + int field1; + int field2; }; BladeRunnerEngine *_vm; @@ -62,6 +62,8 @@ public: void removeAll(); void tick(); + void save(SaveFile &f); + private: int findById(int32 id) const; int findEmpty() const; diff --git a/engines/bladerunner/police_maze.cpp b/engines/bladerunner/police_maze.cpp new file mode 100644 index 0000000000..223171d0be --- /dev/null +++ b/engines/bladerunner/police_maze.cpp @@ -0,0 +1,64 @@ +/* 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 "bladerunner/police_maze.h" + +#include "bladerunner/bladerunner.h" + +#include "bladerunner/police_maze_track.h" +#include "bladerunner/savefile.h" + +namespace BladeRunner { + +PoliceMaze::PoliceMaze(BladeRunnerEngine *vm) : _vm(vm) { + reset(); +} + +PoliceMaze::~PoliceMaze() { + reset(); +} + +bool PoliceMaze::init() { + return true; +} + +void PoliceMaze::save(SaveFile &f) { + f.write(_tracksCount); + f.write(_a2); + f.write(_a3); + for (int i = 0; i < 64; ++i) { + _tracks[i]->save(f); + } +} + +void PoliceMaze::reset() { + _tracksCount = 0; + _a2 = 0; + _a3 = 0; + for (int i = 0; i < 64; ++i) { + _tracks[i] = nullptr; + } + _a4 = 0; + _a5 = 0; +} + +} // End of namespace BladeRunner diff --git a/engines/bladerunner/police_maze.h b/engines/bladerunner/police_maze.h new file mode 100644 index 0000000000..4bd06bb868 --- /dev/null +++ b/engines/bladerunner/police_maze.h @@ -0,0 +1,54 @@ +/* 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 BLADERUNNER_POLICE_MAZE_H +#define BLADERUNNER_POLICE_MAZE_H + +namespace BladeRunner { + +class BladeRunnerEngine; +class PoliceMazeTrack; +class SaveFile; + +class PoliceMaze { + BladeRunnerEngine *_vm; + + PoliceMazeTrack *_tracks[64]; + int _tracksCount; + int _a2; + int _a3; + int _a4; + int _a5; + +public: + PoliceMaze(BladeRunnerEngine *vm); + ~PoliceMaze(); + + bool init(); + + void save(SaveFile &f); + void reset(); +}; + +} // End of namespace BladeRunner + +#endif diff --git a/engines/bladerunner/police_maze_track.cpp b/engines/bladerunner/police_maze_track.cpp new file mode 100644 index 0000000000..988f90499c --- /dev/null +++ b/engines/bladerunner/police_maze_track.cpp @@ -0,0 +1,80 @@ +/* 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 "bladerunner/police_maze_track.h" + +#include "bladerunner/bladerunner.h" + +#include "bladerunner/savefile.h" + +namespace BladeRunner { + +PoliceMazeTrack::PoliceMazeTrack(BladeRunnerEngine *vm) : _vm(vm) { + reset(); +} + +PoliceMazeTrack::~PoliceMazeTrack() { + reset(); +} + +void PoliceMazeTrack::save(SaveFile &f) { + f.write(_isPresent); + f.write(_itemId); + f.write(_count); + f.write(_dataIndex); + f.write(_a6); + f.write(_a7); + f.write(_pointIndex); + f.write(_a9); + f.write(_rotating); + f.write(_maxAngle); + f.write(_angleChange); + f.write(_a13); + + for (int i = 0; i < 100; ++i) { + f.write(_points[i]); + } + + f.write(_a4); + f.write(_a5); + } + +void PoliceMazeTrack::reset() { + _isPresent = false; + _itemId = -1; + _count = 0; + _data = 0; + _dataIndex = 0; + _a4 = 0; + _a5 = 0; + _time = 0; + _a6 = 0; + _a7 = 0; + _pointIndex = 0; + _a9 = 0; + _rotating = 0; + _maxAngle = 0; + _angleChange = 0; + _a13 = 1; +} + +} // End of namespace BladeRunner diff --git a/engines/bladerunner/police_maze_track.h b/engines/bladerunner/police_maze_track.h new file mode 100644 index 0000000000..9de7a1b624 --- /dev/null +++ b/engines/bladerunner/police_maze_track.h @@ -0,0 +1,65 @@ +/* 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 BLADERUNNER_POLICE_MAZE_TRACK_H +#define BLADERUNNER_POLICE_MAZE_TRACK_H + +#include "bladerunner/vector.h" + +namespace BladeRunner { + +class BladeRunnerEngine; +class SaveFile; + +class PoliceMazeTrack { + BladeRunnerEngine *_vm; + + int _time; + bool _isPresent; + int _itemId; + int _count; + Vector2 _points[100]; + int _data; + int _dataIndex; + int _a4; + int _a5; + int _a6; + int _a7; + int _pointIndex; + int _a9; + int _rotating; + int _maxAngle; + int _angleChange; + int _a13; + +public: + PoliceMazeTrack(BladeRunnerEngine *vm); + ~PoliceMazeTrack(); + + void save(SaveFile &f); + + void reset(); +}; + +} // End of namespace BladeRunner + +#endif diff --git a/engines/bladerunner/regions.cpp b/engines/bladerunner/regions.cpp index 80dabf2989..51b2bae2d7 100644 --- a/engines/bladerunner/regions.cpp +++ b/engines/bladerunner/regions.cpp @@ -22,6 +22,8 @@ #include "bladerunner/regions.h" +#include "bladerunner/savefile.h" + namespace BladeRunner { Regions::Regions() { @@ -99,4 +101,13 @@ void Regions::enable() { _enabled = true; } +void Regions::save(SaveFile &f) { + f.write(_enabled); + for (int i = 0; i != 10; ++i) { + f.write(_regions[i].rectangle); + f.write(_regions[i].type); + f.write(_regions[i].present); + } +} + } // End of namespace BladeRunner diff --git a/engines/bladerunner/regions.h b/engines/bladerunner/regions.h index 9868f46ac0..ed4dcba1dc 100644 --- a/engines/bladerunner/regions.h +++ b/engines/bladerunner/regions.h @@ -30,6 +30,8 @@ namespace BladeRunner { +class SaveFile; + class Regions { friend class Debugger; @@ -54,6 +56,8 @@ public: void setEnabled(bool enabled); void enable(); + + void save(SaveFile &f); }; } // End of namespace BladeRunner diff --git a/engines/bladerunner/savefile.cpp b/engines/bladerunner/savefile.cpp new file mode 100644 index 0000000000..ff1ff75165 --- /dev/null +++ b/engines/bladerunner/savefile.cpp @@ -0,0 +1,120 @@ +/* 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 "bladerunner/savefile.h" + +#include "bladerunner/boundingbox.h" +#include "bladerunner/vector.h" + +#include "common/rect.h" +#include "common/savefile.h" + +namespace BladeRunner { + +SaveFile::SaveFile(Common::OutSaveFile *saveFile) + : _saveFile(saveFile), + _stream(DisposeAfterUse::YES) +{ +} + +void SaveFile::finalize() { + _saveFile->writeUint32LE(_stream.size() + 4); + _saveFile->write(_stream.getData(), _stream.size()); + _saveFile->finalize(); +} + +void SaveFile::padBytes(int count) { + for (int i = 0; i < count; ++i) { + _stream.writeByte(0); + } +} + +void SaveFile::write(bool v) { + _stream.writeUint32LE(v); +} + +void SaveFile::write(int v) { + _stream.writeUint32LE(v); +} + +void SaveFile::write(uint32 v) { + _stream.writeUint32LE(v); +} + +void SaveFile::write(byte v) { + _stream.writeByte(v); +} + +void SaveFile::write(float v) { + _stream.writeFloatLE(v); +} + +void SaveFile::debug(char *p) { + _stream.write(p, strlen(p) + 1); +} + +void SaveFile::write(char *p, int sz) { + _stream.write(p, sz); +} + +void SaveFile::write(Common::String &s, int sz) { + assert(s.size() < (uint)sz); + _stream.write(s.begin(), s.size()); + padBytes((uint)sz - s.size()); +} + +void SaveFile::write(const Vector2 &v) { + _stream.writeFloatLE(v.x); + _stream.writeFloatLE(v.y); +} + +void SaveFile::write(const Vector3 &v) { + _stream.writeFloatLE(v.x); + _stream.writeFloatLE(v.y); + _stream.writeFloatLE(v.z); +} + +void SaveFile::write(const Common::Rect &v) { + _stream.writeUint32LE(v.left); + _stream.writeUint32LE(v.top); + _stream.writeUint32LE(v.right); + _stream.writeUint32LE(v.bottom); +} + +void SaveFile::write(const BoundingBox &v) { + float x0, y0, z0, x1, y1, z1; + + v.getXYZ(&x0, &y0, &z0, &x1, &y1, &z1); + _stream.writeFloatLE(x0); + _stream.writeFloatLE(y0); + _stream.writeFloatLE(z0); + _stream.writeFloatLE(x1); + _stream.writeFloatLE(y1); + _stream.writeFloatLE(z1); + + // Bounding boxes have a lot of extra data that's never actually used + for (int i = 0; i != 96; ++i) { + _stream.writeFloatLE(0.0f); + } +} + +} // End of namespace BladeRunner diff --git a/engines/bladerunner/savefile.h b/engines/bladerunner/savefile.h new file mode 100644 index 0000000000..8c5dc0aa80 --- /dev/null +++ b/engines/bladerunner/savefile.h @@ -0,0 +1,67 @@ +/* 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 BLADERUNNER_SAVEFILE_H +#define BLADERUNNER_SAVEFILE_H + +#include "common/memstream.h" +#include "common/types.h" + +namespace Common { + class OutSaveFile; + class String; + struct Rect; +} + +namespace BladeRunner { + +class Vector2; +class Vector3; +class BoundingBox; + +class SaveFile { + Common::OutSaveFile *_saveFile; + Common::MemoryWriteStreamDynamic _stream; +public: + SaveFile(Common::OutSaveFile *saveFile); + + // bool err(); + void finalize(); + + void padBytes(int count); + void write(bool v); + void write(int v); + void write(uint32 v); + void write(byte v); + void write(float v); + void debug(char *p); + void write(char *p, int sz); + void write(Common::String &s, int sz); + void write(const Vector2 &v); + void write(const Vector3 &v); + void write(const Common::Rect &v); + void write(const BoundingBox &v); +}; + +} // End of namespace BladeRunner + +#endif diff --git a/engines/bladerunner/scene.cpp b/engines/bladerunner/scene.cpp index 84d0dd4bd6..d12c85e56b 100644 --- a/engines/bladerunner/scene.cpp +++ b/engines/bladerunner/scene.cpp @@ -30,6 +30,7 @@ #include "bladerunner/items.h" #include "bladerunner/overlays.h" #include "bladerunner/regions.h" +#include "bladerunner/savefile.h" #include "bladerunner/scene_objects.h" #include "bladerunner/screen_effects.h" #include "bladerunner/set.h" @@ -412,4 +413,21 @@ void Scene::loopEnded(int frame, int loopId) { void Scene::loopEndedStatic(void *data, int frame, int loopId) { ((Scene *)data)->loopEnded(frame, loopId); } + +void Scene::save(SaveFile &f) { + f.write(_setId); + f.write(_sceneId); + f.write(_defaultLoop); + f.write(_defaultLoopSet); + f.write(_defaultLoopPreloadedSet); + f.write(_specialLoopMode); + f.write(_specialLoop); + f.write(_nextSetId); + f.write(_nextSceneId); + f.write(_frame); + f.write(_actorStartPosition); + f.write(_actorStartFacing); + f.write(_playerWalkedIn); +} + } // End of namespace BladeRunner diff --git a/engines/bladerunner/scene.h b/engines/bladerunner/scene.h index 91cd2ed604..b1963e8c15 100644 --- a/engines/bladerunner/scene.h +++ b/engines/bladerunner/scene.h @@ -30,6 +30,7 @@ namespace BladeRunner { class BladeRunnerEngine; class BoundingBox; class Regions; +class SaveFile; class Set; class VQAPlayer; @@ -89,6 +90,8 @@ public: void objectSetIsTarget(int objectId, bool isTarget, bool sceneLoaded); const char *objectGetName(int objectId); + void save(SaveFile &f); + private: void loopEnded(int frame, int loopId); static void loopEndedStatic(void *data, int frame, int loopId); diff --git a/engines/bladerunner/scene_objects.cpp b/engines/bladerunner/scene_objects.cpp index 148cde827c..f68dccc0dd 100644 --- a/engines/bladerunner/scene_objects.cpp +++ b/engines/bladerunner/scene_objects.cpp @@ -25,6 +25,7 @@ #include "bladerunner/bladerunner.h" #include "bladerunner/obstacles.h" +#include "bladerunner/savefile.h" #include "bladerunner/view.h" namespace BladeRunner { @@ -327,4 +328,25 @@ void SceneObjects::updateObstacles() { _vm->_obstacles->backup(); } +void SceneObjects::save(SaveFile &f) { + f.write(_count); + for (int i = 0; i < kSceneObjectCount; ++i) { + f.write(_sceneObjects[i].id); + f.write(_sceneObjects[i].type); + f.write(_sceneObjects[i].boundingBox); + f.write(_sceneObjects[i].screenRectangle); + f.write(_sceneObjects[i].distanceToCamera); + f.write(_sceneObjects[i].isPresent); + f.write(_sceneObjects[i].isClickable); + f.write(_sceneObjects[i].isObstacle); + f.write(_sceneObjects[i].unknown1); + f.write(_sceneObjects[i].isTarget); + f.write(_sceneObjects[i].isMoving); + f.write(_sceneObjects[i].isRetired); + } + for (int i = 0; i < kSceneObjectCount; ++i) { + f.write(_sceneObjectsSortedByDistance[i]); + } +} + } // End of namespace BladeRunner diff --git a/engines/bladerunner/scene_objects.h b/engines/bladerunner/scene_objects.h index de31eae88d..2f154db754 100644 --- a/engines/bladerunner/scene_objects.h +++ b/engines/bladerunner/scene_objects.h @@ -30,6 +30,7 @@ namespace BladeRunner { class BladeRunnerEngine; +class SaveFile; class View; enum SceneObjectType { @@ -86,7 +87,7 @@ public: void setIsTarget(int sceneObjectId, bool isTarget); void updateObstacles(); - + void save(SaveFile &f); private: int findById(int sceneObjectId) const; bool addSceneObject(int sceneObjectId, SceneObjectType sceneObjectType, BoundingBox *boundingBox, Common::Rect *screenRectangle, bool isClickable, bool isObstacle, uint8 unknown1, bool isTarget, bool isMoving, bool isRetired); diff --git a/engines/bladerunner/script/ai_script.cpp b/engines/bladerunner/script/ai_script.cpp index c960ff180f..257e323c5b 100644 --- a/engines/bladerunner/script/ai_script.cpp +++ b/engines/bladerunner/script/ai_script.cpp @@ -345,4 +345,31 @@ void AIScripts::fledCombat(int actor) { _inScriptCounter--; } +void AIScripts::setAnimationState(int actor, int animationState, int animationFrame, int animationStateNext, int animationNext) { + if (actor >= _actorCount) { + return; + } + + _inScriptCounter++; + if (_AIScripts[actor]) { + _AIScripts[actor]->SetAnimationState(animationState, animationFrame, animationStateNext, animationNext); + } + _inScriptCounter--; +} + + +void AIScripts::queryAnimationState(int actor, int *animationState, int *animationFrame, int *animationStateNext, int *nextAnimation) { + if (actor >= _actorCount) { + return; + } + + _inScriptCounter++; + if (_AIScripts[actor]) { + _AIScripts[actor]->FledCombat(); + _AIScripts[actor]->QueryAnimationState(animationState, animationFrame, animationStateNext, nextAnimation); + } + _inScriptCounter--; +} + + } // End of namespace BladeRunner diff --git a/engines/bladerunner/script/ai_script.h b/engines/bladerunner/script/ai_script.h index cfd3fe5e1a..5e782d0820 100644 --- a/engines/bladerunner/script/ai_script.h +++ b/engines/bladerunner/script/ai_script.h @@ -566,6 +566,8 @@ public: bool reachedMovementTrackWaypoint(int actor, int waypointId); void updateAnimation(int actor, int *animation, int *frame); void changeAnimationMode(int actor, int mode); + void queryAnimationState(int actor, int *animationState, int *animationFrame, int *animationStateNext, int *nextAnimation); + void setAnimationState(int actor, int animationState, int animationFrame, int animationStateNext, int animationNext); void fledCombat(int actor); bool isInsideScript() const { return _inScriptCounter > 0; } diff --git a/engines/bladerunner/set.cpp b/engines/bladerunner/set.cpp index fe10c189b6..6a83294c4c 100644 --- a/engines/bladerunner/set.cpp +++ b/engines/bladerunner/set.cpp @@ -25,6 +25,7 @@ #include "bladerunner/bladerunner.h" #include "bladerunner/game_constants.h" #include "bladerunner/lights.h" +#include "bladerunner/savefile.h" #include "bladerunner/scene_objects.h" #include "bladerunner/set_effects.h" #include "bladerunner/slice_renderer.h" @@ -82,6 +83,7 @@ bool Set::open(const Common::String &name) { _objects[i].isObstacle = s->readByte(); _objects[i].isClickable = s->readByte(); _objects[i].isHotMouse = 0; + _objects[i].unknown1 = 0; _objects[i].isTarget = 0; s->skip(4); @@ -327,4 +329,40 @@ int Set::getWalkboxSoundRunLeft(int walkboxId) const { int Set::getWalkboxSoundRunRight(int walkboxId) const { return getWalkboxSoundWalkRight(walkboxId); } + +void Set::save(SaveFile &f) { + f.write(_loaded); + f.write(_objectCount); + f.write(_walkboxCount); + + for (int i = 0; i != _objectCount; ++i) { + f.write(_objects[i].name, 20); + f.write(_objects[i].bbox); + f.write(_objects[i].isObstacle); + f.write(_objects[i].isClickable); + f.write(_objects[i].isHotMouse); + f.write(_objects[i].unknown1); + f.write(_objects[i].isTarget); + } + + for (int i = 0; i != _walkboxCount; ++i) { + f.write(_walkboxes[i].name, 20); + f.write(_walkboxes[i].altitude); + f.write(_walkboxes[i].vertexCount); + for (int j = 0; j != 8; ++j) { + f.write(_walkboxes[i].vertices[j]); + + // In BLADE.EXE vertices are a vec5 + f.write(0); + f.write(0); + } + } + + for (int i = 0; i != 85; ++i) { + f.write(_walkboxStepSound[i]); + } + + f.write(_footstepSoundOverride); +} + } // End of namespace BladeRunner diff --git a/engines/bladerunner/set.h b/engines/bladerunner/set.h index a6e7e9f3df..7989ef1e1a 100644 --- a/engines/bladerunner/set.h +++ b/engines/bladerunner/set.h @@ -33,6 +33,7 @@ namespace BladeRunner { class BladeRunnerEngine; class VQADecoder; +class SaveFile; class SetEffects; class SceneObjects; @@ -94,11 +95,14 @@ public: void setWalkboxStepSound(int walkboxId, int soundId); void setFoodstepSoundOverride(int soundId); void resetFoodstepSoundOverride(); + int getWalkboxSoundWalkLeft(int walkboxId) const; int getWalkboxSoundWalkRight(int walkboxId) const; int getWalkboxSoundRunLeft(int walkboxId) const; int getWalkboxSoundRunRight(int walkboxId) const; + void save(SaveFile &f); + private: static bool isXZInWalkbox(float x, float z, const Walkbox &walkbox); }; diff --git a/engines/bladerunner/settings.cpp b/engines/bladerunner/settings.cpp index a5540fcb04..e4db0b81ea 100644 --- a/engines/bladerunner/settings.cpp +++ b/engines/bladerunner/settings.cpp @@ -26,6 +26,7 @@ #include "bladerunner/bladerunner.h" #include "bladerunner/chapters.h" #include "bladerunner/music.h" +#include "bladerunner/savefile.h" #include "bladerunner/scene.h" #include "common/debug.h" @@ -39,14 +40,23 @@ Settings::Settings(BladeRunnerEngine *vm) { _playerAgenda = 1; _chapter = 1; + _scene = -1; + _set = -1; + _unk0 = 0; _gamma = 1.0f; + _ammoType = 0; + _ammoAmounts[0] = 1; + _ammoAmounts[1] = 0; + _ammoAmounts[2] = 0; + + // The remaining fields are not reset in BLADE.EXE _chapterChanged = false; _newChapter = -1; _newScene = -1; _newSet = -1; - _startingGame = true; + _startingGame = false; _loadingGame = false; _fullHDFrames = true; @@ -83,8 +93,9 @@ bool Settings::openNewScene() { _vm->_scene->close(!_loadingGame && !_startingGame); } if (_chapterChanged) { - if (_vm->_chapters->hasOpenResources()) + if (_vm->_chapters->hasOpenResources()) { _vm->_chapters->closeResources(); + } int newChapter = _newChapter; _chapterChanged = false; @@ -103,6 +114,9 @@ bool Settings::openNewScene() { return false; } + _set = newSet; + _scene = newScene; + if (!_loadingGame && currentSet != newSet) { // TODO: Reset actors for new set } @@ -171,4 +185,17 @@ void Settings::setLearyMode(bool learyMode) { _learyMode = learyMode; } +void Settings::save(SaveFile &f) { + f.write(_scene); + f.write(_set); + f.write(_chapter); + f.write(_playerAgenda); + f.write(_unk0); + f.write(_difficulty); + f.write(_ammoType); + for (int i = 0; i != 3; ++i) { + f.write(_ammoAmounts[i]); + } +} + } // End of namespace BladeRunner diff --git a/engines/bladerunner/settings.h b/engines/bladerunner/settings.h index bf2d2d3162..bc1c25553c 100644 --- a/engines/bladerunner/settings.h +++ b/engines/bladerunner/settings.h @@ -26,6 +26,7 @@ namespace BladeRunner { class BladeRunnerEngine; +class SaveFile; enum PlayerAgenda { kPlayerAgendaPolite = 0, @@ -39,6 +40,9 @@ class Settings { BladeRunnerEngine *_vm; int _chapter; + int _scene; + int _set; + int _unk0; float _gamma; bool _chapterChanged; @@ -49,6 +53,8 @@ class Settings { bool _startingGame; bool _loadingGame; + int _unk1; + int _fullHDFrames; int _mst3k; @@ -117,6 +123,8 @@ public: bool getLearyMode() const; void setLearyMode(bool learyMode); + + void save(SaveFile &f); }; } // End of namespace BladeRunner diff --git a/engines/bladerunner/ui/spinner.cpp b/engines/bladerunner/ui/spinner.cpp index 0740715fc4..1f8f197926 100644 --- a/engines/bladerunner/ui/spinner.cpp +++ b/engines/bladerunner/ui/spinner.cpp @@ -25,6 +25,7 @@ #include "bladerunner/bladerunner.h" #include "bladerunner/game_constants.h" #include "bladerunner/mouse.h" +#include "bladerunner/savefile.h" #include "bladerunner/scene.h" #include "bladerunner/shape.h" #include "bladerunner/text_resource.h" @@ -262,6 +263,14 @@ void Spinner::resume() { _vqaPlayer->setLoop(1, -1, kLoopSetModeJustStart, nullptr, nullptr); } +void Spinner::save(SaveFile &f) { + assert(!_isOpen); + + for (int i = 0; i != kSpinnerDestinations; ++i) { + f.write(_isDestinationSelectable[i]); + } +} + const Spinner::Destination *Spinner::getDestinationsFar() { static const Destination destinations[] = { { 0, Common::Rect(220, 227, 246, 262) }, diff --git a/engines/bladerunner/ui/spinner.h b/engines/bladerunner/ui/spinner.h index b1785a57eb..24f66ed4db 100644 --- a/engines/bladerunner/ui/spinner.h +++ b/engines/bladerunner/ui/spinner.h @@ -29,9 +29,10 @@ namespace BladeRunner { class BladeRunnerEngine; +class SaveFile; class Shape; -class VQAPlayer; class UIImagePicker; +class VQAPlayer; class Spinner { static const int kSpinnerDestinations = 10; @@ -70,6 +71,8 @@ public: void reset(); void resume(); + void save(SaveFile &f); + private: static void mouseUpCallback(int, void *); static const Destination *getDestinationsFar(); diff --git a/engines/bladerunner/waypoints.cpp b/engines/bladerunner/waypoints.cpp index 4d80841e50..0783af8e07 100644 --- a/engines/bladerunner/waypoints.cpp +++ b/engines/bladerunner/waypoints.cpp @@ -22,6 +22,8 @@ #include "bladerunner/waypoints.h" +#include "bladerunner/savefile.h" + namespace BladeRunner { Waypoints::Waypoints(BladeRunnerEngine *vm, int count) { @@ -89,4 +91,14 @@ float Waypoints::getZ(int waypointId) const { return _waypoints[waypointId].position.z; } +void Waypoints::save(SaveFile &f) { + f.write(_count); + for (int i = 0; i < _count; ++i) { + Waypoint &w = _waypoints[i]; + f.write(w.setId); + f.write(w.position); + f.write(w.present); + } +} + } // End of namespace BladeRunner diff --git a/engines/bladerunner/waypoints.h b/engines/bladerunner/waypoints.h index 826f8f5a94..9159301cfe 100644 --- a/engines/bladerunner/waypoints.h +++ b/engines/bladerunner/waypoints.h @@ -30,6 +30,8 @@ namespace BladeRunner { +class SaveFile; + class Waypoints { friend class Debugger; @@ -55,6 +57,8 @@ public: bool set(int waypointId, int setId, Vector3 position); bool reset(int waypointId); + + void save(SaveFile &f); }; } // End of namespace BladeRunner |