[Scummvm-git-logs] scummvm master -> b87f98602e0b0023816f5823d22bf9bdf267602f
fracturehill
76959842+fracturehill at users.noreply.github.com
Wed Apr 28 14:08:11 UTC 2021
This automated email contains information about 4 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
090b909631 NANCY: Secondary video fixes
7819ef1c17 NANCY: Fix PlaySoundMultiHS action record in The Vampire Diaries
cf43a600f5 NANCY: Implement sound in The Vampire Diaries
b87f98602e NANCY: Correct logo skip timing in The Vampire Diaries
Commit: 090b9096311001d47801420b4ae118a870cba1ba
https://github.com/scummvm/scummvm/commit/090b9096311001d47801420b4ae118a870cba1ba
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2021-04-28T17:02:58+03:00
Commit Message:
NANCY: Secondary video fixes
Fixed the logic in PlaySecondaryVideo so it properly displays TVD's
character portraits.
Changed paths:
engines/nancy/action/secondaryvideo.cpp
engines/nancy/action/secondaryvideo.h
diff --git a/engines/nancy/action/secondaryvideo.cpp b/engines/nancy/action/secondaryvideo.cpp
index 83cd3cbe40..c6fbfd35a2 100644
--- a/engines/nancy/action/secondaryvideo.cpp
+++ b/engines/nancy/action/secondaryvideo.cpp
@@ -47,11 +47,12 @@ void PlaySecondaryVideo::init() {
_drawSurface.create(_decoder.getWidth(), _decoder.getHeight(), g_nancy->_graphicsManager->getInputPixelFormat());
if (_paletteFilename.size()) {
- GraphicsManager::loadSurfacePalette(_drawSurface, _paletteFilename);
+ GraphicsManager::loadSurfacePalette(_fullFrame, _paletteFilename);
}
setVisible(false);
setTransparent(true);
+ _fullFrame.setTransparentColor(_drawSurface.getTransparentColor());
RenderObject::init();
}
@@ -61,64 +62,73 @@ void PlaySecondaryVideo::updateGraphics() {
return;
}
- if (_isPlaying) {
- if (!_decoder.isPlaying()) {
- _decoder.start();
- }
-
+ if (_isInFrame) {
+ int lastAnimationFrame = -1;
switch (_hoverState) {
case kNoHover:
if (_isHovered) {
- _decoder.seekToFrame(_onHoverFirstFrame);
-
_hoverState = kHover;
+ _decoder.start();
+ _decoder.seekToFrame(_onHoverFirstFrame);
} else {
- if (_decoder.getCurFrame() == _loopLastFrame) {
- // loop back to beginning
- _decoder.seekToFrame(_loopFirstFrame);
- }
-
- break;
+ lastAnimationFrame = _loopLastFrame;
}
- // fall through
+
+ break;
case kHover:
if (!_isHovered) {
- // Stopped hovering, reverse playback
- _decoder.seekToFrame(_onHoverEndLastFrame);
- _decoder.setRate(-_decoder.getRate());
+ _hoverState = kEndHover;
+
if (!_decoder.isPlaying()) {
_decoder.start();
}
- _hoverState = kEndHover;
+ _decoder.seekToFrame(_onHoverEndLastFrame);
+ _decoder.setRate(-_decoder.getRate());
} else {
- break;
+ lastAnimationFrame = _onHoverLastFrame;
}
- // fall through
+
+ break;
case kEndHover:
- if (_decoder.getCurFrame() == _onHoverEndFirstFrame) {
- // reversed playback has ended, go back to no hover _state
+ if (!_decoder.isPlaying()) {
+ _decoder.start();
_decoder.seekToFrame(_loopFirstFrame);
- _decoder.setRate(-_decoder.getRate());
+ lastAnimationFrame = _loopLastFrame;
_hoverState = kNoHover;
+ } else {
+ lastAnimationFrame = _onHoverEndFirstFrame;
}
+ }
- break;
+ if (_decoder.isPlaying() && _decoder.needsUpdate()) {
+ GraphicsManager::copyToManaged(*_decoder.decodeNextFrame(), _fullFrame, _paletteFilename.size() > 0);
+ _needsRedraw = true;
+
+ if (lastAnimationFrame > -1 && _decoder.getCurFrame() == lastAnimationFrame + (_decoder.getRate().getNumerator() > 0 ? 1 : -1)) {
+ if (_hoverState == kNoHover) {
+ _decoder.seekToFrame(_loopFirstFrame);
+ } else {
+ _decoder.stop();
+ }
+ }
}
- if (_decoder.needsUpdate() && !_screenPosition.isEmpty()) {
+ if (_needsRedraw && _isVisible) {
+ int vpFrame = -1;
for (uint i = 0; i < _videoDescs.size(); ++i) {
- if ((uint16)_videoDescs[i].frameID == _currentViewportFrame) {
- // This ignores the srcRects for every frame
- GraphicsManager::copyToManaged(*_decoder.decodeNextFrame(), _drawSurface, _paletteFilename.size() > 0);
+ if (_videoDescs[i].frameID == _currentViewportFrame) {
+ vpFrame = i;
break;
}
}
- _needsRedraw = true;
+ _drawSurface.create(_fullFrame, _videoDescs[vpFrame].srcRect);
+ _screenPosition = _videoDescs[vpFrame].destRect;
+ _hotspot = _screenPosition;
+ _hotspot.clip(NancySceneState.getViewport().getBounds());
+ _hasHotspot = true;
}
- } else {
- _decoder.seekToFrame(0);
}
RenderObject::updateGraphics();
@@ -181,30 +191,37 @@ void PlaySecondaryVideo::execute() {
// fall through
case kRun: {
// Set correct position according to viewport frame
- if (_currentViewportFrame != NancySceneState.getSceneInfo().frameID) {
- _currentViewportFrame = NancySceneState.getSceneInfo().frameID;
+ UI::Viewport &vp = NancySceneState.getViewport();
- int activeFrame = -1;
+ if ( _currentViewportFrame != vp.getCurFrame() ||
+ _currentViewportScroll != vp.getCurVerticalScroll()) {
+ _currentViewportScroll = vp.getCurVerticalScroll();
for (uint i = 0; i < _videoDescs.size(); ++i) {
- if ((uint16)_videoDescs[i].frameID == _currentViewportFrame) {
- activeFrame = i;
+ if ((uint16)_videoDescs[i].frameID == vp.getCurFrame()) {
+ _currentViewportFrame = vp.getCurFrame();
+ break;
}
+
+ _currentViewportFrame = -1;
}
- if (activeFrame != -1) {
- // Make the drawing destination rectangle valid
- _screenPosition = _videoDescs[activeFrame].destRect;
+ if (_currentViewportFrame != -1) {
+ if (!_isInFrame) {
+ _decoder.start();
+ _decoder.seekToFrame(_loopFirstFrame);
+ }
- // Activate the hotspot
- _hotspot = _videoDescs[activeFrame].destRect;
- _hasHotspot = true;
- _isPlaying = true;
+ _isInFrame = true;
+ _hoverState = kNoHover;
setVisible(true);
} else {
- setVisible(false);
- _hasHotspot = false;
- _isPlaying = false;
+ if (_isVisible) {
+ setVisible(false);
+ _hasHotspot = false;
+ _isInFrame = false;
+ _decoder.stop();
+ }
}
}
diff --git a/engines/nancy/action/secondaryvideo.h b/engines/nancy/action/secondaryvideo.h
index e752894e8d..68793c94fa 100644
--- a/engines/nancy/action/secondaryvideo.h
+++ b/engines/nancy/action/secondaryvideo.h
@@ -65,10 +65,12 @@ protected:
virtual Common::String getRecordTypeName() const override { return Common::String::format("PlaySecondaryVideoChan%i", channel); }
virtual bool isViewportRelative() const override { return true; }
+ Graphics::ManagedSurface _fullFrame;
HoverState _hoverState = kNoHover;
AVFDecoder _decoder;
int _currentViewportFrame = -1;
- bool _isPlaying = false;
+ int _currentViewportScroll = -1;
+ bool _isInFrame = false;
bool _isHovered = false;
uint channel;
Commit: 7819ef1c17ae5403908309d92c474001cd5fc923
https://github.com/scummvm/scummvm/commit/7819ef1c17ae5403908309d92c474001cd5fc923
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2021-04-28T17:02:58+03:00
Commit Message:
NANCY: Fix PlaySoundMultiHS action record in The Vampire Diaries
Action record type PlaySoundMultiHS no longer crashes the game
when playing The Vampire Diaries.
Changed paths:
engines/nancy/action/recordtypes.cpp
diff --git a/engines/nancy/action/recordtypes.cpp b/engines/nancy/action/recordtypes.cpp
index f2ffa22417..ea6c61f1ed 100644
--- a/engines/nancy/action/recordtypes.cpp
+++ b/engines/nancy/action/recordtypes.cpp
@@ -521,10 +521,17 @@ void PlaySoundPanFrameAnchorAndDie::readData(Common::SeekableReadStream &stream)
void PlaySoundMultiHS::readData(Common::SeekableReadStream &stream) {
_sound.read(stream, SoundDescription::kNormal);
- _sceneChange.readData(stream);
- _flag.label = stream.readSint16LE();
- _flag.flag = (NancyFlag)stream.readByte();
- stream.skip(2);
+
+ if (g_nancy->getGameType() != kGameTypeVampire) {
+ _sceneChange.readData(stream);
+ _flag.label = stream.readSint16LE();
+ _flag.flag = (NancyFlag)stream.readByte();
+ stream.skip(2);
+ } else {
+ _flag.label = -1;
+ _sceneChange.sceneID = 9999;
+ }
+
uint16 numHotspots = stream.readUint16LE();
_hotspots.reserve(numHotspots);
Commit: cf43a600f5c45f1b554d3c38c7fa058074a225c8
https://github.com/scummvm/scummvm/commit/cf43a600f5c45f1b554d3c38c7fa058074a225c8
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2021-04-28T17:02:59+03:00
Commit Message:
NANCY: Implement sound in The Vampire Diaries
Unlike all later games using the engine, TVD sounds are stored in
an obscure file format (.dwd, DiamondWare Digitized). This commit adds support for uncompressed .dwd files and thus enables audio
in the game.
Changed paths:
engines/nancy/sound.cpp
diff --git a/engines/nancy/sound.cpp b/engines/nancy/sound.cpp
index 7e8dcc6ee5..41b7420bd2 100644
--- a/engines/nancy/sound.cpp
+++ b/engines/nancy/sound.cpp
@@ -33,6 +33,7 @@
namespace Nancy {
enum SoundType {
+ kSoundTypeDiamondware,
kSoundTypeRaw,
kSoundTypeOgg
};
@@ -73,6 +74,36 @@ static const Audio::Mixer::SoundType channelSoundTypes[] = {
Audio::Mixer::kSFXSoundType
};
+bool readDiamondwareHeader(Common::SeekableReadStream *stream, SoundType &type, uint16 &numChannels,
+ uint32 &samplesPerSec, uint16 &bitsPerSample, uint32 &size) {
+ stream->skip(2);
+
+ if (stream->readByte() != 1 || stream->readByte() != 0) {
+ // Version, only 1.0 is supported
+ return false;
+ }
+
+ stream->skip(5); // sound id, reserved
+
+ if (stream->readByte() != 0) {
+ // Compression type, only uncompressed (0) is supported
+ return false;
+ }
+
+ samplesPerSec = stream->readUint16LE();
+ numChannels = stream->readByte();
+ bitsPerSample = stream->readByte();
+ stream->skip(2); // Absolute value of largest sample in file
+ size = stream->readUint32LE();
+ stream->skip(4); // Number of samples
+ uint dataOffset = stream->readUint16LE();
+ stream->seek(dataOffset);
+
+ type = kSoundTypeDiamondware;
+
+ return true;
+}
+
bool readWaveHeader(Common::SeekableReadStream *stream, SoundType &type, uint16 &numChannels,
uint32 &samplesPerSec, uint16 &bitsPerSample, uint32 &size) {
// The earliest HIS files are just WAVE files with the first 22 bytes of
@@ -160,35 +191,39 @@ Audio::SeekableAudioStream *SoundManager::makeHISStream(Common::SeekableReadStre
stream->read(buf, 22);
buf[21] = 0;
+ Common::String headerID(buf);
uint16 numChannels = 0, bitsPerSample = 0;
uint32 samplesPerSec = 0, size = 0;
SoundType type = kSoundTypeRaw;
- if (Common::String(buf) == "Her Interactive Sound") {
+ if (headerID == "DiamondWare Digitized") {
+ if (!readDiamondwareHeader(stream, type, numChannels, samplesPerSec, bitsPerSample, size))
+ return 0;
+ } else if (headerID == "Her Interactive Sound") {
// Early HIS file
if (!readWaveHeader(stream, type, numChannels, samplesPerSec, bitsPerSample, size))
return 0;
- } else if (Common::String(buf) == "HIS") {
+ } else if (headerID == "HIS") {
stream->seek(4);
if (!readHISHeader(stream, type, numChannels, samplesPerSec, bitsPerSample, size))
return 0;
}
byte flags = 0;
- if (type == kSoundTypeRaw) {
- if (bitsPerSample == 8) // 8 bit data is unsigned
- flags |= Audio::FLAG_UNSIGNED;
- else if (bitsPerSample == 16) // 16 bit data is signed little endian
+ if (type == kSoundTypeRaw || type == kSoundTypeDiamondware) {
+ if (bitsPerSample == 8) { // 8 bit data is unsigned in HIS files and signed in DWD files
+ flags |= (type == kSoundTypeRaw ? Audio::FLAG_UNSIGNED : Audio::FLAG_LITTLE_ENDIAN);
+ } else if (bitsPerSample == 16) { // 16 bit data is signed little endian
flags |= (Audio::FLAG_16BITS | Audio::FLAG_LITTLE_ENDIAN);
- else {
+ } else {
warning("Unsupported bitsPerSample %d found in HIS file", bitsPerSample);
return 0;
}
- if (numChannels == 2)
+ if (numChannels == 2) {
flags |= Audio::FLAG_STEREO;
- else if (numChannels != 1) {
+ } else if (numChannels != 1) {
warning("Unsupported number of channels %d found in HIS file", numChannels);
return 0;
}
@@ -196,14 +231,14 @@ Audio::SeekableAudioStream *SoundManager::makeHISStream(Common::SeekableReadStre
// Raw PCM, make sure the last packet is complete
uint sampleSize = (flags & Audio::FLAG_16BITS ? 2 : 1) * (flags & Audio::FLAG_STEREO ? 2 : 1);
if (size % sampleSize != 0) {
- warning("Trying to play an HIS file with an incomplete PCM packet");
+ warning("Trying to play an %s file with an incomplete PCM packet", type == kSoundTypeDiamondware ? "DWD" : "HIS");
size &= ~(sampleSize - 1);
}
}
Common::SeekableSubReadStream *subStream = new Common::SeekableSubReadStream(stream, stream->pos(), stream->pos() + size, disposeAfterUse);
- if (type == kSoundTypeRaw)
+ if (type == kSoundTypeRaw || type == kSoundTypeDiamondware)
return Audio::makeRawStream(subStream, samplesPerSec, flags, DisposeAfterUse::YES);
else
return Audio::makeVorbisStream(subStream, DisposeAfterUse::YES);
@@ -266,7 +301,7 @@ void SoundManager::loadSound(const SoundDescription &description) {
_channels[description.channelID].volume = description.volume;
- Common::SeekableReadStream *file = SearchMan.createReadStreamForMember(description.name + ".his");
+ Common::SeekableReadStream *file = SearchMan.createReadStreamForMember(description.name + (g_nancy->getGameType() == kGameTypeVampire ? ".dwd" : ".his"));
if (file) {
_channels[description.channelID].stream = makeHISStream(file, DisposeAfterUse::YES);
}
Commit: b87f98602e0b0023816f5823d22bf9bdf267602f
https://github.com/scummvm/scummvm/commit/b87f98602e0b0023816f5823d22bf9bdf267602f
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2021-04-28T17:02:59+03:00
Commit Message:
NANCY: Correct logo skip timing in The Vampire Diaries
Added a new logoEndAfter game constant, which controls how long
the game logo will stay on screen after booting the game, and
extracted its value for The Vampire Diaries.
Changed paths:
engines/nancy/constants.cpp
engines/nancy/constants.h
engines/nancy/state/logo.cpp
diff --git a/engines/nancy/constants.cpp b/engines/nancy/constants.cpp
index 923c996183..1a853a96c9 100644
--- a/engines/nancy/constants.cpp
+++ b/engines/nancy/constants.cpp
@@ -32,7 +32,8 @@ const GameConstants gameConstants[] {
{ 0, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 125, 219, 220, -1 },
{ 110, 111, 112, 113, 114, -1 },
8,
- 10
+ 10,
+ 167000
},
// Nancy Drew: Secrets Can Kill
@@ -44,7 +45,8 @@ const GameConstants gameConstants[] {
63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
75, 76, 77, 78, 79, 80, 81, 82, 83, 84, -1 },
12,
- 7
+ 7,
+ 7000
},
// Nancy Drew: Stay Tuned For Danger
@@ -56,7 +58,8 @@ const GameConstants gameConstants[] {
11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
21, 22, 23, 24, 25, 26, 27, 28, 29, 30, -1 },
12, // TODO
- 7 // TODO
+ 7, // TODO
+ 7000 // TODO
}
};
diff --git a/engines/nancy/constants.h b/engines/nancy/constants.h
index 4a9b66b098..3afbc9f795 100644
--- a/engines/nancy/constants.h
+++ b/engines/nancy/constants.h
@@ -35,6 +35,7 @@ struct GameConstants {
int eventFlagsToClearOnSceneChange[32];
uint numNonItemCursors;
uint numCurtainAnimationFrames;
+ uint logoEndAfter;
};
extern const GameConstants gameConstants[];
diff --git a/engines/nancy/state/logo.cpp b/engines/nancy/state/logo.cpp
index 87338aabe7..67a3093063 100644
--- a/engines/nancy/state/logo.cpp
+++ b/engines/nancy/state/logo.cpp
@@ -25,6 +25,7 @@
#include "engines/nancy/nancy.h"
#include "engines/nancy/sound.h"
#include "engines/nancy/input.h"
+#include "engines/nancy/constants.h"
#include "engines/nancy/state/logo.h"
@@ -73,7 +74,8 @@ void Logo::startSound() {
}
void Logo::run() {
- if (g_nancy->getTotalPlayTime() - _startTicks >= 7000 || (g_nancy->_input->getInput().input & NancyInput::kLeftMouseButtonDown)) {
+ if ((g_nancy->getTotalPlayTime() - _startTicks >= g_nancy->getConstants().logoEndAfter) ||
+ (g_nancy->_input->getInput().input & NancyInput::kLeftMouseButtonDown)) {
_state = kStop;
}
}
More information about the Scummvm-git-logs
mailing list