diff options
171 files changed, 3561 insertions, 1687 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. @@ -835,7 +835,7 @@ then consult: <http://wiki.scummvm.org/index.php/HOWTO-Mac_Games> Although it primarily talks about SCUMM games, it mentions the -"HFVExplorer" utility which you need to extract the files. Note that you +"HFSExplorer" utility which you need to extract the files. Note that you have to put the speech data "Inherit the Earth Voices" in the same directory as the game data which is stored in: @@ -1205,7 +1205,7 @@ a Macintosh for this, accessing the CD/floppy data might be tricky. The reason for this is that the mac uses a special disk format called HFS which other systems usually do not support. However, there are various free tools which allow reading such HFS volumes. For example -"HFVExplorer" for Windows and "hfsutils" for Linux and other Unix-like +"HFSExplorer" for Windows and "hfsutils" for Linux and other Unix-like operating systems. Most of the newer games on the Macintosh shipped with only a single data @@ -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/decoders/aiff.cpp b/audio/decoders/aiff.cpp index e1949ebb07..253b36dec0 100644 --- a/audio/decoders/aiff.cpp +++ b/audio/decoders/aiff.cpp @@ -129,6 +129,8 @@ RewindableAudioStream *makeAIFFStream(Common::SeekableReadStream *stream, Dispos foundSSND = true; /* uint32 offset = */ stream->readUint32BE(); /* uint32 blockAlign = */ stream->readUint32BE(); + if (dataStream) + delete dataStream; dataStream = new Common::SeekableSubReadStream(stream, stream->pos(), stream->pos() + length - 8, disposeAfterUse); break; case MKTAG('F', 'V', 'E', 'R'): @@ -154,7 +156,7 @@ RewindableAudioStream *makeAIFFStream(Common::SeekableReadStream *stream, Dispos return 0; default: debug(1, "Skipping AIFF '%s' chunk", tag2str(tag)); - break; + break; } stream->seek(pos + length + (length & 1)); // ensure we're also word-aligned @@ -203,7 +205,7 @@ RewindableAudioStream *makeAIFFStream(Common::SeekableReadStream *stream, Dispos if (codec == MKTAG('s', 'o', 'w', 't')) rawFlags |= Audio::FLAG_LITTLE_ENDIAN; - return makeRawStream(dataStream, rate, rawFlags); + return makeRawStream(dataStream, rate, rawFlags); } case MKTAG('i', 'm', 'a', '4'): // TODO: Use QT IMA ADPCM @@ -212,7 +214,7 @@ RewindableAudioStream *makeAIFFStream(Common::SeekableReadStream *stream, Dispos case MKTAG('Q', 'D', 'M', '2'): // TODO: Need to figure out how to integrate this // (But hopefully never needed) - warning("Unhandled AIFF-C QDM2 compression"); + warning("Unhandled AIFF-C QDM2 compression"); break; case MKTAG('A', 'D', 'P', '4'): // ADP4 on 3DO 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/backends/platform/sdl/amigaos/amigaos-main.cpp b/backends/platform/sdl/amigaos/amigaos-main.cpp index 65da6bbf85..7bbf8d1fff 100644 --- a/backends/platform/sdl/amigaos/amigaos-main.cpp +++ b/backends/platform/sdl/amigaos/amigaos-main.cpp @@ -24,13 +24,44 @@ #if defined(__amigaos4__) +#include "backends/fs/amigaos4/amigaos4-fs.h" #include "backends/platform/sdl/amigaos/amigaos.h" #include "backends/plugins/sdl/sdl-provider.h" #include "base/main.h" int main(int argc, char *argv[]) { - // Set up a stack cookie to avoid crashes due to too few stack set by users + // The following will gather the application name and add the install path + // to a variable in AmigaOS4's ENV(ARC) system. It will be placed in AppPaths + // so that ScummVM can become AmiUpdate aware + const char *const appname = "ScummVM"; + + BPTR lock; + APTR oldwin; + + // Obtain a lock to the home directory + if ((lock = IDOS->GetProgramDir())) { + TEXT progpath[2048]; + TEXT apppath[1024] = "AppPaths"; + + if (IDOS->DevNameFromLock(lock, + progpath, + sizeof(progpath), + DN_FULLPATH)) { + + // Stop any "Insert volume..." type requesters + oldwin = IDOS->SetProcWindow((APTR)-1); + + // Finally, set the variable to the path the executable was run from + IDOS->AddPart( apppath, appname, 1024); + IDOS->SetVar( apppath, progpath, -1, GVF_GLOBAL_ONLY|GVF_SAVE_VAR ); + + // Turn system requesters back on + IDOS->SetProcWindow( oldwin ); + } + } + + // Set up a stack cookie to avoid crashes from a stack set too low static const char *stack_cookie __attribute__((used)) = "$STACK: 600000"; // Create our OSystem instance @@ -44,7 +75,7 @@ int main(int argc, char *argv[]) { PluginManager::instance().addPluginProvider(new SDLPluginProvider()); #endif - // Invoke the actual ScummVM main entry point: + // Invoke the actual ScummVM main entry point int res = scummvm_main(argc, argv); // Free OSystem 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..517f3f5638 100755 --- a/devtools/create_wage/create_wage.sh +++ b/devtools/create_classicmacfonts.sh @@ -4,7 +4,7 @@ # from it. Mac only, unfortunately. # # On Windows you perhaps can perform the extraction manually with use of -# HFV Explorer: https://web.archive.org/web/20011202005455/http://gamma.nic.fi/~lpesonen/HFVExplorer/ +# HFSxplorer: http://www.catacombae.org/hfsexplorer/ # # More information could be found in the vMac documentation: http://www.gryphel.com/c/image/ # @@ -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/create_kyradat/create_kyradat.cpp b/devtools/create_kyradat/create_kyradat.cpp index e064e899de..294eadf92b 100644 --- a/devtools/create_kyradat/create_kyradat.cpp +++ b/devtools/create_kyradat/create_kyradat.cpp @@ -45,7 +45,7 @@ enum { - kKyraDatVersion = 87 + kKyraDatVersion = 88 }; const ExtractFilename extractFilenames[] = { @@ -119,7 +119,6 @@ const ExtractFilename extractFilenames[] = { // AUDIO filename table { k1AudioTracks, kStringList, false }, - { k1AudioTracks2, kStringList, false }, { k1AudioTracksIntro, kStringList, false }, // AMULET anim diff --git a/devtools/create_kyradat/create_kyradat.h b/devtools/create_kyradat/create_kyradat.h index a6bee6f75c..1d58d7551f 100644 --- a/devtools/create_kyradat/create_kyradat.h +++ b/devtools/create_kyradat/create_kyradat.h @@ -131,7 +131,6 @@ enum kExtractID { k1ConfigStrings, k1AudioTracks, - k1AudioTracks2, k1AudioTracksIntro, k1CreditsStrings, diff --git a/devtools/create_kyradat/games.cpp b/devtools/create_kyradat/games.cpp index afe0c67dbf..e6f0b38c45 100644 --- a/devtools/create_kyradat/games.cpp +++ b/devtools/create_kyradat/games.cpp @@ -231,7 +231,6 @@ const int kyra1FloppyNeed[] = { k1NewGameString, k1ConfigStrings, k1AudioTracks, - k1AudioTracks2, k1AudioTracksIntro, -1 }; @@ -317,7 +316,6 @@ const int kyra1FloppyOldNeed[] = { k1NewGameString, k1ConfigStrings, k1AudioTracks, - k1AudioTracks2, k1AudioTracksIntro, -1 }; @@ -405,7 +403,6 @@ const int kyra1CDNeed[] = { k1NewGameString, k1ConfigStrings, k1AudioTracks, - k1AudioTracks2, k1AudioTracksIntro, -1 }; diff --git a/devtools/create_kyradat/resources.cpp b/devtools/create_kyradat/resources.cpp index 4df6bb8fb8..246811f821 100644 --- a/devtools/create_kyradat/resources.cpp +++ b/devtools/create_kyradat/resources.cpp @@ -302,7 +302,6 @@ static const ResourceProvider resourceProviders[] = { { k1NewGameString, kKyra1, kPlatformDOS, kNoSpecial, EN_ANY, &k1NewGameStringDOSEnglishProvider }, { k1ConfigStrings, kKyra1, kPlatformDOS, kNoSpecial, EN_ANY, &k1ConfigStringsDOSEnglishProvider }, { k1AudioTracks, kKyra1, kPlatformDOS, kNoSpecial, UNK_LANG, &k1AudioTracksDOSProvider }, - { k1AudioTracks2, kKyra1, kPlatformDOS, kNoSpecial, UNK_LANG, &k1AudioTracks2DOSProvider }, { k1AudioTracksIntro, kKyra1, kPlatformDOS, kNoSpecial, UNK_LANG, &k1AudioTracksIntroDOSProvider }, { k1IntroStrings, kKyra1, kPlatformDOS, kNoSpecial, DE_DEU, &k1IntroStringsDOSGermanProvider }, { k1ItemNames, kKyra1, kPlatformDOS, kNoSpecial, DE_DEU, &k1ItemNamesDOSGermanProvider }, @@ -472,7 +471,6 @@ static const ResourceProvider resourceProviders[] = { { k1NewGameString, kKyra1, kPlatformDOS, kOldFloppy, RU_RUS, &k1NewGameStringDOSOldFloppyRussianProvider }, { k1ConfigStrings, kKyra1, kPlatformDOS, kOldFloppy, RU_RUS, &k1ConfigStringsDOSOldFloppyRussianProvider }, { k1AudioTracks, kKyra1, kPlatformDOS, kOldFloppy, UNK_LANG, &k1AudioTracksDOSOldFloppyProvider }, - { k1AudioTracks2, kKyra1, kPlatformDOS, kOldFloppy, UNK_LANG, &k1AudioTracks2DOSOldFloppyProvider }, { k1AudioTracksIntro, kKyra1, kPlatformDOS, kOldFloppy, UNK_LANG, &k1AudioTracksIntroDOSOldFloppyProvider }, { k1KallakWritingSeq, kKyra1, kPlatformDOS, kTalkieVersion, UNK_LANG, &k1KallakWritingSeqDOSCDProvider }, { k1MalcolmTreeSeq, kKyra1, kPlatformDOS, kTalkieVersion, UNK_LANG, &k1MalcolmTreeSeqDOSCDProvider }, @@ -556,7 +554,6 @@ static const ResourceProvider resourceProviders[] = { { k1NewGameString, kKyra1, kPlatformDOS, kTalkieVersion, EN_ANY, &k1NewGameStringDOSCDEnglishProvider }, { k1ConfigStrings, kKyra1, kPlatformDOS, kTalkieVersion, EN_ANY, &k1ConfigStringsDOSCDEnglishProvider }, { k1AudioTracks, kKyra1, kPlatformDOS, kTalkieVersion, UNK_LANG, &k1AudioTracksDOSCDProvider }, - { k1AudioTracks2, kKyra1, kPlatformDOS, kTalkieVersion, UNK_LANG, &k1AudioTracks2DOSCDProvider }, { k1AudioTracksIntro, kKyra1, kPlatformDOS, kTalkieVersion, UNK_LANG, &k1AudioTracksIntroDOSCDProvider }, { k1IntroStrings, kKyra1, kPlatformDOS, kTalkieVersion, DE_DEU, &k1IntroStringsDOSCDGermanProvider }, { k1ItemNames, kKyra1, kPlatformDOS, kTalkieVersion, DE_DEU, &k1ItemNamesDOSCDGermanProvider }, diff --git a/devtools/create_kyradat/resources/lok_dos.h b/devtools/create_kyradat/resources/lok_dos.h index e8d987fe1b..6bc9c2525f 100644 --- a/devtools/create_kyradat/resources/lok_dos.h +++ b/devtools/create_kyradat/resources/lok_dos.h @@ -1898,7 +1898,7 @@ static const byte k1OutroReunionSeqDOS[1351] = { static const ByteProvider k1OutroReunionSeqDOSProvider = { ARRAYSIZE(k1OutroReunionSeqDOS), k1OutroReunionSeqDOS }; -static const char *const k1AudioTracksDOS[8] = { +static const char *const k1AudioTracksDOS[9] = { "KYRA1A", "KYRA1B", "KYRA2A", @@ -1906,17 +1906,12 @@ static const char *const k1AudioTracksDOS[8] = { "KYRA4A", "KYRA4B", "KYRA5A", - "KYRA5B" + "KYRA5B", + "KYRAMISC" }; static const StringListProvider k1AudioTracksDOSProvider = { ARRAYSIZE(k1AudioTracksDOS), k1AudioTracksDOS }; -static const char *const k1AudioTracks2DOS[1] = { - "kyramisc" -}; - -static const StringListProvider k1AudioTracks2DOSProvider = { ARRAYSIZE(k1AudioTracks2DOS), k1AudioTracks2DOS }; - static const char *const k1AudioTracksIntroDOS[1] = { "intro" }; diff --git a/devtools/create_kyradat/resources/lok_dos_cd.h b/devtools/create_kyradat/resources/lok_dos_cd.h index 9550d53d61..dc7a521063 100644 --- a/devtools/create_kyradat/resources/lok_dos_cd.h +++ b/devtools/create_kyradat/resources/lok_dos_cd.h @@ -1969,7 +1969,7 @@ static const byte k1OutroReunionSeqDOSCD[1509] = { static const ByteProvider k1OutroReunionSeqDOSCDProvider = { ARRAYSIZE(k1OutroReunionSeqDOSCD), k1OutroReunionSeqDOSCD }; -static const char *const k1AudioTracksDOSCD[8] = { +static const char *const k1AudioTracksDOSCD[9] = { "KYRA1A", "KYRA1B", "KYRA2A", @@ -1977,17 +1977,12 @@ static const char *const k1AudioTracksDOSCD[8] = { "KYRA4A", "KYRA4B", "KYRA5A", - "KYRA5B" + "KYRA5B", + "KYRAMISC" }; static const StringListProvider k1AudioTracksDOSCDProvider = { ARRAYSIZE(k1AudioTracksDOSCD), k1AudioTracksDOSCD }; -static const char *const k1AudioTracks2DOSCD[1] = { - "kyramisc" -}; - -static const StringListProvider k1AudioTracks2DOSCDProvider = { ARRAYSIZE(k1AudioTracks2DOSCD), k1AudioTracks2DOSCD }; - static const char *const k1AudioTracksIntroDOSCD[2] = { "intro", "intro" diff --git a/devtools/create_kyradat/resources/lok_dos_oldfloppy.h b/devtools/create_kyradat/resources/lok_dos_oldfloppy.h index e19cb5a6ef..62b1530941 100644 --- a/devtools/create_kyradat/resources/lok_dos_oldfloppy.h +++ b/devtools/create_kyradat/resources/lok_dos_oldfloppy.h @@ -1884,7 +1884,7 @@ static const byte k1OutroReunionSeqDOSOldFloppy[1351] = { static const ByteProvider k1OutroReunionSeqDOSOldFloppyProvider = { ARRAYSIZE(k1OutroReunionSeqDOSOldFloppy), k1OutroReunionSeqDOSOldFloppy }; -static const char *const k1AudioTracksDOSOldFloppy[8] = { +static const char *const k1AudioTracksDOSOldFloppy[9] = { "KYRA1A", "KYRA1B", "KYRA2A", @@ -1892,17 +1892,12 @@ static const char *const k1AudioTracksDOSOldFloppy[8] = { "KYRA4A", "KYRA4B", "KYRA5A", - "KYRA5B" + "KYRA5B", + "KYRAMISC" }; static const StringListProvider k1AudioTracksDOSOldFloppyProvider = { ARRAYSIZE(k1AudioTracksDOSOldFloppy), k1AudioTracksDOSOldFloppy }; -static const char *const k1AudioTracks2DOSOldFloppy[1] = { - "kyramisc" -}; - -static const StringListProvider k1AudioTracks2DOSOldFloppyProvider = { ARRAYSIZE(k1AudioTracks2DOSOldFloppy), k1AudioTracks2DOSOldFloppy }; - static const char *const k1AudioTracksIntroDOSOldFloppy[1] = { "intro" }; 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/dists/engine-data/kyra.dat b/dists/engine-data/kyra.dat Binary files differindex 1b42cfbadc..d49d107f6f 100644 --- a/dists/engine-data/kyra.dat +++ b/dists/engine-data/kyra.dat diff --git a/doc/cz/PrectiMe b/doc/cz/PrectiMe index 3c03db9802..030ddac916 100644 --- a/doc/cz/PrectiMe +++ b/doc/cz/PrectiMe @@ -651,7 +651,7 @@ Abyste mohli spustit verzi pro Mac OS X od Wyrmkeep musÃte data zkopÃrovat z <http://wiki.scummvm.org/index.php/HOWTO-Mac_Games>
-I když se v tomto Älánku pÃÅ¡e hlavnÄ› o hrách SCUMM, je zde také zmÃnÄ›n nástroj "HFVExplorer", který potÅ™ebujete k extrakci souborů. Nezapomeňte, že data Å™eÄi "Inherit the Earth Voices" musÃte umÃstit do stejného adresáře, kde jsou uložena data hry:
+I když se v tomto Älánku pÃÅ¡e hlavnÄ› o hrách SCUMM, je zde také zmÃnÄ›n nástroj "HFSExplorer", který potÅ™ebujete k extrakci souborů. Nezapomeňte, že data Å™eÄi "Inherit the Earth Voices" musÃte umÃstit do stejného adresáře, kde jsou uložena data hry:
Inherit the Earth.app/Contents/Resources
@@ -915,7 +915,7 @@ Nebo můžete použÃt 'extract_mm_c64' z balÃÄku nástrojů pro extrahovánà 3.26) Poznámky ke hrám Macintosh:
----- ---------------------------
-VÅ¡echny adventury LucasArts založené na SCUMM, kromÄ› COMI, také existujà ve verzÃch pro in Macintosh. ScummVM může vÄ›tÅ¡inu (vÅ¡echny?) použÃt, nicménÄ›, v nÄ›kterých pÅ™Ãpadech je nutná dodateÄná práce. NejdÅ™Ãve, pokud pro toto nepoužÃváte Macintosh, pÅ™Ãstup k datům na CD/disketÄ› může být obtÞný. Důvodem je to, že Mac použÃvá zvláštnà formát disku nazvaný HFS, který ostatnà systémy vÄ›tÅ¡inou nepodporujÃ. NicménÄ› existuje, nÄ›kolik nástrojů, které jsou zadarmo a umožňujà ÄÃst takovéto svazky HFS. NapÅ™Ãklad "HFVExplorer" pro Windows a "hfsutils" pro Linux a ostatnà Unixové operaÄnà systémy.
+VÅ¡echny adventury LucasArts založené na SCUMM, kromÄ› COMI, také existujà ve verzÃch pro in Macintosh. ScummVM může vÄ›tÅ¡inu (vÅ¡echny?) použÃt, nicménÄ›, v nÄ›kterých pÅ™Ãpadech je nutná dodateÄná práce. NejdÅ™Ãve, pokud pro toto nepoužÃváte Macintosh, pÅ™Ãstup k datům na CD/disketÄ› může být obtÞný. Důvodem je to, že Mac použÃvá zvláštnà formát disku nazvaný HFS, který ostatnà systémy vÄ›tÅ¡inou nepodporujÃ. NicménÄ› existuje, nÄ›kolik nástrojů, které jsou zadarmo a umožňujà ÄÃst takovéto svazky HFS. NapÅ™Ãklad "HFSExplorer" pro Windows a "hfsutils" pro Linux a ostatnà Unixové operaÄnà systémy.
VÄ›tÅ¡ina novÄ›jÅ¡Ãch her na Macintosh je dodávána pouze s jednÃm datovým souborem (v nÄ›kterých pÅ™Ãpadech byl tento soubor uÄinÄ›n neviditelným, takže možná budete potÅ™ebovat dodateÄné nástroje, abyste ho mohli zkopÃrovat). ScummVM je schopen takovýto soubor použÃt pÅ™Ãmo; jednoduÅ¡e odkažte ScummVM na složku obsahujÃcà tento soubor a mÄ›lo by to fungovat (tak jako s každou podporovanou hrou).
diff --git a/doc/de/Liesmich b/doc/de/Liesmich index f37fc7d396..84eb6b53fd 100644 --- a/doc/de/Liesmich +++ b/doc/de/Liesmich @@ -878,7 +878,7 @@ einem PC arbeiten, lesen Sie hierfür: http://wiki.scummvm.org/index.php/HOWTO-Mac_Games Obwohl hier in erster Linie über SCUMM-Spiele gesprochen wird, findet das -Dienstprogramm „HFVExplorer“ Erwähnung, welches Sie benötigen, um die Dateien zu +Dienstprogramm „HFSExplorer“ Erwähnung, welches Sie benötigen, um die Dateien zu extrahieren. Beachten Sie, dass Sie die Sprachausgabedaten aus „Inherit the Earth Voices“ im selben Verzeichnis ablegen müssen wie die Spieldaten, die sich an folgendem Ort befinden: @@ -1280,7 +1280,7 @@ kompliziert werden, auf die CD- oder Diskettendaten zuzugreifen. Der Grund hierfür ist, dass der Mac ein spezielles Datenträgerformat nutzt, welches sich HFS nennt, und das andere Systeme normalerweise nicht unterstützen. Es gibt jedoch zahlreiche kostenlose Tools, die es ermöglichen, einen solchen -HFS-Datenträger zu lesen. Z. B. „HFVExplorer“ für Windows und „hfsutils“ für +HFS-Datenträger zu lesen. Z. B. „HFSExplorer“ für Windows und „hfsutils“ für Linux und andere Betriebssysteme, die Unix ähnlich sind. Die meisten neueren Spiele für den Macintosh wurden nur mit einer einzigen 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/access/amazon/amazon_logic.cpp b/engines/access/amazon/amazon_logic.cpp index e78f92cda7..08006fe1b7 100644 --- a/engines/access/amazon/amazon_logic.cpp +++ b/engines/access/amazon/amazon_logic.cpp @@ -185,16 +185,24 @@ void CampScene::mWhileDoOpen() { _vm->_numAnimTimers = 0; _vm->_images.clear(); - if (_vm->_conversation == 2) { - // Cutscene at end of Chapter 6 - Resource *spriteData = _vm->_files->loadFile(28, 37); - _vm->_objectsTable[28] = new SpriteResource(_vm, spriteData); - delete spriteData; - - _vm->_animation->freeAnimationData(); - animResource = _vm->_files->loadFile(28, 38); - _vm->_animation->loadAnimations(animResource); - delete animResource; + if (_vm->isCD()) { + if (_vm->_conversation == 2) { + // Cutscene at end of Chapter 6 + Resource *spriteData = _vm->_files->loadFile(28, 37); + _vm->_objectsTable[28] = new SpriteResource(_vm, spriteData); + delete spriteData; + + _vm->_animation->freeAnimationData(); + animResource = _vm->_files->loadFile(28, 38); + _vm->_animation->loadAnimations(animResource); + delete animResource; + } + } else { + _vm->freeCells(); + _vm->_oldRects.clear(); + _vm->_newRects.clear(); + _vm->_numAnimTimers = 0; + _vm->_images.clear(); } } diff --git a/engines/access/bubble_box.cpp b/engines/access/bubble_box.cpp index ef32e96f59..89c5d0727d 100644 --- a/engines/access/bubble_box.cpp +++ b/engines/access/bubble_box.cpp @@ -165,7 +165,7 @@ void BubbleBox::printBubble(const Common::String &msg) { void BubbleBox::printBubble_v1(const Common::String &msg) { drawBubble(_bubbles.size() - 1); - + // Loop through drawing the lines Common::String s = msg; Common::String line; @@ -369,7 +369,7 @@ void BubbleBox::displayBoxData() { _vm->_screen->drawRect(); _vm->_events->showCursor(); } - + _vm->_events->hideCursor(); int oldPStartY = _boxPStartY; ++_boxPStartY; @@ -474,7 +474,7 @@ int BubbleBox::doBox_v1(int item, int box, int &btnSelected) { --_vm->_screen->_orgX2; --_vm->_screen->_orgY2; _vm->_screen->_lColor = 0xF9; - + // Draw the inner border _vm->_screen->drawBox(); @@ -642,7 +642,9 @@ int BubbleBox::doBox_v1(int item, int box, int &btnSelected) { } } } - + + delete icons; + _vm->_screen->restoreScreen(); _vm->_boxDataStart = _startItem; _vm->_boxSelectYOld = -1; @@ -732,7 +734,7 @@ int BubbleBox::doBox_v1(int item, int box, int &btnSelected) { if (_type != TYPE_3) continue; - + if ((_vm->_events->_mousePos.x < tmpX) || (_vm->_events->_mousePos.x > tmpX + 144)) continue; diff --git a/engines/access/char.cpp b/engines/access/char.cpp index cbe1d5d3d9..f6d3033b1b 100644 --- a/engines/access/char.cpp +++ b/engines/access/char.cpp @@ -44,7 +44,7 @@ CharEntry::CharEntry(const byte *data, AccessEngine *vm) { if (vm->getGameID() == GType_MartianMemorandum) { int lastColor = s.readUint16LE(); _numColors = lastColor - _startColor; - } else + } else _numColors = s.readUint16LE(); // Load cells @@ -131,6 +131,7 @@ void CharManager::loadChar(int charId) { if (ce._animFile._fileNum != -1) { Resource *data = _vm->_files->loadFile(ce._animFile); _vm->_animation->loadAnimations(data); + delete data; } // Load script data diff --git a/engines/access/inventory.cpp b/engines/access/inventory.cpp index 0a962aa69a..e9874cd8d6 100644 --- a/engines/access/inventory.cpp +++ b/engines/access/inventory.cpp @@ -223,6 +223,7 @@ int InventoryManager::displayInv() { else _vm->_useItem = -1; + free(names); free(inv); return 0; } diff --git a/engines/access/room.cpp b/engines/access/room.cpp index a7192d330f..a41de63bf6 100644 --- a/engines/access/room.cpp +++ b/engines/access/room.cpp @@ -142,7 +142,7 @@ void Room::takePicture() { _vm->_player->_roomNumber = 7; _vm->_room->_function = FN_CLEAR1; return; - } else if (result >= 0) + } else if (result >= 0) _vm->_player->_move = (Direction)(result + 1); _vm->_player->_scrollFlag = false; @@ -715,6 +715,8 @@ void Room::executeCommand(int commandId) { screen.plotImage(spr, _selectCommand + 2, Common::Point(_rMouse[_selectCommand][0], (_vm->getGameID() == GType_MartianMemorandum) ? 184 : 176)); + delete spr; + _vm->_screen->restoreScreen(); _vm->_boxSelect = true; } 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/agi/op_cmd.cpp b/engines/agi/op_cmd.cpp index fed07ea986..8a62fce86c 100644 --- a/engines/agi/op_cmd.cpp +++ b/engines/agi/op_cmd.cpp @@ -662,7 +662,7 @@ void cmdWordToString(AgiGame *state, AgiEngine *vm, uint8 *parameter) { uint16 stringNr = parameter[0]; uint16 wordNr = parameter[1]; - strcpy(state->strings[stringNr], state->_vm->_words->getEgoWord(wordNr)); + Common::strlcpy(state->strings[stringNr], state->_vm->_words->getEgoWord(wordNr), MAX_STRINGLEN); } void cmdOpenDialogue(AgiGame *state, AgiEngine *vm, uint8 *parameter) { @@ -2014,7 +2014,7 @@ void cmdGetString(AgiGame *state, AgiEngine *vm, uint8 *parameter) { // copy string to destination // TODO: not sure if set all the time or only when ENTER is pressed - strcpy(&state->_vm->_game.strings[stringDestNr][0], (char *)textMgr->_inputString); + Common::strlcpy(&state->_vm->_game.strings[stringDestNr][0], (char *)textMgr->_inputString, MAX_STRINGLEN); textMgr->charPos_Pop(); @@ -2102,7 +2102,7 @@ void cmdSetString(AgiGame *state, AgiEngine *vm, uint8 *parameter) { // CM: to avoid crash in Groza (str = 150) if (stringNr > MAX_STRINGS) return; - strcpy(state->strings[stringNr], state->_curLogic->texts[textNr]); + Common::strlcpy(state->strings[stringNr], state->_curLogic->texts[textNr], MAX_STRINGLEN); } void cmdDisplay(AgiGame *state, AgiEngine *vm, uint8 *parameter) { diff --git a/engines/agi/op_test.cpp b/engines/agi/op_test.cpp index 4b215edc63..4505668fd1 100644 --- a/engines/agi/op_test.cpp +++ b/engines/agi/op_test.cpp @@ -231,8 +231,8 @@ uint8 AgiEngine::testCompareStrings(uint8 s1, uint8 s2) { char ms2[MAX_STRINGLEN]; int j, k, l; - strcpy(ms1, _game.strings[s1]); - strcpy(ms2, _game.strings[s2]); + Common::strlcpy(ms1, _game.strings[s1], MAX_STRINGLEN); + Common::strlcpy(ms2, _game.strings[s2], MAX_STRINGLEN); l = strlen(ms1); for (k = 0, j = 0; k < l; k++) { diff --git a/engines/agi/preagi_mickey.cpp b/engines/agi/preagi_mickey.cpp index 620d5e0baf..e1545cdb68 100644 --- a/engines/agi/preagi_mickey.cpp +++ b/engines/agi/preagi_mickey.cpp @@ -1205,7 +1205,7 @@ void MickeyEngine::printStory() { clearScreen(IDA_DEFAULT); for (iRow = 0; iRow < 25; iRow++) { - strcpy(szLine, buffer + pBuf); + Common::strlcpy(szLine, buffer + pBuf, 41); drawStr(iRow, 0, IDA_DEFAULT, szLine); pBuf += strlen(szLine) + 1; } @@ -1213,7 +1213,7 @@ void MickeyEngine::printStory() { clearScreen(IDA_DEFAULT); for (iRow = 0; iRow < 21; iRow++) { - strcpy(szLine, buffer + pBuf); + Common::strlcpy(szLine, buffer + pBuf, 41); drawStr(iRow, 0, IDA_DEFAULT, szLine); pBuf += strlen(szLine) + 1; } diff --git a/engines/agi/preagi_winnie.cpp b/engines/agi/preagi_winnie.cpp index 87ac7c19c6..8fb9daca5e 100644 --- a/engines/agi/preagi_winnie.cpp +++ b/engines/agi/preagi_winnie.cpp @@ -292,7 +292,7 @@ int WinnieEngine::parser(int pc, int index, uint8 *buffer) { } // extract menu string - strcpy(szMenu, (char *)(buffer + pc)); + Common::strlcpy(szMenu, (char *)(buffer + pc), 121); XOR80(szMenu); break; default: diff --git a/engines/agi/saveload.cpp b/engines/agi/saveload.cpp index 0658609cd0..09fce9320b 100644 --- a/engines/agi/saveload.cpp +++ b/engines/agi/saveload.cpp @@ -118,7 +118,7 @@ int AgiEngine::saveGame(const Common::String &fileName, const Common::String &de out->writeByte(2); // was _game.state, 2 = STATE_RUNNING - strcpy(gameIDstring, _game.id); + Common::strlcpy(gameIDstring, _game.id, 8); out->write(gameIDstring, 8); debugC(5, kDebugLevelMain | kDebugLevelSavegame, "Writing game id (%s, %s)", gameIDstring, _game.id); diff --git a/engines/agi/text.cpp b/engines/agi/text.cpp index 110ba10632..274a654547 100644 --- a/engines/agi/text.cpp +++ b/engines/agi/text.cpp @@ -457,7 +457,7 @@ void TextMgr::drawMessageBox(const char *textPtr, int16 forcedHeight, int16 want // Caller wants to force specified width/height? set it if (forcedHeight) _messageState.textSize_Height = forcedHeight; - + if (forcedWidth) { if (wantedWidth) _messageState.textSize_Width = wantedWidth; @@ -1207,7 +1207,7 @@ char *TextMgr::stringPrintf(const char *originalText) { } assert(resultString.size() < sizeof(resultPrintfBuffer)); - strcpy(resultPrintfBuffer, resultString.c_str()); + Common::strlcpy(resultPrintfBuffer, resultString.c_str(), 2000); return resultPrintfBuffer; } 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/agos/string.cpp b/engines/agos/string.cpp index 4f6c62c48a..cc443f2f50 100644 --- a/engines/agos/string.cpp +++ b/engines/agos/string.cpp @@ -126,14 +126,14 @@ const byte *AGOSEngine::getStringPtrByID(uint16 stringId, bool upperCase) { _awaitTwoByteToken = 0; uncompressText(ptr); _textBuffer[_textCount] = 0; - strcpy((char *)dst, (const char *)_textBuffer); + Common::strlcpy((char *)dst, (const char *)_textBuffer, 180); } else { if (stringId < 0x8000) { stringPtr = _stringTabPtr[stringId]; } else { stringPtr = getLocalStringByID(stringId); } - strcpy((char *)dst, (const char *)stringPtr); + Common::strlcpy((char *)dst, (const char *)stringPtr, 180); } // WORKAROUND bug #1538873: The French version of Simon 1 and the @@ -796,7 +796,7 @@ void AGOSEngine_Feeble::printInteractText(uint16 num, const char *string) { if (*string2 == 0x00) { if (w == 0xFFFF) w = pixels; - strcpy(convertedString2, string); + Common::strlcpy(convertedString2, string, 320); break; } while (*string2 != ' ') { diff --git a/engines/agos/string_pn.cpp b/engines/agos/string_pn.cpp index 7a364f3ea9..06c8bbd98e 100644 --- a/engines/agos/string_pn.cpp +++ b/engines/agos/string_pn.cpp @@ -114,7 +114,7 @@ void AGOSEngine_PN::getObjectName(char *v, uint16 x) { } void AGOSEngine_PN::pcl(const char *s) { - strcat(_sb, s); + Common::strlcat(_sb, s, 80); if (strchr(s, '\n') == 0) { for (char *str = _sb; *str; str++) windowPutChar(_windowArray[_curWindow], *str); 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/ctp.cpp b/engines/cruise/ctp.cpp index 9515b552e1..4458e39e91 100644 --- a/engines/cruise/ctp.cpp +++ b/engines/cruise/ctp.cpp @@ -307,7 +307,7 @@ int initCt(const char *ctpName) { MemFree(ptr); if (ctpName != currentCtpName) - strcpy(currentCtpName, ctpName); + Common::strlcpy(currentCtpName, ctpName, 40); numberOfWalkboxes = segementSizeTable[6] / 2; // get the number of walkboxes 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/motion.cpp b/engines/fullpipe/motion.cpp index 1a61cb742a..9cf18f3cc2 100644 --- a/engines/fullpipe/motion.cpp +++ b/engines/fullpipe/motion.cpp @@ -855,9 +855,9 @@ Common::Array<MovItem *> *MovGraph::getPaths(StaticANIObject *ani, int x, int y, if (sz > 0) { for (int j = 0; j < sz; j++) _items[idx]->movitems->push_back(movitems[j]); - - delete movitems; } + + delete movitems; } delete movarr; 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/kyra/kyra_v2.cpp b/engines/kyra/kyra_v2.cpp index 925dcf7bfe..106420d9c2 100644 --- a/engines/kyra/kyra_v2.cpp +++ b/engines/kyra/kyra_v2.cpp @@ -46,6 +46,8 @@ KyraEngine_v2::KyraEngine_v2(OSystem *system, const GameFlags &flags, const Engi memset(&_sceneScriptState, 0, sizeof(_sceneScriptState)); memset(&_sceneScriptData, 0, sizeof(_sceneScriptData)); + Common::fill(_sceneSpecialScriptsTimer, ARRAYEND(_sceneSpecialScriptsTimer), 0); + _animObjects = 0; _runFlag = true; diff --git a/engines/kyra/resource.h b/engines/kyra/resource.h index 3ab08a4c7c..c3ebf6e5fe 100644 --- a/engines/kyra/resource.h +++ b/engines/kyra/resource.h @@ -203,7 +203,6 @@ enum KyraResources { k1ConfigStrings, k1AudioTracks, - k1AudioTracks2, k1AudioTracksIntro, k1CreditsStrings, diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp index 1a2e2c093c..e99321ddcb 100644 --- a/engines/kyra/staticres.cpp +++ b/engines/kyra/staticres.cpp @@ -39,7 +39,7 @@ namespace Kyra { -#define RESFILE_VERSION 87 +#define RESFILE_VERSION 88 namespace { bool checkKyraDat(Common::SeekableReadStream *file) { @@ -805,19 +805,11 @@ void KyraEngine_LoK::initStaticResource() { } // audio resource assignment - int size1, size2; - const char *const *soundfiles1 = _staticres->loadStrings(k1AudioTracks, size1); - const char *const *soundfiles2 = _staticres->loadStrings(k1AudioTracks2, size2); - int soundFilesSize = size1 + size2; + int soundFilesSize; + const char *const *soundFiles = _staticres->loadStrings(k1AudioTracks, soundFilesSize); int soundFilesIntroSize = 0; int cdaTableSize = 0; - const char **soundFiles = 0; - if (soundFilesSize) { - soundFiles = new const char*[soundFilesSize]; - for (int i = 0; i < soundFilesSize; i++) - soundFiles[i] = (i < size1) ? soundfiles1[i] : soundfiles2[i - size1]; - } const char *const *soundFilesIntro = _staticres->loadStrings(k1AudioTracksIntro, soundFilesIntroSize); const int32 *cdaTable = (const int32 *)_staticres->loadRawData(k1TownsCDATable, cdaTableSize); diff --git a/engines/lastexpress/entities/gendarmes.cpp b/engines/lastexpress/entities/gendarmes.cpp index b628b8dfe7..1b51dd2006 100644 --- a/engines/lastexpress/entities/gendarmes.cpp +++ b/engines/lastexpress/entities/gendarmes.cpp @@ -174,7 +174,7 @@ IMPLEMENT_FUNCTION_IISS(9, Gendarmes, doCompartment, CarIndex, EntityPosition) strcat((char *)¶meters1->seq1, (char *)¶ms->seq1); strcat((char *)¶meters1->seq2, (char *)¶ms->seq1); - strcat((char *)¶meters1->seq3, (char *)¶ms->seq1); + Common::strlcat((char *)¶meters1->seq3, (char *)¶ms->seq1, 9); // Beware, seq3 is smaller than seq1 if ((getEntities()->isInsideCompartment(kEntityPlayer, (CarIndex)params->param1, (EntityPosition)params->param2) || getEntities()->isInsideCompartment(kEntityPlayer, (CarIndex)params->param1, (EntityPosition)parameters2->param7) 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/lure/game.cpp b/engines/lure/game.cpp index 38ca0ba54f..84cc91ec9a 100644 --- a/engines/lure/game.cpp +++ b/engines/lure/game.cpp @@ -538,7 +538,7 @@ void Game::handleRightClickMenu() { hotspot = res.getHotspot(room.hotspotId()); assert(hotspot); strings.getString(hotspot->nameId, statusLine); - strcat(statusLine, stringList.getString(S_FOR)); + Common::strlcat(statusLine, stringList.getString(S_FOR), MAX_DESC_SIZE); statusLine += strlen(statusLine); itemId = PopupMenu::ShowItems(GET, player->roomNumber()); @@ -549,7 +549,7 @@ void Game::handleRightClickMenu() { hotspot = res.getHotspot(room.hotspotId()); assert(hotspot); strings.getString(hotspot->nameId, statusLine); - strcat(statusLine, stringList.getString(S_TO)); + Common::strlcat(statusLine, stringList.getString(S_TO), MAX_DESC_SIZE); breakFlag = GetTellActions(); break; @@ -559,7 +559,7 @@ void Game::handleRightClickMenu() { case DRINK: hasItems = (res.numInventoryItems() != 0); if (!hasItems) - strcat(statusLine, stringList.getString(S_ACTION_NOTHING)); + Common::strlcat(statusLine, stringList.getString(S_ACTION_NOTHING), MAX_DESC_SIZE); statusLine += strlen(statusLine); room.update(); @@ -579,9 +579,9 @@ void Game::handleRightClickMenu() { assert(useHotspot); strings.getString(useHotspot->nameId, statusLine); if (action == GIVE) - strcat(statusLine, stringList.getString(S_TO)); + Common::strlcat(statusLine, stringList.getString(S_TO), MAX_DESC_SIZE); else - strcat(statusLine, stringList.getString(S_ON)); + Common::strlcat(statusLine, stringList.getString(S_ON), MAX_DESC_SIZE); statusLine += strlen(statusLine); } else if ((action == DRINK) || (action == EXAMINE)) @@ -762,11 +762,11 @@ bool Game::GetTellActions() { // Second parameter action = (Action) commands[_numTellCommands * 3]; if (action == ASK) - strcat(statusLine, stringList.getString(S_FOR)); + Common::strlcat(statusLine, stringList.getString(S_FOR), MAX_DESC_SIZE); else if (action == GIVE) - strcat(statusLine, stringList.getString(S_TO)); + Common::strlcat(statusLine, stringList.getString(S_TO), MAX_DESC_SIZE); else if (action == USE) - strcat(statusLine, stringList.getString(S_ON)); + Common::strlcat(statusLine, stringList.getString(S_ON), MAX_DESC_SIZE); else { // All other commads don't need a second parameter ++paramIndex; diff --git a/engines/lure/hotspots.cpp b/engines/lure/hotspots.cpp index fbf93e1e14..a972909b8b 100644 --- a/engines/lure/hotspots.cpp +++ b/engines/lure/hotspots.cpp @@ -1898,8 +1898,8 @@ void Hotspot::doStatus(HotspotData *hotspot) { endAction(); strings.getString(room.roomNumber(), buffer); - strcat(buffer, "\n\n"); - strcat(buffer, stringList.getString(S_YOU_ARE_CARRYING)); + Common::strlcat(buffer, "\n\n", MAX_DESC_SIZE); + Common::strlcat(buffer, stringList.getString(S_YOU_ARE_CARRYING), MAX_DESC_SIZE); // Scan through the list and add in any items assigned to the player HotspotDataList &list = res.hotspotData(); @@ -1909,25 +1909,25 @@ void Hotspot::doStatus(HotspotData *hotspot) { if (rec.roomNumber == PLAYER_ID) { if (numItems++ == 0) - strcat(buffer, ": "); + Common::strlcat(buffer, ": ", MAX_DESC_SIZE); else - strcat(buffer, ", "); + Common::strlcat(buffer, ", ", MAX_DESC_SIZE); strings.getString(rec.nameId, buffer + strlen(buffer)); } } // If there were no items, add in the word 'nothing' if (numItems == 0) - strcat(buffer, stringList.getString(S_INV_NOTHING)); + Common::strlcat(buffer, stringList.getString(S_INV_NOTHING), MAX_DESC_SIZE); // If the player has money, add it in uint16 numGroats = res.fieldList().numGroats(); if (numGroats > 0) { - strcat(buffer, "\n\n"); - strcat(buffer, stringList.getString(S_YOU_HAVE)); - sprintf(buffer + strlen(buffer), "%d", numGroats); - strcat(buffer, " "); - strcat(buffer, stringList.getString((numGroats == 1) ? S_GROAT : S_GROATS)); + Common::strlcat(buffer, "\n\n", MAX_DESC_SIZE); + Common::strlcat(buffer, stringList.getString(S_YOU_HAVE), MAX_DESC_SIZE); + snprintf(buffer + strlen(buffer), MAX_DESC_SIZE, "%d", numGroats); + Common::strlcat(buffer, " ", MAX_DESC_SIZE); + Common::strlcat(buffer, stringList.getString((numGroats == 1) ? S_GROAT : S_GROATS), MAX_DESC_SIZE); // Make sure we're not overrunning } // Display the dialog diff --git a/engines/lure/scripts.cpp b/engines/lure/scripts.cpp index 3df119a9da..f7dc06033a 100644 --- a/engines/lure/scripts.cpp +++ b/engines/lure/scripts.cpp @@ -926,8 +926,8 @@ uint16 Script::execute(uint16 startOffset) { opcode >>= 1; if (gDebugLevel >= ERROR_DETAILED) - strcat(debugInfo, (opcode > S_OPCODE_RANDOM) ? "INVALID" : - scriptOpcodes[opcode]); + Common::strlcat(debugInfo, (opcode > S_OPCODE_RANDOM) ? "INVALID" : + scriptOpcodes[opcode], MAX_DESC_SIZE); if (hasParam) { // Flag to read next two bytes as active parameter @@ -1087,7 +1087,7 @@ uint16 Script::execute(uint16 startOffset) { else if (scriptMethodNames[param] == NULL) strcat(debugInfo, " UNKNOWN METHOD"); else { strcat(debugInfo, " "); - strcat(debugInfo, scriptMethodNames[param]); + Common::strlcat(debugInfo, scriptMethodNames[param], MAX_DESC_SIZE); } // Any params 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/neverhood/menumodule.cpp b/engines/neverhood/menumodule.cpp index 826f175d47..0f2a421d83 100644 --- a/engines/neverhood/menumodule.cpp +++ b/engines/neverhood/menumodule.cpp @@ -609,7 +609,8 @@ void TextEditWidget::onClick() { ++newCursorPos; _cursorPos = MIN((int)_entryString.size(), newCursorPos); } - _cursorSurface->setVisible(true); + if (!_readOnly) + _cursorSurface->setVisible(true); refresh(); } Widget::onClick(); @@ -1058,7 +1059,7 @@ static const NRect kSaveGameMenuTextEditRect = { 0, 0, 377, 17 }; static const NRect kSaveGameMenuMouseRect = { 50, 47, 427, 64 }; SaveGameMenu::SaveGameMenu(NeverhoodEngine *vm, Module *parentModule, SavegameList *savegameList) - : GameStateMenu(vm, parentModule, savegameList, kSaveGameMenuButtonFileHashes, kSaveGameMenuButtonCollisionBounds, + : GameStateMenu(vm, parentModule, savegameList, kSaveGameMenuButtonFileHashes, kSaveGameMenuButtonCollisionBounds, 0x30084E25, 0x2328121A, 0x84E21308, &kSaveGameMenuMouseRect, 0x1115A223, 60, 142, kSaveGameMenuListBoxRect, @@ -1068,9 +1069,11 @@ SaveGameMenu::SaveGameMenu(NeverhoodEngine *vm, Module *parentModule, SavegameLi } void SaveGameMenu::performAction() { - ((MenuModule*)_parentModule)->setSavegameInfo(_textEditWidget->getString(), - _listBox->getCurrIndex(), _textEditWidget->isModified()); - leaveScene(0); + if (!_textEditWidget->getString().empty()) { + ((MenuModule*)_parentModule)->setSavegameInfo(_textEditWidget->getString(), + _listBox->getCurrIndex(), _textEditWidget->isModified()); + leaveScene(0); + } } static const uint32 kLoadGameMenuButtonFileHashes[] = { @@ -1089,12 +1092,21 @@ static const NRect kLoadGameMenuButtonCollisionBounds[] = { static const NRect kLoadGameMenuListBoxRect = { 0, 0, 320, 272 }; static const NRect kLoadGameMenuTextEditRect = { 0, 0, 320, 17 }; + +#if 0 +// Unlike the original game, the text widget in our load dialog is read-only so +// don't change the mouse cursor to indicate that you can type the name of the +// game to load. +// +// Since we allow multiple saved games to have the same name, it's probably +// better this way. static const NRect kLoadGameMenuMouseRect = { 263, 48, 583, 65 }; +#endif LoadGameMenu::LoadGameMenu(NeverhoodEngine *vm, Module *parentModule, SavegameList *savegameList) : GameStateMenu(vm, parentModule, savegameList, kLoadGameMenuButtonFileHashes, kLoadGameMenuButtonCollisionBounds, 0x98620234, 0x201C2474, - 0x2023098E, &kLoadGameMenuMouseRect, + 0x2023098E, NULL /* &kLoadGameMenuMouseRect */, 0x04040409, 263, 142, kLoadGameMenuListBoxRect, 0x10924C03, 0, 263, 48, kLoadGameMenuTextEditRect, 0x0BC600A3, 0x0F960021) { @@ -1102,8 +1114,11 @@ LoadGameMenu::LoadGameMenu(NeverhoodEngine *vm, Module *parentModule, SavegameLi } void LoadGameMenu::performAction() { - ((MenuModule*)_parentModule)->setLoadgameInfo(_listBox->getCurrIndex()); - leaveScene(0); + // TODO: The original would display a message here if nothing was selected. + if (!_textEditWidget->getString().empty()) { + ((MenuModule*)_parentModule)->setLoadgameInfo(_listBox->getCurrIndex()); + leaveScene(0); + } } static const uint32 kDeleteGameMenuButtonFileHashes[] = { @@ -1134,8 +1149,11 @@ DeleteGameMenu::DeleteGameMenu(NeverhoodEngine *vm, Module *parentModule, Savega } void DeleteGameMenu::performAction() { - ((MenuModule*)_parentModule)->setDeletegameInfo(_listBox->getCurrIndex()); - leaveScene(0); + // TODO: The original would display a message here if no game was selected. + if (!_textEditWidget->getString().empty()) { + ((MenuModule*)_parentModule)->setDeletegameInfo(_listBox->getCurrIndex()); + leaveScene(0); + } } QueryOverwriteMenu::QueryOverwriteMenu(NeverhoodEngine *vm, Module *parentModule, const Common::String &description) 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/pegasus/neighborhood/mars/mars.cpp b/engines/pegasus/neighborhood/mars/mars.cpp index df5a75541c..7c4a8a98ba 100644 --- a/engines/pegasus/neighborhood/mars/mars.cpp +++ b/engines/pegasus/neighborhood/mars/mars.cpp @@ -1950,7 +1950,7 @@ void Mars::pickedUpItem(Item *item) { } void Mars::dropItemIntoRoom(Item *item, Hotspot *dropSpot) { - if (dropSpot->getObjectID() == kAttackRobotHotSpotID) { + if (dropSpot && dropSpot->getObjectID() == kAttackRobotHotSpotID) { _attackingItem = (InventoryItem *)item; startExtraSequence(kMars48RobotDefends, kExtraCompletedFlag, kFilterNoInput); loadLoopSound2(""); diff --git a/engines/prince/prince.cpp b/engines/prince/prince.cpp index b39d26e056..f1fd5a25d3 100644 --- a/engines/prince/prince.cpp +++ b/engines/prince/prince.cpp @@ -1543,20 +1543,18 @@ void PrinceEngine::showAnim(Anim &anim) { // make_special_shadow if ((anim._flags & 0x80)) { - if (animSurface) { - DrawNode newDrawNode; - newDrawNode.posX = x; - newDrawNode.posY = y + animSurface->h - anim._shadowBack; - newDrawNode.posZ = Hero::kHeroShadowZ; - newDrawNode.width = 0; - newDrawNode.height = 0; - newDrawNode.scaleValue = _scaleValue; - newDrawNode.originalRoomSurface = nullptr; - newDrawNode.data = this; - newDrawNode.drawFunction = &Hero::showHeroShadow; - newDrawNode.s = animSurface; - _drawNodeList.push_back(newDrawNode); - } + DrawNode newDrawNode; + newDrawNode.posX = x; + newDrawNode.posY = y + animSurface->h - anim._shadowBack; + newDrawNode.posZ = Hero::kHeroShadowZ; + newDrawNode.width = 0; + newDrawNode.height = 0; + newDrawNode.scaleValue = _scaleValue; + newDrawNode.originalRoomSurface = nullptr; + newDrawNode.data = this; + newDrawNode.drawFunction = &Hero::showHeroShadow; + newDrawNode.s = animSurface; + _drawNodeList.push_back(newDrawNode); } //ShowFrameCodeShadow 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 2ae9802d35..c01613268a 100644 --- a/engines/sci/detection_tables.h +++ b/engines/sci/detection_tables.h @@ -349,6 +349,19 @@ static const struct ADGameDescription SciGameDescriptions[] = { AD_LISTEND}, Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // Conquests of Camelot - English Atari ST + // Game version 1.019.000 + // Floppy: INT#10.12.90 + // Executable reports "1.002.038" + {"camelot", "", { + {"resource.map", 0, "0f80a11867be91a158823887a49cf443", 7290}, + {"resource.001", 0, "162f66c42e4146ee63f78fba6f1a6757", 596773}, + {"resource.002", 0, "162f66c42e4146ee63f78fba6f1a6757", 724615}, + {"resource.003", 0, "162f66c42e4146ee63f78fba6f1a6757", 713351}, + {"resource.004", 0, "162f66c42e4146ee63f78fba6f1a6757", 718766}, + AD_LISTEND}, + Common::EN_ANY, Common::kPlatformAtariST, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // Conquests of Camelot - English DOS // SCI interpreter version 0.000.685 {"camelot", "", { @@ -939,6 +952,22 @@ static const struct ADGameDescription SciGameDescriptions[] = { AD_LISTEND}, Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // Hoyle 1 - English Atari ST + // Game version 1.000.104, SCI interpreter version 1.002.024 + {"hoyle1", "", { + {"resource.001", 0, "e0dd44069a62a463fd124974b915f10d", 518127}, + {"resource.map", 0, "0af9a3dcd72a091960de070432e1f524", 4386}, + AD_LISTEND}, + Common::EN_ANY, Common::kPlatformAtariST, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + + // Hoyle 1 - English Atari ST + // Game version 1.000.108, SCI interpreter version 1.002.026 + {"hoyle1", "", { + {"resource.map", 0, "ed8355f84752e49ffa1f0cf9eca4b28e", 4140}, + {"resource.001", 0, "e0dd44069a62a463fd124974b915f10d", 517454}, + AD_LISTEND}, + Common::EN_ANY, Common::kPlatformAtariST, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // Hoyle 2 - English DOS // SCI interpreter version 0.000.572 {"hoyle2", "", { @@ -982,6 +1011,15 @@ static const struct ADGameDescription SciGameDescriptions[] = { AD_LISTEND}, Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // Hoyle 2 - English Atari ST + // Game version 1.001.017 + // Executable scanning reports "1.002.034" + {"hoyle2", "", { + {"resource.map", 0, "13c8cc977598b6ad61d24c6296a090fd", 1356}, + {"resource.001", 0, "8f2dd70abe01112eca464cda818b5eb6", 216280}, + AD_LISTEND}, + Common::EN_ANY, Common::kPlatformAtariST, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // Hoyle 2 - English Macintosh // Executable scanning reports "x.yyy.zzz" {"hoyle2", "", { @@ -1977,6 +2015,17 @@ static const struct ADGameDescription SciGameDescriptions[] = { AD_LISTEND}, Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // Larry 2 - English Atari ST + // Game version 1.001.006 + // Executable reports "1.000.159" 1988-12-02 12:22 p.m. + {"lsl2", "", { + {"resource.map", 0, "2fc3ce7da1346e4dadfee18606d814fc", 4758}, + {"resource.001", 0, "4a24443a25e2b1492462a52809605dc2", 477342}, + {"resource.002", 0, "4a24443a25e2b1492462a52809605dc2", 406698}, + {"resource.003", 0, "4a24443a25e2b1492462a52809605dc2", 592433}, + AD_LISTEND}, + Common::EN_ANY, Common::kPlatformAtariST, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // Larry 2 - English DOS Non-Interactive Demo // Executable scanning reports "x.yyy.zzz" // SCI interpreter version 0.000.409 @@ -2034,6 +2083,17 @@ static const struct ADGameDescription SciGameDescriptions[] = { AD_LISTEND}, Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // Larry 2 - English Atari ST (Kixx) + // Game version 1.002.000 + // Executable reports "1.001.008" 1989-01-12 16:30 + {"lsl2", "", { + {"resource.map", 0, "2c9c3b0923e3764f5ab999bcb71c2d47", 4758}, + {"resource.001", 0, "4a24443a25e2b1492462a52809605dc2", 477625}, + {"resource.002", 0, "4a24443a25e2b1492462a52809605dc2", 406935}, + {"resource.003", 0, "4a24443a25e2b1492462a52809605dc2", 592533}, + AD_LISTEND}, + Common::EN_ANY, Common::kPlatformAtariST, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // Larry 3 - English Amiga (from www.back2roots.org) // Executable scanning reports "1.002.032" // SCI interpreter version 0.000.685 @@ -2048,6 +2108,19 @@ static const struct ADGameDescription SciGameDescriptions[] = { AD_LISTEND}, Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // Larry 3 - English Atari ST + // Game version 1.021, 1990-01-27 + // Int#6.26.90 + // Executable scanning reports "1.002.026" + {"lsl3", "", { + {"resource.map", 0, "0b6bd3e039682830a51c5755c06591db", 5916}, + {"resource.001", 0, "f18441027154292836b973c655fa3175", 456722}, + {"resource.002", 0, "f18441027154292836b973c655fa3175", 578024}, + {"resource.003", 0, "f18441027154292836b973c655fa3175", 506807}, + {"resource.004", 0, "f18441027154292836b973c655fa3175", 513651}, + AD_LISTEND}, + Common::EN_ANY, Common::kPlatformAtariST, 0, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // Larry 3 - English DOS (supplied by ssburnout in bug report #3049193) // 1.021 8x5.25" (label: Int#5.15.90) {"lsl3", "", { @@ -2916,6 +2989,17 @@ static const struct ADGameDescription SciGameDescriptions[] = { AD_LISTEND}, Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // Police Quest 2 - English Atari ST + // Game version 1.002.011 DS 1989-07-21 + // Executable reports "1.002.003" + {"pq2", "", { + {"resource.map", 0, "28a6f471c7900c2c92da40eecb615d9d", 4584}, + {"resource.001", 0, "77f02def3094af804fd2371db25b7100", 509525}, + {"resource.002", 0, "77f02def3094af804fd2371db25b7100", 546000}, + {"resource.003", 0, "77f02def3094af804fd2371db25b7100", 591851}, + AD_LISTEND}, + Common::EN_ANY, Common::kPlatformAtariST, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // Police Quest 2 - English DOS (from FRG) // SCI interpreter version 0.000.395 {"pq2", "", { @@ -2935,6 +3019,17 @@ static const struct ADGameDescription SciGameDescriptions[] = { AD_LISTEND}, Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // Police Quest 2 - English Atari ST + // Game version 1.001.006 1989-01-16 13:30 + // Executable reports "1.001.009" + {"pq2", "", { + {"resource.map", 0, "8e1161c684b342742d30f938a4839a4b", 4518}, + {"resource.001", 0, "77f02def3094af804fd2371db25b7100", 506563}, + {"resource.002", 0, "77f02def3094af804fd2371db25b7100", 541261}, + {"resource.003", 0, "77f02def3094af804fd2371db25b7100", 587511}, + AD_LISTEND}, + Common::EN_ANY, Common::kPlatformAtariST, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // Police Quest 2 - Japanese PC-98 (also includes english language) // Executable scanning reports "x.yyy.zzz" // SCI interpreter version unknown @@ -3204,6 +3299,19 @@ static const struct ADGameDescription SciGameDescriptions[] = { AD_LISTEND}, Common::EN_ANY, Common::kPlatformDOS, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // Quest for Glory 1 / Hero's Quest - English Atari ST + // Game version 1.137 + // Executable reports "1.002.028" + {"qfg1", "", { + {"resource.map", 0, "2a794066ad161acbedac8fa14e46905d", 6438}, + {"resource.000", 0, "40332d3ebfc70a4b6a6a0443c2763287", 79204}, + {"resource.001", 0, "f7fc269d3db146830d6427d3e02d4187", 473547}, + {"resource.002", 0, "e64004e020fdf1813be52b639b08be89", 635687}, + {"resource.003", 0, "f0af87c60ec869946da442833aa5afa8", 640438}, + {"resource.004", 0, "f0af87c60ec869946da442833aa5afa8", 644452}, + AD_LISTEND}, + Common::EN_ANY, Common::kPlatformAtariST, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // Quest for Glory 1 / Hero's Quest - English DOS Demo // Executable scanning reports "0.000.685" {"qfg1", "Demo", { @@ -3283,6 +3391,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { Common::EN_ANY, Common::kPlatformMacintosh, ADGF_MACRESFORK, GUIO4(GUIO_NOSPEECH, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, // Quest for Glory 2 - English Amiga + // Game version 1.109 // Executable scanning reports "1.003.004" // SCI interpreter version 0.001.010 {"qfg2", "", { @@ -3705,6 +3814,18 @@ static const struct ADGameDescription SciGameDescriptions[] = { AD_LISTEND}, Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // Space Quest 3 - English Atari ST + // Game version 1.0Q 1989-27-03 17:00 + // Int#1.002.002 + // Executable reports "1.002.001" + {"sq3", "", { + {"resource.map", 0, "c36e322805949affd882a75803a6a54e", 5484}, + {"resource.001", 0, "ceeda7202b96e5c85ecaa88a40a540fc", 485146}, + {"resource.002", 0, "ceeda7202b96e5c85ecaa88a40a540fc", 720227}, + {"resource.003", 0, "ceeda7202b96e5c85ecaa88a40a540fc", 688524}, + AD_LISTEND}, + Common::EN_ANY, Common::kPlatformAtariST, 0, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EGA_UNDITHER, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) }, + // Space Quest 3 - German Amiga (also includes english language) // Executable scanning reports "1.004.006" // SCI interpreter version 0.000.453 (just a guess) @@ -4235,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.cpp b/engines/scumm/detection.cpp index 0867b20fc3..4c9d1221aa 100644 --- a/engines/scumm/detection.cpp +++ b/engines/scumm/detection.cpp @@ -186,6 +186,11 @@ Common::String ScummEngine_v70he::generateFilename(const int room) const { } if (_filenamePattern.genMethod == kGenHEPC || _filenamePattern.genMethod == kGenHEIOS) { + if (id == '3' && _game.id == GID_MOONBASE) { + result = Common::String::format("%s.u32", _filenamePattern.pattern); + break; + } + // For HE >= 98, we already called snprintf above. if (_game.heversion < 98 || room < 0) result = Common::String::format("%s.he%c", _filenamePattern.pattern, id); 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..06e6b249f6 100644 --- a/engines/scumm/he/intern_he.h +++ b/engines/scumm/he/intern_he.h @@ -184,8 +184,11 @@ protected: }; #ifdef ENABLE_HE +class Moonbase; + 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 { @@ -433,7 +440,7 @@ protected: byte filename[260]; int32 status; int32 flags; - int32 unk2; + int32 number; int32 wizResNum; }; 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..a32356614f --- /dev/null +++ b/engines/scumm/he/logic/moonbase_logic.cpp @@ -0,0 +1,253 @@ +/* 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" +#include "scumm/he/moonbase/moonbase.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); + int 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: + return 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) { + Common::String str; + + str = Common::String::format("op_set_fow_information(%d", args[0]); + for (int i = 1; i < numArgs; i++) { + str += Common::String::format(", %d", args[i]); + } + str += ")"; + + debug(2, "%s", str.c_str()); + + _vm->_moonbase->setFOWInfo( + args[0], // array + args[1], // array down dimension + args[2], // array across dimension + args[3], // logical view X coordinate + args[4], // logical view Y coordinate + args[5], // screen draw clip rect x1 + args[6], // screen draw clip rect y1 + args[7], // screen draw clip rect x2 + args[8], // screen draw clip rect y2 + args[9], // techinque + args[10] // frame + ); +} + +int LogicHEmoonbase::op_set_fow_image(int op, int numArgs, int32 *args) { + debug(2, "op_set_fow_image(%d)", args[0]); + return _vm->_moonbase->setFOWImage(args[0]) ? 1 : 0; +} + +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..34d4368725 --- /dev/null +++ b/engines/scumm/he/moonbase/moonbase.cpp @@ -0,0 +1,179 @@ +/* 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/moonbase/moonbase.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) { + bool premulAlpa = false; + + if (rawROP == 1) + premulAlpa = true; + + 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 or single + uint8 *src; + int cnt; + if (code == 0) { // quad + src = quadsOffset; + quadsOffset += 8; + cnt = 4; // 4 pixels + } else { // single + src = singlesOffset; + singlesOffset += 2; + cnt = 1; + } + + for (int c = 0; c < cnt; c++) { + if (pixels >= sx) { + if (rawROP == 1) { // MMX_PREMUL_ALPHA_COPY + WRITE_LE_UINT16(dst1, READ_LE_UINT16(src)); + } else if (rawROP == 2) { // MMX_ADDITIVE + uint16 color = READ_LE_UINT16(src); + uint16 orig = READ_LE_UINT16(dst1); + + uint32 r = MIN<uint32>(0x7c00, (orig & 0x7c00) + (color & 0x7c00)); + uint32 g = MIN<uint32>(0x03e0, (orig & 0x03e0) + (color & 0x03e0)); + uint32 b = MIN<uint32>(0x001f, (orig & 0x001f) + (color & 0x001f)); + WRITE_LE_UINT16(dst1, (r | g | b)); + } else if (rawROP == 5) { // MMX_CHEAP_50_50 + uint16 color = (READ_LE_UINT16(src) >> 1) & 0x3DEF; + uint16 orig = (READ_LE_UINT16(dst1) >> 1) & 0x3DEF; + WRITE_LE_UINT16(dst1, (color + orig)); + } + dst1 += 2; + } + src += 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); + + if (!premulAlpa) { + WRITE_LE_UINT16(dst1, color); // ENABLE_PREMUL_ALPHA = 0 + } else { + 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..e82ae0164f --- /dev/null +++ b/engines/scumm/he/moonbase/moonbase.h @@ -0,0 +1,99 @@ +/* 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 + +#include "common/winexe_pe.h" + +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: + 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; + uint32 _fowSentinelConditionBits; + +private: + ScummEngine_v71he *_vm; + + int _fowFrameBaseNumber; + int _fowAnimationFrames; + int _fowCurrentFOWFrame; + + int32 _fowTileW; + int32 _fowTileH; + + uint8 *_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]; + + Common::PEResources _exe; + Common::String _fileName; +}; + +} // End of namespace Scumm + +#endif // ENABLE_HE + +#endif // SCUMM_HE_MOONBASE_H diff --git a/engines/scumm/he/moonbase/moonbase_fow.cpp b/engines/scumm/he/moonbase/moonbase_fow.cpp new file mode 100644 index 0000000000..3f3730b6f1 --- /dev/null +++ b/engines/scumm/he/moonbase/moonbase_fow.cpp @@ -0,0 +1,417 @@ +/* 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" +#include "scumm/he/moonbase/moonbase.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::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, file.size()); + free(wiz); + } + } +#endif + + if (!_fowImage && image < 0) { + int resId; + + // PIECES BUBBLES CIRCLES SIMPLE* WEDGEY BUBBLE2 + // WEDGE2 SPIKEY ANGLES SMOOTHED WUZZY SYS7-BEVELED + if (image >= -12 && image <= -1) + resId = 210 - image; // 211-222 range + else + resId = 214; // default, SIMPLE + + if (_fileName.empty()) { // We are running for the first time + _fileName = _vm->generateFilename(-3); + + if (!_exe.loadFromEXE(_fileName)) + error("Cannot open file %s", _fileName.c_str()); + } + + Common::SeekableReadStream *stream = _exe.getResource(Common::kPERCData, resId); + + if (stream->size()) { + _fowImage = (uint8 *)malloc(stream->size()); + + stream->read(_fowImage, stream->size()); + } + + delete stream; + } + + if (!_fowImage && image > 0) + _fowImage = _vm->getResourceAddress(rtImage, image); + + 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; + + _vm->_wiz->getWizImageDim(_fowImage, (nStates - 1), _fowTileW, _fowTileH); + _fowBlackMode = !_vm->_wiz->isWizPixelNonTransparent(_fowImage, nStates - 1, 0, 0, 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(116) = array; + + 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) { + int32 spotx, spoty; + + _vm->_wiz->getWizImageSpot(_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 dstPitch, int dstw, int dsth, int x1, int y1, int x2, int y2) { + byte *dst = destSurface + dstPitch * y1 + x1 * 2; + int h = y2 - y1; + int w = ((x2 - x1) + 1) * 2; + + while ( --h >= 0 ) { + memset(dst, 0, w); + dst += dstPitch; + } +} + +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, dstPitch, dstw, dsth, 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..4388433c7e 100644 --- a/engines/scumm/he/script_v100he.cpp +++ b/engines/scumm/he/script_v100he.cpp @@ -549,20 +549,20 @@ void ScummEngine_v100he::o100_arrayOps() { debug(9,"o100_arrayOps: array %d case %d", array, subOp); switch (subOp) { - case 35: + case 35: // SO_FORMATTED_STRING decodeScriptString(string); len = resStrLen(string); data = defineArray(array, kStringArray, 0, 0, 0, len); memcpy(data, string, len); break; - case 77: // SO_ASSIGN_STRING + case 77: // SO_STRING copyScriptString(string, sizeof(string)); len = resStrLen(string); data = defineArray(array, kStringArray, 0, 0, 0, len); memcpy(data, string, len); break; - case 128: // SO_ASSIGN_2DIM_LIST + case 128: // SO_ASSIGN_2DIM_LIST len = getStackList(list, ARRAYSIZE(list)); id = readVar(array); if (id == 0) @@ -572,7 +572,7 @@ void ScummEngine_v100he::o100_arrayOps() { writeArray(array, c, len, list[len]); } break; - case 129: // SO_ASSIGN_INT_LIST + case 129: // SO_ASSIGN_INT_LIST b = pop(); c = pop(); id = readVar(array); @@ -583,7 +583,7 @@ void ScummEngine_v100he::o100_arrayOps() { writeArray(array, 0, b + c, pop()); } break; - case 130: + case 130: // len = getStackList(list, ARRAYSIZE(list)); dim1end = pop(); dim1start = pop(); @@ -607,7 +607,7 @@ void ScummEngine_v100he::o100_arrayOps() { dim2start++; } break; - case 131: + case 131: // SO_COMPLEX_ARRAY_COPY_OPERATION { int a2_dim1end = pop(); int a2_dim1start = pop(); @@ -624,7 +624,7 @@ void ScummEngine_v100he::o100_arrayOps() { copyArray(array, a1_dim2start, a1_dim2end, a1_dim1start, a1_dim1end, array2, a2_dim2start, a2_dim2end, a2_dim1start, a2_dim1end); } break; - case 132: + case 132: // SO_COMPLEX_ARRAY_MATH_OPERATION // TODO: Used by room 2 script 2180 in Moonbase Commander fetchScriptWord(); fetchScriptWord(); @@ -659,9 +659,9 @@ void ScummEngine_v100he::o100_arrayOps() { default: error("o100_arrayOps: case 132 unknown type %d)", type); } - debug(0, "o100_arrayOps: case 132 type %d", type); + warning("STUB: o100_arrayOps: case 132 type %d", type); break; - case 133: + case 133: // SO_RANGE_ARRAY_ASSIGNMENT b = pop(); c = pop(); dim1end = pop(); @@ -1110,6 +1110,7 @@ void ScummEngine_v100he::o100_resourceRoutines() { break; case 128: // TODO: Clear Heap + warning("STUB: o100_resourceRoutines: clear Heap"); break; case 129: // Dummy case @@ -1310,36 +1311,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; @@ -1781,14 +1782,14 @@ void ScummEngine_v100he::o100_setSpriteInfo() { byte subOp = fetchScriptByte(); switch (subOp) { - case 0: + case 0: // SO_INIT _curMaxSpriteId = pop(); _curSpriteId = pop(); if (_curSpriteId > _curMaxSpriteId) SWAP(_curSpriteId, _curMaxSpriteId); break; - case 2: + case 2: // SO_ANGLE args[0] = pop(); if (_curSpriteId > _curMaxSpriteId) break; @@ -1799,7 +1800,7 @@ void ScummEngine_v100he::o100_setSpriteInfo() { for (; spriteId <= _curMaxSpriteId; spriteId++) _sprite->setSpriteAngle(spriteId, args[0]); break; - case 3: + case 3: // SO_ANIMATION args[0] = pop(); if (_curSpriteId > _curMaxSpriteId) break; @@ -1810,7 +1811,7 @@ void ScummEngine_v100he::o100_setSpriteInfo() { for (; spriteId <= _curMaxSpriteId; spriteId++) _sprite->setSpriteFlagAutoAnim(spriteId, args[0]); break; - case 4: + case 4: // SO_ANIMATION_SPEED args[0] = pop(); if (_curSpriteId > _curMaxSpriteId) break; @@ -1821,7 +1822,7 @@ void ScummEngine_v100he::o100_setSpriteInfo() { for (; spriteId <= _curMaxSpriteId; spriteId++) _sprite->setSpriteAnimSpeed(spriteId, args[0]); break; - case 6: + case 6: // SO_AT args[1] = pop(); args[0] = pop(); if (_curSpriteId > _curMaxSpriteId) @@ -1833,7 +1834,7 @@ void ScummEngine_v100he::o100_setSpriteInfo() { for (; spriteId <= _curMaxSpriteId; spriteId++) _sprite->setSpritePosition(spriteId, args[0], args[1]); break; - case 7: + case 7: // SO_AT_IMAGE args[0] = pop(); if (_curSpriteId > _curMaxSpriteId) break; @@ -1844,7 +1845,7 @@ void ScummEngine_v100he::o100_setSpriteInfo() { for (; spriteId <= _curMaxSpriteId; spriteId++) _sprite->setSpriteSourceImage(spriteId, args[0]); break; - case 16: + case 16: // SO_CLASS n = getStackList(args, ARRAYSIZE(args)); if (_curSpriteId != 0 && _curMaxSpriteId != 0 && n != 0) { int *p = &args[n - 1]; @@ -1867,7 +1868,7 @@ void ScummEngine_v100he::o100_setSpriteInfo() { } while (--n); } break; - case 32: + case 32: // SO_ERASE args[0] = pop(); if (_curSpriteId > _curMaxSpriteId) break; @@ -1878,7 +1879,7 @@ void ScummEngine_v100he::o100_setSpriteInfo() { for (; spriteId <= _curMaxSpriteId; spriteId++) _sprite->setSpriteFlagEraseType(spriteId, args[0]); break; - case 38: + case 38: // SO_GROUP args[0] = pop(); if (_curSpriteId > _curMaxSpriteId) break; @@ -1889,7 +1890,7 @@ void ScummEngine_v100he::o100_setSpriteInfo() { for (; spriteId <= _curMaxSpriteId; spriteId++) _sprite->setSpriteGroup(spriteId, args[0]); break; - case 40: + case 40: // SO_IMAGE args[0] = pop(); if (_curSpriteId > _curMaxSpriteId) break; @@ -1900,7 +1901,7 @@ void ScummEngine_v100he::o100_setSpriteInfo() { for (; spriteId <= _curMaxSpriteId; spriteId++) _sprite->setSpriteImage(spriteId, args[0]); break; - case 48: + case 48: // SO_MASK args[0] = pop(); if (_curSpriteId > _curMaxSpriteId) break; @@ -1911,7 +1912,7 @@ void ScummEngine_v100he::o100_setSpriteInfo() { for (; spriteId <= _curMaxSpriteId; spriteId++) _sprite->setSpriteMaskImage(spriteId, args[0]); break; - case 49: + case 49: // SO_MOVE args[1] = pop(); args[0] = pop(); if (_curSpriteId > _curMaxSpriteId) @@ -1923,10 +1924,10 @@ void ScummEngine_v100he::o100_setSpriteInfo() { for (; spriteId <= _curMaxSpriteId; spriteId++) _sprite->moveSprite(spriteId, args[0], args[1]); break; - case 52: + case 52: // SO_NAME copyScriptString(string, sizeof(string)); break; - case 53: + case 53: // SO_NEW if (_curSpriteId > _curMaxSpriteId) break; spriteId = _curSpriteId; @@ -1936,7 +1937,7 @@ void ScummEngine_v100he::o100_setSpriteInfo() { for (; spriteId <= _curMaxSpriteId; spriteId++) _sprite->resetSprite(spriteId); break; - case 54: + case 54: // SO_NEW_GENERAL_PROPERTY args[1] = pop(); args[0] = pop(); if (_curSpriteId > _curMaxSpriteId) @@ -1948,7 +1949,7 @@ void ScummEngine_v100he::o100_setSpriteInfo() { for (; spriteId <= _curMaxSpriteId; spriteId++) _sprite->setSpriteGeneralProperty(spriteId, args[0], args[1]); break; - case 57: + case 57: // SO_PALETTE args[0] = pop(); if (_curSpriteId > _curMaxSpriteId) break; @@ -1959,7 +1960,7 @@ void ScummEngine_v100he::o100_setSpriteInfo() { for (; spriteId <= _curMaxSpriteId; spriteId++) _sprite->setSpritePalette(spriteId, args[0]); break; - case 59: + case 59: // SO_PRIORITY args[0] = pop(); if (_curSpriteId > _curMaxSpriteId) break; @@ -1970,7 +1971,7 @@ void ScummEngine_v100he::o100_setSpriteInfo() { for (; spriteId <= _curMaxSpriteId; spriteId++) _sprite->setSpritePriority(spriteId, args[0]); break; - case 60: + case 60: // SO_PROPERTY args[1] = pop(); args[0] = pop(); if (_curSpriteId > _curMaxSpriteId) @@ -1997,13 +1998,14 @@ 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; - case 61: + case 61: // SO_RESTART _sprite->resetTables(true); break; - case 65: + case 65: // SO_SCALE args[0] = pop(); if (_curSpriteId > _curMaxSpriteId) break; @@ -2014,7 +2016,7 @@ void ScummEngine_v100he::o100_setSpriteInfo() { for (; spriteId <= _curMaxSpriteId; spriteId++) _sprite->setSpriteScale(spriteId, args[0]); break; - case 70: + case 70: // SO_SHADOW args[0] = pop(); if (_curSpriteId > _curMaxSpriteId) break; @@ -2025,7 +2027,7 @@ void ScummEngine_v100he::o100_setSpriteInfo() { for (; spriteId <= _curMaxSpriteId; spriteId++) _sprite->setSpriteShadow(spriteId, args[0]); break; - case 73: + case 73: // SO_STATE args[0] = pop(); if (_curSpriteId > _curMaxSpriteId) break; @@ -2036,7 +2038,7 @@ void ScummEngine_v100he::o100_setSpriteInfo() { for (; spriteId <= _curMaxSpriteId; spriteId++) _sprite->setSpriteImageState(spriteId, args[0]); break; - case 74: + case 74: // SO_STEP_DIST args[1] = pop(); args[0] = pop(); if (_curSpriteId > _curMaxSpriteId) @@ -2048,7 +2050,7 @@ void ScummEngine_v100he::o100_setSpriteInfo() { for (; spriteId <= _curMaxSpriteId; spriteId++) _sprite->setSpriteDist(spriteId, args[0], args[1]); break; - case 75: + case 75: // SO_STEP_DIST_X args[0] = pop(); if (_curSpriteId > _curMaxSpriteId) break; @@ -2061,7 +2063,7 @@ void ScummEngine_v100he::o100_setSpriteInfo() { _sprite->setSpriteDist(spriteId, args[0], tmp[1]); } break; - case 76: + case 76: // SO_STEP_DIST_Y args[0] = pop(); if (_curSpriteId > _curMaxSpriteId) break; @@ -2074,7 +2076,7 @@ void ScummEngine_v100he::o100_setSpriteInfo() { _sprite->setSpriteDist(spriteId, tmp[0], args[0]); } break; - case 82: + case 82: // SO_UPDATE args[0] = pop(); if (_curSpriteId > _curMaxSpriteId) break; @@ -2085,7 +2087,7 @@ void ScummEngine_v100he::o100_setSpriteInfo() { for (; spriteId <= _curMaxSpriteId; spriteId++) _sprite->setSpriteFlagUpdateType(spriteId, args[0]); break; - case 83: + case 83: // SO_VARIABLE args[1] = pop(); args[0] = pop(); if (_curSpriteId > _curMaxSpriteId) @@ -2097,7 +2099,7 @@ void ScummEngine_v100he::o100_setSpriteInfo() { for (; spriteId <= _curMaxSpriteId; spriteId++) _sprite->setSpriteUserValue(spriteId, args[0], args[1]); break; - case 88: + case 88: // SO_IMAGE_ZCLIP args[0] = pop(); if (_curSpriteId > _curMaxSpriteId) break; @@ -2106,9 +2108,9 @@ void ScummEngine_v100he::o100_setSpriteInfo() { spriteId++; for (; spriteId <= _curMaxSpriteId; spriteId++) - _sprite->setSpriteField84(spriteId, args[0]); + _sprite->setSpriteZBuffer(spriteId, args[0]); break; - case 89: + case 89: // SO_NEVER_ZCLIP if (_curSpriteId > _curMaxSpriteId) break; spriteId = _curSpriteId; @@ -2116,7 +2118,7 @@ void ScummEngine_v100he::o100_setSpriteInfo() { spriteId++; for (; spriteId <= _curMaxSpriteId; spriteId++) - _sprite->setSpriteField84(spriteId, 0); + _sprite->setSpriteZBuffer(spriteId, 0); break; default: error("o100_setSpriteInfo: Unknown case %d", subOp); @@ -2235,40 +2237,43 @@ void ScummEngine_v100he::o100_videoOps() { byte subOp = fetchScriptByte(); switch (subOp) { - case 0: + case 0: // SO_INIT memset(_videoParams.filename, 0, sizeof(_videoParams.filename)); _videoParams.status = 0; _videoParams.flags = 0; - _videoParams.unk2 = pop(); + _videoParams.number = pop(); _videoParams.wizResNum = 0; + + if (_videoParams.number != 1 && _videoParams.number != -1) + warning("o100_videoOps: number: %d", _videoParams.number); break; - case 19: + case 19: // SO_CLOSE _videoParams.status = 19; break; - case 40: + case 40: // SO_IMAGE _videoParams.wizResNum = pop(); if (_videoParams.wizResNum) _videoParams.flags |= 2; break; - case 47: + case 47: // SO_LOAD copyScriptString(_videoParams.filename, sizeof(_videoParams.filename)); _videoParams.status = 47; break; - case 67: + case 67: // SO_SET_FLAGS _videoParams.flags |= pop(); break; - case 92: - if (_videoParams.status == 47) { + case 92: // SO_END + if (_videoParams.status == 47) { // SO_LOAD // Start video if (_videoParams.flags == 0) _videoParams.flags = 4; - if (_videoParams.flags == 2) { + if (_videoParams.flags & 2) { VAR(119) = _moviePlay->load(convertFilePath(_videoParams.filename), _videoParams.flags, _videoParams.wizResNum); } else { VAR(119) = _moviePlay->load(convertFilePath(_videoParams.filename), _videoParams.flags); } - } else if (_videoParams.status == 19) { + } else if (_videoParams.status == 19) { // SO_CLOSE // Stop video _moviePlay->close(); } @@ -2468,6 +2473,7 @@ void ScummEngine_v100he::o100_getSpriteGroupInfo() { pop(); pop(); push(0); + warning("STUB: o100_getSpriteGroupInfo, subop 54"); break; case 59: spriteGroupId = pop(); diff --git a/engines/scumm/he/script_v90he.cpp b/engines/scumm/he/script_v90he.cpp index f65d2f6077..f63973e3f1 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; @@ -1412,7 +1412,7 @@ void ScummEngine_v90he::o90_videoOps() { memset(_videoParams.filename, 0, sizeof(_videoParams.filename)); _videoParams.status = 0; _videoParams.flags = 0; - _videoParams.unk2 = pop(); + _videoParams.number = pop(); _videoParams.wizResNum = 0; break; case 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..e3f04dfcf0 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: @@ -739,26 +739,24 @@ void Sprite::setSpriteResetClass(int spriteId) { _spriteTable[spriteId].classFlags = 0; } -void Sprite::setSpriteField84(int spriteId, int value) { +void Sprite::setSpriteZBuffer(int spriteId, int value) { assertRange(1, spriteId, _varNumSprites, "sprite"); - _spriteTable[spriteId].field_84 = value; + _spriteTable[spriteId].zbufferImage = value; } void Sprite::setSpriteGeneralProperty(int spriteId, int type, int value) { - debug(0, "setSpriteGeneralProperty: spriteId %d type 0x%x", spriteId, type); + debug(6, "setSpriteGeneralProperty: spriteId %d type 0x%x value 0x%x", spriteId, type, value); assertRange(1, spriteId, _varNumSprites, "sprite"); int32 delay; - // XXX U32 related check - switch (type) { case 0x7B: _spriteTable[spriteId].imgFlags = 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: @@ -797,9 +795,9 @@ void Sprite::resetSprite(int spriteId) { _spriteTable[spriteId].sourceImage = 0; _spriteTable[spriteId].maskImage = 0; _spriteTable[spriteId].priority = 0; - _spriteTable[spriteId].field_84 = 0; + _spriteTable[spriteId].zbufferImage = 0; _spriteTable[spriteId].imgFlags = 0; - _spriteTable[spriteId].field_90 = 0; + _spriteTable[spriteId].conditionBits = 0; if (_vm->_game.heversion >= 100) { _spriteTable[spriteId].flags &= ~kSFMarkDirty; @@ -816,7 +814,7 @@ void Sprite::setSpriteImage(int spriteId, int imageNum) { origResWizStates = _spriteTable[spriteId].imageStateCount; _spriteTable[spriteId].image = imageNum; - _spriteTable[spriteId].field_74 = 0; + _spriteTable[spriteId].animIndex = 0; _spriteTable[spriteId].imageState = 0; if (_spriteTable[spriteId].image) { @@ -1292,7 +1290,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; @@ -1339,9 +1337,9 @@ void Sprite::processImages(bool arg) { } if (spr_flags & kSFRemapPalette) wiz.img.flags |= kWIFRemapPalette; - if (spi->field_84) { + if (spi->zbufferImage) { wiz.processFlags |= 0x200000; - wiz.img.field_390 = spi->field_84; + wiz.img.zbuffer = spi->zbufferImage; wiz.img.zorder = spi->priority; } if (spi->sourceImage) { @@ -1419,14 +1417,14 @@ void Sprite::saveOrLoadSpriteData(Serializer *s) { MKLINE(SpriteInfo, curAngle, sleInt32, VER(48)), MKLINE(SpriteInfo, curScale, sleInt32, VER(48)), MKLINE(SpriteInfo, curImgFlags, sleInt32, VER(48)), - MKLINE(SpriteInfo, field_74, sleInt32, VER(48)), + MKLINE(SpriteInfo, animIndex, sleInt32, VER(48)), MKLINE(SpriteInfo, animSpeed, sleInt32, VER(48)), MKLINE(SpriteInfo, sourceImage, sleInt32, VER(48)), MKLINE(SpriteInfo, maskImage, sleInt32, VER(48)), - MKLINE(SpriteInfo, field_84, sleInt32, VER(48)), + MKLINE(SpriteInfo, zbufferImage, 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..3ea6bb9f84 100644 --- a/engines/scumm/he/sprite_he.h +++ b/engines/scumm/he/sprite_he.h @@ -72,14 +72,14 @@ struct SpriteInfo { int32 curAngle; int32 curScale; int32 curImgFlags; - int32 field_74; + int32 animIndex; int32 animSpeed; int32 sourceImage; int32 maskImage; - int32 field_84; + int32 zbufferImage; int32 classFlags; int32 imgFlags; - int32 field_90; + int32 conditionBits; }; struct SpriteGroup { @@ -182,7 +182,7 @@ public: void setSpriteAnimSpeed(int spriteId, int value); void setSpriteSetClass(int spriteId, int classId, int toggle); void setSpriteResetClass(int spriteId); - void setSpriteField84(int spriteId, int value); + void setSpriteZBuffer(int spriteId, int value); void setSpriteGeneralProperty(int spriteId, int type, int value); void moveGroupMembers(int spriteGroupId, int value1, int value2); diff --git a/engines/scumm/he/wiz_he.cpp b/engines/scumm/he/wiz_he.cpp index 9a59609651..0976a532de 100644 --- a/engines/scumm/he/wiz_he.cpp +++ b/engines/scumm/he/wiz_he.cpp @@ -31,6 +31,7 @@ #include "scumm/scumm.h" #include "scumm/util.h" #include "scumm/he/wiz_he.h" +#include "scumm/he/moonbase/moonbase.h" namespace Scumm { @@ -976,7 +977,7 @@ void Wiz::decompressRawWizImage(uint8 *dst, int dstPitch, int dstType, const uin } } -int Wiz::isWizPixelNonTransparent(const uint8 *data, int x, int y, int w, int h, uint8 bitDepth) { +int Wiz::isPixelNonTransparent(const uint8 *data, int x, int y, int w, int h, uint8 bitDepth) { if (x < 0 || x >= w || y < 0 || y >= h) { return 0; } @@ -1422,19 +1423,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(7, "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; @@ -1454,10 +1455,7 @@ uint8 *Wiz::drawWizImage(int resNum, int state, int maskNum, int maskState, int 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); + debug(7, "wiz_header.comp = %d wiz_header.w = %d wiz_header.h = %d", comp, width, height); uint8 *mask = NULL; if (maskNum) { @@ -1574,58 +1572,261 @@ uint8 *Wiz::drawWizImage(int resNum, int state, int maskNum, int maskState, int transColor = (trns == NULL) ? _vm->VAR(_vm->VAR_WIZ_TCOLOR) : -1; } + if (_vm->_game.id == GID_MOONBASE && + resNum == _vm->_moonbase->_fowSentinelImage && + state == _vm->_moonbase->_fowSentinelState && + conditionBits == _vm->_moonbase->_fowSentinelConditionBits) { + _vm->_moonbase->renderFOW(dst, dstPitch, dstType, cw, ch, flags); + x1 = 0; + y1 = 0; + width = rScreen.width(); + height = rScreen.height(); + } else { + 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(7, "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; + } + + 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: + rawROP = 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 +1948,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 +2016,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 +2027,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 +2202,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 +2224,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 +2274,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 +2305,19 @@ 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)); + drawWizImage(params->img.resNum, state, 0, 0, po_x, po_y, params->img.zorder, shadow, zbuffer, r, flags, dstResNum, _vm->getHEPaletteSlot(palette), params->conditionBits); } } } @@ -2501,6 +2702,10 @@ void Wiz::processWizImage(const WizParameters *params) { void Wiz::getWizImageDim(int resNum, int state, int32 &w, int32 &h) { uint8 *dataPtr = _vm->getResourceAddress(rtImage, resNum); assert(dataPtr); + getWizImageDim(dataPtr, state, w, h); +} + +void Wiz::getWizImageDim(uint8 *dataPtr, int state, int32 &w, int32 &h) { uint8 *wizh = _vm->findWrappedBlock(MKTAG('W','I','Z','H'), dataPtr, state, 0); assert(wizh); w = READ_LE_UINT32(wizh + 0x4); @@ -2510,6 +2715,10 @@ void Wiz::getWizImageDim(int resNum, int state, int32 &w, int32 &h) { void Wiz::getWizImageSpot(int resId, int state, int32 &x, int32 &y) { uint8 *dataPtr = _vm->getResourceAddress(rtImage, resId); assert(dataPtr); + getWizImageSpot(dataPtr, state, x, y); +} + +void Wiz::getWizImageSpot(uint8 *dataPtr, int state, int32 &x, int32 &y) { uint8 *spotPtr = _vm->findWrappedBlock(MKTAG('S','P','O','T'), dataPtr, state, 0); if (spotPtr) { x = READ_LE_UINT32(spotPtr + 0); @@ -2547,6 +2756,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; @@ -2565,9 +2779,14 @@ int Wiz::getWizImageStates(int resNum) { } int Wiz::isWizPixelNonTransparent(int resNum, int state, int x, int y, int flags) { - int ret = 0; uint8 *data = _vm->getResourceAddress(rtImage, resNum); assert(data); + + return isWizPixelNonTransparent(data, state, x, y, flags); +} + +int Wiz::isWizPixelNonTransparent(uint8 *data, int state, int x, int y, int flags) { + int ret = 0; uint8 *wizh = _vm->findWrappedBlock(MKTAG('W','I','Z','H'), data, state, 0); assert(wizh); int c = READ_LE_UINT32(wizh + 0x0); @@ -2591,19 +2810,20 @@ int Wiz::isWizPixelNonTransparent(int resNum, int state, int x, int y, int flags } break; case 1: - ret = isWizPixelNonTransparent(wizd, x, y, w, h, 1); + ret = isPixelNonTransparent(wizd, x, y, w, h, 1); break; #ifdef USE_RGB_COLOR 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); + ret = isPixelNonTransparent(wizd, x, y, w, h, 2); break; #endif default: @@ -2641,8 +2861,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..692ad76db5 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 { @@ -185,14 +220,19 @@ public: void remapWizImagePal(const WizParameters *params); void getWizImageDim(int resNum, int state, int32 &w, int32 &h); + void getWizImageDim(uint8 *dataPtr, int state, int32 &w, int32 &h); int getWizImageStates(int resnum); + int getWizImageStates(const uint8 *ptr); int isWizPixelNonTransparent(int resnum, int state, int x, int y, int flags); + int isWizPixelNonTransparent(uint8 *data, int state, int x, int y, int flags); + int isPixelNonTransparent(const uint8 *data, int x, int y, int w, int h, uint8 bitdepth); uint16 getWizPixelColor(int resnum, int state, int x, int y); int getWizImageData(int resNum, int state, int type); void flushWizBuffer(); void getWizImageSpot(int resId, int state, int32 &x, int32 &y); + void getWizImageSpot(uint8 *data, int state, int32 &x, int32 &y); void loadWizCursor(int resId, int palette); void captureWizImage(int resNum, const Common::Rect& r, bool frontBuffer, int compType); @@ -202,7 +242,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 +251,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); @@ -230,7 +277,6 @@ public: template<int type> static void write8BitColor(uint8 *dst, const uint8 *src, int dstType, const uint8 *palPtr, const uint8 *xmapPtr, uint8 bitDepth); static void writeColor(uint8 *dstPtr, int dstType, uint16 color); - int isWizPixelNonTransparent(const uint8 *data, int x, int y, int w, int h, uint8 bitdepth); uint16 getWizPixelColor(const uint8 *data, int x, int y, int w, int h, uint8 bitDepth, uint16 color); uint16 getRawWizPixelColor(const uint8 *data, int x, int y, int w, int h, uint8 bitDepth, uint16 color); void computeWizHistogram(uint32 *histogram, const uint8 *data, const Common::Rect& rCapt); 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..1f8a85b8c3 100644 --- a/engines/scumm/scumm.cpp +++ b/engines/scumm/scumm.cpp @@ -66,6 +66,7 @@ #include "scumm/players/player_v5m.h" #include "scumm/resource.h" #include "scumm/he/resource_he.h" +#include "scumm/he/moonbase/moonbase.h" #include "scumm/scumm_v0.h" #include "scumm/scumm_v8.h" #include "scumm/sound.h" @@ -733,7 +734,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 +833,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; } @@ -874,7 +882,7 @@ ScummEngine_v90he::ScummEngine_v90he(OSystem *syst, const DetectorResult &dr) memset(_videoParams.filename, 0, sizeof(_videoParams.filename)); _videoParams.status = 0; _videoParams.flags = 0; - _videoParams.unk2 = 0; + _videoParams.number = 0; _videoParams.wizResNum = 0; VAR_NUM_SPRITE_GROUPS = 0xFF; 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..9f4b6c21c6 100644 --- a/engines/sky/control.cpp +++ b/engines/sky/control.cpp @@ -167,7 +167,7 @@ ControlStatus::~ControlStatus() { void ControlStatus::setToText(const char *newText) { char tmpLine[256]; - strcpy(tmpLine, newText); + Common::strlcpy(tmpLine, newText, 256); if (_textData) { _statusText->flushForRedraw(); free(_textData); @@ -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; @@ -398,7 +402,8 @@ void Control::animClick(ConResource *pButton) { void Control::drawMainPanel() { memset(_screenBuf, 0, GAME_SCREEN_WIDTH * FULL_SCREEN_HEIGHT); _system->copyRectToScreen(_screenBuf, GAME_SCREEN_WIDTH, 0, 0, GAME_SCREEN_WIDTH, FULL_SCREEN_HEIGHT); - _controlPanel->drawToScreen(NO_MASK); + if (_controlPanel) + _controlPanel->drawToScreen(NO_MASK); _exitButton->drawToScreen(NO_MASK); _savePanButton->drawToScreen(NO_MASK); _restorePanButton->drawToScreen(NO_MASK); @@ -525,8 +530,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 +1572,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 +1599,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 +1615,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/sword1/resman.cpp b/engines/sword1/resman.cpp index 0a0324a67c..2f8b37d21c 100644 --- a/engines/sword1/resman.cpp +++ b/engines/sword1/resman.cpp @@ -327,13 +327,12 @@ Common::File *ResMan::resFile(uint32 id) { Clu *closeClu = _openCluStart; _openCluStart = _openCluStart->nextOpen; - if (closeClu) { - if (closeClu->file) - closeClu->file->close(); - delete closeClu->file; - closeClu->file = NULL; - closeClu->nextOpen = NULL; - } + if (closeClu->file) + closeClu->file->close(); + delete closeClu->file; + closeClu->file = NULL; + closeClu->nextOpen = NULL; + _openClus--; } } 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/bmv.cpp b/engines/tinsel/bmv.cpp index 22c3798fc6..cfe97e6ec1 100644 --- a/engines/tinsel/bmv.cpp +++ b/engines/tinsel/bmv.cpp @@ -567,8 +567,8 @@ void BMVPlayer::PlayBMV(CORO_PARAM, SCNHANDLE hFileStem, int myEscape) { assert(!bMovieOn); - strcpy(szMovieFile, (char *)LockMem(hFileStem)); - strcat(szMovieFile, BMOVIE_EXTENSION); + Common::strlcpy(szMovieFile, (char *)LockMem(hFileStem), 14); + Common::strlcat(szMovieFile, BMOVIE_EXTENSION, 14); assert(strlen(szMovieFile) <= 12); diff --git a/engines/tinsel/detection.cpp b/engines/tinsel/detection.cpp index 2fde6e788a..c44f1f4ef3 100644 --- a/engines/tinsel/detection.cpp +++ b/engines/tinsel/detection.cpp @@ -235,7 +235,7 @@ const ADGameDescription *TinselMetaEngine::fallbackDetect(const FileMap &allFile for (fileDesc = g->desc.filesDescriptions; fileDesc->fileName; fileDesc++) { // Get the next filename, stripping off any '1' suffix character char tempFilename[50]; - strcpy(tempFilename, fileDesc->fileName); + Common::strlcpy(tempFilename, fileDesc->fileName, 50); char *pOne = strchr(tempFilename, '1'); if (pOne) { do { @@ -275,7 +275,7 @@ const ADGameDescription *TinselMetaEngine::fallbackDetect(const FileMap &allFile for (fileDesc = g->desc.filesDescriptions; fileDesc->fileName; fileDesc++) { // Get the next filename, stripping off any '1' suffix character char tempFilename[50]; - strcpy(tempFilename, fileDesc->fileName); + Common::strlcpy(tempFilename, fileDesc->fileName, 50); char *pOne = strchr(tempFilename, '1'); if (pOne) { do { diff --git a/engines/tinsel/dialogs.cpp b/engines/tinsel/dialogs.cpp index a84dad942c..ad20253b9c 100644 --- a/engines/tinsel/dialogs.cpp +++ b/engines/tinsel/dialogs.cpp @@ -1671,10 +1671,10 @@ static void Select(int i, bool force) { #else // Current description with cursor appended if (cd.box[i].boxText != NULL) { - strcpy(g_sedit, cd.box[i].boxText); - strcat(g_sedit, sCursor); + Common::strlcpy(g_sedit, cd.box[i].boxText, SG_DESC_LEN+2); + Common::strlcat(g_sedit, sCursor, SG_DESC_LEN+2); } else { - strcpy(g_sedit, sCursor); + Common::strlcpy(g_sedit, sCursor, SG_DESC_LEN+2); } #endif @@ -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/tinsel/handle.cpp b/engines/tinsel/handle.cpp index 62d244e449..9ffd477c4a 100644 --- a/engines/tinsel/handle.cpp +++ b/engines/tinsel/handle.cpp @@ -258,7 +258,7 @@ void LoadExtraGraphData(SCNHANDLE start, SCNHANDLE next) { } void SetCdPlaySceneDetails(int fileNum, const char *fileName) { - strcpy(g_szCdPlayFile, fileName); + Common::strlcpy(g_szCdPlayFile, fileName, 100); } void SetCdPlayHandle(int fileNum) { diff --git a/engines/tinsel/saveload.cpp b/engines/tinsel/saveload.cpp index 88cd80b78a..226cbb51c0 100644 --- a/engines/tinsel/saveload.cpp +++ b/engines/tinsel/saveload.cpp @@ -563,7 +563,7 @@ static void DoSave() { while (1) { Common::String fname = _vm->getSavegameFilename(ano); - strcpy(tmpName, fname.c_str()); + Common::strlcpy(tmpName, fname.c_str(), FNAMELEN); for (i = 0; i < g_numSfiles; i++) if (!strcmp(g_savedFiles[i].name, tmpName)) 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 907a1ec435..eda28df159 100644 --- a/engines/wage/design.cpp +++ b/engines/wage/design.cpp @@ -45,20 +45,22 @@ * */ +#include "graphics/managed_surface.h" #include "graphics/primitives.h" -#include "wage/wage.h" + +#include "wage/macwindowmanager.h" #include "wage/design.h" namespace Wage { struct PlotData { - Graphics::Surface *surface; + Graphics::ManagedSurface *surface; Patterns *patterns; uint fillType; int thickness; Design *design; - PlotData(Graphics::Surface *s, Patterns *p, int f, int t, Design *d) : + PlotData(Graphics::ManagedSurface *s, Patterns *p, int f, int t, Design *d) : surface(s), patterns(p), fillType(f), thickness(t), design(d) {} }; @@ -83,7 +85,7 @@ Design::~Design() { delete _surface; } -void Design::paint(Graphics::Surface *surface, Patterns &patterns, int x, int y) { +void Design::paint(Graphics::ManagedSurface *surface, Patterns &patterns, int x, int y) { bool needRender = false; if (_surface == NULL) { @@ -96,11 +98,10 @@ void Design::paint(Graphics::Surface *surface, Patterns &patterns, int x, int y) } _bounds->debugPrint(4, "Calculated bounds:"); - _surface = new Graphics::Surface; + _surface = new Graphics::ManagedSurface; _surface->create(_bounds->width(), _bounds->height(), Graphics::PixelFormat::createFormatCLUT8()); - Common::Rect r(0, 0, _bounds->width(), _bounds->height()); - _surface->fillRect(r, kColorGreen); + _surface->clear(kColorGreen); needRender = true; } @@ -133,16 +134,10 @@ void Design::paint(Graphics::Surface *surface, Patterns &patterns, int x, int y) if (_bounds->width() && _bounds->height()) { const int padding = 3; - for (int i = padding; i < _bounds->height() - 2 * padding; i++) { - const byte *src = (const byte *)_surface->getBasePtr(padding, i); - byte *dst = (byte *)surface->getBasePtr(x + padding, y+i); - for (int j = padding; j < _bounds->width() - 2 * padding; j++) { - if (*src != kColorGreen) - *dst = *src; - src++; - dst++; - } - } + Common::Rect from(padding, padding, _bounds->width() - 2 * padding, _bounds->height() - 2 * padding); + Common::Rect to(from); + to.moveTo(x, y); + surface->transBlitFrom(*_surface, from, to, kColorGreen); } } @@ -215,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++) @@ -240,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++) @@ -269,7 +264,7 @@ void drawPixelPlain(int x, int y, int color, void *data) { *((byte *)p->surface->getBasePtr(x, y)) = (byte)color; } -void Design::drawRect(Graphics::Surface *surface, Common::ReadStream &in, +void Design::drawRect(Graphics::ManagedSurface *surface, Common::ReadStream &in, Patterns &patterns, byte fillType, byte borderThickness, byte borderFillType) { int16 y1 = in.readSint16BE(); int16 x1 = in.readSint16BE(); @@ -298,7 +293,7 @@ void Design::drawRect(Graphics::Surface *surface, Common::ReadStream &in, } } -void Design::drawRoundRect(Graphics::Surface *surface, Common::ReadStream &in, +void Design::drawRoundRect(Graphics::ManagedSurface *surface, Common::ReadStream &in, Patterns &patterns, byte fillType, byte borderThickness, byte borderFillType) { int16 y1 = in.readSint16BE(); int16 x1 = in.readSint16BE(); @@ -324,7 +319,7 @@ void Design::drawRoundRect(Graphics::Surface *surface, Common::ReadStream &in, Graphics::drawRoundRect(r, arc / 2, kColorBlack, false, drawPixel, &pd); } -void Design::drawPolygon(Graphics::Surface *surface, Common::ReadStream &in, +void Design::drawPolygon(Graphics::ManagedSurface *surface, Common::ReadStream &in, Patterns &patterns, byte fillType, byte borderThickness, byte borderFillType) { byte ignored = in.readSint16BE(); // ignored @@ -401,7 +396,7 @@ void Design::drawPolygon(Graphics::Surface *surface, Common::ReadStream &in, free(ypoints); } -void Design::drawOval(Graphics::Surface *surface, Common::ReadStream &in, +void Design::drawOval(Graphics::ManagedSurface *surface, Common::ReadStream &in, Patterns &patterns, byte fillType, byte borderThickness, byte borderFillType) { int16 y1 = in.readSint16BE(); int16 x1 = in.readSint16BE(); @@ -419,7 +414,7 @@ void Design::drawOval(Graphics::Surface *surface, Common::ReadStream &in, Graphics::drawEllipse(x1, y1, x2-1, y2-1, kColorBlack, false, drawPixel, &pd); } -void Design::drawBitmap(Graphics::Surface *surface, Common::SeekableReadStream &in) { +void Design::drawBitmap(Graphics::ManagedSurface *surface, Common::SeekableReadStream &in) { int numBytes = in.readSint16BE(); int y1 = in.readSint16BE(); int x1 = in.readSint16BE(); @@ -427,7 +422,7 @@ void Design::drawBitmap(Graphics::Surface *surface, Common::SeekableReadStream & int x2 = in.readSint16BE(); int w = x2 - x1; int h = y2 - y1; - Graphics::Surface tmp; + Graphics::ManagedSurface tmp; tmp.create(w, h, Graphics::PixelFormat::createFormatCLUT8()); @@ -507,11 +502,11 @@ void Design::drawBitmap(Graphics::Surface *surface, Common::SeekableReadStream & tmp.free(); } -void Design::drawRect(Graphics::Surface *surface, Common::Rect &rect, int thickness, int color, Patterns &patterns, byte fillType) { +void Design::drawRect(Graphics::ManagedSurface *surface, Common::Rect &rect, int thickness, int color, Patterns &patterns, byte fillType) { drawRect(surface, rect.left, rect.top, rect.right, rect.bottom, thickness, color, patterns, fillType); } -void Design::drawRect(Graphics::Surface *surface, int x1, int y1, int x2, int y2, int thickness, int color, Patterns &patterns, byte fillType) { +void Design::drawRect(Graphics::ManagedSurface *surface, int x1, int y1, int x2, int y2, int thickness, int color, Patterns &patterns, byte fillType) { PlotData pd(surface, &patterns, fillType, thickness, nullptr); Graphics::drawLine(x1, y1, x2, y1, kColorBlack, drawPixel, &pd); @@ -521,32 +516,32 @@ void Design::drawRect(Graphics::Surface *surface, int x1, int y1, int x2, int y2 } -void Design::drawFilledRect(Graphics::Surface *surface, Common::Rect &rect, int color, Patterns &patterns, byte fillType) { +void Design::drawFilledRect(Graphics::ManagedSurface *surface, Common::Rect &rect, int color, Patterns &patterns, byte fillType) { PlotData pd(surface, &patterns, fillType, 1, nullptr); for (int y = rect.top; y <= rect.bottom; y++) Graphics::drawHLine(rect.left, rect.right, y, color, drawPixel, &pd); } -void Design::drawFilledRoundRect(Graphics::Surface *surface, Common::Rect &rect, int arc, int color, Patterns &patterns, byte fillType) { +void Design::drawFilledRoundRect(Graphics::ManagedSurface *surface, Common::Rect &rect, int arc, int color, Patterns &patterns, byte fillType) { PlotData pd(surface, &patterns, fillType, 1, nullptr); Graphics::drawRoundRect(rect, arc, color, true, drawPixel, &pd); } -void Design::drawHLine(Graphics::Surface *surface, int x1, int x2, int y, int thickness, int color, Patterns &patterns, byte fillType) { +void Design::drawHLine(Graphics::ManagedSurface *surface, int x1, int x2, int y, int thickness, int color, Patterns &patterns, byte fillType) { PlotData pd(surface, &patterns, fillType, thickness, nullptr); Graphics::drawHLine(x1, x2, y, color, drawPixel, &pd); } -void Design::drawVLine(Graphics::Surface *surface, int x, int y1, int y2, int thickness, int color, Patterns &patterns, byte fillType) { +void Design::drawVLine(Graphics::ManagedSurface *surface, int x, int y1, int y2, int thickness, int color, Patterns &patterns, byte fillType) { PlotData pd(surface, &patterns, fillType, thickness, nullptr); Graphics::drawVLine(x, y1, y2, color, drawPixel, &pd); } -FloodFill::FloodFill(Graphics::Surface *surface, byte color1, byte color2) { +FloodFill::FloodFill(Graphics::ManagedSurface *surface, byte color1, byte color2) { _surface = surface; _color1 = color1; _color2 = color2; diff --git a/engines/wage/design.h b/engines/wage/design.h index e8f42f4e04..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/surface.h" #include "common/memstream.h" #include "common/rect.h" +#include "wage/macwindowmanager.h" + namespace Wage { class Design { @@ -67,14 +68,14 @@ public: return _bounds; } - void paint(Graphics::Surface *canvas, Patterns &patterns, int x, int y); + void paint(Graphics::ManagedSurface *canvas, Patterns &patterns, int x, int y); bool isPointOpaque(int x, int y); - static void drawRect(Graphics::Surface *surface, Common::Rect &rect, int thickness, int color, Patterns &patterns, byte fillType); - static void drawRect(Graphics::Surface *surface, int x1, int y1, int x2, int y2, int thickness, int color, Patterns &patterns, byte fillType); - static void drawFilledRect(Graphics::Surface *surface, Common::Rect &rect, int color, Patterns &patterns, byte fillType); - static void drawFilledRoundRect(Graphics::Surface *surface, Common::Rect &rect, int arc, int color, Patterns &patterns, byte fillType); - static void drawHLine(Graphics::Surface *surface, int x1, int x2, int y, int thickness, int color, Patterns &patterns, byte fillType); - static void drawVLine(Graphics::Surface *surface, int x, int y1, int y2, int thickness, int color, Patterns &patterns, byte fillType); + static void drawRect(Graphics::ManagedSurface *surface, Common::Rect &rect, int thickness, int color, Patterns &patterns, byte fillType); + static void drawRect(Graphics::ManagedSurface *surface, int x1, int y1, int x2, int y2, int thickness, int color, Patterns &patterns, byte fillType); + static void drawFilledRect(Graphics::ManagedSurface *surface, Common::Rect &rect, int color, Patterns &patterns, byte fillType); + static void drawFilledRoundRect(Graphics::ManagedSurface *surface, Common::Rect &rect, int arc, int color, Patterns &patterns, byte fillType); + static void drawHLine(Graphics::ManagedSurface *surface, int x1, int x2, int y, int thickness, int color, Patterns &patterns, byte fillType); + static void drawVLine(Graphics::ManagedSurface *surface, int x, int y1, int y2, int thickness, int color, Patterns &patterns, byte fillType); bool isBoundsCalculation() { return _boundsCalculationMode; } void adjustBounds(int16 x, int16 y); @@ -83,32 +84,32 @@ private: byte *_data; int _len; Common::Rect *_bounds; - Graphics::Surface *_surface; + Graphics::ManagedSurface *_surface; bool _boundsCalculationMode; private: void render(Patterns &patterns); - void drawRect(Graphics::Surface *surface, Common::ReadStream &in, + void drawRect(Graphics::ManagedSurface *surface, Common::ReadStream &in, Patterns &patterns, byte fillType, byte borderThickness, byte borderFillType); - void drawRoundRect(Graphics::Surface *surface, Common::ReadStream &in, + void drawRoundRect(Graphics::ManagedSurface *surface, Common::ReadStream &in, Patterns &patterns, byte fillType, byte borderThickness, byte borderFillType); - void drawPolygon(Graphics::Surface *surface, Common::ReadStream &in, + void drawPolygon(Graphics::ManagedSurface *surface, Common::ReadStream &in, Patterns &patterns, byte fillType, byte borderThickness, byte borderFillType); - void drawOval(Graphics::Surface *surface, Common::ReadStream &in, + void drawOval(Graphics::ManagedSurface *surface, Common::ReadStream &in, Patterns &patterns, byte fillType, byte borderThickness, byte borderFillType); - void drawBitmap(Graphics::Surface *surface, Common::SeekableReadStream &in); + void drawBitmap(Graphics::ManagedSurface *surface, Common::SeekableReadStream &in); }; class FloodFill { public: - FloodFill(Graphics::Surface *surface, byte color1, byte color2); + FloodFill(Graphics::ManagedSurface *surface, byte color1, byte color2); ~FloodFill(); void addSeed(int x, int y); void fill(); private: Common::List<Common::Point *> _queue; - Graphics::Surface *_surface; + Graphics::ManagedSurface *_surface; byte _color1, _color2; byte *_visited; int _w, _h; 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/dialog.h b/engines/wage/dialog.h index c5878acc95..ec99fc06b2 100644 --- a/engines/wage/dialog.h +++ b/engines/wage/dialog.h @@ -74,7 +74,7 @@ public: private: Gui *_gui; - Graphics::Surface _tempSurface; + Graphics::ManagedSurface _tempSurface; Common::Rect _bbox; Common::String _text; diff --git a/engines/wage/entities.cpp b/engines/wage/entities.cpp index adb053868a..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 { @@ -134,20 +135,20 @@ Scene::~Scene() { delete _textBounds; } -void Scene::paint(Graphics::Surface *surface, int x, int y) { +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 33cf087322..9e706f0d58 100644 --- a/engines/wage/entities.h +++ b/engines/wage/entities.h @@ -49,7 +49,7 @@ #define WAGE_ENTITIES_H namespace Graphics { - struct Surface; + class ManagedSurface; } namespace Wage { @@ -322,11 +322,13 @@ 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); } - void paint(Graphics::Surface *screen, int x, int y); + void paint(Graphics::ManagedSurface *screen, int x, int y); const char *getFontName(); }; diff --git a/engines/wage/gui-console.cpp b/engines/wage/gui-console.cpp index ab5df637ec..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); @@ -142,7 +144,7 @@ void Gui::flowText(Common::String &str) { draw(); } -void Gui::renderConsole(Graphics::Surface *g, Common::Rect &r) { +void Gui::renderConsole(Graphics::ManagedSurface *g, const Common::Rect &r) { bool fullRedraw = _consoleFullRedraw; bool textReflow = false; int surfW = r.width() + kConWOverlap * 2; @@ -150,7 +152,6 @@ void Gui::renderConsole(Graphics::Surface *g, Common::Rect &r) { Common::Rect boundsR(kConWOverlap - kConOverscan, kConHOverlap - kConOverscan, r.width() + kConWOverlap + kConOverscan, r.height() + kConHOverlap + kConOverscan); - Common::Rect fullR(0, 0, surfW, surfH); if (_console.w != surfW || _console.h != surfH) { if (_console.w != surfW) @@ -163,7 +164,7 @@ void Gui::renderConsole(Graphics::Surface *g, Common::Rect &r) { } if (fullRedraw) - _console.fillRect(fullR, kColorWhite); + _console.clear(kColorWhite); const Graphics::Font *font = getConsoleFont(); @@ -197,7 +198,7 @@ void Gui::renderConsole(Graphics::Surface *g, 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) { @@ -224,7 +225,7 @@ void Gui::renderConsole(Graphics::Surface *g, 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); @@ -243,7 +244,7 @@ void Gui::renderConsole(Graphics::Surface *g, 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); @@ -280,17 +281,13 @@ void Gui::renderConsole(Graphics::Surface *g, Common::Rect &r) { rr.bottom = _screen.h - 1; g->copyRectToSurface(_console, xcon, ycon, boundsR); - g_system->copyRectToScreen(g->getBasePtr(rr.left, rr.top), g->pitch, rr.left, rr.top, rr.width(), rr.height()); } void Gui::drawInput() { if (!_screen.getPixels()) return; - if (_sceneIsActive) { - _sceneIsActive = false; - _bordersDirty = true; - } + _wm.setActive(_consoleWindow->getId()); _out.pop_back(); _lines.pop_back(); @@ -302,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; @@ -427,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 00b7e24735..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, 0x7f, 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,28 +141,39 @@ Gui::Gui(WageEngine *engine) { _inputTextLineNum = 0; - g_system->getPaletteManager()->setPalette(palette, 0, 4); + 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(); + + _sceneWindow = _wm.addWindow(false, false, false); + _sceneWindow->setCallback(sceneWindowCallback, this); - _menu = new Menu(this); + _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() { @@ -202,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()); @@ -267,434 +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; + _scene->paint(_sceneWindow->getSurface(), 0, 0); + _sceneWindow->setDirty(true); _sceneDirty = true; _consoleDirty = true; - _menuDirty = true; + _menu->setDirty(true); _consoleFullRedraw = true; - - _scene->paint(&_screen, _scene->_designBounds->left, _scene->_designBounds->top); - - _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); - - paintBorder(&_screen, _sceneArea, kWindowScene); -} - -// Render console -void Gui::drawConsole() { - if (!_consoleDirty && !_consoleFullRedraw && !_bordersDirty && !_sceneDirty) - return; - - renderConsole(&_screen, _consoleTextArea); - paintBorder(&_screen, _consoleTextArea, kWindowConsole); } -void Gui::drawBox(Graphics::Surface *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::Surface *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::Surface *surface = (Graphics::Surface *)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::Surface *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 c1f8b83a11..ba1bb5ef3b 100644 --- a/engines/wage/gui.h +++ b/engines/wage/gui.h @@ -50,36 +50,23 @@ #include "common/str-array.h" #include "graphics/font.h" -#include "graphics/fontman.h" -#include "graphics/surface.h" +#include "graphics/managed_surface.h" +#include "common/events.h" #include "common/rect.h" #include "wage/macwindow.h" +#include "wage/macwindowmanager.h" 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); @@ -88,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(); @@ -109,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::Surface *g, Common::Rect &r, WindowType windowType, int highlightedPart = kBorderNone, - float scrollPos = 0.0, float scrollSize = 0.0); - void renderConsole(Graphics::Surface *g, Common::Rect &r); - void drawBox(Graphics::Surface *g, int x, int y, int w, int h); - void fillRect(Graphics::Surface *g, int x, int y, int w, int h, int color = kColorBlack); - void loadFonts(); + void renderConsole(Graphics::ManagedSurface *g, const Common::Rect &r); void flowText(Common::String &str); const Graphics::Font *getConsoleFont(); const Graphics::Font *getTitleFont(); @@ -131,29 +109,27 @@ private: void updateTextSelection(int x, int y); public: - Graphics::Surface _screen; + 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::Surface _console; + Graphics::ManagedSurface _console; Menu *_menu; - Scene *_scene; bool _sceneDirty; bool _consoleDirty; - bool _bordersDirty; Common::StringArray _out; Common::StringArray _lines; @@ -162,10 +138,6 @@ private: uint _consoleNumLines; bool _consoleFullRedraw; - Common::Rect _sceneArea; - bool _sceneIsActive; - bool _cursorIsArrow; - bool _inTextSelection; int _selectionStartX; int _selectionStartY; @@ -176,6 +148,9 @@ private: Common::String _undobuffer; int _inputTextLineNum; + + int _commandsMenuId; + int _weaponsMenuId; }; } // End of namespace Wage diff --git a/engines/wage/menu.cpp b/engines/wage/macmenu.cpp index 12ef8c2219..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::Surface *s = &_gui->_screen; + Graphics::ManagedSurface *s = &_screen; int tx = x, ty = y; if (!menu->subitems[i]->enabled) { @@ -406,7 +392,7 @@ void Menu::renderSubmenu(MenuItem *menu) { ty = 0; accelX -= x; - _tempSurface.fillRect(Common::Rect(0, 0, _tempSurface.w, _tempSurface.h), kColorGreen); + _tempSurface.clear(kColorGreen); } _font->drawString(s, text, tx, ty, r->width(), color); @@ -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 3550356bc6..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,29 +91,43 @@ 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::Surface _screenCopy; - Graphics::Surface _tempSurface; + Graphics::ManagedSurface _screen; + Graphics::ManagedSurface _tempSurface; private: const Graphics::Font *getMenuFont(); @@ -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 a94558900a..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; @@ -74,35 +97,59 @@ void MacWindow::setActive(bool active) { } void MacWindow::resize(int w, int h) { + if (_surface.w == w && _surface.h == h) + return; + _surface.free(); _surface.create(w, h, Graphics::PixelFormat::createFormatCLUT8()); _borderSurface.free(); - _borderSurface.create(w + 2 * kBorderWidth, h + 2 * kBorderWidth, Graphics::PixelFormat::createFormatCLUT8()); + _borderSurface.create(w, h, Graphics::PixelFormat::createFormatCLUT8()); + _composeSurface.free(); + _composeSurface.create(w, h, Graphics::PixelFormat::createFormatCLUT8()); _dims.setWidth(w); _dims.setHeight(h); - _borderDims.setWidth(w + 2 * kBorderWidth); - _borderDims.setHeight(h + 2 * kBorderWidth); - move(_dims.left, _dims.top); // Update _borderDims position + updateInnerDims(); + + _contentIsDirty = true; + _borderIsDirty = true; } void MacWindow::move(int x, int y) { + if (_dims.left == x && _dims.top == y) + return; + _dims.moveTo(x, y); - _borderDims.moveTo(x - kBorderWidth, y - kBorderWidth); + updateInnerDims(); + + _contentIsDirty = true; } -void MacWindow::draw(Graphics::Surface *g, bool forceRedraw) { +void MacWindow::setDimensions(const Common::Rect &r) { + resize(r.width(), r.height()); + _dims.moveTo(r.left, r.top); + updateInnerDims(); + + _contentIsDirty = true; +} + +bool MacWindow::draw(Graphics::ManagedSurface *g, bool forceRedraw) { + if (!_borderIsDirty && !_contentIsDirty && !forceRedraw) + return false; + if (_borderIsDirty || forceRedraw) drawBorder(); -} -const Graphics::Font *MacWindow::getTitleFont() { - return ((WageEngine *)g_engine)->_gui->getFont("Chicago-12", Graphics::FontManager::kBigGUIFont); -} + _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); -bool MacWindow::builtInFonts() { - return ((WageEngine *)g_engine)->_gui->builtInFonts(); + return true; } #define ARROW_W 12 @@ -116,7 +163,7 @@ const int arrowPixels[ARROW_H][ARROW_W] = { {1,1,1,1,1,1,1,1,1,1,1,1}}; static void drawPixelInverted(int x, int y, int color, void *data) { - Graphics::Surface *surface = (Graphics::Surface *)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); @@ -125,10 +172,15 @@ static void drawPixelInverted(int x, int y, int color, void *data) { } } +void MacWindow::updateInnerDims() { + _innerDims = _dims; + _innerDims.grow(-kBorderWidth); +} + void MacWindow::drawBorder() { _borderIsDirty = false; - bool active = _active, scrollable = _scrollable, closeable = _active, drawTitle = _title.empty(); + bool active = _active, scrollable = _scrollable, closeable = _active, drawTitle = !_title.empty(); const int size = kBorderWidth; int x = 0; int y = 0; @@ -136,7 +188,11 @@ void MacWindow::drawBorder() { int height = _borderSurface.h; Graphics::ManagedSurface *g = &_borderSurface; - g->fillRect(_borderDims, kColorGreen2); + // We draw rect with outer kColorGreen2 and inner kColorGreen, so on 2 passes we cut out + // scene by external shape of the border + int sz = kBorderWidth / 2; + g->clear(kColorGreen2); + g->fillRect(Common::Rect(sz, sz, width - sz, height - sz), kColorGreen); drawBox(g, x, y, size, size); drawBox(g, x + width - size - 1, y, size, size); @@ -148,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; @@ -162,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++) { @@ -182,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); } @@ -191,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; @@ -202,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); @@ -215,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 6af2db2718..4c6e9efeff 100644 --- a/engines/wage/macwindow.h +++ b/engines/wage/macwindow.h @@ -52,54 +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 draw(Graphics::Surface *g, bool forceRedraw = false); + void setDimensions(const Common::Rect &r); + 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 _borderDims; + Common::Rect _innerDims; Common::String _title; }; diff --git a/engines/wage/macwindowmanager.cpp b/engines/wage/macwindowmanager.cpp index 14c3f236e8..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/surface.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::Surface *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 0c35356863..13f85cddd4 100644 --- a/engines/wage/macwindowmanager.h +++ b/engines/wage/macwindowmanager.h @@ -48,28 +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::Surface *g); + void setFullRefresh(bool redraw) { _fullRefresh = true; } + + 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: - Common::List<MacWindow *> _windowStack; - Common::Array<MacWindow *> _windows; + void drawDesktop(); + void loadFonts(); + +private: + 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/engines/wintermute/ui/ui_window.cpp b/engines/wintermute/ui/ui_window.cpp index 9f3cdeaaa3..34341d1db2 100644 --- a/engines/wintermute/ui/ui_window.cpp +++ b/engines/wintermute/ui/ui_window.cpp @@ -139,13 +139,12 @@ bool UIWindow::display(int offsetX, int offsetY) { _shieldButton->setListener(this, _shieldButton, 0); _shieldButton->_parent = this; } - if (_shieldButton) { - _shieldButton->_posX = _shieldButton->_posY = 0; - _shieldButton->setWidth(_gameRef->_renderer->getWidth()); - _shieldButton->setHeight(_gameRef->_renderer->getHeight()); - _shieldButton->display(); - } + _shieldButton->_posX = _shieldButton->_posY = 0; + _shieldButton->setWidth(_gameRef->_renderer->getWidth()); + _shieldButton->setHeight(_gameRef->_renderer->getHeight()); + + _shieldButton->display(); } if (!_visible) { 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 |