mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-12 12:09:15 +00:00
Moved game version checking to ScummVM's detector and removed the FreeSCI version checking routines
svn-id: r38458
This commit is contained in:
parent
f51990a3de
commit
056a13f710
File diff suppressed because it is too large
Load Diff
@ -147,20 +147,4 @@ version_parse(const char *vn, sci_version_t *result);
|
||||
** (sci_version_t) *result: The resulting version number on success
|
||||
*/
|
||||
|
||||
int
|
||||
version_detect_from_executable(sci_version_t *result);
|
||||
/* Try to detect version from Sierra executable in cwd
|
||||
** Returns : (int) 0 on success, 1 on failure
|
||||
** (sci_version_t) *result: The version number detected on success
|
||||
*/
|
||||
|
||||
const char *
|
||||
version_guess_from_hashcode(sci_version_t *result, int *res_version, guint32 *code);
|
||||
/* Try to detect version from Sierra resource file(s) in cwd
|
||||
** Returns : (const char *) NULL on failure, the name of the associated game otherwise
|
||||
** (sci_version_t) *result: The version number detected on success
|
||||
** (int) *res_version: The resource version number detected on success
|
||||
** (guint32) *code: The resource hash code
|
||||
*/
|
||||
|
||||
#endif /* !_SCI_VERSIONS_H_ */
|
||||
|
@ -128,86 +128,6 @@ init_gamestate(state_t *gamestate, sci_version_t version) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
detect_versions(sci_version_t *version, int *res_version) {
|
||||
sci_version_t exe_version;
|
||||
sci_version_t hash_version;
|
||||
int hash_res_version;
|
||||
guint32 code;
|
||||
int got_exe_version;
|
||||
const char *game_name;
|
||||
|
||||
sciprintf("Detecting interpreter and resource versions...\n");
|
||||
|
||||
got_exe_version = !version_detect_from_executable(&exe_version);
|
||||
|
||||
if (got_exe_version) {
|
||||
sciprintf("Interpreter version: %d.%03d.%03d (by executable scan)\n",
|
||||
SCI_VERSION_MAJOR(exe_version),
|
||||
SCI_VERSION_MINOR(exe_version),
|
||||
SCI_VERSION_PATCHLEVEL(exe_version));
|
||||
|
||||
if (SCI_VERSION_MAJOR(exe_version) >= 1) {
|
||||
sciprintf("FIXME: Implement version mapping (results of executable scan ignored)\n");
|
||||
got_exe_version = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
game_name = version_guess_from_hashcode(&hash_version, &hash_res_version, &code);
|
||||
|
||||
if (game_name) {
|
||||
sciprintf("Interpreter version: %d.%03d.%03d (by hash code %08X)\n",
|
||||
SCI_VERSION_MAJOR(hash_version),
|
||||
SCI_VERSION_MINOR(hash_version),
|
||||
SCI_VERSION_PATCHLEVEL(hash_version), code);
|
||||
if (got_exe_version && exe_version != hash_version)
|
||||
sciprintf("UNEXPECTED INCONSISTENCY: Hash code %08X indicates interpreter version\n"
|
||||
" %d.%03d.%03d, but analysis of the executable yields %d.%03d.%03d (for game\n"
|
||||
" '%s'). Please report this!\n",
|
||||
code,
|
||||
SCI_VERSION_MAJOR(hash_version),
|
||||
SCI_VERSION_MINOR(hash_version),
|
||||
SCI_VERSION_PATCHLEVEL(hash_version),
|
||||
SCI_VERSION_MAJOR(exe_version),
|
||||
SCI_VERSION_MINOR(exe_version),
|
||||
SCI_VERSION_PATCHLEVEL(exe_version), game_name);
|
||||
|
||||
if (hash_res_version != SCI_VERSION_AUTODETECT)
|
||||
sciprintf("Resource version: %d (by hash code)\n", hash_res_version);
|
||||
|
||||
sciprintf("Game identified as '%s'\n", game_name);
|
||||
} else {
|
||||
sciprintf("Could not identify game by hash code: %08X\n", code);
|
||||
|
||||
if (got_exe_version)
|
||||
sciprintf("Please report the preceding two lines and the name of the game you were trying\n"
|
||||
"to run to the FreeSCI development team to help other users!\n",
|
||||
code);
|
||||
}
|
||||
|
||||
if (game_name)
|
||||
*version = hash_version;
|
||||
else if (got_exe_version)
|
||||
*version = exe_version;
|
||||
else
|
||||
*version = 0;
|
||||
|
||||
if (game_name)
|
||||
*res_version = hash_res_version;
|
||||
else
|
||||
*res_version = SCI_VERSION_AUTODETECT;
|
||||
|
||||
if (*version)
|
||||
sciprintf("Using interpreter version %d.%03d.%03d\n",
|
||||
SCI_VERSION_MAJOR(*version),
|
||||
SCI_VERSION_MINOR(*version),
|
||||
SCI_VERSION_PATCHLEVEL(*version));
|
||||
|
||||
if (*res_version != SCI_VERSION_AUTODETECT)
|
||||
sciprintf("Using resource version %d\n", *res_version);
|
||||
}
|
||||
|
||||
SciEngine::SciEngine(OSystem *syst, const SciGameDescription *desc)
|
||||
: Engine(syst) {
|
||||
// Put your engine in a sane state, but do nothing big yet;
|
||||
@ -221,6 +141,7 @@ SciEngine::SciEngine(OSystem *syst, const SciGameDescription *desc)
|
||||
// Set up the engine specific debug levels
|
||||
//Common::addSpecialDebugLevel(SCI_DEBUG_RESOURCES, "resources", "Debug the resources loading");
|
||||
|
||||
_version = desc->version;
|
||||
printf("SciEngine::SciEngine\n");
|
||||
}
|
||||
|
||||
@ -269,12 +190,12 @@ Common::Error SciEngine::go() {
|
||||
script_debug_flag = 0;
|
||||
|
||||
sci_version_t version;
|
||||
int res_version;
|
||||
int res_version = SCI_VERSION_AUTODETECT;
|
||||
|
||||
// FIXME. An evil hack until File class will be used properly
|
||||
chdir(ConfMan.get("path").c_str());
|
||||
|
||||
detect_versions(&version, &res_version);
|
||||
version = getVersion();
|
||||
|
||||
char resource_dir[MAXPATHLEN+1] = "";
|
||||
getcwd(resource_dir, MAXPATHLEN); /* Store resource directory */
|
||||
|
@ -49,6 +49,7 @@ struct GameFlags {
|
||||
struct SciGameDescription {
|
||||
ADGameDescription desc;
|
||||
GameFlags flags;
|
||||
int version;
|
||||
};
|
||||
|
||||
//class Console;
|
||||
@ -60,8 +61,9 @@ public:
|
||||
|
||||
virtual Common::Error init(void);
|
||||
virtual Common::Error go(void);
|
||||
|
||||
int getVersion() { return _version; }
|
||||
private:
|
||||
int _version;
|
||||
//Console *_console;
|
||||
};
|
||||
|
||||
|
@ -1,125 +0,0 @@
|
||||
/* 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 2
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* $URL$
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
/* Game identification */
|
||||
|
||||
#ifndef _SCI_GAMES_H_
|
||||
#define _SCI_GAMES_H_
|
||||
|
||||
#ifndef NEED_SCI_VERSIONS
|
||||
# error "You shouldn't be including this header file."
|
||||
#endif
|
||||
|
||||
#include "sci/include/versions.h"
|
||||
|
||||
typedef struct _sci_game {
|
||||
int id; /* currently CRC of resource.001 */
|
||||
int res_version;
|
||||
sci_version_t version;
|
||||
const char *name;
|
||||
} sci_game_t;
|
||||
|
||||
/* Interpreter versions for Amiga and Atari ST ports are tentative */
|
||||
sci_game_t sci_games[] = {
|
||||
{ 0x5D451535, SCI_VERSION_AUTODETECT, SCI_VERSION(1, 000, 510), "Leisure Suit Larry 1 v1.0-mac"}, /* x.yyy.zzz */ /* Launcher says v2.0, game crashes on DoAvoider */
|
||||
{ 0x6C176EE0, SCI_VERSION_AUTODETECT, SCI_VERSION(1, 000, 577), "Leisure Suit Larry 1 v2.1"},
|
||||
{ 0x1C36E076, SCI_VERSION_AUTODETECT, SCI_VERSION(1, 000, 510), "Leisure Suit Larry 1 v1.000-es"}, /* 1.SQ4.057 */ /* Crashes on function 0x7b */
|
||||
|
||||
{ 0xFEAB629D, SCI_VERSION_AUTODETECT, SCI_VERSION(0, 000, 343), "Leisure Suit Larry 2 v1.000.011-3.5"},
|
||||
{ 0x13DD3CD2, SCI_VERSION_AUTODETECT, SCI_VERSION(0, 000, 343), "Leisure Suit Larry 2 v1.000.011-5.25" },
|
||||
{ 0x1D0F3B31, SCI_VERSION_AUTODETECT, SCI_VERSION(0, 000, 572), "Leisure Suit Larry 2 v1.001.006-st"}, /* 1.000.159 */
|
||||
{ 0x40BEC726, SCI_VERSION_AUTODETECT, SCI_VERSION(0, 000, 409), "Leisure Suit Larry 2 v1.002.000-3.5"},
|
||||
{ 0x0C848403, SCI_VERSION_AUTODETECT, SCI_VERSION(0, 000, 409), "Leisure Suit Larry 2 v1.002.000-5.25" },
|
||||
{ 0x7E9CF339, SCI_VERSION_AUTODETECT, SCI_VERSION(0, 000, 572), "Leisure Suit Larry 2 v1.003-ami"}, /* x.yyy.zzz */
|
||||
|
||||
{ 0x06D737B5, SCI_VERSION_AUTODETECT, SCI_VERSION(0, 000, 572), "Leisure Suit Larry 3 v1.003-3.5" },
|
||||
{ 0xE0A1C352, SCI_VERSION_AUTODETECT, SCI_VERSION(0, 000, 572), "Leisure Suit Larry 3 v1.003-5.25" },
|
||||
{ 0xC48FE83A, SCI_VERSION_AUTODETECT, SCI_VERSION(0, 000, 572), "Leisure Suit Larry 3 v1.021-3.5" },
|
||||
{ 0x484587DD, SCI_VERSION_AUTODETECT, SCI_VERSION(0, 000, 572), "Leisure Suit Larry 3 v1.021-5.25"},
|
||||
/* { 0x????????, SCI_VERSION_AUTODETECT, SCI_VERSION(0,000,572), "Leisure Suit Larry 3 v1.021-st"},*/ /* 1.002.026 */
|
||||
{ 0x6348030A, SCI_VERSION_AUTODETECT, SCI_VERSION(0, 000, 572), "Leisure Suit Larry 3 v1.039-ami"}, /* 1.002.032 */
|
||||
|
||||
{ 0x94EA377B, SCI_VERSION_AUTODETECT, SCI_VERSION(0, 000, 685), "CB1" },
|
||||
{ 0xFD9EE7BD, SCI_VERSION_AUTODETECT, SCI_VERSION(0, 000, 685), "Camelot" },
|
||||
{ 0x2829987F, SCI_VERSION_AUTODETECT, SCI_VERSION(0, 000, 685), "Camelot" },
|
||||
{ 0x980CEAD3, SCI_VERSION_AUTODETECT, SCI_VERSION(0, 000, 629), "Demo Quest" },
|
||||
{ 0x3DB972CA, SCI_VERSION_AUTODETECT, SCI_VERSION(0, 000, 572), "Hoyle 2" },
|
||||
{ 0xC0B37651, SCI_VERSION_AUTODETECT, SCI_VERSION(0, 000, 685), "Iceman" },
|
||||
{ 0xDABA6B8A, SCI_VERSION_AUTODETECT, SCI_VERSION(0, 000, 999), "KQ1 v1.000.051-3.5" }, /* S.old.010 */
|
||||
{ 0x270E37F3, SCI_VERSION_AUTODETECT, SCI_VERSION(0, 000, 274), "KQ4" },
|
||||
{ 0x685F1205, SCI_VERSION_AUTODETECT, SCI_VERSION(0, 000, 502), "KQ4" },
|
||||
{ 0xC14E3A2A, SCI_VERSION_AUTODETECT, SCI_VERSION(0, 000, 395), "PQ2" },
|
||||
{ 0x4BD66036, SCI_VERSION_AUTODETECT, SCI_VERSION(0, 000, 490), "PQ2" },
|
||||
{ 0x7132D6D8, SCI_VERSION_AUTODETECT, SCI_VERSION(0, 000, 629), "QfG1" },
|
||||
{ 0xF8F4913F, SCI_VERSION_AUTODETECT, SCI_VERSION(0, 000, 685), "SQ3" },
|
||||
{ 0x34FBC324, SCI_VERSION_AUTODETECT, SCI_VERSION(0, 000, 999), "SQ3/DE" }, /* S.old.114 */
|
||||
{ 0xE4A3234D, SCI_VERSION_AUTODETECT, SCI_VERSION(0, 000, 506), "Fun Seekers Guide v1.02"},
|
||||
{ 0x85AFE241, SCI_VERSION_AUTODETECT, SCI_VERSION(0, 000, 519), "Hoyle 1 v1.000.104"},
|
||||
{ 0xE0E070C3, SCI_VERSION_AUTODETECT, SCI_VERSION(0, 000, 572), "Hoyle 2 v1.000.011"},
|
||||
{ 0xD0B8794E, SCI_VERSION_AUTODETECT, SCI_VERSION(0, 000, 668), "Iceman v1.023"},
|
||||
{ 0x94EA377B, SCI_VERSION_AUTODETECT, SCI_VERSION(0, 000, 631), "The Colonel's Bequest v1.000.046"},
|
||||
{ 0x28543FDF, SCI_VERSION_AUTODETECT, SCI_VERSION(0, 000, 453), "Astro Chicken"},
|
||||
{ 0x31F46F7D, SCI_VERSION_AUTODETECT, SCI_VERSION(0, 000, 453), "Space Quest III v1.0V int"},
|
||||
{ 0xAA2C94B9, SCI_VERSION_AUTODETECT, SCI_VERSION(0, 000, 685), "Mixed-Up Mother Goose v1.011 Int.#8.2.90"},
|
||||
{ 0x3B15678B, SCI_VERSION_AUTODETECT, SCI_VERSION(0, 000, 631), "The Colonel's Bequest v1.000.046-3.5"},
|
||||
{ 0x0E042F46, SCI_VERSION_AUTODETECT, SCI_VERSION(0, 000, 530), "Hoyle 1 v1.000.113-3.5"},
|
||||
{ 0x1EACB959, SCI_VERSION_AUTODETECT, SCI_VERSION(0, 000, 566), "HQ v1.000-5.25"},
|
||||
{ 0x2BEAF5E7, SCI_VERSION_AUTODETECT, SCI_VERSION(0, 000, 566), "HQ v1.001-5.25"},
|
||||
{ 0x63626D3E, SCI_VERSION_AUTODETECT, SCI_VERSION(0, 000, 668), "Iceman v1.023-5.25"},
|
||||
{ 0xDA5E7B7D, SCI_VERSION_AUTODETECT, SCI_VERSION(0, 000, 409), "KQ4 v1.003.006-3.5"},
|
||||
{ 0x376A5472, SCI_VERSION_AUTODETECT, SCI_VERSION(0, 000, 502), "KQ4 v1.006.003-5.25"},
|
||||
{ 0x364B40B2, SCI_VERSION_AUTODETECT, SCI_VERSION(0, 000, 395), "PQ2 v1.001.000-5.25"},
|
||||
{ 0x664B4123, SCI_VERSION_AUTODETECT, SCI_VERSION(0, 000, 409), "PQ2 v1.001.006-3.5"},
|
||||
{ 0x379F4582, SCI_VERSION_AUTODETECT, SCI_VERSION(0, 000, 453), "SQ3 v1.0V-5.25"},
|
||||
{ 0x04B0B081, SCI_VERSION_AUTODETECT, SCI_VERSION(0, 000, 294), "xmascard v1.04"},
|
||||
|
||||
{ 0x4447B28D, SCI_VERSION_AUTODETECT, SCI_VERSION(1, 000, 72), "Trial v1.105"},
|
||||
|
||||
{ 0xB1C2CCAE, SCI_VERSION_AUTODETECT, SCI_VERSION(1, 000, 200), "SQ4 v1.052"}, /* 1.000.753 */
|
||||
{ 0xAA6AF6A9, SCI_VERSION_AUTODETECT, SCI_VERSION(1, 000, 60), "KQ5 v0.000.062"},
|
||||
{ 0x092C2C0D, 3, SCI_VERSION(1, 000, 172), "jones v1.000.060"}, /* x.yyy.zzz */
|
||||
|
||||
{ 0xC415A485, SCI_VERSION_AUTODETECT, SCI_VERSION(1, 000, 172), "jones v1.000.060-cd"}, /* x.yyy.zzz */
|
||||
|
||||
{ 0x89C595E3, SCI_VERSION_AUTODETECT, SCI_VERSION(1, 000, 510), "SQ1 v2.000"}, /* T.A00.081 */
|
||||
{ 0x09D4FC54, SCI_VERSION_AUTODETECT, SCI_VERSION(1, 000, 510), "LSL5 v1.000"}, /* T.A00.169 */
|
||||
{ 0xF3ED1D81, SCI_VERSION_AUTODETECT, SCI_VERSION(1, 000, 510), "PQ3 v1.00"}, /* T.A00.178 */
|
||||
{ 0x501B5E6B, SCI_VERSION_AUTODETECT, SCI_VERSION(1, 000, 510), "Brain v1.000"}, /* 1.000.044 */
|
||||
{ 0xB1B7279B, SCI_VERSION_AUTODETECT, SCI_VERSION(1, 000, 510), "Longbow v1.000"}, /* 1.000.168 */
|
||||
|
||||
{ 0x82595EBE, SCI_VERSION_AUTODETECT, SCI_VERSION(0, 000, 453), "SQ3 v1.0V-ami"}, /* x.yyy.zzz */
|
||||
{ 0xF6080B61, SCI_VERSION_AUTODETECT, SCI_VERSION(0, 000, 530), "Hoyle 1 v1.000.139-ami"}, /* x.yyy.zzz */
|
||||
|
||||
{ 0x8AFEA2D0, 2, SCI_VERSION(1, 000, 000), "KQ1 v1.000.054-ami"}, /* 1.003.007 */
|
||||
|
||||
/* Undetermined Amiga versions: */
|
||||
/* { 0x8AE5F854, ?, SCI_VERSION(), "ARTHUR" }, */
|
||||
/* { 0x9FB7015B, ?, SCI_VERSION(), "CB1" }, */
|
||||
/* { 0x560CEDD5, ?, SCI_VERSION(), "iceMan" }, */
|
||||
|
||||
{ 0, 0, 0, NULL } /* terminator */
|
||||
};
|
||||
|
||||
#endif /* _SCI_GAMES_H_ */
|
@ -27,182 +27,8 @@
|
||||
#include "sci/include/versions.h"
|
||||
#include "sci/include/engine.h"
|
||||
#include "sci/include/resource.h"
|
||||
#include "sci/scicore/games.h"
|
||||
#include "sci/scicore/exe.h"
|
||||
|
||||
/* Maxmimum number of bytes to hash from start of file */
|
||||
#define VERSION_DETECT_HASH_SIZE 1000000
|
||||
|
||||
#define VERSION_DETECT_BUF_SIZE 4096
|
||||
|
||||
static int
|
||||
scan_file(char *filename, sci_version_t *version) {
|
||||
char buf[VERSION_DETECT_BUF_SIZE];
|
||||
char result_string[10]; /* string-encoded result, copied from buf */
|
||||
int characters_left;
|
||||
int state = 0;
|
||||
/* 'state' encodes how far we have matched the version pattern
|
||||
** "n.nnn.nnn"
|
||||
**
|
||||
** n.nnn.nnn
|
||||
** 0123456789
|
||||
**
|
||||
** Since we cannot be certain that the pattern does not begin with an
|
||||
** alphanumeric character, some states are ambiguous.
|
||||
** The pattern is expected to be terminated with a non-alphanumeric
|
||||
** character.
|
||||
*/
|
||||
|
||||
exe_file_t *f = exe_open(filename);
|
||||
|
||||
if (!f)
|
||||
return 1;
|
||||
|
||||
do {
|
||||
int i;
|
||||
int accept;
|
||||
|
||||
characters_left = exe_read(f, buf, VERSION_DETECT_BUF_SIZE);
|
||||
|
||||
for (i = 0; i < characters_left; i++) {
|
||||
const char ch = buf[i];
|
||||
accept = 0; /* By default, we don't like this character */
|
||||
|
||||
if (isalnum((unsigned char) ch)) {
|
||||
accept = (state != 1
|
||||
&& state != 5
|
||||
&& state != 9);
|
||||
} else if (ch == '.') {
|
||||
accept = (state == 1
|
||||
|| state == 5);
|
||||
} else if (state == 9) {
|
||||
result_string[9] = 0; /* terminate string */
|
||||
|
||||
if (!version_parse(result_string, version)) {
|
||||
exe_close(f);
|
||||
return 0; /* success! */
|
||||
}
|
||||
|
||||
/* Continue searching. */
|
||||
}
|
||||
|
||||
if (accept)
|
||||
result_string[state++] = ch;
|
||||
else
|
||||
state = 0;
|
||||
|
||||
}
|
||||
|
||||
} while (characters_left == VERSION_DETECT_BUF_SIZE);
|
||||
|
||||
exe_close(f);
|
||||
return 1; /* failure */
|
||||
}
|
||||
|
||||
static guint32
|
||||
read_uint32(byte *data) {
|
||||
return (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
|
||||
}
|
||||
|
||||
static guint16
|
||||
read_uint16(byte *data) {
|
||||
return (data[0] << 8) | data[1];
|
||||
}
|
||||
|
||||
static int
|
||||
is_mac_exe(char *filename) {
|
||||
FILE *file;
|
||||
byte buf[4];
|
||||
guint32 val;
|
||||
unsigned int i;
|
||||
|
||||
/* Mac executables have no extension */
|
||||
if (strchr(filename, '.'))
|
||||
return 0;
|
||||
|
||||
file = fopen(filename, "rb");
|
||||
if (!file)
|
||||
return 0;
|
||||
|
||||
if (fseek(file, 4, SEEK_SET) == -1) {
|
||||
fclose(file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read resource map offset */
|
||||
if (fread(buf, 1, 4, file) < 4) {
|
||||
fclose(file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
val = read_uint32(buf);
|
||||
|
||||
if (fseek(file, val + 28, SEEK_SET) == -1) {
|
||||
fclose(file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read number of types in map */
|
||||
if (fread(buf, 1, 2, file) < 2) {
|
||||
fclose(file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
val = read_uint16(buf) + 1;
|
||||
|
||||
for (i = 0; i < val; i++) {
|
||||
if (fread(buf, 1, 4, file) < 4) {
|
||||
fclose(file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Look for executable code */
|
||||
if (!memcmp(buf, "CODE", 4)) {
|
||||
fclose(file);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Skip to next list entry */
|
||||
if (fseek(file, 4, SEEK_CUR) == -1) {
|
||||
fclose(file);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
is_exe(char *filename) {
|
||||
FILE *file;
|
||||
char buf[4];
|
||||
unsigned char header[] = {0x00, 0x00, 0x03, 0xf3};
|
||||
|
||||
/* PC and Atari ST executable extensions */
|
||||
if (strstr(filename, ".exe") || strstr(filename, ".EXE")
|
||||
|| strstr(filename, ".prg") || strstr(filename, ".PRG"))
|
||||
return 1;
|
||||
|
||||
/* Check for Amiga executable */
|
||||
if (strchr(filename, '.'))
|
||||
return 0;
|
||||
|
||||
file = fopen(filename, "rb");
|
||||
if (!file)
|
||||
return 0;
|
||||
|
||||
if (fread(buf, 1, 4, file) < 4) {
|
||||
fclose(file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
|
||||
/* Check header bytes */
|
||||
return memcmp(buf, header, 4) == 0;
|
||||
}
|
||||
|
||||
void
|
||||
version_require_earlier_than(state_t *s, sci_version_t version) {
|
||||
if (s->version_lock_flag)
|
||||
@ -258,102 +84,4 @@ version_parse(const char *vn, sci_version_t *result) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
version_detect_from_executable(sci_version_t *result) {
|
||||
sci_dir_t dir;
|
||||
char *filename;
|
||||
int mac = 0;
|
||||
|
||||
/* For Mac versions we need to search the resource fork */
|
||||
mac = !chdir(".rsrc");
|
||||
|
||||
sci_init_dir(&dir);
|
||||
|
||||
filename = sci_find_first(&dir, "*");
|
||||
|
||||
while (filename) {
|
||||
if (mac ? is_mac_exe(filename) : is_exe(filename))
|
||||
if (!scan_file(filename, result)) {
|
||||
sci_finish_find(&dir);
|
||||
|
||||
if (mac)
|
||||
chdir("..");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
filename = sci_find_next(&dir);
|
||||
}
|
||||
|
||||
if (mac)
|
||||
chdir("..");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define HASHCODE_MAGIC_RESOURCE_000 0x55555555
|
||||
#define HASHCODE_MAGIC_RESOURCE_001 0x00000001
|
||||
|
||||
const char * /* Original version by Solomon Peachy */
|
||||
version_guess_from_hashcode(sci_version_t *result, int *res_version, guint32 *code) {
|
||||
int i;
|
||||
int fd = -1;
|
||||
int left = VERSION_DETECT_HASH_SIZE;
|
||||
guint32 hash_code;
|
||||
guint8 buf[VERSION_DETECT_BUF_SIZE];
|
||||
|
||||
if (IS_VALID_FD(fd = sci_open("resource.001", O_RDONLY | O_BINARY))) {
|
||||
hash_code = HASHCODE_MAGIC_RESOURCE_001;
|
||||
} else if (IS_VALID_FD(fd = sci_open("resource.000", O_RDONLY | O_BINARY))) {
|
||||
hash_code = HASHCODE_MAGIC_RESOURCE_000;
|
||||
} else {
|
||||
sciprintf("Warning: Could not find RESOURCE.000 or RESOURCE.001, cannot determine hash code\n");
|
||||
*code = 0;
|
||||
/* complete and utter failure */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (left > 0) {
|
||||
int len = read(fd, buf, left < VERSION_DETECT_BUF_SIZE ? left : VERSION_DETECT_BUF_SIZE);
|
||||
|
||||
if (len == -1) {
|
||||
sciprintf("Warning: read error while computing hash code for resource file\n");
|
||||
*code = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (len == 0)
|
||||
/* EOF */
|
||||
break;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
hash_code = (hash_code * 19) + *(buf + i);
|
||||
|
||||
/* This is the string hashing algorithm used by Objective Caml 3.08; the general idea
|
||||
** of multiplying the previous hash code with a prime number between 5 and 23 appears
|
||||
** to be generally considered to be a "good" approach to exhausting the entire 32 bit
|
||||
** number space in a somewhat equal distribution. For large chunks of data, such as
|
||||
** SCI resource files, this should both perform well and yield a good distribution,
|
||||
** or at least that's what standard library designers have been assuming for quite a
|
||||
** while. */
|
||||
|
||||
left -= len;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
||||
*code = hash_code;
|
||||
|
||||
for (i = 0 ; sci_games[i].name ; i++) {
|
||||
if ((unsigned int)sci_games[i].id == hash_code) {
|
||||
*result = sci_games[i].version;
|
||||
*res_version = sci_games[i].res_version;
|
||||
return sci_games[i].name;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL; /* Failed to find matching game */
|
||||
}
|
||||
|
||||
|
||||
#undef VERSION_DETECT_BUF_SIZE
|
||||
|
Loading…
Reference in New Issue
Block a user