aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/tony/lzo/lzo1x.h198
-rw-r--r--engines/tony/lzo/lzoconf.h398
-rw-r--r--engines/tony/module.mk6
-rw-r--r--engines/tony/mpal.h23
-rw-r--r--engines/tony/mpal/expr.cpp471
-rw-r--r--engines/tony/mpal/expr.h116
-rw-r--r--engines/tony/mpal/loadmpc.cpp720
-rw-r--r--engines/tony/mpal/loadmpc.h83
-rw-r--r--engines/tony/mpal/lzo1x.h188
-rw-r--r--engines/tony/mpal/mpal.cpp3071
-rw-r--r--engines/tony/mpal/mpal.h769
-rw-r--r--engines/tony/mpal/mpaldll.h418
-rw-r--r--engines/tony/mpal/stubs.cpp140
-rw-r--r--engines/tony/mpal/stubs.h121
-rw-r--r--engines/tony/tony.cpp45
-rw-r--r--engines/tony/tony.h14
16 files changed, 6765 insertions, 16 deletions
diff --git a/engines/tony/lzo/lzo1x.h b/engines/tony/lzo/lzo1x.h
new file mode 100644
index 0000000000..e481b33fa4
--- /dev/null
+++ b/engines/tony/lzo/lzo1x.h
@@ -0,0 +1,198 @@
+/* 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.
+ *
+ */
+/* lzo1x.h -- public interface of the LZO1X compression algorithm
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+
+ The LZO library 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.
+
+ The LZO library 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 the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus.oberhumer@jk.uni-linz.ac.at>
+ http://wildsau.idv.uni-linz.ac.at/mfx/lzo.html
+ */
+
+
+#ifndef __LZO1X_H
+#define __LZO1X_H
+
+#ifndef __LZOCONF_H
+#include "lzoconf.h"
+#endif
+
+namespace Tony {
+
+namespace LZO {
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+/* Memory required for the wrkmem parameter.
+ * When the required size is 0, you can also pass a NULL pointer.
+ */
+
+#define LZO1X_MEM_COMPRESS LZO1X_1_MEM_COMPRESS
+#define LZO1X_MEM_DECOMPRESS (0)
+#define LZO1X_MEM_OPTIMIZE (0)
+
+
+/* decompression */
+LZO_EXTERN(int)
+lzo1x_decompress ( const lzo_byte *src, lzo_uint src_len,
+ lzo_byte *dst, lzo_uint *dst_len,
+ lzo_voidp wrkmem /* NOT USED */ );
+
+/* safe decompression with overrun testing */
+LZO_EXTERN(int)
+lzo1x_decompress_safe ( const lzo_byte *src, lzo_uint src_len,
+ lzo_byte *dst, lzo_uint *dst_len,
+ lzo_voidp wrkmem /* NOT USED */ );
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+#define LZO1X_1_MEM_COMPRESS ((lzo_uint32) (16384L * lzo_sizeof_dict_t))
+
+LZO_EXTERN(int)
+lzo1x_1_compress ( const lzo_byte *src, lzo_uint src_len,
+ lzo_byte *dst, lzo_uint *dst_len,
+ lzo_voidp wrkmem );
+
+
+/***********************************************************************
+// special compressor versions
+************************************************************************/
+
+/* this version needs only 8 kB work memory */
+#define LZO1X_1_11_MEM_COMPRESS ((lzo_uint32) (2048L * lzo_sizeof_dict_t))
+
+LZO_EXTERN(int)
+lzo1x_1_11_compress ( const lzo_byte *src, lzo_uint src_len,
+ lzo_byte *dst, lzo_uint *dst_len,
+ lzo_voidp wrkmem );
+
+
+/* this version needs 16 kB work memory */
+#define LZO1X_1_12_MEM_COMPRESS ((lzo_uint32) (4096L * lzo_sizeof_dict_t))
+
+LZO_EXTERN(int)
+lzo1x_1_12_compress ( const lzo_byte *src, lzo_uint src_len,
+ lzo_byte *dst, lzo_uint *dst_len,
+ lzo_voidp wrkmem );
+
+
+/* use this version if you need a little more compression speed */
+#define LZO1X_1_15_MEM_COMPRESS ((lzo_uint32) (32768L * lzo_sizeof_dict_t))
+
+LZO_EXTERN(int)
+lzo1x_1_15_compress ( const lzo_byte *src, lzo_uint src_len,
+ lzo_byte *dst, lzo_uint *dst_len,
+ lzo_voidp wrkmem );
+
+
+/***********************************************************************
+// better compression ratio at the cost of more memory and time
+************************************************************************/
+
+#define LZO1X_999_MEM_COMPRESS ((lzo_uint32) (14 * 16384L * sizeof(short)))
+
+#if !defined(LZO_999_UNSUPPORTED)
+LZO_EXTERN(int)
+lzo1x_999_compress ( const lzo_byte *src, lzo_uint src_len,
+ lzo_byte *dst, lzo_uint *dst_len,
+ lzo_voidp wrkmem );
+#endif
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+#if !defined(LZO_999_UNSUPPORTED)
+LZO_EXTERN(int)
+lzo1x_999_compress_dict ( const lzo_byte *in , lzo_uint in_len,
+ lzo_byte *out, lzo_uint *out_len,
+ lzo_voidp wrkmem,
+ const lzo_byte *dict, lzo_uint dict_len );
+
+LZO_EXTERN(int)
+lzo1x_999_compress_level ( const lzo_byte *in , lzo_uint in_len,
+ lzo_byte *out, lzo_uint *out_len,
+ lzo_voidp wrkmem,
+ const lzo_byte *dict, lzo_uint dict_len,
+ lzo_progress_callback_t cb,
+ int compression_level );
+#endif
+
+LZO_EXTERN(int)
+lzo1x_decompress_dict_safe ( const lzo_byte *in, lzo_uint in_len,
+ lzo_byte *out, lzo_uint *out_len,
+ lzo_voidp wrkmem /* NOT USED */,
+ const lzo_byte *dict, lzo_uint dict_len );
+
+
+/***********************************************************************
+// optimize a compressed data block
+************************************************************************/
+
+LZO_EXTERN(int)
+lzo1x_optimize ( lzo_byte *in , lzo_uint in_len,
+ lzo_byte *out, lzo_uint *out_len,
+ lzo_voidp wrkmem );
+
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+} // End of namespace LZO
+
+} // End of namespace Tony
+
+#endif /* already included */
+
diff --git a/engines/tony/lzo/lzoconf.h b/engines/tony/lzo/lzoconf.h
new file mode 100644
index 0000000000..9dfcfb0cbc
--- /dev/null
+++ b/engines/tony/lzo/lzoconf.h
@@ -0,0 +1,398 @@
+/* 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.
+ *
+ */
+/* lzoconf.h -- configuration for the LZO real-time data compression library
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+
+ The LZO library 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.
+
+ The LZO library 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 the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus.oberhumer@jk.uni-linz.ac.at>
+ http://wildsau.idv.uni-linz.ac.at/mfx/lzo.html
+ */
+
+
+#ifndef __LZOCONF_H
+#define __LZOCONF_H
+
+namespace Tony {
+
+namespace LZO {
+
+#define LZO_VERSION 0x1060
+#define LZO_VERSION_STRING "1.06"
+#define LZO_VERSION_DATE "Nov 29 1999"
+
+/* internal Autoconf configuration file - only used when building LZO */
+#if defined(LZO_HAVE_CONFIG_H)
+# include <config.h>
+#endif
+#include <limits.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/***********************************************************************
+// LZO requires a conforming <limits.h>
+************************************************************************/
+
+#if !defined(CHAR_BIT) || (CHAR_BIT != 8)
+# error "invalid CHAR_BIT"
+#endif
+#if !defined(UCHAR_MAX) || !defined(UINT_MAX) || !defined(ULONG_MAX)
+# error "check your compiler installation"
+#endif
+#if (USHRT_MAX < 1 ) || (UINT_MAX < 1) || (ULONG_MAX < 1)
+# error "your limits.h macros are broken"
+#endif
+
+/* workaround a cpp bug under hpux 10.20 */
+#define LZO_0xffffffffL 4294967295ul
+
+
+/***********************************************************************
+// architecture defines
+************************************************************************/
+
+#if !defined(__LZO_WIN) && !defined(__LZO_DOS) && !defined(__LZO_OS2)
+# if defined(__WINDOWS__) || defined(_WINDOWS) || defined(_Windows)
+# define __LZO_WIN
+# elif defined(__WIN32__) || defined(_WIN32) || defined(WIN32)
+# define __LZO_WIN
+# elif defined(__NT__) || defined(__NT_DLL__) || defined(__WINDOWS_386__)
+# define __LZO_WIN
+# elif defined(__DOS__) || defined(__MSDOS__) || defined(MSDOS)
+# define __LZO_DOS
+# elif defined(__OS2__) || defined(__OS2V2__) || defined(OS2)
+# define __LZO_OS2
+# elif defined(__palmos__)
+# define __LZO_PALMOS
+# elif defined(__TOS__) || defined(__atarist__)
+# define __LZO_TOS
+# endif
+#endif
+
+#if (UINT_MAX < LZO_0xffffffffL)
+# if defined(__LZO_WIN)
+# define __LZO_WIN16
+# elif defined(__LZO_DOS)
+# define __LZO_DOS16
+# elif defined(__LZO_PALMOS)
+# define __LZO_PALMOS16
+# elif defined(__LZO_TOS)
+# define __LZO_TOS16
+# elif defined(__C166__)
+# else
+# error "16-bit target not supported - contact me for porting hints"
+# endif
+#endif
+
+#if !defined(__LZO_i386)
+# if defined(__LZO_DOS) || defined(__LZO_WIN16)
+# define __LZO_i386
+# elif defined(__i386__) || defined(__386__) || defined(_M_IX86)
+# define __LZO_i386
+# endif
+#endif
+
+#if defined(__LZO_STRICT_16BIT)
+# if (UINT_MAX < LZO_0xffffffffL)
+# include <lzo16bit.h>
+# endif
+#endif
+
+
+/***********************************************************************
+// integral and pointer types
+************************************************************************/
+
+/* Integral types with 32 bits or more */
+#if !defined(LZO_UINT32_MAX)
+# if (UINT_MAX >= LZO_0xffffffffL)
+ typedef unsigned int lzo_uint32;
+ typedef int lzo_int32;
+# define LZO_UINT32_MAX UINT_MAX
+# define LZO_INT32_MAX INT_MAX
+# define LZO_INT32_MIN INT_MIN
+# elif (ULONG_MAX >= LZO_0xffffffffL)
+ typedef unsigned long lzo_uint32;
+ typedef long lzo_int32;
+# define LZO_UINT32_MAX ULONG_MAX
+# define LZO_INT32_MAX LONG_MAX
+# define LZO_INT32_MIN LONG_MIN
+# else
+# error "lzo_uint32"
+# endif
+#endif
+
+/* lzo_uint is used like size_t */
+#if !defined(LZO_UINT_MAX)
+# if (UINT_MAX >= LZO_0xffffffffL)
+ typedef unsigned int lzo_uint;
+ typedef int lzo_int;
+# define LZO_UINT_MAX UINT_MAX
+# define LZO_INT_MAX INT_MAX
+# define LZO_INT_MIN INT_MIN
+# elif (ULONG_MAX >= LZO_0xffffffffL)
+ typedef unsigned long lzo_uint;
+ typedef long lzo_int;
+# define LZO_UINT_MAX ULONG_MAX
+# define LZO_INT_MAX LONG_MAX
+# define LZO_INT_MIN LONG_MIN
+# else
+# error "lzo_uint"
+# endif
+#endif
+
+
+/* Memory model that allows to access memory at offsets of lzo_uint. */
+#if !defined(__LZO_MMODEL)
+# if (LZO_UINT_MAX <= UINT_MAX)
+# define __LZO_MMODEL
+# elif defined(__LZO_DOS16) || defined(__LZO_WIN16)
+# define __LZO_MMODEL __huge
+# define LZO_999_UNSUPPORTED
+# elif defined(__LZO_PALMOS16) || defined(__LZO_TOS16)
+# define __LZO_MMODEL
+# else
+# error "__LZO_MMODEL"
+# endif
+#endif
+
+/* no typedef here because of const-pointer issues */
+#define lzo_byte unsigned char __LZO_MMODEL
+#define lzo_bytep unsigned char __LZO_MMODEL *
+#define lzo_charp char __LZO_MMODEL *
+#define lzo_voidp void __LZO_MMODEL *
+#define lzo_shortp short __LZO_MMODEL *
+#define lzo_ushortp unsigned short __LZO_MMODEL *
+#define lzo_uint32p lzo_uint32 __LZO_MMODEL *
+#define lzo_int32p lzo_int32 __LZO_MMODEL *
+#define lzo_uintp lzo_uint __LZO_MMODEL *
+#define lzo_intp lzo_int __LZO_MMODEL *
+#define lzo_voidpp lzo_voidp __LZO_MMODEL *
+#define lzo_bytepp lzo_bytep __LZO_MMODEL *
+
+typedef int lzo_bool;
+
+#ifndef lzo_sizeof_dict_t
+# define lzo_sizeof_dict_t sizeof(lzo_bytep)
+#endif
+
+
+/***********************************************************************
+// function types
+************************************************************************/
+
+/* linkage */
+#if !defined(__LZO_EXTERN_C)
+# ifdef __cplusplus
+# define __LZO_EXTERN_C extern "C"
+# else
+# define __LZO_EXTERN_C extern
+# endif
+#endif
+
+/* calling conventions */
+#if !defined(__LZO_CDECL)
+# if defined(__LZO_DOS16) || defined(__LZO_WIN16)
+# define __LZO_CDECL __far __cdecl
+# elif defined(__LZO_i386) && defined(_MSC_VER)
+# define __LZO_CDECL __cdecl
+# elif defined(__LZO_i386) && defined(__WATCOMC__)
+# define __LZO_CDECL __near __cdecl
+# else
+# define __LZO_CDECL
+# endif
+#endif
+#if !defined(__LZO_ENTRY)
+# define __LZO_ENTRY __LZO_CDECL
+#endif
+
+/* DLL export information */
+#if !defined(__LZO_EXPORT1)
+# define __LZO_EXPORT1
+#endif
+#if !defined(__LZO_EXPORT2)
+# define __LZO_EXPORT2
+#endif
+
+/* calling convention for C functions */
+#if !defined(LZO_PUBLIC)
+# define LZO_PUBLIC(_rettype) __LZO_EXPORT1 _rettype __LZO_EXPORT2 __LZO_ENTRY
+#endif
+#if !defined(LZO_EXTERN)
+# define LZO_EXTERN(_rettype) __LZO_EXTERN_C LZO_PUBLIC(_rettype)
+#endif
+#if !defined(LZO_PRIVATE)
+# define LZO_PRIVATE(_rettype) static _rettype __LZO_ENTRY
+#endif
+
+/* cdecl calling convention for assembler functions */
+#if !defined(LZO_PUBLIC_CDECL)
+# define LZO_PUBLIC_CDECL(_rettype) \
+ __LZO_EXPORT1 _rettype __LZO_EXPORT2 __LZO_CDECL
+#endif
+#if !defined(LZO_EXTERN_CDECL)
+# define LZO_EXTERN_CDECL(_rettype) __LZO_EXTERN_C LZO_PUBLIC_CDECL(_rettype)
+#endif
+
+
+typedef int
+(__LZO_ENTRY *lzo_compress_t) ( const lzo_byte *src, lzo_uint src_len,
+ lzo_byte *dst, lzo_uint *dst_len,
+ lzo_voidp wrkmem );
+
+typedef int
+(__LZO_ENTRY *lzo_decompress_t) ( const lzo_byte *src, lzo_uint src_len,
+ lzo_byte *dst, lzo_uint *dst_len,
+ lzo_voidp wrkmem );
+
+typedef int
+(__LZO_ENTRY *lzo_optimize_t) ( lzo_byte *src, lzo_uint src_len,
+ lzo_byte *dst, lzo_uint *dst_len,
+ lzo_voidp wrkmem );
+
+typedef int
+(__LZO_ENTRY *lzo_compress_dict_t)(const lzo_byte *src, lzo_uint src_len,
+ lzo_byte *dst, lzo_uint *dst_len,
+ lzo_voidp wrkmem,
+ const lzo_byte *dict, lzo_uint dict_len );
+
+typedef int
+(__LZO_ENTRY *lzo_decompress_dict_t)(const lzo_byte *src, lzo_uint src_len,
+ lzo_byte *dst, lzo_uint *dst_len,
+ lzo_voidp wrkmem,
+ const lzo_byte *dict, lzo_uint dict_len );
+
+
+/* a progress indicator callback function */
+typedef void (__LZO_ENTRY *lzo_progress_callback_t) (lzo_uint, lzo_uint);
+
+
+/***********************************************************************
+// error codes and prototypes
+************************************************************************/
+
+/* Error codes for the compression/decompression functions. Negative
+ * values are errors, positive values will be used for special but
+ * normal events.
+ */
+#define LZO_E_OK 0
+#define LZO_E_ERROR (-1)
+#define LZO_E_OUT_OF_MEMORY (-2) /* not used right now */
+#define LZO_E_NOT_COMPRESSIBLE (-3) /* not used right now */
+#define LZO_E_INPUT_OVERRUN (-4)
+#define LZO_E_OUTPUT_OVERRUN (-5)
+#define LZO_E_LOOKBEHIND_OVERRUN (-6)
+#define LZO_E_EOF_NOT_FOUND (-7)
+#define LZO_E_INPUT_NOT_CONSUMED (-8)
+
+
+/* lzo_init() should be the first function you call.
+ * Check the return code !
+ *
+ * lzo_init() is a macro to allow checking that the library and the
+ * compiler's view of various types are consistent.
+ */
+#define lzo_init() __lzo_init2(LZO_VERSION,(int)sizeof(short),(int)sizeof(int),\
+ (int)sizeof(long),(int)sizeof(lzo_uint32),(int)sizeof(lzo_uint),\
+ (int)lzo_sizeof_dict_t,(int)sizeof(char *),(int)sizeof(lzo_voidp),\
+ (int)sizeof(lzo_compress_t))
+LZO_EXTERN(int) __lzo_init2(unsigned,int,int,int,int,int,int,int,int,int);
+
+/* version functions (useful for shared libraries) */
+LZO_EXTERN(unsigned) lzo_version(void);
+LZO_EXTERN(const char *) lzo_version_string(void);
+LZO_EXTERN(const char *) lzo_version_date(void);
+LZO_EXTERN(const lzo_charp) _lzo_version_string(void);
+LZO_EXTERN(const lzo_charp) _lzo_version_date(void);
+
+/* string functions */
+LZO_EXTERN(int)
+lzo_memcmp(const lzo_voidp _s1, const lzo_voidp _s2, lzo_uint _len);
+LZO_EXTERN(lzo_voidp)
+lzo_memcpy(lzo_voidp _dest, const lzo_voidp _src, lzo_uint _len);
+LZO_EXTERN(lzo_voidp)
+lzo_memmove(lzo_voidp _dest, const lzo_voidp _src, lzo_uint _len);
+LZO_EXTERN(lzo_voidp)
+lzo_memset(lzo_voidp _s, int _c, lzo_uint _len);
+
+/* checksum functions */
+LZO_EXTERN(lzo_uint32)
+lzo_adler32(lzo_uint32 _adler, const lzo_byte *_buf, lzo_uint _len);
+LZO_EXTERN(lzo_uint32)
+lzo_crc32(lzo_uint32 _c, const lzo_byte *_buf, lzo_uint _len);
+
+/* memory allocation functions */
+LZO_EXTERN(lzo_bytep) lzo_alloc(lzo_uint _nelems, lzo_uint _size);
+LZO_EXTERN(lzo_bytep) lzo_malloc(lzo_uint _size);
+LZO_EXTERN(void) lzo_free(lzo_voidp _ptr);
+
+extern lzo_bytep (__LZO_ENTRY *lzo_alloc_hook) (lzo_uint,lzo_uint);
+extern void (__LZO_ENTRY *lzo_free_hook) (lzo_voidp);
+
+/* misc. */
+LZO_EXTERN(lzo_bool) lzo_assert(int _expr);
+LZO_EXTERN(int) _lzo_config_check(void);
+typedef union { lzo_bytep p; lzo_uint u; } __lzo_pu_u;
+typedef union { lzo_bytep p; lzo_uint32 u32; } __lzo_pu32_u;
+
+/* align a char pointer on a boundary that is a multiple of `size' */
+LZO_EXTERN(unsigned) __lzo_align_gap(const lzo_voidp _ptr, lzo_uint _size);
+#define LZO_PTR_ALIGN_UP(_ptr,_size) \
+ ((_ptr) + (lzo_uint) __lzo_align_gap((const lzo_voidp)(_ptr),(lzo_uint)(_size)))
+
+/* deprecated - only for backward compatibility */
+#define LZO_ALIGN(_ptr,_size) LZO_PTR_ALIGN_UP(_ptr,_size)
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+} // end of namespace MPAL
+
+} // end of namespace Tony
+
+#endif /* already included */
+
diff --git a/engines/tony/module.mk b/engines/tony/module.mk
index 840fbc0dbf..d592fac68b 100644
--- a/engines/tony/module.mk
+++ b/engines/tony/module.mk
@@ -2,7 +2,11 @@ MODULE := engines/tony
MODULE_OBJS := \
detection.o \
- tony.o
+ tony.o \
+ mpal\expr.o \
+ mpal\loadmpc.o \
+ mpal\mpal.o \
+ mpal\stubs.o
# This module can be built as a plugin
ifeq ($(ENABLE_TONY), DYNAMIC_PLUGIN)
diff --git a/engines/tony/mpal.h b/engines/tony/mpal.h
index f0aa5e79e2..0c15ef5b50 100644
--- a/engines/tony/mpal.h
+++ b/engines/tony/mpal.h
@@ -120,6 +120,10 @@
#include "common/rect.h"
+namespace Tony {
+
+namespace MPAL {
+
/****************************************************************************\
* Macro definitions and structures
\****************************************************************************/
@@ -197,10 +201,10 @@ typedef struct {
Common::Rect bbox[MAXFRAMES];
short pattern[MAXPATTERN][MAXFRAMES];
short speed;
- char numframe;
- char numpattern;
- char curframe;
- char curpattern;
+ uint8 numframe;
+ uint8 numpattern;
+ uint8 curframe;
+ uint8 curpattern;
short destX, destY;
signed char Zvalue;
short objectID;
@@ -568,13 +572,9 @@ typedef LPITEMIRQFUNCTION* LPLPITEMIRQFUNCTION;
/****************************************************************************\
-* Functions exported DLL
+* MPAL Interface Functions
\****************************************************************************/
-#ifdef __cplusplus
-extern "C" {
-#endif
-
/****************************************************************************\
*
* Function: bool mpalInit(LPSTR lpszMpcFileName, LPSTR lpszMprFileName,
@@ -741,10 +741,9 @@ void EXPORT mpalSaveState(byte *buf);
int EXPORT mpalGetSaveStateSize(void);
+} // end of namespace MPAL
-#ifdef __cplusplus
-}
-#endif
+} // end of namespace
#endif
diff --git a/engines/tony/mpal/expr.cpp b/engines/tony/mpal/expr.cpp
new file mode 100644
index 0000000000..0faf91744c
--- /dev/null
+++ b/engines/tony/mpal/expr.cpp
@@ -0,0 +1,471 @@
+/* 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.
+ *
+ *
+ */
+/**************************************************************************
+ * ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ *
+ * ... Spyral Software snc *
+ * . x#""*$Nu -= We create much MORE than ALL =- *
+ * d*#R$. R ^#$o ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ *
+ * .F ^$k $ "$b *
+ * ." $b u "$ #$L *
+ * P $c :*$L"$L '$k Project: MPAL................... *
+ * d @$N. $. d ^$b^$k $c *
+ * F 4 "$c '$ $ #$u#$u '$ Module: Expression gestor...... *
+ * 4 4k *N #b .> '$N'*$u * *
+ * M $L #$ $ 8 "$c'#$b.. .@ Author: Giovanni Bajo.......... *
+ * M '$u "$u :" *$. "#*#" *
+ * M '$N. " F ^$k Desc: Gestisce le espressioni *
+ * 4> ^R$oue# d matematiche............ *
+ * '$ "" @ ....................... *
+ * #b u# *
+ * $b .@" OS: [ ] DOS [X] WIN95 [ ] OS/2 *
+ * #$u .d" *
+ * '*$e. .zR".@ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ *
+ * "*$$beooee$*" @"M This source code is *
+ * """ '$.? Copyright (C) Spyral Software *
+ * '$d> ALL RIGHTS RESERVED *
+ * '$> ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ *
+ * *
+ **************************************************************************/
+
+#include "mpal.h"
+#include "mpaldll.h"
+#include "stubs.h"
+
+/*
+#include "lzo1x.h"
+*/
+
+namespace Tony {
+
+namespace MPAL {
+
+/****************************************************************************\
+* Operazioni matematiche gestite
+\****************************************************************************/
+
+#define OP_MUL ((1<<4)|0)
+#define OP_DIV ((1<<4)|1)
+#define OP_MODULE ((1<<4)|2)
+#define OP_ADD ((2<<4)|0)
+#define OP_SUB ((2<<4)|1)
+#define OP_SHL ((3<<4)|0)
+#define OP_SHR ((3<<4)|1)
+#define OP_MINOR ((4<<4)|0)
+#define OP_MAJOR ((4<<4)|1)
+#define OP_MINEQ ((4<<4)|2)
+#define OP_MAJEQ ((4<<4)|3)
+#define OP_EQUAL ((5<<4)|0)
+#define OP_NOEQUAL ((5<<4)|1)
+#define OP_BITAND ((6<<4)|0)
+#define OP_BITXOR ((7<<4)|0)
+#define OP_BITOR ((8<<4)|0)
+#define OP_AND ((9<<4)|0)
+#define OP_OR ((10<<4)|0)
+
+
+/****************************************************************************\
+* enum ExprListTypes
+* ------------------
+* Description: Tipi di oggetto che possono essere contenuti in una struttura
+* EXPRESSION.
+\****************************************************************************/
+
+enum ExprListTypes
+{
+ ELT_NUMBER=1,
+ ELT_VAR=2,
+ ELT_PARENTH=3,
+ ELT_PARENTH2=4
+};
+
+
+/****************************************************************************\
+* Structures
+\****************************************************************************/
+
+/****************************************************************************\
+* typedef EXPRESSION
+* ------------------
+* Description: Struttura per gestire le operazioni matematiche
+\****************************************************************************/
+
+typedef struct {
+ byte type; // Tipo di oggetto (vedi enum ExprListTypes)
+ byte unary; // Unary operatore (NON SUPPORTATO)
+
+ union {
+ int num; // Numero (se type==ELT_NUMBER)
+ char *name; // Nome variabile (se type==ELT_VAR)
+ HGLOBAL son; // Handle a espressione (type==ELT_PARENTH)
+ byte *pson; // Handle lockato (type==ELT_PARENTH2)
+ } val;
+
+ byte symbol; // Simbolo matematico (vedi #define OP_*)
+
+} EXPRESSION;
+typedef EXPRESSION* LPEXPRESSION;
+
+
+/****************************************************************************\
+*
+* Function: LPEXPRESSION DuplicateExpression(HGLOBAL h);
+*
+* Description: Duplica un'espressione matematica. L'espressione duplicata
+* sara' formata da memoria non swappabile.
+*
+* Input: HGLOBAL h Handle dell'espressione originale
+*
+* Return: Pointer all'espressione clone della prima
+*
+\****************************************************************************/
+
+static byte *DuplicateExpression(HGLOBAL h) {
+ int i, num;
+ byte *orig, *clone;
+ LPEXPRESSION one, two;
+
+ orig=(byte *)GlobalLock(h);
+
+ num=*(byte *)orig;
+ one=(LPEXPRESSION)(orig+1);
+
+ clone=GlobalAlloc(GMEM_FIXED,sizeof(EXPRESSION)*num+1);
+ two=(LPEXPRESSION)(clone+1);
+
+ CopyMemory(clone,orig,sizeof(EXPRESSION)*num+1);
+
+ for (i=0;i<num;i++) {
+ if (one->type==ELT_PARENTH) {
+ two->type=ELT_PARENTH2;
+ two->val.pson=DuplicateExpression(two->val.son);
+ }
+
+ one++;
+ two++;
+ }
+
+ GlobalUnlock(h);
+ return clone;
+}
+
+static int Compute(int a, int b, byte symbol) {
+ switch (symbol) {
+ case OP_MUL:
+ return a*b;
+ case OP_DIV:
+ return a/b;
+ case OP_MODULE:
+ return a%b;
+ case OP_ADD:
+ return a+b;
+ case OP_SUB:
+ return a-b;
+ case OP_SHL:
+ return a<<b;
+ case OP_SHR:
+ return a>>b;
+ case OP_MINOR:
+ return a<b;
+ case OP_MAJOR:
+ return a>b;
+ case OP_MINEQ:
+ return a<=b;
+ case OP_MAJEQ:
+ return a>=b;
+ case OP_EQUAL:
+ return a==b;
+ case OP_NOEQUAL:
+ return a!=b;
+ case OP_BITAND:
+ return a&b;
+ case OP_BITXOR:
+ return a^b;
+ case OP_BITOR:
+ return a|b;
+ case OP_AND:
+ return a&&b;
+ case OP_OR:
+ return a||b;
+ default:
+ mpalError=1;
+ break;
+ }
+
+ return 0;
+}
+
+static void Solve(LPEXPRESSION one, int num) {
+ LPEXPRESSION two, three;
+ int j;
+
+ while (num>1) {
+ two=one+1;
+ if ((two->symbol==0) || (one->symbol&0xF0) <= (two->symbol&0xF0)) {
+ two->val.num=Compute(one->val.num,two->val.num,one->symbol);
+ CopyMemory(one,two,(num-1)*sizeof(EXPRESSION));
+ num--;
+ } else {
+ j=1;
+ three=two+1;
+ while ((three->symbol!=0) && (two->symbol&0xF0)>(three->symbol&0xF0)) {
+ two++;
+ three++;
+ j++;
+ }
+
+ three->val.num=Compute(two->val.num,three->val.num,two->symbol);
+ CopyMemory(two,three,(num-j-1)*sizeof(EXPRESSION));
+ num--;
+ }
+ }
+}
+
+
+/****************************************************************************\
+*
+* Function: int EvaluateAndFreeExpression(byte *expr);
+*
+* Description: Calcola il risultato di una espressione matematica, sosti-
+* tuendo ad eventuali variabili il valore corrente.
+*
+* Input: byte *expr Pointer all'espressione duplicata
+* tramite DuplicateExpression
+*
+* Return: Valore dell'espressione
+*
+\****************************************************************************/
+
+static int EvaluateAndFreeExpression(byte *expr) {
+ int i,num,val;
+ LPEXPRESSION one,cur;
+
+ num=*expr;
+ one=(LPEXPRESSION)(expr+1);
+
+ // 1) Sostituzioni delle variabili
+ for (i=0,cur=one;i<num;i++,cur++) {
+ if (cur->type==ELT_VAR) {
+ cur->type=ELT_NUMBER;
+ cur->val.num=varGetValue(cur->val.name);
+ }
+ }
+
+ // 2) Sostituzioni delle parentesi (tramite ricorsione)
+ for (i=0,cur=one;i<num;i++,cur++) {
+ if (cur->type==ELT_PARENTH2) {
+ cur->type=ELT_NUMBER;
+ cur->val.num=EvaluateAndFreeExpression(cur->val.pson);
+ }
+ }
+
+ // 3) Risoluzione algebrica
+ Solve(one,num);
+ val=one->val.num;
+ GlobalFree(expr);
+
+ return val;
+}
+
+/****************************************************************************\
+*
+* Function: byte *ParseExpression(byte *buf, HGLOBAL *h);
+*
+* Description: Esegue il parsing da file .MPC di un'espressione matematica.
+*
+* Input: byte *buf Buffer contenente l'espressione
+* compilata.
+* HGLOBAL *h Pointer a un handle che, alla fine
+* dell'esecuzione, puntera' alla
+* zona di memoria contenete l'espres-
+* sione parsata
+*
+* Return: Puntatore al buffer subito dopo l'espressione, o NULL in caso
+* di errore.
+*
+\****************************************************************************/
+
+byte *ParseExpression(byte *lpBuf, HGLOBAL *h) {
+ LPEXPRESSION cur;
+ byte *start;
+ uint32 num, i;
+
+ num=*lpBuf;
+ lpBuf++;
+
+ if (num==0)
+ return NULL;
+
+ *h=GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT,num*sizeof(EXPRESSION)+1);
+ if (*h==NULL)
+ return NULL;
+
+ start=(byte *)GlobalLock(*h);
+ *start=(byte)num;
+
+ cur=(LPEXPRESSION)(start+1);
+
+ for (i=0;i<num;i++) {
+ cur->type=*(lpBuf);
+ cur->unary=*(lpBuf+1);
+ lpBuf+=2;
+ switch (cur->type) {
+ case ELT_NUMBER:
+ cur->val.num=*(int *)lpBuf;
+ lpBuf+=4;
+ break;
+
+ case ELT_VAR:
+ cur->val.name=(char *)GlobalAlloc(GMEM_FIXED|GMEM_ZEROINIT,(*lpBuf)+1);
+ if (cur->val.name==NULL)
+ return NULL;
+ CopyMemory(cur->val.name,lpBuf+1,*lpBuf);
+ lpBuf+=*lpBuf+1;
+ break;
+
+ case ELT_PARENTH:
+ lpBuf=ParseExpression(lpBuf,&cur->val.son);
+ if (lpBuf==NULL)
+ return NULL;
+ break;
+
+ default:
+ return NULL;
+ }
+
+ cur->symbol=*lpBuf;
+ lpBuf++;
+
+ cur++;
+ }
+
+ if (*lpBuf!=0)
+ return NULL;
+
+ lpBuf++;
+
+ return lpBuf;
+}
+
+
+/****************************************************************************\
+*
+* Function: int EvaluateExpression(HGLOBAL h);
+*
+* Description: Calcola il valore di un'espressione matematica
+*
+* Input: HGLOBAL h Handle all'espressione
+*
+* Return: Valore numerico
+*
+\****************************************************************************/
+
+int EvaluateExpression(HGLOBAL h) {
+ int ret;
+
+ LockVar();
+ ret=EvaluateAndFreeExpression(DuplicateExpression(h));
+ UnlockVar();
+
+ return ret;
+}
+
+
+/****************************************************************************\
+*
+* Function: bool CompareExpressions(HGLOBAL h1, HGLOBAL h2);
+*
+* Description: Confronta due espressioni matematiche tra loro
+*
+* Input: HGLOBAL h1,h2 Espressioni da confrontare
+*
+* Return: true se sono uguali, false se sono diverse
+*
+\****************************************************************************/
+
+bool CompareExpressions(HGLOBAL h1, HGLOBAL h2) {
+ int i,num1,num2;
+ byte *e1, *e2;
+ LPEXPRESSION one, two;
+
+ e1=(byte *)GlobalLock(h1);
+ e2=(byte *)GlobalLock(h2);
+
+ num1=*(byte *)e1;
+ num2=*(byte *)e2;
+
+ if (num1 != num2) {
+ GlobalUnlock(h1);
+ GlobalUnlock(h2);
+ return false;
+ }
+
+ one=(LPEXPRESSION)(e1+1);
+ two=(LPEXPRESSION)(e2+1);
+
+ for (i=0;i<num1;i++) {
+ if (one->type!=two->type || (i!=num1-1 && one->symbol!=two->symbol)) {
+ GlobalUnlock(h1);
+ GlobalUnlock(h2);
+ return false;
+ }
+
+ switch (one->type) {
+ case ELT_NUMBER:
+ if (one->val.num != two->val.num) {
+ GlobalUnlock(h1);
+ GlobalUnlock(h2);
+ return false;
+ }
+ break;
+
+ case ELT_VAR:
+ if (strcmp(one->val.name, two->val.name)!=0) {
+ GlobalUnlock(h1);
+ GlobalUnlock(h2);
+ return false;
+ }
+ break;
+
+ case ELT_PARENTH:
+ if (!CompareExpressions(one->val.son,two->val.son)) {
+ GlobalUnlock(h1);
+ GlobalUnlock(h2);
+ return false;
+ }
+ break;
+ }
+
+ one++;
+ two++;
+ }
+
+ GlobalUnlock(h1);
+ GlobalUnlock(h2);
+
+ return true;
+}
+
+
+} // end of namespace MPAL
+
+} // end of namespace Tony
diff --git a/engines/tony/mpal/expr.h b/engines/tony/mpal/expr.h
new file mode 100644
index 0000000000..d54f17b088
--- /dev/null
+++ b/engines/tony/mpal/expr.h
@@ -0,0 +1,116 @@
+/* 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.
+ *
+ *
+ */
+/**************************************************************************
+ * ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ *
+ * ... Spyral Software snc *
+ * . x#""*$Nu -= We create much MORE than ALL =- *
+ * d*#R$. R ^#$o ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ *
+ * .F ^$k $ "$b *
+ * ." $b u "$ #$L *
+ * P $c :*$L"$L '$k Project: MPAL................... *
+ * d @$N. $. d ^$b^$k $c *
+ * F 4 "$c '$ $ #$u#$u '$ Module: Expression gestor heade *
+ * 4 4k *N #b .> '$N'*$u * *
+ * M $L #$ $ 8 "$c'#$b.. .@ Author: Giovanni Bajo.......... *
+ * M '$u "$u :" *$. "#*#" *
+ * M '$N. " F ^$k Desc: Gestisce le espressioni *
+ * 4> ^R$oue# d matematiche............ *
+ * '$ "" @ ....................... *
+ * #b u# *
+ * $b .@" OS: [ ] DOS [X] WIN95 [ ] OS/2 *
+ * #$u .d" *
+ * '*$e. .zR".@ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ *
+ * "*$$beooee$*" @"M This source code is *
+ * """ '$.? Copyright (C) Spyral Software *
+ * '$d> ALL RIGHTS RESERVED *
+ * '$> ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ *
+ * *
+ **************************************************************************/
+
+#ifndef MPAL_EXPR_H
+#define MPAL_EXPR_H
+
+namespace Tony {
+
+namespace MPAL {
+
+/****************************************************************************\
+* Prototipi di funzione
+\****************************************************************************/
+
+/****************************************************************************\
+*
+* Function: byte *ParseExpression(byte *buf, HGLOBAL *h);
+*
+* Description: Esegue il parsing da file .MPC di un'espressione matematica.
+*
+* Input: byte *buf Buffer contenente l'espressione
+* compilata.
+* HGLOBAL *h Pointer a un handle che, alla fine
+* dell'esecuzione, puntera' alla
+* zona di memoria contenete l'espres-
+* sione parsata
+*
+* Return: Puntatore al buffer subito dopo l'espressione, o NULL in caso
+* di errore.
+*
+\****************************************************************************/
+
+byte *ParseExpression(byte *lpBuf, HGLOBAL *h);
+
+
+/****************************************************************************\
+*
+* Function: int EvaluateExpression(HGLOBAL h);
+*
+* Description: Calcola il valore di un'espressione matematica
+*
+* Input: HGLOBAL h Handle all'espressione
+*
+* Return: Valore numerico
+*
+\****************************************************************************/
+
+int EvaluateExpression(HGLOBAL h);
+
+
+/****************************************************************************\
+*
+* Function: bool CompareExpressions(HGLOBAL h1, HGLOBAL h2);
+*
+* Description: Confronta due espressioni matematiche tra loro
+*
+* Input: HGLOBAL h1,h2 Espressioni da confrontare
+*
+* Return: TRUE se sono uguali, FALSE se sono diverse
+*
+\****************************************************************************/
+
+bool CompareExpressions(HGLOBAL h1, HGLOBAL h2);
+
+
+} // end of namespace MPAL
+
+} // end of namespace Tony
+
+#endif
diff --git a/engines/tony/mpal/loadmpc.cpp b/engines/tony/mpal/loadmpc.cpp
new file mode 100644
index 0000000000..f9426c8d58
--- /dev/null
+++ b/engines/tony/mpal/loadmpc.cpp
@@ -0,0 +1,720 @@
+/* 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.
+ *
+ *
+ */
+/**************************************************************************
+ * ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ *
+ * ... Spyral Software snc *
+ * . x#""*$Nu -= We create much MORE than ALL =- *
+ * d*#R$. R ^#$o ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ *
+ * .F ^$k $ "$b *
+ * ." $b u "$ #$L *
+ * P $c :*$L"$L '$k Project: MPAL................... *
+ * d @$N. $. d ^$b^$k $c *
+ * F 4 "$c '$ $ #$u#$u '$ Module: MPC Loader............. *
+ * 4 4k *N #b .> '$N'*$u * *
+ * M $L #$ $ 8 "$c'#$b.. .@ Author: Giovanni Bajo.......... *
+ * M '$u "$u :" *$. "#*#" *
+ * M '$N. " F ^$k Desc: Legge un file compilato *
+ * 4> ^R$oue# d di MPAL................ *
+ * '$ "" @ ....................... *
+ * #b u# *
+ * $b .@" OS: [ ] DOS [X] WIN95 [ ] OS/2 *
+ * #$u .d" *
+ * '*$e. .zR".@ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ *
+ * "*$$beooee$*" @"M This source code is *
+ * """ '$.? Copyright (C) Spyral Software *
+ * '$d> ALL RIGHTS RESERVED *
+ * '$> ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ *
+ * *
+ **************************************************************************/
+
+/*
+#include "lzo1x.h"
+*/
+#include "mpal.h"
+#include "mpaldll.h"
+
+namespace Tony {
+
+namespace MPAL {
+
+
+/****************************************************************************\
+* Funzioni statiche
+\****************************************************************************/
+
+static bool CompareCommands(struct command *cmd1, struct command *cmd2) {
+ if (cmd1->type == 2 && cmd2->type == 2) {
+ if (strcmp(cmd1->lpszVarName,cmd2->lpszVarName)==0 &&
+ CompareExpressions(cmd1->expr,cmd2->expr))
+ return true;
+ else
+ return false;
+ } else
+ return (memcmp(cmd1,cmd2,sizeof(struct command))==0);
+}
+
+
+/****************************************************************************\
+*
+* Function: LPBTYE ParseScript(byte *lpBuf, LPMPALSCRIPT lpmsScript);
+*
+* Description: Esegue il parsing da file .MPC di uno script e inserisce il
+* tutto dentro una struttura
+*
+* Input: byte *lpBuf Buffer contenente lo script compilato
+* LPMPALSCRIPT lpmsScript Puntatore a una struttura che verra'
+* riempita con i dati dello script
+* lato
+*
+* Return: Puntatore al buffer dopo l'item, o NULL in caso di errore
+*
+\****************************************************************************/
+
+static byte *ParseScript(byte *lpBuf, LPMPALSCRIPT lpmsScript) {
+ int curCmd,j,len;
+ uint i;
+
+ lpmsScript->nObj=*(int *)lpBuf;
+ lpBuf+=4;
+
+ lpmsScript->nMoments=*(uint16 *)lpBuf;
+ lpBuf+=2;
+
+ curCmd=0;
+
+ for (i=0;i<lpmsScript->nMoments;i++) {
+ lpmsScript->Moment[i].dwTime=*(int *)lpBuf; lpBuf+=4;
+ lpmsScript->Moment[i].nCmds=*lpBuf; lpBuf++;
+
+ for (j=0;j<lpmsScript->Moment[i].nCmds;j++) {
+ lpmsScript->Command[curCmd].type=*lpBuf; lpBuf++;
+ switch (lpmsScript->Command[curCmd].type) {
+ case 1:
+ lpmsScript->Command[curCmd].nCf =*(uint16 *)(lpBuf); lpBuf+=2;
+ lpmsScript->Command[curCmd].arg1=*(int *)(lpBuf); lpBuf+=4;
+ lpmsScript->Command[curCmd].arg2=*(int *)(lpBuf); lpBuf+=4;
+ lpmsScript->Command[curCmd].arg3=*(int *)(lpBuf); lpBuf+=4;
+ lpmsScript->Command[curCmd].arg4=*(int *)(lpBuf); lpBuf+=4;
+ break;
+
+ case 2: // Variable assign
+ len=*lpBuf; lpBuf++;
+ lpmsScript->Command[curCmd].lpszVarName=(char *)GlobalAlloc(GMEM_FIXED|GMEM_ZEROINIT,len+1);
+ if (lpmsScript->Command[curCmd].lpszVarName==NULL)
+ return NULL;
+ CopyMemory(lpmsScript->Command[curCmd].lpszVarName, lpBuf, len);
+ lpBuf+=len;
+
+ lpBuf=ParseExpression(lpBuf,&lpmsScript->Command[curCmd].expr);
+ if (lpBuf==NULL)
+ return NULL;
+ break;
+
+ default:
+ return NULL;
+ }
+
+ lpmsScript->Moment[i].CmdNum[j]=curCmd;
+ curCmd++;
+ }
+ }
+
+ return lpBuf;
+}
+
+
+/****************************************************************************\
+*
+* Function: byte *ParseDialog(byte *lpBuf, LPMPALDIALOG lpmdDialog);
+*
+* Description: Esegue il parsing da file .MPC di un dialog, e inserisce il
+* tutto dentro una struttura
+*
+* Input: byte *lpBuf Buffer contenente il dialogo compi-
+* lato
+* LPMPALDIALOG lpmdDialog Puntatore a una struttura che verra'
+* riempita con i dati del dialogo
+* compilato
+*
+* Return: Puntatore al buffer dopo il dialogo, o NULL in caso di errore
+*
+\****************************************************************************/
+
+static byte *ParseDialog(byte *lpBuf, LPMPALDIALOG lpmdDialog) {
+ uint32 i,j,z,kk;
+ uint32 num,num2,num3;
+ byte *lpLock;
+ uint32 curCmd;
+ uint32 len;
+
+ lpmdDialog->nObj=*(int *)lpBuf;
+ lpBuf+=4;
+
+ /* Periodi */
+ num=*(uint16 *)lpBuf; lpBuf+=2;
+
+ if (num >= MAX_PERIODS_PER_DIALOG-1) {
+ Common::String msg = Common::String::format("Too much periods in dialog #%d",lpmdDialog->nObj);
+ MessageBox(msg);
+ }
+
+ for (i=0;i<num;i++) {
+ lpmdDialog->PeriodNums[i]=*(uint16 *)lpBuf; lpBuf+=2;
+ lpmdDialog->Periods[i]=GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT,*lpBuf+1);
+ lpLock = (byte *)GlobalLock(lpmdDialog->Periods[i]);
+ CopyMemory(lpLock,lpBuf+1,*lpBuf);
+ GlobalUnlock(lpmdDialog->Periods[i]);
+ lpBuf+=(*lpBuf)+1;
+ }
+
+ lpmdDialog->PeriodNums[i]=0;
+ lpmdDialog->Periods[i]=NULL;
+
+ /* Gruppi */
+ num=*(uint16 *)lpBuf; lpBuf+=2;
+ curCmd=0;
+
+ if (num >= MAX_GROUPS_PER_DIALOG) {
+ Common::String msg = Common::String::format("Too much groups in dialog #%d",lpmdDialog->nObj);
+ MessageBox(msg);
+ }
+
+ for (i=0;i<num;i++) {
+ lpmdDialog->Group[i].num=*(uint16 *)lpBuf; lpBuf+=2;
+ lpmdDialog->Group[i].nCmds=*lpBuf; lpBuf++;
+
+ if (lpmdDialog->Group[i].nCmds >= MAX_COMMANDS_PER_GROUP) {
+ Common::String msg = Common::String::format("Too much commands in group #%d in dialog #%d",lpmdDialog->Group[i].num,lpmdDialog->nObj);
+ MessageBox(msg);
+ }
+
+ for (j=0;j<lpmdDialog->Group[i].nCmds;j++) {
+ lpmdDialog->Command[curCmd].type=*lpBuf;
+ lpBuf++;
+
+ switch (lpmdDialog->Command[curCmd].type) {
+ // Call custom function
+ case 1:
+ lpmdDialog->Command[curCmd].nCf =*(uint16 *)(lpBuf); lpBuf+=2;
+ lpmdDialog->Command[curCmd].arg1=*(int *)(lpBuf); lpBuf+=4;
+ lpmdDialog->Command[curCmd].arg2=*(int *)(lpBuf); lpBuf+=4;
+ lpmdDialog->Command[curCmd].arg3=*(int *)(lpBuf); lpBuf+=4;
+ lpmdDialog->Command[curCmd].arg4=*(int *)(lpBuf); lpBuf+=4;
+ break;
+
+ // Variable assign
+ case 2:
+ len=*lpBuf;
+ lpBuf++;
+ lpmdDialog->Command[curCmd].lpszVarName=(char *)GlobalAlloc(GMEM_FIXED|GMEM_ZEROINIT,len+1);
+ if (lpmdDialog->Command[curCmd].lpszVarName==NULL)
+ return NULL;
+ CopyMemory(lpmdDialog->Command[curCmd].lpszVarName,lpBuf,len);
+ lpBuf+=len;
+
+ lpBuf=ParseExpression(lpBuf,&lpmdDialog->Command[curCmd].expr);
+ if (lpBuf==NULL)
+ return NULL;
+ break;
+
+ // Do Choice
+ case 3:
+ lpmdDialog->Command[curCmd].nChoice=*(uint16 *)lpBuf; lpBuf+=2;
+ break;
+
+ default:
+ return NULL;
+ }
+
+ for (kk=0;kk<curCmd;kk++) {
+ if (CompareCommands(&lpmdDialog->Command[kk],&lpmdDialog->Command[curCmd])) {
+ lpmdDialog->Group[i].CmdNum[j]=kk;
+ break;
+ }
+ }
+
+ if (kk==curCmd) {
+ lpmdDialog->Group[i].CmdNum[j]=curCmd;
+ curCmd++;
+ }
+ }
+ }
+
+ if (curCmd >= MAX_COMMANDS_PER_DIALOG) {
+ Common::String msg = Common::String::format("Too much commands in dialog #%d",lpmdDialog->nObj);
+ MessageBox(msg);
+ }
+
+ /* Choices */
+ num=*(uint16 *)lpBuf; lpBuf+=2;
+
+ if (num >= MAX_CHOICES_PER_DIALOG) {
+ Common::String msg = Common::String::format("Too much choices in dialog #%d",lpmdDialog->nObj);
+ MessageBox(msg);
+ }
+
+ for (i=0;i<num;i++) {
+ lpmdDialog->Choice[i].nChoice=*(uint16 *)lpBuf; lpBuf+=2;
+
+ num2=*lpBuf++;
+
+ if (num2 >= MAX_SELECTS_PER_CHOICE) {
+ Common::String msg = Common::String::format("Too much selects in choice #%d in dialog #%d",lpmdDialog->Choice[i].nChoice,lpmdDialog->nObj);
+ MessageBox(msg);
+ }
+
+ for (j=0;j<num2;j++) {
+ // When
+ switch (*lpBuf++) {
+ case 0:
+ lpmdDialog->Choice[i].Select[j].when=NULL;
+ break;
+
+ case 1:
+ lpBuf=ParseExpression(lpBuf,&lpmdDialog->Choice[i].Select[j].when);
+ if (lpBuf==NULL)
+ return NULL;
+ break;
+
+ case 2:
+ return NULL;
+ }
+
+ // Attrib
+ lpmdDialog->Choice[i].Select[j].attr=*lpBuf++;
+
+ // Data
+ lpmdDialog->Choice[i].Select[j].dwData=*(uint32 *)lpBuf; lpBuf+=4;
+
+ // PlayGroup
+ num3=*lpBuf; *lpBuf++;
+
+ if (num3 >= MAX_PLAYGROUPS_PER_SELECT) {
+ Common::String msg = Common::String::format("Too much playgroups in select #%d in choice #%d in dialog #%d",j,lpmdDialog->Choice[i].nChoice,lpmdDialog->nObj);
+ MessageBox(msg);
+ }
+
+ for (z=0;z<num3;z++) {
+ lpmdDialog->Choice[i].Select[j].wPlayGroup[z]=*(uint16 *)lpBuf; lpBuf+=2;
+ }
+
+ lpmdDialog->Choice[i].Select[j].wPlayGroup[num3]=0;
+ }
+
+ // Segna l'ultimo select
+ lpmdDialog->Choice[i].Select[num2].dwData=0;
+ }
+
+ lpmdDialog->Choice[num].nChoice=0;
+
+ return lpBuf;
+}
+
+/****************************************************************************\
+*
+* Function: byte *ParseItem(byte *lpBuf, LPMPALITEM lpmiItem);
+*
+* Description: Esegue il parsing da file .MPC di un item, e inserisce il
+* tutto dentro una struttura
+*
+* Input: byte *lpBuf Buffer contenete l'item compilato
+* LPMPALITEM lpmiItem Puntatore a una struttura che verra'
+* riempita con i dati dell'item
+* compilato
+*
+* Return: Puntatore al buffer dopo l'item, o NULL in caso di errore
+*
+* Note: E' necessario che la struttura passata come parametro sia
+* stata completamente inizializzata a 0 (con una ZeroMemory,
+* ad esempio).
+*
+\****************************************************************************/
+
+static byte *ParseItem(byte *lpBuf, LPMPALITEM lpmiItem) {
+ byte len;
+ uint32 i,j,kk;
+ uint32 curCmd;
+
+ lpmiItem->nObj=*(int *)lpBuf;
+ lpBuf+=4;
+
+ len=*lpBuf;
+ lpBuf++;
+ CopyMemory(lpmiItem->lpszDescribe,lpBuf, MIN((byte)127, len));
+ lpBuf+=len;
+
+ if (len >= MAX_DESCRIBE_SIZE) {
+ Common::String msg = Common::String::format("Describe too long in item #%d",lpmiItem->nObj);
+ MessageBox(msg);
+ }
+
+ lpmiItem->nActions=*lpBuf;
+ lpBuf++;
+
+ /* Alloca le azioni */
+ if (lpmiItem->nActions>0)
+ lpmiItem->Action = (ItemAction *)GlobalAlloc(GMEM_FIXED|GMEM_ZEROINIT,sizeof(struct ItemAction)*(int)lpmiItem->nActions);
+
+ curCmd=0;
+
+ for (i=0;i<lpmiItem->nActions;i++) {
+ lpmiItem->Action[i].num=*lpBuf;
+ lpBuf++;
+
+ lpmiItem->Action[i].wParm=*(uint16 *)lpBuf;
+ lpBuf+=2;
+
+ if (lpmiItem->Action[i].num==0xFF) {
+ lpmiItem->Action[i].wTime=*(uint16 *)lpBuf;
+ lpBuf+=2;
+
+ lpmiItem->Action[i].perc=*lpBuf;
+ lpBuf++;
+ }
+
+
+ if (*lpBuf==0) {
+ lpBuf++;
+ lpmiItem->Action[i].when=NULL;
+ } else {
+ lpBuf++;
+ lpBuf=ParseExpression(lpBuf,&lpmiItem->Action[i].when);
+ if (lpBuf==NULL)
+ return NULL;
+ }
+
+ lpmiItem->Action[i].nCmds=*lpBuf;
+ lpBuf++;
+
+ if (lpmiItem->Action[i].nCmds >= MAX_COMMANDS_PER_ACTION) {
+ Common::String msg = Common::String::format("Too much commands in action #%d in item #%d",lpmiItem->Action[i].num,lpmiItem->nObj);
+ MessageBox(msg);
+ }
+
+ for (j=0;j<lpmiItem->Action[i].nCmds;j++) {
+ lpmiItem->Command[curCmd].type=*lpBuf;
+ lpBuf++;
+ switch (lpmiItem->Command[curCmd].type) {
+ case 1: // Call custom function
+ lpmiItem->Command[curCmd].nCf =*(uint16 *)(lpBuf); lpBuf+=2;
+ lpmiItem->Command[curCmd].arg1=*(int *)(lpBuf); lpBuf+=4;
+ lpmiItem->Command[curCmd].arg2=*(int *)(lpBuf); lpBuf+=4;
+ lpmiItem->Command[curCmd].arg3=*(int *)(lpBuf); lpBuf+=4;
+ lpmiItem->Command[curCmd].arg4=*(int *)(lpBuf); lpBuf+=4;
+ break;
+
+ case 2: // Variable assign
+ len=*lpBuf;
+ lpBuf++;
+ lpmiItem->Command[curCmd].lpszVarName=(char *)GlobalAlloc(GMEM_FIXED|GMEM_ZEROINIT,len+1);
+ if (lpmiItem->Command[curCmd].lpszVarName==NULL)
+ return NULL;
+ CopyMemory(lpmiItem->Command[curCmd].lpszVarName,lpBuf,len);
+ lpBuf+=len;
+
+ lpBuf=ParseExpression(lpBuf,&lpmiItem->Command[curCmd].expr);
+ if (lpBuf==NULL)
+ return NULL;
+ break;
+
+ default:
+ return NULL;
+ }
+
+ for (kk=0;kk<curCmd;kk++) {
+ if (CompareCommands(&lpmiItem->Command[kk],&lpmiItem->Command[curCmd])) {
+ lpmiItem->Action[i].CmdNum[j]=kk;
+ break;
+ }
+ }
+
+ if (kk==curCmd) {
+ lpmiItem->Action[i].CmdNum[j]=curCmd;
+ curCmd++;
+
+ if (curCmd >= MAX_COMMANDS_PER_ITEM) {
+ Common::String msg = Common::String::format("Too much commands in item #%d",lpmiItem->nObj);
+ MessageBox(msg);
+ curCmd=0;
+ }
+ }
+ }
+ }
+
+ lpmiItem->dwRes=*(uint32 *)lpBuf; lpBuf+=4;
+
+ return lpBuf;
+}
+
+
+/****************************************************************************\
+*
+* Function: byte *ParseLocation(byte *buf, LPMPALLOCATIONN lpmlLocation)
+*
+* Description: Esegue il parsing da file .MPC di una locazione, riempendo
+* una struttura
+*
+* Input: byte *buf Buffer contenente la locazione
+* compilata
+* LPMPALLOCATION
+* lpmlLocation Pointer alla struttura che verra'
+* riempita con i dati sulla locazione
+*
+* Return: Puntatore al buffer dopo l'item, o NULL in caso di errore
+*
+\****************************************************************************/
+
+static byte *ParseLocation(byte *lpBuf, LPMPALLOCATION lpmlLocation) {
+ lpmlLocation->nObj=*(int *)lpBuf;
+ lpBuf+=4;
+ lpmlLocation->dwXlen=*(uint16 *)lpBuf;
+ lpBuf+=2;
+ lpmlLocation->dwYlen=*(uint16 *)lpBuf;
+ lpBuf+=2;
+ lpmlLocation->dwPicRes=*(uint32 *)lpBuf;
+ lpBuf+=4;
+
+ return lpBuf;
+}
+
+/*static int CompareMoments(int * a, int * b) {
+ if (*a<*b)
+ return -1;
+ else if (*a>*b)
+ return 1;
+ else
+ return 0;
+}*/
+
+/****************************************************************************\
+* Funzioni globali
+\****************************************************************************/
+
+/****************************************************************************\
+*
+* Function: bool ParseMpc(byte *lpBuf);
+*
+* Description: Legge e interpreta un file MPC, e crea le strutture per le
+* varie direttive nelle variabili globali
+*
+* Input: byte *lpBuf Immagine in memoria del file MPC,
+* escluso l'header
+*
+* Return: true se tutto OK, false in caso di errore.
+*
+\****************************************************************************/
+
+bool ParseMpc(byte *lpBuf) {
+ uint16 i,j;
+ uint16 wLen;
+ byte *lpTemp, *lpTemp2;
+
+ // Oggetti dummy. Definiti static per evitare stack overflow
+ static MPALITEM dummyitem;
+ static MPALLOCATION dummylocation;
+ static MPALSCRIPT dummyscript;
+ static MPALDIALOG dummydialog;
+
+ /* 1. Variabili */
+ if (lpBuf[0]!='V' || lpBuf[1]!='A' || lpBuf[2]!='R' || lpBuf[3]!='S')
+ return false;
+
+ lpBuf+=4;
+ nVars=*(uint16 *)lpBuf;
+ lpBuf+=2;
+
+ hVars=GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT,sizeof(MPALVAR)*(uint32)nVars);
+ if (hVars==NULL)
+ return false;
+
+ lpmvVars=(LPMPALVAR)GlobalLock(hVars);
+
+ for (i=0;i<nVars;i++) {
+ wLen=*(byte *)lpBuf;
+ lpBuf++;
+ CopyMemory(lpmvVars->lpszVarName,lpBuf,MIN(wLen, (uint16)32));
+ lpBuf+=wLen;
+ lpmvVars->dwVal=*(int *)lpBuf;
+ lpBuf+=4;
+
+ lpBuf++; // Salta 'ext'
+ lpmvVars++;
+ }
+
+ GlobalUnlock(hVars);
+
+ /* 2. Messaggi */
+ if (lpBuf[0]!='M' || lpBuf[1]!='S' || lpBuf[2]!='G' || lpBuf[3]!='S')
+ return false;
+
+ lpBuf+=4;
+ nMsgs=*(uint16 *)lpBuf;
+ lpBuf+=2;
+
+#ifdef NEED_LOCK_MSGS
+ hMsgs=GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT,sizeof(MPALMSG)*(uint32)nMsgs);
+ if (hMsgs==NULL)
+ return false;
+
+ lpmmMsgs=(LPMPALMSG)GlobalLock(hMsgs);
+#else
+ lpmmMsgs=(LPMPALMSG)GlobalAlloc(GMEM_FIXED|GMEM_ZEROINIT,sizeof(MPALMSG)*(uint32)nMsgs);
+ if (lpmmMsgs==NULL)
+ return false;
+#endif
+
+ for (i=0;i<nMsgs;i++) {
+ lpmmMsgs->wNum=*(uint16 *)lpBuf;
+ lpBuf+=2;
+
+ for (j=0;lpBuf[j]!=0;)
+ j+=lpBuf[j]+1;
+
+ lpmmMsgs->hText=GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT,j+1);
+ lpTemp2=lpTemp=(byte *)GlobalLock(lpmmMsgs->hText);
+
+ for (j=0;lpBuf[j]!=0;) {
+ CopyMemory(lpTemp,&lpBuf[j+1],lpBuf[j]);
+ lpTemp+=lpBuf[j];
+ *lpTemp++='\0';
+ j+=lpBuf[j]+1;
+ }
+
+ lpBuf+=j+1;
+ *lpTemp='\0';
+
+ GlobalUnlock(lpmmMsgs->hText);
+ lpmmMsgs++;
+ }
+
+#ifdef NEED_LOCK_MSGS
+ GlobalUnlock(hMsgs);
+#endif
+
+ /* 3. Oggetti */
+ if (lpBuf[0]!='O' || lpBuf[1]!='B' || lpBuf[2]!='J' || lpBuf[3]!='S')
+ return false;
+
+ lpBuf+=4;
+ nObjs=*(uint16 *)lpBuf;
+ lpBuf+=2;
+
+ // Controlla i dialoghi
+ nDialogs=0;
+ hDialogs=lpmdDialogs=NULL;
+ if (*((const char *)lpBuf+2)==6 && strncmp((const char *)lpBuf+3,"Dialog",6)==0) {
+ nDialogs=*(uint16 *)lpBuf; lpBuf+=2;
+
+ hDialogs=GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT,(uint32)nDialogs*sizeof(MPALDIALOG));
+ if (hDialogs==NULL)
+ return false;
+
+ lpmdDialogs=(LPMPALDIALOG)GlobalLock(hDialogs);
+
+ for (i=0;i<nDialogs;i++)
+ if ((lpBuf=ParseDialog(lpBuf+7,&lpmdDialogs[i]))==NULL)
+ return false;
+
+ GlobalUnlock(hDialogs);
+ }
+
+ // Controlla gli item
+ nItems=0;
+ hItems=lpmiItems=NULL;
+ if (*(lpBuf+2)==4 && strncmp((const char *)lpBuf+3,"Item",4)==0) {
+ nItems=*(uint16 *)lpBuf; lpBuf+=2;
+
+ // Alloca la memoria e li legge
+ hItems=GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT,(uint32)nItems*sizeof(MPALITEM));
+ if (hItems==NULL)
+ return false;
+
+ lpmiItems=(LPMPALITEM)GlobalLock(hItems);
+
+ for (i=0;i<nItems;i++)
+ if ((lpBuf=ParseItem(lpBuf+5,&lpmiItems[i]))==NULL)
+ return false;
+
+ GlobalUnlock(hItems);
+ }
+
+ // Controlla le locazioni
+ nLocations=0;
+ hLocations=lpmlLocations=NULL;
+ if (*(lpBuf+2)==8 && strncmp((const char *)lpBuf+3,"Location",8)==0) {
+ nLocations=*(uint16 *)lpBuf; lpBuf+=2;
+
+ // Alloca la memoria e li legge
+ hLocations=GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT,(uint32)nLocations*sizeof(MPALLOCATION));
+ if (hLocations==NULL)
+ return false;
+
+ lpmlLocations=(LPMPALLOCATION)GlobalLock(hLocations);
+
+ for (i=0;i<nLocations;i++)
+ if ((lpBuf=ParseLocation(lpBuf+9,&lpmlLocations[i]))==NULL)
+ return false;
+
+ GlobalUnlock(hLocations);
+ }
+
+ // Controlla gli script
+ nScripts=0;
+ hScripts=lpmsScripts=NULL;
+ if (*(lpBuf+2)==6 && strncmp((const char *)lpBuf+3,"Script",6)==0) {
+ nScripts=*(uint16 *)lpBuf; lpBuf+=2;
+
+ // Alloca la memoria
+ hScripts=GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT,(uint32)nScripts*sizeof(MPALSCRIPT));
+ if (hScripts==NULL)
+ return false;
+
+ lpmsScripts=(LPMPALSCRIPT)GlobalLock(hScripts);
+
+ for (i=0;i<nScripts;i++) {
+ if ((lpBuf=ParseScript(lpBuf+7,&lpmsScripts[i]))==NULL)
+ return false;
+
+ // Ordina i vari moments dello script
+ //qsort(
+ //lpmsScripts[i].Moment,
+ //lpmsScripts[i].nMoments,
+ //sizeof(lpmsScripts[i].Moment[0]),
+ //(int (*)(const void *, const void *))CompareMoments
+ //);
+
+ }
+
+ GlobalUnlock(hScripts);
+ }
+
+ if (lpBuf[0]!='E' || lpBuf[1]!='N' || lpBuf[2]!='D' || lpBuf[3]!='0')
+ return false;
+
+ return true;
+}
+
+
+} // end of namespace MPAL
+
+} // end of namespace Tony
diff --git a/engines/tony/mpal/loadmpc.h b/engines/tony/mpal/loadmpc.h
new file mode 100644
index 0000000000..8763fbf95b
--- /dev/null
+++ b/engines/tony/mpal/loadmpc.h
@@ -0,0 +1,83 @@
+/* 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.
+ *
+ *
+ */
+/**************************************************************************
+ * ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ *
+ * ... Spyral Software snc *
+ * . x#""*$Nu -= We create much MORE than ALL =- *
+ * d*#R$. R ^#$o ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ *
+ * .F ^$k $ "$b *
+ * ." $b u "$ #$L *
+ * P $c :*$L"$L '$k Project: MPAL................... *
+ * d @$N. $. d ^$b^$k $c *
+ * F 4 "$c '$ $ #$u#$u '$ Module: MPC Loader Header...... *
+ * 4 4k *N #b .> '$N'*$u * *
+ * M $L #$ $ 8 "$c'#$b.. .@ Author: Giovanni Bajo.......... *
+ * M '$u "$u :" *$. "#*#" *
+ * M '$N. " F ^$k Desc: Legge un file compilato *
+ * 4> ^R$oue# d MPC.................... *
+ * '$ "" @ ....................... *
+ * #b u# *
+ * $b .@" OS: [ ] DOS [X] WIN95 [ ] OS/2 *
+ * #$u .d" *
+ * '*$e. .zR".@ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ *
+ * "*$$beooee$*" @"M This source code is *
+ * """ '$.? Copyright (C) Spyral Software *
+ * '$d> ALL RIGHTS RESERVED *
+ * '$> ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ *
+ * *
+ **************************************************************************/
+
+#ifndef __LOADMPC_H
+#define __LOADMPC_H
+
+namespace Tony {
+
+namespace MPAL {
+
+/****************************************************************************\
+* Prototipi di funzione
+\****************************************************************************/
+
+/****************************************************************************\
+*
+* Function: BOOL ParseMpc(LPBYTE lpBuf);
+*
+* Description: Legge e interpreta un file MPC, e crea le strutture per le
+* varie direttive nelle variabili globali
+*
+* Input: LPBYTE lpBuf Immagine in memoria del file MPC,
+* escluso l'header
+*
+* Return: TRUE se tutto OK, FALSE in caso di errore.
+*
+\****************************************************************************/
+
+bool ParseMpc(const byte *lpBuf);
+
+
+} // end of namespace MPAL
+
+} // end of namespace Tony
+
+#endif
+
diff --git a/engines/tony/mpal/lzo1x.h b/engines/tony/mpal/lzo1x.h
new file mode 100644
index 0000000000..83b547428c
--- /dev/null
+++ b/engines/tony/mpal/lzo1x.h
@@ -0,0 +1,188 @@
+/* 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.
+ *
+ *
+ */
+/* lzo1x.h -- public interface of the LZO1X compression algorithm
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
+ Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
+
+ The LZO library 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.
+
+ The LZO library 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 the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Markus F.X.J. Oberhumer
+ <markus.oberhumer@jk.uni-linz.ac.at>
+ http://wildsau.idv.uni-linz.ac.at/mfx/lzo.html
+ */
+
+
+#ifndef __LZO1X_H
+#define __LZO1X_H
+
+#ifndef __LZOCONF_H
+#include "lzoconf.h"
+#endif
+
+namespace Tony {
+
+namespace MPAL {
+
+/***********************************************************************
+//
+************************************************************************/
+
+/* Memory required for the wrkmem parameter.
+ * When the required size is 0, you can also pass a NULL pointer.
+ */
+
+#define LZO1X_MEM_COMPRESS LZO1X_1_MEM_COMPRESS
+#define LZO1X_MEM_DECOMPRESS (0)
+#define LZO1X_MEM_OPTIMIZE (0)
+
+
+/* decompression */
+LZO_EXTERN(int)
+lzo1x_decompress ( const lzo_byte *src, lzo_uint src_len,
+ lzo_byte *dst, lzo_uint *dst_len,
+ lzo_voidp wrkmem /* NOT USED */ );
+
+/* safe decompression with overrun testing */
+LZO_EXTERN(int)
+lzo1x_decompress_safe ( const lzo_byte *src, lzo_uint src_len,
+ lzo_byte *dst, lzo_uint *dst_len,
+ lzo_voidp wrkmem /* NOT USED */ );
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+#define LZO1X_1_MEM_COMPRESS ((lzo_uint32) (16384L * lzo_sizeof_dict_t))
+
+LZO_EXTERN(int)
+lzo1x_1_compress ( const lzo_byte *src, lzo_uint src_len,
+ lzo_byte *dst, lzo_uint *dst_len,
+ lzo_voidp wrkmem );
+
+
+/***********************************************************************
+// special compressor versions
+************************************************************************/
+
+/* this version needs only 8 kB work memory */
+#define LZO1X_1_11_MEM_COMPRESS ((lzo_uint32) (2048L * lzo_sizeof_dict_t))
+
+LZO_EXTERN(int)
+lzo1x_1_11_compress ( const lzo_byte *src, lzo_uint src_len,
+ lzo_byte *dst, lzo_uint *dst_len,
+ lzo_voidp wrkmem );
+
+
+/* this version needs 16 kB work memory */
+#define LZO1X_1_12_MEM_COMPRESS ((lzo_uint32) (4096L * lzo_sizeof_dict_t))
+
+LZO_EXTERN(int)
+lzo1x_1_12_compress ( const lzo_byte *src, lzo_uint src_len,
+ lzo_byte *dst, lzo_uint *dst_len,
+ lzo_voidp wrkmem );
+
+
+/* use this version if you need a little more compression speed */
+#define LZO1X_1_15_MEM_COMPRESS ((lzo_uint32) (32768L * lzo_sizeof_dict_t))
+
+LZO_EXTERN(int)
+lzo1x_1_15_compress ( const lzo_byte *src, lzo_uint src_len,
+ lzo_byte *dst, lzo_uint *dst_len,
+ lzo_voidp wrkmem );
+
+
+/***********************************************************************
+// better compression ratio at the cost of more memory and time
+************************************************************************/
+
+#define LZO1X_999_MEM_COMPRESS ((lzo_uint32) (14 * 16384L * sizeof(short)))
+
+#if !defined(LZO_999_UNSUPPORTED)
+LZO_EXTERN(int)
+lzo1x_999_compress ( const lzo_byte *src, lzo_uint src_len,
+ lzo_byte *dst, lzo_uint *dst_len,
+ lzo_voidp wrkmem );
+#endif
+
+
+/***********************************************************************
+//
+************************************************************************/
+
+#if !defined(LZO_999_UNSUPPORTED)
+LZO_EXTERN(int)
+lzo1x_999_compress_dict ( const lzo_byte *in , lzo_uint in_len,
+ lzo_byte *out, lzo_uint *out_len,
+ lzo_voidp wrkmem,
+ const lzo_byte *dict, lzo_uint dict_len );
+
+LZO_EXTERN(int)
+lzo1x_999_compress_level ( const lzo_byte *in , lzo_uint in_len,
+ lzo_byte *out, lzo_uint *out_len,
+ lzo_voidp wrkmem,
+ const lzo_byte *dict, lzo_uint dict_len,
+ lzo_progress_callback_t cb,
+ int compression_level );
+#endif
+
+LZO_EXTERN(int)
+lzo1x_decompress_dict_safe ( const lzo_byte *in, lzo_uint in_len,
+ lzo_byte *out, lzo_uint *out_len,
+ lzo_voidp wrkmem /* NOT USED */,
+ const lzo_byte *dict, lzo_uint dict_len );
+
+
+/***********************************************************************
+// optimize a compressed data block
+************************************************************************/
+
+LZO_EXTERN(int)
+lzo1x_optimize ( lzo_byte *in , lzo_uint in_len,
+ lzo_byte *out, lzo_uint *out_len,
+ lzo_voidp wrkmem );
+
+
+} // end of namespace MPAL
+
+} // end of namespace Tony
+
+#endif /* already included */
diff --git a/engines/tony/mpal/mpal.cpp b/engines/tony/mpal/mpal.cpp
new file mode 100644
index 0000000000..2fd9f3b9c3
--- /dev/null
+++ b/engines/tony/mpal/mpal.cpp
@@ -0,0 +1,3071 @@
+/* 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.
+ *
+ *
+ */
+/**************************************************************************
+ * ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ *
+ * ... Spyral Software snc *
+ * . x#""*$Nu -= We create much MORE than ALL =- *
+ * d*#R$. R ^#$o ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ *
+ * .F ^$k $ "$b *
+ * ." $b u "$ #$L *
+ * P $c :*$L"$L '$k Project: MPAL................... *
+ * d @$N. $. d ^$b^$k $c *
+ * F 4 "$c '$ $ #$u#$u '$ Module: Mpal Query Library..... *
+ * 4 4k *N #b .> '$N'*$u * *
+ * M $L #$ $ 8 "$c'#$b.. .@ Author: Giovanni Bajo.......... *
+ * M '$u "$u :" *$. "#*#" *
+ * M '$N. " F ^$k Desc: Libreria principale di *
+ * 4> ^R$oue# d MPAL, contenente il *
+ * '$ "" @ codice per le query.... *
+ * #b u# *
+ * $b .@" OS: [ ] DOS [X] WIN95 [ ] OS/2 *
+ * #$u .d" *
+ * '*$e. .zR".@ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ *
+ * "*$$beooee$*" @"M This source code is *
+ * """ '$.? Copyright (C) Spyral Software *
+ * '$d> ALL RIGHTS RESERVED *
+ * '$> ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ *
+ * *
+ **************************************************************************/
+
+#include "common/scummsys.h"
+#include "common/file.h"
+#include "common/savefile.h"
+#include "common/system.h"
+#include "mpal.h"
+#include "mpaldll.h"
+#include "stubs.h"
+#include "tony/tony.h"
+#include "tony/lzo/lzo1x.h"
+
+namespace Tony {
+
+namespace MPAL {
+
+using namespace Tony::LZO;
+
+/****************************************************************************\
+* Copyright
+\****************************************************************************/
+
+const char *mpalCopyright =
+ "\n\nMPAL - MultiPurpose Adventure Language for Windows 95\n"
+ "Copyright 1997-98 Giovanni Bajo and Luca Giusti\n"
+ "ALL RIGHTS RESERVED\n"
+ "\n"
+ "\n";
+
+/****************************************************************************\
+* Structures
+\****************************************************************************/
+
+/****************************************************************************\
+* typedef CFCALL
+* --------------
+* Description: Descrizione di una chiamata a una custom function
+\****************************************************************************/
+
+typedef struct {
+ int nCf;
+
+ int arg1, arg2, arg3, arg4;
+} CFCALL;
+typedef CFCALL* LPCFCALL;
+typedef LPCFCALL* LPLPCFCALL;
+
+
+/****************************************************************************\
+* Global variables
+\****************************************************************************/
+
+uint32 mpalError;
+
+static bool bInit=false;
+static byte * lpMpcImage;
+
+LPITEMIRQFUNCTION lpiifCustom=NULL;
+
+LPLPCUSTOMFUNCTION lplpFunctions=NULL;
+uint16 nObjs;
+
+uint16 nVars;
+HGLOBAL hVars;
+LPMPALVAR lpmvVars;
+
+uint16 nMsgs;
+HGLOBAL hMsgs;
+LPMPALMSG lpmmMsgs;
+
+uint16 nDialogs;
+HGLOBAL hDialogs;
+LPMPALDIALOG lpmdDialogs;
+
+uint16 nItems;
+HGLOBAL hItems;
+LPMPALITEM lpmiItems;
+
+uint16 nLocations;
+HGLOBAL hLocations;
+LPMPALLOCATION lpmlLocations;
+
+uint16 nScripts;
+HGLOBAL hScripts;
+LPMPALSCRIPT lpmsScripts;
+
+Common::File hMpr;
+uint16 nResources;
+uint32 * lpResources;
+
+bool bExecutingAction;
+bool bExecutingDialog;
+
+uint32 nPollingLocations[MAXPOLLINGLOCATIONS];
+HANDLE hEndPollingLocations[MAXPOLLINGLOCATIONS];
+HANDLE PollingThreads[MAXPOLLINGLOCATIONS];
+
+HANDLE hAskChoice;
+HANDLE hDoneChoice;
+
+uint32 nExecutingAction;
+
+uint32 nExecutingDialog;
+uint32 nExecutingChoice;
+uint32 nSelectedChoice;
+
+
+/****************************************************************************\
+* Static functions
+\****************************************************************************/
+
+/****************************************************************************\
+*
+* Function: void LockVar(void);
+*
+* Description: Locka le variabili per accederci
+*
+\****************************************************************************/
+
+void LockVar(void) {
+ lpmvVars=(LPMPALVAR)GlobalLock(hVars);
+}
+
+/****************************************************************************\
+*
+* Function: void UnlockVar(void);
+*
+* Description: Unlocka le variabili dopo l'uso
+*
+\****************************************************************************/
+
+void UnlockVar(void) {
+ GlobalUnlock(hVars);
+}
+
+
+/****************************************************************************\
+*
+* Function: void LockMsg(void);
+*
+* Description: Locka i messaggi per accederci
+*
+\****************************************************************************/
+
+static void LockMsg(void) {
+#ifdef NEED_LOCK_MSGS
+ lpmmMsgs=(LPMPALMSG)GlobalLock(hMsgs);
+#endif
+}
+
+
+/****************************************************************************\
+*
+* Function: void UnlockMsg(void);
+*
+* Description: Unlocka i messaggi dopo l'uso
+*
+\****************************************************************************/
+
+static void UnlockMsg(void) {
+#ifdef NEED_LOCK_MSGS
+ GlobalUnlock(hMsgs);
+#endif
+}
+
+
+/****************************************************************************\
+*
+* Function: void LockDialogs(void);
+*
+* Description: Locka i dialoghi per accederci
+*
+\****************************************************************************/
+
+static void LockDialogs(void) {
+ lpmdDialogs=(LPMPALDIALOG)GlobalLock(hDialogs);
+}
+
+
+/****************************************************************************\
+*
+* Function: void UnlockDialogs(void);
+*
+* Description: Unlocka i dialoghi dopo l'uso
+*
+\****************************************************************************/
+
+static void UnlockDialogs(void) {
+ GlobalUnlock(hDialogs);
+}
+
+
+/****************************************************************************\
+*
+* Function: void LockLocations(void);
+*
+* Description: Locka le strutture di dati sulle locazioni
+*
+\****************************************************************************/
+
+static void LockLocations(void) {
+ lpmlLocations=(LPMPALLOCATION)GlobalLock(hLocations);
+}
+
+
+/****************************************************************************\
+*
+* Function: void UnlockLocations(void);
+*
+* Description: Unlocka le strutture di dati sulle locazioni
+*
+\****************************************************************************/
+
+static void UnlockLocations(void) {
+ GlobalUnlock(hLocations);
+}
+
+
+/****************************************************************************\
+*
+* Function: void LockItems(void);
+*
+* Description: Locka le strutture di dati sugli item
+*
+\****************************************************************************/
+
+static void LockItems(void) {
+ lpmiItems=(LPMPALITEM)GlobalLock(hItems);
+}
+
+
+/****************************************************************************\
+*
+* Function: void UnlockItems(void);
+*
+* Description: Unlocka le strutture di dati sugli item
+*
+\****************************************************************************/
+
+static void UnlockItems(void) {
+ GlobalUnlock(hItems);
+}
+
+/****************************************************************************\
+*
+* Function: void LockScripts(void);
+*
+* Description: Locka le strutture di dati sugli script
+*
+\****************************************************************************/
+
+static void LockScripts(void) {
+ lpmsScripts=(LPMPALSCRIPT)GlobalLock(hScripts);
+}
+
+
+/****************************************************************************\
+*
+* Function: void UnlockScripts(void);
+*
+* Description: Unlocka le strutture di dati sugli script
+*
+\****************************************************************************/
+
+static void UnlockScripts(void) {
+ GlobalUnlock(hScripts);
+}
+
+
+
+
+
+/****************************************************************************\
+*
+* Function: int varGetValue(char * lpszVarName);
+*
+* Description: Restituisce il valore corrente di una variabile globale
+*
+* Input: char * lpszVarName Nome della variabile
+*
+* Return: Valore corrente
+*
+* Note: Prima di questa funzione, bisogna richiamare LockVar() che
+* locka le variabili globali per l'utilizzo. Dopo inoltre bi-
+* sogna ricordarsi di chiamare UnlockVar()
+*
+\****************************************************************************/
+
+int32 varGetValue(const char *lpszVarName) {
+ int i;
+ LPMPALVAR v=lpmvVars;
+
+ for (i=0;i<nVars;v++,i++)
+ if (strcmp(lpszVarName,v->lpszVarName)==0)
+ return v->dwVal;
+
+ mpalError=1;
+ return 0;
+}
+
+
+/****************************************************************************\
+*
+* Function: void varSetValue(char * lpszVarName, int val);
+*
+* Description: Setta un nuovo valore per una variabile globale di MPAL
+*
+* Input: char * lpszVarName Nome della variabile
+* int val Valore da settare
+*
+\****************************************************************************/
+
+void varSetValue(const char *lpszVarName, int32 val) {
+ int i;
+ LPMPALVAR v=lpmvVars;
+
+ for (i=0;i<nVars;v++,i++)
+ if (strcmp(lpszVarName,v->lpszVarName)==0) {
+ v->dwVal=val;
+ if (lpiifCustom!=NULL && strncmp(v->lpszVarName,"Pattern.",8)==0) {
+ i=0;
+ sscanf(v->lpszVarName,"Pattern.%u",&i);
+ lpiifCustom(i,val,-1);
+ } else if (lpiifCustom!=NULL && strncmp(v->lpszVarName,"Status.",7)==0) {
+ i=0;
+ sscanf(v->lpszVarName,"Status.%u",&i);
+ lpiifCustom(i,-1,val);
+ }
+ return;
+ }
+
+ mpalError=1;
+ return;
+}
+
+
+/****************************************************************************\
+*
+* Function: int locGetOrderFromNum(uint32 nLoc);
+*
+* Description: Trova l'indice della locazione #nLoc all'interno dell'array
+* delle strutture delle locazioni
+*
+* Input: uint32 nLoc Numero della locazione da cercare
+*
+* Return: Indice, o -1 se la locazione non e' presente
+*
+* Note: Per funzionare, la funzione necessita che le locazioni siano
+* state lockate con LockLoc()
+*
+\****************************************************************************/
+
+static int locGetOrderFromNum(uint32 nLoc) {
+ int i;
+ LPMPALLOCATION loc=lpmlLocations;
+
+ for (i=0;i<nLocations;i++,loc++)
+ if (loc->nObj==nLoc)
+ return i;
+
+ return -1;
+}
+
+/****************************************************************************\
+*
+* Function: int msgGetOrderFromNum(uint32 nMsg);
+*
+* Description: Trova l'indice del messaggio #nMsg all'interno dell'array
+* delle strutture dei messaggi
+*
+* Input: uint32 nMsg Numero del messaggio da cercare
+*
+* Return: Indice, o -1 se il messaggio non e' presente
+*
+* Note: Per funzionare, la funzione necessita che i messaggi siano
+* stati lockati con LockMsg()
+*
+\****************************************************************************/
+
+static int msgGetOrderFromNum(uint32 nMsg) {
+ int i;
+ LPMPALMSG msg=lpmmMsgs;
+
+ for (i=0;i<nMsgs;i++,msg++)
+ if (msg->wNum==nMsg)
+ return i;
+
+ return -1;
+}
+
+
+/****************************************************************************\
+*
+* Function: int itemGetOrderFromNum(uint32 nItem);
+*
+* Description: Trova l'indice dell'item #nItem all'interno dell'array delle
+* strutture degli item
+*
+* Input: uint32 nItem Numero dell'item da cercare
+*
+* Return: Indice, o -1 se l'item non e' presente
+*
+* Note: Per funzionare, questa funzione necessita che gli item siano
+* stati lockati tramite LockItem()
+*
+\****************************************************************************/
+
+static int itemGetOrderFromNum(uint32 nItem) {
+ int i;
+ LPMPALITEM item=lpmiItems;
+
+ for (i=0;i<nItems;i++,item++)
+ if (item->nObj==nItem)
+ return i;
+
+ return -1;
+}
+
+
+/****************************************************************************\
+*
+* Function: int scriptGetOrderFromNum(uint32 nScript);
+*
+* Description: Trova l'indice dello script #nScript all'interno dell'array
+* delle strutture degli script
+*
+* Input: uint32 nScript Numero dello script da cercare
+*
+* Return: Indice, o -1 se lo script non e' presente
+*
+* Note: Per funzionare, questa funzione necessita che gli script siano
+* stati lockati tramite LockScript()
+*
+\****************************************************************************/
+
+static int scriptGetOrderFromNum(uint32 nScript) {
+ int i;
+ LPMPALSCRIPT script=lpmsScripts;
+
+ for (i=0;i<nScripts;i++,script++)
+ if (script->nObj==nScript)
+ return i;
+
+ return -1;
+}
+
+
+/****************************************************************************\
+*
+* Function: int dialogGetOrderFromNum(uint32 nDialog);
+*
+* Description: Trova l'indice del dialog #nDialog all'interno dell'array
+* delle strutture dei dialog
+*
+* Input: uint32 nDialog Numero del dialog da cercare
+*
+* Return: Indice, o -1 se il dialog non e' presente
+*
+* Note: Per funzionare, questa funzione necessita che i dialog siano
+* stati lockati tramite LockDialogs()
+*
+\****************************************************************************/
+
+static int dialogGetOrderFromNum(uint32 nDialog) {
+ int i;
+ LPMPALDIALOG dialog=lpmdDialogs;
+
+ for (i=0;i<nDialogs;i++,dialog++)
+ if (dialog->nObj==nDialog)
+ return i;
+
+ return -1;
+}
+
+
+
+/****************************************************************************\
+*
+* Function: char * DuplicateMessage(uint32 nMsgOrd);
+*
+* Description: Duplica un messaggio
+*
+* Input: uint32 nMsgOrd Indice del messaggio dentro l'array
+* di strutture dei messaggi
+*
+* Return: Pointer al messaggio duplicato (che puo' essere liberato
+* con GlobalFree()).
+*
+\****************************************************************************/
+
+static char *DuplicateMessage(uint32 nMsgOrd) {
+ const char *origmsg;
+ char *clonemsg;
+ int j;
+
+ if (nMsgOrd == (uint32)-1)
+ return NULL;
+
+ origmsg = (const char *)GlobalLock(lpmmMsgs[nMsgOrd].hText);
+
+ j=0;
+ while (origmsg[j]!='\0' || origmsg[j+1]!='\0')
+ j++;
+ j+=2;
+
+ clonemsg=(char *)GlobalAlloc(GMEM_FIXED|GMEM_ZEROINIT,j);
+ if (clonemsg==NULL)
+ return NULL;
+
+ CopyMemory(clonemsg, origmsg, j);
+ GlobalUnlock(lpmmMsgs[nMsgOrd].hText);
+
+ return clonemsg;
+}
+
+
+/****************************************************************************\
+*
+* Function: char * DuplicateDialogPeriod(uint32 nDlgOrd, uint32 nPeriod);
+*
+* Description: Duplica una frase di un dialog
+*
+* Input: uint32 nDlgOrd Indice del dialogo dentro l'array di
+* strutture dei dialoghi
+*
+* uint32 nPeriod Numero della frase da duplicare
+*
+* Return: Pointer alla frase duplicata (che puo' essere liberata con
+* GlobalFree()).
+*
+\****************************************************************************/
+
+static char *DuplicateDialogPeriod(uint32 nPeriod) {
+ const char *origmsg;
+ char *clonemsg;
+ LPMPALDIALOG dialog=lpmdDialogs+nExecutingDialog;
+ int i,j;
+
+ for (j=0;dialog->Periods[j]!=NULL;j++)
+ if (dialog->PeriodNums[j]==nPeriod) {
+ /* Trovata la frase, va duplicata */
+ origmsg = (const char *)GlobalLock(dialog->Periods[j]);
+
+ /* Calcola la lunghezza e alloca la memoria */
+ i=0;
+ while (origmsg[i]!='\0') i++;
+
+ clonemsg = (char *)GlobalAlloc(GMEM_FIXED|GMEM_ZEROINIT,i+1);
+ if (clonemsg==NULL)
+ return NULL;
+
+ CopyMemory(clonemsg, origmsg, i);
+
+ GlobalUnlock(dialog->Periods[j]);
+
+ return clonemsg;
+ }
+
+ return NULL;
+}
+
+
+
+/****************************************************************************\
+*
+* Function: HGLOBAL resLoad(uint32 dwId);
+*
+* Description: Carica una risorsa dal file MPR
+*
+* Input: uint32 dwId ID della risorsa da caricare
+*
+* Return: Handle alla memoria in cui si trova la risorsa
+*
+\****************************************************************************/
+
+HGLOBAL resLoad(uint32 dwId) {
+ int i;
+ HGLOBAL h;
+ char head[4];
+ uint32 nBytesRead;
+ uint32 nSizeComp, nSizeDecomp;
+ byte *temp, *buf;
+
+ for (i=0;i<nResources;i++)
+ if (lpResources[i*2]==dwId) {
+ hMpr.seek(lpResources[i * 2 + 1]);
+ nBytesRead = hMpr.read(head, 4);
+ if (nBytesRead!=4)
+ return NULL;
+ if (head[0]!='R' || head[1]!='E' || head[2]!='S' || head[3]!='D')
+ return NULL;
+
+ nSizeDecomp = hMpr.readUint32LE();
+ if (hMpr.err())
+ return NULL;
+
+ nSizeComp = hMpr.readUint32LE();
+ if (hMpr.err())
+ return NULL;
+
+ h = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, nSizeDecomp + (nSizeDecomp / 1024) * 16);
+ buf = (byte *)GlobalLock(h);
+ temp = (byte *)GlobalAlloc(GMEM_FIXED|GMEM_ZEROINIT,nSizeComp);
+
+ nBytesRead = hMpr.read(temp, nSizeComp);
+ if (nBytesRead != nSizeComp)
+ return NULL;
+
+ lzo1x_decompress(temp, nSizeComp, buf, (lzo_uint*)&nBytesRead, NULL);
+ if (nBytesRead != nSizeDecomp)
+ return NULL;
+
+ GlobalFree(temp);
+ GlobalUnlock(h);
+ return h;
+ }
+
+ return NULL;
+}
+
+static uint32 *GetSelectList(uint32 i) {
+ uint32 *sl;
+ int j,k,num;
+ LPMPALDIALOG dialog=lpmdDialogs+nExecutingDialog;
+
+ /* Conta quanti select attivi ci sono */
+ num=0;
+ for (j=0;dialog->Choice[i].Select[j].dwData!=0;j++)
+ if (dialog->Choice[i].Select[j].curActive)
+ num++;
+
+ /* Se sono 0, e' un errore */
+ if (num==0)
+ return NULL;
+
+ sl= (uint32 *)GlobalAlloc(GMEM_FIXED|GMEM_ZEROINIT,sizeof(uint32)*(num+1));
+ if (sl==NULL)
+ return NULL;
+
+ /* Copia il dato di ogni select attivo dentro la lista */
+ k=0;
+ for (j=0;dialog->Choice[i].Select[j].dwData!=0;j++)
+ if (dialog->Choice[i].Select[j].curActive)
+ sl[k++]=dialog->Choice[i].Select[j].dwData;
+
+ sl[k] = (uint32)NULL;
+ return sl;
+}
+
+static uint32 *GetItemList(uint32 nLoc) {
+ uint32 *il;
+ uint32 num,i,j;
+ LPMPALVAR v=lpmvVars;
+
+ num=0;
+ for (i=0;i<nVars;i++,v++) {
+ if (strncmp(v->lpszVarName,"Location",8)==0 && v->dwVal==nLoc)
+ num++;
+ }
+
+ il=(uint32 *)GlobalAlloc(GMEM_FIXED|GMEM_ZEROINIT,sizeof(uint32)*(num+1));
+ if (il==NULL)
+ return NULL;
+
+ v=lpmvVars;
+ j=0;
+ for (i=0;i<nVars;i++,v++) {
+ if (strncmp(v->lpszVarName,"Location",8)==0 && v->dwVal==nLoc) {
+ sscanf(v->lpszVarName,"Location.%u",&il[j]);
+ j++;
+ }
+ }
+
+ il[j] = (uint32)NULL;
+ return il;
+}
+
+static LPITEM GetItemData(uint32 nOrdItem) {
+ LPMPALITEM curitem=lpmiItems+nOrdItem;
+ LPITEM ret;
+ HGLOBAL hDat;
+ char *dat;
+ int i,j;
+ char *patlength;
+ uint32 dim;
+
+ // Lo zeroinit e' obbligatorio!!!!
+ ret = (LPITEM)GlobalAlloc(GMEM_FIXED|GMEM_ZEROINIT,sizeof(ITEM));
+ if (ret==NULL)
+ return NULL;
+ ret->speed=150;
+
+ hDat = resLoad(curitem->dwRes);
+ dat = (char *)GlobalLock(hDat);
+
+ if (dat[0]=='D' && dat[1]=='A' && dat[2]=='T') {
+ i=dat[3]; // Versione!! Per ora 1.0
+ dat+=4;
+
+ if (i>=0x10) { // Dalla 1.0 c'e' il punto di destinazione per ogni oggetto
+ ret->destX=*(uint16 *)dat;
+ ret->destY=*(uint16 *)(dat+2);
+ dat+=4;
+ }
+
+ if (i>=0x11) {// Dalla 1.1 c'e' la velocita' di animazione
+ ret->speed=*(uint16 *)dat;
+ dat+=2;
+ } else
+ ret->speed=150;
+ }
+
+ ret->numframe=*dat++;
+ ret->numpattern=*dat++;
+ ret->Zvalue=*dat++;
+
+ // Carica le coordinate left&top di ogni frame
+ for (i=0;i<ret->numframe;i++) {
+ ret->frameslocations[i].left=*(short*)(dat);
+ ret->frameslocations[i].top=*(short*)(dat+2);
+ dat+=4;
+ }
+
+ // Carica le dimensioni di ogni frame e calcola right&bottom
+ for (i=0;i<ret->numframe;i++) {
+ ret->frameslocations[i].right=*(uint16 *)(dat)+ret->frameslocations[i].left;
+ ret->frameslocations[i].bottom=*(uint16 *)(dat+2)+ret->frameslocations[i].top;
+ dat+=4;
+ }
+
+ // Carica i bounding box di ogni frame
+ for (i=0;i<ret->numframe;i++) {
+ ret->bbox[i].left=*(uint16 *)(dat);
+ ret->bbox[i].top=*(uint16 *)(dat+2);
+ ret->bbox[i].right=*(uint16 *)(dat+4);
+ ret->bbox[i].bottom=*(uint16 *)(dat+6);
+ dat+=8;
+ }
+
+ // Carica i pattern di animazione
+ patlength = dat;
+ dat+=ret->numpattern;
+
+ for (i=1;i<ret->numpattern;i++) {
+ for (j=0;j<patlength[i];j++)
+ ret->pattern[i][j]=dat[j];
+ ret->pattern[i][patlength[i]]=255; // Termina i pattern
+ dat+=patlength[i];
+ }
+
+ // Carica i singoli frame di animazione
+ for (i=1;i<ret->numframe;i++) {
+ dim=(uint32)(ret->frameslocations[i].right-ret->frameslocations[i].left)*
+ (uint32)(ret->frameslocations[i].bottom-ret->frameslocations[i].top);
+ ret->frames[i]=(char *)GlobalAlloc(GMEM_FIXED,dim);
+
+ if (ret->frames[i]==NULL)
+ return NULL;
+ CopyMemory(ret->frames[i], dat, dim);
+ dat+=dim;
+ }
+
+ // Controlla se siamo arrivati fino alla fine del file
+ i=*(uint16 *)dat;
+ if (i!=0xABCD)
+ return NULL;
+
+ GlobalUnlock(hDat);
+ GlobalFree(hDat);
+
+ return ret;
+}
+
+
+/****************************************************************************\
+*
+* Function: void PASCAL CustomThread(LPCFCALL p);
+*
+* Description: Thread che richiama una funzione custom. Viene usato negli
+* script, in modo che ciascuna funzione venga eseguita senza
+* ritardare le altre
+*
+* Input: LPCFCALL p Struttura che definisce la chiamata
+*
+* Note: La struttura passata come parametro viene freeata con
+* GlobalFree() alla fine dell'esecuzione.
+*
+\****************************************************************************/
+
+void PASCAL CustomThread(LPCFCALL p) {
+ lplpFunctions[p->nCf](p->arg1,p->arg2,p->arg3,p->arg4);
+ GlobalFree(p);
+ ExitThread(1);
+// _endthread();
+}
+
+
+/****************************************************************************\
+*
+* Function: void PASCAL ScriptThread(LPMPALSCRIPT s);
+*
+* Description: Esegue uno script. Questa funzione e' pensata come starting
+* point per un thread
+*
+* Input: LPMPALSCRIPT s Script da eseguire
+*
+* Note: Lo script passato come parametro viene, alla fine dell'ese-
+* cuzione, freeato con una GlobalFree()
+*
+\****************************************************************************/
+
+void PASCAL ScriptThread(LPMPALSCRIPT s) {
+ uint i,j,k;
+ uint32 dwStartTime = timeGetTime();
+ uint32 dwCurTime;
+ uint32 dwId;
+ static HANDLE cfHandles[MAX_COMMANDS_PER_MOMENT];
+ int numHandles;
+ LPCFCALL p;
+
+// warning("PlayScript(): Moments: %u\n",s->nMoments);
+ for (i=0;i<s->nMoments;i++) {
+ // Dorme il tempo necessario per arrivare al momento successivo
+ if (s->Moment[i].dwTime==-1) {
+ WaitForMultipleObjects(numHandles,cfHandles,true,INFINITE);
+ dwStartTime=timeGetTime();
+ } else {
+ dwCurTime=timeGetTime();
+ if (dwCurTime < dwStartTime+(s->Moment[i].dwTime*100)) {
+ // warning("PlayScript(): Sleeping %lums\n",dwStartTime+(s->Moment[i].dwTime*100)-dwCurTime);
+ Sleep(dwStartTime+(s->Moment[i].dwTime*100)-dwCurTime);
+ }
+ }
+
+ numHandles=0;
+ for (j=0;j<s->Moment[i].nCmds;j++) {
+ k=s->Moment[i].CmdNum[j];
+
+ switch (s->Command[k].type) {
+ case 1:
+ p=(LPCFCALL)GlobalAlloc(GMEM_FIXED,sizeof(CFCALL));
+ if (p==NULL) {
+ mpalError=1;
+ ExitThread(0);
+// _endthread();
+ }
+
+ p->nCf=s->Command[k].nCf;
+ p->arg1=s->Command[k].arg1;
+ p->arg2=s->Command[k].arg2;
+ p->arg3=s->Command[k].arg3;
+ p->arg4=s->Command[k].arg4;
+
+ // !!! Nuova gestione dei thread
+ if ((cfHandles[numHandles++]=CreateThread(NULL,10240,(LPTHREAD_START_ROUTINE)CustomThread,(void *)p,0,&dwId))==NULL) {
+ //if ((cfHandles[numHandles++]=(void*)_beginthread(CustomThread, 10240, (void *)p))==(void*)-1)
+ mpalError=1;
+ ExitThread(0);
+// _endthread();
+ }
+ break;
+
+ case 2:
+ LockVar();
+ varSetValue(
+ s->Command[k].lpszVarName,
+ EvaluateExpression(s->Command[k].expr)
+ );
+ UnlockVar();
+ break;
+
+ default:
+ mpalError=1;
+ GlobalFree(s);
+ ExitThread(0);
+// _endthread();
+ }
+ }
+ }
+
+ GlobalFree(s);
+ ExitThread(1);
+ //_endthread();
+}
+
+
+/****************************************************************************\
+*
+* Function: void PASCAL ActionThread(LPMPALITEM item);
+*
+* Description: Thread che esegue una azione su un item. Il thread
+* esegue sempre l'azione 0, per cui e' necessario creare
+* un item nuovo in cui l'azione 0 sia quella richiesta.
+* Inoltre non viene controllata l'espressione when, ma viene
+* sempre eseguita l'azione.
+*
+* Input: LPMPALITEM item Item che contiene l'azione
+*
+\****************************************************************************/
+
+void PASCAL ActionThread(LPMPALITEM item) {
+ int j,k;
+
+ for (j=0;j<item->Action[item->dwRes].nCmds;j++) {
+ k=item->Action[item->dwRes].CmdNum[j];
+
+ switch (item->Command[k].type) {
+ case 1:
+ // Funzione custom
+ lplpFunctions[item->Command[k].nCf](
+ item->Command[k].arg1,
+ item->Command[k].arg2,
+ item->Command[k].arg3,
+ item->Command[k].arg4
+ );
+ break;
+
+ case 2:
+ // Variable assign
+ LockVar();
+ varSetValue(item->Command[k].lpszVarName,EvaluateExpression(item->Command[k].expr));
+ UnlockVar();
+ break;
+
+ default:
+ mpalError=1;
+ ExitThread(0);
+// _endthread();
+ }
+ }
+
+ GlobalFree(item);
+ //bExecutingAction=false;
+
+ ExitThread(1);
+// _endthread();
+}
+
+void PASCAL ShutUpActionThread(HANDLE hThread) {
+ WaitForSingleObject(hThread,INFINITE);
+ bExecutingAction=false;
+
+ ExitThread(1);
+// _endthread();
+}
+
+/****************************************************************************\
+*
+* Function: void PASCAL LocationPollThread(uint32 id);
+*
+* Description: Esegue il polling di una locazione (starting point di un
+* thread).
+*
+* Input: uint32 id Indice per gli array relativi ai
+* polling degli item delle locazioni
+*
+\****************************************************************************/
+
+void PASCAL LocationPollThread(uint32 id) {
+ uint32 *il;
+ int i,j,k;
+ int numitems;
+ int nRealItems;
+ LPMPALITEM curItem,newItem;
+ int nIdleActions;
+ uint32 curTime;
+ uint32 dwSleepTime;
+ uint32 dwId;
+
+ typedef struct {
+ uint32 nItem, nAction;
+
+ uint16 wTime;
+ byte perc;
+ HGLOBAL when;
+ byte nCmds;
+ uint16 CmdNum[MAX_COMMANDS_PER_ACTION];
+
+ uint32 dwLastTime;
+ } MYACTION;
+
+ typedef struct {
+ uint32 nItem;
+ HANDLE hThread;
+ } MYTHREAD;
+
+ MYACTION *MyActions;
+ MYTHREAD *MyThreads;
+
+ /* Tanto per cominciare, e' necessario richiedere la lista degli item
+ presenti nella locazione. */
+ il = mpalQueryItemList(nPollingLocations[id]);
+
+ /* Contiamo gli items */
+ for (numitems=0;il[numitems]!=0;numitems++)
+ ;
+
+ /* Cerchiamo gli items della locazione senza idle actions e li eliminiamo
+ dalla lista */
+ LockItems();
+ nIdleActions=0;
+ nRealItems=0;
+ for (i=0;i<numitems;i++) {
+ int ord=itemGetOrderFromNum(il[i]);
+
+ if (ord==-1) continue;
+
+ curItem=lpmiItems+ord;
+
+ k=0;
+ for (j=0;j<curItem->nActions;j++)
+ if (curItem->Action[j].num==0xFF)
+ k++;
+
+ nIdleActions+=k;
+
+ if (k==0)
+ /* Possiamo eliminare questo item dalla lista */
+ il[i] = (uint32)NULL;
+ else
+ nRealItems++;
+ }
+ UnlockItems();
+
+ /* Se non e' rimasto nessuno possiamo uscire */
+ if (nRealItems==0) {
+ GlobalFree(il);
+ ExitThread(0);
+// _endthread();
+ }
+
+ MyThreads=(MYTHREAD*)GlobalAlloc(GMEM_FIXED|GMEM_ZEROINIT,nRealItems*sizeof(MYTHREAD));
+ if (MyThreads==NULL) {
+ GlobalFree(il);
+ ExitThread(0);
+// _endthread();
+ }
+
+ /* Inizializziamo le routine random */
+ //curTime=timeGetTime();
+ //srand(curTime);
+
+
+ /* Abbiamo appurato che esiste almeno un item che contiene idle actions.
+ Ora creaiamo le copie speculari delle idle actions */
+ MyActions=(MYACTION*)GlobalAlloc(GMEM_FIXED|GMEM_ZEROINIT,nIdleActions*sizeof(MYACTION));
+ if (MyActions==NULL) {
+ GlobalFree(MyThreads);
+ GlobalFree(il);
+ ExitThread(0);
+// _endthread();
+ }
+
+ LockItems();
+ k=0;
+
+ for (i=0;i<numitems;i++) {
+ if (il[i]==0)
+ continue;
+
+ curItem=lpmiItems+itemGetOrderFromNum(il[i]);
+
+ for (j=0;j<curItem->nActions;j++)
+ if (curItem->Action[j].num==0xFF) {
+ MyActions[k].nItem=il[i];
+ MyActions[k].nAction=j;
+
+ MyActions[k].wTime=curItem->Action[j].wTime;
+ MyActions[k].perc=curItem->Action[j].perc;
+ MyActions[k].when=curItem->Action[j].when;
+ MyActions[k].nCmds=curItem->Action[j].nCmds;
+ CopyMemory(MyActions[k].CmdNum, curItem->Action[j].CmdNum,
+ MAX_COMMANDS_PER_ACTION*sizeof(uint16));
+
+ MyActions[k].dwLastTime=timeGetTime();
+ k++;
+ }
+ }
+
+ UnlockItems();
+
+ /* La item list non ci serve piu' */
+ GlobalFree(il);
+
+
+ /* Eccoci al ciclo principale. */
+ while (1) {
+ /* Cerchiamo tra tutte le idle actions quella a cui manca meno tempo per
+ l'esecuzione */
+ curTime=timeGetTime();
+ dwSleepTime=(uint32)-1L;
+
+ for (k=0;k<nIdleActions;k++)
+ if (curTime>=MyActions[k].dwLastTime+MyActions[k].wTime) {
+ dwSleepTime=0;
+ break;
+ } else
+ dwSleepTime=MIN(dwSleepTime,MyActions[k].dwLastTime+MyActions[k].wTime-curTime);
+
+ /* Ci addormentiamo, ma controllando sempre l'evento che viene settato
+ quando viene richiesta la nostra chiusura */
+ k=WaitForSingleObject(hEndPollingLocations[id],dwSleepTime);
+ if (k==WAIT_OBJECT_0)
+ break;
+
+ for (i=0;i<nRealItems;i++)
+ if (MyThreads[i].nItem!=0) {
+ if (WaitForSingleObject(MyThreads[i].hThread,0)==WAIT_OBJECT_0)
+ MyThreads[i].nItem=0;
+ }
+
+ curTime=timeGetTime();
+
+ /* Cerchiamo all'interno delle idle actions quale e' necessario eseguire */
+ for (k=0;k<nIdleActions;k++)
+ if (curTime>=MyActions[k].dwLastTime+MyActions[k].wTime) {
+ MyActions[k].dwLastTime+=MyActions[k].wTime;
+
+ /* E' il momento di tirare il nostro dado virtuale, e controllare
+ se la sorte e' dalla parte della idle action */
+ byte randomVal = (byte)_vm->_randomSource.getRandomNumber(99);
+ if (randomVal < MyActions[k].perc) {
+ /* Controlliamo se c'e' una action in esecuzione sull'item */
+ if ((bExecutingAction) && (nExecutingAction==MyActions[k].nItem))
+ continue;
+
+ /* Controlliamo se c'e' gia' un'altra idle function in esecuzione
+ sullo stesso item */
+ for (i=0;i<nRealItems;i++)
+ if (MyThreads[i].nItem==MyActions[k].nItem)
+ break;
+
+ if (i<nRealItems)
+ continue;
+
+ /* Ok, siamo gli unici :) */
+ LockItems();
+ curItem=lpmiItems+itemGetOrderFromNum(MyActions[k].nItem);
+
+ /* Controlliamo se c'e' un esperessione WhenExecute */
+ j=MyActions[k].nAction;
+ if (curItem->Action[j].when!=NULL)
+ if (!EvaluateExpression(curItem->Action[j].when)) {
+ UnlockItems();
+ continue;
+ }
+
+ /* Ok, possiamo eseguire la azione. Per comodita' lo facciamo in
+ un nuovo thread */
+ newItem=(LPMPALITEM)GlobalAlloc(GMEM_FIXED|GMEM_ZEROINIT,sizeof(MPALITEM));
+ if (newItem==false) {
+ GlobalFree(MyThreads);
+ GlobalFree(MyActions);
+ ExitThread(0);
+// _endthread();
+ }
+
+ CopyMemory(newItem,curItem,sizeof(MPALITEM));
+ UnlockItems();
+
+ /* Copiamo l'azione nella #0 */
+// newItem->Action[0].nCmds=curItem->Action[j].nCmds;
+// CopyMemory(newItem->Action[0].CmdNum,curItem->Action[j].CmdNum,newItem->Action[0].nCmds*sizeof(newItem->Action[0].CmdNum[0]));
+ newItem->dwRes=j;
+
+ /* Creaiamo l'action thread. Provvedera' lui a liberare la memoria
+ allocata per il nuovo item */
+ for (i=0;i<nRealItems;i++)
+ if (MyThreads[i].nItem==0)
+ break;
+
+ MyThreads[i].nItem=MyActions[k].nItem;
+
+ // !!! Nuova gestione dei thread
+ if ((MyThreads[i].hThread=CreateThread(NULL,10240,(LPTHREAD_START_ROUTINE)ActionThread,(void *)newItem,0,&dwId))==NULL) {
+ //if ((MyThreads[i].hThread=(void*)_beginthread(ActionThread,10240,(void *)newItem))==(void*)-1)
+ GlobalFree(newItem);
+ GlobalFree(MyThreads);
+ GlobalFree(MyActions);
+ ExitThread(0);
+// _endthread();
+ }
+
+ /* Skippa tutte le idle action dello stesso item */
+ }
+ }
+ }
+
+ /* Chiude tutti i thread interni */
+
+ /*
+
+ CODICE OBSOLETO: ANDIAMO DI SKIP CHE RULLA
+
+ for (i=0;i<nRealItems;i++)
+ if (MyThreads[i].nItem!=0) {
+ TerminateThread(MyThreads[i].hThread,0);
+ CloseHandle(MyThreads[i].hThread);
+ }
+*/
+
+ // Set idle skip on
+ lplpFunctions[200](0,0,0,0);
+
+ for (i=0;i<nRealItems;i++)
+ if (MyThreads[i].nItem!=0) {
+ if (WaitForSingleObject(MyThreads[i].hThread,5000)!=WAIT_OBJECT_0)
+ TerminateThread(MyThreads[i].hThread,0);
+
+ CloseHandle(MyThreads[i].hThread);
+ }
+
+ // Set idle skip off
+ lplpFunctions[201](0,0,0,0);
+
+ /* Abbiamo finito */
+ GlobalFree(MyThreads);
+ GlobalFree(MyActions);
+ ExitThread(1);
+//endthread();
+}
+
+
+
+/****************************************************************************\
+*
+* Function: void ShutUpDialogThread(HANDLE hThread);
+*
+* Description: Aspetta la fine dell'esecuzione del dialog thread e ripri-
+* stina le variabili globali indicando che il dialogo e' finito.
+*
+* Input: HANDLE hThread Handle del dialog thread
+*
+* Note: Si ricorre a questo thread aggiuntivo, al posto di azzerare
+* le variabili all'interno del dialog thread stesso, poiche',
+* a causa della natura ricorsiva di un dialogo, non e' sempre
+* possibile sapere quando esattamente finisce un dialogo.
+*
+\****************************************************************************/
+
+void PASCAL ShutUpDialogThread(HANDLE hThread) {
+ WaitForSingleObject(hThread,INFINITE);
+
+ bExecutingDialog=false;
+ nExecutingDialog=0;
+ nExecutingChoice=0;
+
+ SetEvent(hAskChoice);
+ ExitThread(1);
+// _endthread();
+}
+
+
+/****************************************************************************\
+*
+* Function: void GroupThread(uint32 nGroup);
+*
+* Description: Esegue un gruppo del dialogo corrente. Puo' essere lo
+* starting point di un thread.
+*
+* Input: uint32 nGroup Numero del gruppo da eseguire
+*
+\****************************************************************************/
+void DoChoice(uint32 nChoice);
+
+void PASCAL GroupThread(uint32 nGroup) {
+ LPMPALDIALOG dialog;
+ int i,j,k;
+
+ /* Locka i dialoghi */
+ LockDialogs();
+
+ /* Trova il puntatore al dialogo corrente */
+ dialog=lpmdDialogs+nExecutingDialog;
+
+ /* Cerca il gruppo richiesto all'interno del dialogo */
+ for (i=0;dialog->Group[i].num!=0;i++)
+ if (dialog->Group[i].num==nGroup) {
+ /* Cicla eseguendo i comandi del gruppo */
+ for (j=0;j<dialog->Group[i].nCmds;j++) {
+ k=dialog->Group[i].CmdNum[j];
+
+ switch (dialog->Command[k].type) {
+ /* Funzione custom: la richiama */
+ case 1:
+ lplpFunctions[dialog->Command[k].nCf](
+ dialog->Command[k].arg1,
+ dialog->Command[k].arg2,
+ dialog->Command[k].arg3,
+ dialog->Command[k].arg4
+ );
+ break;
+
+ /* Variabile: la setta */
+ case 2:
+ LockVar();
+ varSetValue(dialog->Command[k].lpszVarName,EvaluateExpression(dialog->Command[k].expr));
+ UnlockVar();
+ break;
+
+ /* DoChoice: richiama la funzione di scelta */
+ case 3:
+ DoChoice((uint32)dialog->Command[k].nChoice);
+ break;
+
+ default:
+ mpalError=1;
+ UnlockDialogs();
+ ExitThread(0);
+// _endthread();
+ }
+ }
+
+ /* Abbiamo eseguito il gruppo. Possiamo uscire alla funzione chiamante.
+ Se il gruppo era il primo chiamato, allora automaticamente il
+ thread viene chiuso, altrimenti si ritorno al gruppo chiamante. */
+ UnlockDialogs();
+ return;
+ }
+
+ /* Se siamo qui, vuol dire che non abbiamo trovato il gruppo richiesto */
+ mpalError=1;
+ UnlockDialogs();
+ ExitThread(0);
+// _endthread();
+}
+
+
+/****************************************************************************\
+*
+* Function: void DoChoice(uint32 nChoice);
+*
+* Description: Esegue una scelta nel dialogo corrente
+*
+* Input: uint32 nChoice Numero della scelta da eseguire
+*
+\****************************************************************************/
+
+void DoChoice(uint32 nChoice) {
+ LPMPALDIALOG dialog;
+ int i,j,k;
+
+ /* Locka i dialoghi */
+ LockDialogs();
+
+ /* Trova il puntatore al dialogo corrente */
+ dialog=lpmdDialogs+nExecutingDialog;
+
+ /* Cerca la scelta richiesta tra quelle nel dialogo */
+ for (i=0;dialog->Choice[i].nChoice!=0;i++)
+ if (dialog->Choice[i].nChoice==nChoice)
+ break;
+
+ /* Se non l'ha trovata, esce con errore */
+ if (dialog->Choice[i].nChoice==0) {
+ /* Se siamo qui, non abbiamo trovato la choice richiesta */
+ mpalError=1;
+ UnlockDialogs();
+ ExitThread(0);
+// _endthread();
+ }
+
+ /* Abbiamo trova la choice richiesta. Ricordiamoci qual e' nella
+ variabile globale */
+ nExecutingChoice=i;
+
+ while (1) {
+ nExecutingChoice=i;
+
+ k=0;
+ /* Calcoliamo le when expression di ciascun select, per vedere se sono
+ attivi o disattivi */
+ for (j=0;dialog->Choice[i].Select[j].dwData!=0;j++)
+ if (dialog->Choice[i].Select[j].when==NULL) {
+ dialog->Choice[i].Select[j].curActive=1;
+ k++;
+ } else if (EvaluateExpression(dialog->Choice[i].Select[j].when)) {
+ dialog->Choice[i].Select[j].curActive=1;
+ k++;
+ } else
+ dialog->Choice[i].Select[j].curActive=0;
+
+ /* Se non ci sono scelte attivate, la scelta e' finita */
+ if (k==0) {
+ UnlockDialogs();
+ break;
+ }
+
+ /* Avvertiamo il gioco che c'e' una scelta da far fare all'utente,
+ e restiamo in attesa della risposta */
+ ResetEvent(hDoneChoice);
+ SetEvent(hAskChoice);
+ WaitForSingleObject(hDoneChoice,INFINITE);
+
+ /* Ora che la scelta e' stata effettuata, possiamo eseguire i gruppi
+ associati con la scelta */
+ j=nSelectedChoice;
+ for (k=0;dialog->Choice[i].Select[j].wPlayGroup[k]!=0;k++)
+ GroupThread(dialog->Choice[i].Select[j].wPlayGroup[k]);
+
+ /* Controllo sugli attributi */
+ if (dialog->Choice[i].Select[j].attr&(1<<0)) {
+ /* Bit 0 settato: fine della scelta */
+ UnlockDialogs();
+ break;
+ }
+
+ if (dialog->Choice[i].Select[j].attr&(1<<1)) {
+ /* Bit 1 settato: fine del dialogo */
+ UnlockDialogs();
+ ExitThread(1);
+// _endthread();
+ }
+
+ /* Fine della scelta senza attributi: bisogna rifarla */
+ }
+
+ /* Se siamo qui, abbiamo trovato un end choice. Ritorna al gruppo chiamante */
+ return;
+}
+
+
+
+/****************************************************************************\
+*
+* Function: HANDLE DoAction(uint32 nAction, uint32 ordItem, uint32 dwParam);
+*
+* Description: Esegue una azione su un certo item
+*
+* Input: uint32 nAction Numero dell'azione
+* uint32 ordItem Indice dell'item nelle strutture
+* degli item
+* uint32 dwParam Eventuale parametro per l'azione
+*
+* Return: Handle del thread che sta eseguendo l'azione, oppure
+* INVALID_HANDLE_VALUE se l'azione non e' definita, o l'item
+* e' disattivato.
+*
+* Note: Si puo' ottenere l'indice dell'item a partire dal suo numero
+* tramite la funzione itemGetOrderFromNum().
+* Gli item devono essere lockati, perche' questa funzione
+* funzioni, tramite LockItem();
+*
+\****************************************************************************/
+
+static HANDLE DoAction(uint32 nAction, uint32 ordItem, uint32 dwParam) {
+ LPMPALITEM item=lpmiItems;
+ int i;
+ LPMPALITEM newitem;
+ uint32 dwId;
+ HANDLE h;
+
+ item+=ordItem;
+ Common::String buf = Common::String::format("Status.%u", item->nObj);
+ if (varGetValue(buf.c_str())<=0)
+ return INVALID_HANDLE_VALUE;
+
+ for (i=0;i<item->nActions;i++) {
+ if (item->Action[i].num!=nAction)
+ continue;
+
+ if (item->Action[i].wParm!=dwParam)
+ continue;
+
+ if (item->Action[i].when!=NULL) {
+ if (!EvaluateExpression(item->Action[i].when))
+ continue;
+ }
+
+ // Ora abbiamo trova l'azione giusta che deve essere eseguita.
+ // Duplichiamo l'item corrente e copiamo la azione #i nella #0
+ newitem=(LPMPALITEM)GlobalAlloc(GMEM_FIXED|GMEM_ZEROINIT,sizeof(MPALITEM));
+ if (newitem==NULL)
+ return INVALID_HANDLE_VALUE;
+
+ // Nella nuova versione scriviamo il numero dell'azione in dwRes
+ CopyMemory(newitem,item,sizeof(MPALITEM));
+/* newitem->Action[0].nCmds=item->Action[i].nCmds;
+ CopyMemory(newitem->Action[0].CmdNum,item->Action[i].CmdNum,newitem->Action[0].nCmds*sizeof(newitem->Action[0].CmdNum[0]));
+*/
+ newitem->dwRes=i;
+
+ // E finalmente possiamo richiamare il thread, che eseguira' l'azione
+ // 0 dell'item, e poi liberera' la memoria con la GlobalFree()
+
+/* !!! Nuova gestione dei thread
+*/
+ if ((h=CreateThread(NULL,10240,(LPTHREAD_START_ROUTINE)ActionThread,(void *)newitem,0,&dwId))==NULL)
+ return INVALID_HANDLE_VALUE;
+
+ if ((h=CreateThread(NULL,10240,(LPTHREAD_START_ROUTINE)ShutUpActionThread,(void *)h,0,&dwId))==NULL)
+ return INVALID_HANDLE_VALUE;
+
+/*
+ if ((h=(void*)_beginthread(ActionThread,10240,(void *)newitem))==(void*)-1)
+ return INVALID_HANDLE_VALUE;
+
+ if ((h=(void*)_beginthread(ShutUpActionThread,10240,(void *)h))==(void*)-1)
+ return INVALID_HANDLE_VALUE;
+
+*/
+ nExecutingAction=item->nObj;
+ bExecutingAction=true;
+
+ return h;
+ }
+
+ return INVALID_HANDLE_VALUE;
+}
+
+
+/****************************************************************************\
+*
+* Function: HANDLE DoDialog(uint32 nDlgOrd, uint32 nGroup);
+*
+* Description: Esegue un dialogo in un thread
+*
+* Input: uint32 nDlgOrd Indice del dialogo da eseguire
+* all'interno dell'array di strutture
+* dei dialoghi
+* uint32 nGroup Numero del gruppo da eseguire
+*
+* Return: Handle del thread che sta eseguendo il dialogo, o
+* INVALID_HANDLE_VALUE in caso di errore
+*
+* Note: Il dialogo viene eseguito in un thread creato apposta, che
+* deve informa tramite un evento quando e' necessario far
+* fare una scelta all'utente. I dati sulle scelte possono
+* essere richiesti tramite le varie query.
+*
+\****************************************************************************/
+
+static HANDLE DoDialog(uint32 nDlgOrd, uint32 nGroup) {
+// LPMPALDIALOG dialog=lpmdDialogs+nDlgOrd;
+ uint32 dwId;
+ HANDLE h;
+
+ /* Si ricorda nella variabile globale qual e' il dialogo in esecuzione */
+ nExecutingDialog=nDlgOrd;
+
+ /* Attiva la flag per indicare che c'e' un dialogo in esecuzione */
+ bExecutingDialog=true;
+
+ ResetEvent(hAskChoice);
+ ResetEvent(hDoneChoice);
+
+ /* Crea un thread in cui esegue un gruppo del dialogo */
+
+ // !!! Nuova gestione dei thread
+ if ((h=CreateThread(NULL,10240,(LPTHREAD_START_ROUTINE)GroupThread,(void *)nGroup,0,&dwId))==NULL)
+ // if ((h=(void*)_beginthread(GroupThread,10240,(void *)nGroup))==(void*)-1)
+ return INVALID_HANDLE_VALUE;
+
+ /* Crea un thread che attende la fine del dialogo e rimette a posto le
+ variabili globali */
+ // !!! Nuova gestione dei thread
+ if (CreateThread(NULL,10240,(LPTHREAD_START_ROUTINE)ShutUpDialogThread,(void *)h,0,&dwId)==NULL) {
+ //if ((h=(void*)_beginthread(ShutUpDialogThread,10240,(void *)h))==(void*)-1)
+ TerminateThread(h,0);
+ CloseHandle(h);
+ return INVALID_HANDLE_VALUE;
+ }
+
+ return h;
+}
+
+
+/****************************************************************************\
+*
+* Function: bool DoSelection(uint32 nChoice, uint32 dwData);
+*
+* Description: Prende nota del select scelto dall'utente, e avverte il
+* thread che stava eseguendo il dialogo che puo' continuare.
+*
+* Input: uint32 nChoice Numero della scelta che era in corso
+* uint32 dwData Dato abbinato al select selezionato
+*
+* Return: true se tutto OK, false in caso di errore
+*
+\****************************************************************************/
+
+bool DoSelection(uint32 i, uint32 dwData) {
+ LPMPALDIALOG dialog=lpmdDialogs+nExecutingDialog;
+ int j;
+
+ for (j=0;dialog->Choice[i].Select[j].dwData!=0;j++)
+ if (dialog->Choice[i].Select[j].dwData==dwData && dialog->Choice[i].Select[j].curActive!=0)
+ break;
+
+ if (dialog->Choice[i].Select[j].dwData==0)
+ return false;
+
+ nSelectedChoice=j;
+ SetEvent(hDoneChoice);
+ return true;
+}
+
+
+
+/****************************************************************************\
+* Exported functions
+\****************************************************************************/
+
+/****************************************************************************\
+*
+* Function: bool mpalInit(char * lpszMpcFileName, char * lpszMprFileName,
+* LPLPCUSTOMFUNCTION lplpcfArray);
+*
+* Description: Inizializza la libreria MPAL, e apre un file .MPC, che
+* verra' utilizzato per tutte le query
+*
+* Input: char * lpszMpcFileName Nome del file .MPC, comprensivo di
+* estensione
+* char * lpszMprFileName Nome del file .MPR, comprensivo di
+* estensione
+* LPLPCUSTOMFUNCTION
+* lplpcfArray Array di pointer a funzioni custom
+*
+* Return: true se tutto OK, false in caso di errore
+*
+\****************************************************************************/
+
+bool mpalInit(char * lpszMpcFileName, char * lpszMprFileName, LPLPCUSTOMFUNCTION lplpcfArray) {
+ Common::File hMpc;
+ byte buf[5];
+ uint32 nBytesRead;
+ bool bCompress;
+ uint32 dwSizeDecomp, dwSizeComp;
+ byte *cmpbuf;
+
+ //printf("Item: %lu\n",sizeof(MPALITEM));
+ //printf("Script: %lu\n",sizeof(MPALSCRIPT));
+ //printf("Dialog: %lu\n",sizeof(MPALDIALOG));
+
+ /* Si salva l'array delle funzioni custom */
+ lplpFunctions=lplpcfArray;
+
+ /* Apre il file MPC in lettura */
+ if (!hMpc.open(lpszMpcFileName))
+ return false;
+
+ /* Legge e controlla l'header */
+ nBytesRead = hMpc.read(buf, 5);
+ if (nBytesRead !=5)
+ return false;
+
+ if (buf[0]!='M' || buf[1]!='P' || buf[2]!='C' || buf[3]!=0x20)
+ return false;
+
+ bCompress=buf[4];
+
+ /* Legge la dimensione del file decompresso, e alloca la memoria */
+ dwSizeDecomp = hMpc.readUint32LE();
+ if (hMpc.err())
+ return false;
+
+ lpMpcImage = (byte *)GlobalAlloc(GMEM_FIXED,dwSizeDecomp+16);
+ if (lpMpcImage==NULL)
+ return false;
+
+ if (bCompress) {
+ /* Se il file e' compresso, guarda quanto e' grande e alloca la
+ memoria temporanea per la decompressione */
+ dwSizeComp = hMpc.readUint32LE();
+ if (nBytesRead != 4)
+ return false;
+
+ cmpbuf = (byte *)GlobalAlloc(GMEM_FIXED,dwSizeComp);
+ if (cmpbuf==NULL)
+ return false;
+
+ nBytesRead = hMpc.read(cmpbuf, dwSizeComp);
+ if (nBytesRead != dwSizeComp)
+ return false;
+
+ /* Decomprime l'immagine */
+ lzo1x_decompress(cmpbuf,dwSizeComp,lpMpcImage,(lzo_uint*)&nBytesRead,NULL);
+ if (nBytesRead != dwSizeDecomp)
+ return false;
+
+ GlobalFree(cmpbuf);
+ } else {
+ /* Se il file non e' compresso, lo legge all'interno della memoria gia'
+ allocata */
+ nBytesRead = hMpc.read(lpMpcImage, dwSizeDecomp);
+ if (nBytesRead != dwSizeDecomp)
+ return false;
+ }
+
+ /* Chiude il file */
+ hMpc.close();
+
+ /* Parsa l'immagine */
+ if (ParseMpc(lpMpcImage)==false)
+ return false;
+
+ GlobalFree(lpMpcImage);
+
+ /* Calcola utilizzo di memoria */
+ /*
+ {
+ char errbuf[256];
+ wsprintf(errbuf,"Utilizzo in RAM: VAR %lu, MSG %lu, DLG %lu, ITM %lu, LOC %lu, SCR %lu",
+ nVars*sizeof(MPALVAR),
+ nMsgs*sizeof(MPALMSG),
+ nDialogs*sizeof(MPALDIALOG),
+ nItems*sizeof(MPALITEM),
+ nLocations*sizeof(MPALLOCATION),
+ nScripts*sizeof(MPALSCRIPT));
+ MessageBox(NULL,errbuf,"Dump",MB_OK);
+ }
+*/
+
+ /* Apre il file MPR in lettura */
+ if (!hMpr.open(lpszMprFileName))
+ return false;
+
+ /* Si posiziona a 8 byte dalla fine del file */
+ hMpr.seek(-12, SEEK_END);
+
+ dwSizeComp = hMpr.readUint32LE();
+ if (hMpr.err())
+ return false;
+
+ nResources = hMpr.readUint32LE();
+ if (hMpr.err())
+ return false;
+
+ nBytesRead = hMpr.read(buf, 4);
+ if (hMpr.err())
+ return false;
+
+ if (buf[0] !='E' || buf[1] != 'N' || buf[2] != 'D' || buf[3] != '0')
+ return false;
+
+ /* Si posiziona all'inizio dell'header delle risorse */
+ hMpr.seek(-(12 + (int)dwSizeComp), SEEK_END);
+
+ lpResources = (uint32 *)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, nResources * 8);
+ if (lpResources==NULL)
+ return false;
+
+ cmpbuf = GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, dwSizeComp);
+ if (cmpbuf==NULL)
+ return false;
+
+ nBytesRead = hMpr.read(cmpbuf, dwSizeComp);
+ if (nBytesRead != dwSizeComp)
+ return false;
+
+ lzo1x_decompress((byte *)cmpbuf,dwSizeComp,(byte *)lpResources, (uint32 *)&nBytesRead, NULL);
+ if (nBytesRead != (uint32)nResources*8)
+ return false;
+
+ GlobalFree(cmpbuf);
+
+ /* Si riposiziona all'inizio lasciando il file di risorse aperto */
+ hMpr.seek(0, SEEK_SET);
+
+ /* Non c'e' nessuna azione ne' dialogo in esecuzione */
+ bExecutingAction = false;
+ bExecutingDialog = false;
+
+ /* Non c'e' nessuna locazione in polling */
+ Common::fill(nPollingLocations, nPollingLocations + MAXPOLLINGLOCATIONS, 0);
+
+ /* Crea l'evento che verra' utilizzato per avvertire il gioco che c'e'
+ da effettuare una scelta */
+ hAskChoice=CreateEvent(NULL, true, false, NULL);
+ hDoneChoice=CreateEvent(NULL, true, false, NULL);
+
+ return true;
+}
+
+/****************************************************************************\
+*
+* Function: uint32 mpalQuery(uint16 wQueryType, ...);
+*
+* Description: Questa e' la funzione generale per comunicare con la libreria,
+* per richiedere informazioni riguardo a quanto si trova nel
+* file .MPC
+*
+* Input: uint16 wQueryType Tipo di query. La lista e' in
+* enum QueryTypes
+*
+* Return: 4 bytes che dipendono dal tipo di query
+*
+* Note: E' _FORTEMENTE_ consigliato utilizzare le macro
+* definite sopra per utilizzare le query, dato che
+* permettono di evitare spiacevoli bug dovuti a dimenticanze
+* di parametri.
+*
+\****************************************************************************/
+
+#define GETARG(type) va_arg(v,type)
+
+uint32 mpalQuery(uint16 wQueryType, ...) {
+ uint32 dwRet; int x,y,z; char * n;
+ va_list v;
+ Common::String buf;
+
+ mpalError=OK;
+ va_start(v,wQueryType);
+
+ switch (wQueryType) {
+ /*
+ * uint32 mpalQuery(MPQ_VERSION);
+ */
+ case MPQ_VERSION:
+ dwRet = HEX_VERSION;
+ break;
+
+ /*
+ * uint32 mpalQuery(MPQ_GLOBAL_VAR, char * lpszVarName);
+ */
+ case MPQ_GLOBAL_VAR:
+ LockVar();
+ dwRet=(uint32)varGetValue(GETARG(char *));
+ UnlockVar();
+ break;
+
+ /*
+ * char * mpalQuery(MPQ_MESSAGE, uint32 nMsg);
+ */
+ case MPQ_MESSAGE:
+ LockMsg();
+ dwRet=(uint32)DuplicateMessage(msgGetOrderFromNum(GETARG(uint32)));
+ UnlockMsg();
+ break;
+
+ /*
+ * uint32 mpalQuery(MPQ_ITEM_PATTERN, uint32 nItem);
+ */
+ case MPQ_ITEM_PATTERN:
+ LockVar();
+ buf = Common::String::format("Pattern.%u", GETARG(uint32));
+ dwRet = (uint32)varGetValue(buf.c_str());
+ UnlockVar();
+ break;
+
+ /*
+ * uint32 mpalQuery(MPQ_LOCATION_SIZE, uint32 nLoc, uint32 dwCoord);
+ */
+ case MPQ_LOCATION_SIZE:
+ LockLocations();
+ x=locGetOrderFromNum(GETARG(uint32));
+ y=GETARG(uint32);
+ if (x!=-1) {
+ if (y==MPQ_X)
+ dwRet=lpmlLocations[x].dwXlen;
+ else if (y==MPQ_Y)
+ dwRet=lpmlLocations[x].dwYlen;
+ else
+ mpalError=1;
+ } else
+ mpalError=1;
+ UnlockLocations();
+ break;
+
+ /*
+ * HGLOBAL mpalQuery(MPQ_LOCATION_IMAGE, uint32 nLoc);
+ */
+ case MPQ_LOCATION_IMAGE:
+ LockLocations();
+ x=locGetOrderFromNum(GETARG(uint32));
+ dwRet=(uint32)resLoad(lpmlLocations[x].dwPicRes);
+ UnlockLocations();
+ break;
+
+ /*
+ * HGLOBAL mpalQuery(MPQ_RESOURCE, uint32 dwRes);
+ */
+ case MPQ_RESOURCE:
+ dwRet=(uint32)resLoad(GETARG(uint32));
+ break;
+
+ /*
+ * uint32 mpalQuery(MPQ_ITEM_LIST, uint32 nLoc);
+ */
+ case MPQ_ITEM_LIST:
+ LockVar();
+ dwRet=(uint32)GetItemList(GETARG(uint32));
+ LockVar();
+ break;
+
+ /*
+ * LPITEM mpalQuery(MPQ_ITEM_DATA, uint32 nItem);
+ */
+ case MPQ_ITEM_DATA:
+ LockItems();
+ dwRet=(uint32)GetItemData(itemGetOrderFromNum(GETARG(uint32)));
+ UnlockItems();
+ break;
+
+ /*
+ * bool mpalQuery(MPQ_ITEM_IS_ACTIVE, uint32 nItem);
+ */
+ case MPQ_ITEM_IS_ACTIVE:
+ LockVar();
+ x=GETARG(uint32);
+ buf = Common::String::format("Status.%u", x);
+ if (varGetValue(buf.c_str()) <= 0)
+ dwRet = (uint32)false;
+ else
+ dwRet = (uint32)true;
+ UnlockVar();
+ break;
+
+
+ /*
+ * uint32 mpalQuery(MPQ_ITEM_NAME, uint32 nItem, char * lpszName);
+ */
+ case MPQ_ITEM_NAME:
+ LockVar();
+ x=GETARG(uint32);
+ n=GETARG(char *);
+ buf = Common::String::format("Status.%u", x);
+ if (varGetValue(buf.c_str()) <= 0)
+ n[0]='\0';
+ else {
+ LockItems();
+ y=itemGetOrderFromNum(x);
+ CopyMemory(n, (char *)(lpmiItems+y)->lpszDescribe, MAX_DESCRIBE_SIZE);
+ UnlockItems();
+ }
+
+ UnlockVar();
+ break;
+
+
+ /*
+ * char * mpalQuery(MPQ_DIALOG_PERIOD, uint32 nDialog, uint32 nPeriod);
+ */
+ case MPQ_DIALOG_PERIOD:
+ LockDialogs();
+ y=GETARG(uint32);
+ dwRet=(uint32)DuplicateDialogPeriod(y);
+ UnlockDialogs();
+ break;
+
+
+ /*
+ * void mpalQuery(MPQ_DIALOG_WAITFORCHOICE);
+ */
+ case MPQ_DIALOG_WAITFORCHOICE:
+ WaitForSingleObject(hAskChoice,INFINITE);
+ ResetEvent(hAskChoice);
+
+ if (bExecutingDialog)
+ dwRet=(uint32)nExecutingChoice;
+ else
+ dwRet=(uint32)((int)-1);
+ break;
+
+
+ /*
+ * uint32 *mpalQuery(MPQ_DIALOG_SELECTLIST, uint32 nChoice);
+ */
+ case MPQ_DIALOG_SELECTLIST:
+ LockDialogs();
+ dwRet=(uint32)GetSelectList(GETARG(uint32));
+ UnlockDialogs();
+ break;
+
+ /*
+ * bool mpalQuery(MPQ_DIALOG_SELECTION, uint32 nChoice, uint32 dwData);
+ */
+ case MPQ_DIALOG_SELECTION:
+ LockDialogs();
+ x=GETARG(uint32);
+ y=GETARG(uint32);
+ dwRet=(uint32)DoSelection(x,y);
+ UnlockDialogs();
+ break;
+
+
+ /*
+ * int mpalQuery(MPQ_DO_ACTION, uint32 nAction, uint32 nItem, uint32 dwParam);
+ */
+ case MPQ_DO_ACTION:
+ /*
+ if (bExecutingAction)
+ {
+ dwRet=(uint32)INVALID_HANDLE_VALUE;
+ break;
+ }
+ */
+
+ LockItems();
+ LockVar();
+ x=GETARG(uint32);
+ z=GETARG(uint32);
+ y=itemGetOrderFromNum(z);
+ if (y!=-1) {
+ dwRet=(uint32)DoAction(x,y,GETARG(uint32));
+ } else {
+ dwRet=(uint32)INVALID_HANDLE_VALUE;
+ mpalError=1;
+ }
+ UnlockVar();
+ UnlockItems();
+ break;
+
+ /*
+ * int mpalQuery(MPQ_DO_DIALOG, uint32 nDialog, uint32 nGroup);
+ */
+ case MPQ_DO_DIALOG:
+ if (bExecutingDialog)
+ break;
+
+ LockDialogs();
+
+ x=dialogGetOrderFromNum(GETARG(uint32));
+ y=GETARG(uint32);
+ dwRet=(uint32)DoDialog(x,y);
+ UnlockDialogs();
+ break;
+
+ /*
+ * DEFAULT -> ERROR
+ */
+ default:
+ mpalError=1;
+ break;
+ }
+
+ va_end(v);
+
+ return dwRet;
+}
+
+
+/****************************************************************************\
+*
+* Function: uint32 mpalGetError(void);
+*
+* Description: Ritorna il codice di errore corrente di MPAL
+*
+* Return: Codice di errore
+*
+\****************************************************************************/
+
+uint32 mpalGetError(void) {
+ return mpalError;
+}
+
+
+/****************************************************************************\
+*
+* Function: void mpalExecuteScript(int nScript);
+*
+* Description: Esegue uno script. Lo script viene eseguito in multitasking
+* tramite un thread.
+*
+* Input: int nScript Numero dello script da eseguire
+*
+* Return: true se lo script e' stato avviato, false in caso di errore
+*
+\****************************************************************************/
+
+bool EXPORT mpalExecuteScript(int nScript) {
+ int n;
+ LPMPALSCRIPT s;
+ uint32 dwId;
+
+ LockScripts();
+ n=scriptGetOrderFromNum(nScript);
+ s=(LPMPALSCRIPT)GlobalAlloc(GMEM_FIXED|GMEM_ZEROINIT,sizeof(MPALSCRIPT));
+ if (s==NULL)
+ return false;
+
+ CopyMemory(s, lpmsScripts+n, sizeof(MPALSCRIPT));
+ UnlockScripts();
+
+// !!! Nuova gestione dei thread
+ if (CreateThread(NULL,10240,(LPTHREAD_START_ROUTINE)ScriptThread,(void *)s,0,&dwId)==NULL)
+ //if ((void*)_beginthread(ScriptThread,10240,(void *)s)==(void*)-1)
+ return false;
+
+ return true;
+}
+
+
+/****************************************************************************\
+*
+* Function: void mpalInstallItemIrq(LPITEMIRQFUNCTION lpiifCustom);
+*
+* Description: Install a custom routine that will be called by MPAL every
+* time the pattern of an item has been changed.
+*
+* Input: LPITEMIRQFUNCTION lpiifCustom Custom function to install
+*
+\****************************************************************************/
+
+void EXPORT mpalInstallItemIrq(LPITEMIRQFUNCTION lpiifCus) {
+ lpiifCustom=lpiifCus;
+}
+
+
+/****************************************************************************\
+*
+* Function: bool mpalStartIdlePoll(int nLoc);
+*
+* Description: Process the idle actions of the items on one location.
+*
+* Input: int nLoc Number of the location whose items
+* must be processed for idle actions.
+*
+* Return: true se tutto OK, false se si e' superato il limite massimo.
+*
+* Note: Il numero massimo delle locazione che e' possibile pollare
+* contemporaneamente e' contenuto nel define MAXPOLLINGFUNCIONS
+*
+\****************************************************************************/
+
+bool EXPORT mpalStartIdlePoll(int nLoc) {
+ uint32 i;
+ uint32 dwId;
+
+ for (i=0;i<MAXPOLLINGLOCATIONS;i++)
+ if (nPollingLocations[i] == (uint32)nLoc)
+ return false;
+
+ for (i=0;i<MAXPOLLINGLOCATIONS;i++) {
+ if (nPollingLocations[i]==0) {
+ nPollingLocations[i]=nLoc;
+
+ hEndPollingLocations[i]=CreateEvent(NULL,true,false,NULL);
+// !!! Nuova gestione dei thread
+ if ((PollingThreads[i]=CreateThread(NULL,10240,(LPTHREAD_START_ROUTINE)LocationPollThread,(void *)i,0,&dwId))==NULL)
+// if ((hEndPollingLocations[i]=(void*)_beginthread(LocationPollThread,10240,(void *)i))==(void*)-1)
+ return false;
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+
+/****************************************************************************\
+*
+* Function: bool mpalEndIdlePoll(int nLoc);
+*
+* Description: Stop processing the idle actions of the items on one location.
+*
+* Input: int nLoc Number of the location
+*
+* Return: true se tutto OK, false se la locazione specificata non era
+* in fase di polling
+*
+\****************************************************************************/
+
+bool EXPORT mpalEndIdlePoll(int nLoc) {
+ uint32 i;
+
+ for (i=0;i<MAXPOLLINGLOCATIONS;i++)
+ if (nPollingLocations[i] == (uint32)nLoc) {
+ SetEvent(hEndPollingLocations[i]);
+
+ WaitForSingleObject(PollingThreads[i],INFINITE);
+
+ CloseHandle(hEndPollingLocations[i]);
+ nPollingLocations[i]=0;
+
+ return true;
+ }
+
+ return false;
+}
+
+
+
+/****************************************************************************\
+*
+* Function: int mpalGetSaveStateSize(void);
+*
+* Description: Acquire the length of a save state
+*
+* Return: Length in bytes
+*
+\****************************************************************************/
+
+int mpalGetSaveStateSize(void) {
+ return nVars*sizeof(MPALVAR)+4;
+}
+
+
+/****************************************************************************\
+*
+* Function: void mpalSaveState(byte *buf);
+*
+* Description: Store the save state into a buffer. The buffer must be
+* length at least the size specified with mpalGetSaveStateSize
+*
+* Input: byte *buf Buffer where to store the state
+*
+\****************************************************************************/
+
+void mpalSaveState(byte *buf) {
+ LockVar();
+ WRITE_LE_UINT32(buf, nVars);
+ CopyMemory(buf+4, (byte *)lpmvVars, nVars*sizeof(MPALVAR));
+ UnlockVar();
+}
+
+/****************************************************************************\
+*
+* Function: int mpalLoadState(byte *buf);
+*
+* Description: Load a save state from a buffer.
+*
+* Input: byte *buf Buffer where to store the state
+*
+* Return: Length of the state in bytes
+*
+\****************************************************************************/
+
+int mpalLoadState(byte *buf) {
+ // Dobbiamo distruggere tutte le variabili e ricrearle
+ GlobalFree(hVars);
+
+ nVars = READ_LE_UINT32(buf);
+
+ hVars = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE, nVars * sizeof(MPALVAR));
+ LockVar();
+ CopyMemory((byte *)lpmvVars, buf + 4, nVars * sizeof(MPALVAR));
+ UnlockVar();
+
+ return nVars*sizeof(MPALVAR)+4;
+}
+
+bool bDontOutput;
+
+struct {
+ uint16 wStart;
+ uint16 wEnd;
+ char *pComment;
+} MsgComments[] = {
+ { 10, 16, "###" },
+ { 560, 563, "@@@ BUTCH & DUDLEY:" },
+ { 551, 553, "@@@ JACK'S LETTER (JACK'S VOICE):" },
+ { 679, 679, "@@@ OFF-SCREEN VOICE:" },
+ { 799, 799, "###" },
+ { 830, 838, "RE-HASHING (FROM MACBETH):" },
+ { 890, 894, "@@@ BEARDED LADY FROM WITHIN HER ROOM:" },
+ { 1175, 1175, "###" },
+ { 1210, 1210, "###" },
+ { 1347, 1349, "###" },
+ { 1175, 1175, "###" },
+ { 1342, 1343, "###" },
+ { 1742, 1742, "@@@ OFF-SCREEN VOICE:" },
+ { 1749, 1749, "###" },
+ { 1759, 1759, "###" },
+ { 2165, 2166, "@@@ MORTIMER:" },
+ { 2370, 2372, "@@@ ELECTRONIC VOICE FROM AN AUTOMATIC PICTURE MACHINE:" },
+ { 2580, 2589, "@@@ BIFF:" },
+ { 2590, 2593, "@@@ BARTENDER:" },
+ { 2596, 2596, "@@@ SAD PIRATE:" },
+ { 2760, 2767, "@@@ EGGHEAD:" },
+ { 2959, 2959, "@@@ MONSTROUS VOICE FROM BEHIND A LOCKED DOOR:" },
+ { 3352, 3352, "@@@ POLLY:" },
+ { 3378, 3379, "@@@ POLLY:" },
+ { 3461, 3469, "@@@ RANDALL:" },
+ { 3571, 3574, "@@@ CAPTAIN'S JOURNAL (CAPTAIN'S VOICE):" },
+ { 3646, 3646, "NOTE: THIS SENTENCE ENDS THE STORY TOLD IN SENTENCES 03640 - 03643:" },
+ { 3647, 3648, "TONY SPEAKS TRYING TO IMITATE CAPTAIN CORNELIUS' VOICE:" },
+ { 3670, 3671, "###" },
+ { 3652, 3652, "###" },
+ { 3656, 3657, "@@@ GATEKEEPER:" },
+ { 3658, 3659, "@@@ GATEKEEPER (FAR AWAY):" },
+ { 3790, 3795, "@@@ GATEKEEPER:" },
+ { 3798, 3799, "@@@ OFF-SCREEN VOICE:" },
+ { 4384, 4384, "###" },
+ { 4394, 4395, "###" },
+ { 4780, 4780, "###" },
+ { 5089, 5089, "TONY PLAYING SOMEONE ELSE, WITH A DEEPER TONE:" },
+ { 5090, 5090, "NORMAL TONY:" },
+ { 5091, 5091, "TONY PLAYING SOMEONE ELSE, WITH A DEEPER TONE:" },
+ { 5262, 5262, "@@@ OFF-SCREEN VOICE" },
+ { 5276, 5277, "###" },
+ { 5326, 5326, "###" },
+ { 5472, 5472, "LYRICS FROM THE SONG \"I AM ONE\", BY SMASHING PUMPKINS:" },
+ { 5488, 5488, "LYRICS FROM THE SONG \"I AM ONE\", BY SMASHING PUMPKINS:" },
+ { 5652, 5653, "###" },
+//bernie { 11000, 15000, "###" },
+ { 11000, 11111, "###" },
+
+
+ { 0, 0, NULL }
+};
+
+void OutputStartMsgComment(uint16 wNum, Common::OutSaveFile *f) {
+ int i;
+
+ for (i=0;MsgComments[i].wStart!=0;i++)
+ if (MsgComments[i].wStart == wNum) {
+warning("Start: %d\n", wNum);
+
+ f->writeString("</TABLE>\n<P>\n<P>\n");
+
+ if (strcmp(MsgComments[i].pComment, "###") != 0 && strncmp(MsgComments[i].pComment, "@@@", 3) != 0) {
+ f->writeString(Common::String::format("%s\n", MsgComments[i].pComment));
+ f->writeString("<P>\n<P>\n<TABLE WIDTH=100%% BORDER=1>\n");
+ } else
+ bDontOutput=true;
+ return;
+ }
+}
+
+void OutputEndMsgComment(uint16 wNum, Common::OutSaveFile *f) {
+ int i;
+
+ for (i=0;MsgComments[i].wEnd!=0;i++)
+ if (MsgComments[i].wEnd == wNum) {
+warning("End: %d\n", wNum);
+
+ if (strcmp(MsgComments[i].pComment, "###") != 0 && strncmp(MsgComments[i].pComment, "@@@", 3) != 0) {
+ f->writeString("</TABLE>\n<P>\n");
+ } else
+ bDontOutput=false;
+
+ f->writeString("<P>\n<P>\n<TABLE WIDTH=100%% BORDER=1>\n");
+ return;
+ }
+}
+
+
+int OutputStartOther(uint16 wNum, Common::OutSaveFile *f) {
+ int i;
+
+ for (i=0;MsgComments[i].wStart!=0;i++)
+ if (MsgComments[i].wStart <= wNum && MsgComments[i].wEnd >= wNum) {
+ if (strncmp(MsgComments[i].pComment, "@@@", 3) == 0) {
+ if (MsgComments[i].wStart == wNum) {
+ f->writeString(Common::String::format("%s\n", MsgComments[i].pComment+4));
+ f->writeString("<P>\n<P>\n<TABLE WIDTH=100%% BORDER=1>\n");
+ }
+
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+
+void OutputEndOther(uint16 wNum, Common::OutSaveFile *f) {
+ int i;
+
+ for (i=0;MsgComments[i].wStart!=0;i++)
+ if (MsgComments[i].wEnd == wNum && strncmp(MsgComments[i].pComment, "@@@", 3) == 0) {
+ f->writeString("</TABLE>\n<P>\n");
+ break;
+ }
+}
+
+
+void mpalDumpMessages(void) {
+ int i,j;
+ char *lpMessage;
+ char *p;
+ char *lpPeriods[30];
+ char fname[64];
+ char frase[2048];
+ int nPeriods;
+ Common::OutSaveFile *f, *v1;
+
+ v1 = g_system->getSavefileManager()->openForSaving("voicelist.txt");
+
+ LockMsg();
+
+ bDontOutput=false;
+
+ warning("Dumping MESSAGES.HTM...\n");
+
+ f = g_system->getSavefileManager()->openForSaving("Messages.htm");
+ f->writeString("<HTML>\n<BODY>\n<TABLE WIDTH=100%% BORDER=1>\n");
+
+ for (i=0;i<nMsgs;i++) {
+ lpMessage = (char*)GlobalLock(lpmmMsgs[i].hText);
+ if (*lpMessage != '\0') {
+ // bernie: debug
+ /*if (lpmmMsgs[i].wNum == 1950) {
+ int a=1;
+ }*/
+
+ nPeriods=1;
+ p=lpPeriods[0]=lpMessage;
+
+ OutputStartMsgComment(lpmmMsgs[i].wNum, f);
+
+ while (1) {
+ // Trova la fine del periodo corrente
+ while (*p!='\0')
+ p++;
+
+ // Se c'e' un altro '\0' siamo alla fine del messaggio
+ p++;
+ if (*p=='\0')
+ break;
+
+ // Altrimenti c'e' un altro periodo, e ci ricordiamo il suo inizio
+ lpPeriods[nPeriods++]=p;
+ }
+
+ // Ora fa un ciclo su tutti i periodi
+ for (j=0;j<nPeriods;j++) {
+ if (nPeriods==1)
+ sprintf(fname, "000-%05d.WAV", lpmmMsgs[i].wNum);
+ else
+ sprintf(fname, "000-%05d-%02d.WAV", lpmmMsgs[i].wNum,j);
+
+ strcpy(frase,lpPeriods[j]);
+
+ while ((p=strchr(frase,'^'))!=NULL)
+ *p = '\"';
+
+ p = frase;
+ while (*p == ' ') p++;
+ if (*p == '\0')
+ continue;
+
+ if (!bDontOutput) {
+ v1->writeString(Common::String::format("%s\n", fname));
+ f->writeString("\t<TR>\n");
+ f->writeString(Common::String::format("\t\t<TD WIDTH=20%%> %s </B></TD>\n", fname));
+ f->writeString(Common::String::format("\t\t<TD> %s </TD>\n", frase));
+ f->writeString("\t</TR>\n");
+ }
+ }
+
+ OutputEndMsgComment(lpmmMsgs[i].wNum, f);
+
+ GlobalUnlock(lpmmMsgs[i].hText);
+ }
+ }
+
+ f->writeString("</TABLE>\n</BODY>\n</HTML>\n");
+
+ f->finalize();
+ v1->finalize();
+ delete f;
+ delete v1;
+
+ UnlockMsg();
+}
+
+
+
+void mpalDumpOthers(void) {
+ int i,j;
+ char *lpMessage;
+ char *p;
+ char *lpPeriods[30];
+ char fname[64];
+ char frase[2048];
+ int nPeriods;
+
+ Common::OutSaveFile *f, *v1;
+
+ v1 = g_system->getSavefileManager()->openForSaving("voicelist.txt");
+ f = g_system->getSavefileManager()->openForSaving("Others.htm");
+ LockMsg();
+
+ bDontOutput=false;
+
+ warning("Dumping OTHERS.HTM...\n");
+
+ f->writeString("<HTML>\n<BODY>\n");
+
+ for (i=0;i<nMsgs;i++) {
+ lpMessage = (char*)GlobalLock(lpmmMsgs[i].hText);
+ if (*lpMessage != '\0') {
+ nPeriods=1;
+ p=lpPeriods[0]=lpMessage;
+
+ if (OutputStartOther(lpmmMsgs[i].wNum, f)) {
+ while (1) {
+ // Trova la fine del periodo corrente
+ while (*p!='\0')
+ p++;
+
+ // Se c'e' un altro '\0' siamo alla fine del messaggio
+ p++;
+ if (*p=='\0')
+ break;
+
+ // Altrimenti c'e' un altro periodo, e ci ricordiamo il suo inizio
+ lpPeriods[nPeriods++]=p;
+ }
+
+ // Ora fa un ciclo su tutti i periodi
+ for (j=0;j<nPeriods;j++) {
+ if (nPeriods==1)
+ sprintf(fname, "000-%05d.WAV", lpmmMsgs[i].wNum);
+ else
+ sprintf(fname, "000-%05d-%02d.WAV", lpmmMsgs[i].wNum,j);
+
+ strcpy(frase,lpPeriods[j]);
+
+ while ((p=strchr(frase,'^'))!=NULL)
+ *p = '\"';
+
+ p = frase;
+ while (*p == ' ') p++;
+ if (*p == '\0')
+ continue;
+
+ if (!bDontOutput) {
+ v1->writeString(Common::String::format("%s\n", fname));
+ f->writeString("\t<TR>\n");
+ f->writeString(Common::String::format("\t\t<TD WIDTH=20%%> %s </B></TD>\n", fname));
+ f->writeString(Common::String::format("\t\t<TD> %s </TD>\n", frase));
+ f->writeString("\t</TR>\n");
+ }
+ }
+ }
+
+ OutputEndOther(lpmmMsgs[i].wNum, f);
+
+ GlobalUnlock(lpmmMsgs[i].hText);
+ }
+ }
+
+ f->writeString("</BODY>\n</HTML>\n");
+
+ f->finalize();
+ v1->finalize();
+
+ delete f;
+ delete v1;
+ UnlockMsg();
+}
+
+
+#if 0 // English names
+char *DLG10[] = { "Tony", NULL };
+char *DLG51[] = { "Tony", "Butch", "Dudley" };
+char *DLG52[] = { "Tony", NULL };
+char *DLG61[] = { "Tony", "Old lady 1", NULL };
+char *DLG71[] = { "Tony", "Timothy", "Convict", NULL, NULL, "Jack (with microphone)", "Old lady 1", NULL };
+char *DLG90[] = { "Tony", "Bearded lady", NULL };
+char *DLG110[] = { "Tony", "Lorenz", NULL };
+char *DLG111[] = { "Tony", "Lorenz", NULL };
+char *DLG130[] = { "Tony", "Piranha", NULL };
+char *DLG150[] = { "Tony", "Rufus", "Snowman", NULL };
+char *DLG151[] = { "Tony", "Rufus", "Snowman", NULL };
+char *DLG152[] = { "Tony", "Rufus", "Snowman", NULL };
+char *DLG153[] = { "Tony", "Rufus", "Snowman", NULL };
+char *DLG154[] = { "Tony", "Rufus", "Snowman", NULL };
+char *DLG160[] = { "Tony", "Shmiley", NULL };
+char *DLG161[] = { "Tony", "Shmiley", NULL };
+char *DLG162[] = { "Tony", "Shmiley", NULL };
+char *DLG163[] = { "Tony", "Shmiley", NULL };
+char *DLG180[] = { "Tony", "Beast", NULL };
+char *DLG190[] = { "Tony", "Beast", NULL };
+char *DLG191[] = { "Tony", "Beast", NULL };
+char *DLG201[] = { "Tony", NULL };
+char *DLG210[] = { "Tony", "Mortimer", NULL };
+char *DLG211[] = { "Tony", "Mortimer", NULL };
+char *DLG212[] = { "Tony", "Mortimer", NULL };
+char *DLG240[] = { "Tony", "Isabella", NULL };
+char *DLG250[] = { "Tony", "Bartender", "Sad pirate", "Anchorman", "Biff", NULL };
+char *DLG251[] = { "Tony", "Bartender", "Sad pirate", "Anchorman", "Biff", NULL };
+char *DLG260[] = { "Tony", "Captain", "Captain (tale)", NULL };
+char *DLG270[] = { "Tony", "Egghead", NULL };
+char *DLG271[] = { "Tony", "Egghead", NULL };
+char *DLG272[] = { "Tony", "Egghead", NULL };
+char *DLG290[] = { "Tony", "Old lady 2", NULL };
+char *DLG310[] = { "Tony", "Wally", NULL };
+char *DLG330[] = { "Tony", "Polly", "Captain (off scene)", NULL };
+char *DLG340[] = { "Tony", "Randall", NULL };
+char *DLG360[] = { "Tony", NULL };
+char *DLG361[] = { "Tony", NULL };
+char *DLG370[] = { "Tony", "Gatekeeper", NULL };
+char *DLG371[] = { "Tony", "Gatekeeper", NULL };
+char *DLG372[] = { "Tony", "Gatekeeper", NULL };
+char *DLG373[] = { "Tony", "Gatekeeper", NULL };
+char *DLG380[] = { "Tony", NULL };
+char *DLG410[] = { "Tony", "Gwendel", NULL };
+char *DLG430[] = { "Tony", "Harold", "Chuck", "Pigeons", "Housekeeper (off scene)", NULL };
+char *DLG460[] = { "Tony", NULL };
+char *DLG470[] = { "Tony", "Housekeeper", "Mirror", NULL };
+char *DLG471[] = { "Tony", "Housekeeper", "Mirror", NULL };
+char *DLG472[] = { "Tony", "Housekeeper", "Mirror", NULL };
+char *DLG473[] = { "Tony", "Housekeeper", "Mirror", NULL };
+char *DLG474[] = { "Tony", "Housekeeper", "Mirror", NULL };
+char *DLG480[] = { "Tony", "Pin-up", NULL };
+char *DLG490[] = { "Tony", "Gwendel", NULL };
+char *DLG530[] = { "Tony", "Harold", "Chuck", NULL };
+char *DLG550[] = { "Tony", "Mr. Wishing Well", "Tony (from the top of the well)", NULL };
+char *DLG560[] = { "Tony", "Superintendent", NULL };
+char *DLG590[] = { "Tony", "Pantagruel", NULL };
+char *DLG600[] = { "Tony", "Jack", "Jack", NULL, "Jack", NULL, NULL, NULL, "Storyteller", "Mr. Wishing Well", NULL };
+#endif
+
+#if 0 // Polish names
+char *DLG10[] = { "Tony", NULL };
+char *DLG51[] = { "Tony", "Butch", "Dudley" };
+char *DLG52[] = { "Tony", NULL };
+char *DLG61[] = { "Tony", "Staruszka 1", NULL };
+char *DLG71[] = { "Tony", "Timothy", "Skazaniec", NULL, NULL, "£ebster (przez mikrofon)", "Staruszka 1", NULL };
+char *DLG90[] = { "Tony", "Kobieta z Brod¹", NULL };
+char *DLG110[] = { "Tony", "Lorenz", NULL };
+char *DLG111[] = { "Tony", "Lorenz", NULL };
+char *DLG130[] = { "Tony", "Pirania", NULL };
+char *DLG150[] = { "Tony", "Rufus", "Ba³wan", NULL };
+char *DLG151[] = { "Tony", "Rufus", "Ba³wan", NULL };
+char *DLG152[] = { "Tony", "Rufus", "Ba³wan", NULL };
+char *DLG153[] = { "Tony", "Rufus", "Ba³wan", NULL };
+char *DLG154[] = { "Tony", "Rufus", "Ba³wan", NULL };
+char *DLG160[] = { "Tony", "Œmiechozol", NULL };
+char *DLG161[] = { "Tony", "Œmiechozol", NULL };
+char *DLG162[] = { "Tony", "Œmiechozol", NULL };
+char *DLG163[] = { "Tony", "Œmiechozol", NULL };
+char *DLG180[] = { "Tony", "Wycz", NULL };
+char *DLG190[] = { "Tony", "Wycz", NULL };
+char *DLG191[] = { "Tony", "Wycz", NULL };
+char *DLG201[] = { "Tony", NULL };
+char *DLG210[] = { "Tony", "Mortimer (Okropny)", NULL };
+char *DLG211[] = { "Tony", "Mortimer (Okropny)", NULL };
+char *DLG212[] = { "Tony", "Mortimer (Okropny)", NULL };
+char *DLG240[] = { "Tony", "Isabella", NULL };
+char *DLG250[] = { "Tony", "Barman", "Smutny Pirat", "Wodzirej", "Biff", NULL };
+char *DLG251[] = { "Tony", "Barman", "Smutny Pirat", "Wodzirej", "Biff", NULL };
+char *DLG260[] = { "Tony", "Kapitan", "Captain (opowieϾ)", NULL };
+char *DLG270[] = { "Tony", "Jajog³owy", NULL };
+char *DLG271[] = { "Tony", "Jajog³owy", NULL };
+char *DLG272[] = { "Tony", "Jajog³owy", NULL };
+char *DLG290[] = { "Tony", "Staruszka 2", NULL };
+char *DLG310[] = { "Tony", "Wally", NULL };
+char *DLG330[] = { "Tony", "Polly", "Kapitan (zza sceny)", NULL };
+char *DLG340[] = { "Tony", "Randall", NULL };
+char *DLG360[] = { "Tony", NULL };
+char *DLG361[] = { "Tony", NULL };
+char *DLG370[] = { "Tony", "Stra¿nik", NULL };
+char *DLG371[] = { "Tony", "Stra¿nik", NULL };
+char *DLG372[] = { "Tony", "Stra¿nik", NULL };
+char *DLG373[] = { "Tony", "Stra¿nik", NULL };
+char *DLG380[] = { "Tony", NULL };
+char *DLG410[] = { "Tony", "Gwendel", NULL };
+char *DLG430[] = { "Tony", "Harold", "Chuck", "Pigeons", "Gospodyni (zza sceny)", NULL };
+char *DLG460[] = { "Tony", NULL };
+char *DLG470[] = { "Tony", "Gospodyni", "Mirror", NULL };
+char *DLG471[] = { "Tony", "Gospodyni", "Mirror", NULL };
+char *DLG472[] = { "Tony", "Gospodyni", "Mirror", NULL };
+char *DLG473[] = { "Tony", "Gospodyni", "Mirror", NULL };
+char *DLG474[] = { "Tony", "Gospodyni", "Mirror", NULL };
+char *DLG480[] = { "Tony", "Pin-up", NULL };
+char *DLG490[] = { "Tony", "Gwendel", NULL };
+char *DLG530[] = { "Tony", "Harold", "Chuck", NULL };
+char *DLG550[] = { "Tony", "Pan Studnia ¯yczeñ", "Tony (nad studni¹)", NULL };
+char *DLG560[] = { "Tony", "Inspektor", NULL };
+char *DLG590[] = { "Tony", "Pantaloniarz", NULL };
+char *DLG600[] = { "Tony", "£ebster", "£ebster", NULL, "£ebster", NULL, NULL, NULL, "Narrator", "Pan Studnia ¯yczeñ", NULL };
+#endif // Polish
+
+
+#if 0 // Russian
+char *DLG10[] = { "Òîíè", NULL };
+char *DLG51[] = { "Òîíè", "Áó÷", "Äàäëè" };
+char *DLG52[] = { "Òîíè", NULL };
+char *DLG61[] = { "Òîíè", "Ñòàðóøêà 1", NULL };
+char *DLG71[] = { "Òîíè", "Òèìîòè", "Îñóæäåííûé", NULL, NULL, "Äæåê (ñ ìèêðîôîíîì)", "Ñòàðóøêà 1", NULL };
+char *DLG90[] = { "Òîíè", "Áîðîäàòàÿ æåíùèíà", NULL };
+char *DLG110[] = { "Òîíè", "Ëîðåíö", NULL };
+char *DLG111[] = { "Òîíè", "Ëîðåíö", NULL };
+char *DLG130[] = { "Òîíè", "Ïèðàíüÿ", NULL };
+char *DLG150[] = { "Òîíè", "Ðóôóñ", "Ñíåãîâèê", NULL };
+char *DLG151[] = { "Òîíè", "Ðóôóñ", "Ñíåãîâèê", NULL };
+char *DLG152[] = { "Òîíè", "Ðóôóñ", "Ñíåãîâèê", NULL };
+char *DLG153[] = { "Òîíè", "Ðóôóñ", "Ñíåãîâèê", NULL };
+char *DLG154[] = { "Òîíè", "Ðóôóñ", "Ñíåãîâèê", NULL };
+char *DLG160[] = { "Òîíè", "Øìàéëè", NULL };
+char *DLG161[] = { "Òîíè", "Øìàéëè", NULL };
+char *DLG162[] = { "Òîíè", "Øìàéëè", NULL };
+char *DLG163[] = { "Òîíè", "Øìàéëè", NULL };
+char *DLG180[] = { "Òîíè", "×óäîâèùå", NULL };
+char *DLG190[] = { "Òîíè", "×óäîâèùå", NULL };
+char *DLG191[] = { "Òîíè", "×óäîâèùå", NULL };
+char *DLG201[] = { "Òîíè", NULL };
+char *DLG210[] = { "Òîíè", "Ìîðòèìåð", NULL };
+char *DLG211[] = { "Òîíè", "Ìîðòèìåð", NULL };
+char *DLG212[] = { "Òîíè", "Ìîðòèìåð", NULL };
+char *DLG240[] = { "Òîíè", "Èçàáåëëà", NULL };
+char *DLG250[] = { "Òîíè", "Áàðìåí", "Ãðóñòíûé ïèðàò", "Âåäóùèé", "Áèôô", NULL };
+char *DLG251[] = { "Òîíè", "Áàðìåí", "Ãðóñòíûé ïèðàò", "Âåäóùèé", "Áèôô", NULL };
+char *DLG260[] = { "Òîíè", "Êàïèòàí", "Êàïèòàí (ðàññêàç)", NULL };
+char *DLG270[] = { "Òîíè", "ßéöåãîëîâûé", NULL };
+char *DLG271[] = { "Òîíè", "ßéöåãîëîâûé", NULL };
+char *DLG272[] = { "Òîíè", "ßéöåãîëîâûé", NULL };
+char *DLG290[] = { "Òîíè", "Ñòàðóøêà 2", NULL };
+char *DLG310[] = { "Òîíè", "Óîëëè", NULL };
+char *DLG330[] = { "Òîíè", "Ïîëëè", "Êàïèòàí (çà ñöåíîé)", NULL };
+char *DLG340[] = { "Òîíè", "Ðýíäàë", NULL };
+char *DLG360[] = { "Òîíè", NULL };
+char *DLG361[] = { "Òîíè", NULL };
+char *DLG370[] = { "Òîíè", "Ïðèâðàòíèê", NULL };
+char *DLG371[] = { "Òîíè", "Ïðèâðàòíèê", NULL };
+char *DLG372[] = { "Òîíè", "Ïðèâðàòíèê", NULL };
+char *DLG373[] = { "Òîíè", "Ïðèâðàòíèê", NULL };
+char *DLG380[] = { "Òîíè", NULL };
+char *DLG410[] = { "Òîíè", "Ãâåíäåëü", NULL };
+char *DLG430[] = { "Òîíè", "Ãàðîëüä", "×àê", "Pigeons", "Housekeeper (off scene)", NULL };
+char *DLG460[] = { "Òîíè", NULL };
+char *DLG470[] = { "Òîíè", "Housekeeper", "Mirror", NULL };
+char *DLG471[] = { "Òîíè", "Housekeeper", "Mirror", NULL };
+char *DLG472[] = { "Òîíè", "Housekeeper", "Mirror", NULL };
+char *DLG473[] = { "Òîíè", "Housekeeper", "Mirror", NULL };
+char *DLG474[] = { "Òîíè", "Housekeeper", "Mirror", NULL };
+char *DLG480[] = { "Òîíè", "Pin-up", NULL };
+char *DLG490[] = { "Òîíè", "Ãâåíäåëü", NULL };
+char *DLG530[] = { "Òîíè", "Ãàðîëüä", "×àê", NULL };
+char *DLG550[] = { "Òîíè", "Ãîñïîäèí Êîëîäåö æåëàíèé", "Òîíè (ñ âåðøèíû êîëîäöà)", NULL };
+char *DLG560[] = { "Òîíè", "Íà÷àëüíèê îõðàíû", NULL };
+char *DLG590[] = { "Òîíè", "Ïàíòàãðþýëü", NULL };
+char *DLG600[] = { "Òîíè", "Äæåê", "Äæåê", NULL, "Äæåê", NULL, NULL, NULL, "Ðàññêàç÷èê", "Ãîñïîäèí Êîëîäåö æåëàíèé", NULL };
+#endif // Russian
+
+
+#if 0 // Czech names
+char *DLG10[] = { "Tony", NULL };
+char *DLG51[] = { "Tony", "Butch", "Dudley" };
+char *DLG52[] = { "Tony", NULL };
+char *DLG61[] = { "Tony", "Stará paní 1", NULL };
+char *DLG71[] = { "Tony", "Timothy", "Trestanec", NULL, NULL, "Jack (s mikrofonem)", "Stará paní 1", NULL };
+char *DLG90[] = { "Tony", "Vousatá žena", NULL };
+char *DLG110[] = { "Tony", "Lorenz", NULL };
+char *DLG111[] = { "Tony", "Lorenz", NULL };
+char *DLG130[] = { "Tony", "Piraòa", NULL };
+char *DLG150[] = { "Tony", "Rufus", "Snìhulák", NULL };
+char *DLG151[] = { "Tony", "Rufus", "Snìhulák", NULL };
+char *DLG152[] = { "Tony", "Rufus", "Snìhulák", NULL };
+char *DLG153[] = { "Tony", "Rufus", "Snìhulák", NULL };
+char *DLG154[] = { "Tony", "Rufus", "Snìhulák", NULL };
+char *DLG160[] = { "Tony", "Shmiley", NULL };
+char *DLG161[] = { "Tony", "Shmiley", NULL };
+char *DLG162[] = { "Tony", "Shmiley", NULL };
+char *DLG163[] = { "Tony", "Shmiley", NULL };
+char *DLG180[] = { "Tony", "Zvíøe", NULL };
+char *DLG190[] = { "Tony", "Zvíøe", NULL };
+char *DLG191[] = { "Tony", "Zvíøe", NULL };
+char *DLG201[] = { "Tony", NULL };
+char *DLG210[] = { "Tony", "Mortimer", NULL };
+char *DLG211[] = { "Tony", "Mortimer", NULL };
+char *DLG212[] = { "Tony", "Mortimer", NULL };
+char *DLG240[] = { "Tony", "Isabella", NULL };
+char *DLG250[] = { "Tony", "Barman", "Smutný pirát", "Moderátor", "Biff", NULL };
+char *DLG251[] = { "Tony", "Barman", "Smutný pirát", "Moderátor", "Biff", NULL };
+char *DLG260[] = { "Tony", "Kapitán", "Kapitán (pøíbìh)", NULL };
+char *DLG270[] = { "Tony", "Intelektuál", NULL };
+char *DLG271[] = { "Tony", "Intelektuál", NULL };
+char *DLG272[] = { "Tony", "Intelektuál", NULL };
+char *DLG290[] = { "Tony", "Stará paní 2", NULL };
+char *DLG310[] = { "Tony", "Wally", NULL };
+char *DLG330[] = { "Tony", "Lóra", "Kapitán (mimo scénu)", NULL };
+char *DLG340[] = { "Tony", "Randall", NULL };
+char *DLG360[] = { "Tony", NULL };
+char *DLG361[] = { "Tony", NULL };
+char *DLG370[] = { "Tony", "Strážný", NULL };
+char *DLG371[] = { "Tony", "Strážný", NULL };
+char *DLG372[] = { "Tony", "Strážný", NULL };
+char *DLG373[] = { "Tony", "Strážný", NULL };
+char *DLG380[] = { "Tony", NULL };
+char *DLG410[] = { "Tony", "Gwendel", NULL };
+char *DLG430[] = { "Tony", "Harold", "Chuck", "Pigeons", "Housekeeper (off scene)", NULL };
+char *DLG460[] = { "Tony", NULL };
+char *DLG470[] = { "Tony", "Housekeeper", "Mirror", NULL };
+char *DLG471[] = { "Tony", "Housekeeper", "Mirror", NULL };
+char *DLG472[] = { "Tony", "Housekeeper", "Mirror", NULL };
+char *DLG473[] = { "Tony", "Housekeeper", "Mirror", NULL };
+char *DLG474[] = { "Tony", "Housekeeper", "Mirror", NULL };
+char *DLG480[] = { "Tony", "Pin-up", NULL };
+char *DLG490[] = { "Tony", "Gwendel", NULL };
+char *DLG530[] = { "Tony", "Harold", "Chuck", NULL };
+char *DLG550[] = { "Tony", "Pan Studna pøání", "Tony (z vrcholu studny)", NULL };
+char *DLG560[] = { "Tony", "Správce", NULL };
+char *DLG590[] = { "Tony", "Pantagruel", NULL };
+char *DLG600[] = { "Tony", "Jack", "Jack", NULL, "Jack", NULL, NULL, NULL, "Vypravìè", "Pan Studna pøání", NULL };
+#endif // Czech names
+
+#if 1 // Deutsch names
+char *DLG10[] = { "Tony", NULL };
+char *DLG51[] = { "Tony", "Butch", "Dudley" };
+char *DLG52[] = { "Tony", NULL };
+char *DLG61[] = { "Tony", "Alte Dame 1", NULL };
+char *DLG71[] = { "Tony", "Timothy", "Sträfling", NULL, NULL, "Jack (mit Mikrofon)", "Alte Dame 1", NULL };
+char *DLG90[] = { "Tony", "Bärtige Dame", NULL };
+char *DLG110[] = { "Tony", "Lorenz", NULL };
+char *DLG111[] = { "Tony", "Lorenz", NULL };
+char *DLG130[] = { "Tony", "Piranha", NULL };
+char *DLG150[] = { "Tony", "Rufus", "Schneemann", NULL };
+char *DLG151[] = { "Tony", "Rufus", "Schneemann", NULL };
+char *DLG152[] = { "Tony", "Rufus", "Schneemann", NULL };
+char *DLG153[] = { "Tony", "Rufus", "Schneemann", NULL };
+char *DLG154[] = { "Tony", "Rufus", "Schneemann", NULL };
+char *DLG160[] = { "Tony", "Shmiley", NULL };
+char *DLG161[] = { "Tony", "Shmiley", NULL };
+char *DLG162[] = { "Tony", "Shmiley", NULL };
+char *DLG163[] = { "Tony", "Shmiley", NULL };
+char *DLG180[] = { "Tony", "Biest", NULL };
+char *DLG190[] = { "Tony", "Biest", NULL };
+char *DLG191[] = { "Tony", "Biest", NULL };
+char *DLG201[] = { "Tony", NULL };
+char *DLG210[] = { "Tony", "Mortimer", NULL };
+char *DLG211[] = { "Tony", "Mortimer", NULL };
+char *DLG212[] = { "Tony", "Mortimer", NULL };
+char *DLG240[] = { "Tony", "Isabella", NULL };
+char *DLG250[] = { "Tony", "Barmann", "Trauriger Pirat", "Chefanimateur", "Biff", NULL };
+char *DLG251[] = { "Tony", "Barmann", "Trauriger Pirat", "Chefanimateur", "Biff", NULL };
+char *DLG260[] = { "Tony", "Kapitän", "Kapitän (Erzählung)", NULL };
+char *DLG270[] = { "Tony", "Eierkopf", NULL };
+char *DLG271[] = { "Tony", "Eierkopf", NULL };
+char *DLG272[] = { "Tony", "Eierkopf", NULL };
+char *DLG290[] = { "Tony", "Alte Dame 2", NULL };
+char *DLG310[] = { "Tony", "Wally", NULL };
+char *DLG330[] = { "Tony", "Polly", "Kapitän (im Off)", NULL };
+char *DLG340[] = { "Tony", "Randall", NULL };
+char *DLG360[] = { "Tony", NULL };
+char *DLG361[] = { "Tony", NULL };
+char *DLG370[] = { "Tony", "Pförtner", NULL };
+char *DLG371[] = { "Tony", "Pförtner", NULL };
+char *DLG372[] = { "Tony", "Pförtner", NULL };
+char *DLG373[] = { "Tony", "Pförtner", NULL };
+char *DLG380[] = { "Tony", NULL };
+char *DLG410[] = { "Tony", "Gwendel", NULL };
+char *DLG430[] = { "Tony", "Harold", "Chuck", "Pigeons", "Housekeeper (off scene)", NULL };
+char *DLG460[] = { "Tony", NULL };
+char *DLG470[] = { "Tony", "Housekeeper", "Mirror", NULL };
+char *DLG471[] = { "Tony", "Housekeeper", "Mirror", NULL };
+char *DLG472[] = { "Tony", "Housekeeper", "Mirror", NULL };
+char *DLG473[] = { "Tony", "Housekeeper", "Mirror", NULL };
+char *DLG474[] = { "Tony", "Housekeeper", "Mirror", NULL };
+char *DLG480[] = { "Tony", "Pin-up", NULL };
+char *DLG490[] = { "Tony", "Gwendel", NULL };
+char *DLG530[] = { "Tony", "Harold", "Chuck", NULL };
+char *DLG550[] = { "Tony", "Herr Wunschbrunnen", "Tony (über dem Brunnen)", NULL };
+char *DLG560[] = { "Tony", "Verwalter", NULL };
+char *DLG590[] = { "Tony", "Pantagruel", NULL };
+char *DLG600[] = { "Tony", "Jack", "Jack", NULL, "Jack", NULL, NULL, NULL, "Erzähler", "Herr Wunschbrunnen", NULL };
+#endif
+
+
+#define HANDLE_DIALOG(num) \
+case num: \
+ if (nPers >= sizeof(DLG##num) / sizeof(char*) || DLG##num[nPers]==NULL) \
+ { \
+ warning("ERROR: Il personaggio #%d non esiste nel dialogo %d!\n", nPers, nDlg); \
+ return "ERROR"; \
+ } \
+ else \
+ return DLG##num[nPers];
+
+
+char *GetPersonName(uint16 nDlg, int nPers)
+{
+ switch (nDlg)
+ {
+ HANDLE_DIALOG(10);
+ HANDLE_DIALOG(51);
+ HANDLE_DIALOG(52);
+ HANDLE_DIALOG(61);
+ HANDLE_DIALOG(71);
+ HANDLE_DIALOG(90);
+ HANDLE_DIALOG(110);
+ HANDLE_DIALOG(111);
+ HANDLE_DIALOG(130);
+ HANDLE_DIALOG(150);
+ HANDLE_DIALOG(151);
+ HANDLE_DIALOG(152);
+ HANDLE_DIALOG(153);
+ HANDLE_DIALOG(154);
+ HANDLE_DIALOG(160);
+ HANDLE_DIALOG(161);
+ HANDLE_DIALOG(162);
+ HANDLE_DIALOG(163);
+ HANDLE_DIALOG(180);
+ HANDLE_DIALOG(190);
+ HANDLE_DIALOG(191);
+ HANDLE_DIALOG(201);
+ HANDLE_DIALOG(210);
+ HANDLE_DIALOG(211);
+ HANDLE_DIALOG(212);
+ HANDLE_DIALOG(240);
+ HANDLE_DIALOG(250);
+ HANDLE_DIALOG(251);
+ HANDLE_DIALOG(260);
+ HANDLE_DIALOG(270);
+ HANDLE_DIALOG(271);
+ HANDLE_DIALOG(272);
+ HANDLE_DIALOG(290);
+ HANDLE_DIALOG(310);
+ HANDLE_DIALOG(330);
+ HANDLE_DIALOG(340);
+ HANDLE_DIALOG(360);
+ HANDLE_DIALOG(361);
+ HANDLE_DIALOG(370);
+ HANDLE_DIALOG(371);
+ HANDLE_DIALOG(372);
+ HANDLE_DIALOG(373);
+ HANDLE_DIALOG(380);
+ HANDLE_DIALOG(410);
+ HANDLE_DIALOG(430);
+ HANDLE_DIALOG(460);
+ HANDLE_DIALOG(470);
+ HANDLE_DIALOG(471);
+ HANDLE_DIALOG(472);
+ HANDLE_DIALOG(473);
+ HANDLE_DIALOG(474);
+ HANDLE_DIALOG(480);
+ HANDLE_DIALOG(490);
+ HANDLE_DIALOG(530);
+ HANDLE_DIALOG(550);
+ HANDLE_DIALOG(560);
+ HANDLE_DIALOG(590);
+ HANDLE_DIALOG(600);
+
+ default:
+ warning("ERROR: Il dialogo %d non esiste!\n", nDlg);
+ return "ERROR";
+ }
+}
+
+void mpalDumpDialog(LPMPALDIALOG dlg) {
+ char dfn[64];
+ char fname[64];
+ int g,c,j;
+ struct command* curCmd;
+ char *frase; char *p;
+ char copia[2048];
+ bool bAtLeastOne;
+ Common::OutSaveFile *f, *v1;
+
+ v1 = g_system->getSavefileManager()->openForSaving("voicelist.txt");
+
+ sprintf(dfn,"DIALOG%03d.HTM",dlg->nObj);
+ warning("Dumping %s...\n", dfn);
+
+ f = g_system->getSavefileManager()->openForSaving(dfn);
+
+ f->writeString("<HTML>\n<BODY>\n");
+
+ for (g=0;dlg->Group[g].num != 0; g++) {
+ bAtLeastOne = false;
+
+ for (c=0;c<dlg->Group[g].nCmds; c++) {
+ curCmd = &dlg->Command[dlg->Group[g].CmdNum[c]];
+ if (curCmd->type == 1 && curCmd->nCf == 71) {
+ bAtLeastOne=true;
+ break;
+ }
+ }
+
+ if (!bAtLeastOne)
+ continue;
+
+ f->writeString(Common::String::format("<P>\n<H3>Group %d</H3>\n<P>\n", g));
+ f->writeString("<TABLE WIDTH=100%% BORDER=1>\n");
+
+ for (c=0;c<dlg->Group[g].nCmds; c++) {
+ curCmd = &dlg->Command[dlg->Group[g].CmdNum[c]];
+
+ // Se è una funzione custom, e richiama la SendDialogMessage(nPers, nMsg)
+ if (curCmd->type == 1 && curCmd->nCf == 71) {
+ sprintf(fname, "%03d-%05d.WAV", dlg->nObj, curCmd->arg2);
+
+ for (j=0;dlg->Periods[j]!=NULL;j++)
+ if (dlg->PeriodNums[j] == curCmd->arg2)
+ break;
+
+ if (dlg->Periods[j]==NULL)
+ warning("ERROR: Dialogo %d, Periodo %d non trovato!\n", (int)dlg->nObj, (int)curCmd->arg2);
+ else {
+ frase = (char *)GlobalLock(dlg->Periods[j]);
+ strcpy(copia, frase);
+ GlobalUnlock(dlg->Periods[j]);
+
+ while ((p=strchr(copia,'^')) != NULL)
+ *p = '\"';
+
+ p = frase;
+ while (*p == ' ') p++;
+ if (*p == '\0')
+ continue;
+
+ v1->writeString(Common::String::format("%s\n", fname));
+ f->writeString("\t<TR>\n");
+ f->writeString(Common::String::format("\t\t<TD WIDTH=20%%> %s </TD>\n", fname));
+ f->writeString(Common::String::format("\t\t<TD WIDTH=13%%> <B> %s </B> </TD>\n",
+ GetPersonName(dlg->nObj, curCmd->arg1)));
+ f->writeString(Common::String::format("\t\t<TD> %s </TD>\n",copia));
+ f->writeString("\t</TR>\n");
+ //fprintf(f, "(%s) <%s> %s\n", fname, GetPersonName(dlg->nObj, curCmd->arg1), copia);
+ }
+ }
+ }
+
+ f->writeString("</TABLE><P>\n");
+ //fprintf(f,"\n\n\n\n");
+ }
+
+ f->finalize();
+ v1->finalize();
+ delete f;
+ delete v1;
+}
+
+void mpalDumpDialogs(void) {
+ int i;
+
+ LockDialogs();
+
+ for (i=0;i<nDialogs;i++)
+ mpalDumpDialog(&lpmdDialogs[i]);
+
+ UnlockDialogs();
+}
+
+} // end of namespace MPAL
+
+} // end of namespace Tony
diff --git a/engines/tony/mpal/mpal.h b/engines/tony/mpal/mpal.h
new file mode 100644
index 0000000000..73e2dec50f
--- /dev/null
+++ b/engines/tony/mpal/mpal.h
@@ -0,0 +1,769 @@
+/* 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.
+ *
+ *
+ */
+/**************************************************************************
+ * ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ *
+ * ... Spyral Software snc *
+ * . x#""*$Nu -= We create much MORE than ALL =- *
+ * d*#R$. R ^#$o ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ *
+ * .F ^$k $ "$b *
+ * ." $b u "$ #$L *
+ * P $c :*$L"$L '$k Project: MPAL................... *
+ * d @$N. $. d ^$b^$k $c *
+ * F 4 "$c '$ $ #$u#$u '$ Module: MPAL Main Include file. *
+ * 4 4k *N #b .> '$N'*$u * *
+ * M $L #$ $ 8 "$c'#$b.. .@ Author: Giovanni Bajo.......... *
+ * M '$u "$u :" *$. "#*#" *
+ * M '$N. " F ^$k Desc: Main Include file for *
+ * 4> ^R$oue# d using MPAL.DLL......... *
+ * '$ "" @ ....................... *
+ * #b u# *
+ * $b .@" OS: [ ] DOS [X] WIN95 [ ] OS/2 *
+ * #$u .d" *
+ * '*$e. .zR".@ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ *
+ * "*$$beooee$*" @"M This source code is *
+ * """ '$.? Copyright (C) Spyral Software *
+ * '$d> ALL RIGHTS RESERVED *
+ * '$> ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ *
+ * *
+ **************************************************************************/
+
+
+/****************************************************************************\
+* Copyright Notice
+\****************************************************************************/
+
+/*
+ * A Spyral Software Production:
+ *
+ * MPAL - MultiPurpose Adventure Language
+ * (C) 1997 Giovanni Bajo and Luca Giusti
+ * ALL RIGHTS RESERVED
+ *
+ *
+ */
+
+
+/****************************************************************************\
+* General Introduction
+\****************************************************************************/
+
+/*
+ * MPAL (MultiPurpose Adventure Language) is a high level language
+ * for the definition of adventure. Through the use of MPAL you can describe
+ * storyboard the adventure, and then use it with any user interface.
+ * In fact, unlike many other similar products, MPAL is not programmed through
+ * the whole adventure, but are defined only the locations, objects, as they may
+ * interact with each other, etc.. thus making MPAL useful for any type of adventure.
+ */
+
+/****************************************************************************\
+* Structure
+\****************************************************************************/
+
+/*
+ * MPAL consists of two main files: MPAL.DLL and MPAL.H
+ * The first is the DLL that contains the code to interface with MPAL
+ * adventures, the second is the header that defines the prototypes
+ * functions. MPAL is compiled for Win32, and it can therefore be used with
+ * any compiler that supports Win32 DLL (Watcom C++, Visual C++,
+ * Delphi, etc.), and therefore compatible with both Windows 95 and Windows NT.
+ *
+ * To use the DLL, and 'obviously need to create a library for symbols to export.
+ *
+ */
+
+
+/****************************************************************************\
+* Custom Functions
+\****************************************************************************/
+
+/*
+ * A custom function and a function specified by the program that uses the
+ * library, to perform the particular code. The custom functions are
+ * retrieved from the library as specified in the source MPAL, and in particular
+ * in defining the behavior of an item with some action.
+ *
+ * To use the custom functions, you need to prepare an array of
+ * pointers to functions (such as using the type casting LPCUSTOMFUNCTION,
+ * (defined below), and pass it as second parameter to mpalInit (). Note you
+ * must specify the size of the array, as elements of pointers and which do not
+ * contain the same: the library will call it only those functions specified in
+ * the source MPAL. It can be useful, for debugging reasons, do not bet
+ * the shares of arrays used to debugging function, to avoid unpleasant crash,
+ * if it has been made an error in source and / or some oversight in the code.
+ *
+ */
+
+#ifndef __MPAL_H
+#define __MPAL_H
+
+#include "common/scummsys.h"
+#include "common/rect.h"
+
+/****************************************************************************\
+* Macro definitions and structures
+\****************************************************************************/
+
+/* OK value for the error codes */
+#define OK 0
+
+#define MAXFRAMES 400 // frame animation of an object
+#define MAXPATTERN 40 // pattern of animation of an object
+
+#define MAXPOLLINGLOCATIONS 64
+
+#define EXPORT
+#define LPSTR char *
+
+/****************************************************************************\
+* enum QueryCoordinates
+* ---------------------
+* Description: Macro for use with queries that may refer to X and Y co-ordinates
+\****************************************************************************/
+
+enum QueryCoordinates {
+ MPQ_X,
+ MPQ_Y
+};
+
+
+/****************************************************************************\
+* enum QueryTypes
+* ---------------
+* Description: Query can be used with mpalQuery (). In practice corresponds
+* all claims that can do at the library
+\****************************************************************************/
+
+enum QueryTypes {
+ /* General Query */
+ MPQ_VERSION=10,
+
+ MPQ_GLOBAL_VAR=50,
+ MPQ_RESOURCE,
+ MPQ_MESSAGE,
+
+ /* Query on leases */
+ MPQ_LOCATION_IMAGE=100,
+ MPQ_LOCATION_SIZE,
+
+ /* Queries about items */
+ MPQ_ITEM_LIST=200,
+ MPQ_ITEM_DATA,
+ MPQ_ITEM_PATTERN,
+ MPQ_ITEM_NAME,
+ MPQ_ITEM_IS_ACTIVE,
+
+ /* Query dialog */
+ MPQ_DIALOG_PERIOD=300,
+ MPQ_DIALOG_WAITFORCHOICE,
+ MPQ_DIALOG_SELECTLIST,
+ MPQ_DIALOG_SELECTION,
+
+ /* Query execution */
+ MPQ_DO_ACTION=400,
+ MPQ_DO_DIALOG
+};
+
+
+/****************************************************************************\
+* typedef ITEM
+* ------------
+* Description: Framework to manage the animation of an item
+\****************************************************************************/
+
+typedef struct {
+ char *frames[MAXFRAMES];
+ Common::Rect frameslocations[MAXFRAMES];
+ Common::Rect bbox[MAXFRAMES];
+ short pattern[MAXPATTERN][MAXFRAMES];
+ short speed;
+ char numframe;
+ char numpattern;
+ char curframe;
+ char curpattern;
+ short destX, destY;
+ signed char Zvalue;
+ short objectID;
+ char TAG;
+} ITEM;
+typedef ITEM *LPITEM;
+
+
+/****************************************************************************\
+* typedef LPCUSTOMFUNCTION
+* ------------------------
+* Description: Define a custom function, to use the language MPAL
+* to perform various controls as a result of an action
+\****************************************************************************/
+
+typedef void (*LPCUSTOMFUNCTION)(uint32, uint32, uint32, uint32);
+typedef LPCUSTOMFUNCTION *LPLPCUSTOMFUNCTION;
+
+
+/****************************************************************************\
+* typedef LPITEMIRQFUNCTION
+* -------------------------
+* Description: Define an IRQ of an item that is called when the
+* pattern changes or the status of an item
+\****************************************************************************/
+
+typedef void (*LPITEMIRQFUNCTION)(uint32, int, int);
+typedef LPITEMIRQFUNCTION* LPLPITEMIRQFUNCTION;
+
+
+/****************************************************************************\
+* Macrofunctions query
+\****************************************************************************/
+
+/****************************************************************************\
+*
+* Function: uint32 mpalQueryVersion(void);
+*
+* Description: Gets the current version of MPAL
+*
+* Return: Version number (0x1232 = 1.2.3b)
+*
+\****************************************************************************/
+
+#define mpalQueryVersion() \
+ (uint16)mpalQuery(MPQ_VERSION)
+
+
+
+/****************************************************************************\
+*
+* Function: uint32 mpalQueryGlobalVar(LPSTR lpszVarName);
+*
+* Description: Gets the numerical value of a global variable
+*
+* Input: LPSTR lpszVarName Nome della variabile (ASCIIZ)
+*
+* Return: Valore della variabile
+*
+* Note: This query was implemented for debugging. The program,
+* if well designed, should not need to access variables from
+* within the library.
+*
+\****************************************************************************/
+
+#define mpalQueryGlobalVar(lpszVarName) \
+ (uint32)mpalQuery(MPQ_GLOBAL_VAR,(LPSTR)(lpszVarName))
+
+
+
+/****************************************************************************\
+*
+* Function: HGLOBAL mpalQueryResource(uint32 dwResId);
+*
+* Description: Provides access to a resource inside the .MPC file
+*
+* Input: uint32 dwResId ID della risorsa
+*
+* Return: Handle to a memory area containing the resource,
+* ready for use.
+*
+\****************************************************************************/
+
+#define mpalQueryResource(dwResId) \
+ (HGLOBAL)mpalQuery(MPQ_RESOURCE,(uint32)(dwResId))
+
+
+
+/****************************************************************************\
+*
+* Function: LPSTR mpalQueryMessage(uint32 nMsg);
+*
+* Description: Returns a message.
+*
+* Input: uint32 nMsg Message number
+*
+* Return: ASCIIZ message
+*
+* Note: The returned pointer must be freed with GlobalFree()
+* after use. The message will be in ASCIIZ format.
+*
+\****************************************************************************/
+
+#define mpalQueryMessage(nMsg) \
+ (LPSTR)mpalQuery(MPQ_MESSAGE,(uint32)(nMsg))
+
+
+
+/****************************************************************************\
+*
+* Function: HGLOBAL mpalQueryLocationImage(uint32 nLoc);
+*
+* Description: Provides a image image
+*
+* Input: uint32 nLoc Locazion number
+*
+* Return: Returns a picture handle
+*
+\****************************************************************************/
+
+#define mpalQueryLocationImage(nLoc) \
+ (HGLOBAL)mpalQuery(MPQ_LOCATION_IMAGE,(uint32)(nLoc))
+
+
+
+/****************************************************************************\
+*
+* Function: uint32 mpalQueryLocationSize(uint32 nLoc, uint32 dwCoord);
+*
+* Description: Request the x or y size of a location in pixels
+*
+* Input: uint32 nLoc Location number
+* uint32 dwCoord MPQ_Xr o MPQ_Y
+*
+* Return: Size
+*
+\****************************************************************************/
+
+#define mpalQueryLocationSize(nLoc,dwCoord) \
+ (uint32)mpalQuery(MPQ_LOCATION_SIZE,(uint32)(nLoc),(uint32)(dwCoord))
+
+
+
+/****************************************************************************\
+*
+* Function: uint32 * mpalQueryItemList(uint32 nLoc);
+*
+* Description: Provides the list of objects in the lease.
+*
+* Input: uint32 nLoc Location number
+*
+* Return: List of objects (accessible by Item [0], Item [1], etc.)
+*
+\****************************************************************************/
+
+#define mpalQueryItemList(nLoc) \
+ (uint32 *)mpalQuery(MPQ_ITEM_LIST,(uint32)(nLoc))
+
+
+
+/****************************************************************************\
+*
+* Function: LPBKGANIM mpalQueryItemData(uint32 nItem);
+*
+* Description: Provides information on an item
+*e
+* Input: uint32 nItem Item number
+*
+* Return: structure filled with requested information
+*
+\****************************************************************************/
+
+#define mpalQueryItemData(nItem) \
+ (LPITEM)mpalQuery(MPQ_ITEM_DATA,(uint32)(nItem))
+
+
+
+/****************************************************************************\
+*
+* Function: uint32 mpalQueryItemPattern(uint32 nItem);
+*
+* Description: Provides the current pattern of an item
+*
+* Input: uint32 nItem Item number
+*
+* Return: Number of animation patterns to be executed.
+*
+* Note: By default, the pattern of 0 indicates that we should
+* do nothing.
+*
+\****************************************************************************/
+
+#define mpalQueryItemPattern(nItem) \
+ (uint32)mpalQuery(MPQ_ITEM_PATTERN,(uint32)(nItem))
+
+
+
+/****************************************************************************\
+*
+* Function: bool mpalQueryItemIsActive(uint32 nItem);
+*
+* Description: Returns true if an item is active
+*
+* Input: uint32 nItem Item number
+*
+* Return: TRUE if the item is active, FALSE otherwise
+*
+\****************************************************************************/
+
+#define mpalQueryItemIsActive(nItem) \
+ (bool)mpalQuery(MPQ_ITEM_IS_ACTIVE,(uint32)(nItem))
+
+
+/****************************************************************************\
+*
+* Function: void mpalQueryItemName(uint32 nItem, LPSTR lpszName);
+*
+* Description: Returns the name of an item
+*
+* Input: uint32 nItem Item number
+* LPSTR lpszName Pointer to a buffer of at least 33 bytes
+* that will be filled with the name
+*
+* Note: If the item is not active (ie. if its status or number
+* is less than or equal to 0), the string will be empty.
+*
+\****************************************************************************/
+
+#define mpalQueryItemName(nItem,lpszName) \
+ (uint32)mpalQuery(MPQ_ITEM_NAME,(uint32)(nItem),(LPSTR)(lpszName))
+
+
+
+/****************************************************************************\
+*
+* Function: LPSTR mpalQueryDialogPeriod(uint32 nDialog, uint32 nPeriod);
+*
+* Description: Returns a sentence of dialog.
+*
+* Input: uint32 nDialog Dialog number
+* uint32 nPeriod Number of words
+*
+* Return: A pointer to the string of words, or NULL on failure.
+*
+* Note: The string must be freed after use by GlobalFree ().
+*
+* Unlike normal messages, the sentences of dialogue
+* are formed by a single string terminated with 0.
+*
+\****************************************************************************/
+
+#define mpalQueryDialogPeriod(nPeriod) \
+ (LPSTR)mpalQuery(MPQ_DIALOG_PERIOD,(uint32)(nPeriod))
+
+
+
+/****************************************************************************\
+*
+* Function: int mpalQueryDialogWaitForChoice(void);
+*
+* Description: Wait until the moment in which the need is signaled
+* to make a choice by the user.
+*
+* Return: Number of choice to be made, or -1 if the dialogue is finished.
+*
+\****************************************************************************/
+
+#define mpalQueryDialogWaitForChoice() \
+ (int)mpalQuery(MPQ_DIALOG_WAITFORCHOICE)
+
+
+
+/****************************************************************************\
+*
+* Function: uint32 * mpalQueryDialogSelectList(uint32 nChoice);
+*
+* Description: Requires a list of various options for some choice within
+* the current dialog.
+
+* Input: uint32 nChoice Choice number
+*
+* Return: A pointer to an array containing the data matched to each option.
+*
+* Note: The figure 'a uint32 specified in the source to which MPAL
+* You can 'assign meaning that the more' suits.
+*
+* The pointer msut be freed after use by GlobalFree().
+*
+\****************************************************************************/
+
+#define mpalQueryDialogSelectList(nChoice) \
+ (uint32 *)mpalQuery(MPQ_DIALOG_SELECTLIST,(uint32)(nChoice))
+
+
+
+/****************************************************************************\
+*
+* Function: bool mpalQueryDialogSelection(uint32 nChoice, uint32 dwData);
+*
+* Description: Warns the library that the user has selected, in a certain
+* choice of the current dialog, corresponding option
+* at a certain given.
+*
+* Input: uint32 nChoice Choice number of the choice that
+* was in progress
+* uint32 dwData Option that was selected by the user.
+*
+* Return: TRUE if all OK, FALSE on failure.
+*
+* Note: After execution of this query, MPAL continue
+* Groups according to the execution of the dialogue. And necessary so the game
+* remains on hold again for another Chosen by mpalQueryDialogWaitForChoice ().
+*
+\****************************************************************************/
+
+#define mpalQueryDialogSelection(nChoice,dwData) \
+ (bool)mpalQuery(MPQ_DIALOG_SELECTION,(uint32)(nChoice),(uint32)(dwData))
+
+
+
+/****************************************************************************\
+*
+* Function: HANDLE mpalQueryDoAction(uint32 nAction, uint32 nItem,
+* uint32 dwParam);
+*
+* Description: Warns the library an action was performed on a Object.
+* The library will call 'custom functions, if necessary.
+*
+* Input: uint32 nAction Action number
+* uint32 nItem Item number
+* uint32 dwParam Action parameter
+*
+* Return: Handle to the thread that is performing the action, or
+* INVALID_HANDLE_VALUE if the action is not 'defined for
+* the item, or the item and 'off.
+*
+* Note: The parameter is used primarily to implement actions
+* as "U.S." involving two objects together. The action will be executed only
+* if the item is active, ie if its status is a positive number greater than 0.
+*
+\****************************************************************************/
+
+#define mpalQueryDoAction(nAction,nItem,dwParam) \
+ (HANDLE)mpalQuery(MPQ_DO_ACTION,(uint32)(nAction),(uint32)(nItem),(uint32)(dwParam))
+
+
+
+/****************************************************************************\
+*
+* Function: HANDLE mpalQueryDoDialog(uint32 nDialog, uint32 nGroup);
+*
+* Description: Warns the library a dialogue was required.
+*
+* Input: uint32 nDialog Dialog number
+* uint32 nGroup Group number to use
+*
+* Return: Handle to the thread that is running the box, or
+* INVALID_HANDLE_VALUE if the dialogue does not exist.
+*
+\****************************************************************************/
+
+#define mpalQueryDoDialog(nDialog,nGroup) \
+ (HANDLE)mpalQuery(MPQ_DO_DIALOG,(uint32)(nDialog),(uint32)(nGroup))
+
+
+
+/****************************************************************************\
+* Functions exported DLL
+\****************************************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/****************************************************************************\
+*
+* Function: bool mpalInit(LPSTR lpszMpcFileName, LPSTR lpszMprFileName,
+* LPLPCUSTOMFUNCTION lplpcfArray);
+*
+* Description: Initializes the MPAL library, and opens an .MPC file, which
+* will be 'used for all queries
+*
+* Input: LPSTR lpszMpcFileName Name of the .MPC file, including extension
+* LPSTR lpszMprFileName Name of the .MPR file, including extension
+* LPLPCUSTOMFUNCTION Array of pointers to custom functions
+*
+* Return: TRUE if all OK, FALSE on failure
+*
+\****************************************************************************/
+
+bool EXPORT mpalInit(LPSTR lpszFileName, LPSTR lpszMprFileName,
+ LPLPCUSTOMFUNCTION lplpcfArray);
+
+
+
+/****************************************************************************\
+*
+* Function: uint32 mpalQuery(uint16 wQueryType, ...);
+*
+* Description: This is the general function to communicate with the library,
+* To request information about what is in the .MPC file
+*
+* Input: uint16 wQueryType Type of query. The list is in
+* the QueryTypes enum.
+*
+* Return: 4 bytes depending on the type of query
+*
+* Note: I _strongly_ recommended to use macros defined above to use
+* the query, since it helps avoid any unpleasant bugs due to
+* forgeting parameters.
+*
+\****************************************************************************/
+
+uint32 EXPORT mpalQuery(uint16 wQueryType, ...);
+
+
+
+/****************************************************************************\
+*
+* Function: bool mpalExecuteScript(int nScript);
+*
+* Description: Execute a script. The script runs on multitasking by a thread.
+*
+* Input: int nScript Script number to run
+*
+* Return: TRUE if the script 'was launched, FALSE on failure
+*
+\****************************************************************************/
+
+bool EXPORT mpalExecuteScript(int nScript);
+
+
+
+/****************************************************************************\
+*
+* Function: uint32 mpalGetError(void);
+*
+* Description: Returns the current MPAL error code
+*
+* Return: Error code
+*
+\****************************************************************************/
+
+uint32 EXPORT mpalGetError(void);
+
+
+
+/****************************************************************************\
+*
+* Function: void mpalInstallItemIrq(LPITEMIRQFUNCTION lpiifCustom);
+*
+* Description: Install a custom routine That will be called by MPAL
+* every time the pattern of an item has-been changed.
+*
+* Input: LPITEMIRQFUNCTION lpiifCustom Custom function to install
+*
+\****************************************************************************/
+
+void EXPORT mpalInstallItemIrq(LPITEMIRQFUNCTION lpiifCustom);
+
+
+/****************************************************************************\
+*
+* Function: bool mpalStartIdlePoll(int nLoc);
+*
+* Description: Process the idle actions of the items on one location.
+*
+* Input: int nLoc Number of the location whose items
+* must be processed for idle actions.
+*
+* Return: TRUE if all OK, and FALSE if it exceeded the maximum limit.
+*
+* Note: The maximum number of locations that can be polled
+* simultaneously is defined defined by MAXPOLLINGFUNCIONS
+*
+\****************************************************************************/
+
+bool EXPORT mpalStartIdlePoll(int nLoc);
+
+
+/****************************************************************************\
+*
+* Function: bool mpalEndIdlePoll(int nLoc);
+*
+* Description: Stop processing the idle actions of the items on one location.
+*
+* Input: int nLoc Number of the location
+*
+* Return: TRUE if all OK, FALSE if the specified location was not
+* in the process of polling
+*
+\****************************************************************************/
+
+bool EXPORT mpalEndIdlePoll(int nLoc);
+
+
+
+/****************************************************************************\
+*
+* Function: int mpalLoadState(LPBYTE buf);
+*
+* Description: Load a save state from a buffer.
+*
+* Input: LPBYTE buf Buffer where to store the state
+*
+* Return: Length of the state in bytes
+*
+\****************************************************************************/
+
+int EXPORT mpalLoadState(byte *buf);
+
+
+
+/****************************************************************************\
+*
+* Function: void mpalSaveState(LPBYTE buf);
+*
+* Description: Store the save state into a buffer. The buffer must be
+* length at least the size specified with mpalGetSaveStateSize
+*
+* Input: LPBYTE buf Buffer where to store the state
+*
+\****************************************************************************/
+
+void EXPORT mpalSaveState(byte *buf);
+
+
+
+/****************************************************************************\
+*
+* Function: int mpalGetSaveStateSize(void);
+*
+* Description: Acquire the length of a save state
+*
+* Return: Length in bytes
+*
+\****************************************************************************/
+
+int EXPORT mpalGetSaveStateSize(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+/****************************************************************************\
+*
+* Function: void LockVar(void);
+*
+* Description: Locka le variabili per accederci
+*
+\****************************************************************************/
+
+extern void LockVar(void);
+
+/****************************************************************************\
+*
+* Function: void UnlockVar(void);
+*
+* Description: Unlocka le variabili dopo l'uso
+*
+\****************************************************************************/
+
+extern void UnlockVar(void);
+
+#endif
+
diff --git a/engines/tony/mpal/mpaldll.h b/engines/tony/mpal/mpaldll.h
new file mode 100644
index 0000000000..8a52f1ed90
--- /dev/null
+++ b/engines/tony/mpal/mpaldll.h
@@ -0,0 +1,418 @@
+/* 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.
+ *
+ *
+ */
+/**************************************************************************
+ * ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ *
+ * ... Spyral Software snc *
+ * . x#""*$Nu -= We create much MORE than ALL =- *
+ * d*#R$. R ^#$o ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ *
+ * .F ^$k $ "$b *
+ * ." $b u "$ #$L *
+ * P $c :*$L"$L '$k Project: MPAL................... *
+ * d @$N. $. d ^$b^$k $c *
+ * F 4 "$c '$ $ #$u#$u '$ Module: MPAL DLL Header........ *
+ * 4 4k *N #b .> '$N'*$u * *
+ * M $L #$ $ 8 "$c'#$b.. .@ Author: Giovanni Bajo.......... *
+ * M '$u "$u :" *$. "#*#" *
+ * M '$N. " F ^$k Desc: Header per i moduli per *
+ * 4> ^R$oue# d la DLL di query di MPAL *
+ * '$ "" @ ....................... *
+ * #b u# *
+ * $b .@" OS: [ ] DOS [X] WIN95 [ ] OS/2 *
+ * #$u .d" *
+ * '*$e. .zR".@ ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ *
+ * "*$$beooee$*" @"M This source code is *
+ * """ '$.? Copyright (C) Spyral Software *
+ * '$d> ALL RIGHTS RESERVED *
+ * '$> ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ *
+ * *
+ **************************************************************************/
+
+#ifndef __MPALDLL_H
+#define __MPALDLL_H
+
+#include "common/file.h"
+#include "stubs.h"
+
+namespace Tony {
+
+namespace MPAL {
+
+/****************************************************************************\
+* Defines
+\****************************************************************************/
+
+#define HEX_VERSION 0x0170
+
+/*
+ SICURA
+
+#define MAX_ACTIONS_PER_ITEM 40
+#define MAX_COMMANDS_PER_ITEM 256
+#define MAX_COMMANDS_PER_ACTION 64
+#define MAX_DESCRIBE_SIZE 128
+*/
+
+#define MAX_ACTIONS_PER_ITEM 40
+#define MAX_COMMANDS_PER_ITEM 128
+#define MAX_COMMANDS_PER_ACTION 128
+#define MAX_DESCRIBE_SIZE 64
+
+
+
+#define MAX_MOMENTS_PER_SCRIPT 256
+#define MAX_COMMANDS_PER_SCRIPT 256
+#define MAX_COMMANDS_PER_MOMENT 32
+
+
+
+
+
+/*
+ Versione sicura!
+
+#define MAX_GROUPS_PER_DIALOG 128
+#define MAX_COMMANDS_PER_DIALOG 640
+#define MAX_COMMANDS_PER_GROUP 64
+#define MAX_CHOICES_PER_DIALOG 64
+#define MAX_SELECTS_PER_CHOICE 33
+#define MAX_PLAYGROUPS_PER_SELECT 9
+#define MAX_PERIODS_PER_DIALOG 640
+
+*/
+
+#define MAX_GROUPS_PER_DIALOG 128
+#define MAX_COMMANDS_PER_DIALOG 480
+#define MAX_COMMANDS_PER_GROUP 64
+#define MAX_CHOICES_PER_DIALOG 64
+#define MAX_SELECTS_PER_CHOICE 64
+#define MAX_PLAYGROUPS_PER_SELECT 9
+#define MAX_PERIODS_PER_DIALOG 400
+
+/*
+ Prima di Rufus:
+
+#define MAX_GROUPS_PER_DIALOG 128
+#define MAX_COMMANDS_PER_DIALOG 512
+#define MAX_COMMANDS_PER_GROUP 32
+#define MAX_CHOICES_PER_DIALOG 64
+#define MAX_SELECTS_PER_CHOICE 32
+#define MAX_PLAYGROUPS_PER_SELECT 4
+#define MAX_PERIODS_PER_DIALOG 512
+*/
+
+#define NEED_LOCK_MSGS
+
+
+/****************************************************************************\
+* Strutture
+\****************************************************************************/
+
+#include "common/pack-start.h"
+
+/****************************************************************************\
+* typedef MPALVAR
+* ---------------
+* Description: Variabile globale di MPAL
+\****************************************************************************/
+
+struct MPALVAR {
+ uint32 dwVal; // Valore della variabile
+ char lpszVarName[33]; // Nome della variabile
+} PACKED_STRUCT;
+typedef MPALVAR* LPMPALVAR;
+typedef LPMPALVAR* LPLPMPALVAR;
+
+
+/****************************************************************************\
+* typedef MPALMSG
+* ---------------
+* Description: Messaggio di MPAL
+\****************************************************************************/
+
+struct MPALMSG {
+ HGLOBAL hText; // Handle al testo del messaggio
+ uint16 wNum; // Numero del messaggio
+} PACKED_STRUCT;
+typedef MPALMSG* LPMPALMSG;
+typedef LPMPALMSG* LPLPMPALMSG;
+
+
+/****************************************************************************\
+* typedef MPALLOCATION
+* --------------------
+* Description: Locazione di MPAL
+\****************************************************************************/
+
+struct MPALLOCATION {
+ uint32 nObj; // Numero della locazione
+ uint32 dwXlen, dwYlen; // Dimensione
+ uint32 dwPicRes; // Risorsa che contiene l'immagine
+} PACKED_STRUCT;
+typedef MPALLOCATION* LPMPALLOCATION;
+typedef LPMPALLOCATION* LPLPMPALLOCATION;
+
+
+/****************************************************************************\
+* struct command
+* --------------
+* Description: Gestisce un comando, cioe' le tag utilizzate dalle OnAction
+* negli item, dalle Time negli script e dai Group nei Dialog
+\****************************************************************************/
+
+struct command {
+ /*
+ * Tipi di comandi riconosciuti:
+ *
+ * #1 -> Chiamata a funzione custom (ITEM, SCRIPT, DIALOG)
+ * #2 -> Assegnazione di variabile (ITEM, SCRIPT, DIALOG)
+ * #3 -> Esecuzione di una scelta (DIALOG)
+ *
+ */
+ byte type; // Tipo di comando
+
+ union {
+ int32 nCf; // Numero funzione custom [#1]
+ char *lpszVarName; // Nome variabile [#2]
+ int32 nChoice; // Numero di scelta da fare [#3]
+ };
+
+ union {
+ int32 arg1; // Argomento 1 funzione custom [#1]
+ HGLOBAL expr; // Espressione da assegnare alla
+ // variabile [#2]
+ };
+
+ int32 arg2,arg3,arg4; // Argomenti per funzione custom [#1]
+} PACKED_STRUCT;
+
+/****************************************************************************\
+* typedef MPALDIALOG
+* ------------------
+* Description: Dialog di MPAL
+\****************************************************************************/
+
+struct MPALDIALOG {
+ uint32 nObj; // Numero dialog
+
+ struct command Command[MAX_COMMANDS_PER_DIALOG];
+
+ struct {
+ uint16 num;
+
+ byte nCmds;
+ uint16 CmdNum[MAX_COMMANDS_PER_GROUP];
+
+ } Group[MAX_GROUPS_PER_DIALOG];
+
+ struct {
+ // L'ultima choice ha nChoice==0
+ uint16 nChoice;
+
+ // Non c'e' il numero di Select (siamo abbastanza avari di RAM). L'ultimo
+ // select ha dwData==0
+ struct {
+ HGLOBAL when;
+ uint32 dwData;
+ uint16 wPlayGroup[MAX_PLAYGROUPS_PER_SELECT];
+
+ // Bit 0=endchoice Bit 1=enddialog
+ byte attr;
+
+ // Modificata a run-time: 0 se il select e' correntemente disabilitato,
+ // 1 se e' correntemente attivato
+ byte curActive;
+ } Select[MAX_SELECTS_PER_CHOICE];
+
+ } Choice[MAX_CHOICES_PER_DIALOG];
+
+ uint16 PeriodNums[MAX_PERIODS_PER_DIALOG];
+ HGLOBAL Periods[MAX_PERIODS_PER_DIALOG];
+
+} PACKED_STRUCT;
+typedef MPALDIALOG* LPMPALDIALOG;
+typedef LPMPALDIALOG* LPLPMPALDIALOG;
+
+/****************************************************************************\
+* typedef MPALITEM
+* ----------------
+* Description: Item di MPAL
+\****************************************************************************/
+
+struct ItemAction {
+ byte num; // Numero dell'azione
+ uint16 wTime; // In caso di idle, il tempo che deve passare
+ byte perc; // Percentuale di eseguire l'idle
+ HGLOBAL when; // Espressione da calcolare: se !=0, allora
+ // l'azione puo' essere eseguita
+ uint16 wParm; // Parametro per l'azione
+
+ byte nCmds; // Numero comandi da eseguire
+ uint32 CmdNum[MAX_COMMANDS_PER_ACTION]; // Comando da eseguire
+} PACKED_STRUCT;
+
+struct MPALITEM {
+ uint32 nObj; // Numero item
+
+ byte lpszDescribe[MAX_DESCRIBE_SIZE]; // Nome
+ byte nActions; // Numero delle azioni gestite
+ uint32 dwRes; // Risorsa che contiene frame e pattern
+
+ struct command Command[MAX_COMMANDS_PER_ITEM];
+
+ // Array di strutture contenenti le varie azioni gestite. In pratica, di
+ // ogni azione sappiamo quali comandi eseguire, tra quelli definiti nella
+ // struttura qui sopra
+/*
+ struct
+ {
+ byte num; // Numero dell'azione
+ uint16 wTime; // In caso di idle, il tempo che deve passare
+ byte perc; // Percentuale di eseguire l'idle
+ HGLOBAL when; // Espressione da calcolare: se !=0, allora
+ // l'azione puo' essere eseguita
+ uint16 wParm; // Parametro per l'azione
+
+ byte nCmds; // Numero comandi da eseguire
+ uint32 CmdNum[MAX_COMMANDS_PER_ACTION]; // Comando da eseguire
+
+ } Action[MAX_ACTIONS_PER_ITEM];
+ */
+ struct ItemAction *Action;
+
+} PACKED_STRUCT;
+typedef MPALITEM* LPMPALITEM;
+typedef LPMPALITEM* LPLPMPALITEM;
+
+
+/****************************************************************************\
+* typedef MPALSCRIPT
+* ------------------
+* Description: Script di MPAL
+\****************************************************************************/
+
+struct MPALSCRIPT {
+ uint32 nObj;
+
+ uint32 nMoments;
+
+ struct command Command[MAX_COMMANDS_PER_SCRIPT];
+
+ struct {
+ int32 dwTime;
+
+ byte nCmds;
+ uint32 CmdNum[MAX_COMMANDS_PER_MOMENT];
+
+ } Moment[MAX_MOMENTS_PER_SCRIPT];
+
+} PACKED_STRUCT;
+typedef MPALSCRIPT* LPMPALSCRIPT;
+typedef LPMPALSCRIPT* LPLPMPALSCRIPT;
+
+#include "common/pack-end.h"
+
+/****************************************************************************\
+* Variabili globali
+\****************************************************************************/
+
+extern uint32 mpalError;
+extern LPLPCUSTOMFUNCTION lplpFunctions;
+extern uint16 nObjs;
+
+extern uint16 nVars;
+extern HGLOBAL hVars;
+extern LPMPALVAR lpmvVars;
+
+extern uint16 nMsgs;
+extern HGLOBAL hMsgs;
+extern LPMPALMSG lpmmMsgs;
+
+extern uint16 nDialogs;
+extern HGLOBAL hDialogs;
+extern LPMPALDIALOG lpmdDialogs;
+
+extern uint16 nItems;
+extern HGLOBAL hItems;
+extern LPMPALITEM lpmiItems;
+
+extern uint16 nLocations;
+extern HGLOBAL hLocations;
+extern LPMPALLOCATION lpmlLocations;
+
+extern uint16 nScripts;
+extern HGLOBAL hScripts;
+extern LPMPALSCRIPT lpmsScripts;
+
+extern Common::File hMpr;
+extern uint16 nResources;
+extern uint32 * lpResources;
+
+/****************************************************************************\
+* Prototipi di funzione
+\****************************************************************************/
+
+/****************************************************************************\
+*
+* Function: int32 varGetValue(const char *lpszVarName);
+*
+* Description: Restituisce il valore corrente di una variabile globale
+*
+* Input: const char *lpszVarName Nome della variabile
+*
+* Return: Valore corrente
+*
+* Note: Prima di questa funzione, bisogna richiamare LockVar() che
+* locka le variabili globali per l'utilizzo. Dopo inoltre bi-
+* sogna ricordarsi di chiamare UnlockVar()
+*
+\****************************************************************************/
+
+int32 varGetValue(const char *lpszVarName);
+
+
+/****************************************************************************\
+*
+* Function: void varSetValue(const char *lpszVarName, int32 val);
+*
+* Description: Setta un nuovo valore per una variabile globale di MPAL
+*
+* Input: const char *lpszVarName Nome della variabile
+* int32 val Valore da settare
+*
+\****************************************************************************/
+
+void varSetValue(const char *lpszVarName, int32 val);
+
+/****************************************************************************\
+* Includes the various modules
+\****************************************************************************/
+
+} // end of namespace MPAL
+
+} // end of namespace Tony
+
+#include "loadmpc.h"
+#include "expr.h"
+
+#endif
+
diff --git a/engines/tony/mpal/stubs.cpp b/engines/tony/mpal/stubs.cpp
new file mode 100644
index 0000000000..342678b856
--- /dev/null
+++ b/engines/tony/mpal/stubs.cpp
@@ -0,0 +1,140 @@
+e/* 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.
+ *
+ *
+ */
+
+#ifndef TONY_MPAL_STUBS
+#define TONY_MPAL_STUBS
+
+/****************************************************************************\
+* This file contains stubs and mappings for things used by the MPAL
+* library that are handled differently under ScummVM
+\****************************************************************************/
+
+#include "common/algorithm.h"
+#include "common/system.h"
+#include "engines/engine.h"
+#include "tony/tony.h"
+#include "stubs.h"
+
+namespace Tony {
+
+namespace MPAL {
+
+/**
+ * Allocates a memory block
+ */
+byte *GlobalAlloc(uint16 flags, int size) {
+ byte *result = (byte *)malloc(size);
+
+ if (flags & GMEM_ZEROINIT)
+ Common::fill(result, result + size, 0);
+
+ return result;
+}
+
+/**
+ * Lock a global handle
+ * @param h Global handle
+ * @remarks Since HGLOBALs are directly representing the pointers anyway,
+ * simply return it
+ */
+void *GlobalLock(HGLOBAL h) {
+ return h;
+}
+
+/**
+ * Unlock a global handle
+ * @param h Global handle
+ * @remarks Since HGLOBALs are directly representing the pointers anyway,
+ * the unlock method doesn't need to do anything
+ */
+void GlobalUnlock(HGLOBAL h) {
+}
+
+/**
+ * Free a globally allocated memory block
+ * @param h Global handle
+ */
+void GlobalFree(HGLOBAL h) {
+ free(h);
+}
+
+/**
+ * Display a message
+ * @param msg Message to display
+ */
+void MessageBox(const Common::String &msg) {
+
+ _vm->GUIError(msg);
+}
+
+/**
+ * Gets the current time in milliseconds
+ */
+uint32 timeGetTime() {
+ return g_system->getMillis();
+}
+
+HANDLE CreateThread(void *lpThreadAttributes, size_t dwStackSize,
+ LPTHREAD_START_ROUTINE lpStartAddress, void *lpParameter,
+ uint32 dwCreationFlags, uint32 *lpThreadId) {
+ *lpThreadId = 0;
+ return 0;
+}
+
+void ExitThread(HANDLE ThreadId) {
+}
+
+void TerminateThread(HANDLE ThreadId, uint32 dwExitCode) {
+
+}
+
+void CloseHandle(HANDLE ThreadId) {
+
+}
+
+void Sleep(uint32 time) {
+}
+
+int WaitForSingleObject(HANDLE ThreadId, uint32 dwSleepTime) {
+ return 0;
+}
+
+uint32 WaitForMultipleObjects(uint32 nCount, const HANDLE *lpHandles, bool bWaitAll, uint32 dwMilliseconds) {
+ return 0;
+}
+
+HANDLE CreateEvent(void *lpEventAttributes, bool bManualReset, bool bInitialState, const char *lpName) {
+ return 0;
+}
+
+void SetEvent(HANDLE hEvent) {
+}
+
+void ResetEvent(HANDLE hEvent) {
+}
+
+} // end of namespace MPAL
+
+} // end of namespace Tony
+
+#endif
diff --git a/engines/tony/mpal/stubs.h b/engines/tony/mpal/stubs.h
new file mode 100644
index 0000000000..d66e12d00d
--- /dev/null
+++ b/engines/tony/mpal/stubs.h
@@ -0,0 +1,121 @@
+/* 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.
+ *
+ *
+ */
+
+/****************************************************************************\
+* This file contains stubs and mappings for things used by the MPAL
+* library that are handled differently under ScummVM
+\****************************************************************************/
+
+#ifndef MPAL_STUBS
+#define MPAL_STUBS
+
+#include "common/scummsys.h"
+#include "common/algorithm.h"
+
+namespace Tony {
+
+namespace MPAL {
+
+/****************************************************************************\
+* Types
+\****************************************************************************/
+
+typedef void *HGLOBAL;
+typedef void *HANDLE;
+
+typedef uint32 (__stdcall *LPTHREAD_START_ROUTINE)(void *lpThreadParameter);
+
+/****************************************************************************\
+* Defines
+\****************************************************************************/
+
+#define GMEM_FIXED 1
+#define GMEM_MOVEABLE 2
+#define GMEM_ZEROINIT 4
+
+#define MB_OK 1
+
+#define PASCAL
+
+/****************************************************************************\
+* Templates
+\****************************************************************************/
+
+/**
+ * Copies data from the range [first, last) to [dst, dst + (last - first)).
+ * It requires the range [dst, dst + (last - first)) to be valid.
+ * It also requires dst not to be in the range [first, last).
+ */
+template<class In, class Out>
+Out CopyMemory(Out dst, In first, int size) {
+ return Common::copy(first, first + size, dst);
+}
+
+/****************************************************************************\
+* Methods
+\****************************************************************************/
+
+extern byte *GlobalAlloc(uint16 flags, int size);
+
+extern void *GlobalLock(HGLOBAL h);
+
+extern void GlobalUnlock(HGLOBAL h);
+
+extern void GlobalFree(HGLOBAL h);
+
+extern void MessageBox(const Common::String &msg);
+
+extern uint32 timeGetTime();
+
+#define INFINITE 0xffffffff
+#define WAIT_OBJECT_0 -2
+// Horrendously bad cast
+#define INVALID_HANDLE_VALUE (void *)-3
+
+extern HANDLE CreateThread(void *lpThreadAttributes, size_t dwStackSize,
+ LPTHREAD_START_ROUTINE lpStartAddress, void *lpParameter,
+ uint32 dwCreationFlags, uint32 *lpThreadId);
+
+extern void ExitThread(int ThreadId);
+
+extern void TerminateThread(HANDLE ThreadId, uint32 dwExitCode);
+
+extern void CloseHandle(HANDLE ThreadId);
+
+extern void Sleep(uint32 time);
+
+extern int WaitForSingleObject(HANDLE ThreadId, uint32 dwSleepTime);
+
+extern uint32 WaitForMultipleObjects(uint32 nCount, const HANDLE *lpHandles, bool bWaitAll, uint32 dwMilliseconds);
+
+extern HANDLE CreateEvent(void *lpEventAttributes, bool bManualReset, bool bInitialState, const char *lpName);
+
+extern void SetEvent(HANDLE hEvent);
+
+extern void ResetEvent(HANDLE hEvent);
+
+} // end of namespace MPAL
+
+} // end of namespace Tony
+
+#endif
diff --git a/engines/tony/tony.cpp b/engines/tony/tony.cpp
index 523147c848..2d4385a5e6 100644
--- a/engines/tony/tony.cpp
+++ b/engines/tony/tony.cpp
@@ -20,20 +20,63 @@
*
*/
+#include "common/scummsys.h"
+#include "common/algorithm.h"
+#include "common/file.h"
#include "tony/tony.h"
+#include "tony/mpal/mpal.h"
namespace Tony {
TonyEngine *_vm;
-TonyEngine::TonyEngine(OSystem *syst, const TonyGameDescription *gameDesc) : Engine(syst), _gameDescription(gameDesc) {
+TonyEngine::TonyEngine(OSystem *syst, const TonyGameDescription *gameDesc) : Engine(syst),
+ _gameDescription(gameDesc), _randomSource("tony") {
+ _vm = this;
}
TonyEngine::~TonyEngine() {
}
+/**
+ * Run the game
+ */
Common::Error TonyEngine::run() {
+ Common::ErrorCode result = Init();
+ if (result != Common::kNoError)
+ return result;
+
+ /*
+ Play();
+ Close();
+*/
+ return Common::kNoError;
+}
+
+/**
+ * Initialise the game
+ */
+Common::ErrorCode TonyEngine::Init() {
+ // Initialise the function list
+ Common::fill(FuncList, FuncList + sizeof(FuncList), (LPCUSTOMFUNCTION)NULL);
+
+ // Initializes MPAL system, passing the custom functions list
+ Common::File f;
+ if (!f.open("ROASTED.MPC"))
+ return Common::kReadingFailed;
+ f.close();
+
+ if (!mpalInit("ROASTED.MPC", "ROASTED.MPR", FuncList))
+ return Common::kUnknownError;
+
return Common::kNoError;
}
+/**
+ * Display an error message
+ */
+void TonyEngine::GUIError(const Common::String &msg) {
+ GUIErrorMessage(msg);
+}
+
} // End of namespace Tony
diff --git a/engines/tony/tony.h b/engines/tony/tony.h
index 5aa0de95a3..cfb6748716 100644
--- a/engines/tony/tony.h
+++ b/engines/tony/tony.h
@@ -26,11 +26,12 @@
#include "common/scummsys.h"
#include "common/system.h"
#include "common/error.h"
-#include "common/events.h"
-#include "common/keyboard.h"
+#include "common/random.h"
#include "common/util.h"
#include "engines/engine.h"
+#include "tony/mpal.h"
+
/**
* This is the namespace of the Tony engine.
*
@@ -41,6 +42,8 @@
*/
namespace Tony {
+using namespace MPAL;
+
enum {
kTonyDebugAnimations = 1 << 0,
kTonyDebugActions = 1 << 1,
@@ -55,11 +58,16 @@ enum {
struct TonyGameDescription;
class TonyEngine : public Engine {
+private:
+ Common::ErrorCode Init();
protected:
// Engine APIs
virtual Common::Error run();
virtual bool hasFeature(EngineFeature f) const;
public:
+ LPCUSTOMFUNCTION FuncList[300];
+ Common::RandomSource _randomSource;
+public:
TonyEngine(OSystem *syst, const TonyGameDescription *gameDesc);
virtual ~TonyEngine();
@@ -70,6 +78,8 @@ public:
uint16 getVersion() const;
uint32 getFlags() const;
Common::Platform getPlatform() const;
+
+ void GUIError(const Common::String &msg);
};
// Global reference to the TonyEngine object