diff options
-rw-r--r-- | engines/sci/resource.h | 1 | ||||
-rw-r--r-- | engines/sci/resource_audio.cpp | 52 | ||||
-rw-r--r-- | engines/sci/sound/midiparser_sci.cpp | 21 |
3 files changed, 47 insertions, 27 deletions
diff --git a/engines/sci/resource.h b/engines/sci/resource.h index 584c61dbd6..a13781b157 100644 --- a/engines/sci/resource.h +++ b/engines/sci/resource.h @@ -492,6 +492,7 @@ public: uint16 prio; uint16 size; byte *data; + uint16 curPos; long time; byte prev; }; diff --git a/engines/sci/resource_audio.cpp b/engines/sci/resource_audio.cpp index 8629fecfa7..13aa81cb24 100644 --- a/engines/sci/resource_audio.cpp +++ b/engines/sci/resource_audio.cpp @@ -480,8 +480,8 @@ int ResourceManager::getAudioLanguage() const { return (_audioMapSCI1 ? _audioMapSCI1->_volumeNumber : 0); } -SoundResource::SoundResource(uint32 resNumber, ResourceManager *resMan, SciVersion soundVersion) : _resMan(resMan), _soundVersion(soundVersion) { - Resource *resource = _resMan->findResource(ResourceId(kResourceTypeSound, resNumber), true); +SoundResource::SoundResource(uint32 resourceNr, ResourceManager *resMan, SciVersion soundVersion) : _resMan(resMan), _soundVersion(soundVersion) { + Resource *resource = _resMan->findResource(ResourceId(kResourceTypeSound, resourceNr), true); int trackNr, channelNr; if (!resource) return; @@ -554,6 +554,9 @@ SoundResource::SoundResource(uint32 resNumber, ResourceManager *resMan, SciVersi } _tracks = new Track[_trackCount]; data = resource->data; + + byte channelCount; + for (trackNr = 0; trackNr < _trackCount; trackNr++) { // Track info starts with track type:BYTE // Then the channel information gets appended Unknown:WORD, ChannelOffset:WORD, ChannelSize:WORD @@ -563,34 +566,47 @@ SoundResource::SoundResource(uint32 resNumber, ResourceManager *resMan, SciVersi _tracks[trackNr].type = *data++; // Counting # of channels used data2 = data; - _tracks[trackNr].channelCount = 0; + channelCount = 0; while (*data2 != 0xFF) { data2 += 6; + channelCount++; _tracks[trackNr].channelCount++; } - _tracks[trackNr].channels = new Channel[_tracks[trackNr].channelCount]; + _tracks[trackNr].channels = new Channel[channelCount]; + _tracks[trackNr].channelCount = 0; _tracks[trackNr].digitalChannelNr = -1; // No digital sound associated _tracks[trackNr].digitalSampleRate = 0; _tracks[trackNr].digitalSampleSize = 0; _tracks[trackNr].digitalSampleStart = 0; _tracks[trackNr].digitalSampleEnd = 0; if (_tracks[trackNr].type != 0xF0) { // Digital track marker - not supported currently - for (channelNr = 0; channelNr < _tracks[trackNr].channelCount; channelNr++) { + channelNr = 0; + while (channelCount--) { channel = &_tracks[trackNr].channels[channelNr]; channel->prio = READ_LE_UINT16(data); - channel->data = resource->data + READ_LE_UINT16(data + 2) + 2; - channel->size = READ_LE_UINT16(data + 4) - 2; // Not counting channel header - channel->number = *(channel->data - 2); - channel->poly = *(channel->data - 1); - channel->time = channel->prev = 0; - if (channel->number == 0xFE) { // Digital channel - _tracks[trackNr].digitalChannelNr = channelNr; - _tracks[trackNr].digitalSampleRate = READ_LE_UINT16(channel->data); - _tracks[trackNr].digitalSampleSize = READ_LE_UINT16(channel->data + 2); - _tracks[trackNr].digitalSampleStart = READ_LE_UINT16(channel->data + 4); - _tracks[trackNr].digitalSampleEnd = READ_LE_UINT16(channel->data + 6); - channel->data += 8; // Skip over header - channel->size -= 8; + uint dataOffset = READ_LE_UINT16(data + 2); + if (dataOffset < resource->size) { + channel->data = resource->data + dataOffset; + channel->size = READ_LE_UINT16(data + 4); + channel->curPos = 0; + channel->number = *channel->data; + channel->poly = *(channel->data + 1); + channel->time = channel->prev = 0; + channel->data += 2; // skip over header + channel->size -= 2; // remove header size + if (channel->number == 0xFE) { // Digital channel + _tracks[trackNr].digitalChannelNr = channelNr; + _tracks[trackNr].digitalSampleRate = READ_LE_UINT16(channel->data); + _tracks[trackNr].digitalSampleSize = READ_LE_UINT16(channel->data + 2); + _tracks[trackNr].digitalSampleStart = READ_LE_UINT16(channel->data + 4); + _tracks[trackNr].digitalSampleEnd = READ_LE_UINT16(channel->data + 6); + channel->data += 8; // Skip over header + channel->size -= 8; + } + _tracks[trackNr].channelCount++; + channelNr++; + } else { + warning("Invalid offset inside sound resource %d: track %d, channel %d", resourceNr, trackNr, channelNr); } data += 6; } diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp index ebb2a172cc..5f361c02ec 100644 --- a/engines/sci/sound/midiparser_sci.cpp +++ b/engines/sci/sound/midiparser_sci.cpp @@ -422,7 +422,10 @@ byte MidiParser_SCI::midiGetNextChannel(long ticker) { for (int i = 0; i < _track->channelCount; i++) { if (_track->channels[i].time == -1) // channel ended continue; - next = *_track->channels[i].data; // when the next event should occur + SoundResource::Channel *curChannel = &_track->channels[i]; + if (curChannel->curPos >= curChannel->size) + continue; + next = curChannel->data[curChannel->curPos]; // when the next event should occur if (next == 0xF8) // 0xF8 means 240 ticks delay next = 240; next += _track->channels[i].time; @@ -449,21 +452,21 @@ byte *MidiParser_SCI::midiMixChannels() { byte *outData = new byte[totalSize * 2]; // FIXME: creates overhead and still may be not enough to hold all data _mixedData = outData; long ticker = 0; - byte curr, curDelta; + byte channelNr, curDelta; byte command = 0, par1, global_prev = 0; long new_delta; SoundResource::Channel *channel; - while ((curr = midiGetNextChannel(ticker)) != 0xFF) { // there is still an active channel - channel = &_track->channels[curr]; - curDelta = *channel->data++; + while ((channelNr = midiGetNextChannel(ticker)) != 0xFF) { // there is still an active channel + channel = &_track->channels[channelNr]; + curDelta = channel->data[channel->curPos++]; channel->time += (curDelta == 0xF8 ? 240 : curDelta); // when the command is supposed to occur if (curDelta == 0xF8) continue; new_delta = channel->time - ticker; ticker += new_delta; - command = *channel->data++; + command = channel->data[channel->curPos++]; if (command != kEndOfTrack) { debugC(4, kDebugLevelSound, "\nDELTA "); // Write delta @@ -481,7 +484,7 @@ byte *MidiParser_SCI::midiMixChannels() { *outData++ = command; debugC(4, kDebugLevelSound, "%02X ", command); do { - par1 = *channel->data++; + par1 = channel->data[channel->curPos++]; *outData++ = par1; // out } while (par1 != 0xF7); break; @@ -492,7 +495,7 @@ byte *MidiParser_SCI::midiMixChannels() { break; default: // MIDI command if (command & 0x80) { - par1 = *channel->data++; + par1 = channel->data[channel->curPos++]; } else {// running status par1 = command; command = channel->prev; @@ -506,7 +509,7 @@ byte *MidiParser_SCI::midiMixChannels() { *outData++ = command; // out command *outData++ = par1;// pout par1 if (nMidiParams[(command >> 4) - 8] == 2) - *outData++ = *channel->data++; // out par2 + *outData++ = channel->data[channel->curPos++]; // out par2 channel->prev = command; global_prev = command; }// switch(command) |