diff options
Diffstat (limited to 'engines')
-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 |