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