1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 
24 #include "common/events.h"
25 #include "common/system.h"
26 #include "common/textconsole.h"
27 #include "graphics/cursorman.h"
28 #include "sky/disk.h"
29 #include "sky/logic.h"
30 #include "sky/mouse.h"
31 #include "sky/sky.h"
32 #include "sky/skydefs.h"
33 #include "sky/struc.h"
34 #include "sky/compact.h"
35 
36 namespace Sky {
37 
38 #define MICE_FILE	60300
39 #define NO_MAIN_OBJECTS	24
40 #define NO_LINC_OBJECTS	21
41 
42 uint32 Mouse::_mouseMainObjects[24] = {
43 	65,
44 	9,
45 	66,
46 	64,
47 	8,
48 	63,
49 	10,
50 	11,
51 	71,
52 	76,
53 	37,
54 	36,
55 	42,
56 	75,
57 	79,
58 	6,
59 	74,
60 	39,
61 	49,
62 	43,
63 	34,
64 	35,
65 	77,
66 	38
67 };
68 
69 uint32 Mouse::_mouseLincObjects[21] = {
70 	24625,
71 	24649,
72 	24827,
73 	24651,
74 	24583,
75 	24581,
76 	24582,
77 	24628,
78 	24650,
79 	24629,
80 	24732,
81 	24631,
82 	24584,
83 	24630,
84 	24626,
85 	24627,
86 	24632,
87 	24643,
88 	24828,
89 	24830,
90 	24829
91 };
92 
Mouse(OSystem * system,Disk * skyDisk,SkyCompact * skyCompact)93 Mouse::Mouse(OSystem *system, Disk *skyDisk, SkyCompact *skyCompact) {
94 	_skyDisk = skyDisk;
95 	_skyCompact = skyCompact;
96 	_system = system;
97 	_mouseB = 0;
98 	_currentCursor = 6;
99 	_mouseX = GAME_SCREEN_WIDTH / 2;
100 	_mouseY = GAME_SCREEN_HEIGHT / 2;
101 
102 	_miceData = _skyDisk->loadFile(MICE_FILE);
103 
104 	//load in the object mouse file
105 	_objectMouseData = _skyDisk->loadFile(MICE_FILE + 1);
106 }
107 
~Mouse()108 Mouse::~Mouse( ){
109 	free (_miceData);
110 	free (_objectMouseData);
111 }
112 
replaceMouseCursors(uint16 fileNo)113 void Mouse::replaceMouseCursors(uint16 fileNo) {
114 	free(_objectMouseData);
115 	_objectMouseData = _skyDisk->loadFile(fileNo);
116 }
117 
fnAddHuman()118 bool Mouse::fnAddHuman() {
119 	//reintroduce the mouse so that the human can control the player
120 	//could still be switched out at high-level
121 
122 	if (!Logic::_scriptVariables[MOUSE_STOP]) {
123 		Logic::_scriptVariables[MOUSE_STATUS] |= 6;	//cursor & mouse
124 
125 		if (_mouseY < 2) //stop mouse activating top line
126 			_mouseY = 2;
127 
128 		_system->warpMouse(_mouseX, _mouseY);
129 
130 		//force the pointer engine into running a get-off
131 		//even if it's over nothing
132 
133 		//KWIK-FIX
134 		//get off may contain script to remove mouse pointer text
135 		//surely this script should be run just in case
136 		//I am going to try it anyway
137 		if (Logic::_scriptVariables[GET_OFF])
138 			_skyLogic->script((uint16)Logic::_scriptVariables[GET_OFF],(uint16)(Logic::_scriptVariables[GET_OFF] >> 16));
139 
140 		Logic::_scriptVariables[SPECIAL_ITEM] = 0xFFFFFFFF;
141 		Logic::_scriptVariables[GET_OFF] = RESET_MOUSE;
142 	}
143 
144 	return true;
145 }
146 
fnSaveCoods()147 void Mouse::fnSaveCoods() {
148 	Logic::_scriptVariables[SAFEX] = _mouseX + TOP_LEFT_X;
149 	Logic::_scriptVariables[SAFEY] = _mouseY + TOP_LEFT_Y;
150 }
151 
lockMouse()152 void Mouse::lockMouse() {
153 	SkyEngine::_systemVars.systemFlags |= SF_MOUSE_LOCKED;
154 }
155 
unlockMouse()156 void Mouse::unlockMouse() {
157 	SkyEngine::_systemVars.systemFlags &= ~SF_MOUSE_LOCKED;
158 }
159 
restoreMouseData(uint16 frameNum)160 void Mouse::restoreMouseData(uint16 frameNum) {
161 	warning("Stub: Mouse::restoreMouseData");
162 }
163 
drawNewMouse()164 void Mouse::drawNewMouse() {
165 	warning("Stub: Mouse::drawNewMouse");
166 	//calculateMouseValues();
167 	//saveMouseData();
168 	//drawMouse();
169 }
170 
waitMouseNotPressed(int minDelay)171 void Mouse::waitMouseNotPressed(int minDelay) {
172 	bool mousePressed = true;
173 	uint32 now = _system->getMillis();
174 	Common::Event event;
175 	Common::EventManager *eventMan = _system->getEventManager();
176 	while (mousePressed || _system->getMillis() < now + minDelay) {
177 
178 		if (eventMan->shouldQuit()) {
179 			minDelay = 0;
180 			mousePressed = false;
181 		}
182 
183 		if (!eventMan->getButtonState())
184 			mousePressed = false;
185 
186 		while (eventMan->pollEvent(event)) {
187 			switch (event.type) {
188 			case Common::EVENT_KEYDOWN:
189 				if (event.kbd.keycode == Common::KEYCODE_ESCAPE) {
190 					minDelay = 0;
191 					mousePressed = false;
192 				}
193 				break;
194 			default:
195 				break;
196 			}
197 		}
198 		_system->updateScreen();
199 		_system->delayMillis(20);
200 	}
201 }
202 
spriteMouse(uint16 frameNum,uint8 mouseX,uint8 mouseY)203 void Mouse::spriteMouse(uint16 frameNum, uint8 mouseX, uint8 mouseY) {
204 	_currentCursor = frameNum;
205 
206 	byte *newCursor = _miceData;
207 	newCursor += ((DataFileHeader *)_miceData)->s_sp_size * frameNum;
208 	newCursor += sizeof(DataFileHeader);
209 
210 	uint16 mouseWidth = ((DataFileHeader *)_miceData)->s_width;
211 	uint16 mouseHeight = ((DataFileHeader *)_miceData)->s_height;
212 
213 	CursorMan.replaceCursor(newCursor, mouseWidth, mouseHeight, mouseX, mouseY, 0);
214 	if (frameNum == MOUSE_BLANK)
215 		CursorMan.showMouse(false);
216 	else
217 		CursorMan.showMouse(true);
218 }
219 
mouseEngine()220 void Mouse::mouseEngine() {
221 	_logicClick = (_mouseB > 0); // click signal is available for Logic for one gamecycle
222 
223 	if (!Logic::_scriptVariables[MOUSE_STOP]) {
224 		if (Logic::_scriptVariables[MOUSE_STATUS] & (1 << 1)) {
225 			pointerEngine(_mouseX + TOP_LEFT_X, _mouseY + TOP_LEFT_Y);
226 			if (Logic::_scriptVariables[MOUSE_STATUS] & (1 << 2)) //buttons enabled?
227 				buttonEngine1();
228 		}
229 	}
230 	_mouseB = 0;	//don't save up buttons
231 }
232 
pointerEngine(uint16 xPos,uint16 yPos)233 void Mouse::pointerEngine(uint16 xPos, uint16 yPos) {
234 	uint32 currentListNum = Logic::_scriptVariables[MOUSE_LIST_NO];
235 	uint16 *currentList;
236 	do {
237 		currentList = (uint16 *)_skyCompact->fetchCpt(currentListNum);
238 		while ((*currentList != 0) && (*currentList != 0xFFFF)) {
239 			uint16 itemNum = *currentList;
240 			Compact *itemData = _skyCompact->fetchCpt(itemNum);
241 			currentList++;
242 			if ((itemData->screen == Logic::_scriptVariables[SCREEN]) && (itemData->status & 16)) {
243 				if (itemData->xcood + ((int16)itemData->mouseRelX) > xPos) continue;
244 				if (itemData->xcood + ((int16)itemData->mouseRelX) + itemData->mouseSizeX < xPos) continue;
245 				if (itemData->ycood + ((int16)itemData->mouseRelY) > yPos) continue;
246 				if (itemData->ycood + ((int16)itemData->mouseRelY) + itemData->mouseSizeY < yPos) continue;
247 				// we've hit the item
248 				if (Logic::_scriptVariables[SPECIAL_ITEM] == itemNum)
249 					return;
250 				Logic::_scriptVariables[SPECIAL_ITEM] = itemNum;
251 				if (Logic::_scriptVariables[GET_OFF])
252 					_skyLogic->mouseScript(Logic::_scriptVariables[GET_OFF], itemData);
253 				Logic::_scriptVariables[GET_OFF] = itemData->mouseOff;
254 				if (itemData->mouseOn)
255 					_skyLogic->mouseScript(itemData->mouseOn, itemData);
256 				return;
257 			}
258 		}
259 		if (*currentList == 0xFFFF)
260 			currentListNum = currentList[1];
261 	} while (*currentList != 0);
262 	if (Logic::_scriptVariables[SPECIAL_ITEM] != 0) {
263 		Logic::_scriptVariables[SPECIAL_ITEM] = 0;
264 
265 		if (Logic::_scriptVariables[GET_OFF])
266 			_skyLogic->script((uint16)Logic::_scriptVariables[GET_OFF],(uint16)(Logic::_scriptVariables[GET_OFF] >> 16));
267 		Logic::_scriptVariables[GET_OFF] = 0;
268 	}
269 }
270 
buttonPressed(uint8 button)271 void Mouse::buttonPressed(uint8 button) {
272 	_mouseB = button;
273 }
274 
mouseMoved(uint16 mouseX,uint16 mouseY)275 void Mouse::mouseMoved(uint16 mouseX, uint16 mouseY) {
276 	_mouseX = mouseX;
277 	_mouseY = mouseY;
278 }
279 
buttonEngine1()280 void Mouse::buttonEngine1() {
281 	//checks for clicking on special item
282 	//"compare the size of this routine to S1 mouse_button"
283 
284 	if (_mouseB) {	//anything pressed?
285 		Logic::_scriptVariables[BUTTON] = _mouseB;
286 		if (Logic::_scriptVariables[SPECIAL_ITEM]) { //over anything?
287 			Compact *item = _skyCompact->fetchCpt(Logic::_scriptVariables[SPECIAL_ITEM]);
288 			if (item->mouseClick)
289 				_skyLogic->mouseScript(item->mouseClick, item);
290 		}
291 	}
292 }
293 
resetCursor()294 void Mouse::resetCursor() {
295 	spriteMouse(_currentCursor, 0, 0);
296 }
297 
findMouseCursor(uint32 itemNum)298 uint16 Mouse::findMouseCursor(uint32 itemNum) {
299 	uint8 cnt;
300 	for (cnt = 0; cnt < NO_MAIN_OBJECTS; cnt++) {
301 		if (itemNum == _mouseMainObjects[cnt]) {
302 			return cnt;
303 		}
304 	}
305 	for (cnt = 0; cnt < NO_LINC_OBJECTS; cnt++) {
306 		if (itemNum == _mouseLincObjects[cnt]) {
307 			return cnt;
308 		}
309 	}
310 	return 0;
311 }
312 
fnOpenCloseHand(bool open)313 void Mouse::fnOpenCloseHand(bool open) {
314 	if ((!open) && (!Logic::_scriptVariables[OBJECT_HELD])) {
315 		spriteMouse(1, 0, 0);
316 		return;
317 	}
318 	uint16 cursor = findMouseCursor(Logic::_scriptVariables[OBJECT_HELD]) << 1;
319 	if (open)
320 		cursor++;
321 
322 	uint32 size = ((DataFileHeader *)_objectMouseData)->s_sp_size;
323 	uint8 *srcData;
324 	uint8 *destData;
325 
326 	srcData = (uint8 *)_objectMouseData + size * cursor + sizeof(DataFileHeader);
327 	destData = (uint8 *)_miceData + sizeof(DataFileHeader);
328 	memcpy(destData, srcData, size);
329 	spriteMouse(0, 5, 5);
330 }
331 
wasClicked()332 bool Mouse::wasClicked() {
333 	if (_logicClick) {
334 		_logicClick = false;
335 		return true;
336 	} else
337 		return false;
338 }
339 
340 } // End of namespace Sky
341