aboutsummaryrefslogtreecommitdiff
path: root/engines/neverhood
diff options
context:
space:
mode:
authorjohndoe1232011-07-16 11:01:08 +0000
committerWillem Jan Palenstijn2013-05-08 20:38:48 +0200
commita23b694c94d318b3e06f450189aab82b3908fcc5 (patch)
tree48d9ef4655acc12a3e7483d0ab341d59705c2dbe /engines/neverhood
parent0bfb52df74ac47a4842c66d40fd0ae5efc5d6af6 (diff)
downloadscummvm-rg350-a23b694c94d318b3e06f450189aab82b3908fcc5.tar.gz
scummvm-rg350-a23b694c94d318b3e06f450189aab82b3908fcc5.tar.bz2
scummvm-rg350-a23b694c94d318b3e06f450189aab82b3908fcc5.zip
NEVERHOOD: Implement Scene1005
- Add FontSurface - Add DataResource - Fix NavigationScene, only accept input when interactive
Diffstat (limited to 'engines/neverhood')
-rw-r--r--engines/neverhood/graphics.cpp46
-rw-r--r--engines/neverhood/graphics.h18
-rw-r--r--engines/neverhood/module1000.cpp204
-rw-r--r--engines/neverhood/module1000.h16
-rw-r--r--engines/neverhood/navigationscene.cpp6
-rw-r--r--engines/neverhood/neverhood.cpp14
-rw-r--r--engines/neverhood/resource.cpp263
-rw-r--r--engines/neverhood/resource.h72
-rw-r--r--engines/neverhood/sprite.cpp11
9 files changed, 639 insertions, 11 deletions
diff --git a/engines/neverhood/graphics.cpp b/engines/neverhood/graphics.cpp
index b9e2c482a1..e46d4eaf86 100644
--- a/engines/neverhood/graphics.cpp
+++ b/engines/neverhood/graphics.cpp
@@ -107,6 +107,52 @@ void BaseSurface::drawMouseCursorResource(MouseCursorResource &mouseCursorResour
}
}
+void BaseSurface::copyFrom(Graphics::Surface *sourceSurface, int16 x, int16 y, NDrawRect &sourceRect, bool transparent) {
+ // TODO: Clipping
+ byte *source = (byte*)sourceSurface->getBasePtr(sourceRect.x, sourceRect.y);
+ byte *dest = (byte*)_surface->getBasePtr(x, y);
+ int height = sourceRect.height;
+ if (!transparent) {
+ while (height--) {
+ memcpy(dest, source, sourceRect.width);
+ source += sourceSurface->pitch;
+ dest += _surface->pitch;
+ }
+ } else {
+ while (height--) {
+ for (int xc = 0; xc < sourceRect.width; xc++)
+ if (source[xc] != 0)
+ dest[xc] = source[xc];
+ source += sourceSurface->pitch;
+ dest += _surface->pitch;
+ }
+ }
+}
+
+// FontSurface
+
+FontSurface::FontSurface(NeverhoodEngine *vm, NPointArray *tracking, uint16 numRows, byte firstChar, uint16 charWidth, uint16 charHeight)
+ : BaseSurface(vm, 0, charWidth * 16, charHeight * numRows), _tracking(tracking), _numRows(numRows), _firstChar(firstChar),
+ _charWidth(charWidth), _charHeight(charHeight) {
+}
+
+void FontSurface::drawChar(BaseSurface *destSurface, int16 x, int16 y, byte chr) {
+ NDrawRect sourceRect;
+ chr -= _firstChar;
+ sourceRect.x = (chr % 16) * _charWidth;
+ sourceRect.y = (chr / 16) * _charHeight;
+ sourceRect.width = _charWidth;
+ sourceRect.height = _charHeight;
+ destSurface->copyFrom(_surface, x, y, sourceRect, true);
+}
+
+void FontSurface::drawString(BaseSurface *destSurface, int16 x, int16 y, const byte *string) {
+ for (; *string != 0; string++) {
+ drawChar(destSurface, x, y, *string);
+ x += (*_tracking)[*string - _firstChar].x;
+ }
+}
+
// Misc
void parseBitmapResource(byte *sprite, bool *rle, NDimensions *dimensions, NPoint *position, byte **palette, byte **pixels) {
diff --git a/engines/neverhood/graphics.h b/engines/neverhood/graphics.h
index 9ac23a81f5..8bdf0afd3d 100644
--- a/engines/neverhood/graphics.h
+++ b/engines/neverhood/graphics.h
@@ -34,6 +34,8 @@ struct NPoint {
int16 x, y;
};
+typedef Common::Array<NPoint> NPointArray;
+
struct NDimensions {
int16 width, height;
};
@@ -44,6 +46,8 @@ struct NRect {
NRect(int16 x01, int16 y01, int16 x02, int16 y02) : x1(x01), y1(y01), x2(x02), y2(y02) {}
};
+typedef Common::Array<NRect> NRectArray;
+
struct NDrawRect {
int16 x, y, width, height;
NDrawRect() : x(0), y(0), width(0), height(0) {}
@@ -67,6 +71,7 @@ public:
void drawSpriteResourceEx(SpriteResource &spriteResource, bool flipX, bool flipY, int16 width, int16 height);
void drawAnimResource(AnimResource &animResource, uint frameIndex, bool flipX, bool flipY, int16 width, int16 height);
void drawMouseCursorResource(MouseCursorResource &mouseCursorResource, int frameNum);
+ void copyFrom(Graphics::Surface *sourceSurface, int16 x, int16 y, NDrawRect &sourceRect, bool transparent);
int getPriority() const { return _priority; }
void setPriority(int priority) { _priority = priority; }
NDrawRect& getDrawRect() { return _drawRect; }
@@ -87,6 +92,19 @@ protected:
bool _transparent;
};
+class FontSurface : public BaseSurface {
+public:
+ FontSurface(NeverhoodEngine *vm, NPointArray *tracking, uint16 numRows, byte firstChar, uint16 charWidth, uint16 charHeight);
+ void drawChar(BaseSurface *destSurface, int16 x, int16 y, byte chr);
+ void drawString(BaseSurface *destSurface, int16 x, int16 y, const byte *string);
+protected:
+ NPointArray *_tracking;
+ uint16 _numRows;
+ byte _firstChar;
+ uint16 _charWidth;
+ uint16 _charHeight;
+};
+
// Misc
void parseBitmapResource(byte *sprite, bool *rle, NDimensions *dimensions, NPoint *position, byte **palette, byte **pixels);
diff --git a/engines/neverhood/module1000.cpp b/engines/neverhood/module1000.cpp
index bc898621af..6825f62926 100644
--- a/engines/neverhood/module1000.cpp
+++ b/engines/neverhood/module1000.cpp
@@ -56,7 +56,8 @@ Module1000::Module1000(NeverhoodEngine *vm, Module *parentModule, int which)
} else if (which == 0) {
//createScene1001(0);
// DEBUG: Jump to room
- createScene1002(0);
+ //createScene1002(0);
+ createScene1005(0);
} else if (which == 1) {
createScene1002(1);
}
@@ -95,6 +96,11 @@ void Module1000::createScene1004(int which) {
}
void Module1000::createScene1005(int which) {
+ _vm->gameState().sceneNum = 4;
+ _childObject = new Scene1005(_vm, this, which);
+ // TODO Music18hList_stop(0x061880C6, 0, 0);
+ // TODO Music18hList_play(_musicFileHash, 0, 0, 1);
+ SetUpdateHandler(&Module1000::updateScene1002);
}
void Module1000::updateScene1001() {
@@ -196,6 +202,16 @@ void Module1000::updateScene1004() {
}
void Module1000::updateScene1005() {
+ _childObject->handleUpdate();
+ if (_done) {
+ debug("SCENE 1005 DONE");
+ // TODO Music18hList_stop(_musicFileHash, 0, 1);
+ _done = false;
+ delete _childObject;
+ _childObject = NULL;
+ createScene1004(1);
+ _childObject->handleUpdate();
+ }
}
// Scene1001
@@ -1673,4 +1689,190 @@ uint32 Class152::handleMessage(int messageNum, const MessageParam &param, Entity
return 0;
}
+// Scene1005
+
+Scene1005::Scene1005(NeverhoodEngine *vm, Module *parentModule, int which)
+ : Scene(vm, parentModule, true) {
+
+ SetMessageHandler(&Scene1005::handleMessage);
+
+ _surfaceFlag = true;
+
+ if (getGlobalVar(0xD0A14D10)) {
+ _background = addBackground(new DirtyBackground(_vm, 0x2800E011, 0, 0));
+ _palette = new Palette(_vm, 0x2800E011);
+ _palette->usePalette();
+ addSprite(new StaticSprite(_vm, 0x492D5AD7, 100));
+ _mouseCursor = addSprite(new Mouse435(_vm, 0x0E015288, 20, 620));
+ } else {
+ _background = addBackground(new DirtyBackground(_vm, 0x8870A546, 0, 0));
+ _palette = new Palette(_vm, 0x8870A546);
+ _palette->usePalette();
+ addSprite(new StaticSprite(_vm, 0x40D1E0A9, 100));
+ addSprite(new StaticSprite(_vm, 0x149C00A6, 100));
+ _mouseCursor = addSprite(new Mouse435(_vm, 0x0A54288F, 20, 620));
+ }
+
+ drawTextToBackground();
+
+}
+
+Scene1005::~Scene1005() {
+}
+
+uint32 Scene1005::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+ Scene::handleMessage(messageNum, param, sender);
+ switch (messageNum) {
+ case 0x0001:
+ if (param.asPoint().x <= 20 || param.asPoint().x >= 620) {
+ _parentModule->sendMessage(0x1009, 0, this);
+ }
+ break;
+ }
+ return 0;
+}
+
+void Scene1005::drawTextToBackground() {
+ TextResource textResource(_vm);
+ const char *textStart, *textEnd;
+ int16 y = 36;
+ uint32 textIndex = getTextIndex();
+ FontSurface *fontSurface = createFontSurface();
+ textResource.load(0x80283101);
+ textStart = textResource.getString(textIndex, textEnd);
+ while (textStart < textEnd) {
+ fontSurface->drawString(_background->getSurface(), 188, y, (const byte*)textStart);
+ y += 36;
+ textStart += strlen(textStart) + 1;
+ }
+ delete fontSurface;
+}
+
+FontSurface *Scene1005::createFontSurface() {
+ FontSurface *fontSurface;
+ DataResource fontData(_vm);
+ SpriteResource fontSprite(_vm);
+ fontData.load(calcHash("asRecFont"));
+ uint16 numRows = fontData.getPoint(calcHash("meNumRows")).x;
+ uint16 firstChar = fontData.getPoint(calcHash("meFirstChar")).x;
+ uint16 charWidth = fontData.getPoint(calcHash("meCharWidth")).x;
+ uint16 charHeight = fontData.getPoint(calcHash("meCharHeight")).x;
+ NPointArray *tracking = fontData.getPointArray(calcHash("meTracking"));
+ fontSurface = new FontSurface(_vm, tracking, numRows, firstChar, charWidth, charHeight);
+ if (getGlobalVar(0xD0A14D10)) {
+ fontSprite.load2(0x283CE401);
+ } else {
+ fontSprite.load2(0xC6604282);
+ }
+ fontSurface->drawSpriteResourceEx(fontSprite, false, false, 0, 0);
+ return fontSurface;
+}
+
+uint32 Scene1005::getTextIndex() {
+ uint32 textIndex;
+ textIndex = getTextIndex1();
+ if (getGlobalVar(0xD0A14D10)) {
+ textIndex = getTextIndex2();
+ }
+ if (getGlobalVar(0x8440001F) && getGlobalVar(0x01830201) == textIndex) {
+ textIndex = getTextIndex3();
+ } else {
+ setGlobalVar(0x8440001F, 1);
+ setGlobalVar(0x01830201, textIndex);
+ }
+ return textIndex;
+}
+
+uint32 Scene1005::getTextIndex1() {
+ uint32 textIndex;
+ if (getGlobalVar(0x98109F12)) {
+ if (!getGlobalVar(0x2090590C))
+ textIndex = 18;
+ else if (!getGlobalVar(0x610210B7))
+ textIndex = 19;
+ else if (getGlobalVar(0x0C0288F4)) {
+ if (!getGlobalVar(0xD0A14D10))
+ textIndex = 23;
+ else if (!getSubVar(0x0090EA95, 0) && !getSubVar(0x08D0AB11, 0))
+ textIndex = 24;
+ else if (!getGlobalVar(0xC0780812))
+ textIndex = 26;
+ else if (!getSubVar(0x0090EA95, 1) && !getSubVar(0x08D0AB11, 1))
+ textIndex = 27;
+ else if (!getGlobalVar(0xC0780812))
+ textIndex = 28;
+ else
+ textIndex = 29;
+ } else if (!getGlobalVar(0xE7498218))
+ textIndex = 20;
+ else if (!getGlobalVar(0x081890D14))
+ textIndex = 21;
+ else
+ textIndex = 22;
+ } else if (getGlobalVar(0x00040153)) {
+ if (!getGlobalVar(0x10938830))
+ textIndex = 12;
+ else if (!getGlobalVar(0x2050861A))
+ textIndex = 13;
+ else if (!getGlobalVar(0x4DE80AC0))
+ textIndex = 50;
+ else if (!getGlobalVar(0x89C669AA))
+ textIndex = 14;
+ else if (!getGlobalVar(0x1C1B8A9A))
+ textIndex = 15;
+ else if (!getGlobalVar(0xCB45DE03))
+ textIndex = 16;
+ else
+ textIndex = 17;
+ } else if (!getGlobalVar(0x2B514304)) {
+ textIndex = 0;
+ } else if (getGlobalVar(0x0A18CA33)) {
+ if (!getGlobalVar(0x404290D5))
+ textIndex = 4;
+ else if (!getGlobalVar(0x45080C38))
+ textIndex = 5;
+ else if (!getSubVar(0x14800353, 0x40119852))
+ textIndex = 6;
+ else if (!getGlobalVar(0x4E0BE910))
+ textIndex = 7;
+ else if (!getGlobalVar(0x86615030))
+ textIndex = 8;
+ else if (!getSubVar(0x14800353, 0x304008D2))
+ textIndex = 9;
+ else if (!getSubVar(0x14800353, 0x01180951))
+ textIndex = 10;
+ else
+ textIndex = 11;
+ } else if (!getGlobalVar(0x0A310817)) {
+ textIndex = 1;
+ } else if (getGlobalVar(0x000CF819)) {
+ textIndex = 3;
+ } else {
+ textIndex = 2;
+ }
+ return textIndex;
+}
+
+uint32 Scene1005::getTextIndex2() {
+ uint32 textIndex = getGlobalVar(0x29408F00);
+ if (textIndex + 1 >= 10) {
+ setGlobalVar(0x29408F00, 0);
+ textIndex = 0;
+ } else {
+ setGlobalVar(0x29408F00, textIndex + 1);
+ }
+ return textIndex + 40;
+}
+
+uint32 Scene1005::getTextIndex3() {
+ uint32 textIndex = getGlobalVar(0x8A140C21);
+ if (textIndex + 1 >= 10) {
+ setGlobalVar(0x8A140C21, 0);
+ textIndex = 0;
+ } else {
+ setGlobalVar(0x8A140C21, textIndex + 1);
+ }
+ return textIndex + 30;
+}
+
} // End of namespace Neverhood
diff --git a/engines/neverhood/module1000.h b/engines/neverhood/module1000.h
index 51cb9a4126..4b2121eb53 100644
--- a/engines/neverhood/module1000.h
+++ b/engines/neverhood/module1000.h
@@ -302,6 +302,22 @@ protected:
uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
};
+// Scene1005
+
+class Scene1005 : public Scene {
+public:
+ Scene1005(NeverhoodEngine *vm, Module *parentModule, int which);
+ virtual ~Scene1005();
+protected:
+ uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+ void drawTextToBackground();
+ FontSurface *createFontSurface();
+ uint32 getTextIndex();
+ uint32 getTextIndex1();
+ uint32 getTextIndex2();
+ uint32 getTextIndex3();
+};
+
} // End of namespace Neverhood
#endif /* NEVERHOOD_MODULE1000_H */
diff --git a/engines/neverhood/navigationscene.cpp b/engines/neverhood/navigationscene.cpp
index 81af71fe17..f6be668b3c 100644
--- a/engines/neverhood/navigationscene.cpp
+++ b/engines/neverhood/navigationscene.cpp
@@ -99,10 +99,12 @@ void NavigationScene::update() {
uint32 NavigationScene::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
switch (messageNum) {
case 0x0000:
- _mouseCursor->sendMessage(0x4002, param, this);
+ if (_interactive)
+ _mouseCursor->sendMessage(0x4002, param, this);
break;
case 0x0001:
- handleNavigation(param.asPoint());
+ if (_interactive)
+ handleNavigation(param.asPoint());
break;
case 0x0009:
if (!_interactive)
diff --git a/engines/neverhood/neverhood.cpp b/engines/neverhood/neverhood.cpp
index 4440a05dd6..1f253c0a15 100644
--- a/engines/neverhood/neverhood.cpp
+++ b/engines/neverhood/neverhood.cpp
@@ -146,6 +146,16 @@ Common::Error NeverhoodEngine::run() {
}
#endif
+#if 0
+ { // Create a new scope
+ DataResource dataResource(this);
+ //dataResource.load(0x01801002);
+ //dataResource.load(0x84500132);
+ dataResource.load(0x81120132);
+ }
+#endif
+
+#if 1
_collisionMan = new CollisionMan(this);
_gameModule = new GameModule(this);
@@ -196,7 +206,9 @@ Common::Error NeverhoodEngine::run() {
delete _gameModule;
delete _collisionMan;
-
+#endif
+
+
delete _res;
delete _screen;
diff --git a/engines/neverhood/resource.cpp b/engines/neverhood/resource.cpp
index 97eae89bd5..1c376105cf 100644
--- a/engines/neverhood/resource.cpp
+++ b/engines/neverhood/resource.cpp
@@ -20,11 +20,16 @@
*
*/
+#include "common/memstream.h"
#include "neverhood/resource.h"
#include "neverhood/resourceman.h"
namespace Neverhood {
+// TODO: Since the load() methods are similar in most cases some of the code therein
+// can probably be copied into another method (e.g. inside the resource manager)
+// to reduce code.
+
// SpriteResource
SpriteResource::SpriteResource(NeverhoodEngine *vm)
@@ -360,6 +365,248 @@ void MouseCursorResource::draw(int frameNum, byte *dest, int destPitch) {
}
}
+// TextResource
+
+TextResource::TextResource(NeverhoodEngine *vm)
+ : _vm(vm), _resourceHandle(-1), _textData(NULL), _count(0) {
+
+}
+
+TextResource::~TextResource() {
+ unload();
+}
+
+void TextResource::load(uint32 fileHash) {
+ unload();
+ _resourceHandle = _vm->_res->useResource(fileHash);
+ if (_resourceHandle != -1) {
+ if (_vm->_res->getResourceType(_resourceHandle) == 6) {
+ _textData = _vm->_res->loadResource(_resourceHandle, true);
+ _count = READ_LE_UINT32(_textData);
+ } else {
+ _vm->_res->unuseResource(_resourceHandle);
+ _resourceHandle = -1;
+ }
+ }
+}
+
+void TextResource::unload() {
+ if (_resourceHandle != -1) {
+ _vm->_res->unloadResource(_resourceHandle);
+ _vm->_res->unuseResource(_resourceHandle);
+ _resourceHandle = -1;
+ _textData = NULL;
+ _count = 0;
+ }
+}
+
+const char *TextResource::getString(uint index, const char *&textEnd) {
+ const char *textStart = (const char*)(_textData + 4 + _count * 4 + READ_LE_UINT32(_textData + (index + 1) * 4));
+ textEnd = (const char*)(_textData + 4 + _count * 4 + READ_LE_UINT32(_textData + (index + 2) * 4));
+ return textStart;
+}
+
+// DataResource
+
+DataResource::DataResource(NeverhoodEngine *vm)
+ : _vm(vm), _resourceHandle(-1) {
+}
+
+DataResource::~DataResource() {
+ unload();
+}
+
+void DataResource::load(uint32 fileHash) {
+ debug("DataResource::load(%08X)", fileHash);
+ byte *data = NULL;
+ uint32 dataSize = 0;
+ unload();
+ _resourceHandle = _vm->_res->useResource(fileHash);
+ if (_resourceHandle != -1) {
+ if (_vm->_res->getResourceType(_resourceHandle) == 5) {
+ data = _vm->_res->loadResource(_resourceHandle, true);
+ dataSize = _vm->_res->getResourceSize(_resourceHandle);
+ } else {
+ _vm->_res->unuseResource(_resourceHandle);
+ _resourceHandle = -1;
+ }
+ }
+ if (data && dataSize) {
+ Common::MemoryReadStream dataS(data, dataSize);
+ uint itemCount = dataS.readUint16LE();
+ uint32 itemStartOffs = 2 + itemCount * 8;
+ debug("itemCount = %d", itemCount);
+ for (uint i = 0; i < itemCount; i++) {
+ dataS.seek(2 + i * 8);
+ DRDirectoryItem drDirectoryItem;
+ drDirectoryItem.nameHash = dataS.readUint32LE();
+ drDirectoryItem.offset = dataS.readUint16LE();
+ drDirectoryItem.type = dataS.readUint16LE();
+ debug("%03d nameHash = %08X; offset = %04X; type = %d", i, drDirectoryItem.nameHash, drDirectoryItem.offset, drDirectoryItem.type);
+ dataS.seek(itemStartOffs + drDirectoryItem.offset);
+ switch (drDirectoryItem.type) {
+ case 1:
+ {
+ debug(3, "NPoint");
+ NPoint point;
+ point.x = dataS.readUint16LE();
+ point.y = dataS.readUint16LE();
+ debug(3, "(%d, %d)", point.x, point.y);
+ drDirectoryItem.offset = _points.size();
+ _points.push_back(point);
+ break;
+ }
+ case 2:
+ {
+ uint count = dataS.readUint16LE();
+ NPointArray *pointArray = new NPointArray();
+ debug(3, "NPointArray; count = %d", count);
+ for (uint j = 0; j < count; j++) {
+ NPoint point;
+ point.x = dataS.readUint16LE();
+ point.y = dataS.readUint16LE();
+ debug(3, "(%d, %d)", point.x, point.y);
+ pointArray->push_back(point);
+ }
+ drDirectoryItem.offset = _pointArrays.size();
+ _pointArrays.push_back(pointArray);
+ break;
+ }
+ case 3:
+ {
+ uint count = dataS.readUint16LE();
+ HitRectList *hitRectList = new HitRectList();
+ debug(3, "HitRectList; count = %d", count);
+ for (uint j = 0; j < count; j++) {
+ HitRect hitRect;
+ hitRect.rect.x1 = dataS.readUint16LE();
+ hitRect.rect.y1 = dataS.readUint16LE();
+ hitRect.rect.x2 = dataS.readUint16LE();
+ hitRect.rect.y2 = dataS.readUint16LE();
+ hitRect.type = dataS.readUint16LE();
+ debug(3, "(%d, %d, %d, %d) -> %04d", hitRect.rect.x1, hitRect.rect.y1, hitRect.rect.x2, hitRect.rect.y2, hitRect.type);
+ hitRectList->push_back(hitRect);
+ }
+ drDirectoryItem.offset = _hitRectLists.size();
+ _hitRectLists.push_back(hitRectList);
+ break;
+ }
+ case 4:
+ {
+ uint count = dataS.readUint16LE();
+ MessageList *messageList = new MessageList();
+ debug(3, "MessageList; count = %d", count);
+ for (uint j = 0; j < count; j++) {
+ MessageItem messageItem;
+ messageItem.messageNum = dataS.readUint32LE();
+ messageItem.messageValue = dataS.readUint32LE();
+ debug(3, "(%04X, %08X)", messageItem.messageNum, messageItem.messageValue);
+ messageList->push_back(messageItem);
+ }
+ drDirectoryItem.offset = _messageLists.size();
+ _messageLists.push_back(messageList);
+ break;
+ }
+ case 5:
+ {
+ uint count = dataS.readUint16LE();
+ DRSubRectList *drSubRectList = new DRSubRectList();
+ debug(3, "SubRectList; count = %d", count);
+ for (uint j = 0; j < count; j++) {
+ DRSubRect drSubRect;
+ drSubRect.rect.x1 = dataS.readUint16LE();
+ drSubRect.rect.y1 = dataS.readUint16LE();
+ drSubRect.rect.x2 = dataS.readUint16LE();
+ drSubRect.rect.y2 = dataS.readUint16LE();
+ drSubRect.messageListHash = dataS.readUint32LE();
+ drSubRect.messageListItemIndex = dataS.readUint16LE();
+ debug(3, "(%d, %d, %d, %d) -> %08X (%d)", drSubRect.rect.x1, drSubRect.rect.y1, drSubRect.rect.x2, drSubRect.rect.y2, drSubRect.messageListHash, drSubRect.messageListItemIndex);
+ drSubRectList->push_back(drSubRect);
+ }
+ drDirectoryItem.offset = _drSubRectLists.size();
+ _drSubRectLists.push_back(drSubRectList);
+ break;
+ }
+ case 6:
+ {
+ DRRect drRect;
+ drRect.rect.x1 = dataS.readUint16LE();
+ drRect.rect.y1 = dataS.readUint16LE();
+ drRect.rect.x2 = dataS.readUint16LE();
+ drRect.rect.y2 = dataS.readUint16LE();
+ drRect.subRectIndex = dataS.readUint16LE();
+ debug(3, "(%d, %d, %d, %d) -> %d", drRect.rect.x1, drRect.rect.y1, drRect.rect.x2, drRect.rect.y2, drRect.subRectIndex);
+ drDirectoryItem.offset = _drRects.size();
+ _drRects.push_back(drRect);
+ break;
+ }
+ case 7:
+ {
+ uint count = dataS.readUint16LE();
+ NRectArray *rectArray = new NRectArray();
+ debug(3, "NRectArray; count = %d", count);
+ for (uint j = 0; j < count; j++) {
+ NRect rect;
+ rect.x1 = dataS.readUint16LE();
+ rect.y1 = dataS.readUint16LE();
+ rect.x2 = dataS.readUint16LE();
+ rect.y2 = dataS.readUint16LE();
+ debug(3, "(%d, %d, %d, %d)", rect.x1, rect.y1, rect.x2, rect.y2);
+ rectArray->push_back(rect);
+ }
+ drDirectoryItem.offset = _rectArrays.size();
+ _rectArrays.push_back(rectArray);
+ break;
+ }
+ }
+ _directory.push_back(drDirectoryItem);
+ }
+ }
+}
+
+void DataResource::unload() {
+ if (_resourceHandle != -1) {
+ _vm->_res->unloadResource(_resourceHandle);
+ _vm->_res->unuseResource(_resourceHandle);
+ _resourceHandle = -1;
+ // TODO: Clear arrays
+ }
+}
+
+NPoint DataResource::getPoint(uint32 nameHash) {
+ DataResource::DRDirectoryItem *drDirectoryItem = findDRDirectoryItem(nameHash, 1);
+ if (drDirectoryItem)
+ return _points[drDirectoryItem->offset];
+ return NPoint();
+}
+
+NPointArray *DataResource::getPointArray(uint32 nameHash) {
+ DataResource::DRDirectoryItem *drDirectoryItem = findDRDirectoryItem(nameHash, 2);
+ if (drDirectoryItem)
+ return _pointArrays[drDirectoryItem->offset];
+ return NULL;
+}
+
+HitRectList *DataResource::getHitRectList() {
+ // TODO
+ return NULL;
+}
+
+MessageList *DataResource::getMessageListAtPos(int16 klaymanX, int16 klaymanY, int16 mouseX, int16 mouseY) {
+ // TODO
+ return NULL;
+}
+
+DataResource::DRDirectoryItem *DataResource::findDRDirectoryItem(uint32 nameHash, uint16 type) {
+ for (Common::Array<DRDirectoryItem>::iterator it = _directory.begin(); it != _directory.end(); it++) {
+ if ((*it).nameHash == nameHash && (*it).type == type)
+ return &(*it);
+ }
+ return NULL;
+}
+
+// SoundResource
+
SoundResource::SoundResource(NeverhoodEngine *vm)
: _vm(vm) {
}
@@ -374,4 +621,20 @@ void SoundResource::play(uint32 fileHash, bool looping) {
void SoundResource::play() {
}
+uint32 calcHash(const char *value) {
+ uint32 hash = 0, shiftValue = 0;
+ while (*value != 0) {
+ char ch = *value++;
+ if (ch >= 'a' && ch <= 'z')
+ ch -= 32;
+ else if (ch >= '0' && ch <= '9')
+ ch += 22;
+ shiftValue += ch - 64;
+ if (shiftValue >= 32)
+ shiftValue -= 32;
+ hash ^= 1 << shiftValue;
+ }
+ return hash;
+}
+
} // End of namespace Neverhood
diff --git a/engines/neverhood/resource.h b/engines/neverhood/resource.h
index 610973c155..d273e7c9d9 100644
--- a/engines/neverhood/resource.h
+++ b/engines/neverhood/resource.h
@@ -23,8 +23,10 @@
#ifndef NEVERHOOD_RESOURCE_H
#define NEVERHOOD_RESOURCE_H
+#include "common/str.h"
#include "neverhood/neverhood.h"
#include "neverhood/graphics.h"
+#include "neverhood/staticdata.h"
namespace Neverhood {
@@ -119,6 +121,74 @@ protected:
uint32 _currFileHash;
};
+class TextResource {
+public:
+ TextResource(NeverhoodEngine *vm);
+ ~TextResource();
+ void load(uint32 fileHash);
+ void unload();
+ const char *getString(uint index, const char *&textEnd);
+ uint getCount() const { return _count;}
+protected:
+ NeverhoodEngine *_vm;
+ int _resourceHandle;
+ byte *_textData;
+ uint _count;
+};
+
+/* DataResource
+ 1 Single NPoint
+ 2 Array of NPoints
+ 3 Array of NRects
+ 4 MessageList
+ 5 SubRectList
+ 6 RectList
+*/
+
+class DataResource {
+public:
+ DataResource(NeverhoodEngine *vm);
+ ~DataResource();
+ void load(uint32 fileHash);
+ void unload();
+ NPoint getPoint(uint32 nameHash);
+ NPointArray *getPointArray(uint32 nameHash);
+ HitRectList *getHitRectList();
+ MessageList *getMessageListAtPos(int16 klaymanX, int16 klaymanY, int16 mouseX, int16 mouseY);
+protected:
+
+ struct DRDirectoryItem {
+ uint32 nameHash;
+ uint16 offset;
+ uint16 type;
+ };
+
+ struct DRRect {
+ NRect rect;
+ uint16 subRectIndex;
+ };
+
+ struct DRSubRect {
+ NRect rect;
+ uint32 messageListHash;
+ uint16 messageListItemIndex;
+ };
+
+ typedef Common::Array<DRSubRect> DRSubRectList;
+
+ NeverhoodEngine *_vm;
+ int _resourceHandle;
+ Common::Array<DRDirectoryItem> _directory;
+ Common::Array<NPoint> _points;
+ Common::Array<NPointArray*> _pointArrays;
+ Common::Array<NRectArray*> _rectArrays;
+ Common::Array<HitRectList*> _hitRectLists;
+ Common::Array<MessageList*> _messageLists;
+ Common::Array<DRRect> _drRects;
+ Common::Array<DRSubRectList*> _drSubRectLists;
+ DataResource::DRDirectoryItem *findDRDirectoryItem(uint32 nameHash, uint16 type);
+};
+
// TODO: Dummy class atm
class SoundResource {
@@ -131,6 +201,8 @@ protected:
NeverhoodEngine *_vm;
};
+uint32 calcHash(const char *value);
+
} // End of namespace Neverhood
#endif /* NEVERHOOD_RESOURCE_H */
diff --git a/engines/neverhood/sprite.cpp b/engines/neverhood/sprite.cpp
index 4996bdd28a..87fd13153b 100644
--- a/engines/neverhood/sprite.cpp
+++ b/engines/neverhood/sprite.cpp
@@ -104,7 +104,7 @@ StaticSprite::StaticSprite(NeverhoodEngine *vm, const char *filename, int surfac
: Sprite(vm, 0), _spriteResource(vm) {
_name = "StaticSprite";
- // TODO init(calcHash(filename), surfacePriority, x, y, width, height);
+ init(calcHash(filename), surfacePriority, x, y, width, height);
}
@@ -288,8 +288,7 @@ void AnimatedSprite::updateAnim() {
if (_animResource.loadInternal(_fileHash2)) {
_currAnimFileHash = _fileHash2;
} else {
- debug("TODO");
- // TODO _animResource.loadInternal(calcHash("sqDefault"));
+ _animResource.loadInternal(calcHash("sqDefault"));
_currAnimFileHash = 0;
}
if (_replOldColor != _replNewColor) {
@@ -320,8 +319,7 @@ void AnimatedSprite::updateAnim() {
if (_animResource.loadInternal(_fileHash1)) {
_currAnimFileHash = _fileHash1;
} else {
- debug("TODO");
- // TODO _animResource.loadInternal(calcHash("sqDefault"));
+ _animResource.loadInternal(calcHash("sqDefault"));
_currAnimFileHash = 0;
}
if (_replOldColor != _replNewColor) {
@@ -334,8 +332,7 @@ void AnimatedSprite::updateAnim() {
if (_animResource.loadInternal(_fileHash1)) {
_currAnimFileHash = _fileHash1;
} else {
- debug("TODO");
- // TODO _animResource.loadInternal(calcHash("sqDefault"));
+ _animResource.loadInternal(calcHash("sqDefault"));
_currAnimFileHash = 0;
}
if (_replOldColor != _replNewColor) {