diff options
-rw-r--r-- | engines/tony/lzo/lzo1x.h | 198 | ||||
-rw-r--r-- | engines/tony/lzo/lzoconf.h | 398 | ||||
-rw-r--r-- | engines/tony/module.mk | 6 | ||||
-rw-r--r-- | engines/tony/mpal.h | 23 | ||||
-rw-r--r-- | engines/tony/mpal/expr.cpp | 471 | ||||
-rw-r--r-- | engines/tony/mpal/expr.h | 116 | ||||
-rw-r--r-- | engines/tony/mpal/loadmpc.cpp | 720 | ||||
-rw-r--r-- | engines/tony/mpal/loadmpc.h | 83 | ||||
-rw-r--r-- | engines/tony/mpal/lzo1x.h | 188 | ||||
-rw-r--r-- | engines/tony/mpal/mpal.cpp | 3071 | ||||
-rw-r--r-- | engines/tony/mpal/mpal.h | 769 | ||||
-rw-r--r-- | engines/tony/mpal/mpaldll.h | 418 | ||||
-rw-r--r-- | engines/tony/mpal/stubs.cpp | 140 | ||||
-rw-r--r-- | engines/tony/mpal/stubs.h | 121 | ||||
-rw-r--r-- | engines/tony/tony.cpp | 45 | ||||
-rw-r--r-- | engines/tony/tony.h | 14 |
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 |