TOON: Merged Toon engine to ScummVM trunk

svn-id: r53087
This commit is contained in:
Eugene Sandulenko 2010-10-08 22:30:39 +00:00
parent 741e7c7f5e
commit cf82bef02e
48 changed files with 13718 additions and 0 deletions

View file

@ -163,6 +163,9 @@ public:
#if PLUGIN_ENABLED_STATIC(TINSEL)
LINK_PLUGIN(TINSEL)
#endif
#if PLUGIN_ENABLED_STATIC(TOON)
LINK_PLUGIN(TOON)
#endif
#if PLUGIN_ENABLED_STATIC(TOUCHE)
LINK_PLUGIN(TOUCHE)
#endif

1
configure vendored
View file

@ -108,6 +108,7 @@ add_engine sword2 "Broken Sword II" yes
add_engine teenagent "Teen Agent" yes
add_engine testbed "TestBed: the Testing framework" no
add_engine tinsel "Tinsel" yes
add_engine toon "Toonstruck" no
add_engine touche "Touche: The Adventures of the Fifth Musketeer" yes
add_engine tucker "Bud Tucker in Double Trouble" yes

BIN
dists/engine-data/toon.dat Normal file

Binary file not shown.

View file

@ -156,6 +156,11 @@ DEFINES += -DENABLE_TINSEL=$(ENABLE_TINSEL)
MODULES += engines/tinsel
endif
ifdef ENABLE_TOON
DEFINES += -DENABLE_TOON=$(ENABLE_TOON)
MODULES += engines/toon
endif
ifdef ENABLE_TOUCHE
DEFINES += -DENABLE_TOUCHE=$(ENABLE_TOUCHE)
MODULES += engines/touche

703
engines/toon/anim.cpp Normal file
View file

@ -0,0 +1,703 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#include "anim.h"
#include "toon.h"
#include "tools.h"
namespace Toon {
bool Animation::loadAnimation(Common::String file) {
debugC(1, kDebugAnim, "loadAnimation(%s)", file.c_str());
uint32 fileSize = 0;
uint8 *fileData = _vm->resources()->getFileData(file, &fileSize);
if (!fileData)
return false;
strcpy(_name, "not_loaded");
if (strncmp((char *)fileData, "KevinAguilar", 12))
return false;
strcpy(_name, file.c_str());
uint32 headerSize = READ_LE_UINT32(fileData + 16);
uint32 uncompressedBytes = READ_LE_UINT32(fileData + 20);
uint32 compressedBytes = READ_LE_UINT32(fileData + 24);
_numFrames = READ_LE_UINT32(fileData + 28);
_x1 = READ_LE_UINT32(fileData + 32);
_y1 = READ_LE_UINT32(fileData + 36);
_x2 = READ_LE_UINT32(fileData + 40);
_y2 = READ_LE_UINT32(fileData + 44);
_paletteEntries = READ_LE_UINT32(fileData + 56);
_fps = READ_LE_UINT32(fileData + 60);
uint32 paletteSize = READ_LE_UINT32(fileData + 64);
uint8 *currentData = fileData + 68;
if (_paletteEntries) {
if (paletteSize) {
_palette = new uint8[paletteSize];
memcpy(_palette, currentData, paletteSize);
currentData += paletteSize;
} else {
_palette = 0;
}
}
byte *finalBuffer = new byte[uncompressedBytes];
if (uncompressedBytes > compressedBytes)
decompressLZSS(currentData, finalBuffer, uncompressedBytes);
else
memcpy(finalBuffer, currentData, uncompressedBytes);
if (READ_LE_UINT32(finalBuffer) == 0x12345678) {
uint8 *data = finalBuffer;
_frames = new AnimationFrame[_numFrames];
for (int32 e = 0; e < _numFrames; e++) {
if (READ_LE_UINT32(data) != 0x12345678)
return false;
int32 oldRef = READ_LE_UINT32(data + 4);
uint32 compressedSize = READ_LE_UINT32(data + 8);
uint32 decompressedSize = READ_LE_UINT32(data + 12);
_frames[e]._x1 = READ_LE_UINT32(data + 16);
_frames[e]._y1 = READ_LE_UINT32(data + 20);
_frames[e]._x2 = READ_LE_UINT32(data + 24);
_frames[e]._y2 = READ_LE_UINT32(data + 28);
uint8 *imageData = data + headerSize;
if (oldRef != -1 || decompressedSize == 0) {
_frames[e]._ref = oldRef;
_frames[e]._data = 0;
} else {
_frames[e]._ref = -1;
_frames[e]._data = new uint8[decompressedSize];
decompressLZSS(imageData, _frames[e]._data, decompressedSize);
}
data += headerSize + compressedSize;
}
}
delete[] finalBuffer;
return true;
}
Animation::Animation(ToonEngine *vm) : _vm(vm) {
_palette = 0;
_frames = 0;
}
Animation::~Animation() {
delete[] _palette;
for (int32 i = 0; i < _numFrames; i++) {
delete[] _frames[i]._data;
}
delete[] _frames;
}
Common::Rect Animation::getRect() {
debugC(5, kDebugAnim, "getRect");
return Common::Rect(_x1, _y1, _x2, _y2);
}
void Animation::drawFrame(Graphics::Surface &surface, int32 frame, int32 xx, int32 yy) {
debugC(3, kDebugAnim, "drawFrame(surface, %d, %d, %d)", frame, xx, yy);
if (frame < 0)
frame = 0;
if (frame >= _numFrames)
frame = _numFrames - 1;
if (_numFrames == 0)
return;
if (_frames[frame]._ref != -1)
frame = _frames[frame]._ref;
int32 rectX = _frames[frame]._x2 - _frames[frame]._x1;
int32 rectY = _frames[frame]._y2 - _frames[frame]._y1;
if ((xx + _x1 + _frames[frame]._x1 < 0) || (yy + _y1 + _frames[frame]._y1 < 0))
return;
if (rectX + xx + _x1 + _frames[frame]._x1 >= surface.w)
rectX = surface.w - xx - _x1 - _frames[frame]._x1;
if (rectX < 0)
return;
if (rectY + yy + _y1 + _frames[frame]._y1 >= surface.h)
rectY = surface.h - yy - _y1 - _frames[frame]._y1;
if (rectY < 0)
return;
int32 destPitch = surface.pitch;
uint8 *srcRow = _frames[frame]._data;
uint8 *curRow = (uint8 *)surface.pixels + (yy + _frames[frame]._y1 + _y1) * destPitch + (xx + _x1 + _frames[frame]._x1) ;
for (int32 y = 0; y < rectY; y++) {
uint8 *cur = curRow;
uint8 *c = srcRow + y * (_frames[frame]._x2 - _frames[frame]._x1);
for (int32 x = 0; x < rectX; x++) {
if (*c)
*cur = *c;
c++;
cur++;
}
curRow += destPitch;
}
}
void Animation::drawFrameWithMask(Graphics::Surface &surface, int32 frame, int32 xx, int32 yy, int32 zz, Picture *mask) {
debugC(1, kDebugAnim, "drawFrameWithMask(surface, %d, %d, %d, %d, mask)", frame, xx, yy, zz);
warning("STUB: drawFrameWithMask()");
}
void Animation::drawFrameWithMaskAndScale(Graphics::Surface &surface, int32 frame, int32 xx, int32 yy, int32 zz, Picture *mask, int32 scale) {
debugC(5, kDebugAnim, "drawFrameWithMaskAndScale(surface, %d, %d, %d, %d, mask, %d)", frame, xx, yy, zz, scale);
if (_frames[frame]._ref != -1)
frame = _frames[frame]._ref;
int32 rectX = _frames[frame]._x2 - _frames[frame]._x1;
int32 rectY = _frames[frame]._y2 - _frames[frame]._y1;
int32 finalWidth = rectX * scale / 1024;
int32 finalHeight = rectY * scale / 1024;
// 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;
int32 destPitch = surface.pitch;
int32 destPitchMask = mask->getWidth();
uint8 *c = _frames[frame]._data;
uint8 *curRow = (uint8 *)surface.pixels;
uint8 *curRowMask = mask->getDataPtr();
if (strstr(_name, "shadow")) {
for (int y = yy1; y < yy2; y++) {
for (int x = xx1; x < xx2; x++) {
if (x < 0 || x >= 1280 || y < 0 || y >= 400)
continue;
uint8 *cur = curRow + x + y * destPitch;
uint8 *curMask = curRowMask + x + y * destPitchMask;
// find the good c
int32 xs = (x - xx1) * 1024 / scale;
int32 ys = (y - yy1) * 1024 / scale;
uint8 *cc = &c[ys * w + xs];
if (*cc && ((*curMask) >= zz))
*cur = _vm->getShadowLUT()[*cur];
}
}
} else {
for (int y = yy1; y < yy2; y++) {
for (int x = xx1; x < xx2; x++) {
if (x < 0 || x >= 1280 || y < 0 || y >= 400)
continue;
uint8 *cur = curRow + x + y * destPitch;
uint8 *curMask = curRowMask + x + y * destPitchMask;
// find the good c
int32 xs = (x - xx1) * 1024 / scale;
int32 ys = (y - yy1) * 1024 / scale;
uint8 *cc = &c[ys * w + xs];
if (*cc && ((*curMask) >= zz))
*cur = *cc;
}
}
}
}
void Animation::applyPalette(int32 offset, int32 srcOffset, int32 numEntries) {
debugC(1, kDebugAnim, "applyPalette(%d, %d, %d)", offset, srcOffset, numEntries);
_vm->setPaletteEntries(_palette + srcOffset, offset, numEntries);
}
int32 Animation::getFrameWidth(int32 frame) {
debugC(4, kDebugAnim, "getFrameWidth(%d)", frame);
if ((frame < 0) || (frame >= _numFrames))
return 0;
if (_frames[frame]._ref != -1)
frame = _frames[frame]._ref;
return _frames[frame]._x2 - _frames[frame]._x1;
}
int32 Animation::getFrameHeight(int32 frame) {
debugC(4, kDebugAnim, "getFrameHeight(%d)", frame);
if (frame < 0 || frame >= _numFrames)
return 0;
if (_frames[frame]._ref != -1)
frame = _frames[frame]._ref;
return _frames[frame]._y2 - _frames[frame]._y1;
}
int32 Animation::getWidth() const {
return _x2 - _x1;
}
int32 Animation::getHeight() const {
return _y2 - _y1;
}
void Animation::drawFontFrame(Graphics::Surface &surface, int32 frame, int32 xx, int32 yy, byte *colorMap) {
debugC(4, kDebugAnim, "drawFontFrame(surface, %d, %d, %d, colorMap)", frame, xx, yy);
if (frame < 0)
frame = 0;
if (frame >= _numFrames)
frame = _numFrames - 1;
if (_numFrames == 0)
return;
if (_frames[frame]._ref != -1)
frame = _frames[frame]._ref;
int32 rectX = _frames[frame]._x2 - _frames[frame]._x1;
int32 rectY = _frames[frame]._y2 - _frames[frame]._y1;
if ((xx + _x1 + _frames[frame]._x1 < 0) || (yy + _y1 + _frames[frame]._y1 < 0))
return;
if (rectX + xx + _x1 + _frames[frame]._x1 >= surface.w)
rectX = surface.w - xx - _x1 - _frames[frame]._x1;
if (rectX < 0)
return;
if (rectY + yy + _y1 + _frames[frame]._y1 >= surface.h)
rectY = surface.h - yy - _y1 - _frames[frame]._y1;
if (rectY < 0)
return;
int32 destPitch = surface.pitch;
uint8 *c = _frames[frame]._data;
uint8 *curRow = (uint8 *)surface.pixels + (yy + _frames[frame]._y1 + _y1) * destPitch + (xx + _x1 + _frames[frame]._x1);
for (int32 y = 0; y < rectY; y++) {
unsigned char *cur = curRow;
for (int32 x = 0; x < rectX; x++) {
if (*c && *c < 4)
*cur = colorMap[*c];
c++;
cur++;
}
curRow += destPitch;
}
}
void Animation::drawFrameOnPicture(int32 frame, int32 xx, int32 yy) {
debugC(1, kDebugAnim, "drawFrameOnPicture(%d, %d, %d)", frame, xx, yy);
if (frame < 0)
frame = 0;
if (frame >= _numFrames)
frame = _numFrames - 1;
if (_numFrames == 0)
return;
if (_frames[frame]._ref != -1)
frame = _frames[frame]._ref;
int32 rectX = _frames[frame]._x2 - _frames[frame]._x1;
int32 rectY = _frames[frame]._y2 - _frames[frame]._y1;
Picture *pic = _vm->getPicture();
if ((xx + _x1 + _frames[frame]._x1 < 0) || (yy + _y1 + _frames[frame]._y1 < 0))
return;
if (rectX + xx + _x1 + _frames[frame]._x1 >= pic->getWidth())
rectX = pic->getWidth() - xx - _x1 - _frames[frame]._x1 ;
if (rectX < 0)
return;
if (rectY + yy + _y1 + _frames[frame]._y1 >= pic->getHeight())
rectY = pic->getHeight() - yy - _y1 - _frames[frame]._y1 ;
if (rectY < 0)
return;
int32 destPitch = pic->getWidth();
uint8 *c = _frames[frame]._data;
uint8 *curRow = (uint8 *)pic->getDataPtr() + (yy + _frames[frame]._y1 + _y1) * destPitch + (xx + _x1 + _frames[frame]._x1) ;
for (int32 y = 0; y < rectY; y++) {
unsigned char *cur = curRow;
for (int32 x = 0; x < rectX; x++) {
if (*c)
*cur = *c;
c++;
cur++;
}
curRow += destPitch;
}
}
void AnimationInstance::update(int32 timeIncrement) {
debugC(5, kDebugAnim, "update(%d)", timeIncrement);
if (_currentFrame == -1)
return;
if (_rangeStart == _rangeEnd) {
_currentFrame = _rangeStart;
return;
}
if (_playing) {
_currentTime += timeIncrement;
_currentFrame = _currentTime / (1000 / _fps);
}
if (_looping) {
_currentFrame = (_currentFrame % (_rangeEnd - _rangeStart + 1)) + _rangeStart;
} else {
if (_currentFrame >= _rangeEnd - _rangeStart) {
_playing = false;
_currentFrame = _rangeEnd;
} else {
_currentFrame = _rangeStart + _currentFrame;
}
}
}
AnimationInstance::AnimationInstance(ToonEngine *vm, AnimationInstanceType type) : _vm(vm) {
_id = 0;
_type = type;
_animation = 0;
_currentFrame = 0;
_currentTime = 0;
_fps = 15;
_looping = true;
_playing = false;
_rangeEnd = 0;
_useMask = false;
_rangeStart = 0;
_scale = 1024;
_x = 0;
_y = 0;
_z = 0;
_layerZ = 0;
}
void AnimationInstance::render() {
debugC(5, kDebugAnim, "render()");
if (_visible && _animation) {
int32 frame = _currentFrame;
if (frame < 0)
frame = 0;
if (frame >= _animation->_numFrames)
frame = _animation->_numFrames - 1;
if (_useMask) {
//if (_scale == 100) { // 100% scale
// _animation->drawFrameWithMask(_vm->getMainSurface(), _currentFrame, _x, _y, _z, _vm->getMask());
//} else {
_animation->drawFrameWithMaskAndScale(_vm->getMainSurface(), frame, _x, _y, _z, _vm->getMask(), _scale);
//}
} else {
_animation->drawFrame(_vm->getMainSurface(), frame, _x, _y);
}
}
}
void AnimationInstance::renderOnPicture() {
debugC(5, kDebugAnim, "renderOnPicture()");
if (_visible && _animation)
_animation->drawFrameOnPicture(_currentFrame, _x, _y);
}
void AnimationInstance::playAnimation() {
debugC(6, kDebugAnim, "playAnimation()");
_playing = true;
}
void AnimationInstance::setAnimation(Animation *animation, bool setRange) {
debugC(5, kDebugAnim, "setAnimation(animation)");
_animation = animation;
if (animation && setRange) {
_rangeStart = 0;
_rangeEnd = animation->_numFrames - 1;
}
}
void AnimationInstance::setAnimationRange(int32 rangeStart, int rangeEnd) {
debugC(5, kDebugAnim, "setAnimationRange(%d, %d)", rangeStart, rangeEnd);
_rangeStart = rangeStart;
_rangeEnd = rangeEnd;
if (_currentFrame < _rangeStart)
_currentFrame = _rangeStart;
if (_currentFrame > _rangeEnd)
_currentFrame = _rangeEnd;
}
void AnimationInstance::setPosition(int32 x, int32 y, int32 z, bool relative) {
debugC(5, kDebugAnim, "setPosition(%d, %d, %d, %d)", x, y, z, (relative) ? 1 : 0);
if (relative || !_animation) {
_x = x;
_y = y;
_z = z;
} else {
_x = x - _animation->_x1 ;
_y = y - _animation->_y1;
_z = z;
}
}
void AnimationInstance::moveRelative(int32 dx, int32 dy, int32 dz) {
debugC(1, kDebugAnim, "moveRelative(%d, %d, %d)", dx, dy, dz);
_x += dx;
_y += dy;
_z += dz;
}
void AnimationInstance::forceFrame(int32 position) {
debugC(5, kDebugAnim, "forceFrame(%d)", position);
_currentFrame = position;
_rangeStart = position;
_rangeEnd = position;
}
void AnimationInstance::setFrame(int32 position) {
debugC(5, kDebugAnim, "setFrame(%d)", position);
_currentFrame = position;
}
void AnimationInstance::setFps(int32 fps) {
debugC(4, kDebugAnim, "setFps(%d)", fps);
_fps = fps;
}
void AnimationInstance::stopAnimation() {
debugC(5, kDebugAnim, "stopAnimation()");
_playing = false;
}
void AnimationInstance::setVisible(bool visible) {
debugC(1, kDebugAnim, "setVisible(%d)", (visible) ? 1 : 0);
_visible = visible;
}
void AnimationInstance::setScale(int32 scale) {
debugC(4, kDebugAnim, "setScale(%d)", scale);
_scale = scale;
}
void AnimationInstance::setUseMask(bool useMask) {
debugC(1, kDebugAnim, "setUseMask(%d)", (useMask) ? 1 : 0);
_useMask = useMask;
}
void AnimationInstance::getRect(int32 *x1, int32 *y1, int32 *x2, int32 *y2) const {
debugC(5, kDebugAnim, "getRect(%d, %d, %d, %d)", *x1, *y1, *x2, *y2);
int32 rectX = _animation->_frames[_currentFrame]._x2 - _animation->_frames[_currentFrame]._x1;
int32 rectY = _animation->_frames[_currentFrame]._y2 - _animation->_frames[_currentFrame]._y1;
int32 finalWidth = rectX * _scale / 1024;
int32 finalHeight = rectY * _scale / 1024;
// 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;
*y2 = *y1 + finalHeight;
}
void AnimationInstance::setX(int32 x, bool relative) {
debugC(1, kDebugAnim, "setX(%d, %d)", x, (relative) ? 1 : 0);
if (relative || !_animation)
_x = x;
else
_x = x - _animation->_x1 ;
}
void AnimationInstance::setY(int32 y, bool relative) {
debugC(1, kDebugAnim, "setY(%d, %d)", y, (relative) ? 1 : 0);
if (relative || !_animation)
_y = y;
else
_y = y - _animation->_y1 ;
}
void AnimationInstance::setZ(int32 z, bool relative) {
debugC(1, kDebugAnim, "setZ(%d, %d)", z, (relative) ? 1 : 0);
_z = z;
}
void AnimationInstance::setLayerZ(int32 z) {
_layerZ = z;
}
int32 AnimationInstance::getLayerZ() const {
return _layerZ;
}
int32 AnimationInstance::getX2() const {
return _x + _animation->_x1 ;
}
int32 AnimationInstance::getY2() const {
return _y + _animation->_y1 ;
}
int32 AnimationInstance::getZ2() const {
return _z ;
}
void AnimationInstance::save(Common::WriteStream *stream) {
// we don't load the animation here
// it must be loaded externally to avoid leaks.
stream->writeSint32LE(_currentFrame);
stream->writeSint32LE(_currentTime);
stream->writeSint32LE(_layerZ);
stream->writeSint32LE(_x);
stream->writeSint32LE(_y);
stream->writeSint32LE(_z);
stream->writeSint32LE(_scale);
stream->writeSint32LE(_playing);
stream->writeSint32LE(_looping);
stream->writeSint32LE(_rangeStart);
stream->writeSint32LE(_rangeEnd);
stream->writeSint32LE(_rangeStart);
stream->writeSint32LE(_fps);
stream->writeSint32LE(_id);
stream->writeSint32LE(_type);
stream->writeSint32LE(_visible);
stream->writeSint32LE(_useMask);
}
void AnimationInstance::load(Common::ReadStream *stream) {
_currentFrame = stream->readSint32LE();
_currentTime = stream->readSint32LE();
_layerZ = stream->readSint32LE();
_x = stream->readSint32LE();
_y = stream->readSint32LE();
_z = stream->readSint32LE();
_scale = stream->readSint32LE();
_playing = stream->readSint32LE();
_looping = stream->readSint32LE();
_rangeStart = stream->readSint32LE();
_rangeEnd = stream->readSint32LE();
_rangeStart = stream->readSint32LE();
_fps = stream->readSint32LE();
_id = stream->readSint32LE();
_type = (AnimationInstanceType)stream->readSint32LE();
_visible = stream->readSint32LE();
_useMask = stream->readSint32LE();
}
void AnimationInstance::setLooping(bool enable) {
debugC(6, kDebugAnim, "setLooping(%d)", (enable) ? 1 : 0);
_looping = enable;
}
void AnimationInstance::reset() {
_currentFrame = 0;
_currentTime = 0;
}
AnimationManager::AnimationManager(ToonEngine *vm) : _vm(vm) {
}
void AnimationManager::addInstance(AnimationInstance *instance) {
_instances.push_back(instance);
}
void AnimationManager::removeInstance(AnimationInstance *instance) {
debugC(1, kDebugAnim, "removeInstance(instance)");
int32 found = -1;
for (uint32 i = 0; i < _instances.size(); i++) {
if (_instances[i] == instance) {
found = i;
break;
}
}
if (found > -1)
_instances.remove_at(found);
}
void AnimationManager::removeAllInstances(AnimationInstanceType type) {
debugC(1, kDebugAnim, "removeInstance(type)");
for (int32 i = (int32)_instances.size(); i >= 0 ; i--) {
if (_instances[i]->getType() & type)
_instances.remove_at(i);
}
}
void AnimationManager::update(int32 timeIncrement) {
debugC(5, kDebugAnim, "update(%d)", timeIncrement);
for (uint32 i = 0; i < _instances.size(); i++)
_instances[i]->update(timeIncrement);
}
void AnimationManager::render() {
debugC(5, kDebugAnim, "render()");
// sort the instance by layer z
// bubble sort (replace by faster afterwards)
bool changed = true;
while (changed) {
changed = false;
for (uint32 i = 0; i < _instances.size() - 1; i++) {
if ((_instances[i]->getLayerZ() > _instances[i + 1]->getLayerZ()) ||
((_instances[i]->getLayerZ() == _instances[i + 1]->getLayerZ()) &&
(_instances[i]->getId() < _instances[i+1]->getId()))) {
AnimationInstance *instance = _instances[i];
_instances[i] = _instances[i + 1];
_instances[i + 1] = instance;
changed = true;
}
}
}
for (uint32 i = 0; i < _instances.size(); i++) {
if (_instances[i]->getVisible())
_instances[i]->render();
}
}
AnimationInstance *AnimationManager::createNewInstance(AnimationInstanceType type) {
return new AnimationInstance(_vm, type);
}
} // End of namespace Toon

194
engines/toon/anim.h Normal file
View file

@ -0,0 +1,194 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#ifndef TOON_ANIM_H
#define TOON_ANIM_H
#include "common/stream.h"
#include "common/array.h"
#include "common/func.h"
#include "graphics/surface.h"
#include "script.h"
namespace Toon {
class Picture;
class ToonEngine;
struct AnimationFrame {
int32 _x1;
int32 _y1;
int32 _x2;
int32 _y2;
int32 _ref;
uint8 *_data;
};
class Animation {
public:
Animation(ToonEngine *vm);
~Animation();
int32 _x1;
int32 _y1;
int32 _x2;
int32 _y2;
int32 _numFrames;
int32 _fps;
AnimationFrame *_frames;
uint8 *_palette;
int32 _paletteEntries;
char _name[32];
bool loadAnimation(Common::String file);
void drawFrame(Graphics::Surface &surface, int32 frame, int32 x, int32 y);
void drawFontFrame(Graphics::Surface &surface, int32 frame, int32 x, int32 y, byte *colorMap);
void drawFrameOnPicture(int32 frame, int32 x, int32 y);
void drawFrameWithMask(Graphics::Surface &surface, int32 frame, int32 xx, int32 yy, int32 zz, Picture *mask);
void drawFrameWithMaskAndScale(Graphics::Surface &surface, int32 frame, int32 xx, int32 yy, int32 zz, Picture *mask, int32 scale);
void drawStrip(int32 offset = 0);
void applyPalette(int32 offset, int32 srcOffset, int32 numEntries);
int32 getFrameWidth(int32 frame);
int32 getFrameHeight(int32 frame);
int32 getWidth() const;
int32 getHeight() const;
Common::Rect getRect();
protected:
ToonEngine *_vm;
};
enum AnimationInstanceType {
kAnimationCharacter = 1,
kAnimationScene = 2,
kAnimationCursor = 4
};
class AnimationInstance {
public:
AnimationInstance(ToonEngine *vm, AnimationInstanceType type);
void update(int32 timeIncrement);
void render();
void renderOnPicture();
void setAnimation(Animation *animation, bool setRange = true);
void playAnimation();
void setAnimationRange(int32 rangeStart, int rangeEnd);
void setFps(int32 fps);
void setLooping(bool enable);
void stopAnimation();
void setFrame(int32 position);
void forceFrame(int32 position);
void setPosition(int32 x, int32 y, int32 z, bool relative = false);
Animation *getAnimation() const { return _animation; }
void setScale(int32 scale);
void setVisible(bool visible);
bool getVisible() const { return _visible; }
void setUseMask(bool useMask);
void moveRelative(int32 dx, int32 dy, int32 dz);
void getRect(int32 *x1, int32 *y1, int32 *x2, int32 *y2) const;
int32 getX() const { return _x; };
int32 getY() const { return _y; };
int32 getZ() const { return _z; };
int32 getX2() const;
int32 getY2() const;
int32 getZ2() const;
int32 getFrame() const { return _currentFrame; };
void reset();
void save(Common::WriteStream *stream);
void load(Common::ReadStream *stream);
void setId(int32 id) { _id = id; };
int32 getId() const { return _id; };
void setX(int32 x, bool relative = false);
void setY(int32 y, bool relative = false);
void setZ(int32 z, bool relative = false);
void setLayerZ(int32 layer);
int32 getLayerZ() const;
AnimationInstanceType getType() const { return _type; }
protected:
int32 _currentFrame;
int32 _currentTime;
int32 _fps;
Animation *_animation;
int32 _x;
int32 _y;
int32 _z;
int32 _layerZ;
int32 _rangeStart;
int32 _rangeEnd;
int32 _scale;
int32 _id;
AnimationInstanceType _type;
bool _useMask;
bool _playing;
bool _looping;
bool _visible;
ToonEngine *_vm;
};
class AnimationManager {
public:
AnimationManager(ToonEngine *vm);
AnimationInstance *createNewInstance(AnimationInstanceType type);
void addInstance(AnimationInstance *instance);
void removeInstance(AnimationInstance *instance);
void removeAllInstances(AnimationInstanceType type);
void render();
void update(int32 timeIncrement);
protected:
ToonEngine *_vm;
Common::Array<AnimationInstance *> _instances;
};
class SceneAnimation {
public:
AnimationInstance *_animInstance;
Animation *_animation;
int32 _id;
bool _active;
void load(ToonEngine* vm,Common::ReadStream *stream);
void save(ToonEngine* vm,Common::WriteStream *stream);
};
class SceneAnimationScript {
public:
EMCData *_data;
EMCState _state;
uint32 _lastTimer;
bool _frozen;
bool _active;
};
} // End of namespace Toon
#endif

443
engines/toon/audio.cpp Normal file
View file

@ -0,0 +1,443 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#include "audio.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] = 0;
}
AudioManager::~AudioManager(void) {
}
void AudioManager::removeInstance(AudioStreamInstance *inst) {
debugC(1, kDebugAudio, "removeInstance(inst)");
for (int32 i = 0; i < 16; i++) {
if (inst == _channels[i])
_channels[i] = 0;
}
}
void AudioManager::playMusic(Common::String dir, Common::String music) {
debugC(1, kDebugAudio, "playMusic(%s, %s)", dir.c_str(), music.c_str());
// two musics can be played at same time
Common::String path = Common::String::printf("act%d/%s/%s.mus", _vm->state()->_currentChapter, dir.c_str(), music.c_str());;
if (_currentMusicName == music)
return;
_currentMusicName = music;
// 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;
}
} 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;
}
Common::SeekableReadStream *srs = _vm->resources()->openFile(path);
//if (!_channels[_currentMusicChannel])
// delete _channels[_currentMusicChannel];
_channels[_currentMusicChannel] = new AudioStreamInstance(this, _mixer, srs, true);
_channels[_currentMusicChannel]->play(true, Audio::Mixer::kMusicSoundType);
}
bool AudioManager::voiceStillPlaying() {
if (!_channels[2])
return false;
return _channels[2]->isPlaying();
}
void AudioManager::playVoice(int32 id, bool genericVoice) {
debugC(1, kDebugAudio, "playVoice(%d, %d)", id, (genericVoice) ? 1 : 0);
if (voiceStillPlaying()) {
// stop current voice
_channels[2]->stop(false);
}
Common::SeekableReadStream *stream ;
if (genericVoice)
stream = _audioPacks[0]->getStream(id);
else
stream = _audioPacks[1]->getStream(id);
_channels[2] = new AudioStreamInstance(this, _mixer, stream);
_channels[2]->play(false, Audio::Mixer::kSpeechSoundType);
}
void AudioManager::playSFX(int32 id, int32 volume , bool genericSFX) {
debugC(4, kDebugAudio, "playSFX(%d, %d)", id, (genericSFX) ? 1 : 0);
// find a free SFX channel
Common::SeekableReadStream *stream ;
if (genericSFX)
stream = _audioPacks[2]->getStream(id, true);
else
stream = _audioPacks[3]->getStream(id, true);
if (stream->size() == 0)
return;
for (int32 i = 3; i < 16; i++) {
if (!_channels[i]) {
_channels[i] = new AudioStreamInstance(this, _mixer, stream);
_channels[i]->play(false, Audio::Mixer::kSFXSoundType);
_channels[i]->setVolume(volume);
break;
}
}
}
void AudioManager::stopCurrentVoice() {
debugC(1, kDebugAudio, "stopCurrentVoice()");
if (_channels[2] && _channels[2]->isPlaying())
_channels[2]->stop(false);
}
bool AudioManager::loadAudioPack(int32 id, Common::String indexFile, Common::String packFile) {
debugC(4, kDebugAudio, "loadAudioPack(%d, %s, %s)", id, indexFile.c_str(), packFile.c_str());
_audioPacks[id] = new AudioStreamPackage(_vm);
return _audioPacks[id]->loadAudioPackage(indexFile, packFile);
}
void AudioManager::setMusicVolume(int32 volume) {
debugC(1, kDebugAudio, "setMusicVolume(%d)", volume);
if (_channels[0])
_channels[0]->setVolume(volume);
if (_channels[1])
_channels[1]->setVolume(volume);
}
void AudioManager::stopMusic() {
debugC(1, kDebugAudio, "stopMusic()");
if (_channels[0])
_channels[0]->stop(true);
if (_channels[1])
_channels[1]->stop(true);
}
AudioStreamInstance::~AudioStreamInstance() {
if (_man)
_man->removeInstance(this);
}
AudioStreamInstance::AudioStreamInstance(AudioManager *man, Audio::Mixer *mixer, Common::SeekableReadStream *stream , bool looping) {
_compBufferSize = 0;
_buffer = 0;
_bufferMaxSize = 0;
_mixer = mixer;
_compBuffer = 0;
_bufferOffset = 0;
_lastADPCMval1 = 0;
_lastADPCMval2 = 0;
_file = stream;
_fadingIn = false;
_fadingOut = false;
_fadeTime = 0;
_stopped = false;
_volume = 255;
_totalSize = stream->size();
_currentReadSize = 8;
_man = man;
_looping = looping;
// preload one packet
if (_totalSize > 0) {
_file->skip(8);
readPacket();
} else {
stopNow();
}
}
int32 AudioStreamInstance::readBuffer(int16 *buffer, const int numSamples) {
debugC(5, kDebugAudio, "readBuffer(buffer, %d)", numSamples);
handleFade(numSamples);
int32 leftSamples = numSamples;
int32 destOffset = 0;
if ((_bufferOffset + leftSamples) * 2 >= _bufferSize) {
if (_bufferSize - _bufferOffset * 2 > 0) {
memcpy(buffer, &_buffer[_bufferOffset], _bufferSize - _bufferOffset * 2);
leftSamples -= (_bufferSize - _bufferOffset * 2) / 2;
destOffset += (_bufferSize - _bufferOffset * 2) / 2;
}
if (!readPacket())
return 0;
_bufferOffset = 0;
}
if (leftSamples >= 0) {
memcpy(buffer + destOffset, &_buffer[_bufferOffset], MIN(leftSamples * 2, _bufferSize));
_bufferOffset += leftSamples;
}
return numSamples;
}
bool AudioStreamInstance::readPacket() {
debugC(5, kDebugAudio, "readPacket()");
if (_file->eos() || (_currentReadSize >= _totalSize)) {
if (_looping) {
_file->seek(8);
_currentReadSize = 8;
} else {
_bufferSize = 0;
stopNow();
return false;
}
}
int16 numCompressedBytes = _file->readSint16LE();
int16 numDecompressedBytes = _file->readSint16LE();
_file->readSint32LE();
if (numCompressedBytes > _compBufferSize) {
if (_compBuffer)
delete[] _compBuffer;
_compBufferSize = numCompressedBytes;
_compBuffer = new uint8[_compBufferSize];
}
if (numDecompressedBytes > _bufferMaxSize) {
if (_buffer)
delete [] _buffer;
_bufferMaxSize = numDecompressedBytes;
_buffer = new int16[numDecompressedBytes];
}
_bufferSize = numDecompressedBytes;
_file->read(_compBuffer, numCompressedBytes);
_currentReadSize += 8 + numCompressedBytes;
decodeADPCM(_compBuffer, _buffer, numCompressedBytes);
return true;
}
void AudioStreamInstance::decodeADPCM(uint8 *comp, int16 *dest, int32 packetSize) {
debugC(5, kDebugAudio, "decodeADPCM(comp, dest, %d)", packetSize);
int32 numSamples = 2 * packetSize ;
int32 v18 = _lastADPCMval1;
int32 v19 = _lastADPCMval2;
for (int32 i = 0; i < numSamples; i++) {
uint8 comm = *comp;
int32 v29 = i & 1;
int32 v30;
if (v29 == 0)
v30 = comm & 0xf;
else
v30 = (comm & 0xf0) >> 4;
int32 v31 = v30 & 0x8;
int32 v32 = v30 & 0x7;
int32 v33 = ADPCM_table[v19];
int32 v34 = v33 >> 3;
if (v32 & 4)
v34 += v33;
if (v32 & 2)
v34 += v33 >> 1;
if (v32 & 1)
v34 += v33 >> 2;
v19 += ADPCM_index[v32];
if (v19 < 0)
v19 = 0;
if (v19 > 88)
v19 = 88;
if (v31)
v18 -= v34;
else
v18 += v34;
if (v18 > 32767)
v18 = 32767;
else if (v18 < -32768)
v18 = -32768;
*dest = v18;
comp += v29;
dest ++;
}
_lastADPCMval1 = v18;
_lastADPCMval2 = v19;
}
void AudioStreamInstance::play(bool fade, Audio::Mixer::SoundType soundType ) {
debugC(1, kDebugAudio, "play(%d)", (fade) ? 1 : 0);
Audio::SoundHandle soundHandle;
_stopped = false;
_fadingIn = fade;
_fadeTime = 0;
_mixer->playStream(soundType, &_handle, this);
handleFade(0);
}
void AudioStreamInstance::handleFade(int numSamples) {
debugC(5, kDebugAudio, "handleFade(%d)", numSamples);
if (_fadingOut) {
_fadeTime += numSamples;
if (_fadeTime > 40960) {
_fadeTime = 40960;
stopNow();
_fadingOut = false;
}
_mixer->setChannelVolume(_handle, _volume - _fadeTime * _volume / 40960);
} else {
if (_fadingIn) {
_fadeTime += numSamples;
if (_fadeTime > 40960) {
_fadeTime = 40960;
_fadingIn = false;
}
_mixer->setChannelVolume(_handle, _volume * _fadeTime / 40960);
}
}
}
void AudioStreamInstance::stop(bool fade /*= false*/) {
debugC(1, kDebugAudio, "stop(%d)", (fade) ? 1 : 0);
if (fade) {
_fadingIn = false;
_fadingOut = true;
_fadeTime = 0;
} else {
stopNow();
}
}
void AudioStreamInstance::stopNow() {
debugC(1, kDebugAudio, "stopNow()");
_stopped = true;
}
void AudioStreamInstance::setVolume(int32 volume) {
debugC(1, kDebugAudio, "setVolume(%d)", volume);
_volume = volume;
_mixer->setChannelVolume(_handle, volume);
}
AudioStreamPackage::AudioStreamPackage(ToonEngine *vm) : _vm(vm) {
_indexBuffer = 0;
}
bool AudioStreamPackage::loadAudioPackage(Common::String indexFile, Common::String streamFile) {
debugC(4, kDebugAudio, "loadAudioPackage(%s, %s)", indexFile.c_str(), streamFile.c_str());
uint32 size = 0;
uint8 *fileData = _vm->resources()->getFileData(indexFile, &size);
if (!fileData)
return false;
_indexBuffer = new uint32[size / 4];
memcpy(_indexBuffer, fileData, size);
_file = _vm->resources()->openFile(streamFile);
if (!_file)
return false;
return true;
}
void AudioStreamPackage::getInfo(int32 id, int32 *offset, int32 *size) {
debugC(1, kDebugAudio, "getInfo(%d, offset, size)", id);
*offset = READ_LE_UINT32(_indexBuffer + id);
*size = READ_LE_UINT32(_indexBuffer + id + 1) - READ_LE_UINT32(_indexBuffer + id);
}
Common::SeekableReadStream *AudioStreamPackage::getStream(int32 id, bool ownMemory) {
debugC(1, kDebugAudio, "getStream(%d, %d)", id, (ownMemory) ? 1 : 0);
int32 offset = 0;
int32 size = 0;
getInfo(id, &offset, &size);
if (ownMemory) {
byte *memory = new byte[size];
_file->seek(offset);
_file->read(memory, size);
return new Common::MemoryReadStream(memory, size, DisposeAfterUse::YES);
} else {
return new Common::SeekableSubReadStream(_file, offset, size + offset);
}
}
} // End of namespace Toon

143
engines/toon/audio.h Normal file
View file

@ -0,0 +1,143 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#ifndef TOON_AUDIO_H
#define TOON_AUDIO_H
#include "sound/audiostream.h"
#include "sound/mixer.h"
#include "toon.h"
namespace Toon {
// used for music/voice/everything
class AudioManager;
class AudioStreamInstance : public Audio::AudioStream {
public:
AudioStreamInstance(AudioManager *man, Audio::Mixer *mixer, Common::SeekableReadStream *stream, bool looping = false);
~AudioStreamInstance();
void play(bool fade = false, Audio::Mixer::SoundType soundType = Audio::Mixer::kMusicSoundType);
void stop(bool fade = false);
bool isPlaying() {
return !_stopped;
}
bool isLooping() {
return _looping;
}
bool isFading() {
return _fadingIn || _fadingOut;
}
void setVolume(int32 volume);
protected:
int32 readBuffer(int16 *buffer, const int numSamples);
bool isStereo() const {
return false;
};
int getRate() const {
return 22100;
};
bool endOfData() const {
return _stopped;
};
void handleFade(int32 numSamples);
void stopNow();
bool readPacket();
void decodeADPCM(uint8 *comp, int16 *dest, int32 packetSize);
Common::SeekableReadStream *_file;
bool _fadingIn;
bool _fadingOut;
int32 _fadeTime;
uint8 *_compBuffer;
int16 *_buffer;
int32 _bufferSize;
int32 _bufferMaxSize;
int32 _bufferOffset;
int32 _compBufferSize;
Audio::SoundHandle _handle;
Audio::Mixer *_mixer;
int32 _lastADPCMval1;
int32 _lastADPCMval2;
bool _stopped;
AudioManager *_man;
int32 _totalSize;
int32 _currentReadSize;
bool _looping;
int32 _volume;
};
class AudioStreamPackage {
public:
AudioStreamPackage(ToonEngine *vm);
bool loadAudioPackage(Common::String indexFile, Common::String streamFile);
void getInfo(int32 id, int32 *offset, int32 *size);
Common::SeekableReadStream *getStream(int32 id, bool ownMemory = false);
protected:
Common::SeekableReadStream *_file;
uint32 *_indexBuffer;
ToonEngine *_vm;
};
class AudioManager {
public:
void removeInstance(AudioStreamInstance *inst); // called by destructor
AudioManager(ToonEngine *vm, Audio::Mixer *mixer);
~AudioManager(void);
bool voiceStillPlaying();
void playMusic(Common::String dir, Common::String music);
void playVoice(int32 id, bool genericVoice);
void playSFX(int32 id, int volume, bool genericSFX);
void stopCurrentVoice();
void setMusicVolume(int32 volume);
void stopMusic();
bool loadAudioPack(int32 id, Common::String indexFile, Common::String packFile);
AudioStreamInstance *_channels[16]; // 0-1 : music
// 2 : voice
// 3-16 : SFX
AudioStreamPackage *_audioPacks[4]; // 0 : generic streams
// 1 : local streams
// 2 : generic SFX
// 3 : local SFX
uint32 _currentMusicChannel;
Common::String _currentMusicName;
ToonEngine *_vm;
Audio::Mixer *_mixer;
};
} // End of namespace Toon
#endif

1024
engines/toon/character.cpp Normal file

File diff suppressed because it is too large Load diff

144
engines/toon/character.h Normal file
View file

@ -0,0 +1,144 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#ifndef TOON_CHARACTER_H
#define TOON_CHARACTER_H
#include "toon.h"
namespace Toon {
class ToonEngine;
struct SpecialCharacterAnimation {
char _filename[9]; // 0
byte _flag1; // 9
short _offsetX; // 10
short _offsetY; // 12
short _unused; // 14
short _unused2; // 16
byte _flags2; // 18
byte _flags3; // 19
byte _flags4; // 20
byte _flags5; // 21
byte _flags6; // 22
byte _flags7; // 23
byte _flags8; // 24
byte _flags9; // 25
};
class Character {
public:
Character(ToonEngine *vm);
virtual ~Character(void);
virtual void init();
virtual int32 getId();
virtual void setId(int32 id);
virtual void setFacing(int32 facing);
virtual int32 getFacing();
virtual void setAnimScript(int32 animScriptId);
virtual void setSceneAnimationId(int32 sceneAnimationId);
virtual void setDefaultSpecialAnimationId(int32 defaultAnimationId);
virtual int32 getAnimScript();
virtual int32 getSceneAnimationId();
virtual void setFlag(int flag);
virtual int32 getFlag();
virtual int32 getAnimFlag();
virtual void setAnimFlag(int32 flag);
virtual void setPosition(int32 x, int32 y);
virtual int32 getX();
virtual int32 getY();
virtual int32 getFinalX();
virtual int32 getFinalY();
virtual bool walkTo(int32 newPosX, int32 newPosY);
virtual bool getVisible();
virtual void setVisible(bool visible);
virtual bool loadWalkAnimation(Common::String animName);
virtual bool loadIdleAnimation(Common::String animName);
virtual bool loadTalkAnimation(Common::String animName);
virtual bool loadShadowAnimation(Common::String animName);
virtual bool setupPalette();
virtual void playStandingAnim();
virtual void playWalkAnim(int32 start, int32 end);
virtual void playTalkAnim();
virtual void playAnim(int32 animId, int32 unused, int32 flags);
virtual void update(int32 timeIncrement);
virtual int32 getScale();
virtual AnimationInstance *getAnimationInstance();
virtual void setAnimationInstance(AnimationInstance *instance);
virtual void save(Common::WriteStream *stream);
virtual void load(Common::ReadStream *stream);
virtual void stopWalk();
virtual void stopSpecialAnim();
virtual void updateIdle();
virtual int32 getRandomIdleAnim() { return 0; };
int32 getFacingFromDirection(int32 dx, int32 dy);
static SpecialCharacterAnimation *getSpecialAnimation(int32 characterId, int32 animationId);
protected:
ToonEngine *_vm;
int32 _id;
int32 _animScriptId;
int32 _animSpecialId;
int32 _animSpecialDefaultId;
int32 _sceneAnimationId;
int32 _lineToSayId;
int32 _time;
int32 _x;
int32 _y;
int32 _z;
int32 _finalX;
int32 _finalY;
int32 _facing;
int32 _flags;
int32 _animFlags;
int32 _scale;
int32 _nextIdleTime;
bool _visible;
bool _blockingWalk;
int32 _speed;
int32 _lastWalkTime;
int32 _numPixelToWalk;
AnimationInstance *_animationInstance;
AnimationInstance *_shadowAnimationInstance;
Animation *_walkAnim;
Animation *_idleAnim;
Animation *_talkAnim;
Animation *_shadowAnim;
Animation *_specialAnim;
int32 _currentPathX[4096];
int32 _currentPathY[4096];
int32 _currentPathNodeCount;
int32 _currentPathNode;
};
} // End of namespace Toon
#endif

View file

@ -0,0 +1,49 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#include "conversation.h"
namespace Toon {
void Conversation::save(Common::WriteStream *stream, int16* conversationDataBase) {
stream->writeSint32BE(_enable);
for (int32 i = 0; i < 10; i++) {
stream->writeSint32BE(state[i]._data2);
stream->writeSint16BE(state[i]._data3);
stream->writeSint32BE((int16*)state[i]._data4 - conversationDataBase);
}
}
void Conversation::load(Common::ReadStream *stream, int16* conversationDataBase) {
_enable = stream->readSint32BE();
for (int32 i = 0; i < 10; i++) {
state[i]._data2 = stream->readSint32BE();
state[i]._data3 = stream->readSint16BE();
state[i]._data4 = conversationDataBase + stream->readSint32BE();
}
}
}

View file

@ -0,0 +1,49 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#ifndef TOON_CONVERSATION_H
#define TOON_CONVERSATION_H
#include "engines/engine.h"
#include "common/stream.h"
namespace Toon {
class Conversation {
public:
int32 _enable; // 00
struct ConvState {
int32 _data2; // 04
int16 _data3; // 08
void *_data4; // 10
} state[10];
void save(Common::WriteStream *stream, int16* conversationDataBase);
void load(Common::ReadStream *stream, int16* conversationDataBase);
};
} // End of namespace Toon
#endif

254
engines/toon/detection.cpp Normal file
View file

@ -0,0 +1,254 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#include "common/config-manager.h"
#include "engines/advancedDetector.h"
#include "common/savefile.h"
#include "common/system.h"
#include "base/plugins.h"
#include "graphics/thumbnail.h"
#include "toon.h"
static const PlainGameDescriptor ToonGames[] = {
{ "toon", "Toonstruck" },
{ "toondemo", "Toonstruck Demo" },
{ 0, 0 }
};
namespace Toon {
using Common::GUIO_NONE;
static const ADGameDescription gameDescriptions[] = {
{ "toon", "", {
{"local.pak", 0, "3290209ef9bc92692108dd2f45df0736", 3237611},
{"arcaddbl.svl", 0, "c418478cd2833c7c983799f948af41ac", 7844688},
{"study.svl", 0, "281efa3f33f6712c0f641a605f4d40fd", 2511090},
AD_LISTEND},
Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS, GUIO_NONE
},
{ "toon", "", {
{"local.pak", 0, "517132c3575b38806d1e7b6f59848072", 3224044},
{"arcaddbl.svl", 0, "ff74008827b62fbef1f46f104c438e44", 9699256},
{"study.svl", 0, "df056b94ea83f1ed92a539cf636053ab", 2542668},
AD_LISTEND},
Common::FR_FRA, Common::kPlatformPC, ADGF_NO_FLAGS, GUIO_NONE
},
{ "toon", "", {
{"local.pak", 0, "bf5da4c03f78ffbd643f12122319366e", 3250841},
{"arcaddbl.svl", 0, "7a0d74f4d66d1c722b946abbeb0834ef", 9122249},
{"study.svl", 0, "72fe96a9e10967d3138e918295babc42", 2910283},
AD_LISTEND},
Common::DE_DEU, Common::kPlatformPC, ADGF_NO_FLAGS, GUIO_NONE
},
{ "toon", "", {
{"local.pak", 0, "e8645168a247e2abdbfc2f9fa9d1c0fa", 3232222},
{"arcaddbl.svl", 0, "7893ac4cc78d51356baa058bbee7aa28", 8275016},
{"study.svl", 0, "b6b1ee2d9d94d53d305856039ab7bde7", 2634620},
AD_LISTEND},
Common::ES_ESP, Common::kPlatformPC, ADGF_NO_FLAGS, GUIO_NONE
},
{ "toondemo", "", {
{"local.pak", 0, "bf5da4c03f78ffbd643f12122319366e", 3250841},
{"wacexdbl.emc", 0, "cfbc2156a31b294b038204888407ebc8", 6974},
{"generic.svl", 0, "5eb99850ada22f0b8cf6392262d4dd07", 9404599},
AD_LISTEND},
Common::DE_DEU, Common::kPlatformPC, ADGF_DEMO, GUIO_NONE
},
AD_TABLE_END_MARKER
};
static const ADFileBasedFallback fileBasedFallback[] = {
{ &gameDescriptions[0], { "local.pak", "arcaddbl.svl", "study.svl", 0 } }, // default to english version
{ 0, { 0 } }
};
} // End of namespace Toon
static const char *directoryGlobs[] = {
"misc",
"act1",
"arcaddbl",
"act2",
"study",
0
};
static const ADParams detectionParams = {
(const byte *)Toon::gameDescriptions,
sizeof(ADGameDescription),
5000, // number of md5 bytes
ToonGames,
0, // no obsolete targets data
"toon",
Toon::fileBasedFallback,
0,
// Additional GUI options (for every game}
Common::GUIO_NONE,
// Maximum directory depth
3,
// List of directory globs
directoryGlobs
};
class ToonMetaEngine : public AdvancedMetaEngine {
public:
ToonMetaEngine() : AdvancedMetaEngine(detectionParams) {}
virtual const char *getName() const {
return "Toon Engine";
}
virtual const char *getOriginalCopyright() const {
return "Toonstruck (C) 1996 Virgin Interactive";
}
virtual bool hasFeature(MetaEngineFeature f) const;
virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const;
virtual int getMaximumSaveSlot() const;
virtual SaveStateList listSaves(const char *target) const;
SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const;
// virtual void removeSaveState(const char *target, int slot) const;
};
bool ToonMetaEngine::hasFeature(MetaEngineFeature f) const {
return
(f == kSupportsListSaves) ||
// (f == kSupportsLoadingDuringStartup) ||
(f == kSupportsDeleteSave) ||
(f == kSavesSupportMetaInfo) ||
(f == kSavesSupportThumbnail) ||
(f == kSavesSupportCreationDate);
}
int ToonMetaEngine::getMaximumSaveSlot() const { return 99; }
SaveStateList ToonMetaEngine::listSaves(const char *target) const {
Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
Common::StringArray filenames;
Common::String pattern = target;
pattern += ".???";
filenames = saveFileMan->listSavefiles(pattern);
sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..)
SaveStateList saveList;
int slotNum = 0;
for (Common::StringArray::const_iterator filename = filenames.begin(); filename != filenames.end(); ++filename) {
// Obtain the last 3 digits of the filename, since they correspond to the save slot
slotNum = atoi(filename->c_str() + filename->size() - 3);
if (slotNum >= 0 && slotNum <= 99) {
Common::InSaveFile *file = saveFileMan->openForLoading(*filename);
if (file) {
int32 version = file->readSint32BE();
if (version != TOON_SAVEGAME_VERSION) {
delete file;
continue;
}
// read name
uint16 nameSize = file->readUint16BE();
if (nameSize >= 255) {
delete file;
continue;
}
char name[256];
file->read(name, nameSize);
name[nameSize] = 0;
saveList.push_back(SaveStateDescriptor(slotNum, name));
delete file;
}
}
}
return saveList;
}
SaveStateDescriptor ToonMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
Common::String fileName = Common::String::printf("%s.%03d", target, slot);
Common::InSaveFile *file = g_system->getSavefileManager()->openForLoading(fileName);
if (file) {
int32 version = file->readSint32BE();
if (version != TOON_SAVEGAME_VERSION) {
delete file;
return SaveStateDescriptor();
}
uint32 saveNameLength = file->readUint16BE();
char saveName[256];
file->read(saveName, saveNameLength);
saveName[saveNameLength] = 0;
SaveStateDescriptor desc(slot, saveName);
Graphics::Surface *thumbnail = new Graphics::Surface();
assert(thumbnail);
if (!Graphics::loadThumbnail(*file, *thumbnail)) {
delete thumbnail;
thumbnail = 0;
}
desc.setThumbnail(thumbnail);
desc.setDeletableFlag(true);
desc.setWriteProtectedFlag(false);
uint32 saveDate = file->readUint32BE();
uint16 saveTime = file->readUint16BE();
int day = (saveDate >> 24) & 0xFF;
int month = (saveDate >> 16) & 0xFF;
int year = saveDate & 0xFFFF;
desc.setSaveDate(year, month, day);
int hour = (saveTime >> 8) & 0xFF;
int minutes = saveTime & 0xFF;
desc.setSaveTime(hour, minutes);
delete file;
return desc;
}
return SaveStateDescriptor();
}
bool ToonMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
if (desc) {
*engine = new Toon::ToonEngine(syst, desc);
}
return desc != 0;
}
#if PLUGIN_ENABLED_DYNAMIC(TOON)
REGISTER_PLUGIN_DYNAMIC(TOON, PLUGIN_TYPE_ENGINE, ToonMetaEngine);
#else
REGISTER_PLUGIN_STATIC(TOON, PLUGIN_TYPE_ENGINE, ToonMetaEngine);
#endif

122
engines/toon/drew.cpp Normal file
View file

@ -0,0 +1,122 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#include "drew.h"
namespace Toon {
CharacterDrew::CharacterDrew(ToonEngine *vm) : Character(vm) {
_id = 0;
_blockingWalk = true;
_animationInstance = vm->getAnimationManager()->createNewInstance(kAnimationCharacter);
_animationInstance->setUseMask(true);
vm->getAnimationManager()->addInstance(_animationInstance);
}
CharacterDrew::~CharacterDrew(void) {
}
bool CharacterDrew::setupPalette() {
debugC(1, kDebugCharacter, "setupPalette()");
if (_walkAnim) {
_walkAnim->applyPalette(129, 129 * 3, 63);
return true;
}
return false;
}
void CharacterDrew::setFacing(int32 facing) {
debugC(4, kDebugCharacter, "setFacing(%d)", facing);
_facing = facing;
}
void CharacterDrew::setPosition(int32 x, int32 y) {
debugC(5, kDebugCharacter, "setPosition(%d, %d)", x, y);
_z = _vm->getLayerAtPoint(x, y);
_scale = _vm->getScaleAtPoint(x, y);
// work out position and scale of the character sprite
int32 width = _walkAnim->getWidth() * _scale / 1024;
int32 height = 210 * _scale / 1024;
_animationInstance->setPosition(x - width / 2, y - height, _z , false);
_animationInstance->setScale(_scale);
// work out position and scale of the shadow below character
int32 shadowWidth = _shadowAnim->getWidth() * _scale / 1024;
int32 shadowHeight = _shadowAnim->getHeight() * _scale / 1024;
_shadowAnimationInstance->setPosition(x - shadowWidth / 2, y - shadowHeight / 2 - 4 , _z , false);
_shadowAnimationInstance->setScale(_scale);
_x = x;
_y = y;
_animationInstance->setLayerZ(_y);
}
void CharacterDrew::playStandingAnim() {
debugC(4, kDebugCharacter, "playStandingAnim()");
stopSpecialAnim();
_animationInstance->setAnimation(_walkAnim);
_animationInstance->setFrame(_facing * 2);
_shadowAnimationInstance->setFrame(_facing);
_animationInstance->setAnimationRange(_facing * 2, _facing * 2);
_animationInstance->stopAnimation();
_animationInstance->setLooping(true);
//setVisible(true);
}
void CharacterDrew::playWalkAnim(int32 start, int32 end) {
debugC(4, kDebugCharacter, "playWalkAnim(%d, %d)", start, end);
stopSpecialAnim();
_animationInstance->setAnimation(_walkAnim);
_shadowAnimationInstance->setFrame(_facing);
_animationInstance->setAnimationRange(16 + _facing * 14, 16 + _facing * 14 + 13);
_animationInstance->playAnimation();
_animationInstance->setFps(16);
_animationInstance->setLooping(true);
//setVisible(true);
}
void CharacterDrew::update(int32 timeIncrement) {
debugC(5, kDebugCharacter, "update(%d)", timeIncrement);
Character::update(timeIncrement);
setPosition(_x, _y);
}
int32 CharacterDrew::getRandomIdleAnim() {
debugC(3, kDebugCharacter, "getRandomIdleAnim()");
static int32 idle[] = { 6, 9, 10, 11, 12 };
return idle[_vm->randRange(0, 4)];
}
} // End of namespace Toon

51
engines/toon/drew.h Normal file
View file

@ -0,0 +1,51 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#ifndef TOON_DREW_H
#define TOON_DREW_H
#include "character.h"
namespace Toon {
class ToonEngine;
class CharacterDrew : public Character {
public:
CharacterDrew(ToonEngine *vm);
virtual ~CharacterDrew(void);
bool setupPalette();
void setFacing(int32 facing);
void playStandingAnim();
void setPosition(int32 x, int32 y);
void update(int32 timeIncrement);
void playWalkAnim(int32 start, int32 end);
int32 getRandomIdleAnim();
};
} // End of namespace Toon
#endif

108
engines/toon/flux.cpp Normal file
View file

@ -0,0 +1,108 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#include "flux.h"
namespace Toon {
CharacterFlux::CharacterFlux(ToonEngine *vm) : Character(vm) {
_id = 1;
_animationInstance = vm->getAnimationManager()->createNewInstance(kAnimationCharacter);
_animationInstance->setUseMask(true);
vm->getAnimationManager()->addInstance(_animationInstance);
}
CharacterFlux::~CharacterFlux(void) {
}
void CharacterFlux::playStandingAnim() {
debugC(4, kDebugCharacter, "playStandingAnim()");
_animationInstance->setAnimation(_walkAnim);
_animationInstance->setFrame(_facing * 3);
_animationInstance->setAnimationRange(_facing * 3, _facing * 3);
_animationInstance->stopAnimation();
_animationInstance->setLooping(true);
//s/etVisible(true);
}
void CharacterFlux::setVisible(bool visible) {
if (_vm->state()->_currentChapter == 2) {
Character::setVisible(false);
}
else {
Character::setVisible(visible);
}
}
void CharacterFlux::playWalkAnim(int32 start, int32 end) {
debugC(4, kDebugCharacter, "playWalkAnim(%d, %d)", start, end);
_animationInstance->setAnimation(_walkAnim);
_animationInstance->setAnimationRange(24 + _facing * 10, 24 + _facing * 10 + 9);
_animationInstance->playAnimation();
_animationInstance->setFps(16);
_animationInstance->setLooping(true);
}
void CharacterFlux::setPosition(int32 x, int32 y) {
debugC(5, kDebugCharacter, "setPosition(%d, %d)", x, y);
_z = _vm->getLayerAtPoint(x, y);
_scale = _vm->getScaleAtPoint(x, y);
int32 width = _walkAnim->getWidth() * _scale / 1024;
int32 height = 165 * _scale / 1024;
_animationInstance->setPosition(x - width / 2, y - height, _z , false);
_animationInstance->setScale(_scale);
// in original code, flux shadow scale is 3/4 of real scale
int32 shadowScale = _scale * 3 / 4;
// work out position and scale of the shadow below character
int32 shadowWidth = _shadowAnim->getWidth() * shadowScale / 1024;
int32 shadowHeight = _shadowAnim->getHeight() * shadowScale / 1024;
_shadowAnimationInstance->setPosition(x - shadowWidth / 2, y - shadowHeight / 2 , _z , false);
_shadowAnimationInstance->setScale(shadowScale);
_x = x;
_y = y;
_finalX = x;
_finalY = y;
_animationInstance->setLayerZ(_y);
}
void CharacterFlux::update(int32 timeIncrement) {
debugC(5, kDebugCharacter, "update(%d)", timeIncrement);
Character::update(timeIncrement);
setPosition(_x, _y);
}
int32 CharacterFlux::getRandomIdleAnim() {
debugC(3, kDebugCharacter, "getRandomIdleAnim()");
static int32 idle[] = { 0xe, 0xf, 0x21, 0x22, 0x24, 0x25, 0x27 };
return idle[_vm->randRange(0, 6)];
}
} // End of namespace Toon

51
engines/toon/flux.h Normal file
View file

@ -0,0 +1,51 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#ifndef TOON_FLUX_H
#define TOON_FLUX_H
#include "character.h"
class ToonEngine;
namespace Toon {
class CharacterFlux : public Character {
public:
CharacterFlux(ToonEngine *vm);
virtual ~CharacterFlux(void);
void setPosition(int32 x, int32 y);
void playStandingAnim();
void playWalkAnim(int32 start, int32 end);
void update(int32 timeIncrement);
int32 getRandomIdleAnim();
void setVisible(bool visible);
};
} // End of namespace Toon
#endif

274
engines/toon/font.cpp Normal file
View file

@ -0,0 +1,274 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#include "font.h"
namespace Toon {
FontRenderer::FontRenderer(ToonEngine *vm) : _vm(vm) {
_currentFontColor[0] = 0;
_currentFontColor[1] = 0xc8;
_currentFontColor[2] = 0xcb;
_currentFontColor[3] = 0xce;
}
// mapping extended characters required for foreign versions to font (animation)
static const byte map_textToFont[0x80] = {
'?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', // 0x8x
'?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', // 0x9x
'?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', // 0xAx
'?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', // 0xBx
'?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', // 0xCx
'?', 0x0b, '?', '?', '?', '?', 0x1e, '?', '?', '?', '?', '?', 0x1f, '?', '?', 0x19, // 0xDx
0x0d, 0x04, 0x0e, '?', 0x1a, '?', '?', 0x18, 0x10, 0x0f, 0x12, 0x11, 0x09, 0x05, 0x14, 0x13, // 0xEx
0x23, 0x08, 0x23, 0x06, 0x15, 0x23, 0x1b, 0x23, 0x23, 0x16, 0x07, 0x17, 0x1c, 0x23, 0x23, 0x23 // 0xFx
};
void FontRenderer::renderText(int32 x, int32 y, Common::String origText, int32 mode) {
debugC(5, kDebugFont, "renderText(%d, %d, %s, %d)", x, y, origText.c_str(), mode);
int32 xx, yy;
computeSize(origText, &xx, &yy);
if (mode & 2) {
y -= yy / 2;
} else if (mode & 4) {
y -= yy;
}
if (mode & 1) {
x -= xx / 2;
}
int32 curX = x;
int32 curY = y;
int32 height = 0;
const byte *text = (byte *)origText.c_str();
while (*text) {
byte curChar = *text;
if (curChar == 13) {
curY = curY + height;
height = 0;
curX = x;
} else {
if (curChar >= 0x80)
curChar = map_textToFont[curChar - 0x80];
_currentFont->drawFontFrame(_vm->getMainSurface(), curChar, curX, curY, _currentFontColor);
curX = curX + _currentFont->getFrameWidth(curChar) - 1;
height = MAX(height, _currentFont->getFrameHeight(curChar));
}
text++;
}
}
void FontRenderer::computeSize(Common::String origText, int32 *retX, int32 *retY) {
debugC(4, kDebugFont, "computeSize(%s, retX, retY)", origText.c_str());
int32 lineWidth = 0;
int32 lineHeight = 0;
int32 totalHeight = 0;
int32 totalWidth = 0;
const byte *text = (byte *)origText.c_str();
while (*text) {
byte curChar = *text;
if (curChar < 32) {
text++;
continue;
} else if (curChar == 13) {
totalWidth = MAX(totalWidth, lineWidth);
totalHeight += lineHeight;
lineHeight = 0;
lineWidth = 0;
} else {
if (curChar >= 0x80)
curChar = map_textToFont[curChar - 0x80];
int32 charWidth = _currentFont->getFrameWidth(curChar) - 1;
int32 charHeight = _currentFont->getFrameHeight(curChar);
lineWidth += charWidth;
lineHeight = MAX(lineHeight, charHeight);
}
text++;
}
totalHeight += lineHeight;
totalWidth = MAX(totalWidth, lineWidth);
*retX = totalWidth;
*retY = totalHeight;
}
void FontRenderer::setFont(Animation *font) {
debugC(5, kDebugFont, "setFont(font)");
_currentFont = font;
}
void FontRenderer::setFontColorByCharacter(int32 characterId) {
debugC(5, kDebugFont, "setFontColorByCharacter(%d)", characterId);
// unfortunately this table was hardcoded in the original executable
static byte colorsByCharacters[] = {
0xe0, 0xdc, 0xc8, 0xd6, 0xc1, 0xc8, 0xe9, 0xde, 0xc8, 0xeb, 0xe8, 0xc8,
0xd1, 0xcf, 0xc8, 0xd8, 0xd5, 0xc8, 0xfb, 0xfa, 0xc8, 0xd9, 0xd7, 0xc8,
0xe8, 0xe4, 0xc8, 0xe9, 0xfa, 0xc8, 0xeb, 0xe4, 0xc8, 0xeb, 0xe4, 0xc8,
0xd2, 0xea, 0xc8, 0xd3, 0xd0, 0xc8, 0xe1, 0xdd, 0xc8, 0xd9, 0xd7, 0xc8,
0xd9, 0xd7, 0xc8, 0xd9, 0xd7, 0xc8, 0xd9, 0xd7, 0xc8, 0xd9, 0xd7, 0xc8,
0xd2, 0xcf, 0xc8, 0xd1, 0xcf, 0xc8, 0xd9, 0xd7, 0xc8, 0xe3, 0xdd, 0xc8,
0xd9, 0xd7, 0xc8, 0xd9, 0xd7, 0xc8, 0xd9, 0xd7, 0xc8, 0xd9, 0xd7, 0xc8,
0xd9, 0xd7, 0xc8, 0xd9, 0xd7, 0xc8, 0xd9, 0xd7, 0xc8, 0xd9, 0xd7, 0xc8,
0xd9, 0xd7, 0xc8, 0xe6, 0xe4, 0xc8, 0xd9, 0xd7, 0xc8, 0xcd, 0xca, 0xc8,
0xd9, 0xd7, 0xc8, 0xd9, 0xd7, 0xc8, 0xe8, 0xe8, 0xc8, 0xdb, 0xd5, 0xc8,
0xe0, 0xdc, 0xc8, 0xd6, 0xc1, 0xc8, 0xd3, 0xd0, 0xc8, 0xd1, 0xcf, 0xc8,
0xe6, 0xe4, 0xc8, 0xd1, 0xcf, 0xc8, 0xd2, 0xcf, 0xc8, 0xcc, 0xcb, 0xc8,
0xd9, 0xd7, 0xc8, 0xd9, 0xd7, 0xc8, 0xd9, 0xd7, 0xc8, 0xd9, 0xd7, 0xc8,
0xd9, 0xd7, 0xc8, 0xd9, 0xd7, 0xc8, 0xd9, 0xd7, 0xc8, 0xd9, 0xd7, 0xc8,
0xd9, 0xd7, 0xc8, 0xd9, 0xd7, 0xc8, 0xd9, 0xd7, 0xc8, 0xd9, 0xd7, 0xc8
};
setFontColor(colorsByCharacters[characterId * 3 + 2], colorsByCharacters[characterId * 3 + 1], colorsByCharacters[characterId * 3 + 0]);
}
void FontRenderer::setFontColor(int32 fontColor1, int32 fontColor2, int32 fontColor3) {
debugC(5, kDebugFont, "setFontColor(%d, %d, %d)", fontColor1, fontColor2, fontColor3);
_currentFontColor[0] = 0;
_currentFontColor[1] = fontColor1;
_currentFontColor[2] = fontColor2;
_currentFontColor[3] = fontColor3;
}
void FontRenderer::renderMultiLineText(int32 x, int32 y, Common::String origText, int32 mode) {
debugC(5, kDebugFont, "renderMultiLineText(%d, %d, %s, %d)", x, y, origText.c_str(), mode);
// divide the text in several lines
// based on number of characters or size of lines.
byte text[1024];
strncpy((char *)text, origText.c_str(), 1023);
text[1023] = 0;
byte *lines[16];
int32 lineSize[16];
int32 numLines = 0;
byte *it = text;
int32 maxWidth = 0;
int32 curWidth = 0;
while (1) {
byte *lastLine = it;
byte *lastSpace = it;
int32 lastSpaceX = 0;
int32 curLetterNr = 0;
curWidth = 0;
while (*it && curLetterNr < 50 && curWidth < 580) {
byte curChar = *it;
if (curChar == 32) {
lastSpace = it;
lastSpaceX = curWidth;
} else if (curChar >= 0x80) {
curChar = map_textToFont[curChar - 0x80];
}
int width = _currentFont->getFrameWidth(curChar);
curWidth += width - 2;
it++;
curLetterNr++;
}
if (*lastLine == 0)
break;
lines[numLines] = lastLine;
if (*it == 0)
lineSize[numLines] = curWidth;
else
lineSize[numLines] = lastSpaceX;
if (lineSize[numLines] > maxWidth)
maxWidth = lineSize[numLines];
lastLine = lastSpace + 1;
numLines++;
if (*it == 0)
break;
it = lastLine;
*lastSpace = 0;
if (numLines >= 16)
break;
}
if (curWidth > maxWidth) {
maxWidth = curWidth;
}
//numLines++;
// get font height (assumed to be constant)
int32 height = _currentFont->getHeight();
int textSize = (height - 2) * numLines;
y = y - textSize;
if (y < 30)
y = 30;
if (y + textSize > 370)
y = 370 - textSize;
x -= _vm->state()->_currentScrollValue;
// adapt x
if (x - 30 - maxWidth / 2 < 0)
x = maxWidth / 2 + 30;
if (x + 30 + (maxWidth / 2) > 640)
x = 640 - (maxWidth / 2) - 30;
// we have good coordinates now, we can render the multi line
int32 curX = x;
int32 curY = y;
for (int32 i = 0; i < numLines; i++) {
const byte *line = lines[i];
curX = x - lineSize[i] / 2;
while (*line) {
byte curChar = *line;
if (curChar >= 0x80)
curChar = map_textToFont[curChar - 0x80];
if (curChar != 32) _currentFont->drawFontFrame(_vm->getMainSurface(), curChar, curX + _vm->state()->_currentScrollValue, curY, _currentFontColor);
curX = curX + _currentFont->getFrameWidth(curChar) - 2;
//height = MAX(height, _currentFont->getFrameHeight(curChar));
line++;
}
curY += height;
}
}
} // End of namespace Toon

52
engines/toon/font.h Normal file
View file

@ -0,0 +1,52 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#ifndef TOON_FONT_H
#define TOON_FONT_H
#include "toon.h"
namespace Toon {
class FontRenderer {
public:
FontRenderer(ToonEngine *vm);
~FontRenderer(void);
void setFont(Animation *font);
void computeSize(Common::String origText, int32 *retX, int32 *retY);
void renderText(int32 x, int32 y, Common::String origText, int32 mode);
void renderMultiLineText(int32 x, int32 y, Common::String origText, int32 mode);
void setFontColorByCharacter(int32 characterId);
void setFontColor(int32 fontColor1, int32 fontColor2, int32 fontColor3);
protected:
Animation *_currentFont;
ToonEngine *_vm;
byte _currentFontColor[4];
};
} // End of namespace Toon
#endif

157
engines/toon/hotspot.cpp Normal file
View file

@ -0,0 +1,157 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#include "hotspot.h"
#include "tools.h"
namespace Toon {
Hotspots::Hotspots(ToonEngine *vm) : _vm(vm) {
_items = 0;
_numItems = 0;
}
void Hotspots::load(Common::ReadStream *Stream) {
delete[] _items;
_numItems = Stream->readSint16BE();
_items = new HotspotData[_numItems];
for (int32 i = 0; i < _numItems; i++) {
for (int32 a = 0; a < 256; a++)
_items[i].setData(a,Stream->readSint16BE());
}
}
void Hotspots::save(Common::WriteStream *Stream) {
Stream->writeSint16BE(_numItems);
for (int32 i = 0; i < _numItems; i++) {
for (int32 a = 0; a < 256; a++)
Stream->writeSint16BE(_items[i].getData(a));
}
}
int32 Hotspots::FindBasedOnCorner(int32 x, int32 y) {
debugC(1, kDebugHotspot, "FindBasedOnCorner(%d, %d)", x, y);
for (int32 i = 0; i < _numItems; i++) {
if (x == _items[i].getX1()) {
if (y == _items[i].getY1()) {
if (_items[i].getMode() == -1)
return _items[i].getRef();
return i ;
}
}
}
return -1;
}
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;
for (int i = 0; i < _numItems; i++) {
if (x >= _items[i].getX1() && x <= _items[i].getX2() && y >= _items[i].getY1() && y <= _items[i].getY2()) {
if (_items[i].getMode() == -1)
testId = _items[i].getRef();
else
testId = i;
if (_items[testId].getPriority() > priority) {
// Strangerke - Commented (not used)
// found = true;
foundId = testId;
priority = _items[testId].getPriority();
}
}
}
return foundId;
}
bool Hotspots::LoadRif(Common::String rifName, Common::String additionalRifName) {
debugC(1, kDebugHotspot, "LoadRif(%s, %s)", rifName.c_str(), additionalRifName.c_str());
uint32 size = 0;
uint8 *rifData = _vm->resources()->getFileData(rifName, &size);
if (!rifData)
return false;
uint32 size2 = 0;
uint8 *rifData2 = 0;
if (additionalRifName.size())
rifData2 = _vm->resources()->getFileData(additionalRifName, &size2);
// figure out the number of hotspots based on file size
int32 rifsize = READ_BE_UINT32(&rifData[4]);
int32 rifsize2 = 0;
if (size2)
rifsize2 = READ_BE_UINT32(&rifData2[4]);
_numItems = (rifsize + rifsize2) / 512;
if (_items)
delete[] _items;
_items = new HotspotData[_numItems];
// RIFs are compressed in RNC1
RncDecoder decoder;
decoder.unpackM1(rifData, _items);
if (rifsize2) {
RncDecoder decoder2;
decoder2.unpackM1(rifData2 , _items + (rifsize >> 9));
for (int32 i = 0; i < (rifsize2 >> 9); i++) {
HotspotData *hot = _items + (rifsize >> 9) + i;
hot->setData(0, hot->getX1() + 1280);
hot->setData(2, hot->getX2() + 1280);
if (hot->getMode() == -1)
hot->setData(5, hot->getRef() + (rifsize >> 9));
}
}
return true;
}
HotspotData *Hotspots::Get(int32 id) {
debugC(5, kDebugHotspot, "Get(%d)", id);
if (id < 0 || id >= _numItems)
return 0;
else
return &_items[id];
}
} // End of namespace Toon

73
engines/toon/hotspot.h Normal file
View file

@ -0,0 +1,73 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#ifndef TOON_HOTSPOT_H
#define TOON_HOTSPOT_H
#include "toon.h"
#include "tools.h"
namespace Toon {
class HotspotData {
public:
int16 getX1() const { return READ_LE_INT16(_data + 0); }
int16 getY1() const { return READ_LE_INT16(_data + 1); }
int16 getX2() const { return READ_LE_INT16(_data + 2); }
int16 getY2() const { return READ_LE_INT16(_data + 3); }
int16 getMode() const { return READ_LE_INT16(_data + 4); }
int16 getRef() const { return READ_LE_INT16(_data + 5); }
int16 getPriority() const { return READ_LE_INT16(_data + 7); }
int16 getType() const { return READ_LE_INT16(_data + 8); }
int16 getData(int32 id) const { return READ_LE_INT16(_data + id); }
void setData(int32 id, int16 val) { WRITE_LE_UINT16(&_data[id], val); };
private:
int16 _data[256];
};
class Hotspots {
public:
Hotspots(ToonEngine *vm);
~Hotspots(void);
bool LoadRif(Common::String rifName, Common::String additionalRifName);
int32 Find(int32 x, int32 y);
int32 FindBasedOnCorner(int32 x, int32 y);
HotspotData *Get(int32 id);
int32 getCount() const { return _numItems; };
void load(Common::ReadStream *Stream);
void save(Common::WriteStream *Stream);
protected:
HotspotData *_items;
int32 _numItems;
ToonEngine *_vm;
};
} // End of namespace Toon
#endif

30
engines/toon/module.mk Normal file
View file

@ -0,0 +1,30 @@
MODULE := engines/toon
MODULE_OBJS := \
anim.o \
audio.o \
character.o \
conversation.o \
detection.o \
drew.o \
flux.o \
font.o \
hotspot.o \
movie.o \
path.o \
picture.o \
resource.o \
script.o \
script_func.o \
state.o \
text.o \
tools.o \
toon.o
# This module can be built as a plugin
ifeq ($(ENABLE_TOON), DYNAMIC_PLUGIN)
PLUGIN := 1
endif
# Include common rules
include $(srcdir)/rules.mk

111
engines/toon/movie.cpp Normal file
View file

@ -0,0 +1,111 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#include "movie.h"
namespace Toon {
void ToonstruckSmackerDecoder::handleAudioTrack(const byte &track, const uint32 &chunkSize, const uint32 &unpackedSize) {
debugC(6, kDebugMovie, "handleAudioTrack(%d, %d, %d)", track, chunkSize, unpackedSize);
if (track == 1 && chunkSize == 4) {
/* uint16 width = */ _fileStream->readUint16LE();
uint16 height = _fileStream->readUint16LE();
_header.flags = (height == getHeight() / 2) ? 4 : 0;
} else
Graphics::SmackerDecoder::handleAudioTrack(track, chunkSize, unpackedSize);
}
bool ToonstruckSmackerDecoder::loadFile(const Common::String &filename, int forcedflags) {
debugC(1, kDebugMovie, "loadFile(%s, %d)", filename.c_str(), forcedflags);
if (Graphics::SmackerDecoder::loadFile(filename)) {
if (forcedflags & 0x10 || _surface->h == 200) {
_header.flags = 4;
delete this->_surface;
_surface = new Graphics::Surface();
_surface->create(640, 400, 1);
}
return true;
}
return false;
}
ToonstruckSmackerDecoder::ToonstruckSmackerDecoder(Audio::Mixer *mixer, Audio::Mixer::SoundType soundType) : Graphics::SmackerDecoder(mixer, soundType) {
}
Movie::Movie(ToonEngine *vm , ToonstruckSmackerDecoder *decoder) {
_vm = vm;
_decoder = decoder;
}
Movie::~Movie() {
}
void Movie::init() const {
}
void Movie::play(Common::String video, int32 flags) {
debugC(1, kDebugMovie, "play(%s, %d)", video.c_str(), flags);
if (flags & 1)
_vm->getAudioManager()->setMusicVolume(0);
_decoder->loadFile(video.c_str(), flags);
playVideo();
_vm->flushPalette();
if (flags & 1)
_vm->getAudioManager()->setMusicVolume(100);
_decoder->close();
}
bool Movie::playVideo() {
debugC(1, kDebugMovie, "playVideo()");
int32 x = 0;
int32 y = 0;
while (!_vm->shouldQuit() && !_decoder->endOfVideo()) {
if (_decoder->needsUpdate()) {
Graphics::Surface *frame = _decoder->decodeNextFrame();
if (frame)
_vm->getSystem()->copyRectToScreen((byte *)frame->pixels, frame->pitch, x, y, frame->w, frame->h);
_decoder->setSystemPalette();
_vm->getSystem()->updateScreen();
}
Common::Event event;
while (_vm->getSystem()->getEventManager()->pollEvent(event))
if ((event.type == Common::EVENT_KEYDOWN && event.kbd.keycode == Common::KEYCODE_ESCAPE) || event.type == Common::EVENT_LBUTTONUP) {
return false;
}
_vm->getSystem()->delayMillis(10);
}
return !_vm->shouldQuit();
}
} // End of namespace Toon

58
engines/toon/movie.h Normal file
View file

@ -0,0 +1,58 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#ifndef TOON_MOVIE_H
#define TOON_MOVIE_H
#include "toon.h"
#include "graphics/video/smk_decoder.h"
namespace Toon {
class ToonstruckSmackerDecoder : public Graphics::SmackerDecoder {
public:
ToonstruckSmackerDecoder(Audio::Mixer *mixer, Audio::Mixer::SoundType soundType = Audio::Mixer::kSFXSoundType);
void handleAudioTrack(const byte &track, const uint32 &chunkSize, const uint32 &unpackedSize);
bool loadFile(const Common::String &filename, int forcedflags) ;
};
class Movie {
public:
Movie(ToonEngine *vm, ToonstruckSmackerDecoder *decoder);
~Movie(void);
void init() const;
void play(Common::String video, int32 flags = 0);
protected:
bool playVideo();
ToonEngine *_vm;
Audio::Mixer *_mixer;
ToonstruckSmackerDecoder *_decoder;
};
} // End of namespace Toon
#endif

370
engines/toon/path.cpp Normal file
View file

@ -0,0 +1,370 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#include "path.h"
namespace Toon {
int32 PathFindingHeap::init(int32 size) {
debugC(1, kDebugPath, "init(%d)", size);
_data = new HeapDataGrid[size * 2];
memset(_data, 0, sizeof(HeapDataGrid) * size * 2);
_count = 0;
_alloc = size;
return size;
}
int PathFindingHeap::unload() {
if (_data)
delete[] _data;
return 0;
}
int PathFindingHeap::clear() {
//debugC(1, kDebugPath, "clear()");
_count = 0;
memset(_data, 0, sizeof(HeapDataGrid) * _alloc * 2);
return 1;
}
int PathFindingHeap::push(int x, int y, int weight) {
//debugC(6, kDebugPath, "push(%d, %d, %d)", x, y, weight);
_count++;
_data[_count]._x = x;
_data[_count]._y = y;
_data[_count]._weight = weight;
int32 lMax = _count;
int32 lT = 0;
while (1) {
lT = lMax / 2;
if (lT < 1)
break;
if (_data[lT]._weight > _data[lMax]._weight) {
HeapDataGrid temp;
temp = _data[lT];
_data[lT] = _data[lMax];
_data[lMax] = temp;
lMax = lT;
} else {
break;
}
}
return 1;
}
int32 PathFindingHeap::pop(int32 *x, int32 *y, int32 *weight) {
//debugC(6, kDebugPath, "pop(x, y, weight)");
if (!_count)
return 0;
*x = _data[1]._x;
*y = _data[1]._y;
*weight = _data[1]._weight;
_data[1] = _data[_count];
_count--;
if (!_count)
return 0;
int32 lMin = 1;
int32 lT = 1;
while (1) {
lT = lMin << 1 ;
if (lT <= _count) {
if (lT < _count) {
if (_data[lT + 1]._weight < _data[lT]._weight)
lT++;
}
if (_data[lT]._weight <= _data[lMin]._weight) {
HeapDataGrid temp;
temp = _data[lMin];
_data[lMin] = _data[lT];
_data[lT] = temp;
lMin = lT;
} else {
break;
}
} else {
break;
}
}
return 0;
}
PathFinding::PathFinding(ToonEngine *vm) : _vm(vm) {
_width = 0;
_height = 0;
_heap = new PathFindingHeap();
_gridTemp = 0;
}
PathFinding::~PathFinding(void) {
if (_heap) {
_heap->unload();
delete _heap;
}
}
bool PathFinding::isWalkable(int32 x, int32 y) {
//debugC(6, kDebugPath, "isWalkable(%d, %d)", x, y);
bool maskWalk = (_currentMask->getData(x, y) & 0x1f) > 0;
for (int32 i = 0; i < _numBlockingRects; i++) {
if (_blockingRects[i][4] == 0) {
if (x >= _blockingRects[i][0] && x <= _blockingRects[i][2] && y >= _blockingRects[i][1] && y < _blockingRects[i][3])
return false;
}
else {
int32 dx = abs(_blockingRects[i][0] - x);
int32 dy = abs(_blockingRects[i][1] - y);
if ((dx << 8) / _blockingRects[i][2] < (1 << 8) && (dy << 8) / _blockingRects[i][3] < (1 << 8)) {
return false;
}
}
}
return maskWalk;
}
int32 PathFinding::findClosestWalkingPoint(int32 xx, int32 yy, int32 *fxx, int32 *fyy, int origX, int origY) {
debugC(1, kDebugPath, "findClosestWalkingPoint(%d, %d, fxx, fyy, %d, %d)", xx, yy, origX, origY);
int32 currentFound = -1;
int32 dist = -1;
int32 dist2 = -1;
if (origX == -1)
origX = xx;
if (origY == -1)
origY = yy;
for (int y = 0; y < _height; y++) {
for (int x = 0; x < _width ; x++) {
if (isWalkable(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)) {
dist = ndist;
dist2 = ndist2;
currentFound = y * _width + x;
}
}
}
}
if (currentFound != -1) {
*fxx = currentFound % _width;
*fyy = currentFound / _width;
return 1;
} else {
*fxx = 0;
*fyy = 0;
return 0;
}
}
int PathFinding::findPath(int32 x, int32 y, int32 destx, int32 desty) {
debugC(1, kDebugPath, "findPath(%d, %d, %d, %d)", x, y, destx, desty);
if (x == destx && y == desty) {
_gridPathCount = 0;
return true;
}
memset(_gridTemp , 0, _width * _height * sizeof(int32));
_heap->clear();
int32 curX = x;
int32 curY = y;
int32 curWeight = 0;
int32 *sq = _gridTemp;
sq[curX + curY *_width] = 1;
_heap->push(curX, curY, abs(destx - x) + abs(desty - y));
int wei = 0;
// Strangerke - Commented (not used)
// byte *mask = _currentMask->getDataPtr();
while (_heap->_count) {
wei = 0;
_heap->pop(&curX, &curY, &curWeight);
int curNode = curX + curY * _width;
int32 endX = MIN(curX + 1, _width - 1);
int32 endY = MIN(curY + 1, _height - 1);
int32 startX = MAX(curX - 1, 0);
int32 startY = MAX(curY - 1, 0);
for (int32 px = startX; px <= endX; px++) {
for (int py = startY; py <= endY; py++) {
if (px != curX || py != curY) {
wei = abs(px - curX) + abs(py - curY);
int32 curPNode = px + py * _width;
if (isWalkable(px, py)) { // walkable ?
int sum = sq[curNode] + wei;
if (sq[curPNode] > sum || !sq[curPNode]) {
int newWeight = abs(destx - px) + abs(desty - py);
sq[curPNode] = sum;
_heap->push(px, py, sq[curPNode] + newWeight);
if (!newWeight)
goto next; // we found it !
}
}
}
}
}
}
next:
// let's see if we found a result !
if (!_gridTemp[destx + desty * _width]) {
// didn't find anything
_gridPathCount = 0;
return false;
}
curX = destx;
curY = desty;
int32 retPathX[4096];
int32 retPathY[4096];
int32 numpath = 0;
retPathX[numpath] = curX;
retPathY[numpath] = curY;
numpath++;
int32 bestscore = sq[destx + desty * _width];
while (1) {
int32 bestX = -1;
int32 bestY = -1;
int32 endX = MIN(curX + 1, _width - 1);
int32 endY = MIN(curY + 1, _height - 1);
int32 startX = MAX(curX - 1, 0);
int32 startY = MAX(curY - 1, 0);
for (int32 px = startX; px <= endX; px++) {
for (int32 py = startY; py <= endY; py++) {
if (px != curX || py != curY) {
wei = abs(px - curX) + abs(py - curY);
int PNode = px + py * _width;
if (sq[PNode] && (isWalkable(px, py))) {
if (sq[PNode] < bestscore) {
bestscore = sq[PNode];
bestX = px;
bestY = py;
}
}
}
}
}
if (bestX < 0 || bestY < 0)
return 0;
retPathX[numpath] = bestX;
retPathY[numpath] = bestY;
numpath++;
if ((bestX == x && bestY == y)) {
_gridPathCount = numpath;
memcpy(_tempPathX, retPathX, sizeof(int32) * numpath);
memcpy(_tempPathY, retPathY, sizeof(int32) * numpath);
return true;
}
curX = bestX;
curY = bestY;
}
return false;
}
void PathFinding::init(Picture *mask) {
debugC(1, kDebugPath, "init(mask)");
_width = mask->getWidth();
_height = mask->getHeight();
_currentMask = mask;
_heap->unload();
_heap->init(_width * _height);
if (_gridTemp)
delete[] _gridTemp;
_gridTemp = new int32[_width*_height];
}
void PathFinding::resetBlockingRects() {
_numBlockingRects = 0;
}
void PathFinding::addBlockingRect(int32 x1, int32 y1, int32 x2, int32 y2) {
debugC(1, kDebugPath, "addBlockingRect(%d, %d, %d, %d)", x1, y1, x2, y2);
_blockingRects[_numBlockingRects][0] = x1;
_blockingRects[_numBlockingRects][1] = y1;
_blockingRects[_numBlockingRects][2] = x2;
_blockingRects[_numBlockingRects][3] = y2;
_blockingRects[_numBlockingRects][4] = 0;
_numBlockingRects++;
}
void PathFinding::addBlockingEllipse(int32 x1, int32 y1, int32 w, int32 h) {
debugC(1, kDebugPath, "addBlockingRect(%d, %d, %d, %d)", x1, y1, w, h);
_blockingRects[_numBlockingRects][0] = x1;
_blockingRects[_numBlockingRects][1] = y1;
_blockingRects[_numBlockingRects][2] = w;
_blockingRects[_numBlockingRects][3] = h;
_blockingRects[_numBlockingRects][4] = 1;
_numBlockingRects++;
}
int32 PathFinding::getPathNodeCount() const {
return _gridPathCount;
}
int32 PathFinding::getPathNodeX(int32 nodeId) const {
return _tempPathX[ _gridPathCount - nodeId - 1];
}
int32 PathFinding::getPathNodeY(int32 nodeId) const {
return _tempPathY[ _gridPathCount - nodeId - 1];
}
} // End of namespace Toon

93
engines/toon/path.h Normal file
View file

@ -0,0 +1,93 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#ifndef TOON_PATH_H
#define TOON_PATH_H
#include "toon.h"
namespace Toon {
// binary heap system for fast A*
struct HeapDataGrid {
int16 _x, _y;
int16 _weight;
};
class PathFindingHeap {
private:
HeapDataGrid *_data;
public:
int32 _alloc;
int32 _count;
int32 push(int32 x, int32 y, int32 weight);
int32 pop(int32 *x, int32 *y, int32 *weight);
int32 init(int32 size);
int32 clear();
int32 unload();
};
class PathFinding {
public:
PathFinding(ToonEngine *vm);
~PathFinding(void);
int32 findPath(int32 x, int32 y, int32 destX, int32 destY);
int32 findClosestWalkingPoint(int32 xx, int32 yy, int32 *fxx, int32 *fyy, int origX = -1, int origY = -1);
bool isWalkable(int32 x, int32 y);
void init(Picture *mask);
void resetBlockingRects();
void addBlockingRect(int32 x1, int32 y1, int32 x2, int32 y2);
void addBlockingEllipse(int32 x1, int32 y1, int32 w, int32 h);
int32 getPathNodeCount() const;
int32 getPathNodeX(int32 nodeId) const;
int32 getPathNodeY(int32 nodeId) const;
protected:
Picture *_currentMask;
PathFindingHeap *_heap;
int32 *_gridTemp;
int32 _width;
int32 _height;
int32 _tempPathX[4096];
int32 _tempPathY[4096];
int32 _blockingRects[16][5];
int32 _numBlockingRects;
int32 _allocatedGridPathCount;
int32 _gridPathCount;
ToonEngine *_vm;
};
} // End of namespace Toon
#endif

300
engines/toon/picture.cpp Normal file
View file

@ -0,0 +1,300 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#include "picture.h"
#include "tools.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)
return false;
_useFullPalette = totalPalette;
uint32 compId = READ_BE_UINT32(fileData);
switch (compId) {
case kCompLZSS: {
uint32 dstsize = READ_LE_UINT32(fileData + 4);
_data = new uint8[dstsize];
decompressLZSS(fileData + 8, _data, dstsize);
// size can only be 640x400 or 1280x400
if (dstsize > 640 * 400 + 768)
_width = 1280;
else
_width = 640;
_height = 400;
// do we have a palette ?
_paletteEntries = (dstsize & 0x7ff) / 3;
if (_paletteEntries) {
_palette = new uint8[_paletteEntries * 3];
memcpy(_palette, _data + dstsize - (dstsize & 0x7ff), _paletteEntries * 3);
_vm->fixPaletteEntries(_palette, _paletteEntries);
} else {
_palette = 0;
}
return true;
break;
}
case kCompSPCN: {
uint32 decSize = READ_LE_UINT32(fileData + 10);
_data = new uint8[decSize+100];
_paletteEntries = READ_LE_UINT16(fileData + 14) / 3;
if (_paletteEntries) {
_palette = new uint8[_paletteEntries * 3];
memcpy(_palette, fileData + 16, _paletteEntries * 3);
_vm->fixPaletteEntries(_palette, _paletteEntries);
}
// size can only be 640x400 or 1280x400
if (decSize > 640 * 400 + 768)
_width = 1280;
else
_width = 640;
_height = 400;
// decompress the picture into our buffer
decompressSPCN(fileData + 16 + _paletteEntries * 3, _data, decSize);
return true;
break;
}
case kCompRNC1: {
Toon::RncDecoder rnc;
// allocate enough place
uint32 decSize = READ_BE_UINT32(fileData + 4);
_data = new uint8[decSize];
rnc.unpackM1(fileData, _data);
// size can only be 640x400 or 1280x400
if (decSize > 640 * 400 + 768)
_width = 1280;
else
_width = 640;
_height = 400;
return true;
break;
}
case kCompRNC2: {
Toon::RncDecoder rnc;
// allocate enough place
uint32 decSize = READ_BE_UINT32(fileData + 4);
_data = new uint8[decSize];
decSize = rnc.unpackM2(fileData, _data);
if (decSize > 640 * 400 + 768)
_width = 1280;
else
_width = 640;
_height = 400;
return true;
break;
}
}
return false;
}
Picture::Picture(ToonEngine *vm) : _vm(vm) {
}
void Picture::setupPalette() {
debugC(1, kDebugPicture, "setupPalette()");
if (_useFullPalette)
_vm->setPaletteEntries(_palette, 0, 255);
else
_vm->setPaletteEntries(_palette, 1, 128);
}
void Picture::drawMask(Graphics::Surface &surface, int32 x, int32 y, int32 dx, int32 dy) {
debugC(1, kDebugPicture, "drawMask(surface, %d, %d, %d, %d)", x, y, dx, dy);
for (int32 i = 0; i < 128; i++) {
byte color[3];
color[0] = i * 2;
color[1] = i * 2;
color[2] = 255 - i * 2;
_vm->setPaletteEntries(color, i, 1);
}
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;
uint8 *c = _data + _width * dy + dx ;
uint8 *curRow = (uint8 *)surface.pixels + y * destPitch + x;
for (int32 yy = 0; yy < ry; yy++) {
uint8 *curSrc = c;
uint8 *cur = curRow;
for (int32 xx = 0; xx < rx; xx++) {
//*cur = (*curSrc >> 5) * 8; // & 0x1f;
*cur = (*curSrc & 0x1f) ? 127 : 0;
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);
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;
uint8 *c = _data + _width * dy + dx ;
uint8 *curRow = (uint8 *)surface.pixels + y * destPitch + x;
for (int32 yy = 0; yy < ry; yy++) {
uint8 *curSrc = c;
uint8 *cur = curRow;
for (int32 xx = 0; xx < rx; xx++) {
*cur = *curSrc ;
curSrc++;
cur++;
}
curRow += destPitch;
c += srcPitch;
}
}
uint8 Picture::getData(int32 x, int32 y) {
debugC(6, kDebugPicture, "getData(%d, %d)", x, y);
if (!_data)
return 0;
return _data[y * _width + x];
}
// use original work from johndoe
void Picture::floodFillNotWalkableOnMask( int32 x, int32 y ) {
debugC(1, kDebugPicture, "floodFillNotWalkableOnMask(%d, %d)", x, y);
// Stack-based floodFill algorithm based on
// http://student.kuleuven.be/~m0216922/CG/files/floodfill.cpp
Common::Stack<Common::Point> stack;
bool spanLeft, spanRight;
stack.push(Common::Point(x, y));
while (!stack.empty()) {
Common::Point pt = stack.pop();
while (_data[pt.x + pt.y * _width] & 0x1F && pt.y >= 0)
pt.y--;
pt.y++;
spanLeft = false;
spanRight = false;
while (_data[pt.x + pt.y * _width] & 0x1F && pt.y < _height) {
_data[pt.x + pt.y * _width] &= 0xE0;
if (!spanLeft && pt.x > 0 && _data[pt.x - 1 + pt.y * _width] & 0x1F) {
stack.push(Common::Point(pt.x - 1, pt.y));
spanLeft = 1;
} else if (spanLeft && pt.x > 0 && !(_data[pt.x - 1 + pt.y * _width] & 0x1F)) {
spanLeft = 0;
}
if (!spanRight && pt.x < _width - 1 && _data[pt.x + 1 + pt.y * _width] & 0x1F) {
stack.push(Common::Point(pt.x + 1, pt.y));
spanRight = 1;
} else if (spanRight && pt.x < _width - 1 && !(_data[pt.x + 1 + pt.y * _width] & 0x1F)) {
spanRight = 0;
}
pt.y++;
}
}
}
void Picture::drawLineOnMask( int32 x, int32 y, int32 x2, int32 y2, bool walkable ) {
debugC(1, kDebugPicture, "drawLineOnMask(%d, %d, %d, %d, %d)", x, y, x2, y2, (walkable) ? 1 : 0);
static int32 lastX = 0;
static int32 lastY = 0;
if (x == -1) {
x = lastX;
y = lastY;
}
uint32 bx = x << 16;
int32 dx = x2 - x;
uint32 by = y << 16;
int32 dy = y2 - y;
uint32 adx = abs(dx);
uint32 ady = abs(dy);
int32 t = 0;
if (adx <= ady)
t = ady;
else
t = adx;
int32 cdx = (dx << 16) / t;
int32 cdy = (dy << 16) / t;
int32 i = t;
while (i) {
if (!walkable) {
_data[_width * (by >> 16) + (bx >> 16)] &= 0xe0;
_data[_width * (by >> 16) + (bx >> 16)+1] &= 0xe0;
} else {
int32 v = _data[_width * (by >> 16) + (bx >> 16) - 1];
_data[_width * (by >> 16) + (bx >> 16)] = v;
_data[_width * (by >> 16) + (bx >> 16)+1] = v;
}
bx += cdx;
by += cdy;
i--;
}
}
} // End of namespace Toon

66
engines/toon/picture.h Normal file
View file

@ -0,0 +1,66 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#ifndef PICTURE_H
#define PICTURE_H
#include "common/stream.h"
#include "common/array.h"
#include "common/func.h"
#include "common/str.h"
#include "toon.h"
namespace Toon {
class ToonEngine;
class Picture {
public:
Picture(ToonEngine *vm);
bool loadPicture(Common::String file, bool totalPalette = false);
void setupPalette();
void draw(Graphics::Surface &surface, int32 x, int32 y, int32 dx, int32 dy);
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 );
uint8 getData(int32 x, int32 y);
uint8 *getDataPtr() { return _data; }
int32 getWidth() const { return _width; }
int32 getHeight() const { return _height; }
protected:
int32 _width;
int32 _height;
uint8 *_data;
uint8 *_palette; // need to be copied at 3-387
int32 _paletteEntries;
bool _useFullPalette;
ToonEngine *_vm;
};
} // End of namespace Toon
#endif

215
engines/toon/resource.cpp Normal file
View file

@ -0,0 +1,215 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#include "resource.h"
#include "common/file.h"
#include "toon.h"
namespace Toon {
void Resources::openPackage(Common::String fileName, bool preloadEntirePackage) {
debugC(1, kDebugResource, "openPackage(%s, %d)", fileName.c_str(), (preloadEntirePackage) ? 1 : 0);
Common::File file;
bool opened = file.open(fileName);
if (!opened)
return;
PakFile *pakFile = new PakFile();
pakFile->open(&file, fileName, preloadEntirePackage);
if (preloadEntirePackage)
file.close();
_pakFiles.push_back(pakFile);
}
void Resources::closePackage(Common::String fileName) {
for (uint32 i = 0; i < _pakFiles.size(); i++) {
if (_pakFiles[i]->getPackName() == fileName) {
delete _pakFiles[i];
_pakFiles.remove_at(i);
return;
}
}
}
Resources::Resources(ToonEngine *vm) : _vm(vm) {
}
uint8 *Resources::getFileData(Common::String fileName, uint32 *fileSize) {
debugC(4, kDebugResource, "getFileData(%s, fileSize)", fileName.c_str());
// first try to find files outside of .pak
// some patched files have not been included in package.
if (Common::File::exists(fileName)) {
Common::File file;
bool opened = file.open(fileName);
if (!opened)
return 0;
*fileSize = file.size();
uint8 *memory = (uint8 *)new uint8[*fileSize];
file.read(memory, *fileSize);
file.close();
return memory;
} else {
for (uint32 i = 0; i < _pakFiles.size(); i++) {
uint32 locFileSize = 0;
uint8 *locFileData = 0;
locFileData = _pakFiles[i]->getFileData(fileName, &locFileSize);
if (locFileData) {
*fileSize = locFileSize;
return locFileData;
}
}
return 0;
}
}
Common::SeekableReadStream *Resources::openFile(Common::String fileName) {
debugC(1, kDebugResource, "openFile(%s)", fileName.c_str());
// first try to find files outside of .pak
// some patched files have not been included in package.
if (Common::File::exists(fileName)) {
Common::File *file = new Common::File();
bool opened = file->open(fileName);
if (!opened) {
delete file;
return 0;
}
return file;
} else {
for (uint32 i = 0; i < _pakFiles.size(); i++) {
Common::SeekableReadStream *stream = 0;
stream = _pakFiles[i]->createReadStream(fileName);
if (stream)
return stream;
}
return 0;
}
}
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);
else
return new Common::MemoryReadStream(_buffer + offset, size);
}
uint8 *PakFile::getFileData(Common::String fileName, uint32 *fileSize) {
debugC(4, kDebugResource, "getFileData(%s, fileSize)", fileName.c_str());
for (uint32 i = 0; i < _numFiles; i++) {
if (fileName.compareToIgnoreCase(_files[i]._name) == 0) {
*fileSize = _files[i]._size;
return _buffer + _files[i]._offset;
}
}
return 0;
}
void PakFile::open(Common::SeekableReadStream *rs, Common::String packName, bool preloadEntirePackage) {
debugC(1, kDebugResource, "open(rs, %d)", (preloadEntirePackage) ? 1 : 0);
char buffer[64];
int32 currentPos = 0;
_numFiles = 0;
_packName = packName;
while (1) {
rs->seek(currentPos);
rs->read(buffer, 64);
int32 offset = READ_LE_UINT32(buffer);
char *name = buffer + 4;
if (!*name)
break;
int32 nameSize = strlen(name) + 1;
int32 nextOffset = READ_LE_UINT32(buffer + 4 + nameSize);
currentPos += 4 + nameSize;
PakFile::File newFile;
strcpy(newFile._name, name);
newFile._offset = offset;
newFile._size = nextOffset - offset;
_numFiles++;
_files.push_back(newFile);
}
if (preloadEntirePackage) {
_bufferSize = rs->size();
_buffer = new uint8[_bufferSize];
rs->seek(0);
rs->read(_buffer, _bufferSize);
}
}
void PakFile::close() {
if (_buffer) {
delete[] _buffer;
}
if (_fileHandle) {
_fileHandle->close();
delete _fileHandle;
}
}
PakFile::~PakFile() {
close();
}
PakFile::PakFile() {
_fileHandle = 0;
_buffer = 0;
_bufferSize = 0;
}
} // End of namespace Toon

82
engines/toon/resource.h Normal file
View file

@ -0,0 +1,82 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#ifndef TOON_RESOURCE_H
#define TOON_RESOURCE_H
#include "common/array.h"
#include "common/str.h"
#include "common/file.h"
#include "common/stream.h"
namespace Toon {
class PakFile {
public:
PakFile();
~PakFile();
void open(Common::SeekableReadStream *rs, Common::String packName, bool preloadEntirePackage);
uint8 *getFileData(Common::String fileName, uint32 *fileSize);
Common::String getPackName() { return _packName; };
Common::SeekableReadStream *createReadStream(Common::String fileName);
void close();
protected:
struct File {
char _name[13];
int32 _offset;
int32 _size;
};
Common::String _packName;
uint8 *_buffer;
int32 _bufferSize;
uint32 _numFiles;
Common::Array<File> _files;
Common::File *_fileHandle;
};
class ToonEngine;
class Resources {
public:
Resources(ToonEngine *vm);
void openPackage(Common::String file, bool preloadEntirePackage);
void closePackage(Common::String fileName);
Common::SeekableReadStream *openFile(Common::String file);
uint8 *getFileData(Common::String fileName, uint32 *fileSize);
protected:
ToonEngine *_vm;
Common::Array<PakFile *> _pakFiles;
};
} // End of namespace Toon
#endif

506
engines/toon/script.cpp Normal file
View file

@ -0,0 +1,506 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#include "common/endian.h"
#include "common/stream.h"
#include "common/util.h"
#include "common/system.h"
#include "toon.h"
#include "script.h"
namespace Toon {
EMCInterpreter::EMCInterpreter(ToonEngine *vm) : _vm(vm), _scriptData(0), _filename(0) {
#define OPCODE(x) { &EMCInterpreter::x, #x }
static const OpcodeEntry opcodes[] = {
// 0x00
OPCODE(op_jmp),
OPCODE(op_setRetValue),
OPCODE(op_pushRetOrPos),
OPCODE(op_push),
// 0x04
OPCODE(op_push),
OPCODE(op_pushReg),
OPCODE(op_pushBPNeg),
OPCODE(op_pushBPAdd),
// 0x08
OPCODE(op_popRetOrPos),
OPCODE(op_popReg),
OPCODE(op_popBPNeg),
OPCODE(op_popBPAdd),
// 0x0C
OPCODE(op_addSP),
OPCODE(op_subSP),
OPCODE(op_sysCall),
OPCODE(op_ifNotJmp),
// 0x10
OPCODE(op_negate),
OPCODE(op_eval),
OPCODE(op_setRetAndJmp)
};
_opcodes = opcodes;
#undef OPCODE
}
bool EMCInterpreter::callback(Common::IFFChunk &chunk) {
switch (chunk._type) {
case MKID_BE('TEXT'):
_scriptData->text = new byte[chunk._size];
assert(_scriptData->text);
if (chunk._stream->read(_scriptData->text, chunk._size) != chunk._size)
error("Couldn't read TEXT chunk from file '%s'", _filename);
break;
case MKID_BE('ORDR'):
_scriptData->ordr = new uint16[chunk._size >> 1];
assert(_scriptData->ordr);
if (chunk._stream->read(_scriptData->ordr, chunk._size) != chunk._size)
error("Couldn't read ORDR chunk from file '%s'", _filename);
for (int i = (chunk._size >> 1) - 1; i >= 0; --i)
_scriptData->ordr[i] = READ_BE_UINT16(&_scriptData->ordr[i]);
break;
case MKID_BE('DATA'):
_scriptData->data = new uint16[chunk._size >> 1];
assert(_scriptData->data);
if (chunk._stream->read(_scriptData->data, chunk._size) != chunk._size)
error("Couldn't read DATA chunk from file '%s'", _filename);
for (int i = (chunk._size >> 1) - 1; i >= 0; --i)
_scriptData->data[i] = READ_BE_UINT16(&_scriptData->data[i]);
break;
default:
warning("Unexpected chunk '%s' of size %d found in file '%s'", Common::tag2string(chunk._type).c_str(), chunk._size, _filename);
}
return false;
}
bool EMCInterpreter::load(const char *filename, EMCData *scriptData, const Common::Array<const Opcode *> *opcodes) {
Common::SeekableReadStream *stream = _vm->resources()->openFile(filename);
if (!stream) {
error("Couldn't open script file '%s'", filename);
return false; // for compilers that don't support NORETURN
}
memset(scriptData, 0, sizeof(EMCData));
_scriptData = scriptData;
_filename = filename;
IFFParser iff(*stream);
Common::Functor1Mem< Common::IFFChunk &, bool, EMCInterpreter > c(this, &EMCInterpreter::callback);
iff.parse(c);
if (!_scriptData->ordr)
error("No ORDR chunk found in file: '%s'", filename);
if (!_scriptData->data)
error("No DATA chunk found in file: '%s'", filename);
if (stream->err())
error("Read error while parsing file '%s'", filename);
delete stream;
_scriptData->sysFuncs = opcodes;
strncpy(_scriptData->filename, filename, 13);
_scriptData->filename[12] = 0;
_scriptData = 0;
_filename = 0;
return true;
}
void EMCInterpreter::unload(EMCData *data) {
if (!data)
return;
delete[] data->text;
delete[] data->ordr;
delete[] data->data;
data->text = 0;
data->ordr = data->data = 0;
}
void EMCInterpreter::init(EMCState *scriptStat, const EMCData *data) {
scriptStat->dataPtr = data;
scriptStat->ip = 0;
scriptStat->stack[EMCState::kStackLastEntry] = 0;
scriptStat->bp = EMCState::kStackSize + 1;
scriptStat->sp = EMCState::kStackLastEntry;
scriptStat->running = false;
}
bool EMCInterpreter::start(EMCState *script, int function) {
if (!script->dataPtr)
return false;
uint16 functionOffset = script->dataPtr->ordr[function];
if (functionOffset == 0xFFFF)
return false;
script->ip = &script->dataPtr->data[functionOffset+1];
return true;
}
bool EMCInterpreter::isValid(EMCState *script) {
if (!script->ip || !script->dataPtr || _vm->shouldQuit())
return false;
return true;
}
bool EMCInterpreter::run(EMCState *script) {
if (script->running)
return false;
_parameter = 0;
if (!script->ip)
return false;
script->running = true;
// Should be no Problem at all to cast to uint32 here, since that's the biggest ptrdiff the original
// would allow, of course that's not realistic to happen to be somewhere near the limit of uint32 anyway.
const uint32 instOffset = (uint32)((const byte *)script->ip - (const byte *)script->dataPtr->data);
int16 code = *script->ip++;
int16 opcode = (code >> 8) & 0x1F;
if (code & 0x8000) {
opcode = 0;
_parameter = code & 0x7FFF;
} else if (code & 0x4000) {
_parameter = (int8)(code);
} else if (code & 0x2000) {
_parameter = *script->ip++;
} else {
_parameter = 0;
}
if (opcode > 18) {
error("Unknown script opcode: %d in file '%s' at offset 0x%.08X", opcode, script->dataPtr->filename, instOffset);
} else {
static bool EMCDebug = false;
if (EMCDebug )
debugC(5, 0, "[0x%.08X] EMCInterpreter::%s([%d/%u])", instOffset*2, _opcodes[opcode].desc, _parameter, (uint)_parameter);
//debug(0, "[0x%.08X] EMCInterpreter::%s([%d/%u])", instOffset, _opcodes[opcode].desc, _parameter, (uint)_parameter);
(this->*(_opcodes[opcode].proc))(script);
}
script->running = false;
return (script->ip != 0);
}
#pragma mark -
#pragma mark - Command implementations
#pragma mark -
void EMCInterpreter::op_jmp(EMCState *script) {
script->ip = script->dataPtr->data + _parameter;
}
void EMCInterpreter::op_setRetValue(EMCState *script) {
script->retValue = _parameter;
}
void EMCInterpreter::op_pushRetOrPos(EMCState *script) {
switch (_parameter) {
case 0:
script->stack[--script->sp] = script->retValue;
break;
case 1:
script->stack[--script->sp] = script->ip - script->dataPtr->data + 1;
script->stack[--script->sp] = script->bp;
script->bp = script->sp + 2;
break;
default:
script->ip = 0;
}
}
void EMCInterpreter::op_push(EMCState *script) {
script->stack[--script->sp] = _parameter;
}
void EMCInterpreter::op_pushReg(EMCState *script) {
script->stack[--script->sp] = script->regs[_parameter];
}
void EMCInterpreter::op_pushBPNeg(EMCState *script) {
script->stack[--script->sp] = script->stack[(-(int32)(_parameter + 2)) + script->bp];
}
void EMCInterpreter::op_pushBPAdd(EMCState *script) {
script->stack[--script->sp] = script->stack[(_parameter - 1) + script->bp];
}
void EMCInterpreter::op_popRetOrPos(EMCState *script) {
switch (_parameter) {
case 0:
script->retValue = script->stack[script->sp++];
break;
case 1:
if (script->sp >= EMCState::kStackLastEntry) {
script->ip = 0;
} else {
script->bp = script->stack[script->sp++];
script->ip = script->dataPtr->data + script->stack[script->sp++];
}
break;
default:
script->ip = 0;
}
}
void EMCInterpreter::op_popReg(EMCState *script) {
script->regs[_parameter] = script->stack[script->sp++];
}
void EMCInterpreter::op_popBPNeg(EMCState *script) {
script->stack[(-(int32)(_parameter + 2)) + script->bp] = script->stack[script->sp++];
}
void EMCInterpreter::op_popBPAdd(EMCState *script) {
script->stack[(_parameter - 1) + script->bp] = script->stack[script->sp++];
}
void EMCInterpreter::op_addSP(EMCState *script) {
script->sp += _parameter;
}
void EMCInterpreter::op_subSP(EMCState *script) {
script->sp -= _parameter;
}
void EMCInterpreter::op_sysCall(EMCState *script) {
const uint8 id = _parameter;
assert(script->dataPtr->sysFuncs);
assert(id < script->dataPtr->sysFuncs->size());
if ((*script->dataPtr->sysFuncs)[id] && ((*script->dataPtr->sysFuncs)[id])->isValid()) {
script->retValue = (*(*script->dataPtr->sysFuncs)[id])(script);
} else {
script->retValue = 0;
warning("Unimplemented system call 0x%.02X/%d used in file '%s'", id, id, script->dataPtr->filename);
}
}
void EMCInterpreter::op_ifNotJmp(EMCState *script) {
if (!script->stack[script->sp++]) {
_parameter &= 0x7FFF;
script->ip = script->dataPtr->data + _parameter;
}
}
void EMCInterpreter::op_negate(EMCState *script) {
int16 value = script->stack[script->sp];
switch (_parameter) {
case 0:
if (!value)
script->stack[script->sp] = 1;
else
script->stack[script->sp] = 0;
break;
case 1:
script->stack[script->sp] = -value;
break;
case 2:
script->stack[script->sp] = ~value;
break;
default:
warning("Unknown negation func: %d", _parameter);
script->ip = 0;
}
}
void EMCInterpreter::op_eval(EMCState *script) {
int16 ret = 0;
bool error = false;
int16 val1 = script->stack[script->sp++];
int16 val2 = script->stack[script->sp++];
switch (_parameter) {
case 0:
ret = (val2 && val1) ? 1 : 0;
break;
case 1:
ret = (val2 || val1) ? 1 : 0;
break;
case 2:
ret = (val1 == val2) ? 1 : 0;
break;
case 3:
ret = (val1 != val2) ? 1 : 0;
break;
case 4:
ret = (val1 > val2) ? 1 : 0;
break;
case 5:
ret = (val1 >= val2) ? 1 : 0;
break;
case 6:
ret = (val1 < val2) ? 1 : 0;
break;
case 7:
ret = (val1 <= val2) ? 1 : 0;
break;
case 8:
ret = val1 + val2;
break;
case 9:
ret = val2 - val1;
break;
case 10:
ret = val1 * val2;
break;
case 11:
ret = val2 / val1;
break;
case 12:
ret = val2 >> val1;
break;
case 13:
ret = val2 << val1;
break;
case 14:
ret = val1 & val2;
break;
case 15:
ret = val1 | val2;
break;
case 16:
ret = val2 % val1;
break;
case 17:
ret = val1 ^ val2;
break;
default:
warning("Unknown evaluate func: %d", _parameter);
error = true;
}
if (error)
script->ip = 0;
else
script->stack[--script->sp] = ret;
}
void EMCInterpreter::op_setRetAndJmp(EMCState *script) {
if (script->sp >= EMCState::kStackLastEntry) {
script->ip = 0;
} else {
script->retValue = script->stack[script->sp++];
uint16 temp = script->stack[script->sp++];
script->stack[EMCState::kStackLastEntry] = 0;
script->ip = &script->dataPtr->data[temp];
}
}
void EMCInterpreter::saveState(EMCState* script, Common::WriteStream * stream) {
stream->writeSint16LE(script->bp);
stream->writeSint16LE(script->sp);
if (!script->ip) {
stream->writeSint16LE(-1);
}
else {
stream->writeSint16LE(script->ip - script->dataPtr->data);
}
for (int32 i = 0; i < EMCState::kStackSize; i++) {
stream->writeSint16LE(script->stack[i]);
}
for (int32 i = 0; i < 30; i++) {
stream->writeSint16LE(script->regs[i]);
}
stream->writeSint16LE(script->retValue);
stream->writeByte(script->running);
}
void EMCInterpreter::loadState(EMCState* script, Common::ReadStream* stream) {
script->bp = stream->readSint16LE();
script->sp = stream->readSint16LE();
int16 scriptIp = stream->readSint16LE();
if(scriptIp == -1) {
script->ip = 0;
}
else {
script->ip = scriptIp + script->dataPtr->data;
}
for (int32 i = 0; i < EMCState::kStackSize; i++) {
script->stack[i] = stream->readSint16LE();
}
for (int32 i = 0; i < 30; i++) {
script->regs[i] = stream->readSint16LE();
}
script->retValue = stream->readSint16LE();
script->running = stream->readByte();
}
} // End of namespace Toon

152
engines/toon/script.h Normal file
View file

@ -0,0 +1,152 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#ifndef TOON_SCRIPT_H
#define TOON_SCRIPT_H
#include "common/stream.h"
#include "common/array.h"
#include "common/func.h"
#include "common/iff_container.h"
// Based on Kyra script interpretor
namespace Toon {
struct EMCState;
typedef Common::Functor1<EMCState *, int> Opcode;
struct EMCData {
char filename[13];
byte *text;
uint16 *data;
uint16 *ordr;
uint16 dataSize;
const Common::Array<const Opcode *> *sysFuncs;
};
struct EMCState {
enum {
kStackSize = 100,
kStackLastEntry = kStackSize - 1
};
const uint16 *ip;
const EMCData *dataPtr;
int16 retValue;
uint16 bp;
uint16 sp;
int16 regs[30]; // VM registers
int16 stack[kStackSize]; // VM stack
bool running;
};
#define stackPos(x) (state->stack[state->sp+x])
#define stackPosString(x) ((const char *)&state->dataPtr->text[READ_BE_UINT16(&state->dataPtr->text[stackPos(x)<<1])])
class Resource;
class ToonEngine;
class IFFParser : public Common::IFFParser {
public:
IFFParser(Common::ReadStream &input) : Common::IFFParser(&input) {
// It seems Westwood missunderstood the 'size' field of the FORM chunk.
//
// For EMC scripts (type EMC2) it's filesize instead of filesize - 8,
// means accidently including the 8 bytes used by the chunk header for the FORM
// chunk.
//
// For TIM scripts (type AVFS) it's filesize - 12 instead of filesize - 8,
// means it will not include the size of the 'type' field in the FORM chunk,
// instead of only not including the chunk header size.
//
// 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'))
_formChunk.size -= 8;
else if (_formType == MKID_BE('AVFS'))
_formChunk.size += 4;
}
};
class EMCInterpreter {
public:
EMCInterpreter(ToonEngine *vm);
bool load(const char *filename, EMCData *data, const Common::Array<const Opcode *> *opcodes);
void unload(EMCData *data);
void init(EMCState *scriptState, const EMCData *data);
bool start(EMCState *script, int function);
void saveState(EMCState* script, Common::WriteStream * stream);
void loadState(EMCState* script, Common::ReadStream* stream);
bool isValid(EMCState *script);
bool run(EMCState *script);
protected:
ToonEngine *_vm;
int16 _parameter;
const char *_filename;
EMCData *_scriptData;
bool callback(Common::IFFChunk &chunk);
typedef void (EMCInterpreter::*OpcodeProc)(EMCState *);
struct OpcodeEntry {
OpcodeProc proc;
const char *desc;
};
const OpcodeEntry *_opcodes;
private:
void op_jmp(EMCState *);
void op_setRetValue(EMCState *);
void op_pushRetOrPos(EMCState *);
void op_push(EMCState *);
void op_pushReg(EMCState *);
void op_pushBPNeg(EMCState *);
void op_pushBPAdd(EMCState *);
void op_popRetOrPos(EMCState *);
void op_popReg(EMCState *);
void op_popBPNeg(EMCState *);
void op_popBPAdd(EMCState *);
void op_addSP(EMCState *);
void op_subSP(EMCState *);
void op_sysCall(EMCState *);
void op_ifNotJmp(EMCState *);
void op_negate(EMCState *);
void op_eval(EMCState *);
void op_setRetAndJmp(EMCState *);
};
} // End of namespace Toon
#endif

1153
engines/toon/script_func.cpp Normal file

File diff suppressed because it is too large Load diff

171
engines/toon/script_func.h Normal file
View file

@ -0,0 +1,171 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#ifndef SCRIPT_FUNC_H
#define SCRIPT_FUNC_H
#include "common/array.h"
#include "script.h"
namespace Toon {
class ScriptFunc {
public:
ScriptFunc(ToonEngine *vm);
~ScriptFunc(void);
Common::Array<const Opcode *> _opcodes;
ToonEngine *_vm;
#define SYSFUNC(x) int32 x(EMCState*)
SYSFUNC(sys_Cmd_Dummy);
SYSFUNC(sys_Cmd_Change_Actor_X_And_Y);
SYSFUNC(sys_Cmd_Init_Talking_Character);
SYSFUNC(sys_Cmd_Draw_Actor_Standing);
SYSFUNC(sys_Cmd_Get_Actor_X);
SYSFUNC(sys_Cmd_Get_Actor_Y);
SYSFUNC(sys_Cmd_Get_Actor_Facing);
SYSFUNC(sys_Cmd_Get_Last_Scene);
SYSFUNC(sys_Cmd_Debug_Print);
SYSFUNC(sys_Cmd_Flip_Screens);
SYSFUNC(sys_Cmd_Play_Flic);
SYSFUNC(sys_Cmd_Force_Facing);
SYSFUNC(sys_Cmd_Restart_Thread);
SYSFUNC(sys_Cmd_Walk_Actor_To_Point);
SYSFUNC(sys_Cmd_Set_Sack_Visible);
SYSFUNC(sys_Cmd_Set_Actor_Facing);
SYSFUNC(sys_Cmd_Confiscate_Inventory);
SYSFUNC(sys_Cmd_Character_Talks);
SYSFUNC(sys_Cmd_Visited_Scene);
SYSFUNC(sys_Cmd_Query_Rif_Flag);
SYSFUNC(sys_Cmd_Query_Scroll);
SYSFUNC(sys_Cmd_Set_Initial_Location);
SYSFUNC(sys_Cmd_Make_Line_Non_Walkable);
SYSFUNC(sys_Cmd_Make_Line_Walkable);
SYSFUNC(sys_Cmd_Walk_Actor_On_Condition);
SYSFUNC(sys_Cmd_Set_Actor_Facing_Point);
SYSFUNC(sys_Cmd_Set_Inventory_Slot);
SYSFUNC(sys_Cmd_Get_Inventory_Slot);
SYSFUNC(sys_Cmd_Add_Item_To_Inventory);
SYSFUNC(sys_Cmd_Set_Actor_RGB_Modifiers);
SYSFUNC(sys_Cmd_Init_Conversation_AP);
SYSFUNC(sys_Cmd_Actor_Talks);
SYSFUNC(sys_Cmd_Say_Lines);
SYSFUNC(sys_Cmd_Set_Rif_Flag);
SYSFUNC(sys_Cmd_Empty_Inventory);
SYSFUNC(sys_Cmd_Set_Anim_Scale_Size);
SYSFUNC(sys_Cmd_Delete_Item_From_Inventory);
SYSFUNC(sys_Cmd_Specific_Item_In_Inventory);
SYSFUNC(sys_Cmd_Run_Script);
SYSFUNC(sys_Cmd_Query_Game_Flag);
SYSFUNC(sys_Cmd_Reset_Game_Flag);
SYSFUNC(sys_Cmd_Set_Game_Flag);
SYSFUNC(sys_Cmd_Create_Mouse_Item);
SYSFUNC(sys_Cmd_Destroy_Mouse_Item);
SYSFUNC(sys_Cmd_Get_Mouse_State);
SYSFUNC(sys_Cmd_Hide_Mouse);
SYSFUNC(sys_Cmd_Exit_Conversation);
SYSFUNC(sys_Cmd_Set_Mouse_Pos);
SYSFUNC(sys_Cmd_Show_Mouse);
SYSFUNC(sys_Cmd_In_Close_Up);
SYSFUNC(sys_Cmd_Set_Scroll_Lock);
SYSFUNC(sys_Cmd_Fill_Area_Non_Walkable);
SYSFUNC(sys_Cmd_Set_Scroll_Coords);
SYSFUNC(sys_Cmd_Hide_Cutaway);
SYSFUNC(sys_Cmd_Show_Cutaway);
SYSFUNC(sys_Cmd_Pause_Ticks);
SYSFUNC(sys_Cmd_In_Conversation);
SYSFUNC(sys_Cmd_Character_Talking);
SYSFUNC(sys_Cmd_Set_Flux_Facing_Point);
SYSFUNC(sys_Cmd_Set_Flux_Facing);
SYSFUNC(sys_Cmd_Set_Flux_Coords);
SYSFUNC(sys_Cmd_Set_Flux_Visible);
SYSFUNC(sys_Cmd_Get_Flux_X);
SYSFUNC(sys_Cmd_Get_Flux_Y);
SYSFUNC(sys_Cmd_Get_Flux_Facing);
SYSFUNC(sys_Cmd_Get_Flux_Flags);
SYSFUNC(sys_Cmd_Query_Flux_Coords);
SYSFUNC(sys_Cmd_Have_A_Conversation);
SYSFUNC(sys_Cmd_Walk_Flux_To_Point);
SYSFUNC(sys_Cmd_Query_Scene_Anim_Loaded);
SYSFUNC(sys_Cmd_Play_Flux_Anim);
SYSFUNC(sys_Cmd_Set_Anim_Priority);
SYSFUNC(sys_Cmd_Place_Scene_Anim);
SYSFUNC(sys_Cmd_Update_Scene_Animations);
SYSFUNC(sys_Cmd_Get_Drew_Scale);
SYSFUNC(sys_Cmd_Query_Drew_Flags);
SYSFUNC(sys_Cmd_Set_Music);
SYSFUNC(sys_Cmd_Query_Speech);
SYSFUNC(sys_Cmd_Enter_New_Scene);
SYSFUNC(sys_Cmd_Enter_Same_Scene);
SYSFUNC(sys_Cmd_Is_Pixel_Walkable);
SYSFUNC(sys_Cmd_Show_Screen);
SYSFUNC(sys_Cmd_Hide_Screen);
SYSFUNC(sys_Cmd_Set_Special_Enter_X_And_Y);
SYSFUNC(sys_Cmd_Get_Mouse_X);
SYSFUNC(sys_Cmd_Get_Mouse_Y);
SYSFUNC(sys_Cmd_Fade_Palette);
SYSFUNC(sys_Cmd_Music_Enabled);
SYSFUNC(sys_Cmd_Random);
SYSFUNC(sys_Cmd_Wait_Key);
SYSFUNC(sys_Cmd_Draw_Scene_Anim_WSA_Frame_To_Back);
SYSFUNC(sys_Cmd_Set_Scene_Anim_Wait);
SYSFUNC(sys_Cmd_Init_Scene_Anim);
SYSFUNC(sys_Cmd_Set_Scene_Animation_Active_Flag);
SYSFUNC(sys_Cmd_Draw_Scene_Anim_WSA_Frame);
SYSFUNC(sys_Cmd_Move_Scene_Anim);
SYSFUNC(sys_Cmd_Run_Actor_Default_Script);
SYSFUNC(sys_Cmd_Set_Location_Data);
SYSFUNC(sys_Cmd_Set_CountDown_Timer);
SYSFUNC(sys_Cmd_Query_CountDown_Timer);
SYSFUNC(sys_Cmd_Proceed_To_Next_Chapter);
SYSFUNC(sys_Cmd_Play_Sfx_Plus);
SYSFUNC(sys_Cmd_Play_Sfx);
SYSFUNC(sys_Cmd_Set_Ambient_Sfx);
SYSFUNC(sys_Cmd_Kill_Ambient_Sfx);
SYSFUNC(sys_Cmd_Set_Ambient_Sfx_Plus);
SYSFUNC(sys_Cmd_Set_Ambient_Volume);
SYSFUNC(sys_Cmd_Freeze_Scene_Animation);
SYSFUNC(sys_Cmd_Unfreeze_Scene_Animation);
SYSFUNC(sys_Cmd_Scene_Animation_Frozen);
SYSFUNC(sys_Cmd_Set_Script_Game_Data_Global);
SYSFUNC(sys_Cmd_Get_Script_Game_Data_Global);
SYSFUNC(sys_Cmd_Say_Line);
SYSFUNC(sys_Cmd_Knight_Puzzle_Get_Coord);
SYSFUNC(sys_Cmd_Add_Scene_Anim);
SYSFUNC(sys_Cmd_Remove_Scene_Anim);
SYSFUNC(sys_Cmd_Disable_Timer);
SYSFUNC(sys_Cmd_Enable_Timer);
SYSFUNC(sys_Cmd_Set_Timer);
SYSFUNC(sys_Cmd_Set_Palette_Color);
SYSFUNC(sys_Cmd_Number_Of_NPCs);
SYSFUNC(sys_Cmd_Get_Config_Language);
SYSFUNC(sys_Cmd_Get_Actor_Final_X);
SYSFUNC(sys_Cmd_Get_Actor_Final_Y);
};
} // End of namespace Toon
#endif

261
engines/toon/state.cpp Normal file
View file

@ -0,0 +1,261 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#include "state.h"
#include "toon.h"
namespace Toon {
void Location::save(Common::WriteStream *stream) {
stream->write(_cutaway,64);
stream->write(_music,64);
stream->write(_name,64);
stream->writeSint16BE(_numRifBoxes);
stream->writeSint16BE(_numSceneAnimations);
stream->writeSByte(_visited);
for (int32 i = 0; i < _numRifBoxes*2; i++) {
stream->writeSint16BE(_rifBoxesFlags[i]);
}
}
void Location::load(Common::ReadStream *stream) {
stream->read(_cutaway,64);
stream->read(_music,64);
stream->read(_name,64);
_numRifBoxes = stream->readSint16BE();
_numSceneAnimations = stream->readSint16BE();
_visited = stream->readSByte();
for (int32 i = 0; i < _numRifBoxes*2; i++) {
_rifBoxesFlags[i] = stream->readSint16BE();
}
}
State::State(void) {
for (int32 i = 0; i < 64; i++) {
_locations[i]._visited = false;
_locations[i]._numSceneAnimations = 0;
_locations[i]._numRifBoxes = 0;
}
memset(_gameFlag, 0, sizeof(_gameFlag));
memset(_gameGlobalData, -1, sizeof(_gameGlobalData));
for (int32 i = 0; i < 2; i++) {
_timerEnabled[i] = false;
_timerTimeout[i] = 0;
_timerDelay[i] = -1;
}
_lastVisitedScene = -1;
_currentScene = -1;
_currentScrollLock = false;
_currentScrollValue = 0;
_gameTimer = 0;
_currentChapter = 1;
_showConversationIcons = false;
_inCloseUp = false;
_inConversation = false;
_mouseState = -1;
_mouseHidden = false;
_firstConverstationLine = false;
_sackVisible = false; // to change
_inCutaway = false;
_inInventory = false;
_numInventoryItems = 0; //To chhange
_numConfiscatedInventoryItems = 0;
_nextSpecialEnterX = -1;
_nextSpecialEnterY = -1;
#if 0
for (int i = 0; i < 30; i++) {
_inventory[i] = 90 + i;
if (_inventory[i] == 41)
_inventory[i] = 42;
}
_inventory[0] = 53;
_inventory[1] = 22;
_inventory[2] = 93;
_inventory[3] = 49;
_inventory[4] = 47;
_inventory[5] = 14;
_numInventoryItems = 6; //To change
#endif
memset(_conversationState, 0, sizeof(Conversation) * 60);
}
State::~State(void) {
}
int32 State::getGameFlag(int32 flagId) {
return (_gameFlag[flagId >> 3] & (1 << (flagId & 7))) != 0;
}
bool State::hasItemInInventory(int32 item) {
debugC(1, kDebugState, "hasItemInInventory(%d)", item);
for (int32 i = 0; i < _numInventoryItems; i++) {
if (_inventory[i] == item)
return true;
}
return false;
}
void State::save(Common::WriteStream * stream) {
for (int32 i = 0; i < 256; i++) {
_locations[i].save(stream);
}
for (int32 i = 0; i < 256; i++) {
stream->writeSint16BE(_gameGlobalData[i]);
}
for (int32 i = 0; i < 256; i++) {
stream->writeSint16BE(_gameFlag[i]);
}
stream->writeSint16BE(_lastVisitedScene);
stream->writeSint16BE(_currentScene);
stream->writeSint16BE(_currentScrollValue);
stream->writeSByte(_currentScrollLock);
for (int32 i = 0; i < 35; i++) {
stream->writeSint16BE(_inventory[i]);
}
for (int32 i = 0; i < 35; i++) {
stream->writeSint16BE(_confiscatedInventory[i]);
}
stream->writeSint32BE(_numInventoryItems);
stream->writeSint32BE(_numConfiscatedInventoryItems);
stream->writeSByte(_inCloseUp);
stream->writeSByte(_inCutaway);
stream->writeSByte(_inConversation);
stream->writeSByte(_inInventory);
stream->writeSByte(_showConversationIcons);
stream->writeSint16BE(_mouseState);
stream->writeSint16BE(_currentConversationId);
stream->writeSByte(_firstConverstationLine);
stream->writeSByte(_exitConversation);
stream->writeSByte(_mouseHidden);
stream->writeSByte(_sackVisible);
stream->writeSint32BE(_gameTimer);
stream->writeSByte(_currentChapter);
stream->writeByte(_timerEnabled[0]);
stream->writeByte(_timerEnabled[1]);
stream->writeSint32BE(_timerTimeout[0]);
stream->writeSint32BE(_timerTimeout[1]);
stream->writeSint32BE(_timerDelay[0]);
stream->writeSint32BE(_timerDelay[1]);
}
void State::load(Common::ReadStream* stream) {
for (int32 i = 0; i < 256; i++) {
_locations[i].load(stream);
}
for (int32 i = 0; i < 256; i++) {
_gameGlobalData[i] = stream->readSint16BE();
}
for (int32 i = 0; i < 256; i++) {
_gameFlag[i] = stream->readSint16BE();
}
_lastVisitedScene = stream->readSint16BE();
_currentScene = stream->readSint16BE();
_currentScrollValue = stream->readSint16BE();
_currentScrollLock = stream->readSByte();
for (int32 i = 0; i < 35; i++) {
_inventory[i] = stream->readSint16BE();
}
for (int32 i = 0; i < 35; i++) {
_confiscatedInventory[i] = stream->readSint16BE();
}
_numInventoryItems = stream->readSint32BE();
_numConfiscatedInventoryItems = stream->readSint32BE();
_inCloseUp = stream->readSByte();
_inCutaway = stream->readSByte();
_inConversation = stream->readSByte();
_inInventory = stream->readSByte();
_showConversationIcons = stream->readSByte();
_mouseState = stream->readSint16BE();
_currentConversationId = stream->readSint16BE();
_firstConverstationLine = stream->readSByte();
_exitConversation = stream->readSByte();
_mouseHidden = stream->readSByte();
_sackVisible = stream->readSByte();
_gameTimer = stream->readSint32BE();
_currentChapter = stream->readSByte();
_timerEnabled[0] = stream->readByte();
_timerEnabled[1] = stream->readByte();
_timerTimeout[0] = stream->readSint32BE();
_timerTimeout[1] = stream->readSint32BE();
_timerDelay[0] = stream->readSint32BE();
_timerDelay[1] = stream->readSint32BE();
}
void State::loadConversations(Common::ReadStream *stream) {
for (int32 i = 0; i < 60; i++) {
_conversationState[i].load(stream, _conversationData);
}
}
void State::saveConversations(Common::WriteStream *stream) {
for (int32 i = 0; i < 60; i++) {
_conversationState[i].save(stream, _conversationData);
}
}
} // End of namespace Toon

100
engines/toon/state.h Normal file
View file

@ -0,0 +1,100 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#ifndef STATE_H
#define STATE_H
#include "common/file.h"
#include "common/str.h"
#include "conversation.h"
namespace Toon {
struct Location {
char _name[64];
char _music[64];
char _cutaway[64];
bool _visited;
int32 _numSceneAnimations;
int32 _flags;
int32 _numRifBoxes;
int16 _rifBoxesFlags[256];
void save(Common::WriteStream *stream);
void load(Common::ReadStream *stream);
};
class State {
public:
State(void);
~State(void);
Location _locations[256];
int16 _gameGlobalData[256];
uint8 _gameFlag[256];
int16 _lastVisitedScene;
int16 _currentScene;
int16 _currentScrollValue;
bool _currentScrollLock;
int16 _inventory[35];
int16 _confiscatedInventory[35];
int32 _numInventoryItems;
int32 _numConfiscatedInventoryItems;
bool _inCloseUp;
bool _inCutaway;
bool _inConversation;
bool _inInventory;
bool _showConversationIcons;
int16 _mouseState;
int16 *_conversationData;
Conversation _conversationState[60];
int16 _currentConversationId;
bool _firstConverstationLine;
bool _exitConversation;
bool _mouseHidden;
bool _sackVisible;
int32 _gameTimer;
int8 _currentChapter;
int32 _nextSpecialEnterX;
int32 _nextSpecialEnterY;
bool _timerEnabled[2];
int32 _timerTimeout[2];
int32 _timerDelay[2];
int32 getGameFlag(int32 flagId);
bool hasItemInInventory(int32 item);
void load(Common::ReadStream *stream);
void save(Common::WriteStream *stream);
void loadConversations(Common::ReadStream *stream);
void saveConversations(Common::WriteStream *stream);
};
} // End of namespace Toon
#endif

95
engines/toon/text.cpp Normal file
View file

@ -0,0 +1,95 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#include "text.h"
namespace Toon {
TextResource::TextResource(ToonEngine *vm) : _vm(vm) {
_numTexts = 0;
_textData = 0;
}
TextResource::~TextResource(void) {
}
bool TextResource::loadTextResource(Common::String fileName) {
debugC(1, kDebugText, "loadTextResource(%s)", fileName.c_str());
uint32 fileSize = 0;
uint8 *data = _vm->resources()->getFileData(fileName, &fileSize);
if (!data)
return false;
_textData = new uint8[fileSize];
memcpy(_textData, data, fileSize);
_numTexts = READ_LE_UINT16(data);
return true;
}
int32 TextResource::getNext(int32 offset) {
debugC(1, kDebugText, "getNext(%d)", offset);
uint16 *table = (uint16 *)_textData + 1;
int a = getId(offset);
return table[a+1];
}
int32 TextResource::getId(int32 offset) {
debugC(1, kDebugText, "getId(%d)", offset);
uint16 *table = (uint16 *)_textData + 1;
int32 found = -1;
for (int32 i = 0; i < _numTexts; i++) {
if (offset == table[i]) {
found = i;
break;
}
}
return found;
}
char *TextResource::getText(int32 offset) {
debugC(6, kDebugText, "getText(%d)", offset);
uint16 *table = (uint16 *)_textData + 1;
int32 found = -1;
for (int32 i = 0; i < _numTexts; i++) {
if (offset == table[i]) {
found = i;
break;
}
}
if (found < 0)
return NULL;
int32 realOffset = ((uint16 *)_textData + 1 + _numTexts)[found];
return (char *)_textData + realOffset;
}
} // End of namespace Toon

51
engines/toon/text.h Normal file
View file

@ -0,0 +1,51 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#ifndef TOON_TEXT_H
#define TOON_TEXT_H
#include "toon.h"
namespace Toon {
class TextResource {
public:
TextResource(ToonEngine *vm);
~TextResource(void);
bool loadTextResource(Common::String fileName);
char *getText(int32 id);
int32 getId(int32 offset);
int32 getNext(int32 offset);
protected:
int32 _numTexts;
uint8 *_textData;
ToonEngine *_vm;
};
} // End of namespace Toon
#endif

514
engines/toon/tools.cpp Normal file
View file

@ -0,0 +1,514 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#include "tools.h"
#include "toon.h"
namespace Toon {
uint32 decompressLZSS(byte *src, byte *dst, int dstsize) {
debugC(5, kDebugTools, "decompressLZSS(src, dst, %d)", dstsize);
byte *srcp = src;
byte *dstp = dst;
uint16 bitbuf;
int32 len, ofs;
len = 0;
while (dstsize > 0) {
bitbuf = 0x100 | *(srcp++);
while (bitbuf != 1 && dstsize > 0) {
if (bitbuf & 1) {
ofs = READ_LE_UINT16(srcp);
srcp += 2;
len = ((ofs & 0xF000) >> 12) + 3;
ofs = ofs | 0xF000;
dstsize -= len;
if (dstsize < 0)
break;
while (len--) {
*dstp = *(byte *)(dstp + (signed short)ofs);
dstp++;
}
} else {
len = 0;
while ((bitbuf & 2) == 0) {
len++;
bitbuf >>= 1;
}
len++;
dstsize -= len;
if (dstsize < 0)
break;
while (len--)
*(dstp++) = *(srcp++);
}
bitbuf >>= 1;
}
}
len += dstsize;
if (len < 0)
return 0;
while (len--)
*(dstp++) = *(srcp++);
return (dstp - dst);
}
uint32 decompressSPCN(byte *src, byte *dst, uint32 dstsize) {
debugC(1, kDebugTools, "decompressSPCN(src, dst, %d)", dstsize);
byte *srcp = src;
byte *dstp = dst, *dste = dst + dstsize;
byte val;
uint16 len, ofs;
if (!(*srcp & 0x80)) srcp++;
while (dstp < dste) {
val = *(srcp++);
if (val & 0x80) {
if (val & 0x40) {
if (val == 0xFE) {
len = READ_LE_UINT16(srcp);
while (len--)
*(dstp++) = srcp[2];
srcp += 3;
} else {
if (val == 0xFF) {
len = READ_LE_UINT16(srcp);
srcp += 2;
} else {
len = (val & 0x3F) + 3;
}
ofs = READ_LE_UINT16(srcp);
srcp += 2;
while (len--) {
*dstp = *(byte *)(dstp - ofs);
dstp++;
}
}
} else {
len = val & 0x3F;
while (len--)
*(dstp++) = *(srcp++);
}
} else {
len = (val >> 4) + 3;
ofs = ((val & 0x0F) << 8) | *(srcp++);
while (len--) {
*dstp = *(byte *)(dstp - ofs);
dstp++;
}
}
}
return (dstp - dst);
}
//return codes
#define NOT_PACKED 0
#define PACKED_CRC -1
#define UNPACKED_CRC -2
//other defines
#define TABLE_SIZE (16 * 8)
#define MIN_LENGTH 2
#define HEADER_LEN 18
RncDecoder::RncDecoder() {
initCrc();
}
RncDecoder::~RncDecoder() { }
void RncDecoder::initCrc() {
debugC(1, kDebugTools, "initCrc()");
uint16 cnt = 0;
uint16 tmp1 = 0;
uint16 tmp2 = 0;
for (tmp2 = 0; tmp2 < 0x100; tmp2++) {
tmp1 = tmp2;
for (cnt = 8; cnt > 0; cnt--) {
if (tmp1 % 2) {
tmp1 >>= 1;
tmp1 ^= 0x0a001;
} else
tmp1 >>= 1;
}
_crcTable[tmp2] = tmp1;
}
}
//calculate 16 bit crc of a block of memory
uint16 RncDecoder::crcBlock(const uint8 *block, uint32 size) {
debugC(1, kDebugTools, "crcBlock(block, %d)", size);
uint16 crc = 0;
uint8 *crcTable8 = (uint8 *)_crcTable; //make a uint8* to crc_table
uint8 tmp;
uint32 i;
for (i = 0; i < size; i++) {
tmp = *block++;
crc ^= tmp;
tmp = (uint8)((crc >> 8) & 0x00FF);
crc &= 0x00FF;
crc = *(uint16 *)&crcTable8[crc << 1];
crc ^= tmp;
}
return crc;
}
uint16 RncDecoder::inputBits(uint8 amount) {
debugC(5, kDebugTools, "inputBits(%d)", amount);
uint16 newBitBuffh = _bitBuffh;
uint16 newBitBuffl = _bitBuffl;
int16 newBitCount = _bitCount;
uint16 remBits, returnVal;
returnVal = ((1 << amount) - 1) & newBitBuffl;
newBitCount -= amount;
if (newBitCount < 0) {
newBitCount += amount;
remBits = (newBitBuffh << (16 - newBitCount));
newBitBuffh >>= newBitCount;
newBitBuffl >>= newBitCount;
newBitBuffl |= remBits;
_srcPtr += 2;
newBitBuffh = READ_LE_UINT16(_srcPtr);
amount -= newBitCount;
newBitCount = 16 - amount;
}
remBits = (newBitBuffh << (16 - amount));
_bitBuffh = newBitBuffh >> amount;
_bitBuffl = (newBitBuffl >> amount) | remBits;
_bitCount = (uint8)newBitCount;
return returnVal;
}
void RncDecoder::makeHufftable(uint16 *table) {
debugC(1, kDebugTools, "makeHufftable(table)");
uint16 bitLength, i, j;
uint16 numCodes = inputBits(5);
if (!numCodes)
return;
uint8 huffLength[16];
for (i = 0; i < numCodes; i++)
huffLength[i] = (uint8)(inputBits(4) & 0x00FF);
uint16 huffCode = 0;
for (bitLength = 1; bitLength < 17; bitLength++) {
for (i = 0; i < numCodes; i++) {
if (huffLength[i] == bitLength) {
*table++ = (1 << bitLength) - 1;
uint16 b = huffCode >> (16 - bitLength);
uint16 a = 0;
for (j = 0; j < bitLength; j++)
a |= ((b >> j) & 1) << (bitLength - j - 1);
*table++ = a;
*(table + 0x1e) = (huffLength[i] << 8) | (i & 0x00FF);
huffCode += 1 << (16 - bitLength);
}
}
}
}
uint16 RncDecoder::inputValue(uint16 *table) {
debugC(5, kDebugTools, "inputValue(table)");
uint16 valOne, valTwo, value = _bitBuffl;
do {
valTwo = (*table++) & value;
valOne = *table++;
} while (valOne != valTwo);
value = *(table + 0x1e);
inputBits((uint8)((value >> 8) & 0x00FF));
value &= 0x00FF;
if (value >= 2) {
value--;
valOne = inputBits((uint8)value & 0x00FF);
valOne |= (1 << value);
value = valOne;
}
return value;
}
int RncDecoder::getbit() {
debugC(6, kDebugTools, "getbits()");
if (_bitCount == 0) {
_bitBuffl = *_srcPtr++;
_bitCount = 8;
}
byte temp = (_bitBuffl & 0x80) >> 7;
_bitBuffl <<= 1;
_bitCount--;
return temp;
}
int32 RncDecoder::unpackM1(const void *input, void *output) {
debugC(1, kDebugTools, "unpackM1(input, output)");
uint8 *outputLow, *outputHigh;
const uint8 *inputHigh, *inputptr = (const uint8 *)input;
uint32 unpackLen = 0;
uint32 packLen = 0;
uint16 counts = 0;
uint16 crcUnpacked = 0;
uint16 crcPacked = 0;
_bitBuffl = 0;
_bitBuffh = 0;
_bitCount = 0;
//Check for "RNC "
if (READ_BE_UINT32(inputptr) != RNC1_SIGNATURE)
return NOT_PACKED;
inputptr += 4;
// read unpacked/packed file length
unpackLen = READ_BE_UINT32(inputptr);
inputptr += 4;
packLen = READ_BE_UINT32(inputptr);
inputptr += 4;
uint8 blocks = *(inputptr + 5);
//read CRC's
crcUnpacked = READ_BE_UINT16(inputptr);
inputptr += 2;
crcPacked = READ_BE_UINT16(inputptr);
inputptr += 2;
inputptr = (inputptr + HEADER_LEN - 16);
if (crcBlock(inputptr, packLen) != crcPacked)
return PACKED_CRC;
inputptr = (((const uint8 *)input) + HEADER_LEN);
_srcPtr = inputptr;
inputHigh = ((const uint8 *)input) + packLen + HEADER_LEN;
outputLow = (uint8 *)output;
outputHigh = *(((const uint8 *)input) + 16) + unpackLen + outputLow;
if (!((inputHigh <= outputLow) || (outputHigh <= inputHigh))) {
_srcPtr = inputHigh;
_dstPtr = outputHigh;
memcpy((_dstPtr - packLen), (_srcPtr - packLen), packLen);
_srcPtr = (_dstPtr - packLen);
}
_dstPtr = (uint8 *)output;
_bitCount = 0;
_bitBuffl = READ_LE_UINT16(_srcPtr);
inputBits(2);
do {
makeHufftable(_rawTable);
makeHufftable(_posTable);
makeHufftable(_lenTable);
counts = inputBits(16);
do {
uint32 inputLength = inputValue(_rawTable);
uint32 inputOffset;
if (inputLength) {
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);
_bitBuffl &= ((1 << _bitCount) - 1);
_bitBuffl |= (a << _bitCount);
_bitBuffh = (a >> (16 - _bitCount)) | (b << _bitCount);
}
if (counts > 1) {
inputOffset = inputValue(_posTable) + 1;
inputLength = inputValue(_lenTable) + MIN_LENGTH;
// Don't use memcpy here! because input and output overlap.
uint8 *tmpPtr = (_dstPtr - inputOffset);
while (inputLength--)
*_dstPtr++ = *tmpPtr++;
}
} while (--counts);
} while (--blocks);
if (crcBlock((uint8 *)output, unpackLen) != crcUnpacked)
return UNPACKED_CRC;
// all is done..return the amount of unpacked bytes
return unpackLen;
}
int32 RncDecoder::unpackM2(const void *input, void *output) {
debugC(1, kDebugTools, "unpackM2(input, output)");
const uint8 *inputptr = (const uint8 *)input;
uint32 unpackLen = 0;
uint32 packLen = 0;
uint16 crcUnpacked = 0;
uint16 crcPacked = 0;
// Strangerke - Commented (not used)
// uint16 counts = 0;
_bitBuffl = 0;
_bitCount = 0;
//Check for "RNC "
if (READ_BE_UINT32(inputptr) != RNC2_SIGNATURE)
return NOT_PACKED;
inputptr += 4;
// read unpacked/packed file length
unpackLen = READ_BE_UINT32(inputptr);
inputptr += 4;
packLen = READ_BE_UINT32(inputptr);
inputptr += 4;
//read CRC's
crcUnpacked = READ_BE_UINT16(inputptr);
inputptr += 2;
crcPacked = READ_BE_UINT16(inputptr);
inputptr += 2;
inputptr = (inputptr + HEADER_LEN - 16);
if (crcBlock(inputptr, packLen) != crcPacked)
return PACKED_CRC;
inputptr = (((const uint8 *)input) + HEADER_LEN);
_srcPtr = inputptr;
_dstPtr = (uint8 *)output;
uint16 ofs, len;
byte ofs_hi, ofs_lo;
len = 0;
ofs_hi = 0;
ofs_lo = 0;
getbit();
getbit();
while (1) {
bool loadVal = false;
while (getbit() == 0)
*_dstPtr++ = *_srcPtr++;
len = 2;
ofs_hi = 0;
if (getbit() == 0) {
len = (len << 1) | getbit();
if (getbit() == 1) {
len--;
len = (len << 1) | getbit();
if (len == 9) {
len = 4;
while (len--)
ofs_hi = (ofs_hi << 1) | getbit();
len = (ofs_hi + 3) * 4;
while (len--)
*_dstPtr++ = *_srcPtr++;
continue;
}
}
loadVal = true;
} else {
if (getbit() == 1) {
len++;
if (getbit() == 1) {
len = *_srcPtr++;
if (len == 0) {
if (getbit() == 1)
continue;
else
break;
}
len += 8;
}
loadVal = true;
} else {
loadVal = false;
}
}
if (loadVal) {
if (getbit() == 1) {
ofs_hi = (ofs_hi << 1) | getbit();
if (getbit() == 1) {
ofs_hi = ((ofs_hi << 1) | getbit()) | 4;
if (getbit() == 0)
ofs_hi = (ofs_hi << 1) | getbit();
} else if (ofs_hi == 0) {
ofs_hi = 2 | getbit();
}
}
}
ofs_lo = *_srcPtr++;
ofs = (ofs_hi << 8) | ofs_lo;
while (len--)
*_dstPtr++ = *(byte *)(_dstPtr - ofs - 1);
}
if (crcBlock((uint8 *)output, unpackLen) != crcUnpacked)
return UNPACKED_CRC;
// all is done..return the amount of unpacked bytes
return unpackLen;
}
} // End of namespace Toon

83
engines/toon/tools.h Normal file
View file

@ -0,0 +1,83 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#ifndef TOON_TOOLS_H
#define TOON_TOOLS_H
#include "common/scummsys.h"
#include "common/endian.h"
#define RNC1_SIGNATURE 0x524E4301 // "RNC\001"
#define RNC2_SIGNATURE 0x524E4302 // "RNC\002"
namespace Toon {
const uint32 kCompLZSS = 0x4C5A5353;
const uint32 kCompSPCN = 0x5350434E;
const uint32 kCompRNC1 = 0x524E4301;
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)
uint32 decompressSPCN(byte *src, byte *dst, uint32 dstsize);
uint32 decompressLZSS(byte *src, byte *dst, int dstsize);
class RncDecoder {
protected:
uint16 _rawTable[64];
uint16 _posTable[64];
uint16 _lenTable[64];
uint16 _crcTable[256];
uint16 _bitBuffl;
uint16 _bitBuffh;
uint8 _bitCount;
const uint8 *_srcPtr;
uint8 *_dstPtr;
public:
RncDecoder();
~RncDecoder();
int32 unpackM1(const void *input, void *output);
int32 unpackM2(const void *input, void *output);
protected:
void initCrc();
uint16 crcBlock(const uint8 *block, uint32 size);
uint16 inputBits(uint8 amount);
void makeHufftable(uint16 *table);
uint16 inputValue(uint16 *table);
int getbit();
};
} // End of namespace Toon
#endif

4276
engines/toon/toon.cpp Normal file

File diff suppressed because it is too large Load diff

380
engines/toon/toon.h Normal file
View file

@ -0,0 +1,380 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#ifndef TOON_H
#define TOON_H
#include "engines/advancedDetector.h"
#include "engines/engine.h"
#include "graphics/surface.h"
#include "common/random.h"
#include "resource.h"
#include "script.h"
#include "script_func.h"
#include "state.h"
#include "picture.h"
#include "anim.h"
#include "movie.h"
#include "font.h"
#include "text.h"
#include "audio.h"
#define TOON_DAT_VER_MAJ 0 // 1 byte
#define TOON_DAT_VER_MIN 3 // 1 byte
#define TOON_SAVEGAME_VERSION 4
#define DATAALIGNMENT 4
namespace Toon {
enum ToonGameType {
GType_TOON = 1
};
enum ToonDebugChannels {
kDebugAnim = 1 << 0,
kDebugCharacter = 1 << 1,
kDebugAudio = 1 << 2,
kDebugHotspot = 1 << 3,
kDebugFont = 1 << 4,
kDebugPath = 1 << 5,
kDebugMovie = 1 << 6,
kDebugPicture = 1 << 7,
kDebugResource = 1 << 8,
kDebugState = 1 << 9,
kDebugTools = 1 << 10,
kDebugText = 1 << 11
};
class Picture;
class Movie;
class Hotspots;
class Character;
class CharacterDrew;
class CharacterFlux;
class FontRenderer;
class TextResource;
class AudioManager;
class PathFinding;
class ToonEngine : public Engine {
public:
ToonEngine(OSystem *syst, const ADGameDescription *gameDescription);
~ToonEngine();
const ADGameDescription *_gameDescription;
Common::Language _language;
byte _numVariant;
byte _gameVariant;
char **_locationDirNotVisited;
char **_locationDirVisited;
char **_specialInfoLine;
virtual Common::Error run();
virtual bool showMainmenu(bool& loadedGame);
virtual void init();
bool loadToonDat();
char **loadTextsVariante(Common::File &in);
virtual void setPaletteEntries(uint8 *palette, int32 offset, int32 num);
virtual void fixPaletteEntries(uint8 *palette, int num);
virtual void flushPalette();
virtual void parseInput();
virtual void initChapter();
virtual void initFonts();
virtual void loadScene(int32 SceneId, bool forGameLoad = false);
virtual void exitScene();
virtual void loadCursor();
virtual void setCursor(int32 type, bool inventory = false, int32 offsetX = 0, int offsetY = 0);
virtual void loadAdditionalPalette(Common::String fileName, int32 mode);
virtual void setupGeneralPalette();
virtual void render();
virtual void update(int32 timeIncrement);
virtual void doFrame();
virtual void updateAnimationSceneScripts(int32 timeElapsed);
virtual void updateCharacters(int32 timeElapsed);
virtual void setSceneAnimationScriptUpdate(bool enable);
virtual bool isUpdatingSceneAnimation();
virtual int32 getCurrentUpdatingSceneAnimation();
virtual int32 randRange(int32 minStart, int32 maxStart);
virtual void selectHotspot();
virtual void clickEvent();
virtual int32 runEventScript(int32 x, int32 y, int32 mode, int32 id, int32 scriptId);
virtual void flipScreens();
virtual void drawInfoLine();
virtual void drawConversationLine();
virtual const char *getLocationString(int32 locationId, bool alreadyVisited);
virtual int32 getScaleAtPoint(int32 x, int32 y);
virtual int32 getZAtPoint(int32 x, int32 y);
virtual int32 getLayerAtPoint(int32 x, int32 y);
virtual int32 characterTalk(int32 dialogid, bool blocking = true);
virtual int32 simpleCharacterTalk(int32 dialogid);
virtual void sayLines(int numLines, int dialogId);
virtual void haveAConversation(int32 convId);
virtual void processConversationClick(Conversation *conv, int32 status);
virtual int32 runConversationCommand(int16 **command);
virtual void prepareConversations();
virtual void drawConversationIcons();
virtual void simpleUpdate();
virtual int32 waitTicks(int32 numTicks, bool breakOnMouseClick);
virtual void copyToVirtualScreen(bool updateScreen = true);
virtual void getMouseEvent();
virtual int32 showInventory();
virtual void drawSack();
virtual void addItemToInventory(int32 item);
virtual void deleteItemFromInventory(int32 item);
virtual void replaceItemFromInventory(int32 item, int32 destItem);
virtual void rearrangeInventory();
virtual void createMouseItem(int32 item);
virtual void deleteMouseItem();
virtual void showCutaway(Common::String cutawayPicture);
virtual void hideCutaway();
virtual void drawPalette();
virtual void newGame();
virtual void playSoundWrong();
virtual void playSFX(int32 id, int32 volume);
virtual void storeRifFlags(int32 location);
virtual void restoreRifFlags(int32 location);
virtual void getTextPosition(int32 characterId, int32 *retX, int32 *retY);
virtual int32 getConversationFlag(int32 locationId, int32 param);
virtual int32 getSpecialInventoryItem(int32 item);
virtual Character *getCharacterById(int32 charId);
virtual Common::String getSavegameName(int nr);
virtual bool loadGame(int32 slot);
virtual bool saveGame(int32 slot);
virtual void fadeIn(int32 numFrames) ;
virtual void fadeOut(int32 numFrames) ;
virtual void initCharacter(int32 characterId, int32 animScriptId, int32 animToPlayId, int32 sceneAnimationId);
virtual int32 handleInventoryOnFlux(int32 itemId);
virtual int32 handleInventoryOnInventory(int32 itemDest, int32 itemSrc);
virtual int32 handleInventoryOnDrew(int32 itemId);
virtual int32 pauseSceneAnimationScript(int32 animScriptId, int32 tickToWait);
virtual void updateTimer(int32 timeIncrement);
virtual Common::String createRoomFilename(Common::String name);
virtual void createShadowLUT();
virtual void playTalkAnimOnCharacter(int32 animID, int32 characterId, bool talker);
virtual void updateScrolling(bool force, int32 timeIncrement);
virtual void enableTimer(int32 timerId);
virtual void setTimer(int32 timerId, int32 timerWait);
virtual void disableTimer(int32 timerId);
virtual void updateTimers();
virtual void makeLineNonWalkable(int32 x, int32 y, int32 x2, int32 y2);
virtual void makeLineWalkable(int32 x, int32 y, int32 x2, int32 y2);
virtual void renderInventory();
virtual void viewInventoryItem(Common::String str, int32 lineId, int32 itemDest);
virtual void storePalette();
virtual void restorePalette();
Resources *resources() {
return _resources;
}
State *state() {
return _gameState;
}
Graphics::Surface &getMainSurface() {
return *_mainSurface;
}
Picture *getMask() {
return _currentMask;
}
Picture *getPicture() {
return _currentPicture;
}
AnimationManager *getAnimationManager() {
return _animationManager;
}
Movie *getMoviePlayer() {
return _moviePlayer;
}
SceneAnimation *getSceneAnimation(int32 id) {
return &_sceneAnimations[id];
}
SceneAnimationScript *getSceneAnimationScript(int32 id) {
return &_sceneAnimationScripts[id];
}
EMCInterpreter *getScript() {
return _script;
}
Hotspots *getHotspots() {
return _hotspots;
}
Character *getCharacter(int32 charId) {
return _characters[charId];
}
uint8 *getShadowLUT() {
return _shadowLUT;
}
int32 getCurrentLineToSay() {
return _currentTextLineId;
}
CharacterDrew *getDrew() {
return (CharacterDrew *)_drew;
}
CharacterFlux *getFlux() {
return (CharacterFlux *)_flux;
}
int32 getTickLength() {
return _tickLength;
}
int32 getOldMilli() {
return _oldTimer2;
}
OSystem *getSystem() {
return _system;
}
AudioManager *getAudioManager() {
return _audioManager;
}
int32 getScriptRegionNested() {
return _currentScriptRegion;
}
int32 getMouseX() {
return _mouseX;
}
int32 getMouseY() {
return _mouseY;
}
PathFinding *getPathFinding() {
return _pathFinding;
}
Common::WriteStream *getSaveBufferStream() {
return _saveBufferStream;
}
protected:
OSystem *_system;
int32 _tickLength;
Resources *_resources;
TextResource *_genericTexts;
TextResource *_roomTexts;
State *_gameState;
uint8 *_finalPalette;
uint8 *_backupPalette;
uint8 *_additionalPalette1;
uint8 *_additionalPalette2;
uint8 *_cutawayPalette;
uint8 *_universalPalette;
uint8 *_fluxPalette;
uint8 *_roomScaleData;
uint8 *_shadowLUT;
Picture *_currentPicture;
Picture *_currentMask;
Picture *_currentCutaway;
Picture *_inventoryPicture;
PathFinding *_pathFinding;
EMCInterpreter *_script;
EMCData _scriptData;
EMCState _scriptState[4];
int32 _currentScriptRegion; // script region ( nested script run )
ScriptFunc *_script_func;
SceneAnimation _sceneAnimations[64];
SceneAnimationScript _sceneAnimationScripts[64];
int32 _lastProcessedSceneScript;
bool _animationSceneScriptRunFlag;
bool _updatingSceneScriptRunFlag;
Graphics::Surface *_mainSurface;
AnimationInstance *_cursorAnimationInstance;
Animation *_cursorAnimation;
Animation *_dialogIcons;
Animation *_inventoryIcons;
Animation *_inventoryIconSlots;
int32 _cursorOffsetX;
int32 _cursorOffsetY;
char *_currentTextLine;
int32 _currentTextLineId;
int32 _currentTextLineX;
int32 _currentTextLineY;
int32 _currentTextLineCharacterId;
int32 _oldScrollValue;
AnimationManager *_animationManager;
Character *_characters[32];
Character *_drew;
Character *_flux;
Hotspots *_hotspots;
int32 _currentHotspotItem;
int32 _mouseX;
int32 _mouseY;
int32 _mouseButton;
int32 _lastMouseButton;
int32 _oldTimer;
int32 _oldTimer2;
Movie *_moviePlayer;
Common::RandomSource _rnd;
FontRenderer *_fontRenderer;
Animation *_fontToon;
Animation *_fontEZ;
AudioManager *_audioManager;
Common::MemoryWriteStreamDynamic* _saveBufferStream;
int16 *_conversationData;
bool _firstFrame;
bool _isDemo;
};
} // End of namespace Toon
#endif

View file

@ -0,0 +1,163 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
* This is a utility for storing all the hardcoded data of Toonstruck in a separate
* data file, used by the game engine
*/
// HACK to allow building with the SDL backend on MinGW
// see bug #1800764 "TOOLS: MinGW tools building broken"
#ifdef main
#undef main
#endif // main
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "common/scummsys.h"
#include "common/events.h"
#include "create_toon.h"
#include "staticdata.h"
static void writeByte(FILE *fp, uint8 b) {
fwrite(&b, 1, 1, fp);
}
static void writeUint16BE(FILE *fp, uint16 value) {
writeByte(fp, (uint8)(value >> 8));
writeByte(fp, (uint8)(value & 0xFF));
}
void writeSint16BE(FILE *fp, int16 value) {
writeUint16BE(fp, (uint16)value);
}
static void writeUint32BE(FILE *fp, uint32 value) {
writeByte(fp, (uint8)(value >> 24));
writeByte(fp, (uint8)((value >> 16) & 0xFF));
writeByte(fp, (uint8)((value >> 8) & 0xFF));
writeByte(fp, (uint8)(value & 0xFF));
}
void writeSint32BE(FILE *fp, int32 value) {
writeUint32BE(fp, (uint16)value);
}
int main(int argc, char *argv[]) {
FILE *outFile;
int nbrElem;
outFile = fopen("toon.dat", "wb");
// Write header
fwrite("TOON", 4, 1, outFile);
writeByte(outFile, TOON_DAT_VER_MAJ);
writeByte(outFile, TOON_DAT_VER_MIN);
// game versions/variantes
writeUint16BE(outFile, NUM_VARIANTE);
// Write locationDirNotVisited
nbrElem = sizeof(locationDirNotVisited_EN) / sizeof(char *);
writeTextArray(outFile, locationDirNotVisited_EN, nbrElem);
nbrElem = sizeof(locationDirNotVisited_FR) / sizeof(char *);
writeTextArray(outFile, locationDirNotVisited_FR, nbrElem);
nbrElem = sizeof(locationDirNotVisited_DE) / sizeof(char *);
writeTextArray(outFile, locationDirNotVisited_DE, nbrElem);
nbrElem = sizeof(locationDirNotVisited_RU) / sizeof(char *);
writeTextArray(outFile, locationDirNotVisited_RU, nbrElem);
nbrElem = sizeof(locationDirNotVisited_SP) / sizeof(char *);
writeTextArray(outFile, locationDirNotVisited_SP, nbrElem);
// Write locationDirVisited
nbrElem = sizeof(locationDirVisited_EN) / sizeof(char *);
writeTextArray(outFile, locationDirVisited_EN, nbrElem);
nbrElem = sizeof(locationDirVisited_FR) / sizeof(char *);
writeTextArray(outFile, locationDirVisited_FR, nbrElem);
nbrElem = sizeof(locationDirVisited_DE) / sizeof(char *);
writeTextArray(outFile, locationDirVisited_DE, nbrElem);
nbrElem = sizeof(locationDirVisited_RU) / sizeof(char *);
writeTextArray(outFile, locationDirVisited_RU, nbrElem);
nbrElem = sizeof(locationDirVisited_SP) / sizeof(char *);
writeTextArray(outFile, locationDirVisited_SP, nbrElem);
// Write specialInfoLine
nbrElem = sizeof(specialInfoLine_EN) / sizeof(char *);
writeTextArray(outFile, specialInfoLine_EN, nbrElem);
nbrElem = sizeof(specialInfoLine_FR) / sizeof(char *);
writeTextArray(outFile, specialInfoLine_FR, nbrElem);
nbrElem = sizeof(specialInfoLine_DE) / sizeof(char *);
writeTextArray(outFile, specialInfoLine_DE, nbrElem);
nbrElem = sizeof(specialInfoLine_RU) / sizeof(char *);
writeTextArray(outFile, specialInfoLine_RU, nbrElem);
nbrElem = sizeof(specialInfoLine_SP) / sizeof(char *);
writeTextArray(outFile, specialInfoLine_SP, nbrElem);
// Not yet handled : miscTexts, endingLine and exitLine. Are they useful?
fclose(outFile);
return 0;
}
void writeTextArray(FILE *outFile, const char *textArray[], int nbrText) {
int len, len1, pad;
uint8 padBuf[DATAALIGNMENT];
for (int i = 0; i < DATAALIGNMENT; i++)
padBuf[i] = 0;
writeUint16BE(outFile, nbrText);
len = DATAALIGNMENT - 2;
for (int i = 0; i < nbrText; i++) {
len1 = strlen(textArray[i]) + 1;
pad = DATAALIGNMENT - (len1 + 2) % DATAALIGNMENT;
len += 2 + len1 + pad;
}
writeUint16BE(outFile, len);
fwrite(padBuf, DATAALIGNMENT - 2, 1, outFile); // padding
for (int i = 0; i < nbrText; i++) {
len = strlen(textArray[i]) + 1;
pad = DATAALIGNMENT - (len + 2) % DATAALIGNMENT;
writeUint16BE(outFile, len + pad + 2);
fwrite(textArray[i], len, 1, outFile);
fwrite(padBuf, pad, 1, outFile);
}
}

View file

@ -0,0 +1,47 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#ifndef CREATE_TOON_H
#define CREATE_TOON_H
#define ARRAYSIZE(x) ((int)(sizeof(x) / sizeof(x[0])))
#define DATAALIGNMENT 4
#define TOON_DAT_VER_MAJ 0 // 1 byte
#define TOON_DAT_VER_MIN 3 // 1 byte
// Number of Variante of the game. For the moment, it's the same
// than the number of languages
#define NUM_VARIANTE 5
typedef unsigned char uint8;
typedef unsigned char byte;
typedef unsigned short uint16;
typedef signed short int16;
void writeTextArray(FILE *outFile, const char *textData[], int nbrText);
#endif // CREATE_TOON_H

View file

@ -0,0 +1,20 @@

Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "create_toon", "create_toon.vcproj", "{5F280130-349D-11DD-AE16-0800200C9A66}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{5F280130-349D-11DD-AE16-0800200C9A66}.Debug|Win32.ActiveCfg = Debug|Win32
{5F280130-349D-11DD-AE16-0800200C9A66}.Debug|Win32.Build.0 = Debug|Win32
{5F280130-349D-11DD-AE16-0800200C9A66}.Release|Win32.ActiveCfg = Release|Win32
{5F280130-349D-11DD-AE16-0800200C9A66}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View file

@ -0,0 +1,187 @@
<?xml version="1.0" encoding="windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="create_toon"
ProjectGUID="{5F280130-349D-11DD-AE16-0800200C9A66}"
RootNamespace="create_toon"
Keyword="Win32Proj"
TargetFrameworkVersion="131072"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="Debug"
IntermediateDirectory="Debug"
ConfigurationType="1"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4996"
Optimization="0"
AdditionalIncludeDirectories="..\..\..\.."
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)/create_toon.exe"
LinkIncremental="2"
IgnoreDefaultLibraryNames="libc.lib;libcmt.lib"
GenerateDebugInformation="true"
ProgramDatabaseFile="$(OutDir)/create_toon.pdb"
SubSystem="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="Release"
IntermediateDirectory="Release"
ConfigurationType="1"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/wd4996"
Optimization="3"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)/create_toon.exe"
LinkIncremental="1"
IgnoreDefaultLibraryNames="libc.lib;libcmt.lib"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<File
RelativePath="..\..\create_toon.cpp"
>
</File>
<File
RelativePath="..\..\create_toon.h"
>
</File>
<File
RelativePath="..\..\staticdata.h"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View file

@ -0,0 +1,10 @@
MODULE := tools/create_toon
MODULE_OBJS := \
create_toon.o
# Set the name of the executable
TOOL_EXECUTABLE := create_toon
# Include common rules
include $(srcdir)/rules.mk

View file

@ -0,0 +1,324 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#ifndef STATICDATA_H
#define STATICDATA_H
const char *locationDirNotVisited_EN[] = {
"Lab", "Path", "Outside", "Pothole", "Palace Hallway",
"Door", "Secret Passage", "Doorway", "Doorway", "DUMMY",
"Path", "Shop", "Shop", "Shop", "Shop",
"Path", "Malevolated Countryside", "Malevolated Countryside", "Entrance", "Entrance",
"Path", "Path", "Central Zanydu", "Lower Zanydu", "Wacme Entrance",
"Upper Zanydu", "Entrance", "Entrance", "Path", "Path",
"Path", "Seedy's", "Entrance", "Entrance", "Path",
"DUMMY", "DUMMY", "Dungeon", "Hallway", "Air Vent",
"Upstairs", "Doorway", "Doorway", "Downstairs", "Rec Room",
"Doorway", "Secret Passageway", "Upstairs", "Upstairs", "Up",
"Doorway", "Upstairs", "Doorway", "Doorway", "Doorway",
"Swamp", "Forest", "Meadow", "Farmland", "Main Street",
"Costume Shop", "Shuttle Station", "Central Zanydu", "Upper North-Southeast Zanydu", "Lower South-Northwest Zanydu",
"Way-Outback", "High Road", "Frank's Lab", "Cryo-Crypt", "Fantasyworld",
"Vulture Falls", "Vulture Falls", "Vincent van Gogh's Studio", "Fearworld", "Attic",
"Unorthodontist's Office", "Bedroom", "The Malevolands", "Inhuman Robots, Inc.", "Inhuman Robots, Inc. Workshop",
"The End of the World", "Castle Ramparts", "Castle Top", "Kitchen", "Living Room",
"Bedroom", "Laboratory", "Storage Center First Floor", "Storage Center Second Floor", "Storage Center Third Floor",
"King Hugh's Palace", "Trophy Room", "Hallway", "Hallway", "Throne Room",
"Office", "Balcony", "Lighthouse", "Bedroom", "Hall of Reflection",
"Seedy's", "Barn", "WACME", "Lab"
};
const char *locationDirNotVisited_FR[] = {
"Labo", "Chemin", "Ext\351rieur", "Trou", "Hall du Palais",
"Porte", "Passage Secret", "Porte", "Porte", "DUMMY",
"Chemin", "Boutique", "Boutique", "Boutique", "Boutique",
"Chemin", "Champ perfidifi\351", "Champ perfidifi\351", "Entr\351e", "Entr\351e",
"Chemin", "Chemin", "Zanydu-Centre", "Bas de Zanydu", "Entr\351e des 3 Belges",
"Hauts de Zanydu", "Entr\351e", "Entr\351e", "Chemin", "Chemin",
"Chemin", "Bouling", "Entr\351e", "Entr\351e", "Chemin",
"DUMMY", "DUMMY", "Donjon", "Hall", "Conduit d'a\351ration",
"Etage sup\351rieur", "Porte", "Porte", "Etage inf\351rieur", "Salle de jeux",
"Porte", "Passage Secret", "Etage sup\351rieur", "Etage sup\351rieur", "Vers le haut",
"Porte", "Etage sup\351rieur", "Porte", "Porte", "Porte",
"Mar\351cage", "For\352t", "Prairie", "Champ", "Rue Principale",
"Boutique de costumes", "Gare Navette", "Zanydu-Centre", "Hauts de Zanydu Sud-Est du Nord", "Bas de Zanydu Nord-Ouest du Sud",
"Lointain lointain", "High Road", "Labo de Frank", "Cryo-Crypt", "Fantasyworld",
"Vulture Falls", "Vulture Falls", "Vincent van Gogh's Studio", "Fearworld", "Grenier",
"Unorthodontist's Office", "Chambre", "Perfidia", "Robots Inhumains SARL", "Robots Inhumains SARL. Atelier",
"La Fin du Monde", "Remparts du ch\342teau", "Castle Top", "Cuisine", "Salon",
"Chambre", "Laboratoire", "Storage Center First Floor", "Storage Center Second Floor", "Storage Center Third Floor",
"Ch\342teau de Hilarius 1er", "Salle des Troph\351es", "Hall", "Hall", "Salle du Tr\364ne",
"Bureau", "Balcon", "Lighthouse", "Chambre", "Hall of Reflection",
"Bouling", "Grange", "LES 3 BELGES", "Labo"
};
const char *locationDirNotVisited_DE[] = {
"Labor", "Weg", "Drau\337en", "Schlagloch", "Palastflur",
"T\374r", "Geheimgang", "T\374r", "T\374r", "DUMMY",
"Weg", "Laden", "Laden", "Laden", "Laden",
"Weg", "\334belierte Landschaft", "\334belierte Landschaft", "Eingang", "Eingang",
"Weg", "Weg", "Mittel-Trickreich", "Nieder-Trickreich", "Eingang der Fa. Wacme",
"Ober-Trickreich", "Eingang", "Eingang", "Weg", "Weg",
"Weg", "Seedys", "Eingang", "Eingang", "Weg",
"DUMMY", "DUMMY", "Kerker", "Flur", "Luftschacht",
"Nach oben", "T\374r", "T\374r", "Nach unten", "Ruheraum",
"T\374r", "Geheimgang", "Nach oben", "Nach oben", "Rauf",
"T\374r", "Nach oben", "T\374r", "T\374r", "T\374r",
"Sumpf", "Wald", "Wiese", "Ackerland", "Hauptstra\337e",
"Kost\374mverleih", "Bahnhaltestelle", "Mittel-Trickreich", "Ober-Nord-S\374dost-Trickreich", "Unteres S\374d-Nordwest-Trickreich",
"Weite W\374ste Wildnis", "Hochstra\337e", "Franks Labor", "K\344lteschlafkammer", "Phantasiawelt",
"Geierf\344lle", "Geierf\344lle", "Vincent van Goghs Studio", "Angstwelt", "Dachboden",
"Praxis des Unorthodontisten", "Schlafzimmer", "Das \334beland", "Unmenschliche Roboter AG", "Unmenschliche Roboter AG - Werkstatt",
"Das Ende der Welt", "Schlo\337w\344lle", "Oberer Teil des Schlosses", "K\374che", "Wohnzimmer",
"Schlafzimmer", "Labor", "Lager 1. Stock", "Lager 2. Stock", "Lager 3. Stock",
"K\366nig Nicks Palast", "Pokalsaal", "Flur", "Flur", "Thronsaal",
"B\374ro", "Balkon", "Leuchtturm", "Schlafzimmer", "Saal der Reflektion",
"Seedys", "Scheune", "WACME", "Labor"
};
const char *locationDirNotVisited_RU[] = {
"YBB", "Nelf", "Ds[jl", "Hsndbyf", "Dtcnb,.km",
"D[jl", "Nfqysq ghj[jl", "Ghj[jl", "Ghj[jl", "VFRTN",
"Nelf", "Ijg", "Ijg", "Ijg", "Ijg",
"Nelf", "Bcrjdthrfyyfz ptvkz", "Bcrjdthrfyyfz ptvkz", "D[jl", "D[jl",
"Nelf", "Nelf", "Wtynh", "Yb;yzz pjyf", "Gfhflysq d[jl",
"Dth[yzz pjyf", "D[jl", "D[jl", "Nelf", "Nelf",
"Nelf", "D[jl", "D[jl", "D[jl", "Nelf",
"VFRTN", "VFRTN", "Gjldfk", "Rjhbljh", "Kfp",
"Ddth[", "Ghj[jl", "Ghj[jl", "Dybp", "Buhjdfz",
"Ghj[jl", "Nfqysq ghj[jl", "Ddth[", "Ddth[", "!",
"Ghj[jl", "Ddth[", "Ghj[jl", "Ghj[jl", "Ghj[jl",
"Njgm", "Ktc", "Keu", "Athvf", "Ghjcgtrn",
"Jlt;lf", "Cnfywbz", "Wtynh", "Dth[ybq Ctdthj-.uj-djcnjr", "Yb;ybq >uj-ctdthj-pfgfl",
"Jrhfbyf", "Ljhjuf", "Kf,jhfnjhbz", "Crktg", "Vbh Afynfpbq",
"Cnthdjgfl", "Cnthdjgfl", "Cnelbz Dbyctynf dfy Ujuf", "Rjivfhbz", "Fnnbr",
"Rf,bytn Ytjhnjljrcf", "Cgfkmyz", "Pkjdtybz", "FJPN +Ytuevfyjbl+", "Vfcnthcrfz FJPN +Ytuevfyjbl+",
"Rhfq cdtnf", "Rhtgjcnyjq dfk", "<fiyz", "Re[yz", "Ujcnbyfz",
"Cgfkmyz", "Rf,bytn", "Gthdsq 'nf; [hfybkbof", "Dnjhjq 'nf; [hfybkbof", "Nhtnbq 'nf; [hfybkbof",
"Ldjhtw rjhjkz {m.", "Veptq", "Rjhbljh", "Rjhbljh", "Nhjyysq pfk",
"Jabc", "<fkrjy", "Vfzr", "Cgfkmyz", "Rjvyfnf hfplevbq",
"D[jl", "{ktd", "VJHLS", "YBB"
};
const char *locationDirNotVisited_SP[] = {
"Laboratorio", "Camino", "Exterior", "Bache", "Vest\355bulo del Palacio",
"Puerta", "Pasaje secreto", "Salida", "Salida", "Cosa extra\361a",
"Camino", "Tienda", "Tienda", "Tienda", "Tienda",
"Camino", "Paisaje malificado", "Paisaje malificado", "Entrada", "Entrada",
"Camino", "Camino", "Centro de Loquilandia", "Loquilandia de Abajo", "Entrada a Wacme",
"Loquilandia de arriba", "Entrada", "Entrada", "Camino", "Camino",
"Camino", "Sady's", "Entrada", "Entrada", "Camino",
"OBJETO EXTRA\321O", "OBJETO EXTRA\321O", "Mazmorra", "Vest\355bulo", "Conducto de la ventilaci\363n",
"Planta alta", "Salida", "Salida", "Planta baja", "Sala de entretenimiento",
"Salida", "Pasadizo secreto", "Planta alta", "Planta alta", "Arriba",
"Salida", "Planta alta", "Salida", "Salida", "Salida",
"Ci\351naga", "Bosque", "Pradera", "Tierras", "Calle principal",
"Tienda de disfraces", "Estaci\363n del telecabina", "Centro de Loquilandia", "Norsudeste de Loquilandia de Arriba", "Surnoroeste de Loquilandia de Abajo",
"Camino del interior", "Camino Real ", "Laboratorio de Frankestain", "Crio-Cripta", "Fantasilandia",
"Salto del buitre", "Salto del buitre", "Estudio de Vincent van Gogh ", "Miedilandia", "Atico",
"Despacho del Desortodoncista", "Dormitorio", "Malevolandia", "Robots Inhumanos, S.L.", "Robots Inhumanos, S.L. Taller",
"El fin del mundo", "Murallas del castillo", "Parte alta del castillo", "Cocina", "Sala de estar",
"Dormitorio", "Laboratorio", "Centro de almacenamiento del primer piso", "Centro de almacenamiento del segundo piso", "Centro de almacenamiento del tercer piso",
"Palacio del Rey Hugo", "Sala de trofeos", "Vest\355bulo", "Vest\355bulo", "Sal\363n del trono",
"Oficina", "Balc\363n", "Faro", "Dormitorio", "Sala de reflexi\363n",
"Sady's", "Establo", "Wacme", "Laboratorio"
};
const char *locationDirVisited_EN[] = {
"Lab", "Meadow", "King Hugh's Palace", "Pothole", "Palace Hallway",
"Bedroom", "Cellar", "Trophy Room", "Laboratory", "DUMMY",
"Town Center", "Bakery", "Costume Shop", "Tavern", "Arcade",
"Countryside", "Malevolated Countryside", "Malevolated Countryside", "Entrance", "Entrance",
"Forest", "Shuttle Station", "Central Zanydu", "Lower Zanydu", "Wacme Entrance",
"Upper Zanydu", "Entrance", "Entrance", "Way-Outback", "Wolf Den",
"The Malevolands", "Seedy's", "Robot Maker", "Prison", "The End of the World",
"DUMMY", "DUMMY", "Dungeon", "Climatron Room", "Air Vent",
"First Floor Landing", "Kitchen", "Padded Cell", "Second Floor Landing", "Wrecked Room",
"Knight Hall", "Surveillance Room", "Armory", "Third Floor Landing", "Bathroom",
"Study", "Stairwell", "Fourth Floor Landing", "Ms. Fortune's Lair", "Nefarious's Headquarters",
"Swamp", "Forest", "Meadow", "Farmland", "Main Street",
"Costume Shop", "Shuttle Station", "Inner-Central Middlemost Zanydu", "Upper North-Southeast Zanydu", "Lower South-Northwest Zanydu",
"Way-Outback", "High Road", "Frank's Lab", "Cryo-Crypt", "Fantasyworld",
"Vulture Falls", "Vulture Falls", "Vincent van Gogh's Studio", "Fearworld", "Attic",
"Unorthodontist's Office", "Bedroom", "The Malevolands", "Inhuman Robots, Inc.", "Inhuman Robots, Inc. Workshop",
"The End of the World", "Castle Ramparts", "Castle Top", "Kitchen", "Living Room",
"Bedroom", "Laboratory", "Storage Center First Floor", "Storage Center Second Floor", "Storage Center Third Floor",
"King Hugh's Palace", "Trophy Room", "Hallway", "Hallway", "Throne Room",
"Office", "Balcony", "Lighthouse", "Bedroom", "Hall of Reflection",
"Seedy's", "Barn", "WACME", "Lab"
};
const char *locationDirVisited_FR[] = {
"Labo", "Prairie", "Palais de Hilarius 1er", "Trou", "Hall du Palais",
"Chambre", "Cave", "Salle des Troph\351es", "Laboratoire", "DUMMY",
"Centre ville", "Boulangerie", "Boutique de costumes", "Taverne", "Salle d'arcade",
"Champ", "Champ perfidifi\351", "Champ perfidifi\351", "Etable", "Etable",
"For\352t", "Terminus Navette", "Zanydu-Centre", "Bas-Zanydu", "Entr\351e des 3 Belges",
"Hauts de Zanydu", "Entr\351e", "Entr\351e", "Lointain lointain", "Tani\350re des loups",
"Perfidia", "Bouling", "Faiseur de Robots", "Prison", "Le bout du monde",
"DUMMY", "DUMMY", "Donjon", "Salle du Climatron", "Conduit d'a\351ration",
"Palier 1er \351tage", "Cuisine", "Cellule capiton\351e", "Palier 2\350me \351tage", "Salle de jeux",
"Hall du Chevalier", "Salle de surveillance", "Armurerie", "Palier 3\350me \351tage", "Salle de bains",
"Bureau", "Escalier", "Palier 4\350me \351tage", "Antre de Miss Fortune", "Quartiers g\351n\351raux de N\351farius",
"Mar\351cage", "For\352t", "Prairie", "Champ", "Rue principale",
"Boutique de costumes", "Gare Navette", "Centre du coeur de Zanydu", "Haut-Zanydu Sud-Est du North", "Bas-Zanydu Nord-Ouest du Sud",
"Lointain lointain", "High Road", "Labo de Frank", "Cryo-Crypt", "Fantasyworld",
"Vulture Falls", "Vulture Falls", "Vincent van Gogh's Studio", "Fearworld", "Grenier",
"Unorthodontist's Office", "Chambre", "Perfidia", "Robots Inhumains SARL.", "Robots Inhumains SARL. Atelier",
"La Fin du Monde", "Remparts du Ch\342teau", "Castle Top", "Cuisine", "Salon",
"Chambre", "Laboratoire", "Storage Center First Floor", "Storage Center Second Floor", "Storage Center Third Floor",
"Palais d'Hilarius 1er", "Salle des Troph\351es", "Hall", "Hall", "Salle du Tr\364ne",
"Bureau", "Balcon", "Lighthouse", "Chambre", "Hall of Reflection",
"Bouling", "Grange", "LES 3 BELGES", "Labo"
};
const char *locationDirVisited_DE[] = {
"Labor", "Wiese", "K\366nig Nicks Palast", "Schlagloch", "Palastflur",
"Schlafzimmer", "Keller", "Pokalsaal", "Laboratorium", "DUMMY",
"Stadtmitte", "B\344ckerei", "Kost\374mverleih", "Kneipe", "Spielhalle",
"Landschaft", "\334belierte Landschaft", "\334belierte Landschaft", "Eingang", "Eingang",
"Wald", "Bahnhaltestelle", "Mittel-Trickreich", "Nieder-Trickreich", "Eingang der Fa. Wacme",
"Ober-Trickreich", "Eingang", "Eingang", "Weite W\374ste Wildnis", "Wolfsh\366hle",
"Das \334beland", "Seedys", "Roboterschmied", "Gef\344ngnis", "Das Ende der Welt",
"DUMMY", "DUMMY", "Verlies", "Klimatron-Zimmer", "Luftschacht",
"Treppenabsatz 1. Stock", "K\374che", "Gummizelle", "Treppenabsatz 2. Stock", "Demoliertes Zimmer",
"Rittersaal", "\334berwachungsraum", "Waffenkammer", "Treppenabsatz 3. Stock", "Badezimmer",
"Arbeitszimmer", "Treppenhaus", "Treppenabsatz 4. Stock", "Zimmer von Miss Gunst", "Hauptquartier von Widerlus",
"Sumpf", "Wald", "Wiese", "Ackerland", "Hauptstra\337e",
"Kost\374mverleih", "Bahnhaltestelle", "Zentrum des Inneren Mittel-Trickreichs", "Ober-Nord-S\374dost-Trickreich", "Unteres S\374d-Nordwest-Trickreich",
"Weite W\374ste Wildnis", "Hochstra\337e", "Franks Labor", "K\344lteschlafkammer", "Phantasiawelt",
"Geierf\344lle", "Geierf\344lle", "Vincent van Goghs Studio", "Angstwelt", "Dachboden",
"Praxis des Unorthodontisten", "Schlafzimmer", "Das \334beland", "Unmenschliche Roboter AG", "Unmenschliche Roboter AG - Werkstatt",
"Das Ende der Welt", "Schlo\337w\344lle", "Oberer Teil des Schlosses", "K\374che", "Wohnzimmer",
"Schlafzimmer", "Labor", "Lager 1. Stock", "Lager 2. Stock", "Lager 3. Stock",
"K\366nig Nicks Palast", "Pokalsaal", "Flur", "Flur", "Thronsaal",
"B\374ro", "Balkon", "Leuchtturm", "Schlafzimmer", "Saal der Reflektion",
"Seedys", "Scheune", "WACME", "Labor"
};
const char *locationDirVisited_RU[] = {
"YBB", "Keu", "Ldjhtw rjhjkf {m.", "Hsndbyf", "Dtcnb,.km",
"Cgfkmyz", "Gjuht,", "Veptq", "Rf,bytn", "VFRTN",
"Wtynh", "{kt,", "Jlt;lf", "Rf,fr", "Buhs",
"Lthtdyz", "Bcrjdthrfyyfz ptvkz", "Bcrjdthrfyyfz ptvkz", "D[jl", "D[jl",
"Ktc", "Cnfywbz", "Wtynh", "Yb;yzz pjyf", "Gfhflysq d[jl",
"Dth[yzz pjyf", "D[jl", "D[jl", "Jrhfbyf", "Kjujdj",
"Pkjdtybz", "D[jl", "Hj,jn", "N.hmvf", "Rhfq cdtnf",
"VFRTN", "VFRTN", "Gjldfk", "Rkbvfnhjyyfz", "Kfp",
"Gkjoflrf 1-uj 'nf;f", "Re[yz", "Rfvthf", "Gkjoflrf 2-uj 'nf;f", "Fynbrdfhbfn",
"Hswfhcrfz", "Rjvyfnf j[hfys", "Jhe;bt", "Gkjoflrf 3-uj 'nf;f", "Dfyyfz",
"Jabc", "Rjkjltw", "Gkjoflrf 4-uj 'nf;f", "Yjhf vbcc Ajhneys", "Inf,-rdfhnbhf Ytafhbecf",
"Njgm", "Ktc", "Keu", "Athvf", "Ghjcgtrn",
"Jlt;lf", "Cnfywbz", "Chtlyzz pjyf dyenhtyytuj wtynhf", "Yb;ybq Ctdthj-.uj-djcnjr", "Yb;ybq >uj-ctdthj-pfgfl",
"Jrhfbyf", "Ljhjuf", "Kf,jhfnjhbz", "Crktg", "Vbh Afynfpbq",
"Cnthdjgfl", "Cnthdjgfl", "Cnelbz Dbyctynf dfy Ujuf", "Rjivfhbz", "Fnnbr",
"Rf,bytn Ytjhnjljrcf", "Cgfkmyz", "Pkjdtybz", "FJPN +Ytuevfyjbl+", "Vfcnthcrfz FJPN +Ytuevfyjbl+",
"Rhfq cdtnf", "Rhtgjcnyjq dfk", "<fiyz", "Re[yz", "Ujcnbyfz",
"Cgfkmyz", "Rf,bytn", "Gthdsq 'nf; [hfybkbof", "Dnjhjq 'nf; [hfybkbof", "Nhtnbq 'nf; [hfybkbof",
"Ldjhtw rjhjkz {m.", "Veptq", "Rjhbljh", "Rjhbljh", "Nhjyysq pfk",
"Jabc", "<fkrjy", "Vfzr", "Cgfkmyz", "Rjvyfnf hfplevbq",
"D[jl", "{ktd", "VJHLS", "YBB"
};
const char *locationDirVisited_SP[] = {
"Laboratorio", "Pradera", "Palacio del Rey Hugo", "Bache", "Vest\355bulo del palacio",
"Dormitorio", "S\363tano", "Sala de trofeos", "Laboratorio", "Mu\361eco",
"Centro ciudad", "Panader\355a", "Tienda de disfraces", "Taberna", "Sal\363n de juegos recreativos",
"Paisaje", "Paisaje malificado", "Paisaje malificado", "Entrada", "Entrada",
"Bosque", "Estaci\363n del telecabina", "Centro de Loquilandia", "Loquilandia de Abajo", "Entrada a Wacme",
"Loquilandia de Arriba", "Entrada", "Entrada", "Camino del interior", "Guarida de lobos",
"Malevolandia", "Sady's", "Fabricante de robots", "Prisi\363n", "El fin del mundo",
"Cosa extra\361a", "Cosa extra\361a", "Mazmorra", "Sala del Climatr\363n", "Conducto de ventilaci\363n",
"Descansillo del primer piso", "Cocina", "Jaula de locos", "Descansillo del segundo piso", "Cuarto destrozado",
"Sala del caballero", "Sala de vigilancia", "Sala de blasones", "Descansillo del tercer piso", "Cuarto de ba\361o",
"Estudio", "Escalera", "Descansillo del cuarto piso", "Guarida de Lady Infortunata", "Dependencias de Nefastus",
"Ci\351naga", "Bosque", "Pradera", "Tierras", "Calle principal",
"Tienda de disfraces", "Estaci\363n del telecabina", "Casi medio centro de Loquilandia", "Norsudeste de Loquilandia de Arriba", "Surnoroeste de Loquilandia de Abajo",
"Camino del interior", "Camino Real", "Laboratorio de Frankestain", "Crio-Cripta", "Fantasilandia",
"Salto del buitre", "Salto del buitre", "Estudio de Vincent van Gogh ", "Miedilandia", "Atico",
"Despacho del Desortodoncista", "Dormitorio", "Malevolandia", "Robots Inhumanos, S.L.", "Robots Inhumanos, S.L. Taller",
"El fin del mundo", "Murallas del castillo", "Parte alta del castillo", "Cocina", "Sala de estar",
"Dormitorio", "Laboratorio", "Centro de almacenamiento del primer piso", "Centro de almacenamiento del segundo piso", "Centro de almacenamiento del tercer piso",
"Palacio del Rey Hugo", "Sala de trofeos", "Vest\355bulo", "Vest\355bulo", "Sal\363n del trono",
"Oficina", "Balc\363n", "Faro", "Dormitorio", "Sala de reflexi\363n",
"Sady's", "Establo", "Wacme", "Laboratorio "
};
const char *specialInfoLine_EN[] = { "Exit non defined", "Bottomless Bag", "Flux Wildlie", "Drew Blanc" };
const char *specialInfoLine_FR[] = { "Exit non defined", "Inventaire", "Flux Radieux", "Marc Blanc" };
const char *specialInfoLine_DE[] = { "Exit non defined", "Bodenloser Beutel", "Flux W. Wild", "Mal Block" };
const char *specialInfoLine_RU[] = { "Exit non defined", " Fdjcmrf ", " :bdxbr ", "Lhe <k'yr " };
const char *specialInfoLine_SP[] = { "Exit non defined", "Saco sin fondo", "Flux Tarambana", "Andr\351s Truido" };
// Those are not yet in the DAT file. They'll be added as soon as they are really used.
const char *miscTexts_EN[] = {
"Are you sure you want to exit? (Y/N)",
"Please insert Disc One",
"Please insert Disc Two",
"File %s is missing. Press a key."
};
const char *miscTexts_FR[] = {
"Etes-vous s\373r(e) de vouloir quitter ? (O/N)",
"Ins\351rez le CD 1",
"Ins\351rez le CD 2",
"Le fichier %s est manquant. Appuyez sur une touche."
};
const char *miscTexts_DE[] = {
"Aufh\366ren? Sind Sie sicher? (J/N)",
"Bitte CD 1 einlegen",
"Bitte CD 2 einlegen",
"Datei %s fehlt. Beliebige Taste dr\374cken."
};
const char *miscTexts_RU[] = {
"Are you sure you want to exit? (Y/N)",
"Please insert Disc One",
"Please insert Disc Two",
"File %s is missing. Press a key."
};
const char *miscTexts_SP[] = {
"\277Est\341s seguro de que quieres salir? (S/N)",
"Por favor, inserta el disco 1",
"Por favor, inserta el disco 2",
"El archivo %s no aparece. Pulsa una tecla."
};
const char *endingLine_EN = "Congratulations!!! Hope you enjoyed playing ToonStruck!!";
const char *endingLine_FR = "F\202licitations ! Nous esp\202rons que vous avez aim\202 ToonStruck !";
const char *endingLine_DE = "Herzlichen Gl\201ckwunsch! Wir hoffen, Toonstruck hat Ihnen Spa\341 gemacht!";
const char *endingLine_RU = "Congratulations!!! Hope you enjoyed playing ToonStruck!!";
const char *endingLine_SP = "\255\255Enhorabuena!! \255\255Esperamos que te diviertas jugando a ToonStruck!!";
const char *exitLine_EN = "Hope you enjoyed playing ToonStruck!!";
const char *exitLine_FR = "Nous esp\202rons que vous avez aim\202 jouer \205 ToonStruck !";
const char *exitLine_DE = "Wir hoffen, Toonstruck hat Ihnen Spa\341 gemacht!";
const char *exitLine_RU = "Hope you enjoyed playing ToonStruck!!";
const char* exitLine_SP = "\255\255Esperamos que te diviertas jugando a ToonStruck!!";
#endif