diff options
Diffstat (limited to 'engines/scumm')
-rw-r--r-- | engines/scumm/module.mk | 1 | ||||
-rw-r--r-- | engines/scumm/music.h | 6 | ||||
-rw-r--r-- | engines/scumm/player_v4a.cpp | 193 | ||||
-rw-r--r-- | engines/scumm/player_v4a.h | 98 | ||||
-rw-r--r-- | engines/scumm/scumm.cpp | 21 | ||||
-rw-r--r-- | engines/scumm/scumm.h | 1 | ||||
-rw-r--r-- | engines/scumm/sound.cpp | 20 |
7 files changed, 295 insertions, 45 deletions
diff --git a/engines/scumm/module.mk b/engines/scumm/module.mk index 58d8db91fc..51fbecdb0d 100644 --- a/engines/scumm/module.mk +++ b/engines/scumm/module.mk @@ -40,6 +40,7 @@ MODULE_OBJS := \ player_v2a.o \ player_v2cms.o \ player_v3a.o \ + player_v4a.o \ resource_v2.o \ resource_v3.o \ resource_v4.o \ diff --git a/engines/scumm/music.h b/engines/scumm/music.h index c6555318a9..2fd7c50bce 100644 --- a/engines/scumm/music.h +++ b/engines/scumm/music.h @@ -81,12 +81,6 @@ public: * @return the music timer */ virtual int getMusicTimer() const { return 0; } - - /** - * Terminate the music engine. Called just before the music engine - * is deleted. - */ - virtual void terminate() {} }; } // End of namespace Scumm diff --git a/engines/scumm/player_v4a.cpp b/engines/scumm/player_v4a.cpp new file mode 100644 index 0000000000..f441b3b364 --- /dev/null +++ b/engines/scumm/player_v4a.cpp @@ -0,0 +1,193 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#include "engines/engine.h" +#include "scumm/player_v4a.h" +#include "scumm/scumm.h" + +#include "common/file.h" + +namespace Scumm { + +Player_V4A::Player_V4A(ScummEngine *scumm, Audio::Mixer *mixer) + : _vm(scumm), + _mixer(mixer), + _tfmxMusic(_mixer->getOutputRate(), true), + _tfmxSfx(_mixer->getOutputRate(), true), + _musicHandle(), + _sfxHandle(), + _musicId(), + _sfxSlots(), + _initState(0), + _signal(0) { + + assert(scumm); + assert(mixer); + assert(_vm->_game.id == GID_MONKEY_VGA); + _tfmxMusic.setSignalPtr(&_signal, 1); +} + +bool Player_V4A::init() { + if (_vm->_game.id != GID_MONKEY_VGA) + error("player_v4a - unknown game"); + + Common::File fileMdat, fileSample; + + if (fileMdat.open("music.dat") && fileSample.open("sample.dat")) { + // explicitly request that no instance delets the resources automatically + if (_tfmxMusic.load(fileMdat, fileSample, false)) { + _tfmxSfx.setModuleData(_tfmxMusic); + return true; + } + } else + warning("player_v4a: couldnt load one of the music resources: music.dat, sample.dat"); + + return false; +} + +Player_V4A::~Player_V4A() { + _mixer->stopHandle(_musicHandle); + _mixer->stopHandle(_sfxHandle); + _tfmxMusic.freeResources(); +} + +void Player_V4A::setMusicVolume(int vol) { + debug(5, "player_v4a: setMusicVolume %i", vol); +} + +void Player_V4A::stopAllSounds() { + debug(5, "player_v4a: stopAllSounds"); + if (_initState > 0) { + _tfmxMusic.stopSong(); + _signal = 0; + _musicId = 0; + + _tfmxSfx.stopSong(); + clearSfxSlots(); + } else + _mixer->stopHandle(_musicHandle); +} + +void Player_V4A::stopSound(int nr) { + debug(5, "player_v4a: stopSound %d", nr); + if (nr == 0) + return; + if (nr == _musicId) { + _musicId = 0; + if (_initState > 0) + _tfmxMusic.stopSong(); + else + _mixer->stopHandle(_musicHandle); + _signal = 0; + } else { + const int chan = getSfxChan(nr); + if (chan != -1) { + setSfxSlot(chan, 0); + _tfmxSfx.stopMacroEffect(chan); + } + } +} + +void Player_V4A::startSound(int nr) { + static const int8 monkeyCommands[52] = { + -1, -2, -3, -4, -5, -6, -7, -8, + -9, -10, -11, -12, -13, -14, 18, 17, + -17, -18, -19, -20, -21, -22, -23, -24, + -25, -26, -27, -28, -29, -30, -31, -32, + -33, 16, -35, 0, 1, 2, 3, 7, + 8, 10, 11, 4, 5, 14, 15, 12, + 6, 13, 9, 19 + }; + + const byte *ptr = _vm->getResourceAddress(rtSound, nr); + assert(ptr); + + const int val = ptr[9]; + if (val < 0 || val >= ARRAYSIZE(monkeyCommands)) { + warning("player_v4a: illegal Songnumber %i", val); + return; + } + + if (!_initState) + _initState = init() ? 1 : -1; + + if (_initState < 0) + return; + + int index = monkeyCommands[val]; + const byte type = ptr[6]; + if (index < 0) { // SoundFX + index = -index - 1; + debug(3, "player_v4a: play %d: custom %i - %02X", nr, index, type); + + // start an empty Song so timing is setup + if (_tfmxSfx.getSongIndex() < 0) + _tfmxSfx.doSong(0x18); + + const int chan = _tfmxSfx.doSfx((uint16)index); + if (chan >= 0 && chan < ARRAYSIZE(_sfxSlots)) + setSfxSlot(chan, nr, type); + else + warning("player_v4a: custom %i is not of required type", index); + + // the Tfmx-player never "ends" the output by itself, so this should be threadsafe + if (!_mixer->isSoundHandleActive(_sfxHandle)) + _mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_sfxHandle, &_tfmxSfx, -1, Audio::Mixer::kMaxChannelVolume, 0, false); + + } else { // Song + debug(3, "player_v4a: play %d: song %i - %02X", nr, index, type); + if (ptr[6] != 0x7F) + warning("player_v4a: Song has wrong type"); + + _tfmxMusic.doSong(index); + _signal = 2; + + // the Tfmx-player never "ends" the output by itself, so this should be threadsafe + if (!_mixer->isSoundHandleActive(_musicHandle)) + _mixer->playInputStream(Audio::Mixer::kMusicSoundType, &_musicHandle, &_tfmxMusic, -1, Audio::Mixer::kMaxChannelVolume, 0, false); + _musicId = nr; + } +} + +int Player_V4A::getMusicTimer() const { + // A workaround if the modplayer couldnt load the datafiles - just return a number big enough to pass all tests + if (_initState < 0) + return 2000; + if (_musicId) { + // The titlesong (and a few others) is running with ~70 ticks per second and the scale seems to be based on that. + // The Game itself doesnt get the timing from the Tfmx Player however, so we just use the elapsed time + // 357 ~ 1000 * 25 * (1 / 70) + return _mixer->getSoundElapsedTime(_musicHandle) / 357; + } + return 0; +} + +int Player_V4A::getSoundStatus(int nr) const { + // For music the game queues a variable the Tfmx Player sets through a special command. + // For sfx there seems to be no way to queue them, and the game doesnt try to. + return (nr == _musicId) ? _signal : 0; +} + +} // End of namespace Scumm diff --git a/engines/scumm/player_v4a.h b/engines/scumm/player_v4a.h new file mode 100644 index 0000000000..5f5fae6b56 --- /dev/null +++ b/engines/scumm/player_v4a.h @@ -0,0 +1,98 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#ifndef SCUMM_PLAYER_V4A_H +#define SCUMM_PLAYER_V4A_H + +#include "common/scummsys.h" +#include "scumm/music.h" +#include "sound/mixer.h" +#include "sound/mods/tfmx.h" + +class Mixer; + +namespace Scumm { + +class ScummEngine; + +/** + * Scumm V4 Amiga sound/music driver. + */ +class Player_V4A : public MusicEngine { +public: + Player_V4A(ScummEngine *scumm, Audio::Mixer *mixer); + virtual ~Player_V4A(); + + virtual void setMusicVolume(int vol); + virtual void startSound(int sound); + virtual void stopSound(int sound); + virtual void stopAllSounds(); + virtual int getMusicTimer() const; + virtual int getSoundStatus(int sound) const; + +private: + ScummEngine *const _vm; + Audio::Mixer *const _mixer; + + Audio::Tfmx _tfmxMusic; + Audio::Tfmx _tfmxSfx; + Audio::SoundHandle _musicHandle; + Audio::SoundHandle _sfxHandle; + + int _musicId; + uint16 _signal; + + struct SfxChan { + int id; +// byte type; + } _sfxSlots[4]; + + int8 _initState; // < 0: failed, 0: uninitialised, > 0: initialised + + int getSfxChan(int id) const { + for (int i = 0; i < ARRAYSIZE(_sfxSlots); ++i) + if (_sfxSlots[i].id == id) + return i; + return -1; + } + + void setSfxSlot(int channel, int id, byte type = 0) { + _sfxSlots[channel].id = id; +// _sfxSlots[channel].type = type; + } + + void clearSfxSlots() { + for (int i = 0; i < ARRAYSIZE(_sfxSlots); ++i){ + _sfxSlots[i].id = 0; +// _sfxSlots[i].type = 0; + } + } + + bool init(); +}; + +} // End of namespace Scumm + +#endif diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp index af6b9278c6..587e2a8abe 100644 --- a/engines/scumm/scumm.cpp +++ b/engines/scumm/scumm.cpp @@ -56,6 +56,7 @@ #include "scumm/player_v2.h" #include "scumm/player_v2a.h" #include "scumm/player_v3a.h" +#include "scumm/player_v4a.h" #include "scumm/he/resource_he.h" #include "scumm/scumm_v0.h" #include "scumm/scumm_v8.h" @@ -284,7 +285,6 @@ ScummEngine::ScummEngine(OSystem *syst, const DetectorResult &dr) _useTalkAnims = false; _defaultTalkDelay = 0; _musicType = MDT_NONE; - _tempMusic = 0; _saveSound = 0; memset(_extraBoxFlags, 0, sizeof(_extraBoxFlags)); memset(_scaleSlots, 0, sizeof(_scaleSlots)); @@ -554,10 +554,7 @@ ScummEngine::ScummEngine(OSystem *syst, const DetectorResult &dr) ScummEngine::~ScummEngine() { Common::clearAllDebugChannels(); - if (_musicEngine) { - _musicEngine->terminate(); - delete _musicEngine; - } + delete _musicEngine; _mixer->stopAll(); @@ -1296,7 +1293,6 @@ void ScummEngine::setupCostumeRenderer() { void ScummEngine::resetScumm() { int i; - _tempMusic = 0; debug(9, "resetScumm"); if (_game.version == 0) { @@ -1698,7 +1694,7 @@ void ScummEngine::setupMusic(int midi) { } else if (_game.platform == Common::kPlatformPCEngine && _game.version == 3) { // TODO: Add support for music format } else if (_game.platform == Common::kPlatformAmiga && _game.version <= 4) { - // TODO: Add support for music format + _musicEngine = new Player_V4A(this, _mixer); } else if (_game.id == GID_MANIAC && _game.version == 1) { _musicEngine = new Player_V1(this, _mixer, midiDriver != MD_PCSPK); } else if (_game.version <= 2) { @@ -1909,17 +1905,6 @@ void ScummEngine::scummLoop(int delta) { if (_musicEngine) { // The music engine generates the timer data for us. VAR(VAR_MUSIC_TIMER) = _musicEngine->getMusicTimer(); - } else { - // Used for Money Island 1 (Amiga) - // TODO: The music delay (given in milliseconds) might have to be tuned a little - // to get it correct for all games. Without the ability to watch/listen to the - // original games, I can't do that myself. - const int MUSIC_DELAY = 350; - _tempMusic += delta * 1000 / 60; // Convert delta to milliseconds - if (_tempMusic >= MUSIC_DELAY) { - _tempMusic -= MUSIC_DELAY; - VAR(VAR_MUSIC_TIMER) += 1; - } } } diff --git a/engines/scumm/scumm.h b/engines/scumm/scumm.h index 6866b17668..940ea512d5 100644 --- a/engines/scumm/scumm.h +++ b/engines/scumm/scumm.h @@ -1139,7 +1139,6 @@ protected: bool _haveActorSpeechMsg; bool _useTalkAnims; uint16 _defaultTalkDelay; - int _tempMusic; int _saveSound; bool _native_mt32; bool _enable_gs; diff --git a/engines/scumm/sound.cpp b/engines/scumm/sound.cpp index 524dbf70ea..82ed2a62e6 100644 --- a/engines/scumm/sound.cpp +++ b/engines/scumm/sound.cpp @@ -436,26 +436,6 @@ void Sound::playSound(int soundID) { if (_vm->_game.id == GID_MONKEY_VGA || _vm->_game.id == GID_MONKEY_EGA || (_vm->_game.id == GID_MONKEY && _vm->_game.platform == Common::kPlatformMacintosh)) { - // Sound is currently not supported at all in the amiga versions of these games - if (_vm->_game.platform == Common::kPlatformAmiga) { - int track = -1; - if (soundID == 50) - track = 17; - else if (ptr[6] == 0x7F && ptr[7] == 0x00 && ptr[8] == 0x80) { - static const char tracks[16] = {13,14,10,3,4,9,16,5,1,8,2,15,6,7,11,12}; - if (ptr[9] == 0x0E) - track = 18; - else - track = tracks[ptr[9] - 0x23]; - } - if (track != -1) { - playCDTrack(track,((track < 5) || (track > 16)) ? 1 : -1,0,0); - stopCDTimer(); - _currentCDSound = soundID; - } - return; - } - // Works around the fact that in some places in MonkeyEGA/VGA, // the music is never explicitly stopped. // Rather it seems that starting a new music is supposed to |