From 7632246264102d88922fc963284af6250ea12f57 Mon Sep 17 00:00:00 2001 From: Sven Hesse Date: Fri, 15 Jun 2012 13:32:43 +0200 Subject: [PATCH] GOB: Implement Util::getKeyState() for Little Red This makes the bees level playable, removing the "lock-up". Collision detection between Little Red and the bees and butterflies doesn't work yet though, so they're just flying through her. Nevertheless, the game seems to be completable now. --- engines/gob/inter.cpp | 12 +++++++ engines/gob/inter.h | 9 +++-- engines/gob/inter_littlered.cpp | 58 +++++++++++++++++++++++++++++++++ engines/gob/inter_v1.cpp | 16 +++------ engines/gob/util.cpp | 40 ++++++++++++++++++++++- engines/gob/util.h | 8 +++++ 6 files changed, 128 insertions(+), 15 deletions(-) diff --git a/engines/gob/inter.cpp b/engines/gob/inter.cpp index 9df3c06c7429..843c0bff4846 100644 --- a/engines/gob/inter.cpp +++ b/engines/gob/inter.cpp @@ -52,6 +52,7 @@ Inter::Inter(GobEngine *vm) : _vm(vm), _varStack(600) { _soundEndTimeKey = 0; _soundStopVal = 0; + _lastBusyWait = 0; _noBusyWait = false; _variables = 0; @@ -452,4 +453,15 @@ uint32 Inter::readValue(uint16 index, uint16 type) { return 0; } +void Inter::handleBusyWait() { + uint32 now = _vm->_util->getTimeKey(); + + if (!_noBusyWait) + if ((now - _lastBusyWait) <= 20) + _vm->_util->longDelay(1); + + _lastBusyWait = now; + _noBusyWait = false; +} + } // End of namespace Gob diff --git a/engines/gob/inter.h b/engines/gob/inter.h index 907a275e50c7..0625646cdd00 100644 --- a/engines/gob/inter.h +++ b/engines/gob/inter.h @@ -142,8 +142,9 @@ class Inter { VariableStack _varStack; - // The busy-wait detection in o1_keyFunc breaks fast scrolling in Ween - bool _noBusyWait; + // Busy-wait detection + bool _noBusyWait; + uint32 _lastBusyWait; GobEngine *_vm; @@ -172,6 +173,8 @@ class Inter { void storeString(const char *value); uint32 readValue(uint16 index, uint16 type); + + void handleBusyWait(); }; class Inter_v1 : public Inter { @@ -522,6 +525,8 @@ class Inter_LittleRed : public Inter_v2 { virtual void setupOpcodesDraw(); virtual void setupOpcodesFunc(); virtual void setupOpcodesGob(); + + void oLittleRed_keyFunc(OpFuncParams ¶ms); }; class Inter_v3 : public Inter_v2 { diff --git a/engines/gob/inter_littlered.cpp b/engines/gob/inter_littlered.cpp index 6a6399821647..01d372aaeba9 100644 --- a/engines/gob/inter_littlered.cpp +++ b/engines/gob/inter_littlered.cpp @@ -22,6 +22,13 @@ #include "gob/gob.h" #include "gob/inter.h" +#include "gob/global.h" +#include "gob/util.h" +#include "gob/draw.h" +#include "gob/game.h" +#include "gob/script.h" +#include "gob/hotspots.h" +#include "gob/sound/sound.h" namespace Gob { @@ -39,6 +46,8 @@ void Inter_LittleRed::setupOpcodesDraw() { void Inter_LittleRed::setupOpcodesFunc() { Inter_v2::setupOpcodesFunc(); + + OPCODEFUNC(0x14, oLittleRed_keyFunc); } void Inter_LittleRed::setupOpcodesGob() { @@ -46,4 +55,53 @@ void Inter_LittleRed::setupOpcodesGob() { OPCODEGOB(501, o2_stopProtracker); } +void Inter_LittleRed::oLittleRed_keyFunc(OpFuncParams ¶ms) { + animPalette(); + _vm->_draw->blitInvalidated(); + + handleBusyWait(); + + int16 cmd = _vm->_game->_script->readInt16(); + int16 key; + uint32 keyState; + + switch (cmd) { + case -1: + break; + + case 0: + _vm->_draw->_showCursor &= ~2; + _vm->_util->longDelay(1); + key = _vm->_game->_hotspots->check(0, 0); + storeKey(key); + + _vm->_util->clearKeyBuf(); + break; + + case 1: + _vm->_util->forceMouseUp(true); + key = _vm->_game->checkKeys(&_vm->_global->_inter_mouseX, + &_vm->_global->_inter_mouseY, &_vm->_game->_mouseButtons, 0); + storeKey(key); + break; + + case 2: + _vm->_util->processInput(true); + keyState = _vm->_util->getKeyState(); + + WRITE_VAR(0, keyState); + _vm->_util->clearKeyBuf(); + break; + + default: + _vm->_sound->speakerOnUpdate(cmd); + if (cmd < 20) { + _vm->_util->delay(cmd); + _noBusyWait = true; + } else + _vm->_util->longDelay(cmd); + break; + } +} + } // End of namespace Gob diff --git a/engines/gob/inter_v1.cpp b/engines/gob/inter_v1.cpp index 3652637e32d0..dc533a210a25 100644 --- a/engines/gob/inter_v1.cpp +++ b/engines/gob/inter_v1.cpp @@ -1189,26 +1189,15 @@ void Inter_v1::o1_palLoad(OpFuncParams ¶ms) { } void Inter_v1::o1_keyFunc(OpFuncParams ¶ms) { - static uint32 lastCalled = 0; - int16 cmd; - int16 key; - uint32 now; - if (!_vm->_vidPlayer->isPlayingLive()) { _vm->_draw->forceBlit(); _vm->_video->retrace(); } - cmd = _vm->_game->_script->readInt16(); animPalette(); _vm->_draw->blitInvalidated(); - now = _vm->_util->getTimeKey(); - if (!_noBusyWait) - if ((now - lastCalled) <= 20) - _vm->_util->longDelay(1); - lastCalled = now; - _noBusyWait = false; + handleBusyWait(); // WORKAROUND for bug #1726130: Ween busy-waits in the intro for a counter // to become 5000. We deliberately slow down busy-waiting, so we shorten @@ -1217,6 +1206,9 @@ void Inter_v1::o1_keyFunc(OpFuncParams ¶ms) { (_vm->_game->_script->pos() == 729) && _vm->isCurrentTot("intro5.tot")) WRITE_VAR(59, 4000); + int16 cmd = _vm->_game->_script->readInt16(); + int16 key; + switch (cmd) { case -1: break; diff --git a/engines/gob/util.cpp b/engines/gob/util.cpp index 7f9c6131fdcf..64dfcf9b12f3 100644 --- a/engines/gob/util.cpp +++ b/engines/gob/util.cpp @@ -21,7 +21,6 @@ */ #include "common/stream.h" -#include "common/events.h" #include "graphics/palette.h" @@ -45,6 +44,8 @@ Util::Util(GobEngine *vm) : _vm(vm) { _frameRate = 12; _frameWaitTime = 0; _startFrameTime = 0; + + _keyState = 0; } uint32 Util::getTimeKey() { @@ -116,6 +117,8 @@ void Util::processInput(bool scroll) { _mouseButtons = (MouseButtons) (((uint32) _mouseButtons) & ~((uint32) kMouseButtonsRight)); break; case Common::EVENT_KEYDOWN: + keyDown(event); + if (event.kbd.hasFlags(Common::KBD_CTRL)) { if (event.kbd.keycode == Common::KEYCODE_f) _fastMode ^= 1; @@ -132,6 +135,7 @@ void Util::processInput(bool scroll) { addKeyToBuffer(event.kbd); break; case Common::EVENT_KEYUP: + keyUp(event); break; default: break; @@ -576,4 +580,38 @@ void Util::checkJoystick() { _vm->_global->_useJoystick = 0; } +uint32 Util::getKeyState() const { + return _keyState; +} + +void Util::keyDown(const Common::Event &event) { + if (event.kbd.keycode == Common::KEYCODE_UP) + _keyState |= 0x0001; + else if (event.kbd.keycode == Common::KEYCODE_DOWN) + _keyState |= 0x0002; + else if (event.kbd.keycode == Common::KEYCODE_RIGHT) + _keyState |= 0x0004; + else if (event.kbd.keycode == Common::KEYCODE_LEFT) + _keyState |= 0x0008; + else if (event.kbd.keycode == Common::KEYCODE_SPACE) + _keyState |= 0x0020; + else if (event.kbd.keycode == Common::KEYCODE_ESCAPE) + _keyState |= 0x0040; +} + +void Util::keyUp(const Common::Event &event) { + if (event.kbd.keycode == Common::KEYCODE_UP) + _keyState &= ~0x0001; + else if (event.kbd.keycode == Common::KEYCODE_DOWN) + _keyState &= ~0x0002; + else if (event.kbd.keycode == Common::KEYCODE_RIGHT) + _keyState &= ~0x0004; + else if (event.kbd.keycode == Common::KEYCODE_LEFT) + _keyState &= ~0x0008; + else if (event.kbd.keycode == Common::KEYCODE_SPACE) + _keyState &= ~0x0020; + else if (event.kbd.keycode == Common::KEYCODE_ESCAPE) + _keyState &= ~0x0040; +} + } // End of namespace Gob diff --git a/engines/gob/util.h b/engines/gob/util.h index 4228dac76861..b26a78ab2cca 100644 --- a/engines/gob/util.h +++ b/engines/gob/util.h @@ -25,6 +25,7 @@ #include "common/str.h" #include "common/keyboard.h" +#include "common/events.h" namespace Common { class SeekableReadStream; @@ -110,6 +111,8 @@ class Util { bool checkKey(int16 &key); bool keyPressed(); + uint32 getKeyState() const; + void getMouseState(int16 *pX, int16 *pY, MouseButtons *pButtons); void setMousePos(int16 x, int16 y); void waitMouseUp(); @@ -155,6 +158,8 @@ class Util { int16 _frameWaitTime; uint32 _startFrameTime; + uint32 _keyState; + GobEngine *_vm; bool keyBufferEmpty(); @@ -162,6 +167,9 @@ class Util { bool getKeyFromBuffer(Common::KeyState &key); int16 translateKey(const Common::KeyState &key); void checkJoystick(); + + void keyDown(const Common::Event &event); + void keyUp(const Common::Event &event); }; } // End of namespace Gob