[Scummvm-git-logs] scummvm master -> 29bc5487cd9ca061072a491669a7170bf298633f
mduggan
noreply at scummvm.org
Mon Dec 30 09:51:22 UTC 2024
This automated email contains information about 6 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
3464207be1 DGDS: Fix rendering of Willy Beamish sub-menu header
2f0c00cabf DGDS: Fix dragging items into/out-of inventory in Beamish
14e119bb78 DGDS: Misc fixes for Willy Beamish
f79c7bec8d DGDS: Print debug after loading DDS data
854c2c4665 DGDS: Fix inventory wrapping for Willy Beamish
29bc5487cd DGDS: Implement willy trouble gauge
Commit: 3464207be18eefacf197830abaebc286c486182c
https://github.com/scummvm/scummvm/commit/3464207be18eefacf197830abaebc286c486182c
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2024-12-30T20:04:15+11:00
Commit Message:
DGDS: Fix rendering of Willy Beamish sub-menu header
Changed paths:
engines/dgds/request.cpp
diff --git a/engines/dgds/request.cpp b/engines/dgds/request.cpp
index a8a769e12e0..140d818b33b 100644
--- a/engines/dgds/request.cpp
+++ b/engines/dgds/request.cpp
@@ -69,6 +69,7 @@ static const byte ChinaSliderColors[] = {
static const byte WillyBackgroundColor = 16;
static const byte WillyButtonColor = 20;
+static const byte WillyHeaderTxtColor = 0;
static const byte MenuBackgroundColors[] {
0x71, 0x71, 0x71, 0x71, 0x71, 0x7B, 0x71, 0x7B, 0x7B, 0x7B, 0x7B, 0x7B,
@@ -1050,8 +1051,11 @@ void RequestData::drawBackgroundNoSliders(Graphics::ManagedSurface *dst, const C
drawCorners(dst, cornerOffset, _rect.x, _rect.y, _rect.width, _rect.height);
if (gameId == GID_DRAGON)
drawHeader(dst, _rect.x, _rect.y, _rect.width, 4, header, DragonHeaderTxtColor, true, DragonHeaderTopColor, DragonHeaderBottomColor);
- else
+ else if (gameId == GID_HOC)
drawHeader(dst, _rect.x, _rect.y + 4, _rect.width, 4, header, ChinaHeaderTxtColor, true, ChinaHeaderTopColor, ChinaHeaderBottomColor);
+ else { // WILLY
+ drawHeader(dst, _rect.x, _rect.y + 4, _rect.width, 4, header, WillyHeaderTxtColor, false, 0, 0);
+ }
}
/*static*/
Commit: 2f0c00cabf1280d2d669d633a9225dcf96b754d7
https://github.com/scummvm/scummvm/commit/2f0c00cabf1280d2d669d633a9225dcf96b754d7
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2024-12-30T20:04:15+11:00
Commit Message:
DGDS: Fix dragging items into/out-of inventory in Beamish
Changed paths:
engines/dgds/inventory.cpp
engines/dgds/inventory.h
diff --git a/engines/dgds/inventory.cpp b/engines/dgds/inventory.cpp
index defabceea98..1a2a3aae81a 100644
--- a/engines/dgds/inventory.cpp
+++ b/engines/dgds/inventory.cpp
@@ -49,10 +49,12 @@ void Inventory::open() {
_isOpen = true;
DgdsEngine *engine = DgdsEngine::getInstance();
- if (engine->getGameId() == GID_WILLY)
+ int curScene = engine->getScene()->getNum();
+ if (engine->getGameId() == GID_WILLY) {
+ _openedFromSceneNum = curScene;
return;
+ }
- int curScene = engine->getScene()->getNum();
if (curScene != 2) {
_openedFromSceneNum = curScene;
engine->changeScene(2);
@@ -362,7 +364,7 @@ GameItem *Inventory::itemUnderMouse(const Common::Point &pt) {
return nullptr;
}
-bool Inventory::isItemInInventory(GameItem &item) {
+bool Inventory::isItemInInventory(const GameItem &item) {
DgdsEngine *engine = DgdsEngine::getInstance();
DgdsGameId gameId = engine->getGameId();
bool result = item._inSceneNum == 2; // && (item._flags & 4)
@@ -403,6 +405,8 @@ void Inventory::mouseLUp(const Common::Point &pt) {
GameItem *dragItem = engine->getScene()->getDragItem();
if (dragItem) {
+ if (engine->getGameId() == GID_WILLY)
+ dragItem->_inSceneNum = 2;
engine->getScene()->onDragFinish(pt);
return;
}
@@ -416,7 +420,7 @@ void Inventory::mouseLUp(const Common::Point &pt) {
close();
} else if (_nextPageBtn->containsPoint(pt) && _nextPageBtn->isVisible()) {
int numInvItems = 0;
- Common::Array<GameItem> &items = engine->getGDSScene()->getGameItems();
+ const Common::Array<GameItem> &items = engine->getGDSScene()->getGameItems();
for (auto &item: items) {
if (isItemInInventory(item))
numInvItems++;
diff --git a/engines/dgds/inventory.h b/engines/dgds/inventory.h
index 5a8c0ee3aba..d871b476033 100644
--- a/engines/dgds/inventory.h
+++ b/engines/dgds/inventory.h
@@ -60,7 +60,7 @@ public:
static const byte HOC_CHARACTER_QUALS[];
private:
GameItem *itemUnderMouse(const Common::Point &pt);
- bool isItemInInventory(GameItem &item);
+ bool isItemInInventory(const GameItem &item);
uint16 _openedFromSceneNum;
Commit: 14e119bb78d5c39737e3b6d90787b6de2bd78e0b
https://github.com/scummvm/scummvm/commit/14e119bb78d5c39737e3b6d90787b6de2bd78e0b
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2024-12-30T20:04:15+11:00
Commit Message:
DGDS: Misc fixes for Willy Beamish
* Play sample should be one-shot (don't replay every frame)
* TTM op 0020 should save to background differently (fixes double-drawing)
* Disabled areas still change mouse cursor and hold clicks until enabled,
properly fixes eg exiting detention at the start
* Fix the way "used" sequences are calculated so Willy can enter his house,
removing the previous hack
* Refactor scene condition check to separate file
* Small const correctness improvements
Changed paths:
engines/dgds/ads.cpp
engines/dgds/clock.cpp
engines/dgds/clock.h
engines/dgds/hoc_intro.cpp
engines/dgds/inventory.cpp
engines/dgds/minigames/dragon_arcade_ttm.cpp
engines/dgds/minigames/dragon_arcade_ttm.h
engines/dgds/scene.cpp
engines/dgds/scene.h
engines/dgds/scene_condition.cpp
engines/dgds/scene_condition.h
engines/dgds/scene_op.cpp
engines/dgds/ttm.cpp
diff --git a/engines/dgds/ads.cpp b/engines/dgds/ads.cpp
index 1c43841464e..a13d36a47e8 100644
--- a/engines/dgds/ads.cpp
+++ b/engines/dgds/ads.cpp
@@ -132,11 +132,6 @@ bool ADSInterpreter::load(const Common::String &filename) {
return true;
}
-static const uint16 ADS_SEQ_OPCODES[] = {
- 0x2000, 0x2005, 0x2010, 0x2015, 0x4000, 0x4010, 0x1330,
- 0x1340, 0x1360, 0x1370, 0x1320, 0x1310, 0x1350
-};
-
bool ADSInterpreter::updateSeqTimeAndFrame(const TTMEnviro *env, Common::SharedPtr<TTMSeq> seq) {
if (seq->_timeInterval != 0) {
uint32 now = DgdsEngine::getInstance()->getThisFrameMs();
@@ -163,16 +158,31 @@ bool ADSInterpreter::updateSeqTimeAndFrame(const TTMEnviro *env, Common::SharedP
return true;
}
+static const uint16 ADS_USED_SEQ_OPCODES[] = {
+ 0x2000, 0x2005, 0x2010, 0x2015, 0x4000, 0x4010, 0x1330,
+ 0x1340, 0x1360, 0x1370, 0x1320, 0x1310, 0x1350
+};
+
void ADSInterpreter::findUsedSequencesForSegment(int idx) {
_adsData->_usedSeqs[idx].clear();
int64 startoff = _adsData->scr->pos();
uint16 opcode = 0;
// Skip the segment number.
int16 segno = _adsData->scr->readUint16LE();
+
+ DgdsGameId gameId = DgdsEngine::getInstance()->getGameId();
+ //
+ // HoC and Dragon call a sequence "used" if there is any dependency on
+ // the sequence (reordering, if conditions), but to simplify the use of
+ // getStateForSceneOp, later games only call it "used" if it is directly
+ // started.
+ //
+ int n_ops_to_check = (gameId == GID_DRAGON || gameId == GID_HOC) ? ARRAYSIZE(ADS_USED_SEQ_OPCODES) : 2;
while (opcode != 0xffff && _adsData->scr->pos() < _adsData->scr->size()) {
opcode = _adsData->scr->readUint16LE();
- for (uint16 o : ADS_SEQ_OPCODES) {
- if (opcode == o) {
+ for (int i = 0; i < n_ops_to_check; i++) {
+ uint16 op = ADS_USED_SEQ_OPCODES[i];
+ if (opcode == op) {
int16 envno = _adsData->scr->readSint16LE();
int16 seqno = _adsData->scr->readSint16LE();
Common::SharedPtr<TTMSeq> seq = findTTMSeq(envno, seqno);
@@ -807,7 +817,7 @@ int16 ADSInterpreter::getStateForSceneOp(uint16 segnum) {
}
return 0;
}
- } else if (DgdsEngine::getInstance()->getGameId() == GID_HOC) {
+ } else {
int state = (_adsData->_state[idx] & 0xfff7);
if (state != 4 && state != 1) {
for (const Common::SharedPtr<TTMSeq> &seq: _adsData->_usedSeqs[idx]) {
@@ -818,24 +828,6 @@ int16 ADSInterpreter::getStateForSceneOp(uint16 segnum) {
}
return 0;
}
- } else { // WILLY+
- int state = (_adsData->_state[idx] & 0xfff7);
- if (state != 4 && state != 1) {
- for (const Common::SharedPtr<TTMSeq> &seq: _adsData->_usedSeqs[idx]) {
- if (!seq)
- error("getStateForSceneOp: used seq for seg %d should not be null", segnum);
- //
- // TODO: This last check is a bit of a guess to make Willy Beamish work correctly.
- // It seems to need sequences to return false from this function even when they
- // are delayed. Eg, outside the house (HE.ADS, scene 10), seq 20 (willy scratching
- // his leg) runs and repeats randomly every 400 to 900 frames, but the door hot area
- // is not active if that script is "running".
- //
- if (seq->_runFlag != kRunTypeStopped && seq->_runFlag != kRunTypeFinished && !seq->_selfLoop && seq->_timeNext <= DgdsEngine::getInstance()->getThisFrameMs())
- return 1;
- }
- return 0;
- }
}
return 1;
@@ -1007,7 +999,6 @@ void ADSInterpreter::setGotoTarget(int32 target) {
}
int ADSInterpreter::numArgs(uint16 opcode) const {
- // TODO: This list is from DRAGON, there may be more entries in newer games.
switch (opcode) {
case 0x1080:
case 0x1090:
diff --git a/engines/dgds/clock.cpp b/engines/dgds/clock.cpp
index e6f248fd86f..e9a4b8821ad 100644
--- a/engines/dgds/clock.cpp
+++ b/engines/dgds/clock.cpp
@@ -173,7 +173,7 @@ void Clock::update(bool gameRunning) {
addGameTime(mins_to_add);
}
-Common::String Clock::dump() {
+Common::String Clock::dump() const {
return Common::String::format("days %d hours %d mins %d", _days, _mins, _hours);
}
diff --git a/engines/dgds/clock.h b/engines/dgds/clock.h
index 1fcb1e8d600..66c9c699491 100644
--- a/engines/dgds/clock.h
+++ b/engines/dgds/clock.h
@@ -64,7 +64,7 @@ public:
Common::Error syncState(Common::Serializer &s);
- Common::String dump();
+ Common::String dump() const;
private:
uint32 _lastPlayTime;
diff --git a/engines/dgds/hoc_intro.cpp b/engines/dgds/hoc_intro.cpp
index 8bba17c2942..53118d196b6 100644
--- a/engines/dgds/hoc_intro.cpp
+++ b/engines/dgds/hoc_intro.cpp
@@ -134,7 +134,7 @@ void HocIntro::end() {
_noMaskImg.reset();
globals->setIntroState(0);
- static_cast<HocGlobals *>(engine->getGameGlobals())->setNativeGameState(0);
+ globals->setNativeGameState(0);
}
void HocIntro::doCopy(int16 x1, int16 y1, int16 x2, int16 y2) {
diff --git a/engines/dgds/inventory.cpp b/engines/dgds/inventory.cpp
index 1a2a3aae81a..d21ad3078dc 100644
--- a/engines/dgds/inventory.cpp
+++ b/engines/dgds/inventory.cpp
@@ -277,7 +277,7 @@ void Inventory::drawItems(Graphics::ManagedSurface &surf) {
const Common::Rect drawMask(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
int offset = _itemOffset;
Common::Array<GameItem> &items = engine->getGDSScene()->getGameItems();
- for (auto & item: items) {
+ for (auto &item: items) {
if (!isItemInInventory(item))
continue;
diff --git a/engines/dgds/minigames/dragon_arcade_ttm.cpp b/engines/dgds/minigames/dragon_arcade_ttm.cpp
index e4b7aea861b..f2a2e640dab 100644
--- a/engines/dgds/minigames/dragon_arcade_ttm.cpp
+++ b/engines/dgds/minigames/dragon_arcade_ttm.cpp
@@ -28,7 +28,7 @@
namespace Dgds {
-Common::String ArcadeFloor::dump() {
+Common::String ArcadeFloor::dump() const {
return Common::String::format("ArcadeFloor<x:%d-%d y:%d flg:%d>",
x, x + width, yval, flag);
}
diff --git a/engines/dgds/minigames/dragon_arcade_ttm.h b/engines/dgds/minigames/dragon_arcade_ttm.h
index eb3e4d7ed38..5c36080d644 100644
--- a/engines/dgds/minigames/dragon_arcade_ttm.h
+++ b/engines/dgds/minigames/dragon_arcade_ttm.h
@@ -41,7 +41,7 @@ public:
byte yval;
bool flag;
- Common::String dump();
+ Common::String dump() const;
};
diff --git a/engines/dgds/scene.cpp b/engines/dgds/scene.cpp
index c64b42f95f9..5002aff6d28 100644
--- a/engines/dgds/scene.cpp
+++ b/engines/dgds/scene.cpp
@@ -481,7 +481,7 @@ bool Scene::runOps(const Common::Array<SceneOp> ops, int16 addMinuites /* = 0 */
bool sceneChanged = false;
int16 startSceneNum = engine->getScene()->getNum();
for (const SceneOp &op : ops) {
- if (!checkConditions(op._conditionList))
+ if (!SceneConditions::check(op._conditionList))
continue;
debug(10, "Exec %s", op.dump("").c_str());
if (addMinuites) {
@@ -505,74 +505,12 @@ bool Scene::runOps(const Common::Array<SceneOp> ops, int16 addMinuites /* = 0 */
return startSceneNum == endSceneNum;
}
-/*static*/
-bool Scene::checkConditions(const Common::Array<SceneConditions> &conds) {
- DgdsEngine *engine = DgdsEngine::getInstance();
-
- uint cnum = 0;
- while (cnum < conds.size()) {
- const SceneConditions &c = conds[cnum];
- int16 refval = c.getVal();
- int16 checkval = -1;
- SceneCondition cflag = c.getCond();
- // Hit an "or" here means the last result was true.
- if (cflag & kSceneCondOr)
- return true;
-
- if (cflag & kSceneCondSceneState) {
- refval = 1;
- checkval = engine->adsInterpreter()->getStateForSceneOp(c.getNum());
- SceneCondition equalOrNegate = static_cast<SceneCondition>(cflag & (kSceneCondEqual | kSceneCondNegate));
- if (equalOrNegate != kSceneCondEqual && equalOrNegate != kSceneCondNegate)
- refval = 0;
- cflag = kSceneCondEqual;
- } else if (cflag & kSceneCondNeedItemQuality || cflag & kSceneCondNeedItemSceneNum) {
- const Common::Array<GameItem> &items = engine->getGDSScene()->getGameItems();
- for (const auto &item : items) {
- if (item._num == c.getNum()) {
- if (cflag & kSceneCondNeedItemSceneNum)
- checkval = item._inSceneNum;
- else // cflag & kSceneCondNeedItemQuality
- checkval = item._quality;
- break;
- }
- }
- } else {
- checkval = engine->getGDSScene()->getGlobal(c.getNum());
- if (!(cflag & kSceneCondAbsVal))
- refval = engine->getGDSScene()->getGlobal((uint16)refval);
- }
-
- bool result = false;
- cflag = static_cast<SceneCondition>(cflag & ~(kSceneCondSceneState | kSceneCondNeedItemSceneNum | kSceneCondNeedItemQuality));
- if (cflag == kSceneCondNone)
- cflag = static_cast<SceneCondition>(kSceneCondEqual | kSceneCondNegate);
- if ((cflag & kSceneCondLessThan) && checkval < refval)
- result = true;
- if ((cflag & kSceneCondEqual) && checkval == refval)
- result = true;
- if (cflag & kSceneCondNegate)
- result = !result;
-
- debug(11, "Cond: %s -> %s", c.dump("").c_str(), result ? "true": "false");
-
- if (!result) {
- // Skip just past the next or, or to the end.
- while (cnum < conds.size() && !(conds[cnum].getCond() & kSceneCondOr))
- cnum++;
- if (cnum >= conds.size())
- return false;
- }
- cnum++;
- }
- return true;
-}
-
bool SDSScene::_dlgWithFlagLo8IsClosing = false;
DialogFlags SDSScene::_sceneDialogFlags = kDlgFlagNone;
-SDSScene::SDSScene() : _num(-1), _dragItem(nullptr), _shouldClearDlg(false), _ignoreMouseUp(false), _field6_0x14(0), _rbuttonDown(false), _lbuttonDown(false) {
+SDSScene::SDSScene() : _num(-1), _dragItem(nullptr), _shouldClearDlg(false), _ignoreMouseUp(false),
+ _field6_0x14(0), _rbuttonDown(false), _lbuttonDown(false) {
}
bool SDSScene::load(const Common::String &filename, ResourceManager *resourceManager, Decompressor *decompressor) {
@@ -715,7 +653,7 @@ void SDSScene::checkTriggers() {
continue;
}
- if (!checkConditions(trigger.conditionList))
+ if (!SceneConditions::check(trigger.conditionList))
continue;
trigger._enabled = false;
@@ -1232,7 +1170,12 @@ void SDSScene::mouseMoved(const Common::Point &pt) {
const HotArea *area = findAreaUnderMouse(pt);
DgdsEngine *engine = DgdsEngine::getInstance();
- int16 cursorNum = (!dlg && area) ? area->_cursorNum : 0;
+ int16 cursorNum = 0;
+ if (!dlg) {
+ if (area)
+ cursorNum = area->_cursorNum;
+ }
+
if (_dragItem) {
if (area && area->_objInteractionRectNum == 1) {
// drag over Willy Beamish
@@ -1283,7 +1226,7 @@ static bool _isInRect(const Common::Point &pt, const DgdsRect rect) {
&& rect.y <= pt.y && (rect.y + rect.height) > pt.y;
}
-static const ObjectInteraction * _findInteraction(const Common::Array<ObjectInteraction> &interList, int16 droppedNum, uint16 targetNum) {
+static const ObjectInteraction *_findInteraction(const Common::Array<ObjectInteraction> &interList, int16 droppedNum, uint16 targetNum) {
for (const auto &i : interList) {
if (i.matches(droppedNum, targetNum)) {
return &i;
@@ -1294,6 +1237,7 @@ static const ObjectInteraction * _findInteraction(const Common::Array<ObjectInte
void SDSScene::mouseLUp(const Common::Point &pt) {
_lbuttonDown = false;
+
if (_ignoreMouseUp) {
debug(9, "Ignoring mouseup at %d,%d as it was used to clear a dialog", pt.x, pt.y);
_ignoreMouseUp = false;
@@ -1394,7 +1338,7 @@ void SDSScene::onDragFinish(const Common::Point &pt) {
}
}
- SDSScene *scene = engine->getScene();
+ const SDSScene *scene = engine->getScene();
for (const auto &area : _hotAreaList) {
if (!_isInRect(pt, area._rect))
continue;
@@ -1532,13 +1476,13 @@ void SDSScene::updateHotAreasFromDynamicRects() {
HotArea *SDSScene::findAreaUnderMouse(const Common::Point &pt) {
for (auto &item : DgdsEngine::getInstance()->getGDSScene()->getGameItems()) {
if (item._inSceneNum == _num && _isInRect(pt, item._rect)
- && checkConditions(item.enableConditions)) {
+ && SceneConditions::check(item.enableConditions)) {
return &item;
}
}
for (auto &area : _hotAreaList) {
- if (_isInRect(pt, area._rect) && checkConditions(area.enableConditions)) {
+ if (_isInRect(pt, area._rect) && SceneConditions::check(area.enableConditions)) {
return &area;
}
}
@@ -1661,7 +1605,7 @@ void SDSScene::drawDebugHotAreas(Graphics::ManagedSurface *dst) const {
byte greenish = pal.findBestColor(0, 0xff, 0);
for (const auto &area : _hotAreaList) {
- bool enabled = checkConditions(area.enableConditions);
+ bool enabled = SceneConditions::check(area.enableConditions);
uint32 color = enabled ? greenish : redish;
g_system->getPaletteManager();
const Common::Rect &r = area._rect.toCommonRect();
diff --git a/engines/dgds/scene.h b/engines/dgds/scene.h
index 0d34d27c435..37e1317ff57 100644
--- a/engines/dgds/scene.h
+++ b/engines/dgds/scene.h
@@ -180,8 +180,6 @@ public:
virtual Common::Error syncState(Common::Serializer &s) = 0;
// These are all static as they are potentially run over scene changes.
- static bool checkConditions(const Common::Array<SceneConditions> &cond);
-
static void segmentStateOps(const Common::Array<uint16> &args);
static void setItemAttrOp(const Common::Array<uint16> &args);
static void setDragItemOp(const Common::Array<uint16> &args);
@@ -233,8 +231,8 @@ public:
Common::Array<GameItem> &getGameItems() { return _gameItems; }
int countItemsInInventory() const;
- const Common::Array<ObjectInteraction> &getObjInteractions1() { return _objInteractions1; }
- const Common::Array<ObjectInteraction> &getObjInteractions2() { return _objInteractions2; }
+ const Common::Array<ObjectInteraction> &getObjInteractions1() const { return _objInteractions1; }
+ const Common::Array<ObjectInteraction> &getObjInteractions2() const { return _objInteractions2; }
Common::Error syncState(Common::Serializer &s) override;
void initIconSizes();
@@ -301,8 +299,8 @@ public:
GameItem *getDragItem() { return _dragItem; }
void setDragItem(GameItem *item) { _dragItem = item; }
- const Common::Array<ObjectInteraction> &getObjInteractions1() { return _objInteractions1; }
- const Common::Array<ObjectInteraction> &getObjInteractions2() { return _objInteractions2; }
+ const Common::Array<ObjectInteraction> &getObjInteractions1() const { return _objInteractions1; }
+ const Common::Array<ObjectInteraction> &getObjInteractions2() const { return _objInteractions2; }
bool hasVisibleDialog();
bool hasVisibleOrOpeningDialog() const;
diff --git a/engines/dgds/scene_condition.cpp b/engines/dgds/scene_condition.cpp
index 2129e5c61c5..1ae99aede23 100644
--- a/engines/dgds/scene_condition.cpp
+++ b/engines/dgds/scene_condition.cpp
@@ -20,6 +20,9 @@
*/
#include "dgds/scene_condition.h"
+#include "dgds/dgds.h"
+#include "dgds/ads.h"
+#include "dgds/scene.h"
namespace Dgds {
@@ -54,6 +57,70 @@ Common::String _sceneConditionStr(SceneCondition cflag) {
return ret;
}
+/*static*/
+bool SceneConditions::check(const Common::Array<SceneConditions> &conds) {
+ DgdsEngine *engine = DgdsEngine::getInstance();
+
+ uint cnum = 0;
+ while (cnum < conds.size()) {
+ const SceneConditions &c = conds[cnum];
+ int16 refval = c.getVal();
+ int16 checkval = -1;
+ SceneCondition cflag = c.getCond();
+ // Hit an "or" here means the last result was true.
+ if (cflag & kSceneCondOr)
+ return true;
+
+ if (cflag & kSceneCondSceneState) {
+ refval = 1;
+ checkval = engine->adsInterpreter()->getStateForSceneOp(c.getNum());
+ SceneCondition equalOrNegate = static_cast<SceneCondition>(cflag & (kSceneCondEqual | kSceneCondNegate));
+ if (equalOrNegate != kSceneCondEqual && equalOrNegate != kSceneCondNegate)
+ refval = 0;
+ cflag = kSceneCondEqual;
+ } else if (cflag & kSceneCondNeedItemQuality || cflag & kSceneCondNeedItemSceneNum) {
+ const Common::Array<GameItem> &items = engine->getGDSScene()->getGameItems();
+ for (const auto &item : items) {
+ if (item._num == c.getNum()) {
+ if (cflag & kSceneCondNeedItemSceneNum)
+ checkval = item._inSceneNum;
+ else // cflag & kSceneCondNeedItemQuality
+ checkval = item._quality;
+ break;
+ }
+ }
+ } else {
+ checkval = engine->getGDSScene()->getGlobal(c.getNum());
+ if (!(cflag & kSceneCondAbsVal))
+ refval = engine->getGDSScene()->getGlobal((uint16)refval);
+ }
+
+ bool result = false;
+ cflag = static_cast<SceneCondition>(cflag & ~(kSceneCondSceneState | kSceneCondNeedItemSceneNum | kSceneCondNeedItemQuality));
+ if (cflag == kSceneCondNone)
+ cflag = static_cast<SceneCondition>(kSceneCondEqual | kSceneCondNegate);
+ if ((cflag & kSceneCondLessThan) && checkval < refval)
+ result = true;
+ if ((cflag & kSceneCondEqual) && checkval == refval)
+ result = true;
+ if (cflag & kSceneCondNegate)
+ result = !result;
+
+ debug(11, "Cond: %s -> %s", c.dump("").c_str(), result ? "true": "false");
+
+ if (!result) {
+ // Skip just past the next or, or to the end.
+ while (cnum < conds.size() && !(conds[cnum].getCond() & kSceneCondOr))
+ cnum++;
+ if (cnum >= conds.size())
+ return false;
+ }
+ cnum++;
+ }
+ return true;
+}
+
+
Common::String SceneConditions::dump(const Common::String &indent) const {
return Common::String::format("%sSceneCondition<flg 0x%02x(%s) num %d val %d>", indent.c_str(),
_flags, _sceneConditionStr(_flags).c_str(), _num, _val);
diff --git a/engines/dgds/scene_condition.h b/engines/dgds/scene_condition.h
index 5324644efe5..303d69a0530 100644
--- a/engines/dgds/scene_condition.h
+++ b/engines/dgds/scene_condition.h
@@ -24,6 +24,7 @@
#include "common/types.h"
#include "common/str.h"
+#include "common/array.h"
namespace Dgds {
@@ -44,6 +45,8 @@ public:
SceneConditions(uint16 num, SceneCondition cond, int16 val) : _num(num), _flags(cond), _val(val) {}
Common::String dump(const Common::String &indent) const;
+ static bool check(const Common::Array<SceneConditions> &conds);
+
uint16 getNum() const { return _num; }
SceneCondition getCond() const { return _flags; }
int16 getVal() const { return _val; }
diff --git a/engines/dgds/scene_op.cpp b/engines/dgds/scene_op.cpp
index 684a31428f0..615102f194c 100644
--- a/engines/dgds/scene_op.cpp
+++ b/engines/dgds/scene_op.cpp
@@ -381,7 +381,7 @@ bool SceneOp::runBeamishOp() const {
if (_opCode & kSceneOpHasConditionalOpsFlag) {
uint16 opcode = _opCode & ~kSceneOpHasConditionalOpsFlag;
for (const ConditionalSceneOp &cop : engine->getScene()->getConditionalOps()) {
- if (cop._opCode == opcode && engine->getScene()->checkConditions(cop._conditionList)) {
+ if (cop._opCode == opcode && SceneConditions::check(cop._conditionList)) {
if (!Scene::runOps(cop._opList))
return true;
}
diff --git a/engines/dgds/ttm.cpp b/engines/dgds/ttm.cpp
index 5e4d76fb1de..6742e474b61 100644
--- a/engines/dgds/ttm.cpp
+++ b/engines/dgds/ttm.cpp
@@ -583,16 +583,21 @@ bool TTMInterpreter::handleOperation(TTMEnviro &env, TTMSeq &seq, uint16 op, byt
break;
//
// This appears in the credits, intro sequence, and the
- // "meanwhile" event with the factory in DRAGON. It
- // should reload the background image to clear any previous 0020
- // event, and then save the current FG over it.
+ // "meanwhile" event with the factory in DRAGON. It should
+ // copy the front buffer to the stored buffer, then the stored
+ // buffer to the background?
+ //
// Credits - (no scr loaded) Store large image on black bg after loading and before txt scroll
// Intro - (no scr loaded) After each screen change, draw and save the new comic frame as bg
// on "aaaaah" scene, called after only drawing the AAAH and calling store area
// Meanwhile - (scr loaded) Save the foreground people onto the background before walk animation
//
- _vm->getStoredAreaBuffer().fillRect(Common::Rect(SCREEN_WIDTH, SCREEN_HEIGHT), 0);
- _vm->getBackgroundBuffer().blitFrom(_vm->_compositionBuffer);
+ if (DgdsEngine::getInstance()->getGameId() == GID_WILLY) {
+ _vm->getStoredAreaBuffer().blitFrom(_vm->_compositionBuffer);
+ } else {
+ _vm->getStoredAreaBuffer().fillRect(Common::Rect(SCREEN_WIDTH, SCREEN_HEIGHT), 0);
+ _vm->getBackgroundBuffer().blitFrom(_vm->_compositionBuffer);
+ }
break;
case 0x0070: // FREE PALETTE
if (seq._executed) // this is a one-shot op
@@ -951,10 +956,10 @@ bool TTMInterpreter::handleOperation(TTMEnviro &env, TTMSeq &seq, uint16 op, byt
Drawing::emptyCircle(ivals[0] + xr, ivals[1] + yr, xr, yr, &_vm->_compositionBuffer, seq._drawColFG);
break;
}
- case 0xa500: // DRAW SPRITE: x,y,tile-id,bmp-id:int [-n,+n]
+ case 0xa500: // DRAW SPRITE: x,y,frameno,bmpno:int [-n,+n]
case 0xa510: // DRAW SPRITE FLIP V x,y:int
case 0xa520: // DRAW SPRITE FLIP H: x,y:int
- case 0xa530: { // DRAW SPRITE FLIP HV: x,y,tile-id,bmp-id:int [-n,+n] (CHINA)
+ case 0xa530: { // DRAW SPRITE FLIP HV: x,y,frameno,bmpno:int [-n,+n] (CHINA+)
int frameno;
int bmpNo;
int dstWidth = 0;
@@ -1009,7 +1014,7 @@ bool TTMInterpreter::handleOperation(TTMEnviro &env, TTMSeq &seq, uint16 op, byt
Common::Point(r.left, r.top));
break;
}
- case 0xa700: { // DRAW SCROLL x,y,w,h??
+ case 0xa700: { // DRAW SCROLL x,y,w,h
if (!env._scrollShape) {
warning("Trying to draw scroll with no scrollshape loaded");
} else {
@@ -1024,7 +1029,7 @@ bool TTMInterpreter::handleOperation(TTMEnviro &env, TTMSeq &seq, uint16 op, byt
f.fill();
break;
}
- case 0xaf10: { // DRAW EMPTY POLY
+ case 0xaf10: { // DRAW EMPTY POLY [pts]
ClipSurface clipSurf(seq._drawWin, _vm->_compositionBuffer.surfacePtr());
for (uint i = 1; i < pts.size(); i++) {
const Common::Point &p1 = pts[i - 1];
@@ -1036,7 +1041,7 @@ bool TTMInterpreter::handleOperation(TTMEnviro &env, TTMSeq &seq, uint16 op, byt
plotClippedPoint, &clipSurf);
break;
}
- case 0xaf20: { // DRAW FILLED POLY
+ case 0xaf20: { // DRAW FILLED POLY [pts]
ClipSurface clipSurf(seq._drawWin, _vm->_compositionBuffer.surfacePtr());
Common::Array<int> xvals(pts.size());
Common::Array<int> yvals(pts.size());
@@ -1054,7 +1059,7 @@ bool TTMInterpreter::handleOperation(TTMEnviro &env, TTMSeq &seq, uint16 op, byt
env._creditScrollMeasure = doOpInitCreditScroll(env._scriptShapes[seq._currentBmpId].get());
env._creditScrollYOffset = 0;
break;
- case 0xb010: { // DRAW CREDITS SCROLL
+ case 0xb010: { // DRAW CREDITS SCROLL ygap,ystep
const Image *img = env._scriptShapes[seq._currentBmpId].get();
if (img && img->isLoaded()) {
bool finished = doOpCreditsScroll(env._scriptShapes[seq._currentBmpId].get(), ivals[0], env._creditScrollYOffset,
@@ -1093,6 +1098,8 @@ bool TTMInterpreter::handleOperation(TTMEnviro &env, TTMSeq &seq, uint16 op, byt
break;
}
case 0xc050: { // PLAY SAMPLE: int: i
+ if (seq._executed) // this is a one-shot op
+ break;
_vm->_soundPlayer->playMusicOrSFX(ivals[0]);
break;
}
Commit: f79c7bec8d7434360a6841bdb5983aa548e7cdfd
https://github.com/scummvm/scummvm/commit/f79c7bec8d7434360a6841bdb5983aa548e7cdfd
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2024-12-30T20:04:15+11:00
Commit Message:
DGDS: Print debug after loading DDS data
Changed paths:
engines/dgds/scene.cpp
diff --git a/engines/dgds/scene.cpp b/engines/dgds/scene.cpp
index 5002aff6d28..b7aa5d2636e 100644
--- a/engines/dgds/scene.cpp
+++ b/engines/dgds/scene.cpp
@@ -693,6 +693,8 @@ Dialog *SDSScene::loadDialogData(uint16 num) {
bool result = false;
+ uint prevSize = _dialogs.size();
+
while (chunk.readNextHeader(EX_DDS, filename)) {
if (chunk.isContainer()) {
continue;
@@ -717,6 +719,12 @@ Dialog *SDSScene::loadDialogData(uint16 num) {
delete dlgFile;
+ if (_dialogs.size() != prevSize) {
+ debug(10, "Read %d dialogs from DDS %s:", _dialogs.size() - prevSize, filename.c_str());
+ for (uint i = prevSize; i < _dialogs.size(); i++)
+ debug(10, "%s", _dialogs[i].dump("").c_str());
+ }
+
if (!result)
return nullptr;
Commit: 854c2c4665d3050dd37cba2caa3a9340dc288870
https://github.com/scummvm/scummvm/commit/854c2c4665d3050dd37cba2caa3a9340dc288870
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2024-12-30T20:04:15+11:00
Commit Message:
DGDS: Fix inventory wrapping for Willy Beamish
Changed paths:
engines/dgds/inventory.cpp
diff --git a/engines/dgds/inventory.cpp b/engines/dgds/inventory.cpp
index d21ad3078dc..7231bc3c7b4 100644
--- a/engines/dgds/inventory.cpp
+++ b/engines/dgds/inventory.cpp
@@ -302,7 +302,7 @@ void Inventory::drawItems(Graphics::ManagedSurface &surf) {
// calculate draw offset for the image
int drawX = imgAreaX + x + (xstep - item._rect.width) / 2;
- int drawY = imgAreaY + y + (ystep - item._rect.height) / 2;
+ int drawY = imgAreaY + y + (ystep - item._rect.height) / 2;
icons->drawBitmap(item._iconNum, drawX, drawY, drawMask, surf);
@@ -310,7 +310,9 @@ void Inventory::drawItems(Graphics::ManagedSurface &surf) {
item._rect.y = drawY;
x += xstep;
- if (x >= _itemArea->_width) {
+
+ // Willy Beamish area is 270 and step is 54, so hack the width slightly.
+ if (x >= _itemArea->_width - 2) {
x = 0;
y += ystep;
}
Commit: 29bc5487cd9ca061072a491669a7170bf298633f
https://github.com/scummvm/scummvm/commit/29bc5487cd9ca061072a491669a7170bf298633f
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2024-12-30T20:47:58+11:00
Commit Message:
DGDS: Implement willy trouble gauge
Changed paths:
engines/dgds/dgds.cpp
engines/dgds/dialog.cpp
engines/dgds/globals.cpp
engines/dgds/globals.h
diff --git a/engines/dgds/dgds.cpp b/engines/dgds/dgds.cpp
index f97d5077fbc..0162f05765f 100644
--- a/engines/dgds/dgds.cpp
+++ b/engines/dgds/dgds.cpp
@@ -788,6 +788,7 @@ Common::Error DgdsEngine::run() {
frameCount++;
_skipNextFrame = false;
}
+
const uint32 thisFrameEndMillis = g_system->getMillis();
const uint32 elapsedMillis = thisFrameEndMillis - startMillis;
const uint32 targetMillis = (frameCount * 1000 / 30);
diff --git a/engines/dgds/dialog.cpp b/engines/dgds/dialog.cpp
index b269b2510cd..cc87f2cbdef 100644
--- a/engines/dgds/dialog.cpp
+++ b/engines/dgds/dialog.cpp
@@ -165,9 +165,15 @@ void Dialog::drawType2(Graphics::ManagedSurface *dst, DialogDrawStage stage) {
Common::String title;
Common::String txt;
+
+ //
+ // Colon has to be followed by the first CR to be used as a heading
+ //
uint32 colonpos = _str.find(':');
uint32 crpos = _str.find('\r');
- if (colonpos != Common::String::npos && (crpos == Common::String::npos || crpos > colonpos)) {
+ bool haveColon = colonpos != Common::String::npos;
+ bool haveCR = crpos != Common::String::npos;
+ if (haveColon && haveCR && crpos == colonpos + 1) {
title = _str.substr(0, colonpos);
txt = _str.substr(colonpos + 1);
// Most have a CR after the colon? trim it to remove a blank line.
diff --git a/engines/dgds/globals.cpp b/engines/dgds/globals.cpp
index bd942ef2146..47fd84ccdf8 100644
--- a/engines/dgds/globals.cpp
+++ b/engines/dgds/globals.cpp
@@ -23,6 +23,8 @@
#include "dgds/dgds.h"
#include "dgds/scene.h"
#include "dgds/game_palettes.h"
+#include "dgds/sound.h"
+#include "dgds/includes.h"
namespace Dgds {
@@ -312,14 +314,49 @@ public:
}
};
-class WillyDrawGlobal : public RWI16Global {
+class WillyTroubleGlobal : public RWI16Global {
public:
- WillyDrawGlobal(uint16 num, int16 *val) : RWI16Global(num, val) {}
+ WillyTroubleGlobal(uint16 num, int16 *val) : RWI16Global(num, val) {}
int16 set(int16 val) override {
int16 oldVal = get();
if (val != oldVal) {
+ // Draw the trouble meter changing.
+ DgdsEngine *engine = DgdsEngine::getInstance();
val = CLIP(val, (int16)0, (int16)10);
- error("TODO: Implement set function for willy global 0x02 val %d.", val);
+ Image img(engine->getResourceManager(), engine->getDecompressor());
+ img.loadBitmap("METER.BMP");
+ uint16 soundNum = (oldVal < val) ? 0x386 : 0x387;
+ engine->_soundPlayer->playSFX(soundNum);
+ Graphics::ManagedSurface &compBuf = engine->_compositionBuffer;
+ const Common::Rect screenRect(SCREEN_WIDTH, SCREEN_HEIGHT);
+
+ int16 sign = val > oldVal ? 1 : -1;
+ int16 prevBarSize = oldVal * 8;
+ int16 newBarSize = val * 8;
+
+ // Animate the trouble bar going up or down
+ compBuf.fillRect(Common::Rect(Common::Point(0x80, 0x8a), 0x47, 3), 16);
+
+ for (int sz = prevBarSize; sz != newBarSize; sz += sign) {
+ RequestData::drawCorners(&compBuf, 0, 0x71, 0x25, 0x5e, 0x7e);
+ compBuf.fillRect(Common::Rect(Common::Point(0x80, 0x3a), 0x47, 0x50), 0);
+ if (sz)
+ compBuf.fillRect(Common::Rect(Common::Point(0x80, 0x8a - sz), 0x47, sz), 0x22);
+ img.drawBitmap(0, 0x80, 0x29, screenRect, compBuf);
+
+ //
+ // TODO: Timing is a bit hackily approximate here.
+ // Measure real game timing more accurately. Also probably
+ // should pump messages to make the mouse responsive.
+ //
+ g_system->copyRectToScreen(compBuf.getPixels(), SCREEN_WIDTH, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
+ g_system->updateScreen();
+ g_system->delayMillis(100);
+ }
+
+ g_system->delayMillis(900);
+
+ engine->_soundPlayer->stopSfxByNum(soundNum);
return RWI16Global::set(val);
}
return oldVal;
@@ -328,7 +365,7 @@ public:
WillyGlobals::WillyGlobals(Clock &clock) : Globals(clock),
- _unk2(4), _unk3(0), _invDrawTimeSkipButtons(0), _hideMouseCursor(0), _unk74(0), _unk75(300),
+ _trouble(4), _unk3(0), _invDrawTimeSkipButtons(0), _hideMouseCursor(0), _unk74(0), _unk75(300),
_palFade(255), _droppedItemNum(0), _characterStance(0), _characterPos(0), _unk81(3),
_unk82(1) {
_globals.push_back(new DetailLevelROGlobal(0x53));
@@ -344,12 +381,12 @@ WillyGlobals::WillyGlobals(Clock &clock) : Globals(clock),
_globals.push_back(new RWI16Global(0x05, &_hideMouseCursor));
_globals.push_back(new RWI16Global(0x04, &_invDrawTimeSkipButtons));
_globals.push_back(new RWI16Global(0x03, &_unk3));
- _globals.push_back(new WillyDrawGlobal(0x02, &_unk2));
+ _globals.push_back(new WillyTroubleGlobal(0x02, &_trouble));
}
Common::Error WillyGlobals::syncState(Common::Serializer &s) {
Globals::syncState(s);
- s.syncAsSint16LE(_unk2);
+ s.syncAsSint16LE(_trouble);
s.syncAsSint16LE(_unk3);
s.syncAsSint16LE(_invDrawTimeSkipButtons);
s.syncAsSint16LE(_hideMouseCursor);
diff --git a/engines/dgds/globals.h b/engines/dgds/globals.h
index f99ecc7be9c..0683caf8a3e 100644
--- a/engines/dgds/globals.h
+++ b/engines/dgds/globals.h
@@ -207,7 +207,7 @@ public:
private:
// Willy-specific globals
- int16 _unk2;
+ int16 _trouble;
int16 _unk3;
int16 _invDrawTimeSkipButtons;
int16 _hideMouseCursor;
More information about the Scummvm-git-logs
mailing list