1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #include "audio/miles.h"
24 
25 #include "common/file.h"
26 #include "common/system.h"
27 #include "common/textconsole.h"
28 #include "common/util.h"
29 
30 #include "audio/fmopl.h"
31 #include "audio/adlib_ms.h"
32 
33 namespace Audio {
34 
35 // Miles Audio AdLib/OPL3 driver
36 //
37 // TODO: currently missing: OPL3 4-op voices
38 //
39 // Special cases (great for testing):
40 // - sustain feature is used by Return To Zork (demo) right at the start
41 // - sherlock holmes 2 does lots of priority sorts right at the start of the intro
42 
43 #define MILES_ADLIB_VIRTUAL_FMVOICES_COUNT_MAX 20
44 #define MILES_ADLIB_PHYSICAL_FMVOICES_COUNT_MAX 18
45 
46 #define MILES_ADLIB_PERCUSSION_BANK 127
47 
48 #define MILES_ADLIB_STEREO_PANNING_THRESHOLD_LEFT 27
49 #define MILES_ADLIB_STEREO_PANNING_THRESHOLD_RIGHT 100
50 
51 enum kMilesAdLibUpdateFlags {
52 	kMilesAdLibUpdateFlags_None    = 0,
53 	kMilesAdLibUpdateFlags_Reg_20  = 1 << 0,
54 	kMilesAdLibUpdateFlags_Reg_40  = 1 << 1,
55 	kMilesAdLibUpdateFlags_Reg_60  = 1 << 2, // register 0x6x + 0x8x
56 	kMilesAdLibUpdateFlags_Reg_C0  = 1 << 3,
57 	kMilesAdLibUpdateFlags_Reg_E0  = 1 << 4,
58 	kMilesAdLibUpdateFlags_Reg_A0  = 1 << 5, // register 0xAx + 0xBx
59 	kMilesAdLibUpdateFlags_Reg_All = 0x3F
60 };
61 
62 uint16 milesAdLibOperator1Register[MILES_ADLIB_PHYSICAL_FMVOICES_COUNT_MAX] = {
63 	0x0000, 0x0001, 0x0002, 0x0008, 0x0009, 0x000A, 0x0010, 0x0011, 0x0012,
64 	0x0100, 0x0101, 0x0102, 0x0108, 0x0109, 0x010A, 0x0110, 0x0111, 0x0112
65 };
66 
67 uint16 milesAdLibOperator2Register[MILES_ADLIB_PHYSICAL_FMVOICES_COUNT_MAX] = {
68 	0x0003, 0x0004, 0x0005, 0x000B, 0x000C, 0x000D, 0x0013, 0x0014, 0x0015,
69 	0x0103, 0x0104, 0x0105, 0x010B, 0x010C, 0x010D, 0x0113, 0x0114, 0x0115
70 };
71 
72 uint16 milesAdLibChannelRegister[MILES_ADLIB_PHYSICAL_FMVOICES_COUNT_MAX] = {
73 	0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008,
74 	0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106, 0x0107, 0x0108
75 };
76 
77 struct InstrumentEntry {
78 	byte bankId;
79 	byte patchId;
80 	int16 transposition;
81 	byte reg20op1;
82 	byte reg40op1;
83 	byte reg60op1;
84 	byte reg80op1;
85 	byte regE0op1;
86 	byte reg20op2;
87 	byte reg40op2;
88 	byte reg60op2;
89 	byte reg80op2;
90 	byte regE0op2;
91 	byte regC0;
92 };
93 
94 // hardcoded, dumped from ADLIB.MDI
95 uint16 milesAdLibFrequencyLookUpTable[] = {
96 	0x02B2, 0x02B4, 0x02B7, 0x02B9, 0x02BC, 0x02BE, 0x02C1, 0x02C3, 0x02C6, 0x02C9, 0x02CB, 0x02CE,
97 	0x02D0, 0x02D3, 0x02D6, 0x02D8, 0x02DB, 0x02DD, 0x02E0, 0x02E3, 0x02E5, 0x02E8, 0x02EB, 0x02ED,
98 	0x02F0, 0x02F3, 0x02F6, 0x02F8, 0x02FB, 0x02FE, 0x0301, 0x0303, 0x0306, 0x0309, 0x030C, 0x030F,
99 	0x0311, 0x0314, 0x0317, 0x031A, 0x031D, 0x0320, 0x0323, 0x0326, 0x0329, 0x032B, 0x032E, 0x0331,
100 	0x0334, 0x0337, 0x033A, 0x033D, 0x0340, 0x0343, 0x0346, 0x0349, 0x034C, 0x034F, 0x0352, 0x0356,
101 	0x0359, 0x035C, 0x035F, 0x0362, 0x0365, 0x0368, 0x036B, 0x036F, 0x0372, 0x0375, 0x0378, 0x037B,
102 	0x037F, 0x0382, 0x0385, 0x0388, 0x038C, 0x038F, 0x0392, 0x0395, 0x0399, 0x039C, 0x039F, 0x03A3,
103 	0x03A6, 0x03A9, 0x03AD, 0x03B0, 0x03B4, 0x03B7, 0x03BB, 0x03BE, 0x03C1, 0x03C5, 0x03C8, 0x03CC,
104 	0x03CF, 0x03D3, 0x03D7, 0x03DA, 0x03DE, 0x03E1, 0x03E5, 0x03E8, 0x03EC, 0x03F0, 0x03F3, 0x03F7,
105 	0x03FB, 0x03FE, 0xFE01, 0xFE03, 0xFE05, 0xFE07, 0xFE08, 0xFE0A, 0xFE0C, 0xFE0E, 0xFE10, 0xFE12,
106 	0xFE14, 0xFE16, 0xFE18, 0xFE1A, 0xFE1C, 0xFE1E, 0xFE20, 0xFE21, 0xFE23, 0xFE25, 0xFE27, 0xFE29,
107 	0xFE2B, 0xFE2D, 0xFE2F, 0xFE31, 0xFE34, 0xFE36, 0xFE38, 0xFE3A, 0xFE3C, 0xFE3E, 0xFE40, 0xFE42,
108 	0xFE44, 0xFE46, 0xFE48, 0xFE4A, 0xFE4C, 0xFE4F, 0xFE51, 0xFE53, 0xFE55, 0xFE57, 0xFE59, 0xFE5C,
109 	0xFE5E, 0xFE60, 0xFE62, 0xFE64, 0xFE67, 0xFE69, 0xFE6B, 0xFE6D, 0xFE6F, 0xFE72, 0xFE74, 0xFE76,
110 	0xFE79, 0xFE7B, 0xFE7D, 0xFE7F, 0xFE82, 0xFE84, 0xFE86, 0xFE89, 0xFE8B, 0xFE8D, 0xFE90, 0xFE92,
111 	0xFE95, 0xFE97, 0xFE99, 0xFE9C, 0xFE9E, 0xFEA1, 0xFEA3, 0xFEA5, 0xFEA8, 0xFEAA, 0xFEAD, 0xFEAF
112 };
113 
114 // hardcoded, dumped from ADLIB.MDI
115 uint16 milesAdLibVolumeSensitivityTable[] = {
116 	82, 85, 88, 91, 94, 97, 100, 103, 106, 109, 112, 115, 118, 121, 124, 127
117 };
118 
119 // MIDI panning to register volume table for dual OPL2
120 // hardcoded, dumped from ADLIB.MDI
121 uint8 milesAdLibPanningVolumeLookUpTable[] = {
122 	0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30,
123 	32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62,
124 	64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94,
125 	96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 127,
126 	127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
127 	127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
128 	127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
129 	127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127
130 };
131 
132 class MidiDriver_Miles_AdLib : public MidiDriver_Multisource {
133 public:
134 	MidiDriver_Miles_AdLib(InstrumentEntry *instrumentTablePtr, uint16 instrumentTableCount);
135 	virtual ~MidiDriver_Miles_AdLib();
136 
137 	// MidiDriver
138 	int open() override;
139 	void close() override;
140 	void send(uint32 b) override;
141 	void send(int8 source, uint32 b) override;
142 	void metaEvent(int8 source, byte type, byte *data, uint16 length) override;
allocateChannel()143 	MidiChannel *allocateChannel() override { return NULL; }
getPercussionChannel()144 	MidiChannel *getPercussionChannel() override { return NULL; }
145 
isOpen() const146 	bool isOpen() const override { return _isOpen; }
getBaseTempo()147 	uint32 getBaseTempo() override { return 1000000 / OPL::OPL::kDefaultCallbackFrequency; }
148 
149 	void stopAllNotes(uint8 source, uint8 channel) override;
150 	void applySourceVolume(uint8 source) override;
151 	void deinitSource(uint8 source) override;
152 
153 	uint32 property(int prop, uint32 param) override;
154 
155 	void setVolume(byte volume);
156 
157 private:
158 	OPL::Config::OplType _oplType;
159 	byte _modePhysicalFmVoicesCount;
160 	byte _modeVirtualFmVoicesCount;
161 	bool _modeStereo;
162 
163 	// the version of Miles AIL/MSS to emulate
164 	MilesVersion _milesVersion;
165 
166 	// Structure to hold information about current status of MIDI Channels
167 	struct MidiChannelEntry {
168 		byte   currentPatchBank;
169 		const  InstrumentEntry *currentInstrumentPtr;
170 		uint16 currentPitchBender;
171 		byte   currentPitchRange;
172 		byte   currentVoiceProtection;
173 
174 		byte   currentVolume;
175 		byte   currentVolumeExpression;
176 
177 		byte   currentPanning;
178 
179 		byte   currentModulation;
180 		byte   currentSustain;
181 
182 		byte   currentActiveVoicesCount;
183 
MidiChannelEntryAudio::MidiDriver_Miles_AdLib::MidiChannelEntry184 		MidiChannelEntry() : currentPatchBank(0),
185 							currentInstrumentPtr(NULL),
186 							currentPitchBender(MIDI_PITCH_BEND_DEFAULT),
187 							currentPitchRange(0),
188 							currentVoiceProtection(0),
189 							currentVolume(0), currentVolumeExpression(0),
190 							currentPanning(0),
191 							currentModulation(0),
192 							currentSustain(0),
193 							currentActiveVoicesCount(0) { }
194 	};
195 
196 	// Structure to hold information about current status of virtual FM Voices
197 	struct VirtualFmVoiceEntry {
198 		bool   inUse;
199 		byte   actualMidiChannel;
200 
201 		const  InstrumentEntry *currentInstrumentPtr;
202 
203 		bool   isPhysical;
204 		byte   physicalFmVoice;
205 
206 		uint16 currentPriority;
207 
208 		byte   currentOriginalMidiNote;
209 		byte   currentNote;
210 		int16  currentTransposition;
211 		byte   currentVelocity;
212 
213 		bool   sustained;
214 
VirtualFmVoiceEntryAudio::MidiDriver_Miles_AdLib::VirtualFmVoiceEntry215 		VirtualFmVoiceEntry(): inUse(false),
216 								actualMidiChannel(0),
217 								currentInstrumentPtr(NULL),
218 								isPhysical(false), physicalFmVoice(0),
219 								currentPriority(0),
220 								currentOriginalMidiNote(0),
221 								currentNote(0),
222 								currentTransposition(0),
223 								currentVelocity(0),
224 								sustained(false) { }
225 	};
226 
227 	// Structure to hold information about current status of physical FM Voices
228 	struct PhysicalFmVoiceEntry {
229 		bool   inUse;
230 		byte   virtualFmVoice;
231 
232 		byte   currentB0hReg;
233 
PhysicalFmVoiceEntryAudio::MidiDriver_Miles_AdLib::PhysicalFmVoiceEntry234 		PhysicalFmVoiceEntry(): inUse(false),
235 								virtualFmVoice(0),
236 								currentB0hReg(0) { }
237 	};
238 
239 	OPL::OPL *_opl;
240 	int _masterVolume;
241 
242 	bool _isOpen;
243 
244 	// stores information about all MIDI channels (not the actual OPL FM voice channels!)
245 	MidiChannelEntry _midiChannels[MIDI_CHANNEL_COUNT];
246 
247 	// stores information about all virtual OPL FM voices
248 	VirtualFmVoiceEntry _virtualFmVoices[MILES_ADLIB_VIRTUAL_FMVOICES_COUNT_MAX];
249 
250 	// stores information about all physical OPL FM voices
251 	PhysicalFmVoiceEntry _physicalFmVoices[MILES_ADLIB_PHYSICAL_FMVOICES_COUNT_MAX];
252 
253 	// holds all instruments
254 	InstrumentEntry *_instrumentTablePtr;
255 	uint16           _instrumentTableCount;
256 
257 	bool circularPhysicalAssignment;
258 	byte circularPhysicalAssignmentFmVoice;
259 
260 	void resetData();
261 	void resetAdLib();
262 	void resetAdLibOperatorRegisters(byte baseRegister, byte value);
263 	void resetAdLibFMVoiceChannelRegisters(byte baseRegister, byte value);
264 
265 	void setRegister(int reg, int value);
266 	void setRegisterStereo(uint8 reg, uint8 valueLeft, uint8 valueRight);
267 
268 	int16 searchFreeVirtualFmVoiceChannel();
269 	int16 searchFreePhysicalFmVoiceChannel();
270 
271 	void noteOn(byte midiChannel, byte note, byte velocity);
272 	void noteOff(byte midiChannel, byte note);
273 
274 	void prioritySort();
275 
276 	void releaseFmVoice(byte virtualFmVoice);
277 
278 	void releaseSustain(byte midiChannel);
279 
280 	void updatePhysicalFmVoice(byte virtualFmVoice, bool keyOn, uint16 registerUpdateFlags);
281 
282 	void controlChange(byte midiChannel, byte controllerNumber, byte controllerValue);
283 	void programChange(byte midiChannel, byte patchId);
284 
285 	const InstrumentEntry *searchInstrument(byte bankId, byte patchId);
286 
287 	void pitchBendChange(byte MIDIchannel, byte parameter1, byte parameter2);
288 };
289 
MidiDriver_Miles_AdLib(InstrumentEntry * instrumentTablePtr,uint16 instrumentTableCount)290 MidiDriver_Miles_AdLib::MidiDriver_Miles_AdLib(InstrumentEntry *instrumentTablePtr, uint16 instrumentTableCount)
291 	: _masterVolume(15), _opl(0), _isOpen(false) {
292 
293 	_instrumentTablePtr = instrumentTablePtr;
294 	_instrumentTableCount = instrumentTableCount;
295 
296 	// Set up for OPL3, we will downgrade in case we can't create OPL3 emulator
297 	// regular AdLib (OPL2) card
298 	_oplType = OPL::Config::kOpl3;
299 	_modeVirtualFmVoicesCount = 20;
300 	_modePhysicalFmVoicesCount = 18;
301 	_modeStereo = true;
302 
303 	// Default to Miles v2
304 	_milesVersion = MILES_VERSION_2;
305 
306 	// Older Miles Audio drivers did not do a circular assign for physical FM-voices
307 	// Sherlock Holmes 2 used the circular assign
308 	circularPhysicalAssignment = true;
309 	// this way the first circular physical FM-voice search will start at FM-voice 0
310 	circularPhysicalAssignmentFmVoice = MILES_ADLIB_PHYSICAL_FMVOICES_COUNT_MAX;
311 }
312 
~MidiDriver_Miles_AdLib()313 MidiDriver_Miles_AdLib::~MidiDriver_Miles_AdLib() {
314 	delete[] _instrumentTablePtr; // is created in factory MidiDriver_Miles_AdLib_create()
315 }
316 
open()317 int MidiDriver_Miles_AdLib::open() {
318 	if (_oplType == OPL::Config::kOpl3) {
319 		// Try to create OPL3 first
320 		_opl = OPL::Config::create(OPL::Config::kOpl3);
321 	}
322 	if (!_opl) {
323 		// not created yet, downgrade to dual OPL2
324 		_oplType = OPL::Config::kDualOpl2;
325 		_opl = OPL::Config::create(OPL::Config::kDualOpl2);
326 	}
327 	if (!_opl) {
328 		// not created yet, downgrade to OPL2
329 		_oplType = OPL::Config::kOpl2;
330 		_opl = OPL::Config::create(OPL::Config::kOpl2);
331 	}
332 
333 	if (!_opl) {
334 		// We still got nothing -> can't do anything anymore
335 		return -1;
336 	}
337 
338 	if (_oplType != OPL::Config::kOpl3) {
339 		_modeVirtualFmVoicesCount = 16;
340 		_modePhysicalFmVoicesCount = 9;
341 		_modeStereo = false;
342 	}
343 
344 	_opl->init();
345 
346 	_isOpen = true;
347 
348 	resetData();
349 
350 	_timerRate = getBaseTempo();
351 	_opl->start(new Common::Functor0Mem<void, MidiDriver_Miles_AdLib>(this, &MidiDriver_Miles_AdLib::onTimer));
352 
353 	resetAdLib();
354 
355 	return 0;
356 }
357 
close()358 void MidiDriver_Miles_AdLib::close() {
359 	delete _opl;
360 	_isOpen = false;
361 }
362 
setVolume(byte volume)363 void MidiDriver_Miles_AdLib::setVolume(byte volume) {
364 	_masterVolume = volume;
365 	//renewNotes(-1, true);
366 }
367 
resetData()368 void MidiDriver_Miles_AdLib::resetData() {
369 	ARRAYCLEAR(_midiChannels);
370 	ARRAYCLEAR(_virtualFmVoices);
371 	ARRAYCLEAR(_physicalFmVoices);
372 
373 	for (byte midiChannel = 0; midiChannel < MIDI_CHANNEL_COUNT; midiChannel++) {
374 		// defaults, were sent to driver during driver initialization
375 		_midiChannels[midiChannel].currentVolume = 0x7F;
376 		_midiChannels[midiChannel].currentPanning = 0x40; // center
377 		_midiChannels[midiChannel].currentVolumeExpression = 127;
378 
379 		// Miles Audio 2: hardcoded pitch range as a global (not channel specific), set to 12
380 		// Miles Audio 3: pitch range per MIDI channel; default 2 semitones
381 		_midiChannels[midiChannel].currentPitchBender = MIDI_PITCH_BEND_DEFAULT;
382 		_midiChannels[midiChannel].currentPitchRange = _milesVersion == MILES_VERSION_3 ? 2 : 12;
383 	}
384 
385 }
386 
resetAdLib()387 void MidiDriver_Miles_AdLib::resetAdLib() {
388 	if (_oplType == OPL::Config::kOpl3) {
389 		setRegister(0x105, 1); // enable OPL3
390 		setRegister(0x104, 0); // activate 18 2-operator FM-voices
391 	}
392 
393 	// enable waveform control on both operators
394 	setRegister(0x01, _oplType == OPL::Config::kOpl3 ? 0 : 0x20);
395 	if (_oplType == OPL::Config::kOpl3)
396 		setRegister(0x101, 0);
397 	// Timer control
398 	setRegister(0x02, 0);
399 	setRegister(0x03, 0);
400 	setRegister(0x04, 0x60);
401 	setRegister(0x04, 0x80);
402 
403 	// Set note select and disable CSM mode
404 	setRegister(0x08, 0);
405 	// disable Rhythm; set vibrato and modulation depth to 1
406 	setRegister(0xBD, 0xC0);
407 
408 	// reset FM voice instrument data
409 	resetAdLibOperatorRegisters(0x20, 1);
410 	resetAdLibOperatorRegisters(0x40, 0x3F);
411 	resetAdLibOperatorRegisters(0x60, 0xFF);
412 	resetAdLibOperatorRegisters(0x80, 0x0F);
413 	resetAdLibFMVoiceChannelRegisters(0xA0, 0);
414 	resetAdLibFMVoiceChannelRegisters(0xB0, 0);
415 	resetAdLibFMVoiceChannelRegisters(0xC0, 0);
416 	resetAdLibOperatorRegisters(0xE0, 0);
417 }
418 
resetAdLibOperatorRegisters(byte baseRegister,byte value)419 void MidiDriver_Miles_AdLib::resetAdLibOperatorRegisters(byte baseRegister, byte value) {
420 	byte physicalFmVoice = 0;
421 
422 	for (physicalFmVoice = 0; physicalFmVoice < _modePhysicalFmVoicesCount; physicalFmVoice++) {
423 		setRegister(baseRegister + milesAdLibOperator1Register[physicalFmVoice], value);
424 		setRegister(baseRegister + milesAdLibOperator2Register[physicalFmVoice], value);
425 	}
426 }
427 
resetAdLibFMVoiceChannelRegisters(byte baseRegister,byte value)428 void MidiDriver_Miles_AdLib::resetAdLibFMVoiceChannelRegisters(byte baseRegister, byte value) {
429 	byte physicalFmVoice = 0;
430 
431 	for (physicalFmVoice = 0; physicalFmVoice < _modePhysicalFmVoicesCount; physicalFmVoice++) {
432 		setRegister(baseRegister + milesAdLibChannelRegister[physicalFmVoice], value);
433 	}
434 }
435 
436 // MIDI messages can be found at http://www.midi.org/techspecs/midimessages.php
send(uint32 b)437 void MidiDriver_Miles_AdLib::send(uint32 b) {
438 	byte command = b & 0xf0;
439 	byte channel = b & 0xf;
440 	byte op1 = (b >> 8) & 0xff;
441 	byte op2 = (b >> 16) & 0xff;
442 
443 	switch (command) {
444 	case 0x80:
445 		noteOff(channel, op1);
446 		break;
447 	case 0x90:
448 		noteOn(channel, op1, op2);
449 		break;
450 	case 0xb0: // Control change
451 		controlChange(channel, op1, op2);
452 		break;
453 	case 0xc0: // Program Change
454 		programChange(channel, op1);
455 		break;
456 	case 0xa0: // Polyphonic key pressure (aftertouch)
457 	case 0xd0: // Channel pressure (aftertouch)
458 		// Aftertouch doesn't seem to be implemented in the Miles Audio AdLib driver
459 		break;
460 	case 0xe0:
461 		pitchBendChange(channel, op1, op2);
462 		break;
463 	case 0xf0: // SysEx
464 		warning("MILES-ADLIB: SysEx: %x", b);
465 		break;
466 	default:
467 		warning("MILES-ADLIB: Unknown event %02x", command);
468 	}
469 }
470 
send(int8 source,uint32 b)471 void MidiDriver_Miles_AdLib::send(int8 source, uint32 b) {
472 	// TODO Implement proper multisource support.
473 	if (source == -1 || source == 0)
474 		send(b);
475 }
476 
stopAllNotes(uint8 source,uint8 channel)477 void MidiDriver_Miles_AdLib::stopAllNotes(uint8 source, uint8 channel) {
478 	if (!(source == 0 || source == 0xFF))
479 		return;
480 
481 	for (int i = 0; i < _modeVirtualFmVoicesCount; i++) {
482 		if (_virtualFmVoices[i].inUse && (channel == 0xFF || _virtualFmVoices[i].actualMidiChannel == channel)) {
483 			releaseFmVoice(i);
484 		}
485 	}
486 }
487 
property(int prop,uint32 param)488 uint32 MidiDriver_Miles_AdLib::property(int prop, uint32 param) {
489 	switch (prop) {
490 	case PROP_MILES_VERSION:
491 		if (param == 0xFFFF)
492 			return _milesVersion;
493 
494 		switch (param) {
495 		case MILES_VERSION_3:
496 			_milesVersion = MILES_VERSION_3;
497 			break;
498 		case MILES_VERSION_2:
499 		default:
500 			_milesVersion = MILES_VERSION_2;
501 		}
502 
503 		break;
504 	default:
505 		return MidiDriver_Multisource::property(prop, param);
506 	}
507 	return 0;
508 }
509 
applySourceVolume(uint8 source)510 void MidiDriver_Miles_AdLib::applySourceVolume(uint8 source) {
511 	if (!(source == 0 || source == 0xFF))
512 		return;
513 
514 	for (int i = 0; i < _modeVirtualFmVoicesCount; i++) {
515 		if (_virtualFmVoices[i].inUse) {
516 			updatePhysicalFmVoice(i, true, kMilesAdLibUpdateFlags_Reg_40);
517 		}
518 	}
519 }
520 
searchFreeVirtualFmVoiceChannel()521 int16 MidiDriver_Miles_AdLib::searchFreeVirtualFmVoiceChannel() {
522 	for (byte virtualFmVoice = 0; virtualFmVoice < _modeVirtualFmVoicesCount; virtualFmVoice++) {
523 		if (!_virtualFmVoices[virtualFmVoice].inUse)
524 			return virtualFmVoice;
525 	}
526 	return -1;
527 }
528 
searchFreePhysicalFmVoiceChannel()529 int16 MidiDriver_Miles_AdLib::searchFreePhysicalFmVoiceChannel() {
530 	if (!circularPhysicalAssignment) {
531 		// Older assign logic
532 		for (byte physicalFmVoice = 0; physicalFmVoice < _modePhysicalFmVoicesCount; physicalFmVoice++) {
533 			if (!_physicalFmVoices[physicalFmVoice].inUse)
534 				return physicalFmVoice;
535 		}
536 	} else {
537 		// Newer one
538 		// Remembers last physical FM-voice and searches from that spot
539 		byte physicalFmVoice = circularPhysicalAssignmentFmVoice;
540 		for (byte physicalFmVoiceCount = 0; physicalFmVoiceCount < _modePhysicalFmVoicesCount; physicalFmVoiceCount++) {
541 			physicalFmVoice++;
542 			if (physicalFmVoice >= _modePhysicalFmVoicesCount)
543 				physicalFmVoice = 0;
544 			if (!_physicalFmVoices[physicalFmVoice].inUse) {
545 				circularPhysicalAssignmentFmVoice = physicalFmVoice;
546 				return physicalFmVoice;
547 			}
548 		}
549 	}
550 	return -1;
551 }
552 
noteOn(byte midiChannel,byte note,byte velocity)553 void MidiDriver_Miles_AdLib::noteOn(byte midiChannel, byte note, byte velocity) {
554 	const InstrumentEntry *instrumentPtr = NULL;
555 
556 	if (velocity == 0) {
557 		noteOff(midiChannel, note);
558 		return;
559 	}
560 
561 	if (midiChannel == 9) {
562 		// percussion channel
563 		// search for instrument according to given note
564 		instrumentPtr = searchInstrument(MILES_ADLIB_PERCUSSION_BANK, note);
565 	} else {
566 		// directly get instrument of channel
567 		instrumentPtr = _midiChannels[midiChannel].currentInstrumentPtr;
568 	}
569 	if (!instrumentPtr) {
570 		warning("MILES-ADLIB: noteOn: invalid instrument");
571 		return;
572 	}
573 
574 	//warning("Note On: channel %d, note %d, velocity %d, instrument %d/%d", midiChannel, note, velocity, instrumentPtr->bankId, instrumentPtr->patchId);
575 
576 	// look for free virtual FM voice
577 	int16 virtualFmVoice = searchFreeVirtualFmVoiceChannel();
578 
579 	if (virtualFmVoice == -1) {
580 		// Out of virtual voices,  can't do anything about it
581 		return;
582 	}
583 
584 	// Scale back velocity
585 	velocity = (velocity & 0x7F) >> 3;
586 	velocity = milesAdLibVolumeSensitivityTable[velocity];
587 
588 	if (midiChannel != 9) {
589 		_virtualFmVoices[virtualFmVoice].currentNote = note;
590 		_virtualFmVoices[virtualFmVoice].currentTransposition = instrumentPtr->transposition;
591 	} else {
592 		// Percussion channel
593 		_virtualFmVoices[virtualFmVoice].currentNote = instrumentPtr->transposition;
594 		_virtualFmVoices[virtualFmVoice].currentTransposition = 0;
595 	}
596 
597 	_virtualFmVoices[virtualFmVoice].inUse = true;
598 	_virtualFmVoices[virtualFmVoice].actualMidiChannel = midiChannel;
599 	_virtualFmVoices[virtualFmVoice].currentOriginalMidiNote = note;
600 	_virtualFmVoices[virtualFmVoice].currentInstrumentPtr = instrumentPtr;
601 	_virtualFmVoices[virtualFmVoice].currentVelocity = velocity;
602 	_virtualFmVoices[virtualFmVoice].isPhysical = false;
603 	_virtualFmVoices[virtualFmVoice].sustained = false;
604 	_virtualFmVoices[virtualFmVoice].currentPriority = 32767;
605 
606 	int16 physicalFmVoice = searchFreePhysicalFmVoiceChannel();
607 	if (physicalFmVoice == -1) {
608 		// None found
609 		// go through priorities and reshuffle voices
610 		prioritySort();
611 		return;
612 	}
613 
614 	// Another voice active on this MIDI channel
615 	_midiChannels[midiChannel].currentActiveVoicesCount++;
616 
617 	// Mark virtual FM-Voice as being connected to physical FM-Voice
618 	_virtualFmVoices[virtualFmVoice].isPhysical = true;
619 	_virtualFmVoices[virtualFmVoice].physicalFmVoice = physicalFmVoice;
620 
621 	// Mark physical FM-Voice as being connected to virtual FM-Voice
622 	_physicalFmVoices[physicalFmVoice].inUse = true;
623 	_physicalFmVoices[physicalFmVoice].virtualFmVoice = virtualFmVoice;
624 
625 	// Update the physical FM-Voice
626 	updatePhysicalFmVoice(virtualFmVoice, true, kMilesAdLibUpdateFlags_Reg_All);
627 }
628 
noteOff(byte midiChannel,byte note)629 void MidiDriver_Miles_AdLib::noteOff(byte midiChannel, byte note) {
630 	//warning("Note Off: channel %d, note %d", midiChannel, note);
631 
632 	// Search through all virtual FM-Voices for current midiChannel + note
633 	for (byte virtualFmVoice = 0; virtualFmVoice < _modeVirtualFmVoicesCount; virtualFmVoice++) {
634 		if (_virtualFmVoices[virtualFmVoice].inUse) {
635 			if ((_virtualFmVoices[virtualFmVoice].actualMidiChannel == midiChannel) && (_virtualFmVoices[virtualFmVoice].currentOriginalMidiNote == note)) {
636 				// found one
637 				if (_midiChannels[midiChannel].currentSustain >= 64) {
638 					_virtualFmVoices[virtualFmVoice].sustained = true;
639 					continue;
640 				}
641 				//
642 				releaseFmVoice(virtualFmVoice);
643 			}
644 		}
645 	}
646 }
647 
prioritySort()648 void MidiDriver_Miles_AdLib::prioritySort() {
649 	byte   virtualFmVoice = 0;
650 	uint16 virtualPriority = 0;
651 	uint16 virtualPriorities[MILES_ADLIB_VIRTUAL_FMVOICES_COUNT_MAX];
652 	uint16 virtualFmVoicesCount = 0;
653 	byte   midiChannel = 0;
654 
655 	ARRAYCLEAR(virtualPriorities);
656 
657 	//warning("prioritysort");
658 
659 	// First calculate priorities for all virtual FM voices, that are in use
660 	for (virtualFmVoice = 0; virtualFmVoice < _modeVirtualFmVoicesCount; virtualFmVoice++) {
661 		if (_virtualFmVoices[virtualFmVoice].inUse) {
662 			virtualFmVoicesCount++;
663 
664 			midiChannel = _virtualFmVoices[virtualFmVoice].actualMidiChannel;
665 			if (_midiChannels[midiChannel].currentVoiceProtection >= 64) {
666 				// Voice protection enabled
667 				virtualPriority = 0xFFFF;
668 			} else {
669 				virtualPriority = _virtualFmVoices[virtualFmVoice].currentPriority;
670 			}
671 			byte currentActiveVoicesCount = _midiChannels[midiChannel].currentActiveVoicesCount;
672 			if (virtualPriority >= currentActiveVoicesCount) {
673 				virtualPriority -= _midiChannels[midiChannel].currentActiveVoicesCount;
674 			} else {
675 				virtualPriority = 0; // overflow, should never happen
676 			}
677 			virtualPriorities[virtualFmVoice] = virtualPriority;
678 		}
679 	}
680 
681 	//
682 	while (virtualFmVoicesCount) {
683 		uint16 unvoicedHighestPriority = 0;
684 		byte   unvoicedHighestFmVoice = 0;
685 		uint16 voicedLowestPriority = 65535;
686 		byte   voicedLowestFmVoice = 0;
687 
688 		for (virtualFmVoice = 0; virtualFmVoice < _modeVirtualFmVoicesCount; virtualFmVoice++) {
689 			if (_virtualFmVoices[virtualFmVoice].inUse) {
690 				virtualPriority = virtualPriorities[virtualFmVoice];
691 				if (!_virtualFmVoices[virtualFmVoice].isPhysical) {
692 					// currently not physical, so unvoiced
693 					if (virtualPriority >= unvoicedHighestPriority) {
694 						unvoicedHighestPriority = virtualPriority;
695 						unvoicedHighestFmVoice  = virtualFmVoice;
696 					}
697 				} else {
698 					// currently physical, so voiced
699 					if (virtualPriority <= voicedLowestPriority) {
700 						voicedLowestPriority = virtualPriority;
701 						voicedLowestFmVoice  = virtualFmVoice;
702 					}
703 				}
704 			}
705 		}
706 
707 		if (unvoicedHighestPriority < voicedLowestPriority)
708 			break; // We are done
709 
710 		if (unvoicedHighestPriority == 0)
711 			break;
712 
713 		// Safety checks
714 		assert(_virtualFmVoices[voicedLowestFmVoice].isPhysical);
715 		assert(!_virtualFmVoices[unvoicedHighestFmVoice].isPhysical);
716 
717 		// Steal this physical voice
718 		byte physicalFmVoice = _virtualFmVoices[voicedLowestFmVoice].physicalFmVoice;
719 
720 		//warning("MILES-ADLIB: stealing physical FM-Voice %d from virtual FM-Voice %d for virtual FM-Voice %d", physicalFmVoice, voicedLowestFmVoice, unvoicedHighestFmVoice);
721 		//warning("priority old %d, priority new %d", unvoicedHighestPriority, voicedLowestPriority);
722 
723 		releaseFmVoice(voicedLowestFmVoice);
724 
725 		// Get some data of the unvoiced highest priority virtual FM Voice
726 		midiChannel = _virtualFmVoices[unvoicedHighestFmVoice].actualMidiChannel;
727 
728 		// Another voice active on this MIDI channel
729 		_midiChannels[midiChannel].currentActiveVoicesCount++;
730 
731 		// Mark virtual FM-Voice as being connected to physical FM-Voice
732 		_virtualFmVoices[unvoicedHighestFmVoice].isPhysical = true;
733 		_virtualFmVoices[unvoicedHighestFmVoice].physicalFmVoice = physicalFmVoice;
734 
735 		// Mark physical FM-Voice as being connected to virtual FM-Voice
736 		_physicalFmVoices[physicalFmVoice].inUse = true;
737 		_physicalFmVoices[physicalFmVoice].virtualFmVoice = unvoicedHighestFmVoice;
738 
739 		// Update the physical FM-Voice
740 		updatePhysicalFmVoice(unvoicedHighestFmVoice, true, kMilesAdLibUpdateFlags_Reg_All);
741 
742 		virtualFmVoicesCount--;
743 	}
744 }
745 
releaseFmVoice(byte virtualFmVoice)746 void MidiDriver_Miles_AdLib::releaseFmVoice(byte virtualFmVoice) {
747 	// virtual Voice not actually played? -> exit
748 	if (!_virtualFmVoices[virtualFmVoice].isPhysical) {
749 		_virtualFmVoices[virtualFmVoice].inUse = false;
750 		return;
751 	}
752 
753 	byte midiChannel = _virtualFmVoices[virtualFmVoice].actualMidiChannel;
754 	byte physicalFmVoice = _virtualFmVoices[virtualFmVoice].physicalFmVoice;
755 
756 	// stop note from playing
757 	updatePhysicalFmVoice(virtualFmVoice, false, kMilesAdLibUpdateFlags_Reg_A0);
758 
759 	// this virtual FM voice isn't physical anymore
760 	_virtualFmVoices[virtualFmVoice].isPhysical = false;
761 	_virtualFmVoices[virtualFmVoice].inUse = false;
762 
763 	// Remove physical FM-Voice from being active
764 	_physicalFmVoices[physicalFmVoice].inUse = false;
765 
766 	// One less voice active on this MIDI channel
767 	assert(_midiChannels[midiChannel].currentActiveVoicesCount);
768 	_midiChannels[midiChannel].currentActiveVoicesCount--;
769 }
770 
releaseSustain(byte midiChannel)771 void MidiDriver_Miles_AdLib::releaseSustain(byte midiChannel) {
772 	// Search through all virtual FM-Voices for currently sustained notes and call noteOff on them
773 	for (byte virtualFmVoice = 0; virtualFmVoice < _modeVirtualFmVoicesCount; virtualFmVoice++) {
774 		if (_virtualFmVoices[virtualFmVoice].inUse) {
775 			if ((_virtualFmVoices[virtualFmVoice].actualMidiChannel == midiChannel) && (_virtualFmVoices[virtualFmVoice].sustained)) {
776 				// is currently sustained
777 				// so do a noteOff (which will check current sustain controller)
778 				noteOff(midiChannel, _virtualFmVoices[virtualFmVoice].currentOriginalMidiNote);
779 			}
780 		}
781 	}
782 }
783 
updatePhysicalFmVoice(byte virtualFmVoice,bool keyOn,uint16 registerUpdateFlags)784 void MidiDriver_Miles_AdLib::updatePhysicalFmVoice(byte virtualFmVoice, bool keyOn, uint16 registerUpdateFlags) {
785 	byte midiChannel = _virtualFmVoices[virtualFmVoice].actualMidiChannel;
786 
787 	if (!_virtualFmVoices[virtualFmVoice].isPhysical) {
788 		// virtual FM-Voice has no physical FM-Voice assigned? -> ignore
789 		return;
790 	}
791 
792 	byte                   physicalFmVoice = _virtualFmVoices[virtualFmVoice].physicalFmVoice;
793 	const InstrumentEntry *instrumentPtr = _virtualFmVoices[virtualFmVoice].currentInstrumentPtr;
794 
795 	uint16 op1Reg = milesAdLibOperator1Register[physicalFmVoice];
796 	uint16 op2Reg = milesAdLibOperator2Register[physicalFmVoice];
797 	uint16 channelReg = milesAdLibChannelRegister[physicalFmVoice];
798 
799 	uint16 compositeVolume = 0;
800 	uint8 leftVolume = 0;
801 	uint8 rightVolume = 0;
802 
803 	if (registerUpdateFlags & kMilesAdLibUpdateFlags_Reg_40) {
804 		// Calculate new volume
805 		byte midiVolume = _midiChannels[midiChannel].currentVolume;
806 		byte midiVolumeExpression = _midiChannels[midiChannel].currentVolumeExpression;
807 		compositeVolume = midiVolume * midiVolumeExpression * 2;
808 
809 		compositeVolume = compositeVolume >> 8; // get upmost 8 bits
810 		if (compositeVolume)
811 			compositeVolume++; // round up in case result wasn't 0
812 
813 		compositeVolume = compositeVolume * _virtualFmVoices[virtualFmVoice].currentVelocity * 2;
814 		compositeVolume = compositeVolume >> 8; // get upmost 8 bits
815 		if (compositeVolume)
816 			compositeVolume++; // round up in case result wasn't 0
817 
818 		// Scale by source volume.
819 		compositeVolume = compositeVolume * _sources[0].volume / _sources[0].neutralVolume;
820 		if (_userVolumeScaling) {
821 			if (_userMute) {
822 				compositeVolume = 0;
823 			} else {
824 				// Scale by user volume.
825 				uint16 userVolume = (_sources[0].type == SOURCE_TYPE_SFX ? _userSfxVolume : _userMusicVolume); // Treat SOURCE_TYPE_UNDEFINED as music
826 				compositeVolume = (compositeVolume * userVolume) >> 8;
827 			}
828 		}
829 		// Source volume scaling might clip volume, so reduce to maximum.
830 		compositeVolume = MIN(compositeVolume, (uint16)0x7F);
831 
832 		if (_oplType == OPL::Config::kDualOpl2) {
833 			// For dual OPL2, Miles pans the notes by playing the same note on
834 			// the left and right OPL2 chips at different volume levels.
835 			// Calculate the volume for each chip based on the panning value.
836 			leftVolume = (milesAdLibPanningVolumeLookUpTable[_midiChannels[midiChannel].currentPanning] * compositeVolume) >> 7;
837 			if (leftVolume)
838 				leftVolume++; // round up in case result wasn't 0
839 			uint8 invertedPanning = 0 - (_midiChannels[midiChannel].currentPanning - 127);
840 			rightVolume = (milesAdLibPanningVolumeLookUpTable[invertedPanning] * compositeVolume) >> 7;
841 			if (rightVolume)
842 				rightVolume++; // round up in case result wasn't 0
843 		}
844 	}
845 
846 	if (registerUpdateFlags & kMilesAdLibUpdateFlags_Reg_20) {
847 		// Amplitude Modulation / Vibrato / Envelope Generator Type / Keyboard Scaling Rate / Modulator Frequency Multiple
848 		byte reg20op1 = instrumentPtr->reg20op1;
849 		byte reg20op2 = instrumentPtr->reg20op2;
850 
851 		if (_midiChannels[midiChannel].currentModulation >= 64) {
852 			// set bit 6 (Vibrato)
853 			reg20op1 |= 0x40;
854 			reg20op2 |= 0x40;
855 		}
856 		setRegister(0x20 + op1Reg, reg20op1);
857 		setRegister(0x20 + op2Reg, reg20op2);
858 	}
859 
860 	if (registerUpdateFlags & kMilesAdLibUpdateFlags_Reg_40) {
861 		// Volume (Level Key Scaling / Total Level)
862 		byte reg40op1 = instrumentPtr->reg40op1;
863 		byte reg40op2 = instrumentPtr->reg40op2;
864 
865 		uint16 volumeOp1 = (~reg40op1) & 0x3F;
866 		uint16 volumeOp2 = (~reg40op2) & 0x3F;
867 
868 		if (_oplType != OPL::Config::kDualOpl2) {
869 			if (instrumentPtr->regC0 & 1) {
870 				// operator 2 enabled
871 				// scale volume factor
872 				volumeOp1 = (volumeOp1 * compositeVolume) / 127;
873 				// 2nd operator always scaled
874 			}
875 
876 			volumeOp2 = (volumeOp2 * compositeVolume) / 127;
877 
878 			volumeOp1 = (~volumeOp1) & 0x3F; // negate it, so we get the proper value for the register
879 			volumeOp2 = (~volumeOp2) & 0x3F; // ditto
880 			reg40op1  = (reg40op1 & 0xC0) | volumeOp1; // keep "scaling level" and merge in our volume
881 			reg40op2  = (reg40op2 & 0xC0) | volumeOp2;
882 
883 			setRegister(0x40 + op1Reg, reg40op1);
884 			setRegister(0x40 + op2Reg, reg40op2);
885 		} else {
886 			// For dual OPL2, separate register values are calculated for the
887 			// left and right OPL2 chip.
888 			uint8 volumeLeftOp1 = volumeOp1;
889 			uint8 volumeRightOp1 = volumeOp1;
890 
891 			if (instrumentPtr->regC0 & 1) {
892 				// operator 2 enabled
893 				// scale volume factor
894 				volumeLeftOp1 = (volumeLeftOp1 * leftVolume) / 127;
895 				volumeRightOp1 = (volumeRightOp1 * rightVolume) / 127;
896 				// 2nd operator always scaled
897 			}
898 
899 			uint8 volumeLeftOp2 = (volumeOp2 * leftVolume) / 127;
900 			uint8 volumeRightOp2 = (volumeOp2 * rightVolume) / 127;
901 
902 			volumeLeftOp1 = (~volumeLeftOp1) & 0x3F; // negate it, so we get the proper value for the register
903 			volumeRightOp1 = (~volumeRightOp1) & 0x3F;
904 			volumeLeftOp2 = (~volumeLeftOp2) & 0x3F; // ditto
905 			volumeRightOp2 = (~volumeRightOp2) & 0x3F;
906 			uint8 reg40op1left = (reg40op1 & 0xC0) | volumeLeftOp1; // keep "scaling level" and merge in our volume
907 			uint8 reg40op1right = (reg40op1 & 0xC0) | volumeRightOp1;
908 			uint8 reg40op2left = (reg40op2 & 0xC0) | volumeLeftOp2;
909 			uint8 reg40op2right = (reg40op2 & 0xC0) | volumeRightOp2;
910 
911 			setRegisterStereo(0x40 + op1Reg, reg40op1left, reg40op1right);
912 			setRegisterStereo(0x40 + op2Reg, reg40op2left, reg40op2right);
913 		}
914 	}
915 
916 	if (registerUpdateFlags & kMilesAdLibUpdateFlags_Reg_60) {
917 		// Attack Rate / Decay Rate
918 		// Sustain Level / Release Rate
919 		byte reg60op1 = instrumentPtr->reg60op1;
920 		byte reg60op2 = instrumentPtr->reg60op2;
921 		byte reg80op1 = instrumentPtr->reg80op1;
922 		byte reg80op2 = instrumentPtr->reg80op2;
923 
924 		setRegister(0x60 + op1Reg, reg60op1);
925 		setRegister(0x60 + op2Reg, reg60op2);
926 		setRegister(0x80 + op1Reg, reg80op1);
927 		setRegister(0x80 + op2Reg, reg80op2);
928 	}
929 
930 	if (registerUpdateFlags & kMilesAdLibUpdateFlags_Reg_E0) {
931 		// Waveform Select
932 		byte regE0op1 = instrumentPtr->regE0op1;
933 		byte regE0op2 = instrumentPtr->regE0op2;
934 
935 		setRegister(0xE0 + op1Reg, regE0op1);
936 		setRegister(0xE0 + op2Reg, regE0op2);
937 	}
938 
939 	if (registerUpdateFlags & kMilesAdLibUpdateFlags_Reg_C0) {
940 		// Feedback / Algorithm
941 		byte regC0 = instrumentPtr->regC0;
942 
943 		if (_oplType == OPL::Config::kOpl3) {
944 			// Panning for OPL3
945 			byte panning = _midiChannels[midiChannel].currentPanning;
946 
947 			if (panning <= MILES_ADLIB_STEREO_PANNING_THRESHOLD_LEFT) {
948 				regC0 |= 0x20; // left speaker only
949 			} else if (panning >= MILES_ADLIB_STEREO_PANNING_THRESHOLD_RIGHT) {
950 				regC0 |= 0x10; // right speaker only
951 			} else {
952 				regC0 |= 0x30; // center
953 			}
954 		}
955 
956 		setRegister(0xC0 + channelReg, regC0);
957 	}
958 
959 	if (registerUpdateFlags & kMilesAdLibUpdateFlags_Reg_A0) {
960 		// Frequency / Key-On
961 		// Octave / F-Number / Key-On
962 		if (!keyOn) {
963 			// turn off note
964 			byte regB0 = _physicalFmVoices[physicalFmVoice].currentB0hReg & 0x1F; // remove bit 5 "key on"
965 			setRegister(0xB0 + channelReg, regB0);
966 
967 		} else {
968 			// turn on note, calculate frequency, octave...
969 			int16 pitchBender = _midiChannels[midiChannel].currentPitchBender;
970 			byte  pitchRange = _midiChannels[midiChannel].currentPitchRange;
971 			int16 currentNote = _virtualFmVoices[virtualFmVoice].currentNote;
972 			int16 physicalNote = 0;
973 			int16 halfTone = 0;
974 			uint16 frequency = 0;
975 			uint16 frequencyIdx = 0;
976 			byte   octave = 0;
977 
978 			pitchBender -= 0x2000;
979 			pitchBender = pitchBender >> 5; // divide by 32
980 			pitchBender = pitchBender * pitchRange; // pitchrange 12: now +0x0C00 to -0xC00
981 			// difference between Miles Audio 2 + 3
982 			// Miles Audio 2 used a pitch range of 12, which was basically hardcoded
983 			// Miles Audio 3 used an array, which got set by control change events
984 
985 			currentNote += _virtualFmVoices->currentTransposition;
986 
987 			// Normalize note
988 			currentNote -= 24;
989 			do {
990 				currentNote += 12;
991 			} while (currentNote < 0);
992 			currentNote += 12;
993 
994 			do {
995 				currentNote -= 12;
996 			} while (currentNote > 95);
997 
998 			// combine note + pitchbender, also adjust by 8 for rounding
999 			currentNote = (currentNote << 8) + pitchBender + 8;
1000 
1001 			currentNote = currentNote >> 4; // get actual note
1002 
1003 			// Normalize
1004 			currentNote -= (12 * 16);
1005 			do {
1006 				currentNote += (12 * 16);
1007 			} while (currentNote < 0);
1008 
1009 			currentNote += (12 * 16);
1010 			do {
1011 				currentNote -= (12 * 16);
1012 			} while (currentNote > ((96 * 16) - 1));
1013 
1014 			physicalNote = currentNote >> 4;
1015 
1016 			halfTone = physicalNote % 12; // remainder of physicalNote / 12
1017 
1018 			frequencyIdx = (halfTone << 4) + (currentNote & 0x0F);
1019 			assert(frequencyIdx < sizeof(milesAdLibFrequencyLookUpTable));
1020 			frequency = milesAdLibFrequencyLookUpTable[frequencyIdx];
1021 
1022 			octave = (physicalNote / 12) - 1;
1023 
1024 			if (frequency & 0x8000)
1025 				octave++;
1026 
1027 			if (octave & 0x80) {
1028 				octave++;
1029 				frequency = frequency >> 1;
1030 			}
1031 
1032 			byte regA0 = frequency & 0xFF;
1033 			byte regB0 = ((frequency >> 8) & 0x03) | (octave << 2) | 0x20;
1034 
1035 			setRegister(0xA0 + channelReg, regA0);
1036 			setRegister(0xB0 + channelReg, regB0);
1037 
1038 			_physicalFmVoices[physicalFmVoice].currentB0hReg = regB0;
1039 		}
1040 	}
1041 
1042 	//warning("end of update voice");
1043 }
1044 
controlChange(byte midiChannel,byte controllerNumber,byte controllerValue)1045 void MidiDriver_Miles_AdLib::controlChange(byte midiChannel, byte controllerNumber, byte controllerValue) {
1046 	uint16 registerUpdateFlags = kMilesAdLibUpdateFlags_None;
1047 
1048 	switch (controllerNumber) {
1049 	case MILES_CONTROLLER_SELECT_PATCH_BANK:
1050 		//warning("patch bank channel %d, bank %x", midiChannel, controllerValue);
1051 		_midiChannels[midiChannel].currentPatchBank = controllerValue;
1052 		break;
1053 
1054 	case MILES_CONTROLLER_PROTECT_VOICE:
1055 		_midiChannels[midiChannel].currentVoiceProtection = controllerValue;
1056 		break;
1057 
1058 	case MILES_CONTROLLER_PROTECT_TIMBRE:
1059 		// It seems that this can get ignored, because we don't cache timbres at all
1060 		break;
1061 
1062 	case MIDI_CONTROLLER_MODULATION:
1063 		_midiChannels[midiChannel].currentModulation = controllerValue;
1064 		registerUpdateFlags = kMilesAdLibUpdateFlags_Reg_20;
1065 		break;
1066 
1067 	case MIDI_CONTROLLER_VOLUME:
1068 		_midiChannels[midiChannel].currentVolume = controllerValue;
1069 		registerUpdateFlags = kMilesAdLibUpdateFlags_Reg_40;
1070 		break;
1071 
1072 	case MIDI_CONTROLLER_EXPRESSION:
1073 		_midiChannels[midiChannel].currentVolumeExpression = controllerValue;
1074 		registerUpdateFlags = kMilesAdLibUpdateFlags_Reg_40;
1075 		break;
1076 
1077 	case MIDI_CONTROLLER_PANNING:
1078 		_midiChannels[midiChannel].currentPanning = controllerValue;
1079 		if (_modeStereo) {
1080 			// Update register only in case we are in stereo mode
1081 			registerUpdateFlags = kMilesAdLibUpdateFlags_Reg_C0;
1082 		}
1083 		break;
1084 
1085 	case MIDI_CONTROLLER_SUSTAIN:
1086 		_midiChannels[midiChannel].currentSustain = controllerValue;
1087 		if (controllerValue < 64) {
1088 			releaseSustain(midiChannel);
1089 		}
1090 		break;
1091 
1092 	case MILES_CONTROLLER_PITCH_RANGE:
1093 		// Note that this is in fact the MIDI data entry MSB controller. To use
1094 		// this to set pitch bend range, the pitch bend range RPN should first
1095 		// be selected using the RPN MSB and LSB controllers.
1096 		// MSS does not support the RPN controllers and assumes that any use of
1097 		// the data entry MSB controller is to set the pitch bend range.
1098 
1099 		// Miles Audio 3 feature
1100 		if (_milesVersion == MILES_VERSION_3)
1101 			_midiChannels[midiChannel].currentPitchRange = controllerValue;
1102 		break;
1103 
1104 	case MIDI_CONTROLLER_RESET_ALL_CONTROLLERS:
1105 		_midiChannels[midiChannel].currentSustain = 0;
1106 		releaseSustain(midiChannel);
1107 		_midiChannels[midiChannel].currentModulation = 0;
1108 		_midiChannels[midiChannel].currentVolumeExpression = 127;
1109 		_midiChannels[midiChannel].currentPitchBender = MIDI_PITCH_BEND_DEFAULT;
1110 		registerUpdateFlags = kMilesAdLibUpdateFlags_Reg_20 | kMilesAdLibUpdateFlags_Reg_40 | kMilesAdLibUpdateFlags_Reg_A0;
1111 		break;
1112 
1113 	case MIDI_CONTROLLER_ALL_NOTES_OFF:
1114 		for (byte virtualFmVoice = 0; virtualFmVoice < _modeVirtualFmVoicesCount; virtualFmVoice++) {
1115 			if (_virtualFmVoices[virtualFmVoice].inUse) {
1116 				// used
1117 				if (_virtualFmVoices[virtualFmVoice].actualMidiChannel == midiChannel) {
1118 					// by our current MIDI channel -> noteOff
1119 					noteOff(midiChannel, _virtualFmVoices[virtualFmVoice].currentNote);
1120 				}
1121 			}
1122 		}
1123 		break;
1124 
1125 	default:
1126 		//warning("MILES-ADLIB: Unsupported control change %d", controllerNumber);
1127 		break;
1128 	}
1129 
1130 	if (registerUpdateFlags) {
1131 		for (byte virtualFmVoice = 0; virtualFmVoice < _modeVirtualFmVoicesCount; virtualFmVoice++) {
1132 			if (_virtualFmVoices[virtualFmVoice].inUse) {
1133 				// used
1134 				if (_virtualFmVoices[virtualFmVoice].actualMidiChannel == midiChannel) {
1135 					// by our current MIDI channel -> update
1136 					updatePhysicalFmVoice(virtualFmVoice, true, registerUpdateFlags);
1137 				}
1138 			}
1139 		}
1140 	}
1141 }
1142 
programChange(byte midiChannel,byte patchId)1143 void MidiDriver_Miles_AdLib::programChange(byte midiChannel, byte patchId) {
1144 	const InstrumentEntry *instrumentPtr = NULL;
1145 	byte patchBank = _midiChannels[midiChannel].currentPatchBank;
1146 
1147 	//warning("patch channel %d, patch %x, bank %x", midiChannel, patchId, patchBank);
1148 
1149 	// we check, if we actually have data for the requested instrument...
1150 	instrumentPtr = searchInstrument(patchBank, patchId);
1151 	if (!instrumentPtr) {
1152 		warning("MILES-ADLIB: unknown instrument requested (%d, %d)", patchBank, patchId);
1153 		return;
1154 	}
1155 
1156 	// and remember it in that case for the current MIDI-channel
1157 	_midiChannels[midiChannel].currentInstrumentPtr = instrumentPtr;
1158 }
1159 
searchInstrument(byte bankId,byte patchId)1160 const InstrumentEntry *MidiDriver_Miles_AdLib::searchInstrument(byte bankId, byte patchId) {
1161 	const InstrumentEntry *instrumentPtr = _instrumentTablePtr;
1162 
1163 	for (uint16 instrumentNr = 0; instrumentNr < _instrumentTableCount; instrumentNr++) {
1164 		if ((instrumentPtr->bankId == bankId) && (instrumentPtr->patchId == patchId)) {
1165 			return instrumentPtr;
1166 		}
1167 		instrumentPtr++;
1168 	}
1169 
1170 	return NULL;
1171 }
1172 
pitchBendChange(byte midiChannel,byte parameter1,byte parameter2)1173 void MidiDriver_Miles_AdLib::pitchBendChange(byte midiChannel, byte parameter1, byte parameter2) {
1174 	// Miles Audio actually didn't shift parameter 2 1 down in here
1175 	// which means in memory it used a 15-bit pitch bender, which also means the default was 0x4000
1176 	if ((parameter1 & 0x80) || (parameter2 & 0x80)) {
1177 		warning("MILES-ADLIB: invalid pitch bend change");
1178 		return;
1179 	}
1180 	_midiChannels[midiChannel].currentPitchBender = parameter1 | (parameter2 << 7);
1181 	for (byte virtualFmVoice = 0; virtualFmVoice < _modeVirtualFmVoicesCount; virtualFmVoice++) {
1182 		if (_virtualFmVoices[virtualFmVoice].inUse) {
1183 			// used
1184 			if (_virtualFmVoices[virtualFmVoice].actualMidiChannel == midiChannel) {
1185 				// by our current MIDI channel -> update
1186 				updatePhysicalFmVoice(virtualFmVoice, true, kMilesAdLibUpdateFlags_Reg_A0);
1187 			}
1188 		}
1189 	}
1190 }
1191 
metaEvent(int8 source,byte type,byte * data,uint16 length)1192 void MidiDriver_Miles_AdLib::metaEvent(int8 source, byte type, byte *data, uint16 length) {
1193 	if (type == MIDI_META_END_OF_TRACK && source >= 0)
1194 		// Stop hanging notes and release resources used by this source.
1195 		deinitSource(source);
1196 }
1197 
deinitSource(uint8 source)1198 void MidiDriver_Miles_AdLib::deinitSource(uint8 source) {
1199 	if (!(source == 0 || source == 0xFF))
1200 		return;
1201 
1202 	// Turn off sustained notes.
1203 	for (int i = 0; i < MIDI_CHANNEL_COUNT; i++) {
1204 		controlChange(i, MIDI_CONTROLLER_SUSTAIN, 0);
1205 	}
1206 
1207 	// Stop fades and turn off non-sustained notes.
1208 	MidiDriver_Multisource::deinitSource(source);
1209 }
1210 
setRegister(int reg,int value)1211 void MidiDriver_Miles_AdLib::setRegister(int reg, int value) {
1212 	if (!(reg & 0x100) || _oplType == OPL::Config::kDualOpl2) {
1213 		_opl->write(0x220, reg);
1214 		_opl->write(0x221, value);
1215 		//warning("OPL write %x %x (%d)", reg, value, value);
1216 	}
1217 	if ((reg & 0x100) || _oplType == OPL::Config::kDualOpl2) {
1218 		_opl->write(0x222, reg & 0xFF);
1219 		_opl->write(0x223, value);
1220 		//warning("OPL3 write %x %x (%d)", reg & 0xFF, value, value);
1221 	}
1222 }
1223 
setRegisterStereo(uint8 reg,uint8 valueLeft,uint8 valueRight)1224 void MidiDriver_Miles_AdLib::setRegisterStereo(uint8 reg, uint8 valueLeft, uint8 valueRight) {
1225 	_opl->write(0x220, reg);
1226 	_opl->write(0x221, valueLeft);
1227 	_opl->write(0x222, reg);
1228 	_opl->write(0x223, valueRight);
1229 }
1230 
MidiDriver_Miles_AdLib_create(const Common::String & filenameAdLib,const Common::String & filenameOPL3,Common::SeekableReadStream * streamAdLib,Common::SeekableReadStream * streamOPL3)1231 MidiDriver_Multisource *MidiDriver_Miles_AdLib_create(const Common::String &filenameAdLib, const Common::String &filenameOPL3, Common::SeekableReadStream *streamAdLib, Common::SeekableReadStream *streamOPL3) {
1232 	// Load adlib instrument data from file SAMPLE.AD (OPL3: SAMPLE.OPL)
1233 	Common::String              timbreFilename;
1234 	Common::SeekableReadStream *timbreStream = nullptr;
1235 
1236 	bool          preferOPL3 = false;
1237 
1238 	Common::File *fileStream = new Common::File();
1239 	uint32        fileSize = 0;
1240 	uint32        fileDataOffset = 0;
1241 	uint32        fileDataLeft = 0;
1242 
1243 
1244 	uint32        streamSize = 0;
1245 	byte         *streamDataPtr = nullptr;
1246 
1247 	byte curBankId = 0;
1248 	byte curPatchId = 0;
1249 
1250 	InstrumentEntry *instrumentTablePtr = nullptr;
1251 	uint16           instrumentTableCount = 0;
1252 	InstrumentEntry *instrumentPtr = nullptr;
1253 	uint32           instrumentOffset = 0;
1254 	uint16           instrumentDataSize = 0;
1255 
1256 	// Logic:
1257 	// We prefer OPL3 timbre data in case OPL3 is available in ScummVM
1258 	// If it's not or OPL3 timbre data is not available, we go for AdLib timbre data
1259 	// And if OPL3 is not available in ScummVM and also AdLib timbre data is not available,
1260 	// we then still go for OPL3 timbre data.
1261 	//
1262 	// Note: for most games OPL3 timbre data + AdLib timbre data is the same.
1263 	//       And at least in theory we should still be able to use OPL3 timbre data even for AdLib.
1264 	//       However there is a special OPL3-specific timbre format, which is currently not supported.
1265 	//       In this case the error message "unsupported instrument size" should appear. I haven't found
1266 	//       a game that uses it, which is why I haven't implemented it yet.
1267 
1268 	if (OPL::Config::detect(OPL::Config::kOpl3) >= 0) {
1269 		// OPL3 available, prefer OPL3 timbre data because of this
1270 		preferOPL3 = true;
1271 	}
1272 
1273 	// Check if streams were passed to us and select one of them
1274 	if ((streamAdLib) || (streamOPL3)) {
1275 		// At least one stream was passed by caller
1276 		if (preferOPL3) {
1277 			// Prefer OPL3 timbre stream in case OPL3 is available
1278 			timbreStream = streamOPL3;
1279 		}
1280 		if (!timbreStream) {
1281 			// Otherwise prefer AdLib timbre stream first
1282 			if (streamAdLib) {
1283 				timbreStream = streamAdLib;
1284 			} else {
1285 				// If not available, use OPL3 timbre stream
1286 				if (streamOPL3) {
1287 					timbreStream = streamOPL3;
1288 				}
1289 			}
1290 		}
1291 	}
1292 
1293 	// Now check if any filename was passed to us
1294 	if ((!filenameAdLib.empty()) || (!filenameOPL3.empty())) {
1295 		// If that's the case, check if one of those exists
1296 		if (preferOPL3) {
1297 			// OPL3 available
1298 			if (!filenameOPL3.empty()) {
1299 				if (fileStream->exists(filenameOPL3)) {
1300 					// If OPL3 available, prefer OPL3 timbre file in case file exists
1301 					timbreFilename = filenameOPL3;
1302 				}
1303 			}
1304 			if (timbreFilename.empty()) {
1305 				if (!filenameAdLib.empty()) {
1306 					if (fileStream->exists(filenameAdLib)) {
1307 						// otherwise use AdLib timbre file, if it exists
1308 						timbreFilename = filenameAdLib;
1309 					}
1310 				}
1311 			}
1312 		} else {
1313 			// OPL3 not available
1314 			// Prefer the AdLib one for now
1315 			if (!filenameAdLib.empty()) {
1316 				if (fileStream->exists(filenameAdLib)) {
1317 					// if AdLib file exists, use it
1318 					timbreFilename = filenameAdLib;
1319 				}
1320 			}
1321 			if (timbreFilename.empty()) {
1322 				if (!filenameOPL3.empty()) {
1323 					if (fileStream->exists(filenameOPL3)) {
1324 						// if OPL3 file exists, use it
1325 						timbreFilename = filenameOPL3;
1326 					}
1327 				}
1328 			}
1329 		}
1330 		if (timbreFilename.empty() && (!timbreStream)) {
1331 			// If none of them exists and also no stream was passed, we can't do anything about it
1332 			if (!filenameAdLib.empty()) {
1333 				if (!filenameOPL3.empty()) {
1334 					error("MILES-ADLIB: could not open timbre file (%s or %s)", filenameAdLib.c_str(), filenameOPL3.c_str());
1335 				} else {
1336 					error("MILES-ADLIB: could not open timbre file (%s)", filenameAdLib.c_str());
1337 				}
1338 			} else {
1339 				error("MILES-ADLIB: could not open timbre file (%s)", filenameOPL3.c_str());
1340 			}
1341 		}
1342 	}
1343 
1344 	if (!timbreFilename.empty()) {
1345 		// Filename was passed to us and file exists (this is the common case for most games)
1346 		// We prefer this situation
1347 
1348 		if (!fileStream->open(timbreFilename))
1349 			error("MILES-ADLIB: could not open timbre file (%s)", timbreFilename.c_str());
1350 
1351 		streamSize = fileStream->size();
1352 
1353 		streamDataPtr = new byte[streamSize];
1354 
1355 		if (fileStream->read(streamDataPtr, streamSize) != streamSize)
1356 			error("MILES-ADLIB: error while reading timbre file (%s)", timbreFilename.c_str());
1357 		fileStream->close();
1358 
1359 	} else if (timbreStream) {
1360 		// Timbre data was passed directly (possibly read from resource file by caller)
1361 		// Currently used by "Amazon Guardians of Eden", "Simon 2" and "Return To Zork"
1362 		streamSize = timbreStream->size();
1363 
1364 		streamDataPtr = new byte[streamSize];
1365 
1366 		if (timbreStream->read(streamDataPtr, streamSize) != streamSize)
1367 			error("MILES-ADLIB: error while reading timbre stream");
1368 
1369 	} else {
1370 		error("MILES-ADLIB: timbre filenames nor timbre stream were passed");
1371 	}
1372 
1373 	delete fileStream;
1374 
1375 	// File is like this:
1376 	// [patch:BYTE] [bank:BYTE] [patchoffset:UINT32]
1377 	// ...
1378 	// until patch + bank are both 0xFF, which signals end of header
1379 
1380 	// First we check how many entries there are
1381 	fileDataOffset = 0;
1382 	fileDataLeft = streamSize;
1383 	while (1) {
1384 		if (fileDataLeft < 6)
1385 			error("MILES-ADLIB: unexpected EOF in instrument file");
1386 
1387 		curPatchId = streamDataPtr[fileDataOffset++];
1388 		curBankId  = streamDataPtr[fileDataOffset++];
1389 
1390 		if ((curBankId == 0xFF) && (curPatchId == 0xFF))
1391 			break;
1392 
1393 		fileDataOffset += 4; // skip over offset
1394 		instrumentTableCount++;
1395 	}
1396 
1397 	if (instrumentTableCount == 0)
1398 		error("MILES-ADLIB: no instruments in instrument file");
1399 
1400 	// Allocate space for instruments
1401 	instrumentTablePtr = new InstrumentEntry[instrumentTableCount];
1402 
1403 	// Now actually read all entries
1404 	instrumentPtr = instrumentTablePtr;
1405 
1406 	fileDataOffset = 0;
1407 	fileDataLeft = fileSize;
1408 	while (1) {
1409 		curPatchId = streamDataPtr[fileDataOffset++];
1410 		curBankId  = streamDataPtr[fileDataOffset++];
1411 
1412 		if ((curBankId == 0xFF) && (curPatchId == 0xFF))
1413 			break;
1414 
1415 		instrumentOffset = READ_LE_UINT32(streamDataPtr + fileDataOffset);
1416 		fileDataOffset += 4;
1417 
1418 		instrumentPtr->bankId = curBankId;
1419 		instrumentPtr->patchId = curPatchId;
1420 
1421 		instrumentDataSize = READ_LE_UINT16(streamDataPtr + instrumentOffset);
1422 		if (instrumentDataSize != 14)
1423 			error("MILES-ADLIB: unsupported instrument size");
1424 
1425 		instrumentPtr->transposition = (signed char)streamDataPtr[instrumentOffset + 2];
1426 		instrumentPtr->reg20op1 = streamDataPtr[instrumentOffset + 3];
1427 		instrumentPtr->reg40op1 = streamDataPtr[instrumentOffset + 4];
1428 		instrumentPtr->reg60op1 = streamDataPtr[instrumentOffset + 5];
1429 		instrumentPtr->reg80op1 = streamDataPtr[instrumentOffset + 6];
1430 		instrumentPtr->regE0op1 = streamDataPtr[instrumentOffset + 7];
1431 		instrumentPtr->regC0    = streamDataPtr[instrumentOffset + 8];
1432 		instrumentPtr->reg20op2 = streamDataPtr[instrumentOffset + 9];
1433 		instrumentPtr->reg40op2 = streamDataPtr[instrumentOffset + 10];
1434 		instrumentPtr->reg60op2 = streamDataPtr[instrumentOffset + 11];
1435 		instrumentPtr->reg80op2 = streamDataPtr[instrumentOffset + 12];
1436 		instrumentPtr->regE0op2 = streamDataPtr[instrumentOffset + 13];
1437 
1438 		// Instrument read, next instrument please
1439 		instrumentPtr++;
1440 	}
1441 
1442 	// Free instrument file/stream data
1443 	delete[] streamDataPtr;
1444 
1445 	return new MidiDriver_Miles_AdLib(instrumentTablePtr, instrumentTableCount);
1446 }
1447 
1448 } // End of namespace Audio
1449