diff options
| author | johndoe123 | 2014-04-26 00:08:37 +0200 | 
|---|---|---|
| committer | Eugene Sandulenko | 2018-07-20 06:43:33 +0000 | 
| commit | ad2c0aaf3d81688f9c575eef64b571cb73249997 (patch) | |
| tree | 188ab3b052b4340b8ee7b17c5dc550ae6dd4c4f9 | |
| parent | 9885a050f2e9b718e3fb7bab224dcfdc18292231 (diff) | |
| download | scummvm-rg350-ad2c0aaf3d81688f9c575eef64b571cb73249997.tar.gz scummvm-rg350-ad2c0aaf3d81688f9c575eef64b571cb73249997.tar.bz2 scummvm-rg350-ad2c0aaf3d81688f9c575eef64b571cb73249997.zip  | |
ILLUSIONS: Add sound effects
- Fix priority bugs in Duckman
- Add more script and sequence opcodes
| -rw-r--r-- | engines/illusions/actor.cpp | 26 | ||||
| -rw-r--r-- | engines/illusions/actor.h | 2 | ||||
| -rw-r--r-- | engines/illusions/backgroundresource.cpp | 8 | ||||
| -rw-r--r-- | engines/illusions/backgroundresource.h | 1 | ||||
| -rw-r--r-- | engines/illusions/illusions.cpp | 5 | ||||
| -rw-r--r-- | engines/illusions/illusions_duckman.cpp | 123 | ||||
| -rw-r--r-- | engines/illusions/illusions_duckman.h | 23 | ||||
| -rw-r--r-- | engines/illusions/scriptopcodes_duckman.cpp | 10 | ||||
| -rw-r--r-- | engines/illusions/scriptopcodes_duckman.h | 1 | ||||
| -rw-r--r-- | engines/illusions/scriptresource.cpp | 5 | ||||
| -rw-r--r-- | engines/illusions/sequenceopcodes.cpp | 14 | ||||
| -rw-r--r-- | engines/illusions/sequenceopcodes.h | 1 | ||||
| -rw-r--r-- | engines/illusions/sound.cpp | 106 | ||||
| -rw-r--r-- | engines/illusions/sound.h | 33 | ||||
| -rw-r--r-- | engines/illusions/soundresource.cpp | 57 | ||||
| -rw-r--r-- | engines/illusions/soundresource.h | 19 | 
16 files changed, 389 insertions, 45 deletions
diff --git a/engines/illusions/actor.cpp b/engines/illusions/actor.cpp index 7890d021a7..e2b5e9194a 100644 --- a/engines/illusions/actor.cpp +++ b/engines/illusions/actor.cpp @@ -433,7 +433,19 @@ uint32 Control::getPriority() {  	positionY = CLIP<int16>(positionY, -5000, 5000); -	return p + 50 * ((objectId & 0x3F) + ((10000 * priority + positionY + 5000) << 6));; +	return p + 50 * ((objectId & 0x3F) + ((10000 * priority + positionY + 5000) << 6)); +} + +uint32 Control::getOverlapPriority() { +	if (_vm->getGameId() == kGameIdBBDOU) +		return getPriority(); +	return _priority; +} + +uint32 Control::getDrawPriority() { +	if (_vm->getGameId() == kGameIdBBDOU) +		return getPriority(); +	return (_actor->_position.y + 32768) | (_priority << 16);  }  Common::Point Control::calcPosition(Common::Point posDelta) { @@ -1008,7 +1020,7 @@ void Controls::placeBackgroundObject(BackgroundObject *backgroundObject) {  	control->_priority = backgroundObject->_priority;  	control->readPointsConfig(backgroundObject->_pointsConfig);  	control->activateObject(); -	_controls.push_back(control); +	_controls.push_front(control);  	_vm->_dict->setObjectControl(control->_objectId, control);  } @@ -1069,7 +1081,7 @@ void Controls::placeActor(uint32 actorTypeId, Common::Point placePt, uint32 sequ  	actor->_pathCtrY = 140; -	_controls.push_back(control); +	_controls.push_front(control);  	_vm->_dict->setObjectControl(objectId, control);  	if (_vm->getGameId() == kGameIdDuckman) { @@ -1112,7 +1124,7 @@ void Controls::placeSequenceLessActor(uint32 objectId, Common::Point placePt, Wi  	actor->_namedPoints = 0;  	actor->_pathCtrY = 140; -	_controls.push_back(control); +	_controls.push_front(control);  	_vm->_dict->setObjectControl(objectId, control);  	control->appearActor();  } @@ -1129,7 +1141,7 @@ void Controls::placeActorLessObject(uint32 objectId, Common::Point feetPt, Commo  	control->_position.y = 0;  	control->_actorTypeId = 0;  	control->_actor = 0; -	_controls.push_back(control); +	_controls.push_front(control);  	_vm->_dict->setObjectControl(objectId, control);  } @@ -1161,7 +1173,7 @@ void Controls::placeDialogItem(uint16 objectNum, uint32 actorTypeId, uint32 sequ  	actor->_position2 = placePt;  	actor->_scale = actorType->_scale;  	actor->_color = actorType->_color; -	_controls.push_back(control); +	_controls.push_front(control);  	control->appearActor();  	control->startSequenceActor(sequenceId, 2, 0);  	control->setActorIndex(1); @@ -1272,7 +1284,7 @@ bool Controls::getOverlappedObject(Control *control, Common::Point pt, Control *  			Common::Rect collisionRect;  			testControl->getCollisionRect(collisionRect);  			if (!collisionRect.isEmpty() && collisionRect.contains(pt)) { -				uint32 testPriority = testControl->getPriority(); +				uint32 testPriority = testControl->getOverlapPriority();  				if ((!foundControl || foundPriority < testPriority) &&  					testPriority >= minPriorityExt) {  					foundControl = testControl; diff --git a/engines/illusions/actor.h b/engines/illusions/actor.h index 7e69ee6cab..5f95559fe6 100644 --- a/engines/illusions/actor.h +++ b/engines/illusions/actor.h @@ -177,6 +177,8 @@ public:  	void clearNotifyThreadId1();  	void clearNotifyThreadId2();  	void setPriority(int16 priority); +	uint32 getOverlapPriority(); +	uint32 getDrawPriority();  	uint32 getPriority();  	Common::Point calcPosition(Common::Point posDelta);  	uint32 getSubActorParent(); diff --git a/engines/illusions/backgroundresource.cpp b/engines/illusions/backgroundresource.cpp index 07a07c2079..a39412c5be 100644 --- a/engines/illusions/backgroundresource.cpp +++ b/engines/illusions/backgroundresource.cpp @@ -61,7 +61,7 @@ void BackgroundResourceLoader::load(Resource *resource) {  	_vm->_camera->set(backgroundItem->_bgRes->_bgInfos[index - 1]._panPoint, backgroundItem->_bgRes->_bgInfos[index - 1]._surfInfo._dimensions);  	if (backgroundItem->_bgRes->_palettesCount > 0) { -		Palette *palette = &backgroundItem->_bgRes->_palettes[backgroundItem->_bgRes->_paletteIndex - 1]; +		Palette *palette = backgroundItem->_bgRes->getPalette(backgroundItem->_bgRes->_paletteIndex - 1);  		_vm->_screen->setPalette(palette->_palette, 1, palette->_count);  	} @@ -298,7 +298,7 @@ void BackgroundResource::load(byte *data, uint32 dataSize) {  	_priorityLayers = new PriorityLayer[_priorityLayersCount];  	stream.seek(0x34);  	uint32 priorityLayersOffs = stream.readUint32LE(); -	debug(0, "_priorityLayersCount: %d", _priorityLayersCount); +	debug("_priorityLayersCount: %d", _priorityLayersCount);  	for (uint i = 0; i < _priorityLayersCount; ++i) {  		stream.seek(priorityLayersOffs + i * 12);  		_priorityLayers[i].load(data, stream); @@ -411,6 +411,10 @@ PathWalkRects *BackgroundResource::getPathWalkRects(uint index) {  	return &_pathWalkRects[index];  } +Palette *BackgroundResource::getPalette(uint index) { +	return &_palettes[index]; +} +  bool BackgroundResource::findNamedPoint(uint32 namedPointId, Common::Point &pt) {  	return _namedPoints.findNamedPoint(namedPointId, pt);  } diff --git a/engines/illusions/backgroundresource.h b/engines/illusions/backgroundresource.h index b09c2d5e6f..8d31deb193 100644 --- a/engines/illusions/backgroundresource.h +++ b/engines/illusions/backgroundresource.h @@ -144,6 +144,7 @@ public:  	RegionLayer *getRegionLayer(uint index);  	PathWalkPoints *getPathWalkPoints(uint index);  	PathWalkRects *getPathWalkRects(uint index); +	Palette *getPalette(uint index);  	bool findNamedPoint(uint32 namedPointId, Common::Point &pt);  public: diff --git a/engines/illusions/illusions.cpp b/engines/illusions/illusions.cpp index c58eb85c0d..993da5bad4 100644 --- a/engines/illusions/illusions.cpp +++ b/engines/illusions/illusions.cpp @@ -182,7 +182,7 @@ int IllusionsEngine::updateGraphics(uint flags) {  			}  			*/  			if (actor->_surfInfo._dimensions._width && actor->_surfInfo._dimensions._height) { -				uint32 priority = control->getPriority(); +				uint32 priority = control->getDrawPriority();  				_screen->_drawQueue->insertSprite(&actor->_drawFlags, actor->_surface,  					actor->_surfInfo._dimensions, drawPosition, control->_position,  					priority, actor->_scale, actor->_spriteFlags); @@ -191,7 +191,8 @@ int IllusionsEngine::updateGraphics(uint flags) {  	}  	if (_screenText->_surface) { -		int16 priority = getPriorityFromBase(99); +		// TODO Make nicer +		uint32 priority = getGameId() == kGameIdDuckman ? getPriorityFromBase(19) : getPriorityFromBase(99);  		_screen->_drawQueue->insertTextSurface(_screenText->_surface, _screenText->_dimensions,  			_screenText->_position, priority);  	} diff --git a/engines/illusions/illusions_duckman.cpp b/engines/illusions/illusions_duckman.cpp index 3a87b09b25..1bbaf06a77 100644 --- a/engines/illusions/illusions_duckman.cpp +++ b/engines/illusions/illusions_duckman.cpp @@ -79,7 +79,7 @@ Common::Error IllusionsEngine_Duckman::run() {  	// Init search paths  	const Common::FSNode gameDataDir(ConfMan.get("path"));  	SearchMan.addSubDirectoryMatching(gameDataDir, "music"); -	SearchMan.addSubDirectoryMatching(gameDataDir, "sfx"); +	SearchMan.addSubDirectoryMatching(gameDataDir, "sfx", 0, 2);  	SearchMan.addSubDirectoryMatching(gameDataDir, "video");  	SearchMan.addSubDirectoryMatching(gameDataDir, "voice");  	SearchMan.addSubDirectoryMatching(gameDataDir, "x");// DEBUG until gam reader is done @@ -128,6 +128,9 @@ Common::Error IllusionsEngine_Duckman::run() {  	_fieldA = 0;  	_fieldE = 240; +	_propertyTimersActive = false; +	_propertyTimersPaused = false; +  	_globalSceneId = 0x00010003;  	initInventory(); @@ -144,6 +147,7 @@ Common::Error IllusionsEngine_Duckman::run() {  	startScriptThread(0x00020004, 0);  	_doScriptThreadInit = true; +#if 0  	//DEBUG  	_scriptResource->_properties.set(0x000E003A, true);  	_scriptResource->_properties.set(0x000E0020, true); @@ -152,6 +156,7 @@ Common::Error IllusionsEngine_Duckman::run() {  	_scriptResource->_properties.set(0x000E0009, true);  	_scriptResource->_properties.set(0x000E003D, true);  	_scriptResource->_properties.set(0x000E0024, true); +#endif  	while (!shouldQuit()) {  		runUpdateFunctions(); @@ -165,7 +170,7 @@ Common::Error IllusionsEngine_Duckman::run() {  	delete _fader; -    delete _soundMan; +	delete _soundMan;  	delete _updateFunctions;  	delete _threads;  	delete _talkItems; @@ -359,7 +364,7 @@ Common::Point IllusionsEngine_Duckman::getNamedPointPosition(uint32 namedPointId  }  uint32 IllusionsEngine_Duckman::getPriorityFromBase(int16 priority) { -	return 32000000 * priority; +	return priority << 16;  }  uint32 IllusionsEngine_Duckman::getCurrentScene() { @@ -954,7 +959,7 @@ uint32 IllusionsEngine_Duckman::runTriggerCause(uint32 verbId, uint32 objectId2,  	}  	uint32 tempThreadId = newTempThreadId(); -	debug(2, "Starting cause thread %08X", tempThreadId); +	debug("Starting cause thread %08X with triggerThreadId %08X", tempThreadId, triggerThreadId);  	CauseThread_Duckman *causeThread = new CauseThread_Duckman(this, tempThreadId, 0, 0,  		triggerThreadId);  	_threads->startThread(causeThread); @@ -1211,6 +1216,93 @@ DMInventorySlot *IllusionsEngine_Duckman::findClosestInventorySlot(Common::Point  	return minInventorySlot;  } +void IllusionsEngine_Duckman::addPropertyTimer(uint32 propertyId) { +	PropertyTimer *propertyTimer; +	if (findPropertyTimer(propertyId, propertyTimer) || findPropertyTimer(0, propertyTimer)) { +		propertyTimer->_propertyId = propertyId; +		propertyTimer->_startTime = 0; +		propertyTimer->_duration = 0; +		propertyTimer->_endTime = 0; +	} +} + +void IllusionsEngine_Duckman::setPropertyTimer(uint32 propertyId, uint32 duration) { +	PropertyTimer *propertyTimer; +	if (findPropertyTimer(propertyId, propertyTimer)) { +		propertyTimer->_startTime = getCurrentTime(); +		propertyTimer->_duration = duration; +		propertyTimer->_endTime = duration + propertyTimer->_startTime; +	} +	_scriptResource->_properties.set(propertyId, false); +	if (!_propertyTimersActive) { +		_updateFunctions->add(29, getCurrentScene(), new Common::Functor1Mem<uint, int, IllusionsEngine_Duckman> +			(this, &IllusionsEngine_Duckman::updatePropertyTimers)); +		_propertyTimersActive = true; +	} +} + +void IllusionsEngine_Duckman::removePropertyTimer(uint32 propertyId) { +	PropertyTimer *propertyTimer; +	if (findPropertyTimer(propertyId, propertyTimer)) +		propertyTimer->_propertyId = 0; +	_scriptResource->_properties.set(propertyId, true); +} + +bool IllusionsEngine_Duckman::findPropertyTimer(uint32 propertyId, PropertyTimer *&propertyTimer) { +	for (uint i = 0; i < kPropertyTimersCount; ++i) +		if (_propertyTimers[i]._propertyId == propertyId) { +			propertyTimer = &_propertyTimers[i]; +			return true; +		} +	return false; +} + +int IllusionsEngine_Duckman::updatePropertyTimers(uint flags) { +	int result = 1; +	uint32 currTime = getCurrentTime(); +	if (_pauseCtr <= 0) { +		if (_propertyTimersPaused) { +			for (uint i = 0; i < kPropertyTimersCount; ++i) { +				PropertyTimer &propertyTimer = _propertyTimers[i]; +				propertyTimer._startTime = currTime; +				propertyTimer._endTime = currTime + propertyTimer._duration; +			} +			_propertyTimersPaused = false; +		} +		if (flags & 1) { +			_propertyTimersActive = false; +			_propertyTimersPaused = false; +			result = 2; +		} else { +			bool timersActive = false; +			for (uint i = 0; i < kPropertyTimersCount; ++i) { +				PropertyTimer &propertyTimer = _propertyTimers[i]; +				if (propertyTimer._propertyId) { +					timersActive = true; +					if (!_scriptResource->_properties.get(propertyTimer._propertyId) && +						isTimerExpired(propertyTimer._startTime, propertyTimer._endTime)) +						_scriptResource->_properties.set(propertyTimer._propertyId, true); +				} +			} +			if (!timersActive) { +				_propertyTimersActive = false; +				_propertyTimersPaused = false; +				result = 2; +			} +		} +	} else { +		if (!_propertyTimersPaused) { +			for (uint i = 0; i < kPropertyTimersCount; ++i) { +				PropertyTimer &propertyTimer = _propertyTimers[i]; +				propertyTimer._duration -= getDurationElapsed(propertyTimer._startTime, propertyTimer._endTime); +			} +			_propertyTimersPaused = true; +		} +		result = 1; +	} +	return result; +} +  // Special code  typedef Common::Functor1Mem<OpCall&, void, IllusionsEngine_Duckman> SpecialCodeFunctionDM; @@ -1224,6 +1316,9 @@ void IllusionsEngine_Duckman::initSpecialCode() {  	SPECIAL(0x00160005, spcOpenInventory);  	SPECIAL(0x00160007, spcPutBackInventoryItem);  	SPECIAL(0x00160008, spcClearInventorySlot); +	SPECIAL(0x0016000A, spcAddPropertyTimer); +	SPECIAL(0x0016000B, spcSetPropertyTimer); +	SPECIAL(0x0016000C, spcRemovePropertyTimer);  	SPECIAL(0x00160010, spcCenterNewspaper);  	SPECIAL(0x00160014, spcUpdateObject272Sequence);  	SPECIAL(0x0016001C, spcSetCursorInventoryMode); @@ -1307,7 +1402,6 @@ static const ScreenShakeEffect *kShakerEffects[] = {  void IllusionsEngine_Duckman::spcStartScreenShaker(OpCall &opCall) {  	ARG_BYTE(effect); -	debug("### effect: %d", effect);  	const ScreenShakeEffect *shakerEffect = kShakerEffects[effect];  	startScreenShaker(shakerEffect->_pointsCount, shakerEffect->_duration, shakerEffect->_points, opCall._threadId);  } @@ -1356,6 +1450,25 @@ void IllusionsEngine_Duckman::spcClearInventorySlot(OpCall &opCall) {  	notifyThreadId(opCall._threadId);  } +void IllusionsEngine_Duckman::spcAddPropertyTimer(OpCall &opCall) { +	ARG_UINT32(propertyId); +	addPropertyTimer(propertyId); +	notifyThreadId(opCall._threadId); +} + +void IllusionsEngine_Duckman::spcSetPropertyTimer(OpCall &opCall) { +	ARG_INT16(propertyNum); +	ARG_INT16(duration); +	setPropertyTimer(propertyNum | 0xE0000, duration); +	notifyThreadId(opCall._threadId); +} + +void IllusionsEngine_Duckman::spcRemovePropertyTimer(OpCall &opCall) { +	ARG_UINT32(propertyId); +	removePropertyTimer(propertyId); +	notifyThreadId(opCall._threadId); +} +  void IllusionsEngine_Duckman::spcCenterNewspaper(OpCall &opCall) {  	Control *control = getObjectControl(0x40017);  	control->_flags |= 8; diff --git a/engines/illusions/illusions_duckman.h b/engines/illusions/illusions_duckman.h index 48d8ef28ca..7f6c427b78 100644 --- a/engines/illusions/illusions_duckman.h +++ b/engines/illusions/illusions_duckman.h @@ -91,6 +91,16 @@ struct ScreenShaker {  	const ScreenShakerPoint *_points;  }; +struct PropertyTimer { +	uint32 _propertyId; +	uint32 _startTime; +	uint32 _duration; +	uint32 _endTime; +	PropertyTimer() : _propertyId(0) {} +}; + +const uint kPropertyTimersCount = 6; +  struct OpCall;  typedef Common::Functor1<OpCall&, void> SpecialCodeFunction; @@ -125,6 +135,10 @@ public:  	ScreenShaker *_screenShaker; +	PropertyTimer _propertyTimers[kPropertyTimersCount]; +	bool _propertyTimersActive; +	bool _propertyTimersPaused; +  	uint _chinesePuzzleIndex;  	byte _chinesePuzzleAnswers[3]; @@ -220,6 +234,12 @@ public:  	DMInventoryItem *findInventoryItem(uint32 objectId);  	DMInventorySlot *findClosestInventorySlot(Common::Point pos); +	void addPropertyTimer(uint32 propertyId); +	void setPropertyTimer(uint32 propertyId, uint32 duration); +	void removePropertyTimer(uint32 propertyId); +	bool findPropertyTimer(uint32 propertyId, PropertyTimer *&propertyTimer); +	int updatePropertyTimers(uint flags); +  	// Special code  	void initSpecialCode();  	void runSpecialCode(uint32 specialCodeId, OpCall &opCall); @@ -230,6 +250,9 @@ public:  	void spcOpenInventory(OpCall &opCall);  	void spcPutBackInventoryItem(OpCall &opCall);  	void spcClearInventorySlot(OpCall &opCall); +	void spcAddPropertyTimer(OpCall &opCall); +	void spcSetPropertyTimer(OpCall &opCall); +	void spcRemovePropertyTimer(OpCall &opCall);  	void spcCenterNewspaper(OpCall &opCall);  	void spcSetCursorInventoryMode(OpCall &opCall);  	void spcUpdateObject272Sequence(OpCall &opCall); diff --git a/engines/illusions/scriptopcodes_duckman.cpp b/engines/illusions/scriptopcodes_duckman.cpp index a1e5e1cb9a..e8daf6a999 100644 --- a/engines/illusions/scriptopcodes_duckman.cpp +++ b/engines/illusions/scriptopcodes_duckman.cpp @@ -55,6 +55,7 @@ void ScriptOpcodes_Duckman::initOpcodes() {  	// First clear everything  	for (uint i = 0; i < 256; ++i)  		_opcodes[i] = 0; +	OPCODE(1, opNop);  	OPCODE(2, opSuspend);  	OPCODE(3, opYield);  	OPCODE(4, opTerminate); @@ -169,6 +170,9 @@ void ScriptOpcodes_Duckman::freeOpcodes() {  // Opcodes +void ScriptOpcodes_Duckman::opNop(ScriptThread *scriptThread, OpCall &opCall) { +} +  void ScriptOpcodes_Duckman::opSuspend(ScriptThread *scriptThread, OpCall &opCall) {  	opCall._result = kTSSuspend;  } @@ -242,7 +246,7 @@ void ScriptOpcodes_Duckman::opEnterScene18(ScriptThread *scriptThread, OpCall &o  	_vm->enterScene(sceneId, 0);  } -//static uint dsceneId = 0, dthreadId = 0; +static uint dsceneId = 0, dthreadId = 0;  //static uint dsceneId = 0x00010008, dthreadId = 0x00020029;//Beginning in Jac  //static uint dsceneId = 0x0001000A, dthreadId = 0x00020043;//Home front  //static uint dsceneId = 0x0001000E, dthreadId = 0x0002007C; @@ -251,13 +255,13 @@ void ScriptOpcodes_Duckman::opEnterScene18(ScriptThread *scriptThread, OpCall &o  //static uint dsceneId = 0x00010021, dthreadId = 0x00020113;  //static uint dsceneId = 0x00010022, dthreadId = 0x00020114;  //static uint dsceneId = 0x0001002D, dthreadId = 0x00020141; -static uint dsceneId = 0x00010033, dthreadId = 0x000201A4;//Chinese +//static uint dsceneId = 0x00010033, dthreadId = 0x000201A4;//Chinese  //static uint dsceneId = 0x00010036, dthreadId = 0x000201B5;  //static uint dsceneId = 0x00010039, dthreadId = 0x00020089;//Map  //static uint dsceneId = 0x0001003D, dthreadId = 0x000201E0;  //static uint dsceneId = 0x0001004B, dthreadId = 0x0002029B;  //static uint dsceneId = 0x0001005B, dthreadId = 0x00020341; - +//static uint dsceneId = 0x00010010, dthreadId = 0x0002008A;  void ScriptOpcodes_Duckman::opChangeScene(ScriptThread *scriptThread, OpCall &opCall) {  	ARG_SKIP(2); diff --git a/engines/illusions/scriptopcodes_duckman.h b/engines/illusions/scriptopcodes_duckman.h index 77050deb3f..f9f536e16c 100644 --- a/engines/illusions/scriptopcodes_duckman.h +++ b/engines/illusions/scriptopcodes_duckman.h @@ -42,6 +42,7 @@ protected:  	// Opcodes +	void opNop(ScriptThread *scriptThread, OpCall &opCall);  	void opSuspend(ScriptThread *scriptThread, OpCall &opCall);  	void opYield(ScriptThread *scriptThread, OpCall &opCall);  	void opTerminate(ScriptThread *scriptThread, OpCall &opCall); diff --git a/engines/illusions/scriptresource.cpp b/engines/illusions/scriptresource.cpp index 2054d4dede..18a258aa6c 100644 --- a/engines/illusions/scriptresource.cpp +++ b/engines/illusions/scriptresource.cpp @@ -158,12 +158,13 @@ void TriggerObject::load(byte *dataStart, Common::SeekableReadStream &stream) {  bool TriggerObject::findTriggerCause(uint32 verbId, uint32 objectId2, uint32 &codeOffs) {  	if ((verbId & 0xFFFF0000) == 0) { -		for (uint i = 0; i < _causesCount; ++i) +		for (uint i = 0; i < _causesCount; ++i) {  			if ((verbId == 7 && ((_causes[i]._verbId == 7 && _causes[i]._objectId2 == objectId2) || _causes[i]._verbId == 8)) || -				verbId == _causes[i]._verbId) { +				(verbId != 7 && verbId == _causes[i]._verbId)) {  				codeOffs = _causes[i]._codeOffs;  				return true;  			} +		}  	} else {  		for (uint i = 0; i < _causesCount; ++i)  			if (_causes[i]._verbId == verbId && _causes[i]._objectId2 == objectId2) { diff --git a/engines/illusions/sequenceopcodes.cpp b/engines/illusions/sequenceopcodes.cpp index 7783972f4d..5ef5158951 100644 --- a/engines/illusions/sequenceopcodes.cpp +++ b/engines/illusions/sequenceopcodes.cpp @@ -28,6 +28,7 @@  #include "illusions/screen.h"  #include "illusions/scriptman.h"  #include "illusions/scriptopcodes.h" +#include "illusions/sound.h"  namespace Illusions { @@ -90,6 +91,7 @@ void SequenceOpcodes::initOpcodes() {  	OPCODE(40, opSetPriorityLayer);  	OPCODE(41, opDisableAutoRegionLayer);  	OPCODE(42, opSetRegionLayer); +	OPCODE(48, opSetPalette);  	OPCODE(49, opShiftPalette);  	OPCODE(50, opPlaySound);  	OPCODE(51, opStopSound); @@ -344,6 +346,14 @@ void SequenceOpcodes::opSetRegionLayer(Control *control, OpCall &opCall) {  	control->_actor->_regionLayer = bgRes->getRegionLayer(regionLayerIndex - 1);  } +void SequenceOpcodes::opSetPalette(Control *control, OpCall &opCall) { +	ARG_INT16(paletteIndex); +	ARG_BYTE(fromIndex); +	BackgroundResource *bgRes = _vm->_backgroundItems->getActiveBgResource(); +	Palette *palette = bgRes->getPalette(paletteIndex - 1); +	_vm->_screen->setPalette(palette->_palette, fromIndex, palette->_count); +} +  void SequenceOpcodes::opShiftPalette(Control *control, OpCall &opCall) {  	ARG_INT16(fromIndex);  	ARG_INT16(toIndex); @@ -359,12 +369,12 @@ void SequenceOpcodes::opPlaySound(Control *control, OpCall &opCall) {  		volume = 255;  	if (!(flags & 2))  		pan = _vm->convertPanXCoord(control->_actor->_position.x); -	// TODO _vm->startSound(soundEffectId, volume, pan); +	_vm->_soundMan->playSound(soundEffectId, volume, pan);  }  void SequenceOpcodes::opStopSound(Control *control, OpCall &opCall) {  	ARG_UINT32(soundEffectId); -	// TODO _vm->stopSound(soundEffectId); +	_vm->_soundMan->stopSound(soundEffectId);  }  void SequenceOpcodes::opStartScriptThread(Control *control, OpCall &opCall) { diff --git a/engines/illusions/sequenceopcodes.h b/engines/illusions/sequenceopcodes.h index 48241e11b1..4d5cb7ab53 100644 --- a/engines/illusions/sequenceopcodes.h +++ b/engines/illusions/sequenceopcodes.h @@ -78,6 +78,7 @@ protected:  	void opSetPriorityLayer(Control *control, OpCall &opCall);  	void opDisableAutoRegionLayer(Control *control, OpCall &opCall);  	void opSetRegionLayer(Control *control, OpCall &opCall); +	void opSetPalette(Control *control, OpCall &opCall);  	void opShiftPalette(Control *control, OpCall &opCall);  	void opPlaySound(Control *control, OpCall &opCall);  	void opStopSound(Control *control, OpCall &opCall); diff --git a/engines/illusions/sound.cpp b/engines/illusions/sound.cpp index 0f60e5d14c..23caf7ebb0 100644 --- a/engines/illusions/sound.cpp +++ b/engines/illusions/sound.cpp @@ -27,8 +27,8 @@ namespace Illusions {  // MusicPlayer -MusicPlayer::MusicPlayer(Audio::Mixer *mixer) -	: _mixer(mixer), _musicId(0), _flags(0) { +MusicPlayer::MusicPlayer() +	: _musicId(0), _flags(0) {  	_flags = 1; // TODO?  } @@ -52,15 +52,15 @@ void MusicPlayer::play(uint32 musicId, bool looping, int16 volume, int16 pan) {  		Common::File *fd = new Common::File();  		fd->open(filename);  		Audio::AudioStream *audioStream = Audio::makeLoopingAudioStream(Audio::makeWAVStream(fd, DisposeAfterUse::YES), looping ? 0 : 1); -		_mixer->playStream(Audio::Mixer::kMusicSoundType, &_soundHandle, audioStream, -1, volume, pan); +		g_system->getMixer()->playStream(Audio::Mixer::kMusicSoundType, &_soundHandle, audioStream, -1, volume, pan);  	}  }  void MusicPlayer::stop() {  	debug("MusicPlayer::stop()");  	if ((_flags & 1) && (_flags & 2)) { -		if (_mixer->isSoundHandleActive(_soundHandle)) -			_mixer->stopHandle(_soundHandle); +		if (g_system->getMixer()->isSoundHandleActive(_soundHandle)) +			g_system->getMixer()->stopHandle(_soundHandle);  		_flags &= ~2;  		_flags &= ~4;  		_flags &= ~8; @@ -69,13 +69,12 @@ void MusicPlayer::stop() {  }  bool MusicPlayer::isPlaying() { -	return (_flags & 1) && (_flags & 2) && _mixer->isSoundHandleActive(_soundHandle); +	return (_flags & 1) && (_flags & 2) && g_system->getMixer()->isSoundHandleActive(_soundHandle);  }  // VoicePlayer -VoicePlayer::VoicePlayer(Audio::Mixer *mixer) -	: _mixer(mixer) { +VoicePlayer::VoicePlayer() {  }  VoicePlayer::~VoicePlayer() { @@ -102,19 +101,19 @@ void VoicePlayer::start(int16 volume, int16 pan) {  	Common::File *fd = new Common::File();  	fd->open(filename);  	Audio::AudioStream *audioStream = Audio::makeWAVStream(fd, DisposeAfterUse::YES); -	_mixer->playStream(Audio::Mixer::kSpeechSoundType, &_soundHandle, audioStream, -1, volume, pan); +	g_system->getMixer()->playStream(Audio::Mixer::kSpeechSoundType, &_soundHandle, audioStream, -1, volume, pan);  	_voiceStatus = 4;  }  void VoicePlayer::stop() { -	if (_mixer->isSoundHandleActive(_soundHandle)) -		_mixer->stopHandle(_soundHandle); +	if (g_system->getMixer()->isSoundHandleActive(_soundHandle)) +		g_system->getMixer()->stopHandle(_soundHandle);  	_voiceStatus = 1;  	_voiceName.clear();  }  bool VoicePlayer::isPlaying() { -	return _mixer->isSoundHandleActive(_soundHandle); +	return g_system->getMixer()->isSoundHandleActive(_soundHandle);  }  bool VoicePlayer::isEnabled() { @@ -126,17 +125,62 @@ bool VoicePlayer::isCued() {  	return _voiceStatus == 2;  } +// Sound + +Sound::Sound(uint32 soundEffectId, uint32 soundGroupId, bool looping) +	: _stream(0), _soundEffectId(soundEffectId), _soundGroupId(soundGroupId), _looping(looping) { +	load(); +} + +Sound::~Sound() { +	unload(); +} + +void Sound::load() { +	Common::String filename = Common::String::format("%08x/%08x.wav", _soundGroupId, _soundEffectId); +	Common::File *fd = new Common::File(); +	if (!fd->open(filename)) { +		delete fd; +		error("SoundMan::loadSound() Could not load %s", filename.c_str()); +	} +	_stream = Audio::makeWAVStream(fd, DisposeAfterUse::YES); +} + +void Sound::unload() { +	stop(); +	delete _stream; +	_stream = 0; +} + +void Sound::play(int16 volume, int16 pan) { +	stop(); +	_stream->rewind(); +	Audio::AudioStream *audioStream = new Audio::LoopingAudioStream(_stream, _looping ? 0 : 1, DisposeAfterUse::NO); +	g_system->getMixer()->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle, audioStream, +		-1, volume, pan, DisposeAfterUse::YES); +} + +void Sound::stop() { +	if (g_system->getMixer()->isSoundHandleActive(_soundHandle)) +		g_system->getMixer()->stopHandle(_soundHandle); +} + +bool Sound::isPlaying() { +	return g_system->getMixer()->isSoundHandleActive(_soundHandle); +} +  // SoundMan  SoundMan::SoundMan(IllusionsEngine *vm)  	: _vm(vm), _musicNotifyThreadId(0) { -	_musicPlayer = new MusicPlayer(_vm->_mixer); -	_voicePlayer = new VoicePlayer(_vm->_mixer); +	_musicPlayer = new MusicPlayer(); +	_voicePlayer = new VoicePlayer();  }  SoundMan::~SoundMan() {  	delete _musicPlayer;  	delete _voicePlayer; +	unloadSounds(0);  }  void SoundMan::update() { @@ -183,4 +227,38 @@ bool SoundMan::isVoiceCued() {  	return _voicePlayer->isCued();  } +void SoundMan::loadSound(uint32 soundEffectId, uint32 soundGroupId, bool looping) { +	Sound *soundEffect = new Sound(soundEffectId, soundGroupId, looping); +	_sounds.push_front(soundEffect); +} + +void SoundMan::playSound(uint32 soundEffectId, int16 volume, int16 pan) { +	Sound *soundEffect = getSound(soundEffectId); +	soundEffect->play(volume, pan); +} + +void SoundMan::stopSound(uint32 soundEffectId) { +	Sound *soundEffect = getSound(soundEffectId); +	soundEffect->stop(); +} + +void SoundMan::unloadSounds(uint32 soundGroupId) { +	SoundListIterator it = _sounds.begin(); +	while (it != _sounds.end()) { +		Sound *soundEffect = *it; +		if (soundGroupId == 0 || soundEffect->_soundGroupId == soundGroupId) { +			delete soundEffect; +			it = _sounds.erase(it); +		} else +			++it; +	} +} + +Sound *SoundMan::getSound(uint32 soundEffectId) { +	for (SoundListIterator it = _sounds.begin(); it != _sounds.end(); ++it) +		if ((*it)->_soundEffectId == soundEffectId) +			return *it; +	return 0; +} +  } // End of namespace Illusions diff --git a/engines/illusions/sound.h b/engines/illusions/sound.h index 9e2cd43fa1..d2d91ac3c8 100644 --- a/engines/illusions/sound.h +++ b/engines/illusions/sound.h @@ -35,13 +35,12 @@ class IllusionsEngine;  class MusicPlayer {  public: -	MusicPlayer(Audio::Mixer *mixer); +	MusicPlayer();  	~MusicPlayer();  	void play(uint32 musicId, bool looping, int16 volume, int16 pan);  	void stop();  	bool isPlaying();  protected: -	Audio::Mixer *_mixer;  	Audio::SoundHandle _soundHandle;  	uint32 _musicId;  	uint _flags; @@ -49,7 +48,7 @@ protected:  class VoicePlayer {  public: -	VoicePlayer(Audio::Mixer *mixer); +	VoicePlayer();  	~VoicePlayer();  	bool cue(const char *voiceName);  	void stopCueing(); @@ -59,12 +58,29 @@ public:  	bool isEnabled();  	bool isCued();  protected: -	Audio::Mixer *_mixer;  	Audio::SoundHandle _soundHandle;  	Common::String _voiceName;  	uint _voiceStatus;  }; +class Sound { +public: +	Sound(uint32 soundEffectId, uint32 soundGroupId, bool looping); +	~Sound(); +	void load(); +	void unload(); +	void play(int16 volume, int16 pan); +	void stop(); +	bool isPlaying(); +public: +	uint32 _soundEffectId; +	uint32 _soundGroupId; +protected: +	Audio::RewindableAudioStream *_stream; +	Audio::SoundHandle _soundHandle; +	bool _looping; +}; +  class SoundMan {  public:  	SoundMan(IllusionsEngine *vm); @@ -82,11 +98,20 @@ public:  	bool isVoiceEnabled();  	bool isVoiceCued(); +	void loadSound(uint32 soundEffectId, uint32 soundGroupId, bool looping); +	void playSound(uint32 soundEffectId, int16 volume, int16 pan); +	void stopSound(uint32 soundEffectId); +	void unloadSounds(uint32 soundGroupId); +  protected: +	typedef Common::List<Sound*> SoundList; +	typedef SoundList::iterator SoundListIterator;  	IllusionsEngine *_vm;  	uint32 _musicNotifyThreadId;  	MusicPlayer *_musicPlayer;  	VoicePlayer *_voicePlayer; +	SoundList _sounds; +	Sound *getSound(uint32 soundEffectId);  };  } // End of namespace Illusions diff --git a/engines/illusions/soundresource.cpp b/engines/illusions/soundresource.cpp index e5cc5dde50..8dbe798905 100644 --- a/engines/illusions/soundresource.cpp +++ b/engines/illusions/soundresource.cpp @@ -22,6 +22,7 @@  #include "illusions/illusions.h"  #include "illusions/soundresource.h" +#include "illusions/sound.h"  namespace Illusions { @@ -30,20 +31,68 @@ namespace Illusions {  void SoundGroupResourceLoader::load(Resource *resource) {  	debug("SoundGroupResourceLoader::load() Loading sound group %08X...", resource->_resId); -    // TODO -    // Load all sounds in sfx/{SoundGroupId}/ +	SoundGroupResource *soundGroupResource = new SoundGroupResource(); +	soundGroupResource->load(resource->_data, resource->_dataSize); +	resource->_refId = soundGroupResource; + +	for (uint i = 0; i < soundGroupResource->_soundEffectsCount; ++i) { +		SoundEffect *soundEffect = &soundGroupResource->_soundEffects[i]; +		_vm->_soundMan->loadSound(soundEffect->_soundEffectId, resource->_resId, soundEffect->_looping); +	}  }  void SoundGroupResourceLoader::unload(Resource *resource) { +	_vm->_soundMan->unloadSounds(resource->_resId); +	delete (SoundGroupResource*)resource->_refId;  }  void SoundGroupResourceLoader::buildFilename(Resource *resource) { -	resource->_filename = Common::String::format("%08X.fnt", resource->_resId); +	resource->_filename = Common::String::format("%08X.sg", resource->_resId);  }  bool SoundGroupResourceLoader::isFlag(int flag) { -	return false; +	return +		flag == kRlfLoadFile || +		flag == kRlfFreeDataAfterUse; +} + +// SoundEffect + +void SoundEffect::load(Common::SeekableReadStream &stream) { +	_soundEffectId = stream.readUint32LE(); +	_looping = stream.readUint16LE() != 0; +	_field6 = stream.readUint16LE(); +	_volume = stream.readUint16LE(); +	_frequency = stream.readUint16LE(); +	stream.skip(32 + 4); // Skip name +	debug("SoundEffect::load() _soundEffectId: %08X, _looping: %d, _field6: %d, _volume: %d, _frequency: %d", +		_soundEffectId, _looping, _field6, _volume, _frequency); +} + +// SoundGroupResource + +SoundGroupResource::SoundGroupResource() +	: _soundEffects(0) { +} + +SoundGroupResource::~SoundGroupResource() { +	delete[] _soundEffects; +} + +void SoundGroupResource::load(byte *data, uint32 dataSize) { +	Common::MemoryReadStream stream(data, dataSize, DisposeAfterUse::NO); + +	stream.skip(4); +	_soundEffectsCount = stream.readUint16LE(); +	stream.skip(2); +	uint32 soundEffectsOffs = stream.readUint32LE(); +	debug("_soundEffectsCount: %d; soundEffectsOffs: %08X", _soundEffectsCount, soundEffectsOffs); +	_soundEffects = new SoundEffect[_soundEffectsCount]; +	stream.seek(soundEffectsOffs); +	for (uint i = 0; i < _soundEffectsCount; ++i) +		_soundEffects[i].load(stream); +  }  } // End of namespace Illusions diff --git a/engines/illusions/soundresource.h b/engines/illusions/soundresource.h index d278a30f52..09b88179ab 100644 --- a/engines/illusions/soundresource.h +++ b/engines/illusions/soundresource.h @@ -42,6 +42,25 @@ protected:  	IllusionsEngine *_vm;  }; +struct SoundEffect { +	uint32 _soundEffectId; +	bool _looping; +	int16 _field6; +	int16 _volume; +	int16 _frequency; +	void load(Common::SeekableReadStream &stream); +}; + +class SoundGroupResource { +public: +	SoundGroupResource(); +	~SoundGroupResource(); +	void load(byte *data, uint32 dataSize); +public: +	uint _soundEffectsCount; +	SoundEffect *_soundEffects; +}; +  } // End of namespace Illusions  #endif // ILLUSIONS_SOUNDRESOURCE_H  | 
