diff options
Diffstat (limited to 'engines/tinsel/music.cpp')
-rw-r--r-- | engines/tinsel/music.cpp | 209 |
1 files changed, 120 insertions, 89 deletions
diff --git a/engines/tinsel/music.cpp b/engines/tinsel/music.cpp index b3bfbcc5dc..3144ea7f94 100644 --- a/engines/tinsel/music.cpp +++ b/engines/tinsel/music.cpp @@ -187,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; } @@ -277,63 +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); - if (g_midiBuffer.pDat) - // already allocated - return; + uint32 curTrack = 1; + uint32 songLength = 0; + int32 fileSize = midiStream.size(); - // open MIDI sequence file in binary mode - if (!midiStream.open(MIDI_FILE)) - error(CANNOT_FIND_FILE, MIDI_FILE); + // Init + for (int i = 0; i < ARRAYSIZE(g_midiOffsets); i++) + g_midiOffsets[i] = 0; - // 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; + midiStream.skip(4); // skip file header + + 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() { @@ -784,8 +815,8 @@ bool PCMMusicPlayer::getNextChunk() { // Set parameters for this chunk of music id = _scriptNum; while (id--) - script = scriptBuffer + READ_LE_UINT32(script); - snum = FROM_LE_32(script[_scriptIndex++]); + script = scriptBuffer + READ_32(script); + snum = FROM_32(script[_scriptIndex++]); if (snum == MUSIC_JUMP || snum == MUSIC_END) { // Let usual code sort it out! @@ -797,11 +828,11 @@ bool PCMMusicPlayer::getNextChunk() { musicSegments = (MusicSegment *) LockMem(_hSegment); - assert(FROM_LE_32(musicSegments[snum].numChannels) == 1); - assert(FROM_LE_32(musicSegments[snum].bitsPerSample) == 16); + assert(FROM_32(musicSegments[snum].numChannels) == 1); + assert(FROM_32(musicSegments[snum].bitsPerSample) == 16); - sampleOffset = FROM_LE_32(musicSegments[snum].sampleOffset); - sampleLength = FROM_LE_32(musicSegments[snum].sampleLength); + sampleOffset = FROM_32(musicSegments[snum].sampleOffset); + sampleLength = FROM_32(musicSegments[snum].sampleLength); sampleCLength = (((sampleLength + 63) & ~63)*33)/64; if (!file.open(_filename)) @@ -839,14 +870,14 @@ bool PCMMusicPlayer::getNextChunk() { id = _scriptNum; while (id--) - script = scriptBuffer + READ_LE_UINT32(script); - snum = FROM_LE_32(script[_scriptIndex]); + script = scriptBuffer + READ_32(script); + snum = FROM_32(script[_scriptIndex]); if (snum == MUSIC_END) { _state = S_END2; } else { if (snum == MUSIC_JUMP) - _scriptIndex = FROM_LE_32(script[_scriptIndex+1]); + _scriptIndex = FROM_32(script[_scriptIndex+1]); _state = _forcePlay ? S_NEW : S_NEXT; _forcePlay = false; |