aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/sci/resource.h1
-rw-r--r--engines/sci/resource_audio.cpp52
-rw-r--r--engines/sci/sound/midiparser_sci.cpp21
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)