TOLTECS: Implement volume handling and toggling of speech/text

This commit is contained in:
Filippos Karapetis 2012-09-10 21:53:00 +03:00
parent 4a5333893d
commit 72cdd019fc
9 changed files with 106 additions and 113 deletions

View file

@ -21,8 +21,11 @@
* *
*/ */
#include "audio/mixer.h"
#include "common/savefile.h" #include "common/savefile.h"
#include "common/config-manager.h"
#include "toltecs/toltecs.h" #include "toltecs/toltecs.h"
#include "toltecs/menu.h" #include "toltecs/menu.h"
#include "toltecs/palette.h" #include "toltecs/palette.h"
@ -53,14 +56,8 @@ int MenuSystem::run() {
_newMenuID = kMenuIdMain; _newMenuID = kMenuIdMain;
_currItemID = kItemIdNone; _currItemID = kItemIdNone;
_editingDescription = false; _editingDescription = false;
_cfgText = true;
_cfgVoices = true; _running = true;
_cfgMasterVolume = 10;
_cfgVoicesVolume = 10;
_cfgMusicVolume = 10;
_cfgSoundFXVolume = 10;
_cfgBackgroundVolume = 10;
_running = true;
_top = 30 - _vm->_guiHeight / 2; _top = 30 - _vm->_guiHeight / 2;
_needRedraw = false; _needRedraw = false;
@ -241,8 +238,8 @@ void MenuSystem::initMenu(MenuID menuID) {
drawString(0, 74, 320, 1, 229, _vm->getSysString(kStrWhatCanIDoForYou)); drawString(0, 74, 320, 1, 229, _vm->getSysString(kStrWhatCanIDoForYou));
addClickTextItem(kItemIdLoad, 0, 115, 320, 0, _vm->getSysString(kStrLoad), 229, 255); addClickTextItem(kItemIdLoad, 0, 115, 320, 0, _vm->getSysString(kStrLoad), 229, 255);
addClickTextItem(kItemIdSave, 0, 135, 320, 0, _vm->getSysString(kStrSave), 229, 255); addClickTextItem(kItemIdSave, 0, 135, 320, 0, _vm->getSysString(kStrSave), 229, 255);
addClickTextItem(kItemIdToggleText, 0, 165, 320, 0, _vm->getSysString(kStrTextOn), 229, 255); addClickTextItem(kItemIdToggleText, 0, 165, 320, 0, _vm->getSysString(_vm->_cfgText ? kStrTextOn : kStrTextOff), 229, 255);
addClickTextItem(kItemIdToggleVoices, 0, 185, 320, 0, _vm->getSysString(kStrVoicesOn), 229, 255); addClickTextItem(kItemIdToggleVoices, 0, 185, 320, 0, _vm->getSysString(_vm->_cfgVoices ? kStrVoicesOn : kStrVoicesOff), 229, 255);
addClickTextItem(kItemIdVolumesMenu, 0, 215, 320, 0, _vm->getSysString(kStrVolume), 229, 255); addClickTextItem(kItemIdVolumesMenu, 0, 215, 320, 0, _vm->getSysString(kStrVolume), 229, 255);
addClickTextItem(kItemIdPlay, 0, 245, 320, 0, _vm->getSysString(kStrPlay), 229, 255); addClickTextItem(kItemIdPlay, 0, 245, 320, 0, _vm->getSysString(kStrPlay), 229, 255);
addClickTextItem(kItemIdQuit, 0, 275, 320, 0, _vm->getSysString(kStrQuit), 229, 255); addClickTextItem(kItemIdQuit, 0, 275, 320, 0, _vm->getSysString(kStrQuit), 229, 255);
@ -326,13 +323,13 @@ void MenuSystem::clickItem(ItemID id) {
_newMenuID = kMenuIdLoad; _newMenuID = kMenuIdLoad;
break; break;
case kItemIdToggleText: case kItemIdToggleText:
setCfgText(!_cfgText, true); setCfgText(!_vm->_cfgText, true);
if (!_cfgVoices && !_cfgText) if (!_vm->_cfgVoices && !_vm->_cfgText)
setCfgVoices(true, false); setCfgVoices(true, false);
break; break;
case kItemIdToggleVoices: case kItemIdToggleVoices:
setCfgVoices(!_cfgVoices, true); setCfgVoices(!_vm->_cfgVoices, true);
if (!_cfgVoices && !_cfgText) if (!_vm->_cfgVoices && !_vm->_cfgText)
setCfgText(true, false); setCfgText(true, false);
break; break;
case kItemIdVolumesMenu: case kItemIdVolumesMenu:
@ -518,22 +515,24 @@ void MenuSystem::clickSavegameItem(ItemID id) {
} }
void MenuSystem::setCfgText(bool value, bool active) { void MenuSystem::setCfgText(bool value, bool active) {
if (_cfgText != value) { if (_vm->_cfgText != value) {
Item *item = getItem(kItemIdToggleText); Item *item = getItem(kItemIdToggleText);
_cfgText = value; _vm->_cfgText = value;
restoreRect(item->rect.left, item->rect.top, item->rect.width() + 1, item->rect.height() - 2); restoreRect(item->rect.left, item->rect.top, item->rect.width() + 1, item->rect.height() - 2);
setItemCaption(item, _vm->getSysString(_cfgText ? kStrTextOn : kStrTextOff)); setItemCaption(item, _vm->getSysString(_vm->_cfgText ? kStrTextOn : kStrTextOff));
drawItem(kItemIdToggleText, true); drawItem(kItemIdToggleText, true);
ConfMan.setBool("subtitles", value);
} }
} }
void MenuSystem::setCfgVoices(bool value, bool active) { void MenuSystem::setCfgVoices(bool value, bool active) {
if (_cfgVoices != value) { if (_vm->_cfgVoices != value) {
Item *item = getItem(kItemIdToggleVoices); Item *item = getItem(kItemIdToggleVoices);
_cfgVoices = value; _vm->_cfgVoices = value;
restoreRect(item->rect.left, item->rect.top, item->rect.width() + 1, item->rect.height() - 2); restoreRect(item->rect.left, item->rect.top, item->rect.width() + 1, item->rect.height() - 2);
setItemCaption(item, _vm->getSysString(_cfgVoices ? kStrVoicesOn : kStrVoicesOff)); setItemCaption(item, _vm->getSysString(_vm->_cfgVoices ? kStrVoicesOn : kStrVoicesOff));
drawItem(kItemIdToggleVoices, true); drawItem(kItemIdToggleVoices, true);
ConfMan.setBool("speech_mute", !value);
} }
} }
@ -542,25 +541,25 @@ void MenuSystem::drawVolumeBar(ItemID itemID) {
char text[21]; char text[21];
switch (itemID) { switch (itemID) {
case kItemIdMaster: case kItemIdMaster: // unused in ScummVM, always 20
y = 130 + 25 * 0; y = 130 + 25 * 0;
volume = _cfgMasterVolume; volume = 20;
break; break;
case kItemIdVoices: case kItemIdVoices:
y = 130 + 25 * 1; y = 130 + 25 * 1;
volume = _cfgVoicesVolume; volume = _vm->_cfgVoicesVolume;
break; break;
case kItemIdMusic: case kItemIdMusic:
y = 130 + 25 * 2; y = 130 + 25 * 2;
volume = _cfgMusicVolume; volume = _vm->_cfgMusicVolume;
break; break;
case kItemIdSoundFX: case kItemIdSoundFX:
y = 130 + 25 * 3; y = 130 + 25 * 3;
volume = _cfgSoundFXVolume; volume = _vm->_cfgSoundFXVolume;
break; break;
case kItemIdBackground: case kItemIdBackground: // unused in ScummVM, always 20
y = 130 + 25 * 4; y = 130 + 25 * 4;
volume = _cfgBackgroundVolume; volume = 20;
break; break;
default: default:
return; return;
@ -578,36 +577,37 @@ void MenuSystem::drawVolumeBar(ItemID itemID) {
} }
void MenuSystem::changeVolumeBar(ItemID itemID, int delta) { void MenuSystem::changeVolumeBar(ItemID itemID, int delta) {
byte newVolume;
int *volume, newVolume;
switch (itemID) { switch (itemID) {
case kItemIdMaster:
volume = &_cfgMasterVolume;
break;
case kItemIdVoices: case kItemIdVoices:
volume = &_cfgVoicesVolume; _vm->_cfgVoicesVolume = CLIP(_vm->_cfgVoicesVolume + delta, 0, 20);
newVolume = ceil((double)_vm->_cfgVoicesVolume * Audio::Mixer::kMaxChannelVolume / 20);
_vm->_mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, newVolume);
ConfMan.setInt("speech_volume", newVolume);
break; break;
case kItemIdMusic: case kItemIdMusic:
volume = &_cfgMusicVolume; _vm->_cfgMusicVolume = CLIP(_vm->_cfgMusicVolume + delta, 0, 20);
newVolume = ceil((double)_vm->_cfgMusicVolume * Audio::Mixer::kMaxChannelVolume / 20);
_vm->_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, newVolume);
ConfMan.setInt("music_volume", newVolume);
break; break;
case kItemIdSoundFX: case kItemIdSoundFX:
volume = &_cfgSoundFXVolume; _vm->_cfgSoundFXVolume = CLIP(_vm->_cfgSoundFXVolume + delta, 0, 20);
newVolume = ceil((double)_vm->_cfgSoundFXVolume * Audio::Mixer::kMaxChannelVolume / 20);
_vm->_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, newVolume);
ConfMan.setInt("sfx_volume", newVolume);
break; break;
case kItemIdMaster:
case kItemIdBackground: case kItemIdBackground:
volume = &_cfgBackgroundVolume; // unused in ScummVM
break; break;
default: default:
return; return;
} }
newVolume = CLIP(*volume + delta, 0, 20); _vm->syncSoundSettings();
drawVolumeBar(itemID);
if (newVolume != *volume) {
*volume = newVolume;
drawVolumeBar(itemID);
}
} }
} // End of namespace Toltecs } // End of namespace Toltecs

View file

@ -125,9 +125,6 @@ protected:
Common::Array<Item> _items; Common::Array<Item> _items;
Common::Array<SavegameItem> _savegames; Common::Array<SavegameItem> _savegames;
bool _cfgText, _cfgVoices;
int _cfgMasterVolume, _cfgVoicesVolume, _cfgMusicVolume, _cfgSoundFXVolume, _cfgBackgroundVolume;
void addClickTextItem(ItemID id, int x, int y, int w, uint fontNum, const char *caption, byte defaultColor, byte activeColor); void addClickTextItem(ItemID id, int x, int y, int w, uint fontNum, const char *caption, byte defaultColor, byte activeColor);
void drawItem(ItemID itemID, bool active); void drawItem(ItemID itemID, bool active);

View file

@ -20,15 +20,13 @@
* *
*/ */
// FIXME: This code is taken from SAGA and needs more work (e.g. setVolume). #include "audio/midiparser.h"
#include "common/textconsole.h"
#include "toltecs/toltecs.h" #include "toltecs/toltecs.h"
#include "toltecs/music.h" #include "toltecs/music.h"
#include "toltecs/resource.h" #include "toltecs/resource.h"
#include "audio/midiparser.h"
#include "common/textconsole.h"
namespace Toltecs { namespace Toltecs {
MusicPlayer::MusicPlayer(bool isGM) : _isGM(isGM), _buffer(NULL) { MusicPlayer::MusicPlayer(bool isGM) : _isGM(isGM), _buffer(NULL) {
@ -77,7 +75,7 @@ void MusicPlayer::playMIDI(const byte *data, uint32 size, bool loop) {
_parser = parser; _parser = parser;
setVolume(127); syncVolume();
_isLooping = loop; _isLooping = loop;
_isPlaying = true; _isPlaying = true;
@ -86,16 +84,6 @@ void MusicPlayer::playMIDI(const byte *data, uint32 size, bool loop) {
} }
} }
void MusicPlayer::pause() {
setVolume(-1);
_isPlaying = false;
}
void MusicPlayer::resume() {
setVolume(127);
_isPlaying = true;
}
void MusicPlayer::stopAndClear() { void MusicPlayer::stopAndClear() {
Common::StackLock lock(_mutex); Common::StackLock lock(_mutex);
stop(); stop();

View file

@ -37,8 +37,6 @@ public:
MusicPlayer(bool isGM = true); MusicPlayer(bool isGM = true);
void playMIDI(const byte *data, uint32 size, bool loop = false); void playMIDI(const byte *data, uint32 size, bool loop = false);
void pause();
void resume();
void stopAndClear(); void stopAndClear();
// MidiDriver_BASE interface implementation // MidiDriver_BASE interface implementation

View file

@ -469,7 +469,6 @@ void Screen::addTalkTextRect(Font &font, int16 x, int16 &y, int16 length, int16
} }
void Screen::addTalkTextItemsToRenderQueue() { void Screen::addTalkTextItemsToRenderQueue() {
for (int16 i = 0; i <= _talkTextItemNum; i++) { for (int16 i = 0; i <= _talkTextItemNum; i++) {
TalkTextItem *item = &_talkTextItems[i]; TalkTextItem *item = &_talkTextItems[i];
byte *text = _vm->_script->getSlotData(item->slotIndex) + item->slotOffset; byte *text = _vm->_script->getSlotData(item->slotIndex) + item->slotOffset;
@ -482,14 +481,15 @@ void Screen::addTalkTextItemsToRenderQueue() {
if (item->duration < 0) if (item->duration < 0)
item->duration = 0; item->duration = 0;
if (!_vm->_cfgText)
return;
for (byte j = 0; j < item->lineCount; j++) { for (byte j = 0; j < item->lineCount; j++) {
_renderQueue->addText(item->lines[j].x, item->lines[j].y, item->color, _fontResIndexArray[item->fontNum], _renderQueue->addText(item->lines[j].x, item->lines[j].y, item->color,
text, item->lines[j].length); _fontResIndexArray[item->fontNum], text, item->lines[j].length);
text += item->lines[j].length; text += item->lines[j].length;
} }
} }
} }
int16 Screen::getTalkTextDuration() { int16 Screen::getTalkTextDuration() {

View file

@ -44,39 +44,23 @@ Sound::~Sound() {
void Sound::playSpeech(int16 resIndex) { void Sound::playSpeech(int16 resIndex) {
debug(0, "playSpeech(%d)", resIndex); debug(0, "playSpeech(%d)", resIndex);
internalPlaySound(resIndex, kChannelTypeSpeech, 50 /*TODO*/, 0);
if (_vm->_cfgVoices)
internalPlaySound(resIndex, kChannelTypeSpeech, 50 /*TODO*/, 0);
} }
void Sound::playSound(int16 resIndex, int16 type, int16 volume) { void Sound::playSound(int16 resIndex, int16 type, int16 volume) {
// TODO: Use the right volumes
debug(0, "playSound(%d, %d, %d)", resIndex, type, volume); debug(0, "playSound(%d, %d, %d)", resIndex, type, volume);
if (volume == -1 || type == -2) { internalPlaySound(resIndex, type, volume, 0);
if (type == kChannelTypeBackground) {
internalPlaySound(resIndex, type, 50 /*TODO*/, 0);
} else {
internalPlaySound(resIndex, type, 100 /*TODO*/, 0);
}
} else {
internalPlaySound(resIndex, type, 100 /*TODO*/, 0);
}
} }
void Sound::playSoundAtPos(int16 resIndex, int16 x, int16 y) { void Sound::playSoundAtPos(int16 resIndex, int16 x, int16 y) {
debug(0, "playSoundAtPos(%d, %d, %d)", resIndex, x, y); debug(0, "playSoundAtPos(%d, %d, %d)", resIndex, x, y);
int16 volume, panning = 0, deltaX = 0; int16 volume = 50 + ABS(_vm->_segmap->getScalingAtPoint(x, y)) / 2;
int8 scaling = _vm->_segmap->getScalingAtPoint(x, y); int16 panning = 0, deltaX = 0;
if (scaling >= 0)
volume = 50 + ABS(scaling) / 2;
else
volume = 50 - ABS(scaling) / 2;
if (_vm->_cameraX > x) if (_vm->_cameraX > x)
deltaX = _vm->_cameraX - x; deltaX = _vm->_cameraX - x;
else if (_vm->_cameraX + 640 < x) else if (_vm->_cameraX + 640 < x)
@ -91,11 +75,12 @@ void Sound::playSoundAtPos(int16 resIndex, int16 x, int16 y) {
} }
internalPlaySound(resIndex, 1, volume, panning); internalPlaySound(resIndex, 1, volume, panning);
} }
void Sound::internalPlaySound(int16 resIndex, int16 type, int16 volume, int16 panning) { void Sound::internalPlaySound(int16 resIndex, int16 type, int16 volume, int16 panning) {
// Change the game's sound volume (0 - 100) to Scummvm's scale (0 - 255)
volume = (volume == -1) ? 255 : volume * 255 / 100;
if (resIndex == -1) { if (resIndex == -1) {
// Stop all sounds // Stop all sounds
_vm->_mixer->stopAll(); _vm->_mixer->stopAll();
@ -142,14 +127,10 @@ void Sound::internalPlaySound(int16 resIndex, int16 type, int16 volume, int16 pa
channels[freeChannel].type = type; channels[freeChannel].type = type;
channels[freeChannel].resIndex = resIndex; channels[freeChannel].resIndex = resIndex;
Audio::Mixer::SoundType soundType = Audio::Mixer::kPlainSoundType; Audio::Mixer::SoundType soundType = getScummVMSoundType((SoundChannelType)type);
/*
switch (type) {
}
*/
_vm->_mixer->playStream(soundType, &channels[freeChannel].handle, _vm->_mixer->playStream(soundType, &channels[freeChannel].handle,
stream, -1, volume, panning); stream, -1, volume, panning);
} }
} }
@ -206,11 +187,7 @@ void Sound::loadState(Common::ReadStream *in) {
DisposeAfterUse::NO), DisposeAfterUse::NO),
channels[i].type == kChannelTypeBackground ? 0 : 1); channels[i].type == kChannelTypeBackground ? 0 : 1);
Audio::Mixer::SoundType soundType = Audio::Mixer::kPlainSoundType; Audio::Mixer::SoundType soundType = getScummVMSoundType((SoundChannelType)channels[i].type);
/*
switch (type) {
}
*/
// TODO: Volume and panning // TODO: Volume and panning
int16 volume = (channels[i].type == kChannelTypeBackground) ? 50 : 100; int16 volume = (channels[i].type == kChannelTypeBackground) ? 50 : 100;
@ -221,4 +198,18 @@ void Sound::loadState(Common::ReadStream *in) {
} }
} }
Audio::Mixer::SoundType Sound::getScummVMSoundType(SoundChannelType type) const {
switch (type) {
case kChannelTypeBackground:
case kChannelTypeSfx:
return Audio::Mixer::kSFXSoundType;
case kChannelTypeSpeech:
return Audio::Mixer::kSpeechSoundType;
break;
default:
return Audio::Mixer::kSFXSoundType;
break;
}
}
} // End of namespace Toltecs } // End of namespace Toltecs

View file

@ -68,7 +68,7 @@ protected:
SoundChannel channels[kMaxChannels]; SoundChannel channels[kMaxChannels];
void internalPlaySound(int16 resIndex, int16 type, int16 volume, int16 panning); void internalPlaySound(int16 resIndex, int16 type, int16 volume, int16 panning);
Audio::Mixer::SoundType getScummVMSoundType(SoundChannelType type) const;
}; };

View file

@ -62,11 +62,6 @@ struct GameSettings {
}; };
ToltecsEngine::ToltecsEngine(OSystem *syst, const ToltecsGameDescription *gameDesc) : Engine(syst), _gameDescription(gameDesc) { ToltecsEngine::ToltecsEngine(OSystem *syst, const ToltecsGameDescription *gameDesc) : Engine(syst), _gameDescription(gameDesc) {
// Setup mixer
_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume"));
_rnd = new Common::RandomSource("toltecs"); _rnd = new Common::RandomSource("toltecs");
} }
@ -129,14 +124,24 @@ Common::Error ToltecsEngine::run() {
_sound = new Sound(this); _sound = new Sound(this);
_cfgText = ConfMan.getBool("subtitles");
_cfgVoices = !ConfMan.getBool("speech_mute");
bool mute = false;
if (ConfMan.hasKey("mute"))
mute = ConfMan.getBool("mute");
_mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, mute ? 0 : ConfMan.getInt("speech_volume"));
_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, mute ? 0 : ConfMan.getInt("music_volume"));
_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, mute ? 0 : ConfMan.getInt("sfx_volume"));
syncSoundSettings(); syncSoundSettings();
CursorMan.showMouse(true); CursorMan.showMouse(true);
setupSysStrings(); setupSysStrings();
//#define TEST_MENU #if 0
#ifdef TEST_MENU // Menu test
_screen->registerFont(0, 0x0D); _screen->registerFont(0, 0x0D);
_screen->registerFont(1, 0x0E); _screen->registerFont(1, 0x0E);
_screen->loadMouseCursor(12); _screen->loadMouseCursor(12);
@ -321,7 +326,6 @@ void ToltecsEngine::updateInput() {
//debug("key: flags = %02X; keycode = %d", _keyState.flags, _keyState.keycode); //debug("key: flags = %02X; keycode = %d", _keyState.flags, _keyState.keycode);
// FIXME: This is just for debugging
switch (event.kbd.keycode) { switch (event.kbd.keycode) {
case Common::KEYCODE_F7: case Common::KEYCODE_F7:
savegame("toltecs.001", "Quicksave"); savegame("toltecs.001", "Quicksave");
@ -638,4 +642,16 @@ int16 ToltecsEngine::findRectAtPoint(byte *rectData, int16 x, int16 y, int16 ind
} }
void ToltecsEngine::syncSoundSettings() {
Engine::syncSoundSettings();
bool mute = false;
if (ConfMan.hasKey("mute"))
mute = ConfMan.getBool("mute");
_cfgVoicesVolume = (mute ? 0 : ConfMan.getInt("speech_volume")) * 20 / Audio::Mixer::kMaxChannelVolume;
_cfgMusicVolume = (mute ? 0 : ConfMan.getInt("music_volume")) * 20 / Audio::Mixer::kMaxChannelVolume;
_cfgSoundFXVolume = (mute ? 0 : ConfMan.getInt("sfx_volume")) * 20 / Audio::Mixer::kMaxChannelVolume;
}
} // End of namespace Toltecs } // End of namespace Toltecs

View file

@ -99,6 +99,7 @@ public:
uint32 getFeatures() const; uint32 getFeatures() const;
Common::Language getLanguage() const; Common::Language getLanguage() const;
const Common::String& getTargetName() const { return _targetName; } const Common::String& getTargetName() const { return _targetName; }
void syncSoundSettings();
void setupSysStrings(); void setupSysStrings();
void requestSavegame(int slotNum, Common::String &description); void requestSavegame(int slotNum, Common::String &description);
@ -127,6 +128,8 @@ public:
int16 findRectAtPoint(byte *rectData, int16 x, int16 y, int16 index, int16 itemSize, int16 findRectAtPoint(byte *rectData, int16 x, int16 y, int16 index, int16 itemSize,
byte *rectDataEnd); byte *rectDataEnd);
int _cfgVoicesVolume, _cfgMusicVolume, _cfgSoundFXVolume;
bool _cfgText, _cfgVoices;
public: public:
AnimationPlayer *_anim; AnimationPlayer *_anim;