diff options
Diffstat (limited to 'engines')
83 files changed, 1544 insertions, 1043 deletions
diff --git a/engines/bladerunner/actor.cpp b/engines/bladerunner/actor.cpp index aae1085834..998791d88a 100644 --- a/engines/bladerunner/actor.cpp +++ b/engines/bladerunner/actor.cpp @@ -52,7 +52,6 @@ Actor::Actor(BladeRunnerEngine *vm, int actorId) { _walkInfo = new ActorWalk(vm); _movementTrack = new MovementTrack(); _clues = new ActorClues(vm, (actorId && actorId != 99) ? 2 : 4); - _bbox = new BoundingBox(); _combatInfo = new ActorCombat(vm); _friendlinessToOther.resize(_vm->_gameInfo->getActorCount()); @@ -65,7 +64,6 @@ Actor::Actor(BladeRunnerEngine *vm, int actorId) { Actor::~Actor() { delete _combatInfo; - delete _bbox; delete _clues; delete _movementTrack; delete _walkInfo; @@ -355,7 +353,7 @@ void Actor::setAtXYZ(const Vector3 &position, int facing, bool snapFacing, bool _vm->_sceneObjects->remove(_id + kSceneObjectOffsetActors); if (_vm->_scene->getSetId() == _setId) { - _vm->_sceneObjects->addActor(_id + kSceneObjectOffsetActors, _bbox, &_screenRectangle, true, moving, _isTarget, retired); + _vm->_sceneObjects->addActor(_id + kSceneObjectOffsetActors, _bbox, _screenRectangle, true, moving, _isTarget, retired); } } @@ -469,7 +467,7 @@ bool Actor::loopWalkToItem(int itemId, int destinationOffset, int interruptible, return loopWalk(itemPosition, destinationOffset, interruptible, runFlag, _position, width, 24.0f, a5, isRunningFlag, false); } -bool Actor::loopWalkToSceneObject(const char *objectName, int destinationOffset, bool interruptible, bool runFlag, bool a5, bool *isRunningFlag) { +bool Actor::loopWalkToSceneObject(const Common::String &objectName, int destinationOffset, bool interruptible, bool runFlag, bool a5, bool *isRunningFlag) { int sceneObject = _vm->_scene->_set->findObject(objectName); if (sceneObject < 0) { return true; @@ -760,21 +758,21 @@ void Actor::setFacing(int facing, bool halfOrSet) { void Actor::setBoundingBox(const Vector3 &position, bool retired) { if (retired) { - _bbox->setXYZ(position.x - (_retiredWidth / 2.0f), - position.y, - position.z - (_retiredWidth / 2.0f), + _bbox.setXYZ(position.x - (_retiredWidth / 2.0f), + position.y, + position.z - (_retiredWidth / 2.0f), - position.x + (_retiredWidth / 2.0f), - position.y + _retiredHeight, - position.z + (_retiredWidth / 2.0f)); + position.x + (_retiredWidth / 2.0f), + position.y + _retiredHeight, + position.z + (_retiredWidth / 2.0f)); } else { - _bbox->setXYZ(position.x - 12.0f, - position.y + 6.0f, - position.z - 12.0f, + _bbox.setXYZ(position.x - 12.0f, + position.y + 6.0f, + position.z - 12.0f, - position.x + 12.0f, - position.y + 72.0f, - position.z + 12.0f); + position.x + 12.0f, + position.y + 72.0f, + position.z + 12.0f); } } @@ -820,7 +818,7 @@ void Actor::faceActor(int otherActorId, bool animate) { faceXYZ(otherActor->_position, animate); } -void Actor::faceObject(const char *objectName, bool animate) { +void Actor::faceObject(const Common::String &objectName, bool animate) { int objectId = _vm->_scene->findObject(objectName); if (objectId == -1) { return; @@ -1066,13 +1064,10 @@ int Actor::getGoal() const { } void Actor::speechPlay(int sentenceId, bool voiceOver) { - char name[13]; - sprintf(name, "%02d-%04d%s.AUD", _id, sentenceId, _vm->_languageCode); - int balance; + Common::String name = Common::String::format( "%02d-%04d%s.AUD", _id, sentenceId, _vm->_languageCode.c_str()); - if (voiceOver || _id == BladeRunnerEngine::kActorVoiceOver) { - balance = 0; - } else { + int balance = 0; + if (!voiceOver && _id != BladeRunnerEngine::kActorVoiceOver) { // Vector3 pos = _vm->_view->_frameViewMatrix * _position; int screenX = 320; //, screenY = 0; //TODO: transform to screen space using fov; @@ -1226,66 +1221,66 @@ 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); +void Actor::save(SaveFileWriteStream &f) { + f.writeInt(_id); + f.writeInt(_setId); + f.writeVector3(_position); + f.writeInt(_facing); + f.writeInt(_targetFacing); + f.writeInt(0); // TODO: _timer4RemainDefault + + f.writeInt(_honesty); + f.writeInt(_intelligence); + f.writeInt(_stability); + f.writeInt(_combatAggressiveness); + f.writeInt(_goalNumber); + + f.writeInt(_currentHP); + f.writeInt(_maxHP); + + f.writeBool(_movementTrackPaused); + f.writeInt(_movementTrackNextWaypointId); + f.writeInt(_movementTrackNextDelay); + f.writeInt(_movementTrackNextAngle); + f.writeBool(_movementTrackNextRunning); + + f.writeInt(0); // TODO: _clueType + f.writeBool(_isMoving); + f.writeBool(_isTarget); + f.writeBool(_inCombat); + f.writeBool(_isInvisible); + f.writeBool(_isRetired); + f.writeBool(_isImmuneToObstacles); + + f.writeInt(_animationMode); + f.writeInt(_fps); + f.writeInt(_frameMs); + f.writeInt(_animationId); + f.writeInt(_animationFrame); + + f.writeInt(_movementTrackWalkingToWaypointId); + f.writeInt(_movementTrackDelayOnNextWaypoint); + + f.writeRect(_screenRectangle); + f.writeInt(_retiredWidth); + f.writeInt(_retiredHeight); + f.writeInt(_damageAnimIfMoving); + f.writeInt(0); // TODO: _actorFieldU6 + f.writeInt(0); // TODO: _actorFieldU7 + f.writeFloat(_scale); for (int i = 0; i < 7; ++i) { - f.write(_timersLeft[i]); + f.writeInt(_timersLeft[i]); } uint32 now = _vm->getTotalPlayTime(); // TODO: should be last lock time for (int i = 0; i < 7; ++i) { - f.write(_timersLast[i] - now); + f.writeInt(_timersLast[i] - now); } int actorCount = _vm->_gameInfo->getActorCount(); for (int i = 0; i != actorCount; ++i) { - f.write(_friendlinessToOther[i]); + f.writeInt(_friendlinessToOther[i]); } _clues->save(f); @@ -1294,12 +1289,89 @@ void Actor::save(SaveFile &f) { _walkInfo->save(f); - _bbox->save(f); + f.writeBoundingBox(_bbox); _combatInfo->save(f); - f.write(_animationModeCombatIdle); - f.write(_animationModeCombatWalk); - f.write(_animationModeCombatRun); + f.writeInt(_animationModeCombatIdle); + f.writeInt(_animationModeCombatWalk); + f.writeInt(_animationModeCombatRun); +} + +void Actor::load(SaveFileReadStream &f) { + _id = f.readInt(); + _setId = f.readInt(); + _position = f.readVector3(); + _facing = f.readInt(); + _targetFacing = f.readInt(); + f.skip(4); // TODO: _timer4RemainDefault + + _honesty = f.readInt(); + _intelligence = f.readInt(); + _stability = f.readInt(); + _combatAggressiveness = f.readInt(); + _goalNumber = f.readInt(); + + _currentHP = f.readInt(); + _maxHP = f.readInt(); + + _movementTrackPaused = f.readBool(); + _movementTrackNextWaypointId = f.readInt(); + _movementTrackNextDelay = f.readInt(); + _movementTrackNextAngle = f.readInt(); + _movementTrackNextRunning = f.readBool(); + + f.skip(4); // TODO: _clueType + _isMoving = f.readBool(); + _isTarget = f.readBool(); + _inCombat = f.readBool(); + _isInvisible = f.readBool(); + _isRetired = f.readBool(); + _isImmuneToObstacles = f.readBool(); + + _animationMode = f.readInt(); + _fps = f.readInt(); + _frameMs = f.readInt(); + _animationId = f.readInt(); + _animationFrame = f.readInt(); + + _movementTrackWalkingToWaypointId = f.readInt(); + _movementTrackDelayOnNextWaypoint = f.readInt(); + + _screenRectangle = f.readRect(); + _retiredWidth = f.readInt(); + _retiredHeight = f.readInt(); + _damageAnimIfMoving = f.readInt(); + f.skip(4); // TODO: _actorFieldU6 + f.skip(4); // TODO: _actorFieldU7 + _scale = f.readFloat(); + + for (int i = 0; i < 7; ++i) { + _timersLeft[i] = f.readInt(); + } + + uint32 now = _vm->getTotalPlayTime(); // TODO: should be last lock time + for (int i = 0; i < 7; ++i) { + _timersLast[i] = f.readInt() + now; + } + + int actorCount = _vm->_gameInfo->getActorCount(); + for (int i = 0; i != actorCount; ++i) { + _friendlinessToOther[i] = f.readInt(); + } + + _clues->load(f); + + _movementTrack->load(f); + + _walkInfo->load(f); + + _bbox = f.readBoundingBox(); + + _combatInfo->load(f); + + _animationModeCombatIdle = f.readInt(); + _animationModeCombatWalk = f.readInt(); + _animationModeCombatRun = f.readInt(); } } // End of namespace BladeRunner diff --git a/engines/bladerunner/actor.h b/engines/bladerunner/actor.h index 55ffc4f30e..7498d2bf51 100644 --- a/engines/bladerunner/actor.h +++ b/engines/bladerunner/actor.h @@ -23,6 +23,7 @@ #ifndef BLADERUNNER_ACTOR_H #define BLADERUNNER_ACTOR_H +#include "bladerunner/boundingbox.h" #include "bladerunner/vector.h" #include "common/array.h" @@ -36,14 +37,15 @@ class ActorWalk; class BladeRunnerEngine; class BoundingBox; class MovementTrack; -class SaveFile; +class SaveFileReadStream; +class SaveFileWriteStream; class View; class Actor { BladeRunnerEngine *_vm; public: - BoundingBox *_bbox; + BoundingBox _bbox; Common::Rect _screenRectangle; MovementTrack *_movementTrack; ActorWalk *_walkInfo; @@ -147,7 +149,7 @@ public: bool walkTo(bool runFlag, const Vector3 &destination, bool a3); bool loopWalkToActor(int otherActorId, int destinationOffset, int interruptible, bool runFlag, bool a5, bool *isRunningFlag); bool loopWalkToItem(int itemId, int destinationOffset, int interruptible, bool runFlag, bool a5, bool *isRunningFlag); - bool loopWalkToSceneObject(const char *objectName, int destinationOffset, bool interruptible, bool runFlag, bool a5, bool *isRunningFlag); + bool loopWalkToSceneObject(const Common::String &objectName, int destinationOffset, bool interruptible, bool runFlag, bool a5, bool *isRunningFlag); bool loopWalkToWaypoint(int waypointId, int destinationOffset, int interruptible, bool runFlag, bool a5, bool *isRunningFlag); bool loopWalkToXYZ(const Vector3 &destination, int destinationOffset, bool interruptible, bool runFlag, bool a5, bool *isRunningFlag); bool asyncWalkToWaypoint(int waypointId, int destinationOffset, bool runFlag, bool a5); @@ -160,8 +162,8 @@ public: int getSetId() const; void setSetId(int setId); - BoundingBox *getBoundingBox() const { return _bbox; } - Common::Rect *getScreenRectangle() { return &_screenRectangle; } + const BoundingBox &getBoundingBox() const { return _bbox; } + const Common::Rect &getScreenRectangle() { return _screenRectangle; } int getWalkbox() const { return _walkboxId; } bool isRetired() const { return _isRetired; } @@ -179,7 +181,7 @@ public: void stopWalking(bool value); void faceActor(int otherActorId, bool animate); - void faceObject(const char *objectName, bool animate); + void faceObject(const Common::String &objectName, bool animate); void faceItem(int itemId, bool animate); void faceWaypoint(int waypointId, bool animate); void faceXYZ(float x, float y, float z, bool animate); @@ -247,6 +249,9 @@ public: bool isObstacleBetween(const Vector3 &target); + void save(SaveFileWriteStream &f); + void load(SaveFileReadStream &f); + static int findTargetUnderMouse(BladeRunnerEngine *vm, int mouseX, int mouseY); private: @@ -257,9 +262,6 @@ 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 89db6feb47..0c25ffc19f 100644 --- a/engines/bladerunner/actor_clues.cpp +++ b/engines/bladerunner/actor_clues.cpp @@ -217,21 +217,41 @@ void ActorClues::remove(int index) { _clues[index].field8 = 0; } -void ActorClues::save(SaveFile &f) { - f.write(_count); - f.write(_maxCount); +void ActorClues::save(SaveFileWriteStream &f) { + f.writeInt(_count); + f.writeInt(_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); + f.writeInt(c.clueId); + f.writeInt(c.weight); + f.writeInt(c.fromActorId); + f.writeInt(c.field3); + f.writeInt(c.field4); + f.writeInt(c.field5); + f.writeInt(c.field6); + f.writeInt(c.field7); + f.writeInt(c.field8); + f.writeByte(c.flags); + } +} + +void ActorClues::load(SaveFileReadStream &f) { + _count = f.readInt(); + _maxCount = f.readInt(); + _clues.clear(); + _clues.resize(_maxCount); + for (int i = 0; i < _count; ++i) { + Clue &c = _clues[i]; + c.clueId = f.readInt(); + c.weight = f.readInt(); + c.fromActorId = f.readInt(); + c.field3 = f.readInt(); + c.field4 = f.readInt(); + c.field5 = f.readInt(); + c.field6 = f.readInt(); + c.field7 = f.readInt(); + c.field8 = f.readInt(); + c.flags = f.readByte(); } } diff --git a/engines/bladerunner/actor_clues.h b/engines/bladerunner/actor_clues.h index 03ccff20fd..79181cc20c 100644 --- a/engines/bladerunner/actor_clues.h +++ b/engines/bladerunner/actor_clues.h @@ -28,7 +28,8 @@ namespace BladeRunner { class BladeRunnerEngine; -class SaveFile; +class SaveFileReadStream; +class SaveFileWriteStream; class ActorClues { struct Clue { @@ -41,7 +42,7 @@ class ActorClues { int field6; int field7; int field8; - unsigned char flags; + byte flags; }; BladeRunnerEngine *_vm; @@ -75,8 +76,8 @@ public: void removeAll(); - void save(SaveFile &f); - //loadgame + void save(SaveFileWriteStream &f); + void load(SaveFileReadStream &f); private: bool exists(int clueId) const; diff --git a/engines/bladerunner/actor_combat.cpp b/engines/bladerunner/actor_combat.cpp index 7a60d6d85a..4bcce5d3bf 100644 --- a/engines/bladerunner/actor_combat.cpp +++ b/engines/bladerunner/actor_combat.cpp @@ -50,31 +50,6 @@ 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; @@ -316,11 +291,59 @@ void ActorCombat::hitAttempt() { } } +void ActorCombat::save(SaveFileWriteStream &f) { + f.writeInt(_actorId); + f.writeBool(_active); + f.writeInt(_state); + f.writeBool(_rangedAttack); + f.writeInt(_enemyId); + f.writeInt(_waypointType); + f.writeInt(_damage); + f.writeInt(_fleeRatio); + f.writeInt(_coverRatio); + f.writeInt(_actionRatio); + f.writeInt(_fleeRatioConst); + f.writeInt(_coverRatioConst); + f.writeInt(_actionRatioConst); + f.writeInt(_range); + f.writeInt(_unstoppable); + f.writeInt(_actorHp); + f.writeInt(_fleeingTowards); + f.writeVector3(_actorPosition); + f.writeVector3(_enemyPosition); + f.writeInt(_coversWaypointCount); + f.writeInt(_fleeWaypointsCount); +} + +void ActorCombat::load(SaveFileReadStream &f) { + _actorId = f.readInt(); + _active = f.readBool(); + _state = f.readInt(); + _rangedAttack = f.readBool(); + _enemyId = f.readInt(); + _waypointType = f.readInt(); + _damage = f.readInt(); + _fleeRatio = f.readInt(); + _coverRatio = f.readInt(); + _actionRatio = f.readInt(); + _fleeRatioConst = f.readInt(); + _coverRatioConst = f.readInt(); + _actionRatioConst = f.readInt(); + _range = f.readInt(); + _unstoppable = f.readInt(); + _actorHp = f.readInt(); + _fleeingTowards = f.readInt(); + _actorPosition = f.readVector3(); + _enemyPosition = f.readVector3(); + _coversWaypointCount = f.readInt(); + _fleeWaypointsCount = f.readInt(); +} + void ActorCombat::reset() { _active = false; _actorId = -1; _state = -1; - _rangedAttack = -1; + _rangedAttack = false; _enemyId = -1; _waypointType = -1; _damage = 0; diff --git a/engines/bladerunner/actor_combat.h b/engines/bladerunner/actor_combat.h index a621c3d6ff..2f65f1904d 100644 --- a/engines/bladerunner/actor_combat.h +++ b/engines/bladerunner/actor_combat.h @@ -28,7 +28,8 @@ namespace BladeRunner { class BladeRunnerEngine; -class SaveFile; +class SaveFileReadStream; +class SaveFileWriteStream; class ActorCombat { BladeRunnerEngine *_vm; @@ -36,7 +37,7 @@ class ActorCombat { int _actorId; bool _active; int _state; - int _rangedAttack; + bool _rangedAttack; int _enemyId; int _waypointType; int _damage; @@ -66,10 +67,11 @@ public: void tick(); - void save(SaveFile &f); - void hitAttempt(); + void save(SaveFileWriteStream &f); + void load(SaveFileReadStream &f); + private: void reset(); diff --git a/engines/bladerunner/actor_dialogue_queue.cpp b/engines/bladerunner/actor_dialogue_queue.cpp index 5f0ad60426..48fcf8a6ab 100644 --- a/engines/bladerunner/actor_dialogue_queue.cpp +++ b/engines/bladerunner/actor_dialogue_queue.cpp @@ -54,7 +54,7 @@ void ActorDialogueQueue::add(int actorId, int sentenceId, int animationMode) { if (actorId == 0 || actorId == BladeRunnerEngine::kActorVoiceOver) { animationMode = -1; } - if (_entries.size() < 25) { + if (_entries.size() < kMaxEntries) { Entry entry; entry.isNotPause = true; entry.isPause = false; @@ -68,7 +68,7 @@ void ActorDialogueQueue::add(int actorId, int sentenceId, int animationMode) { } void ActorDialogueQueue::addPause(int delay) { - if (_entries.size() < 25) { + if (_entries.size() < kMaxEntries) { Entry entry; entry.isNotPause = false; entry.isPause = true; @@ -160,30 +160,58 @@ void ActorDialogueQueue::tick() { } } -void ActorDialogueQueue::save(SaveFile &f) { +void ActorDialogueQueue::save(SaveFileWriteStream &f) { int count = (int)_entries.size(); - f.write(count); + f.writeInt(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.writeBool(e.isNotPause); + f.writeBool(e.isPause); + f.writeInt(e.actorId); + f.writeInt(e.sentenceId); + f.writeInt(e.animationMode); + f.writeInt(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.padBytes((kMaxEntries - count) * 24); + + f.writeBool(_isNotPause); + f.writeInt(_actorId); + f.writeInt(_sentenceId); + f.writeInt(_animationMode); + f.writeInt(_animationModePrevious); + f.writeBool(_isPause); + f.writeInt(_delay); // f.write(_timeLast); } +void ActorDialogueQueue::load(SaveFileReadStream &f) { + _entries.clear(); + int count = f.readInt(); + assert(count <= kMaxEntries); + _entries.resize(count); + for (int i = 0; i < count; ++i) { + Entry &e = _entries[i]; + e.isNotPause = f.readBool(); + e.isPause = f.readBool(); + e.actorId = f.readInt(); + e.sentenceId = f.readInt(); + e.animationMode = f.readInt(); + e.delay = f.readInt(); + } + + f.skip((kMaxEntries - count) * 24); + + _isNotPause = f.readBool(); + _actorId = f.readInt(); + _sentenceId = f.readInt(); + _animationMode = f.readInt(); + _animationModePrevious = f.readInt(); + _isPause = f.readBool(); + _delay = f.readInt(); + + _timeLast = 0; +} + void ActorDialogueQueue::clear() { _entries.clear(); _isNotPause = false; diff --git a/engines/bladerunner/actor_dialogue_queue.h b/engines/bladerunner/actor_dialogue_queue.h index e26b6cf1a1..832bcc9dab 100644 --- a/engines/bladerunner/actor_dialogue_queue.h +++ b/engines/bladerunner/actor_dialogue_queue.h @@ -28,9 +28,12 @@ namespace BladeRunner { class BladeRunnerEngine; -class SaveFile; +class SaveFileReadStream; +class SaveFileWriteStream; class ActorDialogueQueue { + static const int kMaxEntries = 25; + struct Entry { bool isNotPause; bool isPause; @@ -63,7 +66,8 @@ public: void flush(int a1, bool callScript); void tick(); - void save(SaveFile &f); + void save(SaveFileWriteStream &f); + void load(SaveFileReadStream &f); private: void clear(); diff --git a/engines/bladerunner/actor_walk.cpp b/engines/bladerunner/actor_walk.cpp index d376e36785..b4587333a1 100644 --- a/engines/bladerunner/actor_walk.cpp +++ b/engines/bladerunner/actor_walk.cpp @@ -239,25 +239,51 @@ 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); +void ActorWalk::save(SaveFileWriteStream &f) { + f.writeInt(_walking); + f.writeInt(_running); + f.writeVector3(_destination); // _originalDestination is not saved - f.write(_current); - f.write(_next); - f.write(_facing); + f.writeVector3(_current); + f.writeVector3(_next); + f.writeInt(_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.writeInt(it->_key); + f.writeBool(it->_value); } f.padBytes(8 * (20 - _nearActors.size())); - f.write((int)_nearActors.size()); + f.writeInt(_nearActors.size()); - f.write(0); // _notUsed - f.write(_status); + f.writeInt(0); // _notUsed + f.writeInt(_status); +} + +void ActorWalk::load(SaveFileReadStream &f) { + _walking = f.readInt(); + _running = f.readInt(); + _destination = f.readVector3(); + // _originalDestination is not saved + _current = f.readVector3(); + _next = f.readVector3(); + _facing = f.readInt(); + + int actorId[20]; + bool isNear[20]; + + for (int i = 0; i < 20; ++i) { + actorId[i] = f.readInt(); + isNear[i] = f.readBool(); + } + + int count = f.readInt(); + for (int i = 0; i < count; ++i) { + _nearActors.setVal(actorId[i], isNear[i]); + } + + f.skip(4); // _notUsed + _status = f.readInt(); } bool ActorWalk::isXYZEmpty(float x, float y, float z, int actorId) const { diff --git a/engines/bladerunner/actor_walk.h b/engines/bladerunner/actor_walk.h index 265421458f..45298e2794 100644 --- a/engines/bladerunner/actor_walk.h +++ b/engines/bladerunner/actor_walk.h @@ -29,7 +29,8 @@ namespace BladeRunner { class BladeRunnerEngine; -class SaveFile; +class SaveFileReadStream; +class SaveFileWriteStream; class ActorWalk { BladeRunnerEngine *_vm; @@ -61,7 +62,9 @@ public: void stop(int actorId, bool immediately, int combatAnimationMode, int animationMode); void run(int actorId); - void save(SaveFile &f); + void save(SaveFileWriteStream &f); + void load(SaveFileReadStream &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 6477f27c8e..81b6174ab9 100644 --- a/engines/bladerunner/ambient_sounds.cpp +++ b/engines/bladerunner/ambient_sounds.cpp @@ -69,25 +69,23 @@ void AmbientSounds::addSound( int panStartMin, int panStartMax, int panEndMin, int panEndMax, int priority, int unk) { - const char *name = _vm->_gameInfo->getSfxTrack(sfxId); sort(volumeMin, volumeMax); sort(panStartMin, panStartMax); sort(panEndMin, panEndMax); addSoundByName( - name, - timeMin, timeMax, - volumeMin, volumeMax, - panStartMin, panStartMax, - panEndMin, panEndMax, - priority, unk + _vm->_gameInfo->getSfxTrack(sfxId), + timeMin, timeMax, + volumeMin, volumeMax, + panStartMin, panStartMax, + panEndMin, panEndMax, + priority, unk ); } void AmbientSounds::removeNonLoopingSound(int sfxId, bool stopPlaying) { - const char *name = _vm->_gameInfo->getSfxTrack(sfxId); - int32 hash = mix_id(name); + int32 hash = MIXArchive::getHash(_vm->_gameInfo->getSfxTrack(sfxId)); int index = findNonLoopingTrackByHash(hash); if (index >= 0) { removeNonLoopingSoundByIndex(index, stopPlaying); @@ -105,8 +103,7 @@ void AmbientSounds::addSpeech(int actorId, int sentenceId, int timeMin, int time sort(panStartMin, panStartMax); sort(panEndMin, panEndMax); - char name[13]; - sprintf(name, "%02d-%04d%s.AUD", actorId, sentenceId, _vm->_languageCode); + Common::String name = Common::String::format( "%02d-%04d%s.AUD", actorId, sentenceId, _vm->_languageCode.c_str()); addSoundByName(name, timeMin, timeMax, volumeMin, volumeMax, @@ -116,15 +113,12 @@ void AmbientSounds::addSpeech(int actorId, int sentenceId, int timeMin, int time } void AmbientSounds::playSound(int sfxId, int volume, int panStart, int panEnd, int priority) { - const char *name = _vm->_gameInfo->getSfxTrack(sfxId); - - _vm->_audioPlayer->playAud(name, volume * _ambientVolume / 100, panStart, panEnd, priority, kAudioPlayerOverrideVolume); + _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(sfxId), volume * _ambientVolume / 100, panStart, panEnd, priority, kAudioPlayerOverrideVolume); } void AmbientSounds::addLoopingSound(int sfxId, int volume, int pan, int delay) { - const char *name = _vm->_gameInfo->getSfxTrack(sfxId); - - int32 hash = mix_id(name); + const Common::String &name = _vm->_gameInfo->getSfxTrack(sfxId); + int32 hash = MIXArchive::getHash(name); if (findLoopingTrackByHash(hash) >= 0) { return; @@ -137,8 +131,7 @@ void AmbientSounds::addLoopingSound(int sfxId, int volume, int pan, int delay) { LoopingSound &track = _loopingSounds[i]; track.isActive = true; - strncpy(track.name, name, sizeof(track.name)); - track.name[sizeof(track.name) - 1] = 0; + track.name = name; track.hash = hash; track.pan = pan; track.volume = volume; @@ -162,8 +155,7 @@ void AmbientSounds::addLoopingSound(int sfxId, int volume, int pan, int delay) { } void AmbientSounds::adjustLoopingSound(int sfxId, int volume, int pan, int delay) { - const char *name = _vm->_gameInfo->getSfxTrack(sfxId); - int32 hash = mix_id(name); + int32 hash = MIXArchive::getHash(_vm->_gameInfo->getSfxTrack(sfxId)); int index = findLoopingTrackByHash(hash); if (index >= 0 && _loopingSounds[index].audioPlayerTrack != -1 && _vm->_audioPlayer->isActive(_loopingSounds[index].audioPlayerTrack)) { @@ -179,8 +171,7 @@ void AmbientSounds::adjustLoopingSound(int sfxId, int volume, int pan, int delay } void AmbientSounds::removeLoopingSound(int sfxId, int delay) { - const char *name = _vm->_gameInfo->getSfxTrack(sfxId); - int32 hash = mix_id(name); + int32 hash = MIXArchive::getHash(_vm->_gameInfo->getSfxTrack(sfxId)); int index = findLoopingTrackByHash(hash); if (index >= 0) { removeLoopingSoundByIndex(index, delay); @@ -298,15 +289,12 @@ int AmbientSounds::findLoopingTrackByHash(int32 hash) const { } void AmbientSounds::addSoundByName( - const char *name, + const Common::String &name, int timeMin, int timeMax, int volumeMin, int volumeMax, int panStartMin, int panStartMax, int panEndMin, int panEndMax, int priority, int unk) { - if (strlen(name) > 12) { - error("AmbientSounds::addSoundByName: Overlong name '%s'", name); - } int i = findAvailableNonLoopingTrack(); if (i < 0) { @@ -318,9 +306,8 @@ void AmbientSounds::addSoundByName( uint32 now = _vm->getTotalPlayTime(); track.isActive = true; - strncpy(track.name, name, sizeof(track.name)); - track.name[sizeof(track.name) - 1] = 0; - track.hash = mix_id(name); + track.name = name; + track.hash = MIXArchive::getHash(name); track.timeMin = 1000 * timeMin; track.timeMax = 1000 * timeMax; track.nextPlayTime = now + _vm->_rnd.getRandomNumberRng(track.timeMin, track.timeMax); @@ -356,46 +343,82 @@ void AmbientSounds::removeLoopingSoundByIndex(int index, int delay) { } } track.isActive = false; - track.name[0] = 0; + track.name.clear(); track.hash = 0; track.audioPlayerTrack = -1; track.volume = 0; track.pan = 0; } -void AmbientSounds::save(SaveFile &f) { - f.write(false); // TODO: _isDisabled +void AmbientSounds::save(SaveFileWriteStream &f) { + f.writeBool(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.writeBool(s.isActive); + f.writeStringSz(s.name, 13); + f.writeSint32LE(s.hash); + f.writeInt(s.audioPlayerTrack); + f.writeInt(s.timeMin); + f.writeInt(s.timeMax); + f.writeUint32LE(s.nextPlayTime); + f.writeInt(s.volumeMin); + f.writeInt(s.volumeMax); + f.writeInt(s.volume); + f.writeInt(s.panStartMin); + f.writeInt(s.panStartMax); + f.writeInt(s.panEndMin); + f.writeInt(s.panEndMax); + f.writeInt(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); + f.writeBool(s.isActive); + f.writeStringSz(s.name, 13); + f.writeSint32LE(s.hash); + f.writeInt(s.audioPlayerTrack); + f.writeInt(s.volume); + f.writeInt(s.pan); + } +} + +void AmbientSounds::load(SaveFileReadStream &f) { + f.skip(4); // TODO: _isDisabled + + for (int i = 0; i != kNonLoopingSounds; ++i) { + // 73 bytes per non-looping sound + NonLoopingSound &s = _nonLoopingSounds[i]; + s.isActive = f.readBool(); + s.name = f.readStringSz(13); + s.hash = f.readSint32LE(); + s.audioPlayerTrack = f.readInt(); + s.timeMin = f.readInt(); + s.timeMax = f.readInt(); + s.nextPlayTime = f.readUint32LE(); + s.volumeMin = f.readInt(); + s.volumeMax = f.readInt(); + s.volume = f.readInt(); + s.panStartMin = f.readInt(); + s.panStartMax = f.readInt(); + s.panEndMin = f.readInt(); + s.panEndMax = f.readInt(); + s.priority = f.readInt(); + f.skip(4); // field_45 + } + + for (int i = 0; i != kLoopingSounds; ++i) { + // 33 bytes per looping sound + LoopingSound &s = _loopingSounds[i]; + s.isActive = f.readBool(); + s.name = f.readStringSz(13); + s.hash = f.readSint32LE(); + s.audioPlayerTrack = f.readInt(); + s.volume = f.readInt(); + s.pan = f.readInt(); } } diff --git a/engines/bladerunner/ambient_sounds.h b/engines/bladerunner/ambient_sounds.h index 6e14c56cec..de08965a11 100644 --- a/engines/bladerunner/ambient_sounds.h +++ b/engines/bladerunner/ambient_sounds.h @@ -25,40 +25,43 @@ #include "audio/audiostream.h" +#include "common/str.h" + namespace BladeRunner { class BladeRunnerEngine; -class SaveFile; +class SaveFileReadStream; +class SaveFileWriteStream; class AmbientSounds { static const int kNonLoopingSounds = 25; static const int kLoopingSounds = 3; struct NonLoopingSound { - bool isActive; - char name[13]; - int32 hash; - int32 audioPlayerTrack; - int32 timeMin; - int32 timeMax; - uint32 nextPlayTime; - int32 volumeMin; - int32 volumeMax; - int32 volume; - int32 panStartMin; - int32 panStartMax; - int32 panEndMin; - int32 panEndMax; - int32 priority; + bool isActive; + Common::String name; + int32 hash; + int audioPlayerTrack; + int timeMin; + int timeMax; + uint32 nextPlayTime; + int volumeMin; + int volumeMax; + int volume; + int panStartMin; + int panStartMax; + int panEndMin; + int panEndMax; + int priority; }; struct LoopingSound { - bool isActive; - char name[13]; - int32 hash; - int audioPlayerTrack; - int32 volume; - int pan; + bool isActive; + Common::String name; + int32 hash; + int audioPlayerTrack; + int volume; + int pan; }; BladeRunnerEngine *_vm; @@ -104,7 +107,8 @@ public: int getVolume() const; void playSample(); - void save(SaveFile &f); + void save(SaveFileWriteStream &f); + void load(SaveFileReadStream &f); private: int findAvailableNonLoopingTrack() const; @@ -122,7 +126,7 @@ private: // playVolumeAdjustSound void addSoundByName( - const char *name, + const Common::String &name, int timeMin, int timeMax, int volumeMin, int volumeMax, int panStartMin, int panStartMax, diff --git a/engines/bladerunner/archive.cpp b/engines/bladerunner/archive.cpp index 8088e1ac67..c116eeb94f 100644 --- a/engines/bladerunner/archive.cpp +++ b/engines/bladerunner/archive.cpp @@ -51,7 +51,7 @@ bool MIXArchive::open(const Common::String &filename) { _entries.resize(_entryCount); for (uint16 i = 0; i != _entryCount; ++i) { - _entries[i].id = _fd.readSint32LE(); + _entries[i].hash = _fd.readUint32LE(); _entries[i].offset = _fd.readUint32LE(); _entries[i].length = _fd.readUint32LE(); @@ -61,7 +61,7 @@ bool MIXArchive::open(const Common::String &filename) { // Verify that the entries are sorted by id. Note that id is signed. if (i > 0) { - assert(_entries[i].id > _entries[i - 1].id); + assert(_entries[i].hash > _entries[i - 1].hash); } } @@ -86,7 +86,7 @@ bool MIXArchive::isOpen() const { #define ROL(n) ((n << 1) | ((n >> 31) & 1)) -int32 mix_id(const Common::String &name) { +int32 MIXArchive::getHash(const Common::String &name) { char buffer[12] = { 0 }; for (uint i = 0; i != name.size() && i < 12u; ++i) { @@ -103,11 +103,10 @@ int32 mix_id(const Common::String &name) { id = ROL(id) + t; } - return reinterpret_cast<int32&>(id); + return id; } -static -int32 tlk_id(const Common::String &name) { +static uint32 tlk_id(const Common::String &name) { char buffer[12] = { 0 }; for (uint i = 0; i != name.size() && i < 12u; ++i) @@ -124,15 +123,15 @@ int32 tlk_id(const Common::String &name) { return 10000 * actor_id + speech_id; } -uint32 MIXArchive::indexForId(int32 id) const { +uint32 MIXArchive::indexForHash(int32 hash) const { uint32 lo = 0, hi = _entryCount; while (lo < hi) { uint32 mid = lo + (hi - lo) / 2; - if (id > _entries[mid].id) { + if (hash > _entries[mid].hash) { lo = mid + 1; - } else if (id < _entries[mid].id) { + } else if (hash < _entries[mid].hash) { hi = mid; } else { return mid; @@ -142,14 +141,15 @@ uint32 MIXArchive::indexForId(int32 id) const { } Common::SeekableReadStream *MIXArchive::createReadStreamForMember(const Common::String &name) { - int32 id; + int32 hash; - if (_isTLK) - id = tlk_id(name); - else - id = mix_id(name); + if (_isTLK) { + hash = tlk_id(name); + } else { + hash = MIXArchive::getHash(name); + } - uint32 i = indexForId(id); + uint32 i = indexForHash(hash); if (i == _entryCount) { return nullptr; diff --git a/engines/bladerunner/archive.h b/engines/bladerunner/archive.h index 7bec41f97a..9f7c67920d 100644 --- a/engines/bladerunner/archive.h +++ b/engines/bladerunner/archive.h @@ -34,6 +34,8 @@ public: MIXArchive(); ~MIXArchive(); + static int32 getHash(const Common::String &name); + bool open(const Common::String &filename); void close(); bool isOpen() const; @@ -50,17 +52,16 @@ private: uint32 _size; struct ArchiveEntry { - int32 id; + int32 hash; uint32 offset; uint32 length; }; Common::Array<ArchiveEntry> _entries; - uint32 indexForId(int32 id) const; + uint32 indexForHash(int32 hash) const; }; -int32 mix_id(const Common::String &name); } // End of namespace BladeRunner diff --git a/engines/bladerunner/audio_player.cpp b/engines/bladerunner/audio_player.cpp index e1ef0263b6..5186888dd2 100644 --- a/engines/bladerunner/audio_player.cpp +++ b/engines/bladerunner/audio_player.cpp @@ -253,7 +253,7 @@ int AudioPlayer::playAud(const Common::String &name, int volume, int panFrom, in } /* Load audio resource and store in cache. Playback will happen directly from there. */ - int32 hash = mix_id(name); + int32 hash = MIXArchive::getHash(name); if (!_cache->findByHash(hash)) { Common::SeekableReadStream *r = _vm->getResourceStream(name); if (!r) { diff --git a/engines/bladerunner/audio_speech.cpp b/engines/bladerunner/audio_speech.cpp index 69883cbce2..87f73737d4 100644 --- a/engines/bladerunner/audio_speech.cpp +++ b/engines/bladerunner/audio_speech.cpp @@ -58,12 +58,12 @@ AudioSpeech::~AudioSpeech() { delete[] _data; } -bool AudioSpeech::playSpeech(const char *name, int pan) { +bool AudioSpeech::playSpeech(const Common::String &name, int pan) { // debug("AudioSpeech::playSpeech(\"%s\")", name); Common::ScopedPtr<Common::SeekableReadStream> r(_vm->getResourceStream(name)); if (!r) { - warning("AudioSpeech::playSpeech: AUD resource \"%s\" not found", name); + warning("AudioSpeech::playSpeech: AUD resource \"%s\" not found", name.c_str()); return false; } @@ -78,7 +78,7 @@ bool AudioSpeech::playSpeech(const char *name, int pan) { r->read(_data, r->size()); if (r->err()) { - warning("AudioSpeech::playSpeech: Error reading resource \"%s\"", name); + warning("AudioSpeech::playSpeech: Error reading resource \"%s\"", name.c_str()); return false; } @@ -117,7 +117,7 @@ bool AudioSpeech::isPlaying() const { bool AudioSpeech::playSpeechLine(int actorId, int sentenceId, int volume, int a4, int priority) { int balance = _vm->_actors[actorId]->soundBalance(); - Common::String name = Common::String::format("%02d-%04d%s.AUD", actorId, sentenceId, _vm->_languageCode); + Common::String name = Common::String::format("%02d-%04d%s.AUD", actorId, sentenceId, _vm->_languageCode.c_str()); return _vm->_audioPlayer->playAud(name, _speechVolume * volume / 100, balance, balance, priority, kAudioPlayerOverrideVolume); } diff --git a/engines/bladerunner/audio_speech.h b/engines/bladerunner/audio_speech.h index 010499f480..5406f1d8e5 100644 --- a/engines/bladerunner/audio_speech.h +++ b/engines/bladerunner/audio_speech.h @@ -23,6 +23,7 @@ #ifndef BLADERUNNER_AUDIO_SPEECH_H #define BLADERUNNER_AUDIO_SPEECH_H +#include "common/str.h" #include "common/types.h" namespace BladeRunner { @@ -44,7 +45,7 @@ public: AudioSpeech(BladeRunnerEngine *vm); ~AudioSpeech(); - bool playSpeech(const char *name, int balance = 0); + bool playSpeech(const Common::String &name, int balance = 0); void stopSpeech(); bool isPlaying() const; diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp index 805461ce3c..f481accfbd 100644 --- a/engines/bladerunner/bladerunner.cpp +++ b/engines/bladerunner/bladerunner.cpp @@ -45,7 +45,6 @@ #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" @@ -356,8 +355,6 @@ bool BladeRunnerEngine::startup(bool hasSavegames) { // TODO: Set actor ids (redundant?) _policeMaze = new PoliceMaze(this); - if (!_policeMaze->init()) - return false; _textActorNames = new TextResource(this); if (!_textActorNames->open("ACTORS")) @@ -827,8 +824,7 @@ void BladeRunnerEngine::gameTick() { // TODO: Process AUD if (_walkSoundId >= 0) { - const char *name = _gameInfo->getSfxTrack(_walkSoundId); - _audioPlayer->playAud(name, _walkSoundVolume, _walkSoundBalance, _walkSoundBalance, 50, 0); + _audioPlayer->playAud(_gameInfo->getSfxTrack(_walkSoundId), _walkSoundVolume, _walkSoundBalance, _walkSoundBalance, 50, 0); _walkSoundId = -1; } @@ -1196,8 +1192,8 @@ void BladeRunnerEngine::handleMouseClickRegion(int regionId, int x, int y, bool } void BladeRunnerEngine::handleMouseClick3DObject(int objectId, bool buttonDown, bool isClickable, bool isTarget) { - const char *objectName = _scene->objectGetName(objectId); - debug("Clicked on object %s", objectName); + const Common::String &objectName = _scene->objectGetName(objectId); + debug("Clicked on object %s", objectName.c_str()); if (_isWalkingInterruptible && objectId != _walkingToObjectId) { _isWalkingInterruptible = false; @@ -1230,7 +1226,7 @@ void BladeRunnerEngine::handleMouseClick3DObject(int objectId, bool buttonDown, _walkingToActorId = -1; _isInsideScriptObject = true; - _sceneScript->clickedOn3DObject(objectName, false); + _sceneScript->clickedOn3DObject(objectName.c_str(), false); _isInsideScriptObject = false; } } else { @@ -1246,7 +1242,7 @@ void BladeRunnerEngine::handleMouseClick3DObject(int objectId, bool buttonDown, //TODO mouse::randomize(Mouse); _isInsideScriptObject = true; - _sceneScript->clickedOn3DObject(objectName, true); + _sceneScript->clickedOn3DObject(objectName.c_str(), true); _isInsideScriptObject = false; } } @@ -1597,53 +1593,29 @@ bool BladeRunnerEngine::saveGame(const Common::String &filename, byte *thumbnail return false; } - SaveFile s(commonSaveFile); + SaveFileWriteStream s; s.padBytes(9600); // TODO: thumbnail - s.write(-1.0f); - + s.writeFloat(-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]); + s.writeInt(_gameVars[i]); } - - // TODO - // _music->save(s); - // s.debug(" - MUSIC - "); - s.padBytes(0x56); - + _music->save(s); // _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); - + s.padBytes(0x28); // TODO: _scores->save(s); _dialogueMenu->save(s); _obstacles->save(s); _actorDialogueQueue->save(s); @@ -1652,12 +1624,12 @@ bool BladeRunnerEngine::saveGame(const Common::String &filename, byte *thumbnail 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); + int animationState, animationFrame, animationStateNext, nextAnimation; + _aiScripts->queryAnimationState(i, &animationState, &animationFrame, &animationStateNext, &nextAnimation); + s.writeInt(animationState); + s.writeInt(animationFrame); + s.writeInt(animationStateNext); + s.writeInt(nextAnimation); } _actors[kActorVoiceOver]->save(s); @@ -1667,11 +1639,86 @@ bool BladeRunnerEngine::saveGame(const Common::String &filename, byte *thumbnail s.finalize(); assert(0 && "ok"); + commonSaveFile->writeUint32LE(s.size() + 4); + commonSaveFile->write(s.getData(), s.size()); + return !commonSaveFile->err(); } -void BladeRunnerEngine::ISez(const char *str) { - debug("\t%s", str); +void BladeRunnerEngine::loadGame(const Common::String &filename, byte *thumbnail) { + warning("BladeRunnerEngine::loadGame not finished"); + + if (!playerHasControl() || _sceneScript->isInsideScript() || _aiScripts->isInsideScript()) { + return; + } + + Common::InSaveFile *commonSaveFile = getSaveFileManager()->openForLoading(filename); + if (commonSaveFile->err()) { + return; + } + + void *buf = malloc(commonSaveFile->size()); + int dataSize = commonSaveFile->read(buf, commonSaveFile->size()); + + SaveFileReadStream s((const byte*)buf, dataSize); + + _ambientSounds->removeAllNonLoopingSounds(true); + _ambientSounds->removeAllLoopingSounds(1); + _music->stop(2); + _audioSpeech->stopSpeech(); + _actorDialogueQueue->flush(true, false); + + int size = s.readInt(); + + if (size != dataSize) { + return; + } + + s.skip(9600); // thumbnail + _settings->load(s); + _scene->load(s); + _scene->_exits->load(s); + _scene->_regions->load(s); + _scene->_set->load(s); + for (uint i = 0; i != _gameInfo->getGlobalVarCount(); ++i) { + _gameVars[i] = s.readInt(); + } + _music->load(s); + // _audioPlayer->load(s) // zero func + // _audioSpeech->load(s) // zero func + _combat->load(s); + _gameFlags->load(s); + _items->load(s); + _sceneObjects->load(s); + _ambientSounds->load(s); + _overlays->load(s); + _spinner->load(s); + s.skip(0x28); // TODO: _scores->load(s); + _dialogueMenu->load(s); + _obstacles->load(s); + _actorDialogueQueue->load(s); + _waypoints->load(s); + + for (uint i = 0; i != _gameInfo->getActorCount(); ++i) { + _actors[i]->load(s); + + int animationState = s.readInt(); + int animationFrame = s.readInt(); + int animationStateNext = s.readInt(); + int nextAnimation = s.readInt(); + _aiScripts->setAnimationState(i, animationState, animationFrame, animationStateNext, nextAnimation); + } + _actors[kActorVoiceOver]->load(s); + + _policeMaze->load(s); + _crimesDatabase->load(s); + + _settings->setNewSetAndScene(_settings->getSet(), _settings->getScene()); + _settings->setChapter(_settings->getChapter()); +} + +void BladeRunnerEngine::ISez(const Common::String &str) { + debug("\t%s", str.c_str()); } void BladeRunnerEngine::blitToScreen(const Graphics::Surface &src) { diff --git a/engines/bladerunner/bladerunner.h b/engines/bladerunner/bladerunner.h index 7561db2acf..32747cc514 100644 --- a/engines/bladerunner/bladerunner.h +++ b/engines/bladerunner/bladerunner.h @@ -104,10 +104,10 @@ public: static const int kActorCount = 100; static const int kActorVoiceOver = kActorCount - 1; - bool _gameIsRunning; - bool _windowIsActive; - int _playerLosesControlCounter; - const char *_languageCode; + bool _gameIsRunning; + bool _windowIsActive; + int _playerLosesControlCounter; + Common::String _languageCode; ActorDialogueQueue *_actorDialogueQueue; ScreenEffects *_screenEffects; @@ -261,11 +261,11 @@ public: void playerGainsControl(); bool saveGame(const Common::String &filename, byte *thumbnail); - void loadGame(); + void loadGame(const Common::String &filename, byte *thumbnail); void newGame(); void autoSaveGame(); - void ISez(const char *str); + void ISez(const Common::String &str); void blitToScreen(const Graphics::Surface &src); diff --git a/engines/bladerunner/boundingbox.cpp b/engines/bladerunner/boundingbox.cpp index aea2dc0a24..40b7d4285a 100644 --- a/engines/bladerunner/boundingbox.cpp +++ b/engines/bladerunner/boundingbox.cpp @@ -84,16 +84,4 @@ 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 0397a86266..0206f0bbdc 100644 --- a/engines/bladerunner/boundingbox.h +++ b/engines/bladerunner/boundingbox.h @@ -27,7 +27,7 @@ namespace BladeRunner { -class SaveFile; +class SaveFileWriteStream; class BoundingBox { Vector3 _vertices[2]; @@ -45,8 +45,6 @@ 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 eefcebccba..e1dc6b1044 100644 --- a/engines/bladerunner/combat.cpp +++ b/engines/bladerunner/combat.cpp @@ -127,8 +127,8 @@ void Combat::shoot(int actorId, Vector3 &to, int screenX) { distanceFromCenter = 100 * ------------------------------- abs(right - left) / 2 */ - Common::Rect *rect = actor->getScreenRectangle(); - int distanceFromCenter = CLIP(100 * (screenX - abs((rect->right + rect->left) / 2)) / abs((rect->right - rect->left) / 2), 0, 100); + const Common::Rect &rect = actor->getScreenRectangle(); + int distanceFromCenter = CLIP(100 * (screenX - abs((rect.right + rect.left) / 2)) / abs((rect.right - rect.left) / 2), 0, 100); int damage = (100 - distanceFromCenter) * _ammoDamage[_vm->_settings->getAmmoType()] / 100; @@ -205,14 +205,25 @@ 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]); +void Combat::save(SaveFileWriteStream &f) { + f.writeBool(_active); + f.writeBool(_enabled); + for (int i = 0; i != kSoundCount; ++i) { + f.writeInt(_hitSoundId[i]); } - for (int i = 0; i != 9; ++i) { - f.write(_missSoundId[i]); + for (int i = 0; i != kSoundCount; ++i) { + f.writeInt(_missSoundId[i]); + } +} + +void Combat::load(SaveFileReadStream &f) { + _active = f.readBool(); + _enabled = f.readBool(); + for (int i = 0; i != kSoundCount; ++i) { + _hitSoundId[i] = f.readInt(); + } + for (int i = 0; i != kSoundCount; ++i) { + _missSoundId[i] = f.readInt(); } } diff --git a/engines/bladerunner/combat.h b/engines/bladerunner/combat.h index 670f580011..e0038d677e 100644 --- a/engines/bladerunner/combat.h +++ b/engines/bladerunner/combat.h @@ -30,7 +30,8 @@ namespace BladeRunner { class BladeRunnerEngine; -class SaveFile; +class SaveFileReadStream; +class SaveFileWriteStream; class Vector3; class Combat { @@ -90,7 +91,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); + void save(SaveFileWriteStream &f); + void load(SaveFileReadStream &f); }; } // End of namespace BladeRunner diff --git a/engines/bladerunner/crimes_database.cpp b/engines/bladerunner/crimes_database.cpp index 131c871654..e9faa22b41 100644 --- a/engines/bladerunner/crimes_database.cpp +++ b/engines/bladerunner/crimes_database.cpp @@ -29,7 +29,7 @@ namespace BladeRunner { -CrimesDatabase::CrimesDatabase(BladeRunnerEngine *vm, const char *cluesResource, int crimeCount) { +CrimesDatabase::CrimesDatabase(BladeRunnerEngine *vm, const Common::String &cluesResource, int crimeCount) { _crimeCount = crimeCount; _crimes.resize(_crimeCount); @@ -71,10 +71,16 @@ const char *CrimesDatabase::getClueText(int clueId) const { return _cluesText->getText(clueId); } -void CrimesDatabase::save(SaveFile &f) { +void CrimesDatabase::save(SaveFileWriteStream &f) { for (int i = 0; i < _crimeCount; ++i) { uint8 c = _crimes[i]; - f.write(c); + f.writeByte(c); + } +} + +void CrimesDatabase::load(SaveFileReadStream &f) { + for (int i = 0; i < _crimeCount; ++i) { + _crimes[i] = f.readByte(); } } diff --git a/engines/bladerunner/crimes_database.h b/engines/bladerunner/crimes_database.h index 1374d52424..9bb83f148f 100644 --- a/engines/bladerunner/crimes_database.h +++ b/engines/bladerunner/crimes_database.h @@ -28,7 +28,8 @@ namespace BladeRunner { class BladeRunnerEngine; -class SaveFile; +class SaveFileReadStream; +class SaveFileWriteStream; class TextResource; class CrimesDatabase { @@ -38,7 +39,7 @@ class CrimesDatabase { TextResource *_cluesText; public: - CrimesDatabase(BladeRunnerEngine *vm, const char *cluesResource, int crimeCount); + CrimesDatabase(BladeRunnerEngine *vm, const Common::String &cluesResource, int crimeCount); ~CrimesDatabase(); void setCrime(int clueId, int crimeId); @@ -49,7 +50,8 @@ public: const char *getClueText(int clueId) const; - void save(SaveFile &f); + void save(SaveFileWriteStream &f); + void load(SaveFileReadStream &f); }; } // End of namespace BladeRunner diff --git a/engines/bladerunner/debugger.cpp b/engines/bladerunner/debugger.cpp index 2c9b7e6f74..87ab5d2cc1 100644 --- a/engines/bladerunner/debugger.cpp +++ b/engines/bladerunner/debugger.cpp @@ -386,9 +386,9 @@ void Debugger::drawSceneObjects() { for (int i = 0; i < count; i++) { SceneObjects::SceneObject *sceneObject = &_vm->_sceneObjects->_sceneObjects[_vm->_sceneObjects->_sceneObjectsSortedByDistance[i]]; - const BoundingBox *bbox = sceneObject->boundingBox; + const BoundingBox &bbox = sceneObject->boundingBox; Vector3 a, b; - bbox->getXYZ(&a.x, &a.y, &a.z, &b.x, &b.y, &b.z); + bbox.getXYZ(&a.x, &a.y, &a.z, &b.x, &b.y, &b.z); Vector3 pos = _vm->_view->calculateScreenPosition(0.5 * (a + b)); int color; @@ -398,7 +398,7 @@ void Debugger::drawSceneObjects() { case kSceneObjectTypeActor: color = 0x7C00; // 11111 00000 00000; drawBBox(a, b, _vm->_view, &_vm->_surfaceFront, color); - _vm->_surfaceFront.frameRect(*sceneObject->screenRectangle, color); + _vm->_surfaceFront.frameRect(sceneObject->screenRectangle, color); _vm->_mainFont->drawColor(_vm->_textActorNames->getText(sceneObject->id - kSceneObjectOffsetActors), _vm->_surfaceFront, pos.x, pos.y, color); break; case kSceneObjectTypeItem: @@ -406,7 +406,7 @@ void Debugger::drawSceneObjects() { char itemText[40]; drawBBox(a, b, _vm->_view, &_vm->_surfaceFront, color); sprintf(itemText, "item %i", sceneObject->id - kSceneObjectOffsetItems); - _vm->_surfaceFront.frameRect(*sceneObject->screenRectangle, color); + _vm->_surfaceFront.frameRect(sceneObject->screenRectangle, color); _vm->_mainFont->drawColor(itemText, _vm->_surfaceFront, pos.x, pos.y, color); break; case kSceneObjectTypeObject: @@ -417,7 +417,7 @@ void Debugger::drawSceneObjects() { color = 0x03E0; // 00000 11111 00000; } drawBBox(a, b, _vm->_view, &_vm->_surfaceFront, color); - _vm->_surfaceFront.frameRect(*sceneObject->screenRectangle, color); + _vm->_surfaceFront.frameRect(sceneObject->screenRectangle, color); _vm->_mainFont->drawColor(_vm->_scene->objectGetName(sceneObject->id - kSceneObjectOffsetObjects), _vm->_surfaceFront, pos.x, pos.y, color); break; } diff --git a/engines/bladerunner/dialogue_menu.cpp b/engines/bladerunner/dialogue_menu.cpp index 7b7223fe94..744183a51f 100644 --- a/engines/bladerunner/dialogue_menu.cpp +++ b/engines/bladerunner/dialogue_menu.cpp @@ -365,27 +365,51 @@ bool DialogueMenu::waitingForInput() const { return _waitingForInput; } -void DialogueMenu::save(SaveFile &f) { - f.write(_isVisible); - f.write(_waitingForInput); - f.write(_selectedItemIndex); - f.write(_listSize); +void DialogueMenu::save(SaveFileWriteStream &f) { + f.writeBool(_isVisible); + f.writeBool(_waitingForInput); + f.writeInt(_selectedItemIndex); + f.writeInt(_listSize); - f.write(_neverRepeatListSize); + f.writeInt(_neverRepeatListSize); for (int i = 0; i < 100; ++i) { - f.write(_neverRepeatValues[i]); + f.writeInt(_neverRepeatValues[i]); } for (int i = 0; i < 100; ++i) { - f.write(_neverRepeatWasSelected[i]); + f.writeBool(_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); + f.writeStringSz(_items[i].text, 50); + f.writeInt(_items[i].answerValue); + f.writeInt(_items[i].colorIntensity); + f.writeInt(_items[i].priorityPolite); + f.writeInt(_items[i].priorityNormal); + f.writeInt(_items[i].prioritySurly); + f.writeInt(_items[i].isDone); + } +} + +void DialogueMenu::load(SaveFileReadStream &f) { + _isVisible = f.readBool(); + _waitingForInput = f.readBool(); + _selectedItemIndex = f.readInt(); + _listSize = f.readInt(); + + _neverRepeatListSize = f.readInt(); + for (int i = 0; i < 100; ++i) { + _neverRepeatValues[i] = f.readInt(); + } + for (int i = 0; i < 100; ++i) { + _neverRepeatWasSelected[i] = f.readBool(); + } + for (int i = 0; i < 10; ++i) { + _items[i].text = f.readStringSz(50); + _items[i].answerValue = f.readInt(); + _items[i].colorIntensity = f.readInt(); + _items[i].priorityPolite = f.readInt(); + _items[i].priorityNormal = f.readInt(); + _items[i].prioritySurly = f.readInt(); + _items[i].isDone = f.readInt(); } } diff --git a/engines/bladerunner/dialogue_menu.h b/engines/bladerunner/dialogue_menu.h index b06cf9dfb6..6dfd3efdc6 100644 --- a/engines/bladerunner/dialogue_menu.h +++ b/engines/bladerunner/dialogue_menu.h @@ -33,7 +33,8 @@ namespace BladeRunner { class BladeRunnerEngine; -class SaveFile; +class SaveFileReadStream; +class SaveFileWriteStream; class TextResource; class DialogueMenu { @@ -97,16 +98,14 @@ public: void mouseUp(); bool waitingForInput() const; + void save(SaveFileWriteStream &f); + void load(SaveFileReadStream &f); + private: bool showAt(int x, int y); int getAnswerIndex(int answer) const; 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/fog.cpp b/engines/bladerunner/fog.cpp index fff27b0558..c732b598c2 100644 --- a/engines/bladerunner/fog.cpp +++ b/engines/bladerunner/fog.cpp @@ -27,7 +27,6 @@ namespace BladeRunner { Fog::Fog() { - _name[0] = 0; _frameCount = 0; _animatedParameters = 0; _fogDensity = 0.0f; @@ -55,7 +54,9 @@ Fog::~Fog() { int Fog::readCommon(Common::ReadStream *stream) { int offset = stream->readUint32LE(); - stream->read(_name, 20); + char buf[20]; + stream->read(buf, sizeof(buf)); + _name = buf; _fogColor.r = stream->readFloatLE(); _fogColor.g = stream->readFloatLE(); _fogColor.b = stream->readFloatLE(); diff --git a/engines/bladerunner/fog.h b/engines/bladerunner/fog.h index 95ac550fd1..e952d24165 100644 --- a/engines/bladerunner/fog.h +++ b/engines/bladerunner/fog.h @@ -38,7 +38,8 @@ class Fog { friend class SetEffects; protected: - char _name[20]; + Common::String _name; + int _frameCount; int _animatedParameters; Matrix4x3 _matrix; diff --git a/engines/bladerunner/game_flags.cpp b/engines/bladerunner/game_flags.cpp index 1e0b58378e..6fdcb89363 100644 --- a/engines/bladerunner/game_flags.cpp +++ b/engines/bladerunner/game_flags.cpp @@ -73,9 +73,15 @@ bool GameFlags::query(int flag) const { return !!(_flags[flag / 32] & (1 << (flag % 32))); } -void GameFlags::save(SaveFile &f) { +void GameFlags::save(SaveFileWriteStream &f) { for (int i = 0; i != _flagCount / 32 + 1; ++i) { - f.write(_flags[i]); + f.writeUint32LE(_flags[i]); + } +} + +void GameFlags::load(SaveFileReadStream &f) { + for (int i = 0; i != _flagCount / 32 + 1; ++i) { + _flags[i] = f.readUint32LE(); } } diff --git a/engines/bladerunner/game_flags.h b/engines/bladerunner/game_flags.h index b409e858b0..837537f689 100644 --- a/engines/bladerunner/game_flags.h +++ b/engines/bladerunner/game_flags.h @@ -27,7 +27,8 @@ namespace BladeRunner { -class SaveFile; +class SaveFileReadStream; +class SaveFileWriteStream; class GameFlags { uint32 *_flags; @@ -43,7 +44,8 @@ public: void reset(int flag); bool query(int flag) const; - void save(SaveFile &f); + void save(SaveFileWriteStream &f); + void load(SaveFileReadStream &f); }; } // End of namespace BladeRunner diff --git a/engines/bladerunner/game_info.cpp b/engines/bladerunner/game_info.cpp index db664c0f2d..9dc261bc31 100644 --- a/engines/bladerunner/game_info.cpp +++ b/engines/bladerunner/game_info.cpp @@ -31,10 +31,6 @@ namespace BladeRunner { GameInfo::GameInfo(BladeRunnerEngine *vm) { _vm = vm; - _sceneNames = nullptr; - _sfxTracks = nullptr; - _musicTracks = nullptr; - _outtakes = nullptr; _actorCount = 0; _playerId = 0; _flagCount = 0; @@ -53,18 +49,12 @@ GameInfo::GameInfo(BladeRunnerEngine *vm) { _fleeWaypointCount = 0; } -GameInfo::~GameInfo() { - delete[] _sceneNames; - delete[] _sfxTracks; - delete[] _musicTracks; - delete[] _outtakes; -} - bool GameInfo::open(const Common::String &name) { Common::SeekableReadStream *s = _vm->getResourceStream(name); - if (!s) + if (!s) { return false; + } uint32 unk; _actorCount = s->readUint32LE(); /* 00 */ @@ -88,25 +78,33 @@ bool GameInfo::open(const Common::String &name) { (void)unk; - _sceneNames = new char[_sceneNamesCount][5]; - for (uint32 i = 0; i != _sceneNamesCount; ++i) - s->read(_sceneNames[i], 5); + char buf[9]; + + _sceneNames.resize(_sceneNamesCount); + for (uint32 i = 0; i != _sceneNamesCount; ++i) { + s->read(buf, 5); + _sceneNames[i] = buf; + } - _sfxTracks = new char[_sfxTrackCount][13]; + _sfxTracks.resize(_sfxTrackCount); for (uint32 i = 0; i != _sfxTrackCount; ++i) { - s->read(_sfxTracks[i], 9); - strcat(_sfxTracks[i], ".AUD"); + s->read(buf, 9); + _sfxTracks[i] = buf; + _sfxTracks[i] += ".AUD"; } - _musicTracks = new char[_musicTrackCount][13]; + _musicTracks.resize(_musicTrackCount); for (uint32 i = 0; i != _musicTrackCount; ++i) { - s->read(_musicTracks[i], 9); - strcat(_musicTracks[i], ".AUD"); + s->read(buf, 9); + _musicTracks[i] = buf; + _musicTracks[i] += ".AUD"; } - _outtakes = new char[_outtakeCount][13]; - for (uint32 i = 0; i != _outtakeCount; ++i) - s->read(_outtakes[i], 9); + _outtakes.resize(_outtakeCount); + for (uint32 i = 0; i != _outtakeCount; ++i) { + s->read(buf, 9); + _outtakes[i] = buf; + } #if BLADERUNNER_DEBUG_CONSOLE debug("\nScene names\n----------------"); @@ -135,34 +133,38 @@ bool GameInfo::open(const Common::String &name) { return !err; } -const char *GameInfo::getSceneName(int i) const { +const Common::String &GameInfo::getSceneName(int i) const { if (i < 0 || i >= (int)_sceneNamesCount) { warning("GameInfo::getSceneName: unknown id \"%i\"", i); - return nullptr; + static Common::String str("UNKNOWN_SCENE"); + return str; } return _sceneNames[i]; } -const char *GameInfo::getSfxTrack(int i) const { +const Common::String &GameInfo::getSfxTrack(int i) const { if (i < 0 || i >= (int)_sfxTrackCount) { warning("GameInfo::getSfxTrack: unknown id \"%i\"", i); - return nullptr; + static Common::String str("UNKNOWN_SFX_TRACK"); + return str; } return _sfxTracks[i]; } -const char *GameInfo::getMusicTrack(int i) const { +const Common::String &GameInfo::getMusicTrack(int i) const { if (i < 0 || i >= (int)_musicTrackCount) { warning("GameInfo::getMusicTrack: unknown id \"%i\"", i); - return nullptr; + static Common::String str("UNKNOWN_MUSIC_TRACK"); + return str; } return _musicTracks[i]; } -const char *GameInfo::getOuttake(int i) const { +const Common::String &GameInfo::getOuttake(int i) const { if (i < 0 || i >= (int)_outtakeCount) { warning("GameInfo::getOuttake: unknown id \"%i\"", i); - return nullptr; + static Common::String str("UNKNOWN_OUTTAKE"); + return str; } return _outtakes[i]; } diff --git a/engines/bladerunner/game_info.h b/engines/bladerunner/game_info.h index bc7fc1eeec..857efa9e0b 100644 --- a/engines/bladerunner/game_info.h +++ b/engines/bladerunner/game_info.h @@ -23,6 +23,7 @@ #ifndef BLADERUNNER_GAME_INFO_H #define BLADERUNNER_GAME_INFO_H +#include "common/array.h" #include "common/str.h" namespace BladeRunner { @@ -49,14 +50,13 @@ class GameInfo { uint32 _coverWaypointCount; uint32 _fleeWaypointCount; - char (*_sceneNames)[5]; - char (*_sfxTracks)[13]; - char (*_musicTracks)[13]; - char (*_outtakes)[13]; + Common::Array<Common::String> _sceneNames; + Common::Array<Common::String> _sfxTracks; + Common::Array<Common::String> _musicTracks; + Common::Array<Common::String> _outtakes; public: GameInfo(BladeRunnerEngine *vm); - ~GameInfo(); bool open(const Common::String &name); @@ -77,10 +77,10 @@ public: uint32 getCoverWaypointCount() const { return _coverWaypointCount; } uint32 getFleeWaypointCount() const { return _fleeWaypointCount; } - const char *getSceneName(int i) const; - const char *getSfxTrack(int i) const; - const char *getMusicTrack(int i) const; - const char *getOuttake(int i) const; + const Common::String &getSceneName(int i) const; + const Common::String &getSfxTrack(int i) const; + const Common::String &getMusicTrack(int i) const; + const Common::String &getOuttake(int i) const; }; } // End of namespace BladeRunner diff --git a/engines/bladerunner/item.cpp b/engines/bladerunner/item.cpp index bf09efb0e6..9aa50e366f 100644 --- a/engines/bladerunner/item.cpp +++ b/engines/bladerunner/item.cpp @@ -174,26 +174,48 @@ 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); +void Item::save(SaveFileWriteStream &f) { + f.writeInt(_setId); + f.writeInt(_itemId); + f.writeBoundingBox(_boundingBox); + f.writeRect(_screenRectangle); + f.writeInt(_animationId); + f.writeVector3(_position); + f.writeInt(_facing); + f.writeFloat(_angle); + f.writeInt(_width); + f.writeInt(_height); + f.writeInt(_screenX); + f.writeInt(_screenY); + f.writeFloat(_depth); + f.writeBool(_isTarget); + f.writeBool(_isSpinning); + f.writeInt(_facingChange); + f.writeFloat(0.0f); // _viewAngle + f.writeBool(_isVisible); + f.writeBool(_isPoliceMazeEnemy); +} + +void Item::load(SaveFileReadStream &f) { + _setId = f.readInt(); + _itemId = f.readInt(); + _boundingBox = f.readBoundingBox(); + _screenRectangle = f.readRect(); + _animationId = f.readInt(); + _position = f.readVector3(); + _facing = f.readInt(); + _angle = f.readFloat(); + _width = f.readInt(); + _height = f.readInt(); + _screenX = f.readInt(); + _screenY = f.readInt(); + _depth = f.readFloat(); + _isTarget = f.readBool(); + _isSpinning = f.readBool(); + _facingChange = f.readInt(); + f.skip(4); + _isVisible = f.readBool(); + _isPoliceMazeEnemy = f.readBool(); } } // End of namespace BladeRunner diff --git a/engines/bladerunner/item.h b/engines/bladerunner/item.h index bf07a118bd..9a28d9b1d4 100644 --- a/engines/bladerunner/item.h +++ b/engines/bladerunner/item.h @@ -32,7 +32,8 @@ namespace BladeRunner { class BladeRunnerEngine; class Items; -class SaveFile; +class SaveFileReadStream; +class SaveFileWriteStream; class Item { friend class Items; @@ -66,8 +67,8 @@ public: void setXYZ(Vector3 position); void getWidthHeight(int *width, int *height) const; - BoundingBox *getBoundingBox() { return &_boundingBox; } - Common::Rect *getScreenRectangle() { return &_screenRectangle; } + const BoundingBox &getBoundingBox() { return _boundingBox; } + const Common::Rect &getScreenRectangle() { return _screenRectangle; } int getFacing() const { return _facing; } void setFacing(int facing) { _facing = facing; } @@ -86,7 +87,8 @@ public: bool isUnderMouse(int mouseX, int mouseY) const; - void save(SaveFile &f); + void save(SaveFileWriteStream &f); + void load(SaveFileReadStream &f); }; } diff --git a/engines/bladerunner/items.cpp b/engines/bladerunner/items.cpp index 7fe769cb93..caae3ae683 100644 --- a/engines/bladerunner/items.cpp +++ b/engines/bladerunner/items.cpp @@ -89,7 +89,7 @@ bool Items::addToWorld(int itemId, int animationId, int setId, Vector3 position, item->setup(itemId, setId, animationId, position, facing, height, width, isTargetFlag, isVisible, isPoliceMazeEnemy); if (addToSetFlag && setId == _vm->_scene->getSetId()) { - return _vm->_sceneObjects->addItem(itemId + kSceneObjectOffsetItems, &item->_boundingBox, &item->_screenRectangle, isTargetFlag, isVisible); + return _vm->_sceneObjects->addItem(itemId + kSceneObjectOffsetItems, item->_boundingBox, item->_screenRectangle, isTargetFlag, isVisible); } return true; } @@ -102,7 +102,7 @@ bool Items::addToSet(int setId) { for (int i = 0; i < itemCount; i++) { Item *item = _items[i]; if (item->_setId == setId) { - _vm->_sceneObjects->addItem(item->_itemId + kSceneObjectOffsetItems, &item->_boundingBox, &item->_screenRectangle, item->isTarget(), item->_isVisible); + _vm->_sceneObjects->addItem(item->_itemId + kSceneObjectOffsetItems, item->_boundingBox, item->_screenRectangle, item->isTarget(), item->_isVisible); } } return true; @@ -184,19 +184,19 @@ void Items::setIsObstacle(int itemId, bool val) { _vm->_sceneObjects->setIsClickable(itemId + kSceneObjectOffsetItems, val); } -BoundingBox *Items::getBoundingBox(int itemId) { +const BoundingBox &Items::getBoundingBox(int itemId) { int itemIndex = findItem(itemId); - if (itemIndex == -1) { - return nullptr; - } + // if (itemIndex == -1) { + // return nullptr; + // } return _items[itemIndex]->getBoundingBox(); } -Common::Rect *Items::getScreenRectangle(int itemId) { +const Common::Rect &Items::getScreenRectangle(int itemId) { int itemIndex = findItem(itemId); - if (itemIndex == -1) { - return nullptr; - } + // if (itemIndex == -1) { + // return nullptr; + // } return _items[itemIndex]->getScreenRectangle(); } @@ -243,10 +243,10 @@ int Items::findItem(int itemId) const { return -1; } -void Items::save(SaveFile &f) { +void Items::save(SaveFileWriteStream &f) { int size = (int)_items.size(); - f.write(size); + f.writeInt(size); int i; for (i = 0; i != size; ++i) { _items[i]->save(f); @@ -258,4 +258,24 @@ void Items::save(SaveFile &f) { } } +void Items::load(SaveFileReadStream &f) { + for (int i = _items.size() - 1; i >= 0; i--) { + delete _items.remove_at(i); + } + _items.resize(f.readInt()); + + int size = (int)_items.size(); + + int i; + for (i = 0; i != size; ++i) { + _items[i] = new Item(_vm); + _items[i]->load(f); + } + + // Always read out 100 items + for (; i != 100; ++i) { + f.skip(0x174); // bbox + rect + 18 float fields + } +} + } // End of namespace BladeRunner diff --git a/engines/bladerunner/items.h b/engines/bladerunner/items.h index cc9af734b2..e3971057bb 100644 --- a/engines/bladerunner/items.h +++ b/engines/bladerunner/items.h @@ -30,7 +30,8 @@ namespace BladeRunner { -class SaveFile; +class SaveFileReadStream; +class SaveFileWriteStream; class Items { BladeRunnerEngine *_vm; @@ -59,14 +60,16 @@ public: bool isVisible(int itemId) const; int findTargetUnderMouse(int mouseX, int mouseY) const; - BoundingBox *getBoundingBox(int itemId); - Common::Rect *getScreenRectangle(int itemId); + const BoundingBox &getBoundingBox(int itemId); + const Common::Rect &getScreenRectangle(int itemId); int getFacing(int itemId) const; void setFacing(int itemId, int facing); void spinInWorld(int itemId); - void save(SaveFile &f); + void save(SaveFileWriteStream &f); + void load(SaveFileReadStream &f); + private: int findItem(int itemId) const; }; diff --git a/engines/bladerunner/light.cpp b/engines/bladerunner/light.cpp index 615958281a..2231e0460e 100644 --- a/engines/bladerunner/light.cpp +++ b/engines/bladerunner/light.cpp @@ -69,7 +69,9 @@ void Light::read(Common::ReadStream *stream, int frameCount, int frame, int anim int size = stream->readUint32LE(); size = size - 32; - stream->read(_name, 20); + char buf[20]; + stream->read(buf, sizeof(buf)); + _name = buf; _animatedParameters = stream->readUint32LE(); diff --git a/engines/bladerunner/light.h b/engines/bladerunner/light.h index 1ef9f3082c..31e40e0b45 100644 --- a/engines/bladerunner/light.h +++ b/engines/bladerunner/light.h @@ -42,7 +42,8 @@ class Light { friend class SliceRenderer; protected: - char _name[20]; + Common::String _name; + int _frameCount; int _animated; int _animatedParameters; diff --git a/engines/bladerunner/module.mk b/engines/bladerunner/module.mk index f4bf926aa0..5fb39b8289 100644 --- a/engines/bladerunner/module.mk +++ b/engines/bladerunner/module.mk @@ -40,8 +40,6 @@ MODULE_OBJS = \ obstacles.o \ outtake.o \ overlays.o \ - police_maze.o \ - police_maze_track.o \ regions.o \ savefile.o \ scene.o \ diff --git a/engines/bladerunner/movement_track.cpp b/engines/bladerunner/movement_track.cpp index 5a6407ed3a..322d92ef31 100644 --- a/engines/bladerunner/movement_track.cpp +++ b/engines/bladerunner/movement_track.cpp @@ -109,17 +109,31 @@ 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) { +void MovementTrack::save(SaveFileWriteStream &f) { + f.writeInt(_currentIndex); + f.writeInt(_lastIndex); + f.writeBool(_hasNext); + f.writeBool(_paused); + for (int i = 0; i < kSize; ++i) { Entry &e = _entries[i]; - f.write(e.waypointId); - f.write(e.delay); - f.write(e.angle); - f.write(e.run); + f.writeInt(e.waypointId); + f.writeInt(e.delay); + f.writeInt(e.angle); + f.writeBool(e.run); + } +} + +void MovementTrack::load(SaveFileReadStream &f) { + _currentIndex = f.readInt(); + _lastIndex = f.readInt(); + _hasNext = f.readBool(); + _paused = f.readBool(); + for (int i = 0; i < kSize; ++i) { + Entry &e = _entries[i]; + e.waypointId = f.readInt(); + e.delay = f.readInt(); + e.angle = f.readInt(); + e.run = f.readBool(); } } diff --git a/engines/bladerunner/movement_track.h b/engines/bladerunner/movement_track.h index 2d59fd98c7..2eab4cdedb 100644 --- a/engines/bladerunner/movement_track.h +++ b/engines/bladerunner/movement_track.h @@ -29,7 +29,8 @@ namespace BladeRunner { class BladeRunnerEngine; class BoundingBox; -class SaveFile; +class SaveFileReadStream; +class SaveFileWriteStream; class MovementTrack { static const int kSize = 100; @@ -60,7 +61,9 @@ public: bool hasNext() const; bool next(int *waypointId, int *delay, int *angle, bool *run); - void save(SaveFile &f); + void save(SaveFileWriteStream &f); + void load(SaveFileReadStream &f); + private: void reset(); }; diff --git a/engines/bladerunner/music.cpp b/engines/bladerunner/music.cpp index 818d412ba9..05412dd8e0 100644 --- a/engines/bladerunner/music.cpp +++ b/engines/bladerunner/music.cpp @@ -26,6 +26,7 @@ #include "bladerunner/aud_stream.h" #include "bladerunner/bladerunner.h" #include "bladerunner/game_info.h" +#include "bladerunner/savefile.h" #include "common/timer.h" @@ -167,6 +168,68 @@ void Music::playSample() { } } +void Music::save(SaveFileWriteStream &f) { + f.writeBool(_isNextPresent); + f.writeBool(_isPlaying); + f.writeBool(_isPaused); + f.writeStringSz(_current.name, 13); + f.writeInt(_current.volume); + f.writeInt(_current.pan); + f.writeInt(_current.timeFadeIn); + f.writeInt(_current.timePlay); + f.writeInt(_current.loop); + f.writeInt(_current.timeFadeOut); + f.writeStringSz(_next.name, 13); + f.writeInt(_next.volume); + f.writeInt(_next.pan); + f.writeInt(_next.timeFadeIn); + f.writeInt(_next.timePlay); + f.writeInt(_next.loop); + f.writeInt(_next.timeFadeOut); +} + +void Music::load(SaveFileReadStream &f) { + _isNextPresent = f.readBool(); + _isPlaying = f.readBool(); + _isPaused = f.readBool(); + _current.name = f.readStringSz(13); + _current.volume = f.readInt(); + _current.pan = f.readInt(); + _current.timeFadeIn = f.readInt(); + _current.timePlay = f.readInt(); + _current.loop = f.readInt(); + _current.timeFadeOut = f.readInt(); + _next.name = f.readStringSz(13); + _next.volume = f.readInt(); + _next.pan = f.readInt(); + _next.timeFadeIn = f.readInt(); + _next.timePlay = f.readInt(); + _next.loop = f.readInt(); + _next.timeFadeOut = f.readInt(); + + stop(2); + if (_isPlaying) { + if (_channel == -1) { + play(_current.name, + _current.volume, + _current.pan, + _current.timeFadeIn, + _current.timePlay, + _current.loop, + _current.timeFadeOut); + } else { + _isNextPresent = true; + _next.name = _current.name; + _next.volume = _current.volume; + _next.pan = _current.pan; + _next.timeFadeIn = _current.timeFadeIn; + _next.timePlay = _current.timePlay; + _next.loop = _current.loop; + _next.timeFadeOut = _current.timeFadeOut; + } + } +} + void Music::adjustVolume(int volume, int delay) { if (_channel >= 0) { _vm->_audioMixer->adjustVolume(_channel, volume, delay); diff --git a/engines/bladerunner/music.h b/engines/bladerunner/music.h index de19942a20..b4dc284def 100644 --- a/engines/bladerunner/music.h +++ b/engines/bladerunner/music.h @@ -30,6 +30,8 @@ namespace BladeRunner { class AudStream; class BladeRunnerEngine; +class SaveFileReadStream; +class SaveFileWriteStream; class Music { struct Track { @@ -47,9 +49,9 @@ class Music { Common::Mutex _mutex; int _musicVolume; int _channel; - int _isNextPresent; - int _isPlaying; - int _isPaused; + bool _isNextPresent; + bool _isPlaying; + bool _isPaused; Track _current; Track _next; byte *_data; @@ -68,6 +70,9 @@ public: int getVolume(); void playSample(); + void save(SaveFileWriteStream &f); + void load(SaveFileReadStream &f); + private: void adjustVolume(int volume, int delay); void adjustPan(int pan, int delay); diff --git a/engines/bladerunner/obstacles.cpp b/engines/bladerunner/obstacles.cpp index 603d514513..ada41df7b3 100644 --- a/engines/bladerunner/obstacles.cpp +++ b/engines/bladerunner/obstacles.cpp @@ -68,28 +68,64 @@ void Obstacles::backup() { void Obstacles::restore() {} -void Obstacles::save(SaveFile &f) { - f.write(_backup); - f.write(_count); +void Obstacles::save(SaveFileWriteStream &f) { + f.writeBool(_backup); + f.writeInt(_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); + f.writeBool(p.isPresent); + f.writeInt(p.verticeCount); + f.writeFloat(p.left); + f.writeFloat(p.bottom); + f.writeFloat(p.right); + f.writeFloat(p.top); for (int j = 0; j < kPolygonVertexCount; ++j) { - f.write(p.vertices[j]); + f.writeVector2(p.vertices[j]); } for (int j = 0; j < kPolygonVertexCount; ++j) { - f.write(p.vertexType[j]); + f.writeInt(p.vertexType[j]); } } for (int i = 0; i < kVertexCount; ++i) { - f.write(_vertices[i]); + f.writeVector2(_vertices[i]); } - f.write(_verticeCount); + f.writeInt(_verticeCount); +} + +void Obstacles::load(SaveFileReadStream &f) { + for (int i = 0; i < kPolygonCount; ++i) { + _polygons[i].isPresent = false; + _polygons[i].verticeCount = 0; + _polygonsBackup[i].isPresent = false; + _polygonsBackup[i].verticeCount = 0; + } + + _backup = f.readBool(); + _count = f.readInt(); + for (int i = 0; i < _count; ++i) { + Polygon &p = _polygonsBackup[i]; + p.isPresent = f.readBool(); + p.verticeCount = f.readInt(); + p.left = f.readFloat(); + p.bottom = f.readFloat(); + p.right = f.readFloat(); + p.top = f.readFloat(); + for (int j = 0; j < kPolygonVertexCount; ++j) { + p.vertices[j] = f.readVector2(); + } + for (int j = 0; j < kPolygonVertexCount; ++j) { + p.vertexType[j] = f.readInt(); + } + } + + for (int i = 0; i < kPolygonCount; ++i) { + _polygons[i] = _polygonsBackup[i]; + } + + for (int i = 0; i < kVertexCount; ++i) { + _vertices[i] = f.readVector2(); + } + _verticeCount = f.readInt(); } diff --git a/engines/bladerunner/obstacles.h b/engines/bladerunner/obstacles.h index fc06fe6920..b50c51e64c 100644 --- a/engines/bladerunner/obstacles.h +++ b/engines/bladerunner/obstacles.h @@ -28,7 +28,8 @@ namespace BladeRunner { class BladeRunnerEngine; -class SaveFile; +class SaveFileReadStream; +class SaveFileWriteStream; class Obstacles { static const int kVertexCount = 150; @@ -64,7 +65,9 @@ public: bool find(const Vector3 &from, const Vector3 &to, Vector3 *next) const; void backup(); void restore(); - void save(SaveFile &f); + + void save(SaveFileWriteStream &f); + void load(SaveFileReadStream &f); }; } // End of namespace BladeRunner diff --git a/engines/bladerunner/overlays.cpp b/engines/bladerunner/overlays.cpp index 0f011ad4d1..65ba83f15d 100644 --- a/engines/bladerunner/overlays.cpp +++ b/engines/bladerunner/overlays.cpp @@ -59,8 +59,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); + int32 hash = MIXArchive::getHash(name); + int index = findByHash(hash); if (index < 0) { index = findEmpty(); if (index < 0) { @@ -68,7 +68,7 @@ int Overlays::play(const Common::String &name, int loopId, bool loopForever, boo } _videos[index].loaded = true; _videos[index].name = name; - _videos[index].id = id; + _videos[index].hash = hash; _videos[index].vqaPlayer = new VQAPlayer(_vm, &_vm->_surfaceFront); // repeat forever @@ -87,8 +87,7 @@ int Overlays::play(const Common::String &name, int loopId, bool loopForever, boo } void Overlays::remove(const Common::String &name) { - int id = mix_id(name); - int index = findById(id); + int index = findByHash(MIXArchive::getHash(name)); if (index >= 0) { resetSingle(index); } @@ -113,9 +112,9 @@ void Overlays::tick() { } } -int Overlays::findById(int32 id) const { +int Overlays::findByHash(int32 hash) const { for (int i = 0; i < kOverlayVideos; ++i) { - if (_videos[i].loaded && _videos[i].id == id) { + if (_videos[i].loaded && _videos[i].hash == hash) { return i; } } @@ -138,7 +137,7 @@ void Overlays::resetSingle(int i) { _videos[i].vqaPlayer = nullptr; } _videos[i].loaded = false; - _videos[i].id = 0; + _videos[i].hash = 0; _videos[i].field2 = -1; _videos[i].name.clear(); } @@ -147,18 +146,34 @@ void Overlays::reset() { _videos.clear(); } -void Overlays::save(SaveFile &f) { +void Overlays::save(SaveFileWriteStream &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); + f.writeBool(ov.loaded); + 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); + } +} + +void Overlays::load(SaveFileReadStream &f) { + for (int i = 0; i < kOverlayVideos; ++i) { + // 37 bytes per overlay + Video &ov = _videos[i]; + + ov.loaded = f.readBool(); + f.skip(4); // vqaPlayer pointer + ov.vqaPlayer = nullptr; + ov.name = f.readStringSz(13); + ov.hash = f.readSint32LE(); + ov.field0 = f.readInt(); + ov.field1 = f.readInt(); + ov.field2 = f.readInt(); } } diff --git a/engines/bladerunner/overlays.h b/engines/bladerunner/overlays.h index fc8dfa11d4..405acbc264 100644 --- a/engines/bladerunner/overlays.h +++ b/engines/bladerunner/overlays.h @@ -33,7 +33,8 @@ struct Surface; namespace BladeRunner { class BladeRunnerEngine; -class SaveFile; +class SaveFileReadStream; +class SaveFileWriteStream; class VQAPlayer; class Overlays { @@ -43,7 +44,7 @@ class Overlays { bool loaded; VQAPlayer *vqaPlayer; Common::String name; - int32 id; + int32 hash; int field0; int field1; int field2; @@ -62,10 +63,11 @@ public: void removeAll(); void tick(); - void save(SaveFile &f); + void save(SaveFileWriteStream &f); + void load(SaveFileReadStream &f); private: - int findById(int32 id) const; + int findByHash(int32 hash) const; int findEmpty() const; void resetSingle(int i); diff --git a/engines/bladerunner/police_maze.cpp b/engines/bladerunner/police_maze.cpp deleted file mode 100644 index 223171d0be..0000000000 --- a/engines/bladerunner/police_maze.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/* 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 deleted file mode 100644 index 4bd06bb868..0000000000 --- a/engines/bladerunner/police_maze.h +++ /dev/null @@ -1,54 +0,0 @@ -/* 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 deleted file mode 100644 index 988f90499c..0000000000 --- a/engines/bladerunner/police_maze_track.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/* 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 deleted file mode 100644 index 9de7a1b624..0000000000 --- a/engines/bladerunner/police_maze_track.h +++ /dev/null @@ -1,65 +0,0 @@ -/* 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 51b2bae2d7..f74186240b 100644 --- a/engines/bladerunner/regions.cpp +++ b/engines/bladerunner/regions.cpp @@ -101,12 +101,21 @@ void Regions::enable() { _enabled = true; } -void Regions::save(SaveFile &f) { - f.write(_enabled); +void Regions::save(SaveFileWriteStream &f) { + f.writeBool(_enabled); for (int i = 0; i != 10; ++i) { - f.write(_regions[i].rectangle); - f.write(_regions[i].type); - f.write(_regions[i].present); + f.writeRect(_regions[i].rectangle); + f.writeInt(_regions[i].type); + f.writeInt(_regions[i].present); + } +} + +void Regions::load(SaveFileReadStream &f) { + _enabled = f.readBool(); + for (int i = 0; i != 10; ++i) { + _regions[i].rectangle = f.readRect(); + _regions[i].type = f.readInt(); + _regions[i].present = f.readInt(); } } diff --git a/engines/bladerunner/regions.h b/engines/bladerunner/regions.h index ed4dcba1dc..aae3627650 100644 --- a/engines/bladerunner/regions.h +++ b/engines/bladerunner/regions.h @@ -30,7 +30,8 @@ namespace BladeRunner { -class SaveFile; +class SaveFileReadStream; +class SaveFileWriteStream; class Regions { friend class Debugger; @@ -57,7 +58,8 @@ public: void setEnabled(bool enabled); void enable(); - void save(SaveFile &f); + void save(SaveFileWriteStream &f); + void load(SaveFileReadStream &f); }; } // End of namespace BladeRunner diff --git a/engines/bladerunner/savefile.cpp b/engines/bladerunner/savefile.cpp index ff1ff75165..3528a6bb82 100644 --- a/engines/bladerunner/savefile.cpp +++ b/engines/bladerunner/savefile.cpp @@ -30,91 +30,137 @@ namespace BladeRunner { -SaveFile::SaveFile(Common::OutSaveFile *saveFile) - : _saveFile(saveFile), - _stream(DisposeAfterUse::YES) -{ +SaveFileWriteStream::SaveFileWriteStream() + : MemoryWriteStreamDynamic(DisposeAfterUse::YES) { } -void SaveFile::finalize() { - _saveFile->writeUint32LE(_stream.size() + 4); - _saveFile->write(_stream.getData(), _stream.size()); - _saveFile->finalize(); +void SaveFileWriteStream::debug(char *p) { + write(p, strlen(p) + 1); } -void SaveFile::padBytes(int count) { +void SaveFileWriteStream::padBytes(int count) { for (int i = 0; i < count; ++i) { - _stream.writeByte(0); + writeByte(0); } } -void SaveFile::write(bool v) { - _stream.writeUint32LE(v); +void SaveFileWriteStream::writeInt(int v) { + writeUint32LE(v); } -void SaveFile::write(int v) { - _stream.writeUint32LE(v); +void SaveFileWriteStream::writeFloat(int v) { + writeFloatLE(v); } -void SaveFile::write(uint32 v) { - _stream.writeUint32LE(v); +void SaveFileWriteStream::writeBool(bool v) { + writeUint32LE(v); } -void SaveFile::write(byte v) { - _stream.writeByte(v); +void SaveFileWriteStream::writeStringSz(const Common::String &s, int sz) { + assert(s.size() < (uint)sz); + write(s.begin(), s.size()); + padBytes((uint)sz - s.size()); } -void SaveFile::write(float v) { - _stream.writeFloatLE(v); +void SaveFileWriteStream::writeVector2(const Vector2 &v) { + writeFloatLE(v.x); + writeFloatLE(v.y); } -void SaveFile::debug(char *p) { - _stream.write(p, strlen(p) + 1); +void SaveFileWriteStream::writeVector3(const Vector3 &v) { + writeFloatLE(v.x); + writeFloatLE(v.y); + writeFloatLE(v.z); } -void SaveFile::write(char *p, int sz) { - _stream.write(p, sz); +void SaveFileWriteStream::writeRect(const Common::Rect &v) { + writeUint32LE(v.left); + writeUint32LE(v.top); + writeUint32LE(v.right); + writeUint32LE(v.bottom); } -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 SaveFileWriteStream::writeBoundingBox(const BoundingBox &v) { + float x0, y0, z0, x1, y1, z1; + + v.getXYZ(&x0, &y0, &z0, &x1, &y1, &z1); + writeFloatLE(x0); + writeFloatLE(y0); + writeFloatLE(z0); + writeFloatLE(x1); + writeFloatLE(y1); + writeFloatLE(z1); + + // Bounding boxes have a lot of extra data that's never actually used + for (int i = 0; i != 96; ++i) { + writeFloatLE(0.0f); + } } -void SaveFile::write(const Vector2 &v) { - _stream.writeFloatLE(v.x); - _stream.writeFloatLE(v.y); +SaveFileReadStream::SaveFileReadStream(const byte *dataPtr, uint32 dataSize) + : MemoryReadStream(dataPtr, dataSize, DisposeAfterUse::YES) { } -void SaveFile::write(const Vector3 &v) { - _stream.writeFloatLE(v.x); - _stream.writeFloatLE(v.y); - _stream.writeFloatLE(v.z); +int SaveFileReadStream::readInt() { + return readUint32LE(); } -void SaveFile::write(const Common::Rect &v) { - _stream.writeUint32LE(v.left); - _stream.writeUint32LE(v.top); - _stream.writeUint32LE(v.right); - _stream.writeUint32LE(v.bottom); +float SaveFileReadStream::readFloat() { + return readFloatLE(); } -void SaveFile::write(const BoundingBox &v) { +bool SaveFileReadStream::readBool() { + return readUint32LE(); +} + +Common::String SaveFileReadStream::readStringSz(int sz) { + char *buf = (char *)malloc(sz); + read(buf, sz); + Common::String result = buf; + free(buf); + return result; +} + +Vector2 SaveFileReadStream::readVector2() { + Vector2 result; + result.x = readFloatLE(); + result.y = readFloatLE(); + return result; +} + +Vector3 SaveFileReadStream::readVector3() { + Vector3 result; + result.x = readFloatLE(); + result.y = readFloatLE(); + result.z = readFloatLE(); + return result; +} + +Common::Rect SaveFileReadStream::readRect() { + Common::Rect result; + result.left = readUint32LE(); + result.top = readUint32LE(); + result.right = readUint32LE(); + result.bottom = readUint32LE(); + return result; +} + +BoundingBox SaveFileReadStream::readBoundingBox() { 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); + 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 - for (int i = 0; i != 96; ++i) { - _stream.writeFloatLE(0.0f); - } + skip(384); + + return BoundingBox(x0, y0, z0, x1, y1, z1); } + + } // End of namespace BladeRunner diff --git a/engines/bladerunner/savefile.h b/engines/bladerunner/savefile.h index 8c5dc0aa80..4dfdb20bd4 100644 --- a/engines/bladerunner/savefile.h +++ b/engines/bladerunner/savefile.h @@ -27,9 +27,9 @@ #include "common/types.h" namespace Common { - class OutSaveFile; - class String; - struct Rect; +class OutSaveFile; +class String; +struct Rect; } namespace BladeRunner { @@ -38,28 +38,36 @@ class Vector2; class Vector3; class BoundingBox; -class SaveFile { - Common::OutSaveFile *_saveFile; - Common::MemoryWriteStreamDynamic _stream; +class SaveFileWriteStream : public Common::MemoryWriteStreamDynamic { public: - SaveFile(Common::OutSaveFile *saveFile); + SaveFileWriteStream(); - // bool err(); - void finalize(); + void debug(char *p); 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); + + void writeInt(int v); + void writeFloat(int 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); +}; + +class SaveFileReadStream : public Common::MemoryReadStream { +public: + SaveFileReadStream(const byte *dataPtr, uint32 dataSize); + + int readInt(); + float readFloat(); + bool readBool(); + Common::String readStringSz(int sz); + Vector2 readVector2(); + Vector3 readVector3(); + Common::Rect readRect(); + BoundingBox readBoundingBox(); }; } // End of namespace BladeRunner diff --git a/engines/bladerunner/scene.cpp b/engines/bladerunner/scene.cpp index d12c85e56b..fe8dbc7b61 100644 --- a/engines/bladerunner/scene.cpp +++ b/engines/bladerunner/scene.cpp @@ -331,7 +331,7 @@ void Scene::loopStartSpecial(int specialLoopMode, int loopId, bool immediately) } } -int Scene::findObject(const char *objectName) { +int Scene::findObject(const Common::String &objectName) { return _set->findObject(objectName); } @@ -377,7 +377,7 @@ void Scene::objectSetIsTarget(int objectId, bool isTarget, bool sceneLoaded) { } } -const char *Scene::objectGetName(int objectId) { +const Common::String &Scene::objectGetName(int objectId) { return _set->objectGetName(objectId); } @@ -414,20 +414,36 @@ 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); +void Scene::save(SaveFileWriteStream &f) { + f.writeInt(_setId); + f.writeInt(_sceneId); + f.writeInt(_defaultLoop); + f.writeBool(_defaultLoopSet); + f.writeBool(_defaultLoopPreloadedSet); + f.writeInt(_specialLoopMode); + f.writeInt(_specialLoop); + f.writeInt(_nextSetId); + f.writeInt(_nextSceneId); + f.writeInt(_frame); + f.writeVector3(_actorStartPosition); + f.writeInt(_actorStartFacing); + f.writeBool(_playerWalkedIn); +} + +void Scene::load(SaveFileReadStream &f) { + _setId = f.readInt(); + _sceneId = f.readInt(); + _defaultLoop = f.readInt(); + _defaultLoopSet = f.readBool(); + _defaultLoopPreloadedSet = f.readBool(); + _specialLoopMode = f.readInt(); + _specialLoop = f.readInt(); + _nextSetId = f.readInt(); + _nextSceneId = f.readInt(); + _frame = f.readInt(); + _actorStartPosition = f.readVector3(); + _actorStartFacing = f.readInt(); + _playerWalkedIn = f.readBool(); } } // End of namespace BladeRunner diff --git a/engines/bladerunner/scene.h b/engines/bladerunner/scene.h index b1963e8c15..0403cd331e 100644 --- a/engines/bladerunner/scene.h +++ b/engines/bladerunner/scene.h @@ -25,12 +25,15 @@ #include "bladerunner/vector.h" +#include "common/str.h" + namespace BladeRunner { class BladeRunnerEngine; class BoundingBox; class Regions; -class SaveFile; +class SaveFileReadStream; +class SaveFileWriteStream; class Set; class VQAPlayer; @@ -81,16 +84,17 @@ public: bool didPlayerWalkIn() { bool r = _playerWalkedIn; _playerWalkedIn = false; return r; } - int findObject(const char *objectName); + int findObject(const Common::String &objectName); bool objectSetHotMouse(int objectId); bool objectGetBoundingBox(int objectId, BoundingBox *boundingBox); void objectSetIsClickable(int objectId, bool isClickable, bool sceneLoaded); void objectSetIsObstacle(int objectId, bool isObstacle, bool sceneLoaded, bool updateWalkpath); void objectSetIsObstacleAll(bool isObstacle, bool sceneLoaded); void objectSetIsTarget(int objectId, bool isTarget, bool sceneLoaded); - const char *objectGetName(int objectId); + const Common::String &objectGetName(int objectId); - void save(SaveFile &f); + void save(SaveFileWriteStream &f); + void load(SaveFileReadStream &f); private: void loopEnded(int frame, int loopId); diff --git a/engines/bladerunner/scene_objects.cpp b/engines/bladerunner/scene_objects.cpp index f68dccc0dd..6857416197 100644 --- a/engines/bladerunner/scene_objects.cpp +++ b/engines/bladerunner/scene_objects.cpp @@ -65,16 +65,16 @@ void SceneObjects::clear() { _count = 0; } -bool SceneObjects::addActor(int sceneObjectId, BoundingBox *boundingBox, Common::Rect *screenRectangle, bool isClickable, bool isMoving, bool isTarget, bool isRetired) { +bool SceneObjects::addActor(int sceneObjectId, const BoundingBox &boundingBox, const Common::Rect &screenRectangle, bool isClickable, bool isMoving, bool isTarget, bool isRetired) { return addSceneObject(sceneObjectId, kSceneObjectTypeActor, boundingBox, screenRectangle, isClickable, false, 0, isTarget, isMoving, isRetired); } -bool SceneObjects::addObject(int sceneObjectId, BoundingBox *boundingBox, bool isClickable, bool isObstacle, uint8 unknown1, bool isTarget) { +bool SceneObjects::addObject(int sceneObjectId, const BoundingBox &boundingBox, bool isClickable, bool isObstacle, uint8 unknown1, bool isTarget) { Common::Rect rect(-1, -1, -1, -1); - return addSceneObject(sceneObjectId, kSceneObjectTypeObject, boundingBox, &rect, isClickable, isObstacle, unknown1, isTarget, false, false); + return addSceneObject(sceneObjectId, kSceneObjectTypeObject, boundingBox, rect, isClickable, isObstacle, unknown1, isTarget, false, false); } -bool SceneObjects::addItem(int sceneObjectId, BoundingBox *boundingBox, Common::Rect *screenRectangle, bool isTarget, bool isObstacle) { +bool SceneObjects::addItem(int sceneObjectId, const BoundingBox &boundingBox, const Common::Rect &screenRectangle, bool isTarget, bool isObstacle) { return addSceneObject(sceneObjectId, kSceneObjectTypeItem, boundingBox, screenRectangle, isObstacle, 0, 0, isTarget, 0, 0); } @@ -111,7 +111,7 @@ int SceneObjects::findByXYZ(bool *isClickable, bool *isObstacle, bool *isTarget, if ((findClickables && sceneObject->isClickable) || (findObstacles && sceneObject->isObstacle) || (findTargets && sceneObject->isTarget)) { - BoundingBox boundingBox = *sceneObject->boundingBox; + BoundingBox boundingBox = sceneObject->boundingBox; if (sceneObject->type == kSceneObjectTypeActor) { boundingBox.expand(-4.0, 0.0, -4.0, 4.0, 0.0, 4.0); @@ -156,7 +156,7 @@ bool SceneObjects::existsOnXZ(int exceptSceneObjectId, float x, float z, bool mo if (isObstacle && sceneObject->id != exceptSceneObjectId) { float x1, y1, z1, x2, y2, z2; - sceneObject->boundingBox->getXYZ(&x1, &y1, &z1, &x2, &y2, &z2); + sceneObject->boundingBox.getXYZ(&x1, &y1, &z1, &x2, &y2, &z2); if (z1 <= zMax && z2 >= zMin && x1 <= xMax && x2 >= xMin) { return true; } @@ -177,7 +177,7 @@ int SceneObjects::findById(int sceneObjectId) const { return -1; } -bool SceneObjects::addSceneObject(int sceneObjectId, SceneObjectType sceneObjectType, BoundingBox *boundingBox, Common::Rect *screenRectangle, bool isClickable, bool isObstacle, uint8 unknown1, bool isTarget, bool isMoving, bool isRetired) { +bool SceneObjects::addSceneObject(int sceneObjectId, SceneObjectType sceneObjectType, const BoundingBox &boundingBox, const Common::Rect &screenRectangle, bool isClickable, bool isObstacle, uint8 unknown1, bool isTarget, bool isMoving, bool isRetired) { int index = findEmpty(); if (index == -1) { return false; @@ -195,7 +195,7 @@ bool SceneObjects::addSceneObject(int sceneObjectId, SceneObjectType sceneObject _sceneObjects[index].isMoving = isMoving; _sceneObjects[index].isRetired = isRetired; - float centerZ = (_sceneObjects[index].boundingBox->getZ0() + _sceneObjects[index].boundingBox->getZ1()) / 2.0f; + float centerZ = (_sceneObjects[index].boundingBox.getZ0() + _sceneObjects[index].boundingBox.getZ1()) / 2.0f; float distanceToCamera = fabs(-centerZ - _view->_cameraPosition.y); // y<->z is intentional, not a bug _sceneObjects[index].distanceToCamera = distanceToCamera; @@ -247,7 +247,7 @@ bool SceneObjects::isBetween(float sourceX, float sourceZ, float targetX, float } float objectX1, objectY1, objectZ1, objectX2, objectY2, objectZ2; - _sceneObjects[i].boundingBox->getXYZ(&objectX1, &objectY1, &objectZ1, &objectX2, &objectY2, &objectZ2); + _sceneObjects[i].boundingBox.getXYZ(&objectX1, &objectY1, &objectZ1, &objectX2, &objectY2, &objectZ2); Vector2 intersection; return lineIntersection(Vector2(sourceX, sourceZ), Vector2(targetX, targetZ), Vector2(objectX1, objectZ1), Vector2(objectX2, objectZ1), &intersection) @@ -265,7 +265,7 @@ bool SceneObjects::isObstacleBetween(const Vector3 &source, const Vector3 &targe } float objectX1, objectY1, objectZ1, objectX2, objectY2, objectZ2; - sceneObject->boundingBox->getXYZ(&objectX1, &objectY1, &objectZ1, &objectX2, &objectY2, &objectZ2); + sceneObject->boundingBox.getXYZ(&objectX1, &objectY1, &objectZ1, &objectX2, &objectY2, &objectZ2); if (84.0f <= objectY1 - source.y || 72.0f >= objectY2 - source.y) { continue; @@ -321,31 +321,52 @@ void SceneObjects::updateObstacles() { const SceneObject *sceneObject = &_sceneObjects[index]; if (sceneObject->isObstacle) { float x0, y0, z0, x1, y1, z1; - sceneObject->boundingBox->getXYZ(&x0, &y0, &z0, &x1, &y1, &z1); + sceneObject->boundingBox.getXYZ(&x0, &y0, &z0, &x1, &y1, &z1); _vm->_obstacles->add(x0, z0, x1, z1); } } _vm->_obstacles->backup(); } -void SceneObjects::save(SaveFile &f) { - f.write(_count); +void SceneObjects::save(SaveFileWriteStream &f) { + f.writeInt(_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); + f.writeInt(_sceneObjects[i].id); + f.writeInt(_sceneObjects[i].type); + f.writeBoundingBox(_sceneObjects[i].boundingBox); + f.writeRect(_sceneObjects[i].screenRectangle); + f.writeFloat(_sceneObjects[i].distanceToCamera); + f.writeBool(_sceneObjects[i].isPresent); + f.writeBool(_sceneObjects[i].isClickable); + f.writeBool(_sceneObjects[i].isObstacle); + f.writeInt(_sceneObjects[i].unknown1); + f.writeBool(_sceneObjects[i].isTarget); + f.writeBool(_sceneObjects[i].isMoving); + f.writeBool(_sceneObjects[i].isRetired); } for (int i = 0; i < kSceneObjectCount; ++i) { - f.write(_sceneObjectsSortedByDistance[i]); + f.writeInt(_sceneObjectsSortedByDistance[i]); + } +} + +void SceneObjects::load(SaveFileReadStream &f) { + _count = f.readInt(); + 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].screenRectangle = f.readRect(); + _sceneObjects[i].distanceToCamera = f.readFloat(); + _sceneObjects[i].isPresent = f.readBool(); + _sceneObjects[i].isClickable = f.readBool(); + _sceneObjects[i].isObstacle = f.readBool(); + _sceneObjects[i].unknown1 = f.readInt(); + _sceneObjects[i].isTarget = f.readBool(); + _sceneObjects[i].isMoving = f.readBool(); + _sceneObjects[i].isRetired = f.readBool(); + } + for (int i = 0; i < kSceneObjectCount; ++i) { + _sceneObjectsSortedByDistance[i] = f.readInt(); } } diff --git a/engines/bladerunner/scene_objects.h b/engines/bladerunner/scene_objects.h index 2f154db754..a6d552017c 100644 --- a/engines/bladerunner/scene_objects.h +++ b/engines/bladerunner/scene_objects.h @@ -30,7 +30,8 @@ namespace BladeRunner { class BladeRunnerEngine; -class SaveFile; +class SaveFileReadStream; +class SaveFileWriteStream; class View; enum SceneObjectType { @@ -46,18 +47,18 @@ class SceneObjects { static const int kSceneObjectCount = 115; struct SceneObject { - int id; - SceneObjectType type; - const BoundingBox *boundingBox; - const Common::Rect *screenRectangle; - float distanceToCamera; - bool isPresent; - bool isClickable; - bool isObstacle; - int unknown1; - bool isTarget; - bool isMoving; - bool isRetired; + int id; + SceneObjectType type; + BoundingBox boundingBox; + Common::Rect screenRectangle; + float distanceToCamera; + bool isPresent; + bool isClickable; + bool isObstacle; + int unknown1; + bool isTarget; + bool isMoving; + bool isRetired; }; BladeRunnerEngine *_vm; @@ -71,9 +72,9 @@ public: SceneObjects(BladeRunnerEngine *vm, View *view); ~SceneObjects(); - bool addActor(int sceneObjectId, BoundingBox *boundingBox, Common::Rect *screenRectangle, bool isClickable, bool isMoving, bool isTarget, bool isRetired); - bool addObject(int sceneObjectId, BoundingBox *boundingBox, bool isClickable, bool isObstacle, uint8 unknown1, bool isTarget); - bool addItem(int sceneObjectId, BoundingBox *boundingBox, Common::Rect *screenRectangle, bool isTarget, bool isObstacle); + bool addActor(int sceneObjectId, const BoundingBox &boundingBox, const Common::Rect &screenRectangle, bool isClickable, bool isMoving, bool isTarget, bool isRetired); + bool addObject(int sceneObjectId, const BoundingBox &boundingBox, bool isClickable, bool isObstacle, uint8 unknown1, bool isTarget); + bool addItem(int sceneObjectId, const BoundingBox &boundingBox, const Common::Rect &screenRectangle, bool isTarget, bool isObstacle); bool remove(int sceneObjectId); void clear(); int findByXYZ(bool *isClickable, bool *isObstacle, bool *isTarget, Vector3 &position, bool findClickables, bool findObstacles, bool findTargets) const; @@ -87,10 +88,12 @@ public: void setIsTarget(int sceneObjectId, bool isTarget); void updateObstacles(); - void save(SaveFile &f); + void save(SaveFileWriteStream &f); + void load(SaveFileReadStream &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); + bool addSceneObject(int sceneObjectId, SceneObjectType sceneObjectType, const BoundingBox &boundingBox, const Common::Rect &screenRectangle, bool isClickable, bool isObstacle, uint8 unknown1, bool isTarget, bool isMoving, bool isRetired); int findEmpty() const; }; diff --git a/engines/bladerunner/script/ai_script.cpp b/engines/bladerunner/script/ai_script.cpp index 257e323c5b..b328824de1 100644 --- a/engines/bladerunner/script/ai_script.cpp +++ b/engines/bladerunner/script/ai_script.cpp @@ -22,9 +22,8 @@ #include "bladerunner/script/ai_script.h" -#include "bladerunner/bladerunner.h" - #include "bladerunner/actor.h" +#include "bladerunner/bladerunner.h" namespace BladeRunner { @@ -358,7 +357,7 @@ void AIScripts::setAnimationState(int actor, int animationState, int animationFr } -void AIScripts::queryAnimationState(int actor, int *animationState, int *animationFrame, int *animationStateNext, int *nextAnimation) { +void AIScripts::queryAnimationState(int actor, int *animationState, int *animationFrame, int *animationStateNext, int *animationNext) { if (actor >= _actorCount) { return; } @@ -366,7 +365,7 @@ void AIScripts::queryAnimationState(int actor, int *animationState, int *animati _inScriptCounter++; if (_AIScripts[actor]) { _AIScripts[actor]->FledCombat(); - _AIScripts[actor]->QueryAnimationState(animationState, animationFrame, animationStateNext, nextAnimation); + _AIScripts[actor]->QueryAnimationState(animationState, animationFrame, animationStateNext, animationNext); } _inScriptCounter--; } diff --git a/engines/bladerunner/script/ai_script.h b/engines/bladerunner/script/ai_script.h index 5e782d0820..03789ae542 100644 --- a/engines/bladerunner/script/ai_script.h +++ b/engines/bladerunner/script/ai_script.h @@ -61,7 +61,7 @@ public: virtual bool GoalChanged(int currentGoalNumber, int newGoalNumber) = 0; virtual bool UpdateAnimation(int *animation, int *frame) = 0; virtual bool ChangeAnimationMode(int mode) = 0; - virtual void QueryAnimationState(int *animationState, int *animationFrame, int *animationStateNext, int *nextAnimation) = 0; + virtual void QueryAnimationState(int *animationState, int *animationFrame, int *animationStateNext, int *animationNext) = 0; virtual void SetAnimationState(int animationState, int animationFrame, int animationStateNext, int animationNext) = 0; virtual bool ReachedMovementTrackWaypoint(int waypointId) = 0; virtual void FledCombat() = 0; @@ -566,7 +566,7 @@ 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 queryAnimationState(int actor, int *animationState, int *animationFrame, int *animationStateNext, int *animationNext); void setAnimationState(int actor, int animationState, int animationFrame, int animationStateNext, int animationNext); void fledCombat(int actor); diff --git a/engines/bladerunner/script/police_maze.cpp b/engines/bladerunner/script/police_maze.cpp index 3aa3ebbfc8..68bb84a762 100644 --- a/engines/bladerunner/script/police_maze.cpp +++ b/engines/bladerunner/script/police_maze.cpp @@ -24,6 +24,7 @@ #include "bladerunner/game_constants.h" #include "bladerunner/items.h" #include "bladerunner/mouse.h" +#include "bladerunner/savefile.h" #include "bladerunner/scene.h" #include "bladerunner/scene_objects.h" #include "bladerunner/script/police_maze.h" @@ -122,6 +123,24 @@ void PoliceMaze::tick() { } } +void PoliceMaze::save(SaveFileWriteStream &f) { + f.writeBool(_isPaused); + f.writeBool(_isActive); + f.writeBool(_isEnding); + for (int i = 0; i < kNumMazeTracks; ++i) { + _tracks[i]->save(f); + } +} + +void PoliceMaze::load(SaveFileReadStream &f) { + _isPaused = f.readBool(); + _isActive = f.readBool(); + _isEnding = f.readBool(); + for (int i = 0; i < kNumMazeTracks; ++i) { + _tracks[i]->load(f); + } +} + PoliceMazeTargetTrack::PoliceMazeTargetTrack(BladeRunnerEngine *vm) : ScriptBase(vm) { reset(); } @@ -139,7 +158,7 @@ void PoliceMazeTargetTrack::reset() { _timeLeftUpdate = 0; _timeLeftWait = 0; _time = 0; - _isWaiting = false; + _isWaiting = false; _isMoving = false; _pointIndex = 0; _pointTarget = 0; @@ -528,8 +547,8 @@ bool PoliceMazeTargetTrack::tick() { void PoliceMazeTargetTrack::readdObject(int itemId) { if (_vm->_sceneObjects->remove(itemId + kSceneObjectOffsetItems)) { - BoundingBox *boundingBox = _vm->_items->getBoundingBox(itemId); - Common::Rect *screenRect = _vm->_items->getScreenRectangle(itemId); + const BoundingBox &boundingBox = _vm->_items->getBoundingBox(itemId); + const Common::Rect &screenRect = _vm->_items->getScreenRectangle(itemId); bool targetable = _vm->_items->isTarget(itemId); bool obstacle = _vm->_items->isVisible(itemId); @@ -537,5 +556,48 @@ void PoliceMazeTargetTrack::readdObject(int itemId) { } } +void PoliceMazeTargetTrack::save(SaveFileWriteStream &f) { + f.writeBool(_isPresent); + f.writeInt(_itemId); + f.writeInt(_pointCount); + f.writeInt(_dataIndex); + f.writeBool(_isWaiting); + f.writeBool(_isMoving); + f.writeInt(_pointIndex); + f.writeInt(_pointTarget); + f.writeBool(_isRotating); + f.writeInt(_angleTarget); + f.writeInt(_angleDelta); + f.writeBool(_isPaused); + + for (int i = 0; i < kNumTrackPoints; ++i) { + f.writeVector3(_points[i]); + } + + f.writeInt(_timeLeftUpdate); + f.writeInt(_timeLeftWait); +} + +void PoliceMazeTargetTrack::load(SaveFileReadStream &f) { + _isPresent = f.readBool(); + _itemId = f.readInt(); + _pointCount = f.readInt(); + _dataIndex = f.readInt(); + _isWaiting = f.readBool(); + _isMoving = f.readBool(); + _pointIndex = f.readInt(); + _pointTarget = f.readInt(); + _isRotating = f.readBool(); + _angleTarget = f.readInt(); + _angleDelta = f.readInt(); + _isPaused = f.readBool(); + + for (int i = 0; i < kNumTrackPoints; ++i) { + _points[i] = f.readVector3(); + } + + _timeLeftUpdate = f.readInt(); + _timeLeftWait = f.readInt(); +} } // End of namespace BladeRunner diff --git a/engines/bladerunner/script/police_maze.h b/engines/bladerunner/script/police_maze.h index e53d68e373..725fbd4319 100644 --- a/engines/bladerunner/script/police_maze.h +++ b/engines/bladerunner/script/police_maze.h @@ -34,25 +34,27 @@ enum { }; class BladeRunnerEngine; +class SaveFileReadStream; +class SaveFileWriteStream; class PoliceMazeTargetTrack : ScriptBase { - uint32 _time; - bool _isPresent; - int _itemId; - int _pointCount; - Vector3 _points[kNumTrackPoints]; + uint32 _time; + bool _isPresent; + int _itemId; + int _pointCount; + Vector3 _points[kNumTrackPoints]; const int *_data; - int _dataIndex; - int32 _timeLeftUpdate; - int32 _timeLeftWait; - bool _isWaiting; - int _isMoving; - int _pointIndex; - int _pointTarget; - bool _isRotating; - int _angleTarget; - int _angleDelta; - bool _isPaused; + int _dataIndex; + int32 _timeLeftUpdate; + int32 _timeLeftWait; + bool _isWaiting; + int _isMoving; + int _pointIndex; + int _pointTarget; + bool _isRotating; + int _angleTarget; + int _angleDelta; + bool _isPaused; public: PoliceMazeTargetTrack(BladeRunnerEngine *vm); @@ -70,6 +72,9 @@ public: void setTime(uint32 t) { _time = t; } void readdObject(int itemId); + + void save(SaveFileWriteStream &f); + void load(SaveFileReadStream &f); }; class PoliceMaze : ScriptBase { @@ -91,6 +96,9 @@ public: void clear(bool isLoadingGame); void setPauseState(bool state); void activate(); + + void save(SaveFileWriteStream &f); + void load(SaveFileReadStream &f); }; } // End of namespace BladeRunner diff --git a/engines/bladerunner/script/script.cpp b/engines/bladerunner/script/script.cpp index 6c7d8f5bd9..6d981fe3e3 100644 --- a/engines/bladerunner/script/script.cpp +++ b/engines/bladerunner/script/script.cpp @@ -832,8 +832,7 @@ int ScriptBase::Random_Query(int min, int max) { } void ScriptBase::Sound_Play(int id, int volume, int panFrom, int panTo, int priority) { - const char *name = _vm->_gameInfo->getSfxTrack(id); - _vm->_audioPlayer->playAud(name, volume, panFrom, panTo, priority); + _vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(id), volume, panFrom, panTo, priority); } void ScriptBase::Sound_Play_Speech_Line(int actorId, int sentenceId, int volume, int a4, int priority) { @@ -899,8 +898,7 @@ void ScriptBase::Footstep_Sound_Override_Off() { } bool ScriptBase::Music_Play(int musicId, int volume, int pan, int timeFadeIn, int timePlay, int loop, int timeFadeOut) { - const char *musicName = _vm->_gameInfo->getMusicTrack(musicId); - return _vm->_music->play(musicName, volume, pan, timeFadeIn, timePlay, loop, timeFadeOut); + return _vm->_music->play(_vm->_gameInfo->getMusicTrack(musicId), volume, pan, timeFadeIn, timePlay, loop, timeFadeOut); } void ScriptBase::Music_Adjust(int volume, int pan, int delay) { diff --git a/engines/bladerunner/script/script.h b/engines/bladerunner/script/script.h index 5e1e160498..09c372d009 100644 --- a/engines/bladerunner/script/script.h +++ b/engines/bladerunner/script/script.h @@ -23,11 +23,11 @@ #ifndef BLADERUNNER_SCRIPT_H #define BLADERUNNER_SCRIPT_H -#include "common/str.h" - #include "bladerunner/bladerunner.h" #include "bladerunner/game_constants.h" +#include "common/str.h" + namespace BladeRunner { class BladeRunnerEngine; diff --git a/engines/bladerunner/set.cpp b/engines/bladerunner/set.cpp index 6a83294c4c..ac026a4d76 100644 --- a/engines/bladerunner/set.cpp +++ b/engines/bladerunner/set.cpp @@ -68,8 +68,10 @@ bool Set::open(const Common::String &name) { _objectCount = s->readUint32LE(); assert(_objectCount <= 85); + char buf[20]; for (int i = 0; i < _objectCount; ++i) { - s->read(_objects[i].name, 20); + s->read(buf, sizeof(buf)); + _objects[i].name = buf; float x0, y0, z0, x1, y1, z1; x0 = s->readFloatLE(); @@ -96,7 +98,9 @@ bool Set::open(const Common::String &name) { for (int i = 0; i < _walkboxCount; ++i) { float x, z; - s->read(_walkboxes[i].name, 20); + s->read(buf, sizeof(buf)); + _walkboxes[i].name = buf; + _walkboxes[i].altitude = s->readFloatLE(); _walkboxes[i].vertexCount = s->readUint32LE(); @@ -131,7 +135,7 @@ bool Set::open(const Common::String &name) { void Set::addObjectsToScene(SceneObjects *sceneObjects) const { for (int i = 0; i < _objectCount; i++) { - sceneObjects->addObject(i + kSceneObjectOffsetObjects, &_objects[i].bbox, _objects[i].isClickable, _objects[i].isObstacle, _objects[i].unknown1, _objects[i].isTarget); + sceneObjects->addObject(i + kSceneObjectOffsetObjects, _objects[i].bbox, _objects[i].isClickable, _objects[i].isObstacle, _objects[i].unknown1, _objects[i].isTarget); } } @@ -209,15 +213,14 @@ int Set::findWalkbox(float x, float z) const { return result; } -int Set::findObject(const char *objectName) const { - int i; - for (i = 0; i < (int)_objectCount; i++) { - if (scumm_stricmp(objectName, _objects[i].name) == 0) { +int Set::findObject(const Common::String &objectName) const { + for (int i = 0; i < _objectCount; ++i) { + if (objectName.compareToIgnoreCase(_objects[i].name) == 0) { return i; } } - debug("Set::findObject didn't find \"%s\"", objectName); + debug("Set::findObject didn't find \"%s\"", objectName.c_str()); return -1; } @@ -258,7 +261,7 @@ void Set::objectSetIsTarget(int objectId, bool isTarget) { _objects[objectId].isTarget = isTarget; } -const char *Set::objectGetName(int objectId) const { +const Common::String &Set::objectGetName(int objectId) const { return _objects[objectId].name; } @@ -330,39 +333,73 @@ int Set::getWalkboxSoundRunRight(int walkboxId) const { return getWalkboxSoundWalkRight(walkboxId); } -void Set::save(SaveFile &f) { - f.write(_loaded); - f.write(_objectCount); - f.write(_walkboxCount); +void Set::save(SaveFileWriteStream &f) { + f.writeBool(_loaded); + f.writeInt(_objectCount); + f.writeInt(_walkboxCount); + + for (int i = 0; i != _objectCount; ++i) { + f.writeStringSz(_objects[i].name, 20); + f.writeBoundingBox(_objects[i].bbox); + f.writeBool(_objects[i].isObstacle); + f.writeBool(_objects[i].isClickable); + f.writeBool(_objects[i].isHotMouse); + f.writeInt(_objects[i].unknown1); + f.writeBool(_objects[i].isTarget); + } + + for (int i = 0; i != _walkboxCount; ++i) { + f.writeStringSz(_walkboxes[i].name, 20); + f.writeFloat(_walkboxes[i].altitude); + f.writeInt(_walkboxes[i].vertexCount); + for (int j = 0; j != 8; ++j) { + f.writeVector3(_walkboxes[i].vertices[j]); + + // In BLADE.EXE vertices are a vec5 + f.writeInt(0); + f.writeInt(0); + } + } + + for (int i = 0; i != 85; ++i) { + f.writeInt(_walkboxStepSound[i]); + } + + f.writeInt(_footstepSoundOverride); +} + +void Set::load(SaveFileReadStream &f) { + _loaded = f.readBool(); + _objectCount = f.readInt(); + _walkboxCount = f.readInt(); 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); + _objects[i].name = f.readStringSz(20); + _objects[i].bbox = f.readBoundingBox(); + _objects[i].isObstacle = f.readBool(); + _objects[i].isClickable = f.readBool(); + _objects[i].isHotMouse = f.readBool(); + _objects[i].unknown1 = f.readInt(); + _objects[i].isTarget = f.readBool(); } for (int i = 0; i != _walkboxCount; ++i) { - f.write(_walkboxes[i].name, 20); - f.write(_walkboxes[i].altitude); - f.write(_walkboxes[i].vertexCount); + _walkboxes[i].name = f.readStringSz(20); + _walkboxes[i].altitude = f.readFloat(); + _walkboxes[i].vertexCount = f.readInt(); for (int j = 0; j != 8; ++j) { - f.write(_walkboxes[i].vertices[j]); + _walkboxes[i].vertices[j] = f.readVector3(); // In BLADE.EXE vertices are a vec5 - f.write(0); - f.write(0); + f.skip(8); } } for (int i = 0; i != 85; ++i) { - f.write(_walkboxStepSound[i]); + _walkboxStepSound[i] = f.readInt(); } - f.write(_footstepSoundOverride); + _footstepSoundOverride = f.readInt(); } } // End of namespace BladeRunner diff --git a/engines/bladerunner/set.h b/engines/bladerunner/set.h index 7989ef1e1a..c6c1081196 100644 --- a/engines/bladerunner/set.h +++ b/engines/bladerunner/set.h @@ -32,29 +32,30 @@ namespace BladeRunner { class BladeRunnerEngine; -class VQADecoder; -class SaveFile; +class SaveFileReadStream; +class SaveFileWriteStream; class SetEffects; class SceneObjects; +class VQADecoder; class Set { friend class Debugger; struct Object { - char name[20]; - BoundingBox bbox; - uint8 isObstacle; - uint8 isClickable; - uint8 isHotMouse; - uint8 isTarget; - uint8 unknown1; + Common::String name; + BoundingBox bbox; + uint8 isObstacle; + uint8 isClickable; + uint8 isHotMouse; + uint8 isTarget; + uint8 unknown1; }; struct Walkbox { - char name[20]; - float altitude; - int vertexCount; - Vector3 vertices[8]; + Common::String name; + float altitude; + int vertexCount; + Vector3 vertices[8]; }; BladeRunnerEngine *_vm; @@ -83,14 +84,14 @@ public: float getAltitudeAtXZ(float x, float z, bool *inWalkbox) const; int findWalkbox(float x, float z) const; - int findObject(const char *objectName) const; + int findObject(const Common::String &objectName) const; bool objectSetHotMouse(int objectId) const; bool objectGetBoundingBox(int objectId, BoundingBox *boundingBox) const; void objectSetIsClickable(int objectId, bool isClickable); void objectSetIsObstacle(int objectId, bool isObstacle); void objectSetIsTarget(int objectId, bool isTarget); - const char *objectGetName(int objectId) const; + const Common::String &objectGetName(int objectId) const; void setWalkboxStepSound(int walkboxId, int soundId); void setFoodstepSoundOverride(int soundId); @@ -101,7 +102,8 @@ public: int getWalkboxSoundRunLeft(int walkboxId) const; int getWalkboxSoundRunRight(int walkboxId) const; - void save(SaveFile &f); + void save(SaveFileWriteStream &f); + void load(SaveFileReadStream &f); private: static bool isXZInWalkbox(float x, float z, const Walkbox &walkbox); diff --git a/engines/bladerunner/set_effects.cpp b/engines/bladerunner/set_effects.cpp index 5c7b2487a8..3d46e41e7b 100644 --- a/engines/bladerunner/set_effects.cpp +++ b/engines/bladerunner/set_effects.cpp @@ -104,7 +104,7 @@ void SetEffects::setFadeDensity(float density) { _fadeDensity = density; } -void SetEffects::setFogColor(const char *fogName, float r, float g, float b) { +void SetEffects::setFogColor(const Common::String &fogName, float r, float g, float b) { Fog *fog = findFog(fogName); if (fog == nullptr) { return; @@ -115,7 +115,7 @@ void SetEffects::setFogColor(const char *fogName, float r, float g, float b) { fog->_fogColor.b = b; } -void SetEffects::setFogDensity(const char *fogName, float density) { +void SetEffects::setFogDensity(const Common::String &fogName, float density) { Fog *fog = findFog(fogName); if (fog == nullptr) { return; @@ -151,7 +151,7 @@ void SetEffects::calculateColor(Vector3 viewPosition, Vector3 position, float *o outColor->b = outColor->b * (1.0f - _fadeDensity) + _fadeColor.b * _fadeDensity; } -Fog *SetEffects::findFog(const char *fogName) const { +Fog *SetEffects::findFog(const Common::String &fogName) const { if (!_fogs) { return nullptr; } @@ -159,7 +159,7 @@ Fog *SetEffects::findFog(const char *fogName) const { Fog *fog = _fogs; while (fog != nullptr) { - if (strcmp(fogName, fog->_name) == 0) { + if (fogName.compareTo(fog->_name) == 0) { break; } fog = fog->_next; diff --git a/engines/bladerunner/set_effects.h b/engines/bladerunner/set_effects.h index 81d7b93149..6bd139c4d6 100644 --- a/engines/bladerunner/set_effects.h +++ b/engines/bladerunner/set_effects.h @@ -53,13 +53,13 @@ public: void setFadeColor(float r, float g, float b); void setFadeDensity(float density); - void setFogColor(const char *fogName, float r, float g, float b); - void setFogDensity(const char *fogName, float density); + void setFogColor(const Common::String &fogName, float r, float g, float b); + void setFogDensity(const Common::String &fogName, float density); void calculateColor(Vector3 viewPosition, Vector3 position, float *outCoeficient, Color *outColor) const; private: - Fog *findFog(const char *fogName) const; + Fog *findFog(const Common::String &fogName) const; }; } // End of namespace BladeRunner diff --git a/engines/bladerunner/settings.cpp b/engines/bladerunner/settings.cpp index e4db0b81ea..071adf6dd5 100644 --- a/engines/bladerunner/settings.cpp +++ b/engines/bladerunner/settings.cpp @@ -22,9 +22,12 @@ #include "bladerunner/settings.h" +#include "bladerunner/actor.h" #include "bladerunner/ambient_sounds.h" #include "bladerunner/bladerunner.h" #include "bladerunner/chapters.h" +#include "bladerunner/game_constants.h" +#include "bladerunner/game_info.h" #include "bladerunner/music.h" #include "bladerunner/savefile.h" #include "bladerunner/scene.h" @@ -118,7 +121,19 @@ bool Settings::openNewScene() { _scene = newScene; if (!_loadingGame && currentSet != newSet) { - // TODO: Reset actors for new set + for (int i = 0; i < (int)_vm->_gameInfo->getActorCount(); ++i) { + Actor *actor = _vm->_actors[i]; + if (i != kActorMcCoy && actor->getSetId() == currentSet) { + if (!actor->isRetired()) { + actor->stopWalking(false); + actor->movementTrackWaypointReached(); + } + if (actor->inCombat()) { + actor->setSetId(kSetFreeSlotG); + actor->combatModeOff(); + } + } + } } _loadingGame = false; @@ -185,16 +200,29 @@ 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); +void Settings::save(SaveFileWriteStream &f) { + f.writeInt(_scene); + f.writeInt(_set); + f.writeInt(_chapter); + f.writeInt(_playerAgenda); + f.writeInt(_unk0); + f.writeInt(_difficulty); + f.writeInt(_ammoType); + for (int i = 0; i != 3; ++i) { + f.writeInt(_ammoAmounts[i]); + } +} + +void Settings::load(SaveFileReadStream &f) { + _scene = f.readInt(); + _set = f.readInt(); + _chapter = f.readInt(); + _playerAgenda = f.readInt(); + _unk0 = f.readInt(); + _difficulty = f.readInt(); + _ammoType = f.readInt(); for (int i = 0; i != 3; ++i) { - f.write(_ammoAmounts[i]); + _ammoAmounts[i] = f.readInt(); } } diff --git a/engines/bladerunner/settings.h b/engines/bladerunner/settings.h index bc1c25553c..413786e2e5 100644 --- a/engines/bladerunner/settings.h +++ b/engines/bladerunner/settings.h @@ -26,7 +26,8 @@ namespace BladeRunner { class BladeRunnerEngine; -class SaveFile; +class SaveFileReadStream; +class SaveFileWriteStream; enum PlayerAgenda { kPlayerAgendaPolite = 0, @@ -53,7 +54,7 @@ class Settings { bool _startingGame; bool _loadingGame; - int _unk1; + // int _unk1; int _fullHDFrames; int _mst3k; @@ -91,6 +92,18 @@ public: return _newSet; } + int getScene() const { + return _scene; + } + + int getSet() const { + return _set; + } + + int getChapter() const { + return _chapter; + } + void setChapter(int newChapter) { _chapterChanged = true; _newChapter = newChapter; @@ -124,7 +137,8 @@ public: bool getLearyMode() const; void setLearyMode(bool learyMode); - void save(SaveFile &f); + void save(SaveFileWriteStream &f); + void load(SaveFileReadStream &f); }; } // End of namespace BladeRunner diff --git a/engines/bladerunner/text_resource.cpp b/engines/bladerunner/text_resource.cpp index 2a4840c833..8f54f8a976 100644 --- a/engines/bladerunner/text_resource.cpp +++ b/engines/bladerunner/text_resource.cpp @@ -46,11 +46,11 @@ TextResource::~TextResource() { bool TextResource::open(const Common::String &name) { assert(name.size() <= 8); - char resName[13]; - sprintf(resName, "%s.TR%s", name.c_str(), _vm->_languageCode); + Common::String resName = Common::String::format("%s.TR%s", name.c_str(), _vm->_languageCode.c_str()); Common::ScopedPtr<Common::SeekableReadStream> s(_vm->getResourceStream(resName)); - if (!s) + if (!s) { return false; + } _count = s->readUint32LE(); diff --git a/engines/bladerunner/ui/elevator.cpp b/engines/bladerunner/ui/elevator.cpp index 3f668efd75..7a6ab3ca35 100644 --- a/engines/bladerunner/ui/elevator.cpp +++ b/engines/bladerunner/ui/elevator.cpp @@ -315,8 +315,7 @@ void Elevator::mouseOutCallback(int, void *self) { void Elevator::mouseDownCallback(int, void *self) { Elevator *elevator = ((Elevator *)self); - const char *name = elevator->_vm->_gameInfo->getSfxTrack(515); - elevator->_vm->_audioPlayer->playAud(name, 100, 0, 0, 50, 0); + elevator->_vm->_audioPlayer->playAud(elevator->_vm->_gameInfo->getSfxTrack(515), 100, 0, 0, 50, 0); } void Elevator::mouseUpCallback(int buttonId, void *self) { diff --git a/engines/bladerunner/ui/kia.cpp b/engines/bladerunner/ui/kia.cpp index 86fdc9254a..756f1bd2cd 100644 --- a/engines/bladerunner/ui/kia.cpp +++ b/engines/bladerunner/ui/kia.cpp @@ -350,7 +350,7 @@ void KIA::tick() { _shapes->get(47)->draw(_vm->_surfaceFront, 182, 446); } } - _vm->_mainFont->drawColor("1.00", _vm->_surfaceFront, 438, 471, 0x1CE7); + _vm->_mainFont->drawColor("1.00", _vm->_surfaceFront, 438, 471, 0x1CE7); // TODO: 1.01 for DVD version if (!_transitionId) { _buttons->drawTooltip(_vm->_surfaceFront, mouse.x, mouse.y); } diff --git a/engines/bladerunner/ui/kia_log.cpp b/engines/bladerunner/ui/kia_log.cpp index 51b922a8f7..7f75f2e944 100644 --- a/engines/bladerunner/ui/kia_log.cpp +++ b/engines/bladerunner/ui/kia_log.cpp @@ -55,7 +55,7 @@ void KIALog::add(int type, int dataSize, const void *data) { _entries[_currentIndex].dataSize = dataSize; if (dataSize > 0) { - char *dataCopy = new char[dataSize]; + unsigned char *dataCopy = new unsigned char[dataSize]; memcpy(dataCopy, data, dataSize); _entries[_currentIndex].data = dataCopy; } else { diff --git a/engines/bladerunner/ui/kia_log.h b/engines/bladerunner/ui/kia_log.h index 4a89492817..99c834e3f0 100644 --- a/engines/bladerunner/ui/kia_log.h +++ b/engines/bladerunner/ui/kia_log.h @@ -33,7 +33,7 @@ class KIALog { struct Entry { int type; int dataSize; - const char *data; + const unsigned char *data; }; BladeRunnerEngine *_vm; diff --git a/engines/bladerunner/ui/spinner.cpp b/engines/bladerunner/ui/spinner.cpp index 1f8f197926..9e491f719c 100644 --- a/engines/bladerunner/ui/spinner.cpp +++ b/engines/bladerunner/ui/spinner.cpp @@ -263,11 +263,17 @@ void Spinner::resume() { _vqaPlayer->setLoop(1, -1, kLoopSetModeJustStart, nullptr, nullptr); } -void Spinner::save(SaveFile &f) { +void Spinner::save(SaveFileWriteStream &f) { assert(!_isOpen); for (int i = 0; i != kSpinnerDestinations; ++i) { - f.write(_isDestinationSelectable[i]); + f.writeBool(_isDestinationSelectable[i]); + } +} + +void Spinner::load(SaveFileReadStream &f) { + for (int i = 0; i != kSpinnerDestinations; ++i) { + _isDestinationSelectable[i] = f.readBool(); } } diff --git a/engines/bladerunner/ui/spinner.h b/engines/bladerunner/ui/spinner.h index 24f66ed4db..d2d666e8e1 100644 --- a/engines/bladerunner/ui/spinner.h +++ b/engines/bladerunner/ui/spinner.h @@ -29,7 +29,8 @@ namespace BladeRunner { class BladeRunnerEngine; -class SaveFile; +class SaveFileReadStream; +class SaveFileWriteStream; class Shape; class UIImagePicker; class VQAPlayer; @@ -71,7 +72,8 @@ public: void reset(); void resume(); - void save(SaveFile &f); + void save(SaveFileWriteStream &f); + void load(SaveFileReadStream &f); private: static void mouseUpCallback(int, void *); diff --git a/engines/bladerunner/ui/ui_scroll_box.cpp b/engines/bladerunner/ui/ui_scroll_box.cpp index 6bd4dabdd4..8621039dd6 100644 --- a/engines/bladerunner/ui/ui_scroll_box.cpp +++ b/engines/bladerunner/ui/ui_scroll_box.cpp @@ -481,7 +481,7 @@ void UIScrollBox::draw(Graphics::Surface &surface) { } if (_center) { - x = (_rect.width() - _vm->_mainFont->getTextWidth(_lines[i]->text)) / 2; + x = _rect.left + (_rect.width() - _vm->_mainFont->getTextWidth(_lines[i]->text)) / 2; } _vm->_mainFont->drawColor(_lines[i]->text, surface, x, y, color); diff --git a/engines/bladerunner/waypoints.cpp b/engines/bladerunner/waypoints.cpp index 0783af8e07..bf2f09b8a6 100644 --- a/engines/bladerunner/waypoints.cpp +++ b/engines/bladerunner/waypoints.cpp @@ -91,13 +91,23 @@ float Waypoints::getZ(int waypointId) const { return _waypoints[waypointId].position.z; } -void Waypoints::save(SaveFile &f) { - f.write(_count); +void Waypoints::save(SaveFileWriteStream &f) { + f.writeInt(_count); for (int i = 0; i < _count; ++i) { Waypoint &w = _waypoints[i]; - f.write(w.setId); - f.write(w.position); - f.write(w.present); + f.writeInt(w.setId); + f.writeVector3(w.position); + f.writeInt(w.present); + } +} + +void Waypoints::load(SaveFileReadStream &f) { + _count = f.readInt(); + for (int i = 0; i < _count; ++i) { + Waypoint &w = _waypoints[i]; + w.setId = f.readInt(); + w.position = f.readVector3(); + w.present = f.readInt(); } } diff --git a/engines/bladerunner/waypoints.h b/engines/bladerunner/waypoints.h index 9159301cfe..6bbe8d3db4 100644 --- a/engines/bladerunner/waypoints.h +++ b/engines/bladerunner/waypoints.h @@ -30,7 +30,8 @@ namespace BladeRunner { -class SaveFile; +class SaveFileReadStream; +class SaveFileWriteStream; class Waypoints { friend class Debugger; @@ -58,7 +59,8 @@ public: bool set(int waypointId, int setId, Vector3 position); bool reset(int waypointId); - void save(SaveFile &f); + void save(SaveFileWriteStream &f); + void load(SaveFileReadStream &f); }; } // End of namespace BladeRunner |