[Scummvm-cvs-logs] scummvm master -> f80cc4a84d9a1ff4e761438164e94425b4239908

m-kiewitz m_kiewitz at users.sourceforge.net
Sat May 30 01:49:23 CEST 2015


This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
f80cc4a84d SHERLOCK: add (unfinished) adlib driver


Commit: f80cc4a84d9a1ff4e761438164e94425b4239908
    https://github.com/scummvm/scummvm/commit/f80cc4a84d9a1ff4e761438164e94425b4239908
Author: Martin Kiewitz (m_kiewitz at users.sourceforge.net)
Date: 2015-05-30T01:48:30+02:00

Commit Message:
SHERLOCK: add (unfinished) adlib driver

Changed paths:
  A engines/sherlock/scalpel/drivers/adlib.cpp
  A engines/sherlock/scalpel/drivers/mididriver.h
    engines/sherlock/music.cpp
    engines/sherlock/music.h



diff --git a/engines/sherlock/music.cpp b/engines/sherlock/music.cpp
index c1aebda..ed047f6 100644
--- a/engines/sherlock/music.cpp
+++ b/engines/sherlock/music.cpp
@@ -23,11 +23,14 @@
 #include "common/config-manager.h"
 #include "sherlock/sherlock.h"
 #include "sherlock/music.h"
+#include "sherlock/scalpel/drivers/mididriver.h"
 
 namespace Sherlock {
 
 #define NUM_SONGS 45
 
+#define USE_SCI_MIDI_PLAYER 1
+
 /* This tells which song to play in each room, 0 = no song played */
 static const char ROOM_SONG[62] = {
 	 0, 20, 43,  6, 11,  2,  8, 15,  6, 28,
@@ -59,7 +62,7 @@ MidiParser_SH::MidiParser_SH() {
 }
 
 void MidiParser_SH::parseNextEvent(EventInfo &info) {
-	warning("parseNextEvent");
+//	warning("parseNextEvent");
 
 	// An attempt to remap MT32 instruments to GMIDI. Only partially successful, it still
 	// does not sound even close to the real MT32. Oddly enough, on the actual hardware MT32
@@ -88,13 +91,15 @@ void MidiParser_SH::parseNextEvent(EventInfo &info) {
 	info.delta = 0;
 
 	info.event = *_position._playPos++;
-	warning("Event %x", info.event);
+	//warning("Event %x", info.event);
 	_position._runningStatus = info.event;
 
 	switch (info.command()) {
-	case 0xC: {
+	case 0xC: { // program change
 		int idx = *_position._playPos++;
-		info.basic.param1 = mt32Map[idx & 0x7f]; // remap MT32 to GM
+		info.basic.param1 = idx & 0x7f;
+		// don't do this here, it breaks adlib
+		//info.basic.param1 = mt32Map[idx & 0x7f]; // remap MT32 to GM
 		info.basic.param2 = 0;
 		}
 		break;
@@ -160,14 +165,12 @@ bool MidiParser_SH::loadMusic(byte *data, uint32 size) {
 	warning("loadMusic");
 	unloadMusic();
 
-	byte *pos = data;
+	byte  *headerPtr  = data;
+	byte  *pos        = data;
+	uint16 headerSize = READ_LE_UINT16(headerPtr);
+	assert(headerSize == 0x7F);
 
-	if (memcmp("            ", pos, 12)) {
-		warning("Expected header not found in music file");
-		return false;
-	}
-	pos += 12;
-	byte headerSize = *pos;
+	// Skip over header
 	pos += headerSize;
 
 	_lastEvent = 0;
@@ -190,16 +193,49 @@ Music::Music(SherlockEngine *vm, Audio::Mixer *mixer) : _vm(vm), _mixer(mixer) {
 		_vm->_res->addToCache("MUSIC.LIB");
 
 	MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM);
-	_driver = MidiDriver::createMidi(dev);
-	assert(_driver);
 
-	int ret = _driver->open();
-	if (ret == 0) {
-		_driver->sendGMReset();
-		_driver->setTimerCallback(&_midiParser, &_midiParser.timerCallback);
+	_musicType = MidiDriver::getMusicType(dev);
+
+#if USE_SCI_MIDI_PLAYER
+	_pMidiDrv = NULL;
+#endif
+	_driver = NULL;
+
+	switch (_musicType) {
+	case MT_ADLIB:
+#if USE_SCI_MIDI_PLAYER
+		_pMidiDrv = MidiPlayer_AdLib_create();
+#else
+		_driver = MidiDriver_AdLib_create();
+#endif
+		break;
+	default:
+		_driver = MidiDriver::createMidi(dev);
+		break;
+	}
+#if USE_SCI_MIDI_PLAYER
+	if (_pMidiDrv) {
+		assert(_pMidiDrv);
+		int ret = _pMidiDrv->open();
+		if (ret == 0) {
+			_pMidiDrv->setTimerCallback(&_midiParser, &_midiParser.timerCallback);
+		}
+		_midiParser.setMidiDriver(_pMidiDrv);
+		_midiParser.setTimerRate(_pMidiDrv->getBaseTempo());
+	}
+#endif
+
+	if (_driver) {
+		assert(_driver);
+
+		int ret = _driver->open();
+		if (ret == 0) {
+			_driver->sendGMReset();
+			_driver->setTimerCallback(&_midiParser, &_midiParser.timerCallback);
+		}
+		_midiParser.setMidiDriver(_driver);
+		_midiParser.setTimerRate(_driver->getBaseTempo());
 	}
-	_midiParser.setMidiDriver(_driver);
-	_midiParser.setTimerRate(_driver->getBaseTempo());
 
 	_musicPlaying = false;
 	_musicOn = true;
@@ -248,17 +284,49 @@ bool Music::playMusic(const Common::String &name) {
 	Common::SeekableReadStream *stream = _vm->_res->load(name, "MUSIC.LIB");
 
 	byte *data = new byte[stream->size()];
-	byte *ptr = data;
+	int32 dataSize = stream->size();
+	assert(data);
+
+	stream->read(data, dataSize);
 
-	stream->read(ptr, stream->size());
+	// for dumping the music tracks
+#if 0
 	Common::DumpFile outFile;
 	outFile.open(name + ".RAW");
 	outFile.write(data, stream->size());
 	outFile.flush();
 	outFile.close();
+#endif
 
-	_midiParser.loadMusic(data, stream->size());
+	if (dataSize < 14) {
+		warning("not enough data in music file");
+		return false;
+	}
+
+	byte *dataPos = data;
+	if (memcmp("            ", dataPos, 12)) {
+		warning("Expected header not found in music file");
+		return false;
+	}
+	dataPos += 12;
+	dataSize -= 12;
+
+	uint16 headerSize = READ_LE_UINT16(dataPos);
+	if (headerSize != 0x7F) {
+		warning("music header is not as expected");
+		return false;
+	}
+
+	if (_musicType == MT_ADLIB) {
+		if (_driver)
+			MidiDriver_AdLib_newMusicData(_driver, dataPos, dataSize);
+#if USE_SCI_MIDI_PLAYER
+		if (_pMidiDrv)
+			MidiPlayer_AdLib_newMusicData(_pMidiDrv, dataPos, dataSize);
+#endif
+	}
 
+	_midiParser.loadMusic(dataPos, dataSize);
 	return true;
 }
 
diff --git a/engines/sherlock/music.h b/engines/sherlock/music.h
index 51ee7bb..a195b26 100644
--- a/engines/sherlock/music.h
+++ b/engines/sherlock/music.h
@@ -25,7 +25,8 @@
 
 #include "audio/midiplayer.h"
 #include "audio/midiparser.h"
-#include "audio/mididrv.h"
+//#include "audio/mididrv.h"
+#include "sherlock/scalpel/drivers/mididriver.h"
 
 namespace Sherlock {
 
@@ -44,15 +45,21 @@ public:
 	virtual bool loadMusic(byte *data, uint32 size);
 };
 
-class Music : public Audio::MidiPlayer {
+class Music {
 private:
 	SherlockEngine *_vm;
 	Audio::Mixer *_mixer;
 	MidiParser_SH _midiParser;
+	MidiPlayer *_pMidiDrv;
+	MidiDriver *_driver;
 
 public:
 	bool _musicPlaying;
 	bool _musicOn;
+
+private:
+	MusicType _musicType;
+
 public:
 	Music(SherlockEngine *vm, Audio::Mixer *mixer);
 
diff --git a/engines/sherlock/scalpel/drivers/adlib.cpp b/engines/sherlock/scalpel/drivers/adlib.cpp
new file mode 100644
index 0000000..7ee5256
--- /dev/null
+++ b/engines/sherlock/scalpel/drivers/adlib.cpp
@@ -0,0 +1,532 @@
+/* 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 "sherlock/sherlock.h"
+#include "sherlock/scalpel/drivers/mididriver.h"
+
+#include "common/file.h"
+#include "common/system.h"
+#include "common/textconsole.h"
+
+#include "audio/fmopl.h"
+#include "audio/softsynth/emumidi.h"
+
+namespace Sherlock {
+
+#define USE_SCI_MIDI_PLAYER 1
+
+#define SHERLOCK_ADLIB_VOICES_COUNT 9
+#define SHERLOCK_ADLIB_NOTES_COUNT 96
+
+byte adlib_Operator1Register[SHERLOCK_ADLIB_VOICES_COUNT] = {
+	0x00, 0x01, 0x02, 0x08, 0x09, 0x0A, 0x10, 0x11, 0x12
+};
+
+byte adlib_Operator2Register[SHERLOCK_ADLIB_VOICES_COUNT] = {
+	0x03, 0x04, 0x05, 0x0B, 0x0C, 0x0D, 0x13, 0x14, 0x15
+};
+
+struct adlib_InstrumentEntry {
+	byte reg20op1;
+	byte reg40op1;
+	byte reg60op1;
+	byte reg80op1;
+	byte regE0op1;
+	byte reg20op2;
+	byte reg40op2;
+	byte reg60op2;
+	byte reg80op2;
+	byte regE0op2;
+	byte regC0;
+	byte frequencyAdjust;
+};
+
+// hardcoded, dumped from ADHOM.DRV
+const adlib_InstrumentEntry adlib_instrumentTable[] = {
+	{ 0x71, 0x89, 0x51, 0x11, 0x00, 0x61, 0x23, 0x42, 0x15, 0x01, 0x02, 0xF4 },
+	{ 0x22, 0x20, 0x97, 0x89, 0x00, 0xA2, 0x1F, 0x70, 0x07, 0x00, 0x0A, 0xF4 },
+	{ 0x70, 0x1A, 0x64, 0x13, 0x00, 0x20, 0x1F, 0x53, 0x46, 0x00, 0x0E, 0xF4 },
+	{ 0xB6, 0x4A, 0xB6, 0x32, 0x00, 0x11, 0x2B, 0xD1, 0x31, 0x00, 0x0E, 0xE8 },
+	{ 0x71, 0x8B, 0x51, 0x11, 0x00, 0x61, 0x20, 0x32, 0x35, 0x01, 0x02, 0xF4 },
+	{ 0x71, 0x8A, 0x51, 0x11, 0x00, 0x61, 0x20, 0x32, 0x25, 0x01, 0x02, 0xF4 },
+	{ 0x23, 0x0F, 0xF4, 0x04, 0x02, 0x2F, 0x25, 0xF0, 0x43, 0x00, 0x06, 0xE8 },
+	{ 0x71, 0x1C, 0x71, 0x03, 0x00, 0x21, 0x1F, 0x54, 0x17, 0x00, 0x0E, 0xF4 },
+	{ 0x71, 0x8A, 0x6E, 0x17, 0x00, 0x25, 0x27, 0x6B, 0x0E, 0x00, 0x02, 0xF4 },
+	{ 0x71, 0x1D, 0x81, 0x03, 0x00, 0x21, 0x1F, 0x64, 0x17, 0x00, 0x0E, 0xF4 },
+	{ 0x01, 0x4B, 0xF1, 0x50, 0x00, 0x01, 0x23, 0xD2, 0x76, 0x00, 0x06, 0xF4 },
+	{ 0x2F, 0xCA, 0xF8, 0xE5, 0x00, 0x21, 0x1F, 0xC0, 0xFF, 0x00, 0x00, 0xF4 },
+	{ 0x29, 0xCD, 0xF0, 0x91, 0x00, 0x21, 0x1F, 0xE0, 0x86, 0x00, 0x02, 0xF4 },
+	{ 0x24, 0xD0, 0xF0, 0x01, 0x00, 0x21, 0x1F, 0xE0, 0x86, 0x00, 0x02, 0xF4 },
+	{ 0x23, 0xC8, 0xF0, 0x01, 0x00, 0x21, 0x1F, 0xE0, 0x86, 0x00, 0x02, 0xF4 },
+	{ 0x64, 0xC9, 0xB0, 0x01, 0x00, 0x61, 0x1F, 0xF0, 0x86, 0x00, 0x02, 0xF4 },
+	{ 0x33, 0x85, 0xA1, 0x10, 0x00, 0x15, 0x9F, 0x72, 0x23, 0x00, 0x08, 0xF4 },
+	{ 0x31, 0x85, 0xA1, 0x10, 0x00, 0x15, 0x9F, 0x73, 0x33, 0x00, 0x08, 0xF4 },
+	{ 0x31, 0x81, 0xA1, 0x30, 0x00, 0x16, 0x9F, 0xC2, 0x74, 0x00, 0x08, 0xF4 },
+	{ 0x03, 0x8A, 0xF0, 0x7B, 0x00, 0x02, 0x9F, 0xF4, 0x7B, 0x00, 0x08, 0xF4 },
+	{ 0x03, 0x8A, 0xF0, 0x7B, 0x00, 0x01, 0x9F, 0xF4, 0x7B, 0x00, 0x08, 0xF4 },
+	{ 0x23, 0x8A, 0xF2, 0x7B, 0x00, 0x01, 0x9F, 0xF4, 0x7B, 0x00, 0x08, 0xF4 },
+	{ 0x32, 0x80, 0x01, 0x10, 0x00, 0x12, 0x9F, 0x72, 0x33, 0x00, 0x08, 0xF4 },
+	{ 0x32, 0x80, 0x01, 0x10, 0x00, 0x14, 0x9F, 0x73, 0x33, 0x00, 0x08, 0xF4 },
+	{ 0x31, 0x16, 0x73, 0x8E, 0x00, 0x21, 0x1F, 0x80, 0x9E, 0x00, 0x0E, 0xF4 },
+	{ 0x30, 0x16, 0x73, 0x7E, 0x00, 0x21, 0x1F, 0x80, 0x9E, 0x00, 0x0E, 0x00 },
+	{ 0x31, 0x94, 0x33, 0x73, 0x00, 0x21, 0x1F, 0xA0, 0x97, 0x00, 0x0E, 0xF4 },
+	{ 0x31, 0x94, 0xD3, 0x73, 0x00, 0x21, 0x20, 0xA0, 0x97, 0x00, 0x0E, 0xF4 },
+	{ 0x31, 0x45, 0xF1, 0x53, 0x00, 0x32, 0x1F, 0xF2, 0x27, 0x00, 0x06, 0xF4 },
+	{ 0x13, 0x0C, 0xF2, 0x01, 0x00, 0x15, 0x2F, 0xF2, 0xB6, 0x00, 0x08, 0xF4 },
+	{ 0x11, 0x0C, 0xF2, 0x01, 0x00, 0x11, 0x1F, 0xF2, 0xB6, 0x00, 0x08, 0xF4 },
+	{ 0x11, 0x0A, 0xFE, 0x04, 0x00, 0x11, 0x1F, 0xF2, 0xBD, 0x00, 0x08, 0xF4 },
+	{ 0x16, 0x4D, 0xFA, 0x11, 0x00, 0xE1, 0x20, 0xF1, 0xF1, 0x00, 0x08, 0xF4 },
+	{ 0x16, 0x40, 0xBA, 0x11, 0x00, 0xF1, 0x20, 0x24, 0x31, 0x00, 0x08, 0xF4 },
+	{ 0x61, 0xA7, 0x72, 0x8E, 0x00, 0xE1, 0x9F, 0x50, 0x1A, 0x00, 0x02, 0xF4 },
+	{ 0x18, 0x4D, 0x32, 0x13, 0x00, 0xE1, 0x20, 0x51, 0xE3, 0x00, 0x08, 0xF4 },
+	{ 0x17, 0xC0, 0x12, 0x41, 0x00, 0x31, 0x9F, 0x13, 0x31, 0x00, 0x06, 0xF4 },
+	{ 0x03, 0x8F, 0xF5, 0x55, 0x00, 0x21, 0x9F, 0xF3, 0x33, 0x00, 0x00, 0xF4 },
+	{ 0x13, 0x4D, 0xFA, 0x11, 0x00, 0xE1, 0x20, 0xF1, 0xF1, 0x00, 0x08, 0xF4 },
+	{ 0x11, 0x43, 0x20, 0x15, 0x00, 0xF1, 0x20, 0x31, 0xF8, 0x00, 0x08, 0xF4 },
+	{ 0x11, 0x03, 0x82, 0x97, 0x00, 0xE4, 0x60, 0xF0, 0xF2, 0x00, 0x08, 0xF4 },
+	{ 0x05, 0x40, 0xD1, 0x53, 0x00, 0x14, 0x1F, 0x51, 0x71, 0x00, 0x06, 0xF4 },
+	{ 0xF1, 0x01, 0x77, 0x17, 0x00, 0x21, 0x1F, 0x81, 0x18, 0x00, 0x02, 0xF4 },
+	{ 0xF1, 0x18, 0x32, 0x11, 0x00, 0xE1, 0x1F, 0xF1, 0x13, 0x00, 0x00, 0xF4 },
+	{ 0x73, 0x48, 0xF1, 0x53, 0x00, 0x71, 0x1F, 0xF1, 0x06, 0x00, 0x08, 0xF4 },
+	{ 0x71, 0x8D, 0x71, 0x11, 0x00, 0x61, 0x5F, 0x72, 0x15, 0x00, 0x06, 0xF4 },
+	{ 0xD7, 0x4F, 0xF2, 0x61, 0x00, 0xD2, 0x1F, 0xF1, 0xB2, 0x00, 0x08, 0xF4 },
+	{ 0x01, 0x11, 0xF0, 0xFF, 0x00, 0x01, 0x1F, 0xF0, 0xF8, 0x00, 0x0A, 0xF4 },
+	{ 0x31, 0x8B, 0x41, 0x11, 0x00, 0x61, 0x1F, 0x22, 0x13, 0x00, 0x06, 0xF4 },
+	{ 0x71, 0x1C, 0x71, 0x03, 0x00, 0x21, 0x1F, 0x64, 0x07, 0x00, 0x0E, 0xF4 },
+	{ 0x31, 0x8B, 0x41, 0x11, 0x00, 0x61, 0x1F, 0x32, 0x15, 0x00, 0x02, 0xF4 },
+	{ 0x71, 0x1C, 0xFD, 0x13, 0x00, 0x21, 0x1F, 0xE7, 0xD6, 0x00, 0x0E, 0xF4 },
+	{ 0x71, 0x1C, 0x51, 0x03, 0x00, 0x21, 0x1F, 0x54, 0x67, 0x00, 0x0E, 0xF4 },
+	{ 0x71, 0x1C, 0x51, 0x03, 0x00, 0x21, 0x1F, 0x54, 0x17, 0x00, 0x0E, 0xF4 },
+	{ 0x71, 0x1C, 0x54, 0x15, 0x00, 0x21, 0x1F, 0x53, 0x49, 0x00, 0x0E, 0xF4 },
+	{ 0x71, 0x56, 0x51, 0x03, 0x00, 0x61, 0x1F, 0x54, 0x17, 0x00, 0x0E, 0xF4 },
+	{ 0x71, 0x1C, 0x51, 0x03, 0x00, 0x21, 0x1F, 0x54, 0x17, 0x00, 0x0E, 0xF4 },
+	{ 0x02, 0x29, 0xF5, 0x75, 0x00, 0x01, 0x9F, 0xF2, 0xF3, 0x00, 0x00, 0xF4 },
+	{ 0x02, 0x29, 0xF0, 0x75, 0x00, 0x01, 0x9F, 0xF4, 0x33, 0x00, 0x00, 0xF4 },
+	{ 0x01, 0x49, 0xF1, 0x53, 0x00, 0x11, 0x1F, 0xF1, 0x74, 0x00, 0x06, 0xF4 },
+	{ 0x01, 0x89, 0xF1, 0x53, 0x00, 0x11, 0x1F, 0xF1, 0x74, 0x00, 0x06, 0xF4 },
+	{ 0x02, 0x89, 0xF1, 0x53, 0x00, 0x11, 0x1F, 0xF1, 0x74, 0x00, 0x06, 0xF4 },
+	{ 0x02, 0x80, 0xF1, 0x53, 0x00, 0x11, 0x1F, 0xF1, 0x74, 0x00, 0x06, 0xF4 },
+	{ 0x01, 0x40, 0xF1, 0x53, 0x00, 0x08, 0x5F, 0xF1, 0x53, 0x00, 0x00, 0xF4 },
+	{ 0x21, 0x15, 0xD3, 0x2C, 0x00, 0x21, 0x9F, 0xC3, 0x2C, 0x00, 0x0A, 0xF4 },
+	{ 0x01, 0x18, 0xD4, 0xF2, 0x00, 0x21, 0x9F, 0xC4, 0x8A, 0x00, 0x0A, 0xF4 },
+	{ 0x01, 0x4E, 0xF0, 0x7B, 0x00, 0x11, 0x1F, 0xF4, 0xC8, 0x00, 0x04, 0xF4 },
+	{ 0x01, 0x44, 0xF0, 0xAB, 0x00, 0x11, 0x1F, 0xF3, 0xAB, 0x00, 0x04, 0xF4 },
+	{ 0x53, 0x0E, 0xF4, 0xC8, 0x00, 0x11, 0x1F, 0xF1, 0xBB, 0x00, 0x04, 0xF4 },
+	{ 0x53, 0x0B, 0xF2, 0xC8, 0x00, 0x11, 0x1F, 0xF2, 0xC5, 0x00, 0x04, 0xF4 },
+	{ 0x21, 0x15, 0xB4, 0x4C, 0x00, 0x21, 0x1F, 0x94, 0xAC, 0x00, 0x0A, 0xF4 },
+	{ 0x21, 0x15, 0x94, 0x1C, 0x00, 0x21, 0x1F, 0x64, 0xAC, 0x00, 0x0A, 0xF4 },
+	{ 0x22, 0x1B, 0x97, 0x89, 0x00, 0xA2, 0x1F, 0x70, 0x07, 0x00, 0x0A, 0xF4 },
+	{ 0x21, 0x19, 0x77, 0xBF, 0x00, 0xA1, 0x9F, 0x60, 0x2A, 0x00, 0x06, 0xF4 },
+	{ 0xA1, 0x13, 0xD6, 0xAF, 0x00, 0xE2, 0x9F, 0x60, 0x2A, 0x00, 0x02, 0xF4 },
+	{ 0xA2, 0x1D, 0x95, 0x24, 0x00, 0xE2, 0x9F, 0x60, 0x2A, 0x00, 0x02, 0xF4 },
+	{ 0x32, 0x9A, 0x51, 0x19, 0x00, 0x61, 0x9F, 0x60, 0x39, 0x00, 0x0C, 0xF4 },
+	{ 0xA4, 0x12, 0xF4, 0x30, 0x00, 0xE2, 0x9F, 0x60, 0x2A, 0x00, 0x02, 0xF4 },
+	{ 0x21, 0x16, 0x63, 0x0E, 0x00, 0x21, 0x1F, 0x63, 0x0E, 0x00, 0x0C, 0xF4 },
+	{ 0x31, 0x16, 0x63, 0x0A, 0x00, 0x21, 0x1F, 0x63, 0x0B, 0x00, 0x0C, 0xF4 },
+	{ 0x21, 0x1B, 0x63, 0x0A, 0x00, 0x21, 0x1F, 0x63, 0x0B, 0x00, 0x0C, 0xF4 },
+	{ 0x20, 0x1B, 0x63, 0x0A, 0x00, 0x21, 0x1F, 0x63, 0x0B, 0x00, 0x0C, 0xF4 },
+	{ 0x32, 0x1C, 0x82, 0x18, 0x00, 0x61, 0x9F, 0x60, 0x07, 0x00, 0x0C, 0xF4 },
+	{ 0x32, 0x18, 0x61, 0x14, 0x00, 0xE1, 0x9F, 0x72, 0x16, 0x00, 0x0C, 0xF4 },
+	{ 0x31, 0xC0, 0x77, 0x17, 0x00, 0x22, 0x1F, 0x6B, 0x09, 0x00, 0x02, 0xF4 },
+	{ 0x71, 0xC3, 0x8E, 0x17, 0x00, 0x22, 0x24, 0x8B, 0x0E, 0x00, 0x02, 0xF4 },
+	{ 0x70, 0x8D, 0x6E, 0x17, 0x00, 0x22, 0x1F, 0x6B, 0x0E, 0x00, 0x02, 0xF4 },
+	{ 0x24, 0x4F, 0xF2, 0x06, 0x00, 0x31, 0x1F, 0x52, 0x06, 0x00, 0x0E, 0xF4 },
+	{ 0x31, 0x1B, 0x64, 0x07, 0x00, 0x61, 0x1F, 0xD0, 0x67, 0x00, 0x0E, 0xF4 },
+	{ 0x31, 0x1B, 0x61, 0x06, 0x00, 0x61, 0x1F, 0xD2, 0x36, 0x00, 0x0C, 0xF4 },
+	{ 0x31, 0x1F, 0x31, 0x06, 0x00, 0x61, 0x1F, 0x50, 0x36, 0x00, 0x0C, 0xF4 },
+	{ 0x31, 0x1F, 0x41, 0x06, 0x00, 0x61, 0x1F, 0xA0, 0x36, 0x00, 0x0C, 0xF4 },
+	{ 0x21, 0x9A, 0x53, 0x56, 0x00, 0x21, 0x9F, 0xA0, 0x16, 0x00, 0x0E, 0xF4 },
+	{ 0x21, 0x9A, 0x53, 0x56, 0x00, 0x21, 0x9F, 0xA0, 0x16, 0x00, 0x0E, 0xF4 },
+	{ 0x61, 0x19, 0x53, 0x58, 0x00, 0x21, 0x1F, 0xA0, 0x18, 0x00, 0x0C, 0xF4 },
+	{ 0x61, 0x19, 0x73, 0x57, 0x00, 0x21, 0x1F, 0xA0, 0x17, 0x00, 0x0C, 0xF4 },
+	{ 0x21, 0x1B, 0x71, 0xA6, 0x00, 0x21, 0x1F, 0xA1, 0x96, 0x00, 0x0E, 0xF4 },
+	{ 0x85, 0x91, 0xF5, 0x44, 0x00, 0xA1, 0x1F, 0xF0, 0x45, 0x00, 0x06, 0xF4 },
+	{ 0x07, 0x51, 0xF5, 0x33, 0x00, 0x61, 0x1F, 0xF0, 0x25, 0x00, 0x06, 0xF4 },
+	{ 0x13, 0x8C, 0xFF, 0x21, 0x00, 0x11, 0x9F, 0xFF, 0x03, 0x00, 0x0E, 0xF4 },
+	{ 0x38, 0x8C, 0xF3, 0x0D, 0x00, 0xB1, 0x5F, 0xF5, 0x33, 0x00, 0x0E, 0xF4 },
+	{ 0x87, 0x91, 0xF5, 0x55, 0x00, 0x22, 0x1F, 0xF0, 0x54, 0x00, 0x06, 0xF4 },
+	{ 0xB6, 0x4A, 0xB6, 0x32, 0x00, 0x11, 0x2B, 0xD1, 0x31, 0x00, 0x0E, 0xF4 },
+	{ 0x04, 0x00, 0xFE, 0xF0, 0x00, 0xC2, 0x1F, 0xF6, 0xB5, 0x00, 0x0E, 0xF4 },
+	{ 0x05, 0x4E, 0xDA, 0x15, 0x00, 0x01, 0x9F, 0xF0, 0x13, 0x00, 0x0A, 0xF4 },
+	{ 0x31, 0x44, 0xF2, 0x9A, 0x00, 0x32, 0x1F, 0xF0, 0x27, 0x00, 0x06, 0xF4 },
+	{ 0xB0, 0xC4, 0xA4, 0x02, 0x00, 0xD7, 0x9F, 0x40, 0x42, 0x00, 0x00, 0xF4 },
+	{ 0xCA, 0x84, 0xF0, 0xF0, 0x00, 0xCF, 0x1F, 0x59, 0x62, 0x00, 0x0C, 0xF4 },
+	{ 0x30, 0x35, 0xF5, 0xF0, 0x00, 0x35, 0x1F, 0xF0, 0x9B, 0x00, 0x02, 0xF4 },
+	{ 0x63, 0x0F, 0xF4, 0x04, 0x02, 0x6F, 0x1F, 0xF0, 0x43, 0x00, 0x06, 0xF4 },
+	{ 0x07, 0x40, 0x09, 0x53, 0x00, 0x05, 0x1F, 0xF6, 0x94, 0x00, 0x0E, 0xF4 },
+	{ 0x09, 0x4E, 0xDA, 0x25, 0x00, 0x01, 0x1F, 0xF1, 0x15, 0x00, 0x0A, 0xF4 },
+	{ 0x04, 0x00, 0xF3, 0xA0, 0x02, 0x04, 0x1F, 0xF8, 0x46, 0x00, 0x0E, 0xF4 },
+	{ 0x07, 0x00, 0xF0, 0xF0, 0x00, 0x00, 0x1F, 0x5C, 0xDC, 0x00, 0x0E, 0xF4 },
+	{ 0x1F, 0x1E, 0xE5, 0x5B, 0x00, 0x0F, 0x1F, 0x5D, 0xFA, 0x00, 0x0E, 0xF4 },
+	{ 0x11, 0x8A, 0xF1, 0x11, 0x00, 0x01, 0x5F, 0xF1, 0xB3, 0x00, 0x06, 0xF4 },
+	{ 0x00, 0x40, 0xD1, 0x53, 0x00, 0x00, 0x1F, 0xF2, 0x56, 0x00, 0x0E, 0xF4 },
+	{ 0x32, 0x44, 0xF8, 0xFF, 0x00, 0x11, 0x1F, 0xF5, 0x7F, 0x00, 0x0E, 0xF4 },
+	{ 0x00, 0x40, 0x09, 0x53, 0x00, 0x02, 0x1F, 0xF7, 0x94, 0x00, 0x0E, 0xF4 },
+	{ 0x11, 0x86, 0xF2, 0xA8, 0x00, 0x01, 0x9F, 0xA0, 0xA8, 0x00, 0x08, 0xF4 },
+	{ 0x00, 0x50, 0xF2, 0x70, 0x00, 0x13, 0x1F, 0xF2, 0x72, 0x00, 0x0E, 0xF4 },
+	{ 0xF0, 0x00, 0x11, 0x11, 0x00, 0xE0, 0xDF, 0x11, 0x11, 0x00, 0x0E, 0xF4 }
+};
+
+// hardcoded, dumped from ADHOM.DRV
+uint16 adlib_FrequencyLookUpTable[SHERLOCK_ADLIB_NOTES_COUNT] = {
+	0x0158, 0x016C, 0x0182, 0x0199, 0x01B1, 0x01CB, 0x01E6, 0x0203, 0x0222, 0x0242,
+	0x0265, 0x0289, 0x0558, 0x056C, 0x0582, 0x0599, 0x05B1, 0x05CB, 0x05E6, 0x0603,
+	0x0622, 0x0642, 0x0665, 0x0689, 0x0958, 0x096C, 0x0982, 0x0999, 0x09B1, 0x09CB,
+	0x09E6, 0x0A03, 0x0A22, 0x0A42, 0x0A65, 0x0A89, 0x0D58, 0x0D6C, 0x0D82, 0x0D99,
+	0x0DB1, 0x0DCB, 0x0DE6, 0x0E03, 0x0E22, 0x0E42, 0x0E65, 0x0E89, 0x1158, 0x116C,
+	0x1182, 0x1199, 0x11B1, 0x11CB, 0x11E6, 0x1203, 0x1222, 0x1242, 0x1265, 0x1289,
+	0x1558, 0x156C, 0x1582, 0x1599, 0x15B1, 0x15CB, 0x15E6, 0x1603, 0x1622, 0x1642,
+	0x1665, 0x1689, 0x1958, 0x196C, 0x1982, 0x1999, 0x19B1, 0x19CB, 0x19E6, 0x1A03,
+	0x1A22, 0x1A42, 0x1A65, 0x1A89, 0x1D58, 0x1D6C, 0x1D82, 0x1D99, 0x1DB1, 0x1DCB,
+	0x1DE6, 0x1E03, 0x1E22, 0x1E42, 0x1E65, 0x1E89
+};
+
+class MidiDriver_AdLib : public MidiDriver_Emulated {
+public:
+	MidiDriver_AdLib(Audio::Mixer *mixer)
+		: MidiDriver_Emulated(mixer), _masterVolume(15), _rhythmKeyMap(0), _opl(0) {
+		memset(_voiceChannelMapping, 0, sizeof(_voiceChannelMapping));
+	}
+	virtual ~MidiDriver_AdLib() { }
+
+	// MidiDriver
+	int open();
+	void close();
+	void send(uint32 b);
+	MidiChannel *allocateChannel() { return NULL; }
+	MidiChannel *getPercussionChannel() { return NULL; }
+
+	// AudioStream
+	bool isStereo() const { return false; }
+	int getRate() const { return _mixer->getOutputRate(); }
+	int getPolyphony() const { return SHERLOCK_ADLIB_VOICES_COUNT; }
+	bool hasRhythmChannel() const { return false; }
+
+	// MidiDriver_Emulated
+	void generateSamples(int16 *buf, int len);
+
+	void setVolume(byte volume);
+	virtual uint32 property(int prop, uint32 param);
+
+	bool useRhythmChannel() const { return _rhythmKeyMap != NULL; }
+
+	void newMusicData(byte *musicData, int32 musicDataSize);
+
+private:
+	struct adlib_ChannelEntry {
+		bool inUse;
+		const adlib_InstrumentEntry *currentInstrumentPtr;
+		byte currentNote;
+		byte currentA0hReg;
+		byte currentB0hReg;
+
+		adlib_ChannelEntry() : inUse(false), currentInstrumentPtr(NULL), currentNote(0),
+								currentA0hReg(0), currentB0hReg(0) { }
+	};
+
+	OPL::OPL *_opl;
+	int _masterVolume;
+	byte *_rhythmKeyMap;
+
+	// points to a MIDI channel for each of the new voice channels
+	byte _voiceChannelMapping[SHERLOCK_ADLIB_VOICES_COUNT];
+
+	// stores information about all FM voice channels
+	adlib_ChannelEntry _channels[SHERLOCK_ADLIB_VOICES_COUNT];
+
+	void programChange(byte channel, byte parameter);
+	void setRegister(int reg, int value);
+	void noteOn(byte channel, byte note, byte velocity);
+	void noteOff(byte channel, byte note);
+	void voiceOnOff(byte FMVoiceChannel, bool KeyOn, byte note, byte velocity);
+};
+
+#if USE_SCI_MIDI_PLAYER
+class MidiPlayer_AdLib : public MidiPlayer {
+public:
+	MidiPlayer_AdLib() : MidiPlayer() { _driver = new MidiDriver_AdLib(g_system->getMixer()); }
+	~MidiPlayer_AdLib() {
+		delete _driver;
+		_driver = 0;
+	}
+
+	int open();
+	void close();
+
+	byte getPlayId() const;
+	int getPolyphony() const { return SHERLOCK_ADLIB_VOICES_COUNT; }
+	bool hasRhythmChannel() const { return false; }
+	void setVolume(byte volume) { static_cast<MidiDriver_AdLib *>(_driver)->setVolume(volume); }
+
+	//int getLastChannel() const { return (static_cast<const MidiDriver_AdLib *>(_driver)->useRhythmChannel() ? 8 : 15); }
+
+	void newMusicData(byte *musicData, int32 musicDataSize) { static_cast<MidiDriver_AdLib *>(_driver)->newMusicData(musicData, musicDataSize); }
+};
+#endif
+
+int MidiDriver_AdLib::open() {
+	int rate = _mixer->getOutputRate();
+
+	debug(3, "ADLIB: Starting driver");
+
+	_opl = OPL::Config::create(OPL::Config::kOpl2);
+
+	if (!_opl)
+		return -1;
+
+	_opl->init(rate);
+
+	setRegister(0xBD, 0);
+	setRegister(0x08, 0);
+	setRegister(0x01, 0x20);
+
+	MidiDriver_Emulated::open();
+
+	_mixer->playStream(Audio::Mixer::kPlainSoundType, &_mixerSoundHandle, this, -1, _mixer->kMaxChannelVolume, 0, DisposeAfterUse::NO);
+
+	return 0;
+}
+
+void MidiDriver_AdLib::close() {
+	_mixer->stopHandle(_mixerSoundHandle);
+
+	delete _opl;
+	delete[] _rhythmKeyMap;
+}
+
+void MidiDriver_AdLib::setVolume(byte volume) {
+	_masterVolume = volume;
+	//renewNotes(-1, true);
+}
+
+// Called when a music track got loaded into memory
+void MidiDriver_AdLib::newMusicData(byte *musicData, int32 musicDataSize) {
+	assert(musicDataSize >= 0x7F);
+	// MIDI Channel <-> FM Voice Channel mapping at offset 0x22 of music data
+	memcpy(&_voiceChannelMapping, musicData + 0x22, 9);
+
+	// reset OPL here?
+	// reset current channel data
+	memset(&_channels, 0, sizeof(_channels));
+}
+
+// MIDI messages can be found at http://www.midi.org/techspecs/midimessages.php
+void MidiDriver_AdLib::send(uint32 b) {
+	byte command = b & 0xf0;
+	byte channel = b & 0xf;
+	byte op1 = (b >> 8) & 0xff;
+	byte op2 = (b >> 16) & 0xff;
+
+	switch (command) {
+	case 0x80:
+		noteOff(channel, op1);
+		break;
+	case 0x90:
+		noteOn(channel, op1, op2);
+		break;
+	case 0xb0: // Control change
+		// Doesn't seem to be implemented in the Sherlock Holmes adlib driver
+		break;
+	case 0xc0: // Program Change
+		programChange(channel, op1);
+		break;
+	case 0xa0: // Polyphonic key pressure (aftertouch)
+	case 0xd0: // Channel pressure (aftertouch)
+		// Aftertouch doesn't seem to be implemented in the Sherlock Holmes adlib driver
+		break;
+	case 0xe0:
+		// TODO: Implement this, occurs right in the intro, second scene
+		warning("pitch bend change");
+		break;
+	case 0xf0: // SysEx
+		warning("SysEx: %lx", b);
+		break;
+	default:
+		warning("ADLIB: Unknown event %02x", command);
+	}
+}
+
+void MidiDriver_AdLib::generateSamples(int16 *data, int len) {
+	_opl->readBuffer(data, len);
+}
+
+void MidiDriver_AdLib::noteOn(byte MIDIchannel, byte note, byte velocity) {
+	if (velocity == 0)
+		return noteOff(MIDIchannel, note);
+
+	if (MIDIchannel != 9) {
+		// Not Percussion
+		for (byte FMvoiceChannel = 0; FMvoiceChannel < SHERLOCK_ADLIB_VOICES_COUNT; FMvoiceChannel++) {
+			if (_voiceChannelMapping[FMvoiceChannel] == MIDIchannel) {
+				if (!_channels[FMvoiceChannel].inUse) {
+					_channels[FMvoiceChannel].inUse = true;
+					_channels[FMvoiceChannel].currentNote = note;
+
+					voiceOnOff(FMvoiceChannel, true, note, velocity);
+					return;
+				}
+			}
+		}
+	}
+	warning("MIDI channel not mapped/all FM voice channels busy %d", MIDIchannel);
+}
+
+void MidiDriver_AdLib::noteOff(byte MIDIchannel, byte note) {
+	for (byte FMvoiceChannel = 0; FMvoiceChannel < SHERLOCK_ADLIB_VOICES_COUNT; FMvoiceChannel++) {
+		if (_voiceChannelMapping[FMvoiceChannel] == MIDIchannel) {
+			if (_channels[FMvoiceChannel].currentNote == note) {
+				_channels[FMvoiceChannel].inUse = false;
+
+				voiceOnOff(FMvoiceChannel, false, note, 0);
+				return;
+			}
+		}
+	}
+}
+
+void MidiDriver_AdLib::voiceOnOff(byte FMvoiceChannel, bool keyOn, byte note, byte velocity) {
+	byte frequencyOffset = 0;
+	uint16 frequency = 0;
+	byte op2RegAdjust = 0;
+	byte regValue40h = 0;
+	byte regValueA0h = 0;
+	byte regValueB0h = 0;
+
+	// Look up frequency
+	if (_channels[FMvoiceChannel].currentInstrumentPtr) {
+		frequencyOffset = note + _channels[FMvoiceChannel].currentInstrumentPtr->frequencyAdjust;
+	} else {
+		frequencyOffset = note;
+	}
+	if (frequencyOffset >= SHERLOCK_ADLIB_NOTES_COUNT) {
+		error("bad note!");
+	}
+	frequency = adlib_FrequencyLookUpTable[frequencyOffset];
+
+	if (keyOn) {
+		// adjust register 40h
+		if (_channels[FMvoiceChannel].currentInstrumentPtr) {
+			regValue40h = _channels[FMvoiceChannel].currentInstrumentPtr->reg40op2;
+		}
+		regValue40h = regValue40h - (velocity >> 3);
+		op2RegAdjust = adlib_Operator2Register[FMvoiceChannel];
+		setRegister(0x40 + op2RegAdjust, regValue40h);
+	}
+
+	regValueA0h = frequency & 0xFF;
+	regValueB0h = frequency >> 8;
+	if (keyOn) {
+		regValueB0h |= 0x20; // set Key-On flag
+	}
+
+	setRegister(0xA0 + FMvoiceChannel, regValueA0h);
+	setRegister(0xB0 + FMvoiceChannel, regValueB0h);
+	_channels[FMvoiceChannel].currentA0hReg = regValueA0h;
+	_channels[FMvoiceChannel].currentB0hReg = regValueB0h;
+}
+
+void MidiDriver_AdLib::programChange(byte MIDIchannel, byte op1) {
+	const adlib_InstrumentEntry *instrumentPtr;
+	byte op1Reg = 0;
+	byte op2Reg = 0;
+
+	// setup instrument
+	instrumentPtr = &adlib_instrumentTable[op1];
+	//warning("program change for MIDI channel %d, instrument id %d", MIDIchannel, op1);
+
+	for (byte FMvoiceChannel = 0; FMvoiceChannel < SHERLOCK_ADLIB_VOICES_COUNT; FMvoiceChannel++) {
+		if (_voiceChannelMapping[FMvoiceChannel] == MIDIchannel) {
+
+			op1Reg = adlib_Operator1Register[FMvoiceChannel];
+			op2Reg = adlib_Operator2Register[FMvoiceChannel];
+
+			setRegister(0x20 + op1Reg, instrumentPtr->reg20op1);
+			setRegister(0x40 + op1Reg, instrumentPtr->reg40op1);
+			setRegister(0x60 + op1Reg, instrumentPtr->reg60op1);
+			setRegister(0x80 + op1Reg, instrumentPtr->reg80op1);
+			setRegister(0xE0 + op1Reg, instrumentPtr->regE0op1);
+
+			setRegister(0x20 + op2Reg, instrumentPtr->reg20op2);
+			setRegister(0x40 + op2Reg, instrumentPtr->reg40op2);
+			setRegister(0x60 + op2Reg, instrumentPtr->reg60op2);
+			setRegister(0x80 + op2Reg, instrumentPtr->reg80op2);
+			setRegister(0xE0 + op2Reg, instrumentPtr->regE0op2);
+
+			setRegister(0xC0 + FMvoiceChannel, instrumentPtr->regC0);
+
+			// Remember instrument
+			_channels[FMvoiceChannel].currentInstrumentPtr = instrumentPtr;
+		}
+	}
+}
+void MidiDriver_AdLib::setRegister(int reg, int value) {
+	_opl->write(0x220, reg);
+	_opl->write(0x221, value);
+}
+
+uint32 MidiDriver_AdLib::property(int prop, uint32 param) {
+#if 0
+	switch(prop) {
+	case MIDI_PROP_MASTER_VOLUME:
+		if (param != 0xffff)
+			_masterVolume = param;
+		return _masterVolume;
+	default:
+		break;
+	}
+#endif
+	return 0;
+}
+
+#if USE_SCI_MIDI_PLAYER
+int MidiPlayer_AdLib::open() {
+	return static_cast<MidiDriver_AdLib *>(_driver)->open();
+}
+
+void MidiPlayer_AdLib::close() {
+	if (_driver) {
+		_driver->close();
+	}
+}
+
+byte MidiPlayer_AdLib::getPlayId() const {
+	return 0x00;
+}
+
+MidiPlayer *MidiPlayer_AdLib_create() {
+	return new MidiPlayer_AdLib();
+}
+
+void MidiPlayer_AdLib_newMusicData(MidiPlayer *driver, byte *musicData, int32 musicDataSize) {
+	static_cast<MidiPlayer_AdLib *>(driver)->newMusicData(musicData, musicDataSize);
+}
+#endif
+
+MidiDriver *MidiDriver_AdLib_create() {
+	return new MidiDriver_AdLib(g_system->getMixer());
+}
+
+void MidiDriver_AdLib_newMusicData(MidiDriver *driver, byte *musicData, int32 musicDataSize) {
+	static_cast<MidiDriver_AdLib *>(driver)->newMusicData(musicData, musicDataSize);
+}
+
+} // End of namespace Sci
diff --git a/engines/sherlock/scalpel/drivers/mididriver.h b/engines/sherlock/scalpel/drivers/mididriver.h
new file mode 100644
index 0000000..f1366f8
--- /dev/null
+++ b/engines/sherlock/scalpel/drivers/mididriver.h
@@ -0,0 +1,91 @@
+/* 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 SHERLOCK_SOFTSEQ_MIDIDRIVER_H
+#define SHERLOCK_SOFTSEQ_MIDIDRIVER_H
+
+#include "sherlock/sherlock.h"
+//#include "audio/mididrv.h"
+#include "common/error.h"
+
+namespace Sherlock {
+
+#define USE_SCI_MIDIPLAYER 1
+
+#if USE_SCI_MIDIPLAYER
+enum {
+	MIDI_CHANNELS = 16,
+	MIDI_PROP_MASTER_VOLUME = 0
+};
+
+#define MIDI_RHYTHM_CHANNEL 9
+
+class MidiPlayer : public MidiDriver_BASE {
+protected:
+	MidiDriver *_driver;
+	int8 _reverb;
+
+public:
+	MidiPlayer() : _driver(0), _reverb(-1) { }
+
+	virtual int open() { return _driver->open(); }
+	virtual void close() { _driver->close(); }
+	virtual void send(uint32 b) { _driver->send(b); }
+	virtual uint32 getBaseTempo() { return _driver->getBaseTempo(); }
+	virtual bool hasRhythmChannel() const = 0;
+	virtual void setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc) { _driver->setTimerCallback(timer_param, timer_proc); }
+
+	virtual byte getPlayId() const = 0;
+	virtual int getPolyphony() const = 0;
+	virtual int getFirstChannel() const { return 0; }
+	//virtual int getLastChannel() const { return 15; }
+
+	virtual void setVolume(byte volume) {
+		if(_driver)
+			_driver->property(MIDI_PROP_MASTER_VOLUME, volume);
+	}
+
+	virtual int getVolume() {
+		return _driver ? _driver->property(MIDI_PROP_MASTER_VOLUME, 0xffff) : 0;
+	}
+
+	// Returns the current reverb, or -1 when no reverb is active
+	int8 getReverb() const { return _reverb; }
+	// Sets the current reverb, used mainly in MT-32
+	virtual void setReverb(int8 reverb) { _reverb = reverb; }
+
+	// Special stuff for Sherlock Holmes
+//	virtual void newMusicData(byte *musicData, int32 musicDataSize);
+
+//protected:
+};
+
+extern MidiPlayer *MidiPlayer_AdLib_create();
+extern void MidiPlayer_AdLib_newMusicData(MidiPlayer *driver, byte *musicData, int32 musicDataSize);
+#endif
+
+extern MidiDriver *MidiDriver_AdLib_create();
+extern void MidiDriver_AdLib_newMusicData(MidiDriver *driver, byte *musicData, int32 musicDataSize);
+
+} // End of namespace Sci
+
+#endif // SHERLOCK_SOFTSEQ_MIDIDRIVER_H






More information about the Scummvm-git-logs mailing list