1 /*
2  * Seven Kingdoms: Ancient Adversaries
3  *
4  * Copyright 1997,1998 Enlight Software Ltd.
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 //Filename    : OMOUSECR.CPP
22 //Description : Object Cursor Resource
23 
24 #include <ALL.h>
25 #include <OVGA.h>
26 #include <OSYS.h>
27 #include <OWORLD.h>
28 #include <ODB.h>
29 #include <OMOUSE.h>
30 #include <OMOUSECR.h>
31 
32 //---------- define constant ------------//
33 
34 #define CURSOR_DBF  	DIR_RES"CURSOR.RES"
35 
36 //---------- Begin of function MouseCursor::MouseCursor --------//
37 
MouseCursor()38 MouseCursor::MouseCursor()
39 {
40 	init_flag = 0;
41 	hide_all_flag = 0;
42 	hide_area_flag = 0;
43 	cur_icon = 0;
44 	hide_x1 = hide_y1 = hide_x2 = hide_y2 = 0;
45 	cur_x1 = cur_y1 = cur_x2 = cur_y2 = 0;
46 	hot_spot_x = hot_spot_y = 0;
47 	icon_width = 0;
48 	icon_height = 0;
49 	cursor_shown = 0;
50 	processing_flag = 0;
51 	wait_mode_count = 0;
52 	icon_ptr = icon_data_ptr = NULL;
53 	save_scr = save_back_scr = merge_buf = NULL;
54 	frame_flag = 0;
55 	frame_shown = 0;
56 	frame_x1 = frame_y1 = frame_x2 = frame_y2 = 0;
57 	frame_origin_x = frame_origin_y = 0;
58 	frame_border_x1 = frame_border_y1 = frame_border_x2 = frame_border_y2 = 0;
59 	memset(frame_top_save_scr, 0, VGA_WIDTH + 4);
60 	memset(frame_bottom_save_scr, 0, VGA_WIDTH + 4);
61 	memset(frame_left_save_scr, 0, VGA_HEIGHT + 4);
62 	memset(frame_right_save_scr, 0, VGA_HEIGHT + 4);
63 	cursor_count = 0;
64 	cursor_info_array = NULL;
65 }
66 //----------- End of function MouseCursor::MouseCursor ------//
67 
68 
69 //---------- Begin of function MouseCursor::~MouseCursor --------//
70 
~MouseCursor()71 MouseCursor::~MouseCursor()
72 {
73 	deinit();
74 }
75 //----------- End of function MouseCursor::~MouseCursor ------//
76 
77 
78 //---------- Begin of function MouseCursor::init --------//
79 //
init()80 void MouseCursor::init()
81 {
82 	//----- open plant material bitmap resource file -------//
83 
84 	String str;
85 
86 	str  = DIR_RES;
87 	str += "I_CURSOR.RES";
88 
89 	res_bitmap.init_imported(str,1);  // 1-read all into buffer
90 
91 	//------- load database information --------//
92 
93 	load_cursor_info();
94 
95 	init_flag=1;
96 }
97 //----------- End of function MouseCursor::init ------//
98 
99 
100 //---------- Begin of function MouseCursor::deinit --------//
101 
deinit()102 void MouseCursor::deinit()
103 {
104 	if( init_flag )
105 	{
106 		mem_del(cursor_info_array);
107 
108 		if( save_scr )
109 		{
110 			mem_del( save_scr );
111 			save_scr = NULL;
112 		}
113 
114 		if( save_back_scr )
115 		{
116 			mem_del( save_back_scr );
117 			save_back_scr = NULL;
118 		}
119 
120 		if( merge_buf )		// buffer for merging save screen from the front and back buffers
121 		{
122 			mem_del( merge_buf );
123 			merge_buf = NULL;
124 		}
125 
126 		init_flag = 0;
127 		icon_ptr  = NULL;
128 		// ###### begin Gilbert 18/8 #####//
129 		cur_icon = 0;
130 		// ###### end Gilbert 18/8 #####//
131 	}
132 }
133 //----------- End of function MouseCursor::deinit ------//
134 
135 
136 //------- Begin of function MouseCursor::load_cursor_info -------//
137 //
load_cursor_info()138 void MouseCursor::load_cursor_info()
139 {
140 	CursorRec  		*cursorRec;
141 	CursorInfo     *cursorInfo;
142 	int      		i;
143 	uint32_t			bitmapOffset;
144 	Database 		dbCursor(CURSOR_DBF, 1);		// 1-read all into the buffer
145 
146 	cursor_count = (short) dbCursor.rec_count();
147 	cursor_info_array = (CursorInfo*) mem_add( sizeof(CursorInfo)*cursor_count );
148 
149 	//-------- read in PLANTBMP.DBF -------//
150 
151 	memset( cursor_info_array, 0, sizeof(CursorInfo) * cursor_count );
152 
153 	for( i=0 ; i<cursor_count ; i++ )
154 	{
155 		cursorRec  = (CursorRec*) dbCursor.read(i+1);
156 		cursorInfo = cursor_info_array+i;
157 
158 		memcpy( &bitmapOffset, cursorRec->bitmap_ptr, sizeof(uint32_t) );
159 
160 		cursorInfo->bitmap_ptr = res_bitmap.read_imported(bitmapOffset);
161 
162 		cursorInfo->hot_spot_x = misc.atoi( cursorRec->hot_spot_x, cursorRec->HOT_SPOT_LEN );
163 		cursorInfo->hot_spot_y = misc.atoi( cursorRec->hot_spot_y, cursorRec->HOT_SPOT_LEN );
164 	}
165 }
166 //--------- End of function MouseCursor::load_cursor_info ---------//
167 
168 
169 //--------- Begin of function MouseCursor::set_icon ------------//
170 //
171 // Set the bitmap of the mouse cursor
172 //
173 // <int> cursorId = id. of the cursor
174 //
set_icon(int cursorId)175 void MouseCursor::set_icon(int cursorId)
176 {
177 	if( !init_flag )
178 		return;
179 
180 	//-------- hide the cursor first ----------//
181 
182 	int hideAllFlag = hide_all_flag;
183 
184 	if( !hideAllFlag )     // if the mouse has been hiden before, don't hide and show it
185 		mouse.hide();
186 
187 	//------------ set cursor icon ------------//
188 
189 	CursorInfo* cursorInfo = cursor_info_array+cursorId-1;
190 
191 	icon_ptr   = cursorInfo->bitmap_ptr;
192 	hot_spot_x = cursorInfo->hot_spot_x;
193 	hot_spot_y = cursorInfo->hot_spot_y;
194 
195 	err_when( !icon_ptr );
196 
197 	icon_width  = *((short*)icon_ptr);
198 	icon_height = *((short*)icon_ptr+1);
199 
200 	// ###### begin Gilbert 18/8 #####//
201 	cur_icon = cursorId;
202 	// ###### end Gilbert 18/8 #####//
203 
204 	//------- allocate buffer for screen saving ------//
205 
206 	save_scr  		= mem_resize( save_scr 		, icon_width*icon_height+sizeof(short)*2 );		// sizeof(short)*2 is the header for storing width and height info
207 	save_back_scr  = mem_resize( save_back_scr, icon_width*icon_height+sizeof(short)*2 );		// sizeof(short)*2 is the header for storing width and height info
208 	merge_buf 		= mem_resize( merge_buf	 	, icon_width*icon_height+sizeof(short)*2 );		// sizeof(short)*2 is the header for storing width and height info
209 
210 	//------------ redisplay cursor -----------//
211 
212 	if( !hideAllFlag )
213 		mouse.show();
214 }
215 //----------- End of function MouseCursor::set_icon -------------//
216 
217 
218 //----------- Begin of function MouseCursor::set_frame --------//
219 //
220 // <char> frameFlag  - frame flag
221 // [char] buildTrack - treat the frame as a line for building track,
222 //							  also align the frame's position to locations.
223 //							  (default:0)
224 //
set_frame(char frameFlag,char buildTrack)225 void MouseCursor::set_frame(char frameFlag, char buildTrack)
226 {
227 	if( frame_flag == frameFlag )
228 		return;
229 
230 	frame_flag  = frameFlag;
231 	frame_shown = 0;
232 }
233 //----------- End of function MouseCursor::set_frame -------//
234 
235 
236 //----------- Begin of function MouseCursor::set_frame_border --------//
237 
set_frame_border(int borderX1,int borderY1,int borderX2,int borderY2)238 void MouseCursor::set_frame_border(int borderX1, int borderY1, int borderX2, int borderY2)
239 {
240 	frame_border_x1 = borderX1;
241 	frame_border_y1 = borderY1;
242 	frame_border_x2 = borderX2;
243 	frame_border_y2 = borderY2;
244 }
245 //----------- End of function MouseCursor::set_frame_border -------//
246 
247 
248 //----------- Begin of function MouseCursor::process --------//
249 
process(int curX,int curY)250 void MouseCursor::process(int curX, int curY)
251 {
252 	if( processing_flag || !icon_ptr)   // it is being nested call by interrupt
253 		return;                          // when another instance of process is
254 													// being run.
255 	processing_flag = 1;    				// Prevent nested call
256 
257 	//---------- store screen area ------------//
258 
259 	if( cursor_shown )
260 	{
261 		// restore screen previously saved
262 		int save_x1, save_x2, save_y1, save_y2;
263 
264 		save_x1 = MAX(cur_x1, 0);
265 		save_y1 = MAX(cur_y1, 0);
266 		save_x2 = MIN(cur_x2, VGA_WIDTH-1);
267 		save_y2 = MIN(cur_y2, VGA_HEIGHT-1);
268 
269 		if ( save_x1 < save_x2 && save_y1 < save_y2 )
270 		{
271 			vga_front.put_bitmap_area_trans( save_x1,
272 							 save_y1,
273 							 save_scr,
274 							 save_x1-cur_x1,
275 							 save_y1-cur_y1,
276 							 save_x2-cur_x1,
277 							 save_y2-cur_y1 );
278 		}
279 	}
280 
281 	//---- only the zoom map can be framed, limit the frame inside that area ----//
282 
283 	if( frame_flag )
284 	{
285 		curX = MAX(curX, ZOOM_X1);
286 		curY = MAX(curY, ZOOM_Y1);
287 		curX = MIN(curX, ZOOM_X2);
288 		curY = MIN(curY, ZOOM_Y2);
289 
290 		process_frame(curX, curY);
291 	}
292 
293 	//------- update cursor postions ----------//
294 
295 	cur_x1 = curX - hot_spot_x;		// handle the offset of the hot site
296 	cur_y1 = curY - hot_spot_y;
297 	cur_x2 = cur_x1 + icon_width  - 1;
298 	cur_y2 = cur_y1 + icon_height - 1;
299 
300 	//------- save screen and put cursor -------//
301 
302 	if( hide_all_flag || ( hide_area_flag &&
303 		 is_touch( hide_x1, hide_y1, hide_x2, hide_y2 ) ) )
304 	{
305 		cursor_shown = 0;
306 	}
307 	else
308 	{
309 		/* Save the screen underneath the cursor
310 		 * where it will be drawn.
311 		 */
312 		int save_x1, save_x2, save_y1, save_y2;
313 
314 		save_x1 = MAX(cur_x1, 0);
315 		save_y1 = MAX(cur_y1, 0);
316 		save_x2 = MIN(cur_x2, VGA_WIDTH-1);
317 		save_y2 = MIN(cur_y2, VGA_HEIGHT-1);
318 
319 		if ( save_x1 < save_x2 && save_y1 < save_y2 ) {
320 			vga_front.read_bitmap( save_x1, save_y1,
321 					       save_x2, save_y2, save_scr );
322 			vga_front.put_bitmap_area_trans( save_x1,
323 							 save_y1,
324 							 icon_ptr,
325 							 save_x1-cur_x1,
326 							 save_y1-cur_y1,
327 							 save_x2-cur_x1,
328 							 save_y2-cur_y1 );
329 
330 			cursor_shown = 1;
331 		}
332 	}
333 
334 	//------------------------------------------//
335 
336 	processing_flag = 0;     // cancel prevention of nested call
337 }
338 //----------- End of function MouseCursor::process -------//
339 
340 
341 //-------- Begin of function MouseCursor::process_frame --------//
342 
process_frame(int curX,int curY)343 void MouseCursor::process_frame(int curX, int curY)
344 {
345 	//---- restore the screen area overwritten by the last frame ---//
346 
347 	if( frame_shown )
348 	{
349 		vga_front.fast_put_bitmap( frame_x1, frame_y1, frame_top_save_scr    );
350 		vga_front.fast_put_bitmap( frame_x1, frame_y2, frame_bottom_save_scr );
351 		vga_front.fast_put_bitmap( frame_x1, frame_y1, frame_left_save_scr   );
352 		vga_front.fast_put_bitmap( frame_x2, frame_y1, frame_right_save_scr  );
353 	}
354 
355 	//---------- update frame position ----------//
356 
357 	if( !frame_shown )			// a new frame
358 	{
359 		frame_origin_x = curX;
360 		frame_origin_y = curY;
361 
362 		frame_x1 = curX;
363 		frame_y1 = curY;
364 		frame_x2 = curX;
365 		frame_y2 = curY;
366 	}
367 	else  	// update the postion of the existing frame
368 	{
369 		//---------- update frame position ----------//
370 
371 		if( curX > frame_origin_x )
372 		{
373 			if( curY > frame_origin_y )		// stretching towards the lower right end
374 			{
375 				frame_x1 = frame_origin_x;
376 				frame_y1 = frame_origin_y;
377 				frame_x2 = curX;
378 				frame_y2 = curY;
379 			}
380 			else		// stretching towards the upper right end
381 			{
382 				frame_x1 = frame_origin_x;
383 				frame_y1 = curY;
384 				frame_x2 = curX;
385 				frame_y2 = frame_origin_y;
386 			}
387 		}
388 		else
389 		{
390 			if( curY > frame_origin_y )		// stretching towards the lower left end
391 			{
392 				frame_x1 = curX;
393 				frame_y1 = frame_origin_y;
394 				frame_x2 =	frame_origin_x;
395 				frame_y2 = curY;
396 			}
397 			else		// stretching towards the upper left end
398 			{
399 				frame_x1 = curX;
400 				frame_y1 = curY;
401 				frame_x2 = frame_origin_x;
402 				frame_y2 = frame_origin_y;
403 			}
404 		}
405 	}
406 
407 	//------- save the screen area and display the frame ------//
408 
409 	disp_frame(&vga_front);
410 }
411 //----------- End of function MouseCursor::process_frame -------//
412 
413 
414 //----------- Begin of function MouseCursor::disp_frame --------//
415 
disp_frame(VgaBuf * vgaBufPtr)416 void MouseCursor::disp_frame(VgaBuf* vgaBufPtr)
417 {
418 	//------- save the screen area that will be overwriteen -------//
419 
420 	vgaBufPtr->read_bitmap( frame_x1, frame_y1, frame_x2, frame_y1, frame_top_save_scr );
421 	vgaBufPtr->read_bitmap( frame_x1, frame_y2, frame_x2, frame_y2, frame_bottom_save_scr );
422 	vgaBufPtr->read_bitmap( frame_x1, frame_y1, frame_x1, frame_y2, frame_left_save_scr );
423 	vgaBufPtr->read_bitmap( frame_x2, frame_y1, frame_x2, frame_y2, frame_right_save_scr );
424 
425 	//---------- draw the rectagular frame now -----------//
426 
427 	vgaBufPtr->rect( frame_x1, frame_y1, frame_x2, frame_y2, 1, OWN_SELECT_FRAME_COLOR );
428 
429 	//---------- set frame flag ----------//
430 
431 	frame_shown = 1;
432 }
433 //----------- End of function MouseCursor::disp_frame -------//
434 
435 
436 //----------- Begin of function MouseCursor::disp_back_buf --------//
437 //
438 // Display the mouse cursor on the back buffer.
439 //
disp_back_buf(int bltX1,int bltY1,int bltX2,int bltY2)440 void MouseCursor::disp_back_buf(int bltX1, int bltY1, int bltX2, int bltY2)
441 {
442 	if( !icon_ptr )
443 		return;
444 
445 	//-------- display frame on the back buffer ----//
446 
447 	if( frame_flag )
448 		disp_frame(&vga_back);
449 
450 	//----- display mouse cursor on the back buffer ----//
451 
452 	if( is_touch(bltX1, bltY1, bltX2, bltY2) )
453 	{
454 		//--- save the front buffer area which will be overwritten ---//
455 
456 		int x1 = MAX(cur_x1,bltX1);
457 		int y1 = MAX(cur_y1,bltY1);
458 		int x2 = MIN(cur_x2,bltX2);
459 		int y2 = MIN(cur_y2,bltY2);
460 
461 		vga_back.read_bitmap( x1, y1, x2, y2, save_back_scr );
462 
463 		//--- merge the save area of the back buf with the front buf's save area ---//
464 
465 		// save_scr width  : MIN(cur_x2,VGA_WIDTH-1) -MAX(cur_x1,0)+1;
466 		// save_scr height : MIN(cur_y2,VGA_HEIGHT-1)-MAX(cur_y1,0)+1;
467 
468 		IMGblt( save_scr+4, MIN(cur_x2,VGA_WIDTH-1) -MAX(cur_x1,0)+1, x1-MAX(cur_x1,0), y1-MAX(cur_y1,0), save_back_scr );		// +4 is the width & height info
469 
470 		//--------- display the mouse cursor now -----------//
471 
472 		if( cur_x1 < bltX1 || cur_x2 > bltX2 || cur_y1 < bltY1 || cur_y2 > bltY2 )
473 		{
474 			vga_back.put_bitmap_area_trans( cur_x1, cur_y1, icon_ptr,
475 				MAX(bltX1,cur_x1)-cur_x1, MAX(bltY1,cur_y1)-cur_y1,
476 				MIN(bltX2,cur_x2)-cur_x1, MIN(bltY2,cur_y2)-cur_y1 );
477 		}
478 
479 		//---- the whole sprite is inside the view area ------//
480 
481 		else
482 		{
483 			vga_back.put_bitmap_trans(cur_x1, cur_y1, icon_ptr);
484 		}
485 
486 		cursor_shown = 1;
487 	}
488 }
489 //----------- End of function MouseCursor::disp_back_buf -------//
490 
491 
492 //--------- Begin of function MouseCursor::is_touch ------------//
493 //
494 // Check if the given area touch the area defined by cur_??.
495 //
496 // Return : 1 or 0
497 //
is_touch(int x1,int y1,int x2,int y2)498 int MouseCursor::is_touch(int x1, int y1, int x2, int y2)
499 {
500 	return (( cur_y1 <=  y1 && cur_y2 >=  y1 ) ||
501 			  (  y1 <= cur_y1 &&  y2 >= cur_y1 )) &&
502 			 (( cur_x1 <=  x1 && cur_x2 >=  x1 ) ||
503 			  (  x1 <= cur_x1 &&  x2 >= cur_x1 ));
504 }
505 //--------- End of function MouseCursor::is_touch -----------//
506 
507 
508 // ####### begin Gilbert 18/8 ########//
509 //--------- Begin of function MouseCursor::restore_icon ------------//
restore_icon(int newCursorId)510 void MouseCursor::restore_icon(int newCursorId)
511 {
512 	if( newCursorId == 0)
513 	{
514 		err_here();
515 
516 		// should restore to invisible cursor ?
517 		if( !hide_all_flag )
518 			mouse.hide();
519 		cur_icon = 0;
520 		icon_ptr = NULL;
521 	}
522 	else if( cur_icon == 0 || newCursorId != cur_icon )
523 	{
524 		set_icon(newCursorId);
525 	}
526 }
527 //--------- End of function MouseCursor::restore_icon ------------//
528 // ####### end Gilbert 18/8 ########//
529