[Scummvm-git-logs] scummvm master -> f0a7d41001aee85d7a3d5aaa70b16dfb9d112285

scott-t s at sthomas.id.au
Wed Oct 27 06:29:54 UTC 2021


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:
f0a7d41001 GROOVIE: Fix ROQ decoder for certain CLAN videos


Commit: f0a7d41001aee85d7a3d5aaa70b16dfb9d112285
    https://github.com/scummvm/scummvm/commit/f0a7d41001aee85d7a3d5aaa70b16dfb9d112285
Author: Scott Thomas (s at sthomas.id.au)
Date: 2021-10-27T16:46:58+10:30

Commit Message:
GROOVIE: Fix ROQ decoder for certain CLAN videos

Thanks for madmoose for finding the root cause

Changed paths:
    engines/groovie/resource.cpp
    engines/groovie/resource.h
    engines/groovie/script.cpp
    engines/groovie/video/roq.cpp
    engines/groovie/video/roq.h


diff --git a/engines/groovie/resource.cpp b/engines/groovie/resource.cpp
index 00ea4a1148..ada07cc0be 100644
--- a/engines/groovie/resource.cpp
+++ b/engines/groovie/resource.cpp
@@ -42,13 +42,18 @@ Common::SeekableReadStream *ResMan::open(uint32 fileRef) {
 		return NULL;
 	}
 
+	debugC(1, kDebugResource, "Groovie::Resource: Opening resource %d", fileRef);
+	return open(resInfo);
+}
+
+Common::SeekableReadStream *ResMan::open(const ResInfo &resInfo) {
 	// Do we know the name of the required GJD?
 	if (resInfo.gjd >= _gjds.size()) {
 		error("Groovie::Resource: Unknown GJD %d", resInfo.gjd);
 		return NULL;
 	}
 
-	debugC(1, kDebugResource, "Groovie::Resource: Opening resource 0x%04X (%s, %d, %d, %d)", fileRef, _gjds[resInfo.gjd].c_str(), resInfo.offset, resInfo.size, resInfo.disks);
+	debugC(1, kDebugResource, "Groovie::Resource: Opening resource (%s, %d, %d, %d)", _gjds[resInfo.gjd].c_str(), resInfo.offset, resInfo.size, resInfo.disks);
 
 	// Does it exist?
 	if (!Common::File::exists(_gjds[resInfo.gjd])) {
@@ -77,17 +82,17 @@ Common::SeekableReadStream *ResMan::open(uint32 fileRef) {
 	return file;
 }
 
-void ResMan::dumpResource(Common::String &fileName) {
+void ResMan::dumpResource(const Common::String &fileName) {
 	uint32 fileRef = getRef(fileName);
 	dumpResource(fileRef, fileName);
 }
 
-void ResMan::dumpResource(uint32 fileRef, Common::String &fileName) {
+void ResMan::dumpResource(uint32 fileRef, const Common::String &fileName) {
 	Common::SeekableReadStream *inFile = open(fileRef);
 	dumpResource(inFile, fileName);
 }
 
-void ResMan::dumpResource(Common::SeekableReadStream *inFile, Common::String &fileName, bool dispose) {
+void ResMan::dumpResource(Common::SeekableReadStream *inFile, const Common::String &fileName, bool dispose) {
 	Common::DumpFile outFile;
 	outFile.open(fileName);
 
diff --git a/engines/groovie/resource.h b/engines/groovie/resource.h
index 10e55e14d8..f1145dd6f7 100644
--- a/engines/groovie/resource.h
+++ b/engines/groovie/resource.h
@@ -42,9 +42,11 @@ public:
 	virtual ~ResMan() {}
 
 	Common::SeekableReadStream *open(uint32 fileRef);
-	void dumpResource(Common::String &fileName);
-	void dumpResource(uint32 fileRef, Common::String &fileName);
-	void dumpResource(Common::SeekableReadStream *inFile, Common::String &fileName, bool dispose = true);
+	Common::SeekableReadStream *open(const ResInfo &resInfo);
+
+	void dumpResource(const Common::String &fileName);
+	void dumpResource(uint32 fileRef, const Common::String &fileName);
+	void dumpResource(Common::SeekableReadStream *inFile, const Common::String &fileName, bool dispose = true);
 
 	virtual uint32 getRef(Common::String name) = 0;
 	virtual bool getResInfo(uint32 fileRef, ResInfo &resInfo) = 0;
diff --git a/engines/groovie/script.cpp b/engines/groovie/script.cpp
index a669b1c74a..8b71a825d9 100644
--- a/engines/groovie/script.cpp
+++ b/engines/groovie/script.cpp
@@ -792,7 +792,13 @@ bool Script::playvideofromref(uint32 fileref, bool loopUntilAudioDone) {
 		}
 
 		// Try to open the new file
-		_videoFile = _vm->_resMan->open(fileref);
+		ResInfo resInfo;
+		if (!_vm->_resMan->getResInfo(fileref, resInfo)) {
+			error("Groovie::Script: Couldn't find resource info for fileref %d", fileref);
+			return true;
+		}
+
+		_videoFile = _vm->_resMan->open(resInfo);
 
 		if (_videoFile) {
 			_videoRef = fileref;
@@ -800,6 +806,10 @@ bool Script::playvideofromref(uint32 fileref, bool loopUntilAudioDone) {
 			// Filename check as sometimes teeth used for puzzle movements (bishops)
 			if (_version == kGroovieT7G && (_lastCursor == 7 || _lastCursor == 4) && _scriptFile == "script.grv")
 				_bitflags |= (1 << 15);
+			// act, door and trailer use a variation of motion blocks in the ROQ decoder.
+			// Original clan engine specifically references these files by name to set the flag
+			else if (_version == kGroovieCDY && (resInfo.filename.hasPrefix("act") || resInfo.filename.hasPrefix("door")))
+				_bitflags |= (1 << 14);
 			_vm->_videoPlayer->load(_videoFile, _bitflags);
 		} else {
 			error("Groovie::Script: Couldn't open file");
diff --git a/engines/groovie/video/roq.cpp b/engines/groovie/video/roq.cpp
index d37f05d9f9..44c601b5dd 100644
--- a/engines/groovie/video/roq.cpp
+++ b/engines/groovie/video/roq.cpp
@@ -138,8 +138,10 @@ uint16 ROQPlayer::loadInternal() {
 
 	// Flags:
 	// - 2 For overlay videos, show the whole video
+	// - 14 Manual flag indication alternate motion copy decoder
 	_flagOne = ((_flags & (1 << 1)) != 0);
 	_flagTwo = ((_flags & (1 << 2)) != 0);
+	_altMotionDecoder = ((_flags & (1 << 14)) != 0);
 
 	// Read the file header
 	ROQBlockHeader blockHeader;
@@ -433,9 +435,10 @@ bool ROQPlayer::processBlock() {
 		_file->skip(blockHeader.size);
 	}
 
-	if (endpos != _file->pos())
+	if (endpos != _file->pos()) {
 		warning("Groovie::ROQ: BLOCK %04x Should have ended at %d, and has ended at %d", blockHeader.type, endpos, (int)_file->pos());
-
+		_file->seek(endpos);
+	}
 	// End the frame when the graphics have been modified or when there's an error
 	return endframe || !ok;
 }
@@ -557,8 +560,8 @@ bool ROQPlayer::processBlockQuadVector(ROQBlockHeader &blockHeader) {
 	debugC(5, kDebugVideo, "Groovie::ROQ: Processing quad vector block");
 
 	// Get the mean motion vectors
-	int8 Mx = blockHeader.param >> 8;
-	int8 My = blockHeader.param & 0xFF;
+	_motionOffX = blockHeader.param >> 8;
+	_motionOffY = blockHeader.param & 0xFF;
 
 	// Calculate where the block should end
 	int32 endpos =_file->pos() + blockHeader.size;
@@ -572,7 +575,7 @@ bool ROQPlayer::processBlockQuadVector(ROQBlockHeader &blockHeader) {
 			// Traverse the macroblock in 8x8 blocks
 			for (int blockY = 0; blockY < 16; blockY += 8) {
 				for (int blockX = 0; blockX < 16; blockX += 8) {
-					processBlockQuadVectorBlock(macroX + blockX, macroY + blockY, Mx, My);
+					processBlockQuadVectorBlock(macroX + blockX, macroY + blockY);
 				}
 			}
 		}
@@ -589,16 +592,16 @@ bool ROQPlayer::processBlockQuadVector(ROQBlockHeader &blockHeader) {
 	return true;
 }
 
-void ROQPlayer::processBlockQuadVectorBlock(int baseX, int baseY, int8 Mx, int8 My) {
+void ROQPlayer::processBlockQuadVectorBlock(int baseX, int baseY) {
 	uint16 codingType = getCodingType();
 	switch (codingType) {
 	case 0: // MOT: Skip block
 		break;
 	case 1: { // FCC: Copy an existing block
 		byte argument = _file->readByte();
-		int16 DDx = 8 - (argument >> 4);
-		int16 DDy = 8 - (argument & 0x0F);
-		copy(8, baseX, baseY, DDx - Mx, DDy - My);
+		int16 dx = 8 - (argument >> 4);
+		int16 dy = 8 - (argument & 0x0F);
+		copy(8, baseX, baseY, dx, dy);
 		break;
 	}
 	case 2: // SLD: Quad vector quantisation
@@ -609,7 +612,7 @@ void ROQPlayer::processBlockQuadVectorBlock(int baseX, int baseY, int8 Mx, int8
 		// Traverse the block in 4x4 sub-blocks
 		for (int subBlockY = 0; subBlockY < 8; subBlockY += 4) {
 			for (int subBlockX = 0; subBlockX < 8; subBlockX += 4) {
-				processBlockQuadVectorBlockSub(baseX + subBlockX, baseY + subBlockY, Mx, My);
+				processBlockQuadVectorBlockSub(baseX + subBlockX, baseY + subBlockY);
 			}
 		}
 		break;
@@ -618,7 +621,7 @@ void ROQPlayer::processBlockQuadVectorBlock(int baseX, int baseY, int8 Mx, int8
 	}
 }
 
-void ROQPlayer::processBlockQuadVectorBlockSub(int baseX, int baseY, int8 Mx, int8 My) {
+void ROQPlayer::processBlockQuadVectorBlockSub(int baseX, int baseY) {
 	debugC(6, kDebugVideo, "Groovie::ROQ: Processing quad vector sub block");
 
 	uint16 codingType = getCodingType();
@@ -627,9 +630,9 @@ void ROQPlayer::processBlockQuadVectorBlockSub(int baseX, int baseY, int8 Mx, in
 		break;
 	case 1: { // FCC: Copy an existing block
 		byte argument = _file->readByte();
-		int16 DDx = 8 - (argument >> 4);
-		int16 DDy = 8 - (argument & 0x0F);
-		copy(4, baseX, baseY, DDx - Mx, DDy - My);
+		int16 dx = 8 - (argument >> 4);
+		int16 dy = 8 - (argument & 0x0F);
+		copy(4, baseX, baseY, dx, dy);
 		break;
 	}
 	case 2: // SLD: Quad vector quantisation
@@ -835,9 +838,14 @@ void ROQPlayer::paint8(byte i, int destx, int desty) {
 	}
 }
 
-void ROQPlayer::copy(byte size, int destx, int desty, int offx, int offy) {
-	offx *= _offScale / _scaleX;
-	offy *= _offScale / _scaleY;
+ void ROQPlayer::copy(byte size, int destx, int desty, int dx, int dy) {
+	int offx = (dx - _motionOffX) * (_offScale / _scaleX);
+	int offy = (dy - _motionOffY) * (_offScale / _scaleY);
+
+	if (_altMotionDecoder) {
+		offx *= 2;
+		offy *= 2;
+	}
 
 	// Get the beginning of the first line
 	byte *dst = (byte *)_currBuf->getBasePtr(destx, desty);
diff --git a/engines/groovie/video/roq.h b/engines/groovie/video/roq.h
index 482d3644d7..32e3964934 100644
--- a/engines/groovie/video/roq.h
+++ b/engines/groovie/video/roq.h
@@ -63,8 +63,8 @@ private:
 	bool processBlockInfo(ROQBlockHeader &blockHeader);
 	bool processBlockQuadCodebook(ROQBlockHeader &blockHeader);
 	bool processBlockQuadVector(ROQBlockHeader &blockHeader);
-	void processBlockQuadVectorBlock(int baseX, int baseY, int8 Mx, int8 My);
-	void processBlockQuadVectorBlockSub(int baseX, int baseY, int8 Mx, int8 My);
+	void processBlockQuadVectorBlock(int baseX, int baseY);
+	void processBlockQuadVectorBlockSub(int baseX, int baseY);
 	bool processBlockStill(ROQBlockHeader &blockHeader);
 	bool processBlockSoundMono(ROQBlockHeader &blockHeader);
 	bool processBlockSoundStereo(ROQBlockHeader &blockHeader);
@@ -74,7 +74,7 @@ private:
 	void paint2(byte i, int destx, int desty);
 	void paint4(byte i, int destx, int desty);
 	void paint8(byte i, int destx, int desty);
-	void copy(byte size, int destx, int desty, int offx, int offy);
+	void copy(byte size, int destx, int desty, int dx, int dy);
 
 	// Origin
 	int16 _origX, _origY;
@@ -95,11 +95,13 @@ private:
 	// Flags
 	bool _flagOne;	// Play only first frame and do not print the image to the screen
 	bool _flagTwo;	// If _flagOne is set. Copy frame to the foreground otherwise to the background
+	bool _altMotionDecoder; // Some ROQ vids use a variation on the copy codeblock
 
 	// Buffers
 	void buildShowBuf();
 	byte _scaleX, _scaleY;
 	byte _offScale;
+	int8 _motionOffX, _motionOffY;
 	bool _interlacedVideo;
 	bool _dirty;
 	byte _alpha;




More information about the Scummvm-git-logs mailing list