From 6588398ce6fab85e287b10c2781d3797d7639cb9 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Wed, 15 Sep 2010 22:00:20 +0000 Subject: [PATCH] MIDI: Send a reset MIDI device signal on startup. This is currently done in the engine code. I adapted AGI, AGOS, DRACI, GROOVIE, LURE, MADE, QUEEN, SAGA, SKY, TINSEL and TOUCHE to send a reset device on startup. The sound output still works fine (started up a game from every engine), so this should hopefully not introduce any regressions. As far as I can tell it seems that SCUMM does send a proper device reset, so I did not touch it. KYRA only sends a proper reset for MT-32 currently. I am not sure about SCI though. This fixes bug #3066826 "SIMON: MIDI notes off when using RTL after SCI". svn-id: r52736 --- engines/agi/sound_midi.cpp | 14 +++++++++----- engines/agos/agos.cpp | 6 +++--- engines/agos/midi.cpp | 8 ++++---- engines/agos/midi.h | 2 ++ engines/draci/draci.cpp | 1 + engines/draci/music.cpp | 14 +++++++++----- engines/groovie/music.cpp | 4 ++++ engines/lure/sound.cpp | 6 +++++- engines/made/made.cpp | 1 + engines/made/music.cpp | 6 +++++- engines/queen/music.cpp | 5 +++++ engines/saga/music.cpp | 13 +++++++++++++ engines/saga/music.h | 2 +- engines/sky/music/gmmusic.cpp | 1 + engines/sky/music/mt32music.cpp | 1 + engines/tinsel/tinsel.cpp | 5 +++++ engines/touche/midi.cpp | 5 +++++ sound/mididrv.cpp | 13 +++++++++++++ sound/mididrv.h | 10 ++++++++++ 19 files changed, 97 insertions(+), 20 deletions(-) diff --git a/engines/agi/sound_midi.cpp b/engines/agi/sound_midi.cpp index d2636727ee7..dcdaac53a79 100644 --- a/engines/agi/sound_midi.cpp +++ b/engines/agi/sound_midi.cpp @@ -74,8 +74,12 @@ SoundGenMIDI::SoundGenMIDI(AgiEngine *vm, Audio::Mixer *pMixer) : SoundGen(vm, p DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB); _driver = MidiDriver::createMidi(dev); - if (ConfMan.getBool("native_mt32")) + if (ConfMan.getBool("native_mt32") || MidiDriver::getMusicType(dev) == MT_MT32) { + _nativeMT32 = true; _driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE); + } else { + _nativeMT32 = false; + } memset(_channel, 0, sizeof(_channel)); memset(_channelVolume, 255, sizeof(_channelVolume)); @@ -125,10 +129,10 @@ int SoundGenMIDI::open() { _driver->setTimerCallback(this, &onTimer); - // General MIDI System On message - // Resets all GM devices to default settings - _driver->sysEx((const byte *)"\x7E\x7F\x09\x01", 4); - g_system->delayMillis(20); + if (_nativeMT32) + _driver->sendMT32Reset(); + else + _driver->sendGMReset(); return 0; } diff --git a/engines/agos/agos.cpp b/engines/agos/agos.cpp index 670c7011981..bbfce5f1a9e 100644 --- a/engines/agos/agos.cpp +++ b/engines/agos/agos.cpp @@ -562,11 +562,11 @@ Common::Error AGOSEngine::init() { _driver = MidiDriver::createMidi(dev); - if (_nativeMT32) { + if (_nativeMT32) _driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE); - } - _midi.mapMT32toGM (getGameType() != GType_SIMON2 && !_nativeMT32); + _midi.setNativeMT32(_nativeMT32); + _midi.mapMT32toGM(getGameType() != GType_SIMON2 && !_nativeMT32); _midi.setDriver(_driver); diff --git a/engines/agos/midi.cpp b/engines/agos/midi.cpp index ab5bfc4c94e..858307685c6 100644 --- a/engines/agos/midi.cpp +++ b/engines/agos/midi.cpp @@ -77,10 +77,10 @@ int MidiPlayer::open() { return ret; _driver->setTimerCallback(this, &onTimer); - // General MIDI System On message - // Resets all GM devices to default settings - _driver->sysEx((const byte *)"\x7E\x7F\x09\x01", 4); - g_system->delayMillis(20); + if (_nativeMT32) + _driver->sendMT32Reset(); + else + _driver->sendGMReset(); return 0; } diff --git a/engines/agos/midi.h b/engines/agos/midi.h index d4c09118f64..d76997737a6 100644 --- a/engines/agos/midi.h +++ b/engines/agos/midi.h @@ -61,6 +61,7 @@ protected: MidiDriver *_driver; bool _map_mt32_to_gm; bool _passThrough; + bool _nativeMT32; MusicInfo _music; MusicInfo _sfx; @@ -97,6 +98,7 @@ public: void loadS1D(Common::File *in, bool sfx = false); void mapMT32toGM(bool map); + void setNativeMT32(bool nativeMT32) { _nativeMT32 = nativeMT32; } void setLoop(bool loop); void startTrack(int track); void queueTrack(int track, bool loop); diff --git a/engines/draci/draci.cpp b/engines/draci/draci.cpp index cd3920b30d0..814159dbbb4 100644 --- a/engines/draci/draci.cpp +++ b/engines/draci/draci.cpp @@ -170,6 +170,7 @@ int DraciEngine::init() { _music = new MusicPlayer(_midiDriver, musicPathMask); _music->setNativeMT32(native_mt32); + _music->open(); //_music->setAdLib(adlib); // Load the game's fonts diff --git a/engines/draci/music.cpp b/engines/draci/music.cpp index 8186d36068f..509bf901218 100644 --- a/engines/draci/music.cpp +++ b/engines/draci/music.cpp @@ -40,13 +40,8 @@ MusicPlayer::MusicPlayer(MidiDriver *driver, const char *pathMask) : _parser(0), memset(_channel, 0, sizeof(_channel)); memset(_channelVolume, 255, sizeof(_channelVolume)); _masterVolume = 0; - this->open(); _smfParser = MidiParser::createParser_SMF(); _midiMusicData = NULL; - - // TODO: Load cmf.ins with the instrument table. It seems that an - // interface for such an operation is supported for AdLib. Maybe for - // this card, setting instruments is necessary. } MusicPlayer::~MusicPlayer() { @@ -89,6 +84,15 @@ int MusicPlayer::open() { if (ret) return ret; + if (_nativeMT32) + _driver->sendMT32Reset(); + else + _driver->sendGMReset(); + + // TODO: Load cmf.ins with the instrument table. It seems that an + // interface for such an operation is supported for AdLib. Maybe for + // this card, setting instruments is necessary. + _driver->setTimerCallback(this, &onTimer); return 0; } diff --git a/engines/groovie/music.cpp b/engines/groovie/music.cpp index 6959a6a6f1c..6ccc68c4983 100644 --- a/engines/groovie/music.cpp +++ b/engines/groovie/music.cpp @@ -427,10 +427,14 @@ MusicPlayerXMI::MusicPlayerXMI(GroovieEngine *vm, const Common::String >lName) setTimbreAD(9, _timbres[i]); } } else if ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32")) { + _driver->sendMT32Reset(); + // MT-32 _musicType = MT_MT32; loadTimbres(gtlName + ".mt"); } else { + _driver->sendGMReset(); + // GM _musicType = 0; } diff --git a/engines/lure/sound.cpp b/engines/lure/sound.cpp index a75545c3302..ca15ad82872 100644 --- a/engines/lure/sound.cpp +++ b/engines/lure/sound.cpp @@ -63,8 +63,12 @@ SoundManager::SoundManager() { _driver = NULL; } else { - if (_nativeMT32) + if (_nativeMT32) { _driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE); + _driver->sendMT32Reset(); + } else { + _driver->sendGMReset(); + } for (index = 0; index < NUM_CHANNELS; ++index) { _channelsInner[index].midiChannel = _driver->allocateChannel(); diff --git a/engines/made/made.cpp b/engines/made/made.cpp index 94926014d3e..51cdd83b2aa 100644 --- a/engines/made/made.cpp +++ b/engines/made/made.cpp @@ -107,6 +107,7 @@ MadeEngine::MadeEngine(OSystem *syst, const MadeGameDescription *gameDesc) : Eng _music = new MusicPlayer(driver); _music->setNativeMT32(native_mt32); + _music->open(); //_music->setAdLib(adlib); // Set default sound frequency diff --git a/engines/made/music.cpp b/engines/made/music.cpp index bb45367805e..4e2789e5fae 100644 --- a/engines/made/music.cpp +++ b/engines/made/music.cpp @@ -40,7 +40,6 @@ namespace Made { MusicPlayer::MusicPlayer(MidiDriver *driver) : _parser(0), _driver(driver), _looping(false), _isPlaying(false), _passThrough(false), _isGM(false) { memset(_channel, 0, sizeof(_channel)); _masterVolume = 0; - this->open(); _xmidiParser = MidiParser::createParser_XMIDI(); _smfParser = MidiParser::createParser_SMF(); } @@ -81,6 +80,11 @@ int MusicPlayer::open() { if (ret) return ret; + if (_nativeMT32) + _driver->sendMT32Reset(); + else + _driver->sendGMReset(); + _driver->setTimerCallback(this, &onTimer); return 0; } diff --git a/engines/queen/music.cpp b/engines/queen/music.cpp index 3d859c83357..be6b0dc773d 100644 --- a/engines/queen/music.cpp +++ b/engines/queen/music.cpp @@ -82,6 +82,11 @@ MidiMusic::MidiMusic(QueenEngine *vm) _driver->open(); _driver->setTimerCallback(this, &timerCallback); + if (_nativeMT32) + _driver->sendMT32Reset(); + else + _driver->sendGMReset(); + _parser = MidiParser::createParser_SMF(); _parser->setMidiDriver(this); _parser->setTimerRate(_driver->getBaseTempo()); diff --git a/engines/saga/music.cpp b/engines/saga/music.cpp index e4a16e27dab..eb791324954 100644 --- a/engines/saga/music.cpp +++ b/engines/saga/music.cpp @@ -60,6 +60,19 @@ MusicDriver::~MusicDriver() { delete _driver; } +int MusicDriver::open() { + int retValue = _driver->open(); + if (retValue) + return retValue; + + if (_nativeMT32) + _driver->sendMT32Reset(); + else + _driver->sendGMReset(); + + return 0; +} + void MusicDriver::setVolume(int volume) { volume = CLIP(volume, 0, 255); diff --git a/engines/saga/music.h b/engines/saga/music.h index 5cce3d4c04b..e3d57231459 100644 --- a/engines/saga/music.h +++ b/engines/saga/music.h @@ -57,7 +57,7 @@ public: void setGM(bool isGM) { _isGM = isGM; } //MidiDriver interface implementation - int open() { return _driver->open(); } + int open(); void close() { _driver->close(); } void send(uint32 b); diff --git a/engines/sky/music/gmmusic.cpp b/engines/sky/music/gmmusic.cpp index f2abb3f277d..e7b3a241705 100644 --- a/engines/sky/music/gmmusic.cpp +++ b/engines/sky/music/gmmusic.cpp @@ -44,6 +44,7 @@ GmMusic::GmMusic(MidiDriver *pMidiDrv, Disk *pDisk) : MusicBase(pDisk) { error("Can't open midi device. Errorcode: %d", midiRes); _timerCount = 0; _midiDrv->setTimerCallback(this, passTimerFunc); + _midiDrv->sendGMReset(); } GmMusic::~GmMusic() { diff --git a/engines/sky/music/mt32music.cpp b/engines/sky/music/mt32music.cpp index ce2a29dad8b..bdefa66709c 100644 --- a/engines/sky/music/mt32music.cpp +++ b/engines/sky/music/mt32music.cpp @@ -44,6 +44,7 @@ MT32Music::MT32Music(MidiDriver *pMidiDrv, Disk *pDisk) : MusicBase(pDisk) { error("Can't open midi device. Errorcode: %d",midiRes); _timerCount = 0; _midiDrv->setTimerCallback(this, passTimerFunc); + _midiDrv->sendMT32Reset(); } MT32Music::~MT32Music() { diff --git a/engines/tinsel/tinsel.cpp b/engines/tinsel/tinsel.cpp index 888a47648ff..bb6ed991380 100644 --- a/engines/tinsel/tinsel.cpp +++ b/engines/tinsel/tinsel.cpp @@ -867,6 +867,11 @@ TinselEngine::TinselEngine(OSystem *syst, const TinselGameDescription *gameDesc) //_midiMusic->setNativeMT32(native_mt32); //_midiMusic->setAdLib(adlib); + if (native_mt32) + _driver->sendMT32Reset(); + else + _driver->sendGMReset(); + _musicVolume = ConfMan.getInt("music_volume"); _sound = new SoundManager(this); diff --git a/engines/touche/midi.cpp b/engines/touche/midi.cpp index 439d3b9ac29..ee7602abf74 100644 --- a/engines/touche/midi.cpp +++ b/engines/touche/midi.cpp @@ -101,6 +101,11 @@ int MidiPlayer::open() { _parser->setMidiDriver(this); _parser->setTimerRate(_driver->getBaseTempo()); _driver->setTimerCallback(this, &timerCallback); + + if (_nativeMT32) + _driver->sendMT32Reset(); + else + _driver->sendGMReset(); } return ret; } diff --git a/sound/mididrv.cpp b/sound/mididrv.cpp index eb8bafee01a..b93df195587 100644 --- a/sound/mididrv.cpp +++ b/sound/mididrv.cpp @@ -306,3 +306,16 @@ MidiDriver::DeviceHandle MidiDriver::getDeviceHandle(const Common::String &ident return 0; } + +void MidiDriver::sendMT32Reset() { + static const byte resetSysEx[] = { 0x41, 0x10, 0x16, 0x12, 0x7F, 0x00, 0x00, 0x01, 0x00 }; + sysEx(resetSysEx, sizeof(resetSysEx)); + g_system->delayMillis(100); +} + +void MidiDriver::sendGMReset() { + static const byte resetSysEx[] = { 0x7E, 0x7F, 0x09, 0x01 }; + sysEx(resetSysEx, sizeof(resetSysEx)); + g_system->delayMillis(100); +} + diff --git a/sound/mididrv.h b/sound/mididrv.h index 7ba1fe19f74..9e649cba3d9 100644 --- a/sound/mididrv.h +++ b/sound/mididrv.h @@ -215,6 +215,16 @@ public: send(0xB0 | channel, 100, 127); } + /** + * Send a Roland MT-32 reset sysEx to the midi device. + */ + void sendMT32Reset(); + + /** + * Send a General MIDI reset sysEx to the midi device. + */ + void sendGMReset(); + /** * Transmit a sysEx to the midi device. *