aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornukeykt2017-12-23 23:01:29 +0900
committerEugene Sandulenko2018-02-04 12:56:06 +0100
commite5bfead3458661140d17863ffe33af5f71638387 (patch)
tree797c71145c22d959e99a019ed51a07ea03c19d99
parentbdda3447a3c0eebc31ac3202699a397ca4122ddf (diff)
downloadscummvm-rg350-e5bfead3458661140d17863ffe33af5f71638387.tar.gz
scummvm-rg350-e5bfead3458661140d17863ffe33af5f71638387.tar.bz2
scummvm-rg350-e5bfead3458661140d17863ffe33af5f71638387.zip
SCUMM HE: Use Miles AdLib driver
-rw-r--r--audio/miles_adlib.cpp9
-rw-r--r--devtools/scumm-md5.txt2
-rw-r--r--engines/scumm/detection_tables.h1
-rw-r--r--engines/scumm/he/sound_he.cpp4
-rw-r--r--engines/scumm/module.mk1
-rw-r--r--engines/scumm/music.h7
-rw-r--r--engines/scumm/players/player_he.cpp243
-rw-r--r--engines/scumm/players/player_he.h76
-rw-r--r--engines/scumm/scumm-md5.h5
-rw-r--r--engines/scumm/scumm.cpp5
10 files changed, 350 insertions, 3 deletions
diff --git a/audio/miles_adlib.cpp b/audio/miles_adlib.cpp
index 790e38932d..4bdb770323 100644
--- a/audio/miles_adlib.cpp
+++ b/audio/miles_adlib.cpp
@@ -1035,6 +1035,15 @@ void MidiDriver_Miles_AdLib::pitchBendChange(byte midiChannel, byte parameter1,
return;
}
_midiChannels[midiChannel].currentPitchBender = parameter1 | (parameter2 << 7);
+ for (byte virtualFmVoice = 0; virtualFmVoice < _modeVirtualFmVoicesCount; virtualFmVoice++) {
+ if (_virtualFmVoices[virtualFmVoice].inUse) {
+ // used
+ if (_virtualFmVoices[virtualFmVoice].actualMidiChannel == midiChannel) {
+ // by our current MIDI channel -> update
+ updatePhysicalFmVoice(virtualFmVoice, true, kMilesAdLibUpdateFlags_Reg_A0);
+ }
+ }
+ }
}
void MidiDriver_Miles_AdLib::setRegister(int reg, int value) {
diff --git a/devtools/scumm-md5.txt b/devtools/scumm-md5.txt
index ab32653da4..7e7d0accb7 100644
--- a/devtools/scumm-md5.txt
+++ b/devtools/scumm-md5.txt
@@ -772,7 +772,7 @@ puttmoon Putt-Putt Goes to the Moon
9c92eeaf517a31b7221ec2546ab669fd -1 en Windows HE 70 - - khalek
3c4c471342bd95505a42334367d8f127 12161 ru Windows HE 70 - - sev
- aa6a91b7f6f119d1b7b1f2a4c9e24d59 6233 en DOS - Demo -
+ aa6a91b7f6f119d1b7b1f2a4c9e24d59 6233 en DOS Demo Demo -
4af4a6b248103c1fe9edef619677f540 -1 en Mac - Demo - khalek
9c143c5905055d5df7a0f014ab379aee -1 en Windows HE 70 Demo - khalek
diff --git a/engines/scumm/detection_tables.h b/engines/scumm/detection_tables.h
index 65891e0b0d..ce8eecfd4d 100644
--- a/engines/scumm/detection_tables.h
+++ b/engines/scumm/detection_tables.h
@@ -284,6 +284,7 @@ static const GameSettings gameVariantsTable[] = {
{"fbear", "HE 70", 0, GID_FBEAR, 6, 70, MDT_NONE, GF_USE_KEY, Common::kPlatformWindows, GUIO2(GUIO_NOLAUNCHLOAD, GUIO_NOMIDI)},
{"puttmoon", "", 0, GID_PUTTMOON, 6, 62, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK, GUIO1(GUIO_NOLAUNCHLOAD)},
+ {"puttmoon", "Demo", 0, GID_HEGAME, 6, 62, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK, GUIO1(GUIO_NOLAUNCHLOAD)},
{"puttmoon", "HE 70", 0, GID_PUTTMOON, 6, 70, MDT_NONE, GF_USE_KEY, Common::kPlatformWindows, GUIO2(GUIO_NOLAUNCHLOAD, GUIO_NOMIDI)},
{"puttputt", "HE 60", 0, GID_HEGAME, 6, 60, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK, GUIO1(GUIO_NOLAUNCHLOAD)},
diff --git a/engines/scumm/he/sound_he.cpp b/engines/scumm/he/sound_he.cpp
index 9da3641064..07a81f5310 100644
--- a/engines/scumm/he/sound_he.cpp
+++ b/engines/scumm/he/sound_he.cpp
@@ -765,6 +765,10 @@ void SoundHE::playHESound(int soundID, int heOffset, int heChannel, int heFlags,
_vm->_imuse->stopSound(_currentMusic);
_currentMusic = soundID;
_vm->_imuse->startSoundWithNoteOffset(soundID, heOffset);
+ } else if (_vm->_musicEngine) {
+ _vm->_musicEngine->stopSound(_currentMusic);
+ _currentMusic = soundID;
+ _vm->_musicEngine->startSoundWithTrackID(soundID, heOffset);
}
}
}
diff --git a/engines/scumm/module.mk b/engines/scumm/module.mk
index fee61ec29f..f5ba4bac2b 100644
--- a/engines/scumm/module.mk
+++ b/engines/scumm/module.mk
@@ -38,6 +38,7 @@ MODULE_OBJS := \
palette.o \
players/player_ad.o \
players/player_apple2.o \
+ players/player_he.o \
players/player_mac.o \
players/player_mod.o \
players/player_nes.o \
diff --git a/engines/scumm/music.h b/engines/scumm/music.h
index 9404ce7af3..06f45fe0e0 100644
--- a/engines/scumm/music.h
+++ b/engines/scumm/music.h
@@ -55,6 +55,13 @@ public:
virtual void startSound(int sound) = 0;
/**
+ * Start playing the sound with the given id and track id.
+ * @param sound the sound to start
+ * @param track the track to start
+ */
+ virtual void startSoundWithTrackID(int sound, int track) { startSound(sound); }
+
+ /**
* Stop playing the sound with the given id.
* @param sound the sound to stop
*/
diff --git a/engines/scumm/players/player_he.cpp b/engines/scumm/players/player_he.cpp
new file mode 100644
index 0000000000..163f4f13f6
--- /dev/null
+++ b/engines/scumm/players/player_he.cpp
@@ -0,0 +1,243 @@
+/* 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.
+ *
+ */
+
+#ifdef ENABLE_HE
+
+#include "scumm/players/player_he.h"
+#include "scumm/scumm.h"
+#include "scumm/file.h"
+#include "audio/miles.h"
+#include "audio/midiparser.h"
+#include "audio/mixer.h"
+#include "common/memstream.h"
+
+namespace Scumm {
+Player_HE::Player_HE(ScummEngine *scumm) :
+ _vm(scumm),
+ _currentMusic(-1),
+ _bank(NULL),
+ _parser(NULL),
+ _midi(NULL),
+ _masterVolume(256) {
+
+ for (int chan = 0; chan < 16; chan++)
+ _channelVolume[chan] = 127;
+
+ loadAdLibBank();
+
+ Common::MemoryReadStream *bankStream = new Common::MemoryReadStream(_bank, _bankSize);
+
+ _midi = Audio::MidiDriver_Miles_AdLib_create("", "", bankStream);
+ if (!_midi) {
+ error("Player_HE::Player_HE: could not create midi driver");
+ }
+ if (_midi->open() != 0) {
+ error("Player_HE::Player_HE: could not open midi driver");
+ }
+}
+
+Player_HE::~Player_HE() {
+ if (_parser) {
+ _parser->stopPlaying();
+ delete _parser;
+ _parser = NULL;
+ }
+ if (_midi) {
+ _midi->setTimerCallback(0, 0);
+ _midi->close();
+ delete _midi;
+ _midi = NULL;
+ }
+ if (_bank) {
+ free(_bank);
+ }
+}
+
+void Player_HE::setMusicVolume(int vol) {
+ _masterVolume = vol;
+ for (int chan = 0; chan < 16; chan++)
+ {
+ byte volume = (_channelVolume[chan] * vol) / 256;
+ if (_midi)
+ _midi->send(0x07b0 | chan | (volume << 16));
+ }
+}
+
+void Player_HE::onTimer(void *data) {
+ Player_HE *player = (Player_HE*)data;
+ Common::StackLock lock(player->_mutex);
+ if (player->_parser)
+ player->_parser->onTimer();
+}
+
+void Player_HE::startSoundWithTrackID(int sound, int track) {
+ Common::StackLock lock(_mutex);
+ byte *ptr = _vm->getResourceAddress(rtSound, sound);
+ if (ptr == NULL)
+ return;
+
+ if (_parser) {
+ _parser->stopPlaying();
+ delete _parser;
+ }
+ _parser = MidiParser::createParser_XMIDI();
+ _parser->setMidiDriver(this);
+ _parser->loadMusic(ptr + 40, 0);
+ _parser->setTrack(track);
+ _parser->setTimerRate(_midi->getBaseTempo());
+ _midi->setTimerCallback(this, &Player_HE::onTimer);
+
+ _currentMusic = sound;
+}
+
+void Player_HE::stopSound(int sound) {
+ Common::StackLock lock(_mutex);
+ if (!_parser || _currentMusic != sound)
+ return;
+ _parser->stopPlaying();
+ delete _parser;
+ _parser = NULL;
+}
+
+void Player_HE::stopAllSounds() {
+ Common::StackLock lock(_mutex);
+ if (!_parser)
+ return;
+ _parser->stopPlaying();
+ delete _parser;
+ _parser = NULL;
+}
+
+int Player_HE::getSoundStatus(int sound) const {
+ Common::StackLock lock(_mutex);
+ return (_parser && _currentMusic == sound) ? _parser->isPlaying() : 0;
+}
+
+int Player_HE::getMusicTimer() {
+ Common::StackLock lock(_mutex);
+ return _parser ? _parser->getTick() : 0;
+}
+
+void Player_HE::loadAdLibBank() {
+ ScummFile file;
+ Common::String drvName;
+ char entryName[14];
+ uint32 tag, entrySize, fileSize;
+ Common::String bankName;
+
+ if (_vm->_game.id == GID_PUTTMOON) {
+ // Use GM bank
+ bankName = "FAT.AD";
+ } else {
+ // Use MT32-like bank
+ bankName = "MIDPAK.AD";
+ }
+
+ const char *ptr = strchr(_vm->_filenamePattern.pattern, '.');
+ if (ptr) {
+ drvName = Common::String(_vm->_filenamePattern.pattern, ptr - _vm->_filenamePattern.pattern + 1);
+ } else {
+ drvName = _vm->_filenamePattern.pattern;
+ drvName += '.';
+ }
+
+ drvName += "drv";
+
+ if (!file.open(drvName))
+ error("Player_HE::loadAdLibBank(): could not open %s", drvName.c_str());
+
+ uint32 size = (uint32)file.size();
+
+ for (uint32 offset = 0; offset < size;) {
+ file.seek(offset, SEEK_SET);
+ if (size - offset < 31)
+ error("Player_HE::loadAdLibBank(): unexpected end of file");
+
+ tag = file.readUint32BE();
+ entrySize = file.readUint32BE();
+ if (size - offset < entrySize)
+ error("Player_HE::loadAdLibBank(): unexpected end of file");
+ fileSize = entrySize - 31;
+ file.read(entryName, 13);
+ entryName[13] = 0;
+
+ if (tag != MKTAG('F', 'I', 'L', 'E'))
+ error("Player_HE::loadAdLibBank(): unknown entry format");
+
+ if (entryName == bankName) {
+ _bank = (byte*)malloc(fileSize);
+ file.read(_bank, fileSize);
+ _bankSize = fileSize;
+ return;
+ }
+
+ offset += entrySize;
+ }
+ error("Player_HE::loadAdLibBank(): could not find %s entry", bankName.c_str());
+}
+
+int Player_HE::open() {
+ if (_midi)
+ return _midi->open();
+ return 0;
+}
+
+bool Player_HE::isOpen() const {
+ if (_midi)
+ return _midi->isOpen();
+ return false;
+}
+
+void Player_HE::close() {
+ if (_midi)
+ _midi->close();
+}
+
+void Player_HE::setTimerCallback(void *timerParam, Common::TimerManager::TimerProc timerProc) {
+ if (_midi)
+ _midi->setTimerCallback(timerParam, timerProc);
+}
+
+uint32 Player_HE::getBaseTempo() {
+ if (_midi)
+ return _midi->getBaseTempo();
+ return 0;
+}
+
+void Player_HE::send(uint32 b) {
+ byte chan = b & 0x0f;
+ byte cmd = b & 0xf0;
+ byte op1 = (b >> 8) & 0x7f;
+ byte op2 = (b >> 16) & 0x7f;
+ if (cmd == 0xb0 && op1 == 0x07)
+ {
+ _channelVolume[chan] = op2;
+ op2 = (op2 * _masterVolume) / 256;
+ b = (b & 0xffff) | (op2 << 16);
+ }
+ if (_midi)
+ _midi->send(b);
+}
+
+}
+
+#endif
diff --git a/engines/scumm/players/player_he.h b/engines/scumm/players/player_he.h
new file mode 100644
index 0000000000..1405a056c9
--- /dev/null
+++ b/engines/scumm/players/player_he.h
@@ -0,0 +1,76 @@
+/* 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 SCUMM_PLAYERS_PLAYER_HE_H
+#define SCUMM_PLAYERS_PLAYER_HE_H
+
+#include "scumm/music.h"
+#include "audio/mixer.h"
+#include "audio/mididrv.h"
+#include "common/mutex.h"
+
+class MidiParser;
+
+#ifdef ENABLE_HE
+
+namespace Scumm {
+class ScummEngine;
+
+class Player_HE : public MusicEngine, public MidiDriver {
+public:
+ Player_HE(ScummEngine *scumm);
+ ~Player_HE();
+ void setMusicVolume(int vol);
+ void startSound(int sound) { startSoundWithTrackID(sound, 0); }
+ void startSoundWithTrackID(int sound, int track);
+ void stopSound(int sound);
+ void stopAllSounds();
+ int getSoundStatus(int sound) const;
+ int getMusicTimer();
+
+ int open();
+ bool isOpen() const;
+ void close();
+ void setTimerCallback(void *timerParam, Common::TimerManager::TimerProc timerProc);
+ uint32 getBaseTempo();
+ MidiChannel *allocateChannel() { return NULL; };
+ MidiChannel *getPercussionChannel() { return NULL; };
+ void send(uint32 b);
+
+private:
+ ScummEngine *_vm;
+ MidiParser *_parser;
+ MidiDriver *_midi;
+ Common::Mutex _mutex;
+ byte *_bank;
+ int _bankSize;
+ int _currentMusic;
+ int _masterVolume;
+ byte _channelVolume[16];
+ static void onTimer(void *data);
+ void loadAdLibBank();
+};
+}
+
+#endif
+
+#endif
diff --git a/engines/scumm/scumm-md5.h b/engines/scumm/scumm-md5.h
index 50ed673a05..0afa5f53d7 100644
--- a/engines/scumm/scumm-md5.h
+++ b/engines/scumm/scumm-md5.h
@@ -1,5 +1,5 @@
/*
- This file was generated by the md5table tool on Fri Dec 22 04:43:47 2017
+ This file was generated by the md5table tool on Thu Feb 01 01:05:11 2018
DO NOT EDIT MANUALLY!
*/
@@ -496,7 +496,7 @@ static const MD5Table md5table[] = {
{ "a9543ef0d79bcb47cd76ec197ad0a967", "puttmoon", "", "", -1, Common::EN_ANY, Common::kPlatform3DO },
{ "a99c39ba65b6086be28aef576da69595", "spyozon", "", "Demo", -1, Common::FR_FRA, Common::kPlatformWindows },
{ "a9f2f04b1ecaab9495b59befffe9bf88", "pajama3", "", "Demo", -1, Common::EN_USA, Common::kPlatformUnknown },
- { "aa6a91b7f6f119d1b7b1f2a4c9e24d59", "puttmoon", "", "Demo", 6233, Common::EN_ANY, Common::kPlatformDOS },
+ { "aa6a91b7f6f119d1b7b1f2a4c9e24d59", "puttmoon", "Demo", "Demo", 6233, Common::EN_ANY, Common::kPlatformDOS },
{ "aa7a07d94ae853f6460be4ce0a1bf530", "monkey", "EGA", "EGA", -1, Common::FR_FRA, Common::kPlatformDOS },
{ "aa81aa6d5545ce172fdba81f2e2f9d36", "puttzoo", "", "Demo", -1, Common::NL_NLD, Common::kPlatformWindows },
{ "aa8a0cb65f3afbbe2c14c3f9f92775a3", "monkey", "CD", "CD", 8955, Common::FR_FRA, Common::kPlatformDOS },
@@ -711,3 +711,4 @@ static const MD5Table md5table[] = {
{ "ff05c07990061d97647f059c48c1d05a", "zak", "V2", "V2", -1, Common::DE_DEU, Common::kPlatformAtariST },
{ 0, 0, 0, 0, 0, Common::UNK_LANG, Common::kPlatformUnknown }
};
+
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index 77d82c88a6..fc64df4a1a 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -64,6 +64,7 @@
#include "scumm/players/player_v3m.h"
#include "scumm/players/player_v4a.h"
#include "scumm/players/player_v5m.h"
+#include "scumm/players/player_he.h"
#include "scumm/resource.h"
#include "scumm/he/resource_he.h"
#include "scumm/he/moonbase/moonbase.h"
@@ -1954,6 +1955,10 @@ void ScummEngine::setupMusic(int midi) {
// support this with the Player_AD code at the moment. The reason here
// is that multi MIDI is supported internally by our iMuse output.
_musicEngine = new Player_AD(this);
+#ifdef ENABLE_HE
+ } else if (_game.platform == Common::kPlatformDOS && _sound->_musicType == MDT_ADLIB && _game.heversion >= 60) {
+ _musicEngine = new Player_HE(this);
+#endif
} else if (_game.version >= 3 && _game.heversion <= 62) {
MidiDriver *nativeMidiDriver = 0;
MidiDriver *adlibMidiDriver = 0;