diff options
Diffstat (limited to 'engines/sci/resource.cpp')
-rw-r--r-- | engines/sci/resource.cpp | 679 |
1 files changed, 0 insertions, 679 deletions
diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 0b985ea67c..89b7a5b7e2 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -26,7 +26,6 @@ // Resource library #include "common/file.h" -#include "common/macresman.h" #include "sci/resource.h" #include "sci/util.h" @@ -45,18 +44,6 @@ struct resource_index_t { uint16 wSize; }; -struct ResourceSource { - ResSourceType source_type; - bool scanned; - Common::String location_name; // FIXME: Replace by FSNode ? - const Common::FSNode *resourceFile; - int volume_number; - ResourceSource *associated_map; - uint32 audioCompressionType; - int32 *audioCompressionOffsetMapping; - Common::MacResManager macResMan; -}; - ////////////////////////////////////////////////////////////////////// static SciVersion s_sciVersion = SCI_VERSION_NONE; // FIXME: Move this inside a suitable class, e.g. SciEngine @@ -270,36 +257,6 @@ ResourceSource *ResourceManager::getVolume(ResourceSource *map, int volume_nr) { // Resource manager constructors and operations -void ResourceManager::checkIfAudioVolumeIsCompressed(ResourceSource *source) { - Common::File *file = getVolumeFile(source->location_name.c_str()); - if (!file) { - warning("Failed to open %s", source->location_name.c_str()); - return; - } - file->seek(0, SEEK_SET); - uint32 compressionType = file->readUint32BE(); - switch (compressionType) { - case MKID_BE('MP3 '): - case MKID_BE('OGG '): - case MKID_BE('FLAC'): - // Detected a compressed audio volume - source->audioCompressionType = compressionType; - // Now read the whole offset mapping table for later usage - int32 recordCount = file->readUint32LE(); - if (!recordCount) - error("compressed audio volume doesn't contain any entries!"); - int32 *offsetMapping = new int32[(recordCount + 1) * 2]; - source->audioCompressionOffsetMapping = offsetMapping; - for (int recordNo = 0; recordNo < recordCount; recordNo++) { - *offsetMapping++ = file->readUint32LE(); - *offsetMapping++ = file->readUint32LE(); - } - // Put ending zero - *offsetMapping++ = 0; - *offsetMapping++ = file->size(); - } -} - bool ResourceManager::loadPatch(Resource *res, Common::File &file) { // We assume that the resource type matches res->type // We also assume that the current file position is right at the actual data (behind resourceid/headersize byte) @@ -341,70 +298,6 @@ bool ResourceManager::loadFromPatchFile(Resource *res) { return loadPatch(res, file); } -bool ResourceManager::loadFromWaveFile(Resource *res, Common::File &file) { - res->data = new byte[res->size]; - - uint32 really_read = file.read(res->data, res->size); - if (really_read != res->size) - error("Read %d bytes from %s but expected %d", really_read, res->_id.toString().c_str(), res->size); - - res->_status = kResStatusAllocated; - return true; -} - -bool ResourceManager::loadFromAudioVolumeSCI11(Resource *res, Common::File &file) { - // Check for WAVE files here - uint32 riffTag = file.readUint32BE(); - if (riffTag == MKID_BE('RIFF')) { - res->_headerSize = 0; - res->size = file.readUint32LE(); - file.seek(-8, SEEK_CUR); - return loadFromWaveFile(res, file); - } - file.seek(-4, SEEK_CUR); - - ResourceType type = (ResourceType)(file.readByte() & 0x7f); - if (((res->_id.type == kResourceTypeAudio || res->_id.type == kResourceTypeAudio36) && (type != kResourceTypeAudio)) - || ((res->_id.type == kResourceTypeSync || res->_id.type == kResourceTypeSync36) && (type != kResourceTypeSync))) { - warning("Resource type mismatch loading %s from %s", res->_id.toString().c_str(), file.getName()); - res->unalloc(); - return false; - } - - res->_headerSize = file.readByte(); - - if (type == kResourceTypeAudio) { - if (res->_headerSize != 11 && res->_headerSize != 12) { - warning("Unsupported audio header"); - res->unalloc(); - return false; - } - - // Load sample size - file.seek(7, SEEK_CUR); - res->size = file.readUint32LE(); - // Adjust offset to point at the header data again - file.seek(-11, SEEK_CUR); - } - - return loadPatch(res, file); -} - -bool ResourceManager::loadFromAudioVolumeSCI1(Resource *res, Common::File &file) { - res->data = new byte[res->size]; - - if (res->data == NULL) { - error("Can't allocate %d bytes needed for loading %s", res->size, res->_id.toString().c_str()); - } - - unsigned int really_read = file.read(res->data, res->size); - if (really_read != res->size) - warning("Read %d bytes from %s but expected %d", really_read, res->_id.toString().c_str(), res->size); - - res->_status = kResStatusAllocated; - return true; -} - Common::File *ResourceManager::getVolumeFile(const char *filename) { Common::List<Common::File *>::iterator it = _volumeFiles.begin(); Common::File *file; @@ -695,36 +588,6 @@ int ResourceManager::addInternalSources() { return 1; } -void ResourceManager::addNewGMPatch(const Common::String &gameId) { - Common::String gmPatchFile; - - if (gameId == "ecoquest") - gmPatchFile = "ECO1GM.PAT"; - else if (gameId == "hoyle3") - gmPatchFile = "HOY3GM.PAT"; - else if (gameId == "hoyle3") - gmPatchFile = "HOY3GM.PAT"; - else if (gameId == "lsl1sci") - gmPatchFile = "LL1_GM.PAT"; - else if (gameId == "lsl5") - gmPatchFile = "LL5_GM.PAT"; - else if (gameId == "longbow") - gmPatchFile = "ROBNGM.PAT"; - else if (gameId == "sq1sci") - gmPatchFile = "SQ1_GM.PAT"; - else if (gameId == "sq4") - gmPatchFile = "SQ4_GM.PAT"; - else if (gameId == "fairytales") - gmPatchFile = "TALEGM.PAT"; - - if (!gmPatchFile.empty() && Common::File::exists(gmPatchFile)) { - ResourceSource *psrcPatch = new ResourceSource; - psrcPatch->source_type = kSourcePatch; - psrcPatch->location_name = gmPatchFile; - processPatch(psrcPatch, kResourceTypePatch, 4); - } -} - void ResourceManager::scanNewSources() { for (Common::List<ResourceSource *>::iterator it = _sources.begin(); it != _sources.end(); ++it) { ResourceSource *source = *it; @@ -1295,49 +1158,6 @@ void ResourceManager::readResourcePatches(ResourceSource *source) { } } -void ResourceManager::readWaveAudioPatches() { - // Here we do check for SCI1.1+ so we can patch wav files in as audio resources - Common::ArchiveMemberList files; - SearchMan.listMatchingMembers(files, "*.wav"); - - for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); ++x) { - Common::String name = (*x)->getName(); - - if (isdigit(name[0])) { - int number = atoi(name.c_str()); - ResourceSource *psrcPatch = new ResourceSource; - psrcPatch->source_type = kSourceWave; - psrcPatch->location_name = name; - psrcPatch->volume_number = 0; - psrcPatch->audioCompressionType = 0; - - ResourceId resId = ResourceId(kResourceTypeAudio, number); - - Resource *newrsc = NULL; - - // Prepare destination, if neccessary - if (_resMap.contains(resId) == false) { - newrsc = new Resource; - _resMap.setVal(resId, newrsc); - } else - newrsc = _resMap.getVal(resId); - - // Get the size of the file - Common::SeekableReadStream *stream = (*x)->createReadStream(); - uint32 fileSize = stream->size(); - delete stream; - - // Overwrite everything, because we're patching - newrsc->_id = resId; - newrsc->_status = kResStatusNoMalloc; - newrsc->_source = psrcPatch; - newrsc->size = fileSize; - newrsc->_headerSize = 0; - debugC(1, kDebugLevelResMan, "Patching %s - OK", psrcPatch->location_name.c_str()); - } - } -} - int ResourceManager::readResourceMapSCI0(ResourceSource *map) { Common::File file; Resource *res; @@ -1558,261 +1378,6 @@ void ResourceManager::addResource(ResourceId resId, ResourceSource *src, uint32 } } -void ResourceManager::removeAudioResource(ResourceId resId) { - // Remove resource, unless it was loaded from a patch - if (_resMap.contains(resId)) { - Resource *res = _resMap.getVal(resId); - - if (res->_source->source_type == kSourceAudioVolume) { - if (res->_status == kResStatusLocked) { - warning("Failed to remove resource %s (still in use)", resId.toString().c_str()); - } else { - if (res->_status == kResStatusEnqueued) - removeFromLRU(res); - - _resMap.erase(resId); - delete res; - } - } - } -} - -// Early SCI1.1 65535.MAP structure (uses RESOURCE.AUD): -// ========= -// 6-byte entries: -// w nEntry -// dw offset - -// Late SCI1.1 65535.MAP structure (uses RESOURCE.SFX): -// ========= -// 5-byte entries: -// w nEntry -// tb offset (cumulative) - -// Early SCI1.1 MAP structure: -// =============== -// 10-byte entries: -// b noun -// b verb -// b cond -// b seq -// dw offset -// w syncSize + syncAscSize - -// Late SCI1.1 MAP structure: -// =============== -// Header: -// dw baseOffset -// Followed by 7 or 11-byte entries: -// b noun -// b verb -// b cond -// b seq -// tb cOffset (cumulative offset) -// w syncSize (iff seq has bit 7 set) -// w syncAscSize (iff seq has bit 6 set) - -int ResourceManager::readAudioMapSCI11(ResourceSource *map) { - bool isEarly = true; - uint32 offset = 0; - Resource *mapRes = findResource(ResourceId(kResourceTypeMap, map->volume_number), false); - - if (!mapRes) { - warning("Failed to open %i.MAP", map->volume_number); - return SCI_ERROR_RESMAP_NOT_FOUND; - } - - ResourceSource *src = getVolume(map, 0); - - if (!src) - return SCI_ERROR_NO_RESOURCE_FILES_FOUND; - - byte *ptr = mapRes->data; - - if (map->volume_number == 65535) { - // Heuristic to detect late SCI1.1 map format - if ((mapRes->size >= 6) && (ptr[mapRes->size - 6] != 0xff)) - isEarly = false; - - while (ptr < mapRes->data + mapRes->size) { - uint16 n = READ_LE_UINT16(ptr); - ptr += 2; - - if (n == 0xffff) - break; - - if (isEarly) { - offset = READ_LE_UINT32(ptr); - ptr += 4; - } else { - offset += READ_LE_UINT24(ptr); - ptr += 3; - } - - addResource(ResourceId(kResourceTypeAudio, n), src, offset); - } - } else { - // Heuristic to detect late SCI1.1 map format - if ((mapRes->size >= 11) && (ptr[mapRes->size - 11] == 0xff)) - isEarly = false; - - if (!isEarly) { - offset = READ_LE_UINT32(ptr); - ptr += 4; - } - - while (ptr < mapRes->data + mapRes->size) { - uint32 n = READ_BE_UINT32(ptr); - int syncSize = 0; - ptr += 4; - - if (n == 0xffffffff) - break; - - if (isEarly) { - offset = READ_LE_UINT32(ptr); - ptr += 4; - } else { - offset += READ_LE_UINT24(ptr); - ptr += 3; - } - - if (isEarly || (n & 0x80)) { - syncSize = READ_LE_UINT16(ptr); - ptr += 2; - - if (syncSize > 0) - addResource(ResourceId(kResourceTypeSync36, map->volume_number, n & 0xffffff3f), src, offset, syncSize); - } - - if (n & 0x40) { - syncSize += READ_LE_UINT16(ptr); - ptr += 2; - } - - addResource(ResourceId(kResourceTypeAudio36, map->volume_number, n & 0xffffff3f), src, offset + syncSize); - } - } - - return 0; -} - -// AUDIOnnn.MAP contains 10-byte entries: -// Early format: -// w 5 bits resource type and 11 bits resource number -// dw 7 bits volume number and 25 bits offset -// dw size -// Later format: -// w nEntry -// dw offset+volume (as in resource.map) -// dw size -// ending with 10 0xFFs -int ResourceManager::readAudioMapSCI1(ResourceSource *map, bool unload) { - Common::File file; - - if (!file.open(map->location_name)) - return SCI_ERROR_RESMAP_NOT_FOUND; - - bool oldFormat = (file.readUint16LE() >> 11) == kResourceTypeAudio; - file.seek(0); - - while (1) { - uint16 n = file.readUint16LE(); - uint32 offset = file.readUint32LE(); - uint32 size = file.readUint32LE(); - - if (file.eos() || file.err()) { - warning("Error while reading %s", map->location_name.c_str()); - return SCI_ERROR_RESMAP_NOT_FOUND; - } - - if (n == 0xffff) - break; - - byte volume_nr; - - if (oldFormat) { - n &= 0x07ff; // Mask out resource type - volume_nr = offset >> 25; // most significant 7 bits - offset &= 0x01ffffff; // least significant 25 bits - } else { - volume_nr = offset >> 28; // most significant 4 bits - offset &= 0x0fffffff; // least significant 28 bits - } - - ResourceSource *src = getVolume(map, volume_nr); - - if (src) { - if (unload) - removeAudioResource(ResourceId(kResourceTypeAudio, n)); - else - addResource(ResourceId(kResourceTypeAudio, n), src, offset, size); - } else { - warning("Failed to find audio volume %i", volume_nr); - } - } - - return 0; -} - -void ResourceManager::setAudioLanguage(int language) { - if (_audioMapSCI1) { - if (_audioMapSCI1->volume_number == language) { - // This language is already loaded - return; - } - - // We already have a map loaded, so we unload it first - readAudioMapSCI1(_audioMapSCI1, true); - - // Remove all volumes that use this map from the source list - Common::List<ResourceSource *>::iterator it = _sources.begin(); - while (it != _sources.end()) { - ResourceSource *src = *it; - if (src->associated_map == _audioMapSCI1) { - it = _sources.erase(it); - delete src; - } else { - ++it; - } - } - - // Remove the map itself from the source list - _sources.remove(_audioMapSCI1); - delete _audioMapSCI1; - - _audioMapSCI1 = NULL; - } - - char filename[9]; - snprintf(filename, 9, "AUDIO%03d", language); - - Common::String fullname = Common::String(filename) + ".MAP"; - if (!Common::File::exists(fullname)) { - warning("No audio map found for language %i", language); - return; - } - - _audioMapSCI1 = addSource(NULL, kSourceExtAudioMap, fullname.c_str(), language); - - // Search for audio volumes for this language and add them to the source list - Common::ArchiveMemberList files; - SearchMan.listMatchingMembers(files, Common::String(filename) + ".0??"); - for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); ++x) { - const Common::String name = (*x)->getName(); - const char *dot = strrchr(name.c_str(), '.'); - int number = atoi(dot + 1); - - addSource(_audioMapSCI1, kSourceAudioVolume, name.c_str(), number); - } - - scanNewSources(); -} - -int ResourceManager::getAudioLanguage() const { - return (_audioMapSCI1 ? _audioMapSCI1->volume_number : 0); -} - int ResourceManager::readResourceInfo(Resource *res, Common::SeekableReadStream *file, uint32&szPacked, ResourceCompression &compression) { // SCI0 volume format: {wResId wPacked+4 wUnpacked wCompression} = 8 bytes @@ -2367,248 +1932,4 @@ Common::String ResourceManager::findSierraGameId() { #undef READ_UINT16 -SoundResource::SoundResource(uint32 resNumber, ResourceManager *resMan, SciVersion soundVersion) : _resMan(resMan), _soundVersion(soundVersion) { - Resource *resource = _resMan->findResource(ResourceId(kResourceTypeSound, resNumber), true); - int trackNr, channelNr; - if (!resource) - return; - - _innerResource = resource; - - byte *data, *data2; - byte *dataEnd; - Channel *channel, *sampleChannel; - - switch (_soundVersion) { - case SCI_VERSION_0_EARLY: - case SCI_VERSION_0_LATE: - // SCI0 only has a header of 0x11/0x21 byte length and the actual midi track follows afterwards - _trackCount = 1; - _tracks = new Track[_trackCount]; - _tracks->digitalChannelNr = -1; - _tracks->type = 0; // Not used for SCI0 - _tracks->channelCount = 1; - // Digital sample data included? -> Add an additional channel - if (resource->data[0] == 2) - _tracks->channelCount++; - _tracks->channels = new Channel[_tracks->channelCount]; - memset(_tracks->channels, 0, sizeof(Channel) * _tracks->channelCount); - channel = &_tracks->channels[0]; - if (_soundVersion == SCI_VERSION_0_EARLY) { - channel->data = resource->data + 0x11; - channel->size = resource->size - 0x11; - } else { - channel->data = resource->data + 0x21; - channel->size = resource->size - 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++; - // Skip any following 0xFCs as well - while ((data < dataEnd) && (*data == 0xfc)) - data++; - // Now adjust channels accordingly - sampleChannel->data = data; - sampleChannel->size = channel->size - (data - channel->data); - channel->size = data - channel->data; - // 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->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: - data = resource->data; - // Count # of tracks - _trackCount = 0; - while ((*data++) != 0xFF) { - _trackCount++; - while (*data != 0xFF) - data += 6; - data++; - } - _tracks = new Track[_trackCount]; - data = resource->data; - 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 - // 0xFF:BYTE as terminator to end that track and begin with another track type - // Track type 0xFF is the marker signifying the end of the tracks - - _tracks[trackNr].type = *data++; - // Counting # of channels used - data2 = data; - _tracks[trackNr].channelCount = 0; - while (*data2 != 0xFF) { - data2 += 6; - _tracks[trackNr].channelCount++; - } - _tracks[trackNr].channels = new Channel[_tracks[trackNr].channelCount]; - _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++) { - 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; - } - data += 6; - } - } else { - // Skip over digital track - data += 6; - } - data++; // Skipping 0xFF that closes channels list - } - break; - - default: - error("SoundResource: SCI version %d is unsupported", _soundVersion); - } -} - -SoundResource::~SoundResource() { - for (int trackNr = 0; trackNr < _trackCount; trackNr++) - delete[] _tracks[trackNr].channels; - delete[] _tracks; - - _resMan->unlockResource(_innerResource); -} - -#if 0 -SoundResource::Track* SoundResource::getTrackByNumber(uint16 number) { - if (_soundVersion <= SCI_VERSION_0_LATE) - return &_tracks[0]; - - if (/*number >= 0 &&*/number < _trackCount) - return &_tracks[number]; - return NULL; -} -#endif - -SoundResource::Track *SoundResource::getTrackByType(byte type) { - if (_soundVersion <= SCI_VERSION_0_LATE) - return &_tracks[0]; - - for (int trackNr = 0; trackNr < _trackCount; trackNr++) { - if (_tracks[trackNr].type == type) - return &_tracks[trackNr]; - } - return NULL; -} - -SoundResource::Track *SoundResource::getDigitalTrack() { - for (int trackNr = 0; trackNr < _trackCount; trackNr++) { - if (_tracks[trackNr].digitalChannelNr != -1) - return &_tracks[trackNr]; - } - return NULL; -} - -// Gets the filter mask for SCI0 sound resources -int SoundResource::getChannelFilterMask(int hardwareMask, bool wantsRhythm) { - byte *data = _innerResource->data; - int channelMask = 0; - - if (_soundVersion > SCI_VERSION_0_LATE) - return 0; - - data++; // Skip over digital sample flag - - for (int channelNr = 0; channelNr < 16; channelNr++) { - channelMask = channelMask >> 1; - - byte flags; - - if (_soundVersion == SCI_VERSION_0_EARLY) { - // Each channel is specified by a single byte - // Upper 4 bits of the byte is a voices count - // Lower 4 bits -> bit 0 set: use for AdLib - // bit 1 set: use for PCjr - // bit 2 set: use for PC speaker - // bit 3 set and bit 0 clear: control channel (15) - // bit 3 set and bit 0 set: rhythm channel (9) - // Note: control channel is dynamically assigned inside the drivers, - // but seems to be fixed at 15 in the song data. - flags = *data++; - - // Get device bits - flags &= 0x7; - } else { - // Each channel is specified by 2 bytes - // 1st byte is voices count - // 2nd byte is play mask, which specifies if the channel is supposed to be played - // by the corresponding hardware - - // Skip voice count - data++; - - flags = *data++; - } - - bool play; - switch (channelNr) { - case 15: - // Always play control channel - play = true; - break; - case 9: - // Play rhythm channel when requested - play = wantsRhythm; - break; - default: - // Otherwise check for flag - play = flags & hardwareMask; - } - - if (play) { - // This Channel is supposed to be played by the hardware - channelMask |= 0x8000; - } - } - - return channelMask; -} - -byte SoundResource::getInitialVoiceCount(byte channel) { - byte *data = _innerResource->data; - - if (_soundVersion > SCI_VERSION_0_LATE) - return 0; // TODO - - data++; // Skip over digital sample flag - - if (_soundVersion == SCI_VERSION_0_EARLY) - return data[channel] >> 4; - else - return data[channel * 2]; -} - } // End of namespace Sci |