[Scummvm-cvs-logs] SF.net SVN: scummvm:[49260] scummvm/trunk/engines/sci

thebluegr at users.sourceforge.net thebluegr at users.sourceforge.net
Thu May 27 10:09:33 CEST 2010


Revision: 49260
          http://scummvm.svn.sourceforge.net/scummvm/?rev=49260&view=rev
Author:   thebluegr
Date:     2010-05-27 08:09:32 +0000 (Thu, 27 May 2010)

Log Message:
-----------
Split all of the audio-related functions of the resource manager in a separate file

Modified Paths:
--------------
    scummvm/trunk/engines/sci/module.mk
    scummvm/trunk/engines/sci/resource.cpp
    scummvm/trunk/engines/sci/resource.h

Added Paths:
-----------
    scummvm/trunk/engines/sci/resource_audio.cpp

Modified: scummvm/trunk/engines/sci/module.mk
===================================================================
--- scummvm/trunk/engines/sci/module.mk	2010-05-27 07:50:23 UTC (rev 49259)
+++ scummvm/trunk/engines/sci/module.mk	2010-05-27 08:09:32 UTC (rev 49260)
@@ -6,6 +6,7 @@
 	detection.o \
 	event.o \
 	resource.o \
+	resource_audio.o \
 	sci.o \
 	util.o \
 	engine/features.o \

Modified: scummvm/trunk/engines/sci/resource.cpp
===================================================================
--- scummvm/trunk/engines/sci/resource.cpp	2010-05-27 07:50:23 UTC (rev 49259)
+++ scummvm/trunk/engines/sci/resource.cpp	2010-05-27 08:09:32 UTC (rev 49260)
@@ -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 @@
 	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 @@
 
 // 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 @@
 	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 @@
 	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::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::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 @@
 
 #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

Modified: scummvm/trunk/engines/sci/resource.h
===================================================================
--- scummvm/trunk/engines/sci/resource.h	2010-05-27 07:50:23 UTC (rev 49259)
+++ scummvm/trunk/engines/sci/resource.h	2010-05-27 08:09:32 UTC (rev 49260)
@@ -26,8 +26,9 @@
 #ifndef SCI_SCICORE_RESOURCE_H
 #define SCI_SCICORE_RESOURCE_H
 
+#include "common/fs.h"
+#include "common/macresman.h"
 #include "common/str.h"
-#include "common/fs.h"
 
 #include "sci/graphics/helpers.h"		// for ViewType
 #include "sci/decompressor.h"
@@ -121,8 +122,19 @@
 
 
 class ResourceManager;
-struct ResourceSource;
 
+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;
+};
+
 class ResourceId {
 public:
 	ResourceType type;

Added: scummvm/trunk/engines/sci/resource_audio.cpp
===================================================================
--- scummvm/trunk/engines/sci/resource_audio.cpp	                        (rev 0)
+++ scummvm/trunk/engines/sci/resource_audio.cpp	2010-05-27 08:09:32 UTC (rev 49260)
@@ -0,0 +1,701 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+// Resource library
+
+#include "common/file.h"
+
+#include "sci/resource.h"
+#include "sci/util.h"
+
+namespace Sci {
+
+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::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;
+}
+
+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::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());
+		}
+	}
+}
+
+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);
+}
+
+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


Property changes on: scummvm/trunk/engines/sci/resource_audio.cpp
___________________________________________________________________
Added: svn:mime-type
   + text/plain
Added: svn:keywords
   + Date Rev Author URL Id
Added: svn:eol-style
   + native


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list