[Scummvm-git-logs] scummvm master -> 09764a18ed56986582f47a929b3477f988f97827
bluegr
noreply at scummvm.org
Sat Jun 6 09:41:35 UTC 2026
This automated email contains information about 2 new commits which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .
Summary:
07a5fb57b8 NANCY: Use a helper method for case insensitive key matching in Nancy10
09764a18ed NANCY: Fix making phone calls within a closeup scene in Nancy10
Commit: 07a5fb57b8740ac3197b91217c243772801bbc55
https://github.com/scummvm/scummvm/commit/07a5fb57b8740ac3197b91217c243772801bbc55
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2026-06-06T12:41:24+03:00
Commit Message:
NANCY: Use a helper method for case insensitive key matching in Nancy10
Allows us to remove relevant hacks. Fixes viewing the trunk in Mary's
Gifts.
Changed paths:
engines/nancy/action/conversation.cpp
engines/nancy/action/miscrecords.cpp
engines/nancy/action/soundrecords.cpp
engines/nancy/ui/cellphonepopup.cpp
engines/nancy/ui/notebookpopup.cpp
engines/nancy/util.cpp
engines/nancy/util.h
diff --git a/engines/nancy/action/conversation.cpp b/engines/nancy/action/conversation.cpp
index 5989b549e1f..4c4a4a609e8 100644
--- a/engines/nancy/action/conversation.cpp
+++ b/engines/nancy/action/conversation.cpp
@@ -185,24 +185,7 @@ void ConversationSound::readTerseCaptionText(Common::SeekableReadStream &stream)
const CVTX *convo = (const CVTX *)g_nancy->getEngineData("CONVO");
assert(convo);
- if (convo->texts.contains(key)) {
- _text = convo->texts[key];
- } else {
- // Nancy10+ searched convo texts in a key insensitive way, but
- // the possible permutations involve mainly the last character
- // being upper or lower case, so just try that before giving up.
- if (key[key.size() - 1] == toupper(key[key.size() - 1]))
- key[key.size() - 1] = tolower(key[key.size() - 1]);
- else
- key[key.size() - 1] = toupper(key[key.size() - 1]);
-
- if (convo->texts.contains(key)) {
- _text = convo->texts[key];
- } else {
- warning("Convo key not found: %s", key.c_str());
- _text = "";
- }
- }
+ _text = getTextFromCaseInsensitiveKey(convo->texts, key);
}
void ConversationSound::readTerseResponseText(Common::SeekableReadStream &stream, ResponseStruct &response) {
@@ -212,7 +195,7 @@ void ConversationSound::readTerseResponseText(Common::SeekableReadStream &stream
const CVTX *convo = (const CVTX *)g_nancy->getEngineData("CONVO");
assert(convo);
- response.text = convo->texts[key];
+ response.text = getTextFromCaseInsensitiveKey(convo->texts, key);
}
void ConversationSound::execute() {
diff --git a/engines/nancy/action/miscrecords.cpp b/engines/nancy/action/miscrecords.cpp
index cacb72796aa..259b1320083 100644
--- a/engines/nancy/action/miscrecords.cpp
+++ b/engines/nancy/action/miscrecords.cpp
@@ -116,7 +116,7 @@ void TextBoxWrite::readData(Common::SeekableReadStream &stream) {
const CVTX *autotext = (const CVTX *)g_nancy->getEngineData("AUTOTEXT");
assert(autotext);
- _text = autotext->texts[stringID];
+ _text = getTextFromCaseInsensitiveKey(autotext->texts, stringID);
} else {
char *buf = new char[size];
stream.read(buf, size);
@@ -159,10 +159,7 @@ void FrameTextBox::readData(Common::SeekableReadStream &stream) {
const CVTX *autotext = (const CVTX *)g_nancy->getEngineData("AUTOTEXT");
assert(autotext);
- // TODO: we probably ought to be doing something more robust here
- // to detect missing keys, but for now just return an empty string
- // if the key isn't found.
- _text = autotext->texts.getValOrDefault(stringID, "");
+ _text = getTextFromCaseInsensitiveKey(autotext->texts, stringID);
} else if (size > 0) {
char *buf = new char[size];
stream.read(buf, size);
diff --git a/engines/nancy/action/soundrecords.cpp b/engines/nancy/action/soundrecords.cpp
index c65cfd4ede6..c27435c3a5d 100644
--- a/engines/nancy/action/soundrecords.cpp
+++ b/engines/nancy/action/soundrecords.cpp
@@ -138,7 +138,7 @@ void PlaySoundCC::readCCText(Common::SeekableReadStream &stream, Common::String
const CVTX *autotext = (const CVTX *)g_nancy->getEngineData("AUTOTEXT");
assert(autotext);
- out = autotext->texts[key];
+ out = getTextFromCaseInsensitiveKey(autotext->texts, key);
}
}
diff --git a/engines/nancy/ui/cellphonepopup.cpp b/engines/nancy/ui/cellphonepopup.cpp
index 60e3f429414..577068cbb6f 100644
--- a/engines/nancy/ui/cellphonepopup.cpp
+++ b/engines/nancy/ui/cellphonepopup.cpp
@@ -728,10 +728,8 @@ void CellPhonePopup::drawLinkList() {
}
Common::String lookupKey = list[absolute].key;
- lookupKey.toUppercase();
- Common::String rowText = (autotext && autotext->texts.contains(lookupKey))
- ? autotext->texts[lookupKey]
- : lookupKey;
+ Common::String rowText = getTextFromCaseInsensitiveKey(autotext->texts, lookupKey);
+
// Single-line draw â drop every <n> markup so they don't render as
// literal "<n>" glyphs and crowd the row.
while (rowText.contains("<n>")) {
@@ -765,9 +763,6 @@ void CellPhonePopup::drawContentView() {
}
const CVTX *autotext = (const CVTX *)g_nancy->getEngineData("AUTOTEXT");
- if (!autotext || !autotext->texts.contains(_contentKey)) {
- return;
- }
const Font *font = g_nancy->_graphics->getFont(_uiclData->fontId2);
if (!font) {
@@ -792,7 +787,7 @@ void CellPhonePopup::drawContentView() {
// Render the engine's hypertext markup into a tall scratch surface,
// then blit a vertically-scrolled window of it into the LCD.
- const Common::String renderText = autotext->texts[_contentKey];
+ const Common::String renderText = getTextFromCaseInsensitiveKey(autotext->texts, _contentKey);
// Find this page in the UIBW chunk (browser pages only); its hotspot
// records are the per-page image table the article references.
diff --git a/engines/nancy/ui/notebookpopup.cpp b/engines/nancy/ui/notebookpopup.cpp
index 50d79fb3842..73037a51983 100644
--- a/engines/nancy/ui/notebookpopup.cpp
+++ b/engines/nancy/ui/notebookpopup.cpp
@@ -441,8 +441,6 @@ void NotebookPopup::buildTextLines() {
return;
const CVTX *autotext = (const CVTX *)g_nancy->getEngineData("AUTOTEXT");
- if (!autotext)
- return;
// Senior-detective Tasks page: hide the to-do list and show the
// AUTOTEXT placeholder body instead.
@@ -459,13 +457,8 @@ void NotebookPopup::buildTextLines() {
const Common::Array<JournalData::Entry> &entries = journalData->journalEntries[surfaceID];
for (uint i = 0; i < entries.size(); ++i) {
- const Common::String &stringID = entries[i].stringID;
- if (!autotext->texts.contains(stringID))
- continue;
-
- Common::String body = autotext->texts[stringID];
- if (body.empty())
- continue;
+ Common::String stringID = entries[i].stringID;
+ Common::String body = getTextFromCaseInsensitiveKey(autotext->texts, stringID);
// Tasks are prefixed with a checkbox showing completion state.
// mark % 10 == 8 means "complete".
diff --git a/engines/nancy/util.cpp b/engines/nancy/util.cpp
index 971d90a6df4..6c9518635f1 100644
--- a/engines/nancy/util.cpp
+++ b/engines/nancy/util.cpp
@@ -344,6 +344,31 @@ void assembleTextLine(char *rawCaption, Common::String &output, uint size) {
}
}
+Common::String getTextFromCaseInsensitiveKey(Common::HashMap<Common::String, Common::String> texts, Common::String &key) {
+ if (texts.contains(key)) {
+ return texts[key];
+ } else {
+ // Nancy10+ searched keyed texts in a key insensitive way, but
+ // the possible permutations involve mainly the last character
+ // being upper or lower case, so just try that before giving up.
+ if (key[key.size() - 1] == toupper(key[key.size() - 1]))
+ key[key.size() - 1] = tolower(key[key.size() - 1]);
+ else
+ key[key.size() - 1] = toupper(key[key.size() - 1]);
+
+ if (texts.contains(key))
+ return texts[key];
+
+ key.toUppercase();
+
+ if (texts.contains(key))
+ return texts[key];
+ }
+
+ warning("Key not found: %s", key.c_str());
+ return "";
+}
+
bool DeferredLoader::load(uint32 endTime) {
uint32 loopStartTime = g_system->getMillis();
uint32 loopTime = 0; // Stores the loop that took the longest time to complete
diff --git a/engines/nancy/util.h b/engines/nancy/util.h
index 3dc6ab1eaf5..0977792e16f 100644
--- a/engines/nancy/util.h
+++ b/engines/nancy/util.h
@@ -22,6 +22,7 @@
#define NANCY_UTIL_H
#include "common/array.h"
+#include "common/hashmap.h"
#include "common/path.h"
#include "common/rect.h"
#include "common/serializer.h"
@@ -64,6 +65,8 @@ void readUISlider(Common::SeekableReadStream &stream, UISliderRecord &dst);
void readUIPopupHeader(Common::SeekableReadStream &stream, UIPopupHeader &dst);
void readUIButtonSlot(Common::SeekableReadStream &stream, UIButtonSlot &dst);
+Common::String getTextFromCaseInsensitiveKey(Common::HashMap<Common::String, Common::String> texts, Common::String &key);
+
// Abstract base class used for loading data that would take too much time in a single frame
class DeferredLoader {
public:
Commit: 09764a18ed56986582f47a929b3477f988f97827
https://github.com/scummvm/scummvm/commit/09764a18ed56986582f47a929b3477f988f97827
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2026-06-06T12:41:26+03:00
Commit Message:
NANCY: Fix making phone calls within a closeup scene in Nancy10
The call phone's scene pushing/popping mechanism could clobber the
global scene stack. Add safeguards, so that doesn't happen.
Fixes making phone calls within a closeup scene, e.g. when calling
Charleena Purcell while looking at a closeup of the trunk in Mary's
Gifts.
Changed paths:
engines/nancy/action/miscrecords.cpp
engines/nancy/ui/cellphonepopup.cpp
engines/nancy/ui/cellphonepopup.h
diff --git a/engines/nancy/action/miscrecords.cpp b/engines/nancy/action/miscrecords.cpp
index 259b1320083..f3054b3afbe 100644
--- a/engines/nancy/action/miscrecords.cpp
+++ b/engines/nancy/action/miscrecords.cpp
@@ -219,8 +219,9 @@ void ControlUIItems::execute() {
case kUITypeNotebook:
NancySceneState.getNotebookPopup().open();
break;
- case kUITypeCellphone:
- NancySceneState.getCellPhonePopup().open();
+ case kUITypeCellphone: {
+ UI::CellPhonePopup &phone = NancySceneState.getCellPhonePopup();
+ phone.open();
if (_startScene != (int16)kNoScene) {
SceneChangeDescription scene;
@@ -230,11 +231,13 @@ void ControlUIItems::execute() {
// The destination scene's sound carries the conversation audio.
scene.continueSceneSound = kLoadSceneSound;
- // Pushed so AR 128 in the conversation scene can return here.
- NancySceneState.pushScene();
+ // Save the pre-call scene on the popup so AR 128 returns
+ // there without touching the global push slot.
+ phone.setReturnScene(NancySceneState.getSceneInfo());
NancySceneState.changeScene(scene);
}
break;
+ }
default:
break;
}
@@ -346,14 +349,22 @@ void CellPhonePopCellSceneFromStack::readData(Common::SeekableReadStream &stream
}
void CellPhonePopCellSceneFromStack::execute() {
- if (_sceneChange.sceneID == kNoScene) {
- NancySceneState.popScene(false);
- } else {
+ UI::CellPhonePopup &phone = NancySceneState.getCellPhonePopup();
+
+ if (_sceneChange.sceneID != kNoScene) {
NancySceneState.changeScene(_sceneChange);
+ } else {
+ // Restore the pre-call scene if one was saved. If there's no saved
+ // scene (e.g. the conversation was entered without a phone call),
+ // do nothing â popping the global scene stack here would clobber
+ // closeup / inventory pushes that have nothing to do with the phone.
+ SceneChangeDescription returnScene;
+ if (phone.consumeReturnScene(returnScene))
+ NancySceneState.changeScene(returnScene);
}
// Conversation is over; take the phone down.
- NancySceneState.getCellPhonePopup().close();
+ phone.close();
finishExecution();
}
diff --git a/engines/nancy/ui/cellphonepopup.cpp b/engines/nancy/ui/cellphonepopup.cpp
index 577068cbb6f..d9aab409861 100644
--- a/engines/nancy/ui/cellphonepopup.cpp
+++ b/engines/nancy/ui/cellphonepopup.cpp
@@ -1116,14 +1116,28 @@ void CellPhonePopup::triggerContactCallSceneChange(uint contactIndex) {
eventFlagValue ? g_nancy->_true : g_nancy->_false);
}
- // Pushed so AR 128 in the conversation scene can return the player here.
- NancySceneState.pushScene();
+ // Save the pre-call scene on the popup so AR 128 can return there
+ // without clobbering the global push slot (used by closeups, etc).
+ setReturnScene(NancySceneState.getSceneInfo());
NancySceneState.changeScene(scene);
// Phone stays on screen through the conversation; AR 128 closes it.
}
+void CellPhonePopup::setReturnScene(const SceneChangeDescription &scene) {
+ _returnScene = scene;
+ _hasReturnScene = true;
+}
+
+bool CellPhonePopup::consumeReturnScene(SceneChangeDescription &out) {
+ if (!_hasReturnScene)
+ return false;
+ out = _returnScene;
+ _hasReturnScene = false;
+ return true;
+}
+
// --------------------------------------------------------------------
// Directory helpers
// --------------------------------------------------------------------
diff --git a/engines/nancy/ui/cellphonepopup.h b/engines/nancy/ui/cellphonepopup.h
index 9a0353003bd..0536c135a7f 100644
--- a/engines/nancy/ui/cellphonepopup.h
+++ b/engines/nancy/ui/cellphonepopup.h
@@ -65,6 +65,12 @@ public:
const Common::String &value, int16 extra,
int16 flag, int16 eventFlag);
+ // Phone-call return scene. Set before jumping into a conversation scene
+ // so AR 128 (CellPhonePopCellSceneFromStack) can return there without
+ // trampling the global push slot used by closeups/inventory views.
+ void setReturnScene(const SceneChangeDescription &scene);
+ bool consumeReturnScene(SceneChangeDescription &out);
+
private:
enum ScreenState : int {
kWelcome = 0,
@@ -212,6 +218,9 @@ private:
bool _noSignal = false;
bool _batteryLow = false;
+
+ SceneChangeDescription _returnScene;
+ bool _hasReturnScene = false;
};
} // End of namespace UI
More information about the Scummvm-git-logs
mailing list