[Scummvm-git-logs] scummvm master -> 1b94ca4b2f1db0c7f0d2a1c9e314ddcea54ab1d2

bluegr noreply at scummvm.org
Tue Apr 28 01:05:30 UTC 2026


This automated email contains information about 8 new commits which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .

Summary:
78fa279001 NANCY: Properly handle the INV chunk for Nancy10+
0dbacb1043 NANCY: Add handling for the UIBW (web browser) chunk, used in Nancy10+
4f1f0822c6 NANCY: Introduce common types for Nancy10+ UI elements
eaa16ce997 NANCY: Add handling for the Nancy10+ UICO (conversation popup) chunk
db4a693481 NANCY: Add handling for the Nancy10+ TASK chunk (main UI)
4922da8092 NANCY: Add handling for the common UI button slot type
133ef5787a NANCY: Handle the Nancy10+ UIIV (inventory) and UINB (notebook) chunks
1b94ca4b2f NANCY: Add handling for the Nancy10+ UICL (cell phone) chunk


Commit: 78fa279001a60cef62e45a3f74c4a902c262e4c7
    https://github.com/scummvm/scummvm/commit/78fa279001a60cef62e45a3f74c4a902c262e4c7
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2026-04-28T03:58:42+03:00

Commit Message:
NANCY: Properly handle the INV chunk for Nancy10+

Changed paths:
    engines/nancy/enginedata.cpp


diff --git a/engines/nancy/enginedata.cpp b/engines/nancy/enginedata.cpp
index 11ca6d02722..8146ca70ca1 100644
--- a/engines/nancy/enginedata.cpp
+++ b/engines/nancy/enginedata.cpp
@@ -223,10 +223,13 @@ INV::INV(Common::SeekableReadStream *chunkStream) : EngineData(chunkStream) {
 			item.cantSound.readNormal(*chunkStream);
 		} else if (s.getVersion() >= kGameTypeNancy9) {
 			for (int j = 0; j < 3; ++j) {
+				if (s.getVersion() >= kGameTypeNancy10)
+					readFilename(s, item.cantSounds[j].name);
 				s.syncBytes(textBuf, 60);
 				textBuf[59] = '\0';
 				assembleTextLine((char *)textBuf, item.cantTexts[j], 60);
-				readFilename(s, item.cantSounds[j].name);
+				if (s.getVersion() == kGameTypeNancy9)
+					readFilename(s, item.cantSounds[j].name);
 			}
 
 			item.cantText = item.cantTexts[0]; // Default text is the first one


Commit: 0dbacb10431ea4086b4b7124698ef645dadc2484
    https://github.com/scummvm/scummvm/commit/0dbacb10431ea4086b4b7124698ef645dadc2484
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2026-04-28T03:58:43+03:00

Commit Message:
NANCY: Add handling for the UIBW (web browser) chunk, used in Nancy10+

Changed paths:
    engines/nancy/enginedata.cpp
    engines/nancy/enginedata.h


diff --git a/engines/nancy/enginedata.cpp b/engines/nancy/enginedata.cpp
index 8146ca70ca1..0ba65b5434f 100644
--- a/engines/nancy/enginedata.cpp
+++ b/engines/nancy/enginedata.cpp
@@ -877,7 +877,31 @@ TASK::TASK(Common::SeekableReadStream *chunkStream) : EngineData(chunkStream) {
 
 UIBW::UIBW(Common::SeekableReadStream *chunkStream) : EngineData(chunkStream) {
 	readFilename(*chunkStream, imageName);
-	// TODO
+
+	// Read URL records one at a time, stopping when the remaining bytes
+	// are no longer enough for a full record or when the record has an
+	// empty (zero-byte) name — the game pads the array with empty slots.
+	while (chunkStream->size() - chunkStream->pos() >= (int64)kUrlRecordSize) {
+		UrlPage page;
+		readFilename(*chunkStream, page.imageName);
+		if (page.imageName.empty()) {
+			// Skip the remainder of the (empty) record: 215 - 33 bytes.
+			chunkStream->skip(kUrlRecordSize - 33);
+			continue;
+		}
+
+		uint16 hotspotCount = chunkStream->readUint16LE();
+		for (uint i = 0; i < kMaxHotspotsPerPage; ++i) {
+			Hotspot h;
+			h.id = chunkStream->readUint16LE();
+			readRect(*chunkStream, h.rect);
+			if (i < hotspotCount) {
+				page.hotspots.push_back(h);
+			}
+		}
+
+		pages.push_back(page);
+	}
 }
 
 UICL::UICL(Common::SeekableReadStream *chunkStream) : EngineData(chunkStream) {
diff --git a/engines/nancy/enginedata.h b/engines/nancy/enginedata.h
index e6124a002b9..9ee4cc434f9 100644
--- a/engines/nancy/enginedata.h
+++ b/engines/nancy/enginedata.h
@@ -507,11 +507,26 @@ struct TASK : public EngineData {
 	Common::Path imageName;
 };
 
-// New web browser UI. Introduced in Nancy 10
+// Web browser popup UI (used from the cell phone to view in-game "web
+// pages"). Introduced in Nancy 10
 struct UIBW : public EngineData {
+	struct Hotspot {
+		uint16 id = 0;
+		Common::Rect rect;
+	};
+
+	struct UrlPage {
+		Common::Path imageName;
+		Common::Array<Hotspot> hotspots;
+	};
+
 	UIBW(Common::SeekableReadStream *chunkStream);
 
+	static const uint kUrlRecordSize = 215;
+	static const uint kMaxHotspotsPerPage = 10;
+
 	Common::Path imageName;
+	Common::Array<UrlPage> pages;
 };
 
 // New cell phone popup UI. Introduced in Nancy 10


Commit: 4f1f0822c601c00e960fd6e335db2dd8bb7d7039
    https://github.com/scummvm/scummvm/commit/4f1f0822c601c00e960fd6e335db2dd8bb7d7039
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2026-04-28T03:58:44+03:00

Commit Message:
NANCY: Introduce common types for Nancy10+ UI elements

Changed paths:
    engines/nancy/commontypes.h
    engines/nancy/util.cpp
    engines/nancy/util.h


diff --git a/engines/nancy/commontypes.h b/engines/nancy/commontypes.h
index c118303ad74..a8863e0531e 100644
--- a/engines/nancy/commontypes.h
+++ b/engines/nancy/commontypes.h
@@ -25,6 +25,7 @@
 #include "common/rect.h"
 #include "common/array.h"
 #include "common/language.h"
+#include "common/path.h"
 #include "common/str.h"
 #include "math/vector3d.h"
 
@@ -348,6 +349,62 @@ struct StaticData {
 	void readData(Common::SeekableReadStream &stream, Common::Language language, uint32 endPos, int8 majorVersion, int8 minorVersion);
 };
 
+// Reusable button widget embedded in Nancy 10+ popup UIs.
+struct UIButtonRecord {
+	static const uint kRecordSize = 239;
+	Common::Path primaryImageName;
+	Common::Path secondaryImageName;
+	uint32 id = 0;
+	Common::Rect sourceRects[4];
+	Common::Rect srcBackgroundRestore;
+	Common::Rect destRect;
+	uint32 destUsesGameFrameOffset = 0; // translate dest by game-frame origin when non-zero
+	uint32 hoverEnableFlag = 0;
+	uint32 hoverCursorFlag = 0; // swap cursor sprite on hover when set
+	uint32 secondaryStateField = 0;
+	uint32 initialState = 0; // 0=idle, 1=hover, 2=pressed, 3/4=disabled
+	uint32 reservedField = 0;
+	SoundDescription clickSound;
+};
+
+// Reusable slider widget embedded in Nancy 10+ popup UIs.
+struct UISliderRecord {
+	static const uint kRecordSize = 198;
+	Common::Path primaryImageName;
+	Common::Path secondaryImageName;
+	uint32 id = 0;
+	Common::Rect sourceRects[4];
+	Common::Rect srcBackgroundRestore;
+	Common::Rect destRect;
+	uint32 destUsesGameFrameOffset = 0; // translate dest by game-frame origin when non-zero
+	uint32 unknownA = 0;
+	uint32 isDraggable = 0; // when zero, the slider stays at its current value on click
+	uint32 unknownC = 0;
+	uint32 orientation = 0;  // 0 = horizontal, 1 = vertical
+	uint32 positionHint = 0; // 0/1 left/right for horiz, 2/3 top/bottom for vert
+	uint32 secondaryStateField = 0;
+	uint32 initialState = 0; // 0=idle, 1=hover, 2=dragging
+};
+
+// Common header shared by all Nancy 10 popup-UI chunks
+// (UIIV, UICO, UICL, UINB).
+struct UIPopupHeader {
+	Common::Path imageName;         // background image
+	uint32 unknownHeaderField = 0;  // chunk version
+	int16 linkbackScene = 9999;     // return scene; 9999 = none
+	Common::Rect normalSrcRect;     // SRC rect on the popup overlay image when in state 2 (normal size)
+	Common::Rect maximizedSrcRect;  // SRC rect on the popup overlay image when in state 3 (maximized size)
+	Common::Rect normalDestRect;    // DEST rect on screen for state 2 (normal size)
+	Common::Rect maximizedDestRect; // DEST rect on screen for state 3 (maximized size)
+	uint32 overlayInGameFrame = 0;  // if non-zero, both dest rects are translated during initialization
+	SoundDescription sounds[4];     // open/close/button-click sound slots
+
+	uint32 secondaryButtonEnabled = 0;
+	UIButtonRecord secondaryButton;
+	uint32 sliderEnabled = 0;
+	UISliderRecord slider;
+};
+
 } // End of namespace Nancy
 
 #endif // NANCY_COMMONYPES_H
diff --git a/engines/nancy/util.cpp b/engines/nancy/util.cpp
index 78d22d2b8ef..7f7906aa27d 100644
--- a/engines/nancy/util.cpp
+++ b/engines/nancy/util.cpp
@@ -18,6 +18,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include "engines/nancy/enginedata.h"
 #include "engines/nancy/nancy.h"
 #include "engines/nancy/util.h"
 #include "common/system.h"
@@ -247,6 +248,73 @@ void readFilenameArray(Common::Serializer &stream, Common::Array<Common::Path> &
 	}
 }
 
+void readUIButton(Common::SeekableReadStream &stream, UIButtonRecord &dst) {
+	// Read common fields for both buttons and sliders
+	readFilename(stream, dst.primaryImageName);
+	readFilename(stream, dst.secondaryImageName);
+	dst.id = stream.readUint32LE();
+	for (int i = 0; i < 4; ++i) {
+		readRect(stream, dst.sourceRects[i]);
+	}
+	readRect(stream, dst.srcBackgroundRestore);
+	readRect(stream, dst.destRect);
+	dst.destUsesGameFrameOffset = stream.readUint32LE();
+
+	dst.hoverEnableFlag = stream.readUint32LE();
+	dst.hoverCursorFlag = stream.readUint32LE();
+	dst.secondaryStateField = stream.readUint32LE();
+	dst.initialState = stream.readUint32LE();
+	dst.reservedField = stream.readUint32LE();
+
+	dst.clickSound.readNormal(stream);
+}
+
+void readUISlider(Common::SeekableReadStream &stream, UISliderRecord &dst) {
+	// Read common fields for both buttons and sliders
+	readFilename(stream, dst.primaryImageName);
+	readFilename(stream, dst.secondaryImageName);
+	dst.id = stream.readUint32LE();
+	for (int i = 0; i < 4; ++i) {
+		readRect(stream, dst.sourceRects[i]);
+	}
+	readRect(stream, dst.srcBackgroundRestore);
+	readRect(stream, dst.destRect);
+	dst.destUsesGameFrameOffset = stream.readUint32LE();
+
+	dst.unknownA = stream.readUint32LE();
+	dst.isDraggable = stream.readUint32LE();
+	dst.unknownC = stream.readUint32LE();
+	dst.orientation = stream.readUint32LE();
+	dst.positionHint = stream.readUint32LE();
+	dst.secondaryStateField = stream.readUint32LE();
+	dst.initialState = stream.readUint32LE();
+}
+
+// Reads the base header that precedes every Nancy 10 popup-UI
+// chunk (UIIV, UICO, UICL, UINB).
+void readUIPopupHeader(Common::SeekableReadStream &stream, UIPopupHeader &dst) {
+	readFilename(stream, dst.imageName);
+	dst.unknownHeaderField = stream.readUint32LE();
+	dst.linkbackScene = stream.readSint16LE();
+	readRect(stream, dst.normalSrcRect);
+	readRect(stream, dst.maximizedSrcRect);
+	readRect(stream, dst.normalDestRect);
+	readRect(stream, dst.maximizedDestRect);
+	dst.overlayInGameFrame = stream.readUint32LE();
+
+	stream.skip(4);
+
+	for (int i = 0; i < 4; ++i) {
+		dst.sounds[i].readNormal(stream);
+	}
+
+	dst.secondaryButtonEnabled = stream.readUint32LE();
+	readUIButton(stream, dst.secondaryButton);
+
+	dst.sliderEnabled = stream.readUint32LE();
+	readUISlider(stream, dst.slider);
+}
+
 // A text line will often be broken up into chunks separated by nulls, use
 // this function to put it back together as a Common::String
 void assembleTextLine(char *rawCaption, Common::String &output, uint size) {
diff --git a/engines/nancy/util.h b/engines/nancy/util.h
index ef1e97b32d1..a4efef64348 100644
--- a/engines/nancy/util.h
+++ b/engines/nancy/util.h
@@ -26,8 +26,14 @@
 #include "common/rect.h"
 #include "common/serializer.h"
 
+#include "engines/nancy/commontypes.h"
+
 namespace Nancy {
 
+void readUIButton(Common::SeekableReadStream &stream, UIButtonRecord &dst);
+void readUISlider(Common::SeekableReadStream &stream, UISliderRecord &dst);
+void readUIPopupHeader(Common::SeekableReadStream &stream, UIPopupHeader &dst);
+
 void readRect(Common::SeekableReadStream &stream, Common::Rect &inRect);
 void readRect(Common::Serializer &stream, Common::Rect &inRect, Common::Serializer::Version minVersion = 0, Common::Serializer::Version maxVersion = Common::Serializer::kLastVersion);
 void readRectArray(Common::SeekableReadStream &stream, Common::Array<Common::Rect> &inArray, uint num, uint totalNum = 0);


Commit: eaa16ce9974cdf3084dd563a753c572b13cf71c3
    https://github.com/scummvm/scummvm/commit/eaa16ce9974cdf3084dd563a753c572b13cf71c3
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2026-04-28T03:58:45+03:00

Commit Message:
NANCY: Add handling for the Nancy10+ UICO (conversation popup) chunk

Changed paths:
    engines/nancy/enginedata.cpp
    engines/nancy/enginedata.h


diff --git a/engines/nancy/enginedata.cpp b/engines/nancy/enginedata.cpp
index 0ba65b5434f..e78fce075a9 100644
--- a/engines/nancy/enginedata.cpp
+++ b/engines/nancy/enginedata.cpp
@@ -910,8 +910,8 @@ UICL::UICL(Common::SeekableReadStream *chunkStream) : EngineData(chunkStream) {
 }
 
 UICO::UICO(Common::SeekableReadStream *chunkStream) : EngineData(chunkStream) {
-	readFilename(*chunkStream, imageName);
-	// TODO
+	readUIPopupHeader(*chunkStream, header);
+	readRect(*chunkStream, textRect);
 }
 
 UIIV::UIIV(Common::SeekableReadStream *chunkStream) : EngineData(chunkStream) {
diff --git a/engines/nancy/enginedata.h b/engines/nancy/enginedata.h
index 9ee4cc434f9..252895cfb3e 100644
--- a/engines/nancy/enginedata.h
+++ b/engines/nancy/enginedata.h
@@ -23,6 +23,7 @@
 #define NANCY_ENGINEDATA_H
 
 #include "engines/nancy/commontypes.h"
+#include "engines/nancy/util.h"
 
 #include "common/hash-str.h"
 #include "common/path.h"
@@ -536,11 +537,16 @@ struct UICL : public EngineData {
 	Common::Path imageName;
 };
 
-// New conversation popup UI. Introduced in Nancy 10
+// New conversation popup UI (the text strip that appears above the taskbar
+// when a character is speaking). Introduced in Nancy 10.
+// Note: response hotspots are NOT in this chunk — they live in a separate
+// TextBoxSummaryChunk, each carrying a response-sound filename referenced
+// by ProcessConversation when STOP_VIDEO transitions to PLAYER_RESPONSE_SOUND.
 struct UICO : public EngineData {
 	UICO(Common::SeekableReadStream *chunkStream);
 
-	Common::Path imageName;
+	UIPopupHeader header;
+	Common::Rect textRect;      // Text-drawing rect inside the popup overlay
 };
 
 // New inventory UI. Introduced in Nancy 10


Commit: db4a693481da9d704580a1196eb86aafcaea1c64
    https://github.com/scummvm/scummvm/commit/db4a693481da9d704580a1196eb86aafcaea1c64
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2026-04-28T03:58:46+03:00

Commit Message:
NANCY: Add handling for the Nancy10+ TASK chunk (main UI)

Changed paths:
    engines/nancy/enginedata.cpp
    engines/nancy/enginedata.h
    engines/nancy/nancy.cpp


diff --git a/engines/nancy/enginedata.cpp b/engines/nancy/enginedata.cpp
index e78fce075a9..e3fc9a24541 100644
--- a/engines/nancy/enginedata.cpp
+++ b/engines/nancy/enginedata.cpp
@@ -870,9 +870,23 @@ SHUI::SHUI(Common::SeekableReadStream *chunkStream) : EngineData(chunkStream) {
 }
 
 TASK::TASK(Common::SeekableReadStream *chunkStream) : EngineData(chunkStream) {
-	chunkStream->skip(97);
 	readFilename(*chunkStream, imageName);
-	// TODO
+
+	readRect(*chunkStream, srcRect);
+	readRect(*chunkStream, dstRect);
+	readRect(*chunkStream, unkRect1);
+	readRect(*chunkStream, unkRect2);
+
+	char nameBuf[34];
+	for (uint i = 0; i < kNumButtons; ++i) {
+		readUIButton(*chunkStream, buttons[i].button);
+		chunkStream->read(buttons[i].unknownPad, sizeof(buttons[i].unknownPad));
+		for (uint s = 0; s < kNumAltSounds; ++s) {
+			chunkStream->read(nameBuf, 33);
+			nameBuf[33] = '\0';
+			buttons[i].clickSoundName[s] = nameBuf;
+		}
+	}
 }
 
 UIBW::UIBW(Common::SeekableReadStream *chunkStream) : EngineData(chunkStream) {
diff --git a/engines/nancy/enginedata.h b/engines/nancy/enginedata.h
index 252895cfb3e..f898e18f3d1 100644
--- a/engines/nancy/enginedata.h
+++ b/engines/nancy/enginedata.h
@@ -501,11 +501,37 @@ struct SCTB : public EngineData {
 	Common::Path imageName;
 };
 
-// New task list UI. Introduced in Nancy 10
+enum TaskButton {
+	kTaskButtonMenu = 0,
+	kTaskButtonInventory = 1,
+	kTaskButtonNotebook = 2,
+	kTaskButtonCellphone = 3,
+	kTaskButtonHelp = 4
+};
+
+// Taskbar (the always-on strip at the bottom of the screen with MENU /
+// inventory / notebook / cellphone / HELP buttons). Introduced in Nancy 10.
 struct TASK : public EngineData {
+	struct ButtonRecord {
+		UIButtonRecord button;
+		byte unknownPad[16];
+		Common::String clickSoundName[3];
+	};
+
 	TASK(Common::SeekableReadStream *chunkStream);
 
+	static const uint kNumButtons = 5;
+	static const uint kButtonRecordSize = 354;
+	static const uint kNumAltSounds = 3;
+
 	Common::Path imageName;
+
+	Common::Rect srcRect;
+	Common::Rect dstRect;
+	Common::Rect unkRect1;
+	Common::Rect unkRect2;
+
+	ButtonRecord buttons[kNumButtons];
 };
 
 // Web browser popup UI (used from the cell phone to view in-game "web
diff --git a/engines/nancy/nancy.cpp b/engines/nancy/nancy.cpp
index 4a31155579c..16b4bf88b01 100644
--- a/engines/nancy/nancy.cpp
+++ b/engines/nancy/nancy.cpp
@@ -482,7 +482,7 @@ void NancyEngine::bootGameEngine() {
 	// FONT chunk has been moved into a separate file
 	// FR0 chunk has been removed
 	LOAD_BOOT(SHUI)	// Shared UI elements
-	LOAD_BOOT(TASK)	// Task list UI
+	LOAD_BOOT(TASK)	// Task bar (main UI)
 	LOAD_BOOT(UIIV)	// Inventory UI
 	LOAD_BOOT(UICO)	// Conversation UI
 	LOAD_BOOT(UICL) // Cell phone UI


Commit: 4922da80925634d893bd4c6ea6d2b2d7f62fd689
    https://github.com/scummvm/scummvm/commit/4922da80925634d893bd4c6ea6d2b2d7f62fd689
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2026-04-28T03:58:47+03:00

Commit Message:
NANCY: Add handling for the common UI button slot type

Used for the notebook tab strip (UINB) and the inventory
category-filter strip (UIIV)

Changed paths:
    engines/nancy/commontypes.h
    engines/nancy/util.cpp
    engines/nancy/util.h


diff --git a/engines/nancy/commontypes.h b/engines/nancy/commontypes.h
index a8863e0531e..8d1cf27be6f 100644
--- a/engines/nancy/commontypes.h
+++ b/engines/nancy/commontypes.h
@@ -367,6 +367,15 @@ struct UIButtonRecord {
 	SoundDescription clickSound;
 };
 
+// A UIButton slot. Used for the notebook tab strip (UINB) and the
+// inventory category-filter strip (UIIV).
+struct UIButtonSlot {
+	static const uint kRecordSize = 247;
+	uint32 enabled = 0;
+	uint32 id = 0;         // slot identifier (filter category / tab)
+	UIButtonRecord button;
+};
+
 // Reusable slider widget embedded in Nancy 10+ popup UIs.
 struct UISliderRecord {
 	static const uint kRecordSize = 198;
diff --git a/engines/nancy/util.cpp b/engines/nancy/util.cpp
index 7f7906aa27d..971d90a6df4 100644
--- a/engines/nancy/util.cpp
+++ b/engines/nancy/util.cpp
@@ -269,6 +269,12 @@ void readUIButton(Common::SeekableReadStream &stream, UIButtonRecord &dst) {
 	dst.clickSound.readNormal(stream);
 }
 
+void readUIButtonSlot(Common::SeekableReadStream &stream, UIButtonSlot &dst) {
+	dst.enabled = stream.readUint32LE();
+	dst.id = stream.readUint32LE();
+	readUIButton(stream, dst.button);
+}
+
 void readUISlider(Common::SeekableReadStream &stream, UISliderRecord &dst) {
 	// Read common fields for both buttons and sliders
 	readFilename(stream, dst.primaryImageName);
diff --git a/engines/nancy/util.h b/engines/nancy/util.h
index a4efef64348..3dc6ab1eaf5 100644
--- a/engines/nancy/util.h
+++ b/engines/nancy/util.h
@@ -30,10 +30,6 @@
 
 namespace Nancy {
 
-void readUIButton(Common::SeekableReadStream &stream, UIButtonRecord &dst);
-void readUISlider(Common::SeekableReadStream &stream, UISliderRecord &dst);
-void readUIPopupHeader(Common::SeekableReadStream &stream, UIPopupHeader &dst);
-
 void readRect(Common::SeekableReadStream &stream, Common::Rect &inRect);
 void readRect(Common::Serializer &stream, Common::Rect &inRect, Common::Serializer::Version minVersion = 0, Common::Serializer::Version maxVersion = Common::Serializer::kLastVersion);
 void readRectArray(Common::SeekableReadStream &stream, Common::Array<Common::Rect> &inArray, uint num, uint totalNum = 0);
@@ -63,6 +59,11 @@ void readFilenameArray(Common::Serializer &stream, Common::Array<Common::Path> &
 
 void assembleTextLine(char *rawCaption, Common::String &output, uint size);
 
+void readUIButton(Common::SeekableReadStream &stream, UIButtonRecord &dst);
+void readUISlider(Common::SeekableReadStream &stream, UISliderRecord &dst);
+void readUIPopupHeader(Common::SeekableReadStream &stream, UIPopupHeader &dst);
+void readUIButtonSlot(Common::SeekableReadStream &stream, UIButtonSlot &dst);
+
 // Abstract base class used for loading data that would take too much time in a single frame
 class DeferredLoader {
 public:


Commit: 133ef5787a7affc090c7eccf3169f1f30e35d585
    https://github.com/scummvm/scummvm/commit/133ef5787a7affc090c7eccf3169f1f30e35d585
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2026-04-28T03:58:48+03:00

Commit Message:
NANCY: Handle the Nancy10+ UIIV (inventory) and UINB (notebook) chunks

Changed paths:
    engines/nancy/enginedata.cpp
    engines/nancy/enginedata.h


diff --git a/engines/nancy/enginedata.cpp b/engines/nancy/enginedata.cpp
index e3fc9a24541..62ac6854540 100644
--- a/engines/nancy/enginedata.cpp
+++ b/engines/nancy/enginedata.cpp
@@ -929,13 +929,48 @@ UICO::UICO(Common::SeekableReadStream *chunkStream) : EngineData(chunkStream) {
 }
 
 UIIV::UIIV(Common::SeekableReadStream *chunkStream) : EngineData(chunkStream) {
-	readFilename(*chunkStream, imageName);
-	// TODO
+	readUIPopupHeader(*chunkStream, header);
+
+	readRectArray(*chunkStream, slotSrcRects, 16);
+	readRectArray(*chunkStream, slotDestRects, 16);
+
+	chunkStream->skip(2);
+
+	for (uint i = 0; i < kNumFilters; ++i) {
+		readUIButtonSlot(*chunkStream, filters[i]);
+	}
+
+	readRectArray(*chunkStream, tabCaptionSrcRects, kNumFilters);
+
+	readRect(*chunkStream, tabCaptionDestRect);
 }
 
 UINB::UINB(Common::SeekableReadStream *chunkStream) : EngineData(chunkStream) {
-	readFilename(*chunkStream, imageName);
-	// TODO
+	readUIPopupHeader(*chunkStream, header);
+
+	for (uint i = 0; i < kNumTabs; ++i) {
+		readUIButtonSlot(*chunkStream, tabs[i]);
+	}
+
+	readRect(*chunkStream, textRect);
+	primaryFontID = chunkStream->readUint16LE();
+	secondaryFontAttr = chunkStream->readUint16LE();
+	useFilenameTextFlag = chunkStream->readUint16LE();
+	readFilename(*chunkStream, conditionalTextFilename);
+
+	// 3 sound names played at random when an item is marked complete
+	// (glyph attr -> 8)
+	for (uint i = 0; i < kNumPageSoundsPerSet; ++i) {
+		readFilename(*chunkStream, actionableClickSounds[i]);
+	}
+
+	// 3 sound names for no-action clicks
+	for (uint i = 0; i < kNumPageSoundsPerSet; ++i) {
+		readFilename(*chunkStream, noActionClickSounds[i]);
+	}
+
+	readRectArray(*chunkStream, tabCaptionSrcRects, kNumTabs);
+	readRect(*chunkStream, tabCaptionDestRect);
 }
 
 } // End of namespace Nancy
diff --git a/engines/nancy/enginedata.h b/engines/nancy/enginedata.h
index f898e18f3d1..ace098cebf9 100644
--- a/engines/nancy/enginedata.h
+++ b/engines/nancy/enginedata.h
@@ -575,18 +575,39 @@ struct UICO : public EngineData {
 	Common::Rect textRect;      // Text-drawing rect inside the popup overlay
 };
 
-// New inventory UI. Introduced in Nancy 10
+// New inventory popup UI (4x4 item grid with paging slider and category
+// filter tabs along the right edge). Introduced in Nancy 10.
 struct UIIV : public EngineData {
 	UIIV(Common::SeekableReadStream *chunkStream);
 
-	Common::Path imageName;
+	static const uint kNumFilters = 6;
+
+	UIPopupHeader header;
+	Common::Array<Common::Rect> slotSrcRects;       // 16 entries (image coords)
+	Common::Array<Common::Rect> slotDestRects;      // 16 entries (screen coords)
+	UIButtonSlot filters[kNumFilters];              // 6 entries
+	Common::Array<Common::Rect> tabCaptionSrcRects; // 6 entries
+	Common::Rect tabCaptionDestRect;                // on-screen target
 };
 
-// New notebook UI. Introduced in Nancy 10
+// New notebook UI. Introduced in Nancy 10.
 struct UINB : public EngineData {
 	UINB(Common::SeekableReadStream *chunkStream);
 
-	Common::Path imageName;
+	static const uint kNumTabs = 2;
+	static const uint kNumPageSoundsPerSet = 3;
+
+	UIPopupHeader header;
+	UIButtonSlot tabs[kNumTabs];
+	Common::Rect textRect;
+	uint16 primaryFontID = 0;
+	uint16 secondaryFontAttr = 0;
+	uint16 useFilenameTextFlag = 0;
+	Common::Path conditionalTextFilename;
+	Common::Path actionableClickSounds[kNumPageSoundsPerSet];
+	Common::Path noActionClickSounds[kNumPageSoundsPerSet];
+	Common::Array<Common::Rect> tabCaptionSrcRects;             // 2 entries
+	Common::Rect tabCaptionDestRect;                            // on-screen target
 };
 } // End of namespace Nancy
 


Commit: 1b94ca4b2f1db0c7f0d2a1c9e314ddcea54ab1d2
    https://github.com/scummvm/scummvm/commit/1b94ca4b2f1db0c7f0d2a1c9e314ddcea54ab1d2
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2026-04-28T03:58:49+03:00

Commit Message:
NANCY: Add handling for the Nancy10+ UICL (cell phone) chunk

Changed paths:
    engines/nancy/enginedata.cpp
    engines/nancy/enginedata.h


diff --git a/engines/nancy/enginedata.cpp b/engines/nancy/enginedata.cpp
index 62ac6854540..d7beb0a3a53 100644
--- a/engines/nancy/enginedata.cpp
+++ b/engines/nancy/enginedata.cpp
@@ -919,8 +919,126 @@ UIBW::UIBW(Common::SeekableReadStream *chunkStream) : EngineData(chunkStream) {
 }
 
 UICL::UICL(Common::SeekableReadStream *chunkStream) : EngineData(chunkStream) {
-	readFilename(*chunkStream, imageName);
-	// TODO
+	readUIPopupHeader(*chunkStream, header);
+
+	readFilename(*chunkStream, overlayImageName);
+
+	// Skip shared UIButton template - the sub-fields data is read
+	// separately for each button record below.
+	chunkStream->skip(206);
+
+	for (uint i = 0; i < kNumDialPadSlots; ++i) {
+		readRect(*chunkStream, dialPadSlots[i].srcRect);
+		readRect(*chunkStream, dialPadSlots[i].destRect);
+		char nameBuf[34];
+		chunkStream->read(nameBuf, 33);
+		nameBuf[33] = '\0';
+		dialPadSlots[i].soundName = nameBuf;
+	}
+
+	// Screen-frame and label rects
+	readRect(*chunkStream, dialHilite.srcRect);
+	readRect(*chunkStream, dialHilite.destRect);
+	readRect(*chunkStream, screenOutSrcRect);
+	statusTextX = chunkStream->readSint32LE();
+	statusTextY = chunkStream->readSint32LE();
+	readRect(*chunkStream, welcomeScreen.srcRect);
+	readRect(*chunkStream, welcomeScreen.destRect);
+
+	char labelBuf[21];
+	for (uint i = 0; i < kNumStatusLabels; ++i) {
+		chunkStream->read(labelBuf, 20);
+		labelBuf[20] = '\0';
+		statusLabels[i] = labelBuf;
+	}
+
+	readRect(*chunkStream, dialLabel.srcRect);
+	readRect(*chunkStream, dialLabel.destRect);
+	readRect(*chunkStream, webLabel.srcRect);
+	readRect(*chunkStream, webLabel.destRect);
+	readRect(*chunkStream, dirLabel.srcRect);
+	readRect(*chunkStream, dirLabel.destRect);
+
+	// Call/hang-up widget (3 rects).
+	readRect(*chunkStream, callButton.srcRectIdle);
+	readRect(*chunkStream, callButton.srcRectPressed);
+	readRect(*chunkStream, callButton.destRect);
+
+	// Screen-content sprite block
+	readFilename(*chunkStream, phoneUseSound);
+	readRect(*chunkStream, signalSpriteSrc);
+	readRect(*chunkStream, signalSpriteSrcAlt);
+	readRect(*chunkStream, signalSpriteDest);
+	readRect(*chunkStream, batterySpriteSrc);
+	readRect(*chunkStream, batterySpriteSrcAlt);
+	readRect(*chunkStream, batterySpriteDest);
+	readRect(*chunkStream, typeMessage.srcRect);
+	readRect(*chunkStream, typeMessage.destRect);
+	readRect(*chunkStream, connectedLabel.srcRect);
+	readRect(*chunkStream, connectedLabel.destRect);
+	readRect(*chunkStream, connectingSpriteSrc);
+	readRect(*chunkStream, connectingSpriteSrcAlt);
+	readRect(*chunkStream, connectingSpriteDest);
+	readRect(*chunkStream, onlineHeading.srcRect);
+	readRect(*chunkStream, onlineHeading.destRect);
+	readRect(*chunkStream, fullEmptyScreenSrc);
+	readRect(*chunkStream, emailListContainer);
+	readRect(*chunkStream, dirArrowSrc);
+	readRect(*chunkStream, dirCursorSrc);
+	readRect(*chunkStream, dirHeading.srcRect);
+	readRect(*chunkStream, dirHeading.destRect);
+
+	for (uint i = 0; i < kNumSubButtons; ++i) {
+		readRect(*chunkStream, subButtons[i].srcRectIdle);
+		readRect(*chunkStream, subButtons[i].srcRectPressed);
+		readRect(*chunkStream, subButtons[i].destRect);
+	}
+
+	// Heading/icon rect pairs
+	readRect(*chunkStream, searchHeading.srcRect);
+	readRect(*chunkStream, searchHeading.destRect);
+	readRect(*chunkStream, emailIconUnread);
+	readRect(*chunkStream, emailIconSelected);
+	readRect(*chunkStream, emailHeading.srcRect);
+	readRect(*chunkStream, emailHeading.destRect);
+	readRect(*chunkStream, helpHeading.srcRect);
+	readRect(*chunkStream, helpHeading.destRect);
+	readRect(*chunkStream, browserHeading.srcRect);
+	readRect(*chunkStream, browserHeading.destRect);
+
+	readFilename(*chunkStream, holdMusicSound);
+	readFilename(*chunkStream, answeringMachineSound);
+	holdLink1 = chunkStream->readSint16LE();
+	holdLink2 = chunkStream->readSint16LE();
+	readFilename(*chunkStream, urlSound);
+	urlLink1 = chunkStream->readSint16LE();
+	urlLink2 = chunkStream->readSint16LE();
+	urlLink3 = chunkStream->readSint16LE();
+
+	fontId1 = chunkStream->readUint16LE();
+	fontId2 = chunkStream->readUint16LE();
+
+	readFilename(*chunkStream, outgoingRingSound);
+	readFilename(*chunkStream, pickupSound);
+	readFilename(*chunkStream, invalidNumberSound);
+
+	contactCount = chunkStream->readUint16LE();
+
+	const int64 maxEntries = (chunkStream->size() - chunkStream->pos()) / 41;
+	const uint16 entries = MIN<uint16>(contactCount, (uint16)maxEntries);
+	contacts.resize(entries);
+	for (uint i = 0; i < entries; ++i) {
+		Contact &c = contacts[i];
+
+		chunkStream->read(c.unknownPrefix, sizeof(c.unknownPrefix));
+
+		char nameBuf[21];
+		chunkStream->read(nameBuf, 20);
+		nameBuf[20] = '\0';
+		c.name = nameBuf;
+
+		chunkStream->read(c.unknownSuffix, sizeof(c.unknownSuffix));
+	}
 }
 
 UICO::UICO(Common::SeekableReadStream *chunkStream) : EngineData(chunkStream) {
diff --git a/engines/nancy/enginedata.h b/engines/nancy/enginedata.h
index ace098cebf9..e42db07bcdf 100644
--- a/engines/nancy/enginedata.h
+++ b/engines/nancy/enginedata.h
@@ -556,11 +556,102 @@ struct UIBW : public EngineData {
 	Common::Array<UrlPage> pages;
 };
 
-// New cell phone popup UI. Introduced in Nancy 10
+// Cell-phone popup UI. Introduced in Nancy 10.
 struct UICL : public EngineData {
+	struct DialPadSlot {
+		Common::Rect srcRect;
+		Common::Rect destRect;
+		Common::String soundName;
+	};
+
+	struct ThreeRectWidget {
+		Common::Rect srcRectIdle;
+		Common::Rect srcRectPressed;
+		Common::Rect destRect;
+	};
+
+	struct Contact {
+		byte unknownPrefix[13];   // 13 bytes preceding the name (purpose not yet determined)
+		Common::String name;      // 20-byte null-terminated contact name
+		byte unknownSuffix[8];    // 8 bytes following the name (purpose not yet determined)
+	};
+
+	struct SrcDestRectPair {
+		Common::Rect srcRect;
+		Common::Rect destRect;
+	};
+
+	static const uint kNumDialPadSlots = 15;
+	static const uint kNumSubButtons = 10;
+	static const uint kNumStatusLabels = 3;        // No Signal / No Access / Old Email Only
+
 	UICL(Common::SeekableReadStream *chunkStream);
 
-	Common::Path imageName;
+	UIPopupHeader header;
+	Common::Path overlayImageName;
+	DialPadSlot dialPadSlots[kNumDialPadSlots];
+
+	// Screen-frame and label rects
+	SrcDestRectPair dialHilite;
+	Common::Rect screenOutSrcRect;
+	int32 statusTextX = 0;                    // text X-baseline
+	int32 statusTextY = 0;                    // text Y-baseline
+	SrcDestRectPair welcomeScreen;
+	Common::String statusLabels[kNumStatusLabels]; // "No Signal", "No Access", "Old Email Only"
+	SrcDestRectPair dialLabel;
+	SrcDestRectPair webLabel;
+	SrcDestRectPair dirLabel;
+
+	ThreeRectWidget callButton;
+
+	// Screen-content sprite block
+	Common::Path phoneUseSound;
+	Common::Rect signalSpriteSrc;
+	Common::Rect signalSpriteSrcAlt;
+	Common::Rect signalSpriteDest;
+	Common::Rect batterySpriteSrc;
+	Common::Rect batterySpriteSrcAlt;
+	Common::Rect batterySpriteDest;
+	SrcDestRectPair typeMessage;
+	SrcDestRectPair connectedLabel;
+	Common::Rect connectingSpriteSrc;
+	Common::Rect connectingSpriteSrcAlt;      // state-8 variant
+	Common::Rect connectingSpriteDest;
+	SrcDestRectPair onlineHeading;
+	Common::Rect fullEmptyScreenSrc;
+	Common::Rect emailListContainer;          // scrollbar/list container
+	Common::Rect dirArrowSrc;
+	Common::Rect dirCursorSrc;
+	SrcDestRectPair dirHeading;
+
+	ThreeRectWidget subButtons[kNumSubButtons];
+
+	// Heading/icon SRC+DEST pairs
+	SrcDestRectPair searchHeading;
+	Common::Rect emailIconUnread;
+	Common::Rect emailIconSelected;
+	SrcDestRectPair emailHeading;
+	SrcDestRectPair helpHeading;
+	SrcDestRectPair browserHeading;
+
+	Common::Path holdMusicSound;
+	Common::Path answeringMachineSound;       // chunk+0xCE4 (33B): "SHAMA02"
+	int16 holdLink1 = 0;
+	int16 holdLink2 = 0;
+	Common::Path urlSound;
+	int16 urlLink1 = 0;
+	int16 urlLink2 = 0;
+	int16 urlLink3 = 0;
+
+	uint16 fontId1 = 0;
+	uint16 fontId2 = 0;
+
+	Common::Path outgoingRingSound;           // Process case 2 (post-dial ring)
+	Common::Path pickupSound;                 // Process cases 0/4 (call connect)
+	Common::Path invalidNumberSound;          // Process case 7 (try again)
+
+	uint16 contactCount = 0;
+	Common::Array<Contact> contacts;
 };
 
 // New conversation popup UI (the text strip that appears above the taskbar




More information about the Scummvm-git-logs mailing list