[Scummvm-git-logs] scummvm master -> 34c5d3f2a22e06cd84179421c1a587b6a6559efd
yuv422
yuv422 at users.noreply.github.com
Thu May 21 08:06:18 UTC 2020
This automated email contains information about 2 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
39c264d853 DRAGONS: Implementing midi music player
34c5d3f2a2 DRAGONS: Moved midi data size init to initializer list
Commit: 39c264d853133ca95f224f52c98e52dd2bbe983b
https://github.com/scummvm/scummvm/commit/39c264d853133ca95f224f52c98e52dd2bbe983b
Author: Eric Fry (yuv422 at users.noreply.github.com)
Date: 2020-05-21T18:06:13+10:00
Commit Message:
DRAGONS: Implementing midi music player
Changed paths:
A engines/dragons/midimusicplayer.cpp
A engines/dragons/midimusicplayer.h
engines/dragons/dragons.cpp
engines/dragons/minigame2.cpp
engines/dragons/minigame3.cpp
engines/dragons/module.mk
engines/dragons/scriptopcodes.cpp
engines/dragons/sound.cpp
engines/dragons/sound.h
engines/dragons/specialopcodes.cpp
engines/dragons/talk.cpp
diff --git a/engines/dragons/dragons.cpp b/engines/dragons/dragons.cpp
index ceda9f75c5..440ae7e2e2 100644
--- a/engines/dragons/dragons.cpp
+++ b/engines/dragons/dragons.cpp
@@ -654,7 +654,9 @@ void DragonsEngine::updateHandler() {
// 0x8001b200
if (isFlagSet(ENGINE_FLAG_8000) && !_sound->isSpeechPlaying()) {
+ //dialog finished playing.
clearFlags(ENGINE_FLAG_8000);
+ _sound->resumeMusic();
}
//TODO logic here
diff --git a/engines/dragons/midimusicplayer.cpp b/engines/dragons/midimusicplayer.cpp
new file mode 100644
index 0000000000..3034cb6c29
--- /dev/null
+++ b/engines/dragons/midimusicplayer.cpp
@@ -0,0 +1,132 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+#include "common/stream.h"
+#include "audio/midiparser.h"
+#include "midimusicplayer.h"
+
+
+namespace Dragons {
+
+MidiMusicPlayer::MidiMusicPlayer(VabSound *musicVab): _musicVab(musicVab) {
+ _midiData = nullptr;
+ _midiDataSize = 0;
+ MidiPlayer::createDriver();
+
+ int ret = _driver->open();
+ if (ret == 0) {
+ if (_nativeMT32)
+ _driver->sendMT32Reset();
+ else
+ _driver->sendGMReset();
+
+ _driver->setTimerCallback(this, &timerCallback);
+ }
+}
+
+MidiMusicPlayer::~MidiMusicPlayer() {
+ if (isPlaying()) {
+ stop();
+ }
+}
+
+void MidiMusicPlayer::playSong(Common::SeekableReadStream *seqData) {
+ Common::StackLock lock(_mutex);
+
+ if (isPlaying()) {
+ stop();
+ }
+
+ if (seqData->readUint32LE() != MKTAG('S', 'E', 'Q', 'p'))
+ error("Failed to find SEQp tag");
+
+ // Make sure we don't have a SEP file (with multiple SEQ's inside)
+ if (seqData->readUint32BE() != 1)
+ error("Can only play SEQ files, not SEP");
+
+ uint16 ppqn = seqData->readUint16BE();
+ uint32 tempo = seqData->readUint16BE() << 8;
+ tempo |= seqData->readByte();
+ /* uint16 beat = */ seqData->readUint16BE();
+
+ // SEQ is directly based on SMF and we'll use that to our advantage here
+ // and convert to SMF and then use the SMF MidiParser.
+
+ // Calculate the SMF size we'll need
+ uint32 dataSize = seqData->size() - 15;
+ uint32 actualSize = dataSize + 7 + 22;
+
+ // Resize the buffer if necessary
+ byte *midiData = resizeMidiBuffer(actualSize);
+
+ // Now construct the header
+ WRITE_BE_UINT32(midiData, MKTAG('M', 'T', 'h', 'd'));
+ WRITE_BE_UINT32(midiData + 4, 6); // header size
+ WRITE_BE_UINT16(midiData + 8, 0); // type 0
+ WRITE_BE_UINT16(midiData + 10, 1); // one track
+ WRITE_BE_UINT16(midiData + 12, ppqn);
+ WRITE_BE_UINT32(midiData + 14, MKTAG('M', 'T', 'r', 'k'));
+ WRITE_BE_UINT32(midiData + 18, dataSize + 7); // SEQ data size + tempo change event size
+
+ // Add in a fake tempo change event
+ WRITE_BE_UINT32(midiData + 22, 0x00FF5103); // no delta, meta event, tempo change, param size = 3
+ WRITE_BE_UINT16(midiData + 26, tempo >> 8);
+ midiData[28] = tempo & 0xFF;
+
+ // Now copy in the rest of the events
+ seqData->read(midiData + 29, dataSize);
+
+ MidiParser *parser = MidiParser::createParser_SMF();
+ if (parser->loadMusic(midiData, actualSize)) {
+ parser->setTrack(0);
+ parser->setMidiDriver(this);
+ parser->setTimerRate(getBaseTempo());
+ parser->property(MidiParser::mpCenterPitchWheelOnUnload, 1);
+ parser->property(MidiParser::mpSendSustainOffOnNotesOff, 1);
+
+ _parser = parser;
+
+ _isLooping = true;
+ _isPlaying = true;
+ } else {
+ delete parser;
+ }
+}
+
+byte *MidiMusicPlayer::resizeMidiBuffer(uint32 desiredSize) {
+ if (_midiData == nullptr) {
+ _midiData = (byte *)malloc(desiredSize);
+ _midiDataSize = desiredSize;
+ } else {
+ if (desiredSize > _midiDataSize) {
+ _midiData = (byte *)realloc(_midiData, desiredSize);
+ _midiDataSize = desiredSize;
+ }
+ }
+ return _midiData;
+}
+
+void MidiMusicPlayer::setVolume(int volume) {
+// _vm->_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, volume); TODO do we need this?
+ MidiPlayer::setVolume(volume);
+}
+
+} // End of namespace Dragons
diff --git a/engines/dragons/midimusicplayer.h b/engines/dragons/midimusicplayer.h
new file mode 100644
index 0000000000..4a57b10bae
--- /dev/null
+++ b/engines/dragons/midimusicplayer.h
@@ -0,0 +1,51 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+#ifndef DRAGONS_MIDIMUSICPLAYER_H
+#define DRAGONS_MIDIMUSICPLAYER_H
+
+#include "audio/midiplayer.h"
+#include "vabsound.h"
+
+namespace Dragons {
+
+class MidiMusicPlayer : public Audio::MidiPlayer {
+private:
+ VabSound *_musicVab;
+ uint32 _midiDataSize;
+public:
+ MidiMusicPlayer(VabSound *musicVab);
+ ~MidiMusicPlayer();
+
+ void setVolume(int volume) override;
+
+ void playSong(Common::SeekableReadStream *seqData);
+
+ // 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; }
+private:
+ byte *resizeMidiBuffer(uint32 desiredSize);
+};
+
+} // End of namespace Dragons
+
+#endif //DRAGONS_MIDIMUSICPLAYER_H
diff --git a/engines/dragons/minigame2.cpp b/engines/dragons/minigame2.cpp
index f45ef6bb25..e198b0e015 100644
--- a/engines/dragons/minigame2.cpp
+++ b/engines/dragons/minigame2.cpp
@@ -693,7 +693,7 @@ void Minigame2::run(int16 param_1, uint16 param_2, int16 param_3) {
_vm->fadeToBlack();
_vm->_fontManager->clearText();
- _vm->_sound->PauseCDMusic();
+ _vm->_sound->resumeMusic();
// DisableVSyncEvent();
_vm->_dragonINIResource->getRecord(0)->x = 0x91;
_vm->_dragonINIResource->getRecord(0)->y = 0x9b;
diff --git a/engines/dragons/minigame3.cpp b/engines/dragons/minigame3.cpp
index 5159ec1a28..6df42746ff 100644
--- a/engines/dragons/minigame3.cpp
+++ b/engines/dragons/minigame3.cpp
@@ -731,7 +731,7 @@ void Minigame3::run() {
_vm->_dragonINIResource->getRecord(0x178)->objectState2 = 0;
}
_vm->waitForFrames(0x3c * 2);
- _vm->_sound->PauseCDMusic();
+ _vm->_sound->resumeMusic();
_vm->fadeToBlack();
// fun_80017f28_noop();
// DAT_80093234 = DAT_80093234 + 1;
diff --git a/engines/dragons/module.mk b/engines/dragons/module.mk
index 5af8bbef9b..d87d67b15b 100644
--- a/engines/dragons/module.mk
+++ b/engines/dragons/module.mk
@@ -19,6 +19,7 @@ MODULE_OBJS := \
dragons.o \
font.o \
inventory.o \
+ midimusicplayer.o \
minigame1.o \
minigame2.o \
minigame3.o \
diff --git a/engines/dragons/scriptopcodes.cpp b/engines/dragons/scriptopcodes.cpp
index 9f1a794cd7..5c5dde41d2 100644
--- a/engines/dragons/scriptopcodes.cpp
+++ b/engines/dragons/scriptopcodes.cpp
@@ -477,10 +477,10 @@ void ScriptOpcodes::opActorLoadSequence(ScriptOpCall &scriptOpCall) {
}
void ScriptOpcodes::opPlayMusic(ScriptOpCall &scriptOpCall) {
- //byte *code = scriptOpCall._code;
- scriptOpCall._code += 4;
+ ARG_SKIP(2);
+ ARG_INT16(songNumber);
if (scriptOpCall._field8 == 0) {
- //TODO play music here.
+ _vm->_sound->playMusic(songNumber);
}
}
@@ -534,7 +534,7 @@ void ScriptOpcodes::opPreLoadSceneData(ScriptOpCall &scriptOpCall) {
ARG_INT16(field0);
ARG_INT16(sceneId);
- _vm->_sound->PauseCDMusic();
+ _vm->_sound->resumeMusic();
_vm->_isLoadingDialogAudio = true;
if (sceneId >= 2) {
@@ -547,7 +547,7 @@ void ScriptOpcodes::opPauseCurrentSpeechAndFetchNextDialog(ScriptOpCall &scriptO
ARG_UINT32(textIndex);
if (scriptOpCall._field8 == 0) {
- _vm->_sound->PauseCDMusic();
+ _vm->_sound->resumeMusic();
//The original starts seeking the CD-ROM here for the `textIndex` dialog but we don't need to do that.
}
}
@@ -907,7 +907,7 @@ void ScriptOpcodes::opLoadScene(ScriptOpCall &scriptOpCall) {
_vm->fadeToBlack();
_vm->clearSceneUpdateFunction();
- _vm->_sound->PauseCDMusic();
+ _vm->_sound->resumeMusic();
if (newSceneID != 0) {
_vm->_scene->_mapTransitionEffectSceneID = _vm->_scene->getSceneId();
diff --git a/engines/dragons/sound.cpp b/engines/dragons/sound.cpp
index 67d6508ab7..f2ab4d7782 100644
--- a/engines/dragons/sound.cpp
+++ b/engines/dragons/sound.cpp
@@ -79,6 +79,9 @@ void SoundManager::playSpeech(uint32 textIndex) {
return;
}
+ // Reduce music volume while playing dialog.
+ _midiPlayer->setVolume(_musicVolume / 2);
+
struct SpeechLocation speechLocation;
if (!getSpeechLocation(textIndex, &speechLocation)) {
return;
@@ -132,12 +135,14 @@ bool SoundManager::getSpeechLocation(uint32 talkId, struct SpeechLocation *locat
return foundId;
}
-void SoundManager::PauseCDMusic() {
- //TODO check PauseCDMusic() to see if we need any more logic.
+void SoundManager::resumeMusic() {
if (isSpeechPlaying()) {
_vm->_mixer->stopHandle(_speechHandle);
_vm->clearFlags(ENGINE_FLAG_8000);
}
+ if (_currentSong != -1) {
+ _midiPlayer->resume();
+ }
}
SoundManager::PSXAudioTrack::PSXAudioTrack() {
@@ -262,6 +267,7 @@ SoundManager::SoundManager(DragonsEngine *vm, BigfileArchive *bigFileArchive, Dr
_bigFileArchive(bigFileArchive),
_dragonRMS(dragonRMS) {
_dat_8006bb60_sound_related = 0;
+ _currentSong = -1;
bool allSoundIsMuted = false;
if (ConfMan.hasKey("mute")) {
@@ -284,7 +290,9 @@ SoundManager::SoundManager(DragonsEngine *vm, BigfileArchive *bigFileArchive, Dr
}
SomeInitSound_FUN_8003f64c();
- loadMusAndGlob();
+ initVabData();
+ _midiPlayer = new MidiMusicPlayer(_vabMusx);
+ _midiPlayer->setVolume(_musicVolume);
}
SoundManager::~SoundManager() {
@@ -294,7 +302,11 @@ SoundManager::~SoundManager() {
stopAllVoices();
+ _midiPlayer->stop();
+
+ delete _midiPlayer;
delete _vabMusx;
+ delete _vabMsf;
delete _vabGlob;
}
@@ -360,8 +372,9 @@ void SoundManager::SomeInitSound_FUN_8003f64c() {
_soundArr[1612] = 0x0b;
}
-void SoundManager::loadMusAndGlob() {
+void SoundManager::initVabData() {
_vabMusx = loadVab("musx.vh", "musx.vb");
+ _vabMsf = loadVab("musx.vh", "musx.vb");
_vabGlob = loadVab("glob.vh", "glob.vb");
}
@@ -402,7 +415,7 @@ void SoundManager::playSound(uint16 soundId, uint16 volumeId) {
volume = _soundArr[volumeId];
_soundArr[volumeId] = _soundArr[volumeId] | 0x40u; // Set bit 0x40
- VabSound *vabSound = ((soundId & 0x8000u) != 0) ? _vabGlob : _vabMusx;
+ VabSound *vabSound = ((soundId & 0x8000u) != 0) ? _vabGlob : _vabMsf;
// TODO: CdVolume!
int cdVolume = 1;
@@ -452,8 +465,8 @@ void SoundManager::loadMsf(uint32 sceneId) {
stopAllVoices();
- delete _vabMusx;
- _vabMusx = new VabSound(msfStream, _vm);
+ delete _vabMsf;
+ _vabMsf = new VabSound(msfStream, _vm);
}
}
@@ -491,4 +504,25 @@ void SoundManager::stopAllVoices() {
}
}
+void SoundManager::playMusic(int16 song) {
+ char sceneName[5] = "nnnn";
+ char filename[12] = "xxxxznn.msq";
+
+ if (_currentSong == song) {
+ return;
+ }
+
+ _currentSong = song;
+
+ memcpy(sceneName, _vm->_dragonRMS->getSceneName(_vm->getCurrentSceneId()), 4);
+ snprintf(filename, 12, "%sz%02d.msq", sceneName, song);
+ debug("Load music file %s", filename);
+
+ uint32 dataSize;
+ byte *seqData = _bigFileArchive->load(filename, dataSize);
+ Common::MemoryReadStream *seq = new Common::MemoryReadStream(seqData, dataSize, DisposeAfterUse::YES);
+ _midiPlayer->playSong(seq);
+ delete seq;
+}
+
} // End of namespace Dragons
diff --git a/engines/dragons/sound.h b/engines/dragons/sound.h
index fe0bec174a..b01ad87387 100644
--- a/engines/dragons/sound.h
+++ b/engines/dragons/sound.h
@@ -25,6 +25,7 @@
#include "common/scummsys.h"
#include "audio/mixer.h"
#include "audio/audiostream.h"
+#include "midimusicplayer.h"
namespace Dragons {
@@ -54,9 +55,10 @@ public:
void loadMsf(uint32 sceneId);
void playOrStopSound(uint16 soundId);
+ void playMusic(int16 song);
void playSpeech(uint32 textIndex);
bool isSpeechPlaying();
- void PauseCDMusic();
+ void resumeMusic();
public:
uint16 _dat_8006bb60_sound_related;
@@ -74,15 +76,19 @@ private:
uint8 _soundArr[0x780];
VabSound* _vabMusx;
+ VabSound* _vabMsf;
VabSound* _vabGlob;
Audio::SoundHandle _speechHandle;
+ MidiMusicPlayer *_midiPlayer;
+
Voice _voice[NUM_VOICES];
+ int16 _currentSong;
private:
void SomeInitSound_FUN_8003f64c();
- void loadMusAndGlob();
+ void initVabData();
void playSound(uint16 soundId, uint16 i);
diff --git a/engines/dragons/specialopcodes.cpp b/engines/dragons/specialopcodes.cpp
index 156e89eef9..09175f6d42 100644
--- a/engines/dragons/specialopcodes.cpp
+++ b/engines/dragons/specialopcodes.cpp
@@ -330,7 +330,7 @@ void SpecialOpcodes::spcLadyOfTheLakeCapturedSceneLogic() {
void SpecialOpcodes::spcStopLadyOfTheLakeCapturedSceneLogic() {
_vm->clearSceneUpdateFunction();
- _vm->_sound->PauseCDMusic();
+ _vm->_sound->resumeMusic();
if ((_dat_80083148 != 0) || (_uint16_t_80083154 != 0)) {
//TODO FUN_8001ac5c((uint)_dat_80083148, (uint)DAT_80083150, (uint)_uint16_t_80083154, (uint)DAT_80083158);
}
diff --git a/engines/dragons/talk.cpp b/engines/dragons/talk.cpp
index 2a3fdb7aa6..aba7ca2337 100644
--- a/engines/dragons/talk.cpp
+++ b/engines/dragons/talk.cpp
@@ -427,7 +427,7 @@ uint8 Talk::conversation_related_maybe(uint16 *dialogText, uint16 x, uint16 y, u
}
if (param_5 != 0) {
if (_vm->isFlagSet(ENGINE_FLAG_8000)) {
- _vm->_sound->PauseCDMusic();
+ _vm->_sound->resumeMusic();
}
if (isFlag8Set) {
_vm->setFlags(ENGINE_FLAG_8);
Commit: 34c5d3f2a22e06cd84179421c1a587b6a6559efd
https://github.com/scummvm/scummvm/commit/34c5d3f2a22e06cd84179421c1a587b6a6559efd
Author: Eric Fry (yuv422 at users.noreply.github.com)
Date: 2020-05-21T18:06:13+10:00
Commit Message:
DRAGONS: Moved midi data size init to initializer list
Changed paths:
engines/dragons/midimusicplayer.cpp
diff --git a/engines/dragons/midimusicplayer.cpp b/engines/dragons/midimusicplayer.cpp
index 3034cb6c29..e4342de516 100644
--- a/engines/dragons/midimusicplayer.cpp
+++ b/engines/dragons/midimusicplayer.cpp
@@ -26,9 +26,8 @@
namespace Dragons {
-MidiMusicPlayer::MidiMusicPlayer(VabSound *musicVab): _musicVab(musicVab) {
+MidiMusicPlayer::MidiMusicPlayer(VabSound *musicVab): _musicVab(musicVab), _midiDataSize(0) {
_midiData = nullptr;
- _midiDataSize = 0;
MidiPlayer::createDriver();
int ret = _driver->open();
More information about the Scummvm-git-logs
mailing list