diff options
author | johndoe123 | 2011-07-16 11:01:08 +0000 |
---|---|---|
committer | Willem Jan Palenstijn | 2013-05-08 20:38:48 +0200 |
commit | a23b694c94d318b3e06f450189aab82b3908fcc5 (patch) | |
tree | 48d9ef4655acc12a3e7483d0ab341d59705c2dbe /engines | |
parent | 0bfb52df74ac47a4842c66d40fd0ae5efc5d6af6 (diff) | |
download | scummvm-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')
-rw-r--r-- | engines/neverhood/graphics.cpp | 46 | ||||
-rw-r--r-- | engines/neverhood/graphics.h | 18 | ||||
-rw-r--r-- | engines/neverhood/module1000.cpp | 204 | ||||
-rw-r--r-- | engines/neverhood/module1000.h | 16 | ||||
-rw-r--r-- | engines/neverhood/navigationscene.cpp | 6 | ||||
-rw-r--r-- | engines/neverhood/neverhood.cpp | 14 | ||||
-rw-r--r-- | engines/neverhood/resource.cpp | 263 | ||||
-rw-r--r-- | engines/neverhood/resource.h | 72 | ||||
-rw-r--r-- | engines/neverhood/sprite.cpp | 11 |
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 ¶m, 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 ¶m, 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 ¶m, Entity *sender); }; +// Scene1005 + +class Scene1005 : public Scene { +public: + Scene1005(NeverhoodEngine *vm, Module *parentModule, int which); + virtual ~Scene1005(); +protected: + uint32 handleMessage(int messageNum, const MessageParam ¶m, 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 ¶m, 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) { |