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

sev- noreply at scummvm.org
Thu Jun 23 18:11:40 UTC 2022


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

Summary:
6b34453b53 GLK: SCOTT: Create C64_checksums.h/cpp
d1121b3c71 GLK: SCOTT: Add game_specific.h/cpp
dd9890ca4d GLK: SCOTT: Add C64 detection
b7b3d58002 GLK: SCOTT: Implement detectC64 in C64_checksums.cpp
09d2b9792b JANITORIAL: Fix header guard naming
464bfdd3cc GLK: SCOTT: Rename C64_checksums to c64_checksums
d6d67b40bb JANITORIAL: Formatting fixes
95c20b538c GLK: SCOTT: Reorder header includes
5aa305e716 GLK: SCOTT: Replace unsigned char with byte
cf55512f80 GLK: SCOTT: Improve error messages
8c2d9e2b7c GLK: SCOTT: Use READ_LE_UINT16
9c4c8af24c GLK: SCOTT: Refactor detect_game
6a0074fe74 GLK: SCOTT: Refactor c64_checksums
ba59cd4c19 GLK: SCOTT: Implement mysteriousMenu and mysteriousMenu2
f453dd8c1b GLK: SCOTT: Add disk_image.h/cpp
dfec9279e1 GLK: SCOTT: Implement getFileNamed
17939767f2 GLK: SCOTT: Implement diOpen
5c3cd93aa9 GLK: SCOTT: Implement diRead
5682465f11 GLK: SCOTT: Implement diGetTsAddr
b808b769b2 GLK: SCOTT: Implement diGetTsErr
03def01209 GLK: SCOTT: Implement diGetBlockNum
25201be1f8 GLK: SCOTT: Implement diGetDirTs
e739547bca GLK: SCOTT: Implement diRawnameFromName
2855ea2e37 GLK: SCOTT: Implement diCreateFromData
14afa5f90f GLK: SCOTT: Implement setStatus
1f333dc3c7 GLK: SCOTT: Implement diTsIsValid
25827d6a8c GLK: SCOTT: Implement diSectorsPerTrack
fd1bb95cea GLK: SCOTT: Implement diTracks
bca64c76bf GLK: SCOTT: Implement findFileEntry
c4fbd8f283 GLK: SCOTT: Implement matchPattern
5ba5ac2f7a GLK: SCOTT: Implement nextTsInChain
1209ca3072 GLK: SCOTT: Implement allocFileEntry
2cf15d1289 GLK: SCOTT: Implement allocNextDirTs
3dde6cfb4b GLK: SCOTT: Implement diTrackBlocksFree
feafc98c3c GLK: SCOTT: Implement diIsTsFree
63909041b3 GLK: SCOTT: Implement diAllocTs
f2c37fe610 GLK: SCOTT: Implement getTsDosErr
a2962c4b43 GLK: SCOTT: Implement blocksFree
eb354e9929 GLK: SCOTT: Implement interleave
a2ef20d0d7 JANITORIAL: Formatting fixes
9f7a9a4493 GLK: SCOTT: Implement decrunchC64
136960a795 GLK: SCOTT: Implement unp64
9fb22510fd JANITORIAL: Fix formatting
be0db5ba1c GLK: SCOTT: Implement 6502 CPU emulation
e581ff0714 GLK: SCOTT: Implement strToInt
acccd129c9 GLK: SCOTT: Implement loadData
b3e54065c9 GLK: SCOTT: Implement findSys
dda8a0febc GLK: SCOTT: Implement isBasicRun1 and isBasicRun2
45f7e4751e GLK: SCOTT: Replace error with warning
20090e73ed GLK: SCOTT: Implement action_packer.cpp
e28dd2b39c GLK: SCOTT: Implement byte_boiler.cpp
9bb67453a0 GLK: SCOTT: Implement caution.cpp
92d62985cc GLK: SCOTT: Implement ccs.cpp
731e0a3f07 GLK: SCOTT: Implement cruel.cpp
0c1f97c0e4 GLK: SCOTT: Implement eca.cpp
bc928dd14f GLK: SCOTT: Implement exomizer.cpp
ccc9e29b75 GLK: SCOTT: Implement expert.cpp
103b17df5d GLK: SCOTT: Implement master_compressor.cpp
825efc500a GLK: SCOTT: Implement megabyte.cpp
81e0cb9bc5 GLK: SCOTT: Implement pu_crunch.cpp
749e7e8dc1 GLK: SCOTT: Implement section8.cpp
3173dfa41b GLK: SCOTT: Implement tbc_multicomp.cpp
c20baf8873 GLK: SCOTT: Implement tcs_crunch.cpp
72076286b6 GLK: SCOTT: Implement xtc.cpp
92ea152c35 GLK: SCOTT: Implement scanners
767586218d GLK: SCOTT: Implement copyData
2356c0d634 GLK: SCOTT: Remove unused gamedata
b20b095e84 GLK: SCOTT: Update game loading to use new game list
1ec46bdd30 GLK: SCOTT: Update license header
f591a6a186 GLK: SCOTT: Add support for Robin of Sherwood
7194234ea6 GLK: SCOTT: Update game detection to use entire file for MD5 calculation of .D64 games
08ae841dc9 GLK: SCOTT: Add missing return statement
ac75abb20a GLK: SCOTT: Use READ_LE_UINT16 instead of READ_LE_INT16
5b032ee851 GLK: SCOTT: Fix out-of-bound errors
fd3b9bede3 GLK: SCOTT: Add language data to detected game
1e914b7e95 GLK: SCOTT: Add support for Gremlins
051d12497f GLK: SCOTT: Use C String instead of Common::String in GLK display
6a11c2bc10 GLK: SCOTT: Fix text decompression
98d5b72442 GLK: SCOTT: Add support for Seas of Blood
ecae491c20 GLK: SCOTT: Add support for Sorcerer of Claymorgue Castle
951e1a8240 GLK: SCOTT: Add support for Adventure Land
b45eecac99 GLK: SCOTT: Add support for Savage Island
ff02ca6def GLK: SCOTT: Add support for Questprobe Games
fd0b4ef953 GLK: SCOTT: Add more variants to game detection
0d4e18e5c7 GLK: SCOTT: Reorganise switch case
fdfd91fd7f GLK: SCOTT: Add support for Super Gran


Commit: 6b34453b5316e085b081c33b5c44886c623d2a31
    https://github.com/scummvm/scummvm/commit/6b34453b5316e085b081c33b5c44886c623d2a31
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Create C64_checksums.h/cpp

Changed paths:
  A engines/glk/scott/C64_checksums.cpp
  A engines/glk/scott/C64_checksums.h
    engines/glk/module.mk


diff --git a/engines/glk/module.mk b/engines/glk/module.mk
index b3b2d99a28b..5e12b0e774f 100644
--- a/engines/glk/module.mk
+++ b/engines/glk/module.mk
@@ -234,6 +234,7 @@ MODULE_OBJS := \
 	quest/read_file.o \
 	quest/string.o \
 	quest/streams.o \
+	scott/C64_checksums.o \
 	scott/command_parser.o \
 	scott/decompress_text.o \
 	scott/decompress_z80.o \
diff --git a/engines/glk/scott/C64_checksums.cpp b/engines/glk/scott/C64_checksums.cpp
new file mode 100644
index 00000000000..8359ae6c12f
--- /dev/null
+++ b/engines/glk/scott/C64_checksums.cpp
@@ -0,0 +1,32 @@
+/* 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 "glk/scott/C64_checksums.h"
+
+namespace Glk {
+namespace Scott {
+
+int detectC64(uint8_t **sf, size_t *extent) {
+	return 0;
+}
+
+} // End of namespace Scott
+} // End of namespace Glk
diff --git a/engines/glk/scott/C64_checksums.h b/engines/glk/scott/C64_checksums.h
new file mode 100644
index 00000000000..f89acbfd542
--- /dev/null
+++ b/engines/glk/scott/C64_checksums.h
@@ -0,0 +1,35 @@
+/* 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 GLK_SCOTT_C64CHECKSUMS
+#define GLK_SCOTT_C64CHECKSUMS
+
+#include "glk/scott/types.h"
+
+namespace Glk {
+namespace Scott {
+
+int detectC64(uint8_t **sf, size_t *extent);
+
+} // End of namespace Scott
+} // End of namespace Glk
+
+#endif


Commit: d1121b3c71ee14040a3b3d75a42d223147d6cbbd
    https://github.com/scummvm/scummvm/commit/d1121b3c71ee14040a3b3d75a42d223147d6cbbd
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Add game_specific.h/cpp

Changed paths:
  A engines/glk/scott/game_specific.cpp
  A engines/glk/scott/game_specific.h
    engines/glk/module.mk


diff --git a/engines/glk/module.mk b/engines/glk/module.mk
index 5e12b0e774f..6d59ed03831 100644
--- a/engines/glk/module.mk
+++ b/engines/glk/module.mk
@@ -241,6 +241,7 @@ MODULE_OBJS := \
 	scott/definitions.o \
 	scott/detect_game.o \
 	scott/game_info.o \
+	scott/game_specific.o \
 	scott/globals.o \
 	scott/hulk.o \
 	scott/layout_text.o \
diff --git a/engines/glk/scott/game_specific.cpp b/engines/glk/scott/game_specific.cpp
new file mode 100644
index 00000000000..3549cc90143
--- /dev/null
+++ b/engines/glk/scott/game_specific.cpp
@@ -0,0 +1,127 @@
+/* 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 "glk/scott/game_specific.h"
+#include "glk/scott/scott.h"
+#include "glk/scott/globals.h"
+#include "common/str.h"
+
+namespace Glk {
+namespace Scott {
+
+void mysterious64Sysmess() {
+	SysMessageType messageKey[] = {
+		NORTH,
+		SOUTH,
+		EAST,
+		WEST,
+		UP,
+		DOWN,
+		EXITS,
+		YOU_SEE,
+		YOU_ARE,
+		TOO_DARK_TO_SEE,
+		LIGHT_HAS_RUN_OUT,
+		LIGHT_RUNS_OUT_IN,
+		TURNS,
+		I_DONT_KNOW_HOW_TO,
+		SOMETHING,
+		I_DONT_KNOW_WHAT_A,
+		IS,
+		YOU_CANT_GO_THAT_WAY,
+		OK,
+		WHAT_NOW,
+		HUH,
+		YOU_HAVENT_GOT_IT,
+		INVENTORY,
+		YOU_DONT_SEE_IT,
+		THATS_BEYOND_MY_POWER,
+		DANGEROUS_TO_MOVE_IN_DARK,
+		DIRECTION,
+		YOU_FELL_AND_BROKE_YOUR_NECK,
+		YOURE_CARRYING_TOO_MUCH,
+		IM_DEAD,
+		PLAY_AGAIN,
+		RESUME_A_SAVED_GAME,
+		IVE_STORED,
+		TREASURES,
+		ON_A_SCALE_THAT_RATES,
+		YOU_CANT_DO_THAT_YET,
+		I_DONT_UNDERSTAND,
+		NOTHING,
+		YOUVE_SOLVED_IT,
+		YOUVE_SOLVED_IT};
+
+	for (int i = 0; i < 40; i++) {
+		_G(_sys)[messageKey[i]] = _G(_systemMessages)[i];
+	}
+
+	_G(_sys)[ITEM_DELIMITER] = " - ";
+	_G(_sys)[MESSAGE_DELIMITER] = "\n";
+
+	_G(_sys)[YOU_SEE] = "\nThings I can see:\n";
+
+	_G(_sys)[I_DONT_KNOW_HOW_TO] = "\"";
+	_G(_sys)[PLAY_AGAIN] = "The game is over, thanks for playing\nWant to play again ? ";
+
+	char *dictword = nullptr;
+	for (int i = 1; i <= 6; i++) {
+		dictword = new char[_G(_gameHeader)->_wordLength];
+		Common::strlcpy(dictword, _G(_sys)[i - 1].c_str(), _G(_gameHeader)->_wordLength);
+		_G(_nouns)[i] = dictword;
+	}
+
+	_G(_nouns)[0] = "ANY\0";
+
+	switch (CURRENT_GAME) {
+	case BATON_C64:
+		_G(_nouns)[79] = "CAST\0";
+		_G(_verbs)[79] = ".\0";
+		_G(_gameHeader)->_numWords = 79;
+		break;
+	case TIME_MACHINE_C64:
+		_G(_verbs)[86] = ".\0";
+		break;
+	case ARROW1_C64:
+		_G(_nouns)[82] = ".\0";
+		break;
+	case ARROW2_C64:
+		_G(_verbs)[80] = ".\0";
+		break;
+	case PULSAR7_C64:
+		_G(_nouns)[102] = ".\0";
+		break;
+	case CIRCUS_C64:
+		_G(_nouns)[96] = ".\0";
+		break;
+	case FEASIBILITY_C64:
+		_G(_nouns)[80] = ".\0";
+		break;
+	case PERSEUS_C64:
+		_G(_nouns)[82] = ".\0";
+		break;
+	default:
+		break;
+	}
+}
+
+} // End of namespace Scott
+} // End of namespace Glk
diff --git a/engines/glk/scott/game_specific.h b/engines/glk/scott/game_specific.h
new file mode 100644
index 00000000000..de4cbbec87c
--- /dev/null
+++ b/engines/glk/scott/game_specific.h
@@ -0,0 +1,33 @@
+/* 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 GLK_SCOTT_GAMESPECIFIC
+#define GLK_SCOTT_GAMESPECIFIC
+
+namespace Glk {
+namespace Scott {
+
+void mysterious64Sysmess();
+
+} // End of namespace Scott
+} // End of namespace Glk
+
+#endif


Commit: dd9890ca4d70262358e1d587baab2db394498d44
    https://github.com/scummvm/scummvm/commit/dd9890ca4d70262358e1d587baab2db394498d44
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Add C64 detection

Changed paths:
    engines/glk/scott/detect_game.cpp


diff --git a/engines/glk/scott/detect_game.cpp b/engines/glk/scott/detect_game.cpp
index eec6a784b69..efd6393db1a 100644
--- a/engines/glk/scott/detect_game.cpp
+++ b/engines/glk/scott/detect_game.cpp
@@ -31,6 +31,8 @@
 #include "glk/scott/line_drawing.h"
 #include "glk/scott/saga_draw.h"
 #include "glk/scott/scott.h"
+#include "glk/scott/C64_checksums.h"
+#include "glk/scott/game_specific.h"
 #include "common/str.h"
 
 namespace Glk {
@@ -414,14 +416,18 @@ GameIDType detectGame(Common::SeekableReadStream *f) {
 						}
 					}
 				}
+			} else if (!scumm_stricmp(p->_extra, "C64")) {
+				_G(_entireFile) = new uint8_t[_G(_fileLength)];
+				size_t result = f->read(_G(_entireFile), _G(_fileLength));
+				if (result != _G(_fileLength))
+					g_scott->fatal("File empty or read error!");
+
+				CURRENT_GAME = static_cast<GameIDType>(detectC64(&_G(_entireFile), &_G(_fileLength)));
 			}
 		}
 		// TODO
 		// TI99/4A Detection
 
-		// TODO
-		// C64 Detection
-
 		++p;
 	}
 
@@ -526,6 +532,10 @@ GameIDType detectGame(Common::SeekableReadStream *f) {
 		break;
 	}
 
+	if (!(_G(_game)->_subType & (C64 | MYSTERIOUS))) {
+		mysterious64Sysmess();
+	}
+
 	/* If it is a C64 or a Mysterious Adventures game, we have setup the graphics already */
 	if (!(_G(_game)->_subType & (C64 | MYSTERIOUS)) && _G(_game)->_numberOfPictures > 0) {
 		sagaSetup(0);


Commit: b7b3d58002b895c4895375c186f1baa7584375c7
    https://github.com/scummvm/scummvm/commit/b7b3d58002b895c4895375c186f1baa7584375c7
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Implement detectC64 in C64_checksums.cpp

Changed paths:
    engines/glk/scott/C64_checksums.cpp


diff --git a/engines/glk/scott/C64_checksums.cpp b/engines/glk/scott/C64_checksums.cpp
index 8359ae6c12f..3ac968f3634 100644
--- a/engines/glk/scott/C64_checksums.cpp
+++ b/engines/glk/scott/C64_checksums.cpp
@@ -20,11 +20,242 @@
  */
 
 #include "glk/scott/C64_checksums.h"
+#include "glk/scott/definitions.h"
+#include "glk/scott/scott.h"
 
 namespace Glk {
 namespace Scott {
 
+#define MAX_LENGTH 300000
+#define MIN_LENGTH 24
+
+enum FileType {
+	UNKNOWN_FILE_TYPE,
+	TYPE_D64,
+	TYPE_T64
+};
+
+struct C64Rec {
+	GameIDType _id;
+	size_t _length;
+	uint16_t _chk;
+	FileType _type;
+	int _decompressIterations;
+	const char *_switches;
+	const char *_appendFile;
+	int _parameter;
+	size_t _copySource;
+	size_t _copyDest;
+	size_t _copySize;
+	size_t _imgOffset;
+};
+
+static C64Rec g_C64Registry[] = {
+	{BATON_C64, 0x2ab00, 0xc3fc, TYPE_D64, 0}, // Mysterious Adventures C64 dsk 1
+	{TIME_MACHINE_C64, 0x2ab00, 0xc3fc, TYPE_D64, 0},
+	{ARROW1_C64, 0x2ab00, 0xc3fc, TYPE_D64, 0},
+	{ARROW2_C64, 0x2ab00, 0xc3fc, TYPE_D64, 0},
+	{PULSAR7_C64, 0x2ab00, 0xc3fc, TYPE_D64, 0},
+	{CIRCUS_C64, 0x2ab00, 0xc3fc, TYPE_D64, 0},
+
+	{FEASIBILITY_C64, 0x2ab00, 0x9eaa, TYPE_D64, 0}, // Mysterious Adventures C64 dsk 2
+	{AKYRZ_C64, 0x2ab00, 0x9eaa, TYPE_D64, 0},
+	{PERSEUS_C64, 0x2ab00, 0x9eaa, TYPE_D64, 0},
+	{INDIANS_C64, 0x2ab00, 0x9eaa, TYPE_D64, 0},
+	{WAXWORKS_C64, 0x2ab00, 0x9eaa, TYPE_D64, 0},
+	{BATON_C64, 0x2ab00, 0x9dca, TYPE_D64, 2},
+
+	{BATON_C64, 0x5170, 0xb240, TYPE_T64, 2},        // The Golden Baton C64, T64
+	{BATON_C64, 0x2ab00, 0xbfbf, TYPE_D64, 2},       // Mysterious Adventures C64 dsk 1 alt
+	{FEASIBILITY_C64, 0x2ab00, 0x9c18, TYPE_D64, 2}, // Mysterious Adventures C64 dsk 2 alt
+	{TIME_MACHINE_C64, 0x5032, 0x5635, TYPE_T64, 1}, // The Time Machine C64
+	{ARROW1_C64, 0x5b46, 0x92db, TYPE_T64, 1},       // Arrow of Death part 1 C64
+	{ARROW2_C64, 0x5fe2, 0xe14f, TYPE_T64, 1},       // Arrow of Death part 2 C64
+	{PULSAR7_C64, 0x46bf, 0x1679, TYPE_T64, 1},      // Escape from Pulsar 7 C64
+	{CIRCUS_C64, 0x4269, 0xa449, TYPE_T64, 2},       // Circus C64
+	{FEASIBILITY_C64, 0x5a7b, 0x0f48, TYPE_T64, 1},  // Feasibility Experiment C64
+	{AKYRZ_C64, 0x2ab00, 0x6cca, TYPE_D64, 0},       // The Wizard of Akyrz C64
+	{AKYRZ_C64, 0x4be1, 0x5a00, TYPE_T64, 1},        // The Wizard of Akyrz C64, T64
+	{PERSEUS_C64, 0x502b, 0x913b, TYPE_T64, 1},      // Perseus and Andromeda C64
+	{INDIANS_C64, 0x4f9f, 0xe6c8, TYPE_T64, 1},      // Ten Little Indians C64
+	{WAXWORKS_C64, 0x4a11, 0xa37a, TYPE_T64, 1},     // Waxworks C64
+
+	{ADVENTURELAND_C64, 0x6a10, 0x1910, TYPE_T64,
+	 1}, // Adventureland C64 (T64) CruelCrunch v2.2
+	{ADVENTURELAND_C64, 0x6a10, 0x1b10, TYPE_T64, 1, nullptr, nullptr, 0, 0,
+	 0}, // Adventureland C64 (T64) alt CruelCrunch v2.2
+	{ADVENTURELAND_C64, 0x2ab00, 0x6638, TYPE_D64, 1, nullptr, nullptr, 0, 0,
+	 0}, // Adventureland C64 (D64) CruelCrunch v2.2
+	{ADVENTURELAND_C64, 0x2adab, 0x751f, TYPE_D64, 0, nullptr, nullptr, 0, 0,
+	 0}, // Adventureland C64 (D64) alt
+	{ADVENTURELAND_C64, 0x2adab, 0x64a4, TYPE_D64, 0, nullptr, "SAG1PIC", -0xa53,
+	 0, 0, 0, 0x65af}, // Adventureland C64 (D64) alt 2
+
+	{SECRET_MISSION_C64, 0x88be, 0xa122, TYPE_T64, 1, nullptr, nullptr, 0, 0,
+	 0}, // Secret Mission  C64 (T64) Section8 Packer
+	{SECRET_MISSION_C64, 0x2ab00, 0x04d6, TYPE_D64, 0, nullptr, nullptr, 0, 0, 0, 0,
+	 -0x1bff}, // Secret Mission  C64 (D64)
+
+	{CLAYMORGUE_C64, 0x6ff7, 0xe4ed, TYPE_T64, 3, nullptr, nullptr, 0, 0x855, 0x7352,
+	 0x20}, // Sorcerer Of Claymorgue Castle C64 (T64), MasterCompressor / Relax
+	// -> ECA Compacker -> MegaByte Cruncher v1.x Missing 17 pictures
+	{CLAYMORGUE_C64, 0x912f, 0xa69f, TYPE_T64, 1, nullptr, nullptr, 0, 0x855, 0x7352,
+	 0x20}, // Sorcerer Of Claymorgue Castle C64 (T64) alt, MegaByte Cruncher
+	// v1.x Missing 17 pictures
+	{CLAYMORGUE_C64, 0xc0dd, 0x3701, TYPE_T64, 1, nullptr, nullptr, 0, 0, 0, 0,
+	 -0x7fe}, // Sorcerer Of Claymorgue Castle C64 (T64) alt 2, Trilogic Expert
+	// v2.7
+	{CLAYMORGUE_C64, 0xbc5f, 0x492c, TYPE_T64, 1, nullptr, nullptr, 0, 0x855, 0x7352,
+	 0x20}, // Sorcerer Of Claymorgue Castle C64 (T64) alt 3, , Section8 Packer
+	{CLAYMORGUE_C64, 0x2ab00, 0xfd67, TYPE_D64, 1, nullptr, nullptr, 0, 0x855, 0x7352,
+	 0x20}, // Sorcerer Of Claymorgue Castle C64 (D64), Section8 Packer
+
+	{HULK_C64, 0x2ab00, 0xcdd8, TYPE_D64, 0, nullptr, nullptr, 0, 0x1806, 0xb801,
+	 0x307}, // Questprobe 1 - The Hulk C64 (D64)
+	{SPIDERMAN_C64, 0x2ab00, 0xde56, TYPE_D64, 0, nullptr, nullptr, 0, 0x1801, 0xa801,
+	 0x2000}, // Spiderman C64 (D64)
+	{SPIDERMAN_C64, 0x08e72, 0xb2f4, TYPE_T64, 3, nullptr, nullptr, 0, 0,
+	 0}, // Spiderman C64 (T64) MasterCompressor / Relax -> ECA Compacker ->
+	// Section8 Packer
+
+	{SAVAGE_ISLAND_C64, 0x2ab00, 0x8801, TYPE_D64, 1, "-f86 -d0x1793",
+	 "SAVAGEISLAND1+", 1, 0, 0}, // Savage Island part 1 C64 (D64)
+	{SAVAGE_ISLAND2_C64, 0x2ab00, 0x8801, TYPE_D64, 1, "-f86 -d0x178b",
+	 "SAVAGEISLAND2+", 1, 0, 0}, // Savage Island part 2 C64 (D64)
+	{SAVAGE_ISLAND_C64, 0x2ab00, 0xc361, TYPE_D64, 1, "-f86 -d0x1793",
+	 "SAVAGE ISLAND P1", 1, 0, 0}, // Savage Island part 1 C64 (D64) alt
+	{SAVAGE_ISLAND2_C64, 0x2ab00, 0xc361, TYPE_D64, 1, nullptr, "SAVAGE ISLAND P2",
+	 0, 0, 0}, // Savage Island part 2  C64 (D64) alt
+
+	{ROBIN_OF_SHERWOOD_C64, 0x2ab00, 0xcf9e, TYPE_D64, 1, nullptr, nullptr, 0, 0x1802,
+	 0xbd27, 0x2000}, // Robin Of Sherwood D64 * unknown packer
+	{ROBIN_OF_SHERWOOD_C64, 0xb2ef, 0x7c44, TYPE_T64, 1, nullptr, nullptr, 0, 0x9702,
+	 0x9627, 0x2000}, // Robin Of Sherwood C64 (T64) * TCS Cruncher v2.0
+	{ROBIN_OF_SHERWOOD_C64, 0xb690, 0x7b61, TYPE_T64, 1, nullptr, nullptr, 0, 0x9702,
+	 0x9627, 0x2000}, // Robin Of Sherwood C64 (T64) alt * TCS Cruncher v2.0
+	{ROBIN_OF_SHERWOOD_C64, 0x8db6, 0x7853, TYPE_T64, 1, nullptr, nullptr, 0, 0xd7fb,
+	 0xbd20, 0x2000}, // Robin Of Sherwood T64 alt 2 * PUCrunch
+
+	{GREMLINS_C64, 0xdd94, 0x25a8, TYPE_T64, 1, nullptr, nullptr,
+	 0}, // Gremlins C64 (T64) version * Action Replay v4.x
+	{GREMLINS_C64, 0x2ab00, 0xc402, TYPE_D64, 0, nullptr, "G1",
+	 -0x8D}, // Gremlins C64 (D64) version
+	{GREMLINS_C64, 0x2ab00, 0x3ccf, TYPE_D64, 0, nullptr, "G1",
+	 -0x8D}, // Gremlins C64 (D64) version 2
+	{GREMLINS_C64, 0x2ab00, 0xabf8, TYPE_D64, 2, "-e0x1255", nullptr,
+	 2}, // Gremlins C64 (D64) version alt * ByteBoiler, Exomizer
+	{GREMLINS_C64, 0x2ab00, 0xa265, TYPE_D64, 2, "-e0x1255", nullptr,
+	 2}, // Gremlins C64 (D64)  version alt 2 * ByteBoiler, Exomizer
+	{GREMLINS_GERMAN_C64, 0xc003, 0x558c, TYPE_T64, 1, nullptr, nullptr, 0, 0xd801,
+	 0xc6c0,
+	 0x1f00}, // German Gremlins C64 (T64) version * TBC Multicompactor v2.x
+	{GREMLINS_GERMAN_C64, 0x2ab00, 0x6729, TYPE_D64, 2, nullptr, nullptr, 0, 0xdc02,
+	 0xcac1, 0x1f00}, // German Gremlins C64 (D64) version * Exomizer
+
+	{SUPERGRAN_C64, 0x726f, 0x0901, TYPE_T64, 1, nullptr, nullptr, 0, 0xd802, 0xc623,
+	 0x1f00}, // Super Gran C64 (T64) PUCrunch Generic Hack
+
+	{SEAS_OF_BLOOD_C64, 0xa209, 0xf115, TYPE_T64, 6, "-e0x1000", nullptr, 3,
+	 0xd802, 0xb07c,
+	 0x2000}, // Seas of Blood C64 (T64) MasterCompressor / Relax -> ECA
+	// Compacker -> Unknown -> MasterCompressor / Relax -> ECA
+	// Compacker -> CCS Packer
+	{SEAS_OF_BLOOD_C64, 0x2ab00, 0x5c1d, TYPE_D64, 1, nullptr, nullptr, 0, 0xd802,
+	 0xb07c, 0x2000}, // Seas of Blood C64 (D64) CCS Packer
+	{SEAS_OF_BLOOD_C64, 0x2ab00, 0xe308, TYPE_D64, 1, nullptr, nullptr, 0, 0xd802,
+	 0xb07c, 0x2000}, // Seas of Blood C64 (D64) alt CCS Packer
+	{UNKNOWN_GAME, 0, 0, UNKNOWN_FILE_TYPE, 0, nullptr, nullptr, 0, 0, 0, 0}};
+
+static uint16_t checksum(unsigned char *sf, uint32_t extent) {
+	return 0;
+}
+
+int decrunchC64(uint8_t **sf, size_t *extent, C64Rec entry);
+
+uint8_t *getLargestFile(uint8_t *data, int length, int *newlength) {
+	return nullptr;
+}
+
+uint8_t *getFileNamed(uint8_t *data, int length, int *newlength, const char *name) {
+	return nullptr;
+}
+
+int savageIslandMenu(uint8_t **sf, size_t *extent, int recindex) {
+	return 0;
+}
+
+int mysteriousMenu(uint8_t **sf, size_t *extent, int recindex) {
+	return 0;
+}
+
+int mysteriousMenu2(uint8_t **sf, size_t *extent, int recindex) {
+	return 0;
+}
+
 int detectC64(uint8_t **sf, size_t *extent) {
+	if (*extent > MAX_LENGTH || *extent < MIN_LENGTH)
+		return 0;
+
+	uint16_t chksum = checksum(*sf, *extent);
+
+	for (int i = 0; g_C64Registry[i]._length != 0; i++) {
+		if (*extent == g_C64Registry[i]._length && chksum == g_C64Registry[i]._chk) {
+			if (g_C64Registry[i]._id == SAVAGE_ISLAND_C64) {
+				return savageIslandMenu(sf, extent, i);
+			} else if (g_C64Registry[i]._id == BATON_C64 && (chksum == 0xc3fc || chksum == 0xbfbf)) {
+				return mysteriousMenu(sf, extent, i);
+			} else if (g_C64Registry[i]._id == FEASIBILITY_C64 && (chksum == 0x9eaa || chksum == 0x9c18)) {
+				return mysteriousMenu2(sf, extent, i);
+			}
+			if (g_C64Registry[i]._type == TYPE_D64) {
+				int newlength;
+				uint8_t *largest_file = getLargestFile(*sf, *extent, &newlength);
+				uint8_t *appendix = nullptr;
+				int appendixlen = 0;
+
+				if (g_C64Registry[i]._appendFile != nullptr) {
+					appendix = getFileNamed(*sf, *extent, &appendixlen, g_C64Registry[i]._appendFile);
+					if (appendix == nullptr)
+						error("Appending file failed!\n");
+					appendixlen -= 2;
+				}
+
+				uint8_t *megabuf = new uint8_t[newlength + appendixlen];
+				memcpy(megabuf, largest_file, newlength);
+				if (appendix != nullptr) {
+					memcpy(megabuf + newlength + g_C64Registry[i]._parameter, appendix + 2, appendixlen);
+					newlength += appendixlen;
+				}
+
+				if (largest_file) {
+					*sf = megabuf;
+					*extent = newlength;
+				}
+
+			} else if (g_C64Registry[i]._type == TYPE_T64) {
+				uint8_t *file_records = *sf + 64;
+				int number_of_records = (*sf)[36] + (*sf)[37] * 0x100;
+				int offset = file_records[8] + file_records[9] * 0x100;
+				int start_addr = file_records[2] + file_records[3] * 0x100;
+				int end_addr = file_records[4] + file_records[5] * 0x100;
+				int size;
+				if (number_of_records == 1)
+					size = *extent - offset;
+				else
+					size = end_addr - start_addr;
+				uint8_t *first_file = new uint8_t[size + 2];
+				memcpy(first_file + 2, *sf + offset, size);
+				memcpy(first_file, file_records + 2, 2);
+				*sf = first_file;
+				*extent = size + 2;
+			}
+			return decrunchC64(sf, extent, g_C64Registry[i]);
+		}
+	}
+	return 0;
+}
+
+int decrunchC64(uint8_t **sf, size_t *extent, C64Rec entry) {
 	return 0;
 }
 


Commit: 09d2b9792b0823674bed648d22e6403e99386785
    https://github.com/scummvm/scummvm/commit/09d2b9792b0823674bed648d22e6403e99386785
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
JANITORIAL: Fix header guard naming

Changed paths:
    engines/glk/scott/C64_checksums.h
    engines/glk/scott/command_parser.h
    engines/glk/scott/decompress_text.h
    engines/glk/scott/decompress_z80.h
    engines/glk/scott/definitions.h
    engines/glk/scott/detect_game.h
    engines/glk/scott/detection.h
    engines/glk/scott/game_info.h
    engines/glk/scott/game_specific.h
    engines/glk/scott/globals.h
    engines/glk/scott/hulk.h
    engines/glk/scott/layout_text.h
    engines/glk/scott/line_drawing.h
    engines/glk/scott/restore_state.h
    engines/glk/scott/ring_buffer.h
    engines/glk/scott/saga_draw.h
    engines/glk/scott/scott.h
    engines/glk/scott/types.h


diff --git a/engines/glk/scott/C64_checksums.h b/engines/glk/scott/C64_checksums.h
index f89acbfd542..d665040b1a9 100644
--- a/engines/glk/scott/C64_checksums.h
+++ b/engines/glk/scott/C64_checksums.h
@@ -19,8 +19,8 @@
  *
  */
 
-#ifndef GLK_SCOTT_C64CHECKSUMS
-#define GLK_SCOTT_C64CHECKSUMS
+#ifndef GLK_SCOTT_C64CHECKSUMS_H
+#define GLK_SCOTT_C64CHECKSUMS_H
 
 #include "glk/scott/types.h"
 
diff --git a/engines/glk/scott/command_parser.h b/engines/glk/scott/command_parser.h
index b336e95e840..e88dea732ac 100644
--- a/engines/glk/scott/command_parser.h
+++ b/engines/glk/scott/command_parser.h
@@ -19,8 +19,8 @@
  *
  */
 
-#ifndef GLK_SCOTT_PARSER
-#define GLK_SCOTT_PARSER
+#ifndef GLK_SCOTT_PARSER_H
+#define GLK_SCOTT_PARSER_H
 
 #include "common/str-array.h"
 #include "glk/glk_types.h"
diff --git a/engines/glk/scott/decompress_text.h b/engines/glk/scott/decompress_text.h
index 61756631f46..da935a3de2c 100644
--- a/engines/glk/scott/decompress_text.h
+++ b/engines/glk/scott/decompress_text.h
@@ -19,8 +19,8 @@
  *
  */
 
-#ifndef GLK_SCOTT_DECOMPRESSTEXT
-#define GLK_SCOTT_DECOMPRESSTEXT
+#ifndef GLK_SCOTT_DECOMPRESSTEXT_H
+#define GLK_SCOTT_DECOMPRESSTEXT_H
 
 #include "glk/scott/types.h"
 
diff --git a/engines/glk/scott/decompress_z80.h b/engines/glk/scott/decompress_z80.h
index ae80faac43e..a3bcaeab620 100644
--- a/engines/glk/scott/decompress_z80.h
+++ b/engines/glk/scott/decompress_z80.h
@@ -19,8 +19,8 @@
  *
  */
 
-#ifndef GLK_SCOTT_DECOMPRESSZ80
-#define GLK_SCOTT_DECOMPRESSZ80
+#ifndef GLK_SCOTT_DECOMPRESSZ80_H
+#define GLK_SCOTT_DECOMPRESSZ80_H
 
 #include "glk/scott/types.h"
 
diff --git a/engines/glk/scott/definitions.h b/engines/glk/scott/definitions.h
index 11b6bb2aad2..28073c21f3a 100644
--- a/engines/glk/scott/definitions.h
+++ b/engines/glk/scott/definitions.h
@@ -19,8 +19,8 @@
  *
  */
 
-#ifndef GLK_SCOTT_DEFINITIONS
-#define GLK_SCOTT_DEFINITIONS
+#ifndef GLK_SCOTT_DEFINITIONS_H
+#define GLK_SCOTT_DEFINITIONS_H
 
 #include "common/str.h"
 
diff --git a/engines/glk/scott/detect_game.h b/engines/glk/scott/detect_game.h
index b038fa3e786..7983c32d54c 100644
--- a/engines/glk/scott/detect_game.h
+++ b/engines/glk/scott/detect_game.h
@@ -19,8 +19,8 @@
  *
  */
 
-#ifndef GLK_SCOTT_DETECTGAME
-#define GLK_SCOTT_DETECTGAME
+#ifndef GLK_SCOTT_DETECTGAME_H
+#define GLK_SCOTT_DETECTGAME_H
 
 #include "common/stream.h"
 #include "glk/scott/definitions.h"
diff --git a/engines/glk/scott/detection.h b/engines/glk/scott/detection.h
index 61067a36257..263e6e156f2 100644
--- a/engines/glk/scott/detection.h
+++ b/engines/glk/scott/detection.h
@@ -19,8 +19,8 @@
  *
  */
 
-#ifndef GLK_SCOTT_DETECTION
-#define GLK_SCOTT_DETECTION
+#ifndef GLK_SCOTT_DETECTION_H
+#define GLK_SCOTT_DETECTION_H
 
 #include "common/fs.h"
 #include "common/hash-str.h"
diff --git a/engines/glk/scott/game_info.h b/engines/glk/scott/game_info.h
index 705fd718638..2fdf4e10897 100644
--- a/engines/glk/scott/game_info.h
+++ b/engines/glk/scott/game_info.h
@@ -19,8 +19,8 @@
  *
  */
 
-#ifndef GLK_SCOTT_GAMEINFO
-#define GLK_SCOTT_GAMEINFO
+#ifndef GLK_SCOTT_GAMEINFO_H
+#define GLK_SCOTT_GAMEINFO_H
 
 #include "glk/scott/definitions.h"
 #include "common/array.h"
diff --git a/engines/glk/scott/game_specific.h b/engines/glk/scott/game_specific.h
index de4cbbec87c..f3a5fa3d6a9 100644
--- a/engines/glk/scott/game_specific.h
+++ b/engines/glk/scott/game_specific.h
@@ -19,8 +19,8 @@
  *
  */
 
-#ifndef GLK_SCOTT_GAMESPECIFIC
-#define GLK_SCOTT_GAMESPECIFIC
+#ifndef GLK_SCOTT_GAMESPECIFIC_H
+#define GLK_SCOTT_GAMESPECIFIC_H
 
 namespace Glk {
 namespace Scott {
diff --git a/engines/glk/scott/globals.h b/engines/glk/scott/globals.h
index 871a902ef61..ee8cd551f30 100644
--- a/engines/glk/scott/globals.h
+++ b/engines/glk/scott/globals.h
@@ -19,8 +19,8 @@
  *
  */
 
-#ifndef GLK_SCOTT_GLOBALS
-#define GLK_SCOTT_GLOBALS
+#ifndef GLK_SCOTT_GLOBALS_H
+#define GLK_SCOTT_GLOBALS_H
 
 #include "glk/glk_types.h"
 #include "glk/windows.h"
diff --git a/engines/glk/scott/hulk.h b/engines/glk/scott/hulk.h
index f69f2cb8398..f234251a935 100644
--- a/engines/glk/scott/hulk.h
+++ b/engines/glk/scott/hulk.h
@@ -19,8 +19,8 @@
  *
  */
 
-#ifndef GLK_SCOTT_HULK
-#define GLK_SCOTT_HULK
+#ifndef GLK_SCOTT_HULK_H
+#define GLK_SCOTT_HULK_H
 
 struct GameInfo;
 
diff --git a/engines/glk/scott/layout_text.h b/engines/glk/scott/layout_text.h
index 54d3125558f..d15629c87da 100644
--- a/engines/glk/scott/layout_text.h
+++ b/engines/glk/scott/layout_text.h
@@ -19,8 +19,8 @@
  *
  */
 
-#ifndef GLK_SCOTT_LAYOUTTEXT
-#define GLK_SCOTT_LAYOUTTEXT
+#ifndef GLK_SCOTT_LAYOUTTEXT_H
+#define GLK_SCOTT_LAYOUTTEXT_H
 
 namespace Glk {
 namespace Scott {
diff --git a/engines/glk/scott/line_drawing.h b/engines/glk/scott/line_drawing.h
index 86e7bf3ada0..398a239b07c 100644
--- a/engines/glk/scott/line_drawing.h
+++ b/engines/glk/scott/line_drawing.h
@@ -19,8 +19,8 @@
  *
  */
 
-#ifndef GLK_SCOTT_LINEDRAWING
-#define GLK_SCOTT_LINEDRAWING
+#ifndef GLK_SCOTT_LINEDRAWING_H
+#define GLK_SCOTT_LINEDRAWING_H
 
 #include "glk/scott/types.h"
 
diff --git a/engines/glk/scott/restore_state.h b/engines/glk/scott/restore_state.h
index 93edf6acc10..e386af98af7 100644
--- a/engines/glk/scott/restore_state.h
+++ b/engines/glk/scott/restore_state.h
@@ -19,8 +19,8 @@
  *
  */
 
-#ifndef GLK_SCOTT_RESTORESTATE
-#define GLK_SCOTT_RESTORESTATE
+#ifndef GLK_SCOTT_RESTORESTATE_H
+#define GLK_SCOTT_RESTORESTATE_H
 
 #include "glk/scott/types.h"
 
diff --git a/engines/glk/scott/ring_buffer.h b/engines/glk/scott/ring_buffer.h
index b8a3e2e8157..82edf238c73 100644
--- a/engines/glk/scott/ring_buffer.h
+++ b/engines/glk/scott/ring_buffer.h
@@ -19,8 +19,8 @@
  *
  */
 
-#ifndef GLK_SCOTT_RINGBUFFER
-#define GLK_SCOTT_RINGBUFFER
+#ifndef GLK_SCOTT_RINGBUFFER_H
+#define GLK_SCOTT_RINGBUFFER_H
 
 #include "glk/scott/types.h"
 
diff --git a/engines/glk/scott/saga_draw.h b/engines/glk/scott/saga_draw.h
index 11fa5be0f6e..ebad80ed289 100644
--- a/engines/glk/scott/saga_draw.h
+++ b/engines/glk/scott/saga_draw.h
@@ -19,8 +19,8 @@
  *
  */
 
-#ifndef GLK_SCOTT_SAGADRAW
-#define GLK_SCOTT_SAGADRAW
+#ifndef GLK_SCOTT_SAGADRAW_H
+#define GLK_SCOTT_SAGADRAW_H
 
 #include "glk/glk_types.h"
 #include "glk/scott/types.h"
diff --git a/engines/glk/scott/scott.h b/engines/glk/scott/scott.h
index 096d068ff7f..865dd520ee7 100644
--- a/engines/glk/scott/scott.h
+++ b/engines/glk/scott/scott.h
@@ -21,8 +21,8 @@
 
 /* Based on ScottFree interpreter version 1.14 */
 
-#ifndef GLK_SCOTT
-#define GLK_SCOTT
+#ifndef GLK_SCOTT_H
+#define GLK_SCOTT_H
 
 /*
  *  Controlling block
diff --git a/engines/glk/scott/types.h b/engines/glk/scott/types.h
index 33340ef9eca..a8de41c63ba 100644
--- a/engines/glk/scott/types.h
+++ b/engines/glk/scott/types.h
@@ -19,8 +19,8 @@
  *
  */
 
-#ifndef GLK_SCOTT_TYPES
-#define GLK_SCOTT_TYPES
+#ifndef GLK_SCOTT_TYPES_H
+#define GLK_SCOTT_TYPES_H
 
 #include "common/scummsys.h"
 


Commit: 464bfdd3cce88143fad8bd731b80f3c604cbd4a2
    https://github.com/scummvm/scummvm/commit/464bfdd3cce88143fad8bd731b80f3c604cbd4a2
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Rename C64_checksums to c64_checksums

Changed paths:
  A engines/glk/scott/c64_checksums.cpp
  A engines/glk/scott/c64_checksums.h
  R engines/glk/scott/C64_checksums.cpp
  R engines/glk/scott/C64_checksums.h
    engines/glk/module.mk
    engines/glk/scott/detect_game.cpp


diff --git a/engines/glk/module.mk b/engines/glk/module.mk
index 6d59ed03831..1ebbf7ef518 100644
--- a/engines/glk/module.mk
+++ b/engines/glk/module.mk
@@ -234,7 +234,7 @@ MODULE_OBJS := \
 	quest/read_file.o \
 	quest/string.o \
 	quest/streams.o \
-	scott/C64_checksums.o \
+	scott/c64_checksums.o \
 	scott/command_parser.o \
 	scott/decompress_text.o \
 	scott/decompress_z80.o \
diff --git a/engines/glk/scott/C64_checksums.cpp b/engines/glk/scott/c64_checksums.cpp
similarity index 99%
rename from engines/glk/scott/C64_checksums.cpp
rename to engines/glk/scott/c64_checksums.cpp
index 3ac968f3634..3bb59bbca27 100644
--- a/engines/glk/scott/C64_checksums.cpp
+++ b/engines/glk/scott/c64_checksums.cpp
@@ -19,7 +19,7 @@
  *
  */
 
-#include "glk/scott/C64_checksums.h"
+#include "glk/scott/c64_checksums.h"
 #include "glk/scott/definitions.h"
 #include "glk/scott/scott.h"
 
diff --git a/engines/glk/scott/C64_checksums.h b/engines/glk/scott/c64_checksums.h
similarity index 100%
rename from engines/glk/scott/C64_checksums.h
rename to engines/glk/scott/c64_checksums.h
diff --git a/engines/glk/scott/detect_game.cpp b/engines/glk/scott/detect_game.cpp
index efd6393db1a..4c5110daeb8 100644
--- a/engines/glk/scott/detect_game.cpp
+++ b/engines/glk/scott/detect_game.cpp
@@ -31,7 +31,7 @@
 #include "glk/scott/line_drawing.h"
 #include "glk/scott/saga_draw.h"
 #include "glk/scott/scott.h"
-#include "glk/scott/C64_checksums.h"
+#include "glk/scott/c64_checksums.h"
 #include "glk/scott/game_specific.h"
 #include "common/str.h"
 


Commit: d6d67b40bb9299bf378f35d25a871be61041b85e
    https://github.com/scummvm/scummvm/commit/d6d67b40bb9299bf378f35d25a871be61041b85e
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
JANITORIAL: Formatting fixes

Changed paths:
    engines/glk/scott/c64_checksums.cpp
    engines/glk/scott/detection_tables.h
    engines/glk/scott/globals.h


diff --git a/engines/glk/scott/c64_checksums.cpp b/engines/glk/scott/c64_checksums.cpp
index 3bb59bbca27..820b5610031 100644
--- a/engines/glk/scott/c64_checksums.cpp
+++ b/engines/glk/scott/c64_checksums.cpp
@@ -51,120 +51,86 @@ struct C64Rec {
 };
 
 static C64Rec g_C64Registry[] = {
-	{BATON_C64, 0x2ab00, 0xc3fc, TYPE_D64, 0}, // Mysterious Adventures C64 dsk 1
-	{TIME_MACHINE_C64, 0x2ab00, 0xc3fc, TYPE_D64, 0},
-	{ARROW1_C64, 0x2ab00, 0xc3fc, TYPE_D64, 0},
-	{ARROW2_C64, 0x2ab00, 0xc3fc, TYPE_D64, 0},
-	{PULSAR7_C64, 0x2ab00, 0xc3fc, TYPE_D64, 0},
-	{CIRCUS_C64, 0x2ab00, 0xc3fc, TYPE_D64, 0},
-
-	{FEASIBILITY_C64, 0x2ab00, 0x9eaa, TYPE_D64, 0}, // Mysterious Adventures C64 dsk 2
-	{AKYRZ_C64, 0x2ab00, 0x9eaa, TYPE_D64, 0},
-	{PERSEUS_C64, 0x2ab00, 0x9eaa, TYPE_D64, 0},
-	{INDIANS_C64, 0x2ab00, 0x9eaa, TYPE_D64, 0},
-	{WAXWORKS_C64, 0x2ab00, 0x9eaa, TYPE_D64, 0},
-	{BATON_C64, 0x2ab00, 0x9dca, TYPE_D64, 2},
-
-	{BATON_C64, 0x5170, 0xb240, TYPE_T64, 2},        // The Golden Baton C64, T64
-	{BATON_C64, 0x2ab00, 0xbfbf, TYPE_D64, 2},       // Mysterious Adventures C64 dsk 1 alt
-	{FEASIBILITY_C64, 0x2ab00, 0x9c18, TYPE_D64, 2}, // Mysterious Adventures C64 dsk 2 alt
-	{TIME_MACHINE_C64, 0x5032, 0x5635, TYPE_T64, 1}, // The Time Machine C64
-	{ARROW1_C64, 0x5b46, 0x92db, TYPE_T64, 1},       // Arrow of Death part 1 C64
-	{ARROW2_C64, 0x5fe2, 0xe14f, TYPE_T64, 1},       // Arrow of Death part 2 C64
-	{PULSAR7_C64, 0x46bf, 0x1679, TYPE_T64, 1},      // Escape from Pulsar 7 C64
-	{CIRCUS_C64, 0x4269, 0xa449, TYPE_T64, 2},       // Circus C64
-	{FEASIBILITY_C64, 0x5a7b, 0x0f48, TYPE_T64, 1},  // Feasibility Experiment C64
-	{AKYRZ_C64, 0x2ab00, 0x6cca, TYPE_D64, 0},       // The Wizard of Akyrz C64
-	{AKYRZ_C64, 0x4be1, 0x5a00, TYPE_T64, 1},        // The Wizard of Akyrz C64, T64
-	{PERSEUS_C64, 0x502b, 0x913b, TYPE_T64, 1},      // Perseus and Andromeda C64
-	{INDIANS_C64, 0x4f9f, 0xe6c8, TYPE_T64, 1},      // Ten Little Indians C64
-	{WAXWORKS_C64, 0x4a11, 0xa37a, TYPE_T64, 1},     // Waxworks C64
-
-	{ADVENTURELAND_C64, 0x6a10, 0x1910, TYPE_T64,
-	 1}, // Adventureland C64 (T64) CruelCrunch v2.2
-	{ADVENTURELAND_C64, 0x6a10, 0x1b10, TYPE_T64, 1, nullptr, nullptr, 0, 0,
-	 0}, // Adventureland C64 (T64) alt CruelCrunch v2.2
-	{ADVENTURELAND_C64, 0x2ab00, 0x6638, TYPE_D64, 1, nullptr, nullptr, 0, 0,
-	 0}, // Adventureland C64 (D64) CruelCrunch v2.2
-	{ADVENTURELAND_C64, 0x2adab, 0x751f, TYPE_D64, 0, nullptr, nullptr, 0, 0,
-	 0}, // Adventureland C64 (D64) alt
-	{ADVENTURELAND_C64, 0x2adab, 0x64a4, TYPE_D64, 0, nullptr, "SAG1PIC", -0xa53,
-	 0, 0, 0, 0x65af}, // Adventureland C64 (D64) alt 2
-
-	{SECRET_MISSION_C64, 0x88be, 0xa122, TYPE_T64, 1, nullptr, nullptr, 0, 0,
-	 0}, // Secret Mission  C64 (T64) Section8 Packer
-	{SECRET_MISSION_C64, 0x2ab00, 0x04d6, TYPE_D64, 0, nullptr, nullptr, 0, 0, 0, 0,
-	 -0x1bff}, // Secret Mission  C64 (D64)
-
-	{CLAYMORGUE_C64, 0x6ff7, 0xe4ed, TYPE_T64, 3, nullptr, nullptr, 0, 0x855, 0x7352,
-	 0x20}, // Sorcerer Of Claymorgue Castle C64 (T64), MasterCompressor / Relax
+	{ BATON_C64,		0x2ab00, 0xc3fc, TYPE_D64, 0 },		// Mysterious Adventures C64 dsk 1
+	{ TIME_MACHINE_C64,	0x2ab00, 0xc3fc, TYPE_D64, 0 },
+	{ ARROW1_C64,		0x2ab00, 0xc3fc, TYPE_D64, 0 },
+	{ ARROW2_C64,		0x2ab00, 0xc3fc, TYPE_D64, 0 },
+	{ PULSAR7_C64,		0x2ab00, 0xc3fc, TYPE_D64, 0 },
+	{ CIRCUS_C64,		0x2ab00, 0xc3fc, TYPE_D64, 0 },
+
+	{ FEASIBILITY_C64,	0x2ab00, 0x9eaa, TYPE_D64, 0 },		// Mysterious Adventures C64 dsk 2
+	{ AKYRZ_C64,		0x2ab00, 0x9eaa, TYPE_D64, 0 },
+	{ PERSEUS_C64,		0x2ab00, 0x9eaa, TYPE_D64, 0 },
+	{ INDIANS_C64,		0x2ab00, 0x9eaa, TYPE_D64, 0 },
+	{ WAXWORKS_C64,		0x2ab00, 0x9eaa, TYPE_D64, 0 },
+	{ BATON_C64,		0x2ab00, 0x9dca, TYPE_D64, 2 },
+
+	{ BATON_C64,		0x5170,	 0xb240, TYPE_T64, 2 },		// The Golden Baton C64, T64
+	{ BATON_C64,		0x2ab00, 0xbfbf, TYPE_D64, 2 },		// Mysterious Adventures C64 dsk 1 alt
+	{ FEASIBILITY_C64,	0x2ab00, 0x9c18, TYPE_D64, 2 },		// Mysterious Adventures C64 dsk 2 alt
+	{ TIME_MACHINE_C64,	0x5032,  0x5635, TYPE_T64, 1 },		// The Time Machine C64
+	{ ARROW1_C64,		0x5b46,  0x92db, TYPE_T64, 1 },		// Arrow of Death part 1 C64
+	{ ARROW2_C64,		0x5fe2,  0xe14f, TYPE_T64, 1 },		// Arrow of Death part 2 C64
+	{ PULSAR7_C64,		0x46bf,  0x1679, TYPE_T64, 1 },		// Escape from Pulsar 7 C64
+	{ CIRCUS_C64,		0x4269,  0xa449, TYPE_T64, 2 },		// Circus C64
+	{ FEASIBILITY_C64,	0x5a7b,  0x0f48, TYPE_T64, 1 },		// Feasibility Experiment C64
+	{ AKYRZ_C64,		0x2ab00, 0x6cca, TYPE_D64, 0 },		// The Wizard of Akyrz C64
+	{ AKYRZ_C64,		0x4be1,  0x5a00, TYPE_T64, 1 },		// The Wizard of Akyrz C64, T64
+	{ PERSEUS_C64,		0x502b,  0x913b, TYPE_T64, 1 },		// Perseus and Andromeda C64
+	{ INDIANS_C64,		0x4f9f,  0xe6c8, TYPE_T64, 1 },		// Ten Little Indians C64
+	{ WAXWORKS_C64,		0x4a11,  0xa37a, TYPE_T64, 1 },		// Waxworks C64
+
+	{ ADVENTURELAND_C64, 0x6a10,  0x1910, TYPE_T64, 1 },												  // Adventureland C64 (T64) CruelCrunch v2.2
+	{ ADVENTURELAND_C64, 0x6a10,  0x1b10, TYPE_T64, 1, nullptr, nullptr,	   0,	   0, 0 },            // Adventureland C64 (T64) alt CruelCrunch v2.2
+	{ ADVENTURELAND_C64, 0x2ab00, 0x6638, TYPE_D64, 1, nullptr, nullptr,	   0,	   0, 0 },            // Adventureland C64 (D64) CruelCrunch v2.2
+	{ ADVENTURELAND_C64, 0x2adab, 0x751f, TYPE_D64, 0, nullptr, nullptr,	   0,	   0, 0 },            // Adventureland C64 (D64) alt
+	{ ADVENTURELAND_C64, 0x2adab, 0x64a4, TYPE_D64, 0, nullptr, "SAG1PIC",	   -0xa53, 0, 0, 0, 0x65af }, // Adventureland C64 (D64) alt 2
+
+	{ SECRET_MISSION_C64, 0x88be,  0xa122, TYPE_T64, 1, nullptr, nullptr, 0, 0, 0 },             // Secret Mission  C64 (T64) Section8 Packer
+	{ SECRET_MISSION_C64, 0x2ab00, 0x04d6, TYPE_D64, 0, nullptr, nullptr, 0, 0, 0, 0, -0x1bff }, // Secret Mission  C64 (D64)
+
+	{ CLAYMORGUE_C64, 0x6ff7,  0xe4ed, TYPE_T64, 3, nullptr, nullptr, 0, 0x855, 0x7352, 0x20 },		// Sorcerer Of Claymorgue Castle C64 (T64), MasterCompressor / Relax
 	// -> ECA Compacker -> MegaByte Cruncher v1.x Missing 17 pictures
-	{CLAYMORGUE_C64, 0x912f, 0xa69f, TYPE_T64, 1, nullptr, nullptr, 0, 0x855, 0x7352,
-	 0x20}, // Sorcerer Of Claymorgue Castle C64 (T64) alt, MegaByte Cruncher
+	{ CLAYMORGUE_C64, 0x912f,  0xa69f, TYPE_T64, 1, nullptr, nullptr, 0, 0x855, 0x7352, 0x20 },		// Sorcerer Of Claymorgue Castle C64 (T64) alt, MegaByte Cruncher
 	// v1.x Missing 17 pictures
-	{CLAYMORGUE_C64, 0xc0dd, 0x3701, TYPE_T64, 1, nullptr, nullptr, 0, 0, 0, 0,
-	 -0x7fe}, // Sorcerer Of Claymorgue Castle C64 (T64) alt 2, Trilogic Expert
+	{ CLAYMORGUE_C64, 0xc0dd,  0x3701, TYPE_T64, 1, nullptr, nullptr, 0, 0,	    0,	    0, -0x7fe },// Sorcerer Of Claymorgue Castle C64 (T64) alt 2, Trilogic Expert
 	// v2.7
-	{CLAYMORGUE_C64, 0xbc5f, 0x492c, TYPE_T64, 1, nullptr, nullptr, 0, 0x855, 0x7352,
-	 0x20}, // Sorcerer Of Claymorgue Castle C64 (T64) alt 3, , Section8 Packer
-	{CLAYMORGUE_C64, 0x2ab00, 0xfd67, TYPE_D64, 1, nullptr, nullptr, 0, 0x855, 0x7352,
-	 0x20}, // Sorcerer Of Claymorgue Castle C64 (D64), Section8 Packer
-
-	{HULK_C64, 0x2ab00, 0xcdd8, TYPE_D64, 0, nullptr, nullptr, 0, 0x1806, 0xb801,
-	 0x307}, // Questprobe 1 - The Hulk C64 (D64)
-	{SPIDERMAN_C64, 0x2ab00, 0xde56, TYPE_D64, 0, nullptr, nullptr, 0, 0x1801, 0xa801,
-	 0x2000}, // Spiderman C64 (D64)
-	{SPIDERMAN_C64, 0x08e72, 0xb2f4, TYPE_T64, 3, nullptr, nullptr, 0, 0,
-	 0}, // Spiderman C64 (T64) MasterCompressor / Relax -> ECA Compacker ->
+	{ CLAYMORGUE_C64, 0xbc5f,  0x492c, TYPE_T64, 1, nullptr, nullptr, 0, 0x855, 0x7352, 0x20 },		// Sorcerer Of Claymorgue Castle C64 (T64) alt 3, , Section8 Packer
+	{ CLAYMORGUE_C64, 0x2ab00, 0xfd67, TYPE_D64, 1, nullptr, nullptr, 0, 0x855, 0x7352, 0x20 },		// Sorcerer Of Claymorgue Castle C64 (D64), Section8 Packer
+
+	{ HULK_C64,		 0x2ab00, 0xcdd8, TYPE_D64, 0, nullptr, nullptr, 0, 0x1806, 0xb801, 0x307 },		// Questprobe 1 - The Hulk C64 (D64)
+	{ SPIDERMAN_C64, 0x2ab00, 0xde56, TYPE_D64, 0, nullptr, nullptr, 0, 0x1801, 0xa801, 0x2000 },		// Spiderman C64 (D64)
+	{ SPIDERMAN_C64, 0x08e72, 0xb2f4, TYPE_T64, 3, nullptr, nullptr, 0, 0,	    0 },					// Spiderman C64 (T64) MasterCompressor / Relax -> ECA Compacker ->
 	// Section8 Packer
 
-	{SAVAGE_ISLAND_C64, 0x2ab00, 0x8801, TYPE_D64, 1, "-f86 -d0x1793",
-	 "SAVAGEISLAND1+", 1, 0, 0}, // Savage Island part 1 C64 (D64)
-	{SAVAGE_ISLAND2_C64, 0x2ab00, 0x8801, TYPE_D64, 1, "-f86 -d0x178b",
-	 "SAVAGEISLAND2+", 1, 0, 0}, // Savage Island part 2 C64 (D64)
-	{SAVAGE_ISLAND_C64, 0x2ab00, 0xc361, TYPE_D64, 1, "-f86 -d0x1793",
-	 "SAVAGE ISLAND P1", 1, 0, 0}, // Savage Island part 1 C64 (D64) alt
-	{SAVAGE_ISLAND2_C64, 0x2ab00, 0xc361, TYPE_D64, 1, nullptr, "SAVAGE ISLAND P2",
-	 0, 0, 0}, // Savage Island part 2  C64 (D64) alt
-
-	{ROBIN_OF_SHERWOOD_C64, 0x2ab00, 0xcf9e, TYPE_D64, 1, nullptr, nullptr, 0, 0x1802,
-	 0xbd27, 0x2000}, // Robin Of Sherwood D64 * unknown packer
-	{ROBIN_OF_SHERWOOD_C64, 0xb2ef, 0x7c44, TYPE_T64, 1, nullptr, nullptr, 0, 0x9702,
-	 0x9627, 0x2000}, // Robin Of Sherwood C64 (T64) * TCS Cruncher v2.0
-	{ROBIN_OF_SHERWOOD_C64, 0xb690, 0x7b61, TYPE_T64, 1, nullptr, nullptr, 0, 0x9702,
-	 0x9627, 0x2000}, // Robin Of Sherwood C64 (T64) alt * TCS Cruncher v2.0
-	{ROBIN_OF_SHERWOOD_C64, 0x8db6, 0x7853, TYPE_T64, 1, nullptr, nullptr, 0, 0xd7fb,
-	 0xbd20, 0x2000}, // Robin Of Sherwood T64 alt 2 * PUCrunch
-
-	{GREMLINS_C64, 0xdd94, 0x25a8, TYPE_T64, 1, nullptr, nullptr,
-	 0}, // Gremlins C64 (T64) version * Action Replay v4.x
-	{GREMLINS_C64, 0x2ab00, 0xc402, TYPE_D64, 0, nullptr, "G1",
-	 -0x8D}, // Gremlins C64 (D64) version
-	{GREMLINS_C64, 0x2ab00, 0x3ccf, TYPE_D64, 0, nullptr, "G1",
-	 -0x8D}, // Gremlins C64 (D64) version 2
-	{GREMLINS_C64, 0x2ab00, 0xabf8, TYPE_D64, 2, "-e0x1255", nullptr,
-	 2}, // Gremlins C64 (D64) version alt * ByteBoiler, Exomizer
-	{GREMLINS_C64, 0x2ab00, 0xa265, TYPE_D64, 2, "-e0x1255", nullptr,
-	 2}, // Gremlins C64 (D64)  version alt 2 * ByteBoiler, Exomizer
-	{GREMLINS_GERMAN_C64, 0xc003, 0x558c, TYPE_T64, 1, nullptr, nullptr, 0, 0xd801,
-	 0xc6c0,
-	 0x1f00}, // German Gremlins C64 (T64) version * TBC Multicompactor v2.x
-	{GREMLINS_GERMAN_C64, 0x2ab00, 0x6729, TYPE_D64, 2, nullptr, nullptr, 0, 0xdc02,
-	 0xcac1, 0x1f00}, // German Gremlins C64 (D64) version * Exomizer
-
-	{SUPERGRAN_C64, 0x726f, 0x0901, TYPE_T64, 1, nullptr, nullptr, 0, 0xd802, 0xc623,
-	 0x1f00}, // Super Gran C64 (T64) PUCrunch Generic Hack
-
-	{SEAS_OF_BLOOD_C64, 0xa209, 0xf115, TYPE_T64, 6, "-e0x1000", nullptr, 3,
-	 0xd802, 0xb07c,
-	 0x2000}, // Seas of Blood C64 (T64) MasterCompressor / Relax -> ECA
+	{ SAVAGE_ISLAND_C64,  0x2ab00, 0x8801, TYPE_D64, 1, "-f86 -d0x1793", "SAVAGEISLAND1+",   1, 0, 0 },		// Savage Island part 1 C64 (D64)
+	{ SAVAGE_ISLAND2_C64, 0x2ab00, 0x8801, TYPE_D64, 1, "-f86 -d0x178b", "SAVAGEISLAND2+",   1, 0, 0 },		// Savage Island part 2 C64 (D64)
+	{ SAVAGE_ISLAND_C64,  0x2ab00, 0xc361, TYPE_D64, 1, "-f86 -d0x1793", "SAVAGE ISLAND P1", 1, 0, 0 },		// Savage Island part 1 C64 (D64) alt
+	{ SAVAGE_ISLAND2_C64, 0x2ab00, 0xc361, TYPE_D64, 1, nullptr,			"SAVAGE ISLAND P2", 0, 0, 0 },  // Savage Island part 2  C64 (D64) alt
+
+	{ ROBIN_OF_SHERWOOD_C64, 0x2ab00, 0xcf9e, TYPE_D64, 1, nullptr, nullptr, 0, 0x1802, 0xbd27, 0x2000 }, // Robin Of Sherwood D64 * unknown packer
+	{ ROBIN_OF_SHERWOOD_C64, 0xb2ef,  0x7c44, TYPE_T64, 1, nullptr, nullptr, 0, 0x9702, 0x9627, 0x2000 }, // Robin Of Sherwood C64 (T64) * TCS Cruncher v2.0
+	{ ROBIN_OF_SHERWOOD_C64, 0xb690,  0x7b61, TYPE_T64, 1, nullptr, nullptr, 0, 0x9702, 0x9627, 0x2000 }, // Robin Of Sherwood C64 (T64) alt * TCS Cruncher v2.0
+	{ ROBIN_OF_SHERWOOD_C64, 0x8db6,  0x7853, TYPE_T64, 1, nullptr, nullptr, 0, 0xd7fb, 0xbd20, 0x2000 }, // Robin Of Sherwood T64 alt 2 * PUCrunch
+
+	{ GREMLINS_C64,			0xdd94,  0x25a8, TYPE_T64, 1, nullptr,	  nullptr, 0 },							 // Gremlins C64 (T64) version * Action Replay v4.x
+	{ GREMLINS_C64,			0x2ab00, 0xc402, TYPE_D64, 0, nullptr,	  "G1",	   -0x8D },                      // Gremlins C64 (D64) version
+	{ GREMLINS_C64,			0x2ab00, 0x3ccf, TYPE_D64, 0, nullptr,	  "G1",    -0x8D },                      // Gremlins C64 (D64) version 2
+	{ GREMLINS_C64,			0x2ab00, 0xabf8, TYPE_D64, 2, "-e0x1255", nullptr,  2 },                         // Gremlins C64 (D64) version alt * ByteBoiler, Exomizer
+	{ GREMLINS_C64,			0x2ab00, 0xa265, TYPE_D64, 2, "-e0x1255", nullptr,  2 },                         // Gremlins C64 (D64)  version alt 2 * ByteBoiler, Exomizer
+	{ GREMLINS_GERMAN_C64,	0xc003,  0x558c, TYPE_T64, 1, nullptr,	  nullptr,  0, 0xd801, 0xc6c0, 0x1f00 }, // German Gremlins C64 (T64) version * TBC Multicompactor v2.x
+	{ GREMLINS_GERMAN_C64,	0x2ab00, 0x6729, TYPE_D64, 2, nullptr,	  nullptr,  0, 0xdc02, 0xcac1, 0x1f00 }, // German Gremlins C64 (D64) version * Exomizer
+
+	{ SUPERGRAN_C64,			0x726f,  0x0901, TYPE_T64, 1, nullptr,	  nullptr,  0, 0xd802, 0xc623, 0x1f00 }, // Super Gran C64 (T64) PUCrunch Generic Hack
+
+	{ SEAS_OF_BLOOD_C64,		0xa209,  0xf115, TYPE_T64, 6, "-e0x1000", nullptr,  3, 0xd802, 0xb07c, 0x2000 }, // Seas of Blood C64 (T64) MasterCompressor / Relax -> ECA
 	// Compacker -> Unknown -> MasterCompressor / Relax -> ECA
 	// Compacker -> CCS Packer
-	{SEAS_OF_BLOOD_C64, 0x2ab00, 0x5c1d, TYPE_D64, 1, nullptr, nullptr, 0, 0xd802,
-	 0xb07c, 0x2000}, // Seas of Blood C64 (D64) CCS Packer
-	{SEAS_OF_BLOOD_C64, 0x2ab00, 0xe308, TYPE_D64, 1, nullptr, nullptr, 0, 0xd802,
-	 0xb07c, 0x2000}, // Seas of Blood C64 (D64) alt CCS Packer
-	{UNKNOWN_GAME, 0, 0, UNKNOWN_FILE_TYPE, 0, nullptr, nullptr, 0, 0, 0, 0}};
+	{ SEAS_OF_BLOOD_C64,		0x2ab00, 0x5c1d, TYPE_D64, 1, nullptr,	  nullptr,  0, 0xd802, 0xb07c, 0x2000 }, // Seas of Blood C64 (D64) CCS Packer
+	{ SEAS_OF_BLOOD_C64,		0x2ab00, 0xe308, TYPE_D64, 1, nullptr,	  nullptr,  0, 0xd802, 0xb07c, 0x2000 }, // Seas of Blood C64 (D64) alt CCS Packer
+
+	{ UNKNOWN_GAME, 0, 0, UNKNOWN_FILE_TYPE, 0, nullptr, nullptr, 0, 0, 0, 0 }
+};
 
 static uint16_t checksum(unsigned char *sf, uint32_t extent) {
 	return 0;
diff --git a/engines/glk/scott/detection_tables.h b/engines/glk/scott/detection_tables.h
index 01d25e66caf..6d074f0ec10 100644
--- a/engines/glk/scott/detection_tables.h
+++ b/engines/glk/scott/detection_tables.h
@@ -59,8 +59,8 @@ const PlainGameDescriptor SCOTT_GAME_LIST[] = {
 	{ "perseus", "Mysterious Adventures 9: Perseus and Andromeda" },
 	{ "10indians", "Mysterious Adventures 10: Ten Little Indians" },
 	{ "waxworks11", "Mysterious Adventures 11: Waxworks" },
-	{ "mysadv1", "11 Mysterious Adventures - Disk 1"},
-	{ "mysadv2", "11 Mysterious Adventures - Disk 2"},
+	{ "mysadv1", "11 Mysterious Adventures - Disk 1" },
+	{ "mysadv2", "11 Mysterious Adventures - Disk 2" },
 
 	// Other Games
 	{ "desert",            "Desert Adventure" },
@@ -149,24 +149,24 @@ const GlkDetectionEntry SCOTT_GAMES[] = {
 	DT_ENTRY0("romulanadv",       "d97b5cb5ed66eb276ef9f1c1bae0b8dd", 13959),
 	DT_ENTRY0("topsecretadv",     "effb411e74dfe3a8d69b57b9bc3a2cef", 15575),
 
-	//ZX Spectrum games
+	// ZX Spectrum games
 	DT_ENTRY1("marveladventure", "ZXSpectrum", "0eec511d3cde815c73e5464ab0cdbef9", 40727),
 
-	//11 Mysterious Adventures
-	DT_ENTRY1("goldenbaton", "ZXSpectrum", "cb7dadc9d5f8bce453b9139265e4dd7d", 32060),
-	DT_ENTRY1("timemachine", "ZXSpectrum", "b22d1f4d46c99ff4443d541d3fe424c1", 30928),
-	DT_ENTRY1("arrowofdeath1", "ZXSpectrum", "3a5c3f4079c1c0347f03420db8ad4596", 34105),
-	DT_ENTRY1("arrowofdeath2", "ZXSpectrum", "d3f8943c4f5f71ce00139065055a72ee", 38043),
-	DT_ENTRY1("pulsar7", "ZXSpectrum", "441edd90fc7f9ff39a5eebe035a974e9", 29961),
-	DT_ENTRY1("circus", "ZXSpectrum", "ed99306a2fb23bf6579068a4d74034ee", 27746),
-	DT_ENTRY1("feasibility", "ZXSpectrum", "5e381e83f15d77e3542be4a4cffc8e25", 37395),
-	DT_ENTRY1("akyrz", "ZXSpectrum", "b0f8676817475753f1edd7f1eeea31fb", 33753),
-	DT_ENTRY1("perseus", "ZXSpectrum", "84d5fbb16a37e495abf09d191fd8b1a2", 31504),
-	DT_ENTRY1("10indians", "ZXSpectrum", "afde056c152de79ea20453c42a2d08af", 31664),
-	DT_ENTRY1("waxworks11", "ZXSpectrum", "6c6fbbbb50032463a6ea71c6750ea1f5", 32662),
+	// 11 Mysterious Adventures
+	DT_ENTRY1("goldenbaton",	"ZXSpectrum", "cb7dadc9d5f8bce453b9139265e4dd7d", 32060),
+	DT_ENTRY1("timemachine",	"ZXSpectrum", "b22d1f4d46c99ff4443d541d3fe424c1", 30928),
+	DT_ENTRY1("arrowofdeath1",	"ZXSpectrum", "3a5c3f4079c1c0347f03420db8ad4596", 34105),
+	DT_ENTRY1("arrowofdeath2",	"ZXSpectrum", "d3f8943c4f5f71ce00139065055a72ee", 38043),
+	DT_ENTRY1("pulsar7",		"ZXSpectrum", "441edd90fc7f9ff39a5eebe035a974e9", 29961),
+	DT_ENTRY1("circus",			"ZXSpectrum", "ed99306a2fb23bf6579068a4d74034ee", 27746),
+	DT_ENTRY1("feasibility",	"ZXSpectrum", "5e381e83f15d77e3542be4a4cffc8e25", 37395),
+	DT_ENTRY1("akyrz",			"ZXSpectrum", "b0f8676817475753f1edd7f1eeea31fb", 33753),
+	DT_ENTRY1("perseus",		"ZXSpectrum", "84d5fbb16a37e495abf09d191fd8b1a2", 31504),
+	DT_ENTRY1("10indians",		"ZXSpectrum", "afde056c152de79ea20453c42a2d08af", 31664),
+	DT_ENTRY1("waxworks11",		"ZXSpectrum", "6c6fbbbb50032463a6ea71c6750ea1f5", 32662),
 
-	//C64 Games
-	//11 Mysterious Adventures
+	// C64 Games
+	// 11 Mysterious Adventures
 	DT_ENTRY1("mysadv1", "C64", "ce5a68cf43b2f29d99c0135b89f4fe31", 174848),
 	DT_ENTRY1("mysadv2", "C64", "1e1ff48f80a8220f5ab9d14c975197b8", 174848),
 	DT_END_MARKER
diff --git a/engines/glk/scott/globals.h b/engines/glk/scott/globals.h
index ee8cd551f30..638d06aa15f 100644
--- a/engines/glk/scott/globals.h
+++ b/engines/glk/scott/globals.h
@@ -22,12 +22,12 @@
 #ifndef GLK_SCOTT_GLOBALS_H
 #define GLK_SCOTT_GLOBALS_H
 
+#include "common/array.h"
+#include "common/str-array.h"
 #include "glk/glk_types.h"
-#include "glk/windows.h"
 #include "glk/scott/definitions.h"
 #include "glk/scott/types.h"
-#include "common/array.h"
-#include "common/str-array.h"
+#include "glk/windows.h"
 
 namespace Glk {
 namespace Scott {
@@ -78,7 +78,7 @@ public:
 	int _counters[16]; ///< Range unknown
 	int _currentCounter = 0;
 	int _savedRoom = 0;
-	int _roomSaved[16]; ///< Range unknown
+	int _roomSaved[16];   ///< Range unknown
 	uint32 _bitFlags = 0; ///< Might be >32 flags - I haven't seen >32 yet
 	int _autoInventory = 0;
 
@@ -138,7 +138,7 @@ public:
 	Common::StringArray _abbreviations;
 	Common::StringArray _abbreviationsKey;
 
-	//restore state
+	// restore state
 	int _justUndid = 0;
 	SavedState *_initialState = nullptr;
 	SavedState *_ramSave = nullptr;


Commit: 95c20b538cec7e68db67bc7989134acb7095169d
    https://github.com/scummvm/scummvm/commit/95c20b538cec7e68db67bc7989134acb7095169d
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Reorder header includes

Changed paths:
    engines/glk/scott/c64_checksums.cpp
    engines/glk/scott/command_parser.cpp
    engines/glk/scott/decompress_text.cpp
    engines/glk/scott/decompress_z80.cpp
    engines/glk/scott/detect_game.cpp
    engines/glk/scott/detection.cpp
    engines/glk/scott/detection_tables.h
    engines/glk/scott/game_info.cpp
    engines/glk/scott/game_info.h
    engines/glk/scott/game_specific.cpp
    engines/glk/scott/globals.cpp
    engines/glk/scott/globals.h
    engines/glk/scott/hulk.cpp
    engines/glk/scott/layout_text.cpp
    engines/glk/scott/line_drawing.cpp
    engines/glk/scott/restore_state.cpp
    engines/glk/scott/saga_draw.cpp
    engines/glk/scott/scott.cpp


diff --git a/engines/glk/scott/c64_checksums.cpp b/engines/glk/scott/c64_checksums.cpp
index 820b5610031..2cdea4c2046 100644
--- a/engines/glk/scott/c64_checksums.cpp
+++ b/engines/glk/scott/c64_checksums.cpp
@@ -19,9 +19,9 @@
  *
  */
 
+#include "glk/scott/scott.h"
 #include "glk/scott/c64_checksums.h"
 #include "glk/scott/definitions.h"
-#include "glk/scott/scott.h"
 
 namespace Glk {
 namespace Scott {
diff --git a/engines/glk/scott/command_parser.cpp b/engines/glk/scott/command_parser.cpp
index e6a58614013..98363cbd578 100644
--- a/engines/glk/scott/command_parser.cpp
+++ b/engines/glk/scott/command_parser.cpp
@@ -19,10 +19,10 @@
  *
  */
 
-#include "glk/scott/command_parser.h"
-#include "glk/scott/globals.h"
-#include "glk/scott/scott.h"
 #include "common/str.h"
+#include "glk/scott/scott.h"
+#include "glk/scott/globals.h"
+#include "glk/scott/command_parser.h"
 
 namespace Glk {
 namespace Scott {
diff --git a/engines/glk/scott/decompress_text.cpp b/engines/glk/scott/decompress_text.cpp
index a972ac09e9d..9029c7edde0 100644
--- a/engines/glk/scott/decompress_text.cpp
+++ b/engines/glk/scott/decompress_text.cpp
@@ -19,8 +19,8 @@
  *
  */
 
-#include "glk/scott/decompress_text.h"
 #include "common/str.h"
+#include "glk/scott/decompress_text.h"
 
 namespace Glk {
 namespace Scott {
diff --git a/engines/glk/scott/decompress_z80.cpp b/engines/glk/scott/decompress_z80.cpp
index 5d7662e952c..b89dd8d592e 100644
--- a/engines/glk/scott/decompress_z80.cpp
+++ b/engines/glk/scott/decompress_z80.cpp
@@ -19,10 +19,10 @@
  *
  */
 
-#include "glk/scott/decompress_z80.h"
 #include "common/algorithm.h"
 #include "common/array.h"
 #include "common/textconsole.h"
+#include "glk/scott/decompress_z80.h"
 
 namespace Glk {
 namespace Scott {
diff --git a/engines/glk/scott/detect_game.cpp b/engines/glk/scott/detect_game.cpp
index 4c5110daeb8..97b404cb181 100644
--- a/engines/glk/scott/detect_game.cpp
+++ b/engines/glk/scott/detect_game.cpp
@@ -19,21 +19,21 @@
  *
  */
 
+#include "common/str.h"
+#include "glk/scott/scott.h"
+#include "glk/scott/globals.h"
 #include "glk/scott/command_parser.h"
-#include "glk/scott/detect_game.h"
 #include "glk/scott/decompress_text.h"
 #include "glk/scott/decompress_z80.h"
 #include "glk/scott/detection.h"
 #include "glk/scott/detection_tables.h"
 #include "glk/scott/game_info.h"
-#include "glk/scott/globals.h"
 #include "glk/scott/hulk.h"
 #include "glk/scott/line_drawing.h"
 #include "glk/scott/saga_draw.h"
-#include "glk/scott/scott.h"
 #include "glk/scott/c64_checksums.h"
 #include "glk/scott/game_specific.h"
-#include "common/str.h"
+#include "glk/scott/detect_game.h"
 
 namespace Glk {
 namespace Scott {
diff --git a/engines/glk/scott/detection.cpp b/engines/glk/scott/detection.cpp
index d3569b18494..ab25af42ffc 100644
--- a/engines/glk/scott/detection.cpp
+++ b/engines/glk/scott/detection.cpp
@@ -19,12 +19,12 @@
  *
  */
 
-#include "glk/scott/detection.h"
-#include "glk/scott/detection_tables.h"
-#include "glk/blorb.h"
 #include "common/file.h"
 #include "common/md5.h"
 #include "engines/game.h"
+#include "glk/blorb.h"
+#include "glk/scott/detection.h"
+#include "glk/scott/detection_tables.h"
 
 namespace Glk {
 namespace Scott {
diff --git a/engines/glk/scott/detection_tables.h b/engines/glk/scott/detection_tables.h
index 6d074f0ec10..54b12ed6a72 100644
--- a/engines/glk/scott/detection_tables.h
+++ b/engines/glk/scott/detection_tables.h
@@ -19,9 +19,9 @@
  *
  */
 
-#include "engines/game.h"
 #include "common/gui_options.h"
 #include "common/language.h"
+#include "engines/game.h"
 
 namespace Glk {
 namespace Scott {
diff --git a/engines/glk/scott/game_info.cpp b/engines/glk/scott/game_info.cpp
index c6902a250a3..79a9a65e383 100644
--- a/engines/glk/scott/game_info.cpp
+++ b/engines/glk/scott/game_info.cpp
@@ -19,10 +19,10 @@
  *
  */
 
-#include "glk/scott/definitions.h"
 #include "common/array.h"
 #include "common/str.h"
 #include "common/str-array.h"
+#include "glk/scott/definitions.h"
 
 namespace Glk {
 namespace Scott {
diff --git a/engines/glk/scott/game_info.h b/engines/glk/scott/game_info.h
index 2fdf4e10897..13b06353d5e 100644
--- a/engines/glk/scott/game_info.h
+++ b/engines/glk/scott/game_info.h
@@ -22,8 +22,8 @@
 #ifndef GLK_SCOTT_GAMEINFO_H
 #define GLK_SCOTT_GAMEINFO_H
 
-#include "glk/scott/definitions.h"
 #include "common/array.h"
+#include "glk/scott/definitions.h"
 
 namespace Glk {
 namespace Scott {
diff --git a/engines/glk/scott/game_specific.cpp b/engines/glk/scott/game_specific.cpp
index 3549cc90143..7d5205c2838 100644
--- a/engines/glk/scott/game_specific.cpp
+++ b/engines/glk/scott/game_specific.cpp
@@ -19,10 +19,10 @@
  *
  */
 
-#include "glk/scott/game_specific.h"
+#include "common/str.h"
 #include "glk/scott/scott.h"
 #include "glk/scott/globals.h"
-#include "common/str.h"
+#include "glk/scott/game_specific.h"
 
 namespace Glk {
 namespace Scott {
diff --git a/engines/glk/scott/globals.cpp b/engines/glk/scott/globals.cpp
index 22df5b1659c..a7d00c89897 100644
--- a/engines/glk/scott/globals.cpp
+++ b/engines/glk/scott/globals.cpp
@@ -19,12 +19,12 @@
  *
  */
 
-#include "glk/scott/globals.h"
+#include "common/algorithm.h"
 #include "glk/scott/scott.h"
 #include "glk/scott/command_parser.h"
 #include "glk/scott/line_drawing.h"
 #include "glk/scott/saga_draw.h"
-#include "common/algorithm.h"
+#include "glk/scott/globals.h"
 
 namespace Glk {
 namespace Scott {
diff --git a/engines/glk/scott/globals.h b/engines/glk/scott/globals.h
index 638d06aa15f..74668ea4696 100644
--- a/engines/glk/scott/globals.h
+++ b/engines/glk/scott/globals.h
@@ -25,9 +25,9 @@
 #include "common/array.h"
 #include "common/str-array.h"
 #include "glk/glk_types.h"
+#include "glk/windows.h"
 #include "glk/scott/definitions.h"
 #include "glk/scott/types.h"
-#include "glk/windows.h"
 
 namespace Glk {
 namespace Scott {
diff --git a/engines/glk/scott/hulk.cpp b/engines/glk/scott/hulk.cpp
index 33073c86c5b..c1cbeb890f4 100644
--- a/engines/glk/scott/hulk.cpp
+++ b/engines/glk/scott/hulk.cpp
@@ -19,12 +19,12 @@
  *
  */
 
-#include "glk/scott/hulk.h"
+#include "glk/scott/scott.h"
 #include "glk/scott/definitions.h"
 #include "glk/scott/detect_game.h"
 #include "glk/scott/globals.h"
-#include "glk/scott/scott.h"
 #include "glk/scott/types.h"
+#include "glk/scott/hulk.h"
 
 namespace Glk {
 namespace Scott {
diff --git a/engines/glk/scott/layout_text.cpp b/engines/glk/scott/layout_text.cpp
index 1ba4700c960..9cb10fb1909 100644
--- a/engines/glk/scott/layout_text.cpp
+++ b/engines/glk/scott/layout_text.cpp
@@ -19,8 +19,8 @@
  *
  */
 
-#include "glk/scott/layout_text.h"
 #include "common/util.h"
+#include "glk/scott/layout_text.h"
 
 namespace Glk {
 namespace Scott {
diff --git a/engines/glk/scott/line_drawing.cpp b/engines/glk/scott/line_drawing.cpp
index e3437a3a043..d95831db1fa 100644
--- a/engines/glk/scott/line_drawing.cpp
+++ b/engines/glk/scott/line_drawing.cpp
@@ -19,11 +19,11 @@
  *
  */
 
-#include "glk/scott/line_drawing.h"
+#include "glk/scott/scott.h"
 #include "glk/scott/globals.h"
 #include "glk/scott/ring_buffer.h"
 #include "glk/scott/saga_draw.h"
-#include "glk/scott/scott.h"
+#include "glk/scott/line_drawing.h"
 
 namespace Glk {
 namespace Scott {
diff --git a/engines/glk/scott/restore_state.cpp b/engines/glk/scott/restore_state.cpp
index 1fd46e0da16..f397876f09d 100644
--- a/engines/glk/scott/restore_state.cpp
+++ b/engines/glk/scott/restore_state.cpp
@@ -19,10 +19,10 @@
  *
  */
 
-#include "glk/scott/restore_state.h"
+#include "glk/scott/scott.h"
 #include "glk/scott/globals.h"
 #include "glk/scott/definitions.h"
-#include "glk/scott/scott.h"
+#include "glk/scott/restore_state.h"
 
 namespace Glk {
 namespace Scott {
diff --git a/engines/glk/scott/saga_draw.cpp b/engines/glk/scott/saga_draw.cpp
index 79db99b7a10..00b557fbd82 100644
--- a/engines/glk/scott/saga_draw.cpp
+++ b/engines/glk/scott/saga_draw.cpp
@@ -19,11 +19,11 @@
  *
  */
 
-#include "glk/scott/saga_draw.h"
+#include "glk/scott/scott.h"
 #include "glk/scott/definitions.h"
 #include "glk/scott/detect_game.h"
 #include "glk/scott/globals.h"
-#include "glk/scott/scott.h"
+#include "glk/scott/saga_draw.h"
 
 namespace Glk {
 namespace Scott {
diff --git a/engines/glk/scott/scott.cpp b/engines/glk/scott/scott.cpp
index ba50aa68bff..a568a7e373d 100644
--- a/engines/glk/scott/scott.cpp
+++ b/engines/glk/scott/scott.cpp
@@ -19,11 +19,11 @@
  *
  */
 
-#include "glk/scott/scott.h"
 #include "common/config-manager.h"
 #include "common/translation.h"
 #include "common/ustr.h"
 #include "glk/quetzal.h"
+#include "glk/scott/scott.h"
 #include "glk/scott/command_parser.h"
 #include "glk/scott/definitions.h"
 #include "glk/scott/detect_game.h"


Commit: 5aa305e716e0881e57113b3e0231fb7fcd6724bb
    https://github.com/scummvm/scummvm/commit/5aa305e716e0881e57113b3e0231fb7fcd6724bb
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Replace unsigned char with byte

Changed paths:
    engines/glk/scott/c64_checksums.cpp


diff --git a/engines/glk/scott/c64_checksums.cpp b/engines/glk/scott/c64_checksums.cpp
index 2cdea4c2046..f3f159689d4 100644
--- a/engines/glk/scott/c64_checksums.cpp
+++ b/engines/glk/scott/c64_checksums.cpp
@@ -132,7 +132,7 @@ static C64Rec g_C64Registry[] = {
 	{ UNKNOWN_GAME, 0, 0, UNKNOWN_FILE_TYPE, 0, nullptr, nullptr, 0, 0, 0, 0 }
 };
 
-static uint16_t checksum(unsigned char *sf, uint32_t extent) {
+static uint16_t checksum(byte *sf, uint32_t extent) {
 	return 0;
 }
 


Commit: cf55512f808c8940bdb3298fdca717855b2b916b
    https://github.com/scummvm/scummvm/commit/cf55512f808c8940bdb3298fdca717855b2b916b
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Improve error messages

Changed paths:
    engines/glk/scott/c64_checksums.cpp
    engines/glk/scott/decompress_z80.cpp
    engines/glk/scott/detect_game.cpp
    engines/glk/scott/detection.cpp
    engines/glk/scott/hulk.cpp
    engines/glk/scott/line_drawing.cpp
    engines/glk/scott/saga_draw.cpp
    engines/glk/scott/scott.cpp


diff --git a/engines/glk/scott/c64_checksums.cpp b/engines/glk/scott/c64_checksums.cpp
index f3f159689d4..ee9067f50fa 100644
--- a/engines/glk/scott/c64_checksums.cpp
+++ b/engines/glk/scott/c64_checksums.cpp
@@ -182,7 +182,7 @@ int detectC64(uint8_t **sf, size_t *extent) {
 				if (g_C64Registry[i]._appendFile != nullptr) {
 					appendix = getFileNamed(*sf, *extent, &appendixlen, g_C64Registry[i]._appendFile);
 					if (appendix == nullptr)
-						error("Appending file failed!\n");
+						error("detectC64(): Appending file failed");
 					appendixlen -= 2;
 				}
 
diff --git a/engines/glk/scott/decompress_z80.cpp b/engines/glk/scott/decompress_z80.cpp
index b89dd8d592e..a3e1715ec30 100644
--- a/engines/glk/scott/decompress_z80.cpp
+++ b/engines/glk/scott/decompress_z80.cpp
@@ -38,7 +38,7 @@ const int SNAPSHOT_RAM_PAGES = 16;
 
 void *libspectrumReallocN(void *ptr, size_t nmemb, size_t size) {
 	if (nmemb > SIZE_MAX / size)
-		error("Can't reallocate to required size");
+		error("libspectrumReallocN: Can't reallocate to required size");
 
 	return realloc(ptr, nmemb * size);
 }
diff --git a/engines/glk/scott/detect_game.cpp b/engines/glk/scott/detect_game.cpp
index 97b404cb181..3647aa5fd8e 100644
--- a/engines/glk/scott/detect_game.cpp
+++ b/engines/glk/scott/detect_game.cpp
@@ -343,12 +343,12 @@ void loadVectorData(GameInfo info, uint8_t *ptr) {
 			lp->_bgColour = *(ptr++);
 			lp->_data = ptr;
 		} else {
-			error("Error! Image data does not start with 0xff!\n");
+			error("loadVectorData: Error! Image data does not start with 0xff");
 		}
 		do {
 			byte = *(ptr++);
 			if (ptr > _G(_entireFile) && static_cast<size_t>(ptr - _G(_entireFile)) >= _G(_fileLength)) {
-				error("Error! Image data for image %d cut off!\n", ct);
+				error("loadVectorData: Error! Image data for image %d cut off", ct);
 				if (_G(_gameHeader)->_numRooms - ct > 1)
 					g_scott->display(_G(_bottomWindow), "[This copy has %d broken or missing pictures. These have been patched out.]\n\n", _G(_gameHeader)->_numRooms - ct);
 				if (lp->_data >= ptr)
@@ -953,12 +953,12 @@ int tryLoading(GameInfo info, int dictStart, int loud) {
 			value = *(ptr++); /* count of actions/conditions */
 			cond = value & 0x1f;
 			if (cond > 5) {
-				debug("Condition error at action %d!\n", ct);
+				debug("Condition error at action %d!", ct);
 				cond = 5;
 			}
 			comm = (value & 0xe0) >> 5;
 			if (comm > 2) {
-				debug("Command error at action %d!\n", ct);
+				debug("Command error at action %d!", ct);
 				comm = 2;
 			}
 		} else {
diff --git a/engines/glk/scott/detection.cpp b/engines/glk/scott/detection.cpp
index ab25af42ffc..42900ab3341 100644
--- a/engines/glk/scott/detection.cpp
+++ b/engines/glk/scott/detection.cpp
@@ -95,7 +95,7 @@ bool ScottMetaEngine::detectGames(const Common::FSList &fslist, DetectedGames &g
 void ScottMetaEngine::detectClashes(Common::StringMap &map) {
 	for (const PlainGameDescriptor *pd = SCOTT_GAME_LIST; pd->gameId; ++pd) {
 		if (map.contains(pd->gameId))
-			error("Duplicate game Id found - %s", pd->gameId);
+			error("ScottMetaEngine::detectClashes: Duplicate game Id found - %s", pd->gameId);
 		map[pd->gameId] = "";
 	}
 }
diff --git a/engines/glk/scott/hulk.cpp b/engines/glk/scott/hulk.cpp
index c1cbeb890f4..6bbdf8b8333 100644
--- a/engines/glk/scott/hulk.cpp
+++ b/engines/glk/scott/hulk.cpp
@@ -113,7 +113,8 @@ void drawHulkImage(int p) {
 		image = 42;
 		break;
 	default:
-		error("Unhandled image number %d!\n", p);
+
+		error("drawHulkImage: Unhandled image number %d", p);
 		break;
 	}
 
diff --git a/engines/glk/scott/line_drawing.cpp b/engines/glk/scott/line_drawing.cpp
index d95831db1fa..3e1eb6276a7 100644
--- a/engines/glk/scott/line_drawing.cpp
+++ b/engines/glk/scott/line_drawing.cpp
@@ -173,7 +173,7 @@ void drawVectorPicture(int image) {
 	uint8_t opcode = 0;
 	while (((p < _G(_lineImages)[image]._data) || static_cast<size_t>(p - _G(_lineImages)[image]._data) < _G(_lineImages)[image]._size) && opcode != 0xff) {
 		if (p > _G(_entireFile) + _G(_fileLength)) {
-			error("Out of range! Opcode: %x. Image: %d. LineImages[%d].size: %llu\n", opcode, image, image, _G(_lineImages)[image]._size);
+			error("drawVectorPicture: Out of range! Opcode: %x. Image: %d. LineImages[%d].size: %llu", opcode, image, image, _G(_lineImages)[image]._size);
 			break;
 		}
 		opcode = *(p++);
diff --git a/engines/glk/scott/saga_draw.cpp b/engines/glk/scott/saga_draw.cpp
index 00b557fbd82..13e26b803b6 100644
--- a/engines/glk/scott/saga_draw.cpp
+++ b/engines/glk/scott/saga_draw.cpp
@@ -314,7 +314,8 @@ uint8_t *drawSagaPictureFromData(uint8_t *dataptr, int xSize, int ySize, int xOf
 void drawSagaPictureNumber(int pictureNumber) {
 	int numgraphics = _G(_game)->_numberOfPictures;
 	if (pictureNumber >= numgraphics) {
-		error("Invalid image number % d !Last image: % d\n ", pictureNumber, numgraphics - 1);
+
+		error("drawSagaPictureNumber: Invalid image number % d !Last image: % d", pictureNumber, numgraphics - 1);
 		return;
 	}
 
@@ -336,7 +337,7 @@ void sagaSetup(size_t imgOffset) {
 	}
 
 	if (_G(_palChosen) == NO_PALETTE) {
-		error("unknown palette\n");
+		error("sagaSetup: unknown palette");
 	}
 
 	definePalette();
diff --git a/engines/glk/scott/scott.cpp b/engines/glk/scott/scott.cpp
index a568a7e373d..81df028f117 100644
--- a/engines/glk/scott/scott.cpp
+++ b/engines/glk/scott/scott.cpp
@@ -585,7 +585,7 @@ void Scott::look(void) {
 	while (ct <= _G(_gameHeader)->_numItems) {
 		if (_G(_items)[ct]._location == MY_LOC) {
 			if (_G(_items)[ct]._text[0] == 0) {
-				error("Invisible item in room: %d\n", ct);
+				error("Scott::look(): Invisible item in room: %d", ct);
 				ct++;
 				continue;
 			}
@@ -1528,7 +1528,7 @@ void Scott::listInventoryInUpperWindow() {
 	while (i <= _G(_gameHeader)->_numItems) {
 		if (_G(_items)[i]._location == CARRIED) {
 			if (_G(_items)[i]._text[0] == 0) {
-				error("Invisible item in inventory: %d\n", i);
+				error("Scott::listInventoryInUpperWindow(): Invisible item in inventory: %d", i);
 				i++;
 				continue;
 			}
@@ -1683,7 +1683,7 @@ void Scott::drawImage(int image) {
 		return;
 	openGraphicsWindow();
 	if (_G(_graphics) == nullptr) {
-		error("DrawImage: Graphic window nullptr?\n");
+		error("drawImage: Graphic window nullptr?");
 		return;
 	}
 	if (_G(_game)->_pictureFormatVersion == 99)
@@ -2074,7 +2074,7 @@ void Scott::swapCounters(int index) {
 		  index);
 #endif
 	if (index > 15) {
-		error("ERROR! parameter out of range. Max 15, got %d\n", index);
+		error("Scott::swapCounters(int index): ERROR! parameter out of range. Max 15, got %d", index);
 		index = 15;
 	}
 	int temp = _G(_currentCounter);


Commit: 8c2d9e2b7cb2b7002e8a9850121f267118cc03cc
    https://github.com/scummvm/scummvm/commit/8c2d9e2b7cb2b7002e8a9850121f267118cc03cc
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Use READ_LE_UINT16

Changed paths:
    engines/glk/scott/c64_checksums.cpp


diff --git a/engines/glk/scott/c64_checksums.cpp b/engines/glk/scott/c64_checksums.cpp
index ee9067f50fa..a820a630e47 100644
--- a/engines/glk/scott/c64_checksums.cpp
+++ b/engines/glk/scott/c64_checksums.cpp
@@ -200,10 +200,10 @@ int detectC64(uint8_t **sf, size_t *extent) {
 
 			} else if (g_C64Registry[i]._type == TYPE_T64) {
 				uint8_t *file_records = *sf + 64;
-				int number_of_records = (*sf)[36] + (*sf)[37] * 0x100;
-				int offset = file_records[8] + file_records[9] * 0x100;
-				int start_addr = file_records[2] + file_records[3] * 0x100;
-				int end_addr = file_records[4] + file_records[5] * 0x100;
+				int number_of_records = READ_LE_UINT16(&(*sf)[36]);
+				int offset = READ_LE_UINT16(&file_records[8]);
+				int start_addr = READ_LE_UINT16(&file_records[2]);
+				int end_addr = READ_LE_UINT16(&file_records[4]);
 				int size;
 				if (number_of_records == 1)
 					size = *extent - offset;


Commit: 9c4c8af24c33eb0c70ad0832a25bc3ac411882dd
    https://github.com/scummvm/scummvm/commit/9c4c8af24c33eb0c70ad0832a25bc3ac411882dd
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Refactor detect_game

Use the md5 hash to directly load the game without having to iterate through the game list. Also rename detect_game to load_game and move the resource loading to resource.cpp.

Changed paths:
  A engines/glk/scott/load_game.cpp
  A engines/glk/scott/load_game.h
  A engines/glk/scott/resource.cpp
  A engines/glk/scott/resource.h
  R engines/glk/scott/detect_game.cpp
  R engines/glk/scott/detect_game.h
    engines/glk/module.mk
    engines/glk/scott/globals.cpp
    engines/glk/scott/globals.h
    engines/glk/scott/hulk.cpp
    engines/glk/scott/saga_draw.cpp
    engines/glk/scott/scott.cpp


diff --git a/engines/glk/module.mk b/engines/glk/module.mk
index 1ebbf7ef518..edf9e59b54a 100644
--- a/engines/glk/module.mk
+++ b/engines/glk/module.mk
@@ -239,13 +239,14 @@ MODULE_OBJS := \
 	scott/decompress_text.o \
 	scott/decompress_z80.o \
 	scott/definitions.o \
-	scott/detect_game.o \
+	scott/load_game.o \
 	scott/game_info.o \
 	scott/game_specific.o \
 	scott/globals.o \
 	scott/hulk.o \
 	scott/layout_text.o \
 	scott/line_drawing.o \
+	scott/resource.o \
 	scott/restore_state.o \
 	scott/ring_buffer.o \
 	scott/saga_draw.o \
diff --git a/engines/glk/scott/globals.cpp b/engines/glk/scott/globals.cpp
index a7d00c89897..8de6499bae5 100644
--- a/engines/glk/scott/globals.cpp
+++ b/engines/glk/scott/globals.cpp
@@ -64,6 +64,19 @@ Globals::Globals() : _sys(MAX_SYSMESS), _directions(NUMBER_OF_DIRECTIONS), _extr
 
 	Common::fill(&_counters[0], &_counters[16], 0);
 	Common::fill(&_roomSaved[0], &_roomSaved[16], 0);
+
+	_md5Index.setVal("cb7dadc9d5f8bce453b9139265e4dd7d",  0); // goldenbaton
+	_md5Index.setVal("b22d1f4d46c99ff4443d541d3fe424c1",  2); // timemachine
+	_md5Index.setVal("3a5c3f4079c1c0347f03420db8ad4596",  4); // arrowofdeath1
+	_md5Index.setVal("d3f8943c4f5f71ce00139065055a72ee",  6); // arrowofdeath2
+	_md5Index.setVal("441edd90fc7f9ff39a5eebe035a974e9",  8); // pulsar7
+	_md5Index.setVal("ed99306a2fb23bf6579068a4d74034ee", 10); // circus
+	_md5Index.setVal("5e381e83f15d77e3542be4a4cffc8e25", 12); // feasibility
+	_md5Index.setVal("b0f8676817475753f1edd7f1eeea31fb", 14); // akyrz
+	_md5Index.setVal("84d5fbb16a37e495abf09d191fd8b1a2", 16); // perseus
+	_md5Index.setVal("afde056c152de79ea20453c42a2d08af", 18); // 10indians
+	_md5Index.setVal("6c6fbbbb50032463a6ea71c6750ea1f5", 20); // waxworks11
+	_md5Index.setVal("0eec511d3cde815c73e5464ab0cdbef9" ,22); // marveladventure
 }
 
 Globals::~Globals() {
diff --git a/engines/glk/scott/globals.h b/engines/glk/scott/globals.h
index 74668ea4696..6b6b20617d6 100644
--- a/engines/glk/scott/globals.h
+++ b/engines/glk/scott/globals.h
@@ -23,7 +23,9 @@
 #define GLK_SCOTT_GLOBALS_H
 
 #include "common/array.h"
+#include "common/str.h"
 #include "common/str-array.h"
+#include "common/hashmap.h"
 #include "glk/glk_types.h"
 #include "glk/windows.h"
 #include "glk/scott/definitions.h"
@@ -150,6 +152,10 @@ public:
 	GameInfo _fallbackGame;
 	// Include game list
 	#include "glk/scott/games.h"
+
+	// detect game
+	Common::HashMap<Common::String, int> _md5Index;
+
 public:
 	Globals();
 	~Globals();
diff --git a/engines/glk/scott/hulk.cpp b/engines/glk/scott/hulk.cpp
index 6bbdf8b8333..76dd1c34c07 100644
--- a/engines/glk/scott/hulk.cpp
+++ b/engines/glk/scott/hulk.cpp
@@ -21,7 +21,7 @@
 
 #include "glk/scott/scott.h"
 #include "glk/scott/definitions.h"
-#include "glk/scott/detect_game.h"
+#include "glk/scott/resource.h"
 #include "glk/scott/globals.h"
 #include "glk/scott/types.h"
 #include "glk/scott/hulk.h"
diff --git a/engines/glk/scott/load_game.cpp b/engines/glk/scott/load_game.cpp
new file mode 100644
index 00000000000..30291354f78
--- /dev/null
+++ b/engines/glk/scott/load_game.cpp
@@ -0,0 +1,156 @@
+/* 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 "common/str.h"
+#include "glk/scott/scott.h"
+#include "glk/scott/globals.h"
+#include "glk/scott/command_parser.h"
+#include "glk/scott/decompress_text.h"
+#include "glk/scott/decompress_z80.h"
+#include "glk/scott/detection.h"
+#include "glk/scott/detection_tables.h"
+#include "glk/scott/game_info.h"
+#include "glk/scott/hulk.h"
+#include "glk/scott/line_drawing.h"
+#include "glk/scott/saga_draw.h"
+#include "glk/scott/c64_checksums.h"
+#include "glk/scott/game_specific.h"
+#include "glk/scott/resource.h"
+#include "glk/scott/load_game.h"
+
+namespace Glk {
+namespace Scott {
+
+void loadZXSpectrum(Common::SeekableReadStream *f, Common::String md5) {
+	_G(_entireFile) = new uint8_t[_G(_fileLength)];
+	size_t result = f->read(_G(_entireFile), _G(_fileLength));
+	if (result != _G(_fileLength))
+		g_scott->fatal("File empty or read error!");
+
+	uint8_t *uncompressed = decompressZ80(_G(_entireFile), _G(_fileLength));
+	if (uncompressed != nullptr) {
+		delete[] _G(_entireFile);
+		_G(_entireFile) = uncompressed;
+		_G(_fileLength) = 0xc000;
+	}
+
+	int offset;
+	DictionaryType dict_type = getId(&offset);
+	if (dict_type == NOT_A_GAME)
+		return;
+
+	int index = _G(_md5Index)[md5];
+	if (tryLoading(g_games[index], offset, 0)) {
+		delete _G(_game);
+		_G(_game) = &g_games[index];
+	}
+}
+
+void loadC64(Common::SeekableReadStream* f, Common::String md5) {
+	_G(_entireFile) = new uint8_t[_G(_fileLength)];
+	size_t result = f->read(_G(_entireFile), _G(_fileLength));
+	if (result != _G(_fileLength))
+		g_scott->fatal("File empty or read error!");
+
+	CURRENT_GAME = static_cast<GameIDType>(detectC64(&_G(_entireFile), &_G(_fileLength)));
+}
+
+void loadGameFile(Common::SeekableReadStream *f) {
+
+	for (int i = 0; i < NUMBER_OF_DIRECTIONS; i++)
+		_G(_directions)[i] = _G(_englishDirections)[i];
+	for (int i = 0; i < NUMBER_OF_SKIPPABLE_WORDS; i++)
+		_G(_skipList)[i] = _G(_englishSkipList)[i];
+	for (int i = 0; i < NUMBER_OF_DELIMITERS; i++)
+		_G(_delimiterList)[i] = _G(_englishDelimiterList)[i];
+	for (int i = 0; i < NUMBER_OF_EXTRA_NOUNS; i++)
+		_G(_extraNouns)[i] = _G(_englishExtraNouns)[i];
+
+	_G(_fileLength) = f->size();
+
+	_G(_game) = new GameInfo;
+
+	Common::String md5 = g_vm->getGameMD5();
+	const GlkDetectionEntry *p = SCOTT_GAMES;
+
+	while (p->_md5) {
+		if (md5.equalsC(p->_md5)) {
+			if (!scumm_stricmp(p->_extra, "")) {
+				CURRENT_GAME = SCOTTFREE;
+			} else if (!scumm_stricmp(p->_extra, "ZXSpectrum")) {
+				loadZXSpectrum(f, md5);
+			} else if (!scumm_stricmp(p->_extra, "C64")) {
+				loadC64(f, md5);
+			}
+			// TODO
+			// TI99/4A Detection
+		}
+		++p;
+	}
+
+	if (CURRENT_GAME == SCOTTFREE || CURRENT_GAME == TI994A)
+		return;
+
+	/* Copy ZX Spectrum style system messages as base */
+	for (int i = 6; i < MAX_SYSMESS && g_sysDictZX[i] != nullptr; i++) {
+		_G(_sys)[i] = g_sysDictZX[i];
+	}
+
+	switch (CURRENT_GAME) {
+	case HULK_C64:
+	case HULK:
+		for (int i = 0; i < 6; i++) {
+			_G(_sys)[i] = g_sysDictZX[i];
+		}
+		break;
+	default:
+		if (!(_G(_game)->_subType & C64)) {
+			if (_G(_game)->_subType & MYSTERIOUS) {
+				for (int i = PLAY_AGAIN; i <= YOU_HAVENT_GOT_IT; i++)
+					_G(_sys)[i] = _G(_systemMessages)[2 - PLAY_AGAIN + i];
+				for (int i = YOU_DONT_SEE_IT; i <= WHAT_NOW; i++)
+					_G(_sys)[i] = _G(_systemMessages)[15 - YOU_DONT_SEE_IT + i];
+				for (int i = LIGHT_HAS_RUN_OUT; i <= RESUME_A_SAVED_GAME; i++)
+					_G(_sys)[i] = _G(_systemMessages)[31 - LIGHT_HAS_RUN_OUT + i];
+				_G(_sys)[ITEM_DELIMITER] = " - ";
+				_G(_sys)[MESSAGE_DELIMITER] = "\n";
+				_G(_sys)[YOU_SEE] = "\nThings I can see:\n";
+				break;
+			} else {
+				for (int i = PLAY_AGAIN; i <= RESUME_A_SAVED_GAME; i++)
+					_G(_sys)[i] = _G(_systemMessages)[2 - PLAY_AGAIN + i];
+			}
+		}
+		break;
+	}
+
+	if (!(_G(_game)->_subType & (C64 | MYSTERIOUS))) {
+		mysterious64Sysmess();
+	}
+
+	/* If it is a C64 or a Mysterious Adventures game, we have setup the graphics already */
+	if (!(_G(_game)->_subType & (C64 | MYSTERIOUS)) && _G(_game)->_numberOfPictures > 0) {
+		sagaSetup(0);
+	}
+}
+
+} // End of namespace Scott
+} // End of namespace Glk
diff --git a/engines/glk/scott/load_game.h b/engines/glk/scott/load_game.h
new file mode 100644
index 00000000000..23e3d5d673c
--- /dev/null
+++ b/engines/glk/scott/load_game.h
@@ -0,0 +1,37 @@
+/* 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 GLK_SCOTT_DETECTGAME_H
+#define GLK_SCOTT_DETECTGAME_H
+
+#include "common/stream.h"
+#include "glk/scott/definitions.h"
+#include "glk/scott/types.h"
+
+namespace Glk {
+namespace Scott {
+
+void loadGameFile(Common::SeekableReadStream *f);
+
+} // End of namespace Scott
+} // End of namespace Glk
+
+#endif
diff --git a/engines/glk/scott/detect_game.cpp b/engines/glk/scott/resource.cpp
similarity index 84%
rename from engines/glk/scott/detect_game.cpp
rename to engines/glk/scott/resource.cpp
index 3647aa5fd8e..8c7ec347ab2 100644
--- a/engines/glk/scott/detect_game.cpp
+++ b/engines/glk/scott/resource.cpp
@@ -33,7 +33,7 @@
 #include "glk/scott/saga_draw.h"
 #include "glk/scott/c64_checksums.h"
 #include "glk/scott/game_specific.h"
-#include "glk/scott/detect_game.h"
+#include "glk/scott/resource.h"
 
 namespace Glk {
 namespace Scott {
@@ -367,183 +367,6 @@ void loadVectorData(GameInfo info, uint8_t *ptr) {
 	} while (ct < info._numberOfRooms);
 }
 
-GameIDType detectGame(Common::SeekableReadStream *f) {
-
-	for (int i = 0; i < NUMBER_OF_DIRECTIONS; i++)
-		_G(_directions)[i] = _G(_englishDirections)[i];
-	for (int i = 0; i < NUMBER_OF_SKIPPABLE_WORDS; i++)
-		_G(_skipList)[i] = _G(_englishSkipList)[i];
-	for (int i = 0; i < NUMBER_OF_DELIMITERS; i++)
-		_G(_delimiterList)[i] = _G(_englishDelimiterList)[i];
-	for (int i = 0; i < NUMBER_OF_EXTRA_NOUNS; i++)
-		_G(_extraNouns)[i] = _G(_englishExtraNouns)[i];
-
-	_G(_fileLength) = f->size();
-
-	_G(_game) = &_G(_fallbackGame);
-
-	Common::String md5 = g_vm->getGameMD5();
-	const GlkDetectionEntry *p = SCOTT_GAMES;
-
-	while (p->_md5) {
-		if (md5.equalsC(p->_md5)) {
-			if (!scumm_stricmp(p->_extra, "")) {
-				_G(_fallbackGame)._gameID = SCOTTFREE;
-			}
-			if (!scumm_stricmp(p->_extra, "ZXSpectrum")) {
-				_G(_entireFile) = new uint8_t[_G(_fileLength)];
-				size_t result = f->read(_G(_entireFile), _G(_fileLength));
-				if (result != _G(_fileLength))
-					g_scott->fatal("File empty or read error!");
-
-				// ZXSpectrum Detection
-				uint8_t *uncompressed = decompressZ80(_G(_entireFile), _G(_fileLength));
-				if (uncompressed != nullptr) {
-					delete[] _G(_entireFile);
-					_G(_entireFile) = uncompressed;
-					_G(_fileLength) = 0xc000;
-				}
-
-				int offset;
-				DictionaryType dict_type = getId(&offset);
-				if (dict_type == NOT_A_GAME)
-					return UNKNOWN_GAME;
-				for (int i = 0; i < NUMGAMES; i++) {
-					if (_G(_games)[i]._dictionary == dict_type) {
-						if (tryLoading(_G(_games)[i], offset, 0)) {
-							_G(_game) = &_G(_games)[i];
-							break;
-						}
-					}
-				}
-			} else if (!scumm_stricmp(p->_extra, "C64")) {
-				_G(_entireFile) = new uint8_t[_G(_fileLength)];
-				size_t result = f->read(_G(_entireFile), _G(_fileLength));
-				if (result != _G(_fileLength))
-					g_scott->fatal("File empty or read error!");
-
-				CURRENT_GAME = static_cast<GameIDType>(detectC64(&_G(_entireFile), &_G(_fileLength)));
-			}
-		}
-		// TODO
-		// TI99/4A Detection
-
-		++p;
-	}
-
-	if (CURRENT_GAME == SCOTTFREE || CURRENT_GAME == TI994A)
-		return CURRENT_GAME;
-
-	/* Copy ZX Spectrum style system messages as base */
-	for (int i = 6; i < MAX_SYSMESS && g_sysDictZX[i] != nullptr; i++) {
-		_G(_sys)[i] = g_sysDictZX[i];
-	}
-
-	switch (CURRENT_GAME) {
-	case ROBIN_OF_SHERWOOD:
-		// TODO
-		break;
-	case ROBIN_OF_SHERWOOD_C64:
-		// TODO
-		break;
-	case SEAS_OF_BLOOD:
-		// TODO
-		break;
-	case SEAS_OF_BLOOD_C64:
-		// TODO
-		break;
-	case CLAYMORGUE:
-		// TODO
-		break;
-	case SECRET_MISSION:
-	case SECRET_MISSION_C64:
-		// TODO
-		break;
-	case ADVENTURELAND:
-		// TODO
-		break;
-	case ADVENTURELAND_C64:
-		// TODO
-		break;
-	case CLAYMORGUE_C64:
-		// TODO
-		break;
-	case GREMLINS_GERMAN_C64:
-		// TODO
-		break;
-	case SPIDERMAN_C64:
-		// TODO
-		break;
-	case SUPERGRAN_C64:
-		// TODO
-		break;
-	case SAVAGE_ISLAND_C64:
-	case SAVAGE_ISLAND2_C64:
-		// TODO
-		break;
-	case SAVAGE_ISLAND:
-	case SAVAGE_ISLAND2:
-	case GREMLINS_GERMAN:
-	case GREMLINS:
-	case SUPERGRAN:
-		// TODO
-		break;
-	case GREMLINS_SPANISH:
-		// TODO
-		break;
-	case HULK_C64:
-	case HULK:
-		for (int i = 0; i < 6; i++) {
-			_G(_sys)[i] = g_sysDictZX[i];
-		}
-		break;
-	default:
-		if (!(_G(_game)->_subType & C64)) {
-			if (_G(_game)->_subType & MYSTERIOUS) {
-				for (int i = PLAY_AGAIN; i <= YOU_HAVENT_GOT_IT; i++)
-					_G(_sys)[i] = _G(_systemMessages)[2 - PLAY_AGAIN + i];
-				for (int i = YOU_DONT_SEE_IT; i <= WHAT_NOW; i++)
-					_G(_sys)[i] = _G(_systemMessages)[15 - YOU_DONT_SEE_IT + i];
-				for (int i = LIGHT_HAS_RUN_OUT; i <= RESUME_A_SAVED_GAME; i++)
-					_G(_sys)[i] = _G(_systemMessages)[31 - LIGHT_HAS_RUN_OUT + i];
-				_G(_sys)[ITEM_DELIMITER] = " - ";
-				_G(_sys)[MESSAGE_DELIMITER] = "\n";
-				_G(_sys)[YOU_SEE] = "\nThings I can see:\n";
-				break;
-			} else {
-				for (int i = PLAY_AGAIN; i <= RESUME_A_SAVED_GAME; i++)
-					_G(_sys)[i] = _G(_systemMessages)[2 - PLAY_AGAIN + i];
-			}
-		}
-		break;
-	}
-
-	switch (CURRENT_GAME) {
-	case GREMLINS_GERMAN:
-		// TODO
-		break;
-	case GREMLINS_GERMAN_C64:
-		// TODO
-		break;
-	case PERSEUS_ITALIAN:
-		// TODO
-		break;
-	default:
-		break;
-	}
-
-	if (!(_G(_game)->_subType & (C64 | MYSTERIOUS))) {
-		mysterious64Sysmess();
-	}
-
-	/* If it is a C64 or a Mysterious Adventures game, we have setup the graphics already */
-	if (!(_G(_game)->_subType & (C64 | MYSTERIOUS)) && _G(_game)->_numberOfPictures > 0) {
-		sagaSetup(0);
-	}
-
-	return CURRENT_GAME;
-}
-
 uint8_t *seekToPos(uint8_t *buf, size_t offset) {
 	if (offset > _G(_fileLength))
 		return 0;
diff --git a/engines/glk/scott/detect_game.h b/engines/glk/scott/resource.h
similarity index 92%
rename from engines/glk/scott/detect_game.h
rename to engines/glk/scott/resource.h
index 7983c32d54c..a28541cc345 100644
--- a/engines/glk/scott/detect_game.h
+++ b/engines/glk/scott/resource.h
@@ -19,8 +19,8 @@
  *
  */
 
-#ifndef GLK_SCOTT_DETECTGAME_H
-#define GLK_SCOTT_DETECTGAME_H
+#ifndef GLK_SCOTT_RESOURCE_H
+#define GLK_SCOTT_RESOURCE_H
 
 #include "common/stream.h"
 #include "glk/scott/definitions.h"
@@ -31,7 +31,6 @@ namespace Scott {
 
 void readHeader(uint8_t *ptr);
 int parseHeader(int *h, HeaderType type, int *ni, int *na, int *nw, int *nr, int *mc, int *pr, int *tr, int *wl, int *lt, int *mn, int *trm);
-GameIDType detectGame(Common::SeekableReadStream *f);
 uint8_t *seekToPos(uint8_t *buf, size_t offset);
 int seekIfNeeded(int expectedStart, int *offset, uint8_t **ptr);
 int tryLoading(GameInfo info, int dictStart, int loud);
diff --git a/engines/glk/scott/saga_draw.cpp b/engines/glk/scott/saga_draw.cpp
index 13e26b803b6..16a69f6a8d6 100644
--- a/engines/glk/scott/saga_draw.cpp
+++ b/engines/glk/scott/saga_draw.cpp
@@ -21,7 +21,7 @@
 
 #include "glk/scott/scott.h"
 #include "glk/scott/definitions.h"
-#include "glk/scott/detect_game.h"
+#include "glk/scott/resource.h"
 #include "glk/scott/globals.h"
 #include "glk/scott/saga_draw.h"
 
diff --git a/engines/glk/scott/scott.cpp b/engines/glk/scott/scott.cpp
index 81df028f117..ae595739573 100644
--- a/engines/glk/scott/scott.cpp
+++ b/engines/glk/scott/scott.cpp
@@ -26,7 +26,7 @@
 #include "glk/scott/scott.h"
 #include "glk/scott/command_parser.h"
 #include "glk/scott/definitions.h"
-#include "glk/scott/detect_game.h"
+#include "glk/scott/load_game.h"
 #include "glk/scott/game_info.h"
 #include "glk/scott/globals.h"
 #include "glk/scott/hulk.h"
@@ -74,19 +74,19 @@ void Scott::runGame() {
 		_G(_sys)[i] = dictpointer[i];
 	}
 
-	GameIDType gameType = detectGame(&_gameFile);
+	loadGameFile(&_gameFile);
 
-	if (gameType == SCOTTFREE)
+	if (CURRENT_GAME == SCOTTFREE)
 		loadDatabase(&_gameFile, (_options & DEBUGGING) ? 1 : 0);
 
-	if (!gameType)
+	if (!CURRENT_GAME)
 		fatal("Unsupported game!");
 
-	if (gameType != SCOTTFREE && gameType != TI994A) {
+	if (CURRENT_GAME != SCOTTFREE && CURRENT_GAME != TI994A) {
 		_options |= SPECTRUM_STYLE;
 		_splitScreen = 1;
 	} else {
-		if (gameType != TI994A)
+		if (CURRENT_GAME != TI994A)
 			_options |= TRS80_STYLE;
 		_splitScreen = 1;
 	}
@@ -118,7 +118,7 @@ void Scott::runGame() {
 
 	openTopWindow();
 
-	if (gameType == SCOTTFREE)
+	if (CURRENT_GAME == SCOTTFREE)
 		output("ScummVM support adapted from Scott Free, A Scott Adams game driver in C.\n\n");
 
 	// Check for savegame


Commit: 6a0074fe7403636d3e3706dd7c5305abf53a6ac1
    https://github.com/scummvm/scummvm/commit/6a0074fe7403636d3e3706dd7c5305abf53a6ac1
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Refactor c64_checksums

Use the md5 hash to directly load the game instead of iterating through the list. Also remove unsupported games.

Changed paths:
    engines/glk/scott/c64_checksums.cpp
    engines/glk/scott/globals.cpp


diff --git a/engines/glk/scott/c64_checksums.cpp b/engines/glk/scott/c64_checksums.cpp
index a820a630e47..749fc20789f 100644
--- a/engines/glk/scott/c64_checksums.cpp
+++ b/engines/glk/scott/c64_checksums.cpp
@@ -19,7 +19,9 @@
  *
  */
 
+#include "common/str.h"
 #include "glk/scott/scott.h"
+#include "glk/scott/globals.h"
 #include "glk/scott/c64_checksums.h"
 #include "glk/scott/definitions.h"
 
@@ -65,91 +67,11 @@ static C64Rec g_C64Registry[] = {
 	{ WAXWORKS_C64,		0x2ab00, 0x9eaa, TYPE_D64, 0 },
 	{ BATON_C64,		0x2ab00, 0x9dca, TYPE_D64, 2 },
 
-	{ BATON_C64,		0x5170,	 0xb240, TYPE_T64, 2 },		// The Golden Baton C64, T64
-	{ BATON_C64,		0x2ab00, 0xbfbf, TYPE_D64, 2 },		// Mysterious Adventures C64 dsk 1 alt
-	{ FEASIBILITY_C64,	0x2ab00, 0x9c18, TYPE_D64, 2 },		// Mysterious Adventures C64 dsk 2 alt
-	{ TIME_MACHINE_C64,	0x5032,  0x5635, TYPE_T64, 1 },		// The Time Machine C64
-	{ ARROW1_C64,		0x5b46,  0x92db, TYPE_T64, 1 },		// Arrow of Death part 1 C64
-	{ ARROW2_C64,		0x5fe2,  0xe14f, TYPE_T64, 1 },		// Arrow of Death part 2 C64
-	{ PULSAR7_C64,		0x46bf,  0x1679, TYPE_T64, 1 },		// Escape from Pulsar 7 C64
-	{ CIRCUS_C64,		0x4269,  0xa449, TYPE_T64, 2 },		// Circus C64
-	{ FEASIBILITY_C64,	0x5a7b,  0x0f48, TYPE_T64, 1 },		// Feasibility Experiment C64
-	{ AKYRZ_C64,		0x2ab00, 0x6cca, TYPE_D64, 0 },		// The Wizard of Akyrz C64
-	{ AKYRZ_C64,		0x4be1,  0x5a00, TYPE_T64, 1 },		// The Wizard of Akyrz C64, T64
-	{ PERSEUS_C64,		0x502b,  0x913b, TYPE_T64, 1 },		// Perseus and Andromeda C64
-	{ INDIANS_C64,		0x4f9f,  0xe6c8, TYPE_T64, 1 },		// Ten Little Indians C64
-	{ WAXWORKS_C64,		0x4a11,  0xa37a, TYPE_T64, 1 },		// Waxworks C64
-
-	{ ADVENTURELAND_C64, 0x6a10,  0x1910, TYPE_T64, 1 },												  // Adventureland C64 (T64) CruelCrunch v2.2
-	{ ADVENTURELAND_C64, 0x6a10,  0x1b10, TYPE_T64, 1, nullptr, nullptr,	   0,	   0, 0 },            // Adventureland C64 (T64) alt CruelCrunch v2.2
-	{ ADVENTURELAND_C64, 0x2ab00, 0x6638, TYPE_D64, 1, nullptr, nullptr,	   0,	   0, 0 },            // Adventureland C64 (D64) CruelCrunch v2.2
-	{ ADVENTURELAND_C64, 0x2adab, 0x751f, TYPE_D64, 0, nullptr, nullptr,	   0,	   0, 0 },            // Adventureland C64 (D64) alt
-	{ ADVENTURELAND_C64, 0x2adab, 0x64a4, TYPE_D64, 0, nullptr, "SAG1PIC",	   -0xa53, 0, 0, 0, 0x65af }, // Adventureland C64 (D64) alt 2
-
-	{ SECRET_MISSION_C64, 0x88be,  0xa122, TYPE_T64, 1, nullptr, nullptr, 0, 0, 0 },             // Secret Mission  C64 (T64) Section8 Packer
-	{ SECRET_MISSION_C64, 0x2ab00, 0x04d6, TYPE_D64, 0, nullptr, nullptr, 0, 0, 0, 0, -0x1bff }, // Secret Mission  C64 (D64)
-
-	{ CLAYMORGUE_C64, 0x6ff7,  0xe4ed, TYPE_T64, 3, nullptr, nullptr, 0, 0x855, 0x7352, 0x20 },		// Sorcerer Of Claymorgue Castle C64 (T64), MasterCompressor / Relax
-	// -> ECA Compacker -> MegaByte Cruncher v1.x Missing 17 pictures
-	{ CLAYMORGUE_C64, 0x912f,  0xa69f, TYPE_T64, 1, nullptr, nullptr, 0, 0x855, 0x7352, 0x20 },		// Sorcerer Of Claymorgue Castle C64 (T64) alt, MegaByte Cruncher
-	// v1.x Missing 17 pictures
-	{ CLAYMORGUE_C64, 0xc0dd,  0x3701, TYPE_T64, 1, nullptr, nullptr, 0, 0,	    0,	    0, -0x7fe },// Sorcerer Of Claymorgue Castle C64 (T64) alt 2, Trilogic Expert
-	// v2.7
-	{ CLAYMORGUE_C64, 0xbc5f,  0x492c, TYPE_T64, 1, nullptr, nullptr, 0, 0x855, 0x7352, 0x20 },		// Sorcerer Of Claymorgue Castle C64 (T64) alt 3, , Section8 Packer
-	{ CLAYMORGUE_C64, 0x2ab00, 0xfd67, TYPE_D64, 1, nullptr, nullptr, 0, 0x855, 0x7352, 0x20 },		// Sorcerer Of Claymorgue Castle C64 (D64), Section8 Packer
-
-	{ HULK_C64,		 0x2ab00, 0xcdd8, TYPE_D64, 0, nullptr, nullptr, 0, 0x1806, 0xb801, 0x307 },		// Questprobe 1 - The Hulk C64 (D64)
-	{ SPIDERMAN_C64, 0x2ab00, 0xde56, TYPE_D64, 0, nullptr, nullptr, 0, 0x1801, 0xa801, 0x2000 },		// Spiderman C64 (D64)
-	{ SPIDERMAN_C64, 0x08e72, 0xb2f4, TYPE_T64, 3, nullptr, nullptr, 0, 0,	    0 },					// Spiderman C64 (T64) MasterCompressor / Relax -> ECA Compacker ->
-	// Section8 Packer
-
-	{ SAVAGE_ISLAND_C64,  0x2ab00, 0x8801, TYPE_D64, 1, "-f86 -d0x1793", "SAVAGEISLAND1+",   1, 0, 0 },		// Savage Island part 1 C64 (D64)
-	{ SAVAGE_ISLAND2_C64, 0x2ab00, 0x8801, TYPE_D64, 1, "-f86 -d0x178b", "SAVAGEISLAND2+",   1, 0, 0 },		// Savage Island part 2 C64 (D64)
-	{ SAVAGE_ISLAND_C64,  0x2ab00, 0xc361, TYPE_D64, 1, "-f86 -d0x1793", "SAVAGE ISLAND P1", 1, 0, 0 },		// Savage Island part 1 C64 (D64) alt
-	{ SAVAGE_ISLAND2_C64, 0x2ab00, 0xc361, TYPE_D64, 1, nullptr,			"SAVAGE ISLAND P2", 0, 0, 0 },  // Savage Island part 2  C64 (D64) alt
-
-	{ ROBIN_OF_SHERWOOD_C64, 0x2ab00, 0xcf9e, TYPE_D64, 1, nullptr, nullptr, 0, 0x1802, 0xbd27, 0x2000 }, // Robin Of Sherwood D64 * unknown packer
-	{ ROBIN_OF_SHERWOOD_C64, 0xb2ef,  0x7c44, TYPE_T64, 1, nullptr, nullptr, 0, 0x9702, 0x9627, 0x2000 }, // Robin Of Sherwood C64 (T64) * TCS Cruncher v2.0
-	{ ROBIN_OF_SHERWOOD_C64, 0xb690,  0x7b61, TYPE_T64, 1, nullptr, nullptr, 0, 0x9702, 0x9627, 0x2000 }, // Robin Of Sherwood C64 (T64) alt * TCS Cruncher v2.0
-	{ ROBIN_OF_SHERWOOD_C64, 0x8db6,  0x7853, TYPE_T64, 1, nullptr, nullptr, 0, 0xd7fb, 0xbd20, 0x2000 }, // Robin Of Sherwood T64 alt 2 * PUCrunch
-
-	{ GREMLINS_C64,			0xdd94,  0x25a8, TYPE_T64, 1, nullptr,	  nullptr, 0 },							 // Gremlins C64 (T64) version * Action Replay v4.x
-	{ GREMLINS_C64,			0x2ab00, 0xc402, TYPE_D64, 0, nullptr,	  "G1",	   -0x8D },                      // Gremlins C64 (D64) version
-	{ GREMLINS_C64,			0x2ab00, 0x3ccf, TYPE_D64, 0, nullptr,	  "G1",    -0x8D },                      // Gremlins C64 (D64) version 2
-	{ GREMLINS_C64,			0x2ab00, 0xabf8, TYPE_D64, 2, "-e0x1255", nullptr,  2 },                         // Gremlins C64 (D64) version alt * ByteBoiler, Exomizer
-	{ GREMLINS_C64,			0x2ab00, 0xa265, TYPE_D64, 2, "-e0x1255", nullptr,  2 },                         // Gremlins C64 (D64)  version alt 2 * ByteBoiler, Exomizer
-	{ GREMLINS_GERMAN_C64,	0xc003,  0x558c, TYPE_T64, 1, nullptr,	  nullptr,  0, 0xd801, 0xc6c0, 0x1f00 }, // German Gremlins C64 (T64) version * TBC Multicompactor v2.x
-	{ GREMLINS_GERMAN_C64,	0x2ab00, 0x6729, TYPE_D64, 2, nullptr,	  nullptr,  0, 0xdc02, 0xcac1, 0x1f00 }, // German Gremlins C64 (D64) version * Exomizer
-
-	{ SUPERGRAN_C64,			0x726f,  0x0901, TYPE_T64, 1, nullptr,	  nullptr,  0, 0xd802, 0xc623, 0x1f00 }, // Super Gran C64 (T64) PUCrunch Generic Hack
-
-	{ SEAS_OF_BLOOD_C64,		0xa209,  0xf115, TYPE_T64, 6, "-e0x1000", nullptr,  3, 0xd802, 0xb07c, 0x2000 }, // Seas of Blood C64 (T64) MasterCompressor / Relax -> ECA
-	// Compacker -> Unknown -> MasterCompressor / Relax -> ECA
-	// Compacker -> CCS Packer
-	{ SEAS_OF_BLOOD_C64,		0x2ab00, 0x5c1d, TYPE_D64, 1, nullptr,	  nullptr,  0, 0xd802, 0xb07c, 0x2000 }, // Seas of Blood C64 (D64) CCS Packer
-	{ SEAS_OF_BLOOD_C64,		0x2ab00, 0xe308, TYPE_D64, 1, nullptr,	  nullptr,  0, 0xd802, 0xb07c, 0x2000 }, // Seas of Blood C64 (D64) alt CCS Packer
-
 	{ UNKNOWN_GAME, 0, 0, UNKNOWN_FILE_TYPE, 0, nullptr, nullptr, 0, 0, 0, 0 }
 };
 
-static uint16_t checksum(byte *sf, uint32_t extent) {
-	return 0;
-}
-
 int decrunchC64(uint8_t **sf, size_t *extent, C64Rec entry);
 
-uint8_t *getLargestFile(uint8_t *data, int length, int *newlength) {
-	return nullptr;
-}
-
-uint8_t *getFileNamed(uint8_t *data, int length, int *newlength, const char *name) {
-	return nullptr;
-}
-
-int savageIslandMenu(uint8_t **sf, size_t *extent, int recindex) {
-	return 0;
-}
-
 int mysteriousMenu(uint8_t **sf, size_t *extent, int recindex) {
 	return 0;
 }
@@ -162,63 +84,14 @@ int detectC64(uint8_t **sf, size_t *extent) {
 	if (*extent > MAX_LENGTH || *extent < MIN_LENGTH)
 		return 0;
 
-	uint16_t chksum = checksum(*sf, *extent);
-
-	for (int i = 0; g_C64Registry[i]._length != 0; i++) {
-		if (*extent == g_C64Registry[i]._length && chksum == g_C64Registry[i]._chk) {
-			if (g_C64Registry[i]._id == SAVAGE_ISLAND_C64) {
-				return savageIslandMenu(sf, extent, i);
-			} else if (g_C64Registry[i]._id == BATON_C64 && (chksum == 0xc3fc || chksum == 0xbfbf)) {
-				return mysteriousMenu(sf, extent, i);
-			} else if (g_C64Registry[i]._id == FEASIBILITY_C64 && (chksum == 0x9eaa || chksum == 0x9c18)) {
-				return mysteriousMenu2(sf, extent, i);
-			}
-			if (g_C64Registry[i]._type == TYPE_D64) {
-				int newlength;
-				uint8_t *largest_file = getLargestFile(*sf, *extent, &newlength);
-				uint8_t *appendix = nullptr;
-				int appendixlen = 0;
-
-				if (g_C64Registry[i]._appendFile != nullptr) {
-					appendix = getFileNamed(*sf, *extent, &appendixlen, g_C64Registry[i]._appendFile);
-					if (appendix == nullptr)
-						error("detectC64(): Appending file failed");
-					appendixlen -= 2;
-				}
-
-				uint8_t *megabuf = new uint8_t[newlength + appendixlen];
-				memcpy(megabuf, largest_file, newlength);
-				if (appendix != nullptr) {
-					memcpy(megabuf + newlength + g_C64Registry[i]._parameter, appendix + 2, appendixlen);
-					newlength += appendixlen;
-				}
-
-				if (largest_file) {
-					*sf = megabuf;
-					*extent = newlength;
-				}
-
-			} else if (g_C64Registry[i]._type == TYPE_T64) {
-				uint8_t *file_records = *sf + 64;
-				int number_of_records = READ_LE_UINT16(&(*sf)[36]);
-				int offset = READ_LE_UINT16(&file_records[8]);
-				int start_addr = READ_LE_UINT16(&file_records[2]);
-				int end_addr = READ_LE_UINT16(&file_records[4]);
-				int size;
-				if (number_of_records == 1)
-					size = *extent - offset;
-				else
-					size = end_addr - start_addr;
-				uint8_t *first_file = new uint8_t[size + 2];
-				memcpy(first_file + 2, *sf + offset, size);
-				memcpy(first_file, file_records + 2, 2);
-				*sf = first_file;
-				*extent = size + 2;
-			}
-			return decrunchC64(sf, extent, g_C64Registry[i]);
-		}
+	Common::String md5 = g_vm->getGameMD5();
+	int index = _G(_md5Index)[md5];
+	if (g_C64Registry[index]._id == BATON_C64) {
+		return mysteriousMenu(sf, extent, index);
+	} else if (g_C64Registry[index]._id == FEASIBILITY_C64) {
+		return mysteriousMenu2(sf, extent, index);
 	}
-	return 0;
+	return decrunchC64(sf, extent, g_C64Registry[index]);
 }
 
 int decrunchC64(uint8_t **sf, size_t *extent, C64Rec entry) {
diff --git a/engines/glk/scott/globals.cpp b/engines/glk/scott/globals.cpp
index 8de6499bae5..d7ebf7f3aea 100644
--- a/engines/glk/scott/globals.cpp
+++ b/engines/glk/scott/globals.cpp
@@ -77,6 +77,8 @@ Globals::Globals() : _sys(MAX_SYSMESS), _directions(NUMBER_OF_DIRECTIONS), _extr
 	_md5Index.setVal("afde056c152de79ea20453c42a2d08af", 18); // 10indians
 	_md5Index.setVal("6c6fbbbb50032463a6ea71c6750ea1f5", 20); // waxworks11
 	_md5Index.setVal("0eec511d3cde815c73e5464ab0cdbef9" ,22); // marveladventure
+	_md5Index.setVal("ce5a68cf43b2f29d99c0135b89f4fe31",  0); // misadv1
+	_md5Index.setVal("1e1ff48f80a8220f5ab9d14c975197b8",  6); // midadv2
 }
 
 Globals::~Globals() {


Commit: ba59cd4c1997ddec46ea772d09433db0ba434264
    https://github.com/scummvm/scummvm/commit/ba59cd4c1997ddec46ea772d09433db0ba434264
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Implement mysteriousMenu and mysteriousMenu2

Changed paths:
    engines/glk/scott/c64_checksums.cpp


diff --git a/engines/glk/scott/c64_checksums.cpp b/engines/glk/scott/c64_checksums.cpp
index 749fc20789f..6de5f0dde83 100644
--- a/engines/glk/scott/c64_checksums.cpp
+++ b/engines/glk/scott/c64_checksums.cpp
@@ -72,12 +72,140 @@ static C64Rec g_C64Registry[] = {
 
 int decrunchC64(uint8_t **sf, size_t *extent, C64Rec entry);
 
+uint8_t *getFileNamed(uint8_t* data, int length, int* newLength, const char* name) {
+	return nullptr;
+}
+
 int mysteriousMenu(uint8_t **sf, size_t *extent, int recindex) {
-	return 0;
+	recindex = 0;
+
+	g_scott->output("This disk image contains six games. Select one.\n\n"
+					"1. The Golden Baton\n"
+					"2. The Time Machine\n"
+					"3. Arrow of Death part 1\n"
+					"4. Arrow of Death part 2\n"
+					"5. Escape from Pulsar 7\n"
+					"6. Circus");
+
+	g_scott->glk_request_char_event(_G(_bottomWindow));
+
+	event_t ev;
+	int result = 0;
+	do {
+		g_scott->glk_select(&ev);
+		if (ev.type == evtype_CharInput) {
+			if (ev.val1 >= '1' && ev.val1 <= '6') {
+				result = ev.val1 - '0';
+			} else {
+				g_scott->glk_request_char_event(_G(_bottomWindow));
+			}
+		}
+	} while (result == 0);
+
+	g_scott->glk_window_clear(_G(_bottomWindow));
+
+	const char *filename = nullptr;
+	switch (result) {
+	case 1:
+		filename = "BATON";
+		break;
+	case 2:
+		filename = "TIME MACHINE";
+		break;
+	case 3:
+		filename = "ARROW I";
+		break;
+	case 4:
+		filename = "ARROW II";
+		break;
+	case 5:
+		filename = "PULSAR 7";
+		break;
+	case 6:
+		filename = "CIRCUS";
+		break;
+	default:
+		error("mysteriousMenu: Unknown Game");
+		break;
+	}
+
+	int length;
+	uint8_t *file = getFileNamed(*sf, *extent, &length, filename);
+
+	if (file != nullptr) {
+		delete[] * sf;
+		*sf = file;
+		*extent = length;
+		C64Rec rec = g_C64Registry[recindex - 1 + result];
+		return decrunchC64(sf, extent, rec);
+	} else {
+		error("mysteriousMenu: Failed loading file %s", filename);
+		return 0;
+	}
 }
 
 int mysteriousMenu2(uint8_t **sf, size_t *extent, int recindex) {
-	return 0;
+	recindex = 6;
+
+	g_scott->output("This disk image contains five games. Select one.\n\n"
+					"1. Feasibility Experiment\n"
+					"2. The Wizard of Akyrz\n"
+					"3. Perseus and Andromeda\n"
+					"4. Ten Little Indians\n"
+					"5. Waxworks");
+
+	g_scott->glk_request_char_event(_G(_bottomWindow));
+
+	event_t ev;
+	int result = 0;
+	do {
+		g_scott->glk_select(&ev);
+		if (ev.type == evtype_CharInput) {
+			if (ev.val1 >= '1' && ev.val1 <= '5') {
+				result = ev.val1 - '0';
+			} else {
+				g_scott->glk_request_char_event(_G(_bottomWindow));
+			}
+		}
+	} while (result == 0);
+
+	g_scott->glk_window_clear(_G(_bottomWindow));
+
+	const char *filename = nullptr;
+	switch (result) {
+	case 1:
+		filename = "EXPERIMENT";
+		break;
+	case 2:
+		filename = "WIZARD OF AKYRZ";
+		break;
+	case 3:
+		filename = "PERSEUS";
+		break;
+	case 4:
+		filename = "INDIANS";
+		break;
+	case 5:
+		filename = "WAXWORKS";
+		break;
+	default:
+		error("mysteriousMenu2: Unknown Game");
+		break;
+	}
+
+	int length;
+	uint8_t *file = getFileNamed(*sf, *extent, &length, filename);
+
+	if (file != nullptr) {
+		delete[] * sf;
+		*sf = file;
+		*extent = length;
+		C64Rec rec = g_C64Registry[recindex - 1 + result];
+		return decrunchC64(sf, extent, rec);
+	} else {
+		error("mysteriousMenu2: Failed loading file %s", filename);
+		return 0;
+	}
 }
 
 int detectC64(uint8_t **sf, size_t *extent) {


Commit: f453dd8c1b107f8105d6b167340f63816be66015
    https://github.com/scummvm/scummvm/commit/f453dd8c1b107f8105d6b167340f63816be66015
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Add disk_image.h/cpp

Changed paths:
  A engines/glk/scott/disk_image.cpp
  A engines/glk/scott/disk_image.h
    engines/glk/module.mk


diff --git a/engines/glk/module.mk b/engines/glk/module.mk
index edf9e59b54a..2f7054c5b87 100644
--- a/engines/glk/module.mk
+++ b/engines/glk/module.mk
@@ -239,6 +239,7 @@ MODULE_OBJS := \
 	scott/decompress_text.o \
 	scott/decompress_z80.o \
 	scott/definitions.o \
+	scott/disk_image.o \
 	scott/load_game.o \
 	scott/game_info.o \
 	scott/game_specific.o \
diff --git a/engines/glk/scott/disk_image.cpp b/engines/glk/scott/disk_image.cpp
new file mode 100644
index 00000000000..0e3accfc253
--- /dev/null
+++ b/engines/glk/scott/disk_image.cpp
@@ -0,0 +1,45 @@
+/* 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 "common/scummsys.h"
+#include "glk/scott/disk_image.h"
+
+namespace Glk {
+namespace Scott {
+
+ImageFile *diOpen(DiskImage *di, byte *rawname, byte type, const char *mode) {
+	return nullptr;
+}
+
+int diRead(ImageFile *imgfile, byte *buffer, int len) {
+	return 0;
+}
+
+int diRawnameFromName(byte *rawname, const char *name) {
+	return 0;
+}
+
+DiskImage *diCreateFromData(uint8_t *data, int length) {
+	return nullptr;
+}
+
+} // End of namespace Scott
+} // End of namespace Glk
diff --git a/engines/glk/scott/disk_image.h b/engines/glk/scott/disk_image.h
new file mode 100644
index 00000000000..dbe9f205cf4
--- /dev/null
+++ b/engines/glk/scott/disk_image.h
@@ -0,0 +1,105 @@
+/* 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 GLK_SCOTT_DISKIMAGE_H
+#define GLK_SCOTT_DISKIMAGE_H
+
+#include "common/scummsys.h"
+#include "glk/scott/types.h"
+
+namespace Glk {
+namespace Scott {
+
+// constants for the supported disk formats
+#define MAXTRACKS 80
+#define MAXSECTORS 40
+#define D64SIZE 174848
+#define D64ERRSIZE 175531
+#define D71SIZE 349696
+#define D71ERRSIZE 351062
+#define D81SIZE 819200
+#define D81ERRSIZE 822400
+
+enum ImageType {
+	D64 = 1,
+	D71,
+	D81
+};
+
+struct TrackSector {
+	byte _track;
+	byte _sector;
+};
+
+struct DiskImage {
+	char *_filename;
+	int _size;
+	ImageType _type;
+	byte *_image;
+	byte *_errinfo;
+	TrackSector _bam;
+	TrackSector _bam2;
+	TrackSector _dir;
+	int _openfiles;
+	int _blocksfree;
+	int _modified;
+	int _status;
+	int _interleave;
+	TrackSector _statusts;
+};
+
+struct RawDirEntry {
+	TrackSector _nextts;
+	byte _type;
+	TrackSector _startts;
+	byte _rawname[16];
+	TrackSector _relsidets;
+	byte _relrecsize;
+	byte _unused[4];
+	TrackSector _replacetemp;
+	byte _sizelo;
+	byte _sizehi;
+};
+
+struct ImageFile {
+	DiskImage *_diskimage;
+	RawDirEntry *_rawdirentry;
+	char _mode;
+	int _position;
+	TrackSector _ts;
+	TrackSector _nextts;
+	byte *_buffer;
+	int _bufptr;
+	int _buflen;
+	byte _visited[MAXTRACKS][MAXSECTORS];
+};
+
+ImageFile *diOpen(DiskImage *di, byte *rawname, byte type, const char *mode);
+int diRead(ImageFile *imgfile, byte *buffer, int len);
+
+int diRawnameFromName(byte *rawname, const char *name);
+
+DiskImage *diCreateFromData(uint8_t *data, int length);
+
+} // End of namespace Scott
+} // End of namespace Glk
+
+#endif


Commit: dfec9279e1a2ce4f2255282f2edc164f3648fa54
    https://github.com/scummvm/scummvm/commit/dfec9279e1a2ce4f2255282f2edc164f3648fa54
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Implement getFileNamed

Changed paths:
    engines/glk/scott/c64_checksums.cpp


diff --git a/engines/glk/scott/c64_checksums.cpp b/engines/glk/scott/c64_checksums.cpp
index 6de5f0dde83..7490c13a8bd 100644
--- a/engines/glk/scott/c64_checksums.cpp
+++ b/engines/glk/scott/c64_checksums.cpp
@@ -20,10 +20,12 @@
  */
 
 #include "common/str.h"
+#include "common/scummsys.h"
 #include "glk/scott/scott.h"
 #include "glk/scott/globals.h"
 #include "glk/scott/c64_checksums.h"
 #include "glk/scott/definitions.h"
+#include "glk/scott/disk_image.h"
 
 namespace Glk {
 namespace Scott {
@@ -73,7 +75,22 @@ static C64Rec g_C64Registry[] = {
 int decrunchC64(uint8_t **sf, size_t *extent, C64Rec entry);
 
 uint8_t *getFileNamed(uint8_t* data, int length, int* newLength, const char* name) {
-	return nullptr;
+	uint8_t *file = nullptr;
+	*newLength = 0;
+	DiskImage *d64 = diCreateFromData(data, length);
+	byte rawname[100];
+	diRawnameFromName(rawname, name);
+	if (d64) {
+		ImageFile *c64file = diOpen(d64, rawname, 0xC2, "rb");
+		if (c64file) {
+			uint8_t *buf = new uint8_t[0xffff];
+			*newLength = diRead(c64file, buf, 0xffff);
+			file = new uint8_t[*newLength];
+			memcpy(file, buf, *newLength);
+			delete[] buf;
+		}
+	}
+	return file;
 }
 
 int mysteriousMenu(uint8_t **sf, size_t *extent, int recindex) {


Commit: 17939767f269db5e8fcd8a6b8d3bab436b7041ab
    https://github.com/scummvm/scummvm/commit/17939767f269db5e8fcd8a6b8d3bab436b7041ab
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Implement diOpen

Changed paths:
    engines/glk/scott/disk_image.cpp
    engines/glk/scott/disk_image.h


diff --git a/engines/glk/scott/disk_image.cpp b/engines/glk/scott/disk_image.cpp
index 0e3accfc253..d9d362b3851 100644
--- a/engines/glk/scott/disk_image.cpp
+++ b/engines/glk/scott/disk_image.cpp
@@ -20,19 +20,143 @@
  */
 
 #include "common/scummsys.h"
+#include "common/str.h"
 #include "glk/scott/disk_image.h"
 
 namespace Glk {
 namespace Scott {
 
-ImageFile *diOpen(DiskImage *di, byte *rawname, byte type, const char *mode) {
+int setStatus(DiskImage* di, int status, int track, int sector) {
+	return 0;
+}
+
+/* check if given track/sector is within valid range */
+int diTsIsValid(ImageType type, TrackSector ts) {
+	return 0;
+}
+
+RawDirEntry *findFileEntry(DiskImage *di, byte *rawPattern, int type) {
+	return nullptr;
+}
+
+RawDirEntry *allocFileEntry(DiskImage* di, byte* rawName, int type) {
 	return nullptr;
 }
 
-int diRead(ImageFile *imgfile, byte *buffer, int len) {
+ImageFile *diOpen(DiskImage *di, byte *rawname, byte type, const char *mode) {
+	ImageFile *imgFile;
+	RawDirEntry *rde;
+	byte *p;
+
+	setStatus(di, 255, 0, 0);
+
+	if (scumm_stricmp("rb", mode) == 0) {
+
+		if ((imgFile = new ImageFile) == nullptr) {
+			return nullptr;
+		}
+
+		memset(imgFile->_visited, 0, sizeof(imgFile->_visited));
+
+		if (scumm_stricmp("$", (char *)rawname) == 0) {
+			imgFile->_mode = 'r';
+
+			imgFile->_ts = di->_dir;
+
+			p = diGetTsAddr(di, di->_dir);
+			imgFile->_buffer = p + 2;
+
+			imgFile->_nextts = diGetDirTs(di);
+
+			imgFile->_buflen = 254;
+
+			if (!diTsIsValid(di->_type, imgFile->_nextts)) {
+				setStatus(di, 66, imgFile->_nextts._track, imgFile->_nextts._sector);
+				delete imgFile;
+				return nullptr;
+			}
+			rde = nullptr;
+
+		} else {
+			if ((rde = findFileEntry(di, rawname, type)) == nullptr) {
+				setStatus(di, 62, 0, 0);
+				delete imgFile;
+				return nullptr;
+			}
+			imgFile->_mode = 'r';
+			imgFile->_ts = rde->_startts;
+
+			if (!diTsIsValid(di->_type, imgFile->_ts)) {
+				setStatus(di, 66, imgFile->_ts._track, imgFile->_ts._sector);
+				delete imgFile;
+				return nullptr;
+			}
+
+			p = diGetTsAddr(di, rde->_startts);
+			imgFile->_buffer = p + 2;
+			imgFile->_nextts._track = p[0];
+			imgFile->_nextts._sector = p[1];
+
+			if (imgFile->_nextts._track == 0) {
+				if (imgFile->_nextts._sector != 0) {
+					imgFile->_buflen = imgFile->_nextts._sector - 1;
+				} else {
+					imgFile->_buflen = 254;
+				}
+			} else {
+				if (!diTsIsValid(di->_type, imgFile->_nextts)) {
+					setStatus(di, 66, imgFile->_nextts._track, imgFile->_nextts._sector);
+					delete imgFile;
+					return nullptr;
+				}
+				imgFile->_buflen = 254;
+			}
+		}
+
+	} else if (strcmp("wb", mode) == 0) {
+
+		if ((rde = allocFileEntry(di, rawname, type)) == nullptr) {
+			return nullptr;
+		}
+		if ((imgFile = new ImageFile) == nullptr) {
+			return nullptr;
+		}
+		imgFile->_mode = 'w';
+		imgFile->_ts._track = 0;
+		imgFile->_ts._sector = 0;
+		if ((imgFile->_buffer = new byte[254]) == nullptr) {
+			delete imgFile;
+			return nullptr;
+		}
+		imgFile->_buflen = 254;
+		di->_modified = 1;
+
+	} else {
+		return nullptr;
+	}
+
+	imgFile->_diskimage = di;
+	imgFile->_rawdirentry = rde;
+	imgFile->_position = 0;
+	imgFile->_bufptr = 0;
+
+	++(di->_openfiles);
+	setStatus(di, 0, 0, 0);
+	return imgFile;
+}
+
+int diRead(ImageFile *imgFile, byte *buffer, int len) {
 	return 0;
 }
 
+byte *diGetTsAddr(DiskImage *di, TrackSector ts) {
+	return nullptr;
+}
+
+TrackSector diGetDirTs(DiskImage *di) {
+	return TrackSector();
+}
+
 int diRawnameFromName(byte *rawname, const char *name) {
 	return 0;
 }
diff --git a/engines/glk/scott/disk_image.h b/engines/glk/scott/disk_image.h
index dbe9f205cf4..b83981f1dfc 100644
--- a/engines/glk/scott/disk_image.h
+++ b/engines/glk/scott/disk_image.h
@@ -95,6 +95,10 @@ struct ImageFile {
 ImageFile *diOpen(DiskImage *di, byte *rawname, byte type, const char *mode);
 int diRead(ImageFile *imgfile, byte *buffer, int len);
 
+byte *diGetTsAddr(DiskImage *di, TrackSector ts);
+
+TrackSector diGetDirTs(DiskImage *di);
+
 int diRawnameFromName(byte *rawname, const char *name);
 
 DiskImage *diCreateFromData(uint8_t *data, int length);


Commit: 5c3cd93aa9d6e1c093cbb94792d0096c11e848db
    https://github.com/scummvm/scummvm/commit/5c3cd93aa9d6e1c093cbb94792d0096c11e848db
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Implement diRead

Changed paths:
    engines/glk/scott/disk_image.cpp
    engines/glk/scott/disk_image.h


diff --git a/engines/glk/scott/disk_image.cpp b/engines/glk/scott/disk_image.cpp
index d9d362b3851..7f809ab1ff2 100644
--- a/engines/glk/scott/disk_image.cpp
+++ b/engines/glk/scott/disk_image.cpp
@@ -145,14 +145,105 @@ ImageFile *diOpen(DiskImage *di, byte *rawname, byte type, const char *mode) {
 	return imgFile;
 }
 
+TrackSector nextTsInChain(DiskImage* di, TrackSector ts) {
+	return TrackSector();
+}
+
 int diRead(ImageFile *imgFile, byte *buffer, int len) {
-	return 0;
+	byte *p;
+	int bytesLeft;
+	int counter = 0;
+	int err;
+
+	while (len) {
+		bytesLeft = imgFile->_buflen - imgFile->_bufptr;
+
+		err = diGetTsErr(imgFile->_diskimage, imgFile->_ts);
+		if (err) {
+			setStatus(imgFile->_diskimage, err, imgFile->_ts._track, imgFile->_ts._sector);
+			return counter;
+		}
+
+		if (bytesLeft == 0) {
+			if (imgFile->_nextts._track == 0) {
+				return counter;
+			}
+			if (((imgFile->_diskimage->_type == D64) || (imgFile->_diskimage->_type == D71)) && imgFile->_ts._track == 18 && imgFile->_ts._sector == 0) {
+				imgFile->_ts._track = 18;
+				imgFile->_ts._sector = 1;
+			} else {
+				imgFile->_ts = nextTsInChain(imgFile->_diskimage, imgFile->_ts);
+			}
+			if (imgFile->_ts._track == 0) {
+				return counter;
+			}
+
+			/* check for cyclic files */
+			if (imgFile->_visited[imgFile->_ts._track][imgFile->_ts._sector]) {
+				/* return 52, file too long error */
+				setStatus(imgFile->_diskimage, 52, imgFile->_ts._track, imgFile->_ts._sector);
+			} else {
+				imgFile->_visited[imgFile->_ts._track][imgFile->_ts._sector] = 1;
+			}
+
+			err = diGetTsErr(imgFile->_diskimage, imgFile->_ts);
+			if (err) {
+				setStatus(imgFile->_diskimage, err, imgFile->_ts._track, imgFile->_ts._sector);
+				return counter;
+			}
+
+			p = diGetTsAddr(imgFile->_diskimage, imgFile->_ts);
+			imgFile->_buffer = p + 2;
+			imgFile->_nextts._track = p[0];
+			imgFile->_nextts._sector = p[1];
+
+			if (imgFile->_nextts._track == 0) {
+				if (imgFile->_nextts._sector == 0) {
+					/* fixme, something is wrong if this happens, should be a proper error */
+					imgFile->_buflen = 0;
+					setStatus(imgFile->_diskimage, -1, imgFile->_ts._track, imgFile->_ts._sector);
+				} else {
+					imgFile->_buflen = imgFile->_nextts._sector - 1;
+				}
+			} else {
+				if (!diTsIsValid(imgFile->_diskimage->_type, imgFile->_nextts)) {
+					setStatus(imgFile->_diskimage, 66, imgFile->_nextts._track, imgFile->_nextts._sector);
+					return counter;
+				}
+				imgFile->_buflen = 254;
+			}
+			imgFile->_bufptr = 0;
+		} else {
+			if (len >= bytesLeft) {
+				while (bytesLeft) {
+					*buffer++ = imgFile->_buffer[imgFile->_bufptr++];
+					--len;
+					--bytesLeft;
+					++counter;
+					++(imgFile->_position);
+				}
+			} else {
+				while (len) {
+					*buffer++ = imgFile->_buffer[imgFile->_bufptr++];
+					--len;
+					--bytesLeft;
+					++counter;
+					++(imgFile->_position);
+				}
+			}
+		}
+	}
+	return counter;
 }
 
 byte *diGetTsAddr(DiskImage *di, TrackSector ts) {
 	return nullptr;
 }
 
+int diGetTsErr(DiskImage *di, TrackSector ts) {
+	return 0;
+}
+
 TrackSector diGetDirTs(DiskImage *di) {
 	return TrackSector();
 }
diff --git a/engines/glk/scott/disk_image.h b/engines/glk/scott/disk_image.h
index b83981f1dfc..e0350fef4a3 100644
--- a/engines/glk/scott/disk_image.h
+++ b/engines/glk/scott/disk_image.h
@@ -96,6 +96,7 @@ ImageFile *diOpen(DiskImage *di, byte *rawname, byte type, const char *mode);
 int diRead(ImageFile *imgfile, byte *buffer, int len);
 
 byte *diGetTsAddr(DiskImage *di, TrackSector ts);
+int diGetTsErr(DiskImage *di, TrackSector ts);
 
 TrackSector diGetDirTs(DiskImage *di);
 


Commit: 5682465f1143c68deb31605ca28d831f68fb61f4
    https://github.com/scummvm/scummvm/commit/5682465f1143c68deb31605ca28d831f68fb61f4
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Implement diGetTsAddr

Changed paths:
    engines/glk/scott/disk_image.cpp
    engines/glk/scott/disk_image.h


diff --git a/engines/glk/scott/disk_image.cpp b/engines/glk/scott/disk_image.cpp
index 7f809ab1ff2..b873b75bd61 100644
--- a/engines/glk/scott/disk_image.cpp
+++ b/engines/glk/scott/disk_image.cpp
@@ -236,14 +236,19 @@ int diRead(ImageFile *imgFile, byte *buffer, int len) {
 	return counter;
 }
 
+// get a pointer to block data 
 byte *diGetTsAddr(DiskImage *di, TrackSector ts) {
-	return nullptr;
+	return di->_image + diGetBlockNum(di->_type, ts) * 256;
 }
 
 int diGetTsErr(DiskImage *di, TrackSector ts) {
 	return 0;
 }
 
+int diGetBlockNum(ImageType type, TrackSector ts) {
+	return 0;
+}
+
 TrackSector diGetDirTs(DiskImage *di) {
 	return TrackSector();
 }
diff --git a/engines/glk/scott/disk_image.h b/engines/glk/scott/disk_image.h
index e0350fef4a3..89619478d00 100644
--- a/engines/glk/scott/disk_image.h
+++ b/engines/glk/scott/disk_image.h
@@ -98,6 +98,8 @@ int diRead(ImageFile *imgfile, byte *buffer, int len);
 byte *diGetTsAddr(DiskImage *di, TrackSector ts);
 int diGetTsErr(DiskImage *di, TrackSector ts);
 
+int diGetBlockNum(ImageType type, TrackSector ts);
+
 TrackSector diGetDirTs(DiskImage *di);
 
 int diRawnameFromName(byte *rawname, const char *name);


Commit: b808b769b2ec89f2f0d9b1556abacd12096f9a0d
    https://github.com/scummvm/scummvm/commit/b808b769b2ec89f2f0d9b1556abacd12096f9a0d
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Implement diGetTsErr

Changed paths:
    engines/glk/scott/disk_image.cpp


diff --git a/engines/glk/scott/disk_image.cpp b/engines/glk/scott/disk_image.cpp
index b873b75bd61..bae9492e4ea 100644
--- a/engines/glk/scott/disk_image.cpp
+++ b/engines/glk/scott/disk_image.cpp
@@ -26,6 +26,32 @@
 namespace Glk {
 namespace Scott {
 
+/* dos errors as used by the DOS internally (and as saves in the error info) */
+struct DosError {
+	signed int _number; /* dos error number */
+	signed int _errnum; /* reported error number */
+	const char *_string;      /* description */
+};
+
+DosError g_dosError[] = {
+	/* non-errors */
+	{0x01, 0, "ok"},
+	/* errors */
+	{0x02, 20, "Header descriptor byte not found (Seek)"},
+	/*  { 0x02, 20, "Header block not found (Seek)" }, */
+	{0x03, 21, "No SYNC sequence found (Seek)"},
+	{0x04, 22, "Data descriptor byte not found (Read)"},
+	{0x05, 23, "Checksum error in data block (Read)"},
+	{0x06, 24, "Write verify (Write)"},
+	{0x07, 25, "Write verify error (Write)"},
+	{0x08, 26, "Write protect on (Write)"},
+	{0x09, 27, "Checksum error in header block (Seek)"},
+	{0x0A, 28, "Write error (Write)"},
+	{0x0B, 29, "Disk sector ID mismatch (Seek)"},
+	{0x0F, 74, "Drive Not Ready (Read)"},
+	{-1, -1, nullptr}
+};
+
 int setStatus(DiskImage* di, int status, int track, int sector) {
 	return 0;
 }
@@ -241,10 +267,25 @@ byte *diGetTsAddr(DiskImage *di, TrackSector ts) {
 	return di->_image + diGetBlockNum(di->_type, ts) * 256;
 }
 
-int diGetTsErr(DiskImage *di, TrackSector ts) {
+/* get error info for a sector */
+int getTsDosErr(DiskImage* di, TrackSector ts) {
 	return 0;
 }
 
+int diGetTsErr(DiskImage *di, TrackSector ts) {
+	int errnum;
+	DosError *err = g_dosError;
+
+	errnum = getTsDosErr(di, ts);
+	while (err->_number >= 0) {
+		if (errnum == err->_number) {
+			return err->_errnum;
+		}
+		++err;
+	}
+	return -1; /* unknown error */
+}
+
 int diGetBlockNum(ImageType type, TrackSector ts) {
 	return 0;
 }


Commit: 03def012091b9bc68c14ae20d71ec71f62da8513
    https://github.com/scummvm/scummvm/commit/03def012091b9bc68c14ae20d71ec71f62da8513
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Implement diGetBlockNum

Changed paths:
    engines/glk/scott/disk_image.cpp


diff --git a/engines/glk/scott/disk_image.cpp b/engines/glk/scott/disk_image.cpp
index bae9492e4ea..0021852fcbe 100644
--- a/engines/glk/scott/disk_image.cpp
+++ b/engines/glk/scott/disk_image.cpp
@@ -21,6 +21,7 @@
 
 #include "common/scummsys.h"
 #include "common/str.h"
+#include "common/textconsole.h"
 #include "glk/scott/disk_image.h"
 
 namespace Glk {
@@ -287,6 +288,48 @@ int diGetTsErr(DiskImage *di, TrackSector ts) {
 }
 
 int diGetBlockNum(ImageType type, TrackSector ts) {
+	int block;
+
+	/* assertion, should never happen (indicates bad error handling elsewhere) */
+	if (!diTsIsValid(type, ts)) {
+		error("diGetBlockNum: internal error, track/sector out of range");
+	}
+
+	switch (type) {
+	case D64:
+		if (ts._track < 18) {
+			block = (ts._track - 1) * 21;
+		} else if (ts._track < 25) {
+			block = (ts._track - 18) * 19 + 17 * 21;
+		} else if (ts._track < 31) {
+			block = (ts._track - 25) * 18 + 17 * 21 + 7 * 19;
+		} else {
+			block = (ts._track - 31) * 17 + 17 * 21 + 7 * 19 + 6 * 18;
+		}
+		return block + ts._sector;
+		break;
+	case D71:
+		if (ts._track > 35) {
+			block = 683;
+			ts._track -= 35;
+		} else {
+			block = 0;
+		}
+		if (ts._track < 18) {
+			block += (ts._track - 1) * 21;
+		} else if (ts._track < 25) {
+			block += (ts._track - 18) * 19 + 17 * 21;
+		} else if (ts._track < 31) {
+			block += (ts._track - 25) * 18 + 17 * 21 + 7 * 19;
+		} else {
+			block += (ts._track - 31) * 17 + 17 * 21 + 7 * 19 + 6 * 18;
+		}
+		return block + ts._sector;
+		break;
+	case D81:
+		return (ts._track - 1) * 40 + ts._sector;
+		break;
+	}
 	return 0;
 }
 


Commit: 25201be1f80385239737132450414e314427eb57
    https://github.com/scummvm/scummvm/commit/25201be1f80385239737132450414e314427eb57
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Implement diGetDirTs

Changed paths:
    engines/glk/scott/disk_image.cpp


diff --git a/engines/glk/scott/disk_image.cpp b/engines/glk/scott/disk_image.cpp
index 0021852fcbe..c66fb81f6f4 100644
--- a/engines/glk/scott/disk_image.cpp
+++ b/engines/glk/scott/disk_image.cpp
@@ -333,8 +333,21 @@ int diGetBlockNum(ImageType type, TrackSector ts) {
 	return 0;
 }
 
+/* return t/s of first directory sector */
 TrackSector diGetDirTs(DiskImage *di) {
-	return TrackSector();
+	TrackSector newTs;
+	byte *p;
+
+	p = diGetTsAddr(di, di->_dir);
+	if ((di->_type == D64) || (di->_type == D71)) {
+		newTs._track = 18; /* 1541/71 ignores bam t/s link */
+		newTs._sector = 1;
+	} else {
+		newTs._track = p[0];
+		newTs._sector = p[1];
+	}
+
+	return newTs;
 }
 
 int diRawnameFromName(byte *rawname, const char *name) {


Commit: e739547bca2ae6dddd281495858256c28b369562
    https://github.com/scummvm/scummvm/commit/e739547bca2ae6dddd281495858256c28b369562
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Implement diRawnameFromName

Changed paths:
    engines/glk/scott/disk_image.cpp


diff --git a/engines/glk/scott/disk_image.cpp b/engines/glk/scott/disk_image.cpp
index c66fb81f6f4..9a6ee5f6c1b 100644
--- a/engines/glk/scott/disk_image.cpp
+++ b/engines/glk/scott/disk_image.cpp
@@ -350,8 +350,14 @@ TrackSector diGetDirTs(DiskImage *di) {
 	return newTs;
 }
 
+/* convert to rawname */
 int diRawnameFromName(byte *rawname, const char *name) {
-	return 0;
+	int i;
+
+	memset(rawname, 0xa0, 16);
+	for (i = 0; i < 16 && name[i]; ++i)
+		rawname[i] = name[i];
+	return i;
 }
 
 DiskImage *diCreateFromData(uint8_t *data, int length) {


Commit: 2855ea2e372d5cba8152550fcb622b08b0daa54b
    https://github.com/scummvm/scummvm/commit/2855ea2e372d5cba8152550fcb622b08b0daa54b
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Implement diCreateFromData

Changed paths:
    engines/glk/scott/disk_image.cpp


diff --git a/engines/glk/scott/disk_image.cpp b/engines/glk/scott/disk_image.cpp
index 9a6ee5f6c1b..dea8c9dbbf4 100644
--- a/engines/glk/scott/disk_image.cpp
+++ b/engines/glk/scott/disk_image.cpp
@@ -360,8 +360,82 @@ int diRawnameFromName(byte *rawname, const char *name) {
 	return i;
 }
 
+/* count number of free blocks */
+int blocksFree(DiskImage* di) {
+	return 0;
+}
+
+/* return write interleave */
+int interleave(ImageType type) {
+	return 0;
+}
+
 DiskImage *diCreateFromData(uint8_t *data, int length) {
-	return nullptr;
+	DiskImage *di;
+
+	if ((di = new DiskImage) == nullptr) {
+		return nullptr;
+	}
+
+	di->_size = length;
+
+	/* allocate buffer for image */
+	if ((di->_image = new byte[length]) == nullptr) {
+		delete di;
+		return nullptr;
+	}
+
+	di->_image = data;
+
+	di->_errinfo = nullptr;
+
+	/* check image type */
+	switch (length) {
+	case D64ERRSIZE: /* D64 with error info */
+		// di->_errinfo = &(di->_error_);
+	case D64SIZE: /* standard D64 */
+		di->_type = D64;
+		di->_bam._track = 18;
+		di->_bam._sector = 0;
+		di->_dir = di->_bam;
+		break;
+
+	case D71ERRSIZE: /* D71 with error info */
+		di->_errinfo = &(di->_image[D71SIZE]);
+	case D71SIZE:
+		di->_type = D71;
+		di->_bam._track = 18;
+		di->_bam._sector = 0;
+		di->_bam2._track = 53;
+		di->_bam2._sector = 0;
+		di->_dir = di->_bam;
+		break;
+
+	case D81ERRSIZE: /* D81 with error info */
+		di->_errinfo = &(di->_image[D81SIZE]);
+	case D81SIZE:
+		di->_type = D81;
+		di->_bam._track = 40;
+		di->_bam._sector = 1;
+		di->_bam2._track = 40;
+		di->_bam2._sector = 2;
+		di->_dir._track = 40;
+		di->_dir._sector = 0;
+		break;
+
+	default:
+		delete[] di->_image;
+		delete di;
+		return nullptr;
+	}
+
+	di->_filename = nullptr;
+	di->_openfiles = 0;
+	di->_blocksfree = blocksFree(di);
+	di->_modified = 0;
+	di->_interleave = interleave(di->_type);
+	setStatus(di, 254, 0, 0);
+	return di;
 }
 
 } // End of namespace Scott


Commit: 14afa5f90f771ecd6d92b57ab7c2dc637d7fb930
    https://github.com/scummvm/scummvm/commit/14afa5f90f771ecd6d92b57ab7c2dc637d7fb930
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Implement setStatus

Changed paths:
    engines/glk/scott/disk_image.cpp


diff --git a/engines/glk/scott/disk_image.cpp b/engines/glk/scott/disk_image.cpp
index dea8c9dbbf4..626ae4389af 100644
--- a/engines/glk/scott/disk_image.cpp
+++ b/engines/glk/scott/disk_image.cpp
@@ -54,7 +54,10 @@ DosError g_dosError[] = {
 };
 
 int setStatus(DiskImage* di, int status, int track, int sector) {
-	return 0;
+	di->_status = status;
+	di->_statusts._track = track;
+	di->_statusts._sector = sector;
+	return status;
 }
 
 /* check if given track/sector is within valid range */


Commit: 1f333dc3c7e986473602b15ba4d6a01417bdea3c
    https://github.com/scummvm/scummvm/commit/1f333dc3c7e986473602b15ba4d6a01417bdea3c
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Implement diTsIsValid

Changed paths:
    engines/glk/scott/disk_image.cpp
    engines/glk/scott/disk_image.h


diff --git a/engines/glk/scott/disk_image.cpp b/engines/glk/scott/disk_image.cpp
index 626ae4389af..c9695f80c06 100644
--- a/engines/glk/scott/disk_image.cpp
+++ b/engines/glk/scott/disk_image.cpp
@@ -62,7 +62,13 @@ int setStatus(DiskImage* di, int status, int track, int sector) {
 
 /* check if given track/sector is within valid range */
 int diTsIsValid(ImageType type, TrackSector ts) {
-	return 0;
+	if ((ts._track < 1) || (ts._track > diTracks(type))) {
+		return 0; /* track out of range */
+	}
+	if (ts._sector > (diSectorsPerTrack(type, ts._track) - 1)) {
+		return 0; /* sector out of range */
+	}
+	return 1;
 }
 
 RawDirEntry *findFileEntry(DiskImage *di, byte *rawPattern, int type) {
@@ -290,6 +296,14 @@ int diGetTsErr(DiskImage *di, TrackSector ts) {
 	return -1; /* unknown error */
 }
 
+int diSectorsPerTrack(ImageType type, int track) {
+	return 0;
+}
+
+int diTracks(ImageType type) {
+	return 0;
+}
+
 int diGetBlockNum(ImageType type, TrackSector ts) {
 	int block;
 
diff --git a/engines/glk/scott/disk_image.h b/engines/glk/scott/disk_image.h
index 89619478d00..30c2a8df9e9 100644
--- a/engines/glk/scott/disk_image.h
+++ b/engines/glk/scott/disk_image.h
@@ -98,6 +98,8 @@ int diRead(ImageFile *imgfile, byte *buffer, int len);
 byte *diGetTsAddr(DiskImage *di, TrackSector ts);
 int diGetTsErr(DiskImage *di, TrackSector ts);
 
+int diSectorsPerTrack(ImageType type, int track);
+int diTracks(ImageType type);
 int diGetBlockNum(ImageType type, TrackSector ts);
 
 TrackSector diGetDirTs(DiskImage *di);


Commit: 25827d6a8c1ea40cd22bd9d46827bb90a00a9dfc
    https://github.com/scummvm/scummvm/commit/25827d6a8c1ea40cd22bd9d46827bb90a00a9dfc
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Implement diSectorsPerTrack

Changed paths:
    engines/glk/scott/disk_image.cpp


diff --git a/engines/glk/scott/disk_image.cpp b/engines/glk/scott/disk_image.cpp
index c9695f80c06..3c313d58669 100644
--- a/engines/glk/scott/disk_image.cpp
+++ b/engines/glk/scott/disk_image.cpp
@@ -296,7 +296,29 @@ int diGetTsErr(DiskImage *di, TrackSector ts) {
 	return -1; /* unknown error */
 }
 
+/* return disk geometry for track */
 int diSectorsPerTrack(ImageType type, int track) {
+	switch (type) {
+	case D71:
+		if (track > 35) {
+			track -= 35;
+		}
+		/* fall through */
+	case D64:
+		if (track < 18) {
+			return 21;
+		} else if (track < 25) {
+			return 19;
+		} else if (track < 31) {
+			return 18;
+		} else {
+			return 17;
+		}
+		break;
+	case D81:
+		return 40;
+		break;
+	}
 	return 0;
 }
 


Commit: fd1bb95cea90dbc0f5d0daa9d3cfcb527cd68a45
    https://github.com/scummvm/scummvm/commit/fd1bb95cea90dbc0f5d0daa9d3cfcb527cd68a45
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Implement diTracks

Changed paths:
    engines/glk/scott/disk_image.cpp


diff --git a/engines/glk/scott/disk_image.cpp b/engines/glk/scott/disk_image.cpp
index 3c313d58669..94fee376275 100644
--- a/engines/glk/scott/disk_image.cpp
+++ b/engines/glk/scott/disk_image.cpp
@@ -322,7 +322,19 @@ int diSectorsPerTrack(ImageType type, int track) {
 	return 0;
 }
 
+/* return number of tracks for image type */
 int diTracks(ImageType type) {
+	switch (type) {
+	case D64:
+		return 35;
+		break;
+	case D71:
+		return 70;
+		break;
+	case D81:
+		return 80;
+		break;
+	}
 	return 0;
 }
 


Commit: bca64c76bfd812af64bf0339467e6da47f92535a
    https://github.com/scummvm/scummvm/commit/bca64c76bfd812af64bf0339467e6da47f92535a
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Implement findFileEntry

Changed paths:
    engines/glk/scott/disk_image.cpp


diff --git a/engines/glk/scott/disk_image.cpp b/engines/glk/scott/disk_image.cpp
index 94fee376275..ba68880c700 100644
--- a/engines/glk/scott/disk_image.cpp
+++ b/engines/glk/scott/disk_image.cpp
@@ -71,7 +71,33 @@ int diTsIsValid(ImageType type, TrackSector ts) {
 	return 1;
 }
 
+int matchPattern(byte *rawPattern, byte *rawname) {
+	return 0;
+}
+
+TrackSector nextTsInChain(DiskImage *di, TrackSector ts) {
+	return TrackSector();
+}
+
 RawDirEntry *findFileEntry(DiskImage *di, byte *rawPattern, int type) {
+	byte *buffer;
+	TrackSector ts;
+	RawDirEntry *rde;
+	int offset;
+
+	ts = diGetDirTs(di);
+
+	while (ts._track) {
+		buffer = diGetTsAddr(di, ts);
+		for (offset = 0; offset < 256; offset += 32) {
+			rde = (RawDirEntry *)(buffer + offset);
+			if (matchPattern(rawPattern, rde->_rawname)) {
+				return rde;
+			}
+		}
+		/* todo: add sanity checking */
+		ts = nextTsInChain(di, ts);
+	}
 	return nullptr;
 }
 
@@ -181,10 +207,6 @@ ImageFile *diOpen(DiskImage *di, byte *rawname, byte type, const char *mode) {
 	return imgFile;
 }
 
-TrackSector nextTsInChain(DiskImage* di, TrackSector ts) {
-	return TrackSector();
-}
-
 int diRead(ImageFile *imgFile, byte *buffer, int len) {
 	byte *p;
 	int bytesLeft;


Commit: c4fbd8f283bfa645556275dd97c35486016acf53
    https://github.com/scummvm/scummvm/commit/c4fbd8f283bfa645556275dd97c35486016acf53
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Implement matchPattern

Changed paths:
    engines/glk/scott/disk_image.cpp


diff --git a/engines/glk/scott/disk_image.cpp b/engines/glk/scott/disk_image.cpp
index ba68880c700..67b45b24686 100644
--- a/engines/glk/scott/disk_image.cpp
+++ b/engines/glk/scott/disk_image.cpp
@@ -72,7 +72,26 @@ int diTsIsValid(ImageType type, TrackSector ts) {
 }
 
 int matchPattern(byte *rawPattern, byte *rawname) {
-	return 0;
+	int i;
+
+	for (i = 0; i < 16; ++i) {
+		if (rawPattern[i] == '*') {
+			return 1;
+		}
+		if (rawname[i] == 0xa0) {
+			if (rawPattern[i] == 0xa0) {
+				return 1;
+			} else {
+				return 0;
+			}
+		} else {
+			if (rawPattern[i] == '?' || rawPattern[i] == rawname[i]) {
+			} else {
+				return 0;
+			}
+		}
+	}
+	return 1;
 }
 
 TrackSector nextTsInChain(DiskImage *di, TrackSector ts) {


Commit: 5ba5ac2f7a4e22976b90049e7fc9fc565a1c643c
    https://github.com/scummvm/scummvm/commit/5ba5ac2f7a4e22976b90049e7fc9fc565a1c643c
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Implement nextTsInChain

Changed paths:
    engines/glk/scott/disk_image.cpp


diff --git a/engines/glk/scott/disk_image.cpp b/engines/glk/scott/disk_image.cpp
index 67b45b24686..abca67ad30b 100644
--- a/engines/glk/scott/disk_image.cpp
+++ b/engines/glk/scott/disk_image.cpp
@@ -94,8 +94,16 @@ int matchPattern(byte *rawPattern, byte *rawname) {
 	return 1;
 }
 
+/* return a pointer to the next block in the chain */
 TrackSector nextTsInChain(DiskImage *di, TrackSector ts) {
-	return TrackSector();
+	byte *p;
+	TrackSector newTs;
+
+	p = diGetTsAddr(di, ts);
+	newTs._track = p[0];
+	newTs._sector = p[1];
+
+	return newTs;
 }
 
 RawDirEntry *findFileEntry(DiskImage *di, byte *rawPattern, int type) {


Commit: 1209ca3072940f55f971c47bc5c39b66020124b9
    https://github.com/scummvm/scummvm/commit/1209ca3072940f55f971c47bc5c39b66020124b9
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Implement allocFileEntry

Changed paths:
    engines/glk/scott/disk_image.cpp


diff --git a/engines/glk/scott/disk_image.cpp b/engines/glk/scott/disk_image.cpp
index abca67ad30b..cba78fe1ffe 100644
--- a/engines/glk/scott/disk_image.cpp
+++ b/engines/glk/scott/disk_image.cpp
@@ -128,8 +128,63 @@ RawDirEntry *findFileEntry(DiskImage *di, byte *rawPattern, int type) {
 	return nullptr;
 }
 
-RawDirEntry *allocFileEntry(DiskImage* di, byte* rawName, int type) {
-	return nullptr;
+/* allocate next available directory block */
+TrackSector allocNextDirTs(DiskImage *di) {
+	return TrackSector();
+}
+
+RawDirEntry *allocFileEntry(DiskImage *di, byte *rawName, int type) {
+	byte *buffer;
+	TrackSector ts;
+	RawDirEntry *rde;
+	int offset;
+
+	/* check if file already exists */
+	ts = nextTsInChain(di, di->_bam);
+	while (ts._track) {
+		buffer = diGetTsAddr(di, ts);
+		for (offset = 0; offset < 256; offset += 32) {
+			rde = (RawDirEntry *)(buffer + offset);
+			if (rde->_type) {
+				if (scumm_strnicmp((char *)rawName, (char *)rde->_rawname, 16) == 0) {
+					setStatus(di, 63, 0, 0);
+					return nullptr;
+				}
+			}
+		}
+		ts = nextTsInChain(di, ts);
+	}
+
+	/* allocate empty slot */
+	ts = nextTsInChain(di, di->_bam);
+	while (ts._track) {
+		buffer = diGetTsAddr(di, ts);
+		for (offset = 0; offset < 256; offset += 32) {
+			rde = (RawDirEntry *)(buffer + offset);
+			if (rde->_type == 0) {
+				memset((byte *)rde + 2, 0, 30);
+				memcpy(rde->_rawname, rawName, 16);
+				rde->_type = type;
+				di->_modified = 1;
+				return rde;
+			}
+		}
+		ts = nextTsInChain(di, ts);
+	}
+
+	/* allocate new dir block */
+	ts = allocNextDirTs(di);
+	if (ts._track) {
+		rde = (RawDirEntry *)diGetTsAddr(di, ts);
+		memset((byte *)rde + 2, 0, 30);
+		memcpy(rde->_rawname, rawName, 16);
+		rde->_type = type;
+		di->_modified = 1;
+		return rde;
+	} else {
+		setStatus(di, 72, 0, 0);
+		return nullptr;
+	}
 }
 
 ImageFile *diOpen(DiskImage *di, byte *rawname, byte type, const char *mode) {


Commit: 2cf15d1289ecdc70d6dbbc94ee2dede4f4e77076
    https://github.com/scummvm/scummvm/commit/2cf15d1289ecdc70d6dbbc94ee2dede4f4e77076
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Implement allocNextDirTs

Changed paths:
    engines/glk/scott/disk_image.cpp
    engines/glk/scott/disk_image.h


diff --git a/engines/glk/scott/disk_image.cpp b/engines/glk/scott/disk_image.cpp
index cba78fe1ffe..b1c699ddaa4 100644
--- a/engines/glk/scott/disk_image.cpp
+++ b/engines/glk/scott/disk_image.cpp
@@ -130,7 +130,44 @@ RawDirEntry *findFileEntry(DiskImage *di, byte *rawPattern, int type) {
 
 /* allocate next available directory block */
 TrackSector allocNextDirTs(DiskImage *di) {
-	return TrackSector();
+	byte *p;
+	int spt;
+	TrackSector ts, lastTs;
+
+	if (diTrackBlocksFree(di, di->_bam._track)) {
+		lastTs._track = di->_bam._track;
+		lastTs._sector = 0;
+		if ((di->_type == D64) || (di->_type == D71)) {
+			ts._track = 18;
+			ts._sector = 1;
+		} else {
+			ts = nextTsInChain(di, lastTs);
+		}
+		while (ts._track) {
+			lastTs = ts;
+			ts = nextTsInChain(di, ts);
+		}
+		ts._track = lastTs._track;
+		ts._sector = lastTs._sector + 3;
+		spt = diSectorsPerTrack(di->_type, ts._track);
+		for (;; ts._sector = (ts._sector + 1) % spt) {
+			if (diIsTsFree(di, ts)) {
+				diAllocTs(di, ts);
+				p = diGetTsAddr(di, lastTs);
+				p[0] = ts._track;
+				p[1] = ts._sector;
+				p = diGetTsAddr(di, ts);
+				memset(p, 0, 256);
+				p[1] = 0xff;
+				di->_modified = 1;
+				return ts;
+			}
+		}
+	} else {
+		ts._track = 0;
+		ts._sector = 0;
+		return ts;
+	}
 }
 
 RawDirEntry *allocFileEntry(DiskImage *di, byte *rawName, int type) {
@@ -505,6 +542,18 @@ TrackSector diGetDirTs(DiskImage *di) {
 	return newTs;
 }
 
+int diTrackBlocksFree(DiskImage *di, int track) {
+	return 0;
+}
+
+int diIsTsFree(DiskImage *di, TrackSector ts) {
+	return 0;
+}
+
+void diAllocTs(DiskImage *di, TrackSector ts) {
+
+}
+
 /* convert to rawname */
 int diRawnameFromName(byte *rawname, const char *name) {
 	int i;
diff --git a/engines/glk/scott/disk_image.h b/engines/glk/scott/disk_image.h
index 30c2a8df9e9..e83317882a0 100644
--- a/engines/glk/scott/disk_image.h
+++ b/engines/glk/scott/disk_image.h
@@ -103,6 +103,9 @@ int diTracks(ImageType type);
 int diGetBlockNum(ImageType type, TrackSector ts);
 
 TrackSector diGetDirTs(DiskImage *di);
+int diTrackBlocksFree(DiskImage *di, int track);
+int diIsTsFree(DiskImage *di, TrackSector ts);
+void diAllocTs(DiskImage *di, TrackSector ts);
 
 int diRawnameFromName(byte *rawname, const char *name);
 


Commit: 3dde6cfb4bc1793271d2e2d45bf71041afd2cd39
    https://github.com/scummvm/scummvm/commit/3dde6cfb4bc1793271d2e2d45bf71041afd2cd39
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Implement diTrackBlocksFree

Changed paths:
    engines/glk/scott/disk_image.cpp


diff --git a/engines/glk/scott/disk_image.cpp b/engines/glk/scott/disk_image.cpp
index b1c699ddaa4..d7059a3ced6 100644
--- a/engines/glk/scott/disk_image.cpp
+++ b/engines/glk/scott/disk_image.cpp
@@ -542,8 +542,32 @@ TrackSector diGetDirTs(DiskImage *di) {
 	return newTs;
 }
 
+/* return number of free blocks in track */
 int diTrackBlocksFree(DiskImage *di, int track) {
-	return 0;
+	byte *bam;
+
+	switch (di->_type) {
+	default:
+	case D64:
+		bam = diGetTsAddr(di, di->_bam);
+		break;
+	case D71:
+		bam = diGetTsAddr(di, di->_bam);
+		if (track >= 36) {
+			return bam[track + 185];
+		}
+		break;
+	case D81:
+		if (track <= 40) {
+			bam = diGetTsAddr(di, di->_bam);
+		} else {
+			bam = diGetTsAddr(di, di->_bam2);
+			track -= 40;
+		}
+		return bam[track * 6 + 10];
+		break;
+	}
+	return bam[track * 4];
 }
 
 int diIsTsFree(DiskImage *di, TrackSector ts) {


Commit: feafc98c3c7a09a3f370348bfbacba735c6b5ae2
    https://github.com/scummvm/scummvm/commit/feafc98c3c7a09a3f370348bfbacba735c6b5ae2
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Implement diIsTsFree

Changed paths:
    engines/glk/scott/disk_image.cpp


diff --git a/engines/glk/scott/disk_image.cpp b/engines/glk/scott/disk_image.cpp
index d7059a3ced6..aa7439d9ad2 100644
--- a/engines/glk/scott/disk_image.cpp
+++ b/engines/glk/scott/disk_image.cpp
@@ -570,7 +570,42 @@ int diTrackBlocksFree(DiskImage *di, int track) {
 	return bam[track * 4];
 }
 
+/* check if track, sector is free in BAM */
 int diIsTsFree(DiskImage *di, TrackSector ts) {
+	byte mask;
+	byte *bam;
+
+	switch (di->_type) {
+	case D64:
+		bam = diGetTsAddr(di, di->_bam);
+		if (bam[ts._track * 4]) {
+			mask = 1 << (ts._sector & 7);
+			return bam[ts._track * 4 + ts._sector / 8 + 1] & mask ? 1 : 0;
+		} else {
+			return 0;
+		}
+		break;
+	case D71:
+		mask = 1 << (ts._sector & 7);
+		if (ts._track < 36) {
+			bam = diGetTsAddr(di, di->_bam);
+			return bam[ts._track * 4 + ts._sector / 8 + 1] & mask ? 1 : 0;
+		} else {
+			bam = diGetTsAddr(di, di->_bam2);
+			return bam[(ts._track - 35) * 3 + ts._sector / 8 - 3] & mask ? 1 : 0;
+		}
+		break;
+	case D81:
+		mask = 1 << (ts._sector & 7);
+		if (ts._track < 41) {
+			bam = diGetTsAddr(di, di->_bam);
+		} else {
+			bam = diGetTsAddr(di, di->_bam2);
+			ts._track -= 40;
+		}
+		return bam[ts._track * 6 + ts._sector / 8 + 11] & mask ? 1 : 0;
+		break;
+	}
 	return 0;
 }
 


Commit: 63909041b378cee4989cd95abb6f094eaf5b8ae8
    https://github.com/scummvm/scummvm/commit/63909041b378cee4989cd95abb6f094eaf5b8ae8
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Implement diAllocTs

Changed paths:
    engines/glk/scott/disk_image.cpp


diff --git a/engines/glk/scott/disk_image.cpp b/engines/glk/scott/disk_image.cpp
index aa7439d9ad2..16199b6097d 100644
--- a/engines/glk/scott/disk_image.cpp
+++ b/engines/glk/scott/disk_image.cpp
@@ -609,8 +609,44 @@ int diIsTsFree(DiskImage *di, TrackSector ts) {
 	return 0;
 }
 
+/* allocate track, sector in BAM */
 void diAllocTs(DiskImage *di, TrackSector ts) {
+	byte mask;
+	byte *bam;
 
+	di->_modified = 1;
+	switch (di->_type) {
+	case D64:
+		bam = diGetTsAddr(di, di->_bam);
+		bam[ts._track * 4] -= 1;
+		mask = 1 << (ts._sector & 7);
+		bam[ts._track * 4 + ts._sector / 8 + 1] &= ~mask;
+		break;
+	case D71:
+		mask = 1 << (ts._sector & 7);
+		if (ts._track < 36) {
+			bam = diGetTsAddr(di, di->_bam);
+			bam[ts._track * 4] -= 1;
+			bam[ts._track * 4 + ts._sector / 8 + 1] &= ~mask;
+		} else {
+			bam = diGetTsAddr(di, di->_bam);
+			bam[ts._track + 185] -= 1;
+			bam = diGetTsAddr(di, di->_bam2);
+			bam[(ts._track - 35) * 3 + ts._sector / 8 - 3] &= ~mask;
+		}
+		break;
+	case D81:
+		if (ts._track < 41) {
+			bam = diGetTsAddr(di, di->_bam);
+		} else {
+			bam = diGetTsAddr(di, di->_bam2);
+			ts._track -= 40;
+		}
+		bam[ts._track * 6 + 10] -= 1;
+		mask = 1 << (ts._sector & 7);
+		bam[ts._track * 6 + ts._sector / 8 + 11] &= ~mask;
+		break;
+	}
 }
 
 /* convert to rawname */


Commit: f2c37fe61054735e37d388a46277033d0ccbbbe8
    https://github.com/scummvm/scummvm/commit/f2c37fe61054735e37d388a46277033d0ccbbbe8
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Implement getTsDosErr

Changed paths:
    engines/glk/scott/disk_image.cpp


diff --git a/engines/glk/scott/disk_image.cpp b/engines/glk/scott/disk_image.cpp
index 16199b6097d..7dc311d01d8 100644
--- a/engines/glk/scott/disk_image.cpp
+++ b/engines/glk/scott/disk_image.cpp
@@ -420,7 +420,12 @@ byte *diGetTsAddr(DiskImage *di, TrackSector ts) {
 
 /* get error info for a sector */
 int getTsDosErr(DiskImage* di, TrackSector ts) {
-	return 0;
+	//	return 1;
+	if (di->_errinfo == nullptr) {
+		return 1; /* return OK if image has no error info */
+	}
+
+	return di->_errinfo[diGetBlockNum(di->_type, ts)];
 }
 
 int diGetTsErr(DiskImage *di, TrackSector ts) {


Commit: a2962c4b43dd1771376bc9578bedd466f018764c
    https://github.com/scummvm/scummvm/commit/a2962c4b43dd1771376bc9578bedd466f018764c
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Implement blocksFree

Changed paths:
    engines/glk/scott/disk_image.cpp


diff --git a/engines/glk/scott/disk_image.cpp b/engines/glk/scott/disk_image.cpp
index 7dc311d01d8..dee34e16d0f 100644
--- a/engines/glk/scott/disk_image.cpp
+++ b/engines/glk/scott/disk_image.cpp
@@ -666,7 +666,14 @@ int diRawnameFromName(byte *rawname, const char *name) {
 
 /* count number of free blocks */
 int blocksFree(DiskImage* di) {
-	return 0;
+	int blocks = 0;
+
+	for (int track = 1; track <= diTracks(di->_type); ++track) {
+		if (track != di->_dir._track) {
+			blocks += diTrackBlocksFree(di, track);
+		}
+	}
+	return blocks;
 }
 
 /* return write interleave */


Commit: eb354e99290e30cbb81abbaf2222a39aa8c7e035
    https://github.com/scummvm/scummvm/commit/eb354e99290e30cbb81abbaf2222a39aa8c7e035
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Implement interleave

Changed paths:
    engines/glk/scott/disk_image.cpp


diff --git a/engines/glk/scott/disk_image.cpp b/engines/glk/scott/disk_image.cpp
index dee34e16d0f..90c7f8261a9 100644
--- a/engines/glk/scott/disk_image.cpp
+++ b/engines/glk/scott/disk_image.cpp
@@ -678,7 +678,17 @@ int blocksFree(DiskImage* di) {
 
 /* return write interleave */
 int interleave(ImageType type) {
-	return 0;
+	switch (type) {
+	case D64:
+		return 10;
+		break;
+	case D71:
+		return 6;
+		break;
+	default:
+		return 1;
+		break;
+	}
 }
 
 DiskImage *diCreateFromData(uint8_t *data, int length) {


Commit: a2ef20d0d7402a9e491b32140ec9efb2cc6ba0bc
    https://github.com/scummvm/scummvm/commit/a2ef20d0d7402a9e491b32140ec9efb2cc6ba0bc
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
JANITORIAL: Formatting fixes

Changed paths:
    engines/glk/scott/disk_image.cpp


diff --git a/engines/glk/scott/disk_image.cpp b/engines/glk/scott/disk_image.cpp
index 90c7f8261a9..45a59c1a4b4 100644
--- a/engines/glk/scott/disk_image.cpp
+++ b/engines/glk/scott/disk_image.cpp
@@ -53,7 +53,7 @@ DosError g_dosError[] = {
 	{-1, -1, nullptr}
 };
 
-int setStatus(DiskImage* di, int status, int track, int sector) {
+int setStatus(DiskImage *di, int status, int track, int sector) {
 	di->_status = status;
 	di->_statusts._track = track;
 	di->_statusts._sector = sector;
@@ -419,7 +419,7 @@ byte *diGetTsAddr(DiskImage *di, TrackSector ts) {
 }
 
 /* get error info for a sector */
-int getTsDosErr(DiskImage* di, TrackSector ts) {
+int getTsDosErr(DiskImage *di, TrackSector ts) {
 	//	return 1;
 	if (di->_errinfo == nullptr) {
 		return 1; /* return OK if image has no error info */
@@ -665,7 +665,7 @@ int diRawnameFromName(byte *rawname, const char *name) {
 }
 
 /* count number of free blocks */
-int blocksFree(DiskImage* di) {
+int blocksFree(DiskImage *di) {
 	int blocks = 0;
 
 	for (int track = 1; track <= diTracks(di->_type); ++track) {


Commit: 9f7a9a4493fa83974ca2fb61ba725445d5eba89d
    https://github.com/scummvm/scummvm/commit/9f7a9a4493fa83974ca2fb61ba725445d5eba89d
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Implement decrunchC64

Changed paths:
  A engines/glk/scott/unp64/unp64.cpp
  A engines/glk/scott/unp64/unp64.h
  A engines/glk/scott/unp64/unp64_interface.h
    engines/glk/module.mk
    engines/glk/scott/c64_checksums.cpp


diff --git a/engines/glk/module.mk b/engines/glk/module.mk
index 2f7054c5b87..60dd2168a61 100644
--- a/engines/glk/module.mk
+++ b/engines/glk/module.mk
@@ -252,6 +252,7 @@ MODULE_OBJS := \
 	scott/ring_buffer.o \
 	scott/saga_draw.o \
 	scott/scott.o \
+	scott/unp64/unp64.o \
 	tads/os_banners.o \
 	tads/os_buffer.o \
 	tads/os_glk.o \
diff --git a/engines/glk/scott/c64_checksums.cpp b/engines/glk/scott/c64_checksums.cpp
index 7490c13a8bd..ba4b8424a96 100644
--- a/engines/glk/scott/c64_checksums.cpp
+++ b/engines/glk/scott/c64_checksums.cpp
@@ -26,6 +26,10 @@
 #include "glk/scott/c64_checksums.h"
 #include "glk/scott/definitions.h"
 #include "glk/scott/disk_image.h"
+#include "glk/scott/game_info.h"
+#include "glk/scott/resource.h"
+#include "glk/scott/saga_draw.h"
+#include "glk/scott/unp64/unp64_interface.h"
 
 namespace Glk {
 namespace Scott {
@@ -239,9 +243,85 @@ int detectC64(uint8_t **sf, size_t *extent) {
 	return decrunchC64(sf, extent, g_C64Registry[index]);
 }
 
-int decrunchC64(uint8_t **sf, size_t *extent, C64Rec entry) {
+size_t copyData(size_t dest, size_t source, uint8_t** data, size_t dataSize, size_t bytesToMove) {
 	return 0;
 }
 
+int decrunchC64(uint8_t **sf, size_t *extent, C64Rec record) {
+	uint8_t *uncompressed = nullptr;
+	_G(_fileLength) = *extent;
+
+	size_t decompressedLength = *extent;
+
+	uncompressed = new uint8_t[0xffff];
+
+	char *switches[3];
+	int numSwitches = 0;
+
+	if (record._switches != nullptr) {
+		char string[100];
+		strcpy(string, record._switches);
+		switches[numSwitches] = strtok(string, " ");
+
+		while (switches[numSwitches] != nullptr)
+			switches[++numSwitches] = strtok(nullptr, " ");
+	}
+
+	size_t result = 0;
+
+	for (int i = 1; i <= record._decompressIterations; i++) {
+		/* We only send switches on the iteration specified by parameter */
+		if (i == record._parameter && record._switches != nullptr) {
+			result = unp64(_G(_entireFile), _G(_fileLength), uncompressed, &decompressedLength, switches, numSwitches);
+		} else
+			result = unp64(_G(_entireFile), _G(_fileLength), uncompressed, &decompressedLength, nullptr, 0);
+		if (result) {
+			if (_G(_entireFile) != nullptr)
+				delete[] _G(_entireFile);
+			_G(_entireFile) = new uint8_t[decompressedLength];
+			memcpy(_G(_entireFile), uncompressed, decompressedLength);
+			_G(_fileLength) = decompressedLength;
+		} else {
+			delete[] uncompressed;
+			break;
+		}
+	}
+
+	for (int i = 0; i < NUMGAMES; i++) {
+		if (g_games[i]._gameID == record._id) {
+			delete _G(_game);
+			_G(_game) = &g_games[i];
+			break;
+		}
+	}
+
+	if (_G(_game)->_title == nullptr) {
+		error("decrunchC64: Game not found");
+	}
+
+	int offset;
+
+	DictionaryType dictype = getId(&offset);
+	if (dictype != _G(_game)->_dictionary) {
+		error("decrunchC64: Wrong game?");
+	}
+
+	if (!tryLoading(*_G(_game), offset, 0)) {
+		error("decrunchC64: Game could not be read");
+	}
+
+	if (record._copySource != 0) {
+		result = copyData(record._copyDest, record._copySource, sf, *extent, record._copySize);
+		if (result) {
+			*extent = result;
+		}
+	}
+
+	if (!(_G(_game)->_subType & MYSTERIOUS))
+		sagaSetup(record._imgOffset);
+
+	return CURRENT_GAME;
+}
+
 } // End of namespace Scott
 } // End of namespace Glk
diff --git a/engines/glk/scott/unp64/unp64.cpp b/engines/glk/scott/unp64/unp64.cpp
new file mode 100644
index 00000000000..d4b3563b69d
--- /dev/null
+++ b/engines/glk/scott/unp64/unp64.cpp
@@ -0,0 +1,33 @@
+/* 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 "glk/scott/unp64/unp64.h"
+#include "glk/scott/types.h"
+
+namespace Glk {
+namespace Scott {
+
+int unp64(uint8_t* compressed, size_t length, uint8_t* destinationBuffer, size_t* finalLength, char* settings[], int numSettings) {
+	return 0;
+}
+
+} // End of namespace Scott
+} // End of namespace Glk
diff --git a/engines/glk/scott/unp64/unp64.h b/engines/glk/scott/unp64/unp64.h
new file mode 100644
index 00000000000..5a875616f75
--- /dev/null
+++ b/engines/glk/scott/unp64/unp64.h
@@ -0,0 +1,32 @@
+/* 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 GLK_SCOTT_UNP64_H
+#define GLK_SCOTT_UNP64_H
+
+namespace Glk {
+namespace Scott {
+
+
+} // End of namespace Scott
+} // End of namespace Glk
+
+#endif 
diff --git a/engines/glk/scott/unp64/unp64_interface.h b/engines/glk/scott/unp64/unp64_interface.h
new file mode 100644
index 00000000000..6e1704bab34
--- /dev/null
+++ b/engines/glk/scott/unp64/unp64_interface.h
@@ -0,0 +1,35 @@
+/* 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 GLK_SCOTT_UNP64_INTERFACE_H
+#define GLK_SCOTT_UNP64_INTERFACE_H
+
+#include "glk/scott/types.h"
+
+namespace Glk {
+namespace Scott {
+
+int unp64(uint8_t *compressed, size_t length, uint8_t *destinationBuffer, size_t *finalLength, char *settings[], int numSettings);
+
+} // End of namespace Scott
+} // End of namespace Glk
+
+#endif 


Commit: 136960a795aad7abd480c0e1b16dc663f46a17ac
    https://github.com/scummvm/scummvm/commit/136960a795aad7abd480c0e1b16dc663f46a17ac
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Implement unp64

Changed paths:
  A engines/glk/scott/unp64/6502_emu.cpp
  A engines/glk/scott/unp64/6502_emu.h
  A engines/glk/scott/unp64/exo_util.cpp
  A engines/glk/scott/unp64/exo_util.h
  A engines/glk/scott/unp64/scanners/scanners.cpp
    engines/glk/module.mk
    engines/glk/scott/globals.h
    engines/glk/scott/unp64/unp64.cpp
    engines/glk/scott/unp64/unp64.h


diff --git a/engines/glk/module.mk b/engines/glk/module.mk
index 60dd2168a61..7251f5a45d2 100644
--- a/engines/glk/module.mk
+++ b/engines/glk/module.mk
@@ -253,6 +253,9 @@ MODULE_OBJS := \
 	scott/saga_draw.o \
 	scott/scott.o \
 	scott/unp64/unp64.o \
+	scott/unp64/6502_emu.o \
+	scott/unp64/exo_util.o \
+	scott/unp64/scanners/scanners.o \
 	tads/os_banners.o \
 	tads/os_buffer.o \
 	tads/os_glk.o \
diff --git a/engines/glk/scott/globals.h b/engines/glk/scott/globals.h
index 6b6b20617d6..cd76920ac08 100644
--- a/engines/glk/scott/globals.h
+++ b/engines/glk/scott/globals.h
@@ -30,6 +30,7 @@
 #include "glk/windows.h"
 #include "glk/scott/definitions.h"
 #include "glk/scott/types.h"
+#include "glk/scott/unp64/unp64.h"
 
 namespace Glk {
 namespace Scott {
@@ -156,6 +157,11 @@ public:
 	// detect game
 	Common::HashMap<Common::String, int> _md5Index;
 
+	// unp64
+	UnpStr _unp;
+	int _parsePar = 1;
+	int _iter = 0;
+
 public:
 	Globals();
 	~Globals();
diff --git a/engines/glk/scott/unp64/6502_emu.cpp b/engines/glk/scott/unp64/6502_emu.cpp
new file mode 100644
index 00000000000..6d9d5f6330a
--- /dev/null
+++ b/engines/glk/scott/unp64/6502_emu.cpp
@@ -0,0 +1,59 @@
+/* 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/>.
+ *
+ */
+
+/*
+ * Copyright (c) 2007 - 2008 Magnus Lind.
+ *
+ * This software is provided 'as-is', without any express or implied warranty.
+ * In no event will the authors be held liable for any damages arising from
+ * the use of this software.
+ *
+ * Permission is granted to anyone to use this software, alter it and re-
+ * distribute it freely for any non-commercial, non-profit purpose subject to
+ * the following restrictions:
+ *
+ *   1. The origin of this software must not be misrepresented; you must not
+ *   claim that you wrote the original software. If you use this software in a
+ *   product, an acknowledgment in the product documentation would be
+ *   appreciated but is not required.
+ *
+ *   2. Altered source versions must be plainly marked as such, and must not
+ *   be misrepresented as being the original software.
+ *
+ *   3. This notice may not be removed or altered from any distribution.
+ *
+ *   4. The names of this software and/or it's copyright holders may not be
+ *   used to endorse or promote products derived from this software without
+ *   specific prior written permission.
+ *
+ */
+
+#include "glk/scott/unp64/6502_emu.h"
+
+namespace Glk {
+namespace Scott {
+
+int nextInst(CpuCtx* r) {
+	return 0;
+}
+
+} // End of namespace Scott
+} // End of namespace Glk
diff --git a/engines/glk/scott/unp64/6502_emu.h b/engines/glk/scott/unp64/6502_emu.h
new file mode 100644
index 00000000000..e751faf8dde
--- /dev/null
+++ b/engines/glk/scott/unp64/6502_emu.h
@@ -0,0 +1,73 @@
+/* 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/>.
+ *
+ */
+
+/*
+ * Copyright (c) 2007 - 2008 Magnus Lind.
+ *
+ * This software is provided 'as-is', without any express or implied warranty.
+ * In no event will the authors be held liable for any damages arising from
+ * the use of this software.
+ *
+ * Permission is granted to anyone to use this software, alter it and re-
+ * distribute it freely for any non-commercial, non-profit purpose subject to
+ * the following restrictions:
+ *
+ *   1. The origin of this software must not be misrepresented; you must not
+ *   claim that you wrote the original software. If you use this software in a
+ *   product, an acknowledgment in the product documentation would be
+ *   appreciated but is not required.
+ *
+ *   2. Altered source versions must be plainly marked as such, and must not
+ *   be misrepresented as being the original software.
+ *
+ *   3. This notice may not be removed or altered from any distribution.
+ *
+ *   4. The names of this software and/or it's copyright holders may not be
+ *   used to endorse or promote products derived from this software without
+ *   specific prior written permission.
+ *
+ */
+
+#ifndef GLK_SCOTT_6502_EMU_H
+#define GLK_SCOTT_6502_EMU_H
+
+#include "glk/scott/types.h"
+
+namespace Glk {
+namespace Scott {
+
+struct CpuCtx {
+	uint32_t _cycles;
+	uint16_t _pc;
+	uint8_t *_mem;
+	uint8_t _sp;
+	uint8_t _flags;
+	uint8_t _a;
+	uint8_t _x;
+	uint8_t _y;
+};
+
+int nextInst(CpuCtx *r);
+
+} // End of namespace Scott
+} // End of namespace Glk
+
+#endif
diff --git a/engines/glk/scott/unp64/exo_util.cpp b/engines/glk/scott/unp64/exo_util.cpp
new file mode 100644
index 00000000000..386dbd5737f
--- /dev/null
+++ b/engines/glk/scott/unp64/exo_util.cpp
@@ -0,0 +1,66 @@
+/* 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/>.
+ *
+ */
+
+/*
+ * Copyright (c) 2007 - 2008 Magnus Lind.
+ *
+ * This software is provided 'as-is', without any express or implied warranty.
+ * In no event will the authors be held liable for any damages arising from
+ * the use of this software.
+ *
+ * Permission is granted to anyone to use this software, alter it and re-
+ * distribute it freely for any non-commercial, non-profit purpose subject to
+ * the following restrictions:
+ *
+ *   1. The origin of this software must not be misrepresented; you must not
+ *   claim that you wrote the original software. If you use this software in a
+ *   product, an acknowledgment in the product documentation would be
+ *   appreciated but is not required.
+ *
+ *   2. Altered source versions must be plainly marked as such, and must not
+ *   be misrepresented as being the original software.
+ *
+ *   3. This notice may not be removed or altered from any distribution.
+ *
+ *   4. The names of this software and/or it's copyright holders may not be
+ *   used to endorse or promote products derived from this software without
+ *   specific prior written permission.
+ *
+ */
+
+#include "glk/scott/unp64/exo_util.h"
+
+namespace Glk {
+namespace Scott {
+
+int findSys(const byte *buf, int target) {
+	return 0;
+}
+
+void loadData(uint8_t *data, size_t dataLength, unsigned char mem[65536], LoadInfo *info) {
+}
+
+int strToInt(const char *str, int *value) {
+	return 0;
+}
+
+} // End of namespace Scott
+} // End of namespace Glk
diff --git a/engines/glk/scott/unp64/exo_util.h b/engines/glk/scott/unp64/exo_util.h
new file mode 100644
index 00000000000..319a9ef613c
--- /dev/null
+++ b/engines/glk/scott/unp64/exo_util.h
@@ -0,0 +1,74 @@
+/* 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/>.
+ *
+ */
+
+/*
+ * Copyright (c) 2007 - 2008 Magnus Lind.
+ *
+ * This software is provided 'as-is', without any express or implied warranty.
+ * In no event will the authors be held liable for any damages arising from
+ * the use of this software.
+ *
+ * Permission is granted to anyone to use this software, alter it and re-
+ * distribute it freely for any non-commercial, non-profit purpose subject to
+ * the following restrictions:
+ *
+ *   1. The origin of this software must not be misrepresented; you must not
+ *   claim that you wrote the original software. If you use this software in a
+ *   product, an acknowledgment in the product documentation would be
+ *   appreciated but is not required.
+ *
+ *   2. Altered source versions must be plainly marked as such, and must not
+ *   be misrepresented as being the original software.
+ *
+ *   3. This notice may not be removed or altered from any distribution.
+ *
+ *   4. The names of this software and/or it's copyright holders may not be
+ *   used to endorse or promote products derived from this software without
+ *   specific prior written permission.
+ *
+ */
+
+#ifndef GLK_SCOTT_EXO_UTIL_H
+#define GLK_SCOTT_EXO_UTIL_H
+
+#include "glk/scott/types.h"
+
+namespace Glk {
+namespace Scott {
+
+struct LoadInfo {
+	int _basicTxtStart; /* in */
+	int _basicVarStart; /* out */
+	int _run;           /* out */
+	int _start;         /* out */
+	int _end;           /* out */
+};
+
+int findSys(const byte *buf, int target);
+
+void loadData(uint8_t *data, size_t dataLength, unsigned char mem[65536], LoadInfo *info);
+
+int strToInt(const char *str, int *value);
+
+} // End of namespace Scott
+} // End of namespace Glk
+
+#endif
diff --git a/engines/glk/scott/unp64/scanners/scanners.cpp b/engines/glk/scott/unp64/scanners/scanners.cpp
new file mode 100644
index 00000000000..9ecbc26491a
--- /dev/null
+++ b/engines/glk/scott/unp64/scanners/scanners.cpp
@@ -0,0 +1,32 @@
+/* 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 "glk/scott/unp64/unp64.h"
+
+namespace Glk {
+namespace Scott {
+
+void scanners(UnpStr* unp) {
+
+}
+
+} // End of namespace Scott
+} // End of namespace Glk
diff --git a/engines/glk/scott/unp64/unp64.cpp b/engines/glk/scott/unp64/unp64.cpp
index d4b3563b69d..436f274fbd4 100644
--- a/engines/glk/scott/unp64/unp64.cpp
+++ b/engines/glk/scott/unp64/unp64.cpp
@@ -19,15 +19,697 @@
  *
  */
 
-#include "glk/scott/unp64/unp64.h"
+// This is a cut-down version of UNP64 with only the bare minimum
+// needed to decompress a number of Scott Adams Commodore 64 games
+// for the ScottFree interpreter.
+
+/*
+UNP64 - generic Commodore 64 prg unpacker
+(C) 2008-2018 iAN CooG/HVSC Crew^C64Intros
+original source and idea: testrun.c, taken from exo20b7
+
+Follows original disclaimer
+*/
+
+/*
+ * Copyright (c) 2002 - 2008 Magnus Lind.
+ *
+ * This software is provided 'as-is', without any express or implied warranty.
+ * In no event will the authors be held liable for any damages arising from
+ * the use of this software.
+ *
+ * Permission is granted to anyone to use this software, alter it and re-
+ * distribute it freely for any non-commercial, non-profit purpose subject to
+ * the following restrictions:
+ *
+ *   1. The origin of this software must not be misrepresented; you must not
+ *   claim that you wrote the original software. If you use this software in a
+ *   product, an acknowledgment in the product documentation would be
+ *   appreciated but is not required.
+ *
+ *   2. Altered source versions must be plainly marked as such, and must not
+ *   be misrepresented as being the original software.
+ *
+ *   3. This notice may not be removed or altered from any distribution.
+ *
+ *   4. The names of this software and/or it's copyright holders may not be
+ *   used to endorse or promote products derived from this software without
+ *   specific prior written permission.
+ *
+ */
+
+#include "glk/scott/globals.h"
 #include "glk/scott/types.h"
+#include "glk/scott/unp64/6502_emu.h"
+#include "glk/scott/unp64/exo_util.h"
+#include "glk/scott/unp64/unp64.h"
 
 namespace Glk {
 namespace Scott {
 
-int unp64(uint8_t* compressed, size_t length, uint8_t* destinationBuffer, size_t* finalLength, char* settings[], int numSettings) {
+void reinitUnp(void) {
+	_G(_unp)._idFlag = 0;
+	_G(_unp)._forced = 0;
+	_G(_unp)._strMem = 0x800;
+	_G(_unp)._retAdr = 0x800;
+	_G(_unp)._depAdr = 0;
+	_G(_unp)._endAdr = 0x10000;
+	_G(_unp)._rtAFrc = 0;
+	_G(_unp)._wrMemF = 0;
+	_G(_unp)._lfMemF = 0;
+	_G(_unp)._exoFnd = 0;
+	_G(_unp)._ecaFlg = 0;
+	_G(_unp)._fEndBf = 0;
+	_G(_unp)._fEndAf = 0;
+	_G(_unp)._fStrAf = 0;
+	_G(_unp)._fStrBf = 0;
+	_G(_unp)._mon1st = 0;
+}
+
+int IsBasicRun1(int pc) {
 	return 0;
 }
 
+int IsBasicRun2(int pc) {
+	return 0;
+}
+
+int unp64(uint8_t *compressed, size_t length, uint8_t *destinationBuffer, size_t *finalLength, char *settings[], int numSettings) {
+	CpuCtx r[1];
+	LoadInfo info[1];
+	char name[260] = {0}, forcedname[260] = {0};
+	byte mem[65536] = {0}, oldmem[65536] = {0};
+	byte vector[0x20] = {0x31, 0xEA, 0x66, 0xFE, 0x47, 0xFE, 0x4A, 0xF3,
+						 0x91, 0xF2, 0x0E, 0xF2, 0x50, 0xF2, 0x33, 0xF3,
+						 0x57, 0xF1, 0xCA, 0xF1, 0xED, 0xF6, 0x3E, 0xF1,
+						 0x2F, 0xF3, 0x66, 0xFE, 0xA5, 0xF4, 0xED, 0xF5};
+
+	byte stack[0x100] = {0x33, 0x38, 0x39, 0x31, 0x31, 0x00, 0x30, 0x30, 0x30, 0x30,
+						 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+						 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+						 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+						 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+						 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+						 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+						 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+						 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+						 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+						 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+						 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+						 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
+						 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+						 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+						 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+						 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+						 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+						 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+						 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+						 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+						 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+						 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7D,
+						 0xEA, 0x00, 0x00, 0x82, 0x22, 0x0E, 0xBC, 0x81, 0x64, 0xB8,
+						 0x0C, 0xBD, 0xBA, 0xB7, 0xBC, 0x03, 0x00, 0x46, 0xE1, 0xE9,
+						 0xA7, 0xA7, 0x79, 0xA6, 0x9C, 0xE3};
+
+	int iterMax = ITERMAX;
+	int copyRoms[2][2] = {{0xa000, 0}, {0xe000, 0}};
+	int p;
+
+	memset(&_G(_unp), 0, sizeof(_G(_unp)));
+	reinitUnp();
+	_G(_unp)._fStack = 1;
+	_G(_unp)._mem = mem;
+	_G(_unp)._r = r;
+	_G(_unp)._name = name;
+	_G(_unp)._info = info;
+
+	p = 0;
+
+	if (numSettings != 0) {
+		if (settings[0][0] == '-' && _G(_parsePar) && settings[0][1] == 'f') {
+			strToInt(settings[p] + 2, (int *)&_G(_unp)._filler);
+			if (_G(_unp)._filler) {
+				memset(mem + (_G(_unp)._filler >> 16), _G(_unp)._filler & 0xff, 0x10000 - (_G(_unp)._filler >> 16));
+			}
+			p++;
+		}
+	}
+
+	looprecurse:
+	info->_basicTxtStart = 0x801;
+	loadData(compressed, length, mem, info);
+		/* no start address from load */
+	if (info->_run == -1) {
+		/* look for sys line */
+		info->_run = findSys(mem + info->_basicTxtStart, 0x9e);
+	}
+
+	scanners(&_G(_unp));
+	if (_G(_unp)._idFlag == 2)
+		return 0;
+
+	if ((_G(_unp)._recurs == 0) && (numSettings > 0)) {
+		while (p < numSettings) {
+			if (settings && settings[p][0] == '-') {
+				switch (settings[p][1]) {
+				case '-':
+					p = numSettings;
+					break;
+				case 'e':
+					strToInt(settings[p] + 2, &_G(_unp)._forced);
+					_G(_unp)._forced &= 0xffff;
+					if (_G(_unp)._forced < 0x1)
+						_G(_unp)._forced = 0;
+					break;
+				case 'a':
+					_G(_unp)._strMem = 2;
+					_G(_unp)._endAdr = 0x10001;
+					_G(_unp)._fEndAf = 0;
+					_G(_unp)._fStrAf = 0;
+					_G(_unp)._strAdC = 0;
+					_G(_unp)._endAdC = 0;
+					_G(_unp)._monEnd = 0;
+					_G(_unp)._monStr = 0;
+					break;
+				case 'r':
+					strToInt(settings[p] + 2, &_G(_unp)._retAdr);
+					_G(_unp)._retAdr &= 0xffff;
+					break;
+				case 'R':
+					strToInt(settings[p] + 2, &_G(_unp)._retAdr);
+					_G(_unp)._retAdr &= 0xffff;
+					_G(_unp)._rtAFrc = 1;
+					break;
+				case 'd':
+					strToInt(settings[p] + 2, &_G(_unp)._depAdr);
+					_G(_unp)._depAdr &= 0xffff;
+					break;
+				case 't':
+					strToInt(settings[p] + 2, &_G(_unp)._endAdr);
+					_G(_unp)._endAdr &= 0xffff;
+					if (_G(_unp)._endAdr >= 0x100)
+						_G(_unp)._endAdr++;
+					break;
+				case 'u':
+					_G(_unp)._wrMemF = 1;
+					break;
+				case 'l':
+					_G(_unp)._lfMemF = info->_end;
+					break;
+				case 's':
+					_G(_unp)._fStack = 0;
+					break;
+				case 'x':
+					break;
+				case 'B':
+					copyRoms[0][1] = 1;
+					break;
+				case 'K':
+					copyRoms[1][1] = 1;
+					break;
+				case 'c':
+					_G(_unp)._recurs++;
+					break;
+				case 'm': // keep undocumented for now
+					strToInt(settings[p] + 2, &iterMax);
+				}
+			}
+			p++;
+		}
+	}
+
+	if (_G(_unp)._idOnly) {
+		if (_G(_unp)._depAdr == 0)
+			return 0;
+	}
+
+	if (_G(_unp)._wrMemF | _G(_unp)._lfMemF) {
+		memcpy(oldmem, mem, sizeof(oldmem));
+	}
+
+	if (_G(_unp)._forced) {
+		info->_run = _G(_unp)._forced;
+	}
+
+	if (info->_run == -1) {
+		return 0;
+	}
+
+	if (_G(_unp)._strMem > _G(_unp)._retAdr) {
+		_G(_unp)._strMem = _G(_unp)._retAdr;
+	}
+
+	mem[0] = 0x60;
+	r->_cycles = 0;
+	mem[1] = 0x37;
+
+	if (((_G(_unp)._forced >= 0xa000) && (_G(_unp)._forced < 0xc000)) || (_G(_unp)._forced >= 0xd000))
+		mem[1] = 0x38;
+
+	/* some packers rely on basic pointers already set */
+	mem[0x2b] = info->_basicTxtStart & 0xff;
+	mem[0x2c] = info->_basicTxtStart >> 8;
+
+	if (info->_basicVarStart == -1) {
+		mem[0x2d] = info->_end & 0xff;
+		mem[0x2e] = info->_end >> 8;
+	} else {
+		mem[0x2d] = info->_basicVarStart & 0xff;
+		mem[0x2e] = info->_basicVarStart >> 8;
+	}
+
+	mem[0x2f] = mem[0x2d];
+	mem[0x30] = mem[0x2e];
+	mem[0x31] = mem[0x2d];
+	mem[0x32] = mem[0x2e];
+	mem[0xae] = info->_end & 0xff;
+	mem[0xaf] = info->_end >> 8;
+
+	/* CCS unpacker requires $39/$3a (current basic line number) set */
+	mem[0x39] = mem[0x803];
+	mem[0x3a] = mem[0x804];
+	mem[0x52] = 0;
+	mem[0x53] = 3;
+
+	if (_G(_unp)._fStack) {
+		memcpy(mem + 0x100, stack,
+			   sizeof(stack)); /* stack as found on clean start */
+		r->_sp = 0xf6;         /* sys from immediate mode leaves $f6 in stackptr */
+	} else {
+		r->_sp = 0xff;
+	}
+
+	if (info->_start > (0x314 + sizeof(vector))) {
+		/* some packers use values in irq pointers to decrypt themselves */
+		memcpy(mem + 0x314, vector, sizeof(vector));
+	}
+
+	mem[0x200] = 0x8a;
+	r->_mem = mem;
+	r->_pc = info->_run;
+	r->_flags = 0x20;
+	r->_a = 0;
+	r->_y = 0;
+
+	if (info->_run > 0x351) /* temporary for XIP */ {
+		r->_x = 0;
+	}
+
+	_G(_iter) = 0;
+	while ((_G(_unp)._depAdr ? r->_pc != _G(_unp)._depAdr : r->_pc >= _G(_unp)._retAdr)) {
+		if ((((mem[1] & 0x7) >= 6) && (r->_pc >= 0xe000)) || ((r->_pc >= 0xa000) && (r->_pc <= 0xbfff) && ((mem[1] & 0x7) > 6))) {
+			/* some packer relies on regs set at return from CLRSCR */
+			if ((r->_pc == 0xe536) || (r->_pc == 0xe544) || (r->_pc == 0xff5b) || ((r->_pc == 0xffd2) && (r->_a == 0x93))) {
+				if (r->_pc != 0xffd2) {
+					r->_x = 0x01;
+					r->_y = 0x84;
+
+					if (r->_pc == 0xff5b)
+						r->_a = 0x97; /* actually depends on $d012 */
+					else
+						r->_a = 0xd8;
+
+					r->_flags &= ~(128 | 2);
+					r->_flags |= (r->_a == 0 ? 2 : 0) | (r->_a & 128);
+				}
+				memset(mem + 0x400, 0x20, 1000);
+			}
+			/* intros */
+			if ((r->_pc == 0xffe4) || (r->_pc == 0xf13e)) {
+				static int flipspe4 = -1;
+				static unsigned char fpressedchars[] = {0x20, 0, 0x4e, 0, 3, 0, 0x5f, 0, 0x11, 00, 0x0d, 0, 0x31, 0};
+				flipspe4++;
+
+				if (flipspe4 > (sizeof(fpressedchars) / sizeof(*fpressedchars)))
+					flipspe4 = 0;
+
+				r->_a = fpressedchars[flipspe4];
+				r->_flags &= ~(128 | 2);
+				r->_flags |= (r->_a == 0 ? 2 : 0) | (r->_a & 128);
+			}
+
+			if (r->_pc == 0xfd15) {
+				r->_a = 0x31;
+				r->_x = 0x30;
+				r->_y = 0xff;
+			}
+
+			if (r->_pc == 0xfda3) {
+				mem[0x01] = 0xe7;
+				r->_a = 0xd7;
+				r->_x = 0xff;
+			}
+
+			if (r->_pc == 0xffbd) {
+				mem[0xB7] = r->_a;
+				mem[0xBB] = r->_x;
+				mem[0xBC] = r->_y;
+			}
+
+			if ((r->_pc == 0xffd5) || (r->_pc == 0xf4a2)) {
+				break;
+			}
+
+			if (IsBasicRun1(r->_pc)) {
+				info->_run = findSys(mem + info->_basicTxtStart, 0x9e);
+				if (info->_run > 0) {
+					r->_sp = 0xf6;
+					r->_pc = info->_run;
+				} else {
+					mem[0] = 0x60;
+					r->_pc = 0; /* force a RTS instead of executing ROM code */
+				}
+			} else {
+				mem[0] = 0x60;
+				r->_pc = 0; /* force a RTS instead of executing ROM code */
+			}
+		}
+
+		if (nextInst(r) == 1)
+			return 0;
+
+		_G(_iter)++;
+		if (_G(_iter) == iterMax) {
+				return 0;
+		}
+
+		if (_G(_unp)._exoFnd && (_G(_unp)._endAdr == 0x10000) && (r->_pc >= 0x100) && (r->_pc <= 0x200) && (_G(_unp)._strMem != 2)) {
+			_G(_unp)._endAdr = r->_mem[0xfe] + (r->_mem[0xff] << 8);
+
+		if ((_G(_unp)._exoFnd & 0xff) == 0x30) { /* low byte of _endAdr, it's a lda $ff00,y */
+			_G(_unp)._endAdr = (_G(_unp)._exoFnd >> 8) + (r->_mem[0xff] << 8);
+		} else if ((_G(_unp)._exoFnd & 0xff) == 0x32) { /* add 1 */
+			_G(_unp)._endAdr = 1 + ((_G(_unp)._exoFnd >> 8) + (r->_mem[0xff] << 8));
+		}
+
+		if (_G(_unp)._endAdr == 0)
+			_G(_unp)._endAdr = 0x10001;
+		}
+
+		if (_G(_unp)._fEndBf && (_G(_unp)._endAdr == 0x10000) && (r->_pc == _G(_unp)._depAdr)) {
+			_G(_unp)._endAdr = r->_mem[_G(_unp)._fEndBf] | r->_mem[_G(_unp)._fEndBf + 1] << 8;
+			_G(_unp)._endAdr++;
+
+			if (_G(_unp)._endAdr == 0)
+					_G(_unp)._endAdr = 0x10001;
+
+			_G(_unp)._fEndBf = 0;
+		}
+
+		if (_G(_unp)._fStrBf && (_G(_unp)._strMem != 0x2) && (r->_pc == _G(_unp)._depAdr)) {
+			_G(_unp)._strMem = r->_mem[_G(_unp)._fStrBf] | r->_mem[_G(_unp)._fStrBf + 1] << 8;
+			_G(_unp)._fStrBf = 0;
+		}
+
+		if (_G(_unp)._debugP) {
+			for (p = 0; p < 0x20; p += 2) {
+				if (*(unsigned short int *)(mem + 0x314 + p) != *(unsigned short int *)(vector + p)) {
+					*(unsigned short int *)(vector + p) = *(unsigned short int *)(mem + 0x314 + p);
+				}
+			}
+		}
+	}
+
+	_G(_iter) = 0;
+	while (_G(_unp)._rtAFrc ? r->_pc != _G(_unp)._retAdr : r->_pc < _G(_unp)._retAdr) {
+		if (_G(_unp)._monEnd && r->_pc == _G(_unp)._depAdr) {
+			p = r->_mem[_G(_unp)._monEnd >> 16] | r->_mem[_G(_unp)._monEnd & 0xffff] << 8;
+			if (p > (_G(_unp)._endAdr & 0xffff)) {
+				_G(_unp)._endAdr = p;
+			}
+		}
+		if (_G(_unp)._monStr && r->_pc == _G(_unp)._depAdr) {
+			p = r->_mem[_G(_unp)._monStr >> 16] | r->_mem[_G(_unp)._monStr & 0xffff] << 8;
+			if (p > 0) {
+				if (_G(_unp)._mon1st == 0) {
+					_G(_unp)._strMem = p;
+				}
+				_G(_unp)._mon1st = _G(_unp)._strMem;
+				_G(_unp)._strMem = (p < _G(_unp)._strMem ? p : _G(_unp)._strMem);
+			}
+		}
+
+		if (r->_pc >= 0xe000) {
+			if (((mem[1] & 0x7) >= 6) && ((mem[1] & 0x7) <= 7)) {
+				mem[0] = 0x60;
+				r->_pc = 0;
+			}
+		}
+		if (nextInst(r) == 1)
+			return 0;
+
+		if ((mem[r->_pc] == 0x40) && (_G(_unp)._rtiFrc == 1)) {
+			if (nextInst(r) == 1)
+				return 0;
+			_G(_unp)._retAdr = r->_pc;
+			_G(_unp)._rtAFrc = 1;
+			if (_G(_unp)._retAdr < _G(_unp)._strMem)
+				_G(_unp)._strMem = 2;
+			break;
+		}
+
+		_G(_iter)++;
+		if (_G(_iter) == iterMax) {
+			return 0;
+		}
+
+		if ((r->_pc >= 0xa000) && (r->_pc <= 0xbfff) && ((mem[1] & 0x7) == 7)) {
+			if (IsBasicRun2(r->_pc)) {
+				r->_pc = 0xa7ae;
+				break;
+			} else {
+				mem[0] = 0x60;
+				r->_pc = 0;
+			}
+		}
+
+		if (r->_pc >= 0xe000) {
+			if (((mem[1] & 0x7) >= 6) && ((mem[1] & 0x7) <= 7)) {
+				if (r->_pc == 0xffbd) {
+					mem[0xB7] = r->_a;
+					mem[0xBB] = r->_x;
+					mem[0xBC] = r->_y;
+				}
+				/* return into IRQ handler, better stop here */
+				if (((r->_pc >= 0xea31) && (r->_pc <= 0xeb76)) || (r->_pc == 0xffd5) || (r->_pc == 0xfce2)) {
+					break;
+				}
+
+				if (r->_pc == 0xfda3) {
+					mem[0x01] = 0xe7;
+					r->_a = 0xd7;
+					r->_x = 0xff;
+				}
+				mem[0] = 0x60;
+				r->_pc = 0;
+			}
+		}
+	}
+
+	if (_G(_unp)._fEndAf && _G(_unp)._monEnd) {
+		_G(_unp)._endAdC = mem[_G(_unp)._fEndAf] | mem[_G(_unp)._fEndAf + 1] << 8;
+		if ((int)_G(_unp)._endAdC > _G(_unp)._endAdr)
+			_G(_unp)._endAdr = _G(_unp)._endAdC;
+
+		_G(_unp)._endAdC = 0;
+		_G(_unp)._fEndAf = 0;
+	}
+
+	if (_G(_unp)._fEndAf && (_G(_unp)._endAdr == 0x10000)) {
+		_G(_unp)._endAdr = r->_mem[_G(_unp)._fEndAf] | r->_mem[_G(_unp)._fEndAf + 1] << 8;
+		if (_G(_unp)._endAdr == 0)
+			_G(_unp)._endAdr = 0x10000;
+		else
+			_G(_unp)._endAdr++;
+		_G(_unp)._fEndAf = 0;
+	}
+
+	if (_G(_unp)._fStrAf /*&&(_G(_unp)._strMem==0x800)*/) {
+		_G(_unp)._strMem = r->_mem[_G(_unp)._fStrAf] | r->_mem[_G(_unp)._fStrAf + 1] << 8;
+		_G(_unp)._strMem++;
+		_G(_unp)._fStrAf = 0;
+	}
+
+	if (_G(_unp)._exoFnd && (_G(_unp)._strMem != 2)) {
+		_G(_unp)._strMem = r->_mem[0xfe] + (r->_mem[0xff] << 8);
+
+		if ((_G(_unp)._exoFnd & 0xff) == 0x30) {
+			_G(_unp)._strMem += r->_y;
+		} else if ((_G(_unp)._exoFnd & 0xff) == 0x32) {
+			_G(_unp)._strMem += r->_y + 1;
+		}
+	}
+
+	if (r->_pc == 0xfce2) {
+		if ((*(unsigned int *)(mem + 0x8004) == 0x38cdc2c3) && (mem[0x8008] == 0x30)) {
+			r->_pc = r->_mem[0x8000] + (r->_mem[0x8001] << 8);
+		}
+	} else if (r->_pc == 0xa7ae) {
+		info->_basicTxtStart = mem[0x2b] | mem[0x2c] << 8;
+		if (info->_basicTxtStart == 0x801) {
+			info->_run = findSys(mem + info->_basicTxtStart, 0x9e);
+			if (info->_run > 0)
+				r->_pc = info->_run;
+		}
+	}
+
+	if (_G(_unp)._wrMemF) {
+		_G(_unp)._wrMemF = 0;
+		for (p = 0x800; p < 0x10000; p += 4) {
+			if (*(unsigned int *)(oldmem + p) == *(unsigned int *)(mem + p)) {
+				*(unsigned int *)(mem + p) = 0;
+				_G(_unp)._wrMemF = 1;
+			}
+		}
+		/* clean also the $fd30 table copy in RAM */
+		if (memcmp(mem + 0xfd30, vector, sizeof(vector)) == 0) {
+			memset(mem + 0xfd30, 0, sizeof(vector));
+		}
+	}
+
+	if (_G(_unp)._lfMemF) {
+		for (p = 0xffff; p > 0x0800; p--) {
+			if (oldmem[--_G(_unp)._lfMemF] == mem[p])
+				mem[p] = 0x0;
+			else {
+				if (p >= 0xffff)
+					_G(_unp)._lfMemF = 0 | _G(_unp)._ecaFlg;
+				break;
+			}
+		}
+	}
+
+	if (*forcedname) {
+		strcpy(name, forcedname);
+	} else {
+		if (strlen(name) > 248) /* dirty hack in case name is REALLY long */
+			name[248] = 0;
+		sprintf(name + strlen(name), ".%04x%s", r->_pc,
+				(_G(_unp)._wrMemF | _G(_unp)._lfMemF ? ".clean" : ""));
+	}
+
+	/*  endadr is set to a ZP location? then use it as a pointer
+	  todo: use __fEndAf instead, it can be used for any location, not only ZP. */
+	if (_G(_unp)._endAdr && (_G(_unp)._endAdr < 0x100)) {
+		p = (mem[_G(_unp)._endAdr] | mem[_G(_unp)._endAdr + 1] << 8) & 0xffff;
+		_G(_unp)._endAdr = p;
+	}
+
+	if (_G(_unp)._ecaFlg && (_G(_unp)._strMem != 2)) /* checkme */ {
+		if (_G(_unp)._endAdr >= ((_G(_unp)._ecaFlg >> 16) & 0xffff)) {
+			/* most of the times transfers $2000 byte from $d000-efff to $e000-ffff but there are exceptions */
+			if (_G(_unp)._lfMemF)
+				memset(mem + ((_G(_unp)._ecaFlg >> 16) & 0xffff), 0, 0x1000);
+			_G(_unp)._endAdr += 0x1000;
+		}
+	}
+
+	if (_G(_unp)._endAdr <= 0)
+		_G(_unp)._endAdr = 0x10000;
+
+	if (_G(_unp)._endAdr > 0x10000)
+		_G(_unp)._endAdr = 0x10000;
+
+	if (_G(_unp)._endAdr < _G(_unp)._strMem)
+		_G(_unp)._endAdr = 0x10000;
+
+	if (_G(_unp)._endAdC & 0xffff) {
+		_G(_unp)._endAdr += (_G(_unp)._endAdC & 0xffff);
+		_G(_unp)._endAdr &= 0xffff;
+	}
+
+	if (_G(_unp)._endAdC & EA_USE_A) {
+		_G(_unp)._endAdr += r->_a;
+		_G(_unp)._endAdr &= 0xffff;
+	}
+
+	if (_G(_unp)._endAdC & EA_USE_X) {
+		_G(_unp)._endAdr += r->_x;
+		_G(_unp)._endAdr &= 0xffff;
+	}
+
+	if (_G(_unp)._endAdC & EA_USE_Y) {
+		_G(_unp)._endAdr += r->_y;
+		_G(_unp)._endAdr &= 0xffff;
+	}
+
+	if (_G(_unp)._strAdC & 0xffff) {
+		_G(_unp)._strMem += (_G(_unp)._strAdC & 0xffff);
+		_G(_unp)._strMem &= 0xffff;
+		/* only if ea_addff, no reg involved */
+		if (((_G(_unp)._strAdC & 0xffff0000) == EA_ADDFF) && ((_G(_unp)._strMem & 0xff) == 0)) {
+			_G(_unp)._strMem += 0x100;
+			_G(_unp)._strMem &= 0xffff;
+		}
+	}
+
+	if (_G(_unp)._strAdC & EA_USE_A) {
+		_G(_unp)._strMem += r->_a;
+		_G(_unp)._strMem &= 0xffff;
+		if (_G(_unp)._strAdC & EA_ADDFF) {
+			if ((_G(_unp)._strMem & 0xff) == 0xff)
+				_G(_unp)._strMem++;
+
+			if (r->_a == 0) {
+				_G(_unp)._strMem += 0x100;
+				_G(_unp)._strMem &= 0xffff;
+			}
+		}
+	}
+
+	if (_G(_unp)._strAdC & EA_USE_X) {
+		_G(_unp)._strMem += r->_x;
+		_G(_unp)._strMem &= 0xffff;
+
+		if (_G(_unp)._strAdC & EA_ADDFF) {
+			if ((_G(_unp)._strMem & 0xff) == 0xff)
+				_G(_unp)._strMem++;
+
+			if (r->_x == 0) {
+				_G(_unp)._strMem += 0x100;
+				_G(_unp)._strMem &= 0xffff;
+			}
+		}
+	}
+
+	if (_G(_unp)._strAdC & EA_USE_Y) {
+		_G(_unp)._strMem += r->_y;
+		_G(_unp)._strMem &= 0xffff;
+
+		if (_G(_unp)._strAdC & EA_ADDFF) {
+			if ((_G(_unp)._strMem & 0xff) == 0xff)
+				_G(_unp)._strMem++;
+
+			if (r->_y == 0) {
+				_G(_unp)._strMem += 0x100;
+				_G(_unp)._strMem &= 0xffff;
+			}
+		}
+	}
+
+	if (_G(_unp)._endAdr <= 0)
+		_G(_unp)._endAdr = 0x10000;
+
+	if (_G(_unp)._endAdr > 0x10000)
+		_G(_unp)._endAdr = 0x10000;
+
+	if (_G(_unp)._endAdr < _G(_unp)._strMem)
+		_G(_unp)._endAdr = 0x10000;
+
+	mem[_G(_unp)._strMem - 2] = _G(_unp)._strMem & 0xff;
+	mem[_G(_unp)._strMem - 1] = _G(_unp)._strMem >> 8;
+
+	memcpy(destinationBuffer, mem + (_G(_unp)._strMem - 2), _G(_unp)._endAdr - _G(_unp)._strMem + 2);
+	*finalLength = _G(_unp)._endAdr - _G(_unp)._strMem + 2;
+
+	if (_G(_unp)._recurs) {
+		if (++_G(_unp)._recurs > RECUMAX)
+			return 1;
+		reinitUnp();
+		goto looprecurse;
+	}
+	return 1;
+}
+
 } // End of namespace Scott
 } // End of namespace Glk
diff --git a/engines/glk/scott/unp64/unp64.h b/engines/glk/scott/unp64/unp64.h
index 5a875616f75..6a09fcbef11 100644
--- a/engines/glk/scott/unp64/unp64.h
+++ b/engines/glk/scott/unp64/unp64.h
@@ -25,6 +25,50 @@
 namespace Glk {
 namespace Scott {
 
+struct LoadInfo;
+struct CpuCtx;
+
+struct UnpStr {
+	int _idFlag;          /* flag, 1=packer identified; 2=not a packer, stop scanning */
+	int _forced;          /* forced entry point */
+	int _strMem;          /* start of unpacked memory */
+	int _retAdr;          /* return address after unpacking */
+	int _depAdr;          /* unpacker entry point */
+	int _endAdr;          /* end of unpacked memory */
+	int _rtAFrc;          /* flag, return address must be exactly RetAdr, else anything >= RetAdr */
+	int _wrMemF;          /* flag, clean unwritten memory */
+	int _lfMemF;          /* flag, clean end memory leftovers */
+	int _exoFnd;          /* flag, Exomizer detected */ 
+	int _fStack;          /* flag, fill stack with 0 and SP=$ff, else as in C64 */
+	int _ecaFlg;          /* ECA found, holds relocated areas high bytes */
+	int _fEndBf;          /* End memory address pointer before unpacking, set when DepAdr is reached */
+	int _fEndAf;          /* End memory address pointer after  unpacking, set when RetAdr is reached */
+	int _fStrBf;          /* Start memory address pointer before unpacking, set when DepAdr is reached */
+	int _fStrAf;          /* Start memory address pointer after  unpacking, set when RetAdr is reached */
+	int _idOnly;          /* flag, just identify packer and exit */
+	int _debugP;          /* flag, verbosely emit various infos */
+	int _rtiFrc;          /* flag, RTI instruction forces return from unpacker */
+	int _recurs;          /* recursion counter */
+	unsigned int _monEnd;	/* End memory address pointers monitored during execution, updated every time DepAdr is reached */
+	unsigned int _monStr;	/* Start memory address pointers monitored during execution, updated every time DepAdr is reached */
+	unsigned int _mon1st;	/* flag for forcingly assign monitored str/end ptr the 1st time */
+	unsigned int _endAdC;	/* add fixed values and/or registers AXY to End memory address */
+	unsigned int _strAdC;	/* add fixed values and/or registers AXY to Start memory address */
+	unsigned int _filler;	/* Memory filler byte*/
+	unsigned char *_mem;    /* pointer to the memory array */
+	char *_name;            /* name of the prg file */
+	LoadInfo *_info; /* pointer to the loaded prg info struct */
+	CpuCtx *_r;      /* pointer to the registers struct */
+};
+
+#define EA_USE_A 0x01000000
+#define EA_USE_X 0x00100000
+#define EA_USE_Y 0x00010000
+#define EA_ADDFF 0x10000000
+#define ITERMAX 0x02000000
+#define RECUMAX 16
+
+void scanners(UnpStr *);
 
 } // End of namespace Scott
 } // End of namespace Glk


Commit: 9fb22510fd6d3590edb603f3c1b7b889a88c519c
    https://github.com/scummvm/scummvm/commit/9fb22510fd6d3590edb603f3c1b7b889a88c519c
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
JANITORIAL: Fix formatting

Changed paths:
    engines/glk/scott/unp64/unp64.cpp


diff --git a/engines/glk/scott/unp64/unp64.cpp b/engines/glk/scott/unp64/unp64.cpp
index 436f274fbd4..409445ac5e6 100644
--- a/engines/glk/scott/unp64/unp64.cpp
+++ b/engines/glk/scott/unp64/unp64.cpp
@@ -584,8 +584,7 @@ int unp64(uint8_t *compressed, size_t length, uint8_t *destinationBuffer, size_t
 	} else {
 		if (strlen(name) > 248) /* dirty hack in case name is REALLY long */
 			name[248] = 0;
-		sprintf(name + strlen(name), ".%04x%s", r->_pc,
-				(_G(_unp)._wrMemF | _G(_unp)._lfMemF ? ".clean" : ""));
+		sprintf(name + strlen(name), ".%04x%s", r->_pc, ((_G(_unp)._wrMemF | _G(_unp)._lfMemF) ? ".clean" : ""));
 	}
 
 	/*  endadr is set to a ZP location? then use it as a pointer


Commit: be0db5ba1c898126cff14d11760fee2789ba27ce
    https://github.com/scummvm/scummvm/commit/be0db5ba1c898126cff14d11760fee2789ba27ce
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Implement 6502 CPU emulation

Changed paths:
    engines/glk/scott/globals.h
    engines/glk/scott/unp64/6502_emu.cpp


diff --git a/engines/glk/scott/globals.h b/engines/glk/scott/globals.h
index cd76920ac08..ced8fc31d41 100644
--- a/engines/glk/scott/globals.h
+++ b/engines/glk/scott/globals.h
@@ -162,6 +162,11 @@ public:
 	int _parsePar = 1;
 	int _iter = 0;
 
+	// 6502 emu
+	int _byted011[2] = {0, 0};
+	int _retfire = 0xff;
+	int _retspace = 0xff;
+
 public:
 	Globals();
 	~Globals();
diff --git a/engines/glk/scott/unp64/6502_emu.cpp b/engines/glk/scott/unp64/6502_emu.cpp
index 6d9d5f6330a..87e427f489b 100644
--- a/engines/glk/scott/unp64/6502_emu.cpp
+++ b/engines/glk/scott/unp64/6502_emu.cpp
@@ -46,12 +46,1300 @@
  *
  */
 
+#include "glk/scott/globals.h"
 #include "glk/scott/unp64/6502_emu.h"
 
 namespace Glk {
 namespace Scott {
 
+#define FLAG_N 128
+#define FLAG_V 64
+#define FLAG_D 8
+#define FLAG_I 4
+#define FLAG_Z 2
+#define FLAG_C 1
+
+struct ArgEa {
+	uint16_t _value;
+};
+struct ArgRelative {
+	int8_t _value;
+};
+struct ArgImmediate {
+	uint8_t _value;
+};
+
+union InstArg {
+	ArgEa _ea;
+	ArgRelative _rel;
+	ArgImmediate _imm;
+};
+
+typedef void op_f(CpuCtx *r, int mode, InstArg *arg);
+typedef int mode_f(CpuCtx *r, InstArg *arg);
+
+struct OpInfo {
+	op_f *_f;
+	const char *_fmt;
+};
+
+struct ModeInfo {
+	mode_f *_f;
+	const char *_fmt;
+};
+
+struct InstInfo {
+	OpInfo *_op;
+	ModeInfo *_mode;
+	uint8_t _cycles;
+};
+
+#define MODE_IMMEDIATE 0
+#define MODE_ZERO_PAGE 1
+#define MODE_ZERO_PAGE_X 2
+#define MODE_ZERO_PAGE_Y 3
+#define MODE_ABSOLUTE 4
+#define MODE_ABSOLUTE_X 5
+#define MODE_ABSOLUTE_Y 6
+#define MODE_INDIRECT 7
+#define MODE_INDIRECT_X 8
+#define MODE_INDIRECT_Y 9
+#define MODE_RELATIVE 10
+#define MODE_ACCUMULATOR 11
+#define MODE_IMPLIED 12
+
+static int mode_imm(CpuCtx *r, InstArg *arg) {
+	arg->_imm._value = r->_mem[r->_pc + 1];
+	r->_pc += 2;
+	return MODE_IMMEDIATE;
+}
+
+static int mode_zp(CpuCtx *r, InstArg *arg) {
+	arg->_ea._value = r->_mem[r->_pc + 1];
+	r->_pc += 2;
+	return MODE_ZERO_PAGE;
+}
+
+static int mode_zpx(CpuCtx *r, InstArg *arg) { /* iAN: ldx #1 lda $ff,x should fetch from $00 and not $100 */
+	uint8_t lsbLo = (r->_mem[r->_pc + 1] + r->_x) & 0xff;
+	arg->_ea._value = lsbLo;
+	r->_pc += 2;
+	return MODE_ZERO_PAGE_X;
+}
+
+static int mode_zpy(CpuCtx *r, InstArg *arg) { /* iAN: ldy #1 ldx $ff,y should fetch from $00 and not $100 */
+	uint8_t lsbLo = (r->_mem[r->_pc + 1] + r->_y) & 0xff;
+	arg->_ea._value = lsbLo;
+	r->_pc += 2;
+	return MODE_ZERO_PAGE_Y;
+}
+
+static int mode_abs(CpuCtx *r, InstArg *arg) {
+	uint16_t offset = r->_mem[r->_pc + 1];
+	uint16_t base = r->_mem[r->_pc + 2] << 8;
+	arg->_ea._value = base + offset;
+	r->_pc += 3;
+	return MODE_ABSOLUTE;
+}
+
+static int mode_absx(CpuCtx *r, InstArg *arg) {
+	uint16_t offset = r->_mem[r->_pc + 1] + r->_x;
+	uint16_t base = r->_mem[r->_pc + 2] << 8;
+	arg->_ea._value = base + offset;
+	r->_pc += 3;
+	r->_cycles += (offset > 255);
+	return MODE_ABSOLUTE_X;
+}
+
+static int mode_absy(CpuCtx *r, InstArg *arg) {
+	uint16_t offset = r->_mem[r->_pc + 1] + r->_y;
+	uint16_t base = r->_mem[r->_pc + 2] << 8;
+	arg->_ea._value = base + offset;
+	r->_pc += 3;
+	r->_cycles += (offset > 255);
+	return MODE_ABSOLUTE_Y;
+}
+
+static int mode_ind(CpuCtx *r, InstArg *arg) {
+	int lsbLo = r->_mem[r->_pc + 1];
+	int msbLo = r->_mem[r->_pc + 2];
+	int offsetlo = lsbLo | msbLo << 8;
+	int offsethi = ((lsbLo + 1) & 0xff) | msbLo << 8;
+	arg->_ea._value = r->_mem[offsetlo] | r->_mem[offsethi] << 8;
+
+	r->_pc += 3;
+	return MODE_INDIRECT;
+}
+
+static int mode_indx(CpuCtx *r, InstArg *arg) {
+	uint8_t lsbLo = r->_mem[r->_pc + 1] + r->_x;
+	uint8_t msbLo = lsbLo + 1;
+	uint16_t base = r->_mem[msbLo] << 8;
+	uint16_t offset = r->_mem[lsbLo];
+	arg->_ea._value = base + offset;
+	r->_pc += 2;
+	return MODE_INDIRECT_X;
+}
+
+static int mode_indy(CpuCtx *r, InstArg *arg) {
+	uint8_t lsbLo = r->_mem[r->_pc + 1];
+	uint8_t msbLo = lsbLo + 1;
+	uint16_t base = r->_mem[msbLo] << 8;
+	uint16_t offset = r->_mem[lsbLo] + r->_y;
+	arg->_ea._value = base + offset;
+	r->_pc += 2;
+	r->_cycles += (offset > 255);
+	return MODE_INDIRECT_Y;
+}
+
+static int mode_rel(CpuCtx *r, InstArg *arg) {
+	arg->_rel._value = r->_mem[r->_pc + 1];
+	r->_pc += 2;
+	return MODE_RELATIVE;
+}
+
+static int mode_acc(CpuCtx *r, InstArg *arg) {
+	r->_pc++;
+	return MODE_ACCUMULATOR;
+}
+
+static int mode_imp(CpuCtx *r, InstArg *arg) {
+	r->_pc++;
+	return MODE_IMPLIED;
+}
+
+static ModeInfo mode_imm_o	= { &mode_imm,	"#$%02x" };
+static ModeInfo mode_zp_o	= { &mode_zp,	"$%02x" };
+static ModeInfo mode_zpx_o	= { &mode_zpx,	"$%02x,x" };
+static ModeInfo mode_zpy_o	= { &mode_zpy,	"$%02x,y" };
+static ModeInfo mode_abs_o	= { &mode_abs,	"$%04x" };
+static ModeInfo mode_absx_o = { &mode_absx,	"$%04x,x" };
+static ModeInfo mode_absy_o = { &mode_absy,	"$%04x,y" };
+static ModeInfo mode_ind_o	= { &mode_ind,	"($%04x)" };
+static ModeInfo mode_indx_o = { &mode_indx,	"($%02x,x)" };
+static ModeInfo mode_indy_o = { &mode_indy,	"($%02x),y" };
+static ModeInfo mode_rel_o	= { &mode_rel,	"$%02x" };
+static ModeInfo mode_acc_o	= { &mode_acc,	"a" };
+static ModeInfo mode_imp_o	= { &mode_imp,	nullptr };
+
+static void updateFlagsNz(CpuCtx *r, uint8_t value) {
+	r->_flags &= ~(FLAG_Z | FLAG_N);
+	r->_flags |= (value == 0 ? FLAG_Z : 0) | (value & FLAG_N);
+}
+
+static void updateCarry(CpuCtx *r, int boolean) {
+	r->_flags = (r->_flags & ~FLAG_C) | (boolean != 0 ? FLAG_C : 0);
+}
+
+static uint16_t subtract(CpuCtx *r, int carry, uint8_t val1, uint8_t value) {
+	uint16_t target = val1 - value - (1 - !!carry);
+	updateCarry(r, !(target & 256));
+	updateFlagsNz(r, target & 255);
+	return target;
+}
+
+static void update_overflow(CpuCtx *r, int boolean) {
+	r->_flags = (r->_flags & ~FLAG_V) | (boolean != 0 ? FLAG_V : 0);
+}
+
+static void op_adc(CpuCtx *r, int mode, InstArg *arg) {
+	uint8_t value;
+	uint16_t result;
+	switch (mode) {
+	case MODE_IMMEDIATE:
+		value = arg->_imm._value;
+		break;
+	default:
+		value = r->_mem[arg->_ea._value];
+		break;
+	}
+	result = r->_a + value + (r->_flags & FLAG_C);
+	updateCarry(r, result & 256);
+	update_overflow(r, !((r->_a & 0x80) ^ (value & 0x80)) && ((r->_a & 0x80) ^ (result & 0x80)));
+	r->_a = result & 0xff;
+	updateFlagsNz(r, r->_a);
+}
+
+static void op_and(CpuCtx *r, int mode, InstArg *arg) {
+	uint8_t value;
+	switch (mode) {
+	case MODE_IMMEDIATE:
+		value = arg->_imm._value;
+		break;
+	default:
+		value = r->_mem[arg->_ea._value];
+		break;
+	}
+	r->_a &= value;
+	updateFlagsNz(r, r->_a);
+}
+
+static void op_asl(CpuCtx *r, int mode, InstArg *arg) {
+	uint8_t *valuep;
+	switch (mode) {
+	case MODE_ACCUMULATOR:
+		valuep = &r->_a;
+		break;
+	default:
+		valuep = &r->_mem[arg->_ea._value];
+		break;
+	}
+	updateCarry(r, *valuep & 128);
+	*valuep <<= 1;
+	updateFlagsNz(r, *valuep);
+}
+
+static void branch(CpuCtx *r, InstArg *arg) {
+	uint16_t target = r->_pc + arg->_rel._value;
+	r->_cycles += 1 + ((target & ~255) != (r->_pc & ~255));
+	r->_pc = target;
+}
+
+static void op_bcc(CpuCtx *r, int mode, InstArg *arg) {
+	if (!(r->_flags & FLAG_C)) {
+		branch(r, arg);
+	}
+}
+
+static void op_bcs(CpuCtx *r, int mode, InstArg *arg) {
+	if (r->_flags & FLAG_C) {
+		branch(r, arg);
+	}
+}
+
+static void op_beq(CpuCtx *r, int mode, InstArg *arg) {
+	if (r->_flags & FLAG_Z) {
+		branch(r, arg);
+	}
+}
+
+static void op_bit(CpuCtx *r, int mode, InstArg *arg) {
+	r->_flags &= ~(FLAG_N | FLAG_V | FLAG_Z);
+	r->_flags |= (r->_mem[arg->_ea._value] & FLAG_N) != 0 ? FLAG_N : 0;
+	r->_flags |= (r->_mem[arg->_ea._value] & FLAG_V) != 0 ? FLAG_V : 0;
+	r->_flags |= (r->_mem[arg->_ea._value] & r->_a) == 0 ? FLAG_Z : 0;
+}
+
+static void op_bmi(CpuCtx *r, int mode, InstArg *arg) {
+	if (r->_flags & FLAG_N) {
+		branch(r, arg);
+	}
+}
+
+static void op_bne(CpuCtx *r, int mode, InstArg *arg) {
+	if (!(r->_flags & FLAG_Z)) {
+		branch(r, arg);
+	}
+}
+
+static void op_bpl(CpuCtx *r, int mode, InstArg *arg) {
+	if (!(r->_flags & FLAG_N)) {
+		branch(r, arg);
+	}
+}
+
+static void op_brk(CpuCtx *r, int mode, InstArg *arg) {
+	r->_mem[0x100 + r->_sp--] = (r->_pc + 1) >> 8;
+	r->_mem[0x100 + r->_sp--] = r->_pc + 1;
+	r->_mem[0x100 + r->_sp--] = r->_flags | 0x10;
+}
+
+static void op_bvc(CpuCtx *r, int mode, InstArg *arg) {
+	if (!(r->_flags & FLAG_V)) {
+		branch(r, arg);
+	}
+}
+
+static void op_bvs(CpuCtx *r, int mode, InstArg *arg) {
+	if ((r->_flags & FLAG_V)) {
+		branch(r, arg);
+	}
+}
+
+static void op_clc(CpuCtx *r, int mode, InstArg *arg) {
+	r->_flags &= ~FLAG_C;
+}
+
+static void op_cld(CpuCtx *r, int mode, InstArg *arg) {
+	r->_flags &= ~FLAG_D;
+}
+
+static void op_cli(CpuCtx *r, int mode, InstArg *arg) {
+	r->_flags &= ~FLAG_I;
+}
+
+static void op_clv(CpuCtx *r, int mode, InstArg *arg) {
+	r->_flags &= ~FLAG_V;
+}
+
+
+static void op_cmp(CpuCtx *r, int mode, InstArg *arg) {
+	uint8_t value;
+	switch (mode) {
+	case MODE_IMMEDIATE:
+		value = arg->_imm._value;
+		break;
+	default:
+		value = r->_mem[arg->_ea._value];
+		break;
+	}
+	subtract(r, 1, r->_a, value);
+}
+
+static void op_cpx(CpuCtx *r, int mode, InstArg *arg) {
+	uint8_t value;
+	switch (mode) {
+	case MODE_IMMEDIATE:
+		value = arg->_imm._value;
+		break;
+	default:
+		value = r->_mem[arg->_ea._value];
+		break;
+	}
+	subtract(r, 1, r->_x, value);
+}
+
+static void op_cpy(CpuCtx *r, int mode, InstArg *arg) {
+	uint8_t value;
+	switch (mode) {
+	case MODE_IMMEDIATE:
+		value = arg->_imm._value;
+		break;
+	default:
+		value = r->_mem[arg->_ea._value];
+		break;
+	}
+	subtract(r, 1, r->_y, value);
+}
+
+static void op_dec(CpuCtx *r, int mode, InstArg *arg) {
+	r->_mem[arg->_ea._value]--;
+	updateFlagsNz(r, r->_mem[arg->_ea._value]);
+}
+
+static void op_dex(CpuCtx *r, int mode, InstArg *arg) {
+	r->_x--;
+	updateFlagsNz(r, r->_x);
+}
+
+static void op_dey(CpuCtx *r, int mode, InstArg *arg) {
+	r->_y--;
+	updateFlagsNz(r, r->_y);
+}
+
+static void op_eor(CpuCtx *r, int mode, InstArg *arg) {
+	uint8_t value;
+	switch (mode) {
+	case MODE_IMMEDIATE:
+		value = arg->_imm._value;
+		break;
+	default:
+		value = r->_mem[arg->_ea._value];
+		break;
+	}
+	r->_a ^= value;
+	updateFlagsNz(r, r->_a);
+}
+
+static void op_inc(CpuCtx *r, int mode, InstArg *arg) {
+	r->_mem[arg->_ea._value]++;
+	updateFlagsNz(r, r->_mem[arg->_ea._value]);
+}
+
+static void op_inx(CpuCtx *r, int mode, InstArg *arg) {
+	r->_x++;
+	updateFlagsNz(r, r->_x);
+}
+
+static void op_iny(CpuCtx *r, int mode, InstArg *arg) {
+	r->_y++;
+	updateFlagsNz(r, r->_y);
+}
+
+static void op_jmp(CpuCtx *r, int mode, InstArg *arg) {
+	r->_pc = arg->_ea._value;
+}
+
+static void op_jsr(CpuCtx *r, int mode, InstArg *arg) {
+	r->_pc--;
+	r->_mem[0x100 + r->_sp--] = r->_pc >> 8;
+	r->_mem[0x100 + r->_sp--] = r->_pc & 0xff;
+	r->_pc = arg->_ea._value;
+}
+
+static void op_lda(CpuCtx *r, int mode, InstArg *arg) {
+	uint8_t value;
+	switch (mode) {
+	case MODE_IMMEDIATE:
+		value = arg->_imm._value;
+		break;
+	default:
+		value = r->_mem[arg->_ea._value];
+		break;
+	}
+	r->_a = value;
+	updateFlagsNz(r, r->_a);
+}
+
+static void op_ldx(CpuCtx *r, int mode, InstArg *arg) {
+	uint8_t value;
+	switch (mode) {
+	case MODE_IMMEDIATE:
+		value = arg->_imm._value;
+		break;
+	default:
+		value = r->_mem[arg->_ea._value];
+		break;
+	}
+	r->_x = value;
+	updateFlagsNz(r, r->_x);
+}
+
+static void op_ldy(CpuCtx *r, int mode, InstArg *arg) {
+	uint8_t value;
+	switch (mode) {
+	case MODE_IMMEDIATE:
+		value = arg->_imm._value;
+		break;
+	default:
+		value = r->_mem[arg->_ea._value];
+		break;
+	}
+	r->_y = value;
+	updateFlagsNz(r, r->_y);
+}
+
+static void op_lsr(CpuCtx *r, int mode, InstArg *arg) {
+	uint8_t *valuep;
+	switch (mode) {
+	case MODE_ACCUMULATOR:
+		valuep = &r->_a;
+		break;
+	default:
+		valuep = &r->_mem[arg->_ea._value];
+		break;
+	}
+	updateCarry(r, *valuep & 1);
+	*valuep >>= 1;
+	updateFlagsNz(r, *valuep);
+}
+
+static void op_nop(CpuCtx *r, int mode, InstArg *arg) {}
+
+static void op_ora(CpuCtx *r, int mode, InstArg *arg) {
+	uint8_t value;
+	switch (mode) {
+	case MODE_IMMEDIATE:
+		value = arg->_imm._value;
+		break;
+	default:
+		value = r->_mem[arg->_ea._value];
+		break;
+	}
+	r->_a |= value;
+	updateFlagsNz(r, r->_a);
+}
+
+static void op_pha(CpuCtx *r, int mode, InstArg *arg) {
+	r->_mem[0x100 + r->_sp--] = r->_a;
+}
+
+static void op_php(CpuCtx *r, int mode, InstArg *arg) {
+	r->_mem[0x100 + r->_sp--] = r->_flags & ~0x10;
+}
+
+static void op_pla(CpuCtx *r, int mode, InstArg *arg) {
+	r->_a = r->_mem[0x100 + ++r->_sp];
+	updateFlagsNz(r, r->_a);
+}
+
+static void op_plp(CpuCtx *r, int mode, InstArg *arg) {
+	r->_flags = r->_mem[0x100 + ++r->_sp];
+}
+
+static void op_rol(CpuCtx *r, int mode, InstArg *arg) {
+	uint8_t *valuep;
+	uint8_t old_flags;
+	switch (mode) {
+	case MODE_ACCUMULATOR:
+		valuep = &r->_a;
+		break;
+	default:
+		valuep = &r->_mem[arg->_ea._value];
+		break;
+	}
+	old_flags = r->_flags;
+	updateCarry(r, *valuep & 128);
+	*valuep <<= 1;
+	*valuep |= (old_flags & FLAG_C) != 0 ? 1 : 0;
+	updateFlagsNz(r, *valuep);
+}
+
+static void op_ror(CpuCtx *r, int mode, InstArg *arg) {
+	uint8_t *valuep;
+	uint8_t old_flags;
+	switch (mode) {
+	case MODE_ACCUMULATOR:
+		valuep = &r->_a;
+		break;
+	default:
+		valuep = &r->_mem[arg->_ea._value];
+		break;
+	}
+	old_flags = r->_flags;
+	updateCarry(r, *valuep & 1);
+	*valuep >>= 1;
+	*valuep |= (old_flags & FLAG_C) != 0 ? 128 : 0;
+	updateFlagsNz(r, *valuep);
+}
+
+static void op_rti(CpuCtx *r, int mode, InstArg *arg) {
+	r->_flags = r->_mem[0x100 + ++r->_sp];
+	r->_pc = r->_mem[0x100 + ++r->_sp];
+	r->_pc |= r->_mem[0x100 + ++r->_sp] << 8;
+}
+
+static void op_rts(CpuCtx *r, int mode, InstArg *arg) {
+	r->_pc = r->_mem[0x100 + ++r->_sp];
+	r->_pc |= r->_mem[0x100 + ++r->_sp] << 8;
+	r->_pc++;
+}
+
+static void op_sbc(CpuCtx *r, int mode, InstArg *arg) {
+	uint8_t value;
+	uint16_t result;
+	switch (mode) {
+	case MODE_IMMEDIATE:
+		value = arg->_imm._value;
+		break;
+	default:
+		value = r->_mem[arg->_ea._value];
+		break;
+	}
+	result = subtract(r, r->_flags & FLAG_C, r->_a, value);
+	update_overflow(r, !((r->_a & 0x80) ^ (value & 0x80)) && ((r->_a & 0x80) ^ (result & 0x80)));
+	r->_a = result & 0xff;
+	updateFlagsNz(r, r->_a);
+}
+
+static void op_sec(CpuCtx *r, int mode, InstArg *arg) {
+	r->_flags |= FLAG_C;
+}
+
+static void op_sed(CpuCtx *r, int mode, InstArg *arg) {
+	r->_flags |= FLAG_D;
+}
+
+static void op_sei(CpuCtx *r, int mode, InstArg *arg) {
+	r->_flags |= FLAG_I;
+}
+
+static void op_sta(CpuCtx *r, int mode, InstArg *arg) {
+	r->_mem[arg->_ea._value] = r->_a;
+}
+
+static void op_stx(CpuCtx *r, int mode, InstArg *arg) {
+	r->_mem[arg->_ea._value] = r->_x;
+}
+
+static void op_sty(CpuCtx *r, int mode, InstArg *arg) {
+	r->_mem[arg->_ea._value] = r->_y;
+}
+
+static void op_tax(CpuCtx *r, int mode, InstArg *arg) {
+	r->_x = r->_a;
+	updateFlagsNz(r, r->_x);
+}
+
+static void op_tay(CpuCtx *r, int mode, InstArg *arg) {
+	r->_y = r->_a;
+	updateFlagsNz(r, r->_y);
+}
+
+static void op_tsx(CpuCtx *r, int mode, InstArg *arg) {
+	r->_x = r->_sp;
+	updateFlagsNz(r, r->_x);
+}
+
+static void op_txa(CpuCtx *r, int mode, InstArg *arg) {
+	r->_a = r->_x;
+	updateFlagsNz(r, r->_a);
+}
+
+static void op_txs(CpuCtx *r, int mode, InstArg *arg) {
+	r->_sp = r->_x;
+}
+
+static void op_tya(CpuCtx *r, int mode, InstArg *arg) {
+	r->_a = r->_y;
+	updateFlagsNz(r, r->_a);
+}
+
+/* iAN */
+static void op_anc(CpuCtx *r, int mode, InstArg *arg) {
+	uint8_t value;
+	switch (mode) {
+	case MODE_IMMEDIATE:
+		value = arg->_imm._value;
+		break;
+	default:
+		value = r->_mem[arg->_ea._value];
+		break;
+	}
+	r->_a &= value;
+	if (r->_a & 0x80)
+		r->_flags |= FLAG_C;
+	updateFlagsNz(r, r->_a);
+}
+
+/* iAN */
+static void op_lax(CpuCtx *r, int mode, InstArg *arg) {
+	op_lda(r, mode, arg);
+	r->_x = r->_a;
+	updateFlagsNz(r, r->_x);
+}
+/* iAN */
+static void op_lae(CpuCtx *r, int mode, InstArg *arg) {
+	op_lda(r, mode, arg);
+	r->_x = r->_a;
+	r->_sp = r->_a;
+	updateFlagsNz(r, r->_a);
+}
+
+/* iAN */
+static void op_dcp(CpuCtx *r, int mode, InstArg *arg) {
+	op_dec(r, mode, arg);
+	op_cmp(r, mode, arg);
+}
+
+/* iAN */
+static void op_sax(CpuCtx *r, int mode, InstArg *arg) {
+	r->_a &= r->_x;
+	op_sta(r, mode, arg);
+}
+
+/* iAN */
+static void op_rla(CpuCtx *r, int mode, InstArg *arg) {
+	op_rol(r, mode, arg);
+	op_and(r, mode, arg);
+}
+
+/* iAN */
+static void op_rra(CpuCtx *r, int mode, InstArg *arg) {
+	op_rol(r, mode, arg);
+	op_adc(r, mode, arg);
+}
+
+/* iAN */
+static void op_isb(CpuCtx *r, int mode, InstArg *arg) {
+	op_inc(r, mode, arg);
+	op_sbc(r, mode, arg);
+}
+
+/* iAN */
+static void op_slo(CpuCtx *r, int mode, InstArg *arg) {
+	op_asl(r, mode, arg);
+	op_ora(r, mode, arg);
+}
+
+/* iAN */
+static void op_sbx(CpuCtx *r, int mode, InstArg *arg) {
+	/* immediate mode only: sbx #$ff */
+	r->_x &= r->_a;
+	r->_flags = (r->_flags & 0xfe) | (r->_x >= arg->_imm._value ? 1 : 0); /* fixed: Carry IS set by SBX but
+												  not used during subtraction */
+	r->_x -= arg->_imm._value;
+	updateFlagsNz(r, r->_x);
+}
+
+/* iAN */
+static void op_sre(CpuCtx *r, int mode, InstArg *arg) {
+	op_lsr(r, mode, arg);
+	op_eor(r, mode, arg);
+}
+/* iAN */
+static void
+op_asr(CpuCtx *r, int mode,
+	   InstArg *arg) { /* first A AND #immediate, then LSR A */
+	op_and(r, MODE_IMMEDIATE, arg);
+	op_lsr(r, MODE_ACCUMULATOR, arg);
+}
+/* iAN */
+static void op_ane(CpuCtx *r, int mode, InstArg *arg) {
+	r->_a |= 0xee;
+	r->_a &= r->_x;
+	op_and(r, MODE_IMMEDIATE, arg);
+}
+/* iAN */
+static void op_lxa(CpuCtx *r, int mode, InstArg *arg) {
+	r->_a |= 0xee;
+	op_and(r, MODE_IMMEDIATE, arg);
+	r->_x = r->_a;
+}
+
+static OpInfo op_adc_o = {&op_adc, "adc"};
+static OpInfo op_anc_o = {&op_anc, "anc"};
+static OpInfo op_and_o = {&op_and, "and"};
+static OpInfo op_ane_o = {&op_ane, "ane"};
+static OpInfo op_asl_o = {&op_asl, "asl"};
+static OpInfo op_asr_o = {&op_asr, "asr"};
+static OpInfo op_bcc_o = {&op_bcc, "bcc"};
+static OpInfo op_bcs_o = {&op_bcs, "bcs"};
+static OpInfo op_beq_o = {&op_beq, "beq"};
+static OpInfo op_bit_o = {&op_bit, "bit"};
+static OpInfo op_bmi_o = {&op_bmi, "bmi"};
+static OpInfo op_bne_o = {&op_bne, "bne"};
+static OpInfo op_bpl_o = {&op_bpl, "bpl"};
+static OpInfo op_brk_o = {&op_brk, "brk"};
+static OpInfo op_bvc_o = {&op_bvc, "bvc"};
+static OpInfo op_bvs_o = {&op_bvs, "bvs"};
+static OpInfo op_clc_o = {&op_clc, "clc"};
+
+static OpInfo op_cld_o = {&op_cld, "cld"};
+static OpInfo op_cli_o = {&op_cli, "cli"};
+static OpInfo op_clv_o = {&op_clv, "clv"};
+static OpInfo op_cmp_o = {&op_cmp, "cmp"};
+static OpInfo op_cpx_o = {&op_cpx, "cpx"};
+static OpInfo op_cpy_o = {&op_cpy, "cpy"};
+static OpInfo op_dcp_o = {&op_dcp, "dcp"};
+static OpInfo op_dec_o = {&op_dec, "dec"};
+static OpInfo op_dex_o = {&op_dex, "dex"};
+static OpInfo op_dey_o = {&op_dey, "dey"};
+static OpInfo op_eor_o = {&op_eor, "eor"};
+static OpInfo op_inc_o = {&op_inc, "inc"};
+static OpInfo op_isb_o = {&op_isb, "isb"};
+static OpInfo op_inx_o = {&op_inx, "inx"};
+static OpInfo op_iny_o = {&op_iny, "iny"};
+static OpInfo op_jmp_o = {&op_jmp, "jmp"};
+
+static OpInfo op_jsr_o = {&op_jsr, "jsr"};
+static OpInfo op_lda_o = {&op_lda, "lda"};
+static OpInfo op_ldx_o = {&op_ldx, "ldx"};
+static OpInfo op_ldy_o = {&op_ldy, "ldy"};
+static OpInfo op_lsr_o = {&op_lsr, "lsr"};
+static OpInfo op_nop_o = {&op_nop, "nop"};
+static OpInfo op_ora_o = {&op_ora, "ora"};
+static OpInfo op_pha_o = {&op_pha, "pha"};
+static OpInfo op_php_o = {&op_php, "php"};
+static OpInfo op_pla_o = {&op_pla, "pla"};
+static OpInfo op_plp_o = {&op_plp, "plp"};
+static OpInfo op_rol_o = {&op_rol, "rol"};
+static OpInfo op_rla_o = {&op_rla, "rla"};
+static OpInfo op_ror_o = {&op_ror, "ror"};
+static OpInfo op_rti_o = {&op_rti, "rti"};
+static OpInfo op_rra_o = {&op_rra, "rra"};
+
+static OpInfo op_rts_o = {&op_rts, "rts"};
+static OpInfo op_sbc_o = {&op_sbc, "sbc"};
+static OpInfo op_sbx_o = {&op_sbx, "sbx"};
+static OpInfo op_sec_o = {&op_sec, "sec"};
+static OpInfo op_sed_o = {&op_sed, "sed"};
+static OpInfo op_sei_o = {&op_sei, "sei"};
+static OpInfo op_slo_o = {&op_slo, "slo"};
+static OpInfo op_sta_o = {&op_sta, "sta"};
+static OpInfo op_stx_o = {&op_stx, "stx"};
+static OpInfo op_sty_o = {&op_sty, "sty"};
+static OpInfo op_lax_o = {&op_lax, "lax"};
+static OpInfo op_lae_o = {&op_lae, "lae"};
+static OpInfo op_lxa_o = {&op_lxa, "lxa"};
+static OpInfo op_tax_o = {&op_tax, "tax"};
+static OpInfo op_sax_o = {&op_sax, "sax"};
+static OpInfo op_sre_o = {&op_sre, "sre"};
+static OpInfo op_tay_o = {&op_tay, "tay"};
+static OpInfo op_tsx_o = {&op_tsx, "tsx"};
+static OpInfo op_txa_o = {&op_txa, "txa"};
+static OpInfo op_txs_o = {&op_txs, "txs"};
+static OpInfo op_tya_o = {&op_tya, "tya"};
+
+#define NULL_OP { nullptr, nullptr, 0 }
+
+static InstInfo g_ops[256] = {
+	/* 0x00 */
+	{ &op_brk_o, &mode_imp_o,	7 },
+	{ &op_ora_o, &mode_indx_o,	6 },
+	NULL_OP,
+	NULL_OP,
+	{ &op_nop_o, &mode_zp_o,	3 }, /* $04 nop $ff */
+	{ &op_ora_o, &mode_zp_o,	3 },
+	{ &op_asl_o, &mode_zp_o,	5 },
+	{ &op_slo_o, &mode_zp_o,	5 }, /* $07 slo $ff */
+	{ &op_php_o, &mode_imp_o,	3 },
+	{ &op_ora_o, &mode_imm_o,	2 },
+	{ &op_asl_o, &mode_acc_o,	2 },
+	{ &op_anc_o, &mode_imm_o,	2 }, /* $0b anc #$ff */
+	{ &op_nop_o, &mode_abs_o,	4 }, /* $0c nop $ffff */
+	{ &op_ora_o, &mode_abs_o,	4 },
+	{ &op_asl_o, &mode_abs_o,	6 },
+	{ &op_slo_o, &mode_abs_o,	6 }, /* $0f slo $ffff */
+	/* 0x10 */
+	{ &op_bpl_o, &mode_rel_o,	2 },
+	{ &op_ora_o, &mode_indy_o,	5 },
+	NULL_OP,
+	NULL_OP,
+	{ &op_nop_o, &mode_zpx_o,	4 }, /* $14 nop $ff,x */
+	{ &op_ora_o, &mode_zpx_o,	4 },
+	{ &op_asl_o, &mode_zpx_o,	6 },
+	NULL_OP,
+	{ &op_clc_o, &mode_imp_o,	2 },
+	{ &op_ora_o, &mode_absy_o,	4 },
+	{ &op_nop_o, &mode_imp_o,	2 },  /* $1a nop */
+	{ &op_slo_o, &mode_absy_o,	4 }, /* $1b slo $ffff,y */
+	{ &op_nop_o, &mode_absx_o,	4 }, /* $1c nop $ffff,x */
+	{ &op_ora_o, &mode_absx_o,	4 },
+	{ &op_asl_o, &mode_absx_o,	7 },
+	{ &op_slo_o, &mode_absx_o,	7 }, /* $1f slo $ffff,x */
+	/* 0x20 */
+	{ &op_jsr_o, &mode_abs_o,	6 },
+	{ &op_and_o, &mode_indx_o,	6 },
+	NULL_OP,
+	{ &op_rla_o, &mode_indx_o,	8 }, /* $23 rla ($ff,x) */
+	{ &op_bit_o, &mode_zp_o,	3 },
+	{ &op_and_o, &mode_zp_o,	3 },
+	{ &op_rol_o, &mode_zp_o,	5 },
+	{ &op_rla_o, &mode_zp_o,	5 }, /* $27 rla $ff */
+	{ &op_plp_o, &mode_imp_o,	4 },
+	{ &op_and_o, &mode_imm_o,	2 },
+	{ &op_rol_o, &mode_acc_o,	2 },
+	{ &op_anc_o, &mode_imm_o,	2 }, /* $2b anc #$ff */
+	{ &op_bit_o, &mode_abs_o,	4 },
+	{ &op_and_o, &mode_abs_o,	4 },
+	{ &op_rol_o, &mode_abs_o,	6 },
+	{ &op_rla_o, &mode_abs_o,	6 }, /* $2f rla $ffff */
+	/* 0x30 */
+	{ &op_bmi_o, &mode_rel_o,	2 },
+	{ &op_and_o, &mode_indy_o,	5 },
+	NULL_OP,
+	{ &op_rla_o, &mode_indy_o,	8 }, /* $33 rla ($ff),y  */
+	{ &op_nop_o, &mode_zpx_o,	4 },  /* $34 nop $ff,x */
+	{ &op_and_o, &mode_zpx_o,	4 },
+	{ &op_rol_o, &mode_zpx_o,	6 },
+	{ &op_rla_o, &mode_zpx_o,	6 }, /* $37 rla $ff,x */
+	{ &op_sec_o, &mode_imp_o,	2 },
+	{ &op_and_o, &mode_absy_o,	4 },
+	{ &op_nop_o, &mode_imp_o,	2 },  /* $3a nop */
+	{ &op_rla_o, &mode_absy_o,	7 }, /* $3b rla $ffff,y */
+	{ &op_nop_o, &mode_absx_o,	7 }, /* $3c nop $ffff,x */
+	{ &op_and_o, &mode_absx_o,	4 },
+	{ &op_rol_o, &mode_absx_o,	7 },
+	{ &op_rla_o, &mode_absx_o,	7 }, /* $3f rla $ffff,x */
+	/* 0x40 */
+	{ &op_rti_o, &mode_imp_o,	6 },
+	{ &op_eor_o, &mode_indx_o,	6 },
+	NULL_OP,
+	{ &op_sre_o, &mode_indx_o,	6 }, /* $43 sre ($ff,x) */
+	{ &op_nop_o, &mode_zp_o,	3 },   /* $44 nop $ff */
+	{ &op_eor_o, &mode_zp_o,	3 },
+	{ &op_lsr_o, &mode_zp_o,	5 },
+	{ &op_sre_o, &mode_zp_o,	5 }, /* $47 sre $ff */
+	{ &op_pha_o, &mode_imp_o,	3 },
+	{ &op_eor_o, &mode_imm_o,	2 },
+	{ &op_lsr_o, &mode_acc_o,	2 },
+	{ &op_asr_o, &mode_imm_o,	2 }, /* $4b asr #$ff */
+	{ &op_jmp_o, &mode_abs_o,	3 },
+	{ &op_eor_o, &mode_abs_o,	4 },
+	{ &op_lsr_o, &mode_abs_o,	6 },
+	{ &op_sre_o, &mode_abs_o,	6 }, /* $4f sre $ffff */
+	/* 0x50 */
+	{ &op_bvc_o, &mode_rel_o,	2 },
+	{ &op_eor_o, &mode_indy_o,	5 },
+	NULL_OP,
+	NULL_OP,
+	{ &op_nop_o, &mode_zpx_o,	4 }, /* $54 nop $ff,x */
+	{ &op_eor_o, &mode_zpx_o,	4 }, /* fix: eor $ff,x takes 4 cycles*/
+	{ &op_lsr_o, &mode_zpx_o,	6 },
+	{ &op_sre_o, &mode_zpx_o,	6 }, /* $57 sre $ff,x */
+	{ &op_cli_o, &mode_imp_o,	2 },
+	{ &op_eor_o, &mode_absy_o,	4 },
+	{ &op_nop_o, &mode_imp_o,	2 },  /* $5a nop */
+	{ &op_sre_o, &mode_absy_o,	7 }, /* $5b sre $ffff,y */
+	{ &op_nop_o, &mode_absx_o,	4 }, /* $5c nop $ffff,x */
+	{ &op_eor_o, &mode_absx_o,	4 },
+	{ &op_lsr_o, &mode_absx_o,	7 },
+	{ &op_sre_o, &mode_absx_o,	7 }, /* $5f sre $ffff,x */
+	/* 0x60 */
+	{ &op_rts_o, &mode_imp_o,	6 },
+	{ &op_adc_o, &mode_indx_o,	6 },
+	NULL_OP,
+	{ &op_rra_o, &mode_indx_o,	8 }, /* $63 rra ($ff,x) */
+	{ &op_nop_o, &mode_zp_o,	3 },   /* $64 nop $ff */
+	{ &op_adc_o, &mode_zp_o,	3 },
+	{ &op_ror_o, &mode_zp_o,	5 },
+	{ &op_rra_o, &mode_zp_o,	5 }, /* $67 rra $ff */
+	{ &op_pla_o, &mode_imp_o,	4 },
+	{ &op_adc_o, &mode_imm_o,	2 },
+	{ &op_ror_o, &mode_acc_o,	2 },
+	NULL_OP,                     /* fix: $6b ARR (todo?) */
+	{ &op_jmp_o, &mode_ind_o,	5 }, /* fix: $6c JMP ($FFFF) */
+	{ &op_adc_o, &mode_abs_o,	4 },
+	{ &op_ror_o, &mode_abs_o,	6 },
+	{ &op_rra_o, &mode_abs_o,	6 }, /* $6f rra $ffff */
+	/* 0x70 */
+	{ &op_bvs_o, &mode_rel_o,	2 },
+	{ &op_adc_o, &mode_indy_o,	5 },
+	NULL_OP,
+	{ &op_rra_o, &mode_indy_o,	8 }, /* $73 rra ($ff),y */
+	{ &op_nop_o, &mode_zpx_o,	4 },  /* $74 nop $ff,x */
+	{ &op_adc_o, &mode_zpx_o,	4 },
+	{ &op_ror_o, &mode_zpx_o,	6 },
+	{ &op_rra_o, &mode_zpx_o,	6 }, /* $77 rra $ff,x */
+	{ &op_sei_o, &mode_imp_o,	2 },
+	{ &op_adc_o, &mode_absy_o,	4 },
+	{ &op_nop_o, &mode_imp_o,	2 },  /* $7a nop */
+	{ &op_rra_o, &mode_absy_o,	7 }, /* $7b rra $ffff,y */
+	{ &op_nop_o, &mode_absx_o,	4 }, /* $7c nop $ffff,x */
+	{ &op_adc_o, &mode_absx_o,	4 },
+	{ &op_ror_o, &mode_absx_o,	7 },
+	{ &op_rra_o, &mode_absx_o,	7 }, /* $7f rra $ffff,x */
+	/* 0x80 */
+	{ &op_nop_o, &mode_imm_o,	2 }, /* $80 nop #$ff */
+	{ &op_sta_o, &mode_indx_o,	6 },
+	{ &op_nop_o, &mode_imm_o,	2 },  /* $82 nop #$ff */
+	{ &op_sax_o, &mode_indx_o,	6 }, /* $83 sax ($ff,x) */
+	{ &op_sty_o, &mode_zp_o,	3 },
+	{ &op_sta_o, &mode_zp_o,	3 },
+	{ &op_stx_o, &mode_zp_o,	3 },
+	{ &op_sax_o, &mode_zp_o,	3 }, /* $87 sax $ff */
+	{ &op_dey_o, &mode_imp_o,	2 },
+	{ &op_nop_o, &mode_imm_o,	2 }, /* $89 nop #$ff */
+	{ &op_txa_o, &mode_imp_o,	2 },
+	{ &op_ane_o, &mode_imm_o,	2 }, /* $8b ane #$ff */
+	{ &op_sty_o, &mode_abs_o,	4 },
+	{ &op_sta_o, &mode_abs_o,	4 },
+	{ &op_stx_o, &mode_abs_o,	4 },
+	{ &op_sax_o, &mode_abs_o,	4 }, /* $8f sax $ffff */
+	/* 0x90 */
+	{ &op_bcc_o, &mode_rel_o,	2 },
+	{ &op_sta_o, &mode_indy_o,	6 },
+	NULL_OP,
+	NULL_OP,
+	{ &op_sty_o, &mode_zpx_o,	4 },
+	{ &op_sta_o, &mode_zpx_o,	4 },
+	{ &op_stx_o, &mode_zpy_o,	4 },
+	{ &op_sax_o, &mode_zpy_o,	4 }, /* $97 sax $ff,y */
+	{ &op_tya_o, &mode_imp_o,	2 },
+	{ &op_sta_o, &mode_absy_o,	5 },
+	{ &op_txs_o, &mode_imp_o,	2 },
+	NULL_OP,
+	NULL_OP,
+	{ &op_sta_o, &mode_absx_o,	5 },
+	NULL_OP,
+	NULL_OP,
+	/* 0xa0 */
+	{ &op_ldy_o, &mode_imm_o,	2 },
+	{ &op_lda_o, &mode_indx_o,	6 },
+	{ &op_ldx_o, &mode_imm_o,	2 },
+	{ &op_lax_o, &mode_indx_o,	6 }, /* $a3 lax ($ff,x) */
+	{ &op_ldy_o, &mode_zp_o,	3 },
+	{ &op_lda_o, &mode_zp_o,	3 },
+	{ &op_ldx_o, &mode_zp_o,	3 },
+	{ &op_lax_o, &mode_zp_o,	3 }, /* $a7 lax $ff */
+	{ &op_tay_o, &mode_imp_o,	2 },
+	{ &op_lda_o, &mode_imm_o,	2 },
+	{ &op_tax_o, &mode_imp_o,	2 },
+	{ &op_lxa_o, &mode_imm_o,	2 }, /* $ab lxa #$ff */
+	{ &op_ldy_o, &mode_abs_o,	4 },
+	{ &op_lda_o, &mode_abs_o,	4 },
+	{ &op_ldx_o, &mode_abs_o,	4 },
+	{ &op_lax_o, &mode_abs_o,	4 }, /* $af lax $ffff */
+	/* 0xb0 */
+	{ &op_bcs_o, &mode_rel_o,	2 },
+	{ &op_lda_o, &mode_indy_o,	5 },
+	NULL_OP,
+	{ &op_lax_o, &mode_indy_o,	5 }, /* $b3 lax ($ff),y */
+	{ &op_ldy_o, &mode_zpx_o,	4 },
+	{ &op_lda_o, &mode_zpx_o,	4 },
+	{ &op_ldx_o, &mode_zpy_o,	4 },
+	{ &op_lax_o, &mode_zpy_o,	4 }, /* $b7 lax $ff,y */
+	{ &op_clv_o, &mode_imp_o,	2 },
+	{ &op_lda_o, &mode_absy_o,	4 },
+	{ &op_tsx_o, &mode_imp_o,	2 },
+	{ &op_lae_o, &mode_absy_o,	4 }, /* $bb lae $ffff,y */
+	{ &op_ldy_o, &mode_absx_o,	4 },
+	{ &op_lda_o, &mode_absx_o,	4 },
+	{ &op_ldx_o, &mode_absy_o,	4 },
+	{ &op_lax_o, &mode_absy_o,	4 }, /* $bf lax $ffff,y */
+	/* 0xc0 */
+	{ &op_cpy_o, &mode_imm_o,	2 },
+	{ &op_cmp_o, &mode_indx_o,	6 },
+	{ &op_nop_o, &mode_imm_o,	2 },  /* $c2 nop #$ff */
+	{ &op_dcp_o, &mode_indx_o,	8 }, /* $c3 dcp ($ff,x) */
+	{ &op_cpy_o, &mode_zp_o,	3 },
+	{ &op_cmp_o, &mode_zp_o,	3 },
+	{ &op_dec_o, &mode_zp_o,	5 },
+	{ &op_dcp_o, &mode_zp_o,	5 }, /* $c7 dcp $FF */
+	{ &op_iny_o, &mode_imp_o,	2 },
+	{ &op_cmp_o, &mode_imm_o,	2 },
+	{ &op_dex_o, &mode_imp_o,	2 },
+	{ &op_sbx_o, &mode_imm_o,	2 }, /* $cb sbx #$ff */
+	{ &op_cpy_o, &mode_abs_o,	4 },
+	{ &op_cmp_o, &mode_abs_o,	4 },
+	{ &op_dec_o, &mode_abs_o,	6 },
+	{ &op_dcp_o, &mode_abs_o,	6 }, /* $cf dcp $ffff */
+	/* 0xd0 */
+	{ &op_bne_o, &mode_rel_o,	2 },
+	{ &op_cmp_o, &mode_indy_o,	5 },
+	NULL_OP,
+	{ &op_dcp_o, &mode_indy_o,	8 }, /* $d3 dcp ($ff),y */
+	{ &op_nop_o, &mode_zpx_o,	4 },  /* $d4 nop $ff,x */
+	{ &op_cmp_o, &mode_zpx_o,	4 },
+	{ &op_dec_o, &mode_zpx_o,	6 },
+	{ &op_dcp_o, &mode_zpx_o,	6 }, /* $d7 dcp $ff,x */
+	{ &op_cld_o, &mode_imp_o,	2 },
+	{ &op_cmp_o, &mode_absy_o,	4 },
+	{ &op_nop_o, &mode_imp_o,	2 },  /* $da nop */
+	{ &op_dcp_o, &mode_absy_o,	7 }, /* $db dcp $ffff,y */
+	{ &op_nop_o, &mode_absx_o,	4 }, /* $dc nop $ffff,x */
+	{ &op_cmp_o, &mode_absx_o,	4 },
+	{ &op_dec_o, &mode_absx_o,	7 },
+	{ &op_dcp_o, &mode_absx_o,	7 }, /* $df dcp $ffff,x */
+	/* 0xe0 */
+	{ &op_cpx_o, &mode_imm_o,	2 },
+	{ &op_sbc_o, &mode_indx_o,	6 },
+	{ &op_nop_o, &mode_imm_o,	2 },  /* $e2 nop #$ff */
+	{ &op_isb_o, &mode_indx_o,	8 }, /* $e3 isb ($ff,x) */
+	{ &op_cpx_o, &mode_zp_o,	3 },
+	{ &op_sbc_o, &mode_zp_o,	3 },
+	{ &op_inc_o, &mode_zp_o,	5 },
+	{ &op_isb_o, &mode_zp_o,	5 }, /* $e7 isb $ff */
+	{ &op_inx_o, &mode_imp_o,	2 },
+	{ &op_sbc_o, &mode_imm_o,	2 },
+	{ &op_nop_o, &mode_imp_o,	2 },
+	{ &op_sbc_o, &mode_imm_o,	2 }, /* $eb sbc #$ff */
+	{ &op_cpx_o, &mode_abs_o,	4 },
+	{ &op_sbc_o, &mode_abs_o,	4 },
+	{ &op_inc_o, &mode_abs_o,	6 },
+	{ &op_isb_o, &mode_abs_o,	6 }, /* $ef isb $ffff */
+	/* 0xf0 */
+	{ &op_beq_o, &mode_rel_o,	2 },
+	{ &op_sbc_o, &mode_indy_o,	5 },
+	NULL_OP,
+	{ &op_isb_o, &mode_indy_o,	8 }, /* $f3 isb ($ff),y */
+	{ &op_nop_o, &mode_zpx_o,	4 },  /* $f4 nop $ff,x */
+	{ &op_sbc_o, &mode_zpx_o,	4 },
+	{ &op_inc_o, &mode_zpx_o,	6 },
+	{ &op_isb_o, &mode_zpx_o,	6 }, /* $f7 isb $ff,x */
+	{ &op_sed_o, &mode_imp_o,	2 },
+	{ &op_sbc_o, &mode_absy_o,	4 },
+	{ &op_nop_o, &mode_imp_o,	2 },  /* $fa nop */
+	{ &op_isb_o, &mode_absy_o,	7 }, /* $fb isb $ffff,y */
+	{ &op_nop_o, &mode_absx_o,	7 }, /* $fc nop $ffff,x */
+	{ &op_sbc_o, &mode_absx_o,	4 },
+	{ &op_inc_o, &mode_absx_o,	7 },
+	{ &op_isb_o, &mode_absx_o,	7 }, /* $ff isb $ffff,x */
+};
+
+int flipfire(void) {
+	_G(_retfire) ^= 0x90;
+	return _G(_retfire);
+}
+int flipspace(void) {
+	_G(_retspace) ^= 0x10;
+	return _G(_retspace);
+}
+
 int nextInst(CpuCtx* r) {
+	InstArg arg[1];
+	int oldpc = r->_pc;
+	int opCode = r->_mem[r->_pc];
+	InstInfo *info = g_ops + opCode;
+	int mode, WriteToIO = 0;
+	int bt = 0, br;
+	if (info->_op == nullptr) {
+		return 1;
+	}
+	mode = info->_mode->_f(r, arg);
+
+	/* iAN: only if RAM is not visible there! */
+	if (((r->_mem[1] & 0x7) >= 0x5) && ((r->_mem[1] & 0x07) <= 0x7)) {
+		if (arg->_ea._value >= 0xd000 && arg->_ea._value < 0xe000) {
+			/* is this an absolute sta, stx or sty to the IO-area? */
+			/* iAN: added all possible writing opcodes */
+			if (opCode == 0x0E || /*ASL $ffff  */
+				opCode == 0x1E || /*ASL $ffff,X*/
+				opCode == 0xCE || /*DEC $ffff  */
+				opCode == 0xDE || /*DEC $ffff,X*/
+				opCode == 0xEE || /*INC $ffff  */
+				opCode == 0xFE || /*INC $ffff,X*/
+				opCode == 0x4E || /*LSR $ffff  */
+				opCode == 0x5E || /*LSR $ffff,X*/
+				opCode == 0x2E || /*ROL $ffff  */
+				opCode == 0x3E || /*ROL $ffff,X*/
+				opCode == 0x6E || /*ROR $ffff  */
+				opCode == 0x7E || /*ROR $ffff,X*/
+				opCode == 0x8D || /*STA $ffff  */
+				opCode == 0x9D || /*STA $ffff,X*/
+				opCode == 0x99 || /*STA $ffff,Y*/
+				opCode == 0x91 || /*STA ($ff),Y*/
+				opCode == 0x8E || /*STX $ffff  */
+				opCode == 0x8C    /*STY $ffff  */
+			) {
+				r->_cycles += g_ops[opCode]._cycles;
+				/* ignore it, its probably an effect */
+				/* try to keep updated at least a copy of $d011 */
+				if (arg->_ea._value == 0xd011) {
+					switch (opCode) {
+					case 0x8D:
+						_G(_byted011)[0] = r->_a & 0x7f;
+					case 0x8E:
+						_G(_byted011)[0] = r->_x & 0x7f;
+					case 0x8C:
+						_G(_byted011)[0] = r->_y & 0x7f;
+					}
+				}
+				WriteToIO = 1;
+			} else {
+				_G(_byted011)[1] = (r->_cycles / 0x3f) % 0x157;
+				_G(_byted011)[0] = (_G(_byted011)[0] & 0x7f) | ((_G(_byted011)[1] & 0x100) >> 1);
+				_G(_byted011)[1] &= 0xff;
+				switch (opCode) {
+				case 0xad:
+				case 0xaf: /* lda $ffff / lax $ffff */
+
+					if ((arg->_ea._value == 0xd011) || (arg->_ea._value == 0xd012)) {
+						r->_cycles += g_ops[opCode]._cycles;
+						r->_a = _G(_byted011)[arg->_ea._value - 0xd011];
+						if (opCode == 0xaf)
+							r->_x = r->_a;
+						updateFlagsNz(r, r->_a);
+						WriteToIO = 5;
+						break;
+					}
+
+					/* intros: simulate space */
+					if (arg->_ea._value == 0xdc00 || arg->_ea._value == 0xdc01) {
+						r->_cycles += g_ops[opCode]._cycles;
+						if (arg->_ea._value == 0xdc00)
+							r->_a = flipfire();
+						else
+							r->_a = flipspace();
+						if (opCode == 0xaf)
+							r->_x = r->_a;
+						updateFlagsNz(r, r->_a);
+						WriteToIO = 6;
+						break;
+					}
+
+					if (arg->_ea._value >= 0xdd01 && arg->_ea._value <= 0xdd0f) {
+						r->_cycles += g_ops[opCode]._cycles;
+						r->_a = 0xff;
+						if (opCode == 0xaf)
+							r->_x = r->_a;
+						updateFlagsNz(r, r->_a);
+						WriteToIO = 2;
+						break;
+					}
+					break;
+				case 0x2d: /* and $ffff */
+
+					/* intros: simulate space */
+					if (arg->_ea._value == 0xdc00 || arg->_ea._value == 0xdc01) {
+						r->_cycles += g_ops[opCode]._cycles;
+						if (arg->_ea._value == 0xdc00)
+							r->_a &= flipfire();
+						else
+							r->_a &= flipspace();
+
+						updateFlagsNz(r, r->_a);
+						WriteToIO = 6;
+						break;
+					}
+					break;
+				case 0xae: /* ldx $ffff */
+
+					if ((arg->_ea._value == 0xd011) || (arg->_ea._value == 0xd012)) {
+						r->_cycles += g_ops[opCode]._cycles;
+						r->_x = _G(_byted011)[arg->_ea._value - 0xd011];
+						updateFlagsNz(r, r->_x);
+						WriteToIO = 5;
+						break;
+					}
+					if (arg->_ea._value == 0xdc00 || arg->_ea._value == 0xdc01) {
+						r->_cycles += g_ops[opCode]._cycles;
+						if (arg->_ea._value == 0xdc00)
+							r->_x = flipfire();
+						else
+							r->_x = flipspace();
+						updateFlagsNz(r, r->_x);
+						WriteToIO = 6;
+						break;
+					}
+					break;
+				case 0xac: /* ldy $ffff */
+
+					if ((arg->_ea._value == 0xd011) || (arg->_ea._value == 0xd012)) {
+						r->_cycles += g_ops[opCode]._cycles;
+						r->_y = _G(_byted011)[arg->_ea._value - 0xd011];
+						updateFlagsNz(r, r->_y);
+						WriteToIO = 5;
+						break;
+					}
+					if (arg->_ea._value == 0xdc00 || arg->_ea._value == 0xdc01) {
+						r->_cycles += g_ops[opCode]._cycles;
+						if (arg->_ea._value == 0xdc00)
+							r->_y = flipfire();
+						else
+							r->_y = flipspace();
+						updateFlagsNz(r, r->_y);
+						WriteToIO = 6;
+						break;
+					}
+					break;
+
+				case 0x2c: /* bit $d011 */
+
+					if ((arg->_ea._value == 0xd011) || (arg->_ea._value == 0xd012)) {
+						r->_cycles += g_ops[opCode]._cycles;
+						bt = _G(_byted011)[arg->_ea._value - 0xd011];
+						r->_flags &= ~(FLAG_N | FLAG_V | FLAG_Z);
+						r->_flags |= (bt & FLAG_N) != 0 ? FLAG_N : 0;
+						r->_flags |= (bt & FLAG_V) != 0 ? FLAG_V : 0;
+						r->_flags |= (bt & r->_a) == 0 ? FLAG_Z : 0;
+						WriteToIO = 3;
+					}
+					break;
+
+				case 0xcd: /* cmp $ffff */
+				case 0xec: /* cpx $ffff */
+				case 0xcc: /* cpy $ffff */
+					if ((arg->_ea._value == 0xd011) || (arg->_ea._value == 0xd012)) {
+						r->_cycles += g_ops[opCode]._cycles;
+						bt = _G(_byted011)[arg->_ea._value - 0xd011];
+						br = r->_a;
+						if (opCode == 0xec)
+							br = r->_x;
+						if (opCode == 0xcc)
+							br = r->_y;
+						subtract(r, 1, br, bt);
+						WriteToIO = 4;
+						break;
+					}
+					/* intros: simulate space */
+					if (arg->_ea._value == 0xdc00 || arg->_ea._value == 0xdc01) {
+						r->_cycles += g_ops[opCode]._cycles;
+						br = r->_a;
+						if (opCode == 0xec)
+							br = r->_x;
+						if (opCode == 0xcc)
+							br = r->_y;
+						if (arg->_ea._value == 0xdc00)
+							bt = flipfire();
+						else
+							bt = flipspace();
+						subtract(r, 1, br, bt);
+						WriteToIO = 6;
+						break;
+					}
+					break;
+				}
+			}
+		}
+	}
+
+	info->_op->_f(r, mode, arg);
+	r->_cycles += info->_cycles;
+	if (opCode == 0) {
+		return 1;
+	}
 	return 0;
 }
 


Commit: e581ff07140ad8457a3a488a6cbe6aa107744842
    https://github.com/scummvm/scummvm/commit/e581ff07140ad8457a3a488a6cbe6aa107744842
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Implement strToInt

Changed paths:
    engines/glk/scott/unp64/exo_util.cpp


diff --git a/engines/glk/scott/unp64/exo_util.cpp b/engines/glk/scott/unp64/exo_util.cpp
index 386dbd5737f..dfd1f5b794b 100644
--- a/engines/glk/scott/unp64/exo_util.cpp
+++ b/engines/glk/scott/unp64/exo_util.cpp
@@ -59,7 +59,41 @@ void loadData(uint8_t *data, size_t dataLength, unsigned char mem[65536], LoadIn
 }
 
 int strToInt(const char *str, int *value) {
-	return 0;
+	int status = 0;
+	do {
+		char *strEnd;
+		long lval;
+
+		/* base 0 is auto detect */
+		int base = 0;
+
+		if (*str == '\0') {
+			/* no string to parse */
+			status = 1;
+			break;
+		}
+
+		if (*str == '$') {
+			/* a $ prefix specifies base 16 */
+			++str;
+			base = 16;
+		}
+
+		lval = strtol(str, &strEnd, base);
+
+		if (*strEnd != '\0') {
+			/* there is garbage in the string */
+			status = 1;
+			break;
+		}
+
+		if (value != nullptr) {
+			/* all is well, set the out parameter */
+			*value = static_cast<int>(lval);
+		}
+	} while (0);
+
+	return status;
 }
 
 } // End of namespace Scott


Commit: acccd129c96f1ee4e4b8789d8f08cd7069b23101
    https://github.com/scummvm/scummvm/commit/acccd129c96f1ee4e4b8789d8f08cd7069b23101
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Implement loadData

Changed paths:
    engines/glk/scott/unp64/exo_util.cpp
    engines/glk/scott/unp64/exo_util.h


diff --git a/engines/glk/scott/unp64/exo_util.cpp b/engines/glk/scott/unp64/exo_util.cpp
index dfd1f5b794b..b388fba340a 100644
--- a/engines/glk/scott/unp64/exo_util.cpp
+++ b/engines/glk/scott/unp64/exo_util.cpp
@@ -46,6 +46,7 @@
  *
  */
 
+#include "common/util.h"
 #include "glk/scott/unp64/exo_util.h"
 
 namespace Glk {
@@ -55,7 +56,23 @@ int findSys(const byte *buf, int target) {
 	return 0;
 }
 
-void loadData(uint8_t *data, size_t dataLength, unsigned char mem[65536], LoadInfo *info) {
+static void loadPrgData(byte mem[65536], uint8_t *data, size_t dataLength, LoadInfo *info) {
+	int len = MIN(65536 - info->_start, static_cast<int>(dataLength));
+	memcpy(mem + info->_start, data, len);
+
+	info->_end = info->_start + len;
+	info->_basicVarStart = -1;
+	info->_run = -1;
+	if (info->_basicTxtStart >= info->_start && info->_basicTxtStart < info->_end) {
+		info->_basicVarStart = info->_end;
+	}
+}
+
+void loadData(uint8_t *data, size_t dataLength, byte mem[65536], LoadInfo *info) {
+	int load = data[0] + data[1] * 0x100;
+
+	info->_start = load;
+	loadPrgData(mem, data + 2, dataLength - 2, info);
 }
 
 int strToInt(const char *str, int *value) {
diff --git a/engines/glk/scott/unp64/exo_util.h b/engines/glk/scott/unp64/exo_util.h
index 319a9ef613c..586f07592b1 100644
--- a/engines/glk/scott/unp64/exo_util.h
+++ b/engines/glk/scott/unp64/exo_util.h
@@ -64,7 +64,7 @@ struct LoadInfo {
 
 int findSys(const byte *buf, int target);
 
-void loadData(uint8_t *data, size_t dataLength, unsigned char mem[65536], LoadInfo *info);
+void loadData(uint8_t *data, size_t dataLength, byte mem[65536], LoadInfo *info);
 
 int strToInt(const char *str, int *value);
 


Commit: b3e54065c9db323509e8fcfec8863246311d9318
    https://github.com/scummvm/scummvm/commit/b3e54065c9db323509e8fcfec8863246311d9318
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Implement findSys

Changed paths:
    engines/glk/scott/unp64/exo_util.cpp


diff --git a/engines/glk/scott/unp64/exo_util.cpp b/engines/glk/scott/unp64/exo_util.cpp
index b388fba340a..7fea9fbc11e 100644
--- a/engines/glk/scott/unp64/exo_util.cpp
+++ b/engines/glk/scott/unp64/exo_util.cpp
@@ -53,7 +53,78 @@ namespace Glk {
 namespace Scott {
 
 int findSys(const byte *buf, int target) {
-	return 0;
+	int outstart = -1;
+	int state = 1;
+	int i = 0;
+	/* skip link and line number */
+	buf += 4;
+	/* iAN: workaround for hidden sysline (1001 cruncher, CFB, etc)*/
+	if (buf[0] == 0) {
+		for (i = 5; i < 32; i++)
+			if (buf[i] == 0x9e && (((buf[i + 1] & 0x30) == 0x30) || ((buf[i + 2] & 0x30) == 0x30)))
+				break;
+	}
+	/* exit loop at line end */
+	while (i < 1000 && buf[i] != '\0') {
+		byte *sysEnd;
+		int c = buf[i];
+		switch (state) {
+			/* look for and consume sys token */
+		case 1:
+			if ((target == -1 && (c == 0x9e)) || c == target) {
+				state = 2;
+			}
+			break;
+			/* skip spaces and left parenthesis, if any */
+		case 2:
+			if (strchr(" (", c) != nullptr)
+				break;
+			/* convert string number to int */
+		case 3:
+			outstart = (int)strtol((char *)(buf + i), (char **)&sysEnd, 10);
+			if ((buf + i) == sysEnd) {
+				/* we got nothing */
+				outstart = -1;
+			} else {
+				c = *sysEnd;
+				if ((c >= 0xaa) && (c <= 0xae)) {
+					i = (int)strtol((char *)(sysEnd + 1), (char **)&sysEnd, 10);
+					switch (c) {
+					case 0xaa:
+						outstart += i;
+						break;
+					case 0xab:
+						outstart -= i;
+						break;
+					case 0xac:
+						outstart *= i;
+						break;
+					case 0xad:
+						if (i > 0)
+							outstart /= i;
+						break;
+					case 0xae:
+						c = outstart;
+						while (--i)
+							outstart *= c;
+						break;
+					}
+				} else if (c == 'E') {
+					i = (int)strtol((char *)(sysEnd + 1), (char **)&sysEnd, 10);
+					i++;
+					while (--i)
+						outstart *= 10;
+				}
+			}
+			state = 4;
+			break;
+		case 4:
+			break;
+		}
+		++i;
+	}
+
+	return outstart;
 }
 
 static void loadPrgData(byte mem[65536], uint8_t *data, size_t dataLength, LoadInfo *info) {


Commit: dda8a0febcdac7b659eadedf9bc5d3fb8bed7a29
    https://github.com/scummvm/scummvm/commit/dda8a0febcdac7b659eadedf9bc5d3fb8bed7a29
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Implement isBasicRun1 and isBasicRun2

Changed paths:
    engines/glk/scott/unp64/unp64.cpp


diff --git a/engines/glk/scott/unp64/unp64.cpp b/engines/glk/scott/unp64/unp64.cpp
index 409445ac5e6..8c651db28e8 100644
--- a/engines/glk/scott/unp64/unp64.cpp
+++ b/engines/glk/scott/unp64/unp64.cpp
@@ -86,12 +86,18 @@ void reinitUnp(void) {
 	_G(_unp)._mon1st = 0;
 }
 
-int IsBasicRun1(int pc) {
-	return 0;
+int isBasicRun1(int pc) {
+	if (pc == 0xa7ae || pc == 0xa7ea || pc == 0xa7b1 || pc == 0xa474 || pc == 0xa533 || pc == 0xa871 || pc == 0xa888 || pc == 0xa8bc)
+		return 1;
+	else
+		return 0;
 }
 
-int IsBasicRun2(int pc) {
-	return 0;
+int isBasicRun2(int pc) {
+	if (isBasicRun1(pc) || ((pc >= 0xA57C) && (pc <= 0xA659)) || pc == 0xa660 || pc == 0xa68e)
+		return 1;
+	else
+		return 0;
 }
 
 int unp64(uint8_t *compressed, size_t length, uint8_t *destinationBuffer, size_t *finalLength, char *settings[], int numSettings) {
@@ -370,7 +376,7 @@ int unp64(uint8_t *compressed, size_t length, uint8_t *destinationBuffer, size_t
 				break;
 			}
 
-			if (IsBasicRun1(r->_pc)) {
+			if (isBasicRun1(r->_pc)) {
 				info->_run = findSys(mem + info->_basicTxtStart, 0x9e);
 				if (info->_run > 0) {
 					r->_sp = 0xf6;
@@ -474,7 +480,7 @@ int unp64(uint8_t *compressed, size_t length, uint8_t *destinationBuffer, size_t
 		}
 
 		if ((r->_pc >= 0xa000) && (r->_pc <= 0xbfff) && ((mem[1] & 0x7) == 7)) {
-			if (IsBasicRun2(r->_pc)) {
+			if (isBasicRun2(r->_pc)) {
 				r->_pc = 0xa7ae;
 				break;
 			} else {


Commit: 45f7e4751efc8bc1f66b21ebb722d44246bee3e9
    https://github.com/scummvm/scummvm/commit/45f7e4751efc8bc1f66b21ebb722d44246bee3e9
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Replace error with warning

Changed paths:
    engines/glk/scott/resource.cpp


diff --git a/engines/glk/scott/resource.cpp b/engines/glk/scott/resource.cpp
index 8c7ec347ab2..2fa5ce9c728 100644
--- a/engines/glk/scott/resource.cpp
+++ b/engines/glk/scott/resource.cpp
@@ -348,7 +348,7 @@ void loadVectorData(GameInfo info, uint8_t *ptr) {
 		do {
 			byte = *(ptr++);
 			if (ptr > _G(_entireFile) && static_cast<size_t>(ptr - _G(_entireFile)) >= _G(_fileLength)) {
-				error("loadVectorData: Error! Image data for image %d cut off", ct);
+				warning("loadVectorData: Error! Image data for image %d cut off", ct);
 				if (_G(_gameHeader)->_numRooms - ct > 1)
 					g_scott->display(_G(_bottomWindow), "[This copy has %d broken or missing pictures. These have been patched out.]\n\n", _G(_gameHeader)->_numRooms - ct);
 				if (lp->_data >= ptr)


Commit: 20090e73ed0a3c2629f670a81a59c25ea2974da6
    https://github.com/scummvm/scummvm/commit/20090e73ed0a3c2629f670a81a59c25ea2974da6
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Implement action_packer.cpp

Changed paths:
  A engines/glk/scott/unp64/scanners/action_packer.cpp
    engines/glk/module.mk


diff --git a/engines/glk/module.mk b/engines/glk/module.mk
index 7251f5a45d2..652d766196a 100644
--- a/engines/glk/module.mk
+++ b/engines/glk/module.mk
@@ -256,6 +256,7 @@ MODULE_OBJS := \
 	scott/unp64/6502_emu.o \
 	scott/unp64/exo_util.o \
 	scott/unp64/scanners/scanners.o \
+	scott/unp64/scanners/action_packer.o \
 	tads/os_banners.o \
 	tads/os_buffer.o \
 	tads/os_glk.o \
diff --git a/engines/glk/scott/unp64/scanners/action_packer.cpp b/engines/glk/scott/unp64/scanners/action_packer.cpp
new file mode 100644
index 00000000000..016a5a74c3f
--- /dev/null
+++ b/engines/glk/scott/unp64/scanners/action_packer.cpp
@@ -0,0 +1,52 @@
+/* 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 "common/endian.h"
+#include "glk/scott/types.h"
+#include "glk/scott/unp64/unp64.h"
+
+namespace Glk {
+namespace Scott {
+
+void scnActionPacker(UnpStr *unp) {
+	byte *mem;
+
+	if (unp->_idFlag)
+		return;
+	mem = unp->_mem;
+	if (unp->_depAdr == 0) {
+		if ((*(unsigned int *)(mem + 0x811) == 0x018538A9) &&
+			(*(unsigned int *)(mem + 0x81d) == 0xCEF7D0E8) &&
+			(*(unsigned int *)(mem + 0x82d) == 0x0F9D0837) &&
+			(*(unsigned int *)(mem + 0x84b) == 0x03D00120)) {
+			unp->_depAdr = 0x110;
+			unp->_forced = 0x811;
+			unp->_strMem = READ_LE_INT16(&mem[0x848]);
+			unp->_fEndAf = 0x120;
+			unp->_retAdr = READ_LE_INT16(&mem[0x863]);
+			unp->_idFlag = 1;
+			return;
+		}
+	}
+}
+
+} // End of namespace Scott
+} // End of namespace Glk


Commit: e28dd2b39cef0a9ac229c1cfe59e3e687ade05b7
    https://github.com/scummvm/scummvm/commit/e28dd2b39cef0a9ac229c1cfe59e3e687ade05b7
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Implement byte_boiler.cpp

Changed paths:
  A engines/glk/scott/unp64/scanners/byte_boiler.cpp
    engines/glk/module.mk


diff --git a/engines/glk/module.mk b/engines/glk/module.mk
index 652d766196a..f38de22cf01 100644
--- a/engines/glk/module.mk
+++ b/engines/glk/module.mk
@@ -257,6 +257,7 @@ MODULE_OBJS := \
 	scott/unp64/exo_util.o \
 	scott/unp64/scanners/scanners.o \
 	scott/unp64/scanners/action_packer.o \
+	scott/unp64/scanners/byte_boiler.o \
 	tads/os_banners.o \
 	tads/os_buffer.o \
 	tads/os_glk.o \
diff --git a/engines/glk/scott/unp64/scanners/byte_boiler.cpp b/engines/glk/scott/unp64/scanners/byte_boiler.cpp
new file mode 100644
index 00000000000..a3c3fb6d49a
--- /dev/null
+++ b/engines/glk/scott/unp64/scanners/byte_boiler.cpp
@@ -0,0 +1,93 @@
+/* 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 "common/endian.h"
+#include "glk/scott/types.h"
+#include "glk/scott/unp64/unp64.h"
+
+namespace Glk {
+namespace Scott {
+
+void scnByteBoiler(UnpStr *unp) {
+	byte *mem;
+	int q, p;
+	if (unp->_idFlag)
+		return;
+	mem = unp->_mem;
+	if (unp->_depAdr == 0) {
+		if ((*(unsigned int *)(mem + 0x813) == 0xE800F09D) &&
+			(*(unsigned int *)(mem + 0x818) == 0x014E4CF7)) {
+			p = READ_LE_INT16(&mem[0x811]);
+			if (*(unsigned int *)(mem + p + 1) == 0x02D0FAA5) {
+				unp->_depAdr = 0x14e;
+				unp->_forced = 0x80b;
+				unp->_retAdr = READ_LE_INT16(&mem[p + 0x5c]);
+				unp->_endAdr = READ_LE_INT16(&mem[p + 0x0e]);
+				unp->_endAdr++;
+				unp->_fStrAf = 0xfe;
+				unp->_idFlag = 1;
+				return;
+			}
+		}
+	}
+	/* CPX hack */
+	if (unp->_depAdr == 0) {
+		if ((*(unsigned int *)(mem + 0x80b) == 0xA97800A2) &&
+			(*(unsigned int *)(mem + 0x815) == 0x4C01E6D0)) {
+			q = READ_LE_INT16(&mem[0x819]);
+			if ((*(unsigned int *)(mem + q + 3) == 0xE800F09D) &&
+				(*(unsigned int *)(mem + q + 8) == 0x014E4CF7)) {
+				p = READ_LE_INT16(&mem[q + 1]);
+				if (*(unsigned int *)(mem + p + 1) == 0x02D0FAA5) {
+					unp->_depAdr = 0x14e;
+					unp->_forced = 0x80b;
+					unp->_retAdr = READ_LE_INT16(&mem[p + 0x5c]); 
+					unp->_endAdr = READ_LE_INT16(&mem[p + 0x0e]); 
+					unp->_endAdr++;
+					unp->_fStrAf = 0xfe;
+					unp->_idFlag = 1;
+					return;
+				}
+			}
+		}
+	}
+	/* SCS hack */
+	if (unp->_depAdr == 0) {
+		if ((*(unsigned int *)(mem + 0x813) == 0xE800F09D) &&
+			(*(unsigned int *)(mem + 0x818) == 0x01bf4CF7)) {
+			p = READ_LE_INT16(&mem[0x811]); 
+			if ((*(unsigned int *)(mem + p + 1) == 0x02D0FAA5) &&
+				(*(unsigned int *)(mem + p + 0xdd) == 0x014e4c01)) {
+				unp->_depAdr = 0x14e;
+				unp->_forced = 0x80b;
+				unp->_retAdr = READ_LE_INT16(&mem[p + 0x5c]); 
+				unp->_endAdr = READ_LE_INT16(&mem[p + 0x0e]); 
+				unp->_endAdr++;
+				unp->_fStrAf = 0xfe;
+				unp->_idFlag = 1;
+				return;
+			}
+		}
+	}
+}
+
+} // End of namespace Scott
+} // End of namespace Glk


Commit: 9bb67453a02828ad373e786e10c58fbb1fba8e9b
    https://github.com/scummvm/scummvm/commit/9bb67453a02828ad373e786e10c58fbb1fba8e9b
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Implement caution.cpp

Changed paths:
  A engines/glk/scott/unp64/scanners/caution.cpp
    engines/glk/module.mk


diff --git a/engines/glk/module.mk b/engines/glk/module.mk
index f38de22cf01..b12a004a655 100644
--- a/engines/glk/module.mk
+++ b/engines/glk/module.mk
@@ -258,6 +258,7 @@ MODULE_OBJS := \
 	scott/unp64/scanners/scanners.o \
 	scott/unp64/scanners/action_packer.o \
 	scott/unp64/scanners/byte_boiler.o \
+	scott/unp64/scanners/caution.o \
 	tads/os_banners.o \
 	tads/os_buffer.o \
 	tads/os_glk.o \
diff --git a/engines/glk/scott/unp64/scanners/caution.cpp b/engines/glk/scott/unp64/scanners/caution.cpp
new file mode 100644
index 00000000000..b300e009607
--- /dev/null
+++ b/engines/glk/scott/unp64/scanners/caution.cpp
@@ -0,0 +1,134 @@
+/* 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 "common/endian.h"
+#include "glk/scott/types.h"
+#include "glk/scott/unp64/unp64.h"
+
+namespace Glk {
+namespace Scott {
+
+void scnCaution(UnpStr *unp) {
+	byte *mem;
+
+	if (unp->_idFlag)
+		return;
+	mem = unp->_mem;
+	/* quickpacker 1.0 sysless */
+	if (unp->_depAdr == 0) {
+		if ((*(unsigned int *)(mem + 0x801) == 0xE67800A2) &&
+			(*(unsigned int *)(mem + 0x805) == 0x07EDBD01) &&
+			(*(unsigned int *)(mem + 0x80d) == 0x00284CF8) &&
+			(*(unsigned int *)(mem + 0x844) == 0xAC00334C)) {
+			unp->_forced = 0x801;
+			unp->_depAdr = 0x28;
+			unp->_retAdr = READ_LE_INT16(&mem[0x86b]);
+			unp->_endAdr = READ_LE_INT16(&mem[0x85a]);
+			unp->_fStrAf = mem[0x863];
+			unp->_strAdC = EA_ADDFF | 0xffff;
+			unp->_idFlag = 1;
+			return;
+		}
+	}
+	/* quickpacker 2.x + sys */
+	if (unp->_depAdr == 0) {
+		if (((*(unsigned int *)(mem + 0x80b) & 0xf0ffffff) == 0x60A200A0) &&
+			 (*(unsigned int *)(mem + 0x80f) == 0x0801BD78) &&
+			 (*(unsigned int *)(mem + 0x813) == 0xD0CA0095) &&
+			 (*(unsigned int *)(mem + 0x81e) == 0xD0C80291) &&
+			 (*(unsigned int *)(mem + 0x817) == 0x001A4CF8)) {
+			unp->_forced = 0x80b;
+			unp->_depAdr = 0x01a;
+			if (mem[0x80e] == 0x69) {
+				unp->_retAdr = READ_LE_INT16(&mem[0x842]);
+				unp->_endAdr = READ_LE_INT16(&mem[0x850]);
+				unp->_endAdr += 0x100;
+				unp->_fStrAf = 0x4f;
+				unp->_strAdC = 0xffff | EA_USE_Y;
+				unp->_idFlag = 1;
+				return;
+			} else if (mem[0x80e] == 0x6c) {
+				unp->_retAdr = READ_LE_INT16(&mem[0x844]);
+				unp->_endAdr = READ_LE_INT16(&mem[0x84e]);
+				unp->_endAdr++;
+				unp->_fStrAf = 0x4d;
+				unp->_idFlag = 1;
+				return;
+			}
+		}
+	}
+	/* strangely enough, sysless v2.0 depacker is at $0002 */
+	if (unp->_depAdr == 0) {
+		if ((*(unsigned int *)(mem + 0x83d) == 0xAA004A20) &&
+			(*(unsigned int *)(mem + 0x801) == 0xA27800A0) &&
+			(*(unsigned int *)(mem + 0x805) == 0x080FBD55) &&
+			(*(unsigned int *)(mem + 0x809) == 0xD0CA0095) &&
+			(*(unsigned int *)(mem + 0x80d) == 0x00024CF8)) {
+			unp->_forced = 0x801;
+			unp->_depAdr = 0x2;
+			unp->_retAdr = READ_LE_INT16(&mem[0x83b]);
+			unp->_endAdr = READ_LE_INT16(&mem[0x845]);
+			unp->_endAdr++;
+			unp->_fStrAf = mem[0x849];
+			// unp->_StrAdC=0xffff;
+			unp->_idFlag = 1;
+			return;
+		}
+	}
+	/* same goes for v2.5 sysless, seems almost another packer */
+	if (unp->_depAdr == 0) {
+		if ((*(unsigned int *)(mem + 0x83b) == 0xAA005520) &&
+			(*(unsigned int *)(mem + 0x801) == 0x60A200A0) &&
+			(*(unsigned int *)(mem + 0x805) == 0x0801BD78) &&
+			(*(unsigned int *)(mem + 0x809) == 0xD0CA0095) &&
+			(*(unsigned int *)(mem + 0x80d) == 0x00104CF8)) {
+			unp->_forced = 0x801;
+			unp->_depAdr = 0x10;
+			unp->_retAdr = READ_LE_INT16(&mem[0x839]); 
+			unp->_endAdr = READ_LE_INT16(&mem[0x847]);
+			unp->_endAdr += 0x100;
+			unp->_fStrAf = 0x46;
+			unp->_strAdC = 0xffff | EA_USE_Y;
+			unp->_idFlag = 1;
+			return;
+		}
+	}
+	/* hardpacker */
+	if (unp->_depAdr == 0) {
+		if ((*(unsigned int *)(mem + 0x80d) == 0x8534A978) &&
+			(*(unsigned int *)(mem + 0x811) == 0xB9B3A001) &&
+			(*(unsigned int *)(mem + 0x815) == 0x4C99081F) &&
+			(*(unsigned int *)(mem + 0x819) == 0xF7D08803) &&
+			(*(unsigned int *)(mem + 0x81d) == 0xB9034D4C)) {
+			unp->_forced = 0x80d;
+			unp->_depAdr = 0x34d;
+			unp->_retAdr = READ_LE_INT16(&mem[0x87f]);
+			unp->_endAdr = READ_LE_INT16(&mem[0x88d]);
+			unp->_fStrAf = 0x3ba;
+			unp->_strAdC = EA_ADDFF | 0xffff;
+			unp->_idFlag = 1;
+			return;
+		}
+	}
+}
+
+} // End of namespace Scott
+} // End of namespace Glk


Commit: 92d62985cc60c3d8ad2c41c85ec788b28a1e1e6d
    https://github.com/scummvm/scummvm/commit/92d62985cc60c3d8ad2c41c85ec788b28a1e1e6d
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Implement ccs.cpp

Changed paths:
  A engines/glk/scott/unp64/scanners/ccs.cpp
    engines/glk/module.mk


diff --git a/engines/glk/module.mk b/engines/glk/module.mk
index b12a004a655..ebbdb456feb 100644
--- a/engines/glk/module.mk
+++ b/engines/glk/module.mk
@@ -259,6 +259,7 @@ MODULE_OBJS := \
 	scott/unp64/scanners/action_packer.o \
 	scott/unp64/scanners/byte_boiler.o \
 	scott/unp64/scanners/caution.o \
+	scott/unp64/scanners/ccs.o \
 	tads/os_banners.o \
 	tads/os_buffer.o \
 	tads/os_glk.o \
diff --git a/engines/glk/scott/unp64/scanners/ccs.cpp b/engines/glk/scott/unp64/scanners/ccs.cpp
new file mode 100644
index 00000000000..0808c7b4b70
--- /dev/null
+++ b/engines/glk/scott/unp64/scanners/ccs.cpp
@@ -0,0 +1,208 @@
+/* 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 "common/endian.h"
+#include "glk/scott/types.h"
+#include "glk/scott/unp64/unp64.h"
+#include "glk/scott/unp64/exo_util.h"
+
+namespace Glk {
+namespace Scott {
+
+void scnCCS(UnpStr *unp) {
+	byte *mem;
+	int p;
+	if (unp->_idFlag)
+		return;
+	mem = unp->_mem;
+	if (unp->_depAdr == 0) {
+		if ((*(unsigned int *)(mem + 0x817) == 0xB901E678) &&
+			(*(unsigned int *)(mem + 0x81b) == 0xFD990831) &&
+			(*(unsigned int *)(mem + 0x8ff) == 0xFEE60290) &&
+			(*(unsigned int *)(mem + 0x90f) == 0x02903985)) {
+			if (unp->_info->_run == -1)
+				unp->_forced = 0x817;
+			unp->_depAdr = 0x0ff;
+			unp->_fEndAf = 0x2d;
+			unp->_endAdC = 0xffff;
+			unp->_retAdr = READ_LE_INT16(&mem[0x8ed]);
+			if (unp->_retAdr == 0xa659) {
+				mem[0x8ec] = 0x2c;
+				unp->_retAdr = READ_LE_INT16(&mem[0x8f0]);
+			}
+			unp->_idFlag = 1;
+			return;
+		}
+	}
+	/* derived from supercomp/eqseq */
+	if (unp->_depAdr == 0) {
+		if ((*(unsigned int *)(mem + 0x80b) == 0x8C7800A0) &&
+			(*(unsigned int *)(mem + 0x812) == 0x0099082F) &&
+			(*(unsigned int *)(mem + 0x846) == 0x0DADF2D0) &&
+			(*(unsigned int *)(mem + 0x8c0) == 0xF001124C)) {
+			if (unp->_info->_run == -1)
+				unp->_forced = 0x80b;
+			unp->_depAdr = 0x100;
+			unp->_endAdr = 0xae;
+			unp->_retAdr = READ_LE_INT16(&mem[0x8f1]);
+			if (unp->_retAdr == 0xa659) {
+				mem[0x8f0] = 0x2c;
+				unp->_retAdr = READ_LE_INT16(&mem[0x8f4]);
+			}
+			unp->_idFlag = 1;
+			return;
+		}
+	}
+	if (unp->_depAdr == 0) {
+		if ((*(unsigned int *)(mem + 0x814) == 0xB901E678) &&
+			(*(unsigned int *)(mem + 0x818) == 0xFD990829) &&
+			(*(unsigned int *)(mem + 0x8a1) == 0xFDA6FDB1) &&
+			(*(unsigned int *)(mem + 0x8a5) == 0xFEC602D0)) {
+			if (unp->_info->_run == -1)
+				unp->_forced = 0x814;
+			unp->_depAdr = 0x0ff;
+			unp->_fEndBf = 0x39;
+			unp->_idFlag = 1;
+			return;
+		}
+	}
+	if (unp->_depAdr == 0) {
+		if ((*(unsigned int *)(mem + 0x818) == 0x2CB901E6) &&
+			(*(unsigned int *)(mem + 0x81c) == 0x00FB9908) &&
+			(*(unsigned int *)(mem + 0x850) == 0xFBB1C84A) &&
+			(*(unsigned int *)(mem + 0x854) == 0xB1C81185)) {
+			if (unp->_info->_run == -1)
+				unp->_forced = 0x812;
+			unp->_depAdr = 0x0ff;
+			unp->_endAdr = 0xae;
+			unp->_idFlag = 1;
+			return;
+		}
+	}
+	if (unp->_depAdr == 0) {
+		if ((*(unsigned int *)(mem + 0x818) == 0x2CB901E6) &&
+			(*(unsigned int *)(mem + 0x81c) == 0x00FB9908) &&
+			(*(unsigned int *)(mem + 0x851) == 0xFBB1C812) &&
+			(*(unsigned int *)(mem + 0x855) == 0xB1C81185)) {
+			if (unp->_info->_run == -1)
+				unp->_forced = 0x812;
+			unp->_depAdr = 0x0ff;
+			unp->_endAdr = 0xae;
+			unp->_idFlag = 1;
+			return;
+		}
+	}
+	if (unp->_depAdr == 0) {
+		if ((*(unsigned int *)(mem + 0x82c) == 0x018538A9) &&
+			(*(unsigned int *)(mem + 0x831) == 0xFD990842) &&
+			(*(unsigned int *)(mem + 0x83e) == 0x00FF4CF1) &&
+			(*(unsigned int *)(mem + 0x8a5) == 0x50C651C6)) {
+			if (unp->_info->_run == -1)
+				unp->_forced = 0x822;
+			unp->_depAdr = 0x0ff;
+			unp->_fEndBf = 0x39;
+			unp->_retAdr = READ_LE_INT16(&mem[0x8ea]);
+			unp->_idFlag = 1;
+			return;
+		}
+	}
+	if (unp->_depAdr == 0) {
+		if ((*(unsigned short int *)(mem + 0x81a) == 0x00A0) &&
+			((*(unsigned int *)(mem + 0x820) == 0xFB990837) ||
+			 (*(unsigned int *)(mem + 0x824) == 0xFB990837)) &&
+			(*(unsigned int *)(mem + 0x83b) == 0xFD91FBB1) &&
+			(*(unsigned int *)(mem + 0x8bc) == 0xEE00FC99)) {
+			if (unp->_info->_run == -1)
+				unp->_forced = 0x81a;
+			unp->_depAdr = 0x0ff;
+			unp->_fEndAf = 0x39;
+			unp->_endAdC = 0xffff;
+			unp->_retAdr = READ_LE_INT16(&mem[0x8b3]);
+			unp->_idFlag = 1;
+			return;
+		}
+	}
+	if (unp->_depAdr == 0) {
+		if ((*(unsigned int *)(mem + 0x812) == 0xE67800A0) &&
+			(*(unsigned int *)(mem + 0x816) == 0x0823B901) &&
+			(*(unsigned int *)(mem + 0x81a) == 0xC800FD99) &&
+			(*(unsigned int *)(mem + 0x81e) == 0xFF4CF7D0) &&
+			(*(unsigned int *)(mem + 0x885) == 0xFDA6FDB1)) {
+			if (unp->_info->_run == -1)
+				unp->_forced = 0x812;
+			unp->_depAdr = 0x0ff;
+			// $2d is unreliable, Executer uses line number at $0803/4,
+			// which is read at $0039/3a by basic, as end address,
+			// then can set arbitrarily $2d/$ae pointers after unpack.
+			// unp->_fEndAf=0x2d;
+			unp->_endAdr = READ_LE_INT16(&mem[0x803]);
+			unp->_endAdr++;
+			if (*(unsigned int *)(mem + 0x87f) == 0x4CA65920)
+				mem[0x87f] = 0x2c;
+			unp->_retAdr = READ_LE_INT16(&mem[0x883]);
+			unp->_idFlag = 1;
+			return;
+		}
+	}
+	if (unp->_depAdr == 0) {
+		if ((*(unsigned int *)(mem + 0x812) == 0xE67800A0) &&
+			(*(unsigned int *)(mem + 0x816) == 0x084CB901) &&
+			(*(unsigned int *)(mem + 0x81a) == 0xA900FB99) &&
+			(*(unsigned int *)(mem + 0x848) == 0x00FF4CE2)) {
+			if (unp->_info->_run == -1)
+				unp->_forced = 0x812;
+			unp->_depAdr = 0x0ff;
+			unp->_fEndAf = 0x2d;
+			unp->_endAdC = 0xffff;
+			unp->_idFlag = 1;
+			return;
+		}
+	}
+	/* Triad Hack */
+	if (unp->_depAdr == 0) {
+		if ((*(unsigned int *)(mem + 0x838) == 0xB9080099) &&
+			(*(unsigned int *)(mem + 0x83f) == 0xD0880816) &&
+			(*(unsigned int *)(mem + 0x8ff) == 0xFEE60290) &&
+			(*(unsigned int *)(mem + 0x90f) == 0x02903985)) {
+			if (unp->_info->_run == -1) {
+				for (p = 0x80b; p < 0x820; p++) {
+					if ((mem[p] & 0xa0) == 0xa0) {
+						unp->_forced = p;
+						break;
+					}
+				}
+			}
+			unp->_depAdr = 0x0ff;
+			unp->_fEndAf = 0x2d;
+			unp->_endAdC = 0xffff;
+			unp->_retAdr = READ_LE_INT16(&mem[0x8ed]);
+			if (unp->_retAdr == 0xa659) {
+				mem[0x8ec] = 0x2c;
+				unp->_retAdr = READ_LE_INT16(&mem[0x8f0]);
+			}
+			unp->_idFlag = 1;
+			return;
+		}
+	}
+}
+
+} // End of namespace Scott
+} // End of namespace Glk


Commit: 731e0a3f0783494f1ac196df902c26bd99e077ac
    https://github.com/scummvm/scummvm/commit/731e0a3f0783494f1ac196df902c26bd99e077ac
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Implement cruel.cpp

Changed paths:
  A engines/glk/scott/unp64/scanners/cruel.cpp
    engines/glk/module.mk


diff --git a/engines/glk/module.mk b/engines/glk/module.mk
index ebbdb456feb..a1def2cec55 100644
--- a/engines/glk/module.mk
+++ b/engines/glk/module.mk
@@ -260,6 +260,7 @@ MODULE_OBJS := \
 	scott/unp64/scanners/byte_boiler.o \
 	scott/unp64/scanners/caution.o \
 	scott/unp64/scanners/ccs.o \
+	scott/unp64/scanners/cruel.o \
 	tads/os_banners.o \
 	tads/os_buffer.o \
 	tads/os_glk.o \
diff --git a/engines/glk/scott/unp64/scanners/cruel.cpp b/engines/glk/scott/unp64/scanners/cruel.cpp
new file mode 100644
index 00000000000..e2e3aa78a65
--- /dev/null
+++ b/engines/glk/scott/unp64/scanners/cruel.cpp
@@ -0,0 +1,374 @@
+/* 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 "common/endian.h"
+#include "glk/scott/types.h"
+#include "glk/scott/unp64/unp64.h"
+#include "glk/scott/unp64/exo_util.h"
+
+namespace Glk {
+namespace Scott {
+
+void scnCruel(UnpStr *unp) {
+	byte *mem;
+	int q, p, strtmp = 0;
+	if (unp->_idFlag)
+		return;
+	mem = unp->_mem;
+	if (unp->_depAdr == 0) {
+		if (mem[0x810] == 0xb9 &&
+			((*(unsigned int *)(mem + 0x813) & 0xfffffeff) == 0xC800FA99) &&
+			(*(unsigned short int *)(mem + 0x818) == 0x4CF7)) {
+			if (mem[0x814] == 0xFA) {
+				p = READ_LE_INT16(&mem[0x811]); // mem[0x811] | mem[0x812] << 8;
+				if (*(unsigned int *)(mem + p + 9) == 0xC8071C99) {
+					unp->_endAdr = READ_LE_INT16(&mem[p + 2]); // mem[p + 2] | mem[p + 3] << 8;
+					unp->_depAdr = 0x100;
+					if (unp->_info->_run == -1)
+						unp->_forced = 0x80b;
+					unp->_fStrAf = 0xfc;
+					q = READ_LE_INT16(&mem[p + 7]); // mem[p + 7] | mem[p + 8] << 8;
+					if ((mem[q + 0x8e] == 0xc6) && (mem[q + 0x8f] == 0x01) &&
+						(mem[q + 0x93] == 0xe6) && (mem[q + 0x94] == 0x01)) {
+						mem[q + 0x90] = 0x2c;
+					}
+					/* retadr is not always at the same addr, but at least can't
+					   be anything < $07e8
+					*/
+					// unp->_retAdr=0x7e8;
+					q = READ_LE_INT16(&mem[p + 7]); // mem[p + 7] | mem[p + 8] << 8;
+					if (mem[q + 0x3c] == 0x4c) {
+						/* v2.2/dynamix, v2.5/cross, v2.5/crest */
+						strtmp = *(unsigned short int *)(mem + q + 0x3d);
+					} else if (mem[q + 0x4a] == 0x4c) {
+						strtmp = *(unsigned short int *)(mem + q + 0x4b);
+					} else if (mem[q + 0x3f] == 0x4c) {
+						/* v2.2/oneway+scs, also hacked as cruel 2mhz 1.0 */
+						strtmp = *(unsigned short int *)(mem + q + 0x40);
+					} else {
+						/* todo: determine real retadr, for now a default seems ok */
+						strtmp = 0;
+					}
+					if (strtmp) {
+						if (strtmp >= unp->_retAdr) {
+							unp->_retAdr = strtmp;
+						} else { /* now search it... variable code here */
+							strtmp += p - *(unsigned short int *)(mem + 0x814);
+							for (q = strtmp; q < unp->_info->_end; q++) {
+								if ((mem[q] == 0xa9) || (mem[q] == 0x85)) {
+									q++;
+									continue;
+								}
+								if (mem[q] == 0x8d) {
+									q += 2;
+									continue;
+								}
+								if (mem[q] == 0x4c) {
+									unp->_retAdr = *(unsigned short int *)(mem + q + 1);
+									;
+									break;
+								}
+							}
+						}
+					}
+				}
+			} else if (mem[0x814] == 0xFB) {
+				/* not Cruel2 but MSCRUNCH by Marco/Taboo
+				   v1.0 works only with some old AR cart (unless patched ;)
+				   v1.5 is infact more common
+				*/
+				p = READ_LE_INT16(&mem[0x811]); // mem[0x811] | mem[0x812] << 8;
+				if (*(unsigned int *)(mem + p + 7) == 0xC8071C99) {
+					unp->_endAdr = READ_LE_INT16(&mem[p + 3]); // mem[p + 3] | mem[p + 4] << 8;
+					unp->_depAdr = 0x100;
+					unp->_forced = 0x80b;
+					unp->_fStrAf = 0xfe;
+					if ((mem[p + 0x93] == 0x4c) && (mem[p + 0xa1] == 0x4c)) {
+						unp->_retAdr = READ_LE_INT16(&mem[p + 0xa2]); // mem[p + 0xa2] | mem[p + 0xa3] << 8;
+					} else if ((mem[p + 0x8c] == 0x4c) && (mem[p + 0x94] == 0x4c)) {
+						unp->_retAdr = READ_LE_INT16(&mem[p + 0x95]); // mem[p + 0x95] | mem[p + 0x96] << 8;
+					} else if ((mem[p + 0x20] == 0x4c) && (mem[p + 0x28] == 0x4c)) {
+						unp->_retAdr = READ_LE_INT16(&mem[p + 0x29]); // mem[p + 0x29] | mem[p + 0x2a] << 8;
+					} 
+				}
+			}
+		}
+		if (unp->_depAdr) {
+			unp->_idFlag = 1;
+			return;
+		}
+	}
+	/* MSCRUNCH 1.5 hack by Anubis */
+	if (unp->_depAdr == 0) {
+		if (mem[0x819] == 0x4c) {
+			p = READ_LE_INT16(&mem[0x81a]);//mem[0x81a] | mem[0x81b] << 8;
+			if ((mem[p] == 0xa9) && (mem[p + 0x0f] == 0x30) &&
+				(*(unsigned int *)(mem + p + 0x13) == 0xCA04009D) &&
+				(*(unsigned int *)(mem + p + 0x38) == 0x01084C01)) {
+				q = READ_LE_INT16(&mem[p + 0x1f]); // mem[p + 0x1f] | mem[p + 0x20] << 8;
+				if (*(unsigned int *)(mem + q + 7) == 0xC8071C99) {
+					unp->_endAdr = READ_LE_INT16(&mem[q + 3]); // mem[q + 3] | mem[q + 4] << 8;
+					unp->_depAdr = 0x100;
+					if (unp->_info->_run == -1)
+						unp->_forced = 0x819;
+					unp->_fStrAf = 0xfe;
+					unp->_retAdr = READ_LE_INT16(&mem[q + 0xa2]); // mem[q + 0xa2] | mem[q + 0xa3] << 8;
+				}
+			}
+		}
+	}
+	/* fast cruel 4.x */
+	if (unp->_depAdr == 0) {
+		if ((*(unsigned int *)(mem + 0x80b) == 0xE67800A0) &&
+			(*(unsigned int *)(mem + 0x813) == 0xC8034099) &&
+			((*(unsigned int *)(mem + 0x818) == 0x03404cF7) ||
+			 (*(unsigned int *)(mem + 0x818) == 0x03b34cF7) ||
+			 (*(unsigned int *)(mem + 0x818) == 0x03db4cF7))) {
+			p = READ_LE_INT16(&mem[0x811]); // mem[0x811] | mem[0x812] << 8;
+			if (*(unsigned int *)(mem + p) == 0xa75801c6) {
+				p += 0x45;
+				q = READ_LE_INT16(&mem[p]);            // mem[p] | mem[p + 1] << 8;
+				unp->_endAdr = READ_LE_INT16(&mem[q + 2]); // mem[q + 2] | mem[q + 3] << 8;
+				unp->_depAdr = 0x340;
+				unp->_forced = 0x80b;
+				unp->_fStrAf = 0xfc;
+				unp->_idFlag = 1;
+				return;
+			}
+		}
+	}
+	/* Cruel 2.0 / (BB) packer header */
+	if (unp->_depAdr == 0) {
+		if ((*(unsigned int *)(mem + 0x837) == 0x9D0845BD) &&
+			(*(unsigned int *)(mem + 0x84f) == 0xE808039D) &&
+			(*(unsigned int *)(mem + 0x83b) == 0xC9E803B7)) {
+			unp->_depAdr = READ_LE_INT16(&mem[0x843]); // mem[0x843] | mem[0x844] << 8;
+			if (unp->_info->_run == -1)
+				unp->_forced = 0x80d;
+			unp->_retAdr = READ_LE_INT16(&mem[0x868]); // mem[0x868] | mem[0x869] << 8;
+			unp->_endAdr = unp->_info->_end - 0x90;
+			unp->_strMem = 0x801;
+			unp->_idFlag = 1;
+			return;
+		}
+		if ((*(unsigned int *)(mem + 0x845) == 0x03E04CF2) &&
+			(*(unsigned int *)(mem + 0x852) == 0x9D0893BD) &&
+			(*(unsigned int *)(mem + 0x856) == 0xD0E80803)) {
+			unp->_depAdr = READ_LE_INT16(&mem[0x847]); // mem[0x847] | mem[0x848] << 8;
+			if (unp->_info->_run == -1)
+				unp->_forced = 0x80d;
+			unp->_retAdr = READ_LE_INT16(&mem[0x869]); // mem[0x869] | mem[0x86a] << 8;
+			unp->_endAdr = unp->_info->_end - 0x90;
+			unp->_strMem = 0x801;
+			unp->_idFlag = 1;
+			return;
+		}
+		if ((*(unsigned int *)(mem + 0x841) == 0x03B74CF5) &&
+			(*(unsigned int *)(mem + 0x84c) == 0x9D089BBD) &&
+			(*(unsigned int *)(mem + 0x850) == 0xD0E8080B)) {
+			unp->_depAdr = READ_LE_INT16(&mem[0x843]); // mem[0x843] | mem[0x844] << 8;
+			if (unp->_info->_run == -1) {
+				unp->_forced = 0x811;
+			} else {
+				mem[0x808] = '5'; /* just to be safe, change sys for next layer */
+				mem[0x809] = '9'; /* this hdr leaves it as sys2065 */
+			}
+			unp->_retAdr = READ_LE_INT16(&mem[0x868]); // mem[0x868] | mem[0x869] << 8; /* fixed $080b */
+			unp->_endAdr = unp->_info->_end - 0x90;
+			unp->_strMem = 0x801;
+			unp->_idFlag = 1;
+			return;
+		}
+		/* this is a totally useless header, cheers TCOM! */
+		if ((*(unsigned int *)(mem + 0x80b) == 0x1BB900A0) &&
+			(*(unsigned int *)(mem + 0x80f) == 0x03B79908) &&
+			(*(unsigned int *)(mem + 0x823) == 0x039D0840)) {
+			unp->_depAdr = READ_LE_INT16(&mem[0x819]); // mem[0x819] | mem[0x81a] << 8;
+			if (unp->_info->_run == -1)
+				unp->_forced = 0x80b;
+			unp->_retAdr = READ_LE_INT16(&mem[0x83e]); // mem[0x83e] | mem[0x83f] << 8;
+			unp->_endAdr = unp->_info->_end - 0x3d;
+			unp->_strMem = 0x801;
+			unp->_idFlag = 1;
+			return;
+		}
+	}
+	/* Cruel 2.0 / (BB) packer sysless */
+	if (unp->_depAdr == 0) {
+		if ((((*(unsigned int *)(mem + 0x80b)) & 0x0000ffff) == 0x000000A0) &&
+			(*(unsigned int *)(mem + 0x817) == 0xC800CB99) &&
+			(*(unsigned int *)(mem + 0x81b) == 0x004CF7D0) && mem[0x81f] == 1) {
+			p = READ_LE_INT16(&mem[0x815]); // mem[0x815] | mem[0x816] << 8;
+			p += 0x31;
+			if ((mem[p + 4] == 0xb9) &&
+				(*(unsigned int *)(mem + p + 7) == 0xC8072099)) {
+				unp->_forced = 0x80b;
+				unp->_depAdr = 0x100;
+				unp->_endAdr = READ_LE_INT16(&mem[p]); // mem[p] | mem[p + 1] << 8;
+				unp->_fStrAf = 0xfc;
+				/* patch: some version contain a zp cleaner sub at $01a2 */
+				if ((*(unsigned int *)(mem + p + 0xa6) == 0x00A9CBA2) &&
+					(*(unsigned int *)(mem + p + 0xaa) == 0xD0E80095)) {
+					mem[p + 0xa6] = 0x60;
+				}
+				/* patch: some version expects $01==#$34 already set from the header */
+				if (*(unsigned int *)(mem + 0x811) == 0xb9eaeaea) {
+					mem[0x811] = 0xe6;
+					mem[0x812] = 0x01;
+				}
+				q = READ_LE_INT16(&mem[p + 5]); // mem[p + 5] | mem[p + 6] << 8;
+				unp->_retAdr = 0x7e8;
+				if (mem[q + 0x6c] == 0x4c)
+					unp->_retAdr = READ_LE_INT16(&mem[q + 0x6d]); // mem[q + 0x6d] | mem[q + 0x6e] << 8;
+				unp->_idFlag = 1;
+				return;
+			}
+		}
+	}
+	/* Cruel 2.1 / STA */
+	if (unp->_depAdr == 0) {
+		if (mem[0x80b] == 0xa0 && (*(unsigned int *)(mem + 0x817) == 0xC800CB99) &&
+			(*(unsigned int *)(mem + 0x81b) == 0x004CF7D0) && mem[0x81f] == 1) {
+			p = READ_LE_INT16(&mem[0x815]); // mem[0x815] | mem[0x816] << 8;
+			p += 0x31;
+			if ((mem[p + 6] == 0xb9) &&
+				(*(unsigned int *)(mem + p + 9) == 0xC8072099)) {
+				unp->_forced = 0x80b;
+				unp->_depAdr = 0x100;
+				unp->_endAdr = READ_LE_INT16(&mem[p]); // mem[p] | mem[p + 1] << 8;
+				unp->_fStrAf = 0xfc;
+				q = READ_LE_INT16(&mem[p + 7]); // mem[p + 7] | mem[p + 8] << 8;
+				unp->_retAdr = 0x7e8;
+				if (mem[q + 0x6c] == 0x4c)
+					unp->_retAdr = READ_LE_INT16(&mem[q + 0x6d]); // mem[q + 0x6d] | mem[q + 0x6e] << 8;
+				unp->_idFlag = 1;
+				return;
+			}
+		}
+	}
+	/* unknown cruel, jmp $00e9, found in Illusion/Random warez */
+	if (unp->_depAdr == 0) {
+		if (mem[0x810] == 0xb9 && (*(unsigned int *)(mem + 0x813) == 0xC800e999) &&
+			(*(unsigned int *)(mem + 0x818) == 0x00e94CF7)) {
+			p = READ_LE_INT16(&mem[0x811]); // mem[0x811] | mem[0x812] << 8;
+			q = p - 0xed;
+			if ((*(unsigned int *)(mem + p) == 0x13F01284) &&
+				(*(unsigned int *)(mem + q) == 0xA9C8C8C8)) {
+				unp->_depAdr = 0xe9;
+				unp->_endAdr = READ_LE_INT16(&mem[p + 0x13]); // mem[p + 0x13] | mem[p + 0x14] << 8;
+				unp->_retAdr = READ_LE_INT16(&mem[q + 0x38]); // mem[q + 0x38] | mem[q + 0x39] << 8;
+				if (unp->_info->_run == -1)
+					unp->_forced = 0x80b;
+				unp->_fStrAf = 0xfc;
+				unp->_idFlag = 1;
+				return;
+			}
+		}
+	}
+	if (unp->_depAdr == 0) {
+		if (mem[0x810] == 0xb9 && (*(unsigned int *)(mem + 0x813) == 0xC800ed99) &&
+			(*(unsigned int *)(mem + 0x818) == 0x01004CF7)) {
+			p = READ_LE_INT16(&mem[0x811]); // mem[0x811] | mem[0x812] << 8;
+			q = p - 0xed;
+			if ((*(unsigned int *)(mem + p) == 0x01C60888) &&
+				(*(unsigned int *)(mem + q) == 0xA9C8C8C8)) {
+				unp->_depAdr = 0x100;
+				unp->_endAdr = READ_LE_INT16(&mem[p + 0x0f]); // mem[p + 0x0f] | mem[p + 0x10] << 8;
+				unp->_retAdr = READ_LE_INT16(&mem[q + 0x38]); // mem[q + 0x38] | mem[q + 0x39] << 8;
+				if (unp->_info->_run == -1)
+					unp->_forced = 0x80b;
+				unp->_fStrAf = 0xfc;
+				unp->_idFlag = 1;
+				return;
+			}
+		}
+	}
+	/* cruel 1.2 / unknown 2059 */
+	if (unp->_depAdr == 0) {
+		if ((*(unsigned int *)(mem + 0x80b) == 0xE67800A0) &&
+			(*(unsigned int *)(mem + 0x80f) == 0x0803B901) &&
+			(*(unsigned int *)(mem + 0x813) == 0xC800E399) &&
+			(*(unsigned int *)(mem + 0x817) == 0x004CF7D0) &&
+			(*(unsigned int *)(mem + 0x90b) == 0xC068FEC6)) {
+			unp->_depAdr = 0x100;
+			unp->_forced = 0x80b;
+			unp->_retAdr = READ_LE_INT16(&mem[0x91c]); // mem[0x91c] | mem[0x91d] << 8;
+			unp->_endAdr = 0x2d;
+			unp->_fStrAf = 0xfc;
+			unp->_idFlag = 1;
+			return;
+		}
+		/* this was found in Agile and S451 cracks, Galleon's "Cruel+Search"
+		   it's actually the real v1.0
+		*/
+		if ((*(unsigned int *)(mem + 0x80b) == 0xE67800A0) &&
+			(*(unsigned int *)(mem + 0x80f) == 0x0803B901) &&
+			(*(unsigned int *)(mem + 0x813) == 0xC800E399) &&
+			(*(unsigned int *)(mem + 0x8c5) == 0x011D4C04) &&
+			(*(unsigned int *)(mem + 0x90b) == 0xB1486018)) {
+			unp->_depAdr = 0x100;
+			unp->_forced = 0x80b;
+			unp->_retAdr = READ_LE_INT16(&mem[0x92d]); // mem[0x92d] | mem[0x92e] << 8;
+			unp->_endAdr = 0x2d;
+			unp->_fStrAf = 0xfc;
+			unp->_idFlag = 1;
+			return;
+		}
+		if ((*(unsigned int *)(mem + 0x80b) == 0xE67800A0) &&
+			(*(unsigned int *)(mem + 0x80f) == 0x0803B901) &&
+			(*(unsigned int *)(mem + 0x813) == 0xC800E399) &&
+			(*(unsigned int *)(mem + 0x8b7) == 0x011D4C04) &&
+			(*(unsigned int *)(mem + 0x8fc) == 0xB1486018)) {
+			unp->_depAdr = 0x100;
+			unp->_forced = 0x80b;
+			unp->_retAdr = READ_LE_INT16(&mem[0x91e]); // mem[0x91e] | mem[0x91f] << 8;
+			unp->_endAdr = 0x2d;
+			unp->_fStrAf = 0xfc;
+			unp->_idFlag = 1;
+			return;
+		}
+	}
+
+	/* TKC "proggy crueler 2.3" (and 2.5) */
+	if (unp->_depAdr == 0) {
+		if ((mem[0x810] == 0xb9) && (mem[0x819] == 0xa9) &&
+			(*(unsigned int *)(mem + 0x813) == 0xC800fa99) &&
+			(*(unsigned int *)(mem + 0x822) == 0x4CAF86AE)) {
+			p = READ_LE_INT16(&mem[0x811]); // mem[0x811] | mem[0x812] << 8;
+			q = p - 0x100;
+
+			if ((*(unsigned int *)(mem + p + 0x0c) == 0x20F7D0C8) &&
+				(*(unsigned int *)(mem + q) == 0xA9C8C8C8)) {
+				unp->_depAdr = 0x100;
+				unp->_endAdr = READ_LE_INT16(&mem[p + 0x02]); // mem[p + 0x02] | mem[p + 0x03] << 8;
+				unp->_retAdr = READ_LE_INT16(&mem[q + 0x3f]); // mem[q + 0x3f] | mem[q + 0x40] << 8;
+				if (unp->_info->_run == -1)
+					unp->_forced = 0x80b;
+				unp->_fStrAf = 0xfc;
+				unp->_idFlag = 1;
+				return;
+			}
+		}
+	}
+}
+
+} // End of namespace Scott
+} // End of namespace Glk


Commit: 0c1f97c0e4113b88641eccaaf7cc190fa818de9e
    https://github.com/scummvm/scummvm/commit/0c1f97c0e4113b88641eccaaf7cc190fa818de9e
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Implement eca.cpp

Changed paths:
  A engines/glk/scott/unp64/scanners/eca.cpp
    engines/glk/module.mk


diff --git a/engines/glk/module.mk b/engines/glk/module.mk
index a1def2cec55..8c3ff03b131 100644
--- a/engines/glk/module.mk
+++ b/engines/glk/module.mk
@@ -261,6 +261,7 @@ MODULE_OBJS := \
 	scott/unp64/scanners/caution.o \
 	scott/unp64/scanners/ccs.o \
 	scott/unp64/scanners/cruel.o \
+	scott/unp64/scanners/eca.o \
 	tads/os_banners.o \
 	tads/os_buffer.o \
 	tads/os_glk.o \
diff --git a/engines/glk/scott/unp64/scanners/eca.cpp b/engines/glk/scott/unp64/scanners/eca.cpp
new file mode 100644
index 00000000000..121305fd31a
--- /dev/null
+++ b/engines/glk/scott/unp64/scanners/eca.cpp
@@ -0,0 +1,184 @@
+/* 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 "common/endian.h"
+#include "glk/scott/types.h"
+#include "glk/scott/unp64/unp64.h"
+
+namespace Glk {
+namespace Scott {
+
+void scnECA(UnpStr *unp) {
+	byte *mem;
+	int q, p;
+	if (unp->_idFlag)
+		return;
+	mem = unp->_mem;
+	if (unp->_depAdr == 0) {
+		// for(p=0x810;p<0x830;p+=0x4)
+		for (p = 0x80d; p < 0x830; p += 0x1) {
+			if ((*(unsigned int *)(mem + p + 0x08) == (unsigned int)0x2D9D0032 + p) &&
+				(*(unsigned int *)(mem + p + 0x3a) == 0x2a2a2a2a) &&
+				(*(unsigned int *)(mem + p + 0x0c) == 0xF710CA00)) {
+				if (((*(unsigned int *)(mem + p + 0x00) & 0xf4fff000) == 0x8434A000) &&
+					(*(unsigned int *)(mem + p + 0x04) == 0xBD05A201)) {
+					unp->_forced = p + 1;
+				} else if (((*(unsigned int *)(mem + p + 0x00) & 0xffffff00) == 0x04A27800) &&
+						   (*(unsigned int *)(mem + p + 0x04) == 0xBDE80186)) {
+					unp->_forced = p + 1;
+				} else if (((*(unsigned int *)(mem + p - 0x03) & 0xffffff00) == 0x04A27800) &&
+						   (*(unsigned int *)(mem + p + 0x04) == 0xBDE80186)) {
+					unp->_forced = p - 2;
+				} else if (*(unsigned int *)(mem + p - 0x03) == 0x8D00a978) {
+					unp->_forced = p - 2;
+				}
+			}
+			if (!unp->_forced) {
+				if ((*(unsigned int *)(mem + p + 0x3a) == 0x2a2a2a2a) &&
+					(*(unsigned int *)(mem + p + 0x02) == 0x8534A978) &&
+					(mem[p - 3] == 0xa0)) {
+					unp->_forced = p - 3;
+					if (mem[p + 0x0d6] == 0x20 && mem[p + 0x0d7] == 0xe0 &&
+						mem[p + 0x0d8] == 0x03 && mem[p + 0x1da] == 0x5b &&
+						mem[p + 0x1e7] == 0x59) {
+						/* antiprotection :D */
+						mem[p + 0x0d6] = 0x4c;
+						mem[p + 0x0d7] = 0xae;
+						mem[p + 0x0d8] = 0xa7;
+					}
+				}
+			}
+			if (!unp->_forced) { /* FDT */
+				if ((*(unsigned int *)(mem + p + 0x3a) == 0x2a2a2a2a) &&
+					(*(unsigned int *)(mem + p + 0x03) == 0x8604A278) &&
+					(*(unsigned int *)(mem + p + 0x0a) == 0x2D950842)) {
+					unp->_forced = p + 3;
+				}
+			}
+			if (!unp->_forced) {
+				/* decibel hacks */
+				if ((*(unsigned int *)(mem + p + 0x3a) == 0x2a2a2a2a) &&
+					(*(unsigned int *)(mem + p + 0x00) == 0x9D085EBD) &&
+					(*(unsigned int *)(mem + p - 0x06) == 0x018534A9)) {
+					unp->_forced = p - 0x6;
+				}
+			}
+			if (unp->_forced) {
+				for (q = 0xd6; q < 0xde; q++) {
+					if (mem[p + q] == 0x20) {
+						if ((*(unsigned short int *)(mem + p + q + 1) == 0xa659) ||
+							(*(unsigned short int *)(mem + p + q + 1) == 0xff81) ||
+							(*(unsigned short int *)(mem + p + q + 1) == 0xe3bf) ||
+							(*(unsigned short int *)(mem + p + q + 1) == 0xe5a0) ||
+							(*(unsigned short int *)(mem + p + q + 1) == 0xe518)) {
+							mem[p + q] = 0x2c;
+							q += 2;
+							continue;
+						} else {
+							unp->_retAdr = READ_LE_INT16(&mem[p + q + 1]); // mem[p + q + 1] | mem[p + q + 2] << 8;
+							break;
+						}
+					}
+					if (mem[p + q] == 0x4c) {
+						unp->_retAdr = READ_LE_INT16(&mem[p + q + 1]); // mem[p + q + 1] | mem[p + q + 2] << 8;
+						break;
+					}
+				}
+				unp->_depAdr = READ_LE_INT16(&mem[p + 0x30]); // mem[p + 0x30] | mem[p + 0x31] << 8;
+				// some use $2d, some $ae
+				for (q = 0xed; q < 0x108; q++) {
+					if (*(unsigned int *)(mem + p + q) == 0xA518F7D0) {
+						unp->_endAdr = mem[p + q + 4];
+						// if(unp->_DebugP)
+						// printf("EndAdr from $%02x\n",unp->_endAdr);
+						break;
+					}
+				}
+				/*
+				if anything it's unpacked to $d000-efff, it will be copied
+				to $e000-ffff as last action in unpacker before starting.
+				0196  20 DA 01  JSR $01DA ; some have this jsr nopped, reloc doesn't
+				happen 0199  A9 37     LDA #$37 019b  85 01     STA $01 019d  58 CLI
+				019e  20 00 0D  JSR $0D00 ; retaddr can be either here or following
+				01a1  4C AE A7  JMP $A7AE
+				01da  B9 00 EF  LDA $EF00,Y
+				01dd  99 00 FF  STA $FF00,Y
+				01e0  C8        INY
+				01e1  D0 F7     BNE $01DA
+				01e3  CE DC 01  DEC $01DC
+				01e6  CE DF 01  DEC $01DF
+				01e9  AD DF 01  LDA $01DF
+				01ec  C9 DF     CMP #$DF   ;<< not fixed, found as lower as $44 for
+				example 01ee  D0 EA     BNE $01DA 01f0  60        RTS Because of this,
+				$d000-dfff will be a copy of $e000-efff. So if $2d points to >= $d000,
+				SOMETIMES it's better save upto $ffff or: mem[$2d]|(mem[$2e]+$10)<<8
+				Still it's not a rule and I don't know exactly when.
+				17/06/09: Implemented but still experimental, so better check
+				extensively. use -v to know when it does the adjustments. 28/10/09:
+				whoops, was clearing ONLY $d000-dfff =)
+				*/
+				unp->_strMem = READ_LE_INT16(&mem[p + 0x32]); // mem[p + 0x32] | mem[p + 0x33] << 8;
+				for (q = 0xcd; q < 0xd0; q++) {
+					if ((*(unsigned int *)(mem + p + q) & 0xffff00ff) == 0xa9010020) {
+						unp->_ecaFlg = READ_LE_INT16(&mem[p + q + 1]); // mem[p + q + 1] | mem[p + q + 2] << 8;
+						for (q = 0x110; q < 0x11f; q++) {
+							if ((*(unsigned int *)(mem + p + q) == 0x99EF00B9) &&
+								(mem[p + q + 0x12] == 0xc9)) {
+								unp->_ecaFlg |= (mem[p + q + 0x13] - 0xf) << 24;
+								break;
+							}
+						}
+						break;
+					}
+				}
+				/* radwar hack has a BRK here, fffe/f used as IRQ/BRK vector */
+				if (mem[0x8e1] == 0) {
+					mem[0x8e1] = 0x6c;
+					mem[0x8e2] = 0xfe;
+					mem[0x8e3] = 0xff;
+				}
+				break;
+			}
+		}
+		if (unp->_depAdr) {
+			unp->_idFlag = 1;
+			return;
+		}
+	}
+	/* old packer, many old 1985 warez used this */
+	if (unp->_depAdr == 0) {
+		if ((*(unsigned int *)(mem + 0x81b) == 0x018534A9) &&
+			(*(unsigned int *)(mem + 0x822) == 0xAFC600A0) &&
+			(*(unsigned int *)(mem + 0x826) == 0xB1082DCE) &&
+			(*(unsigned int *)(mem + 0x85b) == 0x2A2A2A2A)) {
+			unp->_forced = 0x81b;
+			unp->_depAdr = 0x100;
+			unp->_strMem = READ_LE_INT16(&mem[0x853]); // mem[0x853] | mem[0x854] << 8;
+			unp->_endAdr = mem[0x895];
+			unp->_retAdr = READ_LE_INT16(&mem[0x885]); // mem[0x885] | mem[0x886] << 8;
+			unp->_idFlag = 1;
+			return;
+		}
+	}
+}
+
+} // End of namespace Scott
+} // End of namespace Glk


Commit: bc928dd14f2a2c841381325a85592f31bd38c9d4
    https://github.com/scummvm/scummvm/commit/bc928dd14f2a2c841381325a85592f31bd38c9d4
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Implement exomizer.cpp

Changed paths:
  A engines/glk/scott/unp64/scanners/exomizer.cpp
    engines/glk/module.mk


diff --git a/engines/glk/module.mk b/engines/glk/module.mk
index 8c3ff03b131..273dab4b062 100644
--- a/engines/glk/module.mk
+++ b/engines/glk/module.mk
@@ -262,6 +262,7 @@ MODULE_OBJS := \
 	scott/unp64/scanners/ccs.o \
 	scott/unp64/scanners/cruel.o \
 	scott/unp64/scanners/eca.o \
+	scott/unp64/scanners/exomizer.o \
 	tads/os_banners.o \
 	tads/os_buffer.o \
 	tads/os_glk.o \
diff --git a/engines/glk/scott/unp64/scanners/exomizer.cpp b/engines/glk/scott/unp64/scanners/exomizer.cpp
new file mode 100644
index 00000000000..68fad9d564d
--- /dev/null
+++ b/engines/glk/scott/unp64/scanners/exomizer.cpp
@@ -0,0 +1,177 @@
+/* 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 "common/endian.h"
+#include "glk/scott/types.h"
+#include "glk/scott/unp64/unp64.h"
+#include "glk/scott/unp64/exo_util.h"
+
+namespace Glk {
+namespace Scott {
+
+void scnExomizer(UnpStr *unp) {
+	byte *mem;
+	int q, p;
+	if (unp->_idFlag)
+		return;
+	mem = unp->_mem;
+	/* exomizer 3.x */
+	if (unp->_depAdr == 0) {
+		for (p = unp->_info->_end; p > unp->_info->_start; p--) {
+			if ((*(unsigned int *)(mem + p) == 0x100A8069) &&
+				(*(unsigned int *)(mem + p + 4) == 0xD0FD060F) &&
+				mem[p - 6] == 0x4c && mem[p - 4] == 0x01) {
+				p -= 5;
+				q = 2;
+				if (mem[p - q] == 0x8a)
+					q++;
+
+				/* low byte of EndAdr, it's a lda $ff00,y */
+
+				if ((mem[p - q - 1] == mem[p - q - 3]) &&
+					(mem[p - q - 2] == mem[p - q])) { /* a0 xx a0 xx -> exomizer 3.0/3.01 */
+					unp->_exoFnd = 0x30;
+				} else { /* d0 c1 a0 xx -> exomizer 3.0.2, force +1 in start/end */
+					unp->_exoFnd = 0x32;
+				}
+				unp->_exoFnd |= (mem[p - q] << 8);
+				break;
+			}
+		}
+		if (unp->_exoFnd) {
+			unp->_depAdr = 0x100 | mem[p];
+			for (; p < unp->_info->_end; p++) {
+				if (*(unsigned int *)(mem + p) == 0x7d010020)
+					break;
+			}
+			for (; p < unp->_info->_end; p++) {
+				if (mem[p] == 0x4c) {
+					unp->_retAdr = 0;
+					if ((unp->_retAdr = READ_LE_INT16(&mem[p + 1])) >= 0x200) {
+						break;
+					} else { /* it's a jmp $01xx, goto next */
+						p++;
+						p++;
+					}
+				}
+			}
+			if (unp->_info->_run == -1) {
+				p = unp->_info->_start;
+				q = p + 0x10;
+				for (; p < q; p++) {
+					if ((mem[p] == 0xba) && (mem[p + 1] == 0xbd)) {
+						unp->_forced = p;
+						break;
+					}
+				}
+				for (q = p - 1; q >= unp->_info->_start; q--) {
+					if (mem[q] == 0xe6)
+						unp->_forced = q;
+					if (mem[q] == 0xa0)
+						unp->_forced = q;
+					if (mem[q] == 0x78)
+						unp->_forced = q;
+				}
+			}
+		}
+	}
+	/* exomizer 1.x/2.x */
+	if (unp->_depAdr == 0) {
+		for (p = unp->_info->_end; p > unp->_info->_start; p--) {
+			if ((((*(unsigned int *)(mem + p) == 0x4CF7D088) &&
+				  (*(unsigned int *)(mem + p - 0x0d) == 0xD034C0C8)) ||
+				 ((*(unsigned int *)(mem + p) == 0x4CA7A438) &&
+				  (*(unsigned int *)(mem + p - 0x0c) == 0x799FA5AE)) ||
+				 ((*(unsigned int *)(mem + p) == 0x4CECD08A) &&
+				  (*(unsigned int *)(mem + p - 0x13) == 0xCECA0EB0)) ||
+				 ((*(unsigned int *)(mem + p) == 0x4C00A0D3) &&
+				  (*(unsigned int *)(mem + p - 0x04) == 0xD034C0C8)) ||
+				 ((*(unsigned int *)(mem + p) == 0x4C00A0D2) &&
+				  (*(unsigned int *)(mem + p - 0x04) == 0xD034C0C8))) &&
+				mem[p + 5] == 1) {
+				p += 4;
+				unp->_exoFnd = 1;
+				break;
+			} else if ((((*(unsigned int *)(mem + p) == 0x8C00A0d2) &&
+						 (*(unsigned int *)(mem + p - 0x04) == 0xD034C0C8)) ||
+						((*(unsigned int *)(mem + p) == 0x8C00A0d3) &&
+						 (*(unsigned int *)(mem + p - 0x04) == 0xD034C0C8)) ||
+						((*(unsigned int *)(mem + p) == 0x8C00A0cf) &&
+						 (*(unsigned int *)(mem + p - 0x04) == 0xD034C0C8))) &&
+					   mem[p + 6] == 0x4c && mem[p + 8] == 1) {
+				p += 7;
+				unp->_exoFnd = 1;
+				break;
+			}
+		}
+		if (unp->_exoFnd) {
+			unp->_depAdr = 0x100 | mem[p];
+			if (unp->_depAdr >= 0x134 && unp->_depAdr <= 0x14a /*0x13e*/) {
+				for (p = unp->_info->_end - 4; p > unp->_info->_start;
+					 p--) { /* 02 04 04 30 20 10 80 00 */
+					if (*(unsigned int *)(mem + p) == 0x30040402)
+						break;
+				}
+			} else {
+				// exception for exo v1.x, otherwise add 8 to the counter and
+				// scan backward from here
+				if (unp->_depAdr != 0x143)
+					p += 0x08;
+				else
+					p -= 0xb8;
+			}
+			for (; p > unp->_info->_start; p--) {
+				// incredibly there can be a program starting at $4c00 :P
+				if ((mem[p] == 0x4c) && (mem[p - 1] != 0x4c) && (mem[p - 2] != 0x4c)) {
+					unp->_retAdr = 0;
+					if ((unp->_retAdr = READ_LE_INT16(&mem[p + 1])) >= 0x200) {
+						break;
+					}
+				}
+			}
+			if (unp->_info->_run == -1) {
+				p = unp->_info->_start;
+				q = p + 0x10;
+				for (; p < q; p++) {
+					if ((mem[p] == 0xba) && (mem[p + 1] == 0xbd)) {
+						unp->_forced = p;
+						break;
+					}
+				}
+				for (q = p - 1; q >= unp->_info->_start; q--) {
+					if (mem[q] == 0xe6)
+						unp->_forced = q;
+					if (mem[q] == 0xa0)
+						unp->_forced = q;
+					if (mem[q] == 0x78)
+						unp->_forced = q;
+				}
+			}
+		}
+	}
+	if (unp->_depAdr != 0) {
+		unp->_idFlag = 1;
+		return;
+	}
+}
+
+} // End of namespace Scott
+} // End of namespace Glk


Commit: ccc9e29b752adbe25b54527802681a3b409c419d
    https://github.com/scummvm/scummvm/commit/ccc9e29b752adbe25b54527802681a3b409c419d
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Implement expert.cpp

Changed paths:
  A engines/glk/scott/unp64/scanners/expert.cpp
    engines/glk/module.mk


diff --git a/engines/glk/module.mk b/engines/glk/module.mk
index 273dab4b062..f3fcca145ad 100644
--- a/engines/glk/module.mk
+++ b/engines/glk/module.mk
@@ -263,6 +263,7 @@ MODULE_OBJS := \
 	scott/unp64/scanners/cruel.o \
 	scott/unp64/scanners/eca.o \
 	scott/unp64/scanners/exomizer.o \
+	scott/unp64/scanners/expert.o \
 	tads/os_banners.o \
 	tads/os_buffer.o \
 	tads/os_glk.o \
diff --git a/engines/glk/scott/unp64/scanners/expert.cpp b/engines/glk/scott/unp64/scanners/expert.cpp
new file mode 100644
index 00000000000..56463ae2e20
--- /dev/null
+++ b/engines/glk/scott/unp64/scanners/expert.cpp
@@ -0,0 +1,247 @@
+/* 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 "common/endian.h"
+#include "glk/scott/types.h"
+#include "glk/scott/unp64/unp64.h"
+#include "glk/scott/unp64/exo_util.h"
+
+namespace Glk {
+namespace Scott {
+
+void scnExpert(UnpStr *unp) {
+	byte *mem;
+	int q, p;
+	if (unp->_idFlag)
+		return;
+	mem = unp->_mem;
+	if (unp->_depAdr == 0) {
+		for (q = 0x81b; q < 0x81d; q++) {
+			if ((*(unsigned int *)(mem + q + 0x00) == 0x852FA978) &&
+				(*(unsigned int *)(mem + q + 0x04) == 0x8534A900) &&
+				(*(unsigned int *)(mem + q + 0x14) == 0x03860286)) {
+				for (p = 0x900; p < 0xfff0; p++) {
+					if ((*(unsigned int *)(mem + p + 1) == 0x00084C9A) &&
+						(*(unsigned int *)(mem + p - 4) == 0xA2058604)) {
+						if (unp->_info->_run == -1) {
+							unp->_forced = q;
+							unp->_info->_run = q;
+						}
+						q = 0x100 + mem[p] + 1;
+						if (q != 0x100) {
+							unp->_depAdr = q;
+						}
+					}
+				}
+				break;
+			}
+		}
+		if (unp->_depAdr) {
+			unp->_rtiFrc = 1;
+			if (*(unsigned int *)(mem + 0x835) == 0x6E8D48A9) {
+				p = 0;
+				if (*(unsigned int *)(mem + 0x92c) == 0x4902B100) {
+					if (!unp->_idOnly) {
+						p = 0x876;
+						mem[p] = 0x00; /* 1st anti hack */
+						p = mem[0x930];
+					}
+				} else if (*(unsigned int *)(mem + 0x92f) == 0x4902B100) {
+					if (!unp->_idOnly) {
+						p = 0x873;
+						mem[p] = 0xa9; /* 1st anti hack */
+						mem[p + 1] = 0x02;
+						p = mem[0x933];
+					}
+				}
+				if (p && !unp->_idOnly) {
+					p |= (p << 24) | (p << 16) | (p << 8);
+					for (q = 0x980; q < 0xfff0; q++) {
+						if (((mem[q] ^ (p & 0xff)) == 0xac) &&
+							((mem[q + 3] ^ (p & 0xff)) == 0xc0) &&
+							(((*(unsigned int *)(mem + q + 7)) ^ p) == 0xC001F2AC)) {
+							mem[q + 0x06] = (p & 0xff); /* 2nd anti hack */
+							mem[q + 0x0d] = (p & 0xff);
+							break;
+						}
+					}
+				}
+			}
+		}
+	}
+	if (unp->_depAdr == 0) {
+		if ((*(unsigned int *)(mem + 0x81b) == 0x2FA9D878) &&
+			(*(unsigned int *)(mem + 0x82d) == 0x0873BDB0)) {
+			for (p = 0x900; p < 0xfff0; p++) {
+				if ((*(unsigned int *)(mem + p) == 0xA2F3D0CA) &&
+					(mem[p + 0x05] == 0x4c)) {
+					q = READ_LE_INT16(&mem[p + 0x06]); // mem[p + 0x06] | mem[p + 0x07] << 8;
+					if (q != 0x100) {
+						unp->_depAdr = q;
+						break;
+					}
+				}
+			}
+			if (unp->_depAdr) {
+				unp->_rtiFrc = 1;
+				unp->_forced = 0x81b;
+			}
+		}
+	}
+	/* 2.9 Expert User Club version, found in
+	   BloodMoney/HTL & SWIV/Inceria
+	*/
+	if (unp->_depAdr == 0) {
+		if ((*(unsigned int *)(mem + 0x81b) == 0x8C00A078) &&
+			(*(unsigned int *)(mem + 0x831) == 0x05860485) &&
+			(*(unsigned int *)(mem + 0x998) == 0x00084C9A)) {
+			p = mem[0x919];
+			q = p << 24 | p << 16 | p << 8 | p;
+			for (p = 0x900; p < 0xfff0; p++) {
+				if (((*(unsigned int *)(mem + p) ^ q) == 0xA2F3D0CA) &&
+					((mem[p + 0x05] ^ (q & 0xff)) == 0x4c)) {
+					q = (mem[p + 0x06] ^ (q & 0xff)) | (mem[p + 0x07] ^ (q & 0xff)) << 8;
+					if (q != 0x100) {
+						unp->_depAdr = q;
+						break;
+					}
+				}
+			}
+			if (unp->_depAdr) {
+				unp->_rtiFrc = 1;
+				unp->_forced = 0x81b;
+			}
+		}
+	}
+	/* sys2070 A.S.S. */
+	if (unp->_depAdr == 0) {
+		if ((*(unsigned int *)(mem + 0x817) == 0x00852FA9) &&
+			(*(unsigned int *)(mem + 0x823) == 0x05860485) &&
+			(*(unsigned int *)(mem + 0x9a0) == 0x00084C9A)) {
+			p = mem[0x923];
+			q = p << 24 | p << 16 | p << 8 | p;
+			for (p = 0x900; p < 0xfff0; p++) {
+				if (((*(unsigned int *)(mem + p) ^ q) == 0xA2F3D0CA) &&
+					((mem[p + 0x05] ^ (q & 0xff)) == 0x4c)) {
+					q = (mem[p + 0x06] ^ (q & 0xff)) | (mem[p + 0x07] ^ (q & 0xff)) << 8;
+					if (q != 0x100) {
+						unp->_depAdr = q;
+						break;
+					}
+				}
+			}
+			if (unp->_depAdr) {
+				unp->_rtiFrc = 1;
+				unp->_forced = 0x81b;
+			}
+		}
+	}
+	if (unp->_depAdr == 0) {
+		if ((*(unsigned int *)(mem + 0x81b) == 0x7FA978D8) ||
+			(*(unsigned int *)(mem + 0x81b) == 0x7FA9D878) ||
+			(*(unsigned int *)(mem + 0x816) == 0x7FA978D8)) {
+			for (p = 0x900; p < 0xfff0; p++) {
+				if ((*(unsigned int *)(mem + p) == 0xA2F3D0CA) &&
+					(mem[p + 0x05] == 0x4c)) {
+					q = READ_LE_INT16(&mem[p + 0x06]); // mem[p + 0x06] | mem[p + 0x07] << 8;
+					if (q != 0x100) {
+						unp->_depAdr = q;
+						break;
+					}
+				}
+			}
+			if (unp->_depAdr) {
+				unp->_rtiFrc = 1;
+				if (*(unsigned int *)(mem + 0x816) == 0x7FA978D8) {
+					q = 0x816;
+					if (!unp->_idOnly) {
+						for (p = 0x900; p < 0xfff0; p++) {
+							if ((*(unsigned int *)(mem + p) == 0xE0A9F0A2) &&
+								(*(unsigned int *)(mem + p + 4) == 0xE807135D) &&
+								(mem[p + 0x8] == 0xd0)) {
+								mem[p + 0x1] = 0x00;
+								mem[p + 0x3] = 0x98;
+								memset(mem + p + 4, 0xea, 6);
+								break;
+							}
+						}
+					}
+				} else {
+					q = 0x81b;
+					if (!unp->_idOnly) {
+						for (p = 0x900; p < 0xfff0; p++) {
+							if ((*(unsigned int *)(mem + p) == 0xCA08015D) &&
+								(*(unsigned int *)(mem + p + 4) == 0xF8D003E0) &&
+								(mem[p + 0xa] == 0xd0)) {
+								p += 0xa;
+								mem[p] = 0x24;
+								break;
+							}
+						}
+					}
+				}
+				if (unp->_info->_run == -1) {
+					unp->_forced = q;
+					unp->_info->_run = q;
+				}
+			}
+		}
+	}
+	if (unp->_depAdr == 0) {
+		q = 0x81b;
+		if ((*(unsigned int *)(mem + q + 0x00) == 0x852FA978) &&
+			(*(unsigned int *)(mem + q + 0x04) == 0x8534A900) &&
+			(*(unsigned int *)(mem + q + 0x14) == 0x03860286) &&
+			(*(unsigned int *)(mem + q + 0x4f) == 0xA200594C) &&
+			(*(unsigned int *)(mem + q + 0xad) == 0x2000124C)) {
+			unp->_forced = q;
+			unp->_info->_run = q;
+			unp->_depAdr = 0x12;
+			unp->_rtiFrc = 1;
+		}
+	}
+	/* expert 2.11 (sys2074) & unknown sys2061 */
+	if (unp->_depAdr == 0) {
+		for (q = 0x80d; q < 0x820; q++) {
+			if ((*(unsigned int *)(mem + q + 0x00) == 0x852FA978) &&
+				(*(unsigned int *)(mem + q + 0x04) == 0x8534A900) &&
+				(*(unsigned int *)(mem + q + 0x13) == 0x03840284) &&
+				(*(unsigned int *)(mem + q + 0x4f) == 0x084C003A) &&
+				(*(unsigned int *)(mem + q + 0xad) == 0x00AA2048)) {
+				unp->_forced = q;
+				unp->_info->_run = q;
+				unp->_depAdr = 0x100 + mem[q + 0x17a] + 1;
+				break;
+			}
+		}
+		if (unp->_depAdr != 0) {
+			unp->_rtiFrc = 1;
+		}
+	}
+
+	if (unp->_depAdr != 0) {
+		unp->_idFlag = 1;
+		return;
+	}
+}
+
+} // End of namespace Scott
+} // End of namespace Glk


Commit: 103b17df5d506114043813a64e20d0fea5437017
    https://github.com/scummvm/scummvm/commit/103b17df5d506114043813a64e20d0fea5437017
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Implement master_compressor.cpp

Changed paths:
  A engines/glk/scott/unp64/scanners/master_compressor.cpp
    engines/glk/module.mk


diff --git a/engines/glk/module.mk b/engines/glk/module.mk
index f3fcca145ad..40398da10d8 100644
--- a/engines/glk/module.mk
+++ b/engines/glk/module.mk
@@ -264,6 +264,7 @@ MODULE_OBJS := \
 	scott/unp64/scanners/eca.o \
 	scott/unp64/scanners/exomizer.o \
 	scott/unp64/scanners/expert.o \
+	scott/unp64/scanners/master_compressor.o \
 	tads/os_banners.o \
 	tads/os_buffer.o \
 	tads/os_glk.o \
diff --git a/engines/glk/scott/unp64/scanners/master_compressor.cpp b/engines/glk/scott/unp64/scanners/master_compressor.cpp
new file mode 100644
index 00000000000..ae75efaf572
--- /dev/null
+++ b/engines/glk/scott/unp64/scanners/master_compressor.cpp
@@ -0,0 +1,124 @@
+/* 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 "common/endian.h"
+#include "glk/scott/types.h"
+#include "glk/scott/unp64/unp64.h"
+
+namespace Glk {
+namespace Scott {
+
+void scnMasterCompressor(UnpStr *unp) {
+	byte *mem;
+	int p;
+	if (unp->_idFlag)
+		return;
+	mem = unp->_mem;
+	if (unp->_depAdr == 0) {
+		for (p = 0x80d; p < 0x880; p++) {
+			if (((*(unsigned int *)(mem + p + 0x005) & 0x00ffffff) == 0x00BDD2A2) &&
+				 (*(unsigned int *)(mem + p + 0x00a) == 0xE000F99D) &&
+				 (*(unsigned int *)(mem + p + 0x017) == 0xCAEDD0CA) &&
+				 (*(unsigned int *)(mem + p + 0x031) == 0x84C82E86) &&
+				 ((*(unsigned int *)(mem + p + 0x035) & 0x0000ffff) == 0x00004C2D) &&
+				 (*(unsigned int *)(mem + p + 0x134) == 0xDBD0FFE6)) {
+				if (/*mem[p]==0x78&&*/ mem[p + 1] == 0xa9 &&
+					(*(unsigned int *)(mem + p + 0x003) == 0xD2A20185)) {
+					unp->_depAdr = READ_LE_INT16(&mem[p + 0x37]); // mem[p + 0x37] | mem[p + 0x38] << 8;
+					unp->_forced = p + 1;
+					if (mem[p + 0x12b] == 0x020) // jsr $0400, unuseful fx
+						mem[p + 0x12b] = 0x2c;
+				} else if (*(unsigned int *)(mem + p) == 0xD024E0E8) {
+					/* HTL version */
+					unp->_depAdr = READ_LE_INT16(&mem[p + 0x37]); // mem[p + 0x37] | mem[p + 0x38] << 8;
+					unp->_forced = 0x840;
+				}
+				if (unp->_depAdr) {
+					unp->_retAdr = READ_LE_INT16(&mem[p + 0x13e]); // mem[p + 0x13e] | mem[p + 0x13f] << 8;
+					unp->_endAdr = 0x2d;
+					unp->_fStrBf = unp->_endAdr;
+					unp->_idFlag = 1;
+					return;
+				}
+			}
+		}
+	}
+	if (unp->_depAdr == 0) {
+		for (p = 0x80d; p < 0x880; p++) {
+			if (((*(unsigned int *)(mem + p + 0x005) & 0x00ffffff) == 0x00BDD2A2) &&
+				 (*(unsigned int *)(mem + p + 0x00a) == 0xE000F99D) &&
+				 (*(unsigned int *)(mem + p + 0x017) == 0xCAEDD0CA) &&
+				 (*(unsigned int *)(mem + p + 0x031) == 0x84C82E86) &&
+				 ((*(unsigned int *)(mem + p + 0x035) & 0x0000ffff) == 0x00004C2D) &&
+				 (*(unsigned int *)(mem + p + 0x12d) == 0xe2D0FFE6)) {
+				if (mem[p + 1] == 0xa9 &&
+					(*(unsigned int *)(mem + p + 0x003) == 0xD2A20185)) {
+					unp->_depAdr = READ_LE_INT16(&mem[p + 0x37]); // mem[p + 0x37] | mem[p + 0x38] << 8;
+					unp->_forced = p + 1;
+				}
+				if (unp->_depAdr) {
+					if (mem[p + 0x136] == 0x4c)
+						unp->_retAdr = READ_LE_INT16(&mem[p + 0x137]); // mem[p + 0x137] | mem[p + 0x138] << 8;
+					else if (mem[p + 0x13d] == 0x4c)
+						unp->_retAdr = READ_LE_INT16(&mem[p + 0x13e]); // mem[p + 0x13e] | mem[p + 0x13f] << 8;
+					unp->_endAdr = 0x2d;
+					unp->_fStrBf = unp->_endAdr;
+					unp->_idFlag = 1;
+					return;
+				}
+			}
+		}
+	}
+	if (unp->_depAdr == 0) {
+		p = 0x812;
+		if ((*(unsigned int *)(mem + p + 0x000) == 0xE67800A0) &&
+			(*(unsigned int *)(mem + p + 0x004) == 0x0841B901) &&
+			(*(unsigned int *)(mem + p + 0x008) == 0xB900FA99) &&
+			(*(unsigned int *)(mem + p + 0x00c) == 0x34990910)) {
+			unp->_depAdr = 0x100;
+			unp->_forced = p;
+			unp->_retAdr = READ_LE_INT16(&mem[0x943]); // mem[0x943] | mem[0x944] << 8;
+			unp->_endAdr = 0x2d;
+			unp->_fStrBf = unp->_endAdr;
+			unp->_idFlag = 1;
+			return;
+		}
+	}
+	/* Fred/Channel4 hack */
+	if (unp->_depAdr == 0) {
+		if ((*(unsigned int *)(mem + 0x811) == 0xA9A98078) &&
+			(*(unsigned int *)(mem + 0x815) == 0x85EE8034) &&
+			(*(unsigned int *)(mem + 0x819) == 0x802DA201) &&
+			(*(unsigned int *)(mem + 0x882) == 0x01004C2D)) {
+			unp->_depAdr = 0x100;
+			unp->_forced = 0x811;
+			unp->_retAdr = READ_LE_INT16(&mem[0x98b]); // mem[0x98b] | mem[0x98c] << 8;
+			if (unp->_retAdr < 0x800)
+				unp->_rtAFrc = 1;
+			unp->_endAdr = 0x2d;
+			unp->_idFlag = 1;
+			return;
+		}
+	}
+}
+
+} // End of namespace Scott
+} // End of namespace Glk


Commit: 825efc500a46f5d7dc169a992459abbc9586168f
    https://github.com/scummvm/scummvm/commit/825efc500a46f5d7dc169a992459abbc9586168f
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Implement megabyte.cpp

Changed paths:
  A engines/glk/scott/unp64/scanners/megabyte.cpp
    engines/glk/module.mk


diff --git a/engines/glk/module.mk b/engines/glk/module.mk
index 40398da10d8..e9f27d37a70 100644
--- a/engines/glk/module.mk
+++ b/engines/glk/module.mk
@@ -265,6 +265,7 @@ MODULE_OBJS := \
 	scott/unp64/scanners/exomizer.o \
 	scott/unp64/scanners/expert.o \
 	scott/unp64/scanners/master_compressor.o \
+	scott/unp64/scanners/megabyte.o \
 	tads/os_banners.o \
 	tads/os_buffer.o \
 	tads/os_glk.o \
diff --git a/engines/glk/scott/unp64/scanners/megabyte.cpp b/engines/glk/scott/unp64/scanners/megabyte.cpp
new file mode 100644
index 00000000000..7a2f874a568
--- /dev/null
+++ b/engines/glk/scott/unp64/scanners/megabyte.cpp
@@ -0,0 +1,82 @@
+/* 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 "common/endian.h"
+#include "glk/scott/types.h"
+#include "glk/scott/unp64/unp64.h"
+#include "glk/scott/unp64/exo_util.h"
+
+namespace Glk {
+namespace Scott {
+
+void scnMegabyte(UnpStr *unp) {
+	byte *mem;
+	int p;
+	if (unp->_idFlag)
+		return;
+	mem = unp->_mem;
+	if (unp->_depAdr == 0) {
+		p = 0;
+		if (mem[0x816] == 0x4c)
+			p = READ_LE_INT16(&mem[0x817]); // mem[0x817] | mem[0x818] << 8;
+		else if ((unp->_info->_run == 0x810) && (mem[0x814] == 0x4c) &&
+				 ((*(unsigned int *)(mem + 0x810) & 0xffff00ff) == 0x018500A9))
+			p = READ_LE_INT16(&mem[0x815]); // mem[0x815] | mem[0x816] << 8;
+		if (p) {
+			if ((mem[p + 0] == 0x78) && (mem[p + 1] == 0xa2) &&
+				(mem[p + 3] == 0xa0) &&
+				(*(unsigned int *)(mem + p + 0x05) == 0x15841486) &&
+				(*(unsigned int *)(mem + p + 0x1d) == 0x03804CF7)) {
+				unp->_depAdr = 0x380;
+				unp->_endAdr = READ_LE_INT16(&mem[p + 0x55]); // mem[p + 0x55] | mem[p + 0x56] << 8;
+				unp->_endAdr++;
+				unp->_strMem = 0x801;
+				unp->_retAdr = 0x801; /* ususally it just runs */
+				unp->_idFlag = 1;
+				return;
+			}
+		}
+	}
+	if (unp->_depAdr == 0) {
+		p = 0;
+		if ((mem[0x81a] == 0x4c) &&
+			((*(unsigned int *)(mem + 0x816) & 0xffff00ff) == 0x018500A9))
+			p = READ_LE_INT16(&mem[0x81b]); // mem[0x81b] | mem[0x81c] << 8;
+		if (p) {
+			if ((mem[p + 0] == 0x78) && (mem[p + 1] == 0xa2) &&
+				(mem[p + 3] == 0xa0) &&
+				(*(unsigned int *)(mem + p + 0x05) == 0x15841486) &&
+				(*(unsigned int *)(mem + p + 0x1d) == 0x03844CF7)) {
+				unp->_depAdr = 0x384;
+				unp->_forced = 0x816;
+				unp->_endAdr = READ_LE_INT16(&mem[p + 0x59]); // mem[p + 0x59] | mem[p + 0x5a] << 8;
+				unp->_endAdr++;
+				unp->_strMem = 0x801;
+				unp->_retAdr = 0x801; /* ususally it just runs */
+				unp->_idFlag = 1;
+				return;
+			}
+		}
+	}
+}
+
+} // End of namespace Scott
+} // End of namespace Glk


Commit: 81e0cb9bc56e3d5dde3ef8a50a5392f39d681df4
    https://github.com/scummvm/scummvm/commit/81e0cb9bc56e3d5dde3ef8a50a5392f39d681df4
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Implement pu_crunch.cpp

Changed paths:
  A engines/glk/scott/unp64/scanners/pu_crunch.cpp
    engines/glk/module.mk


diff --git a/engines/glk/module.mk b/engines/glk/module.mk
index e9f27d37a70..b1b7abb5702 100644
--- a/engines/glk/module.mk
+++ b/engines/glk/module.mk
@@ -266,6 +266,7 @@ MODULE_OBJS := \
 	scott/unp64/scanners/expert.o \
 	scott/unp64/scanners/master_compressor.o \
 	scott/unp64/scanners/megabyte.o \
+	scott/unp64/scanners/pu_crunch.o \
 	tads/os_banners.o \
 	tads/os_buffer.o \
 	tads/os_glk.o \
diff --git a/engines/glk/scott/unp64/scanners/pu_crunch.cpp b/engines/glk/scott/unp64/scanners/pu_crunch.cpp
new file mode 100644
index 00000000000..533d95dd1d0
--- /dev/null
+++ b/engines/glk/scott/unp64/scanners/pu_crunch.cpp
@@ -0,0 +1,194 @@
+/* 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 "common/endian.h"
+#include "glk/scott/types.h"
+#include "glk/scott/unp64/unp64.h"
+#include "glk/scott/unp64/exo_util.h"
+
+namespace Glk {
+namespace Scott {
+
+void scnPuCrunch(UnpStr *unp) {
+	byte *mem;
+	int q, p;
+	if (unp->_idFlag)
+		return;
+	mem = unp->_mem;
+	if (unp->_depAdr == 0) {
+		if ((mem[0x80d] == 0x78) &&
+			(*(unsigned int *)(mem + 0x813) == 0x34A20185) &&
+			(*(unsigned int *)(mem + 0x817) == 0x9D0842BD) &&
+			(*(unsigned int *)(mem + 0x81b) == 0xD0CA01FF) &&
+			(*(unsigned int *)(mem + 0x83d) == 0x4CEDD088)) {
+			for (p = 0x912; p < 0x938; p++) {
+				if ((*(unsigned int *)(mem + p) == 0x2D85FAA5) &&
+					(*(unsigned int *)(mem + p + 4) == 0x2E85FBA5)) {
+					unp->_endAdr = 0xfa;
+					unp->_strMem = READ_LE_INT16(&mem[0x879]); // mem[0x879] | mem[0x87a] << 8;
+					unp->_depAdr = READ_LE_INT16(&mem[0x841]); // mem[0x841] | mem[0x842] << 8;
+					unp->_retAdr = READ_LE_INT16(&mem[p + 0xa]); // mem[p + 0xa] | mem[p + 0xb] << 8;
+					unp->_forced = 0x80d;
+					break;
+				}
+			}
+		} else if ((mem[0x80d] == 0x78) &&
+				   (*(unsigned int *)(mem + 0x81a) == 0x10CA4B95) &&
+				   (*(unsigned int *)(mem + 0x81e) == 0xBD3BA2F8) &&
+				   (*(unsigned int *)(mem + 0x847) == 0x4CEDD088)) {
+			for (p = 0x912; p < 0x938; p++) {
+				if ((*(unsigned int *)(mem + p) == 0x2D85FAA5) &&
+					(*(unsigned int *)(mem + p + 4) == 0x2E85FBA5)) {
+					unp->_endAdr = 0xfa;
+					unp->_strMem = READ_LE_INT16(&mem[p + 0x88a]); // mem[0x88a] | mem[0x88b] << 8;
+					unp->_depAdr = READ_LE_INT16(&mem[p + 0x84b]); // mem[0x84b] | mem[0x84c] << 8;
+					unp->_retAdr = READ_LE_INT16(&mem[p + 0xa]); // mem[p + 0xa] | mem[p + 0xb] << 8;
+					unp->_forced = 0x80d;
+					break;
+				}
+			}
+		} else if ((mem[0x80d] == 0x78) &&
+				   (*(unsigned int *)(mem + 0x811) == 0x85AAA901) &&
+				   (*(unsigned int *)(mem + 0x81d) == 0xF69D083C) &&
+				   (*(unsigned int *)(mem + 0x861) == 0xC501C320) &&
+				   (*(unsigned int *)(mem + 0x839) == 0x01164CED)) {
+			unp->_endAdr = 0xfa;
+			unp->_strMem = READ_LE_INT16(&mem[0x840]); // mem[0x840] | mem[0x841] << 8;
+			unp->_depAdr = 0x116;
+			unp->_retAdr = READ_LE_INT16(&mem[0x8df]); // mem[0x8df] | mem[0x8e0] << 8;
+			unp->_forced = 0x80d;
+		} else if ((mem[0x80d] == 0x78) &&
+				   (*(unsigned int *)(mem + 0x811) == 0x85AAA901) &&
+				   (*(unsigned int *)(mem + 0x81d) == 0xF69D083C) &&
+				   (*(unsigned int *)(mem + 0x861) == 0xC501C820) &&
+				   (*(unsigned int *)(mem + 0x839) == 0x01164CED)) {
+			unp->_endAdr = 0xfa;
+			unp->_strMem = READ_LE_INT16(&mem[0x840]); // mem[0x840] | mem[0x841] << 8;
+			unp->_depAdr = 0x116;
+			if (mem[0x8de] == 0xa9) {
+				unp->_retAdr = READ_LE_INT16(&mem[0x8e1]); // mem[0x8e1] | mem[0x8e2] << 8;
+				if ((unp->_retAdr == 0xa871) && (mem[0x8e0] == 0x20) &&
+					(mem[0x8e3] == 0x4c)) {
+					mem[0x8e0] = 0x2c;
+					unp->_retAdr = READ_LE_INT16(&mem[0x8e4]); // mem[0x8e4] | mem[0x8e5] << 8;
+				}
+			} else {
+				unp->_retAdr = READ_LE_INT16(&mem[0x8df]); // mem[0x8df] | mem[0x8e0] << 8;
+			}
+			unp->_forced = 0x80d;
+		} else {
+			/* unknown old/hacked pucrunch ? */
+			for (p = 0x80d; p < 0x820; p++) {
+				if (mem[p] == 0x78) {
+					q = p;
+					for (; p < 0x824; p++) {
+						if (((*(unsigned int *)(mem + p) & 0xf0ffffff) == 0xF0BD53A2) &&
+							(*(unsigned int *)(mem + p + 4) == 0x01FF9D08) &&
+							(*(unsigned int *)(mem + p + 8) == 0xA2F7D0CA)) {
+							unp->_forced = q;
+							q = mem[p + 3] & 0xf; /* can be $f0 or $f2, q&0x0f as offset */
+							p = READ_LE_INT16(&mem[p + 0xe]); // mem[p + 0xe] | mem[p + 0xf] << 8;
+							if (mem[p - 2] == 0x4c && mem[p + 0xa0 + q] == 0x85) {
+								unp->_depAdr = READ_LE_INT16(&mem[p - 1]); // mem[p - 1] | mem[p] << 8;
+								unp->_strMem = READ_LE_INT16(&mem[p + 4]); // mem[p + 4] | mem[p + 5] << 8;
+								unp->_endAdr = 0xfa;
+								p += 0xa2;
+								q = p + 8;
+								for (; p < q; p++) {
+									if ((*(unsigned int *)(mem + p) == 0x2D85FAA5) &&
+										(mem[p + 9] == 0x4c)) {
+										unp->_retAdr = READ_LE_INT16(&mem[p + 0xa]); // mem[p + 0xa] | mem[p + 0xb] << 8;
+										break;
+									}
+								}
+							}
+						}
+					}
+				}
+			}
+		}
+
+		/* various old/hacked pucrunch */
+		/* common pattern, variable pos from 0x79 to 0xd1
+		90 ?? C8 20 ?? 0? 85 ?? C9 ?0 90 0B A2 0? 20 ?? 0? 85 ?? 20 ?? 0? A8 20 ??
+		0? AA BD ?? 0? E0 20 90 0? 8A (A2 03) not always 20 ?? 02 A6
+		?? E8 20 F9
+		*/
+		if (unp->_depAdr == 0) {
+			unp->_idFlag = 0;
+			for (q = 0x70; q < 0xff; q++) {
+				if (((*(unsigned int *)(mem + 0x801 + q) & 0xFFFF00FF) == 0x20C80090) &&
+					((*(unsigned int *)(mem + 0x801 + q + 8) & 0xFFFF0FFF) ==
+					 0x0B9000C9) &&
+					((*(unsigned int *)(mem + 0x801 + q + 12) & 0x00FFF0FF) ==
+					 0x002000A2) &&
+					((*(unsigned int *)(mem + 0x801 + q + 30) & 0xF0FFFFFf) ==
+					 0x009020E0)) {
+					unp->_idFlag = 385;
+					break;
+				}
+			}
+			if (unp->_idFlag) {
+				for (p = 0x801 + q + 34; p < 0x9ff; p++) {
+					if (*(unsigned int *)(mem + p) == 0x00F920E8) {
+						for (; p < 0x9ff; p++) {
+							if (mem[p] == 0x4c) {
+								unp->_retAdr = mem[p + 1] | mem[p + 2] << 8;
+								if (unp->_retAdr > 0x257)
+									break;
+							}
+						}
+						break;
+					}
+				}
+				for (p = 0; p < 0x40; p++) {
+					if (unp->_info->_run == -1)
+						if (unp->_forced == 0) {
+							if (mem[0x801 + p] == 0x78) {
+								unp->_forced = 0x801 + p;
+								unp->_info->_run = unp->_forced;
+							}
+						}
+					if ((*(unsigned int *)(mem + 0x801 + p) == 0xCA00F69D) &&
+						(mem[0x801 + p + 0x1b] == 0x4c)) {
+						q = 0x801 + p + 0x1c;
+						unp->_depAdr = mem[q] | mem[q + 1] << 8;
+						q = 0x801 + p - 2;
+						p = mem[q] | mem[q + 1] << 8;
+						if ((mem[p + 3] == 0x8d) && (mem[p + 6] == 0xe6)) {
+							unp->_strMem = mem[p + 4] | mem[p + 5] << 8;
+						}
+						break;
+					}
+				}
+				unp->_endAdr = 0xfa; // some hacks DON'T xfer fa/b to 2d/e
+				unp->_idFlag = 1;
+			}
+		}
+		if (unp->_depAdr) {
+			unp->_idFlag = 1;
+			return;
+		}
+	}
+}
+
+} // End of namespace Scott
+} // End of namespace Glk


Commit: 749e7e8dc11ed8b912412e0c8b3f877557295791
    https://github.com/scummvm/scummvm/commit/749e7e8dc11ed8b912412e0c8b3f877557295791
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Implement section8.cpp

Changed paths:
  A engines/glk/scott/unp64/scanners/section8.cpp
    engines/glk/module.mk


diff --git a/engines/glk/module.mk b/engines/glk/module.mk
index b1b7abb5702..89e57117227 100644
--- a/engines/glk/module.mk
+++ b/engines/glk/module.mk
@@ -267,6 +267,7 @@ MODULE_OBJS := \
 	scott/unp64/scanners/master_compressor.o \
 	scott/unp64/scanners/megabyte.o \
 	scott/unp64/scanners/pu_crunch.o \
+	scott/unp64/scanners/section8.o \
 	tads/os_banners.o \
 	tads/os_buffer.o \
 	tads/os_glk.o \
diff --git a/engines/glk/scott/unp64/scanners/section8.cpp b/engines/glk/scott/unp64/scanners/section8.cpp
new file mode 100644
index 00000000000..c0e71f0038a
--- /dev/null
+++ b/engines/glk/scott/unp64/scanners/section8.cpp
@@ -0,0 +1,103 @@
+/* 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 "common/endian.h"
+#include "glk/scott/types.h"
+#include "glk/scott/unp64/unp64.h"
+#include "glk/scott/unp64/exo_util.h"
+
+namespace Glk {
+namespace Scott {
+
+void scnSection8(UnpStr *unp) {
+	byte *mem;
+	int p;
+	if (unp->_idFlag)
+		return;
+	mem =unp->_mem;
+	if (unp->_depAdr == 0) {
+		for (p = 0x810; p <= 0x828; p++) {
+			if ((*(unsigned int *)(mem + p) == (0x00BD00A2 + (((p & 0xff) + 0x11) << 24))) &&
+				(*(unsigned int *)(mem + p + 0x04) == 0x01009D08) &&
+				(*(unsigned int *)(mem + p + 0x10) == 0x34A97801) &&
+				(*(unsigned int *)(mem + p + 0x6a) == 0xB1017820) &&
+				(*(unsigned int *)(mem + p + 0x78) == 0x017F20AE)) {
+				unp->_depAdr = 0x100;
+				break;
+			}
+		}
+		if (unp->_depAdr) {
+			if (unp->_info->_run == -1)
+				unp->_forced = p;
+			unp->_strMem = READ_LE_INT16(&mem[p + 0x47]); // mem[p + 0x47] | mem[p + 0x4b] << 8;
+			unp->_retAdr = READ_LE_INT16(&mem[p + 0x87]); // mem[p + 0x87] | mem[p + 0x88] << 8;
+			if (unp->_retAdr == 0xf7) {
+				unp->_retAdr = 0xa7ae;
+				mem[p + 0x87] = 0xae;
+				mem[p + 0x88] = 0xa7;
+			}
+			unp->_endAdr = 0xae;
+			unp->_idFlag = 1;
+			return;
+		}
+	}
+	/* Crackman variant? */
+	if (unp->_depAdr == 0) {
+		if ((*(unsigned int *)(mem + 0x827) == 0x38BD00A2) &&
+			(*(unsigned int *)(mem + 0x82b) == 0x01009D08) &&
+			(*(unsigned int *)(mem + 0x837) == 0x34A97801) &&
+			(*(unsigned int *)(mem + 0x891) == 0xB1018420) &&
+			(*(unsigned int *)(mem + 0x89f) == 0x018b20AE)) {
+			unp->_depAdr = 0x100;
+			if (unp->_info->_run == -1)
+				unp->_forced = 0x827;
+			unp->_strMem = READ_LE_INT16(&mem[0x86e]); // mem[0x86e] | mem[0x872] << 8;
+			if (*(unsigned short int *)(mem + 0x8b7) == 0xff5b) {
+				mem[0x8b6] = 0x2c;
+				unp->_retAdr = READ_LE_INT16(&mem[0x8ba]); // mem[0x8ba] | mem[0x8bb] << 8;
+			} else {
+				unp->_retAdr = READ_LE_INT16(&mem[0x8b7]); // mem[0x8b7] | mem[0x8b8] << 8;
+			}
+			unp->_endAdr = 0xae;
+			unp->_idFlag = 1;
+			return;
+		}
+	}
+	/* PET||SLAN variant? */
+	if (unp->_depAdr == 0) {
+		if ((*(unsigned int *)(mem + 0x812) == 0x20BD00A2) &&
+			(*(unsigned int *)(mem + 0x816) == 0x033c9D08) &&
+			(*(unsigned int *)(mem + 0x863) == 0xB103B420) &&
+			(*(unsigned int *)(mem + 0x86c) == 0x03BB20AE)) {
+			unp->_depAdr = 0x33c;
+			if (unp->_info->_run == -1)
+				unp->_forced = 0x812;
+			unp->_strMem = READ_LE_INT16(&mem[0x856]); // mem[0x856] | mem[0x85a] << 8;
+			unp->_retAdr = READ_LE_INT16(&mem[0x896]); // mem[0x896] | mem[0x897] << 8;
+			unp->_endAdr = 0xae;
+			unp->_idFlag = 1;
+			return;
+		}
+	}
+}
+
+} // End of namespace Scott
+} // End of namespace Glk


Commit: 3173dfa41b2b038275f50b14a9bc461bf8a88f98
    https://github.com/scummvm/scummvm/commit/3173dfa41b2b038275f50b14a9bc461bf8a88f98
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Implement tbc_multicomp.cpp

Changed paths:
  A engines/glk/scott/unp64/scanners/tbc_multicomp.cpp
    engines/glk/module.mk


diff --git a/engines/glk/module.mk b/engines/glk/module.mk
index 89e57117227..89d1703843f 100644
--- a/engines/glk/module.mk
+++ b/engines/glk/module.mk
@@ -268,6 +268,7 @@ MODULE_OBJS := \
 	scott/unp64/scanners/megabyte.o \
 	scott/unp64/scanners/pu_crunch.o \
 	scott/unp64/scanners/section8.o \
+	scott/unp64/scanners/tbc_multicomp.o \
 	tads/os_banners.o \
 	tads/os_buffer.o \
 	tads/os_glk.o \
diff --git a/engines/glk/scott/unp64/scanners/tbc_multicomp.cpp b/engines/glk/scott/unp64/scanners/tbc_multicomp.cpp
new file mode 100644
index 00000000000..992f951d0bd
--- /dev/null
+++ b/engines/glk/scott/unp64/scanners/tbc_multicomp.cpp
@@ -0,0 +1,166 @@
+/* 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 "common/endian.h"
+#include "glk/scott/types.h"
+#include "glk/scott/unp64/unp64.h"
+#include "glk/scott/unp64/exo_util.h"
+
+namespace Glk {
+namespace Scott {
+
+void scnTBCMultiComp(UnpStr *unp) {
+	byte *mem;
+	int p = 0, q = 0, strtmp;
+	if (unp->_idFlag)
+		return;
+	mem = unp->_mem;
+	if (unp->_depAdr == 0) {
+		if (((*(unsigned int *)(mem + 0x82c) & 0xfffffffd) == 0x9ACA0184) &&
+			 (*(unsigned int *)(mem + 0x830) == 0xA001004C) &&
+			 (*(unsigned int *)(mem + 0x834) == 0x84FD8400) &&
+			 (*(unsigned int *)(mem + 0x8a2) == 0x01494C01)) {
+			/*normal 2080*/
+			if (mem[0x84a] == 0x81) {
+				if (*(unsigned int *)(mem + 0x820) == 0x32BDE9A2) {
+					unp->_forced = 0x820;
+					unp->_retAdr = READ_LE_INT16(&mem[0x8b2]); // mem[0x8b2] | mem[0x8b3] << 8;
+					if (unp->_retAdr == 0x1e1) {
+						if (*(unsigned int *)(mem + 0x916) == 0x4CA87120) {
+							p = *(unsigned short int *)(mem + 0x91a);
+							if (p == 0xa7ae) {
+								unp->_retAdr = p;
+								mem[0x8b2] = 0xae;
+								mem[0x8b3] = 0xa7;
+							} else {
+								mem[0x916] = 0x2c;
+								unp->_retAdr = p;
+							}
+						} else if ((mem[0x916] == 0x4C) || (mem[0x916] == 0x20)) {
+							unp->_retAdr = READ_LE_INT16(&mem[0x917]); // mem[0x917] | mem[0x918] << 8;
+						} else if (mem[0x919] == 0x4c) {
+							unp->_retAdr = READ_LE_INT16(&mem[0x91a]); // mem[0x91a] | mem[0x91b] << 8;
+						}
+					}
+					if ((unp->_retAdr == 0) && (mem[0x8b1] == 0)) {
+						unp->_retAdr = 0xa7ae;
+						mem[0x8b1] = 0x4c;
+						mem[0x8b2] = 0xae;
+						mem[0x8b3] = 0xa7;
+					}
+					p = 0x8eb;
+				}
+			}
+			/*firelord 2076*/
+			else if (mem[0x84a] == 0x7b) {
+				if (*(unsigned int *)(mem + 0x81d) == 0x32BDE9A2) {
+					unp->_forced = 0x81d;
+					unp->_retAdr = READ_LE_INT16(&mem[0x8ac]); // mem[0x8ac] | mem[0x8ad] << 8;
+					p = 0x8eb;
+				}
+			}
+			if (unp->_forced) {
+				unp->_depAdr = 0x100;
+				unp->_strMem = READ_LE_INT16(&mem[p + 1]); // mem[p + 1] | mem[p + 2] << 8;
+				q = p;
+				q += mem[p];
+				unp->_endAdr = 0;
+				for (; q > p; q -= 4) {
+					strtmp = READ_LE_INT16(&mem[q - 1]); //(mem[q - 1] | mem[q] << 8);
+					if (strtmp == 0)
+						strtmp = 0x10000;
+					if (strtmp > unp->_endAdr)
+						unp->_endAdr = strtmp;
+				}
+				unp->_idFlag = 1;
+				return;
+			}
+		}
+	}
+	/* TBC Multicompactor ?  very similar but larger code */
+	if (unp->_depAdr == 0) {
+		if ((*(unsigned int *)(mem + 0x822) == 0x9D083DBD) &&
+			(*(unsigned int *)(mem + 0x826) == 0xD0CA0333) &&
+			(*(unsigned int *)(mem + 0x832) == 0xF7D0CA00) &&
+			(*(unsigned int *)(mem + 0x836) == 0xCA018678) &&
+			(*(unsigned int *)(mem + 0x946) == 0xADC5AFA5)) {
+			if (unp->_info->_run == -1) {
+				for (p = 0x81e; p < 0x821; p++) {
+					if (mem[p] == 0xa2) {
+						unp->_forced = p;
+						break;
+					}
+				}
+			}
+			unp->_depAdr = 0x334;
+			unp->_retAdr = READ_LE_INT16(&mem[0x92a]); // mem[0x92a] | mem[0x92b] << 8;
+			p = 0x94d;
+			unp->_strMem = READ_LE_INT16(&mem[p + 1]); // mem[p + 1] | mem[p + 2] << 8;
+			q = p;
+			q += mem[p];
+			unp->_endAdr = 0;
+			for (; q > p; q -= 4) {
+				strtmp = READ_LE_INT16(&mem[q - 1]); //(mem[q - 1] | mem[q] << 8);
+				if (strtmp == 0)
+					strtmp = 0x10000;
+				if (strtmp > unp->_endAdr)
+					unp->_endAdr = strtmp;
+			}
+			unp->_idFlag = 1;
+			return;
+		}
+	}
+	/*"AUTOMATIC BREAK SYSTEM" found in Manowar Cracks*/
+	if (unp->_depAdr == 0) {
+		if ((*(unsigned int *)(mem + 0x835) == 0x9D0845BD) &&
+			(*(unsigned int *)(mem + 0x839) == 0xD0CA00ff) &&
+			(*(unsigned int *)(mem + 0x83e) == 0xCA018678) &&
+			(*(unsigned int *)(mem + 0x8e1) == 0xADC5AFA5)) {
+			if (unp->_info->_run == -1) {
+				for (p = 0x830; p < 0x834; p++) {
+					if (mem[p] == 0xa2) {
+						unp->_forced = p;
+						break;
+					}
+				}
+			}
+			unp->_depAdr = 0x100;
+			unp->_retAdr = READ_LE_INT16(&mem[0x8c5]); // mem[0x8c5] | mem[0x8c6] << 8;
+			p = 0x8fe;
+			unp->_strMem = READ_LE_INT16(&mem[p + 1]); // mem[p + 1] | mem[p + 2] << 8;
+			q = p;
+			q += mem[p];
+			unp->_endAdr = 0;
+			for (; q > p; q -= 4) {
+				strtmp = READ_LE_INT16(&mem[q - 1]); //(mem[q - 1] | mem[q] << 8);
+				if (strtmp == 0)
+					strtmp = 0x10000;
+				if (strtmp > unp->_endAdr)
+					unp->_endAdr = strtmp;
+			}
+			unp->_idFlag = 1;
+			return;
+		}
+	}
+}
+
+} // End of namespace Scott
+} // End of namespace Glk


Commit: c20baf88730a34e12b111b5f717e0caf7e2d0672
    https://github.com/scummvm/scummvm/commit/c20baf88730a34e12b111b5f717e0caf7e2d0672
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Implement tcs_crunch.cpp

Changed paths:
  A engines/glk/scott/unp64/scanners/tcs_crunch.cpp
    engines/glk/module.mk


diff --git a/engines/glk/module.mk b/engines/glk/module.mk
index 89d1703843f..e500abf1ac3 100644
--- a/engines/glk/module.mk
+++ b/engines/glk/module.mk
@@ -269,6 +269,7 @@ MODULE_OBJS := \
 	scott/unp64/scanners/pu_crunch.o \
 	scott/unp64/scanners/section8.o \
 	scott/unp64/scanners/tbc_multicomp.o \
+	scott/unp64/scanners/tcs_crunch.o \
 	tads/os_banners.o \
 	tads/os_buffer.o \
 	tads/os_glk.o \
diff --git a/engines/glk/scott/unp64/scanners/tcs_crunch.cpp b/engines/glk/scott/unp64/scanners/tcs_crunch.cpp
new file mode 100644
index 00000000000..50b46003934
--- /dev/null
+++ b/engines/glk/scott/unp64/scanners/tcs_crunch.cpp
@@ -0,0 +1,78 @@
+/* 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 "common/endian.h"
+#include "glk/scott/types.h"
+#include "glk/scott/unp64/unp64.h"
+
+namespace Glk {
+namespace Scott {
+
+void scnTCScrunch(UnpStr *unp) {
+	byte *mem;
+	int q, p;
+	if (unp->_idFlag)
+		return;
+	mem = unp->_mem;
+	if (unp->_depAdr == 0) {
+		if ((*(unsigned int *)(mem + 0x819) == 0x018536A9) && mem[0x81d] == 0x4c) {
+			p = READ_LE_INT16(&mem[0x81e]); // mem[0x81e] | mem[0x81f] << 8;
+			if (mem[p] == 0xa2 && mem[p + 2] == 0xbd &&
+				(*(unsigned int *)(mem + p + 0x05) == 0xE801109D) &&
+				((*(unsigned int *)(mem + p + 0x38) == 0x01524CFB) ||
+				((*(unsigned int *)(mem + p + 0x38) == 0x8DE1A9FB) &&
+				(*(unsigned int *)(mem + p + 0x3c) == 0x524C0328)))) {
+				unp->_depAdr = 0x334;
+				unp->_forced = 0x819;
+				unp->_endAdr = 0x2d;
+			}
+		}
+		else if ((*(unsigned int *)(mem + 0x819) == 0x018534A9) && mem[0x81d] == 0x4c) {
+			p = READ_LE_INT16(&mem[0x81e]); // mem[0x81e] | mem[0x81f] << 8;
+			if (mem[p] == 0xa2 && mem[p + 2] == 0xbd &&
+				(*(unsigned int *)(mem + p + 0x05) == 0xE801109D) &&
+				(*(unsigned int *)(mem + p + 0x38) == 0x01304CFB)) {
+				unp->_depAdr = 0x334;
+				unp->_forced = 0x818;
+				if (mem[unp->_forced] != 0x78)
+					unp->_forced++;
+				unp->_endAdr = 0x2d;
+				unp->_retAdr = READ_LE_INT16(&mem[p + 0xd9]); // mem[p + 0xd9] | mem[p + 0xda] << 8;
+				p += 0xc8;
+				q = p + 6;
+				for (; p < q; p += 3) {
+					if ((mem[p] == 0x20) &&
+						(*(unsigned short int *)(mem + p + 1) >= 0xa000) &&
+						(*(unsigned short int *)(mem + p + 1) <= 0xbfff)) {
+						mem[p] = 0x2c;
+					}
+				}
+			}
+		}
+		if (unp->_depAdr) {
+			unp->_idFlag = 1;
+			return;
+		}
+	}
+}
+
+} // End of namespace Scott
+} // End of namespace Glk


Commit: 72076286b6bb22b1d9ebde3589e927c24d62c268
    https://github.com/scummvm/scummvm/commit/72076286b6bb22b1d9ebde3589e927c24d62c268
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Implement xtc.cpp

Changed paths:
  A engines/glk/scott/unp64/scanners/xtc.cpp
    engines/glk/module.mk


diff --git a/engines/glk/module.mk b/engines/glk/module.mk
index e500abf1ac3..9124f112a71 100644
--- a/engines/glk/module.mk
+++ b/engines/glk/module.mk
@@ -270,6 +270,7 @@ MODULE_OBJS := \
 	scott/unp64/scanners/section8.o \
 	scott/unp64/scanners/tbc_multicomp.o \
 	scott/unp64/scanners/tcs_crunch.o \
+	scott/unp64/scanners/xtc.o \
 	tads/os_banners.o \
 	tads/os_buffer.o \
 	tads/os_glk.o \
diff --git a/engines/glk/scott/unp64/scanners/xtc.cpp b/engines/glk/scott/unp64/scanners/xtc.cpp
new file mode 100644
index 00000000000..f312d53ecb3
--- /dev/null
+++ b/engines/glk/scott/unp64/scanners/xtc.cpp
@@ -0,0 +1,161 @@
+/* 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 "common/endian.h"
+#include "glk/scott/types.h"
+#include "glk/scott/unp64/unp64.h"
+
+namespace Glk {
+namespace Scott {
+
+void scnXTC(UnpStr *unp) {
+	byte *mem;
+	int q = 0, p;
+	if (unp->_idFlag)
+		return;
+	mem = unp->_mem;
+	if (unp->_depAdr == 0) {
+		if ((*(unsigned short int *)(mem + 0x80d) == 0xE678) &&
+			(*(unsigned int *)(mem + 0x811) == 0x1BCE0818) &&
+			(*(unsigned int *)(mem + 0x819) == 0xC8000099) &&
+			(*(unsigned int *)(mem + 0x82c) == 0x4CF7D0CA) &&
+			mem[0x85c] == 0x99) {
+			unp->_retAdr = READ_LE_INT16(&mem[0x872]); // mem[0x872] | mem[0x873] << 8;
+			unp->_depAdr = 0x100;
+			unp->_forced = 0x80d; /* the ldy #$00 can be missing, skipped */
+			unp->_fEndAf = 0x121;
+			unp->_endAdC = 0xffff | EA_USE_Y;
+			unp->_strMem = READ_LE_INT16(&mem[0x85d]); // mem[0x85d] | mem[0x85e] << 8;
+			unp->_idFlag = 1;
+			return;
+		}
+	}
+	/* XTC packer 1.0 & 2.2/2.4 */
+	if (unp->_depAdr == 0) {
+		for (p = 0x801; p < 0x80c; p += 0x0a) {
+			if ((*(unsigned short int *)(mem + p + 0x02) == 0xE678) &&
+				(*(unsigned int *)(mem + p + 0x07) == (0xce08 | ((p + 0x10) << 16))) &&
+				(*(unsigned int *)(mem + p + 0x0e) == 0xC8000099) &&
+				(*(unsigned int *)(mem + p + 0x23) == 0x4CF7D0CA)) {
+				/* has variable codebytes so addresses varies */
+				for (q = p + 0x37; q < p + 0x60; q += 4) {
+					if (mem[q] == 0xc9)
+						continue;
+					if (mem[q] == 0x99) {
+						unp->_depAdr = 0x100;
+						break;
+					}
+					break; /* unexpected byte, get out */
+				}
+				break;
+			}
+		}
+		if (unp->_depAdr) {
+			unp->_retAdr = READ_LE_INT16(&mem[q + 0x16]); // mem[q + 0x16] | mem[q + 0x17] << 8;
+			if (*(unsigned short int *)(mem + p) != 0x00a0)
+				unp->_forced = p + 2; /* the ldy #$00 can be missing, skipped */
+			else
+				unp->_forced = p;
+
+			unp->_fEndAf = READ_LE_INT16(&mem[q + 0x7]); // mem[q + 0x7] | mem[q + 0x8] << 8;
+			unp->_fEndAf--;
+			unp->_endAdC = 0xffff | EA_USE_Y;
+			unp->_strMem = READ_LE_INT16(&mem[q + 1]); // mem[q + 1] | mem[q + 2] << 8;
+			if (*(unsigned int *)(mem + q + 0x1f) == 0xDDD00285) {
+			} else if (*(unsigned int *)(mem + q + 0x1f) == 0xF620DFD0) {
+				/* rockstar's 2.2+ & shade/light's 2.4 are all the same */
+			} else { /* actually found to be Visiomizer 6.2/Zagon */
+				unp->_depAdr = READ_LE_INT16(&mem[p + 0x27]); // mem[p + 0x27] | mem[p + 0x28] << 8;
+			}
+			unp->_idFlag = 1;
+			return;
+		}
+	}
+	/* XTC 2.3 / 6codezipper */
+	if (unp->_depAdr == 0) {
+		if ((*(unsigned int *)(mem + 0x803) == 0xB9018478) &&
+			(*(unsigned int *)(mem + 0x80b) == 0xF7D0C8FF) &&
+			(*(unsigned int *)(mem + 0x81b) == 0x00FC9D08) &&
+			(*(unsigned int *)(mem + 0x85b) == 0xD0D0FFE4)) {
+			unp->_depAdr = READ_LE_INT16(&mem[0x823]); // mem[0x823] | mem[0x824] << 8;
+			unp->_forced = 0x803;
+			unp->_retAdr = READ_LE_INT16(&mem[0x865]); // mem[0x865] | mem[0x866] << 8;
+			unp->_strMem = READ_LE_INT16(&mem[0x850]); // mem[0x850] | mem[0x851] << 8;
+			unp->_endAdC = 0xffff | EA_USE_Y;
+			unp->_fEndAf = 0x128;
+			unp->_idFlag = 1;
+			return;
+		}
+	}
+	/* XTC 2.3 / G*P, probably by Rockstar */
+	if (unp->_depAdr == 0) {
+		if (((*(unsigned int *)(mem + 0x803) == 0xB901e678) ||
+			 (*(unsigned int *)(mem + 0x803) == 0xB9018478)) &&
+			 (*(unsigned int *)(mem + 0x80b) == 0xF7D0C8FF) &&
+			 (*(unsigned int *)(mem + 0x81b) == 0x00F59D08) &&
+			 (*(unsigned int *)(mem + 0x85b) == 0xD0D0F8E4)) {
+			unp->_depAdr = READ_LE_INT16(&mem[0x823]); // mem[0x823] | mem[0x824] << 8;
+			unp->_forced = 0x803;
+			unp->_retAdr = READ_LE_INT16(&mem[0x865]); // mem[0x865] | mem[0x866] << 8;
+			unp->_strMem = READ_LE_INT16(&mem[0x850]); // mem[0x850] | mem[0x851] << 8;
+			unp->_endAdC = 0xffff | EA_USE_Y;
+			unp->_fEndAf = 0x121;
+			unp->_idFlag = 1;
+			return;
+		}
+	}
+	/* XTC packer 2.x? found in G*P/NEI/Armageddon warez
+	just some different byte on copy loop, else is equal to 2.3
+	*/
+	if (unp->_depAdr == 0) {
+		for (p = 0x801; p < 0x80c; p += 0x0a) {
+			if (((*(unsigned int *)(mem + p + 0x00) & 0xffff0000) == 0xE6780000) &&
+				((*(unsigned int *)(mem + p + 0x05) & 0xffff00ff) == 0xB90800CE) &&
+				(*(unsigned int *)(mem + p + 0x0b) == 0xC8000099) &&
+				(*(unsigned int *)(mem + p + 0x1e) == 0x4CF7D0CA)) {
+				/* has variable codebytes so addresses varies */
+				for (q = p + 0x36; q < p + 0x60; q += 4) {
+					if (mem[q] == 0xc9)
+						continue;
+					if (mem[q] == 0x99) {
+						unp->_depAdr = 0x100;
+						break;
+					}
+					break; /* unexpected byte, get out */
+				}
+				break;
+			}
+		}
+		if (unp->_depAdr) {
+			unp->_retAdr = READ_LE_INT16(&mem[q + 0x16]); // mem[q + 0x16] | mem[q + 0x17] << 8;
+			unp->_forced = p + 2;
+			unp->_fEndAf = READ_LE_INT16(&mem[q + 0x7]); // mem[q + 0x7] | mem[q + 0x8] << 8;
+			unp->_fEndAf--;
+			unp->_endAdC = 0xffff | EA_USE_Y;
+			unp->_strMem = READ_LE_INT16(&mem[q + 1]); // mem[q + 1] | mem[q + 2] << 8;
+			unp->_idFlag = 1;
+			return;
+		}
+	}
+}
+
+} // End of namespace Scott
+} // End of namespace Glk


Commit: 92ea152c35af579cbc941700f1b2efb6acf7efd8
    https://github.com/scummvm/scummvm/commit/92ea152c35af579cbc941700f1b2efb6acf7efd8
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Implement scanners

Changed paths:
    engines/glk/scott/unp64/scanners/scanners.cpp
    engines/glk/scott/unp64/unp64.h


diff --git a/engines/glk/scott/unp64/scanners/scanners.cpp b/engines/glk/scott/unp64/scanners/scanners.cpp
index 9ecbc26491a..1a880927a5e 100644
--- a/engines/glk/scott/unp64/scanners/scanners.cpp
+++ b/engines/glk/scott/unp64/scanners/scanners.cpp
@@ -24,8 +24,48 @@
 namespace Glk {
 namespace Scott {
 
-void scanners(UnpStr* unp) {
+void scnECA(UnpStr *unp);
+void scnExpert(UnpStr *unp);
+void scnCruel(UnpStr *unp);
+void scnPuCrunch(UnpStr *unp);
+void scnByteBoiler(UnpStr *unp);
+void scnMasterCompressor(UnpStr *unp);
+void scnTCScrunch(UnpStr *unp);
+void scnTBCMultiComp(UnpStr *unp);
+void scnXTC(UnpStr *unp);
+void scnCCS(UnpStr *unp);
+void scnMegabyte(UnpStr *unp);
+void scnSection8(UnpStr *unp);
+void scnCaution(UnpStr *unp);
+void scnActionPacker(UnpStr *unp);
+void scnExomizer(UnpStr *unp);
+
+Scnptr g_scanFunc[] = {
+	scnECA,
+	scnExpert,
+	scnCruel,
+	scnPuCrunch,
+	scnByteBoiler,
+	scnMasterCompressor,
+	scnTCScrunch,
+	scnTBCMultiComp,
+	scnXTC,
+	scnCCS,
+	scnMegabyte,
+	scnSection8,
+	scnCaution,
+	scnActionPacker,
+	scnExomizer
+};
 
+void scanners(UnpStr* unp) {
+	int x, y;
+	y = sizeof(g_scanFunc) / sizeof(*g_scanFunc);
+	for (x = 0; x < y; x++) {
+		(g_scanFunc[x])(unp);
+		if (unp->_idFlag)
+			break;
+	}
 }
 
 } // End of namespace Scott
diff --git a/engines/glk/scott/unp64/unp64.h b/engines/glk/scott/unp64/unp64.h
index 6a09fcbef11..865816e49e9 100644
--- a/engines/glk/scott/unp64/unp64.h
+++ b/engines/glk/scott/unp64/unp64.h
@@ -61,6 +61,8 @@ struct UnpStr {
 	CpuCtx *_r;      /* pointer to the registers struct */
 };
 
+typedef void (*Scnptr)(UnpStr *);
+
 #define EA_USE_A 0x01000000
 #define EA_USE_X 0x00100000
 #define EA_USE_Y 0x00010000


Commit: 767586218d929a27eb634379f1dc718d11030f24
    https://github.com/scummvm/scummvm/commit/767586218d929a27eb634379f1dc718d11030f24
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Implement copyData

Changed paths:
    engines/glk/scott/c64_checksums.cpp


diff --git a/engines/glk/scott/c64_checksums.cpp b/engines/glk/scott/c64_checksums.cpp
index ba4b8424a96..bcbe0dedd39 100644
--- a/engines/glk/scott/c64_checksums.cpp
+++ b/engines/glk/scott/c64_checksums.cpp
@@ -244,7 +244,16 @@ int detectC64(uint8_t **sf, size_t *extent) {
 }
 
 size_t copyData(size_t dest, size_t source, uint8_t** data, size_t dataSize, size_t bytesToMove) {
-	return 0;
+	if (source > dataSize || *data == nullptr)
+		return 0;
+
+	size_t newSize = MAX(dest + bytesToMove, dataSize);
+	uint8_t *megaBuf = new uint8_t[newSize];
+	memcpy(megaBuf, *data, dataSize);
+	memcpy(megaBuf + dest, *data + source, bytesToMove);
+	delete[] *data;
+	*data = megaBuf;
+	return newSize;
 }
 
 int decrunchC64(uint8_t **sf, size_t *extent, C64Rec record) {


Commit: 2356c0d6342de7e8636e5b9cb251e216f5ccedee
    https://github.com/scummvm/scummvm/commit/2356c0d6342de7e8636e5b9cb251e216f5ccedee
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Remove unused gamedata

Changed paths:
    engines/glk/scott/games.h


diff --git a/engines/glk/scott/games.h b/engines/glk/scott/games.h
index f450e2a6e16..b867414652d 100644
--- a/engines/glk/scott/games.h
+++ b/engines/glk/scott/games.h
@@ -20,2344 +20,992 @@
  */
 
 const GameInfo _games[NUMGAMES] = {
-	GameInfo("Pirate Adventure",
-		 PIRATE,
-		 OLD_STYLE,                 // type
-		 ENGLISH,                   // subtype
-		 THREE_LETTER_UNCOMPRESSED, // dictionary type
-
-		 66,                        // Number of items
-		 177,                       // Number of actions
-		 79,                        // Number of words
-		 26,                        // Number of rooms
-		 6,                         // Max carried items
-		 3,                         // Word length
-		 99,                        // Number of messages
-		 80,                        // number_of_verbs
-		 79,                        // number_of_nouns;
-		 0x2451,                    // header
-		 EARLY,                     // header style
-		 0,                         // no room images
-		 0,                         // no item flags
-		 0,                         // no item images
-		 0x3a50,                    // actions
-
-		 UNCOMPRESSED,
-		 0x469a,     // dictionary
-		 FOLLOWS,    // start_of_room_descriptions;
-		 FOLLOWS,    // start_of_room_connections;
-		 FOLLOWS,    // start_of_messages;
-		 FOLLOWS,    // start_of_item_descriptions;
-		 FOLLOWS,    // start_of_item_locations;
-
-		 0x2539,     // start_of_system_messages
-		 0x28de,     // start of directions
-		 0,          // start_of_characters;
-		 0,          // start_of_image_data;
-		 0,          // image_address_offset
-		 0,          // number_of_pictures;
-		 NO_PALETTE, // palette;
-		 0,
-		 0),
-	GameInfo("Voodoo Castle",
-		VOODOO,
-		OLD_STYLE,                 // type
-		ENGLISH,                   // subtype
-		THREE_LETTER_UNCOMPRESSED, // dictionary type
-
-		65,  // Number of items
-		189, // Number of actions
-		89,  // Number of words
-		25,  // Number of rooms
-		9,   // Max carried items
-		3,   // Word length
-		99,  // Number of messages
-
-		90, // number_of_verbs
-		89, // number_of_nouns;
-
-		0x2451, // header
-		EARLY,  // header style
-
-		0, // no room images
-		0, // no item flags
-		0, // no item images
-
-		0x3a50, // actions
-		UNCOMPRESSED,
-		0x4752,  // dictionary
-		FOLLOWS, // start_of_room_descriptions;
-		FOLLOWS, // start_of_room_connections;
-		FOLLOWS, // start_of_messages;
-		FOLLOWS, // start_of_item_descriptions;
-		FOLLOWS, // start_of_item_locations;
-
-		0x2539, // start_of_system_messages
-		0x28de, // start of directions
-
-		0,          // start_of_characters;
-		0,          // start_of_image_data;
-		0,          // image_address_offset
-		0,          // number_of_pictures;
-		NO_PALETTE, // palette;
-		0,          // picture_format_version;
-		0),
-	GameInfo("Strange Odyssey",
-		STRANGE,
-		OLD_STYLE,                // type
-		ENGLISH,                  // subtype
-		FOUR_LETTER_UNCOMPRESSED, // dictionary type
-
-		55,  // Number of items
-		223, // Number of actions
-		79,  // Number of words
-		35,  // Number of rooms
-		6,   // Max carried items
-		4,   // Word length
-		94,  // Number of messages
-
-		80, // number_of_verbs
-		79, // number_of_nouns;
-
-		0x2451, // header
-		EARLY,  // header style
-
-		0, // no room images
-		0, // no item flags
-		0, // no item images
-
-		0x3a50, // actions
-		UNCOMPRESSED,
-		0x499a,  // dictionary
-		FOLLOWS, // start_of_room_descriptions;
-		FOLLOWS, // start_of_room_connections;
-		FOLLOWS, // start_of_messages;
-		FOLLOWS, // start_of_item_descriptions;
-		FOLLOWS, // start_of_item_locations;
-
-		0x2539, // start_of_system_messages
-		0x28de, // start of directions
-
-		0,          // start_of_characters;
-		0,          // start_of_image_data;
-		0,          // image_address_offset
-		0,          // number_of_pictures;
-		NO_PALETTE, // palette;
-		0,          // picture_format_version;
-		0),
-	GameInfo("Buckaroo Banzai",
-		BANZAI,
-		OLD_STYLE,                // type
-		ENGLISH,                  // subtype
-		FOUR_LETTER_UNCOMPRESSED, // dictionary type
-
-		60,  // Number of items
-		266, // Number of actions
-		110, // Number of words
-		35,  // Number of rooms
-		5,   // Max carried items
-		4,   // Word length
-		95,  // Number of messages
-
-		111, // number_of_verbs
-		110, // number_of_nouns;
-
-		0x2451, // header
-		EARLY,  // header style
-
-		0, // no room images
-		0, // no item flags
-		0, // no item images
-
-		0x3a50, // actions
-		UNCOMPRESSED,
-		0x4c54,  // dictionary
-		FOLLOWS, // start_of_room_descriptions;
-		FOLLOWS, // start_of_room_connections;
-		FOLLOWS, // start_of_messages;
-		FOLLOWS, // start_of_item_descriptions;
-		FOLLOWS, // start_of_item_locations;
-
-		0x2539, // start_of_system_messages
-		0x28de, // start of directions
-
-		0,          // start_of_characters;
-		0,          // start_of_image_data;
-		0,          // image_address_offset
-		0,          // number_of_pictures;
-		NO_PALETTE, // palette;
-		0,          // picture_format_version;
-		0),
 	GameInfo("The Golden Baton",
-		BATON,
-		OLD_STYLE,                // type
-		MYSTERIOUS,               // subtype
-		FOUR_LETTER_UNCOMPRESSED, // dictionary type
-
-		48,  // Number of items
-		171, // Number of actions
-		76,  // Number of words
-		31,  // Number of rooms
-		5,   // Max carried items
-		4,   // Word length
-		82,  // Number of messages
-
-		77, // number_of_verbs
-		76, // number_of_nouns;
-
-		0x2349, // header
-		EARLY,  // header style
-
-		0, // no room images
-		0, // no item flags
-		0, // no item images
-
-		0x3b56, // actions
-		UNCOMPRESSED,
-		0x473a,  // dictionary
-		FOLLOWS, // start_of_room_descriptions;
-		FOLLOWS, // start_of_room_connections;
-		FOLLOWS, // start_of_messages;
-		FOLLOWS, // start_of_item_descriptions;
-		FOLLOWS, // start_of_item_locations;
-
-		0x2450, // start_of_system_messages
-		0x277e, // start of directions
-
-		0,       // start_of_characters;
-		FOLLOWS, // start_of_image_data;
-		0,       // image_address_offset
-		30,      // number_of_pictures;
-		ZXOPT,   // palette
-		99,      // picture_format_version;
-		0),
+			 BATON,
+			 OLD_STYLE,                // type
+			 MYSTERIOUS,               // subtype
+			 FOUR_LETTER_UNCOMPRESSED, // dictionary type
+
+			 48,  // Number of items
+			 171, // Number of actions
+			 76,  // Number of words
+			 31,  // Number of rooms
+			 5,   // Max carried items
+			 4,   // Word length
+			 82,  // Number of messages
+
+			 77, // number_of_verbs
+			 76, // number_of_nouns;
+
+			 0x2349, // header
+			 EARLY,  // header style
+
+			 0, // no room images
+			 0, // no item flags
+			 0, // no item images
+
+			 0x3b56, // actions
+			 UNCOMPRESSED,
+			 0x473a,  // dictionary
+			 FOLLOWS, // start_of_room_descriptions;
+			 FOLLOWS, // start_of_room_connections;
+			 FOLLOWS, // start_of_messages;
+			 FOLLOWS, // start_of_item_descriptions;
+			 FOLLOWS, // start_of_item_locations;
+
+			 0x2450, // start_of_system_messages
+			 0x277e, // start of directions
+
+			 0,       // start_of_characters;
+			 FOLLOWS, // start_of_image_data;
+			 0,       // image_address_offset
+			 30,      // number_of_pictures;
+			 ZXOPT,   // palette
+			 99,      // picture_format_version;
+			 0),
 	GameInfo("The Golden Baton C64",
-		BATON_C64,
-		NO_TYPE,                                          // type
-		static_cast<Subtype>(MYSTERIOUS | ENGLISH | C64), // subtype
-		FOUR_LETTER_UNCOMPRESSED,                         // dictionary type
-
-		48,  // Number of items
-		166, // Number of actions
-		78,  // Number of words
-		31,  // Number of rooms
-		6,   // Max carried items
-		4,   // Word length
-		99,  // Number of messages
-
-		80, // number_of_verbs
-		79, // number_of_nouns;
-
-		0x1dd9,                // header
-		MYSTERIOUS_C64_HEADER, // header style
-
-		0, // no room images
-		0, // no item flags
-		0, // no item images
-
-		0x1df1, // actions
-		UNCOMPRESSED,
-		0x2861,  // dictionary
-		FOLLOWS, // start_of_room_descriptions;
-		FOLLOWS, // start_of_room_connections;
-		FOLLOWS, // start_of_messages;
-		FOLLOWS, // start_of_item_descriptions;
-		FOLLOWS, // start_of_item_locations;
-
-		0x408, // start_of_system_messages
-		0x408, // start of directions
-
-		0,      // start_of_characters;
-		0x38f1, // start_of_image_data;
-		0,      // image_address_offset
-		30,     // number_of_pictures;
-		C64A,   // palette
-		99,     // picture_format_version;
-		0),
+			 BATON_C64,
+			 NO_TYPE,                                          // type
+			 static_cast<Subtype>(MYSTERIOUS | ENGLISH | C64), // subtype
+			 FOUR_LETTER_UNCOMPRESSED,                         // dictionary type
+
+			 48,  // Number of items
+			 166, // Number of actions
+			 78,  // Number of words
+			 31,  // Number of rooms
+			 6,   // Max carried items
+			 4,   // Word length
+			 99,  // Number of messages
+
+			 80, // number_of_verbs
+			 79, // number_of_nouns;
+
+			 0x1dd9,                // header
+			 MYSTERIOUS_C64_HEADER, // header style
+
+			 0, // no room images
+			 0, // no item flags
+			 0, // no item images
+
+			 0x1df1, // actions
+			 UNCOMPRESSED,
+			 0x2861,  // dictionary
+			 FOLLOWS, // start_of_room_descriptions;
+			 FOLLOWS, // start_of_room_connections;
+			 FOLLOWS, // start_of_messages;
+			 FOLLOWS, // start_of_item_descriptions;
+			 FOLLOWS, // start_of_item_locations;
+
+			 0x408, // start_of_system_messages
+			 0x408, // start of directions
+
+			 0,      // start_of_characters;
+			 0x38f1, // start_of_image_data;
+			 0,      // image_address_offset
+			 30,     // number_of_pictures;
+			 C64A,   // palette
+			 99,     // picture_format_version;
+			 0),
 	GameInfo("The Time Machine",
-		TIME_MACHINE,
-		OLD_STYLE,                // type
-		MYSTERIOUS,               // subtype
-		FOUR_LETTER_UNCOMPRESSED, // dictionary type
-
-		62,  // Number of items
-		164, // Number of actions
-		87,  // Number of words
-		44,  // Number of rooms
-		6,   // Max carried items
-		4,   // Word length
-		82,  // Number of messages
-
-		88, // number_of_verbs
-		87, // number_of_nouns;
-
-		0x2351, // header
-		EARLY,  // header style
-
-		0, // no room images
-		0, // no item flags
-		0, // no item images
-
-		0x3b81, // actions
-		UNCOMPRESSED,
-		0x475f,  // dictionary
-		FOLLOWS, // start_of_room_descriptions;
-		FOLLOWS, // start_of_room_connections;
-		FOLLOWS, // start_of_messages;
-		FOLLOWS, // start_of_item_descriptions;
-		FOLLOWS, // start_of_item_locations;
-
-		0x24c0, // start_of_system_messages
-		0x2780, // start of directions
-
-		0, // start_of_characters;
-		FOLLOWS,
-		0,     // image_address_offset
-		43,    // number_of_pictures;
-		ZXOPT, // palette
-		99,    // picture_format_version;
-		0),
+			 TIME_MACHINE,
+			 OLD_STYLE,                // type
+			 MYSTERIOUS,               // subtype
+			 FOUR_LETTER_UNCOMPRESSED, // dictionary type
+
+			 62,  // Number of items
+			 164, // Number of actions
+			 87,  // Number of words
+			 44,  // Number of rooms
+			 6,   // Max carried items
+			 4,   // Word length
+			 82,  // Number of messages
+
+			 88, // number_of_verbs
+			 87, // number_of_nouns;
+
+			 0x2351, // header
+			 EARLY,  // header style
+
+			 0, // no room images
+			 0, // no item flags
+			 0, // no item images
+
+			 0x3b81, // actions
+			 UNCOMPRESSED,
+			 0x475f,  // dictionary
+			 FOLLOWS, // start_of_room_descriptions;
+			 FOLLOWS, // start_of_room_connections;
+			 FOLLOWS, // start_of_messages;
+			 FOLLOWS, // start_of_item_descriptions;
+			 FOLLOWS, // start_of_item_locations;
+
+			 0x24c0, // start_of_system_messages
+			 0x2780, // start of directions
+
+			 0, // start_of_characters;
+			 FOLLOWS,
+			 0,     // image_address_offset
+			 43,    // number_of_pictures;
+			 ZXOPT, // palette
+			 99,    // picture_format_version;
+			 0),
 	GameInfo("The Time Machine C64",
-		TIME_MACHINE_C64,
-		NO_TYPE,                                          // type
-		static_cast<Subtype>(MYSTERIOUS | ENGLISH | C64), // subtype
-		FOUR_LETTER_UNCOMPRESSED,                         // dictionary type
-
-		62,  // Number of items
-		161, // Number of actions
-		85,  // Number of words
-		44,  // Number of rooms
-		6,   // Max carried items
-		4,   // Word length
-		73,  // Number of messages
-
-		87, // number_of_verbs
-		85, // number_of_nouns;
-
-		0x1dd9,                // header
-		MYSTERIOUS_C64_HEADER, // header style
-
-		0, // no room images
-		0, // no item flags
-		0, // no item images
-
-		0x1df1, // actions
-		UNCOMPRESSED,
-		0x2811,  // dictionary
-		0x2b6d,  // start_of_room_descriptions;
-		FOLLOWS, // start_of_room_connections;
-		0x2f0f,  // start_of_messages;
-		FOLLOWS, // start_of_item_descriptions;
-		0x37ce,  // start_of_item_locations;
-
-		0x408, // start_of_system_messages
-		0x408, // start of directions
-
-		0,      // start_of_characters;
-		0x3872, // start_of_image_data;
-		0,      // image_address_offset
-		43,     // number_of_pictures;
-		C64A,   // palette
-		99,     // picture_format_version;
-		0),
+			 TIME_MACHINE_C64,
+			 NO_TYPE,                                          // type
+			 static_cast<Subtype>(MYSTERIOUS | ENGLISH | C64), // subtype
+			 FOUR_LETTER_UNCOMPRESSED,                         // dictionary type
+
+			 62,  // Number of items
+			 161, // Number of actions
+			 85,  // Number of words
+			 44,  // Number of rooms
+			 6,   // Max carried items
+			 4,   // Word length
+			 73,  // Number of messages
+
+			 87, // number_of_verbs
+			 85, // number_of_nouns;
+
+			 0x1dd9,                // header
+			 MYSTERIOUS_C64_HEADER, // header style
+
+			 0, // no room images
+			 0, // no item flags
+			 0, // no item images
+
+			 0x1df1, // actions
+			 UNCOMPRESSED,
+			 0x2811,  // dictionary
+			 0x2b6d,  // start_of_room_descriptions;
+			 FOLLOWS, // start_of_room_connections;
+			 0x2f0f,  // start_of_messages;
+			 FOLLOWS, // start_of_item_descriptions;
+			 0x37ce,  // start_of_item_locations;
+
+			 0x408, // start_of_system_messages
+			 0x408, // start of directions
+
+			 0,      // start_of_characters;
+			 0x3872, // start_of_image_data;
+			 0,      // image_address_offset
+			 43,     // number_of_pictures;
+			 C64A,   // palette
+			 99,     // picture_format_version;
+			 0),
 	GameInfo("Arrow of Death part 1",
-		ARROW1,
-		OLD_STYLE,                // type
-		MYSTERIOUS,               // subtype
-		FOUR_LETTER_UNCOMPRESSED, // dictionary type
-
-		64,  // Number of items
-		150, // Number of actions
-		90,  // Number of words
-		52,  // Number of rooms
-		5,   // Max carried items
-		4,   // Word length
-		82,  // Number of messages
-
-		91, // number_of_verbs
-		83, // number_of_nouns;
-
-		0x2351, // header
-		EARLY,  // header style
-
-		0, // no room images
-		0, // no item flags
-		0, // no item images
-
-		0x3b81, // actions
-		UNCOMPRESSED,
-		0x46b3,  // dictionary
-		0x4a41,  // start_of_room_descriptions;
-		FOLLOWS, // start_of_room_connections;
-		FOLLOWS, // start_of_messages;
-		FOLLOWS, // start_of_item_descriptions;
-		FOLLOWS, // start_of_item_locations;
-
-		0x24c0, // start_of_system_messages
-		0x2780, // start of directions
-
-		0,       // start_of_characters;
-		FOLLOWS, // start_of_image_data;
-		0,       // image_address_offset
-		51,      // number_of_pictures;
-		ZXOPT,   // palette
-		99,      // picture_format_version;
-		0),
+			 ARROW1,
+			 OLD_STYLE,                // type
+			 MYSTERIOUS,               // subtype
+			 FOUR_LETTER_UNCOMPRESSED, // dictionary type
+
+			 64,  // Number of items
+			 150, // Number of actions
+			 90,  // Number of words
+			 52,  // Number of rooms
+			 5,   // Max carried items
+			 4,   // Word length
+			 82,  // Number of messages
+
+			 91, // number_of_verbs
+			 83, // number_of_nouns;
+
+			 0x2351, // header
+			 EARLY,  // header style
+
+			 0, // no room images
+			 0, // no item flags
+			 0, // no item images
+
+			 0x3b81, // actions
+			 UNCOMPRESSED,
+			 0x46b3,  // dictionary
+			 0x4a41,  // start_of_room_descriptions;
+			 FOLLOWS, // start_of_room_connections;
+			 FOLLOWS, // start_of_messages;
+			 FOLLOWS, // start_of_item_descriptions;
+			 FOLLOWS, // start_of_item_locations;
+
+			 0x24c0, // start_of_system_messages
+			 0x2780, // start of directions
+
+			 0,       // start_of_characters;
+			 FOLLOWS, // start_of_image_data;
+			 0,       // image_address_offset
+			 51,      // number_of_pictures;
+			 ZXOPT,   // palette
+			 99,      // picture_format_version;
+			 0),
 	GameInfo("Arrow of Death part 1 C64",
-		ARROW1_C64,
-		NO_TYPE,                                          // type
-		static_cast<Subtype>(MYSTERIOUS | ENGLISH | C64), // subtype
-		FOUR_LETTER_UNCOMPRESSED,                         // dictionary type
-
-		64,  // Number of items
-		150, // Number of actions
-		90,  // Number of words
-		52,  // Number of rooms
-		5,   // Max carried items
-		4,   // Word length
-		82,  // Number of messages
-
-		91, // number_of_verbs
-		82, // number_of_nouns;
-
-		0x1dd9,                // header
-		MYSTERIOUS_C64_HEADER, // header style
-
-		0, // no room images
-		0, // no item flags
-		0, // no item images
-
-		0x1df1, // actions
-		UNCOMPRESSED,
-		0x2761,  // dictionary
-		FOLLOWS, // start_of_room_descriptions;
-		FOLLOWS, // start_of_room_connections;
-		FOLLOWS, // start_of_messages;
-		FOLLOWS, // start_of_item_descriptions;
-		FOLLOWS, // start_of_item_locations;
-
-		0x0408, // start_of_system_messages
-		0x0408, // start of directions
-
-		0,      // start_of_characters;
-		0x38e2, // start_of_image_data;
-		0,      // image_address_offset
-		51,     // number_of_pictures;
-		C64A,   // palette
-		99,     // picture_format_version;
-		0),
+			 ARROW1_C64,
+			 NO_TYPE,                                          // type
+			 static_cast<Subtype>(MYSTERIOUS | ENGLISH | C64), // subtype
+			 FOUR_LETTER_UNCOMPRESSED,                         // dictionary type
+
+			 64,  // Number of items
+			 150, // Number of actions
+			 90,  // Number of words
+			 52,  // Number of rooms
+			 5,   // Max carried items
+			 4,   // Word length
+			 82,  // Number of messages
+
+			 91, // number_of_verbs
+			 82, // number_of_nouns;
+
+			 0x1dd9,                // header
+			 MYSTERIOUS_C64_HEADER, // header style
+
+			 0, // no room images
+			 0, // no item flags
+			 0, // no item images
+
+			 0x1df1, // actions
+			 UNCOMPRESSED,
+			 0x2761,  // dictionary
+			 FOLLOWS, // start_of_room_descriptions;
+			 FOLLOWS, // start_of_room_connections;
+			 FOLLOWS, // start_of_messages;
+			 FOLLOWS, // start_of_item_descriptions;
+			 FOLLOWS, // start_of_item_locations;
+
+			 0x0408, // start_of_system_messages
+			 0x0408, // start of directions
+
+			 0,      // start_of_characters;
+			 0x38e2, // start_of_image_data;
+			 0,      // image_address_offset
+			 51,     // number_of_pictures;
+			 C64A,   // palette
+			 99,     // picture_format_version;
+			 0),
 	GameInfo("Arrow of Death part 2",
-		ARROW2,
-		OLD_STYLE,                // type
-		MYSTERIOUS,               // subtype
-		FOUR_LETTER_UNCOMPRESSED, // dictionary type
-
-		91,  // Number of items
-		190, // Number of actions
-		83,  // Number of words
-		65,  // Number of rooms
-		9,   // Max carried items
-		4,   // Word length
-		82,  // Number of messages
-
-		84, // number_of_verbs
-		83, // number_of_nouns;
-
-		0x2351, // header
-		EARLY,  // header style
-
-		0, // no room images
-		0, // no item flags
-		0, // no item images
-
-		0x3b81, // actions
-		UNCOMPRESSED,
-		0x49b7,  // dictionary
-		FOLLOWS, // start_of_room_descriptions;
-		FOLLOWS, // start_of_room_connections;
-		FOLLOWS, // start_of_messages;
-		FOLLOWS, // start_of_item_descriptions;
-		FOLLOWS, // start_of_item_locations;
-
-		0x24c0, // start_of_system_messages
-		0x2780, // start of directions
-
-		0,       // start_of_characters;
-		FOLLOWS, // start_of_image_data;
-		0,       // image_address_offset
-		64,      // number_of_pictures;
-		ZXOPT,   // palette
-		99,      // picture_format_version;
-		0),
+			 ARROW2,
+			 OLD_STYLE,                // type
+			 MYSTERIOUS,               // subtype
+			 FOUR_LETTER_UNCOMPRESSED, // dictionary type
+
+			 91,  // Number of items
+			 190, // Number of actions
+			 83,  // Number of words
+			 65,  // Number of rooms
+			 9,   // Max carried items
+			 4,   // Word length
+			 82,  // Number of messages
+
+			 84, // number_of_verbs
+			 83, // number_of_nouns;
+
+			 0x2351, // header
+			 EARLY,  // header style
+
+			 0, // no room images
+			 0, // no item flags
+			 0, // no item images
+
+			 0x3b81, // actions
+			 UNCOMPRESSED,
+			 0x49b7,  // dictionary
+			 FOLLOWS, // start_of_room_descriptions;
+			 FOLLOWS, // start_of_room_connections;
+			 FOLLOWS, // start_of_messages;
+			 FOLLOWS, // start_of_item_descriptions;
+			 FOLLOWS, // start_of_item_locations;
+
+			 0x24c0, // start_of_system_messages
+			 0x2780, // start of directions
+
+			 0,       // start_of_characters;
+			 FOLLOWS, // start_of_image_data;
+			 0,       // image_address_offset
+			 64,      // number_of_pictures;
+			 ZXOPT,   // palette
+			 99,      // picture_format_version;
+			 0),
 	GameInfo("Arrow of Death part 2 C64",
-		ARROW2_C64,
-		NO_TYPE,                                          // type
-		static_cast<Subtype>(MYSTERIOUS | ENGLISH | C64), // subtype
-		FOUR_LETTER_UNCOMPRESSED,                         // dictionary type
-
-		90,  // Number of items
-		176, // Number of actions
-		82,  // Number of words
-		65,  // Number of rooms
-		9,   // Max carried items
-		4,   // Word length
-		82,  // Number of messages
-
-		81, // number_of_verbs
-		82, // number_of_nouns;
-
-		0x1dd9,                         // header
-		ARROW_OF_DEATH_PT_2_C64_HEADER, // header style
-
-		0, // no room images
-		0, // no item flags
-		0, // no item images
-
-		0x1df1, // actions
-		UNCOMPRESSED,
-		0x2901,  // dictionary
-		FOLLOWS, // start_of_room_descriptions;
-		FOLLOWS, // start_of_room_connections;
-		FOLLOWS, // start_of_messages;
-		FOLLOWS, // start_of_item_descriptions;
-		FOLLOWS, // start_of_item_locations;
-
-		0x408, // start_of_system_messages
-		0x408, // start of directions
-
-		0,      // start_of_characters;
-		0x3cac, // start_of_image_data;
-		0,      // image_address_offset
-		64,     // number_of_pictures;
-		C64A,   // palette
-		99,     // picture_format_version;
-		0),
+			 ARROW2_C64,
+			 NO_TYPE,                                          // type
+			 static_cast<Subtype>(MYSTERIOUS | ENGLISH | C64), // subtype
+			 FOUR_LETTER_UNCOMPRESSED,                         // dictionary type
+
+			 90,  // Number of items
+			 176, // Number of actions
+			 82,  // Number of words
+			 65,  // Number of rooms
+			 9,   // Max carried items
+			 4,   // Word length
+			 82,  // Number of messages
+
+			 81, // number_of_verbs
+			 82, // number_of_nouns;
+
+			 0x1dd9,                         // header
+			 ARROW_OF_DEATH_PT_2_C64_HEADER, // header style
+
+			 0, // no room images
+			 0, // no item flags
+			 0, // no item images
+
+			 0x1df1, // actions
+			 UNCOMPRESSED,
+			 0x2901,  // dictionary
+			 FOLLOWS, // start_of_room_descriptions;
+			 FOLLOWS, // start_of_room_connections;
+			 FOLLOWS, // start_of_messages;
+			 FOLLOWS, // start_of_item_descriptions;
+			 FOLLOWS, // start_of_item_locations;
+
+			 0x408, // start_of_system_messages
+			 0x408, // start of directions
+
+			 0,      // start_of_characters;
+			 0x3cac, // start_of_image_data;
+			 0,      // image_address_offset
+			 64,     // number_of_pictures;
+			 C64A,   // palette
+			 99,     // picture_format_version;
+			 0),
 	GameInfo("Escape from Pulsar 7",
-		PULSAR7,
-		OLD_STYLE,                // type
-		MYSTERIOUS,               // subtype
-		FOUR_LETTER_UNCOMPRESSED, // dictionary type
-
-		90,  // Number of items
-		220, // Number of actions
-		145, // Number of words
-		45,  // Number of rooms
-		6,   // Max carried items
-		4,   // Word length
-		82,  // Number of messages
-
-		146, // number_of_verbs
-		145, // number_of_nouns;
-
-		0x2351, // header
-		EARLY,  // header style
-
-		0, // no room images
-		0, // no item flags
-		0, // no item images
-
-		0x3b81, // actions
-		UNCOMPRESSED,
-		0x4b1d,  // dictionary
-		FOLLOWS, // start_of_room_descriptions;
-		FOLLOWS, // start_of_room_connections;
-		FOLLOWS, // start_of_messages;
-		FOLLOWS, // start_of_item_descriptions;
-		FOLLOWS, // start_of_item_locations;
-
-		0x24c0, // start_of_system_messages
-		0x2780, // start of directions
-
-		0,       // start_of_characters;
-		FOLLOWS, // start_of_image_data;
-		0,       // image_address_offset
-		44,      // number_of_pictures;
-		ZXOPT,   // palette
-		99,      // picture_format_version;
-		0),
+			 PULSAR7,
+			 OLD_STYLE,                // type
+			 MYSTERIOUS,               // subtype
+			 FOUR_LETTER_UNCOMPRESSED, // dictionary type
+
+			 90,  // Number of items
+			 220, // Number of actions
+			 145, // Number of words
+			 45,  // Number of rooms
+			 6,   // Max carried items
+			 4,   // Word length
+			 82,  // Number of messages
+
+			 146, // number_of_verbs
+			 145, // number_of_nouns;
+
+			 0x2351, // header
+			 EARLY,  // header style
+
+			 0, // no room images
+			 0, // no item flags
+			 0, // no item images
+
+			 0x3b81, // actions
+			 UNCOMPRESSED,
+			 0x4b1d,  // dictionary
+			 FOLLOWS, // start_of_room_descriptions;
+			 FOLLOWS, // start_of_room_connections;
+			 FOLLOWS, // start_of_messages;
+			 FOLLOWS, // start_of_item_descriptions;
+			 FOLLOWS, // start_of_item_locations;
+
+			 0x24c0, // start_of_system_messages
+			 0x2780, // start of directions
+
+			 0,       // start_of_characters;
+			 FOLLOWS, // start_of_image_data;
+			 0,       // image_address_offset
+			 44,      // number_of_pictures;
+			 ZXOPT,   // palette
+			 99,      // picture_format_version;
+			 0),
 	GameInfo("Escape from Pulsar 7 C64",
-		PULSAR7_C64,
-		NO_TYPE,                                          // type
-		static_cast<Subtype>(MYSTERIOUS | ENGLISH | C64), // subtype
-		FOUR_LETTER_UNCOMPRESSED,                         // dictionary type
-
-		88,  // Number of items
-		195, // Number of actions
-		145, // Number of words
-		45,  // Number of rooms
-		6,   // Max carried items
-		4,   // Word length
-		82,  // Number of messages
-
-		146, // number_of_verbs
-		102, // number_of_nouns;
-
-		0x1dd9, // header
-		EARLY,  // header style
-
-		0, // no room images
-		0, // no item flags
-		0, // no item images
-
-		0x1da3, // actions
-		UNCOMPRESSED,
-		0x29e3,  // dictionary
-		FOLLOWS, // start_of_room_descriptions;
-		FOLLOWS, // start_of_room_connections;
-		FOLLOWS, // start_of_messages;
-		FOLLOWS, // start_of_item_descriptions;
-		FOLLOWS, // start_of_item_locations;
-
-		0x408, // start_of_system_messages
-		0x408, // start of directions
-
-		0,      // start_of_characters;
-		0x3bf4, // start_of_image_data;
-		0,      // image_address_offset
-		44,     // number_of_pictures;
-		C64A,   // palette
-		99,     // picture_format_version;
-		0),
+			 PULSAR7_C64,
+			 NO_TYPE,                                          // type
+			 static_cast<Subtype>(MYSTERIOUS | ENGLISH | C64), // subtype
+			 FOUR_LETTER_UNCOMPRESSED,                         // dictionary type
+
+			 88,  // Number of items
+			 195, // Number of actions
+			 145, // Number of words
+			 45,  // Number of rooms
+			 6,   // Max carried items
+			 4,   // Word length
+			 82,  // Number of messages
+
+			 146, // number_of_verbs
+			 102, // number_of_nouns;
+
+			 0x1dd9, // header
+			 EARLY,  // header style
+
+			 0, // no room images
+			 0, // no item flags
+			 0, // no item images
+
+			 0x1da3, // actions
+			 UNCOMPRESSED,
+			 0x29e3,  // dictionary
+			 FOLLOWS, // start_of_room_descriptions;
+			 FOLLOWS, // start_of_room_connections;
+			 FOLLOWS, // start_of_messages;
+			 FOLLOWS, // start_of_item_descriptions;
+			 FOLLOWS, // start_of_item_locations;
+
+			 0x408, // start_of_system_messages
+			 0x408, // start of directions
+
+			 0,      // start_of_characters;
+			 0x3bf4, // start_of_image_data;
+			 0,      // image_address_offset
+			 44,     // number_of_pictures;
+			 C64A,   // palette
+			 99,     // picture_format_version;
+			 0),
 	GameInfo("Circus",
-		CIRCUS,
-		OLD_STYLE,                // type
-		MYSTERIOUS,               // subtype
-		FOUR_LETTER_UNCOMPRESSED, // dictionary type
-
-		65,  // Number of items
-		165, // Number of actions
-		97,  // Number of words
-		36,  // Number of rooms
-		6,   // Max carried items
-		4,   // Word length
-		82,  // Number of messages
-
-		98, // number_of_verbs
-		97, // number_of_nouns;
-
-		0x2349, // header
-		EARLY,  // header style
-
-		0, // no room images
-		0, // no item flags
-		0, // no item images
-
-		0x3b56, // actions
-		UNCOMPRESSED,
-		0x471a,  // dictionary
-		FOLLOWS, // start_of_room_descriptions;
-		FOLLOWS, // start_of_room_connections;
-		FOLLOWS, // start_of_messages;
-		FOLLOWS, // start_of_item_descriptions;
-		FOLLOWS, // start_of_item_locations;
-
-		0x24c0, // start_of_system_messages
-		0x277E, // start of directions
-
-		0,       // start_of_characters;
-		FOLLOWS, // start_of_image_data;
-		0,       // image_address_offset
-		35,      // number_of_pictures;
-		ZXOPT,   // palette
-		99,      // picture_format_version;
-		0),
+			 CIRCUS,
+			 OLD_STYLE,                // type
+			 MYSTERIOUS,               // subtype
+			 FOUR_LETTER_UNCOMPRESSED, // dictionary type
+
+			 65,  // Number of items
+			 165, // Number of actions
+			 97,  // Number of words
+			 36,  // Number of rooms
+			 6,   // Max carried items
+			 4,   // Word length
+			 82,  // Number of messages
+
+			 98, // number_of_verbs
+			 97, // number_of_nouns;
+
+			 0x2349, // header
+			 EARLY,  // header style
+
+			 0, // no room images
+			 0, // no item flags
+			 0, // no item images
+
+			 0x3b56, // actions
+			 UNCOMPRESSED,
+			 0x471a,  // dictionary
+			 FOLLOWS, // start_of_room_descriptions;
+			 FOLLOWS, // start_of_room_connections;
+			 FOLLOWS, // start_of_messages;
+			 FOLLOWS, // start_of_item_descriptions;
+			 FOLLOWS, // start_of_item_locations;
+
+			 0x24c0, // start_of_system_messages
+			 0x277E, // start of directions
+
+			 0,       // start_of_characters;
+			 FOLLOWS, // start_of_image_data;
+			 0,       // image_address_offset
+			 35,      // number_of_pictures;
+			 ZXOPT,   // palette
+			 99,      // picture_format_version;
+			 0),
 	GameInfo("Circus C64",
-		CIRCUS_C64,
-		NO_TYPE,                                          // type
-		static_cast<Subtype>(MYSTERIOUS | ENGLISH | C64), // subtype
-		FOUR_LETTER_UNCOMPRESSED,                         // dictionary type
-
-		65,  // Number of items
-		165, // Number of actions
-		97,  // Number of words
-		36,  // Number of rooms
-		6,   // Max carried items
-		4,   // Word length
-		72,  // Number of messages
-
-		98, // number_of_verbs
-		96, // number_of_nouns;
-
-		0x1dd9,                // header
-		MYSTERIOUS_C64_HEADER, // header style
-
-		0, // no room images
-		0, // no item flags
-		0, // no item images
-
-		0x1df1, // actions
-		UNCOMPRESSED,
-		0x2851,  // dictionary
-		FOLLOWS, // start_of_room_descriptions;
-		FOLLOWS, // start_of_room_connections;
-		FOLLOWS, // start_of_messages;
-		FOLLOWS, // start_of_item_descriptions;
-		FOLLOWS, // start_of_item_locations;
-
-		0x408, // start_of_system_messages
-		0x408, // start of directions
-
-		0,      // start_of_characters;
-		0x3914, // start_of_image_data;
-		0,      // image_address_offset
-		35,     // number_of_pictures;
-		C64A,   // palette
-		99,     // picture_format_version;
-		0),
+			 CIRCUS_C64,
+			 NO_TYPE,                                          // type
+			 static_cast<Subtype>(MYSTERIOUS | ENGLISH | C64), // subtype
+			 FOUR_LETTER_UNCOMPRESSED,                         // dictionary type
+
+			 65,  // Number of items
+			 165, // Number of actions
+			 97,  // Number of words
+			 36,  // Number of rooms
+			 6,   // Max carried items
+			 4,   // Word length
+			 72,  // Number of messages
+
+			 98, // number_of_verbs
+			 96, // number_of_nouns;
+
+			 0x1dd9,                // header
+			 MYSTERIOUS_C64_HEADER, // header style
+
+			 0, // no room images
+			 0, // no item flags
+			 0, // no item images
+
+			 0x1df1, // actions
+			 UNCOMPRESSED,
+			 0x2851,  // dictionary
+			 FOLLOWS, // start_of_room_descriptions;
+			 FOLLOWS, // start_of_room_connections;
+			 FOLLOWS, // start_of_messages;
+			 FOLLOWS, // start_of_item_descriptions;
+			 FOLLOWS, // start_of_item_locations;
+
+			 0x408, // start_of_system_messages
+			 0x408, // start of directions
+
+			 0,      // start_of_characters;
+			 0x3914, // start_of_image_data;
+			 0,      // image_address_offset
+			 35,     // number_of_pictures;
+			 C64A,   // palette
+			 99,     // picture_format_version;
+			 0),
 	GameInfo("Feasibility Experiment",
-		FEASIBILITY,
-		OLD_STYLE,                // type
-		MYSTERIOUS,               // subtype
-		FOUR_LETTER_UNCOMPRESSED, // dictionary type
-
-		65,  // Number of items
-		164, // Number of actions
-		82,  // Number of words
-		59,  // Number of rooms
-		5,   // Max carried items
-		4,   // Word length
-		82,  // Number of messages
-
-		83, // number_of_verbs
-		82, // number_of_nouns;
-
-		0x2351, // header
-		EARLY,  // header style
-
-		0, // no room images
-		0, // no item flags
-		0, // no item images
-
-		0x3b81, // actions
-		UNCOMPRESSED,
-		0x47bf,  // dictionary
-		FOLLOWS, // start_of_room_descriptions;
-		FOLLOWS, // start_of_room_connections;
-		FOLLOWS, // start_of_messages;
-		FOLLOWS, // start_of_item_descriptions;
-		FOLLOWS, // start_of_item_locations;
-
-		0x24c0, // start_of_system_messages
-		0x2780, // start of directions
-
-		0,       // start_of_characters;
-		FOLLOWS, // start_of_image_data;
-		0,       // image_address_offset
-		58,      // number_of_pictures;
-		ZXOPT,   // palette
-		99,      // picture_format_version;
-		0),
+			 FEASIBILITY,
+			 OLD_STYLE,                // type
+			 MYSTERIOUS,               // subtype
+			 FOUR_LETTER_UNCOMPRESSED, // dictionary type
+
+			 65,  // Number of items
+			 164, // Number of actions
+			 82,  // Number of words
+			 59,  // Number of rooms
+			 5,   // Max carried items
+			 4,   // Word length
+			 82,  // Number of messages
+
+			 83, // number_of_verbs
+			 82, // number_of_nouns;
+
+			 0x2351, // header
+			 EARLY,  // header style
+
+			 0, // no room images
+			 0, // no item flags
+			 0, // no item images
+
+			 0x3b81, // actions
+			 UNCOMPRESSED,
+			 0x47bf,  // dictionary
+			 FOLLOWS, // start_of_room_descriptions;
+			 FOLLOWS, // start_of_room_connections;
+			 FOLLOWS, // start_of_messages;
+			 FOLLOWS, // start_of_item_descriptions;
+			 FOLLOWS, // start_of_item_locations;
+
+			 0x24c0, // start_of_system_messages
+			 0x2780, // start of directions
+
+			 0,       // start_of_characters;
+			 FOLLOWS, // start_of_image_data;
+			 0,       // image_address_offset
+			 58,      // number_of_pictures;
+			 ZXOPT,   // palette
+			 99,      // picture_format_version;
+			 0),
 	GameInfo("Feasibility Experiment C64",
-		FEASIBILITY_C64,
-		NO_TYPE,                                          // type
-		static_cast<Subtype>(MYSTERIOUS | ENGLISH | C64), // subtype
-		FOUR_LETTER_UNCOMPRESSED,                         // dictionary type
-
-		65,  // Number of items
-		156, // Number of actions
-		79,  // Number of words
-		59,  // Number of rooms
-		6,   // Max carried items
-		4,   // Word length
-		82,  // Number of messages
-
-		56, // number_of_verbs
-		80, // number_of_nouns;
-
-		0x1dd9, // header
-		EARLY,  // header style
-
-		0, // no room images
-		0, // no item flags
-		0, // no item images
-
-		0x1df3, // actions
-		UNCOMPRESSED,
-		0x27c3,  // dictionary
-		FOLLOWS, // start_of_room_descriptions;
-		FOLLOWS, // start_of_room_connections;
-		FOLLOWS, // start_of_messages;
-		FOLLOWS, // start_of_item_descriptions;
-		FOLLOWS, // start_of_item_locations;
-
-		0x408, // start_of_system_messages
-		0x408, // start of directions
-
-		0,      // start_of_characters;
-		0x3876, // start_of_image_data;
-		0,      // image_address_offset
-		58,     // number_of_pictures;
-		C64A,   // palette
-		99,     // picture_format_version;
-		0),
+			 FEASIBILITY_C64,
+			 NO_TYPE,                                          // type
+			 static_cast<Subtype>(MYSTERIOUS | ENGLISH | C64), // subtype
+			 FOUR_LETTER_UNCOMPRESSED,                         // dictionary type
+
+			 65,  // Number of items
+			 156, // Number of actions
+			 79,  // Number of words
+			 59,  // Number of rooms
+			 6,   // Max carried items
+			 4,   // Word length
+			 82,  // Number of messages
+
+			 56, // number_of_verbs
+			 80, // number_of_nouns;
+
+			 0x1dd9, // header
+			 EARLY,  // header style
+
+			 0, // no room images
+			 0, // no item flags
+			 0, // no item images
+
+			 0x1df3, // actions
+			 UNCOMPRESSED,
+			 0x27c3,  // dictionary
+			 FOLLOWS, // start_of_room_descriptions;
+			 FOLLOWS, // start_of_room_connections;
+			 FOLLOWS, // start_of_messages;
+			 FOLLOWS, // start_of_item_descriptions;
+			 FOLLOWS, // start_of_item_locations;
+
+			 0x408, // start_of_system_messages
+			 0x408, // start of directions
+
+			 0,      // start_of_characters;
+			 0x3876, // start_of_image_data;
+			 0,      // image_address_offset
+			 58,     // number_of_pictures;
+			 C64A,   // palette
+			 99,     // picture_format_version;
+			 0),
 	GameInfo("The Wizard of Akyrz",
-		AKYRZ,
-		OLD_STYLE,                // type
-		MYSTERIOUS,               // subtype
-		FOUR_LETTER_UNCOMPRESSED, // dictionary type
-
-		49,  // Number of items
-		201, // Number of actions
-		85,  // Number of words
-		40,  // Number of rooms
-		6,   // Max carried items
-		4,   // Word length
-		82,  // Number of messages
-
-		86, // number_of_verbs
-		85, // number_of_nouns;
-
-		0x2351, // header
-		EARLY,  // header style
-
-		0, // no room images
-		0, // no item flags
-		0, // no item images
-
-		0x3b81, // actions
-		UNCOMPRESSED,
-		0x497d,  // dictionary
-		FOLLOWS, // start_of_room_descriptions;
-		FOLLOWS, // start_of_room_connections;
-		FOLLOWS, // start_of_messages;
-		FOLLOWS, // start_of_item_descriptions;
-		FOLLOWS, // start_of_item_locations;
-
-		0x24c0, // start_of_system_messages
-		0x2780, // start of directions
-
-		0,       // start_of_characters;
-		FOLLOWS, // start_of_image_data;
-		0,       // image_address_offset
-		39,      // number_of_pictures;
-		ZXOPT,   // palette
-		99,      // picture_format_version;
-		0),
+			 AKYRZ,
+			 OLD_STYLE,                // type
+			 MYSTERIOUS,               // subtype
+			 FOUR_LETTER_UNCOMPRESSED, // dictionary type
+
+			 49,  // Number of items
+			 201, // Number of actions
+			 85,  // Number of words
+			 40,  // Number of rooms
+			 6,   // Max carried items
+			 4,   // Word length
+			 82,  // Number of messages
+
+			 86, // number_of_verbs
+			 85, // number_of_nouns;
+
+			 0x2351, // header
+			 EARLY,  // header style
+
+			 0, // no room images
+			 0, // no item flags
+			 0, // no item images
+
+			 0x3b81, // actions
+			 UNCOMPRESSED,
+			 0x497d,  // dictionary
+			 FOLLOWS, // start_of_room_descriptions;
+			 FOLLOWS, // start_of_room_connections;
+			 FOLLOWS, // start_of_messages;
+			 FOLLOWS, // start_of_item_descriptions;
+			 FOLLOWS, // start_of_item_locations;
+
+			 0x24c0, // start_of_system_messages
+			 0x2780, // start of directions
+
+			 0,       // start_of_characters;
+			 FOLLOWS, // start_of_image_data;
+			 0,       // image_address_offset
+			 39,      // number_of_pictures;
+			 ZXOPT,   // palette
+			 99,      // picture_format_version;
+			 0),
 	GameInfo("The Wizard of Akyrz C64",
-		AKYRZ_C64,
-		NO_TYPE,                                          // type
-		static_cast<Subtype>(MYSTERIOUS | ENGLISH | C64), // subtype
-		FOUR_LETTER_UNCOMPRESSED,                         // dictionary type
-
-		49,  // Number of items
-		199, // Number of actions
-		85,  // Number of words
-		40,  // Number of rooms
-		6,   // Max carried items
-		4,   // Word length
-		82,  // Number of messages
-
-		67, // number_of_verbs
-		85, // number_of_nouns;
-
-		0x1dd9,                // header
-		MYSTERIOUS_C64_HEADER, // header style
-
-		0, // no room images
-		0, // no item flags
-		0, // no item images
-
-		0x1df1, // actions
-		UNCOMPRESSED,
-		0x2a71,  // dictionary
-		FOLLOWS, // start_of_room_descriptions;
-		FOLLOWS, // start_of_room_connections;
-		FOLLOWS, // start_of_messages;
-		FOLLOWS, // start_of_item_descriptions;
-		FOLLOWS, // start_of_item_locations;
-
-		0x408, // start_of_system_messages
-		0x408, // start of directions
-
-		0,      // start_of_characters;
-		0x3bce, // start_of_image_data;
-		0,      // image_address_offset
-		39,     // number_of_pictures;
-		C64A,   // palette
-		99,     // picture_format_version;
-		0),
+			 AKYRZ_C64,
+			 NO_TYPE,                                          // type
+			 static_cast<Subtype>(MYSTERIOUS | ENGLISH | C64), // subtype
+			 FOUR_LETTER_UNCOMPRESSED,                         // dictionary type
+
+			 49,  // Number of items
+			 199, // Number of actions
+			 85,  // Number of words
+			 40,  // Number of rooms
+			 6,   // Max carried items
+			 4,   // Word length
+			 82,  // Number of messages
+
+			 67, // number_of_verbs
+			 85, // number_of_nouns;
+
+			 0x1dd9,                // header
+			 MYSTERIOUS_C64_HEADER, // header style
+
+			 0, // no room images
+			 0, // no item flags
+			 0, // no item images
+
+			 0x1df1, // actions
+			 UNCOMPRESSED,
+			 0x2a71,  // dictionary
+			 FOLLOWS, // start_of_room_descriptions;
+			 FOLLOWS, // start_of_room_connections;
+			 FOLLOWS, // start_of_messages;
+			 FOLLOWS, // start_of_item_descriptions;
+			 FOLLOWS, // start_of_item_locations;
+
+			 0x408, // start_of_system_messages
+			 0x408, // start of directions
+
+			 0,      // start_of_characters;
+			 0x3bce, // start_of_image_data;
+			 0,      // image_address_offset
+			 39,     // number_of_pictures;
+			 C64A,   // palette
+			 99,     // picture_format_version;
+			 0),
 	GameInfo("Perseus and Andromeda",
-		PERSEUS,
-		OLD_STYLE,                // type
-		MYSTERIOUS,               // subtype
-		FOUR_LETTER_UNCOMPRESSED, // dictionary type
-
-		60,  // Number of items
-		178, // Number of actions
-		130, // Number of words
-		40,  // Number of rooms
-		6,   // Max carried items
-		4,   // Word length
-		82,  // Number of messages
-
-		131, // number_of_verbs
-		130, // number_of_nouns;
-
-		0x2351, // header
-		EARLY,  // header style
-
-		0, // no room images
-		0, // no item flags
-		0, // no item images
-
-		0x3b81, // actions
-		UNCOMPRESSED,
-		0x4823,  // dictionary
-		FOLLOWS, // start_of_room_descriptions;
-		FOLLOWS, // start_of_room_connections;
-		FOLLOWS, // start_of_messages;
-		FOLLOWS, // start_of_item_descriptions;
-		FOLLOWS, // start_of_item_locations;
-
-		0x24c0, // start_of_system_messages
-		0x2780, // start of directions
-
-		0,       // start_of_characters;
-		FOLLOWS, // start_of_image_data;
-		0,       // image_address_offset
-		39,      // number_of_pictures;
-		ZXOPT,   // palette
-		99,      // picture_format_version;
-		0),
+			 PERSEUS,
+			 OLD_STYLE,                // type
+			 MYSTERIOUS,               // subtype
+			 FOUR_LETTER_UNCOMPRESSED, // dictionary type
+
+			 60,  // Number of items
+			 178, // Number of actions
+			 130, // Number of words
+			 40,  // Number of rooms
+			 6,   // Max carried items
+			 4,   // Word length
+			 82,  // Number of messages
+
+			 131, // number_of_verbs
+			 130, // number_of_nouns;
+
+			 0x2351, // header
+			 EARLY,  // header style
+
+			 0, // no room images
+			 0, // no item flags
+			 0, // no item images
+
+			 0x3b81, // actions
+			 UNCOMPRESSED,
+			 0x4823,  // dictionary
+			 FOLLOWS, // start_of_room_descriptions;
+			 FOLLOWS, // start_of_room_connections;
+			 FOLLOWS, // start_of_messages;
+			 FOLLOWS, // start_of_item_descriptions;
+			 FOLLOWS, // start_of_item_locations;
+
+			 0x24c0, // start_of_system_messages
+			 0x2780, // start of directions
+
+			 0,       // start_of_characters;
+			 FOLLOWS, // start_of_image_data;
+			 0,       // image_address_offset
+			 39,      // number_of_pictures;
+			 ZXOPT,   // palette
+			 99,      // picture_format_version;
+			 0),
 	GameInfo("Perseus and Andromeda C64",
-		PERSEUS_C64,
-		NO_TYPE,                                          // type
-		static_cast<Subtype>(MYSTERIOUS | ENGLISH | C64), // subtype
-		FOUR_LETTER_UNCOMPRESSED,                         // dictionary type
-
-		59,  // Number of items
-		165, // Number of actions
-		130, // Number of words
-		40,  // Number of rooms
-		6,   // Max carried items
-		4,   // Word length
-		82,  // Number of messages
-
-		131, // number_of_verbs
-		82,  // number_of_nouns;
-
-		0x1dd9, // header
-		EARLY,  // header style
-
-		0, // no room images
-		0, // no item flags
-		0, // no item images
-
-		0x1df3, // actions
-		UNCOMPRESSED,
-		0x2853,  // dictionary
-		FOLLOWS, // start_of_room_descriptions;
-		FOLLOWS, // start_of_room_connections;
-		FOLLOWS, // start_of_messages;
-		FOLLOWS, // start_of_item_descriptions;
-		FOLLOWS, // start_of_item_locations;
-
-		0x408, // start_of_system_messages
-		0x408, // start of directions
-
-		0,      // start_of_characters;
-		0x3d91, // start_of_image_data;
-		0,      // image_address_offset
-		39,     // number_of_pictures;
-		C64A,   // palette
-		99,     // picture_format_version;
-		0),
-	GameInfo("Perseus and Andromeda C64",
-		PERSEUS_C64,
-		NO_TYPE,                                          // type
-		static_cast<Subtype>(MYSTERIOUS | ENGLISH | C64), // subtype
-		FOUR_LETTER_UNCOMPRESSED,                         // dictionary type
-
-		59,  // Number of items
-		165, // Number of actions
-		130, // Number of words
-		40,  // Number of rooms
-		6,   // Max carried items
-		4,   // Word length
-		82,  // Number of messages
-
-		131, // number_of_verbs
-		82,  // number_of_nouns;
-
-		0x1dd9, // header
-		EARLY,  // header style
-
-		0, // no room images
-		0, // no item flags
-		0, // no item images
-
-		0x1df3, // actions
-		UNCOMPRESSED,
-		0x2853,  // dictionary
-		FOLLOWS, // start_of_room_descriptions;
-		FOLLOWS, // start_of_room_connections;
-		FOLLOWS, // start_of_messages;
-		FOLLOWS, // start_of_item_descriptions;
-		FOLLOWS, // start_of_item_locations;
-
-		0x408, // start_of_system_messages
-		0x408, // start of directions
-
-		0,      // start_of_characters;
-		0x3d91, // start_of_image_data;
-		0,      // image_address_offset
-		39,     // number_of_pictures;
-		C64A,   // palette
-		99,     // picture_format_version;
-		0),
-	GameInfo("Perseus and Andromeda C64",
-		PERSEUS_C64,
-		NO_TYPE,                                          // type
-		static_cast<Subtype>(MYSTERIOUS | ENGLISH | C64), // subtype
-		FOUR_LETTER_UNCOMPRESSED,                         // dictionary type
-
-		59,  // Number of items
-		165, // Number of actions
-		130, // Number of words
-		40,  // Number of rooms
-		6,   // Max carried items
-		4,   // Word length
-		82,  // Number of messages
-
-		131, // number_of_verbs
-		82,  // number_of_nouns;
-
-		0x1dd9, // header
-		EARLY,  // header style
-
-		0, // no room images
-		0, // no item flags
-		0, // no item images
-
-		0x1df3, // actions
-		UNCOMPRESSED,
-		0x2853,  // dictionary
-		FOLLOWS, // start_of_room_descriptions;
-		FOLLOWS, // start_of_room_connections;
-		FOLLOWS, // start_of_messages;
-		FOLLOWS, // start_of_item_descriptions;
-		FOLLOWS, // start_of_item_locations;
-
-		0x408, // start_of_system_messages
-		0x408, // start of directions
-
-		0,      // start_of_characters;
-		0x3d91, // start_of_image_data;
-		0,      // image_address_offset
-		39,     // number_of_pictures;
-		C64A,   // palette
-		99,     // picture_format_version;
-		0),
-	GameInfo("Perseus and Andromeda Italian",
-		PERSEUS_ITALIAN,
-		OLD_STYLE,  // type
-		MYSTERIOUS, // subtype
-		ITALIAN,    // dictionary type
-
-		60,  // Number of items
-		178, // Number of actions
-		130, // Number of words
-		40,  // Number of rooms
-		6,   // Max carried items
-		4,   // Word length
-		82,  // Number of messages
-
-		131, // number_of_verbs
-		83,  // number_of_nouns;
-
-		0x045d, // header
-		EARLY,  // header style
-
-		0, // no room images
-		0, // no item flags
-		0, // no item images
-
-		0x1c8d, // actions
-		UNCOMPRESSED,
-		0x292f,  // dictionary
-		0x2e4d,  // start_of_room_descriptions;
-		FOLLOWS, // start_of_room_connections;
-		FOLLOWS, // start_of_messages;
-		FOLLOWS, // start_of_item_descriptions;
-		FOLLOWS, // start_of_item_locations;
-
-		0x5d5, // start_of_system_messages
-		0x892, // start of directions
-
-		0,      // start_of_characters;
-		0x3faa, // start_of_image_data;
-		0,      // image_address_offset
-		40,     // number_of_pictures;
-		ZXOPT,  // palette
-		99,     // picture_format_version;
-		0),
+			 PERSEUS_C64,
+			 NO_TYPE,                                          // type
+			 static_cast<Subtype>(MYSTERIOUS | ENGLISH | C64), // subtype
+			 FOUR_LETTER_UNCOMPRESSED,                         // dictionary type
+
+			 59,  // Number of items
+			 165, // Number of actions
+			 130, // Number of words
+			 40,  // Number of rooms
+			 6,   // Max carried items
+			 4,   // Word length
+			 82,  // Number of messages
+
+			 131, // number_of_verbs
+			 82,  // number_of_nouns;
+
+			 0x1dd9, // header
+			 EARLY,  // header style
+
+			 0, // no room images
+			 0, // no item flags
+			 0, // no item images
+
+			 0x1df3, // actions
+			 UNCOMPRESSED,
+			 0x2853,  // dictionary
+			 FOLLOWS, // start_of_room_descriptions;
+			 FOLLOWS, // start_of_room_connections;
+			 FOLLOWS, // start_of_messages;
+			 FOLLOWS, // start_of_item_descriptions;
+			 FOLLOWS, // start_of_item_locations;
+
+			 0x408, // start_of_system_messages
+			 0x408, // start of directions
+
+			 0,      // start_of_characters;
+			 0x3d91, // start_of_image_data;
+			 0,      // image_address_offset
+			 39,     // number_of_pictures;
+			 C64A,   // palette
+			 99,     // picture_format_version;
+			 0),
 	GameInfo("Ten Little Indians",
-		INDIANS,
-		OLD_STYLE,                // type
-		MYSTERIOUS,               // subtype
-		FOUR_LETTER_UNCOMPRESSED, // dictionary type
-
-		73,  // Number of items
-		161, // Number of actions
-		85,  // Number of words
-		63,  // Number of rooms
-		5,   // Max carried items
-		4,   // Word length
-		82,  // Number of messages
-
-		86, // number_of_verbs
-		85, // number_of_nouns;
-
-		0x2351, // header
-		EARLY,  // header style
-
-		0, // no room images
-		0, // no item flags
-		0, // no item images
-
-		0x3b81, // actions
-		UNCOMPRESSED,
-		0x47b7,  // dictionary
-		FOLLOWS, // start_of_room_descriptions;
-		FOLLOWS, // start_of_room_connections;
-		FOLLOWS, // start_of_messages;
-		FOLLOWS, // start_of_item_descriptions;
-		FOLLOWS, // start_of_item_locations;
-
-		0x24c0, // start_of_system_messages
-		0x2780, // start of directions
-
-		0,       // start_of_characters;
-		FOLLOWS, // start_of_image_data;
-		0,       // image_address_offset
-		62,      // number_of_pictures;
-		ZXOPT,   // palette
-		99,      // picture_format_version;
-		0),
+			 INDIANS,
+			 OLD_STYLE,                // type
+			 MYSTERIOUS,               // subtype
+			 FOUR_LETTER_UNCOMPRESSED, // dictionary type
+
+			 73,  // Number of items
+			 161, // Number of actions
+			 85,  // Number of words
+			 63,  // Number of rooms
+			 5,   // Max carried items
+			 4,   // Word length
+			 82,  // Number of messages
+
+			 86, // number_of_verbs
+			 85, // number_of_nouns;
+
+			 0x2351, // header
+			 EARLY,  // header style
+
+			 0, // no room images
+			 0, // no item flags
+			 0, // no item images
+
+			 0x3b81, // actions
+			 UNCOMPRESSED,
+			 0x47b7,  // dictionary
+			 FOLLOWS, // start_of_room_descriptions;
+			 FOLLOWS, // start_of_room_connections;
+			 FOLLOWS, // start_of_messages;
+			 FOLLOWS, // start_of_item_descriptions;
+			 FOLLOWS, // start_of_item_locations;
+
+			 0x24c0, // start_of_system_messages
+			 0x2780, // start of directions
+
+			 0,       // start_of_characters;
+			 FOLLOWS, // start_of_image_data;
+			 0,       // image_address_offset
+			 62,      // number_of_pictures;
+			 ZXOPT,   // palette
+			 99,      // picture_format_version;
+			 0),
 	GameInfo("Ten Little Indians C64",
-		INDIANS_C64,
-		NO_TYPE,                                          // type
-		static_cast<Subtype>(MYSTERIOUS | ENGLISH | C64), // subtype
-		FOUR_LETTER_UNCOMPRESSED,                         // dictionary type
-
-		73,  // Number of items
-		161, // Number of actions
-		82,  // Number of words
-		63,  // Number of rooms
-		5,   // Max carried items
-		4,   // Word length
-		82,  // Number of messages
-
-		64, // number_of_verbs
-		82, // number_of_nouns;
-
-		0x1dd9,             // header
-		INDIANS_C64_HEADER, // header style
-
-		0, // no room images
-		0, // no item flags
-		0, // no item images
-
-		0x1df0, // actions
-		UNCOMPRESSED,
-		0x2810,  // dictionary
-		FOLLOWS, // start_of_room_descriptions;
-		FOLLOWS, // start_of_room_connections;
-		FOLLOWS, // start_of_messages;
-		FOLLOWS, // start_of_item_descriptions;
-		FOLLOWS, // start_of_item_locations;
-
-		0x408, // start_of_system_messages
-		0x408, // start of directions
-
-		0,      // start_of_characters;
-		0x3a46, // start_of_image_data;
-		0,      // image_address_offset
-		62,     // number_of_pictures;
-		C64A,   // palette
-		99,     // picture_format_version;
-		0),
+			 INDIANS_C64,
+			 NO_TYPE,                                          // type
+			 static_cast<Subtype>(MYSTERIOUS | ENGLISH | C64), // subtype
+			 FOUR_LETTER_UNCOMPRESSED,                         // dictionary type
+
+			 73,  // Number of items
+			 161, // Number of actions
+			 82,  // Number of words
+			 63,  // Number of rooms
+			 5,   // Max carried items
+			 4,   // Word length
+			 82,  // Number of messages
+
+			 64, // number_of_verbs
+			 82, // number_of_nouns;
+
+			 0x1dd9,             // header
+			 INDIANS_C64_HEADER, // header style
+
+			 0, // no room images
+			 0, // no item flags
+			 0, // no item images
+
+			 0x1df0, // actions
+			 UNCOMPRESSED,
+			 0x2810,  // dictionary
+			 FOLLOWS, // start_of_room_descriptions;
+			 FOLLOWS, // start_of_room_connections;
+			 FOLLOWS, // start_of_messages;
+			 FOLLOWS, // start_of_item_descriptions;
+			 FOLLOWS, // start_of_item_locations;
+
+			 0x408, // start_of_system_messages
+			 0x408, // start of directions
+
+			 0,      // start_of_characters;
+			 0x3a46, // start_of_image_data;
+			 0,      // image_address_offset
+			 62,     // number_of_pictures;
+			 C64A,   // palette
+			 99,     // picture_format_version;
+			 0),
 	GameInfo("Waxworks",
-		WAXWORKS,
-		OLD_STYLE,                // type
-		MYSTERIOUS,               // subtype
-		FOUR_LETTER_UNCOMPRESSED, // dictionary type
-
-		57,  // Number of items
-		189, // Number of actions
-		106, // Number of words
-		41,  // Number of rooms
-		6,   // Max carried items
-		4,   // Word length
-		82,  // Number of messages
-
-		107, // number_of_verbs
-		106, // number_of_nouns;
-
-		0x2351, // header
-		EARLY,  // header style
-
-		0, // no room images
-		0, // no item flags
-		0, // no item images
-
-		0x3b81, // actions
-		UNCOMPRESSED,
-		0x48d3,  // dictionary
-		FOLLOWS, // start_of_room_descriptions;
-		FOLLOWS, // start_of_room_connections;
-		FOLLOWS, // start_of_messages;
-		FOLLOWS, // start_of_item_descriptions;
-		FOLLOWS, // start_of_item_locations;
-
-		0x24c0, // start_of_system_messages
-		0x2780, // start of directions
-
-		0,       // start_of_characters;
-		FOLLOWS, // start_of_image_data;
-		0,       // image_address_offset
-		40,      // number_of_pictures;
-		ZXOPT,   // palette
-		99,      // picture_format_version;
-		0),
+			 WAXWORKS,
+			 OLD_STYLE,                // type
+			 MYSTERIOUS,               // subtype
+			 FOUR_LETTER_UNCOMPRESSED, // dictionary type
+
+			 57,  // Number of items
+			 189, // Number of actions
+			 106, // Number of words
+			 41,  // Number of rooms
+			 6,   // Max carried items
+			 4,   // Word length
+			 82,  // Number of messages
+
+			 107, // number_of_verbs
+			 106, // number_of_nouns;
+
+			 0x2351, // header
+			 EARLY,  // header style
+
+			 0, // no room images
+			 0, // no item flags
+			 0, // no item images
+
+			 0x3b81, // actions
+			 UNCOMPRESSED,
+			 0x48d3,  // dictionary
+			 FOLLOWS, // start_of_room_descriptions;
+			 FOLLOWS, // start_of_room_connections;
+			 FOLLOWS, // start_of_messages;
+			 FOLLOWS, // start_of_item_descriptions;
+			 FOLLOWS, // start_of_item_locations;
+
+			 0x24c0, // start_of_system_messages
+			 0x2780, // start of directions
+
+			 0,       // start_of_characters;
+			 FOLLOWS, // start_of_image_data;
+			 0,       // image_address_offset
+			 40,      // number_of_pictures;
+			 ZXOPT,   // palette
+			 99,      // picture_format_version;
+			 0),
 	GameInfo("Waxworks C64",
-		WAXWORKS_C64,
-		NO_TYPE,                                          // type
-		static_cast<Subtype>(MYSTERIOUS | ENGLISH | C64), // subtype
-		FOUR_LETTER_UNCOMPRESSED,                         // dictionary type
-
-		57,  // Number of items
-		189, // Number of actions
-		105, // Number of words
-		41,  // Number of rooms
-		6,   // Max carried items
-		4,   // Word length
-		82,  // Number of messages
-
-		91,  // number_of_verbs
-		105, // number_of_nouns;
-
-		0x1dd9, // header
-		EARLY,  // header style
-
-		0, // no room images
-		0, // no item flags
-		0, // no item images
-
-		0x1df3, // actions
-		UNCOMPRESSED,
-		0x29d3,  // dictionary
-		FOLLOWS, // start_of_room_descriptions;
-		FOLLOWS, // start_of_room_connections;
-		FOLLOWS, // start_of_messages;
-		FOLLOWS, // start_of_item_descriptions;
-		FOLLOWS, // start_of_item_locations;
-
-		0x408, // start_of_system_messages
-		0x408, // start of directions
-
-		0,      // start_of_characters;
-		0x3f31, // start_of_image_data;
-		0,      // image_address_offset
-		40,     // number_of_pictures;
-		C64A,   // palette
-		99,     // picture_format_version;
-		0),
+			 WAXWORKS_C64,
+			 NO_TYPE,                                          // type
+			 static_cast<Subtype>(MYSTERIOUS | ENGLISH | C64), // subtype
+			 FOUR_LETTER_UNCOMPRESSED,                         // dictionary type
+
+			 57,  // Number of items
+			 189, // Number of actions
+			 105, // Number of words
+			 41,  // Number of rooms
+			 6,   // Max carried items
+			 4,   // Word length
+			 82,  // Number of messages
+
+			 91,  // number_of_verbs
+			 105, // number_of_nouns;
+
+			 0x1dd9, // header
+			 EARLY,  // header style
+
+			 0, // no room images
+			 0, // no item flags
+			 0, // no item images
+
+			 0x1df3, // actions
+			 UNCOMPRESSED,
+			 0x29d3,  // dictionary
+			 FOLLOWS, // start_of_room_descriptions;
+			 FOLLOWS, // start_of_room_connections;
+			 FOLLOWS, // start_of_messages;
+			 FOLLOWS, // start_of_item_descriptions;
+			 FOLLOWS, // start_of_item_locations;
+
+			 0x408, // start_of_system_messages
+			 0x408, // start of directions
+
+			 0,      // start_of_characters;
+			 0x3f31, // start_of_image_data;
+			 0,      // image_address_offset
+			 40,     // number_of_pictures;
+			 C64A,   // palette
+			 99,     // picture_format_version;
+			 0),
 	GameInfo("Questprobe 1: The Hulk",
-		HULK,
-		NO_TYPE,                  // type
-		ENGLISH,                  // subtype
-		FOUR_LETTER_UNCOMPRESSED, // dictionary type
-
-		54,  // Number of items
-		261, // Number of actions
-		128, // Number of words
-		20,  // Number of rooms
-		10,  // Max carried items
-		4,   // Word length
-		99,  // Number of messages
-
-		128, // number_of_verbs
-		129, // number_of_nouns;
-
-		0x4bf4,      // header
-		HULK_HEADER, // header style
-
-		0x270c, // room images
-		0,      // item flags
-		0x26c8, // item images
-
-		0x6087, // actions
-		HULK_ACTIONS,
-		0x4cc4,  // dictionary
-		0x51cd,  // start_of_room_descriptions;
-		0x7111,  // start_of_room_connections;
-		0x575e,  // start_of_messages;
-		FOLLOWS, // start_of_item_descriptions;
-		0x5f3d,  // start_of_item_locations;
-
-		0x2553, // start_of_system_messages
-		0x28f7, // start of directions
-
-		0x281b, // start_of_characters;
-		0x2782, // start_of_image_data
-		0,      // image_address_offset
-		43,     // number_of_pictures;
-		ZXOPT,  // palette
-		0,      // picture_format_version;
-		0),
-	GameInfo("Questprobe 1: The Hulk C64", HULK_C64,
-		NO_TYPE,                  // type
-		ENGLISH,                  // subtype
-		FOUR_LETTER_UNCOMPRESSED, // dictionary type
-
-		54,  // Number of items
-		261, // Number of actions
-		128, // Number of words
-		20,  // Number of rooms
-		10,  // Max carried items
-		4,   // Word length
-		99,  // Number of messages
-
-		128, // number_of_verbs
-		129, // number_of_nouns;
-
-		0x7867,      // header
-		HULK_HEADER, // header style
-
-		0x2280, // room images
-		0,      // item flags
-		0x22ba, // item images
-
-		0x8c47, // actions
-		HULK_ACTIONS,
-		0x7884,  // dictionary
-		0x7d8d,  // start_of_room_descriptions;
-		0x9CD1,  // start_of_room_connections;
-		0x831E,  // start_of_messages;
-		FOLLOWS, // start_of_item_descriptions;
-		0x8AFD,  // start_of_item_locations;
-
-		// These are spread out all over the code
-		0,      // start_of_system_messages
-		0xae25, // start of directions
-
-		0x0d01, // start_of_characters;
-		0x2701, // start_of_image_data
-		0,      // image_address_offset
-		43,     // number_of_pictures;
-		C64B,   // palette
-		0,      // picture_format_version;
-		0),
-	GameInfo("Adventureland",
-		ADVENTURELAND,
-		NO_TYPE,                   // type
-		ENGLISH,                   // subtype
-		THREE_LETTER_UNCOMPRESSED, // dictionary type
-
-		65,  // Number of items
-		181, // Number of actions
-		69,  // Number of words
-		33,  // Number of rooms
-		6,   // Max carried items
-		3,   // Word length
-		75,  // Number of messages
-
-		70, // number_of_verbs
-		69, // number_of_nouns;
-
-		0x2473, // header
-		EARLY,  // header style
-
-		0x3ebe,  // room images
-		FOLLOWS, // item flags
-		0x3f1f,  // item images
-		0x3f5e,  // actions
-		UNCOMPRESSED,
-		0x4c10,  // dictionary
-		0x4e40,  // start_of_room_descriptions;
-		0x4abe,  // start_of_room_connections;
-		0x52c3,  // start_of_messages;
-		FOLLOWS, // start_of_item_descriptions;
-		0x4b8a,  // start_of_item_locations;
-
-		0x24eb, // start_of_system_messages
-		0x285e, // start of directions
-
-		0x631e,  // start_of_characters;
-		FOLLOWS, // start_of_image_data
-		-0x3fe5, // image_address_offset
-		41,      // number_of_pictures;
-		ZXOPT,   // palette
-		1,       // picture_format_version;
-		0),
-	GameInfo("Adventureland C64",
-		ADVENTURELAND_C64,
-		NO_TYPE,                             // type
-		static_cast<Subtype>(ENGLISH | C64), // subtype
-		THREE_LETTER_UNCOMPRESSED,           // dictionary type
-
-		62,  // Number of items
-		170, // Number of actions
-		69,  // Number of words
-		33,  // Number of rooms
-		6,   // Max carried items
-		3,   // Word length
-		75,  // Number of messages
-
-		70, // number_of_verbs
-		69, // number_of_nouns;
-
-		0x4146, // header
-		EARLY,  // header style
-
-		0x6364, // room images
-		0x85a7, // item flags
-		0x63c5, // item images
-		0x4160, // actions
-		UNCOMPRESSED,
-		0x4c10,  // dictionary
-		0x4e40,  // start_of_room_descriptions;
-		FOLLOWS, // start_of_room_connections;
-		FOLLOWS, // start_of_messages;
-		FOLLOWS, // start_of_item_descriptions;
-		0x6404,  // start_of_item_locations;
-
-		0x188, // start_of_system_messages
-		0x188, // start of directions
-
-		0x6482,  // start_of_characters;
-		0x6c82,  // start_of_image_data
-		-0x1102, // image_address_offset
-		41,      // number_of_pictures;
-		C64B,    // palette
-		1,       // picture_format_version;
-		0),
-	GameInfo("Secret Mission",
-		SECRET_MISSION,
-		SECRET_MISSION_VARIANT,    // type
-		ENGLISH,                   // subtype
-		THREE_LETTER_UNCOMPRESSED, // dictionary type
-
-		53,  // Number of items
-		164, // Number of actions
-		64,  // Number of words
-		23,  // Number of rooms
-		7,   // Max carried items
-		3,   // Word length
-		81,  // Number of messages
-
-		65, // number_of_verbs
-		65, // number_of_nouns;
-
-		0x2473,  // header
-		EARLY,   // header style
-		0x3f26,  // room images
-		FOLLOWS, // item flags
-		0x3f70,  // item images
-		0x3fa2,  // actions
-		UNCOMPRESSED,
-		0x4af0,  // dictionary
-		0x4cf8,  // start_of_room_descriptions;
-		0x49f2,  // start_of_room_connections;
-		0x4edf,  // start_of_messages;
-		FOLLOWS, // start_of_item_descriptions;
-		0x4a82,  // start_of_item_locations;
-
-		0x24eb, // start_of_system_messages
-		0x285e, // start of directions
-
-		0x625d,  // start_of_characters;
-		FOLLOWS, // start_of_image_data
-		-0x3fe5, // image_address_offset
-		44,      // number_of_pictures;
-		ZXOPT,   // palette
-		1,       // picture_format_version;
-		0),
-	GameInfo("Secret Mission C64",
-		SECRET_MISSION_C64,
-		SECRET_MISSION_VARIANT,              // type
-		static_cast<Subtype>(ENGLISH | C64), // subtype
-		THREE_LETTER_UNCOMPRESSED,           // dictionary type
-
-		49,  // Number of items
-		154, // Number of actions
-		62,  // Number of words
-		23,  // Number of rooms
-		7,   // Max carried items
-		3,   // Word length
-		81,  // Number of messages
-
-		60, // number_of_verbs
-		62, // number_of_nouns;
-
-		0x4572,  // header
-		EARLY,   // header style
-		0x458c,  // room images
-		0x6721,  // item flags
-		FOLLOWS, // item images
-		0x45a4,  // actions
-		UNCOMPRESSED,
-		0x4f54,  // dictionary
-		0x5140,  // start_of_room_descriptions;
-		FOLLOWS, // start_of_room_connections;
-		FOLLOWS, // start_of_messages;
-		FOLLOWS, // start_of_item_descriptions;
-		0x6785,  // start_of_item_locations;
-
-		0x2502, // start_of_system_messages
-		0x2502, // start of directions
-
-		0x681b,  // start_of_characters;
-		0x701b,  // start_of_image_data
-		-0x1CD0, // image_address_offset
-		44,      // number_of_pictures;
-		C64B,    // palette
-		1,       // picture_format_version;
-		0),
-	GameInfo("The Sorcerer of Claymorgue Castle",
-		CLAYMORGUE,
-		NO_TYPE,                  // type
-		ENGLISH,                  // subtype
-		FIVE_LETTER_UNCOMPRESSED, // dictionary type
-
-		75,  // Number of items
-		267, // Number of actions
-		109, // Number of words
-		32,  // Number of rooms
-		10,  // Max carried items
-		5,   // Word length
-		79,  // Number of messages
-
-		110, // number_of_verbs
-		108, // number_of_nouns;
-
-		0x246c, // header
-		EARLY,  // header style
-
-		0x3bf6,  // room images
-		FOLLOWS, // item flags
-		FOLLOWS, // item images
-		FOLLOWS, // actions
-		UNCOMPRESSED,
-		0x4ecf,  // dictionary
-		0x53f7,  // start_of_room_descriptions;
-		0x4d6f,  // start_of_room_connections;
-		0x5605,  // start_of_messages;
-		FOLLOWS, // start_of_item_descriptions;
-		0x4e35,  // start_of_item_locations;
-
-		0x24e2, // start_of_system_messages
-		0x2877, // start of directions
-
-		0x6007,  // start_of_characters;
-		0x6807,  // start_of_image_data
-		-0x3fe5, // image_address_offset
-		37,      // number_of_pictures;
-		ZXOPT,   // palette
-		1,       // picture_format_version;
-		0),
-	GameInfo("The Sorcerer of Claymorgue Castle C64",
-		CLAYMORGUE_C64,
-		NO_TYPE,                             // type
-		static_cast<Subtype>(ENGLISH | C64), // subtype
-		FIVE_LETTER_UNCOMPRESSED,            // dictionary type
-
-		75,  // Number of items
-		265, // Number of actions
-		108, // Number of words
-		32,  // Number of rooms
-		10,  // Max carried items
-		5,   // Word length
-		79,  // Number of messages
-
-		110, // number_of_verbs
-		108, // number_of_nouns;
-
-		0x47d6, // header
-		EARLY,  // header style
-
-		0x471f,  // room images
-		FOLLOWS, // item flags
-		FOLLOWS, // item images
-		0x47f0,  // actions
-		UNCOMPRESSED,
-		0x5891,  // dictionary
-		FOLLOWS, // start_of_room_descriptions;
-		FOLLOWS, // start_of_room_connections;
-		FOLLOWS, // start_of_messages;
-		FOLLOWS, // start_of_item_descriptions;
-		FOLLOWS, // start_of_item_locations;
-
-		0xa2c, // start_of_system_messages
-		0xa2c, // start of directions
-
-		0x6b1a, // start_of_characters;
-		0x731a, // start_of_image_data
-		0x6b1a, // image_address_offset
-		44,     // number_of_pictures;
-		C64B,   // palette
-		1,      // picture_format_version;
-		0),
-	GameInfo("Questprobe 2: Spiderman",
-		SPIDERMAN,
-		NO_TYPE,                  // type
-		ENGLISH,                  // subtype
-		FOUR_LETTER_UNCOMPRESSED, // dictionary type
-
-		72,  // Number of items
-		257, // Number of actions
-		124, // Number of words
-		40,  // Number of rooms
-		12,  // Max carried items
-		4,   // Word length
-		99,  // Number of messages
-
-		125, // number_of_verbs
-		125, // number_of_nouns;
-
-		0x246b, // header
-		EARLY,  // header style
-
-		0x3dd1,  // room images
-		FOLLOWS, // item flags
-		FOLLOWS, // item images
-
-		FOLLOWS, // actions
-		UNCOMPRESSED,
-		0x5036,  // dictionary
-		0x5518,  // start_of_room_descriptions;
-		0x4eac,  // start_of_room_connections;
-		0x575e,  // start_of_messages;
-		FOLLOWS, // start_of_item_descriptions;
-		0x4fa2,  // start_of_item_locations;
-
-		0x2553, // start_of_system_messages
-		0x28f7, // start of directions
-
-		0x6296,  // start_of_characters;
-		0x6a96,  // start_of_image_data
-		-0x3fe5, // image_address_offset
-		41,      // number_of_pictures;
-		ZXOPT,   // palette
-		2,       // picture_format_version;
-		0),
-	GameInfo("Questprobe 2: Spiderman C64",
-		SPIDERMAN_C64,
-		NO_TYPE,                             // type
-		static_cast<Subtype>(ENGLISH | C64), // subtype
-		FOUR_LETTER_UNCOMPRESSED,            // dictionary type
-
-		72,  // Number of items
-		245, // Number of actions
-		124, // Number of words
-		40,  // Number of rooms
-		12,  // Max carried items
-		4,   // Word length
-		98,  // Number of messages
-
-		118, // number_of_verbs
-		124, // number_of_nouns;
-
-		0x4baf, // header
-		EARLY,  // header style
-
-		0x4bc9,  // room images
-		0x70da,  // item flags
-		FOLLOWS, // item images
-
-		0x4bf2, // actions
-		UNCOMPRESSED,
-		0x5b52,  // dictionary
-		0x600c,  // start_of_room_descriptions;
-		FOLLOWS, // start_of_room_connections;
-		FOLLOWS, // start_of_messages;
-		0x6b9b,  // start_of_item_descriptions;
-		FOLLOWS, // start_of_item_locations;
-
-		0x0a7b, // start_of_system_messages
-		0x0a7b, // start of directions
-
-		0x716c, // start_of_characters;
-		0x796c, // start_of_image_data
-		0x716c, // image_address_offset
-		41,     // number_of_pictures;
-		C64B,   // palette
-		2,      // picture_format_version;
-		0),
-	GameInfo("Savage Island part I",
-		SAVAGE_ISLAND,
-		SAVAGE_ISLAND_VARIANT,    // type
-		ENGLISH,                  // subtype
-		FOUR_LETTER_UNCOMPRESSED, // dictionary type
-
-		58,  // Number of items
-		259, // Number of actions
-		84,  // Number of words
-		34,  // Number of rooms
-		6,   // Max carried items
-		4,   // Word length
-		99,  // Number of messages
-
-		82, // number_of_verbs
-		84, // number_of_nouns;
-
-		0x236d,  // header
-		LATE,    // header style
-		0x390c,  // room images
-		FOLLOWS, // item flags
-		FOLLOWS, // item images
-		0x39a6,  // actions
-		COMPRESSED,
-		0x4484,  // dictionary
-		0x47c7,  // start_of_room_descriptions;
-		FOLLOWS, // start_of_room_connections;
-		0x4b91,  // start_of_messages;
-		FOLLOWS, // start_of_item_descriptions;
-		FOLLOWS, // start_of_item_locations;
-
-		0x2423, // start_of_system_messages
-		0x25f3, // start of directions
-
-		0x570f,  // start_of_characters;
-		FOLLOWS, // start_of_image_data
-		0x600f,  // image_address_offset
-		37,      // number_of_pictures;
-		ZXOPT,   // palette
-		3,       // picture_format_version;
-		0),
-	GameInfo("Savage Island part I (C64)",
-		SAVAGE_ISLAND_C64,
-		SAVAGE_ISLAND_VARIANT,               // type
-		static_cast<Subtype>(ENGLISH | C64), // subtype
-		FOUR_LETTER_UNCOMPRESSED,            // dictionary type
-
-		58,  // Number of items
-		259, // Number of actions
-		84,  // Number of words
-		34,  // Number of rooms
-		6,   // Max carried items
-		4,   // Word length
-		99,  // Number of messages
-
-		85, // number_of_verbs
-		84, // number_of_nouns;
-
-		0x46dc,  // header
-		EARLY,   // header style
-		0x4645,  // room images
-		FOLLOWS, // item flags
-		FOLLOWS, // item images
-		0x46f6,  // actions
-		COMPRESSED,
-		0x51d6,  // dictionary
-		0x5528,  // start_of_room_descriptions;
-		FOLLOWS, // start_of_room_connections;
-		FOLLOWS, // start_of_messages;
-				 //        0x58f6, // start_of_messages;
-		FOLLOWS, // start_of_item_descriptions;
-		FOLLOWS, // start_of_item_locations;
-
-		0x0a5f, // start_of_system_messages
-		0x0a5f, // start of directions
-
-		0x6A02, // start_of_characters;
-		0x7202, // start_of_image_data
-		0x7302, // image_address_offset
-		37,     // number_of_pictures;
-		C64B,   // palette
-		3,      // picture_format_version;
-		0),
-	GameInfo("Savage Island part II",
-		SAVAGE_ISLAND2,
-		NO_TYPE,                  // type
-		ENGLISH,                  // subtype
-		FOUR_LETTER_UNCOMPRESSED, // dictionary type
-
-		48,  // Number of items
-		241, // Number of actions
-		79,  // Number of words
-		30,  // Number of rooms
-		6,   // Max carried items
-		4,   // Word length
-		95,  // Number of messages
-
-		74, // number_of_verbs
-		79, // number_of_nouns;
-
-		0x236d,  // header
-		LATE,    // header style
-		0x390c,  // room images
-		FOLLOWS, // item flags
-		FOLLOWS, // item images
-		0x398e,  // actions
-		COMPRESSED,
-		0x43f0,  // dictionary
-		0x46ed,  // start_of_room_descriptions;
-		FOLLOWS, // start_of_room_connections;
-		FOLLOWS, // start_of_messages;
-		FOLLOWS, // start_of_item_descriptions;
-		FOLLOWS, // start_of_item_locations;
-
-		0x2423, // start_of_system_messages
-		0x25f3, // start of directions
-
-		0x57d0,  // start_of_characters;
-		FOLLOWS, // start_of_image_data
-		0x60d0,  // image_address_offset
-		21,      // number_of_pictures;
-		ZXOPT,   // palette
-		3,       // picture_format_version;
-		0),
-	GameInfo("Savage Island part II (C64)",
-		SAVAGE_ISLAND2_C64,
-		NO_TYPE,                             // type
-		static_cast<Subtype>(ENGLISH | C64), // subtype
-		FOUR_LETTER_UNCOMPRESSED,            // dictionary type
-
-		48,  // Number of items
-		241, // Number of actions
-		78,  // Number of words
-		30,  // Number of rooms
-		6,   // Max carried items
-		4,   // Word length
-		94,  // Number of messages
-
-		79, // number_of_verbs
-		79, // number_of_nouns;
-
-		0x4654,  // header
-		EARLY,   // header style
-		0x6310,  // room images
-		FOLLOWS, // item flags
-		FOLLOWS, // item images
-		0x466e,  // actions
-		COMPRESSED,
-		0x50d2,  // dictionary
-		0x53e8,  // start_of_room_descriptions;
-		FOLLOWS, // start_of_room_connections;
-		FOLLOWS, // start_of_messages;
-		FOLLOWS, // start_of_item_descriptions;
-		FOLLOWS, // start_of_item_locations;
-
-		0x0a50, // start_of_system_messages
-		0x0a50, // start of directions
-
-		0x6A02, // start_of_characters;
-		0x7202, // start_of_image_data
-		0x7302, // image_address_offset
-		21,     // number_of_pictures;
-		C64B,   // palette
-		3,      // picture_format_version;
-		0),
-	GameInfo("Gremlins",
-		GREMLINS,
-		GREMLINS_VARIANT,         // type
-		ENGLISH,                  // subtype
-		FOUR_LETTER_UNCOMPRESSED, // dictionary type
-
-		99,  // Number of items
-		236, // Number of actions
-		126, // Number of words
-		42,  // Number of rooms
-		6,   // Max carried items
-		4,   // Word length
-		98,  // Number of messages
-
-		115, // number_of_verbs
-		126, // number_of_nouns;
-
-		0x2370, // header
-		LATE,   // header style
-
-		0x3a09,  // room images
-		FOLLOWS, // item flags
-		FOLLOWS, // item images
-
-		0x3afe,     // actions
-		COMPRESSED, // actions_style;
-		0x45e5,     // dictionary
-		FOLLOWS,    // start_of_room_descriptions;
-		FOLLOWS,    // start_of_room_connections;
-		FOLLOWS,    // start_of_messages;
-		FOLLOWS,    // start_of_item_descriptions;
-		FOLLOWS,    // start_of_item_locations;
-		0x2426,     // start_of_system_messages
-		0x25f6,     // start of directions
-
-		0x5be1, // start_of_characters;
-		0x63e1, // start_of_image_data
-		0x64e1, // image_address_offset
-		78,     // number_of_pictures;
-		ZXOPT,  // palette
-		3,      // picture_format_version;
-		0),
-	GameInfo("Gremlins (alternative)",
-		GREMLINS_ALT,
-		GREMLINS_VARIANT,         // type
-		ENGLISH,                  // subtype
-		FOUR_LETTER_UNCOMPRESSED, // dictionary type
-
-		99,  // Number of items
-		236, // Number of actions
-		126, // Number of words
-		42,  // Number of rooms
-		6,   // Max carried items
-		4,   // Word length
-		98,  // Number of messages
-
-		115, // number_of_verbs
-		126, // number_of_nouns;
-
-		0x2378, // header
-		LATE,   // header style
-
-		0x3a0d,  // room images
-		FOLLOWS, // item flags
-		FOLLOWS, // item images
-
-		0x3b02,     // actions
-		COMPRESSED, // actions_style;
-		0x45e5,     // dictionary
-		FOLLOWS,    // start_of_room_descriptions;
-		FOLLOWS,    // start_of_room_connections;
-		FOLLOWS,    // start_of_messages;
-		FOLLOWS,    // start_of_item_descriptions;
-		FOLLOWS,    // start_of_item_locations;
-		0x242e,     // start_of_system_messages
-		0x25FE,     // start of directions
-
-		0x5bdd, // start_of_characters;
-		0x63dd, // start_of_image_data
-		0x64dd, // image_address_offset
-		78,     // number_of_pictures;
-		ZXOPT,  // palette
-		3,      // picture_format_version;
-		0),
-	GameInfo("Gremlins (German)",
-		GREMLINS_GERMAN,
-		GREMLINS_VARIANT, // type
-		LOCALIZED,        // subtype
-		GERMAN,           // dictionary type
-
-		99,  // Number of items
-		236, // Number of actions
-		126, // Number of words
-		42,  // Number of rooms
-		6,   // Max carried items
-		5,   // Word length
-		98,  // Number of messages
-
-		115, // number_of_verbs
-		126, // number_of_nouns
-
-		0x237d, // header
-		LATE,   // header style
-
-		0x3a07,  // room images
-		FOLLOWS, // item flags
-		FOLLOWS, // item images
-
-		0x3afc, // actions
-		COMPRESSED,
-		0x45d9,  // dictionary
-		FOLLOWS, // start_of_room_descriptions;
-		FOLLOWS, // start_of_room_connections;
-		FOLLOWS, // start_of_messages;
-		FOLLOWS, // start_of_item_descriptions;
-		FOLLOWS, // start_of_item_locations;
-
-		0x23de, // start_of_system_messages
-		0x2623, // start of directions
-
-		0x643e, // start_of_characters
-		0x6c3e, // start_of_image_data
-		0x6d3e, // image_address_offset
-		72,     // number_of_pictures;
-		ZX,     // palette
-		3,      // picture_format_version;
-		0),
-	GameInfo("Gremlins C64",
-		GREMLINS_C64,
-		GREMLINS_VARIANT,                    // type
-		static_cast<Subtype>(ENGLISH | C64), // subtype
-		FOUR_LETTER_UNCOMPRESSED,            // dictionary type
-
-		99,  // Number of items
-		243, // Number of actions
-		126, // Number of words
-		42,  // Number of rooms
-		6,   // Max carried items
-		4,   // Word length
-		99,  // Number of messages
-
-		115, // number_of_verbs
-		126, // number_of_nouns;
-
-		0x4584,              // header
-		GREMLINS_C64_HEADER, // header style
-
-		0x465e,  // room images
-		FOLLOWS, // item flags
-		FOLLOWS, // item images
-
-		0x4751,     // actions
-		COMPRESSED, // actions_style;
-		0x527f,     // dictionary
-		FOLLOWS,    // start_of_room_descriptions;
-		FOLLOWS,    // start_of_room_connections;
-		FOLLOWS,    // start_of_messages;
-		FOLLOWS,    // start_of_item_descriptions;
-		0x4596,     // start_of_item_locations;
-		0x0a5e,     // start_of_system_messages
-		0x0a5e,     // start of directions
-
-		0x6a01, // start_of_characters;
-		0x7201, // start_of_image_data
-		0x7301, // image_address_offset
-		91,     // number_of_pictures;
-		C64B,   // palette
-		3,      // picture_format_version;
-		0),
-	GameInfo("Gremlins (German, C64)",
-		GREMLINS_GERMAN_C64,
-		GREMLINS_VARIANT,                      // type
-		static_cast<Subtype>(LOCALIZED | C64), // subtype
-		FIVE_LETTER_COMPRESSED,                // dictionary type
-
-		99,  // Number of items
-		243, // Number of actions
-		125, // Number of words
-		42,  // Number of rooms
-		6,   // Max carried items
-		5,   // Word length
-		98,  // Number of messages
-
-		125, // number_of_verbs
-		124, // number_of_nouns
-
-		0x4bb2,              // header
-		GREMLINS_C64_HEADER, // header style
-
-		0x4c8c,  // room images
-		FOLLOWS, // item flags
-		FOLLOWS, // item images
-
-		0x4d81, // actions
-		COMPRESSED,
-		0x585e,  // dictionary
-		FOLLOWS, // start_of_room_descriptions;
-		FOLLOWS, // start_of_room_connections;
-		FOLLOWS, // start_of_messages;
-		FOLLOWS, // start_of_item_descriptions;
-		0x4bc4,  // start_of_item_locations;
-
-		0x1325, // start_of_system_messages
-		0x1325, // start of directions
-
-		0x76c5, // start_of_characters
-		0x7cfd, // start_of_image_data
-		0x7db3, // image_address_offset
-		91,     // number_of_pictures;
-		C64B,   // palette
-		3,      // picture_format_version;
-		0),
-	GameInfo("Gremlins (Spanish)",
-		GREMLINS_SPANISH,
-		GREMLINS_VARIANT, // type
-		LOCALIZED,        // subtype
-		SPANISH,          // dictionary type
-
-		99,  // Number of items
-		236, // Number of actions
-		126, // Number of words
-		42,  // Number of rooms
-		6,   // Max carried items
-		4,   // Word length
-		98,  // Number of messages
-
-		115, // number_of_verbs
-		126, // number_of_nouns
-
-		0x23c5, // header
-		LATE,   // header style
-
-		0x3993,  // room images
-		FOLLOWS, // item flags
-		FOLLOWS, // item images
-
-		0x3a88, // actions
-		COMPRESSED,
-		0x455f,  // dictionary
-		FOLLOWS, // start_of_room_descriptions;
-		FOLLOWS, // start_of_room_connections;
-		FOLLOWS, // start_of_messages;
-		FOLLOWS, // start_of_item_descriptions;
-		FOLLOWS, // start_of_item_locations;
-
-		0x2426, // start_of_system_messages
-		0x25c4, // start of directions
-
-		0x6171, // start_of_characters
-		0x6971, // start_of_image_data
-		0x6A71, // image_address_offset
-		74,     // number_of_pictures;
-		ZXOPT,  // palette
-		3,      // picture_format_version;
-		0),
-	GameInfo("Supergran",
-		SUPERGRAN,
-		NO_TYPE,                  // type
-		ENGLISH,                  // subtype
-		FOUR_LETTER_UNCOMPRESSED, // dictionary type
-
-		85,  // Number of items
-		204, // Number of actions
-		105, // Number of words
-		39,  // Number of rooms
-		6,   // Max carried items
-		4,   // Word length
-		99,  // Number of messages
-
-		101, // number_of_verbs
-		106, // number_of_nouns;
-
-		0x236d,  // header
-		LATE,    // header style
-		0x38c8,  // room images
-		FOLLOWS, // item flags
-		FOLLOWS, // item images
-		0x399e,  // actions
-		COMPRESSED,
-		0x42fd,  // dictionary
-		0x4708,  // start_of_room_descriptions;
-		FOLLOWS, // start_of_room_connections;
-		FOLLOWS, // start_of_messages;
-		FOLLOWS, // start_of_item_descriptions;
-		FOLLOWS, // start_of_item_locations;
-
-		0x2423, // start_of_system_messages
-		0x25f3, // start of directions
-
-		0x5a4e,  // start_of_characters;
-		FOLLOWS, // start_of_image_data
-		0x634e,  // image_address_offset
-		47,      // number_of_pictures;
-		ZXOPT,   // palette
-		3,       // picture_format_version;
-		0),
-	GameInfo("Supergran C64",
-		SUPERGRAN_C64,
-		NO_TYPE,                             // type
-		static_cast<Subtype>(ENGLISH | C64), // subtype
-		FOUR_LETTER_UNCOMPRESSED,            // dictionary type
-
-		85,  // Number of items
-		204, // Number of actions
-		105, // Number of words
-		39,  // Number of rooms
-		6,   // Max carried items
-		4,   // Word length
-		99,  // Number of messages
-
-		101, // number_of_verbs
-		105, // number_of_nouns;
-
-		0x4624,               // header
-		SUPERGRAN_C64_HEADER, // header style
-		0x4636,               // room images
-		FOLLOWS,              // item flags
-		FOLLOWS,              // item images
-		0x47b5,               // actions
-		COMPRESSED,
-		0x5119,  // dictionary
-		0x5524,  // start_of_room_descriptions;
-		FOLLOWS, // start_of_room_connections;
-		FOLLOWS, // start_of_messages;
-		FOLLOWS, // start_of_item_descriptions;
-		0x470a,  // start_of_item_locations;
-
-		0x0a53, // start_of_system_messages
-		0x0a53, // start of directions
-
-		0x6a02,  // start_of_characters;
-		FOLLOWS, // start_of_image_data
-		0x7302,  // image_address_offset
-		49,      // number_of_pictures;
-		C64B,    // palette
-		3,       // picture_format_version;
-		0),
-	GameInfo("Robin of Sherwood",
-		ROBIN_OF_SHERWOOD,
-		SHERWOOD_VARIANT,       // type
-		ENGLISH,                // subtype
-		FOUR_LETTER_COMPRESSED, // dictionary type
-
-		87,  // Number of items
-		295, // Number of actions
-		114, // Number of words
-		93,  // Number of rooms
-		10,  // Max carried items
-		4,   // Word length
-		98,  // Number of messages
-
-		115, // number_of_verbs
-		109, // number_of_nouns;
-
-		0x3b5a, // header
-		LATE,   // header style
-
-		0,       // 0x3d99 room images, zero because it needs custom handling
-		0x3db8,  // item flags
-		FOLLOWS, // item images
-
-		0x409b, // actions
-		COMPRESSED,
-		0x4dc3, // dictionary
-		0,      // 0x9b53 start_of_room_descriptions, zero because of custom handling
-		0x3e67, // start_of_room_connections
-		0x5147, // start_of_messages
-		0x5d65, // start_of_item_descriptions
-		0x4d6b, // start_of_item_locations
-
-		0x250b, // start_of_system_messages
-		0x26b5, // start of directions
-
-		0x614f, // start_of_characters
-		0x66bf, // start_of_image_data
-		0x6765, // image_address_offset
-		83,     // number_of_pictures
-		ZXOPT,  // palette
-		4,      // picture_format_version
-		0),
-	GameInfo("Robin of Sherwood C64",
-		ROBIN_OF_SHERWOOD_C64,
-		SHERWOOD_VARIANT,                    // type
-		static_cast<Subtype>(ENGLISH | C64), // subtype
-		FOUR_LETTER_COMPRESSED,              // dictionary type
-
-		87,  // Number of items
-		296, // Number of actions
-		114, // Number of words
-		93,  // Number of rooms
-		10,  // Max carried items
-		4,   // Word length
-		98,  // Number of messages
-
-		115, // number_of_verbs
-		109, // number_of_nouns;
-
-		0x1f85,           // header
-		ROBIN_C64_HEADER, // header style
-
-		0,       // room images, zero because it needs custom handling
-		0x201c,  // item flags
-		FOLLOWS, // item images
-
-		0x252b, // actions
-		COMPRESSED,
-		0x320a, // dictionary
-		0,      // 0x9b53 start_of_room_descriptions, zero because of custom handling
-		0x20cc, // start_of_room_connections
-		0x358e, // start_of_messages
-		0x4215, // start_of_item_descriptions
-		0x1fa5, // start_of_item_locations
-
-		0x428, // start_of_system_messages
-		0x428, // start of directions
-
-		0x45ff, // start_of_characters
-		0x4b6f, // start_of_image_data
-		0x4c23, // image_address_offset
-		90,     // number_of_pictures
-		C64B,   // palette
-		4,      // picture_format_version
-		0),
-	GameInfo("Seas of Blood",
-		SEAS_OF_BLOOD,
-		SEAS_OF_BLOOD_VARIANT,  // type
-		ENGLISH,                // subtype
-		FOUR_LETTER_COMPRESSED, // dictionary type
-
-		125, // Number of items
-		344, // Number of actions
-		134, // Number of words
-		83,  // Number of rooms
-		10,  // Max carried items
-		4,   // Word length
-		99,  // Number of messages
-
-		69,  // number_of_verbs
-		134, // number_of_nouns;
-
-		0x494d, // header
-		LATE,   // header style
-
-		0,       // no room images
-		0x4961,  // item flags
-		FOLLOWS, // item images
-
-		FOLLOWS, // actions
-		COMPRESSED,
-		0x591b, // dictionary
-		0x67cb, // start_of_room_descriptions;
-		0x5c4b, // start_of_room_connections;
-		0x5ebb, // start_of_messages;
-		0x6ce0, // start_of_item_descriptions;
-		0x5e3d, // start_of_item_locations;
-
-		0x24ed, // start_of_system_messages
-		0x26fc, // start of directions
-
-		0x7389, // start_of_characters;
-		0x7a89, // start_of_image_data;
-		0x7b9f, // image_address_offset
-		139,    // number_of_pictures;
-		ZXOPT,  // palette
-		4,      // picture_format_version;
-		0),
-	GameInfo("Seas of Blood C64",
-		SEAS_OF_BLOOD_C64,
-		SEAS_OF_BLOOD_VARIANT,               // type
-		static_cast<Subtype>(ENGLISH | C64), // subtype
-		FOUR_LETTER_COMPRESSED,              // dictionary type
-
-		125, // Number of items
-		347, // Number of actions
-		134, // Number of words
-		82,  // Number of rooms
-		10,  // Max carried items
-		4,   // Word length
-		99,  // Number of messages
-
-		69,  // number_of_verbs
-		134, // number_of_nouns;
-
-		0x527d,                   // header
-		SEAS_OF_BLOOD_C64_HEADER, // header style
-
-		0,       // no room images
-		0x5a73,  // item flags
-		FOLLOWS, // item images
-
-		0x5b69, // actions
-		COMPRESSED,
-		0x6a2d, // dictionary
-		0x78dd, // start_of_room_descriptions;
-		0x6d5d, // start_of_room_connections;
-		0x6fcd, // start_of_messages;
-		0x7df2, // start_of_item_descriptions;
-		0x6f4f, // start_of_item_locations;
-
-		0x0b9d, // start_of_system_messages
-		0x0b9d, // start of directions
-
-		0x84a5, // start_of_characters;
-		0x8ba5, // start_of_image_data;
-		0x8CBB, // image_address_offset
-		139,    // number_of_pictures;
-		C64B,   // palette
-		4,      // picture_format_version;
-		0)
-};
-
+			 HULK,
+			 NO_TYPE,                  // type
+			 ENGLISH,                  // subtype
+			 FOUR_LETTER_UNCOMPRESSED, // dictionary type
+
+			 54,  // Number of items
+			 261, // Number of actions
+			 128, // Number of words
+			 20,  // Number of rooms
+			 10,  // Max carried items
+			 4,   // Word length
+			 99,  // Number of messages
+
+			 128, // number_of_verbs
+			 129, // number_of_nouns;
+
+			 0x4bf4,      // header
+			 HULK_HEADER, // header style
+
+			 0x270c, // room images
+			 0,      // item flags
+			 0x26c8, // item images
+
+			 0x6087, // actions
+			 HULK_ACTIONS,
+			 0x4cc4,  // dictionary
+			 0x51cd,  // start_of_room_descriptions;
+			 0x7111,  // start_of_room_connections;
+			 0x575e,  // start_of_messages;
+			 FOLLOWS, // start_of_item_descriptions;
+			 0x5f3d,  // start_of_item_locations;
+
+			 0x2553, // start_of_system_messages
+			 0x28f7, // start of directions
+
+			 0x281b, // start_of_characters;
+			 0x2782, // start_of_image_data
+			 0,      // image_address_offset
+			 43,     // number_of_pictures;
+			 ZXOPT,  // palette
+			 0,      // picture_format_version;
+			 0)};


Commit: b20b095e848e9e528dea5c46f18f39e7f74664f0
    https://github.com/scummvm/scummvm/commit/b20b095e848e9e528dea5c46f18f39e7f74664f0
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Update game loading to use new game list

Changed paths:
    engines/glk/scott/c64_checksums.cpp
    engines/glk/scott/load_game.cpp


diff --git a/engines/glk/scott/c64_checksums.cpp b/engines/glk/scott/c64_checksums.cpp
index bcbe0dedd39..82dc84dd42d 100644
--- a/engines/glk/scott/c64_checksums.cpp
+++ b/engines/glk/scott/c64_checksums.cpp
@@ -240,7 +240,7 @@ int detectC64(uint8_t **sf, size_t *extent) {
 	} else if (g_C64Registry[index]._id == FEASIBILITY_C64) {
 		return mysteriousMenu2(sf, extent, index);
 	}
-	return decrunchC64(sf, extent, g_C64Registry[index]);
+	return UNKNOWN_GAME;
 }
 
 size_t copyData(size_t dest, size_t source, uint8_t** data, size_t dataSize, size_t bytesToMove) {
@@ -297,9 +297,8 @@ int decrunchC64(uint8_t **sf, size_t *extent, C64Rec record) {
 	}
 
 	for (int i = 0; i < NUMGAMES; i++) {
-		if (g_games[i]._gameID == record._id) {
-			delete _G(_game);
-			_G(_game) = &g_games[i];
+		if (_G(_games)[i]._gameID == record._id) {
+			_G(_game) = &_G(_games)[i];
 			break;
 		}
 	}
diff --git a/engines/glk/scott/load_game.cpp b/engines/glk/scott/load_game.cpp
index 30291354f78..38d4be759a5 100644
--- a/engines/glk/scott/load_game.cpp
+++ b/engines/glk/scott/load_game.cpp
@@ -58,9 +58,8 @@ void loadZXSpectrum(Common::SeekableReadStream *f, Common::String md5) {
 		return;
 
 	int index = _G(_md5Index)[md5];
-	if (tryLoading(g_games[index], offset, 0)) {
-		delete _G(_game);
-		_G(_game) = &g_games[index];
+	if (tryLoading(_G(_games)[index], offset, 0)) {
+		_G(_game) = &_G(_games)[index];
 	}
 }
 
@@ -70,7 +69,7 @@ void loadC64(Common::SeekableReadStream* f, Common::String md5) {
 	if (result != _G(_fileLength))
 		g_scott->fatal("File empty or read error!");
 
-	CURRENT_GAME = static_cast<GameIDType>(detectC64(&_G(_entireFile), &_G(_fileLength)));
+	_G(_fallbackGame)._gameID = static_cast<GameIDType>(detectC64(&_G(_entireFile), &_G(_fileLength)));
 }
 
 void loadGameFile(Common::SeekableReadStream *f) {
@@ -86,7 +85,7 @@ void loadGameFile(Common::SeekableReadStream *f) {
 
 	_G(_fileLength) = f->size();
 
-	_G(_game) = new GameInfo;
+	_G(_game) = &_G(_fallbackGame);
 
 	Common::String md5 = g_vm->getGameMD5();
 	const GlkDetectionEntry *p = SCOTT_GAMES;
@@ -94,11 +93,14 @@ void loadGameFile(Common::SeekableReadStream *f) {
 	while (p->_md5) {
 		if (md5.equalsC(p->_md5)) {
 			if (!scumm_stricmp(p->_extra, "")) {
-				CURRENT_GAME = SCOTTFREE;
+				_G(_fallbackGame)._gameID = SCOTTFREE;
+				break;
 			} else if (!scumm_stricmp(p->_extra, "ZXSpectrum")) {
 				loadZXSpectrum(f, md5);
+				break;
 			} else if (!scumm_stricmp(p->_extra, "C64")) {
 				loadC64(f, md5);
+				break;
 			}
 			// TODO
 			// TI99/4A Detection


Commit: 1ec46bdd30fbc12154d2b51a9ea04906a4458553
    https://github.com/scummvm/scummvm/commit/1ec46bdd30fbc12154d2b51a9ea04906a4458553
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Update license header

Changed paths:
    engines/glk/scott/c64_checksums.cpp
    engines/glk/scott/c64_checksums.h
    engines/glk/scott/command_parser.cpp
    engines/glk/scott/command_parser.h
    engines/glk/scott/decompress_text.cpp
    engines/glk/scott/decompress_text.h
    engines/glk/scott/decompress_z80.cpp
    engines/glk/scott/decompress_z80.h
    engines/glk/scott/definitions.cpp
    engines/glk/scott/definitions.h
    engines/glk/scott/detection.cpp
    engines/glk/scott/detection.h
    engines/glk/scott/detection_tables.h
    engines/glk/scott/disk_image.cpp
    engines/glk/scott/disk_image.h
    engines/glk/scott/game_info.cpp
    engines/glk/scott/game_info.h
    engines/glk/scott/game_specific.cpp
    engines/glk/scott/game_specific.h
    engines/glk/scott/games.h
    engines/glk/scott/globals.cpp
    engines/glk/scott/globals.h
    engines/glk/scott/hulk.cpp
    engines/glk/scott/hulk.h
    engines/glk/scott/layout_text.cpp
    engines/glk/scott/layout_text.h
    engines/glk/scott/line_drawing.cpp
    engines/glk/scott/line_drawing.h
    engines/glk/scott/load_game.cpp
    engines/glk/scott/load_game.h
    engines/glk/scott/resource.cpp
    engines/glk/scott/resource.h
    engines/glk/scott/restore_state.cpp
    engines/glk/scott/restore_state.h
    engines/glk/scott/ring_buffer.cpp
    engines/glk/scott/ring_buffer.h
    engines/glk/scott/saga_draw.cpp
    engines/glk/scott/saga_draw.h
    engines/glk/scott/scott.cpp
    engines/glk/scott/scott.h
    engines/glk/scott/types.h


diff --git a/engines/glk/scott/c64_checksums.cpp b/engines/glk/scott/c64_checksums.cpp
index 82dc84dd42d..eca37b6ed55 100644
--- a/engines/glk/scott/c64_checksums.cpp
+++ b/engines/glk/scott/c64_checksums.cpp
@@ -19,6 +19,17 @@
  *
  */
 
+/*
+ * Based on ScottFree interpreter version 1.14 developed by Swansea
+ * University Computer Society without disassembly of any other game
+ * drivers, only of game databases as permitted by EEC law (for purposes
+ * of compatibility).
+ *
+ * Licensed under GPLv2
+ *
+ * https://github.com/angstsmurf/spatterlight/tree/master/terps/scott
+ */
+
 #include "common/str.h"
 #include "common/scummsys.h"
 #include "glk/scott/scott.h"
diff --git a/engines/glk/scott/c64_checksums.h b/engines/glk/scott/c64_checksums.h
index d665040b1a9..c4c7cf06e72 100644
--- a/engines/glk/scott/c64_checksums.h
+++ b/engines/glk/scott/c64_checksums.h
@@ -19,6 +19,17 @@
  *
  */
 
+/*
+ * Based on ScottFree interpreter version 1.14 developed by Swansea
+ * University Computer Society without disassembly of any other game
+ * drivers, only of game databases as permitted by EEC law (for purposes
+ * of compatibility).
+ *
+ * Licensed under GPLv2
+ *
+ * https://github.com/angstsmurf/spatterlight/tree/master/terps/scott
+ */
+
 #ifndef GLK_SCOTT_C64CHECKSUMS_H
 #define GLK_SCOTT_C64CHECKSUMS_H
 
diff --git a/engines/glk/scott/command_parser.cpp b/engines/glk/scott/command_parser.cpp
index 98363cbd578..ee3d5f43b07 100644
--- a/engines/glk/scott/command_parser.cpp
+++ b/engines/glk/scott/command_parser.cpp
@@ -19,6 +19,17 @@
  *
  */
 
+/*
+ * Based on ScottFree interpreter version 1.14 developed by Swansea
+ * University Computer Society without disassembly of any other game
+ * drivers, only of game databases as permitted by EEC law (for purposes
+ * of compatibility).
+ *
+ * Licensed under GPLv2
+ *
+ * https://github.com/angstsmurf/spatterlight/tree/master/terps/scott
+ */
+
 #include "common/str.h"
 #include "glk/scott/scott.h"
 #include "glk/scott/globals.h"
diff --git a/engines/glk/scott/command_parser.h b/engines/glk/scott/command_parser.h
index e88dea732ac..d1a5b91aa53 100644
--- a/engines/glk/scott/command_parser.h
+++ b/engines/glk/scott/command_parser.h
@@ -19,6 +19,17 @@
  *
  */
 
+/*
+ * Based on ScottFree interpreter version 1.14 developed by Swansea
+ * University Computer Society without disassembly of any other game
+ * drivers, only of game databases as permitted by EEC law (for purposes
+ * of compatibility).
+ *
+ * Licensed under GPLv2
+ *
+ * https://github.com/angstsmurf/spatterlight/tree/master/terps/scott
+ */
+
 #ifndef GLK_SCOTT_PARSER_H
 #define GLK_SCOTT_PARSER_H
 
diff --git a/engines/glk/scott/decompress_text.cpp b/engines/glk/scott/decompress_text.cpp
index 9029c7edde0..4e03b5f7c63 100644
--- a/engines/glk/scott/decompress_text.cpp
+++ b/engines/glk/scott/decompress_text.cpp
@@ -19,6 +19,17 @@
  *
  */
 
+/*
+ * Based on ScottFree interpreter version 1.14 developed by Swansea
+ * University Computer Society without disassembly of any other game
+ * drivers, only of game databases as permitted by EEC law (for purposes
+ * of compatibility).
+ *
+ * Licensed under GPLv2
+ *
+ * https://github.com/angstsmurf/spatterlight/tree/master/terps/scott
+ */
+
 #include "common/str.h"
 #include "glk/scott/decompress_text.h"
 
diff --git a/engines/glk/scott/decompress_text.h b/engines/glk/scott/decompress_text.h
index da935a3de2c..697cf5bc4f5 100644
--- a/engines/glk/scott/decompress_text.h
+++ b/engines/glk/scott/decompress_text.h
@@ -19,6 +19,17 @@
  *
  */
 
+/*
+ * Based on ScottFree interpreter version 1.14 developed by Swansea
+ * University Computer Society without disassembly of any other game
+ * drivers, only of game databases as permitted by EEC law (for purposes
+ * of compatibility).
+ *
+ * Licensed under GPLv2
+ *
+ * https://github.com/angstsmurf/spatterlight/tree/master/terps/scott
+ */
+
 #ifndef GLK_SCOTT_DECOMPRESSTEXT_H
 #define GLK_SCOTT_DECOMPRESSTEXT_H
 
diff --git a/engines/glk/scott/decompress_z80.cpp b/engines/glk/scott/decompress_z80.cpp
index a3e1715ec30..c9979d6f81b 100644
--- a/engines/glk/scott/decompress_z80.cpp
+++ b/engines/glk/scott/decompress_z80.cpp
@@ -19,6 +19,17 @@
  *
  */
 
+/*
+ * Based on ScottFree interpreter version 1.14 developed by Swansea
+ * University Computer Society without disassembly of any other game
+ * drivers, only of game databases as permitted by EEC law (for purposes
+ * of compatibility).
+ *
+ * Licensed under GPLv2
+ *
+ * https://github.com/angstsmurf/spatterlight/tree/master/terps/scott
+ */
+
 #include "common/algorithm.h"
 #include "common/array.h"
 #include "common/textconsole.h"
diff --git a/engines/glk/scott/decompress_z80.h b/engines/glk/scott/decompress_z80.h
index a3bcaeab620..dc01639913c 100644
--- a/engines/glk/scott/decompress_z80.h
+++ b/engines/glk/scott/decompress_z80.h
@@ -19,6 +19,17 @@
  *
  */
 
+/*
+ * Based on ScottFree interpreter version 1.14 developed by Swansea
+ * University Computer Society without disassembly of any other game
+ * drivers, only of game databases as permitted by EEC law (for purposes
+ * of compatibility).
+ *
+ * Licensed under GPLv2
+ *
+ * https://github.com/angstsmurf/spatterlight/tree/master/terps/scott
+ */
+
 #ifndef GLK_SCOTT_DECOMPRESSZ80_H
 #define GLK_SCOTT_DECOMPRESSZ80_H
 
diff --git a/engines/glk/scott/definitions.cpp b/engines/glk/scott/definitions.cpp
index 633104e00f1..934d5a544fd 100644
--- a/engines/glk/scott/definitions.cpp
+++ b/engines/glk/scott/definitions.cpp
@@ -19,6 +19,17 @@
  *
  */
 
+/*
+ * Based on ScottFree interpreter version 1.14 developed by Swansea
+ * University Computer Society without disassembly of any other game
+ * drivers, only of game databases as permitted by EEC law (for purposes
+ * of compatibility).
+ *
+ * Licensed under GPLv2
+ *
+ * https://github.com/angstsmurf/spatterlight/tree/master/terps/scott
+ */
+
 #include "glk/scott/definitions.h"
 
 namespace Glk {
diff --git a/engines/glk/scott/definitions.h b/engines/glk/scott/definitions.h
index 28073c21f3a..4f22d9f832d 100644
--- a/engines/glk/scott/definitions.h
+++ b/engines/glk/scott/definitions.h
@@ -19,6 +19,17 @@
  *
  */
 
+/*
+ * Based on ScottFree interpreter version 1.14 developed by Swansea
+ * University Computer Society without disassembly of any other game
+ * drivers, only of game databases as permitted by EEC law (for purposes
+ * of compatibility).
+ *
+ * Licensed under GPLv2
+ *
+ * https://github.com/angstsmurf/spatterlight/tree/master/terps/scott
+ */
+
 #ifndef GLK_SCOTT_DEFINITIONS_H
 #define GLK_SCOTT_DEFINITIONS_H
 
diff --git a/engines/glk/scott/detection.cpp b/engines/glk/scott/detection.cpp
index 42900ab3341..e2ee0c8b054 100644
--- a/engines/glk/scott/detection.cpp
+++ b/engines/glk/scott/detection.cpp
@@ -19,6 +19,17 @@
  *
  */
 
+/*
+ * Based on ScottFree interpreter version 1.14 developed by Swansea
+ * University Computer Society without disassembly of any other game
+ * drivers, only of game databases as permitted by EEC law (for purposes
+ * of compatibility).
+ *
+ * Licensed under GPLv2
+ *
+ * https://github.com/angstsmurf/spatterlight/tree/master/terps/scott
+ */
+
 #include "common/file.h"
 #include "common/md5.h"
 #include "engines/game.h"
diff --git a/engines/glk/scott/detection.h b/engines/glk/scott/detection.h
index 263e6e156f2..8f15830b4a3 100644
--- a/engines/glk/scott/detection.h
+++ b/engines/glk/scott/detection.h
@@ -19,6 +19,17 @@
  *
  */
 
+/*
+ * Based on ScottFree interpreter version 1.14 developed by Swansea
+ * University Computer Society without disassembly of any other game
+ * drivers, only of game databases as permitted by EEC law (for purposes
+ * of compatibility).
+ *
+ * Licensed under GPLv2
+ *
+ * https://github.com/angstsmurf/spatterlight/tree/master/terps/scott
+ */
+
 #ifndef GLK_SCOTT_DETECTION_H
 #define GLK_SCOTT_DETECTION_H
 
diff --git a/engines/glk/scott/detection_tables.h b/engines/glk/scott/detection_tables.h
index 54b12ed6a72..147bc159306 100644
--- a/engines/glk/scott/detection_tables.h
+++ b/engines/glk/scott/detection_tables.h
@@ -19,6 +19,17 @@
  *
  */
 
+/*
+ * Based on ScottFree interpreter version 1.14 developed by Swansea
+ * University Computer Society without disassembly of any other game
+ * drivers, only of game databases as permitted by EEC law (for purposes
+ * of compatibility).
+ *
+ * Licensed under GPLv2
+ *
+ * https://github.com/angstsmurf/spatterlight/tree/master/terps/scott
+ */
+
 #include "common/gui_options.h"
 #include "common/language.h"
 #include "engines/game.h"
diff --git a/engines/glk/scott/disk_image.cpp b/engines/glk/scott/disk_image.cpp
index 45a59c1a4b4..48622a0c5e0 100644
--- a/engines/glk/scott/disk_image.cpp
+++ b/engines/glk/scott/disk_image.cpp
@@ -19,6 +19,32 @@
  *
  */
 
+/*
+* https://paradroid.automac.se/diskimage/
+* Copyright (c) 2003-2006, Per Olofsson
+* All rights reserved.
+* 
+* Redistribution and use in source and binary forms, with or without modification,
+* are permitted provided that the following conditions are met:
+* Redistributions of source code must retain the above copyright notice,
+* this list of conditions and the following disclaimer. Redistributions in
+* binary form must reproduce the above copyright notice, this list of
+* conditions and the following disclaimer in the documentation and/or
+* other materials provided with the distribution.
+* 
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
 #include "common/scummsys.h"
 #include "common/str.h"
 #include "common/textconsole.h"
diff --git a/engines/glk/scott/disk_image.h b/engines/glk/scott/disk_image.h
index e83317882a0..5db21d113d8 100644
--- a/engines/glk/scott/disk_image.h
+++ b/engines/glk/scott/disk_image.h
@@ -19,6 +19,32 @@
  *
  */
 
+/*
+ * https://paradroid.automac.se/diskimage/
+ * Copyright (c) 2003-2006, Per Olofsson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer. Redistributions in
+ * binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
 #ifndef GLK_SCOTT_DISKIMAGE_H
 #define GLK_SCOTT_DISKIMAGE_H
 
diff --git a/engines/glk/scott/game_info.cpp b/engines/glk/scott/game_info.cpp
index 79a9a65e383..651e9d7e9bd 100644
--- a/engines/glk/scott/game_info.cpp
+++ b/engines/glk/scott/game_info.cpp
@@ -19,6 +19,17 @@
  *
  */
 
+/*
+ * Based on ScottFree interpreter version 1.14 developed by Swansea
+ * University Computer Society without disassembly of any other game
+ * drivers, only of game databases as permitted by EEC law (for purposes
+ * of compatibility).
+ *
+ * Licensed under GPLv2
+ *
+ * https://github.com/angstsmurf/spatterlight/tree/master/terps/scott
+ */
+
 #include "common/array.h"
 #include "common/str.h"
 #include "common/str-array.h"
diff --git a/engines/glk/scott/game_info.h b/engines/glk/scott/game_info.h
index 13b06353d5e..920fc61a881 100644
--- a/engines/glk/scott/game_info.h
+++ b/engines/glk/scott/game_info.h
@@ -19,6 +19,17 @@
  *
  */
 
+/*
+ * Based on ScottFree interpreter version 1.14 developed by Swansea
+ * University Computer Society without disassembly of any other game
+ * drivers, only of game databases as permitted by EEC law (for purposes
+ * of compatibility).
+ *
+ * Licensed under GPLv2
+ *
+ * https://github.com/angstsmurf/spatterlight/tree/master/terps/scott
+ */
+
 #ifndef GLK_SCOTT_GAMEINFO_H
 #define GLK_SCOTT_GAMEINFO_H
 
diff --git a/engines/glk/scott/game_specific.cpp b/engines/glk/scott/game_specific.cpp
index 7d5205c2838..d10debe8a38 100644
--- a/engines/glk/scott/game_specific.cpp
+++ b/engines/glk/scott/game_specific.cpp
@@ -19,6 +19,17 @@
  *
  */
 
+/*
+ * Based on ScottFree interpreter version 1.14 developed by Swansea
+ * University Computer Society without disassembly of any other game
+ * drivers, only of game databases as permitted by EEC law (for purposes
+ * of compatibility).
+ *
+ * Licensed under GPLv2
+ *
+ * https://github.com/angstsmurf/spatterlight/tree/master/terps/scott
+ */
+
 #include "common/str.h"
 #include "glk/scott/scott.h"
 #include "glk/scott/globals.h"
diff --git a/engines/glk/scott/game_specific.h b/engines/glk/scott/game_specific.h
index f3a5fa3d6a9..9550c9843a3 100644
--- a/engines/glk/scott/game_specific.h
+++ b/engines/glk/scott/game_specific.h
@@ -19,6 +19,17 @@
  *
  */
 
+/*
+ * Based on ScottFree interpreter version 1.14 developed by Swansea
+ * University Computer Society without disassembly of any other game
+ * drivers, only of game databases as permitted by EEC law (for purposes
+ * of compatibility).
+ *
+ * Licensed under GPLv2
+ *
+ * https://github.com/angstsmurf/spatterlight/tree/master/terps/scott
+ */
+
 #ifndef GLK_SCOTT_GAMESPECIFIC_H
 #define GLK_SCOTT_GAMESPECIFIC_H
 
diff --git a/engines/glk/scott/games.h b/engines/glk/scott/games.h
index b867414652d..0b61b2fcfbc 100644
--- a/engines/glk/scott/games.h
+++ b/engines/glk/scott/games.h
@@ -19,6 +19,17 @@
  *
  */
 
+/*
+ * Based on ScottFree interpreter version 1.14 developed by Swansea
+ * University Computer Society without disassembly of any other game
+ * drivers, only of game databases as permitted by EEC law (for purposes
+ * of compatibility).
+ *
+ * Licensed under GPLv2
+ *
+ * https://github.com/angstsmurf/spatterlight/tree/master/terps/scott
+ */
+
 const GameInfo _games[NUMGAMES] = {
 	GameInfo("The Golden Baton",
 			 BATON,
diff --git a/engines/glk/scott/globals.cpp b/engines/glk/scott/globals.cpp
index d7ebf7f3aea..3a5d6495c22 100644
--- a/engines/glk/scott/globals.cpp
+++ b/engines/glk/scott/globals.cpp
@@ -19,6 +19,17 @@
  *
  */
 
+/*
+ * Based on ScottFree interpreter version 1.14 developed by Swansea
+ * University Computer Society without disassembly of any other game
+ * drivers, only of game databases as permitted by EEC law (for purposes
+ * of compatibility).
+ *
+ * Licensed under GPLv2
+ *
+ * https://github.com/angstsmurf/spatterlight/tree/master/terps/scott
+ */
+
 #include "common/algorithm.h"
 #include "glk/scott/scott.h"
 #include "glk/scott/command_parser.h"
diff --git a/engines/glk/scott/globals.h b/engines/glk/scott/globals.h
index ced8fc31d41..a99a8cad09c 100644
--- a/engines/glk/scott/globals.h
+++ b/engines/glk/scott/globals.h
@@ -19,6 +19,17 @@
  *
  */
 
+/*
+ * Based on ScottFree interpreter version 1.14 developed by Swansea
+ * University Computer Society without disassembly of any other game
+ * drivers, only of game databases as permitted by EEC law (for purposes
+ * of compatibility).
+ *
+ * Licensed under GPLv2
+ *
+ * https://github.com/angstsmurf/spatterlight/tree/master/terps/scott
+ */
+
 #ifndef GLK_SCOTT_GLOBALS_H
 #define GLK_SCOTT_GLOBALS_H
 
diff --git a/engines/glk/scott/hulk.cpp b/engines/glk/scott/hulk.cpp
index 76dd1c34c07..a0fe9dc87e2 100644
--- a/engines/glk/scott/hulk.cpp
+++ b/engines/glk/scott/hulk.cpp
@@ -19,6 +19,17 @@
  *
  */
 
+/*
+ * Based on ScottFree interpreter version 1.14 developed by Swansea
+ * University Computer Society without disassembly of any other game
+ * drivers, only of game databases as permitted by EEC law (for purposes
+ * of compatibility).
+ *
+ * Licensed under GPLv2
+ *
+ * https://github.com/angstsmurf/spatterlight/tree/master/terps/scott
+ */
+
 #include "glk/scott/scott.h"
 #include "glk/scott/definitions.h"
 #include "glk/scott/resource.h"
diff --git a/engines/glk/scott/hulk.h b/engines/glk/scott/hulk.h
index f234251a935..095f2b6650e 100644
--- a/engines/glk/scott/hulk.h
+++ b/engines/glk/scott/hulk.h
@@ -19,6 +19,17 @@
  *
  */
 
+/*
+ * Based on ScottFree interpreter version 1.14 developed by Swansea
+ * University Computer Society without disassembly of any other game
+ * drivers, only of game databases as permitted by EEC law (for purposes
+ * of compatibility).
+ *
+ * Licensed under GPLv2
+ *
+ * https://github.com/angstsmurf/spatterlight/tree/master/terps/scott
+ */
+
 #ifndef GLK_SCOTT_HULK_H
 #define GLK_SCOTT_HULK_H
 
diff --git a/engines/glk/scott/layout_text.cpp b/engines/glk/scott/layout_text.cpp
index 9cb10fb1909..c9e5bda0aba 100644
--- a/engines/glk/scott/layout_text.cpp
+++ b/engines/glk/scott/layout_text.cpp
@@ -19,6 +19,17 @@
  *
  */
 
+/*
+ * Based on ScottFree interpreter version 1.14 developed by Swansea
+ * University Computer Society without disassembly of any other game
+ * drivers, only of game databases as permitted by EEC law (for purposes
+ * of compatibility).
+ *
+ * Licensed under GPLv2
+ *
+ * https://github.com/angstsmurf/spatterlight/tree/master/terps/scott
+ */
+
 #include "common/util.h"
 #include "glk/scott/layout_text.h"
 
diff --git a/engines/glk/scott/layout_text.h b/engines/glk/scott/layout_text.h
index d15629c87da..8bb2c8683f0 100644
--- a/engines/glk/scott/layout_text.h
+++ b/engines/glk/scott/layout_text.h
@@ -19,6 +19,17 @@
  *
  */
 
+/*
+ * Based on ScottFree interpreter version 1.14 developed by Swansea
+ * University Computer Society without disassembly of any other game
+ * drivers, only of game databases as permitted by EEC law (for purposes
+ * of compatibility).
+ *
+ * Licensed under GPLv2
+ *
+ * https://github.com/angstsmurf/spatterlight/tree/master/terps/scott
+ */
+
 #ifndef GLK_SCOTT_LAYOUTTEXT_H
 #define GLK_SCOTT_LAYOUTTEXT_H
 
diff --git a/engines/glk/scott/line_drawing.cpp b/engines/glk/scott/line_drawing.cpp
index 3e1eb6276a7..3134553f450 100644
--- a/engines/glk/scott/line_drawing.cpp
+++ b/engines/glk/scott/line_drawing.cpp
@@ -19,6 +19,17 @@
  *
  */
 
+/*
+ * Based on ScottFree interpreter version 1.14 developed by Swansea
+ * University Computer Society without disassembly of any other game
+ * drivers, only of game databases as permitted by EEC law (for purposes
+ * of compatibility).
+ *
+ * Licensed under GPLv2
+ *
+ * https://github.com/angstsmurf/spatterlight/tree/master/terps/scott
+ */
+
 #include "glk/scott/scott.h"
 #include "glk/scott/globals.h"
 #include "glk/scott/ring_buffer.h"
diff --git a/engines/glk/scott/line_drawing.h b/engines/glk/scott/line_drawing.h
index 398a239b07c..74ab027e2c5 100644
--- a/engines/glk/scott/line_drawing.h
+++ b/engines/glk/scott/line_drawing.h
@@ -19,6 +19,17 @@
  *
  */
 
+/*
+ * Based on ScottFree interpreter version 1.14 developed by Swansea
+ * University Computer Society without disassembly of any other game
+ * drivers, only of game databases as permitted by EEC law (for purposes
+ * of compatibility).
+ *
+ * Licensed under GPLv2
+ *
+ * https://github.com/angstsmurf/spatterlight/tree/master/terps/scott
+ */
+
 #ifndef GLK_SCOTT_LINEDRAWING_H
 #define GLK_SCOTT_LINEDRAWING_H
 
diff --git a/engines/glk/scott/load_game.cpp b/engines/glk/scott/load_game.cpp
index 38d4be759a5..33428408607 100644
--- a/engines/glk/scott/load_game.cpp
+++ b/engines/glk/scott/load_game.cpp
@@ -19,6 +19,17 @@
  *
  */
 
+/*
+ * Based on ScottFree interpreter version 1.14 developed by Swansea
+ * University Computer Society without disassembly of any other game
+ * drivers, only of game databases as permitted by EEC law (for purposes
+ * of compatibility).
+ *
+ * Licensed under GPLv2
+ *
+ * https://github.com/angstsmurf/spatterlight/tree/master/terps/scott
+ */
+
 #include "common/str.h"
 #include "glk/scott/scott.h"
 #include "glk/scott/globals.h"
diff --git a/engines/glk/scott/load_game.h b/engines/glk/scott/load_game.h
index 23e3d5d673c..8a24befbbb4 100644
--- a/engines/glk/scott/load_game.h
+++ b/engines/glk/scott/load_game.h
@@ -19,6 +19,17 @@
  *
  */
 
+/*
+ * Based on ScottFree interpreter version 1.14 developed by Swansea
+ * University Computer Society without disassembly of any other game
+ * drivers, only of game databases as permitted by EEC law (for purposes
+ * of compatibility).
+ *
+ * Licensed under GPLv2
+ *
+ * https://github.com/angstsmurf/spatterlight/tree/master/terps/scott
+ */
+
 #ifndef GLK_SCOTT_DETECTGAME_H
 #define GLK_SCOTT_DETECTGAME_H
 
diff --git a/engines/glk/scott/resource.cpp b/engines/glk/scott/resource.cpp
index 2fa5ce9c728..c9952675db7 100644
--- a/engines/glk/scott/resource.cpp
+++ b/engines/glk/scott/resource.cpp
@@ -19,6 +19,17 @@
  *
  */
 
+/*
+ * Based on ScottFree interpreter version 1.14 developed by Swansea
+ * University Computer Society without disassembly of any other game
+ * drivers, only of game databases as permitted by EEC law (for purposes
+ * of compatibility).
+ *
+ * Licensed under GPLv2
+ *
+ * https://github.com/angstsmurf/spatterlight/tree/master/terps/scott
+ */
+
 #include "common/str.h"
 #include "glk/scott/scott.h"
 #include "glk/scott/globals.h"
diff --git a/engines/glk/scott/resource.h b/engines/glk/scott/resource.h
index a28541cc345..21395300e0e 100644
--- a/engines/glk/scott/resource.h
+++ b/engines/glk/scott/resource.h
@@ -19,6 +19,17 @@
  *
  */
 
+/*
+ * Based on ScottFree interpreter version 1.14 developed by Swansea
+ * University Computer Society without disassembly of any other game
+ * drivers, only of game databases as permitted by EEC law (for purposes
+ * of compatibility).
+ *
+ * Licensed under GPLv2
+ *
+ * https://github.com/angstsmurf/spatterlight/tree/master/terps/scott
+ */
+
 #ifndef GLK_SCOTT_RESOURCE_H
 #define GLK_SCOTT_RESOURCE_H
 
diff --git a/engines/glk/scott/restore_state.cpp b/engines/glk/scott/restore_state.cpp
index f397876f09d..5e85ab225e1 100644
--- a/engines/glk/scott/restore_state.cpp
+++ b/engines/glk/scott/restore_state.cpp
@@ -19,6 +19,17 @@
  *
  */
 
+/*
+ * Based on ScottFree interpreter version 1.14 developed by Swansea
+ * University Computer Society without disassembly of any other game
+ * drivers, only of game databases as permitted by EEC law (for purposes
+ * of compatibility).
+ *
+ * Licensed under GPLv2
+ *
+ * https://github.com/angstsmurf/spatterlight/tree/master/terps/scott
+ */
+
 #include "glk/scott/scott.h"
 #include "glk/scott/globals.h"
 #include "glk/scott/definitions.h"
diff --git a/engines/glk/scott/restore_state.h b/engines/glk/scott/restore_state.h
index e386af98af7..34bd62efdb9 100644
--- a/engines/glk/scott/restore_state.h
+++ b/engines/glk/scott/restore_state.h
@@ -19,6 +19,17 @@
  *
  */
 
+/*
+ * Based on ScottFree interpreter version 1.14 developed by Swansea
+ * University Computer Society without disassembly of any other game
+ * drivers, only of game databases as permitted by EEC law (for purposes
+ * of compatibility).
+ *
+ * Licensed under GPLv2
+ *
+ * https://github.com/angstsmurf/spatterlight/tree/master/terps/scott
+ */
+
 #ifndef GLK_SCOTT_RESTORESTATE_H
 #define GLK_SCOTT_RESTORESTATE_H
 
diff --git a/engines/glk/scott/ring_buffer.cpp b/engines/glk/scott/ring_buffer.cpp
index de2aa18ae8b..5be0e44f27f 100644
--- a/engines/glk/scott/ring_buffer.cpp
+++ b/engines/glk/scott/ring_buffer.cpp
@@ -19,6 +19,17 @@
  *
  */
 
+/*
+ * Based on ScottFree interpreter version 1.14 developed by Swansea
+ * University Computer Society without disassembly of any other game
+ * drivers, only of game databases as permitted by EEC law (for purposes
+ * of compatibility).
+ *
+ * Licensed under GPLv2
+ *
+ * https://github.com/angstsmurf/spatterlight/tree/master/terps/scott
+ */
+
 #include "glk/scott/ring_buffer.h"
 
 namespace Glk {
diff --git a/engines/glk/scott/ring_buffer.h b/engines/glk/scott/ring_buffer.h
index 82edf238c73..bc56a9517b8 100644
--- a/engines/glk/scott/ring_buffer.h
+++ b/engines/glk/scott/ring_buffer.h
@@ -19,6 +19,17 @@
  *
  */
 
+/*
+ * Based on ScottFree interpreter version 1.14 developed by Swansea
+ * University Computer Society without disassembly of any other game
+ * drivers, only of game databases as permitted by EEC law (for purposes
+ * of compatibility).
+ *
+ * Licensed under GPLv2
+ *
+ * https://github.com/angstsmurf/spatterlight/tree/master/terps/scott
+ */
+
 #ifndef GLK_SCOTT_RINGBUFFER_H
 #define GLK_SCOTT_RINGBUFFER_H
 
diff --git a/engines/glk/scott/saga_draw.cpp b/engines/glk/scott/saga_draw.cpp
index 16a69f6a8d6..aa9f279c69f 100644
--- a/engines/glk/scott/saga_draw.cpp
+++ b/engines/glk/scott/saga_draw.cpp
@@ -19,6 +19,17 @@
  *
  */
 
+/*
+ * Based on ScottFree interpreter version 1.14 developed by Swansea
+ * University Computer Society without disassembly of any other game
+ * drivers, only of game databases as permitted by EEC law (for purposes
+ * of compatibility).
+ *
+ * Licensed under GPLv2
+ *
+ * https://github.com/angstsmurf/spatterlight/tree/master/terps/scott
+ */
+
 #include "glk/scott/scott.h"
 #include "glk/scott/definitions.h"
 #include "glk/scott/resource.h"
diff --git a/engines/glk/scott/saga_draw.h b/engines/glk/scott/saga_draw.h
index ebad80ed289..df89a1c1361 100644
--- a/engines/glk/scott/saga_draw.h
+++ b/engines/glk/scott/saga_draw.h
@@ -19,6 +19,17 @@
  *
  */
 
+/*
+ * Based on ScottFree interpreter version 1.14 developed by Swansea
+ * University Computer Society without disassembly of any other game
+ * drivers, only of game databases as permitted by EEC law (for purposes
+ * of compatibility).
+ *
+ * Licensed under GPLv2
+ *
+ * https://github.com/angstsmurf/spatterlight/tree/master/terps/scott
+ */
+
 #ifndef GLK_SCOTT_SAGADRAW_H
 #define GLK_SCOTT_SAGADRAW_H
 
diff --git a/engines/glk/scott/scott.cpp b/engines/glk/scott/scott.cpp
index ae595739573..6bb148ee540 100644
--- a/engines/glk/scott/scott.cpp
+++ b/engines/glk/scott/scott.cpp
@@ -19,6 +19,17 @@
  *
  */
 
+/*
+ * Based on ScottFree interpreter version 1.14 developed by Swansea
+ * University Computer Society without disassembly of any other game
+ * drivers, only of game databases as permitted by EEC law (for purposes
+ * of compatibility).
+ *
+ * Licensed under GPLv2
+ *
+ * https://github.com/angstsmurf/spatterlight/tree/master/terps/scott
+ */
+
 #include "common/config-manager.h"
 #include "common/translation.h"
 #include "common/ustr.h"
diff --git a/engines/glk/scott/scott.h b/engines/glk/scott/scott.h
index 865dd520ee7..09dca6814f4 100644
--- a/engines/glk/scott/scott.h
+++ b/engines/glk/scott/scott.h
@@ -19,7 +19,16 @@
  *
  */
 
-/* Based on ScottFree interpreter version 1.14 */
+/*
+ * Based on ScottFree interpreter version 1.14 developed by Swansea
+ * University Computer Society without disassembly of any other game
+ * drivers, only of game databases as permitted by EEC law (for purposes
+ * of compatibility).
+ *
+ * Licensed under GPLv2
+ *
+ * https://github.com/angstsmurf/spatterlight/tree/master/terps/scott
+ */
 
 #ifndef GLK_SCOTT_H
 #define GLK_SCOTT_H
diff --git a/engines/glk/scott/types.h b/engines/glk/scott/types.h
index a8de41c63ba..6fe5a86847e 100644
--- a/engines/glk/scott/types.h
+++ b/engines/glk/scott/types.h
@@ -19,6 +19,17 @@
  *
  */
 
+/*
+ * Based on ScottFree interpreter version 1.14 developed by Swansea
+ * University Computer Society without disassembly of any other game
+ * drivers, only of game databases as permitted by EEC law (for purposes
+ * of compatibility).
+ *
+ * Licensed under GPLv2
+ *
+ * https://github.com/angstsmurf/spatterlight/tree/master/terps/scott
+ */
+
 #ifndef GLK_SCOTT_TYPES_H
 #define GLK_SCOTT_TYPES_H
 


Commit: f591a6a1860e5bf0744fb40ccf90891e2a26d580
    https://github.com/scummvm/scummvm/commit/f591a6a1860e5bf0744fb40ccf90891e2a26d580
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Add support for Robin of Sherwood

Changed paths:
  A engines/glk/scott/robin_of_sherwood.cpp
  A engines/glk/scott/robin_of_sherwood.h
    engines/glk/module.mk
    engines/glk/scott/c64_checksums.cpp
    engines/glk/scott/decompress_text.cpp
    engines/glk/scott/detection.cpp
    engines/glk/scott/detection_tables.h
    engines/glk/scott/disk_image.cpp
    engines/glk/scott/disk_image.h
    engines/glk/scott/games.h
    engines/glk/scott/globals.cpp
    engines/glk/scott/globals.h
    engines/glk/scott/load_game.cpp
    engines/glk/scott/resource.cpp
    engines/glk/scott/saga_draw.cpp
    engines/glk/scott/saga_draw.h
    engines/glk/scott/scott.cpp
    engines/glk/scott/scott.h


diff --git a/engines/glk/module.mk b/engines/glk/module.mk
index 9124f112a71..257ce7d3ecf 100644
--- a/engines/glk/module.mk
+++ b/engines/glk/module.mk
@@ -250,6 +250,7 @@ MODULE_OBJS := \
 	scott/resource.o \
 	scott/restore_state.o \
 	scott/ring_buffer.o \
+	scott/robin_of_sherwood.o \
 	scott/saga_draw.o \
 	scott/scott.o \
 	scott/unp64/unp64.o \
diff --git a/engines/glk/scott/c64_checksums.cpp b/engines/glk/scott/c64_checksums.cpp
index eca37b6ed55..797161c3034 100644
--- a/engines/glk/scott/c64_checksums.cpp
+++ b/engines/glk/scott/c64_checksums.cpp
@@ -84,11 +84,35 @@ static C64Rec g_C64Registry[] = {
 	{ WAXWORKS_C64,		0x2ab00, 0x9eaa, TYPE_D64, 0 },
 	{ BATON_C64,		0x2ab00, 0x9dca, TYPE_D64, 2 },
 
+	{ ROBIN_OF_SHERWOOD_C64, 0x2ab00, 0xcf9e, TYPE_D64, 1, nullptr, nullptr, 0, 0x1802, 0xbd27, 0x2000 }, // Robin Of Sherwood D64 * unknown packer
+	{ ROBIN_OF_SHERWOOD_C64, 0xb2ef,  0x7c44, TYPE_T64, 1, nullptr, nullptr, 0, 0x9702, 0x9627, 0x2000 }, // Robin Of Sherwood C64 (T64) * TCS Cruncher v2.0
+	{ ROBIN_OF_SHERWOOD_C64, 0xb690,  0x7b61, TYPE_T64, 1, nullptr, nullptr, 0, 0x9702, 0x9627, 0x2000 }, // Robin Of Sherwood C64 (T64) alt * TCS Cruncher v2.0
+	{ ROBIN_OF_SHERWOOD_C64, 0x8db6,  0x7853, TYPE_T64, 1, nullptr, nullptr, 0, 0xd7fb, 0xbd20, 0x2000 }, // Robin Of Sherwood T64 alt 2 * PUCrunch
+
 	{ UNKNOWN_GAME, 0, 0, UNKNOWN_FILE_TYPE, 0, nullptr, nullptr, 0, 0, 0, 0 }
 };
 
 int decrunchC64(uint8_t **sf, size_t *extent, C64Rec entry);
 
+uint8_t *getLargestFile(uint8_t *data, int length, int *newlength) {
+	uint8_t *file = NULL;
+	*newlength = 0;
+	DiskImage *d64 = diCreateFromData(data, length);
+	if (d64) {
+		RawDirEntry *largest = findLargestFileEntry(d64);
+		if (largest) {
+			ImageFile *c64file = diOpen(d64, largest->_rawname, largest->_type, "rb");
+			if (c64file) {
+				int expectedsize = largest->_sizelo + largest->_sizehi * 0x100;
+				file = new uint8_t[expectedsize];
+				*newlength = diRead(c64file, file, 0xffff);
+			}
+		}
+		//di_free_image(d64);
+	}
+	return file;
+}
+
 uint8_t *getFileNamed(uint8_t* data, int length, int* newLength, const char* name) {
 	uint8_t *file = nullptr;
 	*newLength = 0;
@@ -251,7 +275,49 @@ int detectC64(uint8_t **sf, size_t *extent) {
 	} else if (g_C64Registry[index]._id == FEASIBILITY_C64) {
 		return mysteriousMenu2(sf, extent, index);
 	}
-	return UNKNOWN_GAME;
+	if (g_C64Registry[index]._type == TYPE_D64) {
+		int newlength;
+		uint8_t *largest_file = getLargestFile(*sf, *extent, &newlength);
+		uint8_t *appendix = nullptr;
+		int appendixlen = 0;
+
+		if (g_C64Registry[index]._appendFile != nullptr) {
+			appendix = getFileNamed(*sf, *extent, &appendixlen, g_C64Registry[index]._appendFile);
+			if (appendix == nullptr)
+				error("detectC64(): Appending file failed");
+			appendixlen -= 2;
+		}
+
+		uint8_t *megabuf = new uint8_t[newlength + appendixlen];
+		memcpy(megabuf, largest_file, newlength);
+		if (appendix != nullptr) {
+			memcpy(megabuf + newlength + g_C64Registry[index]._parameter, appendix + 2, appendixlen);
+			newlength += appendixlen;
+		}
+
+		if (largest_file) {
+			*sf = megabuf;
+			*extent = newlength;
+		}
+
+	} else if (g_C64Registry[index]._type == TYPE_T64) {
+		uint8_t *file_records = *sf + 64;
+		int number_of_records = READ_LE_UINT16(&(*sf)[36]);
+		int offset = READ_LE_UINT16(&file_records[8]);
+		int start_addr = READ_LE_UINT16(&file_records[2]);
+		int end_addr = READ_LE_UINT16(&file_records[4]);
+		int size;
+		if (number_of_records == 1)
+			size = *extent - offset;
+		else
+			size = end_addr - start_addr;
+		uint8_t *first_file = new uint8_t[size + 2];
+		memcpy(first_file + 2, *sf + offset, size);
+		memcpy(first_file, file_records + 2, 2);
+		*sf = first_file;
+		*extent = size + 2;
+	}
+	return decrunchC64(sf, extent, g_C64Registry[index]);
 }
 
 size_t copyData(size_t dest, size_t source, uint8_t** data, size_t dataSize, size_t bytesToMove) {
diff --git a/engines/glk/scott/decompress_text.cpp b/engines/glk/scott/decompress_text.cpp
index 4e03b5f7c63..a93ec18ad4b 100644
--- a/engines/glk/scott/decompress_text.cpp
+++ b/engines/glk/scott/decompress_text.cpp
@@ -59,7 +59,8 @@ int decompressOne(uint8_t *bytes) {
 
 char *decompressText(uint8_t *source, int stringIndex) {
 	// Lookup table
-	Common::String alphabet = " abcdefghijklmnopqrstuvwxyz'\x01,.\x00";
+	const char *alphabet = " abcdefghijklmnopqrstuvwxyz'\x01,.\x00";
+	//Common::String alphabet = " abcdefghijklmnopqrstuvwxyz'\x01,.\x00";
 
 	int pos, c, uppercase, i, j;
 	uint8_t decompressed[256];
diff --git a/engines/glk/scott/detection.cpp b/engines/glk/scott/detection.cpp
index e2ee0c8b054..97f2122f560 100644
--- a/engines/glk/scott/detection.cpp
+++ b/engines/glk/scott/detection.cpp
@@ -55,7 +55,7 @@ GameDescriptor ScottMetaEngine::findGame(const char *gameId) {
 }
 
 bool ScottMetaEngine::detectGames(const Common::FSList &fslist, DetectedGames &gameList) {
-	const char *const EXTENSIONS[] = {".z80", ".saga", ".dat", ".D64", nullptr};
+	const char *const EXTENSIONS[] = {".z80", ".saga", ".dat", ".D64", ".T64", nullptr};
 
 	// Loop through the files of the folder
 	for (Common::FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) {
diff --git a/engines/glk/scott/detection_tables.h b/engines/glk/scott/detection_tables.h
index 147bc159306..446897febe6 100644
--- a/engines/glk/scott/detection_tables.h
+++ b/engines/glk/scott/detection_tables.h
@@ -39,24 +39,25 @@ namespace Scott {
 
 const PlainGameDescriptor SCOTT_GAME_LIST[] = {
 	// Scott Adams games
-	{ "adventureland",     "Adventureland" },
-	{ "pirateadventure",   "Pirate Adventure" },
-	{ "missionimpossible", "Mission Impossible" },
-	{ "voodoocastle",      "Voodoo Castle" },
-	{ "thecount",          "The Count" },
-	{ "strangeodyssey",    "Strange Odyssey" },
-	{ "mysteryfunhouse",   "Mystery Fun House" },
-	{ "pyramidofdoom",     "Pyramid Of Doom" },
-	{ "ghosttown",         "Ghost Town" },
-	{ "savageisland1",     "Savage Island, Part 1" },
-	{ "savageisland2",     "Savage Island, Part 2" },
-	{ "goldenvoyage",      "The Golden Voyage" },
-	{ "claymorguesorcerer","Sorcerer of Claymorgue Castle" },
-	{ "pirateisle",        "Return to Pirate Isle" },
-	{ "buckaroobanzai",    "Buckaroo Banzai" },
-	{ "marveladventure",   "Marvel Adventure #1" },
-	{ "marveladventure2",  "Marvel Adventure #2" },
-	{ "scottsampler",      "Adventure International's Mini-Adventure Sampler" },
+	{ "adventureland",		"Adventureland" },
+	{ "pirateadventure",	"Pirate Adventure" },
+	{ "missionimpossible",	"Mission Impossible" },
+	{ "voodoocastle",		"Voodoo Castle" },
+	{ "thecount",			"The Count" },
+	{ "strangeodyssey",		"Strange Odyssey" },
+	{ "mysteryfunhouse",	"Mystery Fun House" },
+	{ "pyramidofdoom",		"Pyramid Of Doom" },
+	{ "ghosttown",			"Ghost Town" },
+	{ "savageisland1",		"Savage Island, Part 1" },
+	{ "savageisland2",		"Savage Island, Part 2" },
+	{ "goldenvoyage",		"The Golden Voyage" },
+	{ "claymorguesorcerer",	"Sorcerer of Claymorgue Castle" },
+	{ "pirateisle",			"Return to Pirate Isle" },
+	{ "buckaroobanzai",		"Buckaroo Banzai" },
+	{ "marveladventure",	"Marvel Adventure #1" },
+	{ "marveladventure2",	"Marvel Adventure #2" },
+	{ "scottsampler",		"Adventure International's Mini-Adventure Sampler" },
+	{ "robinofsherwood",	"Robin Of Sherwood" },
 
 	// 11 Mysterious Adventures by Brian Howarth
 	{ "goldenbaton", "Mysterious Adventures 1: The Golden Baton" },
@@ -177,6 +178,8 @@ const GlkDetectionEntry SCOTT_GAMES[] = {
 	DT_ENTRY1("waxworks11",		"ZXSpectrum", "6c6fbbbb50032463a6ea71c6750ea1f5", 32662),
 
 	// C64 Games
+	DT_ENTRY1("robinofsherwood", "C64", "6bf95a48f366bdf8af3a198c7b723c77", 174848),
+	DT_ENTRY1("robinofsherwood", "C64", "552c95ec15d750cbfa02c1f11dcbca1e", 36278),
 	// 11 Mysterious Adventures
 	DT_ENTRY1("mysadv1", "C64", "ce5a68cf43b2f29d99c0135b89f4fe31", 174848),
 	DT_ENTRY1("mysadv2", "C64", "1e1ff48f80a8220f5ab9d14c975197b8", 174848),
diff --git a/engines/glk/scott/disk_image.cpp b/engines/glk/scott/disk_image.cpp
index 48622a0c5e0..972c74c8f57 100644
--- a/engines/glk/scott/disk_image.cpp
+++ b/engines/glk/scott/disk_image.cpp
@@ -20,30 +20,30 @@
  */
 
 /*
-* https://paradroid.automac.se/diskimage/
-* Copyright (c) 2003-2006, Per Olofsson
-* All rights reserved.
-* 
-* Redistribution and use in source and binary forms, with or without modification,
-* are permitted provided that the following conditions are met:
-* Redistributions of source code must retain the above copyright notice,
-* this list of conditions and the following disclaimer. Redistributions in
-* binary form must reproduce the above copyright notice, this list of
-* conditions and the following disclaimer in the documentation and/or
-* other materials provided with the distribution.
-* 
-* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
-* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
-* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
-* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
+ * https://paradroid.automac.se/diskimage/
+ * Copyright (c) 2003-2006, Per Olofsson
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer. Redistributions in
+ * binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
 
 #include "common/scummsys.h"
 #include "common/str.h"
@@ -717,6 +717,30 @@ int interleave(ImageType type) {
 	}
 }
 
+RawDirEntry *findLargestFileEntry(DiskImage *di) {
+	byte *buffer;
+	TrackSector ts;
+	RawDirEntry *rde, *largest = nullptr;
+	int offset, largestSize = 0;
+
+	ts = diGetDirTs(di);
+
+	while (ts._track) {
+		buffer = diGetTsAddr(di, ts);
+		for (offset = 0; offset < 256; offset += 32) {
+			rde = (RawDirEntry *)(buffer + offset);
+			int size = rde->_sizelo + rde->_sizehi * 0x100;
+			if (size > largestSize) {
+				largest = rde;
+				largestSize = size;
+			}
+		}
+		/* todo: add sanity checking */
+		ts = nextTsInChain(di, ts);
+	}
+	return largest;
+}
+
 DiskImage *diCreateFromData(uint8_t *data, int length) {
 	DiskImage *di;
 
diff --git a/engines/glk/scott/disk_image.h b/engines/glk/scott/disk_image.h
index 5db21d113d8..fb8b5123ca6 100644
--- a/engines/glk/scott/disk_image.h
+++ b/engines/glk/scott/disk_image.h
@@ -135,6 +135,7 @@ void diAllocTs(DiskImage *di, TrackSector ts);
 
 int diRawnameFromName(byte *rawname, const char *name);
 
+RawDirEntry *findLargestFileEntry(DiskImage *di);
 DiskImage *diCreateFromData(uint8_t *data, int length);
 
 } // End of namespace Scott
diff --git a/engines/glk/scott/games.h b/engines/glk/scott/games.h
index 0b61b2fcfbc..4a0f8fe1d64 100644
--- a/engines/glk/scott/games.h
+++ b/engines/glk/scott/games.h
@@ -1019,4 +1019,91 @@ const GameInfo _games[NUMGAMES] = {
 			 43,     // number_of_pictures;
 			 ZXOPT,  // palette
 			 0,      // picture_format_version;
-			 0)};
+			 0),
+	GameInfo("Robin of Sherwood",
+			 ROBIN_OF_SHERWOOD,
+			 SHERWOOD_VARIANT,       // type
+			 ENGLISH,                // subtype
+			 FOUR_LETTER_COMPRESSED, // dictionary type
+
+			 87,  // Number of items
+			 295, // Number of actions
+			 114, // Number of words
+			 93,  // Number of rooms
+			 10,  // Max carried items
+			 4,   // Word length
+			 98,  // Number of messages
+
+			 115, // number_of_verbs
+			 109, // number_of_nouns;
+
+			 0x3b5a, // header
+			 LATE,   // header style
+
+			 0,       // 0x3d99 room images, zero because it needs custom handling
+			 0x3db8,  // item flags
+			 FOLLOWS, // item images
+
+			 0x409b, // actions
+			 COMPRESSED,
+			 0x4dc3, // dictionary
+			 0,      // 0x9b53 start_of_room_descriptions, zero because of custom handling
+			 0x3e67, // start_of_room_connections
+			 0x5147, // start_of_messages
+			 0x5d65, // start_of_item_descriptions
+			 0x4d6b, // start_of_item_locations
+
+			 0x250b, // start_of_system_messages
+			 0x26b5, // start of directions
+
+			 0x614f, // start_of_characters
+			 0x66bf, // start_of_image_data
+			 0x6765, // image_address_offset
+			 83,     // number_of_pictures
+			 ZXOPT,  // palette
+			 4,      // picture_format_version
+			 0),
+	GameInfo("Robin of Sherwood C64",
+			 ROBIN_OF_SHERWOOD_C64,
+			 SHERWOOD_VARIANT,                    // type
+			 static_cast<Subtype>(ENGLISH | C64), // subtype
+			 FOUR_LETTER_COMPRESSED,              // dictionary type
+
+			 87,  // Number of items
+			 296, // Number of actions
+			 114, // Number of words
+			 93,  // Number of rooms
+			 10,  // Max carried items
+			 4,   // Word length
+			 98,  // Number of messages
+
+			 115, // number_of_verbs
+			 109, // number_of_nouns;
+
+			 0x1f85,           // header
+			 ROBIN_C64_HEADER, // header style
+
+			 0,       // room images, zero because it needs custom handling
+			 0x201c,  // item flags
+			 FOLLOWS, // item images
+
+			 0x252b, // actions
+			 COMPRESSED,
+			 0x320a, // dictionary
+			 0,      // 0x9b53 start_of_room_descriptions, zero because of custom handling
+			 0x20cc, // start_of_room_connections
+			 0x358e, // start_of_messages
+			 0x4215, // start_of_item_descriptions
+			 0x1fa5, // start_of_item_locations
+
+			 0x428, // start_of_system_messages
+			 0x428, // start of directions
+
+			 0x45ff, // start_of_characters
+			 0x4b6f, // start_of_image_data
+			 0x4c23, // image_address_offset
+			 90,     // number_of_pictures
+			 C64B,   // palette
+			 4,      // picture_format_version
+			 0)
+};
diff --git a/engines/glk/scott/globals.cpp b/engines/glk/scott/globals.cpp
index 3a5d6495c22..2b8cfc1dcae 100644
--- a/engines/glk/scott/globals.cpp
+++ b/engines/glk/scott/globals.cpp
@@ -90,6 +90,8 @@ Globals::Globals() : _sys(MAX_SYSMESS), _directions(NUMBER_OF_DIRECTIONS), _extr
 	_md5Index.setVal("0eec511d3cde815c73e5464ab0cdbef9" ,22); // marveladventure
 	_md5Index.setVal("ce5a68cf43b2f29d99c0135b89f4fe31",  0); // misadv1
 	_md5Index.setVal("1e1ff48f80a8220f5ab9d14c975197b8",  6); // midadv2
+	_md5Index.setVal("6bf95a48f366bdf8af3a198c7b723c77", 12); // robin of sherwood
+	_md5Index.setVal("552c95ec15d750cbfa02c1f11dcbca1e", 15); // robin of sherwood
 }
 
 Globals::~Globals() {
diff --git a/engines/glk/scott/globals.h b/engines/glk/scott/globals.h
index a99a8cad09c..a24739c04f3 100644
--- a/engines/glk/scott/globals.h
+++ b/engines/glk/scott/globals.h
@@ -95,6 +95,7 @@ public:
 	int _roomSaved[16];   ///< Range unknown
 	uint32 _bitFlags = 0; ///< Might be >32 flags - I haven't seen >32 yet
 	int _autoInventory = 0;
+	int _animationFlag = 0;
 
 	// sagadraw
 	int _drawToBuffer = 0;
@@ -178,6 +179,9 @@ public:
 	int _retfire = 0xff;
 	int _retspace = 0xff;
 
+	// robin of sherwood]
+	uint8_t *_forestImages = nullptr;
+
 public:
 	Globals();
 	~Globals();
diff --git a/engines/glk/scott/load_game.cpp b/engines/glk/scott/load_game.cpp
index 33428408607..b199b603600 100644
--- a/engines/glk/scott/load_game.cpp
+++ b/engines/glk/scott/load_game.cpp
@@ -46,6 +46,7 @@
 #include "glk/scott/game_specific.h"
 #include "glk/scott/resource.h"
 #include "glk/scott/load_game.h"
+#include "glk/scott/robin_of_sherwood.h"
 
 namespace Glk {
 namespace Scott {
@@ -128,6 +129,12 @@ void loadGameFile(Common::SeekableReadStream *f) {
 	}
 
 	switch (CURRENT_GAME) {
+	case ROBIN_OF_SHERWOOD:
+		loadExtraSherwoodData();
+		break;
+	case ROBIN_OF_SHERWOOD_C64:
+		loadExtraSherwoodData64();
+		break;
 	case HULK_C64:
 	case HULK:
 		for (int i = 0; i < 6; i++) {
diff --git a/engines/glk/scott/resource.cpp b/engines/glk/scott/resource.cpp
index c9952675db7..60600724e5f 100644
--- a/engines/glk/scott/resource.cpp
+++ b/engines/glk/scott/resource.cpp
@@ -899,7 +899,7 @@ int tryLoading(GameInfo info, int dictStart, int loud) {
 			_G(_messages)[ct] = decompressText(ptr, ct);
 			if (loud)
 				debug("Message %d: \"%s\"\n", ct, _G(_messages)[ct].c_str());
-			if (_G(_messages)[ct] == nullptr)
+			if (_G(_messages)[ct].size() == 0)
 				return 0;
 			ct++;
 		}
diff --git a/engines/glk/scott/robin_of_sherwood.cpp b/engines/glk/scott/robin_of_sherwood.cpp
new file mode 100644
index 00000000000..580996d07b8
--- /dev/null
+++ b/engines/glk/scott/robin_of_sherwood.cpp
@@ -0,0 +1,460 @@
+/* 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/>.
+ *
+ */
+
+/*
+ * Based on ScottFree interpreter version 1.14 developed by Swansea
+ * University Computer Society without disassembly of any other game
+ * drivers, only of game databases as permitted by EEC law (for purposes
+ * of compatibility).
+ *
+ * Licensed under GPLv2
+ *
+ * https://github.com/angstsmurf/spatterlight/tree/master/terps/scott
+ */
+
+#include "glk/scott/scott.h"
+#include "glk/scott/types.h"
+#include "glk/scott/globals.h"
+#include "glk/scott/resource.h"
+#include "glk/scott/saga_draw.h"
+#include "glk/scott/decompress_text.h"
+#include "glk/scott/robin_of_sherwood.h"
+
+namespace Glk {
+namespace Scott {
+
+#define WATERFALL_ANIMATION_RATE 15
+
+void animateLightning(int stage);
+
+void sherwoodAction(int p) {
+	event_t ev;
+
+	switch (p) {
+	case 0:
+		// Flash animation
+		_G(_animationFlag) = 1;
+		g_scott->glk_request_timer_events(15);
+
+		while (_G(_animationFlag) < 11) {
+			g_scott->glk_select(&ev);
+			if (ev.type == evtype_Timer) {
+				_G(_animationFlag)++;
+				animateLightning(_G(_animationFlag));
+			}
+		}
+		break;
+	case 1:
+		g_scott->drawImage(0); /* Herne */
+		g_scott->display(_G(_bottomWindow), "\n%s\n", _G(_sys)[HIT_ENTER]);
+		g_scott->hitEnter();
+		_G(_items)[39]._location = 79;
+		g_scott->look();
+		break;
+	case 2:
+		// Climbing tree in forest
+		_G(_savedRoom) = MY_LOC;
+		MY_LOC = 93;
+		g_scott->look();
+		break;
+	default:
+		error("sherwoodAction: Unhandled SherwoodAction %d!", p);
+		break;
+	}
+}
+
+int isForestLocation(void) { return (MY_LOC >= 11 && MY_LOC <= 73); }
+
+#define TREES 0
+#define BUSHES 1
+
+void drawSherwood(int loc) {
+	g_scott->glk_window_clear(_G(_graphics));
+	int subimage_index = 0;
+
+	for (int i = 0; i < loc - 11; i++) {
+		// BUSHES type images are made up of 5 smaller images
+		int skip = 5;
+		if (_G(_forestImages)[subimage_index] < 128)
+			// Those with bit 7 unset have 10 (trees only) or 11 (trees with path)
+			skip = 11;
+		subimage_index += skip;
+	}
+
+	int forest_type = TREES;
+	int subimages;
+
+	// if bit 7 of the image index is set then this image is BUSHES
+	if (_G(_forestImages)[subimage_index] >= 128) {
+		forest_type = BUSHES;
+		subimages = 5;
+		// if the last subimage value is 255, there is no path
+	} else if (_G(_forestImages)[subimage_index + 10] == 0xff) {
+		// Trees only
+		subimages = 10;
+	} else {
+		// Trees with path
+		subimages = 11;
+	}
+
+	int xpos = 0, ypos = 0, image_number;
+
+	for (int i = 0; i < subimages; i++) {
+		if (forest_type == TREES) {
+			if (i >= 8) {
+				if (i == 8) { // Undergrowth
+					ypos = 7;
+					xpos = 0;
+				} else if (i == 9) { // _G(_bottomWindow) path
+					ypos = 10;
+					xpos = 0;
+				} else { // Forward path
+					ypos = 7;
+					xpos = 12;
+				}
+			} else { // Trees (every tree image is 4 characters wide)
+				ypos = 0;
+				xpos = i * 4;
+			}
+		}
+
+		image_number = _G(_forestImages)[subimage_index++] & 127;
+
+		drawSagaPictureAtPos(image_number, xpos, ypos);
+
+		if (forest_type == BUSHES) {
+			xpos += _G(_images)[image_number]._width;
+		}
+	}
+}
+
+void animateWaterfall(int stage) {
+	rectFill(88, 16, 48, 64, _G(_whiteColour));
+	for (int line = 2; line < 10; line++) {
+		for (int col = 11; col < 17; col++) {
+			for (int i = 0; i < 8; i++)
+				for (int j = 0; j < 8; j++)
+					if ((_G(_screenchars)[col + line * 32][i] & (1 << j)) != 0) {
+						int ypos = line * 8 + i + stage;
+						if (ypos > 79)
+							ypos = ypos - 64;
+						putPixel(col * 8 + j, ypos, _G(_blueColour));
+					}
+		}
+	}
+}
+
+void animateWaterfallCave(int stage) {
+	rectFill(248, 24, 8, 64, _G(_whiteColour));
+	for (int line = 3; line < 11; line++) {
+		for (int i = 0; i < 8; i++)
+			for (int j = 0; j < 8; j++)
+				if ((_G(_screenchars)[31 + line * 32][i] & (1 << j)) != 0) {
+					int ypos = line * 8 + i + stage;
+					if (ypos > 87)
+						ypos = ypos - 64;
+					putPixel(248 + j, ypos, _G(_blueColour));
+				}
+	}
+}
+
+void animateLightning(int stage) {
+	// swich blue and bright yellow
+	if (_G(_palChosen) == C64B)
+		switchPalettes(6, 7);
+	else {
+		switchPalettes(1, 14);
+		switchPalettes(9, 6);
+	}
+	drawSagaPictureNumber(77);
+	if (stage == 11) {
+		g_scott->glk_request_timer_events(0);
+	} else if (stage == 3) {
+		g_scott->glk_request_timer_events(700);
+	} else {
+		g_scott->glk_request_timer_events(40);
+	}
+}
+
+void robinOfSherwoodLook(void) {
+	if (!isForestLocation()) {
+		if (_G(_rooms)[MY_LOC]._image == 255) {
+			g_scott->closeGraphicsWindow();
+		} else {
+			g_scott->drawImage(_G(_rooms)[MY_LOC]._image);
+			for (int ct = 0; ct <= _G(_gameHeader)->_numItems; ct++)
+				if (_G(_items)[ct]._image) {
+					if ((_G(_items)[ct]._flag & 127) == MY_LOC && _G(_items)[ct]._location == MY_LOC) {
+						g_scott->drawImage(_G(_items)[ct]._image);
+					}
+				}
+		}
+	}
+
+	if (MY_LOC == 82) // Dummy room where exit from Up a tree goes
+		MY_LOC = _G(_savedRoom);
+	if (MY_LOC == 93) // Up a tree
+		for (int i = 0; i < _G(_gameHeader)->_numItems; i++)
+			if (_G(_items)[i]._location == 93)
+				_G(_items)[i]._location = _G(_savedRoom);
+	if (MY_LOC == 7 && _G(_items)[62]._location == 7) // Left bedroom, open treasure chest
+		g_scott->drawImage(70);
+	if (isForestLocation()) {
+		g_scott->openGraphicsWindow();
+		drawSherwood(MY_LOC);
+
+		if (_G(_items)[36]._location == MY_LOC) {
+			//"Gregory the tax collector with his horse and cart"
+			g_scott->drawImage(15); // Horse and cart
+			g_scott->drawImage(3);  // Sacks of grain
+		}
+		if (_G(_items)[60]._location == MY_LOC || _G(_items)[77]._location == MY_LOC) {
+			// "A serf driving a horse and cart"
+			g_scott->drawImage(15); // Horse and cart
+			g_scott->drawImage(12); // Hay
+		}
+		if (MY_LOC == 73) {
+			// Outlaws camp
+			g_scott->drawImage(36); // Campfire
+		}
+	}
+
+	if (MY_LOC == 86 || MY_LOC == 79) {
+		g_scott->glk_request_timer_events(WATERFALL_ANIMATION_RATE);
+	}
+}
+
+void updateRobinOfSherwoodAnimations(void) {
+	_G(_animationFlag)++;
+	if (_G(_animationFlag) > 63)
+		_G(_animationFlag) = 0;
+	if (MY_LOC == 86 || MY_LOC == 79 || MY_LOC == 84) {
+		/* If we're in room 84, the stone circle, we just */
+		/* want the timer to not switch off */
+		if (MY_LOC == 86) {
+			animateWaterfall(_G(_animationFlag));
+		} else if (MY_LOC == 79) {
+			animateWaterfallCave(_G(_animationFlag));
+		}
+	} else {
+		g_scott->glk_request_timer_events(0);
+	}
+}
+
+GameIDType loadExtraSherwoodData(void) {
+
+#pragma mark room images
+
+	int offset = 0x3d99 + _G(_fileBaselineOffset);
+	uint8_t *ptr;
+	/* Load the room images */
+
+jumpRoomImages:
+	ptr = seekToPos(_G(_entireFile), offset);
+	if (ptr == 0)
+		return UNKNOWN_GAME;
+
+	int ct;
+	Room *rp = &_G(_rooms)[0];
+
+	for (ct = 0; ct <= _G(_gameHeader)->_numRooms; ct++) {
+		rp->_image = *(ptr++);
+		rp++;
+		if (ct == 10) {
+			for (int i = 0; i < 63; i++) {
+				rp++;
+				ct++;
+			}
+		}
+	}
+
+#pragma mark rooms
+
+	ct = 0;
+	rp = &_G(_rooms)[0];
+
+	int actual_room_number = 0;
+
+	ptr = seekToPos(_G(_entireFile), 0x5b7e + _G(_fileBaselineOffset));
+	if (ptr == 0)
+		return UNKNOWN_GAME;
+
+	do {
+		rp->_text = decompressText(ptr, ct);
+		rp->_text.toLowercase();
+		ct++;
+		actual_room_number++;
+		if (ct == 11) {
+			for (int i = 0; i < 61; i++) {
+				rp++;
+				rp->_text = "in Sherwood Forest";
+				actual_room_number++;
+			}
+		}
+		rp++;
+	} while (ct < 33);
+
+	for (int i = I_DONT_UNDERSTAND; i <= THATS_BEYOND_MY_POWER; i++)
+		_G(_sys)[i] = _G(_systemMessages)[4 - I_DONT_UNDERSTAND + i];
+
+	for (int i = YOU_SEE; i <= HIT_ENTER; i++)
+		_G(_sys)[i] = _G(_systemMessages)[15 - YOU_SEE + i];
+
+	_G(_sys)[OK] = _G(_systemMessages)[2];
+	_G(_sys)[TAKEN] = _G(_systemMessages)[2];
+	_G(_sys)[DROPPED] = _G(_systemMessages)[2];
+	_G(_sys)[PLAY_AGAIN] = _G(_systemMessages)[3];
+	_G(_sys)[YOURE_CARRYING_TOO_MUCH] = _G(_systemMessages)[21];
+	_G(_sys)[YOU_CANT_GO_THAT_WAY] = _G(_systemMessages)[12];
+	_G(_sys)[YOU_ARE] = _G(_systemMessages)[13];
+	_G(_sys)[EXITS_DELIMITER] = " ";
+	_G(_sys)[MESSAGE_DELIMITER] = ". ";
+
+	ptr = seekToPos(_G(_entireFile), 0x3b6e + _G(_fileBaselineOffset));
+	if (ptr == 0)
+		return UNKNOWN_GAME;
+
+	int cells = 555;
+	_G(_forestImages) = new uint8_t[cells];
+
+	for (int i = 0; i < cells; i++)
+		_G(_forestImages)[i] = *(ptr++);
+
+	return ROBIN_OF_SHERWOOD;
+}
+
+GameIDType loadExtraSherwoodData64(void) {
+
+	//    white_colour = 1;
+	//    blue = 6;
+
+#pragma mark room images
+
+	int offset = 0x1ffd + _G(_fileBaselineOffset);
+	uint8_t *ptr;
+	/* Load the room images */
+
+jumpHereRoomImages:
+	ptr = seekToPos(_G(_entireFile), offset);
+	if (ptr == 0)
+		return UNKNOWN_GAME;
+
+	int ct;
+	Room *rp = &_G(_rooms)[0];
+
+	for (ct = 0; ct <= _G(_gameHeader)->_numRooms; ct++) {
+		rp->_image = *(ptr++);
+		rp++;
+
+		if (ct == 10) {
+			for (int i = 0; i < 63; i++) {
+				rp++;
+				ct++;
+			}
+		}
+	}
+
+#pragma mark rooms
+
+	ct = 0;
+	rp = &_G(_rooms)[0];
+
+	int actual_room_number = 0;
+
+	offset = 0x402e + _G(_fileBaselineOffset);
+
+	ptr = seekToPos(_G(_entireFile), offset);
+	if (ptr == 0)
+		return UNKNOWN_GAME;
+
+	do {
+		rp->_text = decompressText(ptr, ct);
+		rp->_text.toLowercase();
+		ct++;
+		actual_room_number++;
+		if (ct == 11) {
+			for (int i = 0; i < 61; i++) {
+				rp++;
+				rp->_text = "in Sherwood Forest";
+				actual_room_number++;
+			}
+		}
+		rp++;
+	} while (ct < 33);
+
+	SysMessageType messagekey[] = {NORTH,
+								   SOUTH,
+								   EAST,
+								   WEST,
+								   UP,
+								   DOWN,
+								   EXITS,
+								   YOU_SEE,
+								   YOU_ARE,
+								   HIT_ENTER,
+								   YOU_CANT_GO_THAT_WAY,
+								   OK,
+								   WHAT_NOW,
+								   HUH,
+								   YOU_HAVE_IT,
+								   TAKEN,
+								   DROPPED,
+								   YOU_HAVENT_GOT_IT,
+								   INVENTORY,
+								   YOU_DONT_SEE_IT,
+								   THATS_BEYOND_MY_POWER,
+								   DIRECTION,
+								   YOURE_CARRYING_TOO_MUCH,
+								   PLAY_AGAIN,
+								   RESUME_A_SAVED_GAME,
+								   YOU_CANT_DO_THAT_YET,
+								   I_DONT_UNDERSTAND,
+								   NOTHING};
+
+	for (int i = 0; i < 26; i++) {
+		_G(_sys)[messagekey[i]] = _G(_systemMessages)[i];
+	}
+
+	_G(_sys)[HIT_ENTER] = _G(_systemMessages)[30];
+	_G(_sys)[WHAT] = _G(_systemMessages)[13];
+
+	_G(_sys)[EXITS_DELIMITER] = " ";
+	_G(_sys)[MESSAGE_DELIMITER] = ". ";
+
+	offset = 0x2300 + _G(_fileBaselineOffset);
+jumpForestImages:
+
+	ptr = seekToPos(_G(_entireFile), offset);
+	if (ptr == 0)
+		return UNKNOWN_GAME;
+
+	int cells = 555;
+	_G(_forestImages) = new uint8_t[cells];
+
+	for (int i = 0; i < cells; i++) {
+		_G(_forestImages)[i] = *(ptr++);
+	}
+
+	return ROBIN_OF_SHERWOOD_C64;
+}
+
+} // End of namespace Scott
+} // End of namespace Glk
diff --git a/engines/glk/scott/robin_of_sherwood.h b/engines/glk/scott/robin_of_sherwood.h
new file mode 100644
index 00000000000..d6bf9eaceb7
--- /dev/null
+++ b/engines/glk/scott/robin_of_sherwood.h
@@ -0,0 +1,51 @@
+/* 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/>.
+ *
+ */
+
+/*
+ * Based on ScottFree interpreter version 1.14 developed by Swansea
+ * University Computer Society without disassembly of any other game
+ * drivers, only of game databases as permitted by EEC law (for purposes
+ * of compatibility).
+ *
+ * Licensed under GPLv2
+ *
+ * https://github.com/angstsmurf/spatterlight/tree/master/terps/scott
+ */
+
+#ifndef GLK_SCOTT_ROBIN_OF_SHERWOOD_H
+#define GLK_SCOTT_ROBIN_OF_SHERWOOD_H
+
+#include "glk/scott/definitions.h"
+
+namespace Glk {
+namespace Scott {
+
+void updateRobinOfSherwoodAnimations();
+void robinOfSherwoodLook();
+GameIDType loadExtraSherwoodData();
+GameIDType loadExtraSherwoodData64();
+int isForestLocation();
+void sherwoodAction(int p);
+
+} // End of namespace Scott
+} // End of namespace Glk
+
+#endif
diff --git a/engines/glk/scott/saga_draw.cpp b/engines/glk/scott/saga_draw.cpp
index aa9f279c69f..84da8b02148 100644
--- a/engines/glk/scott/saga_draw.cpp
+++ b/engines/glk/scott/saga_draw.cpp
@@ -338,6 +338,12 @@ void drawSagaPictureNumber(int pictureNumber) {
 	drawSagaPictureFromData(img._imageData, img._width, img._height, img._xOff, img._yOff);
 }
 
+void drawSagaPictureAtPos(int pictureNumber, int x, int y) {
+	Image img = _G(_images)[pictureNumber];
+
+	drawSagaPictureFromData(img._imageData, img._width, img._height, x, y);
+}
+
 void sagaSetup(size_t imgOffset) {
 	int32_t i, y;
 
@@ -468,6 +474,22 @@ void rectFill(int32_t x, int32_t y, int32_t width, int32_t height, int32_t color
 							   y * _G(_pixelSize) + yOffset, width * _G(_pixelSize), height * _G(_pixelSize));
 }
 
+void switchPalettes(int pal1, int pal2) {
+	uint8_t temp[3];
+
+	temp[0] = _G(_pal)[pal1][0];
+	temp[1] = _G(_pal)[pal1][1];
+	temp[2] = _G(_pal)[pal1][2];
+
+	_G(_pal)[pal1][0] = _G(_pal)[pal2][0];
+	_G(_pal)[pal1][1] = _G(_pal)[pal2][1];
+	_G(_pal)[pal1][2] = _G(_pal)[pal2][2];
+
+	_G(_pal)[pal2][0] = temp[0];
+	_G(_pal)[pal2][1] = temp[1];
+	_G(_pal)[pal2][2] = temp[2];
+}
+
 void setColor(int32_t index, RGB *colour) {
 	_G(_pal)[index][0] = (*colour)[0];
 	_G(_pal)[index][1] = (*colour)[1];
diff --git a/engines/glk/scott/saga_draw.h b/engines/glk/scott/saga_draw.h
index df89a1c1361..d02a77c4576 100644
--- a/engines/glk/scott/saga_draw.h
+++ b/engines/glk/scott/saga_draw.h
@@ -52,11 +52,13 @@ typedef RGB PALETTE[16];
 
 uint8_t *drawSagaPictureFromData(uint8_t *dataptr, int xSize, int ySize, int xOff, int yOff);
 void drawSagaPictureNumber(int pictureNumber);
+void drawSagaPictureAtPos(int pictureNumber, int x, int y);
 
 void sagaSetup(size_t imgOffset);
 
 void putPixel(glsi32 x, glsi32 y, int32_t color);
 void rectFill(int32_t x, int32_t y, int32_t width, int32_t height, int32_t color);
+void switchPalettes(int pal1, int pal2);
 void definePalette();
 
 int32_t remap(int32_t color);
diff --git a/engines/glk/scott/scott.cpp b/engines/glk/scott/scott.cpp
index 6bb148ee540..93d49936a46 100644
--- a/engines/glk/scott/scott.cpp
+++ b/engines/glk/scott/scott.cpp
@@ -45,6 +45,7 @@
 #include "glk/scott/line_drawing.h"
 #include "glk/scott/saga_draw.h"
 #include "glk/scott/restore_state.h"
+#include "glk/scott/robin_of_sherwood.h"
 
 namespace Glk {
 namespace Scott {
@@ -285,8 +286,7 @@ void Scott::updates(event_t ev) {
 	} else if (ev.type == evtype_Timer) {
 		switch (_G(_game->_type)) {
 		case SHERWOOD_VARIANT:
-			// TODO
-			// UpdateRobinOfSherwoodAnimations();
+			updateRobinOfSherwoodAnimations();
 			break;
 		case GREMLINS_VARIANT:
 			// TODO
@@ -1130,8 +1130,7 @@ ActionResultType Scott::performLine(int ct) {
 					break;
 				case ROBIN_OF_SHERWOOD:
 				case ROBIN_OF_SHERWOOD_C64:
-					// TODO
-					// SherwoodAction(p);
+					sherwoodAction(p);
 					break;
 				case GREMLINS:
 				case GREMLINS_SPANISH:
@@ -1727,8 +1726,7 @@ void Scott::drawRoomImage() {
 		return;
 	case ROBIN_OF_SHERWOOD:
 	case ROBIN_OF_SHERWOOD_C64:
-		// TODO
-		// RobinOfSherwoodLook();
+		robinOfSherwoodLook();
 		return;
 	case HULK:
 	case HULK_C64:
diff --git a/engines/glk/scott/scott.h b/engines/glk/scott/scott.h
index 09dca6814f4..c5497f1a8d8 100644
--- a/engines/glk/scott/scott.h
+++ b/engines/glk/scott/scott.h
@@ -173,7 +173,6 @@ private:
 	Common::String readString(Common::SeekableReadStream *f);
 	void loadDatabase(Common::SeekableReadStream *f, bool loud);
 	void outputNumber(int a);
-	void look(void);
 	int whichWord(const char *word, const Common::StringArray &list);
 
 	ActionResultType performLine(int ct);
@@ -187,9 +186,7 @@ private:
 	void listExitsSpectrumStyle();
 	void listInventoryInUpperWindow();
 	int itemEndsWithPeriod(int item);
-	void closeGraphicsWindow();
 	winid_t findGlkWindowWithRock(glui32 rock);
-	void openGraphicsWindow();
 	glui32 optimalPictureSize(uint *width, uint *height);
 	void openTopWindow();
 	void cleanupAndExit();
@@ -227,6 +224,9 @@ public:
 	void updates(event_t ev);
 	const char *mapSynonym(int noun);
 	int performExtraCommand(int extraStopTime);
+	void look(void);
+	void openGraphicsWindow();
+	void closeGraphicsWindow();
 
 public:
 	/**


Commit: 7194234ea6baf5847a6784affb0fcabf7ad5bc93
    https://github.com/scummvm/scummvm/commit/7194234ea6baf5847a6784affb0fcabf7ad5bc93
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Update game detection to use entire file for MD5 calculation of .D64 games

Changed paths:
    engines/glk/metaengine.cpp
    engines/glk/scott/detection.cpp
    engines/glk/scott/detection_tables.h
    engines/glk/scott/globals.cpp


diff --git a/engines/glk/metaengine.cpp b/engines/glk/metaengine.cpp
index 57374e15319..ac92410a2ae 100644
--- a/engines/glk/metaengine.cpp
+++ b/engines/glk/metaengine.cpp
@@ -192,7 +192,11 @@ Common::Error GlkMetaEngine::createInstance(OSystem *syst, Engine **engine) {
 	if (!f.open(Common::FSNode(ConfMan.get("path")).getChild(gameDesc._filename)))
 		return Common::kNoGameDataFoundError;
 
-	gameDesc._md5 = Common::computeStreamMD5AsString(f, 5000);
+	Common::String fileName = f.getName();
+	if (fileName.hasSuffixIgnoreCase(".D64"))
+		gameDesc._md5 = Common::computeStreamMD5AsString(f);
+	else
+		gameDesc._md5 = Common::computeStreamMD5AsString(f, 5000);
 	f.close();
 
 	// Create the correct engine
diff --git a/engines/glk/scott/detection.cpp b/engines/glk/scott/detection.cpp
index 97f2122f560..221bc70dc46 100644
--- a/engines/glk/scott/detection.cpp
+++ b/engines/glk/scott/detection.cpp
@@ -73,7 +73,12 @@ bool ScottMetaEngine::detectGames(const Common::FSList &fslist, DetectedGames &g
 		Common::File gameFile;
 		if (!gameFile.open(*file))
 			continue;
-		Common::String md5 = Common::computeStreamMD5AsString(gameFile, 5000);
+		Common::String md5;
+		if (filename.hasSuffixIgnoreCase(".D64"))
+			md5 = Common::computeStreamMD5AsString(gameFile);
+		else
+			md5 = Common::computeStreamMD5AsString(gameFile, 5000);
+
 		size_t filesize = (size_t)gameFile.size();
 		gameFile.seek(0);
 		isBlorb = Blorb::isBlorb(gameFile, ID_SAAI);
diff --git a/engines/glk/scott/detection_tables.h b/engines/glk/scott/detection_tables.h
index 446897febe6..ea0514bec78 100644
--- a/engines/glk/scott/detection_tables.h
+++ b/engines/glk/scott/detection_tables.h
@@ -163,6 +163,7 @@ const GlkDetectionEntry SCOTT_GAMES[] = {
 
 	// ZX Spectrum games
 	DT_ENTRY1("marveladventure", "ZXSpectrum", "0eec511d3cde815c73e5464ab0cdbef9", 40727),
+	DT_ENTRY1("gremlins",		 "ZXSpectrum", "4200b260b484a3a9766d587def3113a2", 45332),
 
 	// 11 Mysterious Adventures
 	DT_ENTRY1("goldenbaton",	"ZXSpectrum", "cb7dadc9d5f8bce453b9139265e4dd7d", 32060),
@@ -178,11 +179,12 @@ const GlkDetectionEntry SCOTT_GAMES[] = {
 	DT_ENTRY1("waxworks11",		"ZXSpectrum", "6c6fbbbb50032463a6ea71c6750ea1f5", 32662),
 
 	// C64 Games
-	DT_ENTRY1("robinofsherwood", "C64", "6bf95a48f366bdf8af3a198c7b723c77", 174848),
+	DT_ENTRY1("robinofsherwood", "C64", "10109d9776b9372f9c768b53a664b113", 174848),
 	DT_ENTRY1("robinofsherwood", "C64", "552c95ec15d750cbfa02c1f11dcbca1e", 36278),
+
 	// 11 Mysterious Adventures
-	DT_ENTRY1("mysadv1", "C64", "ce5a68cf43b2f29d99c0135b89f4fe31", 174848),
-	DT_ENTRY1("mysadv2", "C64", "1e1ff48f80a8220f5ab9d14c975197b8", 174848),
+	DT_ENTRY1("mysadv1", "C64", "b4d8fc4eabed4f2400717303561ad0fa", 174848),
+	DT_ENTRY1("mysadv2", "C64", "3ce5ea1a0473244bf469fd3c51f1dc48", 174848),
 	DT_END_MARKER
 };
 
diff --git a/engines/glk/scott/globals.cpp b/engines/glk/scott/globals.cpp
index 2b8cfc1dcae..f27aaf89f27 100644
--- a/engines/glk/scott/globals.cpp
+++ b/engines/glk/scott/globals.cpp
@@ -88,9 +88,9 @@ Globals::Globals() : _sys(MAX_SYSMESS), _directions(NUMBER_OF_DIRECTIONS), _extr
 	_md5Index.setVal("afde056c152de79ea20453c42a2d08af", 18); // 10indians
 	_md5Index.setVal("6c6fbbbb50032463a6ea71c6750ea1f5", 20); // waxworks11
 	_md5Index.setVal("0eec511d3cde815c73e5464ab0cdbef9" ,22); // marveladventure
-	_md5Index.setVal("ce5a68cf43b2f29d99c0135b89f4fe31",  0); // misadv1
-	_md5Index.setVal("1e1ff48f80a8220f5ab9d14c975197b8",  6); // midadv2
-	_md5Index.setVal("6bf95a48f366bdf8af3a198c7b723c77", 12); // robin of sherwood
+	_md5Index.setVal("b4d8fc4eabed4f2400717303561ad0fa",  0); // misadv1
+	_md5Index.setVal("3ce5ea1a0473244bf469fd3c51f1dc48",  6); // midadv2
+	_md5Index.setVal("10109d9776b9372f9c768b53a664b113", 12); // robin of sherwood
 	_md5Index.setVal("552c95ec15d750cbfa02c1f11dcbca1e", 15); // robin of sherwood
 }
 


Commit: 08ae841dc92016ac0db8564215b278d080763693
    https://github.com/scummvm/scummvm/commit/08ae841dc92016ac0db8564215b278d080763693
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Add missing return statement

Changed paths:
    engines/glk/scott/unp64/6502_emu.cpp


diff --git a/engines/glk/scott/unp64/6502_emu.cpp b/engines/glk/scott/unp64/6502_emu.cpp
index 87e427f489b..ae46e960bff 100644
--- a/engines/glk/scott/unp64/6502_emu.cpp
+++ b/engines/glk/scott/unp64/6502_emu.cpp
@@ -1334,6 +1334,9 @@ int nextInst(CpuCtx* r) {
 			}
 		}
 	}
+	if (WriteToIO) {
+		return 0;
+	}
 
 	info->_op->_f(r, mode, arg);
 	r->_cycles += info->_cycles;


Commit: ac75abb20a5c881d6d71ca990db0e7b4147caeac
    https://github.com/scummvm/scummvm/commit/ac75abb20a5c881d6d71ca990db0e7b4147caeac
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Use READ_LE_UINT16 instead of READ_LE_INT16

Changed paths:
    engines/glk/scott/unp64/scanners/action_packer.cpp
    engines/glk/scott/unp64/scanners/byte_boiler.cpp
    engines/glk/scott/unp64/scanners/caution.cpp
    engines/glk/scott/unp64/scanners/ccs.cpp
    engines/glk/scott/unp64/scanners/cruel.cpp
    engines/glk/scott/unp64/scanners/eca.cpp
    engines/glk/scott/unp64/scanners/exomizer.cpp
    engines/glk/scott/unp64/scanners/expert.cpp
    engines/glk/scott/unp64/scanners/master_compressor.cpp
    engines/glk/scott/unp64/scanners/megabyte.cpp
    engines/glk/scott/unp64/scanners/pu_crunch.cpp
    engines/glk/scott/unp64/scanners/section8.cpp
    engines/glk/scott/unp64/scanners/tbc_multicomp.cpp
    engines/glk/scott/unp64/scanners/tcs_crunch.cpp
    engines/glk/scott/unp64/scanners/xtc.cpp


diff --git a/engines/glk/scott/unp64/scanners/action_packer.cpp b/engines/glk/scott/unp64/scanners/action_packer.cpp
index 016a5a74c3f..815d7fc3543 100644
--- a/engines/glk/scott/unp64/scanners/action_packer.cpp
+++ b/engines/glk/scott/unp64/scanners/action_packer.cpp
@@ -39,9 +39,9 @@ void scnActionPacker(UnpStr *unp) {
 			(*(unsigned int *)(mem + 0x84b) == 0x03D00120)) {
 			unp->_depAdr = 0x110;
 			unp->_forced = 0x811;
-			unp->_strMem = READ_LE_INT16(&mem[0x848]);
+			unp->_strMem = READ_LE_UINT16(&mem[0x848]);
 			unp->_fEndAf = 0x120;
-			unp->_retAdr = READ_LE_INT16(&mem[0x863]);
+			unp->_retAdr = READ_LE_UINT16(&mem[0x863]);
 			unp->_idFlag = 1;
 			return;
 		}
diff --git a/engines/glk/scott/unp64/scanners/byte_boiler.cpp b/engines/glk/scott/unp64/scanners/byte_boiler.cpp
index a3c3fb6d49a..8e87dec2ab9 100644
--- a/engines/glk/scott/unp64/scanners/byte_boiler.cpp
+++ b/engines/glk/scott/unp64/scanners/byte_boiler.cpp
@@ -35,12 +35,12 @@ void scnByteBoiler(UnpStr *unp) {
 	if (unp->_depAdr == 0) {
 		if ((*(unsigned int *)(mem + 0x813) == 0xE800F09D) &&
 			(*(unsigned int *)(mem + 0x818) == 0x014E4CF7)) {
-			p = READ_LE_INT16(&mem[0x811]);
+			p = READ_LE_UINT16(&mem[0x811]);
 			if (*(unsigned int *)(mem + p + 1) == 0x02D0FAA5) {
 				unp->_depAdr = 0x14e;
 				unp->_forced = 0x80b;
-				unp->_retAdr = READ_LE_INT16(&mem[p + 0x5c]);
-				unp->_endAdr = READ_LE_INT16(&mem[p + 0x0e]);
+				unp->_retAdr = READ_LE_UINT16(&mem[p + 0x5c]);
+				unp->_endAdr = READ_LE_UINT16(&mem[p + 0x0e]);
 				unp->_endAdr++;
 				unp->_fStrAf = 0xfe;
 				unp->_idFlag = 1;
@@ -52,15 +52,15 @@ void scnByteBoiler(UnpStr *unp) {
 	if (unp->_depAdr == 0) {
 		if ((*(unsigned int *)(mem + 0x80b) == 0xA97800A2) &&
 			(*(unsigned int *)(mem + 0x815) == 0x4C01E6D0)) {
-			q = READ_LE_INT16(&mem[0x819]);
+			q = READ_LE_UINT16(&mem[0x819]);
 			if ((*(unsigned int *)(mem + q + 3) == 0xE800F09D) &&
 				(*(unsigned int *)(mem + q + 8) == 0x014E4CF7)) {
-				p = READ_LE_INT16(&mem[q + 1]);
+				p = READ_LE_UINT16(&mem[q + 1]);
 				if (*(unsigned int *)(mem + p + 1) == 0x02D0FAA5) {
 					unp->_depAdr = 0x14e;
 					unp->_forced = 0x80b;
-					unp->_retAdr = READ_LE_INT16(&mem[p + 0x5c]); 
-					unp->_endAdr = READ_LE_INT16(&mem[p + 0x0e]); 
+					unp->_retAdr = READ_LE_UINT16(&mem[p + 0x5c]); 
+					unp->_endAdr = READ_LE_UINT16(&mem[p + 0x0e]); 
 					unp->_endAdr++;
 					unp->_fStrAf = 0xfe;
 					unp->_idFlag = 1;
@@ -73,13 +73,13 @@ void scnByteBoiler(UnpStr *unp) {
 	if (unp->_depAdr == 0) {
 		if ((*(unsigned int *)(mem + 0x813) == 0xE800F09D) &&
 			(*(unsigned int *)(mem + 0x818) == 0x01bf4CF7)) {
-			p = READ_LE_INT16(&mem[0x811]); 
+			p = READ_LE_UINT16(&mem[0x811]); 
 			if ((*(unsigned int *)(mem + p + 1) == 0x02D0FAA5) &&
 				(*(unsigned int *)(mem + p + 0xdd) == 0x014e4c01)) {
 				unp->_depAdr = 0x14e;
 				unp->_forced = 0x80b;
-				unp->_retAdr = READ_LE_INT16(&mem[p + 0x5c]); 
-				unp->_endAdr = READ_LE_INT16(&mem[p + 0x0e]); 
+				unp->_retAdr = READ_LE_UINT16(&mem[p + 0x5c]); 
+				unp->_endAdr = READ_LE_UINT16(&mem[p + 0x0e]); 
 				unp->_endAdr++;
 				unp->_fStrAf = 0xfe;
 				unp->_idFlag = 1;
diff --git a/engines/glk/scott/unp64/scanners/caution.cpp b/engines/glk/scott/unp64/scanners/caution.cpp
index b300e009607..aa2becedd35 100644
--- a/engines/glk/scott/unp64/scanners/caution.cpp
+++ b/engines/glk/scott/unp64/scanners/caution.cpp
@@ -40,8 +40,8 @@ void scnCaution(UnpStr *unp) {
 			(*(unsigned int *)(mem + 0x844) == 0xAC00334C)) {
 			unp->_forced = 0x801;
 			unp->_depAdr = 0x28;
-			unp->_retAdr = READ_LE_INT16(&mem[0x86b]);
-			unp->_endAdr = READ_LE_INT16(&mem[0x85a]);
+			unp->_retAdr = READ_LE_UINT16(&mem[0x86b]);
+			unp->_endAdr = READ_LE_UINT16(&mem[0x85a]);
 			unp->_fStrAf = mem[0x863];
 			unp->_strAdC = EA_ADDFF | 0xffff;
 			unp->_idFlag = 1;
@@ -58,16 +58,16 @@ void scnCaution(UnpStr *unp) {
 			unp->_forced = 0x80b;
 			unp->_depAdr = 0x01a;
 			if (mem[0x80e] == 0x69) {
-				unp->_retAdr = READ_LE_INT16(&mem[0x842]);
-				unp->_endAdr = READ_LE_INT16(&mem[0x850]);
+				unp->_retAdr = READ_LE_UINT16(&mem[0x842]);
+				unp->_endAdr = READ_LE_UINT16(&mem[0x850]);
 				unp->_endAdr += 0x100;
 				unp->_fStrAf = 0x4f;
 				unp->_strAdC = 0xffff | EA_USE_Y;
 				unp->_idFlag = 1;
 				return;
 			} else if (mem[0x80e] == 0x6c) {
-				unp->_retAdr = READ_LE_INT16(&mem[0x844]);
-				unp->_endAdr = READ_LE_INT16(&mem[0x84e]);
+				unp->_retAdr = READ_LE_UINT16(&mem[0x844]);
+				unp->_endAdr = READ_LE_UINT16(&mem[0x84e]);
 				unp->_endAdr++;
 				unp->_fStrAf = 0x4d;
 				unp->_idFlag = 1;
@@ -84,8 +84,8 @@ void scnCaution(UnpStr *unp) {
 			(*(unsigned int *)(mem + 0x80d) == 0x00024CF8)) {
 			unp->_forced = 0x801;
 			unp->_depAdr = 0x2;
-			unp->_retAdr = READ_LE_INT16(&mem[0x83b]);
-			unp->_endAdr = READ_LE_INT16(&mem[0x845]);
+			unp->_retAdr = READ_LE_UINT16(&mem[0x83b]);
+			unp->_endAdr = READ_LE_UINT16(&mem[0x845]);
 			unp->_endAdr++;
 			unp->_fStrAf = mem[0x849];
 			// unp->_StrAdC=0xffff;
@@ -102,8 +102,8 @@ void scnCaution(UnpStr *unp) {
 			(*(unsigned int *)(mem + 0x80d) == 0x00104CF8)) {
 			unp->_forced = 0x801;
 			unp->_depAdr = 0x10;
-			unp->_retAdr = READ_LE_INT16(&mem[0x839]); 
-			unp->_endAdr = READ_LE_INT16(&mem[0x847]);
+			unp->_retAdr = READ_LE_UINT16(&mem[0x839]); 
+			unp->_endAdr = READ_LE_UINT16(&mem[0x847]);
 			unp->_endAdr += 0x100;
 			unp->_fStrAf = 0x46;
 			unp->_strAdC = 0xffff | EA_USE_Y;
@@ -120,8 +120,8 @@ void scnCaution(UnpStr *unp) {
 			(*(unsigned int *)(mem + 0x81d) == 0xB9034D4C)) {
 			unp->_forced = 0x80d;
 			unp->_depAdr = 0x34d;
-			unp->_retAdr = READ_LE_INT16(&mem[0x87f]);
-			unp->_endAdr = READ_LE_INT16(&mem[0x88d]);
+			unp->_retAdr = READ_LE_UINT16(&mem[0x87f]);
+			unp->_endAdr = READ_LE_UINT16(&mem[0x88d]);
 			unp->_fStrAf = 0x3ba;
 			unp->_strAdC = EA_ADDFF | 0xffff;
 			unp->_idFlag = 1;
diff --git a/engines/glk/scott/unp64/scanners/ccs.cpp b/engines/glk/scott/unp64/scanners/ccs.cpp
index 0808c7b4b70..be2a00f7e2e 100644
--- a/engines/glk/scott/unp64/scanners/ccs.cpp
+++ b/engines/glk/scott/unp64/scanners/ccs.cpp
@@ -43,10 +43,10 @@ void scnCCS(UnpStr *unp) {
 			unp->_depAdr = 0x0ff;
 			unp->_fEndAf = 0x2d;
 			unp->_endAdC = 0xffff;
-			unp->_retAdr = READ_LE_INT16(&mem[0x8ed]);
+			unp->_retAdr = READ_LE_UINT16(&mem[0x8ed]);
 			if (unp->_retAdr == 0xa659) {
 				mem[0x8ec] = 0x2c;
-				unp->_retAdr = READ_LE_INT16(&mem[0x8f0]);
+				unp->_retAdr = READ_LE_UINT16(&mem[0x8f0]);
 			}
 			unp->_idFlag = 1;
 			return;
@@ -62,10 +62,10 @@ void scnCCS(UnpStr *unp) {
 				unp->_forced = 0x80b;
 			unp->_depAdr = 0x100;
 			unp->_endAdr = 0xae;
-			unp->_retAdr = READ_LE_INT16(&mem[0x8f1]);
+			unp->_retAdr = READ_LE_UINT16(&mem[0x8f1]);
 			if (unp->_retAdr == 0xa659) {
 				mem[0x8f0] = 0x2c;
-				unp->_retAdr = READ_LE_INT16(&mem[0x8f4]);
+				unp->_retAdr = READ_LE_UINT16(&mem[0x8f4]);
 			}
 			unp->_idFlag = 1;
 			return;
@@ -119,7 +119,7 @@ void scnCCS(UnpStr *unp) {
 				unp->_forced = 0x822;
 			unp->_depAdr = 0x0ff;
 			unp->_fEndBf = 0x39;
-			unp->_retAdr = READ_LE_INT16(&mem[0x8ea]);
+			unp->_retAdr = READ_LE_UINT16(&mem[0x8ea]);
 			unp->_idFlag = 1;
 			return;
 		}
@@ -135,7 +135,7 @@ void scnCCS(UnpStr *unp) {
 			unp->_depAdr = 0x0ff;
 			unp->_fEndAf = 0x39;
 			unp->_endAdC = 0xffff;
-			unp->_retAdr = READ_LE_INT16(&mem[0x8b3]);
+			unp->_retAdr = READ_LE_UINT16(&mem[0x8b3]);
 			unp->_idFlag = 1;
 			return;
 		}
@@ -153,11 +153,11 @@ void scnCCS(UnpStr *unp) {
 			// which is read at $0039/3a by basic, as end address,
 			// then can set arbitrarily $2d/$ae pointers after unpack.
 			// unp->_fEndAf=0x2d;
-			unp->_endAdr = READ_LE_INT16(&mem[0x803]);
+			unp->_endAdr = READ_LE_UINT16(&mem[0x803]);
 			unp->_endAdr++;
 			if (*(unsigned int *)(mem + 0x87f) == 0x4CA65920)
 				mem[0x87f] = 0x2c;
-			unp->_retAdr = READ_LE_INT16(&mem[0x883]);
+			unp->_retAdr = READ_LE_UINT16(&mem[0x883]);
 			unp->_idFlag = 1;
 			return;
 		}
@@ -193,10 +193,10 @@ void scnCCS(UnpStr *unp) {
 			unp->_depAdr = 0x0ff;
 			unp->_fEndAf = 0x2d;
 			unp->_endAdC = 0xffff;
-			unp->_retAdr = READ_LE_INT16(&mem[0x8ed]);
+			unp->_retAdr = READ_LE_UINT16(&mem[0x8ed]);
 			if (unp->_retAdr == 0xa659) {
 				mem[0x8ec] = 0x2c;
-				unp->_retAdr = READ_LE_INT16(&mem[0x8f0]);
+				unp->_retAdr = READ_LE_UINT16(&mem[0x8f0]);
 			}
 			unp->_idFlag = 1;
 			return;
diff --git a/engines/glk/scott/unp64/scanners/cruel.cpp b/engines/glk/scott/unp64/scanners/cruel.cpp
index e2e3aa78a65..636a41ce594 100644
--- a/engines/glk/scott/unp64/scanners/cruel.cpp
+++ b/engines/glk/scott/unp64/scanners/cruel.cpp
@@ -38,14 +38,14 @@ void scnCruel(UnpStr *unp) {
 			((*(unsigned int *)(mem + 0x813) & 0xfffffeff) == 0xC800FA99) &&
 			(*(unsigned short int *)(mem + 0x818) == 0x4CF7)) {
 			if (mem[0x814] == 0xFA) {
-				p = READ_LE_INT16(&mem[0x811]); // mem[0x811] | mem[0x812] << 8;
+				p = READ_LE_UINT16(&mem[0x811]); // mem[0x811] | mem[0x812] << 8;
 				if (*(unsigned int *)(mem + p + 9) == 0xC8071C99) {
-					unp->_endAdr = READ_LE_INT16(&mem[p + 2]); // mem[p + 2] | mem[p + 3] << 8;
+					unp->_endAdr = READ_LE_UINT16(&mem[p + 2]); // mem[p + 2] | mem[p + 3] << 8;
 					unp->_depAdr = 0x100;
 					if (unp->_info->_run == -1)
 						unp->_forced = 0x80b;
 					unp->_fStrAf = 0xfc;
-					q = READ_LE_INT16(&mem[p + 7]); // mem[p + 7] | mem[p + 8] << 8;
+					q = READ_LE_UINT16(&mem[p + 7]); // mem[p + 7] | mem[p + 8] << 8;
 					if ((mem[q + 0x8e] == 0xc6) && (mem[q + 0x8f] == 0x01) &&
 						(mem[q + 0x93] == 0xe6) && (mem[q + 0x94] == 0x01)) {
 						mem[q + 0x90] = 0x2c;
@@ -54,7 +54,7 @@ void scnCruel(UnpStr *unp) {
 					   be anything < $07e8
 					*/
 					// unp->_retAdr=0x7e8;
-					q = READ_LE_INT16(&mem[p + 7]); // mem[p + 7] | mem[p + 8] << 8;
+					q = READ_LE_UINT16(&mem[p + 7]); // mem[p + 7] | mem[p + 8] << 8;
 					if (mem[q + 0x3c] == 0x4c) {
 						/* v2.2/dynamix, v2.5/cross, v2.5/crest */
 						strtmp = *(unsigned short int *)(mem + q + 0x3d);
@@ -95,18 +95,18 @@ void scnCruel(UnpStr *unp) {
 				   v1.0 works only with some old AR cart (unless patched ;)
 				   v1.5 is infact more common
 				*/
-				p = READ_LE_INT16(&mem[0x811]); // mem[0x811] | mem[0x812] << 8;
+				p = READ_LE_UINT16(&mem[0x811]); // mem[0x811] | mem[0x812] << 8;
 				if (*(unsigned int *)(mem + p + 7) == 0xC8071C99) {
-					unp->_endAdr = READ_LE_INT16(&mem[p + 3]); // mem[p + 3] | mem[p + 4] << 8;
+					unp->_endAdr = READ_LE_UINT16(&mem[p + 3]); // mem[p + 3] | mem[p + 4] << 8;
 					unp->_depAdr = 0x100;
 					unp->_forced = 0x80b;
 					unp->_fStrAf = 0xfe;
 					if ((mem[p + 0x93] == 0x4c) && (mem[p + 0xa1] == 0x4c)) {
-						unp->_retAdr = READ_LE_INT16(&mem[p + 0xa2]); // mem[p + 0xa2] | mem[p + 0xa3] << 8;
+						unp->_retAdr = READ_LE_UINT16(&mem[p + 0xa2]); // mem[p + 0xa2] | mem[p + 0xa3] << 8;
 					} else if ((mem[p + 0x8c] == 0x4c) && (mem[p + 0x94] == 0x4c)) {
-						unp->_retAdr = READ_LE_INT16(&mem[p + 0x95]); // mem[p + 0x95] | mem[p + 0x96] << 8;
+						unp->_retAdr = READ_LE_UINT16(&mem[p + 0x95]); // mem[p + 0x95] | mem[p + 0x96] << 8;
 					} else if ((mem[p + 0x20] == 0x4c) && (mem[p + 0x28] == 0x4c)) {
-						unp->_retAdr = READ_LE_INT16(&mem[p + 0x29]); // mem[p + 0x29] | mem[p + 0x2a] << 8;
+						unp->_retAdr = READ_LE_UINT16(&mem[p + 0x29]); // mem[p + 0x29] | mem[p + 0x2a] << 8;
 					} 
 				}
 			}
@@ -119,18 +119,18 @@ void scnCruel(UnpStr *unp) {
 	/* MSCRUNCH 1.5 hack by Anubis */
 	if (unp->_depAdr == 0) {
 		if (mem[0x819] == 0x4c) {
-			p = READ_LE_INT16(&mem[0x81a]);//mem[0x81a] | mem[0x81b] << 8;
+			p = READ_LE_UINT16(&mem[0x81a]);//mem[0x81a] | mem[0x81b] << 8;
 			if ((mem[p] == 0xa9) && (mem[p + 0x0f] == 0x30) &&
 				(*(unsigned int *)(mem + p + 0x13) == 0xCA04009D) &&
 				(*(unsigned int *)(mem + p + 0x38) == 0x01084C01)) {
-				q = READ_LE_INT16(&mem[p + 0x1f]); // mem[p + 0x1f] | mem[p + 0x20] << 8;
+				q = READ_LE_UINT16(&mem[p + 0x1f]); // mem[p + 0x1f] | mem[p + 0x20] << 8;
 				if (*(unsigned int *)(mem + q + 7) == 0xC8071C99) {
-					unp->_endAdr = READ_LE_INT16(&mem[q + 3]); // mem[q + 3] | mem[q + 4] << 8;
+					unp->_endAdr = READ_LE_UINT16(&mem[q + 3]); // mem[q + 3] | mem[q + 4] << 8;
 					unp->_depAdr = 0x100;
 					if (unp->_info->_run == -1)
 						unp->_forced = 0x819;
 					unp->_fStrAf = 0xfe;
-					unp->_retAdr = READ_LE_INT16(&mem[q + 0xa2]); // mem[q + 0xa2] | mem[q + 0xa3] << 8;
+					unp->_retAdr = READ_LE_UINT16(&mem[q + 0xa2]); // mem[q + 0xa2] | mem[q + 0xa3] << 8;
 				}
 			}
 		}
@@ -142,11 +142,11 @@ void scnCruel(UnpStr *unp) {
 			((*(unsigned int *)(mem + 0x818) == 0x03404cF7) ||
 			 (*(unsigned int *)(mem + 0x818) == 0x03b34cF7) ||
 			 (*(unsigned int *)(mem + 0x818) == 0x03db4cF7))) {
-			p = READ_LE_INT16(&mem[0x811]); // mem[0x811] | mem[0x812] << 8;
+			p = READ_LE_UINT16(&mem[0x811]); // mem[0x811] | mem[0x812] << 8;
 			if (*(unsigned int *)(mem + p) == 0xa75801c6) {
 				p += 0x45;
-				q = READ_LE_INT16(&mem[p]);            // mem[p] | mem[p + 1] << 8;
-				unp->_endAdr = READ_LE_INT16(&mem[q + 2]); // mem[q + 2] | mem[q + 3] << 8;
+				q = READ_LE_UINT16(&mem[p]);            // mem[p] | mem[p + 1] << 8;
+				unp->_endAdr = READ_LE_UINT16(&mem[q + 2]); // mem[q + 2] | mem[q + 3] << 8;
 				unp->_depAdr = 0x340;
 				unp->_forced = 0x80b;
 				unp->_fStrAf = 0xfc;
@@ -160,10 +160,10 @@ void scnCruel(UnpStr *unp) {
 		if ((*(unsigned int *)(mem + 0x837) == 0x9D0845BD) &&
 			(*(unsigned int *)(mem + 0x84f) == 0xE808039D) &&
 			(*(unsigned int *)(mem + 0x83b) == 0xC9E803B7)) {
-			unp->_depAdr = READ_LE_INT16(&mem[0x843]); // mem[0x843] | mem[0x844] << 8;
+			unp->_depAdr = READ_LE_UINT16(&mem[0x843]); // mem[0x843] | mem[0x844] << 8;
 			if (unp->_info->_run == -1)
 				unp->_forced = 0x80d;
-			unp->_retAdr = READ_LE_INT16(&mem[0x868]); // mem[0x868] | mem[0x869] << 8;
+			unp->_retAdr = READ_LE_UINT16(&mem[0x868]); // mem[0x868] | mem[0x869] << 8;
 			unp->_endAdr = unp->_info->_end - 0x90;
 			unp->_strMem = 0x801;
 			unp->_idFlag = 1;
@@ -172,10 +172,10 @@ void scnCruel(UnpStr *unp) {
 		if ((*(unsigned int *)(mem + 0x845) == 0x03E04CF2) &&
 			(*(unsigned int *)(mem + 0x852) == 0x9D0893BD) &&
 			(*(unsigned int *)(mem + 0x856) == 0xD0E80803)) {
-			unp->_depAdr = READ_LE_INT16(&mem[0x847]); // mem[0x847] | mem[0x848] << 8;
+			unp->_depAdr = READ_LE_UINT16(&mem[0x847]); // mem[0x847] | mem[0x848] << 8;
 			if (unp->_info->_run == -1)
 				unp->_forced = 0x80d;
-			unp->_retAdr = READ_LE_INT16(&mem[0x869]); // mem[0x869] | mem[0x86a] << 8;
+			unp->_retAdr = READ_LE_UINT16(&mem[0x869]); // mem[0x869] | mem[0x86a] << 8;
 			unp->_endAdr = unp->_info->_end - 0x90;
 			unp->_strMem = 0x801;
 			unp->_idFlag = 1;
@@ -184,14 +184,14 @@ void scnCruel(UnpStr *unp) {
 		if ((*(unsigned int *)(mem + 0x841) == 0x03B74CF5) &&
 			(*(unsigned int *)(mem + 0x84c) == 0x9D089BBD) &&
 			(*(unsigned int *)(mem + 0x850) == 0xD0E8080B)) {
-			unp->_depAdr = READ_LE_INT16(&mem[0x843]); // mem[0x843] | mem[0x844] << 8;
+			unp->_depAdr = READ_LE_UINT16(&mem[0x843]); // mem[0x843] | mem[0x844] << 8;
 			if (unp->_info->_run == -1) {
 				unp->_forced = 0x811;
 			} else {
 				mem[0x808] = '5'; /* just to be safe, change sys for next layer */
 				mem[0x809] = '9'; /* this hdr leaves it as sys2065 */
 			}
-			unp->_retAdr = READ_LE_INT16(&mem[0x868]); // mem[0x868] | mem[0x869] << 8; /* fixed $080b */
+			unp->_retAdr = READ_LE_UINT16(&mem[0x868]); // mem[0x868] | mem[0x869] << 8; /* fixed $080b */
 			unp->_endAdr = unp->_info->_end - 0x90;
 			unp->_strMem = 0x801;
 			unp->_idFlag = 1;
@@ -201,10 +201,10 @@ void scnCruel(UnpStr *unp) {
 		if ((*(unsigned int *)(mem + 0x80b) == 0x1BB900A0) &&
 			(*(unsigned int *)(mem + 0x80f) == 0x03B79908) &&
 			(*(unsigned int *)(mem + 0x823) == 0x039D0840)) {
-			unp->_depAdr = READ_LE_INT16(&mem[0x819]); // mem[0x819] | mem[0x81a] << 8;
+			unp->_depAdr = READ_LE_UINT16(&mem[0x819]); // mem[0x819] | mem[0x81a] << 8;
 			if (unp->_info->_run == -1)
 				unp->_forced = 0x80b;
-			unp->_retAdr = READ_LE_INT16(&mem[0x83e]); // mem[0x83e] | mem[0x83f] << 8;
+			unp->_retAdr = READ_LE_UINT16(&mem[0x83e]); // mem[0x83e] | mem[0x83f] << 8;
 			unp->_endAdr = unp->_info->_end - 0x3d;
 			unp->_strMem = 0x801;
 			unp->_idFlag = 1;
@@ -216,13 +216,13 @@ void scnCruel(UnpStr *unp) {
 		if ((((*(unsigned int *)(mem + 0x80b)) & 0x0000ffff) == 0x000000A0) &&
 			(*(unsigned int *)(mem + 0x817) == 0xC800CB99) &&
 			(*(unsigned int *)(mem + 0x81b) == 0x004CF7D0) && mem[0x81f] == 1) {
-			p = READ_LE_INT16(&mem[0x815]); // mem[0x815] | mem[0x816] << 8;
+			p = READ_LE_UINT16(&mem[0x815]); // mem[0x815] | mem[0x816] << 8;
 			p += 0x31;
 			if ((mem[p + 4] == 0xb9) &&
 				(*(unsigned int *)(mem + p + 7) == 0xC8072099)) {
 				unp->_forced = 0x80b;
 				unp->_depAdr = 0x100;
-				unp->_endAdr = READ_LE_INT16(&mem[p]); // mem[p] | mem[p + 1] << 8;
+				unp->_endAdr = READ_LE_UINT16(&mem[p]); // mem[p] | mem[p + 1] << 8;
 				unp->_fStrAf = 0xfc;
 				/* patch: some version contain a zp cleaner sub at $01a2 */
 				if ((*(unsigned int *)(mem + p + 0xa6) == 0x00A9CBA2) &&
@@ -234,10 +234,10 @@ void scnCruel(UnpStr *unp) {
 					mem[0x811] = 0xe6;
 					mem[0x812] = 0x01;
 				}
-				q = READ_LE_INT16(&mem[p + 5]); // mem[p + 5] | mem[p + 6] << 8;
+				q = READ_LE_UINT16(&mem[p + 5]); // mem[p + 5] | mem[p + 6] << 8;
 				unp->_retAdr = 0x7e8;
 				if (mem[q + 0x6c] == 0x4c)
-					unp->_retAdr = READ_LE_INT16(&mem[q + 0x6d]); // mem[q + 0x6d] | mem[q + 0x6e] << 8;
+					unp->_retAdr = READ_LE_UINT16(&mem[q + 0x6d]); // mem[q + 0x6d] | mem[q + 0x6e] << 8;
 				unp->_idFlag = 1;
 				return;
 			}
@@ -247,18 +247,18 @@ void scnCruel(UnpStr *unp) {
 	if (unp->_depAdr == 0) {
 		if (mem[0x80b] == 0xa0 && (*(unsigned int *)(mem + 0x817) == 0xC800CB99) &&
 			(*(unsigned int *)(mem + 0x81b) == 0x004CF7D0) && mem[0x81f] == 1) {
-			p = READ_LE_INT16(&mem[0x815]); // mem[0x815] | mem[0x816] << 8;
+			p = READ_LE_UINT16(&mem[0x815]); // mem[0x815] | mem[0x816] << 8;
 			p += 0x31;
 			if ((mem[p + 6] == 0xb9) &&
 				(*(unsigned int *)(mem + p + 9) == 0xC8072099)) {
 				unp->_forced = 0x80b;
 				unp->_depAdr = 0x100;
-				unp->_endAdr = READ_LE_INT16(&mem[p]); // mem[p] | mem[p + 1] << 8;
+				unp->_endAdr = READ_LE_UINT16(&mem[p]); // mem[p] | mem[p + 1] << 8;
 				unp->_fStrAf = 0xfc;
-				q = READ_LE_INT16(&mem[p + 7]); // mem[p + 7] | mem[p + 8] << 8;
+				q = READ_LE_UINT16(&mem[p + 7]); // mem[p + 7] | mem[p + 8] << 8;
 				unp->_retAdr = 0x7e8;
 				if (mem[q + 0x6c] == 0x4c)
-					unp->_retAdr = READ_LE_INT16(&mem[q + 0x6d]); // mem[q + 0x6d] | mem[q + 0x6e] << 8;
+					unp->_retAdr = READ_LE_UINT16(&mem[q + 0x6d]); // mem[q + 0x6d] | mem[q + 0x6e] << 8;
 				unp->_idFlag = 1;
 				return;
 			}
@@ -268,13 +268,13 @@ void scnCruel(UnpStr *unp) {
 	if (unp->_depAdr == 0) {
 		if (mem[0x810] == 0xb9 && (*(unsigned int *)(mem + 0x813) == 0xC800e999) &&
 			(*(unsigned int *)(mem + 0x818) == 0x00e94CF7)) {
-			p = READ_LE_INT16(&mem[0x811]); // mem[0x811] | mem[0x812] << 8;
+			p = READ_LE_UINT16(&mem[0x811]); // mem[0x811] | mem[0x812] << 8;
 			q = p - 0xed;
 			if ((*(unsigned int *)(mem + p) == 0x13F01284) &&
 				(*(unsigned int *)(mem + q) == 0xA9C8C8C8)) {
 				unp->_depAdr = 0xe9;
-				unp->_endAdr = READ_LE_INT16(&mem[p + 0x13]); // mem[p + 0x13] | mem[p + 0x14] << 8;
-				unp->_retAdr = READ_LE_INT16(&mem[q + 0x38]); // mem[q + 0x38] | mem[q + 0x39] << 8;
+				unp->_endAdr = READ_LE_UINT16(&mem[p + 0x13]); // mem[p + 0x13] | mem[p + 0x14] << 8;
+				unp->_retAdr = READ_LE_UINT16(&mem[q + 0x38]); // mem[q + 0x38] | mem[q + 0x39] << 8;
 				if (unp->_info->_run == -1)
 					unp->_forced = 0x80b;
 				unp->_fStrAf = 0xfc;
@@ -286,13 +286,13 @@ void scnCruel(UnpStr *unp) {
 	if (unp->_depAdr == 0) {
 		if (mem[0x810] == 0xb9 && (*(unsigned int *)(mem + 0x813) == 0xC800ed99) &&
 			(*(unsigned int *)(mem + 0x818) == 0x01004CF7)) {
-			p = READ_LE_INT16(&mem[0x811]); // mem[0x811] | mem[0x812] << 8;
+			p = READ_LE_UINT16(&mem[0x811]); // mem[0x811] | mem[0x812] << 8;
 			q = p - 0xed;
 			if ((*(unsigned int *)(mem + p) == 0x01C60888) &&
 				(*(unsigned int *)(mem + q) == 0xA9C8C8C8)) {
 				unp->_depAdr = 0x100;
-				unp->_endAdr = READ_LE_INT16(&mem[p + 0x0f]); // mem[p + 0x0f] | mem[p + 0x10] << 8;
-				unp->_retAdr = READ_LE_INT16(&mem[q + 0x38]); // mem[q + 0x38] | mem[q + 0x39] << 8;
+				unp->_endAdr = READ_LE_UINT16(&mem[p + 0x0f]); // mem[p + 0x0f] | mem[p + 0x10] << 8;
+				unp->_retAdr = READ_LE_UINT16(&mem[q + 0x38]); // mem[q + 0x38] | mem[q + 0x39] << 8;
 				if (unp->_info->_run == -1)
 					unp->_forced = 0x80b;
 				unp->_fStrAf = 0xfc;
@@ -310,7 +310,7 @@ void scnCruel(UnpStr *unp) {
 			(*(unsigned int *)(mem + 0x90b) == 0xC068FEC6)) {
 			unp->_depAdr = 0x100;
 			unp->_forced = 0x80b;
-			unp->_retAdr = READ_LE_INT16(&mem[0x91c]); // mem[0x91c] | mem[0x91d] << 8;
+			unp->_retAdr = READ_LE_UINT16(&mem[0x91c]); // mem[0x91c] | mem[0x91d] << 8;
 			unp->_endAdr = 0x2d;
 			unp->_fStrAf = 0xfc;
 			unp->_idFlag = 1;
@@ -326,7 +326,7 @@ void scnCruel(UnpStr *unp) {
 			(*(unsigned int *)(mem + 0x90b) == 0xB1486018)) {
 			unp->_depAdr = 0x100;
 			unp->_forced = 0x80b;
-			unp->_retAdr = READ_LE_INT16(&mem[0x92d]); // mem[0x92d] | mem[0x92e] << 8;
+			unp->_retAdr = READ_LE_UINT16(&mem[0x92d]); // mem[0x92d] | mem[0x92e] << 8;
 			unp->_endAdr = 0x2d;
 			unp->_fStrAf = 0xfc;
 			unp->_idFlag = 1;
@@ -339,7 +339,7 @@ void scnCruel(UnpStr *unp) {
 			(*(unsigned int *)(mem + 0x8fc) == 0xB1486018)) {
 			unp->_depAdr = 0x100;
 			unp->_forced = 0x80b;
-			unp->_retAdr = READ_LE_INT16(&mem[0x91e]); // mem[0x91e] | mem[0x91f] << 8;
+			unp->_retAdr = READ_LE_UINT16(&mem[0x91e]); // mem[0x91e] | mem[0x91f] << 8;
 			unp->_endAdr = 0x2d;
 			unp->_fStrAf = 0xfc;
 			unp->_idFlag = 1;
@@ -352,14 +352,14 @@ void scnCruel(UnpStr *unp) {
 		if ((mem[0x810] == 0xb9) && (mem[0x819] == 0xa9) &&
 			(*(unsigned int *)(mem + 0x813) == 0xC800fa99) &&
 			(*(unsigned int *)(mem + 0x822) == 0x4CAF86AE)) {
-			p = READ_LE_INT16(&mem[0x811]); // mem[0x811] | mem[0x812] << 8;
+			p = READ_LE_UINT16(&mem[0x811]); // mem[0x811] | mem[0x812] << 8;
 			q = p - 0x100;
 
 			if ((*(unsigned int *)(mem + p + 0x0c) == 0x20F7D0C8) &&
 				(*(unsigned int *)(mem + q) == 0xA9C8C8C8)) {
 				unp->_depAdr = 0x100;
-				unp->_endAdr = READ_LE_INT16(&mem[p + 0x02]); // mem[p + 0x02] | mem[p + 0x03] << 8;
-				unp->_retAdr = READ_LE_INT16(&mem[q + 0x3f]); // mem[q + 0x3f] | mem[q + 0x40] << 8;
+				unp->_endAdr = READ_LE_UINT16(&mem[p + 0x02]); // mem[p + 0x02] | mem[p + 0x03] << 8;
+				unp->_retAdr = READ_LE_UINT16(&mem[q + 0x3f]); // mem[q + 0x3f] | mem[q + 0x40] << 8;
 				if (unp->_info->_run == -1)
 					unp->_forced = 0x80b;
 				unp->_fStrAf = 0xfc;
diff --git a/engines/glk/scott/unp64/scanners/eca.cpp b/engines/glk/scott/unp64/scanners/eca.cpp
index 121305fd31a..1bb1efbef2d 100644
--- a/engines/glk/scott/unp64/scanners/eca.cpp
+++ b/engines/glk/scott/unp64/scanners/eca.cpp
@@ -93,16 +93,16 @@ void scnECA(UnpStr *unp) {
 							q += 2;
 							continue;
 						} else {
-							unp->_retAdr = READ_LE_INT16(&mem[p + q + 1]); // mem[p + q + 1] | mem[p + q + 2] << 8;
+							unp->_retAdr = READ_LE_UINT16(&mem[p + q + 1]); // mem[p + q + 1] | mem[p + q + 2] << 8;
 							break;
 						}
 					}
 					if (mem[p + q] == 0x4c) {
-						unp->_retAdr = READ_LE_INT16(&mem[p + q + 1]); // mem[p + q + 1] | mem[p + q + 2] << 8;
+						unp->_retAdr = READ_LE_UINT16(&mem[p + q + 1]); // mem[p + q + 1] | mem[p + q + 2] << 8;
 						break;
 					}
 				}
-				unp->_depAdr = READ_LE_INT16(&mem[p + 0x30]); // mem[p + 0x30] | mem[p + 0x31] << 8;
+				unp->_depAdr = READ_LE_UINT16(&mem[p + 0x30]); // mem[p + 0x30] | mem[p + 0x31] << 8;
 				// some use $2d, some $ae
 				for (q = 0xed; q < 0x108; q++) {
 					if (*(unsigned int *)(mem + p + q) == 0xA518F7D0) {
@@ -135,10 +135,10 @@ void scnECA(UnpStr *unp) {
 				extensively. use -v to know when it does the adjustments. 28/10/09:
 				whoops, was clearing ONLY $d000-dfff =)
 				*/
-				unp->_strMem = READ_LE_INT16(&mem[p + 0x32]); // mem[p + 0x32] | mem[p + 0x33] << 8;
+				unp->_strMem = READ_LE_UINT16(&mem[p + 0x32]); // mem[p + 0x32] | mem[p + 0x33] << 8;
 				for (q = 0xcd; q < 0xd0; q++) {
 					if ((*(unsigned int *)(mem + p + q) & 0xffff00ff) == 0xa9010020) {
-						unp->_ecaFlg = READ_LE_INT16(&mem[p + q + 1]); // mem[p + q + 1] | mem[p + q + 2] << 8;
+						unp->_ecaFlg = READ_LE_UINT16(&mem[p + q + 1]); // mem[p + q + 1] | mem[p + q + 2] << 8;
 						for (q = 0x110; q < 0x11f; q++) {
 							if ((*(unsigned int *)(mem + p + q) == 0x99EF00B9) &&
 								(mem[p + q + 0x12] == 0xc9)) {
@@ -171,9 +171,9 @@ void scnECA(UnpStr *unp) {
 			(*(unsigned int *)(mem + 0x85b) == 0x2A2A2A2A)) {
 			unp->_forced = 0x81b;
 			unp->_depAdr = 0x100;
-			unp->_strMem = READ_LE_INT16(&mem[0x853]); // mem[0x853] | mem[0x854] << 8;
+			unp->_strMem = READ_LE_UINT16(&mem[0x853]); // mem[0x853] | mem[0x854] << 8;
 			unp->_endAdr = mem[0x895];
-			unp->_retAdr = READ_LE_INT16(&mem[0x885]); // mem[0x885] | mem[0x886] << 8;
+			unp->_retAdr = READ_LE_UINT16(&mem[0x885]); // mem[0x885] | mem[0x886] << 8;
 			unp->_idFlag = 1;
 			return;
 		}
diff --git a/engines/glk/scott/unp64/scanners/exomizer.cpp b/engines/glk/scott/unp64/scanners/exomizer.cpp
index 68fad9d564d..04ec021133c 100644
--- a/engines/glk/scott/unp64/scanners/exomizer.cpp
+++ b/engines/glk/scott/unp64/scanners/exomizer.cpp
@@ -65,7 +65,7 @@ void scnExomizer(UnpStr *unp) {
 			for (; p < unp->_info->_end; p++) {
 				if (mem[p] == 0x4c) {
 					unp->_retAdr = 0;
-					if ((unp->_retAdr = READ_LE_INT16(&mem[p + 1])) >= 0x200) {
+					if ((unp->_retAdr = READ_LE_UINT16(&mem[p + 1])) >= 0x200) {
 						break;
 					} else { /* it's a jmp $01xx, goto next */
 						p++;
@@ -142,7 +142,7 @@ void scnExomizer(UnpStr *unp) {
 				// incredibly there can be a program starting at $4c00 :P
 				if ((mem[p] == 0x4c) && (mem[p - 1] != 0x4c) && (mem[p - 2] != 0x4c)) {
 					unp->_retAdr = 0;
-					if ((unp->_retAdr = READ_LE_INT16(&mem[p + 1])) >= 0x200) {
+					if ((unp->_retAdr = READ_LE_UINT16(&mem[p + 1])) >= 0x200) {
 						break;
 					}
 				}
diff --git a/engines/glk/scott/unp64/scanners/expert.cpp b/engines/glk/scott/unp64/scanners/expert.cpp
index 56463ae2e20..b40f66bc11c 100644
--- a/engines/glk/scott/unp64/scanners/expert.cpp
+++ b/engines/glk/scott/unp64/scanners/expert.cpp
@@ -93,7 +93,7 @@ void scnExpert(UnpStr *unp) {
 			for (p = 0x900; p < 0xfff0; p++) {
 				if ((*(unsigned int *)(mem + p) == 0xA2F3D0CA) &&
 					(mem[p + 0x05] == 0x4c)) {
-					q = READ_LE_INT16(&mem[p + 0x06]); // mem[p + 0x06] | mem[p + 0x07] << 8;
+					q = READ_LE_UINT16(&mem[p + 0x06]); // mem[p + 0x06] | mem[p + 0x07] << 8;
 					if (q != 0x100) {
 						unp->_depAdr = q;
 						break;
@@ -161,7 +161,7 @@ void scnExpert(UnpStr *unp) {
 			for (p = 0x900; p < 0xfff0; p++) {
 				if ((*(unsigned int *)(mem + p) == 0xA2F3D0CA) &&
 					(mem[p + 0x05] == 0x4c)) {
-					q = READ_LE_INT16(&mem[p + 0x06]); // mem[p + 0x06] | mem[p + 0x07] << 8;
+					q = READ_LE_UINT16(&mem[p + 0x06]); // mem[p + 0x06] | mem[p + 0x07] << 8;
 					if (q != 0x100) {
 						unp->_depAdr = q;
 						break;
diff --git a/engines/glk/scott/unp64/scanners/master_compressor.cpp b/engines/glk/scott/unp64/scanners/master_compressor.cpp
index ae75efaf572..a3c35aa8a7c 100644
--- a/engines/glk/scott/unp64/scanners/master_compressor.cpp
+++ b/engines/glk/scott/unp64/scanners/master_compressor.cpp
@@ -42,17 +42,17 @@ void scnMasterCompressor(UnpStr *unp) {
 				 (*(unsigned int *)(mem + p + 0x134) == 0xDBD0FFE6)) {
 				if (/*mem[p]==0x78&&*/ mem[p + 1] == 0xa9 &&
 					(*(unsigned int *)(mem + p + 0x003) == 0xD2A20185)) {
-					unp->_depAdr = READ_LE_INT16(&mem[p + 0x37]); // mem[p + 0x37] | mem[p + 0x38] << 8;
+					unp->_depAdr = READ_LE_UINT16(&mem[p + 0x37]); // mem[p + 0x37] | mem[p + 0x38] << 8;
 					unp->_forced = p + 1;
 					if (mem[p + 0x12b] == 0x020) // jsr $0400, unuseful fx
 						mem[p + 0x12b] = 0x2c;
 				} else if (*(unsigned int *)(mem + p) == 0xD024E0E8) {
 					/* HTL version */
-					unp->_depAdr = READ_LE_INT16(&mem[p + 0x37]); // mem[p + 0x37] | mem[p + 0x38] << 8;
+					unp->_depAdr = READ_LE_UINT16(&mem[p + 0x37]); // mem[p + 0x37] | mem[p + 0x38] << 8;
 					unp->_forced = 0x840;
 				}
 				if (unp->_depAdr) {
-					unp->_retAdr = READ_LE_INT16(&mem[p + 0x13e]); // mem[p + 0x13e] | mem[p + 0x13f] << 8;
+					unp->_retAdr = READ_LE_UINT16(&mem[p + 0x13e]); // mem[p + 0x13e] | mem[p + 0x13f] << 8;
 					unp->_endAdr = 0x2d;
 					unp->_fStrBf = unp->_endAdr;
 					unp->_idFlag = 1;
@@ -71,14 +71,14 @@ void scnMasterCompressor(UnpStr *unp) {
 				 (*(unsigned int *)(mem + p + 0x12d) == 0xe2D0FFE6)) {
 				if (mem[p + 1] == 0xa9 &&
 					(*(unsigned int *)(mem + p + 0x003) == 0xD2A20185)) {
-					unp->_depAdr = READ_LE_INT16(&mem[p + 0x37]); // mem[p + 0x37] | mem[p + 0x38] << 8;
+					unp->_depAdr = READ_LE_UINT16(&mem[p + 0x37]); // mem[p + 0x37] | mem[p + 0x38] << 8;
 					unp->_forced = p + 1;
 				}
 				if (unp->_depAdr) {
 					if (mem[p + 0x136] == 0x4c)
-						unp->_retAdr = READ_LE_INT16(&mem[p + 0x137]); // mem[p + 0x137] | mem[p + 0x138] << 8;
+						unp->_retAdr = READ_LE_UINT16(&mem[p + 0x137]); // mem[p + 0x137] | mem[p + 0x138] << 8;
 					else if (mem[p + 0x13d] == 0x4c)
-						unp->_retAdr = READ_LE_INT16(&mem[p + 0x13e]); // mem[p + 0x13e] | mem[p + 0x13f] << 8;
+						unp->_retAdr = READ_LE_UINT16(&mem[p + 0x13e]); // mem[p + 0x13e] | mem[p + 0x13f] << 8;
 					unp->_endAdr = 0x2d;
 					unp->_fStrBf = unp->_endAdr;
 					unp->_idFlag = 1;
@@ -95,7 +95,7 @@ void scnMasterCompressor(UnpStr *unp) {
 			(*(unsigned int *)(mem + p + 0x00c) == 0x34990910)) {
 			unp->_depAdr = 0x100;
 			unp->_forced = p;
-			unp->_retAdr = READ_LE_INT16(&mem[0x943]); // mem[0x943] | mem[0x944] << 8;
+			unp->_retAdr = READ_LE_UINT16(&mem[0x943]); // mem[0x943] | mem[0x944] << 8;
 			unp->_endAdr = 0x2d;
 			unp->_fStrBf = unp->_endAdr;
 			unp->_idFlag = 1;
@@ -110,7 +110,7 @@ void scnMasterCompressor(UnpStr *unp) {
 			(*(unsigned int *)(mem + 0x882) == 0x01004C2D)) {
 			unp->_depAdr = 0x100;
 			unp->_forced = 0x811;
-			unp->_retAdr = READ_LE_INT16(&mem[0x98b]); // mem[0x98b] | mem[0x98c] << 8;
+			unp->_retAdr = READ_LE_UINT16(&mem[0x98b]); // mem[0x98b] | mem[0x98c] << 8;
 			if (unp->_retAdr < 0x800)
 				unp->_rtAFrc = 1;
 			unp->_endAdr = 0x2d;
diff --git a/engines/glk/scott/unp64/scanners/megabyte.cpp b/engines/glk/scott/unp64/scanners/megabyte.cpp
index 7a2f874a568..18fcc6115b4 100644
--- a/engines/glk/scott/unp64/scanners/megabyte.cpp
+++ b/engines/glk/scott/unp64/scanners/megabyte.cpp
@@ -36,17 +36,17 @@ void scnMegabyte(UnpStr *unp) {
 	if (unp->_depAdr == 0) {
 		p = 0;
 		if (mem[0x816] == 0x4c)
-			p = READ_LE_INT16(&mem[0x817]); // mem[0x817] | mem[0x818] << 8;
+			p = READ_LE_UINT16(&mem[0x817]); // mem[0x817] | mem[0x818] << 8;
 		else if ((unp->_info->_run == 0x810) && (mem[0x814] == 0x4c) &&
 				 ((*(unsigned int *)(mem + 0x810) & 0xffff00ff) == 0x018500A9))
-			p = READ_LE_INT16(&mem[0x815]); // mem[0x815] | mem[0x816] << 8;
+			p = READ_LE_UINT16(&mem[0x815]); // mem[0x815] | mem[0x816] << 8;
 		if (p) {
 			if ((mem[p + 0] == 0x78) && (mem[p + 1] == 0xa2) &&
 				(mem[p + 3] == 0xa0) &&
 				(*(unsigned int *)(mem + p + 0x05) == 0x15841486) &&
 				(*(unsigned int *)(mem + p + 0x1d) == 0x03804CF7)) {
 				unp->_depAdr = 0x380;
-				unp->_endAdr = READ_LE_INT16(&mem[p + 0x55]); // mem[p + 0x55] | mem[p + 0x56] << 8;
+				unp->_endAdr = READ_LE_UINT16(&mem[p + 0x55]); // mem[p + 0x55] | mem[p + 0x56] << 8;
 				unp->_endAdr++;
 				unp->_strMem = 0x801;
 				unp->_retAdr = 0x801; /* ususally it just runs */
@@ -59,7 +59,7 @@ void scnMegabyte(UnpStr *unp) {
 		p = 0;
 		if ((mem[0x81a] == 0x4c) &&
 			((*(unsigned int *)(mem + 0x816) & 0xffff00ff) == 0x018500A9))
-			p = READ_LE_INT16(&mem[0x81b]); // mem[0x81b] | mem[0x81c] << 8;
+			p = READ_LE_UINT16(&mem[0x81b]); // mem[0x81b] | mem[0x81c] << 8;
 		if (p) {
 			if ((mem[p + 0] == 0x78) && (mem[p + 1] == 0xa2) &&
 				(mem[p + 3] == 0xa0) &&
@@ -67,7 +67,7 @@ void scnMegabyte(UnpStr *unp) {
 				(*(unsigned int *)(mem + p + 0x1d) == 0x03844CF7)) {
 				unp->_depAdr = 0x384;
 				unp->_forced = 0x816;
-				unp->_endAdr = READ_LE_INT16(&mem[p + 0x59]); // mem[p + 0x59] | mem[p + 0x5a] << 8;
+				unp->_endAdr = READ_LE_UINT16(&mem[p + 0x59]); // mem[p + 0x59] | mem[p + 0x5a] << 8;
 				unp->_endAdr++;
 				unp->_strMem = 0x801;
 				unp->_retAdr = 0x801; /* ususally it just runs */
diff --git a/engines/glk/scott/unp64/scanners/pu_crunch.cpp b/engines/glk/scott/unp64/scanners/pu_crunch.cpp
index 533d95dd1d0..9247bcb4493 100644
--- a/engines/glk/scott/unp64/scanners/pu_crunch.cpp
+++ b/engines/glk/scott/unp64/scanners/pu_crunch.cpp
@@ -43,9 +43,9 @@ void scnPuCrunch(UnpStr *unp) {
 				if ((*(unsigned int *)(mem + p) == 0x2D85FAA5) &&
 					(*(unsigned int *)(mem + p + 4) == 0x2E85FBA5)) {
 					unp->_endAdr = 0xfa;
-					unp->_strMem = READ_LE_INT16(&mem[0x879]); // mem[0x879] | mem[0x87a] << 8;
-					unp->_depAdr = READ_LE_INT16(&mem[0x841]); // mem[0x841] | mem[0x842] << 8;
-					unp->_retAdr = READ_LE_INT16(&mem[p + 0xa]); // mem[p + 0xa] | mem[p + 0xb] << 8;
+					unp->_strMem = READ_LE_UINT16(&mem[0x879]); // mem[0x879] | mem[0x87a] << 8;
+					unp->_depAdr = READ_LE_UINT16(&mem[0x841]); // mem[0x841] | mem[0x842] << 8;
+					unp->_retAdr = READ_LE_UINT16(&mem[p + 0xa]); // mem[p + 0xa] | mem[p + 0xb] << 8;
 					unp->_forced = 0x80d;
 					break;
 				}
@@ -58,9 +58,9 @@ void scnPuCrunch(UnpStr *unp) {
 				if ((*(unsigned int *)(mem + p) == 0x2D85FAA5) &&
 					(*(unsigned int *)(mem + p + 4) == 0x2E85FBA5)) {
 					unp->_endAdr = 0xfa;
-					unp->_strMem = READ_LE_INT16(&mem[p + 0x88a]); // mem[0x88a] | mem[0x88b] << 8;
-					unp->_depAdr = READ_LE_INT16(&mem[p + 0x84b]); // mem[0x84b] | mem[0x84c] << 8;
-					unp->_retAdr = READ_LE_INT16(&mem[p + 0xa]); // mem[p + 0xa] | mem[p + 0xb] << 8;
+					unp->_strMem = READ_LE_UINT16(&mem[p + 0x88a]); // mem[0x88a] | mem[0x88b] << 8;
+					unp->_depAdr = READ_LE_UINT16(&mem[p + 0x84b]); // mem[0x84b] | mem[0x84c] << 8;
+					unp->_retAdr = READ_LE_UINT16(&mem[p + 0xa]); // mem[p + 0xa] | mem[p + 0xb] << 8;
 					unp->_forced = 0x80d;
 					break;
 				}
@@ -71,9 +71,9 @@ void scnPuCrunch(UnpStr *unp) {
 				   (*(unsigned int *)(mem + 0x861) == 0xC501C320) &&
 				   (*(unsigned int *)(mem + 0x839) == 0x01164CED)) {
 			unp->_endAdr = 0xfa;
-			unp->_strMem = READ_LE_INT16(&mem[0x840]); // mem[0x840] | mem[0x841] << 8;
+			unp->_strMem = READ_LE_UINT16(&mem[0x840]); // mem[0x840] | mem[0x841] << 8;
 			unp->_depAdr = 0x116;
-			unp->_retAdr = READ_LE_INT16(&mem[0x8df]); // mem[0x8df] | mem[0x8e0] << 8;
+			unp->_retAdr = READ_LE_UINT16(&mem[0x8df]); // mem[0x8df] | mem[0x8e0] << 8;
 			unp->_forced = 0x80d;
 		} else if ((mem[0x80d] == 0x78) &&
 				   (*(unsigned int *)(mem + 0x811) == 0x85AAA901) &&
@@ -81,17 +81,17 @@ void scnPuCrunch(UnpStr *unp) {
 				   (*(unsigned int *)(mem + 0x861) == 0xC501C820) &&
 				   (*(unsigned int *)(mem + 0x839) == 0x01164CED)) {
 			unp->_endAdr = 0xfa;
-			unp->_strMem = READ_LE_INT16(&mem[0x840]); // mem[0x840] | mem[0x841] << 8;
+			unp->_strMem = READ_LE_UINT16(&mem[0x840]); // mem[0x840] | mem[0x841] << 8;
 			unp->_depAdr = 0x116;
 			if (mem[0x8de] == 0xa9) {
-				unp->_retAdr = READ_LE_INT16(&mem[0x8e1]); // mem[0x8e1] | mem[0x8e2] << 8;
+				unp->_retAdr = READ_LE_UINT16(&mem[0x8e1]); // mem[0x8e1] | mem[0x8e2] << 8;
 				if ((unp->_retAdr == 0xa871) && (mem[0x8e0] == 0x20) &&
 					(mem[0x8e3] == 0x4c)) {
 					mem[0x8e0] = 0x2c;
-					unp->_retAdr = READ_LE_INT16(&mem[0x8e4]); // mem[0x8e4] | mem[0x8e5] << 8;
+					unp->_retAdr = READ_LE_UINT16(&mem[0x8e4]); // mem[0x8e4] | mem[0x8e5] << 8;
 				}
 			} else {
-				unp->_retAdr = READ_LE_INT16(&mem[0x8df]); // mem[0x8df] | mem[0x8e0] << 8;
+				unp->_retAdr = READ_LE_UINT16(&mem[0x8df]); // mem[0x8df] | mem[0x8e0] << 8;
 			}
 			unp->_forced = 0x80d;
 		} else {
@@ -105,17 +105,17 @@ void scnPuCrunch(UnpStr *unp) {
 							(*(unsigned int *)(mem + p + 8) == 0xA2F7D0CA)) {
 							unp->_forced = q;
 							q = mem[p + 3] & 0xf; /* can be $f0 or $f2, q&0x0f as offset */
-							p = READ_LE_INT16(&mem[p + 0xe]); // mem[p + 0xe] | mem[p + 0xf] << 8;
+							p = READ_LE_UINT16(&mem[p + 0xe]); // mem[p + 0xe] | mem[p + 0xf] << 8;
 							if (mem[p - 2] == 0x4c && mem[p + 0xa0 + q] == 0x85) {
-								unp->_depAdr = READ_LE_INT16(&mem[p - 1]); // mem[p - 1] | mem[p] << 8;
-								unp->_strMem = READ_LE_INT16(&mem[p + 4]); // mem[p + 4] | mem[p + 5] << 8;
+								unp->_depAdr = READ_LE_UINT16(&mem[p - 1]); // mem[p - 1] | mem[p] << 8;
+								unp->_strMem = READ_LE_UINT16(&mem[p + 4]); // mem[p + 4] | mem[p + 5] << 8;
 								unp->_endAdr = 0xfa;
 								p += 0xa2;
 								q = p + 8;
 								for (; p < q; p++) {
 									if ((*(unsigned int *)(mem + p) == 0x2D85FAA5) &&
 										(mem[p + 9] == 0x4c)) {
-										unp->_retAdr = READ_LE_INT16(&mem[p + 0xa]); // mem[p + 0xa] | mem[p + 0xb] << 8;
+										unp->_retAdr = READ_LE_UINT16(&mem[p + 0xa]); // mem[p + 0xa] | mem[p + 0xb] << 8;
 										break;
 									}
 								}
diff --git a/engines/glk/scott/unp64/scanners/section8.cpp b/engines/glk/scott/unp64/scanners/section8.cpp
index c0e71f0038a..5485ffac96f 100644
--- a/engines/glk/scott/unp64/scanners/section8.cpp
+++ b/engines/glk/scott/unp64/scanners/section8.cpp
@@ -47,8 +47,8 @@ void scnSection8(UnpStr *unp) {
 		if (unp->_depAdr) {
 			if (unp->_info->_run == -1)
 				unp->_forced = p;
-			unp->_strMem = READ_LE_INT16(&mem[p + 0x47]); // mem[p + 0x47] | mem[p + 0x4b] << 8;
-			unp->_retAdr = READ_LE_INT16(&mem[p + 0x87]); // mem[p + 0x87] | mem[p + 0x88] << 8;
+			unp->_strMem = READ_LE_UINT16(&mem[p + 0x47]); // mem[p + 0x47] | mem[p + 0x4b] << 8;
+			unp->_retAdr = READ_LE_UINT16(&mem[p + 0x87]); // mem[p + 0x87] | mem[p + 0x88] << 8;
 			if (unp->_retAdr == 0xf7) {
 				unp->_retAdr = 0xa7ae;
 				mem[p + 0x87] = 0xae;
@@ -69,12 +69,12 @@ void scnSection8(UnpStr *unp) {
 			unp->_depAdr = 0x100;
 			if (unp->_info->_run == -1)
 				unp->_forced = 0x827;
-			unp->_strMem = READ_LE_INT16(&mem[0x86e]); // mem[0x86e] | mem[0x872] << 8;
+			unp->_strMem = READ_LE_UINT16(&mem[0x86e]); // mem[0x86e] | mem[0x872] << 8;
 			if (*(unsigned short int *)(mem + 0x8b7) == 0xff5b) {
 				mem[0x8b6] = 0x2c;
-				unp->_retAdr = READ_LE_INT16(&mem[0x8ba]); // mem[0x8ba] | mem[0x8bb] << 8;
+				unp->_retAdr = READ_LE_UINT16(&mem[0x8ba]); // mem[0x8ba] | mem[0x8bb] << 8;
 			} else {
-				unp->_retAdr = READ_LE_INT16(&mem[0x8b7]); // mem[0x8b7] | mem[0x8b8] << 8;
+				unp->_retAdr = READ_LE_UINT16(&mem[0x8b7]); // mem[0x8b7] | mem[0x8b8] << 8;
 			}
 			unp->_endAdr = 0xae;
 			unp->_idFlag = 1;
@@ -90,8 +90,8 @@ void scnSection8(UnpStr *unp) {
 			unp->_depAdr = 0x33c;
 			if (unp->_info->_run == -1)
 				unp->_forced = 0x812;
-			unp->_strMem = READ_LE_INT16(&mem[0x856]); // mem[0x856] | mem[0x85a] << 8;
-			unp->_retAdr = READ_LE_INT16(&mem[0x896]); // mem[0x896] | mem[0x897] << 8;
+			unp->_strMem = READ_LE_UINT16(&mem[0x856]); // mem[0x856] | mem[0x85a] << 8;
+			unp->_retAdr = READ_LE_UINT16(&mem[0x896]); // mem[0x896] | mem[0x897] << 8;
 			unp->_endAdr = 0xae;
 			unp->_idFlag = 1;
 			return;
diff --git a/engines/glk/scott/unp64/scanners/tbc_multicomp.cpp b/engines/glk/scott/unp64/scanners/tbc_multicomp.cpp
index 992f951d0bd..96301a90854 100644
--- a/engines/glk/scott/unp64/scanners/tbc_multicomp.cpp
+++ b/engines/glk/scott/unp64/scanners/tbc_multicomp.cpp
@@ -42,7 +42,7 @@ void scnTBCMultiComp(UnpStr *unp) {
 			if (mem[0x84a] == 0x81) {
 				if (*(unsigned int *)(mem + 0x820) == 0x32BDE9A2) {
 					unp->_forced = 0x820;
-					unp->_retAdr = READ_LE_INT16(&mem[0x8b2]); // mem[0x8b2] | mem[0x8b3] << 8;
+					unp->_retAdr = READ_LE_UINT16(&mem[0x8b2]); // mem[0x8b2] | mem[0x8b3] << 8;
 					if (unp->_retAdr == 0x1e1) {
 						if (*(unsigned int *)(mem + 0x916) == 0x4CA87120) {
 							p = *(unsigned short int *)(mem + 0x91a);
@@ -55,9 +55,9 @@ void scnTBCMultiComp(UnpStr *unp) {
 								unp->_retAdr = p;
 							}
 						} else if ((mem[0x916] == 0x4C) || (mem[0x916] == 0x20)) {
-							unp->_retAdr = READ_LE_INT16(&mem[0x917]); // mem[0x917] | mem[0x918] << 8;
+							unp->_retAdr = READ_LE_UINT16(&mem[0x917]); // mem[0x917] | mem[0x918] << 8;
 						} else if (mem[0x919] == 0x4c) {
-							unp->_retAdr = READ_LE_INT16(&mem[0x91a]); // mem[0x91a] | mem[0x91b] << 8;
+							unp->_retAdr = READ_LE_UINT16(&mem[0x91a]); // mem[0x91a] | mem[0x91b] << 8;
 						}
 					}
 					if ((unp->_retAdr == 0) && (mem[0x8b1] == 0)) {
@@ -73,18 +73,18 @@ void scnTBCMultiComp(UnpStr *unp) {
 			else if (mem[0x84a] == 0x7b) {
 				if (*(unsigned int *)(mem + 0x81d) == 0x32BDE9A2) {
 					unp->_forced = 0x81d;
-					unp->_retAdr = READ_LE_INT16(&mem[0x8ac]); // mem[0x8ac] | mem[0x8ad] << 8;
+					unp->_retAdr = READ_LE_UINT16(&mem[0x8ac]); // mem[0x8ac] | mem[0x8ad] << 8;
 					p = 0x8eb;
 				}
 			}
 			if (unp->_forced) {
 				unp->_depAdr = 0x100;
-				unp->_strMem = READ_LE_INT16(&mem[p + 1]); // mem[p + 1] | mem[p + 2] << 8;
+				unp->_strMem = READ_LE_UINT16(&mem[p + 1]); // mem[p + 1] | mem[p + 2] << 8;
 				q = p;
 				q += mem[p];
 				unp->_endAdr = 0;
 				for (; q > p; q -= 4) {
-					strtmp = READ_LE_INT16(&mem[q - 1]); //(mem[q - 1] | mem[q] << 8);
+					strtmp = READ_LE_UINT16(&mem[q - 1]); //(mem[q - 1] | mem[q] << 8);
 					if (strtmp == 0)
 						strtmp = 0x10000;
 					if (strtmp > unp->_endAdr)
@@ -111,14 +111,14 @@ void scnTBCMultiComp(UnpStr *unp) {
 				}
 			}
 			unp->_depAdr = 0x334;
-			unp->_retAdr = READ_LE_INT16(&mem[0x92a]); // mem[0x92a] | mem[0x92b] << 8;
+			unp->_retAdr = READ_LE_UINT16(&mem[0x92a]); // mem[0x92a] | mem[0x92b] << 8;
 			p = 0x94d;
-			unp->_strMem = READ_LE_INT16(&mem[p + 1]); // mem[p + 1] | mem[p + 2] << 8;
+			unp->_strMem = READ_LE_UINT16(&mem[p + 1]); // mem[p + 1] | mem[p + 2] << 8;
 			q = p;
 			q += mem[p];
 			unp->_endAdr = 0;
 			for (; q > p; q -= 4) {
-				strtmp = READ_LE_INT16(&mem[q - 1]); //(mem[q - 1] | mem[q] << 8);
+				strtmp = READ_LE_UINT16(&mem[q - 1]); //(mem[q - 1] | mem[q] << 8);
 				if (strtmp == 0)
 					strtmp = 0x10000;
 				if (strtmp > unp->_endAdr)
@@ -143,14 +143,14 @@ void scnTBCMultiComp(UnpStr *unp) {
 				}
 			}
 			unp->_depAdr = 0x100;
-			unp->_retAdr = READ_LE_INT16(&mem[0x8c5]); // mem[0x8c5] | mem[0x8c6] << 8;
+			unp->_retAdr = READ_LE_UINT16(&mem[0x8c5]); // mem[0x8c5] | mem[0x8c6] << 8;
 			p = 0x8fe;
-			unp->_strMem = READ_LE_INT16(&mem[p + 1]); // mem[p + 1] | mem[p + 2] << 8;
+			unp->_strMem = READ_LE_UINT16(&mem[p + 1]); // mem[p + 1] | mem[p + 2] << 8;
 			q = p;
 			q += mem[p];
 			unp->_endAdr = 0;
 			for (; q > p; q -= 4) {
-				strtmp = READ_LE_INT16(&mem[q - 1]); //(mem[q - 1] | mem[q] << 8);
+				strtmp = READ_LE_UINT16(&mem[q - 1]); //(mem[q - 1] | mem[q] << 8);
 				if (strtmp == 0)
 					strtmp = 0x10000;
 				if (strtmp > unp->_endAdr)
diff --git a/engines/glk/scott/unp64/scanners/tcs_crunch.cpp b/engines/glk/scott/unp64/scanners/tcs_crunch.cpp
index 50b46003934..063fff29443 100644
--- a/engines/glk/scott/unp64/scanners/tcs_crunch.cpp
+++ b/engines/glk/scott/unp64/scanners/tcs_crunch.cpp
@@ -34,7 +34,7 @@ void scnTCScrunch(UnpStr *unp) {
 	mem = unp->_mem;
 	if (unp->_depAdr == 0) {
 		if ((*(unsigned int *)(mem + 0x819) == 0x018536A9) && mem[0x81d] == 0x4c) {
-			p = READ_LE_INT16(&mem[0x81e]); // mem[0x81e] | mem[0x81f] << 8;
+			p = READ_LE_UINT16(&mem[0x81e]); // mem[0x81e] | mem[0x81f] << 8;
 			if (mem[p] == 0xa2 && mem[p + 2] == 0xbd &&
 				(*(unsigned int *)(mem + p + 0x05) == 0xE801109D) &&
 				((*(unsigned int *)(mem + p + 0x38) == 0x01524CFB) ||
@@ -46,7 +46,7 @@ void scnTCScrunch(UnpStr *unp) {
 			}
 		}
 		else if ((*(unsigned int *)(mem + 0x819) == 0x018534A9) && mem[0x81d] == 0x4c) {
-			p = READ_LE_INT16(&mem[0x81e]); // mem[0x81e] | mem[0x81f] << 8;
+			p = READ_LE_UINT16(&mem[0x81e]); // mem[0x81e] | mem[0x81f] << 8;
 			if (mem[p] == 0xa2 && mem[p + 2] == 0xbd &&
 				(*(unsigned int *)(mem + p + 0x05) == 0xE801109D) &&
 				(*(unsigned int *)(mem + p + 0x38) == 0x01304CFB)) {
@@ -55,7 +55,7 @@ void scnTCScrunch(UnpStr *unp) {
 				if (mem[unp->_forced] != 0x78)
 					unp->_forced++;
 				unp->_endAdr = 0x2d;
-				unp->_retAdr = READ_LE_INT16(&mem[p + 0xd9]); // mem[p + 0xd9] | mem[p + 0xda] << 8;
+				unp->_retAdr = READ_LE_UINT16(&mem[p + 0xd9]); // mem[p + 0xd9] | mem[p + 0xda] << 8;
 				p += 0xc8;
 				q = p + 6;
 				for (; p < q; p += 3) {
diff --git a/engines/glk/scott/unp64/scanners/xtc.cpp b/engines/glk/scott/unp64/scanners/xtc.cpp
index f312d53ecb3..24f692491cc 100644
--- a/engines/glk/scott/unp64/scanners/xtc.cpp
+++ b/engines/glk/scott/unp64/scanners/xtc.cpp
@@ -38,12 +38,12 @@ void scnXTC(UnpStr *unp) {
 			(*(unsigned int *)(mem + 0x819) == 0xC8000099) &&
 			(*(unsigned int *)(mem + 0x82c) == 0x4CF7D0CA) &&
 			mem[0x85c] == 0x99) {
-			unp->_retAdr = READ_LE_INT16(&mem[0x872]); // mem[0x872] | mem[0x873] << 8;
+			unp->_retAdr = READ_LE_UINT16(&mem[0x872]); // mem[0x872] | mem[0x873] << 8;
 			unp->_depAdr = 0x100;
 			unp->_forced = 0x80d; /* the ldy #$00 can be missing, skipped */
 			unp->_fEndAf = 0x121;
 			unp->_endAdC = 0xffff | EA_USE_Y;
-			unp->_strMem = READ_LE_INT16(&mem[0x85d]); // mem[0x85d] | mem[0x85e] << 8;
+			unp->_strMem = READ_LE_UINT16(&mem[0x85d]); // mem[0x85d] | mem[0x85e] << 8;
 			unp->_idFlag = 1;
 			return;
 		}
@@ -69,21 +69,21 @@ void scnXTC(UnpStr *unp) {
 			}
 		}
 		if (unp->_depAdr) {
-			unp->_retAdr = READ_LE_INT16(&mem[q + 0x16]); // mem[q + 0x16] | mem[q + 0x17] << 8;
+			unp->_retAdr = READ_LE_UINT16(&mem[q + 0x16]); // mem[q + 0x16] | mem[q + 0x17] << 8;
 			if (*(unsigned short int *)(mem + p) != 0x00a0)
 				unp->_forced = p + 2; /* the ldy #$00 can be missing, skipped */
 			else
 				unp->_forced = p;
 
-			unp->_fEndAf = READ_LE_INT16(&mem[q + 0x7]); // mem[q + 0x7] | mem[q + 0x8] << 8;
+			unp->_fEndAf = READ_LE_UINT16(&mem[q + 0x7]); // mem[q + 0x7] | mem[q + 0x8] << 8;
 			unp->_fEndAf--;
 			unp->_endAdC = 0xffff | EA_USE_Y;
-			unp->_strMem = READ_LE_INT16(&mem[q + 1]); // mem[q + 1] | mem[q + 2] << 8;
+			unp->_strMem = READ_LE_UINT16(&mem[q + 1]); // mem[q + 1] | mem[q + 2] << 8;
 			if (*(unsigned int *)(mem + q + 0x1f) == 0xDDD00285) {
 			} else if (*(unsigned int *)(mem + q + 0x1f) == 0xF620DFD0) {
 				/* rockstar's 2.2+ & shade/light's 2.4 are all the same */
 			} else { /* actually found to be Visiomizer 6.2/Zagon */
-				unp->_depAdr = READ_LE_INT16(&mem[p + 0x27]); // mem[p + 0x27] | mem[p + 0x28] << 8;
+				unp->_depAdr = READ_LE_UINT16(&mem[p + 0x27]); // mem[p + 0x27] | mem[p + 0x28] << 8;
 			}
 			unp->_idFlag = 1;
 			return;
@@ -95,10 +95,10 @@ void scnXTC(UnpStr *unp) {
 			(*(unsigned int *)(mem + 0x80b) == 0xF7D0C8FF) &&
 			(*(unsigned int *)(mem + 0x81b) == 0x00FC9D08) &&
 			(*(unsigned int *)(mem + 0x85b) == 0xD0D0FFE4)) {
-			unp->_depAdr = READ_LE_INT16(&mem[0x823]); // mem[0x823] | mem[0x824] << 8;
+			unp->_depAdr = READ_LE_UINT16(&mem[0x823]); // mem[0x823] | mem[0x824] << 8;
 			unp->_forced = 0x803;
-			unp->_retAdr = READ_LE_INT16(&mem[0x865]); // mem[0x865] | mem[0x866] << 8;
-			unp->_strMem = READ_LE_INT16(&mem[0x850]); // mem[0x850] | mem[0x851] << 8;
+			unp->_retAdr = READ_LE_UINT16(&mem[0x865]); // mem[0x865] | mem[0x866] << 8;
+			unp->_strMem = READ_LE_UINT16(&mem[0x850]); // mem[0x850] | mem[0x851] << 8;
 			unp->_endAdC = 0xffff | EA_USE_Y;
 			unp->_fEndAf = 0x128;
 			unp->_idFlag = 1;
@@ -112,10 +112,10 @@ void scnXTC(UnpStr *unp) {
 			 (*(unsigned int *)(mem + 0x80b) == 0xF7D0C8FF) &&
 			 (*(unsigned int *)(mem + 0x81b) == 0x00F59D08) &&
 			 (*(unsigned int *)(mem + 0x85b) == 0xD0D0F8E4)) {
-			unp->_depAdr = READ_LE_INT16(&mem[0x823]); // mem[0x823] | mem[0x824] << 8;
+			unp->_depAdr = READ_LE_UINT16(&mem[0x823]); // mem[0x823] | mem[0x824] << 8;
 			unp->_forced = 0x803;
-			unp->_retAdr = READ_LE_INT16(&mem[0x865]); // mem[0x865] | mem[0x866] << 8;
-			unp->_strMem = READ_LE_INT16(&mem[0x850]); // mem[0x850] | mem[0x851] << 8;
+			unp->_retAdr = READ_LE_UINT16(&mem[0x865]); // mem[0x865] | mem[0x866] << 8;
+			unp->_strMem = READ_LE_UINT16(&mem[0x850]); // mem[0x850] | mem[0x851] << 8;
 			unp->_endAdC = 0xffff | EA_USE_Y;
 			unp->_fEndAf = 0x121;
 			unp->_idFlag = 1;
@@ -145,12 +145,12 @@ void scnXTC(UnpStr *unp) {
 			}
 		}
 		if (unp->_depAdr) {
-			unp->_retAdr = READ_LE_INT16(&mem[q + 0x16]); // mem[q + 0x16] | mem[q + 0x17] << 8;
+			unp->_retAdr = READ_LE_UINT16(&mem[q + 0x16]); // mem[q + 0x16] | mem[q + 0x17] << 8;
 			unp->_forced = p + 2;
-			unp->_fEndAf = READ_LE_INT16(&mem[q + 0x7]); // mem[q + 0x7] | mem[q + 0x8] << 8;
+			unp->_fEndAf = READ_LE_UINT16(&mem[q + 0x7]); // mem[q + 0x7] | mem[q + 0x8] << 8;
 			unp->_fEndAf--;
 			unp->_endAdC = 0xffff | EA_USE_Y;
-			unp->_strMem = READ_LE_INT16(&mem[q + 1]); // mem[q + 1] | mem[q + 2] << 8;
+			unp->_strMem = READ_LE_UINT16(&mem[q + 1]); // mem[q + 1] | mem[q + 2] << 8;
 			unp->_idFlag = 1;
 			return;
 		}


Commit: 5b032ee851e48a192d01d0f677369b84a570e01f
    https://github.com/scummvm/scummvm/commit/5b032ee851e48a192d01d0f677369b84a570e01f
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Fix out-of-bound errors

Changed paths:
    engines/glk/scott/c64_checksums.cpp
    engines/glk/scott/saga_draw.cpp


diff --git a/engines/glk/scott/c64_checksums.cpp b/engines/glk/scott/c64_checksums.cpp
index 797161c3034..00df33c9707 100644
--- a/engines/glk/scott/c64_checksums.cpp
+++ b/engines/glk/scott/c64_checksums.cpp
@@ -95,7 +95,7 @@ static C64Rec g_C64Registry[] = {
 int decrunchC64(uint8_t **sf, size_t *extent, C64Rec entry);
 
 uint8_t *getLargestFile(uint8_t *data, int length, int *newlength) {
-	uint8_t *file = NULL;
+	uint8_t *file = nullptr;
 	*newlength = 0;
 	DiskImage *d64 = diCreateFromData(data, length);
 	if (d64) {
@@ -103,9 +103,10 @@ uint8_t *getLargestFile(uint8_t *data, int length, int *newlength) {
 		if (largest) {
 			ImageFile *c64file = diOpen(d64, largest->_rawname, largest->_type, "rb");
 			if (c64file) {
-				int expectedsize = largest->_sizelo + largest->_sizehi * 0x100;
-				file = new uint8_t[expectedsize];
-				*newlength = diRead(c64file, file, 0xffff);
+				uint8_t *largeFile = new uint8_t[0xffff];
+				*newlength = diRead(c64file, largeFile, 0xffff);
+				file = new uint8_t[*newlength];
+				memcpy(file, largeFile, *newlength);
 			}
 		}
 		//di_free_image(d64);
@@ -369,10 +370,14 @@ int decrunchC64(uint8_t **sf, size_t *extent, C64Rec record) {
 			_G(_fileLength) = decompressedLength;
 		} else {
 			delete[] uncompressed;
+			uncompressed = nullptr;
 			break;
 		}
 	}
 
+	if (uncompressed != nullptr)
+		delete[] uncompressed;
+
 	for (int i = 0; i < NUMGAMES; i++) {
 		if (_G(_games)[i]._gameID == record._id) {
 			_G(_game) = &_G(_games)[i];
diff --git a/engines/glk/scott/saga_draw.cpp b/engines/glk/scott/saga_draw.cpp
index 84da8b02148..e3a4f7ce133 100644
--- a/engines/glk/scott/saga_draw.cpp
+++ b/engines/glk/scott/saga_draw.cpp
@@ -108,6 +108,8 @@ void plotsprite(int32_t character, int32_t x, int32_t y, int32_t fg, int32_t bg)
 }
 
 void transform(int32_t character, int32_t flipMode, int32_t ptr) {
+	if (character > 255)
+		return;
 	uint8_t work[8];
 	int32_t i;
 


Commit: fd3b9bede3bbd11acb229bc5978b6036e1742884
    https://github.com/scummvm/scummvm/commit/fd3b9bede3bbd11acb229bc5978b6036e1742884
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Add language data to detected game

Changed paths:
    engines/glk/scott/detection.cpp


diff --git a/engines/glk/scott/detection.cpp b/engines/glk/scott/detection.cpp
index 221bc70dc46..2a845ed4fcd 100644
--- a/engines/glk/scott/detection.cpp
+++ b/engines/glk/scott/detection.cpp
@@ -101,7 +101,7 @@ bool ScottMetaEngine::detectGames(const Common::FSList &fslist, DetectedGames &g
 		} else {
 			// Found a match
 			PlainGameDescriptor gameDesc = findGame(p->_gameId);
-			gameList.push_back(GlkDetectedGame(p->_gameId, gameDesc.description, filename));
+			gameList.push_back(GlkDetectedGame(p->_gameId, gameDesc.description, filename, p->_language));
 		}
 	}
 


Commit: 1e914b7e95122db0acde241ae803e26faf900615
    https://github.com/scummvm/scummvm/commit/1e914b7e95122db0acde241ae803e26faf900615
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Add support for Gremlins

Changed paths:
  A engines/glk/scott/gremlins.cpp
  A engines/glk/scott/gremlins.h
    engines/glk/module.mk
    engines/glk/scott/c64_checksums.cpp
    engines/glk/scott/detection_tables.h
    engines/glk/scott/disk_image.cpp
    engines/glk/scott/games.h
    engines/glk/scott/globals.cpp
    engines/glk/scott/globals.h
    engines/glk/scott/load_game.cpp
    engines/glk/scott/scott.cpp
    engines/glk/scott/scott.h
    engines/glk/scott/unp64/unp64.cpp


diff --git a/engines/glk/module.mk b/engines/glk/module.mk
index 257ce7d3ecf..cea82826d22 100644
--- a/engines/glk/module.mk
+++ b/engines/glk/module.mk
@@ -244,6 +244,7 @@ MODULE_OBJS := \
 	scott/game_info.o \
 	scott/game_specific.o \
 	scott/globals.o \
+	scott/gremlins.o \
 	scott/hulk.o \
 	scott/layout_text.o \
 	scott/line_drawing.o \
diff --git a/engines/glk/scott/c64_checksums.cpp b/engines/glk/scott/c64_checksums.cpp
index 00df33c9707..e8fa959261b 100644
--- a/engines/glk/scott/c64_checksums.cpp
+++ b/engines/glk/scott/c64_checksums.cpp
@@ -89,6 +89,14 @@ static C64Rec g_C64Registry[] = {
 	{ ROBIN_OF_SHERWOOD_C64, 0xb690,  0x7b61, TYPE_T64, 1, nullptr, nullptr, 0, 0x9702, 0x9627, 0x2000 }, // Robin Of Sherwood C64 (T64) alt * TCS Cruncher v2.0
 	{ ROBIN_OF_SHERWOOD_C64, 0x8db6,  0x7853, TYPE_T64, 1, nullptr, nullptr, 0, 0xd7fb, 0xbd20, 0x2000 }, // Robin Of Sherwood T64 alt 2 * PUCrunch
 
+	{ GREMLINS_C64,			0xdd94,		0x25a8, TYPE_T64, 1, nullptr,	nullptr, 0 },                                 // Gremlins C64 (T64) version * Action Replay v4.x
+	{ GREMLINS_C64,			0x2ab00,	0xc402, TYPE_D64, 0, nullptr,	"G1",	-0x8D },                               // Gremlins C64 (D64) version
+	{ GREMLINS_C64,			0x2ab00,	0x3ccf, TYPE_D64, 0, nullptr,	"G1",	-0x8D },                               // Gremlins C64 (D64) version 2
+	{ GREMLINS_C64,			0x2ab00,	0xabf8, TYPE_D64, 2, "-e0x1255",nullptr, 2 },                             // Gremlins C64 (D64) version alt * ByteBoiler, Exomizer
+	{ GREMLINS_C64,			0x2ab00,	0xa265, TYPE_D64, 2, "-e0x1255",nullptr, 2 },                             // Gremlins C64 (D64)  version alt 2 * ByteBoiler, Exomizer
+	{ GREMLINS_GERMAN_C64,	0xc003,		0x558c, TYPE_T64, 1, nullptr,	nullptr, 0, 0xd801, 0xc6c0, 0x1f00 },  // German Gremlins C64 (T64) version * TBC Multicompactor v2.x
+	{ GREMLINS_GERMAN_C64,	0x2ab00,	0x6729, TYPE_D64, 2, nullptr,	nullptr, 0, 0xdc02, 0xcac1, 0x1f00 }, // German Gremlins C64 (D64) version * Exomizer
+
 	{ UNKNOWN_GAME, 0, 0, UNKNOWN_FILE_TYPE, 0, nullptr, nullptr, 0, 0, 0, 0 }
 };
 
diff --git a/engines/glk/scott/detection_tables.h b/engines/glk/scott/detection_tables.h
index ea0514bec78..af1b929b7da 100644
--- a/engines/glk/scott/detection_tables.h
+++ b/engines/glk/scott/detection_tables.h
@@ -84,6 +84,7 @@ const PlainGameDescriptor SCOTT_GAME_LIST[] = {
 	{ "minersadv",         "Miner's Adventure" },
 	{ "romulanadv",        "Romulan Adventure" },
 	{ "topsecretadv",      "Top Secret Adventure" },
+	{ "gremlins",		   "Gremlins" },
 
 	{ nullptr, nullptr }
 };
@@ -163,7 +164,6 @@ const GlkDetectionEntry SCOTT_GAMES[] = {
 
 	// ZX Spectrum games
 	DT_ENTRY1("marveladventure", "ZXSpectrum", "0eec511d3cde815c73e5464ab0cdbef9", 40727),
-	DT_ENTRY1("gremlins",		 "ZXSpectrum", "4200b260b484a3a9766d587def3113a2", 45332),
 
 	// 11 Mysterious Adventures
 	DT_ENTRY1("goldenbaton",	"ZXSpectrum", "cb7dadc9d5f8bce453b9139265e4dd7d", 32060),
@@ -181,6 +181,10 @@ const GlkDetectionEntry SCOTT_GAMES[] = {
 	// C64 Games
 	DT_ENTRY1("robinofsherwood", "C64", "10109d9776b9372f9c768b53a664b113", 174848),
 	DT_ENTRY1("robinofsherwood", "C64", "552c95ec15d750cbfa02c1f11dcbca1e", 36278),
+	DT_ENTRY1("gremlins",		 "C64", "33c920f7ba150dfa1a832d510eebd8fe", 174848),
+	DT_ENTRY1("gremlins",		 "C64", "947e35037cf02269ac013857925137ce", 174848),
+	DT_ENTRY1("gremlins",		 "C64", "108063b2a16a199794f2ecf52ce26377", 56724),
+	DT_ENTRYL1("gremlins", Common::DE_DEU, "C64", "e5d743d8727c8aca011a737bbb5ad818", 49155),
 
 	// 11 Mysterious Adventures
 	DT_ENTRY1("mysadv1", "C64", "b4d8fc4eabed4f2400717303561ad0fa", 174848),
diff --git a/engines/glk/scott/disk_image.cpp b/engines/glk/scott/disk_image.cpp
index 972c74c8f57..deb7e21d27d 100644
--- a/engines/glk/scott/disk_image.cpp
+++ b/engines/glk/scott/disk_image.cpp
@@ -523,13 +523,13 @@ int diGetBlockNum(ImageType type, TrackSector ts) {
 		if (ts._track < 18) {
 			block = (ts._track - 1) * 21;
 		} else if (ts._track < 25) {
-			block = (ts._track - 18) * 19 + 17 * 21;
+ 			block = (ts._track - 18) * 19 + 17 * 21;
 		} else if (ts._track < 31) {
 			block = (ts._track - 25) * 18 + 17 * 21 + 7 * 19;
 		} else {
 			block = (ts._track - 31) * 17 + 17 * 21 + 7 * 19 + 6 * 18;
 		}
-		return block + ts._sector;
+        return block + ts._sector;
 		break;
 	case D71:
 		if (ts._track > 35) {
diff --git a/engines/glk/scott/games.h b/engines/glk/scott/games.h
index 4a0f8fe1d64..6f6c9ea8ce0 100644
--- a/engines/glk/scott/games.h
+++ b/engines/glk/scott/games.h
@@ -1105,5 +1105,260 @@ const GameInfo _games[NUMGAMES] = {
 			 90,     // number_of_pictures
 			 C64B,   // palette
 			 4,      // picture_format_version
+			 0),
+	GameInfo("Gremlins",
+			 GREMLINS,
+			 GREMLINS_VARIANT,         // type
+			 ENGLISH,                  // subtype
+			 FOUR_LETTER_UNCOMPRESSED, // dictionary type
+
+			 99,  // Number of items
+			 236, // Number of actions
+			 126, // Number of words
+			 42,  // Number of rooms
+			 6,   // Max carried items
+			 4,   // Word length
+			 98,  // Number of messages
+
+			 115, // number_of_verbs
+			 126, // number_of_nouns;
+
+			 0x2370, // header
+			 LATE,   // header style
+
+			 0x3a09,  // room images
+			 FOLLOWS, // item flags
+			 FOLLOWS, // item images
+
+			 0x3afe,     // actions
+			 COMPRESSED, // actions_style;
+			 0x45e5,     // dictionary
+			 FOLLOWS,    // start_of_room_descriptions;
+			 FOLLOWS,    // start_of_room_connections;
+			 FOLLOWS,    // start_of_messages;
+			 FOLLOWS,    // start_of_item_descriptions;
+			 FOLLOWS,    // start_of_item_locations;
+			 0x2426,     // start_of_system_messages
+			 0x25f6,     // start of directions
+
+			 0x5be1, // start_of_characters;
+			 0x63e1, // start_of_image_data
+			 0x64e1, // image_address_offset
+			 78,     // number_of_pictures;
+			 ZXOPT,  // palette
+			 3,      // picture_format_version;
+			 0),
+	GameInfo("Gremlins (alternative)",
+			 GREMLINS_ALT,
+			 GREMLINS_VARIANT,         // type
+			 ENGLISH,                  // subtype
+			 FOUR_LETTER_UNCOMPRESSED, // dictionary type
+
+			 99,  // Number of items
+			 236, // Number of actions
+			 126, // Number of words
+			 42,  // Number of rooms
+			 6,   // Max carried items
+			 4,   // Word length
+			 98,  // Number of messages
+
+			 115, // number_of_verbs
+			 126, // number_of_nouns;
+
+			 0x2378, // header
+			 LATE,   // header style
+
+			 0x3a0d,  // room images
+			 FOLLOWS, // item flags
+			 FOLLOWS, // item images
+
+			 0x3b02,     // actions
+			 COMPRESSED, // actions_style;
+			 0x45e5,     // dictionary
+			 FOLLOWS,    // start_of_room_descriptions;
+			 FOLLOWS,    // start_of_room_connections;
+			 FOLLOWS,    // start_of_messages;
+			 FOLLOWS,    // start_of_item_descriptions;
+			 FOLLOWS,    // start_of_item_locations;
+			 0x242e,     // start_of_system_messages
+			 0x25FE,     // start of directions
+
+			 0x5bdd, // start_of_characters;
+			 0x63dd, // start_of_image_data
+			 0x64dd, // image_address_offset
+			 78,     // number_of_pictures;
+			 ZXOPT,  // palette
+			 3,      // picture_format_version;
+			 0),
+	GameInfo("Gremlins (German)",
+			 GREMLINS_GERMAN,
+			 GREMLINS_VARIANT, // type
+			 LOCALIZED,        // subtype
+			 GERMAN,           // dictionary type
+
+			 99,  // Number of items
+			 236, // Number of actions
+			 126, // Number of words
+			 42,  // Number of rooms
+			 6,   // Max carried items
+			 5,   // Word length
+			 98,  // Number of messages
+
+			 115, // number_of_verbs
+			 126, // number_of_nouns
+
+			 0x237d, // header
+			 LATE,   // header style
+
+			 0x3a07,  // room images
+			 FOLLOWS, // item flags
+			 FOLLOWS, // item images
+
+			 0x3afc, // actions
+			 COMPRESSED,
+			 0x45d9,  // dictionary
+			 FOLLOWS, // start_of_room_descriptions;
+			 FOLLOWS, // start_of_room_connections;
+			 FOLLOWS, // start_of_messages;
+			 FOLLOWS, // start_of_item_descriptions;
+			 FOLLOWS, // start_of_item_locations;
+
+			 0x23de, // start_of_system_messages
+			 0x2623, // start of directions
+
+			 0x643e, // start_of_characters
+			 0x6c3e, // start_of_image_data
+			 0x6d3e, // image_address_offset
+			 72,     // number_of_pictures;
+			 ZX,     // palette
+			 3,      // picture_format_version;
+			 0),
+	GameInfo("Gremlins C64",
+			 GREMLINS_C64,
+			 GREMLINS_VARIANT,                    // type
+			 static_cast<Subtype>(ENGLISH | C64), // subtype
+			 FOUR_LETTER_UNCOMPRESSED,            // dictionary type
+
+			 99,  // Number of items
+			 243, // Number of actions
+			 126, // Number of words
+			 42,  // Number of rooms
+			 6,   // Max carried items
+			 4,   // Word length
+			 99,  // Number of messages
+
+			 115, // number_of_verbs
+			 126, // number_of_nouns;
+
+			 0x4584,              // header
+			 GREMLINS_C64_HEADER, // header style
+
+			 0x465e,  // room images
+			 FOLLOWS, // item flags
+			 FOLLOWS, // item images
+
+			 0x4751,     // actions
+			 COMPRESSED, // actions_style;
+			 0x527f,     // dictionary
+			 FOLLOWS,    // start_of_room_descriptions;
+			 FOLLOWS,    // start_of_room_connections;
+			 FOLLOWS,    // start_of_messages;
+			 FOLLOWS,    // start_of_item_descriptions;
+			 0x4596,     // start_of_item_locations;
+			 0x0a5e,     // start_of_system_messages
+			 0x0a5e,     // start of directions
+
+			 0x6a01, // start_of_characters;
+			 0x7201, // start_of_image_data
+			 0x7301, // image_address_offset
+			 91,     // number_of_pictures;
+			 C64B,   // palette
+			 3,      // picture_format_version;
+			 0),
+	GameInfo("Gremlins (German, C64)",
+			 GREMLINS_GERMAN_C64,
+			 GREMLINS_VARIANT,                      // type
+			 static_cast<Subtype>(LOCALIZED | C64), // subtype
+			 FIVE_LETTER_COMPRESSED,                // dictionary type
+
+			 99,  // Number of items
+			 243, // Number of actions
+			 125, // Number of words
+			 42,  // Number of rooms
+			 6,   // Max carried items
+			 5,   // Word length
+			 98,  // Number of messages
+
+			 125, // number_of_verbs
+			 124, // number_of_nouns
+
+			 0x4bb2,              // header
+			 GREMLINS_C64_HEADER, // header style
+
+			 0x4c8c,  // room images
+			 FOLLOWS, // item flags
+			 FOLLOWS, // item images
+
+			 0x4d81, // actions
+			 COMPRESSED,
+			 0x585e,  // dictionary
+			 FOLLOWS, // start_of_room_descriptions;
+			 FOLLOWS, // start_of_room_connections;
+			 FOLLOWS, // start_of_messages;
+			 FOLLOWS, // start_of_item_descriptions;
+			 0x4bc4,  // start_of_item_locations;
+
+			 0x1325, // start_of_system_messages
+			 0x1325, // start of directions
+
+			 0x76c5, // start_of_characters
+			 0x7cfd, // start_of_image_data
+			 0x7db3, // image_address_offset
+			 91,     // number_of_pictures;
+			 C64B,   // palette
+			 3,      // picture_format_version;
+			 0),
+	GameInfo("Gremlins (Spanish)",
+			 GREMLINS_SPANISH,
+			 GREMLINS_VARIANT, // type
+			 LOCALIZED,        // subtype
+			 SPANISH,          // dictionary type
+
+			 99,  // Number of items
+			 236, // Number of actions
+			 126, // Number of words
+			 42,  // Number of rooms
+			 6,   // Max carried items
+			 4,   // Word length
+			 98,  // Number of messages
+
+			 115, // number_of_verbs
+			 126, // number_of_nouns
+
+			 0x23c5, // header
+			 LATE,   // header style
+
+			 0x3993,  // room images
+			 FOLLOWS, // item flags
+			 FOLLOWS, // item images
+
+			 0x3a88, // actions
+			 COMPRESSED,
+			 0x455f,  // dictionary
+			 FOLLOWS, // start_of_room_descriptions;
+			 FOLLOWS, // start_of_room_connections;
+			 FOLLOWS, // start_of_messages;
+			 FOLLOWS, // start_of_item_descriptions;
+			 FOLLOWS, // start_of_item_locations;
+
+			 0x2426, // start_of_system_messages
+			 0x25c4, // start of directions
+
+			 0x6171, // start_of_characters
+			 0x6971, // start_of_image_data
+			 0x6A71, // image_address_offset
+			 74,     // number_of_pictures;
+			 ZXOPT,  // palette
+			 3,      // picture_format_version;
 			 0)
 };
diff --git a/engines/glk/scott/globals.cpp b/engines/glk/scott/globals.cpp
index f27aaf89f27..b0c86a0e203 100644
--- a/engines/glk/scott/globals.cpp
+++ b/engines/glk/scott/globals.cpp
@@ -73,6 +73,25 @@ Globals::Globals() : _sys(MAX_SYSMESS), _directions(NUMBER_OF_DIRECTIONS), _extr
 
 	_englishDelimiterList = {nullptr, ",", "and", "then", " "};
 
+	_spanishDirections = {nullptr, "norte", "sur", "este", "oeste", "arriba", "abajo", "n", "s", "e", "o", "u", "d", "w"};
+
+	_germanDirections = {nullptr, "norden", "sueden", "osten", "westen", "oben", "unten", "n", "s", "o", "w", "u", "d", " "};
+
+	_germanExtraCommands = {nullptr, "restart", "save", "restore", "load", "transcript", "script", "oops", "undo", "ram", "ramload", "ramrestore", "ramsave",
+							"ausser", "bis", "laden", "wiederherstellen", "transkript", "rueckgaengig", "neustarten"};
+
+	_spanishExtraCommands = {nullptr, "restart", "save", "restore", "load", "transcript", "script", "oops", "undo", "ram", "ramload", "ramrestore", "ramsave",
+							 "excepto", "menos", "reanuda", "cargar", "transcripcion", "deshacer", "reinicia"};
+
+	_germanExtraNouns = {nullptr, "spiel", "story", "on", "off", "wiederherstellen", "laden", "speichern", "move", "verschieben", "runde",
+						 "alle", "alles", "es", "einschalten", "ausschalten"};
+
+	_spanishExtraNouns = {nullptr, "juego", "story", "on", "off", "cargar", "reanuda", "conserva", "move", "command", "jugada", "toda", "todo", "eso", "activar", "desactivar"};
+
+	_germanSkipList = {nullptr, "nach", "die", "der", "das", "im", "mein", "meine", "an", "auf", "den", "lassen", "lass", "fallen", " ", " ", " ", " "};
+
+	_germanDelimiterList = {nullptr, ",", "und", "dann", "and"};
+
 	Common::fill(&_counters[0], &_counters[16], 0);
 	Common::fill(&_roomSaved[0], &_roomSaved[16], 0);
 
@@ -92,6 +111,10 @@ Globals::Globals() : _sys(MAX_SYSMESS), _directions(NUMBER_OF_DIRECTIONS), _extr
 	_md5Index.setVal("3ce5ea1a0473244bf469fd3c51f1dc48",  6); // midadv2
 	_md5Index.setVal("10109d9776b9372f9c768b53a664b113", 12); // robin of sherwood
 	_md5Index.setVal("552c95ec15d750cbfa02c1f11dcbca1e", 15); // robin of sherwood
+	_md5Index.setVal("108063b2a16a199794f2ecf52ce26377", 16); // gremlins
+	_md5Index.setVal("947e35037cf02269ac013857925137ce", 17); // gremlins
+	_md5Index.setVal("33c920f7ba150dfa1a832d510eebd8fe", 19); // gremlins
+	_md5Index.setVal("e5d743d8727c8aca011a737bbb5ad818", 21); // gremlins
 }
 
 Globals::~Globals() {
diff --git a/engines/glk/scott/globals.h b/engines/glk/scott/globals.h
index a24739c04f3..c58deb240ea 100644
--- a/engines/glk/scott/globals.h
+++ b/engines/glk/scott/globals.h
@@ -152,6 +152,14 @@ public:
 	Common::Array<ExtraCommand> _extraCommandsKey;
 	Common::StringArray _abbreviations;
 	Common::StringArray _abbreviationsKey;
+	Common::StringArray _spanishDirections;
+	Common::StringArray _germanDirections;
+	Common::StringArray _germanExtraCommands;
+	Common::StringArray _spanishExtraCommands;
+	Common::StringArray _germanExtraNouns;
+	Common::StringArray _spanishExtraNouns;
+	Common::StringArray _germanSkipList;
+	Common::StringArray _germanDelimiterList;
 
 	// restore state
 	int _justUndid = 0;
diff --git a/engines/glk/scott/gremlins.cpp b/engines/glk/scott/gremlins.cpp
new file mode 100644
index 00000000000..d7b90cee78c
--- /dev/null
+++ b/engines/glk/scott/gremlins.cpp
@@ -0,0 +1,335 @@
+/* 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/>.
+ *
+ */
+
+/*
+ * Based on ScottFree interpreter version 1.14 developed by Swansea
+ * University Computer Society without disassembly of any other game
+ * drivers, only of game databases as permitted by EEC law (for purposes
+ * of compatibility).
+ *
+ * Licensed under GPLv2
+ *
+ * https://github.com/angstsmurf/spatterlight/tree/master/terps/scott
+ */
+
+#include "glk/scott/scott.h"
+#include "glk/scott/command_parser.h"
+#include "glk/scott/saga_draw.h"
+#include "glk/scott/globals.h"
+
+namespace Glk {
+namespace Scott {
+
+#define GREMLINS_ANIMATION_RATE 670
+
+void updateGremlinsAnimations(void) {
+	if (_G(_rooms)[MY_LOC]._image == 255) {
+		g_scott->glk_request_timer_events(0);
+		return;
+	}
+	g_scott->openGraphicsWindow();
+	if (_G(_graphics) == nullptr) {
+		g_scott->glk_request_timer_events(0);
+		return;
+	}
+
+	int timer_delay = GREMLINS_ANIMATION_RATE;
+	switch (MY_LOC) {
+	case 1:                          /* Bedroom */
+		if (_G(_items)[50]._location == 1) /* Gremlin throwing darts */
+		{
+			if (_G(_animationFlag)) {
+				g_scott->drawImage(60); /* Gremlin throwing dart frame 1 */
+			} else {
+				g_scott->drawImage(59); /* Gremlin throwing dart frame 2 */
+			}
+		}
+		break;
+	case 17:                          /* Dotty's Tavern */
+		if (_G(_items)[82]._location == 17) /* Gang of GREMLINS */
+		{
+			if (_G(_animationFlag)) {
+				g_scott->drawImage(49); /* Gremlin hanging from curtains frame 1 */
+				g_scott->drawImage(51); /* Gremlin ear frame 1 */
+				g_scott->drawImage(54); /* Gremlin's mouth frame 1 */
+			} else {
+				g_scott->drawImage(50); /* Gremlin hanging from curtains frame 2 */
+				g_scott->drawImage(52); /* Gremlin ear frame 2 */
+				g_scott->drawImage(53); /* Gremlin's mouth frame 2 */
+			}
+		}
+		break;
+	case 16:                          /* Behind a Bar */
+		if (_G(_items)[82]._location == 16) /* Gang of GREMLINS */
+		{
+			if (_G(_animationFlag)) {
+				g_scott->drawImage(57); /* Flasher gremlin frame 1 */
+				g_scott->drawImage(24); /* Gremlin tongue frame 1 */
+				if (CURRENT_GAME == GREMLINS_GERMAN)
+					g_scott->drawImage(46); /* Gremlin ear frame 1 */
+				else
+					g_scott->drawImage(73); /* Gremlin ear frame 1 */
+			} else {
+				g_scott->drawImage(58); /* Flasher gremlin frame 2 */
+
+				if (CURRENT_GAME == GREMLINS_GERMAN) {
+					g_scott->drawImage(33); /* Gremlin tongue frame 2 */
+					g_scott->drawImage(23); /* Gremlin ear frame 2 */
+				} else {
+					g_scott->drawImage(72); /* Gremlin tongue frame 2 */
+					if (CURRENT_GAME == GREMLINS_SPANISH)
+						g_scott->drawImage(23); /* Gremlin ear frame 2 */
+					else
+						g_scott->drawImage(74); /* Gremlin ear frame 2 */
+				}
+			}
+		}
+		break;
+	case 19:                          /* Square */
+		if (_G(_items)[82]._location == 19) /* Gang of GREMLINS */
+		{
+			if (_G(_animationFlag)) {
+				g_scott->drawImage(55); /* Silhouette of Gremlins frame 1 */
+			} else {
+				g_scott->drawImage(71); /* Silhouette of Gremlins frame 1 */
+			}
+		}
+		break;
+	case 6:                          /* on a road */
+		if (_G(_items)[82]._location == 6) /* Gang of GREMLINS */
+		{
+			if (_G(_animationFlag)) {
+				if ((_G(_game)->_subType & (LOCALIZED | C64)) == LOCALIZED) {
+					g_scott->drawImage(25); /* Silhouette 2 of Gremlins  */
+				} else {
+					g_scott->drawImage(75); /* Silhouette 2 of Gremlins  */
+				}
+			} else {
+				g_scott->drawImage(48); /* Silhouette 2 of Gremlins flipped */
+			}
+		}
+		break;
+	case 3:                   /* Kitchen */
+		if (_G(_counters)[2] == 2) /* Blender is on */
+		{
+			if (_G(_animationFlag)) {
+				g_scott->drawImage(56); /* Blended Gremlin */
+			} else {
+				g_scott->drawImage(12); /* Blended Gremlin flipped */
+			}
+		}
+		break;
+	default:
+		timer_delay = 0;
+		break;
+	}
+	_G(_animationFlag) = (_G(_animationFlag) == 0);
+	g_scott->glk_request_timer_events(timer_delay);
+}
+
+void gremlinsLook(void) {
+	if (_G(_rooms)[MY_LOC]._image != 255) {
+		if (MY_LOC == 17 && _G(_items)[82]._location == 17)
+			g_scott->drawImage(45); /* Bar full of Gremlins */
+		else
+			g_scott->drawImage(_G(_rooms)[MY_LOC]._image);
+		_G(_animationFlag) = 0;
+		updateGremlinsAnimations();
+	}
+	/* Ladder image at the top of the department store */
+	if (MY_LOC == 34 && _G(_items)[53]._location == MY_LOC) {
+		g_scott->drawImage(42);
+	} else if (MY_LOC == 10 && _G(_items)[15]._location == 0) {
+		if (_G(_items)[99]._location == MY_LOC && CURRENT_GAME == GREMLINS_GERMAN_C64)
+			g_scott->drawImage(90); /* Dazed Stripe */
+		g_scott->drawImage(82);     /* Empty pool with puddle */
+		/* Draw puddle on top of Stripe */
+		/* Doesn't look great, but better than the other way round */
+	}
+}
+
+void fillInGermanSystemMessages() {
+	_G(_sys)[I_DONT_KNOW_HOW_TO] = "Ich weiss nicht, wie man etwas \"";
+	_G(_sys)[SOMETHING] = "\" macht. ";
+	_G(_sys)[I_DONT_KNOW_WHAT_A] = "\"";
+	_G(_sys)[IS] = "\" kenne ich nicht. ";
+	_G(_sys)[YES] = "Ja";
+	_G(_sys)[NO] = "Nein";
+	_G(_sys)[ANSWER_YES_OR_NO] = "Antworte Ja oder Nein.\n";
+	_G(_sys)[I_DONT_UNDERSTAND] = "Ich verstehe nicht. ";
+	_G(_sys)[ARE_YOU_SURE] = "Sind Sie sicher? ";
+	_G(_sys)[NOTHING_HERE_TO_TAKE] = "Hier gibt es nichts zu nehmen. ";
+	_G(_sys)[YOU_HAVE_NOTHING] = "Ich traege nichts. ";
+	_G(_sys)[MOVE_UNDONE] = "Verschieben rueckgaengig gemacht. ";
+	_G(_sys)[CANT_UNDO_ON_FIRST_TURN] = "Sie koennen die erste Runde nicht rueckgaengig machen. ";
+	_G(_sys)[NO_UNDO_STATES] = "Keine rueckgaengig-Zustaende mehr gespeichert. ";
+	_G(_sys)[SAVED] = "Spiel gespeichert. ";
+	_G(_sys)[CANT_USE_ALL] = "Sie koennen ALLES nicht mit diesem Verb verwenden. ";
+	_G(_sys)[TRANSCRIPT_ON] = "Das Transkript ist jetzt eingeschaltet. ";
+	_G(_sys)[TRANSCRIPT_OFF] = "Das Transkript ist jetzt deaktiviert. ";
+	_G(_sys)[NO_TRANSCRIPT] = "Es wird kein Transkript ausgefuehrt. ";
+	_G(_sys)[TRANSCRIPT_ALREADY] = "Eine Transkript laeuft bereits. ";
+	_G(_sys)[FAILED_TRANSCRIPT] = "Transkriptdatei konnte nicht erstellt werden. ";
+	_G(_sys)[TRANSCRIPT_START] = "Beginn einer Transkript.\n\n";
+	_G(_sys)[TRANSCRIPT_END] = "\n\nEnde eniner Transkript.\n";
+	_G(_sys)[BAD_DATA] = "SCHLECHTE DATEN! Ungueltige Speicherdatei.\n";
+	_G(_sys)[STATE_SAVED] = "Zustand speichern.\n";
+	_G(_sys)[NO_SAVED_STATE] = "Es ist kein gespeicherter Zustand vorhanden.\n";
+	_G(_sys)[STATE_RESTORED] = "Zustand wiederhergestellt.\n";
+
+	_G(_sys)[YOU_ARE] = "Ich bin ";
+	_G(_sys)[WHAT] = _G(_sys)[HUH];
+
+	for (int i = 0; i < NUMBER_OF_DIRECTIONS; i++)
+		_G(_directions)[i] = _G(_germanDirections)[i];
+	for (int i = 0; i < NUMBER_OF_SKIPPABLE_WORDS; i++)
+		_G(_skipList)[i] = _G(_germanSkipList)[i];
+	for (int i = 0; i < NUMBER_OF_DELIMITERS; i++)
+		_G(_delimiterList)[i] = _G(_germanDelimiterList)[i];
+	for (int i = 0; i < NUMBER_OF_EXTRA_COMMANDS; i++)
+		_G(_extraCommands)[i] = _G(_germanExtraCommands)[i];
+	for (int i = 0; i < NUMBER_OF_EXTRA_NOUNS; i++)
+		_G(_extraNouns)[i] = _G(_germanExtraNouns)[i];
+}
+
+void loadExtraGermanGremlinsc64Data() {
+	_G(_verbs)[0] = "AUTO\0";
+	_G(_nouns)[0] = "ANY\0";
+	_G(_nouns)[28] = "*Y.M.C\0";
+
+	// These are broken in some versions
+	_G(_actions)[0]._condition[0] = 1005;
+	_G(_actions)[6]._vocab = 100;
+
+	_G(_gameHeader)->_numActions = 236;
+
+	SysMessageType messagekey[] = {
+		NORTH,
+		SOUTH,
+		EAST,
+		WEST,
+		UP,
+		DOWN,
+		EXITS,
+		YOU_SEE,
+		YOU_ARE,
+		YOU_CANT_GO_THAT_WAY,
+		OK,
+		WHAT_NOW,
+		HUH,
+		YOU_HAVE_IT,
+		TAKEN,
+		DROPPED,
+		YOU_HAVENT_GOT_IT,
+		INVENTORY,
+		YOU_DONT_SEE_IT,
+		THATS_BEYOND_MY_POWER,
+		DIRECTION,
+		YOURE_CARRYING_TOO_MUCH,
+		IM_DEAD,
+		RESUME_A_SAVED_GAME,
+		PLAY_AGAIN,
+		YOU_CANT_DO_THAT_YET,
+		I_DONT_UNDERSTAND,
+		NOTHING};
+
+	for (int i = 0; i < 28; i++) {
+		_G(_sys)[messagekey[i]] = _G(_systemMessages)[i];
+	}
+
+	_G(_sys)[HIT_ENTER] = _G(_systemMessages)[30];
+
+	fillInGermanSystemMessages();
+
+	_G(_items)[99]._image = 255;
+}
+
+void loadExtraGermanGremlinsData() {
+	_G(_verbs)[0] = "AUTO\0";
+	_G(_nouns)[0] = "ANY\0";
+	_G(_nouns)[28] = "*Y.M.C\0";
+
+	_G(_messages)[90] = "Ehe ich etwas anderes mache, much aich erst alles andere fallenlassen. ";
+	fillInGermanSystemMessages();
+}
+
+void loadExtraSpanishGremlinsData() {
+	_G(_verbs)[0] = "AUTO\0";
+	_G(_nouns)[0] = "ANY\0";
+
+	for (int i = YOU_ARE; i <= HIT_ENTER; i++)
+		_G(_sys)[i] = _G(_systemMessages)[15 - YOU_ARE + i];
+	for (int i = I_DONT_UNDERSTAND; i <= THATS_BEYOND_MY_POWER; i++)
+		_G(_sys)[i] = _G(_systemMessages)[6 - I_DONT_UNDERSTAND + i];
+
+	for (int i = DROPPED; i <= OK; i++)
+		_G(_sys)[i] = _G(_systemMessages)[2 - DROPPED + i];
+	_G(_sys)[PLAY_AGAIN] = _G(_systemMessages)[5];
+	_G(_sys)[YOURE_CARRYING_TOO_MUCH] = _G(_systemMessages)[22];
+	_G(_sys)[IM_DEAD] = _G(_systemMessages)[23];
+	_G(_sys)[YOU_CANT_GO_THAT_WAY] = _G(_systemMessages)[14];
+	_G(_sys)[WHAT] = _G(_sys)[HUH];
+	_G(_sys)[YES] = "s}";
+	_G(_sys)[NO] = "no";
+	_G(_sys)[ANSWER_YES_OR_NO] = "Contesta s} o no.\n";
+	_G(_sys)[I_DONT_KNOW_WHAT_A] = "No s\x84 qu\x84 es un \"";
+	_G(_sys)[IS] = "\". ";
+	_G(_sys)[I_DONT_KNOW_HOW_TO] = "No s\x84 c|mo \"";
+	_G(_sys)[SOMETHING] = "\" algo. ";
+
+	_G(_sys)[ARE_YOU_SURE] = "\x83\x45stas segura? ";
+	_G(_sys)[NOTHING_HERE_TO_TAKE] = "No hay nada aqu} para tomar. ";
+	_G(_sys)[YOU_HAVE_NOTHING] = "No llevo nada. ";
+	_G(_sys)[MOVE_UNDONE] = "Deshacer. ";
+	_G(_sys)[CANT_UNDO_ON_FIRST_TURN] = "No se puede deshacer en el primer turno. ";
+	_G(_sys)[NO_UNDO_STATES] = "No hay m{s estados de deshacer disponibles. ";
+	_G(_sys)[SAVED] = "Juego guardado. ";
+	_G(_sys)[CANT_USE_ALL] = "No puedes usar TODO con este verbo. ";
+	_G(_sys)[TRANSCRIPT_ON] = "Transcripci|n en. ";
+	_G(_sys)[TRANSCRIPT_OFF] = "Transcripci|n desactivada. ";
+	_G(_sys)[NO_TRANSCRIPT] = "No se est{ ejecutando ninguna transcripci|n. ";
+	_G(_sys)[TRANSCRIPT_ALREADY] = "Ya se est{ ejecutando una transcripci|n. ";
+	_G(_sys)[FAILED_TRANSCRIPT] = "No se pudo crear el archivo de transcripci|n. ";
+	_G(_sys)[TRANSCRIPT_START] = "Comienzo de una transcripci|n.\n\n";
+	_G(_sys)[TRANSCRIPT_END] = "\n\nFin de una transcripci|n.\n";
+	_G(_sys)[BAD_DATA] = "\x80MALOS DATOS! Guardar archivo no v{lido.\n";
+	_G(_sys)[STATE_SAVED] = "Estado guardado.\n";
+	_G(_sys)[NO_SAVED_STATE] = "No existe ning\x85n estado guardado.\n";
+	_G(_sys)[STATE_RESTORED] = "Estado restaurado.\n";
+
+	for (int i = 0; i < NUMBER_OF_DIRECTIONS; i++)
+		_G(_directions)[i] = _G(_spanishDirections)[i];
+	for (int i = 0; i < NUMBER_OF_EXTRA_NOUNS; i++)
+		_G(_extraNouns)[i] = _G(_spanishExtraNouns)[i];
+	for (int i = 0; i < NUMBER_OF_EXTRA_COMMANDS; i++)
+		_G(_extraCommands)[i] = _G(_spanishExtraCommands)[i];
+}
+
+void gremlinsAction(int parameter) {
+	g_scott->drawImage(68); /* Mogwai */
+	g_scott->display(_G(_bottomWindow), "\n%s\n", _G(_sys)[HIT_ENTER]);
+	g_scott->hitEnter();
+	g_scott->look();
+}
+
+
+} // End of namespace Scott
+} // End of namespace Glk
diff --git a/engines/glk/scott/gremlins.h b/engines/glk/scott/gremlins.h
new file mode 100644
index 00000000000..29f02e4b769
--- /dev/null
+++ b/engines/glk/scott/gremlins.h
@@ -0,0 +1,50 @@
+/* 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/>.
+ *
+ */
+
+/*
+ * Based on ScottFree interpreter version 1.14 developed by Swansea
+ * University Computer Society without disassembly of any other game
+ * drivers, only of game databases as permitted by EEC law (for purposes
+ * of compatibility).
+ *
+ * Licensed under GPLv2
+ *
+ * https://github.com/angstsmurf/spatterlight/tree/master/terps/scott
+ */
+
+#ifndef GLK_SCOTT_GREMLINS_H
+#define GLK_SCOTT_GREMLINS_H
+
+namespace Glk {
+namespace Scott {
+
+void updateGremlinsAnimations();
+void gremlinsLook();
+void gremlinsAction(int p);
+void loadExtraGermanGremlinsData();
+void loadExtraSpanishGremlinsData();
+void loadExtraGermanGremlinsc64Data();
+
+} // End of namespace Scott
+} // End of namespace Glk
+
+#endif
+
diff --git a/engines/glk/scott/load_game.cpp b/engines/glk/scott/load_game.cpp
index b199b603600..4456fa1ccee 100644
--- a/engines/glk/scott/load_game.cpp
+++ b/engines/glk/scott/load_game.cpp
@@ -47,6 +47,7 @@
 #include "glk/scott/resource.h"
 #include "glk/scott/load_game.h"
 #include "glk/scott/robin_of_sherwood.h"
+#include "glk/scott/gremlins.h"
 
 namespace Glk {
 namespace Scott {
@@ -135,6 +136,26 @@ void loadGameFile(Common::SeekableReadStream *f) {
 	case ROBIN_OF_SHERWOOD_C64:
 		loadExtraSherwoodData64();
 		break;
+	case GREMLINS_GERMAN_C64:
+		loadExtraGermanGremlinsc64Data();
+		break;
+	case GREMLINS_GERMAN:
+	case GREMLINS:
+	case SUPERGRAN:
+		for (int i = DROPPED; i <= OK; i++)
+			_G(_sys)[i] = _G(_systemMessages)[2 - DROPPED + i];
+		for (int i = I_DONT_UNDERSTAND; i <= THATS_BEYOND_MY_POWER; i++)
+			_G(_sys)[i] = _G(_systemMessages)[6 - I_DONT_UNDERSTAND + i];
+		for (int i = YOU_ARE; i <= HIT_ENTER; i++)
+			_G(_sys)[i] = _G(_systemMessages)[17 - YOU_ARE + i];
+		_G(_sys)[PLAY_AGAIN] = _G(_systemMessages)[5];
+		_G(_sys)[YOURE_CARRYING_TOO_MUCH] = _G(_systemMessages)[24];
+		_G(_sys)[IM_DEAD] = _G(_systemMessages)[25];
+		_G(_sys)[YOU_CANT_GO_THAT_WAY] = _G(_systemMessages)[14];
+		break;
+	case GREMLINS_SPANISH:
+		loadExtraSpanishGremlinsData();
+		break;
 	case HULK_C64:
 	case HULK:
 		for (int i = 0; i < 6; i++) {
@@ -162,6 +183,17 @@ void loadGameFile(Common::SeekableReadStream *f) {
 		break;
 	}
 
+	switch (CURRENT_GAME) {
+	case GREMLINS_GERMAN:
+		loadExtraGermanGremlinsData();
+		break;
+	case GREMLINS_GERMAN_C64:
+		loadExtraGermanGremlinsc64Data();
+		break;
+	default:
+		break;
+	}
+
 	if (!(_G(_game)->_subType & (C64 | MYSTERIOUS))) {
 		mysterious64Sysmess();
 	}
diff --git a/engines/glk/scott/scott.cpp b/engines/glk/scott/scott.cpp
index 93d49936a46..bc9a5a39b6b 100644
--- a/engines/glk/scott/scott.cpp
+++ b/engines/glk/scott/scott.cpp
@@ -46,6 +46,7 @@
 #include "glk/scott/saga_draw.h"
 #include "glk/scott/restore_state.h"
 #include "glk/scott/robin_of_sherwood.h"
+#include "glk/scott/gremlins.h"
 
 namespace Glk {
 namespace Scott {
@@ -289,8 +290,7 @@ void Scott::updates(event_t ev) {
 			updateRobinOfSherwoodAnimations();
 			break;
 		case GREMLINS_VARIANT:
-			// TODO
-			// UpdateGremlinsAnimations();
+			updateGremlinsAnimations();
 			break;
 		case SECRET_MISSION_VARIANT:
 			// TODO
@@ -304,7 +304,7 @@ void Scott::updates(event_t ev) {
 	}
 }
 
-void Scott::delay(int seconds) {
+void Scott::delay(double seconds) {
 	if (_options & NO_DELAYS)
 		return;
 
@@ -1136,8 +1136,7 @@ ActionResultType Scott::performLine(int ct) {
 				case GREMLINS_SPANISH:
 				case GREMLINS_GERMAN:
 				case GREMLINS_GERMAN_C64:
-					// TODO
-					// GremlinsAction(p);
+					gremlinsAction(p);
 					break;
 				default:
 					break;
@@ -1750,8 +1749,7 @@ void Scott::drawRoomImage() {
 	}
 
 	if (_G(_game)->_type == GREMLINS_VARIANT) {
-		// TODO
-		// GremlinsLook();
+		gremlinsLook();
 	} else {
 		drawImage(_G(_rooms)[MY_LOC]._image & 127);
 	}
diff --git a/engines/glk/scott/scott.h b/engines/glk/scott/scott.h
index c5497f1a8d8..78ecf7766a8 100644
--- a/engines/glk/scott/scott.h
+++ b/engines/glk/scott/scott.h
@@ -165,7 +165,7 @@ private:
 	void initialize();
 
 	void updateSettings();
-	void delay(int seconds);
+	void delay(double seconds);
 	void clearScreen(void);
 	bool randomPercent(uint n);
 	int countCarried(void);
diff --git a/engines/glk/scott/unp64/unp64.cpp b/engines/glk/scott/unp64/unp64.cpp
index 8c651db28e8..7b857a58c8d 100644
--- a/engines/glk/scott/unp64/unp64.cpp
+++ b/engines/glk/scott/unp64/unp64.cpp
@@ -395,21 +395,20 @@ int unp64(uint8_t *compressed, size_t length, uint8_t *destinationBuffer, size_t
 			return 0;
 
 		_G(_iter)++;
-		if (_G(_iter) == iterMax) {
+ 		if (_G(_iter) == iterMax) {
 				return 0;
 		}
 
 		if (_G(_unp)._exoFnd && (_G(_unp)._endAdr == 0x10000) && (r->_pc >= 0x100) && (r->_pc <= 0x200) && (_G(_unp)._strMem != 2)) {
 			_G(_unp)._endAdr = r->_mem[0xfe] + (r->_mem[0xff] << 8);
+			if ((_G(_unp)._exoFnd & 0xff) == 0x30) { /* low byte of _endAdr, it's a lda $ff00,y */
+				_G(_unp)._endAdr = (_G(_unp)._exoFnd >> 8) + (r->_mem[0xff] << 8);
+			} else if ((_G(_unp)._exoFnd & 0xff) == 0x32) { /* add 1 */
+				_G(_unp)._endAdr = 1 + ((_G(_unp)._exoFnd >> 8) + (r->_mem[0xff] << 8));
+			}
 
-		if ((_G(_unp)._exoFnd & 0xff) == 0x30) { /* low byte of _endAdr, it's a lda $ff00,y */
-			_G(_unp)._endAdr = (_G(_unp)._exoFnd >> 8) + (r->_mem[0xff] << 8);
-		} else if ((_G(_unp)._exoFnd & 0xff) == 0x32) { /* add 1 */
-			_G(_unp)._endAdr = 1 + ((_G(_unp)._exoFnd >> 8) + (r->_mem[0xff] << 8));
-		}
-
-		if (_G(_unp)._endAdr == 0)
-			_G(_unp)._endAdr = 0x10001;
+			if (_G(_unp)._endAdr == 0)
+				_G(_unp)._endAdr = 0x10001;
 		}
 
 		if (_G(_unp)._fEndBf && (_G(_unp)._endAdr == 0x10000) && (r->_pc == _G(_unp)._depAdr)) {


Commit: 051d12497fee15d3d87e9263a6864595fe5cedbc
    https://github.com/scummvm/scummvm/commit/051d12497fee15d3d87e9263a6864595fe5cedbc
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Use C String instead of Common::String in GLK display

Changed paths:
    engines/glk/scott/gremlins.cpp
    engines/glk/scott/robin_of_sherwood.cpp


diff --git a/engines/glk/scott/gremlins.cpp b/engines/glk/scott/gremlins.cpp
index d7b90cee78c..627def2cba2 100644
--- a/engines/glk/scott/gremlins.cpp
+++ b/engines/glk/scott/gremlins.cpp
@@ -325,7 +325,7 @@ void loadExtraSpanishGremlinsData() {
 
 void gremlinsAction(int parameter) {
 	g_scott->drawImage(68); /* Mogwai */
-	g_scott->display(_G(_bottomWindow), "\n%s\n", _G(_sys)[HIT_ENTER]);
+	g_scott->display(_G(_bottomWindow), "\n%s\n", _G(_sys)[HIT_ENTER].c_str());
 	g_scott->hitEnter();
 	g_scott->look();
 }
diff --git a/engines/glk/scott/robin_of_sherwood.cpp b/engines/glk/scott/robin_of_sherwood.cpp
index 580996d07b8..610bd29bd7b 100644
--- a/engines/glk/scott/robin_of_sherwood.cpp
+++ b/engines/glk/scott/robin_of_sherwood.cpp
@@ -64,7 +64,7 @@ void sherwoodAction(int p) {
 		break;
 	case 1:
 		g_scott->drawImage(0); /* Herne */
-		g_scott->display(_G(_bottomWindow), "\n%s\n", _G(_sys)[HIT_ENTER]);
+		g_scott->display(_G(_bottomWindow), "\n%s\n", _G(_sys)[HIT_ENTER].c_str());
 		g_scott->hitEnter();
 		_G(_items)[39]._location = 79;
 		g_scott->look();


Commit: 6a11c2bc10105426cda2caf456965571b9b9494d
    https://github.com/scummvm/scummvm/commit/6a11c2bc10105426cda2caf456965571b9b9494d
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Fix text decompression

Changed paths:
    engines/glk/scott/resource.cpp


diff --git a/engines/glk/scott/resource.cpp b/engines/glk/scott/resource.cpp
index 60600724e5f..ddddb02ab17 100644
--- a/engines/glk/scott/resource.cpp
+++ b/engines/glk/scott/resource.cpp
@@ -862,7 +862,7 @@ int tryLoading(GameInfo info, int dictStart, int loud) {
 			do {
 				rp = &_G(_rooms)[ct];
 				rp->_text = decompressText(ptr, ct);
-				if (rp->_text == nullptr)
+				if (rp->_text.size() == 0)
 					return 0;
 				rp->_text.replace(0, 1, Common::String(tolower(rp->_text[0])));
 				ct++;
@@ -937,13 +937,14 @@ int tryLoading(GameInfo info, int dictStart, int loud) {
 				const char *p = strchr(ip->_text.c_str(), '.');
 				if (p) {
 					ip->_autoGet = Common::String(p);
+					ip->_text = Common::String(ip->_text.c_str(), p);
 					ip->_autoGet.deleteChar(0);
 					ip->_autoGet.deleteChar(0);
 					const char *t = strchr(ip->_autoGet.c_str(), '.');
 					if (t)
 						ip->_autoGet = Common::String(ip->_autoGet.c_str(), t);
-					for (int i = 1; i < _G(_gameHeader)->_wordLength; i++)
-						ip->_autoGet.replace(i, 1, Common::String(toupper(ip->_text[i])));
+					for (int i = 1; i < ip->_autoGet.size(); i++)
+						ip->_autoGet.replace(i, 1, Common::String(toupper(ip->_autoGet[i])));
 				}
 			}
 			ct++;


Commit: 98d5b724429237f72c869bb1bd04f90ebfd222cf
    https://github.com/scummvm/scummvm/commit/98d5b724429237f72c869bb1bd04f90ebfd222cf
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Add support for Seas of Blood

Changed paths:
  A engines/glk/scott/seas_of_blood.cpp
  A engines/glk/scott/seas_of_blood.h
    engines/glk/module.mk
    engines/glk/scott/c64_checksums.cpp
    engines/glk/scott/detection_tables.h
    engines/glk/scott/games.h
    engines/glk/scott/globals.cpp
    engines/glk/scott/globals.h
    engines/glk/scott/load_game.cpp
    engines/glk/scott/saga_draw.cpp
    engines/glk/scott/saga_draw.h
    engines/glk/scott/scott.cpp
    engines/glk/scott/scott.h


diff --git a/engines/glk/module.mk b/engines/glk/module.mk
index cea82826d22..a34a9587651 100644
--- a/engines/glk/module.mk
+++ b/engines/glk/module.mk
@@ -254,6 +254,7 @@ MODULE_OBJS := \
 	scott/robin_of_sherwood.o \
 	scott/saga_draw.o \
 	scott/scott.o \
+	scott/seas_of_blood.o \
 	scott/unp64/unp64.o \
 	scott/unp64/6502_emu.o \
 	scott/unp64/exo_util.o \
diff --git a/engines/glk/scott/c64_checksums.cpp b/engines/glk/scott/c64_checksums.cpp
index e8fa959261b..0d5094720e9 100644
--- a/engines/glk/scott/c64_checksums.cpp
+++ b/engines/glk/scott/c64_checksums.cpp
@@ -97,6 +97,12 @@ static C64Rec g_C64Registry[] = {
 	{ GREMLINS_GERMAN_C64,	0xc003,		0x558c, TYPE_T64, 1, nullptr,	nullptr, 0, 0xd801, 0xc6c0, 0x1f00 },  // German Gremlins C64 (T64) version * TBC Multicompactor v2.x
 	{ GREMLINS_GERMAN_C64,	0x2ab00,	0x6729, TYPE_D64, 2, nullptr,	nullptr, 0, 0xdc02, 0xcac1, 0x1f00 }, // German Gremlins C64 (D64) version * Exomizer
 
+	{SEAS_OF_BLOOD_C64, 0xa209,  0xf115, TYPE_T64, 6, "-e0x1000", nullptr, 3, 0xd802, 0xb07c, 0x2000}, // Seas of Blood C64 (T64) MasterCompressor / Relax -> ECA
+	// Compacker -> Unknown -> MasterCompressor / Relax -> ECA
+	// Compacker -> CCS Packer
+	{SEAS_OF_BLOOD_C64, 0x2ab00, 0x5c1d, TYPE_D64, 1, nullptr,	  nullptr, 0, 0xd802, 0xb07c, 0x2000}, // Seas of Blood C64 (D64) CCS Packer
+	{SEAS_OF_BLOOD_C64, 0x2ab00, 0xe308, TYPE_D64, 1, nullptr,	  nullptr, 0, 0xd802, 0xb07c, 0x2000}, // Seas of Blood C64 (D64) alt CCS Packer
+
 	{ UNKNOWN_GAME, 0, 0, UNKNOWN_FILE_TYPE, 0, nullptr, nullptr, 0, 0, 0, 0 }
 };
 
diff --git a/engines/glk/scott/detection_tables.h b/engines/glk/scott/detection_tables.h
index af1b929b7da..dc70db0f160 100644
--- a/engines/glk/scott/detection_tables.h
+++ b/engines/glk/scott/detection_tables.h
@@ -85,6 +85,7 @@ const PlainGameDescriptor SCOTT_GAME_LIST[] = {
 	{ "romulanadv",        "Romulan Adventure" },
 	{ "topsecretadv",      "Top Secret Adventure" },
 	{ "gremlins",		   "Gremlins" },
+	{ "seasofblood",	   "Seas Of Blood" },
 
 	{ nullptr, nullptr }
 };
@@ -185,6 +186,8 @@ const GlkDetectionEntry SCOTT_GAMES[] = {
 	DT_ENTRY1("gremlins",		 "C64", "947e35037cf02269ac013857925137ce", 174848),
 	DT_ENTRY1("gremlins",		 "C64", "108063b2a16a199794f2ecf52ce26377", 56724),
 	DT_ENTRYL1("gremlins", Common::DE_DEU, "C64", "e5d743d8727c8aca011a737bbb5ad818", 49155),
+	DT_ENTRY1("seasofblood",	 "C64", "267c3fe2bb150365de0358f07b5df15c", 174848),
+	DT_ENTRY1("seasofblood",	 "C64", "46280fb1d701a41492b8434467c31029", 41481),
 
 	// 11 Mysterious Adventures
 	DT_ENTRY1("mysadv1", "C64", "b4d8fc4eabed4f2400717303561ad0fa", 174848),
diff --git a/engines/glk/scott/games.h b/engines/glk/scott/games.h
index 6f6c9ea8ce0..b486e90a6cb 100644
--- a/engines/glk/scott/games.h
+++ b/engines/glk/scott/games.h
@@ -1360,5 +1360,91 @@ const GameInfo _games[NUMGAMES] = {
 			 74,     // number_of_pictures;
 			 ZXOPT,  // palette
 			 3,      // picture_format_version;
+			 0),
+	GameInfo("Seas of Blood",
+			 SEAS_OF_BLOOD,
+			 SEAS_OF_BLOOD_VARIANT,  // type
+			 ENGLISH,                // subtype
+			 FOUR_LETTER_COMPRESSED, // dictionary type
+
+			 125, // Number of items
+			 344, // Number of actions
+			 134, // Number of words
+			 83,  // Number of rooms
+			 10,  // Max carried items
+			 4,   // Word length
+			 99,  // Number of messages
+
+			 69,  // number_of_verbs
+			 134, // number_of_nouns;
+
+			 0x494d, // header
+			 LATE,   // header style
+
+			 0,       // no room images
+			 0x4961,  // item flags
+			 FOLLOWS, // item images
+
+			 FOLLOWS, // actions
+			 COMPRESSED,
+			 0x591b, // dictionary
+			 0x67cb, // start_of_room_descriptions;
+			 0x5c4b, // start_of_room_connections;
+			 0x5ebb, // start_of_messages;
+			 0x6ce0, // start_of_item_descriptions;
+			 0x5e3d, // start_of_item_locations;
+
+			 0x24ed, // start_of_system_messages
+			 0x26fc, // start of directions
+
+			 0x7389, // start_of_characters;
+			 0x7a89, // start_of_image_data;
+			 0x7b9f, // image_address_offset
+			 139,    // number_of_pictures;
+			 ZXOPT,  // palette
+			 4,      // picture_format_version;
+			 0),
+	GameInfo("Seas of Blood C64",
+			 SEAS_OF_BLOOD_C64,
+			 SEAS_OF_BLOOD_VARIANT,               // type
+			 static_cast<Subtype>(ENGLISH | C64), // subtype
+			 FOUR_LETTER_COMPRESSED,              // dictionary type
+
+			 125, // Number of items
+			 347, // Number of actions
+			 134, // Number of words
+			 82,  // Number of rooms
+			 10,  // Max carried items
+			 4,   // Word length
+			 99,  // Number of messages
+
+			 69,  // number_of_verbs
+			 134, // number_of_nouns;
+
+			 0x527d,                   // header
+			 SEAS_OF_BLOOD_C64_HEADER, // header style
+
+			 0,       // no room images
+			 0x5a73,  // item flags
+			 FOLLOWS, // item images
+
+			 0x5b69, // actions
+			 COMPRESSED,
+			 0x6a2d, // dictionary
+			 0x78dd, // start_of_room_descriptions;
+			 0x6d5d, // start_of_room_connections;
+			 0x6fcd, // start_of_messages;
+			 0x7df2, // start_of_item_descriptions;
+			 0x6f4f, // start_of_item_locations;
+
+			 0x0b9d, // start_of_system_messages
+			 0x0b9d, // start of directions
+
+			 0x84a5, // start_of_characters;
+			 0x8ba5, // start_of_image_data;
+			 0x8CBB, // image_address_offset
+			 139,    // number_of_pictures;
+			 C64B,   // palette
+			 4,      // picture_format_version;
 			 0)
 };
diff --git a/engines/glk/scott/globals.cpp b/engines/glk/scott/globals.cpp
index b0c86a0e203..5c08b2e361f 100644
--- a/engines/glk/scott/globals.cpp
+++ b/engines/glk/scott/globals.cpp
@@ -115,6 +115,8 @@ Globals::Globals() : _sys(MAX_SYSMESS), _directions(NUMBER_OF_DIRECTIONS), _extr
 	_md5Index.setVal("947e35037cf02269ac013857925137ce", 17); // gremlins
 	_md5Index.setVal("33c920f7ba150dfa1a832d510eebd8fe", 19); // gremlins
 	_md5Index.setVal("e5d743d8727c8aca011a737bbb5ad818", 21); // gremlins
+	_md5Index.setVal("267c3fe2bb150365de0358f07b5df15c", 24); // seas of blood
+	_md5Index.setVal("46280fb1d701a41492b8434467c31029", 23); // seas of blood
 }
 
 Globals::~Globals() {
diff --git a/engines/glk/scott/globals.h b/engines/glk/scott/globals.h
index c58deb240ea..d7d2b9f3efe 100644
--- a/engines/glk/scott/globals.h
+++ b/engines/glk/scott/globals.h
@@ -96,6 +96,8 @@ public:
 	uint32 _bitFlags = 0; ///< Might be >32 flags - I haven't seen >32 yet
 	int _autoInventory = 0;
 	int _animationFlag = 0;
+	uint8_t _enemyTable[126];
+	const char *_battleMessages[33];
 
 	// sagadraw
 	int _drawToBuffer = 0;
@@ -190,6 +192,17 @@ public:
 	// robin of sherwood]
 	uint8_t *_forestImages = nullptr;
 
+	// seas of blood
+	winid_t _leftDiceWin = nullptr;
+	winid_t _rightDiceWin = nullptr;
+	winid_t _battleRight = nullptr;
+	glui32 _backgroundColour = 0;
+	uint8_t *_bloodImageData = nullptr;
+	glui32 _dicePixelSize = 0;
+	glui32 _diceXOffset = 0;
+	glui32 _diceYOffset = 0;
+	int _shouldDrawObjectImages = 0;
+
 public:
 	Globals();
 	~Globals();
diff --git a/engines/glk/scott/load_game.cpp b/engines/glk/scott/load_game.cpp
index 4456fa1ccee..6b2be0cd01f 100644
--- a/engines/glk/scott/load_game.cpp
+++ b/engines/glk/scott/load_game.cpp
@@ -48,6 +48,7 @@
 #include "glk/scott/load_game.h"
 #include "glk/scott/robin_of_sherwood.h"
 #include "glk/scott/gremlins.h"
+#include "glk/scott/seas_of_blood.h"
 
 namespace Glk {
 namespace Scott {
@@ -136,6 +137,12 @@ void loadGameFile(Common::SeekableReadStream *f) {
 	case ROBIN_OF_SHERWOOD_C64:
 		loadExtraSherwoodData64();
 		break;
+	case SEAS_OF_BLOOD:
+		loadExtraSeasOfBloodData();
+		break;
+	case SEAS_OF_BLOOD_C64:
+		loadExtraSeasOfBlood64Data();
+		break;
 	case GREMLINS_GERMAN_C64:
 		loadExtraGermanGremlinsc64Data();
 		break;
diff --git a/engines/glk/scott/saga_draw.cpp b/engines/glk/scott/saga_draw.cpp
index e3a4f7ce133..5bcc0267fde 100644
--- a/engines/glk/scott/saga_draw.cpp
+++ b/engines/glk/scott/saga_draw.cpp
@@ -346,6 +346,42 @@ void drawSagaPictureAtPos(int pictureNumber, int x, int y) {
 	drawSagaPictureFromData(img._imageData, img._width, img._height, x, y);
 }
 
+void drawSagaPictureFromBuffer() {
+	for (int line = 0; line < 12; line++) {
+		for (int col = 0; col < 32; col++) {
+
+			uint8_t colour = _G(_buffer)[col + line * 32][8];
+
+			int paper = (colour >> 3) & 0x7;
+			paper += 8 * ((colour & 0x40) == 0x40);
+			paper = remap(paper);
+			int ink = (colour & 0x7);
+			ink += 8 * ((colour & 0x40) == 0x40);
+			ink = remap(ink);
+
+			background(col, line, paper);
+
+			for (int i = 0; i < 8; i++) {
+				if (_G(_buffer)[col + line * 32][i] == 0)
+					continue;
+				if (_G(_buffer)[col + line * 32][i] == 255) {
+
+					glui32 glk_color = (_G(_pal)[ink][0] << 16) | (_G(_pal)[ink][1] << 8) | _G(_pal)[ink][2];
+
+					g_scott->glk_window_fill_rect(_G(_graphics), glk_color, col * 8 * _G(_pixelSize) + _G(_xOffset),
+												  (line * 8 + i) * _G(_pixelSize), 8 * _G(_pixelSize), _G(_pixelSize));
+					continue;
+				}
+				for (int j = 0; j < 8; j++)
+					if ((_G(_buffer)[col + line * 32][i] & (1 << j)) != 0) {
+						int ypos = line * 8 + i;
+						putPixel(col * 8 + j, ypos, ink);
+					}
+			}
+		}
+	}
+}
+
 void sagaSetup(size_t imgOffset) {
 	int32_t i, y;
 
diff --git a/engines/glk/scott/saga_draw.h b/engines/glk/scott/saga_draw.h
index d02a77c4576..0e92f7c2ed8 100644
--- a/engines/glk/scott/saga_draw.h
+++ b/engines/glk/scott/saga_draw.h
@@ -53,6 +53,8 @@ typedef RGB PALETTE[16];
 uint8_t *drawSagaPictureFromData(uint8_t *dataptr, int xSize, int ySize, int xOff, int yOff);
 void drawSagaPictureNumber(int pictureNumber);
 void drawSagaPictureAtPos(int pictureNumber, int x, int y);
+void drawSagaPictureFromBuffer();
+void flip(uint8_t character[]);
 
 void sagaSetup(size_t imgOffset);
 
diff --git a/engines/glk/scott/scott.cpp b/engines/glk/scott/scott.cpp
index bc9a5a39b6b..1b53a24db18 100644
--- a/engines/glk/scott/scott.cpp
+++ b/engines/glk/scott/scott.cpp
@@ -47,6 +47,7 @@
 #include "glk/scott/restore_state.h"
 #include "glk/scott/robin_of_sherwood.h"
 #include "glk/scott/gremlins.h"
+#include "glk/scott/seas_of_blood.h"
 
 namespace Glk {
 namespace Scott {
@@ -272,6 +273,10 @@ void Scott::updateSettings() {
 	}
 }
 
+uint Scott::getRandomNumber(uint max) {
+	return _random.getRandomNumber(max);
+}
+
 void Scott::updates(event_t ev) {
 	if (ev.type == evtype_Arrange) {
 		updateSettings();
@@ -991,9 +996,7 @@ ActionResultType Scott::performLine(int ct) {
 				break;
 			case 66:
 				if (_G(_game)->_type == SEAS_OF_BLOOD_VARIANT)
-					// TODO
-					// AdventureSheet();
-					debug("case 66 not implemented\n");
+					adventureSheet();
 				else
 					listInventory();
 				_G(_stopTime) = 2;
@@ -1125,8 +1128,7 @@ ActionResultType Scott::performLine(int ct) {
 					break;
 				case SEAS_OF_BLOOD:
 				case SEAS_OF_BLOOD_C64:
-					// TODO
-					// BloodAction(p);
+					bloodAction(p);
 					break;
 				case ROBIN_OF_SHERWOOD:
 				case ROBIN_OF_SHERWOOD_C64:
@@ -1720,8 +1722,7 @@ void Scott::drawRoomImage() {
 	switch (CURRENT_GAME) {
 	case SEAS_OF_BLOOD:
 	case SEAS_OF_BLOOD_C64:
-		// TODO
-		// SeasOfBloodRoomImage();
+		seasOfBloodRoomImage();
 		return;
 	case ROBIN_OF_SHERWOOD:
 	case ROBIN_OF_SHERWOOD_C64:
diff --git a/engines/glk/scott/scott.h b/engines/glk/scott/scott.h
index 78ecf7766a8..5b49acf32ad 100644
--- a/engines/glk/scott/scott.h
+++ b/engines/glk/scott/scott.h
@@ -164,7 +164,6 @@ private:
 	 */
 	void initialize();
 
-	void updateSettings();
 	void delay(double seconds);
 	void clearScreen(void);
 	bool randomPercent(uint n);
@@ -172,7 +171,6 @@ private:
 	int matchUpItem(int noun, int loc);
 	Common::String readString(Common::SeekableReadStream *f);
 	void loadDatabase(Common::SeekableReadStream *f, bool loud);
-	void outputNumber(int a);
 	int whichWord(const char *word, const Common::StringArray &list);
 
 	ActionResultType performLine(int ct);
@@ -196,7 +194,6 @@ private:
 	void transcriptOn();
 	void transcriptOff();
 	int yesOrNo();
-	void listInventory();
 	void lookWithPause();
 	void doneIt();
 	int printScore();
@@ -217,6 +214,7 @@ public:
 	void drawImage(int image);
 	void output(const Common::String &a);
 	void output(const Common::U32String &a);
+	void outputNumber(int a);
 	void display(winid_t w, const char *fmt, ...);
 	void display(winid_t w, const Common::U32String fmt, ...);
 	void fatal(const char *x);
@@ -227,6 +225,9 @@ public:
 	void look(void);
 	void openGraphicsWindow();
 	void closeGraphicsWindow();
+	void listInventory();
+	void updateSettings();
+	uint getRandomNumber(uint max);
 
 public:
 	/**
diff --git a/engines/glk/scott/seas_of_blood.cpp b/engines/glk/scott/seas_of_blood.cpp
new file mode 100644
index 00000000000..f2d8ebb5506
--- /dev/null
+++ b/engines/glk/scott/seas_of_blood.cpp
@@ -0,0 +1,861 @@
+/* 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/>.
+ *
+ */
+
+/*
+ * Based on ScottFree interpreter version 1.14 developed by Swansea
+ * University Computer Society without disassembly of any other game
+ * drivers, only of game databases as permitted by EEC law (for purposes
+ * of compatibility).
+ *
+ * Licensed under GPLv2
+ *
+ * https://github.com/angstsmurf/spatterlight/tree/master/terps/scott
+ */
+
+#include "glk/scott/scott.h"
+#include "glk/scott/saga_draw.h"
+#include "glk/scott/resource.h"
+#include "glk/scott/decompress_text.h"
+#include "glk/scott/seas_of_blood.h"
+
+namespace Glk {
+namespace Scott {
+
+#define VICTORY 0
+#define LOSS 1
+#define DRAW 2
+#define FLEE 3
+#define ERROR 99
+
+int getEnemyStats(int *strike, int *stamina, int *boatFlag);
+void battleLoop(int enemy, int strike, int stamina, int boatFlag);
+void swapStaminaAndCrewStrength(void);
+void bloodBattle(void);
+
+void adventureSheet(void) {
+	g_scott->glk_stream_set_current(g_scott->glk_window_get_stream(_G(_bottomWindow)));
+	g_scott->glk_set_style(style_Preformatted);
+	g_scott->output("\nADVENTURE SHEET\n\n");
+	g_scott->output("SKILL      :");
+	g_scott->outputNumber(9);
+	g_scott->output("      STAMINA      :");
+	g_scott->outputNumber(_G(_counters)[3]);
+	g_scott->output("\nLOG        :");
+	g_scott->outputNumber(_G(_counters)[6]);
+	if (_G(_counters)[6] < 10)
+		g_scott->output("      PROVISIONS   :");
+	else
+		g_scott->output("     PROVISIONS   :"); // one less space!
+	g_scott->outputNumber(_G(_counters)[5]);
+	g_scott->output("\nCREW STRIKE:");
+	g_scott->outputNumber(9);
+	g_scott->output("      CREW STRENGTH:");
+	g_scott->outputNumber(_G(_counters)[7]);
+	g_scott->output("\n\n * * * * * * * * * * * * * * * * * * * * *\n\n");
+	g_scott->listInventory();
+	g_scott->output("\n");
+	g_scott->glk_set_style(style_Normal);
+}
+
+void bloodAction(int p) {
+	switch (p) {
+	case 0:
+		break;
+	case 1:
+		// Update LOG
+		_G(_counters)[6]++;
+		break;
+	case 2:
+		// Battle
+		g_scott->look();
+		g_scott->output("You are attacked \n");
+		g_scott->output("<HIT ENTER> \n");
+		g_scott->hitEnter();
+		bloodBattle();
+		break;
+	default:
+		error("bloodAction: Unhandled special action %d", p);
+		break;
+	}
+}
+
+void mirrorLeftHalf(void) {
+	for (int line = 0; line < 12; line++) {
+		for (int col = 32; col > 16; col--) {
+			_G(_buffer)[line * 32 + col - 1][8] = _G(_buffer)[line * 32 + (32 - col)][8];
+			for (int pixrow = 0; pixrow < 8; pixrow++)
+				_G(_buffer)[line * 32 + col - 1][pixrow] = _G(_buffer)[line * 32 + (32 - col)][pixrow];
+			flip(_G(_buffer)[line * 32 + col - 1]);
+		}
+	}
+}
+
+void replaceColour(uint8_t before, uint8_t after) {
+
+	// I don't think any of the data has bit 7 set,
+	// so masking it is probably unnecessary, but this is what
+	// the original code does.
+	uint8_t beforeink = before & 7;
+	uint8_t afterink = after & 7;
+	uint8_t inkmask = 0x07;
+
+	uint8_t beforepaper = beforeink << 3;
+	uint8_t afterpaper = afterink << 3;
+	uint8_t papermask = 0x38;
+
+	for (int j = 0; j < 384; j++) {
+		if ((_G(_buffer)[j][8] & inkmask) == beforeink) {
+			_G(_buffer)[j][8] = (_G(_buffer)[j][8] & ~inkmask) | afterink;
+		}
+
+		if ((_G(_buffer)[j][8] & papermask) == beforepaper) {
+			_G(_buffer)[j][8] = (_G(_buffer)[j][8] & ~papermask) | afterpaper;
+		}
+	}
+}
+
+void drawColour(uint8_t x, uint8_t y, uint8_t colour, uint8_t length) {
+	for (int i = 0; i < length; i++) {
+		_G(_buffer)[y * 32 + x + i][8] = colour;
+	}
+}
+
+void makeLight(void) {
+	for (int i = 0; i < 384; i++) {
+		_G(_buffer)[i][8] = _G(_buffer)[i][8] | 0x40;
+	}
+}
+
+void flipImage(void) {
+
+	uint8_t mirror[384][9];
+
+	for (int line = 0; line < 12; line++) {
+		for (int col = 32; col > 0; col--) {
+			for (int pixrow = 0; pixrow < 9; pixrow++)
+				mirror[line * 32 + col - 1][pixrow] = _G(_buffer)[line * 32 + (32 - col)][pixrow];
+			flip(mirror[line * 32 + col - 1]);
+		}
+	}
+
+	memcpy(_G(_buffer), mirror, 384 * 9);
+}
+
+void drawObjectImage(uint8_t x, uint8_t y) {
+	for (int i = 0; i < _G(_gameHeader)->_numItems; i++) {
+		if (_G(_items)[i]._flag != MY_LOC)
+			continue;
+		if (_G(_items)[i]._location != MY_LOC)
+			continue;
+		drawSagaPictureAtPos(_G(_items)[i]._image, x, y);
+		_G(_shouldDrawObjectImages) = 0;
+	}
+}
+
+void drawBlood(int loc) {
+	memset(_G(_buffer), 0, 384 * 9);
+	uint8_t *ptr = _G(_bloodImageData);
+	for (int i = 0; i < loc; i++) {
+		while (*(ptr) != 0xff)
+			ptr++;
+		ptr++;
+	}
+	while (ptr < _G(_bloodImageData) + 2010) {
+		switch (*ptr) {
+		case 0xff:
+			if (loc == 13) {
+				_G(_buffer)[8 * 32 + 18][8] = _G(_buffer)[8 * 32 + 18][8] & ~0x40;
+				_G(_buffer)[8 * 32 + 17][8] = _G(_buffer)[8 * 32 + 17][8] & ~0x40;
+
+				_G(_buffer)[8 * 32 + 9][8] = _G(_buffer)[8 * 32 + 9][8] & ~0x40;
+				_G(_buffer)[8 * 32 + 10][8] = _G(_buffer)[8 * 32 + 10][8] & ~0x40;
+			}
+			return;
+		case 0xfe:
+			mirrorLeftHalf();
+			break;
+		case 0xfD:
+			replaceColour(*(ptr + 1), *(ptr + 2));
+			ptr += 2;
+			break;
+		case 0xfc: // Draw colour: x, y, attribute, length
+			drawColour(*(ptr + 1), *(ptr + 2), *(ptr + 3), *(ptr + 4));
+			ptr = ptr + 4;
+			break;
+		case 0xfb: // Make all screen colours bright
+			makeLight();
+			break;
+		case 0xfa: // Flip entire image horizontally
+			flipImage();
+			break;
+		case 0xf9: // Draw object image (if present) at x, y
+			drawObjectImage(*(ptr + 1), *(ptr + 2));
+			ptr = ptr + 2;
+			break;
+		default: // else draw image *ptr at x, y
+			drawSagaPictureAtPos(*ptr, *(ptr + 1), *(ptr + 2));
+			ptr = ptr + 2;
+		}
+		ptr++;
+	}
+}
+
+void seasOfBloodRoomImage(void) {
+	_G(_shouldDrawObjectImages) = 1;
+	drawBlood(MY_LOC);
+	for (int ct = 0; ct <= _G(_gameHeader)->_numItems; ct++)
+		if (_G(_items)[ct]._image && _G(_shouldDrawObjectImages)) {
+			if ((_G(_items)[ct]._flag & 127) == MY_LOC && _G(_items)[ct]._location == MY_LOC) {
+				g_scott->drawImage(_G(_items)[ct]._image);
+			}
+		}
+	drawSagaPictureFromBuffer();
+}
+
+//static void SOBPrint(winid_t w, const char *fmt, ...)
+//#ifdef __GNUC__
+//	__attribute__((__format__(__printf__, 2, 3)))
+//#endif
+//	;
+
+static void SOBPrint(winid_t w, const char *fmt, ...) {
+	va_list ap;
+	char msg[2048];
+
+	int size = sizeof msg;
+
+	va_start(ap, fmt);
+	vsnprintf(msg, size, fmt, ap);
+	va_end(ap);
+
+	g_scott->glk_put_string_stream(g_scott->glk_window_get_stream(w), msg);
+}
+
+const glui32 optimalDicePixelSize(glui32 *width, glui32 *height) {
+	int idealWidth = 8;
+	int idealHeight = 8;
+
+	*width = idealWidth;
+	*height = idealHeight;
+	int multiplier = 1;
+	glui32 graphwidth, graphheight;
+	g_scott->glk_window_get_size(_G(_leftDiceWin), &graphwidth, &graphheight);
+	multiplier = graphheight / idealHeight;
+	if (idealWidth * multiplier > graphwidth)
+		multiplier = graphwidth / idealWidth;
+
+	if (multiplier < 2)
+		multiplier = 2;
+
+	multiplier = multiplier / 2;
+
+	*width = idealWidth * multiplier;
+	*height = idealHeight * multiplier;
+
+	return multiplier;
+}
+
+static void drawBorder(winid_t win) {
+	glui32 width, height;
+	g_scott->glk_stream_set_current(g_scott->glk_window_get_stream(win));
+	g_scott->glk_window_get_size(win, &width, &height);
+	height--;
+	width -= 2;
+	g_scott->glk_window_move_cursor(win, 0, 0);
+	g_scott->glk_put_char_uni(0x250F); // Top left corner
+	for (int i = 1; i < width; i++)
+		g_scott->glk_put_char_uni(0x2501); // Top
+	g_scott->glk_put_char_uni(0x2513);     // Top right corner
+	for (int i = 1; i < height; i++) {
+		g_scott->glk_window_move_cursor(win, 0, i);
+		g_scott->glk_put_char_uni(0x2503);
+		g_scott->glk_window_move_cursor(win, width, i);
+		g_scott->glk_put_char_uni(0x2503);
+	}
+	g_scott->glk_window_move_cursor(win, 0, height);
+	g_scott->glk_put_char_uni(0x2517);
+	for (int i = 1; i < width; i++)
+		g_scott->glk_put_char_uni(0x2501);
+	g_scott->glk_put_char_uni(0x251B);
+}
+
+static void redrawStaticText(winid_t win, int boatFlag) {
+	g_scott->glk_stream_set_current(g_scott->glk_window_get_stream(win));
+	g_scott->glk_window_move_cursor(win, 2, 4);
+
+	if (boatFlag) {
+		g_scott->glk_put_string("STRIKE  :\n");
+		g_scott->glk_window_move_cursor(win, 2, 5);
+		g_scott->glk_put_string("CRW STR :");
+	} else {
+		g_scott->glk_put_string("SKILL   :\n");
+		g_scott->glk_window_move_cursor(win, 2, 5);
+		g_scott->glk_put_string("STAMINA :");
+	}
+
+	if (win == _G(_battleRight)) {
+		glui32 width;
+		g_scott->glk_window_get_size(_G(_battleRight), &width, 0);
+		g_scott->glk_window_move_cursor(_G(_battleRight), width - 6, 1);
+		g_scott->glk_put_string("YOU");
+	}
+}
+
+static void redrawBattleScreen(int boatFlag) {
+	glui32 graphwidth, graphheight, optimal_width, optimal_height;
+
+	g_scott->glk_window_get_size(_G(_leftDiceWin), &graphwidth, &graphheight);
+
+	_G(_dicePixelSize) = optimalDicePixelSize(&optimal_width, &optimal_height);
+	_G(_diceXOffset) = (graphwidth - optimal_width) / 2;
+	_G(_diceYOffset) = (graphheight - optimal_height - _G(_dicePixelSize)) / 2;
+
+	drawBorder(_G(_topWindow));
+	drawBorder(_G(_battleRight));
+
+	redrawStaticText(_G(_topWindow), boatFlag);
+	redrawStaticText(_G(_battleRight), boatFlag);
+}
+
+static void setupBattleScreen(int boatFlag) {
+	winid_t parent = g_scott->glk_window_get_parent(_G(_topWindow));
+	g_scott->glk_window_set_arrangement(parent, winmethod_Above | winmethod_Fixed, 7, _G(_topWindow));
+
+	g_scott->glk_window_clear(_G(_topWindow));
+	g_scott->glk_window_clear(_G(_bottomWindow));
+	_G(_battleRight) = g_scott->glk_window_open(_G(_topWindow), winmethod_Right | winmethod_Proportional,
+								  50, wintype_TextGrid, 0);
+
+	_G(_leftDiceWin) = g_scott->glk_window_open(_G(_topWindow), winmethod_Right | winmethod_Proportional,
+								  30, wintype_Graphics, 0);
+	_G(_rightDiceWin) = g_scott->glk_window_open(_G(_battleRight), winmethod_Left | winmethod_Proportional, 30,
+								   wintype_Graphics, 0);
+
+	// Set the graphics window background to match the top window background, best as we can, and clear the window.
+	 
+	if (g_scott->glk_style_measure(_G(_topWindow), style_Normal, stylehint_BackColor,
+						  &_G(_backgroundColour))) {
+		g_scott->glk_window_set_background_color(_G(_leftDiceWin), _G(_backgroundColour));
+		g_scott->glk_window_set_background_color(_G(_rightDiceWin), _G(_backgroundColour));
+
+		g_scott->glk_window_clear(_G(_leftDiceWin));
+		g_scott->glk_window_clear(_G(_rightDiceWin));
+	}
+
+	if (_G(_palChosen) == C64B)
+		_G(_diceColour) = 0x5f48e9;
+	else
+		_G(_diceColour) = 0xff0000;
+
+	redrawBattleScreen(boatFlag);
+}
+
+void bloodBattle(void) {
+	int enemy, strike, stamina, boatFlag;
+	enemy = getEnemyStats(&strike, &stamina, &boatFlag); // Determine their stats
+	if (enemy == 0) {
+		error("Seas of blood battle: No enemy in location?\n");
+		return;
+	}
+	setupBattleScreen(boatFlag);
+	battleLoop(enemy, strike, stamina, boatFlag); // Into the battle loops
+	if (boatFlag)
+		swapStaminaAndCrewStrength(); // Switch back stamina - crew strength
+	g_scott->glk_window_close(_G(_leftDiceWin), nullptr);
+	g_scott->glk_window_close(_G(_rightDiceWin), nullptr);
+	g_scott->glk_window_close(_G(_battleRight), nullptr);
+	g_scott->closeGraphicsWindow();
+	g_scott->openGraphicsWindow();
+	seasOfBloodRoomImage();
+}
+
+int getEnemyStats(int *strike, int *stamina, int *boatFlag) {
+	int enemy, i = 0;
+	while (i < 124) {
+		enemy = _G(_enemyTable)[i];
+		if (_G(_items)[enemy]._location == MY_LOC) {
+			i++;
+			*strike = _G(_enemyTable)[i++];
+			*stamina = _G(_enemyTable)[i++];
+			*boatFlag = _G(_enemyTable)[i];
+			if (*boatFlag) {
+				swapStaminaAndCrewStrength(); // Switch stamina - crew strength
+			}
+
+			return enemy;
+		}
+		i = i + 4; // Skip to next entry
+	}
+	return 0;
+}
+
+void drawRect(winid_t win, int32_t x, int32_t y, int32_t width, int32_t height,
+			   int32_t color) {
+	g_scott->glk_window_fill_rect(win, color, x * _G(_dicePixelSize) + _G(_diceXOffset),
+						 y * _G(_dicePixelSize) + _G(_diceYOffset),
+						 width * _G(_dicePixelSize), height * _G(_dicePixelSize));
+}
+
+void drawGraphicalDice(winid_t win, int number) {
+	// The eye-less dice backgrounds consist of two rectangles on top of each
+	// other
+	drawRect(win, 1, 2, 7, 5, _G(_diceColour));
+	drawRect(win, 2, 1, 5, 7, _G(_diceColour));
+
+	switch (number + 1) {
+	case 1:
+		drawRect(win, 4, 4, 1, 1, _G(_backgroundColour));
+		break;
+	case 2:
+		drawRect(win, 2, 6, 1, 1, _G(_backgroundColour));
+		drawRect(win, 6, 2, 1, 1, _G(_backgroundColour));
+		break;
+	case 3:
+		drawRect(win, 2, 6, 1, 1, _G(_backgroundColour));
+		drawRect(win, 4, 4, 1, 1, _G(_backgroundColour));
+		drawRect(win, 6, 2, 1, 1, _G(_backgroundColour));
+		break;
+	case 4:
+		drawRect(win, 2, 6, 1, 1, _G(_backgroundColour));
+		drawRect(win, 6, 2, 1, 1, _G(_backgroundColour));
+		drawRect(win, 2, 2, 1, 1, _G(_backgroundColour));
+		drawRect(win, 6, 6, 1, 1, _G(_backgroundColour));
+		break;
+	case 5:
+		drawRect(win, 2, 6, 1, 1, _G(_backgroundColour));
+		drawRect(win, 6, 2, 1, 1, _G(_backgroundColour));
+		drawRect(win, 2, 2, 1, 1, _G(_backgroundColour));
+		drawRect(win, 6, 6, 1, 1, _G(_backgroundColour));
+		drawRect(win, 4, 4, 1, 1, _G(_backgroundColour));
+		break;
+	case 6:
+		drawRect(win, 2, 6, 1, 1, _G(_backgroundColour));
+		drawRect(win, 6, 2, 1, 1, _G(_backgroundColour));
+		drawRect(win, 2, 2, 1, 1, _G(_backgroundColour));
+		drawRect(win, 2, 4, 1, 1, _G(_backgroundColour));
+		drawRect(win, 6, 4, 1, 1, _G(_backgroundColour));
+		drawRect(win, 6, 6, 1, 1, _G(_backgroundColour));
+		break;
+	default:
+		break;
+	}
+}
+
+void updateDice(int ourTurn, int leftDice, int rightDice) {
+	leftDice--;
+	rightDice--;
+	g_scott->glk_window_clear(_G(_leftDiceWin));
+	g_scott->glk_window_clear(_G(_rightDiceWin));
+
+	_G(_diceXOffset) = _G(_diceXOffset) - _G(_dicePixelSize);
+	drawGraphicalDice(_G(_leftDiceWin), leftDice);
+	_G(_diceXOffset) = _G(_diceXOffset) + _G(_dicePixelSize);
+	drawGraphicalDice(_G(_rightDiceWin), rightDice);
+
+	winid_t win = ourTurn ? _G(_battleRight) : _G(_topWindow);
+
+	g_scott->glk_window_move_cursor(win, 2, 1);
+
+	g_scott->glk_stream_set_current(g_scott->glk_window_get_stream(win));
+
+	g_scott->glk_put_char_uni(0x2680 + leftDice);
+	g_scott->glk_put_char('+');
+	g_scott->glk_put_char_uni(0x2680 + rightDice);
+
+	g_scott->glk_window_move_cursor(win, 2, 2);
+	SOBPrint(win, "%d %d", leftDice + 1, rightDice + 1);
+}
+
+void printSum(int ourTurn, int sum, int strike) {
+	winid_t win = ourTurn ? _G(_battleRight) : _G(_topWindow);
+	g_scott->glk_stream_set_current(g_scott->glk_window_get_stream(win));
+
+	g_scott->glk_window_move_cursor(win, 6, 1);
+
+	SOBPrint(win, "+ %d = %d", strike, sum);
+
+	g_scott->glk_stream_set_current(g_scott->glk_window_get_stream(_G(_battleRight)));
+	g_scott->glk_window_move_cursor(_G(_battleRight), 6, 1);
+	g_scott->glk_put_string("+ 9 = ");
+}
+
+void updateResult(int ourTurn, int strike, int stamina, int boatFlag) {
+	winid_t win = ourTurn ? _G(_battleRight) : _G(_topWindow);
+	g_scott->glk_stream_set_current(g_scott->glk_window_get_stream(win));
+
+	g_scott->glk_window_move_cursor(win, 2, 4);
+
+	if (boatFlag) {
+		SOBPrint(win, "STRIKE  : %d\n", strike);
+		g_scott->glk_window_move_cursor(win, 2, 5);
+		SOBPrint(win, "CRW STR : %d", stamina);
+	} else {
+		SOBPrint(win, "SKILL   : %d\n", strike);
+		g_scott->glk_window_move_cursor(win, 2, 5);
+		SOBPrint(win, "STAMINA : %d", stamina);
+	}
+}
+
+void clearResult(void) {
+	winid_t win = _G(_topWindow);
+
+	glui32 width;
+	for (int j = 0; j < 2; j++) {
+		g_scott->glk_window_get_size(win, &width, 0);
+		g_scott->glk_stream_set_current(g_scott->glk_window_get_stream(win));
+
+		g_scott->glk_window_move_cursor(win, 11, 1);
+		for (int i = 0; i < 10; i++)
+			g_scott->glk_put_string(" ");
+		drawBorder(win);
+		win = _G(_battleRight);
+	}
+}
+
+void clearStamina(void) {
+	winid_t win = _G(_topWindow);
+
+	glui32 width;
+	for (int j = 0; j < 2; j++) {
+		g_scott->glk_window_get_size(win, &width, 0);
+		g_scott->glk_stream_set_current(g_scott->glk_window_get_stream(win));
+
+		g_scott->glk_window_move_cursor(win, 11, 5);
+		for (int i = 0; i < width - 13; i++)
+			g_scott->glk_put_string(" ");
+		drawBorder(win);
+		win = _G(_battleRight);
+	}
+}
+
+static void rearrangeBattleDisplay(int strike, int stamina, int boatFlag) {
+	g_scott->updateSettings();
+	g_scott->glk_cancel_char_event(_G(_topWindow));
+	g_scott->closeGraphicsWindow();
+	g_scott->glk_window_close(_G(_battleRight), nullptr);
+	g_scott->glk_window_close(_G(_leftDiceWin), nullptr);
+	g_scott->glk_window_close(_G(_rightDiceWin), nullptr);
+	seasOfBloodRoomImage();
+	setupBattleScreen(boatFlag);
+	updateResult(0, strike, stamina, boatFlag);
+	updateResult(1, 9, _G(_counters)[3], boatFlag);
+	drawBorder(_G(_topWindow));
+	drawBorder(_G(_battleRight));
+	redrawStaticText(_G(_topWindow), boatFlag);
+	redrawStaticText(_G(_battleRight), boatFlag);
+	g_scott->glk_request_char_event(_G(_topWindow));
+}
+
+int rollDice(int strike, int stamina, int boatFlag) {
+	clearResult();
+	redrawStaticText(_G(_battleRight), boatFlag);
+
+	g_scott->glk_request_timer_events(60);
+	int rolls = 0;
+	int ourTurn = 0;
+	int leftDice = 1 + g_scott->getRandomNumber(100) % 6;
+	int rightDice = 1 + g_scott->getRandomNumber(100) % 6;
+	int ourResult;
+	int theirResult = 0;
+	int theirDiceStopped = 0;
+
+	event_t event;
+	int enemyRolls = 20 + g_scott->getRandomNumber(100) % 10;
+	g_scott->glk_cancel_char_event(_G(_topWindow));
+	g_scott->glk_request_char_event(_G(_topWindow));
+
+	g_scott->glk_stream_set_current(g_scott->glk_window_get_stream(_G(_bottomWindow)));
+	g_scott->glk_put_string("Their throw");
+
+	int delay = 60;
+
+	while (1) {
+		g_scott->glk_select(&event);
+		if (event.type == evtype_Timer) {
+			if (theirDiceStopped) {
+				g_scott->glk_request_timer_events(60);
+				theirDiceStopped = 0;
+				printSum(ourTurn, theirResult, strike);
+				ourTurn = 1;
+				g_scott->glk_window_clear(_G(_bottomWindow));
+				g_scott->glk_cancel_char_event(_G(_topWindow));
+				g_scott->glk_request_char_event(_G(_topWindow));
+				g_scott->glk_stream_set_current(g_scott->glk_window_get_stream(_G(_bottomWindow)));
+				g_scott->glk_put_string("Your throw\n");
+				g_scott->glk_put_string("<ENTER> to stop dice");
+				if (!boatFlag)
+					g_scott->glk_put_string("    <X> to run");
+			} else if (ourTurn == 0) {
+				g_scott->glk_request_timer_events(delay);
+			}
+
+			rolls++;
+
+			if (rolls % 2)
+				leftDice = 1 + g_scott->getRandomNumber(100) % 6;
+			else
+				rightDice = 1 + g_scott->getRandomNumber(100) % 6;
+
+			updateDice(ourTurn, leftDice, rightDice);
+			if (ourTurn == 0 && rolls == enemyRolls) {
+				g_scott->glk_window_clear(_G(_bottomWindow));
+				theirResult = leftDice + rightDice + strike;
+				SOBPrint(_G(_bottomWindow), "Their result: %d + %d + %d = %d\n", leftDice,
+						 rightDice, strike, theirResult);
+				g_scott->glk_request_timer_events(1000);
+				theirDiceStopped = 1;
+			}
+		}
+
+		if (event.type == evtype_CharInput) {
+			if (ourTurn && (event.val1 == keycode_Return)) {
+				updateDice(ourTurn, leftDice, rightDice);
+				ourResult = leftDice + rightDice + 9;
+				printSum(ourTurn, ourResult, 9);
+				if (theirResult > ourResult) {
+					return LOSS;
+				} else if (ourResult > theirResult) {
+					return VICTORY;
+				} else {
+					return DRAW;
+				}
+			} else if (MY_LOC != 1 && (event.val1 == 'X' || event.val1 == 'x')) {
+				MY_LOC = _G(_savedRoom);
+				return FLEE;
+			} else {
+				g_scott->glk_request_char_event(_G(_topWindow));
+			}
+		}
+		if (event.type == evtype_Arrange) {
+			rearrangeBattleDisplay(strike, stamina, boatFlag);
+		}
+	}
+	return ERROR;
+}
+
+void battleHitEnter(int strike, int stamina, int boatFlag) {
+	g_scott->glk_request_char_event(_G(_bottomWindow));
+	event_t ev;
+	int result = 0;
+	do {
+		g_scott->glk_select(&ev);
+		if (ev.type == evtype_CharInput) {
+			if (ev.val1 == keycode_Return) {
+				result = 1;
+			} else {
+				g_scott->glk_request_char_event(_G(_bottomWindow));
+			}
+		}
+
+		if (ev.type == evtype_Arrange) {
+			rearrangeBattleDisplay(strike, stamina, boatFlag);
+		}
+
+	} while (result == 0);
+	return;
+}
+
+void battleLoop(int enemy, int strike, int stamina, int boatFlag) {
+	updateResult(0, strike, stamina, boatFlag);
+	updateResult(1, 9, _G(_counters)[3], boatFlag);
+	do {
+		int result = rollDice(strike, stamina, boatFlag);
+		g_scott->glk_cancel_char_event(_G(_topWindow));
+		g_scott->glk_window_clear(_G(_bottomWindow));
+		clearStamina();
+		g_scott->glk_stream_set_current(g_scott->glk_window_get_stream(_G(_bottomWindow)));
+		if (result == LOSS) {
+			_G(_counters)[3] -= 2;
+
+			if (_G(_counters)[3] <= 0) {
+				SOBPrint(_G(_bottomWindow), "%s\n",
+						 boatFlag ? "THE BANSHEE HAS BEEN SUNK!"
+								  : "YOU HAVE BEEN KILLED!");
+				_G(_counters)[3] = 0;
+				_G(_bitFlags) |= (1 << 6);
+				_G(_counters)[7] = 0;
+			} else {
+				SOBPrint(_G(_bottomWindow), "%s", _G(_battleMessages)[1 + g_scott->getRandomNumber(100) % 5 + 16 * boatFlag]);
+			}
+		} else if (result == VICTORY) {
+			stamina -= 2;
+			if (stamina <= 0) {
+				g_scott->glk_put_string("YOU HAVE WON!\n");
+				_G(_bitFlags) &= ~(1 << 6);
+				stamina = 0;
+			} else {
+				SOBPrint(_G(_bottomWindow), "%s", _G(_battleMessages)[6 + g_scott->getRandomNumber(100) % 5 + 16 * boatFlag]);
+			}
+		} else if (result == FLEE) {
+			_G(_bitFlags) |= (1 << 6);
+			MY_LOC = _G(_savedRoom);
+			return;
+		} else {
+			SOBPrint(_G(_bottomWindow), "%s", _G(_battleMessages)[11 + g_scott->getRandomNumber(100) % 5 + 16 * boatFlag]);
+		}
+
+		g_scott->glk_put_string("\n\n");
+
+		if (_G(_counters)[3] > 0 && stamina > 0) {
+			g_scott->glk_put_string("<ENTER> to roll dice");
+			if (!boatFlag)
+				g_scott->glk_put_string("    <X> to run");
+		}
+
+		updateResult(0, strike, stamina, boatFlag);
+		updateResult(1, 9, _G(_counters)[3], boatFlag);
+
+		battleHitEnter(strike, stamina, boatFlag);
+		g_scott->glk_window_clear(_G(_bottomWindow));
+
+	} while (stamina > 0 && _G(_counters)[3] > 0);
+}
+
+void swapStaminaAndCrewStrength(void) {
+	uint8_t temp = _G(_counters)[7]; // Crew strength
+	_G(_counters)[7] = _G(_counters)[3];  // Stamina
+	_G(_counters)[3] = temp;
+}
+
+int loadExtraSeasOfBloodData(void) {
+	_G(_drawToBuffer) = 1;
+
+	int offset;
+
+	offset = 0x47b7 + _G(_fileBaselineOffset);
+
+	uint8_t *ptr = seekToPos(_G(_entireFile), offset);
+
+	int ct;
+
+	for (ct = 0; ct < 124; ct++) {
+		_G(_enemyTable)[ct] = *(ptr++);
+		if (_G(_enemyTable)[ct] == 0xff)
+			break;
+	}
+
+	ptr = seekToPos(_G(_entireFile), 0x71DA + _G(_fileBaselineOffset));
+
+	for (int i = 0; i < 32; i++) {
+		_G(_battleMessages)[i] = decompressText(ptr, i);
+	}
+
+	offset = 0x7af5 - 16357 + _G(_fileBaselineOffset);
+
+	int data_length = 2010;
+
+	_G(_bloodImageData) = new uint8_t[data_length];
+	ptr = seekToPos(_G(_entireFile), offset);
+	for (int i = 0; i < data_length; i++)
+		_G(_bloodImageData)[i] = *(ptr++);
+
+	for (int i = I_DONT_UNDERSTAND; i <= THATS_BEYOND_MY_POWER; i++)
+		_G(_sys)[i] = _G(_systemMessages)[4 - I_DONT_UNDERSTAND + i];
+
+	for (int i = YOU_ARE; i <= HIT_ENTER; i++)
+		_G(_sys)[i] = _G(_systemMessages)[13 - YOU_ARE + i];
+
+	_G(_sys)[OK] = _G(_systemMessages)[2];
+	_G(_sys)[PLAY_AGAIN] = _G(_systemMessages)[3];
+	_G(_sys)[YOURE_CARRYING_TOO_MUCH] = _G(_systemMessages)[27];
+
+	_G(_items)[125]._text = "A loose plank";
+	_G(_items)[125]._autoGet = "PLAN";
+
+	return 0;
+}
+
+int loadExtraSeasOfBlood64Data(void) {
+	_G(_drawToBuffer) = 1;
+
+	int offset;
+
+	offset = 0x3fee + _G(_fileBaselineOffset);
+	uint8_t *ptr;
+
+jumpEnemyTable:
+	ptr = seekToPos(_G(_entireFile), offset);
+
+	int ct;
+	for (ct = 0; ct < 124; ct++) {
+		_G(_enemyTable)[ct] = *(ptr++);
+		if (_G(_enemyTable)[ct] == 0xff)
+			break;
+	}
+
+	offset = 0x82f6 + _G(_fileBaselineOffset);
+	ptr = seekToPos(_G(_entireFile), offset);
+
+	for (int i = 0; i < 32; i++) {
+		_G(_battleMessages)[i] = decompressText(ptr, i);
+	}
+
+	offset = 0x5299 + _G(_fileBaselineOffset);
+
+	int data_length = 2010;
+
+	_G(_bloodImageData) = new uint8_t[data_length];
+
+	ptr = seekToPos(_G(_entireFile), offset);
+	for (int i = 0; i < data_length; i++) {
+		_G(_bloodImageData)[i] = *(ptr++);
+	}
+
+	SysMessageType messagekey[] = {
+		NORTH,
+		SOUTH,
+		EAST,
+		WEST,
+		UP,
+		DOWN,
+		EXITS,
+		YOU_SEE,
+		YOU_ARE,
+		YOU_CANT_GO_THAT_WAY,
+		OK,
+		WHAT_NOW,
+		HUH,
+		YOU_HAVE_IT,
+		YOU_HAVENT_GOT_IT,
+		DROPPED,
+		TAKEN,
+		INVENTORY,
+		YOU_DONT_SEE_IT,
+		THATS_BEYOND_MY_POWER,
+		DIRECTION,
+		YOURE_CARRYING_TOO_MUCH,
+		PLAY_AGAIN,
+		RESUME_A_SAVED_GAME,
+		YOU_CANT_DO_THAT_YET,
+		I_DONT_UNDERSTAND,
+		NOTHING};
+
+	for (int i = 0; i < 27; i++) {
+		_G(_sys)[messagekey[i]] = _G(_systemMessages)[i];
+	}
+
+	return 0;
+}
+
+} // End of namespace Scott
+} // End of namespace Glk
+
+
diff --git a/engines/glk/scott/seas_of_blood.h b/engines/glk/scott/seas_of_blood.h
new file mode 100644
index 00000000000..76e9f5e6b58
--- /dev/null
+++ b/engines/glk/scott/seas_of_blood.h
@@ -0,0 +1,50 @@
+/* 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/>.
+ *
+ */
+
+/*
+ * Based on ScottFree interpreter version 1.14 developed by Swansea
+ * University Computer Society without disassembly of any other game
+ * drivers, only of game databases as permitted by EEC law (for purposes
+ * of compatibility).
+ *
+ * Licensed under GPLv2
+ *
+ * https://github.com/angstsmurf/spatterlight/tree/master/terps/scott
+ */
+
+#ifndef GLK_SCOTT_SEAS_OF_BLOOD_H
+#define GLK_SCOTT_SEAS_OF_BLOOD_H
+
+namespace Glk {
+namespace Scott {
+
+int loadExtraSeasOfBloodData();
+int loadExtraSeasOfBlood64Data();
+void seasOfBloodRoomImage();
+void adventureSheet();
+void bloodAction(int p);
+
+} // End of namespace Scott
+} // End of namespace Glk
+
+#endif
+
+


Commit: ecae491c20153a097fe592c474e380f7f606e63b
    https://github.com/scummvm/scummvm/commit/ecae491c20153a097fe592c474e380f7f606e63b
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Add support for Sorcerer of Claymorgue Castle

Changed paths:
    engines/glk/scott/c64_checksums.cpp
    engines/glk/scott/detection_tables.h
    engines/glk/scott/game_specific.cpp
    engines/glk/scott/game_specific.h
    engines/glk/scott/games.h
    engines/glk/scott/globals.cpp
    engines/glk/scott/load_game.cpp


diff --git a/engines/glk/scott/c64_checksums.cpp b/engines/glk/scott/c64_checksums.cpp
index 0d5094720e9..8a64138f3e2 100644
--- a/engines/glk/scott/c64_checksums.cpp
+++ b/engines/glk/scott/c64_checksums.cpp
@@ -97,11 +97,20 @@ static C64Rec g_C64Registry[] = {
 	{ GREMLINS_GERMAN_C64,	0xc003,		0x558c, TYPE_T64, 1, nullptr,	nullptr, 0, 0xd801, 0xc6c0, 0x1f00 },  // German Gremlins C64 (T64) version * TBC Multicompactor v2.x
 	{ GREMLINS_GERMAN_C64,	0x2ab00,	0x6729, TYPE_D64, 2, nullptr,	nullptr, 0, 0xdc02, 0xcac1, 0x1f00 }, // German Gremlins C64 (D64) version * Exomizer
 
-	{SEAS_OF_BLOOD_C64, 0xa209,  0xf115, TYPE_T64, 6, "-e0x1000", nullptr, 3, 0xd802, 0xb07c, 0x2000}, // Seas of Blood C64 (T64) MasterCompressor / Relax -> ECA
+	{ SEAS_OF_BLOOD_C64, 0xa209,  0xf115, TYPE_T64, 6, "-e0x1000", nullptr, 3, 0xd802, 0xb07c, 0x2000 }, // Seas of Blood C64 (T64) MasterCompressor / Relax -> ECA
 	// Compacker -> Unknown -> MasterCompressor / Relax -> ECA
 	// Compacker -> CCS Packer
-	{SEAS_OF_BLOOD_C64, 0x2ab00, 0x5c1d, TYPE_D64, 1, nullptr,	  nullptr, 0, 0xd802, 0xb07c, 0x2000}, // Seas of Blood C64 (D64) CCS Packer
-	{SEAS_OF_BLOOD_C64, 0x2ab00, 0xe308, TYPE_D64, 1, nullptr,	  nullptr, 0, 0xd802, 0xb07c, 0x2000}, // Seas of Blood C64 (D64) alt CCS Packer
+	{ SEAS_OF_BLOOD_C64, 0x2ab00, 0x5c1d, TYPE_D64, 1, nullptr,	   nullptr, 0, 0xd802, 0xb07c, 0x2000 }, // Seas of Blood C64 (D64) CCS Packer
+	{ SEAS_OF_BLOOD_C64, 0x2ab00, 0xe308, TYPE_D64, 1, nullptr,	   nullptr, 0, 0xd802, 0xb07c, 0x2000 }, // Seas of Blood C64 (D64) alt CCS Packer
+
+	{ CLAYMORGUE_C64, 0x6ff7,  0xe4ed, TYPE_T64, 3, nullptr, nullptr, 0, 0x855, 0x7352, 0x20},		// Sorcerer Of Claymorgue Castle C64 (T64), MasterCompressor / Relax
+	// -> ECA Compacker -> MegaByte Cruncher v1.x Missing 17 pictures
+	{ CLAYMORGUE_C64, 0x912f,  0xa69f, TYPE_T64, 1, nullptr, nullptr, 0, 0x855, 0x7352, 0x20},		// Sorcerer Of Claymorgue Castle C64 (T64) alt, MegaByte Cruncher
+	// v1.x Missing 17 pictures
+	{ CLAYMORGUE_C64, 0xc0dd,  0x3701, TYPE_T64, 1, nullptr, nullptr, 0, 0,		0,		0,	-0x7fe},// Sorcerer Of Claymorgue Castle C64 (T64) alt 2, Trilogic Expert
+	// v2.7
+	{ CLAYMORGUE_C64, 0xbc5f,  0x492c, TYPE_T64, 1, nullptr, nullptr, 0, 0x855, 0x7352, 0x20},		// Sorcerer Of Claymorgue Castle C64 (T64) alt 3, , Section8 Packer
+	{ CLAYMORGUE_C64, 0x2ab00, 0xfd67, TYPE_D64, 1, nullptr, nullptr, 0, 0x855, 0x7352, 0x20},		// Sorcerer Of Claymorgue Castle C64 (D64), Section8 Packer
 
 	{ UNKNOWN_GAME, 0, 0, UNKNOWN_FILE_TYPE, 0, nullptr, nullptr, 0, 0, 0, 0 }
 };
diff --git a/engines/glk/scott/detection_tables.h b/engines/glk/scott/detection_tables.h
index dc70db0f160..1b426b3eedc 100644
--- a/engines/glk/scott/detection_tables.h
+++ b/engines/glk/scott/detection_tables.h
@@ -189,6 +189,9 @@ const GlkDetectionEntry SCOTT_GAMES[] = {
 	DT_ENTRY1("seasofblood",	 "C64", "267c3fe2bb150365de0358f07b5df15c", 174848),
 	DT_ENTRY1("seasofblood",	 "C64", "46280fb1d701a41492b8434467c31029", 41481),
 
+	//Scott Adams
+	DT_ENTRY1("claymorguesorcerer","C64", "a1db488c49ad221fa0dc79591cb5a3db", 28663),
+
 	// 11 Mysterious Adventures
 	DT_ENTRY1("mysadv1", "C64", "b4d8fc4eabed4f2400717303561ad0fa", 174848),
 	DT_ENTRY1("mysadv2", "C64", "3ce5ea1a0473244bf469fd3c51f1dc48", 174848),
diff --git a/engines/glk/scott/game_specific.cpp b/engines/glk/scott/game_specific.cpp
index d10debe8a38..d56d6b5e9a3 100644
--- a/engines/glk/scott/game_specific.cpp
+++ b/engines/glk/scott/game_specific.cpp
@@ -134,5 +134,56 @@ void mysterious64Sysmess() {
 	}
 }
 
+void claymorgue64Sysmess() {
+	SysMessageType messagekey[] = {
+		NORTH,
+		SOUTH,
+		EAST,
+		WEST,
+		UP,
+		DOWN,
+		EXITS,
+		YOU_SEE,
+		YOU_ARE,
+		TOO_DARK_TO_SEE,
+		LIGHT_HAS_RUN_OUT,
+		LIGHT_RUNS_OUT_IN,
+		TURNS,
+		I_DONT_KNOW_HOW_TO,
+		SOMETHING,
+		I_DONT_KNOW_WHAT_A,
+		IS,
+		YOU_CANT_GO_THAT_WAY,
+		OK,
+		WHAT_NOW,
+		HUH,
+		YOU_HAVE_IT,
+		YOU_HAVENT_GOT_IT,
+		INVENTORY,
+		YOU_DONT_SEE_IT,
+		THATS_BEYOND_MY_POWER,
+		DANGEROUS_TO_MOVE_IN_DARK,
+		DIRECTION,
+		YOU_FELL_AND_BROKE_YOUR_NECK,
+		YOURE_CARRYING_TOO_MUCH,
+		IM_DEAD,
+		PLAY_AGAIN,
+		RESUME_A_SAVED_GAME,
+		IVE_STORED,
+		TREASURES,
+		ON_A_SCALE_THAT_RATES,
+		YOU_CANT_DO_THAT_YET,
+		I_DONT_UNDERSTAND,
+		NOTHING,
+		YOUVE_SOLVED_IT};
+
+	for (int i = 0; i < 40; i++) {
+		_G(_sys)[messagekey[i]] = _G(_systemMessages)[i];
+	}
+
+	_G(_sys)[I_DONT_KNOW_HOW_TO] = "I don't know how to \"";
+	_G(_sys)[SOMETHING] = "\" something. ";
+}
+
 } // End of namespace Scott
 } // End of namespace Glk
diff --git a/engines/glk/scott/game_specific.h b/engines/glk/scott/game_specific.h
index 9550c9843a3..d7ae6e881db 100644
--- a/engines/glk/scott/game_specific.h
+++ b/engines/glk/scott/game_specific.h
@@ -37,6 +37,7 @@ namespace Glk {
 namespace Scott {
 
 void mysterious64Sysmess();
+void claymorgue64Sysmess();
 
 } // End of namespace Scott
 } // End of namespace Glk
diff --git a/engines/glk/scott/games.h b/engines/glk/scott/games.h
index b486e90a6cb..19bd1bce493 100644
--- a/engines/glk/scott/games.h
+++ b/engines/glk/scott/games.h
@@ -1446,5 +1446,89 @@ const GameInfo _games[NUMGAMES] = {
 			 139,    // number_of_pictures;
 			 C64B,   // palette
 			 4,      // picture_format_version;
+			 0),
+	GameInfo("The Sorcerer of Claymorgue Castle",
+			 CLAYMORGUE,
+			 NO_TYPE,                  // type
+			 ENGLISH,                  // subtype
+			 FIVE_LETTER_UNCOMPRESSED, // dictionary type
+
+			 75,  // Number of items
+			 267, // Number of actions
+			 109, // Number of words
+			 32,  // Number of rooms
+			 10,  // Max carried items
+			 5,   // Word length
+			 79,  // Number of messages
+
+			 110, // number_of_verbs
+			 108, // number_of_nouns;
+
+			 0x246c, // header
+			 EARLY,  // header style
+
+			 0x3bf6,  // room images
+			 FOLLOWS, // item flags
+			 FOLLOWS, // item images
+			 FOLLOWS, // actions
+			 UNCOMPRESSED,
+			 0x4ecf,  // dictionary
+			 0x53f7,  // start_of_room_descriptions;
+			 0x4d6f,  // start_of_room_connections;
+			 0x5605,  // start_of_messages;
+			 FOLLOWS, // start_of_item_descriptions;
+			 0x4e35,  // start_of_item_locations;
+
+			 0x24e2, // start_of_system_messages
+			 0x2877, // start of directions
+
+			 0x6007,  // start_of_characters;
+			 0x6807,  // start_of_image_data
+			 -0x3fe5, // image_address_offset
+			 37,      // number_of_pictures;
+			 ZXOPT,   // palette
+			 1,       // picture_format_version;
+			 0),
+	GameInfo("The Sorcerer of Claymorgue Castle C64",
+			 CLAYMORGUE_C64,
+			 NO_TYPE,                             // type
+			 static_cast<Subtype>(ENGLISH | C64), // subtype
+			 FIVE_LETTER_UNCOMPRESSED,            // dictionary type
+
+			 75,  // Number of items
+			 265, // Number of actions
+			 108, // Number of words
+			 32,  // Number of rooms
+			 10,  // Max carried items
+			 5,   // Word length
+			 79,  // Number of messages
+
+			 110, // number_of_verbs
+			 108, // number_of_nouns;
+
+			 0x47d6, // header
+			 EARLY,  // header style
+
+			 0x471f,  // room images
+			 FOLLOWS, // item flags
+			 FOLLOWS, // item images
+			 0x47f0,  // actions
+			 UNCOMPRESSED,
+			 0x5891,  // dictionary
+			 FOLLOWS, // start_of_room_descriptions;
+			 FOLLOWS, // start_of_room_connections;
+			 FOLLOWS, // start_of_messages;
+			 FOLLOWS, // start_of_item_descriptions;
+			 FOLLOWS, // start_of_item_locations;
+
+			 0xa2c, // start_of_system_messages
+			 0xa2c, // start of directions
+
+			 0x6b1a, // start_of_characters;
+			 0x731a, // start_of_image_data
+			 0x6b1a, // image_address_offset
+			 44,     // number_of_pictures;
+			 C64B,   // palette
+			 1,      // picture_format_version;
 			 0)
 };
diff --git a/engines/glk/scott/globals.cpp b/engines/glk/scott/globals.cpp
index 5c08b2e361f..e42d9009da4 100644
--- a/engines/glk/scott/globals.cpp
+++ b/engines/glk/scott/globals.cpp
@@ -117,6 +117,7 @@ Globals::Globals() : _sys(MAX_SYSMESS), _directions(NUMBER_OF_DIRECTIONS), _extr
 	_md5Index.setVal("e5d743d8727c8aca011a737bbb5ad818", 21); // gremlins
 	_md5Index.setVal("267c3fe2bb150365de0358f07b5df15c", 24); // seas of blood
 	_md5Index.setVal("46280fb1d701a41492b8434467c31029", 23); // seas of blood
+	_md5Index.setVal("a1db488c49ad221fa0dc79591cb5a3db", 26); // sorcerer of claymorgue castle
 }
 
 Globals::~Globals() {
diff --git a/engines/glk/scott/load_game.cpp b/engines/glk/scott/load_game.cpp
index 6b2be0cd01f..4897ace4378 100644
--- a/engines/glk/scott/load_game.cpp
+++ b/engines/glk/scott/load_game.cpp
@@ -143,6 +143,9 @@ void loadGameFile(Common::SeekableReadStream *f) {
 	case SEAS_OF_BLOOD_C64:
 		loadExtraSeasOfBlood64Data();
 		break;
+	case CLAYMORGUE_C64:
+		claymorgue64Sysmess();
+		break;
 	case GREMLINS_GERMAN_C64:
 		loadExtraGermanGremlinsc64Data();
 		break;


Commit: 951e1a824036a57d00fbd4773ccbe3e377810b8d
    https://github.com/scummvm/scummvm/commit/951e1a824036a57d00fbd4773ccbe3e377810b8d
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Add support for Adventure Land

Changed paths:
    engines/glk/scott/c64_checksums.cpp
    engines/glk/scott/detection_tables.h
    engines/glk/scott/game_specific.cpp
    engines/glk/scott/game_specific.h
    engines/glk/scott/games.h
    engines/glk/scott/globals.cpp
    engines/glk/scott/load_game.cpp
    engines/glk/scott/scott.cpp


diff --git a/engines/glk/scott/c64_checksums.cpp b/engines/glk/scott/c64_checksums.cpp
index 8a64138f3e2..0f15a30c795 100644
--- a/engines/glk/scott/c64_checksums.cpp
+++ b/engines/glk/scott/c64_checksums.cpp
@@ -112,6 +112,12 @@ static C64Rec g_C64Registry[] = {
 	{ CLAYMORGUE_C64, 0xbc5f,  0x492c, TYPE_T64, 1, nullptr, nullptr, 0, 0x855, 0x7352, 0x20},		// Sorcerer Of Claymorgue Castle C64 (T64) alt 3, , Section8 Packer
 	{ CLAYMORGUE_C64, 0x2ab00, 0xfd67, TYPE_D64, 1, nullptr, nullptr, 0, 0x855, 0x7352, 0x20},		// Sorcerer Of Claymorgue Castle C64 (D64), Section8 Packer
 
+	{ ADVENTURELAND_C64, 0x6a10,  0x1910, TYPE_T64, 1 },                                               // Adventureland C64 (T64) CruelCrunch v2.2
+	{ ADVENTURELAND_C64, 0x6a10,  0x1b10, TYPE_T64, 1, nullptr, nullptr,	0,		0, 0 },            // Adventureland C64 (T64) alt CruelCrunch v2.2
+	{ ADVENTURELAND_C64, 0x2ab00, 0x6638, TYPE_D64, 1, nullptr, nullptr,	0,		0, 0 },            // Adventureland C64 (D64) CruelCrunch v2.2
+	{ ADVENTURELAND_C64, 0x2adab, 0x751f, TYPE_D64, 0, nullptr, nullptr,	0,		0, 0 },            // Adventureland C64 (D64) alt
+	{ ADVENTURELAND_C64, 0x2adab, 0x64a4, TYPE_D64, 0, nullptr, "SAG1PIC",	-0xa53, 0, 0, 0, 0x65af} , // Adventureland C64 (D64) alt 2
+
 	{ UNKNOWN_GAME, 0, 0, UNKNOWN_FILE_TYPE, 0, nullptr, nullptr, 0, 0, 0, 0 }
 };
 
diff --git a/engines/glk/scott/detection_tables.h b/engines/glk/scott/detection_tables.h
index 1b426b3eedc..1a94cb84e34 100644
--- a/engines/glk/scott/detection_tables.h
+++ b/engines/glk/scott/detection_tables.h
@@ -190,7 +190,12 @@ const GlkDetectionEntry SCOTT_GAMES[] = {
 	DT_ENTRY1("seasofblood",	 "C64", "46280fb1d701a41492b8434467c31029", 41481),
 
 	//Scott Adams
-	DT_ENTRY1("claymorguesorcerer","C64", "a1db488c49ad221fa0dc79591cb5a3db", 28663),
+	DT_ENTRY1("adventureland",		"C64", "05cf6c64ecde5288ae2e46099bfd19a3", 27152),
+	DT_ENTRY1("adventureland",		"C64", "5af919881417920ec6a3961b4577f587", 27152),
+	DT_ENTRY1("claymorguesorcerer", "C64", "a1db488c49ad221fa0dc79591cb5a3db", 28663),
+	DT_ENTRY1("claymorguesorcerer", "C64", "1ebaf9a378355246aa7ed2623bb27fab", 49373),
+	DT_ENTRY1("claymorguesorcerer", "C64", "dde67117a432420ef05f8d665fbbbe10", 37167),
+	DT_ENTRY1("claymorguesorcerer", "C64", "64fcee173adecc0f03c595e25d4def04", 174848),
 
 	// 11 Mysterious Adventures
 	DT_ENTRY1("mysadv1", "C64", "b4d8fc4eabed4f2400717303561ad0fa", 174848),
diff --git a/engines/glk/scott/game_specific.cpp b/engines/glk/scott/game_specific.cpp
index d56d6b5e9a3..90afef8554e 100644
--- a/engines/glk/scott/game_specific.cpp
+++ b/engines/glk/scott/game_specific.cpp
@@ -185,5 +185,88 @@ void claymorgue64Sysmess() {
 	_G(_sys)[SOMETHING] = "\" something. ";
 }
 
+void adventurelandAction(int p) {
+	int image = 0;
+	switch (p) {
+	case 1:
+		image = 36;
+		break;
+	case 2:
+		image = 34;
+		break;
+	case 3:
+		image = 33;
+		break;
+	case 4:
+		image = 35;
+		break;
+	default:
+		error("Adventureland: Unsupported action parameter %d", p);
+		return;
+	}
+	g_scott->drawImage(image);
+	g_scott->output("\n");
+	g_scott->output(_G(_sys)[HIT_ENTER]);
+	g_scott->hitEnter();
+	return;
+}
+
+void adventurelandDarkness() {
+	if ((_G(_rooms)[MY_LOC]._image & 128) == 128)
+		_G(_bitFlags) |= 1 << DARKBIT;
+	else
+		_G(_bitFlags) &= ~(1 << DARKBIT);
+}
+
+void adventureland64Sysmess() {
+	SysMessageType messagekey[] = {
+		NORTH,
+		SOUTH,
+		EAST,
+		WEST,
+		UP,
+		DOWN,
+		EXITS,
+		YOU_SEE,
+		YOU_ARE,
+		TOO_DARK_TO_SEE,
+		LIGHT_HAS_RUN_OUT,
+		LIGHT_RUNS_OUT_IN,
+		TURNS,
+		I_DONT_KNOW_HOW_TO,
+		SOMETHING,
+		I_DONT_KNOW_WHAT_A,
+		IS,
+		YOU_CANT_GO_THAT_WAY,
+		OK,
+		WHAT_NOW,
+		HUH,
+		YOU_HAVENT_GOT_IT,
+		INVENTORY,
+		YOU_DONT_SEE_IT,
+		THATS_BEYOND_MY_POWER,
+		DANGEROUS_TO_MOVE_IN_DARK,
+		DIRECTION,
+		YOU_FELL_AND_BROKE_YOUR_NECK,
+		YOURE_CARRYING_TOO_MUCH,
+		IM_DEAD,
+		PLAY_AGAIN,
+		RESUME_A_SAVED_GAME,
+		IVE_STORED,
+		TREASURES,
+		ON_A_SCALE_THAT_RATES,
+		YOU_CANT_DO_THAT_YET,
+		I_DONT_UNDERSTAND,
+		NOTHING,
+		YOUVE_SOLVED_IT};
+
+	for (int i = 0; i < 39; i++) {
+		_G(_sys)[messagekey[i]] = _G(_systemMessages)[i];
+	}
+
+	_G(_sys)[I_DONT_KNOW_HOW_TO] = "I don't know how to \"";
+	_G(_sys)[SOMETHING] = "\" something. ";
+}
+
 } // End of namespace Scott
 } // End of namespace Glk
diff --git a/engines/glk/scott/game_specific.h b/engines/glk/scott/game_specific.h
index d7ae6e881db..8916ddf4ced 100644
--- a/engines/glk/scott/game_specific.h
+++ b/engines/glk/scott/game_specific.h
@@ -38,6 +38,9 @@ namespace Scott {
 
 void mysterious64Sysmess();
 void claymorgue64Sysmess();
+void adventurelandAction(int p);
+void adventurelandDarkness();
+void adventureland64Sysmess();
 
 } // End of namespace Scott
 } // End of namespace Glk
diff --git a/engines/glk/scott/games.h b/engines/glk/scott/games.h
index 19bd1bce493..3ad84c48a9d 100644
--- a/engines/glk/scott/games.h
+++ b/engines/glk/scott/games.h
@@ -1530,5 +1530,89 @@ const GameInfo _games[NUMGAMES] = {
 			 44,     // number_of_pictures;
 			 C64B,   // palette
 			 1,      // picture_format_version;
-			 0)
+			 0),
+	GameInfo("Adventureland",
+			 ADVENTURELAND,
+			 NO_TYPE,                   // type
+			 ENGLISH,                   // subtype
+			 THREE_LETTER_UNCOMPRESSED, // dictionary type
+
+			 65,  // Number of items
+			 181, // Number of actions
+			 69,  // Number of words
+			 33,  // Number of rooms
+			 6,   // Max carried items
+			 3,   // Word length
+			 75,  // Number of messages
+
+			 70, // number_of_verbs
+			 69, // number_of_nouns;
+
+			 0x2473, // header
+			 EARLY,  // header style
+
+			 0x3ebe,  // room images
+			 FOLLOWS, // item flags
+			 0x3f1f,  // item images
+			 0x3f5e,  // actions
+			 UNCOMPRESSED,
+			 0x4c10,  // dictionary
+			 0x4e40,  // start_of_room_descriptions;
+			 0x4abe,  // start_of_room_connections;
+			 0x52c3,  // start_of_messages;
+			 FOLLOWS, // start_of_item_descriptions;
+			 0x4b8a,  // start_of_item_locations;
+
+			 0x24eb, // start_of_system_messages
+			 0x285e, // start of directions
+
+			 0x631e,  // start_of_characters;
+			 FOLLOWS, // start_of_image_data
+			 -0x3fe5, // image_address_offset
+			 41,      // number_of_pictures;
+			 ZXOPT,   // palette
+			 1,       // picture_format_version;
+			 0),
+	GameInfo("Adventureland C64",
+			 ADVENTURELAND_C64,
+			 NO_TYPE,                             // type
+			 static_cast<Subtype>(ENGLISH | C64), // subtype
+			 THREE_LETTER_UNCOMPRESSED,           // dictionary type
+
+			 62,  // Number of items
+			 170, // Number of actions
+			 69,  // Number of words
+			 33,  // Number of rooms
+			 6,   // Max carried items
+			 3,   // Word length
+			 75,  // Number of messages
+
+			 70, // number_of_verbs
+			 69, // number_of_nouns;
+
+			 0x4146, // header
+			 EARLY,  // header style
+
+			 0x6364, // room images
+			 0x85a7, // item flags
+			 0x63c5, // item images
+			 0x4160, // actions
+			 UNCOMPRESSED,
+			 0x4c10,  // dictionary
+			 0x4e40,  // start_of_room_descriptions;
+			 FOLLOWS, // start_of_room_connections;
+			 FOLLOWS, // start_of_messages;
+			 FOLLOWS, // start_of_item_descriptions;
+			 0x6404,  // start_of_item_locations;
+
+			 0x188, // start_of_system_messages
+			 0x188, // start of directions
+
+			 0x6482,  // start_of_characters;
+			 0x6c82,  // start_of_image_data
+			 -0x1102, // image_address_offset
+			 41,      // number_of_pictures;
+			 C64B,    // palette
+			 1,       // picture_format_version;
+			 0),
 };
diff --git a/engines/glk/scott/globals.cpp b/engines/glk/scott/globals.cpp
index e42d9009da4..39833c6de4c 100644
--- a/engines/glk/scott/globals.cpp
+++ b/engines/glk/scott/globals.cpp
@@ -118,6 +118,11 @@ Globals::Globals() : _sys(MAX_SYSMESS), _directions(NUMBER_OF_DIRECTIONS), _extr
 	_md5Index.setVal("267c3fe2bb150365de0358f07b5df15c", 24); // seas of blood
 	_md5Index.setVal("46280fb1d701a41492b8434467c31029", 23); // seas of blood
 	_md5Index.setVal("a1db488c49ad221fa0dc79591cb5a3db", 26); // sorcerer of claymorgue castle
+	_md5Index.setVal("1ebaf9a378355246aa7ed2623bb27fab", 28); // sorcerer of claymorgue castle
+	_md5Index.setVal("dde67117a432420ef05f8d665fbbbe10", 27); // sorcerer of claymorgue castle
+	_md5Index.setVal("64fcee173adecc0f03c595e25d4def04", 30); // sorcerer of claymorgue castle
+	_md5Index.setVal("05cf6c64ecde5288ae2e46099bfd19a3", 31); // adventureland
+	_md5Index.setVal("5af919881417920ec6a3961b4577f587", 32); // adventureland
 }
 
 Globals::~Globals() {
diff --git a/engines/glk/scott/load_game.cpp b/engines/glk/scott/load_game.cpp
index 4897ace4378..1ada3b9c6b2 100644
--- a/engines/glk/scott/load_game.cpp
+++ b/engines/glk/scott/load_game.cpp
@@ -143,6 +143,17 @@ void loadGameFile(Common::SeekableReadStream *f) {
 	case SEAS_OF_BLOOD_C64:
 		loadExtraSeasOfBlood64Data();
 		break;
+	case ADVENTURELAND:
+		for (int i = PLAY_AGAIN; i <= ON_A_SCALE_THAT_RATES; i++)
+			_G(_sys)[i] = _G(_systemMessages)[2 - PLAY_AGAIN + i];
+		for (int i = OK; i <= YOU_HAVENT_GOT_IT; i++)
+			_G(_sys)[i] = _G(_systemMessages)[6 - OK + i];
+		for (int i = YOU_DONT_SEE_IT; i <= RESUME_A_SAVED_GAME; i++)
+			_G(_sys)[i] = _G(_systemMessages)[13 - YOU_DONT_SEE_IT + i];
+		break;
+	case ADVENTURELAND_C64:
+		adventureland64Sysmess();
+		break;
 	case CLAYMORGUE_C64:
 		claymorgue64Sysmess();
 		break;
diff --git a/engines/glk/scott/scott.cpp b/engines/glk/scott/scott.cpp
index 1b53a24db18..3a760a33d86 100644
--- a/engines/glk/scott/scott.cpp
+++ b/engines/glk/scott/scott.cpp
@@ -48,6 +48,7 @@
 #include "glk/scott/robin_of_sherwood.h"
 #include "glk/scott/gremlins.h"
 #include "glk/scott/seas_of_blood.h"
+#include "glk/scott/game_specific.h"
 
 namespace Glk {
 namespace Scott {
@@ -1123,8 +1124,7 @@ ActionResultType Scott::performLine(int ct) {
 					break;
 				case ADVENTURELAND:
 				case ADVENTURELAND_C64:
-					// TODO
-					// AdventurelandAction(p);
+					adventurelandAction(p);
 					break;
 				case SEAS_OF_BLOOD:
 				case SEAS_OF_BLOOD_C64:
@@ -1705,8 +1705,7 @@ void Scott::drawImage(int image) {
 
 void Scott::drawRoomImage() {
 	if (CURRENT_GAME == ADVENTURELAND || CURRENT_GAME == ADVENTURELAND_C64) {
-		// TODO
-		// AdventurelandDarkness();
+		adventurelandDarkness();
 	}
 
 	int dark = ((_G(_bitFlags) & (1 << DARKBIT)) && _G(_items)[LIGHT_SOURCE]._location != CARRIED && _G(_items)[LIGHT_SOURCE]._location != MY_LOC);


Commit: b45eecac999513ed54783b586ea944e8ed7f2710
    https://github.com/scummvm/scummvm/commit/b45eecac999513ed54783b586ea944e8ed7f2710
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Add support for Savage Island

Changed paths:
    engines/glk/scott/c64_checksums.cpp
    engines/glk/scott/detection_tables.h
    engines/glk/scott/games.h
    engines/glk/scott/globals.cpp
    engines/glk/scott/globals.h
    engines/glk/scott/load_game.cpp


diff --git a/engines/glk/scott/c64_checksums.cpp b/engines/glk/scott/c64_checksums.cpp
index 0f15a30c795..d4591660232 100644
--- a/engines/glk/scott/c64_checksums.cpp
+++ b/engines/glk/scott/c64_checksums.cpp
@@ -116,7 +116,12 @@ static C64Rec g_C64Registry[] = {
 	{ ADVENTURELAND_C64, 0x6a10,  0x1b10, TYPE_T64, 1, nullptr, nullptr,	0,		0, 0 },            // Adventureland C64 (T64) alt CruelCrunch v2.2
 	{ ADVENTURELAND_C64, 0x2ab00, 0x6638, TYPE_D64, 1, nullptr, nullptr,	0,		0, 0 },            // Adventureland C64 (D64) CruelCrunch v2.2
 	{ ADVENTURELAND_C64, 0x2adab, 0x751f, TYPE_D64, 0, nullptr, nullptr,	0,		0, 0 },            // Adventureland C64 (D64) alt
-	{ ADVENTURELAND_C64, 0x2adab, 0x64a4, TYPE_D64, 0, nullptr, "SAG1PIC",	-0xa53, 0, 0, 0, 0x65af} , // Adventureland C64 (D64) alt 2
+	{ ADVENTURELAND_C64, 0x2adab, 0x64a4, TYPE_D64, 0, nullptr, "SAG1PIC",	-0xa53, 0, 0, 0, 0x65af }, // Adventureland C64 (D64) alt 2
+
+	{ SAVAGE_ISLAND_C64,  0x2ab00, 0x8801, TYPE_D64, 1, "-f86 -d0x1793", "SAVAGEISLAND1+",   1, 0, 0 }, // Savage Island part 1 C64 (D64)
+	{ SAVAGE_ISLAND2_C64, 0x2ab00, 0x8801, TYPE_D64, 1, "-f86 -d0x178b", "SAVAGEISLAND2+",   1, 0, 0 }, // Savage Island part 2 C64 (D64)
+	{ SAVAGE_ISLAND_C64,  0x2ab00, 0xc361, TYPE_D64, 1, "-f86 -d0x1793", "SAVAGE ISLAND P1", 1, 0, 0 }, // Savage Island part 1 C64 (D64) alt
+	{ SAVAGE_ISLAND2_C64, 0x2ab00, 0xc361, TYPE_D64, 1, nullptr,		 "SAVAGE ISLAND P2", 0, 0, 0 }, // Savage Island part 2  C64 (D64) alt
 
 	{ UNKNOWN_GAME, 0, 0, UNKNOWN_FILE_TYPE, 0, nullptr, nullptr, 0, 0, 0, 0 }
 };
@@ -162,6 +167,78 @@ uint8_t *getFileNamed(uint8_t* data, int length, int* newLength, const char* nam
 	return file;
 }
 
+int savageIslandMenu(uint8_t **sf, size_t *extent, int recIndex) {
+	g_scott->output("This disk image contains two games. Select one.\n\n"
+					"1. Savage Island part I\n"
+					"2. Savage Island part II");
+
+	g_scott->glk_request_char_event(_G(_bottomWindow));
+
+	event_t ev;
+	int result = 0;
+	do {
+		g_scott->glk_select(&ev);
+		if (ev.type == evtype_CharInput) {
+			if (ev.val1 == '1' || ev.val1 == '2') {
+				result = ev.val1 - '0';
+			} else {
+				g_scott->glk_request_char_event(_G(_bottomWindow));
+			}
+		}
+	} while (result == 0);
+
+	g_scott->glk_window_clear(_G(_bottomWindow));
+
+	recIndex += result - 1;
+
+	C64Rec rec = g_C64Registry[recIndex];
+	int length;
+	uint8_t *file = getFileNamed(*sf, *extent, &length, rec._appendFile);
+
+	if (file != nullptr) {
+		if (rec._chk == 0xc361) {
+			if (rec._switches != nullptr) {
+				_G(_saveIslandAppendix1) = getFileNamed(*sf, *extent, &_G(_saveIslandAppendix1Length), "SI1PC1");
+				_G(_saveIslandAppendix2) = getFileNamed(*sf, *extent, &_G(_saveIslandAppendix2Length), "SI1PC2");
+			} else {
+				_G(_saveIslandAppendix1) = getFileNamed(*sf, *extent, &_G(_saveIslandAppendix1Length), "SI2PIC");
+			}
+		}
+		delete[] *sf;
+		*sf = file;
+		*extent = length;
+		if (_G(_saveIslandAppendix1Length) > 2)
+			_G(_saveIslandAppendix1Length) -= 2;
+		if (_G(_saveIslandAppendix2Length) > 2)
+			_G(_saveIslandAppendix2Length) -= 2;
+		return decrunchC64(sf, extent, rec);
+	} else {
+		error("savageIslandMenu: Failed loading file %s\n", rec._appendFile);
+		return 0;
+	}
+}
+
+void appendSIfiles(uint8_t **sf, size_t *extent) {
+	int totalLength = *extent + _G(_saveIslandAppendix1Length) + _G(_saveIslandAppendix2Length);
+
+	uint8_t *megabuf = new uint8_t[0xFFFF];
+	memcpy(megabuf, *sf, *extent);
+	delete[] *sf;
+	int offset = 0x6202;
+
+	if (_G(_saveIslandAppendix1)) {
+		memcpy(megabuf + offset, _G(_saveIslandAppendix1) + 2, _G(_saveIslandAppendix1Length));
+		delete[] _G(_saveIslandAppendix1);
+	}
+	if (_G(_saveIslandAppendix2)) {
+		memcpy(megabuf + offset + _G(_saveIslandAppendix1Length), _G(_saveIslandAppendix2) + 2, _G(_saveIslandAppendix2Length));
+		delete[] _G(_saveIslandAppendix2);
+	}
+	*extent = offset + _G(_saveIslandAppendix1Length) + _G(_saveIslandAppendix2Length);
+	*sf = new uint8_t[*extent];
+	memcpy(*sf, megabuf, *extent);
+}
+
 int mysteriousMenu(uint8_t **sf, size_t *extent, int recindex) {
 	recindex = 0;
 
@@ -219,7 +296,7 @@ int mysteriousMenu(uint8_t **sf, size_t *extent, int recindex) {
 	uint8_t *file = getFileNamed(*sf, *extent, &length, filename);
 
 	if (file != nullptr) {
-		delete[] * sf;
+		delete[] *sf;
 		*sf = file;
 		*extent = length;
 		C64Rec rec = g_C64Registry[recindex - 1 + result];
@@ -283,7 +360,7 @@ int mysteriousMenu2(uint8_t **sf, size_t *extent, int recindex) {
 	uint8_t *file = getFileNamed(*sf, *extent, &length, filename);
 
 	if (file != nullptr) {
-		delete[] * sf;
+		delete[] *sf;
 		*sf = file;
 		*extent = length;
 		C64Rec rec = g_C64Registry[recindex - 1 + result];
@@ -300,7 +377,9 @@ int detectC64(uint8_t **sf, size_t *extent) {
 
 	Common::String md5 = g_vm->getGameMD5();
 	int index = _G(_md5Index)[md5];
-	if (g_C64Registry[index]._id == BATON_C64) {
+	if (g_C64Registry[index]._id == SAVAGE_ISLAND_C64) {
+		return savageIslandMenu(sf, extent, index);
+	} else if (g_C64Registry[index]._id == BATON_C64) {
 		return mysteriousMenu(sf, extent, index);
 	} else if (g_C64Registry[index]._id == FEASIBILITY_C64) {
 		return mysteriousMenu2(sf, extent, index);
@@ -429,6 +508,10 @@ int decrunchC64(uint8_t **sf, size_t *extent, C64Rec record) {
 		error("decrunchC64: Game could not be read");
 	}
 
+	if (_G(_saveIslandAppendix1) != nullptr) {
+		appendSIfiles(sf, extent);
+	}
+
 	if (record._copySource != 0) {
 		result = copyData(record._copyDest, record._copySource, sf, *extent, record._copySize);
 		if (result) {
@@ -436,6 +519,13 @@ int decrunchC64(uint8_t **sf, size_t *extent, C64Rec record) {
 		}
 	}
 
+	if (CURRENT_GAME == CLAYMORGUE_C64 && record._copySource == 0x855) {
+		result = copyData(0x1531a, 0x2002, sf, *extent, 0x2000);
+		if (result) {
+			*extent = result;
+		}
+	}
+
 	if (!(_G(_game)->_subType & MYSTERIOUS))
 		sagaSetup(record._imgOffset);
 
diff --git a/engines/glk/scott/detection_tables.h b/engines/glk/scott/detection_tables.h
index 1a94cb84e34..0fb264d1fc1 100644
--- a/engines/glk/scott/detection_tables.h
+++ b/engines/glk/scott/detection_tables.h
@@ -48,6 +48,7 @@ const PlainGameDescriptor SCOTT_GAME_LIST[] = {
 	{ "mysteryfunhouse",	"Mystery Fun House" },
 	{ "pyramidofdoom",		"Pyramid Of Doom" },
 	{ "ghosttown",			"Ghost Town" },
+	{ "savageisland",		"Savage Island" },
 	{ "savageisland1",		"Savage Island, Part 1" },
 	{ "savageisland2",		"Savage Island, Part 2" },
 	{ "goldenvoyage",		"The Golden Voyage" },
@@ -196,6 +197,7 @@ const GlkDetectionEntry SCOTT_GAMES[] = {
 	DT_ENTRY1("claymorguesorcerer", "C64", "1ebaf9a378355246aa7ed2623bb27fab", 49373),
 	DT_ENTRY1("claymorguesorcerer", "C64", "dde67117a432420ef05f8d665fbbbe10", 37167),
 	DT_ENTRY1("claymorguesorcerer", "C64", "64fcee173adecc0f03c595e25d4def04", 174848),
+	DT_ENTRY1("savageisland",		"C64", "414d459ceb211230356ad823475866b3", 174848),
 
 	// 11 Mysterious Adventures
 	DT_ENTRY1("mysadv1", "C64", "b4d8fc4eabed4f2400717303561ad0fa", 174848),
diff --git a/engines/glk/scott/games.h b/engines/glk/scott/games.h
index 3ad84c48a9d..071b17c0b21 100644
--- a/engines/glk/scott/games.h
+++ b/engines/glk/scott/games.h
@@ -1615,4 +1615,169 @@ const GameInfo _games[NUMGAMES] = {
 			 C64B,    // palette
 			 1,       // picture_format_version;
 			 0),
+	GameInfo("Savage Island part I",
+			 SAVAGE_ISLAND,
+			 SAVAGE_ISLAND_VARIANT,    // type
+			 ENGLISH,                  // subtype
+			 FOUR_LETTER_UNCOMPRESSED, // dictionary type
+
+			 58,  // Number of items
+			 259, // Number of actions
+			 84,  // Number of words
+			 34,  // Number of rooms
+			 6,   // Max carried items
+			 4,   // Word length
+			 99,  // Number of messages
+
+			 82, // number_of_verbs
+			 84, // number_of_nouns;
+
+			 0x236d,  // header
+			 LATE,    // header style
+			 0x390c,  // room images
+			 FOLLOWS, // item flags
+			 FOLLOWS, // item images
+			 0x39a6,  // actions
+			 COMPRESSED,
+			 0x4484,  // dictionary
+			 0x47c7,  // start_of_room_descriptions;
+			 FOLLOWS, // start_of_room_connections;
+			 0x4b91,  // start_of_messages;
+			 FOLLOWS, // start_of_item_descriptions;
+			 FOLLOWS, // start_of_item_locations;
+
+			 0x2423, // start_of_system_messages
+			 0x25f3, // start of directions
+
+			 0x570f,  // start_of_characters;
+			 FOLLOWS, // start_of_image_data
+			 0x600f,  // image_address_offset
+			 37,      // number_of_pictures;
+			 ZXOPT,   // palette
+			 3,       // picture_format_version;
+			 0),
+	GameInfo("Savage Island part I (C64)",
+			 SAVAGE_ISLAND_C64,
+			 SAVAGE_ISLAND_VARIANT,               // type
+			 static_cast<Subtype>(ENGLISH | C64), // subtype
+			 FOUR_LETTER_UNCOMPRESSED,            // dictionary type
+
+			 58,  // Number of items
+			 259, // Number of actions
+			 84,  // Number of words
+			 34,  // Number of rooms
+			 6,   // Max carried items
+			 4,   // Word length
+			 99,  // Number of messages
+
+			 85, // number_of_verbs
+			 84, // number_of_nouns;
+
+			 0x46dc,  // header
+			 EARLY,   // header style
+			 0x4645,  // room images
+			 FOLLOWS, // item flags
+			 FOLLOWS, // item images
+			 0x46f6,  // actions
+			 COMPRESSED,
+			 0x51d6,  // dictionary
+			 0x5528,  // start_of_room_descriptions;
+			 FOLLOWS, // start_of_room_connections;
+			 FOLLOWS, // start_of_messages;
+					  //        0x58f6, // start_of_messages;
+			 FOLLOWS, // start_of_item_descriptions;
+			 FOLLOWS, // start_of_item_locations;
+
+			 0x0a5f, // start_of_system_messages
+			 0x0a5f, // start of directions
+
+			 0x6A02, // start_of_characters;
+			 0x7202, // start_of_image_data
+			 0x7302, // image_address_offset
+			 37,     // number_of_pictures;
+			 C64B,   // palette
+			 3,      // picture_format_version;
+			 0),
+	GameInfo("Savage Island part II",
+			 SAVAGE_ISLAND2,
+			 NO_TYPE,                  // type
+			 ENGLISH,                  // subtype
+			 FOUR_LETTER_UNCOMPRESSED, // dictionary type
+
+			 48,  // Number of items
+			 241, // Number of actions
+			 79,  // Number of words
+			 30,  // Number of rooms
+			 6,   // Max carried items
+			 4,   // Word length
+			 95,  // Number of messages
+
+			 74, // number_of_verbs
+			 79, // number_of_nouns;
+
+			 0x236d,  // header
+			 LATE,    // header style
+			 0x390c,  // room images
+			 FOLLOWS, // item flags
+			 FOLLOWS, // item images
+			 0x398e,  // actions
+			 COMPRESSED,
+			 0x43f0,  // dictionary
+			 0x46ed,  // start_of_room_descriptions;
+			 FOLLOWS, // start_of_room_connections;
+			 FOLLOWS, // start_of_messages;
+			 FOLLOWS, // start_of_item_descriptions;
+			 FOLLOWS, // start_of_item_locations;
+
+			 0x2423, // start_of_system_messages
+			 0x25f3, // start of directions
+
+			 0x57d0,  // start_of_characters;
+			 FOLLOWS, // start_of_image_data
+			 0x60d0,  // image_address_offset
+			 21,      // number_of_pictures;
+			 ZXOPT,   // palette
+			 3,       // picture_format_version;
+			 0),
+	GameInfo("Savage Island part II (C64)",
+			 SAVAGE_ISLAND2_C64,
+			 NO_TYPE,                             // type
+			 static_cast<Subtype>(ENGLISH | C64), // subtype
+			 FOUR_LETTER_UNCOMPRESSED,            // dictionary type
+
+			 48,  // Number of items
+			 241, // Number of actions
+			 78,  // Number of words
+			 30,  // Number of rooms
+			 6,   // Max carried items
+			 4,   // Word length
+			 94,  // Number of messages
+
+			 79, // number_of_verbs
+			 79, // number_of_nouns;
+
+			 0x4654,  // header
+			 EARLY,   // header style
+			 0x6310,  // room images
+			 FOLLOWS, // item flags
+			 FOLLOWS, // item images
+			 0x466e,  // actions
+			 COMPRESSED,
+			 0x50d2,  // dictionary
+			 0x53e8,  // start_of_room_descriptions;
+			 FOLLOWS, // start_of_room_connections;
+			 FOLLOWS, // start_of_messages;
+			 FOLLOWS, // start_of_item_descriptions;
+			 FOLLOWS, // start_of_item_locations;
+
+			 0x0a50, // start_of_system_messages
+			 0x0a50, // start of directions
+
+			 0x6A02, // start_of_characters;
+			 0x7202, // start_of_image_data
+			 0x7302, // image_address_offset
+			 21,     // number_of_pictures;
+			 C64B,   // palette
+			 3,      // picture_format_version;
+			 0)
 };
diff --git a/engines/glk/scott/globals.cpp b/engines/glk/scott/globals.cpp
index 39833c6de4c..e96e435d6b9 100644
--- a/engines/glk/scott/globals.cpp
+++ b/engines/glk/scott/globals.cpp
@@ -123,6 +123,7 @@ Globals::Globals() : _sys(MAX_SYSMESS), _directions(NUMBER_OF_DIRECTIONS), _extr
 	_md5Index.setVal("64fcee173adecc0f03c595e25d4def04", 30); // sorcerer of claymorgue castle
 	_md5Index.setVal("05cf6c64ecde5288ae2e46099bfd19a3", 31); // adventureland
 	_md5Index.setVal("5af919881417920ec6a3961b4577f587", 32); // adventureland
+	_md5Index.setVal("414d459ceb211230356ad823475866b3", 38); // savage island
 }
 
 Globals::~Globals() {
diff --git a/engines/glk/scott/globals.h b/engines/glk/scott/globals.h
index d7d2b9f3efe..521380ac991 100644
--- a/engines/glk/scott/globals.h
+++ b/engines/glk/scott/globals.h
@@ -203,6 +203,12 @@ public:
 	glui32 _diceYOffset = 0;
 	int _shouldDrawObjectImages = 0;
 
+	// savage island
+	uint8_t *_saveIslandAppendix1 = nullptr;
+	int _saveIslandAppendix1Length = 0;
+	uint8_t *_saveIslandAppendix2 = nullptr;
+	int _saveIslandAppendix2Length = 0;
+
 public:
 	Globals();
 	~Globals();
diff --git a/engines/glk/scott/load_game.cpp b/engines/glk/scott/load_game.cpp
index 1ada3b9c6b2..b033078bb94 100644
--- a/engines/glk/scott/load_game.cpp
+++ b/engines/glk/scott/load_game.cpp
@@ -157,6 +157,17 @@ void loadGameFile(Common::SeekableReadStream *f) {
 	case CLAYMORGUE_C64:
 		claymorgue64Sysmess();
 		break;
+	case SAVAGE_ISLAND_C64:
+		_G(_items)[20]._image = 13;
+	case SAVAGE_ISLAND2_C64:
+		_G(_sys)[IM_DEAD] = "I'm DEAD!! ";
+		if (CURRENT_GAME == SAVAGE_ISLAND2_C64)
+			_G(_rooms)[30]._image = 20;
+		break;
+	case SAVAGE_ISLAND:
+		_G(_items)[20]._image = 13;
+	case SAVAGE_ISLAND2:
+		MY_LOC = 30; /* Both parts of Savage Island begin in room 30 */
 	case GREMLINS_GERMAN_C64:
 		loadExtraGermanGremlinsc64Data();
 		break;


Commit: ff02ca6def583b0738e201fb08b0c3a2c0a802c8
    https://github.com/scummvm/scummvm/commit/ff02ca6def583b0738e201fb08b0c3a2c0a802c8
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Add support for Questprobe Games

Changed paths:
    engines/glk/scott/c64_checksums.cpp
    engines/glk/scott/detection_tables.h
    engines/glk/scott/game_specific.cpp
    engines/glk/scott/game_specific.h
    engines/glk/scott/games.h
    engines/glk/scott/globals.cpp
    engines/glk/scott/hulk.cpp
    engines/glk/scott/load_game.cpp
    engines/glk/scott/scott.cpp


diff --git a/engines/glk/scott/c64_checksums.cpp b/engines/glk/scott/c64_checksums.cpp
index d4591660232..d18adf021fc 100644
--- a/engines/glk/scott/c64_checksums.cpp
+++ b/engines/glk/scott/c64_checksums.cpp
@@ -66,7 +66,7 @@ struct C64Rec {
 	size_t _copySource;
 	size_t _copyDest;
 	size_t _copySize;
-	size_t _imgOffset;
+	int _imgOffset;
 };
 
 static C64Rec g_C64Registry[] = {
@@ -123,6 +123,10 @@ static C64Rec g_C64Registry[] = {
 	{ SAVAGE_ISLAND_C64,  0x2ab00, 0xc361, TYPE_D64, 1, "-f86 -d0x1793", "SAVAGE ISLAND P1", 1, 0, 0 }, // Savage Island part 1 C64 (D64) alt
 	{ SAVAGE_ISLAND2_C64, 0x2ab00, 0xc361, TYPE_D64, 1, nullptr,		 "SAVAGE ISLAND P2", 0, 0, 0 }, // Savage Island part 2  C64 (D64) alt
 
+	{ HULK_C64,		 0x2ab00, 0xcdd8, TYPE_D64, 0, nullptr, nullptr, 0, 0x1806, 0xb801, 0x307 },  // Questprobe 1 - The Hulk C64 (D64)
+	{ SPIDERMAN_C64, 0x2ab00, 0xde56, TYPE_D64, 0, nullptr, nullptr, 0, 0x1801, 0xa801, 0x2000 }, // Spiderman C64 (D64)
+	{ SPIDERMAN_C64, 0x08e72, 0xb2f4, TYPE_T64, 3, nullptr, nullptr, 0, 0, 0 },                   // Spiderman C64 (T64) MasterCompressor / Relax -> ECA Compacker -> Section8 Packer
+
 	{ UNKNOWN_GAME, 0, 0, UNKNOWN_FILE_TYPE, 0, nullptr, nullptr, 0, 0, 0, 0 }
 };
 
diff --git a/engines/glk/scott/detection_tables.h b/engines/glk/scott/detection_tables.h
index 0fb264d1fc1..aca72c330c2 100644
--- a/engines/glk/scott/detection_tables.h
+++ b/engines/glk/scott/detection_tables.h
@@ -189,6 +189,7 @@ const GlkDetectionEntry SCOTT_GAMES[] = {
 	DT_ENTRYL1("gremlins", Common::DE_DEU, "C64", "e5d743d8727c8aca011a737bbb5ad818", 49155),
 	DT_ENTRY1("seasofblood",	 "C64", "267c3fe2bb150365de0358f07b5df15c", 174848),
 	DT_ENTRY1("seasofblood",	 "C64", "46280fb1d701a41492b8434467c31029", 41481),
+	DT_ENTRY1("marveladventure", "C64", "d80e133dd396565f773052cb317e8222", 174848),
 
 	//Scott Adams
 	DT_ENTRY1("adventureland",		"C64", "05cf6c64ecde5288ae2e46099bfd19a3", 27152),
diff --git a/engines/glk/scott/game_specific.cpp b/engines/glk/scott/game_specific.cpp
index 90afef8554e..283a9458ac4 100644
--- a/engines/glk/scott/game_specific.cpp
+++ b/engines/glk/scott/game_specific.cpp
@@ -268,5 +268,58 @@ void adventureland64Sysmess() {
 	_G(_sys)[SOMETHING] = "\" something. ";
 }
 
+void spiderman64Sysmess() {
+	SysMessageType messagekey[] = {
+		NORTH,
+		SOUTH,
+		EAST,
+		WEST,
+		UP,
+		DOWN,
+		EXITS,
+		YOU_SEE,
+		YOU_ARE,
+		TOO_DARK_TO_SEE,
+		LIGHT_HAS_RUN_OUT,
+		LIGHT_RUNS_OUT_IN,
+		TURNS,
+		I_DONT_KNOW_HOW_TO,
+		SOMETHING,
+		I_DONT_KNOW_WHAT_A,
+		IS,
+		YOU_CANT_GO_THAT_WAY,
+		OK,
+		WHAT_NOW,
+		HUH,
+		YOU_HAVE_IT,
+		YOU_HAVENT_GOT_IT,
+		INVENTORY,
+		YOU_DONT_SEE_IT,
+		THATS_BEYOND_MY_POWER,
+		DANGEROUS_TO_MOVE_IN_DARK,
+		DIRECTION,
+		YOU_FELL_AND_BROKE_YOUR_NECK,
+		YOURE_CARRYING_TOO_MUCH,
+		IM_DEAD,
+		DROPPED,
+		TAKEN,
+		PLAY_AGAIN,
+		RESUME_A_SAVED_GAME,
+		IVE_STORED,
+		TREASURES,
+		ON_A_SCALE_THAT_RATES,
+		YOU_CANT_DO_THAT_YET,
+		I_DONT_UNDERSTAND,
+		NOTHING,
+		YOUVE_SOLVED_IT};
+
+	for (int i = 0; i < 42; i++) {
+		_G(_sys)[messagekey[i]] = _G(_systemMessages)[i];
+	}
+
+	_G(_sys)[I_DONT_KNOW_HOW_TO] = "I don't know how to \"";
+	_G(_sys)[SOMETHING] = "\" something. ";
+}
+
 } // End of namespace Scott
 } // End of namespace Glk
diff --git a/engines/glk/scott/game_specific.h b/engines/glk/scott/game_specific.h
index 8916ddf4ced..75e0af0c67d 100644
--- a/engines/glk/scott/game_specific.h
+++ b/engines/glk/scott/game_specific.h
@@ -41,6 +41,7 @@ void claymorgue64Sysmess();
 void adventurelandAction(int p);
 void adventurelandDarkness();
 void adventureland64Sysmess();
+void spiderman64Sysmess();
 
 } // End of namespace Scott
 } // End of namespace Glk
diff --git a/engines/glk/scott/games.h b/engines/glk/scott/games.h
index 071b17c0b21..d28ec4b060c 100644
--- a/engines/glk/scott/games.h
+++ b/engines/glk/scott/games.h
@@ -1779,5 +1779,134 @@ const GameInfo _games[NUMGAMES] = {
 			 21,     // number_of_pictures;
 			 C64B,   // palette
 			 3,      // picture_format_version;
+			 0),
+	GameInfo("Questprobe 2: Spiderman",
+			 SPIDERMAN,
+			 NO_TYPE,                  // type
+			 ENGLISH,                  // subtype
+			 FOUR_LETTER_UNCOMPRESSED, // dictionary type
+
+			 72,  // Number of items
+			 257, // Number of actions
+			 124, // Number of words
+			 40,  // Number of rooms
+			 12,  // Max carried items
+			 4,   // Word length
+			 99,  // Number of messages
+
+			 125, // number_of_verbs
+			 125, // number_of_nouns;
+
+			 0x246b, // header
+			 EARLY,  // header style
+
+			 0x3dd1,  // room images
+			 FOLLOWS, // item flags
+			 FOLLOWS, // item images
+
+			 FOLLOWS, // actions
+			 UNCOMPRESSED,
+			 0x5036,  // dictionary
+			 0x5518,  // start_of_room_descriptions;
+			 0x4eac,  // start_of_room_connections;
+			 0x575e,  // start_of_messages;
+			 FOLLOWS, // start_of_item_descriptions;
+			 0x4fa2,  // start_of_item_locations;
+
+			 0x2553, // start_of_system_messages
+			 0x28f7, // start of directions
+
+			 0x6296,  // start_of_characters;
+			 0x6a96,  // start_of_image_data
+			 -0x3fe5, // image_address_offset
+			 41,      // number_of_pictures;
+			 ZXOPT,   // palette
+			 2,       // picture_format_version;
+			 0),
+	GameInfo("Questprobe 2: Spiderman C64",
+			 SPIDERMAN_C64,
+			 NO_TYPE,                             // type
+			 static_cast<Subtype>(ENGLISH | C64), // subtype
+			 FOUR_LETTER_UNCOMPRESSED,            // dictionary type
+
+			 72,  // Number of items
+			 245, // Number of actions
+			 124, // Number of words
+			 40,  // Number of rooms
+			 12,  // Max carried items
+			 4,   // Word length
+			 98,  // Number of messages
+
+			 118, // number_of_verbs
+			 124, // number_of_nouns;
+
+			 0x4baf, // header
+			 EARLY,  // header style
+
+			 0x4bc9,  // room images
+			 0x70da,  // item flags
+			 FOLLOWS, // item images
+
+			 0x4bf2, // actions
+			 UNCOMPRESSED,
+			 0x5b52,  // dictionary
+			 0x600c,  // start_of_room_descriptions;
+			 FOLLOWS, // start_of_room_connections;
+			 FOLLOWS, // start_of_messages;
+			 0x6b9b,  // start_of_item_descriptions;
+			 FOLLOWS, // start_of_item_locations;
+
+			 0x0a7b, // start_of_system_messages
+			 0x0a7b, // start of directions
+
+			 0x716c, // start_of_characters;
+			 0x796c, // start_of_image_data
+			 0x716c, // image_address_offset
+			 41,     // number_of_pictures;
+			 C64B,   // palette
+			 2,      // picture_format_version;
+			 0),
+	GameInfo("Questprobe 1: The Hulk C64", HULK_C64,
+			 NO_TYPE,                  // type
+			 ENGLISH,                  // subtype
+			 FOUR_LETTER_UNCOMPRESSED, // dictionary type
+
+			 54,  // Number of items
+			 261, // Number of actions
+			 128, // Number of words
+			 20,  // Number of rooms
+			 10,  // Max carried items
+			 4,   // Word length
+			 99,  // Number of messages
+
+			 128, // number_of_verbs
+			 129, // number_of_nouns;
+
+			 0x7867,      // header
+			 HULK_HEADER, // header style
+
+			 0x2280, // room images
+			 0,      // item flags
+			 0x22ba, // item images
+
+			 0x8c47, // actions
+			 HULK_ACTIONS,
+			 0x7884,  // dictionary
+			 0x7d8d,  // start_of_room_descriptions;
+			 0x9CD1,  // start_of_room_connections;
+			 0x831E,  // start_of_messages;
+			 FOLLOWS, // start_of_item_descriptions;
+			 0x8AFD,  // start_of_item_locations;
+
+			 // These are spread out all over the code
+			 0,      // start_of_system_messages
+			 0xae25, // start of directions
+
+			 0x0d01, // start_of_characters;
+			 0x2701, // start_of_image_data
+			 0,      // image_address_offset
+			 43,     // number_of_pictures;
+			 C64B,   // palette
+			 0,      // picture_format_version;
 			 0)
 };
diff --git a/engines/glk/scott/globals.cpp b/engines/glk/scott/globals.cpp
index e96e435d6b9..49e094c84a3 100644
--- a/engines/glk/scott/globals.cpp
+++ b/engines/glk/scott/globals.cpp
@@ -124,6 +124,7 @@ Globals::Globals() : _sys(MAX_SYSMESS), _directions(NUMBER_OF_DIRECTIONS), _extr
 	_md5Index.setVal("05cf6c64ecde5288ae2e46099bfd19a3", 31); // adventureland
 	_md5Index.setVal("5af919881417920ec6a3961b4577f587", 32); // adventureland
 	_md5Index.setVal("414d459ceb211230356ad823475866b3", 38); // savage island
+	_md5Index.setVal("d80e133dd396565f773052cb317e8222", 40); // questprobe hulk
 }
 
 Globals::~Globals() {
diff --git a/engines/glk/scott/hulk.cpp b/engines/glk/scott/hulk.cpp
index a0fe9dc87e2..299fc6416b5 100644
--- a/engines/glk/scott/hulk.cpp
+++ b/engines/glk/scott/hulk.cpp
@@ -415,6 +415,15 @@ int tryLoadingHulk(GameInfo info, int dictStart) {
 		}
 		ct++;
 	}
+
+	if (CURRENT_GAME == HULK_C64) {
+		_G(_hulkCoordinates) = 0x22cd;
+		_G(_hulkItemImageOffsets) = 0x2731;
+		_G(_hulkLookImageOffsets) = 0x2761;
+		_G(_hulkSpecialImageOffsets) = 0x2781;
+		_G(_hulkImageOffset) = -0x7ff;
+	}
+
 	return 1;
 }
 
diff --git a/engines/glk/scott/load_game.cpp b/engines/glk/scott/load_game.cpp
index b033078bb94..acae2f229e6 100644
--- a/engines/glk/scott/load_game.cpp
+++ b/engines/glk/scott/load_game.cpp
@@ -188,6 +188,9 @@ void loadGameFile(Common::SeekableReadStream *f) {
 	case GREMLINS_SPANISH:
 		loadExtraSpanishGremlinsData();
 		break;
+	case SPIDERMAN_C64:
+		spiderman64Sysmess();
+		break;
 	case HULK_C64:
 	case HULK:
 		for (int i = 0; i < 6; i++) {
diff --git a/engines/glk/scott/scott.cpp b/engines/glk/scott/scott.cpp
index 3a760a33d86..8a86ede52c6 100644
--- a/engines/glk/scott/scott.cpp
+++ b/engines/glk/scott/scott.cpp
@@ -1114,8 +1114,7 @@ ActionResultType Scott::performLine(int ct) {
 				switch (CURRENT_GAME) {
 				case SPIDERMAN:
 				case SPIDERMAN_C64:
-					// TODO
-					// DrawBlack();
+					drawBlack();
 					break;
 				case SECRET_MISSION:
 				case SECRET_MISSION_C64:


Commit: fd0b4ef95386d9d418cbf3226e1d922b55ed4280
    https://github.com/scummvm/scummvm/commit/fd0b4ef95386d9d418cbf3226e1d922b55ed4280
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Add more variants to game detection

Changed paths:
    engines/glk/scott/c64_checksums.cpp
    engines/glk/scott/detection_tables.h
    engines/glk/scott/globals.cpp


diff --git a/engines/glk/scott/c64_checksums.cpp b/engines/glk/scott/c64_checksums.cpp
index d18adf021fc..afe721e9e4f 100644
--- a/engines/glk/scott/c64_checksums.cpp
+++ b/engines/glk/scott/c64_checksums.cpp
@@ -127,6 +127,21 @@ static C64Rec g_C64Registry[] = {
 	{ SPIDERMAN_C64, 0x2ab00, 0xde56, TYPE_D64, 0, nullptr, nullptr, 0, 0x1801, 0xa801, 0x2000 }, // Spiderman C64 (D64)
 	{ SPIDERMAN_C64, 0x08e72, 0xb2f4, TYPE_T64, 3, nullptr, nullptr, 0, 0, 0 },                   // Spiderman C64 (T64) MasterCompressor / Relax -> ECA Compacker -> Section8 Packer
 
+	{ BATON_C64,		0x5170,		0xb240, TYPE_T64, 2 }, // The Golden Baton C64, T64
+	{ BATON_C64,		0x2ab00,	0xbfbf, TYPE_D64, 2 }, // Mysterious Adventures C64 dsk 1 alt
+	{ FEASIBILITY_C64,	0x2ab00,	0x9c18, TYPE_D64, 2 }, // Mysterious Adventures C64 dsk 2 alt
+	{ TIME_MACHINE_C64, 0x5032,		0x5635, TYPE_T64, 1 }, // The Time Machine C64
+	{ ARROW1_C64,		0x5b46,		0x92db, TYPE_T64, 1 }, // Arrow of Death part 1 C64
+	{ ARROW2_C64,		0x5fe2,		0xe14f, TYPE_T64, 1 }, // Arrow of Death part 2 C64
+	{ PULSAR7_C64,		0x46bf,		0x1679, TYPE_T64, 1 }, // Escape from Pulsar 7 C64
+	{ CIRCUS_C64,		0x4269,		0xa449, TYPE_T64, 2 }, // Circus C64
+	{ FEASIBILITY_C64,	0x5a7b,		0x0f48, TYPE_T64, 1 }, // Feasibility Experiment C64
+	{ AKYRZ_C64,		0x2ab00,	0x6cca, TYPE_D64, 0 }, // The Wizard of Akyrz C64
+	{ AKYRZ_C64,		0x4be1,		0x5a00, TYPE_T64, 1 }, // The Wizard of Akyrz C64, T64
+	{ PERSEUS_C64,		0x502b,		0x913b, TYPE_T64, 1 }, // Perseus and Andromeda C64
+	{ INDIANS_C64,		0x4f9f,		0xe6c8, TYPE_T64, 1 }, // Ten Little Indians C64
+	{ WAXWORKS_C64,		0x4a11,		0xa37a, TYPE_T64, 1 }, // Waxworks C64
+
 	{ UNKNOWN_GAME, 0, 0, UNKNOWN_FILE_TYPE, 0, nullptr, nullptr, 0, 0, 0, 0 }
 };
 
@@ -383,9 +398,9 @@ int detectC64(uint8_t **sf, size_t *extent) {
 	int index = _G(_md5Index)[md5];
 	if (g_C64Registry[index]._id == SAVAGE_ISLAND_C64) {
 		return savageIslandMenu(sf, extent, index);
-	} else if (g_C64Registry[index]._id == BATON_C64) {
+	} else if (g_C64Registry[index]._id == BATON_C64 && index == 0) {
 		return mysteriousMenu(sf, extent, index);
-	} else if (g_C64Registry[index]._id == FEASIBILITY_C64) {
+	} else if (g_C64Registry[index]._id == FEASIBILITY_C64 && index == 6) {
 		return mysteriousMenu2(sf, extent, index);
 	}
 	if (g_C64Registry[index]._type == TYPE_D64) {
diff --git a/engines/glk/scott/detection_tables.h b/engines/glk/scott/detection_tables.h
index aca72c330c2..c3807ae494c 100644
--- a/engines/glk/scott/detection_tables.h
+++ b/engines/glk/scott/detection_tables.h
@@ -183,26 +183,52 @@ const GlkDetectionEntry SCOTT_GAMES[] = {
 	// C64 Games
 	DT_ENTRY1("robinofsherwood", "C64", "10109d9776b9372f9c768b53a664b113", 174848),
 	DT_ENTRY1("robinofsherwood", "C64", "552c95ec15d750cbfa02c1f11dcbca1e", 36278),
+	DT_ENTRY1("robinofsherwood", "C64", "4262f85382d1bc3b8924a1929511a558", 45807),
+	DT_ENTRY1("robinofsherwood", "C64", "bf3a4d72cff5ef97bebce6b12c756df2", 46736),
 	DT_ENTRY1("gremlins",		 "C64", "33c920f7ba150dfa1a832d510eebd8fe", 174848),
 	DT_ENTRY1("gremlins",		 "C64", "947e35037cf02269ac013857925137ce", 174848),
+	DT_ENTRY1("gremlins",		 "C64", "95b2582a89c59961d5b709c9b32e4131", 174848),
+	DT_ENTRY1("gremlins",		 "C64", "644c366956202d41df0ea1c4303c5895", 174848),
 	DT_ENTRY1("gremlins",		 "C64", "108063b2a16a199794f2ecf52ce26377", 56724),
+	DT_ENTRYL1("gremlins", Common::DE_DEU, "C64", "c60977950ff22ae57483f073345b8373", 174848),
 	DT_ENTRYL1("gremlins", Common::DE_DEU, "C64", "e5d743d8727c8aca011a737bbb5ad818", 49155),
 	DT_ENTRY1("seasofblood",	 "C64", "267c3fe2bb150365de0358f07b5df15c", 174848),
+	DT_ENTRY1("seasofblood",	 "C64", "0300c2d21289157539bbd03ab4e366ee", 174848),
 	DT_ENTRY1("seasofblood",	 "C64", "46280fb1d701a41492b8434467c31029", 41481),
 	DT_ENTRY1("marveladventure", "C64", "d80e133dd396565f773052cb317e8222", 174848),
+	DT_ENTRY1("marveladventure2","C64", "5d0ea85ca1f260ca718a6bbb6da4cdb9", 174848),
+	DT_ENTRY1("marveladventure2","C64", "3d88539a6dd7e6e179bb61041125cc0f", 36466),
 
 	//Scott Adams
 	DT_ENTRY1("adventureland",		"C64", "05cf6c64ecde5288ae2e46099bfd19a3", 27152),
 	DT_ENTRY1("adventureland",		"C64", "5af919881417920ec6a3961b4577f587", 27152),
+	DT_ENTRY1("adventureland",		"C64", "ccd3e3c805134b4fc36ad92e1cae623f", 174848),
+	DT_ENTRY1("adventureland",		"C64", "547036c586bfcd53e741ecfad74e3001", 175531),
+	DT_ENTRY1("adventureland",		"C64", "6c3de0b0ef39fad9d63e788de8cd972c", 175531),
 	DT_ENTRY1("claymorguesorcerer", "C64", "a1db488c49ad221fa0dc79591cb5a3db", 28663),
 	DT_ENTRY1("claymorguesorcerer", "C64", "1ebaf9a378355246aa7ed2623bb27fab", 49373),
 	DT_ENTRY1("claymorguesorcerer", "C64", "dde67117a432420ef05f8d665fbbbe10", 37167),
+	DT_ENTRY1("claymorguesorcerer", "C64", "8d2af429e53df1c4da0d21bdc9de6826", 48223),
 	DT_ENTRY1("claymorguesorcerer", "C64", "64fcee173adecc0f03c595e25d4def04", 174848),
 	DT_ENTRY1("savageisland",		"C64", "414d459ceb211230356ad823475866b3", 174848),
+	DT_ENTRY1("savageisland",		"C64", "f0087b1f42ea9a0656462bf339278b08", 174848),
 
 	// 11 Mysterious Adventures
-	DT_ENTRY1("mysadv1", "C64", "b4d8fc4eabed4f2400717303561ad0fa", 174848),
-	DT_ENTRY1("mysadv2", "C64", "3ce5ea1a0473244bf469fd3c51f1dc48", 174848),
+	DT_ENTRY1("mysadv1",		"C64", "b4d8fc4eabed4f2400717303561ad0fa", 174848),
+	DT_ENTRY1("mysadv2",		"C64", "3ce5ea1a0473244bf469fd3c51f1dc48", 174848),
+	DT_ENTRY1("goldenbaton",	"C64", "f2711fe0376442f6f320da1b73b5b1a3", 20848),
+	DT_ENTRY1("goldenbaton",	"C64", "ed22cb234af638e7d9f570b937f9fc52", 174848),
+	DT_ENTRY1("timemachine",	"C64", "cc8e94d3fb665d5d23b728e9c1f262ba", 20530),
+	DT_ENTRY1("arrowofdeath1",	"C64", "da044c4c57dc194002ba47f5b2921411", 23366),
+	DT_ENTRY1("arrowofdeath2",	"C64", "3d40cb011167e7ae9f6695cdd1f4a1bf", 24546),
+	DT_ENTRY1("pulsar7",		"C64", "db68753e4c4c536693edca2f58747044", 18111),
+	DT_ENTRY1("circus",			"C64", "4f732cb27e2a0bb484443a7dd1974ccf", 17001),
+	DT_ENTRY1("feasibility",	"C64", "6c7ed2fd5f0247a55beb266344967662", 23163),
+	DT_ENTRY1("akyrz",			"C64", "94e4b070e45204b12d1655091c56045d", 19425),
+	DT_ENTRY1("akyrz",			"C64", "c423ad31ab3f6b45f0215c2e7fc3eb7e", 174848),
+	DT_ENTRY1("perseus",		"C64", "96a1ccb3212808eee03e74cdc1f0d1a4", 20523),
+	DT_ENTRY1("10indians",		"C64", "79ee3669ccfff7338dfc1810228005dc", 20383),
+	DT_ENTRY1("waxworks11",		"C64", "facc11aa8b51e88a807236b765203eb0", 18961),
 	DT_END_MARKER
 };
 
diff --git a/engines/glk/scott/globals.cpp b/engines/glk/scott/globals.cpp
index 49e094c84a3..d336604bb2e 100644
--- a/engines/glk/scott/globals.cpp
+++ b/engines/glk/scott/globals.cpp
@@ -110,21 +110,47 @@ Globals::Globals() : _sys(MAX_SYSMESS), _directions(NUMBER_OF_DIRECTIONS), _extr
 	_md5Index.setVal("b4d8fc4eabed4f2400717303561ad0fa",  0); // misadv1
 	_md5Index.setVal("3ce5ea1a0473244bf469fd3c51f1dc48",  6); // midadv2
 	_md5Index.setVal("10109d9776b9372f9c768b53a664b113", 12); // robin of sherwood
+	_md5Index.setVal("4262f85382d1bc3b8924a1929511a558", 13); // robin of sherwood
+	_md5Index.setVal("bf3a4d72cff5ef97bebce6b12c756df2", 14); // robin of sherwood
 	_md5Index.setVal("552c95ec15d750cbfa02c1f11dcbca1e", 15); // robin of sherwood
 	_md5Index.setVal("108063b2a16a199794f2ecf52ce26377", 16); // gremlins
 	_md5Index.setVal("947e35037cf02269ac013857925137ce", 17); // gremlins
+	_md5Index.setVal("95b2582a89c59961d5b709c9b32e4131", 18); // gremlins
 	_md5Index.setVal("33c920f7ba150dfa1a832d510eebd8fe", 19); // gremlins
+	_md5Index.setVal("644c366956202d41df0ea1c4303c5895", 20); // gremlins
 	_md5Index.setVal("e5d743d8727c8aca011a737bbb5ad818", 21); // gremlins
-	_md5Index.setVal("267c3fe2bb150365de0358f07b5df15c", 24); // seas of blood
+	_md5Index.setVal("c60977950ff22ae57483f073345b8373", 22); // gremlins
 	_md5Index.setVal("46280fb1d701a41492b8434467c31029", 23); // seas of blood
+	_md5Index.setVal("267c3fe2bb150365de0358f07b5df15c", 24); // seas of blood
+	_md5Index.setVal("0300c2d21289157539bbd03ab4e366ee", 25); // seas of blood
 	_md5Index.setVal("a1db488c49ad221fa0dc79591cb5a3db", 26); // sorcerer of claymorgue castle
-	_md5Index.setVal("1ebaf9a378355246aa7ed2623bb27fab", 28); // sorcerer of claymorgue castle
 	_md5Index.setVal("dde67117a432420ef05f8d665fbbbe10", 27); // sorcerer of claymorgue castle
+	_md5Index.setVal("1ebaf9a378355246aa7ed2623bb27fab", 28); // sorcerer of claymorgue castle
+	_md5Index.setVal("8d2af429e53df1c4da0d21bdc9de6826", 29); // sorcerer of claymorgue castle
 	_md5Index.setVal("64fcee173adecc0f03c595e25d4def04", 30); // sorcerer of claymorgue castle
 	_md5Index.setVal("05cf6c64ecde5288ae2e46099bfd19a3", 31); // adventureland
 	_md5Index.setVal("5af919881417920ec6a3961b4577f587", 32); // adventureland
+	_md5Index.setVal("ccd3e3c805134b4fc36ad92e1cae623f", 33); // adventureland
+	_md5Index.setVal("6c3de0b0ef39fad9d63e788de8cd972c", 34); // adventureland
+	_md5Index.setVal("547036c586bfcd53e741ecfad74e3001", 35); // adventureland
+	_md5Index.setVal("f0087b1f42ea9a0656462bf339278b08", 36); // savage island
 	_md5Index.setVal("414d459ceb211230356ad823475866b3", 38); // savage island
 	_md5Index.setVal("d80e133dd396565f773052cb317e8222", 40); // questprobe hulk
+	_md5Index.setVal("5d0ea85ca1f260ca718a6bbb6da4cdb9", 41); // questprobe spiderman
+	_md5Index.setVal("3d88539a6dd7e6e179bb61041125cc0f", 42); // questprobe spiderman
+	_md5Index.setVal("f2711fe0376442f6f320da1b73b5b1a3", 43); // golden baton
+	_md5Index.setVal("ed22cb234af638e7d9f570b937f9fc52", 11); // golden baton
+	_md5Index.setVal("cc8e94d3fb665d5d23b728e9c1f262ba", 46); // time machine
+	_md5Index.setVal("da044c4c57dc194002ba47f5b2921411", 47); // arrow of death 1
+	_md5Index.setVal("3d40cb011167e7ae9f6695cdd1f4a1bf", 48); // arrow of death 2
+	_md5Index.setVal("db68753e4c4c536693edca2f58747044", 49); // pulsar 7
+	_md5Index.setVal("4f732cb27e2a0bb484443a7dd1974ccf", 50); // circus
+	_md5Index.setVal("6c7ed2fd5f0247a55beb266344967662", 51); // feasibility
+	_md5Index.setVal("94e4b070e45204b12d1655091c56045d", 53); // akyrz
+	_md5Index.setVal("c423ad31ab3f6b45f0215c2e7fc3eb7e", 52); // akyrz
+	_md5Index.setVal("96a1ccb3212808eee03e74cdc1f0d1a4", 54); // perseus
+	_md5Index.setVal("79ee3669ccfff7338dfc1810228005dc", 55); // 10 indians
+	_md5Index.setVal("facc11aa8b51e88a807236b765203eb0", 56); // waxworks11
 }
 
 Globals::~Globals() {


Commit: 0d4e18e5c75987a3b30ac65dc212a77934ad7b16
    https://github.com/scummvm/scummvm/commit/0d4e18e5c75987a3b30ac65dc212a77934ad7b16
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Reorganise switch case

Changed paths:
    engines/glk/scott/load_game.cpp


diff --git a/engines/glk/scott/load_game.cpp b/engines/glk/scott/load_game.cpp
index acae2f229e6..c69233462d0 100644
--- a/engines/glk/scott/load_game.cpp
+++ b/engines/glk/scott/load_game.cpp
@@ -143,6 +143,12 @@ void loadGameFile(Common::SeekableReadStream *f) {
 	case SEAS_OF_BLOOD_C64:
 		loadExtraSeasOfBlood64Data();
 		break;
+	case CLAYMORGUE:
+		for (int i = OK; i <= RESUME_A_SAVED_GAME; i++)
+			_G(_sys)[i] = _G(_systemMessages)[6 - OK + i];
+		for (int i = PLAY_AGAIN; i <= ON_A_SCALE_THAT_RATES; i++)
+			_G(_sys)[i] = _G(_systemMessages)[2 - PLAY_AGAIN + i];
+		break;
 	case ADVENTURELAND:
 		for (int i = PLAY_AGAIN; i <= ON_A_SCALE_THAT_RATES; i++)
 			_G(_sys)[i] = _G(_systemMessages)[2 - PLAY_AGAIN + i];
@@ -157,6 +163,12 @@ void loadGameFile(Common::SeekableReadStream *f) {
 	case CLAYMORGUE_C64:
 		claymorgue64Sysmess();
 		break;
+	case GREMLINS_GERMAN_C64:
+		loadExtraGermanGremlinsc64Data();
+		break;
+	case SPIDERMAN_C64:
+		spiderman64Sysmess();
+		break;
 	case SAVAGE_ISLAND_C64:
 		_G(_items)[20]._image = 13;
 	case SAVAGE_ISLAND2_C64:
@@ -168,9 +180,6 @@ void loadGameFile(Common::SeekableReadStream *f) {
 		_G(_items)[20]._image = 13;
 	case SAVAGE_ISLAND2:
 		MY_LOC = 30; /* Both parts of Savage Island begin in room 30 */
-	case GREMLINS_GERMAN_C64:
-		loadExtraGermanGremlinsc64Data();
-		break;
 	case GREMLINS_GERMAN:
 	case GREMLINS:
 	case SUPERGRAN:
@@ -188,9 +197,6 @@ void loadGameFile(Common::SeekableReadStream *f) {
 	case GREMLINS_SPANISH:
 		loadExtraSpanishGremlinsData();
 		break;
-	case SPIDERMAN_C64:
-		spiderman64Sysmess();
-		break;
 	case HULK_C64:
 	case HULK:
 		for (int i = 0; i < 6; i++) {


Commit: fdfd91fd7fbda9494bca086119c1bf7c8529ae6d
    https://github.com/scummvm/scummvm/commit/fdfd91fd7fbda9494bca086119c1bf7c8529ae6d
Author: Avijeet (am388488 at gmail.com)
Date: 2022-06-23T20:11:01+02:00

Commit Message:
GLK: SCOTT: Add support for Super Gran

Changed paths:
    engines/glk/scott/c64_checksums.cpp
    engines/glk/scott/detection_tables.h
    engines/glk/scott/game_specific.cpp
    engines/glk/scott/game_specific.h
    engines/glk/scott/games.h
    engines/glk/scott/globals.cpp
    engines/glk/scott/load_game.cpp


diff --git a/engines/glk/scott/c64_checksums.cpp b/engines/glk/scott/c64_checksums.cpp
index afe721e9e4f..bdd00129512 100644
--- a/engines/glk/scott/c64_checksums.cpp
+++ b/engines/glk/scott/c64_checksums.cpp
@@ -142,6 +142,8 @@ static C64Rec g_C64Registry[] = {
 	{ INDIANS_C64,		0x4f9f,		0xe6c8, TYPE_T64, 1 }, // Ten Little Indians C64
 	{ WAXWORKS_C64,		0x4a11,		0xa37a, TYPE_T64, 1 }, // Waxworks C64
 
+	{ SUPERGRAN_C64, 0x726f, 0x0901, TYPE_T64, 1, nullptr, nullptr, 0, 0xd802, 0xc623, 0x1f00 }, // Super Gran C64 (T64) PUCrunch Generic Hack
+
 	{ UNKNOWN_GAME, 0, 0, UNKNOWN_FILE_TYPE, 0, nullptr, nullptr, 0, 0, 0, 0 }
 };
 
diff --git a/engines/glk/scott/detection_tables.h b/engines/glk/scott/detection_tables.h
index c3807ae494c..abf2740c806 100644
--- a/engines/glk/scott/detection_tables.h
+++ b/engines/glk/scott/detection_tables.h
@@ -87,6 +87,7 @@ const PlainGameDescriptor SCOTT_GAME_LIST[] = {
 	{ "topsecretadv",      "Top Secret Adventure" },
 	{ "gremlins",		   "Gremlins" },
 	{ "seasofblood",	   "Seas Of Blood" },
+	{ "supergran",		   "Super Gran" },
 
 	{ nullptr, nullptr }
 };
@@ -198,6 +199,8 @@ const GlkDetectionEntry SCOTT_GAMES[] = {
 	DT_ENTRY1("marveladventure", "C64", "d80e133dd396565f773052cb317e8222", 174848),
 	DT_ENTRY1("marveladventure2","C64", "5d0ea85ca1f260ca718a6bbb6da4cdb9", 174848),
 	DT_ENTRY1("marveladventure2","C64", "3d88539a6dd7e6e179bb61041125cc0f", 36466),
+	DT_ENTRY1("supergran",		 "C64", "36a5b1b2afb38902933856b3446d760e", 29295),
+
 
 	//Scott Adams
 	DT_ENTRY1("adventureland",		"C64", "05cf6c64ecde5288ae2e46099bfd19a3", 27152),
diff --git a/engines/glk/scott/game_specific.cpp b/engines/glk/scott/game_specific.cpp
index 283a9458ac4..7ffaf6ccc73 100644
--- a/engines/glk/scott/game_specific.cpp
+++ b/engines/glk/scott/game_specific.cpp
@@ -321,5 +321,46 @@ void spiderman64Sysmess() {
 	_G(_sys)[SOMETHING] = "\" something. ";
 }
 
+void supergran64Sysmess(void) {
+	SysMessageType messagekey[] = {
+		NORTH,
+		SOUTH,
+		EAST,
+		WEST,
+		UP,
+		DOWN,
+		EXITS,
+		YOU_SEE,
+		YOU_ARE,
+		I_DONT_KNOW_WHAT_A,
+		IS,
+		YOU_CANT_GO_THAT_WAY,
+		OK,
+		WHAT_NOW,
+		HUH,
+		YOU_HAVE_IT,
+		TAKEN,
+		DROPPED,
+		YOU_HAVENT_GOT_IT,
+		INVENTORY,
+		YOU_DONT_SEE_IT,
+		THATS_BEYOND_MY_POWER,
+		DIRECTION,
+		YOURE_CARRYING_TOO_MUCH,
+		IM_DEAD,
+		PLAY_AGAIN,
+		RESUME_A_SAVED_GAME,
+		YOU_CANT_DO_THAT_YET,
+		I_DONT_UNDERSTAND,
+		NOTHING};
+
+	for (int i = 0; i < 30; i++) {
+		_G(_sys)[messagekey[i]] = _G(_systemMessages)[i];
+	}
+
+	_G(_sys)[I_DONT_KNOW_WHAT_A] = "\"";
+	_G(_sys)[IS] = "\" is a word I don't know. ";
+}
+
 } // End of namespace Scott
 } // End of namespace Glk
diff --git a/engines/glk/scott/game_specific.h b/engines/glk/scott/game_specific.h
index 75e0af0c67d..269537f9d82 100644
--- a/engines/glk/scott/game_specific.h
+++ b/engines/glk/scott/game_specific.h
@@ -42,6 +42,7 @@ void adventurelandAction(int p);
 void adventurelandDarkness();
 void adventureland64Sysmess();
 void spiderman64Sysmess();
+void supergran64Sysmess(void);
 
 } // End of namespace Scott
 } // End of namespace Glk
diff --git a/engines/glk/scott/games.h b/engines/glk/scott/games.h
index d28ec4b060c..2ad4d51d9b2 100644
--- a/engines/glk/scott/games.h
+++ b/engines/glk/scott/games.h
@@ -1908,5 +1908,87 @@ const GameInfo _games[NUMGAMES] = {
 			 43,     // number_of_pictures;
 			 C64B,   // palette
 			 0,      // picture_format_version;
+			 0),
+	GameInfo("Supergran",
+			 SUPERGRAN,
+			 NO_TYPE,                  // type
+			 ENGLISH,                  // subtype
+			 FOUR_LETTER_UNCOMPRESSED, // dictionary type
+
+			 85,  // Number of items
+			 204, // Number of actions
+			 105, // Number of words
+			 39,  // Number of rooms
+			 6,   // Max carried items
+			 4,   // Word length
+			 99,  // Number of messages
+
+			 101, // number_of_verbs
+			 106, // number_of_nouns;
+
+			 0x236d,  // header
+			 LATE,    // header style
+			 0x38c8,  // room images
+			 FOLLOWS, // item flags
+			 FOLLOWS, // item images
+			 0x399e,  // actions
+			 COMPRESSED,
+			 0x42fd,  // dictionary
+			 0x4708,  // start_of_room_descriptions;
+			 FOLLOWS, // start_of_room_connections;
+			 FOLLOWS, // start_of_messages;
+			 FOLLOWS, // start_of_item_descriptions;
+			 FOLLOWS, // start_of_item_locations;
+
+			 0x2423, // start_of_system_messages
+			 0x25f3, // start of directions
+
+			 0x5a4e,  // start_of_characters;
+			 FOLLOWS, // start_of_image_data
+			 0x634e,  // image_address_offset
+			 47,      // number_of_pictures;
+			 ZXOPT,   // palette
+			 3,       // picture_format_version;
+			 0),
+	GameInfo("Supergran C64",
+			 SUPERGRAN_C64,
+			 NO_TYPE,                             // type
+			 static_cast<Subtype>(ENGLISH | C64), // subtype
+			 FOUR_LETTER_UNCOMPRESSED,            // dictionary type
+
+			 85,  // Number of items
+			 204, // Number of actions
+			 105, // Number of words
+			 39,  // Number of rooms
+			 6,   // Max carried items
+			 4,   // Word length
+			 99,  // Number of messages
+
+			 101, // number_of_verbs
+			 105, // number_of_nouns;
+
+			 0x4624,               // header
+			 SUPERGRAN_C64_HEADER, // header style
+			 0x4636,               // room images
+			 FOLLOWS,              // item flags
+			 FOLLOWS,              // item images
+			 0x47b5,               // actions
+			 COMPRESSED,
+			 0x5119,  // dictionary
+			 0x5524,  // start_of_room_descriptions;
+			 FOLLOWS, // start_of_room_connections;
+			 FOLLOWS, // start_of_messages;
+			 FOLLOWS, // start_of_item_descriptions;
+			 0x470a,  // start_of_item_locations;
+
+			 0x0a53, // start_of_system_messages
+			 0x0a53, // start of directions
+
+			 0x6a02,  // start_of_characters;
+			 FOLLOWS, // start_of_image_data
+			 0x7302,  // image_address_offset
+			 49,      // number_of_pictures;
+			 C64B,    // palette
+			 3,       // picture_format_version;
 			 0)
 };
diff --git a/engines/glk/scott/globals.cpp b/engines/glk/scott/globals.cpp
index d336604bb2e..f2d446aa289 100644
--- a/engines/glk/scott/globals.cpp
+++ b/engines/glk/scott/globals.cpp
@@ -151,6 +151,7 @@ Globals::Globals() : _sys(MAX_SYSMESS), _directions(NUMBER_OF_DIRECTIONS), _extr
 	_md5Index.setVal("96a1ccb3212808eee03e74cdc1f0d1a4", 54); // perseus
 	_md5Index.setVal("79ee3669ccfff7338dfc1810228005dc", 55); // 10 indians
 	_md5Index.setVal("facc11aa8b51e88a807236b765203eb0", 56); // waxworks11
+	_md5Index.setVal("36a5b1b2afb38902933856b3446d760e", 57); // super gran
 }
 
 Globals::~Globals() {
diff --git a/engines/glk/scott/load_game.cpp b/engines/glk/scott/load_game.cpp
index c69233462d0..f7900bbe19d 100644
--- a/engines/glk/scott/load_game.cpp
+++ b/engines/glk/scott/load_game.cpp
@@ -169,6 +169,9 @@ void loadGameFile(Common::SeekableReadStream *f) {
 	case SPIDERMAN_C64:
 		spiderman64Sysmess();
 		break;
+	case SUPERGRAN_C64:
+		supergran64Sysmess();
+		break;
 	case SAVAGE_ISLAND_C64:
 		_G(_items)[20]._image = 13;
 	case SAVAGE_ISLAND2_C64:




More information about the Scummvm-git-logs mailing list