diff options
Diffstat (limited to 'engines')
-rw-r--r-- | engines/kyra/animator_v2.cpp | 139 | ||||
-rw-r--r-- | engines/kyra/kyra_v2.cpp | 143 | ||||
-rw-r--r-- | engines/kyra/kyra_v2.h | 213 | ||||
-rw-r--r-- | engines/kyra/scene_v2.cpp | 223 | ||||
-rw-r--r-- | engines/kyra/screen_v2.cpp | 337 | ||||
-rw-r--r-- | engines/kyra/screen_v2.h | 72 |
6 files changed, 1127 insertions, 0 deletions
diff --git a/engines/kyra/animator_v2.cpp b/engines/kyra/animator_v2.cpp new file mode 100644 index 0000000000..ed2c37dae2 --- /dev/null +++ b/engines/kyra/animator_v2.cpp @@ -0,0 +1,139 @@ +/* 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 "kyra/kyra_v2.h" +#include "kyra/screen.h" +#include "kyra/wsamovie.h" + +#include "common/endian.h" + +namespace Kyra { + +KyraEngine_v2::AnimObj *KyraEngine_v2::initAnimList(AnimObj *list, AnimObj *entry) { + debugC(9, kDebugLevelAnimator, "KyraEngine_v2::initAnimList(%p, %p)", (const void*)list, (const void*)entry); + entry->nextObject = list; + return entry; +} + +KyraEngine_v2::AnimObj *KyraEngine_v2::addToAnimListSorted(AnimObj *list, AnimObj *add) { + debugC(9, kDebugLevelAnimator, "KyraEngine_v2::addToAnimListSorted(%p, %p)", (const void*)list, (const void*)add); + add->nextObject = 0; + + if (!list) + return add; + + if (add->yPos1 <= list->yPos1) { + add->nextObject = list; + return add; + } + + AnimObj *cur = list; + AnimObj *prev = list; + while (add->yPos1 > cur->yPos1) { + AnimObj *temp = cur->nextObject; + if (!temp) + break; + prev = cur; + cur = temp; + } + + if (add->yPos1 <= cur->yPos1) { + prev->nextObject = add; + add->nextObject = cur; + } else { + cur->nextObject = add; + add->nextObject = 0; + } + return list; +} + +KyraEngine_v2::AnimObj *KyraEngine_v2::deleteAnimListEntry(AnimObj *list, AnimObj *entry) { + debugC(9, kDebugLevelAnimator, "KyraEngine_v2::addToAnimListSorted(%p, %p)", (const void*)list, (const void*)entry); + if (!list) + return 0; + + AnimObj *old = 0; + AnimObj *cur = list; + + while (true) { + if (cur == entry) + break; + if (!cur->nextObject) + break; + old = cur; + cur = cur->nextObject; + } + + if (cur != entry) + return list; + + if (cur == list) { + if (!cur->nextObject) + return 0; + cur = cur->nextObject; + return cur; + } + + if (!cur->nextObject) { + if (!old) + return 0; + old->nextObject = 0; + return list; + } + + if (cur != entry) + return list; + + old->nextObject = entry->nextObject; + return list; +} + +void KyraEngine_v2::refreshAnimObjectsIfNeed() { + debugC(9, kDebugLevelAnimator, "KyraEngine_v2::refreshAnimObjectsIfNeed()"); + for (AnimObj *curEntry = _animList; curEntry; curEntry = curEntry->nextObject) { + if (curEntry->enabled && curEntry->needRefresh) { + restorePage3(); + drawAnimObjects(); + refreshAnimObjects(0); + screen()->updateScreen(); + return; + } + } +} + +void KyraEngine_v2::flagAnimObjsForRefresh() { + debugC(9, kDebugLevelAnimator, "KyraEngine_v2::flagAnimObjsForRefresh()"); + for (AnimObj *curEntry = _animList; curEntry; curEntry = curEntry->nextObject) + curEntry->needRefresh = 1; +} + +void KyraEngine_v2::flagAnimObjsSpecialRefresh() { + debugC(9, kDebugLevelAnimator, "KyraEngine_v2::flagAnimObjsSpecialRefresh()"); + for (AnimObj *curEntry = _animList; curEntry; curEntry = curEntry->nextObject) + curEntry->specialRefresh = 1; +} + +} // end of namespace Kyra + diff --git a/engines/kyra/kyra_v2.cpp b/engines/kyra/kyra_v2.cpp new file mode 100644 index 0000000000..2fefd08888 --- /dev/null +++ b/engines/kyra/kyra_v2.cpp @@ -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$ + * + */ + +#include "kyra/kyra_v2.h" +#include "kyra/screen_v2.h" + +namespace Kyra { + +KyraEngine_v2::KyraEngine_v2(OSystem *system, const GameFlags &flags) : KyraEngine(system, flags) { + memset(&_sceneAnims, 0, sizeof(_sceneAnims)); + memset(&_sceneAnimMovie, 0, sizeof(_sceneAnimMovie)); + + _lastProcessedSceneScript = 0; + _specialSceneScriptRunFlag = false; +} + +KyraEngine_v2::~KyraEngine_v2() { + for (ShapeMap::iterator i = _gameShapes.begin(); i != _gameShapes.end(); ++i) { + delete [] i->_value; + i->_value = 0; + } + _gameShapes.clear(); +} + +void KyraEngine_v2::updateInput() { + Common::Event event; + + while (_eventMan->pollEvent(event)) { + switch (event.type) { + case Common::EVENT_QUIT: + _quitFlag = true; + break; + + case Common::EVENT_KEYDOWN: + if (event.kbd.keycode == '.' || event.kbd.keycode == Common::KEYCODE_ESCAPE) + _eventList.push_back(Event(event, true)); + else if (event.kbd.keycode == 'q' && event.kbd.flags == Common::KBD_CTRL) + _quitFlag = true; + else + _eventList.push_back(event); + break; + + case Common::EVENT_LBUTTONDOWN: + _eventList.push_back(Event(event, true)); + break; + + case Common::EVENT_LBUTTONUP: + case Common::EVENT_MOUSEMOVE: + _eventList.push_back(event); + break; + + default: + break; + } + } +} + +void KyraEngine_v2::removeInputTop() { + if (!_eventList.empty()) + _eventList.erase(_eventList.begin()); +} + +bool KyraEngine_v2::skipFlag() const { + for (Common::List<Event>::const_iterator i = _eventList.begin(); i != _eventList.end(); ++i) { + if (i->causedSkip) + return true; + } + return false; +} + +void KyraEngine_v2::resetSkipFlag(bool removeEvent) { + for (Common::List<Event>::iterator i = _eventList.begin(); i != _eventList.end(); ++i) { + if (i->causedSkip) { + if (removeEvent) + _eventList.erase(i); + else + i->causedSkip = false; + return; + } + } +} + +bool KyraEngine_v2::checkSpecialSceneExit(int num, int x, int y) { + if (_specialExitTable[0+num] > x || _specialExitTable[5+num] > y || + _specialExitTable[10+num] < x || _specialExitTable[15+num] < y) + return false; + return true; +} + +void KyraEngine_v2::addShapeToPool(const uint8 *data, int realIndex, int shape) { + debugC(9, kDebugLevelMain, "KyraEngine_v2::addShapeToPool(%p, %d, %d)", data, realIndex, shape); + remShapeFromPool(realIndex); + _gameShapes[realIndex] = screen_v2()->makeShapeCopy(data, shape); + assert(_gameShapes[realIndex]); +} + +void KyraEngine_v2::addShapeToPool(uint8 *shpData, int index) { + debugC(9, kDebugLevelMain, "KyraEngine_v2::addShapeToPool(%p, %d)", shpData, index); + remShapeFromPool(index); + _gameShapes[index] = shpData; + assert(_gameShapes[index]); +} + +void KyraEngine_v2::remShapeFromPool(int idx) { + ShapeMap::iterator iter = _gameShapes.find(idx); + if (iter != _gameShapes.end()) { + delete [] iter->_value; + iter->_value = 0; + } +} + +uint8 *KyraEngine_v2::getShapePtr(int shape) const { + debugC(9, kDebugLevelMain, "KyraEngine_v2::getShapePtr(%d)", shape); + ShapeMap::iterator iter = _gameShapes.find(shape); + if (iter == _gameShapes.end()) + return 0; + return iter->_value; +} + +} // end of namespace Kyra + diff --git a/engines/kyra/kyra_v2.h b/engines/kyra/kyra_v2.h new file mode 100644 index 0000000000..08220123bb --- /dev/null +++ b/engines/kyra/kyra_v2.h @@ -0,0 +1,213 @@ +/* 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 KYRA_KYRA_V2_H +#define KYRA_KYRA_V2_H + +#include "kyra/kyra.h" +#include "kyra/gui.h" +#include "kyra/wsamovie.h" + +#include "common/list.h" +#include "common/hashmap.h" + +namespace Kyra { + +class Screen_v2; + +class KyraEngine_v2 : public KyraEngine { +friend class Debugger_v2; +public: + KyraEngine_v2(OSystem *system, const GameFlags &flags); + ~KyraEngine_v2(); + + virtual Screen_v2 *screen_v2() const = 0; +protected: + // run + virtual void update() = 0; + virtual void updateWithText() = 0; + + // MainMenu + MainMenu *_menu; + + // Input + virtual int checkInput(Button *buttonList, bool mainLoop = false) = 0; + + void updateInput(); + void removeInputTop(); + + int _mouseX, _mouseY; + + struct Event { + Common::Event event; + bool causedSkip; + + Event() : event(), causedSkip(false) {} + Event(Common::Event e) : event(e), causedSkip(false) {} + Event(Common::Event e, bool skip) : event(e), causedSkip(skip) {} + + operator Common::Event() const { return event; } + }; + Common::List<Event> _eventList; + + bool skipFlag() const; + void resetSkipFlag(bool removeEvent = true); + + // Animator + struct AnimObj { + uint16 index; + uint16 type; + uint16 enabled; + uint16 needRefresh; + uint16 specialRefresh; + uint16 animFlags; + uint16 flags; + int16 xPos1, yPos1; + uint8 *shapePtr; + uint16 shapeIndex1; + uint16 animNum; + uint16 shapeIndex3; + uint16 shapeIndex2; + int16 xPos2, yPos2; + int16 xPos3, yPos3; + int16 width, height; + int16 width2, height2; + uint16 palette; + AnimObj *nextObject; + }; + + bool _drawNoShapeFlag; + AnimObj *_animList; + + AnimObj *initAnimList(AnimObj *list, AnimObj *entry); + AnimObj *addToAnimListSorted(AnimObj *list, AnimObj *entry); + AnimObj *deleteAnimListEntry(AnimObj *list, AnimObj *entry); + + virtual void refreshAnimObjects(int force) = 0; + void refreshAnimObjectsIfNeed(); + + void flagAnimObjsSpecialRefresh(); + void flagAnimObjsForRefresh(); + + virtual void clearAnimObjects() = 0; + + virtual void drawAnimObjects() = 0; + virtual void drawSceneAnimObject(AnimObj *obj, int x, int y, int drawLayer) = 0; + virtual void drawCharacterAnimObject(AnimObj *obj, int x, int y, int drawLayer) = 0; + + virtual void updateCharacterAnim(int) = 0; + virtual void updateSceneAnim(int anim, int newFrame) = 0; + + virtual void addItemToAnimList(int item) = 0; + virtual void deleteItemAnimEntry(int item) = 0; + + virtual void setCharacterAnimDim(int w, int h) = 0; + virtual void resetCharacterAnimDim() = 0; + + // Scene + struct SceneDesc { + char filename1[10]; + char filename2[10]; + + uint16 exit1, exit2, exit3, exit4; + uint8 flags; + uint8 sound; + }; + + SceneDesc *_sceneList; + int _sceneListSize; + uint16 _currentScene; + + uint16 _sceneExit1, _sceneExit2, _sceneExit3, _sceneExit4; + int _sceneEnterX1, _sceneEnterY1, _sceneEnterX2, _sceneEnterY2, + _sceneEnterX3, _sceneEnterY3, _sceneEnterX4, _sceneEnterY4; + int _specialExitCount; + uint16 _specialExitTable[25]; + bool checkSpecialSceneExit(int num, int x, int y); + + bool _overwriteSceneFacing; + + virtual void enterNewScene(uint16 newScene, int facing, int unk1, int unk2, int unk3) = 0; + + // Animation + virtual void restorePage3() = 0; + + struct SceneAnim { + uint16 flags; + int16 x, y; + int16 x2, y2; + int16 width, height; + uint16 specialSize; + int16 shapeIndex; + uint16 wsaFlag; + char filename[14]; + }; + + SceneAnim _sceneAnims[16]; + WSAMovieV2 *_sceneAnimMovie[16]; + + void freeSceneAnims(); + + bool _specialSceneScriptState[10]; + bool _specialSceneScriptStateBackup[10]; + EMCState _sceneSpecialScripts[10]; + uint32 _sceneSpecialScriptsTimer[10]; + int _lastProcessedSceneScript; + bool _specialSceneScriptRunFlag; + + void updateSpecialSceneScripts(); + virtual int getFirstSpecialSceneScript() const = 0; + + // Shapes + typedef Common::HashMap<int, uint8*> ShapeMap; + ShapeMap _gameShapes; + + uint8 *getShapePtr(int index) const; + void addShapeToPool(const uint8 *data, int realIndex, int shape); + void addShapeToPool(uint8 *shpData, int index); + void remShapeFromPool(int idx); + + // pathfinder + int _movFacingTable[600]; + int _pathfinderFlag; + + int findWay(int curX, int curY, int dstX, int dstY, int *moveTable, int moveTableSize); + + bool directLinePassable(int x, int y, int toX, int toY); + + int pathfinderInitPositionTable(int *moveTable); + int pathfinderAddToPositionTable(int index, int v1, int v2); + int pathfinderInitPositionIndexTable(int tableLen, int x, int y); + int pathfinderAddToPositionIndexTable(int index, int v); + void pathfinderFinializePath(int *moveTable, int unk1, int x, int y, int moveTableSize); + + int _pathfinderPositionTable[400]; + int _pathfinderPositionIndexTable[200]; +}; + +} // end of namespace Kyra + +#endif + diff --git a/engines/kyra/scene_v2.cpp b/engines/kyra/scene_v2.cpp new file mode 100644 index 0000000000..aa54b5c470 --- /dev/null +++ b/engines/kyra/scene_v2.cpp @@ -0,0 +1,223 @@ +/* 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 "kyra/kyra_v2.h" +#include "kyra/screen.h" + +namespace Kyra { + +void KyraEngine_v2::freeSceneAnims() { + debugC(9, kDebugLevelMain, "KyraEngine_v2::freeSceneAnims()"); + + for (int i = 0; i < ARRAYSIZE(_sceneAnims); ++i) + _sceneAnims[i].flags = 0; + + for (int i = 0; i < ARRAYSIZE(_sceneAnimMovie); ++i) { + if (_sceneAnimMovie[i]) + _sceneAnimMovie[i]->close(); + } +} + +void KyraEngine_v2::updateSpecialSceneScripts() { + debugC(9, kDebugLevelMain, "KyraEngine_v2::updateSpecialSceneScripts()"); + uint32 nextTime = _system->getMillis() + _tickLength; + const int startScript = _lastProcessedSceneScript; + + while (_system->getMillis() <= nextTime) { + if (_sceneSpecialScriptsTimer[_lastProcessedSceneScript] <= _system->getMillis() && + !_specialSceneScriptState[_lastProcessedSceneScript]) { + _specialSceneScriptRunFlag = true; + + while (_specialSceneScriptRunFlag && _sceneSpecialScriptsTimer[_lastProcessedSceneScript] <= _system->getMillis()) { + if (!_emc->run(&_sceneSpecialScripts[_lastProcessedSceneScript])) + _specialSceneScriptRunFlag = false; + } + } + + if (!_emc->isValid(&_sceneSpecialScripts[_lastProcessedSceneScript])) { + _emc->start(&_sceneSpecialScripts[_lastProcessedSceneScript], getFirstSpecialSceneScript()+_lastProcessedSceneScript); + _specialSceneScriptRunFlag = false; + } + + ++_lastProcessedSceneScript; + if (_lastProcessedSceneScript >= 10) + _lastProcessedSceneScript = 0; + + if (_lastProcessedSceneScript == startScript) + return; + } +} + +int KyraEngine_v2::findWay(int x, int y, int toX, int toY, int *moveTable, int moveTableSize) { + debugC(9, kDebugLevelMain, "KyraEngine_v2::findWay(%d, %d, %d, %d, %p, %d)", x, y, toX, toY, (const void *)moveTable, moveTableSize); + x &= ~3; toX &= ~3; + y &= ~1; toY &= ~1; + int size = KyraEngine::findWay(x, y, toX, toY, moveTable, moveTableSize); + static bool usePostProcess = false; + if (size && !usePostProcess) { + usePostProcess = true; + int temp = pathfinderInitPositionTable(moveTable); + temp = pathfinderInitPositionIndexTable(temp, x, y); + pathfinderFinializePath(moveTable, temp, x, y, moveTableSize); + usePostProcess = false; + } + return usePostProcess ? size : getMoveTableSize(moveTable); +} + +bool KyraEngine_v2::directLinePassable(int x, int y, int toX, int toY) { + debugC(9, kDebugLevelMain, "KyraEngine_v2::directLinePassable(%d, %d, %d, %d)", x, y, toX, toY); + Screen *scr = screen(); + + while (x != toX && y != toY) { + int facing = getFacingFromPointToPoint(x, y, toX, toY); + x += _addXPosTable[facing]; + y += _addYPosTable[facing]; + if (!scr->getShapeFlag1(x, y)) + return false; + } + return true; +} + +int KyraEngine_v2::pathfinderInitPositionTable(int *moveTable) { + debugC(9, kDebugLevelMain, "KyraEngine_v2::pathfinderInitPositionTable(%p)", (const void*)moveTable); + bool breakLoop = false; + int *moveTableCur = moveTable; + int oldEntry = *moveTableCur, curEntry = *moveTableCur; + int oldX = 0, newX = 0, oldY = 0, newY = 0; + int lastEntry = 0; + lastEntry = pathfinderAddToPositionTable(lastEntry, 0, 0); + + while (*moveTableCur != 8) { + oldEntry = curEntry; + + while (true) { + curEntry = *moveTableCur; + if (curEntry >= 0 && curEntry <= 7) + break; + + if (curEntry == 8) { + breakLoop = true; + break; + } else { + ++moveTableCur; + } + } + + if (breakLoop) + break; + + oldX = newX; + oldY = newY; + + newX += _addXPosTable[curEntry]; + newY += _addYPosTable[curEntry]; + + int temp = ABS(curEntry - oldEntry); + if (temp > 4) { + temp = 8 - temp; + } + + if (temp > 1 || oldEntry != curEntry) + lastEntry = pathfinderAddToPositionTable(lastEntry, oldX, oldY); + + ++moveTableCur; + } + + lastEntry = pathfinderAddToPositionTable(lastEntry, newX, newY); + _pathfinderPositionTable[lastEntry*2+0] = -1; + _pathfinderPositionTable[lastEntry*2+1] = -1; + return lastEntry; +} + +int KyraEngine_v2::pathfinderAddToPositionTable(int index, int v1, int v2) { + debugC(9, kDebugLevelMain, "KyraEngine_v2::pathfinderAddToPositionTable(%d, %d, %d)", index, v1, v2); + _pathfinderPositionTable[index<<1] = v1; + _pathfinderPositionTable[(index<<1)+1] = v2; + ++index; + if (index >= 199) + --index; + return index; +} + +int KyraEngine_v2::pathfinderInitPositionIndexTable(int tableLen, int x, int y) { + debugC(9, kDebugLevelMain, "KyraEngine_v2::pathfinderInitPositionIndexTable(%d, %d, %d)", tableLen, x, y); + int x1 = 0, y1 = 0; + int x2 = 0, y2 = 0; + int lastEntry = 0; + int index2 = tableLen-1, index1 = 0; + while (index2 > index1) { + x1 = _pathfinderPositionTable[index1*2+0] + x; + y1 = _pathfinderPositionTable[index1*2+1] + y; + x2 = _pathfinderPositionTable[index2*2+0] + x; + y2 = _pathfinderPositionTable[index2*2+1] + y; + + if (directLinePassable(x1, y1, x2, y2)) { + lastEntry = pathfinderAddToPositionIndexTable(lastEntry, index2); + if (tableLen-1 == index2) + break; + index1 = index2; + index2 = tableLen-1; + } else if (index1+1 == index2) { + lastEntry = pathfinderAddToPositionIndexTable(lastEntry, index2); + index1 = index2; + index2 = tableLen-1; + } else { + --index2; + } + } + return lastEntry; +} + +int KyraEngine_v2::pathfinderAddToPositionIndexTable(int index, int v) { + debugC(9, kDebugLevelMain, "KyraEngine_v2::pathfinderAddToPositionIndexTable(%d, %d)", index, v); + _pathfinderPositionIndexTable[index] = v; + ++index; + if (index >= 199) + --index; + return index; +} + +void KyraEngine_v2::pathfinderFinializePath(int *moveTable, int tableLen, int x, int y, int moveTableSize) { + debugC(9, kDebugLevelMain, "KyraEngine_v2::pathfinderFinializePath(%p, %d, %d, %d, %d)", (void *)moveTable, tableLen, x, y, moveTableSize); + int x1 = 0, y1 = 0; + int x2 = 0, y2 = 0; + int index1 = 0, index2 = 0; + int sizeLeft = moveTableSize; + for (int i = 0; i < tableLen; ++i) { + index2 = _pathfinderPositionIndexTable[i]; + x1 = _pathfinderPositionTable[index1*2+0] + x; + y1 = _pathfinderPositionTable[index1*2+1] + y; + x2 = _pathfinderPositionTable[index2*2+0] + x; + y2 = _pathfinderPositionTable[index2*2+1] + y; + + int wayLen = findWay(x1, y1, x2, y2, moveTable, sizeLeft); + moveTable += wayLen; + sizeLeft -= wayLen; // unlike the original we want to be sure that the size left is correct + index1 = index2; + } +} + +} // end of namespace Kyra + diff --git a/engines/kyra/screen_v2.cpp b/engines/kyra/screen_v2.cpp new file mode 100644 index 0000000000..704296c534 --- /dev/null +++ b/engines/kyra/screen_v2.cpp @@ -0,0 +1,337 @@ +/* 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 "kyra/screen_v2.h" + +#include "common/endian.h" + +namespace Kyra { + +uint8 *Screen_v2::generateOverlay(const uint8 *palette, uint8 *buffer, int startColor, uint16 factor) { + if (!palette || !buffer) + return buffer; + + factor = MIN<uint16>(255, factor); + factor >>= 1; + factor &= 0xFF; + + const byte col1 = palette[startColor * 3 + 0]; + const byte col2 = palette[startColor * 3 + 1]; + const byte col3 = palette[startColor * 3 + 2]; + + uint8 *dst = buffer; + *dst++ = 0; + + for (int i = 1; i != 255; ++i) { + uint8 processedPalette[3]; + const uint8 *src = palette + i*3; + byte col; + + col = *src++; + col -= ((((col - col1) * factor) << 1) >> 8) & 0xFF; + processedPalette[0] = col; + + col = *src++; + col -= ((((col - col2) * factor) << 1) >> 8) & 0xFF; + processedPalette[1] = col; + + col = *src++; + col -= ((((col - col3) * factor) << 1) >> 8) & 0xFF; + processedPalette[2] = col; + + *dst++ = findLeastDifferentColor(processedPalette, palette+3, 255)+1; + } + + return buffer; +} + +void Screen_v2::applyOverlay(int x, int y, int w, int h, int pageNum, const uint8 *overlay) { + if (pageNum == 0 || pageNum == 1) + addDirtyRect(x, y, w, h); + + uint8 *dst = getPagePtr(pageNum) + y * 320 + x; + while (h--) { + for (int wi = 0; wi < w; ++wi) { + uint8 index = *dst; + *dst++ = overlay[index]; + } + dst += 320 - w; + } +} + +int Screen_v2::findLeastDifferentColor(const uint8 *paletteEntry, const uint8 *palette, uint16 numColors) { + int m = 0x7fff; + int r = 0x101; + + for (int i = 0; i < numColors; i++) { + int v = paletteEntry[0] - *palette++; + int c = v * v; + v = paletteEntry[1] - *palette++; + c += (v * v); + v = paletteEntry[2] - *palette++; + c += (v * v); + + if (c <= m) { + m = c; + r = i; + } + } + + return r; +} + +void Screen_v2::copyWsaRect(int x, int y, int w, int h, int dimState, int plotFunc, const uint8 *src, + int unk1, const uint8 *unkPtr1, const uint8 *unkPtr2) { + uint8 *dstPtr = getPagePtr(_curPage); + uint8 *origDst = dstPtr; + + const ScreenDim *dim = getScreenDim(dimState); + int dimX1 = dim->sx << 3; + int dimX2 = dim->w << 3; + dimX2 += dimX1; + + int dimY1 = dim->sy; + int dimY2 = dim->h; + dimY2 += dimY1; + + int temp = y - dimY1; + if (temp < 0) { + if ((temp += h) <= 0) + return; + else { + SWAP(temp, h); + y += temp - h; + src += (temp - h) * w; + } + } + + temp = dimY2 - y; + if (temp <= 0) + return; + + if (temp < h) + h = temp; + + int srcOffset = 0; + temp = x - dimX1; + if (temp < 0) { + temp = -temp; + srcOffset = temp; + x += temp; + w -= temp; + } + + int srcAdd = 0; + + temp = dimX2 - x; + if (temp <= 0) + return; + + if (temp < w) { + SWAP(w, temp); + temp -= w; + srcAdd = temp; + } + + dstPtr += y * SCREEN_W + x; + uint8 *dst = dstPtr; + + if (_curPage == 0 || _curPage == 1) + addDirtyRect(x, y, w, h); + + clearOverlayRect(_curPage, x, y, w, h); + + temp = h; + int curY = y; + while (h--) { + src += srcOffset; + ++curY; + int cW = w; + + switch (plotFunc) { + case 0: + memcpy(dst, src, cW); + dst += cW; src += cW; + break; + + case 1: + while (cW--) { + uint8 d = *src++; + uint8 t = unkPtr1[d]; + if (t != 0xFF) + d = unkPtr2[*dst + (t << 8)]; + *dst++ = d; + } + break; + + case 4: + while (cW--) { + uint8 d = *src++; + if (d) + *dst = d; + ++dst; + } + break; + + case 5: + while (cW--) { + uint8 d = *src++; + if (d) { + uint8 t = unkPtr1[d]; + if (t != 0xFF) + d = unkPtr2[*dst + (t << 8)]; + *dst = d; + } + ++dst; + } + break; + + case 8: + case 9: + while (cW--) { + uint8 d = *src++; + uint8 t = _shapePages[0][dst - origDst] & 7; + if (unk1 < t && (curY > _maskMinY && curY < _maskMaxY)) + d = _shapePages[1][dst - origDst]; + *dst++ = d; + } + break; + + case 12: + case 13: + while (cW--) { + uint8 d = *src++; + if (d) { + uint8 t = _shapePages[0][dst - origDst] & 7; + if (unk1 < t && (curY > _maskMinY && curY < _maskMaxY)) + d = _shapePages[1][dst - origDst]; + *dst++ = d; + } else { + d = _shapePages[1][dst - origDst]; + *dst++ = d; + } + } + break; + + default: + break; + } + + dst = (dstPtr += SCREEN_W); + src += srcAdd; + } +} + +const uint8 *Screen_v2::getPtrToShape(const uint8 *shpFile, int shape) { + debugC(9, kDebugLevelScreen, "Screen_v2::getPtrToShape(%p, %d)", (const void *)shpFile, shape); + uint16 shapes = READ_LE_UINT16(shpFile); + + if (shapes <= shape) + return 0; + + uint32 offset = READ_LE_UINT32(shpFile + (shape << 2) + 2); + + return shpFile + offset + 2; +} + +uint8 *Screen_v2::getPtrToShape(uint8 *shpFile, int shape) { + debugC(9, kDebugLevelScreen, "Screen_v2::getPtrToShape(%p, %d)", (void *)shpFile, shape); + uint16 shapes = READ_LE_UINT16(shpFile); + + if (shapes <= shape) + return 0; + + uint32 offset = READ_LE_UINT32(shpFile + (shape << 2) + 2); + + return shpFile + offset + 2; +} + +int Screen_v2::getShapeScaledWidth(const uint8 *shpFile, int scale) { + debugC(9, kDebugLevelScreen, "Screen_v2::getShapeScaledWidth(%p, %d)", (const void*)shpFile, scale); + int width = READ_LE_UINT16(shpFile+3); + return (width * scale) >> 8; +} + +int Screen_v2::getShapeScaledHeight(const uint8 *shpFile, int scale) { + debugC(9, kDebugLevelScreen, "Screen_v2::getShapeScaledHeight(%p, %d)", (const void*)shpFile, scale); + int height = shpFile[2]; + return (height * scale) >> 8; +} + +uint16 Screen_v2::getShapeSize(const uint8 *shp) { + debugC(9, kDebugLevelScreen, "Screen_v2::getShapeSize(%p)", (const void *)shp); + + return READ_LE_UINT16(shp+6); +} + +uint8 *Screen_v2::makeShapeCopy(const uint8 *src, int index) { + debugC(9, kDebugLevelScreen, "Screen_v2::makeShapeCopy(%p, %d)", (const void *)src, index); + + const uint8 *shape = getPtrToShape(src, index); + int size = getShapeSize(shape); + + uint8 *copy = new uint8[size]; + assert(copy); + memcpy(copy, shape, size); + + return copy; +} + +int Screen_v2::getLayer(int x, int y) { + debugC(9, kDebugLevelScreen, "Screen_v2::getLayer(%d, %d)", x, y); + if (x < 0) + x = 0; + else if (x >= 320) + x = 319; + if (y < 0) + y = 0; + else if (y >= 144) + y = 143; + + uint8 pixel = *(getCPagePtr(5) + y * 320 + x); + pixel &= 0x7F; + pixel >>= 3; + + if (pixel < 1) + pixel = 1; + else if (pixel > 15) + pixel = 15; + return pixel; +} + +int Screen_v2::getRectSize(int w, int h) { + debugC(9, kDebugLevelScreen, "Screen_v2::getRectSize(%d, %d)", w, h); + if (w > 320 || h > 200) + return 0; + return w*h; +} + +void Screen_v2::setTextColorMap(const uint8 *cmap) { + debugC(9, kDebugLevelScreen, "Screen_v2::setTextColorMap(%p)", (const void *)cmap); + setTextColor(cmap, 0, 15); +} + +} // end of namespace Kyra + diff --git a/engines/kyra/screen_v2.h b/engines/kyra/screen_v2.h new file mode 100644 index 0000000000..5679dadf39 --- /dev/null +++ b/engines/kyra/screen_v2.h @@ -0,0 +1,72 @@ +/* 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 KYRA_SCREEN_V2_H +#define KYRA_SCREEN_V2_H + +#include "kyra/screen.h" +#include "kyra/kyra_v2.h" + +namespace Kyra { + +class Screen_v2 : public Screen { +public: + Screen_v2(KyraEngine *vm, OSystem *system) : Screen(vm, system) {} + + // screen page handling + void copyWsaRect(int x, int y, int w, int h, int dimState, int plotFunc, const uint8 *src, + int unk1, const uint8 *unkPtr1, const uint8 *unkPtr2); + + // palette handling + uint8 *generateOverlay(const uint8 *palette, uint8 *buffer, int color, uint16 factor); + void applyOverlay(int x, int y, int w, int h, int pageNum, const uint8 *overlay); + int findLeastDifferentColor(const uint8 *paletteEntry, const uint8 *palette, uint16 numColors); + + // shape handling + uint8 *getPtrToShape(uint8 *shpFile, int shape); + const uint8 *getPtrToShape(const uint8 *shpFile, int shape); + + int getShapeScaledWidth(const uint8 *shpFile, int scale); + int getShapeScaledHeight(const uint8 *shpFile, int scale); + + uint16 getShapeSize(const uint8 *shp); + + uint8 *makeShapeCopy(const uint8 *src, int index); + + // rect handling + int getRectSize(int w, int h); + + // text display + void setTextColorMap(const uint8 *cmap); + + // layer handling + virtual int getLayer(int x, int y); +protected: +}; + +} // end of namespace Kyra + +#endif + |