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