aboutsummaryrefslogtreecommitdiff
path: root/engines/toon
diff options
context:
space:
mode:
Diffstat (limited to 'engines/toon')
-rw-r--r--engines/toon/anim.cpp29
-rw-r--r--engines/toon/anim.h2
-rw-r--r--engines/toon/audio.cpp91
-rw-r--r--engines/toon/audio.h9
-rw-r--r--engines/toon/character.cpp54
-rw-r--r--engines/toon/character.h2
-rw-r--r--engines/toon/conversation.cpp1
-rw-r--r--engines/toon/conversation.h4
-rw-r--r--engines/toon/detection.cpp9
-rw-r--r--engines/toon/drew.cpp5
-rw-r--r--engines/toon/drew.h2
-rw-r--r--engines/toon/flux.cpp4
-rw-r--r--engines/toon/flux.h1
-rw-r--r--engines/toon/font.cpp14
-rw-r--r--engines/toon/hotspot.cpp10
-rw-r--r--engines/toon/movie.cpp27
-rw-r--r--engines/toon/movie.h2
-rw-r--r--engines/toon/path.cpp17
-rw-r--r--engines/toon/path.h1
-rw-r--r--engines/toon/picture.cpp84
-rw-r--r--engines/toon/picture.h1
-rw-r--r--engines/toon/resource.cpp157
-rw-r--r--engines/toon/resource.h29
-rw-r--r--engines/toon/script.cpp12
-rw-r--r--engines/toon/script.h5
-rw-r--r--engines/toon/script_func.cpp20
-rw-r--r--engines/toon/state.cpp3
-rw-r--r--engines/toon/state.h2
-rw-r--r--engines/toon/text.cpp2
-rw-r--r--engines/toon/tools.cpp42
-rw-r--r--engines/toon/tools.h8
-rw-r--r--engines/toon/toon.cpp376
-rw-r--r--engines/toon/toon.h17
33 files changed, 627 insertions, 415 deletions
diff --git a/engines/toon/anim.cpp b/engines/toon/anim.cpp
index 2e63d89f37..856acbd986 100644
--- a/engines/toon/anim.cpp
+++ b/engines/toon/anim.cpp
@@ -23,6 +23,9 @@
*
*/
+#include "common/debug.h"
+#include "common/rect.h"
+
#include "toon/anim.h"
#include "toon/toon.h"
#include "toon/tools.h"
@@ -99,7 +102,7 @@ bool Animation::loadAnimation(Common::String file) {
_frames[e]._data = new uint8[decompressedSize];
if (compressedSize < decompressedSize) {
decompressLZSS(imageData, _frames[e]._data, decompressedSize);
- } else {
+ } else {
memcpy(_frames[e]._data, imageData, compressedSize);
}
}
@@ -151,6 +154,8 @@ void Animation::drawFrame(Graphics::Surface &surface, int32 frame, int32 xx, int
int32 offsX = 0;
int32 offsY = 0;
+ _vm->addDirtyRect(xx + _x1 + _frames[frame]._x1, yy + _y1 + _frames[frame]._y1, xx + rectX + _x1 + _frames[frame]._x1 , yy + rectY + _y1 + _frames[frame]._y1);
+
if (xx + _x1 + _frames[frame]._x1 < 0) {
offsX = -(xx + _x1 + _frames[frame]._x1);
}
@@ -212,14 +217,14 @@ void Animation::drawFrameWithMaskAndScale(Graphics::Surface &surface, int32 fram
int32 finalWidth = rectX * scale / 1024;
int32 finalHeight = rectY * scale / 1024;
- // compute final x1,y1,x2,y2
+ // compute final x1, y1, x2, y2
int32 xx1 = xx + _x1 + _frames[frame]._x1 * scale / 1024;
int32 yy1 = yy + _y1 + _frames[frame]._y1 * scale / 1024;
int32 xx2 = xx1 + finalWidth;
int32 yy2 = yy1 + finalHeight;
int32 w = _frames[frame]._x2 - _frames[frame]._x1;
-// Strangerke - Commented (not used)
-// int32 h = _frames[frame]._y2 - _frames[frame]._y1;
+
+ _vm->addDirtyRect(xx1, yy1, xx2, yy2);
int32 destPitch = surface.pitch;
int32 destPitchMask = mask->getWidth();
@@ -442,7 +447,6 @@ AnimationInstance::AnimationInstance(ToonEngine *vm, AnimationInstanceType type)
_layerZ = 0;
}
-
void AnimationInstance::render() {
debugC(5, kDebugAnim, "render()");
if (_visible && _animation) {
@@ -574,7 +578,7 @@ void AnimationInstance::getRect(int32 *x1, int32 *y1, int32 *x2, int32 *y2) cons
int32 finalWidth = rectX * _scale / 1024;
int32 finalHeight = rectY * _scale / 1024;
- // compute final x1,y1,x2,y2
+ // compute final x1, y1, x2, y2
*x1 = _x + _animation->_x1 + _animation->_frames[_currentFrame]._x1 * _scale / 1024;
*y1 = _y + _animation->_y1 + _animation->_frames[_currentFrame]._y1 * _scale / 1024;
*x2 = *x1 + finalWidth;
@@ -604,7 +608,7 @@ void AnimationInstance::setZ(int32 z, bool relative) {
void AnimationInstance::setLayerZ(int32 z) {
_layerZ = z;
- if (_vm->getAnimationManager()->hasInstance(this))
+ if (_vm->getAnimationManager()->hasInstance(this))
_vm->getAnimationManager()->updateInstance(this);
}
@@ -665,8 +669,6 @@ void AnimationInstance::load(Common::ReadStream *stream) {
_useMask = stream->readSint32LE();
}
-
-
void AnimationInstance::setLooping(bool enable) {
debugC(6, kDebugAnim, "setLooping(%d)", (enable) ? 1 : 0);
_looping = enable;
@@ -682,7 +684,7 @@ AnimationManager::AnimationManager(ToonEngine *vm) : _vm(vm) {
bool AnimationManager::hasInstance(AnimationInstance* instance) {
for (uint32 i = 0; i < _instances.size(); i++) {
- if(_instances[i] == instance)
+ if(_instances[i] == instance)
return true;
}
return false;
@@ -698,12 +700,12 @@ void AnimationManager::addInstance(AnimationInstance *instance) {
// if the instance already exists, we skip the add
for (uint32 i = 0; i < _instances.size(); i++) {
- if(_instances[i] == instance)
+ if(_instances[i] == instance)
return;
}
-
+
int found = -1;
-
+
// here we now do an ordered insert (closer to the original game)
for (uint32 i = 0; i < _instances.size(); i++) {
if (_instances[i]->getLayerZ() >= instance->getLayerZ()) {
@@ -717,7 +719,6 @@ void AnimationManager::addInstance(AnimationInstance *instance) {
} else {
_instances.insert_at(found, instance);
}
-
}
void AnimationManager::removeInstance(AnimationInstance *instance) {
diff --git a/engines/toon/anim.h b/engines/toon/anim.h
index d7f64ab687..dfb6842b0e 100644
--- a/engines/toon/anim.h
+++ b/engines/toon/anim.h
@@ -161,7 +161,7 @@ public:
AnimationInstance *createNewInstance(AnimationInstanceType type);
void addInstance(AnimationInstance *instance);
void removeInstance(AnimationInstance *instance);
- void updateInstance(AnimationInstance* instance);
+ void updateInstance(AnimationInstance* instance);
void removeAllInstances(AnimationInstanceType type);
void render();
void update(int32 timeIncrement);
diff --git a/engines/toon/audio.cpp b/engines/toon/audio.cpp
index e5e5b85832..026450d3c9 100644
--- a/engines/toon/audio.cpp
+++ b/engines/toon/audio.cpp
@@ -23,32 +23,20 @@
*
*/
+#include "common/debug.h"
+
#include "toon/audio.h"
#include "common/memstream.h"
#include "common/substream.h"
+#include "audio/decoders/adpcm_intern.h"
namespace Toon {
-static int ADPCM_index[8] = {
- -1, -1, -1, -1, 2 , 4 , 6 , 8
-};
-static int ADPCM_table[89] = {
- 7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
- 19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
- 50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
- 130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
- 337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
- 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
- 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
- 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
- 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
-};
-
AudioManager::AudioManager(ToonEngine *vm, Audio::Mixer *mixer) : _vm(vm), _mixer(mixer) {
for (int32 i = 0; i < 16; i++)
_channels[i] = NULL;
- for (int32 i = 0; i < 4; i++)
+ for (int32 i = 0; i < 4; i++)
_audioPacks[i] = NULL;
for (int32 i = 0; i < 4; i++) {
@@ -63,6 +51,8 @@ AudioManager::AudioManager(ToonEngine *vm, Audio::Mixer *mixer) : _vm(vm), _mixe
_voiceMuted = false;
_musicMuted = false;
_sfxMuted = false;
+
+ _currentMusicChannel = 0;
}
AudioManager::~AudioManager(void) {
@@ -113,24 +103,23 @@ void AudioManager::playMusic(Common::String dir, Common::String music) {
return;
// see what channel to take
- if (_channels[0] && _channels[0]->isPlaying() && _channels[1] && _channels[1]->isPlaying()) {
- // take the one that is fading
- if (_channels[0]->isFading()) {
- _channels[0]->stop(false);
- _channels[1]->stop(true);
- _currentMusicChannel = 0;
- } else {
- _channels[1]->stop(false);
- _channels[0]->stop(true);
- _currentMusicChannel = 1;
+ // if the current channel didn't really start. reuse this one
+ if (_channels[_currentMusicChannel] && _channels[_currentMusicChannel]->isPlaying()) {
+ if (_channels[_currentMusicChannel]->getPlayedSampleCount() < 500) {
+ _channels[_currentMusicChannel]->stop(false);
+ _currentMusicChannel = 1 - _currentMusicChannel;
+ }
+ else
+ {
+ _channels[_currentMusicChannel]->stop(true);
}
- } else if (_channels[0] && _channels[0]->isPlaying()) {
- _channels[0]->stop(true);
- _currentMusicChannel = 1;
- } else {
- if (_channels[1] && _channels[1]->isPlaying())
- _channels[1]->stop(true);
- _currentMusicChannel = 0;
+ }
+ // go to the next channel
+ _currentMusicChannel = 1 - _currentMusicChannel;
+
+ // if it's already playing.. stop it quickly (no fade)
+ if (_channels[_currentMusicChannel] && _channels[_currentMusicChannel]->isPlaying()) {
+ _channels[_currentMusicChannel]->stop(false);
}
// no need to delete instance here it will automatically deleted by the mixer is done with it
@@ -208,7 +197,6 @@ void AudioManager::stopCurrentVoice() {
_channels[2]->stop(false);
}
-
void AudioManager::closeAudioPack(int32 id) {
delete _audioPacks[id];
_audioPacks[id] = NULL;
@@ -261,6 +249,7 @@ AudioStreamInstance::AudioStreamInstance(AudioManager *man, Audio::Mixer *mixer,
_looping = looping;
_musicAttenuation = 1000;
_deleteFileStream = deleteFileStreamAtEnd;
+ _playedSamples = 0;
// preload one packet
if (_totalSize > 0) {
@@ -286,7 +275,7 @@ AudioStreamInstance::~AudioStreamInstance() {
int AudioStreamInstance::readBuffer(int16 *buffer, const int numSamples) {
debugC(5, kDebugAudio, "readBuffer(buffer, %d)", numSamples);
- if(_stopped)
+ if(_stopped)
return 0;
handleFade(numSamples);
@@ -309,6 +298,8 @@ int AudioStreamInstance::readBuffer(int16 *buffer, const int numSamples) {
_bufferOffset += leftSamples;
}
+ _playedSamples += numSamples;
+
return numSamples;
}
@@ -369,7 +360,7 @@ void AudioStreamInstance::decodeADPCM(uint8 *comp, int16 *dest, int32 packetSize
int32 v31 = v30 & 0x8;
int32 v32 = v30 & 0x7;
- int32 v33 = ADPCM_table[v19];
+ int32 v33 = Audio::Ima_ADPCMStream::_imaTable[v19];
int32 v34 = v33 >> 3;
if (v32 & 4)
v34 += v33;
@@ -380,12 +371,8 @@ void AudioStreamInstance::decodeADPCM(uint8 *comp, int16 *dest, int32 packetSize
if (v32 & 1)
v34 += v33 >> 2;
- v19 += ADPCM_index[v32];
- if (v19 < 0)
- v19 = 0;
-
- if (v19 > 88)
- v19 = 88;
+ v19 += Audio::ADPCMStream::_stepAdjustTable[v32];
+ v19 = CLIP<int32>(v19, 0, ARRAYSIZE(Audio::Ima_ADPCMStream::_imaTable) - 1);
if (v31)
v18 -= v34;
@@ -423,7 +410,7 @@ void AudioStreamInstance::handleFade(int32 numSamples) {
debugC(5, kDebugAudio, "handleFade(%d)", numSamples);
// Fading enabled only for music
- if (_soundType != Audio::Mixer::kMusicSoundType)
+ if (_soundType != Audio::Mixer::kMusicSoundType)
return;
int32 finalVolume = _volume;
@@ -457,7 +444,7 @@ void AudioStreamInstance::handleFade(int32 numSamples) {
_musicAttenuation = 250;
} else {
_musicAttenuation += numSamples >> 5;
- if (_musicAttenuation > 1000)
+ if (_musicAttenuation > 1000)
_musicAttenuation = 1000;
}
@@ -468,9 +455,11 @@ void AudioStreamInstance::stop(bool fade /*= false*/) {
debugC(1, kDebugAudio, "stop(%d)", (fade) ? 1 : 0);
if (fade) {
- _fadingIn = false;
- _fadingOut = true;
- _fadeTime = 0;
+ if (!_fadingOut) {
+ _fadingIn = false;
+ _fadingOut = true;
+ _fadeTime = 0;
+ }
} else {
stopNow();
}
@@ -551,7 +540,7 @@ void AudioManager::startAmbientSFX(int32 id, int32 delay, int32 mode, int32 volu
}
}
- if (found < 0)
+ if (found < 0)
return;
_ambientSFXs[found]._lastTimer = _vm->getOldMilli() - 1;
@@ -610,13 +599,14 @@ void AudioManager::killAllAmbientSFX()
void AudioManager::updateAmbientSFX()
{
- if (_vm->getMoviePlayer()->isPlaying()) return;
+ if (_vm->getMoviePlayer()->isPlaying())
+ return;
for (int32 i = 0; i < 4; i++) {
AudioAmbientSFX* ambient = &_ambientSFXs[i];
if (ambient->_enabled && (ambient->_channel < 0 || !(_channels[ambient->_channel] && _channels[ambient->_channel]->isPlaying()))) {
if(ambient->_mode == 1) {
- if (_vm->randRange(0, 32767) < ambient->_delay) {
+ if (_vm->randRange(0, 32767) < ambient->_delay) {
ambient->_channel = playSFX(ambient->_id, ambient->_volume, false);
}
} else {
@@ -629,6 +619,5 @@ void AudioManager::updateAmbientSFX()
}
}
-
} // End of namespace Toon
diff --git a/engines/toon/audio.h b/engines/toon/audio.h
index 7c1eedfee9..5feae9c5a1 100644
--- a/engines/toon/audio.h
+++ b/engines/toon/audio.h
@@ -52,6 +52,10 @@ public:
return _fadingIn || _fadingOut;
}
+ int32 getPlayedSampleCount() {
+ return _playedSamples;
+ }
+
void setVolume(int32 volume);
protected:
int readBuffer(int16 *buffer, const int numSamples);
@@ -93,6 +97,7 @@ protected:
int32 _volume;
int32 _musicAttenuation;
bool _deleteFileStream;
+ int32 _playedSamples;
};
class AudioStreamPackage {
@@ -133,14 +138,14 @@ public:
void playVoice(int32 id, bool genericVoice);
int32 playSFX(int32 id, int volume, bool genericSFX);
void stopCurrentVoice();
- void stopAllSfxs();
+ void stopAllSfxs();
void setMusicVolume(int32 volume);
void stopMusic();
void muteVoice(bool mute);
void muteMusic(bool mute);
void muteSfx(bool mute);
bool isVoiceMuted() { return _voiceMuted; }
- bool isMusicMuted() { return _musicMuted; }
+ bool isMusicMuted() { return _musicMuted; }
bool isSfxMuted() { return _sfxMuted; }
void startAmbientSFX(int32 id, int32 delay, int32 mode, int32 volume);
diff --git a/engines/toon/character.cpp b/engines/toon/character.cpp
index f1f246e549..29a61ffd78 100644
--- a/engines/toon/character.cpp
+++ b/engines/toon/character.cpp
@@ -23,6 +23,9 @@
*
*/
+#include "common/debug.h"
+#include "common/system.h"
+
#include "toon/character.h"
#include "toon/drew.h"
#include "toon/flux.h"
@@ -64,6 +67,7 @@ Character::Character(ToonEngine *vm) : _vm(vm) {
_lastWalkTime = 0;
_numPixelToWalk = 0;
_nextIdleTime = _vm->getSystem()->getMillis() + (_vm->randRange(0, 600) + 300) * _vm->getTickLength();
+ _lineToSayId = 0;
}
Character::~Character(void) {
@@ -104,7 +108,7 @@ void Character::setFacing(int32 facing) {
_lastWalkTime = _vm->getSystem()->getMillis();
if ((_facing - facing + 8) % 8 > (facing - _facing + 8) % 8)
dir = 1;
- else
+ else
dir = -1;
while (_facing != facing) {
@@ -125,14 +129,13 @@ void Character::setFacing(int32 facing) {
if (_currentPathNode == 0)
playStandingAnim();
else
- playWalkAnim(0,0);
+ playWalkAnim(0, 0);
_vm->doFrame();
};
_flags &= ~2;
}
-
_facing = facing;
}
@@ -140,7 +143,7 @@ void Character::forcePosition(int32 x, int32 y) {
debugC(5, kDebugCharacter, "forcePosition(%d, %d)", x, y);
- setPosition(x,y);
+ setPosition(x, y);
_finalX = x;
_finalY = y;
}
@@ -166,8 +169,9 @@ bool Character::walkTo(int32 newPosX, int32 newPosY) {
_vm->getPathFinding()->resetBlockingRects();
- if (_id == 1) {
- int32 sizeX = MAX<int32>(5, 40 * _vm->getDrew()->getScale() / 1024);
+ // don't allow flux to go at the same position as drew
+ if (_id == 1 ) {
+ int32 sizeX = MAX<int32>(5, 30 * _vm->getDrew()->getScale() / 1024);
int32 sizeY = MAX<int32>(2, 20 * _vm->getDrew()->getScale() / 1024);
_vm->getPathFinding()->addBlockingEllipse(_vm->getDrew()->getFinalX(), _vm->getDrew()->getFinalY(), sizeX, sizeY);
}
@@ -176,7 +180,6 @@ bool Character::walkTo(int32 newPosX, int32 newPosY) {
if (_x == _finalX && _y == _finalY)
return true;
-
if (_vm->getPathFinding()->findPath(_x, _y, _finalX, _finalY)) {
int32 localFinalX = _finalX;
@@ -191,7 +194,7 @@ bool Character::walkTo(int32 newPosX, int32 newPosY) {
_currentPathNodeCount = _vm->getPathFinding()->getPathNodeCount();
_currentPathNode = 0;
stopSpecialAnim();
-
+
_lastWalkTime = _vm->getSystem()->getMillis();
_numPixelToWalk = 0;
@@ -327,11 +330,6 @@ void Character::updateTimers(int32 relativeAdd) {
void Character::stopSpecialAnim() {
debugC(4, kDebugCharacter, "stopSpecialAnim()");
-// Strangerke - Commented (not used)
-#if 0
- if (_animSpecialId != _animSpecialDefaultId)
- delete anim;
-#endif
if (_animScriptId != -1)
_vm->getSceneAnimationScript(_animScriptId)->_frozenForConversation = false;
@@ -388,7 +386,6 @@ void Character::update(int32 timeIncrement) {
if ((_flags & 4) == 0)
return;
-
if (_animScriptId != -1) {
_animationInstance = _vm->getSceneAnimation(this->)
#endif
@@ -423,19 +420,9 @@ void Character::update(int32 timeIncrement) {
return;
}
-// Strangerke - Commented (not used)
-#if 0
- if (_animFlags & 8) {
- if (anim->_flags7 == 0xff && anim->_flags9 == 0xff) {
- // start voice
- }
- }
-#endif
-
if (_animScriptId != -1)
_vm->getSceneAnimationScript(_animScriptId)->_frozenForConversation = true;
-
-
+
// TODO setup backup //
_animFlags |= 0x10;
@@ -494,17 +481,6 @@ void Character::update(int32 timeIncrement) {
}
} else {
nextFrame = currentFrame + 1;
-// Strangerke - Commented (not used)
-#if 0
- if (!_vm->getAudioManager()->voiceStillPlaying()) {
- if (_animFlags & 8) {
- if ((anim->_flags9 == 0xff && nextFrame == anim->_flags6) ||
- (anim->_flags9 != 0xff && nextFrame >= anim->_flags9)) {
- // start really talking
- }
- }
- }
-#endif
if (nextFrame == anim->_flags7 + 1 && (_animFlags & 0x40) == 0) {
if (anim->_flags8 != 1 && (_vm->randRange(0, 1) || anim->_flags8 == 2)) {
_animFlags |= 0x20;
@@ -525,7 +501,6 @@ void Character::update(int32 timeIncrement) {
//label78
-
#if 0
if (_id == 0)
debug(" drew animation name %s / flag %d / frame %d", _specialAnim->_name, _animFlags, nextFrame);
@@ -611,7 +586,6 @@ int32 Character::getScale() {
}
void Character::playWalkAnim(int32 startFrame, int32 endFrame) {
-
}
void Character::setId(int32 id) {
@@ -677,7 +651,6 @@ int32 Character::getAnimScript() {
}
void Character::playTalkAnim() {
-
}
void Character::stopWalk() {
@@ -1046,7 +1019,6 @@ void Character::playAnim(int32 animId, int32 unused, int32 flags) {
*strchr(animName, '?') = '0' + facing;
strcat(animName, ".CAF");
-
if (_animScriptId != -1 && (flags & 8) == 0)
_vm->getSceneAnimationScript(_animScriptId)->_frozenForConversation = true;
@@ -1068,11 +1040,9 @@ void Character::playAnim(int32 animId, int32 unused, int32 flags) {
}
}
-
if (_sceneAnimationId > -1)
setAnimationInstance(_vm->getSceneAnimation(_sceneAnimationId)->_animInstance);
-
_animFlags |= flags;
delete _specialAnim;
diff --git a/engines/toon/character.h b/engines/toon/character.h
index d4079d82ef..e870d81813 100644
--- a/engines/toon/character.h
+++ b/engines/toon/character.h
@@ -49,7 +49,6 @@ struct SpecialCharacterAnimation {
byte _flags9; // 25
};
-
class Character {
public:
Character(ToonEngine *vm);
@@ -106,7 +105,6 @@ public:
int32 getFacingFromDirection(int32 dx, int32 dy);
static const SpecialCharacterAnimation *getSpecialAnimation(int32 characterId, int32 animationId);
-
protected:
ToonEngine *_vm;
diff --git a/engines/toon/conversation.cpp b/engines/toon/conversation.cpp
index 4678ccc1c8..fc846288ef 100644
--- a/engines/toon/conversation.cpp
+++ b/engines/toon/conversation.cpp
@@ -45,5 +45,4 @@ void Conversation::load(Common::ReadStream *stream, int16 *conversationDataBase)
}
}
-
}
diff --git a/engines/toon/conversation.h b/engines/toon/conversation.h
index 784c681055..0380210e02 100644
--- a/engines/toon/conversation.h
+++ b/engines/toon/conversation.h
@@ -33,10 +33,10 @@ namespace Toon {
class Conversation {
public:
- int32 _enable; // 00
+ int32 _enable; // 00
struct ConvState {
- int32 _data2; // 04
+ int32 _data2; // 04
int16 _data3; // 08
void *_data4; // 10
} state[10];
diff --git a/engines/toon/detection.cpp b/engines/toon/detection.cpp
index f8c4c08ce6..ef023564bc 100644
--- a/engines/toon/detection.cpp
+++ b/engines/toon/detection.cpp
@@ -91,6 +91,15 @@ static const ADGameDescription gameDescriptions[] = {
},
Common::DE_DEU, Common::kPlatformPC, ADGF_DEMO, GUIO_NONE
},
+ {
+ "toon", "",
+ {
+ {"local.pak", 0, "8ef3368078b9ea70b305c04db826feea", 2680573},
+ {"generic.svl", 0, "5c42724bb93b360dca7044d6b7ef26e5", 7739319},
+ AD_LISTEND
+ },
+ Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NONE
+ },
AD_TABLE_END_MARKER
};
diff --git a/engines/toon/drew.cpp b/engines/toon/drew.cpp
index eefb4b8efa..77333c4a9f 100644
--- a/engines/toon/drew.cpp
+++ b/engines/toon/drew.cpp
@@ -23,6 +23,8 @@
*
*/
+#include "common/debug.h"
+
#include "toon/drew.h"
namespace Toon {
@@ -111,11 +113,10 @@ void CharacterDrew::update(int32 timeIncrement) {
_scale = _currentScale;
} else if (_currentScale < _scale) {
_scale -= timeIncrement * 2;
- if (_scale < _currentScale)
+ if (_scale < _currentScale)
_scale = _currentScale;
}
setPosition(_x, _y);
-
}
int32 CharacterDrew::getRandomIdleAnim() {
diff --git a/engines/toon/drew.h b/engines/toon/drew.h
index d8091f2225..f248e4aa51 100644
--- a/engines/toon/drew.h
+++ b/engines/toon/drew.h
@@ -28,7 +28,6 @@
#include "toon/character.h"
-
namespace Toon {
class ToonEngine;
@@ -46,7 +45,6 @@ public:
int32 getRandomIdleAnim();
protected:
int32 _currentScale;
-
};
} // End of namespace Toon
diff --git a/engines/toon/flux.cpp b/engines/toon/flux.cpp
index 2b5551732b..833fdbf5ce 100644
--- a/engines/toon/flux.cpp
+++ b/engines/toon/flux.cpp
@@ -23,6 +23,8 @@
*
*/
+#include "common/debug.h"
+
#include "toon/flux.h"
namespace Toon {
@@ -96,7 +98,7 @@ int32 CharacterFlux::fixFacingForAnimation(int32 originalFacing, int32 animation
if (!facingMask)
break;
}
-
+
return finalFacing;
}
diff --git a/engines/toon/flux.h b/engines/toon/flux.h
index a90853cb02..136dedd415 100644
--- a/engines/toon/flux.h
+++ b/engines/toon/flux.h
@@ -26,7 +26,6 @@
#ifndef TOON_FLUX_H
#define TOON_FLUX_H
-
#include "toon/character.h"
class ToonEngine;
diff --git a/engines/toon/font.cpp b/engines/toon/font.cpp
index 8455ca7b61..9367d79036 100644
--- a/engines/toon/font.cpp
+++ b/engines/toon/font.cpp
@@ -23,6 +23,8 @@
*
*/
+#include "common/debug.h"
+
#include "toon/font.h"
namespace Toon {
@@ -81,6 +83,8 @@ void FontRenderer::renderText(int32 x, int32 y, Common::String origText, int32 m
x -= xx / 2;
}
+ _vm->addDirtyRect(x, y, x + xx + 2, y + yy);
+
int32 curX = x;
int32 curY = y;
int32 height = 0;
@@ -212,7 +216,7 @@ void FontRenderer::renderMultiLineText(int32 x, int32 y, Common::String origText
curChar = textToFont(curChar);
int width = _currentFont->getFrameWidth(curChar);
- curWidth += width - 2;
+ curWidth += MAX<int32>(width - 2, 0);
it++;
curLetterNr++;
}
@@ -263,8 +267,8 @@ void FontRenderer::renderMultiLineText(int32 x, int32 y, Common::String origText
if (x - 30 - maxWidth / 2 < 0)
x = maxWidth / 2 + 30;
- if (x + 30 + (maxWidth / 2) > 640)
- x = 640 - (maxWidth / 2) - 30;
+ if (x + 30 + (maxWidth / 2) > TOON_SCREEN_WIDTH)
+ x = TOON_SCREEN_WIDTH - (maxWidth / 2) - 30;
// we have good coordinates now, we can render the multi line
int32 curX = x;
@@ -273,10 +277,12 @@ void FontRenderer::renderMultiLineText(int32 x, int32 y, Common::String origText
for (int32 i = 0; i < numLines; i++) {
const byte *line = lines[i];
curX = x - lineSize[i] / 2;
+ _vm->addDirtyRect(curX + _vm->state()->_currentScrollValue, curY, curX + lineSize[i] + _vm->state()->_currentScrollValue + 2, curY + height);
+
while (*line) {
byte curChar = textToFont(*line);
if (curChar != 32) _currentFont->drawFontFrame(_vm->getMainSurface(), curChar, curX + _vm->state()->_currentScrollValue, curY, _currentFontColor);
- curX = curX + _currentFont->getFrameWidth(curChar) - 2;
+ curX = curX + MAX<int32>(_currentFont->getFrameWidth(curChar) - 2, 0);
//height = MAX(height, _currentFont->getFrameHeight(curChar));
line++;
}
diff --git a/engines/toon/hotspot.cpp b/engines/toon/hotspot.cpp
index 687ea6ee83..1c1e23e39e 100644
--- a/engines/toon/hotspot.cpp
+++ b/engines/toon/hotspot.cpp
@@ -23,6 +23,8 @@
*
*/
+#include "common/debug.h"
+
#include "toon/hotspot.h"
#include "toon/tools.h"
@@ -78,8 +80,6 @@ int32 Hotspots::Find(int32 x, int32 y) {
debugC(6, kDebugHotspot, "Find(%d, %d)", x, y);
int32 priority = -1;
-// Strangerke - Commented (not used)
-// bool found = false;
int32 foundId = -1;
int32 testId = -1;
@@ -91,8 +91,6 @@ int32 Hotspots::Find(int32 x, int32 y) {
testId = i;
if (_items[testId].getPriority() > priority) {
-// Strangerke - Commented (not used)
-// found = true;
foundId = testId;
priority = _items[testId].getPriority();
}
@@ -128,10 +126,10 @@ bool Hotspots::LoadRif(Common::String rifName, Common::String additionalRifName)
// RIFs are compressed in RNC1
RncDecoder decoder;
- decoder.unpackM1(rifData, _items);
+ decoder.unpackM1(rifData, size, _items);
if (rifsize2) {
RncDecoder decoder2;
- decoder2.unpackM1(rifData2 , _items + (rifsize >> 9));
+ decoder2.unpackM1(rifData2 , size2, _items + (rifsize >> 9));
for (int32 i = 0; i < (rifsize2 >> 9); i++) {
HotspotData *hot = _items + (rifsize >> 9) + i;
hot->setData(0, hot->getX1() + 1280);
diff --git a/engines/toon/movie.cpp b/engines/toon/movie.cpp
index c6b57d96e2..64b80c29b3 100644
--- a/engines/toon/movie.cpp
+++ b/engines/toon/movie.cpp
@@ -23,7 +23,16 @@
*
*/
+#include "common/debug.h"
+#include "common/events.h"
+#include "common/keyboard.h"
+#include "common/stream.h"
+#include "common/system.h"
+#include "graphics/surface.h"
+
+#include "toon/audio.h"
#include "toon/movie.h"
+#include "toon/toon.h"
namespace Toon {
@@ -38,8 +47,8 @@ void ToonstruckSmackerDecoder::handleAudioTrack(byte track, uint32 chunkSize, ui
Video::SmackerDecoder::handleAudioTrack(track, chunkSize, unpackedSize);
}
-bool ToonstruckSmackerDecoder::loadFile(const Common::String &filename, int forcedflags) {
- debugC(1, kDebugMovie, "loadFile(%s, %d)", filename.c_str(), forcedflags);
+bool ToonstruckSmackerDecoder::loadFile(const Common::String &filename) {
+ debugC(1, kDebugMovie, "loadFile(%s)", filename.c_str());
_lowRes = false;
@@ -50,14 +59,12 @@ bool ToonstruckSmackerDecoder::loadFile(const Common::String &filename, int forc
delete _surface;
}
_surface = new Graphics::Surface();
- _surface->create(640, 400, 1);
+ _surface->create(640, 400, Graphics::PixelFormat::createFormatCLUT8());
_header.flags = 4;
}
return true;
}
-
-
return false;
}
@@ -88,7 +95,7 @@ void Movie::play(Common::String video, int32 flags) {
_playing = true;
if (flags & 1)
_vm->getAudioManager()->setMusicVolume(0);
- _decoder->loadFile(video.c_str(), flags);
+ _decoder->loadFile(video.c_str());
playVideo(isFirstIntroVideo);
_vm->flushPalette(false);
if (flags & 1)
@@ -107,9 +114,9 @@ bool Movie::playVideo(bool isFirstIntroVideo) {
if (_decoder->isLowRes()) {
// handle manually 2x scaling here
Graphics::Surface* surf = _vm->getSystem()->lockScreen();
- for (int y = 0; y < frame->h/2; y++) {
- memcpy(surf->getBasePtr(0, y*2+0), frame->getBasePtr(0, y), frame->pitch);
- memcpy(surf->getBasePtr(0, y*2+1), frame->getBasePtr(0, y), frame->pitch);
+ for (int y = 0; y < frame->h / 2; y++) {
+ memcpy(surf->getBasePtr(0, y * 2 + 0), frame->getBasePtr(0, y), frame->pitch);
+ memcpy(surf->getBasePtr(0, y * 2 + 1), frame->getBasePtr(0, y), frame->pitch);
}
_vm->getSystem()->unlockScreen();
} else {
@@ -135,11 +142,13 @@ bool Movie::playVideo(bool isFirstIntroVideo) {
Common::Event event;
while (_vm->getSystem()->getEventManager()->pollEvent(event))
if ((event.type == Common::EVENT_KEYDOWN && event.kbd.keycode == Common::KEYCODE_ESCAPE)) {
+ _vm->dirtyAllScreen();
return false;
}
_vm->getSystem()->delayMillis(10);
}
+ _vm->dirtyAllScreen();
return !_vm->shouldQuit();
}
diff --git a/engines/toon/movie.h b/engines/toon/movie.h
index 2a9173850f..bed2ceceae 100644
--- a/engines/toon/movie.h
+++ b/engines/toon/movie.h
@@ -36,7 +36,7 @@ public:
ToonstruckSmackerDecoder(Audio::Mixer *mixer, Audio::Mixer::SoundType soundType = Audio::Mixer::kSFXSoundType);
virtual ~ToonstruckSmackerDecoder() {}
void handleAudioTrack(byte track, uint32 chunkSize, uint32 unpackedSize);
- bool loadFile(const Common::String &filename, int forcedflags);
+ bool loadFile(const Common::String &filename);
bool isLowRes() { return _lowRes; }
protected:
bool _lowRes;
diff --git a/engines/toon/path.cpp b/engines/toon/path.cpp
index 3f948679f4..26355863f6 100644
--- a/engines/toon/path.cpp
+++ b/engines/toon/path.cpp
@@ -23,6 +23,8 @@
*
*/
+#include "common/debug.h"
+
#include "toon/path.h"
namespace Toon {
@@ -186,7 +188,7 @@ int32 PathFinding::findClosestWalkingPoint(int32 xx, int32 yy, int32 *fxx, int32
for (int y = 0; y < _height; y++) {
for (int x = 0; x < _width; x++) {
- if (isWalkable(x, y) && isLikelyWalkable(x,y)) {
+ if (isWalkable(x, y) && isLikelyWalkable(x, y)) {
int32 ndist = (x - xx) * (x - xx) + (y - yy) * (y - yy);
int32 ndist2 = (x - origX) * (x - origX) + (y - origY) * (y - origY);
if (currentFound < 0 || ndist < dist || (ndist == dist && ndist2 < dist2)) {
@@ -283,8 +285,8 @@ int32 PathFinding::findPath(int32 x, int32 y, int32 destx, int32 desty) {
}
// first test direct line
- if (lineIsWalkable(x,y,destx,desty)) {
- walkLine(x,y,destx,desty);
+ if (lineIsWalkable(x, y, destx, desty)) {
+ walkLine(x, y, destx, desty);
return true;
}
@@ -317,7 +319,7 @@ int32 PathFinding::findPath(int32 x, int32 y, int32 destx, int32 desty) {
int32 curPNode = px + py * _width;
if (isWalkable(px, py)) { // walkable ?
- int sum = sq[curNode] + wei * (1 + (isLikelyWalkable(px,py) ? 5 : 0));
+ int sum = sq[curNode] + wei * (1 + (isLikelyWalkable(px, py) ? 5 : 0));
if (sq[curPNode] > sum || !sq[curPNode]) {
int newWeight = abs(destx - px) + abs(desty - py);
sq[curPNode] = sum;
@@ -407,7 +409,11 @@ void PathFinding::init(Picture *mask) {
_height = mask->getHeight();
_currentMask = mask;
_heap->unload();
- _heap->init(_width * _height);
+ // In order to reduce memory fragmentation on small devices, we use the maximum
+ // possible size here which is TOON_BACKBUFFER_WIDTH. Even though this is
+ // 1280 as opposed to the possible 640, it actually helps memory allocation on
+ // those devices.
+ _heap->init(TOON_BACKBUFFER_WIDTH * _height); // should really be _width
delete[] _gridTemp;
_gridTemp = new int32[_width*_height];
}
@@ -438,7 +444,6 @@ void PathFinding::addBlockingEllipse(int32 x1, int32 y1, int32 w, int32 h) {
_numBlockingRects++;
}
-
int32 PathFinding::getPathNodeCount() const {
return _gridPathCount;
}
diff --git a/engines/toon/path.h b/engines/toon/path.h
index a2b1b7bf92..03d2b188e5 100644
--- a/engines/toon/path.h
+++ b/engines/toon/path.h
@@ -91,7 +91,6 @@ protected:
int32 _gridPathCount;
ToonEngine *_vm;
-
};
} // End of namespace Toon
diff --git a/engines/toon/picture.cpp b/engines/toon/picture.cpp
index 18e6a8cf7f..ce28f9c68b 100644
--- a/engines/toon/picture.cpp
+++ b/engines/toon/picture.cpp
@@ -23,16 +23,18 @@
*
*/
-
#include "toon/picture.h"
#include "toon/tools.h"
+
+#include "common/debug.h"
+#include "common/rect.h"
#include "common/stack.h"
namespace Toon {
bool Picture::loadPicture(Common::String file, bool totalPalette /*= false*/) {
debugC(1, kDebugPicture, "loadPicture(%s, %d)", file.c_str(), (totalPalette) ? 1 : 0);
-
+
uint32 size = 0;
uint8 *fileData = _vm->resources()->getFileData(file, &size);
if (!fileData)
@@ -49,12 +51,12 @@ bool Picture::loadPicture(Common::String file, bool totalPalette /*= false*/) {
decompressLZSS(fileData + 8, _data, dstsize);
// size can only be 640x400 or 1280x400
- if (dstsize > 640 * 400 + 768)
- _width = 1280;
+ if (dstsize > TOON_SCREEN_WIDTH * TOON_SCREEN_HEIGHT + 768)
+ _width = TOON_BACKBUFFER_WIDTH;
else
- _width = 640;
+ _width = TOON_SCREEN_WIDTH;
- _height = 400;
+ _height = TOON_SCREEN_HEIGHT;
// do we have a palette ?
_paletteEntries = (dstsize & 0x7ff) / 3;
@@ -69,7 +71,7 @@ bool Picture::loadPicture(Common::String file, bool totalPalette /*= false*/) {
}
case kCompSPCN: {
uint32 decSize = READ_LE_UINT32(fileData + 10);
- _data = new uint8[decSize+100];
+ _data = new uint8[decSize + 100];
_paletteEntries = READ_LE_UINT16(fileData + 14) / 3;
if (_paletteEntries) {
@@ -79,12 +81,12 @@ bool Picture::loadPicture(Common::String file, bool totalPalette /*= false*/) {
}
// size can only be 640x400 or 1280x400
- if (decSize > 640 * 400 + 768)
- _width = 1280;
+ if (decSize > TOON_SCREEN_WIDTH * TOON_SCREEN_HEIGHT + 768)
+ _width = TOON_BACKBUFFER_WIDTH;
else
- _width = 640;
+ _width = TOON_SCREEN_WIDTH;
- _height = 400;
+ _height = TOON_SCREEN_HEIGHT;
// decompress the picture into our buffer
decompressSPCN(fileData + 16 + _paletteEntries * 3, _data, decSize);
@@ -98,15 +100,15 @@ bool Picture::loadPicture(Common::String file, bool totalPalette /*= false*/) {
_data = new uint8[decSize];
- rnc.unpackM1(fileData, _data);
+ rnc.unpackM1(fileData, size, _data);
// size can only be 640x400 or 1280x400
- if (decSize > 640 * 400 + 768)
- _width = 1280;
+ if (decSize > TOON_SCREEN_WIDTH * TOON_SCREEN_HEIGHT + 768)
+ _width = TOON_BACKBUFFER_WIDTH;
else
- _width = 640;
+ _width = TOON_SCREEN_WIDTH;
- _height = 400;
+ _height = TOON_SCREEN_HEIGHT;
return true;
}
case kCompRNC2: {
@@ -119,12 +121,12 @@ bool Picture::loadPicture(Common::String file, bool totalPalette /*= false*/) {
decSize = rnc.unpackM2(fileData, _data);
- if (decSize > 640 * 400 + 768)
- _width = 1280;
+ if (decSize > TOON_SCREEN_WIDTH * TOON_SCREEN_HEIGHT + 768)
+ _width = TOON_BACKBUFFER_WIDTH;
else
- _width = 640;
+ _width = TOON_SCREEN_WIDTH;
- _height = 400;
+ _height = TOON_SCREEN_HEIGHT;
return true;
}
}
@@ -187,6 +189,41 @@ void Picture::drawMask(Graphics::Surface &surface, int32 x, int32 y, int32 dx, i
}
}
+void Picture::drawWithRectList(Graphics::Surface& surface, int32 x, int32 y, int32 dx, int32 dy, Common::Array<Common::Rect>& rectArray) {
+
+ int32 rx = MIN(_width, surface.w - x);
+ int32 ry = MIN(_height, surface.h - y);
+
+ if (rx < 0 || ry < 0)
+ return;
+
+ int32 destPitch = surface.pitch;
+ int32 srcPitch = _width;
+
+ for (uint32 i = 0; i < rectArray.size(); i++) {
+
+ Common::Rect rect = rectArray[i];
+
+ int32 fillRx = MIN<int32>(rx, rect.right - rect.left);
+ int32 fillRy = MIN<int32>(ry, rect.bottom - rect.top);
+
+ uint8 *c = _data + _width * (dy + rect.top) + (dx + rect.left);
+ uint8 *curRow = (uint8 *)surface.pixels + (y + rect.top) * destPitch + (x + rect.left);
+
+ for (int32 yy = 0; yy < fillRy; yy++) {
+ uint8 *curSrc = c;
+ uint8 *cur = curRow;
+ for (int32 xx = 0; xx < fillRx; xx++) {
+ *cur = *curSrc;
+ curSrc++;
+ cur++;
+ }
+ curRow += destPitch;
+ c += srcPitch;
+ }
+ }
+}
+
void Picture::draw(Graphics::Surface &surface, int32 x, int32 y, int32 dx, int32 dy) {
debugC(6, kDebugPicture, "draw(surface, %d, %d, %d, %d)", x, y, dx, dy);
@@ -279,7 +316,6 @@ void Picture::drawLineOnMask(int32 x, int32 y, int32 x2, int32 y2, bool walkable
else
t = adx;
-
int32 cdx = (dx << 16) / t;
int32 cdy = (dy << 16) / t;
@@ -289,15 +325,15 @@ void Picture::drawLineOnMask(int32 x, int32 y, int32 x2, int32 y2, bool walkable
int32 rx = bx >> 16;
int32 ry = by >> 16;
- if( rx >= 0 && rx < _width-1 && ry >= 0 && ry < _height) { // sanity check: some lines in the game
+ if( rx >= 0 && rx < _width-1 && ry >= 0 && ry < _height) { // sanity check: some lines in the game
// were drawing outside the screen causing corruption
if (!walkable) {
_data[_width * ry + rx] &= 0xe0;
- _data[_width * ry + rx+1] &= 0xe0;
+ _data[_width * ry + rx + 1] &= 0xe0;
} else {
int32 v = _data[_width * (by >> 16) + rx - 1];
_data[_width * ry + rx] = v;
- _data[_width * ry + rx+1] = v;
+ _data[_width * ry + rx + 1] = v;
}
}
diff --git a/engines/toon/picture.h b/engines/toon/picture.h
index 1b0fd7f550..6aca408364 100644
--- a/engines/toon/picture.h
+++ b/engines/toon/picture.h
@@ -44,6 +44,7 @@ public:
bool loadPicture(Common::String file, bool totalPalette = false);
void setupPalette();
void draw(Graphics::Surface &surface, int32 x, int32 y, int32 dx, int32 dy);
+ void drawWithRectList(Graphics::Surface& surface, int32 x, int32 y, int32 dx, int32 dy, Common::Array<Common::Rect>& rectArray);
void drawMask(Graphics::Surface &surface, int32 x, int32 y, int32 dx, int32 dy);
void drawLineOnMask(int32 x, int32 y, int32 x2, int32 y2, bool walkable);
void floodFillNotWalkableOnMask(int32 x, int32 y);
diff --git a/engines/toon/resource.cpp b/engines/toon/resource.cpp
index 61e3ffb111..f9f65b423b 100644
--- a/engines/toon/resource.cpp
+++ b/engines/toon/resource.cpp
@@ -24,18 +24,26 @@
*/
#include "toon/resource.h"
+#include "common/debug.h"
#include "common/file.h"
#include "common/memstream.h"
#include "common/substream.h"
#include "toon/toon.h"
-
namespace Toon {
-Resources::Resources(ToonEngine *vm) : _vm(vm) {
+Resources::Resources(ToonEngine *vm) : _vm(vm), _cacheSize(0) {
+ _resourceCache.clear();
}
Resources::~Resources() {
+
+ while (!_resourceCache.empty()) {
+ CacheEntry *temp = _resourceCache.back();
+ _resourceCache.pop_back();
+ delete temp;
+ }
+
while(!_pakFiles.empty()) {
PakFile *temp = _pakFiles.back();
_pakFiles.pop_back();
@@ -45,8 +53,73 @@ Resources::~Resources() {
purgeFileData();
}
-void Resources::openPackage(Common::String fileName, bool preloadEntirePackage) {
- debugC(1, kDebugResource, "openPackage(%s, %d)", fileName.c_str(), (preloadEntirePackage) ? 1 : 0);
+void Resources::removePackageFromCache(Common::String packName) {
+ // I'm not sure what's a good strategy here. It seems unnecessary to
+ // actually remove the cached resources, because the player may be
+ // wandering back and forth between rooms. So for now, do nothing.
+}
+
+bool Resources::getFromCache(Common::String fileName, uint32 *fileSize, uint8 **fileData) {
+ for (Common::Array<CacheEntry *>::iterator entry = _resourceCache.begin(); entry != _resourceCache.end(); ++entry) {
+ if ((*entry)->_data && (*entry)->_fileName.compareToIgnoreCase(fileName) == 0) {
+ debugC(5, kDebugResource, "getFromCache(%s) - Got %d bytes from %s", fileName.c_str(), (*entry)->_size, (*entry)->_packName.c_str());
+ (*entry)->_age = 0;
+ *fileSize = (*entry)->_size;
+ *fileData = (*entry)->_data;
+ return true;
+ }
+ }
+ return false;
+}
+
+void Resources::addToCache(Common::String packName, Common::String fileName, uint32 fileSize, uint8 *fileData) {
+ debugC(5, kDebugResource, "addToCache(%s, %s, %d) - Total Size: %d", packName.c_str(), fileName.c_str(), fileSize, _cacheSize + fileSize);
+ for (Common::Array<CacheEntry *>::iterator entry = _resourceCache.begin(); entry != _resourceCache.end(); ++entry) {
+ if ((*entry)->_data) {
+ (*entry)->_age++;
+ }
+ }
+ _cacheSize += fileSize;
+
+ while (_cacheSize > MAX_CACHE_SIZE) {
+ CacheEntry *bestEntry = 0;
+ for (Common::Array<CacheEntry *>::iterator entry = _resourceCache.begin(); entry != _resourceCache.end(); ++entry) {
+ if ((*entry)->_data) {
+ if (!bestEntry || ((*entry)->_age >= bestEntry->_age && (*entry)->_size >= bestEntry->_size)) {
+ bestEntry = *entry;
+ }
+ }
+ }
+ if (!bestEntry)
+ break;
+
+ free(bestEntry->_data);
+ bestEntry->_data = 0;
+ _cacheSize -= bestEntry->_size;
+ debugC(5, kDebugResource, "Freed %s (%s) to reclaim %d bytes", bestEntry->_fileName.c_str(), bestEntry->_packName.c_str(), bestEntry->_size);
+ }
+
+ for (Common::Array<CacheEntry *>::iterator entry = _resourceCache.begin(); entry != _resourceCache.end(); ++entry) {
+ if (!(*entry)->_data) {
+ (*entry)->_packName = packName;
+ (*entry)->_fileName = fileName;
+ (*entry)->_age = 0;
+ (*entry)->_size = fileSize;
+ (*entry)->_data = fileData;
+ return;
+ }
+ }
+
+ CacheEntry *entry = new CacheEntry();
+ entry->_packName = packName;
+ entry->_fileName = fileName;
+ entry->_size = fileSize;
+ entry->_data = fileData;
+ _resourceCache.push_back(entry);
+}
+
+void Resources::openPackage(Common::String fileName) {
+ debugC(1, kDebugResource, "openPackage(%s)", fileName.c_str());
Common::File file;
bool opened = file.open(fileName);
@@ -55,15 +128,16 @@ void Resources::openPackage(Common::String fileName, bool preloadEntirePackage)
return;
PakFile *pakFile = new PakFile();
- pakFile->open(&file, fileName, preloadEntirePackage);
+ pakFile->open(&file, fileName);
- if (preloadEntirePackage)
- file.close();
+ file.close();
_pakFiles.push_back(pakFile);
}
void Resources::closePackage(Common::String fileName) {
+
+ removePackageFromCache(fileName);
for (uint32 i = 0; i < _pakFiles.size(); i++) {
if (_pakFiles[i]->getPackName() == fileName) {
delete _pakFiles[i];
@@ -91,13 +165,21 @@ uint8 *Resources::getFileData(Common::String fileName, uint32 *fileSize) {
_allocatedFileData.push_back(memory);
return memory;
} else {
+
+ uint32 locFileSize = 0;
+ uint8 *locFileData = 0;
+
+ if (getFromCache(fileName, &locFileSize, &locFileData)) {
+ *fileSize = locFileSize;
+ return locFileData;
+ }
+
for (uint32 i = 0; i < _pakFiles.size(); i++) {
- uint32 locFileSize = 0;
- uint8 *locFileData = 0;
locFileData = _pakFiles[i]->getFileData(fileName, &locFileSize);
if (locFileData) {
*fileSize = locFileSize;
+ addToCache(_pakFiles[i]->getPackName(), fileName, locFileSize, locFileData);
return locFileData;
}
}
@@ -136,25 +218,16 @@ void Resources::purgeFileData() {
}
_allocatedFileData.clear();
}
+
Common::SeekableReadStream *PakFile::createReadStream(Common::String fileName) {
debugC(1, kDebugResource, "createReadStream(%s)", fileName.c_str());
- int32 offset = 0;
- int32 size = 0;
- for (uint32 i = 0; i < _numFiles; i++) {
- if (fileName.compareToIgnoreCase(_files[i]._name) == 0) {
- size = _files[i]._size;
- offset = _files[i]._offset;
- break;
- }
- }
- if (!size)
- return 0;
-
- if (_fileHandle)
- return new Common::SeekableSubReadStream(_fileHandle, offset, offset + size);
+ uint32 fileSize = 0;
+ uint8 *buffer = getFileData(fileName, &fileSize);
+ if (buffer)
+ return new Common::MemoryReadStream(buffer, fileSize, DisposeAfterUse::YES);
else
- return new Common::MemoryReadStream(_buffer + offset, size);
+ return 0;
}
uint8 *PakFile::getFileData(Common::String fileName, uint32 *fileSize) {
@@ -162,16 +235,26 @@ uint8 *PakFile::getFileData(Common::String fileName, uint32 *fileSize) {
for (uint32 i = 0; i < _numFiles; i++) {
if (fileName.compareToIgnoreCase(_files[i]._name) == 0) {
- *fileSize = _files[i]._size;
- return _buffer + _files[i]._offset;
+ Common::File file;
+ if (file.open(_packName)) {
+ *fileSize = _files[i]._size;
+ file.seek(_files[i]._offset);
+
+ // Use malloc() because that's what MemoryReadStream
+ // uses to dispose of the memory when it's done.
+ uint8 *buffer = (uint8 *)malloc(*fileSize);
+ file.read(buffer, *fileSize);
+ file.close();
+ return buffer;
+ }
}
}
return 0;
}
-void PakFile::open(Common::SeekableReadStream *rs, Common::String packName, bool preloadEntirePackage) {
- debugC(1, kDebugResource, "open(rs, %d)", (preloadEntirePackage) ? 1 : 0);
+void PakFile::open(Common::SeekableReadStream *rs, Common::String packName) {
+ debugC(1, kDebugResource, "open(rs)");
char buffer[64];
int32 currentPos = 0;
@@ -199,30 +282,12 @@ void PakFile::open(Common::SeekableReadStream *rs, Common::String packName, bool
_numFiles++;
_files.push_back(newFile);
}
-
- if (preloadEntirePackage) {
- _bufferSize = rs->size();
- delete[] _buffer;
- _buffer = new uint8[_bufferSize];
- rs->seek(0);
- rs->read(_buffer, _bufferSize);
- }
}
void PakFile::close() {
- delete[] _buffer;
-
- if (_fileHandle) {
- _fileHandle->close();
- delete _fileHandle;
- }
}
PakFile::PakFile() {
- _bufferSize = 0;
- _buffer = NULL;
-
- _fileHandle = NULL;
}
PakFile::~PakFile() {
diff --git a/engines/toon/resource.h b/engines/toon/resource.h
index e117c8e259..d6ed29b81b 100644
--- a/engines/toon/resource.h
+++ b/engines/toon/resource.h
@@ -31,6 +31,8 @@
#include "common/file.h"
#include "common/stream.h"
+#define MAX_CACHE_SIZE (4 * 1024 * 1024)
+
namespace Toon {
class PakFile {
@@ -38,7 +40,7 @@ public:
PakFile();
~PakFile();
- void open(Common::SeekableReadStream *rs, Common::String packName, bool preloadEntirePackage);
+ void open(Common::SeekableReadStream *rs, Common::String packName);
uint8 *getFileData(Common::String fileName, uint32 *fileSize);
Common::String getPackName() { return _packName; }
Common::SeekableReadStream *createReadStream(Common::String fileName);
@@ -52,9 +54,6 @@ protected:
};
Common::String _packName;
- uint8 *_buffer;
- int32 _bufferSize;
-
uint32 _numFiles;
Common::Array<File> _files;
Common::File *_fileHandle;
@@ -62,11 +61,25 @@ protected:
class ToonEngine;
+class CacheEntry {
+public:
+ CacheEntry() : _age(0), _size(0), _data(0) {}
+ ~CacheEntry() {
+ free(_data);
+ }
+
+ Common::String _packName;
+ Common::String _fileName;
+ uint32 _age;
+ uint32 _size;
+ uint8 *_data;
+};
+
class Resources {
public:
Resources(ToonEngine *vm);
~Resources();
- void openPackage(Common::String file, bool preloadEntirePackage);
+ void openPackage(Common::String file);
void closePackage(Common::String fileName);
Common::SeekableReadStream *openFile(Common::String file);
uint8 *getFileData(Common::String fileName, uint32 *fileSize); // this memory must be copied to your own structures!
@@ -76,6 +89,12 @@ protected:
ToonEngine *_vm;
Common::Array<uint8 *> _allocatedFileData;
Common::Array<PakFile *> _pakFiles;
+ uint32 _cacheSize;
+ Common::Array<CacheEntry *> _resourceCache;
+
+ void removePackageFromCache(Common::String packName);
+ bool getFromCache(Common::String fileName, uint32 *fileSize, uint8 **fileData);
+ void addToCache(Common::String packName, Common::String fileName, uint32 fileSize, uint8 *fileData);
};
} // End of namespace Toon
diff --git a/engines/toon/script.cpp b/engines/toon/script.cpp
index 3cd56761f6..8703666781 100644
--- a/engines/toon/script.cpp
+++ b/engines/toon/script.cpp
@@ -23,11 +23,9 @@
*
*/
-
+#include "common/debug.h"
#include "common/endian.h"
#include "common/stream.h"
-#include "common/util.h"
-#include "common/system.h"
#include "toon/toon.h"
#include "toon/script.h"
@@ -71,7 +69,7 @@ EMCInterpreter::~EMCInterpreter() {
bool EMCInterpreter::callback(Common::IFFChunk &chunk) {
switch (chunk._type) {
- case MKID_BE('TEXT'):
+ case MKTAG('T','E','X','T'):
delete[] _scriptData->text;
_scriptData->text = new byte[chunk._size];
assert(_scriptData->text);
@@ -79,7 +77,7 @@ bool EMCInterpreter::callback(Common::IFFChunk &chunk) {
error("Couldn't read TEXT chunk from file '%s'", _filename);
break;
- case MKID_BE('ORDR'):
+ case MKTAG('O','R','D','R'):
delete[] _scriptData->ordr;
_scriptData->ordr = new uint16[chunk._size >> 1];
assert(_scriptData->ordr);
@@ -90,7 +88,7 @@ bool EMCInterpreter::callback(Common::IFFChunk &chunk) {
_scriptData->ordr[i] = READ_BE_UINT16(&_scriptData->ordr[i]);
break;
- case MKID_BE('DATA'):
+ case MKTAG('D','A','T','A'):
delete[] _scriptData->data;
_scriptData->data = new uint16[chunk._size >> 1];
assert(_scriptData->data);
@@ -177,7 +175,7 @@ bool EMCInterpreter::start(EMCState *script, int function) {
if (functionOffset == 0xFFFF)
return false;
- script->ip = &script->dataPtr->data[functionOffset+1];
+ script->ip = &script->dataPtr->data[functionOffset + 1];
return true;
}
diff --git a/engines/toon/script.h b/engines/toon/script.h
index 6c46238238..b6d28e1171 100644
--- a/engines/toon/script.h
+++ b/engines/toon/script.h
@@ -31,7 +31,6 @@
#include "common/func.h"
#include "common/iff_container.h"
-
// Based on Kyra script interpretor
namespace Toon {
@@ -88,9 +87,9 @@ public:
// Both lead to some problems in our IFF parser, either reading after the end
// of file or producing a "Chunk overread" error message. To work around this
// we need to adjust the size field properly.
- if (_formType == MKID_BE('EMC2'))
+ if (_formType == MKTAG('E','M','C','2'))
_formChunk.size -= 8;
- else if (_formType == MKID_BE('AVFS'))
+ else if (_formType == MKTAG('A','V','F','S'))
_formChunk.size += 4;
}
};
diff --git a/engines/toon/script_func.cpp b/engines/toon/script_func.cpp
index adf3a1c9cc..8f75097bd4 100644
--- a/engines/toon/script_func.cpp
+++ b/engines/toon/script_func.cpp
@@ -23,6 +23,9 @@
*
*/
+#include "common/debug.h"
+#include "common/system.h"
+
#include "toon/script_func.h"
#include "toon/script.h"
#include "toon/state.h"
@@ -265,7 +268,6 @@ int32 ScriptFunc::sys_Cmd_Draw_Actor_Standing(EMCState *state) {
arg1 = 1;
}
-
if (arg2 > -1)
_vm->getDrew()->forceFacing(arg2);
@@ -461,7 +463,7 @@ int32 ScriptFunc::sys_Cmd_Actor_Talks(EMCState *state) {
}
int32 ScriptFunc::sys_Cmd_Say_Lines(EMCState *state) {
-
+
// WORKAROUND: In the scene 4 (Castle), if you click twice on the closed door, Drew disappears
// the script makes him disappear for the custom animation and not reappear.
if (_vm->state()->_currentScene == 4 && stackPos(1) == 562) {
@@ -491,11 +493,11 @@ int32 ScriptFunc::sys_Cmd_Empty_Inventory(EMCState *state) {
int32 ScriptFunc::sys_Cmd_Set_Anim_Scale_Size(EMCState *state) {
int32 animID = stackPos(0);
int32 scale = stackPos(1);
-
+
SceneAnimation *sceneAnim = _vm->getSceneAnimation(animID);
if (sceneAnim) {
sceneAnim->_animInstance->setUseMask(true);
- sceneAnim->_animInstance->setScale(scale,true);
+ sceneAnim->_animInstance->setScale(scale, true);
}
return 0;
}
@@ -939,8 +941,6 @@ int32 ScriptFunc::sys_Cmd_Init_Scene_Anim(EMCState *state) {
sceneAnim->_animInstance->setAnimationRange(stackPos(11), stackPos(11));
sceneAnim->_animInstance->setFrame(stackPos(11));
-
-
debugC(0, 0xfff, "Init Anim %s %d %d %d %d %d %d %d %d %d %d %d %d %d\n", GetText(12, state), stackPos(0), stackPos(1), stackPos(2), stackPos(3),
stackPos(4), stackPos(5), stackPos(6), stackPos(7), stackPos(8), stackPos(9), stackPos(10), stackPos(11), stackPos(12));
@@ -950,7 +950,7 @@ int32 ScriptFunc::sys_Cmd_Init_Scene_Anim(EMCState *state) {
int32 layerZ = stackPos(3);
if (dx == -2)
- sceneAnim->_animInstance->moveRelative(640, 0, 0);
+ sceneAnim->_animInstance->moveRelative(TOON_SCREEN_WIDTH, 0, 0);
else if (dx < 0) {
dx = sceneAnim->_animation->_x1;
}
@@ -1028,7 +1028,7 @@ int32 ScriptFunc::sys_Cmd_Draw_Scene_Anim_WSA_Frame(EMCState *state) {
else if (animId == 20 || animId == 15 || animId == 21 || animId == 16 || animId == 17 || animId == 18)
_vm->pauseSceneAnimationScript(_vm->getCurrentUpdatingSceneAnimation(), 1);
else if (animId == 9) {
- _vm->pauseSceneAnimationScript(_vm->getCurrentUpdatingSceneAnimation(), 6);
+ _vm->pauseSceneAnimationScript(_vm->getCurrentUpdatingSceneAnimation(), 3);
}
}
@@ -1091,13 +1091,13 @@ int32 ScriptFunc::sys_Cmd_Proceed_To_Next_Chapter(EMCState *state) {
}
int32 ScriptFunc::sys_Cmd_Play_Sfx_Plus(EMCState *state) {
- //debugC(0,0xfff, "playSfx ( %d , %d, %d, %d, %d )", stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4));
+ //debugC(0, 0xfff, "playSfx ( %d , %d, %d, %d, %d )", stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4));
_vm->playSFX(stackPos(0), stackPos(1));
return 0;
}
int32 ScriptFunc::sys_Cmd_Play_Sfx(EMCState *state) {
- //debugC(0,0xfff, "playSfx ( %d , %d)", stackPos(0), stackPos(1));
+ //debugC(0, 0xfff, "playSfx ( %d , %d)", stackPos(0), stackPos(1));
_vm->playSFX(stackPos(0), stackPos(1));
return 0;
}
diff --git a/engines/toon/state.cpp b/engines/toon/state.cpp
index f676a65025..af37ea9e68 100644
--- a/engines/toon/state.cpp
+++ b/engines/toon/state.cpp
@@ -23,6 +23,8 @@
*
*/
+#include "common/debug.h"
+
#include "toon/state.h"
#include "toon/toon.h"
@@ -119,7 +121,6 @@ State::State(void) {
}
State::~State(void) {
-
}
int32 State::getGameFlag(int32 flagId) {
diff --git a/engines/toon/state.h b/engines/toon/state.h
index d31ff4f3c2..63505fd5fb 100644
--- a/engines/toon/state.h
+++ b/engines/toon/state.h
@@ -81,7 +81,6 @@ public:
int32 _nextSpecialEnterX;
int32 _nextSpecialEnterY;
-
bool _timerEnabled[2];
int32 _timerTimeout[2];
int32 _timerDelay[2];
@@ -94,7 +93,6 @@ public:
void loadConversations(Common::ReadStream *stream);
void saveConversations(Common::WriteStream *stream);
-
};
} // End of namespace Toon
diff --git a/engines/toon/text.cpp b/engines/toon/text.cpp
index f0d17dd34e..94a3ea5aa7 100644
--- a/engines/toon/text.cpp
+++ b/engines/toon/text.cpp
@@ -23,6 +23,8 @@
*
*/
+#include "common/debug.h"
+
#include "toon/text.h"
namespace Toon {
diff --git a/engines/toon/tools.cpp b/engines/toon/tools.cpp
index a03a2d57ce..ff72e69543 100644
--- a/engines/toon/tools.cpp
+++ b/engines/toon/tools.cpp
@@ -23,6 +23,8 @@
*
*/
+#include "common/debug.h"
+
#include "toon/tools.h"
#include "toon/toon.h"
@@ -125,7 +127,6 @@ uint32 decompressSPCN(byte *src, byte *dst, uint32 dstsize) {
return (dstp - dst);
}
-
//return codes
#define NOT_PACKED 0
#define PACKED_CRC -1
@@ -201,7 +202,16 @@ uint16 RncDecoder::inputBits(uint8 amount) {
newBitBuffl >>= newBitCount;
newBitBuffl |= remBits;
_srcPtr += 2;
- newBitBuffh = READ_LE_UINT16(_srcPtr);
+
+ // added some more check here to prevent reading in the buffer
+ // if there are no bytes anymore.
+ _inputByteLeft -= 2;
+ if (_inputByteLeft <= 0)
+ newBitBuffh = 0;
+ else if (_inputByteLeft == 1)
+ newBitBuffh = *_srcPtr;
+ else
+ newBitBuffh = READ_LE_UINT16(_srcPtr);
amount -= newBitCount;
newBitCount = 16 - amount;
}
@@ -284,7 +294,7 @@ int RncDecoder::getbit() {
return temp;
}
-int32 RncDecoder::unpackM1(const void *input, void *output) {
+int32 RncDecoder::unpackM1(const void *input, uint16 inputSize, void *output) {
debugC(1, kDebugTools, "unpackM1(input, output)");
uint8 *outputLow, *outputHigh;
@@ -297,6 +307,7 @@ int32 RncDecoder::unpackM1(const void *input, void *output) {
uint16 crcPacked = 0;
+ _inputByteLeft = inputSize;
_bitBuffl = 0;
_bitBuffh = 0;
_bitCount = 0;
@@ -339,9 +350,12 @@ int32 RncDecoder::unpackM1(const void *input, void *output) {
_srcPtr = (_dstPtr - packLen);
}
+ _inputByteLeft -= HEADER_LEN;
+
_dstPtr = (uint8 *)output;
_bitCount = 0;
+
_bitBuffl = READ_LE_UINT16(_srcPtr);
inputBits(2);
@@ -360,8 +374,22 @@ int32 RncDecoder::unpackM1(const void *input, void *output) {
memcpy(_dstPtr, _srcPtr, inputLength); //memcpy is allowed here
_dstPtr += inputLength;
_srcPtr += inputLength;
- uint16 a = READ_LE_UINT16(_srcPtr);
- uint16 b = READ_LE_UINT16(_srcPtr + 2);
+ _inputByteLeft -= inputLength;
+ uint16 a;
+ if (_inputByteLeft <= 0)
+ a = 0;
+ else if (_inputByteLeft == 1)
+ a = *_srcPtr;
+ else
+ a = READ_LE_UINT16(_srcPtr);
+
+ uint16 b;
+ if (_inputByteLeft <= 2)
+ b = 0;
+ else if(_inputByteLeft == 3)
+ b = *(_srcPtr + 2);
+ else
+ b = READ_LE_UINT16(_srcPtr + 2);
_bitBuffl &= ((1 << _bitCount) - 1);
_bitBuffl |= (a << _bitCount);
@@ -397,9 +425,6 @@ int32 RncDecoder::unpackM2(const void *input, void *output) {
uint16 crcUnpacked = 0;
uint16 crcPacked = 0;
-// Strangerke - Commented (not used)
-// uint16 counts = 0;
-
_bitBuffl = 0;
_bitCount = 0;
@@ -429,7 +454,6 @@ int32 RncDecoder::unpackM2(const void *input, void *output) {
_srcPtr = inputptr;
_dstPtr = (uint8 *)output;
-
uint16 ofs, len;
byte ofs_hi, ofs_lo;
diff --git a/engines/toon/tools.h b/engines/toon/tools.h
index 05fc5c9cda..1434ca26c7 100644
--- a/engines/toon/tools.h
+++ b/engines/toon/tools.h
@@ -42,8 +42,8 @@ const uint32 kCompRNC2 = 0x524E4302;
#define READ_LE_INT16(x) (int16) READ_LE_UINT16(x)
#define READ_LE_INT32(x) (int32) READ_LE_UINT32(x)
-#define WRITE_LE_INT16(x,y) WRITE_LE_UINT16(x,(int16)y)
-#define WRITE_LE_INT32(x,y) WRITE_LE_UINT32(x,(int32)y)
+#define WRITE_LE_INT16(x, y) WRITE_LE_UINT16(x, (int16)y)
+#define WRITE_LE_INT32(x, y) WRITE_LE_UINT32(x, (int32)y)
uint32 decompressSPCN(byte *src, byte *dst, uint32 dstsize);
uint32 decompressLZSS(byte *src, byte *dst, int dstsize);
@@ -63,10 +63,12 @@ protected:
const uint8 *_srcPtr;
uint8 *_dstPtr;
+ int16 _inputByteLeft;
+
public:
RncDecoder();
~RncDecoder();
- int32 unpackM1(const void *input, void *output);
+ int32 unpackM1(const void *input, uint16 inputSize, void *output);
int32 unpackM2(const void *input, void *output);
protected:
diff --git a/engines/toon/toon.cpp b/engines/toon/toon.cpp
index d65230df85..81c4d313e4 100644
--- a/engines/toon/toon.cpp
+++ b/engines/toon/toon.cpp
@@ -33,6 +33,7 @@
#include "common/memstream.h"
#include "engines/util.h"
+#include "graphics/palette.h"
#include "graphics/surface.h"
#include "graphics/thumbnail.h"
#include "gui/saveload.h"
@@ -49,7 +50,6 @@
namespace Toon {
-
void ToonEngine::init() {
_currentScriptRegion = 0;
_resources = new Resources(this);
@@ -58,7 +58,7 @@ void ToonEngine::init() {
_hotspots = new Hotspots(this);
_mainSurface = new Graphics::Surface();
- _mainSurface->create(1280, 400, 1);
+ _mainSurface->create(TOON_BACKBUFFER_WIDTH, TOON_BACKBUFFER_HEIGHT, Graphics::PixelFormat::createFormatCLUT8());
_finalPalette = new uint8[768];
_backupPalette = new uint8[768];
@@ -101,14 +101,13 @@ void ToonEngine::init() {
SearchMan.addSubDirectoryMatching(gameDataDir, "ACT1");
SearchMan.addSubDirectoryMatching(gameDataDir, "ACT2");
-
syncSoundSettings();
_pathFinding = new PathFinding(this);
- resources()->openPackage("LOCAL.PAK", true);
- resources()->openPackage("ONETIME.PAK", true);
- resources()->openPackage("DREW.PAK", true);
+ resources()->openPackage("LOCAL.PAK");
+ resources()->openPackage("ONETIME.PAK");
+ resources()->openPackage("DREW.PAK");
for (int32 i = 0; i < 32; i++)
_characters[i] = NULL;
@@ -118,6 +117,8 @@ void ToonEngine::init() {
_drew = _characters[0];
_flux = _characters[1];
+
+
// preload walk anim for flux and drew
_drew->loadWalkAnimation("STNDWALK.CAF");
_drew->setupPalette();
@@ -137,6 +138,9 @@ void ToonEngine::init() {
memset(_sceneAnimations, 0, sizeof(_sceneAnimations));
memset(_sceneAnimationScripts, 0, sizeof(_sceneAnimationScripts));
+ _drew->setVisible(false);
+ _flux->setVisible(false);
+
_gameState->_currentChapter = 1;
initChapter();
loadCursor();
@@ -262,7 +266,6 @@ void ToonEngine::parseInput() {
selectHotspot();
clickEvent();
}
-
}
void ToonEngine::enableTimer(int32 timerId) {
@@ -325,8 +328,8 @@ void ToonEngine::updateScrolling(bool force, int32 timeIncrement) {
if ((_gameState->_locations[_gameState->_currentScene]._flags & 0x80) == 0) {
if (desiredScrollValue < 0)
desiredScrollValue = 0;
- if (desiredScrollValue >= _currentPicture->getWidth() - 640)
- desiredScrollValue = _currentPicture->getWidth() - 640;
+ if (desiredScrollValue >= _currentPicture->getWidth() - TOON_SCREEN_WIDTH)
+ desiredScrollValue = _currentPicture->getWidth() - TOON_SCREEN_WIDTH;
if (force) {
_gameState->_currentScrollValue = desiredScrollValue;
@@ -378,12 +381,23 @@ void ToonEngine::updateTimer(int32 timeIncrement) {
}
void ToonEngine::render() {
- if (_gameState->_inCutaway)
- _currentCutaway->draw(*_mainSurface, 0, 0, 0, 0);
- else
- _currentPicture->draw(*_mainSurface, 0, 0, 0, 0);
- //_currentMask->drawMask(*_mainSurface,0,0,0,0);
+ if (_dirtyAll) {
+ if (_gameState->_inCutaway)
+ _currentCutaway->draw(*_mainSurface, 0, 0, 0, 0);
+ else
+ _currentPicture->draw(*_mainSurface, 0, 0, 0, 0);
+ _dirtyRects.push_back(Common::Rect(0, 0, TOON_BACKBUFFER_WIDTH, TOON_BACKBUFFER_HEIGHT));
+ } else {
+ if (_gameState->_inCutaway)
+ _currentCutaway->drawWithRectList(*_mainSurface, 0, 0, 0, 0, _dirtyRects);
+ else
+ _currentPicture->drawWithRectList(*_mainSurface, 0, 0, 0, 0, _dirtyRects);
+ }
+
+ clearDirtyRects();
+
+ //_currentMask->drawMask(*_mainSurface, 0, 0, 0, 0);
_animationManager->render();
drawInfoLine();
@@ -399,7 +413,7 @@ void ToonEngine::render() {
sprintf(test, "%d %d / mask %d layer %d z %d", _mouseX, _mouseY, getMask()->getData(_mouseX, _mouseY), getLayerAtPoint(_mouseX, _mouseY), getZAtPoint(_mouseX, _mouseY));
int32 c = *(uint8 *)_mainSurface->getBasePtr(_mouseX, _mouseY);
- sprintf(test, "%d %d / color id %d %d,%d,%d", _mouseX, _mouseY, c, _finalPalette[c*3+0], _finalPalette[c*3+1], _finalPalette[c*3+2]);
+ sprintf(test, "%d %d / color id %d %d,%d,%d", _mouseX, _mouseY, c, _finalPalette[c * 3 + 0], _finalPalette[c * 3 + 1], _finalPalette[c * 3 + 2]);
_fontRenderer->setFont(_fontToon);
_fontRenderer->renderText(40, 150, Common::String(test), 0);
@@ -422,8 +436,8 @@ void ToonEngine::render() {
// add a little sleep here
int32 newMillis = (int32)_system->getMillis();
int32 sleepMs = 1; // Minimum delay to allow thread scheduling
- if ((newMillis - _lastRenderTime) < _tickLength)
- sleepMs = _tickLength - (newMillis - _lastRenderTime);
+ if ((newMillis - _lastRenderTime) < _tickLength * 2)
+ sleepMs = _tickLength * 2 - (newMillis - _lastRenderTime);
assert(sleepMs >= 0);
_system->delayMillis(sleepMs);
_lastRenderTime = _system->getMillis();
@@ -454,24 +468,24 @@ void ToonEngine::doMagnifierEffect() {
11, 11, 11, 11, 12
};
- byte tempBuffer[25*25];
+ byte tempBuffer[25 * 25];
for (int32 y = -12; y <= 12; y++) {
for (int32 x = -12; x <= 12; x++) {
int32 destPitch = surface.pitch;
uint8 *curRow = (uint8 *)surface.pixels + (posY + y) * destPitch + (posX + x);
- tempBuffer[(y+12) * 25 + x + 12] = *curRow;
+ tempBuffer[(y + 12) * 25 + x + 12] = *curRow;
}
}
for (int32 y = -12; y <= 12; y++) {
for (int32 x = -12; x <= 12; x++) {
int32 dist = y * y + x * x;
- if (dist > 144)
+ if (dist > 144)
continue;
int32 destPitch = surface.pitch;
uint8 *curRow = (uint8 *)surface.pixels + (posY + y) * destPitch + (posX + x);
int32 lerp = (512 + intSqrt[dist] * 256 / 12);
- *curRow = tempBuffer[(y*lerp/1024+12) * 25 + x*lerp/1024 + 12];
+ *curRow = tempBuffer[(y * lerp / 1024 + 12) * 25 + x * lerp / 1024 + 12];
}
}
}
@@ -484,7 +498,50 @@ void ToonEngine::copyToVirtualScreen(bool updateScreen) {
_cursorAnimationInstance->setPosition(_mouseX - 40 + state()->_currentScrollValue - _cursorOffsetX, _mouseY - 40 - _cursorOffsetY, 0, false);
_cursorAnimationInstance->render();
}
- _system->copyRectToScreen((byte *)_mainSurface->pixels + state()->_currentScrollValue, 1280, 0, 0, 640, 400);
+
+ // Handle dirty rects here
+ static int32 lastScroll = 0;
+
+ if (_dirtyAll || _gameState->_currentScrollValue != lastScroll) {
+ // we have to refresh everything in case of scrolling.
+ _system->copyRectToScreen((byte *)_mainSurface->pixels + state()->_currentScrollValue, TOON_BACKBUFFER_WIDTH, 0, 0, TOON_SCREEN_WIDTH, TOON_SCREEN_HEIGHT);
+ } else {
+
+ int32 offX = 0;
+ for (uint i = 0; i < _oldDirtyRects.size(); i++) {
+ Common::Rect rect = _oldDirtyRects[i];
+ rect.translate(-state()->_currentScrollValue, 0);
+ offX = 0;
+ if(rect.right <= 0)
+ continue;
+ if (rect.left < 0) {
+ offX = -rect.left;
+ rect.left = 0;
+ }
+ rect.clip(TOON_SCREEN_WIDTH, TOON_SCREEN_HEIGHT);
+ if (rect.left >= 0 && rect.top >= 0 && rect.right - rect.left > 0 && rect.bottom - rect.top > 0) {
+ _system->copyRectToScreen((byte *)_mainSurface->pixels + _oldDirtyRects[i].left + offX + _oldDirtyRects[i].top * TOON_BACKBUFFER_WIDTH, TOON_BACKBUFFER_WIDTH, rect.left , rect.top, rect.right - rect.left, rect.bottom - rect.top);
+ }
+ }
+
+ for (uint i = 0; i < _dirtyRects.size(); i++) {
+ Common::Rect rect = _dirtyRects[i];
+ rect.translate(-state()->_currentScrollValue, 0);
+ offX = 0;
+ if (rect.right <= 0)
+ continue;
+ if (rect.left < 0) {
+ offX = -rect.left;
+ rect.left = 0;
+ }
+ rect.clip(TOON_SCREEN_WIDTH, TOON_SCREEN_HEIGHT);
+ if (rect.left >= 0 && rect.top >= 0 && rect.right - rect.left > 0 && rect.bottom - rect.top > 0) {
+ _system->copyRectToScreen((byte *)_mainSurface->pixels + _dirtyRects[i].left + offX + _dirtyRects[i].top * TOON_BACKBUFFER_WIDTH, TOON_BACKBUFFER_WIDTH, rect.left , rect.top, rect.right - rect.left, rect.bottom - rect.top);
+ }
+ }
+ }
+ lastScroll = _gameState->_currentScrollValue;
+
if (updateScreen) {
_system->updateScreen();
_shouldQuit = shouldQuit(); // update game quit flag - this shouldn't be called all the time, as it's a virtual function
@@ -589,6 +646,7 @@ bool ToonEngine::showMainmenu(bool &loadedGame) {
bool musicPlaying = false;
_gameState->_inMenu = true;
+ dirtyAllScreen();
while (!doExit) {
clickingOn = MAINMENUHOTSPOT_NONE;
@@ -607,7 +665,15 @@ bool ToonEngine::showMainmenu(bool &loadedGame) {
}
while (!clickRelease) {
- mainmenuPicture->draw(*_mainSurface, 0, 0, 0, 0);
+
+ if(_dirtyAll) {
+ mainmenuPicture->draw(*_mainSurface, 0, 0, 0, 0);
+ addDirtyRect(0, 0, TOON_SCREEN_WIDTH, TOON_SCREEN_HEIGHT);
+ } else {
+ mainmenuPicture->drawWithRectList(*_mainSurface, 0, 0, 0, 0, _dirtyRects);
+ }
+
+ clearDirtyRects();
for (int entryNr = 0; entryNr < MAINMENU_ENTRYCOUNT; entryNr++) {
if (entries[entryNr].menuMask & menuMask) {
@@ -719,7 +785,7 @@ Common::Error ToonEngine::run() {
g_eventRec.registerRandomSource(_rnd, "toon");
- initGraphics(640, 400, true);
+ initGraphics(TOON_SCREEN_WIDTH, TOON_SCREEN_HEIGHT, true);
init();
// do we need to load directly a game?
@@ -783,6 +849,7 @@ ToonEngine::ToonEngine(OSystem *syst, const ADGameDescription *gameDescription)
_backupPalette = NULL;
_additionalPalette1 = NULL;
_additionalPalette2 = NULL;
+ _additionalPalette2Present = false;
_cutawayPalette = NULL;
_universalPalette = NULL;
_fluxPalette = NULL;
@@ -817,7 +884,20 @@ ToonEngine::ToonEngine(OSystem *syst, const ADGameDescription *gameDescription)
_inventoryIcons = NULL;
_inventoryIconSlots = NULL;
_genericTexts = NULL;
- _audioManager = NULL;
+ _audioManager = NULL;
+ _gameState = NULL;
+
+ _locationDirNotVisited = NULL;
+ _locationDirVisited = NULL;
+ _specialInfoLine = NULL;
+
+ for (int i = 0; i < 64; i++) {
+ _sceneAnimations[i]._active = false;
+ }
+
+ for (int i = 0; i < 32; i++) {
+ _characters[i] = NULL;
+ }
memset(&_scriptData, 0, sizeof(EMCData));
@@ -859,7 +939,7 @@ ToonEngine::~ToonEngine() {
_mainSurface->free();
delete _mainSurface;
}
-
+
delete[] _finalPalette;
delete[] _backupPalette;
delete[] _additionalPalette1;
@@ -888,7 +968,6 @@ ToonEngine::~ToonEngine() {
delete _pathFinding;
-
for (int32 i = 0; i < 64; i++) {
if (_sceneAnimations[i]._active) {
// see if one character shares this instance
@@ -950,8 +1029,6 @@ void ToonEngine::simpleUpdate(bool waitCharacterToTalk) {
_animationManager->update(elapsedTime);
_audioManager->updateAmbientSFX();
render();
-
-
}
void ToonEngine::fixPaletteEntries(uint8 *palette, int num) {
@@ -967,13 +1044,8 @@ void ToonEngine::fixPaletteEntries(uint8 *palette, int num) {
// adapted from KyraEngine
void ToonEngine::updateAnimationSceneScripts(int32 timeElapsed) {
-
-
static int32 numReentrant = 0;
numReentrant++;
-
-// Strangerke - Commented (not used)
-// uint32 nextTime = _system->getMillis() + _tickLength;
const int startScript = _lastProcessedSceneScript;
_updatingSceneScriptRunFlag = true;
@@ -1006,10 +1078,8 @@ void ToonEngine::updateAnimationSceneScripts(int32 timeElapsed) {
} while (_lastProcessedSceneScript != startScript && !_shouldQuit);
-
_updatingSceneScriptRunFlag = false;
numReentrant--;
-
}
void ToonEngine::loadScene(int32 SceneId, bool forGameLoad) {
@@ -1077,15 +1147,15 @@ void ToonEngine::loadScene(int32 SceneId, bool forGameLoad) {
_mouseButton = 0;
_lastMouseButton = 0x3;
-
// load package
strcpy(temp, createRoomFilename(Common::String::format("%s.PAK", _gameState->_locations[_gameState->_currentScene]._name).c_str()).c_str());
- resources()->openPackage(temp, true);
+ resources()->openPackage(temp);
strcpy(temp, state()->_locations[SceneId]._name);
strcat(temp, ".NPP");
loadAdditionalPalette(temp, 0);
+ _additionalPalette2Present = false;
strcpy(temp, state()->_locations[SceneId]._name);
strcat(temp, ".NP2");
loadAdditionalPalette(temp, 1);
@@ -1198,6 +1268,9 @@ void ToonEngine::loadScene(int32 SceneId, bool forGameLoad) {
state()->_mouseHidden = false;
+ clearDirtyRects();
+ dirtyAllScreen();
+
if (!forGameLoad) {
_script->start(&_scriptState[0], 0);
@@ -1215,7 +1288,7 @@ void ToonEngine::loadScene(int32 SceneId, bool forGameLoad) {
_gameState->_nextSpecialEnterX = -1;
_gameState->_nextSpecialEnterY = -1;
}
-
+
_script->start(&_scriptState[0], 3);
while (_script->run(&_scriptState[0]))
@@ -1253,10 +1326,11 @@ void ToonEngine::loadAdditionalPalette(Common::String fileName, int32 mode) {
case 1:
memcpy(_additionalPalette2, palette, 69);
fixPaletteEntries(_additionalPalette2, 23);
+ _additionalPalette2Present = true;
break;
case 2:
- memcpy(_cutawayPalette, palette, 768);
- fixPaletteEntries(_cutawayPalette, 256);
+ memcpy(_cutawayPalette, palette, size);
+ fixPaletteEntries(_cutawayPalette, size/3);
break;
case 3:
memcpy(_universalPalette, palette, 96);
@@ -1290,7 +1364,6 @@ void ToonEngine::initChapter() {
_script->unload(&data);
setupGeneralPalette();
-
}
void ToonEngine::loadCursor() {
@@ -1412,10 +1485,9 @@ void ToonEngine::clickEvent() {
return;
}
-
int32 mouseX = _mouseX;
if (_gameState->_inCutaway) {
- mouseX += 1280;
+ mouseX += TOON_BACKBUFFER_WIDTH;
}
// find hotspot
@@ -1443,7 +1515,6 @@ void ToonEngine::clickEvent() {
}
}
-
if (!currentHot) {
int32 xx, yy;
@@ -1471,9 +1542,6 @@ void ToonEngine::clickEvent() {
int16 command = currentHot->getData(commandId);
int16 argument = currentHot->getData(commandId + 1);
int16 priority = currentHot->getPriority();
-// Strangerke - Commented (not used)
-// int16 ref = currentHot->getRef();
-// int16 pad1 = currentHot->getData(6);
if (!_gameState->_inCutaway && !_gameState->_inCloseUp) {
if (leftButton && (currentHot->getData(4) != 2 || _gameState->_mouseState >= 0) && currentHot->getData(5) != -1) {
@@ -1515,8 +1583,6 @@ void ToonEngine::clickEvent() {
break;
case 7:
// switch to CloseUp
-// Strangerke - Commented (not used)
-// int closeup = 1;
break;
case 8:
// face flux
@@ -1524,11 +1590,6 @@ void ToonEngine::clickEvent() {
break;
case 9:
case 10:
-// Strangerke - Commented (not used)
-// if (rand() % 1 == 1) {
-// } else {
-// }
- // setFluxFacingPoint(x,y)
sayLines(2, argument);
break;
case 11:
@@ -1552,7 +1613,6 @@ void ToonEngine::clickEvent() {
int32 val = _scriptState[_currentScriptRegion].regs[4];
currentHot->setData(4, currentHot->getData(4) & val);
}
-
}
void ToonEngine::selectHotspot() {
@@ -1564,7 +1624,7 @@ void ToonEngine::selectHotspot() {
int32 mouseX = _mouseX;
if (_gameState->_inCutaway)
- mouseX += 1280;
+ mouseX += TOON_BACKBUFFER_WIDTH;
if (_gameState->_sackVisible) {
if (_mouseX > 0 && _mouseX < 40 && _mouseY > 356 && _mouseY < 396) {
@@ -1722,7 +1782,6 @@ void ToonEngine::exitScene() {
strcpy(temp, createRoomFilename(Common::String::format("%s.PAK", _gameState->_locations[_gameState->_currentScene]._name).c_str()).c_str());
resources()->closePackage(temp);
-
_drew->stopWalk();
_flux->stopWalk();
@@ -1734,9 +1793,10 @@ void ToonEngine::flipScreens() {
_gameState->_inCloseUp = !_gameState->_inCloseUp;
if (_gameState->_inCloseUp) {
- _gameState->_currentScrollValue = 640;
+ _gameState->_currentScrollValue = TOON_SCREEN_WIDTH;
setPaletteEntries(_cutawayPalette, 1, 128);
- setPaletteEntries(_additionalPalette2, 232, 23);
+ if (_additionalPalette2Present)
+ setPaletteEntries(_additionalPalette2, 232, 23);
} else {
_gameState->_currentScrollValue = 0;
_currentPicture->setupPalette();
@@ -1750,9 +1810,9 @@ void ToonEngine::fadeIn(int32 numFrames) {
uint8 vmpalette[3 * 256];
for (int32 i = 0; i < 256; i++) {
- vmpalette[i*3+0] = f * _finalPalette[i*3+0] / (numFrames - 1);
- vmpalette[i*3+1] = f * _finalPalette[i*3+1] / (numFrames - 1);
- vmpalette[i*3+2] = f * _finalPalette[i*3+2] / (numFrames - 1);
+ vmpalette[i * 3 + 0] = f * _finalPalette[i * 3 + 0] / (numFrames - 1);
+ vmpalette[i * 3 + 1] = f * _finalPalette[i * 3 + 1] / (numFrames - 1);
+ vmpalette[i * 3 + 2] = f * _finalPalette[i * 3 + 2] / (numFrames - 1);
}
_system->getPaletteManager()->setPalette(vmpalette, 0, 256);
_system->updateScreen();
@@ -1768,9 +1828,9 @@ void ToonEngine::fadeOut(int32 numFrames) {
for (int32 f = 0; f < numFrames; f++) {
uint8 vmpalette[3 * 256];
for (int32 i = 0; i < 256; i++) {
- vmpalette[i*3+0] = (numFrames - f - 1) * oldpalette[i*3+0] / (numFrames - 1);
- vmpalette[i*3+1] = (numFrames - f - 1) * oldpalette[i*3+1] / (numFrames - 1);
- vmpalette[i*3+2] = (numFrames - f - 1) * oldpalette[i*3+2] / (numFrames - 1);
+ vmpalette[i * 3 + 0] = (numFrames - f - 1) * oldpalette[i * 3 + 0] / (numFrames - 1);
+ vmpalette[i * 3 + 1] = (numFrames - f - 1) * oldpalette[i * 3 + 1] / (numFrames - 1);
+ vmpalette[i * 3 + 2] = (numFrames - f - 1) * oldpalette[i * 3 + 2] / (numFrames - 1);
}
_system->getPaletteManager()->setPalette(vmpalette, 0, 256);
_system->updateScreen();
@@ -1824,11 +1884,11 @@ int32 ToonEngine::getScaleAtPoint(int32 x, int32 y) {
return 1024;
// clamp values
- x = MIN<int32>(1279, MAX<int32>(0, x));
- y = MIN<int32>(399, MAX<int32>(0, y));
+ x = MIN<int32>(TOON_BACKBUFFER_WIDTH - 1, MAX<int32>(0, x));
+ y = MIN<int32>(TOON_BACKBUFFER_HEIGHT - 1, MAX<int32>(0, y));
int32 maskData = _currentMask->getData(x, y) & 0x1f;
- return _roomScaleData[maskData+2] * 1024 / 100;
+ return _roomScaleData[maskData + 2] * 1024 / 100;
}
int32 ToonEngine::getLayerAtPoint(int32 x, int32 y) {
@@ -1836,11 +1896,11 @@ int32 ToonEngine::getLayerAtPoint(int32 x, int32 y) {
return 0;
// clamp values
- x = MIN<int32>(1279, MAX<int32>(0, x));
- y = MIN<int32>(399, MAX<int32>(0, y));
+ x = MIN<int32>(TOON_BACKBUFFER_WIDTH - 1, MAX<int32>(0, x));
+ y = MIN<int32>(TOON_BACKBUFFER_HEIGHT - 1, MAX<int32>(0, y));
int32 maskData = _currentMask->getData(x, y) & 0x1f;
- return _roomScaleData[maskData+130] << 5;
+ return _roomScaleData[maskData + 130] << 5;
}
int32 ToonEngine::getZAtPoint(int32 x, int32 y) {
@@ -1917,25 +1977,11 @@ void ToonEngine::sayLines(int numLines, int dialogId) {
if (oldShowMouse)
Game.MouseHiddenCount = 0;
#endif
-
}
int32 ToonEngine::simpleCharacterTalk(int32 dialogid) {
int32 myId = 0;
-// Strangerke - Commented (not used)
-#if 0
- char *myLine;
- if (dialogid < 1000) {
- myLine = _roomTexts->getText(dialogid);
- myId = dialogid;
- } else {
- myLine = _genericTexts->getText(dialogid - 1000);
- myId = dialogid - 1000;
- }
- debugC(0, 0xfff, "Talker = %d will say '%s' \n", READ_LE_UINT16(c - 2), myLine);
-#endif
-
if (_audioManager->voiceStillPlaying())
_audioManager->stopCurrentVoice();
@@ -1952,14 +1998,6 @@ int32 ToonEngine::simpleCharacterTalk(int32 dialogid) {
void ToonEngine::playTalkAnimOnCharacter(int32 animID, int32 characterId, bool talker) {
if (animID || talker) {
-// Strangerke - Commented (not used)
-#if 0
- if (_gameState->_inCutaway || _gameState->_inInventory) {
- if (talker) {
- // character talks
- }
- } else
-#endif
if (characterId == 0) {
_drew->playAnim(animID, 0, (talker ? 8 : 0) + 2);
} else if (characterId == 1) {
@@ -2009,7 +2047,6 @@ int32 ToonEngine::characterTalk(int32 dialogid, bool blocking) {
_gameState->_mouseHidden = true;
}
-
// get what is before the string
int a = READ_LE_UINT16(myLine - 2);
char *b = myLine - 2 - 4 * a;
@@ -2020,14 +2057,6 @@ int32 ToonEngine::characterTalk(int32 dialogid, bool blocking) {
char *e = c - 2 - 4 * numParticipants;
READ_LE_UINT16(e);
-// Strangerke - Commented (not used)
-// char *g = e - 2 * f;
-
- // flag as talking
-// Strangerke - Commented (not used)
-// char *h = c;
-
-
// if one voice is still playing, wait !
if (blocking) {
while (_audioManager->voiceStillPlaying() && !_shouldQuit)
@@ -2085,8 +2114,6 @@ int32 ToonEngine::characterTalk(int32 dialogid, bool blocking) {
_currentTextLine = myLine;
_currentTextLineCharacterId = talkerId;
_currentTextLineId = dialogid;
-
-
} else {
Character *character = getCharacterById(talkerId);
if (character)
@@ -2095,7 +2122,6 @@ int32 ToonEngine::characterTalk(int32 dialogid, bool blocking) {
debugC(0, 0xfff, "Talker = %d (num participants : %d) will say '%s'", (int)talkerId , (int)numParticipants, myLine);
-
getTextPosition(talkerId, &_currentTextLineX, &_currentTextLineY);
if (dialogid < 1000) {
@@ -2115,8 +2141,6 @@ int32 ToonEngine::characterTalk(int32 dialogid, bool blocking) {
if (character)
character->setTalking(false);
}
-
-
return 1;
}
@@ -2131,7 +2155,7 @@ void ToonEngine::haveAConversation(int32 convId) {
_gameState->_currentConversationId = convId;
// change the music to the "conversation" music if needed.
- playRoomMusic();
+ playRoomMusic();
if (conv->_enable) {
// fix dialog script based on new flags
@@ -2149,7 +2173,6 @@ void ToonEngine::haveAConversation(int32 convId) {
doFrame();
}
-
_mouseButton = 0;
_gameState->_firstConverstationLine = true;
@@ -2178,11 +2201,13 @@ void ToonEngine::haveAConversation(int32 convId) {
a++;
}
}
- if (_shouldQuit) return;
+
+ if (_shouldQuit)
+ return;
+
_gameState->_showConversationIcons = false;
_gameState->_mouseHidden = 1;
-
if (selected < 0 || selected == 1 || selected == 3) {
if (_gameState->_firstConverstationLine)
processConversationClick(conv, 3);
@@ -2194,9 +2219,6 @@ void ToonEngine::haveAConversation(int32 convId) {
}
}
-// Strangerke - Commented (not used)
-// int cur = 0;
-
for (int i = 0; i < 10; i++) {
if (conv->state[i]._data2 == 2) {
if (i != 3)
@@ -2211,8 +2233,7 @@ void ToonEngine::haveAConversation(int32 convId) {
_gameState->_sackVisible = true;
// switch back to original music
- playRoomMusic();
-
+ playRoomMusic();
}
void ToonEngine::drawConversationIcons() {
@@ -2334,7 +2355,6 @@ retry:
break;
}
}
-
}
// hardcoded conversation flag to know if one dialogue icon must be displayed or not
@@ -2495,7 +2515,7 @@ int32 ToonEngine::runConversationCommand(int16 **command) {
int16 *v5 = *command;
int v2 = READ_LE_INT16(v5);
- int v4 = READ_LE_INT16(v5+1);
+ int v4 = READ_LE_INT16(v5 + 1);
int result = v2 - 100;
switch (v2) {
case 100:
@@ -2528,9 +2548,6 @@ int32 ToonEngine::runConversationCommand(int16 **command) {
}
int32 ToonEngine::waitTicks(int32 numTicks, bool breakOnMouseClick) {
-// Strangerke - Commented (not used)
-// Common::EventManager *_event = _system->getEventManager();
-
uint32 nextTime = _system->getMillis() + numTicks * _tickLength;
while (_system->getMillis() < nextTime || numTicks == -1) {
//if (!_animationSceneScriptRunFlag)
@@ -2549,7 +2566,13 @@ void ToonEngine::renderInventory() {
if (!_gameState->_inInventory)
return;
- _inventoryPicture->draw(*_mainSurface, 0, 0, 0, 0);
+ if (!_dirtyAll) {
+ _inventoryPicture->drawWithRectList(*_mainSurface, 0, 0, 0, 0, _dirtyRects);
+ } else {
+ _inventoryPicture->draw(*_mainSurface, 0, 0, 0, 0);
+ _dirtyRects.push_back(Common::Rect(0, 0, TOON_SCREEN_WIDTH, TOON_SCREEN_HEIGHT));
+ }
+ clearDirtyRects();
// draw items on screen
for (int32 i = 0; i < _gameState->_numInventoryItems; i++) {
@@ -2577,13 +2600,13 @@ void ToonEngine::renderInventory() {
int32 ToonEngine::showInventory() {
int32 oldScrollValue = _gameState->_currentScrollValue;
-// Strangerke - Commented (not used)
-// Common::EventManager *_event = _system->getEventManager();
+
delete _inventoryPicture;
_inventoryPicture = new Picture(this);
fadeOut(5);
_inventoryPicture->loadPicture("SACK128.CPS", true);
_inventoryPicture->setupPalette();
+ dirtyAllScreen();
if (_gameState->_mouseState >= 0) {
setCursor(_gameState->_mouseState, true, -18, -14);
@@ -2632,7 +2655,6 @@ int32 ToonEngine::showInventory() {
int32 modItem = getSpecialInventoryItem(item);
if (modItem) {
-
if (modItem == -1) {
_gameState->_mouseState = item;
_gameState->_inventory[foundObj] = 0;
@@ -2681,7 +2703,7 @@ int32 ToonEngine::showInventory() {
}
_gameState->_currentScrollValue = oldScrollValue;
- _gameState->_inInventory = false;
+ _gameState->_inInventory = false;
_mouseButton = 0;
_lastMouseButton = 0x3;
@@ -2697,6 +2719,7 @@ int32 ToonEngine::showInventory() {
setupGeneralPalette();
}
flushPalette();
+ dirtyAllScreen();
_firstFrame = true;
return 0;
@@ -2771,6 +2794,7 @@ void ToonEngine::showCutaway(Common::String cutawayPicture) {
_currentCutaway->setupPalette();
_oldScrollValue = _gameState->_currentScrollValue;
_gameState->_currentScrollValue = 0;
+ dirtyAllScreen();
flushPalette();
}
@@ -2781,6 +2805,7 @@ void ToonEngine::hideCutaway() {
_gameState->_currentScrollValue = _oldScrollValue;
_currentCutaway = 0;
_currentPicture->setupPalette();
+ dirtyAllScreen();
flushPalette();
}
@@ -2805,7 +2830,7 @@ void ToonEngine::rearrangeInventory() {
if (_gameState->_inventory[i] == 0) {
// move all the following items from one
for (int32 j = i + 1; j < _gameState->_numInventoryItems; j++) {
- _gameState->_inventory[j-1] = _gameState->_inventory[j];
+ _gameState->_inventory[j - 1] = _gameState->_inventory[j];
}
_gameState->_numInventoryItems--;
}
@@ -2819,14 +2844,14 @@ void ToonEngine::newGame() {
addItemToInventory(67);
addItemToInventory(11);
addItemToInventory(19);
- loadScene(_gameState->_currentScene);
+ loadScene(22);
+ //loadScene(_gameState->_currentScene);
} else {
//loadScene(4);
loadScene(_gameState->_currentScene);
}
}
-
void ToonEngine::playSFX(int32 id, int32 volume) {
if (id < 0)
_audioManager->playSFX(-id + 1, volume, true);
@@ -2852,7 +2877,7 @@ void ToonEngine::getTextPosition(int32 characterId, int32 *retX, int32 *retY) {
// drew
int32 x = _drew->getX();
int32 y = _drew->getY();
- if (x >= _gameState->_currentScrollValue && x <= _gameState->_currentScrollValue + 640) {
+ if (x >= _gameState->_currentScrollValue && x <= _gameState->_currentScrollValue + TOON_SCREEN_WIDTH) {
if (!_gameState->_inCutaway && !_gameState->_inInventory) {
*retX = x;
*retY = y - ((_drew->getScale() * 256 / 1024) >> 1) - 45;
@@ -2862,7 +2887,7 @@ void ToonEngine::getTextPosition(int32 characterId, int32 *retX, int32 *retY) {
// flux
int32 x = _flux->getX();
int32 y = _flux->getY();
- if (x >= _gameState->_currentScrollValue && x <= _gameState->_currentScrollValue + 640) {
+ if (x >= _gameState->_currentScrollValue && x <= _gameState->_currentScrollValue + TOON_SCREEN_WIDTH) {
if (!_gameState->_inCutaway) {
*retX = x;
*retY = y - ((_drew->getScale() * 100 / 1024) >> 1) - 30;
@@ -2892,7 +2917,7 @@ void ToonEngine::getTextPosition(int32 characterId, int32 *retX, int32 *retY) {
Character *character = getCharacterById(characterId);
if (character && !_gameState->_inCutaway) {
if (character->getAnimationInstance()) {
- if (character->getX() >= _gameState->_currentScrollValue && character->getX() <= _gameState->_currentScrollValue + 640) {
+ if (character->getX() >= _gameState->_currentScrollValue && character->getX() <= _gameState->_currentScrollValue + TOON_SCREEN_WIDTH) {
int32 x1, y1, x2, y2;
character->getAnimationInstance()->getRect(&x1, &y1, &x2, &y2);
*retX = (x1 + x2) / 2;
@@ -2921,7 +2946,7 @@ void ToonEngine::drawConversationLine() {
}
void ToonEngine::pauseEngineIntern(bool pause) {
-
+
Engine::pauseEngineIntern(pause);
static int32 pauseStart = 0;
@@ -3013,7 +3038,6 @@ bool ToonEngine::saveGame(int32 slot, Common::String saveGameDesc) {
saveFile->writeUint32BE(saveDate);
saveFile->writeUint16BE(saveTime);
-
// save global state
_gameState->save(saveFile);
_gameState->saveConversations(saveFile);
@@ -3040,7 +3064,6 @@ bool ToonEngine::saveGame(int32 slot, Common::String saveGameDesc) {
_sceneAnimations[i].save(this, saveFile);
}
-
for (int32 i = 0; i < 8; i++) {
if (_characters[i]) {
saveFile->writeSByte(i);
@@ -3120,7 +3143,7 @@ bool ToonEngine::loadGame(int32 slot) {
_sceneAnimationScripts[i]._frozen = loadFile->readByte();
_sceneAnimationScripts[i]._frozenForConversation = false;
int32 oldTimer = loadFile->readSint32BE();
- _sceneAnimationScripts[i]._lastTimer = MAX<int32>(0,oldTimer + timerDiff);
+ _sceneAnimationScripts[i]._lastTimer = MAX<int32>(0, oldTimer + timerDiff);
_script->loadState(&_sceneAnimationScripts[i]._state, loadFile);
}
@@ -3159,7 +3182,7 @@ bool ToonEngine::loadGame(int32 slot) {
// load "command buffer"
int32 size = loadFile->readSint16BE();
if (size) {
- uint8 *buf = new uint8[size+2];
+ uint8 *buf = new uint8[size + 2];
loadFile->read(buf, size + 2);
Common::MemoryReadStream rStr(buf, size + 2);
@@ -3278,10 +3301,6 @@ void ToonEngine::initCharacter(int32 characterId, int32 animScriptId, int32 scen
return;
}
-// Strangerke - Commented (not used)
-// if (_characters[characterIndex])
-// delete current char
-
_characters[characterIndex] = new Character(this);
_characters[characterIndex]->setId(characterId);
_characters[characterIndex]->setAnimScript(animScriptId);
@@ -3405,6 +3424,7 @@ void ToonEngine::viewInventoryItem(Common::String str, int32 lineId, int32 itemD
Picture *pic = new Picture(this);
pic->loadPicture(str, false);
pic->setupPalette();
+ dirtyAllScreen();
flushPalette();
if (lineId) {
@@ -3428,7 +3448,13 @@ void ToonEngine::viewInventoryItem(Common::String str, int32 lineId, int32 itemD
break;
}
- pic->draw(*_mainSurface, 0, 0, 0, 0);
+ if (!_dirtyAll) {
+ pic->drawWithRectList(*_mainSurface, 0, 0, 0, 0, _dirtyRects);
+ } else {
+ pic->draw(*_mainSurface, 0, 0, 0, 0);
+ _dirtyRects.push_back(Common::Rect(0, 0, TOON_SCREEN_WIDTH, TOON_SCREEN_HEIGHT));
+ }
+ clearDirtyRects();
drawConversationLine();
if (!_audioManager->voiceStillPlaying()) {
@@ -3447,11 +3473,11 @@ void ToonEngine::viewInventoryItem(Common::String str, int32 lineId, int32 itemD
}
fadeOut(5);
+ dirtyAllScreen();
restorePalette();
_firstFrame = true;
_gameState->_currentScrollValue = oldScrollValue;
delete pic;
-
}
int32 ToonEngine::handleInventoryOnInventory(int32 itemDest, int32 itemSrc) {
@@ -3493,7 +3519,7 @@ int32 ToonEngine::handleInventoryOnInventory(int32 itemDest, int32 itemSrc) {
case 11:
if (itemSrc == 0xb) {
_gameState->_mouseState = -1;
- replaceItemFromInventory(11,12);
+ replaceItemFromInventory(11, 12);
setCursor(0, false, 0, 0);
rearrangeInventory();
return 1;
@@ -4506,9 +4532,9 @@ void ToonEngine::createShadowLUT() {
for (int32 i = 0; i < 255; i++) {
// goal color
- uint32 destR = _finalPalette[i*3+0] * scaleNum / scaleDenom;
- uint32 destG = _finalPalette[i*3+1] * scaleNum / scaleDenom;
- uint32 destB = _finalPalette[i*3+2] * scaleNum / scaleDenom;
+ uint32 destR = _finalPalette[i * 3 + 0] * scaleNum / scaleDenom;
+ uint32 destG = _finalPalette[i * 3 + 1] * scaleNum / scaleDenom;
+ uint32 destB = _finalPalette[i * 3 + 2] * scaleNum / scaleDenom;
// search only in the "picture palette" which is in colors 1-128 and 200-255
int32 colorDist = 0xffffff;
@@ -4516,9 +4542,9 @@ void ToonEngine::createShadowLUT() {
for (int32 c = 1; c < 129; c++) {
- int32 diffR = _finalPalette[c*3+0] - destR;
- int32 diffG = _finalPalette[c*3+1] - destG;
- int32 diffB = _finalPalette[c*3+2] - destB;
+ int32 diffR = _finalPalette[c * 3 + 0] - destR;
+ int32 diffG = _finalPalette[c * 3 + 1] - destG;
+ int32 diffB = _finalPalette[c * 3 + 2] - destB;
if (colorDist > diffR * diffR + diffG * diffG + diffB * diffB) {
colorDist = diffR * diffR + diffG * diffG + diffB * diffB;
@@ -4528,9 +4554,9 @@ void ToonEngine::createShadowLUT() {
for (int32 c = 200; c < 256; c++) {
- int32 diffR = _finalPalette[c*3+0] - destR;
- int32 diffG = _finalPalette[c*3+1] - destG;
- int32 diffB = _finalPalette[c*3+2] - destB;
+ int32 diffR = _finalPalette[c * 3 + 0] - destR;
+ int32 diffG = _finalPalette[c * 3 + 1] - destG;
+ int32 diffB = _finalPalette[c * 3 + 2] - destB;
if (colorDist > diffR * diffR + diffG * diffG + diffB * diffB) {
colorDist = diffR * diffR + diffG * diffG + diffB * diffB;
@@ -4660,6 +4686,47 @@ void ToonEngine::playRoomMusic() {
_audioManager->playMusic(_gameState->_locations[_gameState->_currentScene]._name, _gameState->_locations[_gameState->_currentScene]._music);
}
+void ToonEngine::dirtyAllScreen()
+{
+ _dirtyRects.clear();
+ _dirtyAll = true;
+}
+
+void ToonEngine::addDirtyRect( int32 left, int32 top, int32 right, int32 bottom ) {
+ left = MIN<int32>(MAX<int32>(left, 0), TOON_BACKBUFFER_WIDTH);
+ right = MIN<int32>(MAX<int32>(right, 0), TOON_BACKBUFFER_WIDTH);
+ top = MIN<int32>(MAX<int32>(top, 0), TOON_BACKBUFFER_HEIGHT);
+ bottom = MIN<int32>(MAX<int32>(bottom, 0), TOON_BACKBUFFER_HEIGHT);
+
+ Common::Rect rect(left, top, right, bottom);
+
+ if (bottom - top <= 0 || right - left <= 0)
+ return;
+
+ for (uint32 i = 0; i < _dirtyRects.size(); i++) {
+ if (_dirtyRects[i].contains(rect))
+ return;
+ if (rect.contains(_dirtyRects[i])) {
+ _dirtyRects.remove_at(i);
+ i--;
+ }
+ }
+
+ // check also in the old rect (of the old frame)
+ for (int32 i = _oldDirtyRects.size() - 1 ; i >= 0; i--) {
+ if (rect.contains(_oldDirtyRects[i])) {
+ _oldDirtyRects.remove_at(i);
+ }
+ }
+
+ _dirtyRects.push_back(rect);
+}
+
+void ToonEngine::clearDirtyRects() {
+ _oldDirtyRects = _dirtyRects;
+ _dirtyRects.clear();
+ _dirtyAll = false;
+}
void SceneAnimation::save(ToonEngine *vm, Common::WriteStream *stream) {
stream->writeByte(_active);
stream->writeSint32BE(_id);
@@ -4686,7 +4753,6 @@ void SceneAnimation::load(ToonEngine *vm, Common::ReadStream *stream) {
_active = stream->readByte();
_id = stream->readSint32BE();
-
if (!_active)
return;
diff --git a/engines/toon/toon.h b/engines/toon/toon.h
index f3370aed5e..373437d658 100644
--- a/engines/toon/toon.h
+++ b/engines/toon/toon.h
@@ -52,6 +52,11 @@ class MemoryWriteStreamDynamic;
#define TOON_SAVEGAME_VERSION 4
#define DATAALIGNMENT 4
+#define TOON_SCREEN_WIDTH 640
+#define TOON_SCREEN_HEIGHT 400
+#define TOON_BACKBUFFER_WIDTH 1280
+#define TOON_BACKBUFFER_HEIGHT 400
+
/**
* This is the namespace of the Toon engine.
*
@@ -206,8 +211,6 @@ public:
void waitForScriptStep();
void doMagnifierEffect();
-
-
bool canSaveGameStateCurrently();
bool canLoadGameStateCurrently();
void pauseEngineIntern(bool pause);
@@ -334,6 +337,10 @@ public:
(f == kSupportsSavingDuringRuntime);
}
+ void dirtyAllScreen();
+ void addDirtyRect(int32 left, int32 top, int32 right, int32 bottom);
+ void clearDirtyRects();
+
protected:
OSystem *_system;
int32 _tickLength;
@@ -345,6 +352,7 @@ protected:
uint8 *_backupPalette;
uint8 *_additionalPalette1;
uint8 *_additionalPalette2;
+ bool _additionalPalette2Present;
uint8 *_cutawayPalette;
uint8 *_universalPalette;
uint8 *_fluxPalette;
@@ -371,6 +379,11 @@ protected:
bool _updatingSceneScriptRunFlag;
Graphics::Surface *_mainSurface;
+ Common::Array<Common::Rect> _dirtyRects;
+ Common::Array<Common::Rect> _oldDirtyRects;
+
+ bool _dirtyAll;
+
AnimationInstance *_cursorAnimationInstance;
Animation *_cursorAnimation;