diff options
Diffstat (limited to 'engines/mads')
-rw-r--r-- | engines/mads/detection_tables.h | 4 | ||||
-rw-r--r-- | engines/mads/dialogs.cpp | 1 | ||||
-rw-r--r-- | engines/mads/events.cpp | 2 | ||||
-rw-r--r-- | engines/mads/game.cpp | 3 | ||||
-rw-r--r-- | engines/mads/mads.cpp | 7 | ||||
-rw-r--r-- | engines/mads/menu_views.cpp | 5 | ||||
-rw-r--r-- | engines/mads/messages.cpp | 8 | ||||
-rw-r--r-- | engines/mads/nebular/dialogs_nebular.cpp | 56 | ||||
-rw-r--r-- | engines/mads/nebular/dialogs_nebular.h | 3 | ||||
-rw-r--r-- | engines/mads/nebular/game_nebular.cpp | 65 | ||||
-rw-r--r-- | engines/mads/nebular/nebular_scenes1.cpp | 11 | ||||
-rw-r--r-- | engines/mads/nebular/nebular_scenes6.cpp | 10 | ||||
-rw-r--r-- | engines/mads/nebular/nebular_scenes8.cpp | 2 | ||||
-rw-r--r-- | engines/mads/nebular/sound_nebular.cpp | 37 | ||||
-rw-r--r-- | engines/mads/nebular/sound_nebular.h | 8 | ||||
-rw-r--r-- | engines/mads/scene_data.cpp | 1 | ||||
-rw-r--r-- | engines/mads/sound.cpp | 15 | ||||
-rw-r--r-- | engines/mads/sound.h | 6 | ||||
-rw-r--r-- | engines/mads/sprites.cpp | 6 | ||||
-rw-r--r-- | engines/mads/user_interface.cpp | 1 |
20 files changed, 179 insertions, 72 deletions
diff --git a/engines/mads/detection_tables.h b/engines/mads/detection_tables.h index 0a8e98bb31..faf73996ac 100644 --- a/engines/mads/detection_tables.h +++ b/engines/mads/detection_tables.h @@ -55,7 +55,7 @@ static const MADSGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformDOS, - ADGF_NO_FLAGS, + ADGF_TESTING, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EASY_MOUSE, GAMEOPTION_ANIMATED_INVENTORY, GAMEOPTION_ANIMATED_INTERFACE, GAMEOPTION_NAUGHTY_MODE) }, GType_RexNebular, @@ -73,7 +73,7 @@ static const MADSGameDescription gameDescriptions[] = { }, Common::EN_ANY, Common::kPlatformDOS, - ADGF_NO_FLAGS, + ADGF_TESTING, GUIO5(GUIO_NOSPEECH, GAMEOPTION_EASY_MOUSE, GAMEOPTION_ANIMATED_INVENTORY, GAMEOPTION_ANIMATED_INTERFACE, GAMEOPTION_NAUGHTY_MODE) }, GType_RexNebular, diff --git a/engines/mads/dialogs.cpp b/engines/mads/dialogs.cpp index 158d9693ad..7f0b02bc65 100644 --- a/engines/mads/dialogs.cpp +++ b/engines/mads/dialogs.cpp @@ -43,6 +43,7 @@ Dialog::Dialog(MADSEngine *vm) } Dialog::~Dialog() { + delete _savedSurface; } void Dialog::save() { diff --git a/engines/mads/events.cpp b/engines/mads/events.cpp index 767f998d81..52569af375 100644 --- a/engines/mads/events.cpp +++ b/engines/mads/events.cpp @@ -84,8 +84,8 @@ void EventsManager::waitCursor() { CursorType cursorId = (CursorType)MIN(_cursorSprites->getCount(), (int)CURSOR_WAIT); _newCursorId = cursorId; if (_cursorId != _newCursorId) { - changeCursor(); _cursorId = _newCursorId; + changeCursor(); } } diff --git a/engines/mads/game.cpp b/engines/mads/game.cpp index b601a12c82..3d1c194612 100644 --- a/engines/mads/game.cpp +++ b/engines/mads/game.cpp @@ -100,6 +100,7 @@ Game::~Game() { } delete _saveFile; + _surface->free(); delete _surface; delete _sectionHandler; } @@ -115,8 +116,6 @@ void Game::run() { _statusFlag = true; while (!_vm->shouldQuit()) { - initializeGlobals(); - if (_loadGameSlot == -1) { startGame(); } diff --git a/engines/mads/mads.cpp b/engines/mads/mads.cpp index 59d600fbfb..374e373035 100644 --- a/engines/mads/mads.cpp +++ b/engines/mads/mads.cpp @@ -126,6 +126,13 @@ void MADSEngine::loadOptions() { if (ConfMan.hasKey("NaughtyMode")) _game->setNaughtyMode(ConfMan.getBool("NaughtyMode")); } + + // Note: MADS is weird in that sfx and music are handled by the same driver, + // and the game scripts themselves check for music being enabled before playing + // a "music" sound. Which means we can independantly mute music in ScummVM, but + // otherwise all sound, music and sfx, is controlled by the SFX volume slider. + int soundVolume = MIN(255, ConfMan.getInt("sfx_volume")); + _sound->setVolume(soundVolume); } void MADSEngine::saveOptions() { diff --git a/engines/mads/menu_views.cpp b/engines/mads/menu_views.cpp index 5a0c7ee92e..319f5b0f87 100644 --- a/engines/mads/menu_views.cpp +++ b/engines/mads/menu_views.cpp @@ -544,6 +544,7 @@ void AnimationView::doFrame() { scriptDone(); } else { scene._frameStartTime = 0; + scene._spriteSlots.clear(); loadNextResource(); } } else if (_currentAnimation->getCurrentFrame() == 1) { @@ -559,6 +560,10 @@ void AnimationView::doFrame() { ++scene._frameStartTime; _currentAnimation->update(); _redrawFlag = true; + + if (_currentAnimation->freeFlag()) + // We don't want the sprites removed after the last animation frame + scene._spriteSlots.clear(); } } diff --git a/engines/mads/messages.cpp b/engines/mads/messages.cpp index 4b105630d6..304c79aa46 100644 --- a/engines/mads/messages.cpp +++ b/engines/mads/messages.cpp @@ -91,7 +91,7 @@ int KernelMessages::add(const Common::Point &pt, uint fontColor, uint8 flags, rec._position = pt; rec._textDisplayIndex = -1; rec._timeout = timeout; - rec._frameTimer = _vm->_game->_priorFrameTimer; + rec._frameTimer = scene._frameStartTime; rec._trigger = endTrigger; rec._abortMode = _vm->_game->_triggerSetupMode; @@ -162,8 +162,10 @@ void KernelMessages::update() { uint32 currentTimer = _vm->_game->_scene._frameStartTime; for (uint i = 0; i < _entries.size() && !_vm->_game->_trigger; ++i) { - KernelMessage &msg = _entries[i]; + if (_vm->_game->_trigger) + break; + KernelMessage &msg = _entries[i]; if (((msg._flags & KMSG_ACTIVE) != 0) && (currentTimer >= msg._frameTimer)) processText(i); } @@ -172,7 +174,7 @@ void KernelMessages::update() { void KernelMessages::processText(int msgIndex) { Scene &scene = _vm->_game->_scene; KernelMessage &msg = _entries[msgIndex]; - uint32 currentTimer = _vm->_game->_priorFrameTimer; + uint32 currentTimer = scene._frameStartTime; bool flag = false; if ((msg._flags & KMSG_EXPIRE) != 0) { diff --git a/engines/mads/nebular/dialogs_nebular.cpp b/engines/mads/nebular/dialogs_nebular.cpp index 4ba5366a60..5b9942db07 100644 --- a/engines/mads/nebular/dialogs_nebular.cpp +++ b/engines/mads/nebular/dialogs_nebular.cpp @@ -417,7 +417,7 @@ TextDialog(vm, FONT_INTERFACE, Common::Point(-1, -1), 32) { _hogEntry._pageNum, _hogEntry._lineNum, _hogEntry._wordNum); wordWrap(line); - wordWrap("and type it on the line below (we',27h,'ve even given you"); + wordWrap("and type it on the line below (we've even given you"); wordWrap("first letter as a hint). As soon as you do that, we can get"); wordWrap("right into this really COOL adventure game!\n"); wordWrap("\n"); @@ -428,17 +428,58 @@ TextDialog(vm, FONT_INTERFACE, Common::Point(-1, -1), 32) { void CopyProtectionDialog::show() { draw(); - _vm->_events->showCursor(); - // TODO: Replace with text input - while (!_vm->shouldQuit() && !_vm->_events->isKeyPressed() && - !_vm->_events->_mouseClicked) { - _vm->_events->delay(1); + Common::KeyState curKey; + const Common::Rect inputArea(110, 165, 210, 175); + MSurface *origInput = new MSurface(inputArea.width(), inputArea.height()); + _vm->_screen.frameRect(inputArea, TEXTDIALOG_BLACK); + _vm->_screen.copyTo(origInput, inputArea, Common::Point(0, 0)); + _font->setColors(TEXTDIALOG_FE, TEXTDIALOG_FE, TEXTDIALOG_FE, TEXTDIALOG_FE); + _vm->_screen.copyRectToScreen(inputArea); + _vm->_screen.updateScreen(); + + bool firstTime = true; + + while (!_vm->shouldQuit()) { + if (!firstTime) { + while (!_vm->shouldQuit() && !_vm->_events->isKeyPressed()) { + _vm->_events->delay(1); + } + + if (_vm->shouldQuit()) + break; + + curKey = _vm->_events->getKey(); + + if (curKey.keycode == Common::KEYCODE_RETURN || curKey.keycode == Common::KEYCODE_KP_ENTER) + break; + else if (curKey.keycode == Common::KEYCODE_BACKSPACE) + _textInput.deleteLastChar(); + else if (_textInput.size() < 14) + _textInput += curKey.ascii; + + _vm->_events->_pendingKeys.clear(); + } else { + firstTime = false; + _textInput = _hogEntry._word[0]; + } + + _vm->_screen.copyFrom(origInput, Common::Rect(0, 0, inputArea.width(), inputArea.height()), Common::Point(inputArea.left, inputArea.top)); + _font->writeString(&_vm->_screen, _textInput, + Common::Point(inputArea.left + 2, inputArea.top + 1), 1); + _vm->_screen.copyRectToScreen(inputArea); + _vm->_screen.updateScreen(); } - _vm->_events->_pendingKeys.clear(); + origInput->free(); + delete origInput; } +bool CopyProtectionDialog::isCorrectAnswer() { + return _hogEntry._word == _textInput; +} + + bool CopyProtectionDialog::getHogAnusEntry(HOGANUS &entry) { File f; f.open("*HOGANUS.DAT"); @@ -552,6 +593,7 @@ void PictureDialog::save() { void PictureDialog::restore() { if (_savedSurface) { _savedSurface->copyTo(&_vm->_screen); + _savedSurface->free(); delete _savedSurface; _savedSurface = nullptr; diff --git a/engines/mads/nebular/dialogs_nebular.h b/engines/mads/nebular/dialogs_nebular.h index 5dbe4da6f0..0f086f6ec1 100644 --- a/engines/mads/nebular/dialogs_nebular.h +++ b/engines/mads/nebular/dialogs_nebular.h @@ -69,6 +69,7 @@ struct HOGANUS { class CopyProtectionDialog : public TextDialog { private: HOGANUS _hogEntry; + Common::String _textInput; /** * Get a random copy protection entry from the HOGANUS resource @@ -84,6 +85,8 @@ public: * Show the dialog */ virtual void show(); + + bool isCorrectAnswer(); }; class PictureDialog : public TextDialog { diff --git a/engines/mads/nebular/game_nebular.cpp b/engines/mads/nebular/game_nebular.cpp index cde998e66a..e9a3d0b716 100644 --- a/engines/mads/nebular/game_nebular.cpp +++ b/engines/mads/nebular/game_nebular.cpp @@ -45,19 +45,25 @@ GameNebular::GameNebular(MADSEngine *vm) } ProtectionResult GameNebular::checkCopyProtection() { - /* - // DEBUG: Flag copy protection failure - _globals[kCopyProtectFailed] = -1; + //if (!ConfMan.getBool("copy_protection")) + // return PROTECTION_SUCCEED; - if (!ConfMan.getBool("copy_protection")) - return true; + CopyProtectionDialog *dlg; + bool correctAnswer; - * DEBUG: Disabled for now - CopyProtectionDialog *dlg = new CopyProtectionDialog(_vm, false); + dlg = new CopyProtectionDialog(_vm, false); dlg->show(); + correctAnswer = dlg->isCorrectAnswer(); delete dlg; - */ - return PROTECTION_SUCCEED; + + if (!correctAnswer && !_vm->shouldQuit()) { + dlg = new CopyProtectionDialog(_vm, true); + dlg->show(); + correctAnswer = dlg->isCorrectAnswer(); + delete dlg; + } + + return correctAnswer ? PROTECTION_SUCCEED : PROTECTION_FAIL; } void GameNebular::startGame() { @@ -91,26 +97,6 @@ void GameNebular::startGame() { checkShowDialog(); _winStatus = 0; - /* - // Check copy protection - ProtectionResult protectionResult = checkCopyProtection(); - switch (protectionResult) { - case PROTECTION_FAIL: - // Copy protection failed - _scene._nextSceneId = 804; - initializeGlobals(); - _globals[kCopyProtectFailed] = true; - return; - case PROTECTION_ESCAPE: - // User escaped out of copy protection dialog - _vm->quitGame(); - return; - default: - // Copy protection check succeeded - break; - } - */ - _sectionNumber = 1; initSection(_sectionNumber); _vm->_events->setCursor(CURSOR_ARROW); @@ -121,6 +107,9 @@ void GameNebular::startGame() { _vm->_dialogs->showDialog(); } while (!_vm->shouldQuit() && _vm->_dialogs->_pendingDialog != DIALOG_NONE); + if (_vm->shouldQuit()) + return; + _priorSectionNumber = 0; _priorSectionNumber = -1; _scene._priorSceneId = 0; @@ -128,6 +117,24 @@ void GameNebular::startGame() { _scene._nextSceneId = 101; initializeGlobals(); + + // Check copy protection + ProtectionResult protectionResult = checkCopyProtection(); + + switch (protectionResult) { + case PROTECTION_FAIL: + // Copy protection failed + _scene._nextSceneId = 804; + _globals[kCopyProtectFailed] = true; + return; + case PROTECTION_ESCAPE: + // User escaped out of copy protection dialog + _vm->quitGame(); + return; + default: + // Copy protection check succeeded + break; + } } void GameNebular::initializeGlobals() { diff --git a/engines/mads/nebular/nebular_scenes1.cpp b/engines/mads/nebular/nebular_scenes1.cpp index 0c5888b6ec..c9eda08859 100644 --- a/engines/mads/nebular/nebular_scenes1.cpp +++ b/engines/mads/nebular/nebular_scenes1.cpp @@ -1462,7 +1462,6 @@ void Scene103::actions() { } else if (_action.isAction(VERB_TAKE, NOUN_REBREATHER, 0) && _game._objects.isInRoom(OBJ_REBREATHER)) { switch (_vm->_game->_trigger) { case 0: - _scene->changeVariant(1); _globals._sequenceIndexes[12] = _scene->_sequences.startPingPongCycle(_globals._spriteIndexes[12], false, 3, 2); _scene->_sequences.setMsgLayout(_globals._sequenceIndexes[12]); _scene->_sequences.addSubEntry(_globals._sequenceIndexes[12], SEQUENCE_TRIGGER_SPRITE, 6, 1); @@ -2113,9 +2112,9 @@ void Scene106::step() { } if (msgId >= 0) { - int nextAbortVal = _game._trigger + 1; + int nextTrigger = _game._trigger + 1; _scene->_kernelMessages.add(Common::Point(15, _positionY), 0x1110, 0, 0, 360, _game.getQuote(msgId)); - _scene->_sequences.addTimer(150, nextAbortVal); + _scene->_sequences.addTimer(150, nextTrigger); _positionY += 14; } } @@ -2590,8 +2589,8 @@ void Scene109::preActions() { _game._player._walkOffScreenSceneId = 108; if ((_action.isAction(VERB_THROW) || _action.isAction(VERB_GIVE) || _action.isAction(VERB_PUT)) - && (_action.isObject(NOUN_SMALL_HOLE) || _action.isObject(NOUN_TUNNEL)) - && (_action.isObject(NOUN_DEAD_FISH) || _action.isObject(NOUN_STUFFED_FISH) || _action.isObject(NOUN_BURGER))) { + && (_action.isTarget(NOUN_SMALL_HOLE) || _action.isTarget(NOUN_TUNNEL)) + && (_action.isObject(NOUN_DEAD_FISH) || _action.isObject(NOUN_STUFFED_FISH) || _action.isObject(NOUN_BURGER))) { int idx = _game._objects.getIdFromDesc(_action._activeAction._objectNameId); if ((idx >= 0) && _game._objects.isInInventory(idx)) { _game._player._prepareWalkPos = Common::Point(106, 38); @@ -2638,7 +2637,7 @@ void Scene109::actions() { break; case OBJ_BURGER: - _hoovicDifficultFl = (_game._difficulty == DIFFICULTY_EASY); + _hoovicDifficultFl = (_game._difficulty == DIFFICULTY_HARD); _globals._spriteIndexes[8] = _scene->_sprites.addSprites(formAnimName('H', (_hoovicDifficultFl ? 3 : 1))); break; } diff --git a/engines/mads/nebular/nebular_scenes6.cpp b/engines/mads/nebular/nebular_scenes6.cpp index 046782b772..d94fb17fd4 100644 --- a/engines/mads/nebular/nebular_scenes6.cpp +++ b/engines/mads/nebular/nebular_scenes6.cpp @@ -948,8 +948,14 @@ void Scene604::actions() { _bombMode = 1; if ((_game._difficulty == DIFFICULTY_HARD) || _globals[kWarnedFloodCity]) handleBombActions(); - else if ((_game._objects.isInInventory(OBJ_POLYCEMENT) && _game._objects.isInInventory(OBJ_CHICKEN)) - && ((_globals[kLineStatus] == LINE_TIED) || ((_game._difficulty == DIFFICULTY_EASY) && (!_globals[kBoatRaised])))) + else if ( + (_game._objects.isInInventory(OBJ_POLYCEMENT) && (_game._objects.isInInventory(OBJ_CHICKEN) || _game._objects.isInInventory(OBJ_CHICKEN_BOMB))) + && (_globals[kLineStatus] == LINE_TIED || (_game._difficulty == DIFFICULTY_EASY && !_globals[kBoatRaised])) + ) + // The original can get in an impossible state at this point, if the player has + // combined the chicken with the bomb before placing the timer bomb on the ledge. + // Therefore, we also allow the player to place the bomb if the chicken bomb is + // in the inventory. handleBombActions(); else if (_game._difficulty == DIFFICULTY_EASY) _vm->_dialogs->show(60424); diff --git a/engines/mads/nebular/nebular_scenes8.cpp b/engines/mads/nebular/nebular_scenes8.cpp index 8ce559b82b..5f8417cee1 100644 --- a/engines/mads/nebular/nebular_scenes8.cpp +++ b/engines/mads/nebular/nebular_scenes8.cpp @@ -957,7 +957,7 @@ void Scene804::step() { _globals[kInSpace] = false; _globals[kBeamIsUp] = true; - assert(!_globals[kCopyProtectFailed]); + //assert(!_globals[kCopyProtectFailed]); _game._winStatus = 4; return; } diff --git a/engines/mads/nebular/sound_nebular.cpp b/engines/mads/nebular/sound_nebular.cpp index 6412654fd6..9716e6d522 100644 --- a/engines/mads/nebular/sound_nebular.cpp +++ b/engines/mads/nebular/sound_nebular.cpp @@ -44,6 +44,7 @@ AdlibChannel::AdlibChannel() { _field4 = 0; _sampleIndex = 0; _volume = 0; + _volumeOffset = 0; _field7 = 0; _field8 = 0; _field9 = 0; @@ -61,7 +62,6 @@ AdlibChannel::AdlibChannel() { _field19 = 0; _soundData = nullptr; _field1D = 0; - _field1E = 0; _field1F = 0; _field20 = 0; @@ -97,6 +97,7 @@ void AdlibChannel::setPtr2(byte *pData) { void AdlibChannel::load(byte *pData) { _ptr1 = _pSrc = _ptr3 = pData; _ptr4 = _soundData = pData; + _volumeOffset = 0; _fieldA = 0xFF; _activeCount = 1; _fieldD = 64; @@ -104,7 +105,7 @@ void AdlibChannel::load(byte *pData) { _field1F = 0; _field2 = _field3 = 0; _volume = _field7 = 0; - _field1D = _field1E = 0; + _field1D = 0; _fieldE = 0; _field9 = 0; _fieldB = 0; @@ -117,7 +118,7 @@ void AdlibChannel::load(byte *pData) { void AdlibChannel::check(byte *nullPtr) { if (_activeCount && _fieldE) { - if (!_field1E) { + if (!_volumeOffset) { _pSrc = nullPtr; _fieldE = 0; } else { @@ -166,6 +167,7 @@ ASound::ASound(Audio::Mixer *mixer, FM_OPL *opl, const Common::String &filename, _samplePtr = nullptr; _frameCounter = 0; _isDisabled = false; + _masterVolume = 255; _v1 = 0; _v2 = 0; _activeChannelNumber = 0; @@ -540,7 +542,7 @@ void ASound::pollActiveChannel() { chan->_field1 = 0; chan->_field2 = chan->_field3 = 0; chan->_volume = chan->_field7 = 0; - chan->_field1D = chan->_field1E = 0; + chan->_field1D = chan->_volumeOffset = 0; chan->_field8 = 0; chan->_field9 = 0; chan->_fieldB = 0; @@ -615,7 +617,7 @@ void ASound::pollActiveChannel() { if (chan->_fieldE) { chan->_pSrc += 2; } else { - chan->_field1E = *pSrc >> 1; + chan->_volumeOffset = *pSrc >> 1; updateFlag = true; chan->_pSrc += 2; } @@ -659,7 +661,7 @@ void ASound::pollActiveChannel() { if (!--chan->_field9) { chan->_field9 = chan->_fieldA; if (chan->_field2) { - int8 newVal = (int8)chan->_field2 + (int8)chan->_field1E; + int8 newVal = (int8)chan->_field2 + (int8)chan->_volumeOffset; if (newVal < 0) { chan->_field9 = 0; newVal = 0; @@ -668,7 +670,7 @@ void ASound::pollActiveChannel() { newVal = 63; } - chan->_field1E = newVal; + chan->_volumeOffset = newVal; updateFlag = true; } } @@ -755,7 +757,8 @@ static const int outputChannels[] = { void ASound::updateActiveChannel() { int reg = 0x40 + outputChannels[outputIndexes[_activeChannelNumber * 2 + 1]]; int portVal = _ports[reg] & 0xFFC0; - int newVolume = CLIP(_activeChannelPtr->_volume + _activeChannelPtr->_field1E, 0, 63); + int newVolume = CLIP(_activeChannelPtr->_volume + _activeChannelPtr->_volumeOffset, 0, 63); + newVolume = newVolume * _masterVolume / 255; // Note: Original had a whole block not seeming to be used, since the initialisation // sets a variable to 5660h, and doesn't change it, so the branch is never taken @@ -857,6 +860,12 @@ int ASound::readBuffer(int16 *buffer, const int numSamples) { return numSamples; } +void ASound::setVolume(int volume) { + _masterVolume = volume; + if (!volume) + command0(); +} + int ASound::command0() { bool isDisabled = _isDisabled; _isDisabled = true; @@ -1014,22 +1023,22 @@ int ASound1::command10() { int ASound1::command11() { command111213(); - _channels[0]._field1E = 0; - _channels[1]._field1E = 0; + _channels[0]._volumeOffset = 0; + _channels[1]._volumeOffset = 0; return 0; } int ASound1::command12() { command111213(); - _channels[0]._field1E = 40; - _channels[1]._field1E = 0; + _channels[0]._volumeOffset = 40; + _channels[1]._volumeOffset = 0; return 0; } int ASound1::command13() { command111213(); - _channels[0]._field1E = 40; - _channels[1]._field1E = 50; + _channels[0]._volumeOffset = 40; + _channels[1]._volumeOffset = 50; return 0; } diff --git a/engines/mads/nebular/sound_nebular.h b/engines/mads/nebular/sound_nebular.h index cfacb211a4..d2fc552eec 100644 --- a/engines/mads/nebular/sound_nebular.h +++ b/engines/mads/nebular/sound_nebular.h @@ -70,7 +70,7 @@ public: int _field19; byte *_soundData; int _field1D; - int _field1E; + int _volumeOffset; int _field1F; // TODO: Only used by asound.003. Figure out usage @@ -146,6 +146,7 @@ class ASound : public Audio::AudioStream { private: Common::List<CachedDataEntry> _dataCache; uint16 _randomSeed; + int _masterVolume; /** * Does the initial Adlib initialisation @@ -382,6 +383,11 @@ public: * Return sample rate */ virtual int getRate() const { return 11025; } + + /** + * Set the volume + */ + void setVolume(int volume); }; class ASound1 : public ASound { diff --git a/engines/mads/scene_data.cpp b/engines/mads/scene_data.cpp index d0e96be1d7..e48bcd8c6f 100644 --- a/engines/mads/scene_data.cpp +++ b/engines/mads/scene_data.cpp @@ -469,6 +469,7 @@ void SceneInfo::loadMadsV2Background(int sceneId, const Common::String &resName, for (int i = 0; i < tileIndex; i++) ++tile; ((*tile).get())->copyTo(&bgSurface, Common::Point(x * tileWidth, y * tileHeight)); + ((*tile).get())->free(); } } tileSet.clear(); diff --git a/engines/mads/sound.cpp b/engines/mads/sound.cpp index 1baa169c55..4036ee8112 100644 --- a/engines/mads/sound.cpp +++ b/engines/mads/sound.cpp @@ -36,6 +36,7 @@ SoundManager::SoundManager(MADSEngine *vm, Audio::Mixer *mixer) { _pollSoundEnabled = false; _soundPollFlag = false; _newSoundsPaused = false; + _masterVolume = 255; _opl = OPL::Config::create(); _opl->init(11025); @@ -97,15 +98,18 @@ void SoundManager::init(int sectionNumber) { break; default: _driver = nullptr; - break; + return; } break; default: warning("SoundManager: Unknown game"); _driver = nullptr; - break; + return; } + + // Set volume for newly loaded driver + _driver->setVolume(_masterVolume); } void SoundManager::closeDriver() { @@ -141,6 +145,13 @@ void SoundManager::startQueuedCommands() { } } +void SoundManager::setVolume(int volume) { + _masterVolume = volume; + + if (_driver) + _driver->setVolume(volume); +} + void SoundManager::command(int commandId, int param) { if (_newSoundsPaused) { if (_queuedCommands.size() < 8) diff --git a/engines/mads/sound.h b/engines/mads/sound.h index 72bb21a812..5884323474 100644 --- a/engines/mads/sound.h +++ b/engines/mads/sound.h @@ -43,6 +43,7 @@ private: bool _soundPollFlag; bool _newSoundsPaused; Common::Queue<int> _queuedCommands; + int _masterVolume; public: SoundManager(MADSEngine *vm, Audio::Mixer *mixer); ~SoundManager(); @@ -78,6 +79,11 @@ public: */ void startQueuedCommands(); + /** + * Set the master volume + */ + void setVolume(int volume); + //@{ /** * Executes a command on the sound driver diff --git a/engines/mads/sprites.cpp b/engines/mads/sprites.cpp index 67d5e20fe5..f15d6456d3 100644 --- a/engines/mads/sprites.cpp +++ b/engines/mads/sprites.cpp @@ -347,8 +347,10 @@ void SpriteSlots::drawSprites(MSurface *s) { spr->copyTo(s, Common::Point(xp, yp), sprite->getTransparencyIndex()); // Free sprite if it was a flipped one - if (flipped) + if (flipped) { + spr->free(); delete spr; + } } } } @@ -399,7 +401,7 @@ void SpriteSets::remove(int idx) { if (idx == SPRITE_SLOTS_MAX_SIZE) { delete _uiSprites; _uiSprites = nullptr; - } else if (idx >= 0) { + } else if (idx >= 0 && idx < (int)size()) { delete (*this)[idx]; if (idx < ((int)size() - 1)) { diff --git a/engines/mads/user_interface.cpp b/engines/mads/user_interface.cpp index 93a555d9c7..1e5a1d80d2 100644 --- a/engines/mads/user_interface.cpp +++ b/engines/mads/user_interface.cpp @@ -164,6 +164,7 @@ void UISlots::draw(bool updateFlag, bool delFlag) { MSurface *spr = sprite->flipHorizontal(); userInterface.mergeFrom(spr, spr->getBounds(), slot._position, sprite->getTransparencyIndex()); + spr->free(); delete spr; } else { userInterface.mergeFrom(sprite, sprite->getBounds(), slot._position, |