[Scummvm-cvs-logs] scummvm master -> 66df9c95e0eea427527491e964b40adc2a9def05

lordhoto lordhoto at gmail.com
Thu Jul 23 22:41:08 CEST 2015


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

Summary:
979a885ef9 AGOS: Add initial version of Simon1 DOS AdLib output.
33c57c632c Revert "AGOS: Add updated patch for #647 - Simon 1 DOS Adlib instrument bank"
cf42dc0a35 AGOS: Slight cleanup in Simon1 AdLib output initialization code.
757077fecc AGOS: Add simple volume control when Simon1 AdLib output is used.
01eda204d6 NEWS: Mention Simon1 AdLib output addition.
66df9c95e0 NEWS: Slight style fix (MT32 to MT-32).


Commit: 979a885ef9785afbed650dfffc8c5af6af8ea8e5
    https://github.com/scummvm/scummvm/commit/979a885ef9785afbed650dfffc8c5af6af8ea8e5
Author: Johannes Schickel (lordhoto at scummvm.org)
Date: 2015-07-23T22:33:56+02:00

Commit Message:
AGOS: Add initial version of Simon1 DOS AdLib output.

Testing so far has not really happened. Only the first part of the intro has
been tested.

Changed paths:
  A engines/agos/drivers/simon1/adlib.cpp
  A engines/agos/drivers/simon1/adlib.h
    engines/agos/midi.cpp
    engines/agos/midi.h
    engines/agos/module.mk



diff --git a/engines/agos/drivers/simon1/adlib.cpp b/engines/agos/drivers/simon1/adlib.cpp
new file mode 100644
index 0000000..d331b86
--- /dev/null
+++ b/engines/agos/drivers/simon1/adlib.cpp
@@ -0,0 +1,494 @@
+/* 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 "agos/drivers/simon1/adlib.h"
+
+#include "common/textconsole.h"
+#include "common/util.h"
+
+namespace AGOS {
+
+enum {
+	kChannelUnused       = 0xFF,
+	kChannelOrphanedFlag = 0x80,
+
+	kOPLVoicesCount = 9
+};
+
+MidiDriver_Simon1_AdLib::Voice::Voice()
+    : channel(kChannelUnused), note(0), instrTotalLevel(0), instrScalingLevel(0), frequency(0) {
+}
+
+MidiDriver_Simon1_AdLib::MidiDriver_Simon1_AdLib(const byte *instrumentData)
+    : _isOpen(false), _opl(nullptr), _timerProc(nullptr), _timerParam(nullptr),
+      _melodyVoices(0), _amvdrBits(0), _rhythmEnabled(false), _voices(), _midiPrograms(),
+      _instruments(instrumentData) {
+}
+
+MidiDriver_Simon1_AdLib::~MidiDriver_Simon1_AdLib() {
+	close();
+	delete[] _instruments;
+}
+
+int MidiDriver_Simon1_AdLib::open() {
+	if (_isOpen) {
+		return MERR_ALREADY_OPEN;
+	}
+
+	_opl = OPL::Config::create();
+	if (!_opl) {
+		return MERR_DEVICE_NOT_AVAILABLE;
+	}
+
+	if (!_opl->init()) {
+		delete _opl;
+		_opl = nullptr;
+
+		return MERR_CANNOT_CONNECT;
+	}
+
+	_opl->start(new Common::Functor0Mem<void, MidiDriver_Simon1_AdLib>(this, &MidiDriver_Simon1_AdLib::onTimer));
+
+	_opl->writeReg(0x01, 0x20);
+	_opl->writeReg(0x08, 0x40);
+	_opl->writeReg(0xBD, 0xC0);
+	reset();
+
+	_isOpen = true;
+	return 0;
+}
+
+bool MidiDriver_Simon1_AdLib::isOpen() const {
+	return _isOpen;
+}
+
+void MidiDriver_Simon1_AdLib::close() {
+	setTimerCallback(nullptr, nullptr);
+
+	if (_isOpen) {
+		_opl->stop();
+		delete _opl;
+		_opl = nullptr;
+
+		_isOpen = false;
+	}
+}
+
+void MidiDriver_Simon1_AdLib::send(uint32 b) {
+	int channel = b & 0x0F;
+	int command = b & 0xF0;
+	int param1  = (b >>  8) & 0xFF;
+	int param2  = (b >> 16) & 0xFF;
+
+	// The percussion channel is handled specially. The AdLib output uses
+	// channels 11 to 15 for percussions. For this, the original converted
+	// note on on the percussion channel to note on channels 11 to 15 before
+	// giving it to the AdLib output. We do this in here for simplicity.
+	if (command == 0x90 && channel == 9) {
+		param1 -= 36;
+		if (param1 < 0 || param1 >= ARRAYSIZE(_rhythmMap)) {
+			return;
+		}
+
+		channel = _rhythmMap[param1].channel;
+		MidiDriver::send(0xC0 | channel, _rhythmMap[param1].program, 0);
+
+		param1 = _rhythmMap[param1].note;
+		MidiDriver::send(0x80 | channel, param1, param2);
+
+		param2 >>= 1;
+	}
+
+	switch (command) {
+	case 0x80: // note OFF
+		noteOff(channel, param1);
+		break;
+
+	case 0x90: // note ON
+		if (param2 == 0) {
+			noteOff(channel, param1);
+		} else {
+			noteOn(channel, param1, param2);
+		}
+		break;
+
+	case 0xB0: // control change
+		controlChange(channel, param1, param2);
+		break;
+
+	case 0xC0: // program change
+		programChange(channel, param1);
+		break;
+
+	default:
+		break;
+	}
+}
+
+void MidiDriver_Simon1_AdLib::setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc) {
+	_timerParam = timer_param;
+	_timerProc = timer_proc;
+}
+
+uint32 MidiDriver_Simon1_AdLib::getBaseTempo() {
+	return 1000000 / OPL::OPL::kDefaultCallbackFrequency;
+}
+
+void MidiDriver_Simon1_AdLib::onTimer() {
+	if (_timerProc) {
+		(*_timerProc)(_timerParam);
+	}
+}
+
+void MidiDriver_Simon1_AdLib::reset() {
+	resetOPLVoices();
+	resetRhythm();
+	for (int i = 0; i < kNumberOfVoices; ++i) {
+		_voices[i].channel = kChannelUnused;
+	}
+	resetVoices();
+}
+
+void MidiDriver_Simon1_AdLib::resetOPLVoices() {
+	_amvdrBits &= 0xE0;
+	_opl->writeReg(0xBD, _amvdrBits);
+	for (int i = 8; i >= 0; --i) {
+		_opl->writeReg(0xB0 + i, 0);
+	}
+}
+
+void MidiDriver_Simon1_AdLib::resetRhythm() {
+	_melodyVoices = 9;
+	_amvdrBits = 0xC0;
+	_opl->writeReg(0xBD, _amvdrBits);
+}
+
+void MidiDriver_Simon1_AdLib::resetVoices() {
+	memset(_midiPrograms, 0, sizeof(_midiPrograms));
+	for (int i = 0; i < kNumberOfVoices; ++i) {
+		_voices[i].channel = kChannelUnused;
+	}
+
+	for (int i = 0; i < kOPLVoicesCount; ++i) {
+		resetRhythm();
+		_opl->writeReg(0x08, 0x00);
+
+		int oplRegister = _operatorMap[i];
+		for (int j = 0; j < 4; ++j) {
+			oplRegister += 0x20;
+
+			_opl->writeReg(oplRegister + 0, _operatorDefaults[2 * j + 0]);
+			_opl->writeReg(oplRegister + 3, _operatorDefaults[2 * j + 1]);
+		}
+
+		_opl->writeReg(oplRegister + 0x60, 0x00);
+		_opl->writeReg(oplRegister + 0x63, 0x00);
+
+		// This seems to be serious bug but the original does it the same way.
+		_opl->writeReg(_operatorMap[i] + i, 0x08);
+	}
+}
+
+int MidiDriver_Simon1_AdLib::allocateVoice(uint channel) {
+	for (int i = 0; i < _melodyVoices; ++i) {
+		if (_voices[i].channel == (channel | kChannelOrphanedFlag)) {
+			return i;
+		}
+	}
+
+	for (int i = 0; i < _melodyVoices; ++i) {
+		if (_voices[i].channel == kChannelUnused) {
+			return i;
+		}
+	}
+
+	for (int i = 0; i < _melodyVoices; ++i) {
+		if (_voices[i].channel > 0x7F) {
+			return i;
+		}
+	}
+
+	// The original had some logic for a priority based reuse of channels.
+	// However, the priority value is always 0, which causes the first channel
+	// to be picked all the time.
+	const int voice = 0;
+	_opl->writeReg(0xA0 + voice, (_voices[voice].frequency     ) & 0xFF);
+	_opl->writeReg(0xB0 + voice, (_voices[voice].frequency >> 8) & 0xFF);
+	return voice;
+}
+
+void MidiDriver_Simon1_AdLib::noteOff(uint channel, uint note) {
+	if (_melodyVoices <= 6 && channel >= 11) {
+		_amvdrBits &= ~(_rhythmInstrumentMask[channel - 11]);
+		_opl->writeReg(0xBD, _amvdrBits);
+	} else {
+		for (int i = 0; i < _melodyVoices; ++i) {
+			if (_voices[i].note == note && _voices[i].channel == channel) {
+				_voices[i].channel |= kChannelOrphanedFlag;
+				_opl->writeReg(0xA0 + i, (_voices[i].frequency     ) & 0xFF);
+				_opl->writeReg(0xB0 + i, (_voices[i].frequency >> 8) & 0xFF);
+				return;
+			}
+		}
+	}
+}
+
+void MidiDriver_Simon1_AdLib::noteOn(uint channel, uint note, uint velocity) {
+	if (_rhythmEnabled && channel >= 11) {
+		noteOnRhythm(channel, note, velocity);
+		return;
+	}
+
+	const int voiceNum = allocateVoice(channel);
+	Voice &voice = _voices[voiceNum];
+
+	if ((voice.channel & 0x7F) != channel) {
+		setupInstrument(voiceNum, _midiPrograms[channel]);
+	}
+	voice.channel = channel;
+
+	_opl->writeReg(0x43 + _operatorMap[voiceNum], (0x3F - (((velocity | 0x80) * voice.instrTotalLevel) >> 8)) | voice.instrScalingLevel);
+
+	voice.note = note;
+	if (note >= 0x80) {
+		note = 0;
+	}
+
+	const int frequencyAndOctave = _frequencyIndexAndOctaveTable[note];
+	const uint frequency = _frequencyTable[frequencyAndOctave & 0x0F];
+
+	uint highByte = ((frequency & 0xFF00) >> 8) | ((frequencyAndOctave & 0x70) >> 2);
+	uint lowByte  = frequency & 0x00FF;
+	voice.frequency = (highByte << 8) | lowByte;
+
+	_opl->writeReg(0xA0 + voiceNum, lowByte);
+	_opl->writeReg(0xB0 + voiceNum, highByte | 0x20);
+}
+
+void MidiDriver_Simon1_AdLib::noteOnRhythm(uint channel, uint note, uint velocity) {
+	const uint voiceNum = channel - 5;
+	Voice &voice = _voices[voiceNum];
+
+	_amvdrBits |= _rhythmInstrumentMask[voiceNum - 6];
+
+	const uint level = (0x3F - (((velocity | 0x80) * voice.instrTotalLevel) >> 8)) | voice.instrScalingLevel;
+	if (voiceNum == 6) {
+		_opl->writeReg(0x43 + _rhythmOperatorMap[voiceNum - 6], level);
+	} else {
+		_opl->writeReg(0x40 + _rhythmOperatorMap[voiceNum - 6], level);
+	}
+
+	voice.note = note;
+	if (note >= 0x80) {
+		note = 0;
+	}
+
+	const int frequencyAndOctave = _frequencyIndexAndOctaveTable[note];
+	const uint frequency = _frequencyTable[frequencyAndOctave & 0x0F];
+
+	uint highByte = ((frequency & 0xFF00) >> 8) | ((frequencyAndOctave & 0x70) >> 2);
+	uint lowByte  = frequency & 0x00FF;
+	voice.frequency = (highByte << 8) | lowByte;
+
+	const uint oplOperator = _rhythmVoiceMap[voiceNum - 6];
+	_opl->writeReg(0xA0 + oplOperator, lowByte);
+	_opl->writeReg(0xB0 + oplOperator, highByte);
+
+	_opl->writeReg(0xBD, _amvdrBits);
+}
+
+void MidiDriver_Simon1_AdLib::controlChange(uint channel, uint controller, uint value) {
+	// Enable/Disable Rhythm Section
+	if (controller == 0x67) {
+		resetVoices();
+		_rhythmEnabled = (value != 0);
+
+		if (_rhythmEnabled) {
+			_melodyVoices = 6;
+			_amvdrBits = 0xE0;
+		} else {
+			_melodyVoices = 9;
+			_amvdrBits = 0xC0;
+		}
+
+		_voices[6].channel = kChannelUnused;
+		_voices[7].channel = kChannelUnused;
+		_voices[8].channel = kChannelUnused;
+
+		_opl->writeReg(0xBD, _amvdrBits);
+	}
+}
+
+void MidiDriver_Simon1_AdLib::programChange(uint channel, uint program) {
+	_midiPrograms[channel] = program;
+
+	if (_rhythmEnabled && channel >= 11) {
+		setupInstrument(channel - 5, program);
+	} else {
+		// Fully unallocate all previously allocated but now unused voices for
+		// this MIDI channel.
+		for (uint i = 0; i < kOPLVoicesCount; ++i) {
+			if (_voices[i].channel == (channel | kChannelOrphanedFlag)) {
+				_voices[i].channel = kChannelUnused;
+			}
+		}
+
+		// Set the program for all voices allocted for this MIDI channel.
+		for (uint i = 0; i < kOPLVoicesCount; ++i) {
+			if (_voices[i].channel == channel) {
+				setupInstrument(i, program);
+			}
+		}
+	}
+}
+
+void MidiDriver_Simon1_AdLib::setupInstrument(uint voice, uint instrument) {
+	const byte *instrumentData = _instruments + instrument * 16;
+
+	int scaling = instrumentData[3];
+	if (_rhythmEnabled && voice >= 7) {
+		scaling = instrumentData[2];
+	}
+
+	const int scalingLevel = scaling & 0xC0;
+	const int totalLevel   = scaling & 0x3F;
+
+	_voices[voice].instrScalingLevel = scalingLevel;
+	_voices[voice].instrTotalLevel   = (-(totalLevel - 0x3F)) & 0xFF;
+
+	if (!_rhythmEnabled || voice <= 6) {
+		int oplRegister = _operatorMap[voice];
+		for (int j = 0; j < 4; ++j) {
+			oplRegister += 0x20;
+			_opl->writeReg(oplRegister + 0, *instrumentData++);
+			_opl->writeReg(oplRegister + 3, *instrumentData++);
+		}
+		oplRegister += 0x60;
+		_opl->writeReg(oplRegister + 0, *instrumentData++);
+		_opl->writeReg(oplRegister + 3, *instrumentData++);
+
+		_opl->writeReg(0xC0 + voice, *instrumentData++);
+	} else {
+		voice -= 7;
+
+		int oplRegister = _rhythmOperatorMap[voice + 1];
+		for (int j = 0; j < 4; ++j) {
+			oplRegister += 0x20;
+			_opl->writeReg(oplRegister + 0, *instrumentData++);
+			++instrumentData;
+		}
+		oplRegister += 0x60;
+		_opl->writeReg(oplRegister + 0, *instrumentData++);
+		++instrumentData;
+
+		_opl->writeReg(0xC0 + _rhythmVoiceMap[voice + 1], *instrumentData++);
+	}
+}
+
+const int MidiDriver_Simon1_AdLib::_operatorMap[9] = {
+	0x00, 0x01, 0x02, 0x08, 0x09, 0x0A, 0x10, 0x11,
+	0x12
+};
+
+const int MidiDriver_Simon1_AdLib::_operatorDefaults[8] = {
+	0x01, 0x11, 0x4F, 0x00, 0xF1, 0xF2, 0x53, 0x74
+};
+
+const int MidiDriver_Simon1_AdLib::_rhythmOperatorMap[5] = {
+	0x10, 0x14, 0x12, 0x15, 0x11
+};
+
+const uint MidiDriver_Simon1_AdLib::_rhythmInstrumentMask[5] = {
+	0x10, 0x08, 0x04, 0x02, 0x01
+};
+
+const int MidiDriver_Simon1_AdLib::_rhythmVoiceMap[5] = {
+	6, 7, 8, 8, 7
+};
+
+const int MidiDriver_Simon1_AdLib::_frequencyIndexAndOctaveTable[128] = {
+	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+	0x08, 0x09, 0x0A, 0x0B, 0x00, 0x01, 0x02, 0x03,
+	0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+	0x18, 0x19, 0x1A, 0x1B, 0x20, 0x21, 0x22, 0x23,
+	0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B,
+	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+	0x38, 0x39, 0x3A, 0x3B, 0x40, 0x41, 0x42, 0x43,
+	0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B,
+	0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+	0x58, 0x59, 0x5A, 0x5B, 0x60, 0x61, 0x62, 0x63,
+	0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B,
+	0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+	0x78, 0x79, 0x7A, 0x7B, 0x70, 0x71, 0x72, 0x73,
+	0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B,
+	0x7B, 0x7B, 0x7B, 0x7B, 0x7B, 0x7B, 0x7B, 0x7B
+};
+
+const int MidiDriver_Simon1_AdLib::_frequencyTable[16] = {
+	0x0157, 0x016B, 0x0181, 0x0198, 0x01B0, 0x01CA, 0x01E5, 0x0202,
+	0x0220, 0x0241, 0x0263, 0x0287, 0x2100, 0xD121, 0xA307, 0x46A4
+};
+
+const MidiDriver_Simon1_AdLib::RhythmMap MidiDriver_Simon1_AdLib::_rhythmMap[39] = {
+	{ 11, 123,  40 },
+	{ 12, 127,  50 },
+	{ 12, 124,   1 },
+	{ 12, 124,  90 },
+	{ 13, 125,  50 },
+	{ 13, 125,  25 },
+	{ 15, 127,  80 },
+	{ 13, 125,  25 },
+	{ 15, 127,  40 },
+	{ 13, 125,  35 },
+	{ 15, 127,  90 },
+	{ 13, 125,  35 },
+	{ 13, 125,  45 },
+	{ 14, 126,  90 },
+	{ 13, 125,  45 },
+	{ 15, 127,  90 },
+	{  0,   0,   0 },
+	{ 15, 127,  60 },
+	{  0,   0,   0 },
+	{ 13, 125,  60 },
+	{  0,   0,   0 },
+	{  0,   0,   0 },
+	{  0,   0,   0 },
+	{ 13, 125,  45 },
+	{ 13, 125,  40 },
+	{ 13, 125,  35 },
+	{ 13, 125,  30 },
+	{ 13, 125,  25 },
+	{ 13, 125,  80 },
+	{ 13, 125,  40 },
+	{ 13, 125,  80 },
+	{ 13, 125,  40 },
+	{ 14, 126,  40 },
+	{ 15, 127,  60 },
+	{  0,   0,   0 },
+	{  0,   0,   0 },
+	{ 14, 126,  80 },
+	{  0,   0,   0 },
+	{ 13, 125, 100 }
+};
+
+} // End of namespace AGOS
diff --git a/engines/agos/drivers/simon1/adlib.h b/engines/agos/drivers/simon1/adlib.h
new file mode 100644
index 0000000..b92c1dd
--- /dev/null
+++ b/engines/agos/drivers/simon1/adlib.h
@@ -0,0 +1,116 @@
+/* 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 AGOS_SIMON1_ADLIB_H
+#define AGOS_SIMON1_ADLIB_H
+
+#include "audio/mididrv.h"
+#include "audio/fmopl.h"
+
+namespace AGOS {
+
+class MidiDriver_Simon1_AdLib : public MidiDriver {
+public:
+	MidiDriver_Simon1_AdLib(const byte *instrumentData);
+	virtual ~MidiDriver_Simon1_AdLib();
+
+	// MidiDriver API
+	virtual int open();
+	virtual bool isOpen() const;
+	virtual void close();
+
+	virtual void send(uint32 b);
+
+	virtual void setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc);
+	virtual uint32 getBaseTempo();
+
+	virtual MidiChannel *allocateChannel() { return 0; }
+	virtual MidiChannel *getPercussionChannel() { return 0; }
+private:
+	bool _isOpen;
+
+	OPL::OPL *_opl;
+
+	Common::TimerManager::TimerProc _timerProc;
+	void *_timerParam;
+	void onTimer();
+
+	void reset();
+	void resetOPLVoices();
+
+	void resetRhythm();
+	int _melodyVoices;
+	uint8 _amvdrBits;
+	bool _rhythmEnabled;
+
+	enum {
+		kNumberOfVoices = 11,
+		kNumberOfMidiChannels = 16
+	};
+
+	struct Voice {
+		Voice();
+
+		uint channel;
+		uint note;
+		uint instrTotalLevel;
+		uint instrScalingLevel;
+		uint frequency;
+	};
+
+	void resetVoices();
+	int allocateVoice(uint channel);
+
+	Voice _voices[kNumberOfVoices];
+	uint _midiPrograms[kNumberOfMidiChannels];
+
+	void noteOff(uint channel, uint note);
+	void noteOn(uint channel, uint note, uint velocity);
+	void noteOnRhythm(uint channel, uint note, uint velocity);
+	void controlChange(uint channel, uint controller, uint value);
+	void programChange(uint channel, uint program);
+
+	void setupInstrument(uint voice, uint instrument);
+	const byte *_instruments;
+
+	static const int _operatorMap[9];
+	static const int _operatorDefaults[8];
+
+	static const int _rhythmOperatorMap[5];
+	static const uint _rhythmInstrumentMask[5];
+	static const int _rhythmVoiceMap[5];
+
+	static const int _frequencyIndexAndOctaveTable[128];
+	static const int _frequencyTable[16];
+
+	struct RhythmMap {
+		int channel;
+		int program;
+		int note;
+	};
+
+	static const RhythmMap _rhythmMap[39];
+};
+
+} // End of namespace AGOS
+
+#endif
diff --git a/engines/agos/midi.cpp b/engines/agos/midi.cpp
index 85f2dd5..67765fa 100644
--- a/engines/agos/midi.cpp
+++ b/engines/agos/midi.cpp
@@ -29,6 +29,7 @@
 #include "agos/midi.h"
 
 #include "agos/drivers/accolade/mididriver.h"
+#include "agos/drivers/simon1/adlib.h"
 // Miles Audio for Simon 2
 #include "audio/miles.h"
 
@@ -109,6 +110,8 @@ int MidiPlayer::open(int gameType, bool isDemo) {
 		if (isDemo) {
 			_musicMode = kMusicModeAccolade;
 			accoladeDriverFilename = "MUSIC.DRV";
+		} else if (Common::File::exists("MT_FM.IBK")) {
+			_musicMode = kMusicModeSimon1;
 		}
 		break;
 	case GType_SIMON2:
@@ -231,6 +234,35 @@ int MidiPlayer::open(int gameType, bool isDemo) {
 		return 0;
 	}
 
+	case kMusicModeSimon1: {
+		// This only handles the original AdLib driver of Simon1.
+		if (musicType == MT_ADLIB) {
+			_adLibMusic = true;
+			_map_mt32_to_gm = false;
+			_nativeMT32 = false;
+
+			// Load instrument data.
+			Common::File ibk;
+
+			if (ibk.open("MT_FM.IBK")) {
+				if (ibk.readUint32BE() == 0x49424b1a) {
+					byte *instrumentData = new byte[128 * 16];
+					if (ibk.read(instrumentData, 128 * 16) == 128 * 16) {
+						_driver = new MidiDriver_Simon1_AdLib(instrumentData);
+						ret = _driver->open();
+						if (ret == 0) {
+							_driver->setTimerCallback(this, &onTimer);
+							_driver->send(0xB0, 0x67, 0x01);
+							return 0;
+						}
+					}
+				}
+			}
+		}
+
+		_musicMode = kMusicModeDisabled;
+	}
+
 	default:
 		break;
 	}
diff --git a/engines/agos/midi.h b/engines/agos/midi.h
index edb3402..e8a6bca 100644
--- a/engines/agos/midi.h
+++ b/engines/agos/midi.h
@@ -36,7 +36,8 @@ namespace AGOS {
 enum kMusicMode {
 	kMusicModeDisabled = 0,
 	kMusicModeAccolade = 1,
-	kMusicModeMilesAudio
+	kMusicModeMilesAudio = 2,
+	kMusicModeSimon1 = 3
 };
 
 struct MusicInfo {
diff --git a/engines/agos/module.mk b/engines/agos/module.mk
index 6d4e72e..e7b773d 100644
--- a/engines/agos/module.mk
+++ b/engines/agos/module.mk
@@ -4,6 +4,7 @@ MODULE_OBJS := \
 	drivers/accolade/adlib.o \
 	drivers/accolade/driverfile.o \
 	drivers/accolade/mt32.o \
+	drivers/simon1/adlib.o \
 	agos.o \
 	charset.o \
 	charset-fontdata.o \


Commit: 33c57c632cc630d1d64266d9ee2bf340d0052049
    https://github.com/scummvm/scummvm/commit/33c57c632cc630d1d64266d9ee2bf340d0052049
Author: Johannes Schickel (lordhoto at scummvm.org)
Date: 2015-07-23T22:33:56+02:00

Commit Message:
Revert "AGOS: Add updated patch for #647 - Simon 1 DOS Adlib instrument bank"

This reverts commit 06addfc4041b3e20fd89dee46227e04f1c66fe52.

We implement the actual Simon1 DOS AdLib driver now, thus this code is
obsolete.

Changed paths:
    engines/agos/midi.cpp
    engines/agos/midi.h



diff --git a/engines/agos/midi.cpp b/engines/agos/midi.cpp
index 67765fa..61bab7d 100644
--- a/engines/agos/midi.cpp
+++ b/engines/agos/midi.cpp
@@ -53,8 +53,6 @@ MidiPlayer::MidiPlayer() {
 	_driver = 0;
 	_map_mt32_to_gm = false;
 
-	_adlibPatches = NULL;
-
 	_adLibMusic = false;
 	_enable_sfx = true;
 	_current = 0;
@@ -84,7 +82,6 @@ MidiPlayer::~MidiPlayer() {
 	}
 	_driver = NULL;
 	clearConstructs();
-	unloadAdlibPatches();
 }
 
 int MidiPlayer::open(int gameType, bool isDemo) {
@@ -278,12 +275,6 @@ int MidiPlayer::open(int gameType, bool isDemo) {
 	if (_nativeMT32)
 		_driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
 
-	/* Disabled due to not sounding right, and low volume level
-	if (gameType == GType_SIMON1 && MidiDriver::getMusicType(dev) == MT_ADLIB) {
-			loadAdlibPatches();
-	}
-	*/
-
 	_map_mt32_to_gm = (gameType != GType_SIMON2 && !_nativeMT32);
 
 	ret = _driver->open();
@@ -319,10 +310,8 @@ void MidiPlayer::send(uint32 b) {
 		else if (_current == &_music)
 			volume = volume * _musicVolume / 255;
 		b = (b & 0xFF00FFFF) | (volume << 16);
-	} else if ((b & 0xF0) == 0xC0) {
-		if (_map_mt32_to_gm && !_adlibPatches) {
-			b = (b & 0xFFFF00FF) | (MidiDriver::_mt32ToGm[(b >> 8) & 0xFF] << 8);
-		}
+	} else if ((b & 0xF0) == 0xC0 && _map_mt32_to_gm) {
+		b = (b & 0xFFFF00FF) | (MidiDriver::_mt32ToGm[(b >> 8) & 0xFF] << 8);
 	} else if ((b & 0xFFF0) == 0x007BB0) {
 		// Only respond to an All Notes Off if this channel
 		// has already been allocated.
@@ -353,16 +342,7 @@ void MidiPlayer::send(uint32 b) {
 			else if (_current == &_music)
 				_current->channel[9]->volume(_current->volume[9] * _musicVolume / 255);
 		}
-
-		if ((b & 0xF0) == 0xC0 && _adlibPatches) {
-			// NOTE: In the percussion channel, this function is a
-			//       no-op. Any percussion instruments you hear may
-			//       be the stock ones from adlib.cpp.
-			_driver->sysEx_customInstrument(_current->channel[channel]->getNumber(), 'ADL ', _adlibPatches + 30 * ((b >> 8) & 0xFF));
-		} else {
-			_current->channel[channel]->send(b);
-		}
-
+		_current->channel[channel]->send(b);
 		if ((b & 0xFFF0) == 0x79B0) {
 			// We have received a "Reset All Controllers" message
 			// and passed it on to the MIDI driver. This may or may
@@ -573,47 +553,6 @@ void MidiPlayer::resetVolumeTable() {
 	}
 }
 
-void MidiPlayer::loadAdlibPatches() {
-	Common::File ibk;
-
-	if (!ibk.open("mt_fm.ibk"))
-		return;
-
-	if (ibk.readUint32BE() == 0x49424b1a) {
-		_adlibPatches = new byte[128 * 30];
-		byte *ptr = _adlibPatches;
-
-		memset(_adlibPatches, 0, 128 * 30);
-
-		for (int i = 0; i < 128; i++) {
-			byte instr[16];
-
-			ibk.read(instr, 16);
-
-			ptr[0] = instr[0];   // Modulator Sound Characteristics
-			ptr[1] = instr[2];   // Modulator Scaling/Output Level
-			ptr[2] = ~instr[4];  // Modulator Attack/Decay
-			ptr[3] = ~instr[6];  // Modulator Sustain/Release
-			ptr[4] = instr[8];   // Modulator Wave Select
-			ptr[5] = instr[1];   // Carrier Sound Characteristics
-			ptr[6] = instr[3];   // Carrier Scaling/Output Level
-			ptr[7] = ~instr[5];  // Carrier Attack/Delay
-			ptr[8] = ~instr[7];  // Carrier Sustain/Release
-			ptr[9] = instr[9];   // Carrier Wave Select
-			ptr[10] = instr[10]; // Feedback/Connection
-
-			// The remaining six bytes are reserved for future use
-
-			ptr += 30;
-		}
-	}
-}
-
-void MidiPlayer::unloadAdlibPatches() {
-	delete[] _adlibPatches;
-	_adlibPatches = NULL;
-}
-
 static const int simon1_gmf_size[] = {
 	8900, 12166, 2848, 3442, 4034, 4508, 7064, 9730, 6014, 4742, 3138,
 	6570, 5384, 8909, 6457, 16321, 2742, 8968, 4804, 8442, 7717,
diff --git a/engines/agos/midi.h b/engines/agos/midi.h
index e8a6bca..fb987fd 100644
--- a/engines/agos/midi.h
+++ b/engines/agos/midi.h
@@ -82,15 +82,11 @@ protected:
 	byte _queuedTrack;
 	bool _loopQueuedTrack;
 
-	byte *_adlibPatches;
-
 protected:
 	static void onTimer(void *data);
 	void clearConstructs();
 	void clearConstructs(MusicInfo &info);
 	void resetVolumeTable();
-	void loadAdlibPatches();
-	void unloadAdlibPatches();
 
 public:
 	bool _adLibMusic;


Commit: cf42dc0a358da489ff93d32c18a5103de4dc4385
    https://github.com/scummvm/scummvm/commit/cf42dc0a358da489ff93d32c18a5103de4dc4385
Author: Johannes Schickel (lordhoto at scummvm.org)
Date: 2015-07-23T22:33:56+02:00

Commit Message:
AGOS: Slight cleanup in Simon1 AdLib output initialization code.

Changed paths:
    engines/agos/drivers/simon1/adlib.cpp
    engines/agos/drivers/simon1/adlib.h
    engines/agos/midi.cpp



diff --git a/engines/agos/drivers/simon1/adlib.cpp b/engines/agos/drivers/simon1/adlib.cpp
index d331b86..7f1370e 100644
--- a/engines/agos/drivers/simon1/adlib.cpp
+++ b/engines/agos/drivers/simon1/adlib.cpp
@@ -24,6 +24,7 @@
 
 #include "common/textconsole.h"
 #include "common/util.h"
+#include "common/file.h"
 
 namespace AGOS {
 
@@ -491,4 +492,25 @@ const MidiDriver_Simon1_AdLib::RhythmMap MidiDriver_Simon1_AdLib::_rhythmMap[39]
 	{ 13, 125, 100 }
 };
 
+MidiDriver *createMidiDriverSimon1AdLib(const char *instrumentFilename) {
+	// Load instrument data.
+	Common::File ibk;
+
+	if (!ibk.open(instrumentFilename)) {
+		return nullptr;
+	}
+
+	if (ibk.readUint32BE() != 0x49424b1a) {
+		return nullptr;
+	}
+
+	byte *instrumentData = new byte[128 * 16];
+	if (ibk.read(instrumentData, 128 * 16) != 128 * 16) {
+		delete[] instrumentData;
+		return nullptr;
+	}
+
+	return new MidiDriver_Simon1_AdLib(instrumentData);
+}
+
 } // End of namespace AGOS
diff --git a/engines/agos/drivers/simon1/adlib.h b/engines/agos/drivers/simon1/adlib.h
index b92c1dd..6057bf1 100644
--- a/engines/agos/drivers/simon1/adlib.h
+++ b/engines/agos/drivers/simon1/adlib.h
@@ -111,6 +111,8 @@ private:
 	static const RhythmMap _rhythmMap[39];
 };
 
+MidiDriver *createMidiDriverSimon1AdLib(const char *instrumentFilename);
+
 } // End of namespace AGOS
 
 #endif
diff --git a/engines/agos/midi.cpp b/engines/agos/midi.cpp
index 61bab7d..c5bace0 100644
--- a/engines/agos/midi.cpp
+++ b/engines/agos/midi.cpp
@@ -238,23 +238,16 @@ int MidiPlayer::open(int gameType, bool isDemo) {
 			_map_mt32_to_gm = false;
 			_nativeMT32 = false;
 
-			// Load instrument data.
-			Common::File ibk;
-
-			if (ibk.open("MT_FM.IBK")) {
-				if (ibk.readUint32BE() == 0x49424b1a) {
-					byte *instrumentData = new byte[128 * 16];
-					if (ibk.read(instrumentData, 128 * 16) == 128 * 16) {
-						_driver = new MidiDriver_Simon1_AdLib(instrumentData);
-						ret = _driver->open();
-						if (ret == 0) {
-							_driver->setTimerCallback(this, &onTimer);
-							_driver->send(0xB0, 0x67, 0x01);
-							return 0;
-						}
-					}
-				}
+			_driver = createMidiDriverSimon1AdLib("MT_FM.IBK");
+			if (_driver && _driver->open() == 0) {
+				_driver->setTimerCallback(this, &onTimer);
+				// Like the original, we enable the rhythm support by default.
+				_driver->send(0xB0, 0x67, 0x01);
+				return 0;
 			}
+
+			delete _driver;
+			_driver = nullptr;
 		}
 
 		_musicMode = kMusicModeDisabled;


Commit: 757077fecc2a939e767ccd29822547828a9c5e2f
    https://github.com/scummvm/scummvm/commit/757077fecc2a939e767ccd29822547828a9c5e2f
Author: Johannes Schickel (lordhoto at scummvm.org)
Date: 2015-07-23T22:33:57+02:00

Commit Message:
AGOS: Add simple volume control when Simon1 AdLib output is used.

Changed paths:
    engines/agos/midi.cpp



diff --git a/engines/agos/midi.cpp b/engines/agos/midi.cpp
index c5bace0..f636c13 100644
--- a/engines/agos/midi.cpp
+++ b/engines/agos/midi.cpp
@@ -288,7 +288,28 @@ void MidiPlayer::send(uint32 b) {
 		return;
 
 	if (_musicMode != kMusicModeDisabled) {
-		// Send directly to Accolade/Miles Audio driver
+		// Handle volume control for Simon1 output.
+		if (_musicMode == kMusicModeSimon1) {
+			// The driver does not support any volume control, thus we simply
+			// scale the velocities on note on for now.
+			// TODO: We should probably handle this at output level at some
+			// point. Then we can allow volume changes to affect already
+			// playing notes too. For now this simple change allows us to
+			// have some simple volume control though.
+			if ((b & 0xF0) == 0x90) {
+				byte volume = (b >> 16) & 0x7F;
+
+				if (_current == &_sfx) {
+					volume = volume * _sfxVolume / 255;
+				} else if (_current == &_music) {
+					volume = volume * _musicVolume / 255;
+				}
+
+				b = (b & 0xFF00FFFF) | (volume << 16);
+			}
+		}
+
+		// Send directly to Accolade/Miles/Simon1 Audio driver
 		_driver->send(b);
 		return;
 	}


Commit: 01eda204d63ab78dbdb5623359c21b526c38661c
    https://github.com/scummvm/scummvm/commit/01eda204d63ab78dbdb5623359c21b526c38661c
Author: Johannes Schickel (lordhoto at scummvm.org)
Date: 2015-07-23T22:33:57+02:00

Commit Message:
NEWS: Mention Simon1 AdLib output addition.

Changed paths:
    NEWS



diff --git a/NEWS b/NEWS
index 3e411f0..685ea7b 100644
--- a/NEWS
+++ b/NEWS
@@ -25,6 +25,8 @@ For a more comprehensive changelog of the latest experimental code, see:
    - Fixed verb area been removed in Amiga versions of Simon the Sorcerer 1.
    - Added Accolade AdLib & MT32 music drivers for the games:
      Elvira 1, Elvira 2, Waxworks and Simon the Sorcerer 1 demo.
+   - Added Simon the Sorcerer 1 AdLib output. This vastly improves the AdLib
+     output and makes it closer to the original.
 
  Broken Sword 1:
    - Fix speech endianness detection on big endian systems for the Macintosh


Commit: 66df9c95e0eea427527491e964b40adc2a9def05
    https://github.com/scummvm/scummvm/commit/66df9c95e0eea427527491e964b40adc2a9def05
Author: Johannes Schickel (lordhoto at scummvm.org)
Date: 2015-07-23T22:33:57+02:00

Commit Message:
NEWS: Slight style fix (MT32 to MT-32).

Changed paths:
    NEWS



diff --git a/NEWS b/NEWS
index 685ea7b..f9aac42 100644
--- a/NEWS
+++ b/NEWS
@@ -23,7 +23,7 @@ For a more comprehensive changelog of the latest experimental code, see:
    - Fixed arpeggio effect used in music of Amiga version of Elvira 1.
    - Fixed loading and saving progress in the PC version of Waxworks.
    - Fixed verb area been removed in Amiga versions of Simon the Sorcerer 1.
-   - Added Accolade AdLib & MT32 music drivers for the games:
+   - Added Accolade AdLib & MT-32 music drivers for the games:
      Elvira 1, Elvira 2, Waxworks and Simon the Sorcerer 1 demo.
    - Added Simon the Sorcerer 1 AdLib output. This vastly improves the AdLib
      output and makes it closer to the original.






More information about the Scummvm-git-logs mailing list