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 "sherlock/sherlock.h"
24 #include "sherlock/scalpel/drivers/mididriver.h"
25
26 #include "common/config-manager.h"
27 #include "common/file.h"
28 #include "common/system.h"
29 #include "common/textconsole.h"
30
31 //#include "audio/mididrv.h"
32
33 namespace Sherlock {
34
35 #define SHERLOCK_MT32_CHANNEL_COUNT 16
36
37 const byte mt32ReverbDataSysEx[] = {
38 0x10, 0x00, 0x01, 0x01, 0x05, 0x05, 0xFF
39 };
40
41 class MidiDriver_MT32 : public MidiDriver {
42 public:
MidiDriver_MT32()43 MidiDriver_MT32() {
44 _driver = NULL;
45 _isOpen = false;
46 _nativeMT32 = false;
47 _baseFreq = 250;
48
49 memset(_MIDIchannelActive, 1, sizeof(_MIDIchannelActive));
50 }
51 virtual ~MidiDriver_MT32();
52
53 // MidiDriver
54 int open();
55 void close();
isOpen() const56 bool isOpen() const { return _isOpen; }
57
58 void send(uint32 b);
59
60 void newMusicData(byte *musicData, int32 musicDataSize);
61
allocateChannel()62 MidiChannel *allocateChannel() {
63 if (_driver)
64 return _driver->allocateChannel();
65 return NULL;
66 }
getPercussionChannel()67 MidiChannel *getPercussionChannel() {
68 if (_driver)
69 return _driver->getPercussionChannel();
70 return NULL;
71 }
72
setTimerCallback(void * timer_param,Common::TimerManager::TimerProc timer_proc)73 void setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc) {
74 if (_driver)
75 _driver->setTimerCallback(timer_param, timer_proc);
76 }
77
getBaseTempo()78 uint32 getBaseTempo() {
79 if (_driver) {
80 return _driver->getBaseTempo();
81 }
82 return 1000000 / _baseFreq;
83 }
84
85 protected:
86 Common::Mutex _mutex;
87 MidiDriver *_driver;
88 bool _nativeMT32;
89
90 bool _isOpen;
91 int _baseFreq;
92
93 private:
94 // points to a MIDI channel for each of the new voice channels
95 byte _MIDIchannelActive[SHERLOCK_MT32_CHANNEL_COUNT];
96
97 public:
98 void uploadMT32Patches(byte *driverData, int32 driverSize);
99
100 void mt32SysEx(const byte *&dataPtr, int32 &bytesLeft);
101 };
102
~MidiDriver_MT32()103 MidiDriver_MT32::~MidiDriver_MT32() {
104 Common::StackLock lock(_mutex);
105 if (_driver) {
106 _driver->setTimerCallback(0, 0);
107 _driver->close();
108 delete _driver;
109 }
110 _driver = NULL;
111 }
112
open()113 int MidiDriver_MT32::open() {
114 assert(!_driver);
115
116 debugC(kDebugLevelMT32Driver, "MT32: starting driver");
117
118 // Setup midi driver
119 MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_PREFER_MT32);
120 MusicType musicType = MidiDriver::getMusicType(dev);
121
122 switch (musicType) {
123 case MT_MT32:
124 _nativeMT32 = true;
125 break;
126 case MT_GM:
127 if (ConfMan.getBool("native_mt32")) {
128 _nativeMT32 = true;
129 }
130 break;
131 default:
132 break;
133 }
134
135 _driver = MidiDriver::createMidi(dev);
136 if (!_driver)
137 return 255;
138
139 if (_nativeMT32)
140 _driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
141
142 int ret = _driver->open();
143 if (ret)
144 return ret;
145
146 if (_nativeMT32)
147 _driver->sendMT32Reset();
148 else
149 _driver->sendGMReset();
150
151 return 0;
152 }
153
close()154 void MidiDriver_MT32::close() {
155 if (_driver) {
156 _driver->close();
157 }
158 }
159
160 // Called when a music track got loaded into memory
newMusicData(byte * musicData,int32 musicDataSize)161 void MidiDriver_MT32::newMusicData(byte *musicData, int32 musicDataSize) {
162 assert(musicDataSize >= 0x7F); // Security check
163
164 // MIDI Channel Enable/Disable bytes at offset 0x2 of music data
165 memcpy(&_MIDIchannelActive, musicData + 0x2, SHERLOCK_MT32_CHANNEL_COUNT);
166
167 // Send 16 bytes from offset 0x12 to MT32
168 // All the music tracks of Sherlock seem to contain dummy data
169 // probably a feature, that was used in the game "Ski or Die"
170 // that's why we don't implement this
171
172 // Also send these bytes to MT32 (SysEx) - seems to be reverb configuration
173 if (_nativeMT32) {
174 const byte *reverbData = mt32ReverbDataSysEx;
175 int32 reverbDataSize = sizeof(mt32ReverbDataSysEx);
176 mt32SysEx(reverbData, reverbDataSize);
177 }
178 }
179
uploadMT32Patches(byte * driverData,int32 driverSize)180 void MidiDriver_MT32::uploadMT32Patches(byte *driverData, int32 driverSize) {
181 if (!_driver)
182 return;
183
184 if (!_nativeMT32)
185 return;
186
187 // patch data starts at offset 0x863
188 assert(driverSize == 0x13B9); // Security check
189 assert(driverData[0x863] == 0x7F); // another security check
190
191 const byte *patchPtr = driverData + 0x863;
192 int32 bytesLeft = driverSize - 0x863;
193
194 while(1) {
195 mt32SysEx(patchPtr, bytesLeft);
196
197 assert(bytesLeft);
198 if (*patchPtr == 0x80) // List terminator
199 break;
200 }
201 }
202
mt32SysEx(const byte * & dataPtr,int32 & bytesLeft)203 void MidiDriver_MT32::mt32SysEx(const byte *&dataPtr, int32 &bytesLeft) {
204 byte sysExMessage[270];
205 uint16 sysExPos = 0;
206 byte sysExByte = 0;
207 uint16 sysExChecksum = 0;
208
209 memset(&sysExMessage, 0, sizeof(sysExMessage));
210
211 sysExMessage[0] = 0x41; // Roland
212 sysExMessage[1] = 0x10;
213 sysExMessage[2] = 0x16; // Model MT32
214 sysExMessage[3] = 0x12; // Command DT1
215
216 sysExPos = 4;
217 sysExChecksum = 0;
218 while (1) {
219 assert(bytesLeft);
220
221 sysExByte = *dataPtr++;
222 bytesLeft--;
223 if (sysExByte == 0xff)
224 break; // Message done
225
226 assert(sysExPos < sizeof(sysExMessage));
227 sysExMessage[sysExPos++] = sysExByte;
228 sysExChecksum -= sysExByte;
229 }
230
231 // Calculate checksum
232 assert(sysExPos < sizeof(sysExMessage));
233 sysExMessage[sysExPos++] = sysExChecksum & 0x7f;
234
235 debugC(kDebugLevelMT32Driver, "MT32: uploading patch data, size %d", sysExPos);
236
237 // Send SysEx
238 _driver->sysEx(sysExMessage, sysExPos);
239
240 // Wait the time it takes to send the SysEx data
241 uint32 delay = (sysExPos + 2) * 1000 / 3125;
242
243 // Plus an additional delay for the MT-32 rev00
244 if (_nativeMT32)
245 delay += 40;
246
247 g_system->delayMillis(delay);
248 }
249
250 // MIDI messages can be found at http://www.midi.org/techspecs/midimessages.php
send(uint32 b)251 void MidiDriver_MT32::send(uint32 b) {
252 byte command = b & 0xf0;
253 byte channel = b & 0xf;
254
255 if (command == 0xF0) {
256 if (_driver) {
257 _driver->send(b);
258 }
259 return;
260 }
261
262 if (_MIDIchannelActive[channel]) {
263 // Only forward MIDI-data in case the channel is currently enabled via music-data
264 if (_driver) {
265 _driver->send(b);
266 }
267 }
268 }
269
MidiDriver_MT32_create()270 MidiDriver *MidiDriver_MT32_create() {
271 return new MidiDriver_MT32();
272 }
273
MidiDriver_MT32_newMusicData(MidiDriver * driver,byte * musicData,int32 musicDataSize)274 void MidiDriver_MT32_newMusicData(MidiDriver *driver, byte *musicData, int32 musicDataSize) {
275 static_cast<MidiDriver_MT32 *>(driver)->newMusicData(musicData, musicDataSize);
276 }
277
MidiDriver_MT32_uploadPatches(MidiDriver * driver,byte * driverData,int32 driverSize)278 void MidiDriver_MT32_uploadPatches(MidiDriver *driver, byte *driverData, int32 driverSize) {
279 static_cast<MidiDriver_MT32 *>(driver)->uploadMT32Patches(driverData, driverSize);
280 }
281
282 } // End of namespace Sherlock
283