aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/resource_audio.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/sci/resource_audio.cpp')
-rw-r--r--engines/sci/resource_audio.cpp181
1 files changed, 97 insertions, 84 deletions
diff --git a/engines/sci/resource_audio.cpp b/engines/sci/resource_audio.cpp
index f17a684cc9..0125a0e19b 100644
--- a/engines/sci/resource_audio.cpp
+++ b/engines/sci/resource_audio.cpp
@@ -80,11 +80,12 @@ AudioVolumeResourceSource::~AudioVolumeResourceSource() {
}
bool Resource::loadFromWaveFile(Common::SeekableReadStream *file) {
- data = new byte[size];
+ byte *ptr = new byte[_size];
+ _data = ptr;
- uint32 really_read = file->read(data, size);
- if (really_read != size)
- error("Read %d bytes from %s but expected %d", really_read, _id.toString().c_str(), size);
+ uint32 bytesRead = file->read(ptr, _size);
+ if (bytesRead != _size)
+ error("Read %d bytes from %s but expected %lu", bytesRead, _id.toString().c_str(), _size);
_status = kResStatusAllocated;
return true;
@@ -95,7 +96,7 @@ bool Resource::loadFromAudioVolumeSCI11(Common::SeekableReadStream *file) {
uint32 riffTag = file->readUint32BE();
if (riffTag == MKTAG('R','I','F','F')) {
_headerSize = 0;
- size = file->readUint32LE() + 8;
+ _size = file->readUint32LE() + 8;
file->seek(-8, SEEK_CUR);
return loadFromWaveFile(file);
}
@@ -123,7 +124,8 @@ bool Resource::loadFromAudioVolumeSCI11(Common::SeekableReadStream *file) {
if (_headerSize != 7) { // Size is defined already from the map
// Load sample size
file->seek(7, SEEK_CUR);
- size = file->readUint32LE();
+ _size = file->readUint32LE();
+ assert(!file->err() && !file->eos());
// Adjust offset to point at the header data again
file->seek(-11, SEEK_CUR);
}
@@ -133,15 +135,16 @@ bool Resource::loadFromAudioVolumeSCI11(Common::SeekableReadStream *file) {
}
bool Resource::loadFromAudioVolumeSCI1(Common::SeekableReadStream *file) {
- data = new byte[size];
+ byte *ptr = new byte[size()];
+ _data = ptr;
- if (data == NULL) {
- error("Can't allocate %d bytes needed for loading %s", size, _id.toString().c_str());
+ if (!ptr) {
+ error("Can't allocate %lu bytes needed for loading %s", _size, _id.toString().c_str());
}
- uint32 really_read = file->read(data, size);
- if (really_read != size)
- warning("Read %d bytes from %s but expected %d", really_read, _id.toString().c_str(), size);
+ uint32 bytesRead = file->read(ptr, size());
+ if (bytesRead != size())
+ warning("Read %d bytes from %s but expected %lu", bytesRead, _id.toString().c_str(), _size);
_status = kResStatusAllocated;
return true;
@@ -300,11 +303,13 @@ int ResourceManager::readAudioMapSCI11(IntMapResourceSource *map) {
return SCI_ERROR_NO_RESOURCE_FILES_FOUND;
}
- byte *ptr = mapRes->data;
+ const uint32 srcSize = getVolumeFile(src)->size();
+
+ SciSpan<const byte>::const_iterator ptr = mapRes->cbegin();
// Heuristic to detect entry size
uint32 entrySize = 0;
- for (int i = mapRes->size - 1; i >= 0; --i) {
+ for (int i = mapRes->size() - 1; i >= 0; --i) {
if (ptr[i] == 0xff)
entrySize++;
else
@@ -312,52 +317,54 @@ int ResourceManager::readAudioMapSCI11(IntMapResourceSource *map) {
}
if (map->_mapNumber == 65535) {
- while (ptr < mapRes->data + mapRes->size) {
- uint16 n = READ_LE_UINT16(ptr);
+ while (ptr != mapRes->cend()) {
+ uint16 n = ptr.getUint16LE();
ptr += 2;
if (n == 0xffff)
break;
if (entrySize == 6) {
- offset = READ_LE_UINT32(ptr);
+ offset = ptr.getUint32LE();
ptr += 4;
} else {
- offset += READ_LE_UINT24(ptr);
+ offset += ptr.getUint24LE();
ptr += 3;
}
+ assert(offset < srcSize);
addResource(ResourceId(kResourceTypeAudio, n), src, offset);
}
} else if (map->_mapNumber == 0 && entrySize == 10 && ptr[3] == 0) {
// QFG3 demo format
// ptr[3] would be 'seq' in the normal format and cannot possibly be 0
- while (ptr < mapRes->data + mapRes->size) {
- uint16 n = READ_BE_UINT16(ptr);
+ while (ptr != mapRes->cend()) {
+ uint16 n = ptr.getUint16BE();
ptr += 2;
if (n == 0xffff)
break;
- offset = READ_LE_UINT32(ptr);
+ offset = ptr.getUint32LE();
ptr += 4;
- uint32 size = READ_LE_UINT32(ptr);
+ uint32 size = ptr.getUint32LE();
ptr += 4;
+ assert(offset + size <= srcSize);
addResource(ResourceId(kResourceTypeAudio, n), src, offset, size);
}
- } else if (map->_mapNumber == 0 && entrySize == 8 && READ_LE_UINT16(ptr + 2) == 0xffff) {
+ } else if (map->_mapNumber == 0 && entrySize == 8 && (ptr + 2).getUint16LE() == 0xffff) {
// LB2 Floppy/Mother Goose SCI1.1 format
Common::SeekableReadStream *stream = getVolumeFile(src);
- while (ptr < mapRes->data + mapRes->size) {
- uint16 n = READ_LE_UINT16(ptr);
+ while (ptr != mapRes->cend()) {
+ uint16 n = ptr.getUint16LE();
ptr += 4;
if (n == 0xffff)
break;
- offset = READ_LE_UINT32(ptr);
+ offset = ptr.getUint32LE();
ptr += 4;
// The size is not stored in the map and the entries have no order.
@@ -369,18 +376,19 @@ int ResourceManager::readAudioMapSCI11(IntMapResourceSource *map) {
stream->skip(5);
uint32 size = stream->readUint32LE() + headerSize + 2;
+ assert(offset + size <= srcSize);
addResource(ResourceId(kResourceTypeAudio, n), src, offset, size);
}
} else {
bool isEarly = (entrySize != 11);
if (!isEarly) {
- offset = READ_LE_UINT32(ptr);
+ offset = ptr.getUint32LE();
ptr += 4;
}
- while (ptr < mapRes->data + mapRes->size) {
- uint32 n = READ_BE_UINT32(ptr);
+ while (ptr != mapRes->cend()) {
+ uint32 n = ptr.getUint32BE();
int syncSize = 0;
ptr += 4;
@@ -388,21 +396,23 @@ int ResourceManager::readAudioMapSCI11(IntMapResourceSource *map) {
break;
if (isEarly) {
- offset = READ_LE_UINT32(ptr);
+ offset = ptr.getUint32LE();
ptr += 4;
} else {
- offset += READ_LE_UINT24(ptr);
+ offset += ptr.getUint24LE();
ptr += 3;
}
if (isEarly || (n & 0x80)) {
- syncSize = READ_LE_UINT16(ptr);
+ syncSize = ptr.getUint16LE();
ptr += 2;
// FIXME: The sync36 resource seems to be two bytes too big in KQ6CD
// (bytes taken from the RAVE resource right after it)
- if (syncSize > 0)
+ if (syncSize > 0) {
+ assert(offset + syncSize <= srcSize);
addResource(ResourceId(kResourceTypeSync36, map->_mapNumber, n & 0xffffff3f), src, offset, syncSize);
+ }
}
// Checking for this 0x40 flag breaks at least Laura Bow 2 CD 1.1
@@ -410,15 +420,17 @@ int ResourceManager::readAudioMapSCI11(IntMapResourceSource *map) {
if (g_sci->getGameId() == GID_KQ6 && (n & 0x40)) {
// This seems to define the size of raw lipsync data (at least
// in KQ6 CD Windows).
- int kq6HiresSyncSize = READ_LE_UINT16(ptr);
+ int kq6HiresSyncSize = ptr.getUint16LE();
ptr += 2;
if (kq6HiresSyncSize > 0) {
+ assert(offset + syncSize + kq6HiresSyncSize <= srcSize);
addResource(ResourceId(kResourceTypeRave, map->_mapNumber, n & 0xffffff3f), src, offset + syncSize, kq6HiresSyncSize);
syncSize += kq6HiresSyncSize;
}
}
+ assert(offset + syncSize < srcSize);
addResource(ResourceId(kResourceTypeAudio36, map->_mapNumber, n & 0xffffff3f), src, offset + syncSize);
}
}
@@ -445,7 +457,10 @@ int ResourceManager::readAudioMapSCI1(ResourceSource *map, bool unload) {
bool oldFormat = (file.readUint16LE() >> 11) == kResourceTypeAudio;
file.seek(0);
- while (1) {
+ uint32 volumeSize;
+ int lastVolumeNo = -1;
+
+ for (;;) {
uint16 n = file.readUint16LE();
uint32 offset = file.readUint32LE();
uint32 size = file.readUint32LE();
@@ -472,10 +487,17 @@ int ResourceManager::readAudioMapSCI1(ResourceSource *map, bool unload) {
ResourceSource *src = findVolume(map, volume_nr);
if (src) {
+ if (volume_nr != lastVolumeNo) {
+ volumeSize = getVolumeFile(src)->size();
+ lastVolumeNo = volume_nr;
+ }
+
if (unload)
removeAudioResource(ResourceId(kResourceTypeAudio, n));
- else
+ else {
+ assert(offset + size <= volumeSize);
addResource(ResourceId(kResourceTypeAudio, n), src, offset, size);
+ }
} else {
warning("Failed to find audio volume %i", volume_nr);
}
@@ -583,8 +605,6 @@ SoundResource::SoundResource(uint32 resourceNr, ResourceManager *resMan, SciVers
_innerResource = resource;
_soundPriority = 0xFF;
- byte *data, *data2;
- byte *dataEnd;
Channel *channel, *sampleChannel;
switch (_soundVersion) {
@@ -597,60 +617,54 @@ SoundResource::SoundResource(uint32 resourceNr, ResourceManager *resMan, SciVers
_tracks->type = 0; // Not used for SCI0
_tracks->channelCount = 1;
// Digital sample data included? -> Add an additional channel
- if (resource->data[0] == 2)
+ if (resource->getUint8At(0) == 2)
_tracks->channelCount++;
_tracks->channels = new Channel[_tracks->channelCount];
- memset(_tracks->channels, 0, sizeof(Channel) * _tracks->channelCount);
channel = &_tracks->channels[0];
channel->flags |= 2; // don't remap (SCI0 doesn't have remapping)
if (_soundVersion == SCI_VERSION_0_EARLY) {
- channel->data = resource->data + 0x11;
- channel->size = resource->size - 0x11;
+ channel->data = resource->subspan(0x11);
} else {
- channel->data = resource->data + 0x21;
- channel->size = resource->size - 0x21;
+ channel->data = resource->subspan(0x21);
}
if (_tracks->channelCount == 2) {
// Digital sample data included
_tracks->digitalChannelNr = 1;
sampleChannel = &_tracks->channels[1];
// we need to find 0xFC (channel terminator) within the data
- data = channel->data;
- dataEnd = channel->data + channel->size;
- while ((data < dataEnd) && (*data != 0xfc))
- data++;
+ SciSpan<const byte>::const_iterator it = channel->data.cbegin();
+ while (it != channel->data.cend() && *it != 0xfc)
+ it++;
// Skip any following 0xFCs as well
- while ((data < dataEnd) && (*data == 0xfc))
- data++;
+ while (it != channel->data.cend() && *it == 0xfc)
+ it++;
// Now adjust channels accordingly
- sampleChannel->data = data;
- sampleChannel->size = channel->size - (data - channel->data);
- channel->size = data - channel->data;
+ sampleChannel->data = channel->data.subspan(it - channel->data.cbegin());
+ channel->data = channel->data.subspan(0, it - channel->data.cbegin());
// Read sample header information
//Offset 14 in the header contains the frequency as a short integer. Offset 32 contains the sample length, also as a short integer.
- _tracks->digitalSampleRate = READ_LE_UINT16(sampleChannel->data + 14);
- _tracks->digitalSampleSize = READ_LE_UINT16(sampleChannel->data + 32);
+ _tracks->digitalSampleRate = sampleChannel->data.getUint16LEAt(14);
+ _tracks->digitalSampleSize = sampleChannel->data.getUint16LEAt(32);
_tracks->digitalSampleStart = 0;
_tracks->digitalSampleEnd = 0;
sampleChannel->data += 44; // Skip over header
- sampleChannel->size -= 44;
}
break;
case SCI_VERSION_1_EARLY:
case SCI_VERSION_1_LATE:
- case SCI_VERSION_2_1_EARLY:
- data = resource->data;
+ case SCI_VERSION_2_1_EARLY: {
+ SciSpan<const byte> data = *resource;
// Count # of tracks
_trackCount = 0;
while ((*data++) != 0xFF) {
_trackCount++;
while (*data != 0xFF)
data += 6;
- data++;
+ ++data;
}
_tracks = new Track[_trackCount];
- data = resource->data;
+ data = *resource;
byte channelCount;
@@ -662,7 +676,7 @@ SoundResource::SoundResource(uint32 resourceNr, ResourceManager *resMan, SciVers
_tracks[trackNr].type = *data++;
// Counting # of channels used
- data2 = data;
+ SciSpan<const byte> data2 = data;
channelCount = 0;
while (*data2 != 0xFF) {
data2 += 6;
@@ -680,38 +694,37 @@ SoundResource::SoundResource(uint32 resourceNr, ResourceManager *resMan, SciVers
channelNr = 0;
while (channelCount--) {
channel = &_tracks[trackNr].channels[channelNr];
- uint dataOffset = READ_LE_UINT16(data + 2);
+ const uint16 dataOffset = data.getUint16LEAt(2);
- if (dataOffset >= resource->size) {
+ if (dataOffset >= resource->size()) {
warning("Invalid offset inside sound resource %d: track %d, channel %d", resourceNr, trackNr, channelNr);
data += 6;
continue;
}
- channel->data = resource->data + dataOffset;
- channel->size = READ_LE_UINT16(data + 4);
+ uint16 size = data.getUint16LEAt(4);
- if (dataOffset + channel->size > resource->size) {
+ if (dataOffset + size > resource->size()) {
warning("Invalid size inside sound resource %d: track %d, channel %d", resourceNr, trackNr, channelNr);
- channel->size = resource->size - dataOffset;
+ size = resource->size() - dataOffset;
}
+ channel->data = resource->subspan(dataOffset, size);
+
channel->curPos = 0;
- channel->number = *channel->data;
+ channel->number = channel->data[0];
- channel->poly = *(channel->data + 1) & 0x0F;
- channel->prio = *(channel->data + 1) >> 4;
+ channel->poly = channel->data[1] & 0x0F;
+ channel->prio = channel->data[1] >> 4;
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);
+ _tracks[trackNr].digitalSampleRate = channel->data.getUint16LEAt(0);
+ _tracks[trackNr].digitalSampleSize = channel->data.getUint16LEAt(2);
+ _tracks[trackNr].digitalSampleStart = channel->data.getUint16LEAt(4);
+ _tracks[trackNr].digitalSampleEnd = channel->data.getUint16LEAt(6);
channel->data += 8; // Skip over header
- channel->size -= 8;
channel->flags = 0;
} else {
channel->flags = channel->number >> 4;
@@ -740,9 +753,10 @@ SoundResource::SoundResource(uint32 resourceNr, ResourceManager *resMan, SciVers
// Skip over digital track
data += 6;
}
- data++; // Skipping 0xFF that closes channels list
+ ++data; // Skipping 0xFF that closes channels list
}
break;
+ }
default:
error("SoundResource: SCI version %d is unsupported", _soundVersion);
@@ -789,13 +803,13 @@ SoundResource::Track *SoundResource::getDigitalTrack() {
// Gets the filter mask for SCI0 sound resources
int SoundResource::getChannelFilterMask(int hardwareMask, bool wantsRhythm) {
- byte *data = _innerResource->data;
+ SciSpan<const byte> data = *_innerResource;
int channelMask = 0;
if (_soundVersion > SCI_VERSION_0_LATE)
return 0;
- data++; // Skip over digital sample flag
+ ++data; // Skip over digital sample flag
for (int channelNr = 0; channelNr < 16; channelNr++) {
channelMask = channelMask >> 1;
@@ -823,7 +837,7 @@ int SoundResource::getChannelFilterMask(int hardwareMask, bool wantsRhythm) {
// by the corresponding hardware
// Skip voice count
- data++;
+ ++data;
flags = *data++;
}
@@ -853,12 +867,11 @@ int SoundResource::getChannelFilterMask(int hardwareMask, bool wantsRhythm) {
}
byte SoundResource::getInitialVoiceCount(byte channel) {
- byte *data = _innerResource->data;
-
if (_soundVersion > SCI_VERSION_0_LATE)
return 0; // TODO
- data++; // Skip over digital sample flag
+ // Skip over digital sample flag
+ SciSpan<const byte> data = _innerResource->subspan(1);
if (_soundVersion == SCI_VERSION_0_EARLY)
return data[channel] >> 4;
@@ -902,7 +915,7 @@ void AudioVolumeResourceSource::loadResource(ResourceManager *resMan, Resource *
break;
default:
mappingTable += 2;
- res->size = *mappingTable - compressedOffset;
+ res->_size = *mappingTable - compressedOffset;
}
break;
}