Logo Search packages:      
Sourcecode: scummvm version File versions  Download package

util.cpp

/* 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.
 *
 * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/tags/release-0-11-1/engines/gob/util.cpp $
 * $Id: util.cpp 30944 2008-02-23 22:50:18Z sev $
 *
 */


#include "common/events.h"

#include "gob/gob.h"
#include "gob/util.h"
#include "gob/global.h"
#include "gob/dataio.h"
#include "gob/draw.h"
#include "gob/game.h"
#include "gob/sound.h"
#include "gob/video.h"

namespace Gob {

Util::Util(GobEngine *vm) : _vm(vm) {
      _mouseButtons = 0;
      _keyBufferHead = 0;
      _keyBufferTail = 0;
      _fastMode = 0;
}

uint32 Util::getTimeKey(void) {
      return g_system->getMillis() * _vm->_global->_speedFactor;
}

int16 Util::getRandom(int16 max) {
      if (max == 0)
            return 0;

      return _vm->_rnd.getRandomNumber(max - 1);
}

void Util::beep(int16 freq) {
      if (_vm->_global->_soundFlags == 0)
            return;

      _vm->_snd->speakerOn(freq, 50);
}

void Util::delay(uint16 msecs) {
      g_system->delayMillis(msecs / _vm->_global->_speedFactor);
}

void Util::longDelay(uint16 msecs) {
      uint32 time = g_system->getMillis() * _vm->_global->_speedFactor + msecs;
      do {
            _vm->_video->waitRetrace();
            processInput();
            delay(15);
      } while (!_vm->_quitRequested &&
               ((g_system->getMillis() * _vm->_global->_speedFactor) < time));
}

void Util::initInput(void) {
      _mouseButtons = 0;
      _keyBufferHead = _keyBufferTail = 0;
}

void Util::processInput(bool scroll) {
      Common::Event event;
      Common::EventManager *eventMan = g_system->getEventManager();
      int16 x = 0, y = 0;
      bool hasMove = false;

      while (eventMan->pollEvent(event)) {
            switch (event.type) {
            case Common::EVENT_MOUSEMOVE:
                  hasMove = true;
                  x = event.mouse.x;
                  y = event.mouse.y;
                  break;
            case Common::EVENT_LBUTTONDOWN:
                  _mouseButtons |= 1;
                  break;
            case Common::EVENT_RBUTTONDOWN:
                  _mouseButtons |= 2;
                  break;
            case Common::EVENT_LBUTTONUP:
                  _mouseButtons &= ~1;
                  break;
            case Common::EVENT_RBUTTONUP:
                  _mouseButtons &= ~2;
                  break;
            case Common::EVENT_KEYDOWN:
                  if (event.kbd.flags == Common::KBD_CTRL) {
                        if (event.kbd.keycode == Common::KEYCODE_f)
                              _fastMode ^= 1;
                        else if (event.kbd.keycode == Common::KEYCODE_g)
                              _fastMode ^= 2;
                        break;
                  }
                  addKeyToBuffer(event.kbd);
                  break;
            case Common::EVENT_KEYUP:
                  break;
            case Common::EVENT_QUIT:
                  _vm->_quitRequested = true;
                  break;
            default:
                  break;
            }
      }

      _vm->_global->_speedFactor = MIN(_fastMode + 1, 3);
      if (scroll && hasMove) {
            if (y >= (_vm->_height - _vm->_video->_splitHeight2)) {
                  y = _vm->_height - _vm->_video->_splitHeight2 - 1;
                  _vm->_util->setMousePos(x, y);
            }
            _vm->_game->evaluateScroll(x, y);
      }
}

void Util::clearKeyBuf(void) {
      processInput();
      _keyBufferHead = _keyBufferTail = 0;
}

bool Util::keyBufferEmpty() {
      return (_keyBufferHead == _keyBufferTail);
}

void Util::addKeyToBuffer(const Common::KeyState &key) {
      if ((_keyBufferHead + 1) % KEYBUFSIZE == _keyBufferTail) {
            warning("key buffer overflow");
            return;
      }

      _keyBuffer[_keyBufferHead] = key;
      _keyBufferHead = (_keyBufferHead + 1) % KEYBUFSIZE;
}

bool Util::getKeyFromBuffer(Common::KeyState &key) {
      if (_keyBufferHead == _keyBufferTail) return false;

      key = _keyBuffer[_keyBufferTail];
      _keyBufferTail = (_keyBufferTail + 1) % KEYBUFSIZE;

      return true;
}

int16 Util::translateKey(const Common::KeyState &key) {
      static struct keyS {
            int16 from;
            int16 to;
      } keys[] = {
            {Common::KEYCODE_INVALID,   0x0000},
            {Common::KEYCODE_BACKSPACE, 0x0E08},
            {Common::KEYCODE_SPACE,     0x3920},
            {Common::KEYCODE_RETURN,    0x1C0D},
            {Common::KEYCODE_ESCAPE,    0x011B},
            {Common::KEYCODE_DELETE,    0x5300},
            {Common::KEYCODE_UP,        0x4800},
            {Common::KEYCODE_DOWN,      0x5000},
            {Common::KEYCODE_RIGHT,     0x4D00},
            {Common::KEYCODE_LEFT,      0x4B00},
            {Common::KEYCODE_F1,        0x3B00},
            {Common::KEYCODE_F2,        0x3C00},
            {Common::KEYCODE_F3,        0x3D00},
            {Common::KEYCODE_F4,        0x3E00},
            {Common::KEYCODE_F5,        0x011B},
            {Common::KEYCODE_F6,        0x4000},
            {Common::KEYCODE_F7,        0x4100},
            {Common::KEYCODE_F8,        0x4200},
            {Common::KEYCODE_F9,        0x4300},
            {Common::KEYCODE_F10,       0x4400}
      };

      for (int i = 0; i < ARRAYSIZE(keys); i++)
            if (key.keycode == keys[i].from)
                  return keys[i].to;

      if ((key.keycode >= Common::KEYCODE_SPACE) &&
          (key.keycode <= Common::KEYCODE_DELETE)) {

            // Used as a user input in Gobliins 2 notepad, in the save dialog, ...
            return key.ascii;
      }

      return 0;
}

int16 Util::getKey(void) {
      Common::KeyState key;

      while (!getKeyFromBuffer(key)) {
            processInput();

            if (keyBufferEmpty())
                  g_system->delayMillis(10 / _vm->_global->_speedFactor);
      }
      return translateKey(key);
}

int16 Util::checkKey(void) {
      Common::KeyState key;

      getKeyFromBuffer(key);

      return translateKey(key);
}

void Util::getMouseState(int16 *pX, int16 *pY, int16 *pButtons) {
      Common::Point mouse = g_system->getEventManager()->getMousePos();
      *pX = mouse.x + _vm->_video->_scrollOffsetX;
      *pY = mouse.y + _vm->_video->_scrollOffsetY;

      if (pButtons != 0)
            *pButtons = _mouseButtons;
}

void Util::setMousePos(int16 x, int16 y) {
      g_system->warpMouse(x, y);
}

void Util::waitMouseUp(void) {
      do {
            processInput();
            if (_mouseButtons != 0)
                  delay(10);
      } while (_mouseButtons != 0);
}

void Util::waitMouseDown(void) {
      int16 x;
      int16 y;
      int16 buttons;

      do {
            processInput();
            getMouseState(&x, &y, &buttons);
            if (buttons == 0)
                  delay(10);
      } while (buttons == 0);
}

void Util::waitMouseRelease(char drawMouse) {
      int16 buttons;
      int16 mouseX;
      int16 mouseY;

      do {
            _vm->_game->checkKeys(&mouseX, &mouseY, &buttons, drawMouse);
            if (drawMouse != 0)
                  _vm->_draw->animateCursor(2);
            delay(10);
      } while (buttons != 0);
}

void Util::forceMouseUp(bool onlyWhenSynced) {
      if (onlyWhenSynced && (_vm->_game->_mouseButtons != _mouseButtons))
            return;

      _vm->_game->_mouseButtons = 0;
      _mouseButtons = 0;
}

void Util::clearPalette(void) {
      int16 i;
      byte colors[768];

      _vm->validateVideoMode(_vm->_global->_videoMode);

      if (_vm->_global->_setAllPalette) {
            for (i = 0; i < 768; i++)
                  colors[i] = 0;
            g_system->setPalette(colors, 0, 256);
            return;
      }

      for (i = 0; i < 16; i++)
            _vm->_video->setPalElem(i, 0, 0, 0, 0, _vm->_global->_videoMode);
}

void Util::setFrameRate(int16 rate) {
      if (rate == 0)
            rate = 1;

      _vm->_global->_frameWaitTime = 1000 / rate;
      _vm->_global->_startFrameTime = getTimeKey();
}

void Util::waitEndFrame() {
      int32 time;

      _vm->_video->waitRetrace();

      time = getTimeKey() - _vm->_global->_startFrameTime;
      if ((time > 1000) || (time < 0)) {
            _vm->_global->_startFrameTime = getTimeKey();
            return;
      }

      if ((_vm->_global->_frameWaitTime - time) > 0)
            delay(_vm->_global->_frameWaitTime - time);

      _vm->_global->_startFrameTime = getTimeKey();
}

void Util::setScrollOffset(int16 x, int16 y) {
      processInput();

      if(x >= 0)
            _vm->_video->_scrollOffsetX = x; 
      else
            _vm->_video->_scrollOffsetX = _vm->_draw->_scrollOffsetX;

      if(y >= 0)
            _vm->_video->_scrollOffsetY = y; 
      else
            _vm->_video->_scrollOffsetY = _vm->_draw->_scrollOffsetY;

      _vm->_video->waitRetrace();
}

Video::FontDesc *Util::loadFont(const char *path) {
      Video::FontDesc *fontDesc = new Video::FontDesc;
      byte *data;

      if (!fontDesc)
            return 0;

      data = _vm->_dataIO->getData(path);
      if (!data) {
            delete fontDesc;
            return 0;
      }

      fontDesc->dataPtr = data + 4;
      fontDesc->itemWidth = data[0] & 0x7F;
      fontDesc->itemHeight = data[1];
      fontDesc->startItem = data[2];
      fontDesc->endItem = data[3];

      fontDesc->itemSize =
          ((fontDesc->itemWidth - 1) / 8 + 1) * fontDesc->itemHeight;
      fontDesc->bitWidth = fontDesc->itemWidth;

      if (data[0] & 0x80)
            fontDesc->extraData = data + 4 + fontDesc->itemSize *
                  (fontDesc->endItem - fontDesc->startItem + 1);
      else
            fontDesc->extraData = 0;

      return fontDesc;
}

void Util::freeFont(Video::FontDesc *fontDesc) {
      delete[] (fontDesc->dataPtr - 4);
      delete fontDesc;
}

void Util::insertStr(const char *str1, char *str2, int16 pos) {
      int len1 = strlen(str1);
      int len2 = strlen(str2);
      int from = MIN((int) pos, len2);

      for (int i = len2; i >= from; i--)
            str2[len1 + i] = str2[i];
      for (int i = 0; i < len1; i++)
            str2[i + from] = str1[i];
}

void Util::cutFromStr(char *str, int16 from, int16 cutlen) {
      int len = strlen(str);

      if (from >= len)
            return;
      if ((from + cutlen) > len) {
            str[from] = 0;
            return;
      }

      int i = from;
      do {
            str[i] = str[i + cutlen];
            i++;
      } while (str[i] != 0);
}

void Util::replaceChar(char *str, char c1, char c2) {
      while ((str = strchr(str, c1)))
            *str = c2;
}

static const char trStr1[] =
      "       '   + - :0123456789: <=>  abcdefghijklmnopqrstuvwxyz      "
      "abcdefghijklmnopqrstuvwxyz     ";
static const char trStr2[] =
      " ueaaaaceeeiii     ooouu        aioun"
      "                                                           ";
static const char trStr3[] = "                                ";

void Util::prepareStr(char *str) {
      char *start, *end;
      char buf[300];

      strcpy(buf, trStr1);
      strcat(buf, trStr2);
      strcat(buf, trStr3);

      for (size_t i = 0; i < strlen(str); i++)
            str[i] = buf[str[i] - 32];

      while (str[0] == ' ')
            cutFromStr(str, 0, 1);

      while ((strlen(str) > 0) && (str[strlen(str) - 1] == ' '))
            cutFromStr(str, strlen(str) - 1, 1);

      start = strchr(str, ' ');

      while (start) {
            if (start[1] == ' ') {
                  cutFromStr(str, start - str, 1);
                  continue;
            }

            end = strchr(start + 1, ' ');
            start = end ? end + 1 : 0;
      }
}

void Util::listInsertFront(List *list, void *data) {
      ListNode *node;

      node = new ListNode;
      if (list->pHead) {
            node->pData = data;
            node->pNext = list->pHead;
            node->pPrev = 0;
            list->pHead->pPrev = node;
            list->pHead = node;
      } else {
            list->pHead = node;
            list->pTail = node;
            node->pData = data;
            node->pNext = 0;
            node->pPrev = 0;
      }
}

void Util::listInsertBack(List *list, void *data) {
      ListNode *node;

      if (list->pHead != 0) {
            if (list->pTail == 0) {
                  list->pTail = list->pHead;
                  warning("Util::listInsertBack(): Broken list");
            }

            node = new ListNode;
            node->pData = data;
            node->pPrev = list->pTail;
            node->pNext = 0;
            list->pTail->pNext = node;
            list->pTail = node;
      } else
            listInsertFront(list, data);
}

void Util::listDropFront(List *list) {
      if (list->pHead->pNext == 0) {
            delete list->pHead;
            list->pHead = 0;
            list->pTail = 0;
      } else {
            list->pHead = list->pHead->pNext;
            delete list->pHead->pPrev;
            list->pHead->pPrev = 0;
      }
}

void Util::deleteList(List *list) {
      while (list->pHead)
            listDropFront(list);

      delete list;
}

/* NOT IMPLEMENTED */
void Util::checkJoystick() {
      _vm->_global->_useJoystick = 0;
}

} // End of namespace Gob

Generated by  Doxygen 1.6.0   Back to index