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