scummvm/gob/util.cpp
Torbjörn Andersson c3f3d9f3f2 Made Gobliiins less of a CPU hog by adding some strategic delays and
turning on the screen auto-dirtying - some as Simon uses. It's not perfect
by any means, but it may be good enough for 0.8.0 at least.

svn-id: r18649
2005-08-10 15:48:50 +00:00

503 lines
9.8 KiB
C++

/* ScummVM - Scumm Interpreter
* Copyright (C) 2004 Ivan Dubrov
* Copyright (C) 2004-2005 The ScummVM project
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Header$
*
*/
#include "gob/gob.h"
#include "gob/global.h"
#include "gob/timer.h"
#include "gob/util.h"
#include "gob/draw.h"
#include "gob/game.h"
namespace Gob {
static const int kKeyBufSize = 16;
static int16 _mouseX, _mouseY, _mouseButtons;
static int16 _keyBuffer[kKeyBufSize], _keyBufferHead, _keyBufferTail;
static void addKeyToBuffer(int16 key) {
if ((_keyBufferHead + 1) % kKeyBufSize == _keyBufferTail) {
warning("key buffer overflow!");
return;
}
_keyBuffer[_keyBufferHead] = key;
_keyBufferHead = (_keyBufferHead + 1) % kKeyBufSize;
}
static bool keyBufferEmpty() {
return (_keyBufferHead == _keyBufferTail);
}
static bool getKeyFromBuffer(int16& key) {
if (_keyBufferHead == _keyBufferTail) return false;
key = _keyBuffer[_keyBufferTail];
_keyBufferTail = (_keyBufferTail + 1) % kKeyBufSize;
return true;
}
void util_initInput(void) {
_mouseX = _mouseY = _mouseButtons = 0;
_keyBufferHead = _keyBufferTail = 0;
}
void util_waitKey(void) {
// FIXME: wrong function name? This functions clears the keyboard buffer.
util_processInput();
_keyBufferHead = _keyBufferTail = 0;
}
int16 util_translateKey(int16 key) {
struct keyS {
int16 from;
int16 to;
} keys[] = {
{8, 0x0e08}, // Backspace
{13, 0x1C0D}, // Enter
{27, 0x011b}, // ESC
{127, 0x5300}, // Del
{273, 0x4800}, // Up arrow
{274, 0x5000}, // Down arrow
{275, 0x4D00}, // Right arrow
{276, 0x4B00}, // Left arrow
{282, 0x3b00}, // F1
{283, 0x3c00}, // F2
{284, 0x3d00}, // F3
{285, 0x3E00}, // F4
{286, 0x011b}, // F5
{287, 0x4000}, // F6
{288, 0x4100}, // F7
{289, 0x4200}, // F8
{290, 0x4300}, // F9
{291, 0x4400} // F10
};
int i;
for (i = 0; i < ARRAYSIZE(keys); i++)
if (key == keys[i].from)
return keys[i].to;
if (key < 32 || key >= 128)
return 0;
return key;
}
int16 util_getKey(void) {
int16 key;
while (!getKeyFromBuffer(key)) {
util_processInput();
if (keyBufferEmpty())
g_system->delayMillis(10);
}
return util_translateKey(key);
}
int16 util_checkKey(void) {
int16 key;
if (!getKeyFromBuffer(key))
key = 0;
return util_translateKey(key);
}
int16 util_getRandom(int16 max) {
return _vm->_rnd.getRandomNumber(max - 1);
}
void util_processInput() {
OSystem::Event event;
while (g_system->pollEvent(event)) {
switch (event.type) {
case OSystem::EVENT_MOUSEMOVE:
_mouseX = event.mouse.x;
_mouseY = event.mouse.y;
break;
case OSystem::EVENT_LBUTTONDOWN:
_mouseButtons |= 1;
break;
case OSystem::EVENT_RBUTTONDOWN:
_mouseButtons |= 2;
break;
case OSystem::EVENT_LBUTTONUP:
_mouseButtons &= ~1;
break;
case OSystem::EVENT_RBUTTONUP:
_mouseButtons &= ~2;
break;
case OSystem::EVENT_KEYDOWN:
addKeyToBuffer(event.kbd.keycode);
break;
case OSystem::EVENT_KEYUP:
break;
case OSystem::EVENT_QUIT:
g_system->quit();
break;
default:
break;
}
}
}
void util_getMouseState(int16 *pX, int16 *pY, int16 *pButtons) {
*pX = _mouseX;
*pY = _mouseY;
if (pButtons != 0)
*pButtons = _mouseButtons;
}
void util_setMousePos(int16 x, int16 y) {
g_system->warpMouse(x, y);
}
void util_longDelay(uint16 msecs)
{
uint32 time = g_system->getMillis() + msecs;
do {
util_processInput();
util_delay(10);
} while (g_system->getMillis() < time);
}
void util_delay(uint16 msecs) {
g_system->delayMillis(msecs);
}
void util_beep(int16 freq) {
if (soundFlags == 0)
return;
snd_speakerOn(freq, 50);
}
uint32 util_getTimeKey(void) {
return g_system->getMillis();
}
void util_waitMouseUp(void) {
int16 x;
int16 y;
int16 buttons;
do {
util_processInput();
util_getMouseState(&x, &y, &buttons);
if (buttons != 0) util_delay(10);
} while (buttons != 0);
}
void util_waitMouseDown(void) {
int16 x;
int16 y;
int16 buttons;
do {
util_processInput();
util_getMouseState(&x, &y, &buttons);
if (buttons == 0) util_delay(10);
} while (buttons == 0);
}
/* NOT IMPLEMENTED */
int16 util_calcDelayTime() {
return 0;
}
/* NOT IMPLEMENTED */
void util_checkJoystick() {
useJoystick = 0;
}
void util_setFrameRate(int16 rate) {
if (rate == 0)
rate = 1;
frameWaitTime = 1000 / rate;
startFrameTime = util_getTimeKey();
}
void util_waitEndFrame() {
int32 time;
vid_waitRetrace(videoMode);
time = util_getTimeKey() - startFrameTime;
if (time > 1000 || time < 0) {
startFrameTime = util_getTimeKey();
return;
}
if (frameWaitTime - time > 0) {
util_delay(frameWaitTime - time);
}
startFrameTime = util_getTimeKey();
}
int16 joy_getState() {
return 0;
}
int16 joy_calibrate() {
return 0;
}
FontDesc *util_loadFont(const char *path) {
FontDesc *fontDesc = (FontDesc *) malloc(sizeof(FontDesc));
char *data;
if (fontDesc == 0)
return 0;
data = data_getData(path);
if (data == 0) {
free(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(FontDesc * fontDesc) {
free(fontDesc->dataPtr - 4);
free(fontDesc);
}
void util_clearPalette(void) {
int16 i;
byte colors[768];
if (videoMode != 0x13)
error("util_clearPalette: Video mode 0x%x is not supported!",
videoMode);
if (setAllPalette) {
for (i = 0; i < 768; i++)
colors[i] = 0;
g_system->setPalette(colors, 0, 256);
return;
}
for (i = 0; i < 16; i++)
vid_setPalElem(i, 0, 0, 0, 0, videoMode);
}
void util_insertStr(const char *str1, char *str2, int16 pos) {
int16 len1;
int16 i;
int16 from;
i = strlen(str2);
len1 = strlen(str1);
if (pos < i)
from = pos;
else
from = i;
for (; i >= from; i--)
str2[len1 + i] = str2[i];
for (i = 0; i < len1; i++)
str2[i + from] = str1[i];
}
void util_cutFromStr(char *str, int16 from, int16 cutlen) {
int16 len;
int16 i;
//log_write("util_cutFromStr: str = %s, ", str);
len = strlen(str);
if (from >= len)
return;
if (from + cutlen > len) {
str[from] = 0;
//log_write("res = %s\n", str);
return;
}
i = from;
do {
str[i] = str[i + cutlen];
i++;
} while (str[i] != 0);
//log_write("res = %s\n", str);
}
int16 util_strstr(const char *str1, char *str2) {
char c;
uint16 len1;
uint16 i;
//log_write("util_strstr: str1 = %s, str2 = %s\n", str1, str2);
for (i = 0, len1 = strlen(str1); strlen(str2 + i) >= len1; i++) {
c = str2[i + len1];
str2[i + len1] = 0;
if (strcmp(str2 + i, str1) == 0) {
str2[i + len1] = c;
return i + 1;
}
str2[i + len1] = c;
}
return 0;
}
void util_listInsertFront(Util_List * list, void *data) {
Util_ListNode *node;
node = (Util_ListNode *) malloc(sizeof(Util_ListNode));
if (list->pHead != 0) {
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(Util_List * list, void *data) {
Util_ListNode *node;
if (list->pHead != 0) {
if (list->pTail == 0) {
list->pTail = list->pHead;
warning("util_listInsertBack: Broken list!");
}
node =
(Util_ListNode *) malloc(sizeof(Util_ListNode));
node->pData = data;
node->pPrev = list->pTail;
node->pNext = 0;
list->pTail->pNext = node;
list->pTail = node;
} else {
util_listInsertFront(list, data);
}
}
void util_listDropFront(Util_List * list) {
if (list->pHead->pNext == 0) {
free((list->pHead));
list->pHead = 0;
list->pTail = 0;
} else {
list->pHead = list->pHead->pNext;
free((list->pHead->pPrev));
list->pHead->pPrev = 0;
}
}
void util_deleteList(Util_List * list) {
while (list->pHead != 0) {
util_listDropFront(list);
}
free(list);
}
char util_str1[] =
" ' + - :0123456789: <=> abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz ";
char util_str2[] =
" ueaaaaceeeiii ooouu aioun ";
char util_str3[] = " ";
void util_prepareStr(char *str) {
uint16 i;
int16 j;
char buf[300];
strcpy(buf, util_str1);
strcat(buf, util_str2);
strcat(buf, util_str3);
for (i = 0; i < strlen(str); i++)
str[i] = buf[str[i] - 32];
while (str[0] == ' ')
util_cutFromStr(str, 0, 1);
while (strlen(str) > 0 && str[strlen(str) - 1] == ' ')
util_cutFromStr(str, strlen(str) - 1, 1);
i = util_strstr(" ", str);
while (1) {
if (i == 0)
return;
if (str[i] == ' ') {
util_cutFromStr(str, i - 1, 1);
continue;
}
j = util_strstr(" ", str + i);
if (j != 0)
i += j;
else
i = 0;
}
}
void util_waitMouseRelease(char drawMouse) {
int16 buttons;
int16 mouseX;
int16 mouseY;
do {
game_checkKeys(&mouseX, &mouseY, &buttons, drawMouse);
if (drawMouse != 0)
draw_animateCursor(2);
util_delay(10);
} while (buttons != 0);
}
void keyboard_release(void) {;}
} // End of namespace Gob