scummvm/sky/mouse.cpp
2004-08-20 13:37:50 +00:00

314 lines
7.7 KiB
C++

/* ScummVM - Scumm Interpreter
* Copyright (C) 2003-2004 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 "stdafx.h"
#include "common/system.h"
#include "sky/disk.h"
#include "sky/logic.h"
#include "sky/mouse.h"
#include "sky/sky.h"
#include "sky/skydefs.h"
#include "sky/struc.h"
namespace Sky {
#define MICE_FILE 60300
#define NO_MAIN_OBJECTS 24
#define NO_LINC_OBJECTS 21
uint32 Mouse::_mouseMainObjects[24] = {
65,
9,
66,
64,
8,
63,
10,
11,
71,
76,
37,
36,
42,
75,
79,
6,
74,
39,
49,
43,
34,
35,
77,
38
};
uint32 Mouse::_mouseLincObjects[21] = {
24625,
24649,
24827,
24651,
24583,
24581,
24582,
24628,
24650,
24629,
24732,
24631,
24584,
24630,
24626,
24627,
24632,
24643,
24828,
24830,
24829
};
Mouse::Mouse(OSystem *system, Disk *skyDisk) {
_skyDisk = skyDisk;
_system = system;
_mouseB = 0;
_currentCursor = 6;
_mouseX = GAME_SCREEN_WIDTH / 2;
_mouseY = GAME_SCREEN_HEIGHT / 2;
_miceData = _skyDisk->loadFile(MICE_FILE, NULL);
//load in the object mouse file
_objectMouseData = _skyDisk->loadFile(MICE_FILE + 1, NULL);
}
Mouse::~Mouse( ){
free (_miceData);
free (_objectMouseData);
}
void Mouse::replaceMouseCursors(uint16 fileNo) {
_skyDisk->loadFile(fileNo, _objectMouseData);
}
bool Mouse::fnAddHuman(void) {
//reintroduce the mouse so that the human can control the player
//could still be switched out at high-level
if (!Logic::_scriptVariables[MOUSE_STOP]) {
Logic::_scriptVariables[MOUSE_STATUS] |= 6; //cursor & mouse
if (_mouseY < 2) //stop mouse activating top line
_mouseY = 2;
_system->warpMouse(_mouseX, _mouseY);
//force the pointer engine into running a get-off
//even if it's over nothing
//KWIK-FIX
//get off may contain script to remove mouse pointer text
//surely this script should be run just in case
//I am going to try it anyway
if (Logic::_scriptVariables[GET_OFF])
_skyLogic->script((uint16)Logic::_scriptVariables[GET_OFF],(uint16)(Logic::_scriptVariables[GET_OFF] >> 16));
Logic::_scriptVariables[SPECIAL_ITEM] = 0xFFFFFFFF;
Logic::_scriptVariables[GET_OFF] = RESET_MOUSE;
}
return true;
}
void Mouse::fnSaveCoods(void) {
Logic::_scriptVariables[SAFEX] = _mouseX + TOP_LEFT_X;
Logic::_scriptVariables[SAFEY] = _mouseY + TOP_LEFT_Y;
}
void Mouse::lockMouse(void) {
SkyEngine::_systemVars.systemFlags |= SF_MOUSE_LOCKED;
}
void Mouse::unlockMouse(void) {
SkyEngine::_systemVars.systemFlags &= ~SF_MOUSE_LOCKED;
}
void Mouse::restoreMouseData(uint16 frameNum) {
warning("Stub: Mouse::restoreMouseData");
}
void Mouse::drawNewMouse() {
warning("Stub: Mouse::drawNewMouse");
//calculateMouseValues();
//saveMouseData();
//drawMouse();
}
void Mouse::waitMouseNotPressed(void) {
bool mousePressed = true;
OSystem::Event event;
while (mousePressed) {
_system->delay_msecs(20);
while (_system->poll_event(&event)) {
if ((event.event_code == OSystem::EVENT_LBUTTONUP) ||
(event.event_code == OSystem::EVENT_QUIT))
mousePressed = false;
}
}
}
void Mouse::spriteMouse(uint16 frameNum, uint8 mouseX, uint8 mouseY) {
_currentCursor = frameNum;
byte *newCursor = _miceData;
newCursor += ((struct dataFileHeader *)_miceData)->s_sp_size * frameNum;
newCursor += sizeof(struct dataFileHeader);
uint16 mouseWidth = ((struct dataFileHeader *)_miceData)->s_width;
uint16 mouseHeight = ((struct dataFileHeader *)_miceData)->s_height;
_system->setMouseCursor(newCursor, mouseWidth, mouseHeight, mouseX, mouseY, 0);
if (frameNum == MOUSE_BLANK) _system->showMouse(false);
else _system->showMouse(true);
}
void Mouse::mouseEngine(uint16 mouseX, uint16 mouseY) {
_mouseX = mouseX;
_mouseY = mouseY;
_logicClick = (_mouseB > 0); // click signal is available for Logic for one gamecycle
if (!Logic::_scriptVariables[MOUSE_STOP]) {
if (Logic::_scriptVariables[MOUSE_STATUS] & (1 << 1)) {
pointerEngine(mouseX + TOP_LEFT_X, mouseY + TOP_LEFT_Y);
if (Logic::_scriptVariables[MOUSE_STATUS] & (1 << 2)) //buttons enabled?
buttonEngine1();
}
}
_mouseB = 0; //don't save up buttons
}
void Mouse::pointerEngine(uint16 xPos, uint16 yPos) {
uint32 currentListNum = Logic::_scriptVariables[MOUSE_LIST_NO];
uint16 *currentList;
do {
currentList = (uint16 *)SkyEngine::fetchCompact(currentListNum);
while ((*currentList != 0) && (*currentList != 0xFFFF)) {
uint16 itemNum = *currentList;
Compact *itemData = SkyEngine::fetchCompact(itemNum);
currentList++;
if ((itemData->screen == Logic::_scriptVariables[SCREEN]) && (itemData->status & 16)) {
if (itemData->xcood + ((int16)itemData->mouseRelX) > xPos) continue;
if (itemData->xcood + ((int16)itemData->mouseRelX) + itemData->mouseSizeX < xPos) continue;
if (itemData->ycood + ((int16)itemData->mouseRelY) > yPos) continue;
if (itemData->ycood + ((int16)itemData->mouseRelY) + itemData->mouseSizeY < yPos) continue;
// we've hit the item
if (Logic::_scriptVariables[SPECIAL_ITEM] == itemNum)
return;
Logic::_scriptVariables[SPECIAL_ITEM] = itemNum;
if (Logic::_scriptVariables[GET_OFF])
_skyLogic->mouseScript(Logic::_scriptVariables[GET_OFF], itemData);
Logic::_scriptVariables[GET_OFF] = itemData->mouseOff;
if (itemData->mouseOn)
_skyLogic->mouseScript(itemData->mouseOn, itemData);
return;
}
}
if (*currentList == 0xFFFF) currentListNum = currentList[1];
} while (*currentList != 0);
if (Logic::_scriptVariables[SPECIAL_ITEM] != 0) {
Logic::_scriptVariables[SPECIAL_ITEM] = 0;
if (Logic::_scriptVariables[GET_OFF])
_skyLogic->script((uint16)Logic::_scriptVariables[GET_OFF],(uint16)(Logic::_scriptVariables[GET_OFF] >> 16));
Logic::_scriptVariables[GET_OFF] = 0;
}
}
void Mouse::buttonPressed(uint8 button) {
_mouseB = button;
}
void Mouse::buttonEngine1(void) {
//checks for clicking on special item
//"compare the size of this routine to S1 mouse_button"
if (_mouseB) { //anything pressed?
Logic::_scriptVariables[BUTTON] = _mouseB;
if (Logic::_scriptVariables[SPECIAL_ITEM]) { //over anything?
Compact *item = SkyEngine::fetchCompact(Logic::_scriptVariables[SPECIAL_ITEM]);
if (item->mouseClick)
_skyLogic->mouseScript(item->mouseClick, item);
}
}
}
uint16 Mouse::findMouseCursor(uint32 itemNum) {
uint8 cnt;
for (cnt = 0; cnt < NO_MAIN_OBJECTS; cnt++) {
if (itemNum == _mouseMainObjects[cnt]) {
return cnt;
}
}
for (cnt = 0; cnt < NO_LINC_OBJECTS; cnt++) {
if (itemNum == _mouseLincObjects[cnt]) {
return cnt;
}
}
return 0;
}
void Mouse::fnOpenCloseHand(bool open) {
if ((!open) && (!Logic::_scriptVariables[OBJECT_HELD])) {
spriteMouse(1, 0, 0);
return;
}
uint16 cursor = findMouseCursor(Logic::_scriptVariables[OBJECT_HELD]) << 1;
if (open)
cursor++;
uint32 size = ((dataFileHeader*)_objectMouseData)->s_sp_size;
uint8 *srcData;
uint8 *destData;
srcData = (uint8 *)_objectMouseData + size * cursor + sizeof(dataFileHeader);
destData = (uint8 *)_miceData + sizeof(dataFileHeader);
memcpy(destData, srcData, size);
spriteMouse(0, 5, 5);
}
bool Mouse::wasClicked(void) {
if (_logicClick) {
_logicClick = false;
return true;
} else
return false;
}
} // End of namespace Sky