aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Fach-Pedersen2017-03-28 17:50:04 +0200
committerThomas Fach-Pedersen2017-03-28 17:50:11 +0200
commit5f552c9446ddf3f02ec99ff6902822d66d2cc955 (patch)
treeb28610bf509c67109a042136873fd26b93d9fcf2
parent532828c143e0872525dadfe8b0ebe804f7071633 (diff)
downloadscummvm-rg350-5f552c9446ddf3f02ec99ff6902822d66d2cc955.tar.gz
scummvm-rg350-5f552c9446ddf3f02ec99ff6902822d66d2cc955.tar.bz2
scummvm-rg350-5f552c9446ddf3f02ec99ff6902822d66d2cc955.zip
BLADERUNNER: Implement ZBuffer class
-rw-r--r--engines/bladerunner/actor.cpp23
-rw-r--r--engines/bladerunner/actor.h4
-rw-r--r--engines/bladerunner/bladerunner.cpp30
-rw-r--r--engines/bladerunner/bladerunner.h8
-rw-r--r--engines/bladerunner/item.cpp67
-rw-r--r--engines/bladerunner/item.h2
-rw-r--r--engines/bladerunner/item_pickup.cpp7
-rw-r--r--engines/bladerunner/items.cpp6
-rw-r--r--engines/bladerunner/module.mk3
-rw-r--r--engines/bladerunner/mouse.cpp3
-rw-r--r--engines/bladerunner/scene.cpp6
-rw-r--r--engines/bladerunner/scene.h2
-rw-r--r--engines/bladerunner/script/scene/rc01.cpp6
-rw-r--r--engines/bladerunner/vqa_decoder.cpp79
-rw-r--r--engines/bladerunner/vqa_decoder.h8
-rw-r--r--engines/bladerunner/vqa_player.cpp6
-rw-r--r--engines/bladerunner/vqa_player.h3
-rw-r--r--engines/bladerunner/zbuffer.cpp221
-rw-r--r--engines/bladerunner/zbuffer.h87
19 files changed, 422 insertions, 149 deletions
diff --git a/engines/bladerunner/actor.cpp b/engines/bladerunner/actor.cpp
index 330ed58ddf..f783791ba1 100644
--- a/engines/bladerunner/actor.cpp
+++ b/engines/bladerunner/actor.cpp
@@ -40,6 +40,7 @@
#include "bladerunner/slice_animations.h"
#include "bladerunner/slice_renderer.h"
#include "bladerunner/waypoints.h"
+#include "bladerunner/zbuffer.h"
namespace BladeRunner {
@@ -534,7 +535,7 @@ bool Actor::loopWalkToWaypoint(int waypointId, int destinationOffset, int a3, bo
return loopWalk(waypointPosition, destinationOffset, a3, run, _position, 0.0f, 24.0f, a5, isRunning, false);
}
-bool Actor::tick(bool forceDraw) {
+bool Actor::tick(bool forceDraw, Common::Rect *screenRect) {
int remain = 0;
bool needsUpdate = false;
if (_fps > 0) {
@@ -639,7 +640,13 @@ bool Actor::tick(bool forceDraw) {
}
}
- draw();
+ bool isVisible = false;
+ if (!_isInvisible) {
+ isVisible = draw(screenRect);
+ if (isVisible) {
+ _screenRectangle = *screenRect;
+ }
+ }
if (needsUpdate) {
int nextFrameTime = remain + _frame_ms;
@@ -654,18 +661,20 @@ bool Actor::tick(bool forceDraw) {
this->setFacing(this->_targetFacing, false);
}
}
- return false;
+ return isVisible;
}
-void Actor::draw() {
+bool Actor::draw(Common::Rect *screenRect) {
Vector3 drawPosition(_position.x, -_position.z, _position.y + 2.0);
float drawAngle = M_PI - _facing * (M_PI / 512.0f);
float drawScale = _scale;
// TODO: Handle SHORTY mode
- _vm->_sliceRenderer->drawInWorld(_animationId, _animationFrame, drawPosition, drawAngle, drawScale, _vm->_surface2, _vm->_zBuffer2);
- _vm->_sliceRenderer->getScreenRectangle(&_screenRectangle, _animationId, _animationFrame, drawPosition, drawAngle, drawScale);
+ _vm->_sliceRenderer->drawInWorld(_animationId, _animationFrame, drawPosition, drawAngle, drawScale, _vm->_surface2, _vm->_zbuffer->getData());
+ _vm->_sliceRenderer->getScreenRectangle(screenRect, _animationId, _animationFrame, drawPosition, drawAngle, drawScale);
+
+ return !screenRect->isEmpty();
}
int Actor::getSetId() {
@@ -1011,7 +1020,7 @@ void Actor::setGoal(int goalNumber) {
_goalNumber = goalNumber;
if (goalNumber == oldGoalNumber) {
return;
- }
+ }
_vm->_aiScripts->GoalChanged(_id, oldGoalNumber, goalNumber);
_vm->_sceneScript->ActorChangedGoal(_id, goalNumber, oldGoalNumber, _vm->_scene->getSetId() == _setId);
diff --git a/engines/bladerunner/actor.h b/engines/bladerunner/actor.h
index d924730b4b..40bcae5b70 100644
--- a/engines/bladerunner/actor.h
+++ b/engines/bladerunner/actor.h
@@ -149,8 +149,8 @@ public:
bool loopWalkToWaypoint(int waypointId, int destinationOffset, int a3, bool run, bool a5, bool *isRunning);
bool loopWalkToXYZ(const Vector3 &destination, int destinationOffset, bool a3, bool run, bool a5, bool *isRunning);
- bool tick(bool forceUpdate);
- void draw();
+ bool tick(bool forceUpdate, Common::Rect *screenRect);
+ bool draw(Common::Rect *screenRect);
int getSetId();
void setSetId(int setId);
diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp
index 78239adbbb..ec54a7c76a 100644
--- a/engines/bladerunner/bladerunner.cpp
+++ b/engines/bladerunner/bladerunner.cpp
@@ -52,6 +52,7 @@
#include "bladerunner/text_resource.h"
#include "bladerunner/vqa_decoder.h"
#include "bladerunner/waypoints.h"
+#include "bladerunner/zbuffer.h"
#include "common/array.h"
#include "common/error.h"
@@ -61,7 +62,7 @@
#include "engines/util.h"
#include "graphics/pixelformat.h"
-#include "suspects_database.h"
+#include "suspects_database.h"
namespace BladeRunner {
@@ -112,8 +113,7 @@ BladeRunnerEngine::~BladeRunnerEngine() {
// _surface1.free();
// _surface2.free();
- // delete[] _zBuffer1;
- // delete[] _zBuffer2;
+ delete _zbuffer;
delete _itemPickup;
delete _obstacles;
@@ -232,9 +232,8 @@ bool BladeRunnerEngine::startup(bool hasSavegames) {
// TODO: Video overlays
- // TODO: Proper ZBuf class
- _zBuffer1 = new uint16[640 * 480];
- _zBuffer2 = new uint16[640 * 480];
+ _zbuffer = new ZBuffer();
+ _zbuffer->init(640, 480);
int actorCount = (int)_gameInfo->getActorCount();
assert(actorCount < ACTORS_COUNT);
@@ -500,12 +499,8 @@ void BladeRunnerEngine::shutdown() {
_playerActor = nullptr;
- // TODO: Delete proper ZBuf class
- delete[] _zBuffer1;
- _zBuffer1 = nullptr;
-
- delete[] _zBuffer2;
- _zBuffer2 = nullptr;
+ delete _zbuffer;
+ _zbuffer = nullptr;
delete _gameInfo;
_gameInfo = nullptr;
@@ -597,19 +592,19 @@ void BladeRunnerEngine::gameTick() {
_sceneScript->PlayerWalkedIn();
}
// TODO: Gun range announcements
- // TODO: ZBUF repair dirty rects
+
+ _zbuffer->clean();
_ambientSounds->tick();
bool backgroundChanged = false;
- int frame = _scene->advanceFrame(_surface1, _zBuffer1);
+ int frame = _scene->advanceFrame(_surface1);
if (frame >= 0) {
_sceneScript->SceneFrameAdvanced(frame);
backgroundChanged = true;
}
(void)backgroundChanged;
_surface2.copyFrom(_surface1);
- memcpy(_zBuffer2, _zBuffer1, 640 * 480 * 2);
#if 0
{
@@ -641,7 +636,10 @@ void BladeRunnerEngine::gameTick() {
for (int i = 0, end = _gameInfo->getActorCount(); i != end; ++i) {
if (_actors[i]->getSetId() == setId) {
if (i == 0 || i == 15 || i == 23) { // Currently limited to McCoy, Runciter and Officer Leroy
- _actors[i]->tick(backgroundChanged);
+ Common::Rect screenRect;
+ if (_actors[i]->tick(backgroundChanged, &screenRect)) {
+ _zbuffer->mark(screenRect);
+ }
}
}
}
diff --git a/engines/bladerunner/bladerunner.h b/engines/bladerunner/bladerunner.h
index 87bb7dbeca..fd62f35bed 100644
--- a/engines/bladerunner/bladerunner.h
+++ b/engines/bladerunner/bladerunner.h
@@ -63,6 +63,7 @@ class SliceRenderer;
class TextResource;
class View;
class Waypoints;
+class ZBuffer;
#define ACTORS_COUNT 100
#define VOICEOVER_ACTOR (ACTORS_COUNT - 1)
@@ -72,7 +73,7 @@ public:
bool _gameIsRunning;
bool _windowIsActive;
int _playerLosesControlCounter;
-
+
ADQ *_adq;
AIScripts *_aiScripts;
AmbientSounds *_ambientSounds;
@@ -99,7 +100,7 @@ public:
View *_view;
Waypoints *_waypoints;
int *_gameVars;
-
+
TextResource *_textActorNames;
TextResource *_textCrimes;
TextResource *_textCluetype;
@@ -117,8 +118,7 @@ public:
Graphics::Surface _surface1;
Graphics::Surface _surface2;
- uint16 *_zBuffer1;
- uint16 *_zBuffer2;
+ ZBuffer *_zbuffer;
Common::RandomSource _rnd;
diff --git a/engines/bladerunner/item.cpp b/engines/bladerunner/item.cpp
index b8d4cd2c1f..3ad2868c51 100644
--- a/engines/bladerunner/item.cpp
+++ b/engines/bladerunner/item.cpp
@@ -25,6 +25,7 @@
#include "bladerunner/bladerunner.h"
#include "bladerunner/slice_renderer.h"
+#include "bladerunner/zbuffer.h"
namespace BladeRunner {
@@ -75,40 +76,54 @@ bool Item::isTargetable() {
return _isTargetable;
}
-void Item::tick(bool special) {
- if (_isVisible) {
- Vector3 postition(_position.x, -_position.z, _position.y);
- int animationId = _animationId + (special ? 1 : 0);
- _vm->_sliceRenderer->drawInWorld(animationId, 0, postition, M_PI - _angle, 1.0f, _vm->_surface2, _vm->_zBuffer2);
- _vm->_sliceRenderer->getScreenRectangle(&_screenRectangle, animationId, 0, postition, M_PI - _angle, 1.0f);
+bool Item::tick(Common::Rect *screenRect, bool special) {
+ if (!_isVisible) {
+ *screenRect = Common::Rect();
+ return false;
+ }
- if (_isSpinning) {
- _facing += _facingChange;
+ bool isVisible = false;
- if (_facing >= 1024) {
- _facing -= 1024;
- } else if (_facing < 0) {
- _facing += 1024;
- }
- _angle = _facing * (M_PI / 512.0f);
+ Vector3 position(_position.x, -_position.z, _position.y);
+ int animationId = _animationId + (special ? 1 : 0);
+ _vm->_sliceRenderer->drawInWorld(animationId, 0, position, M_PI - _angle, 1.0f, _vm->_surface2, _vm->_zbuffer->getData());
+ _vm->_sliceRenderer->getScreenRectangle(&_screenRectangle, animationId, 0, position, M_PI - _angle, 1.0f);
+
+ if (!_screenRectangle.isEmpty()) {
+ *screenRect = _screenRectangle;
+ isVisible = true;
+ } else {
+ *screenRect = Common::Rect();
+ }
+
+ if (_isSpinning) {
+ _facing += _facingChange;
+ if (_facing >= 1024) {
+ _facing -= 1024;
+ } else if (_facing < 0) {
+ _facing += 1024;
+ }
+ _angle = _facing * (M_PI / 512.0f);
+
+ if (_facingChange > 0) {
+ _facingChange = _facingChange - 20;
+ if (_facingChange < 0) {
+ _facingChange = 0;
+ _isSpinning = false;
+ }
+ } else if (_facingChange < 0) {
+ _facingChange = _facingChange + 20;
if (_facingChange > 0) {
- _facingChange = _facingChange - 20;
- if (_facingChange < 0) {
- _facingChange = 0;
- _isSpinning = false;
- }
- } else if (_facingChange < 0) {
- _facingChange = _facingChange + 20;
- if (_facingChange > 0) {
- _facingChange = 0;
- _isSpinning = false;
- }
- } else {
+ _facingChange = 0;
_isSpinning = false;
}
+ } else {
+ _isSpinning = false;
}
}
+
+ return isVisible;
}
void Item::setXYZ(Vector3 position) {
diff --git a/engines/bladerunner/item.h b/engines/bladerunner/item.h
index 0c74bf3be3..76d49ac614 100644
--- a/engines/bladerunner/item.h
+++ b/engines/bladerunner/item.h
@@ -68,7 +68,7 @@ public:
void getWidthHeight(int *width, int *height);
bool isTargetable();
- void tick(bool special);
+ bool tick(Common::Rect *screenRect, bool special);
void setup(int itemId, int setId, int animationId, Vector3 position, int facing, int height, int width, bool isTargetableFlag, bool isVisibleFlag, bool isPoliceMazeEnemyFlag);
};
diff --git a/engines/bladerunner/item_pickup.cpp b/engines/bladerunner/item_pickup.cpp
index aa293c2b9b..7549c8db01 100644
--- a/engines/bladerunner/item_pickup.cpp
+++ b/engines/bladerunner/item_pickup.cpp
@@ -26,8 +26,9 @@
#include "bladerunner/audio_player.h"
#include "bladerunner/gameinfo.h"
-#include "slice_animations.h"
-#include "slice_renderer.h"
+#include "bladerunner/slice_animations.h"
+#include "bladerunner/slice_renderer.h"
+#include "bladerunner/zbuffer.h"
namespace BladeRunner {
@@ -103,6 +104,6 @@ void ItemPickup::draw() {
return;
}
- _vm->_sliceRenderer->drawOnScreen(_animationId, _animationFrame, _screenX, _screenY, _facing, _scale, _vm->_surface2, _vm->_zBuffer2);
+ _vm->_sliceRenderer->drawOnScreen(_animationId, _animationFrame, _screenX, _screenY, _facing, _scale, _vm->_surface2, _vm->_zbuffer->getData());
}
} // End of namespace BladeRunner
diff --git a/engines/bladerunner/items.cpp b/engines/bladerunner/items.cpp
index 6fa17dffd5..dda284f67d 100644
--- a/engines/bladerunner/items.cpp
+++ b/engines/bladerunner/items.cpp
@@ -24,6 +24,7 @@
#include "bladerunner/scene.h"
#include "bladerunner/scene_objects.h"
+#include "bladerunner/zbuffer.h"
namespace BladeRunner {
@@ -58,7 +59,10 @@ void Items::tick() {
continue;
}
bool set14NotTarget = setId == 14 && !_items[i]->isTargetable();
- _items[i]->tick(set14NotTarget);
+ Common::Rect screenRect;
+ if (_items[i]->tick(&screenRect, set14NotTarget)) {
+ _vm->_zbuffer->mark(screenRect);
+ }
}
}
diff --git a/engines/bladerunner/module.mk b/engines/bladerunner/module.mk
index 5ef5735a74..408d5ae207 100644
--- a/engines/bladerunner/module.mk
+++ b/engines/bladerunner/module.mk
@@ -170,7 +170,8 @@ MODULE_OBJS = \
view.o \
vqa_decoder.o \
vqa_player.o \
- waypoints.o
+ waypoints.o \
+ zbuffer.o
# This module can be built as a plugin
ifeq ($(ENABLE_BLADERUNNER), DYNAMIC_PLUGIN)
diff --git a/engines/bladerunner/mouse.cpp b/engines/bladerunner/mouse.cpp
index 675e20c0fd..be114dc1bb 100644
--- a/engines/bladerunner/mouse.cpp
+++ b/engines/bladerunner/mouse.cpp
@@ -26,6 +26,7 @@
#include "bladerunner/scene.h"
#include "bladerunner/scene_objects.h"
#include "bladerunner/shape.h"
+#include "bladerunner/zbuffer.h"
#include "graphics/surface.h"
@@ -308,7 +309,7 @@ Vector3 Mouse::getXYZ(int x, int y) {
float x3d = (2.0f / 640.0f * screenRight - 1.0f);
float y3d = (2.0f / 480.0f * screenDown - 1.0f) * 0.75f;
- uint16 zbufval = _vm->_zBuffer1[x + y * 640];
+ uint16 zbufval = _vm->_zbuffer->getZValue(x, y);
Vector3 pos;
pos.z = zbufval / 25.5f;
diff --git a/engines/bladerunner/scene.cpp b/engines/bladerunner/scene.cpp
index 05abfbe16e..be5be7cc67 100644
--- a/engines/bladerunner/scene.cpp
+++ b/engines/bladerunner/scene.cpp
@@ -105,7 +105,7 @@ bool Scene::open(int setId, int sceneId, bool isLoadingGame) {
_defaultLoopSet = true;
_specialLoopAtEnd = false;
}
- _vm->_scene->advanceFrame(_vm->_surface1, _vm->_zBuffer1);
+ _vm->_scene->advanceFrame(_vm->_surface1);
_vm->_playerActor->setAtXYZ(_actorStartPosition, _actorStartFacing);
_vm->_playerActor->setSetId(setId);
@@ -168,11 +168,11 @@ bool Scene::close(bool isLoadingGame) {
return result;
}
-int Scene::advanceFrame(Graphics::Surface &surface, uint16 *&zBuffer) {
+int Scene::advanceFrame(Graphics::Surface &surface) {
int frame = _vqaPlayer->update();
if (frame >= 0) {
surface.copyFrom(*_vqaPlayer->getSurface());
- memcpy(zBuffer, _vqaPlayer->getZBuffer(), 640 * 480 * 2);
+ _vqaPlayer->updateZBuffer(_vm->_zbuffer);
_vqaPlayer->updateView(_vm->_view);
_vqaPlayer->updateLights(_vm->_lights);
}
diff --git a/engines/bladerunner/scene.h b/engines/bladerunner/scene.h
index 5bc25fc6fc..fac67ff5f4 100644
--- a/engines/bladerunner/scene.h
+++ b/engines/bladerunner/scene.h
@@ -88,7 +88,7 @@ public:
bool open(int setId, int sceneId, bool isLoadingGame);
bool close(bool isLoadingGame);
- int advanceFrame(Graphics::Surface &surface, uint16 *&zBuffer);
+ int advanceFrame(Graphics::Surface &surface);
void setActorStart(Vector3 position, int facing);
void loopSetDefault(int a);
diff --git a/engines/bladerunner/script/scene/rc01.cpp b/engines/bladerunner/script/scene/rc01.cpp
index 1a5367b0fc..3a26cd2fdd 100644
--- a/engines/bladerunner/script/scene/rc01.cpp
+++ b/engines/bladerunner/script/scene/rc01.cpp
@@ -291,8 +291,8 @@ bool SceneScriptRC01::ClickedOnActor(int actorId) {
Game_Flag_Reset(392);
}
} else {
- I_Sez("MG: Hey, leave that officer alone.Can't you see he's busy?");
- I_Sez("JM: (...mmm, donuts...");
+ I_Sez("MG: Hey, leave that officer alone. Can't you see he's busy?");
+ I_Sez("JM: (...mmm, donuts...)");
Game_Flag_Set(3);
Actor_Clue_Acquire(0, 0, 1, 23);
Actor_Says(0, 4515, 13);
@@ -301,7 +301,7 @@ bool SceneScriptRC01::ClickedOnActor(int actorId) {
if (!Game_Flag_Query(1)) {
Actor_Says(23, 50, 14);
Actor_Says(23, 60, 15);
- I_Sez("MG: It's all fun and games until someone loses a tiger cub");
+ I_Sez("MG: It's all fun and games until someone loses a tiger cub.");
Actor_Says(0, 4520, 18);
Actor_Says(23, 70, 16);
Actor_Says(0, 4525, 14);
diff --git a/engines/bladerunner/vqa_decoder.cpp b/engines/bladerunner/vqa_decoder.cpp
index 15bf49306a..1e22257843 100644
--- a/engines/bladerunner/vqa_decoder.cpp
+++ b/engines/bladerunner/vqa_decoder.cpp
@@ -27,6 +27,7 @@
#include "bladerunner/decompress_lzo.h"
#include "bladerunner/lights.h"
#include "bladerunner/view.h"
+#include "bladerunner/zbuffer.h"
#include "audio/decoders/raw.h"
@@ -191,8 +192,8 @@ const Graphics::Surface *VQADecoder::decodeVideoFrame() {
return _videoTrack->decodeVideoFrame();
}
-const uint16 *VQADecoder::decodeZBuffer() {
- return _videoTrack->decodeZBuffer();
+void VQADecoder::decodeZBuffer(ZBuffer *zbuffer) {
+ _videoTrack->decodeZBuffer(zbuffer);
}
Audio::SeekableAudioStream *VQADecoder::decodeAudioFrame() {
@@ -552,7 +553,6 @@ VQADecoder::VQAVideoTrack::VQAVideoTrack(VQADecoder *vqaDecoder) {
_maxVPTRSize = header->maxVPTRSize;
_maxCBFZSize = header->maxCBFZSize;
_maxZBUFChunkSize = vqaDecoder->_maxZBUFChunkSize;
- _zbuffer = nullptr;
_codebookSize = 0;
_codebook = nullptr;
@@ -564,7 +564,6 @@ VQADecoder::VQAVideoTrack::VQAVideoTrack(VQADecoder *vqaDecoder) {
_curFrame = -1;
-
_zbufChunk = new uint8[roundup(_maxZBUFChunkSize)];
_surface = new Graphics::Surface();
@@ -583,7 +582,6 @@ VQADecoder::VQAVideoTrack::~VQAVideoTrack() {
if (_surface)
_surface->free();
delete _surface;
- delete[] _zbuffer;
if (_viewData)
delete[] _viewData;
@@ -668,42 +666,6 @@ bool VQADecoder::VQAVideoTrack::readCBFZ(Common::SeekableReadStream *s, uint32 s
return true;
}
-static int decodeZBUF_partial(uint8 *src, uint16 *curZBUF, uint32 srcLen) {
- uint32 dstSize = 640 * 480; // This is taken from global variables?
- uint32 dstRemain = dstSize;
-
- uint16 *curzp = curZBUF;
- uint16 *inp = (uint16*)src;
-
- while (dstRemain && (inp - (uint16*)src) < (std::ptrdiff_t)srcLen) {
- uint32 count = FROM_LE_16(*inp++);
-
- if (count & 0x8000) {
- count = MIN(count & 0x7fff, dstRemain);
- dstRemain -= count;
-
- while (count--) {
- uint16 value = FROM_LE_16(*inp++);
- if (value)
- *curzp = value;
- ++curzp;
- }
- } else {
- count = MIN(count, dstRemain);
- dstRemain -= count;
- uint16 value = FROM_LE_16(*inp++);
-
- if (!value) {
- curzp += count;
- } else {
- while (count--)
- *curzp++ = value;
- }
- }
- }
- return dstSize - dstRemain;
-}
-
bool VQADecoder::VQAVideoTrack::readZBUF(Common::SeekableReadStream *s, uint32 size) {
if (size > _maxZBUFChunkSize) {
debug("VQA ERROR: ZBUF chunk size: %08x > %08x", size, _maxZBUFChunkSize);
@@ -711,42 +673,17 @@ bool VQADecoder::VQAVideoTrack::readZBUF(Common::SeekableReadStream *s, uint32 s
return false;
}
- uint32 width, height, complete, unk0;
- width = s->readUint32LE();
- height = s->readUint32LE();
- complete = s->readUint32LE();
- unk0 = s->readUint32LE();
-
- uint32 remain = size - 16;
-
- if (_width != width || _height != height) {
- debug("%d, %d, %d, %d", width, height, complete, unk0);
- s->skip(roundup(remain));
- return false;
- }
-
- _zbufChunkComplete = complete;
- _zbufChunkSize = remain;
- s->read(_zbufChunk, roundup(remain));
+ _zbufChunkSize = size;
+ s->read(_zbufChunk, roundup(size));
return true;
}
-const uint16 *VQADecoder::VQAVideoTrack::decodeZBuffer() {
+void VQADecoder::VQAVideoTrack::decodeZBuffer(ZBuffer *zbuffer) {
if (_maxZBUFChunkSize == 0)
- return nullptr;
-
- if (!_zbuffer)
- _zbuffer = new uint16[_width * _height];
-
- if (_zbufChunkComplete) {
- size_t zbufOutSize;
- decompress_lzo1x(_zbufChunk, _zbufChunkSize, (uint8*)_zbuffer, &zbufOutSize);
- } else {
- decodeZBUF_partial(_zbufChunk, _zbuffer, _zbufChunkSize);
- }
+ return;
- return _zbuffer;
+ zbuffer->decodeData(_zbufChunk, _zbufChunkSize);
}
bool VQADecoder::VQAVideoTrack::readVIEW(Common::SeekableReadStream *s, uint32 size) {
diff --git a/engines/bladerunner/vqa_decoder.h b/engines/bladerunner/vqa_decoder.h
index 7863afaff0..fb81ef1dc3 100644
--- a/engines/bladerunner/vqa_decoder.h
+++ b/engines/bladerunner/vqa_decoder.h
@@ -40,6 +40,7 @@ namespace BladeRunner {
class Lights;
class View;
+class ZBuffer;
class VQADecoder {
public:
@@ -52,7 +53,7 @@ public:
void readPacket(int frame);
const Graphics::Surface *decodeVideoFrame();
- const uint16 *decodeZBuffer();
+ void decodeZBuffer(ZBuffer *zbuffer);
Audio::SeekableAudioStream *decodeAudioFrame();
void decodeView(View *view);
void decodeLights(Lights *lights);
@@ -160,7 +161,7 @@ private:
int getCurFrame() const;
int getFrameCount() const;
const Graphics::Surface *decodeVideoFrame();
- const uint16 *decodeZBuffer();
+ void decodeZBuffer(ZBuffer *zbuffer);
void decodeView(View *view);
void decodeLights(Lights *lights);
@@ -180,8 +181,7 @@ private:
private:
Graphics::Surface *_surface;
- uint16 *_zbuffer;
- bool _hasNewFrame;
+ bool _hasNewFrame;
uint16 _numFrames;
uint16 _width, _height;
diff --git a/engines/bladerunner/vqa_player.cpp b/engines/bladerunner/vqa_player.cpp
index c15ebc6d7a..6018f40bab 100644
--- a/engines/bladerunner/vqa_player.cpp
+++ b/engines/bladerunner/vqa_player.cpp
@@ -72,7 +72,6 @@ int VQAPlayer::update() {
if (_hasAudio)
queueAudioFrame(_decoder.decodeAudioFrame());
_surface = _decoder.decodeVideoFrame();
- _zBuffer = _decoder.decodeZBuffer();
}
_frameDecoded = calcNextFrame(_frameCurrent);
@@ -95,7 +94,6 @@ int VQAPlayer::update() {
_frameCurrent = _frameDecoded;
if (_frameCurrent >= 0) {
_surface = _decoder.decodeVideoFrame();
- _zBuffer = _decoder.decodeZBuffer();
}
_frameDecoded = calcNextFrame(_frameCurrent);
@@ -117,8 +115,8 @@ const Graphics::Surface *VQAPlayer::getSurface() const {
return _surface;
}
-const uint16 *VQAPlayer::getZBuffer() const {
- return _zBuffer;
+void VQAPlayer::updateZBuffer(ZBuffer *zbuffer) {
+ _decoder.decodeZBuffer(zbuffer);
}
void VQAPlayer::updateView(View *view) {
diff --git a/engines/bladerunner/vqa_player.h b/engines/bladerunner/vqa_player.h
index 941b3638ed..d0eb069969 100644
--- a/engines/bladerunner/vqa_player.h
+++ b/engines/bladerunner/vqa_player.h
@@ -35,6 +35,7 @@ namespace BladeRunner {
class BladeRunnerEngine;
class View;
class Lights;
+class ZBuffer;
//TODO: split this into two components as it is in original game: universal vqa player, blade runner player functionality
@@ -99,7 +100,7 @@ public:
int update();
const Graphics::Surface *getSurface() const;
- const uint16 *getZBuffer() const;
+ void updateZBuffer(ZBuffer *zbuffer);
void updateView(View *view);
void updateLights(Lights *lights);
diff --git a/engines/bladerunner/zbuffer.cpp b/engines/bladerunner/zbuffer.cpp
new file mode 100644
index 0000000000..76391f009f
--- /dev/null
+++ b/engines/bladerunner/zbuffer.cpp
@@ -0,0 +1,221 @@
+/* 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/zbuffer.h"
+
+#include "bladerunner/decompress_lzo.h"
+
+namespace BladeRunner {
+
+void ZBufferDirtyRects::reset() {
+ _count = 0;
+}
+
+bool ZBufferDirtyRects::add(Common::Rect rect) {
+ if (_count == MAX_DIRTY_RECTS)
+ return false;
+
+ _rects[_count++] = rect;
+ if (_count > 1) {
+ extendExisting();
+ }
+ return true;
+}
+
+void ZBufferDirtyRects::extendExisting() {
+ if (_count < 2)
+ return;
+
+ Common::Rect last = _rects[_count - 1];
+
+ int i;
+ for (i = 0; i != _count - 1; ++i) {
+ if (last.intersects(_rects[i])) {
+ _rects[i].extend(last);
+ _count--;
+ break;
+ }
+ }
+}
+
+int ZBufferDirtyRects::getCount() {
+ return _count;
+}
+
+bool ZBufferDirtyRects::popRect(Common::Rect *rect) {
+ if (_count == 0)
+ return false;
+
+ *rect = _rects[--_count];
+ return true;
+}
+
+ZBuffer::ZBuffer() {
+ reset();
+}
+
+ZBuffer::~ZBuffer() {
+ delete[] _zbuf1;
+ delete[] _zbuf2;
+}
+
+void ZBuffer::init(int width, int height) {
+ _width = width;
+ _height = height;
+
+ _zbuf1 = new uint16[width * height];
+ _zbuf2 = new uint16[width * height];
+
+ _dirtyRects = new ZBufferDirtyRects();
+}
+
+static int decodePartialZBuffer(const uint8 *src, uint16 *curZBUF, uint32 srcLen) {
+ uint32 dstSize = 640 * 480; // This is taken from global variables?
+ uint32 dstRemain = dstSize;
+
+ uint16 *curzp = curZBUF;
+ uint16 *inp = (uint16*)src;
+
+ while (dstRemain && (inp - (uint16*)src) < (std::ptrdiff_t)srcLen) {
+ uint32 count = FROM_LE_16(*inp++);
+
+ if (count & 0x8000) {
+ count = MIN(count & 0x7fff, dstRemain);
+ dstRemain -= count;
+
+ while (count--) {
+ uint16 value = FROM_LE_16(*inp++);
+ if (value)
+ *curzp = value;
+ ++curzp;
+ }
+ } else {
+ count = MIN(count, dstRemain);
+ dstRemain -= count;
+ uint16 value = FROM_LE_16(*inp++);
+
+ if (!value) {
+ curzp += count;
+ } else {
+ while (count--)
+ *curzp++ = value;
+ }
+ }
+ }
+ return dstSize - dstRemain;
+}
+
+bool ZBuffer::decodeData(const uint8 *data, int size) {
+ if (_disabled) {
+ return false;
+ }
+
+ uint32 width, height, complete, unk0;
+
+ width = READ_LE_UINT32(data + 0);
+ height = READ_LE_UINT32(data + 4);
+ complete = READ_LE_UINT32(data + 8);
+ unk0 = READ_LE_UINT32(data + 12);
+
+ if (width != (uint32)_width || height != (uint32)_height) {
+ warning("zbuffer size mismatch (%d, %d) != (%d, %d)", _width, _height, width, height);
+ return false;
+ }
+
+ data += 16;
+ size -= 16;
+
+ if (complete) {
+ resetUpdates();
+ size_t zbufOutSize;
+ decompress_lzo1x(data, size, (uint8*)_zbuf1, &zbufOutSize);
+ memcpy(_zbuf2, _zbuf1, 2 * _width * _height);
+ } else {
+ clean();
+ decodePartialZBuffer(data, _zbuf1, size);
+ decodePartialZBuffer(data, _zbuf2, size);
+ }
+
+ return true;
+}
+
+uint16 *ZBuffer::getData() {
+ return _zbuf2;
+}
+
+uint16 ZBuffer::getZValue(int x, int y) {
+ assert(x >= 0 && x < _width);
+ assert(y >= 0 && y < _height);
+
+ if (!_zbuf2)
+ return 0;
+
+ return _zbuf2[y * _width + x];
+}
+
+void ZBuffer::reset() {
+ _zbuf1 = nullptr;
+ _zbuf2 = nullptr;
+ _dirtyRects = nullptr;
+ _width = 0;
+ _height = 0;
+ enable();
+}
+
+void ZBuffer::blit(Common::Rect rect) {
+ int line_width = rect.width();
+
+ for (int y = rect.top; y != rect.bottom; ++y) {
+ int offset = y * _width + rect.left;
+ memcpy(_zbuf2 + offset, _zbuf1 + offset, 2 * line_width);
+ }
+}
+
+void ZBuffer::mark(Common::Rect rect) {
+ assert(rect.isValidRect());
+
+ // debug("mark %d, %d, %d, %d", rect.top, rect.right, rect.bottom, rect.left);
+ rect.clip(_width, _height);
+ _dirtyRects->add(rect);
+}
+
+void ZBuffer::clean() {
+ Common::Rect rect;
+ while (_dirtyRects->popRect(&rect)) {
+ // debug("blit %d, %d, %d, %d", rect.top, rect.right, rect.bottom, rect.left);
+ blit(rect);
+ }
+}
+
+void ZBuffer::resetUpdates() {
+ _dirtyRects->reset();
+}
+
+void ZBuffer::disable() {
+ _disabled = true;
+}
+
+void ZBuffer::enable() {
+ _disabled = false;
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/zbuffer.h b/engines/bladerunner/zbuffer.h
new file mode 100644
index 0000000000..5c771b1381
--- /dev/null
+++ b/engines/bladerunner/zbuffer.h
@@ -0,0 +1,87 @@
+/* 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_ZBUFFER_H
+#define BLADERUNNER_ZBUFFER_H
+
+#include "bladerunner/bladerunner.h"
+
+#include "common/rect.h"
+
+namespace BladeRunner {
+
+#define MAX_DIRTY_RECTS 20
+
+class ZBufferDirtyRects {
+ int _count;
+ Common::Rect _rects[MAX_DIRTY_RECTS];
+
+public:
+ ZBufferDirtyRects() :
+ _count(0)
+ {}
+
+ void reset();
+ bool add(Common::Rect rect);
+ void extendExisting();
+ int getCount();
+ bool popRect(Common::Rect *rect);
+};
+
+class ZBuffer {
+ int _width;
+ int _height;
+
+ uint16 *_zbuf1;
+ uint16 *_zbuf2;
+
+ ZBufferDirtyRects *_dirtyRects;;
+
+ bool _disabled;
+
+public:
+ ZBuffer();
+ ~ZBuffer();
+
+ void init(int width, int height);
+ bool decodeData(const uint8 *data, int size);
+
+ uint16 *getData();
+ uint16 getZValue(int x, int y);
+
+private:
+ void reset();
+ void blit(Common::Rect rect);
+
+public:
+ void mark(Common::Rect rect);
+ void clean();
+ void resetUpdates();
+
+ // Only called from Scene::resume which is not yet implemented
+ void disable();
+ void enable();
+};
+
+} // End of namespace BladeRunner
+
+#endif