[Scummvm-cvs-logs] SF.net SVN: scummvm:[38509] scummvm/trunk/engines/sci

thebluegr at users.sourceforge.net thebluegr at users.sourceforge.net
Wed Feb 18 23:20:28 CET 2009


Revision: 38509
          http://scummvm.svn.sourceforge.net/scummvm/?rev=38509&view=rev
Author:   thebluegr
Date:     2009-02-18 22:20:28 +0000 (Wed, 18 Feb 2009)

Log Message:
-----------
Readded the code which reads the version from the original executable to the fallback detector (still very hackish...). This is probably the only known way currently to determine the version used by each game variant and add appropriate game flags

Modified Paths:
--------------
    scummvm/trunk/engines/sci/detection.cpp
    scummvm/trunk/engines/sci/include/versions.h
    scummvm/trunk/engines/sci/module.mk
    scummvm/trunk/engines/sci/scicore/versions.cpp

Added Paths:
-----------
    scummvm/trunk/engines/sci/scicore/exe.cpp
    scummvm/trunk/engines/sci/scicore/exe.h
    scummvm/trunk/engines/sci/scicore/exe_dec.h
    scummvm/trunk/engines/sci/scicore/exe_lzexe.cpp
    scummvm/trunk/engines/sci/scicore/exe_raw.cpp

Modified: scummvm/trunk/engines/sci/detection.cpp
===================================================================
--- scummvm/trunk/engines/sci/detection.cpp	2009-02-18 22:07:15 UTC (rev 38508)
+++ scummvm/trunk/engines/sci/detection.cpp	2009-02-18 22:20:28 UTC (rev 38509)
@@ -1044,7 +1044,7 @@
 		{},
 		SCI_VERSION(0, 000, 000)	// FIXME: add version here
 	},
-		
+#if 0	
 	// Space Quest 1 VGA Remake - English Amiga (from www.back2roots.org)
 	{{"sq1sci", "VGA Remake", {
 		{"resource.map", 0, "106484b372af1d4cbf866472cc2813dc", 6396},
@@ -1085,7 +1085,7 @@
 		{},
 		SCI_VERSION(1, 000, 510)
 	},
-
+#endif
 	// Space Quest 3 - English Amiga (from www.back2roots.org)
 	{{"sq3", "", {
 		{"resource.map", 0, "bad41385acde6d677a8d55a7b20437e3", 5868},
@@ -1357,11 +1357,30 @@
 
 
 const ADGameDescription *SciMetaEngine::fallbackDetect(const Common::FSList &fslist) const {
-		printf("If this is *NOT* a fan-modified version (in particular, not a fan-made\n");
-		printf("translation), please, report the data above, including the following\n");
-		printf("version number, from the game's executable: ");
+	int exeVersion = 0;
 
-		// TODO
+	// First grab all filenames
+	for (Common::FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) {
+		if (file->isDirectory()) continue;
+		Common::String filename = file->getName();
+		filename.toLowercase();
+
+		// FIXME: This is all quite hackish
+		if (filename.contains("scidhuv")) {
+			exeVersion = version_detect_from_executable((char *)file->getPath().c_str());
+			break;
+		} 
+	}
+
+	printf("If this is *NOT* a fan-modified version (in particular, not a fan-made\n");
+	printf("translation), please, report the data above, including the following\n");
+	printf("version number, from the game's executable:\n");
+
+	printf("Interpreter version: %d.%03d.%03d (by executable scan)\n",
+			SCI_VERSION_MAJOR(exeVersion),
+ 			SCI_VERSION_MINOR(exeVersion),
+ 			SCI_VERSION_PATCHLEVEL(exeVersion));
+		
 	return 0;
 }
 

Modified: scummvm/trunk/engines/sci/include/versions.h
===================================================================
--- scummvm/trunk/engines/sci/include/versions.h	2009-02-18 22:07:15 UTC (rev 38508)
+++ scummvm/trunk/engines/sci/include/versions.h	2009-02-18 22:20:28 UTC (rev 38509)
@@ -147,4 +147,10 @@
 **             (sci_version_t) *result: The resulting version number on success
 */
 
+int
+version_detect_from_executable(char *filename);
+/* Try to detect version from Sierra executable in cwd
+** Returns   : (int) The version number detected, or 0 if we weren't successful
+*/
+
 #endif /* !_SCI_VERSIONS_H_ */

Modified: scummvm/trunk/engines/sci/module.mk
===================================================================
--- scummvm/trunk/engines/sci/module.mk	2009-02-18 22:07:15 UTC (rev 38508)
+++ scummvm/trunk/engines/sci/module.mk	2009-02-18 22:20:28 UTC (rev 38509)
@@ -55,6 +55,9 @@
 	scicore/decompress01.o \
 	scicore/decompress1.o \
 	scicore/decompress11.o \
+	scicore/exe.o \
+	scicore/exe_lzexe.o \
+	scicore/exe_raw.o \
 	scicore/resource.o \
 	scicore/resource_map.o \
 	scicore/resource_patch.o \

Added: scummvm/trunk/engines/sci/scicore/exe.cpp
===================================================================
--- scummvm/trunk/engines/sci/scicore/exe.cpp	                        (rev 0)
+++ scummvm/trunk/engines/sci/scicore/exe.cpp	2009-02-18 22:20:28 UTC (rev 38509)
@@ -0,0 +1,80 @@
+/* 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$
+ *
+ */
+
+#include "sci/include/sci_memory.h"
+
+#include "sci/scicore/exe.h"
+#include "sci/scicore/exe_dec.h"
+
+extern exe_decompressor_t exe_decompressor_lzexe;
+extern exe_decompressor_t exe_decompressor_raw;
+
+exe_decompressor_t *exe_decompressors[] = {
+	&exe_decompressor_lzexe,
+	&exe_decompressor_raw,
+	NULL
+};
+
+struct _exe_file {
+	struct _exe_decompressor *decompressor;
+	struct _exe_handle *handle;
+};
+
+exe_file_t *
+exe_open(const char *filename) {
+	int i = 0;
+	exe_decompressor_t *dec;
+
+	while ((dec = exe_decompressors[i])) {
+		exe_handle_t *handle = dec->open(filename);
+
+		if (handle) {
+			exe_file_t *file = (exe_file_t*)sci_malloc(sizeof(exe_file_t));
+
+			sciprintf("Scanning '%s' with decompressor '%s'\n",
+			          filename, dec->name);
+
+			file->handle = handle;
+			file->decompressor = dec;
+			return file;
+		}
+
+		i++;
+	}
+
+	return NULL;
+}
+
+int
+exe_read(exe_file_t *file, void *buf, int count) {
+	return file->decompressor->read(file->handle, buf, count);
+}
+
+void
+exe_close(exe_file_t *file) {
+	file->decompressor->close(file->handle);
+
+	free(file);
+}


Property changes on: scummvm/trunk/engines/sci/scicore/exe.cpp
___________________________________________________________________
Added: svn:mime-type
   + text/plain
Added: svn:keywords
   + Date Rev Author URL Id
Added: svn:eol-style
   + native

Added: scummvm/trunk/engines/sci/scicore/exe.h
===================================================================
--- scummvm/trunk/engines/sci/scicore/exe.h	                        (rev 0)
+++ scummvm/trunk/engines/sci/scicore/exe.h	2009-02-18 22:20:28 UTC (rev 38509)
@@ -0,0 +1,58 @@
+/* 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$
+ *
+ */
+
+#ifndef _SCI_EXE_H_
+#define _SCI_EXE_H_
+
+typedef struct _exe_file exe_file_t;
+
+exe_file_t *
+exe_open(const char *filename);
+/* Opens an executable file
+** Parameters: (const char *) filename: Filename of executable to open
+** Returns   : (exe_file_t *) File handle, or NULL on error
+** This function will try to find a decompressor that can handle this type
+** of executable
+*/
+
+int
+exe_read(exe_file_t *file, void *buf, int count);
+/* Reads from an executable file
+** Parameters: (exe_file_t *) file: File handle
+**             (void *) buf: Buffer to store decompressed data
+**             (int) count: Size of decompressed data requested, in bytes
+** Returns   : (int) Number of bytes of decompressed data that was stored in
+**                   buf. If this value is less than count an error has
+**                   occured, or end-of-file was reached.
+*/
+
+void
+exe_close(exe_file_t *handle);
+/* Closes an executable file
+** Parameters: (exe_file_t *) file: File handle
+** Returns   : (void)
+*/
+
+#endif /* !_SCI_EXE_H_ */


Property changes on: scummvm/trunk/engines/sci/scicore/exe.h
___________________________________________________________________
Added: svn:mime-type
   + text/plain
Added: svn:keywords
   + Date Rev Author URL Id
Added: svn:eol-style
   + native

Added: scummvm/trunk/engines/sci/scicore/exe_dec.h
===================================================================
--- scummvm/trunk/engines/sci/scicore/exe_dec.h	                        (rev 0)
+++ scummvm/trunk/engines/sci/scicore/exe_dec.h	2009-02-18 22:20:28 UTC (rev 38509)
@@ -0,0 +1,64 @@
+/* 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$
+ *
+ */
+
+#ifndef _SCI_EXE_DEC_H_
+#define _SCI_EXE_DEC_H_
+
+typedef struct _exe_handle exe_handle_t;
+
+typedef struct _exe_decompressor {
+	const char *name; /* Decompressor name. Unique identifier, should consist
+	            ** of lower-case (where applicable) alphanumerics
+	            */
+
+	exe_handle_t * (*open)(const char *filename);
+	/* Opens an executable file
+	** Parameters: (const char *) filename: Filename of executable to open.
+	** Returns   : (exe_handle_t *) Decompressor file handle, or NULL on
+	**                              error.
+	** This function will verify that the file can be handled by the
+	** decompressor. If this is not the case the function will fail.
+	*/
+
+	int (*read)(exe_handle_t *handle, void *buf, int count);
+	/* Reads from executable file
+	** Parameters: (exe_handle_t *) handle: Decompressor file handle.
+	**             (void *) buf: Buffer to store decompressed data.
+	**             (int) count: Size of decompressed data requested, in
+	**                          bytes.
+	** Returns   : (int) Number of bytes of decompressed data that was
+	**                   stored in buf. If this value is less than count
+	**                   an error has occured, or end-of-file was
+	**                   reached.
+	*/
+
+	void (*close)(exe_handle_t *handle);
+	/* Closes a decompressor file handle.
+	** Parameters: (exe_handle_t *) handle: Decompressor file handle.
+	** Returns   : (void)
+	*/
+} exe_decompressor_t;
+
+#endif /* !_SCI_EXE_DEC_H_ */


Property changes on: scummvm/trunk/engines/sci/scicore/exe_dec.h
___________________________________________________________________
Added: svn:mime-type
   + text/plain
Added: svn:keywords
   + Date Rev Author URL Id
Added: svn:eol-style
   + native

Added: scummvm/trunk/engines/sci/scicore/exe_lzexe.cpp
===================================================================
--- scummvm/trunk/engines/sci/scicore/exe_lzexe.cpp	                        (rev 0)
+++ scummvm/trunk/engines/sci/scicore/exe_lzexe.cpp	2009-02-18 22:20:28 UTC (rev 38509)
@@ -0,0 +1,328 @@
+/* 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$
+ *
+ */
+
+/* Based on public domain code by Mitugu Kurizono. */
+
+#include "sci/include/sci_memory.h"
+#include "sci/scicore/exe_dec.h"
+
+/* Macro to interpret two sequential bytes as an unsigned integer. */
+#define UINT16(A) ((*((A) + 1) << 8) + *(A))
+
+/* The amount of most recent data (in bytes) that we need to keep in the
+** buffer. lzexe compression is based on copying chunks of previous data to
+** form new data.
+*/
+#define LZEXE_WINDOW 8192
+
+/* Buffer size. */
+#define LZEXE_BUFFER_SIZE (LZEXE_WINDOW + 4096)
+
+/* Maximum amount of data (in bytes) that can be in the buffer at the start
+** of the decompression loop. The maximum amount of data that can be added
+** to the buffer during a single step of the loop is 256 bytes.
+*/
+#define LZEXE_BUFFER_MAX (LZEXE_BUFFER_SIZE - 256)
+
+struct _exe_handle {
+	FILE *f;
+
+	/* Output buffer. */
+	guint8 buffer[LZEXE_BUFFER_SIZE];
+	guint8 *bufptr;
+
+	/* Bit buffer. Bits [0..count) still contain unprocessed data. */
+	int buf;
+	int count;
+
+	/* End of data flag. */
+	int eod;
+};
+
+static int
+lzexe_read_uint16(FILE *f, int *value) {
+	int data;
+
+	if ((*value = fgetc(f)) == EOF)
+		return 0;
+
+	if ((data = fgetc(f)) == EOF)
+		return 0;
+
+	*value |= data << 8;
+	return 1;
+}
+
+static int
+lzexe_read_uint8(FILE *f, int *value) {
+	if ((*value = fgetc(f)) == EOF)
+		return 0;
+
+	return 1;
+}
+
+static int
+lzexe_init(exe_handle_t *handle, FILE *f) {
+	handle->f = f;
+	handle->bufptr = handle->buffer;
+	handle->eod = 0;
+
+	if (!lzexe_read_uint16(handle->f, &handle->buf))
+		return 0;
+
+	handle->count = 16;
+	return 1;
+}
+
+static int
+lzexe_get_bit(exe_handle_t *handle, int *bit) {
+	*bit = handle->buf & 1;
+
+	if (--handle->count == 0) {
+		if (!lzexe_read_uint16(handle->f, &handle->buf))
+			return 0;
+		handle->count = 16;
+	} else
+		handle->buf >>= 1;
+
+	return 1;
+}
+
+static int
+lzexe_decompress(exe_handle_t *handle) {
+	while (!handle->eod
+	        && handle->bufptr - handle->buffer <= LZEXE_BUFFER_MAX) {
+		int bit;
+		int len, span;
+
+		if (!lzexe_get_bit(handle, &bit))
+			return 0;
+
+		if (bit) {
+			/* 1: copy byte verbatim. */
+
+			int data;
+
+			if (!lzexe_read_uint8(handle->f, &data))
+				return 0;
+
+			*handle->bufptr++ = data;
+
+			continue;
+		}
+
+		if (!lzexe_get_bit(handle, &bit))
+			return 0;
+
+		if (!bit) {
+			/* 00: copy small block. */
+
+			/* Next two bits indicate block length - 2. */
+			if (!lzexe_get_bit(handle, &bit))
+				return 0;
+
+			len = bit << 1;
+
+			if (!lzexe_get_bit(handle, &bit))
+				return 0;
+
+			len |= bit;
+			len += 2;
+
+			/* Read span byte. This forms the low byte of a
+			** negative two's compliment value.
+			*/
+			if (!lzexe_read_uint8(handle->f, &span))
+				return 0;
+
+			/* Convert to negative integer. */
+			span -= 256;
+		} else {
+			/* 01: copy large block. */
+			int data;
+
+			/* Read low byte of span value. */
+			if (!lzexe_read_uint8(handle->f, &span))
+				return 0;
+
+			/* Read next byte. Bits [7..3] contain bits [12..8]
+			** of span value. Bits [2..0] contain block length -
+			** 2.
+			*/
+			if (!lzexe_read_uint8(handle->f, &data))
+				return 0;
+			span |= (data & 0xf8) << 5;
+			/* Convert to negative integer. */
+			span -= 8192;
+
+			len = (data & 7) + 2;
+
+			if (len == 2) {
+				/* Next byte is block length value - 1. */
+				if (!lzexe_read_uint8(handle->f, &len))
+					return 0;
+
+				if (len == 0) {
+					/* End of data reached. */
+					handle->eod = 1;
+					break;
+				}
+
+				if (len == 1)
+					/* Segment change marker. */
+					continue;
+
+				len++;
+			}
+		}
+
+		assert(handle->bufptr + span >= handle->buffer);
+
+		/* Copy block. */
+		while (len-- > 0) {
+			*handle->bufptr = *(handle->bufptr + span);
+			handle->bufptr++;
+		}
+	}
+
+	return 1;
+}
+
+static exe_handle_t *
+lzexe_open(const char *filename) {
+	exe_handle_t *handle;
+	guint8 head[0x20];
+	guint8 size[2];
+	off_t fpos;
+
+	FILE *f = sci_fopen(filename, "rb");
+
+	if (!f)
+		return NULL;
+
+	/* Read exe header plus possible lzexe signature. */
+	if (fread(head, 1, 0x20, f) != 0x20)
+		return NULL;
+
+	/* Verify "MZ" signature, header size == 2 paragraphs and number of
+	** overlays == 0.
+	*/
+	if (UINT16(head) != 0x5a4d || UINT16(head + 8) != 2
+	        || UINT16(head + 0x1a) != 0)
+		return NULL;
+
+	/* Verify that first relocation item offset is 0x1c. */
+	if (UINT16(head + 0x18) != 0x1c)
+		return NULL;
+
+	/* Look for lzexe signature. */
+	if (memcmp(head + 0x1c, "LZ09", 4)
+	        && memcmp(head + 0x1c, "LZ91", 4)) {
+		return NULL;
+	}
+
+	/* Calculate code segment offset in exe file. */
+	fpos = (UINT16(head + 0x16) + UINT16(head + 8)) << 4;
+	/* Seek to offset 8 of info table at start of code segment. */
+	if (fseek(f, fpos + 8, SEEK_SET) == -1)
+		return NULL;
+
+	/* Read size of compressed data in paragraphs. */
+	if (fread(size, 1, 2, f) != 2)
+		return NULL;
+
+	/* Move file pointer to start of compressed data. */
+	fpos -= UINT16(size) << 4;
+	if (fseek(f, fpos, SEEK_SET) == -1)
+		return NULL;
+
+	handle = (exe_handle_t*)sci_malloc(sizeof(exe_handle_t));
+
+	if (!lzexe_init(handle, f)) {
+		free(handle);
+		return NULL;
+	}
+
+	return handle;
+}
+
+static int
+lzexe_read(exe_handle_t *handle, void *buf, int count) {
+	int done = 0;
+
+	while (done != count) {
+		int size, copy, i;
+		int left = count - done;
+
+		if (!lzexe_decompress(handle))
+			return done;
+
+		/* Total amount of bytes in buffer. */
+		size = handle->bufptr - handle->buffer;
+
+		/* If we're not at end of data we need to maintain the
+		** window.
+		*/
+		if (!handle->eod)
+			copy = size - LZEXE_WINDOW;
+		else {
+			if (size == 0)
+				/* No data left. */
+				return done;
+
+			copy = size;
+		}
+
+		/* Do not copy more than requested. */
+		if (copy > left)
+			copy = left;
+
+		memcpy((char *) buf + done, handle->buffer, copy);
+
+		/* Move remaining data to start of buffer. */
+		for (i = copy; i < size; i++)
+			handle->buffer[i - copy] = handle->buffer[i];
+
+		handle->bufptr -= copy;
+		done += copy;
+	}
+
+	return done;
+}
+
+static void
+lzexe_close(exe_handle_t *handle) {
+	fclose(handle->f);
+
+	free(handle);
+}
+
+exe_decompressor_t
+exe_decompressor_lzexe = {
+	"lzexe",
+	lzexe_open,
+	lzexe_read,
+	lzexe_close
+};


Property changes on: scummvm/trunk/engines/sci/scicore/exe_lzexe.cpp
___________________________________________________________________
Added: svn:mime-type
   + text/plain
Added: svn:keywords
   + Date Rev Author URL Id
Added: svn:eol-style
   + native

Added: scummvm/trunk/engines/sci/scicore/exe_raw.cpp
===================================================================
--- scummvm/trunk/engines/sci/scicore/exe_raw.cpp	                        (rev 0)
+++ scummvm/trunk/engines/sci/scicore/exe_raw.cpp	2009-02-18 22:20:28 UTC (rev 38509)
@@ -0,0 +1,66 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 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$
+ *
+ */
+
+#include "sci/include/sci_memory.h"
+
+struct _exe_handle {
+	FILE *f;
+};
+
+#include "sci/scicore/exe_dec.h"
+
+static exe_handle_t *
+raw_open(const char *filename) {
+	FILE *f = sci_fopen(filename, "rb");
+	exe_handle_t *handle;
+
+	if (!f)
+		return NULL;
+
+	handle = (exe_handle_t*)sci_malloc(sizeof(exe_handle_t));
+	handle->f = f;
+
+	return handle;
+}
+
+static int
+raw_read(exe_handle_t *handle, void *buf, int count) {
+	return fread(buf, 1, count, handle->f);
+}
+
+static void
+raw_close(exe_handle_t *handle) {
+	fclose(handle->f);
+
+	free(handle);
+}
+
+exe_decompressor_t
+exe_decompressor_raw = {
+	"raw",
+	raw_open,
+	raw_read,
+	raw_close
+};


Property changes on: scummvm/trunk/engines/sci/scicore/exe_raw.cpp
___________________________________________________________________
Added: svn:mime-type
   + text/plain
Added: svn:keywords
   + Date Rev Author URL Id
Added: svn:eol-style
   + native

Modified: scummvm/trunk/engines/sci/scicore/versions.cpp
===================================================================
--- scummvm/trunk/engines/sci/scicore/versions.cpp	2009-02-18 22:07:15 UTC (rev 38508)
+++ scummvm/trunk/engines/sci/scicore/versions.cpp	2009-02-18 22:20:28 UTC (rev 38509)
@@ -24,9 +24,14 @@
  */
 
 #define NEED_SCI_VERSIONS
+
+#include "common/system.h"
+#include "common/config-manager.h"
+
 #include "sci/include/versions.h"
 #include "sci/include/engine.h"
 #include "sci/include/resource.h"
+#include "sci/scicore/exe.h"		// for reading version from the executable
 
 void
 version_require_earlier_than(state_t *s, sci_version_t version) {
@@ -83,4 +88,193 @@
 	return 0;
 }
 
+// Exe scanning functions
+
+/* 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;
+}
+
+int
+version_detect_from_executable(char *filename) {
+	int mac = 0;
+	int result;
+
+	if (mac ? is_mac_exe(filename) : is_exe(filename)) {
+		if (scan_file(filename, &result)) {
+			return result;
+		}
+	}
+
+	return 0;
+}
+
 #undef VERSION_DETECT_BUF_SIZE


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list