diff options
126 files changed, 3047 insertions, 1404 deletions
| diff --git a/.gitignore b/.gitignore index 3e80289a16..2ad104214e 100644 --- a/.gitignore +++ b/.gitignore @@ -166,6 +166,7 @@ ipch/  *.vcxproj*  *.bat  *.tss +*.VC.db  #Ignore default Visual Studio build folders  [Dd]ebug/ @@ -14,6 +14,7 @@ For a more comprehensive changelog of the latest experimental code, see:   General:     - Removed TESTING flag from several supported games.     - Added Chinese Pinyin translation. +   - Fixed cursor stuttering in the launcher that occured on some systems.   BBVS:     - Fixed game restart. @@ -27,10 +28,23 @@ For a more comprehensive changelog of the latest experimental code, see:     - Fixed loading savegames in the Pendulum scene.     - Fixed wrong background for inventory items during chapter 6 in the       Spanish version. +   - Fixed animations speed (they were running two times slower than in the +     original engine). +   - Fixed noise at start and/or end of speech. This was most noticeable +     with the Spanish speech. +   - Fixed delay when interacting with the verb menu and the inventory. +   - Fixed possibility to pick up the axe in the castle multiple times.   Gob:     - Fixed lock up for some games during sound initialization. + KYRA: +   - Fixed potential crash when using swamp snake potion on the rat in Hand +     of Fate. (NOTE: This fix was included in version 1.8.0, but it was not +     added to the NEWS file). +   - Fixed missing voice reactions when hitting enemies in CD version of +     Lands of Lore. +   Lab:     - Fixed lock-up during ending sequence.     - Improved internal game controls. @@ -70,6 +84,9 @@ For a more comprehensive changelog of the latest experimental code, see:       not running and allows starting those games.     - Enabled Sparkle application updater. + GCW0 port: +   - Improved support for built-in ScummVM documentation. +  1.8.0 (2016-03-04)   New Games:     - Added support for Rex Nebular and the Cosmic Gender Bender. @@ -1742,8 +1742,8 @@ The platforms that currently have a different default directory are:      $HOME/Documents/ScummVM Savegames/      Other unices: -    We follow the XDG Base Directory Specification. This means our -    configuration can be found in: +    We follow the XDG Base Directory Specification. This means by default +    saved games can be found in:      $XDG_DATA_HOME/scummvm/saves/      If XDG_DATA_HOME is not defined or empty, ~/.local/share will be used diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp index 685ee99e6f..d536429f4e 100644 --- a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp @@ -1043,12 +1043,12 @@ void TownsPC98_FmSynth::writeReg(uint8 part, uint8 regAddress, uint8 value) {  			if (value & 0x10) {  				_timers[0].smpTillCb = _timers[0].smpPerCb; -				_timers[0].smpTillCbRem = _timers[0].smpTillCbRem; +				_timers[0].smpTillCbRem = _timers[0].smpPerCbRem;  			}  			if (value & 0x20) {  				_timers[1].smpTillCb = _timers[1].smpPerCb; -				_timers[1].smpTillCbRem = _timers[1].smpTillCbRem; +				_timers[1].smpTillCbRem = _timers[1].smpPerCbRem;  			}  		} else if (l == 2) {  			// LFO diff --git a/backends/graphics/opengl/pipelines/shader.cpp b/backends/graphics/opengl/pipelines/shader.cpp index 8e38458f73..a2dabb7c22 100644 --- a/backends/graphics/opengl/pipelines/shader.cpp +++ b/backends/graphics/opengl/pipelines/shader.cpp @@ -56,6 +56,8 @@ void ShaderPipeline::activateInternal() {  	}  	_activeShader->activate(); + +	GL_CALL(glVertexAttribPointer(_colorAttribLocation, 4, GL_FLOAT, GL_FALSE, 0, _colorAttributes));  }  void ShaderPipeline::deactivateInternal() { @@ -74,8 +76,6 @@ void ShaderPipeline::setColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a) {  		*dst++ = b;  		*dst++ = a;  	} - -	GL_CALL(glVertexAttribPointer(_colorAttribLocation, 4, GL_FLOAT, GL_FALSE, 0, _colorAttributes));  }  void ShaderPipeline::drawTexture(const GLTexture &texture, const GLfloat *coordinates) { diff --git a/backends/graphics/opengl/shader.cpp b/backends/graphics/opengl/shader.cpp index 27981f25dc..0b4c677d70 100644 --- a/backends/graphics/opengl/shader.cpp +++ b/backends/graphics/opengl/shader.cpp @@ -37,7 +37,7 @@ namespace {  #pragma mark - Builtin Shader Sources - -const char *const g_defaultVertexShader =  +const char *const g_defaultVertexShader =  	"attribute vec4 position;\n"  	"attribute vec2 texCoordIn;\n"  	"attribute vec4 blendColorIn;\n" @@ -286,6 +286,9 @@ GLshader Shader::compileShader(const char *source, GLenum shaderType) {  }  ShaderManager::ShaderManager() : _initializeShaders(true) { +	for (int i = 0; i < ARRAYSIZE(_builtIn); ++i) { +		_builtIn[i] = nullptr; +	}  }  ShaderManager::~ShaderManager() { diff --git a/backends/graphics/opengl/texture.cpp b/backends/graphics/opengl/texture.cpp index 8b94549971..33598b5488 100644 --- a/backends/graphics/opengl/texture.cpp +++ b/backends/graphics/opengl/texture.cpp @@ -509,6 +509,7 @@ TextureCLUT8GPU::TextureCLUT8GPU()  	// Setup pipeline.  	_clut8Pipeline->setFramebuffer(_target);  	_clut8Pipeline->setPaletteTexture(&_paletteTexture); +	_clut8Pipeline->setColor(1.0f, 1.0f, 1.0f, 1.0f);  }  TextureCLUT8GPU::~TextureCLUT8GPU() { diff --git a/backends/platform/dingux/README.GCW0 b/backends/platform/dingux/README.GCW0 index 1875e5323a..1b7e30e266 100644 --- a/backends/platform/dingux/README.GCW0 +++ b/backends/platform/dingux/README.GCW0 @@ -24,3 +24,12 @@ It's pretty simple if you are running Linux on an x86/amd64 machine:  3. Run backends/platform/dingux/build.gcw0.sh script  4. Copy the resulting file scummvm.opk to your device  5. Enjoy + +Troubleshooting +=============== +In case you need to submit a bugreport, you may find the log file at the +following path: + +     /var/tmp/scummvm.log + +The log file is being overwritten at every ScummVM run. diff --git a/backends/platform/dingux/dingux.mk b/backends/platform/dingux/dingux.mk index b7f700d7fd..dc87e41241 100644 --- a/backends/platform/dingux/dingux.mk +++ b/backends/platform/dingux/dingux.mk @@ -59,7 +59,7 @@ endif  	echo >> $(gcw0_bundle)/README.man.txt  	echo '[General README]' >> $(gcw0_bundle)/README.man.txt  	echo >> $(gcw0_bundle)/README.man.txt -	cat README | sed -e 's/\[/⟦/g' -e 's/\]/⟧/g' -e '/^1\.1)/,$$ s/^[0-9][0-9]*\.[0-9][0-9]*.*/\[&\]/' >> $(gcw0_bundle)/README.man.txt +	cat $(srcdir)/README | sed -e 's/\[/⟦/g' -e 's/\]/⟧/g' -e '/^1\.1)/,$$ s/^[0-9][0-9]*\.[0-9][0-9]*.*/\[&\]/' >> $(gcw0_bundle)/README.man.txt  #	$(CP) GeneralUser\ GS\ FluidSynth\ v1.44.sf2 $(gcw0_bundle)/ @@ -67,12 +67,12 @@ endif  gcw0-opk-unstripped: $(gcw0_bundle)  	$(CP) $(PLUGINS) $(gcw0_bundle)/plugins/  	$(CP) $(EXECUTABLE) $(gcw0_bundle)/scummvm -	./dists/gcw0/opk_make.sh -d $(gcw0_bundle) -o scummvm +	$(srcdir)/dists/gcw0/opk_make.sh -d $(gcw0_bundle) -o scummvm  gcw-opk: $(gcw0_bundle)  	$(STRIP) $(gcw0_bundle)/plugins/*  	$(STRIP) $(gcw0_bundle)/scummvm -	./dists/gcw0/opk_make.sh -d $(gcw0_bundle) -o scummvm +	$(srcdir)/dists/gcw0/opk_make.sh -d $(gcw0_bundle) -o scummvm  GeneralUser_GS_1.44-FluidSynth.zip:  	curl -s http://www.scummvm.org/frs/extras/SoundFont/GeneralUser_GS_1.44-FluidSynth.zip -o GeneralUser_GS_1.44-FluidSynth.zip diff --git a/config.guess b/config.guess index 6c32c8645c..0967f2afa9 100755 --- a/config.guess +++ b/config.guess @@ -1,8 +1,8 @@  #! /bin/sh  # Attempt to guess a canonical system name. -#   Copyright 1992-2014 Free Software Foundation, Inc. +#   Copyright 1992-2016 Free Software Foundation, Inc. -timestamp='2014-11-04' +timestamp='2016-04-02'  # This file is free software; you can redistribute it and/or modify it  # under the terms of the GNU General Public License as published by @@ -27,7 +27,7 @@ timestamp='2014-11-04'  # Originally written by Per Bothner; maintained since 2000 by Ben Elliston.  #  # You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess  #  # Please send patches to <config-patches@gnu.org>. @@ -50,7 +50,7 @@ version="\  GNU config.guess ($timestamp)  Originally written by Per Bothner. -Copyright 1992-2014 Free Software Foundation, Inc. +Copyright 1992-2016 Free Software Foundation, Inc.  This is free software; see the source for copying conditions.  There is NO  warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -168,20 +168,27 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in  	# Note: NetBSD doesn't particularly care about the vendor  	# portion of the name.  We always set it to "unknown".  	sysctl="sysctl -n hw.machine_arch" -	UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ -	    /usr/sbin/$sysctl 2>/dev/null || echo unknown)` +	UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ +	    /sbin/$sysctl 2>/dev/null || \ +	    /usr/sbin/$sysctl 2>/dev/null || \ +	    echo unknown)`  	case "${UNAME_MACHINE_ARCH}" in  	    armeb) machine=armeb-unknown ;;  	    arm*) machine=arm-unknown ;;  	    sh3el) machine=shl-unknown ;;  	    sh3eb) machine=sh-unknown ;;  	    sh5el) machine=sh5le-unknown ;; +	    earmv*) +		arch=`echo ${UNAME_MACHINE_ARCH} | sed -e 's,^e\(armv[0-9]\).*$,\1,'` +		endian=`echo ${UNAME_MACHINE_ARCH} | sed -ne 's,^.*\(eb\)$,\1,p'` +		machine=${arch}${endian}-unknown +		;;  	    *) machine=${UNAME_MACHINE_ARCH}-unknown ;;  	esac  	# The Operating System including object format, if it has switched  	# to ELF recently, or will in the future.  	case "${UNAME_MACHINE_ARCH}" in -	    arm*|i386|m68k|ns32k|sh3*|sparc|vax) +	    arm*|earm*|i386|m68k|ns32k|sh3*|sparc|vax)  		eval $set_cc_for_build  		if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \  			| grep -q __ELF__ @@ -197,6 +204,13 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in  		os=netbsd  		;;  	esac +	# Determine ABI tags. +	case "${UNAME_MACHINE_ARCH}" in +	    earm*) +		expr='s/^earmv[0-9]/-eabi/;s/eb$//' +		abi=`echo ${UNAME_MACHINE_ARCH} | sed -e "$expr"` +		;; +	esac  	# The OS release  	# Debian GNU/NetBSD machines have a different userland, and  	# thus, need a distinct triplet. However, they do not need @@ -207,13 +221,13 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in  		release='-gnu'  		;;  	    *) -		release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` +		release=`echo ${UNAME_RELEASE} | sed -e 's/[-_].*//' | cut -d. -f1,2`  		;;  	esac  	# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:  	# contains redundant information, the shorter form:  	# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. -	echo "${machine}-${os}${release}" +	echo "${machine}-${os}${release}${abi}"  	exit ;;      *:Bitrig:*:*)  	UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` @@ -223,6 +237,10 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in  	UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`  	echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}  	exit ;; +    *:LibertyBSD:*:*) +	UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` +	echo ${UNAME_MACHINE_ARCH}-unknown-libertybsd${UNAME_RELEASE} +	exit ;;      *:ekkoBSD:*:*)  	echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}  	exit ;; @@ -235,6 +253,9 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in      *:MirBSD:*:*)  	echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}  	exit ;; +    *:Sortix:*:*) +	echo ${UNAME_MACHINE}-unknown-sortix +	exit ;;      alpha:OSF1:*:*)  	case $UNAME_RELEASE in  	*4.0) @@ -251,42 +272,42 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in  	ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^  The alpha \(.*\) processor.*$/\1/p' | head -n 1`  	case "$ALPHA_CPU_TYPE" in  	    "EV4 (21064)") -		UNAME_MACHINE="alpha" ;; +		UNAME_MACHINE=alpha ;;  	    "EV4.5 (21064)") -		UNAME_MACHINE="alpha" ;; +		UNAME_MACHINE=alpha ;;  	    "LCA4 (21066/21068)") -		UNAME_MACHINE="alpha" ;; +		UNAME_MACHINE=alpha ;;  	    "EV5 (21164)") -		UNAME_MACHINE="alphaev5" ;; +		UNAME_MACHINE=alphaev5 ;;  	    "EV5.6 (21164A)") -		UNAME_MACHINE="alphaev56" ;; +		UNAME_MACHINE=alphaev56 ;;  	    "EV5.6 (21164PC)") -		UNAME_MACHINE="alphapca56" ;; +		UNAME_MACHINE=alphapca56 ;;  	    "EV5.7 (21164PC)") -		UNAME_MACHINE="alphapca57" ;; +		UNAME_MACHINE=alphapca57 ;;  	    "EV6 (21264)") -		UNAME_MACHINE="alphaev6" ;; +		UNAME_MACHINE=alphaev6 ;;  	    "EV6.7 (21264A)") -		UNAME_MACHINE="alphaev67" ;; +		UNAME_MACHINE=alphaev67 ;;  	    "EV6.8CB (21264C)") -		UNAME_MACHINE="alphaev68" ;; +		UNAME_MACHINE=alphaev68 ;;  	    "EV6.8AL (21264B)") -		UNAME_MACHINE="alphaev68" ;; +		UNAME_MACHINE=alphaev68 ;;  	    "EV6.8CX (21264D)") -		UNAME_MACHINE="alphaev68" ;; +		UNAME_MACHINE=alphaev68 ;;  	    "EV6.9A (21264/EV69A)") -		UNAME_MACHINE="alphaev69" ;; +		UNAME_MACHINE=alphaev69 ;;  	    "EV7 (21364)") -		UNAME_MACHINE="alphaev7" ;; +		UNAME_MACHINE=alphaev7 ;;  	    "EV7.9 (21364A)") -		UNAME_MACHINE="alphaev79" ;; +		UNAME_MACHINE=alphaev79 ;;  	esac  	# A Pn.n version is a patched version.  	# A Vn.n version is a released version.  	# A Tn.n version is a released field test version.  	# A Xn.n version is an unreleased experimental baselevel.  	# 1.2 uses "1.2" for uname -r. -	echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` +	echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`  	# Reset EXIT trap before exiting to avoid spurious non-zero exit code.  	exitcode=$?  	trap '' 0 @@ -359,16 +380,16 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in  	exit ;;      i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)  	eval $set_cc_for_build -	SUN_ARCH="i386" +	SUN_ARCH=i386  	# If there is a compiler, see if it is configured for 64-bit objects.  	# Note that the Sun cc does not turn __LP64__ into 1 like gcc does.  	# This test works for both compilers. -	if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then +	if [ "$CC_FOR_BUILD" != no_compiler_found ]; then  	    if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ -		(CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ +		(CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \  		grep IS_64BIT_ARCH >/dev/null  	    then -		SUN_ARCH="x86_64" +		SUN_ARCH=x86_64  	    fi  	fi  	echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` @@ -393,7 +414,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in  	exit ;;      sun*:*:4.2BSD:*)  	UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` -	test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 +	test "x${UNAME_RELEASE}" = x && UNAME_RELEASE=3  	case "`/bin/arch`" in  	    sun3)  		echo m68k-sun-sunos${UNAME_RELEASE} @@ -618,13 +639,13 @@ EOF  		    sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`  		    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`  		    case "${sc_cpu_version}" in -		      523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 -		      528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 +		      523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 +		      528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1  		      532)                      # CPU_PA_RISC2_0  			case "${sc_kernel_bits}" in -			  32) HP_ARCH="hppa2.0n" ;; -			  64) HP_ARCH="hppa2.0w" ;; -			  '') HP_ARCH="hppa2.0" ;;   # HP-UX 10.20 +			  32) HP_ARCH=hppa2.0n ;; +			  64) HP_ARCH=hppa2.0w ;; +			  '') HP_ARCH=hppa2.0 ;;   # HP-UX 10.20  			esac ;;  		    esac  		fi @@ -663,11 +684,11 @@ EOF  		    exit (0);  		}  EOF -		    (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` +		    (CCOPTS="" $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`  		    test -z "$HP_ARCH" && HP_ARCH=hppa  		fi ;;  	esac -	if [ ${HP_ARCH} = "hppa2.0w" ] +	if [ ${HP_ARCH} = hppa2.0w ]  	then  	    eval $set_cc_for_build @@ -680,12 +701,12 @@ EOF  	    # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess  	    # => hppa64-hp-hpux11.23 -	    if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | +	    if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) |  		grep -q __LP64__  	    then -		HP_ARCH="hppa2.0w" +		HP_ARCH=hppa2.0w  	    else -		HP_ARCH="hppa64" +		HP_ARCH=hppa64  	    fi  	fi  	echo ${HP_ARCH}-hp-hpux${HPUX_REV} @@ -790,14 +811,14 @@ EOF  	echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'  	exit ;;      F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) -	FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` -	FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` +	FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` +	FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`  	FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`  	echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"  	exit ;;      5000:UNIX_System_V:4.*:*) -	FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` -	FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` +	FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` +	FUJITSU_REL=`echo ${UNAME_RELEASE} | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'`  	echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"  	exit ;;      i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) @@ -879,7 +900,7 @@ EOF  	exit ;;      *:GNU/*:*:*)  	# other systems with GNU libc and userland -	echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} +	echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC}  	exit ;;      i*86:Minix:*:*)  	echo ${UNAME_MACHINE}-pc-minix @@ -902,7 +923,7 @@ EOF  	  EV68*) UNAME_MACHINE=alphaev68 ;;  	esac  	objdump --private-headers /bin/sh | grep -q ld.so.1 -	if test "$?" = 0 ; then LIBC="gnulibc1" ; fi +	if test "$?" = 0 ; then LIBC=gnulibc1 ; fi  	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}  	exit ;;      arc:Linux:*:* | arceb:Linux:*:*) @@ -933,6 +954,9 @@ EOF      crisv32:Linux:*:*)  	echo ${UNAME_MACHINE}-axis-linux-${LIBC}  	exit ;; +    e2k:Linux:*:*) +	echo ${UNAME_MACHINE}-unknown-linux-${LIBC} +	exit ;;      frv:Linux:*:*)  	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}  	exit ;; @@ -945,6 +969,9 @@ EOF      ia64:Linux:*:*)  	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}  	exit ;; +    k1om:Linux:*:*) +	echo ${UNAME_MACHINE}-unknown-linux-${LIBC} +	exit ;;      m32r*:Linux:*:*)  	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}  	exit ;; @@ -1021,7 +1048,7 @@ EOF  	echo ${UNAME_MACHINE}-dec-linux-${LIBC}  	exit ;;      x86_64:Linux:*:*) -	echo ${UNAME_MACHINE}-unknown-linux-${LIBC} +	echo ${UNAME_MACHINE}-pc-linux-${LIBC}  	exit ;;      xtensa*:Linux:*:*)  	echo ${UNAME_MACHINE}-unknown-linux-${LIBC} @@ -1100,7 +1127,7 @@ EOF  	# uname -m prints for DJGPP always 'pc', but it prints nothing about  	# the processor, so we play safe by assuming i586.  	# Note: whatever this is, it MUST be the same as what config.sub -	# prints for the "djgpp" host, or else GDB configury will decide that +	# prints for the "djgpp" host, or else GDB configure will decide that  	# this is a cross-build.  	echo i586-pc-msdosdjgpp  	exit ;; @@ -1249,6 +1276,9 @@ EOF      SX-8R:SUPER-UX:*:*)  	echo sx8r-nec-superux${UNAME_RELEASE}  	exit ;; +    SX-ACE:SUPER-UX:*:*) +	echo sxace-nec-superux${UNAME_RELEASE} +	exit ;;      Power*:Rhapsody:*:*)  	echo powerpc-apple-rhapsody${UNAME_RELEASE}  	exit ;; @@ -1262,9 +1292,9 @@ EOF  	    UNAME_PROCESSOR=powerpc  	fi  	if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then -	    if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then +	    if [ "$CC_FOR_BUILD" != no_compiler_found ]; then  		if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ -		    (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ +		    (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \  		    grep IS_64BIT_ARCH >/dev/null  		then  		    case $UNAME_PROCESSOR in @@ -1286,7 +1316,7 @@ EOF  	exit ;;      *:procnto*:*:* | *:QNX:[0123456789]*:*)  	UNAME_PROCESSOR=`uname -p` -	if test "$UNAME_PROCESSOR" = "x86"; then +	if test "$UNAME_PROCESSOR" = x86; then  		UNAME_PROCESSOR=i386  		UNAME_MACHINE=pc  	fi @@ -1317,7 +1347,7 @@ EOF  	# "uname -m" is not consistent, so use $cputype instead. 386  	# is converted to i386 for consistency with other x86  	# operating systems. -	if test "$cputype" = "386"; then +	if test "$cputype" = 386; then  	    UNAME_MACHINE=i386  	else  	    UNAME_MACHINE="$cputype" @@ -1359,7 +1389,7 @@ EOF  	echo i386-pc-xenix  	exit ;;      i*86:skyos:*:*) -	echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' +	echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE} | sed -e 's/ .*$//'`  	exit ;;      i*86:rdos:*:*)  	echo ${UNAME_MACHINE}-pc-rdos @@ -1370,6 +1400,9 @@ EOF      x86_64:VMkernel:*:*)  	echo ${UNAME_MACHINE}-unknown-esx  	exit ;; +    amd64:Isilon\ OneFS:*:*) +	echo x86_64-unknown-onefs +	exit ;;  esac  cat >&2 <<EOF @@ -1379,9 +1412,9 @@ This script, last modified $timestamp, has failed to recognize  the operating system you are using. It is advised that you  download the most up to date version of the config scripts from -  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD +  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess  and -  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD +  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub  If the version you run ($0) is already up to date, please  send the following data and any information you think might be diff --git a/config.sub b/config.sub index 7ffe373784..8d39c4ba39 100755 --- a/config.sub +++ b/config.sub @@ -1,8 +1,8 @@  #! /bin/sh  # Configuration validation subroutine script. -#   Copyright 1992-2014 Free Software Foundation, Inc. +#   Copyright 1992-2016 Free Software Foundation, Inc. -timestamp='2014-12-03' +timestamp='2016-03-30'  # This file is free software; you can redistribute it and/or modify it  # under the terms of the GNU General Public License as published by @@ -33,7 +33,7 @@ timestamp='2014-12-03'  # Otherwise, we print the canonical config type on stdout and succeed.  # You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub  # This file is supposed to be the same for all GNU packages  # and recognize all the CPU types, system types and aliases @@ -53,8 +53,7 @@ timestamp='2014-12-03'  me=`echo "$0" | sed -e 's,.*/,,'`  usage="\ -Usage: $0 [OPTION] CPU-MFR-OPSYS -       $0 [OPTION] ALIAS +Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS  Canonicalize a configuration name. @@ -68,7 +67,7 @@ Report bugs and patches to <config-patches@gnu.org>."  version="\  GNU config.sub ($timestamp) -Copyright 1992-2014 Free Software Foundation, Inc. +Copyright 1992-2016 Free Software Foundation, Inc.  This is free software; see the source for copying conditions.  There is NO  warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -117,7 +116,7 @@ maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`  case $maybe_os in    nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \    linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ -  knetbsd*-gnu* | netbsd*-gnu* | \ +  knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \    kopensolaris*-gnu* | \    storm-chaos* | os2-emx* | rtmk-nova*)      os=-$maybe_os @@ -255,12 +254,13 @@ case $basic_machine in  	| arc | arceb \  	| arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \  	| avr | avr32 \ +	| ba \  	| be32 | be64 \  	| bfin \  	| c4x | c8051 | clipper \  	| d10v | d30v | dlx | dsp16xx \ -	| epiphany \ -	| fido | fr30 | frv \ +	| e2k | epiphany \ +	| fido | fr30 | frv | ft32 \  	| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \  	| hexagon \  	| i370 | i860 | i960 | ia64 \ @@ -305,7 +305,7 @@ case $basic_machine in  	| riscv32 | riscv64 \  	| rl78 | rx \  	| score \ -	| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ +	| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \  	| sh64 | sh64le \  	| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \  	| sparcv8 | sparcv9 | sparcv9b | sparcv9v \ @@ -376,12 +376,13 @@ case $basic_machine in  	| alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \  	| arm-*  | armbe-* | armle-* | armeb-* | armv*-* \  	| avr-* | avr32-* \ +	| ba-* \  	| be32-* | be64-* \  	| bfin-* | bs2000-* \  	| c[123]* | c30-* | [cjt]90-* | c4x-* \  	| c8051-* | clipper-* | craynv-* | cydra-* \  	| d10v-* | d30v-* | dlx-* \ -	| elxsi-* \ +	| e2k-* | elxsi-* \  	| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \  	| h8300-* | h8500-* \  	| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ @@ -428,12 +429,13 @@ case $basic_machine in  	| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \  	| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \  	| pyramid-* \ +	| riscv32-* | riscv64-* \  	| rl78-* | romp-* | rs6000-* | rx-* \  	| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \  	| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \  	| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \  	| sparclite-* \ -	| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ +	| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \  	| tahoe-* \  	| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \  	| tile*-* \ @@ -518,6 +520,9 @@ case $basic_machine in  		basic_machine=i386-pc  		os=-aros  		;; +	asmjs) +		basic_machine=asmjs-unknown +		;;  	aux)  		basic_machine=m68k-apple  		os=-aux @@ -1373,11 +1378,11 @@ case $os in  	      | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \  	      | -sym* | -kopensolaris* | -plan9* \  	      | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ -	      | -aos* | -aros* \ +	      | -aos* | -aros* | -cloudabi* | -sortix* \  	      | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \  	      | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \  	      | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ -	      | -bitrig* | -openbsd* | -solidbsd* \ +	      | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \  	      | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \  	      | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \  	      | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ @@ -1393,7 +1398,8 @@ case $os in  	      | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \  	      | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \  	      | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ -	      | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*) +	      | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \ +	      | -onefs* | -tirtos*)  	# Remember, each alternative MUST END IN *, to match a version number.  		;;  	-qnx*) @@ -1525,6 +1531,8 @@ case $os in  		;;  	-nacl*)  		;; +	-ios) +		;;  	-none)  		;;  	*) diff --git a/devtools/create_wage/create_wage.sh b/devtools/create_classicmacfonts.sh index 5e8fe352a2..6942d07111 100755 --- a/devtools/create_wage/create_wage.sh +++ b/devtools/create_classicmacfonts.sh @@ -106,8 +106,8 @@ echo_n "Converting fonts..."  fondu-060102/fondu -force *.bin  echo done -zip -9 wage *.bdf -mv wage.zip wage.dat +zip -9 classicmacfonts *.bdf +mv classicmacfonts.zip classicmacfonts.dat  echo_n "Cleaning up..."  rm *.bdf @@ -116,4 +116,4 @@ rm *.bin  rm *.dmg  echo done -ls -l wage.dat +ls -l classicmacfonts.dat diff --git a/devtools/scumm-md5.txt b/devtools/scumm-md5.txt index 235986a878..92754a27b4 100644 --- a/devtools/scumm-md5.txt +++ b/devtools/scumm-md5.txt @@ -237,6 +237,7 @@ monkey	The Secret of Monkey Island  	71523b539491527d9860f4407faf0411	7607	en	DOS	Demo	EGA Demo	-	Fingolfin  	771bc18ec6f93837b839c992b211904b	-1	de	DOS	Demo	EGA Demo	-	khalek  	54a936ad06161ff7bfefcb96200f7bff	7617	en	Amiga	VGA	VGA Demo	-	khalek +	c0c9de81fb965e6cbe77f6e5631ca705	9135	en	DOS	SE Talkie	Unofficial SE Talkie v1.02	rootfather  pass	Passport to Adventure  	e6cd81b25ab1453a8a6d3482118c391e	7857	en	DOS	-	-	v1.0 9/14/90	Fingolfin @@ -269,6 +270,7 @@ monkey2	Monkey Island 2: LeChuck's Revenge  	430bc518017b6fac046f58bab6baad5d	-1	jp	FM-TOWNS	FM-TOWNS	-	-	Antti Leimi, Andrea Petrucci  	387a544b8b10b26912d8413bab63a853	-1	en	DOS	-	Demo	non-interactive	khalek +	f4d20ab4ce19743a646cb48bd93aee72	10835	en	DOS	SE Talkie	Unofficial SE Talkie v0.2	rootfather  atlantis	Indiana Jones and the Fate of Atlantis  	3a03dab514e4038df192d8a8de469788	-1	en	Amiga	Floppy	Floppy	-	dhewg diff --git a/doc/de/Neues b/doc/de/Neues index 106dc6ea88..e3d8f3a607 100644 --- a/doc/de/Neues +++ b/doc/de/Neues @@ -15,6 +15,8 @@ Programmcodes finden Sie auf Englisch unter:   Allgemein:     - "TESTING"-Markierung von mehreren unterstützten Spielen entfernt.     - Chinesische Übersetzung (Pinyin) der Benutzeroberfläche hinzugefügt. +   - Ruckeln des Mauszeigers im ScummVM-Programmfenster behoben, welches auf +     einigen Systemen auftrat.   BBVS:     - Fehler beim erneuten Starten des Spiels behoben. @@ -28,10 +30,24 @@ Programmcodes finden Sie auf Englisch unter:     - Laden eines Spielstandes in der "Pendulum"-Szene repariert.     - Falscher Hintergrund für Inventar-Gegenstände im Kapitel 6 in der       spanischen Version korrigiert. +   - Geschwindigkeit der Animationen korrigiert. Animationen wurden nur halb +     so schnell wie im originalen Interpreter abgespielt. +   - Rauschen am Beginn und/oder am Ende der Sprachausgabe behoben. +     Dieser Fehler trat hauptsächlich in der spanischen Version auf. +   - Verzögerung während der Interaktion mit dem Verben-Menü und dem Inventar behoben. +   - Fehler behoben, durch den die Axt im Schloss mehrfach aufgehoben werden konnte.   Gob:     - Aufhängen während Sound-Initialisierung in mehreren Spielen behoben. + KYRA: +   - Potentieller Absturz behoben, der in "Hand of Fate" auftritt, wenn der +     Sumpfschlangentrank an der Ratte verwendet wird. +     (HINWEIS: Dieser Fehler wurde bereits in Version 1.8.0 behoben, +     jedoch nicht in der Neues-Datei erwähnt). +   - Fehlende Stimm-Reaktionen korrigiert, wenn Gegner in der CD-Version von +     Lands of Lore getroffen wurden. +   Lab:     - Aufhängen während der End-Sequenz behoben.     - Interne Spiel-Bedienelemente verbessert. @@ -74,6 +90,9 @@ Programmcodes finden Sie auf Englisch unter:       wenn ScummVM nicht läuft, und ermöglicht den direkten Start dieser Spiele.     - Sparkle-Updater für vereinfachte Programmaktualisierungen hinzugefügt. + GCW0-Portierung: +   - Verbesserte Unterstützung für die in ScummVM integrierte Dokumentation. +  1.8.0 (04.03.2016)   Neue Spiele:     - Unterstützung für Rex Nebular and the Cosmic Gender Bender hinzugefügt. @@ -90,7 +109,7 @@ Programmcodes finden Sie auf Englisch unter:       hinzugefügt.     - Unterstützung für Labyrinth of Time hinzugefügt. -Neue Portierungen: + Neue Portierungen:     - Portierung für den Raspberry Pi hinzugefügt.     - Portierung für den GCW Zero (GCW0) hinzugefügt. @@ -100,7 +119,7 @@ Neue Portierungen:   SDL:     - Alt+x beendet ScummVM nicht mehr. Verwenden Sie stattdessen       Cmd+q/Strg+q/Strg+z und beachten Sie die Hinweise in der Liesmich-Datei. -  -  Auf POSIX-Systemen befolgen wir nun die Spezifikation XDG Base Directory +   - Auf POSIX-Systemen befolgen wir nun die Spezifikation XDG Base Directory       für die Speicherung von Benutzerdaten. Dies führt zu neuen       Speicherorten für unsere Konfigurationsdatei, unsere Log-Datei sowie für       den standardmäßig voreingestellten Speicherort für Spielstände. Wir diff --git a/engines/agi/agi.cpp b/engines/agi/agi.cpp index e566ad12f6..60c8d1f3ef 100644 --- a/engines/agi/agi.cpp +++ b/engines/agi/agi.cpp @@ -403,6 +403,11 @@ AgiEngine::AgiEngine(OSystem *syst, const AGIGameDescription *gameDesc) : AgiBas  	_lastSaveTime = 0; +	_playTimeInSecondsAdjust = 0; +	_lastUsedPlayTimeInCycles = 0; +	_lastUsedPlayTimeInSeconds = 0; +	_passedPlayTimeCycles = 0; +  	memset(_keyQueue, 0, sizeof(_keyQueue));  	_console = nullptr; @@ -418,6 +423,9 @@ AgiEngine::AgiEngine(OSystem *syst, const AGIGameDescription *gameDesc) : AgiBas  	_inventory = nullptr;  	_keyHoldMode = false; + +	_artificialDelayCurrentRoom = 0; +	_artificialDelayCurrentPicture = 0;  }  void AgiEngine::initialize() { diff --git a/engines/agos/detection_tables.h b/engines/agos/detection_tables.h index 793d4081cf..90e5a84829 100644 --- a/engines/agos/detection_tables.h +++ b/engines/agos/detection_tables.h @@ -2251,6 +2251,31 @@ static const AGOSGameDescription gameDescriptions[] = {  		GF_TALKIE  	}, +	// Simon the Sorcerer 2 - Russian DOS CD +	{ +		{ +			"simon2", +			"CD", + +			{ +	{ "gsptr30",		GAME_BASEFILE,	"e26d162e573587f4601b88701292212c", 58851}, +	{ "icon.dat",		GAME_ICONFILE,	"72096a62d36e6034ea9fecc13b2dbdab", 18089}, +	{ "simon2.gme",		GAME_GMEFILE,	"9c535d403966750ae98bdaf698375a38", 19687892}, +	{ "stripped.txt",	GAME_STRFILE,	"e229f84d46fa83f99b4a7115679f3fb6", 171}, +	{ "tbllist",		GAME_TBLFILE,	"2082f8d02075e590300478853a91ffd9", 513}, +	{ NULL, 0, NULL, 0} +			}, +			Common::RU_RUS, +			Common::kPlatformDOS, +			ADGF_CD, +			GUIO0() +		}, + +		GType_SIMON2, +		GID_SIMON2, +		GF_TALKIE +	}, +  	// Simon the Sorcerer 2 - Czech Windows CD  	{  		{ diff --git a/engines/cge2/vga13h.cpp b/engines/cge2/vga13h.cpp index 54f5c00d93..8b0d8b6c77 100644 --- a/engines/cge2/vga13h.cpp +++ b/engines/cge2/vga13h.cpp @@ -952,8 +952,9 @@ uint8 Vga::closest(Dac *pal, const uint8 colR, const uint8 colG, const uint8 col  }  uint8 Vga::closest(Dac *pal, Dac x) { -	int exp = (sizeof(long) * 8 - 1); -	long D = (1 << exp) - 1; // Maximum value of long. +	long D = 0; +	D = ~D; +	D = (unsigned long)D >> 1; // Maximum value of long.  	long R = x._r;  	long G = x._g;  	long B = x._b; diff --git a/engines/cruise/dataLoader.cpp b/engines/cruise/dataLoader.cpp index 7a1258dbde..2eff82bc61 100644 --- a/engines/cruise/dataLoader.cpp +++ b/engines/cruise/dataLoader.cpp @@ -249,12 +249,19 @@ int loadFile(const char* name, int idx, int destIdx) {  		int numMaxEntriesInSet = getNumMaxEntiresInSet(ptr);  		if (destIdx > numMaxEntriesInSet) { +			MemFree(ptr);  			return 0;	// exit if limit is reached  		} -		return loadSetEntry(name, ptr, destIdx, idx); +		int res = loadSetEntry(name, ptr, destIdx, idx); +		MemFree(ptr); + +		return res;  	}  	case type_FNT: { -		return loadFNTSub(ptr, idx); +		int res = loadFNTSub(ptr, idx); +		MemFree(ptr); + +		return res;  	}  	case type_SPL: {  		// Sound file diff --git a/engines/drascula/actors.cpp b/engines/drascula/actors.cpp index a1f2c5386c..b459c4539b 100644 --- a/engines/drascula/actors.cpp +++ b/engines/drascula/actors.cpp @@ -196,10 +196,6 @@ void DrasculaEngine::moveCharacters() {  			return;  		}  	} -	 -	byte *srcSurface = extraSurface; -	if (currentChapter == 6 && _lang == kSpanish) -		srcSurface = tableSurface;  	if (characterMoved == 0) {  		curPos[0] = 0; @@ -218,17 +214,17 @@ void DrasculaEngine::moveCharacters() {  			curPos[1] = 0;  			if (currentChapter == 2)  				copyRect(curPos[0], curPos[1], curPos[2], curPos[3], curPos[4], curPos[5], -						 srcSurface, screenSurface); +						 extraSurface, screenSurface);  			else  				reduce_hare_chico(curPos[0], curPos[1], curPos[2], curPos[3], curPos[4], curPos[5], -									factor_red[curY + curHeight], srcSurface, screenSurface); +									factor_red[curY + curHeight], extraSurface, screenSurface);  		} else if (trackProtagonist == 1) {  			if (currentChapter == 2)  				copyRect(curPos[0], curPos[1], curPos[2], curPos[3], curPos[4], curPos[5], -						 srcSurface, screenSurface); +						 extraSurface, screenSurface);  			else  				reduce_hare_chico(curPos[0], curPos[1], curPos[2], curPos[3], curPos[4], curPos[5], -									factor_red[curY + curHeight], srcSurface, screenSurface); +									factor_red[curY + curHeight], extraSurface, screenSurface);  		} else if (trackProtagonist == 2) {  			if (currentChapter == 2)  				copyRect(curPos[0], curPos[1], curPos[2], curPos[3], curPos[4], curPos[5], @@ -260,17 +256,17 @@ void DrasculaEngine::moveCharacters() {  			curPos[1] = 0;  			if (currentChapter == 2)  				copyRect(curPos[0], curPos[1], curPos[2], curPos[3], curPos[4], curPos[5], -						 srcSurface, screenSurface); +						 extraSurface, screenSurface);  			else  				reduce_hare_chico(curPos[0], curPos[1], curPos[2], curPos[3], curPos[4], curPos[5], -									factor_red[curY + curHeight], srcSurface, screenSurface); +									factor_red[curY + curHeight], extraSurface, screenSurface);  		} else if (trackProtagonist == 1) {  			if (currentChapter == 2)  				copyRect(curPos[0], curPos[1], curPos[2], curPos[3], curPos[4], curPos[5], -						 srcSurface, screenSurface); +						 extraSurface, screenSurface);  			else  				reduce_hare_chico(curPos[0], curPos[1], curPos[2], curPos[3], curPos[4], curPos[5], -									factor_red[curY + curHeight], srcSurface, screenSurface); +									factor_red[curY + curHeight], extraSurface, screenSurface);  		} else if (trackProtagonist == 2) {  			if (currentChapter == 2)  				copyRect(curPos[0], curPos[1], curPos[2], curPos[3], curPos[4], curPos[5], diff --git a/engines/drascula/animation.cpp b/engines/drascula/animation.cpp index 0ed2c61e3f..f672ad3b55 100644 --- a/engines/drascula/animation.cpp +++ b/engines/drascula/animation.cpp @@ -1612,7 +1612,7 @@ void DrasculaEngine::animation_6_6() {  	removeObject(20);  	loadPic(96, frontSurface);  	loadPic(97, frontSurface); -	loadPic(97, _lang == kSpanish ? tableSurface : extraSurface); +	loadPic(97, extraSurface);  	loadPic(99, backSurface);  	doBreak = 1;  	objExit = 104; @@ -2216,7 +2216,7 @@ void DrasculaEngine::activatePendulum() {  	_roomNumber = 102;  	loadPic(102, bgSurface, HALF_PAL);  	loadPic("an_p1.alg", drawSurface3); -	loadPic("an_p2.alg", _lang == kSpanish ? tableSurface : extraSurface); +	loadPic("an_p2.alg", extraSurface);  	loadPic("an_p3.alg", frontSurface);  	copyBackground(0, 171, 0, 0, OBJWIDTH, OBJHEIGHT, backSurface, drawSurface3); diff --git a/engines/drascula/drascula.cpp b/engines/drascula/drascula.cpp index 75a81c20b0..ab91056480 100644 --- a/engines/drascula/drascula.cpp +++ b/engines/drascula/drascula.cpp @@ -359,16 +359,13 @@ Common::Error DrasculaEngine::run() {  		for (i = 0; i < 25; i++)  			memcpy(crosshairCursor + i * 40, tableSurface + 225 + (56 + i) * 320, 40); -		if (_lang == kSpanish) -			loadPic(currentChapter == 6 ? 97 : 974, tableSurface); +		if (_lang == kSpanish && currentChapter != 6) +			loadPic(974, tableSurface);  		if (currentChapter != 2) {  			loadPic(99, cursorSurface);  			loadPic(99, backSurface); -			if (currentChapter == 6 && _lang == kSpanish) -				loadPic(95, extraSurface); -			else -				loadPic(97, extraSurface); +			loadPic(97, extraSurface);  		}  		memset(iconName, 0, sizeof(iconName)); @@ -598,7 +595,6 @@ bool DrasculaEngine::runCurrentChapter() {  		if (_rightMouseButton == 1 && _menuScreen) {  #endif  			_rightMouseButton = 0; -			delay(100);  			if (currentChapter == 2) {  				loadPic(menuBackground, cursorSurface);  				loadPic(menuBackground, backSurface); @@ -627,7 +623,6 @@ bool DrasculaEngine::runCurrentChapter() {  			!(currentChapter == 5 && pickedObject == 16)) {  #endif  			_rightMouseButton = 0; -			delay(100);  			characterMoved = 0;  			if (trackProtagonist == 2)  				trackProtagonist = 1; @@ -655,12 +650,11 @@ bool DrasculaEngine::runCurrentChapter() {  #endif  		if (_leftMouseButton == 1 && _menuBar) { -			delay(100);  			selectVerbFromBar();  		} else if (_leftMouseButton == 1 && takeObject == 0) { -			delay(100);  			if (verify1())  				return true; +			delay(100);  		} else if (_leftMouseButton == 1 && takeObject == 1) {  			if (verify2())  				return true; @@ -894,7 +888,7 @@ void DrasculaEngine::pause(int duration) {  }  int DrasculaEngine::getTime() { -	return _system->getMillis() / 20; // originally was 1 +	return _system->getMillis() / 10;  }  void DrasculaEngine::reduce_hare_chico(int xx1, int yy1, int xx2, int yy2, int width, int height, int factor, byte *dir_inicio, byte *dir_fin) { diff --git a/engines/drascula/graphics.cpp b/engines/drascula/graphics.cpp index 01bd267158..6bfb2e1823 100644 --- a/engines/drascula/graphics.cpp +++ b/engines/drascula/graphics.cpp @@ -217,6 +217,10 @@ void DrasculaEngine::print_abc(const char *said, int screenX, int screenY) {  	int letterY = 0, letterX = 0, i;  	uint len = strlen(said);  	byte c; +	 +	byte *srcSurface = tableSurface; +	if (_lang == kSpanish && currentChapter == 6) +		srcSurface = extraSurface;  	for (uint h = 0; h < len; h++) {  		c = toupper(said[h]); @@ -241,7 +245,7 @@ void DrasculaEngine::print_abc(const char *said, int screenX, int screenY) {  		}	// for  		copyRect(letterX, letterY, screenX, screenY, -				 CHAR_WIDTH, CHAR_HEIGHT, tableSurface, screenSurface); +				 CHAR_WIDTH, CHAR_HEIGHT, srcSurface, screenSurface);  		screenX = screenX + CHAR_WIDTH;  		if (screenX > 317) { diff --git a/engines/drascula/interface.cpp b/engines/drascula/interface.cpp index a09b9da07d..07f192cd4c 100644 --- a/engines/drascula/interface.cpp +++ b/engines/drascula/interface.cpp @@ -123,15 +123,6 @@ void DrasculaEngine::showMenu() {  	int h, n, x;  	byte *srcSurface = (currentChapter == 6) ? tableSurface : frontSurface;  	x = whichObject(); -	 -	// The original uses extraSurface to draw text in draw_abc() in the Spanish version -	// while other languages use tableSurface. Here all language use tableSurface for -	// chapter 6. However the code in ScummVM was changed to use tableSurface for all -	// labguage in draw_abc(). So instead here for the Spanish version we use extraSurface. -	// Compared to the original the use of the tableSurface and extraSurface has been swapped -	// for the Spanish language all through chapter 6. -	if (currentChapter == 6 && _lang == kSpanish) -		srcSurface = extraSurface;  	for (n = 1; n < ARRAYSIZE(inventoryObjects); n++) {  		h = inventoryObjects[n]; diff --git a/engines/drascula/objects.cpp b/engines/drascula/objects.cpp index 823c073d43..02846abcc9 100644 --- a/engines/drascula/objects.cpp +++ b/engines/drascula/objects.cpp @@ -272,6 +272,8 @@ void DrasculaEngine::updateVisible() {  			visible[2] = 0;  		if (_roomNumber == 26 && flags[12] == 1)  			visible[1] = 0; +		if (_roomNumber == 31 && flags[13] == 1) +			visible[1] = 0;  		if (_roomNumber == 35 && flags[14] == 1)  			visible[2] = 0;  		if (_roomNumber == 35 && flags[17] == 1) diff --git a/engines/drascula/rooms.cpp b/engines/drascula/rooms.cpp index acfc528b0c..57d4517295 100644 --- a/engines/drascula/rooms.cpp +++ b/engines/drascula/rooms.cpp @@ -1501,7 +1501,7 @@ void DrasculaEngine::update_102() {  	if (actorFrames[kFramePendulum] <= 4)  		pendulumSurface = drawSurface3;  	else if (actorFrames[kFramePendulum] <= 11) -		pendulumSurface = _lang == kSpanish ? tableSurface : extraSurface; +		pendulumSurface = extraSurface;  	else  		pendulumSurface = frontSurface; diff --git a/engines/drascula/sound.cpp b/engines/drascula/sound.cpp index 6c0c171664..62ec796678 100644 --- a/engines/drascula/sound.cpp +++ b/engines/drascula/sound.cpp @@ -44,13 +44,10 @@ void DrasculaEngine::updateVolume(Audio::Mixer::SoundType soundType, int prevVol  }  void DrasculaEngine::volumeControls() { -	byte* srcSurface = tableSurface; -	if (currentChapter == 6 && _lang == kSpanish) -		srcSurface = extraSurface; -	if (_lang == kSpanish) -		loadPic(95, srcSurface); +	if (_lang == kSpanish && currentChapter != 6) +		loadPic(95, tableSurface); -	copyRect(1, 56, 73, 63, 177, 97, srcSurface, screenSurface); +	copyRect(1, 56, 73, 63, 177, 97, tableSurface, screenSurface);  	updateScreen(73, 63, 73, 63, 177, 97, screenSurface);  	setCursor(kCursorCrosshair); @@ -67,11 +64,11 @@ void DrasculaEngine::volumeControls() {  		updateRoom(); -		copyRect(1, 56, 73, 63, 177, 97, srcSurface, screenSurface); +		copyRect(1, 56, 73, 63, 177, 97, tableSurface, screenSurface); -		copyBackground(183, 56, 82, masterVolumeY, 39, 2 + masterVolume * 4, srcSurface, screenSurface); -		copyBackground(183, 56, 138, voiceVolumeY, 39, 2 + voiceVolume * 4, srcSurface, screenSurface); -		copyBackground(183, 56, 194, musicVolumeY, 39, 2 + musicVolume * 4, srcSurface, screenSurface); +		copyBackground(183, 56, 82, masterVolumeY, 39, 2 + masterVolume * 4, tableSurface, screenSurface); +		copyBackground(183, 56, 138, voiceVolumeY, 39, 2 + voiceVolume * 4, tableSurface, screenSurface); +		copyBackground(183, 56, 194, musicVolumeY, 39, 2 + musicVolume * 4, tableSurface, screenSurface);  		updateScreen(); @@ -104,8 +101,8 @@ void DrasculaEngine::volumeControls() {  	} -	if (_lang == kSpanish) -		loadPic(currentChapter == 6 ? 95 : 974, srcSurface); +	if (_lang == kSpanish && currentChapter != 6) +		loadPic(974, tableSurface);  	selectVerb(kVerbNone); @@ -169,8 +166,8 @@ void DrasculaEngine::MusicFadeout() {  void DrasculaEngine::playFile(const char *fname) {  	Common::SeekableReadStream *stream = _archives.open(fname);  	if (stream) { -		int startOffset = 0; -		int soundSize = stream->size() - startOffset; +		int startOffset = 32; +		int soundSize = stream->size() - 64;  		if (!strcmp(fname, "3.als") && soundSize == 145166 && _lang != kSpanish) {  			// WORKAROUND: File 3.als with English speech files has a big silence at diff --git a/engines/drascula/talk.cpp b/engines/drascula/talk.cpp index 3176c5e0f3..cc329b206b 100644 --- a/engines/drascula/talk.cpp +++ b/engines/drascula/talk.cpp @@ -440,12 +440,9 @@ void DrasculaEngine::talk(const char *said, const char *filename) {  				copyRect(x_talk_izq[face], y_mask_talk, curX + 8, curY - 1, TALK_WIDTH, TALK_HEIGHT,  						extraSurface, screenSurface);  			else if (notTowers) { -				byte *srcSurface = extraSurface; -				if (currentChapter == 6 && _lang == kSpanish) -					srcSurface = tableSurface;  				reduce_hare_chico(x_talk_izq[face], y_mask_talk, curX + (int)((8.0f / 100) * factor_red[MIN(201, curY + curHeight)]),  					curY, TALK_WIDTH, TALK_HEIGHT, factor_red[MIN(201, curY + curHeight)], -					srcSurface, screenSurface); +					extraSurface, screenSurface);  			}  			updateRefresh();  		} else if (trackProtagonist == 1) { @@ -453,11 +450,8 @@ void DrasculaEngine::talk(const char *said, const char *filename) {  				copyRect(x_talk_dch[face], y_mask_talk, curX + 12, curY, TALK_WIDTH, TALK_HEIGHT,  					extraSurface, screenSurface);  			else if (notTowers) { -				byte *srcSurface = extraSurface; -				if (currentChapter == 6 && _lang == kSpanish) -					srcSurface = tableSurface;  				reduce_hare_chico(x_talk_dch[face], y_mask_talk, curX + (int)((12.0f / 100) * factor_red[MIN(201, curY + curHeight)]), -					curY, TALK_WIDTH, TALK_HEIGHT, factor_red[MIN(201, curY + curHeight)], srcSurface, screenSurface); +					curY, TALK_WIDTH, TALK_HEIGHT, factor_red[MIN(201, curY + curHeight)], extraSurface, screenSurface);  			}  			updateRefresh();  		} else if (trackProtagonist == 2) { diff --git a/engines/fullpipe/fullpipe.cpp b/engines/fullpipe/fullpipe.cpp index ebaff32550..c2aae9ba88 100644 --- a/engines/fullpipe/fullpipe.cpp +++ b/engines/fullpipe/fullpipe.cpp @@ -24,6 +24,7 @@  #include "common/archive.h"  #include "common/config-manager.h" +#include "audio/mixer.h"  #include "engines/util.h" @@ -112,6 +113,8 @@ FullpipeEngine::FullpipeEngine(OSystem *syst, const ADGameDescription *gameDesc)  	_musicLocal = 0;  	_trackStartDelay = 0; +	_sceneTrackHandle = new Audio::SoundHandle(); +  	memset(_sceneTracks, 0, sizeof(_sceneTracks));  	memset(_trackName, 0, sizeof(_trackName));  	memset(_sceneTracksCurrentTrack, 0, sizeof(_sceneTracksCurrentTrack)); @@ -192,6 +195,7 @@ FullpipeEngine::~FullpipeEngine() {  	delete _rnd;  	delete _console;  	delete _globalMessageQueueList; +	delete _sceneTrackHandle;  }  void FullpipeEngine::initialize() { diff --git a/engines/fullpipe/fullpipe.h b/engines/fullpipe/fullpipe.h index 7f20a6d6af..fba61aa13b 100644 --- a/engines/fullpipe/fullpipe.h +++ b/engines/fullpipe/fullpipe.h @@ -30,8 +30,6 @@  #include "common/savefile.h"  #include "common/system.h" -#include "audio/mixer.h" -  #include "graphics/transparent_surface.h"  #include "engines/engine.h" @@ -41,6 +39,10 @@  struct ADGameDescription; +namespace Audio { +class SoundHandle; +} +  namespace Fullpipe {  enum FullpipeGameFeatures { @@ -312,7 +314,7 @@ public:  	void lift_openLift();  	GameVar *_musicGameVar; -	Audio::SoundHandle _sceneTrackHandle; +	Audio::SoundHandle *_sceneTrackHandle;  public: diff --git a/engines/fullpipe/sound.cpp b/engines/fullpipe/sound.cpp index 230d6c39a9..c82c2c414c 100644 --- a/engines/fullpipe/sound.cpp +++ b/engines/fullpipe/sound.cpp @@ -30,6 +30,7 @@  #include "fullpipe/statics.h"  #include "common/memstream.h" +#include "audio/mixer.h"  #include "audio/audiostream.h"  #include "audio/decoders/vorbis.h"  #include "audio/decoders/wave.h" @@ -96,12 +97,13 @@ Sound::Sound() {  	memset(_directSoundBuffers, 0, sizeof(_directSoundBuffers));  	_description = 0;  	_volume = 100; +	_handle = new Audio::SoundHandle();  }  Sound::~Sound() {  	freeSound(); -  	free(_description); +	delete _handle;  }  bool Sound::load(MfcArchive &file, NGIArchive *archive) { @@ -206,14 +208,14 @@ void Sound::setPanAndVolumeByStaticAni() {  }  void Sound::setPanAndVolume(int vol, int pan) { -	g_fp->_mixer->setChannelVolume(_handle, vol / 39); // 0..10000 -	g_fp->_mixer->setChannelBalance(_handle, pan / 78); // -10000..10000 +	g_fp->_mixer->setChannelVolume(*_handle, vol / 39); // 0..10000 +	g_fp->_mixer->setChannelBalance(*_handle, pan / 78); // -10000..10000  }  void Sound::play(int flag) { -	Audio::SoundHandle handle = getHandle(); +	Audio::SoundHandle *handle = getHandle(); -	if (g_fp->_mixer->isSoundHandleActive(handle)) +	if (g_fp->_mixer->isSoundHandleActive(*handle))  		return;  	byte *soundData = loadData(); @@ -221,7 +223,7 @@ void Sound::play(int flag) {  	Audio::RewindableAudioStream *wav = Audio::makeWAVStream(dataStream, DisposeAfterUse::YES);  	Audio::AudioStream *audioStream = new Audio::LoopingAudioStream(wav, (flag == 1) ? 0 : 1); -	g_fp->_mixer->playStream(Audio::Mixer::kSFXSoundType, &handle, audioStream); +	g_fp->_mixer->playStream(Audio::Mixer::kSFXSoundType, handle, audioStream);  }  void Sound::freeSound() { @@ -231,11 +233,11 @@ void Sound::freeSound() {  }  int Sound::getVolume() { -	return g_fp->_mixer->getChannelVolume(_handle) * 39;  // 0..10000 +	return g_fp->_mixer->getChannelVolume(*_handle) * 39;  // 0..10000  }  void Sound::stop() { -	g_fp->_mixer->stopHandle(_handle); +	g_fp->_mixer->stopHandle(*_handle);  }  void FullpipeEngine::setSceneMusicParameters(GameVar *gvar) { @@ -353,7 +355,7 @@ void FullpipeEngine::startSoundStream1(char *trackName) {  	stopAllSoundStreams();  #ifdef USE_VORBIS -	if (_mixer->isSoundHandleActive(_sceneTrackHandle)) +	if (_mixer->isSoundHandleActive(*_sceneTrackHandle))  		return;  	Common::File *track = new Common::File(); @@ -363,7 +365,7 @@ void FullpipeEngine::startSoundStream1(char *trackName) {  		return;  	}  	Audio::RewindableAudioStream *ogg = Audio::makeVorbisStream(track, DisposeAfterUse::YES); -	_mixer->playStream(Audio::Mixer::kMusicSoundType, &_sceneTrackHandle, ogg); +	_mixer->playStream(Audio::Mixer::kMusicSoundType, _sceneTrackHandle, ogg);  #endif  } diff --git a/engines/fullpipe/sound.h b/engines/fullpipe/sound.h index 14e766f5bb..983f28312b 100644 --- a/engines/fullpipe/sound.h +++ b/engines/fullpipe/sound.h @@ -23,6 +23,10 @@  #ifndef FULLPIPE_SOUND_H  #define FULLPIPE_SOUND_H +namespace Audio { +class SoundHandle; +} +  namespace Fullpipe {  class Sound : public MemoryObject { @@ -31,7 +35,7 @@ class Sound : public MemoryObject {  	int _directSoundBuffer;  	int _directSoundBuffers[7];  	byte *_soundData; -	Audio::SoundHandle _handle; +	Audio::SoundHandle *_handle;  	int _volume;  public: @@ -45,7 +49,7 @@ public:  	virtual bool load(MfcArchive &file) { assert(0); return false; } // Disable base class  	void updateVolume();  	int getId() const { return _id; } -	Audio::SoundHandle getHandle() const { return _handle; } +	Audio::SoundHandle *getHandle() const { return _handle; }  	void play(int flag);  	void freeSound(); diff --git a/engines/fullpipe/statics.cpp b/engines/fullpipe/statics.cpp index 8ee3b14d0c..36fbb73037 100644 --- a/engines/fullpipe/statics.cpp +++ b/engines/fullpipe/statics.cpp @@ -1576,6 +1576,9 @@ Movement::Movement(Movement *src, int *oldIdxs, int newSize, StaticANIObject *an  	_m2x = 0;  	_m2y = 0; +	_counter = 0; +	_counterMax = 0; +  	_field_78 = 0;  	_framePosOffsets = 0;  	_field_84 = 0; diff --git a/engines/lastexpress/sound/entry.cpp b/engines/lastexpress/sound/entry.cpp index 697e6e1269..7308214551 100644 --- a/engines/lastexpress/sound/entry.cpp +++ b/engines/lastexpress/sound/entry.cpp @@ -366,7 +366,7 @@ void SoundEntry::saveLoadWithSerializer(Common::Serializer &s) {  	assert(_name1.size() <= 16);  	assert(_name2.size() <= 16); -	if (_name2.matchString("NISSND?") && (_status.status & kFlagType9) != kFlag3) { +	if (_name2.matchString("NISSND?") && ((_status.status & kFlagType9) != kFlag3)) {  		s.syncAsUint32LE(_status.status);  		s.syncAsUint32LE(_type);  		s.syncAsUint32LE(_blockCount); // field_8; diff --git a/engines/made/database.cpp b/engines/made/database.cpp index 3eab31acc2..0020cb398c 100644 --- a/engines/made/database.cpp +++ b/engines/made/database.cpp @@ -40,6 +40,7 @@ namespace Made {  */  Object::Object() : _objData(NULL), _freeData(false) { +	_objSize = 0;  }  Object::~Object() { diff --git a/engines/made/made.cpp b/engines/made/made.cpp index f1539297ee..a29aa2512f 100644 --- a/engines/made/made.cpp +++ b/engines/made/made.cpp @@ -58,11 +58,24 @@ MadeEngine::MadeEngine(OSystem *syst, const MadeGameDescription *gameDesc) : Eng  	const GameSettings *g; +	_eventNum = 0; +	_eventMouseX = _eventMouseY = 0; +	_eventKey = 0; +	_autoStopSound = false; +	_soundEnergyIndex = 0; +	_soundEnergyArray = 0; +	_musicBeatStart = 0; +	_cdTimeStart = 0; + +	_gameId = -1; +  	const char *gameid = ConfMan.get("gameid").c_str();  	for (g = madeSettings; g->gameid; ++g)  		if (!scumm_stricmp(g->gameid, gameid))  			_gameId = g->id; +	assert(_gameId != -1); +  	_rnd = new Common::RandomSource("made");  	_console = new MadeConsole(this); @@ -85,6 +98,8 @@ MadeEngine::MadeEngine(OSystem *syst, const MadeGameDescription *gameDesc) : Eng  	_music = nullptr; +	_soundRate = 0; +  	// Set default sound frequency  	switch (getGameID()) {  	case GID_RODNEY: diff --git a/engines/made/pmvplayer.cpp b/engines/made/pmvplayer.cpp index 453e2a4872..0beb132b93 100644 --- a/engines/made/pmvplayer.cpp +++ b/engines/made/pmvplayer.cpp @@ -223,7 +223,10 @@ bool PmvPlayer::play(const char *filename) {  	//delete _audioStream;  	delete _fd; -	_surface->free(); + +	if(_surface) +		_surface->free(); +  	delete _surface;  	return !_aborted; diff --git a/engines/made/redreader.cpp b/engines/made/redreader.cpp index f92ffd8dd8..a0aaf7be43 100644 --- a/engines/made/redreader.cpp +++ b/engines/made/redreader.cpp @@ -102,7 +102,7 @@ int LzhDecompressor::decompress(Common::SeekableReadStream &source, byte *dest,  	int bufsize;  	byte* buffer; -	buffer = (byte *) malloc(DICSIZ); +	buffer = (byte *)calloc(DICSIZ, 1);  	_source = &source;  	_compSize = sourceLen; diff --git a/engines/made/resource.cpp b/engines/made/resource.cpp index f8e763e74e..a9734ed47d 100644 --- a/engines/made/resource.cpp +++ b/engines/made/resource.cpp @@ -43,6 +43,7 @@ Resource::~Resource() {  PictureResource::PictureResource() : _picture(NULL), _picturePalette(NULL) {  	_hasPalette = false; +	_paletteColorCount = 0;  }  PictureResource::~PictureResource() { @@ -182,6 +183,9 @@ void PictureResource::loadChunked(byte *source, int size) {  /* AnimationResource */  AnimationResource::AnimationResource() { +	_flags = 0; +	_width = 0; +	_height = 0;  }  AnimationResource::~AnimationResource() { diff --git a/engines/made/screen.cpp b/engines/made/screen.cpp index edccb68953..33edb3834c 100644 --- a/engines/made/screen.cpp +++ b/engines/made/screen.cpp @@ -91,6 +91,8 @@ Screen::Screen(MadeEngine *vm) : _vm(vm) {  	_currentFontNum = 0;  	_fontDrawCtx.clipRect = Common::Rect(320, 200);  	_fontDrawCtx.destSurface = _backgroundScreen; +	_outlineColor = 0; +	_dropShadowColor = 0;  	clearChannels();  } diff --git a/engines/made/sound.cpp b/engines/made/sound.cpp index ad49031e7b..62559efa84 100644 --- a/engines/made/sound.cpp +++ b/engines/made/sound.cpp @@ -155,6 +155,7 @@ void decompressSound(byte *source, byte *dest, uint16 chunkSize, uint16 chunkCou  	};  	soundEnergyItem.position = 0; +	memset(deltaSoundBuffer, 0, 1024);  	if (soundEnergyArray)  		soundEnergyArray->clear(); @@ -237,6 +238,7 @@ void decompressSound(byte *source, byte *dest, uint16 chunkSize, uint16 chunkCou  			break;  		default: +			delete[] soundBuffer;  			return;  		} @@ -247,6 +249,9 @@ void decompressSound(byte *source, byte *dest, uint16 chunkSize, uint16 chunkCou  			// soundBuffer.  			soundBuffer[workChunkSize] = soundBuffer[workChunkSize - 1]; +			for (i = 0; i < chunkSize; i++) +				soundBuffer[i] = 0; +  			if (deltaType == 1) {  				for (i = 0; i < chunkSize - 1; i += 2) {  					l = i / 2; diff --git a/engines/mads/mads.cpp b/engines/mads/mads.cpp index 29bcd10094..5776d813cf 100644 --- a/engines/mads/mads.cpp +++ b/engines/mads/mads.cpp @@ -58,6 +58,7 @@ MADSEngine::MADSEngine(OSystem *syst, const MADSGameDescription *gameDesc) :  	_resources = nullptr;  	_sound = nullptr;  	_audio = nullptr; +	_screen = nullptr;  }  MADSEngine::~MADSEngine() { diff --git a/engines/mads/menu_views.h b/engines/mads/menu_views.h index c203248ad9..e22b6223a7 100644 --- a/engines/mads/menu_views.h +++ b/engines/mads/menu_views.h @@ -8,20 +8,12 @@   * 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. -<<<<<<< HEAD - -=======   * ->>>>>>> master   * 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. -<<<<<<< HEAD - -=======   * ->>>>>>> master   * 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. diff --git a/engines/mohawk/myst.cpp b/engines/mohawk/myst.cpp index e2bc88ebf6..633b67f7e9 100644 --- a/engines/mohawk/myst.cpp +++ b/engines/mohawk/myst.cpp @@ -604,7 +604,8 @@ void MohawkEngine_Myst::changeToCard(uint16 card, TransitionType transition) {  			_gfx->runTransition(transition, Common::Rect(544, 333), 10, 0);  		} else {  			_gfx->copyBackBufferToScreen(Common::Rect(544, 333)); -			_needsUpdate = true; +			_system->updateScreen(); +			_needsUpdate = false;  		}  	} diff --git a/engines/mortevielle/mortevielle.cpp b/engines/mortevielle/mortevielle.cpp index 90d366ed7e..81b2edb57d 100644 --- a/engines/mortevielle/mortevielle.cpp +++ b/engines/mortevielle/mortevielle.cpp @@ -145,6 +145,7 @@ MortevielleEngine::MortevielleEngine(OSystem *system, const MortevielleGameDescr  	_endGame = false;  	_loseGame = false;  	_txxFileFl = false; +	_is = 0;  }  MortevielleEngine::~MortevielleEngine() { diff --git a/engines/parallaction/objects.cpp b/engines/parallaction/objects.cpp index 50a5b38d8d..8f895f1532 100644 --- a/engines/parallaction/objects.cpp +++ b/engines/parallaction/objects.cpp @@ -163,7 +163,7 @@ int16 Program::findLocal(const char* name) {  int16 Program::addLocal(const char *name, int16 value, int16 min, int16 max) {  	assert(_numLocals < NUM_LOCALS); -	strcpy(_localNames[_numLocals], name); +	Common::strlcpy(_localNames[_numLocals], name, 10);  	_locals[_numLocals].setRange(min, max);  	_locals[_numLocals].setValue(value); diff --git a/engines/parallaction/parallaction.cpp b/engines/parallaction/parallaction.cpp index 2b75e78582..bbe759dffe 100644 --- a/engines/parallaction/parallaction.cpp +++ b/engines/parallaction/parallaction.cpp @@ -60,6 +60,7 @@ Parallaction::Parallaction(OSystem *syst, const PARALLACTIONGameDescription *gam  	DebugMan.addDebugChannel(kDebugMenu, "menu", "Menu debug level");  	DebugMan.addDebugChannel(kDebugInventory, "inventory", "Inventory debug level"); +	_screenWidth = 0;  	_screenHeight = 0;  	_screenSize = 0;  	_gameType = 0; @@ -86,6 +87,7 @@ Parallaction::Parallaction(OSystem *syst, const PARALLACTIONGameDescription *gam  	_inventory = 0;  	_currentLocationIndex = 0;  	_numLocations = 0; +	_language = 0;  }  Parallaction::~Parallaction() { @@ -208,7 +210,7 @@ void Parallaction::allocateLocationSlot(const char *name) {  		error("No more location slots available. Please report this immediately to ScummVM team");  	if (_currentLocationIndex  == -1) { -		strcpy(_locationNames[_numLocations], name); +		Common::strlcpy(_locationNames[_numLocations], name, 10);  		_currentLocationIndex = _numLocations;  		_numLocations++; diff --git a/engines/parallaction/parallaction_br.cpp b/engines/parallaction/parallaction_br.cpp index 1e1c0b0a3d..9f045cb397 100644 --- a/engines/parallaction/parallaction_br.cpp +++ b/engines/parallaction/parallaction_br.cpp @@ -320,7 +320,7 @@ void Parallaction_br::changeLocation() {  	freeLocation(false);  	// load new location -	strcpy(_location._name, _newLocationName.c_str()); +	Common::strlcpy(_location._name, _newLocationName.c_str(), 100);  	parseLocation(_location._name);  	if (_location._startPosition.x != -1000) { diff --git a/engines/saga/isomap.cpp b/engines/saga/isomap.cpp index 77680178c1..e50378b9c0 100644 --- a/engines/saga/isomap.cpp +++ b/engines/saga/isomap.cpp @@ -97,6 +97,23 @@ IsoMap::IsoMap(SagaEngine *vm) : _vm(vm) {  	_viewScroll.x = (128 - 8) * 16;  	_viewScroll.y = (128 - 8) * 16 - 64;  	_viewDiff = 1; +	_platformHeight = 0; +	_queueCount = _readCount = 0; + +	for (int i = 0; i < SAGA_DRAGON_SEARCH_DIAMETER; i++) +		for (int j = 0; j < SAGA_DRAGON_SEARCH_DIAMETER; j++) +			_dragonSearchArray.cell[i][j].visited = _dragonSearchArray.cell[i][j].direction = 0; + +	for (int i = 0; i < SAGA_SEARCH_DIAMETER; i++) +		for (int j = 0; j < SAGA_SEARCH_DIAMETER; j++) +			_searchArray.cell[i][j].visited = _searchArray.cell[i][j].direction = 0; + +	for (int i = 0; i < SAGA_SEARCH_QUEUE_SIZE; i++) { +		memset(&_dragonSearchArray.queue[i], 0, sizeof(DragonTilePoint)); +		memset(&_searchArray.queue[i], 0, sizeof(TilePoint)); +	} + +	memset(&_tileMap, 0, sizeof(TileMapData));  }  void IsoMap::loadImages(const ByteArray &resourceData) { diff --git a/engines/saga/puzzle.cpp b/engines/saga/puzzle.cpp index 099bf79e6b..2c9a02beec 100644 --- a/engines/saga/puzzle.cpp +++ b/engines/saga/puzzle.cpp @@ -86,6 +86,11 @@ Puzzle::Puzzle(SagaEngine *vm) : _vm(vm), _solved(false), _active(false) {  	_hintBox.setWidth(240);  	_hintBox.setHeight(30); +	_hintNextRqState = kRQNoHint; +	_hintGiver = 0; +	_hintSpeaker = 0; +	_slidePointX = _slidePointY = 0; +  	initPieceInfo( 0, 268,  18,  0, 0,  0 + PUZZLE_X_OFFSET,   0 + PUZZLE_Y_OFFSET, 0, 3,  		  Point(0, 1),  Point(0, 62), Point(15, 31), Point(0, 0), Point(0, 0), Point(0,0));  	initPieceInfo( 1, 270,  52,  0, 0,  0 + PUZZLE_X_OFFSET,  32 + PUZZLE_Y_OFFSET, 0, 4, diff --git a/engines/saga/saveload.cpp b/engines/saga/saveload.cpp index e659e09ce8..2d798bb0d6 100644 --- a/engines/saga/saveload.cpp +++ b/engines/saga/saveload.cpp @@ -56,7 +56,7 @@ SaveFileData *SagaEngine::getSaveFile(uint idx) {  		return &_saveFiles[_saveFilesCount - idx - 1];  	} else {  		if (!emptySlot.name[0]) -			strcpy(emptySlot.name, getTextString(kTextNewSave)); +			Common::strlcpy(emptySlot.name, getTextString(kTextNewSave), SAVE_TITLE_SIZE);  		return (idx == 0) ? &emptySlot : &_saveFiles[_saveFilesCount - idx];  	} diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h index 2f6ca167a0..c01613268a 100644 --- a/engines/sci/detection_tables.h +++ b/engines/sci/detection_tables.h @@ -4356,6 +4356,16 @@ static const struct ADGameDescription SciGameDescriptions[] = {  		AD_LISTEND},  		Common::FR_FRA, Common::kPlatformWindows, ADGF_UNSTABLE | ADGF_CD, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI)	}, +	// Torin's Passage - Russian Windows CD (SoftClub official translate) +	// SCI interpreter version 2.100.002 +	// VERSION file "1.0" +	{ "torin", "",{ +		{ "resource.aud", 0, "f66df699be5ed011b16b3f816cee8a04", 210583510 }, +		{ "ressci.000", 0, "e672da099fb1663b87c78abc6c8ba2a4", 130622695 }, +		{ "resmap.000", 0, "643859f8f2be8e7701611e29b3b65208", 9799 }, +	AD_LISTEND }, +	Common::RU_RUS, Common::kPlatformWindows, ADGF_UNSTABLE | ADGF_CD, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, +  	// Torin's Passage - English Macintosh  	{"torin", "", {  		{"Data1", 0, "63887e33cc282c92dc1f916f54aea8eb", 700786}, diff --git a/engines/scumm/detection_tables.h b/engines/scumm/detection_tables.h index 5a994cb699..bb3e7f6ec3 100644 --- a/engines/scumm/detection_tables.h +++ b/engines/scumm/detection_tables.h @@ -245,9 +245,11 @@ static const GameSettings gameVariantsTable[] = {  	{"monkey", "CD",           0, GID_MONKEY,     5, 0, MDT_ADLIB,                        GF_AUDIOTRACKS, UNK, GUIO2(GUIO_NOSPEECH, GUIO_NOMIDI)},  	{"monkey", "FM-TOWNS",     0, GID_MONKEY,     5, 0, MDT_TOWNS,                        GF_AUDIOTRACKS, Common::kPlatformFMTowns, GUIO4(GUIO_NOSPEECH, GUIO_NOMIDI, GUIO_MIDITOWNS, GUIO_NOASPECT)},  	{"monkey", "SEGA",         0, GID_MONKEY,     5, 0, MDT_NONE,                         GF_AUDIOTRACKS, Common::kPlatformSegaCD, GUIO2(GUIO_NOSPEECH, GUIO_NOMIDI)}, +	{"monkey", "SE Talkie",    0, GID_MONKEY,     5, 0, MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32, GF_AUDIOTRACKS, UNK, GUIO0()},  	{"monkey2",  "", 0, GID_MONKEY2,  5, 0, MDT_PCSPK | MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32, 0, UNK, GUIO1(GUIO_NOSPEECH)},  	{"monkey2", "FM-TOWNS", 0, GID_MONKEY2,  5, 0, MDT_PCSPK | MDT_TOWNS | MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32, 0, Common::kPlatformFMTowns, GUIO5(GUIO_NOSPEECH, GUIO_MIDITOWNS, GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_NOASPECT)}, +	{"monkey2", "SE Talkie",0, GID_MONKEY2,  5, 0, MDT_PCSPK | MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32, 0, UNK, GUIO0()},  	{"atlantis", "", 0, GID_INDY4,    5, 0, MDT_PCSPK | MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32, 0, UNK, GUIO0()},  	{"atlantis", "Steam", "steam", GID_INDY4,    5, 0, MDT_PCSPK | MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32, 0, UNK, GUIO0()}, diff --git a/engines/scumm/he/intern_he.h b/engines/scumm/he/intern_he.h index 370f54c1d8..51d9a9045f 100644 --- a/engines/scumm/he/intern_he.h +++ b/engines/scumm/he/intern_he.h @@ -27,6 +27,8 @@  #ifdef ENABLE_HE  #include "scumm/he/floodfill_he.h"  #include "scumm/he/wiz_he.h" + +#include "scumm/he/moonbase/moonbase.h"  #endif  #include "scumm/actor_he.h"	// For AuxBlock & AuxEntry @@ -186,6 +188,7 @@ protected:  #ifdef ENABLE_HE  class ScummEngine_v71he : public ScummEngine_v70he {  	friend class Wiz; +	friend class Moonbase;  protected:  	bool _skipProcessActors; @@ -244,6 +247,10 @@ public:  	void queueAuxEntry(int actorNum, int subIndex);  	void remapHEPalette(const uint8 *src, uint8 *dst); + +public: +	/* Moonbase stuff */ +	Moonbase *_moonbase;  };  class ScummEngine_v72he : public ScummEngine_v71he { diff --git a/engines/scumm/he/logic/moonbase.cpp b/engines/scumm/he/logic/moonbase.cpp deleted file mode 100644 index 29a0dde7a2..0000000000 --- a/engines/scumm/he/logic/moonbase.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#include "scumm/he/intern_he.h" -#include "scumm/he/logic_he.h" - -namespace Scumm { - -/** - * Logic code for: - *     Moonbase Commander - */ -class LogicHEmoonbase : public LogicHE { -public: -	LogicHEmoonbase(ScummEngine_v90he *vm) : LogicHE(vm) {} - -	int versionID(); -}; - -int LogicHEmoonbase::versionID() { -	if (_vm->_game.features & GF_DEMO) -		return -100; -	else if (strcmp(_vm->_game.variant, "1.1") == 0) -		return 110; -	else -		return 100; -} - -LogicHE *makeLogicHEmoonbase(ScummEngine_v90he *vm) { -	return new LogicHEmoonbase(vm); -} - -} // End of namespace Scumm diff --git a/engines/scumm/he/logic/moonbase_logic.cpp b/engines/scumm/he/logic/moonbase_logic.cpp new file mode 100644 index 0000000000..5f02fa9cd4 --- /dev/null +++ b/engines/scumm/he/logic/moonbase_logic.cpp @@ -0,0 +1,231 @@ +/* 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. + * + */ + +#include "scumm/he/intern_he.h" +#include "scumm/he/logic_he.h" + +namespace Scumm { + +/** + * Logic code for: + *     Moonbase Commander + */ +class LogicHEmoonbase : public LogicHE { +public: +	LogicHEmoonbase(ScummEngine_v90he *vm) : LogicHE(vm) {} + +	int versionID(); + +	int32 dispatch(int op, int numArgs, int32 *args); + +private: +	void op_create_multi_state_wiz(int op, int numArgs, int32 *args); +	void op_load_multi_channel_wiz(int op, int numArgs, int32 *args); +	void op_wiz_from_multi_channel_wiz(int op, int numArgs, int32 *args); +	void op_dos_command(int op, int numArgs, int32 *args); +	void op_set_fow_sentinel(int32 *args); +	void op_set_fow_information(int op, int numArgs, int32 *args); +	void op_set_fow_image(int op, int numArgs, int32 *args); + +	void op_ai_test_kludge(int op, int numArgs, int32 *args); +	void op_ai_master_control_program(int op, int numArgs, int32 *args); +	void op_ai_reset(int op, int numArgs, int32 *args); +	void op_ai_set_type(int op, int numArgs, int32 *args); +	void op_ai_clean_up(int op, int numArgs, int32 *args); +}; + +int LogicHEmoonbase::versionID() { +	if (_vm->_game.features & GF_DEMO) +		return -100; +	else if (strcmp(_vm->_game.variant, "1.1") == 0) +		return 110; +	else +		return 100; +} + +#define OP_CREATE_MULTI_STATE_WIZ		100 +#define OP_LOAD_MULTI_CHANNEL_WIZ		101 +#define OP_WIZ_FROM_MULTI_CHANNEL_WIZ	102 +#define OP_DOS_COMMAND					103 +#define OP_SET_FOW_SENTINEL				104 +#define OP_SET_FOW_INFORMATION			105 +#define OP_SET_FOW_IMAGE				106 + +#define OP_AI_TEST_KLUDGE				10000 +#define OP_AI_MASTER_CONTROL_PROGRAM	10001 +#define OP_AI_RESET						10002 +#define OP_AI_SET_TYPE					10003 +#define OP_AI_CLEAN_UP					10004 + +#define OP_NET_REMOTE_START_SCRIPT			1492 +#define OP_NET_DO_INIT_ALL					1493 +#define OP_NET_DO_INIT_PROVIDER				1494 +#define OP_NET_DO_INIT_SESSION				1495 +#define OP_NET_DO_INIT_USER					1496 +#define OP_NET_QUERY_PROVIDERS				1497 +#define OP_NET_GET_PROVIDER_NAME			1498 +#define OP_NET_SET_PROVIDER					1499 +#define OP_NET_CLOSE_PROVIDER				1500 +#define OP_NET_QUERY_SESSIONS				1501 +#define OP_NET_GET_SESSION_NAME				1502 +#define OP_NET_CREATE_SESSION				1503 +#define OP_NET_JOIN_SESSION					1504 +#define OP_NET_END_SESSION					1505 +#define OP_NET_ADD_USER						1506 +#define OP_NET_REMOVE_USER					1507 +#define OP_NET_WHO_SENT_THIS				1508 +#define OP_NET_REMOTE_SEND_ARRAY			1509 +#define OP_NET_WHO_AM_I						1510 +#define OP_NET_REMOTE_START_FUNCTION		1511 +#define OP_NET_GET_PLAYER_LONG_NAME			1512 +#define OP_NET_GET_PLAYER_SHORT_NAME		1513 +#define OP_NET_SET_PROVIDER_BY_NAME			1516 +#define OP_NET_HOST_TCPIP_GAME				1517 +#define OP_NET_JOIN_TCPIP_GAME				1518 +#define OP_NET_SET_FAKE_LAG					1555 +#define OP_NET_GET_HOST_NAME				1556 +#define OP_NET_GET_IP_FROM_NAME				1557 +#define OP_NET_GET_SESSION_PLAYER_COUNT		1558 +#define OP_NET_DISABLE_SESSION_PLAYER_JOIN	1559 +#define OP_NET_START_QUERY_SESSIONS			1560 +#define OP_NET_UPDATE_QUERY_SESSIONS		1561 +#define OP_NET_STOP_QUERY_SESSIONS			1562 +#define OP_NET_DESTROY_PLAYER				1563 +#define OP_NET_ENABLE_SESSION_PLAYER_JOIN	1564 +#define OP_NET_SET_AI_PLAYER_COUNT			1565 + + +int32 LogicHEmoonbase::dispatch(int op, int numArgs, int32 *args) { +	switch (op) { +	case OP_CREATE_MULTI_STATE_WIZ: +		op_create_multi_state_wiz(op, numArgs, args); +		break; +	case OP_LOAD_MULTI_CHANNEL_WIZ: +		op_load_multi_channel_wiz(op, numArgs, args); +		break; +	case OP_WIZ_FROM_MULTI_CHANNEL_WIZ: +		op_wiz_from_multi_channel_wiz(op, numArgs, args); +		break; +	case OP_DOS_COMMAND: +		op_dos_command(op, numArgs, args); +		break; +	case OP_SET_FOW_SENTINEL: +		op_set_fow_sentinel(args); +		break; +	case OP_SET_FOW_INFORMATION: +		op_set_fow_information(op, numArgs, args); +		break; +	case OP_SET_FOW_IMAGE: +		op_set_fow_image(op, numArgs, args); +		break; + +	case OP_AI_TEST_KLUDGE: +		op_ai_test_kludge(op, numArgs, args); +		break; +	case OP_AI_MASTER_CONTROL_PROGRAM: +		op_ai_master_control_program(op, numArgs, args); +		break; +	case OP_AI_RESET: +		op_ai_reset(op, numArgs, args); +		break; +	case OP_AI_SET_TYPE: +		op_ai_set_type(op, numArgs, args); +		break; +	case OP_AI_CLEAN_UP: +		op_ai_clean_up(op, numArgs, args); +		break; + +	default: +		LogicHE::dispatch(op, numArgs, args); +	} + +	return 0; +} + +void LogicHEmoonbase::op_create_multi_state_wiz(int op, int numArgs, int32 *args) { +	warning("STUB: op_create_multi_state_wiz()"); +	LogicHE::dispatch(op, numArgs, args); +} + +void LogicHEmoonbase::op_load_multi_channel_wiz(int op, int numArgs, int32 *args) { +	warning("STUB: op_load_multi_channel_wiz()"); +	LogicHE::dispatch(op, numArgs, args); +} + +void LogicHEmoonbase::op_wiz_from_multi_channel_wiz(int op, int numArgs, int32 *args) { +	warning("STUB: op_wiz_from_multi_channel_wiz()"); +	LogicHE::dispatch(op, numArgs, args); +} + +void LogicHEmoonbase::op_dos_command(int op, int numArgs, int32 *args) { +	warning("STUB: op_dos_command()"); +	LogicHE::dispatch(op, numArgs, args); +} + +void LogicHEmoonbase::op_set_fow_sentinel(int32 *args) { +	debug(2, "op_set_fow_sentinel(%d, %d, %d)", args[0], args[1], args[2]); + +	_vm->_moonbase->_fowSentinelImage = args[0]; +	_vm->_moonbase->_fowSentinelState = args[1]; +	_vm->_moonbase->_fowSentinelConditionBits = args[2]; +} + +void LogicHEmoonbase::op_set_fow_information(int op, int numArgs, int32 *args) { +	warning("STUB: op_set_fow_information()"); +	LogicHE::dispatch(op, numArgs, args); +} + +void LogicHEmoonbase::op_set_fow_image(int op, int numArgs, int32 *args) { +	warning("STUB: op_set_fow_image()"); +	LogicHE::dispatch(op, numArgs, args); +} + +void LogicHEmoonbase::op_ai_test_kludge(int op, int numArgs, int32 *args) { +	warning("STUB: op_ai_test_kludge()"); +	LogicHE::dispatch(op, numArgs, args); +} + +void LogicHEmoonbase::op_ai_master_control_program(int op, int numArgs, int32 *args) { +	warning("STUB: op_ai_master_control_program()"); +	LogicHE::dispatch(op, numArgs, args); +} + +void LogicHEmoonbase::op_ai_reset(int op, int numArgs, int32 *args) { +	warning("STUB: op_ai_reset)"); +	LogicHE::dispatch(op, numArgs, args); +} + +void LogicHEmoonbase::op_ai_set_type(int op, int numArgs, int32 *args) { +	warning("STUB: op_ai_set_type()"); +	LogicHE::dispatch(op, numArgs, args); +} + +void LogicHEmoonbase::op_ai_clean_up(int op, int numArgs, int32 *args) { +	warning("STUB: op_ai_clean_up()"); +	LogicHE::dispatch(op, numArgs, args); +} + +LogicHE *makeLogicHEmoonbase(ScummEngine_v90he *vm) { +	return new LogicHEmoonbase(vm); +} + +} // End of namespace Scumm diff --git a/engines/scumm/he/moonbase/moonbase.cpp b/engines/scumm/he/moonbase/moonbase.cpp new file mode 100644 index 0000000000..a07a874b48 --- /dev/null +++ b/engines/scumm/he/moonbase/moonbase.cpp @@ -0,0 +1,154 @@ +/* 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. + * + */ + +#include "scumm/he/intern_he.h" + +namespace Scumm { + +Moonbase::Moonbase(ScummEngine_v71he *vm) : _vm(vm) { +	initFOW(); +} + +Moonbase::~Moonbase() { +} + +void Moonbase::blitT14WizImage(uint8 *dst, int dstw, int dsth, int dstPitch, const Common::Rect *clipBox, +		 uint8 *wizd, int x, int y, int rawROP, int paramROP) { + +	Common::Rect clippedDstRect(dstw, dsth); +	if (clipBox) { +		Common::Rect clip(clipBox->left, clipBox->top, clipBox->right, clipBox->bottom); +		if (clippedDstRect.intersects(clip)) { +			clippedDstRect.clip(clip); +		} else { +			return; +		} +	} + +	int width = READ_LE_UINT16(wizd + 0x8 + 0); +	int height = READ_LE_UINT16(wizd + 0x8 + 2); + +	Common::Rect srcLimitsRect(width, height); +	Common::Rect dstOperation(x, y, x + width, y + height); +	if (!clippedDstRect.intersects(dstOperation)) +		return; +	Common::Rect clippedRect = clippedDstRect.findIntersectingRect(dstOperation); + +	int cx = clippedRect.right - clippedRect.left; +	int cy = clippedRect.bottom - clippedRect.top; + +	int sx = ((clippedRect.left - x) + srcLimitsRect.left); +	int sy = ((clippedRect.top - y) + srcLimitsRect.top); + +	dst += clippedRect.top * dstPitch + clippedRect.left * 2; + +	int headerSize = READ_LE_UINT32(wizd + 0x4); +	uint8 *dataPointer = wizd + 0x8 + headerSize; + +	for (int i = 0; i < sy; i++) { +		uint16 lineSize = READ_LE_UINT16(dataPointer + 0); + +		dataPointer += lineSize; +	} + +	for (int i = 0; i < cy; i++) { +		uint16 lineSize      = READ_LE_UINT16(dataPointer + 0); +		uint8 *singlesOffset = READ_LE_UINT16(dataPointer + 2) + dataPointer; +		uint8 *quadsOffset   = READ_LE_UINT16(dataPointer + 4) + dataPointer; + +		int pixels = 0; +		byte *dst1 = dst; +		byte *codes = dataPointer + 6; + +		while (1) { +			int code = *codes - 2; +			codes++; + +			if (code == 0) { // quad +				for (int c = 0; c < 4; c++) { +					if (pixels >= sx) { +						WRITE_LE_UINT16(dst1, READ_LE_UINT16(quadsOffset)); +						dst1 += 2; +					} +					quadsOffset += 2; +					pixels++; +				} +			} else if (code < 0) { // single +				if (pixels >= sx) { +					WRITE_LE_UINT16(dst1, READ_LE_UINT16(singlesOffset)); +					dst1 += 2; +				} +				singlesOffset += 2; +				pixels++; +			} else { // skip +				if ((code & 1) == 0) { +					code >>= 1; + +					for (int j = 0; j < code; j++) { +						if (pixels >= sx) +							dst1 += 2; +						pixels++; +					} +				} else { // special case +					if (pixels >= sx) { +						int alpha = code >> 1; +						uint16 color = READ_LE_UINT16(singlesOffset); +						uint32 orig = READ_LE_UINT16(dst1); + +						//WRITE_LE_UINT16(dst1, color); // ENABLE_PREMUL_ALPHA = 0 +						// ENABLE_PREMUL_ALPHA = 2 +						if (alpha > 32) { +							alpha -= 32; + +							uint32 oR = orig & 0x7c00; +							uint32 oG = orig & 0x03e0; +							uint32 oB = orig & 0x1f; +							uint32 dR = ((((color & 0x7c00) - oR) * alpha) >> 5) + oR; +							uint32 dG = ((((color &  0x3e0) - oG) * alpha) >> 5) + oG; +							uint32 dB = ((((color &   0x1f) - oB) * alpha) >> 5) + oB; + +							WRITE_LE_UINT16(dst1, (dR & 0x7c00) | (dG & 0x3e0) | (dB & 0x1f)); +						} else { +							uint32 pix = ((orig << 16) | orig) & 0x3e07c1f; +							pix = (((pix * alpha) & 0xffffffff) >> 5) & 0x3e07c1f; +							pix = ((pix << 16) + pix + color) & 0xffff; + +							WRITE_LE_UINT16(dst1, pix); +						} + +						dst1 += 2; +					} +					singlesOffset += 2; +					pixels++; +				} +			} + +			if (pixels >= cx + sx) +				break; +		} + +		dataPointer += lineSize; +		dst += dstPitch; +	} +} + +} // End of namespace Scumm diff --git a/engines/scumm/he/moonbase/moonbase.h b/engines/scumm/he/moonbase/moonbase.h new file mode 100644 index 0000000000..e50337ddeb --- /dev/null +++ b/engines/scumm/he/moonbase/moonbase.h @@ -0,0 +1,95 @@ +/* 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 SCUMM_HE_MOONBASE_H +#define SCUMM_HE_MOONBASE_H + +#ifdef ENABLE_HE + +namespace Scumm { + +class Moonbase { +public: +	Moonbase(ScummEngine_v71he *vm); +	~Moonbase(); + +	void blitT14WizImage(uint8 *dst, int dstw, int dsth, int dstPitch, const Common::Rect *clipBox, +			 uint8 *wizd, int srcx, int srcy, int rawROP, int paramROP); + +	// FOW Stuff +	void initFOW(); +	void releaseFOWResources(); + +	bool setFOWImage(int id); + +	void setFOWInfo(int fowInfoArray, int downDim, int acrossDim, int viewX, int viewY, int clipX1, +		int clipY1, int clipX2, int clipY2, int technique, int nFrame); + + +	void renderFOW(uint8 *destSurface, int dstPitch, int dstType, int dstw, int dsth, int flags); + +private: +	bool captureFOWImageFromLocation(void *src); +	int readFOWVisibilityArray(int array, int y, int x); +	void renderFOWState(uint8 *destSurface, int dstPitch, int dstType, int dstw, int dsth, int x, int y, int srcw, int srch, int state, int flags); + +public: +	int _fowSentinelImage; +	int _fowSentinelState; +	uint16 _fowSentinelConditionBits; + +private: +	ScummEngine_v71he *_vm; + +	int _fowFrameBaseNumber; +	int _fowAnimationFrames; +	int _fowCurrentFOWFrame; + +	int _fowTileW; +	int _fowTileH; + +	byte *_fowImage; +	int _fowClipX1; +	int _fowClipY1; +	int _fowClipX2; +	int _fowClipY2; + +	int _fowDrawX; +	int _fowDrawY; + +	int _fowVtx1; +	int _fowVty1; +	int _fowMvx; +	int _fowMvy; +	int _fowVw; +	int _fowVh; + +	bool _fowBlackMode; + +	int _fowRenderTable[32768]; +}; + +#endif + +} // End of namespace Scumm + +#endif diff --git a/engines/scumm/he/moonbase/moonbase_fow.cpp b/engines/scumm/he/moonbase/moonbase_fow.cpp new file mode 100644 index 0000000000..f76bebf89e --- /dev/null +++ b/engines/scumm/he/moonbase/moonbase_fow.cpp @@ -0,0 +1,435 @@ +/* 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. + * + */ + +#include "common/config-manager.h" +#include "scumm/he/intern_he.h" + +namespace Scumm { + +#define FOW_ANIM_FRAME_COUNT	38 + +void Moonbase::initFOW() { +	_fowSentinelImage = -1; +	_fowSentinelState = -1; +	_fowSentinelConditionBits = 0; + +	_fowFrameBaseNumber = 0; +	_fowAnimationFrames = 1; +	_fowCurrentFOWFrame = 0; + +	_fowTileW = 0; +	_fowTileH = 0; + +	_fowImage = nullptr; +	_fowClipX1 = 0; +	_fowClipY1 = 0; +	_fowClipX2 = 0; +	_fowClipY2 = 0; + +	_fowDrawX = 0; +	_fowDrawY = 0; + +	_fowVtx1 = 0; +	_fowVty1 = 0; +	_fowMvx = 0; +	_fowMvy = 0; +	_fowVw = 0; +	_fowVh = 0; + +	_fowBlackMode = true; + +	memset(_fowRenderTable, 0, 32768); +} + +void Moonbase::releaseFOWResources() { +	if (_fowImage) { +		free(_fowImage); +		_fowImage = 0; +	} +} + +bool Moonbase::captureFOWImageFromLocation(void *src) { +	if (!src) +		return false; + +	int imageDataSize = 0; //getMemoryBlockSize(src); // TODO + +	if (imageDataSize <= 0) +		return false; + +	_fowImage = (byte *)malloc(imageDataSize); + +	if (!_fowImage) +		return false; + +	memcpy(_fowImage, src, imageDataSize); + +	return true; +} + +bool Moonbase::setFOWImage(int image) { +	releaseFOWResources(); + +	if (!_fowImage) { +		Common::String fowImageFilename(ConfMan.get("MOONX_FOWImageFilename").c_str()); + +#if 0 // TODO +		if (!fowImageFilename.empty()) { +			void *wiz = loadWizFromFilename(fowImageFilename); + +			if (wiz) { +				captureFOWImageFromLocation(wiz); +				free(wiz); +			} +		} +#endif + +		if (!_fowImage && image < 0) { +			int resType; + +			// PIECES  BUBBLES CIRCLES SIMPLE*  WEDGEY BUBBLE2 +			// WEDGE2  SPIKEY  ANGLES  SMOOTHED WUZZY  SYS7-BEVELED +			if (image >= -1 && image <= 12) +				resType = 210 - image; // 211-222 range +			else +				resType = 214; // default, SIMPLE +#if 0 // TODO +			HRSRC hResource = FindResource(g_hInst, resType, 10); +			if (hResource) { +				byte res = LoadResource(g_hInst, hResource); + +				if (res) { +					uint16 nDataSize = SizeofResource(g_hInst, hResource); + +					if (nDataSize) +						captureFOWImageFromLocation(res); +				} +			} +#endif +		} + +		if (!_fowImage && image > 0) { +			void *glob = _vm->getResourceAddress(rtImage, image); + +			if (glob) +				captureFOWImageFromLocation(glob); +		} + +		if (!_fowImage) +			return false; +	} + +	int nStates = _vm->_wiz->getWizImageStates(_fowImage); + +	if (nStates > FOW_ANIM_FRAME_COUNT) { +		releaseFOWResources(); +		return false; +	} + +	_fowAnimationFrames = (nStates + FOW_ANIM_FRAME_COUNT - 1) / FOW_ANIM_FRAME_COUNT; + +	Common::Point fowTileSize(0, 0); //getWizStateSize(_fowImage, (nStates - 1)); // TODO + +	_fowTileW = fowTileSize.x; +	_fowTileH = fowTileSize.y; + +	int hitTestValue = 0; +	uint pixelValue = 0; + +	//LayeredWizHitTest(&hitTestValue, &pixelValue, _fowImage, (nStates - 1), 0, 0, 0, 0); // TODO +	_fowBlackMode = (pixelValue == 0) ? 1 : 0; + +	if (ConfMan.hasKey("EnableFOWRects")) +		_fowBlackMode = (ConfMan.getInt("EnableFOWRects") == 1); + +	return true; +} + +enum FOWElement { +	FOW_EMPTY	= 0, +	FOW_SOLID	= 1, + +	FF_L		= 0x01, +	FF_R		= 0x02, +	FF_T		= 0x04, +	FF_B		= 0x08, +	FF_T_L		= 0x10, +	FF_T_R		= 0x20, +	FF_B_L		= 0x40, +	FF_B_R		= 0x80, +	FF_Q_A		= (FF_L | FF_T | FF_T_L), +	FF_Q_B		= (FF_R | FF_T | FF_T_R), +	FF_Q_C		= (FF_L | FF_B | FF_B_L), +	FF_Q_D		= (FF_R | FF_B | FF_B_R) +}; + +int Moonbase::readFOWVisibilityArray(int array, int y, int x) { +	//_vm->VAR(_vm->VAR_U32_ARRAY_UNK) = array; // TODO + +	if (_vm->readArray(116, y, x) > 0) +		return FOW_EMPTY; + +	return FOW_SOLID; +} + +void Moonbase::setFOWInfo(int fowInfoArray, int downDim, int acrossDim, int viewX, int viewY, int clipX1, +				int clipY1, int clipX2, int clipY2, int technique, int nFrame) { +	if (!_fowImage) +		return; + +	_fowDrawX = clipX1; +	_fowDrawY = clipY1; + +	_fowClipX1 = clipX1; +	_fowClipY1 = clipY1; +	_fowClipX2 = clipX2; +	_fowClipY2 = clipY2; + +	// Figure out the number of tiles are involved +	int view_W = (clipX2 - clipX1) + 1; +	int view_H = (clipY2 - clipY1) + 1; + +	int tw = _fowTileW; +	int th = _fowTileH; + +	int dw = acrossDim; +	int dh = downDim; + +	int dlw = dw * tw; +	int dlh = dh * th; + +	_fowMvx = (0 <= viewX) ? (viewX % dlw) : (dlw - (-viewX % dlw)); +	_fowMvy = (0 <= viewY) ? (viewY % dlh) : (dlh - (-viewY % dlh)); + +	_fowVtx1 = _fowMvx / tw; +	_fowVty1 = _fowMvy / th; + +	_fowVw = (((_fowMvx + view_W + tw - 1) / tw) - _fowVtx1) + 1; +	_fowVh = (((_fowMvy + view_H + th - 1) / th) - _fowVty1) + 1; + +	// Build the connectivity table +	int t = (_fowVty1 - 1); if (t >= dh) { t = 0; } else if (t < 0) { t = (dh - 1); } +	int m = (_fowVty1 + 0); if (m >= dh) { m = 0; } else if (m < 0) { m = (dh - 1); } +	int b = (_fowVty1 + 1); if (b >= dh) { b = 0; } else if (b < 0) { b = (dh - 1); } + +	int il = (_fowVtx1 - 1); if (il >= dh) { il = 0; } else if (il < 0) { il = (dw - 1); } +	int ic = (_fowVtx1 + 0); if (ic >= dh) { ic = 0; } else if (ic < 0) { ic = (dw - 1); } +	int ir = (_fowVtx1 + 1); if (ir >= dh) { ir = 0; } else if (ir < 0) { ir = (dw - 1); } + +	int dataOffset = (_fowVw * 3); +	int dataOffset2 = (dataOffset * 2); +	int *pOutterRenderTableA = _fowRenderTable; +	int *pOutterRenderTableB = pOutterRenderTableA + dataOffset; + +	for (int ay = 0; ay < _fowVh; ay++) { +		int l = il; +		int c = ic; +		int r = ir; + +		int *pRenderTableA = pOutterRenderTableA; +		int *pRenderTableB = pOutterRenderTableB; + +		pOutterRenderTableA += dataOffset2; +		pOutterRenderTableB += dataOffset2; + +		for (int ax = 0; ax < _fowVw; ax++) { +			int visibility = readFOWVisibilityArray(fowInfoArray, m, c); + +			if (visibility == FOW_EMPTY) { +				int bits = 0; + +				if (readFOWVisibilityArray(fowInfoArray, t, l) != 0) bits |= FF_T_L; +				if (readFOWVisibilityArray(fowInfoArray, t, c) != 0) bits |= FF_T; +				if (readFOWVisibilityArray(fowInfoArray, t, r) != 0) bits |= FF_T_R; +				if (readFOWVisibilityArray(fowInfoArray, m, l) != 0) bits |= FF_L; +				if (readFOWVisibilityArray(fowInfoArray, m, r) != 0) bits |= FF_R; +				if (readFOWVisibilityArray(fowInfoArray, b, l) != 0) bits |= FF_B_L; +				if (readFOWVisibilityArray(fowInfoArray, b, c) != 0) bits |= FF_B; +				if (readFOWVisibilityArray(fowInfoArray, b, r) != 0) bits |= FF_B_R; + +				if (bits) { +					*pRenderTableA++ = 1; +					*pRenderTableB++ = 1; + +					// Quadrant (A) +					if (bits & FF_Q_A) { +						*pRenderTableA++ = ( +							((FF_L   & bits) ? 1 : 0) | +							((FF_T   & bits) ? 2 : 0) | +							((FF_T_L & bits) ? 4 : 0) +						) + 0; +					} else { +						*pRenderTableA++ = 0; +					} + +					// Quadrant (B) +					if (bits & FF_Q_B) { +						*pRenderTableA++ = ( +							((FF_R   & bits) ? 1 : 0) | +							((FF_T   & bits) ? 2 : 0) | +							((FF_T_R & bits) ? 4 : 0) +						) + 8; +					} else { +						*pRenderTableA++ = 0; +					} + +					// Quadrant (C) +					if (bits & FF_Q_C) { +						*pRenderTableB++ = ( +							((FF_L   & bits) ? 1 : 0) | +							((FF_B   & bits) ? 2 : 0) | +							((FF_B_L & bits) ? 4 : 0) +						) + 16; +					} else { +						*pRenderTableB++ = 0; +					} + +					// Quadrant (D) +					if (bits & FF_Q_D) { +						*pRenderTableB++ = ( +							((FF_R   & bits) ? 1 : 0) | +							((FF_B   & bits) ? 2 : 0) | +							((FF_B_R & bits) ? 4 : 0) +						) + 24; +					} else { +						*pRenderTableB++ = 0; +					} +				} else { +					*pRenderTableA++ = 0; +					*pRenderTableB++ = 0; +				} +			} else { +				if (_fowBlackMode) { +					*pRenderTableA++ = 2; +					*pRenderTableB++ = 2; +				} else { +					*pRenderTableA++ = 1; +					*pRenderTableA++ = 33; +					*pRenderTableA++ = 34; + +					*pRenderTableB++ = 1; +					*pRenderTableB++ = 35; +					*pRenderTableB++ = 36; +				} +			} + +			if (++l >= dw) { l = 0; } +			if (++c >= dw) { c = 0; } +			if (++r >= dw) { r = 0; } +		} + +		if (++t >= dh) { t = 0; } +		if (++m >= dh) { m = 0; } +		if (++b >= dh) { b = 0; } +	} + +	_fowCurrentFOWFrame = (nFrame >= 0) ? (nFrame % _fowAnimationFrames) : ((-nFrame) % _fowAnimationFrames); +	_fowFrameBaseNumber = (_fowCurrentFOWFrame * FOW_ANIM_FRAME_COUNT); +} + +void Moonbase::renderFOWState(uint8 *destSurface, int dstPitch, int dstType, int dstw, int dsth, int x, int y, int srcw, int srch, int state, int flags) { +	int spotx, spoty; + +	_vm->_wiz->getWizStateSpot(_fowImage, state, &spotx, &spoty); +	Common::Rect r(_fowClipX1, _fowClipY1, _fowClipX2, _fowClipY2); + +	_vm->_wiz->drawWizImageEx(destSurface, _fowImage, 0, dstPitch, dstType, dstw, dsth, x - spotx, y - spoty, srcw, srch, state, &r, flags, 0, 0, 16, 0, 0); +} + +static void blackRect_16bpp(uint8 *destSurface, int x1, int y1, int x2, int y2) { +	// TODO +} + +void Moonbase::renderFOW(uint8 *destSurface, int dstPitch, int dstType, int dstw, int dsth, int flags) { +	if (!_fowImage) +		return; + +	const int *pOutterRenderTable = _fowRenderTable; +	int ixPos = ((_fowVtx1 * _fowTileW) - _fowMvx) + _fowDrawX; +	int yPos = ((_fowVty1 * _fowTileH) - _fowMvy) + _fowDrawY; +	int dataOffset = _fowVw * 3; +	int halfTileHeight = _fowTileH / 2; +	int cx2 = MIN(_fowClipX2, (dstw - 1)); +	int cy2 = MIN(_fowClipY2, (dsth - 1)); + +	for (int ry = 0; ry < _fowVh; ry++) { +		int real_yPos = yPos; + +		for (int i = 0; i < 2; i++) { +			const int *pRenderTable = pOutterRenderTable; +			pOutterRenderTable += dataOffset; + +			int xPos = ixPos; + +			for (int rx = 0; rx < _fowVw; rx++) { +				int nState = *pRenderTable++; + +				if (nState != 0) { +					if (nState == 2) { +						int countLeft = (_fowVw - rx); +						int count = 0; + +						for (; count < countLeft; count++) { +							if (*(pRenderTable + count) != 2) +								break; + +							pRenderTable++; +							rx++; +						} +						count++; + +						int x1 = xPos; +						int y1 = real_yPos; + +						xPos += _fowTileW * count; +						int x2 = (xPos - 1); +						int y2 = ((y1 + halfTileHeight) - 1); + +						x1 = MAX(0, x1); +						y1 = MAX(0, y1); +						x2 = MIN(x2, cx2); +						y2 = MIN(y2, cy2); + +						if ((x2 >= x1) && (y2 >= y1) && (x1 <= _fowClipX2) && (y1 <= _fowClipY2)) +							blackRect_16bpp(destSurface, x1, y1, x2, y2); +					} else { +						int subState; + +						if ((subState = *pRenderTable++) != 0) +							renderFOWState(destSurface, dstPitch, dstType, dstw, dsth, xPos, yPos, _fowTileW, _fowTileH, (subState + _fowFrameBaseNumber), flags); + +						if ((subState = *pRenderTable++) != 0) +							renderFOWState(destSurface, dstPitch, dstType, dstw, dsth, xPos, yPos, _fowTileW, _fowTileH, (subState + _fowFrameBaseNumber), flags); + +						xPos += _fowTileW; +					} +				} else { +					xPos += _fowTileW; +				} +			} +			real_yPos += halfTileHeight; +		} +		yPos += _fowTileH; +	} +} + +} // End of namespace Scumm diff --git a/engines/scumm/he/script_v100he.cpp b/engines/scumm/he/script_v100he.cpp index afc6633ef6..7d56138247 100644 --- a/engines/scumm/he/script_v100he.cpp +++ b/engines/scumm/he/script_v100he.cpp @@ -1310,36 +1310,36 @@ void ScummEngine_v100he::o100_wizImageOps() {  		if (_wizParams.img.resNum)  			_wiz->processWizImage(&_wizParams);  		break; -	case 128: -		_wizParams.field_239D = pop(); -		_wizParams.field_2399 = pop(); -		_wizParams.field_23A5 = pop(); -		_wizParams.field_23A1 = pop(); -		copyScriptString(_wizParams.string2, sizeof(_wizParams.string2)); +	case 128: // Font create  		_wizParams.processMode = 15; +		_wizParams.fontProperties.bgColor = pop(); +		_wizParams.fontProperties.fgColor = pop(); +		_wizParams.fontProperties.size = pop(); +		_wizParams.fontProperties.style = pop(); +		copyScriptString(_wizParams.fontProperties.fontName, sizeof(_wizParams.fontProperties.fontName));  		break;  	case 129:  		_wizParams.processMode = 14;  		break; -	case 130: +	case 130: // Font render  		_wizParams.processMode = 16; -		_wizParams.field_23AD = pop(); -		_wizParams.field_23A9 = pop(); -		copyScriptString(_wizParams.string1, sizeof(_wizParams.string1)); +		_wizParams.fontProperties.yPos = pop(); +		_wizParams.fontProperties.xPos = pop(); +		copyScriptString(_wizParams.fontProperties.string, sizeof(_wizParams.fontProperties.string));  		break;  	case 131:  		_wizParams.processMode = 13;  		break; -	case 133: +	case 133: // Render ellipse  		_wizParams.processMode = 17; -		_wizParams.field_23CD = pop(); -		_wizParams.field_23C9 = pop(); -		_wizParams.field_23C5 = pop(); -		_wizParams.field_23C1 = pop(); -		_wizParams.field_23BD = pop(); -		_wizParams.field_23B9 = pop(); -		_wizParams.field_23B5 = pop(); -		_wizParams.field_23B1 = pop(); +		_wizParams.ellipseProperties.color = pop(); +		_wizParams.ellipseProperties.lod = pop(); +		_wizParams.ellipseProperties.ky = pop(); +		_wizParams.ellipseProperties.kx = pop(); +		_wizParams.ellipseProperties.qy = pop(); +		_wizParams.ellipseProperties.qx = pop(); +		_wizParams.ellipseProperties.py = pop(); +		_wizParams.ellipseProperties.px = pop();  		break;  	case 134:  		_wizParams.processFlags |= kWPFFillColor | kWPFClipBox2; @@ -1997,6 +1997,7 @@ void ScummEngine_v100he::o100_setSpriteInfo() {  				_sprite->setSpriteFlagRemapPalette(spriteId, args[0]);  				break;  			default: +				warning("Unknown sprite property %d for sprite %d", args[0], spriteId);  				break;  			}  		break; diff --git a/engines/scumm/he/script_v90he.cpp b/engines/scumm/he/script_v90he.cpp index f65d2f6077..f2d92bc2ca 100644 --- a/engines/scumm/he/script_v90he.cpp +++ b/engines/scumm/he/script_v90he.cpp @@ -285,29 +285,29 @@ void ScummEngine_v90he::o90_wizImageOps() {  		_wizParams.processMode = 13;  		break;  	case 142: // HE99+ -		_wizParams.field_239D = pop(); -		_wizParams.field_2399 = pop(); -		_wizParams.field_23A5 = pop(); -		_wizParams.field_23A1 = pop(); -		copyScriptString(_wizParams.string2, sizeof(_wizParams.string2));  		_wizParams.processMode = 15; +		_wizParams.fontProperties.bgColor = pop(); +		_wizParams.fontProperties.fgColor = pop(); +		_wizParams.fontProperties.size = pop(); +		_wizParams.fontProperties.style = pop(); +		copyScriptString(_wizParams.fontProperties.fontName, sizeof(_wizParams.fontProperties.fontName));  		break;  	case 143: // HE99+  		_wizParams.processMode = 16; -		_wizParams.field_23AD = pop(); -		_wizParams.field_23A9 = pop(); -		copyScriptString(_wizParams.string1, sizeof(_wizParams.string1)); +		_wizParams.fontProperties.yPos = pop(); +		_wizParams.fontProperties.xPos = pop(); +		copyScriptString(_wizParams.fontProperties.string, sizeof(_wizParams.fontProperties.string));  		break;  	case 189: // HE99+  		_wizParams.processMode = 17; -		_wizParams.field_23CD = pop(); -		_wizParams.field_23C9 = pop(); -		_wizParams.field_23C5 = pop(); -		_wizParams.field_23C1 = pop(); -		_wizParams.field_23BD = pop(); -		_wizParams.field_23B9 = pop(); -		_wizParams.field_23B5 = pop(); -		_wizParams.field_23B1 = pop(); +		_wizParams.ellipseProperties.color = pop(); +		_wizParams.ellipseProperties.lod = pop(); +		_wizParams.ellipseProperties.ky = pop(); +		_wizParams.ellipseProperties.kx = pop(); +		_wizParams.ellipseProperties.qy = pop(); +		_wizParams.ellipseProperties.qx = pop(); +		_wizParams.ellipseProperties.py = pop(); +		_wizParams.ellipseProperties.px = pop();  		break;  	case 196: // HE99+  		_wizParams.processMode = 14; diff --git a/engines/scumm/he/sound_he.cpp b/engines/scumm/he/sound_he.cpp index 9a456b86c0..2e0a03af7f 100644 --- a/engines/scumm/he/sound_he.cpp +++ b/engines/scumm/he/sound_he.cpp @@ -470,6 +470,10 @@ void SoundHE::processSoundOpcodes(int sound, byte *codePtr, int *soundVars) {  			if (arg == 2) {  				val = getSoundVar(sound, val);  			} +			if (!val) { +				val = 1; // Safeguard for division by zero +				warning("Incorrect value 0 for processSoundOpcodes() kludge DIV"); +			}  			val = getSoundVar(sound, var) / val;  			setSoundVar(sound, var, val);  			break; diff --git a/engines/scumm/he/sprite_he.cpp b/engines/scumm/he/sprite_he.cpp index 245a986531..b192fab233 100644 --- a/engines/scumm/he/sprite_he.cpp +++ b/engines/scumm/he/sprite_he.cpp @@ -386,7 +386,7 @@ int Sprite::getSpriteGeneralProperty(int spriteId, int type) {  	case 0x7B:  		return _spriteTable[spriteId].imgFlags;  	case 0x7D: -		return _spriteTable[spriteId].field_90; +		return _spriteTable[spriteId].conditionBits;  	case 0x7E:  		return _spriteTable[spriteId].animProgress;  	default: @@ -746,7 +746,7 @@ void Sprite::setSpriteField84(int spriteId, int value) {  }  void Sprite::setSpriteGeneralProperty(int spriteId, int type, int value) { -	debug(0, "setSpriteGeneralProperty: spriteId %d type 0x%x", spriteId, type); +	debug(0, "setSpriteGeneralProperty: spriteId %d type 0x%x value 0x%x", spriteId, type, value);  	assertRange(1, spriteId, _varNumSprites, "sprite");  	int32 delay; @@ -758,7 +758,7 @@ void Sprite::setSpriteGeneralProperty(int spriteId, int type, int value) {  		_spriteTable[spriteId].flags |= kSFChanged | kSFNeedRedraw;  		break;  	case 0x7D: -		_spriteTable[spriteId].field_90 = value; +		_spriteTable[spriteId].conditionBits = value;  		_spriteTable[spriteId].flags |= kSFChanged | kSFNeedRedraw;  		break;  	case 0x7E: @@ -799,7 +799,7 @@ void Sprite::resetSprite(int spriteId) {  	_spriteTable[spriteId].priority = 0;  	_spriteTable[spriteId].field_84 = 0;  	_spriteTable[spriteId].imgFlags = 0; -	_spriteTable[spriteId].field_90 = 0; +	_spriteTable[spriteId].conditionBits = 0;  	if (_vm->_game.heversion >= 100) {  		_spriteTable[spriteId].flags &= ~kSFMarkDirty; @@ -1292,7 +1292,7 @@ void Sprite::processImages(bool arg) {  		wiz.spriteId = spi->id;  		wiz.spriteGroup = spi->group; -		wiz.field_23EA = spi->field_90; +		wiz.conditionBits = spi->conditionBits;  		spi->curImageState = wiz.img.state = imageState;  		spi->curImage = wiz.img.resNum = image;  		wiz.processFlags = kWPFNewState | kWPFSetPos; @@ -1341,7 +1341,7 @@ void Sprite::processImages(bool arg) {  			wiz.img.flags |= kWIFRemapPalette;  		if (spi->field_84) {  			wiz.processFlags |= 0x200000; -			wiz.img.field_390 = spi->field_84; +			wiz.img.zbuffer = spi->field_84;  			wiz.img.zorder = spi->priority;  		}  		if (spi->sourceImage) { @@ -1426,7 +1426,7 @@ void Sprite::saveOrLoadSpriteData(Serializer *s) {  		MKLINE(SpriteInfo, field_84, sleInt32, VER(48)),  		MKLINE(SpriteInfo, classFlags, sleInt32, VER(48)),  		MKLINE(SpriteInfo, imgFlags, sleInt32, VER(48)), -		MKLINE(SpriteInfo, field_90, sleInt32, VER(48)), +		MKLINE(SpriteInfo, conditionBits, sleInt32, VER(48)),  		MKEND()  	}; diff --git a/engines/scumm/he/sprite_he.h b/engines/scumm/he/sprite_he.h index e31ccbf790..b1a7641fcc 100644 --- a/engines/scumm/he/sprite_he.h +++ b/engines/scumm/he/sprite_he.h @@ -79,7 +79,7 @@ struct SpriteInfo {  	int32 field_84;  	int32 classFlags;  	int32 imgFlags; -	int32 field_90; +	int32 conditionBits;  };  struct SpriteGroup { diff --git a/engines/scumm/he/wiz_he.cpp b/engines/scumm/he/wiz_he.cpp index 9a59609651..9a5be1cc5f 100644 --- a/engines/scumm/he/wiz_he.cpp +++ b/engines/scumm/he/wiz_he.cpp @@ -1422,19 +1422,19 @@ void Wiz::displayWizImage(WizImage *pwi) {  		wi->state = pwi->state;  		wi->flags = pwi->flags;  		wi->shadow = 0; -		wi->field_390 = 0; +		wi->zbuffer = 0;  		wi->palette = 0;  		++_imagesNum;  	} else if (pwi->flags & kWIFIsPolygon) {  		drawWizPolygon(pwi->resNum, pwi->state, pwi->x1, pwi->flags, 0, 0, 0);  	} else {  		const Common::Rect *r = NULL; -		drawWizImage(pwi->resNum, pwi->state, 0, 0, pwi->x1, pwi->y1, 0, 0, 0, r, pwi->flags, 0, _vm->getHEPaletteSlot(0)); +		drawWizImage(pwi->resNum, pwi->state, 0, 0, pwi->x1, pwi->y1, 0, 0, 0, r, pwi->flags, 0, _vm->getHEPaletteSlot(0), 0);  	}  } -uint8 *Wiz::drawWizImage(int resNum, int state, int maskNum, int maskState, int x1, int y1, int zorder, int shadow, int field_390, const Common::Rect *clipBox, int flags, int dstResNum, const uint8 *palPtr) { -	debug(3, "drawWizImage(resNum %d, state %d maskNum %d maskState %d x1 %d y1 %d flags 0x%X zorder %d shadow %d field_390 %d dstResNum %d)", resNum, state, maskNum, maskState, x1, y1, flags, zorder, shadow, field_390, dstResNum); +uint8 *Wiz::drawWizImage(int resNum, int state, int maskNum, int maskState, int x1, int y1, int zorder, int shadow, int zbuffer, const Common::Rect *clipBox, int flags, int dstResNum, const uint8 *palPtr, uint32 conditionBits) { +	debug(3, "drawWizImage(resNum %d, state %d maskNum %d maskState %d x1 %d y1 %d flags 0x%X zorder %d shadow %d zbuffer %d dstResNum %d conditionBits: 0x%x)", resNum, state, maskNum, maskState, x1, y1, flags, zorder, shadow, zbuffer, dstResNum, conditionBits);  	uint8 *dataPtr;  	uint8 *dst = NULL; @@ -1456,9 +1456,6 @@ uint8 *Wiz::drawWizImage(int resNum, int state, int maskNum, int maskState, int  	uint32 height = READ_LE_UINT32(wizh + 0x8);  	debug(3, "wiz_header.comp = %d wiz_header.w = %d wiz_header.h = %d", comp, width, height); -	uint8 *wizd = _vm->findWrappedBlock(MKTAG('W','I','Z','D'), dataPtr, state, 0); -	assert(wizd); -  	uint8 *mask = NULL;  	if (maskNum) {  		uint8 *maskPtr = _vm->getResourceAddress(rtImage, maskNum); @@ -1574,58 +1571,251 @@ uint8 *Wiz::drawWizImage(int resNum, int state, int maskNum, int maskState, int  		transColor = (trns == NULL) ? _vm->VAR(_vm->VAR_WIZ_TCOLOR) : -1;  	} +	drawWizImageEx(dst, dataPtr, mask, dstPitch, dstType, cw, ch, x1, y1, width, height, +		state, &rScreen, flags, palPtr, transColor, _vm->_bytesPerPixel, xmapPtr, conditionBits); + +	if (!(flags & kWIFBlitToMemBuffer) && dstResNum == 0) { +		Common::Rect rImage(x1, y1, x1 + width, y1 + height); +		if (rImage.intersects(rScreen)) { +			rImage.clip(rScreen); +			if (!(flags & kWIFBlitToFrontVideoBuffer) && (flags & (kWIFBlitToFrontVideoBuffer | kWIFMarkBufferDirty))) { +				++rImage.bottom; +				_vm->markRectAsDirty(kMainVirtScreen, rImage); +			} else { +				_vm->restoreBackgroundHE(rImage); +			} +		} +	} + +	return dst; +} + +void Wiz::drawWizImageEx(uint8 *dst, uint8 *dataPtr, uint8 *maskPtr, int dstPitch, int dstType, +		int dstw, int dsth, int srcx, int srcy, int srcw, int srch, int state, const Common::Rect *rect, +		int flags, const uint8 *palPtr, int transColor, uint8 bitDepth, const uint8 *xmapPtr, uint32 conditionBits) { +	uint8 *wizh = _vm->findWrappedBlock(MKTAG('W','I','Z','H'), dataPtr, state, 0); +	assert(wizh); +	uint32 comp   = READ_LE_UINT32(wizh + 0x0); +	uint32 width  = READ_LE_UINT32(wizh + 0x4); +	uint32 height = READ_LE_UINT32(wizh + 0x8); +	debug(3, "wiz_header.comp = %d wiz_header.w = %d wiz_header.h = %d", comp, width, height); + +	uint8 *wizd = _vm->findWrappedBlock(MKTAG('W','I','Z','D'), dataPtr, state, 0); +	assert(wizd); +  	switch (comp) {  	case 0: -		copyRawWizImage(dst, wizd, dstPitch, dstType, cw, ch, x1, y1, width, height, &rScreen, flags, palPtr, transColor, _vm->_bytesPerPixel); +		copyRawWizImage(dst, wizd, dstPitch, dstType, dstw, dsth, srcx, srcy, srcw, srch, rect, flags, palPtr, transColor, bitDepth);  		break;  	case 1: -		if (flags & 0x80) { +		if (flags & kWIFZPlaneOn) {  			dst = _vm->getMaskBuffer(0, 0, 1);  			dstPitch /= _vm->_bytesPerPixel; -			copyWizImageWithMask(dst, wizd, dstPitch, cw, ch, x1, y1, width, height, &rScreen, 0, 2); -		} else if (flags & 0x100) { +			copyWizImageWithMask(dst, wizd, dstPitch, dstw, dsth, srcx, srcy, srcw, srch, rect, 0, 2); +		} else if (flags & kWIFZPlaneOff) {  			dst = _vm->getMaskBuffer(0, 0, 1);  			dstPitch /= _vm->_bytesPerPixel; -			copyWizImageWithMask(dst, wizd, dstPitch, cw, ch, x1, y1, width, height, &rScreen, 0, 1); +			copyWizImageWithMask(dst, wizd, dstPitch, dstw, dsth, srcx, srcy, srcw, srch, rect, 0, 1);  		} else { -			copyWizImage(dst, wizd, dstPitch, dstType, cw, ch, x1, y1, width, height, &rScreen, flags, palPtr, xmapPtr, _vm->_bytesPerPixel); +			copyWizImage(dst, wizd, dstPitch, dstType, dstw, dsth, srcx, srcy, srcw, srch, rect, flags, palPtr, xmapPtr, bitDepth);  		}  		break;  #ifdef USE_RGB_COLOR  	case 2: -		if (maskNum) { -			copyMaskWizImage(dst, wizd, mask, dstPitch, dstType, cw, ch, x1, y1, width, height, &rScreen, flags, palPtr); +		if (maskPtr) { +			copyMaskWizImage(dst, wizd, maskPtr, dstPitch, dstType, dstw, dsth, srcx, srcy, srcw, srch, rect, flags, palPtr);  		} else { -			copyRaw16BitWizImage(dst, wizd, dstPitch, dstType, cw, ch, x1, y1, width, height, &rScreen, flags, transColor); +			copyRaw16BitWizImage(dst, wizd, dstPitch, dstType, dstw, dsth, srcx, srcy, srcw, srch, rect, flags, transColor);  		}  		break;  	case 4: -		// TODO: Unknown image type +		copyCompositeWizImage(dst, dataPtr, wizd, maskPtr, dstPitch, dstType, dstw, dsth, srcx, srcy, srcw, srch, state, rect, flags, palPtr, transColor, bitDepth, xmapPtr, conditionBits);  		break;  	case 5: -		copy16BitWizImage(dst, wizd, dstPitch, dstType, cw, ch, x1, y1, width, height, &rScreen, flags, xmapPtr); +		copy16BitWizImage(dst, wizd, dstPitch, dstType, dstw, dsth, srcx, srcy, srcw, srch, rect, flags, xmapPtr); +		break; +	case 9: +		copy555WizImage(dst, wizd, dstPitch, dstType, dstw, dsth, srcx, srcy, rect, conditionBits);  		break;  #endif  	default: -		error("drawWizImage: Unhandled wiz compression type %d", comp); +		error("drawWizImageEx: Unhandled wiz compression type %d", comp);  	} +} -	if (!(flags & kWIFBlitToMemBuffer) && dstResNum == 0) { -		Common::Rect rImage(x1, y1, x1 + width, y1 + height); -		if (rImage.intersects(rScreen)) { -			rImage.clip(rScreen); -			if (!(flags & kWIFBlitToFrontVideoBuffer) && (flags & (kWIFBlitToFrontVideoBuffer | kWIFMarkBufferDirty))) { -				++rImage.bottom; -				_vm->markRectAsDirty(kMainVirtScreen, rImage); -			} else { -				_vm->restoreBackgroundHE(rImage); +#ifdef USE_RGB_COLOR + +void Wiz::copyCompositeWizImage(uint8 *dst, uint8 *wizPtr, uint8 *compositeInfoBlockPtr, uint8 *maskPtr, int dstPitch, int dstType, +		int dstw, int dsth, int srcx, int srcy, int srcw, int srch, int state, const Common::Rect *clipBox, +		int flags, const uint8 *palPtr, int transColor, uint8 bitDepth, const uint8 *xmapPtr, uint32 conditionBits) { + +	uint8 *nestedBlockHeader = _vm->heFindResource(MKTAG('N','E','S','T'), wizPtr); +	assert(nestedBlockHeader); + +	uint8 *nestedWizHeader = _vm->heFindResource(MKTAG('M','U','L','T'), nestedBlockHeader); +	assert(nestedWizHeader); + +	uint16 layerCount = READ_LE_UINT16(compositeInfoBlockPtr); +	compositeInfoBlockPtr += 2; + +	uint16 defaultSubConditionBits = (conditionBits & kWMSBReservedBits); + +	conditionBits &= ~kWMSBReservedBits; + +	for (uint layerCounter = 0; layerCounter < layerCount; layerCounter++) { +		int cmdSize = READ_LE_UINT16(compositeInfoBlockPtr); +		uint8 *cmdPtr = compositeInfoBlockPtr + 2; + +		compositeInfoBlockPtr += (cmdSize + 2); +		uint32 layerCmdDataBits = READ_LE_UINT32(cmdPtr); +		cmdPtr += 4; + +		uint32 subConditionBits; + +		if (layerCmdDataBits & kWCFConditionBits) { +			uint32 layerConditionBits = READ_LE_UINT32(cmdPtr); +			cmdPtr += 4; + +			subConditionBits = (layerConditionBits & kWMSBReservedBits); +			layerConditionBits &= ~kWMSBReservedBits; + +			if (subConditionBits == 0) +				subConditionBits = defaultSubConditionBits; + +			uint32 conditionType = (layerConditionBits & kWSPCCTBits); +			layerConditionBits &= ~kWSPCCTBits; + +			switch (conditionType) { +			case kWSPCCTAnd: +				if (layerConditionBits != (layerConditionBits & conditionBits)) +					continue; +				break; + +			case kWSPCCTNot: +				if (layerConditionBits & conditionBits) +					continue; +				break; + +			case kWSPCCTOr: +			default: +				if (!(layerConditionBits & conditionBits)) +					continue; +				break;  			} +		} else { +			subConditionBits = defaultSubConditionBits; +		} + +		uint16 subState; +		if (layerCmdDataBits & kWCFSubState) { +			subState = READ_LE_UINT16(cmdPtr); +			cmdPtr += 2; +		} else { +			subState = 0; +		} + +		int16 xPos; +		if (layerCmdDataBits & kWCFXDelta) { +			xPos = (int16)READ_LE_UINT16(cmdPtr); +			cmdPtr += 2; +		} else { +			xPos = 0;  		} + +		int16 yPos; +		if (layerCmdDataBits & kWCFYDelta) { +			yPos = (int16)READ_LE_UINT16(cmdPtr); +			cmdPtr += 2; +		} else { +			yPos = 0; +		} + +		uint32 drawFlags; +		if (layerCmdDataBits & kWCFDrawFlags) { +			drawFlags = READ_LE_UINT32(cmdPtr); +			cmdPtr += 4; +		} else { +			drawFlags = flags; +		} + +		uint srcw1, srch1; +		if (drawFlags & (kWIFFlipX | kWIFFlipY)) { +			uint8 *wizh = _vm->findWrappedBlock(MKTAG('W','I','Z','H'), wizPtr, subState, 0); +			assert(wizh); +			srcw1 = READ_LE_UINT32(wizh + 0x4); +			srch1 = READ_LE_UINT32(wizh + 0x8); +		} + +		if (drawFlags & kWIFFlipX) +			xPos = (srcw - (xPos + srcw1)); + +		if (drawFlags & kWIFFlipY) +			yPos = (srch - (yPos + srch1)); + +		if (layerCmdDataBits & kWCFSubConditionBits) { +			subConditionBits = READ_LE_UINT32(cmdPtr); +			cmdPtr += 4; +		} else { +			subConditionBits = 0; +		} + +		drawWizImageEx(dst, nestedWizHeader, maskPtr, dstPitch, dstType, dstw, dsth, srcx + xPos, srcy + yPos, srcw, srch, +			subState, clipBox, drawFlags, palPtr, transColor, bitDepth, xmapPtr, subConditionBits); +	} +} + +void Wiz::copy555WizImage(uint8 *dst, uint8 *wizd, int dstPitch, int dstType, +		int dstw, int dsth, int srcx, int srcy, const Common::Rect *clipBox, uint32 conditionBits) { + +	int rawROP = conditionBits & kWMSBRopMask; +	int paramROP = (conditionBits & kWMSBReservedBits) >> kWMSBRopParamRShift; + +	switch (rawROP) { +	default: +	case 1: +		// MMX_PREMUL_ALPHA_COPY +		break; + +	case 2: +		warning("T14: MMX_ADDITIVE"); +		break; + +	case 3: +		warning("T14: MMX_SUBTRACTIVE"); +		break; + +	case 4: +		warning("T14: MMX_CONSTANT_ALPHA"); +		break; + +	case 5: +		warning("T14: MMX_CHEAP_50_50"); +		break; + +	case 6: +		warning("T14: COPY"); +		break; + +	case 7: +		warning("T14: CHEAP_50_50"); +		break; +	} + + +	uint32 compID = READ_LE_UINT32(wizd); + +	if (compID == 0x12340102) { +		_vm->_moonbase->blitT14WizImage(dst, dstw, dsth, dstPitch, clipBox, wizd, srcx, srcy, rawROP, paramROP); +	} else if (compID == 0x12340802) { +		warning("Distorion codec"); +	} else if (compID == 0x12340902) { +		error("Unsupported Distortion");  	} -	return dst;  } +#endif +  struct PolygonDrawData {  	struct PolygonArea {  		int32 xmin; @@ -1747,7 +1937,7 @@ void Wiz::captureWizPolygon(int resNum, int maskNum, int maskState, int id1, int  	assert(maskNum);  	const Common::Rect *r = NULL; -	const uint8 *src = drawWizImage(maskNum, maskState, 0, 0, 0, 0, 0, 0, 0, r, kWIFBlitToMemBuffer, 0, 0); +	const uint8 *src = drawWizImage(maskNum, maskState, 0, 0, 0, 0, 0, 0, 0, r, kWIFBlitToMemBuffer, 0, 0, 0);  	getWizImageDim(maskNum, maskState, srcw, srch);  	dstw = wp->bound.width(); @@ -1815,7 +2005,7 @@ void Wiz::drawWizPolygonTransform(int resNum, int state, Common::Point *wp, int  				debug(0, "drawWizPolygonTransform() unhandled flag 0x800000");  			} -			srcWizBuf = drawWizImage(resNum, state, 0, 0, 0, 0, 0, shadow, 0, r, flags, 0, _vm->getHEPaletteSlot(palette)); +			srcWizBuf = drawWizImage(resNum, state, 0, 0, 0, 0, 0, shadow, 0, r, flags, 0, _vm->getHEPaletteSlot(palette), 0);  		} else {  			assert(_vm->_bytesPerPixel == 1);  			uint8 *dataPtr = _vm->getResourceAddress(rtImage, resNum); @@ -1826,7 +2016,7 @@ void Wiz::drawWizPolygonTransform(int resNum, int state, Common::Point *wp, int  		}  	} else {  		if (getWizImageData(resNum, state, 0) != 0) { -			srcWizBuf = drawWizImage(resNum, state, 0, 0, 0, 0, 0, shadow, 0, r, kWIFBlitToMemBuffer, 0, _vm->getHEPaletteSlot(palette)); +			srcWizBuf = drawWizImage(resNum, state, 0, 0, 0, 0, 0, shadow, 0, r, kWIFBlitToMemBuffer, 0, _vm->getHEPaletteSlot(palette), 0);  		} else {  			uint8 *dataPtr = _vm->getResourceAddress(rtImage, resNum);  			assert(dataPtr); @@ -2001,7 +2191,7 @@ void Wiz::flushWizBuffer() {  			drawWizPolygon(pwi->resNum, pwi->state, pwi->x1, pwi->flags, pwi->shadow, 0, pwi->palette);  		} else {  			const Common::Rect *r = NULL; -			drawWizImage(pwi->resNum, pwi->state, 0, 0, pwi->x1, pwi->y1, pwi->zorder, pwi->shadow, pwi->field_390, r, pwi->flags, 0, _vm->getHEPaletteSlot(pwi->palette)); +			drawWizImage(pwi->resNum, pwi->state, 0, 0, pwi->x1, pwi->y1, pwi->zorder, pwi->shadow, pwi->zbuffer, r, pwi->flags, 0, _vm->getHEPaletteSlot(pwi->palette), 0);  		}  	}  	_imagesNum = 0; @@ -2023,7 +2213,7 @@ void Wiz::loadWizCursor(int resId, int palette) {  	const Common::Rect *r = NULL;  	_cursorImage = true; -	uint8 *cursor = drawWizImage(resId, 0, 0, 0, 0, 0, 0, 0, 0, r, kWIFBlitToMemBuffer, 0, _vm->getHEPaletteSlot(palette)); +	uint8 *cursor = drawWizImage(resId, 0, 0, 0, 0, 0, 0, 0, 0, r, kWIFBlitToMemBuffer, 0, _vm->getHEPaletteSlot(palette), 0);  	_cursorImage = false;  	int32 cw, ch; @@ -2073,10 +2263,10 @@ void Wiz::displayWizComplexImage(const WizParameters *params) {  	if (params->processFlags & kWPFShadow) {  		shadow = params->img.shadow;  	} -	int field_390 = 0; -	if (params->processFlags & 0x200000) { -		field_390 = params->img.field_390; -		debug(0, "displayWizComplexImage() unhandled flag 0x200000"); +	int zbuffer = 0; +	if (params->processFlags & kWPFZBuffer) { +		zbuffer = params->img.zbuffer; +		debug(0, "displayWizComplexImage() unhandled flag kWPFZBuffer");  	}  	const Common::Rect *r = NULL;  	if (params->processFlags & kWPFClipBox) { @@ -2104,19 +2294,26 @@ void Wiz::displayWizComplexImage(const WizParameters *params) {  		pwi->state = state;  		pwi->flags = flags;  		pwi->shadow = shadow; -		pwi->field_390 = field_390; +		pwi->zbuffer = zbuffer;  		pwi->palette = palette;  		++_imagesNum;  	} else {  		if (sourceImage != 0) { -			drawWizImage(params->sourceImage, 0, params->img.resNum, state, po_x, po_y, params->img.zorder, shadow, field_390, r, flags, dstResNum, _vm->getHEPaletteSlot(palette)); +			drawWizImage(params->sourceImage, 0, params->img.resNum, state, po_x, po_y, params->img.zorder, shadow, zbuffer, r, flags, dstResNum, _vm->getHEPaletteSlot(palette), 0);  		} else if (params->processFlags & (kWPFScaled | kWPFRotate)) {  			drawWizComplexPolygon(params->img.resNum, state, po_x, po_y, shadow, rotationAngle, scale, r, flags, dstResNum, palette);  		} else {  			if (flags & kWIFIsPolygon) {  				drawWizPolygon(params->img.resNum, state, po_x, flags, shadow, dstResNum, palette);  			} else { -				drawWizImage(params->img.resNum, state, 0, 0, po_x, po_y, params->img.zorder, shadow, field_390, r, flags, dstResNum, _vm->getHEPaletteSlot(palette)); +				if (_vm->_game.id == GID_MOONBASE) { +					if (params->img.resNum == _vm->_moonbase->_fowSentinelImage && +							state == _vm->_moonbase->_fowSentinelState && +							params->conditionBits == _vm->_moonbase->_fowSentinelConditionBits) +						_vm->_moonbase->renderFOW(0, 0, 0, 0, 0, flags); +				} + +				drawWizImage(params->img.resNum, state, 0, 0, po_x, po_y, params->img.zorder, shadow, zbuffer, r, flags, dstResNum, _vm->getHEPaletteSlot(palette), params->conditionBits);  			}  		}  	} @@ -2547,6 +2744,11 @@ int Wiz::getWizImageData(int resNum, int state, int type) {  int Wiz::getWizImageStates(int resNum) {  	const uint8 *dataPtr = _vm->getResourceAddress(rtImage, resNum);  	assert(dataPtr); + +	return getWizImageStates(dataPtr); +} + +int Wiz::getWizImageStates(const uint8 *dataPtr) {  	if (READ_BE_UINT32(dataPtr) == MKTAG('M','U','L','T')) {  		const byte *offs, *wrap; @@ -2564,6 +2766,18 @@ int Wiz::getWizImageStates(int resNum) {  	}  } +void Wiz::getWizStateSpot(byte *data, int state, int *x, int *y) { +	byte *spot = _vm->findWrappedBlock(MKTAG('S','P','O','T'), data, state, 0); + +	if (!spot) { +		*x = *y = 0; +		return; +	} + +	*x = READ_LE_UINT32(spot + 0x0); +	*y = READ_LE_UINT32(spot + 0x4); +} +  int Wiz::isWizPixelNonTransparent(int resNum, int state, int x, int y, int flags) {  	int ret = 0;  	uint8 *data = _vm->getResourceAddress(rtImage, resNum); @@ -2597,11 +2811,12 @@ int Wiz::isWizPixelNonTransparent(int resNum, int state, int x, int y, int flags  		case 2:  			ret = getRawWizPixelColor(wizd, x, y, w, h, 2, _vm->VAR(_vm->VAR_WIZ_TCOLOR)) != _vm->VAR(_vm->VAR_WIZ_TCOLOR) ? 1 : 0;  			break; -		case 4: -			// TODO: Unknown image type -			ret = 1; -			debug(0, "isWizPixelNonTransparent: Unhandled wiz compression type %d", c); +		case 4: { +			uint16 color = 0xffff; +			copyCompositeWizImage((byte *)&color, data, wizd, 0, 2, kDstMemory, 1, 1, -x, -y, w, h, state, 0, 0, 0, 0, 2, 0, 0); +			ret = color != 0xffff;  			break; +		}  		case 5:  			ret = isWizPixelNonTransparent(wizd, x, y, w, h, 2);  			break; @@ -2641,8 +2856,7 @@ uint16 Wiz::getWizPixelColor(int resNum, int state, int x, int y) {  		color = getRawWizPixelColor(wizd, x, y, w, h, 2, _vm->VAR(_vm->VAR_WIZ_TCOLOR));  		break;  	case 4: -		// TODO: Unknown image type -		debug(0, "getWizPixelColor: Unhandled wiz compression type %d", c); +		copyCompositeWizImage((byte *)&color, data, wizd, 0, 2, kDstMemory, 1, 1, -x, -y, w, h, state, 0, 0, 0, 0, 2, 0, 0);  		break;  	case 5:  		color = getWizPixelColor(wizd, x, y, w, h, 2, _vm->VAR(_vm->VAR_WIZ_TCOLOR)); diff --git a/engines/scumm/he/wiz_he.h b/engines/scumm/he/wiz_he.h index 8db438a074..ff5169f7e8 100644 --- a/engines/scumm/he/wiz_he.h +++ b/engines/scumm/he/wiz_he.h @@ -43,10 +43,32 @@ struct WizImage {  	int state;  	int flags;  	int shadow; -	int field_390; +	int zbuffer;  	int palette;  }; +struct FontProperties { +	byte string[4096]; +	byte fontName[4096]; +	int fgColor; +	int bgColor; +	int style; +	int size; +	int xPos; +	int yPos; +}; + +struct EllipseProperties { +	int px; +	int py; +	int qx; +	int qy; +	int kx; +	int ky; +	int lod; +	int color; +}; +  struct WizParameters {  	int field_0;  	byte filename[260]; @@ -77,27 +99,13 @@ struct WizParameters {  	int remapNum;  	int dstResNum;  	uint16 fillColor; -	byte string1[4096]; -	byte string2[4096]; -	int field_2399; -	int field_239D; -	int field_23A1; -	int field_23A5; -	int field_23A9; -	int field_23AD; -	int field_23B1; -	int field_23B5; -	int field_23B9; -	int field_23BD; -	int field_23C1; -	int field_23C5; -	int field_23C9; -	int field_23CD; +	FontProperties fontProperties; +	EllipseProperties ellipseProperties;  	Common::Rect box2; -	int field_23DE; +	int blendFlags;  	int spriteId;  	int spriteGroup; -	int field_23EA; +	int conditionBits;  	WizImage img;  }; @@ -109,6 +117,9 @@ enum WizImageFlags {  	kWIFMarkBufferDirty = 0x10,  	kWIFBlitToMemBuffer = 0x20,  	kWIFIsPolygon = 0x40, +	kWIFZPlaneOn = 0x80, +	kWIFZPlaneOff = 0x100, +	kWIFUseShadow = 0x200,  	kWIFFlipX = 0x400,  	kWIFFlipY = 0x800  }; @@ -130,7 +141,31 @@ enum WizProcessFlags {  	kWPFFillColor = 0x20000,  	kWPFClipBox2 = 0x40000,  	kWPFMaskImg = 0x80000, -	kWPFParams = 0x100000 +	kWPFParams = 0x100000, +	kWPFZBuffer = 0x200000 +}; + +enum WizCompositeFlags { +	kWCFConditionBits = 0x01, +	kWCFSubState = 0x02, +	kWCFXDelta = 0x04, +	kWCFYDelta = 0x08, +	kWCFDrawFlags = 0x10, +	kWCFSubConditionBits = 0x20 +}; + +enum WizSpcConditionTypes { +	kWSPCCTBits = 0xc0000000, +	kWSPCCTOr   = 0x00000000, +	kWSPCCTAnd  = 0x40000000, +	kWSPCCTNot  = 0x80000000 +}; + +enum WizMoonSystemBits { +	kWMSBRopMask = 0xff, +	kWMSBRopParamMask = 0xff00, +	kWMSBReservedBits = (kWMSBRopMask | kWMSBRopParamMask), +	kWMSBRopParamRShift = 8  };  enum { @@ -186,6 +221,8 @@ public:  	void getWizImageDim(int resNum, int state, int32 &w, int32 &h);  	int getWizImageStates(int resnum); +	int getWizImageStates(const uint8 *ptr); +	void getWizStateSpot(byte *data, int state, int *x, int *y);  	int isWizPixelNonTransparent(int resnum, int state, int x, int y, int flags);  	uint16 getWizPixelColor(int resnum, int state, int x, int y);  	int getWizImageData(int resNum, int state, int type); @@ -202,7 +239,8 @@ public:  	void displayWizImage(WizImage *pwi);  	void processWizImage(const WizParameters *params); -	uint8 *drawWizImage(int resNum, int state, int maskNum, int maskState, int x1, int y1, int zorder, int shadow, int field_390, const Common::Rect *clipBox, int flags, int dstResNum, const uint8 *palPtr); +	uint8 *drawWizImage(int resNum, int state, int maskNum, int maskState, int x1, int y1, int zorder, int shadow, int zbuffer, const Common::Rect *clipBox, int flags, int dstResNum, const uint8 *palPtr, uint32 conditionBits); +	void drawWizImageEx(uint8 *dst, uint8 *src, uint8 *mask, int dstPitch, int dstType, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, int state, const Common::Rect *rect, int flags, const uint8 *palPtr, int transColor, uint8 bitDepth, const uint8 *xmapPtr, uint32 conditionBits);  	void drawWizPolygon(int resNum, int state, int id, int flags, int shadow, int dstResNum, int palette);  	void drawWizComplexPolygon(int resNum, int state, int po_x, int po_y, int shadow, int angle, int zoom, const Common::Rect *r, int flags, int dstResNum, int palette);  	void drawWizPolygonTransform(int resNum, int state, Common::Point *wp, int flags, int shadow, int dstResNum, int palette); @@ -210,6 +248,12 @@ public:  #ifdef USE_RGB_COLOR  	static void copyMaskWizImage(uint8 *dst, const uint8 *src, const uint8 *mask, int dstPitch, int dstType, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, const Common::Rect *rect, int flags, const uint8 *palPtr); + +	void copyCompositeWizImage(uint8 *dst, uint8 *wizPtr, uint8 *wizd, uint8 *maskPtr, int dstPitch, int dstType, +		int dstw, int dsth, int srcx, int srcy, int srcw, int srch, int state, const Common::Rect *clipBox, +		int flags, const uint8 *palPtr, int transColor, uint8 bitDepth, const uint8 *xmapPtr, uint32 conditionBits); +	void copy555WizImage(uint8 *dst, uint8 *wizd, int dstPitch, int dstType, +			int dstw, int dsth, int srcx, int srcy, const Common::Rect *clipBox, uint32 conditionBits);  #endif  	static void copyAuxImage(uint8 *dst1, uint8 *dst2, const uint8 *src, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, uint8 bitdepth); diff --git a/engines/scumm/module.mk b/engines/scumm/module.mk index 416a8f7ef9..c56ef7e5f4 100644 --- a/engines/scumm/module.mk +++ b/engines/scumm/module.mk @@ -136,9 +136,11 @@ MODULE_OBJS += \  	he/logic/basketball.o \  	he/logic/football.o \  	he/logic/funshop.o \ -	he/logic/moonbase.o \ +	he/logic/moonbase_logic.o \  	he/logic/puttrace.o \ -	he/logic/soccer.o +	he/logic/soccer.o \ +	he/moonbase/moonbase.o \ +	he/moonbase/moonbase_fow.o  endif  # This module can be built as a plugin diff --git a/engines/scumm/scumm-md5.h b/engines/scumm/scumm-md5.h index e986ae4b47..68e4887b00 100644 --- a/engines/scumm/scumm-md5.h +++ b/engines/scumm/scumm-md5.h @@ -1,5 +1,5 @@  /* -  This file was generated by the md5table tool on Mon Mar 28 09:52:54 2016 +  This file was generated by the md5table tool on Sat Apr 30 14:24:41 2016    DO NOT EDIT MANUALLY!   */ @@ -532,6 +532,7 @@ static const MD5Table md5table[] = {  	{ "bf8b52fdd9a69c67f34e8e9fec72661c", "farm", "HE 71", "Demo", -1, Common::EN_ANY, Common::kPlatformWindows },  	{ "bfdf584b01503f0762baded581f6a0a2", "SoccerMLS", "", "", -1, Common::EN_ANY, Common::kPlatformWindows },  	{ "c0039ad982999c92d0de81910d640fa0", "freddi", "HE 71", "", 26159, Common::NL_NLD, Common::kPlatformWindows }, +	{ "c0c9de81fb965e6cbe77f6e5631ca705", "monkey", "SE Talkie", "Unofficial SE Talkie v1.02", 9135, Common::EN_ANY, Common::kPlatformDOS },  	{ "c13225cb1bbd3bc9fe578301696d8021", "monkey", "SEGA", "", -1, Common::EN_ANY, Common::kPlatformSegaCD },  	{ "c20848f53c2d48bfacdc840993843765", "freddi2", "HE 80", "Demo", -1, Common::NL_NLD, Common::kPlatformUnknown },  	{ "c225bec1b6c0798a2b8c89ac226dc793", "pajama", "HE 101", "", -1, Common::EN_ANY, Common::kPlatformWii }, @@ -672,6 +673,7 @@ static const MD5Table md5table[] = {  	{ "f3c5d9bf3f091bd1f18dc1013fba5396", "atlantis", "Steam", "Steam", 638976, Common::EN_ANY, Common::kPlatformWindows },  	{ "f3d55aea441e260e9e9c7d2a187097e0", "puttzoo", "", "Demo", 14337, Common::EN_ANY, Common::kPlatformWindows },  	{ "f40a7f495f59188ca57a9d1d50301bb6", "puttputt", "HE 60", "Demo", -1, Common::EN_ANY, Common::kPlatformMacintosh }, +	{ "f4d20ab4ce19743a646cb48bd93aee72", "monkey2", "SE Talkie", "Unofficial SE Talkie v0.2", 10835, Common::EN_ANY, Common::kPlatformDOS },  	{ "f5228b0cc1c19e6ea8268ba2eeb61f60", "freddi", "HE 73", "Demo", -1, Common::FR_FRA, Common::kPlatformWindows },  	{ "f73883f13b5a302749a5bad31d909780", "tentacle", "", "CD", -1, Common::DE_DEU, Common::kPlatformMacintosh },  	{ "f7635a0e2ab82c9a0f9ace5f232a488f", "catalog", "HE 72", "Demo", -1, Common::EN_ANY, Common::kPlatformWindows }, diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp index e7118616ba..ff25dc9201 100644 --- a/engines/scumm/scumm.cpp +++ b/engines/scumm/scumm.cpp @@ -733,7 +733,7 @@ ScummEngine_v0::ScummEngine_v0(OSystem *syst, const DetectorResult &dr)  	VAR_ACTIVE_VERB = 0xFF;  	if (strcmp(dr.fp.pattern, "maniacdemo.d64") == 0 ) -		_game.features |= GF_DEMO;  +		_game.features |= GF_DEMO;  }  ScummEngine_v6::ScummEngine_v6(OSystem *syst, const DetectorResult &dr) @@ -832,9 +832,16 @@ ScummEngine_v71he::ScummEngine_v71he(OSystem *syst, const DetectorResult &dr)  	_skipProcessActors = 0;  	VAR_WIZ_TCOLOR = 0xFF; + +	/* Moonbase stuff */ +	_moonbase = 0; + +	if (_game.id == GID_MOONBASE) +		_moonbase = new Moonbase(this);  }  ScummEngine_v71he::~ScummEngine_v71he() { +	delete _moonbase;  	delete _wiz;  } diff --git a/engines/sherlock/tattoo/tattoo_fixed_text.h b/engines/sherlock/tattoo/tattoo_fixed_text.h index 7dbe13bbb3..eb636cdada 100644 --- a/engines/sherlock/tattoo/tattoo_fixed_text.h +++ b/engines/sherlock/tattoo/tattoo_fixed_text.h @@ -233,7 +233,7 @@ public:  	virtual const Common::String getActionMessage(FixedTextActionId actionId, int messageIndex);  }; -} // End of namespace Scalpel +} // End of namespace Tattoo  } // End of namespace Sherlock diff --git a/engines/sherlock/tattoo/tattoo_journal.cpp b/engines/sherlock/tattoo/tattoo_journal.cpp index 8e1a61d36e..4d4f37f8d5 100644 --- a/engines/sherlock/tattoo/tattoo_journal.cpp +++ b/engines/sherlock/tattoo/tattoo_journal.cpp @@ -50,7 +50,7 @@ void TattooJournal::show() {  	Screen &screen = *_vm->_screen;  	TattooUserInterface &ui = *(TattooUserInterface *)_vm->_ui;  	byte palette[PALETTE_SIZE]; -	 +  	Common::Point oldScroll = screen._currentScroll;  	screen._currentScroll = Common::Point(0, 0); @@ -66,7 +66,7 @@ void TattooJournal::show() {  	// Set screen to black, and set background  	screen._backBuffer1.SHblitFrom((*_journalImages)[0], Common::Point(0, 0)); -	screen.empty(); +	screen.clear();  	screen.setPalette(palette);  	if (_journal.empty()) { @@ -87,12 +87,12 @@ void TattooJournal::show() {  		handleKeyboardEvents();  		highlightJournalControls(true); -		 +  		handleButtons();  		if (_wait)  			events.wait(2); -		 +  	} while (!_vm->shouldQuit() && !_exitJournal);  	// Clear events @@ -275,7 +275,7 @@ void TattooJournal::handleButtons() {  		if (frameCounter >= _scrollingTimer) {  			// Set next scrolling time  			_scrollingTimer = frameCounter + 6; -			 +  			// Handle different scrolling actions  			switch (_selector) {  			case JH_SCROLL_LEFT: @@ -355,13 +355,13 @@ void TattooJournal::handleButtons() {  					_savedIndex = _index;  					_savedSub = _sub;  					_savedPage = _page; -					 +  					bool drawResult = drawJournal(dir + 2, 1000 * LINES_PER_PAGE);  					if (!drawResult) {  						_index = _savedIndex;  						_sub = _savedSub;  						_page = _savedPage; -						 +  						drawFrame();  						drawJournal(0, 0);  						notFound = true; @@ -539,7 +539,7 @@ void TattooJournal::drawControls(int mode) {  	_oldSelector = 100;  	switch (mode) { -	case 0:  +	case 0:  		highlightJournalControls(false);  		break;  	case 1: @@ -548,7 +548,7 @@ void TattooJournal::drawControls(int mode) {  	default:  		break;  	} -	 +  	_oldSelector = savedSelector;  } @@ -558,7 +558,7 @@ void TattooJournal::highlightJournalControls(bool slamIt) {  	Common::Point mousePos = events.mousePos();  	Common::Rect r(JOURNAL_BAR_WIDTH, BUTTON_SIZE + screen.fontHeight() + 13);  	r.moveTo((SHERLOCK_SCREEN_WIDTH - r.width()) / 2, SHERLOCK_SCREEN_HEIGHT - r.height()); -	 +  	if ((events._pressed || events._released) && _selector == JH_THUMBNAIL) {  		if (events._released)  			_selector = JH_NONE; @@ -576,7 +576,7 @@ void TattooJournal::highlightJournalControls(bool slamIt) {  		_selector = JH_NONE;  		if (bounds.contains(mousePos))  			_selector = (mousePos.x - r.left) / (r.width() / 3); -	 +  		else if (events._pressed && mousePos.y >= (r.top + screen.fontHeight() + 10)  				&& mousePos.y < (r.top + screen.fontHeight() + 10 + BUTTON_SIZE)) {  			if (mousePos.x >= r.left && mousePos.x < (r.left + BUTTON_SIZE)) @@ -628,7 +628,7 @@ void TattooJournal::highlightJournalControls(bool slamIt) {  			color = (_selector == JH_SAVE) ? COMMAND_HIGHLIGHTED : INFO_TOP;  		else  			color = INFO_BOTTOM; -		screen.gPrint(Common::Point(xp - screen.stringWidth(FIXED(SaveJournal)) / 2, r.top + 5),  +		screen.gPrint(Common::Point(xp - screen.stringWidth(FIXED(SaveJournal)) / 2, r.top + 5),  			color, "%s", FIXED(SaveJournal));  		// Draw the horizontal scrollbar @@ -701,7 +701,7 @@ void TattooJournal::drawScrollBar() {  	raised = _selector != JH_SCROLL_LEFT;  	screen._backBuffer1.fillRect(Common::Rect(r.left, r.top + screen.fontHeight() + 12, r.left + BUTTON_SIZE,  		r.top + screen.fontHeight() + BUTTON_SIZE + 9), INFO_MIDDLE); -	ui.drawDialogRect(screen._backBuffer1, Common::Rect(r.left + 3, r.top + screen.fontHeight() + 10, r.left + 3 + BUTTON_SIZE,  +	ui.drawDialogRect(screen._backBuffer1, Common::Rect(r.left + 3, r.top + screen.fontHeight() + 10, r.left + 3 + BUTTON_SIZE,  		r.top + screen.fontHeight() + 10 + BUTTON_SIZE), raised);  	color = (_page > 1) ? INFO_BOTTOM + 2 : INFO_BOTTOM; @@ -716,15 +716,15 @@ void TattooJournal::drawScrollBar() {  	// Draw the Scroll Right button  	raised = _selector != JH_SCROLL_RIGHT; -	screen._backBuffer1.fillRect(Common::Rect(r.right - BUTTON_SIZE - 1, r.top + screen.fontHeight() + 12,  +	screen._backBuffer1.fillRect(Common::Rect(r.right - BUTTON_SIZE - 1, r.top + screen.fontHeight() + 12,  		r.right - 5, r.top + screen.fontHeight() + BUTTON_SIZE + 9), INFO_MIDDLE);  	ui.drawDialogRect(screen._backBuffer1, Common::Rect(r.right - BUTTON_SIZE - 3, r.top + screen.fontHeight() + 10, r.right - 3,  		r.top + screen.fontHeight() + BUTTON_SIZE + 9), raised);  	color = _down ? INFO_BOTTOM + 2 : INFO_BOTTOM; -	screen._backBuffer1.vLine(r.right - 1 - BUTTON_SIZE + BUTTON_SIZE / 2, r.top + screen.fontHeight() + 10 + BUTTON_SIZE / 2,  +	screen._backBuffer1.vLine(r.right - 1 - BUTTON_SIZE + BUTTON_SIZE / 2, r.top + screen.fontHeight() + 10 + BUTTON_SIZE / 2,  		r.top + screen.fontHeight() + 10 + BUTTON_SIZE / 2, color); -	screen._backBuffer1.vLine(r.right - 2 - BUTTON_SIZE + BUTTON_SIZE / 2, r.top + screen.fontHeight() + 9 + BUTTON_SIZE / 2,  +	screen._backBuffer1.vLine(r.right - 2 - BUTTON_SIZE + BUTTON_SIZE / 2, r.top + screen.fontHeight() + 9 + BUTTON_SIZE / 2,  		r.top + screen.fontHeight() + 11 + BUTTON_SIZE / 2, color);  	screen._backBuffer1.vLine(r.right - 3 - BUTTON_SIZE + BUTTON_SIZE / 2, r.top + screen.fontHeight() + 8 + BUTTON_SIZE / 2,  		r.top + screen.fontHeight() + 12 + BUTTON_SIZE / 2, color); @@ -776,14 +776,14 @@ int TattooJournal::getFindName(bool printError) {  	drawControls(1);  	disableControls(); -	 +  	// Backup the area under the text entry  	Surface bgSurface(r.width() - 6, screen.fontHeight()); -	bgSurface.SHblitFrom(screen._backBuffer1, Common::Point(0, 0), Common::Rect(r.left + 3, cursorY,  +	bgSurface.SHblitFrom(screen._backBuffer1, Common::Point(0, 0), Common::Rect(r.left + 3, cursorY,  		r.right - 3, cursorY + screen.fontHeight()));  	if (printError) { -		screen.gPrint(Common::Point(r.left + (r.width() - screen.stringWidth(FIXED(TextNotFound))) / 2, cursorY),  +		screen.gPrint(Common::Point(r.left + (r.width() - screen.stringWidth(FIXED(TextNotFound))) / 2, cursorY),  			INFO_TOP, "%s", FIXED(TextNotFound));  	} else {  		// If there was a name already entered, copy it to name and display it @@ -977,7 +977,7 @@ void TattooJournal::saveJournal() {  		int line = 0;  		// Copy all of the talk files entries into one big string -		do {	 +		do {  			if (_lines[line].hasPrefix("@")) {  				text += Common::String(_lines[line].c_str() + 1);  				if ((line + 1) < (int)_lines.size() && _lines[line + 1].hasPrefix("@")) @@ -992,7 +992,7 @@ void TattooJournal::saveJournal() {  				// which show up as a blank line with the next line starting  				// with a '@'. We have to add a line break here because the '@' handler  				// previously assumes that they're always following a blank line -				 +  				if ((_lines[line].empty() || _lines[line] == " ")  						&& (line + 1) < (int)_lines.size() && _lines[line + 1].hasPrefix("@"))  					text += "\n"; @@ -1005,7 +1005,7 @@ void TattooJournal::saveJournal() {  		do {  			if (text.size() > 80) {  				const char *msgP = text.c_str() + 80; -				 +  				if (Common::String(text.c_str(), msgP).contains("\n")) {  					// The 80 characters contain a carriage return,  					// so we can print out that line @@ -1013,7 +1013,7 @@ void TattooJournal::saveJournal() {  					file->writeString(Common::String(text.c_str(), cr));  					text = Common::String(cr + 1);  				} else { -					// Move backwards to find a word break				 +					// Move backwards to find a word break  					while (*msgP != ' ')  						--msgP; diff --git a/engines/sherlock/tattoo/tattoo_people.h b/engines/sherlock/tattoo/tattoo_people.h index e0d53c67dd..c844d86e19 100644 --- a/engines/sherlock/tattoo/tattoo_people.h +++ b/engines/sherlock/tattoo/tattoo_people.h @@ -273,9 +273,8 @@ public:  	virtual void setListenSequence(int speaker, int sequenceNum = 1);  }; -} // End of namespace Scalpel +} // End of namespace Tattoo  } // End of namespace Sherlock -  #endif diff --git a/engines/sky/control.cpp b/engines/sky/control.cpp index dfdd765120..9f78234aba 100644 --- a/engines/sky/control.cpp +++ b/engines/sky/control.cpp @@ -324,7 +324,11 @@ void Control::initPanel() {  }  void Control::buttonControl(ConResource *pButton) { -	char autoSave[] = "Restore Autosave"; +	char autoSave[50] = "Restore Autosave"; + +	if (Common::parseLanguage(ConfMan.get("language")) == Common::RU_RUS) +		strncpy(autoSave, "Zarpyzit/ abtocoxpahehie", 50); +  	if (pButton == NULL) {  		free(_textSprite);  		_textSprite = NULL; @@ -525,8 +529,13 @@ void Control::doControlPanel() {  }  uint16 Control::handleClick(ConResource *pButton) { -	char quitDos[] = "Quit to DOS?"; -	char restart[] = "Restart?"; +	char quitDos[50] = "Quit to DOS?"; +	char restart[50] = "Restart?"; + +	if (Common::parseLanguage(ConfMan.get("language")) == Common::RU_RUS) { +		strncpy(quitDos, "B[uti b DOC?", 50); +		strncpy(restart, "Hobaq irpa?", 50); +	}  	switch (pButton->_onClick) {  	case DO_NOTHING: @@ -1562,8 +1571,13 @@ void Control::showGameQuitMsg() {  	screenData = _skyScreen->giveCurrent(); -	_skyText->displayText(_quitTexts[SkyEngine::_systemVars.language * 2 + 0], textBuf1, true, 320, 255); -	_skyText->displayText(_quitTexts[SkyEngine::_systemVars.language * 2 + 1], textBuf2, true, 320, 255); +	if (Common::parseLanguage(ConfMan.get("language")) == Common::RU_RUS) { +		_skyText->displayText(_quitTexts[8 * 2 + 0], textBuf1, true, 320, 255); +		_skyText->displayText(_quitTexts[8 * 2 + 1], textBuf2, true, 320, 255); +	} else { +		_skyText->displayText(_quitTexts[SkyEngine::_systemVars.language * 2 + 0], textBuf1, true, 320, 255); +		_skyText->displayText(_quitTexts[SkyEngine::_systemVars.language * 2 + 1], textBuf2, true, 320, 255); +	}  	uint8 *curLine1 = textBuf1 + sizeof(DataFileHeader);  	uint8 *curLine2 = textBuf2 + sizeof(DataFileHeader);  	uint8 *targetLine = screenData + GAME_SCREEN_WIDTH * 80; @@ -1584,7 +1598,7 @@ void Control::showGameQuitMsg() {  	free(textBuf2);  } -char Control::_quitTexts[16][35] = { +char Control::_quitTexts[18][35] = {  	"Game over player one",  	"BE VIGILANT",  	"Das Spiel ist aus.", @@ -1600,7 +1614,9 @@ char Control::_quitTexts[16][35] = {  	"Fim de jogo para o jogador um",  	"BE VIGILANT",  	"Game over player one", -	"BE VIGILANT" +	"BE VIGILANT", +	"Irpa okohseha, irpok 1", +	"JYD\x96 JDITELEH"  };  uint8 Control::_crossImg[594] = { diff --git a/engines/sky/control.h b/engines/sky/control.h index 44591f299d..2089c74363 100644 --- a/engines/sky/control.h +++ b/engines/sky/control.h @@ -292,7 +292,7 @@ private:  	ControlStatus *_statusBar; -	static char _quitTexts[16][35]; +	static char _quitTexts[18][35];  	static uint8 _crossImg[594];  }; diff --git a/engines/sky/skydefs.h b/engines/sky/skydefs.h index 167b7dade2..ed07a5e2cd 100644 --- a/engines/sky/skydefs.h +++ b/engines/sky/skydefs.h @@ -45,6 +45,7 @@ namespace Sky {  #define SKY_ITALIAN		5  #define SKY_PORTUGUESE	6  #define SKY_SPANISH		7 +#define SKY_RUSSIAN		8  #define ST_COLLISION_BIT	5 diff --git a/engines/sword2/screen.cpp b/engines/sword2/screen.cpp index 0cb951fdfc..40baf67e46 100644 --- a/engines/sword2/screen.cpp +++ b/engines/sword2/screen.cpp @@ -1296,7 +1296,7 @@ void Screen::setPsxScrCache(byte *psxScrCache, uint8 level) {  }  byte *Screen::getPsxScrCache(uint8 level) { -	if (level > 3) { +	if (level > 2) {  		level = 0;  	} @@ -1307,7 +1307,7 @@ byte *Screen::getPsxScrCache(uint8 level) {  }  bool Screen::getPsxScrCacheStatus(uint8 level) { -	if (level > 3) { +	if (level > 2) {  		level = 0;  	} diff --git a/engines/sword25/gfx/image/vectorimage.cpp b/engines/sword25/gfx/image/vectorimage.cpp index a678fdccad..5d35a4f47e 100644 --- a/engines/sword25/gfx/image/vectorimage.cpp +++ b/engines/sword25/gfx/image/vectorimage.cpp @@ -217,6 +217,7 @@ Common::Rect CalculateBoundingBox(const VectorImageElement &vectorImageElement)  VectorImage::VectorImage(const byte *pFileData, uint fileSize, bool &success, const Common::String &fname) : _pixelData(0), _fname(fname) {  	success = false; +	_bgColor = 0;  	// Create bitstream object  	// In the following the file data will be readout of the bitstream object. diff --git a/engines/sword25/gfx/renderobject.cpp b/engines/sword25/gfx/renderobject.cpp index c109e49aa8..92d39c252d 100644 --- a/engines/sword25/gfx/renderobject.cpp +++ b/engines/sword25/gfx/renderobject.cpp @@ -71,19 +71,18 @@ RenderObject::RenderObject(RenderObjectPtr<RenderObject> parentPtr, TYPES type,  	_version(++_nextGlobalVersion),  	_isSolid(false) { -	// Renderobject registrieren, abhängig vom Handle-Parameter entweder mit beliebigem oder vorgegebenen Handle.  	if (handle == 0)  		_handle = RenderObjectRegistry::instance().registerObject(this);  	else  		_handle = RenderObjectRegistry::instance().registerObject(this, handle);  	if (_handle == 0) -		return; +		error("Failed to initialize RenderObject()");  	updateAbsolutePos(); -	// Dieses Objekt zu den Kindern der Elternobjektes hinzufügen, falls nicht Wurzel (ParentPtr ungültig) und dem -	// selben RenderObjektManager zuweisen. +	// Add this item to the children of the parent object, if not root (ParentPtr is invalid), +	// assign to the same RenderObjectManager.  	if (_parentPtr.isValid()) {  		_managerPtr = _parentPtr->getManager();  		_parentPtr->addObject(this->getHandle()); @@ -100,24 +99,22 @@ RenderObject::RenderObject(RenderObjectPtr<RenderObject> parentPtr, TYPES type,  }  RenderObject::~RenderObject() { -	// Objekt aus dem Elternobjekt entfernen. +	// Remove object from its parent.  	if (_parentPtr.isValid())  		_parentPtr->detatchChildren(this->getHandle());  	deleteAllChildren(); -	// Objekt deregistrieren.  	RenderObjectRegistry::instance().deregisterObject(this);  }  void RenderObject::preRender(RenderObjectQueue *renderQueue) { -	// Objektänderungen validieren  	validateObject();  	if (!_visible)  		return; -	// Falls notwendig, wird die Renderreihenfolge der Kinderobjekte aktualisiert. +	// If necessary, update the children rendering order of the updated objects.  	if (_childChanged) {  		sortRenderObjects();  		_childChanged = false; @@ -149,7 +146,7 @@ bool RenderObject::render(RectangleList *updateRects, const Common::Array<int> &  	if (needRender)  		doRender(updateRects); -	// Dann müssen die Kinder gezeichnet werden +	// Draw all children  	RENDEROBJECT_ITER it = _children.begin();  	for (; it != _children.end(); ++it)  		if (!(*it)->render(updateRects, updateRectsMinZ)) @@ -159,7 +156,6 @@ bool RenderObject::render(RectangleList *updateRects, const Common::Array<int> &  }  void RenderObject::validateObject() { -	// Die Veränderungen in den Objektvariablen aufheben  	_oldBbox = _bbox;  	_oldVisible = _visible;  	_oldX = _x; @@ -169,15 +165,14 @@ void RenderObject::validateObject() {  }  bool RenderObject::updateObjectState() { -	// Falls sich das Objekt verändert hat, muss der interne Zustand neu berechnet werden und evtl. Update-Regions für den nächsten Frame -	// registriert werden. +	// If the object has changed, the internal state must be recalculated and possibly +	// update Regions be registered for the next frame.  	if ((calcBoundingBox() != _oldBbox) ||  	        (_visible != _oldVisible) ||  	        (_x != _oldX) ||  	        (_y != _oldY) ||  	        (_z != _oldZ) ||  	        _refreshForced) { -		// Renderrang des Objektes neu bestimmen, da sich dieser verändert haben könnte  		if (_parentPtr.isValid())  			_parentPtr->signalChildChange(); @@ -200,12 +195,10 @@ bool RenderObject::updateObjectState() {  }  void RenderObject::updateBoxes() { -	// Bounding-Box aktualisieren  	_bbox = calcBoundingBox();  }  Common::Rect RenderObject::calcBoundingBox() const { -	// Die Bounding-Box mit der Objektgröße initialisieren.  	Common::Rect bbox(0, 0, _width, _height);  	// Die absolute Position der Bounding-Box berechnen. @@ -247,8 +240,6 @@ int32 RenderObject::calcAbsoluteZ() const {  }  void RenderObject::deleteAllChildren() { -	// Es ist nicht notwendig die Liste zu iterieren, da jedes Kind für sich DetatchChildren an diesem Objekt aufruft und sich somit -	// selber entfernt. Daher muss immer nur ein beliebiges Element (hier das letzte) gelöscht werden, bis die Liste leer ist.  	while (!_children.empty()) {  		RenderObjectPtr<RenderObject> curPtr = _children.back();  		curPtr.erase(); @@ -261,10 +252,10 @@ bool RenderObject::addObject(RenderObjectPtr<RenderObject> pObject) {  		return false;  	} -	// Objekt in die Kinderliste einfügen. +	// Insert Object in the children list.  	_children.push_back(pObject); -	// Sicherstellen, dass vor dem nächsten Rendern die Renderreihenfolge aktualisiert wird. +	// Make sure that before the next render the channel order is updated.  	if (_parentPtr.isValid())  		_parentPtr->signalChildChange(); diff --git a/engines/teenagent/music.cpp b/engines/teenagent/music.cpp index 5d66c3c90c..795b8f7312 100644 --- a/engines/teenagent/music.cpp +++ b/engines/teenagent/music.cpp @@ -36,7 +36,7 @@ static const uint32 noteToPeriod[3][12] = {  	{214, 201, 189, 179, 170, 160, 151, 143, 135, 127, 120, 113}  }; -MusicPlayer::MusicPlayer(TeenAgentEngine *vm) : Paula(false, 44100, 5000), _vm(vm), _id(0) { +MusicPlayer::MusicPlayer(TeenAgentEngine *vm) : Paula(false, 44100, 5000), _vm(vm), _id(0), _currRow(0) {  }  MusicPlayer::~MusicPlayer() { @@ -55,7 +55,7 @@ bool MusicPlayer::load(int id) {  	Common::StackLock lock(_mutex);  	// Load the samples -	sampleCount = stream->readByte(); +	byte sampleCount = stream->readByte();  	debugC(0, kDebugMusic, "sampleCount = %d", sampleCount); diff --git a/engines/teenagent/music.h b/engines/teenagent/music.h index e1630cc845..4b1b683a30 100644 --- a/engines/teenagent/music.h +++ b/engines/teenagent/music.h @@ -74,7 +74,6 @@ private:  			size = 0;  		}  	} _samples[256]; -	byte sampleCount;  	Common::Array<Row> _rows;  	uint _currRow; diff --git a/engines/teenagent/objects.h b/engines/teenagent/objects.h index f923ae52ab..1f8a82a66e 100644 --- a/engines/teenagent/objects.h +++ b/engines/teenagent/objects.h @@ -165,7 +165,7 @@ struct Object {  	//19  	Common::String name, description; -	Object(): _base(NULL) {} +	Object(): _base(NULL) { id = 0; actorOrientation = 0; enabled = 0;  }  	void dump(int level = 0) const;  	void setName(const Common::String &newName);  	void load(byte *addr); @@ -205,7 +205,7 @@ struct Walkbox {  	Rect rect;  	byte sideHint[4]; -	Walkbox() : _base(NULL) {} +	Walkbox() : _base(NULL) { memset(this, 0, sizeof(Walkbox)); }  	void dump(int level = 0) const;  	void load(byte *src);  	void save() const; diff --git a/engines/teenagent/scene.cpp b/engines/teenagent/scene.cpp index 6e1cef31bc..c250269844 100644 --- a/engines/teenagent/scene.cpp +++ b/engines/teenagent/scene.cpp @@ -71,6 +71,9 @@ Scene::Scene(TeenAgentEngine *vm) : _vm(vm), intro(false), _id(0), ons(0),  	varia.close();  	loadObjectData(); + +	_onsCount = 0; +	_messageColor = 0;  }  Scene::~Scene() { @@ -314,7 +317,7 @@ void Scene::loadOns() {  	uint16 addr = _vm->res->dseg.get_word(dsAddr_onsAnimationTablePtr + (_id - 1) * 2);  	debugC(0, kDebugScene, "ons index: %04x", addr); -	onsCount = 0; +	_onsCount = 0;  	byte b;  	byte onId[16];  	while ((b = _vm->res->dseg.get_byte(addr)) != 0xff) { @@ -323,15 +326,15 @@ void Scene::loadOns() {  		if (b == 0)  			continue; -		onId[onsCount++] = b; +		onId[_onsCount++] = b;  	}  	delete[] ons;  	ons = NULL; -	if (onsCount > 0) { -		ons = new Surface[onsCount]; -		for (uint32 i = 0; i < onsCount; ++i) { +	if (_onsCount > 0) { +		ons = new Surface[_onsCount]; +		for (uint32 i = 0; i < _onsCount; ++i) {  			Common::ScopedPtr<Common::SeekableReadStream> s(_vm->res->ons.getStream(onId[i]));  			if (s) {  				ons[i].load(*s, Surface::kTypeOns); @@ -498,7 +501,7 @@ bool Scene::processEvent(const Common::Event &event) {  				events.clear();  				sounds.clear();  				currentEvent.clear(); -				messageColor = textColorMark; +				_messageColor = textColorMark;  				for (int i = 0; i < 4; ++i)  					customAnimation[i].free();  				_vm->playMusic(4); @@ -651,7 +654,7 @@ bool Scene::render(bool tickGame, bool tickMark, uint32 messageDelta) {  		bool gotAnyAnimation = false;  		if (ons != NULL && debugFeatures.feature[DebugFeatures::kShowOns]) { -			for (uint32 i = 0; i < onsCount; ++i) { +			for (uint32 i = 0; i < _onsCount; ++i) {  				Surface *s = ons + i;  				if (s != NULL)  					s->render(surface); @@ -821,7 +824,7 @@ bool Scene::render(bool tickGame, bool tickMark, uint32 messageDelta) {  			}  			if (visible) { -				_vm->res->font7.render(surface, messagePos.x, messagePos.y, message, messageColor); +				_vm->res->font7.render(surface, messagePos.x, messagePos.y, message, _messageColor);  				busy = true;  			}  		} @@ -1005,7 +1008,7 @@ bool Scene::processEventQueue() {  					warning("no animation in slot %u", messageSlot);  			}  			messagePos = messagePosition(message, p); -			messageColor = currentEvent.color; +			_messageColor = currentEvent.color;  			if (messageFirstFrame)  				currentEvent.clear(); // async message, clearing event @@ -1153,7 +1156,7 @@ bool Scene::processEventQueue() {  	}  	if (events.empty()) { -		messageColor = textColorMark; +		_messageColor = textColorMark;  		hideActor = false;  	} @@ -1232,7 +1235,7 @@ void Scene::displayMessage(const Common::String &str, byte color, const Common::  	debugC(0, kDebugScene, "displayMessage: %s", str.c_str());  	message = str;  	messagePos = (pos.x | pos.y) ? pos : messagePosition(str, position); -	messageColor = color; +	_messageColor = color;  	messageTimer = messageDuration(message);  } @@ -1251,7 +1254,7 @@ void Scene::clear() {  void Scene::clearMessage() {  	message.clear();  	messageTimer = 0; -	messageColor = textColorMark; +	_messageColor = textColorMark;  	messageFirstFrame = 0;  	messageLastFrame = 0;  	messageAnimation = NULL; diff --git a/engines/teenagent/scene.h b/engines/teenagent/scene.h index 07b304ed97..40f910a3aa 100644 --- a/engines/teenagent/scene.h +++ b/engines/teenagent/scene.h @@ -194,7 +194,7 @@ private:  	SurfaceList on;  	bool onEnabled;  	Surface *ons; -	uint32 onsCount; +	uint32 _onsCount;  	Animation actorAnimation, animation[4], customAnimation[4];  	Common::Rect actorAnimationPosition, animationPosition[4]; @@ -214,7 +214,7 @@ private:  	Common::String message;  	Common::Point messagePos; -	byte messageColor; +	byte _messageColor;  	uint messageTimer;  	byte messageFirstFrame;  	byte messageLastFrame; diff --git a/engines/teenagent/teenagent.cpp b/engines/teenagent/teenagent.cpp index 4dc785754c..2d10b82f51 100644 --- a/engines/teenagent/teenagent.cpp +++ b/engines/teenagent/teenagent.cpp @@ -71,6 +71,13 @@ TeenAgentEngine::TeenAgentEngine(OSystem *system, const ADGameDescription *gd)  	res = new Resources();  	console = 0; +	scene = 0; +	inventory = 0; +	_sceneBusy = false; +	_dstObject = 0; +	_musicStream = 0; +	_markDelay = 0; +	_gameDelay = 0;  }  TeenAgentEngine::~TeenAgentEngine() { diff --git a/engines/tinsel/dialogs.cpp b/engines/tinsel/dialogs.cpp index a84dad942c..4bc28ffb53 100644 --- a/engines/tinsel/dialogs.cpp +++ b/engines/tinsel/dialogs.cpp @@ -3676,13 +3676,13 @@ extern void HideConversation(bool bHide) {  				ConstructInventory(FULL);  			else {  				// Move it all back on-screen -				for (i = 0; g_objArray[i] && i < MAX_WCOMP; i++) { +				for (i = 0; i < MAX_WCOMP && g_objArray[i]; i++) {  					MultiAdjustXY(g_objArray[i], -2 * SCREEN_WIDTH, 0);  				}  				// Don't flash if items changed. If they have, will be redrawn anyway.  				if (TinselV2 || !g_ItemsChanged) { -					for (i = 0; g_iconArray[i] && i < MAX_ICONS; i++) { +					for (i = 0; i < MAX_ICONS && g_iconArray[i]; i++) {  						MultiAdjustXY(g_iconArray[i], -2*SCREEN_WIDTH, 0);  					}  				} @@ -3739,10 +3739,10 @@ extern void HideConversation(bool bHide) {  				deltay = g_InvD[INV_CONV].inventoryY - deltay;  				// Move it all -				for (i = 0; g_objArray[i] && i < MAX_WCOMP; i++) { +				for (i = 0; i < MAX_WCOMP && g_objArray[i]; i++) {  					MultiMoveRelXY(g_objArray[i], x - center, deltay);  				} -				for (i = 0; g_iconArray[i] && i < MAX_ICONS; i++) { +				for (i = 0; i < MAX_ICONS && g_iconArray[i]; i++) {  					MultiMoveRelXY(g_iconArray[i], x - center, deltay);  				}  				g_InvD[INV_CONV].inventoryX += x - center; @@ -3771,10 +3771,10 @@ extern void HideConversation(bool bHide) {  					y = 0;  				if (x || y) { -					for (i = 0; g_objArray[i] && i < MAX_WCOMP; i++) { +					for (i = 0; i < MAX_WCOMP && g_objArray[i]; i++) {  						MultiMoveRelXY(g_objArray[i], x, y);  					} -					for (i = 0; g_iconArray[i] && i < MAX_ICONS; i++) { +					for (i = 0; i < MAX_ICONS && g_iconArray[i]; i++) {  						MultiMoveRelXY(g_iconArray[i], x, y);  					}  					g_InvD[INV_CONV].inventoryX += x; @@ -3786,10 +3786,10 @@ extern void HideConversation(bool bHide) {  				 */  				if (MultiLowest(g_RectObject) > SCREEN_BOX_HEIGHT2 - SysVar(SV_CONV_MINY)) {  					y = (SCREEN_BOX_HEIGHT2 - SysVar(SV_CONV_MINY)) - MultiLowest(g_RectObject); -					for (i = 0; g_objArray[i] && i < MAX_WCOMP; i++) { +					for (i = 0; i < MAX_WCOMP && g_objArray[i]; i++) {  						MultiMoveRelXY(g_objArray[i], 0, y);  					} -					for (i = 0; g_iconArray[i] && i < MAX_ICONS; i++) { +					for (i = 0; i < MAX_ICONS && g_iconArray[i]; i++) {  						MultiMoveRelXY(g_iconArray[i], 0, y);  					}  					g_InvD[INV_CONV].inventoryY += y; diff --git a/engines/toltecs/movie.cpp b/engines/toltecs/movie.cpp index b64903ec6d..b26408fadc 100644 --- a/engines/toltecs/movie.cpp +++ b/engines/toltecs/movie.cpp @@ -45,7 +45,7 @@ enum ChunkTypes {  	kChunkStopSubtitles = 8  }; -MoviePlayer::MoviePlayer(ToltecsEngine *vm) : _vm(vm), _isPlaying(false), _lastPrefetchOfs(0), _framesPerSoundChunk(0), _endPos(0) { +MoviePlayer::MoviePlayer(ToltecsEngine *vm) : _vm(vm), _isPlaying(false), _lastPrefetchOfs(0), _framesPerSoundChunk(0), _endPos(0), _audioStream(0) {  }  MoviePlayer::~MoviePlayer() { diff --git a/engines/toltecs/resource.cpp b/engines/toltecs/resource.cpp index 468ae0272f..6dbb9c2843 100644 --- a/engines/toltecs/resource.cpp +++ b/engines/toltecs/resource.cpp @@ -31,6 +31,7 @@ namespace Toltecs {  /* ArchiveReader */  ArchiveReader::ArchiveReader() { +	_offsets = 0;  }  ArchiveReader::~ArchiveReader() { diff --git a/engines/toltecs/sprite.cpp b/engines/toltecs/sprite.cpp index f29f64dcfe..be4be5d9e3 100644 --- a/engines/toltecs/sprite.cpp +++ b/engines/toltecs/sprite.cpp @@ -84,6 +84,7 @@ public:  		_yerror = _sprite->yerror;  		_origHeight = _sprite->origHeight;  		_scalerStatus = 0; +		_xerror = 0;  	}  	SpriteReaderStatus readPacket(PixelPacket &packet) {  		SpriteReaderStatus status = kSrsPixelsLeft; @@ -135,6 +136,8 @@ public:  		_yerror = _sprite->yerror;  		_origHeight = _sprite->origHeight;  		_scalerStatus = 0; +		_sourcep = 0; +		_xerror = 0;  	}  	SpriteReaderStatus readPacket(PixelPacket &packet) {  		SpriteReaderStatus status; diff --git a/engines/tony/gfxcore.cpp b/engines/tony/gfxcore.cpp index 2a32926c53..27145d7c4b 100644 --- a/engines/tony/gfxcore.cpp +++ b/engines/tony/gfxcore.cpp @@ -1733,13 +1733,6 @@ void RMGfxSourceBuffer8AA::drawAA(RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *pri  				g /= 5;  				b /= 5; -				if (r > 0x1f) -					r = 0x1f; -				if (g > 0x3f) -					g = 0x3f; -				if (b > 0x1f) -					b = 0x1f; -  				mybuf[0] = (r << 11) | (g << 5) | b;  			}  		} @@ -1774,13 +1767,6 @@ void RMGfxSourceBuffer8AA::drawAA(RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *pri  				g /= 6;  				b /= 6; -				if (r > 0x1f) -					r = 0x1f; -				if (g > 0x3f) -					g = 0x3f; -				if (b > 0x1f) -					b = 0x1f; -  				mybuf[0] = (r << 11) | (g << 5) | b;  			}  		} diff --git a/engines/tony/mpal/loadmpc.cpp b/engines/tony/mpal/loadmpc.cpp index 8d030f1e52..01892a40e6 100644 --- a/engines/tony/mpal/loadmpc.cpp +++ b/engines/tony/mpal/loadmpc.cpp @@ -331,7 +331,7 @@ static const byte *parseItem(const byte *lpBuf, LpMpalItem lpmiItem) {  	byte len = *lpBuf;  	lpBuf++; -	memcpy(lpmiItem->_lpszDescribe, lpBuf, MIN((byte)127, len)); +	memcpy(lpmiItem->_lpszDescribe, lpBuf, MIN((byte)MAX_DESCRIBE_SIZE, len));  	lpBuf += len;  	if (len >= MAX_DESCRIBE_SIZE) diff --git a/engines/tony/mpal/mpal.cpp b/engines/tony/mpal/mpal.cpp index 89cc28130d..9172843781 100644 --- a/engines/tony/mpal/mpal.cpp +++ b/engines/tony/mpal/mpal.cpp @@ -367,12 +367,18 @@ MpalHandle resLoad(uint32 dwId) {  			temp = (byte *)globalAlloc(GMEM_FIXED | GMEM_ZEROINIT, nSizeComp);  			nBytesRead = GLOBALS._hMpr.read(temp, nSizeComp); -			if (nBytesRead != nSizeComp) +			if (nBytesRead != nSizeComp) { +				globalDestroy(temp); +				globalDestroy(h);  				return NULL; +			}  			lzo1x_decompress(temp, nSizeComp, buf, &nBytesRead); -			if (nBytesRead != nSizeDecomp) +			if (nBytesRead != nSizeDecomp) { +				globalDestroy(temp); +				globalDestroy(h);  				return NULL; +			}  			globalDestroy(temp);  			globalUnlock(h); @@ -526,8 +532,10 @@ static LpItem getItemData(uint32 nOrdItem) {  	globalFree(hDat);  	// Check if we've got to the end of the file -	if (i != 0xABCD) +	if (i != 0xABCD) { +		globalDestroy(ret);  		return NULL; +	}  	return ret;  } @@ -1413,36 +1421,51 @@ bool mpalInit(const char *lpszMpcFileName, const char *lpszMprFileName,  	if (bCompress) {  		// Get the compressed size and read the data in  		uint32 dwSizeComp = hMpc.readUint32LE(); -		if (hMpc.err()) +		if (hMpc.err()) { +			globalDestroy(lpMpcImage);  			return false; +		}  		cmpbuf = (byte *)globalAlloc(GMEM_FIXED, dwSizeComp); -		if (cmpbuf == NULL) +		if (cmpbuf == NULL) { +			globalDestroy(lpMpcImage);  			return false; +		}  		nBytesRead = hMpc.read(cmpbuf, dwSizeComp); -		if (nBytesRead != dwSizeComp) +		if (nBytesRead != dwSizeComp) { +			globalDestroy(cmpbuf); +			globalDestroy(lpMpcImage);  			return false; +		}  		// Decompress the data  		lzo1x_decompress(cmpbuf, dwSizeComp, lpMpcImage, &nBytesRead); -		if (nBytesRead != dwSizeDecomp) +		if (nBytesRead != dwSizeDecomp) { +			globalDestroy(cmpbuf); +			globalDestroy(lpMpcImage);  			return false; +		}  		globalDestroy(cmpbuf);  	} else {  		// If the file is not compressed, we directly read in the data  		nBytesRead = hMpc.read(lpMpcImage, dwSizeDecomp); -		if (nBytesRead != dwSizeDecomp) +		if (nBytesRead != dwSizeDecomp) { +			globalDestroy(lpMpcImage);  			return false; +		}  	}  	// Close the file  	hMpc.close();  	// Process the data -	if (parseMpc(lpMpcImage) == false) +	if (parseMpc(lpMpcImage) == false) { +		globalDestroy(lpMpcImage); +  		return false; +	}  	globalDestroy(lpMpcImage); diff --git a/engines/tsage/ringworld2/ringworld2_scenes2.cpp b/engines/tsage/ringworld2/ringworld2_scenes2.cpp index bd8a0cdd0d..6b44ecc514 100644 --- a/engines/tsage/ringworld2/ringworld2_scenes2.cpp +++ b/engines/tsage/ringworld2/ringworld2_scenes2.cpp @@ -1440,7 +1440,7 @@ void Scene2425::postInit(SceneObjectList *OwnerList) {  	case 2425:  		_sceneMode = 10;  		R2_GLOBALS._player.setPosition(Common::Point(280, 150)); -		_action->signal(); +		signal();  		break;  	case 2455:  		_sceneMode = 2428; diff --git a/engines/wage/debugger.cpp b/engines/wage/debugger.cpp index 7d01b0b85e..d34aca7d49 100644 --- a/engines/wage/debugger.cpp +++ b/engines/wage/debugger.cpp @@ -56,7 +56,7 @@ static int strToInt(const char *s) {  }  bool Debugger::Cmd_ListScenes(int argc, const char **argv) { -	int currentScene; +	int currentScene = 0;  	for (uint i = 1; i < _engine->_world->_orderedScenes.size(); i++) { // #0 is STORAGE@  		if (_engine->_world->_player->_currentScene == _engine->_world->_orderedScenes[i]) diff --git a/engines/wage/design.cpp b/engines/wage/design.cpp index 185c051eb6..eda28df159 100644 --- a/engines/wage/design.cpp +++ b/engines/wage/design.cpp @@ -45,8 +45,10 @@   *   */ +#include "graphics/managed_surface.h"  #include "graphics/primitives.h" -#include "wage/wage.h" + +#include "wage/macwindowmanager.h"  #include "wage/design.h"  namespace Wage { @@ -208,9 +210,9 @@ void drawPixel(int x, int y, int color, void *data) {  		if (p->thickness == 1) {  			p->design->adjustBounds(x, y);  		} else { -			int x1 = x - p->thickness / 2; +			int x1 = x;  			int x2 = x1 + p->thickness; -			int y1 = y - p->thickness / 2; +			int y1 = y;  			int y2 = y1 + p->thickness;  			for (y = y1; y < y2; y++) @@ -233,9 +235,9 @@ void drawPixel(int x, int y, int color, void *data) {  					color : kColorWhite;  		}  	} else { -		int x1 = x - p->thickness / 2; +		int x1 = x;  		int x2 = x1 + p->thickness; -		int y1 = y - p->thickness / 2; +		int y1 = y;  		int y2 = y1 + p->thickness;  		for (y = y1; y < y2; y++) diff --git a/engines/wage/design.h b/engines/wage/design.h index a6e0df4c40..9b0231ca96 100644 --- a/engines/wage/design.h +++ b/engines/wage/design.h @@ -48,10 +48,11 @@  #ifndef WAGE_DESIGN_H  #define WAGE_DESIGN_H -#include "graphics/managed_surface.h"  #include "common/memstream.h"  #include "common/rect.h" +#include "wage/macwindowmanager.h" +  namespace Wage {  class Design { diff --git a/engines/wage/dialog.cpp b/engines/wage/dialog.cpp index 263570bddc..d9bb3e6a61 100644 --- a/engines/wage/dialog.cpp +++ b/engines/wage/dialog.cpp @@ -49,6 +49,7 @@  #include "common/events.h"  #include "wage/wage.h" +#include "wage/macwindowmanager.h"  #include "wage/design.h"  #include "wage/gui.h"  #include "wage/dialog.h" @@ -88,11 +89,11 @@ Dialog::~Dialog() {  }  const Graphics::Font *Dialog::getDialogFont() { -	return _gui->getFont("Chicago-12", Graphics::FontManager::kBigGUIFont); +	return _gui->_wm.getFont("Chicago-12", Graphics::FontManager::kBigGUIFont);  }  void Dialog::paint() { -	Design::drawFilledRect(&_gui->_screen, _bbox, kColorWhite, _gui->_patterns, kPatternSolid); +	Design::drawFilledRect(&_gui->_screen, _bbox, kColorWhite, _gui->_wm.getPatterns(), kPatternSolid);  	_font->drawString(&_gui->_screen, _text, _bbox.left + 24, _bbox.top + 16, _bbox.width(), kColorBlack);  	static int boxOutline[] = { 1, 0, 0, 1, 1 }; @@ -114,7 +115,7 @@ void Dialog::paint() {  			Common::Rect bb(button->bounds.left + 5, button->bounds.top + 5,  				button->bounds.right - 5, button->bounds.bottom - 5); -			Design::drawFilledRect(&_gui->_screen, bb, kColorBlack, _gui->_patterns, kPatternSolid); +			Design::drawFilledRect(&_gui->_screen, bb, kColorBlack, _gui->_wm.getPatterns(), kPatternSolid);  			color = kColorWhite;  		} @@ -137,7 +138,7 @@ void Dialog::drawOutline(Common::Rect &bounds, int *spec, int speclen) {  	for (int i = 0; i < speclen; i++)  		if (spec[i] != 0)  			Design::drawRect(&_gui->_screen, bounds.left + i, bounds.top + i, bounds.right - i, bounds.bottom - i, -						1, kColorBlack, _gui->_patterns, kPatternSolid); +						1, kColorBlack, _gui->_wm.getPatterns(), kPatternSolid);  }  int Dialog::run() { @@ -145,7 +146,7 @@ int Dialog::run() {  	Common::Rect r(_bbox);  	_tempSurface.copyRectToSurface(_gui->_screen.getBasePtr(_bbox.left, _bbox.top), _gui->_screen.pitch, 0, 0, _bbox.width() + 1, _bbox.height() + 1); -	_gui->pushArrowCursor(); +	_gui->_wm.pushArrowCursor();  	while (!shouldQuit) {  		Common::Event event; @@ -189,7 +190,7 @@ int Dialog::run() {  	_gui->_screen.copyRectToSurface(_tempSurface.getBasePtr(0, 0), _tempSurface.pitch, _bbox.left, _bbox.top, _bbox.width() + 1, _bbox.height() + 1);  	g_system->copyRectToScreen(_gui->_screen.getBasePtr(r.left, r.top), _gui->_screen.pitch, r.left, r.top, r.width() + 1, r.height() + 1); -	_gui->popCursor(); +	_gui->_wm.popCursor();  	return _pressedButton;  } diff --git a/engines/wage/entities.cpp b/engines/wage/entities.cpp index 49e2592949..43ac6c8cc7 100644 --- a/engines/wage/entities.cpp +++ b/engines/wage/entities.cpp @@ -52,6 +52,7 @@  #include "wage/world.h"  #include "common/memstream.h" +#include "graphics/managed_surface.h"  namespace Wage { @@ -138,16 +139,16 @@ void Scene::paint(Graphics::ManagedSurface *surface, int x, int y) {  	Common::Rect r(x + 5, y + 5, _design->getBounds()->width() + x - 10, _design->getBounds()->height() + y - 10);  	surface->fillRect(r, kColorWhite); -	_design->paint(surface, ((WageEngine *)g_engine)->_world->_patterns, x, y); +	_design->paint(surface, *((WageEngine *)g_engine)->_world->_patterns, x, y);  	for (ObjList::const_iterator it = _objs.begin(); it != _objs.end(); ++it) {  		debug(2, "paining Obj: %s, index: %d, type: %d", (*it)->_name.c_str(), (*it)->_index, (*it)->_type); -		(*it)->_design->paint(surface, ((WageEngine *)g_engine)->_world->_patterns, x, y); +		(*it)->_design->paint(surface, *((WageEngine *)g_engine)->_world->_patterns, x, y);  	}  	for (ChrList::const_iterator it = _chrs.begin(); it != _chrs.end(); ++it) {  		debug(2, "paining Chr: %s", (*it)->_name.c_str()); -		(*it)->_design->paint(surface, ((WageEngine *)g_engine)->_world->_patterns, x, y); +		(*it)->_design->paint(surface, *((WageEngine *)g_engine)->_world->_patterns, x, y);  	}  } @@ -202,6 +203,22 @@ const char *Scene::getFontName() {  	return "Unknown";  } +Designed *Scene::lookUpEntity(int x, int y) { +	for (ObjList::const_iterator it = _objs.end(); it != _objs.begin(); ) { +		it--; +		if ((*it)->_design->isPointOpaque(x, y)) +			return *it; +	} + +	for (ChrList::const_iterator it = _chrs.end(); it != _chrs.begin(); ) { +		it--; +		if ((*it)->_design->isPointOpaque(x, y)) +			return *it; +	} + +	return nullptr; +} +  Obj::Obj() : _currentOwner(NULL), _currentScene(NULL) {  	_index = 0;  	_namePlural = false; diff --git a/engines/wage/entities.h b/engines/wage/entities.h index c393f15f01..9e706f0d58 100644 --- a/engines/wage/entities.h +++ b/engines/wage/entities.h @@ -322,6 +322,8 @@ public:  	Scene(Common::String name, Common::SeekableReadStream *data);  	~Scene(); +	Designed *lookUpEntity(int x, int y); +  	Common::Rect *getTextBounds() {  		return _textBounds == NULL ? NULL : new Common::Rect(*_textBounds);  	} diff --git a/engines/wage/gui-console.cpp b/engines/wage/gui-console.cpp index 840b8e3ced..8b6fe43a17 100644 --- a/engines/wage/gui-console.cpp +++ b/engines/wage/gui-console.cpp @@ -45,6 +45,7 @@   *   */ +#include "common/events.h"  #include "common/timer.h"  #include "common/unzip.h"  #include "graphics/cursorman.h" @@ -54,7 +55,8 @@  #include "wage/wage.h"  #include "wage/design.h"  #include "wage/entities.h" -#include "wage/menu.h" +#include "wage/macwindow.h" +#include "wage/macmenu.h"  #include "wage/gui.h"  #include "wage/world.h" @@ -66,7 +68,7 @@ const Graphics::Font *Gui::getConsoleFont() {  	snprintf(fontName, 128, "%s-%d", scene->getFontName(), scene->_fontSize); -	return getFont(fontName, Graphics::FontManager::kConsoleFont); +	return _wm.getFont(fontName, Graphics::FontManager::kConsoleFont);  }  void Gui::clearOutput() { @@ -114,7 +116,7 @@ enum {  void Gui::flowText(Common::String &str) {  	Common::StringArray wrappedLines; -	int textW = _consoleTextArea.width() - kConWPadding * 2; +	int textW = _consoleWindow->getInnerDimensions().width() - kConWPadding * 2;  	const Graphics::Font *font = getConsoleFont();  	font->wordWrapText(str, textW, wrappedLines); @@ -196,7 +198,7 @@ void Gui::renderConsole(Graphics::ManagedSurface *g, const Common::Rect &r) {  			color = kColorWhite;  			Common::Rect trect(0, y1, _console.w, y1 + _consoleLineHeight); -			Design::drawFilledRect(&_console, trect, kColorBlack, _patterns, kPatternSolid); +			Design::drawFilledRect(&_console, trect, kColorBlack, _wm.getPatterns(), kPatternSolid);  		}  		if (line == _selectionStartY || line == _selectionEndY) { @@ -223,7 +225,7 @@ void Gui::renderConsole(Graphics::ManagedSurface *g, const Common::Rect &r) {  				else  					trect.left = rectW; -				Design::drawFilledRect(&_console, trect, kColorBlack, _patterns, kPatternSolid); +				Design::drawFilledRect(&_console, trect, kColorBlack, _wm.getPatterns(), kPatternSolid);  				font->drawString(&_console, beg, x1, y1, textW, color1);  				font->drawString(&_console, end, x1 + rectW - kConWPadding - kConWOverlap, y1, textW, color2); @@ -242,7 +244,7 @@ void Gui::renderConsole(Graphics::ManagedSurface *g, const Common::Rect &r) {  				int rectW2 = rectW1 + font->getStringWidth(mid);  				Common::Rect trect(rectW1, y1, rectW2, y1 + _consoleLineHeight); -				Design::drawFilledRect(&_console, trect, kColorBlack, _patterns, kPatternSolid); +				Design::drawFilledRect(&_console, trect, kColorBlack, _wm.getPatterns(), kPatternSolid);  				font->drawString(&_console, beg, x1, y1, textW, kColorBlack);  				font->drawString(&_console, mid, x1 + rectW1 - kConWPadding - kConWOverlap, y1, textW, kColorWhite); @@ -285,10 +287,7 @@ void Gui::drawInput() {  	if (!_screen.getPixels())  		return; -	if (_sceneIsActive) { -		_sceneIsActive = false; -		_bordersDirty = true; -	} +	_wm.setActive(_consoleWindow->getId());  	_out.pop_back();  	_lines.pop_back(); @@ -300,17 +299,17 @@ void Gui::drawInput() {  	if (_engine->_inputText.contains('\n')) {  		_consoleDirty = true;  	} else { -		int x = kConWPadding + _consoleTextArea.left; -		int y = _cursorY + _consoleTextArea.top; +		int x = kConWPadding + _consoleWindow->getInnerDimensions().left; +		int y = _cursorY + _consoleWindow->getInnerDimensions().top; -		Common::Rect r(x, y, x + _consoleTextArea.width() - kConWPadding, y + font->getFontHeight()); +		Common::Rect r(x, y, x + _consoleWindow->getInnerDimensions().width() - kConWPadding, y + font->getFontHeight());  		_screen.fillRect(r, kColorWhite);  		undrawCursor();  		font->drawString(&_screen, _out[_inputTextLineNum], x, y, _screen.w, kColorBlack); -		g_system->copyRectToScreen(_screen.getBasePtr(x, y), _screen.pitch, x, y, _consoleTextArea.width(), font->getFontHeight()); +		g_system->copyRectToScreen(_screen.getBasePtr(x, y), _screen.pitch, x, y, _consoleWindow->getInnerDimensions().width(), font->getFontHeight());  	}  	_cursorX = font->getStringWidth(_out[_inputTextLineNum]) + kConHPadding; @@ -425,4 +424,140 @@ void Gui::enableNewGameMenus() {  	_menu->enableCommand(kMenuFile, kMenuActionQuit, true);  } +bool Gui::processConsoleEvents(WindowClick click, Common::Event &event) { +	if (click == kBorderScrollUp || click == kBorderScrollDown) { +		if (event.type == Common::EVENT_LBUTTONDOWN) { +			int consoleHeight = _consoleWindow->getInnerDimensions().height(); +			int textFullSize = _lines.size() * _consoleLineHeight + consoleHeight; +			float scrollPos = (float)_scrollPos / textFullSize; +			float scrollSize = (float)consoleHeight / textFullSize; + +			_consoleWindow->setScroll(scrollPos, scrollSize); + +			return true; +		} else if (event.type == Common::EVENT_LBUTTONUP) { +			int oldScrollPos = _scrollPos; + +			switch (click) { +			case kBorderScrollUp: +				_scrollPos = MAX<int>(0, _scrollPos - _consoleLineHeight); +				undrawCursor(); +				_cursorY -= (_scrollPos - oldScrollPos); +				_consoleDirty = true; +				_consoleFullRedraw = true; +				break; +			case kBorderScrollDown: +				_scrollPos = MIN<int>((_lines.size() - 2) * _consoleLineHeight, _scrollPos + _consoleLineHeight); +				undrawCursor(); +				_cursorY -= (_scrollPos - oldScrollPos); +				_consoleDirty = true; +				_consoleFullRedraw = true; +				break; +			default: +				return false; +			} + +			return true; +		} + +		return false; +	} + +	if (click == kBorderResizeButton) { +		_consoleDirty = true; +		_consoleFullRedraw = true; + +		return true; +	} + +	if (click == kBorderInner) { +		if (event.type == Common::EVENT_LBUTTONDOWN) { +			startMarking(event.mouse.x, event.mouse.y); + +			return true; +		} else if (event.type == Common::EVENT_LBUTTONUP) { +			if (_inTextSelection) { +				_inTextSelection = false; + +				if (_selectionEndY == -1 || +						(_selectionEndX == _selectionStartX && _selectionEndY == _selectionStartY)) { +					_selectionStartY = _selectionEndY = -1; +					_consoleFullRedraw = true; +					_menu->enableCommand(kMenuEdit, kMenuActionCopy, false); +				} else { +					_menu->enableCommand(kMenuEdit, kMenuActionCopy, true); + +					bool cutAllowed = false; + +					if (_selectionStartY == _selectionEndY && _selectionStartY == (int)_lines.size() - 1) +						cutAllowed = true; + +					_menu->enableCommand(kMenuEdit, kMenuActionCut, cutAllowed); +					_menu->enableCommand(kMenuEdit, kMenuActionClear, cutAllowed); +				} +			} + +			return true; +		} else if (event.type == Common::EVENT_MOUSEMOVE) { +			if (_inTextSelection) { +				updateTextSelection(event.mouse.x, event.mouse.y); +				return true; +			} +		} + +		return false; +	} + +	return false; +} + +int Gui::calcTextX(int x, int textLine) { +	const Graphics::Font *font = getConsoleFont(); + +	if ((uint)textLine >= _lines.size()) +		return 0; + +	Common::String str = _lines[textLine]; + +	x -= _consoleWindow->getInnerDimensions().left; + +	for (int i = str.size(); i >= 0; i--) { +		if (font->getStringWidth(str) < x) { +			return i; +		} + +		str.deleteLastChar(); +	} + +	return 0; +} + +int Gui::calcTextY(int y) { +	y -= _consoleWindow->getInnerDimensions().top; + +	if (y < 0) +		y = 0; + +	const int firstLine = _scrollPos / _consoleLineHeight; +	int textLine = (y - _scrollPos % _consoleLineHeight) / _consoleLineHeight + firstLine; + +	return textLine; +} + +void Gui::startMarking(int x, int y) { +	_selectionStartY = calcTextY(y); +	_selectionStartX = calcTextX(x, _selectionStartY); + +	_selectionEndY = -1; + +	_inTextSelection = true; +} + +void Gui::updateTextSelection(int x, int y) { +	_selectionEndY = calcTextY(y); +	_selectionEndX = calcTextX(x, _selectionEndY); + +	_consoleFullRedraw = true; +} +  } // End of namespace Wage diff --git a/engines/wage/gui.cpp b/engines/wage/gui.cpp index 436d17c56f..310e5734b7 100644 --- a/engines/wage/gui.cpp +++ b/engines/wage/gui.cpp @@ -46,73 +46,40 @@   */  #include "common/timer.h" -#include "common/unzip.h" +#include "common/system.h"  #include "graphics/cursorman.h" -#include "graphics/fonts/bdf.h" -#include "graphics/palette.h"  #include "graphics/primitives.h"  #include "wage/wage.h"  #include "wage/design.h"  #include "wage/entities.h" +#include "wage/gui.h"  #include "wage/macwindow.h"  #include "wage/macwindowmanager.h" -#include "wage/menu.h" -#include "wage/gui.h" +#include "wage/macmenu.h"  #include "wage/world.h"  namespace Wage { -static const byte palette[] = { -	0, 0, 0,           // Black -	0x80, 0x80, 0x80,  // Gray -	0xff, 0xff, 0xff,  // White -	0x00, 0xff, 0x00,  // Green -	0x00, 0xcf, 0x00   // Green2 -}; - -static byte fillPatterns[][8] = { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, // kPatternSolid -								  { 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55 }, // kPatternStripes -								  { 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55 }, // kPatternCheckers -								  { 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa }  // kPatternCheckers2 -}; - -static const byte macCursorArrow[] = { -	2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, -	2, 0, 2, 3, 3, 3, 3, 3, 3, 3, 3, -	2, 0, 0, 2, 3, 3, 3, 3, 3, 3, 3, -	2, 0, 0, 0, 2, 3, 3, 3, 3, 3, 3, -	2, 0, 0, 0, 0, 2, 3, 3, 3, 3, 3, -	2, 0, 0, 0, 0, 0, 2, 3, 3, 3, 3, -	2, 0, 0, 0, 0, 0, 0, 2, 3, 3, 3, -	2, 0, 0, 0, 0, 0, 0, 0, 2, 3, 3, -	2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, -	2, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, -	2, 0, 0, 2, 0, 0, 2, 3, 3, 3, 3, -	2, 0, 2, 3, 2, 0, 0, 2, 3, 3, 3, -	2, 2, 3, 3, 2, 0, 0, 2, 3, 3, 3, -	2, 3, 3, 3, 3, 2, 0, 0, 2, 3, 3, -	3, 3, 3, 3, 3, 2, 0, 0, 2, 3, 3, -	3, 3, 3, 3, 3, 3, 2, 2, 2, 3, 3 -}; - -static const byte macCursorBeam[] = { -	0, 0, 3, 3, 3, 0, 0, 3, 3, 3, 3, -	3, 3, 0, 3, 0, 3, 3, 3, 3, 3, 3, -	3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, -	3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, -	3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, -	3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, -	3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, -	3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, -	3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, -	3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, -	3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, -	3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, -	3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, -	3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, -	3, 3, 0, 3, 0, 3, 3, 3, 3, 3, 3, -	0, 0, 3, 3, 3, 0, 0, 3, 3, 3, 3, +static const MenuData menuSubItems[] = { +	{ kMenuHighLevel, "File",	0, 0, false }, +	{ kMenuHighLevel, "Edit",	0, 0, false }, +	{ kMenuFile, "New",			kMenuActionNew, 0, false }, +	{ kMenuFile, "Open...",		kMenuActionOpen, 0, false }, +	{ kMenuFile, "Close",		kMenuActionClose, 0, true }, +	{ kMenuFile, "Save",		kMenuActionSave, 0, false }, +	{ kMenuFile, "Save as...",	kMenuActionSaveAs, 0, true }, +	{ kMenuFile, "Revert",		kMenuActionRevert, 0, false }, +	{ kMenuFile, "Quit",		kMenuActionQuit, 0, true }, + +	{ kMenuEdit, "Undo",		kMenuActionUndo, 'Z', false }, +	{ kMenuEdit, NULL,			0, 0, false }, +	{ kMenuEdit, "Cut",			kMenuActionCut, 'K', false }, +	{ kMenuEdit, "Copy",		kMenuActionCopy, 'C', false }, +	{ kMenuEdit, "Paste",		kMenuActionPaste, 'V', false }, +	{ kMenuEdit, "Clear",		kMenuActionClear, 'B', false }, + +	{ 0, NULL,			0, 0, false }  };  static void cursorTimerHandler(void *refCon) { @@ -127,8 +94,8 @@ static void cursorTimerHandler(void *refCon) {  	if (!gui->_screen.getPixels())  		return; -	x += gui->_consoleTextArea.left; -	y += gui->_consoleTextArea.top; +	x += gui->_consoleWindow->getInnerDimensions().left; +	y += gui->_consoleWindow->getInnerDimensions().top;  	gui->_screen.vLine(x, y, y + kCursorHeight, gui->_cursorState ? kColorBlack : kColorWhite); @@ -143,22 +110,25 @@ static void cursorTimerHandler(void *refCon) {  	gui->_cursorDirty = true;  } +static bool sceneWindowCallback(WindowClick click, Common::Event &event, void *gui); +static bool consoleWindowCallback(WindowClick click, Common::Event &event, void *gui); +static void menuCommandsCallback(int action, Common::String &text, void *data); + +  Gui::Gui(WageEngine *engine) {  	_engine = engine;  	_scene = NULL;  	_sceneDirty = true;  	_consoleDirty = true; -	_bordersDirty = true; -	_menuDirty = true;  	_cursorDirty = false;  	_consoleFullRedraw = true;  	_screen.create(g_system->getWidth(), g_system->getHeight(), Graphics::PixelFormat::createFormatCLUT8()); +	_wm.setScreen(&_screen); +  	_scrollPos = 0;  	_consoleLineHeight = 8; // Dummy value which makes sense  	_consoleNumLines = 24; // Dummy value -	_builtInFonts = false; -	_sceneIsActive = false;  	_cursorX = 0;  	_cursorY = 0; @@ -171,31 +141,39 @@ Gui::Gui(WageEngine *engine) {  	_inputTextLineNum = 0; -	g_system->getPaletteManager()->setPalette(palette, 0, ARRAYSIZE(palette) / 3); +	g_system->getTimerManager()->installTimerProc(&cursorTimerHandler, 200000, this, "wageCursor"); -	CursorMan.replaceCursorPalette(palette, 0, 4); -	CursorMan.replaceCursor(macCursorArrow, 11, 16, 1, 1, 3); -	_cursorIsArrow = true; -	CursorMan.showMouse(true); +	_menu = _wm.addMenu(); -	for (int i = 0; i < ARRAYSIZE(fillPatterns); i++) -		_patterns.push_back(fillPatterns[i]); +	_menu->setCommandsCallback(menuCommandsCallback, this); -	loadFonts(); +	_menu->addStaticMenus(menuSubItems); +	_menu->addMenuSubItem(kMenuAbout, _engine->_world->getAboutMenuItemName(), kMenuActionAbout); -	g_system->getTimerManager()->installTimerProc(&cursorTimerHandler, 200000, this, "wageCursor"); +	_commandsMenuId = _menu->addMenuItem(_engine->_world->_commandsMenuName.c_str()); +	regenCommandsMenu(); + +	if (!_engine->_world->_weaponMenuDisabled) { +		_weaponsMenuId = _menu->addMenuItem(_engine->_world->_weaponsMenuName.c_str()); + +		regenWeaponsMenu(); +	} else { +		_weaponsMenuId = -1; +	} + +	_menu->calcDimensions(); -	_menu = new Menu(this); +	_sceneWindow = _wm.addWindow(false, false, false); +	_sceneWindow->setCallback(sceneWindowCallback, this); -	_sceneWindowId = _wm.add(false); -	_consoleWindowId = _wm.add(true); +	_consoleWindow = _wm.addWindow(true, true, true); +	_consoleWindow->setCallback(consoleWindowCallback, this);  }  Gui::~Gui() {  	_screen.free();  	_console.free();  	g_system->getTimerManager()->removeTimerProc(&cursorTimerHandler); -	delete _menu;  }  void Gui::undrawCursor() { @@ -205,63 +183,34 @@ void Gui::undrawCursor() {  	_cursorOff = false;  } -const Graphics::Font *Gui::getFont(const char *name, Graphics::FontManager::FontUsage fallback) { -	const Graphics::Font *font = 0; - -	if (!_builtInFonts) { -		font = FontMan.getFontByName(name); - -		if (!font) -			warning("Cannot load font %s", name); -	} - -	if (_builtInFonts || !font) -		font = FontMan.getFontByUsage(fallback); - -	return font; -} - -const Graphics::Font *Gui::getTitleFont() { -	return getFont("Chicago-12", Graphics::FontManager::kBigGUIFont); -} - -void Gui::drawDesktop() { -	// Draw desktop -	Common::Rect r(0, 0, _screen.w - 1, _screen.h - 1); -	Design::drawFilledRoundRect(&_screen, r, kDesktopArc, kColorBlack, _patterns, kPatternCheckers); -	g_system->copyRectToScreen(_screen.getPixels(), _screen.pitch, 0, 0, _screen.w, _screen.h); -} -  void Gui::draw() {  	if (_engine->_isGameOver) { -		if (_menuDirty) { -			drawDesktop(); -			_menu->render(); -		} - -		_menuDirty = false; +		_wm.draw();  		return;  	} -	if (_scene != _engine->_world->_player->_currentScene) +	if (!_engine->_world->_player->_currentScene) +		return; + +	if (_scene != _engine->_world->_player->_currentScene) {  		_sceneDirty = true; -	if (_sceneDirty || _bordersDirty) -		drawDesktop(); +		_scene = _engine->_world->_player->_currentScene; -	if (_sceneIsActive) { -		drawConsole(); -		drawScene(); -	} else { -		drawScene(); -		drawConsole(); +		_sceneWindow->setDimensions(*_scene->_designBounds); +		_sceneWindow->setTitle(_scene->_name); +		_consoleWindow->setDimensions(*_scene->_textBounds); + +		_wm.setFullRefresh(true);  	} -	if (_menuDirty) -		_menu->render(); +	drawScene(); +	drawConsole(); + +	_wm.draw(); -	if (_cursorDirty) { +	if (_cursorDirty && _cursorRect.left < _screen.w && _cursorRect.bottom < _screen.h) {  		g_system->copyRectToScreen(_screen.getBasePtr(_cursorRect.left, _cursorRect.top), _screen.pitch,  				_cursorRect.left, _cursorRect.top, _cursorRect.width(), _cursorRect.height()); @@ -270,446 +219,141 @@ void Gui::draw() {  	_sceneDirty = false;  	_consoleDirty = false; -	_bordersDirty = false; -	_menuDirty = false;  	_consoleFullRedraw = false;  }  void Gui::drawScene() { -	if (!_sceneDirty && !_bordersDirty) +	if (!_sceneDirty)  		return; -	_scene = _engine->_world->_player->_currentScene; - -	MacWindow *w = _wm.getWindow(_sceneWindowId); - -	w->setDimensions(*_scene->_designBounds); -	w->setTitle(_scene->_name); -	_scene->paint(w->getSurface(), 0, 0); -	w->draw(&_screen); -	g_system->copyRectToScreen(_screen.getBasePtr(_scene->_designBounds->left - 2, _scene->_designBounds->top - 2), -			_screen.pitch, _scene->_designBounds->left - 2, _scene->_designBounds->top - 2, -			_scene->_designBounds->width(), _scene->_designBounds->height()); +	_scene->paint(_sceneWindow->getSurface(), 0, 0); +	_sceneWindow->setDirty(true);  	_sceneDirty = true;  	_consoleDirty = true; -	_menuDirty = true; +	_menu->setDirty(true);  	_consoleFullRedraw = true; - -	_sceneArea.left = _scene->_designBounds->left + kBorderWidth - 2; -	_sceneArea.top = _scene->_designBounds->top + kBorderWidth - 2; -	_sceneArea.setWidth(_scene->_designBounds->width() - 2 * kBorderWidth); -	_sceneArea.setHeight(_scene->_designBounds->height() - 2 * kBorderWidth); - -	_consoleTextArea.left = _scene->_textBounds->left + kBorderWidth - 2; -	_consoleTextArea.top = _scene->_textBounds->top + kBorderWidth - 2; -	_consoleTextArea.setWidth(_scene->_textBounds->width() - 2 * kBorderWidth); -	_consoleTextArea.setHeight(_scene->_textBounds->height() - 2 * kBorderWidth); -} - -// Render console -void Gui::drawConsole() { -	if (!_consoleDirty && !_consoleFullRedraw && !_bordersDirty && !_sceneDirty) -		return; - -	MacWindow *w = _wm.getWindow(_consoleWindowId); -	w->setDimensions(*_scene->_textBounds); -	renderConsole(w->getSurface(), Common::Rect(kBorderWidth - 2, kBorderWidth - 2, -				_scene->_textBounds->width() - kBorderWidth, _scene->_textBounds->height() - kBorderWidth)); -	w->draw(&_screen); -	g_system->copyRectToScreen(_screen.getBasePtr(_scene->_textBounds->left - 2, _scene->_textBounds->top - 2), -			_screen.pitch, _scene->_textBounds->left - 2, _scene->_textBounds->top - 2, -			_scene->_textBounds->width(), _scene->_textBounds->height());  } -void Gui::drawBox(Graphics::ManagedSurface *g, int x, int y, int w, int h) { -	Common::Rect r(x, y, x + w + 1, y + h + 1); - -	g->fillRect(r, kColorWhite); -	g->frameRect(r, kColorBlack); -} - -void Gui::fillRect(Graphics::ManagedSurface *g, int x, int y, int w, int h, int color) { -	Common::Rect r(x, y, x + w, y + h); - -	g->fillRect(r, color); -} - -#define ARROW_W 12 -#define ARROW_H 6 -const int arrowPixels[ARROW_H][ARROW_W] = { -		{0,0,0,0,0,1,1,0,0,0,0,0}, -		{0,0,0,0,1,1,1,1,0,0,0,0}, -		{0,0,0,1,1,1,1,1,1,0,0,0}, -		{0,0,1,1,1,1,1,1,1,1,0,0}, -		{0,1,1,1,1,1,1,1,1,1,1,0}, -		{1,1,1,1,1,1,1,1,1,1,1,1}}; - -static void drawPixelInverted(int x, int y, int color, void *data) { -	Graphics::ManagedSurface *surface = (Graphics::ManagedSurface *)data; - -	if (x >= 0 && x < surface->w && y >= 0 && y < surface->h) { -		byte *p = (byte *)surface->getBasePtr(x, y); +static bool sceneWindowCallback(WindowClick click, Common::Event &event, void *g) { +	Gui *gui = (Gui *)g; -		*p = *p == kColorWhite ? kColorBlack : kColorWhite; -	} +	return gui->processSceneEvents(click, event);  } -void Gui::paintBorder(Graphics::ManagedSurface *g, Common::Rect &r, WindowType windowType, int highlightedPart, float scrollPos, float scrollSize) { -	bool active = false, scrollable = false, closeable = false, drawTitle = false; -	const int size = kBorderWidth; -	int x = r.left - size; -	int y = r.top - size; -	int width = r.width() + 2 * size; -	int height = r.height() + 2 * size; - -	switch (windowType) { -	case kWindowScene: -		active = _sceneIsActive; -		scrollable = false; -		closeable = _sceneIsActive; -		drawTitle = true; -		break; -	case kWindowConsole: -		active = !_sceneIsActive; -		scrollable = true; -		closeable = !_sceneIsActive; -		drawTitle = false; -		break; -	} - -	drawBox(g, x,                    y,                     size,                 size); -	drawBox(g, x + width - size - 1, y,                     size,                 size); -	drawBox(g, x + width - size - 1, y + height - size - 1, size,                 size); -	drawBox(g, x,                    y + height - size - 1, size,                 size); -	drawBox(g, x + size,             y + 2,                 width - 2 * size - 1, size - 4); -	drawBox(g, x + size,             y + height - size + 1, width - 2 * size - 1, size - 4); -	drawBox(g, x + 2,                y + size,              size - 4,             height - 2 * size - 1); -	drawBox(g, x + width - size + 1, y + size,              size - 4,             height - 2 * size - 1); - -	if (active) { -		fillRect(g, x + size, y + 5,           width - 2 * size - 1, 8); -		fillRect(g, x + size, y + height - 13, width - 2 * size - 1, 8); -		fillRect(g, x + 5,    y + size,        8,                    height - 2 * size - 1); -		if (!scrollable) { -			fillRect(g, x + width - 13, y + size, 8, height - 2 * size - 1); -		} else { -			int x1 = x + width - 15; -			int y1 = y + size + 1; - -			for (int yy = 0; yy < ARROW_H; yy++) { -				for (int xx = 0; xx < ARROW_W; xx++) -					g->hLine(x1 + xx, y1 + yy, x1 + xx, (arrowPixels[yy][xx] != 0 ? kColorBlack : kColorWhite)); -			} - -			fillRect(g, x + width - 13, y + size + ARROW_H, 8, height - 2 * size - 1 - ARROW_H * 2); - -			y1 += height - 2 * size - ARROW_H - 2; -			for (int yy = 0; yy < ARROW_H; yy++) { -				for (int xx = 0; xx < ARROW_W; xx++) -					g->hLine(x1 + xx, y1 + yy, x1 + xx, (arrowPixels[ARROW_H - yy - 1][xx] != 0 ? kColorBlack : kColorWhite)); -			} - -			if (highlightedPart == kBorderScrollUp || highlightedPart == kBorderScrollDown) { -				int rx1 = x + width - kBorderWidth + 2; -				int ry1 = y + size + r.height() * scrollPos; -				int rx2 = rx1 + size - 4; -				int ry2 = ry1 + r.height() * scrollSize; -				Common::Rect rr(rx1, ry1, rx2, ry2); - -				Graphics::drawFilledRect(rr, kColorBlack, drawPixelInverted, g); -			} -		} -		if (closeable) { -			if (highlightedPart == kBorderCloseButton) { -				fillRect(g, x + 6, y + 6, 6, 6); -			} else { -				drawBox(g, x + 5, y + 5, 7, 7); -			} -		} -	} - -	if (drawTitle) { -		const Graphics::Font *font = getTitleFont(); -		int yOff = _builtInFonts ? 3 : 1; +bool Gui::processSceneEvents(WindowClick click, Common::Event &event) { +	if (click == kBorderInner && event.type == Common::EVENT_LBUTTONUP) { +		Designed *obj = _scene->lookUpEntity(event.mouse.x - _sceneWindow->getDimensions().left, +												  event.mouse.y - _sceneWindow->getDimensions().top); -		int w = font->getStringWidth(_scene->_name) + 10; -		int maxWidth = width - size * 2 - 7; -		if (w > maxWidth) -			w = maxWidth; -		drawBox(g, x + (width - w) / 2, y, w, size); -		font->drawString(g, _scene->_name, x + (width - w) / 2 + 5, y + yOff, w, kColorBlack); -	} +		if (obj != nullptr) +			_engine->processTurn(NULL, obj); -	if (x < 0) { -		width += x; -		x = 0; -	} -	if (y < 0) { -		height += y; -		y = 0; +		return true;  	} -	if (x + width > _screen.w) -		width = _screen.w - x; -	if (y + height > _screen.h) -		height = _screen.h - y; -	g_system->copyRectToScreen(g->getBasePtr(x, y), g->pitch, x, y, width, height); +	return false;  } -void Gui::loadFonts() { -	Common::Archive *dat; - -	dat = Common::makeZipArchive("wage.dat"); - -	if (!dat) { -		warning("Could not find wage.dat. Falling back to built-in fonts"); -		_builtInFonts = true; - +// Render console +void Gui::drawConsole() { +	if (!_consoleDirty && !_consoleFullRedraw && !_sceneDirty)  		return; -	} - -	Common::ArchiveMemberList list; -	dat->listMembers(list); -	for (Common::ArchiveMemberList::iterator it = list.begin(); it != list.end(); ++it) { -		Common::SeekableReadStream *stream = dat->createReadStreamForMember((*it)->getName()); - -		Graphics::BdfFont *font = Graphics::BdfFont::loadFont(*stream); - -		delete stream; - -		Common::String fontName = (*it)->getName(); - -		// Trim the .bdf extension -		for (int i = fontName.size() - 1; i >= 0; --i) { -			if (fontName[i] == '.') { -				while ((uint)i < fontName.size()) { -					fontName.deleteLastChar(); -				} -				break; -			} -		} - -		FontMan.assignFontToName(fontName, font); - -		debug(2, " %s", fontName.c_str()); -	} +	renderConsole(_consoleWindow->getSurface(), Common::Rect(kBorderWidth - 2, kBorderWidth - 2, +				_consoleWindow->getDimensions().width(), _consoleWindow->getDimensions().height())); +	_consoleWindow->setDirty(true); +} -	_builtInFonts = false; +static bool consoleWindowCallback(WindowClick click, Common::Event &event, void *g) { +	Gui *gui = (Gui *)g; -	delete dat; +	return gui->processConsoleEvents(click, event);  } +//////////////// +// Menu stuff +////////////////  void Gui::regenCommandsMenu() { -	_menu->regenCommandsMenu(); +	_menu->createSubMenuFromString(_commandsMenuId, _engine->_world->_commandsMenu.c_str());  }  void Gui::regenWeaponsMenu() { -	_menu->regenWeaponsMenu(); -} - -void Gui::processMenuShortCut(byte flags, uint16 ascii) { -	_menu->processMenuShortCut(flags, ascii); -} - -void Gui::mouseMove(int x, int y) { -	if (_menu->_menuActivated) { -		if (_menu->mouseMove(x, y)) -			_menuDirty = true; - +	if (_engine->_world->_weaponMenuDisabled)  		return; -	} - -	if (_inTextSelection) { -		updateTextSelection(x, y); -		return; -	} - -	if (_consoleTextArea.contains(x, y)) { -		if (_cursorIsArrow) { -			CursorMan.replaceCursor(macCursorBeam, 11, 16, 3, 8, 3); -			_cursorIsArrow = false; -		} -	} else if (_cursorIsArrow == false) { -		CursorMan.replaceCursor(macCursorArrow, 11, 16, 1, 1, 3); -		_cursorIsArrow = true; -	} -} - -void Gui::pushArrowCursor() { -	CursorMan.pushCursor(macCursorArrow, 11, 16, 1, 1, 3); -} - -void Gui::popCursor() { -	CursorMan.popCursor(); -} - -static int isInBorder(Common::Rect &rect, int x, int y) { -	if (x >= rect.left - kBorderWidth && x < rect.left && y >= rect.top - kBorderWidth && y < rect.top) -		return kBorderCloseButton; - -	if (x >= rect.right && x < rect.right + kBorderWidth) { -		if (y < rect.top - kBorderWidth) -			return kBorderNone; - -		if (y >= rect.bottom + kBorderWidth) -			return kBorderNone; - -		if (y >= rect.top + rect.height() / 2) -			return kBorderScrollDown; - -		return kBorderScrollUp; -	} - -	return kBorderNone; -} - -Designed *Gui::mouseUp(int x, int y) { -	if (_menu->_menuActivated) { -		if (_menu->mouseRelease(x, y)) { -			_sceneDirty = true; -			_consoleDirty = true; -			_bordersDirty = true; -			_menuDirty = true; -		} -		return NULL; -	} - -	if (_inTextSelection) { -		_inTextSelection = false; - -		if (_selectionEndY == -1 || -				(_selectionEndX == _selectionStartX && _selectionEndY == _selectionStartY)) { -			_selectionStartY = _selectionEndY = -1; -			_consoleFullRedraw = true; -			_menu->enableCommand(kMenuEdit, kMenuActionCopy, false); -		} else { -			_menu->enableCommand(kMenuEdit, kMenuActionCopy, true); +	_menu->clearSubMenu(_weaponsMenuId); -			bool cutAllowed = false; +	Chr *player = _engine->_world->_player; +	ObjArray *weapons = player->getWeapons(true); -			if (_selectionStartY == _selectionEndY && _selectionStartY == (int)_lines.size() - 1) -				cutAllowed = true; +	bool empty = true; -			_menu->enableCommand(kMenuEdit, kMenuActionCut, cutAllowed); -			_menu->enableCommand(kMenuEdit, kMenuActionClear, cutAllowed); -		} -	} +	for (uint i = 0; i < weapons->size(); i++) { +		Obj *obj = (*weapons)[i]; +		if (obj->_type == Obj::REGULAR_WEAPON || +			obj->_type == Obj::THROW_WEAPON || +			obj->_type == Obj::MAGICAL_OBJECT) { +			Common::String command(obj->_operativeVerb); +			command += " "; +			command += obj->_name; -	int borderClick; - -	if (_sceneArea.contains(x, y)) { -		if (!_sceneIsActive) { -			_sceneIsActive = true; -			_bordersDirty = true; -		} - -		for (ObjList::const_iterator it = _scene->_objs.end(); it != _scene->_objs.begin(); ) { -			it--; -			if ((*it)->_design->isPointOpaque(x - _sceneArea.left + kBorderWidth, y - _sceneArea.top + kBorderWidth)) -				return *it; -		} +			_menu->addMenuSubItem(_weaponsMenuId, command.c_str(), kMenuActionCommand, 0, 0, true); -		for (ChrList::const_iterator it = _scene->_chrs.end(); it != _scene->_chrs.begin(); ) { -			it--; -			if ((*it)->_design->isPointOpaque(x - _sceneArea.left + kBorderWidth, y - _sceneArea.top + kBorderWidth)) -				return *it; -		} -	} else if (_consoleTextArea.contains(x, y)) { -		if (_sceneIsActive) { -			_sceneIsActive = false; -			_bordersDirty = true; -		} -	} else if ((borderClick = isInBorder(_consoleTextArea, x, y)) != kBorderNone) { -		_bordersDirty = true; -		int _oldScrollPos = _scrollPos; - -		switch (borderClick) { -			case kBorderScrollUp: -				_scrollPos = MAX<int>(0, _scrollPos - _consoleLineHeight); -				undrawCursor(); -				_cursorY -= (_scrollPos - _oldScrollPos); -				_consoleDirty = true; -				_consoleFullRedraw = true; -				break; -			case kBorderScrollDown: -				_scrollPos = MIN<int>((_lines.size() - 2) * _consoleLineHeight, _scrollPos + _consoleLineHeight); -				undrawCursor(); -				_cursorY -= (_scrollPos - _oldScrollPos); -				_consoleDirty = true; -				_consoleFullRedraw = true; -				break; +			empty = false;  		}  	} +	delete weapons; -	return NULL; +	if (empty) +		_menu->addMenuSubItem(_weaponsMenuId, "You have no weapons", 0, 0, 0, false);  } -void Gui::mouseDown(int x, int y) { -	int borderClick; - -	if (_menu->mouseClick(x, y)) { -		_menuDirty = true; -	} else if (_consoleTextArea.contains(x, y)) { -		startMarking(x, y); -	} else if ((borderClick = isInBorder(_consoleTextArea, x, y)) != kBorderNone) { -		int textFullSize = _lines.size() * _consoleLineHeight + _consoleTextArea.height(); -		float scrollPos = (float)_scrollPos / textFullSize; -		float scrollSize = (float)_consoleTextArea.height() / textFullSize; - -		paintBorder(&_screen, _consoleTextArea, kWindowConsole, borderClick, scrollPos, scrollSize); -	} -} - -int Gui::calcTextX(int x, int textLine) { -	const Graphics::Font *font = getConsoleFont(); - -	if ((uint)textLine >= _lines.size()) -		return 0; - -	Common::String str = _lines[textLine]; - -	x -= _consoleTextArea.left; - -	for (int i = str.size(); i >= 0; i--) { -		if (font->getStringWidth(str) < x) { -			return i; -		} - -		str.deleteLastChar(); -	} - -	return 0; +bool Gui::processEvent(Common::Event &event) { +	return _wm.processEvent(event);  } -int Gui::calcTextY(int y) { -	y -= _consoleTextArea.top; - -	if (y < 0) -		y = 0; +void menuCommandsCallback(int action, Common::String &text, void *data) { +	Gui *g = (Gui *)data; -	const int firstLine = _scrollPos / _consoleLineHeight; -	int textLine = (y - _scrollPos % _consoleLineHeight) / _consoleLineHeight + firstLine; - -	return textLine; +	g->executeMenuCommand(action, text);  } -void Gui::startMarking(int x, int y) { -	_selectionStartY = calcTextY(y); -	_selectionStartX = calcTextX(x, _selectionStartY); - -	_selectionEndY = -1; +void Gui::executeMenuCommand(int action, Common::String &text) { +	switch(action) { +	case kMenuActionAbout: +	case kMenuActionNew: +	case kMenuActionOpen: +	case kMenuActionClose: +	case kMenuActionSave: +	case kMenuActionSaveAs: +	case kMenuActionRevert: +	case kMenuActionQuit: + +	case kMenuActionUndo: +		actionUndo(); +		break; +	case kMenuActionCut: +		actionCut(); +		break; +	case kMenuActionCopy: +		actionCopy(); +		break; +	case kMenuActionPaste: +		actionPaste(); +		break; +	case kMenuActionClear: +		actionClear(); +		break; -	_inTextSelection = true; -} +	case kMenuActionCommand: +		_engine->processTurn(&text, NULL); +		break; -void Gui::updateTextSelection(int x, int y) { -	_selectionEndY = calcTextY(y); -	_selectionEndX = calcTextX(x, _selectionEndY); +	default: +		warning("Unknown action: %d", action); -	_consoleFullRedraw = true; +	}  }  } // End of namespace Wage diff --git a/engines/wage/gui.h b/engines/wage/gui.h index dc3a593bda..ba1bb5ef3b 100644 --- a/engines/wage/gui.h +++ b/engines/wage/gui.h @@ -50,8 +50,8 @@  #include "common/str-array.h"  #include "graphics/font.h" -#include "graphics/fontman.h"  #include "graphics/managed_surface.h" +#include "common/events.h"  #include "common/rect.h"  #include "wage/macwindow.h" @@ -60,27 +60,13 @@  namespace Wage {  class Menu; +class Scene; +class WageEngine;  enum { -	kMenuHeight = 20, -	kMenuLeftMargin = 7, -	kMenuSpacing = 13, -	kMenuPadding = 16, -	kMenuDropdownPadding = 14, -	kMenuDropdownItemHeight = 16, -	kMenuItemHeight = 20, -	kDesktopArc = 7, -	kComponentsPadding = 10,  	kCursorHeight = 12  }; -enum { -	kPatternSolid = 1, -	kPatternStripes = 2, -	kPatternCheckers = 3, -	kPatternCheckers2 = 4 -}; -  class Gui {  public:  	Gui(WageEngine *engine); @@ -89,17 +75,12 @@ public:  	void draw();  	void appendText(const char *str);  	void clearOutput(); -	void mouseMove(int x, int y); -	void mouseDown(int x, int y); -	Designed *mouseUp(int x, int y); +	bool processEvent(Common::Event &event); +  	void drawInput();  	void setSceneDirty() { _sceneDirty = true; } -	const Graphics::Font *getFont(const char *name, Graphics::FontManager::FontUsage fallback);  	void regenCommandsMenu();  	void regenWeaponsMenu(); -	void processMenuShortCut(byte flags, uint16 ascii); -	void pushArrowCursor(); -	void popCursor();  	void actionCopy();  	void actionPaste(); @@ -110,19 +91,15 @@ public:  	void disableAllMenus();  	void enableNewGameMenus(); -	bool builtInFonts() { return _builtInFonts; } +	bool processSceneEvents(WindowClick click, Common::Event &event); +	bool processConsoleEvents(WindowClick click, Common::Event &event); +	void executeMenuCommand(int action, Common::String &text);  private:  	void drawScene();  	void drawConsole();  	void undrawCursor(); -	void drawDesktop(); -	void paintBorder(Graphics::ManagedSurface *g, Common::Rect &r, WindowType windowType, int highlightedPart = kBorderNone, -						float scrollPos = 0.0, float scrollSize = 0.0);  	void renderConsole(Graphics::ManagedSurface *g, const Common::Rect &r); -	void drawBox(Graphics::ManagedSurface *g, int x, int y, int w, int h); -	void fillRect(Graphics::ManagedSurface *g, int x, int y, int w, int h, int color = kColorBlack); -	void loadFonts();  	void flowText(Common::String &str);  	const Graphics::Font *getConsoleFont();  	const Graphics::Font *getTitleFont(); @@ -135,26 +112,24 @@ public:  	Graphics::ManagedSurface _screen;  	int _cursorX, _cursorY;  	bool _cursorState; -	Common::Rect _consoleTextArea; -	bool _builtInFonts;  	WageEngine *_engine; -	Patterns _patterns; -  	bool _cursorDirty;  	Common::Rect _cursorRect;  	bool _cursorOff; -	bool _menuDirty; +	Scene *_scene; + +	MacWindowManager _wm; +	MacWindow *_sceneWindow; +	MacWindow *_consoleWindow;  private:  	Graphics::ManagedSurface _console;  	Menu *_menu; -	Scene *_scene;  	bool _sceneDirty;  	bool _consoleDirty; -	bool _bordersDirty;  	Common::StringArray _out;  	Common::StringArray _lines; @@ -163,10 +138,6 @@ private:  	uint _consoleNumLines;  	bool _consoleFullRedraw; -	Common::Rect _sceneArea; -	bool _sceneIsActive; -	bool _cursorIsArrow; -  	bool _inTextSelection;  	int _selectionStartX;  	int _selectionStartY; @@ -178,9 +149,8 @@ private:  	int _inputTextLineNum; -	MacWindowManager _wm; -	int _sceneWindowId; -	int _consoleWindowId; +	int _commandsMenuId; +	int _weaponsMenuId;  };  } // End of namespace Wage diff --git a/engines/wage/menu.cpp b/engines/wage/macmenu.cpp index 27cbf5e4f5..ed5f5070ff 100644 --- a/engines/wage/menu.cpp +++ b/engines/wage/macmenu.cpp @@ -48,15 +48,25 @@  #include "common/system.h"  #include "common/keyboard.h" -#include "wage/wage.h" -#include "wage/entities.h" -#include "wage/design.h" -#include "wage/gui.h" -#include "wage/menu.h" -#include "wage/world.h" +#include "graphics/primitives.h" +#include "graphics/font.h" + +#include "wage/macwindowmanager.h" +#include "wage/macwindow.h" +#include "wage/macmenu.h"  namespace Wage { +enum { +	kMenuHeight = 20, +	kMenuLeftMargin = 7, +	kMenuSpacing = 13, +	kMenuPadding = 16, +	kMenuDropdownPadding = 14, +	kMenuDropdownItemHeight = 16, +	kMenuItemHeight = 20 +}; +  struct MenuSubItem {  	Common::String text;  	int action; @@ -79,66 +89,65 @@ struct MenuItem {  	MenuItem(const char *n) : name(n) {}  }; -struct MenuData { -	int menunum; -	const char *title; -	int action; -	byte shortcut; -	bool enabled; -} static const menuSubItems[] = { -	{ kMenuFile, "New",			kMenuActionNew, 0, false }, -	{ kMenuFile, "Open...",		kMenuActionOpen, 0, false }, -	{ kMenuFile, "Close",		kMenuActionClose, 0, true }, -	{ kMenuFile, "Save",		kMenuActionSave, 0, false }, -	{ kMenuFile, "Save as...",	kMenuActionSaveAs, 0, true }, -	{ kMenuFile, "Revert",		kMenuActionRevert, 0, false }, -	{ kMenuFile, "Quit",		kMenuActionQuit, 0, true }, - -	{ kMenuEdit, "Undo",		kMenuActionUndo, 'Z', false }, -	{ kMenuEdit, NULL,			0, 0, false }, -	{ kMenuEdit, "Cut",			kMenuActionCut, 'K', false }, -	{ kMenuEdit, "Copy",		kMenuActionCopy, 'C', false }, -	{ kMenuEdit, "Paste",		kMenuActionPaste, 'V', false }, -	{ kMenuEdit, "Clear",		kMenuActionClear, 'B', false }, - -	{ 0, NULL,			0, 0, false } -}; +Menu::Menu(int id, const Common::Rect &bounds, MacWindowManager *wm) +		: BaseMacWindow(id, false, wm) { +	_font = getMenuFont(); -Menu::Menu(Gui *gui) : _gui(gui) { -	assert(_gui->_engine); -	assert(_gui->_engine->_world); +	_screen.create(bounds.width(), bounds.height(), Graphics::PixelFormat::createFormatCLUT8()); -	_font = getMenuFont(); +	_bbox.left = 0; +	_bbox.top = 0; +	_bbox.right = _screen.w; +	_bbox.bottom = kMenuHeight; + +	_menuActivated = false; +	_activeItem = -1; +	_activeSubItem = -1; + +	_ccallback = NULL; +	_cdata = NULL; + +	_tempSurface.create(_screen.w, _font->getFontHeight(), Graphics::PixelFormat::createFormatCLUT8()); +} + +Menu::~Menu() { +	for (uint i = 0; i < _items.size(); i++) { +		for (uint j = 0; j < _items[i]->subitems.size(); j++) +			delete _items[i]->subitems[j]; +		delete _items[i]; +	} +} -	MenuItem *about = new MenuItem(_gui->_builtInFonts ? "\xa9" : "\xf0"); // (c) Symbol as the most resembling apple +void Menu::addStaticMenus(const MenuData *data) { +	MenuItem *about = new MenuItem(_wm->hasBuiltInFonts() ? "\xa9" : "\xf0"); // (c) Symbol as the most resembling apple  	_items.push_back(about); -	_items[0]->subitems.push_back(new MenuSubItem(_gui->_engine->_world->getAboutMenuItemName(), kMenuActionAbout)); -	MenuItem *file = new MenuItem("File"); -	_items.push_back(file); +	for (int i = 0; data[i].menunum; i++) { +		const MenuData *m = &data[i]; -	MenuItem *edit = new MenuItem("Edit"); -	_items.push_back(edit); +		if (m->menunum == kMenuHighLevel) { +			MenuItem *item = new MenuItem(m->title); +			_items.push_back(item); -	for (int i = 0; menuSubItems[i].menunum; i++) { -		const MenuData *m = &menuSubItems[i]; +			continue; +		}  		_items[m->menunum]->subitems.push_back(new MenuSubItem(m->title, m->action, 0, m->shortcut, m->enabled));  	} +} -	_commands = new MenuItem(_gui->_engine->_world->_commandsMenuName.c_str()); -	_items.push_back(_commands); -	regenCommandsMenu(); - -	_weapons = NULL; +int Menu::addMenuItem(const char *name) { +	MenuItem *i = new MenuItem(name); +	_items.push_back(i); -	if (!_gui->_engine->_world->_weaponMenuDisabled) { -		_weapons = new MenuItem(_gui->_engine->_world->_weaponsMenuName.c_str()); -		_items.push_back(_weapons); +	return _items.size() - 1; +} -		regenWeaponsMenu(); -	} +void Menu::addMenuSubItem(int id, const char *text, int action, int style, char shortcut, bool enabled) { +	_items[id]->subitems.push_back(new MenuSubItem(text, action, style, shortcut, enabled)); +} +void Menu::calcDimensions() {  	// Calculate menu dimensions  	int y = 1;  	int x = 18; @@ -150,47 +159,29 @@ Menu::Menu(Gui *gui) : _gui(gui) {  			_items[i]->bbox.left = x - kMenuLeftMargin;  			_items[i]->bbox.top = y;  			_items[i]->bbox.right = x + w + kMenuSpacing - kMenuLeftMargin; -			_items[i]->bbox.bottom = y + _font->getFontHeight() + (_gui->_builtInFonts ? 3 : 2); +			_items[i]->bbox.bottom = y + _font->getFontHeight() + (_wm->hasBuiltInFonts() ? 3 : 2);  		}  		calcMenuBounds(_items[i]);  		x += w + kMenuSpacing;  	} - -	_bbox.left = 0; -	_bbox.top = 0; -	_bbox.right = _gui->_screen.w - 1; -	_bbox.bottom = kMenuHeight - 1; - -	_menuActivated = false; -	_activeItem = -1; -	_activeSubItem = -1; - -	_screenCopy.create(_gui->_screen.w, _gui->_screen.h, Graphics::PixelFormat::createFormatCLUT8()); -	_tempSurface.create(_gui->_screen.w, _font->getFontHeight(), Graphics::PixelFormat::createFormatCLUT8()); -} - -Menu::~Menu() { -	for (uint i = 0; i < _items.size(); i++) { -		for (uint j = 0; j < _items[i]->subitems.size(); j++) -			delete _items[i]->subitems[j]; -		delete _items[i]; -	}  } -void Menu::regenCommandsMenu() { -	for (uint j = 0; j < _commands->subitems.size(); j++) -		delete _commands->subitems[j]; +void Menu::clearSubMenu(int id) { +	MenuItem *menu = _items[id]; -	_commands->subitems.clear(); +	for (uint j = 0; j < menu->subitems.size(); j++) +		delete menu->subitems[j]; -	createCommandsMenu(_commands); -	calcMenuBounds(_commands); +	menu->subitems.clear();  } -void Menu::createCommandsMenu(MenuItem *menu) { -	Common::String string(_gui->_engine->_world->_commandsMenu); +void Menu::createSubMenuFromString(int id, const char *str) { +	clearSubMenu(id); + +	MenuItem *menu = _items[id]; +	Common::String string(str);  	Common::String item; @@ -253,45 +244,12 @@ void Menu::createCommandsMenu(MenuItem *menu) {  		item.clear();  	} -} - -void Menu::regenWeaponsMenu() { -	if (_gui->_engine->_world->_weaponMenuDisabled) -		return; - -	for (uint j = 0; j < _weapons->subitems.size(); j++) -		delete _weapons->subitems[j]; - -	_weapons->subitems.clear(); - -	createWeaponsMenu(_weapons); -	calcMenuBounds(_weapons); -} - -void Menu::createWeaponsMenu(MenuItem *menu) { -	Chr *player = _gui->_engine->_world->_player; -	ObjArray *weapons = player->getWeapons(true); - -	for (uint i = 0; i < weapons->size(); i++) { -		Obj *obj = (*weapons)[i]; -		if (obj->_type == Obj::REGULAR_WEAPON || -			obj->_type == Obj::THROW_WEAPON || -			obj->_type == Obj::MAGICAL_OBJECT) { -			Common::String command(obj->_operativeVerb); -			command += " "; -			command += obj->_name; - -			menu->subitems.push_back(new MenuSubItem(command.c_str(), kMenuActionCommand, 0, 0, true)); -		} -	} -	delete weapons; -	if (menu->subitems.empty()) -		menu->subitems.push_back(new MenuSubItem("You have no weapons", 0, 0, 0, false)); +	calcMenuBounds(menu);  }  const Graphics::Font *Menu::getMenuFont() { -	return _gui->getFont("Chicago-12", Graphics::FontManager::kBigGUIFont); +	return _wm->getFont("Chicago-12", Graphics::FontManager::kBigGUIFont);  }  const char *Menu::getAcceleratorString(MenuSubItem *item, const char *prefix) { @@ -299,7 +257,7 @@ const char *Menu::getAcceleratorString(MenuSubItem *item, const char *prefix) {  	*res = 0;  	if (item->shortcut != 0) -		sprintf(res, "%s%c%c", prefix, (_gui->_builtInFonts ? '^' : '\x11'), item->shortcut); +		sprintf(res, "%s%c%c", prefix, (_wm->hasBuiltInFonts() ? '^' : '\x11'), item->shortcut);  	return res;  } @@ -338,14 +296,35 @@ void Menu::calcMenuBounds(MenuItem *menu) {  	menu->subbbox.bottom = y2;  } -void Menu::render() { +static void drawPixelPlain(int x, int y, int color, void *data) { +	Graphics::ManagedSurface *surface = (Graphics::ManagedSurface *)data; + +	if (x >= 0 && x < surface->w && y >= 0 && y < surface->h) +		*((byte *)surface->getBasePtr(x, y)) = (byte)color; +} + +static void drawFilledRoundRect(Graphics::ManagedSurface *surface, Common::Rect &rect, int arc, int color) { +	Graphics::drawRoundRect(rect, arc, color, true, drawPixelPlain, surface); +} + +bool Menu::draw(Graphics::ManagedSurface *g, bool forceRedraw) {  	Common::Rect r(_bbox); -	Design::drawFilledRoundRect(&_gui->_screen, r, kDesktopArc, kColorWhite, _gui->_patterns, kPatternSolid); +	if (!_contentIsDirty && !forceRedraw) +		return false; + +	_contentIsDirty = false; + +	_screen.clear(kColorGreen); + +	drawFilledRoundRect(&_screen, r, kDesktopArc, kColorWhite);  	r.top = 7; -	Design::drawFilledRect(&_gui->_screen, r, kColorWhite, _gui->_patterns, kPatternSolid); +	_screen.fillRect(r, kColorWhite);  	r.top = kMenuHeight - 1; -	Design::drawFilledRect(&_gui->_screen, r, kColorBlack, _gui->_patterns, kPatternSolid); +	r.bottom++; +	_screen.fillRect(r, kColorGreen); +	r.bottom--; +	_screen.fillRect(r, kColorBlack);  	for (uint i = 0; i < _items.size(); i++) {  		int color = kColorBlack; @@ -355,19 +334,24 @@ void Menu::render() {  			Common::Rect hbox = it->bbox;  			hbox.left -= 1; -			hbox.right += 2; +			hbox.right += 3; +			hbox.bottom += 1; -			Design::drawFilledRect(&_gui->_screen, hbox, kColorBlack, _gui->_patterns, kPatternSolid); +			_screen.fillRect(hbox, kColorBlack);  			color = kColorWhite;  			if (!it->subitems.empty())  				renderSubmenu(it);  		} -		_font->drawString(&_gui->_screen, it->name, it->bbox.left + kMenuLeftMargin, it->bbox.top + (_gui->_builtInFonts ? 2 : 1), it->bbox.width(), color); +		_font->drawString(&_screen, it->name, it->bbox.left + kMenuLeftMargin, it->bbox.top + (_wm->hasBuiltInFonts() ? 2 : 1), it->bbox.width(), color);  	} -	g_system->copyRectToScreen(_gui->_screen.getPixels(), _gui->_screen.pitch, 0, 0, _gui->_screen.w, kMenuHeight); +	g->transBlitFrom(_screen, kColorGreen); + +	g_system->copyRectToScreen(g->getPixels(), g->pitch, 0, 0, g->w, g->h); + +	return true;  }  void Menu::renderSubmenu(MenuItem *menu) { @@ -376,10 +360,12 @@ void Menu::renderSubmenu(MenuItem *menu) {  	if (r->width() == 0 || r->height() == 0)  		return; -	Design::drawFilledRect(&_gui->_screen, *r, kColorWhite, _gui->_patterns, kPatternSolid); -	Design::drawRect(&_gui->_screen, *r, 1, kColorBlack, _gui->_patterns, kPatternSolid); -	Design::drawVLine(&_gui->_screen, r->right + 1, r->top + 3, r->bottom + 1, 1, kColorBlack, _gui->_patterns, kPatternSolid); -	Design::drawHLine(&_gui->_screen, r->left + 3, r->right + 1, r->bottom + 1, 1, kColorBlack, _gui->_patterns, kPatternSolid); +	_screen.fillRect(*r, kColorWhite); +	_screen.frameRect(*r, kColorBlack); +	_screen.vLine(r->right, r->top + 3, r->bottom + 1, kColorBlack); +	_screen.vLine(r->right + 1, r->top + 3, r->bottom + 1, kColorBlack); +	_screen.hLine(r->left + 3, r->bottom, r->right + 1, kColorBlack); +	_screen.hLine(r->left + 3, r->bottom + 1, r->right + 1, kColorBlack);  	int x = r->left + kMenuDropdownPadding;  	int y = r->top + 1; @@ -391,13 +377,13 @@ void Menu::renderSubmenu(MenuItem *menu) {  		int color = kColorBlack;  		if (i == (uint)_activeSubItem && !text.empty() && menu->subitems[i]->enabled) {  			color = kColorWhite; -			Common::Rect trect(r->left, y - (_gui->_builtInFonts ? 1 : 0), r->right, y + _font->getFontHeight()); +			Common::Rect trect(r->left, y - (_wm->hasBuiltInFonts() ? 1 : 0), r->right, y + _font->getFontHeight()); -			Design::drawFilledRect(&_gui->_screen, trect, kColorBlack, _gui->_patterns, kPatternSolid); +			_screen.fillRect(trect, kColorBlack);  		}  		if (!text.empty()) { -			Graphics::ManagedSurface *s = &_gui->_screen; +			Graphics::ManagedSurface *s = &_screen;  			int tx = x, ty = y;  			if (!menu->subitems[i]->enabled) { @@ -419,8 +405,8 @@ void Menu::renderSubmenu(MenuItem *menu) {  				// fake it here  				for (int ii = 0; ii < _tempSurface.h; ii++) {  					const byte *src = (const byte *)_tempSurface.getBasePtr(0, ii); -					byte *dst = (byte *)_gui->_screen.getBasePtr(x, y+ii); -					byte pat = _gui->_patterns[kPatternCheckers2 - 1][ii % 8]; +					byte *dst = (byte *)_screen.getBasePtr(x, y+ii); +					byte pat = _wm->getPatterns()[kPatternCheckers2 - 1][ii % 8];  					for (int j = 0; j < r->width(); j++) {  						if (*src != kColorGreen && (pat & (1 << (7 - (x + j) % 8))))  							*dst = *src; @@ -430,20 +416,51 @@ void Menu::renderSubmenu(MenuItem *menu) {  				}  			}  		} else { // Delimiter -			Design::drawHLine(&_gui->_screen, r->left + 1, r->right - 1, y + kMenuDropdownItemHeight / 2, 1, kColorBlack, _gui->_patterns, kPatternStripes); +			bool flip = r->left & 2; +			byte *ptr = (byte *)_screen.getBasePtr(r->left + 1, y + kMenuDropdownItemHeight / 2); +			for (int xx = r->left + 1; xx <= r->right - 1; xx++, ptr++) { +				*ptr = flip ? kColorBlack : kColorWhite; +				flip = !flip; +			}  		}  		y += kMenuDropdownItemHeight;  	} -	g_system->copyRectToScreen(_gui->_screen.getBasePtr(r->left, r->top), _gui->_screen.pitch, r->left, r->top, r->width() + 3, r->height() + 3); +	_contentIsDirty = true; +	//g_system->copyRectToScreen(_screen.getBasePtr(r->left, r->top), _screen.pitch, r->left, r->top, r->width() + 2, r->height() + 2); +} + +bool Menu::processEvent(Common::Event &event) { +	switch (event.type) { +	case Common::EVENT_KEYDOWN: +		return keyEvent(event); +	case Common::EVENT_LBUTTONDOWN: +		return mouseClick(event.mouse.x, event.mouse.y); +	case Common::EVENT_LBUTTONUP: +		return mouseRelease(event.mouse.x, event.mouse.y); +	case Common::EVENT_MOUSEMOVE: +		return mouseMove(event.mouse.x, event.mouse.y); +	default: +		return false; +	} +} + +bool Menu::keyEvent(Common::Event &event) { +	if (event.type != Common::EVENT_KEYDOWN) +		return false; + +	if (event.kbd.flags & (Common::KBD_ALT | Common::KBD_CTRL | Common::KBD_META)) { +		if (event.kbd.ascii >= 0x20 && event.kbd.ascii <= 0x7f) { +			return processMenuShortCut(event.kbd.flags, event.kbd.ascii); +		} +	} + +	return false;  }  bool Menu::mouseClick(int x, int y) {  	if (_bbox.contains(x, y)) { -		if (!_menuActivated) -			_screenCopy.copyFrom(_gui->_screen); -  		for (uint i = 0; i < _items.size(); i++)  			if (_items[i]->bbox.contains(x, y)) {  			  if ((uint)_activeItem == i) @@ -454,14 +471,15 @@ bool Menu::mouseClick(int x, int y) {  					r.right += 3;  					r.bottom += 3; -					_gui->_screen.copyRectToSurface(_screenCopy, r.left, r.top, r); -					g_system->copyRectToScreen(_gui->_screen.getBasePtr(r.left, r.top), _gui->_screen.pitch, r.left, r.top, r.width() + 1, r.height() + 1); +					_wm->setFullRefresh(true);  				}  				_activeItem = i;  				_activeSubItem = -1;  				_menuActivated = true; +				_contentIsDirty = true; +  				return true;  			}  	} else if (_menuActivated && _items[_activeItem]->subbbox.contains(x, y)) { @@ -472,11 +490,13 @@ bool Menu::mouseClick(int x, int y) {  			_activeSubItem = numSubItem;  			renderSubmenu(_items[_activeItem]); +			_contentIsDirty = true;  		}  	} else if (_menuActivated && _activeItem != -1) {  		_activeSubItem = -1;  		renderSubmenu(_items[_activeItem]); +		_contentIsDirty = true;  	}  	return false; @@ -495,77 +515,49 @@ bool Menu::mouseRelease(int x, int y) {  		_menuActivated = false;  		if (_activeItem != -1 && _activeSubItem != -1 && _items[_activeItem]->subitems[_activeSubItem]->enabled) -			executeCommand(_items[_activeItem]->subitems[_activeSubItem]); +			(*_ccallback)(_items[_activeItem]->subitems[_activeSubItem]->action, +					_items[_activeItem]->subitems[_activeSubItem]->text, _cdata);  		_activeItem = -1;  		_activeSubItem = -1; +		_wm->setFullRefresh(true); +  		return true;  	}  	return false;  } -void Menu::executeCommand(MenuSubItem *subitem) { -	switch(subitem->action) { -	case kMenuActionAbout: -	case kMenuActionNew: -	case kMenuActionOpen: -	case kMenuActionClose: -	case kMenuActionSave: -	case kMenuActionSaveAs: -	case kMenuActionRevert: -	case kMenuActionQuit: - -	case kMenuActionUndo: -		_gui->actionUndo(); -		break; -	case kMenuActionCut: -		_gui->actionCut(); -		break; -	case kMenuActionCopy: -		_gui->actionCopy(); -		break; -	case kMenuActionPaste: -		_gui->actionPaste(); -		break; -	case kMenuActionClear: -		_gui->actionClear(); -		break; - -	case kMenuActionCommand: -		_gui->_engine->processTurn(&subitem->text, NULL); -		break; - -	default: -		warning("Unknown action: %d", subitem->action); - -	} -} - -void Menu::processMenuShortCut(byte flags, uint16 ascii) { +bool Menu::processMenuShortCut(byte flags, uint16 ascii) {  	ascii = tolower(ascii);  	if (flags & (Common::KBD_CTRL | Common::KBD_META)) {  		for (uint i = 0; i < _items.size(); i++)  			for (uint j = 0; j < _items[i]->subitems.size(); j++)  				if (_items[i]->subitems[j]->enabled && tolower(_items[i]->subitems[j]->shortcut) == ascii) { -					executeCommand(_items[i]->subitems[j]); -					break; +					(*_ccallback)(_items[i]->subitems[j]->action, _items[i]->subitems[j]->text, _cdata); +					return true;  				}  	} + +	return false;  }  void Menu::enableCommand(int menunum, int action, bool state) {  	for (uint i = 0; i < _items[menunum]->subitems.size(); i++)  		if (_items[menunum]->subitems[i]->action == action)  			_items[menunum]->subitems[i]->enabled = state; + +	_contentIsDirty = true;  }  void Menu::disableAllMenus() {  	for (uint i = 1; i < _items.size(); i++) // Leave About menu on  		for (uint j = 0; j < _items[i]->subitems.size(); j++)  			_items[i]->subitems[j]->enabled = false; + +	_contentIsDirty = true;  }  } // End of namespace Wage diff --git a/engines/wage/menu.h b/engines/wage/macmenu.h index 916ef6d50e..e73e4c48a9 100644 --- a/engines/wage/menu.h +++ b/engines/wage/macmenu.h @@ -45,8 +45,8 @@   *   */ -#ifndef WAGE_MENU_H -#define WAGE_MENU_H +#ifndef WAGE_MACMENU_H +#define WAGE_MACMENU_H  namespace Wage { @@ -64,6 +64,7 @@ enum {  };  enum { +	kMenuHighLevel = -1,  	kMenuAbout = 0,  	kMenuFile = 1,  	kMenuEdit = 2, @@ -90,28 +91,42 @@ enum {  	kMenuActionCommand  }; -class Menu { +struct MenuData { +	int menunum; +	const char *title; +	int action; +	byte shortcut; +	bool enabled; +}; + +class Menu : public BaseMacWindow {  public: -	Menu(Gui *gui); +	Menu(int id, const Common::Rect &bounds, MacWindowManager *wm);  	~Menu(); -	void render(); -	bool mouseClick(int x, int y); -	bool mouseRelease(int x, int y); -	bool mouseMove(int x, int y); +	void setCommandsCallback(void (*callback)(int, Common::String &, void *), void *data) { _ccallback = callback; _cdata = data; } + +	void addStaticMenus(const MenuData *data); +	void calcDimensions(); + +	int addMenuItem(const char *name); +	void addMenuSubItem(int id, const char *text, int action, int style = 0, char shortcut = 0, bool enabled = true); +	void createSubMenuFromString(int id, const char *string); +	void clearSubMenu(int id); + +	bool draw(Graphics::ManagedSurface *g, bool forceRedraw = false); +	bool processEvent(Common::Event &event); -	void regenCommandsMenu(); -	void regenWeaponsMenu(); -	void processMenuShortCut(byte flags, uint16 ascii);  	void enableCommand(int menunum, int action, bool state);  	void disableAllMenus(); -	bool _menuActivated; +	void setActive(bool active) { _menuActivated = active; } +	bool hasAllFocus() { return _menuActivated; } +  	Common::Rect _bbox;  private: -	Gui *_gui; -	Graphics::ManagedSurface _screenCopy; +	Graphics::ManagedSurface _screen;  	Graphics::ManagedSurface _tempSurface;  private: @@ -120,18 +135,25 @@ private:  	int calculateMenuWidth(MenuItem *menu);  	void calcMenuBounds(MenuItem *menu);  	void renderSubmenu(MenuItem *menu); -	void createCommandsMenu(MenuItem *menu); -	void createWeaponsMenu(MenuItem *menu); -	void executeCommand(MenuSubItem *subitem); + +	bool keyEvent(Common::Event &event); +	bool mouseClick(int x, int y); +	bool mouseRelease(int x, int y); +	bool mouseMove(int x, int y); + +	bool processMenuShortCut(byte flags, uint16 ascii);  	Common::Array<MenuItem *> _items; -	MenuItem *_weapons; -	MenuItem *_commands;  	const Graphics::Font *_font; +	bool _menuActivated; +  	int _activeItem;  	int _activeSubItem; + +	void (*_ccallback)(int action, Common::String &text, void *data); +	void *_cdata;  };  } // End of namespace Wage diff --git a/engines/wage/macwindow.cpp b/engines/wage/macwindow.cpp index 41d842286a..8903936061 100644 --- a/engines/wage/macwindow.cpp +++ b/engines/wage/macwindow.cpp @@ -45,26 +45,49 @@   *   */ +#include "graphics/font.h"  #include "graphics/primitives.h" +#include "common/events.h" -#include "wage/wage.h" -#include "wage/gui.h"  #include "wage/macwindow.h" +#include "wage/macwindowmanager.h"  namespace Wage { -MacWindow::MacWindow(bool scrollable) : _scrollable(scrollable) { +BaseMacWindow::BaseMacWindow(int id, bool editable, MacWindowManager *wm) : +		_id(id), _editable(editable), _wm(wm) { +	_callback = 0; +	_dataPtr = 0; + +	_contentIsDirty = true; + +	_type = kWindowUnknown; +} + +MacWindow::MacWindow(int id, bool scrollable, bool resizable, bool editable, MacWindowManager *wm) : +		BaseMacWindow(id, editable, wm), _scrollable(scrollable), _resizable(resizable) {  	_active = false;  	_borderIsDirty = true;  	_highlightedPart = kBorderNone;  	_scrollPos = _scrollSize = 0.0; + +	_beingDragged = false; +	_beingResized = false; + +	_draggedX = _draggedY = 0; + +	_type = kWindowWindow;  }  MacWindow::~MacWindow() {  } +const Graphics::Font *MacWindow::getTitleFont() { +	return _wm->getFont("Chicago-12", Graphics::FontManager::kBigGUIFont); +} +  void MacWindow::setActive(bool active) {  	if (active == _active)  		return; @@ -86,34 +109,47 @@ void MacWindow::resize(int w, int h) {  	_dims.setWidth(w);  	_dims.setHeight(h); + +	updateInnerDims(); + +	_contentIsDirty = true; +	_borderIsDirty = true;  }  void MacWindow::move(int x, int y) { +	if (_dims.left == x && _dims.top == y) +		return; +  	_dims.moveTo(x, y); +	updateInnerDims(); + +	_contentIsDirty = true;  }  void MacWindow::setDimensions(const Common::Rect &r) {  	resize(r.width(), r.height());  	_dims.moveTo(r.left, r.top); +	updateInnerDims(); + +	_contentIsDirty = true;  } -void MacWindow::draw(Graphics::ManagedSurface *g, bool forceRedraw) { +bool MacWindow::draw(Graphics::ManagedSurface *g, bool forceRedraw) { +	if (!_borderIsDirty && !_contentIsDirty && !forceRedraw) +		return false; +  	if (_borderIsDirty || forceRedraw)  		drawBorder(); +	_contentIsDirty = false; +  	// Compose  	_composeSurface.blitFrom(_surface, Common::Rect(0, 0, _surface.w - 2, _surface.h - 2), Common::Point(2, 2));  	_composeSurface.transBlitFrom(_borderSurface, kColorGreen);  	g->transBlitFrom(_composeSurface, _composeSurface.getBounds(), Common::Point(_dims.left - 2, _dims.top - 2), kColorGreen2); -} -const Graphics::Font *MacWindow::getTitleFont() { -	return ((WageEngine *)g_engine)->_gui->getFont("Chicago-12", Graphics::FontManager::kBigGUIFont); -} - -bool MacWindow::builtInFonts() { -	return ((WageEngine *)g_engine)->_gui->builtInFonts(); +	return true;  }  #define ARROW_W 12 @@ -136,6 +172,11 @@ static void drawPixelInverted(int x, int y, int color, void *data) {  	}  } +void MacWindow::updateInnerDims() { +	_innerDims = _dims; +	_innerDims.grow(-kBorderWidth); +} +  void MacWindow::drawBorder() {  	_borderIsDirty = false; @@ -163,11 +204,11 @@ void MacWindow::drawBorder() {  	drawBox(g, x + width - size + 1, y + size,              size - 4,             height - 2 * size - 1);  	if (active) { -		fillRect(g, x + size, y + 5,           width - 2 * size - 1, 8); -		fillRect(g, x + size, y + height - 13, width - 2 * size - 1, 8); -		fillRect(g, x + 5,    y + size,        8,                    height - 2 * size - 1); +		fillRect(g, x + size, y + 5,           width - 2 * size - 1, 8, kColorBlack); +		fillRect(g, x + size, y + height - 13, width - 2 * size - 1, 8, kColorBlack); +		fillRect(g, x + 5,    y + size,        8,                    height - 2 * size - 1, kColorBlack);  		if (!scrollable) { -			fillRect(g, x + width - 13, y + size, 8, height - 2 * size - 1); +			fillRect(g, x + width - 13, y + size, 8, height - 2 * size - 1, kColorBlack);  		} else {  			int x1 = x + width - 15;  			int y1 = y + size + 1; @@ -177,7 +218,7 @@ void MacWindow::drawBorder() {  					g->hLine(x1 + xx, y1 + yy, x1 + xx, (arrowPixels[yy][xx] != 0 ? kColorBlack : kColorWhite));  			} -			fillRect(g, x + width - 13, y + size + ARROW_H, 8, height - 2 * size - 1 - ARROW_H * 2); +			fillRect(g, x + width - 13, y + size + ARROW_H, 8, height - 2 * size - 1 - ARROW_H * 2, kColorBlack);  			y1 += height - 2 * size - ARROW_H - 2;  			for (int yy = 0; yy < ARROW_H; yy++) { @@ -197,7 +238,7 @@ void MacWindow::drawBorder() {  		}  		if (closeable) {  			if (_highlightedPart == kBorderCloseButton) { -				fillRect(g, x + 6, y + 6, 6, 6); +				fillRect(g, x + 6, y + 6, 6, 6, kColorBlack);  			} else {  				drawBox(g, x + 5, y + 5, 7, 7);  			} @@ -206,7 +247,7 @@ void MacWindow::drawBorder() {  	if (drawTitle) {  		const Graphics::Font *font = getTitleFont(); -		int yOff = builtInFonts() ? 3 : 1; +		int yOff = _wm->hasBuiltInFonts() ? 3 : 1;  		int w = font->getStringWidth(_title) + 10;  		int maxWidth = width - size * 2 - 7; @@ -217,6 +258,24 @@ void MacWindow::drawBorder() {  	}  } +void MacWindow::setHighlight(WindowClick highlightedPart) { +	if (_highlightedPart == highlightedPart) +		return; + +	_highlightedPart = highlightedPart; +	_borderIsDirty = true; + } + + void MacWindow::setScroll(float scrollPos, float scrollSize) { +	if (_scrollPos == scrollPos && _scrollSize == scrollSize) +		return; + +	_scrollPos = scrollPos; +	_scrollSize = scrollSize; +	_borderIsDirty = true; + } + +  void MacWindow::drawBox(Graphics::ManagedSurface *g, int x, int y, int w, int h) {  	Common::Rect r(x, y, x + w + 1, y + h + 1); @@ -230,4 +289,88 @@ void MacWindow::fillRect(Graphics::ManagedSurface *g, int x, int y, int w, int h  	g->fillRect(r, color);  } +WindowClick MacWindow::isInBorder(int x, int y) { +	if (_innerDims.contains(x, y)) +		return kBorderInner; + +	if (x >= _innerDims.left - kBorderWidth && x < _innerDims.left && y >= _innerDims.top - kBorderWidth && y < _innerDims.top) +		return kBorderCloseButton; + +	if (_resizable) +		if (x >= _innerDims.right && x < _innerDims.right + kBorderWidth && y >= _innerDims.bottom && y < _innerDims.bottom + kBorderWidth) +			return kBorderResizeButton; + +	if (_scrollable && x >= _innerDims.right && x < _innerDims.right + kBorderWidth) { +		if (y < _innerDims.top - kBorderWidth) +			return kBorderBorder; + +		if (y >= _innerDims.bottom + kBorderWidth) +			return kBorderBorder; + +		if (y >= _innerDims.top + _innerDims.height() / 2) +			return kBorderScrollDown; + +		return kBorderScrollUp; +	} + +	return kBorderBorder; +} + +bool MacWindow::processEvent(Common::Event &event) { +	WindowClick click = isInBorder(event.mouse.x, event.mouse.y); + +	switch (event.type) { +	case Common::EVENT_MOUSEMOVE: +		if (_beingDragged) { +			_dims.translate(event.mouse.x - _draggedX, event.mouse.y - _draggedY); +			updateInnerDims(); + +			_draggedX = event.mouse.x; +			_draggedY = event.mouse.y; + +			_wm->setFullRefresh(true); +		} + +		if (_beingResized) { +			resize(MAX(kBorderWidth * 4, _dims.width()  + event.mouse.x - _draggedX), +				   MAX(kBorderWidth * 4, _dims.height() + event.mouse.y - _draggedY)); + +			_draggedX = event.mouse.x; +			_draggedY = event.mouse.y; + +			_wm->setFullRefresh(true); +			(*_callback)(click, event, _dataPtr); +		} +		break; +	case Common::EVENT_LBUTTONDOWN: +		setHighlight(click); + +		if (click == kBorderBorder) { +			_beingDragged = true; + +			_draggedX = event.mouse.x; +			_draggedY = event.mouse.y; +		} + +		if (click == kBorderResizeButton) { +			_beingResized = true; + +			_draggedX = event.mouse.x; +			_draggedY = event.mouse.y; +		} + +		break; +	case Common::EVENT_LBUTTONUP: +		_beingDragged = false; +		_beingResized = false; + +		setHighlight(kBorderNone); +		break; +	default: +		return false; +	} + +	return (*_callback)(click, event, _dataPtr); +} +  } // End of namespace Wage diff --git a/engines/wage/macwindow.h b/engines/wage/macwindow.h index e635528c23..4c6e9efeff 100644 --- a/engines/wage/macwindow.h +++ b/engines/wage/macwindow.h @@ -52,55 +52,106 @@  namespace Wage { +class MacWindowManager; +  enum WindowType { -	kWindowScene, -	kWindowConsole +	kWindowUnknown, +	kWindowWindow, +	kWindowMenu  };  enum {  	kBorderWidth = 17  }; -enum BorderHighlight { +enum WindowClick {  	kBorderNone = 0,  	kBorderScrollUp,  	kBorderScrollDown, -	kBorderCloseButton +	kBorderCloseButton, +	kBorderInner, +	kBorderBorder, +	kBorderResizeButton  }; -class MacWindow { +class BaseMacWindow {  public: -	MacWindow(bool scrollable); -	~MacWindow(); +	BaseMacWindow(int id, bool editable, MacWindowManager *wm); +	virtual ~BaseMacWindow() {} + +	const Common::Rect &getDimensions() { return _dims; } +	int getId() { return _id; } +	WindowType getType() { return _type; } +	bool isEditable() { return _editable; } +	Graphics::ManagedSurface *getSurface() { return &_surface; } +	virtual void setActive(bool active) = 0; +	void setDirty(bool dirty) { _contentIsDirty = dirty; } + +	virtual bool draw(Graphics::ManagedSurface *g, bool forceRedraw = false) = 0; +	virtual bool processEvent(Common::Event &event) = 0; + +	virtual bool hasAllFocus() = 0; + +	void setCallback(bool (*callback)(WindowClick, Common::Event &, void *), void *data) { _callback = callback; _dataPtr = data; } + +protected: +	int _id; +	WindowType _type; + +	bool _editable; + +	Graphics::ManagedSurface _surface; +	bool _contentIsDirty; + +	Common::Rect _dims; + +	bool (*_callback)(WindowClick, Common::Event &, void *); +	void *_dataPtr; + +	MacWindowManager *_wm; +}; + +class MacWindow : public BaseMacWindow { +public: +	MacWindow(int id, bool scrollable, bool resizable, bool editable, MacWindowManager *wm); +	virtual ~MacWindow();  	void move(int x, int y);  	void resize(int w, int h);  	void setDimensions(const Common::Rect &r); -	void draw(Graphics::ManagedSurface *g, bool forceRedraw = false); +	const Common::Rect &getInnerDimensions() { return _innerDims; } + +	bool draw(Graphics::ManagedSurface *g, bool forceRedraw = false); +  	void setActive(bool active); -	Graphics::ManagedSurface *getSurface() { return &_surface; }  	void setTitle(Common::String &title) { _title = title; } -	void setHighlight(BorderHighlight highlightedPart) { _highlightedPart = highlightedPart; } -	void setScroll(float scrollPos, float scrollSize) { _scrollPos = scrollPos; _scrollSize = scrollSize; } +	void setHighlight(WindowClick highlightedPart); +	void setScroll(float scrollPos, float scrollSize); +	bool processEvent(Common::Event &event); +	bool hasAllFocus() { return _beingDragged || _beingResized; }  private:  	void drawBorder();  	void drawBox(Graphics::ManagedSurface *g, int x, int y, int w, int h); -	void fillRect(Graphics::ManagedSurface *g, int x, int y, int w, int h, int color = kColorBlack); +	void fillRect(Graphics::ManagedSurface *g, int x, int y, int w, int h, int color);  	const Graphics::Font *getTitleFont(); -	bool builtInFonts(); +	void updateInnerDims(); +	WindowClick isInBorder(int x, int y);  private: -	Graphics::ManagedSurface _surface;  	Graphics::ManagedSurface _borderSurface;  	Graphics::ManagedSurface _composeSurface;  	bool _scrollable; +	bool _resizable;  	bool _active;  	bool _borderIsDirty; -	BorderHighlight _highlightedPart; +	bool _beingDragged, _beingResized; +	int _draggedX, _draggedY; + +	WindowClick _highlightedPart;  	float _scrollPos, _scrollSize; -	Common::Rect _dims; +	Common::Rect _innerDims;  	Common::String _title;  }; diff --git a/engines/wage/macwindowmanager.cpp b/engines/wage/macwindowmanager.cpp index 72f01fac67..5cc54d648a 100644 --- a/engines/wage/macwindowmanager.cpp +++ b/engines/wage/macwindowmanager.cpp @@ -45,38 +45,127 @@   *   */ -#include "common/list.h"  #include "common/array.h" +#include "common/events.h" +#include "common/list.h" +#include "common/unzip.h" +#include "common/system.h" +#include "common/stream.h" +#include "graphics/cursorman.h" +#include "graphics/fonts/bdf.h"  #include "graphics/managed_surface.h" +#include "graphics/palette.h" +#include "graphics/primitives.h" -#include "wage/wage.h" -#include "wage/macwindow.h"  #include "wage/macwindowmanager.h" +#include "wage/macwindow.h" +#include "wage/macmenu.h"  namespace Wage { +static const byte palette[] = { +	0, 0, 0,           // Black +	0x80, 0x80, 0x80,  // Gray +	0xff, 0xff, 0xff,  // White +	0x00, 0xff, 0x00,  // Green +	0x00, 0xcf, 0x00   // Green2 +}; + +static byte fillPatterns[][8] = { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, // kPatternSolid +								  { 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55 }, // kPatternStripes +								  { 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55 }, // kPatternCheckers +								  { 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa }  // kPatternCheckers2 +}; + +static const byte macCursorArrow[] = { +	2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, +	2, 0, 2, 3, 3, 3, 3, 3, 3, 3, 3, +	2, 0, 0, 2, 3, 3, 3, 3, 3, 3, 3, +	2, 0, 0, 0, 2, 3, 3, 3, 3, 3, 3, +	2, 0, 0, 0, 0, 2, 3, 3, 3, 3, 3, +	2, 0, 0, 0, 0, 0, 2, 3, 3, 3, 3, +	2, 0, 0, 0, 0, 0, 0, 2, 3, 3, 3, +	2, 0, 0, 0, 0, 0, 0, 0, 2, 3, 3, +	2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, +	2, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, +	2, 0, 0, 2, 0, 0, 2, 3, 3, 3, 3, +	2, 0, 2, 3, 2, 0, 0, 2, 3, 3, 3, +	2, 2, 3, 3, 2, 0, 0, 2, 3, 3, 3, +	2, 3, 3, 3, 3, 2, 0, 0, 2, 3, 3, +	3, 3, 3, 3, 3, 2, 0, 0, 2, 3, 3, +	3, 3, 3, 3, 3, 3, 2, 2, 2, 3, 3 +}; + +static const byte macCursorBeam[] = { +	0, 0, 3, 3, 3, 0, 0, 3, 3, 3, 3, +	3, 3, 0, 3, 0, 3, 3, 3, 3, 3, 3, +	3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, +	3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, +	3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, +	3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, +	3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, +	3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, +	3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, +	3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, +	3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, +	3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, +	3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, +	3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, +	3, 3, 0, 3, 0, 3, 3, 3, 3, 3, 3, +	0, 0, 3, 3, 3, 0, 0, 3, 3, 3, 3, +}; +  MacWindowManager::MacWindowManager() { +    _screen = 0;      _lastId = 0;      _activeWindow = -1; + +	_menu = 0; + +	_fullRefresh = true; + +	_builtInFonts = true; + +	for (int i = 0; i < ARRAYSIZE(fillPatterns); i++) +		_patterns.push_back(fillPatterns[i]); + +	loadFonts(); + +	g_system->getPaletteManager()->setPalette(palette, 0, ARRAYSIZE(palette) / 3); + +	CursorMan.replaceCursorPalette(palette, 0, ARRAYSIZE(palette) / 3); +	CursorMan.replaceCursor(macCursorArrow, 11, 16, 1, 1, 3); +	_cursorIsArrow = true; +	CursorMan.showMouse(true);  }  MacWindowManager::~MacWindowManager() { -    for (uint i = 0; i < _lastId; i++) +    for (int i = 0; i < _lastId; i++)          delete _windows[i];  } -int MacWindowManager::add(bool scrollable) { -    MacWindow *w = new MacWindow(scrollable); +MacWindow *MacWindowManager::addWindow(bool scrollable, bool resizable, bool editable) { +    MacWindow *w = new MacWindow(_lastId, scrollable, resizable, editable, this);      _windows.push_back(w);      _windowStack.push_back(w); -    _activeWindow = _lastId; +    setActive(_lastId);      _lastId++; -    return _activeWindow; +    return w; +} + +Menu *MacWindowManager::addMenu() { +	_menu = new Menu(_lastId, _screen->getBounds(), this); + +	_windows.push_back(_menu); + +	_lastId++; + +	return _menu;  }  void MacWindowManager::setActive(int id) { @@ -86,6 +175,8 @@ void MacWindowManager::setActive(int id) {      if (_activeWindow != -1)          _windows[_activeWindow]->setActive(false); +    _activeWindow = id; +      _windows[id]->setActive(true);      _windowStack.remove(_windows[id]); @@ -94,11 +185,196 @@ void MacWindowManager::setActive(int id) {      _fullRefresh = true;  } -void MacWindowManager::draw(Graphics::ManagedSurface *g) { -    for (Common::List<MacWindow *>::const_iterator it = _windowStack.begin(); it != _windowStack.end(); it++) -        (*it)->draw(g, _fullRefresh); +struct PlotData { +	Graphics::ManagedSurface *surface; +	Patterns *patterns; +	uint fillType; +	int thickness; + +	PlotData(Graphics::ManagedSurface *s, Patterns *p, int f, int t) : +		surface(s), patterns(p), fillType(f), thickness(t) {} +}; + +static void drawPixel(int x, int y, int color, void *data) { +	PlotData *p = (PlotData *)data; + +	if (p->fillType > p->patterns->size()) +		return; + +	byte *pat = p->patterns->operator[](p->fillType - 1); + +	if (p->thickness == 1) { +		if (x >= 0 && x < p->surface->w && y >= 0 && y < p->surface->h) { +			uint xu = (uint)x; // for letting compiler optimize it +			uint yu = (uint)y; + +			*((byte *)p->surface->getBasePtr(xu, yu)) = +				(pat[yu % 8] & (1 << (7 - xu % 8))) ? +					color : kColorWhite; +		} +	} else { +		int x1 = x; +		int x2 = x1 + p->thickness; +		int y1 = y; +		int y2 = y1 + p->thickness; + +		for (y = y1; y < y2; y++) +			for (x = x1; x < x2; x++) +				if (x >= 0 && x < p->surface->w && y >= 0 && y < p->surface->h) { +					uint xu = (uint)x; // for letting compiler optimize it +					uint yu = (uint)y; +					*((byte *)p->surface->getBasePtr(xu, yu)) = +						(pat[yu % 8] & (1 << (7 - xu % 8))) ? +							color : kColorWhite; +				} +	} +} + +void MacWindowManager::drawDesktop() { +	Common::Rect r(_screen->getBounds()); + +	PlotData pd(_screen, &_patterns, kPatternCheckers, 1); + +	Graphics::drawRoundRect(r, kDesktopArc, kColorBlack, true, drawPixel, &pd); + +	g_system->copyRectToScreen(_screen->getPixels(), _screen->pitch, 0, 0, _screen->w, _screen->h); +} + +void MacWindowManager::draw() { +    assert(_screen); + +	if (_fullRefresh) +		drawDesktop(); + +    for (Common::List<BaseMacWindow *>::const_iterator it = _windowStack.begin(); it != _windowStack.end(); it++) { +        BaseMacWindow *w = *it; +        if (w->draw(_screen, _fullRefresh)) { +            w->setDirty(false); + +			Common::Rect clip(w->getDimensions().left - 2, w->getDimensions().top - 2, w->getDimensions().right - 2, w->getDimensions().bottom - 2); +			clip.clip(_screen->getBounds()); + +            g_system->copyRectToScreen(_screen->getBasePtr(clip.left, clip.top), _screen->pitch, clip.left, clip.top, clip.width(), clip.height()); +        } +    } + +	// Menu is drawn on top of everything and always +	if (_menu) +		_menu->draw(_screen, _fullRefresh);      _fullRefresh = false;  } +bool MacWindowManager::processEvent(Common::Event &event) { +	// Menu gets events first fir shortcuts and menu bar +	if (_menu && _menu->processEvent(event)) +		return true; + +    if (event.type != Common::EVENT_MOUSEMOVE && event.type != Common::EVENT_LBUTTONDOWN && +            event.type != Common::EVENT_LBUTTONUP) +        return false; + +	if (_windows[_activeWindow]->isEditable() && _windows[_activeWindow]->getType() == kWindowWindow && +			((MacWindow *)_windows[_activeWindow])->getInnerDimensions().contains(event.mouse.x, event.mouse.y)) { +		if (_cursorIsArrow) { +			CursorMan.replaceCursor(macCursorBeam, 11, 16, 3, 8, 3); +			_cursorIsArrow = false; +		} +	} else { +		if (_cursorIsArrow == false) { +			CursorMan.replaceCursor(macCursorArrow, 11, 16, 1, 1, 3); +			_cursorIsArrow = true; +		} +	} + +    for (Common::List<BaseMacWindow *>::const_iterator it = _windowStack.end(); it != _windowStack.begin();) { +        it--; +        BaseMacWindow *w = *it; + +        if (w->hasAllFocus() || w->getDimensions().contains(event.mouse.x, event.mouse.y)) { +            if (event.type == Common::EVENT_LBUTTONDOWN || event.type == Common::EVENT_LBUTTONUP) +                setActive(w->getId()); + +            return w->processEvent(event); +        } +    } + +    return false; +} + +////////////////////// +// Font stuff +////////////////////// +void MacWindowManager::loadFonts() { +	Common::Archive *dat; + +	dat = Common::makeZipArchive("classicmacfonts.dat"); + +	if (!dat) { +		warning("Could not find classicmacfonts.dat. Falling back to built-in fonts"); +		_builtInFonts = true; + +		return; +	} + +	Common::ArchiveMemberList list; +	dat->listMembers(list); + +	for (Common::ArchiveMemberList::iterator it = list.begin(); it != list.end(); ++it) { +		Common::SeekableReadStream *stream = dat->createReadStreamForMember((*it)->getName()); + +		Graphics::BdfFont *font = Graphics::BdfFont::loadFont(*stream); + +		delete stream; + +		Common::String fontName = (*it)->getName(); + +		// Trim the .bdf extension +		for (int i = fontName.size() - 1; i >= 0; --i) { +			if (fontName[i] == '.') { +				while ((uint)i < fontName.size()) { +					fontName.deleteLastChar(); +				} +				break; +			} +		} + +		FontMan.assignFontToName(fontName, font); + +		debug(2, " %s", fontName.c_str()); +	} + +	_builtInFonts = false; + +	delete dat; +} + +const Graphics::Font *MacWindowManager::getFont(const char *name, Graphics::FontManager::FontUsage fallback) { +	const Graphics::Font *font = 0; + +	if (!_builtInFonts) { +		font = FontMan.getFontByName(name); + +		if (!font) +			warning("Cannot load font %s", name); +	} + +	if (_builtInFonts || !font) +		font = FontMan.getFontByUsage(fallback); + +	return font; +} + +///////////////// +// Cursor stuff +///////////////// +void MacWindowManager::pushArrowCursor() { +	CursorMan.pushCursor(macCursorArrow, 11, 16, 1, 1, 3); +} + +void MacWindowManager::popCursor() { +	CursorMan.popCursor(); +} + +  } // End of namespace Wage diff --git a/engines/wage/macwindowmanager.h b/engines/wage/macwindowmanager.h index 1c8ed02a85..13f85cddd4 100644 --- a/engines/wage/macwindowmanager.h +++ b/engines/wage/macwindowmanager.h @@ -48,30 +48,92 @@  #ifndef WAGE_MACWINDOWMANAGER_H  #define WAGE_MACWINDOWMANAGER_H +#include "common/array.h" +#include "common/list.h" +#include "common/events.h" +#include "common/archive.h" + +#include "graphics/fontman.h" + +namespace Graphics { +class ManagedSurface; +} +  namespace Wage { +enum { +	kDesktopArc = 7 +}; + +enum { +	kColorBlack  = 0, +	kColorGray   = 1, +	kColorWhite  = 2, +	kColorGreen  = 3, +	kColorGreen2 = 4 +}; + +enum { +	kPatternSolid = 1, +	kPatternStripes = 2, +	kPatternCheckers = 3, +	kPatternCheckers2 = 4 +}; + +class BaseMacWindow;  class MacWindow; +class Menu; + +typedef Common::Array<byte *> Patterns;  class MacWindowManager {  public:  	MacWindowManager();  	~MacWindowManager(); -	int add(bool scrollable); +	void setScreen(Graphics::ManagedSurface *screen) { _screen = screen; } +	bool hasBuiltInFonts() { return _builtInFonts; } +	const Graphics::Font *getFont(const char *name, Graphics::FontManager::FontUsage fallback); + +	MacWindow *addWindow(bool scrollable, bool resizable, bool editable); +	Menu *addMenu();  	void setActive(int id); -	void draw(Graphics::ManagedSurface *g); +	void setFullRefresh(bool redraw) { _fullRefresh = true; } -	MacWindow *getWindow(int id) { return _windows[id]; } +	void draw(); + +	bool processEvent(Common::Event &event); + +	BaseMacWindow *getWindow(int id) { return _windows[id]; } + +	Patterns &getPatterns() { return _patterns; } +	void drawFilledRoundRect(Graphics::ManagedSurface *surface, Common::Rect &rect, int arc, int color); + +	void pushArrowCursor(); +	void popCursor(); + +private: +	void drawDesktop(); +	void loadFonts();  private: -	Common::List<MacWindow *> _windowStack; -	Common::Array<MacWindow *> _windows; +	Graphics::ManagedSurface *_screen; + +	Common::List<BaseMacWindow *> _windowStack; +	Common::Array<BaseMacWindow *> _windows;  	int _lastId;  	int _activeWindow;  	bool _fullRefresh; + +	Patterns _patterns; + +	Menu *_menu; + +	bool _builtInFonts; +	bool _cursorIsArrow;  };  } // End of namespace Wage diff --git a/engines/wage/module.mk b/engines/wage/module.mk index d65934fc2b..e150d5f27e 100644 --- a/engines/wage/module.mk +++ b/engines/wage/module.mk @@ -9,9 +9,9 @@ MODULE_OBJS := \  	entities.o \  	gui.o \  	gui-console.o \ +	macmenu.o \  	macwindow.o \  	macwindowmanager.o \ -	menu.o \  	randomhat.o \  	script.o \  	sound.o \ diff --git a/engines/wage/wage.cpp b/engines/wage/wage.cpp index 3a52aed1c4..567e2768d8 100644 --- a/engines/wage/wage.cpp +++ b/engines/wage/wage.cpp @@ -86,6 +86,7 @@ WageEngine::WageEngine(OSystem *syst, const ADGameDescription *desc) : Engine(sy  	_offer = NULL;  	_resManager = NULL; +	_debugger = NULL;  	debug("WageEngine::WageEngine()");  } @@ -148,24 +149,14 @@ void WageEngine::processEvents() {  	Common::Event event;  	while (_eventMan->pollEvent(event)) { +		if (_gui->processEvent(event)) +			continue; +  		switch (event.type) {  		case Common::EVENT_QUIT:  			if (saveDialog())  				_shouldQuit = true;  			break; -		case Common::EVENT_MOUSEMOVE: -			_gui->mouseMove(event.mouse.x, event.mouse.y); -			break; -		case Common::EVENT_LBUTTONDOWN: -			_gui->mouseDown(event.mouse.x, event.mouse.y); -			break; -		case Common::EVENT_LBUTTONUP: -			{ -				Designed *obj = _gui->mouseUp(event.mouse.x, event.mouse.y); -				if (obj != NULL) -					processTurn(NULL, obj); -			} -			break;  		case Common::EVENT_KEYDOWN:  			switch (event.kbd.keycode) {  			case Common::KEYCODE_BACKSPACE: @@ -189,13 +180,6 @@ void WageEngine::processEvents() {  					break;  				} -				if (event.kbd.flags & (Common::KBD_ALT | Common::KBD_CTRL | Common::KBD_META)) { -					if (event.kbd.ascii >= 0x20 && event.kbd.ascii <= 0x7f) { -						_gui->processMenuShortCut(event.kbd.flags, event.kbd.ascii); -					} -					break; -				} -  				if (event.kbd.ascii >= 0x20 && event.kbd.ascii <= 0x7f) {  					_inputText += (char)event.kbd.ascii;  					_gui->drawInput(); @@ -236,7 +220,6 @@ void WageEngine::gameOver() {  	_gui->disableAllMenus();  	_gui->enableNewGameMenus(); -	_gui->_menuDirty = true;  }  bool WageEngine::saveDialog() { diff --git a/engines/wage/wage.h b/engines/wage/wage.h index 87009c2350..eb50a2e3dd 100644 --- a/engines/wage/wage.h +++ b/engines/wage/wage.h @@ -103,14 +103,6 @@ enum {  	// the current limitation is 32 debug levels (1 << 31 is the last one)  }; -enum { -	kColorBlack  = 0, -	kColorGray   = 1, -	kColorWhite  = 2, -	kColorGreen  = 3, -	kColorGreen2 = 4 -}; -  Common::String readPascalString(Common::SeekableReadStream *in);  Common::Rect *readRect(Common::SeekableReadStream *in);  const char *getIndefiniteArticle(const Common::String &word); @@ -118,8 +110,6 @@ const char *prependGenderSpecificPronoun(int gender);  const char *getGenderSpecificPronoun(int gender, bool capitalize);  bool isStorageScene(const Common::String &name); -typedef Common::Array<byte *> Patterns; -  class WageEngine : public Engine {  	friend class Dialog;  public: diff --git a/engines/wage/world.cpp b/engines/wage/world.cpp index 954a425b7b..53fc1b4742 100644 --- a/engines/wage/world.cpp +++ b/engines/wage/world.cpp @@ -73,6 +73,8 @@ World::World(WageEngine *engine) {  	_weaponMenuDisabled = true;  	_engine = engine; + +	_patterns = new Patterns;  }  World::~World() { @@ -88,8 +90,10 @@ World::~World() {  	for (uint i = 0; i < _orderedScenes.size(); i++)  		delete _orderedScenes[i]; -	for (uint i = 0; i < _patterns.size(); i++) -		free(_patterns[i]); +	for (uint i = 0; i < _patterns->size(); i++) +		free(_patterns->operator[](i)); + +	delete _patterns;  	delete _globalScript; @@ -261,7 +265,7 @@ bool World::loadWorld(Common::MacResManager *resMan) {  			byte *pattern = (byte *)malloc(8);  			res->read(pattern, 8); -			_patterns.push_back(pattern); +			_patterns->push_back(pattern);  		}  		delete res; @@ -274,7 +278,7 @@ bool World::loadWorld(Common::MacResManager *resMan) {  				byte *pattern = (byte *)malloc(8);  				res->read(pattern, 8); -				_patterns.push_back(pattern); +				_patterns->push_back(pattern);  			}  		}  		delete res; diff --git a/engines/wage/world.h b/engines/wage/world.h index 355d660c8d..468bedbc59 100644 --- a/engines/wage/world.h +++ b/engines/wage/world.h @@ -48,6 +48,8 @@  #ifndef WAGE_WORLD_H  #define WAGE_WORLD_H +#include "wage/macwindowmanager.h" +  namespace Wage {  class Sound; @@ -85,7 +87,7 @@ public:  	ObjArray _orderedObjs;  	ChrArray _orderedChrs;  	Common::Array<Sound *> _orderedSounds; -	Patterns _patterns; +	Patterns *_patterns;  	Scene *_storageScene;  	Chr *_player;  	//List<MoveListener> moveListeners; diff --git a/engines/wintermute/base/base_engine.cpp b/engines/wintermute/base/base_engine.cpp index 2166a3e070..4ce334aceb 100644 --- a/engines/wintermute/base/base_engine.cpp +++ b/engines/wintermute/base/base_engine.cpp @@ -84,7 +84,7 @@ void BaseEngine::LOG(bool res, const char *fmt, ...) {  	va_end(va);  	if (instance()._gameRef) { -		instance()._gameRef->LOG("%s", buff); +		instance()._gameRef->LOG(res, "%s", buff);  	} else {  		debugCN(kWintermuteDebugLog, "%02d:%02d:%02d: %s\n", hours, mins, secs, buff);  	} diff --git a/engines/wintermute/base/sound/base_sound_manager.cpp b/engines/wintermute/base/sound/base_sound_manager.cpp index f1e0c3b1f9..74c0086817 100644 --- a/engines/wintermute/base/sound/base_sound_manager.cpp +++ b/engines/wintermute/base/sound/base_sound_manager.cpp @@ -100,15 +100,14 @@ BaseSoundBuffer *BaseSoundMgr::addSound(const Common::String &filename, Audio::M  	BaseSoundBuffer *sound;  	Common::String useFilename = filename; +	useFilename.toLowercase();  	// try to switch WAV to OGG file (if available) -	AnsiString ext = PathUtil::getExtension(filename); -	if (StringUtil::compareNoCase(ext, "wav")) { -		AnsiString path = PathUtil::getDirectoryName(filename); -		AnsiString name = PathUtil::getFileNameWithoutExtension(filename); - -		AnsiString newFile = PathUtil::combine(path, name + "ogg"); -		if (BaseFileManager::getEngineInstance()->hasFile(newFile)) { -			useFilename = newFile; +	if (useFilename.hasSuffix(".wav")) { +		Common::String oggFilename = useFilename; +		oggFilename.erase(oggFilename.size() - 4); +		oggFilename = oggFilename + ".ogg"; +		if (BaseFileManager::getEngineInstance()->hasFile(oggFilename)) { +			useFilename = oggFilename;  		}  	} diff --git a/gui/Tooltip.h b/gui/Tooltip.h index 58b6d8a429..60688412e6 100644 --- a/gui/Tooltip.h +++ b/gui/Tooltip.h @@ -41,6 +41,8 @@ public:  	void setup(Dialog *parent, Widget *widget, int x, int y);  	void drawDialog(); + +	virtual void receivedFocus(int x = -1, int y = -1) {}  protected:  	virtual void handleMouseDown(int x, int y, int button, int clickCount) {  		close(); @@ -64,7 +66,6 @@ protected:  	}  	virtual void handleMouseMoved(int x, int y, int button) {  		close(); -		_parent->handleMouseMoved(x + (getAbsX() - _parent->getAbsX()), y + (getAbsY() - _parent->getAbsY()), button);  	}  	int _maxWidth; diff --git a/gui/debugger.cpp b/gui/debugger.cpp index c9b435963d..72d05e2973 100644 --- a/gui/debugger.cpp +++ b/gui/debugger.cpp @@ -42,6 +42,7 @@  #elif defined(USE_READLINE)  	#include <readline/readline.h>  	#include <readline/history.h> +	#include "common/events.h"  #endif @@ -191,6 +192,15 @@ char *readline_completionFunction(const char *text, int state) {  	return g_readline_debugger->readlineComplete(text, state);  } +void readline_eventFunction() { +	Common::EventManager *eventMan = g_system->getEventManager(); + +	Common::Event event; +	while (eventMan->pollEvent(event)) { +		// drop all events +	} +} +  #ifdef USE_READLINE_INT_COMPLETION  typedef int RLCompFunc_t(const char *, int);  #else @@ -228,6 +238,7 @@ void Debugger::enter() {  	g_readline_debugger = this;  	rl_completion_entry_function = (RLCompFunc_t *)&readline_completionFunction; +	rl_event_hook = (rl_hook_func_t *)&readline_eventFunction;  	char *line_read = 0;  	do { diff --git a/gui/dialog.cpp b/gui/dialog.cpp index 315c24e9bf..075a3bb533 100644 --- a/gui/dialog.cpp +++ b/gui/dialog.cpp @@ -119,6 +119,8 @@ void Dialog::reflowLayout() {  }  void Dialog::lostFocus() { +	_dragWidget = NULL; +  	if (_tickleWidget) {  		_tickleWidget->lostFocus();  	} diff --git a/gui/dialog.h b/gui/dialog.h index 593ee13458..0e06effabd 100644 --- a/gui/dialog.h +++ b/gui/dialog.h @@ -82,7 +82,7 @@ public:  	virtual void reflowLayout();  	virtual void lostFocus(); -	virtual void receivedFocus() {} +	virtual void receivedFocus(int x = -1, int y = -1) { if (x >= 0 && y >= 0) handleMouseMoved(x, y, 0); }  protected:  	virtual void open(); diff --git a/gui/gui-manager.cpp b/gui/gui-manager.cpp index 4ddf62b2fe..3ce8bee020 100644 --- a/gui/gui-manager.cpp +++ b/gui/gui-manager.cpp @@ -281,15 +281,10 @@ void GuiManager::runLoop() {  		redraw();  	} -	_lastMousePosition.x = _lastMousePosition.y = -1; -	_lastMousePosition.time = 0; -  	Common::EventManager *eventMan = _system->getEventManager();  	uint32 lastRedraw = 0;  	const uint32 waitTime = 1000 / 60; -	bool tooltipCheck = false; -  	while (!_dialogStack.empty() && activeDialog == getTopDialog() && !eventMan->shouldQuit()) {  		redraw(); @@ -336,11 +331,6 @@ void GuiManager::runLoop() {  			processEvent(event, activeDialog); -			if (event.type == Common::EVENT_MOUSEMOVE) { -				tooltipCheck = true; -			} - -  			if (lastRedraw + waitTime < _system->getMillis(true)) {  				lastRedraw = _system->getMillis(true);  				_theme->updateScreen(); @@ -348,7 +338,7 @@ void GuiManager::runLoop() {  			}  		} -		if (tooltipCheck && _lastMousePosition.time + kTooltipDelay < _system->getMillis(true)) { +		if (_lastMousePosition.time + kTooltipDelay < _system->getMillis(true)) {  			Widget *wdg = activeDialog->findWidget(_lastMousePosition.x, _lastMousePosition.y);  			if (wdg && wdg->hasTooltip() && !(wdg->getFlags() & WIDGET_PRESSED)) {  				Tooltip *tooltip = new Tooltip(); @@ -415,7 +405,7 @@ void GuiManager::restoreState() {  }  void GuiManager::openDialog(Dialog *dialog) { -	dialog->receivedFocus(); +	giveFocusToDialog(dialog);  	if (!_dialogStack.empty())  		getTopDialog()->lostFocus(); @@ -439,8 +429,10 @@ void GuiManager::closeTopDialog() {  	// Remove the dialog from the stack  	_dialogStack.pop()->lostFocus(); -	if (!_dialogStack.empty()) -		getTopDialog()->receivedFocus(); +	if (!_dialogStack.empty()) { +		Dialog *dialog = getTopDialog(); +		giveFocusToDialog(dialog); +	}  	if (_redrawStatus != kRedrawFull)  		_redrawStatus = kRedrawCloseDialog; @@ -515,6 +507,7 @@ void GuiManager::processEvent(const Common::Event &event, Dialog *const activeDi  	int button;  	uint32 time;  	Common::Point mouse(event.mouse.x - activeDialog->_x, event.mouse.y - activeDialog->_y); +  	switch (event.type) {  	case Common::EVENT_KEYDOWN:  		activeDialog->handleKeyDown(event.kbd); @@ -523,12 +516,12 @@ void GuiManager::processEvent(const Common::Event &event, Dialog *const activeDi  		activeDialog->handleKeyUp(event.kbd);  		break;  	case Common::EVENT_MOUSEMOVE: +		_globalMousePosition.x = event.mouse.x; +		_globalMousePosition.y = event.mouse.y;  		activeDialog->handleMouseMoved(mouse.x, mouse.y, 0);  		if (mouse.x != _lastMousePosition.x || mouse.y != _lastMousePosition.y) { -			_lastMousePosition.x = mouse.x; -			_lastMousePosition.y = mouse.y; -			_lastMousePosition.time = _system->getMillis(true); +			setLastMousePos(mouse.x, mouse.y);  		}  		break; @@ -571,4 +564,17 @@ void GuiManager::processEvent(const Common::Event &event, Dialog *const activeDi  	}  } +void GuiManager::giveFocusToDialog(Dialog *dialog) { +	int16 dialogX = _globalMousePosition.x - dialog->_x; +	int16 dialogY = _globalMousePosition.y - dialog->_y; +	dialog->receivedFocus(dialogX, dialogY); +	setLastMousePos(dialogX, dialogY); +} + +void GuiManager::setLastMousePos(int16 x, int16 y) { +	_lastMousePosition.x = x; +	_lastMousePosition.y = y; +	_lastMousePosition.time = _system->getMillis(true); +} +  } // End of namespace GUI diff --git a/gui/gui-manager.h b/gui/gui-manager.h index 26c8d6def9..35779215b2 100644 --- a/gui/gui-manager.h +++ b/gui/gui-manager.h @@ -124,11 +124,12 @@ protected:  	bool		_useStdCursor;  	// position and time of last mouse click (used to detect double clicks) -	struct { +	struct MousePos { +		MousePos() : x(-1), y(-1), count(0) { time = 0; }  		int16 x, y;	// Position of mouse when the click occurred  		uint32 time;	// Time  		int count;	// How often was it already pressed? -	} _lastClick, _lastMousePosition; +	} _lastClick, _lastMousePosition, _globalMousePosition;  	// mouse cursor state  	int		_cursorAnimateCounter; @@ -155,6 +156,9 @@ protected:  	Dialog *getTopDialog() const;  	void screenChange(); + +	void giveFocusToDialog(Dialog *dialog); +	void setLastMousePos(int16 x, int16 y);  };  } // End of namespace GUI diff --git a/gui/predictivedialog.cpp b/gui/predictivedialog.cpp index 9557da1206..63b69a39ea 100644 --- a/gui/predictivedialog.cpp +++ b/gui/predictivedialog.cpp @@ -190,7 +190,7 @@ void PredictiveDialog::saveUserDictToFile() {  void PredictiveDialog::handleKeyUp(Common::KeyState state) {  	if (_curPressedButton != kNoAct && !_needRefresh) { -		_button[_curPressedButton]->startAnimatePressedState(); +		_button[_curPressedButton]->setUnpressedState();  		processButton(_curPressedButton);  	}  } @@ -352,7 +352,7 @@ void PredictiveDialog::handleKeyDown(Common::KeyState state) {  	}  	if (_lastButton != _curPressedButton) -		_button[_lastButton]->stopAnimatePressedState(); +		_button[_lastButton]->setUnpressedState();  	if (_curPressedButton != kNoAct && !_needRefresh)  		_button[_curPressedButton]->setPressedState(); @@ -604,18 +604,6 @@ void PredictiveDialog::processButton(ButtonId button) {  	}  } -void PredictiveDialog::handleTickle() { -	if (_lastTime) { -		if ((_curTime - _lastTime) > kRepeatDelay) { -			_lastTime = 0; -		} -	} - -	if (getTickleWidget()) { -		getTickleWidget()->handleTickle(); -	} -} -  void PredictiveDialog::mergeDicts() {  	_unitedDict.dictLineCount  = _predictiveDict.dictLineCount + _userDict.dictLineCount;  	_unitedDict.dictLine = (char **)calloc(_unitedDict.dictLineCount, sizeof(char *)); diff --git a/gui/predictivedialog.h b/gui/predictivedialog.h index 4c167c3efa..1f6bdf84e0 100644 --- a/gui/predictivedialog.h +++ b/gui/predictivedialog.h @@ -43,7 +43,6 @@ public:  	virtual void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data);  	virtual void handleKeyUp(Common::KeyState state);  	virtual void handleKeyDown(Common::KeyState state); -	virtual void handleTickle();  	const char *getResult() const { return _predictiveResult; } diff --git a/gui/widget.cpp b/gui/widget.cpp index 4143111e54..03540f7b91 100644 --- a/gui/widget.cpp +++ b/gui/widget.cpp @@ -299,7 +299,7 @@ ButtonWidget::ButtonWidget(GuiObject *boss, const Common::String &name, const Co  void ButtonWidget::handleMouseUp(int x, int y, int button, int clickCount) {  	if (isEnabled() && _duringPress && x >= 0 && x < _w && y >= 0 && y < _h) { -		startAnimatePressedState(); +		setUnpressedState();  		sendCommand(_cmd, 0);  	}  	_duringPress = false; @@ -344,40 +344,17 @@ void ButtonWidget::setHighLighted(bool enable) {  	draw();  } -void ButtonWidget::handleTickle() { -	if (_lastTime) { -		uint32 curTime = g_system->getMillis(); -		if (curTime - _lastTime > kPressedButtonTime) { -			stopAnimatePressedState(); -		} -	} -} -  void ButtonWidget::setPressedState() { -	wantTickle(true);  	setFlags(WIDGET_PRESSED);  	clearFlags(WIDGET_HILITED);  	draw();  } -void ButtonWidget::stopAnimatePressedState() { -	wantTickle(false); -	_lastTime = 0; +void ButtonWidget::setUnpressedState() {  	clearFlags(WIDGET_PRESSED);  	draw();  } -void ButtonWidget::startAnimatePressedState() { -	_lastTime = g_system->getMillis(); -} - -void ButtonWidget::wantTickle(bool tickled) { -	if (tickled) -		((GUI::Dialog *)_boss)->setTickleWidget(this); -	else -		((GUI::Dialog *)_boss)->unSetTickleWidget(); -} -  #pragma mark -  PicButtonWidget::PicButtonWidget(GuiObject *boss, int x, int y, int w, int h, const char *tooltip, uint32 cmd, uint8 hotkey) diff --git a/gui/widget.h b/gui/widget.h index 4f181954b5..7f6f0c0533 100644 --- a/gui/widget.h +++ b/gui/widget.h @@ -201,17 +201,12 @@ public:  	void handleMouseDown(int x, int y, int button, int clickCount);  	void handleMouseEntered(int button)	{ if (_duringPress) { setFlags(WIDGET_PRESSED); } else { setFlags(WIDGET_HILITED); } draw(); }  	void handleMouseLeft(int button)	{ clearFlags(WIDGET_HILITED | WIDGET_PRESSED); draw(); } -	void handleTickle();  	void setHighLighted(bool enable);  	void setPressedState(); -	void startAnimatePressedState(); -	void stopAnimatePressedState(); - -	void lostFocusWidget() { stopAnimatePressedState(); } +	void setUnpressedState();  protected:  	void drawWidget(); -	void wantTickle(bool tickled);  	bool _duringPress;  private:  	uint32 _lastTime; diff --git a/gui/widgets/popup.cpp b/gui/widgets/popup.cpp index b10b4fb5fe..0b2ea9fd4e 100644 --- a/gui/widgets/popup.cpp +++ b/gui/widgets/popup.cpp @@ -388,6 +388,8 @@ PopUpWidget::PopUpWidget(GuiObject *boss, int x, int y, int w, int h, const char  	_type = kPopUpWidget;  	_selectedItem = -1; + +	_leftPadding = _rightPadding = 0;  }  void PopUpWidget::handleMouseDown(int x, int y, int button, int clickCount) { diff --git a/po/de_DE.po b/po/de_DE.po index 8cfa723ece..65765ecca0 100644 --- a/po/de_DE.po +++ b/po/de_DE.po @@ -7,8 +7,8 @@ msgid ""  msgstr ""  "Project-Id-Version: ScummVM 1.9.0git\n"  "Report-Msgid-Bugs-To: scummvm-devel@lists.sf.net\n" -"POT-Creation-Date: 2016-04-07 08:55+0100\n" -"PO-Revision-Date: 2016-04-10 11:00+0100\n" +"POT-Creation-Date: 2016-04-07 08:55+0200\n" +"PO-Revision-Date: 2016-05-01 15:45+0200\n"  "Last-Translator: Lothar Serra Mari <rootfather@scummvm.org>\n"  "Language-Team: Simon Sawatzki <SimSaw@gmx.de>, Lothar Serra Mari "  "<rootfather@scummvm.org>\n" @@ -978,7 +978,7 @@ msgstr "Musiklautstärke:"  #: gui/options.cpp:970  msgid "Mute All" -msgstr "Alles aus" +msgstr "Stumm"  #: gui/options.cpp:973  msgid "SFX volume:" @@ -2967,7 +2967,7 @@ msgstr "Objektzeile zeigen"  #: engines/scumm/detection.cpp:1336  msgid "Show the names of objects at the bottom of the screen" -msgstr "Die Objektzeile wird während des Spiels im unteren Bildbereich eingeblendet" +msgstr "Objektnamen und Verben am unteren Bildrand anzeigen"  #: engines/scumm/dialogs.cpp:176  #, c-format diff --git a/po/hu_HU.po b/po/hu_HU.po index 1033063868..1033063868 100755..100644 --- a/po/hu_HU.po +++ b/po/hu_HU.po | 
