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 "common/config-manager.h"
24 #include "common/file.h"
25 #include "common/textconsole.h"
26 #include "common/memstream.h"
27
28 #include "agos/agos.h"
29 #include "agos/midi.h"
30
31 #include "agos/drivers/accolade/mididriver.h"
32 #include "agos/drivers/accolade/adlib.h"
33 #include "agos/drivers/accolade/mt32.h"
34 #include "agos/drivers/simon1/adlib.h"
35 // Miles Audio for Simon 2
36 #include "audio/miles.h"
37
38 // PKWARE data compression library decompressor required for Simon 2
39 #include "common/dcl.h"
40
41 #include "gui/message.h"
42
43 namespace AGOS {
44
45
46 // MidiParser_S1D is not considered part of the standard
47 // MidiParser suite, but we still try to mask its details
48 // and just provide a factory function.
49 extern MidiParser *MidiParser_createS1D();
50
MidiPlayer()51 MidiPlayer::MidiPlayer() {
52 // Since initialize() is called every time the music changes,
53 // this is where we'll initialize stuff that must persist
54 // between songs.
55 _driver = 0;
56 _map_mt32_to_gm = false;
57
58 _adLibMusic = false;
59 _enable_sfx = true;
60 _current = 0;
61
62 _musicVolume = 255;
63 _sfxVolume = 255;
64
65 resetVolumeTable();
66 _paused = false;
67
68 _currentTrack = 255;
69 _loopTrack = 0;
70 _queuedTrack = 255;
71 _loopQueuedTrack = 0;
72
73 _musicMode = kMusicModeDisabled;
74 }
75
~MidiPlayer()76 MidiPlayer::~MidiPlayer() {
77 stop();
78
79 Common::StackLock lock(_mutex);
80 if (_driver) {
81 _driver->setTimerCallback(0, 0);
82 _driver->close();
83 delete _driver;
84 }
85 _driver = NULL;
86 clearConstructs();
87 }
88
open(int gameType,bool isDemo)89 int MidiPlayer::open(int gameType, bool isDemo) {
90 // Don't call open() twice!
91 assert(!_driver);
92
93 Common::String accoladeDriverFilename;
94 musicType = MT_INVALID;
95
96 switch (gameType) {
97 case GType_ELVIRA1:
98 _musicMode = kMusicModeAccolade;
99 accoladeDriverFilename = "INSTR.DAT";
100 break;
101 case GType_ELVIRA2:
102 case GType_WW:
103 // Attention: Elvira 2 shipped with INSTR.DAT and MUSIC.DRV
104 // MUSIC.DRV is the correct one. INSTR.DAT seems to be a left-over
105 _musicMode = kMusicModeAccolade;
106 accoladeDriverFilename = "MUSIC.DRV";
107 break;
108 case GType_SIMON1:
109 if (isDemo) {
110 _musicMode = kMusicModeAccolade;
111 accoladeDriverFilename = "MUSIC.DRV";
112 } else if (Common::File::exists("MT_FM.IBK")) {
113 _musicMode = kMusicModeSimon1;
114 }
115 break;
116 case GType_SIMON2:
117 //_musicMode = kMusicModeMilesAudio;
118 // currently disabled, because there are a few issues
119 // MT32 seems to work fine now, AdLib seems to use bad instruments and is also outputting music on
120 // the right speaker only. The original driver did initialize the panning to 0 and the Simon2 XMIDI
121 // tracks don't set panning at all. We can reset panning to be centered, which would solve this
122 // issue, but we still don't know who's setting it in the original interpreter.
123 break;
124 default:
125 break;
126 }
127
128 MidiDriver::DeviceHandle dev;
129 int ret = 0;
130
131 if (_musicMode != kMusicModeDisabled) {
132 dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MT32);
133 musicType = MidiDriver::getMusicType(dev);
134
135 switch (musicType) {
136 case MT_ADLIB:
137 case MT_MT32:
138 break;
139 case MT_GM:
140 if (!ConfMan.getBool("native_mt32")) {
141 // Not a real MT32 / no MUNT
142 ::GUI::MessageDialog dialog(("You appear to be using a General MIDI device,\n"
143 "but your game only supports Roland MT32 MIDI.\n"
144 "We try to map the Roland MT32 instruments to\n"
145 "General MIDI ones. It is still possible that\n"
146 "some tracks sound incorrect."));
147 dialog.runModal();
148 }
149 // Switch to MT32 driver in any case
150 musicType = MT_MT32;
151 break;
152 default:
153 _musicMode = kMusicModeDisabled;
154 break;
155 }
156 }
157
158 switch (_musicMode) {
159 case kMusicModeAccolade: {
160 // Setup midi driver
161 switch (musicType) {
162 case MT_ADLIB:
163 _driver = MidiDriver_Accolade_AdLib_create(accoladeDriverFilename);
164
165 break;
166 case MT_MT32:
167 _driver = MidiDriver_Accolade_MT32_create(accoladeDriverFilename);
168 break;
169 default:
170 assert(0);
171 break;
172 }
173 if (!_driver)
174 return 255;
175
176 ret = _driver->open();
177 if (ret == 0) {
178 // Reset is done inside our MIDI driver
179 _driver->setTimerCallback(this, &onTimer);
180 }
181
182 //setTimerRate(_driver->getBaseTempo());
183 return 0;
184 }
185
186 case kMusicModeMilesAudio: {
187 switch (musicType) {
188 case MT_ADLIB: {
189 Common::File instrumentDataFile;
190 if (instrumentDataFile.exists("MIDPAK.AD")) {
191 // if there is a file called MIDPAK.AD, use it directly
192 warning("SIMON 2: using MIDPAK.AD");
193 _driver = Audio::MidiDriver_Miles_AdLib_create("MIDPAK.AD", "MIDPAK.AD");
194 } else {
195 // if there is no file called MIDPAK.AD, try to extract it from the file SETUP.SHR
196 // if we didn't do this, the user would be forced to "install" the game instead of simply
197 // copying all files from CD-ROM.
198 Common::SeekableReadStream *midpakAdLibStream;
199 midpakAdLibStream = simon2SetupExtractFile("MIDPAK.AD");
200 if (!midpakAdLibStream)
201 error("MidiPlayer: could not extract MIDPAK.AD from SETUP.SHR");
202
203 // Pass this extracted data to the driver
204 warning("SIMON 2: using MIDPAK.AD extracted from SETUP.SHR");
205 _driver = Audio::MidiDriver_Miles_AdLib_create("", "", midpakAdLibStream);
206 delete midpakAdLibStream;
207 }
208 // TODO: not sure what's going wrong with AdLib
209 // it doesn't seem to matter if we use the regular XMIDI tracks or the 2nd set meant for MT32
210 break;
211 }
212 case MT_MT32:
213 _driver = Audio::MidiDriver_Miles_MT32_create("");
214 _nativeMT32 = true; // use 2nd set of XMIDI tracks
215 break;
216 case MT_GM:
217 if (ConfMan.getBool("native_mt32")) {
218 _driver = Audio::MidiDriver_Miles_MT32_create("");
219 _nativeMT32 = true; // use 2nd set of XMIDI tracks
220 }
221 break;
222
223 default:
224 break;
225 }
226 if (!_driver)
227 return 255;
228
229 ret = _driver->open();
230 if (ret == 0) {
231 // Reset is done inside our MIDI driver
232 _driver->setTimerCallback(this, &onTimer);
233 }
234 return 0;
235 }
236
237 case kMusicModeSimon1: {
238 // This only handles the original AdLib driver of Simon1.
239 if (musicType == MT_ADLIB) {
240 _adLibMusic = true;
241 _map_mt32_to_gm = false;
242 _nativeMT32 = false;
243
244 _driver = createMidiDriverSimon1AdLib("MT_FM.IBK");
245 if (_driver && _driver->open() == 0) {
246 _driver->setTimerCallback(this, &onTimer);
247 // Like the original, we enable the rhythm support by default.
248 _driver->send(0xB0, 0x67, 0x01);
249 return 0;
250 }
251
252 delete _driver;
253 _driver = nullptr;
254 }
255
256 _musicMode = kMusicModeDisabled;
257 }
258
259 default:
260 break;
261 }
262
263 dev = MidiDriver::detectDevice(MDT_ADLIB | MDT_MIDI | (gameType == GType_SIMON1 ? MDT_PREFER_MT32 : MDT_PREFER_GM));
264 _adLibMusic = (MidiDriver::getMusicType(dev) == MT_ADLIB);
265 _nativeMT32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32"));
266
267 _driver = MidiDriver::createMidi(dev);
268 if (!_driver)
269 return 255;
270
271 if (_nativeMT32)
272 _driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
273
274 _map_mt32_to_gm = (gameType != GType_SIMON2 && !_nativeMT32);
275
276 ret = _driver->open();
277 if (ret)
278 return ret;
279 _driver->setTimerCallback(this, &onTimer);
280
281 if (_nativeMT32)
282 _driver->sendMT32Reset();
283 else
284 _driver->sendGMReset();
285
286 return 0;
287 }
288
send(uint32 b)289 void MidiPlayer::send(uint32 b) {
290 if (!_current)
291 return;
292
293 if (_musicMode != kMusicModeDisabled) {
294 // Handle volume control for Simon1 output.
295 if (_musicMode == kMusicModeSimon1) {
296 // The driver does not support any volume control, thus we simply
297 // scale the velocities on note on for now.
298 // TODO: We should probably handle this at output level at some
299 // point. Then we can allow volume changes to affect already
300 // playing notes too. For now this simple change allows us to
301 // have some simple volume control though.
302 if ((b & 0xF0) == 0x90) {
303 byte volume = (b >> 16) & 0x7F;
304
305 if (_current == &_sfx) {
306 volume = volume * _sfxVolume / 255;
307 } else if (_current == &_music) {
308 volume = volume * _musicVolume / 255;
309 }
310
311 b = (b & 0xFF00FFFF) | (volume << 16);
312 }
313 }
314
315 // Send directly to Accolade/Miles/Simon1 Audio driver
316 _driver->send(b);
317 return;
318 }
319
320 byte channel = (byte)(b & 0x0F);
321 if ((b & 0xFFF0) == 0x07B0) {
322 // Adjust volume changes by master music and master sfx volume.
323 byte volume = (byte)((b >> 16) & 0x7F);
324 _current->volume[channel] = volume;
325 if (_current == &_sfx)
326 volume = volume * _sfxVolume / 255;
327 else if (_current == &_music)
328 volume = volume * _musicVolume / 255;
329 b = (b & 0xFF00FFFF) | (volume << 16);
330 } else if ((b & 0xF0) == 0xC0 && _map_mt32_to_gm) {
331 b = (b & 0xFFFF00FF) | (MidiDriver::_mt32ToGm[(b >> 8) & 0xFF] << 8);
332 } else if ((b & 0xFFF0) == 0x007BB0) {
333 // Only respond to an All Notes Off if this channel
334 // has already been allocated.
335 if (!_current->channel[b & 0x0F])
336 return;
337 } else if ((b & 0xFFF0) == 0x79B0) {
338 // "Reset All Controllers". There seems to be some confusion
339 // about what this message should do to the volume controller.
340 // See http://www.midi.org/about-midi/rp15.shtml for more
341 // information.
342 //
343 // If I understand it correctly, the current standard indicates
344 // that the volume should be reset, but the next revision will
345 // exclude it. On my system, both ALSA and FluidSynth seem to
346 // reset it, while AdLib does not. Let's follow the majority.
347
348 _current->volume[channel] = 127;
349 }
350
351 // Allocate channels if needed
352 if (!_current->channel[channel])
353 _current->channel[channel] = (channel == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel();
354
355 if (_current->channel[channel]) {
356 if (channel == 9) {
357 if (_current == &_sfx)
358 _current->channel[9]->volume(_current->volume[9] * _sfxVolume / 255);
359 else if (_current == &_music)
360 _current->channel[9]->volume(_current->volume[9] * _musicVolume / 255);
361 }
362 _current->channel[channel]->send(b);
363 if ((b & 0xFFF0) == 0x79B0) {
364 // We have received a "Reset All Controllers" message
365 // and passed it on to the MIDI driver. This may or may
366 // not have affected the volume controller. To ensure
367 // consistent behavior, explicitly set the volume to
368 // what we think it should be.
369
370 if (_current == &_sfx)
371 _current->channel[channel]->volume(_current->volume[channel] * _sfxVolume / 255);
372 else if (_current == &_music)
373 _current->channel[channel]->volume(_current->volume[channel] * _musicVolume / 255);
374 }
375 }
376 }
377
metaEvent(byte type,byte * data,uint16 length)378 void MidiPlayer::metaEvent(byte type, byte *data, uint16 length) {
379 // Only thing we care about is End of Track.
380 if (!_current || type != 0x2F) {
381 return;
382 } else if (_current == &_sfx) {
383 clearConstructs(_sfx);
384 } else if (_loopTrack) {
385 _current->parser->jumpToTick(0);
386 } else if (_queuedTrack != 255) {
387 _currentTrack = 255;
388 byte destination = _queuedTrack;
389 _queuedTrack = 255;
390 _loopTrack = _loopQueuedTrack;
391 _loopQueuedTrack = false;
392
393 // Remember, we're still inside the locked mutex.
394 // Have to unlock it before calling jump()
395 // (which locks it itself), and then relock it
396 // upon returning.
397 _mutex.unlock();
398 startTrack(destination);
399 _mutex.lock();
400 } else {
401 stop();
402 }
403 }
404
onTimer(void * data)405 void MidiPlayer::onTimer(void *data) {
406 MidiPlayer *p = (MidiPlayer *)data;
407 Common::StackLock lock(p->_mutex);
408
409 if (!p->_paused) {
410 if (p->_music.parser && p->_currentTrack != 255) {
411 p->_current = &p->_music;
412 p->_music.parser->onTimer();
413 }
414 }
415 if (p->_sfx.parser) {
416 p->_current = &p->_sfx;
417 p->_sfx.parser->onTimer();
418 }
419 p->_current = 0;
420 }
421
startTrack(int track)422 void MidiPlayer::startTrack(int track) {
423 Common::StackLock lock(_mutex);
424
425 if (track == _currentTrack)
426 return;
427
428 if (_music.num_songs > 0) {
429 if (track >= _music.num_songs)
430 return;
431
432 if (_music.parser) {
433 _current = &_music;
434 delete _music.parser;
435 _current = 0;
436 _music.parser = 0;
437 }
438
439 MidiParser *parser = MidiParser::createParser_SMF();
440 parser->property (MidiParser::mpMalformedPitchBends, 1);
441 parser->setMidiDriver(this);
442 parser->setTimerRate(_driver->getBaseTempo());
443 if (!parser->loadMusic(_music.songs[track], _music.song_sizes[track])) {
444 warning("Error reading track %d", track);
445 delete parser;
446 parser = 0;
447 }
448
449 _currentTrack = (byte)track;
450 _music.parser = parser; // That plugs the power cord into the wall
451 } else if (_music.parser) {
452 if (!_music.parser->setTrack(track)) {
453 return;
454 }
455 _currentTrack = (byte)track;
456 _current = &_music;
457 _music.parser->jumpToTick(0);
458 _current = 0;
459 }
460 }
461
stop()462 void MidiPlayer::stop() {
463 Common::StackLock lock(_mutex);
464
465 if (_music.parser) {
466 _current = &_music;
467 _music.parser->jumpToTick(0);
468 }
469 _current = 0;
470 _currentTrack = 255;
471 }
472
pause(bool b)473 void MidiPlayer::pause(bool b) {
474 if (_paused == b || !_driver)
475 return;
476 _paused = b;
477
478 Common::StackLock lock(_mutex);
479 // if using the driver Accolade_AdLib call setVolume() to turn off\on the volume on all channels
480 if (musicType == MT_ADLIB && _musicMode == kMusicModeAccolade) {
481 static_cast <MidiDriver_Accolade_AdLib*> (_driver)->setVolume(_paused ? 0 : 128);
482 }
483 for (int i = 0; i < 16; ++i) {
484 if (_music.channel[i])
485 _music.channel[i]->volume(_paused ? 0 : (_music.volume[i] * _musicVolume / 255));
486 if (_sfx.channel[i])
487 _sfx.channel[i]->volume(_paused ? 0 : (_sfx.volume[i] * _sfxVolume / 255));
488 }
489 }
490
setVolume(int musicVol,int sfxVol)491 void MidiPlayer::setVolume(int musicVol, int sfxVol) {
492 musicVol = CLIP(musicVol, 0, 255);
493 sfxVol = CLIP(sfxVol, 0, 255);
494
495 if (_musicVolume == musicVol && _sfxVolume == sfxVol)
496 return;
497
498 _musicVolume = musicVol;
499 _sfxVolume = sfxVol;
500
501 // Now tell all the channels this.
502 Common::StackLock lock(_mutex);
503 if (_driver && !_paused) {
504 for (int i = 0; i < 16; ++i) {
505 if (_music.channel[i])
506 _music.channel[i]->volume(_music.volume[i] * _musicVolume / 255);
507 if (_sfx.channel[i])
508 _sfx.channel[i]->volume(_sfx.volume[i] * _sfxVolume / 255);
509 }
510 }
511 }
512
setLoop(bool loop)513 void MidiPlayer::setLoop(bool loop) {
514 Common::StackLock lock(_mutex);
515
516 _loopTrack = loop;
517 }
518
queueTrack(int track,bool loop)519 void MidiPlayer::queueTrack(int track, bool loop) {
520 _mutex.lock();
521 if (_currentTrack == 255) {
522 _mutex.unlock();
523 setLoop(loop);
524 startTrack(track);
525 } else {
526 _queuedTrack = track;
527 _loopQueuedTrack = loop;
528 _mutex.unlock();
529 }
530 }
531
clearConstructs()532 void MidiPlayer::clearConstructs() {
533 clearConstructs(_music);
534 clearConstructs(_sfx);
535 }
536
clearConstructs(MusicInfo & info)537 void MidiPlayer::clearConstructs(MusicInfo &info) {
538 int i;
539 if (info.num_songs > 0) {
540 for (i = 0; i < info.num_songs; ++i)
541 free(info.songs[i]);
542 info.num_songs = 0;
543 }
544
545 free(info.data);
546 info.data = 0;
547
548 delete info.parser;
549 info.parser = 0;
550
551 if (_driver) {
552 for (i = 0; i < 16; ++i) {
553 if (info.channel[i]) {
554 info.channel[i]->allNotesOff();
555 info.channel[i]->release();
556 }
557 }
558 }
559 info.clear();
560 }
561
resetVolumeTable()562 void MidiPlayer::resetVolumeTable() {
563 int i;
564 for (i = 0; i < 16; ++i) {
565 _music.volume[i] = _sfx.volume[i] = 127;
566 if (_driver)
567 _driver->send(((_musicVolume >> 1) << 16) | 0x7B0 | i);
568 }
569 }
570
571 static const int simon1_gmf_size[] = {
572 8900, 12166, 2848, 3442, 4034, 4508, 7064, 9730, 6014, 4742, 3138,
573 6570, 5384, 8909, 6457, 16321, 2742, 8968, 4804, 8442, 7717,
574 9444, 5800, 1381, 5660, 6684, 2456, 4744, 2455, 1177, 1232,
575 17256, 5103, 8794, 4884, 16
576 };
577
loadSMF(Common::File * in,int song,bool sfx)578 void MidiPlayer::loadSMF(Common::File *in, int song, bool sfx) {
579 Common::StackLock lock(_mutex);
580
581 MusicInfo *p = sfx ? &_sfx : &_music;
582 clearConstructs(*p);
583
584 uint32 startpos = in->pos();
585 byte header[4];
586 in->read(header, 4);
587 bool isGMF = !memcmp(header, "GMF\x1", 4);
588 in->seek(startpos, SEEK_SET);
589
590 uint32 size = in->size() - in->pos();
591 if (isGMF) {
592 if (sfx) {
593 // Multiple GMF resources are stored in the SFX files,
594 // but each one is referenced by a pointer at the
595 // beginning of the file. Those pointers can be used
596 // to determine file size.
597 in->seek(0, SEEK_SET);
598 uint16 value = in->readUint16LE() >> 2; // Number of resources
599 if (song != value - 1) {
600 in->seek(song * 2 + 2, SEEK_SET);
601 value = in->readUint16LE();
602 size = value - startpos;
603 }
604 in->seek(startpos, SEEK_SET);
605 } else if (size >= 64000) {
606 // For GMF resources not in separate
607 // files, we're going to have to use
608 // hardcoded size tables.
609 size = simon1_gmf_size[song];
610 }
611 }
612
613 // When allocating space, add 4 bytes in case
614 // this is a GMF and we have to tack on our own
615 // End of Track event.
616 p->data = (byte *)calloc(size + 4, 1);
617 in->read(p->data, size);
618
619 uint32 timerRate = _driver->getBaseTempo();
620
621 if (isGMF) {
622 // The GMF header
623 // 3 BYTES: 'GMF'
624 // 1 BYTE : Major version
625 // 1 BYTE : Minor version
626 // 1 BYTE : Ticks (Ranges from 2 - 8, always 2 for SFX)
627 // 1 BYTE : Loop control. 0 = no loop, 1 = loop (Music only)
628 if (!sfx) {
629 // In the original, the ticks value indicated how many
630 // times the music timer was called before it actually
631 // did something. The larger the value the slower the
632 // music.
633 //
634 // We, on the other hand, have a timer rate which is
635 // used to control by how much the music advances on
636 // each onTimer() call. The larger the value, the
637 // faster the music.
638 //
639 // It seems that 4 corresponds to our base tempo, so
640 // this should be the right way to calculate it.
641 timerRate = (4 * _driver->getBaseTempo()) / p->data[5];
642
643 // According to bug #1004919 calling setLoop() from
644 // within a lock causes a lockup, though I have no
645 // idea when this actually happens.
646 _loopTrack = (p->data[6] != 0);
647 }
648 }
649
650 MidiParser *parser = MidiParser::createParser_SMF();
651 parser->property(MidiParser::mpMalformedPitchBends, 1);
652 parser->setMidiDriver(this);
653 parser->setTimerRate(timerRate);
654 if (!parser->loadMusic(p->data, size)) {
655 warning("Error reading track");
656 delete parser;
657 parser = 0;
658 }
659
660 if (!sfx) {
661 _currentTrack = 255;
662 resetVolumeTable();
663 }
664 p->parser = parser; // That plugs the power cord into the wall
665 }
666
loadMultipleSMF(Common::File * in,bool sfx)667 void MidiPlayer::loadMultipleSMF(Common::File *in, bool sfx) {
668 // This is a special case for Simon 2 Windows.
669 // Instead of having multiple sequences as
670 // separate tracks in a Type 2 file, simon2win
671 // has multiple songs, each of which is a Type 1
672 // file. Thus, preceding the songs is a single
673 // byte specifying how many songs are coming.
674 // We need to load ALL the songs and then
675 // treat them as separate tracks -- for the
676 // purpose of jumps, anyway.
677 Common::StackLock lock(_mutex);
678
679 MusicInfo *p = sfx ? &_sfx : &_music;
680 clearConstructs(*p);
681
682 p->num_songs = in->readByte();
683 if (p->num_songs > 16) {
684 warning("playMultipleSMF: %d is too many songs to keep track of", (int)p->num_songs);
685 return;
686 }
687
688 byte i;
689 for (i = 0; i < p->num_songs; ++i) {
690 byte buf[5];
691 uint32 pos = in->pos();
692
693 // Make sure there's a MThd
694 in->read(buf, 4);
695 if (memcmp(buf, "MThd", 4) != 0) {
696 warning("Expected MThd but found '%c%c%c%c' instead", buf[0], buf[1], buf[2], buf[3]);
697 return;
698 }
699 in->seek(in->readUint32BE(), SEEK_CUR);
700
701 // Now skip all the MTrk blocks
702 while (true) {
703 in->read(buf, 4);
704 if (memcmp(buf, "MTrk", 4) != 0)
705 break;
706 in->seek(in->readUint32BE(), SEEK_CUR);
707 }
708
709 uint32 pos2 = in->pos() - 4;
710 uint32 size = pos2 - pos;
711 p->songs[i] = (byte *)calloc(size, 1);
712 in->seek(pos, SEEK_SET);
713 in->read(p->songs[i], size);
714 p->song_sizes[i] = size;
715 }
716
717 if (!sfx) {
718 _currentTrack = 255;
719 resetVolumeTable();
720 }
721 }
722
loadXMIDI(Common::File * in,bool sfx)723 void MidiPlayer::loadXMIDI(Common::File *in, bool sfx) {
724 Common::StackLock lock(_mutex);
725 MusicInfo *p = sfx ? &_sfx : &_music;
726 clearConstructs(*p);
727
728 char buf[4];
729 uint32 pos = in->pos();
730 uint32 size = 4;
731 in->read(buf, 4);
732 if (!memcmp(buf, "FORM", 4)) {
733 int i;
734 for (i = 0; i < 16; ++i) {
735 if (!memcmp(buf, "CAT ", 4))
736 break;
737 size += 2;
738 memcpy(buf, &buf[2], 2);
739 in->read(&buf[2], 2);
740 }
741 if (memcmp(buf, "CAT ", 4) != 0) {
742 error("Could not find 'CAT ' tag to determine resource size");
743 }
744 size += 4 + in->readUint32BE();
745 in->seek(pos, 0);
746 p->data = (byte *)calloc(size, 1);
747 in->read(p->data, size);
748 } else {
749 error("Expected 'FORM' tag but found '%c%c%c%c' instead", buf[0], buf[1], buf[2], buf[3]);
750 }
751
752 // In the DOS version of Simon the Sorcerer 2, the music contains lots
753 // of XMIDI callback controller events. As far as we know, they aren't
754 // actually used, so we disable the callback handler explicitly.
755
756 MidiParser *parser = MidiParser::createParser_XMIDI(NULL);
757 parser->setMidiDriver(this);
758 parser->setTimerRate(_driver->getBaseTempo());
759 if (!parser->loadMusic(p->data, size))
760 error("Error reading track");
761
762 if (!sfx) {
763 _currentTrack = 255;
764 resetVolumeTable();
765 }
766 p->parser = parser; // That plugs the power cord into the wall
767 }
768
loadS1D(Common::File * in,bool sfx)769 void MidiPlayer::loadS1D(Common::File *in, bool sfx) {
770 Common::StackLock lock(_mutex);
771 MusicInfo *p = sfx ? &_sfx : &_music;
772 clearConstructs(*p);
773
774 uint16 size = in->readUint16LE();
775 if (size != in->size() - 2) {
776 error("Size mismatch in MUS file (%ld versus reported %d)", (long)in->size() - 2, (int)size);
777 }
778
779 p->data = (byte *)calloc(size, 1);
780 in->read(p->data, size);
781
782 MidiParser *parser = MidiParser_createS1D();
783 parser->setMidiDriver(this);
784 parser->setTimerRate(_driver->getBaseTempo());
785 if (!parser->loadMusic(p->data, size))
786 error("Error reading track");
787
788 if (!sfx) {
789 _currentTrack = 255;
790 resetVolumeTable();
791 }
792 p->parser = parser; // That plugs the power cord into the wall
793 }
794
795 #define MIDI_SETUP_BUNDLE_HEADER_SIZE 56
796 #define MIDI_SETUP_BUNDLE_FILEHEADER_SIZE 48
797 #define MIDI_SETUP_BUNDLE_FILENAME_MAX_SIZE 12
798
799 // PKWARE data compression library (called "DCL" in ScummVM) was used for storing files within SETUP.SHR
800 // we need it to be able to get the file MIDPAK.AD, otherwise we would have to require the user
801 // to "install" the game before being able to actually play it, when using AdLib.
802 //
803 // SETUP.SHR file format:
804 // [bundle file header]
805 // [compressed file header] [compressed file data]
806 // * compressed file count
simon2SetupExtractFile(const Common::String & requestedFileName)807 Common::SeekableReadStream *MidiPlayer::simon2SetupExtractFile(const Common::String &requestedFileName) {
808 Common::File *setupBundleStream = new Common::File();
809 uint32 bundleSize = 0;
810 uint32 bundleBytesLeft = 0;
811 byte bundleHeader[MIDI_SETUP_BUNDLE_HEADER_SIZE];
812 byte bundleFileHeader[MIDI_SETUP_BUNDLE_FILEHEADER_SIZE];
813 uint16 bundleFileCount = 0;
814 uint16 bundleFileNr = 0;
815
816 Common::String fileName;
817 uint32 fileCompressedSize = 0;
818 byte *fileCompressedDataPtr = nullptr;
819
820 Common::SeekableReadStream *extractedStream = nullptr;
821
822 if (!setupBundleStream->open("setup.shr"))
823 error("MidiPlayer: could not open setup.shr");
824
825 bundleSize = setupBundleStream->size();
826 bundleBytesLeft = bundleSize;
827
828 if (bundleSize < MIDI_SETUP_BUNDLE_HEADER_SIZE)
829 error("MidiPlayer: unexpected EOF in setup.shr");
830
831 if (setupBundleStream->read(bundleHeader, MIDI_SETUP_BUNDLE_HEADER_SIZE) != MIDI_SETUP_BUNDLE_HEADER_SIZE)
832 error("MidiPlayer: setup.shr read error");
833 bundleBytesLeft -= MIDI_SETUP_BUNDLE_HEADER_SIZE;
834
835 // Verify header byte
836 if (bundleHeader[13] != 't')
837 error("MidiPlayer: setup.shr bundle header data mismatch");
838
839 bundleFileCount = READ_LE_UINT16(&bundleHeader[14]);
840
841 // Search for requested file
842 while (bundleFileNr < bundleFileCount) {
843 if (bundleBytesLeft < sizeof(bundleFileHeader))
844 error("MidiPlayer: unexpected EOF in setup.shr");
845
846 if (setupBundleStream->read(bundleFileHeader, sizeof(bundleFileHeader)) != sizeof(bundleFileHeader))
847 error("MidiPlayer: setup.shr read error");
848 bundleBytesLeft -= MIDI_SETUP_BUNDLE_FILEHEADER_SIZE;
849
850 // Extract filename from file-header
851 fileName.clear();
852 for (byte curPos = 0; curPos < MIDI_SETUP_BUNDLE_FILENAME_MAX_SIZE; curPos++) {
853 if (!bundleFileHeader[curPos]) // terminating NUL
854 break;
855 fileName.insertChar(bundleFileHeader[curPos], curPos);
856 }
857
858 // Get compressed
859 fileCompressedSize = READ_LE_UINT32(&bundleFileHeader[20]);
860 if (!fileCompressedSize)
861 error("MidiPlayer: compressed file is 0 bytes, data corruption?");
862 if (bundleBytesLeft < fileCompressedSize)
863 error("MidiPlayer: unexpected EOF in setup.shr");
864
865 if (fileName == requestedFileName) {
866 // requested file found
867 fileCompressedDataPtr = new byte[fileCompressedSize];
868
869 if (setupBundleStream->read(fileCompressedDataPtr, fileCompressedSize) != fileCompressedSize)
870 error("MidiPlayer: setup.shr read error");
871
872 Common::MemoryReadStream *compressedStream = nullptr;
873
874 compressedStream = new Common::MemoryReadStream(fileCompressedDataPtr, fileCompressedSize);
875 // we don't know the unpacked size, let decompressor figure it out
876 extractedStream = Common::decompressDCL(compressedStream);
877 delete compressedStream;
878 break;
879 }
880
881 // skip compressed size
882 setupBundleStream->skip(fileCompressedSize);
883 bundleBytesLeft -= fileCompressedSize;
884
885 bundleFileNr++;
886 }
887 setupBundleStream->close();
888 delete setupBundleStream;
889
890 return extractedStream;
891 }
892
893 } // End of namespace AGOS
894