]> icculus.org git repositories - btb/d2x.git/blob - 2d/bitblt.c
fix compiler warnings, #ifdef out dos-only code
[btb/d2x.git] / 2d / bitblt.c
1 /* $Id: bitblt.c,v 1.8 2002-09-04 23:29:53 btb Exp $ */
2 /*
3 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
4 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
5 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
6 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
7 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
8 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
9 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
10 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
11 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
12 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
13 */
14
15 /*
16  *
17  * Routines for bitblt's.
18  *
19  * Old Log:
20  * Revision 1.29  1995/03/14  12:14:28  john
21  * Added code to double horz/vert bitblts.
22  *
23  * Revision 1.28  1995/03/13  09:01:48  john
24  * Fixed bug with VFX1 screen not tall enough.
25  *
26  * Revision 1.27  1995/03/01  15:38:10  john
27  * Better ModeX support.
28  *
29  * Revision 1.26  1994/12/15  12:19:00  john
30  * Added gr_bm_bitblt (clipped!) function.
31  *
32  * Revision 1.25  1994/12/09  18:58:42  matt
33  * Took out include of 3d.h
34  *
35  * Revision 1.24  1994/11/28  17:08:32  john
36  * Took out some unused functions in linear.asm, moved
37  * gr_linear_movsd from linear.asm to bitblt.c, made sure that
38  * the code in ibiblt.c sets the direction flags before rep movsing.
39  *
40  * Revision 1.22  1994/11/23  16:04:00  john
41  * Fixed generic rle'ing to use new bit method.
42  *
43  * Revision 1.21  1994/11/18  22:51:03  john
44  * Changed a bunch of shorts to ints in calls.
45  *
46  * Revision 1.20  1994/11/10  15:59:48  john
47  * Fixed bugs with canvas's being created with bogus bm_flags.
48  *
49  * Revision 1.19  1994/11/09  21:03:35  john
50  * Added RLE for svga gr_ubitmap.
51  *
52  * Revision 1.18  1994/11/09  17:41:29  john
53  * Made a slow version of rle bitblt to svga, modex.
54  *
55  * Revision 1.17  1994/11/09  16:35:15  john
56  * First version with working RLE bitmaps.
57  *
58  * Revision 1.16  1994/11/04  10:06:58  john
59  * Added fade table for fading fonts. Made font that partially clips
60  * not print a warning message.
61  *
62  * Revision 1.15  1994/09/22  16:08:38  john
63  * Fixed some palette stuff.
64  *
65  * Revision 1.14  1994/09/19  11:44:27  john
66  * Changed call to allocate selector to the dpmi module.
67  *
68  * Revision 1.13  1994/08/08  13:03:00  john
69  * Fixed bug in gr_bitmap in modex
70  *
71  * Revision 1.12  1994/07/13  19:47:23  john
72  * Fixed bug with modex bitblt to page 2 not working.
73  *
74  * Revision 1.11  1994/05/31  11:10:52  john
75  * *** empty log message ***
76  *
77  * Revision 1.10  1994/03/18  15:24:34  matt
78  * Removed interlace stuff
79  *
80  * Revision 1.9  1994/02/18  15:32:20  john
81  * *** empty log message ***
82  *
83  * Revision 1.8  1994/02/01  13:22:54  john
84  * *** empty log message ***
85  *
86  * Revision 1.7  1994/01/13  08:28:25  mike
87  * Modify rect copy to copy alternate scanlines when in interlaced mode.
88  *
89  * Revision 1.6  1993/12/28  12:09:46  john
90  * added lbitblt.asm
91  *
92  * Revision 1.5  1993/10/26  13:18:09  john
93  * *** empty log message ***
94  *
95  * Revision 1.4  1993/10/15  16:23:30  john
96  * y
97  *
98  * Revision 1.3  1993/09/13  17:52:58  john
99  * Fixed bug in BitBlt linear to SVGA
100  *
101  * Revision 1.2  1993/09/08  14:47:00  john
102  * Made bitmap00 add rowsize instead of bitmap width.
103  * Other routines might have this problem too.
104  *
105  * Revision 1.1  1993/09/08  11:43:01  john
106  * Initial revision
107  *
108  */
109
110 #ifdef HAVE_CONFIG_H
111 #include <conf.h>
112 #endif
113
114 #include "pa_enabl.h"                   //$$POLY_ACC
115 #include "u_mem.h"
116 #include "gr.h"
117 #include "grdef.h"
118 #include "rle.h"
119 #include "mono.h"
120 #include "byteswap.h"       // because of rle code that has short for row offsets
121 #include "error.h"
122
123 #ifdef OGL
124 #include "ogl_init.h"
125 #endif
126
127 #if defined(POLY_ACC)
128 #include "poly_acc.h"
129 #endif
130
131 int gr_bitblt_dest_step_shift = 0;
132 int gr_bitblt_double = 0;
133 ubyte *gr_bitblt_fade_table=NULL;
134
135 extern void gr_vesa_bitmap( grs_bitmap * source, grs_bitmap * dest, int x, int y );
136
137 #ifdef NO_ASM
138
139 #define THRESHOLD   8
140
141 #ifdef RELEASE
142 #define test_byteblit   0
143 #else
144 ubyte test_byteblit = 0;
145 #endif
146
147 void gr_linear_movsd(ubyte * src, ubyte * dest, unsigned int num_pixels )
148 {
149         int i;
150         uint n, r;
151         double *d, *s;
152         ubyte *d1, *s1;
153
154 // check to see if we are starting on an even byte boundry
155 // if not, move appropriate number of bytes to even
156 // 8 byte boundry
157
158         if ( (num_pixels < THRESHOLD) || (((int)src & 0x7) != ((int)dest & 0x7)) || test_byteblit ) {
159                 for (i = 0; i < num_pixels; i++)
160                         *dest++ = *src++;
161                 return;
162         }
163
164         i = 0;
165         if ((r = (int)src & 0x7)) {
166                 for (i = 0; i < 8 - r; i++)
167                         *dest++ = *src++;
168         }
169         num_pixels -= i;
170
171         n = num_pixels / 8;
172         r = num_pixels % 8;
173         s = (double *)src;
174         d = (double *)dest;
175         for (i = 0; i < n; i++)
176                 *d++ = *s++;
177         s1 = (ubyte *)s;
178         d1 = (ubyte *)d;
179         for (i = 0; i < r; i++)
180                 *d1++ = *s1++;
181 }
182
183 #endif  //#ifdef NO_ASM
184
185
186 static void gr_linear_rep_movsdm(ubyte * src, ubyte * dest, unsigned int num_pixels );
187
188 #if !defined(NO_ASM) && defined(__WATCOMC__)
189
190 #pragma aux gr_linear_rep_movsdm parm [esi] [edi] [ecx] modify exact [ecx esi edi eax] = \
191 "nextpixel:"                \
192     "mov    al,[esi]"       \
193     "inc    esi"            \
194     "cmp    al, 255"        \
195     "je skip_it"            \
196     "mov    [edi], al"      \
197 "skip_it:"                  \
198     "inc    edi"            \
199     "dec    ecx"            \
200     "jne    nextpixel";
201
202 #elif !defined(NO_ASM) && defined(__GNUC__)
203
204 static inline void gr_linear_rep_movsdm(ubyte * src, ubyte * dest, unsigned int num_pixels ) {
205         int dummy[3];
206  __asm__ __volatile__ (
207 "0: ;"
208 " movb  (%%esi), %%al;"
209 " incl  %%esi;"
210 " cmpb  $255, %%al;"
211 " je    1f;"
212 " movb  %%al,(%%edi);"
213 "1: ;"
214 " incl  %%edi;"
215 " decl  %%ecx;"
216 " jne   0b"
217  : "=S" (dummy[0]), "=D" (dummy[1]), "=c" (dummy[2])
218  : "0" (src), "1" (dest), "2" (num_pixels)
219  : "%eax");
220 }
221
222 #elif !defined(NO_ASM) && defined(_MSC_VER)
223
224 __inline void gr_linear_rep_movsdm(ubyte * src, ubyte * dest, unsigned int num_pixels )
225 {
226  __asm {
227   nextpixel:
228   mov esi, [src]
229   mov edi, [dest]
230   mov ecx, [num_pixels]
231   mov al,  [esi]
232   inc esi
233   cmp al,  255
234   je skip_it
235   mov [edi], al
236   skip_it:
237   inc edi
238   dec ecx
239   jne nextpixel
240  }
241 }
242
243 #else
244
245 static void gr_linear_rep_movsdm(ubyte * src, ubyte * dest, unsigned int num_pixels )
246 {
247         int i;
248         for (i=0; i<num_pixels; i++ ) {
249                 if (*src != TRANSPARENCY_COLOR )
250                         *dest = *src;
251                 dest++;
252                 src++;
253         }
254 }
255
256 #endif
257
258 static void gr_linear_rep_movsdm_faded(ubyte * src, ubyte * dest, unsigned int num_pixels, ubyte fade_value );
259
260 #if !defined(NO_ASM) && defined(__WATCOMC__)
261
262 #pragma aux gr_linear_rep_movsdm_faded parm [esi] [edi] [ecx] [ebx] modify exact [ecx esi edi eax ebx] = \
263 "  xor eax, eax"                    \
264 "  mov ah, bl"                      \
265 "nextpixel:"                        \
266     "mov    al,[esi]"               \
267     "inc    esi"                    \
268     "cmp    al, 255"                \
269     "je skip_it"                    \
270     "mov  al, gr_fade_table[eax]"   \
271     "mov    [edi], al"              \
272 "skip_it:"                          \
273     "inc    edi"                    \
274     "dec    ecx"                    \
275     "jne    nextpixel";
276
277 #elif !defined(NO_ASM) && defined(__GNUC__)
278
279 /* #pragma aux gr_linear_rep_movsdm_faded parm [esi] [edi] [ecx] [ebx] modify exact [ecx esi edi eax ebx] */
280 static inline void gr_linear_rep_movsdm_faded(ubyte * src, ubyte * dest, unsigned int num_pixels, ubyte fade_value ) {
281         int dummy[4];
282  __asm__ __volatile__ (
283 "  xorl   %%eax, %%eax;"
284 "  movb   %%bl, %%ah;"
285 "0:;"
286 "  movb   (%%esi), %%al;"
287 "  incl   %%esi;"
288 "  cmpb   $255, %%al;"
289 "  je 1f;"
290 #ifdef __linux__
291 "  movb   gr_fade_table(%%eax), %%al;"
292 #else
293 "  movb   _gr_fade_table(%%eax), %%al;"
294 #endif
295 "  movb   %%al, (%%edi);"
296 "1:"
297 "  incl   %%edi;"
298 "  decl   %%ecx;"
299 "  jne    0b"
300  : "=S" (dummy[0]), "=D" (dummy[1]), "=c" (dummy[2]), "=b" (dummy[3])
301  : "0" (src), "1" (dest), "2" (num_pixels), "3" (fade_value)
302  : "%eax");
303 }
304
305 #elif !defined(NO_ASM) && defined(_MSC_VER)
306
307 __inline void gr_linear_rep_movsdm_faded(void * src, void * dest, unsigned int num_pixels, ubyte fade_value )
308 {
309  __asm {
310   mov esi, [src]
311   mov edi, [dest]
312   mov ecx, [num_pixels]
313   movzx ebx, byte ptr [fade_value]
314   xor eax, eax
315   mov ah, bl
316   nextpixel:
317   mov al, [esi]
318   inc esi
319   cmp al, 255
320   je skip_it
321   mov al, gr_fade_table[eax]
322   mov [edi], al
323   skip_it:
324   inc edi
325   dec ecx
326   jne nextpixel
327  }
328 }
329
330 #else
331
332 static void gr_linear_rep_movsdm_faded(ubyte * src, ubyte * dest, unsigned int num_pixels, ubyte fade_value )
333 {
334         int i;
335         ubyte source;
336         ubyte *fade_base;
337
338         fade_base = gr_fade_table + (fade_value * 256);
339
340         for (i=num_pixels; i != 0; i-- )
341         {
342                 source = *src;
343                 if (source != (ubyte)TRANSPARENCY_COLOR )
344                         *dest = *(fade_base + source);
345                 dest++;
346                 src++;
347         }
348 }
349
350 #endif
351
352
353 static void gr_linear_rep_movsd_2x(ubyte * src, ubyte * dest, unsigned int num_dest_pixels );
354
355 #if !defined(NO_ASM) && defined(__WATCOMC__)
356
357 #pragma aux gr_linear_rep_movsd_2x parm [esi] [edi] [ecx] modify exact [ecx esi edi eax ebx] = \
358     "shr    ecx, 1"             \
359     "jnc    nextpixel"          \
360     "mov    al, [esi]"          \
361     "mov    [edi], al"          \
362     "inc    esi"                \
363     "inc    edi"                \
364     "cmp    ecx, 0"             \
365     "je done"                   \
366 "nextpixel:"                    \
367     "mov    al,[esi]"           \
368     "mov    ah, al"             \
369     "mov    [edi], ax"          \
370     "inc    esi"                \
371     "inc    edi"                \
372     "inc    edi"                \
373     "dec    ecx"                \
374     "jne    nextpixel"          \
375 "done:"
376
377 #elif !defined(NO_ASM) && defined (__GNUC__)
378
379 static inline void gr_linear_rep_movsd_2x(ubyte * src, ubyte * dest, unsigned int num_dest_pixels ) {
380 /* #pragma aux gr_linear_rep_movsd_2x parm [esi] [edi] [ecx] modify exact [ecx esi edi eax ebx] */
381         int dummy[3];
382  __asm__ __volatile__ (
383     "shrl   $1, %%ecx;"
384     "jnc    0f;"
385     "movb   (%%esi), %%al;"
386     "movb   %%al, (%%edi);"
387     "incl   %%esi;"
388     "incl   %%edi;"
389     "cmpl   $0, %%ecx;"
390     "je 1f;"
391 "0: ;"
392     "movb   (%%esi), %%al;"
393     "movb   %%al, %%ah;"
394     "movw   %%ax, (%%edi);"
395     "incl   %%esi;"
396     "incl   %%edi;"
397     "incl   %%edi;"
398     "decl   %%ecx;"
399     "jne    0b;"
400 "1:"
401  : "=S" (dummy[0]), "=D" (dummy[1]), "=c" (dummy[2])
402  : "0" (src), "1" (dest), "2" (num_dest_pixels)
403  :      "%eax");
404 }
405
406 #elif !defined(NO_ASM) && defined(_MSC_VER)
407
408 __inline void gr_linear_rep_movsd_2x(ubyte * src, ubyte * dest, unsigned int num_dest_pixels )
409 {
410  __asm {
411   mov esi, [src]
412   mov edi, [dest]
413   mov ecx, [num_dest_pixels]
414   shr ecx, 1
415   jnc nextpixel
416   mov al, [esi]
417   mov [edi], al
418   inc esi
419   inc edi
420   cmp ecx, 0
421   je done
422 nextpixel:
423   mov al, [esi]
424   mov ah, al
425   mov [edi], ax
426   inc esi
427   inc edi
428   inc edi
429   dec ecx
430   jne nextpixel
431 done:
432  }
433 }
434
435 #else
436
437 static void gr_linear_rep_movsd_2x(ubyte *src, ubyte *dest, unsigned int num_pixels)
438 {
439         double  *d = (double *)dest;
440         uint    *s = (uint *)src;
441         uint    doubletemp[2];
442         uint    temp, work;
443         int     i;
444
445         if (num_pixels & 0x3) {
446                 // not a multiple of 4?  do single pixel at a time
447                 for (i=0; i<num_pixels; i++) {
448                         *dest++ = *src;
449                         *dest++ = *src++;
450                 }
451                 return;
452         }
453
454         for (i = 0; i < num_pixels / 4; i++) {
455                 temp = work = *s++;
456
457                 temp = ((temp >> 8) & 0x00FFFF00) | (temp & 0xFF0000FF); // 0xABCDEFGH -> 0xABABCDEF
458                 temp = ((temp >> 8) & 0x000000FF) | (temp & 0xFFFFFF00); // 0xABABCDEF -> 0xABABCDCD
459                 doubletemp[0] = temp;
460
461                 work = ((work << 8) & 0x00FFFF00) | (work & 0xFF0000FF); // 0xABCDEFGH -> 0xABEFGHGH
462                 work = ((work << 8) & 0xFF000000) | (work & 0x00FFFFFF); // 0xABEFGHGH -> 0xEFEFGHGH
463                 doubletemp[1] = work;
464
465                 *d = *(double *) &(doubletemp[0]);
466                 d++;
467         }
468 }
469
470 #endif
471
472
473 #ifdef __MSDOS__
474
475 static void modex_copy_column(ubyte * src, ubyte * dest, int num_pixels, int src_rowsize, int dest_rowsize );
476
477 #if !defined(NO_ASM) && defined(__WATCOMC__)
478
479 #pragma aux modex_copy_column parm [esi] [edi] [ecx] [ebx] [edx] modify exact [ecx esi edi] = \
480 "nextpixel:"            \
481     "mov    al,[esi]"   \
482     "add    esi, ebx"   \
483     "mov    [edi], al"  \
484     "add    edi, edx"   \
485     "dec    ecx"        \
486     "jne    nextpixel"
487
488 #elif !defined(NO_ASM) && defined(__GNUC__)
489
490 static inline void modex_copy_column(ubyte * src, ubyte * dest, int num_pixels, int src_rowsize, int dest_rowsize ) {
491 /*#pragma aux modex_copy_column parm [esi] [edi] [ecx] [ebx] [edx] modify exact [ecx esi edi] = */
492  __asm__ __volatile__ (
493 "0: ;"
494     "movb   (%%esi), %%al;"
495     "addl   %%ebx, %%esi;"
496     "movb   %%al, (%%edi);"
497     "addl   %%edx, %%edi;"
498     "decl   %%ecx;"
499     "jne    0b"
500  : : "S" (src), "D" (dest), "c" (num_pixels), "b" (src_rowsize), "d" (dest_rowsize)
501  : "%eax", "%ecx", "%esi", "%edi");
502 }
503
504 #else
505
506 static void modex_copy_column(ubyte * src, ubyte * dest, int num_pixels, int src_rowsize, int dest_rowsize )
507 {
508         src = src;
509         dest = dest;
510         num_pixels = num_pixels;
511         src_rowsize = src_rowsize;
512         dest_rowsize = dest_rowsize;
513         Int3();
514 }
515
516 #endif
517
518
519 static void modex_copy_column_m(ubyte * src, ubyte * dest, int num_pixels, int src_rowsize, int dest_rowsize );
520
521 #if !defined(NO_ASM) && defined(__WATCOMC__)
522
523 #pragma aux modex_copy_column_m parm [esi] [edi] [ecx] [ebx] [edx] modify exact [ecx esi edi] = \
524 "nextpixel:"            \
525     "mov    al,[esi]"   \
526     "add    esi, ebx"   \
527     "cmp    al, 255"    \
528     "je skip_itx"       \
529     "mov    [edi], al"  \
530 "skip_itx:"             \
531     "add    edi, edx"   \
532     "dec    ecx"        \
533     "jne    nextpixel"
534
535 #elif !defined(NO_ASM) && defined(__GNUC__)
536
537 static inline void modex_copy_column_m(ubyte * src, ubyte * dest, int num_pixels, int src_rowsize, int dest_rowsize ) {
538 /* #pragma aux modex_copy_column_m parm [esi] [edi] [ecx] [ebx] [edx] modify exact [ecx esi edi] = */
539  int dummy[3];
540  __asm__ __volatile__ (
541 "0: ;"
542     "movb    (%%esi), %%al;"
543     "addl    %%ebx, %%esi;"
544     "cmpb    $255, %%al;"
545     "je 1f;"
546     "movb   %%al, (%%edi);"
547 "1: ;"
548     "addl   %%edx, %%edi;"
549     "decl   %%ecx;"
550     "jne    0b"
551  : "=c" (dummy[0]), "=S" (dummy[1]), "=D" (dummy[2])
552  : "1" (src), "2" (dest), "0" (num_pixels), "b" (src_rowsize), "d" (dest_rowsize)
553  :      "%eax" );
554 }
555
556 #else
557
558 static void modex_copy_column_m(ubyte * src, ubyte * dest, int num_pixels, int src_rowsize, int dest_rowsize )
559 {
560         src = src;
561         dest = dest;
562         num_pixels = num_pixels;
563         src_rowsize = src_rowsize;
564         dest_rowsize = dest_rowsize;
565         Int3();
566 }
567
568 #endif
569
570 #endif /* __MSDOS__ */
571
572 void gr_ubitmap00( int x, int y, grs_bitmap *bm )
573 {
574         register int y1;
575         int dest_rowsize;
576
577         unsigned char * dest;
578         unsigned char * src;
579
580         dest_rowsize=grd_curcanv->cv_bitmap.bm_rowsize << gr_bitblt_dest_step_shift;
581         dest = &(grd_curcanv->cv_bitmap.bm_data[ dest_rowsize*y+x ]);
582
583         src = bm->bm_data;
584
585         for (y1=0; y1 < bm->bm_h; y1++ )    {
586                 if (gr_bitblt_double)
587                         gr_linear_rep_movsd_2x( src, dest, bm->bm_w );
588                 else
589                         gr_linear_movsd( src, dest, bm->bm_w );
590                 src += bm->bm_rowsize;
591                 dest+= (int)(dest_rowsize);
592         }
593 }
594
595 void gr_ubitmap00m( int x, int y, grs_bitmap *bm )
596 {
597         register int y1;
598         int dest_rowsize;
599
600         unsigned char * dest;
601         unsigned char * src;
602
603         dest_rowsize=grd_curcanv->cv_bitmap.bm_rowsize << gr_bitblt_dest_step_shift;
604         dest = &(grd_curcanv->cv_bitmap.bm_data[ dest_rowsize*y+x ]);
605
606         src = bm->bm_data;
607
608         if (gr_bitblt_fade_table==NULL) {
609                 for (y1=0; y1 < bm->bm_h; y1++ )    {
610                         gr_linear_rep_movsdm( src, dest, bm->bm_w );
611                         src += bm->bm_rowsize;
612                         dest+= (int)(dest_rowsize);
613                 }
614         } else {
615                 for (y1=0; y1 < bm->bm_h; y1++ )    {
616                         gr_linear_rep_movsdm_faded( src, dest, bm->bm_w, gr_bitblt_fade_table[y1+y] );
617                         src += bm->bm_rowsize;
618                         dest+= (int)(dest_rowsize);
619                 }
620         }
621 }
622
623 #if 0
624 "       jmp     aligned4        "   \
625 "       mov eax, edi            "   \
626 "       and eax, 11b            "   \
627 "       jz      aligned4        "   \
628 "       mov ebx, 4              "   \
629 "       sub ebx, eax            "   \
630 "       sub ecx, ebx            "   \
631 "alignstart:                    "   \
632 "       mov al, [esi]           "   \
633 "       add esi, 4              "   \
634 "       mov [edi], al           "   \
635 "       inc edi                 "   \
636 "       dec ebx                 "   \
637 "       jne alignstart          "   \
638 "aligned4:                      "
639 #endif
640
641 #ifdef __MSDOS__
642
643 static void modex_copy_scanline( ubyte * src, ubyte * dest, int npixels );
644
645 #if !defined(NO_ASM) && defined(__WATCOMC__)
646
647 #pragma aux modex_copy_scanline parm [esi] [edi] [ecx] modify exact [ecx esi edi eax ebx edx] = \
648 "       mov ebx, ecx            "   \
649 "       and ebx, 11b            "   \
650 "       shr ecx, 2              "   \
651 "       cmp ecx, 0              "   \
652 "       je      no2group        "   \
653 "next4pixels:                   "   \
654 "       mov al, [esi+8]         "   \
655 "       mov ah, [esi+12]        "   \
656 "       shl eax, 16             "   \
657 "       mov al, [esi]           "   \
658 "       mov ah, [esi+4]         "   \
659 "       mov [edi], eax          "   \
660 "       add esi, 16             "   \
661 "       add edi, 4              "   \
662 "       dec ecx                 "   \
663 "       jne next4pixels         "   \
664 "no2group:                      "   \
665 "       cmp ebx, 0              "   \
666 "       je      done2           "   \
667 "finishend:                     "   \
668 "       mov al, [esi]           "   \
669 "       add esi, 4              "   \
670 "       mov [edi], al           "   \
671 "       inc edi                 "   \
672 "       dec ebx                 "   \
673 "       jne finishend           "   \
674 "done2:                         ";
675
676 #elif !defined (NO_ASM) && defined(__GNUC__)
677
678 static inline void modex_copy_scanline( ubyte * src, ubyte * dest, int npixels ) {
679 /* #pragma aux modex_copy_scanline parm [esi] [edi] [ecx] modify exact [ecx esi edi eax ebx edx] */
680 int dummy[3];
681  __asm__ __volatile__ (
682 "       movl %%ecx, %%ebx;"
683 "       andl $3, %%ebx;"
684 "       shrl $2, %%ecx;"
685 "       cmpl $0, %%ecx;"
686 "       je   1f;"
687 "0: ;"
688 "       movb 8(%%esi), %%al;"
689 "       movb 12(%%esi), %%ah;"
690 "       shll $16, %%eax;"
691 "       movb (%%esi), %%al;"
692 "       movb 4(%%esi), %%ah;"
693 "       movl %%eax, (%%edi);"
694 "       addl $16, %%esi;"
695 "       addl $4, %%edi;"
696 "       decl %%ecx;"
697 "       jne 0b;"
698 "1: ;"
699 "       cmpl $0, %%ebx;"
700 "       je      3f;"
701 "2: ;"
702 "       movb (%%esi), %%al;"
703 "       addl $4, %%esi;"
704 "       movb %%al, (%%edi);"
705 "       incl %%edi;"
706 "       decl %%ebx;"
707 "       jne 2b;"
708 "3:"
709  : "=c" (dummy[0]), "=S" (dummy[1]), "=D" (dummy[2])
710  : "1" (src), "2" (dest), "0" (npixels)
711  :      "%eax", "%ebx", "%edx" );
712 }
713
714 #else
715
716 static void modex_copy_scanline( ubyte * src, ubyte * dest, int npixels )
717 {
718         src = src;
719         dest = dest;
720         npixels = npixels;
721         Int3();
722 }
723
724 #endif
725
726 static void modex_copy_scanline_2x( ubyte * src, ubyte * dest, int npixels );
727
728 #if !defined(NO_ASM) && defined(__WATCOMC__)
729
730 #pragma aux modex_copy_scanline_2x parm [esi] [edi] [ecx] modify exact [ecx esi edi eax ebx edx] = \
731 "       mov ebx, ecx            "   \
732 "       and ebx, 11b            "   \
733 "       shr ecx, 2              "   \
734 "       cmp ecx, 0              "   \
735 "       je      no2group        "   \
736 "next4pixels:                   "   \
737 "       mov al, [esi+4]         "   \
738 "       mov ah, [esi+6]         "   \
739 "       shl eax, 16             "   \
740 "       mov al, [esi]           "   \
741 "       mov ah, [esi+2]         "   \
742 "       mov [edi], eax          "   \
743 "       add esi, 8              "   \
744 "       add edi, 4              "   \
745 "       dec ecx                 "   \
746 "       jne next4pixels         "   \
747 "no2group:                      "   \
748 "       cmp ebx, 0              "   \
749 "       je      done2           "   \
750 "finishend:                     "   \
751 "       mov al, [esi]           "   \
752 "       add esi, 2              "   \
753 "       mov [edi], al           "   \
754 "       inc edi                 "   \
755 "       dec ebx                 "   \
756 "       jne finishend           "   \
757 "done2:                         ";
758
759 #elif !defined(NO_ASM) && defined(__GNUC__)
760
761 static inline void modex_copy_scanline_2x( ubyte * src, ubyte * dest, int npixels ) {
762 /* #pragma aux modex_copy_scanline_2x parm [esi] [edi] [ecx] modify exact [ecx esi edi eax ebx edx] = */
763 int dummy[3];
764  __asm__ __volatile__ (
765 "       movl %%ecx, %%ebx;"
766 "       andl $3, %%ebx;"
767 "       shrl $2, %%ecx;"
768 "       cmpl $0, %%ecx;"
769 "       je 1f;"
770 "0: ;"
771 "       movb 4(%%esi), %%al;"
772 "       movb 6(%%esi), %%ah;"
773 "       shll $16, %%eax;"
774 "       movb (%%esi), %%al;"
775 "       movb 2(%%esi), %%ah;"
776 "       movl %%eax, (%%edi);"
777 "       addl $8, %%esi;"
778 "       addl $4, %%edi;"
779 "       decl %%ecx;"
780 "       jne 0b;"
781 "1: ;"
782 "       cmp $0, %%ebx;"
783 "       je  3f;"
784 "2:"
785 "       movb (%%esi),%%al;"
786 "       addl $2, %%esi;"
787 "       movb %%al, (%%edi);"
788 "       incl %%edi;"
789 "       decl %%ebx;"
790 "       jne 2b;"
791 "3:"
792  : "=c" (dummy[0]), "=S" (dummy[1]), "=D" (dummy[2])
793  : "1" (src), "2" (dest), "0" (npixels)
794  :      "%eax", "%ebx", "%edx" );
795 }
796
797 #else
798
799 static void modex_copy_scanline_2x( ubyte * src, ubyte * dest, int npixels )
800 {
801         src = src;
802         dest = dest;
803         npixels = npixels;
804         Int3();
805 }
806
807 #endif
808
809
810 // From Linear to ModeX
811 void gr_bm_ubitblt01(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
812 {
813         ubyte * dbits;
814         ubyte * sbits;
815         int sstep,dstep;
816         int y,plane;
817         int w1;
818
819         if ( w < 4 ) return;
820
821         sstep = src->bm_rowsize;
822         dstep = dest->bm_rowsize << gr_bitblt_dest_step_shift;
823
824         if (!gr_bitblt_double) {
825                 for (plane=0; plane<4; plane++ ) {
826                         gr_modex_setplane( (plane+dx)&3 );
827                         sbits = src->bm_data + (src->bm_rowsize * sy) + sx + plane;
828                         dbits = &gr_video_memory[(dest->bm_rowsize * dy) + ((plane+dx)/4) ];
829                         w1 = w >> 2;
830                         if ( (w&3) > plane ) w1++;
831                         for (y=dy; y < dy+h; y++ ) {
832                                 modex_copy_scanline( sbits, dbits, w1 );
833                                 dbits += dstep;
834                                 sbits += sstep;
835                         }
836                 }
837         } else {
838                 for (plane=0; plane<4; plane++ ) {
839                         gr_modex_setplane( (plane+dx)&3 );
840                         sbits = src->bm_data + (src->bm_rowsize * sy) + sx + plane/2;
841                         dbits = &gr_video_memory[(dest->bm_rowsize * dy) + ((plane+dx)/4) ];
842                         w1 = w >> 2;
843                         if ( (w&3) > plane ) w1++;
844                         for (y=dy; y < dy+h; y++ ) {
845                                 modex_copy_scanline_2x( sbits, dbits, w1 );
846                                 dbits += dstep;
847                                 sbits += sstep;
848                         }
849                 }
850         }
851 }
852
853
854 // From Linear to ModeX masked
855 void gr_bm_ubitblt01m(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
856 {
857         //ubyte * dbits1;
858         //ubyte * sbits1;
859
860         ubyte * dbits;
861         ubyte * sbits;
862
863         int x;
864         //int y;
865
866         sbits =   src->bm_data  + (src->bm_rowsize * sy) + sx;
867         dbits =   &gr_video_memory[(dest->bm_rowsize * dy) + dx/4];
868
869         for (x=dx; x < dx+w; x++ ) {
870                 gr_modex_setplane( x&3 );
871
872                 //sbits1 = sbits;
873                 //dbits1 = dbits;
874                 //for (y=0; y < h; y++ )    {
875                 //      *dbits1 = *sbits1;
876                 //      sbits1 += src_bm_rowsize;
877                 //      dbits1 += dest_bm_rowsize;
878                 //}
879                 modex_copy_column_m(sbits, dbits, h, src->bm_rowsize, dest->bm_rowsize << gr_bitblt_dest_step_shift );
880
881                 sbits++;
882                 if ( (x&3)==3 )
883                         dbits++;
884         }
885 }
886
887 #endif /* __MSDOS__ */
888
889
890 void gr_ubitmap012( int x, int y, grs_bitmap *bm )
891 {
892         register int x1, y1;
893         unsigned char * src;
894
895         src = bm->bm_data;
896
897         for (y1=y; y1 < (y+bm->bm_h); y1++ )    {
898                 for (x1=x; x1 < (x+bm->bm_w); x1++ )    {
899                         gr_setcolor( *src++ );
900                         gr_upixel( x1, y1 );
901                 }
902         }
903 }
904
905 void gr_ubitmap012m( int x, int y, grs_bitmap *bm )
906 {
907         register int x1, y1;
908         unsigned char * src;
909
910         src = bm->bm_data;
911
912         for (y1=y; y1 < (y+bm->bm_h); y1++ ) {
913                 for (x1=x; x1 < (x+bm->bm_w); x1++ ) {
914                         if ( *src != TRANSPARENCY_COLOR ) {
915                                 gr_setcolor( *src );
916                                 gr_upixel( x1, y1 );
917                         }
918                         src++;
919                 }
920         }
921 }
922
923 #if defined(POLY_ACC)
924 void gr_ubitmap05( int x, int y, grs_bitmap *bm )
925 {
926         register int x1, y1;
927         unsigned char *src;
928         short *dst;
929         int mod;
930
931         pa_flush();
932         src = bm->bm_data;
933         dst = (short *)(DATA + y * ROWSIZE + x * PA_BPP);
934         mod = ROWSIZE / 2 - bm->bm_w;
935
936         for (y1=y; y1 < (y+bm->bm_h); y1++ )    {
937                 for (x1=x; x1 < (x+bm->bm_w); x1++ )    {
938                         *dst++ = pa_clut[*src++];
939                 }
940                 dst += mod;
941         }
942 }
943
944 void gr_ubitmap05m( int x, int y, grs_bitmap *bm )
945 {
946         register int x1, y1;
947         unsigned char *src;
948         short *dst;
949         int mod;
950
951         pa_flush();
952         src = bm->bm_data;
953         dst = (short *)(DATA + y * ROWSIZE + x * PA_BPP);
954         mod = ROWSIZE / 2 - bm->bm_w;
955
956         for (y1=y; y1 < (y+bm->bm_h); y1++ )    {
957                 for (x1=x; x1 < (x+bm->bm_w); x1++ )    {
958                         if ( *src != TRANSPARENCY_COLOR )   {
959                                 *dst = pa_clut[*src];
960                         }
961                         src++;
962                         ++dst;
963                 }
964                 dst += mod;
965         }
966 }
967
968 void gr_bm_ubitblt05_rle(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
969 {
970         unsigned short * dbits;
971         unsigned char * sbits, scanline[640];
972         int i, data_offset, j, nextrow;
973
974         pa_flush();
975         nextrow=dest->bm_rowsize/PA_BPP;
976
977         data_offset = 1;
978         if (src->bm_flags & BM_FLAG_RLE_BIG)
979                 data_offset = 2;
980
981         sbits = &src->bm_data[4 + (src->bm_h*data_offset)];
982         for (i=0; i<sy; i++ )
983                 sbits += (int)(INTEL_SHORT(src->bm_data[4+(i*data_offset)]));
984
985         dbits = (unsigned short *)(dest->bm_data + (dest->bm_rowsize * dy) + dx*PA_BPP);
986
987         // No interlacing, copy the whole buffer.
988         for (i=0; i < h; i++ )    {
989                 gr_rle_expand_scanline( scanline, sbits, sx, sx+w-1 );
990                 for(j = 0; j != w; ++j)
991                         dbits[j] = pa_clut[scanline[j]];
992                 if ( src->bm_flags & BM_FLAG_RLE_BIG )
993                         sbits += (int)INTEL_SHORT(*((short *)&(src->bm_data[4+((i+sy)*data_offset)])));
994                 else
995                         sbits += (int)(src->bm_data[4+i+sy]);
996                 dbits += nextrow;
997         }
998 }
999
1000 void gr_bm_ubitblt05m_rle(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
1001 {
1002         unsigned short * dbits;
1003         unsigned char * sbits, scanline[640];
1004         int i, data_offset, j, nextrow;
1005
1006         pa_flush();
1007         nextrow=dest->bm_rowsize/PA_BPP;
1008         data_offset = 1;
1009         if (src->bm_flags & BM_FLAG_RLE_BIG)
1010                 data_offset = 2;
1011
1012         sbits = &src->bm_data[4 + (src->bm_h*data_offset)];
1013         for (i=0; i<sy; i++ )
1014                 sbits += (int)(INTEL_SHORT(src->bm_data[4+(i*data_offset)]));
1015
1016         dbits = (unsigned short *)(dest->bm_data + (dest->bm_rowsize * dy) + dx*PA_BPP);
1017
1018         // No interlacing, copy the whole buffer.
1019         for (i=0; i < h; i++ )    {
1020                 gr_rle_expand_scanline( scanline, sbits, sx, sx+w-1 );
1021                 for(j = 0; j != w; ++j)
1022                         if(scanline[j] != TRANSPARENCY_COLOR)
1023                                 dbits[j] = pa_clut[scanline[j]];
1024                 if ( src->bm_flags & BM_FLAG_RLE_BIG )
1025                         sbits += (int)INTEL_SHORT(*((short *)&(src->bm_data[4+((i+sy)*data_offset)])));
1026                 else
1027                         sbits += (int)(src->bm_data[4+i+sy]);
1028                 dbits += nextrow;
1029         }
1030 }
1031 #endif
1032
1033 void gr_ubitmapGENERIC(int x, int y, grs_bitmap * bm)
1034 {
1035         register int x1, y1;
1036
1037         for (y1=0; y1 < bm->bm_h; y1++ )    {
1038                 for (x1=0; x1 < bm->bm_w; x1++ )    {
1039                         gr_setcolor( gr_gpixel(bm,x1,y1) );
1040                         gr_upixel( x+x1, y+y1 );
1041                 }
1042         }
1043 }
1044
1045 void gr_ubitmapGENERICm(int x, int y, grs_bitmap * bm)
1046 {
1047         register int x1, y1;
1048         ubyte c;
1049
1050         for (y1=0; y1 < bm->bm_h; y1++ ) {
1051                 for (x1=0; x1 < bm->bm_w; x1++ ) {
1052                         c = gr_gpixel(bm,x1,y1);
1053                         if ( c != TRANSPARENCY_COLOR ) {
1054                                 gr_setcolor( c );
1055                                 gr_upixel( x+x1, y+y1 );
1056                         }
1057                 }
1058         }
1059 }
1060
1061
1062 #ifdef __MSDOS__
1063 // From linear to SVGA
1064 void gr_bm_ubitblt02(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
1065 {
1066         unsigned char * sbits;
1067
1068         unsigned int offset, EndingOffset, VideoLocation;
1069
1070         int sbpr, dbpr, y1, page, BytesToMove;
1071
1072         sbpr = src->bm_rowsize;
1073
1074         dbpr = dest->bm_rowsize << gr_bitblt_dest_step_shift;
1075
1076         VideoLocation = (unsigned int)dest->bm_data + (dest->bm_rowsize * dy) + dx;
1077
1078         sbits = src->bm_data + ( sbpr*sy ) + sx;
1079
1080         for (y1=0; y1 < h; y1++ )    {
1081
1082                 page    = VideoLocation >> 16;
1083                 offset  = VideoLocation & 0xFFFF;
1084
1085                 gr_vesa_setpage( page );
1086
1087                 EndingOffset = offset+w-1;
1088
1089                 if ( EndingOffset <= 0xFFFF )
1090                 {
1091                         if ( gr_bitblt_double )
1092                                 gr_linear_rep_movsd_2x( (void *)sbits, (void *)(offset+0xA0000), w );
1093                         else
1094                                 gr_linear_movsd( (void *)sbits, (void *)(offset+0xA0000), w );
1095
1096                         VideoLocation += dbpr;
1097                         sbits += sbpr;
1098                 }
1099                 else
1100                 {
1101                         BytesToMove = 0xFFFF-offset+1;
1102
1103                         if ( gr_bitblt_double )
1104                                 gr_linear_rep_movsd_2x( (void *)sbits, (void *)(offset+0xA0000), BytesToMove );
1105                         else
1106                                 gr_linear_movsd( (void *)sbits, (void *)(offset+0xA0000), BytesToMove );
1107
1108                         page++;
1109                         gr_vesa_setpage(page);
1110
1111                         if ( gr_bitblt_double )
1112                                 gr_linear_rep_movsd_2x( (void *)(sbits+BytesToMove/2), (void *)0xA0000, EndingOffset - 0xFFFF );
1113                         else
1114                                 gr_linear_movsd( (void *)(sbits+BytesToMove), (void *)0xA0000, EndingOffset - 0xFFFF );
1115
1116                         VideoLocation += dbpr;
1117                         sbits += sbpr;
1118                 }
1119         }
1120 }
1121 #endif
1122
1123 #ifdef __MSDOS__
1124
1125 void gr_bm_ubitblt02m(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
1126 {
1127         unsigned char * sbits;
1128
1129         unsigned int offset, EndingOffset, VideoLocation;
1130
1131         int sbpr, dbpr, y1, page, BytesToMove;
1132
1133         sbpr = src->bm_rowsize;
1134
1135         dbpr = dest->bm_rowsize << gr_bitblt_dest_step_shift;
1136
1137         VideoLocation = (unsigned int)dest->bm_data + (dest->bm_rowsize * dy) + dx;
1138
1139         sbits = src->bm_data + ( sbpr*sy ) + sx;
1140
1141         for (y1=0; y1 < h; y1++ )    {
1142
1143                 page    = VideoLocation >> 16;
1144                 offset  = VideoLocation & 0xFFFF;
1145
1146                 gr_vesa_setpage( page );
1147
1148                 EndingOffset = offset+w-1;
1149
1150                 if ( EndingOffset <= 0xFFFF )
1151                 {
1152                         gr_linear_rep_movsdm( (void *)sbits, (void *)(offset+0xA0000), w );
1153
1154                         VideoLocation += dbpr;
1155                         sbits += sbpr;
1156                 }
1157                 else
1158                 {
1159                         BytesToMove = 0xFFFF-offset+1;
1160
1161                         gr_linear_rep_movsdm( (void *)sbits, (void *)(offset+0xA0000), BytesToMove );
1162
1163                         page++;
1164                         gr_vesa_setpage(page);
1165
1166                         gr_linear_rep_movsdm( (void *)(sbits+BytesToMove), (void *)0xA0000, EndingOffset - 0xFFFF );
1167
1168                         VideoLocation += dbpr;
1169                         sbits += sbpr;
1170                 }
1171         }
1172 }
1173
1174
1175 // From SVGA to linear
1176 void gr_bm_ubitblt20(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
1177 {
1178         unsigned char * dbits;
1179
1180         unsigned int offset, offset1, offset2;
1181
1182         int sbpr, dbpr, y1, page;
1183
1184         dbpr = dest->bm_rowsize;
1185
1186         sbpr = src->bm_rowsize;
1187
1188         for (y1=0; y1 < h; y1++ )    {
1189
1190                 offset2 =   (unsigned int)src->bm_data  + (sbpr * (y1+sy)) + sx;
1191                 dbits   =   dest->bm_data + (dbpr * (y1+dy)) + dx;
1192
1193                 page = offset2 >> 16;
1194                 offset = offset2 & 0xFFFF;
1195                 offset1 = offset+w-1;
1196                 gr_vesa_setpage( page );
1197
1198                 if ( offset1 > 0xFFFF )  {
1199                         // Overlaps two pages
1200                         while( offset <= 0xFFFF )
1201                                 *dbits++ = gr_video_memory[offset++];
1202                         offset1 -= (0xFFFF+1);
1203                         offset = 0;
1204                         page++;
1205                         gr_vesa_setpage(page);
1206                 }
1207                 while( offset <= offset1 )
1208                         *dbits++ = gr_video_memory[offset++];
1209
1210         }
1211 }
1212
1213 #endif
1214
1215 //@extern int Interlacing_on;
1216
1217 // From Linear to Linear
1218 void gr_bm_ubitblt00(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
1219 {
1220         unsigned char * dbits;
1221         unsigned char * sbits;
1222         //int src_bm_rowsize_2, dest_bm_rowsize_2;
1223         int dstep;
1224
1225         int i;
1226
1227         sbits =   src->bm_data  + (src->bm_rowsize * sy) + sx;
1228         dbits =   dest->bm_data + (dest->bm_rowsize * dy) + dx;
1229
1230         dstep = dest->bm_rowsize << gr_bitblt_dest_step_shift;
1231
1232         // No interlacing, copy the whole buffer.
1233         for (i=0; i < h; i++ )    {
1234                 if (gr_bitblt_double)
1235                         gr_linear_rep_movsd_2x( sbits, dbits, w );
1236                 else
1237                         gr_linear_movsd( sbits, dbits, w );
1238                 sbits += src->bm_rowsize;
1239                 dbits += dstep;
1240         }
1241 }
1242 // From Linear to Linear Masked
1243 void gr_bm_ubitblt00m(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
1244 {
1245         unsigned char * dbits;
1246         unsigned char * sbits;
1247         //int src_bm_rowsize_2, dest_bm_rowsize_2;
1248
1249         int i;
1250
1251         sbits =   src->bm_data  + (src->bm_rowsize * sy) + sx;
1252         dbits =   dest->bm_data + (dest->bm_rowsize * dy) + dx;
1253
1254         // No interlacing, copy the whole buffer.
1255
1256         if (gr_bitblt_fade_table==NULL) {
1257                 for (i=0; i < h; i++ )    {
1258                         gr_linear_rep_movsdm( sbits, dbits, w );
1259                         sbits += src->bm_rowsize;
1260                         dbits += dest->bm_rowsize;
1261                 }
1262         } else {
1263                 for (i=0; i < h; i++ )    {
1264                         gr_linear_rep_movsdm_faded( sbits, dbits, w, gr_bitblt_fade_table[dy+i] );
1265                         sbits += src->bm_rowsize;
1266                         dbits += dest->bm_rowsize;
1267                 }
1268         }
1269 }
1270
1271
1272 extern void gr_lbitblt( grs_bitmap * source, grs_bitmap * dest, int height, int width );
1273
1274 #if 1 //def MACINTOSH
1275
1276 // width == number of destination pixels
1277
1278 void gr_linear_movsd_double(ubyte *src, ubyte *dest, int width)
1279 {
1280         double  *d = (double *)dest;
1281         uint    *s = (uint *)src;
1282         uint    doubletemp[2];
1283         uint    temp, work;
1284         int     i, num_pixels;
1285
1286         num_pixels = width / 2;
1287         if ( (num_pixels & 0x3) || (((int)src & 0x7) != ((int)dest & 0x7)) ) {
1288                 // not a multiple of 4?  do single pixel at a time
1289                 for (i=0; i<num_pixels; i++) {
1290                         *dest++ = *src;
1291                         *dest++ = *src++;
1292                 }
1293                 return;
1294         }
1295
1296         for (i = 0; i < num_pixels / 4; i++) {
1297                 temp = work = *s++;
1298
1299                 temp = ((temp >> 8) & 0x00FFFF00) | (temp & 0xFF0000FF); // 0xABCDEFGH -> 0xABABCDEF
1300                 temp = ((temp >> 8) & 0x000000FF) | (temp & 0xFFFFFF00); // 0xABABCDEF -> 0xABABCDCD
1301                 doubletemp[0] = temp;
1302
1303                 work = ((work << 8) & 0x00FFFF00) | (work & 0xFF0000FF); // 0xABCDEFGH -> 0xABEFGHGH
1304                 work = ((work << 8) & 0xFF000000) | (work & 0x00FFFFFF); // 0xABEFGHGH -> 0xEFEFGHGH
1305                 doubletemp[1] = work;
1306
1307                 *d = *(double *) &(doubletemp[0]);
1308                 d++;
1309         }
1310 }
1311
1312 //extern void BlitLargeAlign(ubyte *draw_buffer, int dstRowBytes, ubyte *dstPtr, int w, int h, int modulus);
1313
1314 #ifdef MACINTOSH
1315 asm void BlitLargeAlign(ubyte *rSrcPtr, int rDblDStrd, ubyte *rDst1Ptr, int rWidth, int rHeight, int rModulus)
1316 {
1317     stw     r31,-4(SP)          // store non-volatile reg in red zone
1318     addi    r5,r5,-8            // subtract 8 from dst
1319     stw     r30,-8(SP)          // store non-volatile reg in red zone
1320
1321     la      r30,-16(SP)         // calculate copy of local 8-byte variable
1322     sub     r9,r8,r6
1323                                 // rSStrd = modulus - w
1324     add     r31,r5,r4           // dst2 = dstRowBytes + dst1
1325     sub     r4,r4,r6            // r4 = dstRowBytes - w
1326     addi    r7,r7,-1            // subtract 1 from height count
1327     srawi   r6,r6,2             // rWidth = w >> 2
1328     addi    r3,r3,-4            // subtract 4 from src
1329     addi    r6,r6,-1            // subtract 1 from width count
1330     add     r4,r4,r4            // rDblDStrd = 2 * r4
1331
1332 BlitLargeAlignY:                // y count is in r7
1333     lwzu     r10,4(r3)          // load a long into r10
1334     mr       r0,r10             // put a copy in r0
1335     mr       r11,r10
1336 // these are simplified -- can't use 'em    inslwi   r0,r10,16,8
1337 // these are simplified -- can't use 'em    insrwi   r11,r10,16,8
1338     rlwimi   r0,r10,24,8,31
1339     rlwimi   r11,r10,8,8,23
1340     rlwimi   r0,r10,16,24,31
1341     stw      r0,0(r30)
1342     rlwimi   r11,r10,16,0,7
1343     stw      r11,4(r30)
1344     mtctr       r6              // copy x count into the counter
1345     lfd      fp0,0(r30)
1346
1347 BlitLargeAlignX:
1348     lwzu     r10,4(r3)          // load a long into r10
1349     stfdu    fp0,8(r5)
1350     mr       r0,r10             // put a copy in r0
1351     mr       r11,r10
1352 // simplefied   inslwi   r0,r10,16,8
1353 // simplefied   insrwi   r11,r10,16,8
1354     rlwimi   r0,r10,24,8,31
1355     rlwimi   r11,r10,8,8,23
1356     rlwimi   r0,r10,16,24,31
1357     stw      r0,0(r30)
1358     rlwimi   r11,r10,16,0,7
1359     stw      r11,4(r30)
1360     stfdu    fp0,8(r31)
1361     lfd      fp0,0(r30)
1362     bdnz     BlitLargeAlignX    // loop over all x
1363
1364     stfdu    fp0,8(r5)
1365     addic.   r7,r7,-1           // decrement the counter
1366     add      r3,r3,r9
1367                                 // src += sstride
1368     add      r5,r5,r4
1369                                 // dst1 += dstride
1370     stfdu    fp0,8(r31)
1371     add      r31,r31,r4
1372                                 // dst2 += dstride
1373     bne      BlitLargeAlignY    // loop for all y
1374
1375     lwz     r30,-8(SP)          // restore non-volatile regs
1376     lwz     r31,-4(SP)          // restore non-volatile regs
1377     blr                         // return to caller
1378 }
1379
1380 void gr_bm_ubitblt_double(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap *src, grs_bitmap *dest)
1381 {
1382         ubyte * dbits;
1383         ubyte * sbits;
1384         int dstep, i;
1385
1386         sbits = src->bm_data  + (src->bm_rowsize * sy) + sx;
1387         dbits = dest->bm_data + (dest->bm_rowsize * dy) + dx;
1388         dstep = dest->bm_rowsize << gr_bitblt_dest_step_shift;
1389         Assert( !((int)dbits & 0x7) );  // assert to check double word alignment
1390         BlitLargeAlign(sbits, dstep, dbits, src->bm_w, src->bm_h, src->bm_rowsize);
1391 }
1392 #endif
1393
1394 // w and h are the doubled width and height
1395
1396 void gr_bm_ubitblt_double_slow(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap *src, grs_bitmap *dest)
1397 {
1398         ubyte * dbits;
1399         ubyte * sbits;
1400         int dstep, i;
1401
1402         sbits = src->bm_data  + (src->bm_rowsize * sy) + sx;
1403         dbits = dest->bm_data + (dest->bm_rowsize * dy) + dx;
1404         dstep = dest->bm_rowsize << gr_bitblt_dest_step_shift;
1405
1406         for (i=0; i < h; i++ )    {
1407
1408                 gr_linear_movsd_double(sbits, dbits, w);
1409                 dbits += dstep;
1410                 if (i & 1)
1411                         sbits += src->bm_rowsize;
1412         }
1413 }
1414
1415 #endif
1416
1417
1418 // Clipped bitmap ...
1419
1420 void gr_bitmap( int x, int y, grs_bitmap *bm )
1421 {
1422         int dx1=x, dx2=x+bm->bm_w-1;
1423         int dy1=y, dy2=y+bm->bm_h-1;
1424         int sx=0, sy=0;
1425
1426         if ((dx1 >= grd_curcanv->cv_bitmap.bm_w ) || (dx2 < 0)) return;
1427         if ((dy1 >= grd_curcanv->cv_bitmap.bm_h) || (dy2 < 0)) return;
1428         if ( dx1 < 0 ) { sx = -dx1; dx1 = 0; }
1429         if ( dy1 < 0 ) { sy = -dy1; dy1 = 0; }
1430         if ( dx2 >= grd_curcanv->cv_bitmap.bm_w ) { dx2 = grd_curcanv->cv_bitmap.bm_w-1; }
1431         if ( dy2 >= grd_curcanv->cv_bitmap.bm_h ) { dy2 = grd_curcanv->cv_bitmap.bm_h-1; }
1432
1433         // Draw bitmap bm[x,y] into (dx1,dy1)-(dx2,dy2)
1434
1435         gr_bm_ubitblt(dx2-dx1+1,dy2-dy1+1, dx1, dy1, sx, sy, bm, &grd_curcanv->cv_bitmap );
1436
1437 }
1438
1439 //-NOT-used // From linear to SVGA
1440 //-NOT-used void gr_bm_ubitblt02_2x(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
1441 //-NOT-used {
1442 //-NOT-used     unsigned char * sbits;
1443 //-NOT-used
1444 //-NOT-used     unsigned int offset, EndingOffset, VideoLocation;
1445 //-NOT-used
1446 //-NOT-used     int sbpr, dbpr, y1, page, BytesToMove;
1447 //-NOT-used
1448 //-NOT-used     sbpr = src->bm_rowsize;
1449 //-NOT-used
1450 //-NOT-used     dbpr = dest->bm_rowsize << gr_bitblt_dest_step_shift;
1451 //-NOT-used
1452 //-NOT-used     VideoLocation = (unsigned int)dest->bm_data + (dest->bm_rowsize * dy) + dx;
1453 //-NOT-used
1454 //-NOT-used     sbits = src->bm_data + ( sbpr*sy ) + sx;
1455 //-NOT-used
1456 //-NOT-used     for (y1=0; y1 < h; y1++ )    {
1457 //-NOT-used
1458 //-NOT-used             page    = VideoLocation >> 16;
1459 //-NOT-used             offset  = VideoLocation & 0xFFFF;
1460 //-NOT-used
1461 //-NOT-used             gr_vesa_setpage( page );
1462 //-NOT-used
1463 //-NOT-used             EndingOffset = offset+w-1;
1464 //-NOT-used
1465 //-NOT-used             if ( EndingOffset <= 0xFFFF )
1466 //-NOT-used             {
1467 //-NOT-used                     gr_linear_rep_movsd_2x( (void *)sbits, (void *)(offset+0xA0000), w );
1468 //-NOT-used
1469 //-NOT-used                     VideoLocation += dbpr;
1470 //-NOT-used                     sbits += sbpr;
1471 //-NOT-used             }
1472 //-NOT-used             else
1473 //-NOT-used             {
1474 //-NOT-used                     BytesToMove = 0xFFFF-offset+1;
1475 //-NOT-used
1476 //-NOT-used                     gr_linear_rep_movsd_2x( (void *)sbits, (void *)(offset+0xA0000), BytesToMove );
1477 //-NOT-used
1478 //-NOT-used                     page++;
1479 //-NOT-used                     gr_vesa_setpage(page);
1480 //-NOT-used
1481 //-NOT-used                     gr_linear_rep_movsd_2x( (void *)(sbits+BytesToMove/2), (void *)0xA0000, EndingOffset - 0xFFFF );
1482 //-NOT-used
1483 //-NOT-used                     VideoLocation += dbpr;
1484 //-NOT-used                     sbits += sbpr;
1485 //-NOT-used             }
1486 //-NOT-used
1487 //-NOT-used
1488 //-NOT-used     }
1489 //-NOT-used }
1490
1491
1492 //-NOT-used // From Linear to Linear
1493 //-NOT-used void gr_bm_ubitblt00_2x(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
1494 //-NOT-used {
1495 //-NOT-used     unsigned char * dbits;
1496 //-NOT-used     unsigned char * sbits;
1497 //-NOT-used     //int src_bm_rowsize_2, dest_bm_rowsize_2;
1498 //-NOT-used
1499 //-NOT-used     int i;
1500 //-NOT-used
1501 //-NOT-used     sbits =   src->bm_data  + (src->bm_rowsize * sy) + sx;
1502 //-NOT-used     dbits =   dest->bm_data + (dest->bm_rowsize * dy) + dx;
1503 //-NOT-used
1504 //-NOT-used     // No interlacing, copy the whole buffer.
1505 //-NOT-used     for (i=0; i < h; i++ )    {
1506 //-NOT-used             gr_linear_rep_movsd_2x( sbits, dbits, w );
1507 //-NOT-used
1508 //-NOT-used             sbits += src->bm_rowsize;
1509 //-NOT-used             dbits += dest->bm_rowsize << gr_bitblt_dest_step_shift;
1510 //-NOT-used     }
1511 //-NOT-used }
1512
1513 void gr_bm_ubitblt00_rle(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
1514 {
1515         unsigned char * dbits;
1516         unsigned char * sbits;
1517         int i, data_offset;
1518
1519         data_offset = 1;
1520         if (src->bm_flags & BM_FLAG_RLE_BIG)
1521                 data_offset = 2;
1522
1523         sbits = &src->bm_data[4 + (src->bm_h*data_offset)];
1524
1525         for (i=0; i<sy; i++ )
1526                 sbits += (int)(INTEL_SHORT(src->bm_data[4+(i*data_offset)]));
1527
1528         dbits = dest->bm_data + (dest->bm_rowsize * dy) + dx;
1529
1530         // No interlacing, copy the whole buffer.
1531         for (i=0; i < h; i++ )    {
1532                 gr_rle_expand_scanline( dbits, sbits, sx, sx+w-1 );
1533                 if ( src->bm_flags & BM_FLAG_RLE_BIG )
1534                         sbits += (int)INTEL_SHORT(*((short *)&(src->bm_data[4+((i+sy)*data_offset)])));
1535                 else
1536                         sbits += (int)(src->bm_data[4+i+sy]);
1537                 dbits += dest->bm_rowsize << gr_bitblt_dest_step_shift;
1538         }
1539 }
1540
1541 void gr_bm_ubitblt00m_rle(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
1542 {
1543         unsigned char * dbits;
1544         unsigned char * sbits;
1545         int i, data_offset;
1546
1547         data_offset = 1;
1548         if (src->bm_flags & BM_FLAG_RLE_BIG)
1549                 data_offset = 2;
1550
1551         sbits = &src->bm_data[4 + (src->bm_h*data_offset)];
1552         for (i=0; i<sy; i++ )
1553                 sbits += (int)(INTEL_SHORT(src->bm_data[4+(i*data_offset)]));
1554
1555         dbits = dest->bm_data + (dest->bm_rowsize * dy) + dx;
1556
1557         // No interlacing, copy the whole buffer.
1558         for (i=0; i < h; i++ )    {
1559                 gr_rle_expand_scanline_masked( dbits, sbits, sx, sx+w-1 );
1560                 if ( src->bm_flags & BM_FLAG_RLE_BIG )
1561                         sbits += (int)INTEL_SHORT(*((short *)&(src->bm_data[4+((i+sy)*data_offset)])));
1562                 else
1563                         sbits += (int)(src->bm_data[4+i+sy]);
1564                 dbits += dest->bm_rowsize << gr_bitblt_dest_step_shift;
1565         }
1566 }
1567
1568 // in rle.c
1569
1570 extern void gr_rle_expand_scanline_generic( grs_bitmap * dest, int dx, int dy, ubyte *src, int x1, int x2  );
1571 extern void gr_rle_expand_scanline_generic_masked( grs_bitmap * dest, int dx, int dy, ubyte *src, int x1, int x2  );
1572 extern void gr_rle_expand_scanline_svga_masked( grs_bitmap * dest, int dx, int dy, ubyte *src, int x1, int x2  );
1573
1574 void gr_bm_ubitblt0x_rle(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
1575 {
1576         int i, data_offset;
1577         register int y1;
1578         unsigned char * sbits;
1579
1580         //mprintf( 0, "SVGA RLE!\n" );
1581
1582         data_offset = 1;
1583         if (src->bm_flags & BM_FLAG_RLE_BIG)
1584                 data_offset = 2;
1585
1586         sbits = &src->bm_data[4 + (src->bm_h*data_offset)];
1587         for (i=0; i<sy; i++ )
1588                 sbits += (int)(INTEL_SHORT(src->bm_data[4+(i*data_offset)]));
1589
1590         for (y1=0; y1 < h; y1++ )    {
1591                 gr_rle_expand_scanline_generic( dest, dx, dy+y1,  sbits, sx, sx+w-1  );
1592                 if ( src->bm_flags & BM_FLAG_RLE_BIG )
1593                         sbits += (int)INTEL_SHORT(*((short *)&(src->bm_data[4+((y1+sy)*data_offset)])));
1594                 else
1595                         sbits += (int)src->bm_data[4+y1+sy];
1596         }
1597
1598 }
1599
1600 void gr_bm_ubitblt0xm_rle(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
1601 {
1602         int i, data_offset;
1603         register int y1;
1604         unsigned char * sbits;
1605
1606         //mprintf( 0, "SVGA RLE!\n" );
1607
1608         data_offset = 1;
1609         if (src->bm_flags & BM_FLAG_RLE_BIG)
1610                 data_offset = 2;
1611
1612         sbits = &src->bm_data[4 + (src->bm_h*data_offset)];
1613         for (i=0; i<sy; i++ )
1614                 sbits += (int)(INTEL_SHORT(src->bm_data[4+(i*data_offset)]));
1615
1616         for (y1=0; y1 < h; y1++ )    {
1617                 gr_rle_expand_scanline_generic_masked( dest, dx, dy+y1,  sbits, sx, sx+w-1  );
1618                 if ( src->bm_flags & BM_FLAG_RLE_BIG )
1619                         sbits += (int)INTEL_SHORT(*((short *)&(src->bm_data[4+((y1+sy)*data_offset)])));
1620                 else
1621                         sbits += (int)src->bm_data[4+y1+sy];
1622         }
1623
1624 }
1625
1626 #ifdef __MSDOS__
1627 void gr_bm_ubitblt02m_rle(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
1628 {
1629         int i, data_offset;
1630         register int y1;
1631         unsigned char * sbits;
1632
1633         //mprintf( 0, "SVGA RLE!\n" );
1634
1635         data_offset = 1;
1636         if (src->bm_flags & BM_FLAG_RLE_BIG)
1637                 data_offset = 2;
1638
1639         sbits = &src->bm_data[4 + (src->bm_h*data_offset)];
1640         for (i=0; i<sy; i++ )
1641                 sbits += (int)(INTEL_SHORT(src->bm_data[4+(i*data_offset)]));
1642
1643         for (y1=0; y1 < h; y1++ )    {
1644                 gr_rle_expand_scanline_svga_masked( dest, dx, dy+y1,  sbits, sx, sx+w-1  );
1645                 if ( src->bm_flags & BM_FLAG_RLE_BIG )
1646                         sbits += (int)INTEL_SHORT(*((short *)&(src->bm_data[4+((y1+sy)*data_offset)])));
1647                 else
1648                         sbits += (int)src->bm_data[4+y1+sy];
1649         }
1650 }
1651 #endif
1652
1653 void gr_bm_ubitblt(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
1654 {
1655         register int x1, y1;
1656
1657         if ( (src->bm_type == BM_LINEAR) && (dest->bm_type == BM_LINEAR ))
1658         {
1659                 if ( src->bm_flags & BM_FLAG_RLE )
1660                         gr_bm_ubitblt00_rle( w, h, dx, dy, sx, sy, src, dest );
1661                 else
1662                         gr_bm_ubitblt00( w, h, dx, dy, sx, sy, src, dest );
1663                 return;
1664         }
1665
1666 #ifdef OGL
1667         if ( (src->bm_type == BM_LINEAR) && (dest->bm_type == BM_OGL ))
1668         {
1669                 ogl_ubitblt(w, h, dx, dy, sx, sy, src, dest);
1670                 return;
1671         }
1672         if ( (src->bm_type == BM_OGL) && (dest->bm_type == BM_LINEAR ))
1673         {
1674                 ogl_ubitblt_tolinear(w, h, dx, dy, sx, sy, src, dest);
1675                 return;
1676         }
1677         if ( (src->bm_type == BM_OGL) && (dest->bm_type == BM_OGL ))
1678         {
1679                 ogl_ubitblt_copy(w, h, dx, dy, sx, sy, src, dest);
1680                 return;
1681         }
1682 #endif
1683
1684 #ifdef D1XD3D
1685         if ( (src->bm_type == BM_LINEAR) && (dest->bm_type == BM_DIRECTX ))
1686         {
1687                 Assert ((int)dest->bm_data == BM_D3D_RENDER || (int)dest->bm_data == BM_D3D_DISPLAY);
1688                 Win32_BlitLinearToDirectX_bm (src, sx, sy, w, h, dx, dy, 0);
1689                 return;
1690         }
1691         if ( (src->bm_type == BM_DIRECTX) && (dest->bm_type == BM_LINEAR ))
1692         {
1693                 return;
1694         }
1695         if ( (src->bm_type == BM_DIRECTX) && (dest->bm_type == BM_DIRECTX ))
1696         {
1697                 return;
1698         }
1699 #endif
1700
1701         if ( (src->bm_flags & BM_FLAG_RLE ) && (src->bm_type == BM_LINEAR) ) {
1702                 gr_bm_ubitblt0x_rle(w, h, dx, dy, sx, sy, src, dest );
1703                 return;
1704         }
1705
1706 #ifdef __MSDOS__
1707         if ( (src->bm_type == BM_LINEAR) && (dest->bm_type == BM_SVGA ))
1708         {
1709                 gr_bm_ubitblt02( w, h, dx, dy, sx, sy, src, dest );
1710                 return;
1711         }
1712
1713         if ( (src->bm_type == BM_SVGA) && (dest->bm_type == BM_LINEAR ))
1714         {
1715                 gr_bm_ubitblt20( w, h, dx, dy, sx, sy, src, dest );
1716                 return;
1717         }
1718
1719         if ( (src->bm_type == BM_LINEAR) && (dest->bm_type == BM_MODEX ))
1720         {
1721                 gr_bm_ubitblt01( w, h, dx+XOFFSET, dy+YOFFSET, sx, sy, src, dest );
1722                 return;
1723         }
1724 #endif
1725
1726 #if defined(POLY_ACC)
1727         if ( (src->bm_type == BM_LINEAR) && (dest->bm_type == BM_LINEAR15 ))
1728         {
1729                 ubyte *s = src->bm_data + sy * src->bm_rowsize + sx;
1730                 ushort *t = (ushort *)(dest->bm_data + dy * dest->bm_rowsize + dx * PA_BPP);
1731                 int x;
1732                 pa_flush();
1733                 for(;h--;)
1734                 {
1735                         for(x = 0; x < w; x++)
1736                                 t[x] = pa_clut[s[x]];
1737                         s += src->bm_rowsize;
1738                         t += dest->bm_rowsize / PA_BPP;
1739                 }
1740                 return;
1741         }
1742
1743         if ( (src->bm_type == BM_LINEAR15) && (dest->bm_type == BM_LINEAR15 ))
1744         {
1745                 pa_blit(dest, dx, dy, src, sx, sy, w, h);
1746                 return;
1747         }
1748 #endif
1749
1750         for (y1=0; y1 < h; y1++ )    {
1751                 for (x1=0; x1 < w; x1++ )    {
1752                         gr_bm_pixel( dest, dx+x1, dy+y1, gr_gpixel(src,sx+x1,sy+y1) );
1753                 }
1754         }
1755 }
1756
1757 void gr_bm_bitblt(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
1758 {
1759         int dx1=dx, dx2=dx+dest->bm_w-1;
1760         int dy1=dy, dy2=dy+dest->bm_h-1;
1761
1762         int sx1=sx, sx2=sx+src->bm_w-1;
1763         int sy1=sy, sy2=sy+src->bm_h-1;
1764
1765         if ((dx1 >= dest->bm_w ) || (dx2 < 0)) return;
1766         if ((dy1 >= dest->bm_h ) || (dy2 < 0)) return;
1767         if ( dx1 < 0 ) { sx1 += -dx1; dx1 = 0; }
1768         if ( dy1 < 0 ) { sy1 += -dy1; dy1 = 0; }
1769         if ( dx2 >= dest->bm_w ) { dx2 = dest->bm_w-1; }
1770         if ( dy2 >= dest->bm_h ) { dy2 = dest->bm_h-1; }
1771
1772         if ((sx1 >= src->bm_w ) || (sx2 < 0)) return;
1773         if ((sy1 >= src->bm_h ) || (sy2 < 0)) return;
1774         if ( sx1 < 0 ) { dx1 += -sx1; sx1 = 0; }
1775         if ( sy1 < 0 ) { dy1 += -sy1; sy1 = 0; }
1776         if ( sx2 >= src->bm_w ) { sx2 = src->bm_w-1; }
1777         if ( sy2 >= src->bm_h ) { sy2 = src->bm_h-1; }
1778
1779         // Draw bitmap bm[x,y] into (dx1,dy1)-(dx2,dy2)
1780         if ( dx2-dx1+1 < w )
1781                 w = dx2-dx1+1;
1782         if ( dy2-dy1+1 < h )
1783                 h = dy2-dy1+1;
1784         if ( sx2-sx1+1 < w )
1785                 w = sx2-sx1+1;
1786         if ( sy2-sy1+1 < h )
1787                 h = sy2-sy1+1;
1788
1789         gr_bm_ubitblt(w,h, dx1, dy1, sx1, sy1, src, dest );
1790 }
1791
1792 void gr_ubitmap( int x, int y, grs_bitmap *bm )
1793 {
1794         int source, dest;
1795
1796         source = bm->bm_type;
1797         dest = TYPE;
1798
1799         if (source==BM_LINEAR) {
1800                 switch( dest )
1801                 {
1802                 case BM_LINEAR:
1803                         if ( bm->bm_flags & BM_FLAG_RLE )
1804                                 gr_bm_ubitblt00_rle(bm->bm_w, bm->bm_h, x, y, 0, 0, bm, &grd_curcanv->cv_bitmap );
1805                         else
1806                                 gr_ubitmap00( x, y, bm );
1807                         return;
1808 #ifdef OGL
1809                 case BM_OGL:
1810                         ogl_ubitmapm(x,y,bm);
1811                         return;
1812 #endif
1813 #ifdef D1XD3D
1814                 case BM_DIRECTX:
1815                         Assert ((int)grd_curcanv->cv_bitmap.bm_data == BM_D3D_RENDER || (int)grd_curcanv->cv_bitmap.bm_data == BM_D3D_DISPLAY);
1816                         Win32_BlitLinearToDirectX_bm(bm, 0, 0, bm->bm_w, bm->bm_h, x, y, 0);
1817                         return;
1818 #endif
1819 #ifdef __MSDOS__
1820                 case BM_SVGA:
1821                         if ( bm->bm_flags & BM_FLAG_RLE )
1822                                 gr_bm_ubitblt0x_rle(bm->bm_w, bm->bm_h, x, y, 0, 0, bm, &grd_curcanv->cv_bitmap );
1823                         else
1824                                 gr_vesa_bitmap( bm, &grd_curcanv->cv_bitmap, x, y );
1825                         return;
1826                 case BM_MODEX:
1827                         gr_bm_ubitblt01(bm->bm_w, bm->bm_h, x+XOFFSET, y+YOFFSET, 0, 0, bm, &grd_curcanv->cv_bitmap);
1828                         return;
1829 #endif
1830 #if defined(POLY_ACC)
1831                 case BM_LINEAR15:
1832                         if ( bm->bm_flags & BM_FLAG_RLE )
1833                                 gr_bm_ubitblt05_rle(bm->bm_w, bm->bm_h, x, y, 0, 0, bm, &grd_curcanv->cv_bitmap );
1834                         else
1835                                 gr_ubitmap05( x, y, bm);
1836                         return;
1837
1838 #endif
1839                 default:
1840                         gr_ubitmap012( x, y, bm );
1841                         return;
1842                 }
1843         } else  {
1844                 gr_ubitmapGENERIC(x, y, bm);
1845         }
1846 }
1847
1848
1849 void gr_ubitmapm( int x, int y, grs_bitmap *bm )
1850 {
1851         int source, dest;
1852
1853         source = bm->bm_type;
1854         dest = TYPE;
1855
1856         Assert(x+bm->bm_w <= grd_curcanv->cv_w);
1857         Assert(y+bm->bm_h <= grd_curcanv->cv_h);
1858
1859 #ifdef _3DFX
1860         _3dfx_Blit( x, y, bm );
1861         if ( _3dfx_skip_ddraw )
1862                 return;
1863 #endif
1864
1865         if (source==BM_LINEAR) {
1866                 switch( dest )
1867                 {
1868                 case BM_LINEAR:
1869                         if ( bm->bm_flags & BM_FLAG_RLE )
1870                                 gr_bm_ubitblt00m_rle(bm->bm_w, bm->bm_h, x, y, 0, 0, bm, &grd_curcanv->cv_bitmap );
1871                         else
1872                                 gr_ubitmap00m( x, y, bm );
1873                         return;
1874 #ifdef __MSDOS__
1875                 case BM_SVGA:
1876                         if (bm->bm_flags & BM_FLAG_RLE)
1877                                 gr_bm_ubitblt02m_rle(bm->bm_w, bm->bm_h, x, y, 0, 0, bm, &grd_curcanv->cv_bitmap);
1878                         //gr_bm_ubitblt0xm_rle(bm->bm_w, bm->bm_h, x, y, 0, 0, bm, &grd_curcanv->cv_bitmap);
1879                         else
1880                                 gr_bm_ubitblt02m(bm->bm_w, bm->bm_h, x, y, 0, 0, bm, &grd_curcanv->cv_bitmap);
1881                         //gr_ubitmapGENERICm(x, y, bm);
1882                         return;
1883                 case BM_MODEX:
1884                         gr_bm_ubitblt01m(bm->bm_w, bm->bm_h, x+XOFFSET, y+YOFFSET, 0, 0, bm, &grd_curcanv->cv_bitmap);
1885                         return;
1886 #endif
1887 #if defined(POLY_ACC)
1888                 case BM_LINEAR15:
1889                         if ( bm->bm_flags & BM_FLAG_RLE )
1890                                 gr_bm_ubitblt05m_rle(bm->bm_w, bm->bm_h, x, y, 0, 0, bm, &grd_curcanv->cv_bitmap );
1891                         else
1892                                 gr_ubitmap05m( x, y, bm );
1893                         return;
1894 #endif
1895
1896                 default:
1897                         gr_ubitmap012m( x, y, bm );
1898                         return;
1899                 }
1900         } else {
1901                 gr_ubitmapGENERICm(x, y, bm);
1902         }
1903 }
1904
1905
1906 void gr_bitmapm( int x, int y, grs_bitmap *bm )
1907 {
1908         int dx1=x, dx2=x+bm->bm_w-1;
1909         int dy1=y, dy2=y+bm->bm_h-1;
1910         int sx=0, sy=0;
1911
1912         if ((dx1 >= grd_curcanv->cv_bitmap.bm_w ) || (dx2 < 0)) return;
1913         if ((dy1 >= grd_curcanv->cv_bitmap.bm_h) || (dy2 < 0)) return;
1914         if ( dx1 < 0 ) { sx = -dx1; dx1 = 0; }
1915         if ( dy1 < 0 ) { sy = -dy1; dy1 = 0; }
1916         if ( dx2 >= grd_curcanv->cv_bitmap.bm_w ) { dx2 = grd_curcanv->cv_bitmap.bm_w-1; }
1917         if ( dy2 >= grd_curcanv->cv_bitmap.bm_h ) { dy2 = grd_curcanv->cv_bitmap.bm_h-1; }
1918
1919         // Draw bitmap bm[x,y] into (dx1,dy1)-(dx2,dy2)
1920
1921         if ( (bm->bm_type == BM_LINEAR) && (grd_curcanv->cv_bitmap.bm_type == BM_LINEAR ))
1922         {
1923                 if ( bm->bm_flags & BM_FLAG_RLE )
1924                         gr_bm_ubitblt00m_rle(dx2-dx1+1,dy2-dy1+1, dx1, dy1, sx, sy, bm, &grd_curcanv->cv_bitmap );
1925                 else
1926                         gr_bm_ubitblt00m(dx2-dx1+1,dy2-dy1+1, dx1, dy1, sx, sy, bm, &grd_curcanv->cv_bitmap );
1927                 return;
1928         }
1929 #ifdef __MSDOS__
1930         else if ( (bm->bm_type == BM_LINEAR) && (grd_curcanv->cv_bitmap.bm_type == BM_SVGA ))
1931         {
1932                 gr_bm_ubitblt02m(dx2-dx1+1,dy2-dy1+1, dx1, dy1, sx, sy, bm, &grd_curcanv->cv_bitmap );
1933                 return;
1934         }
1935 #endif
1936
1937         gr_bm_ubitbltm(dx2-dx1+1,dy2-dy1+1, dx1, dy1, sx, sy, bm, &grd_curcanv->cv_bitmap );
1938
1939 }
1940
1941 void gr_bm_ubitbltm(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
1942 {
1943         register int x1, y1;
1944         ubyte c;
1945
1946 #ifdef OGL
1947         if ( (src->bm_type == BM_LINEAR) && (dest->bm_type == BM_OGL ))
1948         {
1949                 ogl_ubitblt(w, h, dx, dy, sx, sy, src, dest);
1950                 return;
1951         }
1952         if ( (src->bm_type == BM_OGL) && (dest->bm_type == BM_LINEAR ))
1953         {
1954                 ogl_ubitblt_tolinear(w, h, dx, dy, sx, sy, src, dest);
1955                 return;
1956         }
1957         if ( (src->bm_type == BM_OGL) && (dest->bm_type == BM_OGL ))
1958         {
1959                 ogl_ubitblt_copy(w, h, dx, dy, sx, sy, src, dest);
1960                 return;
1961         }
1962 #endif
1963 #ifdef D1XD3D
1964         if ( (src->bm_type == BM_LINEAR) && (dest->bm_type == BM_DIRECTX ))
1965         {
1966                 Assert ((int)dest->bm_data == BM_D3D_RENDER || (int)dest->bm_data == BM_D3D_DISPLAY);
1967                 Win32_BlitLinearToDirectX_bm (src, sx, sy, w, h, dx, dy, 1);
1968                 return;
1969         }
1970         if ( (src->bm_type == BM_DIRECTX) && (dest->bm_type == BM_DIRECTX ))
1971         {
1972                 Assert ((int)src->bm_data == BM_D3D_RENDER || (int)src->bm_data == BM_D3D_DISPLAY);
1973                 //Win32_BlitDirectXToDirectX (w, h, dx, dy, sx, sy, src->bm_data, dest->bm_data, 0);
1974                 return;
1975         }
1976 #endif
1977 #if defined(POLY_ACC)
1978         if(src->bm_type == BM_LINEAR && dest->bm_type == BM_LINEAR15)
1979         {
1980                 ubyte *s;
1981                 ushort *d;
1982                 ushort u;
1983                 int smod, dmod;
1984
1985                 pa_flush();
1986                 s = (ubyte *)(src->bm_data + src->bm_rowsize * sy + sx);
1987                 smod = src->bm_rowsize - w;
1988                 d = (ushort *)(dest->bm_data + dest->bm_rowsize * dy + dx * PA_BPP);
1989                 dmod = dest->bm_rowsize / PA_BPP - w;
1990                 for (; h--;) {
1991                         for (x1=w; x1--; ) {
1992                                 if ((u = *s) != TRANSPARENCY_COLOR)
1993                                         *d = pa_clut[u];
1994                                 ++s;
1995                                 ++d;
1996                         }
1997                         s += smod;
1998                         d += dmod;
1999                 }
2000         }
2001
2002         if(src->bm_type == BM_LINEAR15)
2003         {
2004                 Assert(src->bm_type == dest->bm_type);         // I don't support 15 to 8 yet.
2005                 pa_blit_transparent(dest, dx, dy, src, sx, sy, w, h);
2006                 return;
2007         }
2008 #endif
2009
2010         for (y1=0; y1 < h; y1++ )    {
2011                 for (x1=0; x1 < w; x1++ )    {
2012                         if ((c=gr_gpixel(src,sx+x1,sy+y1))!=TRANSPARENCY_COLOR)
2013                                 gr_bm_pixel( dest, dx+x1, dy+y1,c  );
2014                 }
2015         }
2016 }
2017
2018
2019 // rescalling bitmaps, 10/14/99 Jan Bobrowski jb@wizard.ae.krakow.pl
2020
2021 inline void scale_line(byte *in, byte *out, int ilen, int olen)
2022 {
2023         int a = olen/ilen, b = olen%ilen;
2024         int c = 0, i;
2025         byte *end = out + olen;
2026         while(out<end) {
2027                 i = a;
2028                 c += b;
2029                 if(c >= ilen) {
2030                         c -= ilen;
2031                         goto inside;
2032                 }
2033                 while(--i>=0) {
2034                 inside:
2035                         *out++ = *in;
2036                 }
2037                 in++;
2038         }
2039 }
2040
2041 void gr_bitmap_scale_to(grs_bitmap *src, grs_bitmap *dst)
2042 {
2043         byte *s = src->bm_data;
2044         byte *d = dst->bm_data;
2045         int h = src->bm_h;
2046         int a = dst->bm_h/h, b = dst->bm_h%h;
2047         int c = 0, i, y;
2048
2049         for(y=0; y<h; y++) {
2050                 i = a;
2051                 c += b;
2052                 if(c >= h) {
2053                         c -= h;
2054                         goto inside;
2055                 }
2056                 while(--i>=0) {
2057                 inside:
2058                         scale_line(s, d, src->bm_w, dst->bm_w);
2059                         d += dst->bm_rowsize;
2060                 }
2061                 s += src->bm_rowsize;
2062         }
2063 }
2064
2065 void show_fullscr(grs_bitmap *bm)
2066 {
2067         grs_bitmap * const scr = &grd_curcanv->cv_bitmap;
2068
2069 #ifdef OGL
2070         if(bm->bm_type == BM_LINEAR && scr->bm_type == BM_OGL) {
2071                 ogl_ubitblt_i(scr->bm_w,scr->bm_h,0,0,bm->bm_w,bm->bm_h,0,0,bm,scr);//use opengl to scale, faster and saves ram. -MPM
2072                 return;
2073         }
2074 #endif
2075         if(scr->bm_type != BM_LINEAR) {
2076                 grs_bitmap *tmp = gr_create_bitmap(scr->bm_w, scr->bm_h);
2077                 gr_bitmap_scale_to(bm, tmp);
2078                 gr_bitmap(0, 0, tmp);
2079                 gr_free_bitmap(tmp);
2080                 return;
2081         }
2082         gr_bitmap_scale_to(bm, scr);
2083 }