[Scummvm-cvs-logs] SF.net SVN: scummvm: [29509] scummvm/trunk

cyx at users.sourceforge.net cyx at users.sourceforge.net
Thu Nov 15 21:21:33 CET 2007


Revision: 29509
          http://scummvm.svn.sourceforge.net/scummvm/?rev=29509&view=rev
Author:   cyx
Date:     2007-11-15 12:21:33 -0800 (Thu, 15 Nov 2007)

Log Message:
-----------
added support for Adlib tracks

Modified Paths:
--------------
    scummvm/trunk/dists/msvc8/queen.vcproj
    scummvm/trunk/engines/queen/module.mk
    scummvm/trunk/engines/queen/music.cpp
    scummvm/trunk/engines/queen/music.h
    scummvm/trunk/engines/queen/musicdata.cpp
    scummvm/trunk/engines/queen/sound.cpp
    scummvm/trunk/engines/queen/sound.h

Added Paths:
-----------
    scummvm/trunk/engines/queen/midiadlib.cpp

Modified: scummvm/trunk/dists/msvc8/queen.vcproj
===================================================================
--- scummvm/trunk/dists/msvc8/queen.vcproj	2007-11-15 11:33:16 UTC (rev 29508)
+++ scummvm/trunk/dists/msvc8/queen.vcproj	2007-11-15 20:21:33 UTC (rev 29509)
@@ -253,6 +253,10 @@
 			>
 		</File>
 		<File
+			RelativePath="..\..\engines\queen\midiadlib.cpp"
+			>
+		</File>
+		<File
 			RelativePath="..\..\engines\queen\music.cpp"
 			>
 		</File>

Added: scummvm/trunk/engines/queen/midiadlib.cpp
===================================================================
--- scummvm/trunk/engines/queen/midiadlib.cpp	                        (rev 0)
+++ scummvm/trunk/engines/queen/midiadlib.cpp	2007-11-15 20:21:33 UTC (rev 29509)
@@ -0,0 +1,628 @@
+/* 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.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/endian.h"
+
+#include "sound/fmopl.h"
+#include "sound/softsynth/emumidi.h"
+
+namespace Queen {
+
+class AdlibMidiChannel;
+
+class AdlibMidiDriver : public MidiDriver_Emulated {
+public:
+
+	AdlibMidiDriver(Audio::Mixer *mixer) : MidiDriver_Emulated(mixer) {}
+	~AdlibMidiDriver() {}
+
+	// MidiDriver
+	int open();
+	void close();
+	void send(uint32 b);
+	void metaEvent(byte type, byte *data, uint16 length);
+	MidiChannel *allocateChannel() { return 0; }
+	MidiChannel *getPercussionChannel() { return 0; }
+
+	// AudioStream
+	bool isStereo() const { return false; }
+	int getRate() const { return _mixer->getOutputRate(); }
+
+	// MidiDriver_Emulated
+	void generateSamples(int16 *buf, int len);
+
+private:
+
+	void handleMidiEvent0x90_NoteOn(int channel, int param1, int param2);
+	void handleSequencerSpecificMetaEvent1(int channel, const uint8 *data);
+	void handleSequencerSpecificMetaEvent2(uint8 value);
+	void handleSequencerSpecificMetaEvent3(uint8 value);
+
+	void Adlib_Write(uint8 port, uint8 value);
+	void Adlib_SetupCard();
+	void Adlib_SetupChannels(int fl);
+	void Adlib_ResetAmpVibratoRhythm(int am, int vib, int kso);
+	void Adlib_ResetChannels();
+	void Adlib_SetAmpVibratoRhythm();
+	void Adlib_SetCSMKeyboardSplit();
+	void Adlib_SetNoteMul(int mul);
+	void Adlib_SetWaveformSelect(int fl);
+	void Adlib_SetPitchBend(int channel, int range);
+	void Adlib_PlayNote(int channel);
+	uint8 Adlib_PlayNoteHelper(int channel, int note1, int note2, int oct);
+	void Adlib_TurnNoteOff(int channel);
+	void Adlib_TurnNoteOn(int channel, int note);
+	void Adlib_SetupChannelFromSequence(int channel, const uint8 *src, int fl);
+	void Adlib_SetupChannel(int channel, const uint16 *src, int fl);
+	void Adlib_SetNoteVolume(int channel, int volume);
+	void Adlib_SetupChannelHelper(int channel);
+	void Adlib_SetChannel0x40(int channel);
+	void Adlib_SetChannel0xC0(int channel);
+	void Adlib_SetChannel0x60(int channel);
+	void Adlib_SetChannel0x80(int channel);
+	void Adlib_SetChannel0x20(int channel);
+	void Adlib_SetChannel0xE0(int channel);
+
+	FM_OPL *_opl;
+	int _midiNumberOfChannels;
+	int _adlibNoteMul;
+	int _adlibWaveformSelect;
+	int _adlibAMDepthEq48;
+	int _adlibVibratoDepthEq14;
+	int _adlibRhythmEnabled;
+	int _adlibKeyboardSplitOn;
+	int _adlibVibratoRhythm;
+	uint8 _midiChannelsFreqTable[9];
+	uint8 _adlibChannelsLevelKeyScalingTable[11];
+	uint8 _adlibSetupChannelSequence1[14 * 18];
+	uint16 _adlibSetupChannelSequence2[14];
+	int16 _midiChannelsNote2Table[9];
+	uint8 _midiChannelsNote1Table[9];
+	uint8 _midiChannelsOctTable[9];
+	uint16 _adlibChannelsVolume[11];
+	uint16 _adlibMetaSequenceData[28];
+
+	static const uint8 _adlibChannelsMappingTable1[];
+	static const uint8 _adlibChannelsNoFeedback[];
+	static const uint8 _adlibChannelsMappingTable2[];
+	static const uint8 _adlibChannelsMappingTable3[];
+	static const uint8 _adlibChannelsKeyScalingTable1[];
+	static const uint8 _adlibChannelsKeyScalingTable2[];
+	static const uint8 _adlibChannelsVolumeTable[];
+	static const uint8 _adlibInitSequenceData1[];
+	static const uint8 _adlibInitSequenceData2[];
+	static const uint8 _adlibInitSequenceData3[];
+	static const uint8 _adlibInitSequenceData4[];
+	static const uint8 _adlibInitSequenceData5[];
+	static const uint8 _adlibInitSequenceData6[];
+	static const uint8 _adlibInitSequenceData7[];
+	static const uint8 _adlibInitSequenceData8[];
+	static const int16 _midiChannelsNoteTable[];
+	static const int16 _midiNoteFreqTable[];
+};
+
+int AdlibMidiDriver::open() {
+	MidiDriver_Emulated::open();
+	_opl = makeAdlibOPL(getRate());
+	Adlib_SetupCard();
+	for (int i = 0; i < 11; ++i) {
+		_adlibChannelsVolume[i] = 0;
+		Adlib_SetNoteVolume(i, 0);
+		Adlib_TurnNoteOff(i);
+	}
+	_mixer->playInputStream(Audio::Mixer::kPlainSoundType, &_mixerSoundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, false, true);
+	return 0;
+}
+
+void AdlibMidiDriver::close() {
+	_mixer->stopHandle(_mixerSoundHandle);
+	OPLDestroy(_opl);
+}
+
+void AdlibMidiDriver::send(uint32 b) {
+	int channel = b & 15;
+	int cmd = (b >> 4) & 7;
+	int param1 = (b >> 8) & 255;
+	int param2 = (b >> 16) & 255;
+	switch (cmd) {
+	case 0:
+		Adlib_TurnNoteOff(channel);
+		break;
+	case 1:
+		handleMidiEvent0x90_NoteOn(channel, param1, param2);
+		break;
+	case 3:
+		break;
+	case 5:
+		Adlib_SetNoteVolume(channel, param1);
+		_adlibChannelsVolume[channel] = param1;
+		break;
+	case 6:
+		Adlib_SetPitchBend(channel, param1 | (param2 << 7));
+		break;
+	default:
+//		warning("Unhandled cmd %d channel %d (0x%X)\n", cmd, channel, b);
+		break;
+	}
+}
+
+void AdlibMidiDriver::metaEvent(byte type, byte *data, uint16 length) {
+	int event = 0;
+	if (length > 4 && READ_BE_UINT32(data) == 0x3F00) {
+		event = data[4];
+		switch (event) {
+		case 1:
+			if (length == 34) {
+				handleSequencerSpecificMetaEvent1(data[5], data + 6);
+				return;
+			}
+			break;
+		case 2:
+			if (length == 6) {
+				handleSequencerSpecificMetaEvent2(data[5]);
+				return;
+			}
+			break;
+		case 3:
+			if (length == 6) {
+				handleSequencerSpecificMetaEvent3(data[5]);
+				return;
+			}
+			break;
+		}
+	}
+	warning("Unhandled meta event %d len %d", event, length);
+}
+
+void AdlibMidiDriver::generateSamples(int16 *data, int len) {
+	memset(data, 0, sizeof(int16) * len);
+	YM3812UpdateOne(_opl, data, len);
+}
+
+void AdlibMidiDriver::handleSequencerSpecificMetaEvent1(int channel, const uint8 *data) {
+	for (int i = 0; i < 28; ++i) {
+		_adlibMetaSequenceData[i] = data[i];
+	}
+	if (_midiNumberOfChannels > channel) {
+		const uint8 *p;
+		if (_adlibRhythmEnabled) {
+			p = &_adlibChannelsKeyScalingTable2[channel * 2];
+		} else {
+			p = &_adlibChannelsKeyScalingTable1[channel * 2];
+		}
+		Adlib_SetupChannel(p[0], _adlibMetaSequenceData, _adlibMetaSequenceData[26]);
+		if (p[1] != 255) {
+			Adlib_SetupChannel(p[1], _adlibMetaSequenceData + 13, _adlibMetaSequenceData[27]);
+		}
+	}
+}
+
+void AdlibMidiDriver::handleSequencerSpecificMetaEvent2(uint8 value) {
+	_adlibRhythmEnabled = value;
+	_midiNumberOfChannels = _adlibRhythmEnabled ? 11 : 9;
+	Adlib_SetAmpVibratoRhythm();
+}
+
+void AdlibMidiDriver::handleSequencerSpecificMetaEvent3(uint8 value) {
+	Adlib_SetNoteMul(value);
+}
+
+void AdlibMidiDriver::handleMidiEvent0x90_NoteOn(int channel, int param1, int param2) { // note, volume
+	if (param2 == 0) {
+		Adlib_TurnNoteOff(channel);
+		_adlibChannelsVolume[channel] = param2;
+	} else {
+		Adlib_SetNoteVolume(channel, param2);
+		_adlibChannelsVolume[channel] = param2;
+		Adlib_TurnNoteOff(channel);
+		Adlib_TurnNoteOn(channel, param1);
+	}
+}
+
+void AdlibMidiDriver::Adlib_Write(uint8 port, uint8 value) {
+	OPLWriteReg(_opl, port, value);
+}
+
+void AdlibMidiDriver::Adlib_SetupCard() {
+	for (int i = 1; i <= 0xF5; ++i) {
+		Adlib_Write(i, 0);
+	}
+	Adlib_Write(4, 6);
+	for (int i = 0; i < 9; ++i) {
+		_midiChannelsNote2Table[i] = 8192;
+		_midiChannelsOctTable[i] = 0;
+		_midiChannelsNote1Table[i] = 0;
+		_midiChannelsFreqTable[i] = 0;
+	}
+	memset(_adlibChannelsLevelKeyScalingTable, 127, 11);
+	Adlib_SetupChannels(0);
+	Adlib_ResetAmpVibratoRhythm(0, 0, 0);
+	Adlib_SetNoteMul(1);
+	Adlib_SetWaveformSelect(1);
+}
+
+void AdlibMidiDriver::Adlib_SetupChannels(int fl) {
+	if (fl != 0) {
+		_midiChannelsNote1Table[8] = 24;
+		_midiChannelsNote2Table[8] = 8192;
+		Adlib_PlayNote(8);
+		_midiChannelsNote1Table[7] = 31;
+		_midiChannelsNote2Table[7] = 8192;
+		Adlib_PlayNote(7);
+	}
+	_adlibRhythmEnabled = fl;
+	_midiNumberOfChannels = fl ? 11 : 9;
+	_adlibVibratoRhythm = 0;
+	_adlibAMDepthEq48 = 0;
+	_adlibVibratoDepthEq14 = 0;
+	_adlibKeyboardSplitOn = 0;
+	Adlib_ResetChannels();
+	Adlib_SetAmpVibratoRhythm();
+}
+
+void AdlibMidiDriver::Adlib_ResetAmpVibratoRhythm(int am, int vib, int kso) {
+	_adlibAMDepthEq48 = am;
+	_adlibVibratoDepthEq14 = vib;
+	_adlibKeyboardSplitOn = kso;
+	Adlib_SetAmpVibratoRhythm();
+	Adlib_SetCSMKeyboardSplit();
+}
+
+void AdlibMidiDriver::Adlib_ResetChannels() {
+	for (int i = 0; i < 18; ++i) {
+		Adlib_SetupChannelFromSequence(i, _adlibChannelsNoFeedback[i] ? _adlibInitSequenceData2 : _adlibInitSequenceData1, 0);
+	}
+	if (_adlibRhythmEnabled) {
+		Adlib_SetupChannelFromSequence(12, _adlibInitSequenceData3, 0);
+		Adlib_SetupChannelFromSequence(15, _adlibInitSequenceData4, 0);
+		Adlib_SetupChannelFromSequence(16, _adlibInitSequenceData5, 0);
+		Adlib_SetupChannelFromSequence(14, _adlibInitSequenceData6, 0);
+		Adlib_SetupChannelFromSequence(17, _adlibInitSequenceData7, 0);
+		Adlib_SetupChannelFromSequence(13, _adlibInitSequenceData8, 0);
+	}
+}
+
+void AdlibMidiDriver::Adlib_SetAmpVibratoRhythm() {
+	uint8 value = 0;
+	if (_adlibAMDepthEq48) {
+		value |= 0x80;
+	}
+	if (_adlibVibratoDepthEq14) {
+		value |= 0x40;
+	}
+	if (_adlibRhythmEnabled) {
+		value |= 0x20;
+	}
+	Adlib_Write(0xBD, value | _adlibVibratoRhythm);
+}
+
+void AdlibMidiDriver::Adlib_SetCSMKeyboardSplit() {
+	uint8 value = _adlibKeyboardSplitOn ? 0x40 : 0;
+	Adlib_Write(8, value);
+}
+
+void AdlibMidiDriver::Adlib_SetNoteMul(int mul) {
+	if (mul > 12) {
+		mul = 12;
+	} else if (mul < 1) {
+		mul = 1;
+	}
+	_adlibNoteMul = mul;
+}
+
+void AdlibMidiDriver::Adlib_SetWaveformSelect(int fl) {
+	_adlibWaveformSelect = fl ? 0x20 : 0;
+	for (int i = 0; i < 18; ++i) {
+		Adlib_Write(0xE0 + _adlibChannelsMappingTable1[i], 0);
+	}
+	Adlib_Write(1, _adlibWaveformSelect);
+}
+
+void AdlibMidiDriver::Adlib_SetPitchBend(int channel, int range) {
+	if ((_adlibRhythmEnabled && channel <= 6) || channel < 9) {
+		if (range > 16383) {
+			range = 16383;
+		}
+		_midiChannelsNote2Table[channel] = range;
+		Adlib_PlayNote(channel);
+	}
+}
+
+void AdlibMidiDriver::Adlib_PlayNote(int channel) {
+	_midiChannelsFreqTable[channel] = Adlib_PlayNoteHelper(channel, _midiChannelsNote1Table[channel], _midiChannelsNote2Table[channel], _midiChannelsOctTable[channel]);
+}
+
+uint8 AdlibMidiDriver::Adlib_PlayNoteHelper(int channel, int note1, int note2, int oct) {
+	int n = ((note2 * _midiChannelsNoteTable[channel]) >> 8) - 8192;
+	if (n != 0) {
+		n >>= 5;
+		n *= _adlibNoteMul;
+	}
+	n += (note1 << 8) + 8;
+	n >>= 4;
+	if (n < 0) {
+		n = 0;
+	} else if (n > 1535) {
+		n = 1535;
+	}
+	int index = (((n >> 4) % 12) << 4) | (n & 0xF);
+	int f = _midiNoteFreqTable[index];
+	int o = (n >> 4) / 12 - 1;
+	if (f < 0) {
+		++o;
+	}
+	if (o < 0) {
+		++o;
+		f >>= 1;
+	}
+	Adlib_Write(0xA0 + channel, f & 0xFF);
+	int value = ((f >> 8) & 3) | (o << 2) | oct;
+	Adlib_Write(0xB0 + channel, value);
+	return value;
+}
+
+void AdlibMidiDriver::Adlib_TurnNoteOff(int channel) {
+	if ((_adlibRhythmEnabled && channel <= 6) || channel < 9) {
+		_midiChannelsOctTable[channel] = 0;
+		_midiChannelsFreqTable[channel] &= ~0x20;
+		Adlib_Write(0xB0 + channel, _midiChannelsFreqTable[channel]);
+	} else if (_adlibRhythmEnabled && channel <= 10) {
+		_adlibVibratoRhythm &= ~(1 << (4 - (channel - 6)));
+		Adlib_SetAmpVibratoRhythm();
+	}
+}
+
+void AdlibMidiDriver::Adlib_TurnNoteOn(int channel, int note) {
+	note -= 12;
+	if (note < 0) {
+		note = 0;
+	}
+	if ((_adlibRhythmEnabled && channel <= 6) || channel < 9) {
+		_midiChannelsNote1Table[channel] = note;
+		_midiChannelsOctTable[channel] = 0x20;
+		Adlib_PlayNote(channel);
+	} else if (_adlibRhythmEnabled && channel <= 10) {
+		if (channel == 6) {
+			_midiChannelsNote1Table[6] = note;
+			Adlib_PlayNote(channel);
+		} else if (channel == 8 && _midiChannelsNote1Table[8] == note) {
+			_midiChannelsNote1Table[8] = note;
+			_midiChannelsNote1Table[7] = note + 7;
+			Adlib_PlayNote(8);
+			Adlib_PlayNote(7);
+		}
+		_adlibVibratoRhythm = 1 << (4 - (channel - 6));
+		Adlib_SetAmpVibratoRhythm();
+	}
+}
+
+void AdlibMidiDriver::Adlib_SetupChannelFromSequence(int channel, const uint8 *src, int fl) {
+	for (int i = 0; i < 13; ++i) {
+		_adlibSetupChannelSequence2[i] = src[i];
+	}
+	Adlib_SetupChannel(channel, _adlibSetupChannelSequence2, fl);
+}
+
+void AdlibMidiDriver::Adlib_SetupChannel(int channel, const uint16 *src, int fl) {
+	for (int i = 0; i < 13; ++i) {
+		_adlibSetupChannelSequence1[14 * channel + i] = src[i];
+	}
+	_adlibSetupChannelSequence1[14 * channel + 13] = fl & 3;
+	Adlib_SetupChannelHelper(channel);
+}
+
+void AdlibMidiDriver::Adlib_SetNoteVolume(int channel, int volume) {
+	if (_midiNumberOfChannels > channel) {
+		if (volume > 127) {
+			volume = 127;
+		}
+		_adlibChannelsLevelKeyScalingTable[channel] = volume;
+		const uint8 *p;
+		if (_adlibRhythmEnabled) {
+			p = &_adlibChannelsKeyScalingTable2[channel * 2];
+		} else {
+			p = &_adlibChannelsKeyScalingTable1[channel * 2];
+		}
+		Adlib_SetChannel0x40(p[0]);
+		if (p[1] != 255) {
+			Adlib_SetChannel0x40(p[1]);
+		}
+	}
+}
+
+void AdlibMidiDriver::Adlib_SetupChannelHelper(int channel) {
+	Adlib_SetAmpVibratoRhythm();
+	Adlib_SetCSMKeyboardSplit();
+	Adlib_SetChannel0x40(channel);
+	Adlib_SetChannel0xC0(channel);
+	Adlib_SetChannel0x60(channel);
+	Adlib_SetChannel0x80(channel);
+	Adlib_SetChannel0x20(channel);
+	Adlib_SetChannel0xE0(channel);
+}
+
+void AdlibMidiDriver::Adlib_SetChannel0x40(int channel) {
+	int index, value, fl;
+
+	if (_adlibRhythmEnabled) {
+		index = _adlibChannelsMappingTable3[channel];
+	} else {
+		index = _adlibChannelsMappingTable2[channel];
+	}
+	value = 63 - (_adlibSetupChannelSequence1[channel * 14 + 8] & 63);
+	fl = 0;
+	if (_adlibRhythmEnabled && index > 6) {
+		fl = -1;
+	}
+	if (_adlibChannelsNoFeedback[channel] || _adlibSetupChannelSequence1[channel * 14 + 12] == 0 || fl != 0) {
+		value = ((_adlibChannelsLevelKeyScalingTable[index] * value) + 64) >> 7;
+	}
+	value = (_adlibChannelsVolumeTable[index] * value * 2) >> 8;
+	if (value > 63) {
+		value = 63;
+	}
+	value = 63 - value;
+	value |= _adlibSetupChannelSequence1[channel * 14] << 6;
+	Adlib_Write(0x40 + _adlibChannelsMappingTable1[channel], value);
+}
+
+void AdlibMidiDriver::Adlib_SetChannel0xC0(int channel) {
+	if (_adlibChannelsNoFeedback[channel] == 0) {
+		const uint8 *p = &_adlibSetupChannelSequence1[channel * 14];
+		uint8 value = p[2] << 1;
+		if (p[12] == 0) {
+			value |= 1;
+		}
+		Adlib_Write(0xC0 + _adlibChannelsMappingTable2[channel], value);
+	}
+}
+
+void AdlibMidiDriver::Adlib_SetChannel0x60(int channel) {
+	const uint8 *p = &_adlibSetupChannelSequence1[channel * 14];
+	uint8 value = (p[3] << 4) | (p[6] & 15);
+	Adlib_Write(0x60 + _adlibChannelsMappingTable1[channel], value);
+}
+
+void AdlibMidiDriver::Adlib_SetChannel0x80(int channel) {
+	const uint8 *p = &_adlibSetupChannelSequence1[channel * 14];
+	uint8 value = (p[4] << 4) | (p[7] & 15);
+	Adlib_Write(0x80 + _adlibChannelsMappingTable1[channel], value);
+}
+
+void AdlibMidiDriver::Adlib_SetChannel0x20(int channel) {
+	const uint8 *p = &_adlibSetupChannelSequence1[channel * 14];
+	uint8 value = p[1] & 15;
+	if (p[9]) {
+		value |= 0x80;
+	}
+	if (p[10]) {
+		value |= 0x40;
+	}
+	if (p[5]) {
+		value |= 0x20;
+	}
+	if (p[11]) {
+		value |= 0x10;
+	}
+	Adlib_Write(0x20 + _adlibChannelsMappingTable1[channel], value);
+}
+
+void AdlibMidiDriver::Adlib_SetChannel0xE0(int channel) {
+	uint8 value = 0;
+	if (_adlibWaveformSelect) {
+		const uint8 *p = &_adlibSetupChannelSequence1[channel * 14];
+		value = p[13] & 3;
+	}
+	Adlib_Write(0xE0 + _adlibChannelsMappingTable1[channel], value);
+}
+
+const uint8 AdlibMidiDriver::_adlibChannelsMappingTable1[] = {
+	0, 1, 2, 3, 4, 5, 8, 9, 10, 11, 12, 13, 16, 17, 18, 19, 20, 21
+};
+
+const uint8 AdlibMidiDriver::_adlibChannelsNoFeedback[] = {
+	0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1
+};
+
+const uint8 AdlibMidiDriver::_adlibChannelsMappingTable2[] = {
+	0, 1, 2, 0, 1, 2, 3, 4, 5, 3, 4, 5, 6, 7, 8, 6, 7, 8
+};
+
+const uint8 AdlibMidiDriver::_adlibChannelsMappingTable3[] = {
+	0, 1, 2, 0, 1, 2, 3, 4, 5, 3, 4, 5, 6, 10, 8, 6, 7, 9
+};
+
+const uint8 AdlibMidiDriver::_adlibChannelsKeyScalingTable1[] = {
+	0, 3, 1, 4, 2, 5, 6, 9, 7, 10, 8, 11, 12, 15, 13, 16, 14, 17
+};
+
+const uint8 AdlibMidiDriver::_adlibChannelsKeyScalingTable2[] = {
+	0, 3, 1, 4, 2, 5, 6, 9, 7, 10, 8, 11, 12, 15, 16, 255, 14, 255, 17, 255, 13, 255
+};
+
+const uint8 AdlibMidiDriver::_adlibChannelsVolumeTable[] = {
+	128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128
+};
+
+const uint8 AdlibMidiDriver::_adlibInitSequenceData1[] = {
+	1, 1, 3, 15, 5, 0, 1, 3, 15, 0, 0, 0, 1, 0
+};
+
+const uint8 AdlibMidiDriver::_adlibInitSequenceData2[] = {
+	0, 1, 1, 15, 7, 0, 2, 4, 0, 0, 0, 1, 0, 0
+};
+
+const uint8 AdlibMidiDriver::_adlibInitSequenceData3[] = {
+	0, 0, 0, 10, 4, 0, 8, 12, 11, 0, 0, 0, 1, 0
+};
+
+const uint8 AdlibMidiDriver::_adlibInitSequenceData4[] = {
+	0, 0, 0, 13, 4, 0, 6, 15, 0, 0, 0, 0, 1, 0
+};
+
+const uint8 AdlibMidiDriver::_adlibInitSequenceData5[] = {
+	0, 12, 0, 15, 11, 0, 8, 5, 0, 0, 0, 0, 0, 0
+};
+
+const uint8 AdlibMidiDriver::_adlibInitSequenceData6[] = {
+	0, 4, 0, 15, 11, 0, 7, 5, 0, 0, 0, 0, 0, 0
+};
+
+const uint8 AdlibMidiDriver::_adlibInitSequenceData7[] = {
+	0, 1, 0, 15, 11, 0, 5, 5, 0, 0, 0, 0, 0, 0
+};
+
+const uint8 AdlibMidiDriver::_adlibInitSequenceData8[] = {
+	0, 1, 0, 15, 11, 0, 7, 5, 0, 0, 0, 0, 0, 0
+};
+
+const int16 AdlibMidiDriver::_midiChannelsNoteTable[] = {
+	256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256
+};
+
+const int16 AdlibMidiDriver::_midiNoteFreqTable[] = {
+	 690,  692,  695,  697,  700,  702,  705,  707,  710,  713,  715,  718,
+	 720,  723,  726,  728,  731,  733,  736,  739,  741,  744,  747,  749,
+	 752,  755,  758,  760,  763,  766,  769,  771,  774,  777,  780,  783,
+	 785,  788,  791,  794,  797,  800,  803,  806,  809,  811,  814,  817,
+	 820,  823,  826,  829,  832,  835,  838,  841,  844,  847,  850,  854,
+	 857,  860,  863,  866,  869,  872,  875,  879,  882,  885,  888,  891,
+	 895,  898,  901,  904,  908,  911,  914,  917,  921,  924,  927,  931,
+	 934,  937,  941,  944,  948,  951,  955,  958,  961,  965,  968,  972,
+	 975,  979,  983,  986,  990,  993,  997, 1000, 1004, 1008, 1011, 1015,
+	1019, 1022, -511, -509, -507, -505, -504, -502, -500, -498, -496, -494,
+	-492, -490, -488, -486, -484, -482, -480, -479, -477, -475, -473, -471,
+	-469, -467, -465, -463, -460, -458, -456, -454, -452, -450, -448, -446,
+	-444, -442, -440, -438, -436, -433, -431, -429, -427, -425, -423, -420,
+	-418, -416, -414, -412, -409, -407, -405, -403, -401, -398, -396, -394,
+	-391, -389, -387, -385, -382, -380, -378, -375, -373, -371, -368, -366,
+	-363, -361, -359, -356, -354, -351, -349, -347, -344, -342, -339, -337
+};
+
+MidiDriver *C_Player_CreateAdlibMidiDriver(Audio::Mixer *mixer) {
+	return new AdlibMidiDriver(mixer);
+}
+
+} // End of namespace Queen


Property changes on: scummvm/trunk/engines/queen/midiadlib.cpp
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:keywords
   + Date Rev Author URL Id
Name: svn:eol-style
   + native

Modified: scummvm/trunk/engines/queen/module.mk
===================================================================
--- scummvm/trunk/engines/queen/module.mk	2007-11-15 11:33:16 UTC (rev 29508)
+++ scummvm/trunk/engines/queen/module.mk	2007-11-15 20:21:33 UTC (rev 29509)
@@ -12,6 +12,7 @@
 	input.o \
 	journal.o \
 	logic.o \
+	midiadlib.o \
 	music.o \
 	musicdata.o \
 	queen.o \
@@ -27,5 +28,5 @@
 PLUGIN := 1
 endif
 
-# Include common rules 
+# Include common rules
 include $(srcdir)/rules.mk

Modified: scummvm/trunk/engines/queen/music.cpp
===================================================================
--- scummvm/trunk/engines/queen/music.cpp	2007-11-15 11:33:16 UTC (rev 29508)
+++ scummvm/trunk/engines/queen/music.cpp	2007-11-15 20:21:33 UTC (rev 29509)
@@ -23,6 +23,7 @@
  *
  */
 
+#include "common/config-manager.h"
 #include "common/events.h"
 
 #include "queen/music.h"
@@ -34,28 +35,64 @@
 
 namespace Queen {
 
-MidiMusic::MidiMusic(MidiDriver *driver, QueenEngine *vm)
-	: _driver(driver), _isPlaying(false), _looping(false), _randomLoop(false), _masterVolume(192), _queuePos(0), _passThrough(false), _buf(0) {
+extern MidiDriver *C_Player_CreateAdlibMidiDriver(Audio::Mixer *);
+
+MidiMusic::MidiMusic(QueenEngine *vm)
+	: _isPlaying(false), _looping(false), _randomLoop(false), _masterVolume(192), _buf(0) {
+
 	memset(_channel, 0, sizeof(_channel));
+	_queuePos = _lastSong = _currentSong = 0;
 	queueClear();
-	_lastSong = _currentSong = 0;
+
+	int midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI);
+	_adlib = (midiDriver == MD_ADLIB);
+	_nativeMT32 = ((midiDriver == MD_MT32) || ConfMan.getBool("native_mt32"));
+
+	const char *musicDataFile;
+	if (vm->resource()->isDemo()) {
+		_tune = Sound::_tuneDemo;
+		musicDataFile = "AQ8.RL";
+	} else {
+		_tune = Sound::_tune;
+		musicDataFile = "AQ.RL";
+	}
+	if (_adlib) {
+		musicDataFile = "AQBANK.MUS";
+	}
+	_musicData = vm->resource()->loadFile(musicDataFile, 0, &_musicDataSize);
+	_numSongs = READ_LE_UINT16(_musicData);
+
+	_tune = vm->resource()->isDemo() ? Sound::_tuneDemo : Sound::_tune;
+
+	if (_adlib) {
+//		int infoOffset = _numSongs * 4 + 2;
+//		if (READ_LE_UINT16(_musicData + 2) != infoOffset) {
+//			defaultAdlibVolume = _musicData[infoOffset];
+//		}
+		_driver = C_Player_CreateAdlibMidiDriver(vm->_mixer);
+	} else {
+		_driver = MidiDriver::createMidi(midiDriver);
+		if (_nativeMT32) {
+			_driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
+		}
+	}
+
+	_driver->open();
+	_driver->setTimerCallback(this, &onTimer);
+
 	_parser = MidiParser::createParser_SMF();
 	_parser->setMidiDriver(this);
 	_parser->setTimerRate(_driver->getBaseTempo());
 
-	const char *filename = vm->resource()->isDemo() ? "AQ8.RL" : "AQ.RL";
-	_musicData = vm->resource()->loadFile(filename, 0, &_musicDataSize);
-	_numSongs = READ_LE_UINT16(_musicData);
-	this->open();
-
-	_tune = vm->resource()->isDemo() ? Sound::_tuneDemo : Sound::_tune;
 	vm->_system->getEventManager()->registerRandomSource(_rnd, "queenMusic");
 }
 
 MidiMusic::~MidiMusic() {
+	_driver->setTimerCallback(0, 0);
+	_driver->close();
+	delete _driver;
 	_parser->unloadMusic();
 	delete _parser;
-	this->close();
 	delete[] _buf;
 	delete[] _musicData;
 }
@@ -100,7 +137,7 @@
 
 	// Work around bug in Roland music, note that these numbers are 'one-off'
 	// from the original code
-	if (/*isRoland && */ songNum == 88 || songNum == 89)
+	if (!_adlib && (songNum == 88 || songNum == 89))
 		songNum = 62;
 
 	_songQueue[MUSIC_QUEUE_SIZE - emptySlots] = songNum;
@@ -114,27 +151,8 @@
 	memset(_songQueue, 0, sizeof(_songQueue));
 }
 
-int MidiMusic::open() {
-	// Don't ever call open without first setting the output driver!
-	if (!_driver)
-		return 255;
-
-	int ret = _driver->open();
-	if (ret)
-		return ret;
-	_driver->setTimerCallback(this, &onTimer);
-	return 0;
-}
-
-void MidiMusic::close() {
-	_driver->setTimerCallback(NULL, NULL);
-	if (_driver)
-		_driver->close();
-	_driver = 0;
-}
-
 void MidiMusic::send(uint32 b) {
-	if (_passThrough) {
+	if (_adlib) {
 		_driver->send(b);
 		return;
 	}
@@ -146,13 +164,12 @@
 		_channelVolume[channel] = volume;
 		volume = volume * _masterVolume / 255;
 		b = (b & 0xFF00FFFF) | (volume << 16);
-	} else if ((b & 0xF0) == 0xC0 && !_nativeMT32) {
+	} else if ((b & 0xF0) == 0xC0 && !_adlib && !_nativeMT32) {
 		b = (b & 0xFFFF00FF) | MidiDriver::_mt32ToGm[(b >> 8) & 0xFF] << 8;
-	}
-	else if ((b & 0xFFF0) == 0x007BB0) {
+	} else if ((b & 0xFFF0) == 0x007BB0) {
 		//Only respond to All Notes Off if this channel
 		//has currently been allocated
-		if (_channel[b & 0x0F])
+		if (_channel[channel])
 			return;
 	}
 
@@ -172,14 +189,23 @@
 }
 
 void MidiMusic::metaEvent(byte type, byte *data, uint16 length) {
-	//Only thing we care about is End of Track.
-	if (type != 0x2F)
-		return;
-
-	if (_looping || _songQueue[1])
-		playMusic();
-	else
-		stopMusic();
+	switch (type) {
+	case 0x2F: // End of Track
+		if (_looping || _songQueue[1]) {
+			playMusic();
+		} else {
+			stopMusic();
+		}
+		break;
+	case 0x7F: // Specific
+		if (_adlib) {
+			_driver->metaEvent(type, data, length);
+		}
+		break;
+	default:
+//		warning("Unhandled meta event: %02x", type);
+		break;
+	}
 }
 
 void MidiMusic::onTimer(void *refCon) {
@@ -248,7 +274,7 @@
 	}
 
 	byte *prevSong = _musicData + songOffset(_currentSong);
-	if (*prevSong == 0x43 || *prevSong == 0x63) {
+	if (*prevSong == 'C' || *prevSong == 'c') {
 		if (_buf) {
 			delete[] _buf;
 			_buf = 0;
@@ -263,7 +289,7 @@
 
 	byte *musicPtr = _musicData + songOffset(songNum);
 	uint32 size = songLength(songNum);
-	if (*musicPtr == 0x43 || *musicPtr == 0x63) {
+	if (*musicPtr == 'C' || *musicPtr == 'c') {
 		uint32 packedSize = songLength(songNum) - 0x200;
 		_buf = new uint16[packedSize];
 
@@ -277,7 +303,7 @@
 			_buf[i] = data[*(idx + i)];
 #endif
 
-		musicPtr = ((byte *)_buf) + ((*musicPtr == 0x63) ? 1 : 0);
+		musicPtr = ((byte *)_buf) + ((*musicPtr == 'c') ? 1 : 0);
 		size = packedSize * 2;
 	}
 

Modified: scummvm/trunk/engines/queen/music.h
===================================================================
--- scummvm/trunk/engines/queen/music.h	2007-11-15 11:33:16 UTC (rev 29508)
+++ scummvm/trunk/engines/queen/music.h	2007-11-15 20:21:33 UTC (rev 29509)
@@ -33,18 +33,17 @@
 
 namespace Queen {
 
-struct tuneData;
+struct TuneData;
 
 class QueenEngine;
 
 class MidiMusic : public MidiDriver {
 public:
-	MidiMusic(MidiDriver *driver, QueenEngine *vm);
+	MidiMusic(QueenEngine *vm);
 	~MidiMusic();
 	void setVolume(int volume);
-	int getVolume()			{ return _masterVolume; }
+	int getVolume()	const { return _masterVolume; }
 
-	void hasNativeMT32(bool b)	{ _nativeMT32 = b; }
 	void playSong(uint16 songNum);
 	void stopSong() { stopMusic(); }
 	void playMusic();
@@ -53,12 +52,11 @@
 	void queueTuneList(int16 tuneList);
 	bool queueSong(uint16 songNum);
 	void queueClear();
-	void setPassThrough(bool b)		{ _passThrough = b; }
 	void toggleVChange();
 
 	//MidiDriver interface implementation
-	int open();
-	void close();
+	int open() { return 0; }
+	void close() {}
 	void send(uint32 b);
 
 	void metaEvent(byte type, byte *data, uint16 length);
@@ -86,8 +84,8 @@
 	MidiParser *_parser;
 	MidiChannel *_channel[16];
 	byte _channelVolume[16];
+	bool _adlib;
 	bool _nativeMT32;
-	bool _passThrough;
 
 	Common::RandomSource _rnd;
 
@@ -105,7 +103,7 @@
 	uint32 _musicDataSize;
 	bool _vToggle;
 	byte *_musicData;
-	const tuneData *_tune;
+	const TuneData *_tune;
 };
 
 } // End of namespace Queen

Modified: scummvm/trunk/engines/queen/musicdata.cpp
===================================================================
--- scummvm/trunk/engines/queen/musicdata.cpp	2007-11-15 11:33:16 UTC (rev 29508)
+++ scummvm/trunk/engines/queen/musicdata.cpp	2007-11-15 20:21:33 UTC (rev 29509)
@@ -28,7 +28,7 @@
 
 namespace Queen {
 
-const songData Sound::_songDemo[] = {
+const SongData Sound::_songDemo[] = {
 	/* 1 - Hotel Gangsters */
 	{ { 1, 0 }, 128, 128, 128, 1, 0 },
 
@@ -123,7 +123,7 @@
 	{ { 34, 0 }, 128, 128, 128, 1, 1 },
 };
 
-const songData Sound::_song[] = {
+const SongData Sound::_song[] = {
 	/* 1 - Hotel Gangsters */
 	{ { 1, 0 }, 128, 180, 0, 1, 0 },
 
@@ -752,7 +752,7 @@
 	{ { 212, 0 }, 128, 128, 128, 1, 0 }
 };
 
-const tuneData Sound::_tuneDemo[] = {
+const TuneData Sound::_tuneDemo[] = {
 	/* 1 - Hotel Gangsters */
 	{ { 32, 0 }, { 0, 0 }, 1, 0 },
 
@@ -859,7 +859,7 @@
 	{ { 46, 0 }, { 0, 0 }, 1, 0 },
 };
 
-const tuneData Sound::_tune[] = {
+const TuneData Sound::_tune[] = {
 	/* 1 - Hotel Gangsters */
 	{ { 32, 0 }, { 0, 0 }, 1, 0 },
 

Modified: scummvm/trunk/engines/queen/sound.cpp
===================================================================
--- scummvm/trunk/engines/queen/sound.cpp	2007-11-15 11:33:16 UTC (rev 29508)
+++ scummvm/trunk/engines/queen/sound.cpp	2007-11-15 20:21:33 UTC (rev 29509)
@@ -157,15 +157,7 @@
 PCSound::PCSound(Audio::Mixer *mixer, QueenEngine *vm)
 	: Sound(mixer, vm) {
 
-	int midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI);
-	bool native_mt32 = ((midiDriver == MD_MT32) || ConfMan.getBool("native_mt32"));
-
-	MidiDriver *driver = MidiDriver::createMidi(midiDriver);
-	if (native_mt32)
-		driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
-
-	_music = new MidiMusic(driver, vm);
-	_music->hasNativeMT32(native_mt32);
+	_music = new MidiMusic(vm);
 }
 
 PCSound::~PCSound() {

Modified: scummvm/trunk/engines/queen/sound.h
===================================================================
--- scummvm/trunk/engines/queen/sound.h	2007-11-15 11:33:16 UTC (rev 29508)
+++ scummvm/trunk/engines/queen/sound.h	2007-11-15 20:21:33 UTC (rev 29509)
@@ -37,7 +37,7 @@
 
 namespace Queen {
 
-struct songData {
+struct SongData {
 	int16 tuneList[5];
 	int16 volume;
 	int16 tempo;
@@ -46,7 +46,7 @@
 	int16 ignore;
 };
 
-struct tuneData {
+struct TuneData {
 	int16 tuneNum[9];
 	int16 sfx[2];
 	int16 mode;
@@ -103,10 +103,10 @@
 	void saveState(byte *&ptr);
 	void loadState(uint32 ver, byte *&ptr);
 
-	static const songData _songDemo[];
-	static const songData _song[];
-	static const tuneData _tuneDemo[];
-	static const tuneData _tune[];
+	static const SongData _songDemo[];
+	static const SongData _song[];
+	static const TuneData _tuneDemo[];
+	static const TuneData _tune[];
 	static const char *_sfxName[];
 	static const int16 _jungleList[];
 


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list