diff options
Diffstat (limited to 'engines/neverhood')
31 files changed, 4561 insertions, 159 deletions
diff --git a/engines/neverhood/blbarchive.cpp b/engines/neverhood/blbarchive.cpp index 2e29485d58..6a047cab46 100644 --- a/engines/neverhood/blbarchive.cpp +++ b/engines/neverhood/blbarchive.cpp @@ -105,12 +105,11 @@ void BlbArchive::load(uint index, byte *buffer, uint32 size) { byte *BlbArchive::getEntryExtData(uint index) { BlbArchiveEntry &entry = _entries[index]; - return _extData && entry.extDataOfs != 0 ? &_extData[entry.extDataOfs - 1] : NULL; + return (_extData && entry.extDataOfs != 0) ? &_extData[entry.extDataOfs - 1] : NULL; } Common::SeekableReadStream *BlbArchive::createStream(uint index) { const BlbArchiveEntry &entry = _entries[index]; - //debug("entry.offset = %08X; entry.offset + entry.diskSize = %08X", entry.offset, entry.offset + entry.diskSize); return new Common::SafeSubReadStream(&_fd, entry.offset, entry.offset + entry.diskSize); } diff --git a/engines/neverhood/collisionman.cpp b/engines/neverhood/collisionman.cpp index 87ec0cdcad..4296b91a10 100644 --- a/engines/neverhood/collisionman.cpp +++ b/engines/neverhood/collisionman.cpp @@ -52,7 +52,7 @@ void CollisionMan::setHitRects(HitRectList *hitRects) { } void CollisionMan::clearHitRects() { - _hitRects = 0; + _hitRects = NULL; } HitRect *CollisionMan::findHitRectAtPos(int16 x, int16 y) { @@ -82,7 +82,12 @@ void CollisionMan::addSprite(Sprite *sprite) { } void CollisionMan::removeSprite(Sprite *sprite) { - // TODO + for (uint index = 0; index < _sprites.size(); index++) { + if (_sprites[index] == sprite) { + _sprites.remove_at(index); + break; + } + } } void CollisionMan::clearSprites() { diff --git a/engines/neverhood/diskplayerscene.cpp b/engines/neverhood/diskplayerscene.cpp new file mode 100644 index 0000000000..dd2c837dbd --- /dev/null +++ b/engines/neverhood/diskplayerscene.cpp @@ -0,0 +1,563 @@ +/* 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/diskplayerscene.h" +#include "neverhood/mouse.h" + +namespace Neverhood { + +// TODO: Maybe move hash tables into neverhood.dat + +static const uint32 kDiskplayerPaletteFileHashes[] = { + 0x03B78240, + 0x34B32B08, + 0x4F2569D4, + 0x07620590, + 0x38422401 +}; + +static const byte kDiskplayerInitArray[] = { + 2, 1, 4, 5, 3, 11, 8, 6, 7, 9, 10, 17, 16, 18, 19, 20, 15, 14, 13, 12 +}; + +static const uint32 kDiskplayerSmackerFileHashes[] = { + 0x010A2810, + 0x020A2810, + 0x040A2810, + 0x080A2810, + 0x100A2810, + 0x200A2810, + 0x400A2810, + 0x800A2810, + 0x000A2811, + 0x010C2810, + 0x020C2810, + 0x040C2810, + 0x080C2810, + 0x100C2810, + 0x200C2810, + 0x400C2810, + 0x800C2810, + 0x000C2811, + 0x000C2812, + 0x02002810, + 0x04002810 +}; + +static const uint32 kDiskplayerSlotFileHashes1[] = { + 0x81312280, + 0x01312281, + 0x01312282, + 0x01312284, + 0x01312288, + 0x01312290, + 0x013122A0, + 0x013122C0, + 0x01312200, + 0x82312280, + 0x02312281, + 0x02312282, + 0x02312284, + 0x02312288, + 0x02312290, + 0x023122A0, + 0x023122C0, + 0x02312200, + 0x02312380, + 0x04312281 +}; + +static const uint32 kDiskplayerSlotFileHashes2[] = { + 0x90443A00, + 0x90443A18, + 0x90443A28, + 0x90443A48, + 0x90443A88, + 0x90443B08, + 0x90443808, + 0x90443E08, + 0x90443208, + 0xA0443A00, + 0xA0443A18, + 0xA0443A28, + 0xA0443A48, + 0xA0443A88, + 0xA0443B08, + 0xA0443808, + 0xA0443E08, + 0xA0443208, + 0xA0442A08, + 0xC0443A18 +}; + +static const uint32 kDiskplayerSlotFileHashes3[] = { + 0x10357320, + 0x10557320, + 0x10957320, + 0x11157320, + 0x12157320, + 0x14157320, + 0x18157320, + 0x00157320, + 0x30157320, + 0x1035B320, + 0x1055B320, + 0x1095B320, + 0x1115B320, + 0x1215B320, + 0x1415B320, + 0x1815B320, + 0x0015B320, + 0x3015B320, + 0x5015B320, + 0x10543320 +}; + +static const uint32 kDiskplayerSlotFileHashes4[] = { + 0xDC8020E4, + 0xDC802164, + 0xDC802264, + 0xDC802464, + 0xDC802864, + 0xDC803064, + 0xDC800064, + 0xDC806064, + 0xDC80A064, + 0xDC8020E7, + 0xDC802167, + 0xDC802267, + 0xDC802467, + 0xDC802867, + 0xDC803067, + 0xDC800067, + 0xDC806067, + 0xDC80A067, + 0xDC812067, + 0xDC802161 +}; + +Class494::Class494(NeverhoodEngine *vm) + : AnimatedSprite(vm, 1100) { + + createSurface1(0x100B90B4, 1200); + _x = 211; + _y = 195; + setFileHash(0x100B90B4, 0, -1); + _newHashListIndex = 0; + _needRefresh = true; + updatePosition(); + _surface->setVisible(false); +} + +uint32 Class494::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x3002: + removeCallbacks(); + break; + } + return messageResult; +} + +void Class494::sub43BE00() { + setFileHash1(); + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&Sprite::handleMessage); + _surface->setVisible(false); +} + +void Class494::sub43BE20() { + setFileHash(0x100B90B4, 0, -1); + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&Class494::handleMessage); + SetAnimationCallback3(&Class494::sub43BE00); + _surface->setVisible(true); +} + +DiskplayerPlayButton::DiskplayerPlayButton(NeverhoodEngine *vm, DiskplayerScene *diskplayerScene) + : StaticSprite(vm, 1400), _soundResource1(vm), _soundResource2(vm), + _diskplayerScene(diskplayerScene), _isPlaying(false) { + + _spriteResource.load2(0x24A4A664); + createSurface(400, _spriteResource.getDimensions().width, _spriteResource.getDimensions().height); + _drawRect.x = 0; + _drawRect.y = 0; + _drawRect.width = _spriteResource.getDimensions().width; + _drawRect.height = _spriteResource.getDimensions().height; + _deltaRect.x = 0; + _deltaRect.y = 0; + _deltaRect.width = _spriteResource.getDimensions().width; + _deltaRect.height = _spriteResource.getDimensions().height; + _x = _spriteResource.getPosition().x; + _y = _spriteResource.getPosition().y; + _surface->setVisible(false); + processDelta(); + _needRefresh = true; + StaticSprite::update(); + _soundResource1.load(0x44043000); + _soundResource2.load(0x44045000); + SetMessageHandler(&DiskplayerPlayButton::handleMessage); +} + +uint32 DiskplayerPlayButton::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = 0; + Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x1011: + if (!_diskplayerScene->getFlag3()) { + if (_isPlaying) { + _diskplayerScene->sendMessage(0x2001, 0, this); + release(); + } else { + _diskplayerScene->sendMessage(0x2000, 0, this); + press(); + } + } + StaticSprite::update(); + messageResult = 1; + break; + } + return messageResult; +} + +void DiskplayerPlayButton::press() { + if (!_isPlaying) { + _surface->setVisible(true); + StaticSprite::update(); + _soundResource1.play(); + _isPlaying = true; + } +} + +void DiskplayerPlayButton::release() { + if (_isPlaying) { + _surface->setVisible(false); + StaticSprite::update(); + _soundResource2.play(); + _isPlaying = false; + } +} + +DiskplayerSlot::DiskplayerSlot(NeverhoodEngine *vm, DiskplayerScene *diskplayerScene, int elementIndex, int value) + : Entity(vm, 0), _diskplayerScene(diskplayerScene), _soundResource(vm), _elementIndex(elementIndex), + _value(value), _flag2(false), _flag(false), _countdown(0), _initialCountdown(2), + _inactiveSlot(NULL), _appearSlot(NULL), _activeSlot(NULL) { + + if (value != 0 && elementIndex < 20) { + _inactiveSlot = _diskplayerScene->addSprite(new StaticSprite(_vm, kDiskplayerSlotFileHashes1[_elementIndex], 1100)); + _appearSlot = _diskplayerScene->addSprite(new StaticSprite(_vm, kDiskplayerSlotFileHashes2[_elementIndex], 1000)); + _activeSlot = _diskplayerScene->addSprite(new StaticSprite(_vm, kDiskplayerSlotFileHashes3[_elementIndex], 1100)); + _inactiveSlot->getSurface()->setVisible(false); + _appearSlot->getSurface()->setVisible(false); + _activeSlot->getSurface()->setVisible(false); + _soundResource.load(0x46210074); + // TODO sound panning stuff + } else if (elementIndex != 20) { + _activeSlot = _diskplayerScene->addSprite(new StaticSprite(_vm, kDiskplayerSlotFileHashes4[_elementIndex], 1100)); + _activeSlot->getSurface()->setVisible(false); + } + SetUpdateHandler(&DiskplayerSlot::update); +} + +void DiskplayerSlot::update() { + if (_countdown != 0 && (--_countdown == 0)) { + if (_flag) { + if (_inactiveSlot) { + _inactiveSlot->getSurface()->setVisible(true); + } + if (_activeSlot) { + _activeSlot->getSurface()->setVisible(false); + } + _countdown = _initialCountdown / 2; + } else { + if (_inactiveSlot) { + _inactiveSlot->getSurface()->setVisible(false); + } + if (_activeSlot) { + _activeSlot->getSurface()->setVisible(true); + } + _countdown = _initialCountdown; + } + _flag = !_flag; + } +} + +void DiskplayerSlot::appear() { + if (_inactiveSlot) { + _inactiveSlot->getSurface()->setVisible(true); + } + if (_appearSlot) { + _appearSlot->getSurface()->setVisible(true); + } + if (_inactiveSlot) { + _soundResource.play(); + } +} + +void DiskplayerSlot::play() { + if (!_flag2) { + if (_inactiveSlot) { + _inactiveSlot->getSurface()->setVisible(false); + } + if (_activeSlot) { + _activeSlot->getSurface()->setVisible(true); + } + _flag = true; + _countdown = 0; + } +} + +void DiskplayerSlot::activate() { + if (!_flag2) { + _countdown = _initialCountdown; + } +} + +void DiskplayerSlot::stop() { + if (!_flag2) { + if (_inactiveSlot) { + _inactiveSlot->getSurface()->setVisible(true); + } + if (_activeSlot) { + _activeSlot->getSurface()->setVisible(false); + } + _flag = false; + _countdown = 0; + } +} + +DiskplayerScene::DiskplayerScene(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule, true), _which(which), _diskIndex(0), _appearCountdown(0), _tuneInCountdown(0), + _fullFlag(false), _flag3(false), _inputDisabled(true), _updateStatus(0) { + + int count = 0; + + _surfaceFlag = true; + + _background = addBackground(new DirtyBackground(_vm, 0x8A000044, 0, 0)); + _palette = new Palette(_vm, kDiskplayerPaletteFileHashes[_which]); + _playButton = new DiskplayerPlayButton(_vm, this); + addSprite(_playButton); + _vm->_collisionMan->addSprite(_playButton); + _class494 = new Class494(_vm); + addSprite(_class494); + + // DEBUG: Give all disks + for (int i = 0; i < 19; i++) { + setSubVar(0x02720344, i, 1); + } + + for (int i = 0; i < 20; i++) { + _diskAvailable[i] = 0; + if (getSubVar(0x02720344, i)) + count++; + } + + for (int i = 0; i < count; i++) { + _diskAvailable[kDiskplayerInitArray[i] - 1] = 1; + } + + for (int i = 0; i < 20; i++) { + _diskSlots[i] = new DiskplayerSlot(_vm, this, i, _diskAvailable[i]); + addEntity(_diskSlots[i]); + } + + _fullFlag = count == 20; + + if (_fullFlag && !getGlobalVar(0xC0780812)) + _flag3 = true; + + _flag4 = _flag3; + + _class650 = new DiskplayerSlot(_vm, this, 20, 0); + addEntity(_class650); + + _mouseCursor = addSprite(new Mouse435(_vm, 0x000408A8, 20, 620)); + _mouseCursor->getSurface()->setVisible(false); + + _smackerPlayer = new SmackerPlayer(_vm, this, 0x08288103, false, true); + addEntity(_smackerPlayer); + addSurface(_smackerPlayer->getSurface()); + _smackerPlayer->setDrawPos(154, 86); + // TODO _smackerPlayer->gotoFrame(0); + + _palette->usePalette(); + + SetMessageHandler(&DiskplayerScene::handleMessage); + SetUpdateHandler(&DiskplayerScene::update); + _appearCountdown = 6; + +} + +void DiskplayerScene::update() { + Scene::update(); + + debug("_updateStatus = %d", _updateStatus); + + if (_updateStatus == 1) { + if (_smackerPlayer->getFrameNumber() == _smackerPlayer->getFrameCount() - 1) { + if (_diskAvailable[_diskIndex]) { + playDisk(); + } else { + playStatic(); + } + } + } else if (_updateStatus == 2) { + if (_smackerPlayer->getFrameNumber() == _smackerPlayer->getFrameCount() - 1) { + _diskSlots[_diskIndex]->stop(); + _diskIndex++; + if (_fullFlag) { + if (_diskIndex == 20) { + if (_flag3) { + playDisk(); + _updateStatus = 3; + } else { + _diskIndex = 0; + stop(); + } + } else { + playDisk(); + } + } else { + if (_diskIndex == 20) { + _diskIndex = 0; + stop(); + } else { + tuneIn(); + } + } + } + } else if (_updateStatus == 3) { + if (_smackerPlayer->getFrameNumber() == 133) { + _class494->sub43BE20(); + setGlobalVar(0xC0780812, 1); + } else if (_smackerPlayer->getFrameNumber() == _smackerPlayer->getFrameCount() - 1) { + for (int i = 0; i < 20; i++) { + _diskSlots[i]->setFlag2(false); + _diskSlots[i]->stop(); + } + _diskIndex = 0; + stop(); + _mouseCursor->getSurface()->setVisible(true); + _flag3 = false; + } + } + + if (_appearCountdown != 0 && (--_appearCountdown == 0)) { + _diskSlots[_diskIndex]->appear(); + if (_flag3) { + _diskSlots[_diskIndex]->activate(); + _diskSlots[_diskIndex]->setFlag2(true); + } + _diskIndex++; + while (_diskAvailable[_diskIndex] == 0 && _diskIndex < 19) + _diskIndex++; + if (_diskIndex < 20) { + _appearCountdown = 1; + } else { + _diskIndex = 0; + _inputDisabled = false; + if (_flag3) { + _playButton->press(); + _tuneInCountdown = 2; + } else { + _mouseCursor->getSurface()->setVisible(true); + _diskSlots[_diskIndex]->activate(); + } + } + } + + if (_tuneInCountdown != 0 && (--_tuneInCountdown == 0)) { + playDisk(); + } + +} + +uint32 DiskplayerScene::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = 0; + Scene::handleMessage(messageNum, param, sender); + if (!_inputDisabled) { + switch (messageNum) { + case 0x0001: + // TODO: Debug/Cheat + if (param.asPoint().x <= 20 || param.asPoint().x >= 620) { + _parentModule->sendMessage(0x1009, 0, this); + } else if (!_flag3 && + param.asPoint().x > 38 && param.asPoint().x < 598 && + param.asPoint().y > 400 && param.asPoint().y < 460) { + + _diskSlots[_diskIndex]->stop(); + _diskIndex = (param.asPoint().x - 38) / 28; + _diskSlots[_diskIndex]->activate(); + if (_updateStatus == 2) { + if (_diskAvailable[_diskIndex]) { + playDisk(); + } else { + playStatic(); + } + } + } + break; + // case 0x000D: TODO: Debug/Cheat + case 0x2000: + tuneIn(); + break; + case 0x2001: + stop(); + break; + } + } + return messageResult; +} + +void DiskplayerScene::stop() { + _smackerPlayer->open(0x08288103, true); + _palette->usePalette(); + _playButton->release(); + _updateStatus = 0; + _diskSlots[_diskIndex]->activate(); +} + +void DiskplayerScene::tuneIn() { + _smackerPlayer->open(0x900001C1, false); + _palette->usePalette(); + _playButton->release(); + _updateStatus = 1; + _diskSlots[_diskIndex]->activate(); +} + +void DiskplayerScene::playDisk() { + _smackerPlayer->open(kDiskplayerSmackerFileHashes[_diskIndex], false); + _palette->usePalette(); + _updateStatus = 2; + _diskSlots[_diskIndex]->play(); +} + +void DiskplayerScene::playStatic() { + _smackerPlayer->open(0x90000101, false); + _palette->usePalette(); + _playButton->release(); + _updateStatus = 2; + _diskSlots[_diskIndex]->activate(); +} + +} // End of namespace Neverhood diff --git a/engines/neverhood/diskplayerscene.h b/engines/neverhood/diskplayerscene.h new file mode 100644 index 0000000000..7969a7a03b --- /dev/null +++ b/engines/neverhood/diskplayerscene.h @@ -0,0 +1,110 @@ +/* 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_DISKPLAYERSCENE_H +#define NEVERHOOD_DISKPLAYERSCENE_H + +#include "neverhood/neverhood.h" +#include "neverhood/resourceman.h" +#include "neverhood/scene.h" +#include "neverhood/smackerplayer.h" + +namespace Neverhood { + +class DiskplayerScene; + +class Class494 : public AnimatedSprite { +public: + Class494(NeverhoodEngine *vm); + void sub43BE20(); +protected: + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void sub43BE00(); +}; + +class DiskplayerPlayButton : public StaticSprite { +public: + DiskplayerPlayButton(NeverhoodEngine *vm, DiskplayerScene *diskplayerScene); + void press(); + void release(); +protected: + DiskplayerScene *_diskplayerScene; + SoundResource _soundResource1; + SoundResource _soundResource2; + bool _isPlaying; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class DiskplayerSlot : public Entity { +public: + DiskplayerSlot(NeverhoodEngine *vm, DiskplayerScene *diskplayerScene, int elementIndex, int value); + void activate(); + void stop(); + void appear(); + void play(); + void setFlag2(bool value) { _flag2 = value; } +protected: + DiskplayerScene *_diskplayerScene; + SoundResource _soundResource; + Sprite *_inactiveSlot; + Sprite *_appearSlot; + Sprite *_activeSlot; + int _elementIndex; + int _initialCountdown; + int _countdown; + bool _flag2; + int _value; + bool _flag; + void update(); +}; + +class DiskplayerScene : public Scene { +public: + DiskplayerScene(NeverhoodEngine *vm, Module *parentModule, int which); + bool getFlag3() const { return _flag3; } +protected: + SmackerPlayer *_smackerPlayer; + DiskplayerPlayButton *_playButton; + Class494 *_class494; + DiskplayerSlot *_diskSlots[20]; + DiskplayerSlot *_class650; + int _updateStatus; + byte _diskAvailable[20]; + bool _flag4; + int _which; + int _diskIndex; + int _appearCountdown; + int _tuneInCountdown; + bool _fullFlag; + bool _inputDisabled; + bool _flag3; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void stop(); + void tuneIn(); + void playDisk(); + void playStatic(); +}; + +} // End of namespace Neverhood + +#endif /* NEVERHOOD_DISKPLAYERSCENE_H */ diff --git a/engines/neverhood/gamemodule.cpp b/engines/neverhood/gamemodule.cpp index 95a6a5f48a..02ae2a7cac 100644 --- a/engines/neverhood/gamemodule.cpp +++ b/engines/neverhood/gamemodule.cpp @@ -25,7 +25,10 @@ #include "neverhood/graphics.h" #include "neverhood/module1000.h" #include "neverhood/module1200.h" +#include "neverhood/module1400.h" #include "neverhood/module1500.h" +#include "neverhood/module1700.h" +#include "neverhood/module1800.h" #include "neverhood/module2300.h" namespace Neverhood { @@ -110,8 +113,13 @@ void GameModule::startup() { // TODO: Displaying of error text probably not needed in ScummVM // createModule1500(0); // Logos and intro video //Real // createModule1000(-1); -// createModule2300(0); - createModule1200(0); +// createModule2300(2); + _vm->gameState().sceneNum = 6; + //createModule1200(-1); + //createModule1800(-1); + //createModule1700(-1); + //createModule1700(1); + createModule1400(-1); } void GameModule::createModule1000(int which) { @@ -149,6 +157,7 @@ void GameModule::updateModule1200() { delete _childObject; _childObject = NULL; if (_field20 == 1) { + error("// TODO createModule2600(0);"); // TODO createModule2600(0); // TODO _childObject->handleUpdate(); } else { @@ -158,6 +167,29 @@ void GameModule::updateModule1200() { } } +void GameModule::createModule1400(int which) { + setGlobalVar(0x91080831, 0x00AD0012); + _childObject = new Module1400(_vm, this, which); + SetUpdateHandler(&GameModule::updateModule1400); +} + +void GameModule::updateModule1400() { + if (!_childObject) + return; + _childObject->handleUpdate(); + if (_done) { + _done = false; + delete _childObject; + _childObject = NULL; + if (_field20 == 1) { + error("WEIRD!"); + } else { + // TODO createModule1600(1); + // TODO _childObject->handleUpdate(); + } + } +} + void GameModule::createModule1500(int which) { _someFlag1 = false; setGlobalVar(0x91080831, 0x00F10114); @@ -178,6 +210,61 @@ void GameModule::updateModule1500() { } } +void GameModule::createModule1700(int which) { + setGlobalVar(0x91080831, 0x04212331); + _childObject = new Module1700(_vm, this, which); + SetUpdateHandler(&GameModule::updateModule1700); +} + +void GameModule::updateModule1700() { + if (!_childObject) + return; + _childObject->handleUpdate(); + if (_done) { + _done = false; + delete _childObject; + _childObject = NULL; + debug("Module1700 done; _field20 = %d", _field20); + if (_field20 == 1) { + // TODO createModule2900(3); + // TODO _childObject->handleUpdate(); + } else { + // TODO createModule1600(2); + // TODO _childObject->handleUpdate(); + } + } +} + +void GameModule::createModule1800(int which) { + setGlobalVar(0x91080831, 0x04A14718); + _childObject = new Module1800(_vm, this, which); + SetUpdateHandler(&GameModule::updateModule1800); +} + +void GameModule::updateModule1800() { + if (!_childObject) + return; + _childObject->handleUpdate(); + if (_done) { + _done = false; + delete _childObject; + _childObject = NULL; + if (_field20 == 1) { + // TODO GameState_clear(); + // TODO GameModule_handleKeyEscape(); + } else if (_field20 == 2) { + // TODO createModule2700(0); + // TODO _childObject->handleUpdate(); + } else if (_field20 == 3) { + // TODO createModule3000(3); + // TODO _childObject->handleUpdate(); + } else { + // TODO createModule2800(0); + // TODO _childObject->handleUpdate(); + } + } +} + void GameModule::createModule2300(int which) { setGlobalVar(0x91080831, 0x1A214010); _childObject = new Module2300(_vm, this, which); @@ -223,13 +310,11 @@ void GameModule::updateModule2300() { } void GameModule::createModule2400(int which) { - debug("createModule2400"); - _vm->_system->quit(); + error("createModule2400"); } void GameModule::createModule3000(int which) { - debug("createModule3000"); - _vm->_system->quit(); + error("createModule3000"); } } // End of namespace Neverhood diff --git a/engines/neverhood/gamemodule.h b/engines/neverhood/gamemodule.h index d95c31e47d..344a78ff60 100644 --- a/engines/neverhood/gamemodule.h +++ b/engines/neverhood/gamemodule.h @@ -53,8 +53,14 @@ protected: void updateModule1000(); void createModule1200(int which); void updateModule1200(); + void createModule1400(int which); + void updateModule1400(); void createModule1500(int which); void updateModule1500(); + void createModule1700(int which); + void updateModule1700(); + void createModule1800(int which); + void updateModule1800(); void createModule2200(int which); void createModule2300(int which); void updateModule2300(); diff --git a/engines/neverhood/graphics.cpp b/engines/neverhood/graphics.cpp index e46d4eaf86..204e38628d 100644 --- a/engines/neverhood/graphics.cpp +++ b/engines/neverhood/graphics.cpp @@ -43,7 +43,7 @@ BaseSurface::BaseSurface(NeverhoodEngine *vm, int priority, int16 width, int16 h _clipRect.x2 = 640; _clipRect.y2 = 480; _surface = new Graphics::Surface(); - _surface->create(width, height, Graphics::PixelFormat::createFormatCLUT8()); + _surface->create(_sysRect.width, _sysRect.height, Graphics::PixelFormat::createFormatCLUT8()); } BaseSurface::~BaseSurface() { @@ -51,7 +51,6 @@ BaseSurface::~BaseSurface() { } void BaseSurface::draw() { - debug(8, "BaseSurface::draw()"); if (_surface && _visible && _drawRect.width > 0 && _drawRect.height > 0) { // TODO: _sysRect alternate drawing code (is that used?) _vm->_screen->drawSurface2(_surface, _drawRect, _clipRect, _transparent); @@ -223,9 +222,9 @@ void unpackSpriteRle(byte *source, int width, int height, byte *dest, int destPi skip = READ_LE_UINT16(source); copy = READ_LE_UINT16(source + 2); source += 4; - if (!flipX) + if (!flipX) { memcpy(dest + skip, source, copy); - else { + } else { byte *flipDest = dest + width - skip - 1; for (int xc = 0; xc < copy; xc++) { *flipDest-- = source[xc]; @@ -247,8 +246,6 @@ void unpackSpriteRleRepl(byte *source, int width, int height, byte *dest, int de // TODO: Flip Y - debug("unpackSpriteRleRepl(%d, %d)", oldColor, newColor); - int16 rows, chunks; int16 skip, copy; diff --git a/engines/neverhood/klayman.cpp b/engines/neverhood/klayman.cpp index 91de87d7f5..b24e3eb6b4 100644 --- a/engines/neverhood/klayman.cpp +++ b/engines/neverhood/klayman.cpp @@ -266,6 +266,172 @@ uint32 Klayman::handleMessage41EFE0(int messageNum, const MessageParam ¶m, E return messageResult; } +void Klayman::sub421350() { + _status2 = 0; + _flagE5 = true; + setFileHash(0x582EC138, 0, -1); + _counter = 0; + SetSpriteCallback(NULL); + SetUpdateHandler(&Klayman::update41D1C0); + SetMessageHandler(&Klayman::handleMessage41D360); + _counter3 = 0; + _counterMax = 8; + _counter3Max = _vm->_rnd->getRandomNumber(64) + 24; +} + +void Klayman::update41D1C0() { + update(); + _counter++; + if (_counter >= _counterMax) { + _counter = 0; + if (_table) { + int randomValue = _vm->_rnd->getRandomNumber(_tableMaxValue); + for (int i = 0; i < _tableCount; i++) { + if (randomValue < _table[_tableCount].value) { + (this->*(_table[_tableCount].callback))(); + _counterMax = _vm->_rnd->getRandomNumber(128) + 24; + break; + } + randomValue -= _table[_tableCount].value; + } + } + } else { + _counter3++; + if (_counter3 >= _counter3Max) { + _counter3 = 0; + _counter3Max = _vm->_rnd->getRandomNumber(64) + 24; + sub4213F0(); + } + } +} + +void Klayman::sub4213F0() { + _status2 = 0; + _flagE5 = true; + setFileHash(0x5C24C018, 0, -1); + SetUpdateHandler(&Klayman::update); + SetMessageHandler(&Klayman::handleMessage41D480); + SetSpriteCallback(NULL); + SetAnimationCallback3(&Klayman::sub4213B0); +} + +void Klayman::sub4213B0() { + _status2 = 0; + _flagE5 = true; + setFileHash(0x5C24C018, 0, -1); + SetUpdateHandler(&Klayman::update41D1C0); + SetMessageHandler(&Klayman::handleMessage41D360); + SetSpriteCallback(NULL); +} + +void Klayman::sub420060() { + setDoDeltaX(((Sprite*)_attachedSprite)->getX() < _x ? 1 : 0); + if (!sub41CEB0(AnimationCallback(&Klayman::sub420060))) { + _status2 = 1; + _flagE5 = false; + setFileHash(0x1449C169, 0, -1); + SetUpdateHandler(&Klayman::update); + SetMessageHandler(&Klayman::handleMessage41D4C0); + SetSpriteCallback(NULL); + } +} + +void Klayman::sub41FFF0() { + setDoDeltaX(((Sprite*)_attachedSprite)->getX() < _x ? 1 : 0); + if (!sub41CEB0(AnimationCallback(&Klayman::sub41FFF0))) { + _status2 = 1; + _flagE5 = false; + setFileHash(0x0018C032, 0, -1); + SetUpdateHandler(&Klayman::update); + SetMessageHandler(&Klayman::handleMessage41D640); + SetSpriteCallback(NULL); + } +} + +uint32 Klayman::handleMessage41D640(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = handleMessage41D480(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0xC1380080) { + if (_attachedSprite) { + _attachedSprite->sendMessage(0x4806, 0, this); + _soundResource1.play(0xC8004340); + } + } else if (param.asInteger() == 0x02B20220) { + _soundResource1.play(0xC5408620); + } else if (param.asInteger() == 0x03020231) { + _soundResource1.play(0xD4C08010); + } else if (param.asInteger() == 0x67221A03) { + _soundResource1.play(0x44051000); + } else if (param.asInteger() == 0x925A0C1E) { + _soundResource1.play(0x40E5884D); + } + break; + } + return messageResult; +} + +void Klayman::sub4214D0() { + _status2 = 0; + _flagE5 = false; + setFileHash(0xD229823D, 0, -1); + SetUpdateHandler(&Klayman::update); + SetMessageHandler(&Klayman::handleMessage41D480); + SetSpriteCallback(NULL); +} + +void Klayman::sub421510() { + _status2 = 0; + _flagE5 = false; + setFileHash(0x9A2801E0, 0, -1); + SetUpdateHandler(&Klayman::update); + SetMessageHandler(&Klayman::handleMessage41D480); + SetSpriteCallback(NULL); +} + +void Klayman::sub421160() { + if (!sub41CEB0(AnimationCallback(&Klayman::sub421160))) { + _status2 = 2; + _flagE5 = false; + setFileHash(0x004AA310, 0, -1); + SetUpdateHandler(&Klayman::update); + SetMessageHandler(&Klayman::handleMessage41EC70); + SetSpriteCallback(&Klayman::spriteUpdate41F230); + } +} + +void Klayman::sub4212C0() { + if (!sub41CEB0(AnimationCallback(&Klayman::sub4212C0))) { + _status2 = 0; + _flagE5 = false; + setFileHash(0x392A0330, 0, -1); + SetUpdateHandler(&Klayman::update); + SetMessageHandler(&Klayman::handleMessage41EAB0); + SetSpriteCallback(&Klayman::spriteUpdate41F230); + } +} + +uint32 Klayman::handleMessage41EAB0(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = handleMessage41D480(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x001A2832) { + _soundResource1.play(0xC0E4884C); + } + break; + } + return messageResult; +} + +void Klayman::sub421310() { + _status2 = 0; + _flagE5 = false; + setFileHash(0x913AB120, 0, -1); + SetUpdateHandler(&Klayman::update); + SetMessageHandler(&Klayman::handleMessage41D480); + SetSpriteCallback(&Klayman::spriteUpdate41F230); +} + ///////////////////////////////////////////////////////////////// void Klayman::sub41D320(uint32 fileHash, AnimationCb callback) { @@ -460,7 +626,6 @@ uint32 Klayman::handleMessage41F140(int messageNum, const MessageParam ¶m, E void Klayman::sub41C930(int16 x, bool flag) { debug("Klayman::sub41C930(%d, %d)", x, flag); int16 xdiff = ABS(x - _x); - debug("xdiff = %d", xdiff); if (x == _x) { _x4 = x; if (!_flagE1 && !_flagE2 && !_flagE3) { @@ -623,7 +788,7 @@ void Klayman::sub41FB40() { _status2 = 1; _flagE2 = true; _flagE5 = true; - setDoDeltaX(_x4 < _x); + setDoDeltaX(_x4 < _x ? 1 : 0); setFileHash(0x5C48C506, 0, -1); SetUpdateHandler(&Klayman::update); SetMessageHandler(&Klayman::handleMessage41DD80); @@ -688,10 +853,7 @@ void Klayman::sub41F950() { _status2 = 0; _flagE1 = true; _flagE5 = true; - - debug("222222222222222222222 x = %d; x4 = %d", _x, _x4); - - setDoDeltaX(_x4 < _x); + setDoDeltaX(_x4 < _x ? 1 : 0); setFileHash(0x242C0198, 0, -1); SetUpdateHandler(&Klayman::update); SetMessageHandler(&Klayman::handleMessage41EC70); @@ -823,9 +985,6 @@ void Klayman::spriteUpdate41F320() { sendMessage(0x1019, 0, this); } else { HitRect *hitRectPrev = _vm->_collisionMan->findHitRectAtPos(_x, _y); - - debug("xxxxxxxxxxxxxxxxxxxxxxxxx xdelta = %d", xdelta); - _x += xdelta; if (_field114) { error("_field114"); @@ -876,7 +1035,7 @@ uint32 Klayman::handleMessage41E210(int messageNum, const MessageParam ¶m, E } void Klayman::sub41FF80() { - setDoDeltaX(((Sprite*)_attachedSprite)->getX() < _x); + setDoDeltaX(((Sprite*)_attachedSprite)->getX() < _x ? 1 : 0); if (!sub41CEB0(AnimationCallback(&Klayman::sub41FF80))) { _status2 = 1; _flagE5 = false; @@ -985,28 +1144,22 @@ void Klayman::sub41CD00(int16 x) { void Klayman::sub41CC40(int16 x1, int16 x2) { if (_x > x1) { if (_x == x1 + x2) { - debug("sub41CC40 #1"); _x4 = x1 + x2; setCallback2(NULL); sub41C7B0(); } else if (_x < x1 + x2) { - debug("sub41CC40 #2"); sub41CAC0(x1 + x2); } else { - debug("sub41CC40 #3"); sub41C930(x1 + x2, false); } } else { if (_x == x1 - x2) { - debug("sub41CC40 #4"); _x4 = x1 - x2; setCallback2(NULL); sub41C7B0(); } else if (_x > x1 - x2) { - debug("sub41CC40 #5"); sub41CAC0(x1 - x2); } else { - debug("sub41CC40 #6"); sub41C930(x1 - x2, false); } } @@ -1044,7 +1197,7 @@ void Klayman::sub41FBC0() { _status2 = 2; _flagE3 = true; _flagE5 = true; - setDoDeltaX(_x4 >= _x); + setDoDeltaX(_x4 >= _x ? 1 : 0); setFileHash(0x08B28116, 0, -1); SetUpdateHandler(&Klayman::update); SetMessageHandler(&Klayman::handleMessage41DF10); @@ -1641,6 +1794,68 @@ void Klayman::spriteUpdate41F5A0() { AnimatedSprite::updateDeltaXY(); } +void Klayman::sub420600() { + setDoDeltaX(((Sprite*)_attachedSprite)->getX() < _x ? 1 : 0); + _flagE4 = false; + _flagE5 = true; + setFileHash2(0x0C1CA072, 0x01084280, 0); + SetUpdateHandler(&Klayman::update); + SetSpriteCallback(&Klayman::spriteUpdate41F230); + SetMessageHandler(&Klayman::handleMessage41D970); +} + +void Klayman::sub420660() { + _attachedSprite->sendMessage(0x4807, 0, this); +} + +uint32 Klayman::handleMessage41D970(int messageNum, const MessageParam ¶m, Entity *sender) { + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x01084280) { + if (_attachedSprite) + _attachedSprite->sendMessage(0x480B, _doDeltaX ? 1 : 0, this); + } else if (param.asInteger() == 0x02421405) { + if (_flagE4 && _attachedSprite->hasMessageHandler() && _attachedSprite->sendMessage(0x480C, _doDeltaX ? 1 : 0, this) != 0) { + sub4205C0(); + } else { + setCallback1(AnimationCallback(&Klayman::sub420660)); + SetMessageHandler(&Klayman::handleMessage41D480); + } + } else if (param.asInteger() == 0x32180101) { + _soundResource1.play(0x405002D8); + } else if (param.asInteger() == 0x0A2A9098) { + _soundResource1.play(0x0460E2FA); + } + break; + case 0x480A: + _flagE4 = true; + return 0; + } + return handleMessage41D480(messageNum, param, sender); +} + +void Klayman::sub4205C0() { + _flagE4 = false; + _flagE5 = true; + setFileHash2(0x0C1CA072, 0x01084280, 0); + SetUpdateHandler(&Klayman::update); + SetSpriteCallback(&Klayman::spriteUpdate41F230); + SetMessageHandler(&Klayman::handleMessage41D970); +} + +void Klayman::sub420550() { + setDoDeltaX(((Sprite*)_attachedSprite)->getX() < _x ? 1 : 0); + if (!sub41CEB0(AnimationCallback(&Klayman::sub420550))) { + _status2 = 2; + _flagE4 = false; + _flagE5 = true; + setFileHash(0x0C1CA072, 0, -1); + SetUpdateHandler(&Klayman::update); + SetSpriteCallback(&Klayman::spriteUpdate41F230); + SetMessageHandler(&Klayman::handleMessage41D970); + } +} + //############################################################################## // KmScene1001 @@ -1705,7 +1920,7 @@ uint32 KmScene1001::xHandleMessage(int messageNum, const MessageParam ¶m) { } break; case 0x482D: - setDoDeltaX(_x > (int16)param.asInteger()); + setDoDeltaX(_x > (int16)param.asInteger() ? 1 : 0); sub41C7B0(); break; case 0x4836: @@ -2401,7 +2616,7 @@ uint32 KmScene1201::xHandleMessage(int messageNum, const MessageParam ¶m) { } break; case 0x4817: - setDoDeltaX(param.asInteger() != 0 ? 1 : 0); + setDoDeltaX(param.asInteger()); sub41C7B0(); break; case 0x481B: @@ -2563,4 +2778,271 @@ void KmScene1201::sub40E040() { } } +// KmScene1401 + +KmScene1401::KmScene1401(NeverhoodEngine *vm, Entity *parentScene, int16 x, int16 y) + : Klayman(vm, parentScene, x, y, 1000, 1000) { + + // Empty +} + +uint32 KmScene1401::xHandleMessage(int messageNum, const MessageParam ¶m) { + switch (messageNum) { + case 0x4001: + case 0x4800: + sub41C930(param.asPoint().x, false); + break; + case 0x4004: + setCallback2(AnimationCallback(&Klayman::sub41FC80)); + break; + case 0x480A: + if (param.asInteger() == 1) { + setCallback2(AnimationCallback(&Klayman::sub420600)); + } else { + setCallback2(AnimationCallback(&Klayman::sub420550)); + } + break; + case 0x4816: + if (param.asInteger() == 1) { + setCallback2(AnimationCallback(&Klayman::sub420120)); + } else if (param.asInteger() == 2) { + setCallback2(AnimationCallback(&Klayman::sub420170)); + } else { + setCallback2(AnimationCallback(&Klayman::sub4200D0)); + } + break; + case 0x4817: + setDoDeltaX(param.asInteger()); + sub41C7B0(); + break; + case 0x481B: + if (param.asPoint().y != 0) { + sub41CC40(param.asPoint().y, param.asPoint().x); + } else { + sub41CCE0(param.asPoint().x); + } + break; + case 0x481F: + if (param.asInteger() == 1) { + setCallback2(AnimationCallback(&Klayman::sub420930)); + } else if (param.asInteger() == 0) { + setCallback2(AnimationCallback(&Klayman::sub4208F0)); + } else { + setCallback2(AnimationCallback(&Klayman::sub420830)); + } + break; + case 0x482D: + setDoDeltaX(_x > (int16)param.asInteger() ? 1 : 0); + sub41C7B0(); + break; + case 0x482E: + if (param.asInteger() == 1) { + setCallback2(AnimationCallback(&Klayman::sub421030)); + } else { + setCallback2(AnimationCallback(&Klayman::sub420FE0)); + } + break; + case 0x482F: + if (param.asInteger() == 1) { + setCallback2(AnimationCallback(&Klayman::sub4210C0)); + } else { + setCallback2(AnimationCallback(&Klayman::sub421070)); + } + break; + } + return 0; +} + +// KmScene1402 + +KmScene1402::KmScene1402(NeverhoodEngine *vm, Entity *parentScene, int16 x, int16 y) + : Klayman(vm, parentScene, x, y, 1000, 1000) { + + SetFilterY(&Sprite::defFilterY); +} + +uint32 KmScene1402::xHandleMessage(int messageNum, const MessageParam ¶m) { + switch (messageNum) { + case 0x4001: + case 0x4800: + sub41C930(param.asPoint().x, false); + break; + case 0x4004: + setCallback2(AnimationCallback(&Klayman::sub41FC80)); + break; + case 0x480A: + if (param.asInteger() == 1) { + setCallback2(AnimationCallback(&Klayman::sub420600)); + } else { + setCallback2(AnimationCallback(&Klayman::sub420550)); + } + break; + case 0x4817: + setDoDeltaX(param.asInteger()); + sub41C7B0(); + break; + case 0x481B: + if (param.asPoint().y != 0) { + sub41CC40(param.asPoint().y, param.asPoint().x); + } else { + sub41CCE0(param.asPoint().x); + } + break; + case 0x481D: + setCallback2(AnimationCallback(&Klayman::sub4207A0)); + break; + case 0x481E: + setCallback2(AnimationCallback(&Klayman::sub4207F0)); + break; + } + return 0; +} + +// KmScene1705 + +KmScene1705::KmScene1705(NeverhoodEngine *vm, Entity *parentScene, int16 x, int16 y) + : Klayman(vm, parentScene, x, y, 1000, 1000), _flag(false) { + + // Empty +} + +uint32 KmScene1705::xHandleMessage(int messageNum, const MessageParam ¶m) { + uint32 messageResult = 0; + switch (messageNum) { + case 0x2000: + _flag = param.asInteger() != 0; + messageResult = 1; + break; + case 0x4001: + case 0x4800: + sub41C930(param.asPoint().x, false); + break; + case 0x4004: + if (_flag) { + setCallback2(AnimationCallback(&Klayman::sub421350)); + } else { + setCallback2(AnimationCallback(&Klayman::sub41FC80)); + } + break; + case 0x4803: + setCallback2(AnimationCallback(&KmScene1705::sub468A80)); + break; + case 0x4812: + if (param.asInteger() == 2) { + setCallback2(AnimationCallback(&Klayman::sub420060)); + } else if (param.asInteger() == 1) { + setCallback2(AnimationCallback(&Klayman::sub41FFF0)); + } else { + setCallback2(AnimationCallback(&Klayman::sub41FF80)); + } + break; + case 0x4817: + setDoDeltaX(param.asInteger()); + sub41C7B0(); + break; + case 0x481B: + if (param.asPoint().y != 0) { + sub41CC40(param.asPoint().y, param.asPoint().x); + } else { + sub41CCE0(param.asPoint().x); + } + break; + case 0x481D: + if (_flag) { + setCallback2(AnimationCallback(&Klayman::sub4214D0)); + } + break; + case 0x481E: + if (_flag) { + setCallback2(AnimationCallback(&Klayman::sub421510)); + } + break; + case 0x481F: + if (param.asInteger() == 1) { + setCallback2(AnimationCallback(&Klayman::sub4208B0)); + } else if (param.asInteger() == 0) { + setCallback2(AnimationCallback(&Klayman::sub420870)); + } else if (param.asInteger() == 4) { + setCallback2(AnimationCallback(&Klayman::sub420930)); + } else if (param.asInteger() == 3) { + setCallback2(AnimationCallback(&Klayman::sub4208F0)); + } else { + setCallback2(AnimationCallback(&Klayman::sub420830)); + } + break; + case 0x4834: + setCallback2(AnimationCallback(&Klayman::sub421160)); + break; + case 0x4835: + _parentScene->sendMessage(0x2000, 1, this); + _flag = true; + setCallback2(AnimationCallback(&Klayman::sub4212C0)); + break; + case 0x4836: + _parentScene->sendMessage(0x2000, 0, this); + _flag = false; + setCallback2(AnimationCallback(&Klayman::sub421310)); + break; + case 0x483D: + sub468AD0(); + break; + case 0x483E: + sub468B10(); + break; + } + return messageResult; +} + +uint32 KmScene1705::handleMessage4689A0(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = handleMessage41D480(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x4E0A2C24) { + _soundResource1.play(0x85B10BB8); + } else if (param.asInteger() == 0x4E6A0CA0) { + _soundResource1.play(0xC5B709B0); + } + break; + } + return messageResult; +} + +void KmScene1705::spriteUpdate468A30() { + updateDeltaXY(); + HitRect *hitRect = _vm->_collisionMan->findHitRectAtPos(_x, _y + 10); + if (hitRect->type == 0x5001) { + _y = hitRect->rect.y1; + processDelta(); + sendMessage(0x1019, 0, this); + } +} + +void KmScene1705::sub468A80() { + _status2 = 2; + _flagE5 = false; + setFileHash2(0xB93AB151, 0x40A100F8, 0); + SetUpdateHandler(&Klayman::update); + SetSpriteCallback(&KmScene1705::spriteUpdate468A30); + SetMessageHandler(&Klayman::handleMessage41D360); + SetAnimationCallback3(&Klayman::sub420420); +} + +void KmScene1705::sub468AD0() { + _status2 = 0; + _flagE5 = false; + setFileHash(0x5E0A4905, 0, -1); + SetUpdateHandler(&Klayman::update); + SetSpriteCallback(NULL); + SetMessageHandler(&KmScene1705::handleMessage4689A0); +} + +void KmScene1705::sub468B10() { + _status2 = 0; + _flagE5 = false; + setFileHash(0xD86E4477, 0, -1); + SetUpdateHandler(&Klayman::update); + SetSpriteCallback(NULL); + SetMessageHandler(&KmScene1705::handleMessage4689A0); +} + } // End of namespace Neverhood diff --git a/engines/neverhood/klayman.h b/engines/neverhood/klayman.h index 3682d75e69..5cb11abd10 100644 --- a/engines/neverhood/klayman.h +++ b/engines/neverhood/klayman.h @@ -85,6 +85,20 @@ public: void sub4207A0(); void sub4207F0(); void sub420F20(); + void sub421350(); + void sub4213F0(); + void sub4213B0(); + void sub420060(); + void sub41FFF0(); + void sub4214D0(); + void sub421510(); + void sub421160(); + void sub4212C0(); + void sub421310(); + void sub420600(); + void sub420660(); + void sub4205C0(); + void sub420550(); void spriteUpdate41F250(); void spriteUpdate41F5F0(); @@ -95,6 +109,11 @@ public: uint32 handleMessage41D360(int messageNum, const MessageParam ¶m, Entity *sender); uint32 handleMessage41D480(int messageNum, const MessageParam ¶m, Entity *sender); + void setKlaymanTable(const KlaymanTableItem *table, int tableCount); + void setKlaymanTable1(); + void setKlaymanTable2(); + void setKlaymanTable3(); + protected: Entity *_parentScene; Entity *_attachedSprite; @@ -129,11 +148,6 @@ protected: virtual void xUpdate(); virtual uint32 xHandleMessage(int messageNum, const MessageParam ¶m); - void setKlaymanTable(const KlaymanTableItem *table, int tableCount); - void setKlaymanTable1(); - void setKlaymanTable2(); - void setKlaymanTable3(); - void sub41FD40(); void sub41FD90(); uint32 handleMessage41EB10(int messageNum, const MessageParam ¶m, Entity *sender); @@ -210,6 +224,11 @@ protected: uint32 handleMessage41E490(int messageNum, const MessageParam ¶m, Entity *sender); uint32 handleMessage41E290(int messageNum, const MessageParam ¶m, Entity *sender); uint32 handleMessage41E2F0(int messageNum, const MessageParam ¶m, Entity *sender); + uint32 handleMessage41D640(int messageNum, const MessageParam ¶m, Entity *sender); + uint32 handleMessage41EAB0(int messageNum, const MessageParam ¶m, Entity *sender); + uint32 handleMessage41D970(int messageNum, const MessageParam ¶m, Entity *sender); + + void update41D1C0(); }; @@ -287,6 +306,33 @@ protected: void sub40E040(); }; +class KmScene1401 : public Klayman { +public: + KmScene1401(NeverhoodEngine *vm, Entity *parentScene, int16 x, int16 y); +protected: + uint32 xHandleMessage(int messageNum, const MessageParam ¶m); +}; + +class KmScene1402 : public Klayman { +public: + KmScene1402(NeverhoodEngine *vm, Entity *parentScene, int16 x, int16 y); +protected: + uint32 xHandleMessage(int messageNum, const MessageParam ¶m); +}; + +class KmScene1705 : public Klayman { +public: + KmScene1705(NeverhoodEngine *vm, Entity *parentScene, int16 x, int16 y); +protected: + bool _flag; + uint32 xHandleMessage(int messageNum, const MessageParam ¶m); + uint32 handleMessage4689A0(int messageNum, const MessageParam ¶m, Entity *sender); + void spriteUpdate468A30(); + void sub468A80(); + void sub468AD0(); + void sub468B10(); +}; + } // End of namespace Neverhood #endif /* NEVERHOOD_KLAYMAN_H */ diff --git a/engines/neverhood/module.mk b/engines/neverhood/module.mk index 17424765e0..0b3b10c2f8 100644 --- a/engines/neverhood/module.mk +++ b/engines/neverhood/module.mk @@ -5,6 +5,7 @@ MODULE_OBJS = \ blbarchive.o \ collisionman.o \ detection.o \ + diskplayerscene.o \ gamemodule.o \ gamevars.o \ graphics.o \ @@ -12,7 +13,10 @@ MODULE_OBJS = \ module.o \ module1000.o \ module1200.o \ + module1400.o \ module1500.o \ + module1700.o \ + module1800.o \ module2300.o \ mouse.o \ navigationscene.o \ diff --git a/engines/neverhood/module1200.cpp b/engines/neverhood/module1200.cpp index eef543385c..7a09b5f060 100644 --- a/engines/neverhood/module1200.cpp +++ b/engines/neverhood/module1200.cpp @@ -76,8 +76,8 @@ void Module1200::createScene1201(int which) { void Module1200::createScene1202(int which) { _vm->gameState().sceneNum = 1; - //_childObject = new Scene1202(_vm, this, which); - //SetUpdateHandler(&Module1200::updateScene1202); + _childObject = new Scene1202(_vm, this, which); + SetUpdateHandler(&Module1200::updateScene1202); } void Module1200::createScene1203(int which) { @@ -161,7 +161,7 @@ static const NPoint kScene1201PointArray[] = { {493, 174} }; -static const uint32 kScene1201SsScene1201TntFileHashList1[] = { +static const uint32 kScene1201TntFileHashList1[] = { 0x2098212D, 0x1600437E, 0x1600437E, @@ -182,7 +182,7 @@ static const uint32 kScene1201SsScene1201TntFileHashList1[] = { 0xDA460476 }; -static const uint32 kScene1201SsScene1201TntFileHashList2[] = { +static const uint32 kScene1201TntFileHashList2[] = { 0x3040C676, 0x10914448, 0x10914448, @@ -209,7 +209,7 @@ SsScene1201Tnt::SsScene1201Tnt(NeverhoodEngine *vm, uint32 elemIndex, uint32 poi int16 x = kScene1201PointArray[pointIndex].x; int16 y = kScene1201PointArray[pointIndex].y; if (x < 300) { - _spriteResource.load2(kScene1201SsScene1201TntFileHashList1[elemIndex]); + _spriteResource.load2(kScene1201TntFileHashList1[elemIndex]); _x = _spriteResource.getPosition().x; _y = _spriteResource.getPosition().y; _drawRect.x = 0; @@ -217,7 +217,7 @@ SsScene1201Tnt::SsScene1201Tnt(NeverhoodEngine *vm, uint32 elemIndex, uint32 poi _drawRect.width = _spriteResource.getDimensions().width; _drawRect.height = _spriteResource.getDimensions().height; } else { - _spriteResource.load2(kScene1201SsScene1201TntFileHashList2[elemIndex]); + _spriteResource.load2(kScene1201TntFileHashList2[elemIndex]); _x = x; _y = y; _drawRect.x = -(_spriteResource.getDimensions().width / 2); @@ -307,14 +307,14 @@ void Class466::sub40D380() { _newHashListIndex = -2; } -Class468::Class468(NeverhoodEngine *vm, Sprite *klayman, bool flag) +AsScene1201RightDoor::AsScene1201RightDoor(NeverhoodEngine *vm, Sprite *klayman, bool flag) : AnimatedSprite(vm, 1100), _soundResource(vm), _klayman(klayman), _countdown(0) { - createSurface1(100, 0xD088AC30); + createSurface1(0xD088AC30, 100); _x = 320; _y = 240; - SetUpdateHandler(&Class468::update); - SetMessageHandler(&Class468::handleMessage); + SetUpdateHandler(&AsScene1201RightDoor::update); + SetMessageHandler(&AsScene1201RightDoor::handleMessage); _newHashListIndex = -2; if (flag) { setFileHash(0xD088AC30, -1, -1); @@ -326,14 +326,14 @@ Class468::Class468(NeverhoodEngine *vm, Sprite *klayman, bool flag) } } -void Class468::update() { +void AsScene1201RightDoor::update() { if (_countdown != 0 && (--_countdown == 0)) { sub40D830(); } AnimatedSprite::update(); } -uint32 Class468::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { +uint32 AsScene1201RightDoor::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); switch (messageNum) { case 0x3002: @@ -346,22 +346,22 @@ uint32 Class468::handleMessage(int messageNum, const MessageParam ¶m, Entity return messageResult; } -void Class468::sub40D7E0() { +void AsScene1201RightDoor::sub40D7E0() { setFileHash(0xD088AC30, 0, -1); _newHashListIndex = -2; _surface->setVisible(true); _soundResource.play(calcHash("fxDoorOpen20")); } -void Class468::sub40D830() { +void AsScene1201RightDoor::sub40D830() { setFileHash(0xD088AC30, -1, -1); _playBackwards = true; _surface->setVisible(true); _soundResource.play(calcHash("fxDoorClose20")); - SetAnimationCallback3(&Class468::sub40D880); + SetAnimationCallback3(&AsScene1201RightDoor::sub40D880); } -void Class468::sub40D880() { +void AsScene1201RightDoor::sub40D880() { setFileHash1(); _surface->setVisible(false); } @@ -394,14 +394,14 @@ uint32 Class464::handleMessage(int messageNum, const MessageParam ¶m, Entity return messageResult; } -Class463::Class463(NeverhoodEngine *vm, Scene *parentScene, Sprite *class466, bool flag) +AsScene1201TntMan::AsScene1201TntMan(NeverhoodEngine *vm, Scene *parentScene, Sprite *class466, bool flag) : AnimatedSprite(vm, 1100), _soundResource(vm), _parentScene(parentScene), _class466(class466), _flag(false) { - - //TODO_field_F0 = -1; + + flag = false; SetUpdateHandler(&AnimatedSprite::update); - SetMessageHandler(&Class463::handleMessage); + SetMessageHandler(&AsScene1201TntMan::handleMessage); createSurface(990, 106, 181); _x = 201; if (flag) { @@ -413,11 +413,11 @@ Class463::Class463(NeverhoodEngine *vm, Scene *parentScene, Sprite *class466, bo } } -Class463::~Class463() { +AsScene1201TntMan::~AsScene1201TntMan() { // TODO Sound1ChList_sub_407AF0(0x01D00560); } -uint32 Class463::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { +uint32 AsScene1201TntMan::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); switch (messageNum) { case 0x100D: @@ -441,8 +441,8 @@ uint32 Class463::handleMessage(int messageNum, const MessageParam ¶m, Entity } -uint32 Class463::handleMessage40CCD0(int messageNum, const MessageParam ¶m, Entity *sender) { - uint32 messageResult = Class463::handleMessage(messageNum, param, sender); +uint32 AsScene1201TntMan::handleMessage40CCD0(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = AsScene1201TntMan::handleMessage(messageNum, param, sender); switch (messageNum) { case 0x3002: removeCallbacks(); @@ -451,37 +451,37 @@ uint32 Class463::handleMessage40CCD0(int messageNum, const MessageParam ¶m, return messageResult; } -void Class463::spriteUpdate40CD10() { +void AsScene1201TntMan::spriteUpdate40CD10() { _x = _sprite->getX() + 100; } -void Class463::sub40CD30() { +void AsScene1201TntMan::sub40CD30() { setFileHash(0x654913D0, 0, -1); - SetMessageHandler(&Class463::handleMessage); + SetMessageHandler(&AsScene1201TntMan::handleMessage); SetSpriteCallback(NULL); } -void Class463::sub40CD60() { +void AsScene1201TntMan::sub40CD60() { setFileHash(0x356803D0, 0, -1); - SetMessageHandler(&Class463::handleMessage40CCD0); + SetMessageHandler(&AsScene1201TntMan::handleMessage40CCD0); SetSpriteCallback(&AnimatedSprite::updateDeltaXY); - SetAnimationCallback3(&Class463::sub40CD30); + SetAnimationCallback3(&AsScene1201TntMan::sub40CD30); } -void Class463::sub40CD90() { +void AsScene1201TntMan::sub40CD90() { // TODO Sound1ChList_addSoundResource(0x01D00560, 0x4B044624, true); // TODO Sound1ChList_playLooping(0x4B044624); _flag = true; setFileHash(0x85084190, 0, -1); - SetMessageHandler(&Class463::handleMessage); - SetSpriteCallback(&Class463::spriteUpdate40CD10); + SetMessageHandler(&AsScene1201TntMan::handleMessage); + SetSpriteCallback(&AsScene1201TntMan::spriteUpdate40CD10); _newHashListIndex = -2; } -Class465::Class465(NeverhoodEngine *vm, Sprite *class463) - : AnimatedSprite(vm, 1200), _class463(class463) { +Class465::Class465(NeverhoodEngine *vm, Sprite *asTntMan) + : AnimatedSprite(vm, 1200), _asTntMan(asTntMan) { - createSurface1(995, 0x828C0411); + createSurface1(0x828C0411, 995); SetUpdateHandler(&Class465::update); SetMessageHandler(&Sprite::handleMessage); SetSpriteCallback(&Class465::spriteUpdate40D150); @@ -504,8 +504,251 @@ void Class465::update() { } void Class465::spriteUpdate40D150() { - _x = _class463->getX() - 18; - _y = _class463->getY() - 158; + _x = _asTntMan->getX() - 18; + _y = _asTntMan->getY() - 158; +} + +AsScene1201Match::AsScene1201Match(NeverhoodEngine *vm, Scene *parentScene) + : AnimatedSprite(vm, 1100), _soundResource(vm), _parentScene(parentScene) { + + createSurface(1100, 57, 60); + SetUpdateHandler(&AsScene1201Match::update); + SetMessageHandler(&AsScene1201Match::handleMessage40C2D0); + SetSpriteCallback(&AnimatedSprite::updateDeltaXY); + + switch (getGlobalVar(0x0112090A)) { + case 0: + _x = 521; + _y = 112; + _status = 0; + sub40C4C0(); + break; + case 1: + _x = 521; + _y = 112; + _status = 2; + sub40C470(); + _soundResource.load(0xD00230CD); + break; + case 2: + setDoDeltaX(1); + _x = 403; + _y = 337; + _status = 0; + sub40C4F0(); + break; + } +} + +void AsScene1201Match::update() { + if (_countdown != 0 && (--_countdown == 0)) { + removeCallbacks(); + } + updateAnim(); + handleSpriteUpdate(); + updatePosition(); +} + +uint32 AsScene1201Match::handleMessage40C2D0(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x86668011) { + _soundResource.play(); + } + break; + } + return messageResult; +} + +uint32 AsScene1201Match::handleMessage40C320(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = handleMessage40C2D0(messageNum, param, sender); + switch (messageNum) { + case 0x3002: + removeCallbacks(); + break; + } + return messageResult; +} + +uint32 AsScene1201Match::handleMessage40C360(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = handleMessage40C2D0(messageNum, param, sender); + switch (messageNum) { + case 0x1011: + _parentScene->sendMessage(0x2001, 0, this); + messageResult = 1; + break; + case 0x4806: + _surface->setVisible(false); + setGlobalVar(0x0112090A, 3); + break; + } + return messageResult; +} + +void AsScene1201Match::sub40C3E0() { + setFileHash(0x00842374, 0, -1); + SetMessageHandler(&AsScene1201Match::handleMessage40C320); + if (_status == 0) { + SetAnimationCallback3(&AsScene1201Match::sub40C420); + } else { + SetAnimationCallback3(&AsScene1201Match::sub40C470); + } +} + +void AsScene1201Match::sub40C420() { + setGlobalVar(0x0112090A, 2); + _x -= 199; + _y += 119; + setFileHash(0x018D0240, 0, -1); + SetMessageHandler(&AsScene1201Match::handleMessage40C320); + SetAnimationCallback3(&AsScene1201Match::sub40C4F0); +} + +void AsScene1201Match::sub40C470() { + setFileHash(0x00842374, 0, -1); + SetMessageHandler(&AsScene1201Match::handleMessage40C2D0); + _newHashListIndex = 0; + if (_status != 0) { + _countdown = 36; + _status--; + SetAnimationCallback3(&AsScene1201Match::sub40C3E0); + } +} + +void AsScene1201Match::sub40C4C0() { + setFileHash(0x00842374, 0, -1); + SetMessageHandler(&AsScene1201Match::handleMessage40C360); + _newHashListIndex = 0; +} + +void AsScene1201Match::sub40C4F0() { + setDoDeltaX(1); + _x = 403; + _y = 337; + setFileHash(0x00842374, 0, -1); + SetMessageHandler(&AsScene1201Match::handleMessage40C360); + _newHashListIndex = 0; +} + +AsScene1201Creature::AsScene1201Creature(NeverhoodEngine *vm, Scene *parentScene, Sprite *klayman) + : AnimatedSprite(vm, 900), _soundResource(vm), _parentScene(parentScene), _klayman(klayman), + _flag(false) { + + createSurface(1100, 203, 199); + SetUpdateHandler(&AsScene1201Creature::update); + SetMessageHandler(&AsScene1201Creature::handleMessage40C710); + _x = 540; + _y = 320; + sub40C8E0(); + _countdown3 = 2; +} + +void AsScene1201Creature::update() { + bool oldFlag = _flag; + _flag = _x >= 385; + if (_flag != oldFlag) + sub40C8E0(); + if (_countdown1 != 0 && (--_countdown1 == 0)) { + removeCallbacks(); + } + updateAnim(); + handleSpriteUpdate(); + updatePosition(); +} + +uint32 AsScene1201Creature::handleMessage40C710(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x02060018) { + _soundResource.play(0xCD298116); + } + break; + case 0x2004: + setCallback2(AnimationCallback(&AsScene1201Creature::sub40C960)); + break; + case 0x2006: + setCallback2(AnimationCallback(&AsScene1201Creature::sub40C9B0)); + break; + } + return messageResult; +} + +uint32 AsScene1201Creature::handleMessage40C7B0(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = handleMessage40C710(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x02421405) { + if (_countdown2 != 0 && (--_countdown2 == 0)) { + sub40C990(); + } + } + break; + case 0x3002: + removeCallbacks(); + break; + } + return messageResult; +} + +uint32 AsScene1201Creature::handleMessage40C830(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x02060018) { + _soundResource.play(0xCD298116); + _parentScene->sendMessage(0x4814, 0, this); + _klayman->sendMessage(0x4814, 0, this); + } + break; + case 0x3002: + removeCallbacks(); + break; + } + return messageResult; +} + +void AsScene1201Creature::sub40C8E0() { + _countdown3--; + if (_countdown3 == 0) + _countdown3 = 3; + setFileHash(0x08081513, 0, -1); + SetMessageHandler(&AsScene1201Creature::handleMessage40C710); + SetAnimationCallback3(&AsScene1201Creature::sub40C930); + _countdown1 = 36; +} + +void AsScene1201Creature::sub40C930() { + if (!_flag) { + setFileHash(0xCA287133, 0, -1); + SetMessageHandler(&AsScene1201Creature::handleMessage40C7B0); + SetAnimationCallback3(&AsScene1201Creature::sub40C8E0); + } +} + +void AsScene1201Creature::sub40C960() { + setFileHash(0x08081513, 0, -1); + SetMessageHandler(&AsScene1201Creature::handleMessage40C710); + SetAnimationCallback3(&AsScene1201Creature::sub40C9E0); + _countdown1 = 48; +} + +void AsScene1201Creature::sub40C990() { + setFileHash2(0x0B6E13FB, 0x01084280, 0); +} + +void AsScene1201Creature::sub40C9B0() { + setFileHash(0xCA287133, 0, -1); + SetMessageHandler(&AsScene1201Creature::handleMessage40C830); + SetAnimationCallback3(&AsScene1201Creature::sub40C8E0); + _countdown1 = 0; +} + +void AsScene1201Creature::sub40C9E0() { + setFileHash(0x5A201453, 0, -1); + SetMessageHandler(&AsScene1201Creature::handleMessage40C710); + _countdown1 = 0; } AsScene1201LeftDoor::AsScene1201LeftDoor(NeverhoodEngine *vm, Sprite *klayman) @@ -543,7 +786,8 @@ void AsScene1201LeftDoor::sub40D590() { } Scene1201::Scene1201(NeverhoodEngine *vm, Module *parentModule, int which) - : Scene(vm, parentModule, true), _flag(false) { + : Scene(vm, parentModule, true), _flag(false), _asMatch(NULL), _asTntMan(NULL), + _asCreature(NULL), _class466(NULL), _asLeftDoor(NULL), _asRightDoor(NULL), _asTape(NULL) { int16 topY1, topY2, topY3, topY4; int16 x1, x2; @@ -589,12 +833,12 @@ Scene1201::Scene1201(NeverhoodEngine *vm, Module *parentModule, int which) tempSprite = addSprite(new StaticSprite(_vm, 0x04063110, 500)); topY4 = tempSprite->getY() + 1; - _class466 = addSprite(new Class466(_vm, getGlobalVar(0x000CF819) && which != 1 ? 1 : 0)); + _class466 = addSprite(new Class466(_vm, getGlobalVar(0x000CF819) && which != 1)); _class466->getSurface()->getClipRect().x1 = 0; _class466->getSurface()->getClipRect().y1 = topY4; _class466->getSurface()->getClipRect().x2 = 640; _class466->getSurface()->getClipRect().y2 = 480; - + addSprite(new StaticSprite(_vm, 0x400B04B0, 1200)); tempSprite = addSprite(new StaticSprite(_vm, 0x40295462, 1200)); @@ -644,31 +888,31 @@ Scene1201::Scene1201(NeverhoodEngine *vm, Module *parentModule, int which) _background = addBackground(new DirtyBackground(_vm, 0x4019A2C4, 0, 0)); _palette = new Palette(_vm, 0x4019A2C4); _palette->usePalette(); - _class468 = NULL; + _asRightDoor = NULL; } else { _background = addBackground(new DirtyBackground(_vm, 0x40206EC5, 0, 0)); _palette = new Palette(_vm, 0x40206EC5); _palette->usePalette(); - _class468 = addSprite(new Class468(_vm, _klayman, which - 2 != 1)); // CHECKME??? + _asRightDoor = addSprite(new AsScene1201RightDoor(_vm, _klayman, which == 2)); } if (getGlobalVar(0x000CF819)) { addSprite(new StaticSprite(_vm, 0x10002ED8, 500)); if (!getGlobalVar(0x0A18CA33)) { - Class463 *class463; - class463 = new Class463(_vm, this, _class466, which - 1 != 1); - class463->getSurface()->getClipRect().x1 = x1; - class463->getSurface()->getClipRect().y1 = 0; - class463->getSurface()->getClipRect().x2 = x2; - class463->getSurface()->getClipRect().y2 = 480; - _vm->_collisionMan->addSprite(_class463); - _class463 = addSprite(class463); - tempSprite = addSprite(new Class465(_vm, _class463)); + AsScene1201TntMan *asTntMan; + asTntMan = new AsScene1201TntMan(_vm, this, _class466, which == 1); + asTntMan->getSurface()->getClipRect().x1 = x1; + asTntMan->getSurface()->getClipRect().y1 = 0; + asTntMan->getSurface()->getClipRect().x2 = x2; + asTntMan->getSurface()->getClipRect().y2 = 480; + _vm->_collisionMan->addSprite(asTntMan); + _asTntMan = addSprite(asTntMan); + tempSprite = addSprite(new Class465(_vm, _asTntMan)); tempSprite->getSurface()->getClipRect().x1 = x1; tempSprite->getSurface()->getClipRect().y1 = 0; tempSprite->getSurface()->getClipRect().x2 = x2; tempSprite->getSurface()->getClipRect().y2 = 480; - class463->setRepl(64, 0); + asTntMan->setRepl(64, 0); } uint32 tntIndex = 1; @@ -741,22 +985,20 @@ Scene1201::Scene1201(NeverhoodEngine *vm, Module *parentModule, int which) setGlobalVar(0x0112090A, 1); } - _class461 = NULL; + _asMatch = NULL; -#if 0 if (getGlobalVar(0x0112090A) < 3) { - _class461 = addSprite(new Class461(_vm, this)); - _vm->_collisionMan->addSprite(_class461); + _asMatch = addSprite(new AsScene1201Match(_vm, this)); + _vm->_collisionMan->addSprite(_asMatch); } if (getGlobalVar(0x0A310817) && !getGlobalVar(0x0A18CA33)) { - _class462 = addSprite(new Class462(_vm, this, _klayman)); - _class462->getSurface()->getClipRect().x1 = x1; - _class462->getSurface()->getClipRect().y1 = 0; - _class462->getSurface()->getClipRect().x2 = x2; - _class462->getSurface()->getClipRect().y2 = 480; + _asCreature = addSprite(new AsScene1201Creature(_vm, this, _klayman)); + _asCreature->getSurface()->getClipRect().x1 = x1; + _asCreature->getSurface()->getClipRect().y1 = 0; + _asCreature->getSurface()->getClipRect().x2 = x2; + _asCreature->getSurface()->getClipRect().y2 = 480; } -#endif } @@ -765,8 +1007,8 @@ Scene1201::~Scene1201() { void Scene1201::update() { Scene::update(); - if (_class461 && getGlobalVar(0x0112090A)) { - deleteSprite(&_class461); + if (_asMatch && getGlobalVar(0x0112090A)) { + deleteSprite(&_asMatch); } } @@ -777,12 +1019,12 @@ uint32 Scene1201::handleMessage(int messageNum, const MessageParam ¶m, Entit case 0x100D: if (param.asInteger() == 0x07053000) { _flag = true; - _class462->sendMessage(0x2004, 0, this); + _asCreature->sendMessage(0x2004, 0, this); } else if (param.asInteger() == 0x140E5744) { - _class462->sendMessage(0x2005, 0, this); + _asCreature->sendMessage(0x2005, 0, this); } else if (param.asInteger() == 0x40253C40) { _messageListFlag = false; - _class462->sendMessage(0x2006, 0, this); + _asCreature->sendMessage(0x2006, 0, this); } else if (param.asInteger() == 0x090EB048) { if (_klayman->getX() < 572) { setMessageList2(0x004AEC90); @@ -795,17 +1037,17 @@ uint32 Scene1201::handleMessage(int messageNum, const MessageParam ¶m, Entit if (!getGlobalVar(0x0112090A)) { setMessageList2(0x004AECB0); } else { - _klayman->sendEntityMessage(0x1014, _class461, this); + _klayman->sendEntityMessage(0x1014, _asMatch, this); setMessageList2(0x004AECC0); } break; case 0x2002: if (getGlobalVar(0x20A0C516)) { - _klayman->sendEntityMessage(0x1014, _class463, this); + _klayman->sendEntityMessage(0x1014, _asTntMan, this); setMessageList2(0x004AECF0); } else if (getGlobalVar(0x0112090A) == 3) { - _klayman->sendEntityMessage(0x1014, _class463, this); - if (_klayman->getX() > _class463->getX()) { + _klayman->sendEntityMessage(0x1014, _asTntMan, this); + if (_klayman->getX() > _asTntMan->getX()) { setMessageList(0x004AECD0); } else { setMessageList(0x004AECE0); @@ -822,10 +1064,253 @@ uint32 Scene1201::handleMessage(int messageNum, const MessageParam ¶m, Entit } break; case 0x4829: - _class468->sendMessage(0x4829, 0, this); + _asRightDoor->sendMessage(0x4829, 0, this); + break; + } + return messageResult; +} + +// Scene1202 + +static const uint32 kScene1202Table[] = { + 1, 2, 0, 4, 5, 3, 7, 8, 6, 10, 11, 9, 13, 14, 12, 16, 17, 15 +}; + +static const NPoint kScene1202Points[] = { + {203, 140}, + {316, 212}, + {277, 264}, + {176, 196}, + {275, 159}, + {366, 212}, + {230, 195}, + {412, 212}, + {368, 263}, + {204, 192}, + {365, 164}, + {316, 262}, + {191, 255}, + {280, 213}, + {406, 266}, + {214, 254}, + {316, 158}, + {402, 161} +}; + +static const uint32 kScene1202FileHashes[] = { + 0x1AC00B8, + 0x1AC14B8, + 0x1AC14B8, + 0x1AC30B8, + 0x1AC14B8, + 0x1AC14B8, + 0x1AC00B8, + 0x1AC14B8, + 0x1AC14B8, + 0x1AC90B8, + 0x1AC18B8, + 0x1AC18B8, + 0x1AC30B8, + 0x1AC14B8, + 0x1AC14B8, + 0x1AC50B8, + 0x1AC14B8, + 0x1AC14B8 +}; + +AsScene1202TntItem::AsScene1202TntItem(NeverhoodEngine *vm, Scene *parentScene, int index) + : AnimatedSprite(vm, 900), _parentScene(parentScene), _index(index) { + + int positionIndex; + + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&AsScene1202TntItem::handleMessage453FE0); + positionIndex = getSubVar(0x10055D14, _index); + createSurface(900, 37, 67); + _x = kScene1202Points[positionIndex].x; + _y = kScene1202Points[positionIndex].y; + sub4540A0(); +} + +uint32 AsScene1202TntItem::handleMessage453FE0(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x1011: + _parentScene->sendMessage(0x2000, _index, this); + messageResult = 1; + break; + case 0x2001: + _index2 = (int)param.asInteger(); + sub4540D0(); break; } return messageResult; } +uint32 AsScene1202TntItem::handleMessage454060(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x3002: + removeCallbacks(); + break; + } + return messageResult; +} + +void AsScene1202TntItem::sub4540A0() { + setFileHash(kScene1202FileHashes[_index], 0, -1); + SetMessageHandler(&AsScene1202TntItem::handleMessage453FE0); + _newHashListIndex = 0; +} + +void AsScene1202TntItem::sub4540D0() { + setFileHash(kScene1202FileHashes[_index], 0, -1); + SetMessageHandler(&AsScene1202TntItem::handleMessage454060); + SetAnimationCallback3(&AsScene1202TntItem::sub454100); +} + +void AsScene1202TntItem::sub454100() { + _x = kScene1202Points[_index2].x; + _y = kScene1202Points[_index2].y; + setFileHash(kScene1202FileHashes[_index], 6, -1); + SetMessageHandler(&AsScene1202TntItem::handleMessage454060); + SetAnimationCallback3(&AsScene1202TntItem::sub454160); + _playBackwards = true; +} + +void AsScene1202TntItem::sub454160() { + _parentScene->sendMessage(0x2002, _index, this); + sub4540A0(); +} + +Scene1202::Scene1202(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule, true), _paletteResource(vm), _soundResource1(vm), + _soundResource2(vm), _soundResource3(vm), _soundResource4(vm), + _flag(true), _soundFlag(false), _counter(0), _index(-1) { + + Palette2 *palette2; + + SetMessageHandler(&Scene1202::handleMessage453C10); + SetUpdateHandler(&Scene1202::update); + + _surfaceFlag = true; + + _background = addBackground(new DirtyBackground(_vm, 0x60210ED5, 0, 0)); + + palette2 = new Palette2(_vm, 0x60210ED5); + palette2->usePalette(); + _palette = palette2; + addEntity(_palette); + + _paletteResource.load(0x60250EB5); + _paletteResource.copyPalette(_paletteData); + + _mouseCursor = addSprite(new Mouse435(_vm, 0x10ED160A, 20, 620)); + + for (int i = 0; i < 18; i++) { + _asTntItems[i] = addSprite(new AsScene1202TntItem(_vm, this, i)); + _vm->_collisionMan->addSprite(_asTntItems[i]); + } + + addSprite(new StaticSprite(_vm, 0x8E8419C1, 1100)); + + if (getGlobalVar(0x000CF819)) { + SetMessageHandler(&Scene1202::handleMessage453D90); + } + + _soundResource1.play(0x40106542); + _soundResource2.load(0x40005446); + _soundResource2.load(0x40005446); + _soundResource2.load(0x68E25540); + +} + +Scene1202::~Scene1202() { + if (isSolved()) { + setGlobalVar(0x000CF819, 1); + } +} + +void Scene1202::update() { + Scene::update(); + if (_soundFlag) { + if (!_soundResource4.isPlaying()) { + _parentModule->sendMessage(0x1009, 0, this); + } + } else if (_counter == 0 && isSolved()) { + SetMessageHandler(&Scene1202::handleMessage453D90); + setGlobalVar(0x000CF819, 1); + doPaletteEffect(); + _soundResource4.play(); + _soundFlag = true; + } else if (_index >= 0 && _counter == 0) { + int index2 = kScene1202Table[_index]; + _asTntItems[_index]->sendMessage(0x2001, getSubVar(0x10055D14, index2), this); + _asTntItems[index2]->sendMessage(0x2001, getSubVar(0x10055D14, _index), this); + int temp = getSubVar(0x10055D14, index2); + setSubVar(0x10055D14, index2, getSubVar(0x10055D14, _index)); + setSubVar(0x10055D14, _index, temp); + _counter = 2; + _index = -1; + if (_flag) { + _soundResource2.play(); + } else { + _soundResource3.play(); + } + _flag = !_flag; + } +} + +uint32 Scene1202::handleMessage453C10(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = 0; + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x0001: + // TODO: Debug/Cheat stuff + if ((param.asPoint().x <= 20 || param.asPoint().x >= 620) && !_soundFlag) { + _parentModule->sendMessage(0x1009, 0, this); + } + break; + case 0x000D: + if (param.asInteger() == 0x14210006) { + // TODO: Debug/Cheat stuff + messageResult = 1; + } + break; + case 0x2000: + _index = (int)param.asInteger(); + break; + case 0x2002: + _counter--; + break; + } + return messageResult; +} + +uint32 Scene1202::handleMessage453D90(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; +} + +bool Scene1202::isSolved() { + return + getSubVar(0x10055D14, 0) == 0 && getSubVar(0x10055D14, 3) == 3 && + getSubVar(0x10055D14, 6) == 6 && getSubVar(0x10055D14, 9) == 9 && + getSubVar(0x10055D14, 12) == 12 && getSubVar(0x10055D14, 15) == 15; +} + +void Scene1202::doPaletteEffect() { +#if 0 // TODO + Palette2 *palette2 = (Palette2*)_palette; + palette2->startFadeToPalette(24); +#endif +} + } // End of namespace Neverhood diff --git a/engines/neverhood/module1200.h b/engines/neverhood/module1200.h index 2a8a933b59..3ffed442d9 100644 --- a/engines/neverhood/module1200.h +++ b/engines/neverhood/module1200.h @@ -70,9 +70,9 @@ protected: void sub40D380(); }; -class Class468 : public AnimatedSprite { +class AsScene1201RightDoor : public AnimatedSprite { public: - Class468(NeverhoodEngine *vm, Sprite *klayman, bool flag); + AsScene1201RightDoor(NeverhoodEngine *vm, Sprite *klayman, bool flag); protected: SoundResource _soundResource; Sprite *_klayman; @@ -91,10 +91,10 @@ protected: uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); }; -class Class463 : public AnimatedSprite { +class AsScene1201TntMan : public AnimatedSprite { public: - Class463(NeverhoodEngine *vm, Scene *parentScene, Sprite *class466, bool flag); - virtual ~Class463(); + AsScene1201TntMan(NeverhoodEngine *vm, Scene *parentScene, Sprite *class466, bool flag); + virtual ~AsScene1201TntMan(); protected: Scene *_parentScene; Sprite *_class466; @@ -111,14 +111,56 @@ protected: class Class465 : public AnimatedSprite { public: - Class465(NeverhoodEngine *vm, Sprite *class463); + Class465(NeverhoodEngine *vm, Sprite *asTntMan); ~Class465(); protected: - Sprite *_class463; + Sprite *_asTntMan; void update(); void spriteUpdate40D150(); }; +class AsScene1201Match : public AnimatedSprite { +public: + AsScene1201Match(NeverhoodEngine *vm, Scene *parentScene); +protected: + Scene *_parentScene; + SoundResource _soundResource; + int _countdown; + int _status; + void update(); + uint32 handleMessage40C2D0(int messageNum, const MessageParam ¶m, Entity *sender); + uint32 handleMessage40C320(int messageNum, const MessageParam ¶m, Entity *sender); + uint32 handleMessage40C360(int messageNum, const MessageParam ¶m, Entity *sender); + void sub40C3E0(); + void sub40C420(); + void sub40C470(); + void sub40C4C0(); + void sub40C4F0(); +}; + +class AsScene1201Creature : public AnimatedSprite { +public: + AsScene1201Creature(NeverhoodEngine *vm, Scene *parentScene, Sprite *klayman); +protected: + Scene *_parentScene; + Sprite *_klayman; + SoundResource _soundResource; + int _countdown1; + int _countdown2; + int _countdown3; + bool _flag; + void update(); + uint32 handleMessage40C710(int messageNum, const MessageParam ¶m, Entity *sender); + uint32 handleMessage40C7B0(int messageNum, const MessageParam ¶m, Entity *sender); + uint32 handleMessage40C830(int messageNum, const MessageParam ¶m, Entity *sender); + void sub40C8E0(); + void sub40C930(); + void sub40C960(); + void sub40C990(); + void sub40C9B0(); + void sub40C9E0(); +}; + class AsScene1201LeftDoor : public AnimatedSprite { public: AsScene1201LeftDoor(NeverhoodEngine *vm, Sprite *klayman); @@ -144,18 +186,57 @@ public: protected: // TODO ResourceTable _resourceTable1; // TODO ResourceTable _resourceTable2; - Sprite *_class461; - Sprite *_class463; - Sprite *_class462; + Sprite *_asMatch; + Sprite *_asTntMan; + Sprite *_asCreature; Sprite *_class466; Sprite *_asLeftDoor; - Sprite *_class468; + Sprite *_asRightDoor; Sprite *_asTape; bool _flag; void update(); uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); }; +// Scene1202 + +class AsScene1202TntItem : public AnimatedSprite { +public: + AsScene1202TntItem(NeverhoodEngine *vm, Scene *parentScene, int index); +protected: + Scene *_parentScene; + int _index, _index2; + uint32 handleMessage453FE0(int messageNum, const MessageParam ¶m, Entity *sender); + uint32 handleMessage454060(int messageNum, const MessageParam ¶m, Entity *sender); + void sub4540A0(); + void sub4540D0(); + void sub454100(); + void sub454160(); +}; + +class Scene1202 : public Scene { +public: + Scene1202(NeverhoodEngine *vm, Module *parentModule, int which); + virtual ~Scene1202(); +protected: + SoundResource _soundResource1; + SoundResource _soundResource2; + SoundResource _soundResource3; + SoundResource _soundResource4; + PaletteResource _paletteResource; + Sprite *_asTntItems[18]; + int _counter; + int _index; + byte _paletteData[1024]; + bool _soundFlag; + bool _flag; + void update(); + uint32 handleMessage453C10(int messageNum, const MessageParam ¶m, Entity *sender); + uint32 handleMessage453D90(int messageNum, const MessageParam ¶m, Entity *sender); + bool isSolved(); + void doPaletteEffect(); +}; + } // End of namespace Neverhood #endif /* NEVERHOOD_MODULE1200_H */ diff --git a/engines/neverhood/module1400.cpp b/engines/neverhood/module1400.cpp new file mode 100644 index 0000000000..7d618f5319 --- /dev/null +++ b/engines/neverhood/module1400.cpp @@ -0,0 +1,1439 @@ +/* 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/module1400.h" +#include "neverhood/module1000.h" +#include "neverhood/diskplayerscene.h" +#include "neverhood/navigationscene.h" + +namespace Neverhood { + +Module1400::Module1400(NeverhoodEngine *vm, Module *parentModule, int which) + : Module(vm, parentModule) { + + debug("Create Module1400(%d)", which); + + // TODO Music18hList_add(0x00AD0012, 0x06333232); + // TODO Music18hList_add(0x00AD0012, 0x624A220E); + + if (which < 0) { + switch (_vm->gameState().sceneNum) { + case 1: + createScene1402(-1); + break; + case 2: + createScene1403(-1); + break; + case 3: + createScene1404(-1); + break; + case 4: + createScene1405(-1); + break; + case 5: + createScene1406(-1); + break; + case 6: + createScene1407(-1); + break; + default: + createScene1401(-1); + } + } else { + createScene1401(0); + } + +} + +Module1400::~Module1400() { + // TODO Music18hList_deleteGroup(0x00AD0012); +} + +void Module1400::createScene1401(int which) { + _vm->gameState().sceneNum = 0; + // TODO Music18hList_play(0x06333232, 0, 2, 1); + _childObject = new Scene1401(_vm, this, which); + SetUpdateHandler(&Module1400::updateScene1401); +} + +void Module1400::createScene1402(int which) { + _vm->gameState().sceneNum = 1; + // TODO Music18hList_stop(0x06333232, 0, 2); + // TODO Music18hList_stop(0x624A220E, 0, 2); + _childObject = new Scene1402(_vm, this, which); + SetUpdateHandler(&Module1400::updateScene1402); +} + +void Module1400::createScene1403(int which) { + _vm->gameState().sceneNum = 2; + // TODO Music18hList_stop(0x06333232, 0, 2); + // TODO Music18hList_play(0x624A220E, 0, 2, 1); + // TODO _childObject = new Scene1403(_vm, this, which); + SetUpdateHandler(&Module1400::updateScene1403); +} + +void Module1400::createScene1404(int which) { + _vm->gameState().sceneNum = 3; + // TODO Music18hList_play(0x06333232, 0, 2, 1); + // TODO _childObject = new Scene1404(_vm, this, which); + SetUpdateHandler(&Module1400::updateScene1404); +} + +void Module1400::createScene1405(int which) { + _vm->gameState().sceneNum = 4; + // TODO Music18hList_play(0x06333232, 0, 2, 1); + // TODO _childObject = new Scene1405(_vm, this, which); + SetUpdateHandler(&Module1400::updateScene1405); +} + +void Module1400::createScene1406(int which) { + _vm->gameState().sceneNum = 5; + // TODO Music18hList_stop(0x06333232, 0, 2); + _childObject = new DiskplayerScene(_vm, this, 2); + SetUpdateHandler(&Module1400::updateScene1405); +} + +void Module1400::createScene1407(int which) { + _vm->gameState().sceneNum = 6; + // TODO Music18hList_stop(0x06333232, 0, 2); + _childObject = new Scene1407(_vm, this, which); + SetUpdateHandler(&Module1400::updateScene1407); +} + +void Module1400::updateScene1401() { + _childObject->handleUpdate(); + if (_done) { + _done = false; + delete _childObject; + _childObject = NULL; + if (_field20 == 1) { + createScene1402(0); + _childObject->handleUpdate(); + } else if (_field20 == 2) { + createScene1404(0); + _childObject->handleUpdate(); + } else { + _parentModule->sendMessage(0x1009, 0, this); + } + } +} + +void Module1400::updateScene1402() { + _childObject->handleUpdate(); + if (_done) { + _done = false; + delete _childObject; + _childObject = NULL; + + debug("Scene1402: _field20 = %d", _field20); + + if (_field20 == 1) { + createScene1403(0); + _childObject->handleUpdate(); + } else if (_field20 == 2) { + createScene1407(-1); + _childObject->handleUpdate(); + } else { + createScene1401(1); + _childObject->handleUpdate(); + } + } +} + +void Module1400::updateScene1403() { + _childObject->handleUpdate(); + if (_done) { + _done = false; + delete _childObject; + _childObject = NULL; + createScene1402(1); + _childObject->handleUpdate(); + } +} + +void Module1400::updateScene1404() { + _childObject->handleUpdate(); + if (_done) { + _done = false; + delete _childObject; + _childObject = NULL; + if (_field20 == 1) { + createScene1405(0); + _childObject->handleUpdate(); + } else if (_field20 == 2) { + createScene1406(-1); + _childObject->handleUpdate(); + } else { + createScene1401(2); + _childObject->handleUpdate(); + } + } +} + +void Module1400::updateScene1405() { + _childObject->handleUpdate(); + if (_done) { + _done = false; + delete _childObject; + _childObject = NULL; + createScene1404(1); + _childObject->handleUpdate(); + } +} + +void Module1400::updateScene1406() { + _childObject->handleUpdate(); + if (_done) { + _done = false; + delete _childObject; + _childObject = NULL; + createScene1404(2); + _childObject->handleUpdate(); + } +} + +void Module1400::updateScene1407() { + _childObject->handleUpdate(); + if (_done) { + _done = false; + delete _childObject; + _childObject = NULL; + createScene1402(2); + _childObject->handleUpdate(); + } +} + +// Scene1401 + +Class525::Class525(NeverhoodEngine *vm) + : AnimatedSprite(vm, 1100), _soundResource1(vm), _soundResource2(vm), + _countdown1(0), _countdown2(0) { + + // TODO createSurface3(900, dword_4B6768); + createSurface(900, 640, 480); //TODO: Remeove once the line above is done + _x = 454; + _y = 217; + SetUpdateHandler(&Class525::update4662A0); + SetMessageHandler(&Class525::handleMessage466320); + setFileHash(0x4C210500, 0, -1); +} + +Class525::~Class525() { + // TODO Sound1ChList_sub_407AF0(0x01104C08); +} + +void Class525::update4662A0() { + AnimatedSprite::update(); + if (_countdown1 != 0 && (--_countdown1 == 0)) { + sub466460(); + } + if (_countdown2 != 0 && (--_countdown2 == 0)) { + // TODO Sound1ChList_addSoundResource(0x01104C08, 0x4A116437, true); + // TODO Sound1ChList_playLooping(0x4A116437); + } +} + +void Class525::update466300() { + AnimatedSprite::update(); + if (_countdown1 != 0) { + _countdown1--; + } +} + +uint32 Class525::handleMessage466320(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x0A8A1490) { + _soundResource2.play(0x6AB6666F); + } + break; + case 0x2000: + _countdown1 = 70; + _countdown2 = 8; + sub466420(); + break; + case 0x483A: + sub4664B0(); + break; + } + return messageResult; +} + +uint32 Class525::handleMessage4663C0(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x3002: + if (_countdown1 != 0) { + sub466420(); + } else { + sub466460(); + } + SetMessageHandler(&Class525::handleMessage466320); + SetUpdateHandler(&Class525::update4662A0); + break; + } + return messageResult; +} + +void Class525::sub466420() { + setFileHash(0x4C240100, 0, -1); + _soundResource1.play(0x4A30063F); +} + +void Class525::sub466460() { + // TODO Sound1ChList_deleteSoundByHash(0x4A116437); + _soundResource1.play(0x4A120435); + setFileHash(0x4C210500, 0, -1); +} + +void Class525::sub4664B0() { + setFileHash(0x6C210810, 0, -1); + SetMessageHandler(&Class525::handleMessage4663C0); + SetUpdateHandler(&Class525::update466300); +} + +Class526::Class526(NeverhoodEngine *vm, Sprite *class525) + : AnimatedSprite(vm, 1100), _soundResource(vm), _class525(class525) { + + // TODO createSurface3(100, dword_4B6778); + createSurface(100, 640, 480); //TODO: Remeove once the line above is done + _x = 478; + _y = 433; + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&Class526::handleMessage); + setFileHash(0xA282C472, 0, -1); +} + +uint32 Class526::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x66382026) { + _soundResource.play(0x0CD84468); + } else if (param.asInteger() == 0x6E28061C) { + _soundResource.play(0x78C8402C); + } else if (param.asInteger() == 0x462F0410) { + _soundResource.play(0x60984E28); + } + break; + case 0x4839: + sub466770(); + break; + } + return messageResult; +} + +void Class526::spriteUpdate466720() { + AnimatedSprite::updateDeltaXY(); + if (_rect.y1 <= 150) { + _soundResource.play(0x0E32247F); + setFileHash1(); + SetSpriteCallback(NULL); + SetMessageHandler(NULL); + _surface->setVisible(false); + } +} + +void Class526::sub466770() { + setFileHash(0x34880040, 0, -1); + SetSpriteCallback(&Class526::spriteUpdate466720); +} + +Class527::Class527(NeverhoodEngine *vm, Sprite *class526) + : AnimatedSprite(vm, 1100), _soundResource(vm), _class526(class526) { + + // TODO createSurface3(200, dword_4B6768); + createSurface(200, 640, 480); //TODO: Remeove once the line above is done + _x = 427; + _y = 433; + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&Class527::handleMessage); + setFileHash(0x461A1490, 0, -1); +} + +uint32 Class527::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x4839: + sub466970(); + break; + } + return messageResult; +} + +void Class527::spriteUpdate466920() { + AnimatedSprite::updateDeltaXY(); + if (_rect.y1 <= 150) { + _soundResource.play(0x18020439); + setFileHash1(); + SetSpriteCallback(NULL); + SetMessageHandler(NULL); + _surface->setVisible(false); + } +} + +void Class527::sub466970() { + setFileHash(0x103B8020, 0, -1); + SetSpriteCallback(&Class527::spriteUpdate466920); +} + +Class528::Class528(NeverhoodEngine *vm, Sprite *klayman, bool flag) + : AnimatedSprite(vm, 1100), _soundResource(vm), _klayman(klayman), _countdown(0) { + + _x = 320; + _y = 240; + createSurface1(100, 0x04551900); + SetUpdateHandler(&Class528::update); + SetMessageHandler(&Class528::handleMessage); + _newHashListIndex = -2; + if (flag) { + _flag = true; + setFileHash(0x04551900, -1,- 1); + _countdown = 48; + } else { + _flag = false; + setFileHash1(); + _surface->setVisible(false); + } +} + +void Class528::update() { + if (_countdown != 0 && (--_countdown == 0)) { + sub466C50(); + } + AnimatedSprite::update(); +} + + +uint32 Class528::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x2001: + if (_flag) + _countdown = 168; + messageResult = _flag ? 1 : 0; + break; + case 0x3002: + removeCallbacks(); + break; + case 0x4808: + _countdown = 168; + if (_flag) + sub466BF0(); + break; + } + return messageResult; +} + +void Class528::sub466BF0() { + _flag = true; + _surface->setVisible(true); + setFileHash(0x04551900, 0, -1); + _newHashListIndex = -2; + _soundResource.play(calcHash("fxDoorOpen24")); +} + +void Class528::sub466C50() { + _flag = false; + _surface->setVisible(true); + setFileHash(0x04551900, -1, -1); + _soundResource.play(calcHash("fxDoorClose24")); + _playBackwards = true; + SetAnimationCallback3(&Class528::sub466CB0); +} + +void Class528::sub466CB0() { + setFileHash1(); + _surface->setVisible(false); +} + +static const Class489Item kClass489Items[] = { + {{154, 453}, 4, 2, 0, -1, 0, 1}, + {{104, 391}, 4, -1, -1, -1, 1, 1}, + {{ 22, 447}, 6, -1, -1, -1, 1, 1}, + {{112, 406}, 2, -1, -1, -1, 1, 0}, + {{262, 433}, 1, 1, 0, -1, 0, 0} +}; + +Class489::Class489(NeverhoodEngine *vm, Scene *parentScene, Sprite *klayman, Sprite *class525) + : AnimatedSprite(vm, 1100), _parentScene(parentScene), _klayman(klayman), _class525(class525), + _soundResource1(vm), _soundResource2(vm), _soundResource3(vm) { + + _class489Item = &kClass489Items[getGlobalVar(0x04A105B3)]; + // TODO createSurface3(990, dword_4B26D8); + createSurface(990, 640, 480); //TODO: Remeove once the line above is done + setFileHash(0x10E3042B, 0, -1); + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&Class489::handleMessage); + _x = getGlobalVar(0x04A10F33) * 108 + _class489Item->point.x; + _flag = true; + sub434C80(); + setDoDeltaX(1); + if ((int8)getGlobalVar(0x04A10F33) == _class489Item->varIndex2) { + sub434E90(); + } + _soundResource3.load(0xC8C2507C); +} + +Class489::~Class489() { + // TODO Sound1ChList_sub_407AF0(0x05331081); +} + +uint32 Class489::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x1011: + _parentScene->sendMessage(0x4826, 0, this); + messageResult = 1; + break; + case 0x4807: + setGlobalVar(0x04A10F33, (_x - _class489Item->point.x) / 108); + if ((int8)getGlobalVar(0x04A10F33) == _class489Item->varIndex2) { + sub434E60(); + } else { + sub434DD0(); + } + break; + case 0x480B: + if (param.asInteger() != 1) { + if ((int8)getGlobalVar(0x04A10F33) < _class489Item->varIndex1) { + incGlobalVar(0x04A10F33, 1); + } + } else if (getGlobalVar(0x04A10F33) > 0) { + incGlobalVar(0x04A10F33, -1); + } + sub434DF0(); + break; + case 0x480C: + if (param.asInteger() != 1) { + messageResult = (int8)getGlobalVar(0x04A10F33) < _class489Item->varIndex1 ? 1 : 0; + } else { + messageResult = getGlobalVar(0x04A10F33) > 0 ? 1 : 0; + } + break; + case 0x482A: + _parentScene->sendMessage(0x1022, 990, this); + break; + case 0x482B: + _parentScene->sendMessage(0x1022, 1010, this); + break; + case 0x4828: + sub435040(); + break; + } + return messageResult; +} + +uint32 Class489::handleMessage4348E0(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x1011: + if (param.asPoint().x - _x >= 17 && param.asPoint().x - _x <= 56 && + param.asPoint().y - _y >= -120 && param.asPoint().y - _y <= -82) { + _parentScene->sendMessage(0x4826, 1, this); + } else { + _parentScene->sendMessage(0x4826, 0, this); + } + messageResult = 1; + break; + case 0x4807: + _parentScene->sendMessage(0x4807, 0, this); + sub434F80(); + break; + case 0x480B: + if (param.asInteger() != 1) { + if ((int8)getGlobalVar(0x04A10F33) < _class489Item->varIndex1) { + incGlobalVar(0x04A10F33, 1); + } + } else if (getGlobalVar(0x04A10F33) > 0) { + incGlobalVar(0x04A10F33, -1); + } + sub434FF0(); + break; + case 0x480C: + if (param.asInteger() != 1) { + messageResult = (int8)getGlobalVar(0x04A10F33) < _class489Item->varIndex1 ? 1 : 0; + } else { + messageResult = getGlobalVar(0x04A10F33) > 0 ? 1 : 0; + } + break; + case 0x480F: + sub434EC0(); + break; + case 0x482A: + _parentScene->sendMessage(0x1022, 990, this); + break; + case 0x482B: + _parentScene->sendMessage(0x1022, 1010, this); + break; + } + return messageResult; +} + +uint32 Class489::handleMessage434B20(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x3002: + removeCallbacks(); + break; + } + return messageResult; +} + +void Class489::spriteUpdate434B60() { + if (_x <= _klayman->getX()) + _x = _klayman->getX() - 100; + else + _x = _klayman->getX() + 100; + sub434C80(); + if (_remX == _x) { + if (getGlobalVar(0x04A10F33) == 0 && _class489Item->flag4 != 0) { + _parentScene->sendMessage(0x1019, 0, this); + incGlobalVar(0x04A105B3, -1); + setGlobalVar(0x04A10F33, kClass489Items[getGlobalVar(0x04A105B3)].varIndex1); + } else if ((int8)getGlobalVar(0x04A10F33) == _class489Item->varIndex1 && _class489Item->flag != 0) { + _parentScene->sendMessage(0x1019, 1, this); + incGlobalVar(0x04A105B3, +1); + setGlobalVar(0x04A10F33, 0); + } + } + Sprite::processDelta(); +} + +void Class489::sub434C80() { + + bool soundFlag = false; + + _y = _class489Item->point.y; + + if (_class489Item->index1 != -1) { + int16 elX = _class489Item->index1 * 108 + _class489Item->point.x; + if (elX - 20 < _x && elX + 20 > _x) { + soundFlag = true; + _y = _class489Item->point.y + 10; + } + } + + if (_class489Item->flag2 != -1) { + int16 elX = _class489Item->index1 * 108 + _class489Item->point.x; + if (elX - 20 < _x && elX + 20 > _x) { + soundFlag = true; + _y = _class489Item->point.y + 10; + } + } + + if (_class489Item->varIndex2 != -1) { + int16 elX = _class489Item->varIndex2 * 108 + _class489Item->point.x; + if (elX - 20 < _x && elX + 20 > _x) { + soundFlag = true; + _y = _class489Item->point.y + 10; + } + } + + if (_flag) { + if (!soundFlag) { + _flag = false; + } + } else if (soundFlag) { + _soundResource2.play(0x5440E474); + _flag = true; + } + +} + +void Class489::sub434D80() { + AnimatedSprite::updateDeltaXY(); + if (_rect.y1 <= 150) { + _class525->sendMessage(0x483A, 0, this); + setFileHash1(); + SetMessageHandler(&Sprite::handleMessage); + SetSpriteCallback(NULL); + _surface->setVisible(false); + } +} + +void Class489::sub434DD0() { + SetSpriteCallback(NULL); + SetMessageHandler(&Class489::handleMessage); + setFileHash(0x10E3042B, 0, -1); +} + +void Class489::sub434DF0() { + _remX = getGlobalVar(0x04A10F33) * 108 + _class489Item->point.x; + setFileHash(0x14A10137, 0, -1); + SetSpriteCallback(&Class489::spriteUpdate434B60); + SetMessageHandler(&Class489::handleMessage); + _soundResource2.play(0xEC008474); +} + +void Class489::sub434E60() { + SetSpriteCallback(NULL); + SetMessageHandler(&Class489::handleMessage434B20); + setFileHash(0x80C32213, 0, -1); + SetAnimationCallback3(&Class489::sub434E90); +} + +void Class489::sub434E90() { + SetSpriteCallback(NULL); + SetMessageHandler(&Class489::handleMessage4348E0); + setFileHash(0xD23B207F, 0, -1); +} + +void Class489::sub434EC0() { + setFileHash(0x50A80517, 0, -1); + SetMessageHandler(&Class489::handleMessage434B20); + SetSpriteCallback(NULL); + SetAnimationCallback3(&Class489::sub434F40); + setGlobalVar(0x12A10DB3, 1); + _soundResource1.play(0xCC4A8456); + // TODO Sound1ChList_addSoundResource(0x05331081, 0xCE428854, true); + // TODO Sound1ChList_playLooping(0xCE428854); +} + +void Class489::sub434F40() { + _parentScene->sendMessage(0x480F, 0, this); + setFileHash(0xD833207F, 0, -1); + SetSpriteCallback(NULL); + SetMessageHandler(&Class489::handleMessage4348E0); +} + +void Class489::sub434F80() { + setFileHash(0x50A94417, 0, -1); + SetSpriteCallback(NULL); + SetMessageHandler(&Class489::handleMessage434B20); + SetAnimationCallback3(&Class489::sub434E90); + setGlobalVar(0x12A10DB3, 0); + _soundResource1.play(0xCC4A8456); + // TODO Sound1ChList_deleteSoundByHash(0xCE428854); +} + +void Class489::sub434FF0() { + _remX = getGlobalVar(0x04A10F33) * 108 + _class489Item->point.x; + setFileHash(0x22CB4A33, 0, -1); + SetSpriteCallback(&Class489::spriteUpdate434B60); + SetMessageHandler(&Class489::handleMessage434B20); + SetAnimationCallback3(&Class489::sub434DF0); +} + +void Class489::sub435040() { + setGlobalVar(0x04A105B3, 4); + setGlobalVar(0x04A10F33, 0); + SetSpriteCallback(&Class489::sub434D80); + SetMessageHandler(&Sprite::handleMessage); + setFileHash(0x708D4712, 0, -1); + _soundResource3.play(); +} + +Scene1401::Scene1401(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule, true), _flag(false), _class427(NULL), _class489(NULL), + _class525(NULL), _class526(NULL), _class527(NULL), _class528(NULL), + _sprite1(NULL), _sprite2(NULL), _sprite3(NULL), _ssButton(NULL) { + + SetMessageHandler(&Scene1401::handleMessage); + SetUpdateHandler(&Scene1401::update); + setRectList(0x004B6758); + _surfaceFlag = true; + + _background = addBackground(new DirtyBackground(_vm, 0x08221FA5, 0, 0)); + _palette = new Palette(_vm, 0x08221FA5); + _palette->usePalette(); + _mouseCursor = addSprite(new Mouse433(_vm, 0x21FA108A, NULL)); + + // TODO _class427 = addSprite(new Class427(_vm, this, 0x980F3124, 0x12192892, 100, 0)); + _class525 = addSprite(new Class525(_vm)); + + if (!getGlobalVar(0x01023818)) { + _class526 = addSprite(new Class526(_vm, _class525)); + _class527 = addSprite(new Class527(_vm, _class525)); + } + + _sprite3 = addSprite(new StaticSprite(_vm, 0xA82BA811, 1100)); + addSprite(new StaticSprite(_vm, 0x0A116C60, 1100)); + _ssButton = addSprite(new SsCommonButtonSprite(_vm, this, 0xB84B1100, 100, 0)); + _sprite1 = addSprite(new StaticSprite(_vm, 0x38EA100C, 1005)); + _sprite2 = addSprite(new StaticSprite(_vm, 0x98D0223C, 1200)); + _sprite2->getSurface()->setVisible(false); + + if (which < 0) { + _klayman = new KmScene1401(_vm, this, 380, 447); + setMessageList(0x004B65C8); + _sprite1->getSurface()->setVisible(false); + } else if (which == 1) { + _klayman = new KmScene1401(_vm, this, 0, 447); + setMessageList(0x004B65D0); + _sprite1->getSurface()->setVisible(false); + } else if (which == 2) { + _klayman = new KmScene1401(_vm, this, 660, 447); + setMessageList(0x004B65D8); + _sprite1->getSurface()->setVisible(false); + } else { + _klayman = new KmScene1401(_vm, this, 290, 413); + setMessageList(0x004B65E8); + _sprite1->getSurface()->setVisible(false); + } + addSprite(_klayman); + + if (getGlobalVar(0x04A105B3) == 2) { + _class489 = addSprite(new Class489(_vm, this, _klayman, _class525)); + _vm->_collisionMan->addSprite(_class489); + if (getGlobalVar(0x04A10F33) == 6) { + _klayman->sendEntityMessage(0x1014, _class489, this); + _klayman->setX(_class489->getX() + 100); + _klayman->processDelta(); + setMessageList(0x004B6670); + } else if (getGlobalVar(0x04A10F33) == 0) { + _klayman->sendEntityMessage(0x1014, _class489, this); + _klayman->setX(_class489->getX() - 100); + _klayman->processDelta(); + setMessageList(0x004B6670); + } + _class489->getSurface()->getClipRect().x1 = _sprite3->getSurface()->getDrawRect().x; + _class489->getSurface()->getClipRect().y1 = _sprite2->getSurface()->getDrawRect().y; + _class489->getSurface()->getClipRect().x2 = 640; + _class489->getSurface()->getClipRect().y2 = 480; + } + + _klayman->getSurface()->getClipRect().x1 = _sprite3->getSurface()->getDrawRect().x; + _klayman->getSurface()->getClipRect().y1 = 0; + _klayman->getSurface()->getClipRect().x2 = 640; + _klayman->getSurface()->getClipRect().y2 = 480; + + if (which == 0 && _class489 && _class489->hasMessageHandler()) { + _class489->sendMessage(0x482B, 0, this); + } + + _class528 = addSprite(new Class528(_vm, _klayman, which == 1)); + +} + +void Scene1401::update() { + Scene::update(); + if (_class489 && !_flag && _class489->getY() < 360) { + _sprite2->getSurface()->setVisible(true); + _flag = true; + } else { + _sprite2->getSurface()->setVisible(false); + } +} + +uint32 Scene1401::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x02144CB1) { + _klayman->sendEntityMessage(0x1014, _class427, this); + } else if (param.asInteger() == 0x402064D8) { + _klayman->sendEntityMessage(0x1014, _ssButton, this); + } else if (param.asInteger() == 0x01C66840) { + if (_class528->hasMessageHandler() && _class528->sendMessage(0x2001, 0, this) != 0) { + setMessageList(0x004B6690); + } else { + setMessageList(0x004B66B0); + } + } + break; + case 0x1019: + if (param.asInteger() != 0) { + _parentModule->sendMessage(0x1009, 2, this); + } else { + _parentModule->sendMessage(0x1009, 1, this); + } + break; + case 0x480B: + if (sender == _class427) { + _class525->sendMessage(0x2000, 0, this); + if (!getGlobalVar(0x01023818)) { + _class526->sendMessage(0x4839, 0, this); + _class527->sendMessage(0x4839, 0, this); + setGlobalVar(0x01023818, 1); + } + if (_class489 && _class489->getX() > 404 && _class489->getX() < 504) { + _class489 ->sendMessage(0x4839, 0, this); + } + } else if (sender == _ssButton) { + _ssButton->sendMessage(0x4808, 0, this); + } + break; + case 0x4826: + if (sender == _class489) { + if (_class489->sendMessage(0x480C, _klayman->getX() > _class489->getX() ? 1 : 0, this) != 0) { + _klayman->sendEntityMessage(0x1014, _class489, this); + setMessageList2(0x004B6658); + } else { + setMessageList2(0x004B65F0); + } + } + break; + case 0x482A: + _sprite1->getSurface()->setVisible(true); + if (_class489) { + _class489->sendMessage(0x482B, 0, this); + } + break; + case 0x482B: + _sprite1->getSurface()->setVisible(false); + if (_class489) { + _class489->sendMessage(0x482A, 0, this); + } + break; + } + return 0; +} + +// Scene1402 + +Class454::Class454(NeverhoodEngine *vm, uint32 fileHash, int surfacePriority) + : StaticSprite(vm, fileHash, surfacePriority) { + + SetFilterY(&Sprite::defFilterY); + SetUpdateHandler(&StaticSprite::update); + +} + +Class482::Class482(NeverhoodEngine *vm, Scene *parentScene, int which) + : AnimatedSprite(vm, 1100), _parentScene(parentScene), _soundResource1(vm), + _soundResource2(vm) { + + // TODO createSurface3(900, dword_4B6768); + createSurface(900, 640, 480); //TODO: Remeove once the line above is done + + SetFilterY(&Sprite::defFilterY); + SetUpdateHandler(&AnimatedSprite::update); + SetMessageHandler(&Class482::handleMessage); + _x = 279; + _y = 270; + if (which == 2) { + setFileHash(0x20060259, 0, -1); + _soundResource1.play(0x419014AC); + _soundResource2.load(0x61901C29); + } else if (which == 1) { + setFileHash(0x210A0213, 0, -1); + _soundResource1.play(0x41809C6C); + } else { + setFileHash(0x20060259, 0, -1); + _soundResource2.load(0x61901C29); + _newHashListIndex = -2; + } +} + +uint32 Class482::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x2002: + _soundResource2.play(); + setFileHash(0x20060259, -1, -1); + _playBackwards = true; + SetAnimationCallback3(&Class482::sub428530); + break; + case 0x3002: + removeCallbacks(); + break; + } + return messageResult; +} + +void Class482::sub428500() { + _parentScene->sendMessage(0x2000, 0, this); + setFileHash1(); + _surface->setVisible(false); +} + +void Class482::sub428530() { + _parentScene->sendMessage(0x2001, 0, this); + setFileHash1(); + _surface->setVisible(false); +} + +void Class482::sub428560() { + _parentScene->sendMessage(0x2003, 0, this); + setFileHash1(); +} + +Scene1402::Scene1402(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule, true), _flag(false), _class482(NULL), _class489(NULL) { + + SetMessageHandler(&Scene1402::handleMessage); + + _background = addBackground(new Background(_vm, 0x231482F0, 0, 0)); + _background->getSurface()->getDrawRect().y = -10; + // TODO g_screen->field_26 = 0; + _palette = new Palette(_vm, 0x231482F0); + _palette->addPalette(0x91D3A391, 0, 64, 0); + _palette->usePalette(); + _mouseCursor = addSprite(new Mouse433(_vm, 0x482F4239, NULL)); + + _class454_1 = addSprite(new Class454(_vm, 0x15402D64, 1100)); + _class454_2 = addSprite(new Class454(_vm, 0x10A02120, 1100)); + _class454_3 = addSprite(new Class454(_vm, 0x60882BE0, 1100)); + + if (getGlobalVar(0x70A1189C)) + setRectList(0x004B0C48); + else + setRectList(0x004B0C98); + + if (which < 0) { + _klayman = new KmScene1402(_vm, this, 377, 391); + setMessageList(0x004B0B48); + if (!getGlobalVar(0x70A1189C)) { + _class482 = addSprite(new Class482(_vm, this, 0)); + } + } else if (which == 1) { + _klayman = new KmScene1402(_vm, this, 42, 391); + setMessageList(0x004B0B50); + } else if (which == 2) { + _klayman = new KmScene1402(_vm, this, 377, 391); + setMessageList(0x004B0B60); + _klayman->setDoDeltaX(1); + if (getGlobalVar(0x70A1189C)) { + _class482 = addSprite(new Class482(_vm, this, 1)); + clearRectList(); + _mouseCursor->getSurface()->setVisible(false); + sub428220(); + } else { + _class482 = addSprite(new Class482(_vm, this, 0)); + } + } else { + _klayman = new KmScene1402(_vm, this, 513, 391); + setMessageList(0x004B0B58); + if (!getGlobalVar(0x70A1189C)) { + _class482 = addSprite(new Class482(_vm, this, 2)); + sub428220(); + } + } + addSprite(_klayman); + + if (_class482) { + _class482->getSurface()->getClipRect().x1 = 0; + _class482->getSurface()->getClipRect().y1 = 0; + _class482->getSurface()->getClipRect().x2 = 640; + _class482->getSurface()->getClipRect().y2 = _class454_3->getSurface()->getDrawRect().y + _class454_3->getSurface()->getDrawRect().height; + } + + if (getGlobalVar(0x4A105B3) == 1) { + _class489 = addSprite(new Class489(_vm, this, _klayman, 0)); + _vm->_collisionMan->addSprite(_class489); + if (getGlobalVar(0x4A10F33) == 4) { + _klayman->sendEntityMessage(0x1014, _class489, this); + _klayman->setX(_class489->getX() + 100); + _klayman->processDelta(); + setMessageList(0x004B0BD0); + } else if (getGlobalVar(0x4A10F33) == 0) { + _klayman->sendEntityMessage(0x1014, _class489, this); + _klayman->setX(_class489->getX() - 100); + _klayman->processDelta(); + setMessageList(0x004B0BD0); + } + _class489->getSurface()->getClipRect().x1 = _class454_1->getSurface()->getDrawRect().x; + _class489->getSurface()->getClipRect().y1 = 0; + _class489->getSurface()->getClipRect().x2 = _class454_2->getSurface()->getDrawRect().x; + _class489->getSurface()->getClipRect().y2 = _class454_3->getSurface()->getDrawRect().y + _class454_3->getSurface()->getDrawRect().height; + } + + _klayman->getSurface()->getClipRect().x1 = _class454_1->getSurface()->getDrawRect().x; + _klayman->getSurface()->getClipRect().y1 = 0; + _klayman->getSurface()->getClipRect().x2 = _class454_2->getSurface()->getDrawRect().x + _class454_2->getSurface()->getDrawRect().width; + _klayman->getSurface()->getClipRect().y2 = _class454_3->getSurface()->getDrawRect().y + _class454_3->getSurface()->getDrawRect().height; + +} + +void Scene1402::update() { + if (_flag) { + _background->getSurface()->getDrawRect().y = _vm->_rnd->getRandomNumber(10) - 10; + // TODO g_screen->field_26 = -10 - _background->getSurface()->getDrawRect().y; + } else { + _background->getSurface()->getDrawRect().y = -10; + // TODO g_screen->field_26 = 0; + SetUpdateHandler(&Scene::update); + } + Scene::update(); + if (_class482) { + _class482->getSurface()->getClipRect().x1 = 0; + _class482->getSurface()->getClipRect().y1 = 0; + _class482->getSurface()->getClipRect().x2 = 640; + _class482->getSurface()->getClipRect().y2 = _class454_3->getSurface()->getDrawRect().y + _class454_3->getSurface()->getDrawRect().height; + } + _klayman->getSurface()->getClipRect().x1 = _class454_1->getSurface()->getDrawRect().x; + _klayman->getSurface()->getClipRect().y1 = 0; + _klayman->getSurface()->getClipRect().x2 = _class454_2->getSurface()->getDrawRect().x + _class454_2->getSurface()->getDrawRect().width; + _klayman->getSurface()->getClipRect().y2 = _class454_3->getSurface()->getDrawRect().y + _class454_3->getSurface()->getDrawRect().height; +} + +uint32 Scene1402::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x100D: + if (param.asInteger() == 0x00F43389) { + if (getGlobalVar(0x70A1189C)) { + _parentModule->sendMessage(0x1009, 0, this); + } else { + clearRectList(); + _klayman->getSurface()->setVisible(false); + _mouseCursor->getSurface()->setVisible(false); + _class482->sendMessage(0x2002, 0, this); + sub428220(); + } + } + break; + case 0x1019: + if (param.asInteger()) { + _parentModule->sendMessage(0x1009, 0, this); + } else { + _parentModule->sendMessage(0x1009, 1, this); + } + break; + case 0x2000: + sub428230(); + _mouseCursor->getSurface()->setVisible(true); + setRectList(0x004B0C48); + break; + case 0x2001: + sub428230(); + _parentModule->sendMessage(0x1009, 0, this); + break; + case 0x2003: + sub428230(); + break; + case 0x4826: + if (sender == _class489) { + if (_class489->sendMessage(0x408C, _klayman->getX() > _class489->getX() ? 1 : 0, this) != 0) { + _klayman->sendEntityMessage(0x1014, _class489, this); + setMessageList2(0x004B0BB8); + } else { + setMessageList2(0x004B0B68); + } + } + } + return 0; +} + +void Scene1402::sub428220() { + _flag = true; + SetUpdateHandler(&Scene1402::update); +} + +void Scene1402::sub428230() { + _flag = false; +} + +// Scene1407 + +static const int16 kScene1407MouseFloorY[] = { + 106, 150, 191, 230, 267, 308, 350, 395 +}; + +static const struct { + int16 x; + int16 floorIndex; + int16 sectionIndex; + int16 nextHoleIndex; +} kScene1407MouseHoles[] = { + {125, 0, 0, 7}, + {452, 7, 21, 0}, + {337, 4, 11, 4}, + {286, 6, 17, 6}, + {348, 6, 17, 39}, + {536, 6, 18, 42}, + {111, 1, 3, 18}, + {203, 1, 3, 38}, + {270, 1, 3, 9}, + {197, 5, 14, 3}, + {252, 5, 14, 35}, + {297, 5, 14, 7}, + {359, 5, 14, 8}, + {422, 4, 12, 26}, + {467, 4, 12, 2}, + {539, 4, 12, 40}, + {111, 5, 13, 17}, + {211, 0, 1, 20}, + {258, 0, 1, 11}, + {322, 0, 1, 16}, + { 99, 6, 16, 31}, + {142, 6, 16, 27}, + {194, 6, 16, 12}, + {205, 2, 6, 45}, + {264, 2, 6, 10}, + { 98, 4, 10, 2}, + {152, 4, 10, 37}, + {199, 4, 10, 13}, + {258, 4, 10, 16}, + {100, 7, 19, 43}, + {168, 7, 19, 23}, + {123, 3, 8, 14}, + {181, 3, 8, 39}, + {230, 3, 8, 28}, + {292, 3, 8, 22}, + {358, 3, 8, 36}, + {505, 3, 9, 44}, + {400, 2, 7, 34}, + {454, 2, 7, 32}, + {532, 2, 7, 46}, + {484, 5, 15, 25}, + {529, 5, 15, 30}, + {251, 7, 20, 48}, + {303, 7, 20, 21}, + {360, 7, 20, 33}, + {503, 0, 2, 5}, + {459, 1, 4, 19}, + {530, 1, 4, 42}, + {111, 2, 5, 47}, + {442, 6, 18, 1} +}; + +static const struct { + int16 x1, x2; + int16 goodHoleIndex; +} kScene1407MouseSections[] = { + {100, 149, 0}, + {182, 351, 17}, + {430, 524, 45}, + { 89, 293, 7}, + {407, 555, 47}, + { 89, 132, 48}, + {178, 303, 23}, + {367, 551, 38}, + {105, 398, 31}, + {480, 537, 36}, + { 84, 275, 27}, + {318, 359, 2}, + {402, 560, 15}, + { 91, 132, 16}, + {179, 400, 10}, + {461, 552, 41}, + { 86, 218, 21}, + {267, 376, 4}, + {420, 560, 49}, + { 77, 188, 30}, + {237, 394, 44}, + {438, 515, 5} +}; + +AsScene1407Mouse::AsScene1407Mouse(NeverhoodEngine *vm, Scene *parentScene) + : AnimatedSprite(vm, 1100), _parentScene(parentScene), _currSectionIndex(0) { + + // TODO createSurface3(100, dword_4B05B0); + createSurface(100, 640, 480); //TODO: Remeove once the line above is done + + SetUpdateHandler(&AnimatedSprite::update); + _x = 108; + _y = 106; + stIdleLookAtGoodHole(); +} + +void AsScene1407Mouse::suWalkTo() { + int16 xdelta = _walkDestX - _x; + if (xdelta > _deltaX) + xdelta = _deltaX; + else if (xdelta < -_deltaX) + xdelta = -_deltaX; + _deltaX = 0; + if (_walkDestX == _x) { + sendMessage(0x1019, 0, this); + } else { + _x += xdelta; + processDelta(); + } +} + +void AsScene1407Mouse::upGoThroughHole() { + if (_countdown != 0 && (--_countdown == 0)) { + SetUpdateHandler(&AnimatedSprite::update); + removeCallbacks(); + } + AnimatedSprite::update(); +} + +uint32 AsScene1407Mouse::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x0001: + { + int16 mouseX = param.asPoint().x; + int16 mouseY = param.asPoint().y; + int holeIndex; + for (holeIndex = 0; holeIndex < 50; holeIndex++) { + int16 holeX = kScene1407MouseHoles[holeIndex].x; + int16 holeY = kScene1407MouseFloorY[kScene1407MouseHoles[holeIndex].floorIndex]; + if (mouseX >= holeX - 14 && mouseX <= holeX + 14 && mouseY >= holeY - 36 && mouseY <= holeY) + break; + } + if (holeIndex < 50 && kScene1407MouseHoles[holeIndex].sectionIndex == _currSectionIndex) { + _nextHoleIndex = kScene1407MouseHoles[holeIndex].nextHoleIndex; + _walkDestX = kScene1407MouseHoles[holeIndex].x; + stWalkToHole(); + } else { + if (mouseX < kScene1407MouseSections[_currSectionIndex].x1) { + _walkDestX = kScene1407MouseSections[_currSectionIndex].x1; + } else if (mouseX > kScene1407MouseSections[_currSectionIndex].x2) { + _walkDestX = kScene1407MouseSections[_currSectionIndex].x2; + } else { + _walkDestX = mouseX; + } + stWalkToDest(); + } + } + break; + case 0x1019: + removeCallbacks(); + break; + case 0x2001: + { + // Reset the position + // Find the nearest hole and go through it, and exit at the first hole + int16 distance = 640; + int matchIndex = 50; + for (int index = 0; index < 50; index++) { + if (kScene1407MouseHoles[index].sectionIndex == _currSectionIndex) { + if (ABS(kScene1407MouseHoles[index].x - _x) < distance) { + matchIndex = index; + distance = ABS(kScene1407MouseHoles[index].x - _x); + } + } + } + if (matchIndex < 50) { + _nextHoleIndex = 0; + _walkDestX = kScene1407MouseHoles[matchIndex].x; + stWalkToHole(); + } + } + break; + } + return messageResult; +} + +void AsScene1407Mouse::stIdleLookAtGoodHole() { + setDoDeltaX(kScene1407MouseHoles[kScene1407MouseSections[_currSectionIndex].goodHoleIndex].x < _x ? 1 : 0); + setFileHash(0x72215194, 0, -1); + SetSpriteCallback(NULL); + SetMessageHandler(&AsScene1407Mouse::handleMessage); +} + +void AsScene1407Mouse::stWalkToDest() { + if (_walkDestX != _x) { + setDoDeltaX(_walkDestX < _x ? 1 : 0); + setFileHash(0x22291510, 0, -1); + SetSpriteCallback(&AsScene1407Mouse::suWalkTo); + SetMessageHandler(&AsScene1407Mouse::handleMessage); + SetAnimationCallback3(&AsScene1407Mouse::stIdleLookAtGoodHole); + } +} + +void AsScene1407Mouse::stWalkToHole() { + setDoDeltaX(_walkDestX < _x ? 1 : 0); + setFileHash(0x22291510, 0, -1); + SetSpriteCallback(&AsScene1407Mouse::suWalkTo); + SetMessageHandler(&AsScene1407Mouse::handleMessage); + SetAnimationCallback3(&AsScene1407Mouse::stGoThroughHole); +} + +void AsScene1407Mouse::stGoThroughHole() { + setFileHash(0x72215194, 0, -1); + SetSpriteCallback(NULL); + SetMessageHandler(NULL); + SetUpdateHandler(&AsScene1407Mouse::upGoThroughHole); + SetAnimationCallback3(&AsScene1407Mouse::stArriveAtHole); + _surface->setVisible(false); + _countdown = 12; +} + +void AsScene1407Mouse::stArriveAtHole() { + _currSectionIndex = kScene1407MouseHoles[_nextHoleIndex].sectionIndex; + _x = kScene1407MouseHoles[_nextHoleIndex].x; + _y = kScene1407MouseFloorY[kScene1407MouseHoles[_nextHoleIndex].floorIndex]; + if (_nextHoleIndex == 1) { + _parentScene->sendMessage(0x2000, 0, this); + _walkDestX = 512; + stWalkToDest(); + _surface->setVisible(true); + } else { + _walkDestX = _x + 14; + stWalkToDest(); + _surface->setVisible(true); + } +} + +Scene1407::Scene1407(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule, true), _soundResource(vm), _puzzleSolvedCountdown(0), + _resetButtonCountdown(0) { + + _surfaceFlag = true; + + SetMessageHandler(&Scene1407::handleMessage); + SetUpdateHandler(&Scene1407::update); + + _background = addBackground(new DirtyBackground(_vm, 0x00442225, 0, 0)); + _palette = new Palette(_vm, 0x00442225); + _palette->usePalette(); + _mouseCursor = addSprite(new Mouse435(_vm, 0x4222100C, 20, 620)); + + _asMouse = addSprite(new AsScene1407Mouse(_vm, this)); + _ssResetButton = addSprite(new StaticSprite(_vm, 0x12006600, 100)); + _ssResetButton->getSurface()->setVisible(false); + +} + +void Scene1407::update() { + Scene::update(); + if (_puzzleSolvedCountdown != 0 && (--_puzzleSolvedCountdown == 0)) { + _parentModule->sendMessage(0x1009, 1, this); + } else if (_resetButtonCountdown != 0 && (--_resetButtonCountdown == 0)) { + _ssResetButton->getSurface()->setVisible(false); + } +} + +uint32 Scene1407::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x0001: + if (_puzzleSolvedCountdown == 0) { + // TODO: Debug/Cheat stuff + if (param.asPoint().x <= 20 || param.asPoint().x >= 620) { + // Exit scene + _parentModule->sendMessage(0x1009, 0, this); + } else if (param.asPoint().x >= 75 && param.asPoint().x <= 104 && + param.asPoint().y >= 62 && param.asPoint().y <= 90) { + // The reset button was clicked + _asMouse->sendMessage(0x2001, 0, this); + _ssResetButton->getSurface()->setVisible(true); + _soundResource.play(0x44045000); + _resetButtonCountdown = 12; + } else { + // Handle the mouse + _asMouse->sendMessage(messageNum, param, this); + } + } + break; + case 0x000D: + // TODO: Debug/Cheat stuff + break; + case 0x2000: + // The mouse got the cheese (nomnom) + setGlobalVar(0x70A1189C, 1); + _soundResource.play(0x68E25540); + _mouseCursor->getSurface()->setVisible(false); + _puzzleSolvedCountdown = 72; + break; + } + return 0; +} + +} // End of namespace Neverhood diff --git a/engines/neverhood/module1400.h b/engines/neverhood/module1400.h new file mode 100644 index 0000000000..433dc413f5 --- /dev/null +++ b/engines/neverhood/module1400.h @@ -0,0 +1,242 @@ +/* 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_MODULE1400_H +#define NEVERHOOD_MODULE1400_H + +#include "neverhood/neverhood.h" +#include "neverhood/module.h" +#include "neverhood/scene.h" + +namespace Neverhood { + +class Module1400 : public Module { +public: + Module1400(NeverhoodEngine *vm, Module *parentModule, int which); + virtual ~Module1400(); +protected: + void createScene1401(int which); + void createScene1402(int which); + void createScene1403(int which); + void createScene1404(int which); + void createScene1405(int which); + void createScene1406(int which); + void createScene1407(int which); + void updateScene1401(); + void updateScene1402(); + void updateScene1403(); + void updateScene1404(); + void updateScene1405(); + void updateScene1406(); + void updateScene1407(); +}; + +// Scene1401 + +class Class525 : public AnimatedSprite { +public: + Class525(NeverhoodEngine *vm); + virtual ~Class525(); +protected: + int _countdown1; + int _countdown2; + SoundResource _soundResource1; + SoundResource _soundResource2; + void update4662A0(); + void update466300(); + uint32 handleMessage466320(int messageNum, const MessageParam ¶m, Entity *sender); + uint32 handleMessage4663C0(int messageNum, const MessageParam ¶m, Entity *sender); + void sub466420(); + void sub466460(); + void sub4664B0(); +}; + +class Class526 : public AnimatedSprite { +public: + Class526(NeverhoodEngine *vm, Sprite *class525); +protected: + Sprite *_class525; + SoundResource _soundResource; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void spriteUpdate466720(); + void sub466770(); +}; + +class Class527 : public AnimatedSprite { +public: + Class527(NeverhoodEngine *vm, Sprite *class526); +protected: + Sprite *_class526; + SoundResource _soundResource; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void spriteUpdate466920(); + void sub466970(); +}; + +class Class528 : public AnimatedSprite { +public: + Class528(NeverhoodEngine *vm, Sprite *klayman, bool flag); +protected: + Sprite *_klayman; + SoundResource _soundResource; + int _countdown; + bool _flag; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void sub466BF0(); + void sub466C50(); + void sub466CB0(); +}; + +struct Class489Item { + NPoint point; + int8 varIndex1; + int8 varIndex2; + int8 index1; + int8 flag2; + int8 flag4; + int8 flag; +}; + +class Class489 : public AnimatedSprite { +public: + Class489(NeverhoodEngine *vm, Scene *parentScene, Sprite *klayman, Sprite *class525); + virtual ~Class489(); +protected: + Scene *_parentScene; + Sprite *_klayman; + Sprite *_class525; + const Class489Item *_class489Item; + SoundResource _soundResource1; + SoundResource _soundResource2; + SoundResource _soundResource3; + int16 _remX; + bool _flag; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + uint32 handleMessage4348E0(int messageNum, const MessageParam ¶m, Entity *sender); + uint32 handleMessage434B20(int messageNum, const MessageParam ¶m, Entity *sender); + void spriteUpdate434B60(); + void sub434C80(); + void sub434D80(); + void sub434DD0(); + void sub434DF0(); + void sub434E60(); + void sub434E90(); + void sub434EC0(); + void sub434F40(); + void sub434F80(); + void sub434FF0(); + void sub435040(); +}; + +class Scene1401 : public Scene { +public: + Scene1401(NeverhoodEngine *vm, Module *parentModule, int which); +protected: + bool _flag; + Sprite *_class427; + Sprite *_class489; + Sprite *_class525; + Sprite *_class526; + Sprite *_class527; + Sprite *_class528; + Sprite *_sprite1; + Sprite *_sprite2; + Sprite *_sprite3; + Sprite *_ssButton; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +// Scene1402 + +class Class454 : public StaticSprite { +public: + Class454(NeverhoodEngine *vm, uint32 fileHash, int surfacePriority); +}; + +class Class482 : public AnimatedSprite { +public: + Class482(NeverhoodEngine *vm, Scene *parentScene, int which); +protected: + Scene *_parentScene; + SoundResource _soundResource1; + SoundResource _soundResource2; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void sub428500(); + void sub428530(); + void sub428560(); +}; + +class Scene1402 : public Scene { +public: + Scene1402(NeverhoodEngine *vm, Module *parentModule, int which); +protected: + Sprite *_class454_1; + Sprite *_class454_2; + Sprite *_class454_3; + Sprite *_class482; + Sprite *_class489; + bool _flag; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void sub428220(); + void sub428230(); +}; + +// Scene1407 + +class AsScene1407Mouse : public AnimatedSprite { +public: + AsScene1407Mouse(NeverhoodEngine *vm, Scene *parentScene); +protected: + Scene *_parentScene; + int16 _walkDestX; + int16 _currSectionIndex; + int16 _nextHoleIndex; + int _countdown; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void suWalkTo(); + void upGoThroughHole(); + void stIdleLookAtGoodHole(); + void stWalkToDest(); + void stWalkToHole(); + void stGoThroughHole(); + void stArriveAtHole(); +}; + +class Scene1407 : public Scene { +public: + Scene1407(NeverhoodEngine *vm, Module *parentModule, int which); +protected: + SoundResource _soundResource; + Sprite *_asMouse; + Sprite *_ssResetButton; + int _puzzleSolvedCountdown; + int _resetButtonCountdown; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +} // End of namespace Neverhood + +#endif /* NEVERHOOD_MODULE1400_H */ diff --git a/engines/neverhood/module1700.cpp b/engines/neverhood/module1700.cpp new file mode 100644 index 0000000000..3289173dfb --- /dev/null +++ b/engines/neverhood/module1700.cpp @@ -0,0 +1,359 @@ +/* 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/module1700.h" +#include "neverhood/navigationscene.h" + +namespace Neverhood { + +Module1700::Module1700(NeverhoodEngine *vm, Module *parentModule, int which) + : Module(vm, parentModule), _soundResource(vm) { + + debug("Create Module1700(%d)", which); + + // TODO Music18hList_add(0x04212331); + // TODO Sound1ChList_addSoundResources(0x04212331, dword_4AE930, true); + // TODO Sound1ChList_setSoundValuesMulti(dword_4AE930, 1, 50, 600, 5, 150); + // TODO Sound1ChList_sub_407C70(0x04212331, 0x41861371, 0x43A2507F, 0); + + if (which < 0) { + switch (_vm->gameState().sceneNum) { + case 0: + createScene1701(-1); + break; + case 1: + createScene1702(-1); + break; + case 2: + createScene1703(-1); + break; + case 3: + createScene1704(-1); + break; + default: + createScene1705(-1); + } + } else if (which == 0) { + createScene1701(-1); + } else if (which == 1) { + createScene1705(1); + } else { + createScene1705(3); + } + +} + +Module1700::~Module1700() { + // TODO Sound1ChList_sub_407A50(0x04212331); +} + +void Module1700::createScene1701(int which) { + SmackerScene *smackerScene; + _vm->gameState().sceneNum = 0; + // TODO Sound1ChList_setSoundValuesMulti(dword_4AE930, 0, 0, 0, 0, 0); + smackerScene = new SmackerScene(_vm, this, true, true, false); + smackerScene->setFileHash(0x3028A005); + smackerScene->nextVideo(); + _childObject = smackerScene; + SetUpdateHandler(&Module1700::updateScene1701); +} + +void Module1700::createScene1702(int which) { + _vm->gameState().sceneNum = 1; + _childObject = new NavigationScene(_vm, this, 0x004AE8B8, which, NULL); + SetUpdateHandler(&Module1700::updateScene1702); +} + +void Module1700::createScene1703(int which) { + _vm->gameState().sceneNum = 2; + _childObject = new NavigationScene(_vm, this, 0x004AE8E8, which, NULL); + SetUpdateHandler(&Module1700::updateScene1703); +} + +void Module1700::createScene1704(int which) { + SmackerScene *smackerScene; + _vm->gameState().sceneNum = 3; + // TODO Sound1ChList_setSoundValuesMulti(dword_4AE930, 0, 0, 0, 0, 0); + smackerScene = new SmackerScene(_vm, this, true, true, false); + smackerScene->setFileHash(0x01190041); + smackerScene->nextVideo(); + _childObject = smackerScene; + SetUpdateHandler(&Module1700::updateScene1701); +} + +void Module1700::createScene1705(int which) { + _vm->gameState().sceneNum = 4; + // TODO Sound1ChList_setSoundValuesMulti(dword_4AE930, 0, 0, 0, 0, 0); + // TODO Music18hList_play(0x31114225, 0, 2, 1); + _childObject = new Scene1705(_vm, this, which); + SetUpdateHandler(&Module1700::updateScene1705); +} + +void Module1700::updateScene1701() { + _childObject->handleUpdate(); + if (_done) { + _done = false; + delete _childObject; + _childObject = NULL; + if (_vm->gameState().sceneNum == 3) { + createScene1705(0); + _childObject->handleUpdate(); + } else { + // TODO Sound1ChList_setSoundValuesMulti(dword_4AE930, 1, 0, 0, 0); + createScene1702(0); + _childObject->handleUpdate(); + } + } +} + +void Module1700::updateScene1702() { + _childObject->handleUpdate(); + if (_done) { + _done = false; + delete _childObject; + _childObject = NULL; + if (_field20 == 0) { + createScene1703(0); + _childObject->handleUpdate(); + } else if (_field20 == 1) { + createScene1702(1); + _childObject->handleUpdate(); + } + } +} + +void Module1700::updateScene1703() { + _childObject->handleUpdate(); + if (_done) { + _done = false; + delete _childObject; + _childObject = NULL; + if (_field20 == 0) { + createScene1704(-1); + _childObject->handleUpdate(); + } else if (_field20 == 1) { + createScene1702(1); + _childObject->handleUpdate(); + } else if (_field20 == 2) { + if (!_soundResource.isPlaying()) { + // TODO _soundResource.setVolume(60); + _soundResource.play(0x58B45E58); + } + createScene1703(2); + _childObject->handleUpdate(); + } + } +} + +void Module1700::updateScene1705() { + _childObject->handleUpdate(); + if (_done) { + _done = false; + delete _childObject; + _childObject = NULL; + _parentModule->sendMessage(0x1009, 1, this); + } +} + +// Scene1705 + +static const uint32 kScene1705FileHashes[] = { + 0x910EA801, + 0x920EA801, + 0x940EA801, + 0x980EA801, + 0x800EA801, + 0xB00EA801, + 0xD00EA801, + 0x100EA801, + 0x900EA800, + 0xD10EA801, + 0x110EA801, + 0x910EA800 +}; + +Class602::Class602(NeverhoodEngine *vm, uint32 fileHash, int index) + : StaticSprite(vm, fileHash, 100) { + + _x = _spriteResource.getPosition().x + index * 30; + _y = _spriteResource.getPosition().y + 160; + StaticSprite::update(); +} + +Class606::Class606(NeverhoodEngine *vm, Scene *parentScene, int index, int surfacePriority, int16 x, int16 y, uint32 fileHash) + : StaticSprite(vm, fileHash, surfacePriority, x - 24, y - 4), _parentScene(parentScene), _index(index) { + + if (!getSubVar(0x02038314, _index) && !getSubVar(0x02720344, _index)) { + SetMessageHandler(&Class606::handleMessage); + } else { + _surface->setVisible(false); + SetMessageHandler(NULL); + } + _deltaRect = _drawRect; + _deltaRect.x -= 4; + _deltaRect.y -= 8; + _deltaRect.width += 8; + _deltaRect.height += 16; + Sprite::processDelta(); +} + +uint32 Class606::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + uint32 messageResult = Sprite::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x1011: + _parentScene->sendMessage(0x4826, 0, this); + messageResult = 1; + break; + case 0x4806: + setSubVar(0x02038314, _index, 1); + _surface->setVisible(false); + SetMessageHandler(NULL); + break; + } + return messageResult; +} + +Scene1705::Scene1705(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule, true), _paletteArea(1) { + + Palette2 *palette2; + Sprite *tempSprite; + + setGlobalVar(0xE7498218, 1); + // TODO _vm->initVarsScene1705(); + + SetMessageHandler(&Scene1705::handleMessage); + SetUpdateHandler(&Scene1705::update); + + _vm->_collisionMan->setHitRects(0x004B69D8); + + _surfaceFlag = true; + + _background = addBackground(new DirtyBackground(_vm, 0x03118226, 0, 0)); + + palette2 = new Palette2(_vm, 0x03118226); + palette2->addPalette(0x91D3A391, 0, 64, 0); + palette2->copyBasePalette(0, 256, 0); + palette2->usePalette(); + _palette = palette2; + addEntity(_palette); + + _mouseCursor = addSprite(new Mouse433(_vm, 0x18222039, NULL)); + + addSprite(new Class602(_vm, kScene1705FileHashes[getSubVar(0x0A4C0A9A, 0)], 0)); + addSprite(new Class602(_vm, kScene1705FileHashes[getSubVar(0x0A4C0A9A, 1)], 1)); + addSprite(new Class602(_vm, kScene1705FileHashes[getSubVar(0x0A4C0A9A, 2)], 2)); + + _sprite = addSprite(new StaticSprite(_vm, 0x31313A22, 1100)); + + _class606 = addSprite(new Class606(_vm, this, 15, 1100, 238, 439, 0x02363852)); + _vm->_collisionMan->addSprite(_class606); + + which = 4; + + if (which < 0) { + _klayman = new KmScene1705(_vm, this, 231, 434); + setMessageList(0x004B69E8); + sendMessage(0x2000, 0, this); + _klayman->getSurface()->getClipRect().x1 = 0; + _klayman->getSurface()->getClipRect().y1 = 0; + _klayman->getSurface()->getClipRect().x2 = _sprite->getSurface()->getDrawRect().x + _sprite->getSurface()->getDrawRect().width; + _klayman->getSurface()->getClipRect().y2 = 480; + } else if (which == 1) { + _klayman = new KmScene1705(_vm, this, 431, 434); + _klayman->sendMessage(0x2000, 1, this); + setMessageList(0x004B6A08); + sendMessage(0x2000, 1, this); + _klayman->getSurface()->getClipRect().x1 = 0; + _klayman->getSurface()->getClipRect().y1 = 0; + _klayman->getSurface()->getClipRect().x2 = _sprite->getSurface()->getDrawRect().x + _sprite->getSurface()->getDrawRect().width; + _klayman->getSurface()->getClipRect().y2 = 480; + } else if (which == 2) { + _klayman = new KmScene1705(_vm, this, 431, 434); + _klayman->sendMessage(0x2000, 1, this); + setMessageList(0x004B6AA0); + sendMessage(0x2000, 1, this); + _klayman->getSurface()->getClipRect().x1 = 0; + _klayman->getSurface()->getClipRect().y1 = 0; + _klayman->getSurface()->getClipRect().x2 = _sprite->getSurface()->getDrawRect().x + _sprite->getSurface()->getDrawRect().width; + _klayman->getSurface()->getClipRect().y2 = 480; + } else if (which == 3) { + _klayman = new KmScene1705(_vm, this, 431, 434); + _klayman->sendMessage(0x2000, 1, this); + setMessageList(0x004B6A18); + sendMessage(0x2000, 1, this); + _klayman->getSurface()->getClipRect().x1 = 0; + _klayman->getSurface()->getClipRect().y1 = 0; + _klayman->getSurface()->getClipRect().x2 = _sprite->getSurface()->getDrawRect().x + _sprite->getSurface()->getDrawRect().width; + _klayman->getSurface()->getClipRect().y2 = 480; + } else { + _klayman = new KmScene1705(_vm, this, 231, 74); + _klayman->sendMessage(0x2000, 0, this); + setMessageList(0x004B69F0); + sendMessage(0x2000, 0, this); + tempSprite = addSprite(new StaticSprite(_vm, 0x30303822, 1100)); + _klayman->getSurface()->getClipRect().x1 = 0; + _klayman->getSurface()->getClipRect().y1 = tempSprite->getSurface()->getDrawRect().y; + _klayman->getSurface()->getClipRect().x2 = _sprite->getSurface()->getDrawRect().x + _sprite->getSurface()->getDrawRect().width; + _klayman->getSurface()->getClipRect().y2 = 480; + } + + addSprite(_klayman); + +} + +void Scene1705::update() { + Scene::update(); + if (_klayman->getX() < 224 && _paletteArea != 0) { + ((Palette2*)_palette)->addPalette(0xF2210C15, 0, 64, 0); + ((Palette2*)_palette)->startFadeToPalette(12); + _paletteArea = 0; + } else if (_klayman->getX() >= 224 && _paletteArea == 0) { + ((Palette2*)_palette)->addPalette(0x91D3A391, 0, 64, 0); + ((Palette2*)_palette)->startFadeToPalette(12); + _paletteArea = 1; + } +} + +uint32 Scene1705::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x2000: + if (param.asInteger()) { + setRectList(0x004B6B40); + _klayman->setKlaymanTable3(); + } else { + setRectList(0x004B6B30); + _klayman->setKlaymanTable1(); + } + break; + case 0x4826: + if (sender == _class606 && _klayman->getX() <= 318) { + _klayman->sendEntityMessage(0x1014, sender, this); + setMessageList(0x004B6AC0); + } + break; + } + return 0; +} + +} // End of namespace Neverhood diff --git a/engines/neverhood/module1700.h b/engines/neverhood/module1700.h new file mode 100644 index 0000000000..0fefa72122 --- /dev/null +++ b/engines/neverhood/module1700.h @@ -0,0 +1,80 @@ +/* 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_MODULE1700_H +#define NEVERHOOD_MODULE1700_H + +#include "neverhood/neverhood.h" +#include "neverhood/module.h" +#include "neverhood/scene.h" +#include "neverhood/smackerscene.h" + +namespace Neverhood { + +class Module1700 : public Module { +public: + Module1700(NeverhoodEngine *vm, Module *parentModule, int which); + virtual ~Module1700(); +protected: + SoundResource _soundResource; + void update(); + void createScene1701(int which); + void createScene1702(int which); + void createScene1703(int which); + void createScene1704(int which); + void createScene1705(int which); + void updateScene1701(); + void updateScene1702(); + void updateScene1703(); + void updateScene1705(); +}; + +// Scene1705 + +class Class602 : public StaticSprite { +public: + Class602(NeverhoodEngine *vm, uint32 fileHash, int index); +}; + +class Class606 : public StaticSprite { +public: + Class606(NeverhoodEngine *vm, Scene *parentScene, int index, int surfacePriority, int16 x, int16 y, uint32 fileHash); +protected: + Scene *_parentScene; + int _index; + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +class Scene1705 : public Scene { +public: + Scene1705(NeverhoodEngine *vm, Module *parentModule, int which); +protected: + Sprite *_sprite; + Sprite *_class606; + int _paletteArea; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); +}; + +} // End of namespace Neverhood + +#endif /* NEVERHOOD_MODULE1700_H */ diff --git a/engines/neverhood/module1800.cpp b/engines/neverhood/module1800.cpp new file mode 100644 index 0000000000..2a4d89cead --- /dev/null +++ b/engines/neverhood/module1800.cpp @@ -0,0 +1,300 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "neverhood/module1800.h" +#include "neverhood/navigationscene.h" +#include "neverhood/smackerscene.h" + +#include "neverhood/diskplayerscene.h" + +namespace Neverhood { + +Module1800::Module1800(NeverhoodEngine *vm, Module *parentModule, int which) + : Module(vm, parentModule) { + + debug("Create Module1800(%d)", which); + + // TODO Sound1ChList_addSoundResources(0x04A14718, dword_4AFE70); + // TODO Sound1ChList_setSoundValuesMulti(dword_4AFE70, 1, 50, 600, 10, 150); + // TODO Sound1ChList_sub_407C70(0x04A14718, 0x8A382B55, 0x0C242F1D, 0); + + if (which < 0) { + switch (_vm->gameState().sceneNum) { + case 0: + createScene1801(-1); + break; + case 1: + createScene1802(-1); + break; + case 2: + createScene1803(-1); + break; + default: + case 3: + createScene1804(-1); + break; + case 4: + createScene1805(-1); + break; + case 5: + createScene1806(-1); + break; + case 6: + createScene1807(-1); + break; + case 7: + createScene1808(-1); + break; + case 8: + createScene1809(-1); + break; + } + } else if (which == 2) { + createScene1806(0); + } else if (which == 3) { + createScene1801(0); + } else { + createScene1804(1); + } + +} + +Module1800::~Module1800() { + // TODO Sound1ChList_sub_407A50(0x04A14718); +} + +void Module1800::createScene1801(int which) { + static const byte kNavigationTypes[] = {1, 0, 2, 0}; + _vm->gameState().sceneNum = 0; +#if 0 + _childObject = new NavigationScene(_vm, this, 0x004AFD38, which, kNavigationTypes); +#endif + _childObject = new DiskplayerScene(_vm, this, 3); + SetUpdateHandler(&Module1800::updateScene1801); +} + +void Module1800::createScene1802(int which) { + static const byte kNavigationTypes[] = {5}; + _vm->gameState().sceneNum = 1; + _childObject = new NavigationScene(_vm, this, 0x004AFD98, which, kNavigationTypes); + SetUpdateHandler(&Module1800::updateScene1802); +} + +void Module1800::createScene1803(int which) { + SmackerScene *smackerScene; + _vm->gameState().sceneNum = 2; + smackerScene = new SmackerScene(_vm, this, true, true, false); + smackerScene->setFileHash(0x006C0085); + smackerScene->nextVideo(); + _childObject = smackerScene; + SetUpdateHandler(&Module1800::updateScene1803); +} + +void Module1800::createScene1804(int which) { + _vm->gameState().sceneNum = 3; + _childObject = new NavigationScene(_vm, this, 0x004AFDB0, which, NULL); + SetUpdateHandler(&Module1800::updateScene1804); +} + +void Module1800::createScene1804b(int which) { + SmackerScene *smackerScene; + _vm->gameState().sceneNum = 3; + smackerScene = new SmackerScene(_vm, this, true, true, false); + smackerScene->setFileHash(0x0A840C01); + smackerScene->nextVideo(); + _childObject = smackerScene; + SetUpdateHandler(&Module1800::updateScene1803); +} + +void Module1800::createScene1805(int which) { + _vm->gameState().sceneNum = 4; + _childObject = new NavigationScene(_vm, this, 0x004AFDE0, which, NULL); + SetUpdateHandler(&Module1800::updateScene1805); +} + +void Module1800::createScene1806(int which) { + _vm->gameState().sceneNum = 5; + _childObject = new NavigationScene(_vm, this, 0x004AFE40, which, NULL); + SetUpdateHandler(&Module1800::updateScene1806); +} + +void Module1800::createScene1807(int which) { + SmackerScene *smackerScene; + _vm->gameState().sceneNum = 6; + smackerScene = new SmackerScene(_vm, this, true, true, false); + smackerScene->setFileHash(0x08D84010); + smackerScene->nextVideo(); + _childObject = smackerScene; + SetUpdateHandler(&Module1800::updateScene1803); + // TODO Sound1ChList_sub_407A50(0x04A14718); +} + +void Module1800::createScene1808(int which) { + SmackerScene *smackerScene; + _vm->gameState().sceneNum = 7; + // TODO Sound1ChList_setSoundValuesMulti(dword_4AFE70, 0, 0, 0, 0, 0); + smackerScene = new SmackerScene(_vm, this, true, true, false); + smackerScene->setFileHash(0x0168B121); + smackerScene->nextVideo(); + _childObject = smackerScene; + SetUpdateHandler(&Module1800::updateScene1803); +} + +void Module1800::createScene1809(int which) { +#if 0 // TODO + _vm->gameState().sceneNum = 8; + _childObject = new CreditsScene(_vm, this, 0); + SetUpdateHandler(&Module1800::updateScene1809); +#endif +} + +void Module1800::updateScene1801() { + _childObject->handleUpdate(); +#if 0 // TODO + NavigationScene *navigationScene = (NavigationScene*)_childObject; + if (navigationScene->soundFlag1 && navigationScene->index == 2) { + // TODO Sound1ChList_sub_4080B0(false); + } +#endif + if (_done) { + _done = false; + delete _childObject; + _childObject = NULL; + if (_field20 == 1) { + createScene1805(0); + _childObject->handleUpdate(); + } else if (_field20 == 2) { + createScene1802(-1); + _childObject->handleUpdate(); + } else if (_field20 == 3) { + createScene1804(0); + _childObject->handleUpdate(); + } + } +} + +void Module1800::updateScene1802() { + _childObject->handleUpdate(); + if (_done) { + int areaType = ((NavigationScene*)_childObject)->getNavigationAreaType(); + _done = false; + delete _childObject; + _childObject = NULL; + if (areaType == 3) { + createScene1808(-1); + } else { + createScene1803(-1); + } + _childObject->handleUpdate(); + } +} + +void Module1800::updateScene1803() { + _childObject->handleUpdate(); + if (_done) { + _done = false; + delete _childObject; + _childObject = NULL; + if (_field20 == 2) { + createScene1801(2); + _childObject->handleUpdate(); + } else if (_field20 == 3) { + _parentModule->sendMessage(0x1009, 0, this); + } else if (_field20 == 6) { + createScene1809(-1); + _childObject->handleUpdate(); + } else if (_field20 == 7) { + _parentModule->sendMessage(0x1009, 3, this); + } + } +} + +void Module1800::updateScene1804() { + _childObject->handleUpdate(); + if (_done) { + _done = false; + delete _childObject; + _childObject = NULL; + if (_field20 == 0) { + createScene1804b(-1); + _childObject->handleUpdate(); + } else if (_field20 == 1) { + createScene1801(1); + _childObject->handleUpdate(); + } + } +} + +void Module1800::updateScene1805() { + _childObject->handleUpdate(); + if (_done) { + _done = false; + delete _childObject; + _childObject = NULL; + if (_field20 == 0) { + createScene1807(-1); + _childObject->handleUpdate(); + } else if (_field20 == 1) { + createScene1806(0); + _childObject->handleUpdate(); + } else if (_field20 == 2) { + createScene1801(3); + _childObject->handleUpdate(); + } else if (_field20 == 3) { + createScene1805(3); + _childObject->handleUpdate(); + } + } +} + +void Module1800::updateScene1806() { + _childObject->handleUpdate(); + if (_done) { + _done = false; + delete _childObject; + _childObject = NULL; + if (_field20 == 0) { + _parentModule->sendMessage(0x1009, 2, this); + } else if (_field20 == 1) { + createScene1805(3); + _childObject->handleUpdate(); + } + } + if (_field24 >= 0) { + if (_field24 == 1) { + // TODO _resourceTable.setResourceList(ex_sub_42EDA0(0), true); + } + _field24 = -1; + } +} + +void Module1800::updateScene1809() { + _childObject->handleUpdate(); + if (_done) { + _done = false; + delete _childObject; + _childObject = NULL; + _parentModule->sendMessage(0x1009, 1, this); + // TODO GameState stuff + } +} +} // End of namespace Neverhood diff --git a/engines/neverhood/module1800.h b/engines/neverhood/module1800.h new file mode 100644 index 0000000000..13d4790a8c --- /dev/null +++ b/engines/neverhood/module1800.h @@ -0,0 +1,63 @@ +/* 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_MODULE1800_H +#define NEVERHOOD_MODULE1800_H + +#include "neverhood/neverhood.h" +#include "neverhood/module.h" +#include "neverhood/scene.h" + +namespace Neverhood { + +// Module1800 + +class Module1800 : public Module { +public: + Module1800(NeverhoodEngine *vm, Module *parentModule, int which); + virtual ~Module1800(); +protected: + // TODO ResourceTable _resourceTable; + void createScene1801(int which); + void createScene1802(int which); + void createScene1803(int which); + void createScene1804(int which); + void createScene1804b(int which); + void createScene1805(int which); + void createScene1806(int which); + void createScene1807(int which); + void createScene1808(int which); + void createScene1809(int which); + void updateScene1801(); + void updateScene1802(); + void updateScene1803(); + void updateScene1804(); + void updateScene1805(); + void updateScene1806(); + void updateScene1807(); + void updateScene1808(); + void updateScene1809(); +}; + +} // End of namespace Neverhood + +#endif /* NEVERHOOD_MODULE1800_H */ diff --git a/engines/neverhood/navigationscene.cpp b/engines/neverhood/navigationscene.cpp index f6be668b3c..7bc1551250 100644 --- a/engines/neverhood/navigationscene.cpp +++ b/engines/neverhood/navigationscene.cpp @@ -25,7 +25,7 @@ namespace Neverhood { -NavigationScene::NavigationScene(NeverhoodEngine *vm, Module *parentModule, uint32 navigationListId, int navigationIndex, byte *itemsTypes) +NavigationScene::NavigationScene(NeverhoodEngine *vm, Module *parentModule, uint32 navigationListId, int navigationIndex, const byte *itemsTypes) : Scene(vm, parentModule, true), _itemsTypes(itemsTypes), _navigationIndex(navigationIndex), _smackerDone(false), _soundFlag1(false), _soundFlag2(false), _smackerFileHash(0), _interactive(true), _done(false) { @@ -64,8 +64,11 @@ NavigationScene::~NavigationScene() { // TODO Sound1ChList_sub_408110(0); } -byte NavigationScene::getNavigationAreaType() { - return 0; // TODO +int NavigationScene::getNavigationAreaType() { + NPoint mousePos; + mousePos.x = _mouseCursor->getX(); + mousePos.y = _mouseCursor->getY(); + return _mouseCursor->sendPointMessage(0x2064, mousePos, this); } void NavigationScene::update() { diff --git a/engines/neverhood/navigationscene.h b/engines/neverhood/navigationscene.h index 08aefb7cc4..c37a7fc178 100644 --- a/engines/neverhood/navigationscene.h +++ b/engines/neverhood/navigationscene.h @@ -31,9 +31,9 @@ namespace Neverhood { class NavigationScene : public Scene { public: - NavigationScene(NeverhoodEngine *vm, Module *parentModule, uint32 navigationListId, int navigationIndex, byte *itemsTypes); + NavigationScene(NeverhoodEngine *vm, Module *parentModule, uint32 navigationListId, int navigationIndex, const byte *itemsTypes); virtual ~NavigationScene(); - byte getNavigationAreaType(); + int getNavigationAreaType(); protected: SmackerPlayer *_smackerPlayer; bool _smackerDone; @@ -44,7 +44,7 @@ protected: bool _soundFlag1; bool _soundFlag2; bool _done; - byte *_itemsTypes; + const byte *_itemsTypes; void update(); uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); void createMouseCursor(); diff --git a/engines/neverhood/palette.cpp b/engines/neverhood/palette.cpp index e186d3814f..28fa81b87a 100644 --- a/engines/neverhood/palette.cpp +++ b/engines/neverhood/palette.cpp @@ -160,7 +160,6 @@ void Palette2::update() { if (_status == 1) { Palette::update(); } else if (_status == 2) { - debug("... _palCounter = %d", _palCounter); if (_palCounter > 1) { for (int i = 0; i < 256; i++) { fadeColor(_palette + i * 4, _basePalette[i * 4 + 0], _basePalette[i * 4 + 1], _basePalette[i * 4 + 2]); @@ -174,6 +173,12 @@ void Palette2::update() { } } +void Palette2::copyBasePalette(int toIndex, int count, int fromIndex) { + if (toIndex + count > 256) + count = 256 - toIndex; + memcpy(_basePalette + toIndex * 4, _palette + fromIndex * 4, count * 4); +} + void Palette2::addPalette(uint32 fileHash, int toIndex, int count, int fromIndex) { PaletteResource paletteResource(_vm); if (toIndex + count > 256) diff --git a/engines/neverhood/palette.h b/engines/neverhood/palette.h index e3d95aa7f6..01f63e8e7e 100644 --- a/engines/neverhood/palette.h +++ b/engines/neverhood/palette.h @@ -38,7 +38,7 @@ public: Palette(NeverhoodEngine *vm, const char *filename); // Create from resource with fileHash Palette(NeverhoodEngine *vm, uint32 fileHash); - ~Palette(); + virtual ~Palette(); void usePalette(); void addPalette(const char *filename, int toIndex, int count, int fromIndex); void addPalette(uint32 fileHash, int toIndex, int count, int fromIndex); @@ -60,7 +60,8 @@ public: Palette2(NeverhoodEngine *vm); // TODO: Other ctors Palette2(NeverhoodEngine *vm, uint32 fileHash); - ~Palette2(); + virtual ~Palette2(); + void copyBasePalette(int toIndex, int count, int fromIndex); void addPalette(uint32 fileHash, int toIndex, int count, int fromIndex); void startFadeToPalette(int counter); public: diff --git a/engines/neverhood/resource.cpp b/engines/neverhood/resource.cpp index 44fef14ebe..39824de7f9 100644 --- a/engines/neverhood/resource.cpp +++ b/engines/neverhood/resource.cpp @@ -313,6 +313,21 @@ void AnimResource::setRepl(byte oldColor, byte newColor) { _replNewColor = newColor; } +NDimensions AnimResource::loadSpriteDimensions(uint32 fileHash) { + NDimensions dimensions; + byte *resDimensions = _vm->_res->getResourceExtDataByHash(fileHash); + if (resDimensions) { + dimensions.width = READ_LE_UINT16(resDimensions + 0); + dimensions.height = READ_LE_UINT16(resDimensions + 2); + } else { + dimensions.width = 0; + dimensions.height = 0; + } + return dimensions; +} + +// MouseCursorResource + MouseCursorResource::MouseCursorResource(NeverhoodEngine *vm) : _cursorSprite(vm), _cursorNum(4), _currFileHash(0) { diff --git a/engines/neverhood/resource.h b/engines/neverhood/resource.h index 5d8d5ca13d..a7d5e6c761 100644 --- a/engines/neverhood/resource.h +++ b/engines/neverhood/resource.h @@ -91,6 +91,7 @@ public: int16 getFrameIndex(uint32 frameHash); void setReplEnabled(bool value) { _replEnabled = value; } void setRepl(byte oldColor, byte newColor); + NDimensions loadSpriteDimensions(uint32 fileHash); protected: NeverhoodEngine *_vm; int _resourceHandle; diff --git a/engines/neverhood/resourceman.cpp b/engines/neverhood/resourceman.cpp index 28f0994cb1..0538f58e87 100644 --- a/engines/neverhood/resourceman.cpp +++ b/engines/neverhood/resourceman.cpp @@ -135,8 +135,8 @@ byte *ResourceMan::getResourceExtData(int resourceHandle) { } byte *ResourceMan::getResourceExtDataByHash(uint32 fileHash) { - ResourceFileEntry *entry = findEntry(fileHash); - return _archives[entry->archiveIndex]->getEntryExtData(entry->entryIndex); + ResourceFileEntry *entry = findEntrySimple(fileHash); + return entry ? _archives[entry->archiveIndex]->getEntryExtData(entry->entryIndex) : NULL; } byte *ResourceMan::loadResource(int resourceHandle, bool moveToFront) { diff --git a/engines/neverhood/scene.cpp b/engines/neverhood/scene.cpp index 43f1ca79bc..d725cedb99 100644 --- a/engines/neverhood/scene.cpp +++ b/engines/neverhood/scene.cpp @@ -88,14 +88,16 @@ void Scene::draw() { if (_smackerPlayer->getSurface()) _smackerPlayer->getSurface()->draw(); } else { +#if 0 if (_surfaceFlag) { // TODO g_screen->copyDirtyRects(); for (Common::Array<BaseSurface*>::iterator iter = _surfaces.begin(); iter != _surfaces.end(); iter++) (*iter)->addDirtyRect(); // TODO g_screen->addDirtyRects(); } +#endif for (Common::Array<BaseSurface*>::iterator iter = _surfaces.begin(); iter != _surfaces.end(); iter++) { - debug(4, "priority = %d", (*iter)->getPriority()); + //debug(4, "priority = %d", (*iter)->getPriority()); (*iter)->draw(); } } @@ -501,6 +503,11 @@ void Scene::setRectList(RectList *rectList) { _rectType = 1; } +void Scene::clearRectList() { + _rectList = NULL; + _rectType = 1; +} + void Scene::loadDataResource(uint32 fileHash) { _dataResource.load(fileHash); if (_klayman) diff --git a/engines/neverhood/scene.h b/engines/neverhood/scene.h index 47114053b0..65326c310f 100644 --- a/engines/neverhood/scene.h +++ b/engines/neverhood/scene.h @@ -50,6 +50,7 @@ public: void setSurfacePriority(BaseSurface *surface, int priority); void deleteSprite(Sprite **sprite); Background *addBackground(Background *background); + void update(); protected: Module *_parentModule; Common::Array<Entity*> _entities; @@ -89,7 +90,6 @@ protected: bool _prevVisible; int _messageValue; // TODO 000000CF field_CF db ? - void update(); uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); void smackerUpdate(); uint32 smackerHandleMessage(int messageNum, const MessageParam ¶m, Entity *sender); @@ -102,6 +102,7 @@ protected: void runMessageList(); void setRectList(uint32 id); void setRectList(RectList *rectList); + void clearRectList(); void messageList402220(); void loadDataResource(uint32 fileHash); }; diff --git a/engines/neverhood/smackerplayer.cpp b/engines/neverhood/smackerplayer.cpp index f0b30084cc..66e7a58746 100644 --- a/engines/neverhood/smackerplayer.cpp +++ b/engines/neverhood/smackerplayer.cpp @@ -69,12 +69,10 @@ void SmackerDoubleSurface::draw() { SmackerPlayer::SmackerPlayer(NeverhoodEngine *vm, Scene *scene, uint32 fileHash, bool doubleSurface, bool flag) : Entity(vm, 0), _scene(scene), _doubleSurface(doubleSurface), _dirtyFlag(false), _flag2(false), - _palette(NULL), _smackerDecoder(NULL), _smackerSurface(NULL), _stream(NULL), _smackerFirst(true) { - - debug("_smackerSurface = %p", (void*)_smackerSurface); + _palette(NULL), _smackerDecoder(NULL), _smackerSurface(NULL), _stream(NULL), _smackerFirst(true), + _drawX(-1), _drawY(-1) { SetUpdateHandler(&SmackerPlayer::update); - open(fileHash, flag); } @@ -121,14 +119,31 @@ void SmackerPlayer::close() { } void SmackerPlayer::gotoFrame(uint frameNumber) { + // TODO? +} + +uint32 SmackerPlayer::getFrameCount() { + return _smackerDecoder ? _smackerDecoder->getFrameCount() : 0; +} + +uint32 SmackerPlayer::getFrameNumber() { + return _smackerDecoder ? _smackerDecoder->getCurFrame() : 0; } uint SmackerPlayer::getStatus() { return 0; } -void SmackerPlayer::update() { +void SmackerPlayer::setDrawPos(int16 x, int16 y) { + _drawX = x; + _drawY = y; + if (_smackerSurface) { + _smackerSurface->getDrawRect().x = _drawX; + _smackerSurface->getDrawRect().y = _drawY; + } +} +void SmackerPlayer::update() { debug(8, "SmackerPlayer::update()"); if (!_smackerDecoder) @@ -144,15 +159,18 @@ void SmackerPlayer::update() { const Graphics::Surface *smackerFrame = _smackerDecoder->decodeNextFrame(); if (_smackerFirst) { - if (_doubleSurface) { - _smackerSurface->getDrawRect().x = 320 - _smackerDecoder->getWidth(); - _smackerSurface->getDrawRect().y = 240 - _smackerDecoder->getHeight(); - _smackerSurface->setSmackerFrame(smackerFrame); - } else { - _smackerSurface->getDrawRect().x = (640 - _smackerDecoder->getWidth()) / 2; - _smackerSurface->getDrawRect().y = (480 - _smackerDecoder->getHeight()) / 2; - _smackerSurface->setSmackerFrame(smackerFrame); + _smackerSurface->setSmackerFrame(smackerFrame); + if (_drawX < 0 || _drawY < 0) { + if (_doubleSurface) { + _drawX = 320 - _smackerDecoder->getWidth(); + _drawY = 240 - _smackerDecoder->getHeight(); + } else { + _drawX = (640 - _smackerDecoder->getWidth()) / 2; + _drawY = (480 - _smackerDecoder->getHeight()) / 2; + } } + _smackerSurface->getDrawRect().x = _drawX; + _smackerSurface->getDrawRect().y = _drawY; _smackerFirst = false; } @@ -164,7 +182,6 @@ void SmackerPlayer::update() { _dirtyFlag = true; if (_smackerDecoder->hasDirtyPalette()) { - debug("updatePalette()"); updatePalette(); } @@ -179,7 +196,6 @@ void SmackerPlayer::update() { } } - } void SmackerPlayer::updatePalette() { diff --git a/engines/neverhood/smackerplayer.h b/engines/neverhood/smackerplayer.h index 2262277956..6579bb4add 100644 --- a/engines/neverhood/smackerplayer.h +++ b/engines/neverhood/smackerplayer.h @@ -55,7 +55,10 @@ public: void open(uint32 fileHash, bool keepLastFrame); void close(); void gotoFrame(uint frameNumber); + uint32 getFrameCount(); + uint32 getFrameNumber(); uint getStatus(); + void setDrawPos(int16 x, int16 y); protected: Scene *_scene; Palette *_palette; @@ -67,6 +70,7 @@ protected: bool _keepLastFrame; bool _flag2; bool _dirtyFlag; + int _drawX, _drawY; void update(); void updatePalette(); }; diff --git a/engines/neverhood/sprite.cpp b/engines/neverhood/sprite.cpp index d0a6628d75..ee6e7aa942 100644 --- a/engines/neverhood/sprite.cpp +++ b/engines/neverhood/sprite.cpp @@ -93,6 +93,11 @@ void Sprite::createSurface(int surfacePriority, int16 width, int16 height) { _surface = new BaseSurface(_vm, surfacePriority, width, height); } +int16 Sprite::defFilterY(int16 y) { + // TODO return y - g_screen->field_26; + return y; +} + // StaticSprite StaticSprite::StaticSprite(NeverhoodEngine *vm, int objectPriority) @@ -209,7 +214,6 @@ AnimatedSprite::AnimatedSprite(NeverhoodEngine *vm, uint32 fileHash, int surface _x = x; _y = y; setFileHash(fileHash, 0, -1); - } void AnimatedSprite::init() { @@ -428,10 +432,7 @@ void AnimatedSprite::updateFrameInfo() { } void AnimatedSprite::createSurface1(uint32 fileHash, int surfacePriority) { - NDimensions dimensions; - // TODO dimensions = getAnimatedSpriteDimensions(fileHash); - dimensions.width = 640; - dimensions.height = 480; + NDimensions dimensions = _animResource.loadSpriteDimensions(fileHash); _surface = new BaseSurface(_vm, surfacePriority, dimensions.width, dimensions.height); } diff --git a/engines/neverhood/sprite.h b/engines/neverhood/sprite.h index 18c9ae32da..86165f3440 100644 --- a/engines/neverhood/sprite.h +++ b/engines/neverhood/sprite.h @@ -48,12 +48,15 @@ public: bool checkCollision(NRect &rect); int16 getX() const { return _x; } int16 getY() const { return _y; } + void setX(int16 value) { _x = value; } + void setY(int16 value) { _y = value; } uint16 getFlags() const { return _flags; } bool isDoDeltaX() const { return _doDeltaX; } bool isDoDeltaY() const { return _doDeltaY; } NRect& getRect() { return _rect; } uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); void loadDataResource(uint32 fileHash); + int16 defFilterY(int16 y); protected: void (Sprite::*_spriteUpdateCb)(); Common::String _spriteUpdateCbName; // For debugging purposes @@ -71,7 +74,6 @@ protected: uint16 _flags; //0000004A field4A dw ? // seems to be unused except in ctor DataResource _dataResource; - //void update(); void createSurface(int surfacePriority, int16 width, int16 height); void handleSpriteUpdate() { if (_spriteUpdateCb) @@ -91,10 +93,10 @@ public: StaticSprite(NeverhoodEngine *vm, const char *filename, int surfacePriority, int16 x = kDefPosition, int16 y = kDefPosition, int16 width = 0, int16 height = 0); StaticSprite(NeverhoodEngine *vm, uint32 fileHash, int surfacePriority, int16 x = kDefPosition, int16 y = kDefPosition, int16 width = 0, int16 height = 0); void load(uint32 fileHash, bool dimensions, bool position); + void update(); protected: SpriteResource _spriteResource; void init(uint32 fileHash, int surfacePriority, int16 x, int16 y, int16 width, int16 height); - void update(); }; #define SetAnimationCallback1(callback) _callback1Cb = static_cast <void (AnimatedSprite::*)(void)> (callback); debug("SetAnimationCallback1(" #callback ")"); _callback1CbName = #callback |