aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/neverhood/entity.h7
-rw-r--r--engines/neverhood/gamemodule.cpp2
-rw-r--r--engines/neverhood/graphics.cpp18
-rw-r--r--engines/neverhood/graphics.h22
-rw-r--r--engines/neverhood/module.mk4
-rw-r--r--engines/neverhood/neverhood.cpp2
-rw-r--r--engines/neverhood/resource.cpp2
-rw-r--r--engines/neverhood/resource.h5
-rw-r--r--engines/neverhood/scene.cpp307
-rw-r--r--engines/neverhood/scene.h100
-rw-r--r--engines/neverhood/sprite.cpp179
-rw-r--r--engines/neverhood/sprite.h90
12 files changed, 708 insertions, 30 deletions
diff --git a/engines/neverhood/entity.h b/engines/neverhood/entity.h
index fe5d07e585..bbe67a187c 100644
--- a/engines/neverhood/entity.h
+++ b/engines/neverhood/entity.h
@@ -24,15 +24,18 @@
#define NEVERHOOD_ENTITY_H
#include "neverhood/neverhood.h"
+#include "neverhood/graphics.h"
namespace Neverhood {
struct MessageParam {
union {
uint32 _integer;
+ NPoint _point;
// TODO: Other types...
};
MessageParam(uint32 value) { _integer = value; }
+ MessageParam(NPoint value) { _point = value; }
// TODO: Constructors for the param types...
};
@@ -60,6 +63,10 @@ public:
uint32 sendMessage(int messageNum, uint32 param, Entity *sender) {
return sendMessage(messageNum, MessageParam(param), sender);
}
+ uint32 sendMessage(int messageNum, NPoint param, Entity *sender) {
+ return sendMessage(messageNum, MessageParam(param), sender);
+ }
+ int getPriority() const { return _priority; }
protected:
void (Entity::*_updateHandlerCb)();
uint32 (Entity::*_messageHandlerCb)(int messageNum, const MessageParam &param, Entity *sender);
diff --git a/engines/neverhood/gamemodule.cpp b/engines/neverhood/gamemodule.cpp
index 887ff3d37a..09046cfa3e 100644
--- a/engines/neverhood/gamemodule.cpp
+++ b/engines/neverhood/gamemodule.cpp
@@ -29,7 +29,7 @@ GameModule::GameModule(NeverhoodEngine *vm)
// Other initializations moved to actual engine class
- // TODO .text:0048AD96
+ // TODO
// TODO Sound1ChList_sub_407F70(0x2D0031, 0x8861079);
diff --git a/engines/neverhood/graphics.cpp b/engines/neverhood/graphics.cpp
index 315c62dbec..d7c1064948 100644
--- a/engines/neverhood/graphics.cpp
+++ b/engines/neverhood/graphics.cpp
@@ -61,8 +61,8 @@ void BaseSurface::clear() {
}
void BaseSurface::drawSpriteResource(SpriteResource &spriteResource) {
- if (spriteResource.dimensions().width <= _drawRect.width &&
- spriteResource.dimensions().height <= _drawRect.height) {
+ if (spriteResource.getDimensions().width <= _drawRect.width &&
+ spriteResource.getDimensions().height <= _drawRect.height) {
clear();
spriteResource.draw((byte*)_surface->pixels, _surface->pitch, false, false);
}
@@ -70,7 +70,7 @@ void BaseSurface::drawSpriteResource(SpriteResource &spriteResource) {
// Misc
-void parseBitmapResource(byte *sprite, bool *rle, NDimensions *dimensions, NUnknown *unknown, byte **palette, byte **pixels) {
+void parseBitmapResource(byte *sprite, bool *rle, NDimensions *dimensions, NPoint *position, byte **palette, byte **pixels) {
uint16 flags;
@@ -92,14 +92,14 @@ void parseBitmapResource(byte *sprite, bool *rle, NDimensions *dimensions, NUnkn
}
if (flags & 4) {
- if (unknown) {
- unknown->unk1 = READ_LE_UINT16(sprite);
- unknown->unk2 = READ_LE_UINT16(sprite + 2);
+ if (position) {
+ position->x = READ_LE_UINT16(sprite);
+ position->y = READ_LE_UINT16(sprite + 2);
}
sprite += 4;
- } else if (unknown) {
- unknown->unk1 = 0;
- unknown->unk2 = 0;
+ } else if (position) {
+ position->x = 0;
+ position->y = 0;
}
if (flags & 8) {
diff --git a/engines/neverhood/graphics.h b/engines/neverhood/graphics.h
index 27ef6cdee6..68ff84dc25 100644
--- a/engines/neverhood/graphics.h
+++ b/engines/neverhood/graphics.h
@@ -30,12 +30,12 @@
namespace Neverhood {
-struct NDimensions {
- int16 width, height;
+struct NPoint {
+ int16 x, y;
};
-struct NUnknown {
- int16 unk1, unk2;
+struct NDimensions {
+ int16 width, height;
};
struct NRect {
@@ -60,6 +60,8 @@ public:
virtual void addDirtyRect();
void clear();
void drawSpriteResource(SpriteResource &spriteResource);
+ int getPriority() const { return _priority; }
+ void setPriority(int priority) { _priority = priority; }
protected:
NeverhoodEngine *_vm;
int _priority;
@@ -70,19 +72,9 @@ protected:
NRect _clipRect;
};
-/*
-class Palette {
-public:
- Palette();
- ~Palette();
-protected:
-
-};
-*/
-
// Misc
-void parseBitmapResource(byte *sprite, bool *rle, NDimensions *dimensions, NUnknown *unknown, byte **palette, byte **pixels);
+void parseBitmapResource(byte *sprite, bool *rle, NDimensions *dimensions, NPoint *position, byte **palette, byte **pixels);
void unpackSpriteRle(byte *source, int width, int height, byte *dest, int destPitch, bool flipX, bool flipY);
void unpackSpriteNormal(byte *source, int width, int height, byte *dest, int destPitch, bool flipX, bool flipY);
diff --git a/engines/neverhood/module.mk b/engines/neverhood/module.mk
index 97ad70e654..709538e565 100644
--- a/engines/neverhood/module.mk
+++ b/engines/neverhood/module.mk
@@ -11,7 +11,9 @@ MODULE_OBJS = \
neverhood.o \
palette.o \
resource.o \
- resourceman.o
+ resourceman.o \
+ scene.o \
+ sprite.o
# This module can be built as a plugin
ifdef BUILD_PLUGINS
diff --git a/engines/neverhood/neverhood.cpp b/engines/neverhood/neverhood.cpp
index f7bf0327d4..d4418cb8cd 100644
--- a/engines/neverhood/neverhood.cpp
+++ b/engines/neverhood/neverhood.cpp
@@ -117,7 +117,7 @@ Common::Error NeverhoodEngine::run() {
SpriteResource r(this);
BaseSurface *surf = new BaseSurface(this, 0, 640, 480);
r.load(0x0CA04202);
- debug("r: width = %d; height = %d", r.dimensions().width, r.dimensions().height);
+ debug("r: width = %d; height = %d", r.getDimensions().width, r.getDimensions().height);
surf->drawSpriteResource(r);
delete surf;
}
diff --git a/engines/neverhood/resource.cpp b/engines/neverhood/resource.cpp
index 2dd919c087..4dcbd838fe 100644
--- a/engines/neverhood/resource.cpp
+++ b/engines/neverhood/resource.cpp
@@ -66,7 +66,7 @@ bool SpriteResource::load2(uint32 fileHash) {
if (_resourceHandle != -1) {
if (_vm->_res->getResourceType(_resourceHandle) == 2) {
byte *spriteData = _vm->_res->loadResource(_resourceHandle, true);
- parseBitmapResource(spriteData, &_rle, &_dimensions, &_unknown, NULL, &_pixels);
+ parseBitmapResource(spriteData, &_rle, &_dimensions, &_position, NULL, &_pixels);
} else {
_vm->_res->unuseResource(_resourceHandle);
_resourceHandle = -1;
diff --git a/engines/neverhood/resource.h b/engines/neverhood/resource.h
index 7f699c54df..5a30d1292d 100644
--- a/engines/neverhood/resource.h
+++ b/engines/neverhood/resource.h
@@ -36,12 +36,13 @@ public:
bool load(uint32 fileHash);
bool load2(uint32 fileHash);
void unload();
- const NDimensions& dimensions() { return _dimensions; };
+ const NDimensions& getDimensions() { return _dimensions; }
+ const NPoint& getPosition() { return _position; }
protected:
NeverhoodEngine *_vm;
int _resourceHandle;
NDimensions _dimensions;
- NUnknown _unknown;
+ NPoint _position;
byte *_pixels;
bool _rle;
};
diff --git a/engines/neverhood/scene.cpp b/engines/neverhood/scene.cpp
new file mode 100644
index 0000000000..ccdae3a287
--- /dev/null
+++ b/engines/neverhood/scene.cpp
@@ -0,0 +1,307 @@
+/* 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.
+ *
+ */
+
+#include "neverhood/scene.h"
+
+namespace Neverhood {
+
+Scene::Scene(NeverhoodEngine *vm, Module *parentModule, bool clearHitRects)
+ : Entity(vm, 0), _parentModule(parentModule) {
+
+ _messageListFlag1 = false;
+ _systemCallbackFlag = false;
+ _messageList = NULL;
+ // TODO _rectType = 0;
+ _mouseClickPos.x = 0;
+ _mouseClickPos.y = 0;
+ _mouseClicked = false;
+ // TODO _rectList = NULL;
+ // TODO _someRects = NULL;
+ // TODO _playerSprite = NULL;
+ // TODO _mouseSprite = NULL;
+ _palette = NULL;
+ // TODO _class300 = NULL;
+ // TODO _field_8E = -1;
+ if (clearHitRects) {
+ // TODO g_Class700->setHitRects(NULL, 0);
+ // TODO g_Class700->clear();
+ }
+ // TODO g_screen->setFps(24);
+ // TODO g_screen->hSmack = NULL;
+ // TODO g_screen->field_24 = 0;
+ // TODO g_screen->field_26 = 0;
+ // TODO g_screen->resetDirtyRects();
+ _messageListFlag = true;
+ _surfaceFlag = false;
+ _messageList2 = NULL;
+ // TODO _smackerPlayer = NULL;
+ _smkFileHash = 0;
+ _messageListFlag2 = false;
+ _messageValue = -1;
+
+ SetUpdateHandler(&Scene::update);
+ SetMessageHandler(&Scene::handleMessage);
+}
+
+Scene::~Scene() {
+
+ if (_palette) {
+ removeEntity(_palette);
+ delete _palette;
+ }
+
+ // Delete all entities
+ for (Common::Array<Entity*>::iterator iter = _entities.begin(); iter != _entities.end(); iter++)
+ delete *iter;
+
+ // Don't delete surfaces since they always belong to an entity
+
+}
+
+void Scene::draw() {
+ //**ALL TODO
+#if 0
+ if (_smackerPlayer) {
+ if (_surfaceFlag) {
+ g_screen->resetDirtyRects();
+ g_screen->copyDirtyRects();
+ g_screen->addDirtyRects();
+ }
+ _smackerPlayer->_surface->draw();
+ } else {
+ if (_surfaceFlag) {
+ g_screen->copyDirtyRects();
+ for (Common::Array<BaseSurface*>::iterator iter = _surfaces.begin(); iter != _surfaces.end(); iter++)
+ (*iter)->addDirtyRect();
+ g_screen->addDirtyRects();
+ }
+ for (Common::Array<BaseSurface*>::iterator iter = _surfaces.begin(); iter != _surfaces.end(); iter++)
+ (*iter)->draw();
+ }
+#endif
+}
+
+void Scene::addEntity(Entity *entity) {
+ int index = 0, insertIndex = -1;
+ for (Common::Array<Entity*>::iterator iter = _entities.begin(); iter != _entities.end(); iter++) {
+ if ((*iter)->getPriority() > entity->getPriority()) {
+ insertIndex = index;
+ break;
+ }
+ index++;
+ }
+ if (insertIndex >= 0)
+ _entities.insert_at(insertIndex, entity);
+ else
+ _entities.push_back(entity);
+}
+
+bool Scene::removeEntity(Entity *entity) {
+ for (uint index = 0; index < _entities.size(); index++) {
+ if (_entities[index] == entity) {
+ _entities.remove_at(index);
+ return true;
+ }
+ }
+ return false;
+}
+
+void Scene::addSurface(BaseSurface *surface) {
+ int index = 0, insertIndex = -1;
+ for (Common::Array<BaseSurface*>::iterator iter = _surfaces.begin(); iter != _surfaces.end(); iter++) {
+ if ((*iter)->getPriority() > surface->getPriority()) {
+ insertIndex = index;
+ break;
+ }
+ index++;
+ }
+ if (insertIndex >= 0)
+ _surfaces.insert_at(insertIndex, surface);
+ else
+ _surfaces.push_back(surface);
+}
+
+bool Scene::removeSurface(BaseSurface *surface) {
+ for (uint index = 0; index < _surfaces.size(); index++) {
+ if (_surfaces[index] == surface) {
+ _surfaces.remove_at(index);
+ return true;
+ }
+ }
+ return false;
+}
+
+Sprite *Scene::addSprite(Sprite *sprite) {
+ addEntity(sprite);
+ addSurface(sprite->getSurface());
+ return sprite;
+}
+
+void Scene::setSurfacePriority(BaseSurface *surface, int priority) {
+ surface->setPriority(priority);
+ if (removeSurface(surface))
+ addSurface(surface);
+}
+
+void Scene::deleteSprite(Sprite **sprite) {
+ // TODO g_Class700->removeSprite(*sprite);
+ removeSurface((*sprite)->getSurface());
+ removeEntity(*sprite);
+ delete *sprite;
+ *sprite = NULL;
+}
+
+void Scene::update() {
+
+ if (_smkFileHash != 0) {
+ // TODO
+ //**** ALL TODO
+ //_smackerPlayer = new SmackerPlayer(this, _smkFileHash, true, 0);
+ _savedUpdateHandlerCb = _updateHandlerCb;
+ _savedMessageHandlerCb = _messageHandlerCb;
+ SetUpdateHandler(&Scene::smackerUpdate);
+ SetMessageHandler(&Scene::smackerHandleMessage);
+ _smackerDone = false;
+ // smackerUpdate();
+ // g_screen->smackerPlayer = _smackerPlayer;
+ _smkFileHash = 0;
+ } else {
+ if (_mouseClicked) {
+ //** ALL TODO
+#if 0
+ if (_playerSprite) {
+ // TODO: Merge later
+ if (_playerSprite->hasMessageHandler() &&
+ _playerSprite->sendMessage(0x1008, 0, this) != 0 &&
+ _messageListFlag &&
+ queryPositionClass400(_mouseClickPos.x, _mouseClickPos.y)) {
+ _mouseClicked = false;
+ } else if (_playerSprite->hasMessageHandler() &&
+ _playerSprite->sendMessage(0x1008, 0, this) != 0 &&
+ _messageListFlag) {
+ _mouseClicked = !queryPositionRectList(_mouseClickPos.x, _mouseClickPos.y);
+ }
+ } else if (queryPositionClass400(_mouseClickPos.x, _mouseClickPos.y)) {
+ _mouseClicked = false;
+ }
+#endif
+ }
+
+ // TODO runMessageList();
+
+ // Update all entities
+ for (Common::Array<Entity*>::iterator iter = _entities.begin(); iter != _entities.end(); iter++)
+ (*iter)->handleUpdate();
+
+ }
+
+}
+
+uint32 Scene::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ // TODO
+#if 0
+ switch (messageNum) {
+ case 0: // mouse moved
+ if (_mouseSprite && _mouseSprite->hasMessageHandler())
+ _mouseSprite->sendMessage(0x4002, param, this);
+ queryPositionSomeRects(param._point.x, param._point.y);
+ break;
+ case 1: // mouse clicked
+ _mouseClicked = true;
+ _mouseClickPos = param._point;
+ break;
+ /* ORIGINAL DEBUG
+ case 3:
+ drawSurfaceRects();
+ break;
+ */
+ /* ORIGINAL DEBUG
+ case 4:
+ drawRectListRects();
+ break;
+ */
+ case 5:
+ broadcastObjectMessage5();
+ break;
+ case 6:
+ _parentModule->sendMessage(0x1009, param, this);
+ break;
+ case 0x1006:
+ if (_messageListFlag1) {
+ _messageListFlag1 = false;
+ if (_messageListIndex == _messageListCount)
+ _playerSprite->sendMessage(0x4004, 0, this);
+ else
+ runMessageList();
+ }
+ break;
+ case 0x1007:
+ if (_messageListFlag1) {
+ _messageListFlag1 = false;
+ _messageList = NULL;
+ _playerSprite->sendMessage(0x4004, 0, this);
+ }
+ break;
+ case 0x101D:
+ if (_mouseSprite) {
+ _prevVisible = _mouseSprite->_drawSurface->_visible;
+ _mouseSprite->_drawSurface->_visible = false;
+ }
+ break;
+ case 0x101E:
+ if (_prevVisible && _mouseSprite) {
+ _mouseSprite->_drawSurface->_visible = true;
+ _mouseSprite->sendMessage(0x4002, g_Screen->_mousePos, this);
+ }
+ break;
+ case 0x1022:
+ setSurfacePriority(((Sprite*)sender)->_surface, param._integer);
+ break;
+ }
+#endif
+ return 0;
+}
+
+void Scene::smackerUpdate() {
+ //**ALL TODO
+#if 0
+ _smackerPlayer->handleUpdate();
+ if (_smackerDone) {
+ delete _smackerPlayer;
+ _smackerPlayer = NULL;
+ _updateHandlerCb = _savedUpdateHandlerCb;
+ _messageHandlerCb = _savedMessageHandlerCb;
+ if (_palette)
+ _palette->usePalette();
+ // TODO class300->restore();
+ // TODO g_screen->smackerPlayer = NULL;
+ }
+#endif
+}
+
+uint32 Scene::smackerHandleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ if (messageNum == 0x3002)
+ _smackerDone = true;
+ return 0;
+}
+
+} // End of namespace Neverhood
diff --git a/engines/neverhood/scene.h b/engines/neverhood/scene.h
new file mode 100644
index 0000000000..3532a43b0b
--- /dev/null
+++ b/engines/neverhood/scene.h
@@ -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.
+ *
+ */
+
+#ifndef NEVERHOOD_SCENE_H
+#define NEVERHOOD_SCENE_H
+
+#include "common/array.h"
+#include "neverhood/neverhood.h"
+#include "neverhood/entity.h"
+#include "neverhood/graphics.h"
+#include "neverhood/module.h"
+#include "neverhood/palette.h"
+#include "neverhood/sprite.h"
+
+namespace Neverhood {
+
+struct MessageListItem {
+ uint32 messageNum;
+ uint32 messageValue;
+};
+
+class Scene : public Entity {
+public:
+ Scene(NeverhoodEngine *vm, Module *parentModule, bool clearHitRects);
+ virtual ~Scene();
+ virtual void draw();
+ void addEntity(Entity *entity);
+ bool removeEntity(Entity *entity);
+ void addSurface(BaseSurface *surface);
+ bool removeSurface(BaseSurface *surface);
+ Sprite *addSprite(Sprite *sprite);
+ void setSurfacePriority(BaseSurface *surface, int priority);
+ void deleteSprite(Sprite **sprite);
+protected:
+ Module *_parentModule;
+ Common::Array<Entity*> _entities;
+ Common::Array<BaseSurface*> _surfaces;
+ bool _systemCallbackFlag;
+ MessageListItem *_messageList;
+ int _messageListIndex;
+ int _messageListCount;
+ bool _messageListFlag1;
+ NPoint _mouseClickPos;
+ bool _mouseClicked;
+ // TODO RectResource _rectResource;
+ // TODO 00000080 rectList dd ?
+ // TODO 00000084 rectType dw ?
+ // TODO 00000086 rectListCount dw ?
+ // TODO 00000088 someRects dd ?
+ // TODO 0000008C someRectsCount dw ?
+ // TODO 0000008E field_8E dw ?
+ // TODO 00000090 playerSprite dd ?
+ // TODO 00000094 mouseSprite dd ?
+ Palette *_palette;
+ // TODO 0000009C class300 dd ?
+ bool _surfaceFlag;
+ bool _messageListFlag;
+ MessageListItem *_messageList2;
+ int _messageListStatus;
+ // TODO 000000B0 smackerPlayer dd ?
+ void (Entity::*_savedUpdateHandlerCb)();
+ uint32 (Entity::*_savedMessageHandlerCb)(int messageNum, const MessageParam &param, Entity *sender);
+ bool _smackerDone;
+ // TODO 000000BD field_BD db ?
+ // TODO 000000BE field_BE db ?
+ // TODO 000000BF field_BF db ?
+ uint32 _smkFileHash;
+ // TODO 000000C4 hitArray dd ?
+ bool _messageListFlag2;
+ bool _prevVisible;
+ int _messageValue;
+ // TODO 000000CF field_CF db ?
+ void update();
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+ void smackerUpdate();
+ uint32 smackerHandleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+} // End of namespace Neverhood
+
+#endif /* NEVERHOOD_SCENE_H */
diff --git a/engines/neverhood/sprite.cpp b/engines/neverhood/sprite.cpp
new file mode 100644
index 0000000000..6ee0a6633c
--- /dev/null
+++ b/engines/neverhood/sprite.cpp
@@ -0,0 +1,179 @@
+/* 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.
+ *
+ */
+
+#include "neverhood/sprite.h"
+
+namespace Neverhood {
+
+// Sprite
+
+Sprite::Sprite(NeverhoodEngine *vm, int objectPriority)
+ : Entity(vm, objectPriority), _x(0), _y(0),
+ _spriteUpdateCb(NULL), _filterXCb(NULL), _filterYCb(NULL),
+ _doDeltaX(false), _doDeltaY(false), _needRedraw(false),
+ _deltaX1(0), _deltaY1(0), _deltaX2(0), _deltaY2(0),
+ _flags(0) {
+
+ SetMessageHandler(&Sprite::handleMessage);
+
+}
+
+Sprite::~Sprite() {
+ delete _surface;
+}
+
+void Sprite::processDelta() {
+ if (_doDeltaX) {
+ _rect.x1 = _x - _deltaX1 - _deltaX2 + 1;
+ _rect.x2 = _x - _deltaX1;
+ } else {
+ _rect.x1 = _x + _deltaX1;
+ _rect.x2 = _x + _deltaX1 + _deltaX2 - 1;
+ }
+ if (_doDeltaY) {
+ _rect.y1 = _y - _deltaY1 - _deltaY2 + 1;
+ _rect.y2 = _y - _deltaY1;
+ } else {
+ _rect.y1 = _y + _deltaY1;
+ _rect.y2 = _y + _deltaY1 + _deltaY2 - 1;
+ }
+}
+
+void Sprite::setDoDeltaX(int type) {
+ // Clear, set or toggle
+ _doDeltaX = type == 2 ? !_doDeltaX : type == 1;
+}
+
+void Sprite::setDoDeltaY(int type) {
+ // Clear, set or toggle
+ _doDeltaY = type == 2 ? !_doDeltaY : type == 1;
+}
+
+bool Sprite::isPointInside(int16 x, int16 y) {
+ return x >= _rect.x1 && x <= _rect.x2 && y >= _rect.y1 && y <= _rect.y2;
+}
+
+uint32 Sprite::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ if (messageNum == 5) {
+ // TODO: Draw debug marker (?)
+ // TODO g_Screen->drawLine(_x - 5, _y, _x + 6, _y);
+ // TODO g_Screen->drawLine(_x, _y - 5, _x, _y + 6);
+ }
+ return 0;
+}
+
+void Sprite::createSurface(int surfacePriority, int16 width, int16 height) {
+ _surface = new BaseSurface(_vm, surfacePriority, width, height);
+}
+
+// StaticSprite
+
+StaticSprite::StaticSprite(NeverhoodEngine *vm, int objectPriority)
+ : Sprite(vm, objectPriority), _spriteResource(vm) {
+
+}
+
+StaticSprite::StaticSprite(NeverhoodEngine *vm, const char *filename, int surfacePriority, int16 x, int16 y, int16 width, int16 height)
+ : Sprite(vm, 0), _spriteResource(vm) {
+
+ // TODO init(calcHash(filename), surfacePriority, x, y, width, height);
+
+}
+
+StaticSprite::StaticSprite(NeverhoodEngine *vm, uint32 fileHash, int surfacePriority, int16 x, int16 y, int16 width, int16 height)
+ : Sprite(vm, 0), _spriteResource(vm) {
+
+ init(fileHash, surfacePriority, x, y, width, height);
+
+}
+
+void StaticSprite::init(uint32 fileHash, int surfacePriority, int16 x, int16 y, int16 width, int16 height) {
+
+ _spriteResource.load2(fileHash);
+
+ if (width == 0)
+ width = _spriteResource.getDimensions().width;
+
+ if (height == 0)
+ height = _spriteResource.getDimensions().height;
+
+ createSurface(surfacePriority, width, height);
+
+ _x = x == kDefPosition ? _spriteResource.getPosition().x : x;
+ _y = y == kDefPosition ? _spriteResource.getPosition().y : y;
+
+ _rect1.x1 = 0;
+ _rect1.y1 = 0;
+ _rect1.x2 = width;
+ _rect1.y2 = height;
+
+ _needRedraw = true;
+
+ update();
+
+}
+
+void StaticSprite::update() {
+
+ if (!_surface)
+ return;
+
+ if (_doDeltaX) {
+ _x = filterX(_x - _rect1.x1 - _rect1.x2 + 1);
+ } else {
+ _x = filterX(_x + _rect1.x1);
+ }
+
+ if (_doDeltaY) {
+ _y = filterY(_y - _rect1.y1 - _rect1.y2 + 1);
+ } else {
+ _y = filterY(_y + _rect1.y1);
+ }
+
+ if (_needRedraw) {
+ // TODO _surface->drawSpriteResourceEx(_spriteResource, _doDeltaX, _doDeltaY, _rect1.x2, _rect1.y2);
+ _needRedraw = false;
+ }
+
+}
+
+void StaticSprite::load(uint32 fileHash, bool dimensions, bool position) {
+
+ _spriteResource.load2(fileHash);
+
+ if (dimensions) {
+ _rect1.x1 = 0;
+ _rect1.y1 = 0;
+ _rect1.x2 = _spriteResource.getDimensions().width;
+ _rect1.y2 = _spriteResource.getDimensions().height;
+ }
+
+ if (position) {
+ _x = _spriteResource.getPosition().x;
+ _y = _spriteResource.getPosition().y;
+ }
+
+ _needRedraw = true;
+
+}
+
+} // End of namespace Neverhood
diff --git a/engines/neverhood/sprite.h b/engines/neverhood/sprite.h
new file mode 100644
index 0000000000..5c08e3c66f
--- /dev/null
+++ b/engines/neverhood/sprite.h
@@ -0,0 +1,90 @@
+/* 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.
+ *
+ */
+
+#ifndef NEVERHOOD_SPRITE_H
+#define NEVERHOOD_SPRITE_H
+
+#include "neverhood/neverhood.h"
+#include "neverhood/entity.h"
+#include "neverhood/graphics.h"
+#include "neverhood/resource.h"
+
+namespace Neverhood {
+
+#define SetSpriteCallback(callback) _spriteCallbackCb = static_cast <void (Sprite::*)(void)> (callback)
+#define SetFilterX(callback) _filterXCb = static_cast <int16 (Sprite::*)(int16)> (callback)
+#define SetFilterY(callback) _filterYCb = static_cast <int16 (Sprite::*)(int16)> (callback)
+
+const int16 kDefPosition = -32768;
+
+class Sprite : public Entity {
+public:
+ Sprite(NeverhoodEngine *vm, int objectPriority);
+ ~Sprite();
+ BaseSurface *getSurface() { return _surface; }
+ void processDelta();
+ void setDoDeltaX(int type);
+ void setDoDeltaY(int type);
+ bool isPointInside(int16 x, int16 y);
+protected:
+ void (Sprite::*_spriteUpdateCb)();
+ int16 (Sprite::*_filterXCb)(int16);
+ int16 (Sprite::*_filterYCb)(int16);
+ BaseSurface *_surface;
+ int16 _x, _y;
+ bool _doDeltaX, _doDeltaY;
+ bool _needRedraw;
+ //0000002B field_2B db ?
+ //0000002C field2C dd ? // unused
+ NRect _rect1;
+ int16 _deltaX1, _deltaY1;
+ int16 _deltaX2, _deltaY2;
+ NRect _rect;
+ uint16 _flags;
+ //0000004A field4A dw ? // seems to be unused except in ctor
+ //0000004C rectResource RectResource ?
+ //void update();
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+ void createSurface(int surfacePriority, int16 width, int16 height);
+ int16 filterX(int16 x) {
+ return _filterXCb ? (this->*_filterXCb)(x) : x;
+ }
+ int16 filterY(int16 y) {
+ return _filterYCb ? (this->*_filterYCb)(y) : y;
+ }
+};
+
+class StaticSprite : public Sprite {
+public:
+ StaticSprite(NeverhoodEngine *vm, int objectPriority);
+ StaticSprite(NeverhoodEngine *vm, const char *filename, int surfacePriority, int16 x, int16 y, int16 width, int16 height);
+ StaticSprite(NeverhoodEngine *vm, uint32 fileHash, int surfacePriority, int16 x, int16 y, int16 width, int16 height);
+ void load(uint32 fileHash, bool dimensions, bool position);
+protected:
+ SpriteResource _spriteResource;
+ void init(uint32 fileHash, int surfacePriority, int16 x, int16 y, int16 width, int16 height);
+ void update();
+};
+
+} // End of namespace Neverhood
+
+#endif /* NEVERHOOD_SPRITE_H */