diff options
author | Paul Gilbert | 2012-10-31 09:34:38 +1100 |
---|---|---|
committer | Paul Gilbert | 2012-10-31 09:34:38 +1100 |
commit | 798ddfaab500bb212f620cf095328eee5eb140a4 (patch) | |
tree | 55b5d0b90affd88063c04b7ff62fea1616b83e80 /engines/toltecs | |
parent | ef663f95a516d8fe47a245653d418c047361281a (diff) | |
parent | fdc80fd952120ecb8a4941edd4c2e404cdc5fa33 (diff) | |
download | scummvm-rg350-798ddfaab500bb212f620cf095328eee5eb140a4.tar.gz scummvm-rg350-798ddfaab500bb212f620cf095328eee5eb140a4.tar.bz2 scummvm-rg350-798ddfaab500bb212f620cf095328eee5eb140a4.zip |
Merge branch 'master' into hopkins
Diffstat (limited to 'engines/toltecs')
-rw-r--r-- | engines/toltecs/animation.cpp | 14 | ||||
-rw-r--r-- | engines/toltecs/animation.h | 2 | ||||
-rw-r--r-- | engines/toltecs/menu.cpp | 110 | ||||
-rw-r--r-- | engines/toltecs/menu.h | 21 | ||||
-rw-r--r-- | engines/toltecs/microtiles.cpp | 2 | ||||
-rw-r--r-- | engines/toltecs/movie.cpp | 58 | ||||
-rw-r--r-- | engines/toltecs/movie.h | 8 | ||||
-rw-r--r-- | engines/toltecs/music.cpp | 20 | ||||
-rw-r--r-- | engines/toltecs/music.h | 2 | ||||
-rw-r--r-- | engines/toltecs/palette.cpp | 18 | ||||
-rw-r--r-- | engines/toltecs/palette.h | 2 | ||||
-rw-r--r-- | engines/toltecs/render.cpp | 14 | ||||
-rw-r--r-- | engines/toltecs/render.h | 4 | ||||
-rw-r--r-- | engines/toltecs/resource.cpp | 8 | ||||
-rw-r--r-- | engines/toltecs/saveload.cpp | 17 | ||||
-rw-r--r-- | engines/toltecs/screen.cpp | 49 | ||||
-rw-r--r-- | engines/toltecs/screen.h | 19 | ||||
-rw-r--r-- | engines/toltecs/script.cpp | 41 | ||||
-rw-r--r-- | engines/toltecs/script.h | 6 | ||||
-rw-r--r-- | engines/toltecs/segmap.cpp | 20 | ||||
-rw-r--r-- | engines/toltecs/segmap.h | 8 | ||||
-rw-r--r-- | engines/toltecs/sound.cpp | 107 | ||||
-rw-r--r-- | engines/toltecs/sound.h | 7 | ||||
-rw-r--r-- | engines/toltecs/sprite.cpp | 20 | ||||
-rw-r--r-- | engines/toltecs/toltecs.cpp | 82 | ||||
-rw-r--r-- | engines/toltecs/toltecs.h | 23 |
26 files changed, 347 insertions, 335 deletions
diff --git a/engines/toltecs/animation.cpp b/engines/toltecs/animation.cpp index eef9cef9ed..084332cf83 100644 --- a/engines/toltecs/animation.cpp +++ b/engines/toltecs/animation.cpp @@ -53,7 +53,7 @@ void AnimationPlayer::start(uint resIndex) { _vm->_arc->closeResource(); debug(1, "AnimationPlayer::start() width = %d; height = %d; frameCount = %d", _width, _height, _frameCount); - + _vm->_sceneWidth = _width; _vm->_sceneHeight = _height; @@ -63,7 +63,7 @@ void AnimationPlayer::start(uint resIndex) { _frameNumber = 0; // TODO mov screenFlag01, 0FFFFh // TODO mov animDrawFrameFlag, 0FFFFh - + _firstNextFrameOffset = _nextFrameOffset; _firstCurFrameSize = _curFrameSize; _firstNextFrameSize = _nextFrameSize; @@ -81,25 +81,25 @@ void AnimationPlayer::nextFrame() { } else { _frameNumber++; } - + debug(1, "AnimationPlayer::nextFrame() frameNumber = %d", _frameNumber); if (_keepFrameCounter > 0) { _keepFrameCounter--; return; } - + _vm->_arc->openResource(_resIndex); _vm->_arc->seek(_nextFrameOffset, SEEK_CUR); _curFrameSize = _nextFrameSize; - + if (_curFrameSize == 0) _curFrameSize = 1; - + _vm->_arc->read(_animBuffer, _curFrameSize); _nextFrameSize = _vm->_arc->readUint32LE(); _nextFrameOffset += _curFrameSize + 4; - + if (_curFrameSize > 1) { unpackFrame(); // TODO mov animDrawFrameFlag, 0FFFFh diff --git a/engines/toltecs/animation.h b/engines/toltecs/animation.h index 22576d7535..54ec5d8afa 100644 --- a/engines/toltecs/animation.h +++ b/engines/toltecs/animation.h @@ -54,7 +54,7 @@ public: uint16 _width, _height; uint16 _frameNumber, _frameCount; uint32 _keepFrameCounter; - + uint32 _curFrameSize; uint32 _nextFrameSize, _nextFrameOffset; diff --git a/engines/toltecs/menu.cpp b/engines/toltecs/menu.cpp index 415f19ca31..6e23ff988f 100644 --- a/engines/toltecs/menu.cpp +++ b/engines/toltecs/menu.cpp @@ -21,8 +21,11 @@ * */ +#include "audio/mixer.h" #include "common/savefile.h" +#include "common/config-manager.h" + #include "toltecs/toltecs.h" #include "toltecs/menu.h" #include "toltecs/palette.h" @@ -37,7 +40,7 @@ MenuSystem::MenuSystem(ToltecsEngine *vm) : _vm(vm) { MenuSystem::~MenuSystem() { } -int MenuSystem::run() { +int MenuSystem::run(MenuID menuId) { //debug("MenuSystem::run()"); @@ -50,18 +53,13 @@ int MenuSystem::run() { memcpy(backgroundOrig.getBasePtr(0,0), _vm->_screen->_frontScreen, 640 * 400); _currMenuID = kMenuIdNone; - _newMenuID = kMenuIdMain; + _newMenuID = menuId; _currItemID = kItemIdNone; _editingDescription = false; - _cfgText = true; - _cfgVoices = true; - _cfgMasterVolume = 10; - _cfgVoicesVolume = 10; - _cfgMusicVolume = 10; - _cfgSoundFXVolume = 10; - _cfgBackgroundVolume = 10; - _running = true; + + _running = true; _top = 30 - _vm->_guiHeight / 2; + _needRedraw = false; // TODO: buildColorTransTable2 @@ -78,7 +76,7 @@ int MenuSystem::run() { update(); _vm->_system->updateScreen(); } - + // Restore original background memcpy(_vm->_screen->_frontScreen, backgroundOrig.getBasePtr(0,0), 640 * 400); _vm->_system->copyRectToScreen(_vm->_screen->_frontScreen, 640, 0, 0, 640, 400); @@ -89,7 +87,7 @@ int MenuSystem::run() { _background->free(); delete _background; - return 0; + return 0; } void MenuSystem::update() { @@ -104,7 +102,7 @@ void MenuSystem::update() { if (_needRedraw) { //_vm->_system->copyRectToScreen(_vm->_screen->_frontScreen + 39 * 640 + 60, 640, 60, 39, 520, 247); - _vm->_system->copyRectToScreen(_vm->_screen->_frontScreen, 640, 0, 0, 640, 400); + _vm->_system->copyRectToScreen(_vm->_screen->_frontScreen, 640, 0, _top, 640, 400 - _top); //debug("redraw"); _needRedraw = false; } @@ -204,7 +202,7 @@ void MenuSystem::handleKeyDown(const Common::KeyState& kbd) { ItemID MenuSystem::findItemAt(int x, int y) { for (Common::Array<Item>::iterator iter = _items.begin(); iter != _items.end(); iter++) { - if ((*iter).rect.contains(x, y)) + if ((*iter).rect.contains(x, y - _top)) return (*iter).id; } return kItemIdNone; @@ -241,8 +239,8 @@ void MenuSystem::initMenu(MenuID menuID) { drawString(0, 74, 320, 1, 229, _vm->getSysString(kStrWhatCanIDoForYou)); addClickTextItem(kItemIdLoad, 0, 115, 320, 0, _vm->getSysString(kStrLoad), 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(kItemIdToggleVoices, 0, 185, 320, 0, _vm->getSysString(kStrVoicesOn), 229, 255); + addClickTextItem(kItemIdToggleText, 0, 165, 320, 0, _vm->getSysString(_vm->_cfgText ? kStrTextOn : kStrTextOff), 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(kItemIdPlay, 0, 245, 320, 0, _vm->getSysString(kStrPlay), 229, 255); addClickTextItem(kItemIdQuit, 0, 275, 320, 0, _vm->getSysString(kStrQuit), 229, 255); @@ -326,13 +324,13 @@ void MenuSystem::clickItem(ItemID id) { _newMenuID = kMenuIdLoad; break; case kItemIdToggleText: - setCfgText(!_cfgText, true); - if (!_cfgVoices && !_cfgText) + setCfgText(!_vm->_cfgText, true); + if (!_vm->_cfgVoices && !_vm->_cfgText) setCfgVoices(true, false); break; case kItemIdToggleVoices: - setCfgVoices(!_cfgVoices, true); - if (!_cfgVoices && !_cfgText) + setCfgVoices(!_vm->_cfgVoices, true); + if (!_vm->_cfgVoices && !_vm->_cfgText) setCfgText(true, false); break; case kItemIdVolumesMenu: @@ -416,7 +414,7 @@ void MenuSystem::restoreRect(int x, int y, int w, int h) { } void MenuSystem::shadeRect(int x, int y, int w, int h, byte color1, byte color2) { - byte *src = (byte *)_background->getBasePtr(x, y); + byte *src = (byte *)_vm->_screen->_frontScreen + x + y * 640; for (int xc = 0; xc < w; xc++) { src[xc] = color2; src[xc + h * 640] = color1; @@ -518,49 +516,51 @@ void MenuSystem::clickSavegameItem(ItemID id) { } void MenuSystem::setCfgText(bool value, bool active) { - if (_cfgText != value) { + if (_vm->_cfgText != value) { Item *item = getItem(kItemIdToggleText); - _cfgText = value; + _vm->_cfgText = value; 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); + ConfMan.setBool("subtitles", value); } } void MenuSystem::setCfgVoices(bool value, bool active) { - if (_cfgVoices != value) { + if (_vm->_cfgVoices != value) { Item *item = getItem(kItemIdToggleVoices); - _cfgVoices = value; + _vm->_cfgVoices = value; 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); + ConfMan.setBool("speech_mute", !value); } } void MenuSystem::drawVolumeBar(ItemID itemID) { int w = 440, y, volume; char text[21]; - + switch (itemID) { - case kItemIdMaster: + case kItemIdMaster: // unused in ScummVM, always 20 y = 130 + 25 * 0; - volume = _cfgMasterVolume; + volume = 20; break; case kItemIdVoices: y = 130 + 25 * 1; - volume = _cfgVoicesVolume; + volume = _vm->_cfgVoicesVolume; break; case kItemIdMusic: y = 130 + 25 * 2; - volume = _cfgMusicVolume; + volume = _vm->_cfgMusicVolume; break; case kItemIdSoundFX: y = 130 + 25 * 3; - volume = _cfgSoundFXVolume; + volume = _vm->_cfgSoundFXVolume; break; - case kItemIdBackground: + case kItemIdBackground: // unused in ScummVM, always 20 y = 130 + 25 * 4; - volume = _cfgBackgroundVolume; + volume = 20; break; default: return; @@ -568,46 +568,48 @@ void MenuSystem::drawVolumeBar(ItemID itemID) { Font font(_vm->_res->load(_vm->_screen->getFontResIndex(1))->data); restoreRect(390, y - font.getHeight(), 100, 25); - + for (int i = 0; i < volume; i++) text[i] = '|'; text[volume] = 0; - + drawString(0, y, w, 0, 246, text); - + } void MenuSystem::changeVolumeBar(ItemID itemID, int delta) { - - int *volume, newVolume; + byte newVolume; switch (itemID) { - case kItemIdMaster: - volume = &_cfgMasterVolume; - break; case kItemIdVoices: - volume = &_cfgVoicesVolume; + _vm->_cfgVoicesVolume = CLIP(_vm->_cfgVoicesVolume + delta, 0, 20); + // Always round volume up instead of down. + newVolume = (_vm->_cfgVoicesVolume * Audio::Mixer::kMaxChannelVolume + 19) / 20; + _vm->_mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, newVolume); + ConfMan.setInt("speech_volume", newVolume); break; case kItemIdMusic: - volume = &_cfgMusicVolume; + _vm->_cfgMusicVolume = CLIP(_vm->_cfgMusicVolume + delta, 0, 20); + newVolume = (_vm->_cfgMusicVolume * Audio::Mixer::kMaxChannelVolume + 19) / 20; + _vm->_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, newVolume); + ConfMan.setInt("music_volume", newVolume); break; case kItemIdSoundFX: - volume = &_cfgSoundFXVolume; + _vm->_cfgSoundFXVolume = CLIP(_vm->_cfgSoundFXVolume + delta, 0, 20); + newVolume = (_vm->_cfgSoundFXVolume * Audio::Mixer::kMaxChannelVolume + 19) / 20; + _vm->_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, newVolume); + ConfMan.setInt("sfx_volume", newVolume); break; + case kItemIdMaster: case kItemIdBackground: - volume = &_cfgBackgroundVolume; + // unused in ScummVM break; default: return; } - newVolume = CLIP(*volume + delta, 0, 20); - - if (newVolume != *volume) { - *volume = newVolume; - drawVolumeBar(itemID); - } - + _vm->syncSoundSettings(); + drawVolumeBar(itemID); } } // End of namespace Toltecs diff --git a/engines/toltecs/menu.h b/engines/toltecs/menu.h index 3e2c2da8d9..a72205c2e5 100644 --- a/engines/toltecs/menu.h +++ b/engines/toltecs/menu.h @@ -29,14 +29,6 @@ namespace Toltecs { -enum MenuID { - kMenuIdNone, - kMenuIdMain, - kMenuIdSave, - kMenuIdLoad, - kMenuIdVolumes -}; - enum ItemID { kItemIdNone, // Main menu @@ -85,10 +77,10 @@ public: MenuSystem(ToltecsEngine *vm); ~MenuSystem(); - int run(); + int run(MenuID menuId); void update(); void handleEvents(); - + protected: struct Item { @@ -99,7 +91,7 @@ protected: int x, y, w; uint fontNum; }; - + struct SavegameItem { int _slotNum; Common::String _description; @@ -124,9 +116,6 @@ protected: Common::Array<Item> _items; 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); @@ -134,13 +123,13 @@ protected: void handleMouseMove(int x, int y); void handleMouseClick(int x, int y); void handleKeyDown(const Common::KeyState& kbd); - + ItemID findItemAt(int x, int y); Item *getItem(ItemID id); void setItemCaption(Item *item, const char *caption); void initMenu(MenuID menuID); - + void enterItem(ItemID id); void leaveItem(ItemID id); void clickItem(ItemID id); diff --git a/engines/toltecs/microtiles.cpp b/engines/toltecs/microtiles.cpp index 0b61ac38a5..60e65bdaf3 100644 --- a/engines/toltecs/microtiles.cpp +++ b/engines/toltecs/microtiles.cpp @@ -138,7 +138,7 @@ Common::Rect * MicroTileArray::getRectangles(int *num_rects, int min_x, int min_ x0 = CLIP (x0, min_x, max_x); y0 = CLIP (y0, min_y, max_y); y1 = CLIP (y1, min_y, max_y); - + // FIXME: Why is the following code in an #if block? #if 1 start = i; diff --git a/engines/toltecs/movie.cpp b/engines/toltecs/movie.cpp index 76d42ebf0a..35accb5d93 100644 --- a/engines/toltecs/movie.cpp +++ b/engines/toltecs/movie.cpp @@ -61,7 +61,7 @@ void MoviePlayer::playMovie(uint resIndex) { int16 savedCameraY = _vm->_cameraY; int16 savedGuiHeight = _vm->_guiHeight; byte moviePalette[768]; - + _vm->_isSaveAllowed = false; memset(moviePalette, 0, sizeof(moviePalette)); @@ -78,7 +78,7 @@ void MoviePlayer::playMovie(uint resIndex) { _vm->_arc->readUint32LE(); _vm->_arc->readUint32LE(); _framesPerSoundChunk = _vm->_arc->readUint32LE(); - _vm->_arc->readUint32LE(); + int rate = _vm->_arc->readUint32LE(); _vm->_sceneWidth = 640; _vm->_sceneHeight = 400; @@ -87,7 +87,7 @@ void MoviePlayer::playMovie(uint resIndex) { _vm->_cameraY = 0; _vm->_guiHeight = 0; - _audioStream = Audio::makeQueuingAudioStream(22050, false); + _audioStream = Audio::makeQueuingAudioStream(rate, false); _vm->_mixer->playStream(Audio::Mixer::kPlainSoundType, &_audioStreamHandle, _audioStream); @@ -96,49 +96,52 @@ void MoviePlayer::playMovie(uint resIndex) { fetchAudioChunks(); - uint32 lastTime = _vm->_mixer->getSoundElapsedTime(_audioStreamHandle); + byte *chunkBuffer = NULL; + uint32 chunkBufferSize = 0; + uint32 frame = 0; while (_chunkCount--) { - byte chunkType = _vm->_arc->readByte(); uint32 chunkSize = _vm->_arc->readUint32LE(); - byte *chunkBuffer = NULL; - uint32 movieOffset; debug(0, "chunkType = %d; chunkSize = %d", chunkType, chunkSize); - + // Skip audio chunks - we've already queued them in // fetchAudioChunks() above if (chunkType == kChunkAudio) { _vm->_arc->skip(chunkSize); } else { - chunkBuffer = new byte[chunkSize]; + // Only reallocate the chunk buffer if the new chunk is bigger + if (chunkSize > chunkBufferSize) { + delete[] chunkBuffer; + chunkBuffer = new byte[chunkSize]; + chunkBufferSize = chunkSize; + } + _vm->_arc->read(chunkBuffer, chunkSize); } - movieOffset = _vm->_arc->pos(); - switch (chunkType) { case kChunkFirstImage: case kChunkSubsequentImages: unpackRle(chunkBuffer, _vm->_screen->_backScreen); - // TODO: Rework this - _vm->_screen->updateShakeScreen(); _vm->_screen->_fullRefresh = true; - _vm->updateInput(); - _vm->drawScreen(); _soundChunkFramesLeft--; if (_soundChunkFramesLeft <= _framesPerSoundChunk) { fetchAudioChunks(); } - while (_vm->_mixer->getSoundElapsedTime(_audioStreamHandle) < lastTime + 111) { - g_system->delayMillis(10); + while (_vm->_mixer->getSoundElapsedTime(_audioStreamHandle) < (1000 * frame) / 9) { + if (_vm->_screen->_shakeActive && _vm->_screen->updateShakeScreen()) { + _vm->_screen->_fullRefresh = true; + } + _vm->updateInput(); + _vm->drawScreen(); + // Note: drawScreen() calls delayMillis() } - lastTime = _vm->_mixer->getSoundElapsedTime(_audioStreamHandle); - + frame++; break; case kChunkPalette: unpackPalette(chunkBuffer, moviePalette, 256, 3); @@ -150,10 +153,10 @@ void MoviePlayer::playMovie(uint resIndex) { // Already processed break; case kChunkShowSubtitle: - // TODO: Check if the text is a subtitle (last character == 0xFE). - // If so, don't show it if text display is disabled. - memcpy(_vm->_script->getSlotData(subtitleSlot), chunkBuffer, chunkSize); - _vm->_screen->updateTalkText(subtitleSlot, 0); + if (_vm->_cfgText) { + memcpy(_vm->_script->getSlotData(subtitleSlot), chunkBuffer, chunkSize); + _vm->_screen->updateTalkText(subtitleSlot, 0); + } break; case kChunkShakeScreen: // start/stop shakescreen effect if (chunkBuffer[0] == 0xFF) @@ -176,20 +179,17 @@ void MoviePlayer::playMovie(uint resIndex) { error("MoviePlayer::playMovie(%04X) Unknown chunk type %d at %08X", resIndex, chunkType, _vm->_arc->pos() - 5 - chunkSize); } - delete[] chunkBuffer; - - _vm->_arc->seek(movieOffset, SEEK_SET); - if (!handleInput()) break; - } + delete[] chunkBuffer; + _audioStream->finish(); _vm->_mixer->stopHandle(_audioStreamHandle); _vm->_arc->closeResource(); - + debug(0, "playMovie() done"); _vm->_sceneWidth = savedSceneWidth; diff --git a/engines/toltecs/movie.h b/engines/toltecs/movie.h index aecfac240f..8fa48975d7 100644 --- a/engines/toltecs/movie.h +++ b/engines/toltecs/movie.h @@ -36,7 +36,7 @@ public: ~MoviePlayer(); void playMovie(uint resIndex); - + protected: ToltecsEngine *_vm; Audio::QueuingAudioStream *_audioStream; @@ -47,11 +47,11 @@ protected: void unpackPalette(byte *source, byte *dest, int elemCount, int elemSize); void unpackRle(byte *source, byte *dest); - + void fetchAudioChunks(); - + bool handleInput(); - + }; } // End of namespace Toltecs diff --git a/engines/toltecs/music.cpp b/engines/toltecs/music.cpp index c322961077..830e4a97da 100644 --- a/engines/toltecs/music.cpp +++ b/engines/toltecs/music.cpp @@ -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/music.h" #include "toltecs/resource.h" -#include "audio/midiparser.h" -#include "common/textconsole.h" - namespace Toltecs { MusicPlayer::MusicPlayer(bool isGM) : _isGM(isGM), _buffer(NULL) { @@ -62,7 +60,7 @@ void MusicPlayer::playMIDI(const byte *data, uint32 size, bool loop) { memcpy(_buffer, data, size); MidiParser *parser; - + if (!memcmp(data, "FORM", 4)) parser = MidiParser::createParser_XMIDI(NULL); else @@ -77,7 +75,7 @@ void MusicPlayer::playMIDI(const byte *data, uint32 size, bool loop) { _parser = parser; - setVolume(127); + syncVolume(); _isLooping = loop; _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() { Common::StackLock lock(_mutex); stop(); diff --git a/engines/toltecs/music.h b/engines/toltecs/music.h index 79df1ea2f5..8d364dbb9f 100644 --- a/engines/toltecs/music.h +++ b/engines/toltecs/music.h @@ -37,8 +37,6 @@ public: MusicPlayer(bool isGM = true); void playMIDI(const byte *data, uint32 size, bool loop = false); - void pause(); - void resume(); void stopAndClear(); // MidiDriver_BASE interface implementation diff --git a/engines/toltecs/palette.cpp b/engines/toltecs/palette.cpp index 706218e0ba..74683c6d7a 100644 --- a/engines/toltecs/palette.cpp +++ b/engines/toltecs/palette.cpp @@ -31,7 +31,7 @@ namespace Toltecs { Palette::Palette(ToltecsEngine *vm) : _vm(vm) { clearFragments(); - + memset(_colorTransTable, 0, sizeof(_colorTransTable)); } @@ -81,7 +81,7 @@ void Palette::setDeltaPalette(byte *palette, byte mask, int8 deltaValue, int16 c if (mask & 4) colors[index * 3 + 2] = CLIP<int>(rgb + deltaValue, 0, 63) << 2; index++; } - + debug(0, "startIndex = %d; colorCount = %d", startIndex, colorCount); _vm->_system->getPaletteManager()->setPalette((const byte *)colors, 0, 256); @@ -101,9 +101,9 @@ void Palette::addFragment(uint resIndex, int16 id) { Resource *fragmentResource = _vm->_res->load(resIndex); byte count = fragmentResource->size / 3; - + memcpy(&_mainPalette[_fragmentIndex * 3], fragmentResource->data, count * 3); - + PaletteFragment fragment; fragment.id = id; fragment.index = _fragmentIndex; @@ -126,7 +126,7 @@ uint16 Palette::findFragment(int16 id) { break; } } - + debug(0, "Palette::findFragment() result = %04X", result); return result; @@ -140,9 +140,9 @@ void Palette::clearFragments() { void Palette::buildColorTransTable(byte limit, int8 deltaValue, byte mask) { byte r = 0, g = 0, b = 0; - + mask &= 7; - + for (int i = 0; i < 256; i++) { if (deltaValue < 0) { @@ -161,7 +161,7 @@ void Palette::buildColorTransTable(byte limit, int8 deltaValue, byte mask) { b -= deltaValue; } } - + int bestIndex = 0; uint16 bestMatch = 0xFFFF; @@ -174,7 +174,7 @@ void Palette::buildColorTransTable(byte limit, int8 deltaValue, byte mask) { bestIndex = j; } } - + _colorTransTable[i] = bestIndex; } diff --git a/engines/toltecs/palette.h b/engines/toltecs/palette.h index 7bcf06e027..570f51777e 100644 --- a/engines/toltecs/palette.h +++ b/engines/toltecs/palette.h @@ -66,7 +66,7 @@ protected: int16 id; byte index, count; }; - + typedef Common::Array<PaletteFragment> PaletteFragmentArray; ToltecsEngine *_vm; diff --git a/engines/toltecs/render.cpp b/engines/toltecs/render.cpp index 3f5356493e..4c41e6ce00 100644 --- a/engines/toltecs/render.cpp +++ b/engines/toltecs/render.cpp @@ -114,7 +114,7 @@ void RenderQueue::addMask(SegmapMaskRect &mask) { void RenderQueue::update() { bool doFullRefresh = _vm->_screen->_fullRefresh; - + _updateUta->clear(); if (!doFullRefresh) { @@ -166,7 +166,7 @@ void RenderQueue::update() { for (RenderQueueArray::iterator iter = _currQueue->begin(); iter != _currQueue->end(); iter++) { const RenderQueueItem *item = &(*iter); - + if (item->flags == kRefresh || doFullRefresh) { switch (item->type) { @@ -200,7 +200,7 @@ void RenderQueue::update() { SWAP(_currQueue, _prevQueue); _currQueue->clear(); - + } void RenderQueue::clear() { @@ -249,16 +249,16 @@ bool RenderQueue::hasItemChanged(const RenderQueueItem &item1, const RenderQueue if (item1.type != item2.type) return true; - + if (item1.rect.left != item2.rect.left || item1.rect.top != item2.rect.top || item1.rect.right != item2.rect.right || item1.rect.bottom != item2.rect.bottom) return true; - + if (item1.type == kText && item1.text.color != item2.text.color) return true; - + return false; } @@ -268,7 +268,7 @@ void RenderQueue::invalidateItemsByRect(const Common::Rect &rect, const RenderQu if (item != subItem && subItem->flags == kUnchanged && rect.intersects(subItem->rect)) { - + subItem->flags = kRefresh; invalidateItemsByRect(subItem->rect, subItem); } diff --git a/engines/toltecs/render.h b/engines/toltecs/render.h index bb9ec29959..59d7a3ddb9 100644 --- a/engines/toltecs/render.h +++ b/engines/toltecs/render.h @@ -75,7 +75,7 @@ public: void addMask(SegmapMaskRect &mask); void update(); void clear(); - + protected: typedef Common::List<RenderQueueItem> RenderQueueArray; @@ -87,7 +87,7 @@ protected: RenderQueueItem *findItemInQueue(RenderQueueArray *queue, const RenderQueueItem &item); bool hasItemChanged(const RenderQueueItem &item1, const RenderQueueItem &item2); void invalidateItemsByRect(const Common::Rect &rect, const RenderQueueItem *item); - + void addDirtyRect(const Common::Rect &rect); void restoreDirtyBackground(); void updateDirtyRects(); diff --git a/engines/toltecs/resource.cpp b/engines/toltecs/resource.cpp index b95e0444b1..0b9f7c8fcd 100644 --- a/engines/toltecs/resource.cpp +++ b/engines/toltecs/resource.cpp @@ -66,7 +66,7 @@ void ArchiveReader::dump(uint resIndex, const char *prefix) { byte *data = new byte[resourceSize]; Common::String fn; - + if (prefix) fn = Common::String::format("%s_%04X.0", prefix, resIndex); else @@ -117,11 +117,11 @@ Resource *ResourceCache::load(uint resIndex) { resItem->data = new byte[resItem->size]; _vm->_arc->read(resItem->data, resItem->size); _vm->_arc->closeResource(); - + _cache[resIndex] = resItem; - + return resItem; - + } } diff --git a/engines/toltecs/saveload.cpp b/engines/toltecs/saveload.cpp index c24d2149b0..6c195a34c2 100644 --- a/engines/toltecs/saveload.cpp +++ b/engines/toltecs/saveload.cpp @@ -36,12 +36,11 @@ namespace Toltecs { /* TODO: - - Save with F7; Load with F9 - Saving during an animation (AnimationPlayer) is not working correctly yet - Maybe switch to SCUMM/Tinsel serialization approach? */ -#define TOLTECS_SAVEGAME_VERSION 3 +#define TOLTECS_SAVEGAME_VERSION 4 ToltecsEngine::kReadSaveHeaderError ToltecsEngine::readSaveHeader(Common::SeekableReadStream *in, bool loadThumbnail, SaveHeader &header) { @@ -93,7 +92,7 @@ void ToltecsEngine::savegame(const char *filename, const char *description) { byte descriptionLen = strlen(description); out->writeByte(descriptionLen); out->write(description, descriptionLen); - + Graphics::saveThumbnail(*out); // Not used yet, reserved for future usage @@ -141,8 +140,8 @@ void ToltecsEngine::savegame(const char *filename, const char *description) { } void ToltecsEngine::loadgame(const char *filename) { - Common::InSaveFile *in; - if (!(in = g_system->getSavefileManager()->openForLoading(filename))) { + Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(filename); + if (!in) { warning("Can't open file '%s', game not loaded", filename); return; } @@ -150,13 +149,13 @@ void ToltecsEngine::loadgame(const char *filename) { SaveHeader header; kReadSaveHeaderError errorCode = readSaveHeader(in, false, header); - + if (errorCode != kRSHENoError) { warning("Error loading savegame '%s'", filename); delete in; return; } - + _sound->stopAll(); _music->stopSequence(); g_engine->setTotalPlayTime(header.playTime * 1000); @@ -182,7 +181,7 @@ void ToltecsEngine::loadgame(const char *filename) { _mouseX = in->readUint16LE(); _mouseY = in->readUint16LE(); _mouseDisabled = in->readUint16LE(); - + _system->warpMouse(_mouseX, _mouseY); _system->showMouse(_mouseDisabled == 0); @@ -191,7 +190,7 @@ void ToltecsEngine::loadgame(const char *filename) { _anim->loadState(in); _screen->loadState(in); if (header.version >= 2) - _sound->loadState(in); + _sound->loadState(in, header.version); if (header.version >= 3) _music->loadState(in); diff --git a/engines/toltecs/screen.cpp b/engines/toltecs/screen.cpp index 634917a7b1..c8d6740b02 100644 --- a/engines/toltecs/screen.cpp +++ b/engines/toltecs/screen.cpp @@ -43,9 +43,11 @@ Screen::Screen(ToltecsEngine *vm) : _vm(vm) { // Screen shaking _shakeActive = false; + _shakeTime = 0; _shakeCounterInit = 0; _shakeCounter = 0; _shakePos = 0; + _shakeTime = 0; // Verb line _verbLineNum = 0; @@ -73,7 +75,7 @@ Screen::~Screen() { delete[] _frontScreen; delete[] _backScreen; - + delete _renderQueue; } @@ -129,7 +131,7 @@ void Screen::drawGuiImage(int16 x, int16 y, uint resIndex) { byte *dest = _frontScreen + x + (y + _vm->_cameraHeight) * 640; //debug(0, "Screen::drawGuiImage() x = %d; y = %d; w = %d; h = %d; resIndex = %d", x, y, width, height, resIndex); - + while (workHeight > 0) { int count = 1; byte pixel = *imageData++; @@ -156,6 +158,7 @@ void Screen::drawGuiImage(int16 x, int16 y, uint resIndex) { void Screen::startShakeScreen(int16 shakeCounter) { _shakeActive = true; + _shakeTime = 0; _shakeCounterInit = shakeCounter; _shakeCounter = shakeCounter; _shakePos = 0; @@ -166,15 +169,19 @@ void Screen::stopShakeScreen() { _vm->_system->setShakePos(0); } -void Screen::updateShakeScreen() { - if (_shakeActive) { +bool Screen::updateShakeScreen() { + // Assume shaking happens no more often than 50 times per second + if (_shakeActive && _vm->_system->getMillis() - _shakeTime >= 20) { + _shakeTime = _vm->_system->getMillis(); _shakeCounter--; if (_shakeCounter == 0) { _shakeCounter = _shakeCounterInit; _shakePos ^= 8; _vm->_system->setShakePos(_shakePos); + return true; } } + return false; } void Screen::addStaticSprite(byte *spriteItem) { @@ -247,7 +254,7 @@ void Screen::addAnimatedSprite(int16 x, int16 y, int16 fragmentId, byte *data, i } else { loopNum |= 0x8000; } - + WRITE_LE_UINT16(spriteItem + 0, loopNum); WRITE_LE_UINT16(spriteItem + 4, frameNum); @@ -308,9 +315,9 @@ void Screen::updateVerbLine(int16 slotIndex, int16 slotOffset) { wrapState.len2 = 0; y = _verbLineY; - + memset(wrapState.textBuffer, 0, sizeof(wrapState.textBuffer)); - + for (int16 i = 0; i <= _verbLineNum; i++) { wrapState.sourceString = _vm->_script->getSlotData(_verbLineItems[i].slotIndex) + _verbLineItems[i].slotOffset; len = wrapGuiText(_fontResIndexArray[0], _verbLineWidth, wrapState); @@ -331,19 +338,19 @@ void Screen::updateVerbLine(int16 slotIndex, int16 slotOffset) { wrapState.sourceString++; wrapState.len1 -= len; wrapState.len2 = len + 1; - + drawGuiText(_verbLineX - 1 - (wrapState.width / 2), y, 0xF9, 0xFF, _fontResIndexArray[0], wrapState); wrapState.destString = wrapState.textBuffer; wrapState.width = 0; len = wrapGuiText(_fontResIndexArray[0], _verbLineWidth, wrapState); wrapState.len1 += len; - + y += 9; } y += 9; } - + wrapState.len1 -= len; wrapState.len2 = len; @@ -463,13 +470,12 @@ void Screen::addTalkTextRect(Font &font, int16 x, int16 &y, int16 length, int16 textRect->x = CLIP<int16>(x - width / 2, 0, 640); item->lineCount++; } - + y += font.getHeight() - 1; } void Screen::addTalkTextItemsToRenderQueue() { - for (int16 i = 0; i <= _talkTextItemNum; i++) { TalkTextItem *item = &_talkTextItems[i]; byte *text = _vm->_script->getSlotData(item->slotIndex) + item->slotOffset; @@ -482,14 +488,15 @@ void Screen::addTalkTextItemsToRenderQueue() { if (item->duration < 0) item->duration = 0; + if (!_vm->_cfgText) + return; + for (byte j = 0; j < item->lineCount; j++) { - _renderQueue->addText(item->lines[j].x, item->lines[j].y, item->color, _fontResIndexArray[item->fontNum], - text, item->lines[j].length); + _renderQueue->addText(item->lines[j].x, item->lines[j].y, item->color, + _fontResIndexArray[item->fontNum], text, item->lines[j].length); text += item->lines[j].length; } - } - } int16 Screen::getTalkTextDuration() { @@ -559,7 +566,7 @@ int16 Screen::wrapGuiText(uint fontResIndex, int maxWidth, GuiTextWrapState &wra Font font(_vm->_res->load(fontResIndex)->data); int16 len = 0; - + while (*wrapState.sourceString >= 0x20 && *wrapState.sourceString < 0xF0) { byte ch = *wrapState.sourceString; byte charWidth; @@ -573,9 +580,9 @@ int16 Screen::wrapGuiText(uint fontResIndex, int maxWidth, GuiTextWrapState &wra wrapState.width += charWidth; *wrapState.destString++ = *wrapState.sourceString++; } - + return len; - + } void Screen::drawGuiText(int16 x, int16 y, byte fontColor1, byte fontColor2, uint fontResIndex, GuiTextWrapState &wrapState) { @@ -765,7 +772,7 @@ void Screen::loadState(Common::ReadStream *in) { _verbLineItems[i].slotIndex = in->readUint16LE(); _verbLineItems[i].slotOffset = in->readUint16LE(); } - + // Load talk text items _talkTextX = in->readUint16LE(); _talkTextY = in->readUint16LE(); @@ -786,7 +793,7 @@ void Screen::loadState(Common::ReadStream *in) { _talkTextItems[i].lines[j].length = in->readUint16LE(); } } - + // Load GUI bitmap { byte *gui = _frontScreen + _vm->_cameraHeight * 640; diff --git a/engines/toltecs/screen.h b/engines/toltecs/screen.h index 988f59c840..788cde50c6 100644 --- a/engines/toltecs/screen.h +++ b/engines/toltecs/screen.h @@ -154,15 +154,15 @@ public: ~Screen(); void unpackRle(byte *source, byte *dest, uint16 width, uint16 height); - + void loadMouseCursor(uint resIndex); - + void drawGuiImage(int16 x, int16 y, uint resIndex); - + void startShakeScreen(int16 shakeCounter); void stopShakeScreen(); - void updateShakeScreen(); - + bool updateShakeScreen(); + // Sprite list void addStaticSprite(byte *spriteItem); void addAnimatedSprite(int16 x, int16 y, int16 fragmentId, byte *data, int16 *spriteArray, bool loop, int mode); @@ -175,7 +175,7 @@ public: // Verb line void updateVerbLine(int16 slotIndex, int16 slotOffset); - + // Talk text void updateTalkText(int16 slotIndex, int16 slotOffset); void addTalkTextRect(Font &font, int16 x, int16 &y, int16 length, int16 width, TalkTextItem *item); @@ -207,7 +207,7 @@ public: int16 slotIndex; int16 slotOffset; }; - + struct Rect { int16 x, y, width, height; }; @@ -215,12 +215,13 @@ public: ToltecsEngine *_vm; byte *_frontScreen, *_backScreen; - + uint _fontResIndexArray[10]; byte _fontColor1, _fontColor2; // Screen shaking bool _shakeActive; + uint32 _shakeTime; int16 _shakeCounterInit, _shakeCounter; int _shakePos; @@ -229,7 +230,7 @@ public: VerbLineItem _verbLineItems[8]; int16 _verbLineX, _verbLineY, _verbLineWidth; int16 _verbLineCount; - + // Talk text int16 _talkTextX, _talkTextY; int16 _talkTextMaxWidth; diff --git a/engines/toltecs/script.cpp b/engines/toltecs/script.cpp index 9683831980..5e8617bc43 100644 --- a/engines/toltecs/script.cpp +++ b/engines/toltecs/script.cpp @@ -183,10 +183,7 @@ void ScriptInterpreter::setMainScript(uint slotIndex) { } void ScriptInterpreter::runScript() { - uint32 lastScreenUpdate = 0; - while (!_vm->shouldQuit()) { - if (_vm->_movieSceneFlag) _vm->_mouseButton = 0; @@ -197,7 +194,7 @@ void ScriptInterpreter::runScript() { _vm->saveGameState(_vm->_saveLoadSlot, _vm->_saveLoadDescription); _vm->_saveLoadRequested = 0; } - + if (_switchLocalDataNear) { _switchLocalDataNear = false; _localData = getSlotData(_regs.reg4); @@ -214,20 +211,10 @@ void ScriptInterpreter::runScript() { _localData = _stack + 2; _switchLocalDataNear = true; } - + byte opcode = readByte(); execOpcode(opcode); - - // Update the screen at semi-regular intervals, else the mouse - // cursor will be jerky. - uint32 now = _vm->_system->getMillis(); - if (now < lastScreenUpdate || now - lastScreenUpdate > 10) { - _vm->_system->updateScreen(); - lastScreenUpdate = _vm->_system->getMillis(); - } - } - } byte ScriptInterpreter::readByte() { @@ -547,7 +534,7 @@ const char *getVarName(uint variable) { int16 ScriptInterpreter::getGameVar(uint variable) { debug(0, "ScriptInterpreter::getGameVar(%d{%s})", variable, getVarName(variable)); - + switch (variable) { case 0: return _vm->_mouseDisabled; case 1: return _vm->_mouseY; @@ -579,7 +566,7 @@ int16 ScriptInterpreter::getGameVar(uint variable) { void ScriptInterpreter::setGameVar(uint variable, int16 value) { debug(0, "ScriptInterpreter::setGameVar(%d{%s}, %d)", variable, getVarName(variable), value); - + switch (variable) { case 0: _vm->_mouseDisabled = value; @@ -718,7 +705,7 @@ void ScriptInterpreter::saveState(Common::WriteStream *out) { // Save stack out->write(_stack, kScriptStackSize); out->writeUint16LE(_savedSp); - + // Save IP out->writeUint16LE((int16)(_code - getSlotData(_regs.reg4))); @@ -1046,29 +1033,21 @@ void ScriptInterpreter::sfHandleInput() { Only scancodes known to be used (so far) are converted */ switch (_vm->_keyState.keycode) { - case Common::KEYCODE_ESCAPE: + case Common::KEYCODE_ESCAPE: keyCode = 1; break; case Common::KEYCODE_F10: keyCode = 68; break; default: - break; + break; } } localWrite16(varOfs, keyCode); } void ScriptInterpreter::sfRunOptionsScreen() { - _vm->_screen->loadMouseCursor(12); - _vm->_palette->loadAddPalette(9, 224); - _vm->_palette->setDeltaPalette(_vm->_palette->getMainPalette(), 7, 0, 31, 224); - _vm->_screen->finishTalkTextItems(); - _vm->_screen->clearSprites(); - CursorMan.showMouse(true); - _vm->_menuSystem->run(); - _vm->_keyState.reset(); - _switchLocalDataNear = true; + _vm->showMenu(kMenuIdMain); } /* NOTE: The opcodes sfPrecacheSprites, sfPrecacheSounds1, sfPrecacheSounds2 and @@ -1076,7 +1055,7 @@ void ScriptInterpreter::sfRunOptionsScreen() { of data so the game doesn't stall while playing (due to the slow speed of CD-Drives back then). This is not needed in ScummVM since all supported systems are fast enough to load data in-game. */ - + void ScriptInterpreter::sfPrecacheSprites() { // See note above } @@ -1102,7 +1081,9 @@ void ScriptInterpreter::sfSaveStackPtr() { } void ScriptInterpreter::sfPlayMovie() { + CursorMan.showMouse(false); _vm->_moviePlayer->playMovie(arg16(3)); + CursorMan.showMouse(true); } } // End of namespace Toltecs diff --git a/engines/toltecs/script.h b/engines/toltecs/script.h index 0c1898c525..89dca4598f 100644 --- a/engines/toltecs/script.h +++ b/engines/toltecs/script.h @@ -56,6 +56,8 @@ public: void saveState(Common::WriteStream *out); void loadState(Common::ReadStream *in); + void setSwitchLocalDataNear(bool newValue) { _switchLocalDataNear = newValue; } + protected: struct ScriptRegs { @@ -88,13 +90,13 @@ protected: bool _cmpBitTest; ScriptSlot _slots[kMaxScriptSlots]; - + ScriptRegs _regs; int16 _savedSp; byte readByte(); int16 readInt16(); - + void execOpcode(byte opcode); void setupScriptFunctions(); diff --git a/engines/toltecs/segmap.cpp b/engines/toltecs/segmap.cpp index f7d806c67b..b06c0af675 100644 --- a/engines/toltecs/segmap.cpp +++ b/engines/toltecs/segmap.cpp @@ -48,7 +48,7 @@ void SegmentMap::load(byte *source) { uint16 maskRectCount = READ_LE_UINT16(source); source += 2; uint16 maskRectDataSize = maskRectCount * 12 + 2; - + debug(0, "SegmentMap::load() maskRectCount = %d", maskRectCount); for (uint16 i = 0; i < maskRectCount; i++) { @@ -74,25 +74,25 @@ void SegmentMap::load(byte *source) { // Load path rects source += 2; // skip rects array size - + uint16 pathRectCount = READ_LE_UINT16(source); source += 2; - + debug(0, "SegmentMap::load() pathRectCount = %d", pathRectCount); - + for (uint16 i = 0; i < pathRectCount; i++) { SegmapPathRect pathRect; pathRect.y1 = READ_LE_UINT16(source); pathRect.x1 = READ_LE_UINT16(source + 2); pathRect.y2 = pathRect.y1 + READ_LE_UINT16(source + 4); pathRect.x2 = pathRect.x1 + READ_LE_UINT16(source + 6); - + debug(0, "SegmentMap::load() (%d, %d, %d, %d)", pathRect.x1, pathRect.y1, pathRect.x2, pathRect.y2); source += 8; _pathRects.push_back(pathRect); } - + // Load info rects source += 2; // skip rects array size @@ -141,7 +141,7 @@ void SegmentMap::adjustPathPoint(int16 &x, int16 &y) { uint32 minDistance = 0xFFFFFFFF, distance; int16 adjustedX = 0, adjustedY = 0, x2, y2; - + for (int16 rectIndex = 0; rectIndex < (int16)_pathRects.size(); rectIndex++) { if (x >= _pathRects[rectIndex].x1 && x < _pathRects[rectIndex].x2) { @@ -174,7 +174,7 @@ void SegmentMap::adjustPathPoint(int16 &x, int16 &y) { } } - + x = adjustedX; y = adjustedY; @@ -318,7 +318,7 @@ void SegmentMap::findPath(int16 *pointsArray, int16 destX, int16 destY, int16 so pointsArray[0] = 0; pointsArray[1] = TO_LE_16(_pathNodesCount + 1); } - + debug(0, "SegmentMap::findPath() count = %d", FROM_LE_16(pointsArray[1])); #if 0 // DEBUG: Draw the path we found @@ -335,7 +335,7 @@ void SegmentMap::findPath(int16 *pointsArray, int16 destX, int16 destY, int16 so sy = y; } #endif - + } int8 SegmentMap::getScalingAtPoint(int16 x, int16 y) { diff --git a/engines/toltecs/segmap.h b/engines/toltecs/segmap.h index 30182a6b71..dda0edeb88 100644 --- a/engines/toltecs/segmap.h +++ b/engines/toltecs/segmap.h @@ -61,14 +61,14 @@ public: void getRgbModifiertAtPoint(int16 x, int16 y, int16 id, byte &r, byte &g, byte &b); void addMasksToRenderQueue(); - + //protected: public: // for debugging purposes struct SegmapPathRect { int16 x1, y1, x2, y2; }; - + struct SegmapInfoRect { int16 y, x; int16 height, width; @@ -78,11 +78,11 @@ public: // for debugging purposes return py >= y && py <= y + height && px >= x && px <= x + width; } }; - + struct PathPoint { int16 y, x; }; - + typedef Common::Array<SegmapMaskRect> SegmapMaskRectArray; typedef Common::Array<SegmapPathRect> SegmapPathRectArray; typedef Common::Array<SegmapInfoRect> SegmapInfoRectArray; diff --git a/engines/toltecs/sound.cpp b/engines/toltecs/sound.cpp index c9ef00e31b..4b281392e5 100644 --- a/engines/toltecs/sound.cpp +++ b/engines/toltecs/sound.cpp @@ -34,48 +34,38 @@ namespace Toltecs { Sound::Sound(ToltecsEngine *vm) : _vm(vm) { for (int i = 0; i < kMaxChannels; i++) { - channels[i].type = kChannelTypeEmpty; - channels[i].resIndex = -1; + clearChannel(i); } } Sound::~Sound() { } +void Sound::clearChannel(int channel) { + channels[channel].type = kChannelTypeEmpty; + channels[channel].resIndex = -1; + channels[channel].volume = 0; + channels[channel].panning = 0; +} + void Sound::playSpeech(int16 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) { - - // TODO: Use the right volumes - debug(0, "playSound(%d, %d, %d)", resIndex, type, volume); - - if (volume == -1 || type == -2) { - if (type == kChannelTypeBackground) { - internalPlaySound(resIndex, type, 50 /*TODO*/, 0); - } else { - internalPlaySound(resIndex, type, 100 /*TODO*/, 0); - } - } else { - internalPlaySound(resIndex, type, 100 /*TODO*/, 0); - } + internalPlaySound(resIndex, type, volume, 0); } void Sound::playSoundAtPos(int16 resIndex, int16 x, int16 y) { - debug(0, "playSoundAtPos(%d, %d, %d)", resIndex, x, y); - int16 volume, panning = 0, deltaX = 0; - int8 scaling = _vm->_segmap->getScalingAtPoint(x, y); - - if (scaling >= 0) - volume = 50 + ABS(scaling) / 2; - else - volume = 50 - ABS(scaling) / 2; + int16 volume = 50 + ABS(_vm->_segmap->getScalingAtPoint(x, y)) / 2; + int16 panning = 0, deltaX = 0; if (_vm->_cameraX > x) deltaX = _vm->_cameraX - x; @@ -85,32 +75,31 @@ void Sound::playSoundAtPos(int16 resIndex, int16 x, int16 y) { deltaX = 600; volume = ((100 - deltaX / 6) * volume) / 100; - + if (_vm->_cameraX + 320 != x) { panning = CLIP(x - (_vm->_cameraX + 320), -381, 381) / 3; } internalPlaySound(resIndex, 1, volume, 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) { // Stop all sounds _vm->_mixer->stopAll(); _vm->_screen->keepTalkTextItemsAlive(); for (int i = 0; i < kMaxChannels; i++) { - channels[i].type = kChannelTypeEmpty; - channels[i].resIndex = -1; + clearChannel(i); } } else if (type == -2) { // Stop sounds with specified resIndex for (int i = 0; i < kMaxChannels; i++) { if (channels[i].resIndex == resIndex) { _vm->_mixer->stopHandle(channels[i].handle); - channels[i].type = kChannelTypeEmpty; - channels[i].resIndex = -1; + clearChannel(i); } } } else { @@ -119,7 +108,7 @@ void Sound::internalPlaySound(int16 resIndex, int16 type, int16 volume, int16 pa // Stop speech and play new sound stopSpeech(); } - + // Play new sound in empty channel int freeChannel = -1; for (int i = 0; i < kMaxChannels; i++) { @@ -128,7 +117,7 @@ void Sound::internalPlaySound(int16 resIndex, int16 type, int16 volume, int16 pa break; } } - + // If all channels are in use no new sound will be played if (freeChannel >= 0) { Resource *soundResource = _vm->_res->load(resIndex); @@ -141,19 +130,17 @@ void Sound::internalPlaySound(int16 resIndex, int16 type, int16 volume, int16 pa channels[freeChannel].type = type; channels[freeChannel].resIndex = resIndex; + channels[freeChannel].volume = volume; + channels[freeChannel].panning = panning; - Audio::Mixer::SoundType soundType = Audio::Mixer::kPlainSoundType; - /* - switch (type) { - } - */ + Audio::Mixer::SoundType soundType = getScummVMSoundType((SoundChannelType)type); _vm->_mixer->playStream(soundType, &channels[freeChannel].handle, - stream, -1, volume, panning); + stream, -1, volume, panning); } } - + } void Sound::updateSpeech() { @@ -170,8 +157,7 @@ void Sound::stopSpeech() { if (channels[i].type == kChannelTypeSpeech) { _vm->_mixer->stopHandle(channels[i].handle); _vm->_screen->keepTalkTextItemsAlive(); - channels[i].type = kChannelTypeEmpty; - channels[i].resIndex = -1; + clearChannel(i); } } } @@ -180,8 +166,7 @@ void Sound::stopAll() { for (int i = 0; i < kMaxChannels; i++) { _vm->_mixer->stopHandle(channels[i].handle); _vm->_screen->keepTalkTextItemsAlive(); - channels[i].type = kChannelTypeEmpty; - channels[i].resIndex = -1; + clearChannel(i); } } @@ -189,13 +174,22 @@ void Sound::saveState(Common::WriteStream *out) { for (int i = 0; i < kMaxChannels; i++) { out->writeSint16LE(channels[i].type); out->writeSint16LE(channels[i].resIndex); + out->writeSint16LE(channels[i].volume); + out->writeSint16LE(channels[i].panning); } } -void Sound::loadState(Common::ReadStream *in) { +void Sound::loadState(Common::ReadStream *in, int version) { for (int i = 0; i < kMaxChannels; i++) { channels[i].type = in->readSint16LE(); channels[i].resIndex = in->readSint16LE(); + if (version < 4) { + channels[i].volume = (channels[i].type == kChannelTypeBackground) ? 50 : 100; + channels[i].panning = 0; + } else { + channels[i].volume = in->readSint16LE(); + channels[i].panning = in->readSint16LE(); + } if (channels[i].type != kChannelTypeEmpty) { Resource *soundResource = _vm->_res->load(channels[i].resIndex); @@ -206,19 +200,26 @@ void Sound::loadState(Common::ReadStream *in) { DisposeAfterUse::NO), channels[i].type == kChannelTypeBackground ? 0 : 1); - Audio::Mixer::SoundType soundType = Audio::Mixer::kPlainSoundType; - /* - switch (type) { - } - */ - - // TODO: Volume and panning - int16 volume = (channels[i].type == kChannelTypeBackground) ? 50 : 100; + Audio::Mixer::SoundType soundType = getScummVMSoundType((SoundChannelType)channels[i].type); _vm->_mixer->playStream(soundType, &channels[i].handle, - stream, -1, volume, /*panning*/0); + stream, -1, channels[i].volume, channels[i].panning); } } } +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 diff --git a/engines/toltecs/sound.h b/engines/toltecs/sound.h index e292d22c0f..48a6cd1318 100644 --- a/engines/toltecs/sound.h +++ b/engines/toltecs/sound.h @@ -42,6 +42,8 @@ enum SoundChannelType { struct SoundChannel { int16 resIndex; int16 type; + int16 volume; + int16 panning; Audio::SoundHandle handle; }; @@ -60,15 +62,16 @@ public: void stopAll(); void saveState(Common::WriteStream *out); - void loadState(Common::ReadStream *in); + void loadState(Common::ReadStream *in, int version); protected: ToltecsEngine *_vm; SoundChannel channels[kMaxChannels]; + void clearChannel(int channel); void internalPlaySound(int16 resIndex, int16 type, int16 volume, int16 panning); - + Audio::Mixer::SoundType getScummVMSoundType(SoundChannelType type) const; }; diff --git a/engines/toltecs/sprite.cpp b/engines/toltecs/sprite.cpp index 7a02663793..6101eb7d85 100644 --- a/engines/toltecs/sprite.cpp +++ b/engines/toltecs/sprite.cpp @@ -199,7 +199,7 @@ bool Screen::createSpriteDrawItem(const DrawRequest &drawRequest, SpriteDrawItem sprite.frameNum = frameNum; spriteData = _vm->_res->load(drawRequest.resIndex)->data; - + if (drawRequest.flags & 0x1000) { sprite.flags |= 4; } @@ -207,7 +207,7 @@ bool Screen::createSpriteDrawItem(const DrawRequest &drawRequest, SpriteDrawItem if (drawRequest.flags & 0x2000) { sprite.flags |= 0x10; } - + if (drawRequest.flags & 0x4000) { sprite.flags |= 0x40; } @@ -218,7 +218,7 @@ bool Screen::createSpriteDrawItem(const DrawRequest &drawRequest, SpriteDrawItem if (spriteFrameEntry.w == 0 || spriteFrameEntry.h == 0) return false; - + sprite.offset = spriteFrameEntry.offset; sprite.width = spriteFrameEntry.w; @@ -263,12 +263,12 @@ bool Screen::createSpriteDrawItem(const DrawRequest &drawRequest, SpriteDrawItem xoffs -= (xoffs * scaleValue) / 100; yoffs -= (yoffs * scaleValue) / 100; } - + } - + sprite.x -= xoffs; sprite.y -= yoffs; - + sprite.yerror = sprite.ydelta; // Now we check if the sprite needs to be clipped @@ -283,7 +283,7 @@ bool Screen::createSpriteDrawItem(const DrawRequest &drawRequest, SpriteDrawItem sprite.height -= clipHeight; if (sprite.height <= 0) return false; - + sprite.y = _vm->_cameraY; // If the sprite is scaled @@ -311,7 +311,7 @@ bool Screen::createSpriteDrawItem(const DrawRequest &drawRequest, SpriteDrawItem } sprite.yerror = chopHeight; } - + spriteFrameData = spriteData + sprite.offset; // Now the sprite's offset is adjusted to point to the starting line if ((sprite.flags & 0x10) == 0) { @@ -439,7 +439,7 @@ void Screen::drawSpriteCore(byte *dest, SpriteFilter &reader, const SpriteDrawIt SpriteReaderStatus status; PixelPacket packet; - + byte *destp = dest; int16 skipX = sprite.skipX; @@ -459,7 +459,7 @@ void Screen::drawSpriteCore(byte *dest, SpriteFilter &reader, const SpriteDrawIt status = reader.readPacket(packet); } } - + if (w - packet.count < 0) packet.count = w; diff --git a/engines/toltecs/toltecs.cpp b/engines/toltecs/toltecs.cpp index 6d6c37dffd..9f3a10a03b 100644 --- a/engines/toltecs/toltecs.cpp +++ b/engines/toltecs/toltecs.cpp @@ -62,11 +62,6 @@ struct GameSettings { }; 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"); } @@ -85,7 +80,7 @@ Common::Error ToltecsEngine::run() { _flag01 = 0; _saveLoadRequested = 0; - + _cameraX = 0; _cameraY = 0; _newCameraX = 0; @@ -96,7 +91,7 @@ Common::Error ToltecsEngine::run() { _sceneWidth = 0; _sceneHeight = 0; - + _doSpeech = true; _doText = true; @@ -126,17 +121,27 @@ Common::Error ToltecsEngine::run() { _moviePlayer = new MoviePlayer(this); _music = new Music(_arc); _menuSystem = new MenuSystem(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(); CursorMan.showMouse(true); setupSysStrings(); -//#define TEST_MENU -#ifdef TEST_MENU +#if 0 + // Menu test _screen->registerFont(0, 0x0D); _screen->registerFont(1, 0x0E); _screen->loadMouseCursor(12); @@ -181,7 +186,7 @@ Common::Error ToltecsEngine::run() { delete _music; delete _moviePlayer; delete _menuSystem; - + delete _sound; return Common::kNoError; @@ -245,7 +250,7 @@ void ToltecsEngine::loadScene(uint resIndex) { _screen->_fullRefresh = true; _screen->_renderQueue->clear(); - + } void ToltecsEngine::updateScreen() { @@ -306,6 +311,7 @@ void ToltecsEngine::drawScreen() { } _system->updateScreen(); + _system->delayMillis(10); updateCamera(); } @@ -321,15 +327,14 @@ void ToltecsEngine::updateInput() { //debug("key: flags = %02X; keycode = %d", _keyState.flags, _keyState.keycode); - // FIXME: This is just for debugging switch (event.kbd.keycode) { - case Common::KEYCODE_F7: - savegame("toltecs.001", "Quicksave"); + case Common::KEYCODE_F5: + showMenu(kMenuIdSave); break; - case Common::KEYCODE_F9: - loadgame("toltecs.001"); + case Common::KEYCODE_F7: + showMenu(kMenuIdLoad); break; - case Common::KEYCODE_ESCAPE: + case Common::KEYCODE_SPACE: // Skip current dialog line, if a dialog is active if (_screen->getTalkTextDuration() > 0) { _sound->stopSpeech(); @@ -422,7 +427,7 @@ void ToltecsEngine::setCamera(int16 x, int16 y) { _screen->finishTalkTextItems(); _screen->clearSprites(); - + _cameraX = x; _newCameraX = x; @@ -491,9 +496,9 @@ void ToltecsEngine::updateCamera() { } void ToltecsEngine::talk(int16 slotIndex, int16 slotOffset) { - + byte *scanData = _script->getSlotData(slotIndex) + slotOffset; - + while (*scanData < 0xF0) { if (*scanData == 0x19) { scanData++; @@ -506,7 +511,7 @@ void ToltecsEngine::talk(int16 slotIndex, int16 slotOffset) { } scanData++; } - + if (*scanData == 0xFE) { if (_doSpeech) { int16 resIndex = READ_LE_UINT16(scanData + 1); @@ -540,7 +545,7 @@ void ToltecsEngine::walk(byte *walkData) { walkInfo.xerror = READ_LE_UINT16(walkData + 14); walkInfo.mulValue = READ_LE_UINT16(walkData + 16); walkInfo.scaling = READ_LE_UINT16(walkData + 18); - + walkInfo.scaling = -_segmap->getScalingAtPoint(walkInfo.x, walkInfo.y); if (walkInfo.y1 < walkInfo.y2) @@ -548,7 +553,7 @@ void ToltecsEngine::walk(byte *walkData) { else ystep = 1; ydelta = ABS(walkInfo.y1 - walkInfo.y2) * _walkSpeedY; - + if (walkInfo.x1 < walkInfo.x2) xstep = -1; else @@ -611,11 +616,11 @@ void ToltecsEngine::walk(byte *walkData) { } -int16 ToltecsEngine::findRectAtPoint(byte *rectData, int16 x, int16 y, int16 index, int16 itemSize, +int16 ToltecsEngine::findRectAtPoint(byte *rectData, int16 x, int16 y, int16 index, int16 itemSize, byte *rectDataEnd) { rectData += index * itemSize; - + while (rectData < rectDataEnd) { int16 rectY = READ_LE_UINT16(rectData); if (rectY == -10) @@ -633,9 +638,32 @@ int16 ToltecsEngine::findRectAtPoint(byte *rectData, int16 x, int16 y, int16 ind index++; rectData += itemSize; } - + return -1; +} + +void ToltecsEngine::showMenu(MenuID menuId) { + _screen->loadMouseCursor(12); + _palette->loadAddPalette(9, 224); + _palette->setDeltaPalette(_palette->getMainPalette(), 7, 0, 31, 224); + _screen->finishTalkTextItems(); + _screen->clearSprites(); + CursorMan.showMouse(true); + _menuSystem->run(menuId); + _keyState.reset(); + _script->setSwitchLocalDataNear(true); +} + +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 diff --git a/engines/toltecs/toltecs.h b/engines/toltecs/toltecs.h index efa1f9d13a..b95a4f77cb 100644 --- a/engines/toltecs/toltecs.h +++ b/engines/toltecs/toltecs.h @@ -81,6 +81,14 @@ enum SysString { kSysStrCount }; +enum MenuID { + kMenuIdNone, + kMenuIdMain, + kMenuIdSave, + kMenuIdLoad, + kMenuIdVolumes +}; + class ToltecsEngine : public ::Engine { Common::KeyState _keyPressed; @@ -99,6 +107,7 @@ public: uint32 getFeatures() const; Common::Language getLanguage() const; const Common::String& getTargetName() const { return _targetName; } + void syncSoundSettings(); void setupSysStrings(); void requestSavegame(int slotNum, Common::String &description); @@ -119,14 +128,18 @@ public: void scrollCameraLeft(int16 delta); void scrollCameraRight(int16 delta); void updateCamera(); - + + void showMenu(MenuID menuId); + void talk(int16 slotIndex, int16 slotOffset); void walk(byte *walkData); - - 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); + int _cfgVoicesVolume, _cfgMusicVolume, _cfgSoundFXVolume; + bool _cfgText, _cfgVoices; public: AnimationPlayer *_anim; @@ -150,7 +163,7 @@ public: uint _sceneResIndex; int16 _sceneWidth, _sceneHeight; - + int _counter01, _counter02; bool _movieSceneFlag; byte _flag01; @@ -161,7 +174,7 @@ public: int16 _guiHeight; bool _doSpeech, _doText; - + int16 _walkSpeedY, _walkSpeedX; Common::KeyState _keyState; |