aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Gilbert2019-10-25 20:11:51 -0700
committerPaul Gilbert2019-10-26 11:13:29 -0700
commit0facfc2b2497cc61e86582f72dbab1dad1b1b83b (patch)
tree89cb954251c7b8a6eb0fd954107255e62ba2573c
parent4332df2bda8d8f3942d81db3051f780d2f1bf02a (diff)
downloadscummvm-rg350-0facfc2b2497cc61e86582f72dbab1dad1b1b83b.tar.gz
scummvm-rg350-0facfc2b2497cc61e86582f72dbab1dad1b1b83b.tar.bz2
scummvm-rg350-0facfc2b2497cc61e86582f72dbab1dad1b1b83b.zip
GLK: LEVEL9: Moved pre-existing detection code into separate class
-rw-r--r--engines/glk/level9/detection.cpp183
-rw-r--r--engines/glk/level9/detection.h80
-rw-r--r--engines/glk/level9/detection_tables.h773
-rw-r--r--engines/glk/level9/level9.cpp3
-rw-r--r--engines/glk/level9/level9.h3
-rw-r--r--engines/glk/level9/level9_main.cpp4
-rw-r--r--engines/glk/level9/level9_main.h3
-rw-r--r--engines/glk/level9/os_glk.cpp1033
-rw-r--r--engines/glk/level9/os_glk.h3
9 files changed, 1046 insertions, 1039 deletions
diff --git a/engines/glk/level9/detection.cpp b/engines/glk/level9/detection.cpp
index 9904091d97..2648db85d6 100644
--- a/engines/glk/level9/detection.cpp
+++ b/engines/glk/level9/detection.cpp
@@ -22,6 +22,7 @@
#include "glk/level9/detection.h"
#include "glk/level9/detection_tables.h"
+#include "glk/level9/os_glk.h"
#include "glk/blorb.h"
#include "common/debug.h"
#include "common/file.h"
@@ -31,6 +32,176 @@
namespace Glk {
namespace Level9 {
+GameDetection::GameDetection(byte *&startData, size_t &fileSize) :
+ _startData(startData), _fileSize(fileSize), _crcInitialized(false), _gameName(nullptr) {
+ Common::fill(&_crcTable[0], &_crcTable[256], 0);
+}
+
+gln_game_tableref_t GameDetection::gln_gameid_identify_game() {
+ uint16 length, crc;
+ byte checksum;
+ int is_version2;
+ gln_game_tableref_t game;
+ gln_patch_tableref_t patch;
+
+ /* If the data file appears too short for a header, give up now. */
+ if (_fileSize < 30)
+ return nullptr;
+
+ /*
+ * Find the version of the game, and the length of game data. This logic
+ * is taken from L9cut, with calcword() replaced by simple byte comparisons.
+ * If the length exceeds the available data, fail.
+ */
+ assert(_startData);
+ is_version2 = _startData[4] == 0x20 && _startData[5] == 0x00
+ && _startData[10] == 0x00 && _startData[11] == 0x80
+ && _startData[20] == _startData[22]
+ && _startData[21] == _startData[23];
+
+ length = is_version2
+ ? _startData[28] | _startData[29] << BITS_PER_CHAR
+ : _startData[0] | _startData[1] << BITS_PER_CHAR;
+ if (length >= _fileSize)
+ return nullptr;
+
+ /* Calculate or retrieve the checksum, in a version specific way. */
+ if (is_version2) {
+ int index;
+
+ checksum = 0;
+ for (index = 0; index < length + 1; index++)
+ checksum += _startData[index];
+ }
+ else
+ checksum = _startData[length];
+
+ /*
+ * Generate a CRC for this data. When L9cut calculates a CRC, it's using a
+ * copy taken up to length + 1 and then padded with two NUL bytes, so we
+ * mimic that here.
+ */
+ crc = gln_get_buffer_crc(_startData, length + 1, 2);
+
+ /*
+ * See if this is a patched file. If it is, look up the game based on the
+ * original CRC and checksum. If not, use the current CRC and checksum.
+ */
+ patch = gln_gameid_lookup_patch(length, checksum, crc);
+ game = gln_gameid_lookup_game(length,
+ patch ? patch->orig_checksum : checksum,
+ patch ? patch->orig_crc : crc,
+ false);
+
+ /* If no game identified, retry without the CRC. This is guesswork. */
+ if (!game)
+ game = gln_gameid_lookup_game(length, checksum, crc, true);
+
+ return game;
+}
+
+// CRC table initialization polynomial
+static const uint16 GLN_CRC_POLYNOMIAL = 0xa001;
+
+uint16 GameDetection::gln_get_buffer_crc(const void *void_buffer, size_t length, size_t padding) {
+
+ const char *buffer = (const char *)void_buffer;
+ uint16 crc;
+ size_t index;
+
+ /* Build the static CRC lookup table on first call. */
+ if (!_crcInitialized) {
+ for (index = 0; index < BYTE_MAX + 1; index++) {
+ int bit;
+
+ crc = (uint16)index;
+ for (bit = 0; bit < BITS_PER_CHAR; bit++)
+ crc = crc & 1 ? GLN_CRC_POLYNOMIAL ^ (crc >> 1) : crc >> 1;
+
+ _crcTable[index] = crc;
+ }
+
+ _crcInitialized = true;
+
+ /* CRC lookup table self-test, after is_initialized set -- recursion. */
+ assert(gln_get_buffer_crc("123456789", 9, 0) == 0xbb3d);
+ }
+
+ /* Start with zero in the crc, then update using table entries. */
+ crc = 0;
+ for (index = 0; index < length; index++)
+ crc = _crcTable[(crc ^ buffer[index]) & BYTE_MAX] ^ (crc >> BITS_PER_CHAR);
+
+ /* Add in any requested NUL padding bytes. */
+ for (index = 0; index < padding; index++)
+ crc = _crcTable[crc & BYTE_MAX] ^ (crc >> BITS_PER_CHAR);
+
+ return crc;
+}
+
+gln_game_tableref_t GameDetection::gln_gameid_lookup_game(uint16 length, byte checksum, uint16 crc, int ignore_crc) const {
+ gln_game_tableref_t game;
+
+ for (game = GLN_GAME_TABLE; game->length; game++) {
+ if (game->length == length && game->checksum == checksum
+ && (ignore_crc || game->crc == crc))
+ break;
+ }
+
+ return game->length ? game : nullptr;
+}
+
+gln_patch_tableref_t GameDetection::gln_gameid_lookup_patch(uint16 length, byte checksum, uint16 crc) const {
+ gln_patch_tableref_t patch;
+
+ for (patch = GLN_PATCH_TABLE; patch->length; patch++) {
+ if (patch->length == length && patch->patch_checksum == checksum
+ && patch->patch_crc == crc)
+ break;
+ }
+
+ return patch->length ? patch : nullptr;
+}
+
+const char *GameDetection::gln_gameid_get_game_name() {
+ /*
+ * If no game name yet known, attempt to identify the game. If it can't
+ * be identified, set the cached game name to "" -- this special value
+ * indicates that the game is an unknown one, but suppresses repeated
+ * attempts to identify it on successive calls.
+ */
+ if (!_gameName) {
+ gln_game_tableref_t game;
+
+ /*
+ * If the interpreter hasn't yet loaded a game, startdata is nullptr
+ * (uninitialized, global). In this case, we return nullptr, allowing
+ * for retries until a game is loaded.
+ */
+ if (!_startData)
+ return nullptr;
+
+ game = gln_gameid_identify_game();
+ _gameName = game ? game->name : "";
+ }
+
+ /* Return the game's name, or nullptr if it was unidentifiable. */
+ assert(_gameName);
+ return strlen(_gameName) > 0 ? _gameName : nullptr;
+}
+
+/**
+ * Clear the saved game name, forcing a new lookup when next queried. This
+ * function should be called by actions that may cause the interpreter to
+ * change game file, for example os_set_filenumber().
+ */
+void GameDetection::gln_gameid_game_name_reset() {
+ _gameName = nullptr;
+}
+
+
+/*----------------------------------------------------------------------*/
+
void Level9MetaEngine::getSupportedGames(PlainGameList &games) {
for (const PlainGameDescriptor *pd = LEVEL9_GAME_LIST; pd->gameId; ++pd) {
games.push_back(*pd);
@@ -62,7 +233,7 @@ bool Level9MetaEngine::detectGames(const Common::FSList &fslist, DetectedGames &
continue;
Common::String md5 = Common::computeStreamMD5AsString(gameFile, 5000);
- size_t filesize = gameFile.size();
+ size_t _fileSize = gameFile.size();
gameFile.seek(0);
bool isBlorb = Blorb::isBlorb(gameFile, ID_ADRI);
gameFile.close();
@@ -72,12 +243,12 @@ bool Level9MetaEngine::detectGames(const Common::FSList &fslist, DetectedGames &
// Check for known games
const GlkDetectionEntry *p = LEVEL9_GAMES;
- while (p->_gameId && (md5 != p->_md5 || filesize != p->_filesize))
+ while (p->_gameId && (md5 != p->_md5 || _fileSize != p->_filesize))
++p;
if (!p->_gameId) {
const PlainGameDescriptor &desc = LEVEL9_GAME_LIST[0];
- gameList.push_back(GlkDetectedGame(desc.gameId, desc.description, filename, md5, filesize));
+ gameList.push_back(GlkDetectedGame(desc.gameId, desc.description, filename, md5, _fileSize));
} else {
PlainGameDescriptor gameDesc = findGame(p->_gameId);
gameList.push_back(GlkDetectedGame(p->_gameId, gameDesc.description, p->_extra, filename, p->_language));
@@ -88,11 +259,7 @@ bool Level9MetaEngine::detectGames(const Common::FSList &fslist, DetectedGames &
}
void Level9MetaEngine::detectClashes(Common::StringMap &map) {
- for (const PlainGameDescriptor *pd = LEVEL9_GAME_LIST; pd->gameId; ++pd) {
- if (map.contains(pd->gameId))
- error("Duplicate game Id found - %s", pd->gameId);
- map[pd->gameId] = "";
- }
+ // No implementation
}
} // End of namespace Level9
diff --git a/engines/glk/level9/detection.h b/engines/glk/level9/detection.h
index 386e4755e9..9e8401bb44 100644
--- a/engines/glk/level9/detection.h
+++ b/engines/glk/level9/detection.h
@@ -31,6 +31,86 @@
namespace Glk {
namespace Level9 {
+struct gln_game_table_t {
+ const size_t length; ///< Datafile length in bytes
+ const byte checksum; ///< 8-bit checksum, last datafile byte
+ const uint16 crc; ///< 16-bit CRC, L9cut-internal
+ const char *const name; ///< Game title and platform
+};
+typedef const gln_game_table_t *gln_game_tableref_t;
+
+struct gln_patch_table_t {
+ const size_t length; ///< Datafile length in bytes
+ const byte orig_checksum; ///< 8-bit checksum, last datafile byte
+ const uint16 orig_crc; ///< 16-bit CRC, L9cut-internal
+ const byte patch_checksum; ///< 8-bit checksum, last datafile byte
+ const uint16 patch_crc; ///< 16-bit CRC, L9cut-internal
+};
+typedef const gln_patch_table_t *gln_patch_tableref_t;
+
+/**
+ * Detection manager for specific games
+ */
+class GameDetection {
+private:
+ byte *&_startData;
+ size_t &_fileSize;
+ bool _crcInitialized;
+ uint16 _crcTable[256];
+public:
+ const char *_gameName;
+public:
+ /**
+ * Constructor
+ */
+ GameDetection(byte *&startData, size_t &fileSize);
+
+ /**
+ * Identify a game from its data length, checksum, and CRC. Returns the
+ * entry of the game in the game table, or nullptr if not found.
+ *
+ * This function uses startdata and FileSize from the core interpreter.
+ * These aren't advertised symbols, so be warned.
+ */
+ gln_game_tableref_t gln_gameid_identify_game();
+
+ /**
+ * Return the CRC of the bytes buffer[0..length-1].
+ *
+ * This algorithm is selected to match the CRCs used in L9cut. Because of
+ * the odd way CRCs are padded when L9cut calculates the CRC, this function
+ * allows a count of NUL padding bytes to be included within the return CRC.
+ */
+ uint16 gln_get_buffer_crc(const void *void_buffer, size_t length, size_t padding = 0);
+
+ /*
+ * Look up and return game table and patch table entries given a game's
+ * length, checksum, and CRC. Returns the entry, or nullptr if not found.
+ */
+ gln_game_tableref_t gln_gameid_lookup_game(uint16 length, byte checksum, uint16 crc, int ignore_crc) const;
+
+ /**
+ * Look up and return patch table entries given a game's length, checksum, and CRC.
+ * Returns the entry, or nullptr if not found
+ */
+ gln_patch_tableref_t gln_gameid_lookup_patch(uint16 length, byte checksum, uint16 crc) const;
+
+ /**
+ * Return the name of the game, or nullptr if not identifiable.
+ *
+ * This function uses startdata from the core interpreter. This isn't an
+ * advertised symbol, so be warned.
+ */
+ const char *gln_gameid_get_game_name();
+
+ /**
+ * Clear the saved game name, forcing a new lookup when next queried. This
+ * function should be called by actions that may cause the interpreter to
+ * change game file, for example os_set_filenumber().
+ */
+ void gln_gameid_game_name_reset();
+};
+
/**
* Meta engine for Level 9 interpreter
*/
diff --git a/engines/glk/level9/detection_tables.h b/engines/glk/level9/detection_tables.h
index 12b3b0e136..dda4ce43ba 100644
--- a/engines/glk/level9/detection_tables.h
+++ b/engines/glk/level9/detection_tables.h
@@ -21,12 +21,781 @@
*/
#include "engines/game.h"
-#include "common/gui_options.h"
-#include "common/language.h"
+
+/**
+ * Unlike other ScummVM GLK subengines, Level9 has a detection table that was already
+ * included in the Level9 interpreter. So it's used instead of a standard MD5-based list
+ */
namespace Glk {
namespace Level9 {
+/**
+ * The following game database is obtained from L9cut's l9data_d.h, and
+ * lets us find a game's name from its data CRC. Entries marked "WANTED" in
+ * l9data_d.h, and file commentary, have been removed for brevity, and the
+ * file has been reformatted (patchlevel data removed).
+ *
+ * The version of l9data_d.h used is 050 (22 Oct 2002).
+ */
+static const gln_game_table_t GLN_GAME_TABLE[] = {
+ {0x5323, 0xb7, 0x8af7, "Adventure Quest (Amstrad CPC/Spectrum)"},
+
+ {0x630e, 0x8d, 0x7d7d, "Dungeon Adventure (Amstrad CPC)"},
+ {0x630e, 0xbe, 0x3374, "Dungeon Adventure (MSX)"},
+
+ {0x5eb9, 0x30, 0xe99a, "Lords of Time (Amstrad CPC)"},
+ {0x5eb9, 0x5d, 0xc098, "Lords of Time (MSX)"},
+ {0x5eb9, 0x6e, 0xc689, "Lords of Time (Spectrum)"},
+
+ {0x5fab, 0x5c, 0xa309, "Snowball (Amstrad CPC)"},
+ {0x5fab, 0x2f, 0x8aa2, "Snowball (MSX)"},
+
+ {0x60c4, 0x28, 0x0154, "Return to Eden (Amstrad CPC/Commodore 64[v1])"},
+ {0x6064, 0x01, 0x5b3c, "Return to Eden (BBC[v1])"},
+ {0x6064, 0x95, 0x510c, "Return to Eden (Commodore 64[v2])"},
+ {0x6064, 0xda, 0xe610, "Return to Eden (Commodore 64[v2] *corrupt*)"},
+ {0x6064, 0xbd, 0x73ec, "Return to Eden (Atari *corrupt*)"},
+ {0x6047, 0x6c, 0x17ab, "Return to Eden (BBC[v2])"},
+ {0x5ca1, 0x33, 0x1c43, "Return to Eden (Spectrum[v1])"},
+ {0x5cb7, 0x64, 0x0790, "Return to Eden (Spectrum[v2])"},
+ {0x5cb7, 0xfe, 0x3533, "Return to Eden (MSX)"},
+
+ {0x34b3, 0x20, 0xccda, "Erik the Viking (BBC/Commodore 64)"},
+ {0x34b3, 0x53, 0x8f00, "Erik the Viking (Spectrum)"},
+ {0x34b3, 0xc7, 0x9058, "Erik the Viking (Amstrad CPC)"},
+
+ {0x63be, 0xd6, 0xcf5d, "Emerald Isle (Atari/Commodore 64/Amstrad CPC/Spectrum)"},
+ {0x63be, 0x0a, 0x21ed, "Emerald Isle (MSX *corrupt*)"},
+ {0x378c, 0x8d, 0x3a21, "Emerald Isle (BBC)"},
+
+ {0x506c, 0xf0, 0xba72, "Red Moon (BBC/Commodore 64/Amstrad CPC/MSX)"},
+ {0x505d, 0x32, 0x2dcf, "Red Moon (Spectrum)"},
+
+ {0x772b, 0xcd, 0xa503, "Worm in Paradise (Spectrum 128)"},
+ {0x546c, 0xb7, 0x9420, "Worm in Paradise (Spectrum 48)"},
+ {0x6d84, 0xf9, 0x49ae, "Worm in Paradise (Commodore 64 *corrupt*)"},
+ {0x6d84, 0xc8, 0x943f, "Worm in Paradise (Commodore 64 *fixed*)"},
+ {0x6030, 0x47, 0x46ad, "Worm in Paradise (Amstrad CPC)"},
+ {0x5828, 0xbd, 0xe7cb, "Worm in Paradise (BBC)"},
+
+ {0x7410, 0x5e, 0x60be, "Price of Magik (Spectrum 128)"},
+ {0x5aa4, 0xc1, 0x10a0, "Price of Magik (Spectrum 48[v1])"},
+ {0x5aa4, 0xc1, 0xeda4, "Price of Magik (Spectrum 48[v2])"},
+ {0x6fc6, 0x14, 0xf9b6, "Price of Magik (Commodore 64)"},
+ {0x5aa4, 0xc1, 0xbbf4, "Price of Magik (Amstrad CPC)"},
+ {0x5671, 0xbc, 0xff35, "Price of Magik (BBC)"},
+
+ {0x76f4, 0x5e, 0x1fe5, "Colossal Adventure /JoD (Amiga/PC)"},
+ {0x76f4, 0x5a, 0xcf4b, "Colossal Adventure /JoD (ST)"},
+ {0x6e60, 0x83, 0x18e0, "Adventure Quest /JoD (Amiga/PC)"},
+ {0x6e5c, 0xf6, 0xd356, "Adventure Quest /JoD (ST)"},
+ {0x6f0c, 0x95, 0x1f64, "Dungeon Adventure /JoD (Amiga/PC/ST)"},
+
+ {0x6f70, 0x40, 0xbd91, "Colossal Adventure /JoD (MSX)"},
+
+ {0x6f6e, 0x78, 0x28cd, "Colossal Adventure /JoD (Spectrum 128)"},
+ {0x6970, 0xd6, 0xa820, "Adventure Quest /JoD (Spectrum 128)"},
+ {0x6de8, 0x4c, 0xd795, "Dungeon Adventure /JoD (Spectrum 128)"},
+
+ {0x6f4d, 0xcb, 0xe8f2, "Colossal Adventure /JoD (Amstrad CPC128[v1]/Spectrum +3)"},
+ {0x6f6a, 0xa5, 0x8dd2, "Colossal Adventure /JoD (Amstrad CPC128[v2])"},
+ {0x6968, 0x32, 0x0c01, "Adventure Quest /JoD (Amstrad CPC128/Spectrum +3)"},
+ {0x6dc0, 0x63, 0x5d95, "Dungeon Adventure /JoD (Amstrad CPC128/Spectrum +3)"},
+
+ {0x5e31, 0x7c, 0xaa54, "Colossal Adventure /JoD (Amstrad CPC64)"},
+ {0x5b50, 0x66, 0x1800, "Adventure Quest /JoD (Amstrad CPC64)"},
+ {0x58a6, 0x24, 0xb50f, "Dungeon Adventure /JoD (Amstrad CPC64)"},
+
+ {0x6c8e, 0xb6, 0x9be3, "Colossal Adventure /JoD (Commodore 64)"},
+ {0x63b6, 0x2e, 0xef38, "Adventure Quest /JoD (Commodore 64)"},
+ {0x6bd2, 0x65, 0xa41f, "Dungeon Adventure /JoD (Commodore 64)"},
+
+ {0x5b16, 0x3b, 0xe2aa, "Colossal Adventure /JoD (Atari)"},
+ {0x5b58, 0x50, 0x332e, "Adventure Quest /JoD (Atari)"},
+ {0x593a, 0x80, 0x7a34, "Dungeon Adventure /JoD (Atari)"},
+
+ {0x5a8e, 0xf2, 0x7cca, "Colossal Adventure /JoD (Spectrum 48)"},
+ {0x5ace, 0x11, 0xdc12, "Adventure Quest /JoD (Spectrum 48)"},
+ {0x58a3, 0x38, 0x8ce4, "Dungeon Adventure /JoD (Spectrum 48)"},
+
+ {0x7b31, 0x6e, 0x2e2b, "Snowball /SD (Amiga/ST)"},
+ {0x7d16, 0xe6, 0x5438, "Return to Eden /SD (Amiga/ST)"},
+ {0x7cd9, 0x0c, 0x4df1, "Worm in Paradise /SD (Amiga/ST)"},
+
+ {0x7b2f, 0x70, 0x6955, "Snowball /SD (Mac/PC/Spectrum 128)"},
+ {0x7b2f, 0x70, 0x6f6c, "Snowball /SD (Amstrad CPC/Spectrum +3)"},
+ {0x7d14, 0xe8, 0xfbab, "Return to Eden /SD (PC)"},
+ {0x7cff, 0xf8, 0x6044, "Return to Eden /SD (Amstrad CPC/Spectrum +3)"},
+ {0x7cf8, 0x24, 0x9c1c, "Return to Eden /SD (Mac)"},
+ {0x7c55, 0x18, 0xdaee, "Return to Eden /SD (Spectrum 128)"},
+ {0x7cd7, 0x0e, 0x4feb, "Worm in Paradise /SD (Amstrad CPC/Mac/PC/Spectrum 128/Spectrum +3)"},
+
+ {0x7363, 0x65, 0xa0ab, "Snowball /SD (Commodore 64)"},
+ {0x772f, 0xca, 0x8602, "Return to Eden /SD (Commodore 64)"},
+ {0x788d, 0x72, 0x888a, "Worm in Paradise /SD (Commodore 64)"},
+
+ {0x6bf8, 0x3f, 0xc9f7, "Snowball /SD (Atari)"},
+ {0x60f7, 0x68, 0xc2bc, "Return to Eden /SD (Atari)"},
+ {0x6161, 0xf3, 0xe6d7, "Worm in Paradise /SD (Atari)"},
+
+ {0x67a3, 0x9d, 0x1d05, "Snowball /SD (Apple ][)"},
+ {0x639c, 0x8b, 0x06e2, "Return to Eden /SD (Apple ][)"},
+ {0x60dd, 0xf2, 0x5bb8, "Worm in Paradise /SD (Apple ][)"},
+
+ {0x6541, 0x02, 0x2e6c, "Snowball /SD (Spectrum 48)"},
+ {0x5f43, 0xca, 0x828c, "Return to Eden /SD (Spectrum 48)"},
+ {0x5ebb, 0xf1, 0x4dec, "Worm in Paradise /SD (Spectrum 48)"},
+
+ {0x8333, 0xb7, 0xe2ac, "Adrian Mole I, pt. 1 (Commodore 64)"},
+ {0x844d, 0x50, 0x5353, "Adrian Mole I, pt. 2 (Commodore 64)"},
+ {0x8251, 0x5f, 0x862a, "Adrian Mole I, pt. 3 (Commodore 64)"},
+ {0x7a78, 0x5e, 0x6ea3, "Adrian Mole I, pt. 4 (Commodore 64)"},
+
+ {0x7c6f, 0x0f, 0xba24, "Adrian Mole I, pt. 1 (Amstrad CPC)"},
+
+ {0x72fa, 0x8b, 0x6f12, "Adrian Mole I, pt. 1 (Spectrum)"},
+ {0x738e, 0x5b, 0x7e3d, "Adrian Mole I, pt. 2 (Spectrum)"},
+ {0x7375, 0xe5, 0x3f3e, "Adrian Mole I, pt. 3 (Spectrum)"},
+ {0x78d5, 0xe3, 0xcd7d, "Adrian Mole I, pt. 4 (Spectrum)"},
+
+ {0x3a31, 0xe5, 0x0bdb, "Adrian Mole I, pt. 1 (BBC)"},
+ {0x37f1, 0x77, 0xd231, "Adrian Mole I, pt. 2 (BBC)"},
+ {0x3900, 0x1c, 0x5d9a, "Adrian Mole I, pt. 3 (BBC)"},
+ {0x3910, 0xac, 0x07f9, "Adrian Mole I, pt. 4 (BBC)"},
+ {0x3ad6, 0xa7, 0x95d2, "Adrian Mole I, pt. 5 (BBC)"},
+ {0x38a5, 0x0f, 0xdefc, "Adrian Mole I, pt. 6 (BBC)"},
+ {0x361e, 0x7e, 0xfd9f, "Adrian Mole I, pt. 7 (BBC)"},
+ {0x3934, 0x75, 0xe141, "Adrian Mole I, pt. 8 (BBC)"},
+ {0x3511, 0xcc, 0xd829, "Adrian Mole I, pt. 9 (BBC)"},
+ {0x38dd, 0x31, 0x2534, "Adrian Mole I, pt. 10 (BBC)"},
+ {0x39c0, 0x44, 0x89df, "Adrian Mole I, pt. 11 (BBC)"},
+ {0x3a12, 0x8f, 0xc2bd, "Adrian Mole I, pt. 12 (BBC)"},
+
+ {0x7931, 0xb9, 0xc51b, "Adrian Mole II, pt. 1 (Commodore 64/Amstrad CPC)"},
+ {0x7cdf, 0xa5, 0x43e3, "Adrian Mole II, pt. 2 (Commodore 64/Amstrad CPC)"},
+ {0x7a0c, 0x97, 0x4bea, "Adrian Mole II, pt. 3 (Commodore 64/Amstrad CPC)"},
+ {0x7883, 0xe2, 0xee0e, "Adrian Mole II, pt. 4 (Commodore 64/Amstrad CPC)"},
+
+ {0x6841, 0x4a, 0x94e7, "Adrian Mole II, pt. 1 (Spectrum)"},
+ {0x6bc0, 0x62, 0xab3d, "Adrian Mole II, pt. 2 (Spectrum)"},
+ {0x692c, 0x21, 0x2015, "Adrian Mole II, pt. 3 (Spectrum)"},
+ {0x670a, 0x94, 0xa2a6, "Adrian Mole II, pt. 4 (Spectrum)"},
+
+ {0x593a, 0xaf, 0x30e9, "Adrian Mole II, pt. 1 (BBC)"},
+ {0x57e6, 0x8a, 0xc41a, "Adrian Mole II, pt. 2 (BBC)"},
+ {0x5819, 0xcd, 0x1ba0, "Adrian Mole II, pt. 3 (BBC)"},
+ {0x579b, 0xad, 0xa723, "Adrian Mole II, pt. 4 (BBC)"},
+
+ {0x765d, 0xcd, 0xfc02, "The Archers, pt. 1 (Commodore 64)"},
+ {0x6e58, 0x07, 0xbffc, "The Archers, pt. 2 (Commodore 64)"},
+ {0x7e98, 0x6a, 0x95e5, "The Archers, pt. 3 (Commodore 64)"},
+ {0x81e2, 0xd5, 0xb278, "The Archers, pt. 4 (Commodore 64)"},
+
+ {0x6ce5, 0x58, 0x46de, "The Archers, pt. 1 (Spectrum)"},
+ {0x68da, 0xc1, 0x3b8e, "The Archers, pt. 2 (Spectrum)"},
+ {0x6c67, 0x9a, 0x9a6a, "The Archers, pt. 3 (Spectrum)"},
+ {0x6d91, 0xb9, 0x12a7, "The Archers, pt. 4 (Spectrum)"},
+
+ {0x5834, 0x42, 0xcc9d, "The Archers, pt. 1 (BBC)"},
+ {0x56dd, 0x51, 0xe582, "The Archers, pt. 2 (BBC)"},
+ {0x5801, 0x53, 0xf2ef, "The Archers, pt. 3 (BBC)"},
+ {0x54a4, 0x01, 0xc0ab, "The Archers, pt. 4 (BBC)"},
+
+ {0x579e, 0x97, 0x9faa, "Lords of Time /T&M GD (BBC)"},
+ {0x5500, 0x50, 0xca75, "Red Moon /T&M GD (BBC)"},
+ {0x579a, 0x2a, 0x9373, "Price of Magik /T&M GD (BBC)"},
+
+ {0x4fd2, 0x9d, 0x799a, "Lancelot, pt. 1 GD (BBC)"},
+ {0x4dac, 0xa8, 0x86ed, "Lancelot, pt. 2 GD (BBC)"},
+ {0x4f96, 0x22, 0x30f8, "Lancelot, pt. 3 GD (BBC)"},
+
+ {0x55ce, 0xa1, 0xba12, "Scapeghost, pt. 1 GD (BBC)"},
+ {0x54a6, 0xa9, 0xc9f3, "Scapeghost, pt. 2 GD (BBC)"},
+ {0x51bc, 0xe3, 0x89c3, "Scapeghost, pt. 3 GD (BBC)"},
+
+ {0x46ec, 0x64, 0x2300, "Knight Orc, pt. 1 GD (Amstrad CPC/Spectrum +3)"},
+ {0x6140, 0x18, 0x4f66, "Knight Orc, pt. 2 GD (Amstrad CPC/Spectrum +3)"},
+ {0x640e, 0xc1, 0xfc69, "Knight Orc, pt. 3 GD (Amstrad CPC/Spectrum +3)"},
+
+ {0x5ff0, 0xf8, 0x3a13, "Gnome Ranger, pt. 1 GD (Amstrad CPC/Spectrum +3)"},
+ {0x6024, 0x01, 0xaaa9, "Gnome Ranger, pt. 2 GD (Amstrad CPC/Spectrum +3)"},
+ {0x6036, 0x3d, 0x6c6c, "Gnome Ranger, pt. 3 GD (Amstrad CPC/Spectrum +3)"},
+
+ {0x69fe, 0x56, 0xecfb, "Lords of Time /T&M GD (Amstrad CPC/Spectrum +3)"},
+ {0x6888, 0x8d, 0x7f6a, "Red Moon /T&M GD (Amstrad CPC/Spectrum +3)"},
+ {0x5a50, 0xa9, 0xa5fa, "Price of Magik /T&M GD (Amstrad CPC/Spectrum +3)"},
+
+ {0x5c7a, 0x44, 0x460e, "Lancelot, pt. 1 GD (Amstrad CPC/Spectrum +3)"},
+ {0x53a2, 0x1e, 0x2fae, "Lancelot, pt. 2 GD (Amstrad CPC/Spectrum +3)"},
+ {0x5914, 0x22, 0x4a31, "Lancelot, pt. 3 GD (Amstrad CPC/Spectrum +3)"},
+
+ {0x5a38, 0xf7, 0x876e, "Ingrid's Back, pt. 1 GD (Amstrad CPC/Spectrum +3)"},
+ {0x531a, 0xed, 0xcf3f, "Ingrid's Back, pt. 2 GD (Amstrad CPC/Spectrum +3)"},
+ {0x57e4, 0x19, 0xb354, "Ingrid's Back, pt. 3 GD (Amstrad CPC/Spectrum +3)"},
+
+ {0x5cbc, 0xa5, 0x0dbe, "Scapeghost, pt. 1 GD (Amstrad CPC/Spectrum +3)"},
+ {0x5932, 0x4e, 0xb2f5, "Scapeghost, pt. 2 GD (Amstrad CPC/Spectrum +3)"},
+ {0x5860, 0x95, 0x3227, "Scapeghost, pt. 3 GD (Amstrad CPC/Spectrum +3)"},
+
+ {0x74e0, 0x92, 0x885e, "Knight Orc, pt. 1 GD (Spectrum 128)"},
+ {0x6dbc, 0x97, 0x6f55, "Knight Orc, pt. 2 GD (Spectrum 128)"},
+ {0x7402, 0x07, 0x385f, "Knight Orc, pt. 3 GD (Spectrum 128)"},
+
+ {0x52aa, 0xdf, 0x7b5b, "Gnome Ranger, pt. 1 GD (Spectrum 128)"},
+ {0x6ffa, 0xdb, 0xdde2, "Gnome Ranger, pt. 2 GD (Spectrum 128)"},
+ {0x723a, 0x69, 0x039b, "Gnome Ranger, pt. 3 GD (Spectrum 128)"},
+
+ {0x6f1e, 0xda, 0x2ce0, "Lords of Time /T&M GD (Spectrum 128)"},
+ {0x6da0, 0xb8, 0x3802, "Red Moon /T&M GD (Spectrum 128)"},
+ {0x6108, 0xdd, 0xefe7, "Price of Magik /T&M GD (Spectrum 128)"},
+
+ {0x768c, 0xe8, 0x8fc6, "Lancelot, pt. 1 GD (Spectrum 128)"},
+ {0x76b0, 0x1d, 0x0fcd, "Lancelot, pt. 2 GD (Spectrum 128)"},
+ {0x765e, 0x4f, 0x3b73, "Lancelot, pt. 3 GD (Spectrum 128)"},
+
+ {0x76a0, 0x3a, 0xb803, "Ingrid's Back, pt. 1 GD (Spectrum 128)"},
+ {0x7674, 0x0b, 0xe92f, "Ingrid's Back, pt. 2 GD (Spectrum 128)"},
+ {0x765e, 0xba, 0x086d, "Ingrid's Back, pt. 3 GD (Spectrum 128)"},
+
+ {0x762e, 0x82, 0x8848, "Scapeghost, pt. 1 GD (Spectrum 128)"},
+ {0x5bd6, 0x35, 0x79ef, "Scapeghost, pt. 2 GD (Spectrum 128)"},
+ {0x6fa8, 0xa4, 0x62c2, "Scapeghost, pt. 3 GD (Spectrum 128)"},
+
+ {0xbb93, 0x36, 0x6a05, "Knight Orc, pt. 1 (Amiga)"},
+ {0xbb6e, 0xad, 0x4d40, "Knight Orc, pt. 1 (ST)"},
+ {0xc58e, 0x4a, 0x4e9d, "Knight Orc, pt. 2 (Amiga/ST)"},
+ {0xcb9a, 0x0f, 0x0804, "Knight Orc, pt. 3 (Amiga/ST)"},
+
+ {0xbb6e, 0xa6, 0x9753, "Knight Orc, pt. 1 (PC)"},
+ {0xc58e, 0x43, 0xe9ce, "Knight Orc, pt. 2 (PC)"},
+ {0xcb9a, 0x08, 0x6c36, "Knight Orc, pt. 3 (PC)"},
+
+ {0x898a, 0x43, 0xfc8b, "Knight Orc, pt. 1 (Apple ][)"},
+ {0x8b9f, 0x61, 0x7288, "Knight Orc, pt. 2 (Apple ][)"},
+ {0x8af9, 0x61, 0x7542, "Knight Orc, pt. 3 (Apple ][)"},
+
+ {0x8970, 0x6b, 0x3c7b, "Knight Orc, pt. 1 (Commodore 64 Gfx)"},
+ {0x8b90, 0x4e, 0x098c, "Knight Orc, pt. 2 (Commodore 64 Gfx)"},
+ {0x8aea, 0x4e, 0xca54, "Knight Orc, pt. 3 (Commodore 64 Gfx)"},
+
+ {0x86d0, 0xb7, 0xadbd, "Knight Orc, pt. 1 (Spectrum 48)"},
+ {0x8885, 0x22, 0xe293, "Knight Orc, pt. 2 (Spectrum 48)"},
+ {0x87e5, 0x0e, 0xdc33, "Knight Orc, pt. 3 (Spectrum 48)"},
+
+ {0xb1a9, 0x80, 0x5fb7, "Gnome Ranger, pt. 1 (Amiga/ST)"},
+ {0xab9d, 0x31, 0xbe6d, "Gnome Ranger, pt. 2 (Amiga/ST)"},
+ {0xae28, 0x87, 0xb6b6, "Gnome Ranger, pt. 3 (Amiga/ST)"},
+
+ {0xb0ec, 0xc2, 0x0053, "Gnome Ranger, pt. 1 (ST[v1])"},
+ {0xaf82, 0x83, 0x19f7, "Gnome Ranger, pt. 2 (ST[v1])"},
+
+ {0xb1aa, 0xad, 0xaf47, "Gnome Ranger, pt. 1 (PC)"},
+ {0xb19e, 0x92, 0x8f96, "Gnome Ranger, pt. 1 (ST[v2])"},
+ {0xab8b, 0xbf, 0x31e6, "Gnome Ranger, pt. 2 (PC/ST[v2])"},
+ {0xae16, 0x81, 0x8741, "Gnome Ranger, pt. 3 (PC/ST[v2])"},
+
+ {0xad41, 0xa8, 0x42c5, "Gnome Ranger, pt. 1 (Commodore 64 TO)"},
+ {0xa735, 0xf7, 0x2e08, "Gnome Ranger, pt. 2 (Commodore 64 TO)"},
+ {0xa9c0, 0x9e, 0x0d70, "Gnome Ranger, pt. 3 (Commodore 64 TO)"},
+
+ {0x908e, 0x0d, 0x58a7, "Gnome Ranger, pt. 1 (Commodore 64 Gfx)"},
+ {0x8f6f, 0x0a, 0x411a, "Gnome Ranger, pt. 2 (Commodore 64 Gfx)"},
+ {0x9060, 0xbb, 0xe75d, "Gnome Ranger, pt. 3 (Commodore 64 Gfx)"},
+
+ {0x8aab, 0xc0, 0xde5f, "Gnome Ranger, pt. 1 (Spectrum 48)"},
+ {0x8ac8, 0x9a, 0xc89b, "Gnome Ranger, pt. 2 (Spectrum 48)"},
+ {0x8a93, 0x4f, 0x10cc, "Gnome Ranger, pt. 3 (Spectrum 48)"},
+
+ {0xb57c, 0x44, 0x7779, "Lords of Time /T&M (PC)"},
+ {0xa69e, 0x6c, 0xb268, "Red Moon /T&M (PC)"},
+ {0xbac7, 0x7f, 0xddb2, "Price of Magik /T&M (PC)"},
+
+ {0xb579, 0x89, 0x3e89, "Lords of Time /T&M (ST)"},
+ {0xa698, 0x41, 0xcaca, "Red Moon /T&M (ST)"},
+ {0xbac4, 0x80, 0xa750, "Price of Magik /T&M (ST)"},
+
+ {0xb576, 0x2a, 0x7239, "Lords of Time /T&M (Amiga)"},
+ {0xa692, 0xd1, 0x6a99, "Red Moon /T&M (Amiga)"},
+ {0xbaca, 0x3a, 0x221b, "Price of Magik /T&M (Amiga)"},
+
+ {0xb563, 0x6a, 0x0c5c, "Lords of Time /T&M (Mac)"},
+ {0xa67c, 0xb8, 0xff41, "Red Moon /T&M (Mac)"},
+ {0xbab2, 0x87, 0x09f5, "Price of Magik /T&M (Mac)"},
+
+ {0xb38c, 0x37, 0x9f8e, "Lords of Time /T&M (Commodore 64 TO)"},
+ {0xa4e2, 0xa6, 0x016d, "Red Moon /T&M (Commodore 64 TO)"},
+ {0xb451, 0xa8, 0x2682, "Price of Magik /T&M (Commodore 64 TO)"},
+
+ {0x9070, 0x43, 0x45d4, "Lords of Time /T&M (Commodore 64 Gfx)"},
+ {0x903f, 0x6b, 0x603e, "Red Moon /T&M (Commodore 64 Gfx)"},
+ {0x8f51, 0xb2, 0x6c9a, "Price of Magik /T&M (Commodore 64 Gfx)"},
+
+ {0x8950, 0xa1, 0xbb16, "Lords of Time /T&M (Spectrum 48)"},
+ {0x8813, 0x11, 0x22de, "Red Moon /T&M (Spectrum 48)"},
+ {0x8a60, 0x2a, 0x29ed, "Price of Magik /T&M (Spectrum 48)"},
+
+ {0xb260, 0xe5, 0xc5b2, "Lords of Time /T&M (PC/ST *USA*)"},
+ {0xa3a4, 0xdf, 0x6732, "Red Moon /T&M (PC/ST *USA*)"},
+ {0xb7a0, 0x7e, 0x2226, "Price of Magik /T&M (PC/ST *USA*)"},
+
+ {0xb257, 0xf8, 0xfbd5, "Lords of Time /T&M (Amiga *USA*)"},
+ {0xa398, 0x82, 0xd031, "Red Moon /T&M (Amiga *USA*)"},
+ {0xb797, 0x1f, 0x84a9, "Price of Magik /T&M (Amiga *USA*)"},
+
+ {0x8d78, 0x3a, 0xba6e, "Lords of Time /T&M (Commodore 64 Gfx *USA*)"},
+ {0x8d56, 0xd3, 0x146a, "Red Moon /T&M (Commodore 64 Gfx *USA*)"},
+ {0x8c46, 0xf0, 0xcaf6, "Price of Magik /T&M (Commodore 64 Gfx *USA*)"},
+
+ {0xc0cf, 0x4e, 0xb7fa, "Lancelot, pt. 1 (Amiga/PC/ST)"},
+ {0xd5e9, 0x6a, 0x4192, "Lancelot, pt. 2 (Amiga/PC/ST)"},
+ {0xbb8f, 0x1a, 0x7487, "Lancelot, pt. 3 (Amiga/PC/ST)"},
+
+ {0xc0bd, 0x57, 0x6ef1, "Lancelot, pt. 1 (Mac)"},
+ {0xd5d7, 0x99, 0x770b, "Lancelot, pt. 2 (Mac)"},
+ {0xbb7d, 0x17, 0xbc42, "Lancelot, pt. 3 (Mac)"},
+
+ {0xb4c9, 0x94, 0xd784, "Lancelot, pt. 1 (Commodore 64 TO)"},
+ {0xb729, 0x51, 0x8ee5, "Lancelot, pt. 2 (Commodore 64 TO)"},
+ {0xb702, 0xe4, 0x1809, "Lancelot, pt. 3 (Commodore 64 TO)"},
+
+ {0x8feb, 0xba, 0xa800, "Lancelot, pt. 1 (Commodore 64 Gfx)"},
+ {0x8f6b, 0xfa, 0x0f7e, "Lancelot, pt. 2 (Commodore 64 Gfx)"},
+ {0x8f71, 0x2f, 0x0ddc, "Lancelot, pt. 3 (Commodore 64 Gfx)"},
+
+ {0x8ade, 0xf2, 0xfffb, "Lancelot, pt. 1 (Spectrum 48)"},
+ {0x8b0e, 0xfb, 0x0bab, "Lancelot, pt. 2 (Spectrum 48)"},
+ {0x8ab3, 0xc1, 0xcb62, "Lancelot, pt. 3 (Spectrum 48)"},
+
+ {0xbba4, 0x94, 0x0871, "Lancelot, pt. 1 (Amiga/PC *USA*)"},
+ {0xd0c0, 0x56, 0x8c48, "Lancelot, pt. 2 (Amiga/PC *USA*)"},
+ {0xb6ac, 0xc6, 0xaea0, "Lancelot, pt. 3 (Amiga/PC *USA*)"},
+
+ {0x8afc, 0x07, 0x8321, "Lancelot, pt. 1 (Commodore 64 Gfx *USA*)"},
+ {0x8aec, 0x13, 0x6791, "Lancelot, pt. 2 (Commodore 64 Gfx *USA*)"},
+ {0x8aba, 0x0d, 0x5602, "Lancelot, pt. 3 (Commodore 64 Gfx *USA*)"},
+
+ {0xd19b, 0xad, 0x306d, "Ingrid's Back, pt. 1 (PC)"},
+ {0xc5a5, 0xfe, 0x3c98, "Ingrid's Back, pt. 2 (PC)"},
+ {0xd7ae, 0x9e, 0x1878, "Ingrid's Back, pt. 3 (PC)"},
+
+ {0xd188, 0x13, 0xdc60, "Ingrid's Back, pt. 1 (Amiga)"},
+ {0xc594, 0x03, 0xea95, "Ingrid's Back, pt. 2 (Amiga)"},
+ {0xd79f, 0xb5, 0x1661, "Ingrid's Back, pt. 3 (Amiga)"},
+
+ {0xd183, 0x83, 0xef72, "Ingrid's Back, pt. 1 (ST)"},
+ {0xc58f, 0x65, 0xf337, "Ingrid's Back, pt. 2 (ST)"},
+ {0xd79a, 0x57, 0x49c5, "Ingrid's Back, pt. 3 (ST)"},
+
+ {0xb770, 0x03, 0x9a03, "Ingrid's Back, pt. 1 (Commodore 64 TO)"},
+ {0xb741, 0xb6, 0x2aa5, "Ingrid's Back, pt. 2 (Commodore 64 TO)"},
+ {0xb791, 0xa1, 0xd065, "Ingrid's Back, pt. 3 (Commodore 64 TO)"},
+
+ {0x9089, 0xce, 0xc5e2, "Ingrid's Back, pt. 1 (Commodore 64 Gfx)"},
+ {0x908d, 0x80, 0x30c7, "Ingrid's Back, pt. 2 (Commodore 64 Gfx)"},
+ {0x909e, 0x9f, 0xdecc, "Ingrid's Back, pt. 3 (Commodore 64 Gfx)"},
+
+ {0x8ab7, 0x68, 0xee57, "Ingrid's Back, pt. 1 (Spectrum 48)"},
+ {0x8b1e, 0x84, 0x2538, "Ingrid's Back, pt. 2 (Spectrum 48)"},
+ {0x8b1c, 0xa8, 0x9262, "Ingrid's Back, pt. 3 (Spectrum 48)"},
+
+ {0xbeab, 0x2d, 0x94d9, "Scapeghost, pt. 1 (Amiga)"},
+ {0xc132, 0x14, 0x7adc, "Scapeghost, pt. 1 (Amiga *bak*)"},
+ {0xbe94, 0xcc, 0x04b8, "Scapeghost, pt. 1 (PC/ST)"},
+ {0x99bd, 0x65, 0x032e, "Scapeghost, pt. 2 (Amiga/PC/ST)"},
+ {0xbcb6, 0x7a, 0x7d4f, "Scapeghost, pt. 3 (Amiga/PC/ST)"},
+
+ {0x9058, 0xcf, 0x9748, "Scapeghost, pt. 1 (Commodore 64 Gfx)"},
+ {0x8f43, 0xc9, 0xeefd, "Scapeghost, pt. 2 (Commodore 64 Gfx)"},
+ {0x90ac, 0x68, 0xb4a8, "Scapeghost, pt. 3 (Commodore 64 Gfx)"},
+
+ {0x8a21, 0xf4, 0xd9e4, "Scapeghost, pt. 1 (Spectrum 48)"},
+ {0x8a12, 0xe3, 0xc2ff, "Scapeghost, pt. 2 (Spectrum 48)"},
+ {0x8a16, 0xcc, 0x4f3b, "Scapeghost, pt. 3 (Spectrum 48)"},
+
+ {0x3ebb, 0x00, 0xf6dc, "Champion of the Raj (English) 1/2 GD (Amiga)"},
+ {0x0fd8, 0x00, 0xf250, "Champion of the Raj (English) 2/2 GD (Amiga)"},
+
+ {0x3e8f, 0x00, 0x5599, "Champion of the Raj (English) 1/2 GD (ST)"},
+
+ {0x3e4f, 0x00, 0xb202, "Champion of the Raj (English) 1/2 GD (PC)"},
+ {0x14a3, 0x00, 0xa288, "Champion of the Raj (English) 2/2 GD (PC)"},
+
+ {0x1929, 0x00, 0xd4b2, "Champion of the Raj (demo), 1/2 GD (ST)"},
+ {0x40e0, 0x02, 0x080d, "Champion of the Raj (demo), 2/2 GD (ST)"},
+
+ {0x4872, 0x00, 0x9515, "Champion of the Raj (German) 1/2 GD (Amiga)"},
+ {0x11f5, 0x00, 0xbf39, "Champion of the Raj (German) 2/2 GD (Amiga)"},
+
+ {0x4846, 0x00, 0xd9c1, "Champion of the Raj (German) 1/2 GD (ST)"},
+ {0x11f5, 0x00, 0x7aa4, "Champion of the Raj (German) 2/2 GD (ST)"},
+
+ {0x110f, 0x00, 0x4b57, "Champion of the Raj (French) 2/2 GD (ST)"},
+
+ {0x0000, 0x00, 0x0000, nullptr}
+};
+
+/**
+ * The following patch database is obtained from L9cut's l9data_p.h, and
+ * allows CRCs from patched games to be translated into original CRCs for
+ * lookup in the game database above. Some file commentary has been removed
+ * for brevity, and unused patch fields deleted.
+ *
+ * The version of l9data_p.h used is 012 (22 May 2001).
+ */
+static const gln_patch_table_t GLN_PATCH_TABLE[] = {
+ /* Price of Magik (Spectrum128) */
+ {0x7410, 0x5e, 0x60be, 0x70, 0x6cef},
+
+ /* Price of Magik (Commodore 64) */
+ {0x6fc6, 0x14, 0xf9b6, 0x26, 0x3326},
+
+ /* Price of Magik (Spectrum48) */
+ {0x5aa4, 0xc1, 0xeda4, 0xd3, 0xed35},
+ {0x5aa4, 0xc1, 0xeda4, 0xc1, 0x8a65},
+
+ /* Colossal Adventure /JoD (Amiga/PC) */
+ {0x76f4, 0x5e, 0x1fe5, 0xea, 0x1305},
+ {0x76f4, 0x5e, 0x1fe5, 0xb5, 0x901f},
+ {0x76f4, 0x5e, 0x1fe5, 0x5e, 0x6ea1},
+
+ /* Colossal Adventure /JoD (ST) */
+ {0x76f4, 0x5a, 0xcf4b, 0xe6, 0x012a},
+ {0x76f4, 0x5a, 0xcf4b, 0xb1, 0x40b1},
+
+ /* Adventure Quest /JoD (Amiga/PC) */
+ {0x6e60, 0x83, 0x18e0, 0x4c, 0xcfb0},
+ {0x6e60, 0x83, 0x18e0, 0xfa, 0x9b3b},
+ {0x6e60, 0x83, 0x18e0, 0x83, 0x303d},
+
+ /* Adventure Quest /JoD (ST) */
+ {0x6e5c, 0xf6, 0xd356, 0xbf, 0xede7},
+ {0x6e5c, 0xf6, 0xd356, 0x6d, 0x662d},
+
+ /* Dungeon Adventure /JoD (Amiga/PC/ST) */
+ {0x6f0c, 0x95, 0x1f64, 0x6d, 0x2443},
+ {0x6f0c, 0x95, 0x1f64, 0x0c, 0x6066},
+ {0x6f0c, 0x95, 0x1f64, 0x96, 0xdaca},
+ {0x6f0c, 0x95, 0x1f64, 0x95, 0x848d},
+
+ /* Colossal Adventure /JoD (Spectrum128) */
+ {0x6f6e, 0x78, 0x28cd, 0xf8, 0xda5f},
+ {0x6f6e, 0x78, 0x28cd, 0x77, 0x5b4e},
+
+ /* Adventure Quest /JoD (Spectrum128) */
+ {0x6970, 0xd6, 0xa820, 0x3b, 0x1870},
+ {0x6970, 0xd6, 0xa820, 0xd5, 0x13c4},
+
+ /* Dungeon Adventure /JoD (Spectrum128) */
+ {0x6de8, 0x4c, 0xd795, 0xa2, 0x3eea},
+ {0x6de8, 0x4c, 0xd795, 0x4b, 0xad30},
+
+ /* Colossal Adventure /JoD (Amstrad CPC) */
+ {0x6f4d, 0xcb, 0xe8f2, 0x4b, 0xb384},
+ {0x6f4d, 0xcb, 0xe8f2, 0xca, 0x96e7},
+
+ /* Adventure Quest /JoD (Amstrad CPC) */
+ {0x6968, 0x32, 0x0c01, 0x97, 0xdded},
+ {0x6968, 0x32, 0x0c01, 0x31, 0xe8c2},
+
+ /* Dungeon Adventure /JoD (Amstrad CPC) */
+ {0x6dc0, 0x63, 0x5d95, 0xb9, 0xc963},
+ {0x6dc0, 0x63, 0x5d95, 0x62, 0x79f7},
+
+ /* Colossal Adventure /JoD (Commodore 64) */
+ {0x6c8e, 0xb6, 0x9be3, 0x36, 0x6971},
+ {0x6c8e, 0xb6, 0x9be3, 0xb5, 0xeba0},
+
+ /* Adventure Quest /JoD (Commodore 64) */
+ {0x63b6, 0x2e, 0xef38, 0x93, 0x4e68},
+ {0x63b6, 0x2e, 0xef38, 0x2d, 0x54dc},
+
+ /* Dungeon Adventure /JoD (Commodore 64) */
+ {0x6bd2, 0x65, 0xa41f, 0xbb, 0x4260},
+ {0x6bd2, 0x65, 0xa41f, 0x64, 0xdf5a},
+
+ /* Colossal Adventure /JoD (Spectrum48) */
+ {0x5a8e, 0xf2, 0x7cca, 0x72, 0x8e58},
+ {0x5a8e, 0xf2, 0x7cca, 0xf1, 0x0c89},
+ {0x5a8e, 0xf2, 0x7cca, 0xf2, 0x2c96},
+
+ /* Adventure Quest /JoD (Spectrum48) */
+ {0x5ace, 0x11, 0xdc12, 0x76, 0x8663},
+ {0x5ace, 0x11, 0xdc12, 0x10, 0xa757},
+ {0x5ace, 0x11, 0xdc12, 0x11, 0xf118},
+
+ /* Dungeon Adventure /JoD (Spectrum48) */
+ {0x58a3, 0x38, 0x8ce4, 0x8e, 0xb61a},
+ {0x58a3, 0x38, 0x8ce4, 0x37, 0x34c0},
+ {0x58a3, 0x38, 0x8ce4, 0x38, 0xa1ee},
+
+ /* Snowball /SD (Amiga/ST) */
+ {0x7b31, 0x6e, 0x2e2b, 0xe5, 0x6017},
+
+ /* Return to Eden /SD (Amiga/ST) */
+ {0x7d16, 0xe6, 0x5438, 0x5d, 0xc770},
+
+ /* Worm in Paradise /SD (Amiga/ST) */
+ {0x7cd9, 0x0c, 0x4df1, 0x83, 0xe997},
+
+ /* Snowball /SD (PC/Spectrum128) */
+ {0x7b2f, 0x70, 0x6955, 0xe7, 0x0af4},
+ {0x7b2f, 0x70, 0x6955, 0x70, 0x1179},
+
+ /* Return to Eden /SD (PC) */
+ {0x7d14, 0xe8, 0xfbab, 0x5f, 0xeab9},
+ {0x7d14, 0xe8, 0xfbab, 0xe8, 0xe216},
+
+ /* Return to Eden /SD (Amstrad CPC) */
+ {0x7cff, 0xf8, 0x6044, 0x6f, 0xbb57},
+
+ /* Return to Eden /SD (Spectrum128) */
+ {0x7c55, 0x18, 0xdaee, 0x8f, 0x01fd},
+
+ /* Worm in Paradise /SD (Amstrad CPC/PC/Spectrum128) */
+ {0x7cd7, 0x0e, 0x4feb, 0x85, 0x4eae},
+ {0x7cd7, 0x0e, 0x4feb, 0x0e, 0xb02c},
+
+ /* Snowball /SD (Commodore 64) */
+ {0x7363, 0x65, 0xa0ab, 0xdc, 0xca6a},
+
+ /* Return to Eden /SD (Commodore 64) */
+ {0x772f, 0xca, 0x8602, 0x41, 0x9bd0},
+
+ /* Worm in Paradise /SD (Commodore 64) */
+ {0x788d, 0x72, 0x888a, 0xe9, 0x4cce},
+
+ /* Snowball /SD (Atari) */
+ {0x6bf8, 0x3f, 0xc9f7, 0x96, 0x1908},
+
+ /* Return to Eden /SD (Atari) */
+ {0x60f7, 0x68, 0xc2bc, 0xdf, 0xd3ae},
+
+ /* Worm in Paradise /SD (Atari) */
+ {0x6161, 0xf3, 0xe6d7, 0x6a, 0xe232},
+
+ /* Snowball /SD (Spectrum48) */
+ {0x6541, 0x02, 0x2e6c, 0x79, 0xb80c},
+ {0x6541, 0x02, 0x2e6c, 0x02, 0x028a},
+
+ /* Return to Eden /SD (Spectrum48) */
+ {0x5f43, 0xca, 0x828c, 0x41, 0x9f5e},
+ {0x5f43, 0xca, 0x828c, 0xca, 0x6e1b},
+
+ /* Worm in Paradise /SD (Spectrum48) */
+ {0x5ebb, 0xf1, 0x4dec, 0x68, 0x4909},
+ {0x5ebb, 0xf1, 0x4dec, 0xf1, 0xcc1a},
+
+ /* Knight Orc, pt. 1 (Amiga) */
+ {0xbb93, 0x36, 0x6a05, 0xad, 0xe52d},
+
+ /* Knight Orc, pt. 1 (ST) */
+ {0xbb6e, 0xad, 0x4d40, 0x24, 0x3bcd},
+
+ /* Knight Orc, pt. 2 (Amiga/ST) */
+ {0xc58e, 0x4a, 0x4e9d, 0xc1, 0xe2bf},
+
+ /* Knight Orc, pt. 3 (Amiga/ST) */
+ {0xcb9a, 0x0f, 0x0804, 0x86, 0x6487},
+
+ /* Knight Orc, pt. 1 (PC) */
+ {0xbb6e, 0xa6, 0x9753, 0x1d, 0x2e7f},
+ {0xbb6e, 0xa6, 0x9753, 0xa6, 0x001d},
+
+ /* Knight Orc, pt. 2 (PC) */
+ {0xc58e, 0x43, 0xe9ce, 0xba, 0x5e4c},
+ {0xc58e, 0x43, 0xe9ce, 0x43, 0xa8f0},
+
+ /* Knight Orc, pt. 3 (PC) */
+ {0xcb9a, 0x08, 0x6c36, 0x7f, 0xf0d4},
+ {0xcb9a, 0x08, 0x6c36, 0x08, 0x2d08},
+
+ /* Knight Orc, pt. 1 (Commodore 64 Gfx) */
+ {0x8970, 0x6b, 0x3c7b, 0xe2, 0xb6f3},
+
+ /* Knight Orc, pt. 1 (Spectrum48) */
+ {0x86d0, 0xb7, 0xadbd, 0x2e, 0x43e1},
+
+ /* Gnome Ranger, pt. 1 (Amiga/ST) */
+ {0xb1a9, 0x80, 0x5fb7, 0xf7, 0x5c6c},
+
+ /* Gnome Ranger, pt. 2 (Amiga/ST) */
+ {0xab9d, 0x31, 0xbe6d, 0xa8, 0xcb96},
+
+ /* Gnome Ranger, pt. 3 (Amiga/ST) */
+ {0xae28, 0x87, 0xb6b6, 0xfe, 0x760c},
+
+ /* Gnome Ranger, pt. 1 (PC) */
+ {0xb1aa, 0xad, 0xaf47, 0x24, 0x5cfd},
+ {0xb1aa, 0xad, 0xaf47, 0xad, 0xe0ed},
+
+ /* Gnome Ranger, pt. 1 (ST-var) */
+ {0xb19e, 0x92, 0x8f96, 0x09, 0x798c},
+
+ /* Gnome Ranger, pt. 2 (PC/ST-var) */
+ {0xab8b, 0xbf, 0x31e6, 0x36, 0x811c},
+ {0xab8b, 0xbf, 0x31e6, 0xbf, 0x8ff3},
+
+ /* Gnome Ranger, pt. 3 (PC/ST-var) */
+ {0xae16, 0x81, 0x8741, 0xf8, 0x47fb},
+ {0xae16, 0x81, 0x8741, 0x81, 0xc8eb},
+
+ /* Gnome Ranger, pt. 1 (Commodore 64 TO) */
+ {0xad41, 0xa8, 0x42c5, 0x1f, 0x7d1e},
+
+ /* Gnome Ranger, pt. 2 (Commodore 64 TO) */
+ {0xa735, 0xf7, 0x2e08, 0x6e, 0x780e},
+
+ /* Gnome Ranger, pt. 3 (Commodore 64 TO) */
+ {0xa9c0, 0x9e, 0x0d70, 0x15, 0x3e6b},
+
+ /* Gnome Ranger, pt. 1 (Commodore 64 Gfx) */
+ {0x908e, 0x0d, 0x58a7, 0x84, 0xab1d},
+
+ /* Gnome Ranger, pt. 2 (Commodore 64 Gfx) */
+ {0x8f6f, 0x0a, 0x411a, 0x81, 0x12bc},
+
+ /* Gnome Ranger, pt. 3 (Commodore 64 Gfx) */
+ {0x9060, 0xbb, 0xe75d, 0x32, 0x14e7},
+
+ /* Lords of Time /T&M (PC) */
+ {0xb57c, 0x44, 0x7779, 0xbb, 0x31a6},
+ {0xb57c, 0x44, 0x7779, 0x44, 0xea72},
+
+ /* Red Moon /T&M (PC) */
+ {0xa69e, 0x6c, 0xb268, 0xe3, 0x4cef},
+ {0xa69e, 0x6c, 0xb268, 0x6c, 0x3799},
+
+ /* Price of Magik /T&M (PC) */
+ {0xbac7, 0x7f, 0xddb2, 0xf6, 0x6ab3},
+ {0xbac7, 0x7f, 0xddb2, 0x7f, 0x905c},
+
+ /* Lords of Time /T&M (ST) */
+ {0xb579, 0x89, 0x3e89, 0x00, 0xa2b7},
+
+ /* Red Moon /T&M (ST) */
+ {0xa698, 0x41, 0xcaca, 0xb8, 0xeeac},
+
+ /* Price of Magik /T&M (ST) */
+ {0xbac4, 0x80, 0xa750, 0xf7, 0xe030},
+
+ /* Lords of Time /T&M (Amiga) */
+ {0xb576, 0x2a, 0x7239, 0xa1, 0x2ea6},
+
+ /* Red Moon /T&M (Amiga) */
+ {0xa692, 0xd1, 0x6a99, 0x48, 0x50ff},
+
+ /* Price of Magik /T&M (Amiga) */
+ {0xbaca, 0x3a, 0x221b, 0xb1, 0x55bb},
+
+ /* Lords of Time /T&M (Commodore 64 TO) */
+ {0xb38c, 0x37, 0x9f8e, 0xae, 0xc6b1},
+
+ /* Red Moon /T&M (Commodore 64 TO) */
+ {0xa4e2, 0xa6, 0x016d, 0x1d, 0x31ab},
+
+ /* Price of Magik /T&M (Commodore 64 TO) */
+ {0xb451, 0xa8, 0x2682, 0x1f, 0x5de2},
+
+ /* Lords of Time /T&M (Commodore 64 Gfx) */
+ {0x9070, 0x43, 0x45d4, 0xba, 0x02eb},
+
+ /* Red Moon /T&M (Commodore 64 Gfx) */
+ {0x903f, 0x6b, 0x603e, 0xe2, 0x9f59},
+
+ /* Price of Magik /T&M (Commodore 64 Gfx) */
+ {0x8f51, 0xb2, 0x6c9a, 0x29, 0xde3b},
+
+ /* Lords of Time /T&M (Spectrum48) */
+ {0x8950, 0xa1, 0xbb16, 0x18, 0x2828},
+ {0x8950, 0xa1, 0xbb16, 0xa1, 0x1ea2},
+
+ /* Red Moon /T&M (Spectrum48) */
+ {0x8813, 0x11, 0x22de, 0x88, 0x18b8},
+ {0x8813, 0x11, 0x22de, 0x11, 0xd0cd},
+
+ /* Price of Magik /T&M (Spectrum48) */
+ {0x8a60, 0x2a, 0x29ed, 0xa1, 0x5e4d},
+
+ /* Lancelot, pt. 1 (Amiga/PC/ST) */
+ {0xc0cf, 0x4e, 0xb7fa, 0xc5, 0x4400},
+
+ /* Lancelot, pt. 2 (Amiga/PC/ST) */
+ {0xd5e9, 0x6a, 0x4192, 0xe1, 0x3b1e},
+
+ /* Lancelot, pt. 3 (Amiga/PC/ST) */
+ {0xbb8f, 0x1a, 0x7487, 0x91, 0x877d},
+
+ /* Lancelot, pt. 1 (Commodore 64 TO) */
+ {0xb4c9, 0x94, 0xd784, 0x0b, 0x203e},
+
+ /* Lancelot, pt. 2 (Commodore 64 TO) */
+ {0xb729, 0x51, 0x8ee5, 0xc8, 0xf1c9},
+
+ /* Lancelot, pt. 3 (Commodore 64 TO) */
+ {0xb702, 0xe4, 0x1809, 0x5b, 0x25b2},
+
+ /* Lancelot, pt. 1 (Commodore 64 Gfx) */
+ {0x8feb, 0xba, 0xa800, 0x31, 0x5bfa},
+
+ /* Lancelot, pt. 2 (Commodore 64 Gfx) */
+ {0x8f6b, 0xfa, 0x0f7e, 0x71, 0x75f2},
+
+ /* Lancelot, pt. 3 (Commodore 64 Gfx) */
+ {0x8f71, 0x2f, 0x0ddc, 0xa6, 0x3e87},
+
+ /* Ingrid's Back, pt. 1 (PC) */
+ {0xd19b, 0xad, 0x306d, 0x24, 0x4504},
+ {0xd19b, 0xad, 0x306d, 0xad, 0x878e},
+
+ /* Ingrid's Back, pt. 2 (PC) */
+ {0xc5a5, 0xfe, 0x3c98, 0x75, 0x8950},
+ {0xc5a5, 0xfe, 0x3c98, 0xfe, 0x8b7b},
+
+ /* Ingrid's Back, pt. 3 (PC) */
+ {0xd7ae, 0x9e, 0x1878, 0x15, 0xadb0},
+ {0xd7ae, 0x9e, 0x1878, 0x9e, 0xaf9b},
+
+ /* Ingrid's Back, pt. 1 (Amiga) */
+ {0xd188, 0x13, 0xdc60, 0x8a, 0x755c},
+
+ /* Ingrid's Back, pt. 2 (Amiga) */
+ {0xc594, 0x03, 0xea95, 0x7a, 0xb5a8},
+
+ /* Ingrid's Back, pt. 3 (Amiga) */
+ {0xd79f, 0xb5, 0x1661, 0x2c, 0xbf5d},
+
+ /* Ingrid's Back, pt. 1 (ST) */
+ {0xd183, 0x83, 0xef72, 0xfa, 0xb04f},
+
+ /* Ingrid's Back, pt. 2 (ST) */
+ {0xc58f, 0x65, 0xf337, 0xdc, 0x900a},
+
+ /* Ingrid's Back, pt. 3 (ST) */
+ {0xd79a, 0x57, 0x49c5, 0xce, 0xe0f9},
+
+ /* Ingrid's Back, pt. 1 (Commodore 64 TO) */
+ {0xb770, 0x03, 0x9a03, 0x7a, 0xdc6a},
+
+ /* Ingrid's Back, pt. 2 (Commodore 64 TO) */
+ {0xb741, 0xb6, 0x2aa5, 0x2d, 0x5a6c},
+
+ /* Ingrid's Back, pt. 3 (Commodore 64 TO) */
+ {0xb791, 0xa1, 0xd065, 0x18, 0xaa0c},
+
+ /* Ingrid's Back, pt. 1 (Commodore 64 Gfx) */
+ {0x9089, 0xce, 0xc5e2, 0x44, 0xeff4},
+
+ /* Ingrid's Back, pt. 2 (Commodore 64 Gfx) */
+ {0x908d, 0x80, 0x30c7, 0xf6, 0x2a11},
+
+ /* Ingrid's Back, pt. 3 (Commodore 64 Gfx) */
+ {0x909e, 0x9f, 0xdecc, 0x15, 0xf4da},
+
+ {0x0000, 0x00, 0x0000, 0x00, 0x0000},
+};
+
+
// TODO: The list of Level 9 games and detection entries needs to be filled out
const PlainGameDescriptor LEVEL9_GAME_LIST[] = {
{ "level9", "Level 9 IF Game" },
diff --git a/engines/glk/level9/level9.cpp b/engines/glk/level9/level9.cpp
index 7fe85ee485..31caeedaa1 100644
--- a/engines/glk/level9/level9.cpp
+++ b/engines/glk/level9/level9.cpp
@@ -29,7 +29,8 @@ namespace Level9 {
Level9 *g_vm = nullptr;
-Level9::Level9(OSystem *syst, const GlkGameDescription &gameDesc) : GlkAPI(syst, gameDesc) {
+Level9::Level9(OSystem *syst, const GlkGameDescription &gameDesc) : GlkAPI(syst, gameDesc),
+ _detection(startdata, FileSize) {
g_vm = this;
}
diff --git a/engines/glk/level9/level9.h b/engines/glk/level9/level9.h
index 90c441e74f..ee7dbce83b 100644
--- a/engines/glk/level9/level9.h
+++ b/engines/glk/level9/level9.h
@@ -27,6 +27,7 @@
#include "common/serializer.h"
#include "common/stack.h"
#include "glk/glk_api.h"
+#include "glk/level9/detection.h"
namespace Glk {
namespace Level9 {
@@ -46,6 +47,8 @@ private:
*/
void deinitialize();
public:
+ GameDetection _detection;
+public:
/**
* Constructor
*/
diff --git a/engines/glk/level9/level9_main.cpp b/engines/glk/level9/level9_main.cpp
index 2ce60a5fed..b4ab1a85f5 100644
--- a/engines/glk/level9/level9_main.cpp
+++ b/engines/glk/level9/level9_main.cpp
@@ -77,8 +77,8 @@ enum L9GfxTypes { GFX_V2, GFX_V3A, GFX_V3B, GFX_V3C };
/* Global Variables */
L9BYTE *startfile, *pictureaddress, *picturedata;
-L9BYTE *startdata;
-L9UINT32 FileSize, picturesize;
+byte *startdata;
+size_t FileSize, picturesize;
L9BYTE *L9Pointers[12];
L9BYTE *absdatablock, *list2ptr, *list3ptr, *list9startptr, *acodeptr;
diff --git a/engines/glk/level9/level9_main.h b/engines/glk/level9/level9_main.h
index ec04db376a..95d9f18338 100644
--- a/engines/glk/level9/level9_main.h
+++ b/engines/glk/level9/level9_main.h
@@ -86,6 +86,9 @@ struct Bitmap {
#define L9SETWORD(x,val) WRITE_LE_UINT16(x, val)
#define L9SETDWORD(x,val) WRITE_LE_UINT32(x, val)
+extern byte *startdata;
+extern size_t FileSize;
+
extern void level9_initialize();
/* routines provided by os dependent code */
diff --git a/engines/glk/level9/os_glk.cpp b/engines/glk/level9/os_glk.cpp
index 586b80840c..ab171c300c 100644
--- a/engines/glk/level9/os_glk.cpp
+++ b/engines/glk/level9/os_glk.cpp
@@ -20,6 +20,7 @@
*
*/
+#include "glk/level9/os_glk.h"
#include "glk/level9/level9_main.h"
#include "glk/level9/level9.h"
#include "common/textconsole.h"
@@ -27,9 +28,6 @@
namespace Glk {
namespace Level9 {
-#define BYTE_MAX 0xff
-#define BITS_PER_CHAR 8
-
/*---------------------------------------------------------------------*/
/* Module variables, miscellaneous other stuff */
/*---------------------------------------------------------------------*/
@@ -83,7 +81,6 @@ typedef L9UINT32 gln_uint32;
extern void save();
extern void restore();
extern gln_bool Cheating;
-extern gln_byte *startdata;
extern gln_uint32 FileSize;
/* Forward declarations of event wait and other miscellaneous functions. */
@@ -285,1022 +282,6 @@ int gln_strcasecmp(const char *s1, const char *s2) {
}
/*---------------------------------------------------------------------*/
-/* Glk port CRC functions */
-/*---------------------------------------------------------------------*/
-
-/* CRC table initialization polynomial. */
-static const gln_uint16 GLN_CRC_POLYNOMIAL = 0xa001;
-
-
-/*
- * gln_get_buffer_crc()
- *
- * Return the CRC of the bytes buffer[0..length-1].
- *
- * This algorithm is selected to match the CRCs used in L9cut. Because of
- * the odd way CRCs are padded when L9cut calculates the CRC, this function
- * allows a count of NUL padding bytes to be included within the return CRC.
- */
-static gln_uint16 gln_get_buffer_crc(const void *void_buffer, size_t length, size_t padding) {
- static int is_initialized = FALSE;
- static gln_uint16 crc_table[BYTE_MAX + 1];
-
- const char *buffer = (const char *) void_buffer;
- gln_uint16 crc;
- size_t index;
-
- /* Build the static CRC lookup table on first call. */
- if (!is_initialized) {
- for (index = 0; index < BYTE_MAX + 1; index++) {
- int bit;
-
- crc = (gln_uint16) index;
- for (bit = 0; bit < BITS_PER_CHAR; bit++)
- crc = crc & 1 ? GLN_CRC_POLYNOMIAL ^ (crc >> 1) : crc >> 1;
-
- crc_table[index] = crc;
- }
-
- is_initialized = TRUE;
-
- /* CRC lookup table self-test, after is_initialized set -- recursion. */
- assert(gln_get_buffer_crc("123456789", 9, 0) == 0xbb3d);
- }
-
- /* Start with zero in the crc, then update using table entries. */
- crc = 0;
- for (index = 0; index < length; index++)
- crc = crc_table[(crc ^ buffer[index]) & BYTE_MAX] ^ (crc >> BITS_PER_CHAR);
-
- /* Add in any requested NUL padding bytes. */
- for (index = 0; index < padding; index++)
- crc = crc_table[crc & BYTE_MAX] ^ (crc >> BITS_PER_CHAR);
-
- return crc;
-}
-
-
-/*---------------------------------------------------------------------*/
-/* Glk port game identification data and identification functions */
-/*---------------------------------------------------------------------*/
-
-/*
- * The game's name, suitable for printing out on a status line, or other
- * location where game information is relevant. It's generated on demand,
- * and may be re-requested when, say, the game changes, perhaps by moving to
- * the next part of a multipart game.
- */
-static const char *gln_gameid_game_name = nullptr;
-
-
-/*
- * The following game database is obtained from L9cut's l9data_d.h, and
- * lets us find a game's name from its data CRC. Entries marked "WANTED" in
- * l9data_d.h, and file commentary, have been removed for brevity, and the
- * file has been reformatted (patchlevel data removed).
- *
- * The version of l9data_d.h used is 050 (22 Oct 2002).
- */
-struct gln_game_table_t {
- const gln_uint16 length; /* Datafile length in bytes */
- const gln_byte checksum; /* 8-bit checksum, last datafile byte */
- const gln_uint16 crc; /* 16-bit CRC, L9cut-internal */
- const char *const name; /* Game title and platform */
-};
-typedef const gln_game_table_t *gln_game_tableref_t;
-
-static const gln_game_table_t GLN_GAME_TABLE[] = {
- {0x5323, 0xb7, 0x8af7, "Adventure Quest (Amstrad CPC/Spectrum)"},
-
- {0x630e, 0x8d, 0x7d7d, "Dungeon Adventure (Amstrad CPC)"},
- {0x630e, 0xbe, 0x3374, "Dungeon Adventure (MSX)"},
-
- {0x5eb9, 0x30, 0xe99a, "Lords of Time (Amstrad CPC)"},
- {0x5eb9, 0x5d, 0xc098, "Lords of Time (MSX)"},
- {0x5eb9, 0x6e, 0xc689, "Lords of Time (Spectrum)"},
-
- {0x5fab, 0x5c, 0xa309, "Snowball (Amstrad CPC)"},
- {0x5fab, 0x2f, 0x8aa2, "Snowball (MSX)"},
-
- {0x60c4, 0x28, 0x0154, "Return to Eden (Amstrad CPC/Commodore 64[v1])"},
- {0x6064, 0x01, 0x5b3c, "Return to Eden (BBC[v1])"},
- {0x6064, 0x95, 0x510c, "Return to Eden (Commodore 64[v2])"},
- {0x6064, 0xda, 0xe610, "Return to Eden (Commodore 64[v2] *corrupt*)"},
- {0x6064, 0xbd, 0x73ec, "Return to Eden (Atari *corrupt*)"},
- {0x6047, 0x6c, 0x17ab, "Return to Eden (BBC[v2])"},
- {0x5ca1, 0x33, 0x1c43, "Return to Eden (Spectrum[v1])"},
- {0x5cb7, 0x64, 0x0790, "Return to Eden (Spectrum[v2])"},
- {0x5cb7, 0xfe, 0x3533, "Return to Eden (MSX)"},
-
- {0x34b3, 0x20, 0xccda, "Erik the Viking (BBC/Commodore 64)"},
- {0x34b3, 0x53, 0x8f00, "Erik the Viking (Spectrum)"},
- {0x34b3, 0xc7, 0x9058, "Erik the Viking (Amstrad CPC)"},
-
- {
- 0x63be, 0xd6, 0xcf5d,
- "Emerald Isle (Atari/Commodore 64/Amstrad CPC/Spectrum)"
- },
- {0x63be, 0x0a, 0x21ed, "Emerald Isle (MSX *corrupt*)"},
- {0x378c, 0x8d, 0x3a21, "Emerald Isle (BBC)"},
-
- {0x506c, 0xf0, 0xba72, "Red Moon (BBC/Commodore 64/Amstrad CPC/MSX)"},
- {0x505d, 0x32, 0x2dcf, "Red Moon (Spectrum)"},
-
- {0x772b, 0xcd, 0xa503, "Worm in Paradise (Spectrum 128)"},
- {0x546c, 0xb7, 0x9420, "Worm in Paradise (Spectrum 48)"},
- {0x6d84, 0xf9, 0x49ae, "Worm in Paradise (Commodore 64 *corrupt*)"},
- {0x6d84, 0xc8, 0x943f, "Worm in Paradise (Commodore 64 *fixed*)"},
- {0x6030, 0x47, 0x46ad, "Worm in Paradise (Amstrad CPC)"},
- {0x5828, 0xbd, 0xe7cb, "Worm in Paradise (BBC)"},
-
- {0x7410, 0x5e, 0x60be, "Price of Magik (Spectrum 128)"},
- {0x5aa4, 0xc1, 0x10a0, "Price of Magik (Spectrum 48[v1])"},
- {0x5aa4, 0xc1, 0xeda4, "Price of Magik (Spectrum 48[v2])"},
- {0x6fc6, 0x14, 0xf9b6, "Price of Magik (Commodore 64)"},
- {0x5aa4, 0xc1, 0xbbf4, "Price of Magik (Amstrad CPC)"},
- {0x5671, 0xbc, 0xff35, "Price of Magik (BBC)"},
-
- {0x76f4, 0x5e, 0x1fe5, "Colossal Adventure /JoD (Amiga/PC)"},
- {0x76f4, 0x5a, 0xcf4b, "Colossal Adventure /JoD (ST)"},
- {0x6e60, 0x83, 0x18e0, "Adventure Quest /JoD (Amiga/PC)"},
- {0x6e5c, 0xf6, 0xd356, "Adventure Quest /JoD (ST)"},
- {0x6f0c, 0x95, 0x1f64, "Dungeon Adventure /JoD (Amiga/PC/ST)"},
-
- {0x6f70, 0x40, 0xbd91, "Colossal Adventure /JoD (MSX)"},
-
- {0x6f6e, 0x78, 0x28cd, "Colossal Adventure /JoD (Spectrum 128)"},
- {0x6970, 0xd6, 0xa820, "Adventure Quest /JoD (Spectrum 128)"},
- {0x6de8, 0x4c, 0xd795, "Dungeon Adventure /JoD (Spectrum 128)"},
-
- {
- 0x6f4d, 0xcb, 0xe8f2,
- "Colossal Adventure /JoD (Amstrad CPC128[v1]/Spectrum +3)"
- },
- {0x6f6a, 0xa5, 0x8dd2, "Colossal Adventure /JoD (Amstrad CPC128[v2])"},
- {0x6968, 0x32, 0x0c01, "Adventure Quest /JoD (Amstrad CPC128/Spectrum +3)"},
- {0x6dc0, 0x63, 0x5d95, "Dungeon Adventure /JoD (Amstrad CPC128/Spectrum +3)"},
-
- {0x5e31, 0x7c, 0xaa54, "Colossal Adventure /JoD (Amstrad CPC64)"},
- {0x5b50, 0x66, 0x1800, "Adventure Quest /JoD (Amstrad CPC64)"},
- {0x58a6, 0x24, 0xb50f, "Dungeon Adventure /JoD (Amstrad CPC64)"},
-
- {0x6c8e, 0xb6, 0x9be3, "Colossal Adventure /JoD (Commodore 64)"},
- {0x63b6, 0x2e, 0xef38, "Adventure Quest /JoD (Commodore 64)"},
- {0x6bd2, 0x65, 0xa41f, "Dungeon Adventure /JoD (Commodore 64)"},
-
- {0x5b16, 0x3b, 0xe2aa, "Colossal Adventure /JoD (Atari)"},
- {0x5b58, 0x50, 0x332e, "Adventure Quest /JoD (Atari)"},
- {0x593a, 0x80, 0x7a34, "Dungeon Adventure /JoD (Atari)"},
-
- {0x5a8e, 0xf2, 0x7cca, "Colossal Adventure /JoD (Spectrum 48)"},
- {0x5ace, 0x11, 0xdc12, "Adventure Quest /JoD (Spectrum 48)"},
- {0x58a3, 0x38, 0x8ce4, "Dungeon Adventure /JoD (Spectrum 48)"},
-
- {0x7b31, 0x6e, 0x2e2b, "Snowball /SD (Amiga/ST)"},
- {0x7d16, 0xe6, 0x5438, "Return to Eden /SD (Amiga/ST)"},
- {0x7cd9, 0x0c, 0x4df1, "Worm in Paradise /SD (Amiga/ST)"},
-
- {0x7b2f, 0x70, 0x6955, "Snowball /SD (Mac/PC/Spectrum 128)"},
- {0x7b2f, 0x70, 0x6f6c, "Snowball /SD (Amstrad CPC/Spectrum +3)"},
- {0x7d14, 0xe8, 0xfbab, "Return to Eden /SD (PC)"},
- {0x7cff, 0xf8, 0x6044, "Return to Eden /SD (Amstrad CPC/Spectrum +3)"},
- {0x7cf8, 0x24, 0x9c1c, "Return to Eden /SD (Mac)"},
- {0x7c55, 0x18, 0xdaee, "Return to Eden /SD (Spectrum 128)"},
- {
- 0x7cd7, 0x0e, 0x4feb,
- "Worm in Paradise /SD (Amstrad CPC/Mac/PC/Spectrum 128/Spectrum +3)"
- },
-
- {0x7363, 0x65, 0xa0ab, "Snowball /SD (Commodore 64)"},
- {0x772f, 0xca, 0x8602, "Return to Eden /SD (Commodore 64)"},
- {0x788d, 0x72, 0x888a, "Worm in Paradise /SD (Commodore 64)"},
-
- {0x6bf8, 0x3f, 0xc9f7, "Snowball /SD (Atari)"},
- {0x60f7, 0x68, 0xc2bc, "Return to Eden /SD (Atari)"},
- {0x6161, 0xf3, 0xe6d7, "Worm in Paradise /SD (Atari)"},
-
- {0x67a3, 0x9d, 0x1d05, "Snowball /SD (Apple ][)"},
- {0x639c, 0x8b, 0x06e2, "Return to Eden /SD (Apple ][)"},
- {0x60dd, 0xf2, 0x5bb8, "Worm in Paradise /SD (Apple ][)"},
-
- {0x6541, 0x02, 0x2e6c, "Snowball /SD (Spectrum 48)"},
- {0x5f43, 0xca, 0x828c, "Return to Eden /SD (Spectrum 48)"},
- {0x5ebb, 0xf1, 0x4dec, "Worm in Paradise /SD (Spectrum 48)"},
-
- {0x8333, 0xb7, 0xe2ac, "Adrian Mole I, pt. 1 (Commodore 64)"},
- {0x844d, 0x50, 0x5353, "Adrian Mole I, pt. 2 (Commodore 64)"},
- {0x8251, 0x5f, 0x862a, "Adrian Mole I, pt. 3 (Commodore 64)"},
- {0x7a78, 0x5e, 0x6ea3, "Adrian Mole I, pt. 4 (Commodore 64)"},
-
- {0x7c6f, 0x0f, 0xba24, "Adrian Mole I, pt. 1 (Amstrad CPC)"},
-
- {0x72fa, 0x8b, 0x6f12, "Adrian Mole I, pt. 1 (Spectrum)"},
- {0x738e, 0x5b, 0x7e3d, "Adrian Mole I, pt. 2 (Spectrum)"},
- {0x7375, 0xe5, 0x3f3e, "Adrian Mole I, pt. 3 (Spectrum)"},
- {0x78d5, 0xe3, 0xcd7d, "Adrian Mole I, pt. 4 (Spectrum)"},
-
- {0x3a31, 0xe5, 0x0bdb, "Adrian Mole I, pt. 1 (BBC)"},
- {0x37f1, 0x77, 0xd231, "Adrian Mole I, pt. 2 (BBC)"},
- {0x3900, 0x1c, 0x5d9a, "Adrian Mole I, pt. 3 (BBC)"},
- {0x3910, 0xac, 0x07f9, "Adrian Mole I, pt. 4 (BBC)"},
- {0x3ad6, 0xa7, 0x95d2, "Adrian Mole I, pt. 5 (BBC)"},
- {0x38a5, 0x0f, 0xdefc, "Adrian Mole I, pt. 6 (BBC)"},
- {0x361e, 0x7e, 0xfd9f, "Adrian Mole I, pt. 7 (BBC)"},
- {0x3934, 0x75, 0xe141, "Adrian Mole I, pt. 8 (BBC)"},
- {0x3511, 0xcc, 0xd829, "Adrian Mole I, pt. 9 (BBC)"},
- {0x38dd, 0x31, 0x2534, "Adrian Mole I, pt. 10 (BBC)"},
- {0x39c0, 0x44, 0x89df, "Adrian Mole I, pt. 11 (BBC)"},
- {0x3a12, 0x8f, 0xc2bd, "Adrian Mole I, pt. 12 (BBC)"},
-
- {0x7931, 0xb9, 0xc51b, "Adrian Mole II, pt. 1 (Commodore 64/Amstrad CPC)"},
- {0x7cdf, 0xa5, 0x43e3, "Adrian Mole II, pt. 2 (Commodore 64/Amstrad CPC)"},
- {0x7a0c, 0x97, 0x4bea, "Adrian Mole II, pt. 3 (Commodore 64/Amstrad CPC)"},
- {0x7883, 0xe2, 0xee0e, "Adrian Mole II, pt. 4 (Commodore 64/Amstrad CPC)"},
-
- {0x6841, 0x4a, 0x94e7, "Adrian Mole II, pt. 1 (Spectrum)"},
- {0x6bc0, 0x62, 0xab3d, "Adrian Mole II, pt. 2 (Spectrum)"},
- {0x692c, 0x21, 0x2015, "Adrian Mole II, pt. 3 (Spectrum)"},
- {0x670a, 0x94, 0xa2a6, "Adrian Mole II, pt. 4 (Spectrum)"},
-
- {0x593a, 0xaf, 0x30e9, "Adrian Mole II, pt. 1 (BBC)"},
- {0x57e6, 0x8a, 0xc41a, "Adrian Mole II, pt. 2 (BBC)"},
- {0x5819, 0xcd, 0x1ba0, "Adrian Mole II, pt. 3 (BBC)"},
- {0x579b, 0xad, 0xa723, "Adrian Mole II, pt. 4 (BBC)"},
-
- {0x765d, 0xcd, 0xfc02, "The Archers, pt. 1 (Commodore 64)"},
- {0x6e58, 0x07, 0xbffc, "The Archers, pt. 2 (Commodore 64)"},
- {0x7e98, 0x6a, 0x95e5, "The Archers, pt. 3 (Commodore 64)"},
- {0x81e2, 0xd5, 0xb278, "The Archers, pt. 4 (Commodore 64)"},
-
- {0x6ce5, 0x58, 0x46de, "The Archers, pt. 1 (Spectrum)"},
- {0x68da, 0xc1, 0x3b8e, "The Archers, pt. 2 (Spectrum)"},
- {0x6c67, 0x9a, 0x9a6a, "The Archers, pt. 3 (Spectrum)"},
- {0x6d91, 0xb9, 0x12a7, "The Archers, pt. 4 (Spectrum)"},
-
- {0x5834, 0x42, 0xcc9d, "The Archers, pt. 1 (BBC)"},
- {0x56dd, 0x51, 0xe582, "The Archers, pt. 2 (BBC)"},
- {0x5801, 0x53, 0xf2ef, "The Archers, pt. 3 (BBC)"},
- {0x54a4, 0x01, 0xc0ab, "The Archers, pt. 4 (BBC)"},
-
- {0x579e, 0x97, 0x9faa, "Lords of Time /T&M GD (BBC)"},
- {0x5500, 0x50, 0xca75, "Red Moon /T&M GD (BBC)"},
- {0x579a, 0x2a, 0x9373, "Price of Magik /T&M GD (BBC)"},
-
- {0x4fd2, 0x9d, 0x799a, "Lancelot, pt. 1 GD (BBC)"},
- {0x4dac, 0xa8, 0x86ed, "Lancelot, pt. 2 GD (BBC)"},
- {0x4f96, 0x22, 0x30f8, "Lancelot, pt. 3 GD (BBC)"},
-
- {0x55ce, 0xa1, 0xba12, "Scapeghost, pt. 1 GD (BBC)"},
- {0x54a6, 0xa9, 0xc9f3, "Scapeghost, pt. 2 GD (BBC)"},
- {0x51bc, 0xe3, 0x89c3, "Scapeghost, pt. 3 GD (BBC)"},
-
- {0x46ec, 0x64, 0x2300, "Knight Orc, pt. 1 GD (Amstrad CPC/Spectrum +3)"},
- {0x6140, 0x18, 0x4f66, "Knight Orc, pt. 2 GD (Amstrad CPC/Spectrum +3)"},
- {0x640e, 0xc1, 0xfc69, "Knight Orc, pt. 3 GD (Amstrad CPC/Spectrum +3)"},
-
- {0x5ff0, 0xf8, 0x3a13, "Gnome Ranger, pt. 1 GD (Amstrad CPC/Spectrum +3)"},
- {0x6024, 0x01, 0xaaa9, "Gnome Ranger, pt. 2 GD (Amstrad CPC/Spectrum +3)"},
- {0x6036, 0x3d, 0x6c6c, "Gnome Ranger, pt. 3 GD (Amstrad CPC/Spectrum +3)"},
-
- {0x69fe, 0x56, 0xecfb, "Lords of Time /T&M GD (Amstrad CPC/Spectrum +3)"},
- {0x6888, 0x8d, 0x7f6a, "Red Moon /T&M GD (Amstrad CPC/Spectrum +3)"},
- {0x5a50, 0xa9, 0xa5fa, "Price of Magik /T&M GD (Amstrad CPC/Spectrum +3)"},
-
- {0x5c7a, 0x44, 0x460e, "Lancelot, pt. 1 GD (Amstrad CPC/Spectrum +3)"},
- {0x53a2, 0x1e, 0x2fae, "Lancelot, pt. 2 GD (Amstrad CPC/Spectrum +3)"},
- {0x5914, 0x22, 0x4a31, "Lancelot, pt. 3 GD (Amstrad CPC/Spectrum +3)"},
-
- {0x5a38, 0xf7, 0x876e, "Ingrid's Back, pt. 1 GD (Amstrad CPC/Spectrum +3)"},
- {0x531a, 0xed, 0xcf3f, "Ingrid's Back, pt. 2 GD (Amstrad CPC/Spectrum +3)"},
- {0x57e4, 0x19, 0xb354, "Ingrid's Back, pt. 3 GD (Amstrad CPC/Spectrum +3)"},
-
- {0x5cbc, 0xa5, 0x0dbe, "Scapeghost, pt. 1 GD (Amstrad CPC/Spectrum +3)"},
- {0x5932, 0x4e, 0xb2f5, "Scapeghost, pt. 2 GD (Amstrad CPC/Spectrum +3)"},
- {0x5860, 0x95, 0x3227, "Scapeghost, pt. 3 GD (Amstrad CPC/Spectrum +3)"},
-
- {0x74e0, 0x92, 0x885e, "Knight Orc, pt. 1 GD (Spectrum 128)"},
- {0x6dbc, 0x97, 0x6f55, "Knight Orc, pt. 2 GD (Spectrum 128)"},
- {0x7402, 0x07, 0x385f, "Knight Orc, pt. 3 GD (Spectrum 128)"},
-
- {0x52aa, 0xdf, 0x7b5b, "Gnome Ranger, pt. 1 GD (Spectrum 128)"},
- {0x6ffa, 0xdb, 0xdde2, "Gnome Ranger, pt. 2 GD (Spectrum 128)"},
- {0x723a, 0x69, 0x039b, "Gnome Ranger, pt. 3 GD (Spectrum 128)"},
-
- {0x6f1e, 0xda, 0x2ce0, "Lords of Time /T&M GD (Spectrum 128)"},
- {0x6da0, 0xb8, 0x3802, "Red Moon /T&M GD (Spectrum 128)"},
- {0x6108, 0xdd, 0xefe7, "Price of Magik /T&M GD (Spectrum 128)"},
-
- {0x768c, 0xe8, 0x8fc6, "Lancelot, pt. 1 GD (Spectrum 128)"},
- {0x76b0, 0x1d, 0x0fcd, "Lancelot, pt. 2 GD (Spectrum 128)"},
- {0x765e, 0x4f, 0x3b73, "Lancelot, pt. 3 GD (Spectrum 128)"},
-
- {0x76a0, 0x3a, 0xb803, "Ingrid's Back, pt. 1 GD (Spectrum 128)"},
- {0x7674, 0x0b, 0xe92f, "Ingrid's Back, pt. 2 GD (Spectrum 128)"},
- {0x765e, 0xba, 0x086d, "Ingrid's Back, pt. 3 GD (Spectrum 128)"},
-
- {0x762e, 0x82, 0x8848, "Scapeghost, pt. 1 GD (Spectrum 128)"},
- {0x5bd6, 0x35, 0x79ef, "Scapeghost, pt. 2 GD (Spectrum 128)"},
- {0x6fa8, 0xa4, 0x62c2, "Scapeghost, pt. 3 GD (Spectrum 128)"},
-
- {0xbb93, 0x36, 0x6a05, "Knight Orc, pt. 1 (Amiga)"},
- {0xbb6e, 0xad, 0x4d40, "Knight Orc, pt. 1 (ST)"},
- {0xc58e, 0x4a, 0x4e9d, "Knight Orc, pt. 2 (Amiga/ST)"},
- {0xcb9a, 0x0f, 0x0804, "Knight Orc, pt. 3 (Amiga/ST)"},
-
- {0xbb6e, 0xa6, 0x9753, "Knight Orc, pt. 1 (PC)"},
- {0xc58e, 0x43, 0xe9ce, "Knight Orc, pt. 2 (PC)"},
- {0xcb9a, 0x08, 0x6c36, "Knight Orc, pt. 3 (PC)"},
-
- {0x898a, 0x43, 0xfc8b, "Knight Orc, pt. 1 (Apple ][)"},
- {0x8b9f, 0x61, 0x7288, "Knight Orc, pt. 2 (Apple ][)"},
- {0x8af9, 0x61, 0x7542, "Knight Orc, pt. 3 (Apple ][)"},
-
- {0x8970, 0x6b, 0x3c7b, "Knight Orc, pt. 1 (Commodore 64 Gfx)"},
- {0x8b90, 0x4e, 0x098c, "Knight Orc, pt. 2 (Commodore 64 Gfx)"},
- {0x8aea, 0x4e, 0xca54, "Knight Orc, pt. 3 (Commodore 64 Gfx)"},
-
- {0x86d0, 0xb7, 0xadbd, "Knight Orc, pt. 1 (Spectrum 48)"},
- {0x8885, 0x22, 0xe293, "Knight Orc, pt. 2 (Spectrum 48)"},
- {0x87e5, 0x0e, 0xdc33, "Knight Orc, pt. 3 (Spectrum 48)"},
-
- {0xb1a9, 0x80, 0x5fb7, "Gnome Ranger, pt. 1 (Amiga/ST)"},
- {0xab9d, 0x31, 0xbe6d, "Gnome Ranger, pt. 2 (Amiga/ST)"},
- {0xae28, 0x87, 0xb6b6, "Gnome Ranger, pt. 3 (Amiga/ST)"},
-
- {0xb0ec, 0xc2, 0x0053, "Gnome Ranger, pt. 1 (ST[v1])"},
- {0xaf82, 0x83, 0x19f7, "Gnome Ranger, pt. 2 (ST[v1])"},
-
- {0xb1aa, 0xad, 0xaf47, "Gnome Ranger, pt. 1 (PC)"},
- {0xb19e, 0x92, 0x8f96, "Gnome Ranger, pt. 1 (ST[v2])"},
- {0xab8b, 0xbf, 0x31e6, "Gnome Ranger, pt. 2 (PC/ST[v2])"},
- {0xae16, 0x81, 0x8741, "Gnome Ranger, pt. 3 (PC/ST[v2])"},
-
- {0xad41, 0xa8, 0x42c5, "Gnome Ranger, pt. 1 (Commodore 64 TO)"},
- {0xa735, 0xf7, 0x2e08, "Gnome Ranger, pt. 2 (Commodore 64 TO)"},
- {0xa9c0, 0x9e, 0x0d70, "Gnome Ranger, pt. 3 (Commodore 64 TO)"},
-
- {0x908e, 0x0d, 0x58a7, "Gnome Ranger, pt. 1 (Commodore 64 Gfx)"},
- {0x8f6f, 0x0a, 0x411a, "Gnome Ranger, pt. 2 (Commodore 64 Gfx)"},
- {0x9060, 0xbb, 0xe75d, "Gnome Ranger, pt. 3 (Commodore 64 Gfx)"},
-
- {0x8aab, 0xc0, 0xde5f, "Gnome Ranger, pt. 1 (Spectrum 48)"},
- {0x8ac8, 0x9a, 0xc89b, "Gnome Ranger, pt. 2 (Spectrum 48)"},
- {0x8a93, 0x4f, 0x10cc, "Gnome Ranger, pt. 3 (Spectrum 48)"},
-
- {0xb57c, 0x44, 0x7779, "Lords of Time /T&M (PC)"},
- {0xa69e, 0x6c, 0xb268, "Red Moon /T&M (PC)"},
- {0xbac7, 0x7f, 0xddb2, "Price of Magik /T&M (PC)"},
-
- {0xb579, 0x89, 0x3e89, "Lords of Time /T&M (ST)"},
- {0xa698, 0x41, 0xcaca, "Red Moon /T&M (ST)"},
- {0xbac4, 0x80, 0xa750, "Price of Magik /T&M (ST)"},
-
- {0xb576, 0x2a, 0x7239, "Lords of Time /T&M (Amiga)"},
- {0xa692, 0xd1, 0x6a99, "Red Moon /T&M (Amiga)"},
- {0xbaca, 0x3a, 0x221b, "Price of Magik /T&M (Amiga)"},
-
- {0xb563, 0x6a, 0x0c5c, "Lords of Time /T&M (Mac)"},
- {0xa67c, 0xb8, 0xff41, "Red Moon /T&M (Mac)"},
- {0xbab2, 0x87, 0x09f5, "Price of Magik /T&M (Mac)"},
-
- {0xb38c, 0x37, 0x9f8e, "Lords of Time /T&M (Commodore 64 TO)"},
- {0xa4e2, 0xa6, 0x016d, "Red Moon /T&M (Commodore 64 TO)"},
- {0xb451, 0xa8, 0x2682, "Price of Magik /T&M (Commodore 64 TO)"},
-
- {0x9070, 0x43, 0x45d4, "Lords of Time /T&M (Commodore 64 Gfx)"},
- {0x903f, 0x6b, 0x603e, "Red Moon /T&M (Commodore 64 Gfx)"},
- {0x8f51, 0xb2, 0x6c9a, "Price of Magik /T&M (Commodore 64 Gfx)"},
-
- {0x8950, 0xa1, 0xbb16, "Lords of Time /T&M (Spectrum 48)"},
- {0x8813, 0x11, 0x22de, "Red Moon /T&M (Spectrum 48)"},
- {0x8a60, 0x2a, 0x29ed, "Price of Magik /T&M (Spectrum 48)"},
-
- {0xb260, 0xe5, 0xc5b2, "Lords of Time /T&M (PC/ST *USA*)"},
- {0xa3a4, 0xdf, 0x6732, "Red Moon /T&M (PC/ST *USA*)"},
- {0xb7a0, 0x7e, 0x2226, "Price of Magik /T&M (PC/ST *USA*)"},
-
- {0xb257, 0xf8, 0xfbd5, "Lords of Time /T&M (Amiga *USA*)"},
- {0xa398, 0x82, 0xd031, "Red Moon /T&M (Amiga *USA*)"},
- {0xb797, 0x1f, 0x84a9, "Price of Magik /T&M (Amiga *USA*)"},
-
- {0x8d78, 0x3a, 0xba6e, "Lords of Time /T&M (Commodore 64 Gfx *USA*)"},
- {0x8d56, 0xd3, 0x146a, "Red Moon /T&M (Commodore 64 Gfx *USA*)"},
- {0x8c46, 0xf0, 0xcaf6, "Price of Magik /T&M (Commodore 64 Gfx *USA*)"},
-
- {0xc0cf, 0x4e, 0xb7fa, "Lancelot, pt. 1 (Amiga/PC/ST)"},
- {0xd5e9, 0x6a, 0x4192, "Lancelot, pt. 2 (Amiga/PC/ST)"},
- {0xbb8f, 0x1a, 0x7487, "Lancelot, pt. 3 (Amiga/PC/ST)"},
-
- {0xc0bd, 0x57, 0x6ef1, "Lancelot, pt. 1 (Mac)"},
- {0xd5d7, 0x99, 0x770b, "Lancelot, pt. 2 (Mac)"},
- {0xbb7d, 0x17, 0xbc42, "Lancelot, pt. 3 (Mac)"},
-
- {0xb4c9, 0x94, 0xd784, "Lancelot, pt. 1 (Commodore 64 TO)"},
- {0xb729, 0x51, 0x8ee5, "Lancelot, pt. 2 (Commodore 64 TO)"},
- {0xb702, 0xe4, 0x1809, "Lancelot, pt. 3 (Commodore 64 TO)"},
-
- {0x8feb, 0xba, 0xa800, "Lancelot, pt. 1 (Commodore 64 Gfx)"},
- {0x8f6b, 0xfa, 0x0f7e, "Lancelot, pt. 2 (Commodore 64 Gfx)"},
- {0x8f71, 0x2f, 0x0ddc, "Lancelot, pt. 3 (Commodore 64 Gfx)"},
-
- {0x8ade, 0xf2, 0xfffb, "Lancelot, pt. 1 (Spectrum 48)"},
- {0x8b0e, 0xfb, 0x0bab, "Lancelot, pt. 2 (Spectrum 48)"},
- {0x8ab3, 0xc1, 0xcb62, "Lancelot, pt. 3 (Spectrum 48)"},
-
- {0xbba4, 0x94, 0x0871, "Lancelot, pt. 1 (Amiga/PC *USA*)"},
- {0xd0c0, 0x56, 0x8c48, "Lancelot, pt. 2 (Amiga/PC *USA*)"},
- {0xb6ac, 0xc6, 0xaea0, "Lancelot, pt. 3 (Amiga/PC *USA*)"},
-
- {0x8afc, 0x07, 0x8321, "Lancelot, pt. 1 (Commodore 64 Gfx *USA*)"},
- {0x8aec, 0x13, 0x6791, "Lancelot, pt. 2 (Commodore 64 Gfx *USA*)"},
- {0x8aba, 0x0d, 0x5602, "Lancelot, pt. 3 (Commodore 64 Gfx *USA*)"},
-
- {0xd19b, 0xad, 0x306d, "Ingrid's Back, pt. 1 (PC)"},
- {0xc5a5, 0xfe, 0x3c98, "Ingrid's Back, pt. 2 (PC)"},
- {0xd7ae, 0x9e, 0x1878, "Ingrid's Back, pt. 3 (PC)"},
-
- {0xd188, 0x13, 0xdc60, "Ingrid's Back, pt. 1 (Amiga)"},
- {0xc594, 0x03, 0xea95, "Ingrid's Back, pt. 2 (Amiga)"},
- {0xd79f, 0xb5, 0x1661, "Ingrid's Back, pt. 3 (Amiga)"},
-
- {0xd183, 0x83, 0xef72, "Ingrid's Back, pt. 1 (ST)"},
- {0xc58f, 0x65, 0xf337, "Ingrid's Back, pt. 2 (ST)"},
- {0xd79a, 0x57, 0x49c5, "Ingrid's Back, pt. 3 (ST)"},
-
- {0xb770, 0x03, 0x9a03, "Ingrid's Back, pt. 1 (Commodore 64 TO)"},
- {0xb741, 0xb6, 0x2aa5, "Ingrid's Back, pt. 2 (Commodore 64 TO)"},
- {0xb791, 0xa1, 0xd065, "Ingrid's Back, pt. 3 (Commodore 64 TO)"},
-
- {0x9089, 0xce, 0xc5e2, "Ingrid's Back, pt. 1 (Commodore 64 Gfx)"},
- {0x908d, 0x80, 0x30c7, "Ingrid's Back, pt. 2 (Commodore 64 Gfx)"},
- {0x909e, 0x9f, 0xdecc, "Ingrid's Back, pt. 3 (Commodore 64 Gfx)"},
-
- {0x8ab7, 0x68, 0xee57, "Ingrid's Back, pt. 1 (Spectrum 48)"},
- {0x8b1e, 0x84, 0x2538, "Ingrid's Back, pt. 2 (Spectrum 48)"},
- {0x8b1c, 0xa8, 0x9262, "Ingrid's Back, pt. 3 (Spectrum 48)"},
-
- {0xbeab, 0x2d, 0x94d9, "Scapeghost, pt. 1 (Amiga)"},
- {0xc132, 0x14, 0x7adc, "Scapeghost, pt. 1 (Amiga *bak*)"},
- {0xbe94, 0xcc, 0x04b8, "Scapeghost, pt. 1 (PC/ST)"},
- {0x99bd, 0x65, 0x032e, "Scapeghost, pt. 2 (Amiga/PC/ST)"},
- {0xbcb6, 0x7a, 0x7d4f, "Scapeghost, pt. 3 (Amiga/PC/ST)"},
-
- {0x9058, 0xcf, 0x9748, "Scapeghost, pt. 1 (Commodore 64 Gfx)"},
- {0x8f43, 0xc9, 0xeefd, "Scapeghost, pt. 2 (Commodore 64 Gfx)"},
- {0x90ac, 0x68, 0xb4a8, "Scapeghost, pt. 3 (Commodore 64 Gfx)"},
-
- {0x8a21, 0xf4, 0xd9e4, "Scapeghost, pt. 1 (Spectrum 48)"},
- {0x8a12, 0xe3, 0xc2ff, "Scapeghost, pt. 2 (Spectrum 48)"},
- {0x8a16, 0xcc, 0x4f3b, "Scapeghost, pt. 3 (Spectrum 48)"},
-
- {0x3ebb, 0x00, 0xf6dc, "Champion of the Raj (English) 1/2 GD (Amiga)"},
- {0x0fd8, 0x00, 0xf250, "Champion of the Raj (English) 2/2 GD (Amiga)"},
-
- {0x3e8f, 0x00, 0x5599, "Champion of the Raj (English) 1/2 GD (ST)"},
-
- {0x3e4f, 0x00, 0xb202, "Champion of the Raj (English) 1/2 GD (PC)"},
- {0x14a3, 0x00, 0xa288, "Champion of the Raj (English) 2/2 GD (PC)"},
-
- {0x1929, 0x00, 0xd4b2, "Champion of the Raj (demo), 1/2 GD (ST)"},
- {0x40e0, 0x02, 0x080d, "Champion of the Raj (demo), 2/2 GD (ST)"},
-
- {0x4872, 0x00, 0x9515, "Champion of the Raj (German) 1/2 GD (Amiga)"},
- {0x11f5, 0x00, 0xbf39, "Champion of the Raj (German) 2/2 GD (Amiga)"},
-
- {0x4846, 0x00, 0xd9c1, "Champion of the Raj (German) 1/2 GD (ST)"},
- {0x11f5, 0x00, 0x7aa4, "Champion of the Raj (German) 2/2 GD (ST)"},
-
- {0x110f, 0x00, 0x4b57, "Champion of the Raj (French) 2/2 GD (ST)"},
-
- {0x0000, 0x00, 0x0000, nullptr}
-};
-
-
-/*
- * The following patch database is obtained from L9cut's l9data_p.h, and
- * allows CRCs from patched games to be translated into original CRCs for
- * lookup in the game database above. Some file commentary has been removed
- * for brevity, and unused patch fields deleted.
- *
- * The version of l9data_p.h used is 012 (22 May 2001).
- */
-struct gln_patch_table_t {
- const gln_uint16 length; /* Datafile length in bytes */
- const gln_byte orig_checksum; /* 8-bit checksum, last datafile byte */
- const gln_uint16 orig_crc; /* 16-bit CRC, L9cut-internal */
- const gln_byte patch_checksum; /* 8-bit checksum, last datafile byte */
- const gln_uint16 patch_crc; /* 16-bit CRC, L9cut-internal */
-};
-typedef const gln_patch_table_t *gln_patch_tableref_t;
-
-static const gln_patch_table_t GLN_PATCH_TABLE[] = {
- /* Price of Magik (Spectrum128) */
- {0x7410, 0x5e, 0x60be, 0x70, 0x6cef},
-
- /* Price of Magik (Commodore 64) */
- {0x6fc6, 0x14, 0xf9b6, 0x26, 0x3326},
-
- /* Price of Magik (Spectrum48) */
- {0x5aa4, 0xc1, 0xeda4, 0xd3, 0xed35},
- {0x5aa4, 0xc1, 0xeda4, 0xc1, 0x8a65},
-
- /* Colossal Adventure /JoD (Amiga/PC) */
- {0x76f4, 0x5e, 0x1fe5, 0xea, 0x1305},
- {0x76f4, 0x5e, 0x1fe5, 0xb5, 0x901f},
- {0x76f4, 0x5e, 0x1fe5, 0x5e, 0x6ea1},
-
- /* Colossal Adventure /JoD (ST) */
- {0x76f4, 0x5a, 0xcf4b, 0xe6, 0x012a},
- {0x76f4, 0x5a, 0xcf4b, 0xb1, 0x40b1},
-
- /* Adventure Quest /JoD (Amiga/PC) */
- {0x6e60, 0x83, 0x18e0, 0x4c, 0xcfb0},
- {0x6e60, 0x83, 0x18e0, 0xfa, 0x9b3b},
- {0x6e60, 0x83, 0x18e0, 0x83, 0x303d},
-
- /* Adventure Quest /JoD (ST) */
- {0x6e5c, 0xf6, 0xd356, 0xbf, 0xede7},
- {0x6e5c, 0xf6, 0xd356, 0x6d, 0x662d},
-
- /* Dungeon Adventure /JoD (Amiga/PC/ST) */
- {0x6f0c, 0x95, 0x1f64, 0x6d, 0x2443},
- {0x6f0c, 0x95, 0x1f64, 0x0c, 0x6066},
- {0x6f0c, 0x95, 0x1f64, 0x96, 0xdaca},
- {0x6f0c, 0x95, 0x1f64, 0x95, 0x848d},
-
- /* Colossal Adventure /JoD (Spectrum128) */
- {0x6f6e, 0x78, 0x28cd, 0xf8, 0xda5f},
- {0x6f6e, 0x78, 0x28cd, 0x77, 0x5b4e},
-
- /* Adventure Quest /JoD (Spectrum128) */
- {0x6970, 0xd6, 0xa820, 0x3b, 0x1870},
- {0x6970, 0xd6, 0xa820, 0xd5, 0x13c4},
-
- /* Dungeon Adventure /JoD (Spectrum128) */
- {0x6de8, 0x4c, 0xd795, 0xa2, 0x3eea},
- {0x6de8, 0x4c, 0xd795, 0x4b, 0xad30},
-
- /* Colossal Adventure /JoD (Amstrad CPC) */
- {0x6f4d, 0xcb, 0xe8f2, 0x4b, 0xb384},
- {0x6f4d, 0xcb, 0xe8f2, 0xca, 0x96e7},
-
- /* Adventure Quest /JoD (Amstrad CPC) */
- {0x6968, 0x32, 0x0c01, 0x97, 0xdded},
- {0x6968, 0x32, 0x0c01, 0x31, 0xe8c2},
-
- /* Dungeon Adventure /JoD (Amstrad CPC) */
- {0x6dc0, 0x63, 0x5d95, 0xb9, 0xc963},
- {0x6dc0, 0x63, 0x5d95, 0x62, 0x79f7},
-
- /* Colossal Adventure /JoD (Commodore 64) */
- {0x6c8e, 0xb6, 0x9be3, 0x36, 0x6971},
- {0x6c8e, 0xb6, 0x9be3, 0xb5, 0xeba0},
-
- /* Adventure Quest /JoD (Commodore 64) */
- {0x63b6, 0x2e, 0xef38, 0x93, 0x4e68},
- {0x63b6, 0x2e, 0xef38, 0x2d, 0x54dc},
-
- /* Dungeon Adventure /JoD (Commodore 64) */
- {0x6bd2, 0x65, 0xa41f, 0xbb, 0x4260},
- {0x6bd2, 0x65, 0xa41f, 0x64, 0xdf5a},
-
- /* Colossal Adventure /JoD (Spectrum48) */
- {0x5a8e, 0xf2, 0x7cca, 0x72, 0x8e58},
- {0x5a8e, 0xf2, 0x7cca, 0xf1, 0x0c89},
- {0x5a8e, 0xf2, 0x7cca, 0xf2, 0x2c96},
-
- /* Adventure Quest /JoD (Spectrum48) */
- {0x5ace, 0x11, 0xdc12, 0x76, 0x8663},
- {0x5ace, 0x11, 0xdc12, 0x10, 0xa757},
- {0x5ace, 0x11, 0xdc12, 0x11, 0xf118},
-
- /* Dungeon Adventure /JoD (Spectrum48) */
- {0x58a3, 0x38, 0x8ce4, 0x8e, 0xb61a},
- {0x58a3, 0x38, 0x8ce4, 0x37, 0x34c0},
- {0x58a3, 0x38, 0x8ce4, 0x38, 0xa1ee},
-
- /* Snowball /SD (Amiga/ST) */
- {0x7b31, 0x6e, 0x2e2b, 0xe5, 0x6017},
-
- /* Return to Eden /SD (Amiga/ST) */
- {0x7d16, 0xe6, 0x5438, 0x5d, 0xc770},
-
- /* Worm in Paradise /SD (Amiga/ST) */
- {0x7cd9, 0x0c, 0x4df1, 0x83, 0xe997},
-
- /* Snowball /SD (PC/Spectrum128) */
- {0x7b2f, 0x70, 0x6955, 0xe7, 0x0af4},
- {0x7b2f, 0x70, 0x6955, 0x70, 0x1179},
-
- /* Return to Eden /SD (PC) */
- {0x7d14, 0xe8, 0xfbab, 0x5f, 0xeab9},
- {0x7d14, 0xe8, 0xfbab, 0xe8, 0xe216},
-
- /* Return to Eden /SD (Amstrad CPC) */
- {0x7cff, 0xf8, 0x6044, 0x6f, 0xbb57},
-
- /* Return to Eden /SD (Spectrum128) */
- {0x7c55, 0x18, 0xdaee, 0x8f, 0x01fd},
-
- /* Worm in Paradise /SD (Amstrad CPC/PC/Spectrum128) */
- {0x7cd7, 0x0e, 0x4feb, 0x85, 0x4eae},
- {0x7cd7, 0x0e, 0x4feb, 0x0e, 0xb02c},
-
- /* Snowball /SD (Commodore 64) */
- {0x7363, 0x65, 0xa0ab, 0xdc, 0xca6a},
-
- /* Return to Eden /SD (Commodore 64) */
- {0x772f, 0xca, 0x8602, 0x41, 0x9bd0},
-
- /* Worm in Paradise /SD (Commodore 64) */
- {0x788d, 0x72, 0x888a, 0xe9, 0x4cce},
-
- /* Snowball /SD (Atari) */
- {0x6bf8, 0x3f, 0xc9f7, 0x96, 0x1908},
-
- /* Return to Eden /SD (Atari) */
- {0x60f7, 0x68, 0xc2bc, 0xdf, 0xd3ae},
-
- /* Worm in Paradise /SD (Atari) */
- {0x6161, 0xf3, 0xe6d7, 0x6a, 0xe232},
-
- /* Snowball /SD (Spectrum48) */
- {0x6541, 0x02, 0x2e6c, 0x79, 0xb80c},
- {0x6541, 0x02, 0x2e6c, 0x02, 0x028a},
-
- /* Return to Eden /SD (Spectrum48) */
- {0x5f43, 0xca, 0x828c, 0x41, 0x9f5e},
- {0x5f43, 0xca, 0x828c, 0xca, 0x6e1b},
-
- /* Worm in Paradise /SD (Spectrum48) */
- {0x5ebb, 0xf1, 0x4dec, 0x68, 0x4909},
- {0x5ebb, 0xf1, 0x4dec, 0xf1, 0xcc1a},
-
- /* Knight Orc, pt. 1 (Amiga) */
- {0xbb93, 0x36, 0x6a05, 0xad, 0xe52d},
-
- /* Knight Orc, pt. 1 (ST) */
- {0xbb6e, 0xad, 0x4d40, 0x24, 0x3bcd},
-
- /* Knight Orc, pt. 2 (Amiga/ST) */
- {0xc58e, 0x4a, 0x4e9d, 0xc1, 0xe2bf},
-
- /* Knight Orc, pt. 3 (Amiga/ST) */
- {0xcb9a, 0x0f, 0x0804, 0x86, 0x6487},
-
- /* Knight Orc, pt. 1 (PC) */
- {0xbb6e, 0xa6, 0x9753, 0x1d, 0x2e7f},
- {0xbb6e, 0xa6, 0x9753, 0xa6, 0x001d},
-
- /* Knight Orc, pt. 2 (PC) */
- {0xc58e, 0x43, 0xe9ce, 0xba, 0x5e4c},
- {0xc58e, 0x43, 0xe9ce, 0x43, 0xa8f0},
-
- /* Knight Orc, pt. 3 (PC) */
- {0xcb9a, 0x08, 0x6c36, 0x7f, 0xf0d4},
- {0xcb9a, 0x08, 0x6c36, 0x08, 0x2d08},
-
- /* Knight Orc, pt. 1 (Commodore 64 Gfx) */
- {0x8970, 0x6b, 0x3c7b, 0xe2, 0xb6f3},
-
- /* Knight Orc, pt. 1 (Spectrum48) */
- {0x86d0, 0xb7, 0xadbd, 0x2e, 0x43e1},
-
- /* Gnome Ranger, pt. 1 (Amiga/ST) */
- {0xb1a9, 0x80, 0x5fb7, 0xf7, 0x5c6c},
-
- /* Gnome Ranger, pt. 2 (Amiga/ST) */
- {0xab9d, 0x31, 0xbe6d, 0xa8, 0xcb96},
-
- /* Gnome Ranger, pt. 3 (Amiga/ST) */
- {0xae28, 0x87, 0xb6b6, 0xfe, 0x760c},
-
- /* Gnome Ranger, pt. 1 (PC) */
- {0xb1aa, 0xad, 0xaf47, 0x24, 0x5cfd},
- {0xb1aa, 0xad, 0xaf47, 0xad, 0xe0ed},
-
- /* Gnome Ranger, pt. 1 (ST-var) */
- {0xb19e, 0x92, 0x8f96, 0x09, 0x798c},
-
- /* Gnome Ranger, pt. 2 (PC/ST-var) */
- {0xab8b, 0xbf, 0x31e6, 0x36, 0x811c},
- {0xab8b, 0xbf, 0x31e6, 0xbf, 0x8ff3},
-
- /* Gnome Ranger, pt. 3 (PC/ST-var) */
- {0xae16, 0x81, 0x8741, 0xf8, 0x47fb},
- {0xae16, 0x81, 0x8741, 0x81, 0xc8eb},
-
- /* Gnome Ranger, pt. 1 (Commodore 64 TO) */
- {0xad41, 0xa8, 0x42c5, 0x1f, 0x7d1e},
-
- /* Gnome Ranger, pt. 2 (Commodore 64 TO) */
- {0xa735, 0xf7, 0x2e08, 0x6e, 0x780e},
-
- /* Gnome Ranger, pt. 3 (Commodore 64 TO) */
- {0xa9c0, 0x9e, 0x0d70, 0x15, 0x3e6b},
-
- /* Gnome Ranger, pt. 1 (Commodore 64 Gfx) */
- {0x908e, 0x0d, 0x58a7, 0x84, 0xab1d},
-
- /* Gnome Ranger, pt. 2 (Commodore 64 Gfx) */
- {0x8f6f, 0x0a, 0x411a, 0x81, 0x12bc},
-
- /* Gnome Ranger, pt. 3 (Commodore 64 Gfx) */
- {0x9060, 0xbb, 0xe75d, 0x32, 0x14e7},
-
- /* Lords of Time /T&M (PC) */
- {0xb57c, 0x44, 0x7779, 0xbb, 0x31a6},
- {0xb57c, 0x44, 0x7779, 0x44, 0xea72},
-
- /* Red Moon /T&M (PC) */
- {0xa69e, 0x6c, 0xb268, 0xe3, 0x4cef},
- {0xa69e, 0x6c, 0xb268, 0x6c, 0x3799},
-
- /* Price of Magik /T&M (PC) */
- {0xbac7, 0x7f, 0xddb2, 0xf6, 0x6ab3},
- {0xbac7, 0x7f, 0xddb2, 0x7f, 0x905c},
-
- /* Lords of Time /T&M (ST) */
- {0xb579, 0x89, 0x3e89, 0x00, 0xa2b7},
-
- /* Red Moon /T&M (ST) */
- {0xa698, 0x41, 0xcaca, 0xb8, 0xeeac},
-
- /* Price of Magik /T&M (ST) */
- {0xbac4, 0x80, 0xa750, 0xf7, 0xe030},
-
- /* Lords of Time /T&M (Amiga) */
- {0xb576, 0x2a, 0x7239, 0xa1, 0x2ea6},
-
- /* Red Moon /T&M (Amiga) */
- {0xa692, 0xd1, 0x6a99, 0x48, 0x50ff},
-
- /* Price of Magik /T&M (Amiga) */
- {0xbaca, 0x3a, 0x221b, 0xb1, 0x55bb},
-
- /* Lords of Time /T&M (Commodore 64 TO) */
- {0xb38c, 0x37, 0x9f8e, 0xae, 0xc6b1},
-
- /* Red Moon /T&M (Commodore 64 TO) */
- {0xa4e2, 0xa6, 0x016d, 0x1d, 0x31ab},
-
- /* Price of Magik /T&M (Commodore 64 TO) */
- {0xb451, 0xa8, 0x2682, 0x1f, 0x5de2},
-
- /* Lords of Time /T&M (Commodore 64 Gfx) */
- {0x9070, 0x43, 0x45d4, 0xba, 0x02eb},
-
- /* Red Moon /T&M (Commodore 64 Gfx) */
- {0x903f, 0x6b, 0x603e, 0xe2, 0x9f59},
-
- /* Price of Magik /T&M (Commodore 64 Gfx) */
- {0x8f51, 0xb2, 0x6c9a, 0x29, 0xde3b},
-
- /* Lords of Time /T&M (Spectrum48) */
- {0x8950, 0xa1, 0xbb16, 0x18, 0x2828},
- {0x8950, 0xa1, 0xbb16, 0xa1, 0x1ea2},
-
- /* Red Moon /T&M (Spectrum48) */
- {0x8813, 0x11, 0x22de, 0x88, 0x18b8},
- {0x8813, 0x11, 0x22de, 0x11, 0xd0cd},
-
- /* Price of Magik /T&M (Spectrum48) */
- {0x8a60, 0x2a, 0x29ed, 0xa1, 0x5e4d},
-
- /* Lancelot, pt. 1 (Amiga/PC/ST) */
- {0xc0cf, 0x4e, 0xb7fa, 0xc5, 0x4400},
-
- /* Lancelot, pt. 2 (Amiga/PC/ST) */
- {0xd5e9, 0x6a, 0x4192, 0xe1, 0x3b1e},
-
- /* Lancelot, pt. 3 (Amiga/PC/ST) */
- {0xbb8f, 0x1a, 0x7487, 0x91, 0x877d},
-
- /* Lancelot, pt. 1 (Commodore 64 TO) */
- {0xb4c9, 0x94, 0xd784, 0x0b, 0x203e},
-
- /* Lancelot, pt. 2 (Commodore 64 TO) */
- {0xb729, 0x51, 0x8ee5, 0xc8, 0xf1c9},
-
- /* Lancelot, pt. 3 (Commodore 64 TO) */
- {0xb702, 0xe4, 0x1809, 0x5b, 0x25b2},
-
- /* Lancelot, pt. 1 (Commodore 64 Gfx) */
- {0x8feb, 0xba, 0xa800, 0x31, 0x5bfa},
-
- /* Lancelot, pt. 2 (Commodore 64 Gfx) */
- {0x8f6b, 0xfa, 0x0f7e, 0x71, 0x75f2},
-
- /* Lancelot, pt. 3 (Commodore 64 Gfx) */
- {0x8f71, 0x2f, 0x0ddc, 0xa6, 0x3e87},
-
- /* Ingrid's Back, pt. 1 (PC) */
- {0xd19b, 0xad, 0x306d, 0x24, 0x4504},
- {0xd19b, 0xad, 0x306d, 0xad, 0x878e},
-
- /* Ingrid's Back, pt. 2 (PC) */
- {0xc5a5, 0xfe, 0x3c98, 0x75, 0x8950},
- {0xc5a5, 0xfe, 0x3c98, 0xfe, 0x8b7b},
-
- /* Ingrid's Back, pt. 3 (PC) */
- {0xd7ae, 0x9e, 0x1878, 0x15, 0xadb0},
- {0xd7ae, 0x9e, 0x1878, 0x9e, 0xaf9b},
-
- /* Ingrid's Back, pt. 1 (Amiga) */
- {0xd188, 0x13, 0xdc60, 0x8a, 0x755c},
-
- /* Ingrid's Back, pt. 2 (Amiga) */
- {0xc594, 0x03, 0xea95, 0x7a, 0xb5a8},
-
- /* Ingrid's Back, pt. 3 (Amiga) */
- {0xd79f, 0xb5, 0x1661, 0x2c, 0xbf5d},
-
- /* Ingrid's Back, pt. 1 (ST) */
- {0xd183, 0x83, 0xef72, 0xfa, 0xb04f},
-
- /* Ingrid's Back, pt. 2 (ST) */
- {0xc58f, 0x65, 0xf337, 0xdc, 0x900a},
-
- /* Ingrid's Back, pt. 3 (ST) */
- {0xd79a, 0x57, 0x49c5, 0xce, 0xe0f9},
-
- /* Ingrid's Back, pt. 1 (Commodore 64 TO) */
- {0xb770, 0x03, 0x9a03, 0x7a, 0xdc6a},
-
- /* Ingrid's Back, pt. 2 (Commodore 64 TO) */
- {0xb741, 0xb6, 0x2aa5, 0x2d, 0x5a6c},
-
- /* Ingrid's Back, pt. 3 (Commodore 64 TO) */
- {0xb791, 0xa1, 0xd065, 0x18, 0xaa0c},
-
- /* Ingrid's Back, pt. 1 (Commodore 64 Gfx) */
- {0x9089, 0xce, 0xc5e2, 0x44, 0xeff4},
-
- /* Ingrid's Back, pt. 2 (Commodore 64 Gfx) */
- {0x908d, 0x80, 0x30c7, 0xf6, 0x2a11},
-
- /* Ingrid's Back, pt. 3 (Commodore 64 Gfx) */
- {0x909e, 0x9f, 0xdecc, 0x15, 0xf4da},
-
- {0x0000, 0x00, 0x0000, 0x00, 0x0000},
-};
-
-
-/*
- * gln_gameid_lookup_game()
- * gln_gameid_lookup_patch()
- *
- * Look up and return game table and patch table entries given a game's
- * length, checksum, and CRC. Returns the entry, or nullptr if not found.
- */
-static gln_game_tableref_t gln_gameid_lookup_game(gln_uint16 length, gln_byte checksum,
- gln_uint16 crc, int ignore_crc) {
- gln_game_tableref_t game;
-
- for (game = GLN_GAME_TABLE; game->length; game++) {
- if (game->length == length && game->checksum == checksum
- && (ignore_crc || game->crc == crc))
- break;
- }
-
- return game->length ? game : nullptr;
-}
-
-static gln_patch_tableref_t gln_gameid_lookup_patch(gln_uint16 length, gln_byte checksum,
- gln_uint16 crc) {
- gln_patch_tableref_t patch;
-
- for (patch = GLN_PATCH_TABLE; patch->length; patch++) {
- if (patch->length == length && patch->patch_checksum == checksum
- && patch->patch_crc == crc)
- break;
- }
-
- return patch->length ? patch : nullptr;
-}
-
-
-/*
- * gln_gameid_identify_game()
- *
- * Identify a game from its data length, checksum, and CRC. Returns the
- * entry of the game in the game table, or nullptr if not found.
- *
- * This function uses startdata and FileSize from the core interpreter.
- * These aren't advertised symbols, so be warned.
- */
-static gln_game_tableref_t gln_gameid_identify_game() {
- gln_uint16 length, crc;
- gln_byte checksum;
- int is_version2;
- gln_game_tableref_t game;
- gln_patch_tableref_t patch;
-
- /* If the data file appears too short for a header, give up now. */
- if (FileSize < 30)
- return nullptr;
-
- /*
- * Find the version of the game, and the length of game data. This logic
- * is taken from L9cut, with calcword() replaced by simple byte comparisons.
- * If the length exceeds the available data, fail.
- */
- assert(startdata);
- is_version2 = startdata[4] == 0x20 && startdata[5] == 0x00
- && startdata[10] == 0x00 && startdata[11] == 0x80
- && startdata[20] == startdata[22]
- && startdata[21] == startdata[23];
-
- length = is_version2
- ? startdata[28] | startdata[29] << BITS_PER_CHAR
- : startdata[0] | startdata[1] << BITS_PER_CHAR;
- if (length >= FileSize)
- return nullptr;
-
- /* Calculate or retrieve the checksum, in a version specific way. */
- if (is_version2) {
- int index;
-
- checksum = 0;
- for (index = 0; index < length + 1; index++)
- checksum += startdata[index];
- } else
- checksum = startdata[length];
-
- /*
- * Generate a CRC for this data. When L9cut calculates a CRC, it's using a
- * copy taken up to length + 1 and then padded with two NUL bytes, so we
- * mimic that here.
- */
- crc = gln_get_buffer_crc(startdata, length + 1, 2);
-
- /*
- * See if this is a patched file. If it is, look up the game based on the
- * original CRC and checksum. If not, use the current CRC and checksum.
- */
- patch = gln_gameid_lookup_patch(length, checksum, crc);
- game = gln_gameid_lookup_game(length,
- patch ? patch->orig_checksum : checksum,
- patch ? patch->orig_crc : crc,
- FALSE);
-
- /* If no game identified, retry without the CRC. This is guesswork. */
- if (!game)
- game = gln_gameid_lookup_game(length, checksum, crc, TRUE);
-
- return game;
-}
-
-
-/*
- * gln_gameid_get_game_name()
- *
- * Return the name of the game, or nullptr if not identifiable.
- *
- * This function uses startdata from the core interpreter. This isn't an
- * advertised symbol, so be warned.
- */
-static const char *gln_gameid_get_game_name() {
- /*
- * If no game name yet known, attempt to identify the game. If it can't
- * be identified, set the cached game name to "" -- this special value
- * indicates that the game is an unknown one, but suppresses repeated
- * attempts to identify it on successive calls.
- */
- if (!gln_gameid_game_name) {
- gln_game_tableref_t game;
-
- /*
- * If the interpreter hasn't yet loaded a game, startdata is nullptr
- * (uninitialized, global). In this case, we return nullptr, allowing
- * for retries until a game is loaded.
- */
- if (!startdata)
- return nullptr;
-
- game = gln_gameid_identify_game();
- gln_gameid_game_name = game ? game->name : "";
- }
-
- /* Return the game's name, or nullptr if it was unidentifiable. */
- assert(gln_gameid_game_name);
- return strlen(gln_gameid_game_name) > 0 ? gln_gameid_game_name : nullptr;
-}
-
-
-/*
- * gln_gameid_game_name_reset()
- *
- * Clear the saved game name, forcing a new lookup when next queried. This
- * function should be called by actions that may cause the interpreter to
- * change game file, for example os_set_filenumber().
- */
-static void gln_gameid_game_name_reset() {
- gln_gameid_game_name = nullptr;
-}
-
-
-/*---------------------------------------------------------------------*/
/* Glk port bitmap picture functions */
/*---------------------------------------------------------------------*/
@@ -3307,7 +2288,7 @@ static void gln_status_update() {
* Try to establish a game identity to display; if none, use a standard
* message instead.
*/
- game_name = gln_gameid_get_game_name();
+ game_name = g_vm->_detection._gameName;
g_vm->glk_put_string(game_name ? game_name : "ScummVM GLK Level 9 Game");
g_vm->glk_set_window(gln_main_window);
@@ -3333,7 +2314,7 @@ static void gln_status_print() {
const char *game_name;
/* Get the current game name, and do nothing if none available. */
- game_name = gln_gameid_get_game_name();
+ game_name = g_vm->_detection._gameName;
if (game_name) {
gln_uint16 new_crc;
@@ -3341,7 +2322,7 @@ static void gln_status_print() {
* If not the first call and the game identity string has not changed,
* again, do nothing.
*/
- new_crc = gln_get_buffer_crc(game_name, strlen(game_name), 0);
+ new_crc = g_vm->_detection.gln_get_buffer_crc(game_name, strlen(game_name));
if (!is_initialized || new_crc != crc) {
int index;
@@ -5445,7 +4426,7 @@ gln_bool os_get_game_file(char *newname, int size) {
}
/* Encourage game name re-lookup, and return success. */
- gln_gameid_game_name_reset();
+ g_vm->_detection.gln_gameid_game_name_reset();
gln_watchdog_tick();
return TRUE;
}
@@ -5502,7 +4483,7 @@ void os_set_filenumber(char *newname, int size, int file_number) {
gln_standout_string("\n\n");
/* Encourage game name re-lookup, and return. */
- gln_gameid_game_name_reset();
+ g_vm->_detection.gln_gameid_game_name_reset();
gln_watchdog_tick();
}
@@ -5788,7 +4769,7 @@ void gln_main(const char *filename) {
* of the game. So we have to encourage a re-lookup of the game name
* at this point.
*/
- gln_gameid_game_name_reset();
+ g_vm->_detection.gln_gameid_game_name_reset();
/* Load the game, sending in any established graphics file. */
int errNum = 0;
diff --git a/engines/glk/level9/os_glk.h b/engines/glk/level9/os_glk.h
index a10a640a56..d617fb37c3 100644
--- a/engines/glk/level9/os_glk.h
+++ b/engines/glk/level9/os_glk.h
@@ -26,6 +26,9 @@
namespace Glk {
namespace Level9 {
+#define BYTE_MAX 0xff
+#define BITS_PER_CHAR 8
+
extern bool gln_graphics_enabled;
extern bool gln_graphics_possible;