/* 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); //load in the object mouse file _objectMouseData = _skyDisk->loadFile(MICE_FILE + 1); } Mouse::~Mouse( ){ free (_miceData); free (_objectMouseData); } void Mouse::replaceMouseCursors(uint16 fileNo) { free(_objectMouseData); _objectMouseData = _skyDisk->loadFile(fileNo); } 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->delayMillis(20); while (_system->pollEvent(event)) { if ((event.type == OSystem::EVENT_LBUTTONUP) || (event.type == 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); } } } void Mouse::resetCursor() { spriteMouse(_currentCursor, 0, 0); } 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