diff options
| -rw-r--r-- | engines/saga/actor.cpp | 2 | ||||
| -rw-r--r-- | engines/saga/font.cpp | 2 | ||||
| -rw-r--r-- | engines/saga/music.cpp | 4 | ||||
| -rw-r--r-- | engines/saga/resource.cpp | 458 | ||||
| -rw-r--r-- | engines/saga/resource.h | 201 | ||||
| -rw-r--r-- | engines/saga/resource_hrs.cpp | 50 | ||||
| -rw-r--r-- | engines/saga/resource_rsc.cpp | 166 | ||||
| -rw-r--r-- | engines/saga/saga.h | 2 | ||||
| -rw-r--r-- | engines/saga/scene.cpp | 8 | ||||
| -rw-r--r-- | engines/saga/script.cpp | 6 | ||||
| -rw-r--r-- | engines/saga/sndres.cpp | 47 | ||||
| -rw-r--r-- | engines/saga/sprite.cpp | 4 | 
12 files changed, 440 insertions, 510 deletions
| diff --git a/engines/saga/actor.cpp b/engines/saga/actor.cpp index 0ffbe66314..c3f5fec83a 100644 --- a/engines/saga/actor.cpp +++ b/engines/saga/actor.cpp @@ -352,7 +352,7 @@ void Actor::loadFrameList(int frameListResourceId, ActorFrameSequence *&framesPo  		memoryError("Actor::loadFrameList");  	} -	MemoryReadStreamEndian readS(resourcePointer, resourceLength, _actorContext->isBigEndian); +	MemoryReadStreamEndian readS(resourcePointer, resourceLength, _actorContext->isBigEndian());  	for (int i = 0; i < framesCount; i++) {  		debug(9, "frameType %d", i); diff --git a/engines/saga/font.cpp b/engines/saga/font.cpp index d414b903e6..3ffe27f783 100644 --- a/engines/saga/font.cpp +++ b/engines/saga/font.cpp @@ -90,7 +90,7 @@ void Font::loadFont(uint32 fontResourceId) {  		error("Font::loadFont() Invalid font length (%i < %i)", (int)fontResourceLength, FONT_DESCSIZE);  	} -	MemoryReadStreamEndian readS(fontResourcePointer, fontResourceLength, fontContext->isBigEndian); +	MemoryReadStreamEndian readS(fontResourcePointer, fontResourceLength, fontContext->isBigEndian());  	// Create new font structure  	font = (FontData *)malloc(sizeof(*font)); diff --git a/engines/saga/music.cpp b/engines/saga/music.cpp index 31517f403e..aeca848719 100644 --- a/engines/saga/music.cpp +++ b/engines/saga/music.cpp @@ -296,12 +296,12 @@ void Music::play(uint32 resourceId, MusicFlags flags) {  				// Digital music  				ResourceData *resData = _digitalMusicContext->getResourceData(resourceId - 9);  				Common::File *musicFile = _digitalMusicContext->getFile(resData); -				int offs = (_digitalMusicContext->isCompressed) ? 9 : 0; +				int offs = (_digitalMusicContext->isCompressed()) ? 9 : 0;  				Common::SeekableSubReadStream *musicStream = new Common::SeekableSubReadStream(musicFile,   							(uint32)resData->offset + offs, (uint32)resData->offset + resData->size - offs); -				if (!_digitalMusicContext->isCompressed) { +				if (!_digitalMusicContext->isCompressed()) {  					byte musicFlags = Audio::Mixer::FLAG_AUTOFREE | Audio::Mixer::FLAG_STEREO |   										Audio::Mixer::FLAG_16BITS | Audio::Mixer::FLAG_LITTLE_ENDIAN;  					if (flags == MUSIC_LOOP) diff --git a/engines/saga/resource.cpp b/engines/saga/resource.cpp index 3bdd8e00db..bdff209704 100644 --- a/engines/saga/resource.cpp +++ b/engines/saga/resource.cpp @@ -39,21 +39,13 @@  namespace Saga { -Resource::Resource(SagaEngine *vm): _vm(vm) { -	_contexts = NULL; -	_contextsCount = 0; -} - -Resource::~Resource() { -	clearContexts(); -} - -bool Resource::loadResContext_v1(ResourceContext *context, uint32 contextOffset, uint32 contextSize) { +bool ResourceContext::loadResV1(uint32 contextOffset, uint32 contextSize) {  	size_t i;  	bool result;  	byte tableInfo[RSC_TABLEINFO_SIZE];  	byte *tableBuffer;  	size_t tableSize; +	uint32 count;  	uint32 resourceTableOffset;  	ResourceData *resourceData; @@ -61,41 +53,41 @@ bool Resource::loadResContext_v1(ResourceContext *context, uint32 contextOffset,  		return false;  	} -	context->file->seek(contextOffset + contextSize - RSC_TABLEINFO_SIZE); +	_file.seek(contextOffset + contextSize - RSC_TABLEINFO_SIZE); -	if (context->file->read(tableInfo, RSC_TABLEINFO_SIZE) != RSC_TABLEINFO_SIZE) { +	if (_file.read(tableInfo, RSC_TABLEINFO_SIZE) != RSC_TABLEINFO_SIZE) {  		return false;  	} -	MemoryReadStreamEndian readS(tableInfo, RSC_TABLEINFO_SIZE, context->isBigEndian); +	MemoryReadStreamEndian readS(tableInfo, RSC_TABLEINFO_SIZE, _isBigEndian);  	resourceTableOffset = readS.readUint32(); -	context->count = readS.readUint32(); +	count = readS.readUint32();  	// Check for sane table offset -	if (resourceTableOffset != contextSize - RSC_TABLEINFO_SIZE - RSC_TABLEENTRY_SIZE * context->count) { +	if (resourceTableOffset != contextSize - RSC_TABLEINFO_SIZE - RSC_TABLEENTRY_SIZE * count) {  		return false;  	}  	// Load resource table -	tableSize = RSC_TABLEENTRY_SIZE * context->count; +	tableSize = RSC_TABLEENTRY_SIZE * count;  	tableBuffer = (byte *)malloc(tableSize); -	context->file->seek(resourceTableOffset + contextOffset, SEEK_SET); +	_file.seek(resourceTableOffset + contextOffset, SEEK_SET); -	result = (context->file->read(tableBuffer, tableSize) == tableSize); +	result = (_file.read(tableBuffer, tableSize) == tableSize);  	if (result) { -		context->table = (ResourceData *)calloc(context->count, sizeof(*context->table)); +		_table.resize(count); -		MemoryReadStreamEndian readS1(tableBuffer, tableSize, context->isBigEndian); +		MemoryReadStreamEndian readS1(tableBuffer, tableSize, _isBigEndian); -		for (i = 0; i < context->count; i++) { -			resourceData = &context->table[i]; +		for (i = 0; i < count; i++) { +			resourceData = &_table[i];  			resourceData->offset = contextOffset + readS1.readUint32();  			resourceData->size = readS1.readUint32();  			//sanity check -			if ((resourceData->offset > (uint)context->fileSize) || (resourceData->size > contextSize)) { +			if ((resourceData->offset > (uint)_fileSize) || (resourceData->size > contextSize)) {  				result = false;  				break;  			} @@ -106,7 +98,7 @@ bool Resource::loadResContext_v1(ResourceContext *context, uint32 contextOffset,  	return result;  } -bool Resource::loadContext(ResourceContext *context) { +bool ResourceContext::load(SagaEngine *vm, Resource *resource) {  	size_t i;  	const GamePatchDescription *patchDescription;  	ResourceData *resourceData; @@ -119,45 +111,49 @@ bool Resource::loadContext(ResourceContext *context) {  	size_t tableSize;  	bool isMacBinary; -	if (!context->file->open(context->fileName)) { +	if (_fileName == NULL) { // IHNM special case +		return true; +	} + +	if (!_file.open(_fileName)) {  		return false;  	} -	context->fileSize = context->file->size(); -	context->isBigEndian = _vm->isBigEndian(); +	_fileSize = _file.size(); +	_isBigEndian = vm->isBigEndian(); -	if (context->fileType & GAME_SWAPENDIAN) -		context->isBigEndian = !context->isBigEndian; +	if (_fileType & GAME_SWAPENDIAN) +		_isBigEndian = !_isBigEndian; -	isMacBinary = (context->fileType & GAME_MACBINARY) > 0; -	context->fileType &= ~GAME_MACBINARY; +	isMacBinary = (_fileType & GAME_MACBINARY) > 0; +	_fileType &= ~GAME_MACBINARY;  	if (!isMacBinary) { -		if (!loadResContext(context, 0, context->fileSize)) { +		if (!loadRes(0, _fileSize)) {  			return false;  		}  	} else { -		if (!loadMacContext(context)) { +		if (!loadMac()) {  			return false;  		}  	}  	//process internal patch files -	if (context->fileType & GAME_PATCHFILE) { -		subjectResourceType = ~GAME_PATCHFILE & context->fileType; -		subjectContext = getContext((GameFileTypes)subjectResourceType); +	if (_fileType & GAME_PATCHFILE) { +		subjectResourceType = ~GAME_PATCHFILE & _fileType; +		subjectContext = resource->getContext((GameFileTypes)subjectResourceType);  		if (subjectContext == NULL) { -			error("Resource::loadContext() Subject context not found"); +			error("ResourceContext::load() Subject context not found");  		} -		loadResource(context, context->count - 1, tableBuffer, tableSize); +		resource->loadResource(this, _table.size() - 1, tableBuffer, tableSize); -		MemoryReadStreamEndian readS2(tableBuffer, tableSize, context->isBigEndian); +		MemoryReadStreamEndian readS2(tableBuffer, tableSize, _isBigEndian);  		for (i = 0; i < tableSize / 8; i++) {  			subjectResourceId = readS2.readUint32();  			patchResourceId = readS2.readUint32();  			subjectResourceData = subjectContext->getResourceData(subjectResourceId); -			resourceData = context->getResourceData(patchResourceId); -			subjectResourceData->patchData = new PatchData(context->file); +			resourceData = getResourceData(patchResourceId); +			subjectResourceData->patchData = new PatchData(&_file);  			subjectResourceData->offset = resourceData->offset;  			subjectResourceData->size = resourceData->size;  		} @@ -165,10 +161,10 @@ bool Resource::loadContext(ResourceContext *context) {  	}  	//process external patch files -	for (patchDescription = _vm->getPatchDescriptions(); patchDescription && patchDescription->fileName; ++patchDescription) { -		if ((patchDescription->fileType & context->fileType) != 0) { -			if (patchDescription->resourceId < context->count) { -				resourceData = &context->table[patchDescription->resourceId]; +	for (patchDescription = vm->getPatchDescriptions(); patchDescription && patchDescription->fileName; ++patchDescription) { +		if ((patchDescription->fileType & _fileType) != 0) { +			if (patchDescription->resourceId < _table.size()) { +				resourceData = &_table[patchDescription->resourceId];  				resourceData->patchData = new PatchData(patchDescription);  				if (resourceData->patchData->_patchFile->open(patchDescription->fileName)) {  					resourceData->offset = 0; @@ -176,7 +172,7 @@ bool Resource::loadContext(ResourceContext *context) {  					// ITE uses several patch files which are loaded and then not needed  					// anymore (as they're in memory), so close them here. IHNM uses only  					// 1 patch file, which is reused, so don't close it -					if (_vm->getGameId() == GID_ITE) +					if (vm->getGameId() == GID_ITE)  						resourceData->patchData->_patchFile->close();  				} else {  					delete resourceData->patchData; @@ -189,221 +185,140 @@ bool Resource::loadContext(ResourceContext *context) {  	// Close the file if it's part of a series of files  	// This prevents having all voice files open in IHNM for no reason, as each chapter uses  	// a different voice file -	if (context->serial > 0) -		context->file->close(); +	if (_serial > 0) +		_file.close();  	return true;  } -bool Resource::createContexts() { -	int i; +Resource::Resource(SagaEngine *vm): _vm(vm) { +} + +Resource::~Resource() { +	clearContexts(); +} + +void Resource::addContext(const char *fileName, uint16 fileType, bool isCompressed, int serial) {  	ResourceContext *context; -	int soundFileIndex = 0; -	int voicesFileIndex = 0; -	bool digitalMusic = false; +	context = createContext(); +	context->_fileName = fileName; +	context->_fileType = fileType; +	context->_isCompressed = isCompressed; +	context->_serial = serial; +	_contexts.push_back(context); +} + +bool Resource::createContexts() {  	bool soundFileInArray = false; -	bool multipleVoices = false; -	bool censoredVersion = false; -	bool compressedSounds = false; -	bool compressedMusic = false; -	uint16 voiceFileType = GAME_VOICEFILE; -	bool fileFound = false; -	int maxFile = 0;  	_vm->_voiceFilesExist = true;  	struct SoundFileInfo { +		int gameId;  		char fileName[40];  		bool isCompressed; +		uint16 voiceFileAddType;  	}; -	SoundFileInfo *curSoundfiles = 0;  	// If the Wyrmkeep credits file is found, set the Wyrmkeep version flag to true  	if (Common::File::exists("graphics/credit3n.dlt")) {  		_vm->_gf_wyrmkeep = true;  	} -	_contextsCount = 0; -	for (i = 0; _vm->getFilesDescriptions()[i].fileName; i++) { -		_contextsCount++; -		if (_vm->getFilesDescriptions()[i].fileType == GAME_SOUNDFILE) +	for (const ADGameFileDescription *gameFileDescription = _vm->getFilesDescriptions(); +		gameFileDescription->fileName; gameFileDescription++) { +		addContext(gameFileDescription->fileName, gameFileDescription->fileType); +		if (gameFileDescription->fileType == GAME_SOUNDFILE) {  			soundFileInArray = true; +		}  	}  	//// Detect and add SFX files //////////////////////////////////////////////// -	SoundFileInfo sfxFilesITE[] = { -		{	"sounds.rsc",		false	}, -		{	"sounds.cmp",		true	}, -		{	"soundsd.rsc",		false	}, -		{	"soundsd.cmp",		true	} -	}; - +	SoundFileInfo sfxFiles[] = { +		{	GID_ITE,	"sounds.rsc",		false	}, +		{	GID_ITE,	"sounds.cmp",		true	}, +		{	GID_ITE,	"soundsd.rsc",		false	}, +		{	GID_ITE,	"soundsd.cmp",		true	},  #ifdef ENABLE_IHNM -	SoundFileInfo sfxFilesIHNM[] = { -		{	"sfx.res",			false	}, -		{	"sfx.cmp",			true	} -	}; +		{	GID_IHNM,	"sfx.res",			false	}, +		{	GID_IHNM,	"sfx.cmp",			true	},  #endif -  #ifdef ENABLE_SAGA2 -	SoundFileInfo sfxFilesFTA2[] = { -		{	"ftasound.hrs",		false	} -	}; - -	SoundFileInfo sfxFilesDino[] = { -		{	"dinosnd.hrs",		false	}, -	}; +		{	GID_FTA2,	"ftasound.hrs",		false	}, +		{	GID_DINO,	"dinosnd.hrs",		false	},  #endif +		{	-1,			NULL,				false	} +	}; +	_soundFileName[0] = 0;  	if (!soundFileInArray) { -		// If the sound file is not specified in the detector table, add it here -		fileFound = false; - -		switch (_vm->getGameId()) { -			case GID_ITE: -				curSoundfiles = sfxFilesITE; -				maxFile = 4; -				break; -#ifdef ENABLE_IHNM -			case GID_IHNM: -				curSoundfiles = sfxFilesIHNM; -				maxFile = 2; -				break; -#endif -#ifdef ENABLE_SAGA2 -			case GID_DINO: -				curSoundfiles = sfxFilesDino; -				maxFile = 1; -				break; -			case GID_FTA2: -				curSoundfiles = sfxFilesFTA2; -				maxFile = 1; -				break; -#endif -		} - -		for (i = 0; i < maxFile; i++) { -			if (Common::File::exists(curSoundfiles[i].fileName)) { -				_contextsCount++; -				soundFileIndex = _contextsCount - 1; -				strcpy(_soundFileName, curSoundfiles[i].fileName); -				compressedSounds = curSoundfiles[i].isCompressed; -				fileFound = true; -				break; -			} -		} - -		if (!fileFound) { -			// No sound file found, don't add any file to the array -			soundFileInArray = true; -			if (_vm->getGameId() == GID_ITE) { -				// ITE floppy versions have both voices and sounds in voices.rsc -				voiceFileType = GAME_SOUNDFILE | GAME_VOICEFILE; -			} +		for (SoundFileInfo *curSoundFile = sfxFiles; (curSoundFile->gameId != -1); curSoundFile++) { +			if (curSoundFile->gameId != _vm->getGameId()) continue; +			if (!Common::File::exists(curSoundFile->fileName)) continue; +			strcpy(_soundFileName, curSoundFile->fileName); +			addContext(_soundFileName, GAME_SOUNDFILE, curSoundFile->isCompressed); +			break;  		}  	}  	//// Detect and add voice files ///////////////////////////////////////////// -	SoundFileInfo voiceFilesITE[] = { -		{	"voices.rsc",					false	}, -		{	"voices.cmp",					true	}, -		{	"voicesd.rsc",					false	}, -		{	"voicesd.cmp",					true	}, -		{	"inherit the earth voices",		false	}, -		{	"inherit the earth voices.cmp",	true	}, -		{	"ite voices.bin",				false	} -	}; - +	SoundFileInfo voiceFiles[] = { +		{	GID_ITE,	"voices.rsc",					false	,	(_soundFileName[0] == 0) ? GAME_SOUNDFILE : 0}, +		{	GID_ITE,	"voices.cmp",					true	,	(_soundFileName[0] == 0) ? GAME_SOUNDFILE : 0}, +		{	GID_ITE,	"voicesd.rsc",					false	,	(_soundFileName[0] == 0) ? GAME_SOUNDFILE : 0}, +		{	GID_ITE,	"voicesd.cmp",					true	,	(_soundFileName[0] == 0) ? GAME_SOUNDFILE : 0}, +		// The resources in the Wyrmkeep combined Windows/Mac/Linux CD version are little endian, but +		// the voice file is big endian. If we got such a version with mixed files, mark this voice file +		// as big endian +		{	GID_ITE,	"inherit the earth voices",		false	,	_vm->isBigEndian() ? 0 : GAME_SWAPENDIAN}, +		{	GID_ITE,	"inherit the earth voices.cmp",	true	,	_vm->isBigEndian() ? 0 : GAME_SWAPENDIAN}, +		{	GID_ITE,	"ite voices.bin",				false	,	GAME_MACBINARY},  #ifdef ENABLE_IHNM -	SoundFileInfo voiceFilesIHNM[] = { -		{	"voicess.res",					false	}, -		{	"voicess.cmp",					true	}, -		{	"voicesd.res",					false	}, -		{	"voicesd.cmp",					true	}, -	}; +		{	GID_IHNM,	"voicess.res",					false	,	0}, +		{	GID_IHNM,	"voicess.cmp",					true	,	0}, +		{	GID_IHNM,	"voicesd.res",					false	,	0}, +		{	GID_IHNM,	"voicesd.cmp",					true	,	0},  #endif -  #ifdef ENABLE_SAGA2 -	SoundFileInfo voiceFilesFTA2[] = { -		{	"ftavoice.hrs",					false	}, -	}; +		{	GID_FTA2,	"ftavoice.hrs",					false	,	0},  #endif +		{	-1,			NULL,							false	,	0} +	};  	// Detect and add voice files -	fileFound = false; - -	switch (_vm->getGameId()) { -		case GID_ITE: -			curSoundfiles = voiceFilesITE; -			maxFile = 7; -			break; -#ifdef ENABLE_IHNM -		case GID_IHNM: -			curSoundfiles = voiceFilesIHNM; -			maxFile = 4; -			break; -#endif -#ifdef ENABLE_SAGA2 -		/* -		case GID_DINO: -			// TODO -			curSoundfiles = NULL; -			maxFile = 0; -			break; -		*/ -		case GID_FTA2: -			curSoundfiles = voiceFilesFTA2; -			maxFile = 1; -			break; -#endif -	} +	_voicesFileName[0][0] = 0; +	for (SoundFileInfo *curSoundFile = voiceFiles; (curSoundFile->gameId != -1); curSoundFile++) { +		if (curSoundFile->gameId != _vm->getGameId()) continue; +		if (!Common::File::exists(curSoundFile->fileName)) continue; -	for (i = 0; i < maxFile; i++) { -		if (Common::File::exists(curSoundfiles[i].fileName)) { -			_contextsCount++; -			voicesFileIndex = _contextsCount - 1; -			strcpy(_voicesFileName[0], curSoundfiles[i].fileName); -			compressedSounds = curSoundfiles[i].isCompressed; -			fileFound = true; - -			// Special cases -			if (!scumm_stricmp(curSoundfiles[i].fileName, "inherit the earth voices") || -				!scumm_stricmp(curSoundfiles[i].fileName, "inherit the earth voices.cmp")) { -				// The resources in the Wyrmkeep combined Windows/Mac/Linux CD version are little endian, but -				// the voice file is big endian. If we got such a version with mixed files, mark this voice file -				// as big endian -				if (!_vm->isBigEndian()) -					voiceFileType = GAME_VOICEFILE | GAME_SWAPENDIAN;	// This file is big endian -			} - -			if (!scumm_stricmp(curSoundfiles[i].fileName, "ite voices.bin")) { -				voiceFileType = GAME_VOICEFILE | GAME_MACBINARY; -			} +		strcpy(_voicesFileName[0], curSoundFile->fileName); +		addContext(_voicesFileName[0], GAME_VOICEFILE | curSoundFile->voiceFileAddType, curSoundFile->isCompressed); -			if (!scumm_stricmp(curSoundfiles[i].fileName, "voicess.res") || -				!scumm_stricmp(curSoundfiles[i].fileName, "voicess.cmp")) { +		// Special cases +		if (!scumm_stricmp(curSoundFile->fileName, "voicess.res") || +			!scumm_stricmp(curSoundFile->fileName, "voicess.cmp")) {  				// IHNM has multiple voice files -				multipleVoices = true; -				// Note: it is assumed that the voice files are always last in the list -				if (Common::File::exists("voices4.res") || Common::File::exists("voices4.cmp")) { -					_contextsCount += 6;	// voices1-voices6 -				} else { -					// The German and French versions of IHNM don't have Nimdok's chapter, -					// therefore the voices file for that chapter is missing -					_contextsCount += 5;	// voices1-voices3, voices4-voices5 -					censoredVersion = true; +				for (size_t i = 1; i <= 6; i++) { // voices1-voices6 +					sprintf(_voicesFileName[i], "voices%i.%s", i, curSoundFile->isCompressed ? "cmp" : "res"); +					if (i == 4) { +						// The German and French versions of IHNM don't have Nimdok's chapter, +						// therefore the voices file for that chapter is missing +						if (!Common::File::exists(_voicesFileName[i])) { +							continue; +						} +					} +					addContext(_voicesFileName[i], GAME_VOICEFILE, curSoundFile->isCompressed, i);  				} -			} - -			break;  		} +		break;  	} -	if (!fileFound) { +	if (_voicesFileName[0][0] == 0) {  		if (_vm->getGameId() == GID_IHNM && _vm->isMacResources()) {  			// The Macintosh version of IHNM has no voices.res, and it has all  			// its voice files in subdirectories, so don't do anything here +			_contexts.push_back(new VoiceResourceContext_RES());  		} else {  			warning("No voice file found, voices will be disabled");  			_vm->_voicesEnabled = false; @@ -412,83 +327,27 @@ bool Resource::createContexts() {  		}  	} -	//// Detect and add ITE music files ///////////////////////////////////////// -	SoundFileInfo musicFilesITE[] = { -		{	"music.rsc",	false	}, -		{	"music.cmp",	true	}, -		{	"musicd.rsc",	false	}, -		{	"musicd.cmp",	true	}, +	//// Detect and add music files ///////////////////////////////////////// +	SoundFileInfo musicFiles[] = { +		{	GID_ITE,	"music.rsc",	false	}, +		{	GID_ITE,	"music.cmp",	true	}, +		{	GID_ITE,	"musicd.rsc",	false	}, +		{	GID_ITE,	"musicd.cmp",	true	}, +		{	-1,			NULL,			false	}  	};  	// Check for digital music in ITE -	if (_vm->getGameId() == GID_ITE) { -		fileFound = false; - -		for (i = 0; i < 4; i++) { -			if (Common::File::exists(musicFilesITE[i].fileName)) { -				_contextsCount++; -				digitalMusic = true; -				compressedMusic = musicFilesITE[i].isCompressed; -				fileFound = true; -				strcpy(_musicFileName, musicFilesITE[i].fileName); -				break; -			} -		} -		if (!fileFound) { -			// No sound file found, don't add any file to the array -			digitalMusic = false; -		} +	for (SoundFileInfo *curSoundFile = musicFiles; (curSoundFile->gameId != -1); curSoundFile++) { +		if (curSoundFile->gameId != _vm->getGameId()) continue; +		if (!Common::File::exists(curSoundFile->fileName)) continue; +		strcpy(_musicFileName, curSoundFile->fileName); +		addContext(_musicFileName, GAME_DIGITALMUSICFILE, curSoundFile->isCompressed); +		break;  	} -	_contexts = (ResourceContext*)calloc(_contextsCount, sizeof(*_contexts)); - -	for (i = 0; i < _contextsCount; i++) { -		context = &_contexts[i]; -		context->file = new Common::File(); -		context->serial = 0; - -		// For ITE, add the digital music file and sfx file information here -		if (_vm->getGameId() == GID_ITE && digitalMusic && i == _contextsCount - 1) { -			context->fileName = _musicFileName; -			context->fileType = GAME_DIGITALMUSICFILE; -			context->isCompressed = compressedMusic; -		} else if (!soundFileInArray && i == soundFileIndex) { -			context->fileName = _soundFileName; -			context->fileType = GAME_SOUNDFILE; -			context->isCompressed = compressedSounds; -		} else if (_vm->_voiceFilesExist && i == voicesFileIndex && !(_vm->getGameId() == GID_IHNM && _vm->isMacResources())) { -			context->fileName = _voicesFileName[0]; -			// can be GAME_VOICEFILE or GAME_SOUNDFILE | GAME_VOICEFILE or GAME_VOICEFILE | GAME_SWAPENDIAN -			context->fileType = voiceFileType; -			context->isCompressed = compressedSounds; -		} else { -			if (!(_vm->_voiceFilesExist && multipleVoices && (i > voicesFileIndex))) { -				context->fileName = _vm->getFilesDescriptions()[i].fileName; -				context->fileType = _vm->getFilesDescriptions()[i].fileType; -				context->isCompressed = compressedSounds; -			} else { -				int token = (censoredVersion && (i - voicesFileIndex >= 4)) ? 1 : 0;	// censored versions don't have voice4 - -				if (compressedSounds) -					sprintf(_voicesFileName[i - voicesFileIndex + token], "voices%i.cmp", i - voicesFileIndex + token); -				else -					sprintf(_voicesFileName[i - voicesFileIndex + token], "voices%i.res", i - voicesFileIndex + token); - -				context->fileName = _voicesFileName[i - voicesFileIndex + token]; -				context->fileType = GAME_VOICEFILE; -				context->isCompressed = compressedSounds; - -				// IHNM has several different voice files, so we need to allow -				// multiple resource contexts of the same type. We tell them -				// apart by assigning each of the duplicates a unique serial -				// number. The default behaviour when requesting a context will -				// be to look for serial number 0. -				context->serial = i - voicesFileIndex + token; -			} -		} - -		if (!loadContext(context)) { +	for (ResourceContextList::iterator i = _contexts.begin(); i != _contexts.end(); ++i) { +		if (!(*i)->load(_vm, this)) {  			return false;  		}  	} @@ -496,27 +355,12 @@ bool Resource::createContexts() {  }  void Resource::clearContexts() { -	int i; -	size_t j; -	ResourceContext *context; -	if (_contexts == NULL) { -		return; -	} -	for (i = 0; i < _contextsCount; i++) { -		context = &_contexts[i]; -		delete context->file; -		if (context->table != NULL) { -			for (j = 0; j < context->count; j++) { -				delete context->table[j].patchData; -			} -		} -		if (_vm->isSaga2()) { -			free(context->categories); -		} -		free(context->table); +	ResourceContextList::iterator i = _contexts.begin(); +	while (i != _contexts.end()) { +		ResourceContext * context = *i; +		i = _contexts.erase(i); +		delete context;  	} -	free(_contexts); -	_contexts = NULL;  }  void Resource::loadResource(ResourceContext *context, uint32 resourceId, byte*&resourceBuffer, size_t &resourceSize) { @@ -548,4 +392,14 @@ void Resource::loadResource(ResourceContext *context, uint32 resourceId, byte*&r  		file->close();  } +ResourceContext *Resource::getContext(uint16 fileType, int serial) { +	for (ResourceContextList::const_iterator i = _contexts.begin(); i != _contexts.end(); ++i) { +		ResourceContext * context = *i; +		if ((context->fileType() & fileType) && (context->serial() == serial)) { +			return context; +		} +	} +	return NULL; +} +  } // End of namespace Saga diff --git a/engines/saga/resource.h b/engines/saga/resource.h index c7d7eb9126..42b7a93404 100644 --- a/engines/saga/resource.h +++ b/engines/saga/resource.h @@ -62,53 +62,111 @@ struct ResourceData {  	size_t size;  	PatchData *patchData; -	bool isExternal() { return ((offset & (1L<<31)) != 0L); }	// SAGA2 +	ResourceData() : +		id(0), offset(0), size(0), patchData(NULL) { +	} + +	~ResourceData() { +		if (patchData) { +			delete patchData; +			patchData = NULL; +		} +	} + +	bool isExternal() {	// SAGA2 +		return ((offset & (1L<<31)) != 0L); +	} +}; + +class ResourceDataArray : public Common::Array<ResourceData> {  }; -struct ResourceContext { -	const char *fileName; -	uint16 fileType; -	Common::File *file; -	int32 fileSize; -	int serial;			// IHNM speech files - -	bool isCompressed; -	bool isBigEndian; -	ResourceData *table; -	size_t count; -	ResourceData *categories;		// SAGA2 - -	Common::File *getFile(ResourceData *resourceData) const { -		if (resourceData->patchData != NULL) { -			if (!resourceData->patchData->_patchFile->isOpen()) -				resourceData->patchData->_patchFile->open(resourceData->patchData->_patchDescription->fileName); -			return resourceData->patchData->_patchFile; +class ResourceContext { +friend class Resource; +protected: +	const char *_fileName; +	uint16 _fileType; +	bool _isCompressed; +	int _serial;					// IHNM speech files + +	bool _isBigEndian; +	ResourceDataArray _table; +	Common::File _file; +	int32 _fileSize; + +	bool load(SagaEngine *_vm, Resource *resource); +	bool loadResV1(uint32 contextOffset, uint32 contextSize); + +	virtual bool loadMac() = 0; +	virtual bool loadRes(uint32 contextOffset, uint32 contextSize) = 0; +public: + +	ResourceContext(): +		_fileName(NULL), _fileType(0), _isCompressed(false), _serial(0), +		_isBigEndian(false), +		_fileSize(0) { +	} + +	bool isCompressed() const { +		return _isCompressed; +	} + +	uint16 fileType() const { +		return _fileType; +	} + +	int serial() const { +		return _serial; +	} + +	bool isBigEndian() const { +		return _isBigEndian; +	} + +	const char * fileName() const { +		return _fileName; +	} + +	Common::File *getFile(ResourceData *resourceData) { +		Common::File *file; +		const char * fn; +		if (resourceData && resourceData->patchData != NULL) { +			file = resourceData->patchData->_patchFile; +			fn = resourceData->patchData->_patchDescription->fileName;  		} else { -			return file; +			file = &_file; +			fn = _fileName;  		} +		if (!file->isOpen()) +			file->open(fn); +		return file;  	}  	bool validResourceId(uint32 resourceId) const { -		return (resourceId < count); +		return (resourceId < _table.size());  	} -	ResourceData *getResourceData(uint32 resourceId) const { -		if (resourceId >= count) { +	ResourceData *getResourceData(uint32 resourceId) { +		if (resourceId >= _table.size()) {  			error("ResourceContext::getResourceData() wrong resourceId %d", resourceId);  		} -		return &table[resourceId]; +		return &_table[resourceId];  	}  	// SAGA 2  	int32 getEntryNum(uint32 id) { -		for (int32 i = 0; i < (int32)count; i++) { -			if (table[i].id == id) { -				return i; +		int32 num = 0; +		for (ResourceDataArray::const_iterator i = _table.begin(); i != _table.end(); ++i) { +			if (i->id == id) { +				return num;  			} +			num++;  		}  		return -1;  	} +}; +class ResourceContextList : public Common::List<ResourceContext*> {  };  struct MetaResource { @@ -145,32 +203,29 @@ public:  	virtual uint32 convertResourceId(uint32 resourceId) = 0;  	virtual void loadGlobalResources(int chapter, int actorsEntrance) = 0; -	ResourceContext *getContext(uint16 fileType, int serial = 0) { -		for (int i = 0; i < _contextsCount; i++) { -			if ((_contexts[i].fileType & fileType) && _contexts[i].serial == serial) { -				return &_contexts[i]; -			} -		} -		return NULL; -	} - +	ResourceContext *getContext(uint16 fileType, int serial = 0);  protected:  	SagaEngine *_vm; -	ResourceContext *_contexts; -	int _contextsCount; +	ResourceContextList _contexts;  	char _voicesFileName[8][256];  	char _musicFileName[256];  	char _soundFileName[256]; -	bool loadContext(ResourceContext *context); -	virtual bool loadMacContext(ResourceContext *context) = 0; -	virtual bool loadResContext(ResourceContext *context, uint32 contextOffset, uint32 contextSize) = 0; -	bool loadResContext_v1(ResourceContext *context, uint32 contextOffset, uint32 contextSize); +	void addContext(const char *fileName, uint16 fileType, bool isCompressed = false, int serial = 0); +	virtual ResourceContext *createContext() = 0;  public:  	virtual MetaResource* getMetaResource() = 0;  };  // ITE +class ResourceContext_RSC: public ResourceContext { +protected: +	virtual bool loadMac(); +	virtual bool loadRes(uint32 contextOffset, uint32 contextSize) { +		return loadResV1(contextOffset, contextSize); +	} +}; +  class Resource_RSC : public Resource {  public:  	Resource_RSC(SagaEngine *vm) : Resource(vm) {} @@ -180,32 +235,70 @@ public:  		MetaResource *dummy = 0;  		return dummy;  	} -private: -	virtual bool loadMacContext(ResourceContext *context); -	virtual bool loadResContext(ResourceContext *context, uint32 contextOffset, uint32 contextSize) { -		return loadResContext_v1(context, contextOffset, contextSize); +protected: +	virtual ResourceContext *createContext() { +		return new ResourceContext_RSC();  	}  };  #ifdef ENABLE_IHNM  // IHNM +class ResourceContext_RES: public ResourceContext { +protected: +	virtual bool loadMac() { +		return false; +	} +	virtual bool loadRes(uint32 contextOffset, uint32 contextSize) { +		return loadResV1(0, contextSize); +	} +}; + +//TODO: move load routines from sndres +class VoiceResourceContext_RES: public ResourceContext { +protected: +	virtual bool loadMac() { +		return false; +	} +	virtual bool loadRes(uint32 contextOffset, uint32 contextSize) { +		return false; +	} +public: +	VoiceResourceContext_RES() : ResourceContext() { +		_fileType = GAME_VOICEFILE; +		_isBigEndian = true; +	} +}; +  class Resource_RES : public Resource {  public:  	Resource_RES(SagaEngine *vm) : Resource(vm) {}  	virtual uint32 convertResourceId(uint32 resourceId) { return resourceId; }  	virtual void loadGlobalResources(int chapter, int actorsEntrance);  	virtual MetaResource* getMetaResource() { return &_metaResource; }; -private: -	virtual bool loadMacContext(ResourceContext *context) { return false; } -	virtual bool loadResContext(ResourceContext *context, uint32 contextOffset, uint32 contextSize) { -		return loadResContext_v1(context, 0, contextSize); +protected: +	virtual ResourceContext *createContext() { +		return new ResourceContext_RES();  	} +private:  	MetaResource _metaResource;  };  #endif  #ifdef ENABLE_SAGA2  // DINO, FTA2 +class ResourceContext_HRS: public ResourceContext { +protected: +	ResourceDataArray _categories; + +	virtual bool loadMac() { +		return false; +	} +	virtual bool loadRes(uint32 contextOffset, uint32 contextSize) { +		return loadResV2(contextSize); +	} +	bool loadResV2(uint32 contextSize); +}; +  class Resource_HRS : public Resource {  public:  	Resource_HRS(SagaEngine *vm) : Resource(vm) {} @@ -215,12 +308,10 @@ public:  		MetaResource *dummy = 0;  		return dummy;  	} -private: -	virtual bool loadMacContext(ResourceContext *context) { return false; } -	virtual bool loadResContext(ResourceContext *context, uint32 contextOffset, uint32 contextSize) { -		return loadResContext_v2(context, contextSize); +protected: +	virtual ResourceContext *createContext() { +		return new ResourceContext_HRS();  	} -	bool loadResContext_v2(ResourceContext *context, uint32 contextSize);  };  #endif diff --git a/engines/saga/resource_hrs.cpp b/engines/saga/resource_hrs.cpp index 9a7b593913..2ec2099c8d 100644 --- a/engines/saga/resource_hrs.cpp +++ b/engines/saga/resource_hrs.cpp @@ -42,64 +42,54 @@  namespace Saga { -void readElement(Common::File *file, Saga::ResourceData *element) { -	element->id = file->readUint32BE(); -	element->offset = file->readUint32LE(); -	element->size = file->readUint32LE(); -	debug(3, "Entry: id %u, offset %u, size %u", element->id, (uint)element->offset, (uint)element->size); +void readElement(Common::File &file, Saga::ResourceData &element) { +	element.id = file.readUint32BE(); +	element.offset = file.readUint32LE(); +	element.size = file.readUint32LE(); +	debug(3, "Entry: id %u, offset %u, size %u", element.id, (uint)element.offset, (uint)element.size);  } -bool Resource_HRS::loadResContext_v2(ResourceContext *context, uint32 contextSize) { -	ResourceData *origin = new ResourceData(); +bool ResourceContext_HRS::loadResV2(uint32 contextSize) { +	ResourceData origin;  	uint32 firstEntryOffset;  	uint32 tableSize;  	int i, count;  	const uint32 resourceSize = 4 + 4 + 4;	// id, size, offset -	debug(3, "Context %s =====", context->fileName); -	context->file->seek(0, SEEK_SET); +	debug(3, "Context %s =====", _fileName); +	_file.seek(0, SEEK_SET); -	readElement(context->file, origin); +	readElement(_file, origin);  	// Check if the file is valid -	if (origin->id != MKID_BE('HRES')) {	// header -		delete origin; +	if (origin.id != MKID_BE('HRES')) {	// header  		return false;  	}  	// Read offset of first entry -	context->file->seek(origin->offset - sizeof(uint32), SEEK_SET); -	firstEntryOffset = context->file->readUint32LE(); +	_file.seek(origin.offset - sizeof(uint32), SEEK_SET); +	firstEntryOffset = _file.readUint32LE();  	// Allocate buffers for table, categories and data -	context->categories = (ResourceData *) calloc(origin->size / resourceSize, sizeof(*context->categories)); -	tableSize = origin->offset - firstEntryOffset - sizeof(uint32); -	context->table = (ResourceData *) calloc(tableSize / resourceSize, sizeof(*context->table)); - -	if (context->categories == NULL || context->table == NULL) { -		delete origin; -		return false; -	} +	_categories.resize(origin.size / resourceSize); +	tableSize = origin.offset - firstEntryOffset - sizeof(uint32); +	_table.resize(tableSize / resourceSize);  	// Read categories -	count = origin->size / resourceSize; +	count = origin.size / resourceSize;  	debug(3, "Categories: %d =====", count);  	for (i = 0; i < count; i++) { -		readElement(context->file, &context->categories[i]); +		readElement(_file, _categories[i]);  	} -	context->file->seek(firstEntryOffset, SEEK_SET); +	_file.seek(firstEntryOffset, SEEK_SET);  	// Read table entries  	count = tableSize / resourceSize;  	debug(3, "Entries: %d =====", count);  	for (i = 0; i < count; i++) { -		readElement(context->file, &context->table[i]); +		readElement(_file, _table[i]);  	} - -	context->count = tableSize / resourceSize; - -	delete origin;  	return true;  } diff --git a/engines/saga/resource_rsc.cpp b/engines/saga/resource_rsc.cpp index 035db7723a..7d5753ea07 100644 --- a/engines/saga/resource_rsc.cpp +++ b/engines/saga/resource_rsc.cpp @@ -52,6 +52,12 @@ struct MacResource {  	byte attr;  	int32 dataOffset;  	byte name[255]; +	MacResource() : id(0), nameOffset(0), attr(0), dataOffset(0) { +		name[0] = 0; +	} +}; + +class MacResourceArray : public Common::Array<MacResource> {  };  struct MacResType { @@ -59,27 +65,17 @@ struct MacResType {  	int16 items;  	int16 maxItemId;  	int16 offset; -	MacResource *resources; +	MacResourceArray resources; +	MacResType() : id(0), items(0), maxItemId(0), offset(0) { +	}  }; -#define ID_MIDI     MKID_BE('Midi') - -uint32 Resource_RSC::convertResourceId(uint32 resourceId) { - -	if (_vm->isMacResources()) { -		if (resourceId > 1537) { -			return resourceId - 2; -		} else { -			if (resourceId == 1535 || resourceId == 1536) { -				error("Wrong resource number %d for Mac ITE", resourceId); -			} -		} -	} +class MacResTypeArray : public Common::Array<MacResType> { +}; -	return resourceId; -} +#define ID_MIDI     MKID_BE('Midi') -bool Resource_RSC::loadMacContext(ResourceContext *context) { +bool ResourceContext_RSC::loadMac() {  	int32 macDataSize, macDataSizePad;  	int32 macResSize, macResSizePad;  	int32 macResOffset; @@ -90,123 +86,127 @@ bool Resource_RSC::loadMacContext(ResourceContext *context) {  	uint32 macDataOffset;  	MacResMap macResMap; -	MacResType *macResTypes; +	MacResTypeArray macResTypes; -	MacResType *macResType; -	MacResource *macResource; -	int i, j;  	byte macNameLen;  	bool notSagaContext = false; -	if (context->fileSize < RSC_MIN_FILESIZE + MAC_BINARY_HEADER_SIZE) { +	if (_fileSize < RSC_MIN_FILESIZE + MAC_BINARY_HEADER_SIZE) {  		return false;  	} -	if (context->file->readByte() != 0) { +	if (_file.readByte() != 0) {  		return false;  	} -	context->file->readByte(); //MAX Name Len -	context->file->seek(74); -	if (context->file->readByte() != 0) { +	_file.readByte(); //MAX Name Len +	_file.seek(74); +	if (_file.readByte() != 0) {  		return false;  	} -	context->file->seek(82); -	if (context->file->readByte() != 0) { +	_file.seek(82); +	if (_file.readByte() != 0) {  		return false;  	} -	macDataSize = context->file->readSint32BE(); -	macResSize = context->file->readSint32BE(); +	macDataSize = _file.readSint32BE(); +	macResSize = _file.readSint32BE();  	macDataSizePad = (((macDataSize + 127) >> 7) << 7);  	macResSizePad = (((macResSize + 127) >> 7) << 7);  	macResOffset = MAC_BINARY_HEADER_SIZE + macDataSizePad; -	context->file->seek(macResOffset); +	_file.seek(macResOffset); -	macDataOffset = context->file->readUint32BE() + macResOffset; -	macMapOffset = context->file->readUint32BE() + macResOffset; -	macDataLength = context->file->readUint32BE(); -	macMapLength = context->file->readUint32BE(); +	macDataOffset = _file.readUint32BE() + macResOffset; +	macMapOffset = _file.readUint32BE() + macResOffset; +	macDataLength = _file.readUint32BE(); +	macMapLength = _file.readUint32BE(); -	if (macDataOffset >= (uint)context->fileSize || macMapOffset >= (uint)context->fileSize || -		macDataLength + macMapLength > (uint)context->fileSize) { +	if (macDataOffset >= (uint)_fileSize || macMapOffset >= (uint)_fileSize || +		macDataLength + macMapLength > (uint)_fileSize) {  			return false;  	} -	context->file->seek(macMapOffset + 22); +	_file.seek(macMapOffset + 22); -	macResMap.resAttr = context->file->readUint16BE(); -	macResMap.typeOffset = context->file->readUint16BE(); -	macResMap.nameOffset = context->file->readUint16BE(); -	macResMap.numTypes = context->file->readUint16BE(); +	macResMap.resAttr = _file.readUint16BE(); +	macResMap.typeOffset = _file.readUint16BE(); +	macResMap.nameOffset = _file.readUint16BE(); +	macResMap.numTypes = _file.readUint16BE();  	macResMap.numTypes++; -	context->file->seek(macMapOffset + macResMap.typeOffset + 2); +	_file.seek(macMapOffset + macResMap.typeOffset + 2); -	macResTypes = (MacResType *)calloc(macResMap.numTypes, sizeof(*macResTypes)); +	macResTypes.resize(macResMap.numTypes); -	for (i = macResMap.numTypes, macResType = macResTypes; i > 0; i--, macResType++) { -		macResType->id = context->file->readUint32BE(); -		macResType->items = context->file->readUint16BE(); -		macResType->offset = context->file->readUint16BE(); -		macResType->items++; -		macResType->resources = (MacResource*)calloc(macResType->items, sizeof(*macResType->resources)); +	for (MacResTypeArray::iterator k = macResTypes.begin(); k != macResTypes.end(); ++k) { +		k->id = _file.readUint32BE(); +		k->items = _file.readUint16BE(); +		k->offset = _file.readUint16BE(); +		k->items++; +		k->resources.resize(k->items);  	} -	for (i = macResMap.numTypes, macResType = macResTypes; i > 0; i--, macResType++) { -		context->file->seek(macResType->offset + macMapOffset + macResMap.typeOffset); +	for (MacResTypeArray::iterator k = macResTypes.begin(); k != macResTypes.end(); ++k) { +		_file.seek(k->offset + macMapOffset + macResMap.typeOffset); -		for (j = macResType->items, macResource = macResType->resources; j > 0; j--, macResource++) { -			macResource->id = context->file->readUint16BE(); -			macResource->nameOffset = context->file->readUint16BE(); -			macResource->dataOffset = context->file->readUint32BE(); -			macResSize = context->file->readUint32BE(); +		for (MacResourceArray::iterator j = k->resources.begin(); j != k->resources.end(); ++j) { +			j->id = _file.readUint16BE(); +			j->nameOffset = _file.readUint16BE(); +			j->dataOffset = _file.readUint32BE(); +			macResSize = _file.readUint32BE(); -			macResource->attr = macResource->dataOffset >> 24; -			macResource->dataOffset &= 0xFFFFFF; -			if (macResource->id > macResType->maxItemId) { -				macResType->maxItemId = macResource->id; +			j->attr = j->dataOffset >> 24; +			j->dataOffset &= 0xFFFFFF; +			if (j->id > k->maxItemId) { +				k->maxItemId = j->id;  			}  		} -		for (j = macResType->items, macResource = macResType->resources; j > 0; j--, macResource++) { -			if (macResource->nameOffset != -1) { -				context->file->seek(macResource->nameOffset + macMapOffset + macResMap.nameOffset); -				macNameLen = context->file->readByte(); -				context->file->read(macResource->name, macNameLen); +		for (MacResourceArray::iterator j = k->resources.begin(); j != k->resources.end(); ++j) { +			if (j->nameOffset != -1) { +				_file.seek(j->nameOffset + macMapOffset + macResMap.nameOffset); +				macNameLen = _file.readByte(); +				_file.read(j->name, macNameLen);  			}  		}  	} -// -	for (i = macResMap.numTypes, macResType = macResTypes; i > 0; i--, macResType++) { +	// +	for (MacResTypeArray::iterator k = macResTypes.begin(); k != macResTypes.end(); ++k) {  		//getting offsets & sizes of midi -		if (((context->fileType & GAME_MUSICFILE_GM) > 0) && (macResType->id == ID_MIDI)) { - -			context->count = macResType->maxItemId + 1; -			context->table = (ResourceData *)calloc(context->count, sizeof(*context->table)); -			for (j = macResType->items, macResource = macResType->resources; j > 0; j--, macResource++) { -				context->file->seek(macDataOffset + macResource->dataOffset); -				context->table[macResource->id].size = context->file->readUint32BE(); -				context->table[macResource->id].offset = context->file->pos(); +		if (((_fileType & GAME_MUSICFILE_GM) > 0) && (k->id == ID_MIDI)) { + +			_table.resize(k->maxItemId + 1); +			for (MacResourceArray::iterator j = k->resources.begin(); j != k->resources.end(); ++j) { +				_file.seek(macDataOffset + j->dataOffset); +				_table[j->id].size = _file.readUint32BE(); +				_table[j->id].offset = _file.pos();  			}  			notSagaContext = true;  			break;  		}  	} -//free -	for (i = 0; i < macResMap.numTypes; i++) { -		free(macResTypes[i].resources); -	} -	free(macResTypes); - -	if ((!notSagaContext) && (!loadResContext(context, MAC_BINARY_HEADER_SIZE, macDataSize))) { +	if ((!notSagaContext) && (!loadRes(MAC_BINARY_HEADER_SIZE, macDataSize))) {  		return false;  	}  	return true;  } +uint32 Resource_RSC::convertResourceId(uint32 resourceId) { + +	if (_vm->isMacResources()) { +		if (resourceId > 1537) { +			return resourceId - 2; +		} else { +			if (resourceId == 1535 || resourceId == 1536) { +				error("Wrong resource number %d for Mac ITE", resourceId); +			} +		} +	} + +	return resourceId; +}  } // End of namespace Saga diff --git a/engines/saga/saga.h b/engines/saga/saga.h index 2cf15946e7..674447a511 100644 --- a/engines/saga/saga.h +++ b/engines/saga/saga.h @@ -79,7 +79,7 @@ class PalAnim;  class Puzzle;  class Resource; -struct ResourceContext; +class ResourceContext;  struct StringList;  using Common::MemoryReadStream; diff --git a/engines/saga/scene.cpp b/engines/saga/scene.cpp index f43db12d1a..5cb1890a2d 100644 --- a/engines/saga/scene.cpp +++ b/engines/saga/scene.cpp @@ -168,7 +168,7 @@ Scene::Scene(SagaEngine *vm) : _vm(vm) {  		memoryError("Scene::Scene()");  	} -	MemoryReadStreamEndian readS(sceneLUTPointer, sceneLUTLength, _sceneContext->isBigEndian); +	MemoryReadStreamEndian readS(sceneLUTPointer, sceneLUTLength, _sceneContext->isBigEndian());  	for (i = 0; i < _sceneCount; i++) {  		_sceneLUT[i] = readS.readUint16(); @@ -929,7 +929,7 @@ void Scene::loadSceneDescriptor(uint32 resourceId) {  	_vm->_resource->loadResource(_sceneContext, resourceId, sceneDescriptorData, sceneDescriptorDataLength);  	if (sceneDescriptorDataLength == 16) { -		MemoryReadStreamEndian readS(sceneDescriptorData, sceneDescriptorDataLength, _sceneContext->isBigEndian); +		MemoryReadStreamEndian readS(sceneDescriptorData, sceneDescriptorDataLength, _sceneContext->isBigEndian());  		_sceneDescription.flags = readS.readSint16();  		_sceneDescription.resourceListResourceId = readS.readSint16(); @@ -960,7 +960,7 @@ void Scene::loadSceneResourceList(uint32 resourceId) {  	_vm->_resource->loadResource(_sceneContext, resourceId, resourceListData, resourceListDataLength);  	if ((resourceListDataLength % SAGA_RESLIST_ENTRY_LEN) == 0) { -		MemoryReadStreamEndian readS(resourceListData, resourceListDataLength, _sceneContext->isBigEndian); +		MemoryReadStreamEndian readS(resourceListData, resourceListDataLength, _sceneContext->isBigEndian());  		// Allocate memory for scene resource list  		_resourceListCount = resourceListDataLength / SAGA_RESLIST_ENTRY_LEN; @@ -1302,7 +1302,7 @@ void Scene::loadSceneEntryList(const byte* resourcePointer, size_t resourceLengt  	_entryList.entryListCount = resourceLength / 8; -	MemoryReadStreamEndian readS(resourcePointer, resourceLength, _sceneContext->isBigEndian); +	MemoryReadStreamEndian readS(resourcePointer, resourceLength, _sceneContext->isBigEndian());  	if (_entryList.entryList) diff --git a/engines/saga/script.cpp b/engines/saga/script.cpp index 8ddcc7d0bb..6f8810af40 100644 --- a/engines/saga/script.cpp +++ b/engines/saga/script.cpp @@ -109,7 +109,7 @@ SAGA1Script::SAGA1Script(SagaEngine *vm) : Script(vm) {  	}  	// Convert LUT resource to logical LUT -	MemoryReadStreamEndian scriptS(resourcePointer, resourceLength, resourceContext->isBigEndian); +	MemoryReadStreamEndian scriptS(resourcePointer, resourceLength, resourceContext->isBigEndian());  	for (i = 0; i < _modulesCount; i++) {  		memset(&_modules[i], 0, sizeof(ModuleData)); @@ -1127,7 +1127,7 @@ void Script::loadModuleBase(ModuleData &module, const byte *resourcePointer, siz  	memcpy(module.moduleBase, resourcePointer, resourceLength); -	MemoryReadStreamEndian scriptS(module.moduleBase, module.moduleBaseSize, _scriptContext->isBigEndian); +	MemoryReadStreamEndian scriptS(module.moduleBase, module.moduleBaseSize, _scriptContext->isBigEndian());  	module.entryPointsCount = scriptS.readUint16();  	scriptS.readUint16(); //skip @@ -1177,7 +1177,7 @@ void Script::loadVoiceLUT(VoiceLUT &voiceLUT, const byte *resourcePointer, size_  		error("Script::loadVoiceLUT() not enough memory");  	} -	MemoryReadStreamEndian scriptS(resourcePointer, resourceLength, _scriptContext->isBigEndian); +	MemoryReadStreamEndian scriptS(resourcePointer, resourceLength, _scriptContext->isBigEndian());  	for (i = 0; i < voiceLUT.voicesCount; i++) {  		voiceLUT.voices[i] = scriptS.readUint16(); diff --git a/engines/saga/sndres.cpp b/engines/saga/sndres.cpp index eddd35300e..05dd6219a1 100644 --- a/engines/saga/sndres.cpp +++ b/engines/saga/sndres.cpp @@ -48,15 +48,14 @@ namespace Saga {  #define RID_IHNM_SFX_LUT 265  #define RID_IHNMDEMO_SFX_LUT 222 -SndRes::SndRes(SagaEngine *vm) : _vm(vm) { +SndRes::SndRes(SagaEngine *vm) : _vm(vm), _sfxContext(NULL), _voiceContext(NULL), _voiceSerial(-1) { +  	// Load sound module resource file contexts  	_sfxContext = _vm->_resource->getContext(GAME_SOUNDFILE);  	if (_sfxContext == NULL) {  		error("SndRes::SndRes resource context not found");  	} -	_voiceSerial = -1; -  	setVoiceBank(0);  	if (_vm->getGameId() == GID_ITE) { @@ -117,6 +116,7 @@ SndRes::~SndRes() {  }  void SndRes::setVoiceBank(int serial) { +	Common::File *file;  	if (_voiceSerial == serial)  		return; @@ -126,12 +126,7 @@ void SndRes::setVoiceBank(int serial) {  	if (_vm->getGameId() == GID_IHNM && _vm->isMacResources()) {  		_voiceSerial = serial;  		// Set a dummy voice context -		_voiceContext = new ResourceContext(); -		_voiceContext->fileType = GAME_VOICEFILE; -		_voiceContext->count = 0; -		_voiceContext->serial = 0; -		_voiceContext->isBigEndian = true; -		_voiceContext->isCompressed = false; +		_voiceContext = new VoiceResourceContext_RES();  		return;  	}  #endif @@ -141,16 +136,16 @@ void SndRes::setVoiceBank(int serial) {  		return;  	// Close previous voice bank file -	if (_voiceSerial >= 0 && _voiceContext->file->isOpen()) -		_voiceContext->file->close(); +	if (_voiceContext != NULL) { +		file = _voiceContext->getFile(NULL); +		if (file->isOpen()) { +			file->close(); +		} +	}  	_voiceSerial = serial;  	_voiceContext = _vm->_resource->getContext(GAME_VOICEFILE, _voiceSerial); - -	// Open new voice bank file -	if (!_voiceContext->file->isOpen()) -		_voiceContext->file->open(_voiceContext->fileName);  }  void SndRes::playSound(uint32 resourceId, int volume, bool loop) { @@ -199,11 +194,12 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff  	}  #ifdef ENABLE_IHNM +	//TODO: move to resource_res so we can use normal "getResourceData" and "getFile" methods  	if (_vm->getGameId() == GID_IHNM && _vm->isMacResources()) {  		char soundFileName[40];  		int dirIndex = resourceId / 64; -		if ((context->fileType & GAME_VOICEFILE) != 0) { +		if ((context->fileType() & GAME_VOICEFILE) != 0) {  			if (_voiceSerial == 0) {  				sprintf(soundFileName, "Voices/VoicesS/Voices%d/VoicesS%03x", dirIndex, resourceId);  			} else { @@ -217,7 +213,6 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff  		file->open(soundFileName);  		soundResourceLength = file->size(); -		context->isBigEndian = true;  	} else  #endif  	{ @@ -249,14 +244,14 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff  		bool uncompressedSound = false;  		// If patch data exists for sound resource 4 (used in ITE intro), don't treat this sound as compressed  		// Patch data for this resource is in file p2_a.iaf or p2_a.voc -		if (_vm->getGameId() == GID_ITE && resourceId == 4 && context->table[resourceId].patchData != NULL) +		if (_vm->getGameId() == GID_ITE && resourceId == 4 && context->getResourceData(resourceId)->patchData != NULL)  			uncompressedSound = true;  		// FIXME: Currently, the SFX.RES file in IHNM cannot be compressed -		if (_vm->getGameId() == GID_IHNM && (context->fileType & GAME_SOUNDFILE)) +		if (_vm->getGameId() == GID_IHNM && (context->fileType() & GAME_SOUNDFILE))  			uncompressedSound = true; -		if (context->isCompressed && !uncompressedSound) { +		if (context->isCompressed() && !uncompressedSound) {  			if (header[0] == char(0)) {  				resourceType = kSoundMP3;  			} else if (header[0] == char(1)) { @@ -269,7 +264,7 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff  	}  	// Default sound type is 16-bit signed PCM, used in ITE by PCM and VOX files -	buffer.isCompressed = context->isCompressed; +	buffer.isCompressed = context->isCompressed();  	buffer.soundType = resourceType;  	buffer.originalSize = 0;  	// Set default flags and frequency for PCM, VOC and VOX files, which got no header @@ -281,20 +276,20 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff  			buffer.flags &= ~Audio::Mixer::FLAG_16BITS;  		} else {  			// Voice files in newer ITE demo versions are OKI ADPCM (VOX) encoded -			if (!scumm_stricmp(context->fileName, "voicesd.rsc")) +			if (!scumm_stricmp(context->fileName(), "voicesd.rsc"))  				resourceType = kSoundVOX;  		}  	}  	buffer.buffer = NULL;  	// Check for LE sounds -	if (!context->isBigEndian) +	if (!context->isBigEndian())  		buffer.flags |= Audio::Mixer::FLAG_LITTLE_ENDIAN; -	if ((context->fileType & GAME_VOICEFILE) && (_vm->getFeatures() & GF_LE_VOICES)) +	if ((context->fileType() & GAME_VOICEFILE) && (_vm->getFeatures() & GF_LE_VOICES))  		buffer.flags |= Audio::Mixer::FLAG_LITTLE_ENDIAN;  	// Older Mac versions of ITE were Macbinary packed -	int soundOffset = (context->fileType & GAME_MACBINARY) ? 36 : 0; +	int soundOffset = (context->fileType() & GAME_MACBINARY) ? 36 : 0;  	switch (resourceType) {  	case kSoundPCM: @@ -404,7 +399,7 @@ int SndRes::getVoiceLength(uint32 resourceId) {  		return -1;  	} -	if (!_voiceContext->isCompressed || buffer.originalSize == 0) +	if (!_voiceContext->isCompressed() || buffer.originalSize == 0)  		msDouble = (double)buffer.size;  	else  		msDouble = (double)buffer.originalSize; diff --git a/engines/saga/sprite.cpp b/engines/saga/sprite.cpp index 7296637c2c..9e93efde4e 100644 --- a/engines/saga/sprite.cpp +++ b/engines/saga/sprite.cpp @@ -106,7 +106,7 @@ void Sprite::loadList(int resourceId, SpriteList &spriteList) {  		return;  	} -	MemoryReadStreamEndian readS(spriteListData, spriteListLength, _spriteContext->isBigEndian); +	MemoryReadStreamEndian readS(spriteListData, spriteListLength, _spriteContext->isBigEndian());  	spriteCount = readS.readUint16(); @@ -142,7 +142,7 @@ void Sprite::loadList(int resourceId, SpriteList &spriteList) {  		spritePointer += offset;  		if (bigHeader) { -			MemoryReadStreamEndian readS2(spritePointer, 8, _spriteContext->isBigEndian); +			MemoryReadStreamEndian readS2(spritePointer, 8, _spriteContext->isBigEndian());  			spriteInfo->xAlign = readS2.readSint16();  			spriteInfo->yAlign = readS2.readSint16(); | 
