SCUMM HE: Use Miles AdLib driver

This commit is contained in:
nukeykt 2017-12-23 23:01:29 +09:00 committed by Eugene Sandulenko
parent bdda3447a3
commit e5bfead345
10 changed files with 350 additions and 3 deletions

View file

@ -1035,6 +1035,15 @@ void MidiDriver_Miles_AdLib::pitchBendChange(byte midiChannel, byte parameter1,
return; return;
} }
_midiChannels[midiChannel].currentPitchBender = parameter1 | (parameter2 << 7); _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) { void MidiDriver_Miles_AdLib::setRegister(int reg, int value) {

View file

@ -772,7 +772,7 @@ puttmoon Putt-Putt Goes to the Moon
9c92eeaf517a31b7221ec2546ab669fd -1 en Windows HE 70 - - khalek 9c92eeaf517a31b7221ec2546ab669fd -1 en Windows HE 70 - - khalek
3c4c471342bd95505a42334367d8f127 12161 ru Windows HE 70 - - sev 3c4c471342bd95505a42334367d8f127 12161 ru Windows HE 70 - - sev
aa6a91b7f6f119d1b7b1f2a4c9e24d59 6233 en DOS - Demo - aa6a91b7f6f119d1b7b1f2a4c9e24d59 6233 en DOS Demo Demo -
4af4a6b248103c1fe9edef619677f540 -1 en Mac - Demo - khalek 4af4a6b248103c1fe9edef619677f540 -1 en Mac - Demo - khalek
9c143c5905055d5df7a0f014ab379aee -1 en Windows HE 70 Demo - khalek 9c143c5905055d5df7a0f014ab379aee -1 en Windows HE 70 Demo - khalek

View file

@ -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)}, {"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", "", 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)}, {"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)}, {"puttputt", "HE 60", 0, GID_HEGAME, 6, 60, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK, GUIO1(GUIO_NOLAUNCHLOAD)},

View file

@ -765,6 +765,10 @@ void SoundHE::playHESound(int soundID, int heOffset, int heChannel, int heFlags,
_vm->_imuse->stopSound(_currentMusic); _vm->_imuse->stopSound(_currentMusic);
_currentMusic = soundID; _currentMusic = soundID;
_vm->_imuse->startSoundWithNoteOffset(soundID, heOffset); _vm->_imuse->startSoundWithNoteOffset(soundID, heOffset);
} else if (_vm->_musicEngine) {
_vm->_musicEngine->stopSound(_currentMusic);
_currentMusic = soundID;
_vm->_musicEngine->startSoundWithTrackID(soundID, heOffset);
} }
} }
} }

View file

@ -38,6 +38,7 @@ MODULE_OBJS := \
palette.o \ palette.o \
players/player_ad.o \ players/player_ad.o \
players/player_apple2.o \ players/player_apple2.o \
players/player_he.o \
players/player_mac.o \ players/player_mac.o \
players/player_mod.o \ players/player_mod.o \
players/player_nes.o \ players/player_nes.o \

View file

@ -54,6 +54,13 @@ public:
*/ */
virtual void startSound(int sound) = 0; 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. * Stop playing the sound with the given id.
* @param sound the sound to stop * @param sound the sound to stop

View file

@ -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

View file

@ -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

View file

@ -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! DO NOT EDIT MANUALLY!
*/ */
@ -496,7 +496,7 @@ static const MD5Table md5table[] = {
{ "a9543ef0d79bcb47cd76ec197ad0a967", "puttmoon", "", "", -1, Common::EN_ANY, Common::kPlatform3DO }, { "a9543ef0d79bcb47cd76ec197ad0a967", "puttmoon", "", "", -1, Common::EN_ANY, Common::kPlatform3DO },
{ "a99c39ba65b6086be28aef576da69595", "spyozon", "", "Demo", -1, Common::FR_FRA, Common::kPlatformWindows }, { "a99c39ba65b6086be28aef576da69595", "spyozon", "", "Demo", -1, Common::FR_FRA, Common::kPlatformWindows },
{ "a9f2f04b1ecaab9495b59befffe9bf88", "pajama3", "", "Demo", -1, Common::EN_USA, Common::kPlatformUnknown }, { "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 }, { "aa7a07d94ae853f6460be4ce0a1bf530", "monkey", "EGA", "EGA", -1, Common::FR_FRA, Common::kPlatformDOS },
{ "aa81aa6d5545ce172fdba81f2e2f9d36", "puttzoo", "", "Demo", -1, Common::NL_NLD, Common::kPlatformWindows }, { "aa81aa6d5545ce172fdba81f2e2f9d36", "puttzoo", "", "Demo", -1, Common::NL_NLD, Common::kPlatformWindows },
{ "aa8a0cb65f3afbbe2c14c3f9f92775a3", "monkey", "CD", "CD", 8955, Common::FR_FRA, Common::kPlatformDOS }, { "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 }, { "ff05c07990061d97647f059c48c1d05a", "zak", "V2", "V2", -1, Common::DE_DEU, Common::kPlatformAtariST },
{ 0, 0, 0, 0, 0, Common::UNK_LANG, Common::kPlatformUnknown } { 0, 0, 0, 0, 0, Common::UNK_LANG, Common::kPlatformUnknown }
}; };

View file

@ -64,6 +64,7 @@
#include "scumm/players/player_v3m.h" #include "scumm/players/player_v3m.h"
#include "scumm/players/player_v4a.h" #include "scumm/players/player_v4a.h"
#include "scumm/players/player_v5m.h" #include "scumm/players/player_v5m.h"
#include "scumm/players/player_he.h"
#include "scumm/resource.h" #include "scumm/resource.h"
#include "scumm/he/resource_he.h" #include "scumm/he/resource_he.h"
#include "scumm/he/moonbase/moonbase.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 // support this with the Player_AD code at the moment. The reason here
// is that multi MIDI is supported internally by our iMuse output. // is that multi MIDI is supported internally by our iMuse output.
_musicEngine = new Player_AD(this); _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) { } else if (_game.version >= 3 && _game.heversion <= 62) {
MidiDriver *nativeMidiDriver = 0; MidiDriver *nativeMidiDriver = 0;
MidiDriver *adlibMidiDriver = 0; MidiDriver *adlibMidiDriver = 0;