[Scummvm-git-logs] scummvm master -> b174006c5bfa9b4bd2b87eda377ab5b07d9d31b5

fracturehill noreply at scummvm.org
Thu Aug 31 09:56:23 UTC 2023


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

Summary:
c3a5d2523a NANCY: Return to main menu after losing game
24670d9afd NANCY: Remove check for number of action records
03d4791ed2 NANCY: Implement standard way to access boot chunks
35e0946ff7 NANCY: Add support for nancy5's day counter
4cc3e98362 NANCY: Destroy Scene when winning/losing game
aa00471113 NANCY Fix #define name
b174006c5b NANCY: Implement TurningPuzzle


Commit: c3a5d2523a5247d64e903c01103fff5dc79f5f03
    https://github.com/scummvm/scummvm/commit/c3a5d2523a5247d64e903c01103fff5dc79f5f03
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2023-08-31T12:20:38+03:00

Commit Message:
NANCY: Return to main menu after losing game

Changed paths:
    engines/nancy/action/recordtypes.cpp


diff --git a/engines/nancy/action/recordtypes.cpp b/engines/nancy/action/recordtypes.cpp
index 66ede04956f..b02d1b82cea 100644
--- a/engines/nancy/action/recordtypes.cpp
+++ b/engines/nancy/action/recordtypes.cpp
@@ -29,6 +29,7 @@
 #include "engines/nancy/state/scene.h"
 
 #include "common/events.h"
+#include "common/config-manager.h"
 
 namespace Nancy {
 namespace Action {
@@ -470,13 +471,14 @@ void LoseGame::readData(Common::SeekableReadStream &stream) {
 void LoseGame::execute() {
 	g_nancy->_sound->stopAndUnloadSpecificSounds();
 
-	// We're not using original menus yet, so just quit the game and go back to the launcher
-	// g_nancy->setState(NancyState::kMainMenu);
-
-	Common::Event ev;
-	ev.type = Common::EVENT_RETURN_TO_LAUNCHER;
-	g_system->getEventManager()->pushEvent(ev);
-
+	if (!ConfMan.hasKey("original_menus") || ConfMan.getBool("original_menus")) {
+		g_nancy->setState(NancyState::kMainMenu);
+	} else {
+		Common::Event ev;
+		ev.type = Common::EVENT_RETURN_TO_LAUNCHER;
+		g_system->getEventManager()->pushEvent(ev);
+	}
+	
 	_isDone = true;
 }
 


Commit: 24670d9afd474fb9e173edff5cb9e4b857bf753c
    https://github.com/scummvm/scummvm/commit/24670d9afd474fb9e173edff5cb9e4b857bf753c
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2023-08-31T12:20:39+03:00

Commit Message:
NANCY: Remove check for number of action records

There is at least one scene in nancy5 with more than 30
records. The check is pretty much useless anyway, since
we have a variable-size array of records while the original
engine didn't, so it has simply been removed.

Changed paths:
    engines/nancy/state/scene.cpp


diff --git a/engines/nancy/state/scene.cpp b/engines/nancy/state/scene.cpp
index 1938f45e913..5a11d7322b5 100644
--- a/engines/nancy/state/scene.cpp
+++ b/engines/nancy/state/scene.cpp
@@ -682,10 +682,6 @@ void Scene::load() {
 	Common::SeekableReadStream *actionRecordChunk = nullptr;
 
 	while (actionRecordChunk = sceneIFF.getChunkStream("ACT", _actionManager._records.size()), actionRecordChunk != nullptr) {
-		if (_actionManager._records.size() >= 30) {
-			error("Invalid number of Action Records");
-		}
-
 		_actionManager.addNewActionRecord(*actionRecordChunk);
 		delete actionRecordChunk;
 	}


Commit: 03d4791ed26fdb7457e47ceb33c15178d191b737
    https://github.com/scummvm/scummvm/commit/03d4791ed26fdb7457e47ceb33c15178d191b737
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2023-08-31T12:20:39+03:00

Commit Message:
NANCY: Implement standard way to access boot chunks

Previously, the NancyEngine class was responsible for
handling creation and destruction of many naked pointers
to engine data, which led to several instances of memory
leaks that needed to be fixed. These changes introduce a
standard way of handling that same data, similar to the
one already used by PuzzleData inside Scene. Unfortunately,
this does add the need for relevant data to be casted to
the proper type before it is handled.

Changed paths:
    engines/nancy/action/actionmanager.cpp
    engines/nancy/action/raycastpuzzle.cpp
    engines/nancy/action/raycastpuzzle.h
    engines/nancy/action/recordtypes.cpp
    engines/nancy/action/sliderpuzzle.cpp
    engines/nancy/action/sliderpuzzle.h
    engines/nancy/action/soundequalizerpuzzle.cpp
    engines/nancy/console.cpp
    engines/nancy/cursor.cpp
    engines/nancy/enginedata.cpp
    engines/nancy/enginedata.h
    engines/nancy/graphics.cpp
    engines/nancy/misc/specialeffect.cpp
    engines/nancy/misc/specialeffect.h
    engines/nancy/nancy.cpp
    engines/nancy/nancy.h
    engines/nancy/state/credits.cpp
    engines/nancy/state/credits.h
    engines/nancy/state/help.cpp
    engines/nancy/state/loadsave.cpp
    engines/nancy/state/loadsave.h
    engines/nancy/state/logo.cpp
    engines/nancy/state/mainmenu.cpp
    engines/nancy/state/mainmenu.h
    engines/nancy/state/map.cpp
    engines/nancy/state/map.h
    engines/nancy/state/savedialog.cpp
    engines/nancy/state/savedialog.h
    engines/nancy/state/scene.cpp
    engines/nancy/state/setupmenu.cpp
    engines/nancy/state/setupmenu.h
    engines/nancy/ui/button.cpp
    engines/nancy/ui/button.h
    engines/nancy/ui/clock.cpp
    engines/nancy/ui/clock.h
    engines/nancy/ui/inventorybox.cpp
    engines/nancy/ui/ornaments.cpp
    engines/nancy/ui/textbox.cpp
    engines/nancy/ui/viewport.cpp


diff --git a/engines/nancy/action/actionmanager.cpp b/engines/nancy/action/actionmanager.cpp
index 8111e6e5acf..2d0b30cc541 100644
--- a/engines/nancy/action/actionmanager.cpp
+++ b/engines/nancy/action/actionmanager.cpp
@@ -61,7 +61,10 @@ void ActionManager::handleInput(NancyInput &input) {
 
 				if (!rec->_dependencies.satisfied) {
 					if (g_nancy->getGameType() >= kGameTypeNancy2 && rec->_cursorDependency != nullptr) {
-						SoundDescription &sound = g_nancy->_inventoryData->itemDescriptions[rec->_cursorDependency->label].specificCantSound;
+						const INV *inventoryData = (const INV *)g_nancy->getEngineData("INV");
+						assert(inventoryData);
+
+						const SoundDescription &sound = inventoryData->itemDescriptions[rec->_cursorDependency->label].specificCantSound;
 						g_nancy->_sound->loadSound(sound);
 						g_nancy->_sound->playSound(sound);
 					} else {
@@ -78,7 +81,10 @@ void ActionManager::handleInput(NancyInput &input) {
 
 						// Re-add the object to the inventory unless it's marked as a one-time use
 						if (item == NancySceneState.getHeldItem() && item != -1) {
-							switch (g_nancy->_inventoryData->itemDescriptions[item].keepItem) {
+							const INV *inventoryData = (const INV *)g_nancy->getEngineData("INV");
+							assert(inventoryData);
+
+							switch (inventoryData->itemDescriptions[item].keepItem) {
 							case kInvItemKeepAlways :
 								if (g_nancy->getGameType() >= kGameTypeNancy3) {
 									// In nancy3 and up this means the object remains in hand, so do nothing
diff --git a/engines/nancy/action/raycastpuzzle.cpp b/engines/nancy/action/raycastpuzzle.cpp
index 6bd9597570e..8700ddd97ff 100644
--- a/engines/nancy/action/raycastpuzzle.cpp
+++ b/engines/nancy/action/raycastpuzzle.cpp
@@ -103,12 +103,11 @@ public:
 	Common::Array<uint16> _cells;
 	Common::Array<byte> _walls;
 
-	RCLB *_themeData;
+	const RCLB *_themeData;
 };
 
 RaycastLevelBuilder::RaycastLevelBuilder(uint width, uint height, uint verticalHeight) {
-	_themeData = g_nancy->_raycastPuzzleLevelBuilderData;
-
+	_themeData = (const RCLB *)g_nancy->getEngineData("RCLB");
 	assert(_themeData);
 
 	_verticalHeight = verticalHeight;
@@ -290,7 +289,7 @@ void RaycastLevelBuilder::writeThemesAndExitFloor() {
 
 uint RaycastLevelBuilder::writeTheme(uint startX, uint startY, uint quadrant) {
 	uint themeID = g_nancy->_randomSource->getRandomNumber(_themeData->themes.size() - 1);
-	RCLB::Theme &theme = _themeData->themes[themeID];
+	const RCLB::Theme &theme = _themeData->themes[themeID];
 
 	uint themeHalfWidth, themeHalfHeight;
 
@@ -347,7 +346,7 @@ uint RaycastLevelBuilder::writeTheme(uint startX, uint startY, uint quadrant) {
 }
 
 void RaycastLevelBuilder::writeTransparentWalls(uint startX, uint startY, uint themeID) {
-	RCLB::Theme &theme = _themeData->themes[themeID];
+	const RCLB::Theme &theme = _themeData->themes[themeID];
 	uint numWallsToWrite = (int)((float)theme.objectWallDensity * _objectsBaseDensity);
 
 	for (uint numWrittenWalls = 0; numWrittenWalls < numWallsToWrite;) {
@@ -453,7 +452,7 @@ void RaycastLevelBuilder::writeTransparentWalls(uint startX, uint startY, uint t
 }
 
 void RaycastLevelBuilder::writeObjectWalls(uint startX, uint startY, uint themeID) {
-	RCLB::Theme &theme = _themeData->themes[themeID];
+	const RCLB::Theme &theme = _themeData->themes[themeID];
 	uint numWallsToWrite = (int)((float)theme.objectWallDensity * _objectsBaseDensity);
 
 	uint textureVerticalHeight = _verticalHeight * 128; // 128 is a constant inside RayCast
@@ -578,7 +577,7 @@ void RaycastLevelBuilder::writeObjectWalls(uint startX, uint startY, uint themeI
 }
 
 void RaycastLevelBuilder::writeDoors(uint startX, uint startY, uint themeID) {
-	RCLB::Theme &theme = _themeData->themes[themeID];
+	const RCLB::Theme &theme = _themeData->themes[themeID];
 	uint numDoorsToWrite = (int)((float)theme.doorDensity * _objectsBaseDensity);
 
 	for (uint numWrittenWalls = 0; numWrittenWalls < numDoorsToWrite;) {
@@ -816,7 +815,7 @@ void RaycastLevelBuilder::writeLightSwitch(uint startX, uint startY, uint quadra
 }
 
 void RaycastLevelBuilder::writeExitFloorTexture(uint themeID) {
-	RCLB::Theme &theme = _themeData->themes[themeID];
+	const RCLB::Theme &theme = _themeData->themes[themeID];
 	int16 selectedFloorID = theme.exitFloorIDs[g_nancy->_randomSource->getRandomNumber(theme.exitFloorIDs.size() - 1)];
 	uint addToID = 0;
 
@@ -891,7 +890,10 @@ private:
 bool RaycastDeferredLoader::loadInner() {
 	switch(_loadState) {
 	case kInitDrawSurface : {
-		Common::Rect viewport = g_nancy->_viewportData->bounds;
+		const VIEW *viewportData = (const VIEW *)g_nancy->getEngineData("VIEW");
+		assert(viewportData);
+		
+		Common::Rect viewport = viewportData->bounds;
 		_owner.moveTo(viewport);
 		_owner._drawSurface.create(viewport.width(), viewport.height(), g_nancy->_graphicsManager->getInputPixelFormat());
 		_owner.setTransparent(true);
@@ -915,8 +917,11 @@ bool RaycastDeferredLoader::loadInner() {
 	case kInitMap : {
 		// TODO map is a debug feature, make sure to hide it
 		// Also, fix the fact that it's rendered upside-down
+		const BSUM *bootSummary = (const BSUM *)g_nancy->getEngineData("BSUM");
+		assert(bootSummary);
+
 		_owner._map._drawSurface.create(_owner._mapFullWidth, _owner._mapFullHeight, g_nancy->_graphicsManager->getInputPixelFormat());
-		Common::Rect mapPos(g_nancy->_bootSummary->textboxScreenPosition);
+		Common::Rect mapPos(bootSummary->textboxScreenPosition);
 		mapPos.setWidth(_owner._mapFullWidth * 2);
 		mapPos.setHeight(_owner._mapFullHeight * 2);
 		_owner._map.moveTo(mapPos);
@@ -928,8 +933,10 @@ bool RaycastDeferredLoader::loadInner() {
 	}
 	case kInitTables1 : {
 		Common::Rect selectedBounds = _owner._puzzleData->screenViewportSizes[_owner._puzzleData->viewportSizeUsed];
+		const VIEW *viewportData = (const VIEW *)g_nancy->getEngineData("VIEW");
+		assert(viewportData);
 
-		_owner._wallCastColumnAngles.resize(g_nancy->_viewportData->screenPosition.width());
+		_owner._wallCastColumnAngles.resize(viewportData->screenPosition.width());
 		uint center = selectedBounds.left + (selectedBounds.width() >> 1);
 		for (uint i = 0; i < _owner._wallCastColumnAngles.size(); ++i) {
 			int32 &angle = _owner._wallCastColumnAngles[i];
@@ -944,6 +951,9 @@ bool RaycastDeferredLoader::loadInner() {
 		break;
 	}
 	case kInitTables2 : {
+		const VIEW *viewportData = (const VIEW *)g_nancy->getEngineData("VIEW");
+		assert(viewportData);
+
 		_owner._sinTable.resize(4096);
 		_owner._cosTable.resize(4096);
 
@@ -954,8 +964,8 @@ bool RaycastDeferredLoader::loadInner() {
 		}
 
 		_owner._maxWorldDistance = sqrt(((128 * _owner._mapFullWidth) - 1) * ((128 * _owner._mapFullHeight) - 1) * 2);
-		_owner._depthBuffer.resize(g_nancy->_viewportData->bounds.width());
-		_owner._zBuffer.resize(g_nancy->_viewportData->bounds.width() * g_nancy->_viewportData->bounds.height(), 0);
+		_owner._depthBuffer.resize(viewportData->bounds.width());
+		_owner._zBuffer.resize(viewportData->bounds.width() * viewportData->bounds.height(), 0);
 		_owner._lastZDepth = 0;
 
 		_loadState = kLoadTextures;
@@ -1037,7 +1047,7 @@ bool RaycastDeferredLoader::loadInner() {
 }
 
 void RaycastPuzzle::init() {
-	_puzzleData = g_nancy->_raycastPuzzleData;
+	_puzzleData = (const RCPR *)g_nancy->getEngineData("RCPR");
 	assert(_puzzleData);
 
 	RaycastDeferredLoader *loader = _loaderPtr.get();
@@ -1361,7 +1371,7 @@ void RaycastPuzzle::loadTextures() {
 	
 }
 
-void RaycastPuzzle::createTextureLightSourcing(Common::Array<Graphics::ManagedSurface> *array, Common::String &textureName) {
+void RaycastPuzzle::createTextureLightSourcing(Common::Array<Graphics::ManagedSurface> *array, const Common::String &textureName) {
 	Graphics::PixelFormat format = g_nancy->_graphicsManager->getInputPixelFormat();
 	array->resize(8);
 
diff --git a/engines/nancy/action/raycastpuzzle.h b/engines/nancy/action/raycastpuzzle.h
index a8e35733f30..6b6af1ccdba 100644
--- a/engines/nancy/action/raycastpuzzle.h
+++ b/engines/nancy/action/raycastpuzzle.h
@@ -54,7 +54,7 @@ protected:
 	bool isViewportRelative() const override { return true; }
 
 	void loadTextures();
-	void createTextureLightSourcing(Common::Array<Graphics::ManagedSurface> *array, Common::String &textureName);
+	void createTextureLightSourcing(Common::Array<Graphics::ManagedSurface> *array, const Common::String &textureName);
 
 	void drawMap();
 	void drawMaze();
@@ -117,7 +117,7 @@ protected:
 	int32 _slowdownDeltaX = -1;
 	int32 _slowdownDeltaY = -1;
 
-	RCPR *_puzzleData = nullptr;
+	const RCPR *_puzzleData = nullptr;
 	Common::SharedPtr<RaycastDeferredLoader> _loaderPtr;
 };
 
diff --git a/engines/nancy/action/recordtypes.cpp b/engines/nancy/action/recordtypes.cpp
index b02d1b82cea..c79c3092617 100644
--- a/engines/nancy/action/recordtypes.cpp
+++ b/engines/nancy/action/recordtypes.cpp
@@ -352,7 +352,8 @@ void TextBoxWrite::readData(Common::SeekableReadStream &stream) {
 void TextBoxWrite::execute() {
 	auto &tb = NancySceneState.getTextbox();
 	tb.clear();
-	tb.overrideFontID(g_nancy->_textboxData->defaultFontID);
+	const TBOX *textboxData = (const TBOX *)g_nancy->getEngineData("TBOX");
+	tb.overrideFontID(textboxData->defaultFontID);
 	tb.addTextLine(_text);
 	tb.setVisible(true);
 	finishExecution();
@@ -478,7 +479,7 @@ void LoseGame::execute() {
 		ev.type = Common::EVENT_RETURN_TO_LAUNCHER;
 		g_system->getEventManager()->pushEvent(ev);
 	}
-	
+
 	_isDone = true;
 }
 
diff --git a/engines/nancy/action/sliderpuzzle.cpp b/engines/nancy/action/sliderpuzzle.cpp
index 5dc9a70e076..49845bd637b 100644
--- a/engines/nancy/action/sliderpuzzle.cpp
+++ b/engines/nancy/action/sliderpuzzle.cpp
@@ -44,7 +44,7 @@ void SliderPuzzle::init() {
 }
 
 void SliderPuzzle::readData(Common::SeekableReadStream &stream) {
-	_spuzData = g_nancy->_sliderPuzzleData;
+	_spuzData = (const SPUZ*)g_nancy->getEngineData("SPUZ");
 	assert(_spuzData);
 
 	_puzzleState = (SliderPuzzleData *)NancySceneState.getPuzzleData(SliderPuzzleData::getTag());
diff --git a/engines/nancy/action/sliderpuzzle.h b/engines/nancy/action/sliderpuzzle.h
index c71242b0910..b062f22701f 100644
--- a/engines/nancy/action/sliderpuzzle.h
+++ b/engines/nancy/action/sliderpuzzle.h
@@ -43,7 +43,7 @@ public:
 	void execute() override;
 	void handleInput(NancyInput &input) override;
 
-	SPUZ *_spuzData = nullptr;
+	const SPUZ *_spuzData = nullptr;
 	SliderPuzzleData *_puzzleState = nullptr;
 
 	Common::String _imageName;
diff --git a/engines/nancy/action/soundequalizerpuzzle.cpp b/engines/nancy/action/soundequalizerpuzzle.cpp
index 67e01fa5c17..d58cb0c456e 100644
--- a/engines/nancy/action/soundequalizerpuzzle.cpp
+++ b/engines/nancy/action/soundequalizerpuzzle.cpp
@@ -71,7 +71,8 @@ void SoundEqualizerPuzzle::init() {
 	g_nancy->_resource->loadImage(_imageName, _image);
 	_image.setTransparentColor(_drawSurface.getTransparentColor());
 
-	Common::Rect vpPos = g_nancy->_viewportData->screenPosition;
+	const VIEW *viewportData = (const VIEW *)g_nancy->getEngineData("VIEW");
+	Common::Rect vpPos = viewportData->screenPosition;
 
 	if (_puzzleState->sliderValues[0] == 255) {
 		for (uint i = 0; i < 6; ++i) {
diff --git a/engines/nancy/console.cpp b/engines/nancy/console.cpp
index 273c92ee699..04cc94315e0 100644
--- a/engines/nancy/console.cpp
+++ b/engines/nancy/console.cpp
@@ -462,6 +462,9 @@ bool NancyConsole::Cmd_sceneID(int argc, const char **argv) {
 void NancyConsole::recurseDependencies(const Nancy::Action::DependencyRecord &record) {
 	using namespace Nancy::Action;
 
+	const INV *inventoryData = (const INV *)g_nancy->getEngineData("INV");
+	assert(inventoryData);
+
 	for (const DependencyRecord &dep : record.children) {
 		debugPrintf("\n\t\t");
 		switch (dep.type) {
@@ -471,7 +474,7 @@ void NancyConsole::recurseDependencies(const Nancy::Action::DependencyRecord &re
 		case DependencyType::kInventory :
 			debugPrintf("kInventory, item %u, %s, %s",
 				dep.label,
-				g_nancy->_inventoryData->itemDescriptions[dep.label].name.c_str(),
+				inventoryData->itemDescriptions[dep.label].name.c_str(),
 				dep.condition == g_nancy->_true ? "true" : "false");
 			break;
 		case DependencyType::kEvent :
@@ -518,7 +521,7 @@ void NancyConsole::recurseDependencies(const Nancy::Action::DependencyRecord &re
 		case DependencyType::kCursorType :
 			debugPrintf("kCursorType, item %u, %s, %s",
 				dep.label,
-				g_nancy->_inventoryData->itemDescriptions[dep.label].name.c_str(),
+				inventoryData->itemDescriptions[dep.label].name.c_str(),
 				dep.condition == ActionManager::kCursInvHolding ? "kCursInvHolding" : "kCursInvNotHolding");
 			break;
 		case DependencyType::kPlayerTOD :
@@ -754,21 +757,23 @@ bool NancyConsole::Cmd_getInventory(int argc, const char **argv) {
 	}
 
 	uint numItems = g_nancy->getStaticData().numItems;
+	const INV *inventoryData = (const INV *)g_nancy->getEngineData("INV");
+	assert(inventoryData);
 
 	debugPrintf("Total number of inventory items: %u\n", numItems);
 
 	if (argc == 1) {
 		for (uint i = 0; i < numItems; ++i) {
-			byte keep = g_nancy->_inventoryData->itemDescriptions[i].keepItem;
+			byte keep = inventoryData->itemDescriptions[i].keepItem;
 			debugPrintf("\nItem %u, %s, %s, %s",
 				i,
-				g_nancy->_inventoryData->itemDescriptions[i].name.c_str(),
+				inventoryData->itemDescriptions[i].name.c_str(),
 				keep == 0 ? "UseThenLose" : keep == 1 ? "KeepAlways" : "ReturnToInventory",
 				NancySceneState.hasItem(i) == g_nancy->_true ? "true" : "false");
 		}
 	} else {
 		for (int i = 1; i < argc; ++i) {
-			byte keep = g_nancy->_inventoryData->itemDescriptions[i].keepItem;
+			byte keep = inventoryData->itemDescriptions[i].keepItem;
 			int flagID = atoi(argv[i]);
 			if (flagID < 0 || flagID >= (int)numItems) {
 				debugPrintf("\nInvalid flag %s", argv[i]);
@@ -776,7 +781,7 @@ bool NancyConsole::Cmd_getInventory(int argc, const char **argv) {
 			}
 			debugPrintf("\nItem %u, %s, %s, %s",
 				flagID,
-				g_nancy->_inventoryData->itemDescriptions[flagID].name.c_str(),
+				inventoryData->itemDescriptions[flagID].name.c_str(),
 				keep == 0 ? "UseThenLose" : keep == 1 ? "KeepAlways" : "ReturnToInventory",
 				NancySceneState.hasItem(i) == g_nancy->_true ? "true" : "false");
 
@@ -789,6 +794,9 @@ bool NancyConsole::Cmd_getInventory(int argc, const char **argv) {
 }
 
 bool NancyConsole::Cmd_setInventory(int argc, const char **argv) {
+	const INV *inventoryData = (const INV *)g_nancy->getEngineData("INV");
+	assert(inventoryData);
+	
 	if (g_nancy->_gameFlow.curState != NancyState::kScene) {
 		debugPrintf("Not in the kScene state\n");
 		return true;
@@ -811,12 +819,12 @@ bool NancyConsole::Cmd_setInventory(int argc, const char **argv) {
 			NancySceneState.addItemToInventory(itemID);
 			debugPrintf("Added item %i, %s, to inventory\n",
 				itemID,
-				g_nancy->_inventoryData->itemDescriptions[itemID].name.c_str());
+				inventoryData->itemDescriptions[itemID].name.c_str());
 		} else if (Common::String(argv[i + 1]).compareTo("false") == 0) {
 			NancySceneState.removeItemFromInventory(itemID, false);
 			debugPrintf("Removed item %i, %s, from inventory\n",
 				itemID,
-				g_nancy->_inventoryData->itemDescriptions[itemID].name.c_str());
+				inventoryData->itemDescriptions[itemID].name.c_str());
 		} else {
 			debugPrintf("Invalid value %s\n", argv[i + 1]);
 			continue;
diff --git a/engines/nancy/cursor.cpp b/engines/nancy/cursor.cpp
index 15225a2eeeb..adc3acf3b1a 100644
--- a/engines/nancy/cursor.cpp
+++ b/engines/nancy/cursor.cpp
@@ -66,7 +66,10 @@ void CursorManager::init(Common::SeekableReadStream *chunkStream) {
 	_primaryVideoInitialPos.x = chunkStream->readUint16LE();
 	_primaryVideoInitialPos.y = chunkStream->readUint16LE();
 
-	g_nancy->_resource->loadImage(g_nancy->_inventoryData->inventoryCursorsImageName, _invCursorsSurface);
+	const INV *inventoryData = (const INV *)g_nancy->getEngineData("INV");
+	assert(inventoryData);
+
+	g_nancy->_resource->loadImage(inventoryData->inventoryCursorsImageName, _invCursorsSurface);
 
 	setCursor(kNormalArrow, -1);
 	showCursor(false);
diff --git a/engines/nancy/enginedata.cpp b/engines/nancy/enginedata.cpp
index f732964bb60..7ff11c2afc8 100644
--- a/engines/nancy/enginedata.cpp
+++ b/engines/nancy/enginedata.cpp
@@ -27,10 +27,13 @@
 
 namespace Nancy {
 
-BSUM::BSUM(Common::SeekableReadStream *chunkStream) {
+EngineData::EngineData(Common::SeekableReadStream *chunkStream) {
 	assert(chunkStream);
-
 	chunkStream->seek(0);
+}
+
+BSUM::BSUM(Common::SeekableReadStream *chunkStream) : EngineData(chunkStream) {
+	
 	Common::Serializer s(chunkStream, nullptr);
 	s.setVersion(g_nancy->getGameType());
 
@@ -79,25 +82,15 @@ BSUM::BSUM(Common::SeekableReadStream *chunkStream) {
 	s.syncAsByte(overrideMovementTimeDeltas);
 	s.syncAsSint16LE(slowMovementTimeDelta);
 	s.syncAsSint16LE(fastMovementTimeDelta);
-
-	delete chunkStream;
 }
 
-VIEW::VIEW(Common::SeekableReadStream *chunkStream) {
-	assert(chunkStream);
-
-	chunkStream->seek(0);
+VIEW::VIEW(Common::SeekableReadStream *chunkStream) : EngineData(chunkStream) {
 	readRect(*chunkStream, screenPosition);
 	readRect(*chunkStream, bounds);
-
-	delete chunkStream;
 }
 
-INV::INV(Common::SeekableReadStream *chunkStream) {
-	assert(chunkStream);
-
-	chunkStream->seek(0);
-	Common::Serializer s(chunkStream, nullptr);
+INV::INV(Common::SeekableReadStream *chunkStream) : EngineData(chunkStream) {
+		Common::Serializer s(chunkStream, nullptr);
 	s.setVersion(g_nancy->getGameType());
 
 	readRect(*chunkStream, scrollbarSrcBounds);
@@ -181,11 +174,9 @@ INV::INV(Common::SeekableReadStream *chunkStream) {
 			item.specificCantSound.readNormal(*chunkStream);
 		}
 	}
-
-	delete chunkStream;
 }
 
-TBOX::TBOX(Common::SeekableReadStream *chunkStream) {
+TBOX::TBOX(Common::SeekableReadStream *chunkStream) : EngineData(chunkStream) {
 	assert(chunkStream);
 
 	bool isVampire = g_nancy->getGameType() == Nancy::GameType::kGameTypeVampire;
@@ -230,14 +221,9 @@ TBOX::TBOX(Common::SeekableReadStream *chunkStream) {
 		conversationFontID = defaultFontID;
 		highlightConversationFontID = defaultFontID;
 	}
-
-	delete chunkStream;
 }
 
-MAP::MAP(Common::SeekableReadStream *chunkStream) {
-	assert(chunkStream);
-
-	chunkStream->seek(0);
+MAP::MAP(Common::SeekableReadStream *chunkStream) : EngineData(chunkStream) {
 	Common::Serializer s(chunkStream, nullptr);
 	s.setVersion(g_nancy->getGameType());
 	uint numLocations = s.getVersion() == kGameTypeVampire ? 7 : 4;
@@ -301,14 +287,9 @@ MAP::MAP(Common::SeekableReadStream *chunkStream) {
 			s.syncAsUint16LE(sc.paletteID, kGameTypeVampire, kGameTypeVampire);
 		}
 	}
-
-	delete chunkStream;
 }
 
-HELP::HELP(Common::SeekableReadStream *chunkStream) {
-	assert(chunkStream);
-
-	chunkStream->seek(0);
+HELP::HELP(Common::SeekableReadStream *chunkStream) : EngineData(chunkStream) {
 	readFilename(*chunkStream, imageName);
 	chunkStream->skip(20);
 
@@ -326,11 +307,9 @@ HELP::HELP(Common::SeekableReadStream *chunkStream) {
 		readRect(*chunkStream, buttonSrc);
 		readRect(*chunkStream, buttonHoverSrc);
 	}
-
-	delete chunkStream;
 }
 
-CRED::CRED(Common::SeekableReadStream *chunkStream) {
+CRED::CRED(Common::SeekableReadStream *chunkStream) : EngineData(chunkStream) {
 	assert(chunkStream);
 
 	bool isVampire = g_nancy->getGameType() == kGameTypeVampire;
@@ -350,14 +329,9 @@ CRED::CRED(Common::SeekableReadStream *chunkStream) {
 	updateTime = chunkStream->readUint16LE();
 	pixelsToScroll = chunkStream->readUint16LE();
 	sound.readMenu(*chunkStream);
-
-	delete chunkStream;
 }
 
-MENU::MENU(Common::SeekableReadStream *chunkStream) {
-	assert(chunkStream);
-
-	chunkStream->seek(0);
+MENU::MENU(Common::SeekableReadStream *chunkStream) : EngineData(chunkStream) {
 	readFilename(*chunkStream, _imageName);
 	chunkStream->skip(22);
 
@@ -390,14 +364,9 @@ MENU::MENU(Common::SeekableReadStream *chunkStream) {
 		readRectArray(*chunkStream, _buttonDisabledSrcs, numOptions);
 		readRectArray(*chunkStream, _buttonHighlightSrcs, numOptions);
 	}
-
-	delete chunkStream;
 }
 
-SET::SET(Common::SeekableReadStream *chunkStream) {
-	assert(chunkStream);
-
-	chunkStream->seek(0);
+SET::SET(Common::SeekableReadStream *chunkStream) : EngineData(chunkStream) {
 	readFilename(*chunkStream, _imageName);
 	chunkStream->skip(20); // image info
 	chunkStream->skip(16); // bounds for all scrollbars
@@ -427,17 +396,13 @@ SET::SET(Common::SeekableReadStream *chunkStream) {
 	for (uint i = 0; i < 3; ++i) {
 		_sounds[i].readMenu(*chunkStream);
 	}
-
-	delete chunkStream;
 }
 
 LOAD::LOAD(Common::SeekableReadStream *chunkStream) :
+		EngineData(chunkStream),
 		_highlightFontID(-1),
 		_disabledFontID(-1),
 		_blinkingTimeDelay(0) {
-	assert(chunkStream);
-
-	chunkStream->seek(0);
 	Common::Serializer s(chunkStream, nullptr);
 	s.setVersion(g_nancy->getGameType());
 
@@ -497,14 +462,9 @@ LOAD::LOAD(Common::SeekableReadStream *chunkStream) :
 		readFilename(s, _gameSavedPopup, kGameTypeNancy3);
 		s.skip(16, kGameTypeNancy3);
 	}
-
-	delete chunkStream;
 }
 
-SDLG::SDLG(Common::SeekableReadStream *chunkStream) {
-	assert(chunkStream);
-
-	chunkStream->seek(0);
+SDLG::SDLG(Common::SeekableReadStream *chunkStream) : EngineData(chunkStream) {
 	readFilename(*chunkStream, _imageName);
 	chunkStream->skip(16);
 
@@ -521,27 +481,17 @@ SDLG::SDLG(Common::SeekableReadStream *chunkStream) {
 	readRect(*chunkStream, _yesDownSrc);
 	readRect(*chunkStream, _noDownSrc);
 	readRect(*chunkStream, _cancelDownSrc);
-
-	delete chunkStream;
 }
 
-HINT::HINT(Common::SeekableReadStream *chunkStream) {
-	assert(chunkStream);
-
-	chunkStream->seek(0);
+HINT::HINT(Common::SeekableReadStream *chunkStream) : EngineData(chunkStream) {
 	uint size = chunkStream->size();
 	numHints.resize(size);
 	for (uint i = 0; i < size; ++i) {
 		numHints[i] = chunkStream->readByte();
 	}
-
-	delete chunkStream;
 }
 
-SPUZ::SPUZ(Common::SeekableReadStream *chunkStream) {
-	assert(chunkStream);
-
-	chunkStream->seek(0);
+SPUZ::SPUZ(Common::SeekableReadStream *chunkStream) : EngineData(chunkStream) {
 	tileOrder.resize(3);
 
 	for (uint i = 0; i < 3; ++i) {
@@ -550,14 +500,9 @@ SPUZ::SPUZ(Common::SeekableReadStream *chunkStream) {
 			tileOrder[i][j] = chunkStream->readSint16LE();
 		}
 	}
-
-	delete chunkStream;
 }
 
-CLOK::CLOK(Common::SeekableReadStream *chunkStream) {
-	assert(chunkStream);
-
-	chunkStream->seek(0);
+CLOK::CLOK(Common::SeekableReadStream *chunkStream) : EngineData(chunkStream) {
 	Common::Serializer s(chunkStream, nullptr);
 	s.setVersion(g_nancy->getGameType());
 
@@ -585,11 +530,9 @@ CLOK::CLOK(Common::SeekableReadStream *chunkStream) {
 
 	s.syncAsUint32LE(timeToKeepOpen);
 	s.syncAsUint16LE(frameTime);
-
-	delete chunkStream;
 }
 
-SPEC::SPEC(Common::SeekableReadStream *chunkStream) {
+SPEC::SPEC(Common::SeekableReadStream *chunkStream) : EngineData(chunkStream) {
 	assert(chunkStream);
 
 	chunkStream->seek(0);
@@ -599,7 +542,7 @@ SPEC::SPEC(Common::SeekableReadStream *chunkStream) {
 	crossDissolveNumFrames = chunkStream->readUint16LE();
 }
 
-RCLB::RCLB(Common::SeekableReadStream *chunkStream) {
+RCLB::RCLB(Common::SeekableReadStream *chunkStream) : EngineData(chunkStream) {
 	assert(chunkStream);
 
 	chunkStream->seek(0);
@@ -680,7 +623,7 @@ RCLB::RCLB(Common::SeekableReadStream *chunkStream) {
 	}
 }
 
-RCPR::RCPR(Common::SeekableReadStream *chunkStream) {
+RCPR::RCPR(Common::SeekableReadStream *chunkStream) : EngineData(chunkStream) {
 	assert(chunkStream);
 
 	chunkStream->seek(0);
@@ -743,15 +686,10 @@ RCPR::RCPR(Common::SeekableReadStream *chunkStream) {
 	}
 }
 
-ImageChunk::ImageChunk(Common::SeekableReadStream *chunkStream) {
-	assert(chunkStream);
-
-	chunkStream->seek(0);
+ImageChunk::ImageChunk(Common::SeekableReadStream *chunkStream) : EngineData(chunkStream) {
 	readFilename(*chunkStream, imageName);
 	width = chunkStream->readUint16LE();
 	height = chunkStream->readUint16LE();
-
-	delete chunkStream;
 }
 
 } // End of namespace Nancy
diff --git a/engines/nancy/enginedata.h b/engines/nancy/enginedata.h
index ca2c28c9f51..1467837855c 100644
--- a/engines/nancy/enginedata.h
+++ b/engines/nancy/enginedata.h
@@ -28,7 +28,12 @@ namespace Nancy {
 
 // Data types corresponding to chunks found inside BOOT
 
-struct BSUM {
+struct EngineData {
+	EngineData(Common::SeekableReadStream *chunkStream);
+	virtual ~EngineData() {}
+};
+
+struct BSUM : public EngineData {
 	BSUM(Common::SeekableReadStream *chunkStream);
 
 	byte header[90];
@@ -61,14 +66,14 @@ struct BSUM {
 	uint16 fastMovementTimeDelta;
 };
 
-struct VIEW {
+struct VIEW : public EngineData {
 	VIEW(Common::SeekableReadStream *chunkStream);
 
 	Common::Rect screenPosition;
 	Common::Rect bounds;
 };
 
-struct INV {
+struct INV : public EngineData {
 	struct ItemDescription {
 		Common::String name;
 		byte keepItem;
@@ -103,7 +108,7 @@ struct INV {
 	Common::Array<ItemDescription> itemDescriptions;
 };
 
-struct TBOX {
+struct TBOX : public EngineData {
 	TBOX(Common::SeekableReadStream *chunkStream);
 
 	Common::Rect scrollbarSrcBounds;
@@ -124,7 +129,7 @@ struct TBOX {
 	uint16 highlightConversationFontID;
 };
 
-struct MAP {
+struct MAP : public EngineData {
 	struct Location {
 		Common::String description;
 		Common::Rect hotspot;
@@ -157,7 +162,7 @@ struct MAP {
 	Common::Point cursorPosition;
 };
 
-struct HELP {
+struct HELP : public EngineData {
 	HELP(Common::SeekableReadStream *chunkStream);
 
 	Common::String imageName;
@@ -166,7 +171,7 @@ struct HELP {
 	Common::Rect buttonHoverSrc;
 };
 
-struct CRED {
+struct CRED : public EngineData {
 	CRED(Common::SeekableReadStream *chunkStream);
 
 	Common::String imageName;
@@ -177,7 +182,7 @@ struct CRED {
 	SoundDescription sound;
 };
 
-struct MENU {
+struct MENU : public EngineData {
 	MENU(Common::SeekableReadStream *chunkStream);
 
 	Common::String _imageName;
@@ -187,7 +192,7 @@ struct MENU {
 	Common::Array<Common::Rect> _buttonDisabledSrcs;
 };
 
-struct SET {
+struct SET : public EngineData {
 	SET(Common::SeekableReadStream *chunkStream);
 
 	Common::String _imageName;
@@ -205,7 +210,7 @@ struct SET {
 	Common::Array<SoundDescription> _sounds;
 };
 
-struct LOAD {
+struct LOAD : public EngineData {
 	LOAD(Common::SeekableReadStream *chunkStream);
 
 	Common::String _imageName;
@@ -244,7 +249,7 @@ struct LOAD {
 	// Common::Rect _gameSavedBounds
 };
 
-struct SDLG {
+struct SDLG : public EngineData {
 	SDLG(Common::SeekableReadStream *chunkStream);
 
 	Common::String _imageName;
@@ -262,19 +267,19 @@ struct SDLG {
 	Common::Rect _cancelDownSrc;
 };
 
-struct HINT {
+struct HINT : public EngineData {
 	HINT(Common::SeekableReadStream *chunkStream);
 
 	Common::Array<uint16> numHints;
 };
 
-struct SPUZ {
+struct SPUZ : public EngineData {
 	SPUZ(Common::SeekableReadStream *chunkStream);
 
 	Common::Array<Common::Array<int16>> tileOrder;
 };
 
-struct CLOK {
+struct CLOK : public EngineData {
 	CLOK(Common::SeekableReadStream *chunkStream);
 
 	Common::Array<Common::Rect> animSrcs;
@@ -293,7 +298,7 @@ struct CLOK {
 	uint16 frameTime;
 };
 
-struct SPEC {
+struct SPEC : public EngineData {
 	SPEC(Common::SeekableReadStream *chunkStream);
 
 	byte fadeToBlackNumFrames;
@@ -301,7 +306,7 @@ struct SPEC {
 	byte crossDissolveNumFrames;
 };
 
-struct RCLB {
+struct RCLB : public EngineData {
 	struct Theme {
 		Common::String themeName;
 
@@ -331,7 +336,7 @@ struct RCLB {
 	Common::Array<Theme> themes;
 };
 
-struct RCPR {
+struct RCPR : public EngineData {
 	RCPR(Common::SeekableReadStream *chunkStream);
 
 	Common::Array<Common::Rect> screenViewportSizes;
@@ -354,8 +359,7 @@ struct RCPR {
 	Common::Array<Common::String> floorNames;
 };
 
-struct ImageChunk {
-	ImageChunk() : width(0), height(0) {}
+struct ImageChunk : public EngineData {
 	ImageChunk(Common::SeekableReadStream *chunkStream);
 
 	Common::String imageName;
diff --git a/engines/nancy/graphics.cpp b/engines/nancy/graphics.cpp
index b393d37e21e..583c6731e78 100644
--- a/engines/nancy/graphics.cpp
+++ b/engines/nancy/graphics.cpp
@@ -45,7 +45,10 @@ void GraphicsManager::init() {
 	_screen.setTransparentColor(getTransColor());
 	_screen.clear();
 
-	g_nancy->_resource->loadImage(g_nancy->_imageChunks["OB0"].imageName, _object0);
+	const ImageChunk *ob0 = (const ImageChunk *)g_nancy->getEngineData("OB0");
+	assert(ob0);
+
+	g_nancy->_resource->loadImage(ob0->imageName, _object0);
 }
 
 void GraphicsManager::draw(bool updateScreen) {
@@ -365,10 +368,13 @@ void GraphicsManager::grabViewportObjects(Common::Array<RenderObject *> &inArray
 }
 
 void GraphicsManager::screenshotViewport(Graphics::ManagedSurface &inSurf) {
+	const VIEW *viewportData = (const VIEW *)g_nancy->getEngineData("VIEW");
+	assert(viewportData);
+
 	draw(false);
 	inSurf.free();
-	inSurf.create(g_nancy->_viewportData->bounds.width(), g_nancy->_viewportData->bounds.height(), _screenPixelFormat);
-	inSurf.blitFrom(_screen, g_nancy->_viewportData->screenPosition, g_nancy->_viewportData->bounds);
+	inSurf.create(viewportData->bounds.width(), viewportData->bounds.height(), _screenPixelFormat);
+	inSurf.blitFrom(_screen, viewportData->screenPosition, viewportData->bounds);
 }
 
 void GraphicsManager::screenshotScreen(Graphics::ManagedSurface &inSurf) {
diff --git a/engines/nancy/misc/specialeffect.cpp b/engines/nancy/misc/specialeffect.cpp
index 2d929f11f11..96a846d5083 100644
--- a/engines/nancy/misc/specialeffect.cpp
+++ b/engines/nancy/misc/specialeffect.cpp
@@ -28,14 +28,17 @@ namespace Nancy {
 namespace Misc {
 
 void SpecialEffect::init() {
-	_specialEffectData = g_nancy->_specialEffectData;
+	_specialEffectData = (const SPEC *)g_nancy->getEngineData("SPEC");
 	assert(_specialEffectData);
 
+	const VIEW *viewportData = (const VIEW *)g_nancy->getEngineData("VIEW");
+	assert(viewportData);
+
 	_numFrames = _type == kSceneChangeFadeOutToBlack ? _specialEffectData->fadeToBlackNumFrames : _specialEffectData->crossDissolveNumFrames;
 	_frameTime = _type == kSceneChangeFadeOutToBlack ? _specialEffectData->fadeToBlackFrameTime : _frameTime;
 
-	_drawSurface.create(g_nancy->_viewportData->bounds.width(), g_nancy->_viewportData->bounds.height(), g_nancy->_graphicsManager->getScreenPixelFormat());
-	moveTo(g_nancy->_viewportData->screenPosition);
+	_drawSurface.create(viewportData->bounds.width(), viewportData->bounds.height(), g_nancy->_graphicsManager->getScreenPixelFormat());
+	moveTo(viewportData->screenPosition);
 	setTransparent(false);
 
 	RenderObject::init();
diff --git a/engines/nancy/misc/specialeffect.h b/engines/nancy/misc/specialeffect.h
index d66b2080105..f842325d5f8 100644
--- a/engines/nancy/misc/specialeffect.h
+++ b/engines/nancy/misc/specialeffect.h
@@ -67,7 +67,8 @@ protected:
 
 	int _currentFrame = 0;
 	uint _numFrames = 0;
-	SPEC *_specialEffectData = nullptr;
+
+	const SPEC *_specialEffectData = nullptr;
 };
 
 } // End of namespace Misc
diff --git a/engines/nancy/nancy.cpp b/engines/nancy/nancy.cpp
index 07cef66b43c..4249f4b7e37 100644
--- a/engines/nancy/nancy.cpp
+++ b/engines/nancy/nancy.cpp
@@ -73,24 +73,6 @@ NancyEngine::NancyEngine(OSystem *syst, const NancyGameDescription *gd) :
 
 	_resource = nullptr;
 
-	_bootSummary = nullptr;
-	_viewportData = nullptr;
-	_inventoryData = nullptr;
-	_textboxData = nullptr;
-	_mapData = nullptr;
-	_helpData = nullptr;
-	_creditsData = nullptr;
-	_menuData = nullptr;
-	_setupData = nullptr;
-	_loadSaveData = nullptr;
-	_saveDialogData = nullptr;
-	_hintData = nullptr;
-	_sliderPuzzleData = nullptr;
-	_clockData = nullptr;
-	_specialEffectData = nullptr;
-	_raycastPuzzleData = nullptr;
-	_raycastPuzzleLevelBuilderData = nullptr;
-
 	_hasJustSaved = false;
 }
 
@@ -112,23 +94,9 @@ NancyEngine::~NancyEngine() {
 	delete _input;
 	delete _sound;
 
-	delete _bootSummary;
-	delete _viewportData;
-	delete _inventoryData;
-	delete _textboxData;
-	delete _mapData;
-	delete _helpData;
-	delete _creditsData;
-	delete _menuData;
-	delete _setupData;
-	delete _loadSaveData;
-	delete _saveDialogData;
-	delete _hintData;
-	delete _sliderPuzzleData;
-	delete _clockData;
-	delete _specialEffectData;
-	delete _raycastPuzzleData;
-	delete _raycastPuzzleLevelBuilderData;
+	for (auto &data : _engineData) {
+		delete data._value;
+	}
 }
 
 NancyEngine *NancyEngine::create(GameType type, OSystem *syst, const NancyGameDescription *gd) {
@@ -198,6 +166,14 @@ const StaticData &NancyEngine::getStaticData() const {
 	return _staticData;
 }
 
+const EngineData *NancyEngine::getEngineData(const Common::String &name) const {
+	if (_engineData.contains(name)) {
+		return _engineData[name];
+	}
+
+	return nullptr;
+}
+
 void NancyEngine::setState(NancyState::NancyState state, NancyState::NancyState overridePrevious) {
 	// Handle special cases first
 	switch (state) {
@@ -390,25 +366,34 @@ void NancyEngine::bootGameEngine() {
 	preloadCals(*boot);
 
 	// Load BOOT chunks data
-	_bootSummary = new BSUM(boot->getChunkStream("BSUM"));
-	_viewportData = new VIEW(boot->getChunkStream("VIEW"));
-	_inventoryData = new INV(boot->getChunkStream("INV"));
-	_textboxData = new TBOX(boot->getChunkStream("TBOX"));
-	_helpData = new HELP(boot->getChunkStream("HELP"));
-	_creditsData = new CRED(boot->getChunkStream("CRED"));
-	_menuData = new MENU(boot->getChunkStream("MENU"));
-	_setupData = new SET(boot->getChunkStream("SET"));
-	_loadSaveData = new LOAD(boot->getChunkStream("LOAD"));
-
-	auto *chunkStream = boot->getChunkStream("SDLG");
-	if (chunkStream) {
-		_saveDialogData = new SDLG(chunkStream);
-	}
-
-	// For now we ignore the potential for more than one of each of these
-	_imageChunks.setVal("OB0", boot->getChunkStream("OB0"));
-	_imageChunks.setVal("FR0", boot->getChunkStream("FR0"));
-	_imageChunks.setVal("LG0", boot->getChunkStream("LG0"));
+	Common::SeekableReadStream *chunkStream = nullptr;
+	#define LOAD_BOOT_L(t, s) if (chunkStream = boot->getChunkStream(s), chunkStream) {	\
+								_engineData.setVal(s, new t(chunkStream));				\
+								delete chunkStream;										\
+							}
+	#define LOAD_BOOT(t) LOAD_BOOT_L(t, #t)
+
+	LOAD_BOOT(BSUM)
+	LOAD_BOOT(VIEW)
+	LOAD_BOOT(INV)
+	LOAD_BOOT(TBOX)
+	LOAD_BOOT(HELP)
+	LOAD_BOOT(CRED)
+	LOAD_BOOT(MENU)
+	LOAD_BOOT(SET)
+	LOAD_BOOT(LOAD)
+	LOAD_BOOT(SDLG)
+	LOAD_BOOT(MAP)
+	LOAD_BOOT(HINT)
+	LOAD_BOOT(SPUZ)
+	LOAD_BOOT(CLOK)
+	LOAD_BOOT(SPEC)
+	LOAD_BOOT(RCPR)
+	LOAD_BOOT(RCLB)
+
+	LOAD_BOOT_L(ImageChunk, "OB0")
+	LOAD_BOOT_L(ImageChunk, "FR0")
+	LOAD_BOOT_L(ImageChunk, "LG0")
 
 	chunkStream = boot->getChunkStream("PLG0");
 	if (!chunkStream) {
@@ -416,7 +401,7 @@ void NancyEngine::bootGameEngine() {
 	}	
 
 	if (chunkStream) {
-		_imageChunks.setVal("PLG0", chunkStream);
+		_engineData.setVal("PLG0", new ImageChunk(chunkStream));
 	}
 
 	_cursorManager->init(boot->getChunkStream("CURS"));
@@ -424,40 +409,8 @@ void NancyEngine::bootGameEngine() {
 	_graphicsManager->init();
 	_graphicsManager->loadFonts(boot->getChunkStream("FONT"));
 
-	chunkStream = boot->getChunkStream("MAP");
-	if (chunkStream) {
-		_mapData = new MAP(chunkStream);
-	}
-
-	chunkStream = boot->getChunkStream("HINT");
-	if (chunkStream) {
-		_hintData = new HINT(chunkStream);
-	}
-
-	chunkStream = boot->getChunkStream("SPUZ");
-	if (chunkStream) {
-		_sliderPuzzleData = new SPUZ(chunkStream);
-	}
-
-	chunkStream = boot->getChunkStream("CLOK");
-	if (chunkStream) {
-		_clockData = new CLOK(chunkStream);
-	}
-
-	chunkStream = boot->getChunkStream("SPEC");
-	if (chunkStream) {
-		_specialEffectData = new SPEC(chunkStream);
-	}
-
-	chunkStream = boot->getChunkStream("RCPR");
-	if (chunkStream) {
-		_raycastPuzzleData = new RCPR(chunkStream);
-	}
-
-	chunkStream = boot->getChunkStream("RCLB");
-	if (chunkStream) {
-		_raycastPuzzleLevelBuilderData = new RCLB(chunkStream);
-	}
+	#undef LOAD_BOOT_L
+	#undef LOAD_BOOT
 
 	_sound->initSoundChannels();
 	_sound->loadCommonSounds(boot);
@@ -612,11 +565,12 @@ void NancyEngine::readDatFile() {
 }
 
 Common::Error NancyEngine::synchronize(Common::Serializer &ser) {
-	assert(_bootSummary);
+	const BSUM *bootSummary = (const BSUM *)getEngineData("BSUM");
+	assert(bootSummary);
 
 	// Sync boot summary header, which includes full game title
 	ser.syncVersion(kSavegameVersion);
-	ser.matchBytes((char *)_bootSummary->header, 90);
+	ser.matchBytes((const char *)bootSummary->header, 90);
 
 	// Sync scene and action records
 	NancySceneState.synchronize(ser);
diff --git a/engines/nancy/nancy.h b/engines/nancy/nancy.h
index 9bd3b6e9b92..133b794b006 100644
--- a/engines/nancy/nancy.h
+++ b/engines/nancy/nancy.h
@@ -95,6 +95,7 @@ public:
 	Common::Platform getPlatform() const;
 
 	const StaticData &getStaticData() const;
+	const EngineData *getEngineData(const Common::String &name) const;
 
 	void setState(NancyState::NancyState state, NancyState::NancyState overridePrevious = NancyState::kNone);
 	NancyState::NancyState getState() { return _gameFlow.curState; }
@@ -118,27 +119,6 @@ public:
 
 	Common::RandomSource *_randomSource;
 
-	// BOOT chunks data
-	BSUM *_bootSummary;
-	VIEW *_viewportData;
-	INV *_inventoryData;
-	TBOX *_textboxData;
-	MAP *_mapData;
-	HELP *_helpData;
-	CRED *_creditsData;
-	MENU *_menuData;
-	SET *_setupData;
-	LOAD *_loadSaveData;
-	SDLG *_saveDialogData;
-	HINT *_hintData;
-	SPUZ *_sliderPuzzleData;
-	CLOK *_clockData;
-	SPEC *_specialEffectData;
-	RCPR *_raycastPuzzleData;
-	RCLB *_raycastPuzzleLevelBuilderData;
-
-	Common::HashMap<Common::String, ImageChunk> _imageChunks;
-
 	// Used to check whether we need to show the SaveDialog
 	bool _hasJustSaved;
 
@@ -167,6 +147,8 @@ private:
 	bool isCompressed();
 
 	StaticData _staticData;
+	Common::HashMap<Common::String, EngineData *> _engineData;
+
 	const byte _datFileMajorVersion;
 	const byte _datFileMinorVersion;
 
diff --git a/engines/nancy/state/credits.cpp b/engines/nancy/state/credits.cpp
index 2c4bea9bb0c..71587866033 100644
--- a/engines/nancy/state/credits.cpp
+++ b/engines/nancy/state/credits.cpp
@@ -69,7 +69,7 @@ bool Credits::onStateExit(const NancyState::NancyState nextState) {
 }
 
 void Credits::init() {
-	_creditsData = g_nancy->_creditsData;
+	_creditsData = (const CRED *)g_nancy->getEngineData("CRED");
 	assert(_creditsData);
 
 	_background.init(_creditsData->imageName);
diff --git a/engines/nancy/state/credits.h b/engines/nancy/state/credits.h
index cf1bbcc056f..a2eae4d6032 100644
--- a/engines/nancy/state/credits.h
+++ b/engines/nancy/state/credits.h
@@ -51,7 +51,8 @@ protected:
 
 	void drawTextSurface(uint id);
 
-	CRED *_creditsData;
+	const CRED *_creditsData;
+	
 	State _state;
 	UI::FullScreenImage _background;
 	RenderObject _textSurface;
diff --git a/engines/nancy/state/help.cpp b/engines/nancy/state/help.cpp
index f3394b038ed..cb6d93f7fcb 100644
--- a/engines/nancy/state/help.cpp
+++ b/engines/nancy/state/help.cpp
@@ -80,8 +80,9 @@ bool Help::onStateExit(const NancyState::NancyState nextState) {
 }
 
 void Help::init() {
-	HELP *helpData = g_nancy->_helpData;
+	const HELP *helpData = (const HELP *)g_nancy->getEngineData("HELP");
 	assert(helpData);
+	
 	_image.init(helpData->imageName);
 
 	_button = new UI::Button(5, _image._drawSurface, helpData->buttonSrc, helpData->buttonDest, helpData->buttonHoverSrc);
@@ -109,9 +110,12 @@ void Help::run() {
 	_button->handleInput(input);
 
 	if (_button->_isClicked) {
+		const BSUM *bootSummary = (const BSUM *)g_nancy->getEngineData("BSUM");
+		assert(bootSummary);
+
 		_button->_isClicked = false;
 		g_nancy->_sound->playSound("BUOK");
-		_buttonPressActivationTime = g_system->getMillis() + g_nancy->_bootSummary->buttonPressTimeDelay;
+		_buttonPressActivationTime = g_system->getMillis() + bootSummary->buttonPressTimeDelay;
 		_state = kWait;
 	}
 }
diff --git a/engines/nancy/state/loadsave.cpp b/engines/nancy/state/loadsave.cpp
index dcba56ae02c..e930958617e 100644
--- a/engines/nancy/state/loadsave.cpp
+++ b/engines/nancy/state/loadsave.cpp
@@ -133,7 +133,7 @@ void LoadSaveMenu::registerGraphics() {
 }
 
 void LoadSaveMenu::init() {
-	_loadSaveData = g_nancy->_loadSaveData;
+	_loadSaveData = (const LOAD*)g_nancy->getEngineData("LOAD");
 	assert(_loadSaveData);
 
 	_background.init(_loadSaveData->_imageName);
@@ -154,7 +154,7 @@ void LoadSaveMenu::init() {
 		// Load textbox objects
 		RenderObject *newTb = new RenderObject(5);
 		_textboxes[i] = newTb;
-		Common::Rect &bounds = _loadSaveData->_textboxBounds[i];
+		const Common::Rect &bounds = _loadSaveData->_textboxBounds[i];
 		newTb->_drawSurface.create(bounds.width(), bounds.height(), g_nancy->_graphicsManager->getScreenPixelFormat());
 		newTb->_drawSurface.clear(g_nancy->_graphicsManager->getTransColor());
 		newTb->moveTo(bounds);
diff --git a/engines/nancy/state/loadsave.h b/engines/nancy/state/loadsave.h
index 57552c11c17..ecf1cec2d6f 100644
--- a/engines/nancy/state/loadsave.h
+++ b/engines/nancy/state/loadsave.h
@@ -93,7 +93,7 @@ private:
 	bool _enteringNewState;
 	uint32 _nextBlink;
 
-	LOAD *_loadSaveData;
+	const LOAD *_loadSaveData;
 };
 
 } // End of namespace State
diff --git a/engines/nancy/state/logo.cpp b/engines/nancy/state/logo.cpp
index 56e19bbb9d0..1c1f6332fc9 100644
--- a/engines/nancy/state/logo.cpp
+++ b/engines/nancy/state/logo.cpp
@@ -81,11 +81,15 @@ bool Logo::onStateExit(const NancyState::NancyState nextState) {
 }
 
 void Logo::init() {
-	_logoImage.init(g_nancy->_imageChunks["LG0"].imageName);
+	const ImageChunk *lg0 = (const ImageChunk *)g_nancy->getEngineData("LG0");
+	const ImageChunk *plg0 = (const ImageChunk *)g_nancy->getEngineData("PLG0");
+	assert(lg0);
+
+	_logoImage.init(lg0->imageName);
 	_logoImage.registerGraphics();
 
-	if (g_nancy->_imageChunks.contains("PLG0")) {
-		_partnerLogoImage.init(g_nancy->_imageChunks["PLG0"].imageName);
+	if (plg0) {
+		_partnerLogoImage.init(plg0->imageName);
 		_partnerLogoImage.registerGraphics();
 	}
 
diff --git a/engines/nancy/state/mainmenu.cpp b/engines/nancy/state/mainmenu.cpp
index 936206b8c9b..f4de3c2688b 100644
--- a/engines/nancy/state/mainmenu.cpp
+++ b/engines/nancy/state/mainmenu.cpp
@@ -81,7 +81,7 @@ void MainMenu::clearButtonState() {
 }
 
 void MainMenu::init() {
-	_menuData = g_nancy->_menuData;
+	_menuData = (const MENU*)g_nancy->getEngineData("MENU");
 	assert(_menuData);
 
 	_background.init(_menuData->_imageName);
@@ -187,7 +187,7 @@ void MainMenu::stop() {
 		break;
 	case 6:
 		// Exit Game
-		if (g_nancy->_saveDialogData && Nancy::State::Scene::hasInstance() && !g_nancy->_hasJustSaved) {
+		if (g_nancy->getEngineData("SDLG") && Nancy::State::Scene::hasInstance() && !g_nancy->_hasJustSaved) {
 			g_nancy->setState(NancyState::kSaveDialog);
 		} else {
 			g_nancy->quitGame();
diff --git a/engines/nancy/state/mainmenu.h b/engines/nancy/state/mainmenu.h
index d0492b32109..0a270498e71 100644
--- a/engines/nancy/state/mainmenu.h
+++ b/engines/nancy/state/mainmenu.h
@@ -64,7 +64,7 @@ private:
 
 	Common::Array<UI::Button *> _buttons;
 
-	MENU *_menuData;
+	const MENU *_menuData;
 };
 
 } // End of namespace State
diff --git a/engines/nancy/state/map.cpp b/engines/nancy/state/map.cpp
index b12f597a51d..5b0d8df9f60 100644
--- a/engines/nancy/state/map.cpp
+++ b/engines/nancy/state/map.cpp
@@ -54,7 +54,7 @@ Map::Map() : _state(kInit),
 			_label(7),
 			_closedLabel(7),
 			_background(0) {
-	_mapData = g_nancy->_mapData;
+	_mapData = (const MAP*)g_nancy->getEngineData("MAP");
 	assert(_mapData);
 }
 
@@ -146,7 +146,10 @@ void Map::setLabel(int labelID) {
 }
 
 void Map::MapViewport::init() {
-	moveTo(g_nancy->_viewportData->screenPosition);
+	const VIEW *viewportData = (const VIEW *)g_nancy->getEngineData("VIEW");
+	assert(viewportData);
+
+	moveTo(viewportData->screenPosition);
 	_drawSurface.create(_screenPosition.width(), _screenPosition.height(), g_nancy->_graphicsManager->getInputPixelFormat());
 
 	RenderObject::init();
@@ -190,7 +193,10 @@ void TVDMap::init() {
 	_ornaments.init();
 	_globe.init();
 
-	Common::Rect textboxScreenPosition = g_nancy->_bootSummary->textboxScreenPosition;
+	const BSUM *bootSummary = (const BSUM *)g_nancy->getEngineData("BSUM");
+	assert(bootSummary);
+
+	Common::Rect textboxScreenPosition = bootSummary->textboxScreenPosition;
 	_closedLabel._drawSurface.create(g_nancy->_graphicsManager->_object0, _mapData->closedLabelSrc);
 
 	Common::Rect closedScreenRect;
diff --git a/engines/nancy/state/map.h b/engines/nancy/state/map.h
index 1917e695927..6fb784b1087 100644
--- a/engines/nancy/state/map.h
+++ b/engines/nancy/state/map.h
@@ -78,7 +78,7 @@ protected:
 
 	void setLabel(int labelID);
 
-	MAP *_mapData;
+	const MAP *_mapData;
 
 	MapViewport _viewport;
 	RenderObject _label;
diff --git a/engines/nancy/state/savedialog.cpp b/engines/nancy/state/savedialog.cpp
index 58858d9dc70..1e89f607ef4 100644
--- a/engines/nancy/state/savedialog.cpp
+++ b/engines/nancy/state/savedialog.cpp
@@ -87,7 +87,7 @@ void SaveDialog::registerGraphics() {
 }
 
 void SaveDialog::init() {
-	_dialogData = g_nancy->_saveDialogData;
+	_dialogData = (const SDLG*)g_nancy->getEngineData("SDLG");
 	assert(_dialogData);
 
 	_background.init(_dialogData->_imageName);
diff --git a/engines/nancy/state/savedialog.h b/engines/nancy/state/savedialog.h
index d2551141886..e04c8ed7da0 100644
--- a/engines/nancy/state/savedialog.h
+++ b/engines/nancy/state/savedialog.h
@@ -65,7 +65,7 @@ private:
 	UI::Button *_noButton;
 	UI::Button *_cancelButton;
 
-	SDLG *_dialogData;
+	const SDLG *_dialogData;
 };
 
 } // End of namespace State
diff --git a/engines/nancy/state/scene.cpp b/engines/nancy/state/scene.cpp
index 5a11d7322b5..780aa3d96ca 100644
--- a/engines/nancy/state/scene.cpp
+++ b/engines/nancy/state/scene.cpp
@@ -89,9 +89,12 @@ void Scene::SceneSummary::read(Common::SeekableReadStream &stream) {
 	ser.syncAsUint16LE((uint32 &)fastMoveTimeDelta);
 	ser.skip(1); // CD required for scene
 
-	if (g_nancy->_bootSummary->overrideMovementTimeDeltas) {
-		slowMoveTimeDelta = g_nancy->_bootSummary->slowMovementTimeDelta;
-		fastMoveTimeDelta = g_nancy->_bootSummary->fastMovementTimeDelta;
+	const BSUM *bootSummary = (const BSUM *)g_nancy->getEngineData("BSUM");
+	assert(bootSummary);
+
+	if (bootSummary->overrideMovementTimeDeltas) {
+		slowMoveTimeDelta = bootSummary->slowMovementTimeDelta;
+		fastMoveTimeDelta = bootSummary->fastMovementTimeDelta;
 	}
 
 	delete[] buf;
@@ -265,7 +268,10 @@ void Scene::setPlayerTime(Time time, byte relative) {
 		_timers.playerTime = _timers.playerTime.getDays() * 86400000 + time;
 	}
 
-	_timers.playerTimeNextMinute = g_nancy->getTotalPlayTime() + g_nancy->_bootSummary->playerTimeMinuteLength;
+	const BSUM *bootSummary = (const BSUM *)g_nancy->getEngineData("BSUM");
+	assert(bootSummary);
+
+	_timers.playerTimeNextMinute = g_nancy->getTotalPlayTime() + bootSummary->playerTimeMinuteLength;
 }
 
 byte Scene::getPlayerTOD() const {
@@ -555,6 +561,10 @@ void Scene::synchronize(Common::Serializer &ser) {
 }
 
 void Scene::init() {
+	const BSUM *bootSummary = (const BSUM *)g_nancy->getEngineData("BSUM");
+	const HINT *hintData = (const HINT *)g_nancy->getEngineData("HINT");
+	assert(bootSummary);
+
 	_flags.eventFlags.resize(g_nancy->getStaticData().numEventFlags, g_nancy->_false);
 
 	_flags.sceneCounts.clear();
@@ -562,20 +572,18 @@ void Scene::init() {
 	_flags.items.resize(g_nancy->getStaticData().numItems, g_nancy->_false);
 
 	_timers.lastTotalTime = 0;
-	_timers.playerTime = g_nancy->_bootSummary->startTimeHours * 3600000;
+	_timers.playerTime = bootSummary->startTimeHours * 3600000;
 	_timers.sceneTime = 0;
 	_timers.timerTime = 0;
 	_timers.timerIsActive = false;
 	_timers.playerTimeNextMinute = 0;
 	_timers.pushedPlayTime = 0;
 
-	changeScene(g_nancy->_bootSummary->firstScene);
+	changeScene(bootSummary->firstScene);
 
-	if (g_nancy->_hintData) {
+	if (hintData) {
 		_hintsRemaining.clear();
-
-		_hintsRemaining = g_nancy->_hintData->numHints;
-
+		_hintsRemaining = hintData->numHints;
 		_lastHintCharacter = _lastHintID = -1;
 	}
 
@@ -758,8 +766,11 @@ void Scene::run() {
 
 	// Calculate the in-game time (playerTime)
 	if (currentPlayTime > _timers.playerTimeNextMinute) {
+		const BSUM *bootSummary = (const BSUM *)g_nancy->getEngineData("BSUM");
+		assert(bootSummary);
+
 		_timers.playerTime += 60000; // Add a minute
-		_timers.playerTimeNextMinute = currentPlayTime + g_nancy->_bootSummary->playerTimeMinuteLength;
+		_timers.playerTimeNextMinute = currentPlayTime + bootSummary->playerTimeMinuteLength;
 	}
 
 	handleInput();
@@ -852,8 +863,11 @@ void Scene::handleInput() {
 
 		if (_menuButton->_isClicked) {
 			if (_buttonPressActivationTime == 0) {
+				const BSUM *bootSummary = (const BSUM *)g_nancy->getEngineData("BSUM");
+				assert(bootSummary);
+
 				g_nancy->_sound->playSound("BUOK");
-				_buttonPressActivationTime = g_system->getMillis() + g_nancy->_bootSummary->buttonPressTimeDelay;
+				_buttonPressActivationTime = g_system->getMillis() + bootSummary->buttonPressTimeDelay;
 			} else if (g_system->getMillis() > _buttonPressActivationTime) {
 				_menuButton->_isClicked = false;
 				requestStateChange(NancyState::kMainMenu);
@@ -867,8 +881,11 @@ void Scene::handleInput() {
 
 		if (_helpButton->_isClicked) {
 			if (_buttonPressActivationTime == 0) {
+				const BSUM *bootSummary = (const BSUM *)g_nancy->getEngineData("BSUM");
+				assert(bootSummary);
+
 				g_nancy->_sound->playSound("BUOK");
-				_buttonPressActivationTime = g_system->getMillis() + g_nancy->_bootSummary->buttonPressTimeDelay;
+				_buttonPressActivationTime = g_system->getMillis() + bootSummary->buttonPressTimeDelay;
 			} else if (g_system->getMillis() > _buttonPressActivationTime) {
 				_helpButton->_isClicked = false;
 				requestStateChange(NancyState::kHelp);
@@ -879,23 +896,28 @@ void Scene::handleInput() {
 }
 
 void Scene::initStaticData() {
-	_frame.init(g_nancy->_imageChunks["FR0"].imageName);
+	const BSUM *bootSummary = (const BSUM *)g_nancy->getEngineData("BSUM");
+	assert(bootSummary);
+
+	const ImageChunk *fr0 = (const ImageChunk *)g_nancy->getEngineData("FR0");
+	assert(fr0);
+
+	const MAP *mapData = (const MAP *)g_nancy->getEngineData("MAP");
+
+	_frame.init(fr0->imageName);
 	_viewport.init();
 	_textbox.init();
 	_inventoryBox.init();
 
 	// Init buttons
-	BSUM *bsum = g_nancy->_bootSummary;
-	assert(bsum);
-
 	if (g_nancy->getGameType() == kGameTypeVampire) {
-		_mapHotspot = bsum->extraButtonHotspot;
-	} else if (g_nancy->_mapData) {
-		_mapHotspot = g_nancy->_mapData->buttonDest;
+		_mapHotspot = bootSummary->extraButtonHotspot;
+	} else if (mapData) {
+		_mapHotspot = mapData->buttonDest;
 	}
 
-	_menuButton = new UI::Button(5, g_nancy->_graphicsManager->_object0, bsum->menuButtonSrc, bsum->menuButtonDest, bsum->menuButtonHighlightSrc);
-	_helpButton = new UI::Button(5, g_nancy->_graphicsManager->_object0, bsum->helpButtonSrc, bsum->helpButtonDest, bsum->helpButtonHighlightSrc);
+	_menuButton = new UI::Button(5, g_nancy->_graphicsManager->_object0, bootSummary->menuButtonSrc, bootSummary->menuButtonDest, bootSummary->menuButtonHighlightSrc);
+	_helpButton = new UI::Button(5, g_nancy->_graphicsManager->_object0, bootSummary->helpButtonSrc, bootSummary->helpButtonDest, bootSummary->helpButtonHighlightSrc);
 	g_nancy->setMouseEnabled(true);
 
 	// Init ornaments and clock (TVD only)
diff --git a/engines/nancy/state/setupmenu.cpp b/engines/nancy/state/setupmenu.cpp
index 855341f6e87..86c30fb2d85 100644
--- a/engines/nancy/state/setupmenu.cpp
+++ b/engines/nancy/state/setupmenu.cpp
@@ -90,7 +90,7 @@ void SetupMenu::registerGraphics() {
 }
 
 void SetupMenu::init() {
-	_setupData = g_nancy->_setupData;
+	_setupData = (const SET*)g_nancy->getEngineData("SET");
 	assert(_setupData);
 
 	if (g_nancy->getGameType() == kGameTypeVampire) {
diff --git a/engines/nancy/state/setupmenu.h b/engines/nancy/state/setupmenu.h
index 58b6d228054..7c5bc61eae0 100644
--- a/engines/nancy/state/setupmenu.h
+++ b/engines/nancy/state/setupmenu.h
@@ -66,7 +66,7 @@ private:
 	Common::Array<UI::Scrollbar *> _scrollbars;
 	UI::Button *_exitButton;
 
-	SET *_setupData;
+	const SET *_setupData;
 };
 
 } // End of namespace State
diff --git a/engines/nancy/ui/button.cpp b/engines/nancy/ui/button.cpp
index 85027ed1826..98811c9826b 100644
--- a/engines/nancy/ui/button.cpp
+++ b/engines/nancy/ui/button.cpp
@@ -86,7 +86,7 @@ void Button::setDisabled(bool disabled) {
 	}
 }
 
-Toggle::Toggle(uint16 zOrder, Graphics::ManagedSurface &surface, Common::Rect &srcRect, Common::Rect &destRect) :
+Toggle::Toggle(uint16 zOrder, Graphics::ManagedSurface &surface, const Common::Rect &srcRect, const Common::Rect &destRect) :
 		RenderObject(zOrder, surface, srcRect, destRect),
 		surf(surface),
 		_clickSrc(srcRect),
diff --git a/engines/nancy/ui/button.h b/engines/nancy/ui/button.h
index ee754eeb056..5ee31dbd012 100644
--- a/engines/nancy/ui/button.h
+++ b/engines/nancy/ui/button.h
@@ -54,7 +54,7 @@ public:
 
 class Toggle : public RenderObject {
 public:
-	Toggle(uint16 zOrder, Graphics::ManagedSurface &surface, Common::Rect &srcRect, Common::Rect &destRect);
+	Toggle(uint16 zOrder, Graphics::ManagedSurface &surface, const Common::Rect &srcRect, const Common::Rect &destRect);
 	virtual ~Toggle() = default;
 
 	void handleInput(NancyInput &input);
diff --git a/engines/nancy/ui/clock.cpp b/engines/nancy/ui/clock.cpp
index cb1e3534fd4..10b734393f5 100644
--- a/engines/nancy/ui/clock.cpp
+++ b/engines/nancy/ui/clock.cpp
@@ -43,18 +43,18 @@ Clock::Clock() : 	RenderObject(g_nancy->getGameType() == kGameTypeVampire ? 11 :
 void Clock::init() {
 	Graphics::ManagedSurface &object0 = g_nancy->_graphicsManager->_object0;
 
-	_clockData = g_nancy->_clockData;
+	_clockData = (const CLOK *)g_nancy->getEngineData("CLOK");
 	assert(_clockData);
 
 	// Calculate the size and location of the surface we'll need to draw the clock hands,
 	// since their dest rects are in absolute screen space
 	Common::Rect clockSurfaceScreenBounds;
 
-	for (Common::Rect &r : _clockData->hoursHandDests) {
+	for (const Common::Rect &r : _clockData->hoursHandDests) {
 		clockSurfaceScreenBounds.extend(r);
 	}
 
-	for (Common::Rect &r : _clockData->minutesHandDests) {
+	for (const Common::Rect &r : _clockData->minutesHandDests) {
 		clockSurfaceScreenBounds.extend(r);
 	}
 
@@ -125,13 +125,16 @@ void Clock::drawClockHands() {
 }
 
 void Clock::ClockAnim::init() {
+	const BSUM *bootSummary = (const BSUM *)g_nancy->getEngineData("BSUM");
+	assert(bootSummary);
+
 	_srcRects = _owner->_clockData->animSrcs;
 	_destRects = _owner->_clockData->animDests;
-	_highlightSrcRect = g_nancy->_bootSummary->clockHighlightSrc;
-	_highlightDestRect = g_nancy->_bootSummary->extraButtonHighlightDest;
+	_highlightSrcRect = bootSummary->clockHighlightSrc;
+	_highlightDestRect = bootSummary->extraButtonHighlightDest;
 
 	if (_destRects.size()) {
-		moveTo(g_nancy->_bootSummary->extraButtonHotspot);
+		moveTo(bootSummary->extraButtonHotspot);
 	} else {
 		moveTo(_owner->_clockData->screenPosition);
 	}
diff --git a/engines/nancy/ui/clock.h b/engines/nancy/ui/clock.h
index 76361c7b42a..d25b907c9cf 100644
--- a/engines/nancy/ui/clock.h
+++ b/engines/nancy/ui/clock.h
@@ -68,7 +68,7 @@ protected:
 		uint32 _timeToKeepOpen;
 	};
 
-	CLOK *_clockData;
+	const CLOK *_clockData;
 	ClockAnim _animation;
 
 	// Used for gargoyle eyes in TVD, inside of watch in nancy2 and up
diff --git a/engines/nancy/ui/inventorybox.cpp b/engines/nancy/ui/inventorybox.cpp
index b39a1760ae4..810ecd3e4f5 100644
--- a/engines/nancy/ui/inventorybox.cpp
+++ b/engines/nancy/ui/inventorybox.cpp
@@ -48,10 +48,16 @@ InventoryBox::~InventoryBox() {
 }
 
 void InventoryBox::init() {
+	const BSUM *bootSummary = (const BSUM *)g_nancy->getEngineData("BSUM");
+	assert(bootSummary);
+
+	const INV *inventoryData = (const INV *)g_nancy->getEngineData("INV");
+	assert(inventoryData);
+
 	_order.clear();
 
-	moveTo(g_nancy->_bootSummary->inventoryBoxScreenPosition);
-	g_nancy->_resource->loadImage(g_nancy->_inventoryData->inventoryBoxIconsImageName, _iconsSurface);
+	moveTo(bootSummary->inventoryBoxScreenPosition);
+	g_nancy->_resource->loadImage(inventoryData->inventoryBoxIconsImageName, _iconsSurface);
 
 	_fullInventorySurface.create(_screenPosition.width(), _screenPosition.height() * ((g_nancy->getStaticData().numItems / 4) + 1), g_nancy->_graphicsManager->getScreenPixelFormat());
 	Common::Rect sourceRect = _screenPosition;
@@ -69,9 +75,9 @@ void InventoryBox::init() {
 	RenderObject::init();
 
 	_scrollbar = new Scrollbar(	9,
-								g_nancy->_inventoryData->scrollbarSrcBounds,
-								g_nancy->_inventoryData->scrollbarDefaultPos,
-								g_nancy->_inventoryData->scrollbarMaxScroll - g_nancy->_inventoryData->scrollbarDefaultPos.y);
+								inventoryData->scrollbarSrcBounds,
+								inventoryData->scrollbarDefaultPos,
+								inventoryData->scrollbarMaxScroll - inventoryData->scrollbarDefaultPos.y);
 	_scrollbar->init();
 	_curtains.init();
 }
@@ -194,7 +200,10 @@ void InventoryBox::setHotspots(const uint pageNr) {
 }
 
 void InventoryBox::drawItemInSlot(const uint itemID, const uint slotID, const bool highlighted) {
-	auto &item = g_nancy->_inventoryData->itemDescriptions[itemID];
+	const INV *inventoryData = (const INV *)g_nancy->getEngineData("INV");
+	assert(inventoryData);
+
+	auto &item = inventoryData->itemDescriptions[itemID];
 	Common::Rect dest;
 
 	dest.setWidth(_screenPosition.width() / 2);
@@ -223,7 +232,10 @@ void InventoryBox::onScrollbarMove() {
 }
 
 void InventoryBox::Curtains::init() {
-	moveTo(g_nancy->_inventoryData->curtainsScreenPosition);
+	const INV *inventoryData = (const INV *)g_nancy->getEngineData("INV");
+	assert(inventoryData);
+
+	moveTo(inventoryData->curtainsScreenPosition);
 	Common::Rect bounds = _screenPosition;
 	bounds.moveTo(0, 0);
 	_drawSurface.create(bounds.width(), bounds.height(), g_nancy->_graphicsManager->getInputPixelFormat());
@@ -246,8 +258,11 @@ void InventoryBox::Curtains::updateGraphics() {
 	Time time = g_nancy->getTotalPlayTime();
 	if (_areOpen) {
 		if (_curFrame < g_nancy->getStaticData().numCurtainAnimationFrames && time > _nextFrameTime) {
+			const INV *inventoryData = (const INV *)g_nancy->getEngineData("INV");
+			assert(inventoryData);
+
 			setAnimationFrame(++_curFrame);
-			_nextFrameTime = time + g_nancy->_inventoryData->curtainsFrameTime;
+			_nextFrameTime = time + inventoryData->curtainsFrameTime;
 
 			if (!_soundTriggered) {
 				_soundTriggered = true;
@@ -256,8 +271,11 @@ void InventoryBox::Curtains::updateGraphics() {
 		}
 	} else {
 		if (_curFrame > 0 && time > _nextFrameTime) {
+			const INV *inventoryData = (const INV *)g_nancy->getEngineData("INV");
+			assert(inventoryData);
+
 			setAnimationFrame(--_curFrame);
-			_nextFrameTime = time + g_nancy->_inventoryData->curtainsFrameTime;
+			_nextFrameTime = time + inventoryData->curtainsFrameTime;
 
 			if (!_soundTriggered) {
 				_soundTriggered = true;
@@ -287,14 +305,17 @@ void InventoryBox::Curtains::setAnimationFrame(uint frame) {
 		setVisible(true);
 	}
 
+	const INV *inventoryData = (const INV *)g_nancy->getEngineData("INV");
+	assert(inventoryData);
+
 	_drawSurface.clear(g_nancy->_graphicsManager->getTransColor());
 
-	// Draw left shade
-	srcRect = g_nancy->_inventoryData->curtainAnimationSrcs[frame * 2];
+	// Draw left curtain
+	srcRect = inventoryData->curtainAnimationSrcs[frame * 2];
 	_drawSurface.blitFrom(_object0, srcRect, destPoint);
 
-	// Draw right shade
-	srcRect = g_nancy->_inventoryData->curtainAnimationSrcs[frame * 2 + 1];
+	// Draw right curtain
+	srcRect = inventoryData->curtainAnimationSrcs[frame * 2 + 1];
 	destPoint.x = getBounds().width() - srcRect.width();
 	_drawSurface.blitFrom(_object0, srcRect, destPoint);
 
diff --git a/engines/nancy/ui/ornaments.cpp b/engines/nancy/ui/ornaments.cpp
index 78b7df9b995..58fc6945d99 100644
--- a/engines/nancy/ui/ornaments.cpp
+++ b/engines/nancy/ui/ornaments.cpp
@@ -29,8 +29,11 @@ namespace Nancy {
 namespace UI {
 
 void ViewportOrnaments::init() {
-	Common::Rect viewportBounds = g_nancy->_viewportData->bounds;
-	moveTo(g_nancy->_viewportData->screenPosition);
+	const VIEW *viewportData = (const VIEW *)g_nancy->getEngineData("VIEW");
+	assert(viewportData);
+
+	Common::Rect viewportBounds = viewportData->bounds;
+	moveTo(viewportData->screenPosition);
 
 	Graphics::ManagedSurface &object0 = g_nancy->_graphicsManager->_object0;
 
@@ -71,7 +74,13 @@ void ViewportOrnaments::init() {
 }
 
 void TextboxOrnaments::init() {
-	moveTo(g_nancy->_bootSummary->textboxScreenPosition);
+	const BSUM *bootSummary = (const BSUM *)g_nancy->getEngineData("BSUM");
+	assert(bootSummary);
+
+	const TBOX *textboxData = (const TBOX *)g_nancy->getEngineData("TBOX");
+	assert(textboxData);
+
+	moveTo(bootSummary->textboxScreenPosition);
 	Common::Rect textboxBounds = _screenPosition;
 	textboxBounds.moveTo(0, 0);
 
@@ -87,16 +96,22 @@ void TextboxOrnaments::init() {
 	setTransparent(true);
 
 	for (uint i = 0; i < 14; ++i) {
-		_drawSurface.blitFrom(object0, g_nancy->_textboxData->ornamentSrcs[i],
-								Common::Point(	g_nancy->_textboxData->ornamentDests[i].left - _screenPosition.left,
-												g_nancy->_textboxData->ornamentDests[i].top - _screenPosition.top));
+		_drawSurface.blitFrom(object0, textboxData->ornamentSrcs[i],
+								Common::Point(	textboxData->ornamentDests[i].left - _screenPosition.left,
+												textboxData->ornamentDests[i].top - _screenPosition.top));
 	}
 
 	RenderObject::init();
 }
 
 void InventoryBoxOrnaments::init() {
-	moveTo(g_nancy->_bootSummary->inventoryBoxScreenPosition);
+	const BSUM *bootSummary = (const BSUM *)g_nancy->getEngineData("BSUM");
+	assert(bootSummary);
+
+	const INV *inventoryData = (const INV *)g_nancy->getEngineData("INV");
+	assert(inventoryData);
+
+	moveTo(bootSummary->inventoryBoxScreenPosition);
 	Common::Rect invBoxBounds = _screenPosition;
 	invBoxBounds.moveTo(0, 0);
 
@@ -112,9 +127,9 @@ void InventoryBoxOrnaments::init() {
 	setTransparent(true);
 
 	for (uint i = 0; i < 6; ++i) {
-		_drawSurface.blitFrom(object0, g_nancy->_inventoryData->ornamentSrcs[i],
-								Common::Point(	g_nancy->_inventoryData->ornamentDests[i].left - _screenPosition.left,
-												g_nancy->_inventoryData->ornamentDests[i].top - _screenPosition.top));
+		_drawSurface.blitFrom(object0, inventoryData->ornamentSrcs[i],
+								Common::Point(	inventoryData->ornamentDests[i].left - _screenPosition.left,
+												inventoryData->ornamentDests[i].top - _screenPosition.top));
 	}
 }
 
diff --git a/engines/nancy/ui/textbox.cpp b/engines/nancy/ui/textbox.cpp
index 8be10bb5457..53111027703 100644
--- a/engines/nancy/ui/textbox.cpp
+++ b/engines/nancy/ui/textbox.cpp
@@ -50,13 +50,16 @@ Textbox::~Textbox() {
 }
 
 void Textbox::init() {
-	TBOX *tbox = g_nancy->_textboxData;
-	assert(tbox);
+	const BSUM *bootSummary = (const BSUM *)g_nancy->getEngineData("BSUM");
+	assert(bootSummary);
 
-	moveTo(g_nancy->_bootSummary->textboxScreenPosition);
-	_highlightRObj.moveTo(g_nancy->_bootSummary->textboxScreenPosition);
-	_fullSurface.create(tbox->innerBoundingBox.width(), tbox->innerBoundingBox.height(), g_nancy->_graphicsManager->getScreenPixelFormat());
-	_textHighlightSurface.create(tbox->innerBoundingBox.width(), tbox->innerBoundingBox.height(), g_nancy->_graphicsManager->getScreenPixelFormat());
+	const TBOX *textboxData = (const TBOX *)g_nancy->getEngineData("TBOX");
+	assert(textboxData);
+
+	moveTo(bootSummary->textboxScreenPosition);
+	_highlightRObj.moveTo(bootSummary->textboxScreenPosition);
+	_fullSurface.create(textboxData->innerBoundingBox.width(), textboxData->innerBoundingBox.height(), g_nancy->_graphicsManager->getScreenPixelFormat());
+	_textHighlightSurface.create(textboxData->innerBoundingBox.width(), textboxData->innerBoundingBox.height(), g_nancy->_graphicsManager->getScreenPixelFormat());
 	_textHighlightSurface.setTransparentColor(g_nancy->_graphicsManager->getTransColor());
 
 	Common::Rect outerBoundingBox = _screenPosition;
@@ -67,9 +70,9 @@ void Textbox::init() {
 
 	// zOrder bumped by 2 to avoid overlap with the inventory box curtains in The Vampire Diaries
 	_scrollbar = new Scrollbar(	11,
-								tbox->scrollbarSrcBounds,
-								tbox->scrollbarDefaultPos,
-								tbox->scrollbarMaxScroll - tbox->scrollbarDefaultPos.y);
+								textboxData->scrollbarSrcBounds,
+								textboxData->scrollbarDefaultPos,
+								textboxData->scrollbarMaxScroll - textboxData->scrollbarDefaultPos.y);
 	_scrollbar->init();
 }
 
@@ -133,13 +136,13 @@ void Textbox::handleInput(NancyInput &input) {
 void Textbox::drawTextbox() {
 	using namespace Common;
 
-	TBOX *tbox = g_nancy->_textboxData;
-	assert(tbox);
+	const TBOX *textboxData = (const TBOX *)g_nancy->getEngineData("TBOX");
+	assert(textboxData);
 
 	_numLines = 0;
 
-	uint maxWidth = _fullSurface.w - tbox->maxWidthDifference - tbox->borderWidth - 2;
-	uint lineDist = tbox->lineHeight + tbox->lineHeight / 4;
+	uint maxWidth = _fullSurface.w - textboxData->maxWidthDifference - textboxData->borderWidth - 2;
+	uint lineDist = textboxData->lineHeight + textboxData->lineHeight / 4;
 
 	for (uint lineID = 0; lineID < _textLines.size(); ++lineID) {
 		Common::String currentLine;
@@ -229,8 +232,8 @@ void Textbox::drawTextbox() {
 			currentLine += curToken;
 		}
 		
-		const Font *font = g_nancy->_graphicsManager->getFont(fontID == -1 ? tbox->conversationFontID : fontID);
-		const Font *highlightFont = g_nancy->_graphicsManager->getFont(tbox->highlightConversationFontID);
+		const Font *font = g_nancy->_graphicsManager->getFont(fontID == -1 ? textboxData->conversationFontID : fontID);
+		const Font *highlightFont = g_nancy->_graphicsManager->getFont(textboxData->highlightConversationFontID);
 
 		// Do word wrapping on the text, sans tokens
 		Array<Common::String> wrappedLines;
@@ -238,9 +241,9 @@ void Textbox::drawTextbox() {
 
 		// Setup most of the hotspot
 		if (hasHotspot) {
-			hotspot.left = tbox->borderWidth;
-			hotspot.top = tbox->firstLineOffset - tbox->lineHeight + (_numLines * lineDist) - 1;
-			hotspot.setHeight((wrappedLines.size() * lineDist) - (lineDist - tbox->lineHeight));
+			hotspot.left = textboxData->borderWidth;
+			hotspot.top = textboxData->firstLineOffset - textboxData->lineHeight + (_numLines * lineDist) - 1;
+			hotspot.setHeight((wrappedLines.size() * lineDist) - (lineDist - textboxData->lineHeight));
 			hotspot.setWidth(0);
 		}
 
@@ -294,8 +297,8 @@ void Textbox::drawTextbox() {
 				// Draw the normal text
 				font->drawString(				&_fullSurface,
 												stringToDraw,
-												tbox->borderWidth + horizontalOffset,
-												tbox->firstLineOffset - font->getFontHeight() + _numLines * lineDist,
+												textboxData->borderWidth + horizontalOffset,
+												textboxData->firstLineOffset - font->getFontHeight() + _numLines * lineDist,
 												maxWidth,
 												isColor);
 
@@ -303,8 +306,8 @@ void Textbox::drawTextbox() {
 				if (hasHotspot) {
 					highlightFont->drawString(	&_textHighlightSurface,
 												stringToDraw,
-												tbox->borderWidth + horizontalOffset,
-												tbox->firstLineOffset - font->getFontHeight() + _numLines * lineDist,
+												textboxData->borderWidth + horizontalOffset,
+												textboxData->firstLineOffset - font->getFontHeight() + _numLines * lineDist,
 												maxWidth,
 												isColor);
 				}
@@ -409,15 +412,15 @@ void Textbox::onScrollbarMove() {
 }
 
 uint16 Textbox::getInnerHeight() const {
-	TBOX *tbox = g_nancy->_textboxData;
-	assert(tbox);
+	const TBOX *textboxData = (const TBOX *)g_nancy->getEngineData("TBOX");
+	assert(textboxData);
 
 	// These calculations are _almost_ correct, but off by a pixel sometimes
-	uint lineDist = tbox->lineHeight + tbox->lineHeight / 4;
+	uint lineDist = textboxData->lineHeight + textboxData->lineHeight / 4;
 	if (g_nancy->getGameType() == kGameTypeVampire) {
-		return _numLines * lineDist + tbox->firstLineOffset + (_lastResponseisMultiline ? - tbox->lineHeight / 2 : 1);
+		return _numLines * lineDist + textboxData->firstLineOffset + (_lastResponseisMultiline ? - textboxData->lineHeight / 2 : 1);
 	} else {
-		return _numLines * lineDist + tbox->firstLineOffset + lineDist / 2 - 1;
+		return _numLines * lineDist + textboxData->firstLineOffset + lineDist / 2 - 1;
 	}
 }
 
diff --git a/engines/nancy/ui/viewport.cpp b/engines/nancy/ui/viewport.cpp
index 191125eeaa7..31922edc9aa 100644
--- a/engines/nancy/ui/viewport.cpp
+++ b/engines/nancy/ui/viewport.cpp
@@ -36,12 +36,18 @@ namespace UI {
 
 // does NOT put the object in a valid state until loadVideo is called
 void Viewport::init() {
-	moveTo(g_nancy->_viewportData->screenPosition);
+	const BSUM *bootSummary = (const BSUM *)g_nancy->getEngineData("BSUM");
+	assert(bootSummary);
 
-	setEdgesSize(	g_nancy->_bootSummary->verticalEdgesSize,
-					g_nancy->_bootSummary->verticalEdgesSize,
-					g_nancy->_bootSummary->horizontalEdgesSize,
-					g_nancy->_bootSummary->horizontalEdgesSize);
+	const VIEW *viewportData = (const VIEW *)g_nancy->getEngineData("VIEW");
+	assert(viewportData);
+
+	moveTo(viewportData->screenPosition);
+
+	setEdgesSize(	bootSummary->verticalEdgesSize,
+					bootSummary->verticalEdgesSize,
+					bootSummary->horizontalEdgesSize,
+					bootSummary->horizontalEdgesSize);
 
 	RenderObject::init();
 }


Commit: 35e0946ff703a3c7480a3073c58423cf8aa53099
    https://github.com/scummvm/scummvm/commit/35e0946ff703a3c7480a3073c58423cf8aa53099
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2023-08-31T12:20:39+03:00

Commit Message:
NANCY: Add support for nancy5's day counter

Added support for the nancy5 day counter/countdown
clock that replaces the normal clock in the bottom left of
the UI.

Changed paths:
    engines/nancy/enginedata.cpp
    engines/nancy/enginedata.h
    engines/nancy/state/scene.cpp
    engines/nancy/state/scene.h
    engines/nancy/ui/clock.cpp
    engines/nancy/ui/clock.h


diff --git a/engines/nancy/enginedata.cpp b/engines/nancy/enginedata.cpp
index 7ff11c2afc8..f6d5cbc5ec4 100644
--- a/engines/nancy/enginedata.cpp
+++ b/engines/nancy/enginedata.cpp
@@ -530,6 +530,12 @@ CLOK::CLOK(Common::SeekableReadStream *chunkStream) : EngineData(chunkStream) {
 
 	s.syncAsUint32LE(timeToKeepOpen);
 	s.syncAsUint16LE(frameTime);
+
+	s.skip(2, kGameTypeNancy5);
+	s.syncAsUint32LE(nancy5CountdownTime, kGameTypeNancy5);
+	s.skip(2, kGameTypeNancy5);
+	readRectArray(s, nancy5DaySrcs, 3, kGameTypeNancy5);
+	readRectArray(s, nancy5CountdownSrcs, 13, kGameTypeNancy5);
 }
 
 SPEC::SPEC(Common::SeekableReadStream *chunkStream) : EngineData(chunkStream) {
diff --git a/engines/nancy/enginedata.h b/engines/nancy/enginedata.h
index 1467837855c..3e51a8d457c 100644
--- a/engines/nancy/enginedata.h
+++ b/engines/nancy/enginedata.h
@@ -296,6 +296,10 @@ struct CLOK : public EngineData {
 
 	uint32 timeToKeepOpen;
 	uint16 frameTime;
+
+	uint32 nancy5CountdownTime;
+	Common::Array<Common::Rect> nancy5DaySrcs;
+	Common::Array<Common::Rect> nancy5CountdownSrcs;
 };
 
 struct SPEC : public EngineData {
diff --git a/engines/nancy/state/scene.cpp b/engines/nancy/state/scene.cpp
index 780aa3d96ca..808566034b2 100644
--- a/engines/nancy/state/scene.cpp
+++ b/engines/nancy/state/scene.cpp
@@ -560,6 +560,10 @@ void Scene::synchronize(Common::Serializer &ser) {
 	// Sync sound data
 }
 
+UI::Clock *Scene::getClock() {
+	return g_nancy->getGameType() != kGameTypeNancy5 ? (UI::Clock *)_clock : nullptr;
+}
+
 void Scene::init() {
 	const BSUM *bootSummary = (const BSUM *)g_nancy->getEngineData("BSUM");
 	const HINT *hintData = (const HINT *)g_nancy->getEngineData("HINT");
@@ -843,8 +847,8 @@ void Scene::handleInput() {
 	}
 
 	// Handle clock before viewport since it overlaps the left hotspot in TVD
-	if (_clock) {
-		_clock->handleInput(input);
+	if (getClock()) {
+		getClock()->handleInput(input);
 	}
 
 	_viewport.handleInput(input);
@@ -936,7 +940,13 @@ void Scene::initStaticData() {
 	}
 
 	if (g_nancy->getGameType() >= kGameTypeNancy2) {
-		_clock = new UI::Clock();
+		if (g_nancy->getGameType() == kGameTypeNancy5) {
+			// Nancy 5 uses a custom "clock" that mostly just indicates the in-game day
+			_clock = new UI::Nancy5Clock();
+		} else {
+			_clock = new UI::Clock();
+		}
+		
 		_clock->init();
 	}
 
diff --git a/engines/nancy/state/scene.h b/engines/nancy/state/scene.h
index 251309e712c..bb73b670a19 100644
--- a/engines/nancy/state/scene.h
+++ b/engines/nancy/state/scene.h
@@ -168,7 +168,7 @@ public:
 	UI::Viewport &getViewport() { return _viewport; }
 	UI::Textbox &getTextbox() { return _textbox; }
 	UI::InventoryBox &getInventoryBox() { return _inventoryBox; }
-	UI::Clock *getClock() { return _clock; }
+	UI::Clock *getClock();
 
 	Action::ActionManager &getActionManager() { return _actionManager; }
 
@@ -254,7 +254,7 @@ private:
 	UI::ViewportOrnaments *_viewportOrnaments;
 	UI::TextboxOrnaments *_textboxOrnaments;
 	UI::InventoryBoxOrnaments *_inventoryBoxOrnaments;
-	UI::Clock *_clock;
+	RenderObject *_clock;
 
 	Common::Rect _mapHotspot;
 
diff --git a/engines/nancy/ui/clock.cpp b/engines/nancy/ui/clock.cpp
index 10b734393f5..32d1366a8e2 100644
--- a/engines/nancy/ui/clock.cpp
+++ b/engines/nancy/ui/clock.cpp
@@ -186,5 +186,51 @@ void Clock::ClockAnim::onTrigger() {
 	}
 }
 
+void Nancy5Clock::init() {
+	_clockData = (const CLOK *)g_nancy->getEngineData("CLOK");
+	assert(_clockData);
+
+	setVisible(true);
+}
+
+void Nancy5Clock::updateGraphics() {
+	// Show current day
+	if (_currentDay < 3) {
+		if (NancySceneState.getEventFlag(59, true) && _currentDay != 2) {
+			_currentDay = 2;
+			_drawSurface.create(g_nancy->_graphicsManager->_object0, _clockData->nancy5DaySrcs[2]);
+			moveTo(_clockData->staticImageDest);
+			setVisible(true);
+			setTransparent(true);
+		} else if (NancySceneState.getEventFlag(58, true) && _currentDay != 1) {
+			_currentDay = 1;
+			_drawSurface.create(g_nancy->_graphicsManager->_object0, _clockData->nancy5DaySrcs[1]);
+			moveTo(_clockData->staticImageDest);
+			setVisible(true);
+			setTransparent(true);
+		} else if (NancySceneState.getEventFlag(57, true) && _currentDay != 0) {
+			_currentDay = 0;
+			_drawSurface.create(g_nancy->_graphicsManager->_object0, _clockData->nancy5DaySrcs[0]);
+			moveTo(_clockData->staticImageDest);
+			setVisible(true);
+			setTransparent(true);
+		}
+	}
+
+	// Show demolition countdown
+	if (NancySceneState.getEventFlag(320, true)) {
+		_currentDay = 3;
+		Time timerTime = NancySceneState.getTimerTime();
+		int32 countdownFrameID = MIN<int32>((uint32)timerTime / (_clockData->nancy5CountdownTime / 12), 13);
+		if (countdownFrameID != _countdownProgress) {
+			_countdownProgress = countdownFrameID;
+
+			_drawSurface.create(g_nancy->_graphicsManager->_object0, _clockData->nancy5CountdownSrcs[_countdownProgress]);
+			moveTo(_clockData->staticImageDest);
+			setVisible(true);
+		}
+	}
+}
+
 } // End of namespace UI
 } // End of namespace Nancy
diff --git a/engines/nancy/ui/clock.h b/engines/nancy/ui/clock.h
index d25b907c9cf..2e9ae903b4b 100644
--- a/engines/nancy/ui/clock.h
+++ b/engines/nancy/ui/clock.h
@@ -78,6 +78,23 @@ protected:
 	bool _locked;
 };
 
+// Separate class since it's not actually a clock, and is non-interactable. Instead, this shows which
+// in-game day it currently is, and also displays a countdown during the endgame
+class Nancy5Clock : public RenderObject {
+public:
+	Nancy5Clock() : RenderObject(10) {}
+	virtual ~Nancy5Clock() = default;
+
+	void init() override;
+	void updateGraphics() override;
+
+private:
+	int32 _currentDay = -1;
+	int32 _countdownProgress = -1;
+
+	const CLOK *_clockData = nullptr;
+};
+
 } // End of namespace UI
 } // End of namespace Nancy
 


Commit: 4cc3e98362965382059244e4430793356603256e
    https://github.com/scummvm/scummvm/commit/4cc3e98362965382059244e4430793356603256e
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2023-08-31T12:20:40+03:00

Commit Message:
NANCY: Destroy Scene when winning/losing game

This makes sure the player can't press Continue game
after winning/losing the game.

Changed paths:
    engines/nancy/action/recordtypes.cpp
    engines/nancy/state/scene.cpp
    engines/nancy/state/scene.h


diff --git a/engines/nancy/action/recordtypes.cpp b/engines/nancy/action/recordtypes.cpp
index c79c3092617..75ba07e1e08 100644
--- a/engines/nancy/action/recordtypes.cpp
+++ b/engines/nancy/action/recordtypes.cpp
@@ -471,6 +471,7 @@ void LoseGame::readData(Common::SeekableReadStream &stream) {
 
 void LoseGame::execute() {
 	g_nancy->_sound->stopAndUnloadSpecificSounds();
+	NancySceneState.setDestroyOnExit();
 
 	if (!ConfMan.hasKey("original_menus") || ConfMan.getBool("original_menus")) {
 		g_nancy->setState(NancyState::kMainMenu);
@@ -507,6 +508,7 @@ void WinGame::readData(Common::SeekableReadStream &stream) {
 
 void WinGame::execute() {
 	g_nancy->_sound->stopAndUnloadSpecificSounds();
+	NancySceneState.setDestroyOnExit();
 	g_nancy->setState(NancyState::kCredits, NancyState::kMainMenu);
 
 	_isDone = true;
diff --git a/engines/nancy/state/scene.cpp b/engines/nancy/state/scene.cpp
index 808566034b2..5bb6b3b0ce0 100644
--- a/engines/nancy/state/scene.cpp
+++ b/engines/nancy/state/scene.cpp
@@ -118,7 +118,8 @@ Scene::Scene() :
 		_actionManager(),
 		_difficulty(0),
 		_activeConversation(nullptr),
-		_lightning(nullptr) {}
+		_lightning(nullptr),
+		_destroyOnExit(false) {}
 
 Scene::~Scene()  {
 	delete _helpButton;
@@ -210,7 +211,7 @@ bool Scene::onStateExit(const NancyState::NancyState nextState) {
 		_clock->registerGraphics();
 	}
 
-	return false;
+	return _destroyOnExit;
 }
 
 void Scene::changeScene(const SceneChangeDescription &sceneDescription) {
diff --git a/engines/nancy/state/scene.h b/engines/nancy/state/scene.h
index bb73b670a19..354b5b16d71 100644
--- a/engines/nancy/state/scene.h
+++ b/engines/nancy/state/scene.h
@@ -119,6 +119,9 @@ public:
 	void onStateEnter(const NancyState::NancyState prevState) override;
 	bool onStateExit(const NancyState::NancyState nextState) override;
 
+	// Used when winning/losing game
+	void setDestroyOnExit() { _destroyOnExit = true; }
+
 	void changeScene(const SceneChangeDescription &sceneDescription);
 	void pushScene();
 	void popScene();
@@ -279,6 +282,8 @@ private:
 	// Contains a screenshot of the Scene state from the last time it was exited
 	Graphics::ManagedSurface _lastScreenshot;
 
+	bool _destroyOnExit;
+
 	State _state;
 };
 


Commit: aa004711136a578ec78232ef2adcecea717b03b5
    https://github.com/scummvm/scummvm/commit/aa004711136a578ec78232ef2adcecea717b03b5
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2023-08-31T12:20:40+03:00

Commit Message:
NANCY Fix #define name

Changed paths:
    engines/nancy/action/towerpuzzle.h


diff --git a/engines/nancy/action/towerpuzzle.h b/engines/nancy/action/towerpuzzle.h
index b4847812133..6f2159e7c1f 100644
--- a/engines/nancy/action/towerpuzzle.h
+++ b/engines/nancy/action/towerpuzzle.h
@@ -19,8 +19,8 @@
  *
  */
 
-#ifndef NANCY_ACTION_TOWERIPPEDLETTERPUZZLE_H
-#define NANCY_ACTION_TOWERIPPEDLETTERPUZZLE_H
+#ifndef NANCY_ACTION_TOWERPUZZLE_H
+#define NANCY_ACTION_TOWERPUZZLE_H
 
 #include "engines/nancy/action/actionrecord.h"
 
@@ -78,4 +78,4 @@ protected:
 } // End of namespace Action
 } // End of namespace Nancy
 
-#endif // NANCY_ACTION_TOWERIPPEDLETTERPUZZLE_H
+#endif // NANCY_ACTION_TOWERPUZZLE_H


Commit: b174006c5bfa9b4bd2b87eda377ab5b07d9d31b5
    https://github.com/scummvm/scummvm/commit/b174006c5bfa9b4bd2b87eda377ab5b07d9d31b5
Author: Kaloyan Chehlarski (strahy at outlook.com)
Date: 2023-08-31T12:20:40+03:00

Commit Message:
NANCY: Implement TurningPuzzle

Implemented the puzzle type that handles the sun/moon
and staircase spindle puzzles in nancy3.

Changed paths:
  A engines/nancy/action/turningpuzzle.cpp
  A engines/nancy/action/turningpuzzle.h
    engines/nancy/action/arfactory.cpp
    engines/nancy/module.mk


diff --git a/engines/nancy/action/arfactory.cpp b/engines/nancy/action/arfactory.cpp
index e58d29af038..e1625dd3183 100644
--- a/engines/nancy/action/arfactory.cpp
+++ b/engines/nancy/action/arfactory.cpp
@@ -38,6 +38,7 @@
 #include "engines/nancy/action/soundequalizerpuzzle.h"
 #include "engines/nancy/action/setplayerclock.h"
 #include "engines/nancy/action/raycastpuzzle.h"
+#include "engines/nancy/action/turningpuzzle.h"
 
 #include "engines/nancy/state/scene.h"
 
@@ -201,6 +202,8 @@ ActionRecord *ActionManager::createActionRecord(uint16 type) {
 		return new RaycastPuzzle();
 	case 208:
 		return new OrderingPuzzle(OrderingPuzzle::PuzzleType::kPiano);
+	case 209:
+		return new TurningPuzzle();
 	default:
 		error("Action Record type %i is invalid!", type);
 		return nullptr;
diff --git a/engines/nancy/action/turningpuzzle.cpp b/engines/nancy/action/turningpuzzle.cpp
new file mode 100644
index 00000000000..ffb6d0ca151
--- /dev/null
+++ b/engines/nancy/action/turningpuzzle.cpp
@@ -0,0 +1,308 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "engines/nancy/util.h"
+#include "engines/nancy/nancy.h"
+#include "engines/nancy/graphics.h"
+#include "engines/nancy/resource.h"
+#include "engines/nancy/sound.h"
+#include "engines/nancy/input.h"
+#include "engines/nancy/puzzledata.h"
+#include "engines/nancy/state/scene.h"
+
+#include "engines/nancy/action/turningpuzzle.h"
+
+namespace Nancy {
+namespace Action {
+
+void TurningPuzzle::init() {
+	Common::Rect screenBounds = NancySceneState.getViewport().getBounds();
+	_drawSurface.create(screenBounds.width(), screenBounds.height(), g_nancy->_graphicsManager->getInputPixelFormat());
+	_drawSurface.clear(g_nancy->_graphicsManager->getTransColor());
+	setTransparent(true);
+	setVisible(true);
+	moveTo(screenBounds);
+
+	g_nancy->_resource->loadImage(_imageName, _image);
+	registerGraphics();
+}
+
+void TurningPuzzle::updateGraphics() {
+	if (_state == kBegin) {
+		return;
+	}
+
+	if (_solveState == kWaitForAnimation) {
+		if (g_nancy->getTotalPlayTime() > _nextTurnTime) {
+			_nextTurnTime = g_nancy->getTotalPlayTime() + (_solveDelayBetweenTurns * 1000 / _currentOrder.size());
+
+			if (	(_turnFrameID == 0 && _solveAnimFace == 0) ||
+					(_turnFrameID == 1 && _solveAnimFace > 0 && (int)_solveAnimFace < _numFaces - 1)) {
+				g_nancy->_sound->playSound(_turnSound);
+			}
+
+			if (_turnFrameID >= _numFramesPerTurn) {
+				++_solveAnimFace;
+				_turnFrameID = 0;
+				_nextTurnTime += 1000 * _solveDelayBetweenTurns;
+			}
+
+			for (uint i = 0; i < _currentOrder.size(); ++i) {
+				uint faceID = _currentOrder[i] + _solveAnimFace;
+				if (faceID >= _numFaces) {
+					faceID -= _numFaces;
+				}
+
+				drawObject(i, faceID, _turnFrameID);
+			}
+			
+			if ((int)_solveAnimFace >= _numFaces - 1) {
+				_solveAnimFace = 0;
+				++_solveAnimLoop;
+
+				if (_solveAnimLoop >= _solveAnimationNumRepeats) {
+					_solveState = kWaitBeforeSound;
+					_objectCurrentlyTurning = -1;
+				}
+			}
+
+			++_turnFrameID;
+		}
+
+		return;
+	}
+
+	if (_objectCurrentlyTurning != -1) {
+		if (g_nancy->getTotalPlayTime() > _nextTurnTime) {
+			_nextTurnTime = g_nancy->getTotalPlayTime() + (_solveDelayBetweenTurns * 1000 / _currentOrder.size());
+			++_turnFrameID;
+			
+			uint faceID = _currentOrder[_objectCurrentlyTurning];
+			uint frameID = _turnFrameID;
+
+			if (frameID == _numFramesPerTurn && (int)faceID == _numFaces - 1) {
+				faceID = frameID = 0;
+			}
+
+			// Draw clicked spindle
+			drawObject(_objectCurrentlyTurning, faceID, frameID);
+
+			// Draw linked spindles
+			for (uint i = 0; i < _links[_objectCurrentlyTurning].size(); ++i) {
+				faceID = _currentOrder[_links[_objectCurrentlyTurning][i] - 1];
+				frameID = _turnFrameID;
+
+				if (frameID == _numFramesPerTurn && (int)faceID == _numFaces - 1) {
+					faceID = frameID = 0;
+				}
+
+				drawObject(_links[_objectCurrentlyTurning][i] - 1, faceID, frameID);
+			}
+
+			if (_turnFrameID >= _numFramesPerTurn) {
+				turnLogic(_objectCurrentlyTurning);
+				_objectCurrentlyTurning = -1;
+				_turnFrameID = 0;
+				_nextTurnTime = 0;
+			}
+		}
+	}
+}
+
+void TurningPuzzle::readData(Common::SeekableReadStream &stream) {
+	readFilename(stream, _imageName);
+	uint numSpindles = stream.readUint16LE();
+	_numFaces = stream.readUint16LE();
+	_numFramesPerTurn = stream.readUint16LE();
+	
+	_startPositions.resize(numSpindles);
+	for (uint i = 0; i < numSpindles; ++i) {
+		_startPositions[i] = stream.readUint16LE();
+	}
+	stream.skip((16 - numSpindles) * 2);
+
+	readRectArray(stream, _destRects, numSpindles);
+	stream.skip((16 - numSpindles) * 16);
+
+	readRectArray(stream, _hotspots, numSpindles);
+	stream.skip((16 - numSpindles) * 16);
+
+	_separateRows = stream.readByte();
+
+	_startPos.x = stream.readSint32LE();
+	_startPos.y = stream.readSint32LE();
+	_srcIncrement.x = stream.readSint16LE();
+	_srcIncrement.y = stream.readSint16LE();
+	
+	_links.resize(numSpindles);
+	for (uint i = 0; i < numSpindles; ++i) {
+		for (uint j = 0; j < 4; ++j) {
+			uint16 val = stream.readUint16LE();
+			if (val == 0) {
+				break;
+			}
+
+			_links[i].push_back(val);
+		}
+
+		if (_links[i].size() < 4) {
+			stream.skip((4 - _links[i].size() - 1) * 2);
+		}
+	}
+
+	stream.skip((16 - numSpindles) * 4 * 2);
+
+	_solveDelayBetweenTurns = stream.readUint16LE();
+	_solveAnimate = stream.readByte();
+	_solveAnimationNumRepeats = stream.readUint16LE();
+
+	_turnSound.readNormal(stream);
+
+	_correctOrder.resize(numSpindles);
+	for (uint i = 0; i < numSpindles; ++i) {
+		_correctOrder[i] = stream.readUint16LE();
+	}
+	stream.skip((16 - numSpindles) * 2);
+
+	_solveScene.readData(stream);
+	_solveSoundDelayTime = stream.readUint16LE();
+	_solveSound.readNormal(stream);
+
+	_exitScene.readData(stream);
+	readRect(stream, _exitHotspot);
+}
+
+void TurningPuzzle::execute() {
+	switch (_state) {
+	case kBegin :
+		init();
+		g_nancy->_sound->loadSound(_turnSound);
+		_currentOrder = _startPositions;
+		for (uint i = 0; i < _currentOrder.size(); ++i) {
+			drawObject(i, _currentOrder[i], 0);
+		}
+		_state = kRun;
+		// fall through
+	case kRun :
+		if (_objectCurrentlyTurning != -1) {
+			return;
+		}
+
+		if (_currentOrder == _correctOrder) {
+			_state = kActionTrigger;
+			_solveState = _solveAnimate ? kWaitForAnimation : kWaitForSound;
+			_objectCurrentlyTurning = -1;
+			_turnFrameID = 0;
+			_nextTurnTime = g_nancy->getTotalPlayTime() + (_solveDelayBetweenTurns * 1000 / _currentOrder.size());
+		}
+
+		break;
+	case kActionTrigger :
+		switch (_solveState) {
+		case kWaitForAnimation :
+			if (_nextTurnTime == 0) {
+				_solveState = kWaitForSound;
+			}
+			return;
+		case kWaitBeforeSound :
+			if (_soundDelayTime == 0) {
+				_soundDelayTime = g_nancy->getTotalPlayTime() + (_soundDelayTime * 1000);
+			} else if (g_nancy->getTotalPlayTime() > _soundDelayTime) {
+				g_nancy->_sound->loadSound(_solveSound);
+				g_nancy->_sound->playSound(_solveSound);
+				NancySceneState.setEventFlag(_solveScene._flag);
+				_solveState = kWaitForSound;
+			}
+			
+			return;
+		case kWaitForSound :
+			if (g_nancy->_sound->isSoundPlaying(_solveSound) || g_nancy->_sound->isSoundPlaying(_turnSound)) {
+				return;
+			}
+
+			NancySceneState.changeScene(_solveScene._sceneChange);
+			break;
+		case kNotSolved :
+			_exitScene.execute();
+		}
+
+		g_nancy->_sound->stopSound(_turnSound);
+		g_nancy->_sound->stopSound(_solveSound);
+		finishExecution();
+	}
+}
+
+void TurningPuzzle::handleInput(NancyInput &input) {
+	if (NancySceneState.getViewport().convertViewportToScreen(_exitHotspot).contains(input.mousePos)) {
+		g_nancy->_cursorManager->setCursorType(CursorManager::kExit);
+
+		if (input.input & NancyInput::kLeftMouseButtonUp) {
+			_state = kActionTrigger;
+		}
+
+		return;
+	}
+
+	for (uint i = 0; i < _hotspots.size(); ++i) {
+		if (NancySceneState.getViewport().convertViewportToScreen(_hotspots[i]).contains(input.mousePos)) {
+			g_nancy->_cursorManager->setCursorType(CursorManager::kHotspot);
+
+			if (_objectCurrentlyTurning != -1) {
+				break;
+			}
+
+			if (input.input & NancyInput::kLeftMouseButtonUp) {
+				g_nancy->_sound->playSound(_turnSound);
+				_objectCurrentlyTurning = i;
+			}
+
+			return;
+		}
+	}
+}
+
+void TurningPuzzle::drawObject(uint objectID, uint faceID, uint frameID) {
+	Common::Rect srcRect = _destRects[objectID];
+	srcRect.moveTo(_startPos);
+	Common::Point inc(_srcIncrement.x == 1 ? srcRect.width() : _srcIncrement.x, _srcIncrement.y == -2 ? srcRect.height() : _srcIncrement.y);
+	srcRect.translate(	inc.x * frameID + inc.x * _numFramesPerTurn * faceID,
+						_separateRows ? inc.y * objectID : 0);
+	
+	_drawSurface.blitFrom(_image, srcRect, _destRects[objectID]);
+	_needsRedraw = true;
+}
+
+void TurningPuzzle::turnLogic(uint objectID) {
+	++_currentOrder[objectID];
+	if (_currentOrder[objectID] >= _numFaces) {
+		_currentOrder[objectID] = 0;
+	}
+
+	for (uint j = 0; j < _links[objectID].size(); ++j) {
+		++_currentOrder[_links[objectID][j] - 1];
+		if (_currentOrder[_links[objectID][j] - 1] >= _numFaces) {
+			_currentOrder[_links[objectID][j] - 1] = 0;
+		}
+	}
+}
+
+} // End of namespace Action
+} // End of namespace Nancy
diff --git a/engines/nancy/action/turningpuzzle.h b/engines/nancy/action/turningpuzzle.h
new file mode 100644
index 00000000000..72dd3c19149
--- /dev/null
+++ b/engines/nancy/action/turningpuzzle.h
@@ -0,0 +1,102 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef NANCY_ACTION_TURNINGPUZZLE_H
+#define NANCY_ACTION_TURNINGPUZZLE_H
+
+#include "engines/nancy/action/actionrecord.h"
+
+namespace Nancy {
+namespace Action {
+
+// Handles a specific type of puzzle where clicking an object rotates it,
+// as well as several other objects linked to it. Examples are the sun/moon
+// and staircase spindle puzzles in nancy3
+class TurningPuzzle : public RenderActionRecord {
+public:
+	enum SolveState { kNotSolved, kWaitForAnimation, kWaitBeforeSound, kWaitForSound };
+	TurningPuzzle() : RenderActionRecord(7) {}
+	virtual ~TurningPuzzle() {}
+
+	void init() override;
+	void updateGraphics() override;
+
+	void readData(Common::SeekableReadStream &stream) override;
+	void execute() override;
+	void handleInput(NancyInput &input) override;
+
+
+protected:
+	Common::String getRecordTypeName() const override { return "TurningPuzzle"; }
+	bool isViewportRelative() const override { return true; }
+
+	void drawObject(uint objectID, uint faceID, uint frameID);
+	void turnLogic(uint objectID);
+
+	Common::String _imageName;
+
+	uint16 _numFaces = 0;
+	uint16 _numFramesPerTurn = 0;
+
+	Common::Array<Common::Rect> _destRects;
+	Common::Array<Common::Rect> _hotspots;
+	Common::Array<uint16> _startPositions;
+
+	bool _separateRows = false;
+
+	Common::Point _startPos;
+	Common::Point _srcIncrement;
+
+	Common::Array<Common::Array<uint16>> _links;
+
+	uint16 _solveDelayBetweenTurns = 0;
+	bool _solveAnimate = false;
+	uint16 _solveAnimationNumRepeats = 0;
+
+	SoundDescription _turnSound;
+
+	Common::Array<uint16> _correctOrder;
+
+	SceneChangeWithFlag _solveScene;
+	uint16 _soundDelayTime = 0;
+	SoundDescription _solveSound;
+
+	SceneChangeWithFlag _exitScene;
+	Common::Rect _exitHotspot;
+
+	Graphics::ManagedSurface _image;
+	Common::Array<uint16> _currentOrder;
+
+	uint32 _solveSoundDelayTime = 0;
+	uint32 _nextTurnTime = 0;
+	int32 _objectCurrentlyTurning = -1;
+	uint32 _turnFrameID = 0;
+
+	uint32 _solveAnimLoop = 0;
+	uint32 _solveAnimFace = 0;
+
+	SolveState _solveState = kNotSolved;
+};
+
+} // End of namespace Action
+} // End of namespace Nancy
+
+#endif // NANCY_ACTION_TURNINGPUZZLE_H
diff --git a/engines/nancy/module.mk b/engines/nancy/module.mk
index e0ccbad0d37..9ce5418defd 100644
--- a/engines/nancy/module.mk
+++ b/engines/nancy/module.mk
@@ -22,6 +22,7 @@ MODULE_OBJS = \
   action/sliderpuzzle.o \
   action/soundequalizerpuzzle.o \
   action/towerpuzzle.o \
+  action/turningpuzzle.o \
   action/telephone.o \
   ui/fullscreenimage.o \
   ui/animatedbutton.o \




More information about the Scummvm-git-logs mailing list