[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