[Scummvm-git-logs] scummvm master -> 5f552c9446ddf3f02ec99ff6902822d66d2cc955

madmoose thomas at fach-pedersen.net
Tue Mar 28 17:53:32 CEST 2017


This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
5f552c9446 BLADERUNNER: Implement ZBuffer class


Commit: 5f552c9446ddf3f02ec99ff6902822d66d2cc955
    https://github.com/scummvm/scummvm/commit/5f552c9446ddf3f02ec99ff6902822d66d2cc955
Author: Thomas Fach-Pedersen (thomas at fach-pedersen.net)
Date: 2017-03-28T17:50:11+02:00

Commit Message:
BLADERUNNER: Implement ZBuffer class

Changed paths:
  A engines/bladerunner/zbuffer.cpp
  A engines/bladerunner/zbuffer.h
    engines/bladerunner/actor.cpp
    engines/bladerunner/actor.h
    engines/bladerunner/bladerunner.cpp
    engines/bladerunner/bladerunner.h
    engines/bladerunner/item.cpp
    engines/bladerunner/item.h
    engines/bladerunner/item_pickup.cpp
    engines/bladerunner/items.cpp
    engines/bladerunner/module.mk
    engines/bladerunner/mouse.cpp
    engines/bladerunner/scene.cpp
    engines/bladerunner/scene.h
    engines/bladerunner/script/scene/rc01.cpp
    engines/bladerunner/vqa_decoder.cpp
    engines/bladerunner/vqa_decoder.h
    engines/bladerunner/vqa_player.cpp
    engines/bladerunner/vqa_player.h


diff --git a/engines/bladerunner/actor.cpp b/engines/bladerunner/actor.cpp
index 330ed58..f783791 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 d924730..40bcae5 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 78239ad..ec54a7c 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 87bb7db..fd62f35 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 b8d4cd2..3ad2868 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 0c74bf3..76d49ac 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 aa293c2..7549c8d 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 6fa17df..dda284f 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 5ef5735..408d5ae 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 675e20c..be114dc 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 05abfbe..be5be7c 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 5bc25fc..fac67ff 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 1a5367b..3a26cd2 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 15bf493..1e22257 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 7863afa..fb81ef1 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 c15ebc6..6018f40 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 941b363..d0eb069 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 0000000..76391f0
--- /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 0000000..5c771b1
--- /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





More information about the Scummvm-git-logs mailing list