aboutsummaryrefslogtreecommitdiff
path: root/engines/mads
diff options
context:
space:
mode:
authorWillem Jan Palenstijn2015-05-07 23:35:36 +0200
committerWillem Jan Palenstijn2015-05-07 23:35:36 +0200
commit57109ef0a8d30f15aa1fcef7d9d229fc9701f630 (patch)
tree230c0a7822875e9c41a4606fce54166d4dc37db0 /engines/mads
parentd9e93f8e015ce27a95090e854494c4b3f7d1c0d4 (diff)
parent04931d040085d77d031290fda57ca2c5dc486f54 (diff)
downloadscummvm-rg350-57109ef0a8d30f15aa1fcef7d9d229fc9701f630.tar.gz
scummvm-rg350-57109ef0a8d30f15aa1fcef7d9d229fc9701f630.tar.bz2
scummvm-rg350-57109ef0a8d30f15aa1fcef7d9d229fc9701f630.zip
Merge branch 'master' into sherlock
Diffstat (limited to 'engines/mads')
-rw-r--r--engines/mads/detection_tables.h4
-rw-r--r--engines/mads/dialogs.cpp1
-rw-r--r--engines/mads/events.cpp2
-rw-r--r--engines/mads/game.cpp3
-rw-r--r--engines/mads/mads.cpp7
-rw-r--r--engines/mads/menu_views.cpp5
-rw-r--r--engines/mads/messages.cpp8
-rw-r--r--engines/mads/nebular/dialogs_nebular.cpp56
-rw-r--r--engines/mads/nebular/dialogs_nebular.h3
-rw-r--r--engines/mads/nebular/game_nebular.cpp65
-rw-r--r--engines/mads/nebular/nebular_scenes1.cpp11
-rw-r--r--engines/mads/nebular/nebular_scenes6.cpp10
-rw-r--r--engines/mads/nebular/nebular_scenes8.cpp2
-rw-r--r--engines/mads/nebular/sound_nebular.cpp37
-rw-r--r--engines/mads/nebular/sound_nebular.h8
-rw-r--r--engines/mads/scene_data.cpp1
-rw-r--r--engines/mads/sound.cpp15
-rw-r--r--engines/mads/sound.h6
-rw-r--r--engines/mads/sprites.cpp6
-rw-r--r--engines/mads/user_interface.cpp1
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,