aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFilippos Karapetis2013-04-12 19:28:20 +0300
committerFilippos Karapetis2013-04-12 19:31:11 +0300
commit95f92ed9dea8049fc148095d1ca99cde4fdad522 (patch)
treecfeabf8ab085a9d83144193768421a94843301fe
parentcfeda2888564111c7c8d9e178429c8b1080fdbf4 (diff)
downloadscummvm-rg350-95f92ed9dea8049fc148095d1ca99cde4fdad522.tar.gz
scummvm-rg350-95f92ed9dea8049fc148095d1ca99cde4fdad522.tar.bz2
scummvm-rg350-95f92ed9dea8049fc148095d1ca99cde4fdad522.zip
TINSEL: Add support for enhanced music in the Mac version of DW1
-rw-r--r--engines/tinsel/detection_tables.h2
-rw-r--r--engines/tinsel/music.cpp198
-rw-r--r--engines/tinsel/sound.cpp20
-rw-r--r--engines/tinsel/sound.h2
4 files changed, 114 insertions, 108 deletions
diff --git a/engines/tinsel/detection_tables.h b/engines/tinsel/detection_tables.h
index f6b1487561..4762acfe2c 100644
--- a/engines/tinsel/detection_tables.h
+++ b/engines/tinsel/detection_tables.h
@@ -490,7 +490,7 @@ static const TinselGameDescription gameDescriptions[] = {
},
GID_DW1,
0,
- GF_SCNFILES,
+ GF_SCNFILES | GF_ENHANCED_AUDIO_SUPPORT,
TINSEL_V1,
},
diff --git a/engines/tinsel/music.cpp b/engines/tinsel/music.cpp
index dab2a897fc..3144ea7f94 100644
--- a/engines/tinsel/music.cpp
+++ b/engines/tinsel/music.cpp
@@ -135,10 +135,6 @@ bool PlayMidiSequence(uint32 dwFileOffset, bool bLoop) {
if (ConfMan.hasKey("mute"))
mute = ConfMan.getBool("mute");
- // The Macintosh version of DW1 uses raw PCM for music
- if (TinselV1Mac)
- return _vm->_sound->playDW1MacMusic(dwFileOffset);
-
SetMidiVolume(mute ? 0 : _vm->_config->_musicVolume);
// the index and length of the last tune loaded
@@ -191,43 +187,48 @@ bool PlayMidiSequence(uint32 dwFileOffset, bool bLoop) {
// move to correct position in the file
midiStream.seek(dwFileOffset, SEEK_SET);
- // read the length of the sequence
- dwSeqLen = midiStream.readUint32LE();
-
- // make sure buffer is large enough for this sequence
- assert(dwSeqLen > 0 && dwSeqLen <= g_midiBuffer.size);
-
- // stop any currently playing tune
- _vm->_midiMusic->stop();
-
- // read the sequence. This needs to be read again before playSEQ() is
- // called even if the music is restarting, as playSEQ() reads the file
- // name off the buffer itself. However, that function adds SMF headers
- // to the buffer, thus if it's read again, the SMF headers will be read
- // and the filename will always be 'MThd'.
- if (midiStream.read(g_midiBuffer.pDat, dwSeqLen) != dwSeqLen)
- error(FILE_IS_CORRUPT, MIDI_FILE);
-
- midiStream.close();
+ if (TinselV1Mac) {
+ // The Macintosh version of DW1 uses raw PCM for music
+ dwSeqLen = midiStream.readUint32BE();
+ _vm->_sound->playDW1MacMusic(midiStream, dwSeqLen);
+ } else {
+ dwSeqLen = midiStream.readUint32LE();
+
+ // make sure buffer is large enough for this sequence
+ assert(dwSeqLen > 0 && dwSeqLen <= g_midiBuffer.size);
+
+ // stop any currently playing tune
+ _vm->_midiMusic->stop();
+
+ // read the sequence. This needs to be read again before playSEQ() is
+ // called even if the music is restarting, as playSEQ() reads the file
+ // name off the buffer itself. However, that function adds SMF headers
+ // to the buffer, thus if it's read again, the SMF headers will be read
+ // and the filename will always be 'MThd'.
+ if (midiStream.read(g_midiBuffer.pDat, dwSeqLen) != dwSeqLen)
+ error(FILE_IS_CORRUPT, MIDI_FILE);
+
+ // WORKAROUND for bug #2820054 "DW1: No intro music at first start on Wii",
+ // which actually affects all ports, since it's specific to the GRA version.
+ //
+ // The GRA version does not seem to set the channel volume at all for the first
+ // intro track, thus we need to do that here. We only initialize the channels
+ // used in that sequence. And we are using 127 as default channel volume.
+ //
+ // Only in the GRA version dwFileOffset can be "38888", just to be sure, we
+ // check for the SCN files feature flag not being set though.
+ if (_vm->getGameID() == GID_DW1 && dwFileOffset == 38888 && !(_vm->getFeatures() & GF_SCNFILES)) {
+ _vm->_midiMusic->send(0x7F07B0 | 3);
+ _vm->_midiMusic->send(0x7F07B0 | 5);
+ _vm->_midiMusic->send(0x7F07B0 | 8);
+ _vm->_midiMusic->send(0x7F07B0 | 10);
+ _vm->_midiMusic->send(0x7F07B0 | 13);
+ }
- // WORKAROUND for bug #2820054 "DW1: No intro music at first start on Wii",
- // which actually affects all ports, since it's specific to the GRA version.
- //
- // The GRA version does not seem to set the channel volume at all for the first
- // intro track, thus we need to do that here. We only initialize the channels
- // used in that sequence. And we are using 127 as default channel volume.
- //
- // Only in the GRA version dwFileOffset can be "38888", just to be sure, we
- // check for the SCN files feature flag not being set though.
- if (_vm->getGameID() == GID_DW1 && dwFileOffset == 38888 && !(_vm->getFeatures() & GF_SCNFILES)) {
- _vm->_midiMusic->send(0x7F07B0 | 3);
- _vm->_midiMusic->send(0x7F07B0 | 5);
- _vm->_midiMusic->send(0x7F07B0 | 8);
- _vm->_midiMusic->send(0x7F07B0 | 10);
- _vm->_midiMusic->send(0x7F07B0 | 13);
+ _vm->_midiMusic->playMIDI(dwSeqLen, bLoop);
}
- _vm->_midiMusic->playMIDI(dwSeqLen, bLoop);
+ midiStream.close();
return true;
}
@@ -281,68 +282,89 @@ void SetMidiVolume(int vol) {
void OpenMidiFiles() {
Common::File midiStream;
- // Demo version has no midi file
- if (TinselV0 || TinselV2)
- return;
+ if (TinselV0) {
+ // The early demo version of DW1 doesn't have MIDI
+ } else if (TinselV2) {
+ // DW2 uses a different music mechanism
+ } else if (TinselV1Mac) {
+ // open MIDI sequence file in binary mode
+ if (!midiStream.open(MIDI_FILE))
+ error(CANNOT_FIND_FILE, MIDI_FILE);
- // The Macintosh version of DW1 does not use MIDI for music.
- // It uses PCM music instead, which is quite big to be preloaded here.
- if (TinselV1Mac)
- return;
+ uint32 curTrack = 1;
+ uint32 songLength = 0;
+ int32 fileSize = midiStream.size();
- if (g_midiBuffer.pDat)
- // already allocated
- return;
+ // Init
+ for (int i = 0; i < ARRAYSIZE(g_midiOffsets); i++)
+ g_midiOffsets[i] = 0;
- // open MIDI sequence file in binary mode
- if (!midiStream.open(MIDI_FILE))
- error(CANNOT_FIND_FILE, MIDI_FILE);
+ midiStream.skip(4); // skip file header
- // gen length of the largest sequence
- g_midiBuffer.size = midiStream.readUint32LE();
- if (midiStream.eos() || midiStream.err())
- error(FILE_IS_CORRUPT, MIDI_FILE);
-
- if (g_midiBuffer.size) {
- // allocate a buffer big enough for the largest MIDI sequence
- if ((g_midiBuffer.pDat = (uint8 *)malloc(g_midiBuffer.size)) != NULL) {
- // clear out the buffer
- memset(g_midiBuffer.pDat, 0, g_midiBuffer.size);
-// VMM_lock(midiBuffer.pDat, midiBuffer.size);
- } else {
- //mSeqHandle = NULL;
+ while (!midiStream.eos() && !midiStream.err() && midiStream.pos() != fileSize) {
+ assert(curTrack < ARRAYSIZE(g_midiOffsets));
+ g_midiOffsets[curTrack] = midiStream.pos();
+ //debug("%d: %d", curTrack, g_midiOffsets[curTrack]);
+
+ songLength = midiStream.readUint32BE();
+ midiStream.skip(songLength);
+
+ curTrack++;
}
- }
- // Now scan through the contents of the MIDI file to find the offset
- // of each individual track, in order to create a mapping from MIDI
- // offset to track number, for the enhanced MIDI soundtrack.
- // The first song is always at position 4. The subsequent ones are
- // calculated dynamically.
- uint32 curOffset = 4;
- uint32 curTrack = 0;
- uint32 songLength = 0;
+ midiStream.close();
+ } else {
+ if (g_midiBuffer.pDat)
+ // already allocated
+ return;
+
+ // open MIDI sequence file in binary mode
+ if (!midiStream.open(MIDI_FILE))
+ error(CANNOT_FIND_FILE, MIDI_FILE);
+
+ // get length of the largest sequence
+ g_midiBuffer.size = midiStream.readUint32LE();
+ if (midiStream.eos() || midiStream.err())
+ error(FILE_IS_CORRUPT, MIDI_FILE);
+
+ if (g_midiBuffer.size) {
+ // allocate a buffer big enough for the largest MIDI sequence
+ if ((g_midiBuffer.pDat = (uint8 *)malloc(g_midiBuffer.size)) != NULL) {
+ // clear out the buffer
+ memset(g_midiBuffer.pDat, 0, g_midiBuffer.size);
+ }
+ }
- // Init
- for (int i = 0; i < ARRAYSIZE(g_midiOffsets); i++)
- g_midiOffsets[i] = 0;
+ // Now scan through the contents of the MIDI file to find the offset
+ // of each individual track, in order to create a mapping from MIDI
+ // offset to track number, for the enhanced MIDI soundtrack.
+ // The first song is always at position 4. The subsequent ones are
+ // calculated dynamically.
+ uint32 curOffset = 4;
+ uint32 curTrack = 0;
+ uint32 songLength = 0;
+
+ // Init
+ for (int i = 0; i < ARRAYSIZE(g_midiOffsets); i++)
+ g_midiOffsets[i] = 0;
+
+ while (!midiStream.eos() && !midiStream.err()) {
+ if (curOffset + (4 * curTrack) >= (uint32)midiStream.size())
+ break;
- while (!midiStream.eos() && !midiStream.err()) {
- if (curOffset + (4 * curTrack) >= (uint32)midiStream.size())
- break;
+ assert(curTrack < ARRAYSIZE(g_midiOffsets));
+ g_midiOffsets[curTrack] = curOffset + (4 * curTrack);
+ //debug("%d: %d", curTrack, midiOffsets[curTrack]);
- assert(curTrack < ARRAYSIZE(g_midiOffsets));
- g_midiOffsets[curTrack] = curOffset + (4 * curTrack);
- //debug("%d: %d", curTrack, midiOffsets[curTrack]);
+ songLength = midiStream.readUint32LE();
+ curOffset += songLength;
+ midiStream.skip(songLength);
- songLength = midiStream.readUint32LE();
- curOffset += songLength;
- midiStream.skip(songLength);
+ curTrack++;
+ }
- curTrack++;
+ midiStream.close();
}
-
- midiStream.close();
}
void DeleteMidiBuffer() {
diff --git a/engines/tinsel/sound.cpp b/engines/tinsel/sound.cpp
index cea4971769..cadc754de6 100644
--- a/engines/tinsel/sound.cpp
+++ b/engines/tinsel/sound.cpp
@@ -177,15 +177,7 @@ bool SoundManager::playSample(int id, Audio::Mixer::SoundType type, Audio::Sound
return true;
}
-bool SoundManager::playDW1MacMusic(int dwFileOffset) {
- Common::File s;
-
- if (!s.open("midi.dat"))
- error(CANNOT_FIND_FILE, "midi.dat");
-
- s.seek(dwFileOffset);
- uint32 length = s.readUint32BE();
-
+void SoundManager::playDW1MacMusic(Common::File &s, uint32 length) {
// TODO: It's a bad idea to load the music track in a buffer.
// We should use a SubReadStream instead, and keep midi.dat open.
// However, the track lengths aren't that big (about 1-4MB),
@@ -195,28 +187,20 @@ bool SoundManager::playDW1MacMusic(int dwFileOffset) {
// read all of the sample
if (s.read(soundData, length) != length)
- error(FILE_IS_CORRUPT, "midi.dat");
+ error(FILE_IS_CORRUPT, MIDI_FILE);
Common::SeekableReadStream *memStream = new Common::MemoryReadStream(soundData, length);
Audio::SoundHandle *handle = &_channels[kChannelDW1MacMusic].handle;
- //_channels[kChannelDW1MacMusic].sampleNum = dwFileOffset;
// Stop any previously playing music track
_vm->_mixer->stopHandle(*handle);
- // FIXME: Should set this in a different place ;)
- _vm->_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, _vm->_config->_musicVolume);
-
// TODO: Compression support (MP3/OGG/FLAC) for midi.dat in DW1 Mac
Audio::RewindableAudioStream *musicStream = Audio::makeRawStream(memStream, 22050, Audio::FLAG_UNSIGNED, DisposeAfterUse::YES);
if (musicStream)
_vm->_mixer->playStream(Audio::Mixer::kMusicSoundType, handle, Audio::makeLoopingAudioStream(musicStream, 0));
-
- s.close();
-
- return true;
}
// playSample for DiscWorld 2
diff --git a/engines/tinsel/sound.h b/engines/tinsel/sound.h
index 8510c1618f..c68d9cb71e 100644
--- a/engines/tinsel/sound.h
+++ b/engines/tinsel/sound.h
@@ -109,7 +109,7 @@ public:
bool playSample(int id, Audio::Mixer::SoundType type, Audio::SoundHandle *handle = 0);
bool playSample(int id, int sub, bool bLooped, int x, int y, int priority,
Audio::Mixer::SoundType type, Audio::SoundHandle *handle = 0);
- bool playDW1MacMusic(int dwFileOffset);
+ void playDW1MacMusic(Common::File &s, uint32 length);
void stopAllSamples(); // Stops any currently playing sample
void stopSpecSample(int id, int sub = 0); // Stops a specific sample