aboutsummaryrefslogtreecommitdiff
path: root/engines/toltecs
diff options
context:
space:
mode:
authorPaul Gilbert2012-10-31 09:34:38 +1100
committerPaul Gilbert2012-10-31 09:34:38 +1100
commit798ddfaab500bb212f620cf095328eee5eb140a4 (patch)
tree55b5d0b90affd88063c04b7ff62fea1616b83e80 /engines/toltecs
parentef663f95a516d8fe47a245653d418c047361281a (diff)
parentfdc80fd952120ecb8a4941edd4c2e404cdc5fa33 (diff)
downloadscummvm-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.cpp14
-rw-r--r--engines/toltecs/animation.h2
-rw-r--r--engines/toltecs/menu.cpp110
-rw-r--r--engines/toltecs/menu.h21
-rw-r--r--engines/toltecs/microtiles.cpp2
-rw-r--r--engines/toltecs/movie.cpp58
-rw-r--r--engines/toltecs/movie.h8
-rw-r--r--engines/toltecs/music.cpp20
-rw-r--r--engines/toltecs/music.h2
-rw-r--r--engines/toltecs/palette.cpp18
-rw-r--r--engines/toltecs/palette.h2
-rw-r--r--engines/toltecs/render.cpp14
-rw-r--r--engines/toltecs/render.h4
-rw-r--r--engines/toltecs/resource.cpp8
-rw-r--r--engines/toltecs/saveload.cpp17
-rw-r--r--engines/toltecs/screen.cpp49
-rw-r--r--engines/toltecs/screen.h19
-rw-r--r--engines/toltecs/script.cpp41
-rw-r--r--engines/toltecs/script.h6
-rw-r--r--engines/toltecs/segmap.cpp20
-rw-r--r--engines/toltecs/segmap.h8
-rw-r--r--engines/toltecs/sound.cpp107
-rw-r--r--engines/toltecs/sound.h7
-rw-r--r--engines/toltecs/sprite.cpp20
-rw-r--r--engines/toltecs/toltecs.cpp82
-rw-r--r--engines/toltecs/toltecs.h23
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;