diff options
116 files changed, 2904 insertions, 772 deletions
diff --git a/audio/audiostream.h b/audio/audiostream.h index 9c28e4d67f..801f13d9d9 100644 --- a/audio/audiostream.h +++ b/audio/audiostream.h @@ -20,8 +20,8 @@ * */ -#ifndef SOUND_AUDIOSTREAM_H -#define SOUND_AUDIOSTREAM_H +#ifndef AUDIO_AUDIOSTREAM_H +#define AUDIO_AUDIOSTREAM_H #include "common/ptr.h" #include "common/scummsys.h" diff --git a/audio/decoders/aac.h b/audio/decoders/aac.h index 68e322c844..9ad78b28a4 100644 --- a/audio/decoders/aac.h +++ b/audio/decoders/aac.h @@ -26,8 +26,8 @@ * - groovie */ -#ifndef SOUND_AAC_H -#define SOUND_AAC_H +#ifndef AUDIO_AAC_H +#define AUDIO_AAC_H #include "common/scummsys.h" #include "common/types.h" @@ -59,4 +59,4 @@ Codec *makeAACDecoder( } // End of namespace Audio #endif // #ifdef USE_FAAD -#endif // #ifndef SOUND_AAC_H +#endif // #ifndef AUDIO_AAC_H diff --git a/audio/decoders/adpcm.h b/audio/decoders/adpcm.h index 1dd4d510df..ac8d529917 100644 --- a/audio/decoders/adpcm.h +++ b/audio/decoders/adpcm.h @@ -31,8 +31,8 @@ * - tinsel */ -#ifndef SOUND_ADPCM_H -#define SOUND_ADPCM_H +#ifndef AUDIO_ADPCM_H +#define AUDIO_ADPCM_H #include "common/scummsys.h" #include "common/types.h" diff --git a/audio/decoders/adpcm_intern.h b/audio/decoders/adpcm_intern.h index 38514d7fca..f7162f5f2a 100644 --- a/audio/decoders/adpcm_intern.h +++ b/audio/decoders/adpcm_intern.h @@ -28,8 +28,8 @@ * ADPCM decoder implementations. */ -#ifndef SOUND_ADPCM_INTERN_H -#define SOUND_ADPCM_INTERN_H +#ifndef AUDIO_ADPCM_INTERN_H +#define AUDIO_ADPCM_INTERN_H #include "audio/audiostream.h" #include "common/endian.h" diff --git a/audio/decoders/aiff.h b/audio/decoders/aiff.h index 558a018f57..59664bb85a 100644 --- a/audio/decoders/aiff.h +++ b/audio/decoders/aiff.h @@ -28,8 +28,8 @@ * - sword1 */ -#ifndef SOUND_AIFF_H -#define SOUND_AIFF_H +#ifndef AUDIO_AIFF_H +#define AUDIO_AIFF_H #include "common/scummsys.h" #include "common/types.h" diff --git a/audio/decoders/flac.h b/audio/decoders/flac.h index 3182b26425..a90675cc20 100644 --- a/audio/decoders/flac.h +++ b/audio/decoders/flac.h @@ -37,8 +37,8 @@ * - tucker */ -#ifndef SOUND_FLAC_H -#define SOUND_FLAC_H +#ifndef AUDIO_FLAC_H +#define AUDIO_FLAC_H #include "common/scummsys.h" #include "common/types.h" @@ -68,4 +68,4 @@ SeekableAudioStream *makeFLACStream( } // End of namespace Audio #endif // #ifdef USE_FLAC -#endif // #ifndef SOUND_FLAC_H +#endif // #ifndef AUDIO_FLAC_H diff --git a/audio/decoders/iff_sound.h b/audio/decoders/iff_sound.h index b266e629a1..28b2c67227 100644 --- a/audio/decoders/iff_sound.h +++ b/audio/decoders/iff_sound.h @@ -26,8 +26,8 @@ * - parallaction */ -#ifndef SOUND_IFF_H -#define SOUND_IFF_H +#ifndef AUDIO_IFF_H +#define AUDIO_IFF_H namespace Common { class ReadStream; diff --git a/audio/decoders/mac_snd.h b/audio/decoders/mac_snd.h index cbbd82bbe0..7e960058ae 100644 --- a/audio/decoders/mac_snd.h +++ b/audio/decoders/mac_snd.h @@ -26,8 +26,8 @@ * - sci */ -#ifndef SOUND_MAC_SND_H -#define SOUND_MAC_SND_H +#ifndef AUDIO_MAC_SND_H +#define AUDIO_MAC_SND_H #include "common/scummsys.h" #include "common/types.h" diff --git a/audio/decoders/mp3.h b/audio/decoders/mp3.h index 86ddc599ea..cb0cc8375d 100644 --- a/audio/decoders/mp3.h +++ b/audio/decoders/mp3.h @@ -38,8 +38,8 @@ * - tucker */ -#ifndef SOUND_MP3_H -#define SOUND_MP3_H +#ifndef AUDIO_MP3_H +#define AUDIO_MP3_H #include "common/scummsys.h" #include "common/types.h" @@ -69,4 +69,4 @@ SeekableAudioStream *makeMP3Stream( } // End of namespace Audio #endif // #ifdef USE_MAD -#endif // #ifndef SOUND_MP3_H +#endif // #ifndef AUDIO_MP3_H diff --git a/audio/decoders/raw.h b/audio/decoders/raw.h index 5a7897b688..5cbf2c9b79 100644 --- a/audio/decoders/raw.h +++ b/audio/decoders/raw.h @@ -20,8 +20,8 @@ * */ -#ifndef SOUND_RAW_H -#define SOUND_RAW_H +#ifndef AUDIO_RAW_H +#define AUDIO_RAW_H #include "common/scummsys.h" #include "common/types.h" diff --git a/audio/decoders/voc.h b/audio/decoders/voc.h index a920eac933..7d96d261b5 100644 --- a/audio/decoders/voc.h +++ b/audio/decoders/voc.h @@ -30,8 +30,8 @@ * - touche */ -#ifndef SOUND_VOC_H -#define SOUND_VOC_H +#ifndef AUDIO_VOC_H +#define AUDIO_VOC_H #include "common/scummsys.h" #include "common/types.h" diff --git a/audio/decoders/vorbis.h b/audio/decoders/vorbis.h index e3d989e9b8..9e7600af56 100644 --- a/audio/decoders/vorbis.h +++ b/audio/decoders/vorbis.h @@ -38,8 +38,8 @@ * - tucker */ -#ifndef SOUND_VORBIS_H -#define SOUND_VORBIS_H +#ifndef AUDIO_VORBIS_H +#define AUDIO_VORBIS_H #include "common/scummsys.h" #include "common/types.h" @@ -69,4 +69,4 @@ SeekableAudioStream *makeVorbisStream( } // End of namespace Audio #endif // #ifdef USE_VORBIS -#endif // #ifndef SOUND_VORBIS_H +#endif // #ifndef AUDIO_VORBIS_H diff --git a/audio/decoders/wave.h b/audio/decoders/wave.h index 6a34bc175a..c8ac7fe318 100644 --- a/audio/decoders/wave.h +++ b/audio/decoders/wave.h @@ -34,8 +34,8 @@ * - tucker */ -#ifndef SOUND_WAVE_H -#define SOUND_WAVE_H +#ifndef AUDIO_WAVE_H +#define AUDIO_WAVE_H #include "common/scummsys.h" #include "common/types.h" diff --git a/audio/fmopl.h b/audio/fmopl.h index f62587f557..323cc3d028 100644 --- a/audio/fmopl.h +++ b/audio/fmopl.h @@ -19,8 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef SOUND_FMOPL_H -#define SOUND_FMOPL_H +#ifndef AUDIO_FMOPL_H +#define AUDIO_FMOPL_H #include "common/scummsys.h" diff --git a/audio/mididrv.h b/audio/mididrv.h index cdf2943f2a..fb3e29bd60 100644 --- a/audio/mididrv.h +++ b/audio/mididrv.h @@ -20,8 +20,8 @@ * */ -#ifndef SOUND_MIDIDRV_H -#define SOUND_MIDIDRV_H +#ifndef AUDIO_MIDIDRV_H +#define AUDIO_MIDIDRV_H #include "common/scummsys.h" #include "common/str.h" diff --git a/audio/midiparser.h b/audio/midiparser.h index 9dff4b54ba..c935969e72 100644 --- a/audio/midiparser.h +++ b/audio/midiparser.h @@ -22,8 +22,8 @@ /// \brief Declarations related to the MidiParser class -#ifndef SOUND_MIDIPARSER_H -#define SOUND_MIDIPARSER_H +#ifndef AUDIO_MIDIPARSER_H +#define AUDIO_MIDIPARSER_H #include "common/scummsys.h" #include "common/endian.h" diff --git a/audio/midiplayer.h b/audio/midiplayer.h index e1da0bfb79..e58c78cafd 100644 --- a/audio/midiplayer.h +++ b/audio/midiplayer.h @@ -20,8 +20,8 @@ * */ -#ifndef SOUND_MIDIPLAYER_H -#define SOUND_MIDIPLAYER_H +#ifndef AUDIO_MIDIPLAYER_H +#define AUDIO_MIDIPLAYER_H #include "common/scummsys.h" #include "common/mutex.h" diff --git a/audio/mixer.h b/audio/mixer.h index de709e13fe..e38e052bef 100644 --- a/audio/mixer.h +++ b/audio/mixer.h @@ -20,8 +20,8 @@ * */ -#ifndef SOUND_MIXER_H -#define SOUND_MIXER_H +#ifndef AUDIO_MIXER_H +#define AUDIO_MIXER_H #include "common/types.h" #include "common/noncopyable.h" diff --git a/audio/mixer_intern.h b/audio/mixer_intern.h index dc361ce560..c6dfa55ada 100644 --- a/audio/mixer_intern.h +++ b/audio/mixer_intern.h @@ -20,8 +20,8 @@ * */ -#ifndef SOUND_MIXER_INTERN_H -#define SOUND_MIXER_INTERN_H +#ifndef AUDIO_MIXER_INTERN_H +#define AUDIO_MIXER_INTERN_H #include "common/scummsys.h" #include "common/mutex.h" diff --git a/audio/mods/infogrames.h b/audio/mods/infogrames.h index 307a26d4e1..8b246eebe7 100644 --- a/audio/mods/infogrames.h +++ b/audio/mods/infogrames.h @@ -26,8 +26,8 @@ * - gob */ -#ifndef SOUND_MODS_INFOGRAMES_H -#define SOUND_MODS_INFOGRAMES_H +#ifndef AUDIO_MODS_INFOGRAMES_H +#define AUDIO_MODS_INFOGRAMES_H #include "audio/mods/paula.h" diff --git a/audio/mods/maxtrax.cpp b/audio/mods/maxtrax.cpp index 344d678b76..8ed51ae5c3 100644 --- a/audio/mods/maxtrax.cpp +++ b/audio/mods/maxtrax.cpp @@ -29,7 +29,7 @@ #include "audio/mods/maxtrax.h" // test for engines using this class. -#if defined(SOUND_MODS_MAXTRAX_H) +#if defined(AUDIO_MODS_MAXTRAX_H) namespace { @@ -1034,4 +1034,4 @@ void MaxTrax::outPutScore(const Score &sc, int num) {} } // End of namespace Audio -#endif // #if defined(SOUND_MODS_MAXTRAX_H) +#endif // #if defined(AUDIO_MODS_MAXTRAX_H) diff --git a/audio/mods/maxtrax.h b/audio/mods/maxtrax.h index bef6669d2a..c61f4e1b50 100644 --- a/audio/mods/maxtrax.h +++ b/audio/mods/maxtrax.h @@ -24,8 +24,8 @@ #if !defined(ENABLE_KYRA) // normal Header Guard -#elif !defined SOUND_MODS_MAXTRAX_H -#define SOUND_MODS_MAXTRAX_H +#elif !defined AUDIO_MODS_MAXTRAX_H +#define AUDIO_MODS_MAXTRAX_H // #define MAXTRAX_HAS_MODULATION // #define MAXTRAX_HAS_MICROTONAL @@ -219,4 +219,4 @@ private: }; } // End of namespace Audio -#endif // !defined SOUND_MODS_MAXTRAX_H +#endif // !defined AUDIO_MODS_MAXTRAX_H diff --git a/audio/mods/module.h b/audio/mods/module.h index a57a89225e..eb7cbf260e 100644 --- a/audio/mods/module.h +++ b/audio/mods/module.h @@ -20,8 +20,8 @@ * */ -#ifndef SOUND_MODS_MODULE_H -#define SOUND_MODS_MODULE_H +#ifndef AUDIO_MODS_MODULE_H +#define AUDIO_MODS_MODULE_H #include "common/scummsys.h" diff --git a/audio/mods/paula.h b/audio/mods/paula.h index cd797f51cb..5d11cc7bb6 100644 --- a/audio/mods/paula.h +++ b/audio/mods/paula.h @@ -20,8 +20,8 @@ * */ -#ifndef SOUND_MODS_PAULA_H -#define SOUND_MODS_PAULA_H +#ifndef AUDIO_MODS_PAULA_H +#define AUDIO_MODS_PAULA_H #include "audio/audiostream.h" #include "common/frac.h" diff --git a/audio/mods/protracker.h b/audio/mods/protracker.h index 15f708d801..d52322f07e 100644 --- a/audio/mods/protracker.h +++ b/audio/mods/protracker.h @@ -27,8 +27,8 @@ * - parallaction */ -#ifndef SOUND_MODS_PROTRACKER_H -#define SOUND_MODS_PROTRACKER_H +#ifndef AUDIO_MODS_PROTRACKER_H +#define AUDIO_MODS_PROTRACKER_H namespace Common { class SeekableReadStream; diff --git a/audio/mods/rjp1.h b/audio/mods/rjp1.h index 232b1926e9..e7e54dafb3 100644 --- a/audio/mods/rjp1.h +++ b/audio/mods/rjp1.h @@ -26,8 +26,8 @@ * - queen */ -#ifndef SOUND_MODS_RJP1_H -#define SOUND_MODS_RJP1_H +#ifndef AUDIO_MODS_RJP1_H +#define AUDIO_MODS_RJP1_H namespace Common { class SeekableReadStream; diff --git a/audio/mods/soundfx.h b/audio/mods/soundfx.h index 48ccff2da6..d517c6c78f 100644 --- a/audio/mods/soundfx.h +++ b/audio/mods/soundfx.h @@ -26,8 +26,8 @@ * - cine */ -#ifndef SOUND_MODS_SOUNDFX_H -#define SOUND_MODS_SOUNDFX_H +#ifndef AUDIO_MODS_SOUNDFX_H +#define AUDIO_MODS_SOUNDFX_H namespace Common { class SeekableReadStream; diff --git a/audio/mods/tfmx.cpp b/audio/mods/tfmx.cpp index a89da78af1..8d584809c8 100644 --- a/audio/mods/tfmx.cpp +++ b/audio/mods/tfmx.cpp @@ -29,7 +29,7 @@ #include "audio/mods/tfmx.h" // test for engines using this class. -#if defined(SOUND_MODS_TFMX_H) +#if defined(AUDIO_MODS_TFMX_H) // couple debug-functions namespace { @@ -1187,4 +1187,4 @@ void displayPatternstep(const void * const vptr) { } // End of anonymous namespace #endif -#endif // #if defined(SOUND_MODS_TFMX_H) +#endif // #if defined(AUDIO_MODS_TFMX_H) diff --git a/audio/mods/tfmx.h b/audio/mods/tfmx.h index 2b07e2e660..4174fbfb27 100644 --- a/audio/mods/tfmx.h +++ b/audio/mods/tfmx.h @@ -24,8 +24,8 @@ #if !defined(ENABLE_SCUMM) // normal Header Guard -#elif !defined(SOUND_MODS_TFMX_H) -#define SOUND_MODS_TFMX_H +#elif !defined(AUDIO_MODS_TFMX_H) +#define AUDIO_MODS_TFMX_H #include "audio/mods/paula.h" @@ -278,4 +278,4 @@ private: } // End of namespace Audio -#endif // !defined(SOUND_MODS_TFMX_H) +#endif // !defined(AUDIO_MODS_TFMX_H) diff --git a/audio/mpu401.h b/audio/mpu401.h index 15728a6d97..d4580b6e79 100644 --- a/audio/mpu401.h +++ b/audio/mpu401.h @@ -20,8 +20,8 @@ * */ -#ifndef SOUND_MPU401_H -#define SOUND_MPU401_H +#ifndef AUDIO_MPU401_H +#define AUDIO_MPU401_H #include "audio/mididrv.h" diff --git a/audio/musicplugin.h b/audio/musicplugin.h index 307293a7c9..2a0f2f0a99 100644 --- a/audio/musicplugin.h +++ b/audio/musicplugin.h @@ -19,8 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef SOUND_MUSICPLUGIN_H -#define SOUND_MUSICPLUGIN_H +#ifndef AUDIO_MUSICPLUGIN_H +#define AUDIO_MUSICPLUGIN_H #include "base/plugins.h" #include "audio/mididrv.h" diff --git a/audio/null.h b/audio/null.h index 97c7c8cc93..90897be6af 100644 --- a/audio/null.h +++ b/audio/null.h @@ -19,8 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef SOUND_NULL_H -#define SOUND_NULL_H +#ifndef AUDIO_NULL_H +#define AUDIO_NULL_H #include "audio/musicplugin.h" #include "audio/mpu401.h" diff --git a/audio/rate.h b/audio/rate.h index 72bcbf48c5..9813b75b08 100644 --- a/audio/rate.h +++ b/audio/rate.h @@ -20,8 +20,8 @@ * */ -#ifndef SOUND_RATE_H -#define SOUND_RATE_H +#ifndef AUDIO_RATE_H +#define AUDIO_RATE_H #include "common/scummsys.h" diff --git a/audio/softsynth/cms.h b/audio/softsynth/cms.h index 48064746a8..0aad856a9d 100644 --- a/audio/softsynth/cms.h +++ b/audio/softsynth/cms.h @@ -19,8 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef SOUND_SOFTSYNTH_CMS_H -#define SOUND_SOFTSYNTH_CMS_H +#ifndef AUDIO_SOFTSYNTH_CMS_H +#define AUDIO_SOFTSYNTH_CMS_H #include "common/scummsys.h" diff --git a/audio/softsynth/emumidi.h b/audio/softsynth/emumidi.h index f72dad7eaf..3e9d669933 100644 --- a/audio/softsynth/emumidi.h +++ b/audio/softsynth/emumidi.h @@ -19,8 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef SOUND_SOFTSYNTH_EMUMIDI_H -#define SOUND_SOFTSYNTH_EMUMIDI_H +#ifndef AUDIO_SOFTSYNTH_EMUMIDI_H +#define AUDIO_SOFTSYNTH_EMUMIDI_H #include "audio/audiostream.h" #include "audio/mididrv.h" diff --git a/audio/softsynth/opl/dbopl.h b/audio/softsynth/opl/dbopl.h index 3dbd98986d..99234ebf88 100644 --- a/audio/softsynth/opl/dbopl.h +++ b/audio/softsynth/opl/dbopl.h @@ -18,8 +18,8 @@ // Last synch with DOSBox SVN trunk r3752 -#ifndef SOUND_SOFTSYNTH_OPL_DBOPL_H -#define SOUND_SOFTSYNTH_OPL_DBOPL_H +#ifndef AUDIO_SOFTSYNTH_OPL_DBOPL_H +#define AUDIO_SOFTSYNTH_OPL_DBOPL_H #include "common/scummsys.h" diff --git a/audio/softsynth/opl/dosbox.h b/audio/softsynth/opl/dosbox.h index cdf86df114..3adfe98852 100644 --- a/audio/softsynth/opl/dosbox.h +++ b/audio/softsynth/opl/dosbox.h @@ -26,8 +26,8 @@ * http://www.dosbox.com */ -#ifndef SOUND_SOFTSYNTH_OPL_DOSBOX_H -#define SOUND_SOFTSYNTH_OPL_DOSBOX_H +#ifndef AUDIO_SOFTSYNTH_OPL_DOSBOX_H +#define AUDIO_SOFTSYNTH_OPL_DOSBOX_H #ifndef DISABLE_DOSBOX_OPL diff --git a/audio/softsynth/opl/mame.h b/audio/softsynth/opl/mame.h index 803ca897e7..3714fa4e0a 100644 --- a/audio/softsynth/opl/mame.h +++ b/audio/softsynth/opl/mame.h @@ -23,8 +23,8 @@ */ -#ifndef SOUND_SOFTSYNTH_OPL_MAME_H -#define SOUND_SOFTSYNTH_OPL_MAME_H +#ifndef AUDIO_SOFTSYNTH_OPL_MAME_H +#define AUDIO_SOFTSYNTH_OPL_MAME_H #include "common/scummsys.h" #include "common/random.h" diff --git a/audio/softsynth/pcspk.h b/audio/softsynth/pcspk.h index 3641400b1f..f27eb94904 100644 --- a/audio/softsynth/pcspk.h +++ b/audio/softsynth/pcspk.h @@ -19,8 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef SOUND_SOFTSYNTH_PCSPK_H -#define SOUND_SOFTSYNTH_PCSPK_H +#ifndef AUDIO_SOFTSYNTH_PCSPK_H +#define AUDIO_SOFTSYNTH_PCSPK_H #include "audio/audiostream.h" #include "common/mutex.h" @@ -81,4 +81,4 @@ protected: } // End of namespace Audio -#endif // SOUND_SOFTSYNTH_PCSPEAKER_H +#endif // AUDIO_SOFTSYNTH_PCSPEAKER_H diff --git a/audio/softsynth/sid.cpp b/audio/softsynth/sid.cpp index 4b8f783ef4..1ad822b86a 100644 --- a/audio/softsynth/sid.cpp +++ b/audio/softsynth/sid.cpp @@ -27,7 +27,7 @@ #ifndef DISABLE_SID -#include "sid.h" +#include "audio/softsynth/sid.h" #include "audio/null.h" namespace Resid { diff --git a/audio/softsynth/sid.h b/audio/softsynth/sid.h index a015242844..19577e94d1 100644 --- a/audio/softsynth/sid.h +++ b/audio/softsynth/sid.h @@ -25,8 +25,8 @@ * Copyright (C) 2004 Dag Lem <resid@nimrod.no> */ -#ifndef __SID_H__ -#define __SID_H__ +#ifndef AUDIO_SOFTSYNTH_SID_H +#define AUDIO_SOFTSYNTH_SID_H // Inlining on/off. #define RESID_INLINE inline @@ -342,4 +342,4 @@ protected: } -#endif // not __SID_H__ +#endif // not AUDIO_SOFTSYNTH_SID_H diff --git a/audio/softsynth/wave6581.cpp b/audio/softsynth/wave6581.cpp index 63e08fb113..832a7272ff 100644 --- a/audio/softsynth/wave6581.cpp +++ b/audio/softsynth/wave6581.cpp @@ -27,7 +27,7 @@ #ifndef DISABLE_SID -#include "sid.h" +#include "audio/softsynth/sid.h" namespace Resid { diff --git a/audio/timestamp.h b/audio/timestamp.h index ef095a2106..1683b554cb 100644 --- a/audio/timestamp.h +++ b/audio/timestamp.h @@ -20,8 +20,8 @@ * */ -#ifndef SOUND_TIMESTAMP_H -#define SOUND_TIMESTAMP_H +#ifndef AUDIO_TIMESTAMP_H +#define AUDIO_TIMESTAMP_H #include "common/scummsys.h" diff --git a/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java b/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java index 7c61520d43..fbd6513761 100644 --- a/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java +++ b/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java @@ -134,6 +134,7 @@ public class ScummVMActivity extends Activity { // world-readable and don't get deleted on uninstall. String savePath = Environment.getExternalStorageDirectory() + "/ScummVM/Saves/"; File saveDir = new File(savePath); + saveDir.mkdirs(); if (!saveDir.isDirectory()) { // If it doesn't work, resort to the internal app path. savePath = getDir("saves", MODE_WORLD_READABLE).getPath(); diff --git a/common/macresman.cpp b/common/macresman.cpp index 2b9c68ade9..1317600cb7 100644 --- a/common/macresman.cpp +++ b/common/macresman.cpp @@ -110,7 +110,7 @@ bool MacResManager::open(String filename) { String fullPath = ConfMan.get("path") + "/" + filename + "/..namedfork/rsrc"; FSNode resFsNode = FSNode(fullPath); if (resFsNode.exists()) { - SeekableReadStream *macResForkRawStream = resFsNode.createReadStream();; + SeekableReadStream *macResForkRawStream = resFsNode.createReadStream(); if (macResForkRawStream && loadFromRawFork(*macResForkRawStream)) { _baseFileName = filename; @@ -173,7 +173,7 @@ bool MacResManager::open(FSNode path, String filename) { String fullPath = path.getPath() + "/" + filename + "/..namedfork/rsrc"; FSNode resFsNode = FSNode(fullPath); if (resFsNode.exists()) { - SeekableReadStream *macResForkRawStream = resFsNode.createReadStream();; + SeekableReadStream *macResForkRawStream = resFsNode.createReadStream(); if (macResForkRawStream && loadFromRawFork(*macResForkRawStream)) { _baseFileName = filename; diff --git a/engines/gob/iniconfig.cpp b/engines/gob/iniconfig.cpp index 9b8f1c703e..bba531723c 100644 --- a/engines/gob/iniconfig.cpp +++ b/engines/gob/iniconfig.cpp @@ -90,7 +90,7 @@ bool INIConfig::openConfig(const Common::String &file, Config &config) { bool INIConfig::createConfig(const Common::String &file, Config &config) { config.config = new Common::ConfigFile(); - config.created = true;; + config.created = true; _configs.setVal(file, config); diff --git a/engines/kyra/kyra_hof.cpp b/engines/kyra/kyra_hof.cpp index 4497ab8019..8a3229ea1f 100644 --- a/engines/kyra/kyra_hof.cpp +++ b/engines/kyra/kyra_hof.cpp @@ -1473,7 +1473,7 @@ void KyraEngine_HoF::snd_playVoiceFile(int id) { char vocFile[9]; assert(id >= 0 && id <= 9999999); sprintf(vocFile, "%07d", id); - if (_sound->voiceFileIsPresent(vocFile)) { + if (_sound->isVoicePresent(vocFile)) { snd_stopVoice(); while (!_sound->voicePlay(vocFile, &_speechHandle)) { diff --git a/engines/kyra/kyra_v1.h b/engines/kyra/kyra_v1.h index 584176e08c..5a9feb0054 100644 --- a/engines/kyra/kyra_v1.h +++ b/engines/kyra/kyra_v1.h @@ -52,14 +52,16 @@ class KyraMetaEngine; * * Status of this engine: * - * The KYRA engine supports all three Kyrandia games by Westwood. It also supports Westwood's - * Lands of Lore. There are various platform ports of the different games, almost all of them are - * fully supported. Only the Macintosh port of Kyrandia 1 makes a difference here, which lacks - * support for sound effects and music. + * The KYRA engine supports all three Kyrandia games by Westwood. It also + * supports Westwood's Lands of Lore. There are various platform ports of + * the different games, almost all of them are fully supported. Only the + * Macintosh port of Kyrandia 1 makes a difference here, which lacks support + * for sound effects and music. * - * The different translations of the games are mostly supported, since every translation - * requires some work for kyra.dat for example, it is almost impossible to support translations, - * without owning them. There a currently a few reported unsupported translations: + * The different translations of the games are mostly supported, since every + * translation requires some work for kyra.dat for example, it is almost + * impossible to support translations, without owning them. There a currently + * a few reported unsupported translations: * * - Official translations * None known. @@ -69,24 +71,30 @@ class KyraMetaEngine; * Kyrandia 1 Korean (feature request #1758252 "KYRA1: Add support for Korean/DOS version") * Kyrandia 2 Polish (feature request #2146192 "KYRA2: Add support for Polish floppy version") * - Fan translations: - * Kyrandia 1 Russian (no feature request) - * Kyrandia 2 Russian (no feature request) * Kyrandia 3 Russian (feature request #2812792 "Kyrandia3 Russian") * - * The engine is maintained by _athrxx. + * The primary maintainer for the engine is LordHoto, although some parts are + * maintained by _athrxx. If you have questions about parts of the code, the + * following rough description might help in determining who you should ask: + * _athrxx is the maintainer for the Lands of Lore subengine, he also + * maintains most of the FM-TOWNS and PC98 specific code (especially the sound + * code, also some ingame code) and the Kyrandia 2 sequence player code. + * LordHoto is responsible for the rest of the codebase, he also worked on the + * graphics output for 16 color PC98 games. * - * Other people who worked on this engine include cyx, who initially started to work on Kyrandia 1 - * support, vinterstum, who did various things for Kyrandia 1 and started to work on the Kyrandia 2 - * sequence player code and also on the TIM script code, and eriktorbjorn, who helped out naming - * our AdLib player code and also contributed a work around for a music bug in the "Pool of Sorrow" - * scene of Kyrandia 1, which is also present in the original. LordHoto worked on Kyrandia 1 to 3 - * support and graphics output for 16 color PC98 games and was a maintainer of the Kyrandia part. - * All mentioned developers are not actively working on KYRA anymore. + * Other people who worked on this engine include cyx, who initially started + * to work on Kyrandia 1 support. Vinterstum, who did various things for + * Kyrandia 1 and started to work on the Kyrandia 2 sequence player code and + * also on the TIM script code. Eriktorbjorn, who helped out naming our AdLib + * player code and also contributed a work around for a music bug in the + * "Pool of Sorrow" scene of Kyrandia 1, which is also present in the original. + * He also contributed the VQA player for Kyrandia 3. * - * The engine is mostly finished code wise. A possible remaining task is proper refactoring, - * which might help in reducing binary size and along with it runtime memory use, but of course - * might lead to regressions (since the current code makes no problems on our low end ports, it - * is pretty minor priority though, since the benefit would be mostly nicer code). The biggest + * The engine is mostly finished code wise. A possible remaining task is + * proper refactoring, which might help in reducing binary size and along with + * it runtime memory use, but of course might lead to regressions (since the + * current code makes no problems on our low end ports, it is pretty minor + * priority though, since the benefit would be mostly nicer code). The biggest * task left is the kyra.dat handling. * * Games using this engine: diff --git a/engines/kyra/sequences_lol.cpp b/engines/kyra/sequences_lol.cpp index 83d525d400..01db92c225 100644 --- a/engines/kyra/sequences_lol.cpp +++ b/engines/kyra/sequences_lol.cpp @@ -788,7 +788,7 @@ void HistoryPlayer::play() { for (; voiceFilename[3] <= '9' && !_vm->shouldQuit() && !_vm->skipFlag(); ++voiceFilename[3], voiceFilename[4] = 'a') { while (!_vm->shouldQuit() && !_vm->skipFlag()) { - if (!sound->voiceFileIsPresent(voiceFilename)) + if (!sound->isVoicePresent(voiceFilename)) break; if (data[part * 15] == voiceFilename[3] && data[part * 15 + 1] == voiceFilename[4]) { diff --git a/engines/kyra/sound.cpp b/engines/kyra/sound.cpp index 0e83c1cb1f..5195271808 100644 --- a/engines/kyra/sound.cpp +++ b/engines/kyra/sound.cpp @@ -43,25 +43,30 @@ Sound::Sound(KyraEngine_v1 *vm, Audio::Mixer *mixer) Sound::~Sound() { } -bool Sound::voiceFileIsPresent(const char *file) { - for (int i = 0; _supportedCodecs[i].fileext; ++i) { - Common::String f = file; - f += _supportedCodecs[i].fileext; - if (_vm->resource()->getFileSize(f.c_str()) > 0) - return true; - } +Sound::kType Sound::getSfxType() const { + return getMusicType(); +} + +void Sound::setSoundList(const AudioDataStruct *list) { + _soundDataList = list; +} +bool Sound::hasSoundFile(uint file) const { + return (fileListEntry(file) != 0); +} + +bool Sound::isPlaying() const { return false; } -bool Sound::isVoicePresent(const char *file) { - char filenamebuffer[25]; +bool Sound::isVoicePresent(const char *file) const { + Common::String filename; for (int i = 0; _supportedCodecs[i].fileext; ++i) { - strcpy(filenamebuffer, file); - strcat(filenamebuffer, _supportedCodecs[i].fileext); + filename = file; + filename += _supportedCodecs[i].fileext; - if (_vm->resource()->exists(filenamebuffer)) + if (_vm->resource()->exists(filename.c_str())) return true; } @@ -80,15 +85,15 @@ int32 Sound::voicePlay(const char *file, Audio::SoundHandle *handle, uint8 volum return playTime; } -Audio::SeekableAudioStream *Sound::getVoiceStream(const char *file) { - char filenamebuffer[25]; +Audio::SeekableAudioStream *Sound::getVoiceStream(const char *file) const { + Common::String filename; Audio::SeekableAudioStream *audioStream = 0; for (int i = 0; _supportedCodecs[i].fileext; ++i) { - strcpy(filenamebuffer, file); - strcat(filenamebuffer, _supportedCodecs[i].fileext); + filename = file; + filename += _supportedCodecs[i].fileext; - Common::SeekableReadStream *stream = _vm->resource()->createReadStream(filenamebuffer); + Common::SeekableReadStream *stream = _vm->resource()->createReadStream(filename); if (!stream) continue; @@ -136,7 +141,7 @@ void Sound::voiceStop(const Audio::SoundHandle *handle) { } } -bool Sound::voiceIsPlaying(const Audio::SoundHandle *handle) { +bool Sound::voiceIsPlaying(const Audio::SoundHandle *handle) const { if (!handle) { for (int h = 0; h < kNumChannelHandles; ++h) { if (_mixer->isSoundHandleActive(_soundChannels[h])) @@ -149,7 +154,7 @@ bool Sound::voiceIsPlaying(const Audio::SoundHandle *handle) { return false; } -bool Sound::allVoiceChannelsPlaying() { +bool Sound::allVoiceChannelsPlaying() const { for (int i = 0; i < kNumChannelHandles; ++i) if (!_mixer->isSoundHandleActive(_soundChannels[i])) return false; @@ -158,6 +163,91 @@ bool Sound::allVoiceChannelsPlaying() { #pragma mark - +MixedSoundDriver::MixedSoundDriver(KyraEngine_v1 *vm, Audio::Mixer *mixer, Sound *music, Sound *sfx) + : Sound(vm, mixer), _music(music), _sfx(sfx) { +} + +MixedSoundDriver::~MixedSoundDriver() { + delete _music; + delete _sfx; +} + +Sound::kType MixedSoundDriver::getMusicType() const { + return _music->getMusicType(); +} + +Sound::kType MixedSoundDriver::getSfxType() const { + return _sfx->getSfxType(); +} + +bool MixedSoundDriver::init() { + return (_music->init() && _sfx->init()); +} + +void MixedSoundDriver::process() { + _music->process(); + _sfx->process(); +} + +void MixedSoundDriver::updateVolumeSettings() { + _music->updateVolumeSettings(); + _sfx->updateVolumeSettings(); +} + +void MixedSoundDriver::setSoundList(const AudioDataStruct *list) { + _music->setSoundList(list); + _sfx->setSoundList(list); +} + +bool MixedSoundDriver::hasSoundFile(uint file) const { + return _music->hasSoundFile(file) && _sfx->hasSoundFile(file); +} + +void MixedSoundDriver::loadSoundFile(uint file) { + _music->loadSoundFile(file); + _sfx->loadSoundFile(file); +} + +void MixedSoundDriver::loadSoundFile(Common::String file) { + _music->loadSoundFile(file); + _sfx->loadSoundFile(file); +} + +void MixedSoundDriver::loadSfxFile(Common::String file) { + _sfx->loadSoundFile(file); +} + +void MixedSoundDriver::playTrack(uint8 track) { + _music->playTrack(track); +} + +void MixedSoundDriver::haltTrack() { + _music->haltTrack(); +} + +bool MixedSoundDriver::isPlaying() const { + return _music->isPlaying() | _sfx->isPlaying(); +} + +void MixedSoundDriver::playSoundEffect(uint8 track) { + _sfx->playSoundEffect(track); +} + +void MixedSoundDriver::stopAllSoundEffects() { + _sfx->stopAllSoundEffects(); +} + +void MixedSoundDriver::beginFadeOut() { + _music->beginFadeOut(); +} + +void MixedSoundDriver::pause(bool paused) { + _music->pause(paused); + _sfx->pause(paused); +} + +#pragma mark - + void KyraEngine_v1::snd_playTheme(int file, int track) { if (_curMusicTheme == file) return; diff --git a/engines/kyra/sound.h b/engines/kyra/sound.h index c3c32331be..f3de56520e 100644 --- a/engines/kyra/sound.h +++ b/engines/kyra/sound.h @@ -58,7 +58,7 @@ public: }; virtual kType getMusicType() const = 0; - virtual kType getSfxType() const { return getMusicType(); } + virtual kType getSfxType() const; /** * Initializes the output device. @@ -83,7 +83,7 @@ public: * * @param list soundfile list */ - virtual void setSoundList(const AudioDataStruct *list) { _soundDataList = list; } + virtual void setSoundList(const AudioDataStruct *list); /** * Checks if a given sound file is present. @@ -91,7 +91,7 @@ public: * @param track track number * @return true if available, false otherwise */ - virtual bool hasSoundFile(uint file) const { return (fileListEntry(file) != 0); } + virtual bool hasSoundFile(uint file) const; /** * Load a specifc sound file for use of @@ -140,7 +140,7 @@ public: * * @return true if playing, false otherwise */ - virtual bool isPlaying() const { return false; } + virtual bool isPlaying() const; /** * Starts fading out the volume. @@ -163,15 +163,13 @@ public: void enableSFX(bool enable) { _sfxEnabled = enable; } bool sfxEnabled() const { return _sfxEnabled; } - virtual bool voiceFileIsPresent(const char *file); - /** * Checks whether a voice file with the given name is present * * @param file file name * @return true if available, false otherwise */ - bool isVoicePresent(const char *file); + bool isVoicePresent(const char *file) const; /** * Plays the specified voice file. @@ -188,7 +186,7 @@ public: */ virtual int32 voicePlay(const char *file, Audio::SoundHandle *handle = 0, uint8 volume = 255, bool isSfx = false); - Audio::SeekableAudioStream *getVoiceStream(const char *file); + Audio::SeekableAudioStream *getVoiceStream(const char *file) const; bool playVoiceStream(Audio::AudioStream *stream, Audio::SoundHandle *handle = 0, uint8 volume = 255, bool isSfx = false); @@ -197,21 +195,21 @@ public: * * @return true when playing, else false */ - bool voiceIsPlaying(const Audio::SoundHandle *handle = 0); + bool voiceIsPlaying(const Audio::SoundHandle *handle = 0) const; /** * Checks if all voice handles are used. * * @return false when a handle is free, else true */ - bool allVoiceChannelsPlaying(); + bool allVoiceChannelsPlaying() const; /** * Checks how long a voice has been playing * * @return time in milliseconds */ - uint32 voicePlayedTime(const Audio::SoundHandle &handle) { + uint32 voicePlayedTime(const Audio::SoundHandle &handle) const { return _mixer->getSoundElapsedTime(handle); } @@ -253,34 +251,34 @@ private: class MixedSoundDriver : public Sound { public: - MixedSoundDriver(KyraEngine_v1 *vm, Audio::Mixer *mixer, Sound *music, Sound *sfx) : Sound(vm, mixer), _music(music), _sfx(sfx) {} - ~MixedSoundDriver() { delete _music; delete _sfx; } + MixedSoundDriver(KyraEngine_v1 *vm, Audio::Mixer *mixer, Sound *music, Sound *sfx); + ~MixedSoundDriver(); - kType getMusicType() const { return _music->getMusicType(); } - kType getSfxType() const { return _sfx->getSfxType(); } + virtual kType getMusicType() const; + virtual kType getSfxType() const; - bool init() { return (_music->init() && _sfx->init()); } - void process() { _music->process(); _sfx->process(); } + virtual bool init(); + virtual void process(); - void updateVolumeSettings() { _music->updateVolumeSettings(); _sfx->updateVolumeSettings(); } + virtual void updateVolumeSettings(); - void setSoundList(const AudioDataStruct * list) { _music->setSoundList(list); _sfx->setSoundList(list); } - bool hasSoundFile(uint file) const { return _music->hasSoundFile(file) && _sfx->hasSoundFile(file); } - void loadSoundFile(uint file) { _music->loadSoundFile(file); _sfx->loadSoundFile(file); } - void loadSoundFile(Common::String file) { _music->loadSoundFile(file); _sfx->loadSoundFile(file); } + virtual void setSoundList(const AudioDataStruct *list); + virtual bool hasSoundFile(uint file) const; + virtual void loadSoundFile(uint file); + virtual void loadSoundFile(Common::String file); - void loadSfxFile(Common::String file) { _sfx->loadSoundFile(file); } + virtual void loadSfxFile(Common::String file); - void playTrack(uint8 track) { _music->playTrack(track); } - void haltTrack() { _music->haltTrack(); } - bool isPlaying() const { return _music->isPlaying() | _sfx->isPlaying(); } + virtual void playTrack(uint8 track); + virtual void haltTrack(); + virtual bool isPlaying() const; - void playSoundEffect(uint8 track) { _sfx->playSoundEffect(track); } + virtual void playSoundEffect(uint8 track); - void stopAllSoundEffects() { _sfx->stopAllSoundEffects(); } + virtual void stopAllSoundEffects(); - void beginFadeOut() { _music->beginFadeOut(); } - void pause(bool paused) { _music->pause(paused); _sfx->pause(paused); } + virtual void beginFadeOut(); + virtual void pause(bool paused); private: Sound *_music, *_sfx; }; diff --git a/engines/kyra/sound_adlib.cpp b/engines/kyra/sound_adlib.cpp index 8976eba99c..b04abea080 100644 --- a/engines/kyra/sound_adlib.cpp +++ b/engines/kyra/sound_adlib.cpp @@ -42,6 +42,7 @@ #include "common/system.h" #include "common/mutex.h" +#include "common/config-manager.h" #include "audio/mixer.h" #include "audio/fmopl.h" @@ -59,7 +60,13 @@ public: AdLibDriver(Audio::Mixer *mixer, bool v2); ~AdLibDriver(); - int callback(int opcode, ...); + void initDriver(); + void setSoundData(uint8 *data); + void queueTrack(int track); + bool isChannelPlaying(int channel) const; + void stopAllChannels(); + int getSoundTrigger() const { return _soundTrigger; } + void callback(); // AudioStream API @@ -92,36 +99,10 @@ public: void setSyncJumpMask(uint16 mask) { _syncJumpMask = mask; } -private: - struct OpcodeEntry { - typedef int (AdLibDriver::*DriverOpcode)(va_list &list); - DriverOpcode function; - const char *name; - }; - - void setupOpcodeList(); - const OpcodeEntry *_opcodeList; - int _opcodesEntries; - - int snd_ret0x100(va_list &list); - int snd_ret0x1983(va_list &list); - int snd_initDriver(va_list &list); - int snd_deinitDriver(va_list &list); - int snd_setSoundData(va_list &list); - int snd_unkOpcode1(va_list &list); - int snd_startSong(va_list &list); - int snd_isChannelPlaying(va_list &list); - int snd_stopChannel(va_list &list); - int snd_readByte(va_list &list); - int snd_writeByte(va_list &list); - int snd_getSoundTrigger(va_list &list); - int snd_unkOpcode4(va_list &list); - int snd_dummy(va_list &list); - int snd_getNullvar4(va_list &list); - int snd_setNullvar3(va_list &list); - int snd_setFlag(va_list &list); - int snd_clearFlag(va_list &list); + void setMusicVolume(uint8 volume); + void setSfxVolume(uint8 volume); +private: // These variables have not yet been named, but some of them are partly // known nevertheless: // @@ -195,6 +176,7 @@ private: uint8 tempoReset; uint8 rawNote; int8 unk16; + uint8 volumeModifier; }; void primaryEffect1(Channel &channel); @@ -346,11 +328,8 @@ private: int32 _samplesTillCallback; int32 _samplesTillCallbackRemainder; - int _lastProcessed; - int8 _flagTrigger; int _curChannel; uint8 _soundTrigger; - int _soundsPlaying; uint16 _rnd; @@ -375,12 +354,19 @@ private: uint8 _unkValue19; uint8 _unkValue20; - int _flags; FM_OPL *_adlib; uint8 *_soundData; - uint8 _soundIdTable[0x10]; + int _programStartTimeout; + uint8 *_programQueue[16]; + int _programQueueStart, _programQueueEnd; + + void adjustSfxData(uint8 *data); + uint8 *_sfxPointer; + int _sfxPriority; + int _sfxVelocity; + Channel _channels[10]; uint8 _vibratoAndAMDepthBits; @@ -406,18 +392,18 @@ private: Audio::Mixer *_mixer; Audio::SoundHandle _soundHandle; + uint8 _musicVolume, _sfxVolume; + bool _v2; }; AdLibDriver::AdLibDriver(Audio::Mixer *mixer, bool v2) { - setupOpcodeList(); setupParserOpcodeTable(); _v2 = v2; _mixer = mixer; - _flags = 0; _adlib = makeAdLibOPL(getRate()); assert(_adlib); @@ -426,12 +412,12 @@ AdLibDriver::AdLibDriver(Audio::Mixer *mixer, bool v2) { _vibratoAndAMDepthBits = _curRegOffset = 0; - _lastProcessed = _flagTrigger = _curChannel = _rhythmSectionBits = 0; - _soundsPlaying = 0; + _curChannel = _rhythmSectionBits = 0; _rnd = 0x1234; _tempo = 0; _soundTrigger = 0; + _programStartTimeout = 0; _callbackTimer = 0xFF; _unkValue1 = _unkValue2 = _unkValue4 = _unkValue5 = 0; @@ -441,14 +427,7 @@ AdLibDriver::AdLibDriver(Audio::Mixer *mixer, bool v2) { _tablePtr1 = _tablePtr2 = 0; - // HACK: We use MusicSoundType here for now so we can adjust the volume in the launcher dialog. - // This affects SFX too, but if we want to support different volumes for SFX and music we would - // have to change our player implementation, currently we setup the volume for an AdLib channel - // in AdLibDriver::adjustVolume, so if that would be called, we would have to know if the channel - // is used by SFX or music, and then adjust the volume accordingly. Since Kyrandia 2 supports - // different volumes for SFX and music, looking at the disasm and checking how the original does it - // would be a good idea. - _mixer->playStream(Audio::Mixer::kMusicSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true); + _mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true); _samplesPerCallback = getRate() / CALLBACKS_PER_SECOND; _samplesPerCallbackRemainder = getRate() % CALLBACKS_PER_SECOND; @@ -456,6 +435,13 @@ AdLibDriver::AdLibDriver(Audio::Mixer *mixer, bool v2) { _samplesTillCallbackRemainder = 0; _syncJumpMask = 0; + + _musicVolume = 0; + _sfxVolume = 0; + + _sfxPointer = 0; + + _programQueueStart = _programQueueEnd = 0; } AdLibDriver::~AdLibDriver() { @@ -464,100 +450,108 @@ AdLibDriver::~AdLibDriver() { _adlib = 0; } -int AdLibDriver::callback(int opcode, ...) { +void AdLibDriver::setMusicVolume(uint8 volume) { Common::StackLock lock(_mutex); - if (opcode >= _opcodesEntries || opcode < 0) { - warning("AdLibDriver: calling unknown opcode '%d'", opcode); - return 0; + + _musicVolume = volume; + + for (uint i = 0; i < 6; ++i) { + Channel &chan = _channels[i]; + chan.volumeModifier = volume; + + const uint8 regOffset = _regOffset[i]; + + // Level Key Scaling / Total Level + writeOPL(0x40 + regOffset, calculateOpLevel1(chan)); + writeOPL(0x43 + regOffset, calculateOpLevel2(chan)); } - debugC(9, kDebugLevelSound, "Calling opcode '%s' (%d)", _opcodeList[opcode].name, opcode); + // For now we use the music volume for both sfx and music in Kyra1. + if (!_v2) { + _sfxVolume = volume; - va_list args; - va_start(args, opcode); - int returnValue = (this->*(_opcodeList[opcode].function))(args); - va_end(args); - return returnValue; -} + for (uint i = 6; i < 9; ++i) { + Channel &chan = _channels[i]; + chan.volumeModifier = volume; -// Opcodes + const uint8 regOffset = _regOffset[i]; -int AdLibDriver::snd_ret0x100(va_list &list) { - return 0x100; + // Level Key Scaling / Total Level + writeOPL(0x40 + regOffset, calculateOpLevel1(chan)); + writeOPL(0x43 + regOffset, calculateOpLevel2(chan)); + } + } } -int AdLibDriver::snd_ret0x1983(va_list &list) { - return 0x1983; -} +void AdLibDriver::setSfxVolume(uint8 volume) { + // We only support sfx volume in v2 games. + if (!_v2) + return; -int AdLibDriver::snd_initDriver(va_list &list) { - _lastProcessed = _soundsPlaying = 0; - resetAdLibState(); - return 0; + Common::StackLock lock(_mutex); + + _sfxVolume = volume; + + for (uint i = 6; i < 9; ++i) { + Channel &chan = _channels[i]; + chan.volumeModifier = volume; + + const uint8 regOffset = _regOffset[i]; + + // Level Key Scaling / Total Level + writeOPL(0x40 + regOffset, calculateOpLevel1(chan)); + writeOPL(0x43 + regOffset, calculateOpLevel2(chan)); + } } -int AdLibDriver::snd_deinitDriver(va_list &list) { +void AdLibDriver::initDriver() { + Common::StackLock lock(_mutex); resetAdLibState(); - return 0; } -int AdLibDriver::snd_setSoundData(va_list &list) { +void AdLibDriver::setSoundData(uint8 *data) { + Common::StackLock lock(_mutex); + + // Drop all tracks that are still queued. These would point to the old + // sound data. + _programQueueStart = _programQueueEnd = 0; + memset(_programQueue, 0, sizeof(_programQueue)); + if (_soundData) { delete[] _soundData; _soundData = 0; } - _soundData = va_arg(list, uint8 *); - return 0; -} -int AdLibDriver::snd_unkOpcode1(va_list &list) { - warning("unimplemented snd_unkOpcode1"); - return 0; + _soundData = data; } -int AdLibDriver::snd_startSong(va_list &list) { - int songId = va_arg(list, int); - _flags |= 8; - _flagTrigger = 1; +void AdLibDriver::queueTrack(int track) { + Common::StackLock lock(_mutex); - uint8 *ptr = getProgram(songId); - assert(ptr); - uint8 chan = *ptr; + uint8 *trackData = getProgram(track); + if (!trackData) + return; - if ((songId << 1) != 0) { - if (chan == 9) { - if (_flags & 2) - return 0; - } else { - if (_flags & 1) - return 0; - } + if (_programQueueEnd == _programQueueStart && _programQueue[_programQueueEnd] != 0) { + warning("AdLibDriver: Program queue full, dropping track %d", track); + return; } - _soundIdTable[_soundsPlaying++] = songId; - _soundsPlaying &= 0x0F; - - return 0; + _programQueue[_programQueueEnd++] = trackData; + _programQueueEnd &= 15; } -int AdLibDriver::snd_isChannelPlaying(va_list &list) { - int channel = va_arg(list, int); +bool AdLibDriver::isChannelPlaying(int channel) const { + Common::StackLock lock(_mutex); + assert(channel >= 0 && channel <= 9); - return (_channels[channel].dataptr != 0) ? 1 : 0; + return (_channels[channel].dataptr != 0); } -int AdLibDriver::snd_stopChannel(va_list &list) { - int channel = va_arg(list, int); - - int maxChannel; - if (channel < 0) { - channel = 0; - maxChannel = 9; - } else { - maxChannel = channel; - } +void AdLibDriver::stopAllChannels() { + Common::StackLock lock(_mutex); - for (; channel <= maxChannel; ++channel) { + for (int channel = 0; channel <= 9; ++channel) { _curChannel = channel; Channel &chan = _channels[_curChannel]; @@ -567,71 +561,16 @@ int AdLibDriver::snd_stopChannel(va_list &list) { if (channel != 9) noteOff(chan); } - - return 0; -} - -int AdLibDriver::snd_readByte(va_list &list) { - int a = va_arg(list, int); - int b = va_arg(list, int); - uint8 *ptr = getProgram(a) + b; - assert(ptr); - return *ptr; -} - -int AdLibDriver::snd_writeByte(va_list &list) { - int a = va_arg(list, int); - int b = va_arg(list, int); - uint8 value = va_arg(list, int); - uint8 *ptr = getProgram(a) + b; - assert(ptr); - SWAP(*ptr, value); - return value; -} - -int AdLibDriver::snd_getSoundTrigger(va_list &list) { - return _soundTrigger; -} - -int AdLibDriver::snd_unkOpcode4(va_list &list) { - warning("unimplemented snd_unkOpcode4"); - return 0; -} - -int AdLibDriver::snd_dummy(va_list &list) { - return 0; -} - -int AdLibDriver::snd_getNullvar4(va_list &list) { - warning("unimplemented snd_getNullvar4"); - return 0; -} - -int AdLibDriver::snd_setNullvar3(va_list &list) { - warning("unimplemented snd_setNullvar3"); - return 0; -} - -int AdLibDriver::snd_setFlag(va_list &list) { - int oldFlags = _flags; - _flags |= va_arg(list, int); - return oldFlags; -} - -int AdLibDriver::snd_clearFlag(va_list &list) { - int oldFlags = _flags; - _flags &= ~(va_arg(list, int)); - return oldFlags; } // timer callback void AdLibDriver::callback() { Common::StackLock lock(_mutex); - --_flagTrigger; - if (_flagTrigger < 0) - _flags &= ~8; - setupPrograms(); + if (_programStartTimeout) + --_programStartTimeout; + else + setupPrograms(); executePrograms(); uint8 temp = _callbackTimer; @@ -645,36 +584,86 @@ void AdLibDriver::callback() { } void AdLibDriver::setupPrograms() { - while (_lastProcessed != _soundsPlaying) { - uint8 *ptr = getProgram(_soundIdTable[_lastProcessed]); - uint8 chan = *ptr++; - uint8 priority = *ptr++; - - // Only start this sound if its priority is higher than the one - // already playing. - - Channel &channel = _channels[chan]; - - if (priority >= channel.priority) { - initChannel(channel); - channel.priority = priority; - channel.dataptr = ptr; - channel.tempo = 0xFF; - channel.position = 0xFF; - channel.duration = 1; - unkOutput2(chan); - } + // If there is no program queued, we skip this. + if (_programQueueStart == _programQueueEnd) + return; + + uint8 *ptr = _programQueue[_programQueueStart]; + // Clear the queue entry + _programQueue[_programQueueStart] = 0; + _programQueueStart = (_programQueueStart + 1) & 15; + + // Adjust data in case we hit a sound effect. + adjustSfxData(ptr); + + const int chan = *ptr++; + const int priority = *ptr++; + + // Only start this sound if its priority is higher than the one + // already playing. + + Channel &channel = _channels[chan]; - // What we have set up now is, probably, the controlling - // channel for the sound. It is assumed that this program will - // set up all the other channels it needs, clearing their locks - // along the way. + if (priority >= channel.priority) { + initChannel(channel); + channel.priority = priority; + channel.dataptr = ptr; + channel.tempo = 0xFF; + channel.position = 0xFF; + channel.duration = 1; - ++_lastProcessed; - _lastProcessed &= 0x0F; + if (chan <= 5) + channel.volumeModifier = _musicVolume; + else + channel.volumeModifier = _sfxVolume; + + unkOutput2(chan); + + // We need to wait two callback calls till we can start another track. + // This is (probably) required to assure that the sfx are started with + // the correct priority and velocity. + _programStartTimeout = 2; } } +void AdLibDriver::adjustSfxData(uint8 *ptr) { + // Check whether we need to reset the data of an old sfx which has been + // started. + if (_sfxPointer) { + _sfxPointer[1] = _sfxPriority; + _sfxPointer[3] = _sfxVelocity; + _sfxPointer = 0; + } + + // Only music tracks are started on channel 9, thus we need to make sure + // we do not have a music track here. + if (*ptr == 9) + return; + + // Store the pointer so we can reset the data when a new program is started. + _sfxPointer = ptr; + + // Store the old values. + _sfxPriority = ptr[1]; + _sfxVelocity = ptr[3]; + + // In the cases I've seen, the mysterious fourth byte has been + // the parameter for the update_setExtraLevel3() callback. + // + // The extra level is part of the channels "total level", which + // is a six-bit value where larger values means softer volume. + // + // So what seems to be happening here is that sounds which are + // started by this function are given a slightly lower priority + // and a slightly higher (i.e. softer) extra level 3 than they + // would have if they were started from anywhere else. Strange. + + // Adjust the values. + int newVal = ((((ptr[3]) + 63) * 0xFF) >> 8) & 0xFF; + ptr[3] = -newVal + 63; + ptr[1] = ((ptr[1] * 0xFF) >> 8) & 0xFF; +} + // A few words on opcode parsing and timing: // // First of all, We simulate a timer callback 72 times per second. Each timeout @@ -1273,9 +1262,21 @@ uint8 AdLibDriver::calculateOpLevel1(Channel &channel) { if (channel.twoChan) { value += channel.opExtraLevel1; value += channel.opExtraLevel2; - value += channel.opExtraLevel3; + + uint16 level3 = (channel.opExtraLevel3 ^ 0x3F) * channel.volumeModifier; + if (level3) { + level3 += 0x3F; + level3 >>= 8; + } + + value += level3 ^ 0x3F; } + value = CLIP<int8>(value, 0, 0x3F); + + if (!channel.volumeModifier) + value = 0x3F; + // Preserve the scaling level bits from opLevel1 return checkValue(value) | (channel.opLevel1 & 0xC0); @@ -1286,7 +1287,19 @@ uint8 AdLibDriver::calculateOpLevel2(Channel &channel) { value += channel.opExtraLevel1; value += channel.opExtraLevel2; - value += channel.opExtraLevel3; + + uint16 level3 = (channel.opExtraLevel3 ^ 0x3F) * channel.volumeModifier; + if (level3) { + level3 += 0x3F; + level3 >>= 8; + } + + value += level3 ^ 0x3F; + + value = CLIP<int8>(value, 0, 0x3F); + + if (!channel.volumeModifier) + value = 0x3F; // Preserve the scaling level bits from opLevel2 @@ -1323,14 +1336,22 @@ int AdLibDriver::update_setupProgram(uint8 *&dataptr, Channel &channel, uint8 va Channel &channel2 = _channels[chan]; if (priority >= channel2.priority) { - _flagTrigger = 1; - _flags |= 8; + // We keep new tracks from being started for two further iterations of + // the callback. This assures the correct velocity is used for this + // program. + _programStartTimeout = 2; initChannel(channel2); channel2.priority = priority; channel2.dataptr = ptr; channel2.tempo = 0xFF; channel2.position = 0xFF; channel2.duration = 1; + + if (chan <= 5) + channel2.volumeModifier = _musicVolume; + else + channel2.volumeModifier = _sfxVolume; + unkOutput2(chan); } @@ -1911,32 +1932,6 @@ int AdLibDriver::updateCallback56(uint8 *&dataptr, Channel &channel, uint8 value #define COMMAND(x) { &AdLibDriver::x, #x } -void AdLibDriver::setupOpcodeList() { - static const OpcodeEntry opcodeList[] = { - COMMAND(snd_ret0x100), - COMMAND(snd_ret0x1983), - COMMAND(snd_initDriver), - COMMAND(snd_deinitDriver), - COMMAND(snd_setSoundData), - COMMAND(snd_unkOpcode1), - COMMAND(snd_startSong), - COMMAND(snd_isChannelPlaying), - COMMAND(snd_stopChannel), - COMMAND(snd_readByte), - COMMAND(snd_writeByte), - COMMAND(snd_getSoundTrigger), - COMMAND(snd_unkOpcode4), - COMMAND(snd_dummy), - COMMAND(snd_getNullvar4), - COMMAND(snd_setNullvar3), - COMMAND(snd_setFlag), - COMMAND(snd_clearFlag) - }; - - _opcodeList = opcodeList; - _opcodesEntries = ARRAYSIZE(opcodeList); -} - void AdLibDriver::setupParserOpcodeTable() { static const ParserOpcode parserOpcodeTable[] = { // 0 @@ -2266,13 +2261,12 @@ SoundAdLibPC::~SoundAdLibPC() { } bool SoundAdLibPC::init() { - _driver->callback(2); - _driver->callback(16, int(4)); + _driver->initDriver(); return true; } void SoundAdLibPC::process() { - uint8 trigger = _driver->callback(11); + int trigger = _driver->getSoundTrigger(); if (trigger < _numSoundTriggers) { int soundId = _soundTriggers[trigger]; @@ -2285,6 +2279,23 @@ void SoundAdLibPC::process() { } } +void SoundAdLibPC::updateVolumeSettings() { + bool mute = false; + if (ConfMan.hasKey("mute")) + mute = ConfMan.getBool("mute"); + + int newMusicVolume = mute ? 0 : ConfMan.getInt("music_volume"); + //newMusicVolume = (newMusicVolume * 145) / Audio::Mixer::kMaxMixerVolume + 110; + newMusicVolume = CLIP(newMusicVolume, 0, 255); + + int newSfxVolume = mute ? 0 : ConfMan.getInt("sfx_volume"); + //newSfxVolume = (newSfxVolume * 200) / Audio::Mixer::kMaxMixerVolume + 55; + newSfxVolume = CLIP(newSfxVolume, 0, 255); + + _driver->setMusicVolume(newMusicVolume); + _driver->setSfxVolume(newSfxVolume); +} + void SoundAdLibPC::playTrack(uint8 track) { if (_musicEnabled) { // WORKAROUND: There is a bug in the Kyra 1 "Pool of Sorrow" @@ -2301,13 +2312,13 @@ void SoundAdLibPC::playTrack(uint8 track) { } void SoundAdLibPC::haltTrack() { - playSoundEffect(0); - playSoundEffect(0); + play(0); + play(0); //_vm->_system->delayMillis(3 * 60); } bool SoundAdLibPC::isPlaying() const { - return _driver->callback(7, int(0)) != 0; + return _driver->isChannelPlaying(0); } void SoundAdLibPC::playSoundEffect(uint8 track) { @@ -2326,60 +2337,11 @@ void SoundAdLibPC::play(uint8 track) { if ((soundId == 0xFFFF && _v2) || (soundId == 0xFF && !_v2) || !_soundDataPtr) return; - // HACK: Since we might call this when the engines is paused (on game load via GMM) - // we must unpause the engine here, so this will work properly - - int pauseCount = 0; - while (_vm->isPaused()) { - ++pauseCount; - _vm->pauseEngine(false); - } - - while ((_driver->callback(16, 0) & 8)) { - // We call the system delay and not the game delay to avoid concurrency issues. - _vm->_system->delayMillis(10); - } - - while (pauseCount--) - _vm->pauseEngine(true); - - if (_sfxPlayingSound != -1) { - // Restore the sounds's normal values. - _driver->callback(10, _sfxPlayingSound, int(1), int(_sfxPriority)); - _driver->callback(10, _sfxPlayingSound, int(3), int(_sfxFourthByteOfSong)); - _sfxPlayingSound = -1; - } - - int chan = _driver->callback(9, soundId, int(0)); - - if (chan != 9) { - _sfxPlayingSound = soundId; - _sfxPriority = _driver->callback(9, soundId, int(1)); - _sfxFourthByteOfSong = _driver->callback(9, soundId, int(3)); - - // In the cases I've seen, the mysterious fourth byte has been - // the parameter for the update_setExtraLevel3() callback. - // - // The extra level is part of the channels "total level", which - // is a six-bit value where larger values means softer volume. - // - // So what seems to be happening here is that sounds which are - // started by this function are given a slightly lower priority - // and a slightly higher (i.e. softer) extra level 3 than they - // would have if they were started from anywhere else. Strange. - - int newVal = ((((-_sfxFourthByteOfSong) + 63) * 0xFF) >> 8) & 0xFF; - newVal = -newVal + 63; - _driver->callback(10, soundId, int(3), newVal); - newVal = ((_sfxPriority * 0xFF) >> 8) & 0xFF; - _driver->callback(10, soundId, int(1), newVal); - } - - _driver->callback(6, soundId); + _driver->queueTrack(soundId); } void SoundAdLibPC::beginFadeOut() { - playSoundEffect(1); + play(1); } void SoundAdLibPC::loadSoundFile(uint file) { @@ -2409,7 +2371,7 @@ void SoundAdLibPC::internalLoadFile(Common::String file) { playSoundEffect(0); playSoundEffect(0); - _driver->callback(8, int(-1)); + _driver->stopAllChannels(); _soundDataPtr = 0; int soundDataSize = fileSize; @@ -2434,7 +2396,7 @@ void SoundAdLibPC::internalLoadFile(Common::String file) { fileData = p = 0; fileSize = 0; - _driver->callback(4, _soundDataPtr); + _driver->setSoundData(_soundDataPtr); _soundFileLoaded = file; } diff --git a/engines/kyra/sound_adlib.h b/engines/kyra/sound_adlib.h index c09fec997e..923a4cb75f 100644 --- a/engines/kyra/sound_adlib.h +++ b/engines/kyra/sound_adlib.h @@ -62,22 +62,23 @@ public: SoundAdLibPC(KyraEngine_v1 *vm, Audio::Mixer *mixer); ~SoundAdLibPC(); - kType getMusicType() const { return kAdLib; } + virtual kType getMusicType() const { return kAdLib; } - bool init(); - void process(); + virtual bool init(); + virtual void process(); - void loadSoundFile(uint file); - void loadSoundFile(Common::String file); - void loadSoundFile(const uint8 *soundData, int dataSize) {} + virtual void updateVolumeSettings(); - void playTrack(uint8 track); - void haltTrack(); - bool isPlaying() const; + virtual void loadSoundFile(uint file); + virtual void loadSoundFile(Common::String file); - void playSoundEffect(uint8 track); + virtual void playTrack(uint8 track); + virtual void haltTrack(); + virtual bool isPlaying() const; - void beginFadeOut(); + virtual void playSoundEffect(uint8 track); + + virtual void beginFadeOut(); private: void internalLoadFile(Common::String file); @@ -92,9 +93,6 @@ private: Common::String _soundFileLoaded; - uint8 _sfxPriority; - uint8 _sfxFourthByteOfSong; - int _numSoundTriggers; const int *_soundTriggers; diff --git a/engines/made/screen.cpp b/engines/made/screen.cpp index dbe2f1c7ba..168902d577 100644 --- a/engines/made/screen.cpp +++ b/engines/made/screen.cpp @@ -437,15 +437,15 @@ uint16 Screen::placeSprite(uint16 channelIndex, uint16 flexIndex, int16 x, int16 PictureResource *flex = _vm->_res->getPicture(flexIndex); if (flex) { - Graphics::Surface *surf = flex->getPicture(); + //Graphics::Surface *surf = flex->getPicture(); int16 state = 1; - int16 x1, y1, x2, y2; + /*int16 x1, y1, x2, y2; x1 = x; y1 = y; x2 = x + surf->w + 1; - y2 = y + surf->h + 1; + y2 = y + surf->h + 1;*/ if (_ground == 0) state |= 2; @@ -485,12 +485,12 @@ uint16 Screen::placeAnim(uint16 channelIndex, uint16 animIndex, int16 x, int16 y if (anim) { int16 state = 1; - int16 x1, y1, x2, y2; + /*int16 x1, y1, x2, y2; x1 = x; y1 = y; x2 = x + anim->getWidth(); - y2 = y + anim->getHeight(); + y2 = y + anim->getHeight();*/ if (anim->getFlags() == 1 || _ground == 0) state |= 2; @@ -543,7 +543,7 @@ uint16 Screen::placeText(uint16 channelIndex, uint16 textObjectIndex, int16 x, i Object *obj = _vm->_dat->getObject(textObjectIndex); const char *text = obj->getString(); - int16 x1, y1, x2, y2; + //int16 x1, y1, x2, y2; setFont(fontNum); @@ -557,10 +557,10 @@ uint16 Screen::placeText(uint16 channelIndex, uint16 textObjectIndex, int16 x, i y--; } - x1 = x; + /*x1 = x; y1 = y; x2 = x + textWidth; - y2 = y + textHeight; + y2 = y + textHeight;*/ if (textWidth > 0 && outlineColor != -1) { x++; diff --git a/engines/saga/detection.cpp b/engines/saga/detection.cpp index 091ec8d427..d39ec34cc8 100644 --- a/engines/saga/detection.cpp +++ b/engines/saga/detection.cpp @@ -209,7 +209,7 @@ int SagaMetaEngine::getMaximumSaveSlot() const { return MAX_SAVES - 1; } void SagaMetaEngine::removeSaveState(const char *target, int slot) const { Common::String filename = target; - filename += Common::String::format(".s%02d", slot);; + filename += Common::String::format(".s%02d", slot); g_system->getSavefileManager()->removeSavefile(filename); } diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index 8cb294e166..e549c1f8ae 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -457,6 +457,7 @@ reg_t kListFirstTrue(EngineState *s, int argc, reg_t *argv); reg_t kListAllTrue(EngineState *s, int argc, reg_t *argv); reg_t kInPolygon(EngineState *s, int argc, reg_t *argv); reg_t kObjectIntersect(EngineState *s, int argc, reg_t *argv); +reg_t kEditText(EngineState *s, int argc, reg_t *argv); // SCI2.1 Kernel Functions reg_t kText(EngineState *s, int argc, reg_t *argv); diff --git a/engines/sci/engine/kernel_tables.h b/engines/sci/engine/kernel_tables.h index afe6b176e5..d8d9f6bd82 100644 --- a/engines/sci/engine/kernel_tables.h +++ b/engines/sci/engine/kernel_tables.h @@ -499,6 +499,7 @@ static SciKernelMapEntry s_kernelMap[] = { { MAP_CALL(UpdatePlane), SIG_EVERYWHERE, "o", NULL, NULL }, { MAP_CALL(UpdateScreenItem), SIG_EVERYWHERE, "o", NULL, NULL }, { MAP_CALL(ObjectIntersect), SIG_EVERYWHERE, "oo", NULL, NULL }, + { MAP_CALL(EditText), SIG_EVERYWHERE, "o", NULL, NULL }, // SCI2 unmapped functions - TODO! @@ -523,13 +524,6 @@ static SciKernelMapEntry s_kernelMap[] = { // TODO: Implement once the original save/load menus are implemented. { MAP_DUMMY(MakeSaveFileName), SIG_EVERYWHERE, "(.*)", NULL, NULL }, - // Used for edit boxes in save/load dialogs. It's a rewritten version of kEditControl, - // but it handles events on its own, using an internal loop, instead of using SCI - // scripts for event management like kEditControl does. Called by script 64914, - // DEdit::hilite(). - // TODO: Implement once the original save/load menus are implemented. - { MAP_DUMMY(EditText), SIG_EVERYWHERE, "o", NULL, NULL }, - // Unused / debug SCI2 unused functions, always mapped to kDummy // AddMagnify/DeleteMagnify are both called by script 64979 (the Magnifier diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp index 9e9441847d..ce903626e7 100644 --- a/engines/sci/engine/kfile.cpp +++ b/engines/sci/engine/kfile.cpp @@ -22,6 +22,7 @@ #include "common/archive.h" #include "common/config-manager.h" +#include "common/debug-channels.h" #include "common/file.h" #include "common/str.h" #include "common/savefile.h" @@ -52,9 +53,10 @@ struct SavegameDesc { * arbitrary data files, simply because many of our target platforms do not * support this. The only files one can create are savestates. But SCI has an * opcode to create and write to seemingly 'arbitrary' files. This is mainly - * used in LSL3 for LARRY3.DRV (which is a game data file, not a driver) and - * in LSL5 for MEMORY.DRV (which is again a game data file and contains the - * game's password). + * used in LSL3 for LARRY3.DRV (which is a game data file, not a driver, used + * for persisting the results of the "age quiz" across restarts) and in LSL5 + * for MEMORY.DRV (which is again a game data file and contains the game's + * password, XOR encrypted). * To implement that opcode, we combine the SaveFileManager with regular file * code, similarly to how the SCUMM HE engine does it. * @@ -115,20 +117,6 @@ reg_t file_open(EngineState *s, const Common::String &filename, int mode, bool u if (!inFile) inFile = SearchMan.createReadStreamForMember(englishName); - // Special case for LSL3: It tries to create a new dummy file, - // LARRY3.DRV. Apparently, if the file doesn't exist here, it should be - // created. The game scripts then go ahead and fill its contents with - // data. It seems to be a similar case as the dummy MEMORY.DRV file in - // LSL5, but LSL5 creates the file if it can't find it with a separate - // call to file_open(). - if (!inFile && englishName == "LARRY3.DRV") { - outFile = saveFileMan->openForSaving(wrappedName); - outFile->finalize(); - delete outFile; - outFile = 0; - inFile = SearchMan.createReadStreamForMember(wrappedName); - } - if (!inFile) debugC(kDebugLevelFile, " -> file_open(_K_FILE_MODE_OPEN_OR_FAIL): failed to open file '%s'", englishName.c_str()); } else if (mode == _K_FILE_MODE_CREATE) { @@ -1060,6 +1048,18 @@ reg_t kFileIOExists(EngineState *s, int argc, reg_t *argv) { exists = !saveFileMan->listSavefiles(wrappedName).empty(); } + // SCI2+ debug mode + if (DebugMan.isDebugChannelEnabled(kDebugLevelDebugMode)) { + if (!exists && name == "1.scr") // PQ4 + exists = true; + if (!exists && name == "18.scr") // QFG4 + exists = true; + if (!exists && name == "99.scr") // GK1, KQ7 + exists = true; + if (!exists && name == "classes") // GK2, SQ6, LSL7 + exists = true; + } + // Special case for non-English versions of LSL5: The English version of // LSL5 calls kFileIO(), case K_FILEIO_OPEN for reading to check if // memory.drv exists (which is where the game's password is stored). If diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 566f2a9a7d..76c6778f0a 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -49,6 +49,7 @@ #include "sci/graphics/text16.h" #include "sci/graphics/view.h" #ifdef ENABLE_SCI32 +#include "sci/graphics/controls32.h" #include "sci/graphics/font.h" // TODO: remove once kBitmap is moved in a separate class #include "sci/graphics/text32.h" #include "sci/graphics/frameout.h" @@ -1665,8 +1666,8 @@ reg_t kBitmap(EngineState *s, int argc, reg_t *argv) { memset(memoryPtr + BITMAP_HEADER_SIZE, back, width * height); // Save totalWidth, totalHeight // TODO: Save the whole bitmap header, like SSCI does - WRITE_LE_UINT16((void *)memoryPtr, width); - WRITE_LE_UINT16((void *)(memoryPtr + 2), height); + WRITE_LE_UINT16(memoryPtr, width); + WRITE_LE_UINT16(memoryPtr + 2, height); return memoryId; } break; @@ -1692,8 +1693,8 @@ reg_t kBitmap(EngineState *s, int argc, reg_t *argv) { byte *memoryPtr = s->_segMan->getHunkPointer(hunkId); // Get totalWidth, totalHeight - uint16 totalWidth = READ_LE_UINT16((void *)memoryPtr); - uint16 totalHeight = READ_LE_UINT16((void *)(memoryPtr + 2)); + uint16 totalWidth = READ_LE_UINT16(memoryPtr); + uint16 totalHeight = READ_LE_UINT16(memoryPtr + 2); byte *bitmap = memoryPtr + BITMAP_HEADER_SIZE; GfxView *view = g_sci->_gfxCache->getView(viewNum); @@ -1733,8 +1734,8 @@ reg_t kBitmap(EngineState *s, int argc, reg_t *argv) { byte *memoryPtr = s->_segMan->getHunkPointer(hunkId); // Get totalWidth, totalHeight - uint16 totalWidth = READ_LE_UINT16((void *)memoryPtr); - uint16 totalHeight = READ_LE_UINT16((void *)(memoryPtr + 2)); + uint16 totalWidth = READ_LE_UINT16(memoryPtr); + uint16 totalHeight = READ_LE_UINT16(memoryPtr + 2); byte *bitmap = memoryPtr + BITMAP_HEADER_SIZE; GfxFont *font = g_sci->_gfxCache->getFont(fontId); @@ -1776,8 +1777,8 @@ reg_t kBitmap(EngineState *s, int argc, reg_t *argv) { byte *memoryPtr = s->_segMan->getHunkPointer(hunkId); // Get totalWidth, totalHeight - uint16 totalWidth = READ_LE_UINT16((void *)memoryPtr); - uint16 totalHeight = READ_LE_UINT16((void *)(memoryPtr + 2)); + uint16 totalWidth = READ_LE_UINT16(memoryPtr); + uint16 totalHeight = READ_LE_UINT16(memoryPtr + 2); uint16 width = MIN<uint16>(totalWidth - x, fillWidth); uint16 height = MIN<uint16>(totalHeight - y, fillHeight); byte *bitmap = memoryPtr + BITMAP_HEADER_SIZE; @@ -1798,6 +1799,20 @@ reg_t kBitmap(EngineState *s, int argc, reg_t *argv) { return s->r_acc; } +// Used for edit boxes in save/load dialogs. It's a rewritten version of kEditControl, +// but it handles events on its own, using an internal loop, instead of using SCI +// scripts for event management like kEditControl does. Called by script 64914, +// DEdit::hilite(). +reg_t kEditText(EngineState *s, int argc, reg_t *argv) { + reg_t controlObject = argv[0]; + + if (!controlObject.isNull()) { + g_sci->_gfxControls32->kernelTexteditChange(controlObject); + } + + return s->r_acc; +} + #endif } // End of namespace Sci diff --git a/engines/sci/engine/kstring.cpp b/engines/sci/engine/kstring.cpp index 1a9359bb26..5ae18c1367 100644 --- a/engines/sci/engine/kstring.cpp +++ b/engines/sci/engine/kstring.cpp @@ -697,13 +697,15 @@ reg_t kString(EngineState *s, int argc, reg_t *argv) { case 6: { // Cpy const char *string2 = 0; uint32 string2Size = 0; + Common::String string; if (argv[3].segment == s->_segMan->getStringSegmentId()) { - SciString *string = s->_segMan->lookupString(argv[3]); - string2 = string->getRawData(); - string2Size = string->getSize(); + SciString *sstr; + sstr = s->_segMan->lookupString(argv[3]); + string2 = sstr->getRawData(); + string2Size = sstr->getSize(); } else { - Common::String string = s->_segMan->getString(argv[3]); + string = s->_segMan->getString(argv[3]); string2 = string.c_str(); string2Size = string.size() + 1; } diff --git a/engines/sci/engine/selector.cpp b/engines/sci/engine/selector.cpp index a9aca9e22f..a8b1cf7ec2 100644 --- a/engines/sci/engine/selector.cpp +++ b/engines/sci/engine/selector.cpp @@ -178,6 +178,7 @@ void Kernel::mapSelectors() { FIND_SELECTOR(dimmed); FIND_SELECTOR(fore); FIND_SELECTOR(back); + FIND_SELECTOR(skip); FIND_SELECTOR(fixPriority); FIND_SELECTOR(mirrored); FIND_SELECTOR(useInsetRect); diff --git a/engines/sci/engine/selector.h b/engines/sci/engine/selector.h index bbd86bb03e..4b913a866a 100644 --- a/engines/sci/engine/selector.h +++ b/engines/sci/engine/selector.h @@ -144,6 +144,7 @@ struct SelectorCache { Selector fore; Selector back; + Selector skip; Selector dimmed; Selector fixPriority; diff --git a/engines/sci/event.cpp b/engines/sci/event.cpp index c14cfada07..378e88b7df 100644 --- a/engines/sci/event.cpp +++ b/engines/sci/event.cpp @@ -253,14 +253,11 @@ SciEvent EventManager::getScummVMEvent() { if ((modifiers & Common::KBD_ALT) && input.character > 0 && input.character < 27) input.character += 96; // 0x01 -> 'a' - if (getSciVersion() <= SCI_VERSION_1_MIDDLE) { - // TODO: find out if altify is also not needed for sci1late+, couldnt find any game that uses those keys - // Scancodify if appropriate - if (modifiers & Common::KBD_ALT) - input.character = altify(input.character); - else if ((modifiers & Common::KBD_CTRL) && input.character > 0 && input.character < 27) - input.character += 96; // 0x01 -> 'a' - } + // Scancodify if appropriate + if (modifiers & Common::KBD_ALT) + input.character = altify(input.character); + else if ((modifiers & Common::KBD_CTRL) && input.character > 0 && input.character < 27) + input.character += 96; // 0x01 -> 'a' // If no actual key was pressed (e.g. if only a modifier key was pressed), // ignore the event diff --git a/engines/sci/graphics/controls32.cpp b/engines/sci/graphics/controls32.cpp new file mode 100644 index 0000000000..ad1d9e8623 --- /dev/null +++ b/engines/sci/graphics/controls32.cpp @@ -0,0 +1,204 @@ +/* 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/system.h" + +#include "sci/sci.h" +#include "sci/event.h" +#include "sci/engine/kernel.h" +#include "sci/engine/seg_manager.h" +#include "sci/graphics/cache.h" +#include "sci/graphics/compare.h" +#include "sci/graphics/controls32.h" +#include "sci/graphics/font.h" +#include "sci/graphics/screen.h" +#include "sci/graphics/text32.h" + +namespace Sci { + +GfxControls32::GfxControls32(SegManager *segMan, GfxCache *cache, GfxScreen *screen, GfxText32 *text) + : _segMan(segMan), _cache(cache), _screen(screen), _text(text) { +} + +GfxControls32::~GfxControls32() { +} + +void GfxControls32::kernelTexteditChange(reg_t controlObject) { + SciEvent curEvent; + uint16 maxChars = 40; //readSelectorValue(_segMan, controlObject, SELECTOR(max)); // TODO + reg_t textReference = readSelector(_segMan, controlObject, SELECTOR(text)); + GfxFont *font = _cache->getFont(readSelectorValue(_segMan, controlObject, SELECTOR(font))); + Common::String text; + uint16 textSize; + bool textChanged = false; + bool textAddChar = false; + Common::Rect rect; + + if (textReference.isNull()) + error("kEditControl called on object that doesnt have a text reference"); + text = _segMan->getString(textReference); + + // TODO: Finish this + warning("kEditText ('%s')", text.c_str()); + return; + + uint16 cursorPos = 0; + //uint16 oldCursorPos = cursorPos; + bool captureEvents = true; + EventManager* eventMan = g_sci->getEventManager(); + + while (captureEvents) { + curEvent = g_sci->getEventManager()->getSciEvent(SCI_EVENT_KEYBOARD | SCI_EVENT_PEEK); + + if (curEvent.type == SCI_EVENT_NONE) { + eventMan->getSciEvent(SCI_EVENT_KEYBOARD); // consume the event + } else { + textSize = text.size(); + + switch (curEvent.type) { + case SCI_EVENT_MOUSE_PRESS: + // TODO: Implement mouse support for cursor change + break; + case SCI_EVENT_KEYBOARD: + switch (curEvent.data) { + case SCI_KEY_BACKSPACE: + if (cursorPos > 0) { + cursorPos--; text.deleteChar(cursorPos); + textChanged = true; + } + eventMan->getSciEvent(SCI_EVENT_KEYBOARD); // consume the event + break; + case SCI_KEY_DELETE: + if (cursorPos < textSize) { + text.deleteChar(cursorPos); + textChanged = true; + } + eventMan->getSciEvent(SCI_EVENT_KEYBOARD); // consume the event + break; + case SCI_KEY_HOME: // HOME + cursorPos = 0; textChanged = true; + eventMan->getSciEvent(SCI_EVENT_KEYBOARD); // consume the event + break; + case SCI_KEY_END: // END + cursorPos = textSize; textChanged = true; + eventMan->getSciEvent(SCI_EVENT_KEYBOARD); // consume the event + break; + case SCI_KEY_LEFT: // LEFT + if (cursorPos > 0) { + cursorPos--; textChanged = true; + } + eventMan->getSciEvent(SCI_EVENT_KEYBOARD); // consume the event + break; + case SCI_KEY_RIGHT: // RIGHT + if (cursorPos + 1 <= textSize) { + cursorPos++; textChanged = true; + } + eventMan->getSciEvent(SCI_EVENT_KEYBOARD); // consume the event + break; + case 3: // returned in SCI1 late and newer when Control - C is pressed + if (curEvent.modifiers & SCI_KEYMOD_CTRL) { + // Control-C erases the whole line + cursorPos = 0; text.clear(); + textChanged = true; + } + eventMan->getSciEvent(SCI_EVENT_KEYBOARD); // consume the event + break; + case SCI_KEY_UP: + case SCI_KEY_DOWN: + case SCI_KEY_ENTER: + case SCI_KEY_ESC: + case SCI_KEY_TAB: + case SCI_KEY_SHIFT_TAB: + captureEvents = false; + break; + default: + if ((curEvent.modifiers & SCI_KEYMOD_CTRL) && curEvent.data == 99) { + // Control-C in earlier SCI games (SCI0 - SCI1 middle) + // Control-C erases the whole line + cursorPos = 0; text.clear(); + textChanged = true; + } else if (curEvent.data > 31 && curEvent.data < 256 && textSize < maxChars) { + // insert pressed character + textAddChar = true; + textChanged = true; + } + eventMan->getSciEvent(SCI_EVENT_KEYBOARD); // consume the event + break; + } + break; + } + } + + if (textChanged) { + rect = g_sci->_gfxCompare->getNSRect(controlObject); + + if (textAddChar) { + const char *textPtr = text.c_str(); + + // We check if we are really able to add the new char + uint16 textWidth = 0; + while (*textPtr) + textWidth += font->getCharWidth((byte)*textPtr++); + textWidth += font->getCharWidth(curEvent.data); + + // Does it fit? + if (textWidth >= rect.width()) { + return; + } + + text.insertChar(curEvent.data, cursorPos++); + + // Note: the following checkAltInput call might make the text + // too wide to fit, but SSCI fails to check that too. + } + + reg_t hunkId = readSelector(_segMan, controlObject, SELECTOR(bitmap)); + Common::Rect nsRect = g_sci->_gfxCompare->getNSRect(controlObject); + //texteditCursorErase(); // TODO: Cursor + + // Write back string + _segMan->strcpy(textReference, text.c_str()); + // Modify the buffer and show it + _text->createTextBitmap(controlObject, 0, 0, hunkId); + + _text->drawTextBitmap(0, 0, nsRect, controlObject); + //texteditCursorDraw(rect, text.c_str(), cursorPos); // TODO: Cursor + g_system->updateScreen(); + } else { + // TODO: Cursor + /* + if (g_system->getMillis() >= _texteditBlinkTime) { + _paint16->invertRect(_texteditCursorRect); + _paint16->bitsShow(_texteditCursorRect); + _texteditCursorVisible = !_texteditCursorVisible; + texteditSetBlinkTime(); + } + */ + } + + textAddChar = false; + textChanged = false; + g_sci->sleep(10); + } // while +} + +} // End of namespace Sci diff --git a/engines/sci/graphics/controls32.h b/engines/sci/graphics/controls32.h new file mode 100644 index 0000000000..68dca59462 --- /dev/null +++ b/engines/sci/graphics/controls32.h @@ -0,0 +1,51 @@ +/* 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 SCI_GRAPHICS_CONTROLS32_H +#define SCI_GRAPHICS_CONTROLS32_H + +namespace Sci { + +class GfxCache; +class GfxScreen; +class GfxText32; + +/** + * Controls class, handles drawing of controls in SCI32 (SCI2, SCI2.1, SCI3) games + */ +class GfxControls32 { +public: + GfxControls32(SegManager *segMan, GfxCache *cache, GfxScreen *screen, GfxText32 *text); + ~GfxControls32(); + + void kernelTexteditChange(reg_t controlObject); + +private: + SegManager *_segMan; + GfxCache *_cache; + GfxScreen *_screen; + GfxText32 *_text; +}; + +} // End of namespace Sci + +#endif diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index a41efd6a9f..aa53576b13 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -488,12 +488,10 @@ void GfxFrameout::kernelFrameout() { itemEntry->picture->drawSci32Vga(itemEntry->celNo, pictureX, itemEntry->y, pictureOffsetX, pictureOffsetY, it->planePictureMirrored); // warning("picture cel %d %d", itemEntry->celNo, itemEntry->priority); - } else if (itemEntry->viewId != 0xFFFF) { - GfxView *view = _cache->getView(itemEntry->viewId); - -// warning("view %s %04x:%04x", _segMan->getObjectName(itemEntry->object), PRINT_REG(itemEntry->object)); - - if (view->isSci2Hires()) { + } else { + GfxView *view = (itemEntry->viewId != 0xFFFF) ? _cache->getView(itemEntry->viewId) : NULL; + + if (view && view->isSci2Hires()) { int16 dummyX = 0; view->adjustToUpscaledCoordinates(itemEntry->y, itemEntry->x); view->adjustToUpscaledCoordinates(itemEntry->z, dummyX); @@ -513,24 +511,27 @@ void GfxFrameout::kernelFrameout() { itemEntry->celRect.left = readSelectorValue(_segMan, itemEntry->object, SELECTOR(inLeft)); itemEntry->celRect.bottom = readSelectorValue(_segMan, itemEntry->object, SELECTOR(inBottom)) + 1; itemEntry->celRect.right = readSelectorValue(_segMan, itemEntry->object, SELECTOR(inRight)) + 1; - if (view->isSci2Hires()) { + if (view && view->isSci2Hires()) { view->adjustToUpscaledCoordinates(itemEntry->celRect.top, itemEntry->celRect.left); view->adjustToUpscaledCoordinates(itemEntry->celRect.bottom, itemEntry->celRect.right); } itemEntry->celRect.translate(itemEntry->x, itemEntry->y); // TODO: maybe we should clip the cels rect with this, i'm not sure // the only currently known usage is game menu of gk1 - } else { - if ((itemEntry->scaleX == 128) && (itemEntry->scaleY == 128)) - view->getCelRect(itemEntry->loopNo, itemEntry->celNo, itemEntry->x, itemEntry->y, itemEntry->z, itemEntry->celRect); - else - view->getCelScaledRect(itemEntry->loopNo, itemEntry->celNo, itemEntry->x, itemEntry->y, itemEntry->z, itemEntry->scaleX, itemEntry->scaleY, itemEntry->celRect); + } else if (view) { + if ((itemEntry->scaleX == 128) && (itemEntry->scaleY == 128)) + view->getCelRect(itemEntry->loopNo, itemEntry->celNo, + itemEntry->x, itemEntry->y, itemEntry->z, itemEntry->celRect); + else + view->getCelScaledRect(itemEntry->loopNo, itemEntry->celNo, + itemEntry->x, itemEntry->y, itemEntry->z, itemEntry->scaleX, + itemEntry->scaleY, itemEntry->celRect); Common::Rect nsRect = itemEntry->celRect; // Translate back to actual coordinate within scrollable plane nsRect.translate(it->planeOffsetX, it->planeOffsetY); - if (view->isSci2Hires()) { + if (view && view->isSci2Hires()) { view->adjustBackUpscaledCoordinates(nsRect.top, nsRect.left); view->adjustBackUpscaledCoordinates(nsRect.bottom, nsRect.right); } else if (getSciVersion() == SCI_VERSION_2_1) { @@ -552,7 +553,7 @@ void GfxFrameout::kernelFrameout() { int16 screenHeight = _screen->getHeight(); int16 screenWidth = _screen->getWidth(); - if (view->isSci2Hires()) { + if (view && view->isSci2Hires()) { screenHeight = _screen->getDisplayHeight(); screenWidth = _screen->getDisplayWidth(); } @@ -565,7 +566,8 @@ void GfxFrameout::kernelFrameout() { Common::Rect clipRect, translatedClipRect; clipRect = itemEntry->celRect; - if (view->isSci2Hires()) { + + if (view && view->isSci2Hires()) { clipRect.clip(it->upscaledPlaneClipRect); translatedClipRect = clipRect; translatedClipRect.translate(it->upscaledPlaneRect.left, it->upscaledPlaneRect.top); @@ -575,16 +577,20 @@ void GfxFrameout::kernelFrameout() { translatedClipRect.translate(it->planeRect.left, it->planeRect.top); } - if (!clipRect.isEmpty()) { - if ((itemEntry->scaleX == 128) && (itemEntry->scaleY == 128)) - view->draw(itemEntry->celRect, clipRect, translatedClipRect, itemEntry->loopNo, itemEntry->celNo, 255, 0, view->isSci2Hires()); - else - view->drawScaled(itemEntry->celRect, clipRect, translatedClipRect, itemEntry->loopNo, itemEntry->celNo, 255, itemEntry->scaleX, itemEntry->scaleY); + if (view) { + if (!clipRect.isEmpty()) { + if ((itemEntry->scaleX == 128) && (itemEntry->scaleY == 128)) + view->draw(itemEntry->celRect, clipRect, translatedClipRect, + itemEntry->loopNo, itemEntry->celNo, 255, 0, view->isSci2Hires()); + else + view->drawScaled(itemEntry->celRect, clipRect, translatedClipRect, + itemEntry->loopNo, itemEntry->celNo, 255, itemEntry->scaleX, itemEntry->scaleY); + } } - } else { - // Most likely a text entry + + // Draw text, if it exists if (lookupSelector(_segMan, itemEntry->object, SELECTOR(text), NULL, NULL) == kSelectorVariable) { - g_sci->_gfxText32->drawTextBitmap(itemEntry->object); + g_sci->_gfxText32->drawTextBitmap(itemEntry->x, itemEntry->y, it->planeRect, itemEntry->object); } } } diff --git a/engines/sci/graphics/text32.cpp b/engines/sci/graphics/text32.cpp index 029030165d..fd6637f313 100644 --- a/engines/sci/graphics/text32.cpp +++ b/engines/sci/graphics/text32.cpp @@ -41,6 +41,10 @@ namespace Sci { #define BITMAP_HEADER_SIZE 46 +#define SCI_TEXT32_ALIGNMENT_RIGHT -1 +#define SCI_TEXT32_ALIGNMENT_CENTER 1 +#define SCI_TEXT32_ALIGNMENT_LEFT 0 + GfxText32::GfxText32(SegManager *segMan, GfxCache *fonts, GfxScreen *screen) : _segMan(segMan), _cache(fonts), _screen(screen) { } @@ -48,7 +52,7 @@ GfxText32::GfxText32(SegManager *segMan, GfxCache *fonts, GfxScreen *screen) GfxText32::~GfxText32() { } -reg_t GfxText32::createTextBitmap(reg_t textObject, uint16 maxWidth, uint16 maxHeight) { +reg_t GfxText32::createTextBitmap(reg_t textObject, uint16 maxWidth, uint16 maxHeight, reg_t prevHunk) { reg_t stringObject = readSelector(_segMan, textObject, SELECTOR(text)); // The object in the text selector of the item can be either a raw string @@ -58,13 +62,21 @@ reg_t GfxText32::createTextBitmap(reg_t textObject, uint16 maxWidth, uint16 maxH stringObject = readSelector(_segMan, stringObject, SELECTOR(data)); Common::String text = _segMan->getString(stringObject); - GfxFont *font = _cache->getFont(readSelectorValue(_segMan, textObject, SELECTOR(font))); + // HACK: The character offsets of the up and down arrow buttons are off by one + // in GK1, for some unknown reason. Fix them here. + if (text.size() == 1 && (text[0] == 29 || text[0] == 30)) { + text.setChar(text[0] + 1, 0); + } + GuiResourceId fontId = readSelectorValue(_segMan, textObject, SELECTOR(font)); + GfxFont *font = _cache->getFont(fontId); bool dimmed = readSelectorValue(_segMan, textObject, SELECTOR(dimmed)); + int16 alignment = readSelectorValue(_segMan, textObject, SELECTOR(mode)); uint16 foreColor = readSelectorValue(_segMan, textObject, SELECTOR(fore)); + uint16 backColor = readSelectorValue(_segMan, textObject, SELECTOR(back)); - Common::Rect planeRect = getPlaneRect(textObject); - uint16 width = planeRect.width() + 1; - uint16 height = planeRect.height() + 1; + Common::Rect nsRect = g_sci->_gfxCompare->getNSRect(textObject); + uint16 width = nsRect.width() + 1; + uint16 height = nsRect.height() + 1; // Limit rectangle dimensions, if requested if (maxWidth > 0) @@ -79,24 +91,74 @@ reg_t GfxText32::createTextBitmap(reg_t textObject, uint16 maxWidth, uint16 maxH } int entrySize = width * height + BITMAP_HEADER_SIZE; - reg_t memoryId = _segMan->allocateHunkEntry("TextBitmap()", entrySize); - writeSelector(_segMan, textObject, SELECTOR(bitmap), memoryId); + reg_t memoryId = NULL_REG; + if (prevHunk.isNull()) { + memoryId = _segMan->allocateHunkEntry("TextBitmap()", entrySize); + writeSelector(_segMan, textObject, SELECTOR(bitmap), memoryId); + } else { + memoryId = prevHunk; + } byte *memoryPtr = _segMan->getHunkPointer(memoryId); - memset(memoryPtr, 0, entrySize); + + if (prevHunk.isNull()) + memset(memoryPtr, 0, BITMAP_HEADER_SIZE); + byte *bitmap = memoryPtr + BITMAP_HEADER_SIZE; + memset(bitmap, backColor, width * height); + + // Save totalWidth, totalHeight + WRITE_LE_UINT16(memoryPtr, width); + WRITE_LE_UINT16(memoryPtr + 2, height); int16 charCount = 0; uint16 curX = 0, curY = 0; const char *txt = text.c_str(); + int16 textWidth, textHeight, totalHeight = 0, offsetX = 0, offsetY = 0; + uint16 start = 0; + // Calculate total text height while (*txt) { charCount = GetLongest(txt, width, font); if (charCount == 0) break; + Width(txt, 0, (int16)strlen(txt), fontId, textWidth, textHeight, true); + + totalHeight += textHeight; + txt += charCount; + while (*txt == ' ') + txt++; // skip over breaking spaces + } + + txt = text.c_str(); + + // Draw text in buffer + while (*txt) { + charCount = GetLongest(txt, width, font); + if (charCount == 0) + break; + Width(txt, start, charCount, fontId, textWidth, textHeight, true); + + switch (alignment) { + case SCI_TEXT32_ALIGNMENT_RIGHT: + offsetX = width - textWidth; + break; + case SCI_TEXT32_ALIGNMENT_CENTER: + // Center text both horizontally and vertically + offsetX = (width - textWidth) / 2; + offsetY = (height - totalHeight) / 2; + break; + case SCI_TEXT32_ALIGNMENT_LEFT: + offsetX = 0; + break; + + default: + warning("Invalid alignment %d used in TextBox()", alignment); + } + for (int i = 0; i < charCount; i++) { unsigned char curChar = txt[i]; - font->drawToBuffer(curChar, curY, curX, foreColor, dimmed, bitmap, width, height); + font->drawToBuffer(curChar, curY + offsetY, curX + offsetX, foreColor, dimmed, bitmap, width, height); curX += font->getCharWidth(curChar); } @@ -114,7 +176,7 @@ void GfxText32::disposeTextBitmap(reg_t hunkId) { _segMan->freeHunkEntry(hunkId); } -void GfxText32::drawTextBitmap(reg_t textObject) { +void GfxText32::drawTextBitmap(uint16 x, uint16 y, Common::Rect planeRect, reg_t textObject) { reg_t hunkId = readSelector(_segMan, textObject, SELECTOR(bitmap)); // Sanity check: Check if the hunk is set. If not, either the game scripts // didn't set it, or an old saved game has been loaded, where it wasn't set. @@ -129,46 +191,28 @@ void GfxText32::drawTextBitmap(reg_t textObject) { byte *surface = memoryPtr + BITMAP_HEADER_SIZE; int curByte = 0; - Common::Rect nsRect = g_sci->_gfxCompare->getNSRect(textObject); - Common::Rect planeRect = getPlaneRect(textObject); - uint16 x = readSelectorValue(_segMan, textObject, SELECTOR(x)); - uint16 y = readSelectorValue(_segMan, textObject, SELECTOR(y)); + uint16 skipColor = readSelectorValue(_segMan, textObject, SELECTOR(skip)); uint16 textX = planeRect.left + x; uint16 textY = planeRect.top + y; - uint16 width = nsRect.width() + 1; - uint16 height = nsRect.height() + 1; + // Get totalWidth, totalHeight + uint16 width = READ_LE_UINT16(memoryPtr); + uint16 height = READ_LE_UINT16(memoryPtr + 2); // Upscale the coordinates/width if the fonts are already upscaled if (_screen->fontIsUpscaled()) { textX = textX * _screen->getDisplayWidth() / _screen->getWidth(); textY = textY * _screen->getDisplayHeight() / _screen->getHeight(); - width = width * _screen->getDisplayWidth() / _screen->getWidth(); - height = height * _screen->getDisplayHeight() / _screen->getHeight(); } for (int curY = 0; curY < height; curY++) { for (int curX = 0; curX < width; curX++) { byte pixel = surface[curByte++]; - if (pixel) + if (pixel != skipColor) _screen->putFontPixel(textY, curX + textX, curY, pixel); } } } -Common::Rect GfxText32::getPlaneRect(reg_t textObject) { - Common::Rect planeRect(0, 0, _screen->getWidth(), _screen->getHeight()); - - reg_t planeObject = readSelector(_segMan, textObject, SELECTOR(plane)); - if (!planeObject.isNull()) { - planeRect.top = readSelectorValue(_segMan, planeObject, SELECTOR(top)); - planeRect.left = readSelectorValue(_segMan, planeObject, SELECTOR(left)); - planeRect.bottom = readSelectorValue(_segMan, planeObject, SELECTOR(bottom)); - planeRect.right = readSelectorValue(_segMan, planeObject, SELECTOR(right)); - } - - return planeRect; -} - int16 GfxText32::GetLongest(const char *text, int16 maxWidth, GfxFont *font) { uint16 curChar = 0; int16 maxChars = 0, curCharCount = 0; diff --git a/engines/sci/graphics/text32.h b/engines/sci/graphics/text32.h index dfcbf63ccf..3a411ce663 100644 --- a/engines/sci/graphics/text32.h +++ b/engines/sci/graphics/text32.h @@ -35,9 +35,9 @@ class GfxText32 { public: GfxText32(SegManager *segMan, GfxCache *fonts, GfxScreen *screen); ~GfxText32(); - reg_t createTextBitmap(reg_t textObject, uint16 maxWidth = 0, uint16 maxHeight = 0); + reg_t createTextBitmap(reg_t textObject, uint16 maxWidth = 0, uint16 maxHeight = 0, reg_t prevHunk = NULL_REG); void disposeTextBitmap(reg_t hunkId); - void drawTextBitmap(reg_t textObject); + void drawTextBitmap(uint16 x, uint16 y, Common::Rect planeRect, reg_t textObject); int16 GetLongest(const char *text, int16 maxWidth, GfxFont *font); void kernelTextSize(const char *text, int16 font, int16 maxWidth, int16 *textWidth, int16 *textHeight); @@ -46,7 +46,6 @@ private: int16 Size(Common::Rect &rect, const char *text, GuiResourceId fontId, int16 maxWidth); void Width(const char *text, int16 from, int16 len, GuiResourceId orgFontId, int16 &textWidth, int16 &textHeight, bool restoreFont); void StringWidth(const char *str, GuiResourceId orgFontId, int16 &textWidth, int16 &textHeight); - Common::Rect getPlaneRect(reg_t textObject); SegManager *_segMan; GfxCache *_cache; diff --git a/engines/sci/module.mk b/engines/sci/module.mk index 828a36298d..25fbbab207 100644 --- a/engines/sci/module.mk +++ b/engines/sci/module.mk @@ -78,6 +78,7 @@ MODULE_OBJS := \ ifdef ENABLE_SCI32 MODULE_OBJS += \ + graphics/controls32.o \ graphics/frameout.o \ graphics/paint32.o \ graphics/text32.o \ diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index c50d1b8d8a..9171e5e5d9 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -169,8 +169,11 @@ ResourceType ResourceManager::convertResType(byte type) { if (type < ARRAYSIZE(s_resTypeMapSci21)) { // LSL6 hires doesn't have the chunk resource type, to match // the resource types of the lowres version, thus we use the - // older resource types here - if (g_sci && g_sci->getGameId() == GID_LSL6HIRES) + // older resource types here. + // PQ4 CD and QFG4 CD are SCI2.1, but use the resource types of the + // corresponding SCI2 floppy disk versions. + if (g_sci && (g_sci->getGameId() == GID_LSL6HIRES || + g_sci->getGameId() == GID_QFG4 || g_sci->getGameId() == GID_PQ4)) return s_resTypeMapSci0[type]; else return s_resTypeMapSci21[type]; diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index 2dc8c95fec..6eeed66e4f 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -47,6 +47,7 @@ #include "sci/graphics/cache.h" #include "sci/graphics/compare.h" #include "sci/graphics/controls16.h" +#include "sci/graphics/controls32.h" #include "sci/graphics/coordadjuster.h" #include "sci/graphics/cursor.h" #include "sci/graphics/maciconbar.h" @@ -113,6 +114,7 @@ SciEngine::SciEngine(OSystem *syst, const ADGameDescription *desc, SciGameId gam DebugMan.addDebugChannel(kDebugLevelGC, "GC", "Garbage Collector debugging"); DebugMan.addDebugChannel(kDebugLevelResMan, "ResMan", "Resource manager debugging"); DebugMan.addDebugChannel(kDebugLevelOnStartup, "OnStartup", "Enter debugger at start of game"); + DebugMan.addDebugChannel(kDebugLevelDebugMode, "DebugMode", "Enable game debug mode at start of game"); const Common::FSNode gameDataDir(ConfMan.get("path")); @@ -147,6 +149,7 @@ SciEngine::~SciEngine() { DebugMan.clearAllDebugChannels(); #ifdef ENABLE_SCI32 + delete _gfxControls32; delete _gfxText32; delete _robotDecoder; delete _gfxFrameout; @@ -600,6 +603,7 @@ void SciEngine::initGraphics() { _gfxText16 = 0; _gfxTransitions = 0; #ifdef ENABLE_SCI32 + _gfxControls32 = 0; _gfxText32 = 0; _robotDecoder = 0; _gfxFrameout = 0; @@ -622,6 +626,7 @@ void SciEngine::initGraphics() { _gfxPaint32 = new GfxPaint32(_resMan, _gamestate->_segMan, _kernel, _gfxCoordAdjuster, _gfxCache, _gfxScreen, _gfxPalette); _gfxPaint = _gfxPaint32; _gfxText32 = new GfxText32(_gamestate->_segMan, _gfxCache, _gfxScreen); + _gfxControls32 = new GfxControls32(_gamestate->_segMan, _gfxCache, _gfxScreen, _gfxText32); _robotDecoder = new RobotDecoder(g_system->getMixer(), getPlatform() == Common::kPlatformMacintosh); _gfxFrameout = new GfxFrameout(_gamestate->_segMan, _resMan, _gfxCoordAdjuster, _gfxCache, _gfxScreen, _gfxPalette, _gfxPaint32); } else { diff --git a/engines/sci/sci.h b/engines/sci/sci.h index e76b71b61e..9bead768a6 100644 --- a/engines/sci/sci.h +++ b/engines/sci/sci.h @@ -60,6 +60,7 @@ class GfxAnimate; class GfxCache; class GfxCompare; class GfxControls16; +class GfxControls32; class GfxCoordAdjuster; class GfxCursor; class GfxMacIconBar; @@ -101,7 +102,8 @@ enum kDebugLevels { kDebugLevelScripts = 1 << 17, kDebugLevelGC = 1 << 18, kDebugLevelResMan = 1 << 19, - kDebugLevelOnStartup = 1 << 20 + kDebugLevelOnStartup = 1 << 20, + kDebugLevelDebugMode = 1 << 21 }; enum SciGameId { @@ -304,6 +306,7 @@ public: GfxCache *_gfxCache; GfxCompare *_gfxCompare; GfxControls16 *_gfxControls16; // Controls for 16-bit gfx + GfxControls32 *_gfxControls32; // Controls for 32-bit gfx GfxCoordAdjuster *_gfxCoordAdjuster; GfxCursor *_gfxCursor; GfxMenu *_gfxMenu; // Menu for 16-bit gfx diff --git a/engines/sword1/animation.cpp b/engines/sword1/animation.cpp index 324154f709..d55a08293e 100644 --- a/engines/sword1/animation.cpp +++ b/engines/sword1/animation.cpp @@ -28,6 +28,7 @@ #include "sword1/sword1.h" #include "sword1/animation.h" #include "sword1/text.h" +#include "sword1/resman.h" #include "common/str.h" #include "common/system.h" @@ -65,8 +66,8 @@ static const char *const sequenceList[20] = { // Basic movie player /////////////////////////////////////////////////////////////////////////////// -MoviePlayer::MoviePlayer(SwordEngine *vm, Text *textMan, Audio::Mixer *snd, OSystem *system, Audio::SoundHandle *bgSoundHandle, Video::VideoDecoder *decoder, DecoderType decoderType) - : _vm(vm), _textMan(textMan), _snd(snd), _bgSoundHandle(bgSoundHandle), _system(system) { +MoviePlayer::MoviePlayer(SwordEngine *vm, Text *textMan, ResMan *resMan, Audio::Mixer *snd, OSystem *system, Audio::SoundHandle *bgSoundHandle, Video::VideoDecoder *decoder, DecoderType decoderType) + : _vm(vm), _textMan(textMan), _resMan(resMan), _snd(snd), _bgSoundHandle(bgSoundHandle), _system(system) { _bgSoundStream = NULL; _decoderType = decoderType; _decoder = decoder; @@ -183,8 +184,8 @@ void MoviePlayer::performPostProcessing(byte *screen) { _textMan->makeTextSprite(2, (const uint8 *)_movieTexts.front()._text.c_str(), 600, LETTER_COL); FrameHeader *frame = _textMan->giveSpriteData(2); - _textWidth = frame->width; - _textHeight = frame->height; + _textWidth = _resMan->toUint16(frame->width); + _textHeight = _resMan->toUint16(frame->height); _textX = 320 - _textWidth / 2; _textY = 420 - _textHeight; } @@ -323,7 +324,7 @@ uint32 DXADecoderWithSound::getElapsedTime() const { // Factory function for creating the appropriate cutscene player /////////////////////////////////////////////////////////////////////////////// -MoviePlayer *makeMoviePlayer(uint32 id, SwordEngine *vm, Text *textMan, Audio::Mixer *snd, OSystem *system) { +MoviePlayer *makeMoviePlayer(uint32 id, SwordEngine *vm, Text *textMan, ResMan *resMan, Audio::Mixer *snd, OSystem *system) { Common::String filename; Audio::SoundHandle *bgSoundHandle = new Audio::SoundHandle; @@ -331,7 +332,7 @@ MoviePlayer *makeMoviePlayer(uint32 id, SwordEngine *vm, Text *textMan, Audio::M if (Common::File::exists(filename)) { Video::SmackerDecoder *smkDecoder = new Video::SmackerDecoder(snd); - return new MoviePlayer(vm, textMan, snd, system, bgSoundHandle, smkDecoder, kVideoDecoderSMK); + return new MoviePlayer(vm, textMan, resMan, snd, system, bgSoundHandle, smkDecoder, kVideoDecoderSMK); } filename = Common::String::format("%s.dxa", sequenceList[id]); @@ -339,7 +340,7 @@ MoviePlayer *makeMoviePlayer(uint32 id, SwordEngine *vm, Text *textMan, Audio::M if (Common::File::exists(filename)) { #ifdef USE_ZLIB DXADecoderWithSound *dxaDecoder = new DXADecoderWithSound(snd, bgSoundHandle); - return new MoviePlayer(vm, textMan, snd, system, bgSoundHandle, dxaDecoder, kVideoDecoderDXA); + return new MoviePlayer(vm, textMan, resMan, snd, system, bgSoundHandle, dxaDecoder, kVideoDecoderDXA); #else GUI::MessageDialog dialog(_("DXA cutscenes found but ScummVM has been built without zlib support"), _("OK")); dialog.runModal(); diff --git a/engines/sword1/animation.h b/engines/sword1/animation.h index fc3061bbf9..1c03c66342 100644 --- a/engines/sword1/animation.h +++ b/engines/sword1/animation.h @@ -67,7 +67,7 @@ private: class MoviePlayer { public: - MoviePlayer(SwordEngine *vm, Text *textMan, Audio::Mixer *snd, OSystem *system, Audio::SoundHandle *bgSoundHandle, Video::VideoDecoder *decoder, DecoderType decoderType); + MoviePlayer(SwordEngine *vm, Text *textMan, ResMan *resMan, Audio::Mixer *snd, OSystem *system, Audio::SoundHandle *bgSoundHandle, Video::VideoDecoder *decoder, DecoderType decoderType); virtual ~MoviePlayer(); bool load(uint32 id); void play(); @@ -75,6 +75,7 @@ public: protected: SwordEngine *_vm; Text *_textMan; + ResMan *_resMan; Audio::Mixer *_snd; OSystem *_system; Common::List<MovieText> _movieTexts; @@ -93,7 +94,7 @@ protected: byte findWhitePalIndex(); }; -MoviePlayer *makeMoviePlayer(uint32 id, SwordEngine *vm, Text *textMan, Audio::Mixer *snd, OSystem *system); +MoviePlayer *makeMoviePlayer(uint32 id, SwordEngine *vm, Text *textMan, ResMan *resMan, Audio::Mixer *snd, OSystem *system); } // End of namespace Sword1 diff --git a/engines/sword1/logic.cpp b/engines/sword1/logic.cpp index d1c69c80ff..9d92a29a63 100644 --- a/engines/sword1/logic.cpp +++ b/engines/sword1/logic.cpp @@ -959,7 +959,7 @@ int Logic::fnPlaySequence(Object *cpt, int32 id, int32 sequenceId, int32 d, int3 // meantime, we don't want any looping sound effects still playing. _sound->quitScreen(); - MoviePlayer *player = makeMoviePlayer(sequenceId, _vm, _textMan, _mixer, _system); + MoviePlayer *player = makeMoviePlayer(sequenceId, _vm, _textMan, _resMan, _mixer, _system); if (player) { _screen->clearScreen(); if (player->load(sequenceId)) diff --git a/engines/tsage/blue_force/blueforce_logic.cpp b/engines/tsage/blue_force/blueforce_logic.cpp index 91fd5d3197..77609715c7 100644 --- a/engines/tsage/blue_force/blueforce_logic.cpp +++ b/engines/tsage/blue_force/blueforce_logic.cpp @@ -955,7 +955,7 @@ void SceneHandlerExt::process(Event &event) { return; } - // If the user clicks the button whislt the introduction is active, prompt for playing the game + // If the user clicks the button whilst the introduction is active, prompt for playing the game if ((BF_GLOBALS._dayNumber == 0) && (event.eventType == EVENT_BUTTON_DOWN)) { // Prompt user for whether to start play or watch introduction BF_GLOBALS._player.enableControl(); diff --git a/engines/tsage/blue_force/blueforce_scenes0.cpp b/engines/tsage/blue_force/blueforce_scenes0.cpp index bb283d051e..69a2273237 100644 --- a/engines/tsage/blue_force/blueforce_scenes0.cpp +++ b/engines/tsage/blue_force/blueforce_scenes0.cpp @@ -121,7 +121,7 @@ void Scene20::Action1::signal() { void Scene20::postInit(SceneObjectList *OwnerList) { loadScene(20); - Scene::postInit(); + SceneExt::postInit(); setZoomPercents(60, 85, 200, 100); BF_GLOBALS._interfaceY = SCREEN_HEIGHT; diff --git a/engines/tsage/blue_force/blueforce_scenes1.cpp b/engines/tsage/blue_force/blueforce_scenes1.cpp index 425446d6fb..c73f3f8499 100644 --- a/engines/tsage/blue_force/blueforce_scenes1.cpp +++ b/engines/tsage/blue_force/blueforce_scenes1.cpp @@ -243,8 +243,8 @@ void Scene109::Action1::signal() { scene->_drunk.show(); scene->_drunk.setAction(&scene->_action3); scene->_object2.show(); - scene->_object9.show(); - scene->_object9.setAction(&scene->_action2); + scene->_beerSign.show(); + scene->_beerSign.setAction(&scene->_action2); BF_GLOBALS._v501FC = 170; setDelay(60); @@ -257,27 +257,27 @@ void Scene109::Action1::signal() { break; case 5: // Open briefcase and pass over disk - setAction(&scene->_sequenceManager6, this, 105, &scene->_object10, NULL); + setAction(&scene->_sequenceManager6, this, 105, &scene->_animationInset, NULL); break; case 6: // Protaginist 2 walk to the bar - scene->_object10.remove(); + scene->_animationInset.remove(); setAction(&scene->_sequenceManager6, this, 100, &scene->_protaginist2, NULL); break; case 7: // Two thugs enter and walk to table - scene->_object7.setAction(&scene->_sequenceManager7, NULL, 103, &scene->_object7, NULL); - scene->_object5.setAction(&scene->_sequenceManager8, this, 102, &scene->_object5, NULL); + scene->_cop2.setAction(&scene->_sequenceManager7, NULL, 103, &scene->_cop2, NULL); + scene->_cop1.setAction(&scene->_sequenceManager8, this, 102, &scene->_cop1, NULL); scene->_protaginist2.setAction(&scene->_sequenceManager6, NULL, 104, &scene->_protaginist2, &scene->_bartender, NULL); break; case 8: // Protaginist 1 leaves, protaginist 2 stands up - setAction(&scene->_sequenceManager8, this, 101, &scene->_object5, &scene->_protaginist1, NULL); + setAction(&scene->_sequenceManager8, this, 101, &scene->_cop1, &scene->_protaginist1, NULL); break; case 9: // Shots fired! scene->_protaginist1.setAction(&scene->_sequenceManager5, this, 98, &scene->_protaginist1, NULL); - scene->_object7.setAction(&scene->_sequenceManager7, NULL, 99, &scene->_object7, NULL); + scene->_cop2.setAction(&scene->_sequenceManager7, NULL, 99, &scene->_cop2, NULL); break; case 10: // End scene @@ -289,12 +289,12 @@ void Scene109::Action1::signal() { void Scene109::Action2::signal() { Scene109 *scene = (Scene109 *)BF_GLOBALS._sceneManager._scene; - scene->setAction(&scene->_sequenceManager2, this, 3117, &scene->_object9, NULL); + setAction(&scene->_sequenceManager2, this, 3117, &scene->_beerSign, NULL); } void Scene109::Action3::signal() { Scene109 *scene = (Scene109 *)BF_GLOBALS._sceneManager._scene; - scene->setAction(&scene->_sequenceManager3, this, 108, &scene->_drunk, NULL); + setAction(&scene->_sequenceManager3, this, 108, &scene->_drunk, NULL); } /*--------------------------------------------------------------------------*/ @@ -353,21 +353,21 @@ void Scene109::postInit(SceneObjectList *OwnerList) { _object2.setPosition(Common::Point(104, 64)); _object2.hide(); - _object9.postInit(); - _object9.setVisage(115); - _object9.setStrip(4); - _object9.setFrame(1); - _object9.setPosition(Common::Point(262, 29)); - _object9.hide(); + _beerSign.postInit(); + _beerSign.setVisage(115); + _beerSign.setStrip(4); + _beerSign.setFrame(1); + _beerSign.setPosition(Common::Point(262, 29)); + _beerSign.hide(); - _object5.postInit(); - _object5.hide(); + _cop1.postInit(); + _cop1.hide(); - _object7.postInit(); - _object7.hide(); + _cop2.postInit(); + _cop2.hide(); - _object10.postInit(); - _object10.hide(); + _animationInset.postInit(); + _animationInset.hide(); BF_GLOBALS._player.disableControl(); setAction(&_action1, this); diff --git a/engines/tsage/blue_force/blueforce_scenes1.h b/engines/tsage/blue_force/blueforce_scenes1.h index bdf414ec9b..403fbfbab6 100644 --- a/engines/tsage/blue_force/blueforce_scenes1.h +++ b/engines/tsage/blue_force/blueforce_scenes1.h @@ -99,11 +99,12 @@ public: SequenceManager _sequenceManager1, _sequenceManager2, _sequenceManager3; SequenceManager _sequenceManager4, _sequenceManager5, _sequenceManager6; SequenceManager _sequenceManager7, _sequenceManager8; - SceneObject _object1, _object2, _protaginist2, _protaginist1, _object5; - SceneObject _drunk, _object7, _bartender, _object9, _object10; + SceneObject _object1, _object2, _protaginist2, _protaginist1, _cop1; + SceneObject _drunk, _cop2, _bartender, _beerSign, _animationInset; IntroSceneText _text; Action1 _action1; - Action _action2, _action3; + Action2 _action2; + Action3 _action3; public: Scene109(); diff --git a/engines/tsage/blue_force/blueforce_scenes3.cpp b/engines/tsage/blue_force/blueforce_scenes3.cpp index d1ed2cd5e6..3d42304926 100644 --- a/engines/tsage/blue_force/blueforce_scenes3.cpp +++ b/engines/tsage/blue_force/blueforce_scenes3.cpp @@ -58,7 +58,7 @@ bool Scene300::Object19::startAction(CursorType action, Event &event) { return true; } - +// entrance door bool Scene300::Item1::startAction(CursorType action, Event &event) { if (action == CURSOR_USE) { Scene300 *scene = (Scene300 *)BF_GLOBALS._sceneManager._scene; @@ -75,6 +75,8 @@ bool Scene300::Item1::startAction(CursorType action, Event &event) { bool Scene300::Item2::startAction(CursorType action, Event &event) { if ((action == CURSOR_LOOK) || (action == CURSOR_USE)) { Scene300 *scene = (Scene300 *)BF_GLOBALS._sceneManager._scene; + BF_GLOBALS._player.disableControl(); + scene->_sceneMode = 0; scene->setAction(&scene->_sequenceManager1, scene, 304, &scene->_object11, NULL); return true; } else { @@ -108,7 +110,7 @@ void Scene300::Action1::signal() { setDelay(1); break; case 2: { - ADD_PLAYER_MOVER_THIS(BF_GLOBALS._player, BF_GLOBALS._player._position.x - 8, + ADD_MOVER(BF_GLOBALS._player, BF_GLOBALS._player._position.x - 8, BF_GLOBALS._player._position.y); break; } @@ -183,12 +185,13 @@ void Scene300::Action4::signal() { break; case 2: BF_GLOBALS._sceneManager.changeScene(60); + setDelay(15); break; case 3: setAction(&scene->_sequenceManager1, this, 319, &scene->_object19, NULL); break; case 4: - BF_GLOBALS.setFlag(2); + BF_GLOBALS.setFlag(onBike); BF_GLOBALS._sceneManager.changeScene(190); break; default: @@ -213,6 +216,7 @@ void Scene300::Action5::signal() { break; case 3: { ADD_PLAYER_MOVER_NULL(BF_GLOBALS._player, 186, 140); + setDelay(3); break; } case 4: @@ -474,10 +478,10 @@ void Scene300::signal() { _object10.postInit(); _object10.hide(); - if (BF_GLOBALS.getFlag(1)) { + if (BF_GLOBALS.getFlag(gunClean)) { BF_GLOBALS._player.disableControl(); _sceneMode = 4308; - setAction(&_sequenceManager1, this, 6307, &_object2, &_object1, &_object9, &_object10, NULL); + setAction(&_sequenceManager1, this, 6307, &_object12, &_object1, &_object9, &_object10, NULL); } else { BF_GLOBALS._player.disableControl(); _sceneMode = 4308; @@ -638,7 +642,7 @@ bool Scene315::Barry::startAction(CursorType action, Event &event) { switch (action) { case CURSOR_USE: - if (scene->_field1B60 || scene->_field1B64) + if (scene->_invGreenCount || scene->_invGangCount) SceneItem::display2(320, 51); else NamedHotspot::startAction(action, event); @@ -667,7 +671,7 @@ bool Scene315::Barry::startAction(CursorType action, Event &event) { scene->_stripNumber = 3174; scene->setAction(&scene->_action1); } else { - ++scene->_field1B62; + ++scene->_bookGreenCount; scene->_stripNumber = (action == INV_GREENS_GUN) ? 3168 : 0; scene->_sceneMode = 3153; scene->setAction(&scene->_sequenceManager, scene, 3153, &BF_GLOBALS._player, NULL); @@ -717,8 +721,8 @@ bool Scene315::Barry::startAction(CursorType action, Event &event) { scene->_stripNumber = 3174; scene->setAction(&scene->_action1); } else { - ++scene->_field1B66; - if (!scene->_field1B6C && (scene->_field1B66 == 1)) { + ++scene->_bookGangCount; + if (!scene->_field1B6C && (scene->_bookGangCount == 1)) { scene->_field1B6C = 1; scene->_stripNumber = 3169; } else { @@ -759,9 +763,9 @@ bool Scene315::SutterSlot::startAction(CursorType action, Event &event) { case INV_BOOKING_FRANKIE: case INV_BOOKING_GANG: if (action == INV_BOOKING_GREEN) - ++scene->_field1B62; + ++scene->_bookGreenCount; else - ++scene->_field1B66; + ++scene->_bookGangCount; BF_GLOBALS._player.disableControl(); scene->_sceneMode = 12; @@ -874,6 +878,7 @@ bool Scene315::BulletinMemo::startAction(CursorType action, Event &event) { } } +// Own Mail Slot bool Scene315::Object2::startAction(CursorType action, Event &event) { Scene315 *scene = (Scene315 *)BF_GLOBALS._sceneManager._scene; @@ -957,9 +962,9 @@ Scene315::Scene315() { BF_GLOBALS.clearFlag(fCanDrawGun); _field1B68 = true; - _field1B6A = false; - _field1B60 = _field1B62 = 0; - _field1B64 = _field1B66 = 0; + _doorOpened = false; + _invGreenCount = _bookGreenCount = 0; + _invGangCount = _bookGangCount = 0; } void Scene315::synchronize(Serializer &s) { @@ -968,18 +973,19 @@ void Scene315::synchronize(Serializer &s) { s.syncAsSint16LE(_field1390); s.syncAsSint16LE(_stripNumber); s.syncAsSint16LE(_field1398); - s.syncAsSint16LE(_field1B60); - s.syncAsSint16LE(_field1B62); - s.syncAsSint16LE(_field1B64); - s.syncAsSint16LE(_field1B66); + s.syncAsSint16LE(_invGreenCount); + s.syncAsSint16LE(_bookGreenCount); + s.syncAsSint16LE(_invGangCount); + s.syncAsSint16LE(_bookGangCount); s.syncAsSint16LE(_field1B6C); s.syncAsSint16LE(_field139C); s.syncAsByte(_field1B68); - s.syncAsByte(_field1B6A); + s.syncAsByte(_doorOpened); s.syncAsSint16LE(_currentCursor); } void Scene315::postInit(SceneObjectList *OwnerList) { + SceneExt::postInit(OwnerList); loadScene(315); if (BF_GLOBALS._sceneManager._previousScene != 325) @@ -1061,29 +1067,29 @@ void Scene315::postInit(SceneObjectList *OwnerList) { // Set up evidence objects in inventory if (BF_INVENTORY._bookingGreen.inInventory()) - ++_field1B60; + ++_invGreenCount; if (BF_INVENTORY._greensGun.inInventory()) - ++_field1B60; + ++_invGreenCount; if (BF_INVENTORY._greensKnife.inInventory()) - ++_field1B60; + ++_invGreenCount; if (BF_INVENTORY._bullet22.inInventory()) - ++_field1B64; + ++_invGangCount; if (BF_INVENTORY._autoRifle.inInventory()) - ++_field1B64; + ++_invGangCount; if (BF_INVENTORY._wig.inInventory()) - ++_field1B64; + ++_invGangCount; if (BF_INVENTORY._bookingFrankie.inInventory()) - ++_field1B64; + ++_invGangCount; if (BF_INVENTORY._bookingGang.inInventory()) - ++_field1B64; + ++_invGangCount; if (BF_INVENTORY._snub22.inInventory()) - ++_field1B64; + ++_invGangCount; switch (BF_GLOBALS._sceneManager._previousScene) { case 190: if (_field1398) - _field1B6A = true; + _doorOpened = true; _sceneMode = BF_GLOBALS.getFlag(onDuty) ? 3150 : 3165; setAction(&_sequenceManager, this, _sceneMode, &BF_GLOBALS._player, NULL); break; @@ -1099,7 +1105,7 @@ void Scene315::postInit(SceneObjectList *OwnerList) { case 300: default: if (_field1398) - _field1B6A = true; + _doorOpened = true; if (!BF_GLOBALS.getFlag(onDuty)) _sceneMode = 3166; else if (!_field1398) @@ -1111,7 +1117,7 @@ void Scene315::postInit(SceneObjectList *OwnerList) { break; } - if (_field1B6A) { + if (_doorOpened) { _object8.setFrame(8); } else { BF_GLOBALS._walkRegions.disableRegion(4); @@ -1135,15 +1141,15 @@ void Scene315::signal() { BF_GLOBALS._player.enableControl(); break; case 10: - if (_field1B62) { - if (_field1B62 >= _field1B60) + if (_bookGreenCount) { + if (_bookGreenCount >= _invGreenCount) BF_GLOBALS.setFlag(fLeftTraceIn910); else ++ctr; } - if (_field1B66) { - if (_field1B66 < _field1B64) + if (_bookGangCount) { + if (_bookGangCount < _invGangCount) ++ctr; else if (BF_GLOBALS._bookmark < bBookedFrankieEvidence) BF_GLOBALS._bookmark = bBookedFrankieEvidence; @@ -1158,15 +1164,15 @@ void Scene315::signal() { BF_GLOBALS._sound1.fadeOut2(NULL); break; case 11: - if (_field1B62) { - if (_field1B62 >= _field1B60) + if (_bookGreenCount) { + if (_bookGreenCount >= _invGreenCount) BF_GLOBALS.setFlag(fLeftTraceIn910); else ++ctr; } - if (_field1B66) { - if (_field1B66 < _field1B64) + if (_bookGangCount) { + if (_bookGangCount < _invGangCount) ++ctr; else if (BF_GLOBALS._bookmark < bBookedFrankie) BF_GLOBALS._bookmark = bBookedFrankie; @@ -1195,7 +1201,7 @@ void Scene315::signal() { T2_GLOBALS._uiElements.addScore(30); BF_INVENTORY.setObjectScene((int)_currentCursor, 315); - if (!_field1B64 || (_field1B66 != _field1B64)) + if (!_invGangCount || (_bookGangCount != _invGangCount)) BF_GLOBALS._player.enableControl(); else { _field139C = 1; @@ -1217,7 +1223,8 @@ void Scene315::signal() { BF_GLOBALS._walkRegions.disableRegion(4); _object7.remove(); _object6.remove(); - + // No break on purpose + case 3155: BF_GLOBALS._player.enableControl(); _field1B68 = false; BF_GLOBALS._walkRegions.disableRegion(4); @@ -1230,7 +1237,7 @@ void Scene315::signal() { if (_stripNumber != 0) setAction(&_action1); - else if (!_field1B64 || (_field1B66 != _field1B64)) + else if (!_invGangCount || (_bookGangCount != _invGangCount)) BF_GLOBALS._player.enableControl(); else { _stripNumber = 3171; @@ -1238,13 +1245,6 @@ void Scene315::signal() { _field139C = 1; } break; - case 3155: - BF_GLOBALS._player.enableControl(); - _field1B68 = false; - BF_GLOBALS._walkRegions.disableRegion(4); - T2_GLOBALS._uiElements._active = true; - T2_GLOBALS._uiElements.show(); - break; case 3156: T2_GLOBALS._uiElements.addScore(10); BF_INVENTORY.setObjectScene(INV_DA_NOTE, 1); @@ -1318,7 +1318,7 @@ void Scene315::dispatch() { if (_field1B68) return; - if (_field1B6A) { + if (_doorOpened) { if (BF_GLOBALS._player._position.y < 69) { BF_GLOBALS._player.disableControl(); _field1B68 = true; diff --git a/engines/tsage/blue_force/blueforce_scenes3.h b/engines/tsage/blue_force/blueforce_scenes3.h index 73fcef2851..2cff4d5df8 100644 --- a/engines/tsage/blue_force/blueforce_scenes3.h +++ b/engines/tsage/blue_force/blueforce_scenes3.h @@ -213,9 +213,9 @@ public: int _field1390; int _stripNumber; int _field1398; - int _field1B60, _field1B62, _field1B64; - int _field1B66, _field1B6C, _field139C; - bool _field1B68, _field1B6A; + int _invGreenCount, _bookGreenCount, _invGangCount; + int _bookGangCount, _field1B6C, _field139C; + bool _field1B68, _doorOpened; CursorType _currentCursor; Scene315(); diff --git a/engines/tsage/blue_force/blueforce_scenes4.cpp b/engines/tsage/blue_force/blueforce_scenes4.cpp index 4cff38feab..deff4f2518 100644 --- a/engines/tsage/blue_force/blueforce_scenes4.cpp +++ b/engines/tsage/blue_force/blueforce_scenes4.cpp @@ -371,21 +371,27 @@ bool Scene410::Passenger::startAction(CursorType action, Event &event) { switch (action) { case CURSOR_USE: if (!BF_GLOBALS.getFlag(fCalledBackup)) { - if (BF_GLOBALS.getFlag(fTalkedShooterNoBkup)) { + if (BF_GLOBALS.getFlag(fTalkedShooterNoBkup)) scene->setAction(&scene->_action3); - } else { - SceneItem::display2(410, 5); - } + else + SceneItem::display(410, 5, SET_WIDTH, 300, + SET_X, 10 + GLOBALS._sceneManager._scene->_sceneBounds.left, + SET_Y, GLOBALS._sceneManager._scene->_sceneBounds.top + UI_INTERFACE_Y + 2, + SET_FONT, 4, SET_BG_COLOR, 1, SET_FG_COLOR, 96, SET_EXT_BGCOLOR, 99, + SET_EXT_FGCOLOR, 13, LIST_END); } else if (!scene->_field1FBA) { - SceneItem::display2(410, 5); + SceneItem::display(410, 5, SET_WIDTH, 300, + SET_X, 10 + GLOBALS._sceneManager._scene->_sceneBounds.left, + SET_Y, GLOBALS._sceneManager._scene->_sceneBounds.top + UI_INTERFACE_Y + 2, + SET_FONT, 4, SET_BG_COLOR, 1, SET_FG_COLOR, 96, SET_EXT_BGCOLOR, 99, + SET_EXT_FGCOLOR, 13, LIST_END); } else if (!scene->_field1FBE) { scene->_sceneMode = 4121; scene->_field1FBE = 1; T2_GLOBALS._uiElements.addScore(50); scene->signal(); - } else { + } else break; - } return true; case CURSOR_TALK: scene->setAction(&scene->_action5); @@ -711,6 +717,7 @@ void Scene410::signal() { break; case 7: BF_INVENTORY.setObjectScene(INV_TYRONE_ID, 1); + _sceneMode = 0; signal(); break; case 8: @@ -778,6 +785,7 @@ void Scene410::signal() { BF_GLOBALS._player.setObjectWrapper(new SceneObjectWrapper()); BF_GLOBALS._player.updateAngle(Common::Point(100, 170)); BF_GLOBALS._walkRegions.enableRegion(22); + BF_GLOBALS._walkRegions.enableRegion(7); BF_GLOBALS._walkRegions.enableRegion(16); BF_GLOBALS._player.disableControl(); _sceneMode = 0; @@ -920,6 +928,17 @@ bool Scene415::GunInset::startAction(CursorType action, Event &event) { } } +void Scene415::GunInset::remove() { + Scene415 *scene = (Scene415 *)BF_GLOBALS._sceneManager._scene; + + BF_GLOBALS._player.disableControl(); + scene->_gunAndWig.remove(); + FocusObject::remove(); + + scene->_sceneMode = 0; + scene->_animatedSeat.animate(ANIM_MODE_6, scene); +} + bool Scene415::GunAndWig::startAction(CursorType action, Event &event) { Scene415 *scene = (Scene415 *)BF_GLOBALS._sceneManager._scene; @@ -954,7 +973,7 @@ bool Scene415::BulletsInset::startAction(CursorType action, Event &event) { Scene415 *scene = (Scene415 *)BF_GLOBALS._sceneManager._scene; if (action == CURSOR_USE) { - if (BF_GLOBALS.getFlag(fGotAutoWeapon)) { + if (BF_GLOBALS.getFlag(fGotBulletsFromDash)) { FocusObject::startAction(action, event); } else { remove(); @@ -966,6 +985,13 @@ bool Scene415::BulletsInset::startAction(CursorType action, Event &event) { } } +void Scene415::BulletsInset::remove() { + Scene415 *scene = (Scene415 *)BF_GLOBALS._sceneManager._scene; + + scene->_theBullets.remove(); + FocusObject::remove(); +} + bool Scene415::DashDrawer::startAction(CursorType action, Event &event) { Scene415 *scene = (Scene415 *)BF_GLOBALS._sceneManager._scene; @@ -993,7 +1019,6 @@ bool Scene415::TheBullets::startAction(CursorType action, Event &event) { case INV_FOREST_RAP: if (scene->_scoreBulletRapFlag) { SceneItem::display2(415, 35); - return true; } else { BF_GLOBALS._player.disableControl(); scene->_sceneMode = 0; @@ -1001,7 +1026,7 @@ bool Scene415::TheBullets::startAction(CursorType action, Event &event) { T2_GLOBALS._uiElements.addScore(50); scene->_scoreBulletRapFlag = true; } - break; + return true; default: break; } @@ -1021,7 +1046,7 @@ bool Scene415::Lever::startAction(CursorType action, Event &event) { } else { BF_GLOBALS._player.disableControl(); scene->_sceneMode = 2; - scene->setAction(&scene->_sequenceManager, scene, 4150, &scene->_object6, NULL); + scene->setAction(&scene->_sequenceManager, scene, 4150, &scene->_animatedSeat, NULL); } return true; default: @@ -1053,11 +1078,11 @@ void Scene415::postInit(SceneObjectList *OwnerList) { _dashDrawer.setPosition(Common::Point(151, 97)); _dashDrawer.setDetails(415, 22, -1, -1, 1, NULL); - _object6.postInit(); - _object6.setVisage(419); - _object6.setStrip(1); - _object6.setPosition(Common::Point(306, 116)); - _object6.fixPriority(80); + _animatedSeat.postInit(); + _animatedSeat.setVisage(419); + _animatedSeat.setStrip(1); + _animatedSeat.setPosition(Common::Point(306, 116)); + _animatedSeat.fixPriority(80); _windowLever.setDetails(16, 415, 25, -1, 26, 1); _item7.setDetails(17, 415, 32, -1, 33, 1); diff --git a/engines/tsage/blue_force/blueforce_scenes4.h b/engines/tsage/blue_force/blueforce_scenes4.h index 48b48ec7f8..937c015a4c 100644 --- a/engines/tsage/blue_force/blueforce_scenes4.h +++ b/engines/tsage/blue_force/blueforce_scenes4.h @@ -133,6 +133,7 @@ class Scene415: public SceneExt { class GunInset: public FocusObject { public: virtual bool startAction(CursorType action, Event &event); + virtual void remove(); }; class GunAndWig: public NamedObject { public: @@ -141,6 +142,7 @@ class Scene415: public SceneExt { class BulletsInset: public FocusObject { public: virtual bool startAction(CursorType action, Event &event); + virtual void remove(); }; class DashDrawer: public NamedObject { public: @@ -166,7 +168,7 @@ public: BulletsInset _bulletsInset; DashDrawer _dashDrawer; TheBullets _theBullets; - NamedObject _object6; + NamedObject _animatedSeat; NamedHotspot _item1, _steeringWheel, _horn, _dashboard; NamedHotspot _seat, _windowLever, _item7, _seatBelt; Lever _lever; diff --git a/engines/tsage/blue_force/blueforce_scenes5.cpp b/engines/tsage/blue_force/blueforce_scenes5.cpp index d1f1e90234..f5f05c8148 100644 --- a/engines/tsage/blue_force/blueforce_scenes5.cpp +++ b/engines/tsage/blue_force/blueforce_scenes5.cpp @@ -924,7 +924,7 @@ void Scene560::Action1::signal() { scene->_deskChair.setStrip(BF_GLOBALS._player._strip); scene->_deskChair.setPosition(BF_GLOBALS._player._position); - scene->_field380 = 1; + scene->_field380 = true; BF_GLOBALS._player.enableControl(); remove(); break; @@ -950,7 +950,7 @@ void Scene560::Action2::signal() { BF_GLOBALS._player.animate(ANIM_MODE_6, this); break; case 2: - scene->_field380 = 0; + scene->_field380 = false; scene->_deskChair.setPosition(Common::Point(81, 149)); scene->_deskChair.setVisage(561); scene->_deskChair.setStrip(3); @@ -1378,7 +1378,7 @@ bool Scene560::Computer::startAction(CursorType action, Event &event) { /*--------------------------------------------------------------------------*/ Scene560::Scene560(): SceneExt() { - _field380 = _field11EA = 0; + _field380 = _field11EA = false; } void Scene560::postInit(SceneObjectList *OwnerList) { @@ -1433,12 +1433,12 @@ void Scene560::postInit(SceneObjectList *OwnerList) { _deskChair.setStrip(BF_GLOBALS._player._strip); _deskChair.setPosition(BF_GLOBALS._player._position); - _field11EA = 0; - _field380 = 1; + _field11EA = false; + _field380 = true; } else { // Entering study through doorway - _field11EA = 0; - _field380 = 0; + _field11EA = false; + _field380 = false; BF_GLOBALS._player.postInit(); BF_GLOBALS._player.setVisage(563); @@ -1529,7 +1529,7 @@ void Scene560::signal() { } break; case 10: - _field11EA = 0; + _field11EA = false; BF_GLOBALS._player.enableControl(); break; case 11: @@ -1540,7 +1540,7 @@ void Scene560::signal() { void Scene560::process(Event &event) { if ((event.eventType == EVENT_BUTTON_DOWN) && (BF_GLOBALS._events.getCursor() == CURSOR_WALK) && - (_field380 == 1) && !_action) { + (_field380) && !_action) { _destPosition = event.mousePos; BF_GLOBALS._player.disableControl(); setAction(&_action2); @@ -1553,7 +1553,7 @@ void Scene560::process(Event &event) { void Scene560::dispatch() { if (!_field11EA && (BF_GLOBALS._player._position.y < 105)) { - _field11EA = 1; + _field11EA = true; BF_GLOBALS._player.disableControl(); BF_GLOBALS._sceneManager.changeScene(270); } diff --git a/engines/tsage/blue_force/blueforce_scenes5.h b/engines/tsage/blue_force/blueforce_scenes5.h index 34328ab9e8..76bf4cdbc3 100644 --- a/engines/tsage/blue_force/blueforce_scenes5.h +++ b/engines/tsage/blue_force/blueforce_scenes5.h @@ -228,7 +228,8 @@ public: NamedHotspot _chair, _lamp, _item4, _trophy, _watercolours, _fileCabinets; NamedHotspot _certificate, _bookcase, _desk, _carpet, _item12, _office; ASound _sound1; - int _field380, _field11EA; + bool _field380; + bool _field11EA; Common::Point _destPosition; Scene560(); diff --git a/engines/tsage/blue_force/blueforce_scenes7.cpp b/engines/tsage/blue_force/blueforce_scenes7.cpp index 21a27640e9..7b84e3ccdd 100644 --- a/engines/tsage/blue_force/blueforce_scenes7.cpp +++ b/engines/tsage/blue_force/blueforce_scenes7.cpp @@ -37,7 +37,7 @@ namespace BlueForce { void Scene710::Timer1::signal() { PaletteRotation *rotation = BF_GLOBALS._scenePalette.addRotation(136, 138, -1); - rotation->setDelay(25); + rotation->setDelay(20); rotation = BF_GLOBALS._scenePalette.addRotation(146, 148, -1); rotation->setDelay(30); rotation = BF_GLOBALS._scenePalette.addRotation(187, 191, -1); @@ -113,19 +113,19 @@ bool Scene710::Object5::startAction(CursorType action, Event &event) { switch (action) { case CURSOR_LOOK: - if (scene->_v1D64 <= 2) + if (scene->_stickThrowCount <= 2) return NamedObject::startAction(action, event); else { SceneItem::display2(710, 3); - scene->_v1D66 = 1; + scene->_watchCrate = true; return true; } case CURSOR_USE: - if ((scene->_kid._position.x < 0) && (scene->_v1D62 == 1)) { - scene->_v1D64++; - if (scene->_v1D66 == 0) { + if ((scene->_kid._position.x < 0) && (scene->_dogLying)) { + scene->_stickThrowCount++; + if (!scene->_watchCrate) { BF_GLOBALS._player.disableControl(); - scene->_v1D62 = 0; + scene->_dogLying = false; scene->_sceneMode = 7105; scene->setAction(&scene->_sequenceManager1, scene, 7105, &BF_GLOBALS._player, &scene->_stick, &scene->_dog, NULL); } else { @@ -187,7 +187,8 @@ void Scene710::postInit(SceneObjectList *OwnerList) { _item7.setDetails(Rect(0, 0, 640, 52), 710, 11, 17, -1, 1, NULL); _item9.setDetails(Rect(0, 0, 640, 128), 710, 5, 15, -1, 1, NULL); - _v1D62 = _v1D64 = _v1D66 = _v1D68 = 0; + _stickThrowCount = 0; + _dogLying = _watchCrate = _throwStick = false; _action1._state = 7100; _timer1.set(2, NULL); _sceneMode = 7100; @@ -205,6 +206,7 @@ void Scene710::signal() { setAction(&_sequenceManager1, this, 7102, &_dog, NULL); break; case 7101: + // Pick up crate part BF_GLOBALS._player.enableControl(); BF_INVENTORY.setObjectScene(INV_CRATE1, 1); _stick.remove(); @@ -214,19 +216,19 @@ void Scene710::signal() { _stick.setPosition(Common::Point(100, 122)); _stick.animate(ANIM_MODE_NONE, NULL); _stick._strip = 2; - if (_v1D64 <= 2) + if (_stickThrowCount <= 2) _stick._frame = 2; else { - if (_v1D64 == 3) { + if (_stickThrowCount == 3) { BF_GLOBALS._player.disableControl(); _sceneMode = 0; _stripManager.start(7108, this); } _stick._frame = 1; } - _v1D62 = 1; + _dogLying = true; BF_GLOBALS._walkRegions.disableRegion(2); - if ((_v1D68 != 0) && (_sceneMode != 0)) + if ((_throwStick) && (_sceneMode != 0)) BF_GLOBALS._player.enableControl(); break; case 7103: @@ -239,7 +241,7 @@ void Scene710::signal() { } break; case 7105: - _v1D68 = 1; + _throwStick = true; // No break on purpose case 7104: _sceneMode = 7102; @@ -256,8 +258,8 @@ void Scene710::signal() { } void Scene710::dispatch() { - if ((_kid._position.x > 0) && (_v1D62 == 1) && (_sceneMode != 7106)) { - _v1D62 = 0; + if ((_kid._position.x > 0) && (_dogLying) && (_sceneMode != 7106)) { + _dogLying = false; _sceneMode = 7103; setAction(&_sequenceManager1, this, 7103, &_kid, &_stick, &_dog, NULL); } @@ -266,10 +268,10 @@ void Scene710::dispatch() { void Scene710::synchronize(Serializer &s) { SceneExt::synchronize(s); - s.syncAsSint16LE(_v1D62); - s.syncAsSint16LE(_v1D64); - s.syncAsSint16LE(_v1D66); - s.syncAsSint16LE(_v1D68); + s.syncAsSint16LE(_dogLying); + s.syncAsSint16LE(_stickThrowCount); + s.syncAsSint16LE(_watchCrate); + s.syncAsSint16LE(_throwStick); } diff --git a/engines/tsage/blue_force/blueforce_scenes7.h b/engines/tsage/blue_force/blueforce_scenes7.h index 91bd1e537f..161d94cc2c 100644 --- a/engines/tsage/blue_force/blueforce_scenes7.h +++ b/engines/tsage/blue_force/blueforce_scenes7.h @@ -89,7 +89,10 @@ public: NamedHotspot _item7; NamedHotspot _item8; NamedHotspot _item9; - int _v1D62, _v1D64, _v1D66, _v1D68; + int _stickThrowCount; + bool _dogLying; + bool _watchCrate; + bool _throwStick; virtual void postInit(SceneObjectList *OwnerList = NULL); virtual void signal(); diff --git a/engines/tsage/core.cpp b/engines/tsage/core.cpp index 5a51a9c9ef..84ab98d4e0 100644 --- a/engines/tsage/core.cpp +++ b/engines/tsage/core.cpp @@ -1081,7 +1081,7 @@ void PaletteRotation::signal() { uint32 frameNumber = g_globals->_events.getFrameNumber(); if (frameNumber >= _frameNumber) { - _delayCtr = frameNumber - _frameNumber; + _delayCtr -= frameNumber - _frameNumber; _frameNumber = frameNumber; if (_delayCtr < 0) @@ -1438,8 +1438,8 @@ void ScenePalette::changeBackground(const Rect &bounds, FadeMode fadeMode) { } Rect tempRect = bounds; - if (g_vm->getGameID() != GType_Ringworld) - tempRect.setHeight(BF_GLOBALS._interfaceY); + if ((g_vm->getGameID() != GType_Ringworld) && (g_vm->getGameID() != GType_Geekwad)) + tempRect.setHeight(T2_GLOBALS._interfaceY); g_globals->_screenSurface.copyFrom(g_globals->_sceneManager._scene->_backSurface, tempRect, Rect(0, 0, tempRect.width(), tempRect.height()), NULL); @@ -2929,6 +2929,16 @@ Player::Player(): SceneObject() { _enabled = false; _uiEnabled = false; _field8C = 0; + + // Return to Ringworld specific fields + _characterIndex = 0; + _oldSceneNumber = 0; + + for (int i = 0; i < MAX_CHARACTERS; ++i) { + _characterScene[i] = 0; + _characterStrip[i] = 0; + _characterFrame[i] = 0; + } } void Player::postInit(SceneObjectList *OwnerList) { @@ -3017,6 +3027,19 @@ void Player::synchronize(Serializer &s) { if (g_vm->getGameID() != GType_Ringworld) s.syncAsByte(_enabled); + + if (g_vm->getGameID() == GType_Ringworld2) { + s.syncAsSint16LE(_characterIndex); + s.syncAsSint16LE(_oldSceneNumber); + + for (int i = 0; i < MAX_CHARACTERS; ++i) { + s.syncAsSint16LE(_characterScene[i]); + s.syncAsSint16LE(_characterPos[i].x); + s.syncAsSint16LE(_characterPos[i].y); + s.syncAsSint16LE(_characterStrip[i]); + s.syncAsSint16LE(_characterFrame[i]); + } + } } /*--------------------------------------------------------------------------*/ @@ -3458,6 +3481,7 @@ void WalkRegions::clear() { _field18.clear(); _idxList.clear(); _idxList2.clear(); + _disabledRegions.clear(); } void WalkRegions::load(int sceneNum) { diff --git a/engines/tsage/core.h b/engines/tsage/core.h index 1a50d0beae..23e720929c 100644 --- a/engines/tsage/core.h +++ b/engines/tsage/core.h @@ -418,6 +418,7 @@ public: virtual void destroy() {} virtual bool startAction(CursorType action, Event &event); virtual void doAction(int action); + virtual bool performAction(CursorType action, Event &event) { return startAction(action, event); } bool contains(const Common::Point &pt); void setBounds(const Rect &newBounds) { _bounds = newBounds; } @@ -616,12 +617,22 @@ public: virtual void updateScreen(); }; +#define MAX_CHARACTERS 4 + class Player : public SceneObject { public: bool _canWalk; bool _uiEnabled; int _field8C; bool _enabled; + + // Return to Ringworld specific fields + int _characterIndex; + int _oldSceneNumber; + int _characterScene[MAX_CHARACTERS]; + Common::Point _characterPos[MAX_CHARACTERS]; + int _characterStrip[MAX_CHARACTERS]; + int _characterFrame[MAX_CHARACTERS]; public: Player(); @@ -810,6 +821,7 @@ public: Common::List<int> _disabledRegions; public: WalkRegions() { _resNum = -1; } + virtual ~WalkRegions() {} virtual void synchronize(Serializer &s); void clear(); diff --git a/engines/tsage/detection.cpp b/engines/tsage/detection.cpp index 12add10c58..ab179cbac8 100644 --- a/engines/tsage/detection.cpp +++ b/engines/tsage/detection.cpp @@ -62,6 +62,7 @@ static const PlainGameDescriptor tSageGameTitles[] = { { "ringworld", "Ringworld: Revenge of the Patriarch" }, { "blueforce", "Blue Force" }, { "ringworld2", "Return to Ringworld" }, + { "geekwad", "The Geekwad: Games Of The Galaxy" }, { 0, 0 } }; diff --git a/engines/tsage/detection_tables.h b/engines/tsage/detection_tables.h index 360dbac0ae..e9796426cd 100644 --- a/engines/tsage/detection_tables.h +++ b/engines/tsage/detection_tables.h @@ -156,6 +156,21 @@ static const tSageGameDescription gameDescriptions[] = { GF_CD | GF_ALT_REGIONS }, + // Geekwad + { + { + "geekwad", + "CD", + AD_ENTRY1s("geekwad.rlb", "0a441f7c4c7ce20fd3ac7707a5d64ee5", 5570365), + Common::EN_ANY, + Common::kPlatformPC, + ADGF_CD | ADGF_UNSTABLE, + GUIO2(GUIO_NOSPEECH, GUIO_NOSFX) + }, + GType_Geekwad, + GF_CD | GF_ALT_REGIONS + }, + { AD_TABLE_END_MARKER, 0, 0 } }; diff --git a/engines/tsage/events.cpp b/engines/tsage/events.cpp index d42b996e41..8958482404 100644 --- a/engines/tsage/events.cpp +++ b/engines/tsage/events.cpp @@ -320,7 +320,6 @@ void EventsClass::setCursor(Graphics::Surface &cursor, int transColor, const Com } void EventsClass::setCursor(GfxSurface &cursor) { - // TODO: Find proper parameters for this form in Blue Force Graphics::Surface s = cursor.lockSurface(); const byte *cursorData = (const byte *)s.getBasePtr(0, 0); diff --git a/engines/tsage/events.h b/engines/tsage/events.h index 67d56ceb87..2ffa862ca6 100644 --- a/engines/tsage/events.h +++ b/engines/tsage/events.h @@ -83,8 +83,8 @@ enum CursorType { INV_CARAVAN_KEY = 67, BF_LAST_INVENT = 68, // Ringworld 2 objects - R2_1 = 1, R2_2 = 2, R2_NEGATOR_GUN = 3, R2_STEPPING_DISKS = 4, R2_5 = 5, R2_6 = 6, R2_7 = 7, - R2_8 = 8, R2_9 = 9, R2_10 = 10, R2_11 = 11, R2_12 = 12, R2_13 = 13, R2_14 = 14, + R2_OPTO_DISK = 1, R2_2 = 2, R2_NEGATOR_GUN = 3, R2_STEPPING_DISKS = 4, R2_5 = 5, R2_6 = 6, + R2_7 = 7, R2_8 = 8, R2_9 = 9, R2_10 = 10, R2_11 = 11, R2_12 = 12, R2_13 = 13, R2_14 = 14, R2_15 = 15, R2_16 = 16, R2_17 = 17, R2_18 = 18, R2_19 = 19, R2_20 = 20, R2_21 = 21, R2_22 = 22, R2_23 = 23, R2_24 = 24, R2_25 = 25, R2_26 = 26, R2_27 = 27, R2_28 = 28, R2_29 = 29, R2_30 = 30, R2_31 = 31, R2_32 = 32, R2_33 = 33, R2_34 = 34, R2_35 = 35, diff --git a/engines/tsage/geekwad/geekwad_logic.cpp b/engines/tsage/geekwad/geekwad_logic.cpp new file mode 100644 index 0000000000..a2d4fcb0f4 --- /dev/null +++ b/engines/tsage/geekwad/geekwad_logic.cpp @@ -0,0 +1,80 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "common/config-manager.h" +#include "tsage/scenes.h" +#include "tsage/tsage.h" +#include "tsage/geekwad/geekwad_logic.h" +#include "tsage/geekwad/geekwad_scenes0.h" + +namespace TsAGE { + +namespace Geekwad { + +void GeekwadGame::start() { + // Start the game + g_globals->_sceneManager.changeScene(150); +} + +Scene *GeekwadGame::createScene(int sceneNumber) { + switch (sceneNumber) { + /* Scene group #0 */ + // Tsunami title screen + case 150: return new Scene150(); + + // Geekwad credits screen + case 200: return new Scene200(); + + default: + error("Unknown scene number - %d", sceneNumber); + break; + } +} + +void GeekwadGame::rightClick() { +} + +/** + * Returns true if it is currently okay to restore a game + */ +bool GeekwadGame::canLoadGameStateCurrently() { + return true; +} + +/** + * Returns true if it is currently okay to save the game + */ +bool GeekwadGame::canSaveGameStateCurrently() { + return true; +} + +void GeekwadGame::processEvent(Event &event) { +} + +/*--------------------------------------------------------------------------*/ + +SceneExt::SceneExt(): Scene() { +} + +} // End of namespace Geekwad + +} // End of namespace TsAGE diff --git a/engines/tsage/geekwad/geekwad_logic.h b/engines/tsage/geekwad/geekwad_logic.h new file mode 100644 index 0000000000..fbccaeee00 --- /dev/null +++ b/engines/tsage/geekwad/geekwad_logic.h @@ -0,0 +1,79 @@ +/* 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 TSAGE_GEEKWAD_LOGIC_H +#define TSAGE_GEEKWAD_LOGIC_H + +#include "common/scummsys.h" +#include "tsage/events.h" +#include "tsage/core.h" +#include "tsage/scenes.h" +#include "tsage/globals.h" + +namespace TsAGE { + +namespace Geekwad { + +using namespace TsAGE; + +class SceneFactory { +public: + static Scene *createScene(int sceneNumber); +}; + +class SceneExt: public Scene { +public: +public: + SceneExt(); + + virtual Common::String getClassName() { return "SceneExt"; } +}; + +class GeekwadGame: public Game { +public: + virtual void start(); + + virtual Scene *createScene(int sceneNumber); + virtual void processEvent(Event &event); + virtual void rightClick(); + virtual bool canSaveGameStateCurrently(); + virtual bool canLoadGameStateCurrently(); +}; + +class SceneObject2: public SceneObject { +public: + int _v1, _v2; + + SceneObject2() { _v1 = _v2 = 0; } + virtual Common::String getClassName() { return "SceneObject2"; } + virtual void synchronize(Serializer &s) { + SceneObject::synchronize(s); + s.syncAsSint16LE(_v1); + s.syncAsSint16LE(_v2); + } +}; + +} // End of namespace Geekwad + +} // End of namespace TsAGE + +#endif diff --git a/engines/tsage/geekwad/geekwad_scenes0.cpp b/engines/tsage/geekwad/geekwad_scenes0.cpp new file mode 100644 index 0000000000..9241b1dace --- /dev/null +++ b/engines/tsage/geekwad/geekwad_scenes0.cpp @@ -0,0 +1,498 @@ +/* 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 "tsage/scenes.h" +#include "tsage/tsage.h" +#include "tsage/staticres.h" +#include "tsage/geekwad/geekwad_scenes0.h" + +namespace TsAGE { + +namespace Geekwad { + +/*-------------------------------------------------------------------------- + * Scene 150 - Tsunami Title Screen + * + *--------------------------------------------------------------------------*/ + +void Scene150::Action1::signal() { + Scene150 *scene = (Scene150 *)GW_GLOBALS._sceneManager._scene; + static byte black[3] = { 0, 0, 0 }; + + switch (_actionIndex++) { + case 0: + setDelay(2); + break; + case 1: + GW_GLOBALS._sound1.play(1); + GW_GLOBALS._scenePalette.addRotation(64, 127, -1, 1, this); + break; + case 2: + scene->_object1.setVisage(822); + scene->_object1._strip = 1; + scene->_object1._frame = 1; + scene->_object1.changeZoom(100); + + scene->_object2.setVisage(822); + scene->_object2._strip = 2; + scene->_object2._frame = 1; + scene->_object2.changeZoom(100); + + scene->_object3.setVisage(822); + scene->_object3._strip = 3; + scene->_object3._frame = 1; + scene->_object3.changeZoom(100); + + scene->_object4.setVisage(822); + scene->_object4._strip = 4; + scene->_object4._frame = 1; + scene->_object4.changeZoom(100); + + scene->_object5.setVisage(822); + scene->_object5._strip = 5; + scene->_object5._frame = 1; + scene->_object5.changeZoom(100); + + scene->_object6.setVisage(822); + scene->_object6._strip = 6; + scene->_object6._frame = 1; + scene->_object6.changeZoom(100); + + scene->_object7.setVisage(822); + scene->_object7._strip = 7; + scene->_object7._frame = 1; + scene->_object7.changeZoom(100); + + scene->_object8.setVisage(822); + scene->_object8._strip = 8; + scene->_object8._frame = 1; + scene->_object8.changeZoom(100); + + setDelay(1); + break; + case 3: + GW_GLOBALS._scenePalette.addFader(scene->_scenePalette._palette, 256, 8, this); + break; + case 4: + setDelay(60); + break; + case 5: + scene->_object2.animate(ANIM_MODE_5, NULL); + scene->_object3.animate(ANIM_MODE_5, NULL); + scene->_object4.animate(ANIM_MODE_5, NULL); + scene->_object5.animate(ANIM_MODE_5, NULL); + scene->_object6.animate(ANIM_MODE_5, NULL); + scene->_object7.animate(ANIM_MODE_5, this); + break; + case 6: + setDelay(120); + break; + case 7: + GW_GLOBALS._scenePalette.addFader(black, 1, 5, this); + break; + case 8: + GW_GLOBALS._sceneManager.changeScene(200); + remove(); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +void Scene150::postInit(SceneObjectList *OwnerList) { + loadScene(820); + Scene::postInit(); + setZoomPercents(60, 85, 200, 100); + + _scenePalette.loadPalette(822); + + _object1.postInit(); + _object1.setVisage(821); + _object1._strip = 1; + _object1._frame = 1; + _object1.animate(ANIM_MODE_NONE, NULL); + _object1.setPosition(Common::Point(62, 85)); + + _object2.postInit(); + _object2.setVisage(821); + _object2._strip = 2; + _object2._frame = 1; + _object2.animate(ANIM_MODE_NONE, NULL); + _object2.setPosition(Common::Point(27, 94)); + + _object3.postInit(); + _object3.setVisage(821); + _object3._strip = 2; + _object3._frame = 2; + _object3.animate(ANIM_MODE_NONE, NULL); + _object3.setPosition(Common::Point(68, 94)); + + _object4.postInit(); + _object4.setVisage(821); + _object4._strip = 2; + _object4._frame = 3; + _object4.animate(ANIM_MODE_NONE, NULL); + _object4.setPosition(Common::Point(110, 94)); + + _object5.postInit(); + _object5.setVisage(821); + _object5._strip = 2; + _object5._frame = 4; + _object5.animate(ANIM_MODE_NONE, NULL); + _object5.setPosition(Common::Point(154, 94)); + + _object6.postInit(); + _object6.setVisage(821); + _object6._strip = 2; + _object6._frame = 5; + _object6.animate(ANIM_MODE_NONE, NULL); + _object6.setPosition(Common::Point(199, 94)); + + _object7.postInit(); + _object7.setVisage(821); + _object7._strip = 2; + _object7._frame = 6; + _object7.animate(ANIM_MODE_NONE, NULL); + _object7.setPosition(Common::Point(244, 94)); + + _object8.postInit(); + _object8.setVisage(821); + _object8._strip = 2; + _object8._frame = 7; + _object8.animate(ANIM_MODE_NONE, NULL); + _object8.setPosition(Common::Point(286, 94)); + + setAction(&_action1); +} + +/*-------------------------------------------------------------------------- + * Scene 200 - Geekwad credits screen + * + *--------------------------------------------------------------------------*/ + +struct CreditEntry { + int visage; + int strip; + int frame; +}; + +const CreditEntry credits[] = { + {5500, 1, 1}, {5500, 1, 2}, {5500, 2, 1}, {5500, 2, 2}, {5500, 8, 2}, {5500, 3, 1}, + {5500, 3, 2}, {5500, 4, 1}, {5500, 4, 2}, {5500, 5, 1}, {5500, 5, 2}, {5500, 8, 2}, + {5500, 6, 1}, {5500, 6, 2}, {5500, 7, 1}, {5500, 7, 2}, {5500, 8, 1} +}; +#define TOTAL_CREDITS 17 + +void Scene200::Action1::signal() { + Scene200 *scene = (Scene200 *)GW_GLOBALS._sceneManager._scene; + + switch (_actionIndex) { + case 0: { + ++scene->_fieldAB2; + + if ((scene->_creditIndex < TOTAL_CREDITS) && (!scene->_creditIndex || (*scene->_list2.begin())->_position.y < 192)) { + SceneObject2 *obj = new SceneObject2(); + obj->postInit(); + obj->setVisage(credits[scene->_creditIndex].visage); + obj->setStrip(credits[scene->_creditIndex].strip); + obj->setFrame(credits[scene->_creditIndex].frame); + obj->changeZoom(106); + obj->fixPriority(100); + obj->setPosition(Common::Point(160, 210)); + obj->_flags |= OBJFLAG_CLONED; + obj->_v1 = obj->_v2 = 0; + + scene->_list2.push_back(obj); + ++scene->_creditIndex; + } + + SceneObject2 *item; + SynchronizedList<SceneObject2 *>::iterator i; + for (i = scene->_list2.begin(); i != scene->_list2.end(); ++i) { + item = *i; + item->setPosition(Common::Point(item->_position.x, item->_position.y - 1)); + item->changeZoom(item->_percent - ((210 - item->_position.y + 100) / 100)); + } + + item = *scene->_list2.begin(); + if (item->_percent < 20) { + item->remove(); + scene->_list2.remove(item); + + if (scene->_list2.empty()) { + ++_actionIndex; + scene->_sound1.fadeOut(this); + } + } + + setDelay(6); + break; + } + case 1: + setDelay(1); + ++_actionIndex; + break; + case 2: + scene->_sound1.play(3); + scene->_sound1.setVol(127); + + scene->_object1.postInit(); + scene->_object1.setVisage(5510); + scene->_object1.setStrip(1); + scene->_object1.setFrame(1); + scene->_object1.changeZoom(10); + scene->_object1.fixPriority(100); + scene->_object1.setPosition(Common::Point(160, 190)); + + setDelay(3); + ++_actionIndex; + break; + case 3: + scene->_object1.changeZoom(scene->_object1._percent + 5); + if (scene->_object1._percent >= 100) + ++_actionIndex; + + setDelay(3); + break; + case 4: + scene->_object2.postInit(); + scene->_object2.setVisage(5000); + scene->_object2.setStrip(1); + scene->_object2.setFrame(1); + scene->_object2.fixPriority(110); + scene->_object2.setPosition(Common::Point(-30, 100)); + scene->_object2.animate(ANIM_MODE_2); + + scene->_object3.postInit(); + scene->_object3.setVisage(5505); + scene->_object3.setStrip(1); + scene->_object3.setFrame(1); + scene->_object3.fixPriority(100); + scene->_object3.setPosition(Common::Point(412, 117)); + + scene->_object4.postInit(); + scene->_object4.setVisage(5505); + scene->_object4.setStrip(2); + scene->_object4.setFrame(1); + scene->_object4.fixPriority(101); + scene->_object4.setPosition(Common::Point(scene->_object3._position.x + 35, + scene->_object3._position.y - 19)); + + ++_actionIndex; + setDelay(6); + break; + case 5: + scene->_creditIndex = 0; + scene->_object2.setPosition(Common::Point(scene->_object2._position.x +12, scene->_object2._position.y)); + + if (scene->_object2._position.x > 240) + ++_actionIndex; + break; + case 6: + ++scene->_creditIndex; + if ((scene->_creditIndex % 2) != 0) { + scene->_object2.setPosition(Common::Point(scene->_object2._position.x - 12, scene->_object2._position.y)); + scene->_sound2.play(611); + } else { + scene->_object2.setPosition(Common::Point(scene->_object2._position.x + 12, scene->_object2._position.y)); + } + + if (scene->_creditIndex >= 6) + ++_actionIndex; + break; + case 7: + scene->loadBackground(8, 0); + scene->_object2.setPosition(Common::Point(scene->_object2._position.x, scene->_object2._position.y + 2)); + scene->_object1.setPosition(Common::Point(scene->_object1._position.x - 12, scene->_object1._position.y)); + + if (scene->_sceneBounds.left >= 160) { + scene->_object1.remove(); + ++_actionIndex; + } + break; + case 8: + scene->_object2.setPosition(Common::Point(scene->_object2._position.x + 12, scene->_object2._position.y)); + + if (scene->_object2._position.x > 321) + ++_actionIndex; + break; + case 9: + scene->_sound2.play(611); + scene->_object2.setPosition(Common::Point(scene->_object2._position.x - 12, scene->_object2._position.y)); + scene->_object3.setPosition(Common::Point(scene->_object3._position.x + 12, scene->_object3._position.y)); + scene->_object4.setPosition(Common::Point(scene->_object4._position.x + 12, scene->_object2._position.y)); + scene->_object4.setFrame(scene->_object4.getFrameCount()); + + setDelay(6); + ++_actionIndex; + break; + case 10: + scene->_object3.setPosition(Common::Point(scene->_object3._position.x - 12, scene->_object3._position.y)); + scene->_object4.setPosition(Common::Point(scene->_object4._position.x - 12, scene->_object2._position.y)); + scene->_object4.setAction(&scene->_action2); + scene->_object2.setPosition(Common::Point(scene->_object2._position.x - 12, scene->_object2._position.y)); + scene->_object2.fixPriority(80); + + setDelay(6); + ++_actionIndex; + break; + case 11: + scene->_object2.changeZoom(scene->_object2._percent - 5); + if (scene->_object2._percent < 20) + ++_actionIndex; + break; + case 12: + scene->_object2.setPosition(Common::Point(scene->_object2._position.x + 2, + scene->_object2._position.y - ((scene->_object2._position.y <= 80) ? 0 : 2))); + if (scene->_object2._position.x > 390) + ++_actionIndex; + break; + case 13: + scene->_field846 = GW_GLOBALS._events.getFrameNumber() - scene->_field846; + scene->_field848 = (scene->_field846 > 3600) ? 2 : 1; + scene->_creditIndex = 0; + ++_actionIndex; + // Deliberate fall-through + case 14: { + setDelay(2); + + if ((scene->_creditIndex != 0) && ((scene->_creditIndex == -1) || ((*scene->_list1.begin())->_position.y >= 142))) { + Common::String msg = g_resourceManager->getMessage(200, scene->_creditIndex); + + if (msg.hasPrefix("~")) { + scene->_creditIndex = -1; + } else { + if (msg.empty()) + msg = " "; + + SceneText *sceneText = new SceneText(); + sceneText->_fontNumber = 71; + + if (msg.hasPrefix("@")) { + sceneText->_color1 = 43; + sceneText->_color2 = 46; + sceneText->_color3 = 80; + msg.deleteChar(0); + } else { + sceneText->_color1 = 100; + sceneText->_color2 = 103; + sceneText->_color3 = 16; + } + + sceneText->_width = 400; + sceneText->setup(msg); + sceneText->_flags |= OBJFLAG_CLONED; + sceneText->fixPriority(199); + + int fontNumber = GW_GLOBALS.gfxManager()._font._fontNumber; + GW_GLOBALS.gfxManager()._font.setFontNumber(sceneText->_fontNumber); + int strWidth = GW_GLOBALS.gfxManager().getStringWidth(msg.c_str()); + + sceneText->setPosition(Common::Point(270 - (strWidth / 2), 150)); + GW_GLOBALS.gfxManager()._font.setFontNumber(fontNumber); + + scene->_list1.push_back(sceneText); + } + } + + SynchronizedList<SceneText *>::iterator i; + for (i = scene->_list1.begin(); i != scene->_list1.end(); ++i) { + SceneText *item = *i; + item->setPosition(Common::Point(item->_position.x, item->_position.y - scene->_field848)); + } + + SceneText *topItem = *scene->_list1.begin(); + if (topItem->_position.y < 50) { + topItem->remove(); + scene->_list1.remove(topItem); + + if (scene->_list1.empty()) { + setDelay(10); + ++_actionIndex; + } + } + break; + } + case 15: + ++_actionIndex; + scene->_sound1.fade(0, 5, 4, true, this); + break; + case 16: + GW_GLOBALS._sceneManager.changeScene(500); + remove(); + break; + } +} + +void Scene200::Action2::signal() { + switch (_actionIndex++) { + case 0: + ++_actionIndex; + setDelay(GW_GLOBALS._randomSource.getRandomNumber(50) + 50); + break; + case 1: + ++_actionIndex; + static_cast<SceneObject *>(_owner)->animate(ANIM_MODE_8, 1, this); + break; + case 2: + _actionIndex = 0; + static_cast<SceneObject *>(_owner)->setFrame(1); + setDelay(1); + break; + } +} + +/*--------------------------------------------------------------------------*/ + +Scene200::Scene200(): Scene() { + _creditIndex = _fieldAB2 = 0; + _field846 = GW_GLOBALS._events.getFrameNumber(); +} + +void Scene200::postInit(SceneObjectList *OwnerList) { + Scene::postInit(); + loadScene(5500); + _sound1.play(2); + + setAction(&_action1); +} + +void Scene200::process(Event &event) { + switch (event.eventType) { + case EVENT_BUTTON_DOWN: + GW_GLOBALS._sceneManager.changeScene(500); + break; + case EVENT_KEYPRESS: + if ((event.kbd.keycode == Common::KEYCODE_ESCAPE) || (event.kbd.keycode == Common::KEYCODE_RETURN)) + GW_GLOBALS._sceneManager.changeScene(500); + break; + default: + break; + } + + if (!event.handled) + Scene::process(event); +} + +} // End of namespace Geekwad + +} // End of namespace TsAGE diff --git a/engines/tsage/geekwad/geekwad_scenes0.h b/engines/tsage/geekwad/geekwad_scenes0.h new file mode 100644 index 0000000000..8c04f12486 --- /dev/null +++ b/engines/tsage/geekwad/geekwad_scenes0.h @@ -0,0 +1,85 @@ +/* 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 TSAGE_GEEKWAD_SCENES0_H +#define TSAGE_GEEKWAD_SCENES0_H + +#include "common/scummsys.h" +#include "tsage/converse.h" +#include "tsage/events.h" +#include "tsage/core.h" +#include "tsage/scenes.h" +#include "tsage/globals.h" +#include "tsage/sound.h" +#include "tsage/geekwad/geekwad_logic.h" + +namespace TsAGE { + +namespace Geekwad { + +using namespace TsAGE; + +class Scene150: public Scene { + /* Actions */ + class Action1 : public Action { + public: + virtual void signal(); + }; +public: + Action1 _action1; + ScenePalette _scenePalette; + SceneObject _object1, _object2, _object3, _object4; + SceneObject _object5, _object6, _object7, _object8; + + virtual void postInit(SceneObjectList *OwnerList = NULL); +}; + +class Scene200: public Scene { + /* Actions */ + class Action1: public Action { + public: + virtual void signal(); + }; + class Action2: public Action { + public: + virtual void signal(); + }; +public: + Action1 _action1; + Action2 _action2; + ASound _sound1, _sound2; + SceneObject _object1, _object2, _object3, _object4; + int _field846, _field848; + int _fieldAB2, _fieldAB4, _creditIndex; + SynchronizedList<SceneText *> _list1; + SynchronizedList<SceneObject2 *> _list2; + + Scene200(); + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void process(Event &event); +}; + +} // End of namespace Geekwad + +} // End of namespace TsAGE + +#endif diff --git a/engines/tsage/globals.cpp b/engines/tsage/globals.cpp index 9bae180bc6..23898b5449 100644 --- a/engines/tsage/globals.cpp +++ b/engines/tsage/globals.cpp @@ -23,6 +23,7 @@ #include "tsage/globals.h" #include "tsage/tsage.h" #include "tsage/blue_force/blueforce_logic.h" +#include "tsage/geekwad/geekwad_logic.h" #include "tsage/ringworld/ringworld_demo.h" #include "tsage/ringworld/ringworld_logic.h" #include "tsage/ringworld2/ringworld2_logic.h" @@ -84,6 +85,14 @@ Globals::Globals() : _dialogCenter(160, 140), _gfxManagerInstance(_screenSurface _fontColors.background = 88; _fontColors.foreground = 92; _dialogCenter.y = 140; + } else if (g_vm->getGameID() == GType_Geekwad) { + // Blue Force + _gfxFontNumber = 0; + _gfxColors.background = 89; + _gfxColors.foreground = 83; + _fontColors.background = 88; + _fontColors.foreground = 92; + _dialogCenter.y = 140; } else if ((g_vm->getGameID() == GType_Ringworld) && (g_vm->getFeatures() & GF_CD)) { _gfxFontNumber = 50; _gfxColors.background = 53; @@ -94,6 +103,7 @@ Globals::Globals() : _dialogCenter(160, 140), _gfxManagerInstance(_screenSurface _color2 = 18; _color3 = 18; } else { + // Ringworld _gfxFontNumber = 50; _gfxColors.background = 53; _gfxColors.foreground = 18; @@ -137,6 +147,12 @@ Globals::Globals() : _dialogCenter(160, 140), _gfxManagerInstance(_screenSurface case GType_Ringworld2: _inventory = new Ringworld2::Ringworld2InvObjectList(); _game = new Ringworld2::Ringworld2Game(); + _sceneHandler = new Ringworld2::SceneHandlerExt(); + break; + + case GType_Geekwad: + _game = new Geekwad::GeekwadGame(); + _inventory = NULL; _sceneHandler = new SceneHandler(); break; } @@ -367,10 +383,21 @@ void Ringworld2Globals::reset() { R2_INVENTORY.reset(); T2_GLOBALS._uiElements.updateInventory(); T2_GLOBALS._uiElements._active = false; + + // Reset fields + _v5657C = 0; + _v565F5 = 0; + _diskScene = 0; + _v57C2C = 0; } void Ringworld2Globals::synchronize(Serializer &s) { TsAGE2Globals::synchronize(s); + + s.syncAsSint16LE(_v5657C); + s.syncAsSint16LE(_v565F5); + s.syncAsSint16LE(_diskScene); + s.syncAsSint16LE(_v57C2C); } } // end of namespace Ringworld2 diff --git a/engines/tsage/globals.h b/engines/tsage/globals.h index 1e50c08f56..5eaa68deab 100644 --- a/engines/tsage/globals.h +++ b/engines/tsage/globals.h @@ -121,6 +121,7 @@ extern Globals *g_globals; #define T2_GLOBALS (*((::TsAGE::TsAGE2Globals *)g_globals)) #define BF_GLOBALS (*((::TsAGE::BlueForce::BlueForceGlobals *)g_globals)) #define R2_GLOBALS (*((::TsAGE::Ringworld2::Ringworld2Globals *)g_globals)) +#define GW_GLOBALS (*((::TsAGE::Geekwad::GeekwadGlobals *)g_globals)) // Note: Currently this can't be part of the g_globals structure, since it needs to be constructed // prior to many of the fields in Globals execute their constructors @@ -243,6 +244,11 @@ namespace Ringworld2 { class Ringworld2Globals: public TsAGE2Globals { public: ASoundExt _sound1, _sound2, _sound3, _sound4; + PlayStream _playStream; + int _diskScene; + int _v565F5; + int _v5657C; + int _v57C2C; virtual void reset(); virtual void synchronize(Serializer &s); @@ -250,6 +256,15 @@ public: } // End of namespace Ringworld2 +namespace Geekwad { + +class GeekwadGlobals: public Globals { +public: + ASoundExt _sound1; +}; + +} // End of namespace Geekwad + } // End of namespace TsAGE #endif diff --git a/engines/tsage/module.mk b/engines/tsage/module.mk index 0ea8916647..60f1823da7 100644 --- a/engines/tsage/module.mk +++ b/engines/tsage/module.mk @@ -20,6 +20,8 @@ MODULE_OBJS := \ detection.o \ dialogs.o \ events.o \ + geekwad/geekwad_logic.o \ + geekwad/geekwad_scenes0.o \ globals.o \ graphics.o \ resources.o \ diff --git a/engines/tsage/ringworld/ringworld_scenes5.cpp b/engines/tsage/ringworld/ringworld_scenes5.cpp index 3cf1207e9e..2090bc5da7 100644 --- a/engines/tsage/ringworld/ringworld_scenes5.cpp +++ b/engines/tsage/ringworld/ringworld_scenes5.cpp @@ -2173,7 +2173,7 @@ void Scene4050::Action4::signal() { case 5: scene->_hotspot16.setStrip2(4); scene->_hotspot16.setFrame(1); - scene->_hotspot16.animate(ANIM_MODE_4, 4, 1, this);; + scene->_hotspot16.animate(ANIM_MODE_4, 4, 1, this); break; case 6: scene->_hotspot16.animate(ANIM_MODE_5, NULL); diff --git a/engines/tsage/ringworld/ringworld_scenes6.cpp b/engines/tsage/ringworld/ringworld_scenes6.cpp index 57a073caee..30a91b57aa 100644 --- a/engines/tsage/ringworld/ringworld_scenes6.cpp +++ b/engines/tsage/ringworld/ringworld_scenes6.cpp @@ -1124,7 +1124,7 @@ void Scene5100::postInit(SceneObjectList *OwnerList) { _hotspot4.setVisage(5363); _hotspot4.setPosition(Common::Point(1025, 65)); _hotspot4.setStrip(4); - _hotspot4.animate(ANIM_MODE_7, 0, NULL);; + _hotspot4.animate(ANIM_MODE_7, 0, NULL); g_globals->_sceneItems.push_back(&_hotspot4); _hotspot9.postInit(); diff --git a/engines/tsage/ringworld2/ringworld2_logic.cpp b/engines/tsage/ringworld2/ringworld2_logic.cpp index d033627ae9..642d265e42 100644 --- a/engines/tsage/ringworld2/ringworld2_logic.cpp +++ b/engines/tsage/ringworld2/ringworld2_logic.cpp @@ -38,6 +38,9 @@ Scene *Ringworld2Game::createScene(int sceneNumber) { // Quinn's room case 100: return new Scene100(); + // Computer console + case 125: return new Scene125(); + default: error("Unknown scene number - %d", sceneNumber); break; @@ -221,6 +224,22 @@ void SceneExt::refreshBackground(int xAmount, int yAmount) { /*--------------------------------------------------------------------------*/ +void SceneHandlerExt::postInit(SceneObjectList *OwnerList) { + SceneHandler::postInit(OwnerList); +} + +void SceneHandlerExt::process(Event &event) { + if (T2_GLOBALS._uiElements._active) { + T2_GLOBALS._uiElements.process(event); + if (event.handled) + return; + } + + SceneHandler::process(event); +} + +/*--------------------------------------------------------------------------*/ + DisplayHotspot::DisplayHotspot(int regionId, ...) { _sceneRegionId = regionId; @@ -398,7 +417,7 @@ void Ringworld2InvObjectList::reset() { } // Set up default inventory - setObjectScene(R2_1, 800); + setObjectScene(R2_OPTO_DISK, 800); setObjectScene(R2_2, 400); setObjectScene(R2_NEGATOR_GUN, 100); setObjectScene(R2_STEPPING_DISKS, 100); diff --git a/engines/tsage/ringworld2/ringworld2_logic.h b/engines/tsage/ringworld2/ringworld2_logic.h index b12978344c..b0f388a2ae 100644 --- a/engines/tsage/ringworld2/ringworld2_logic.h +++ b/engines/tsage/ringworld2/ringworld2_logic.h @@ -73,6 +73,13 @@ public: void clearScreen(); }; +class SceneHandlerExt: public SceneHandler { +public: + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void process(Event &event); +}; + + class DisplayHotspot : public SceneObject { private: Common::Array<int> _actions; diff --git a/engines/tsage/ringworld2/ringworld2_scenes0.cpp b/engines/tsage/ringworld2/ringworld2_scenes0.cpp index a2fb011d23..c03005ba8f 100644 --- a/engines/tsage/ringworld2/ringworld2_scenes0.cpp +++ b/engines/tsage/ringworld2/ringworld2_scenes0.cpp @@ -346,6 +346,773 @@ void Scene100::dispatch() { } } +/*-------------------------------------------------------------------------- + * Scene 125 - Computer Terminal + * + *--------------------------------------------------------------------------*/ + +bool Scene125::Object5::startAction(CursorType action, Event &event) { + if (action == CURSOR_USE) + return true; + else + return SceneActor::startAction(action, event); +} + +/*--------------------------------------------------------------------------*/ + +void Scene125::Icon::postInit(SceneObjectList *OwnerList) { + SceneObject::postInit(); + _lookLineNum = 0; + _pressed = false; + + _object1.postInit(); + _object1.hide(); + + _sceneText1._color1 = 92; + _sceneText1._color2 = 0; + _sceneText1._width = 200; + _sceneText2._color1 = 0; + _sceneText2._color2 = 0; + _sceneText2._width = 200; + setDetails(125, -1, -1, -1, 2, NULL); +} + +void Scene125::Icon::synchronize(Serializer &s) { + SceneActor::synchronize(s); + s.syncAsSint16LE(_lookLineNum); + s.syncAsSint16LE(_field98); + s.syncAsSint16LE(_pressed); +} + +void Scene125::Icon::process(Event &event) { + Scene125 *scene = (Scene125 *)R2_GLOBALS._sceneManager._scene; + + if (!event.handled && !(_flags & OBJFLAG_HIDING) && R2_GLOBALS._player._uiEnabled && + (event.eventType == EVENT_BUTTON_DOWN)) { + + int regionIndex = R2_GLOBALS._sceneRegions.indexOf(event.mousePos); + + switch (R2_GLOBALS._events.getCursor()) { + case CURSOR_LOOK: + if (regionIndex == _sceneRegionId) { + event.handled = true; + if (_lookLineNum == 26) { + SceneItem::display2(130, 7); + } else { + SceneItem::display2(130, _lookLineNum); + } + } + break; + + case CURSOR_USE: + if ((regionIndex == _sceneRegionId) && !_pressed) { + scene->_sound1.play(14); + setFrame(2); + + switch (_object1._strip) { + case 1: + _object1.setStrip(2); + break; + case 3: + _object1.setStrip(4); + break; + case 5: + _object1.setStrip(6); + break; + default: + break; + } + + _pressed = true; + event.handled = true; + } + break; + + default: + break; + } + + if ((event.eventType == EVENT_BUTTON_UP) && _pressed) { + switch (_object1._strip) { + case 2: + _object1.setStrip(1); + break; + case 4: + _object1.setStrip(3); + break; + case 6: + _object1.setStrip(5); + break; + default: + break; + } + + _pressed = false; + event.handled = true; + scene->consoleAction(_lookLineNum); + } + } +} + +void Scene125::Icon::setIcon(int id) { + Scene125 *scene = (Scene125 *)R2_GLOBALS._sceneManager._scene; + + _lookLineNum = _field98 = id; + SceneActor::_lookLineNum = id; + + _sceneText1.remove(); + _sceneText2.remove(); + + if (_lookLineNum) { + showIcon(); + _object1.setup(161, ((id - 1) / 10) * 2 + 1, ((id - 1) % 10) + 1); + _object1.setPosition(_position); + + _sceneText1._fontNumber = scene->_iconFontNumber; + _sceneText1.setup(CONSOLE_MESSAGES[id]); + _sceneText1.fixPriority(20); + + _sceneText2._fontNumber = scene->_iconFontNumber; + _sceneText2.setup(CONSOLE_MESSAGES[id]); + _sceneText2.fixPriority(20); + + _sceneText2._fontNumber = scene->_iconFontNumber; + _sceneText2.setup(CONSOLE_MESSAGES[id]); + _sceneText2.fixPriority(10); + + switch (_lookLineNum) { + case 5: + _sceneText1.setPosition(Common::Point(62, _position.y + 8)); + _sceneText2.setPosition(Common::Point(64, _position.y + 10)); + break; + case 6: + case 7: + case 24: + case 25: + _sceneText1.setPosition(Common::Point(65, _position.y + 8)); + _sceneText2.setPosition(Common::Point(67, _position.y + 10)); + break; + case 26: + _sceneText1.setPosition(Common::Point(83, _position.y + 8)); + _sceneText2.setPosition(Common::Point(85, _position.y + 10)); + break; + default: + _sceneText1.setPosition(Common::Point(121, _position.y + 8)); + _sceneText2.setPosition(Common::Point(123, _position.y + 10)); + break; + } + } else { + hideIcon(); + } +} + +void Scene125::Icon::showIcon() { + _sceneText1.show(); + _sceneText2.show(); + _object1.show(); + _object2.show(); + show(); +} + +void Scene125::Icon::hideIcon() { + _sceneText1.hide(); + _sceneText2.hide(); + _object1.hide(); + _object2.hide(); + hide(); +} + +/*--------------------------------------------------------------------------*/ + +bool Scene125::Item4::startAction(CursorType action, Event &event) { + Scene125 *scene = (Scene125 *)R2_GLOBALS._sceneManager._scene; + switch (action) { + case CURSOR_USE: + if (R2_INVENTORY.getObjectScene(R2_OPTO_DISK) == R2_GLOBALS._diskScene) { + R2_GLOBALS._player.disableControl(); + scene->_sceneMode = 126; + scene->setAction(&scene->_sequenceManager, scene, 126, &scene->_object7, NULL); + return true; + } + break; + case R2_OPTO_DISK: + if (R2_INVENTORY.getObjectScene(R2_OPTO_DISK) == 1) { + R2_GLOBALS._player.disableControl(); + scene->_object7.postInit(); + scene->_sceneMode = 125; + scene->setAction(&scene->_sequenceManager, scene, 125, &scene->_object7, NULL); + return true; + } + break; + default: + break; + } + + return SceneHotspot::startAction(action, event); +} + +/*--------------------------------------------------------------------------*/ + +Scene125::Scene125(): SceneExt() { + _soundCount = _soundIndex = 0; + _iconFontNumber = 50; + _field412 = 5; +} + +void Scene125::postInit(SceneObjectList *OwnerList) { + SceneExt::postInit(); + loadScene(160); + _palette.loadPalette(0); + + if (R2_GLOBALS._v5657C == 125) + R2_GLOBALS._diskScene = R2_GLOBALS._sceneManager._previousScene; + + R2_GLOBALS._player.postInit(); + R2_GLOBALS._player.hide(); + R2_GLOBALS._player.disableControl(); + + if (R2_INVENTORY.getObjectScene(R2_OPTO_DISK) == R2_GLOBALS._diskScene) { + _object7.postInit(); + _object7.setup(160, 3, 5); + _object7.setPosition(Common::Point(47, 167)); + } + + _object6.postInit(); + _object6.setup(162, 1, 1); + _object6.setPosition(Common::Point(214, 168)); + + _item4.setDetails(Rect(27, 145, 81, 159), 126, 9, -1, -1, 1, NULL); + _item3.setDetails(Rect(144, 119, 286, 167), 126, 6, 7, 8, 1, NULL); + _item2.setDetails(1, 126, 3, 4, 5); + _background.setDetails(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT), 126, 0, 1, -1, 1, NULL); + + _sceneMode = 1; + signal(); +} + +void Scene125::signal() { + switch (_sceneMode) { + case 1: + _icon1.postInit(); + _icon1._sceneRegionId = 2; + _icon2.postInit(); + _icon2._sceneRegionId = 3; + _icon3.postInit(); + _icon3._sceneRegionId = 4; + _icon4.postInit(); + _icon4._sceneRegionId = 5; + + setAction(&_sequenceManager, this, 127, &_icon1, &_icon2, &_icon3, &_icon4, &R2_GLOBALS._player, NULL); + break; + case 2: + _icon1.setup(160, 1, 1); + _icon1.setPosition(Common::Point(65, 17)); + _icon1._object2.postInit(); + _icon1._object2.setup(160, 7, 1); + _icon1._object2.setPosition(Common::Point(106, 41)); + + _icon2.setup(160, 1, 1); + _icon2.setPosition(Common::Point(80, 32)); + _icon2._object2.postInit(); + _icon2._object2.setup(160, 7, 2); + _icon2._object2.setPosition(Common::Point(106, 56)); + + _icon3.setup(160, 1, 1); + _icon3.setPosition(Common::Point(65, 47)); + _icon3._object2.postInit(); + _icon3._object2.setup(160, 7, 1); + _icon3._object2.setPosition(Common::Point(106, 71)); + + _icon4.setup(160, 1, 1); + _icon4.setPosition(Common::Point(80, 62)); + _icon4._sceneRegionId = 5; + _icon4._object2.postInit(); + _icon4._object2.setup(160, 7, 2); + _icon4._object2.setPosition(Common::Point(106, 86)); + + _icon5.postInit(); + _icon5.setup(160, 1, 1); + _icon5.setPosition(Common::Point(37, 92)); + _icon5.setIcon(6); + _icon5._sceneRegionId = 7; + + _icon6.postInit(); + _icon6.setPosition(Common::Point(106, 110)); + _icon6.setIcon(5); + _icon6._sceneRegionId = 8; + + R2_GLOBALS._player.enableControl(); + R2_GLOBALS._player._canWalk = false; + break; + case 10: + switch (_field412) { + case 12: + _sceneMode = 129; + + _object1.postInit(); + _object2.postInit(); + _object3.postInit(); + + if (R2_GLOBALS.getFlag(13)) { + _object4.postInit(); + setAction(&_sequenceManager, this, 130, &R2_GLOBALS._player, &_object1, &_object2, + &_object3, &_object4, NULL); + } else { + setAction(&_sequenceManager, this, 129, &R2_GLOBALS._player, &_object1, &_object2, &_object3, NULL); + } + break; + case 13: + R2_GLOBALS._player.enableControl(); + R2_GLOBALS._player._canWalk = false; + _field41A = 0; + setDetails(129, 0); + break; + case 23: + R2_GLOBALS._sceneManager.changeScene(1330); + break; + case 27: + R2_GLOBALS._player.enableControl(); + R2_GLOBALS._player._canWalk = false; + _field418 = 0; + setDetails(128, 0); + break; + case 28: + R2_GLOBALS._player.enableControl(); + R2_GLOBALS._player._canWalk = false; + _field418 = 37; + setDetails(128, 37); + break; + case 29: + R2_GLOBALS._player.enableControl(); + R2_GLOBALS._player._canWalk = false; + _field418 = 68; + setDetails(128, 68); + break; + case 30: + R2_GLOBALS._player.enableControl(); + R2_GLOBALS._player._canWalk = false; + _field418 = 105; + setDetails(128, 105); + break; + default: + R2_GLOBALS._player.enableControl(); + R2_GLOBALS._player._canWalk = false; + _field416 = 0; + setDetails(127, 0); + break; + } + break; + case 11: + R2_GLOBALS._player.enableControl(); + R2_GLOBALS._player._canWalk = false; + + if ((_field412 >= 27) && (_field412 <= 30)) { + consoleAction(11); + } + consoleAction(2); + _icon6.setIcon(5); + break; + case 12: + if (_soundCount > 0) + --_soundCount; + if (!_soundCount || (R2_GLOBALS._v57C2C == 2)) { + _soundIndex = 0; + R2_GLOBALS._playStream.stop(); + } else { + _sceneMode = 12; + R2_GLOBALS._playStream.play(_soundIndexes[_soundIndex++], this); + } + break; + case 125: + warning("TODO: Scene125::signal #125"); + break; + case 126: + R2_INVENTORY.setObjectScene(R2_OPTO_DISK, 1); + _object7.remove(); + R2_GLOBALS._player.enableControl(); + R2_GLOBALS._player._canWalk = false; + break; + case 128: + R2_GLOBALS._player.enableControl(); + R2_GLOBALS._player._canWalk = false; + SceneItem::display2(126, 12); + break; + default: + R2_GLOBALS._player.enableControl(); + R2_GLOBALS._player._canWalk = false; + break; + } +} + +void Scene125::synchronize(Serializer &s) { + error("TODO"); +} + +void Scene125::process(Event &event) { + SceneExt::process(event); + + if (R2_GLOBALS._player._uiEnabled) { + _icon1.process(event); + _icon2.process(event); + _icon3.process(event); + _icon4.process(event); + _icon5.process(event); + _icon6.process(event); + } +} + +void Scene125::dispatch() { + if (_soundCount) + R2_GLOBALS._playStream.proc1(); + + Scene::dispatch(); +} + +void Scene125::consoleAction(int id) { + _icon3.setIcon(0); + _icon4.setIcon(0); + + if (id == 5) + _icon5.setIcon(5); + else { + switch (_field412) { + case 10: + case 12: + case 13: + case 27: + case 28: + case 29: + case 30: + break; + default: + _icon5.setIcon(7); + break; + } + } + + switch (id) { + case 0: + _icon1.setIcon(8); + _icon2.setIcon(9); + break; + case 1: + _icon1.setIcon(10); + _icon2.setIcon(11); + _icon3.setIcon(12); + _icon4.setIcon(13); + break; + case 2: + _icon1.setIcon(15); + _icon2.setIcon(16); + _icon3.setIcon(17); + break; + case 3: + _icon1.setIcon(22); + _icon2.setIcon(23); + break; + case 5: + R2_GLOBALS._sceneManager.changeScene(R2_GLOBALS._player._oldSceneNumber); + break; + case 6: + if (_field412 == 11) + consoleAction(2); + else if (_field412 == 22) + consoleAction(4); + else + consoleAction(5); + break; + case 7: + _iconFontNumber = 50; + stop(); + _icon6.setIcon(5); + consoleAction(1); + break; + case 8: + _iconFontNumber = 52; + stop(); + _icon6.setIcon(5); + consoleAction(1); + break; + case 9: + R2_GLOBALS._player.disableControl(); + consoleAction(2); + _icon1.hideIcon(); + _icon2.hideIcon(); + _icon3.hideIcon(); + _icon5.setIcon(24); + + _icon4.setPosition(Common::Point(52, 107)); + _icon4._sceneRegionId = 9; + _icon4.setIcon(25); + _icon4._object2.hide(); + + _icon6.setIcon(26); + _sceneMode = 10; + + _palette.loadPalette(161); + R2_GLOBALS._scenePalette.addFader(_palette._palette, 256, 5, this); + break; + case 10: + _icon1.setIcon(27); + _icon2.setIcon(28); + _icon3.setIcon(29); + _icon4.setIcon(30); + break; + case 11: + R2_GLOBALS._player.disableControl(); + consoleAction(2); + _icon1.hideIcon(); + _icon2.hideIcon(); + _icon3.hideIcon(); + _icon4.hideIcon(); + _icon5.hideIcon(); + + _icon6.setIcon(26); + R2_GLOBALS._scenePalette.addFader(_palette._palette, 256, 5, this); + break; + case 12: + consoleAction(2); + if (R2_INVENTORY.getObjectScene(R2_OPTO_DISK) != R2_GLOBALS._player._oldSceneNumber) { + SceneItem::display2(126, 17); + } else { + R2_GLOBALS._player.disableControl(); + + _icon1.hideIcon(); + _icon2.hideIcon(); + _icon3.hideIcon(); + _icon5.setIcon(24); + + _icon4.setPosition(Common::Point(52, 107)); + _icon4._sceneRegionId = 9; + _icon4.setIcon(25); + _icon4._object2.hide(); + + _icon6.setIcon(26); + _sceneMode = 10; + + _palette.loadPalette(161); + R2_GLOBALS._scenePalette.addFader(_palette._palette, 256, 5, this); + } + break; + case 14: + consoleAction(3); + + if (R2_GLOBALS._v565F5 < 3) { + R2_GLOBALS._player.disableControl(); + _object5.postInit(); + _object5.setup(162, 2, 2); + _object5.setPosition(Common::Point(216, UI_INTERFACE_Y)); + + R2_GLOBALS._v565F5 += 2; + } else if (R2_GLOBALS._v565F5 == 3) { + SceneItem::display2(126, 13); + } else { + SceneItem::display2(126, 14); + } + break; + case 15: + consoleAction(3); + + if (R2_GLOBALS._v565F5 < 4) { + R2_GLOBALS._player.disableControl(); + _object5.postInit(); + _object5.setup(162, 2, 3); + _object5.setPosition(Common::Point(218, UI_INTERFACE_Y)); + + ++R2_GLOBALS._v565F5; + } else { + SceneItem::display2(126, 15); + } + break; + case 16: + consoleAction(3); + + if (R2_GLOBALS._v565F5 < 4) { + R2_GLOBALS._player.disableControl(); + _object5.postInit(); + _object5.setup(162, 2, 1); + _object5.setPosition(Common::Point(215, UI_INTERFACE_Y)); + + ++R2_GLOBALS._v565F5; + } else { + SceneItem::display2(126, 16); + } + break; + case 21: + _icon1.setIcon(31); + _icon2.setIcon(32); + _icon3.setIcon(33); + _icon4.setIcon(34); + break; + case 22: + R2_GLOBALS._player.disableControl(); + consoleAction(4); + _icon1.hideIcon(); + _icon2.hideIcon(); + _icon3.hideIcon(); + _icon4.hideIcon(); + _icon5.hideIcon(); + _icon6.hideIcon(); + + _sceneMode = 10; + _palette.loadPalette(161); + break; + case 23: + _icon4.setIcon(25); + _icon4._object2.hide(); + + if (_field412 == 10) { + setDetails(127, --_field416); + } else if (_field412 == 13) { + setDetails(129, --_field41A); + } else { + setDetails(128, --_field418); + } + break; + case 24: + _icon4.setIcon(25); + _icon4._object2.hide(); + + if (_field412 == 10) { + setDetails(127, ++_field416); + } else if (_field412 == 13) { + setDetails(129, ++_field41A); + } else { + setDetails(128, ++_field418); + } + break; + case 25: + R2_GLOBALS._player.disableControl(); + stop(); + _icon4.setPosition(Common::Point(80, 62)); + _icon4._sceneRegionId = 5; + _icon4.hideIcon(); + + R2_GLOBALS._player.hide(); + _object1.hide(); + _object2.hide(); + _object3.hide(); + _object4.hide(); + + _sceneMode = 11; + _palette.loadPalette(160); + R2_GLOBALS._scenePalette.addFader(_palette._palette, 256, 5, this); + break; + case 26: + case 27: + case 28: + case 29: + R2_GLOBALS._player.disableControl(); + consoleAction(11); + _field412 = id; + + _icon1.hideIcon(); + _icon2.hideIcon(); + _icon3.hideIcon(); + _icon4.hideIcon(); + _icon5.setIcon(24); + + _icon4.setPosition(Common::Point(52, 107)); + _icon4._sceneRegionId = 9; + _icon4.setIcon(25); + _icon4._object2.hide(); + + _icon6.setIcon(26); + _sceneMode = 10; + + _palette.loadPalette(161); + R2_GLOBALS._scenePalette.addFader(_palette._palette, 256, 5, this); + break; + case 30: + consoleAction(22); + R2_GLOBALS._sound1.play((R2_GLOBALS._sound1.getSoundNum() == 10) ? 63 : 10); + break; + case 31: + consoleAction(22); + R2_GLOBALS._sound1.play((R2_GLOBALS._sound1.getSoundNum() == 10) ? 64 : 10); + break; + case 32: + consoleAction(22); + R2_GLOBALS._sound1.play((R2_GLOBALS._sound1.getSoundNum() == 10) ? 65 : 10); + break; + case 33: + consoleAction(22); + R2_GLOBALS._sound1.play((R2_GLOBALS._sound1.getSoundNum() == 10) ? 66 : 10); + break; + default: + _icon1.setIcon(1); + _icon2.setIcon(2); + _icon3.setIcon(3); + _icon4.setIcon(4); + break; + } + + if ((id != 6) && (id != 7) && (id != 23) && (id != 24)) + _field412 = id; +} + +void Scene125::setDetails(int resNum, int lineNum) { + stop(); + + Common::String msg = g_resourceManager->getMessage(resNum, lineNum); + + if (msg.empty()) { + // Check for any specified sound numbers embedded in the message + Common::String msg = parseMessage(msg); + + _sceneText._fontNumber = _iconFontNumber; + _sceneText._color1 = 92; + _sceneText._color2 = 0; + _sceneText._width = 221; + _sceneText.fixPriority(20); + _sceneText.setup(msg); + _sceneText.setPosition(Common::Point(49, 19)); + + R2_GLOBALS._sceneObjects->draw(); + + if ((_soundCount > 0) && (R2_GLOBALS._v57C2C != 2)) { + _sceneMode = 12; + R2_GLOBALS._playStream.play(_soundIndexes[_soundIndex], this); + } + } else { + R2_GLOBALS._player.disableControl(); + R2_GLOBALS._player.hide(); + + _icon4.setPosition(Common::Point(80, 62)); + _icon4._sceneRegionId = 5; + _icon4.hideIcon(); + + _field412 = 0; + _palette.loadPalette(160); + _sceneMode = 11; + R2_GLOBALS._scenePalette.addFader(_palette._palette, 256, 5, this); + } +} + +void Scene125::stop() { + _sceneText.remove(); + _soundIndex = 0; + _soundCount = 0; + + R2_GLOBALS._playStream.stop(); +} + +Common::String Scene125::parseMessage(const Common::String &msg) { + _soundIndex = 0; + _soundCount = 0; + + const char *msgP = msg.c_str(); + while (*msgP == '!') { + // Get the sound number + _soundIndexes[_soundCount++] = atoi(++msgP); + + while (!((*msgP == '\0') || (*msgP < '0') || (*msgP > '9'))) + ++msgP; + } + + return Common::String(msgP); +} + } // End of namespace Ringworld2 } // End of namespace TsAGE diff --git a/engines/tsage/ringworld2/ringworld2_scenes0.h b/engines/tsage/ringworld2/ringworld2_scenes0.h index a80bda0726..9ffe10f132 100644 --- a/engines/tsage/ringworld2/ringworld2_scenes0.h +++ b/engines/tsage/ringworld2/ringworld2_scenes0.h @@ -85,6 +85,62 @@ public: virtual void dispatch(); }; +class Scene125: public SceneExt { + /* Objects */ + class Object5: public SceneActor { + public: + virtual bool startAction(CursorType action, Event &event); + }; + + class Icon: public SceneActor { + public: + int _lookLineNum, _field98; + bool _pressed; + SceneObject _object1, _object2; + SceneText _sceneText1, _sceneText2; + + virtual Common::String getClassName() { return "Scene125_Icon"; } + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void synchronize(Serializer &s); + virtual void process(Event &event); + + void setIcon(int id); + void showIcon(); + void hideIcon(); + }; + + /* Items */ + class Item4: public NamedHotspot { + public: + virtual bool startAction(CursorType action, Event &event); + }; + +public: + ScenePalette _palette; + ASoundExt _sound1; + NamedHotspot _background, _item2, _item3; + Item4 _item4; + SceneActor _object1, _object2, _object3, _object4, _object5, _object6, _object7; + Icon _icon1, _icon2, _icon3, _icon4, _icon5, _icon6; + SequenceManager _sequenceManager; + SceneText _sceneText; + int _field412, _iconFontNumber, _field416, _field418, _field41A; + int _soundCount, _soundIndex; + int _soundIndexes[10]; + + Scene125(); + virtual void postInit(SceneObjectList *OwnerList = NULL); + virtual void synchronize(Serializer &s); + virtual void signal(); + virtual void process(Event &event); + virtual void dispatch(); + + void consoleAction(int id); + void setDetails(int resNum, int lineNum); + void stop(); + Common::String parseMessage(const Common::String &msg); +}; + } // End of namespace Ringworld2 } // End of namespace TsAGE diff --git a/engines/tsage/sound.h b/engines/tsage/sound.h index 2c5d2ac951..3eb2432563 100644 --- a/engines/tsage/sound.h +++ b/engines/tsage/sound.h @@ -414,6 +414,15 @@ public: virtual void signal(); }; +class PlayStream { +public: + Sound _sound; + + void setFile(const Common::String &filename) {} + void play(int soundNum, EventHandler *endAction) {} + void stop() {} + void proc1() {} +}; #define ADLIB_CHANNEL_COUNT 9 diff --git a/engines/tsage/staticres.cpp b/engines/tsage/staticres.cpp index c98d9d2e53..a6e6eae84e 100644 --- a/engines/tsage/staticres.cpp +++ b/engines/tsage/staticres.cpp @@ -180,4 +180,17 @@ const char *THE_NEXT_DAY = "The Next Day"; } // End of namespace BlueForce +namespace Ringworld2 { + +const char *CONSOLE_MESSAGES[] = { + NULL, "Select Language", "Computer Services", "Food Services", "Entertainment Services", + "Main Menu", "Exit Menu", "Previous Menu", "Interworld", "Hero's Tongue", "Personal Log", + "Database", "Starchart", "Iso-Opto Disk Reader", "Eject Disk", "Meals", "Snacks", + "Beverages", "Human Basic Snacks", "Kzin Basic Snacks", "Hot Beverages", "Cold Beverages", + "Music", "Outpost Alpha", " ", " ", "Done", "A-G", "H-O", "P-S", "T-Z", "Tchaikovsky", + "Mozart", "Bach", "Rossini" +}; + +} // End of namespace Ringworld2 + } // End of namespace TsAGE diff --git a/engines/tsage/staticres.h b/engines/tsage/staticres.h index 203fa1481d..b2c0b0f262 100644 --- a/engines/tsage/staticres.h +++ b/engines/tsage/staticres.h @@ -143,6 +143,13 @@ extern const char *THE_NEXT_DAY; } // End of namespace BlueForce +namespace Ringworld2 { + +// Scene 125 - Console messages +extern const char *CONSOLE_MESSAGES[]; + +} // End of namespace Ringworld2 + } // End of namespace TsAGE #endif diff --git a/engines/tsage/tsage.cpp b/engines/tsage/tsage.cpp index 7e7198fc2b..20b2eeac8f 100644 --- a/engines/tsage/tsage.cpp +++ b/engines/tsage/tsage.cpp @@ -97,7 +97,13 @@ void TSageEngine::initialize() { // Reset all global variables R2_GLOBALS.reset(); - } + } else if (g_vm->getGameID() == GType_Geekwad) { + g_resourceManager->addLib("GEEKWAD.RLB"); + g_globals = new Geekwad::GeekwadGlobals(); + + // Reset all global variables + GW_GLOBALS.reset(); + } g_globals->gfxManager().setDefaults(); diff --git a/engines/tsage/tsage.h b/engines/tsage/tsage.h index eb36cf0790..e57823ecbc 100644 --- a/engines/tsage/tsage.h +++ b/engines/tsage/tsage.h @@ -41,7 +41,8 @@ namespace TsAGE { enum { GType_Ringworld = 0, GType_BlueForce = 1, - GType_Ringworld2 = 2 + GType_Ringworld2 = 2, + GType_Geekwad = 3 }; enum { diff --git a/engines/tsage/user_interface.cpp b/engines/tsage/user_interface.cpp index f6eae80d9c..9657d25875 100644 --- a/engines/tsage/user_interface.cpp +++ b/engines/tsage/user_interface.cpp @@ -266,7 +266,10 @@ void UICollection::draw() { /*--------------------------------------------------------------------------*/ UIElements::UIElements(): UICollection() { - _cursorVisage.setVisage(1, 5); + if (g_vm->getGameID() == GType_Ringworld2) + _cursorVisage.setVisage(5, 1); + else + _cursorVisage.setVisage(1, 5); g_saver->addLoadNotifier(&UIElements::loadNotifierProc); _characterIndex = 0; } @@ -302,7 +305,8 @@ void UIElements::synchronize(Serializer &s) { } void UIElements::process(Event &event) { - if (_clearScreen && GLOBALS._player._enabled && (GLOBALS._sceneManager._sceneNumber != 50)) { + if (_clearScreen && GLOBALS._player._enabled && + ((g_vm->getGameID() != GType_BlueForce) || (GLOBALS._sceneManager._sceneNumber != 50))) { if (_bounds.contains(event.mousePos)) { // Cursor inside UI area if (!_cursorChanged) { @@ -310,7 +314,8 @@ void UIElements::process(Event &event) { // Inventory icon being displayed, so leave alone } else { // Change to the inventory use cursor - GfxSurface surface = _cursorVisage.getFrame(6); + int cursorId = (g_vm->getGameID() == GType_Ringworld2) ? 11 : 6; + GfxSurface surface = _cursorVisage.getFrame(cursorId); GLOBALS._events.setCursor(surface); } _cursorChanged = true; diff --git a/gui/console.cpp b/gui/console.cpp index dc2c5c4f33..49e2fccd98 100644 --- a/gui/console.cpp +++ b/gui/console.cpp @@ -245,6 +245,8 @@ void ConsoleDialog::handleTickle() { } else draw(); } + + _scrollBar->handleTickle(); } void ConsoleDialog::handleMouseWheel(int x, int y, int direction) { diff --git a/gui/widgets/list.cpp b/gui/widgets/list.cpp index 2a0d4afff0..13784ddf7f 100644 --- a/gui/widgets/list.cpp +++ b/gui/widgets/list.cpp @@ -220,6 +220,7 @@ void ListWidget::scrollBarRecalc() { void ListWidget::handleTickle() { if (_editMode) EditableWidget::handleTickle(); + _scrollBar->handleTickle(); } void ListWidget::handleMouseDown(int x, int y, int button, int clickCount) { diff --git a/gui/widgets/scrollbar.cpp b/gui/widgets/scrollbar.cpp index e0dbcec59c..c7c17bc908 100644 --- a/gui/widgets/scrollbar.cpp +++ b/gui/widgets/scrollbar.cpp @@ -45,28 +45,8 @@ ScrollBarWidget::ScrollBarWidget(GuiObject *boss, int x, int y, int w, int h) _numEntries = 0; _entriesPerPage = 0; _currentPos = 0; -} - -static void upArrowRepeater(void *ref) { - ScrollBarWidget *sb = (ScrollBarWidget *)ref; - int old_pos = sb->_currentPos; - - sb->_currentPos -= 3; - sb->checkBounds(old_pos); - - g_system->getTimerManager()->removeTimerProc(&upArrowRepeater); - g_system->getTimerManager()->installTimerProc(&upArrowRepeater, 1000000/10, ref, "guiScrollBarUp"); -} - -static void downArrowRepeater(void *ref) { - ScrollBarWidget *sb = (ScrollBarWidget *)ref; - int old_pos = sb->_currentPos; - sb->_currentPos += 3; - sb->checkBounds(old_pos); - - g_system->getTimerManager()->removeTimerProc(&downArrowRepeater); - g_system->getTimerManager()->installTimerProc(&downArrowRepeater, 1000000/10, ref, "guiScrollBarDown"); + _repeatTimer = 0; } void ScrollBarWidget::handleMouseDown(int x, int y, int button, int clickCount) { @@ -79,13 +59,13 @@ void ScrollBarWidget::handleMouseDown(int x, int y, int button, int clickCount) if (y <= UP_DOWN_BOX_HEIGHT) { // Up arrow _currentPos--; + _repeatTimer = g_system->getMillis() + kRepeatInitialDelay; _draggingPart = kUpArrowPart; - g_system->getTimerManager()->installTimerProc(&upArrowRepeater, 1000000/2, this, "guiScrollBarUp"); } else if (y >= _h - UP_DOWN_BOX_HEIGHT) { // Down arrow _currentPos++; + _repeatTimer = g_system->getMillis() + kRepeatInitialDelay; _draggingPart = kDownArrowPart; - g_system->getTimerManager()->installTimerProc(&downArrowRepeater, 1000000/2, this, "guiScrollBarDown"); } else if (y < _sliderPos) { _currentPos -= _entriesPerPage - 1; } else if (y >= _sliderPos + _sliderHeight) { @@ -101,9 +81,7 @@ void ScrollBarWidget::handleMouseDown(int x, int y, int button, int clickCount) void ScrollBarWidget::handleMouseUp(int x, int y, int button, int clickCount) { _draggingPart = kNoPart; - - g_system->getTimerManager()->removeTimerProc(&upArrowRepeater); - g_system->getTimerManager()->removeTimerProc(&downArrowRepeater); + _repeatTimer = 0; } void ScrollBarWidget::handleMouseWheel(int x, int y, int direction) { @@ -160,23 +138,21 @@ void ScrollBarWidget::handleMouseMoved(int x, int y, int button) { } void ScrollBarWidget::handleTickle() { -/* - // FIXME/TODO - this code is supposed to allow for "click-repeat" (like key repeat), - // i.e. if you click on one of the arrows and keep clicked, it will scroll - // continuously. However, just like key repeat, this requires two delays: - // First an "initial" delay that has to pass before repeating starts (otherwise - // it is near to impossible to achieve single clicks). Secondly, a repeat delay - // that determines how often per second a click is simulated. - int old_pos = _currentPos; + if (_repeatTimer) { + const uint32 curTime = g_system->getMillis(); + if (curTime >= _repeatTimer) { + const int old_pos = _currentPos; - if (_draggingPart == kUpArrowPart) - _currentPos--; - else if (_draggingPart == kDownArrowPart) - _currentPos++; + if (_part == kUpArrowPart) + _currentPos -= 3; + else if (_part == kDownArrowPart) + _currentPos += 3; - // Make sure that _currentPos is still inside the bounds - checkBounds(old_pos); -*/ + checkBounds(old_pos); + + _repeatTimer = curTime + kRepeatDelay; + } + } } void ScrollBarWidget::checkBounds(int old_pos) { diff --git a/gui/widgets/scrollbar.h b/gui/widgets/scrollbar.h index 3b248ce8a4..1c9f371cbc 100644 --- a/gui/widgets/scrollbar.h +++ b/gui/widgets/scrollbar.h @@ -49,6 +49,12 @@ protected: Part _draggingPart; int _sliderDeltaMouseDownPos; + enum { + kRepeatInitialDelay = 500, + kRepeatDelay = 100 + }; + uint32 _repeatTimer; + public: int _numEntries; int _entriesPerPage; |