From b8d939a94b364a8d992a5053b527a822babccd37 Mon Sep 17 00:00:00 2001 From: johndoe123 Date: Fri, 12 Oct 2012 19:19:24 +0000 Subject: NEVERHOOD: Implement Scene2802 (radio tuning scene) - Handle mouse button up events - Use the SmackerDecoder's rewind - Implement SmackerPlayer::gotoFrame (slow but better than nothing) --- engines/neverhood/gamemodule.cpp | 39 ++++++- engines/neverhood/gamemodule.h | 2 + engines/neverhood/module2800.cpp | 215 ++++++++++++++++++++++++++++++++++-- engines/neverhood/module2800.h | 22 +++- engines/neverhood/neverhood.cpp | 4 + engines/neverhood/smackerplayer.cpp | 60 +++++----- engines/neverhood/smackerplayer.h | 5 +- 7 files changed, 304 insertions(+), 43 deletions(-) diff --git a/engines/neverhood/gamemodule.cpp b/engines/neverhood/gamemodule.cpp index 0c2e0907a7..a85d8a90e5 100644 --- a/engines/neverhood/gamemodule.cpp +++ b/engines/neverhood/gamemodule.cpp @@ -46,6 +46,27 @@ namespace Neverhood { +static const uint32 kScene2801MusicFileHashes[] = { + 0x82B22000, + 0x02B22004, + 0x42B22000, + 0x03322008, + 0x02B22001, + 0x02B22008, + 0x02B22020, + 0x03322001, + 0x03322002, + 0x03322004, + 0x03322040, + 0x02B22002, + 0x02B22010, + 0x03322010, + 0x02B22040, + 0x43322000, + 0x83322000, + 0x03322020 +}; + GameModule::GameModule(NeverhoodEngine *vm) : Module(vm, NULL), _moduleNum(-1) { @@ -85,6 +106,16 @@ void GameModule::handleMouseDown(int16 x, int16 y) { } } +void GameModule::handleMouseUp(int16 x, int16 y) { + if (_childObject) { + NPoint mousePos; + mousePos.x = x; + mousePos.y = y; + debug(2, "GameModule::handleMouseUp(%d, %d)", x, y); + sendPointMessage(_childObject, 2, mousePos); + } +} + void GameModule::handleSpaceKey() { if (_childObject) { debug(2, "GameModule::handleSpaceKey()"); @@ -279,6 +310,12 @@ void GameModule::initScene3009Vars() { } } +uint32 GameModule::getScene2802MusicFileHash() { + uint musicNum = getGlobalVar(0x08CC0828); + return (musicNum % 5 != 0) ? 0 : kScene2801MusicFileHashes[CLIP(musicNum / 5, 0, 17)]; +} + + uint32 GameModule::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { uint32 messageResult = Module::handleMessage(messageNum, param, sender); switch (messageNum) { @@ -321,7 +358,7 @@ void GameModule::startup() { #if 1 _vm->gameState().which = 0; _vm->gameState().sceneNum = 1; - createModule(3000, -1); + createModule(2800, -1); #endif #if 0 _vm->gameState().sceneNum = 0; diff --git a/engines/neverhood/gamemodule.h b/engines/neverhood/gamemodule.h index 7031bbbe16..82e6fa57c8 100644 --- a/engines/neverhood/gamemodule.h +++ b/engines/neverhood/gamemodule.h @@ -37,6 +37,7 @@ public: void startup(); void handleMouseMove(int16 x, int16 y); void handleMouseDown(int16 x, int16 y); + void handleMouseUp(int16 x, int16 y); void handleSpaceKey(); void initScene1307Vars(); void initScene1405Vars(); @@ -44,6 +45,7 @@ public: void initScene2808Vars1(); void initScene2808Vars2(); void initScene3009Vars(); + uint32 getScene2802MusicFileHash(); protected: Entity *_prevChildObject; bool _someFlag1; diff --git a/engines/neverhood/module2800.cpp b/engines/neverhood/module2800.cpp index 4232b794df..1a51571fa3 100644 --- a/engines/neverhood/module2800.cpp +++ b/engines/neverhood/module2800.cpp @@ -31,9 +31,9 @@ namespace Neverhood { Module2800::Module2800(NeverhoodEngine *vm, Module *parentModule, int which) - : Module(vm, parentModule) { + : Module(vm, parentModule), _musicResource(NULL) { - _fileHash = 0; + _currentMusicFileHash = 0; // TODO music stuff _vm->_soundMan->addMusic(0x64210814, 0xD2FA4D14); setGlobalVar(0x28D8C940, 1); @@ -51,7 +51,10 @@ Module2800::Module2800(NeverhoodEngine *vm, Module *parentModule, int which) } Module2800::~Module2800() { - // TODO music stuff + if (_musicResource) { + _musicResource->unload(); + delete _musicResource; + } _vm->_soundMan->deleteGroup(0x64210814); } @@ -65,6 +68,11 @@ void Module2800::createScene(int sceneNum, int which) { break; case 1: _vm->_soundMan->stopMusic(0xD2FA4D14, 0, 0); + + // TODO!! + + _childObject = new Scene2802(_vm, this, which); + #if 0 _flag = true; // DEBUG! if (_flag) { @@ -180,10 +188,10 @@ void Module2800::createScene(int sceneNum, int which) { _vm->_soundMan->startMusic(0xD2FA4D14, 0, 2); _childObject = new DiskplayerScene(_vm, this, 4); break; - // case 1001: + _vm->_soundMan->stopMusic(0xD2FA4D14, 0, 0); + createSmackerScene(0x00800801, true, true, false); break; - // TODO ... } SetUpdateHandler(&Module2800::updateScene); _childObject->handleUpdate(); @@ -351,22 +359,51 @@ void Module2800::updateScene() { case 26: createScene(11, 2); break; - // case 1001: + createScene(1, -1); break; } } else { switch (_vm->gameState().sceneNum) { case 0: - // TODO Module2800_updateMusic(true); + updateMusic(true); break; case 1: - // TODO Module2800_updateMusic(false); + updateMusic(false); break; } } } +void Module2800::updateMusic(bool halfVolume) { + + uint32 newMusicFileHash = _vm->_gameModule->getScene2802MusicFileHash(); + + if (!_musicResource) + _musicResource = new MusicResource(_vm); + + if (newMusicFileHash != _currentMusicFileHash) { + _currentMusicFileHash = newMusicFileHash; + if (_currentMusicFileHash != 0) { + _musicResource->load(_currentMusicFileHash); + _musicResource->setVolume(halfVolume ? 60 : 100); + _musicResource->play(0); + } else { + _musicResource->stop(0); + } + } else if (_currentMusicFileHash != 0) { + if (!_musicResource->isPlaying()) { + _musicResource->setVolume(halfVolume ? 60 : 100); + _musicResource->play(0); + } else { + _musicResource->setVolume(halfVolume ? 60 : 100); + } + } else { + _musicResource->stop(0); + } + +} + Scene2801::Scene2801(NeverhoodEngine *vm, Module *parentModule, int which) : Scene(vm, parentModule, true) { @@ -475,6 +512,168 @@ uint32 Scene2801::handleMessage(int messageNum, const MessageParam ¶m, Entit return messageResult; } +Scene2802::Scene2802(NeverhoodEngine *vm, Module *parentModule, int which) + : Scene(vm, parentModule, true), _countdownType(0), _countdown1(0), _countdown2(0) { + + //DEBUG>>> Disable video + setGlobalVar(0x28D8C940, 0); + //DEBUG<<< + + _surfaceFlag = true; + SetMessageHandler(&Scene2802::handleMessage); + SetUpdateHandler(&Scene2802::update); + insertMouse435(0x008810A8, 20, 620); + _smackerPlayer = addSmackerPlayer(new SmackerPlayer(_vm, this, 0x8284C100, true, true, true)); + _smackerFrameNumber = getGlobalVar(0x08CC0828); + _smackerPlayer->gotoFrame(_smackerFrameNumber); + _vm->_soundMan->addSound(0x04360A18, 0x422630C2); + _vm->_soundMan->addSound(0x04360A18, 0x00632252); + _vm->_soundMan->addSound(0x04360A18, 0x00372241); + _vm->_soundMan->setSoundVolume(0x00372241, 60); + changeCountdownType(0, 0); + _vm->_soundMan->playSoundLooping(0x00372241); +} + +Scene2802::~Scene2802() { + _vm->_soundMan->deleteSoundGroup(0x04360A18); + if (_smackerFrameNumber == 0) { + setGlobalVar(0x09880D40, 1); + setGlobalVar(0x08180ABC, 0); + } else if (_smackerFrameNumber == getGlobalVar(0x88880915)) { + setGlobalVar(0x09880D40, 0); + setGlobalVar(0x08180ABC, 1); + } else { + setGlobalVar(0x09880D40, 0); + setGlobalVar(0x08180ABC, 0); + } + setGlobalVar(0x08CC0828, _smackerFrameNumber); +} + +void Scene2802::update() { + int prevCountdownType = _countdownType; + uint prevSmackerFrameNumber = _smackerFrameNumber; + + Scene::update(); + if (_countdown1 > 0) + --_countdown1; + else if (_countdownType == 1) + _countdownType = 3; + else if (_countdownType == 4) + _countdownType = 6; + + switch (_countdownType) { + case 2: + if (_smackerFrameNumber < 90) + incSmackerFrameNumber(+1); + _countdownType = 0; + break; + case 3: + if (_countdown2 > 0) + --_countdown2; + else if (_smackerFrameNumber < 90) { + incSmackerFrameNumber(+1); + _countdown2 = 1; + } else + _countdownType = 0; + break; + case 5: + if (_smackerFrameNumber > 0) + incSmackerFrameNumber(-1); + _countdownType = 0; + break; + case 6: + if (_countdown2 > 0) + --_countdown2; + else if (_smackerFrameNumber > 0) { + incSmackerFrameNumber(-1); + _countdown2 = 1; + } else + _countdownType = 0; + break; + + } + + if (prevSmackerFrameNumber != _smackerFrameNumber) + _smackerPlayer->gotoFrame(_smackerFrameNumber); + + if (prevCountdownType != _countdownType) + changeCountdownType(prevCountdownType, _countdownType); + + if (getGlobalVar(0x28D8C940) && prevCountdownType != _countdownType && _smackerFrameNumber != 0) { + setGlobalVar(0x28D8C940, 0); + leaveScene(1); + } + +} + +uint32 Scene2802::handleMessage(int messageNum, const MessageParam ¶m, Entity *sender) { + int prevCountdownType = _countdownType; + Scene::handleMessage(messageNum, param, sender); + switch (messageNum) { + case 0x0001: + if (param.asPoint().x <= 20 || param.asPoint().x >= 620) { + leaveScene(0); + } else if (_countdownType == 0) { + if (param.asPoint().x > 180 && param.asPoint().x < 300 && + param.asPoint().y > 130 && param.asPoint().y < 310) { + _countdownType = 4; + } else if (param.asPoint().x > 300 && param.asPoint().x < 400 && + param.asPoint().y > 130 && param.asPoint().y < 310) { + _countdownType = 1; + } + if (_countdownType == 1 || _countdownType == 4) { + _countdown1 = 8; + changeCountdownType(0, _countdownType); + } + } + break; + case 0x0002: // TODO Implement button up event + if (_countdown1 == 0) + _countdownType = 0; + else { + if (_countdownType == 1) + _countdownType = 2; + else if (_countdownType == 4) + _countdownType = 5; + else + _countdownType = 0; + _countdown1 = 0; + } + if (prevCountdownType != _countdownType) + changeCountdownType(prevCountdownType, _countdownType); + break; + case 0x000D: + // DEBUG message + break; + } + return 0; +} + +void Scene2802::incSmackerFrameNumber(int delta) { + _smackerFrameNumber += delta; + setGlobalVar(0x08CC0828, _smackerFrameNumber); +} + +void Scene2802::changeCountdownType(int prevCountdownType, int newCountdownType) { + + if (prevCountdownType == 3 || prevCountdownType == 6) { + _vm->_soundMan->stopSound(0x422630C2); + _vm->_soundMan->stopSound(0x00632252); + } + + if (newCountdownType == 0) { + if (_vm->_gameModule->getScene2802MusicFileHash() != 0) { + _vm->_soundMan->stopSound(0x00632252); + } + else + _vm->_soundMan->playSoundLooping(0x00632252); + } else if (newCountdownType == 3 || newCountdownType == 6) { + _vm->_soundMan->playSoundLooping(0x422630C2); + _vm->_soundMan->playSoundLooping(0x00632252); + } + +} + AsScene2803LightCord::AsScene2803LightCord(NeverhoodEngine *vm, Scene *parentScene, uint32 fileHash1, uint32 fileHash2, int16 x, int16 y) : AnimatedSprite(vm, 1100), _parentScene(parentScene), _fileHash1(fileHash1), _fileHash2(fileHash2), _isPulled(false), _isBusy(false) { diff --git a/engines/neverhood/module2800.h b/engines/neverhood/module2800.h index f0403f4990..ca8b058ca1 100644 --- a/engines/neverhood/module2800.h +++ b/engines/neverhood/module2800.h @@ -37,15 +37,17 @@ public: virtual ~Module2800(); protected: bool _flag; - uint32 _fileHash; + uint32 _currentMusicFileHash; + MusicResource *_musicResource; void createScene(int sceneNum, int which); void updateScene(); + void updateMusic(bool halfVolume); }; class Scene2801 : public Scene { public: Scene2801(NeverhoodEngine *vm, Module *parentModule, int which); - ~Scene2801(); + virtual ~Scene2801(); protected: Sprite *_sprite1; Sprite *_sprite2; @@ -54,6 +56,22 @@ protected: uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); }; +class Scene2802 : public Scene { +public: + Scene2802(NeverhoodEngine *vm, Module *parentModule, int which); + virtual ~Scene2802(); +protected: + SmackerPlayer *_smackerPlayer; + uint _smackerFrameNumber; + int _countdownType; + int _countdown1; + int _countdown2; + void update(); + uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender); + void incSmackerFrameNumber(int delta); + void changeCountdownType(int prevCountdownType, int newCountdownType); +}; + class AsScene2803LightCord : public AnimatedSprite { public: AsScene2803LightCord(NeverhoodEngine *vm, Scene *parentScene, uint32 fileHash1, uint32 fileHash2, int16 x, int16 y); diff --git a/engines/neverhood/neverhood.cpp b/engines/neverhood/neverhood.cpp index 4b75f68c3e..cfeaf927d3 100644 --- a/engines/neverhood/neverhood.cpp +++ b/engines/neverhood/neverhood.cpp @@ -136,6 +136,10 @@ Common::Error NeverhoodEngine::run() { case Common::EVENT_RBUTTONDOWN: _gameModule->handleMouseDown(event.mouse.x, event.mouse.y); break; + case Common::EVENT_LBUTTONUP: + case Common::EVENT_RBUTTONUP: + _gameModule->handleMouseUp(event.mouse.x, event.mouse.y); + break; case Common::EVENT_QUIT: _system->quit(); break; diff --git a/engines/neverhood/smackerplayer.cpp b/engines/neverhood/smackerplayer.cpp index 0ed6748e45..b491bc5789 100644 --- a/engines/neverhood/smackerplayer.cpp +++ b/engines/neverhood/smackerplayer.cpp @@ -65,8 +65,8 @@ void SmackerDoubleSurface::draw() { // SmackerPlayer -SmackerPlayer::SmackerPlayer(NeverhoodEngine *vm, Scene *scene, uint32 fileHash, bool doubleSurface, bool flag) - : Entity(vm, 0), _scene(scene), _doubleSurface(doubleSurface), _dirtyFlag(false), _videoDone(false), +SmackerPlayer::SmackerPlayer(NeverhoodEngine *vm, Scene *scene, uint32 fileHash, bool doubleSurface, bool flag, bool paused) + : Entity(vm, 0), _scene(scene), _doubleSurface(doubleSurface), _dirtyFlag(false), _videoDone(false), _paused(paused), _palette(NULL), _smackerDecoder(NULL), _smackerSurface(NULL), _stream(NULL), _smackerFirst(true), _drawX(-1), _drawY(-1) { @@ -104,7 +104,8 @@ void SmackerPlayer::open(uint32 fileHash, bool keepLastFrame) { _palette = new Palette(_vm); _palette->usePalette(); - _smackerDecoder->start(); + if (!_paused) + _smackerDecoder->start(); } @@ -121,8 +122,14 @@ void SmackerPlayer::close() { _smackerSurface = NULL; } -void SmackerPlayer::gotoFrame(uint frameNumber) { - // TODO? +void SmackerPlayer::gotoFrame(int frameNumber) { + // NOTE Slow as hell but only used in Scene2802 + if (frameNumber != _smackerDecoder->getCurFrame()) { + if (frameNumber < _smackerDecoder->getCurFrame()) + rewind(); + while (_smackerDecoder->getCurFrame() != frameNumber) + updateFrame(); + } } uint32 SmackerPlayer::getFrameCount() { @@ -147,20 +154,8 @@ void SmackerPlayer::setDrawPos(int16 x, int16 y) { } void SmackerPlayer::rewind() { - - // TODO Quite dirty, try to implement this in the decoder - - delete _smackerDecoder; - _smackerDecoder = NULL; - _stream = NULL; - - _smackerFirst = true; - - _stream = _vm->_res->createStream(_fileHash); - - _smackerDecoder = new Video::SmackerDecoder(); - _smackerDecoder->loadStream(_stream); - + if (_smackerDecoder) + _smackerDecoder->rewind(); } void SmackerPlayer::update() { @@ -174,17 +169,22 @@ void SmackerPlayer::update() { _dirtyFlag = false; } - if (!_smackerDecoder->endOfVideo()) { - updateFrame(); - } else if (!_keepLastFrame) { - // Inform the scene about the end of the video playback - if (_scene) - sendMessage(_scene, 0x3002, 0); - _videoDone = true; + if (_paused) { + if (_smackerFirst) + updateFrame(); } else { - rewind(); - updateFrame(); - _videoDone = false; + if (!_smackerDecoder->endOfVideo()) { + updateFrame(); + } else if (!_keepLastFrame) { + // Inform the scene about the end of the video playback + if (_scene) + sendMessage(_scene, 0x3002, 0); + _videoDone = true; + } else { + rewind(); + updateFrame(); + _videoDone = false; + } } } @@ -214,7 +214,7 @@ void SmackerPlayer::updateFrame() { // TODO _vm->_screen->_skipUpdate = true; _dirtyFlag = true; - + if (_smackerDecoder->hasDirtyPalette()) updatePalette(); diff --git a/engines/neverhood/smackerplayer.h b/engines/neverhood/smackerplayer.h index c480c2d8d8..63c9ebb774 100644 --- a/engines/neverhood/smackerplayer.h +++ b/engines/neverhood/smackerplayer.h @@ -49,12 +49,12 @@ public: class SmackerPlayer : public Entity { public: - SmackerPlayer(NeverhoodEngine *vm, Scene *scene, uint32 fileHash, bool doubleSurface, bool flag); + SmackerPlayer(NeverhoodEngine *vm, Scene *scene, uint32 fileHash, bool doubleSurface, bool flag, bool paused = false); ~SmackerPlayer(); BaseSurface *getSurface() { return _smackerSurface; } void open(uint32 fileHash, bool keepLastFrame); void close(); - void gotoFrame(uint frameNumber); + void gotoFrame(int frameNumber); uint32 getFrameCount(); uint32 getFrameNumber(); uint getStatus(); @@ -74,6 +74,7 @@ protected: bool _keepLastFrame; bool _videoDone; bool _dirtyFlag; + bool _paused; int _drawX, _drawY; void update(); void updateFrame(); -- cgit v1.2.3