[Scummvm-git-logs] scummvm master -> 63684ea1cf67d00931d19d95c3eeb941c3b6745c

sev- noreply at scummvm.org
Sun Nov 13 23:27:42 UTC 2022


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

Summary:
8b5c5d9b85 SAGA: Mark Amiga as big-endian
8809f2db79 SAGA: Make loadStrings accept configurable endianness
1dd16ea8be SAGA: Move intro description to detection_tables.h
64241d1657 SAGA: Add new flags to specify AGA and ECS graphics
e8643e41de SAGA: Allow working without sound
8ff65b22cc SAGA: Introduce flag for differentiating mask and dissolve background image
ee8151e007 SAGA: Support decoding AGA and ECS graphics
03c1d029a1 SAGA: Make unknown scene descriptor size an error
5a431670d4 SAGA: Disable music on Amiga
8fde889532 SAGA: Support reading Amiga resources
0c56fe819a SAGA: Treat resources with "ECHO is on\r\n" as invalid
f90c541b9b SAGA: Use screen height if bgmask height is zero
9fae5e4efd SAGA: Load module strings as little-endian
002ec9cf03 SAGA: Adjust isNonInteractiveDemo for Amiga
63684ea1cf SAGA: Add detection entries for ITE Amiga CD-ROMs


Commit: 8b5c5d9b85dc8879a676511b637b49c98d44320b
    https://github.com/scummvm/scummvm/commit/8b5c5d9b85dc8879a676511b637b49c98d44320b
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2022-11-14T00:27:33+01:00

Commit Message:
SAGA: Mark Amiga as big-endian

Changed paths:
    engines/saga/metaengine.cpp


diff --git a/engines/saga/metaengine.cpp b/engines/saga/metaengine.cpp
index 5071bae263d..9a7ae97977f 100644
--- a/engines/saga/metaengine.cpp
+++ b/engines/saga/metaengine.cpp
@@ -41,7 +41,7 @@
 
 namespace Saga {
 
-bool SagaEngine::isBigEndian() const { return isMacResources() && getGameId() == GID_ITE; }
+bool SagaEngine::isBigEndian() const { return (isMacResources() || (getPlatform() == Common::kPlatformAmiga)) && getGameId() == GID_ITE; }
 bool SagaEngine::isMacResources() const { return (getPlatform() == Common::kPlatformMacintosh); }
 const GameResourceDescription *SagaEngine::getResourceDescription() const { return _gameDescription->resourceDescription; }
 


Commit: 8809f2db799756fedef91be09e6eb39b14a0e0a2
    https://github.com/scummvm/scummvm/commit/8809f2db799756fedef91be09e6eb39b14a0e0a2
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2022-11-14T00:27:33+01:00

Commit Message:
SAGA: Make loadStrings accept configurable endianness

On Amiga releases some files use LE and others BE, so allow to specify
it manually

Changed paths:
    engines/saga/actor.cpp
    engines/saga/resource_res.cpp
    engines/saga/saga.cpp
    engines/saga/saga.h
    engines/saga/scene.cpp
    engines/saga/script.cpp


diff --git a/engines/saga/actor.cpp b/engines/saga/actor.cpp
index 95c3df8cc06..29d1c4b7eed 100644
--- a/engines/saga/actor.cpp
+++ b/engines/saga/actor.cpp
@@ -248,7 +248,7 @@ Actor::Actor(SagaEngine *vm) : _vm(vm) {
 
 		_vm->_resource->loadResource(_actorContext, _vm->getResourceDescription()->actorsStringsResourceId, stringsData);
 
-		_vm->loadStrings(_actorsStrings, stringsData);
+		_vm->loadStrings(_actorsStrings, stringsData, _vm->isBigEndian());
 	}
 
 	if (_vm->getGameId() == GID_ITE) {
diff --git a/engines/saga/resource_res.cpp b/engines/saga/resource_res.cpp
index 5fb6a93aa3d..1f1bf76ef2c 100644
--- a/engines/saga/resource_res.cpp
+++ b/engines/saga/resource_res.cpp
@@ -100,7 +100,7 @@ void Resource_RES::loadGlobalResources(int chapter, int actorsEntrance) {
 	_vm->_actor->_objectsStrings.clear();
 
 	_vm->_resource->loadResource(resourceContext, _metaResource.objectsStringsResourceID, resourceData);
-	_vm->loadStrings(_vm->_actor->_objectsStrings, resourceData);
+	_vm->loadStrings(_vm->_actor->_objectsStrings, resourceData, _vm->isBigEndian());
 
 	if (uint(chapter) >= _vm->_sndRes->_fxTableIDs.size()) {
 		error("Chapter ID exceeds fxTableIDs length");
@@ -131,7 +131,7 @@ void Resource_RES::loadGlobalResources(int chapter, int actorsEntrance) {
 	_vm->_actor->_actorsStrings.clear();
 
 	_vm->_resource->loadResource(resourceContext, _metaResource.actorsStringsResourceID, resourceData);
-	_vm->loadStrings(_vm->_actor->_actorsStrings, resourceData);
+	_vm->loadStrings(_vm->_actor->_actorsStrings, resourceData, _vm->isBigEndian());
 
 	_vm->_sprite->_inventorySprites.clear();
 	_vm->_sprite->loadList(_metaResource.inventorySpritesID, _vm->_sprite->_inventorySprites);
diff --git a/engines/saga/saga.cpp b/engines/saga/saga.cpp
index 143658e12f9..f3c4c77a3bf 100644
--- a/engines/saga/saga.cpp
+++ b/engines/saga/saga.cpp
@@ -370,7 +370,7 @@ Common::Error SagaEngine::run() {
 	return Common::kNoError;
 }
 
-void SagaEngine::loadStrings(StringsTable &stringsTable, const ByteArray &stringsData) {
+void SagaEngine::loadStrings(StringsTable &stringsTable, const ByteArray &stringsData, bool isBigEndian) {
 	uint16 stringsCount;
 	size_t offset;
 	size_t prevOffset = 0;
@@ -382,7 +382,7 @@ void SagaEngine::loadStrings(StringsTable &stringsTable, const ByteArray &string
 	}
 
 
-	ByteArrayReadStreamEndian scriptS(stringsData, isBigEndian()); //TODO: get endianess from context
+	ByteArrayReadStreamEndian scriptS(stringsData, isBigEndian);
 
 	offset = scriptS.readUint16();
 	stringsCount = offset / 2;
diff --git a/engines/saga/saga.h b/engines/saga/saga.h
index 497170fa440..e004b33fe0d 100644
--- a/engines/saga/saga.h
+++ b/engines/saga/saga.h
@@ -476,7 +476,7 @@ public:
 
 		return &imageData.front() + SAGA_IMAGE_HEADER_LEN;
 	}
-	void loadStrings(StringsTable &stringsTable, const ByteArray &stringsData);
+	void loadStrings(StringsTable &stringsTable, const ByteArray &stringsData, bool isBigEndian);
 
 	const char *getObjectName(uint16 objectId) const;
 public:
diff --git a/engines/saga/scene.cpp b/engines/saga/scene.cpp
index 1da5c18c20c..d9216c37bd8 100644
--- a/engines/saga/scene.cpp
+++ b/engines/saga/scene.cpp
@@ -983,7 +983,7 @@ void Scene::processSceneResources(SceneResourceDataArray &resourceList) {
 			break;
 		case SAGA_STRINGS:
 			debug(3, "Loading scene strings resource...");
-			_vm->loadStrings(_sceneStrings, resourceData);
+			_vm->loadStrings(_sceneStrings, resourceData, _vm->isBigEndian());
 			break;
 		case SAGA_OBJECT_MAP:
 			debug(3, "Loading object map resource...");
diff --git a/engines/saga/script.cpp b/engines/saga/script.cpp
index 47235cf253d..b583886a9ff 100644
--- a/engines/saga/script.cpp
+++ b/engines/saga/script.cpp
@@ -125,7 +125,7 @@ SAGA1Script::SAGA1Script(SagaEngine *vm) : Script(vm) {
 
 	_vm->_resource->loadResource(resourceContext, _vm->getResourceDescription()->mainStringsResourceId, stringsData);
 
-	_vm->loadStrings(_mainStrings, stringsData);
+	_vm->loadStrings(_mainStrings, stringsData, _vm->isBigEndian());
 
 	setupScriptOpcodeList();
 
@@ -906,7 +906,7 @@ void Script::loadModule(uint scriptModuleNumber) {
 
 	_vm->_resource->loadResource(_scriptContext, _modules[scriptModuleNumber].stringsResourceId, resourceData);
 
-	_vm->loadStrings(_modules[scriptModuleNumber].strings, resourceData);
+	_vm->loadStrings(_modules[scriptModuleNumber].strings, resourceData, _vm->isBigEndian());
 
 	if (_modules[scriptModuleNumber].voicesResourceId > 0) {
 		_vm->_resource->loadResource(_scriptContext, _modules[scriptModuleNumber].voicesResourceId, resourceData);


Commit: 1dd16ea8be983f19949e8e9e730e79374a0c92a9
    https://github.com/scummvm/scummvm/commit/1dd16ea8be983f19949e8e9e730e79374a0c92a9
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2022-11-14T00:27:33+01:00

Commit Message:
SAGA: Move intro description to detection_tables.h

Literally all Amiga releases so far have different resource IDs, it's
unreasonable by now to make introproc_ite.cpp re-recognize those versions.
Just pass parameters along.

Changed paths:
    engines/saga/detection.h
    engines/saga/detection_tables.h
    engines/saga/introproc_ite.cpp
    engines/saga/saga.h
    engines/saga/scene.h
    engines/saga/shared_detection_defines.h


diff --git a/engines/saga/detection.h b/engines/saga/detection.h
index fea1b762e52..fd3b0e60e0b 100644
--- a/engines/saga/detection.h
+++ b/engines/saga/detection.h
@@ -86,6 +86,7 @@ enum GameFileTypes {
 	GAME_PATCHFILE        = 1 << 10    // IHNM patch file (patch.re_/patch.res)
 };
 
+struct LoadSceneParams;
 struct SAGAGameDescription {
 	ADGameDescription desc;
 
@@ -96,8 +97,11 @@ struct SAGAGameDescription {
 	int fontsCount;
 	const GameFontDescription *fontDescriptions;
 	const GamePatchDescription *patchDescriptions;
+	const LoadSceneParams *introScenes;
 };
 
+extern LoadSceneParams ITE_IntroListDefault[];
+
 } // End of namespace Saga
 
 #endif // SAGA_DETECTION_H
diff --git a/engines/saga/detection_tables.h b/engines/saga/detection_tables.h
index cbdcef05c32..e41bb20fa2a 100644
--- a/engines/saga/detection_tables.h
+++ b/engines/saga/detection_tables.h
@@ -114,6 +114,42 @@ static const GameFontDescription IHNMDEMO_GameFonts[]   = { {2}, {3}, {4} };
 // Font 6 is kIHNMFont8, font 8 is kIHNMMainFont
 static const GameFontDescription IHNMCD_GameFonts[]     = { {2}, {3}, {4}, {5}, {6}, {7}, {8} };
 
+// Intro scenes
+#define RID_ITE_INTRO_ANIM_SCENE 1538
+#define RID_ITE_CAVE_SCENE_1 1542
+#define RID_ITE_CAVE_SCENE_2 1545
+#define RID_ITE_CAVE_SCENE_3 1548
+#define RID_ITE_CAVE_SCENE_4 1551
+#define RID_ITE_VALLEY_SCENE 1556
+#define RID_ITE_TREEHOUSE_SCENE 1560
+#define RID_ITE_FAIREPATH_SCENE 1564
+#define RID_ITE_FAIRETENT_SCENE 1567
+
+// Intro scenes - DOS demo
+#define RID_ITE_INTRO_ANIM_SCENE_DOS_DEMO 298
+#define RID_ITE_CAVE_SCENE_DOS_DEMO 302
+#define RID_ITE_VALLEY_SCENE_DOS_DEMO 310
+
+LoadSceneParams ITE_IntroListDefault[] = {
+	{RID_ITE_INTRO_ANIM_SCENE, kLoadByResourceId, SceneHandlers::SC_ITEIntroAnimProc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE},
+	{RID_ITE_CAVE_SCENE_1, kLoadByResourceId, SceneHandlers::SC_ITEIntroCave1Proc, false, kTransitionFade, 0, NO_CHAPTER_CHANGE},
+	{RID_ITE_CAVE_SCENE_2, kLoadByResourceId, SceneHandlers::SC_ITEIntroCave2Proc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE},
+	{RID_ITE_CAVE_SCENE_3, kLoadByResourceId, SceneHandlers::SC_ITEIntroCave3Proc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE},
+	{RID_ITE_CAVE_SCENE_4, kLoadByResourceId, SceneHandlers::SC_ITEIntroCave4Proc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE},
+	{RID_ITE_VALLEY_SCENE, kLoadByResourceId, SceneHandlers::SC_ITEIntroValleyProc, false, kTransitionFade, 0, NO_CHAPTER_CHANGE},
+	{RID_ITE_TREEHOUSE_SCENE, kLoadByResourceId, SceneHandlers::SC_ITEIntroTreeHouseProc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE},
+	{RID_ITE_FAIREPATH_SCENE, kLoadByResourceId, SceneHandlers::SC_ITEIntroFairePathProc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE},
+	{RID_ITE_FAIRETENT_SCENE, kLoadByResourceId, SceneHandlers::SC_ITEIntroFaireTentProc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE},
+	{0, kLoadByResourceId, nullptr, false, kTransitionNoFade, 0, 0}
+};
+
+static const LoadSceneParams ITE_DOS_Demo_IntroList[] = {
+	{RID_ITE_INTRO_ANIM_SCENE_DOS_DEMO, kLoadByResourceId, SceneHandlers::SC_ITEIntroAnimProc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE},
+	{RID_ITE_CAVE_SCENE_DOS_DEMO, kLoadByResourceId, SceneHandlers::SC_ITEIntroCaveDemoProc, false, kTransitionFade, 0, NO_CHAPTER_CHANGE},
+	{RID_ITE_VALLEY_SCENE_DOS_DEMO, kLoadByResourceId, SceneHandlers::SC_ITEIntroValleyProc, false, kTransitionFade, 0, NO_CHAPTER_CHANGE},
+	{0, kLoadByResourceId, nullptr, false, kTransitionNoFade, 0, 0}
+};
+
 // Patch files. Files not found will be ignored
 static const GamePatchDescription ITEPatch_Files[] = {
 	{       "cave.mid", GAME_RESOURCEFILE,    9},
@@ -203,6 +239,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		ARRAYSIZE(ITEDEMO_GameFonts),
 		ITEDEMO_GameFonts,
 		NULL,
+		ITE_DOS_Demo_IntroList,
 	},
 
 	// Inherit the earth - MAC Demo version
@@ -227,6 +264,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		ARRAYSIZE(ITEWINDEMO_GameFonts),
 		ITEWINDEMO_GameFonts,
 		ITEMacPatch_Files,
+		ITE_IntroListDefault,
 	},
 
 
@@ -253,6 +291,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		ARRAYSIZE(ITEWINDEMO_GameFonts),
 		ITEWINDEMO_GameFonts,
 		ITEMacPatch_Files,
+		ITE_IntroListDefault,
 	},
 
 
@@ -279,6 +318,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		ARRAYSIZE(ITEWINDEMO_GameFonts),
 		ITEWINDEMO_GameFonts,
 		ITEPatch_Files,
+		ITE_IntroListDefault,
 	},
 
 
@@ -305,6 +345,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		ARRAYSIZE(ITEWINDEMO_GameFonts),
 		ITEWINDEMO_GameFonts,
 		ITEPatch_Files,
+		ITE_IntroListDefault,
 	},
 
 
@@ -338,6 +379,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		ARRAYSIZE(ITEWINDEMO_GameFonts),
 		ITEWINDEMO_GameFonts,
 		NULL,
+		ITE_IntroListDefault,
 	},
 
 	// Inherit the earth - MAC CD First edition
@@ -365,6 +407,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		ARRAYSIZE(ITEWINDEMO_GameFonts),
 		ITEWINDEMO_GameFonts,
 		NULL,
+		ITE_IntroListDefault,
 	},
 
 	// Inherit the earth - MAC CD Wyrmkeep version
@@ -389,6 +432,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		ARRAYSIZE(ITEWINDEMO_GameFonts),
 		ITEWINDEMO_GameFonts,
 		ITEMacPatch_Files,
+		ITE_IntroListDefault,
 	},
 
 	// Inherit the earth - MAC CD GOG version 1.1
@@ -413,6 +457,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		ARRAYSIZE(ITE_GameFonts),
 		ITE_GameFonts,
 		NULL,
+		ITE_IntroListDefault,
 	},
 
 
@@ -445,6 +490,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		ARRAYSIZE(ITE_GameFonts),
 		ITE_GameFonts,
 		NULL,
+		ITE_IntroListDefault,
 	},
 
 	// Inherit the earth - German Wyrmkeep combined Windows/Mac/Linux CD
@@ -472,6 +518,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		ARRAYSIZE(ITE_GameFonts),
 		ITE_GameFonts,
 		NULL,
+		ITE_IntroListDefault,
 	},
 
 	// Inherit the earth - Italian Wyrmkeep combined Windows/Mac/Linux CD (fan translation)
@@ -503,6 +550,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		ARRAYSIZE(ITE_GameFonts),
 		ITE_GameFonts,
 		NULL,
+		ITE_IntroListDefault,
 	},
 
 	// Inherit the earth - Wyrmkeep Windows CD version
@@ -529,6 +577,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		ARRAYSIZE(ITE_GameFonts),
 		ITE_GameFonts,
 		ITEPatch_Files,
+		ITE_IntroListDefault,
 	},
 
 	// Inherit the earth - Wyrmkeep Linux CD version
@@ -555,6 +604,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		ARRAYSIZE(ITE_GameFonts),
 		ITE_GameFonts,
 		ITEPatch_Files,
+		ITE_IntroListDefault,
 	},
 
 	// Inherit the earth - DOS CD version - 17-06-1994
@@ -580,6 +630,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		ARRAYSIZE(ITE_GameFonts),
 		ITE_GameFonts,
 		ITEPatch_Files,
+		ITE_IntroListDefault,
 	},
 
 	// Inherit the earth - Wyrmkeep Italian Windows CD version (fan translation)
@@ -605,6 +656,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		ARRAYSIZE(ITE_GameFonts),
 		ITE_GameFonts,
 		ITEPatch_Files,
+		ITE_IntroListDefault,
 	},
 
 	// Inherit the earth - Wyrmkeep Italian Linux CD version (fan translation)
@@ -630,6 +682,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		ARRAYSIZE(ITE_GameFonts),
 		ITE_GameFonts,
 		ITEPatch_Files,
+		ITE_IntroListDefault,
 	},
 
 	// Inherit the earth - Italian DOS CD version (fan translation)
@@ -654,6 +707,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		ARRAYSIZE(ITE_GameFonts),
 		ITE_GameFonts,
 		ITEPatch_Files,
+		ITE_IntroListDefault,
 	},
 
 	// Inherit the earth - Wyrmkeep French Windows CD version (fan translation)
@@ -679,6 +733,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		ARRAYSIZE(ITE_GameFonts),
 		ITE_GameFonts,
 		ITEPatch_Files,
+		ITE_IntroListDefault,
 	},
 
 	// Inherit the earth - Wyrmkeep French Linux CD version (fan translation)
@@ -704,6 +759,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		ARRAYSIZE(ITE_GameFonts),
 		ITE_GameFonts,
 		ITEPatch_Files,
+		ITE_IntroListDefault,
 	},
 
 	// Inherit the earth - French DOS CD version (fan translation)
@@ -728,6 +784,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		ARRAYSIZE(ITE_GameFonts),
 		ITE_GameFonts,
 		ITEPatch_Files,
+		ITE_IntroListDefault,
 	},
 
 	// Inherit the earth - DOS CD version - 30-06-1994
@@ -752,6 +809,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		ARRAYSIZE(ITE_GameFonts),
 		ITE_GameFonts,
 		ITEPatch_Files,
+		ITE_IntroListDefault,
 	},
 
 	// Inherit the earth - Hebrew fan translation
@@ -776,6 +834,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		ARRAYSIZE(ITE_GameFonts),
 		ITE_GameFonts,
 		NULL,
+		ITE_IntroListDefault,
 	},
 
 	// Inherit the earth - DOS CD German version
@@ -801,6 +860,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		ARRAYSIZE(ITE_GameFonts),
 		ITE_GameFonts,
 		NULL,
+		ITE_IntroListDefault,
 	},
 
 	// Inherit the earth - Windows Trial
@@ -828,6 +888,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		ARRAYSIZE(ITE_GameFonts),
 		ITE_GameFonts,
 		NULL,
+		ITE_IntroListDefault,
 	},
 
 	// Inherit the earth - macOS Trial
@@ -854,6 +915,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		ARRAYSIZE(ITE_GameFonts),
 		ITE_GameFonts,
 		NULL,
+		ITE_IntroListDefault,
 	},
 
 	// Inherit the earth - Pocket PC Trial
@@ -880,6 +942,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		ARRAYSIZE(ITE_GameFonts),
 		ITE_GameFonts,
 		ITEPatch_Files,
+		ITE_IntroListDefault,
 	},
 
 	// Inherit the Earth - Japanese PC-98 CD version
@@ -904,6 +967,7 @@ static const SAGAGameDescription gameDescriptions[] = {
  		ARRAYSIZE(ITE_GameFonts),
  		ITE_GameFonts,
  		NULL,
+		ITE_IntroListDefault,
  	},
 
 	// Inherit the earth - Russian CD version (fan translation)
@@ -928,6 +992,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		ARRAYSIZE(ITE_GameFonts),
 		ITE_GameFonts,
 		ITEPatch_Files,
+		ITE_IntroListDefault,
 	},
 
 	// ITE floppy versions ////////////////////////////////////////////////////////////////////////////////////
@@ -954,6 +1019,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		ARRAYSIZE(ITE_GameFonts),
 		ITE_GameFonts,
 		NULL,
+		ITE_IntroListDefault,
 	},
 
 	// Inherit the earth - Disk version
@@ -978,6 +1044,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		ARRAYSIZE(ITE_GameFonts),
 		ITE_GameFonts,
 		ITEPatch_Files,
+		ITE_IntroListDefault,
 	},
 
 	// Inherit the earth - Italian Disk version (fan translation)
@@ -1002,6 +1069,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		ARRAYSIZE(ITE_GameFonts),
 		ITE_GameFonts,
 		ITEPatch_Files,
+		ITE_IntroListDefault,
 	},
 
 	// Inherit the earth - Chinese Disk version
@@ -1026,6 +1094,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		ARRAYSIZE(ITE_GameFonts),
 		ITE_GameFonts,
 		ITEPatch_Files,
+		ITE_IntroListDefault,
 	},
 
 	// Inherit the earth - Russian Disk version (fan translation)
@@ -1050,6 +1119,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		ARRAYSIZE(ITE_GameFonts),
 		ITE_GameFonts,
 		ITEPatch_Files,
+		ITE_IntroListDefault,
 	},
 
 	// ITE Amiga versions /////////////////////////////////////////////////////////////////////////////////////
@@ -1082,6 +1152,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		ARRAYSIZE(IHNMDEMO_GameFonts),
 		IHNMDEMO_GameFonts,
 		NULL,
+		NULL,
 	},
 
 	// I Have No Mouth And I Must Scream - English CD version
@@ -1114,6 +1185,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		ARRAYSIZE(IHNMCD_GameFonts),
 		IHNMCD_GameFonts,
 		NULL,
+		NULL,
 	},
 
 	// I Have No Mouth And I Must Scream - De CD version
@@ -1144,6 +1216,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		ARRAYSIZE(IHNMCD_GameFonts),
 		IHNMCD_GameFonts,
 		NULL,
+		NULL,
 	},
 
 	// I Have No Mouth And I Must Scream - German fan CD translation
@@ -1174,6 +1247,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		ARRAYSIZE(IHNMCD_GameFonts),
 		IHNMCD_GameFonts,
 		NULL,
+		NULL,
 	},
 
 	// I Have No Mouth And I Must Scream - Hungarian fan CD translation
@@ -1204,6 +1278,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		ARRAYSIZE(IHNMCD_GameFonts),
 		IHNMCD_GameFonts,
 		NULL,
+		NULL,
 	},
 
 	// I Have No Mouth And I Must Scream - Sp CD version
@@ -1232,6 +1307,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		ARRAYSIZE(IHNMCD_GameFonts),
 		IHNMCD_GameFonts,
 		NULL,
+		NULL,
 	},
 
 	// I Have No Mouth And I Must Scream - Korean CD version
@@ -1261,6 +1337,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		ARRAYSIZE(IHNMCD_GameFonts),
 		IHNMCD_GameFonts,
 		NULL,
+		NULL,
 	},
 
 	// I Have No Mouth And I Must Scream - Fr CD version
@@ -1290,6 +1367,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		ARRAYSIZE(IHNMCD_GameFonts),
 		IHNMCD_GameFonts,
 		NULL,
+		NULL,
 	},
 
 	// I Have No Mouth And I Must Scream - Chinese CD
@@ -1319,6 +1397,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		ARRAYSIZE(IHNMCD_GameFonts),
 		IHNMCD_GameFonts,
 		NULL,
+		NULL,
 	},
 
 	// I Have No Mouth And I Must Scream - Italian fan CD translation
@@ -1347,6 +1426,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		ARRAYSIZE(IHNMCD_GameFonts),
 		IHNMCD_GameFonts,
 		NULL,
+		NULL,
 	},
 
 	// I Have No Mouth And I Must Scream - Russian fan translaction v1.0 (by jack7277 et al)
@@ -1379,6 +1459,7 @@ static const SAGAGameDescription gameDescriptions[] = {
 		ARRAYSIZE(IHNMCD_GameFonts),
 		IHNMCD_GameFonts,
 		NULL,
+		NULL,
 	},
 
 	// I Have No Mouth And I Must Scream - Mac English CD
@@ -1405,9 +1486,10 @@ static const SAGAGameDescription gameDescriptions[] = {
 		ARRAYSIZE(IHNMCD_GameFonts),
 		IHNMCD_GameFonts,
 		NULL,
+		NULL,
 	},
 
-	{ AD_TABLE_END_MARKER, 0, 0, 0, NULL, 0, NULL, NULL }
+	{ AD_TABLE_END_MARKER, 0, 0, 0, NULL, 0, NULL, NULL, NULL }
 };
 
 } // End of namespace Saga
diff --git a/engines/saga/introproc_ite.cpp b/engines/saga/introproc_ite.cpp
index 4b49a0b31ab..aaefb0942d3 100644
--- a/engines/saga/introproc_ite.cpp
+++ b/engines/saga/introproc_ite.cpp
@@ -49,52 +49,19 @@ namespace Saga {
 #define DISSOLVE_DURATION 3000
 #define LOGO_DISSOLVE_DURATION 1000
 
-// Intro scenes
-#define RID_ITE_INTRO_ANIM_SCENE 1538
-#define RID_ITE_CAVE_SCENE_1 1542
-#define RID_ITE_CAVE_SCENE_2 1545
-#define RID_ITE_CAVE_SCENE_3 1548
-#define RID_ITE_CAVE_SCENE_4 1551
-#define RID_ITE_VALLEY_SCENE 1556
-#define RID_ITE_TREEHOUSE_SCENE 1560
-#define RID_ITE_FAIREPATH_SCENE 1564
-#define RID_ITE_FAIRETENT_SCENE 1567
-
-// Intro scenes - DOS demo
-#define RID_ITE_INTRO_ANIM_SCENE_DOS_DEMO 298
-#define RID_ITE_CAVE_SCENE_DOS_DEMO 302
-#define RID_ITE_VALLEY_SCENE_DOS_DEMO 310
-
 // ITE intro music
 #define MUSIC_INTRO 9
 #define MUSIC_TITLE_THEME 10
 
-LoadSceneParams ITE_IntroList[] = {
-	{RID_ITE_INTRO_ANIM_SCENE, kLoadByResourceId, Scene::SC_ITEIntroAnimProc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE},
-	{RID_ITE_CAVE_SCENE_1, kLoadByResourceId, Scene::SC_ITEIntroCave1Proc, false, kTransitionFade, 0, NO_CHAPTER_CHANGE},
-	{RID_ITE_CAVE_SCENE_2, kLoadByResourceId, Scene::SC_ITEIntroCave2Proc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE},
-	{RID_ITE_CAVE_SCENE_3, kLoadByResourceId, Scene::SC_ITEIntroCave3Proc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE},
-	{RID_ITE_CAVE_SCENE_4, kLoadByResourceId, Scene::SC_ITEIntroCave4Proc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE},
-	{RID_ITE_VALLEY_SCENE, kLoadByResourceId, Scene::SC_ITEIntroValleyProc, false, kTransitionFade, 0, NO_CHAPTER_CHANGE},
-	{RID_ITE_TREEHOUSE_SCENE, kLoadByResourceId, Scene::SC_ITEIntroTreeHouseProc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE},
-	{RID_ITE_FAIREPATH_SCENE, kLoadByResourceId, Scene::SC_ITEIntroFairePathProc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE},
-	{RID_ITE_FAIRETENT_SCENE, kLoadByResourceId, Scene::SC_ITEIntroFaireTentProc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE}
-};
-
-LoadSceneParams ITE_DOS_Demo_IntroList[] = {
-	{RID_ITE_INTRO_ANIM_SCENE_DOS_DEMO, kLoadByResourceId, Scene::SC_ITEIntroAnimProc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE},
-	{RID_ITE_CAVE_SCENE_DOS_DEMO, kLoadByResourceId, Scene::SC_ITEIntroCaveDemoProc, false, kTransitionFade, 0, NO_CHAPTER_CHANGE},
-	{RID_ITE_VALLEY_SCENE_DOS_DEMO, kLoadByResourceId, Scene::SC_ITEIntroValleyProc, false, kTransitionFade, 0, NO_CHAPTER_CHANGE},
-};
-
 int Scene::ITEStartProc() {
 	LoadSceneParams firstScene;
 	LoadSceneParams tempScene;
-	bool dosDemo = (_vm->getFeatures() & GF_ITE_DOS_DEMO);
-	int scenesCount = (!dosDemo) ? ARRAYSIZE(ITE_IntroList) : ARRAYSIZE(ITE_DOS_Demo_IntroList);
+	const LoadSceneParams *scenes;
+
+	scenes = _vm->getIntroScenes();
 
-	for (int i = 0; i < scenesCount; i++) {
-		tempScene = (!dosDemo) ? ITE_IntroList[i] : ITE_DOS_Demo_IntroList[i];
+	for (int i = 0; scenes[i].sceneDescriptor; i++) {
+		tempScene = scenes[i];
 		tempScene.sceneDescriptor = _vm->_resource->convertResourceId(tempScene.sceneDescriptor);
 		_vm->_scene->queueScene(tempScene);
 	}
@@ -323,7 +290,7 @@ EventColumns *Scene::queueCredits(int delta_time, int duration, int n_credits, c
 	return eventColumns;
 }
 
-int Scene::SC_ITEIntroAnimProc(int param, void *refCon) {
+int SceneHandlers::SC_ITEIntroAnimProc(int param, void *refCon) {
 	return ((Scene *)refCon)->ITEIntroAnimProc(param);
 }
 
@@ -503,31 +470,31 @@ int Scene::ITEIntroCaveDemoProc(int param) {
 	return 0;
 }
 
-int Scene::SC_ITEIntroCaveDemoProc(int param, void *refCon) {
+int SceneHandlers::SC_ITEIntroCaveDemoProc(int param, void *refCon) {
 	return ((Scene *)refCon)->ITEIntroCaveDemoProc(param);
 }
 
 // Handles first introductory cave painting scene
-int Scene::SC_ITEIntroCave1Proc(int param, void *refCon) {
+int SceneHandlers::SC_ITEIntroCave1Proc(int param, void *refCon) {
 	return ((Scene *)refCon)->ITEIntroCaveCommonProc(param, 1);
 }
 
 // Handles second introductory cave painting scene
-int Scene::SC_ITEIntroCave2Proc(int param, void *refCon) {
+int SceneHandlers::SC_ITEIntroCave2Proc(int param, void *refCon) {
 	return ((Scene *)refCon)->ITEIntroCaveCommonProc(param, 2);
 }
 
 // Handles third introductory cave painting scene
-int Scene::SC_ITEIntroCave3Proc(int param, void *refCon) {
+int SceneHandlers::SC_ITEIntroCave3Proc(int param, void *refCon) {
 	return ((Scene *)refCon)->ITEIntroCaveCommonProc(param, 3);
 }
 
 // Handles fourth introductory cave painting scene
-int Scene::SC_ITEIntroCave4Proc(int param, void *refCon) {
+int SceneHandlers::SC_ITEIntroCave4Proc(int param, void *refCon) {
 	return ((Scene *)refCon)->ITEIntroCaveCommonProc(param, 4);
 }
 
-int Scene::SC_ITEIntroValleyProc(int param, void *refCon) {
+int SceneHandlers::SC_ITEIntroValleyProc(int param, void *refCon) {
 	return ((Scene *)refCon)->ITEIntroValleyProc(param);
 }
 
@@ -608,7 +575,7 @@ int Scene::ITEIntroValleyProc(int param) {
 	return 0;
 }
 
-int Scene::SC_ITEIntroTreeHouseProc(int param, void *refCon) {
+int SceneHandlers::SC_ITEIntroTreeHouseProc(int param, void *refCon) {
 	return ((Scene *)refCon)->ITEIntroTreeHouseProc(param);
 }
 
@@ -664,7 +631,7 @@ int Scene::ITEIntroTreeHouseProc(int param) {
 	return 0;
 }
 
-int Scene::SC_ITEIntroFairePathProc(int param, void *refCon) {
+int SceneHandlers::SC_ITEIntroFairePathProc(int param, void *refCon) {
 	return ((Scene *)refCon)->ITEIntroFairePathProc(param);
 }
 
@@ -718,7 +685,7 @@ int Scene::ITEIntroFairePathProc(int param) {
 	return 0;
 }
 
-int Scene::SC_ITEIntroFaireTentProc(int param, void *refCon) {
+int SceneHandlers::SC_ITEIntroFaireTentProc(int param, void *refCon) {
 	return ((Scene *)refCon)->ITEIntroFaireTentProc(param);
 }
 
diff --git a/engines/saga/saga.h b/engines/saga/saga.h
index e004b33fe0d..886c402753f 100644
--- a/engines/saga/saga.h
+++ b/engines/saga/saga.h
@@ -420,6 +420,8 @@ public:
 
 	bool isIHNMDemo() const { return _isIHNMDemo; }
 
+	const LoadSceneParams *getIntroScenes() const { return _gameDescription->introScenes; }
+
 	int16 _framesEsc;
 
 	uint32 _globalFlags;
diff --git a/engines/saga/scene.h b/engines/saga/scene.h
index cec4bfb5421..fb981d44551 100644
--- a/engines/saga/scene.h
+++ b/engines/saga/scene.h
@@ -38,7 +38,6 @@ namespace Saga {
 //#define SCENE_DEBUG // for scene debugging
 
 #define SCENE_DOORS_MAX 16
-#define NO_CHAPTER_CHANGE -2
 
 // Scenes
 #define ITE_SCENE_INV -1
@@ -59,9 +58,6 @@ struct BGInfo {
 	byte *buffer;
 };
 
-typedef int (SceneProc) (int, void *);
-
-
 enum SCENE_PROC_PARAMS {
 	SCENE_BEGIN = 0,
 	SCENE_END
@@ -140,26 +136,6 @@ struct SceneImage {
 };
 
 
-enum SceneTransitionType {
-	kTransitionNoFade,
-	kTransitionFade
-};
-
-enum SceneLoadFlags {
-	kLoadByResourceId,
-	kLoadBySceneNumber
-};
-
-struct LoadSceneParams {
-	int32 sceneDescriptor;
-	SceneLoadFlags loadFlag;
-	SceneProc *sceneProc;
-	bool sceneSkipTarget;
-	SceneTransitionType transitionType;
-	int actorsEntrance;
-	int chapter;
-};
-
 typedef Common::List<LoadSceneParams> SceneQueueList;
 
 ///// IHNM-specific stuff
@@ -362,18 +338,6 @@ class Scene {
 	bool playTitle(int title, int time, int mode = kPanelVideo);
 	bool playLoopingTitle(int title, int seconds);
 
- public:
-	static int SC_ITEIntroAnimProc(int param, void *refCon);
-	static int SC_ITEIntroCave1Proc(int param, void *refCon);
-	static int SC_ITEIntroCave2Proc(int param, void *refCon);
-	static int SC_ITEIntroCave3Proc(int param, void *refCon);
-	static int SC_ITEIntroCave4Proc(int param, void *refCon);
-	static int SC_ITEIntroValleyProc(int param, void *refCon);
-	static int SC_ITEIntroTreeHouseProc(int param, void *refCon);
-	static int SC_ITEIntroFairePathProc(int param, void *refCon);
-	static int SC_ITEIntroFaireTentProc(int param, void *refCon);
-	static int SC_ITEIntroCaveDemoProc(int param, void *refCon);
-
  private:
 	EventColumns *queueIntroDialogue(EventColumns *eventColumns, int n_dialogues, const IntroDialogue dialogue[]);
 	EventColumns *queueCredits(int delta_time, int duration, int n_credits, const IntroCredit credits[]);
@@ -385,6 +349,7 @@ class Scene {
 	int ITEIntroFairePathProc(int param);
 	int ITEIntroFaireTentProc(int param);
 
+	friend SceneHandlers;
 };
 
 } // End of namespace Saga
diff --git a/engines/saga/shared_detection_defines.h b/engines/saga/shared_detection_defines.h
index fed4e2d9e19..657f0436e49 100644
--- a/engines/saga/shared_detection_defines.h
+++ b/engines/saga/shared_detection_defines.h
@@ -24,3 +24,43 @@
 #define IHNM_DEFAULT_SCENE 151
 #define ITEDEMO_DEFAULT_SCENE 68
 #define IHNMDEMO_DEFAULT_SCENE 144
+
+namespace Saga {
+typedef int (SceneProc) (int, void *);
+
+class SceneHandlers {
+public:
+	static int SC_ITEIntroAnimProc(int param, void *refCon);
+	static int SC_ITEIntroCave1Proc(int param, void *refCon);
+	static int SC_ITEIntroCave2Proc(int param, void *refCon);
+	static int SC_ITEIntroCave3Proc(int param, void *refCon);
+	static int SC_ITEIntroCave4Proc(int param, void *refCon);
+	static int SC_ITEIntroValleyProc(int param, void *refCon);
+	static int SC_ITEIntroTreeHouseProc(int param, void *refCon);
+	static int SC_ITEIntroFairePathProc(int param, void *refCon);
+	static int SC_ITEIntroFaireTentProc(int param, void *refCon);
+	static int SC_ITEIntroCaveDemoProc(int param, void *refCon);
+};
+
+enum SceneTransitionType {
+	kTransitionNoFade,
+	kTransitionFade
+};
+
+enum SceneLoadFlags {
+	kLoadByResourceId,
+	kLoadBySceneNumber
+};
+
+struct LoadSceneParams {
+	int32 sceneDescriptor;
+	SceneLoadFlags loadFlag;
+	SceneProc *sceneProc;
+	bool sceneSkipTarget;
+	SceneTransitionType transitionType;
+	int actorsEntrance;
+	int chapter;
+};
+
+#define NO_CHAPTER_CHANGE -2
+}


Commit: 64241d1657fc4250f7e806756b308f1ab46358b2
    https://github.com/scummvm/scummvm/commit/64241d1657fc4250f7e806756b308f1ab46358b2
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2022-11-14T00:27:33+01:00

Commit Message:
SAGA: Add new flags to specify AGA and ECS graphics

Changed paths:
    engines/saga/detection.cpp
    engines/saga/detection.h
    engines/saga/saga.h


diff --git a/engines/saga/detection.cpp b/engines/saga/detection.cpp
index 374e6929f87..7732c8fc985 100644
--- a/engines/saga/detection.cpp
+++ b/engines/saga/detection.cpp
@@ -40,6 +40,7 @@ public:
 		static const char *const DIRECTORY_GLOBS[2] = { "music", nullptr };
 		_maxScanDepth = 2;
 		_directoryGlobs = DIRECTORY_GLOBS;
+		_flags = kADFlagUseExtraAsHint;
 	}
 
 	const char *getName() const override {
diff --git a/engines/saga/detection.h b/engines/saga/detection.h
index fd3b0e60e0b..89d6b3013f3 100644
--- a/engines/saga/detection.h
+++ b/engines/saga/detection.h
@@ -66,7 +66,9 @@ enum GameFeatures {
 	GF_EXTRA_ITE_CREDITS = 1 << 2,
 	GF_8BIT_UNSIGNED_PCM = 1 << 3,
 	GF_IHNM_COLOR_FIX    = 1 << 4,
-	GF_SOME_MAC_RESOURCES= 1 << 5
+	GF_SOME_MAC_RESOURCES= 1 << 5,
+	GF_AGA_GRAPHICS      = 1 << 6,
+	GF_ECS_GRAPHICS      = 1 << 7
 };
 
 enum GameFileTypes {
diff --git a/engines/saga/saga.h b/engines/saga/saga.h
index 886c402753f..e1d94161104 100644
--- a/engines/saga/saga.h
+++ b/engines/saga/saga.h
@@ -420,6 +420,10 @@ public:
 
 	bool isIHNMDemo() const { return _isIHNMDemo; }
 
+	bool isITEAmiga() const { return getPlatform() == Common::kPlatformAmiga && getGameId() == GID_ITE; }
+	bool isAGA() const { return _gameDescription->features & GF_AGA_GRAPHICS; }
+	bool isECS() const { return _gameDescription->features & GF_ECS_GRAPHICS; }
+	unsigned getPalNumEntries() const { return isECS() ? 32 : 256; }
 	const LoadSceneParams *getIntroScenes() const { return _gameDescription->introScenes; }
 
 	int16 _framesEsc;


Commit: e8643e41defde968b7f3cc140df627f7245246f0
    https://github.com/scummvm/scummvm/commit/e8643e41defde968b7f3cc140df627f7245246f0
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2022-11-14T00:27:33+01:00

Commit Message:
SAGA: Allow working without sound

Changed paths:
    engines/saga/sndres.cpp


diff --git a/engines/saga/sndres.cpp b/engines/saga/sndres.cpp
index f7bb03d4fae..19a7e721a9c 100644
--- a/engines/saga/sndres.cpp
+++ b/engines/saga/sndres.cpp
@@ -52,7 +52,8 @@ SndRes::SndRes(SagaEngine *vm) : _vm(vm), _sfxContext(nullptr), _voiceContext(nu
 	// Load sound module resource file contexts
 	_sfxContext = _vm->_resource->getContext(GAME_SOUNDFILE);
 	if (_sfxContext == nullptr) {
-		error("SndRes::SndRes resource context not found");
+		warning("SndRes::SndRes resource context not found");
+		return;
 	}
 
 	setVoiceBank(0);
@@ -105,6 +106,8 @@ SndRes::~SndRes() {
 
 void SndRes::setVoiceBank(int serial) {
 	Common::File *file;
+	if (_sfxContext == nullptr)
+		return;
 	if (_voiceSerial == serial)
 		return;
 
@@ -141,6 +144,9 @@ void SndRes::playSound(uint32 resourceId, int volume, bool loop) {
 
 	debug(4, "SndRes::playSound %i", resourceId);
 
+	if (_sfxContext == nullptr)
+		return;
+
 	if (!load(_sfxContext, resourceId, buffer, false)) {
 		warning("Failed to load sound");
 		return;
@@ -152,6 +158,9 @@ void SndRes::playSound(uint32 resourceId, int volume, bool loop) {
 void SndRes::playVoice(uint32 resourceId) {
 	SoundBuffer buffer;
 
+	if (_sfxContext == nullptr)
+		return;
+
 	if (!(_vm->_voiceFilesExist))
 		return;
 
@@ -195,6 +204,9 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff
 	int rate = 0, size = 0;
 	Common::File *file;
 
+	if (_sfxContext == nullptr)
+		return false;
+
 	if (resourceId == (uint32)-1) {
 		return false;
 	}
@@ -455,6 +467,9 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff
 int SndRes::getVoiceLength(uint32 resourceId) {
 	SoundBuffer buffer;
 
+	if (_sfxContext == nullptr)
+		return -1;
+
 	if (!(_vm->_voiceFilesExist))
 		return -1;
 


Commit: 8ff65b22ccf2800f3774102374e35a16b10de769
    https://github.com/scummvm/scummvm/commit/8ff65b22ccf2800f3774102374e35a16b10de769
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2022-11-14T00:27:33+01:00

Commit Message:
SAGA: Introduce flag for differentiating mask and dissolve background image

On Amiga they're actually loaded differently. Fortunately only intro uses
later cases so we can ust mark specific intro scenes as needing special
handling.

Changed paths:
    engines/saga/detection_tables.h
    engines/saga/scene.cpp
    engines/saga/scene.h
    engines/saga/shared_detection_defines.h


diff --git a/engines/saga/detection_tables.h b/engines/saga/detection_tables.h
index e41bb20fa2a..4ca3bf1c670 100644
--- a/engines/saga/detection_tables.h
+++ b/engines/saga/detection_tables.h
@@ -136,7 +136,7 @@ LoadSceneParams ITE_IntroListDefault[] = {
 	{RID_ITE_CAVE_SCENE_2, kLoadByResourceId, SceneHandlers::SC_ITEIntroCave2Proc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE},
 	{RID_ITE_CAVE_SCENE_3, kLoadByResourceId, SceneHandlers::SC_ITEIntroCave3Proc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE},
 	{RID_ITE_CAVE_SCENE_4, kLoadByResourceId, SceneHandlers::SC_ITEIntroCave4Proc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE},
-	{RID_ITE_VALLEY_SCENE, kLoadByResourceId, SceneHandlers::SC_ITEIntroValleyProc, false, kTransitionFade, 0, NO_CHAPTER_CHANGE},
+	{RID_ITE_VALLEY_SCENE, (Saga::SceneLoadFlags) (kLoadByResourceId | kLoadBgMaskIsImage), SceneHandlers::SC_ITEIntroValleyProc, false, kTransitionFade, 0, NO_CHAPTER_CHANGE},
 	{RID_ITE_TREEHOUSE_SCENE, kLoadByResourceId, SceneHandlers::SC_ITEIntroTreeHouseProc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE},
 	{RID_ITE_FAIREPATH_SCENE, kLoadByResourceId, SceneHandlers::SC_ITEIntroFairePathProc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE},
 	{RID_ITE_FAIRETENT_SCENE, kLoadByResourceId, SceneHandlers::SC_ITEIntroFaireTentProc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE},
diff --git a/engines/saga/scene.cpp b/engines/saga/scene.cpp
index d9216c37bd8..d3f1e9bd587 100644
--- a/engines/saga/scene.cpp
+++ b/engines/saga/scene.cpp
@@ -576,7 +576,7 @@ void Scene::loadScene(LoadSceneParams &loadSceneParams) {
 
 #ifdef ENABLE_IHNM
 	if ((_vm->getGameId() == GID_IHNM) && (loadSceneParams.chapter != NO_CHAPTER_CHANGE)) {
-		if (loadSceneParams.loadFlag != kLoadBySceneNumber) {
+		if ((loadSceneParams.loadFlag & kLoadIdTypeMask) != kLoadBySceneNumber) {
 			error("loadScene wrong usage");
 		}
 
@@ -621,13 +621,13 @@ void Scene::loadScene(LoadSceneParams &loadSceneParams) {
 
 #ifdef ENABLE_IHNM
 	if (_vm->getGameId() == GID_IHNM) {
-		if (loadSceneParams.loadFlag == kLoadBySceneNumber) // When will we get rid of it?
+		if ((loadSceneParams.loadFlag & kLoadIdTypeMask) == kLoadBySceneNumber) // When will we get rid of it?
 			if (loadSceneParams.sceneDescriptor <= 0)
 				loadSceneParams.sceneDescriptor = _vm->_resource->getMetaResource()->sceneIndex;
 	}
 #endif
 
-	switch (loadSceneParams.loadFlag) {
+	switch (loadSceneParams.loadFlag & kLoadIdTypeMask) {
 	case kLoadByResourceId:
 		_sceneNumber = 0;		// original assign zero for loaded by resource id
 		_sceneResourceId = loadSceneParams.sceneDescriptor;
@@ -660,7 +660,7 @@ void Scene::loadScene(LoadSceneParams &loadSceneParams) {
 	loadSceneResourceList(_sceneDescription.resourceListResourceId, resourceList);
 
 	// Process resources from scene resource list
-	processSceneResources(resourceList);
+	processSceneResources(resourceList, loadSceneParams.loadFlag);
 
 	if (_sceneDescription.flags & kSceneFlagISO) {
 		_outsetSceneNumber = _sceneNumber;
@@ -901,7 +901,7 @@ void Scene::loadSceneResourceList(uint32 resourceId, SceneResourceDataArray &res
 	}
 }
 
-void Scene::processSceneResources(SceneResourceDataArray &resourceList) {
+void Scene::processSceneResources(SceneResourceDataArray &resourceList, SceneLoadFlags flags) {
 	ByteArray resourceData;
 	const byte *palPointer;
 	SAGAResourceTypes *types = nullptr;
diff --git a/engines/saga/scene.h b/engines/saga/scene.h
index fb981d44551..e30f68887d7 100644
--- a/engines/saga/scene.h
+++ b/engines/saga/scene.h
@@ -292,7 +292,7 @@ class Scene {
 	void loadSceneDescriptor(uint32 resourceId);
 	void loadSceneResourceList(uint32 resourceId, SceneResourceDataArray &resourceList);
 	void loadSceneEntryList(const ByteArray &resourceData);
-	void processSceneResources(SceneResourceDataArray &resourceList);
+	void processSceneResources(SceneResourceDataArray &resourceList, SceneLoadFlags flags);
 	void getResourceTypes(SAGAResourceTypes *&types, int &typesCount);
 
 
diff --git a/engines/saga/shared_detection_defines.h b/engines/saga/shared_detection_defines.h
index 657f0436e49..0d03a0c5e98 100644
--- a/engines/saga/shared_detection_defines.h
+++ b/engines/saga/shared_detection_defines.h
@@ -48,8 +48,10 @@ enum SceneTransitionType {
 };
 
 enum SceneLoadFlags {
-	kLoadByResourceId,
-	kLoadBySceneNumber
+	kLoadByResourceId = 0,
+	kLoadBySceneNumber = 1,
+	kLoadIdTypeMask = 1,
+	kLoadBgMaskIsImage = 1 << 16,
 };
 
 struct LoadSceneParams {


Commit: ee8151e007417b4c34106bd1b72cb3eb54e38ba6
    https://github.com/scummvm/scummvm/commit/ee8151e007417b4c34106bd1b72cb3eb54e38ba6
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2022-11-14T00:27:33+01:00

Commit Message:
SAGA: Support decoding AGA and ECS graphics

Changed paths:
    engines/saga/animation.cpp
    engines/saga/animation.h
    engines/saga/image.cpp
    engines/saga/isomap.cpp
    engines/saga/isomap.h
    engines/saga/saga.h
    engines/saga/scene.cpp
    engines/saga/sprite.cpp


diff --git a/engines/saga/animation.cpp b/engines/saga/animation.cpp
index 8986c9bf7e3..01145a1fc56 100644
--- a/engines/saga/animation.cpp
+++ b/engines/saga/animation.cpp
@@ -389,7 +389,7 @@ void Anim::load(uint16 animId, const ByteArray &resourceData) {
 	} else
 		anim = _animations[animId] = new AnimationData();
 
-	ByteArrayReadStreamEndian headerReadS(resourceData, _vm->isBigEndian());
+	ByteArrayReadStreamEndian headerReadS(resourceData, _vm->isBigEndian() && !_vm->isAGA() && !_vm->isECS());
 	anim->magic = headerReadS.readUint16LE(); // cause ALWAYS LE
 	anim->screenWidth = headerReadS.readUint16();
 	anim->screenHeight = headerReadS.readUint16();
@@ -689,6 +689,70 @@ void Anim::decodeFrame(AnimationData *anim, size_t frameOffset, byte *buf, size_
 #define VALIDATE_WRITE_POINTER
 #endif
 
+	if (_vm->isAGA() || _vm->isECS()) {
+		int curY = 0, curX = 0;
+		unsigned realY;
+		unsigned outbit;
+		// TODO: Check if we want to use tempaltes instead to optimize AGA case
+		unsigned int pixelSize = _vm->isAGA() ? 8 : 5;
+		while (1) {
+			markByte = readS.readByte();
+			if (markByte == SAGA_FRAME_AMIGA_END)
+				break;
+			if (markByte == SAGA_FRAME_AMIGA_START) {
+				xStart = readS.readByte();
+				yStart = readS.readUint16BE();
+				/* int xPos = */ readS.readUint16BE();
+				/* int yPos = */ readS.readUint16BE();
+				/* int width = */ readS.readUint16BE();
+				/*int height = */ readS.readUint16BE();
+				curX = xStart;
+				curY = yStart;
+				realY = curY / pixelSize;
+				outbit = curY % pixelSize;
+				continue;
+			}
+
+			uint8 param = markByte & SAGA_FRAME_AMIGA_PARAM_MASK;
+			
+			switch (markByte & SAGA_FRAME_AMIGA_OPCODE_MASK) {
+			case SAGA_FRAME_AMIGA_OPCODE_LITERAL:
+				for (i = 0; i < param + 1; i++, curX++) {
+					byte b = readS.readByte();
+					for (unsigned inbit = 0;inbit < 8; inbit++) {
+						unsigned realX = (curX << 3) + 7 - inbit;
+						if (realX < screenWidth && realY < screenHeight) {
+							buf[realX + realY * screenWidth] =
+								(buf[realX + realY * screenWidth] & (~(1 << outbit))) | (((b >> inbit) & 1) << outbit);
+						}
+					}
+				}
+				continue;
+
+			case SAGA_FRAME_AMIGA_OPCODE_TRANSPARENT:
+				curX += param;
+				continue;
+				
+			case SAGA_FRAME_AMIGA_OPCODE_NEWLINE:
+				curY++;
+				curX = param;
+				outbit++;
+				if (outbit >= pixelSize) {
+					outbit -= pixelSize;
+					realY++;
+				}
+				continue;
+			case SAGA_FRAME_AMIGA_OPCODE_REPOSITION:
+				curY = readS.readUint16BE();
+				realY = curY / pixelSize;
+				outbit = curY % pixelSize;
+				curX = param;
+				continue;
+			}
+		}
+		
+		return;
+	}
 
 	// Begin RLE decompression to output buffer
 	do {
@@ -815,6 +879,44 @@ int Anim::fillFrameOffsets(AnimationData *anim, bool reallyFill) {
 
 	Common::MemoryReadStreamEndian readS(&anim->resourceData.front(), anim->resourceData.size(), !_vm->isBigEndian()); // RLE has inversion BE<>LE
 
+	if (_vm->isAGA() || _vm->isECS()) {
+	  	while (readS.pos() != readS.size()) {
+			if (reallyFill) {
+				anim->frameOffsets[currentFrame] = readS.pos();
+
+				if (currentFrame == anim->maxFrame) {
+					break;
+				}
+			}
+			currentFrame++;
+
+			while (1) {
+				markByte = readS.readByte();
+
+				// debug(7, "_pos=%X currentFrame=%i markByte=%X", (int) readS.pos(), (int) currentFrame, (int) markByte);
+				if (markByte == SAGA_FRAME_AMIGA_END)
+					break;
+				if (markByte == SAGA_FRAME_AMIGA_START) {
+					readS.seek(11, SEEK_CUR);
+					continue;
+				}
+				switch (markByte & SAGA_FRAME_AMIGA_OPCODE_MASK) {
+				case SAGA_FRAME_AMIGA_OPCODE_LITERAL:
+					readS.seek((markByte & SAGA_FRAME_AMIGA_PARAM_MASK) + 1, SEEK_CUR);
+					continue;
+
+				case SAGA_FRAME_AMIGA_OPCODE_TRANSPARENT:
+				case SAGA_FRAME_AMIGA_OPCODE_NEWLINE:
+					continue;
+				case SAGA_FRAME_AMIGA_OPCODE_REPOSITION:
+					readS.readSint16BE();
+					continue;
+				}
+			}
+		}
+		return currentFrame;
+	}
+
 	while (readS.pos() != readS.size()) {
 		if (reallyFill) {
 			anim->frameOffsets[currentFrame] = readS.pos();
diff --git a/engines/saga/animation.h b/engines/saga/animation.h
index cb7a7f5b5fb..9491dd05cd2 100644
--- a/engines/saga/animation.h
+++ b/engines/saga/animation.h
@@ -40,6 +40,15 @@ namespace Saga {
 #define SAGA_FRAME_UNCOMPRESSED_RUN 0x40
 #define SAGA_FRAME_EMPTY_RUN 0xC0
 
+#define SAGA_FRAME_AMIGA_OPCODE_REPOSITION 0x00
+#define SAGA_FRAME_AMIGA_OPCODE_LITERAL 0x40
+#define SAGA_FRAME_AMIGA_OPCODE_TRANSPARENT 0xC0
+#define SAGA_FRAME_AMIGA_OPCODE_NEWLINE 0x80
+#define SAGA_FRAME_AMIGA_OPCODE_MASK 0xC0
+#define SAGA_FRAME_AMIGA_PARAM_MASK 0x3F
+#define SAGA_FRAME_AMIGA_END 0x3F
+#define SAGA_FRAME_AMIGA_START 0x3E
+
 enum AnimationState {
 	ANIM_PLAYING = 0x01,
 	ANIM_PAUSE = 0x02,
diff --git a/engines/saga/image.cpp b/engines/saga/image.cpp
index ac12472246a..5b2758de842 100644
--- a/engines/saga/image.cpp
+++ b/engines/saga/image.cpp
@@ -43,11 +43,45 @@ static int granulate(int value, int granularity) {
 	}
 }
 
+bool SagaEngine::decodeBGImageMask(const ByteArray &imageData, ByteArray &outputBuffer, int *w, int *h, bool flip) {
+	if (isAGA() || isECS()) {
+		if (imageData.size() < 160 * 137 + 64)
+			return false;
+		*w = 320;
+		*h = 137;
+		outputBuffer.resize(320*137);
+
+		// First read types
+		for (int i = 0; i < 160*137; i++) {
+			outputBuffer[2 * i] = (imageData[i] << 4) | 0xf;
+			outputBuffer[2 * i + 1] = (imageData[i] << 4) | 0xf;
+		}
+
+		// Now instead of storing depth amiga variant stores precomputed mask for every
+		// depth. Obviously not every set of precomputed masks is valid but we assume
+		// that it is. So far it has always been the case. If ever it isn't then we'll
+		// get a minor graphical glitch
+		for (int depth = 15; depth > 0; depth--) {
+			uint32 off = READ_BE_UINT32(&imageData[160 * 137 + 4 * (15 - depth)]);
+			if (off == 0)
+				continue;
+			off += 160 * 137;
+			if (imageData.size() < off + 137 * 40)
+				return false;
+			for (int y = 0; y < 137; y++)
+				for (int x = 0; x < 320; x++)
+					if ((imageData[y * 40 + (x / 8) + off] << (x % 8)) & 0x80)
+						outputBuffer[y * 320 + x] = (outputBuffer[y * 320 + x] & 0xf0) | (depth - 1);
+		}
+
+		return true;
+	}
+
+	return decodeBGImage(imageData, outputBuffer, w, h, flip);
+}
+
 bool SagaEngine::decodeBGImage(const ByteArray &imageData, ByteArray &outputBuffer, int *w, int *h, bool flip) {
 	ImageHeader hdr;
-	int modex_height;
-	const byte *RLE_data_ptr;
-	size_t RLE_data_len;
 	ByteArray decodeBuffer;
 
 	if (imageData.size() <= SAGA_IMAGE_DATA_OFFSET) {
@@ -62,21 +96,39 @@ bool SagaEngine::decodeBGImage(const ByteArray &imageData, ByteArray &outputBuff
 	readS.readUint16();
 	readS.readUint16();
 
-	RLE_data_ptr = &imageData.front() + SAGA_IMAGE_DATA_OFFSET;
-	RLE_data_len = imageData.size() - SAGA_IMAGE_DATA_OFFSET;
-
-	modex_height = granulate(hdr.height, 4);
+	outputBuffer.resize(hdr.width * hdr.height);
 
-	decodeBuffer.resize(hdr.width * modex_height);
+	if (isAGA() || isECS()) {
+		int planePitch = (hdr.width + 15) & ~15;
+		int linePitch = isAGA() ? planePitch : (planePitch * 5 / 8);
+		unsigned bitnum = isAGA() ? 8 : 5;
+		int headerSize = 8 + (3 << bitnum);
+		const byte *RLE_data_ptr = &imageData.front() + headerSize;
+		size_t RLE_data_len = imageData.size() - headerSize;
 
-	outputBuffer.resize(hdr.width * hdr.height);
+		if (RLE_data_len != (size_t) linePitch * hdr.height)
+			return false;
 
-	if (!decodeBGImageRLE(RLE_data_ptr, RLE_data_len, decodeBuffer)) {
-		return false;
+		memset(outputBuffer.getBuffer(), 0, hdr.width * hdr.height);
+		for (int y = 0; y < hdr.height; y++)
+			for (int x = 0; x < hdr.width; x++)
+				for (unsigned bit = 0; bit < bitnum; bit++) {
+					int inXbit = x + bit * planePitch;
+					outputBuffer[y * hdr.width + x] |= ((RLE_data_ptr[y * linePitch + inXbit / 8] >> (7 - inXbit % 8)) & 1) << bit;
+				}
+	} else {
+		int modex_height = granulate(hdr.height, 4);
+		const byte *RLE_data_ptr;
+		size_t RLE_data_len;
+		decodeBuffer.resize(hdr.width * modex_height);
+		RLE_data_ptr = &imageData.front() + SAGA_IMAGE_DATA_OFFSET;
+		RLE_data_len = imageData.size() - SAGA_IMAGE_DATA_OFFSET;
+		if (!decodeBGImageRLE(RLE_data_ptr, RLE_data_len, decodeBuffer)) {
+			return false;
+		}
+		unbankBGImage(outputBuffer.getBuffer(), decodeBuffer.getBuffer(), hdr.width, hdr.height);
 	}
 
-	unbankBGImage(outputBuffer.getBuffer(), decodeBuffer.getBuffer(), hdr.width, hdr.height);
-
 	// For some reason bg images in IHNM are upside down
 	if (getGameId() == GID_IHNM && !flip) {
 		flipImage(outputBuffer.getBuffer(), hdr.width, hdr.height);
diff --git a/engines/saga/isomap.cpp b/engines/saga/isomap.cpp
index bfb6fa9d6e5..27bcc47bbec 100644
--- a/engines/saga/isomap.cpp
+++ b/engines/saga/isomap.cpp
@@ -124,10 +124,11 @@ void IsoMap::loadImages(const ByteArray &resourceData) {
 		error("IsoMap::loadImages wrong resourceLength");
 	}
 
+	bool longOffset = _vm->isAGA() || _vm->isECS();
 
 	ByteArrayReadStreamEndian readS(resourceData, _vm->isBigEndian());
 	readS.readUint16(); // skip
-	i = readS.readUint16();
+	i = longOffset ? readS.readUint32() : readS.readUint16();
 	i = i / SAGA_ISOTILEDATA_LEN;
 	_tilesTable.resize(i);
 	Common::Array<size_t> tempOffsets;
@@ -139,7 +140,7 @@ void IsoMap::loadImages(const ByteArray &resourceData) {
 		tileData = &_tilesTable[i];
 		tileData->height = readS.readByte();
 		tileData->attributes = readS.readSByte();
-		tempOffsets[i] = readS.readUint16();
+		tempOffsets[i] = longOffset ? readS.readUint32() : readS.readUint16();
 		tileData->terrainMask = readS.readUint16();
 		tileData->FGDBGDAttr = readS.readByte();
 		readS.readByte(); //skip
@@ -152,6 +153,7 @@ void IsoMap::loadImages(const ByteArray &resourceData) {
 
 	for (i = 0; i < _tilesTable.size(); i++) {
 		_tilesTable[i].tilePointer = _tileData.getBuffer() + tempOffsets[i] - offsetDiff;
+		_tilesTable[i].tileSize = i + 1 == (int)_tilesTable.size() ? resourceData.size() - tempOffsets[i] : tempOffsets[i+1] - tempOffsets[i];
 	}
 }
 
@@ -819,6 +821,40 @@ void IsoMap::drawTile(uint16 tileIndex, const Point &point, const Location *loca
 
 	readPointer = tilePointer;
 	lowBound = MIN((int)(drawPoint.y + height), (int)_tileClip.bottom);
+
+	if (_vm->isAGA() || _vm->isECS()) {
+		if (height == 0)
+			return;
+		int pitchLine = _tilesTable[tileIndex].tileSize / height;
+		int pitchPlane = _vm->isAGA() ? pitchLine / 8 : pitchLine / 5;
+		int width = pitchPlane * 8;
+		int bitnum = _vm->isAGA() ? 8 : 5;
+		Common::Rect bounds(
+			MAX((int)drawPoint.x, (int)_tileClip.left),
+			MAX((int)drawPoint.y, (int)_tileClip.top),
+			MIN((int)drawPoint.x + width, (int)_tileClip.right),
+			MIN((int)drawPoint.y + height, (int)_tileClip.bottom)
+			);
+		for (row = bounds.top; row < bounds.bottom; row++)
+			for (col = bounds.left; col < bounds.right; col++) {
+				int sourceX = (col - drawPoint.x);
+				int sourceY = (row - drawPoint.y);
+				byte res = 0;
+
+				for (int bit = 0; bit < bitnum; bit++) {
+				        unsigned inOff = sourceY * pitchLine + sourceX / 8 + pitchPlane * bit;
+					if (inOff >= _tilesTable[tileIndex].tileSize) {
+					  //warning("Overrun sourceX=%d, sourceY=%d, pitch=%d, height=%d", sourceX, sourceY, pitchLine, height);
+						continue;
+					}
+					res |= ((tilePointer[inOff] >> (7 - sourceX % 8)) & 1) << bit;
+				}
+				if (res != 0)
+					_vm->_gfx->getBackBufferPixels()[col + (row * _vm->_gfx->getBackBufferPitch())] = res;
+			}
+		return;
+	}
+
 	for (row = drawPoint.y; row < lowBound; row++) {
 		widthCount = 0;
 		if (row >= _tileClip.top) {
diff --git a/engines/saga/isomap.h b/engines/saga/isomap.h
index 7e27fc527fb..e95f8c67f2e 100644
--- a/engines/saga/isomap.h
+++ b/engines/saga/isomap.h
@@ -90,6 +90,7 @@ enum TileMapEdgeType {
 
 struct IsoTileData {
 	byte height;
+	size_t tileSize;
 	int8 attributes;
 	byte *tilePointer;
 	uint16 terrainMask;
diff --git a/engines/saga/saga.h b/engines/saga/saga.h
index e1d94161104..89cdcf1f7f9 100644
--- a/engines/saga/saga.h
+++ b/engines/saga/saga.h
@@ -475,6 +475,7 @@ private:
 
 public:
 	bool decodeBGImage(const ByteArray &imageData, ByteArray &outputBuffer, int *w, int *h, bool flip = false);
+  	bool decodeBGImageMask(const ByteArray &imageData, ByteArray &outputBuffer, int *w, int *h, bool flip = false);
 	const byte *getImagePal(const ByteArray &imageData) {
 		if (imageData.size() <= SAGA_IMAGE_HEADER_LEN) {
 			return NULL;
diff --git a/engines/saga/scene.cpp b/engines/saga/scene.cpp
index d3f1e9bd587..770114466b5 100644
--- a/engines/saga/scene.cpp
+++ b/engines/saga/scene.cpp
@@ -971,7 +971,10 @@ void Scene::processSceneResources(SceneResourceDataArray &resourceList, SceneLoa
 				error("Scene::ProcessSceneResources(): Duplicate background mask resource encountered");
 
 			debug(3, "Loading BACKGROUND MASK resource.");
-			_vm->decodeBGImage(resourceData, _bgMask.buffer, &_bgMask.w, &_bgMask.h, true);
+			if (flags & kLoadBgMaskIsImage)
+				_vm->decodeBGImage(resourceData, _bgMask.buffer, &_bgMask.w, &_bgMask.h, true);
+			else
+				_vm->decodeBGImageMask(resourceData, _bgMask.buffer, &_bgMask.w, &_bgMask.h, true);
 			_bgMask.loaded = true;
 
 			// At least in ITE the mask needs to be clipped.
@@ -1053,15 +1056,21 @@ void Scene::processSceneResources(SceneResourceDataArray &resourceList, SceneLoa
 			{
 				PalEntry pal[PAL_ENTRIES];
 				byte *palPtr = resourceData.getBuffer();
+				uint16 c;
 
-				if (resourceData.size() < 3 * PAL_ENTRIES)
+				if (resourceData.size() < 3 * _vm->getPalNumEntries())
 					error("Too small scene palette %i", (int)resourceData.size());
 
-				for (uint16 c = 0; c < PAL_ENTRIES; c++) {
+				for (c = 0; c < _vm->getPalNumEntries(); c++) {
 					pal[c].red = *palPtr++;
 					pal[c].green = *palPtr++;
 					pal[c].blue = *palPtr++;
 				}
+				for (; c < PAL_ENTRIES; c++) {
+					pal[c].red = 0;
+					pal[c].green = 0;
+					pal[c].blue = 0;
+				}
 				_vm->_gfx->setPalette(pal);
 			}
 			break;
diff --git a/engines/saga/sprite.cpp b/engines/saga/sprite.cpp
index f89944af456..f0e451fe257 100644
--- a/engines/saga/sprite.cpp
+++ b/engines/saga/sprite.cpp
@@ -33,6 +33,83 @@
 
 namespace Saga {
 
+namespace {
+
+template<int bitsPerPixel, int bitsPerEntry>
+bool blitAmigaSprite(byte *outBuf, int outPitch, const byte *inputBuffer, size_t inLength, int width, int height) {
+	byte *outPointer = outBuf;
+	int c;
+	int widthAligned = (width + 15) & ~15;
+
+	Common::MemoryReadStream readS(inputBuffer, inLength);
+	const byte *ptr = inputBuffer, *end = inputBuffer + inLength;
+
+	for (int bitOut = 0; bitOut < bitsPerPixel; bitOut++)
+		for (int x = 0; x < widthAligned; x += bitsPerEntry) {
+			for (int y = 0; y < height; ) {
+				int bg_runcount = bitsPerEntry == 16 ? READ_BE_UINT16(ptr) : *ptr;
+				ptr += bitsPerEntry / 8;
+				if (ptr >= end)
+					return true;
+
+				// Transparent
+				y += bg_runcount;
+
+				if (y > height) {
+					warning("Sprite height overrun in transparent run: coord=%d+%dx%d, size=%dx%d, pos=%d",
+						x, bitOut, y, width, height, (int)readS.pos());
+					return true;
+				}
+
+				if (y == height) {
+					continue;
+				}
+
+				int fg_runcount = bitsPerEntry == 16 ? READ_BE_UINT16(ptr) : *ptr;
+				ptr += bitsPerEntry / 8;
+				if (ptr >= end)
+					return true;
+
+				for (c = 0; c < fg_runcount && ptr < end; c++, y++) {
+					uint16 val = bitsPerEntry == 16 ? READ_BE_UINT16(ptr) : *ptr;
+					ptr += bitsPerEntry / 8;
+					if (y >= height) {
+						warning("Sprite height overrun in opaque run: coord=%d+%dx%d, size=%dx%d, pos=%d",
+							x, bitOut, y, width, height, (int)readS.pos());
+						return false;
+					}
+					for (int bitIn = 0; bitIn < bitsPerEntry; bitIn++) {
+						int realX = x + (bitsPerEntry - 1 - bitIn);
+						if (realX >= width) {
+							continue;
+						}
+						outPointer[y * outPitch + realX] =
+							(outPointer[y * outPitch + realX] & ~(1 << bitOut)) | (((val >> bitIn) & 1) << bitOut);
+					}
+				}
+				if (bitsPerEntry < 8) {
+					byte mask = (byte) ~(0xff << bitsPerEntry);
+					for (c = 0, y -= fg_runcount; c < fg_runcount; c++, y++) {
+						for (int z = 0; z < bitsPerEntry; z++) {
+							int realX = x + z;
+							if (realX >= width) {
+								continue;
+							}
+							outPointer[y * outPitch + realX] &= mask;
+						}
+					}
+				}
+				if (fg_runcount == 0 && bg_runcount == 0) {
+					warning("Sprite zero-sized run: coord=%d+%dx%d, size=%dx%d, pos=%d",
+						x, bitOut, y, width, height, (int)readS.pos());
+					return false;
+				}
+			}
+		}
+	return true;
+}
+
+}
 #define RID_IHNM_ARROW_SPRITES 13
 #define RID_IHNM_SAVEREMINDER_SPRITES 14
 #define RID_IHNMDEMO_ARROW_SPRITES 8
@@ -92,7 +169,7 @@ void Sprite::loadList(int resourceId, SpriteList &spriteList) {
 
 	for (uint i = oldSpriteCount; i < spriteList.size(); i++) {
 		uint32 offset;
-		if (bigHeader)
+		if (bigHeader || _vm->isITEAmiga())
 			offset = readS.readUint32();
 		else
 			offset = readS.readUint16();
@@ -134,7 +211,15 @@ void Sprite::loadList(int resourceId, SpriteList &spriteList) {
 		int inputLength = spriteListData.size() - (spriteDataPointer - spriteListData.getBuffer());
 		spriteInfo->decodedBuffer.resize(outputLength);
 		if (outputLength > 0) {
-			decodeRLEBuffer(spriteDataPointer, inputLength, outputLength);
+			if (_vm->isAGA() || _vm->isECS()) {
+				_decodeBuf.resize(spriteInfo->width * spriteInfo->height);
+				memset(&_decodeBuf.front(), 0, _decodeBuf.size());
+				if (_vm->isAGA())
+					blitAmigaSprite<8, 16>(&_decodeBuf.front(), spriteInfo->width, spriteDataPointer, inputLength, spriteInfo->width, spriteInfo->height);
+				else
+					blitAmigaSprite<4, 8>(&_decodeBuf.front(), spriteInfo->width, spriteDataPointer, inputLength, spriteInfo->width, spriteInfo->height);
+			} else
+				decodeRLEBuffer(spriteDataPointer, inputLength, outputLength);
 			byte *dst = &spriteInfo->decodedBuffer.front();
 #ifdef ENABLE_IHNM
 			// IHNM sprites are upside-down, for reasons which i can only


Commit: 03c1d029a111558abdc89e3be1741360e1252081
    https://github.com/scummvm/scummvm/commit/03c1d029a111558abdc89e3be1741360e1252081
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2022-11-14T00:27:33+01:00

Commit Message:
SAGA: Make unknown scene descriptor size an error

Wrong size usually means that we've got the wrong resource. Just error
out as continueing is futile

Changed paths:
    engines/saga/scene.cpp


diff --git a/engines/saga/scene.cpp b/engines/saga/scene.cpp
index 770114466b5..68246d477bf 100644
--- a/engines/saga/scene.cpp
+++ b/engines/saga/scene.cpp
@@ -864,7 +864,7 @@ void Scene::loadSceneDescriptor(uint32 resourceId) {
 		if (sceneDescriptorData.size() == 16)
 			_sceneDescription.musicResourceId = readS.readSint16();
 	} else {
-		warning("Scene::loadSceneDescriptor: Unknown scene descriptor data size (%d)", sceneDescriptorData.size());
+		error("Scene::loadSceneDescriptor: Unknown scene descriptor data size (%d)", sceneDescriptorData.size());
 	}
 }
 


Commit: 5a431670d419f2f34333afa27ef0e306599fa257
    https://github.com/scummvm/scummvm/commit/5a431670d419f2f34333afa27ef0e306599fa257
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2022-11-14T00:27:33+01:00

Commit Message:
SAGA: Disable music on Amiga

Not implemented yet.

Changed paths:
    engines/saga/music.cpp


diff --git a/engines/saga/music.cpp b/engines/saga/music.cpp
index 222ead0e2ec..71653678270 100644
--- a/engines/saga/music.cpp
+++ b/engines/saga/music.cpp
@@ -466,6 +466,8 @@ void Music::playQuickTime(uint32 resourceId, MusicFlags flags) {
 }
 
 void Music::playMidi(uint32 resourceId, MusicFlags flags) {
+	if (_vm->isITEAmiga()) // Not supported yet
+		return;
 	if (_currentMusicBuffer == &_musicBuffer[1]) {
 		_currentMusicBuffer = &_musicBuffer[0];
 	} else {


Commit: 8fde889532c52af853b17889d6343ad621027fd6
    https://github.com/scummvm/scummvm/commit/8fde889532c52af853b17889d6343ad621027fd6
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2022-11-14T00:27:33+01:00

Commit Message:
SAGA: Support reading Amiga resources

Changed paths:
    engines/saga/resource.cpp
    engines/saga/resource.h


diff --git a/engines/saga/resource.cpp b/engines/saga/resource.cpp
index 8de7718101a..6374d839b77 100644
--- a/engines/saga/resource.cpp
+++ b/engines/saga/resource.cpp
@@ -35,6 +35,27 @@
 
 namespace Saga {
 
+bool ResourceContext::loadResIteAmiga(uint32 contextOffset, uint32 contextSize, int type) {
+	_file.seek(contextOffset);
+	uint16 resourceCount = _file.readUint16BE();
+	uint16 scriptCount = _file.readUint16BE();
+	uint32 count = (type &  GAME_SCRIPTFILE) ? scriptCount : resourceCount;
+
+	if (type &  GAME_SCRIPTFILE)
+		_file.seek(resourceCount * 10, SEEK_CUR);
+
+	_table.resize(count);
+
+	for (uint32 i = 0; i < count; i++) {
+		ResourceData *resourceData = &_table[i];
+		resourceData->offset = _file.readUint32BE();
+		resourceData->size = _file.readUint32BE();
+		resourceData->diskNum = _file.readUint16BE();
+	}
+
+	return true;
+}
+
 bool ResourceContext::loadResV1(uint32 contextOffset, uint32 contextSize) {
 	size_t i;
 	bool result;
@@ -116,14 +137,15 @@ bool ResourceContext::load(SagaEngine *vm, Resource *resource) {
 			_file.seek(83);
 			uint32 macDataSize = _file.readSint32BE();
 			// Skip the MacBinary headers, and read the resource data.
-			return loadRes(MAC_BINARY_HEADER_SIZE, macDataSize);
+			return loadRes(MAC_BINARY_HEADER_SIZE, macDataSize, _fileType);
 		} else {
 			// Unpack MacBinary packed MIDI files
 			return loadMacMIDI();
 		}
 	}
 
-	if (!loadRes(0, _fileSize))
+
+	if (!loadRes(0, _fileSize, _fileType))
 		return false;
 
 	processPatches(resource, vm->getPatchDescriptions());
@@ -170,6 +192,8 @@ bool Resource::createContexts() {
 		gameFileDescription->fileName; gameFileDescription++) {
 		if (gameFileDescription->fileType > 0)
 			addContext(gameFileDescription->fileName, gameFileDescription->fileType);
+		if ((gameFileDescription->fileType & GAME_RESOURCEFILE) && _vm->getPlatform() == Common::kPlatformAmiga && _vm->getGameId() == GID_ITE)
+			addContext(gameFileDescription->fileName, (gameFileDescription->fileType & ~GAME_RESOURCEFILE) | GAME_SCRIPTFILE | GAME_SWAPENDIAN);
 		if (gameFileDescription->fileType == GAME_SOUNDFILE) {
 			soundFileInArray = true;
 		}
@@ -312,9 +336,24 @@ void Resource::clearContexts() {
 
 void Resource::loadResource(ResourceContext *context, uint32 resourceId, ByteArray &resourceBuffer) {
 	ResourceData *resourceData = context->getResourceData(resourceId);
-	Common::File *file = context->getFile(resourceData);
+	Common::File *file = nullptr;
 	uint32 resourceOffset = resourceData->offset;
 
+	if (resourceData->diskNum < 0)
+		file = context->getFile(resourceData);
+	else {
+		file = new Common::File();
+		Common::String fileName = context->_fileName;
+		int sz = fileName.size();
+		while(sz > 0 && fileName[sz - 1] != '.')
+			sz--;
+		if (sz > 0)
+			sz--;
+		fileName = Common::String::format("%s.%03d", fileName.substr(0, sz).c_str(), resourceData->diskNum);
+		if (!file->open(fileName))
+			error("Resource::loadResource() failed to open %s", fileName.c_str());
+	}
+
 	debug(8, "loadResource %d 0x%X:0x%X", resourceId, resourceOffset, uint(resourceData->size));
 	resourceBuffer.resize(resourceData->size);
 
diff --git a/engines/saga/resource.h b/engines/saga/resource.h
index fc896a6f565..b583a78d481 100644
--- a/engines/saga/resource.h
+++ b/engines/saga/resource.h
@@ -60,10 +60,11 @@ struct PatchData {
 struct ResourceData {
 	size_t offset;
 	size_t size;
+	int diskNum;
 	PatchData *patchData;
 
 	ResourceData() :
-		offset(0), size(0), patchData(NULL) {
+		offset(0), size(0), patchData(NULL), diskNum(-1) {
 	}
 
 	~ResourceData() {
@@ -134,9 +135,10 @@ protected:
 
 	bool load(SagaEngine *_vm, Resource *resource);
 	bool loadResV1(uint32 contextOffset, uint32 contextSize);
+	bool loadResIteAmiga(uint32 contextOffset, uint32 contextSize, int type);
 
 	virtual bool loadMacMIDI() { return false; }
-	virtual bool loadRes(uint32 contextOffset, uint32 contextSize) = 0;
+	virtual bool loadRes(uint32 contextOffset, uint32 contextSize, int type) = 0;
 	virtual void processPatches(Resource *resource, const GamePatchDescription *patchFiles) { }
 };
 
@@ -193,12 +195,19 @@ protected:
 class ResourceContext_RSC: public ResourceContext {
 protected:
 	bool loadMacMIDI() override;
-	bool loadRes(uint32 contextOffset, uint32 contextSize) override {
+	bool loadRes(uint32 contextOffset, uint32 contextSize, int type) override {
 		return loadResV1(contextOffset, contextSize);
 	}
 	void processPatches(Resource *resource, const GamePatchDescription *patchFiles) override;
 };
 
+class ResourceContext_RSC_ITE_Amiga: public ResourceContext {
+protected:
+	bool loadRes(uint32 contextOffset, uint32 contextSize, int type) override {
+		return loadResIteAmiga(contextOffset, contextSize, type);
+	}
+};
+
 class Resource_RSC : public Resource {
 public:
 	Resource_RSC(SagaEngine *vm) : Resource(vm) {}
@@ -212,6 +221,8 @@ public:
 	}
 protected:
 	ResourceContext *createContext() override {
+		if (_vm->getPlatform() == Common::kPlatformAmiga && _vm->getGameId() == GID_ITE)
+			return new ResourceContext_RSC_ITE_Amiga();
 		return new ResourceContext_RSC();
 	}
 };
@@ -220,7 +231,7 @@ protected:
 // IHNM
 class ResourceContext_RES: public ResourceContext {
 protected:
-	bool loadRes(uint32 contextOffset, uint32 contextSize) override {
+	bool loadRes(uint32 contextOffset, uint32 contextSize, int type) override {
 		return loadResV1(0, contextSize);
 	}
 
@@ -230,7 +241,7 @@ protected:
 // TODO: move load routines from sndres
 class VoiceResourceContext_RES: public ResourceContext {
 protected:
-	bool loadRes(uint32 contextOffset, uint32 contextSize) override {
+	bool loadRes(uint32 contextOffset, uint32 contextSize, int type) override {
 		return false;
 	}
 public:


Commit: 0c56fe819aefcceea35e412d5526c84fd378e944
    https://github.com/scummvm/scummvm/commit/0c56fe819aefcceea35e412d5526c84fd378e944
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2022-11-14T00:27:33+01:00

Commit Message:
SAGA: Treat resources with "ECHO is on\r\n" as invalid

There are some number of them in Amiga build but they're invalid. Skip them

Changed paths:
    engines/saga/scene.cpp


diff --git a/engines/saga/scene.cpp b/engines/saga/scene.cpp
index 68246d477bf..c16a44b9bde 100644
--- a/engines/saga/scene.cpp
+++ b/engines/saga/scene.cpp
@@ -925,6 +925,12 @@ void Scene::processSceneResources(SceneResourceDataArray &resourceList, SceneLoa
 			}
 		}
 
+		// Thos resources are bogus. Skip them
+		if (_vm->isITEAmiga() && resourceData.size() == 12 && memcmp(resourceData.getBuffer(), "ECHO is on\r\n", 12) == 0) {
+			resource->invalid = true;
+			warning("DUMMY resource %i", resource->resourceId);
+		}
+
 		if (resource->invalid) {
 			continue;
 		}


Commit: f90c541b9ba6b0744af5fe7d20158995fc9d8a14
    https://github.com/scummvm/scummvm/commit/f90c541b9ba6b0744af5fe7d20158995fc9d8a14
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2022-11-14T00:27:33+01:00

Commit Message:
SAGA: Use screen height if bgmask height is zero

Changed paths:
    engines/saga/scene.cpp


diff --git a/engines/saga/scene.cpp b/engines/saga/scene.cpp
index c16a44b9bde..551ac08f5e9 100644
--- a/engines/saga/scene.cpp
+++ b/engines/saga/scene.cpp
@@ -528,14 +528,19 @@ bool Scene::offscreenPath(Point &testPoint) {
 		return false;
 	}
 
+	int h = _bgMask.h;
+
+	if (h == 0)
+		h = _vm->getDisplayInfo().height;
+
 	point.x = CLIP<int>(testPoint.x, 0, _vm->getDisplayInfo().width - 1);
-	point.y = CLIP<int>(testPoint.y, 0, _bgMask.h - 1);
+	point.y = CLIP<int>(testPoint.y, 0, h - 1);
 	if (point == testPoint) {
 		return false;
 	}
 
-	if (point.y >= _bgMask.h - 1) {
-		point.y = _bgMask.h - 2;
+	if (point.y >= h - 1) {
+		point.y = h - 2;
 	}
 	testPoint = point;
 


Commit: 9fae5e4efd563c4db2c450faa3b655407e116058
    https://github.com/scummvm/scummvm/commit/9fae5e4efd563c4db2c450faa3b655407e116058
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2022-11-14T00:27:33+01:00

Commit Message:
SAGA: Load module strings as little-endian

No idea why they're stored this way

Changed paths:
    engines/saga/script.cpp


diff --git a/engines/saga/script.cpp b/engines/saga/script.cpp
index b583886a9ff..32f89d405fb 100644
--- a/engines/saga/script.cpp
+++ b/engines/saga/script.cpp
@@ -906,7 +906,7 @@ void Script::loadModule(uint scriptModuleNumber) {
 
 	_vm->_resource->loadResource(_scriptContext, _modules[scriptModuleNumber].stringsResourceId, resourceData);
 
-	_vm->loadStrings(_modules[scriptModuleNumber].strings, resourceData, _vm->isBigEndian());
+	_vm->loadStrings(_modules[scriptModuleNumber].strings, resourceData, _vm->isBigEndian() && !_vm->isITEAmiga());
 
 	if (_modules[scriptModuleNumber].voicesResourceId > 0) {
 		_vm->_resource->loadResource(_scriptContext, _modules[scriptModuleNumber].voicesResourceId, resourceData);


Commit: 002ec9cf035623b542622609f14d8cbdd17193fd
    https://github.com/scummvm/scummvm/commit/002ec9cf035623b542622609f14d8cbdd17193fd
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2022-11-14T00:27:33+01:00

Commit Message:
SAGA: Adjust isNonInteractiveDemo for Amiga

On Amiga main resource file is just an index, so it's very small even on
the full game

Changed paths:
    engines/saga/script.cpp


diff --git a/engines/saga/script.cpp b/engines/saga/script.cpp
index 32f89d405fb..5544e6e44bb 100644
--- a/engines/saga/script.cpp
+++ b/engines/saga/script.cpp
@@ -1129,7 +1129,7 @@ void Script::setVerb(int verb) {
 bool Script::isNonInteractiveDemo() {
 	// This detection only works in ITE. The early non-interactive demos had
 	// a very small script file
-	return _vm->getGameId() == GID_ITE && _scriptContext->fileSize() < 50000;
+	return _vm->getGameId() == GID_ITE && _scriptContext->fileSize() < 50000 && !_vm->isITEAmiga();
 }
 
 void Script::setLeftButtonVerb(int verb) {


Commit: 63684ea1cf67d00931d19d95c3eeb941c3b6745c
    https://github.com/scummvm/scummvm/commit/63684ea1cf67d00931d19d95c3eeb941c3b6745c
Author: Vladimir Serbinenko (phcoder at gmail.com)
Date: 2022-11-14T00:27:33+01:00

Commit Message:
SAGA: Add detection entries for ITE Amiga CD-ROMs

Changed paths:
    engines/saga/detection_tables.h


diff --git a/engines/saga/detection_tables.h b/engines/saga/detection_tables.h
index 4ca3bf1c670..48154e9ffa7 100644
--- a/engines/saga/detection_tables.h
+++ b/engines/saga/detection_tables.h
@@ -29,6 +29,44 @@
 
 namespace Saga {
 
+static const GameResourceDescription ITE_Resources_GermanAGACD = {
+	1810,	// Scene lookup table RN
+	216,	// Script lookup table RN
+	3,		// Main panel
+	4,		// Converse panel
+	5,		// Option panel
+	6,		// Main sprites
+	7,		// Main panel sprites
+	35,		// Main strings
+	// ITE specific resources
+	36,		// Actor names
+	125,	// Default portraits
+	// IHNM specific resources
+	0,		// Option panel sprites
+	0,		// Warning panel
+	0,		// Warning panel sprites
+	0		// Psychic profile background
+};
+
+static const GameResourceDescription ITE_Resources_GermanECSCD = {
+	1816,	// Scene lookup table RN
+	216,	// Script lookup table RN
+	3,		// Main panel
+	4,		// Converse panel
+	5,		// Option panel
+	6,		// Main sprites
+	7,		// Main panel sprites
+	35,		// Main strings
+	// ITE specific resources
+	36,		// Actor names
+	125,	// Default portraits
+	// IHNM specific resources
+	0,		// Option panel sprites
+	0,		// Warning panel
+	0,		// Warning panel sprites
+	0		// Psychic profile background
+};
+
 static const GameResourceDescription ITE_Resources = {
 	1806,	// Scene lookup table RN
 	216,	// Script lookup table RN
@@ -48,6 +86,25 @@ static const GameResourceDescription ITE_Resources = {
 	0		// Psychic profile background
 };
 
+static const GameResourceDescription ITE_Resources_EnglishECSCD = {
+	1812,	// Scene lookup table RN
+	216,	// Script lookup table RN
+	3,		// Main panel
+	4,		// Converse panel
+	5,		// Option panel
+	6,		// Main sprites
+	7,		// Main panel sprites
+	35,		// Main strings
+	// ITE specific resources
+	36,		// Actor names
+	125,	// Default portraits
+	// IHNM specific resources
+	0,		// Option panel sprites
+	0,		// Warning panel
+	0,		// Warning panel sprites
+	0		// Psychic profile background
+};
+
 // FIXME: Option panel should be 4 but it is an empty resource.
 // Proper fix would be to not load the options panel when the demo is running
 static const GameResourceDescription ITEDemo_Resources = {
@@ -143,6 +200,45 @@ LoadSceneParams ITE_IntroListDefault[] = {
 	{0, kLoadByResourceId, nullptr, false, kTransitionNoFade, 0, 0}
 };
 
+static const LoadSceneParams ITE_AmigaEnglishECSCD_IntroList[] = {
+//	{1544, kLoadByResourceId, SceneHandlers::SC_ITEIntroAnimProc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE}, // Crashes, skip for now
+	{1548, kLoadByResourceId, SceneHandlers::SC_ITEIntroCave1Proc, false, kTransitionFade, 0, NO_CHAPTER_CHANGE},
+	{1551, kLoadByResourceId, SceneHandlers::SC_ITEIntroCave2Proc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE},
+	{1554, kLoadByResourceId, SceneHandlers::SC_ITEIntroCave3Proc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE},
+	{1557, kLoadByResourceId, SceneHandlers::SC_ITEIntroCave4Proc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE},
+	{1562, (Saga::SceneLoadFlags) (kLoadByResourceId | kLoadBgMaskIsImage), SceneHandlers::SC_ITEIntroValleyProc, false, kTransitionFade, 0, NO_CHAPTER_CHANGE},
+	{1566, kLoadByResourceId, SceneHandlers::SC_ITEIntroTreeHouseProc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE},
+	{1570, kLoadByResourceId, SceneHandlers::SC_ITEIntroFairePathProc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE},
+	{1573, kLoadByResourceId, SceneHandlers::SC_ITEIntroFaireTentProc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE},
+	{0, kLoadByResourceId, nullptr, false, kTransitionNoFade, 0, 0}
+};
+
+static const LoadSceneParams ITE_AmigaGermanAGA_IntroList[] = {
+	{1538, kLoadByResourceId, SceneHandlers::SC_ITEIntroAnimProc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE},
+	{1543, kLoadByResourceId, SceneHandlers::SC_ITEIntroCave1Proc, false, kTransitionFade, 0, NO_CHAPTER_CHANGE},
+	{1547, kLoadByResourceId, SceneHandlers::SC_ITEIntroCave2Proc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE},
+	{1551, kLoadByResourceId, SceneHandlers::SC_ITEIntroCave3Proc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE},
+	{1555, kLoadByResourceId, SceneHandlers::SC_ITEIntroCave4Proc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE},
+	{1560, (Saga::SceneLoadFlags) (kLoadByResourceId | kLoadBgMaskIsImage), SceneHandlers::SC_ITEIntroValleyProc, false, kTransitionFade, 0, NO_CHAPTER_CHANGE},
+	{1564, kLoadByResourceId, SceneHandlers::SC_ITEIntroTreeHouseProc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE},
+	{1568, kLoadByResourceId, SceneHandlers::SC_ITEIntroFairePathProc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE},
+	{1571, kLoadByResourceId, SceneHandlers::SC_ITEIntroFaireTentProc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE},
+	{0, kLoadByResourceId, nullptr, false, kTransitionNoFade, 0, 0}
+};
+
+static const LoadSceneParams ITE_AmigaGermanECS_IntroList[] = {
+	{1544, kLoadByResourceId, SceneHandlers::SC_ITEIntroAnimProc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE},
+	{1549, kLoadByResourceId, SceneHandlers::SC_ITEIntroCave1Proc, false, kTransitionFade, 0, NO_CHAPTER_CHANGE},
+	{1553, kLoadByResourceId, SceneHandlers::SC_ITEIntroCave2Proc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE},
+	{1557, kLoadByResourceId, SceneHandlers::SC_ITEIntroCave3Proc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE},
+	{1561, kLoadByResourceId, SceneHandlers::SC_ITEIntroCave4Proc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE},
+	{1566, (Saga::SceneLoadFlags) (kLoadByResourceId | kLoadBgMaskIsImage), SceneHandlers::SC_ITEIntroValleyProc, false, kTransitionFade, 0, NO_CHAPTER_CHANGE},
+	{1570, kLoadByResourceId, SceneHandlers::SC_ITEIntroTreeHouseProc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE},
+	{1574, kLoadByResourceId, SceneHandlers::SC_ITEIntroFairePathProc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE},
+	{1577, kLoadByResourceId, SceneHandlers::SC_ITEIntroFaireTentProc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE},
+	{0, kLoadByResourceId, nullptr, false, kTransitionNoFade, 0, 0}
+};
+
 static const LoadSceneParams ITE_DOS_Demo_IntroList[] = {
 	{RID_ITE_INTRO_ANIM_SCENE_DOS_DEMO, kLoadByResourceId, SceneHandlers::SC_ITEIntroAnimProc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE},
 	{RID_ITE_CAVE_SCENE_DOS_DEMO, kLoadByResourceId, SceneHandlers::SC_ITEIntroCaveDemoProc, false, kTransitionFade, 0, NO_CHAPTER_CHANGE},
@@ -1124,7 +1220,100 @@ static const SAGAGameDescription gameDescriptions[] = {
 
 	// ITE Amiga versions /////////////////////////////////////////////////////////////////////////////////////
 
-	// TODO: Add the Amiga versions here (not supported yet)
+	// Official Dreamers Guild German release
+	{
+		{
+			"ite",
+			"AGA CD",
+			{
+				{"ite.rtn",		GAME_RESOURCEFILE,	"9d97f645eb877d1c9eb9d906930c3257", 18564},
+				AD_LISTEND
+			},
+			Common::DE_DEU,
+			Common::kPlatformAmiga,
+			ADGF_CD,
+			GUIO0()
+		},
+		GID_ITE,
+		GF_EXTRA_ITE_CREDITS | GF_AGA_GRAPHICS,
+		ITE_DEFAULT_SCENE,
+		&ITE_Resources_GermanAGACD,
+		ARRAYSIZE(ITE_GameFonts),
+		ITE_GameFonts,
+		ITEPatch_Files,
+		ITE_AmigaGermanAGA_IntroList,
+	},
+	// This is on the same disk as previous but it's for ECS systems
+	{
+		{
+			"ite",
+			"ECS CD",
+			{
+				{"ecs.rtn",		GAME_RESOURCEFILE,	"62d738d3201c1624f0e4bfcc8fb587dd", 18624},
+				AD_LISTEND
+			},
+			Common::DE_DEU,
+			Common::kPlatformAmiga,
+			ADGF_CD,
+			GUIO0()
+		},
+		GID_ITE,
+		GF_EXTRA_ITE_CREDITS | GF_ECS_GRAPHICS,
+		ITE_DEFAULT_SCENE,
+		&ITE_Resources_GermanECSCD,
+		ARRAYSIZE(ITE_GameFonts),
+		ITE_GameFonts,
+		ITEPatch_Files,
+		ITE_AmigaGermanECS_IntroList,
+	},
+	// Amiga Future coverdisk/Wyrmkeep English edition
+	{
+		{
+			"ite",
+			"AGA CD",
+			{
+				{"ite.rtn",		GAME_RESOURCEFILE,	"749885c0f7eaab4e977dc26a41d99ad8", 18524},
+				AD_LISTEND
+			},
+			Common::EN_ANY,
+			Common::kPlatformAmiga,
+			ADGF_CD,
+			GUIO0()
+		},
+		GID_ITE,
+		GF_EXTRA_ITE_CREDITS | GF_AGA_GRAPHICS,
+		ITE_DEFAULT_SCENE,
+		&ITE_Resources,
+		ARRAYSIZE(ITE_GameFonts),
+		ITE_GameFonts,
+		ITEPatch_Files,
+		ITE_IntroListDefault + 1, // Skip first (logo) scene until we figure it out
+	},
+	// This is on the same disk as previous but it's for ECS systems
+	{
+		{
+			"ite",
+			"ECS CD",
+			{
+				{"ecs.rtn",		GAME_RESOURCEFILE,	"c9d09514839d771efdc82ad761413349", 18584},
+				AD_LISTEND
+			},
+			Common::EN_ANY,
+			Common::kPlatformAmiga,
+			ADGF_CD,
+			GUIO0()
+		},
+		GID_ITE,
+		GF_EXTRA_ITE_CREDITS | GF_ECS_GRAPHICS,
+		ITE_DEFAULT_SCENE,
+		&ITE_Resources_EnglishECSCD,
+		ARRAYSIZE(ITE_GameFonts),
+		ITE_GameFonts,
+		ITEPatch_Files,
+		ITE_AmigaEnglishECSCD_IntroList,
+	},
+
+	// TODO: Add Amiga floppy versions
 
 	// IHNM Section ///////////////////////////////////////////////////////////////////////////////////////////
 




More information about the Scummvm-git-logs mailing list