diff options
Diffstat (limited to 'engines')
33 files changed, 384 insertions, 759 deletions
diff --git a/engines/agi/sound_midi.cpp b/engines/agi/sound_midi.cpp index 2c6a189fbd..ff23a70808 100644 --- a/engines/agi/sound_midi.cpp +++ b/engines/agi/sound_midi.cpp @@ -90,24 +90,11 @@ SoundGenMIDI::SoundGenMIDI(AgiEngine *vm, Audio::Mixer *pMixer) : SoundGen(vm, p else _driver->sendGMReset(); - _driver->setTimerCallback(this, &onTimer); + // FIXME: We need to cast "this" here due to the effects of + // multiple inheritance. This hack can go away once this + // setTimerCallback() has been moved inside Audio::MidiPlayer code. + _driver->setTimerCallback(static_cast<Audio::MidiPlayer *>(this), &timerCallback); } - - _smfParser = MidiParser::createParser_SMF(); - _midiMusicData = NULL; -} - -SoundGenMIDI::~SoundGenMIDI() { - _driver->setTimerCallback(NULL, NULL); - stop(); - if (_driver) { - _driver->close(); - delete _driver; - _driver = 0; - } - _smfParser->setMidiDriver(NULL); - delete _smfParser; - delete[] _midiMusicData; } void SoundGenMIDI::send(uint32 b) { @@ -136,14 +123,6 @@ void SoundGenMIDI::endOfTrack() { _vm->_sound->soundIsFinished(); } -void SoundGenMIDI::onTimer(void *refCon) { - SoundGenMIDI *music = (SoundGenMIDI *)refCon; - Common::StackLock lock(music->_mutex); - - if (music->_parser) - music->_parser->onTimer(); -} - void SoundGenMIDI::play(int resnum) { MIDISound *track; @@ -154,10 +133,10 @@ void SoundGenMIDI::play(int resnum) { track = (MIDISound *)_vm->_game.sounds[resnum]; // Convert AGI Sound data to MIDI - int midiMusicSize = convertSND2MIDI(track->_data, &_midiMusicData); + int midiMusicSize = convertSND2MIDI(track->_data, &_midiData); - if (_smfParser->loadMusic(_midiMusicData, midiMusicSize)) { - MidiParser *parser = _smfParser; + MidiParser *parser = MidiParser::createParser_SMF(); + if (parser->loadMusic(_midiData, midiMusicSize)) { parser->setTrack(0); parser->setMidiDriver(this); parser->setTimerRate(_driver->getBaseTempo()); @@ -168,6 +147,8 @@ void SoundGenMIDI::play(int resnum) { syncVolume(); _isPlaying = true; + } else { + delete parser; } } diff --git a/engines/agi/sound_midi.h b/engines/agi/sound_midi.h index 9551673a4e..5733358fee 100644 --- a/engines/agi/sound_midi.h +++ b/engines/agi/sound_midi.h @@ -28,6 +28,8 @@ #ifndef AGI_SOUND_MIDI_H #define AGI_SOUND_MIDI_H +#include "agi/sound.h" + #include "audio/midiplayer.h" namespace Agi { @@ -47,13 +49,12 @@ protected: class SoundGenMIDI : public SoundGen, public Audio::MidiPlayer { public: SoundGenMIDI(AgiEngine *vm, Audio::Mixer *pMixer); - ~SoundGenMIDI(); void play(int resnum); + // We must overload stop() here to implement the pure virtual + // stop() method of the SoundGen class. void stop() { Audio::MidiPlayer::stop(); } - void setGM(bool isGM) { _isGM = isGM; } - // MidiDriver_BASE interface implementation virtual void send(uint32 b); @@ -62,14 +63,8 @@ public: virtual void endOfTrack(); private: - - static void onTimer(void *data); - - MidiParser *_smfParser; bool _isGM; - byte *_midiMusicData; - SoundMgr *_manager; }; diff --git a/engines/draci/music.cpp b/engines/draci/music.cpp index 77f51544d5..242e58e92c 100644 --- a/engines/draci/music.cpp +++ b/engines/draci/music.cpp @@ -47,9 +47,6 @@ MusicPlayer::MusicPlayer(const char *pathMask) : _pathMask(pathMask), _isGM(fals if (_nativeMT32) _driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE); - _smfParser = MidiParser::createParser_SMF(); - _midiMusicData = NULL; - int ret = _driver->open(); if (ret == 0) { if (_nativeMT32) @@ -61,21 +58,8 @@ MusicPlayer::MusicPlayer(const char *pathMask) : _pathMask(pathMask), _isGM(fals // interface for such an operation is supported for AdLib. Maybe for // this card, setting instruments is necessary. - _driver->setTimerCallback(this, &onTimer); - } -} - -MusicPlayer::~MusicPlayer() { - _driver->setTimerCallback(NULL, NULL); - stop(); - if (_driver) { - _driver->close(); - delete _driver; - _driver = 0; + _driver->setTimerCallback(this, &timerCallback); } - _smfParser->setMidiDriver(NULL); - delete _smfParser; - delete[] _midiMusicData; } void MusicPlayer::sendToChannel(byte channel, uint32 b) { @@ -91,15 +75,9 @@ void MusicPlayer::sendToChannel(byte channel, uint32 b) { _channelsTable[channel]->send(b); } -void MusicPlayer::onTimer(void *refCon) { - MusicPlayer *music = (MusicPlayer *)refCon; - Common::StackLock lock(music->_mutex); - - if (music->_parser) - music->_parser->onTimer(); -} - void MusicPlayer::playSMF(int track, bool loop) { + Common::StackLock lock(_mutex); + if (_isPlaying && track == _track) { debugC(2, kDraciSoundDebugLevel, "Already plaing track %d", track); return; @@ -109,24 +87,23 @@ void MusicPlayer::playSMF(int track, bool loop) { _isGM = true; - // Load MIDI resource data Common::File musicFile; char musicFileName[40]; - sprintf(musicFileName, _pathMask.c_str(), track); + snprintf(musicFileName, sizeof(musicFileName), _pathMask.c_str(), track); musicFile.open(musicFileName); if (!musicFile.isOpen()) { debugC(2, kDraciSoundDebugLevel, "Cannot open track %d", track); return; } int midiMusicSize = musicFile.size(); - delete[] _midiMusicData; - _midiMusicData = new byte[midiMusicSize]; - musicFile.read(_midiMusicData, midiMusicSize); + free(_midiData); + _midiData = (byte *)malloc(midiMusicSize); + musicFile.read(_midiData, midiMusicSize); musicFile.close(); - if (_smfParser->loadMusic(_midiMusicData, midiMusicSize)) { - MidiParser *parser = _smfParser; + MidiParser *parser = MidiParser::createParser_SMF(); + if (parser->loadMusic(_midiData, midiMusicSize)) { parser->setTrack(0); parser->setMidiDriver(this); parser->setTimerRate(_driver->getBaseTempo()); @@ -142,6 +119,7 @@ void MusicPlayer::playSMF(int track, bool loop) { debugC(2, kDraciSoundDebugLevel, "Playing track %d", track); } else { debugC(2, kDraciSoundDebugLevel, "Cannot play track %d", track); + delete parser; } } diff --git a/engines/draci/music.h b/engines/draci/music.h index a1d0aaacb6..c0228074e5 100644 --- a/engines/draci/music.h +++ b/engines/draci/music.h @@ -37,27 +37,18 @@ namespace Draci { class MusicPlayer : public Audio::MidiPlayer { public: MusicPlayer(const char *pathMask); - ~MusicPlayer(); void playSMF(int track, bool loop); void stop(); - void setGM(bool isGM) { _isGM = isGM; } - // Overload Audio::MidiPlayer method virtual void sendToChannel(byte channel, uint32 b); protected: - - static void onTimer(void *data); - - MidiParser *_smfParser; Common::String _pathMask; bool _isGM; int _track; - - byte *_midiMusicData; }; } // End of namespace Draci diff --git a/engines/hugo/sound.cpp b/engines/hugo/sound.cpp index 04da0c89ee..24359a2c54 100644 --- a/engines/hugo/sound.cpp +++ b/engines/hugo/sound.cpp @@ -47,58 +47,46 @@ namespace Hugo { -MidiPlayer::MidiPlayer(MidiDriver *driver) - : _midiData(0) { +MidiPlayer::MidiPlayer() { + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM); + _driver = MidiDriver::createMidi(dev); assert(_driver); _paused = false; -} -MidiPlayer::~MidiPlayer() { - stop(); - Common::StackLock lock(_mutex); - _driver->setTimerCallback(0, 0); - _driver->close(); - delete _driver; - _driver = 0; - if (_parser) - _parser->setMidiDriver(0); - delete _parser; + int ret = _driver->open(); + if (ret == 0) { + _driver->sendGMReset(); + + _driver->setTimerCallback(this, &timerCallback); + } } void MidiPlayer::play(uint8 *stream, uint16 size) { debugC(3, kDebugMusic, "MidiPlayer::play"); - if (!stream) { - stop(); - return; - } + + Common::StackLock lock(_mutex); stop(); + if (!stream) + return; + _midiData = (uint8 *)malloc(size); if (_midiData) { memcpy(_midiData, stream, size); - Common::StackLock lock(_mutex); syncVolume(); // FIXME: syncVolume calls setVolume which in turn also locks the mutex! ugh + + _parser = MidiParser::createParser_SMF(); _parser->loadMusic(_midiData, size); _parser->setTrack(0); + _parser->setMidiDriver(this); + _parser->setTimerRate(_driver->getBaseTempo()); _isLooping = false; _isPlaying = true; } } -void MidiPlayer::stop() { - debugC(3, kDebugMusic, "MidiPlayer::stop"); - - Common::StackLock lock(_mutex); - if (_isPlaying) { - _isPlaying = false; - _parser->unloadMusic(); - free(_midiData); - _midiData = 0; - } -} - void MidiPlayer::pause(bool p) { _paused = p; @@ -109,34 +97,14 @@ void MidiPlayer::pause(bool p) { } } -void MidiPlayer::updateTimer() { - if (_paused) { - return; - } - +void MidiPlayer::onTimer() { Common::StackLock lock(_mutex); - if (_isPlaying) { + + if (!_paused && _isPlaying && _parser) { _parser->onTimer(); } } -int MidiPlayer::open() { - if (!_driver) - return 255; - int ret = _driver->open(); - if (ret) - return ret; - - _driver->sendGMReset(); - - _parser = MidiParser::createParser_SMF(); - _parser->setMidiDriver(this); - _parser->setTimerRate(_driver->getBaseTempo()); - _driver->setTimerCallback(this, &timerCallback); - - return 0; -} - void MidiPlayer::sendToChannel(byte channel, uint32 b) { if (!_channelsTable[channel]) { _channelsTable[channel] = (channel == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel(); @@ -151,17 +119,8 @@ void MidiPlayer::sendToChannel(byte channel, uint32 b) { } -void MidiPlayer::timerCallback(void *p) { - MidiPlayer *player = (MidiPlayer *)p; - - player->updateTimer(); -} - SoundHandler::SoundHandler(HugoEngine *vm) : _vm(vm) { - MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM); - MidiDriver *driver = MidiDriver::createMidi(dev); - - _midiPlayer = new MidiPlayer(driver); + _midiPlayer = new MidiPlayer(); _speakerStream = new Audio::PCSpeaker(_vm->_mixer->getOutputRate()); _vm->_mixer->playStream(Audio::Mixer::kSFXSoundType, &_speakerHandle, _speakerStream, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true); @@ -263,7 +222,7 @@ void SoundHandler::playSound(int16 sound, const byte priority) { * Initialize for MCI sound and midi */ void SoundHandler::initSound() { - _midiPlayer->open(); + //_midiPlayer->open(); } void SoundHandler::syncVolume() { diff --git a/engines/hugo/sound.h b/engines/hugo/sound.h index b8a7bf9678..d5f51704aa 100644 --- a/engines/hugo/sound.h +++ b/engines/hugo/sound.h @@ -41,24 +41,18 @@ namespace Hugo { class MidiPlayer : public Audio::MidiPlayer { public: - MidiPlayer(MidiDriver *driver); - ~MidiPlayer(); + MidiPlayer(); void pause(bool p); void play(uint8 *stream, uint16 size); - void stop(); - void updateTimer(); - int open(); uint32 getBaseTempo(); // Overload Audio::MidiPlayer method virtual void sendToChannel(byte channel, uint32 b); + virtual void onTimer(); private: - static void timerCallback(void *p); - - uint8 *_midiData; bool _paused; }; diff --git a/engines/m4/midi.cpp b/engines/m4/midi.cpp index b982fc8129..d58b92bf01 100644 --- a/engines/m4/midi.cpp +++ b/engines/m4/midi.cpp @@ -34,7 +34,7 @@ namespace M4 { -MidiPlayer::MidiPlayer(MadsM4Engine *vm) : _vm(vm), _midiData(NULL), _isGM(false) { +MidiPlayer::MidiPlayer(MadsM4Engine *vm) : _vm(vm), _isGM(false) { MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM); _nativeMT32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32")); @@ -44,26 +44,10 @@ MidiPlayer::MidiPlayer(MadsM4Engine *vm) : _vm(vm), _midiData(NULL), _isGM(false if (_nativeMT32) _driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE); - _parser = MidiParser::createParser_SMF(); - _parser->setMidiDriver(this); - _parser->setTimerRate(_driver->getBaseTempo()); - int ret = _driver->open(); - if (ret == 0) - _driver->setTimerCallback(this, &onTimer); -} - -MidiPlayer::~MidiPlayer() { - _driver->setTimerCallback(NULL, NULL); - _parser->setMidiDriver(NULL); - stop(); - if (_driver) { - _driver->close(); - delete _driver; + if (ret == 0) { + _driver->setTimerCallback(this, &timerCallback); } - _driver = 0; - delete _parser; - free(_midiData); } void MidiPlayer::send(uint32 b) { @@ -74,15 +58,9 @@ void MidiPlayer::send(uint32 b) { Audio::MidiPlayer::send(b); } -void MidiPlayer::onTimer(void *refCon) { - MidiPlayer *midi = (MidiPlayer *)refCon; - Common::StackLock lock(midi->_mutex); - - if (midi->_isPlaying) - midi->_parser->onTimer(); -} - void MidiPlayer::playMusic(const char *name, int32 vol, bool loop, int32 trigger, int32 scene) { + Common::StackLock lock(_mutex); + stop(); char fullname[144]; @@ -99,11 +77,10 @@ void MidiPlayer::playMusic(const char *name, int32 vol, bool loop, int32 trigger _vm->res()->purge(); if (_midiData) { - /* - FILE *out = fopen("music.mid", "wb"); - fwrite(_midiData, smfSize, 1, out); - fclose(out); - */ + _parser = MidiParser::createParser_SMF(); + _parser->setMidiDriver(this); + _parser->setTimerRate(_driver->getBaseTempo()); + _parser->loadMusic(_midiData, smfSize); _parser->property(MidiParser::mpAutoLoop, loop); } @@ -113,20 +90,6 @@ void MidiPlayer::playMusic(const char *name, int32 vol, bool loop, int32 trigger _isPlaying = true; } -void MidiPlayer::stop() { - Common::StackLock lock(_mutex); - - _isPlaying = false; - if (_parser) { - _parser->unloadMusic(); - } - - if (_midiData) { - free(_midiData); - _midiData = NULL; - } -} - // This function will convert HMP music into type 1 SMF, which our SMF parser // will be able to handle. It is based on Hans de Goede's HMP 2 MIDI file // converter, which in turn is "based on the conversion algorithms found in diff --git a/engines/m4/midi.h b/engines/m4/midi.h index e1f92cd4b6..a544fb72aa 100644 --- a/engines/m4/midi.h +++ b/engines/m4/midi.h @@ -35,10 +35,8 @@ namespace M4 { class MidiPlayer : public Audio::MidiPlayer { public: MidiPlayer(MadsM4Engine *vm); - ~MidiPlayer(); void playMusic(const char *name, int32 vol, bool loop, int32 trigger, int32 scene); - virtual void stop(); void setGM(bool isGM) { _isGM = isGM; } @@ -46,10 +44,7 @@ public: virtual void send(uint32 b); protected: - static void onTimer(void *data); - MadsM4Engine *_vm; - byte *_midiData; bool _isGM; diff --git a/engines/made/music.cpp b/engines/made/music.cpp index 054f8126d6..c8b13ba210 100644 --- a/engines/made/music.cpp +++ b/engines/made/music.cpp @@ -47,9 +47,6 @@ MusicPlayer::MusicPlayer() : _isGM(false) { if (_nativeMT32) _driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE); - _xmidiParser = MidiParser::createParser_XMIDI(); - _smfParser = MidiParser::createParser_SMF(); - int ret = _driver->open(); if (ret == 0) { if (_nativeMT32) @@ -57,22 +54,8 @@ MusicPlayer::MusicPlayer() : _isGM(false) { else _driver->sendGMReset(); - _driver->setTimerCallback(this, &onTimer); - } -} - -MusicPlayer::~MusicPlayer() { - _driver->setTimerCallback(NULL, NULL); - stop(); - if (_driver) { - _driver->close(); - delete _driver; - _driver = 0; + _driver->setTimerCallback(this, &timerCallback); } - _xmidiParser->setMidiDriver(NULL); - _smfParser->setMidiDriver(NULL); - delete _xmidiParser; - delete _smfParser; } void MusicPlayer::send(uint32 b) { @@ -83,15 +66,9 @@ void MusicPlayer::send(uint32 b) { Audio::MidiPlayer::send(b); } -void MusicPlayer::onTimer(void *refCon) { - MusicPlayer *music = (MusicPlayer *)refCon; - Common::StackLock lock(music->_mutex); - - if (music->_isPlaying) - music->_parser->onTimer(); -} - void MusicPlayer::playXMIDI(GenericResource *midiResource, MusicFlags flags) { + Common::StackLock lock(_mutex); + if (_isPlaying) return; @@ -101,8 +78,8 @@ void MusicPlayer::playXMIDI(GenericResource *midiResource, MusicFlags flags) { _isGM = true; - if (_xmidiParser->loadMusic(midiResource->getData(), midiResource->getSize())) { - MidiParser *parser = _xmidiParser; + MidiParser *parser = MidiParser::createParser_XMIDI(); + if (parser->loadMusic(midiResource->getData(), midiResource->getSize())) { parser->setTrack(0); parser->setMidiDriver(this); parser->setTimerRate(_driver->getBaseTempo()); @@ -115,10 +92,14 @@ void MusicPlayer::playXMIDI(GenericResource *midiResource, MusicFlags flags) { _isLooping = flags & MUSIC_LOOP; _isPlaying = true; + } else { + delete parser; } } void MusicPlayer::playSMF(GenericResource *midiResource, MusicFlags flags) { + Common::StackLock lock(_mutex); + if (_isPlaying) return; @@ -128,8 +109,8 @@ void MusicPlayer::playSMF(GenericResource *midiResource, MusicFlags flags) { _isGM = true; - if (_smfParser->loadMusic(midiResource->getData(), midiResource->getSize())) { - MidiParser *parser = _smfParser; + MidiParser *parser = MidiParser::createParser_SMF(); + if (parser->loadMusic(midiResource->getData(), midiResource->getSize())) { parser->setTrack(0); parser->setMidiDriver(this); parser->setTimerRate(_driver->getBaseTempo()); @@ -141,6 +122,8 @@ void MusicPlayer::playSMF(GenericResource *midiResource, MusicFlags flags) { _isLooping = flags & MUSIC_LOOP; _isPlaying = true; + } else { + delete parser; } } diff --git a/engines/made/music.h b/engines/made/music.h index 8925440b75..f8f70cdad6 100644 --- a/engines/made/music.h +++ b/engines/made/music.h @@ -44,7 +44,6 @@ enum MusicFlags { class MusicPlayer : public Audio::MidiPlayer { public: MusicPlayer(); - ~MusicPlayer(); void playXMIDI(GenericResource *midiResource, MusicFlags flags = MUSIC_NORMAL); void playSMF(GenericResource *midiResource, MusicFlags flags = MUSIC_NORMAL); @@ -52,16 +51,10 @@ public: void pause(); void resume(); - void setGM(bool isGM) { _isGM = isGM; } - // MidiDriver_BASE interface implementation virtual void send(uint32 b); protected: - - static void onTimer(void *data); - - MidiParser *_xmidiParser, *_smfParser; bool _isGM; }; diff --git a/engines/parallaction/parallaction_br.cpp b/engines/parallaction/parallaction_br.cpp index 457c421fd7..619a4f7559 100644 --- a/engines/parallaction/parallaction_br.cpp +++ b/engines/parallaction/parallaction_br.cpp @@ -61,9 +61,7 @@ Common::Error Parallaction_br::init() { _disk = new DosDisk_br(this); } _disk->setLanguage(2); // NOTE: language is now hardcoded to English. Original used command-line parameters. - MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM); - MidiDriver *driver = MidiDriver::createMidi(dev); - _soundManI = new DosSoundMan_br(this, driver); + _soundManI = new DosSoundMan_br(this); } else { _disk = new AmigaDisk_br(this); _disk->setLanguage(2); // NOTE: language is now hardcoded to English. Original used command-line parameters. diff --git a/engines/parallaction/parallaction_ns.cpp b/engines/parallaction/parallaction_ns.cpp index c3d917a33d..ffac22e118 100644 --- a/engines/parallaction/parallaction_ns.cpp +++ b/engines/parallaction/parallaction_ns.cpp @@ -166,9 +166,7 @@ Common::Error Parallaction_ns::init() { _disk->init(); if (getPlatform() == Common::kPlatformPC) { - MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM); - MidiDriver *driver = MidiDriver::createMidi(dev); - _soundManI = new DosSoundMan_ns(this, driver); + _soundManI = new DosSoundMan_ns(this); _soundManI->setMusicVolume(ConfMan.getInt("music_volume")); } else { _soundManI = new AmigaSoundMan_ns(this); diff --git a/engines/parallaction/sound.h b/engines/parallaction/sound.h index 7b3eff37cb..455189d1fc 100644 --- a/engines/parallaction/sound.h +++ b/engines/parallaction/sound.h @@ -140,7 +140,7 @@ class DosSoundMan_ns : public SoundMan_ns { public: - DosSoundMan_ns(Parallaction_ns *vm, MidiDriver *midiDriver); + DosSoundMan_ns(Parallaction_ns *vm); ~DosSoundMan_ns(); void playMusic(); void stopMusic(); @@ -228,7 +228,7 @@ class DosSoundMan_br : public SoundMan_br { Audio::AudioStream *loadChannelData(const char *filename, Channel *ch, bool looping); public: - DosSoundMan_br(Parallaction_br *vm, MidiDriver *midiDriver); + DosSoundMan_br(Parallaction_br *vm); ~DosSoundMan_br(); void playMusic(); diff --git a/engines/parallaction/sound_br.cpp b/engines/parallaction/sound_br.cpp index 1bc085fd34..ee53f9641e 100644 --- a/engines/parallaction/sound_br.cpp +++ b/engines/parallaction/sound_br.cpp @@ -204,94 +204,69 @@ MidiParser *createParser_MSC() { class MidiPlayer_MSC : public Audio::MidiPlayer { public: - MidiPlayer_MSC(MidiDriver *driver); - ~MidiPlayer_MSC(); + MidiPlayer_MSC(); void play(Common::SeekableReadStream *stream); - void stop(); - void pause(bool p); - void updateTimer(); - void setVolume(int volume); + virtual void pause(bool p); + virtual void setVolume(int volume); + virtual void onTimer(); // MidiDriver_BASE interface virtual void send(uint32 b); -private: - static void timerCallback(void *p); +private: void setVolumeInternal(int volume); - - uint8 *_midiData; bool _paused; }; -MidiPlayer_MSC::MidiPlayer_MSC(MidiDriver *driver) - : _midiData(0), _paused(false) { - _driver = driver; +MidiPlayer_MSC::MidiPlayer_MSC() + : _paused(false) { + + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM); + _driver = MidiDriver::createMidi(dev); assert(_driver); int ret = _driver->open(); if (ret == 0) { - _parser = createParser_MSC(); - _parser->setMidiDriver(this); - _parser->setTimerRate(_driver->getBaseTempo()); _driver->setTimerCallback(this, &timerCallback); } } -MidiPlayer_MSC::~MidiPlayer_MSC() { - stop(); - +void MidiPlayer_MSC::play(Common::SeekableReadStream *stream) { Common::StackLock lock(_mutex); - _driver->setTimerCallback(NULL, NULL); - _driver->close(); - delete _driver; - _driver = 0; - _parser->setMidiDriver(NULL); - delete _parser; -} -void MidiPlayer_MSC::play(Common::SeekableReadStream *stream) { - if (!stream) { - stop(); + stop(); + if (!stream) return; - } - stop(); int size = stream->size(); _midiData = (uint8 *)malloc(size); if (_midiData) { stream->read(_midiData, size); delete stream; - Common::StackLock lock(_mutex); + _parser = createParser_MSC(); _parser->loadMusic(_midiData, size); _parser->setTrack(0); + _parser->setMidiDriver(this); + _parser->setTimerRate(_driver->getBaseTempo()); _isLooping = true; _isPlaying = true; } } -void MidiPlayer_MSC::stop() { - Audio::MidiPlayer::stop(); - free(_midiData); - _midiData = 0; -} - void MidiPlayer_MSC::pause(bool p) { _paused = p; setVolumeInternal(_paused ? 0 : _masterVolume); } -void MidiPlayer_MSC::updateTimer() { - if (_paused) { - return; - } - +void MidiPlayer_MSC::onTimer() { Common::StackLock lock(_mutex); - if (_isPlaying) { + + if (!_paused && _isPlaying && _parser) { _parser->onTimer(); } } @@ -327,14 +302,8 @@ void MidiPlayer_MSC::send(uint32 b) { sendToChannel(ch, b); } -void MidiPlayer_MSC::timerCallback(void *p) { - MidiPlayer_MSC *player = (MidiPlayer_MSC *)p; - - player->updateTimer(); -} - -DosSoundMan_br::DosSoundMan_br(Parallaction_br *vm, MidiDriver *driver) : SoundMan_br(vm) { - _midiPlayer = new MidiPlayer_MSC(driver); +DosSoundMan_br::DosSoundMan_br(Parallaction_br *vm) : SoundMan_br(vm) { + _midiPlayer = new MidiPlayer_MSC(); assert(_midiPlayer); } diff --git a/engines/parallaction/sound_ns.cpp b/engines/parallaction/sound_ns.cpp index 8f3f0c39e6..ba81314da6 100644 --- a/engines/parallaction/sound_ns.cpp +++ b/engines/parallaction/sound_ns.cpp @@ -42,74 +42,52 @@ namespace Parallaction { class MidiPlayer : public Audio::MidiPlayer { public: - MidiPlayer(MidiDriver *driver); - ~MidiPlayer(); + MidiPlayer(); void play(Common::SeekableReadStream *stream); - void stop(); void pause(bool p); - void updateTimer(); + virtual void onTimer(); private: - static void timerCallback(void *p); - - uint8 *_midiData; bool _paused; }; -MidiPlayer::MidiPlayer(MidiDriver *driver) - : _midiData(0), _paused(false) { - assert(driver); - _driver = driver; +MidiPlayer::MidiPlayer() + : _paused(false) { + + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM); + _driver = MidiDriver::createMidi(dev); + assert(_driver); int ret = _driver->open(); if (ret == 0) { - _parser = MidiParser::createParser_SMF(); - _parser->setMidiDriver(this); - _parser->setTimerRate(_driver->getBaseTempo()); _driver->setTimerCallback(this, &timerCallback); } } -MidiPlayer::~MidiPlayer() { - stop(); - +void MidiPlayer::play(Common::SeekableReadStream *stream) { Common::StackLock lock(_mutex); - _driver->setTimerCallback(NULL, NULL); - _driver->close(); - delete _driver; - _driver = 0; - _parser->setMidiDriver(NULL); - delete _parser; -} -void MidiPlayer::play(Common::SeekableReadStream *stream) { - if (!stream) { - stop(); + stop(); + if (!stream) return; - } int size = stream->size(); - _midiData = (uint8 *)malloc(size); if (_midiData) { stream->read(_midiData, size); delete stream; - Common::StackLock lock(_mutex); + _parser = MidiParser::createParser_SMF(); _parser->loadMusic(_midiData, size); _parser->setTrack(0); + _parser->setMidiDriver(this); + _parser->setTimerRate(_driver->getBaseTempo()); _isLooping = true; _isPlaying = true; } } -void MidiPlayer::stop() { - Audio::MidiPlayer::stop(); - free(_midiData); - _midiData = 0; -} - void MidiPlayer::pause(bool p) { _paused = p; @@ -120,25 +98,16 @@ void MidiPlayer::pause(bool p) { } } -void MidiPlayer::updateTimer() { - if (_paused) { - return; - } - +void MidiPlayer::onTimer() { Common::StackLock lock(_mutex); - if (_isPlaying) { + + if (!_paused && _isPlaying && _parser) { _parser->onTimer(); } } -void MidiPlayer::timerCallback(void *p) { - MidiPlayer *player = (MidiPlayer *)p; - - player->updateTimer(); -} - -DosSoundMan_ns::DosSoundMan_ns(Parallaction_ns *vm, MidiDriver *midiDriver) : SoundMan_ns(vm), _playing(false) { - _midiPlayer = new MidiPlayer(midiDriver); +DosSoundMan_ns::DosSoundMan_ns(Parallaction_ns *vm) : SoundMan_ns(vm), _playing(false) { + _midiPlayer = new MidiPlayer(); } DosSoundMan_ns::~DosSoundMan_ns() { diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 93d21c32e0..e2e5ee9682 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -3154,10 +3154,9 @@ bool Console::cmdBreakpointKernel(int argc, const char **argv) { } bool Console::cmdBreakpointFunction(int argc, const char **argv) { - // TODO/FIXME: Why does this accept 2 parameters (the high and the low part of the address)?" if (argc != 3) { DebugPrintf("Sets a breakpoint on the execution of the specified exported function.\n"); - DebugPrintf("Usage: %s <addr1> <addr2>\n", argv[0]); + DebugPrintf("Usage: %s <script number> <export number\n", argv[0]); return true; } @@ -3166,6 +3165,7 @@ bool Console::cmdBreakpointFunction(int argc, const char **argv) { A breakpoint set on an invalid method name will just never trigger. */ Breakpoint bp; bp.type = BREAK_EXPORT; + // script number, export number bp.address = (atoi(argv[1]) << 16 | atoi(argv[2])); _debugState._breakpoints.push_back(bp); diff --git a/engines/sci/debug.h b/engines/sci/debug.h index d9959f0b7f..8ddbbd0d45 100644 --- a/engines/sci/debug.h +++ b/engines/sci/debug.h @@ -34,18 +34,18 @@ namespace Sci { // These types are used both as identifiers and as elements of bitfields enum BreakpointType { /** - * Break when selector is executed. data contains (char *) selector name + * Break when a selector is executed. Data contains (char *) selector name * (in the format Object::Method) */ - BREAK_SELECTOREXEC = 1 << 0, // break when selector gets executed - BREAK_SELECTORREAD = 1 << 1, // break when selector gets executed - BREAK_SELECTORWRITE = 1 << 2, // break when selector gets executed + BREAK_SELECTOREXEC = 1 << 0, // break when a function selector is executed + BREAK_SELECTORREAD = 1 << 1, // break when a variable selector is read + BREAK_SELECTORWRITE = 1 << 2, // break when a variable selector is written /** - * Break when an exported function is called. data contains + * Break when an exported function is called. Data contains * script_no << 16 | export_no. */ - BREAK_EXPORT = 1 << 3 + BREAK_EXPORT = 1 << 3 }; struct Breakpoint { diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 24f3c96f62..7e75dbf000 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -270,26 +270,6 @@ static void validate_write_var(reg_t *r, reg_t *stack_base, int type, int max, i #define PUSH32(a) (*(validate_stack_addr(s, (s->xs->sp)++)) = (a)) #define POP32() (*(validate_stack_addr(s, --(s->xs->sp)))) -bool SciEngine::checkExportBreakpoint(uint16 script, uint16 pubfunct) { - if (_debugState._activeBreakpointTypes & BREAK_EXPORT) { - uint32 bpaddress; - - bpaddress = (script << 16 | pubfunct); - - Common::List<Breakpoint>::const_iterator bp; - for (bp = _debugState._breakpoints.begin(); bp != _debugState._breakpoints.end(); ++bp) { - if (bp->type == BREAK_EXPORT && bp->address == bpaddress) { - _console->DebugPrintf("Break on script %d, export %d\n", script, pubfunct); - _debugState.debugging = true; - _debugState.breakpointWasHit = true; - return true; - } - } - } - - return false; -} - ExecStack *execute_method(EngineState *s, uint16 script, uint16 pubfunct, StackPtr sp, reg_t calling_obj, uint16 argc, StackPtr argp) { int seg = s->_segMan->getScriptSegment(script); Script *scr = s->_segMan->getScriptIfLoaded(seg); @@ -322,6 +302,111 @@ ExecStack *execute_method(EngineState *s, uint16 script, uint16 pubfunct, StackP return add_exec_stack_entry(s->_executionStack, make_reg(seg, temp), sp, calling_obj, argc, argp, -1, pubfunct, -1, calling_obj, s->_executionStack.size()-1, seg); } +bool SciEngine::checkSelectorBreakpoint(BreakpointType breakpointType, reg_t send_obj, int selector) { + Common::String methodName = _gamestate->_segMan->getObjectName(send_obj); + methodName += ("::" + getKernel()->getSelectorName(selector)); + + Common::List<Breakpoint>::const_iterator bpIter; + for (bpIter = _debugState._breakpoints.begin(); bpIter != _debugState._breakpoints.end(); ++bpIter) { + if ((*bpIter).type == breakpointType && (*bpIter).name == methodName) { + _console->DebugPrintf("Break on %s (in [%04x:%04x])\n", methodName.c_str(), PRINT_REG(send_obj)); + _debugState.debugging = true; + _debugState.breakpointWasHit = true; + return true; + } + } + return false; +} + +bool SciEngine::checkExportBreakpoint(uint16 script, uint16 pubfunct) { + if (_debugState._activeBreakpointTypes & BREAK_EXPORT) { + uint32 bpaddress = (script << 16 | pubfunct); + + Common::List<Breakpoint>::const_iterator bp; + for (bp = _debugState._breakpoints.begin(); bp != _debugState._breakpoints.end(); ++bp) { + if (bp->type == BREAK_EXPORT && bp->address == bpaddress) { + _console->DebugPrintf("Break on script %d, export %d\n", script, pubfunct); + _debugState.debugging = true; + _debugState.breakpointWasHit = true; + return true; + } + } + } + + return false; +} + +void debugSelectorCall(reg_t send_obj, Selector selector, int argc, StackPtr argp, ObjVarRef &varp, reg_t funcp, SegManager *segMan, SelectorType selectorType) { + int activeBreakpointTypes = g_sci->_debugState._activeBreakpointTypes; + const char *objectName = segMan->getObjectName(send_obj); + const char *selectorName = g_sci->getKernel()->getSelectorName(selector).c_str(); + Console *con = g_sci->getSciDebugger(); + +#ifdef VM_DEBUG_SEND + debugN("Send to %04x:%04x (%s), selector %04x (%s):", PRINT_REG(send_obj), + s->_segMan->getObjectName(send_obj), selector, + g_sci->getKernel()->getSelectorName(selector).c_str()); +#endif // VM_DEBUG_SEND + + switch (selectorType) { + case kSelectorNone: + break; + case kSelectorVariable: +#ifdef VM_DEBUG_SEND + if (argc) + debugN("Varselector: Write %04x:%04x\n", PRINT_REG(argp[1])); + else + debugN("Varselector: Read\n"); +#endif // VM_DEBUG_SEND + + // argc == 0: read selector + // argc == 1: write selector + // argc can be bigger than 1 in some cases, because of a script bug. + // Usually, these aren't fatal. + if ((activeBreakpointTypes & BREAK_SELECTORREAD) || + (activeBreakpointTypes & BREAK_SELECTORWRITE) || + argc > 1) { + + reg_t selectorValue = *varp.getPointer(segMan); + if (!argc && (activeBreakpointTypes & BREAK_SELECTORREAD)) { + if (g_sci->checkSelectorBreakpoint(BREAK_SELECTORREAD, send_obj, selector)) + con->DebugPrintf("Read from selector (%s:%s): %04x:%04x\n", + objectName, selectorName, + PRINT_REG(selectorValue)); + } else if (argc && (activeBreakpointTypes & BREAK_SELECTORWRITE)) { + if (g_sci->checkSelectorBreakpoint(BREAK_SELECTORWRITE, send_obj, selector)) + con->DebugPrintf("Write to selector (%s:%s): change %04x:%04x to %04x:%04x\n", + objectName, selectorName, + PRINT_REG(selectorValue), PRINT_REG(argp[1])); + } + + if (argc > 1) + debug(kDebugLevelScripts, "Write to selector (%s:%s): change %04x:%04x to %04x:%04x, argc == %d\n", + objectName, selectorName, + PRINT_REG(selectorValue), PRINT_REG(argp[1]), argc); + } + break; + case kSelectorMethod: +#ifndef VM_DEBUG_SEND + if (activeBreakpointTypes & BREAK_SELECTOREXEC) { + if (g_sci->checkSelectorBreakpoint(BREAK_SELECTOREXEC, send_obj, selector)) { +#else + if (true) { + if (true) { +#endif + con->DebugPrintf("%s::%s(", objectName, selectorName); + for (int i = 0; i < argc; i++) { + con->DebugPrintf("%04x:%04x", PRINT_REG(argp[i+1])); + if (i + 1 < argc) + con->DebugPrintf(", "); + } + con->DebugPrintf(") at %04x:%04x\n", PRINT_REG(funcp)); + } + } + break; + } // switch +} + static void _exec_varselectors(EngineState *s) { // Executes all varselector read/write ops on the TOS @@ -357,38 +442,21 @@ struct CallsStruct { int type; /**< Same as ExecStack.type */ }; -bool SciEngine::checkSelectorBreakpoint(BreakpointType breakpointType, reg_t send_obj, int selector) { - Common::String methodName = _gamestate->_segMan->getObjectName(send_obj); - methodName += ("::" + getKernel()->getSelectorName(selector)); - - Common::List<Breakpoint>::const_iterator bpIter; - for (bpIter = _debugState._breakpoints.begin(); bpIter != _debugState._breakpoints.end(); ++bpIter) { - if ((*bpIter).type == breakpointType && (*bpIter).name == methodName) { - _console->DebugPrintf("Break on %s (in [%04x:%04x])\n", methodName.c_str(), PRINT_REG(send_obj)); - _debugState.debugging = true; - _debugState.breakpointWasHit = true; - return true; - } - } - return false; -} - ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPtr sp, int framesize, StackPtr argp) { -// send_obj and work_obj are equal for anything but 'super' -// Returns a pointer to the TOS exec_stack element + // send_obj and work_obj are equal for anything but 'super' + // Returns a pointer to the TOS exec_stack element assert(s); reg_t funcp; - int selector; + Selector selector; int argc; - int origin = s->_executionStack.size()-1; // Origin: Used for debugging + int origin = s->_executionStack.size() - 1; // Origin: Used for debugging + int activeBreakpointTypes = g_sci->_debugState._activeBreakpointTypes; // We return a pointer to the new active ExecStack // The selector calls we catch are stored below: Common::Stack<CallsStruct> sendCalls; - int activeBreakpointTypes = g_sci->_debugState._activeBreakpointTypes; - while (framesize > 0) { selector = argp->requireUint16(); argp++; @@ -397,145 +465,49 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt if (argc > 0x800) // More arguments than the stack could possibly accomodate for error("send_selector(): More than 0x800 arguments to function call"); -#ifdef VM_DEBUG_SEND - debugN("Send to %04x:%04x (%s), selector %04x (%s):", PRINT_REG(send_obj), - s->_segMan->getObjectName(send_obj), selector, - g_sci->getKernel()->getSelectorName(selector).c_str()); -#endif // VM_DEBUG_SEND - ObjVarRef varp; - switch (lookupSelector(s->_segMan, send_obj, selector, &varp, &funcp)) { + CallsStruct call; + call.argp = argp; + call.argc = argc; + call.selector = selector; + SelectorType selectorType = lookupSelector(s->_segMan, send_obj, selector, &varp, &funcp); + if (activeBreakpointTypes || DebugMan.isDebugChannelEnabled(kDebugLevelScripts)) + debugSelectorCall(send_obj, selector, argc, argp, varp, funcp, s->_segMan, selectorType); + + switch (selectorType) { case kSelectorNone: error("Send to invalid selector 0x%x of object at %04x:%04x", 0xffff & selector, PRINT_REG(send_obj)); break; - case kSelectorVariable: - -#ifdef VM_DEBUG_SEND - if (argc) - debugN("Varselector: Write %04x:%04x\n", PRINT_REG(argp[1])); - else - debugN("Varselector: Read\n"); -#endif // VM_DEBUG_SEND - - // argc == 0: read selector - // argc != 0: write selector - if (!argc) { - // read selector - if (activeBreakpointTypes & BREAK_SELECTORREAD) { - if (g_sci->checkSelectorBreakpoint(BREAK_SELECTORREAD, send_obj, selector)) - debug("[read selector]\n"); - } - } else { - // write selector - if (activeBreakpointTypes & BREAK_SELECTORWRITE) { - if (g_sci->checkSelectorBreakpoint(BREAK_SELECTORWRITE, send_obj, selector)) { - reg_t oldReg = *varp.getPointer(s->_segMan); - reg_t newReg = argp[1]; - warning("[write to selector (%s:%s): change %04x:%04x to %04x:%04x]\n", - s->_segMan->getObjectName(send_obj), g_sci->getKernel()->getSelectorName(selector).c_str(), - PRINT_REG(oldReg), PRINT_REG(newReg)); - } - } - } - - if (argc > 1) { - // argc can indeed be bigger than 1 in some cases, and it's usually the - // result of a script bug. Usually these aren't fatal. - - const char *objectName = s->_segMan->getObjectName(send_obj); - - reg_t oldReg = *varp.getPointer(s->_segMan); - reg_t newReg = argp[1]; - const char *selectorName = g_sci->getKernel()->getSelectorName(selector).c_str(); - debug(2, "send_selector(): argc = %d while modifying variable selector " - "%x (%s) of object %04x:%04x (%s) from %04x:%04x to %04x:%04x", - argc, selector, selectorName, PRINT_REG(send_obj), - objectName, PRINT_REG(oldReg), PRINT_REG(newReg)); - } - - { - CallsStruct call; - call.address.var = varp; // register the call - call.argp = argp; - call.argc = argc; - call.selector = selector; - call.type = EXEC_STACK_TYPE_VARSELECTOR; // Register as a varselector - sendCalls.push(call); - } - + call.address.var = varp; // register the call + call.type = EXEC_STACK_TYPE_VARSELECTOR; // Register as a varselector break; - case kSelectorMethod: - -#ifndef VM_DEBUG_SEND - if (activeBreakpointTypes & BREAK_SELECTOREXEC) { - if (g_sci->checkSelectorBreakpoint(BREAK_SELECTOREXEC, send_obj, selector)) { - debugN("[execute selector]"); - - int displaySize = 0; - for (int argNr = 1; argNr <= argc; argNr++) { - if (argNr == 1) - debugN(" - "); - reg_t curParam = argp[argNr]; - if (curParam.isPointer()) { - debugN("[%04x:%04x] ", PRINT_REG(curParam)); - displaySize += 12; - } else { - debugN("[%04x] ", curParam.offset); - displaySize += 7; - } - if (displaySize > 50) { - if (argNr < argc) - debugN("..."); - break; - } - } - debugN("\n"); - } - } -#else // VM_DEBUG_SEND - if (activeBreakpointTypes & BREAK_SELECTOREXEC) - g_sci->checkSelectorBreakpoint(BREAK_SELECTOREXEC, send_obj, selector); - debugN("Funcselector("); - for (int i = 0; i < argc; i++) { - debugN("%04x:%04x", PRINT_REG(argp[i+1])); - if (i + 1 < argc) - debugN(", "); - } - debugN(") at %04x:%04x\n", PRINT_REG(funcp)); -#endif // VM_DEBUG_SEND - - { - CallsStruct call; - call.address.func = funcp; // register call - call.argp = argp; - call.argc = argc; - call.selector = selector; - call.type = EXEC_STACK_TYPE_CALL; - call.sp = sp; - sp = CALL_SP_CARRY; // Destroy sp, as it will be carried over - sendCalls.push(call); - } - + call.address.func = funcp; // register call + call.type = EXEC_STACK_TYPE_CALL; + call.sp = sp; + sp = CALL_SP_CARRY; // Destroy sp, as it will be carried over break; } // switch (lookupSelector()) + sendCalls.push(call); + framesize -= (2 + argc); argp += argc + 1; - } + } // while (framesize > 0) // Iterate over all registered calls in the reverse order. This way, the first call is // placed on the TOS; as soon as it returns, it will cause the second call to be executed. while (!sendCalls.empty()) { CallsStruct call = sendCalls.pop(); if (call.type == EXEC_STACK_TYPE_VARSELECTOR) // Write/read variable? - add_exec_stack_varselector(s->_executionStack, work_obj, call.argc, call.argp, - call.selector, call.address.var, origin); - else + add_exec_stack_varselector(s->_executionStack, work_obj, + call.argc, call.argp, call.selector, + call.address.var, origin); + else // Invoke function add_exec_stack_entry(s->_executionStack, call.address.func, call.sp, work_obj, - call.argc, call.argp, - call.selector, -1, -1, send_obj, origin, SCI_XS_CALLEE_LOCALS); + call.argc, call.argp, call.selector, + -1, -1, send_obj, origin, SCI_XS_CALLEE_LOCALS); } _exec_varselectors(s); diff --git a/engines/sci/engine/workarounds.cpp b/engines/sci/engine/workarounds.cpp index 17c9f9fa0f..bd93f602f8 100644 --- a/engines/sci/engine/workarounds.cpp +++ b/engines/sci/engine/workarounds.cpp @@ -90,7 +90,7 @@ const SciWorkaroundEntry uninitializedReadWorkarounds[] = { { GID_KQ6, 520, 520, 0, "rm520", "init", -1, 0, { WORKAROUND_FAKE, 0 } }, // going to boiling water trap on beast isle { GID_KQ6, -1, 903, 0, "controlWin", "open", -1, 4, { WORKAROUND_FAKE, 0 } }, // when opening the controls window (save, load etc) { GID_KQ6, -1, 907, 0, "tomato", "doVerb", -1, 2, { WORKAROUND_FAKE, 0 } }, // when looking at the rotten tomato in the inventory - bug #3059544 - { GID_KQ7, 30, 64996, 0, "User", "handleEvent", -1, 1, { WORKAROUND_FAKE, 0 } }, // called when pushing a keyboard key + { GID_KQ7, -1, 64996, 0, "User", "handleEvent", -1, 1, { WORKAROUND_FAKE, 0 } }, // called when pushing a keyboard key { GID_LAURABOW, 37, 0, 0, "CB1", "doit", -1, 1, { WORKAROUND_FAKE, 0 } }, // when going up the stairs (bug #3037694) { GID_LAURABOW, -1, 967, 0, "myIcon", "cycle", -1, 1, { WORKAROUND_FAKE, 0 } }, // having any portrait conversation coming up (initial bug #3034985) { GID_LAURABOW2, -1, 24, 0, "gcWin", "open", -1, 5, { WORKAROUND_FAKE, 0xf } }, // is used as priority for game menu diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index fbfd140e6b..e68f964dab 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -123,7 +123,10 @@ void GfxFrameout::kernelUpdatePlane(reg_t object) { if (it->planeRect.left < 0) { it->planeOffsetX = -it->planeRect.left; it->planeRect.left = 0; + } else { + it->planeOffsetX = 0; } + if (it->planeRect.top < 0) it->planeRect.top = 0; // We get bad plane-bottom in sq6 diff --git a/engines/sci/graphics/screen.cpp b/engines/sci/graphics/screen.cpp index 89463badd0..d544dad26f 100644 --- a/engines/sci/graphics/screen.cpp +++ b/engines/sci/graphics/screen.cpp @@ -156,12 +156,14 @@ void GfxScreen::copyToScreen() { } void GfxScreen::copyFromScreen(byte *buffer) { + // TODO this ignores the pitch Graphics::Surface *screen = g_system->lockScreen(); memcpy(buffer, screen->pixels, _displayPixels); g_system->unlockScreen(); } void GfxScreen::kernelSyncWithFramebuffer() { + // TODO this ignores the pitch Graphics::Surface *screen = g_system->lockScreen(); memcpy(_displayScreen, screen->pixels, _displayPixels); g_system->unlockScreen(); diff --git a/engines/sword25/gfx/image/pngloader.cpp b/engines/sword25/gfx/image/pngloader.cpp index e2a8510c32..f6c00b6968 100644 --- a/engines/sword25/gfx/image/pngloader.cpp +++ b/engines/sword25/gfx/image/pngloader.cpp @@ -218,7 +218,7 @@ bool PNGLoader::doDecodeImage(const byte *fileDataPtr, uint fileSize, byte *&unc Common::MemoryReadStream *fileStr = new Common::MemoryReadStream(fileDataPtr, fileSize, DisposeAfterUse::NO); Graphics::PNG *png = new Graphics::PNG(); if (!png->read(fileStr)) // the fileStr pointer, and thus pFileData will be deleted after this is done - error("Error while reading PNG image"); + error("Error while reading PNG image"); Graphics::PixelFormat format = Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24); Graphics::Surface *pngSurface = png->getSurface(format); diff --git a/engines/sword25/gfx/image/renderedimage.cpp b/engines/sword25/gfx/image/renderedimage.cpp index 0d2ffb5aee..ced3296e57 100644 --- a/engines/sword25/gfx/image/renderedimage.cpp +++ b/engines/sword25/gfx/image/renderedimage.cpp @@ -59,7 +59,7 @@ RenderedImage::RenderedImage(const Common::String &filename, bool &result) : _backSurface = Kernel::getInstance()->getGfx()->getSurface(); - // Datei laden + // Load file byte *pFileData; uint fileSize; pFileData = pPackage->getFile(filename, &fileSize); @@ -68,7 +68,7 @@ RenderedImage::RenderedImage(const Common::String &filename, bool &result) : return; } - // Bildeigenschaften bestimmen + // Determine image properties int pitch; if (!PNGLoader::imageProperties(pFileData, fileSize, _width, _height)) { error("Could not read image properties."); @@ -76,14 +76,14 @@ RenderedImage::RenderedImage(const Common::String &filename, bool &result) : return; } - // Das Bild dekomprimieren + // Uncompress the image if (!PNGLoader::decodeImage(pFileData, fileSize, _data, _width, _height, pitch)) { error("Could not decode image."); delete[] pFileData; return; } - // Dateidaten freigeben + // Cleanup FileData delete[] pFileData; _doCleanup = true; @@ -134,7 +134,7 @@ bool RenderedImage::fill(const Common::Rect *pFillRect, uint color) { // ----------------------------------------------------------------------------- bool RenderedImage::setContent(const byte *pixeldata, uint size, uint offset, uint stride) { - // Überprüfen, ob PixelData ausreichend viele Pixel enthält um ein Bild der Größe Width * Height zu erzeugen + // Check if PixelData contains enough pixel to create an image with image size equals width * height if (size < static_cast<uint>(_width * _height * 4)) { error("PixelData vector is too small to define a 32 bit %dx%d image.", _width, _height); return false; @@ -198,11 +198,11 @@ bool RenderedImage::blit(int posX, int posY, int flipping, Common::Rect *pPartRe srcImage.w = pPartRect->right - pPartRect->left; srcImage.h = pPartRect->bottom - pPartRect->top; - debug(6, "Blit(%d, %d, %d, [%d, %d, %d, %d], %08x, %d, %d)", posX, posY, flipping, + debug(6, "Blit(%d, %d, %d, [%d, %d, %d, %d], %08x, %d, %d)", posX, posY, flipping, pPartRect->left, pPartRect->top, pPartRect->width(), pPartRect->height(), color, width, height); } else { - debug(6, "Blit(%d, %d, %d, [%d, %d, %d, %d], %08x, %d, %d)", posX, posY, flipping, 0, 0, + debug(6, "Blit(%d, %d, %d, [%d, %d, %d, %d], %08x, %d, %d)", posX, posY, flipping, 0, 0, srcImage.w, srcImage.h, color, width, height); } @@ -324,7 +324,7 @@ bool RenderedImage::blit(int posX, int posY, int flipping, Common::Rect *pPartRe ino += inoStep; } - g_system->copyRectToScreen((byte *)_backSurface->getBasePtr(posX, posY), _backSurface->pitch, posX, posY, + g_system->copyRectToScreen((byte *)_backSurface->getBasePtr(posX, posY), _backSurface->pitch, posX, posY, img->w, img->h); } @@ -413,7 +413,7 @@ int *RenderedImage::scaleLine(int size, int srcSize) { distCtr -= 100; } } - + return v; } diff --git a/engines/sword25/gfx/image/renderedimage.h b/engines/sword25/gfx/image/renderedimage.h index 0375c7acbe..e3f23747da 100644 --- a/engines/sword25/gfx/image/renderedimage.h +++ b/engines/sword25/gfx/image/renderedimage.h @@ -50,12 +50,12 @@ public: RenderedImage(const Common::String &filename, bool &result); /** - @brief Erzeugt ein leeres BS_RenderedImage + @brief Creates an empty BS_RenderedImage - @param Width die Breite des zu erzeugenden Bildes. - @param Height die Höhe des zu erzeugenden Bildes - @param Result gibt dem Aufrufer bekannt, ob der Konstruktor erfolgreich ausgeführt wurde. Wenn es nach dem Aufruf false enthalten sollte, - dürfen keine Methoden am Objekt aufgerufen werden und das Objekt ist sofort zu zerstören. + @param Width The width of the image to be created. + @param Height The height of the image to be created + @param Result Informs the caller, whether the constructor is executed successfully. If it contains false + after the call, do not call methods on the object and destroy the object immediately. */ RenderedImage(uint width, uint height, bool &result); RenderedImage(); @@ -84,25 +84,25 @@ public: void replaceContent(byte *pixeldata, int width, int height); virtual uint getPixel(int x, int y); - virtual bool isBlitSource() const { + virtual bool isBlitSource() const { return true; } - virtual bool isBlitTarget() const { + virtual bool isBlitTarget() const { return false; } - virtual bool isScalingAllowed() const { + virtual bool isScalingAllowed() const { return true; } - virtual bool isFillingAllowed() const { + virtual bool isFillingAllowed() const { return false; } - virtual bool isAlphaAllowed() const { + virtual bool isAlphaAllowed() const { return true; } - virtual bool isColorModulationAllowed() const { + virtual bool isColorModulationAllowed() const { return true; } - virtual bool isSetContentAllowed() const { + virtual bool isSetContentAllowed() const { return true; } diff --git a/engines/sword25/gfx/image/swimage.cpp b/engines/sword25/gfx/image/swimage.cpp index ff06491b36..3b9b939eb3 100644 --- a/engines/sword25/gfx/image/swimage.cpp +++ b/engines/sword25/gfx/image/swimage.cpp @@ -47,7 +47,7 @@ SWImage::SWImage(const Common::String &filename, bool &result) : PackageManager *pPackage = Kernel::getInstance()->getPackage(); assert(pPackage); - // Datei laden + // Load file byte *pFileData; uint fileSize; pFileData = pPackage->getFile(filename, &fileSize); @@ -56,21 +56,21 @@ SWImage::SWImage(const Common::String &filename, bool &result) : return; } - // Bildeigenschaften bestimmen + // Determine image properties int pitch; if (!PNGLoader::imageProperties(pFileData, fileSize, _width, _height)) { error("Could not read image properties."); return; } - // Das Bild dekomprimieren + // Uncompress the image byte *pUncompressedData; if (!PNGLoader::decodeImage(pFileData, fileSize, pUncompressedData, _width, _height, pitch)) { error("Could not decode image."); return; } - // Dateidaten freigeben + // Cleanup FileData delete[] pFileData; _imageDataPtr = (uint *)pUncompressedData; diff --git a/engines/sword25/gfx/image/vectorimage.cpp b/engines/sword25/gfx/image/vectorimage.cpp index 094e6a59a8..241e80bad3 100644 --- a/engines/sword25/gfx/image/vectorimage.cpp +++ b/engines/sword25/gfx/image/vectorimage.cpp @@ -47,15 +47,15 @@ namespace Sword25 { #define BEZSMOOTHNESS 0.5 // ----------------------------------------------------------------------------- -// SWF Datentypen +// SWF datatype // ----------------------------------------------------------------------------- // ----------------------------------------------------------------------------- -// Bitstream Hilfsklasse +// Bitstream helper class // ----------------------------------------------------------------------------- -// Das Parsen von SWF-Dateien erfordert sowohl bitweises Auslesen als auch an -// Bytegrenzen ausgerichtetes Lesen. -// Diese Klasse ist speziell dafür ausgestattet. +// The parsing of SWF files requires both bitwise readout and on Byte boundaries +// oriented reading. +// This class is specially equipped for this. // ----------------------------------------------------------------------------- class VectorImage::SWFBitStream { @@ -85,10 +85,10 @@ public: } inline int32 getSignedBits(uint bitCount) { - // Bits einlesen + // readout bits uint32 temp = getBits(bitCount); - // Falls das Sign-Bit gesetzt ist, den Rest des Rückgabewertes mit 1-Bits auffüllen (Sign Extension) + // If the sign-bit is set, fill the rest of the return value with 1-bit (sign extension) if (temp & 1 << (bitCount - 1)) return (0xffffffff << bitCount) | temp; else @@ -151,28 +151,28 @@ private: // ----------------------------------------------------------------------------- -// Konstanten und Hilfsfunktionen +// Constants and utility functions // ----------------------------------------------------------------------------- namespace { // ----------------------------------------------------------------------------- -// Konstanten +// Constants // ----------------------------------------------------------------------------- -const uint32 MAX_ACCEPTED_FLASH_VERSION = 3; // Die höchste Flash-Dateiversion, die vom Lader akzeptiert wird +const uint32 MAX_ACCEPTED_FLASH_VERSION = 3; // The maximum flash file version that is accepted by the loader // ----------------------------------------------------------------------------- -// Konvertiert SWF-Rechteckdaten in einem Bitstrom in Common::Rect-Objekte +// Converts SWF rectangle data in a bit stream in Common::Rect objects // ----------------------------------------------------------------------------- Common::Rect flashRectToBSRect(VectorImage::SWFBitStream &bs) { bs.flushByte(); - // Feststellen mit wie vielen Bits die einzelnen Komponenten kodiert sind + // Determines how many bits of the single components are encoded uint32 bitsPerValue = bs.getBits(5); - // Die einzelnen Komponenten einlesen + // Readout the single components int32 xMin = bs.getSignedBits(bitsPerValue); int32 xMax = bs.getSignedBits(bitsPerValue); int32 yMin = bs.getSignedBits(bitsPerValue); @@ -182,7 +182,7 @@ Common::Rect flashRectToBSRect(VectorImage::SWFBitStream &bs) { } // ----------------------------------------------------------------------------- -// Berechnet die Bounding-Box eines BS_VectorImageElement +// Calculate the bounding box of a BS_VectorImageElement // ----------------------------------------------------------------------------- Common::Rect CalculateBoundingBox(const VectorImageElement &vectorImageElement) { @@ -214,17 +214,17 @@ Common::Rect CalculateBoundingBox(const VectorImageElement &vectorImageElement) // ----------------------------------------------------------------------------- -// Konstruktion +// Construction // ----------------------------------------------------------------------------- VectorImage::VectorImage(const byte *pFileData, uint fileSize, bool &success, const Common::String &fname) : _pixelData(0), _fname(fname) { success = false; - // Bitstream-Objekt erzeugen - // Im Folgenden werden die Dateidaten aus diesem ausgelesen. + // Create bitstream object + // In the following the file data will be readout of the bitstream object. SWFBitStream bs(pFileData, fileSize); - // SWF-Signatur überprüfen + // Check SWF signature uint32 signature[3]; signature[0] = bs.getByte(); signature[1] = bs.getByte(); @@ -236,37 +236,37 @@ VectorImage::VectorImage(const byte *pFileData, uint fileSize, bool &success, co return; } - // Versionsangabe überprüfen + // Check the version uint32 version = bs.getByte(); if (version > MAX_ACCEPTED_FLASH_VERSION) { error("File is of version %d. Highest accepted version is %d.", version, MAX_ACCEPTED_FLASH_VERSION); return; } - // Dateigröße auslesen und mit der tatsächlichen Größe vergleichen + // Readout filesize and compare with the actual size uint32 storedFileSize = bs.getUInt32(); if (storedFileSize != fileSize) { error("File is not a valid SWF-file"); return; } - // SWF-Maße auslesen + // readout SWF size Common::Rect movieRect = flashRectToBSRect(bs); - // Framerate und Frameanzahl auslesen + // Get frame rate and frame count /* uint32 frameRate = */ bs.getUInt16(); /* uint32 frameCount = */ bs.getUInt16(); - // Tags parsen - // Da wir uns nur für das erste DefineShape-Tag interessieren + // Parse tags + // Because we are only interested in the first DifneShape-Tag... bool keepParsing = true; while (keepParsing) { - // Tags beginnen immer an Bytegrenzen + // Tags always begin on byte boundaries bs.flushByte(); - // Tagtyp und Länge auslesen + // Readout tag type and length uint16 tagTypeAndLength = bs.getUInt16(); uint32 tagType = tagTypeAndLength >> 6; uint32 tagLength = tagTypeAndLength & 0x3f; @@ -286,13 +286,13 @@ VectorImage::VectorImage(const byte *pFileData, uint fileSize, bool &success, co success = parseDefineShape(3, bs); return; default: - // Unbekannte Tags ignorieren + // Ignore unknown tags bs.skipBytes(tagLength); } } - // Die Ausführung darf nicht an dieser Stelle ankommen: Entweder es wird ein Shape gefunden, dann wird die Funktion mit vorher verlassen, oder - // es wird keines gefunden, dann tritt eine Exception auf sobald über das Ende der Datei hinaus gelesen wird. + // The execution must not arrive at this point: Either a shape is found, then the function will be leaved before, or it is found none, then + // an exception occurs as soon as it is read beyond of the end of file. assert(false); } @@ -336,13 +336,13 @@ ArtBpath *VectorImage::storeBez(ArtBpath *bez, int lineStyle, int fillStyle0, in bool VectorImage::parseDefineShape(uint shapeType, SWFBitStream &bs) { /*uint32 shapeID = */bs.getUInt16(); - // Bounding Box auslesen + // readout bounding box _boundingBox = flashRectToBSRect(bs); - // Erstes Image-Element erzeugen + // create first image element _elements.resize(1); - // Styles einlesen + // read styles uint numFillBits; uint numLineBits; if (!parseStyles(shapeType, bs, numFillBits, numLineBits)) @@ -352,7 +352,7 @@ bool VectorImage::parseDefineShape(uint shapeType, SWFBitStream &bs) { uint fillStyle0 = 0; uint fillStyle1 = 0; - // Shaperecord parsen + // parse shaperecord // ------------------ double curX = 0; @@ -367,7 +367,7 @@ bool VectorImage::parseDefineShape(uint shapeType, SWFBitStream &bs) { // Non-Edge Record if (typeFlag == 0) { - // Feststellen welche Parameter gesetzt werden + // Determines which parameters are set uint32 stateNewStyles = bs.getBits(1); uint32 stateLineStyle = bs.getBits(1); uint32 stateFillStyle1 = bs.getBits(1); @@ -378,10 +378,10 @@ bool VectorImage::parseDefineShape(uint shapeType, SWFBitStream &bs) { uint prevFillStyle0 = fillStyle0; uint prevFillStyle1 = fillStyle1; - // End der Shape-Definition erreicht? + // End of the shape definition is reached? if (!stateNewStyles && !stateLineStyle && !stateFillStyle0 && !stateFillStyle1 && !stateMoveTo) { endOfShapeDiscovered = true; - // Parameter dekodieren + // Decode parameters } else { if (stateMoveTo) { uint32 moveToBits = bs.getBits(5); @@ -410,7 +410,7 @@ bool VectorImage::parseDefineShape(uint shapeType, SWFBitStream &bs) { numLineBits = 0; } - // Ein neuen Pfad erzeugen, es sei denn, es wurden nur neue Styles definiert + // Create a new path, unless there were only defined new styles if (stateLineStyle || stateFillStyle0 || stateFillStyle1 || stateMoveTo) { // Store previous curve if any if (bezNodes) { @@ -426,15 +426,15 @@ bool VectorImage::parseDefineShape(uint shapeType, SWFBitStream &bs) { } if (stateNewStyles) { - // An dieser Stelle werden in Flash die alten Style-Definitionen verworfen und mit den neuen überschrieben. - // Es wird ein neues Element begonnen. + // The old style definitions will be discarded and overwritten with the new at this point in Flash. + // A new element will be started with a new element. _elements.resize(_elements.size() + 1); if (!parseStyles(shapeType, bs, numFillBits, numLineBits)) return false; } } } else { - // Edge Record + // Edge record uint32 edgeFlag = bs.getBits(1); uint32 numBits = bs.getBits(4) + 2; @@ -499,7 +499,7 @@ bool VectorImage::parseDefineShape(uint shapeType, SWFBitStream &bs) { free(bez); - // Bounding-Boxes der einzelnen Elemente berechnen + // Calculate the bounding boxes of each element Common::Array<VectorImageElement>::iterator it = _elements.begin(); for (; it != _elements.end(); ++it) it->_boundingBox = CalculateBoundingBox(*it); @@ -513,16 +513,16 @@ bool VectorImage::parseDefineShape(uint shapeType, SWFBitStream &bs) { bool VectorImage::parseStyles(uint shapeType, SWFBitStream &bs, uint &numFillBits, uint &numLineBits) { bs.flushByte(); - // Fillstyles parsen + // Parse fill styles // ----------------- - // Anzahl an Fillstyles bestimmen + // Determine number of fill styles uint fillStyleCount = bs.getByte(); if (fillStyleCount == 0xff) fillStyleCount = bs.getUInt16(); - // Alle Fillstyles einlesen, falls ein Fillstyle mit Typ != 0 gefunden wird, wird das Parsen abgebrochen. - // Es wird nur "solid fill" (Typ 0) unterstützt. + // Readout all fill styles. If a fill style with Typ != 0 is found, the parsing is aborted. + // Only "solid fill" (Typ 0) is supported. _elements.back()._fillStyles.reserve(fillStyleCount); for (uint i = 0; i < fillStyleCount; ++i) { byte type = bs.getByte(); @@ -543,15 +543,15 @@ bool VectorImage::parseStyles(uint shapeType, SWFBitStream &bs, uint &numFillBit _elements.back()._fillStyles.push_back(color); } - // Linestyles parsen + // Line styles parsen // ----------------- - // Anzahl an Linestyles bestimmen + // Determine number of line styles uint lineStyleCount = bs.getByte(); if (lineStyleCount == 0xff) lineStyleCount = bs.getUInt16(); - // Alle Linestyles einlesen + // Readout all line styles _elements.back()._lineStyles.reserve(lineStyleCount); for (uint i = 0; i < lineStyleCount; ++i) { double width = bs.getUInt16(); @@ -569,7 +569,7 @@ bool VectorImage::parseStyles(uint shapeType, SWFBitStream &bs, uint &numFillBit _elements.back()._lineStyles.push_back(VectorImageElement::LineStyleType(width, color)); } - // Bitbreite für die folgenden Styleindizes auslesen + // Readout the bit width for the following style indices numFillBits = bs.getBits(4); numLineBits = bs.getBits(4); @@ -608,11 +608,11 @@ bool VectorImage::blit(int posX, int posY, static int oldWidth = -2; static int oldHeight = -2; - // Falls Breite oder Höhe 0 sind, muss nichts dargestellt werden. + // If width or height to 0, nothing needs to be shown. if (width == 0 || height == 0) return true; - // Feststellen, ob das alte Bild im Cache nicht wiederbenutzt werden kann und neu Berechnet werden muss + // Determine if the old image in the cache can not be reused and must be recalculated if (!(oldThis == this && oldWidth == width && oldHeight == height)) { render(width, height); diff --git a/engines/tinsel/music.cpp b/engines/tinsel/music.cpp index 943beb474e..3b9833b418 100644 --- a/engines/tinsel/music.cpp +++ b/engines/tinsel/music.cpp @@ -388,37 +388,23 @@ void DeleteMidiBuffer() { MidiMusicPlayer::MidiMusicPlayer() { MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM); - bool native_mt32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32")); + _nativeMT32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32")); //bool adlib = (MidiDriver::getMusicType(dev) == MT_ADLIB); _driver = MidiDriver::createMidi(dev); assert(_driver); - if (native_mt32) + if (_nativeMT32) _driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE); int ret = _driver->open(); if (ret == 0) { - if (native_mt32) + if (_nativeMT32) _driver->sendMT32Reset(); else _driver->sendGMReset(); - _driver->setTimerCallback(this, &onTimer); + _driver->setTimerCallback(this, &timerCallback); } - - _xmidiParser = MidiParser::createParser_XMIDI(); -} - -MidiMusicPlayer::~MidiMusicPlayer() { - _driver->setTimerCallback(NULL, NULL); - stop(); - if (_driver) { - _driver->close(); - delete _driver; - _driver = 0; - } - _xmidiParser->setMidiDriver(NULL); - delete _xmidiParser; } void MidiMusicPlayer::setVolume(int volume) { @@ -441,15 +427,9 @@ void MidiMusicPlayer::send(uint32 b) { } } -void MidiMusicPlayer::onTimer(void *refCon) { - MidiMusicPlayer *music = (MidiMusicPlayer *)refCon; - Common::StackLock lock(music->_mutex); - - if (music->_isPlaying) - music->_parser->onTimer(); -} - void MidiMusicPlayer::playXMIDI(byte *midiData, uint32 size, bool loop) { + Common::StackLock lock(_mutex); + if (_isPlaying) return; @@ -467,8 +447,8 @@ void MidiMusicPlayer::playXMIDI(byte *midiData, uint32 size, bool loop) { // Load XMID resource data - if (_xmidiParser->loadMusic(midiData, size)) { - MidiParser *parser = _xmidiParser; + MidiParser *parser = MidiParser::createParser_XMIDI(); + if (parser->loadMusic(midiData, size)) { parser->setTrack(0); parser->setMidiDriver(this); parser->setTimerRate(getBaseTempo()); @@ -479,6 +459,8 @@ void MidiMusicPlayer::playXMIDI(byte *midiData, uint32 size, bool loop) { _isLooping = loop; _isPlaying = true; + } else { + delete parser; } } diff --git a/engines/tinsel/music.h b/engines/tinsel/music.h index 9436c02032..af089caf24 100644 --- a/engines/tinsel/music.h +++ b/engines/tinsel/music.h @@ -64,7 +64,6 @@ void dumpMusic(); class MidiMusicPlayer : public Audio::MidiPlayer { public: MidiMusicPlayer(); - ~MidiMusicPlayer(); virtual void setVolume(int volume); @@ -80,12 +79,6 @@ public: // The original sets the "sequence timing" to 109 Hz, whatever that // means. The default is 120. uint32 getBaseTempo() { return _driver ? (109 * _driver->getBaseTempo()) / 120 : 0; } - -protected: - - static void onTimer(void *data); - - MidiParser *_xmidiParser; }; class PCMMusicPlayer : public Audio::AudioStream { diff --git a/engines/tinsel/tinsel.cpp b/engines/tinsel/tinsel.cpp index ef0fe1c909..1b3173719f 100644 --- a/engines/tinsel/tinsel.cpp +++ b/engines/tinsel/tinsel.cpp @@ -859,8 +859,6 @@ TinselEngine::TinselEngine(OSystem *syst, const TinselGameDescription *gameDesc) _midiMusic = new MidiMusicPlayer(); _pcmMusic = new PCMMusicPlayer(); - _musicVolume = ConfMan.getInt("music_volume"); - _sound = new SoundManager(this); _bmv = new BMVPlayer(); diff --git a/engines/tinsel/tinsel.h b/engines/tinsel/tinsel.h index 009f6fe26d..5c7a1cdfb2 100644 --- a/engines/tinsel/tinsel.h +++ b/engines/tinsel/tinsel.h @@ -219,9 +219,6 @@ public: RectList _clipRects; private: - //MidiMusicPlayer *_midiMusic; - int _musicVolume; - void NextGameCycle(); void CreateConstProcesses(); void RestartGame(); diff --git a/engines/touche/midi.cpp b/engines/touche/midi.cpp index 4349a29bf5..c89375d876 100644 --- a/engines/touche/midi.cpp +++ b/engines/touche/midi.cpp @@ -32,9 +32,21 @@ namespace Touche { -MidiPlayer::MidiPlayer() - : _driver(0), _parser(0), _midiData(0), _isLooping(false), _isPlaying(false), _masterVolume(0) { - memset(_channelsTable, 0, sizeof(_channelsTable)); +static const uint8 _gmToRol[256] = { + 0x01, 0x02, 0x03, 0x08, 0x04, 0x05, 0x11, 0x14, 0x66, 0x66, 0x66, 0x62, 0x69, 0x68, 0x67, 0x26, + 0x09, 0x0A, 0x0B, 0x0E, 0x0F, 0x10, 0x10, 0x10, 0x3C, 0x3D, 0x3D, 0x3D, 0x3D, 0x3E, 0x3F, 0x3F, + 0x47, 0x41, 0x42, 0x48, 0x45, 0x46, 0x1D, 0x1E, 0x35, 0x36, 0x37, 0x39, 0x33, 0x34, 0x3A, 0x71, + 0x31, 0x32, 0x31, 0x32, 0x23, 0x23, 0x23, 0x7B, 0x59, 0x5B, 0x5F, 0x5A, 0x5D, 0x60, 0x19, 0x1A, + 0x4F, 0x50, 0x51, 0x52, 0x55, 0x56, 0x57, 0x53, 0x4B, 0x49, 0x4D, 0x4E, 0x6F, 0x6C, 0x6D, 0x6E, + 0x30, 0x19, 0x4E, 0x2B, 0x28, 0x23, 0x19, 0x30, 0x21, 0x25, 0x1C, 0x21, 0x24, 0x22, 0x21, 0x22, + 0x2A, 0x25, 0x24, 0x26, 0x2E, 0x22, 0x29, 0x21, 0x40, 0x40, 0x6A, 0x6A, 0x68, 0x10, 0x35, 0x10, + 0x7F, 0x6B, 0x69, 0x75, 0x76, 0x72, 0x74, 0x01, 0x01, 0x70, 0x01, 0x7D, 0x7C, 0x01, 0x01, 0x01 +}; + + +MidiPlayer::MidiPlayer() { + + // FIXME: Necessary? memset(_channelsVolume, 0, sizeof(_channelsVolume)); MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM); @@ -42,9 +54,6 @@ MidiPlayer::MidiPlayer() _driver = MidiDriver::createMidi(dev); int ret = _driver->open(); if (ret == 0) { - _parser = MidiParser::createParser_SMF(); - _parser->setMidiDriver(this); - _parser->setTimerRate(_driver->getBaseTempo()); _driver->setTimerCallback(this, &timerCallback); if (_nativeMT32) @@ -54,25 +63,18 @@ MidiPlayer::MidiPlayer() } } -MidiPlayer::~MidiPlayer() { - stop(); - +void MidiPlayer::play(Common::ReadStream &stream, int size, bool loop) { Common::StackLock lock(_mutex); - _driver->setTimerCallback(NULL, NULL); - _driver->close(); - delete _driver; - _driver = 0; - _parser->setMidiDriver(NULL); - delete _parser; -} -void MidiPlayer::play(Common::ReadStream &stream, int size, bool loop) { stop(); - _midiData = (uint8 *)malloc(size); + _midiData = (byte *)malloc(size); if (_midiData) { stream.read(_midiData, size); - Common::StackLock lock(_mutex); + _parser = MidiParser::createParser_SMF(); + _parser->setMidiDriver(this); + _parser->setTimerRate(_driver->getBaseTempo()); + _parser->loadMusic(_midiData, size); _parser->setTrack(0); _isLooping = loop; @@ -80,31 +82,22 @@ void MidiPlayer::play(Common::ReadStream &stream, int size, bool loop) { } } -void MidiPlayer::stop() { - Common::StackLock lock(_mutex); - if (_isPlaying) { - _isPlaying = false; - _parser->unloadMusic(); - free(_midiData); - _midiData = 0; - } -} - -void MidiPlayer::updateTimer() { - Common::StackLock lock(_mutex); - if (_isPlaying) { - _parser->onTimer(); - } -} - void MidiPlayer::adjustVolume(int diff) { setVolume(_masterVolume + diff); } void MidiPlayer::setVolume(int volume) { + // FIXME: This is almost identical to Audio::MidiPlayer::setVolume, + // the only difference is that this implementation will always + // transmit the volume change, even if the current _masterVolume + // equals the new master volume. This *could* make a difference in + // some situations. + // So, we should determine whether Touche requires this behavioral + // difference; and maybe also if other engines could benefit from it + // (as hypothetically, it might fix some subtle bugs?) _masterVolume = CLIP(volume, 0, 255); Common::StackLock lock(_mutex); - for (int i = 0; i < NUM_CHANNELS; ++i) { + for (int i = 0; i < kNumChannels; ++i) { if (_channelsTable[i]) { _channelsTable[i]->volume(_channelsVolume[i] * _masterVolume / 255); } @@ -112,52 +105,10 @@ void MidiPlayer::setVolume(int volume) { } void MidiPlayer::send(uint32 b) { - byte volume, ch = (byte)(b & 0xF); - switch (b & 0xFFF0) { - case 0x07B0: // volume change - volume = (byte)((b >> 16) & 0x7F); - _channelsVolume[ch] = volume; - volume = volume * _masterVolume / 255; - b = (b & 0xFF00FFFF) | (volume << 16); - break; - case 0x7BB0: // all notes off - if (!_channelsTable[ch]) { - // channel not yet allocated, no need to send the event - return; - } - break; - default: - if ((b & 0xF0) == 0xC0 && _nativeMT32) { // program change - b = (b & 0xFFFF00FF) | (_gmToRol[(b >> 8) & 0x7F] << 8); - } - break; + if ((b & 0xF0) == 0xC0 && _nativeMT32) { // program change + b = (b & 0xFFFF00FF) | (_gmToRol[(b >> 8) & 0x7F] << 8); } - if (!_channelsTable[ch]) { - _channelsTable[ch] = (ch == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel(); - } - if (_channelsTable[ch]) { - _channelsTable[ch]->send(b); - } -} - -void MidiPlayer::metaEvent(byte type, byte *data, uint16 length) { - switch (type) { - case 0x2F: // end of Track - if (_isLooping) { - _parser->jumpToTick(0); - } else { - stop(); - } - break; - default: -// warning("Unhandled meta event: %02x", type); - break; - } -} - -void MidiPlayer::timerCallback(void *p) { - MidiPlayer *player = (MidiPlayer *)p; - player->updateTimer(); + Audio::MidiPlayer::send(b); } } // Touche namespace diff --git a/engines/touche/midi.h b/engines/touche/midi.h index bc5adc6b5f..f0f55e64e6 100644 --- a/engines/touche/midi.h +++ b/engines/touche/midi.h @@ -29,7 +29,7 @@ #include "common/util.h" #include "common/mutex.h" -#include "audio/mididrv.h" +#include "audio/midiplayer.h" class MidiParser; @@ -39,44 +39,16 @@ namespace Common { namespace Touche { -class MidiPlayer : public MidiDriver_BASE { +class MidiPlayer : public Audio::MidiPlayer { public: - - enum { - NUM_CHANNELS = 16 - }; - MidiPlayer(); - ~MidiPlayer(); void play(Common::ReadStream &stream, int size, bool loop = false); - void stop(); - void updateTimer(); void adjustVolume(int diff); void setVolume(int volume); - int getVolume() const { return _masterVolume; } - void setLooping(bool loop) { _isLooping = loop; } // MidiDriver_BASE interface virtual void send(uint32 b); - virtual void metaEvent(byte type, byte *data, uint16 length); - -private: - - static void timerCallback(void *p); - - MidiDriver *_driver; - MidiParser *_parser; - uint8 *_midiData; - bool _isLooping; - bool _isPlaying; - int _masterVolume; - bool _nativeMT32; - MidiChannel *_channelsTable[NUM_CHANNELS]; - uint8 _channelsVolume[NUM_CHANNELS]; - Common::Mutex _mutex; - - static const uint8 _gmToRol[]; }; } // namespace Touche diff --git a/engines/touche/staticres.cpp b/engines/touche/staticres.cpp index a377a6e45f..74aa7954de 100644 --- a/engines/touche/staticres.cpp +++ b/engines/touche/staticres.cpp @@ -1822,15 +1822,4 @@ int Graphics::_fontSize = Graphics::_engFontSize; const uint8 *Graphics::_fontData = Graphics::_engFontData; -const uint8 MidiPlayer::_gmToRol[] = { - 0x01, 0x02, 0x03, 0x08, 0x04, 0x05, 0x11, 0x14, 0x66, 0x66, 0x66, 0x62, 0x69, 0x68, 0x67, 0x26, - 0x09, 0x0A, 0x0B, 0x0E, 0x0F, 0x10, 0x10, 0x10, 0x3C, 0x3D, 0x3D, 0x3D, 0x3D, 0x3E, 0x3F, 0x3F, - 0x47, 0x41, 0x42, 0x48, 0x45, 0x46, 0x1D, 0x1E, 0x35, 0x36, 0x37, 0x39, 0x33, 0x34, 0x3A, 0x71, - 0x31, 0x32, 0x31, 0x32, 0x23, 0x23, 0x23, 0x7B, 0x59, 0x5B, 0x5F, 0x5A, 0x5D, 0x60, 0x19, 0x1A, - 0x4F, 0x50, 0x51, 0x52, 0x55, 0x56, 0x57, 0x53, 0x4B, 0x49, 0x4D, 0x4E, 0x6F, 0x6C, 0x6D, 0x6E, - 0x30, 0x19, 0x4E, 0x2B, 0x28, 0x23, 0x19, 0x30, 0x21, 0x25, 0x1C, 0x21, 0x24, 0x22, 0x21, 0x22, - 0x2A, 0x25, 0x24, 0x26, 0x2E, 0x22, 0x29, 0x21, 0x40, 0x40, 0x6A, 0x6A, 0x68, 0x10, 0x35, 0x10, - 0x7F, 0x6B, 0x69, 0x75, 0x76, 0x72, 0x74, 0x01, 0x01, 0x70, 0x01, 0x7D, 0x7C, 0x01, 0x01, 0x01 -}; - } // namespace Touche |