SCUMM HE: Use Miles AdLib driver
This commit is contained in:
parent
bdda3447a3
commit
e5bfead345
10 changed files with 350 additions and 3 deletions
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)},
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -54,6 +54,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
|
||||
|
|
243
engines/scumm/players/player_he.cpp
Normal file
243
engines/scumm/players/player_he.cpp
Normal 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
|
76
engines/scumm/players/player_he.h
Normal file
76
engines/scumm/players/player_he.h
Normal 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
|
|
@ -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 }
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue