[Scummvm-git-logs] scummvm master -> 3dd19a47e1ab4559fa8a494473c8c624cf4bfaa6
fracturehill
76959842+fracturehill at users.noreply.github.com
Thu Apr 29 13:06:58 UTC 2021
This automated email contains information about 5 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
46e7231628 NANCY: Implement non-wrapping scenes
4b48535395 NANCY: Add support for DiamondWare v1.1 sound files
6efcbebef5 NANCY: Fix primary video in The Vampire Diaries
6abc61edf7 NANCY: Render text in The Vampire Diaries
3dd19a47e1 NANCY: Set correct cursor when hovering a UI element
Commit: 46e723162882c66ec768ec069db496718a545757
https://github.com/scummvm/scummvm/commit/46e723162882c66ec768ec069db496718a545757
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2021-04-29T15:58:59+03:00
Commit Message:
NANCY: Implement non-wrapping scenes
Implemented scenes that don't wrap around when they go beyond
the first/last frame of the video.
Changed paths:
engines/nancy/state/scene.cpp
engines/nancy/state/scene.h
engines/nancy/ui/viewport.cpp
engines/nancy/ui/viewport.h
diff --git a/engines/nancy/state/scene.cpp b/engines/nancy/state/scene.cpp
index 4845f77333..937fc8a383 100644
--- a/engines/nancy/state/scene.cpp
+++ b/engines/nancy/state/scene.cpp
@@ -69,7 +69,9 @@ void Scene::SceneSummary::read(Common::SeekableReadStream &stream) {
sound.read(stream, SoundDescription::kScene);
- ser.skip(0x10);
+ ser.skip(6);
+ ser.syncAsByte(dontWrap);
+ ser.skip(9);
ser.syncAsUint16LE(verticalScrollDelta);
ser.syncAsUint16LE(horizontalEdgeSize);
ser.syncAsUint16LE(verticalEdgeSize);
@@ -488,6 +490,7 @@ void Scene::load() {
_viewport.loadVideo(_sceneState.summary.videoFile,
_sceneState.nextScene.frameID,
_sceneState.nextScene.verticalOffset,
+ _sceneState.summary.dontWrap,
_sceneState.summary.videoFormat,
_sceneState.summary.videoPaletteFile);
diff --git a/engines/nancy/state/scene.h b/engines/nancy/state/scene.h
index 3710183203..197e32ea9b 100644
--- a/engines/nancy/state/scene.h
+++ b/engines/nancy/state/scene.h
@@ -94,6 +94,8 @@ public:
Common::String audioFile;
SoundDescription sound;
//
+ NancyFlag dontWrap;
+ //
uint16 verticalScrollDelta;
uint16 horizontalEdgeSize;
uint16 verticalEdgeSize;
diff --git a/engines/nancy/ui/viewport.cpp b/engines/nancy/ui/viewport.cpp
index 7a85f3f6dc..ac26209834 100644
--- a/engines/nancy/ui/viewport.cpp
+++ b/engines/nancy/ui/viewport.cpp
@@ -179,7 +179,7 @@ void Viewport::handleInput(NancyInput &input) {
_movementLastFrame = direction;
}
-void Viewport::loadVideo(const Common::String &filename, uint frameNr, uint verticalScroll, uint16 format, const Common::String &palette) {
+void Viewport::loadVideo(const Common::String &filename, uint frameNr, uint verticalScroll, NancyFlag dontWrap, uint16 format, const Common::String &palette) {
if (_decoder.isVideoLoaded()) {
_decoder.close();
}
@@ -202,6 +202,7 @@ void Viewport::loadVideo(const Common::String &filename, uint frameNr, uint vert
_movementLastFrame = 0;
_nextMovementTime = 0;
+ _dontWrap = dontWrap;
}
void Viewport::setFrame(uint frameNr) {
@@ -215,6 +216,16 @@ void Viewport::setFrame(uint frameNr) {
_needsRedraw = true;
_currentFrame = frameNr;
+
+ if (_dontWrap == kTrue && !((_edgesMask & kLeft) && (_edgesMask & kRight))) {
+ if (_currentFrame == 0) {
+ disableEdges(kRight);
+ } else if (_currentFrame == getFrameCount() - 1) {
+ disableEdges(kLeft);
+ } else {
+ enableEdges(kLeft | kRight);
+ }
+ }
}
void Viewport::setNextFrame() {
diff --git a/engines/nancy/ui/viewport.h b/engines/nancy/ui/viewport.h
index b31ed3f9b3..e944cb2349 100644
--- a/engines/nancy/ui/viewport.h
+++ b/engines/nancy/ui/viewport.h
@@ -47,14 +47,15 @@ public:
_edgesMask(0),
_currentFrame(0),
_videoFormat(0),
- _stickyCursorPos(-1, -1) {}
+ _stickyCursorPos(-1, -1),
+ _dontWrap(kFalse) {}
virtual ~Viewport() { _decoder.close(); _fullFrame.free(); }
virtual void init() override;
void handleInput(NancyInput &input);
- void loadVideo(const Common::String &filename, uint frameNr = 0, uint verticalScroll = 0, uint16 format = 2, const Common::String &palette = Common::String());
+ void loadVideo(const Common::String &filename, uint frameNr = 0, uint verticalScroll = 0, NancyFlag dontWrap = kFalse, uint16 format = 2, const Common::String &palette = Common::String());
void setFrame(uint frameNr);
void setNextFrame();
@@ -86,6 +87,8 @@ protected:
byte _movementLastFrame;
Time _nextMovementTime;
+ NancyFlag _dontWrap;
+
AVFDecoder _decoder;
uint16 _currentFrame;
uint16 _videoFormat;
Commit: 4b48535395d7e3b74d958457d5404fbc6fa07d6a
https://github.com/scummvm/scummvm/commit/4b48535395d7e3b74d958457d5404fbc6fa07d6a
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2021-04-29T15:58:59+03:00
Commit Message:
NANCY: Add support for DiamondWare v1.1 sound files
Bumped up the supported version of DWD files to 1.1 so a couple of
special cases in The Vampire Diaries can play.
Changed paths:
engines/nancy/sound.cpp
diff --git a/engines/nancy/sound.cpp b/engines/nancy/sound.cpp
index 41b7420bd2..0d71ca1da6 100644
--- a/engines/nancy/sound.cpp
+++ b/engines/nancy/sound.cpp
@@ -78,8 +78,8 @@ bool readDiamondwareHeader(Common::SeekableReadStream *stream, SoundType &type,
uint32 &samplesPerSec, uint16 &bitsPerSample, uint32 &size) {
stream->skip(2);
- if (stream->readByte() != 1 || stream->readByte() != 0) {
- // Version, only 1.0 is supported
+ if (stream->readByte() != 1 || stream->readByte() > 1) {
+ // Version, up to 1.1 is supported
return false;
}
Commit: 6efcbebef5ad22654f93d056cddfd590c300d898
https://github.com/scummvm/scummvm/commit/6efcbebef5ad22654f93d056cddfd590c300d898
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2021-04-29T15:58:59+03:00
Commit Message:
NANCY: Fix primary video in The Vampire Diaries
Primary videos in The Vampire Diaries now load and display correctly.
Changed paths:
engines/nancy/action/primaryvideo.cpp
engines/nancy/action/primaryvideo.h
diff --git a/engines/nancy/action/primaryvideo.cpp b/engines/nancy/action/primaryvideo.cpp
index 861cb58174..17e8579aaf 100644
--- a/engines/nancy/action/primaryvideo.cpp
+++ b/engines/nancy/action/primaryvideo.cpp
@@ -23,11 +23,13 @@
#include "common/system.h"
#include "common/random.h"
#include "common/config-manager.h"
+#include "common/serializer.h"
#include "engines/nancy/nancy.h"
#include "engines/nancy/sound.h"
#include "engines/nancy/input.h"
#include "engines/nancy/util.h"
+#include "engines/nancy/graphics.h"
#include "engines/nancy/action/primaryvideo.h"
#include "engines/nancy/action/responses.cpp"
@@ -123,6 +125,11 @@ void PlayPrimaryVideoChan0::init() {
_drawSurface.create(_src.width(), _src.height(), _decoder.getPixelFormat());
+ if (!_paletteName.empty()) {
+ GraphicsManager::loadSurfacePalette(_drawSurface, _paletteName);
+ setTransparent(true);
+ }
+
RenderObject::init();
NancySceneState.setShouldClearTextbox(false);
@@ -138,7 +145,17 @@ void PlayPrimaryVideoChan0::updateGraphics() {
}
if (_decoder.needsUpdate()) {
- _drawSurface.blitFrom(*_decoder.decodeNextFrame(), _src, Common::Point());
+ if (_videoFormat == 2) {
+ _drawSurface.blitFrom(*_decoder.decodeNextFrame(), _src, Common::Point());
+ } else if (_videoFormat == 1) {
+ // This seems to be the only place in the engine where format 1 videos
+ // are scaled with arbitrary sizes; everything else uses double size
+ Graphics::Surface *scaledFrame = _decoder.decodeNextFrame()->getSubArea(_src).scale(_screenPosition.width(), _screenPosition.height());
+ GraphicsManager::copyToManaged(*scaledFrame, _drawSurface, true);
+ scaledFrame->free();
+ delete scaledFrame;
+ }
+
_needsRedraw = true;
}
@@ -154,48 +171,58 @@ void PlayPrimaryVideoChan0::onPause(bool pause) {
}
void PlayPrimaryVideoChan0::readData(Common::SeekableReadStream &stream) {
- uint16 beginOffset = stream.pos();
+ Common::Serializer ser(&stream, nullptr);
+ ser.setVersion(g_nancy->getGameType());
readFilename(stream, _videoName);
- stream.skip(0x13);
+ if (ser.getVersion() == kGameTypeVampire) {
+ readFilename(stream, _paletteName);
+ }
+
+ ser.skip(2);
+ ser.syncAsUint16LE(_videoFormat);
+ ser.skip(0x13, kGameTypeVampire, kGameTypeVampire);
+ ser.skip(0xF, kGameTypeNancy1);
readRect(stream, _src);
readRect(stream, _screenPosition);
char *rawText = new char[1500];
- stream.read(rawText, 1500);
+ ser.syncBytes((byte *)rawText, 1500);
UI::Textbox::assembleTextLine(rawText, _text, 1500);
delete[] rawText;
_sound.read(stream, SoundDescription::kNormal);
_responseGenericSound.read(stream, SoundDescription::kNormal);
- stream.skip(1);
- _conditionalResponseCharacterID = stream.readByte();
- _goodbyeResponseCharacterID = stream.readByte();
- _isDialogueExitScene = (NancyFlag)stream.readByte();
- _doNotPop = (NancyFlag)stream.readByte();
+ ser.skip(1);
+ ser.syncAsByte(_conditionalResponseCharacterID);
+ ser.syncAsByte(_goodbyeResponseCharacterID);
+ ser.syncAsByte(_isDialogueExitScene);
+ ser.syncAsByte(_doNotPop);
_sceneChange.readData(stream);
- stream.seek(beginOffset + 0x69C);
+ ser.skip(0x35, kGameTypeVampire, kGameTypeVampire);
+ ser.skip(0x32, kGameTypeNancy1);
- uint16 numResponses = stream.readUint16LE();
+ uint16 numResponses = 0;
+ ser.syncAsUint16LE(numResponses);
rawText = new char[400];
_responses.reserve(numResponses);
for (uint i = 0; i < numResponses; ++i) {
_responses.push_back(ResponseStruct());
- ResponseStruct &response = _responses[i];
+ ResponseStruct &response = _responses.back();
response.conditionFlags.read(stream);
- stream.read(rawText, 400);
+ ser.syncBytes((byte*)rawText, 400);
UI::Textbox::assembleTextLine(rawText, response.text, 400);
readFilename(stream, response.soundName);
- stream.skip(1);
+ ser.skip(1);
response.sceneChange.readData(stream);
- response.flagDesc.label = stream.readSint16LE();
- response.flagDesc.flag = (NancyFlag)stream.readByte();
-
- stream.skip(0x32);
+ ser.skip(3, kGameTypeVampire, kGameTypeVampire);
+ ser.syncAsSint16LE(response.flagDesc.label);
+ ser.syncAsByte(response.flagDesc.flag);
+ ser.skip(0x32);
}
delete[] rawText;
diff --git a/engines/nancy/action/primaryvideo.h b/engines/nancy/action/primaryvideo.h
index 13d794ec3d..15e1b3d95d 100644
--- a/engines/nancy/action/primaryvideo.h
+++ b/engines/nancy/action/primaryvideo.h
@@ -85,22 +85,23 @@ public:
void addConditionalResponses();
void addGoodbye();
- Common::String _videoName; // 0x00
- Common::Rect _src; // 0x1D
- // _screenPosition 0x2D
- Common::String _text; // 0x3D
-
- SoundDescription _sound; // 0x619
- SoundDescription _responseGenericSound; // 0x63B
-
- byte _conditionalResponseCharacterID = 0; // 0x65E
- byte _goodbyeResponseCharacterID = 0; // 0x65F
- NancyFlag _isDialogueExitScene = NancyFlag::kFalse; // 0x660
- NancyFlag _doNotPop = NancyFlag::kFalse; // 0x661
- SceneChangeDescription _sceneChange; // 0x662
-
- Common::Array<ResponseStruct> _responses; // 0x69E
- Common::Array<FlagsStruct> _flagsStructs; // 0x6AA
+ Common::String _videoName;
+ Common::String _paletteName;
+ uint _videoFormat = 2;
+ Common::Rect _src;
+ Common::String _text;
+
+ SoundDescription _sound;
+ SoundDescription _responseGenericSound;
+
+ byte _conditionalResponseCharacterID = 0;
+ byte _goodbyeResponseCharacterID = 0;
+ NancyFlag _isDialogueExitScene = NancyFlag::kFalse;
+ NancyFlag _doNotPop = NancyFlag::kFalse;
+ SceneChangeDescription _sceneChange;
+
+ Common::Array<ResponseStruct> _responses;
+ Common::Array<FlagsStruct> _flagsStructs;
AVFDecoder _decoder;
Commit: 6abc61edf73c298880a1da8232a760268e22f6fd
https://github.com/scummvm/scummvm/commit/6abc61edf73c298880a1da8232a760268e22f6fd
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2021-04-29T15:59:00+03:00
Commit Message:
NANCY: Render text in The Vampire Diaries
Text in TVD is now rendered in the textbox, and should be
pixel-accurate to the original engine.
Changed paths:
engines/nancy/font.cpp
engines/nancy/font.h
engines/nancy/nancy.cpp
engines/nancy/nancy.h
engines/nancy/ui/textbox.cpp
diff --git a/engines/nancy/font.cpp b/engines/nancy/font.cpp
index 5585fe01f6..6a31074ddb 100644
--- a/engines/nancy/font.cpp
+++ b/engines/nancy/font.cpp
@@ -75,6 +75,11 @@ void Font::read(Common::SeekableReadStream &stream) {
Common::Rect &cur = _symbolRects[i];
readRect(stream, cur);
+ if (g_nancy->getGameType() == kGameTypeVampire) {
+ ++cur.bottom;
+ ++cur.right;
+ }
+
_maxCharWidth = MAX<int>(cur.width(), _maxCharWidth);
_fontHeight = MAX<int>(cur.height(), _maxCharWidth);
}
@@ -90,16 +95,29 @@ void Font::drawChar(Graphics::Surface *dst, uint32 chr, int x, int y, uint32 col
srcRect.translate(_colorCoordsOffset.x, _colorCoordsOffset.y);
}
- uint width = srcRect.width();
+ uint vampireAdjust = g_nancy->getGameType() == kGameTypeVampire ? 1 : 0;
+ uint width = MAX<int>(srcRect.width() - vampireAdjust, 0);
uint height = srcRect.height();
uint yOffset = getFontHeight() - height;
+ height = MAX<int>(height - vampireAdjust, 0);
for (uint curY = 0; curY < height; ++curY) {
for (uint curX = 0; curX < width; ++curX) {
switch (g_nancy->_graphicsManager->getInputPixelFormat().bytesPerPixel) {
- case 1:
- // TODO
+ case 1: {
+ byte colorID = *(const byte *)_image.getBasePtr(srcRect.left + curX, srcRect.top + curY);
+
+ if (colorID != _transColor) {
+ uint8 r, g, b;
+ uint curColor = _image.getPalette()[colorID];
+ r = curColor & 0xFF;
+ g = (curColor & 0xFF00) >> 8;
+ b = (curColor & 0xFF0000) >> 16;
+ *(uint16 *)dst->getBasePtr(x + curX, y + yOffset + curY) = dst->format.RGBToColor(r, g, b);
+ }
+
break;
+ }
case 2: {
uint16 curColor = *(const uint16 *)_image.getBasePtr(srcRect.left + curX, srcRect.top + curY);
@@ -121,6 +139,12 @@ void Font::drawChar(Graphics::Surface *dst, uint32 chr, int x, int y, uint32 col
void Font::wordWrap(const Common::String &str, int maxWidth, Common::Array<Common::String> &lines, int initWidth) const {
Common::String temp;
for (const char *c = str.begin(); c != str.end(); ++c) {
+ if (*c == '\n') {
+ lines.push_back(temp);
+ temp.clear();
+ continue;
+ }
+
temp += *c;
int size = getStringWidth(temp) + (lines.size() == 0 ? initWidth : 0);
if (size >= maxWidth) {
diff --git a/engines/nancy/font.h b/engines/nancy/font.h
index 2237d0d06e..2409e3af04 100644
--- a/engines/nancy/font.h
+++ b/engines/nancy/font.h
@@ -25,7 +25,7 @@
#include "common/array.h"
#include "graphics/font.h"
-#include "graphics/surface.h"
+#include "graphics/managed_surface.h"
namespace Common {
class SeekableReadStream;
@@ -82,7 +82,7 @@ private:
Common::Array<Common::Rect> _symbolRects; // 0x62
- Graphics::Surface _image;
+ Graphics::ManagedSurface _image;
int _fontHeight;
int _maxCharWidth;
diff --git a/engines/nancy/nancy.cpp b/engines/nancy/nancy.cpp
index 01ad267506..49d4d5825e 100644
--- a/engines/nancy/nancy.cpp
+++ b/engines/nancy/nancy.cpp
@@ -37,6 +37,7 @@
#include "engines/nancy/dialogs.h"
#include "engines/nancy/console.h"
#include "engines/nancy/constants.h"
+#include "engines/nancy/util.h"
#include "engines/nancy/action/primaryvideo.h"
@@ -467,8 +468,12 @@ void NancyEngine::readBootSummary(const IFF &boot) {
readChunkList(boot, ser, "OB");
}
- ser.skip(0x96, kGameTypeVampire, kGameTypeVampire);
- ser.skip(0x79, kGameTypeNancy1, kGameTypeNancy1);
+ ser.skip(0x28, kGameTypeVampire, kGameTypeVampire);
+ ser.skip(0x10, kGameTypeNancy1, kGameTypeNancy1);
+ readRect(*bsum, _textboxScreenPosition);
+
+ ser.skip(0x5E, kGameTypeVampire, kGameTypeVampire);
+ ser.skip(0x59, kGameTypeNancy1, kGameTypeNancy1);
ser.syncAsUint16LE(_horizontalEdgesSize, kGameTypeVampire, kGameTypeNancy1);
ser.syncAsUint16LE(_verticalEdgesSize, kGameTypeVampire, kGameTypeNancy1);
ser.skip(0x1C, kGameTypeVampire, kGameTypeNancy1);
diff --git a/engines/nancy/nancy.h b/engines/nancy/nancy.h
index c349334774..5b6ec38eca 100644
--- a/engines/nancy/nancy.h
+++ b/engines/nancy/nancy.h
@@ -122,6 +122,7 @@ public:
Common::RandomSource *_randomSource;
+ // BSUM data
uint16 _firstSceneID;
uint16 _startTimeHours;
@@ -133,6 +134,8 @@ public:
uint _horizontalEdgesSize;
uint _verticalEdgesSize;
+ Common::Rect _textboxScreenPosition;
+
private:
struct GameFlow {
NancyState::NancyState curState = NancyState::kNone;
diff --git a/engines/nancy/ui/textbox.cpp b/engines/nancy/ui/textbox.cpp
index b289e08a98..ce668ba299 100644
--- a/engines/nancy/ui/textbox.cpp
+++ b/engines/nancy/ui/textbox.cpp
@@ -81,9 +81,7 @@ void Textbox::init() {
chunk->seek(0x1FE, SEEK_SET);
_fontID = chunk->readUint16LE();
- chunk = g_nancy->getBootChunkStream("BSUM");
- chunk->seek(0x164);
- readRect(*chunk, _screenPosition);
+ _screenPosition = g_nancy->_textboxScreenPosition;
Common::Rect outerBoundingBox = _screenPosition;
outerBoundingBox.moveTo(0, 0);
@@ -142,11 +140,10 @@ void Textbox::drawTextbox() {
const Font *font = g_nancy->_graphicsManager->getFont(_fontID);
uint maxWidth = _fullSurface.w - _maxWidthDifference - _borderWidth - 2;
- uint lineDist = _lineHeight + _lineHeight / 4;
+ uint lineDist = _lineHeight + _lineHeight / 4 + (g_nancy->getGameType() == kGameTypeVampire ? 1 : 0);
for (uint lineID = 0; lineID < _textLines.size(); ++lineID) {
Common::String currentLine = _textLines[lineID];
- currentLine.trim();
uint horizontalOffset = 0;
bool hasHotspot = false;
@@ -168,12 +165,21 @@ void Textbox::drawTextbox() {
currentLine = currentLine.substr(0, currentLine.size() - ARRAYSIZE(_telephoneEndToken) + 1);
}
- // Remove hotspot token and mark that we need to calculate the bounds
- // Assumes a single text line has a single hotspot
- uint32 hotspotPos = currentLine.find(_hotspotToken);
- if (hotspotPos != String::npos) {
+ // Remove hotspot tokens and mark that we need to calculate the bounds
+ // A single text line should only have one hotspot, but there's at least
+ // one malformed line in TVD that breaks this
+ uint32 hotspotPos, lastHotspotPos;
+ while (hotspotPos = currentLine.find(_hotspotToken), hotspotPos != String::npos) {
currentLine.erase(hotspotPos, ARRAYSIZE(_hotspotToken) - 1);
+
+ if (hasHotspot) {
+ // Replace the second hotspot token with a newline to copy the original behavior
+ // Maybe consider fixing the glitch instead of replicating it??
+ currentLine.insertChar('\n', lastHotspotPos);
+ }
+
hasHotspot = true;
+ lastHotspotPos = hotspotPos;
}
// Subdivide current line into sublines for proper handling of the tab and color tokens
@@ -280,6 +286,14 @@ void Textbox::assembleTextLine(char *rawCaption, Common::String &output, uint si
i += newBit.size();
}
}
+
+ // Fix spaces at the end of the string in nancy1
+ output.trim();
+
+ // Fix at least one broken string in TVD
+ if (output.hasSuffix(">>")) {
+ output.deleteLastChar();
+ }
}
void Textbox::onScrollbarMove() {
Commit: 3dd19a47e1ab4559fa8a494473c8c624cf4bfaa6
https://github.com/scummvm/scummvm/commit/3dd19a47e1ab4559fa8a494473c8c624cf4bfaa6
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2021-04-29T15:59:00+03:00
Commit Message:
NANCY: Set correct cursor when hovering a UI element
Set the correct ID for the cursor that displays when hovering a
clickable UI element.
Changed paths:
engines/nancy/cursor.cpp
diff --git a/engines/nancy/cursor.cpp b/engines/nancy/cursor.cpp
index a751690a07..0397ae4f84 100644
--- a/engines/nancy/cursor.cpp
+++ b/engines/nancy/cursor.cpp
@@ -81,7 +81,7 @@ void CursorManager::setCursor(CursorType type, int16 itemID) {
_curCursorID = 4;
break;
case kHotspotArrow:
- _curCursorID = 6;
+ _curCursorID = 5;
break;
default: {
uint itemsOffset = 0;
More information about the Scummvm-git-logs
mailing list