1 /*
2 * OpenBOR - http://www.LavaLit.com
3 * -----------------------------------------------------------------------
4 * All rights reserved, see LICENSE in OpenBOR root for details.
5 *
6 * Copyright (c) 2004 - 2011 OpenBOR Team
7 */
8
9 ///////////////////////////////////////////////////////////////////////////
10 // This file defines some commmon methods used by the gamelib
11 ////////////////////////////////////////////////////////////////////////////
12 #include <assert.h>
13 #include "globals.h"
14 #include "types.h"
15 #include "transform.h"
16
17 static transpixelfunc pfp;
18 static unsigned int fillcolor;
19 static blend16fp pfp16;
20 static blend32fp pfp32;
21 static unsigned char *table;
22 static unsigned char *remaptable;
23 static int transbg;
24 int trans_sw, trans_sh, trans_dw, trans_dh;
25 static void (*drawfp)(s_screen *dest, gfx_entry *src, int dx, int dy, int sx, int sy);
26
27 static s_screen *handle_dest;
28
29 static int y_dest;
30 static int x_dest;
31 static int span_dest;
32
33 static unsigned char *ptr_dest;
34 static unsigned char *cur_dest;
35
36 static gfx_entry *handle_src;
37
38 static int y_src;
39 static int x_src;
40 static int span_src;
41
42 static unsigned char *ptr_src;
43 static unsigned char *cur_src;
44 static unsigned char dummyptrs[8] = {0, 0, 0, 0, 0, 0, 0, 0};
45 //static unsigned char dummyptrd[8] = {0,0,0,0,0,0,0,0};
46 static unsigned char *cur_spr; // for sprite only
47
48 static int spf, dpf, dpb, spb; //pixelformat
49
50 static int wpcond;
51
52 static int xmin, xmax, ymin, ymax;
53
54
55 /*transpixelfunc, 8bit*/
remapcolor(unsigned char * unusedt,unsigned char color,unsigned char unused)56 static unsigned char remapcolor(unsigned char *unusedt, unsigned char color, unsigned char unused)
57 {
58 return remaptable[color];
59 }
60
blendcolor(unsigned char * t,unsigned char color1,unsigned char color2)61 static unsigned char blendcolor(unsigned char *t, unsigned char color1, unsigned char color2)
62 {
63 if(remaptable)
64 {
65 color1 = remaptable[color1];
66 }
67 if(!t)
68 {
69 return color1;
70 }
71 return t[color1 << 8 | color2];
72 }
73
blendfillcolor(unsigned char * t,unsigned char unused,unsigned char color)74 static unsigned char blendfillcolor(unsigned char *t, unsigned char unused, unsigned char color)
75 {
76 if(!t)
77 {
78 return fillcolor;
79 }
80 return t[fillcolor << 8 | color];
81 }
82
83
84 /**
85
86 draw a pixel from source gfx surface to destination screen
87 complex
88
89 */
90
draw_pixel_dummy(s_screen * dest,gfx_entry * src,int dx,int dy,int sx,int sy)91 void draw_pixel_dummy(s_screen *dest, gfx_entry *src, int dx, int dy, int sx, int sy)
92 {
93 unsigned char *pd = ((unsigned char *)(dest->data)) + (dx + dy * dest->width) * dpb;
94 memset(pd, 0, dpb);
95 }
96
draw_pixel_screen(s_screen * dest,gfx_entry * src,int dx,int dy,int sx,int sy)97 void draw_pixel_screen(s_screen *dest, gfx_entry *src, int dx, int dy, int sx, int sy)
98 {
99 unsigned char *ptrd8, *ptrs8, ps8;
100 unsigned short *ptrd16, *ptrs16, pd16, ps16;
101 unsigned int *ptrd32, *ptrs32, pd32, ps32;
102 switch(dest->pixelformat)
103 {
104 case PIXEL_8:
105 ps8 = *(((unsigned char *)src->screen->data) + sx + sy * src->screen->width);
106 if(transbg && !ps8)
107 {
108 return;
109 }
110 else if(fillcolor)
111 {
112 ps8 = fillcolor;
113 }
114 ptrd8 = ((unsigned char *)dest->data) + dx + dy * dest->width;
115 *ptrd8 = pfp ? pfp(table, ps8, *ptrd8) : ps8;
116 break;
117 case PIXEL_16:
118 ptrd16 = ((unsigned short *)dest->data) + dx + dy * dest->width;
119 pd16 = *ptrd16;
120 switch(src->screen->pixelformat)
121 {
122 case PIXEL_16:
123 ptrs16 = ((unsigned short *)src->screen->data) + sx + sy * src->screen->width;
124 ps16 = *ptrs16;
125 if(transbg && !ps16)
126 {
127 return;
128 }
129 break;
130 case PIXEL_x8:
131 ptrs8 = ((unsigned char *)src->screen->data) + sx + sy * src->screen->width;
132 if(transbg && !*ptrs8)
133 {
134 return;
135 }
136 ps16 = table ? ((unsigned short *)table)[*ptrs8] : ((unsigned short *)src->screen->palette)[*ptrs8];
137 break;
138 default:
139 return;
140 }
141 if(fillcolor)
142 {
143 ps16 = fillcolor;
144 }
145 if(!pfp16)
146 {
147 *ptrd16 = ps16;
148 }
149 else
150 {
151 *ptrd16 = pfp16(ps16, pd16);
152 }
153 break;
154 case PIXEL_32:
155 ptrd32 = ((unsigned int *)dest->data) + dx + dy * dest->width;
156 pd32 = *ptrd32;
157 switch(src->screen->pixelformat)
158 {
159 case PIXEL_32:
160 ptrs32 = ((unsigned int *)src->screen->data) + sx + sy * src->screen->width;
161 ps32 = *ptrs32;
162 if(transbg && !ps32)
163 {
164 return;
165 }
166 break;
167 case PIXEL_x8:
168 ptrs8 = ((unsigned char *)src->screen->data) + sx + sy * src->screen->width;
169 if(transbg && !*ptrs8)
170 {
171 return;
172 }
173 ps32 = table ? ((unsigned int *)table)[*ptrs8] : ((unsigned int *)src->screen->palette)[*ptrs8];
174 break;
175 default:
176 return;
177 }
178 if(fillcolor)
179 {
180 ps32 = fillcolor;
181 }
182 if(!pfp32)
183 {
184 *ptrd32 = ps32;
185 }
186 else
187 {
188 *ptrd32 = pfp32(ps32, pd32);
189 }
190 break;
191
192 }
193 }
194
195
draw_pixel_bitmap(s_screen * dest,gfx_entry * src,int dx,int dy,int sx,int sy)196 void draw_pixel_bitmap(s_screen *dest, gfx_entry *src, int dx, int dy, int sx, int sy)
197 {
198 //stub
199 // should be OK for now since s_screen and s_bitmap are identical to each other
200 assert(sizeof(s_screen) != sizeof(s_bitmap));
201 draw_pixel_screen(dest, src, dx, dy, sx, sy);
202 }
203
204 // get a pixel from specific sprite
205 // should be fairly slow due to the RLE compression
sprite_get_pixel(s_sprite * sprite,int x,int y)206 char sprite_get_pixel(s_sprite *sprite, int x, int y)
207 {
208 int *linetab;
209 register int lx = 0, count;
210 unsigned char *data;
211
212 //should we check?
213 //if(y<0 || y>=sprite->height || x<0 || x>=sprite->width)
214 // return 0;
215
216
217 linetab = ((int *)sprite->data) + y;
218
219 data = ((unsigned char *)linetab) + (*linetab);
220
221 while(1)
222 {
223 count = *data++;
224 if(count == 0xFF)
225 {
226 return 0;
227 }
228 if(lx + count > x)
229 {
230 return 0; // transparent pixel
231 }
232 lx += count;
233 count = *data++;
234 if(!count)
235 {
236 continue;
237 }
238 if(lx + count > x)
239 {
240 return data[x - lx]; // not transparent pixel
241 }
242 lx += count;
243 data += count;
244 }
245
246 return 0;
247
248 }
249
draw_pixel_sprite(s_screen * dest,gfx_entry * src,int dx,int dy,int sx,int sy)250 void draw_pixel_sprite(s_screen *dest, gfx_entry *src, int dx, int dy, int sx, int sy)
251 {
252 unsigned char *ptrd8, ps8;
253 unsigned short *ptrd16, pd16, ps16;
254 unsigned int *ptrd32, pd32, ps32;
255 switch(dest->pixelformat)
256 {
257 case PIXEL_8:
258 if(!(ps8 = sprite_get_pixel(src->sprite, sx, sy)))
259 {
260 return;
261 }
262 ptrd8 = ((unsigned char *)dest->data) + dx + dy * dest->width;
263 if(fillcolor)
264 {
265 ps8 = fillcolor;
266 }
267 *ptrd8 = pfp ? pfp(table, ps8, *ptrd8) : ps8;
268 break;
269 case PIXEL_16:
270 if(!(ps8 = sprite_get_pixel(src->sprite, sx, sy)))
271 {
272 return;
273 }
274 ptrd16 = ((unsigned short *)dest->data) + dx + dy * dest->width;
275 pd16 = *ptrd16;
276 if(fillcolor)
277 {
278 ps16 = fillcolor;
279 }
280 else
281 {
282 ps16 = table ? ((unsigned short *)table)[ps8] : ((unsigned short *)src->sprite->palette)[ps8];
283 }
284 if(!pfp16)
285 {
286 *ptrd16 = ps16;
287 }
288 else
289 {
290 *ptrd16 = pfp16(ps16, pd16);
291 }
292 break;
293 case PIXEL_32:
294 if(!(ps8 = sprite_get_pixel(src->sprite, sx, sy)))
295 {
296 return;
297 }
298 ptrd32 = ((unsigned int *)dest->data) + dx + dy * dest->width;
299 pd32 = *ptrd32;
300 if(fillcolor)
301 {
302 ps32 = fillcolor;
303 }
304 else
305 {
306 ps32 = table ? ((unsigned int *)table)[ps8] : ((unsigned int *)src->sprite->palette)[ps8];
307 }
308 if(!pfp32)
309 {
310 *ptrd32 = ps32;
311 }
312 else
313 {
314 *ptrd32 = pfp32(ps32, pd32);
315 }
316 break;
317 }
318
319 }
320
draw_pixel_gfx(s_screen * dest,gfx_entry * src,int dx,int dy,int sx,int sy)321 void draw_pixel_gfx(s_screen *dest, gfx_entry *src, int dx, int dy, int sx, int sy)
322 {
323 //drawfp(dest, src, dx, dy, sx, sy);
324 switch(src->screen->magic)
325 {
326 case sprite_magic:
327 draw_pixel_sprite(dest, src, dx, dy, sx, sy);
328 break;
329 case screen_magic:
330 draw_pixel_screen(dest, src, dx, dy, sx, sy);
331 break;
332 case bitmap_magic:
333 draw_pixel_bitmap(dest, src, dx, dy, sx, sy);
334 break;
335 default:
336 draw_pixel_dummy(dest, src, dx, dy, sx, sy);//debug purpose
337 break;
338 }
339 }
340
copy_pixel_block(int bytes)341 void copy_pixel_block(int bytes)
342 {
343 memcpy(cur_dest, cur_src, bytes);
344 }
345
346 #if 1
347 #include "writepixel.h"
348
write_pixel()349 __attribute__((always_inline)) void write_pixel()
350 {
351 writepixelswitch(,)
352
353 }
354 #endif
355
356 #if 0
357 __attribute__((always_inline)) void write_pixel()
358 {
359 unsigned char ps8;
360 unsigned short ps16;
361 unsigned ps32;
362 switch(dpf)
363 {
364 case PIXEL_8:
365 ps8 = *cur_src;
366 if(transbg && !ps8)
367 {
368 return;
369 }
370 else if(fillcolor)
371 {
372 ps8 = fillcolor;
373 }
374 *cur_dest = pfp ? pfp(table, ps8, *cur_dest) : ps8;
375 break;
376 case PIXEL_16:
377 switch(spf)
378 {
379 case PIXEL_16:
380 ps16 = *(unsigned short *)cur_src;
381 if(transbg && !ps16)
382 {
383 return;
384 }
385 break;
386 case PIXEL_x8:
387 if(!(ps8 = *cur_src) && transbg)
388 {
389 return;
390 }
391 ps16 = ((unsigned short *)table)[ps8];
392 break;
393 default:
394 return;
395 }
396 if(fillcolor)
397 {
398 ps16 = fillcolor;
399 }
400 if(!pfp16)
401 {
402 *(unsigned short *)cur_dest = ps16;
403 }
404 else
405 {
406 *(unsigned short *)cur_dest = pfp16(ps16, *(unsigned short *)cur_dest);
407 }
408 break;
409 case PIXEL_32:
410 switch(spf)
411 {
412 case PIXEL_32:
413 ps32 = *(unsigned *)cur_src;
414 if(transbg && !ps32)
415 {
416 return;
417 }
418 break;
419 case PIXEL_x8:
420 if(!(ps8 = *cur_src) && transbg)
421 {
422 return;
423 }
424 ps32 = ((unsigned *)table)[ps8];
425 break;
426 default:
427 return;
428 }
429 if(fillcolor)
430 {
431 ps32 = fillcolor;
432 }
433 if(!pfp32)
434 {
435 *(unsigned *)cur_dest = ps32;
436 }
437 else
438 {
439 *(unsigned *)cur_dest = pfp32(ps32, *(unsigned *)cur_dest);
440 }
441 break;
442 default:
443 break;
444 }
445
446 }
447 #endif
448
dest_seek(int x,int y)449 void dest_seek(int x, int y)
450 {
451 //x_dest = x; y_dest = y;
452 cur_dest = ptr_dest + (y * trans_dw + x) * dpb;
453 }
454
dest_line_inc()455 void dest_line_inc()
456 {
457 //y_dest++;
458 cur_dest += span_dest;
459 }
460
dest_line_dec()461 void dest_line_dec()
462 {
463 //y_dest--;
464 cur_dest -= span_dest;
465 }
466
467 //should be within a line
dest_inc()468 void dest_inc()
469 {
470 //x_dest++;
471 cur_dest += dpb;
472 }
473
474 //should be within a line
dest_dec()475 void dest_dec()
476 {
477 //x_dest--;
478 cur_dest -= dpb;
479 }
480
_sprite_seek(int x,int y)481 void _sprite_seek(int x, int y)
482 {
483 int *linetab;
484 unsigned char *data = NULL;
485 register int lx = 0, count;
486
487 linetab = ((int *)ptr_src) + y;
488
489 data = ((unsigned char *)linetab) + (*linetab);
490
491 while(1)
492 {
493 count = *data++;
494 if(count == 0xFF)
495 {
496 cur_src = dummyptrs;
497 goto quit;
498 }
499 if(lx + count > x) // transparent pixel
500 {
501 cur_src = dummyptrs;
502 goto quit;
503 }
504 lx += count;
505 count = *data++;
506 if(!count)
507 {
508 continue;
509 }
510 if(lx + count > x)
511 {
512 cur_src = data + x - lx;
513 goto quit;
514 }
515 lx += count;
516 data += count;
517 }
518
519 quit:
520 cur_spr = data - 1; // current block head
521 return ;
522
523 }
524
src_seek(int x,int y)525 __attribute__((always_inline)) void src_seek(int x, int y)
526 {
527 switch(handle_src->screen->magic)
528 {
529 case sprite_magic:
530 x_src = x;
531 y_src = y;
532 _sprite_seek(x, y);
533 break;
534 case screen_magic:
535 case bitmap_magic:
536 cur_src = ptr_src + (y * trans_sw + x) * spb;
537 break;
538 default:
539 break;
540 }
541 }
542
src_line_inc()543 void src_line_inc()
544 {
545 switch(handle_src->screen->magic)
546 {
547 case sprite_magic:
548 y_src++;
549 _sprite_seek(x_src, y_src);
550 break;
551 case screen_magic:
552 case bitmap_magic:
553 cur_src += span_src;
554 break;
555 default:
556 break;
557 }
558 }
559
src_line_dec()560 void src_line_dec()
561 {
562 switch(handle_src->screen->magic)
563 {
564 case sprite_magic:
565 y_src--;
566 _sprite_seek(x_src, y_src);
567 break;
568 case screen_magic:
569 case bitmap_magic:
570 cur_src -= span_src;
571 break;
572 default:
573 break;
574 }
575 }
576
577 //should be within a line
src_inc()578 void src_inc()
579 {
580 //int cnt;
581 x_src++;
582 switch(handle_src->screen->magic)
583 {
584 case sprite_magic:
585 //_sprite_seek(x,y);
586 if(cur_src != dummyptrs && cur_spr + *cur_spr > cur_src)
587 {
588 cur_src++;
589 }
590 else
591 {
592 _sprite_seek(x_src, y_src);
593 }
594 break;
595 case screen_magic:
596 case bitmap_magic:
597 cur_src += spb;
598 break;
599 default:
600 break;
601 }
602 }
603
604 //should be within a line
src_dec()605 void src_dec()
606 {
607 x_src--;
608 switch(handle_src->screen->magic)
609 {
610 case sprite_magic:
611 //_sprite_seek(x,y);
612 if(cur_src != dummyptrs && cur_spr + 1 < cur_src)
613 {
614 cur_src--;
615 }
616 else
617 {
618 _sprite_seek(x_src, y_src);
619 }
620 break;
621 case screen_magic:
622 case bitmap_magic:
623 cur_src -= spb;
624 break;
625 default:
626 break;
627 }
628 }
629
calc_wp_cond()630 void calc_wp_cond()
631 {
632 static int wp_cond[5][2][2][2] =
633 {
634 {{{0, 1}, {2, 3}}, {{4, 5}, {6, 7}}},
635 {{{8, 9}, {10, 11}}, {{12, 13}, {14, 15}}},
636 {{{16, 17}, {18, 19}}, {{20, 21}, {22, 23}}},
637 {{{24, 25}, {26, 27}}, {{28, 29}, {30, 31}}},
638 {{{32, 33}, {24, 35}}, {{36, 37}, {38, 39}}},
639 };
640 int c1;
641 void *p;
642 if(dpf == PIXEL_16)
643 {
644 c1 = spf == PIXEL_x8 ? 1 : 2;
645 p = pfp16;
646 }
647 else if(dpf == PIXEL_32)
648 {
649 c1 = spf == PIXEL_x8 ? 3 : 4;
650 p = pfp32;
651 }
652 else
653 {
654 c1 = 0;
655 p = pfp;
656 }
657
658 wpcond = wp_cond[c1][transbg != 0][fillcolor != 0][p != NULL];
659 }
660
init_gfx_global_draw_stuff(s_screen * dest,gfx_entry * src,s_drawmethod * drawmethod)661 void init_gfx_global_draw_stuff(s_screen *dest, gfx_entry *src, s_drawmethod *drawmethod)
662 {
663
664 spf = dpf = 0; //source pixel format
665 drawfp = draw_pixel_dummy;
666 pfp = NULL;
667 fillcolor = 0;
668 pfp16 = NULL;
669 pfp32 = NULL;
670 table = NULL;
671 transbg = 0;
672
673 handle_dest = dest;
674 handle_src = src;
675 cur_dest = ptr_dest = (unsigned char *)dest->data;
676 x_dest = y_dest = x_src = y_src = 0;
677
678 //nasty checkings due to those different pixel formats
679 switch(src->screen->magic)
680 {
681 case screen_magic:
682 //printf("gfx_screen\n");
683 spf = src->screen->pixelformat;
684 drawfp = draw_pixel_screen;
685 trans_sw = src->screen->width;
686 trans_sh = src->screen->height;
687 cur_src = ptr_src = (unsigned char *)src->screen->data;
688 table = drawmethod->table ? drawmethod->table : src->screen->palette;
689 break;
690 case bitmap_magic:
691 //printf("gfx_bitmap\n");
692 spf = src->bitmap->pixelformat;
693 drawfp = draw_pixel_bitmap;
694 trans_sw = src->bitmap->width;
695 trans_sh = src->bitmap->height;
696 cur_src = ptr_src = (unsigned char *)src->bitmap->data;
697 table = drawmethod->table ? drawmethod->table : src->bitmap->palette;
698 break;
699 case sprite_magic:
700 //printf("gfx_sprite\n");
701 spf = src->sprite->pixelformat;
702 drawfp = draw_pixel_sprite;
703 trans_sw = src->sprite->width;
704 trans_sh = src->sprite->height;
705 if(trans_sw)
706 {
707 ptr_src = (unsigned char *)src->sprite->data;
708 cur_spr = ptr_src + (*(int *)ptr_src);
709 }
710 table = drawmethod->table ? drawmethod->table : src->sprite->palette;
711 break;
712 default:
713 //printf("gfx_unknown\n");
714 return;
715 }
716
717 trans_dw = dest->width;
718 trans_dh = dest->height;
719
720 xmin = useclip ? clipx1 : 0;
721 xmax = useclip ? clipx2 : dest->width;
722 ymin = useclip ? clipy1 : 0;
723 ymax = useclip ? clipy2 : dest->height;
724
725 dpf = dest->pixelformat;
726
727 switch(dest->pixelformat)
728 {
729 case PIXEL_8:
730 if(drawmethod->fillcolor)
731 {
732 fillcolor = drawmethod->fillcolor & 0xFF;
733 }
734 else
735 {
736 fillcolor = 0;
737 }
738
739 table = NULL;
740 remaptable = NULL;
741
742 if(drawmethod->alpha > 0)
743 {
744 table = blendtables[drawmethod->alpha - 1];
745 remaptable = drawmethod->table;
746 pfp = (fillcolor == TRANSPARENT_IDX ? blendcolor : blendfillcolor);
747 }
748 else if(drawmethod->table)
749 {
750 remaptable = drawmethod->table;
751 pfp = (fillcolor == TRANSPARENT_IDX ? remapcolor : blendfillcolor);
752 }
753 else
754 {
755 pfp = (fillcolor == TRANSPARENT_IDX ? NULL : blendfillcolor);
756 }
757 break;
758 case PIXEL_16:
759 fillcolor = drawmethod->fillcolor;
760 pfp16 = getblendfunction16(drawmethod->alpha);
761 break;
762 case PIXEL_32:
763 fillcolor = drawmethod->fillcolor;
764 pfp32 = getblendfunction32(drawmethod->alpha);
765 break;
766 default:
767 return;
768 }
769 dpb = pixelbytes[dpf];
770 spb = pixelbytes[spf];
771
772 span_src = spb * trans_sw;
773 span_dest = dpb * trans_dw;
774 transbg = (drawmethod->transbg || src->screen->magic == sprite_magic); // check color key, we'll need this for screen and bitmap
775 calc_wp_cond();
776
777 if(!trans_sw)
778 {
779 return;
780 }
781 src_seek(0, 0);
782 }
783
784 #if 0
785 void gfx_draw_rotate(s_screen *dest, gfx_entry *src, int x, int y, int centerx, int centery, s_drawmethod *drawmethod)
786 {
787 float zoomx, zoomy, rzoomx, rzoomy, sina, cosa, ax, ay, bx, by, rx0, ry0, cx, cy, srcx0_f, srcx_f, srcy0_f, srcy_f, angle;
788 int i, j, srcx, srcy;
789 int xbound[4], ybound[4];
790 float xboundf[4], yboundf[4];
791 zoomx = drawmethod->scalex / 256.0;
792 zoomy = drawmethod->scaley / 256.0;
793 angle = drawmethod->rotate;
794 sina = sin_table[(int)angle];
795 cosa = cos_table[(int)angle];
796
797 init_gfx_global_draw_stuff(dest, src, drawmethod);
798 if(!trans_sw)
799 {
800 return;
801 }
802
803 centerx += drawmethod->centerx;
804 centery += drawmethod->centery;
805
806 /////////////////begin clipping////////////////////////////
807 xboundf[0] = drawmethod->flipx ? (centerx - trans_sw) * zoomx : -centerx * zoomx;
808 yboundf[0] = drawmethod->flipy ? (centery - trans_sh) * zoomy : -centery * zoomy;
809 xboundf[1] = xboundf[0] + trans_sw * zoomx;
810 yboundf[1] = yboundf[0];
811 xboundf[2] = xboundf[0];
812 yboundf[2] = yboundf[0] + trans_sh * zoomy;
813 xboundf[3] = xboundf[1];
814 yboundf[3] = yboundf[2];
815
816 for(i = 0; i < 4; i++)
817 {
818 xbound[i] = (int)(x + xboundf[i] * cosa - yboundf[i] * sina);
819 ybound[i] = (int)(y + xboundf[i] * sina + yboundf[i] * cosa);
820 }
821
822 xmin = MAX(MIN(MIN(xbound[0], xbound[1]), MIN(xbound[2], xbound[3])), xmin);
823 xmax = MIN(MAX(MAX(xbound[0], xbound[1]), MAX(xbound[2], xbound[3])), xmax);
824 ymin = MAX(MIN(MIN(ybound[0], ybound[1]), MIN(ybound[2], ybound[3])), ymin);
825 ymax = MIN(MAX(MAX(ybound[0], ybound[1]), MAX(ybound[2], ybound[3])), ymax);
826 /////////////////end clipping////////////////////////////
827
828 // tricks to keep rotate not affected by flip
829 if(drawmethod->flipx)
830 {
831 zoomx = -zoomx;
832 }
833 else
834 {
835 angle = -angle;
836 }
837 if(drawmethod->flipy)
838 {
839 zoomy = -zoomy;
840 angle = -angle;
841 }
842
843 angle = (((int)angle) % 360 + 360) % 360;
844 //if(!zoomx || !zoomy) return; //should be checked already
845 rzoomx = 1.0 / zoomx;
846 rzoomy = 1.0 / zoomy;
847 sina = sin_table[(int)angle];
848 cosa = cos_table[(int)angle];
849 ax = rzoomx * cosa;
850 ay = rzoomx * sina;
851 bx = -rzoomy * sina;
852 by = rzoomy * cosa;
853 rx0 = centerx;
854 ry0 = centery;
855 x -= rx0;
856 y -= ry0;
857 cx = -(rx0 + x) * rzoomx * cosa + (ry0 + y) * rzoomy * sina + rx0;
858 cy = -(rx0 + x) * rzoomx * sina - (ry0 + y) * rzoomy * cosa + ry0;
859 srcx0_f = cx + ymin * bx + xmin * ax, srcx_f;
860 srcy0_f = cy + ymin * by + xmin * ay, srcy_f;
861
862 for (j = ymin; j < ymax; j++)
863 {
864 srcx_f = srcx0_f;
865 srcy_f = srcy0_f;
866 for (i = xmin; i < xmax; i++)
867 {
868 srcx = (int)(srcx_f);
869 srcy = (int)(srcy_f);
870 if(srcx >= 0 && srcx < trans_sw && srcy >= 0 && srcy < trans_sh)
871 {
872 draw_pixel_gfx(dest, src, i, j, srcx, srcy);
873 }
874 srcx_f += ax;
875 srcy_f += ay;
876 }
877 srcx0_f += bx;
878 srcy0_f += by;
879 }
880 }
881 #endif
882
883 //fix point version
gfx_draw_rotate(s_screen * dest,gfx_entry * src,int x,int y,int centerx,int centery,s_drawmethod * drawmethod)884 void gfx_draw_rotate(s_screen *dest, gfx_entry *src, int x, int y, int centerx, int centery, s_drawmethod *drawmethod)
885 {
886 float zoomx, zoomy, rzoomx, rzoomy, sina, cosa, ax, ay, bx, by, rx0, ry0, cx, cy, srcx0_f, srcy0_f, angle;
887 unsigned i, j, srcx, srcy;
888 int srcx_16, srcy_16, srcx0_16, srcy0_16, ax_16, ay_16, bx_16, by_16;
889 int xbound[4], ybound[4];
890 float xboundf[4], yboundf[4];
891 zoomx = drawmethod->scalex / 256.0;
892 zoomy = drawmethod->scaley / 256.0;
893 angle = drawmethod->rotate;
894 sina = sin_table[(int)angle];
895 cosa = cos_table[(int)angle];
896
897 init_gfx_global_draw_stuff(dest, src, drawmethod);
898 if(!trans_sw)
899 {
900 return;
901 }
902
903 centerx += drawmethod->centerx;
904 centery += drawmethod->centery;
905
906 /////////////////begin clipping////////////////////////////
907 xboundf[0] = drawmethod->flipx ? (centerx - trans_sw) * zoomx : -centerx * zoomx;
908 yboundf[0] = drawmethod->flipy ? (centery - trans_sh) * zoomy : -centery * zoomy;
909 xboundf[1] = xboundf[0] + trans_sw * zoomx;
910 yboundf[1] = yboundf[0];
911 xboundf[2] = xboundf[0];
912 yboundf[2] = yboundf[0] + trans_sh * zoomy;
913 xboundf[3] = xboundf[1];
914 yboundf[3] = yboundf[2];
915
916 for(i = 0; i < 4; i++)
917 {
918 xbound[i] = (int)(x + xboundf[i] * cosa - yboundf[i] * sina);
919 ybound[i] = (int)(y + xboundf[i] * sina + yboundf[i] * cosa);
920 }
921
922 xmin = MAX(MIN(MIN(xbound[0], xbound[1]), MIN(xbound[2], xbound[3])), xmin);
923 xmin = MIN(trans_dw, xmin);
924 xmax = MIN(MAX(MAX(xbound[0], xbound[1]), MAX(xbound[2], xbound[3])), xmax);
925 xmax = MAX(0, xmax);
926 ymin = MAX(MIN(MIN(ybound[0], ybound[1]), MIN(ybound[2], ybound[3])), ymin);
927 ymin = MIN(trans_dh, ymin);
928 ymax = MIN(MAX(MAX(ybound[0], ybound[1]), MAX(ybound[2], ybound[3])), ymax);
929 ymax = MAX(0, ymax);
930 /////////////////end clipping////////////////////////////
931
932 // tricks to keep rotate not affected by flip
933 if(drawmethod->flipx)
934 {
935 zoomx = -zoomx;
936 }
937 else
938 {
939 angle = -angle;
940 }
941 if(drawmethod->flipy)
942 {
943 zoomy = -zoomy;
944 angle = -angle;
945 }
946
947 angle = (((int)angle) % 360 + 360) % 360;
948 //if(!zoomx || !zoomy) return; //should be checked already
949 rzoomx = 1.0 / zoomx;
950 rzoomy = 1.0 / zoomy;
951 sina = sin_table[(int)angle];
952 cosa = cos_table[(int)angle];
953 ax = rzoomx * cosa;
954 ay = rzoomx * sina;
955 bx = -rzoomy * sina;
956 by = rzoomy * cosa;
957 rx0 = centerx;
958 ry0 = centery;
959 x -= rx0;
960 y -= ry0;
961 cx = -(rx0 + x) * rzoomx * cosa + (ry0 + y) * rzoomy * sina + rx0;
962 cy = -(rx0 + x) * rzoomx * sina - (ry0 + y) * rzoomy * cosa + ry0;
963 srcx0_f = cx + ymin * bx + xmin * ax;
964 srcy0_f = cy + ymin * by + xmin * ay;
965
966
967 srcx0_16 = srcx0_f * 65536;
968 srcy0_16 = srcy0_f * 65536;
969 ax_16 = ax * 65536;
970 ay_16 = ay * 65536;
971 bx_16 = bx * 65536;
972 by_16 = by * 65536;
973
974 #define for1 \
975 for (j=ymin; j<ymax; j++)\
976 {\
977 srcx_16 = srcx0_16;\
978 srcy_16= srcy0_16;\
979 dest_seek(xmin,j);\
980 for (i=xmin;i<xmax;i++)\
981 {\
982 srcx=srcx_16>>16;\
983 srcy=srcy_16>>16;\
984 if(srcx<trans_sw && srcy<trans_sh){\
985 src_seek(srcx, srcy);\
986
987 #define for2 \
988 }\
989 dest_inc();\
990 srcx_16+=ax_16;\
991 srcy_16+=ay_16;\
992 }\
993 srcx0_16+=bx_16;\
994 srcy0_16+=by_16;\
995 }
996
997 writepixelswitch(for1, for2)
998
999 #undef for1
1000 #undef for2
1001 }
1002
gfx_quad(s_screen * dest,gfx_entry * src,int x0,int y0,int x1,int y1,int x2,int y2,int x3,int y3,s_drawmethod * drawmethod)1003 void gfx_quad(s_screen *dest, gfx_entry *src,
1004 int x0, int y0,
1005 int x1, int y1,
1006 int x2, int y2,
1007 int x3, int y3,
1008 s_drawmethod *drawmethod)
1009 {
1010 int a[4] = { y1 - y0, y2 - y1, y3 - y2, y0 - y3};
1011 int b[4] = { x0 - x1, x1 - x2, x2 - x3, x3 - x0};
1012 float r[4] =
1013 {
1014 invsqrt(a[0]*a[0] + b[0]*b[0]),
1015 invsqrt(a[1]*a[1] + b[1]*b[1]),
1016 invsqrt(a[2]*a[2] + b[2]*b[2]),
1017 invsqrt(a[3]*a[3] + b[3]*b[3])
1018 };
1019 int c[4] =
1020 {
1021 -x0 *a[0] - y0 *b[0],
1022 -x1 *a[1] - y1 *b[1],
1023 -x2 *a[2] - y2 *b[2],
1024 -x3 *a[3] - y3 *b[3]
1025 };
1026 int x, y, i;
1027 float dist[4];
1028 unsigned sx, sy;
1029 for(y = ymin; y < ymax; y++)
1030 {
1031 dest_seek(xmin, y);
1032 for(x = xmin; x < xmax; x++, dest_inc())
1033 {
1034 for(i = 0; i < 4; i++)
1035 {
1036 dist[i] = (x * a[i] + y * b[i] + c[i]) * r[i];
1037 }
1038 sx = (unsigned)(dist[3] * (trans_sw - 1) / (dist[3] + dist[1]));
1039 sy = (unsigned)(dist[0] * (trans_sh - 1) / (dist[0] + dist[2]));
1040 if(sx >= trans_sw || sy >= trans_sh)
1041 {
1042 continue;
1043 }
1044 src_seek(sx, sy);
1045 write_pixel();
1046 }
1047 }
1048 }
1049
1050 #if 0
1051 // scalex scaley flipy ...
1052 void gfx_draw_scale(s_screen *dest, gfx_entry *src, int x, int y, int centerx, int centery, s_drawmethod *drawmethod)
1053 {
1054 float beginy, endy, beginx, endx, w, h, cx, cy;
1055 int i;
1056 float zoomx = drawmethod->scalex / 256.0;
1057 float zoomy = drawmethod->scaley / 256.0;
1058 float shiftf = drawmethod->shiftx / 256.0;
1059 float qx[4], qy[4];
1060
1061 init_gfx_global_draw_stuff(dest, src, drawmethod);
1062 if(!trans_sw)
1063 {
1064 return;
1065 }
1066
1067 centerx += drawmethod->centerx;
1068 centery += drawmethod->centery;
1069
1070 w = trans_sw * zoomx;
1071 h = trans_sh * zoomy;
1072 cx = centerx * zoomx;
1073 cy = centery * zoomy;
1074
1075 qx[0] = x - cx;
1076 qy[0] = y - cy;
1077 qx[1] = qx[0] + w;
1078 qy[1] = qy[0];
1079 qx[2] = qx[1];
1080 qy[2] = qy[0] + h;
1081 qx[3] = qx[0];
1082 qy[3] = qy[2];
1083
1084 if(drawmethod->flipy)
1085 {
1086 shiftf = -shiftf;
1087 for(i = 0; i < 4; i++)
1088 {
1089 qy[i] = 2 * y - qy[i];
1090 }
1091 }
1092 if(drawmethod->flipx)
1093 {
1094 for(i = 0; i < 4; i++)
1095 {
1096 qx[i] = 2 * x - qx[i];
1097 }
1098 }
1099 if(shiftf)
1100 {
1101 for(i = 0; i < 4; i++)
1102 {
1103 qx[i] += (qy[i] - y) * shiftf;
1104 }
1105 }
1106
1107 beginx = MIN(MIN(qx[0], qx[1]), MIN(qx[2], qx[3]));
1108 endx = MAX(MAX(qx[0], qx[1]), MAX(qx[2], qx[3]));
1109 beginy = MIN(qy[0], qy[3]);
1110 endy = MAX(qy[0], qy[3]);
1111
1112 if(endy <= ymin || beginy >= ymax)
1113 {
1114 return;
1115 }
1116 if(endx <= xmin || beginx >= xmax)
1117 {
1118 return;
1119 }
1120
1121 ymin = MAX(ymin, beginy);
1122 ymax = MIN(ymax, endy);
1123 xmin = MAX(xmin, beginx);
1124 xmax = MIN(xmax, endx);
1125
1126 gfx_quad(dest, src, qx[0], qy[0], qx[1], qy[1], qx[2], qy[2], qx[3], qy[3], drawmethod);
1127
1128 }
1129 #endif
1130
1131 #if 0
1132 // scalex scaley flipy ...
1133 void gfx_draw_scale(s_screen *dest, gfx_entry *src, int x, int y, int centerx, int centery, s_drawmethod *drawmethod)
1134 {
1135 float osx, sx, sy, dx, dy, w, h, cx, cy, stepdx, stepdy, beginy, endy, beginx, endx;
1136 int i, j;
1137 float zoomx = drawmethod->scalex / 256.0;
1138 float zoomy = drawmethod->scaley / 256.0;
1139 float shiftf = drawmethod->shiftx / 256.0;
1140
1141 //if(!zoomy || !zoomx) return; //should be checked already
1142
1143 //printf("==%d %d %d %d %d\n", drawmethod->scalex, drawmethod->scaley, drawmethod->flipx, drawmethod->flipy, drawmethod->shiftx);
1144
1145 init_gfx_global_draw_stuff(dest, src, drawmethod);
1146 if(!trans_sw)
1147 {
1148 return;
1149 }
1150
1151 centerx += drawmethod->centerx;
1152 centery += drawmethod->centery;
1153
1154 w = trans_sw * zoomx;
1155 h = trans_sh * zoomy;
1156 cx = centerx * zoomx;
1157 cy = centery * zoomy;
1158
1159 if(drawmethod->flipx)
1160 {
1161 dx = cx - w + x;
1162 }
1163 else
1164 {
1165 dx = x - cx;
1166 }
1167
1168 if(drawmethod->flipy)
1169 {
1170 dy = cy - h + y;
1171 shiftf = - shiftf;
1172 }
1173 else
1174 {
1175 dy = y - cy;
1176 }
1177
1178 dx += (dy + h - y) * shiftf;
1179
1180 if(drawmethod->flipx)
1181 {
1182 stepdx = 1.0 / zoomx;
1183 osx = 0.0;
1184 }
1185 else
1186 {
1187 stepdx = -1.0 / zoomx;
1188 osx = trans_sw + stepdx;
1189 }
1190 if(drawmethod->flipy)
1191 {
1192 stepdy = 1.0 / zoomy;
1193 sy = 0.0;
1194 }
1195 else
1196 {
1197 stepdy = -1.0 / zoomy;
1198 sy = trans_sh + stepdy;
1199 }
1200
1201 if(MAX(dx + w, dx + w - shiftf * h) <= xmin)
1202 {
1203 return;
1204 }
1205 if(MIN(dx, dx - shiftf * h) >= xmax)
1206 {
1207 return;
1208 }
1209 if(dy >= ymax)
1210 {
1211 return;
1212 }
1213 if(dy + h <= ymin)
1214 {
1215 return;
1216 }
1217
1218 if(dy + h > ymax)
1219 {
1220 endy = ymax;
1221 dx -= shiftf * (dy + h - endy);
1222 sy += stepdy * (dy + h - endy);
1223 }
1224 else
1225 {
1226 endy = dy + h;
1227 }
1228
1229 if(dy < ymin)
1230 {
1231 beginy = ymin;
1232 }
1233 else
1234 {
1235 beginy = dy;
1236 }
1237
1238 //printf("=%d, %d, %lf, %lf, %lf, %lf, %lf, %lf\n ",x, y, w, h, osx, sy, dx, dy);
1239 // =64, 144, 44.000000, 36.500000, 43.000000, 0.000000, 38.000000, 143.000000
1240
1241 for(j = endy - 1; j >= beginy; j--, sy += stepdy, dx -= shiftf)
1242 {
1243 if(dx >= xmax)
1244 {
1245 continue;
1246 }
1247 if(dx + w <= xmin)
1248 {
1249 continue;
1250 }
1251 sx = osx;
1252 beginx = dx;
1253 endx = dx + w;
1254 if(dx < xmin)
1255 {
1256 beginx = xmin;
1257 }
1258 else
1259 {
1260 beginx = dx;
1261 }
1262 if(dx + w > xmax)
1263 {
1264 endx = xmax;
1265 sx += stepdx * (dx + w - xmax);
1266 }
1267 else
1268 {
1269 endx = dx + w;
1270 }
1271 dest_seek(endx - 1, j);
1272 for(i = endx - 1; i >= beginx; i--, sx += stepdx)
1273 {
1274 //draw_pixel_gfx(dest, src, i, j, (int)sx, (int)sy);
1275 src_seek((int)sx, (int)sy);
1276 write_pixel();
1277 dest_dec();
1278 }
1279 }
1280
1281 }
1282 #endif
1283
1284 #if 1
1285 //same as above, fix point version
1286 // scalex scaley flipy ...
gfx_draw_scale(s_screen * dest,gfx_entry * src,int x,int y,int centerx,int centery,s_drawmethod * drawmethod)1287 void gfx_draw_scale(s_screen *dest, gfx_entry *src, int x, int y, int centerx, int centery, s_drawmethod *drawmethod)
1288 {
1289 int osx, sx, sy, dx, dy, w, h, cx, cy, stepdx, stepdy, beginy, endy, beginx, endx;
1290 int i, j;
1291 int zoomx = drawmethod->scalex;
1292 int zoomy = drawmethod->scaley;
1293 int shiftf = drawmethod->shiftx;
1294
1295 init_gfx_global_draw_stuff(dest, src, drawmethod);
1296 if(!trans_sw)
1297 {
1298 return;
1299 }
1300
1301 centerx += drawmethod->centerx;
1302 centery += drawmethod->centery;
1303
1304 xmin <<= 8;
1305 xmax <<= 8;
1306 ymin <<= 8;
1307 ymax <<= 8;
1308 x <<= 8;
1309 y <<= 8;
1310
1311 w = trans_sw * zoomx;
1312 h = trans_sh * zoomy;
1313 cx = centerx * zoomx;
1314 cy = centery * zoomy;
1315
1316 if(drawmethod->flipx)
1317 {
1318 dx = cx - w + x;
1319 }
1320 else
1321 {
1322 dx = x - cx;
1323 }
1324
1325 if(drawmethod->flipy)
1326 {
1327 dy = cy - h + y;
1328 shiftf = - shiftf;
1329 }
1330 else
1331 {
1332 dy = y - cy;
1333 }
1334
1335 dx += ((dy + h - y) * shiftf) >> 8;
1336
1337 if(drawmethod->flipx)
1338 {
1339 stepdx = 65536 / zoomx;
1340 osx = 0;
1341 }
1342 else
1343 {
1344 stepdx = -65536 / zoomx;
1345 osx = (trans_sw << 8) + stepdx;
1346 }
1347 if(drawmethod->flipy)
1348 {
1349 stepdy = 65536 / zoomy;
1350 sy = 0;
1351 }
1352 else
1353 {
1354 stepdy = -65536 / zoomy;
1355 sy = (trans_sh << 8) + stepdy;
1356 }
1357
1358 if(MAX(dx + w, dx + w - (shiftf * h >> 8)) <= xmin)
1359 {
1360 return;
1361 }
1362 if(MIN(dx, dx - (shiftf * h >> 8)) >= xmax)
1363 {
1364 return;
1365 }
1366 if(dy >= ymax)
1367 {
1368 return;
1369 }
1370 if(dy + h <= ymin)
1371 {
1372 return;
1373 }
1374
1375 if(dy + h > ymax)
1376 {
1377 endy = ymax;
1378 dx -= shiftf * (dy + h - endy) >> 8;
1379 sy += stepdy * (dy + h - endy) >> 8;
1380 }
1381 else
1382 {
1383 endy = dy + h;
1384 }
1385
1386 if(dy < ymin)
1387 {
1388 beginy = ymin;
1389 }
1390 else
1391 {
1392 beginy = dy;
1393 }
1394
1395 //printf("=%d, %d, %lf, %lf, %lf, %lf, %lf, %lf\n ",x, y, w, h, osx, sy, dx, dy);
1396 // =64, 144, 44.000000, 36.500000, 43.000000, 0.000000, 38.000000, 143.000000
1397
1398 #define for1() \
1399 for(j=endy-256; j>=beginy; j-=256, sy+=stepdy, dx -= shiftf){\
1400 if(dx>=xmax) continue;\
1401 if(dx+w<=xmin) continue;\
1402 sx = osx;\
1403 beginx = dx;\
1404 endx = dx+w;\
1405 if(dx<xmin) beginx = xmin;\
1406 else beginx = dx;\
1407 if(dx+w>xmax) {\
1408 endx = xmax;\
1409 sx += stepdx*(dx+w-xmax)>>8;\
1410 } else endx = dx+w;\
1411 dest_seek((endx>>8)-1, j>>8);\
1412 for(i=endx-256; i>=beginx; i-=256, sx+=stepdx){\
1413 src_seek(sx>>8, sy>>8); \
1414
1415 #define for2() \
1416 dest_dec();\
1417 }\
1418 }
1419
1420 writepixelswitch(for1(), for2())
1421
1422 #undef for1
1423 #undef for2
1424 }
1425 #endif
1426
1427 float _sinfactors[256] = {1.0f, 1.0245412285229123f, 1.049067674327418f, 1.0735645635996673f, 1.0980171403295606f, 1.1224106751992162f, 1.1467304744553617f, 1.1709618887603012f, 1.1950903220161282f, 1.2191012401568697f, 1.2429801799032638f, 1.2667127574748984f, 1.2902846772544622f, 1.3136817403988914f, 1.33688985339222f, 1.3598950365349882f, 1.3826834323650898f, 1.4052413140049897f, 1.427555093430282f, 1.4496113296546064f, 1.4713967368259977f, 1.492898192229784f, 1.5141027441932215f, 1.5349976198870971f, 1.5555702330196021f, 1.5758081914178454f, 1.5956993044924332f, 1.6152315905806267f, 1.6343932841636454f, 1.6531728429537766f, 1.6715589548470184f, 1.6895405447370668f, 1.7071067811865474f, 1.724247082951467f, 1.7409511253549592f, 1.7572088465064843f, 1.7730104533627368f, 1.7883464276266063f, 1.8032075314806448f, 1.8175848131515837f, 1.8314696123025453f, 1.8448535652497071f, 1.8577286100002721f, 1.8700869911087112f, 1.881921264348355f, 1.8932243011955152f, 1.9039892931234434f, 1.9142097557035307f, 1.9238795325112867f, 1.9329927988347388f, 1.9415440651830207f, 1.9495281805930366f, 1.956940335732209f, 1.96377606579544f, 1.970031253194544f, 1.9757021300385284f, 1.9807852804032304f, 1.985277642388941f, 1.9891765099647811f, 1.99247953459871f, 1.9951847266721967f, 1.9972904566786902f, 1.9987954562051724f, 1.9996988186962041f, 2.0f, 1.9996988186962041f, 1.9987954562051724f, 1.9972904566786902f, 1.995184726672197f, 1.99247953459871f, 1.9891765099647811f, 1.985277642388941f, 1.9807852804032304f, 1.9757021300385284f, 1.970031253194544f, 1.96377606579544f, 1.956940335732209f, 1.9495281805930366f, 1.9415440651830207f, 1.9329927988347388f, 1.9238795325112867f, 1.9142097557035307f, 1.9039892931234434f, 1.8932243011955152f, 1.881921264348355f, 1.8700869911087114f, 1.8577286100002721f, 1.8448535652497071f, 1.8314696123025453f, 1.8175848131515837f, 1.8032075314806448f, 1.7883464276266063f, 1.773010453362737f, 1.7572088465064848f, 1.740951125354959f, 1.724247082951467f, 1.7071067811865474f, 1.689540544737067f, 1.6715589548470184f, 1.6531728429537766f, 1.6343932841636454f, 1.615231590580627f, 1.5956993044924334f, 1.5758081914178454f, 1.5555702330196021f, 1.5349976198870971f, 1.5141027441932217f, 1.4928981922297841f, 1.471396736825998f, 1.449611329654607f, 1.427555093430282f, 1.40524131400499f, 1.3826834323650898f, 1.3598950365349882f, 1.3368898533922202f, 1.3136817403988914f, 1.2902846772544625f, 1.2667127574748984f, 1.242980179903264f, 1.2191012401568701f, 1.1950903220161286f, 1.1709618887603012f, 1.146730474455362f, 1.1224106751992164f, 1.0980171403295608f, 1.0735645635996677f, 1.0490676743274178f, 1.0245412285229123f, 1.0000000000000002f, 0.9754587714770879f, 0.9509323256725822f, 0.9264354364003325f, 0.9019828596704394f, 0.8775893248007839f, 0.8532695255446384f, 0.8290381112396991f, 0.8049096779838716f, 0.7808987598431302f, 0.7570198200967362f, 0.7332872425251018f, 0.709715322745538f, 0.6863182596011088f, 0.6631101466077799f, 0.6401049634650119f, 0.6173165676349104f, 0.5947586859950102f, 0.5724449065697181f, 0.5503886703453933f, 0.5286032631740023f, 0.5071018077702161f, 0.48589725580677845f, 0.46500238011290307f, 0.44442976698039804f, 0.42419180858215466f, 0.40430069550756675f, 0.3847684094193733f, 0.36560671583635473f, 0.34682715704622346f, 0.32844104515298156f, 0.31045945526293317f, 0.29289321881345254f, 0.2757529170485332f, 0.2590488746450411f, 0.24279115349351576f, 0.22698954663726334f, 0.2116535723733941f, 0.19679246851935494f, 0.18241518684841618f, 0.16853038769745476f, 0.155146434750293f, 0.142271389999728f, 0.12991300889128865f, 0.11807873565164506f, 0.10677569880448478f, 0.09601070687655688f, 0.08579024429646953f, 0.07612046748871348f, 0.06700720116526104f, 0.058455934816979194f, 0.050471819406963325f, 0.043059664267791176f, 0.03622393420456016f, 0.029968746805456026f, 0.02429786996147154f, 0.01921471959676968f, 0.01472235761105889f, 0.010823490035219096f, 0.007520465401289922f, 0.004815273327803071f, 0.002709543321309793f, 0.001204543794827595f, 0.00030118130379575003f, 0.0f, 0.00030118130379575003f, 0.001204543794827595f, 0.002709543321309793f, 0.004815273327803071f, 0.007520465401289922f, 0.010823490035219096f, 0.014722357611058778f, 0.01921471959676957f, 0.02429786996147143f, 0.029968746805456026f, 0.03622393420456005f, 0.043059664267791065f, 0.050471819406963214f, 0.05845593481697908f, 0.06700720116526093f, 0.07612046748871337f, 0.08579024429646942f, 0.09601070687655666f, 0.10677569880448467f, 0.11807873565164495f, 0.12991300889128854f, 0.14227138999972777f, 0.15514643475029277f, 0.16853038769745454f, 0.18241518684841595f, 0.19679246851935472f, 0.21165357237339388f, 0.22698954663726312f, 0.24279115349351543f, 0.2590488746450409f, 0.275752917048533f, 0.2928932188134523f, 0.31045945526293283f, 0.32844104515298133f, 0.3468271570462229f, 0.36560671583635407f, 0.3847684094193726f, 0.40430069550756675f, 0.4241918085821548f, 0.4444297669803978f, 0.46500238011290273f, 0.4858972558067781f, 0.5071018077702157f, 0.5286032631740021f, 0.5503886703453931f, 0.5724449065697175f, 0.5947586859950096f, 0.6173165676349096f, 0.640104963465012f, 0.66311014660778f, 0.6863182596011085f, 0.7097153227455375f, 0.7332872425251014f, 0.7570198200967358f, 0.7808987598431298f, 0.8049096779838712f, 0.8290381112396983f, 0.8532695255446376f, 0.877589324800784f, 0.9019828596704394f, 0.9264354364003325f, 0.9509323256725819f, 0.9754587714770876f};
1428 #define distortion(x, a) ((int)(_sinfactors[x]*a+0.5))
1429
gfx_draw_water(s_screen * dest,gfx_entry * src,int x,int y,int centerx,int centery,s_drawmethod * drawmethod)1430 void gfx_draw_water(s_screen *dest, gfx_entry *src, int x, int y, int centerx, int centery, s_drawmethod *drawmethod)
1431 {
1432 int sw, sh, dw, dh, ch, sy, t, u, sbeginx, sendx, bytestocopy, dbeginx, dendx, amplitude, time;
1433 float s, wavelength;
1434
1435 init_gfx_global_draw_stuff(dest, src, drawmethod);
1436 if(!trans_sw)
1437 {
1438 return;
1439 }
1440
1441 centerx += drawmethod->centerx;
1442 centery += drawmethod->centery;
1443
1444 sw = trans_sw;
1445 sh = trans_sh;
1446 dw = trans_dw;
1447 dh = trans_dh;
1448 ch = sh;
1449 x -= centerx;
1450 y -= centery;
1451
1452 amplitude = drawmethod->water.amplitude;
1453 time = drawmethod->water.wavetime;
1454
1455 s = time % 256;
1456
1457 // Clip x
1458 if(x + amplitude * 2 + sw <= 0 || x - amplitude * 2 >= dw)
1459 {
1460 return;
1461 }
1462 if(y + sh <= 0 || y >= dh)
1463 {
1464 return;
1465 }
1466
1467 sy = 0;
1468 if(s < 0)
1469 {
1470 s += 256;
1471 }
1472
1473 // Clip y
1474 if(y < 0)
1475 {
1476 sy = -y;
1477 ch += y;
1478 }
1479 if(y + sh > dh)
1480 {
1481 ch -= (y + sh) - dh;
1482 }
1483
1484 if(y < 0)
1485 {
1486 y = 0;
1487 }
1488
1489 u = (drawmethod->water.watermode == 1) ? distortion((int)s, amplitude) : amplitude;
1490 wavelength = 256 / drawmethod->water.wavelength;
1491 s += sy * wavelength;
1492
1493 printf("drawing water ... \n");
1494
1495 // Copy data
1496 do
1497 {
1498 s = s - (int)s + (int)s % 256;
1499 t = distortion((int)s, amplitude) - u;
1500
1501 dbeginx = x + t;
1502 dendx = x + t + sw;
1503
1504 if(dbeginx >= dw || dendx <= 0)
1505 {
1506 dbeginx = dendx = sbeginx = sendx = 0; //Nothing to draw
1507 }
1508 //clip both
1509 else if(dbeginx < 0 && dendx > dw)
1510 {
1511 sbeginx = -dbeginx;
1512 sendx = sbeginx + dw;
1513 dbeginx = 0;
1514 dendx = dw;
1515 }
1516 //clip left
1517 else if(dbeginx < 0)
1518 {
1519 sbeginx = -dbeginx;
1520 sendx = sw;
1521 dbeginx = 0;
1522 }
1523 // clip right
1524 else if(dendx > dw)
1525 {
1526 sbeginx = 0;
1527 sendx = dw - dbeginx;
1528 dendx = dw;
1529 }
1530 // clip none
1531 else
1532 {
1533 sbeginx = 0;
1534 sendx = sw;
1535 }
1536 if(pixelformat == PIXEL_8 && !transbg && src->screen->magic == screen_magic)
1537 {
1538 dest_seek(dbeginx, y);
1539 src_seek(sbeginx, sy);
1540 copy_pixel_block(dendx - dbeginx);
1541 }
1542 else
1543 {
1544 bytestocopy = dendx - dbeginx;
1545 //TODO: optimize this if necessary
1546 for(t = 0, dest_seek(dbeginx, y), src_seek(sbeginx, sy); t < bytestocopy; t++, dest_inc(), src_inc())
1547 {
1548 //draw_pixel_gfx(dest, src, dbeginx, y, sbeginx, sy);
1549 write_pixel();
1550 }
1551 }
1552
1553 s += wavelength;
1554 y++;
1555 sy++;
1556 }
1557 while(--ch);
1558 }
1559
gfx_draw_plane(s_screen * dest,gfx_entry * src,int x,int y,int centerx,int centery,s_drawmethod * drawmethod)1560 void gfx_draw_plane(s_screen *dest, gfx_entry *src, int x, int y, int centerx, int centery, s_drawmethod *drawmethod)
1561 {
1562
1563 int i, j, dx, dy, sx, sy, width, height, copyh;
1564 float osxpos, sxpos, sypos, sxstep, systep, xpos, ypos, factor, size, cx, beginsize, endsize;
1565
1566 init_gfx_global_draw_stuff(dest, src, drawmethod);
1567 if(!trans_sw)
1568 {
1569 return;
1570 }
1571
1572 centerx += drawmethod->centerx;
1573 centery += drawmethod->centery;
1574
1575 x -= centerx;
1576 y -= centery;
1577
1578 xpos = x;
1579 ypos = y;
1580
1581 beginsize = drawmethod->water.beginsize;
1582 endsize = drawmethod->water.endsize;
1583
1584 if(beginsize < 0 || endsize < 0)
1585 {
1586 return;
1587 }
1588
1589 width = trans_sw;
1590 height = trans_sh;
1591
1592 // Check dimensions
1593 if(x >= trans_dw)
1594 {
1595 return;
1596 }
1597 if(y >= trans_dh)
1598 {
1599 return;
1600 }
1601 if(x < 0)
1602 {
1603 width += x;
1604 x = 0;
1605 }
1606 if(y < 0)
1607 {
1608 copyh = -y;
1609 height += y;
1610 y = 0;
1611 }
1612 else
1613 {
1614 copyh = 0;
1615 }
1616 if(x + width > trans_dw)
1617 {
1618 width = trans_dw - x;
1619 }
1620 if(y + height > trans_dh)
1621 {
1622 height = trans_dh - y;
1623 }
1624 if(width <= 0)
1625 {
1626 return;
1627 }
1628 if(height <= 0)
1629 {
1630 return;
1631 }
1632
1633 copyh += height;
1634
1635 dy = ypos;
1636 dx = x;
1637
1638 cx = trans_dw / 2.0 - x;
1639
1640 osxpos = drawmethod->water.wavetime - xpos + trans_sw;
1641
1642 factor = (endsize - beginsize) / trans_sh;
1643 size = beginsize;
1644
1645 sypos = 0.0;
1646 for(i = 0; i < copyh; i++, dy++, size += factor, sypos += systep)
1647 {
1648 sy = (int)sypos;
1649 sy %= trans_sh;
1650 if(sy < 0)
1651 {
1652 sy += trans_sh;
1653 }
1654 sxstep = 1 / size;
1655 switch(drawmethod->water.perspective)
1656 {
1657 case 1: // tile
1658 systep = sxstep;
1659 break;
1660 case 2: //stretch
1661 systep = sxstep * trans_sh / (float)trans_sw;
1662 break;
1663 default:
1664 systep = 1.0;
1665 }
1666 if(dy < 0)
1667 {
1668 continue;
1669 }
1670 sxpos = osxpos - cx * sxstep;
1671
1672 //dest_seek(dx, dy);
1673 for(j = 0; j < width; j++, sxpos += sxstep)
1674 {
1675 sx = (int)sxpos;
1676 sx %= trans_sw;
1677 if(sx < 0)
1678 {
1679 sx += trans_sw;
1680 }
1681 //src_seek(sx, sy);
1682 draw_pixel_gfx(dest, src, dx + j, dy, sx, sy);
1683 //write_pixel();
1684 //dest_inc();
1685 }
1686 }
1687
1688 }
1689
1690