]> icculus.org git repositories - btb/d2x.git/blob - 2d/bitblt.c
added gr_rle_expand_scanline_generic_masked from d2src
[btb/d2x.git] / 2d / bitblt.c
1 /* $Id: bitblt.c,v 1.7 2002-09-04 22:01:07 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, 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 static void modex_copy_column(ubyte * src, ubyte * dest, int num_pixels, int src_rowsize, int dest_rowsize );
473
474 #if !defined(NO_ASM) && defined(__WATCOMC__)
475
476 #pragma aux modex_copy_column parm [esi] [edi] [ecx] [ebx] [edx] modify exact [ecx esi edi] = \
477 "nextpixel:"            \
478     "mov    al,[esi]"   \
479     "add    esi, ebx"   \
480     "mov    [edi], al"  \
481     "add    edi, edx"   \
482     "dec    ecx"        \
483     "jne    nextpixel"
484
485 #elif !defined(NO_ASM) && defined(__GNUC__)
486
487 static inline void modex_copy_column(ubyte * src, ubyte * dest, int num_pixels, int src_rowsize, int dest_rowsize ) {
488 /*#pragma aux modex_copy_column parm [esi] [edi] [ecx] [ebx] [edx] modify exact [ecx esi edi] = */
489  __asm__ __volatile__ (
490 "0: ;"
491     "movb   (%%esi), %%al;"
492     "addl   %%ebx, %%esi;"
493     "movb   %%al, (%%edi);"
494     "addl   %%edx, %%edi;"
495     "decl   %%ecx;"
496     "jne    0b"
497  : : "S" (src), "D" (dest), "c" (num_pixels), "b" (src_rowsize), "d" (dest_rowsize)
498  : "%eax", "%ecx", "%esi", "%edi");
499 }
500
501 #else
502
503 static void modex_copy_column(ubyte * src, ubyte * dest, int num_pixels, int src_rowsize, int dest_rowsize )
504 {
505         src = src;
506         dest = dest;
507         num_pixels = num_pixels;
508         src_rowsize = src_rowsize;
509         dest_rowsize = dest_rowsize;
510         Int3();
511 }
512
513 #endif
514
515 static void modex_copy_column_m(ubyte * src, ubyte * dest, int num_pixels, int src_rowsize, int dest_rowsize );
516
517 #if !defined(NO_ASM) && defined(__WATCOMC__)
518
519 #pragma aux modex_copy_column_m parm [esi] [edi] [ecx] [ebx] [edx] modify exact [ecx esi edi] = \
520 "nextpixel:"            \
521     "mov    al,[esi]"   \
522     "add    esi, ebx"   \
523     "cmp    al, 255"    \
524     "je skip_itx"       \
525     "mov    [edi], al"  \
526 "skip_itx:"             \
527     "add    edi, edx"   \
528     "dec    ecx"        \
529     "jne    nextpixel"
530
531 #elif !defined(NO_ASM) && defined(__GNUC__)
532
533 static inline void modex_copy_column_m(ubyte * src, ubyte * dest, int num_pixels, int src_rowsize, int dest_rowsize ) {
534 /* #pragma aux modex_copy_column_m parm [esi] [edi] [ecx] [ebx] [edx] modify exact [ecx esi edi] = */
535  int dummy[3];
536  __asm__ __volatile__ (
537 "0: ;"
538     "movb    (%%esi), %%al;"
539     "addl    %%ebx, %%esi;"
540     "cmpb    $255, %%al;"
541     "je 1f;"
542     "movb   %%al, (%%edi);"
543 "1: ;"
544     "addl   %%edx, %%edi;"
545     "decl   %%ecx;"
546     "jne    0b"
547  : "=c" (dummy[0]), "=S" (dummy[1]), "=D" (dummy[2])
548  : "1" (src), "2" (dest), "0" (num_pixels), "b" (src_rowsize), "d" (dest_rowsize)
549  :      "%eax" );
550 }
551
552 #else
553
554 static void modex_copy_column_m(ubyte * src, ubyte * dest, int num_pixels, int src_rowsize, int dest_rowsize )
555 {
556         src = src;
557         dest = dest;
558         num_pixels = num_pixels;
559         src_rowsize = src_rowsize;
560         dest_rowsize = dest_rowsize;
561         Int3();
562 }
563
564 #endif
565
566 void gr_ubitmap00( int x, int y, grs_bitmap *bm )
567 {
568         register int y1;
569         int dest_rowsize;
570
571         unsigned char * dest;
572         unsigned char * src;
573
574         dest_rowsize=grd_curcanv->cv_bitmap.bm_rowsize << gr_bitblt_dest_step_shift;
575         dest = &(grd_curcanv->cv_bitmap.bm_data[ dest_rowsize*y+x ]);
576
577         src = bm->bm_data;
578
579         for (y1=0; y1 < bm->bm_h; y1++ )    {
580                 if (gr_bitblt_double)
581                         gr_linear_rep_movsd_2x( src, dest, bm->bm_w );
582                 else
583                         gr_linear_movsd( src, dest, bm->bm_w );
584                 src += bm->bm_rowsize;
585                 dest+= (int)(dest_rowsize);
586         }
587 }
588
589 void gr_ubitmap00m( int x, int y, grs_bitmap *bm )
590 {
591         register int y1;
592         int dest_rowsize;
593
594         unsigned char * dest;
595         unsigned char * src;
596
597         dest_rowsize=grd_curcanv->cv_bitmap.bm_rowsize << gr_bitblt_dest_step_shift;
598         dest = &(grd_curcanv->cv_bitmap.bm_data[ dest_rowsize*y+x ]);
599
600         src = bm->bm_data;
601
602         if (gr_bitblt_fade_table==NULL) {
603                 for (y1=0; y1 < bm->bm_h; y1++ )    {
604                         gr_linear_rep_movsdm( src, dest, bm->bm_w );
605                         src += bm->bm_rowsize;
606                         dest+= (int)(dest_rowsize);
607                 }
608         } else {
609                 for (y1=0; y1 < bm->bm_h; y1++ )    {
610                         gr_linear_rep_movsdm_faded( src, dest, bm->bm_w, gr_bitblt_fade_table[y1+y] );
611                         src += bm->bm_rowsize;
612                         dest+= (int)(dest_rowsize);
613                 }
614         }
615 }
616
617 #if 0
618 "       jmp     aligned4        "   \
619 "       mov eax, edi            "   \
620 "       and eax, 11b            "   \
621 "       jz      aligned4        "   \
622 "       mov ebx, 4              "   \
623 "       sub ebx, eax            "   \
624 "       sub ecx, ebx            "   \
625 "alignstart:                    "   \
626 "       mov al, [esi]           "   \
627 "       add esi, 4              "   \
628 "       mov [edi], al           "   \
629 "       inc edi                 "   \
630 "       dec ebx                 "   \
631 "       jne alignstart          "   \
632 "aligned4:                      "
633 #endif
634
635 static void modex_copy_scanline( ubyte * src, ubyte * dest, int npixels );
636
637 #if !defined(NO_ASM) && defined(__WATCOMC__)
638
639 #pragma aux modex_copy_scanline parm [esi] [edi] [ecx] modify exact [ecx esi edi eax ebx edx] = \
640 "       mov ebx, ecx            "   \
641 "       and ebx, 11b            "   \
642 "       shr ecx, 2              "   \
643 "       cmp ecx, 0              "   \
644 "       je      no2group        "   \
645 "next4pixels:                   "   \
646 "       mov al, [esi+8]         "   \
647 "       mov ah, [esi+12]        "   \
648 "       shl eax, 16             "   \
649 "       mov al, [esi]           "   \
650 "       mov ah, [esi+4]         "   \
651 "       mov [edi], eax          "   \
652 "       add esi, 16             "   \
653 "       add edi, 4              "   \
654 "       dec ecx                 "   \
655 "       jne next4pixels         "   \
656 "no2group:                      "   \
657 "       cmp ebx, 0              "   \
658 "       je      done2           "   \
659 "finishend:                     "   \
660 "       mov al, [esi]           "   \
661 "       add esi, 4              "   \
662 "       mov [edi], al           "   \
663 "       inc edi                 "   \
664 "       dec ebx                 "   \
665 "       jne finishend           "   \
666 "done2:                         ";
667
668 #elif !defined (NO_ASM) && defined(__GNUC__)
669
670 static inline void modex_copy_scanline( ubyte * src, ubyte * dest, int npixels ) {
671 /* #pragma aux modex_copy_scanline parm [esi] [edi] [ecx] modify exact [ecx esi edi eax ebx edx] */
672 int dummy[3];
673  __asm__ __volatile__ (
674 "       movl %%ecx, %%ebx;"
675 "       andl $3, %%ebx;"
676 "       shrl $2, %%ecx;"
677 "       cmpl $0, %%ecx;"
678 "       je   1f;"
679 "0: ;"
680 "       movb 8(%%esi), %%al;"
681 "       movb 12(%%esi), %%ah;"
682 "       shll $16, %%eax;"
683 "       movb (%%esi), %%al;"
684 "       movb 4(%%esi), %%ah;"
685 "       movl %%eax, (%%edi);"
686 "       addl $16, %%esi;"
687 "       addl $4, %%edi;"
688 "       decl %%ecx;"
689 "       jne 0b;"
690 "1: ;"
691 "       cmpl $0, %%ebx;"
692 "       je      3f;"
693 "2: ;"
694 "       movb (%%esi), %%al;"
695 "       addl $4, %%esi;"
696 "       movb %%al, (%%edi);"
697 "       incl %%edi;"
698 "       decl %%ebx;"
699 "       jne 2b;"
700 "3:"
701  : "=c" (dummy[0]), "=S" (dummy[1]), "=D" (dummy[2])
702  : "1" (src), "2" (dest), "0" (npixels)
703  :      "%eax", "%ebx", "%edx" );
704 }
705
706 #else
707
708 static void modex_copy_scanline( ubyte * src, ubyte * dest, int npixels )
709 {
710         src = src;
711         dest = dest;
712         npixels = npixels;
713         Int3();
714 }
715
716 #endif
717
718 static void modex_copy_scanline_2x( ubyte * src, ubyte * dest, int npixels );
719
720 #if !defined(NO_ASM) && defined(__WATCOMC__)
721
722 #pragma aux modex_copy_scanline_2x parm [esi] [edi] [ecx] modify exact [ecx esi edi eax ebx edx] = \
723 "       mov ebx, ecx            "   \
724 "       and ebx, 11b            "   \
725 "       shr ecx, 2              "   \
726 "       cmp ecx, 0              "   \
727 "       je      no2group        "   \
728 "next4pixels:                   "   \
729 "       mov al, [esi+4]         "   \
730 "       mov ah, [esi+6]         "   \
731 "       shl eax, 16             "   \
732 "       mov al, [esi]           "   \
733 "       mov ah, [esi+2]         "   \
734 "       mov [edi], eax          "   \
735 "       add esi, 8              "   \
736 "       add edi, 4              "   \
737 "       dec ecx                 "   \
738 "       jne next4pixels         "   \
739 "no2group:                      "   \
740 "       cmp ebx, 0              "   \
741 "       je      done2           "   \
742 "finishend:                     "   \
743 "       mov al, [esi]           "   \
744 "       add esi, 2              "   \
745 "       mov [edi], al           "   \
746 "       inc edi                 "   \
747 "       dec ebx                 "   \
748 "       jne finishend           "   \
749 "done2:                         ";
750
751 #elif !defined(NO_ASM) && defined(__GNUC__)
752
753 static inline void modex_copy_scanline_2x( ubyte * src, ubyte * dest, int npixels ) {
754 /* #pragma aux modex_copy_scanline_2x parm [esi] [edi] [ecx] modify exact [ecx esi edi eax ebx edx] = */
755 int dummy[3];
756  __asm__ __volatile__ (
757 "       movl %%ecx, %%ebx;"
758 "       andl $3, %%ebx;"
759 "       shrl $2, %%ecx;"
760 "       cmpl $0, %%ecx;"
761 "       je 1f;"
762 "0: ;"
763 "       movb 4(%%esi), %%al;"
764 "       movb 6(%%esi), %%ah;"
765 "       shll $16, %%eax;"
766 "       movb (%%esi), %%al;"
767 "       movb 2(%%esi), %%ah;"
768 "       movl %%eax, (%%edi);"
769 "       addl $8, %%esi;"
770 "       addl $4, %%edi;"
771 "       decl %%ecx;"
772 "       jne 0b;"
773 "1: ;"
774 "       cmp $0, %%ebx;"
775 "       je  3f;"
776 "2:"
777 "       movb (%%esi),%%al;"
778 "       addl $2, %%esi;"
779 "       movb %%al, (%%edi);"
780 "       incl %%edi;"
781 "       decl %%ebx;"
782 "       jne 2b;"
783 "3:"
784  : "=c" (dummy[0]), "=S" (dummy[1]), "=D" (dummy[2])
785  : "1" (src), "2" (dest), "0" (npixels)
786  :      "%eax", "%ebx", "%edx" );
787 }
788
789 #else
790
791 static void modex_copy_scanline_2x( ubyte * src, ubyte * dest, int npixels )
792 {
793         src = src;
794         dest = dest;
795         npixels = npixels;
796         Int3();
797 }
798
799 #endif
800
801
802 #ifdef __MSDOS__
803
804 // From Linear to ModeX
805 void gr_bm_ubitblt01(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
806 {
807         ubyte * dbits;
808         ubyte * sbits;
809         int sstep,dstep;
810         int y,plane;
811         int w1;
812
813         if ( w < 4 ) return;
814
815         sstep = src->bm_rowsize;
816         dstep = dest->bm_rowsize << gr_bitblt_dest_step_shift;
817
818         if (!gr_bitblt_double) {
819                 for (plane=0; plane<4; plane++ ) {
820                         gr_modex_setplane( (plane+dx)&3 );
821                         sbits = src->bm_data + (src->bm_rowsize * sy) + sx + plane;
822                         dbits = &gr_video_memory[(dest->bm_rowsize * dy) + ((plane+dx)/4) ];
823                         w1 = w >> 2;
824                         if ( (w&3) > plane ) w1++;
825                         for (y=dy; y < dy+h; y++ ) {
826                                 modex_copy_scanline( sbits, dbits, w1 );
827                                 dbits += dstep;
828                                 sbits += sstep;
829                         }
830                 }
831         } else {
832                 for (plane=0; plane<4; plane++ ) {
833                         gr_modex_setplane( (plane+dx)&3 );
834                         sbits = src->bm_data + (src->bm_rowsize * sy) + sx + plane/2;
835                         dbits = &gr_video_memory[(dest->bm_rowsize * dy) + ((plane+dx)/4) ];
836                         w1 = w >> 2;
837                         if ( (w&3) > plane ) w1++;
838                         for (y=dy; y < dy+h; y++ ) {
839                                 modex_copy_scanline_2x( sbits, dbits, w1 );
840                                 dbits += dstep;
841                                 sbits += sstep;
842                         }
843                 }
844         }
845 }
846
847
848 // From Linear to ModeX masked
849 void gr_bm_ubitblt01m(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
850 {
851         //ubyte * dbits1;
852         //ubyte * sbits1;
853
854         ubyte * dbits;
855         ubyte * sbits;
856
857         int x;
858         //int y;
859
860         sbits =   src->bm_data  + (src->bm_rowsize * sy) + sx;
861         dbits =   &gr_video_memory[(dest->bm_rowsize * dy) + dx/4];
862
863         for (x=dx; x < dx+w; x++ ) {
864                 gr_modex_setplane( x&3 );
865
866                 //sbits1 = sbits;
867                 //dbits1 = dbits;
868                 //for (y=0; y < h; y++ )    {
869                 //      *dbits1 = *sbits1;
870                 //      sbits1 += src_bm_rowsize;
871                 //      dbits1 += dest_bm_rowsize;
872                 //}
873                 modex_copy_column_m(sbits, dbits, h, src->bm_rowsize, dest->bm_rowsize << gr_bitblt_dest_step_shift );
874
875                 sbits++;
876                 if ( (x&3)==3 )
877                         dbits++;
878         }
879 }
880
881 #endif
882
883
884 void gr_ubitmap012( int x, int y, grs_bitmap *bm )
885 {
886         register int x1, y1;
887         unsigned char * src;
888
889         src = bm->bm_data;
890
891         for (y1=y; y1 < (y+bm->bm_h); y1++ )    {
892                 for (x1=x; x1 < (x+bm->bm_w); x1++ )    {
893                         gr_setcolor( *src++ );
894                         gr_upixel( x1, y1 );
895                 }
896         }
897 }
898
899 void gr_ubitmap012m( int x, int y, grs_bitmap *bm )
900 {
901         register int x1, y1;
902         unsigned char * src;
903
904         src = bm->bm_data;
905
906         for (y1=y; y1 < (y+bm->bm_h); y1++ ) {
907                 for (x1=x; x1 < (x+bm->bm_w); x1++ ) {
908                         if ( *src != TRANSPARENCY_COLOR ) {
909                                 gr_setcolor( *src );
910                                 gr_upixel( x1, y1 );
911                         }
912                         src++;
913                 }
914         }
915 }
916
917 #if defined(POLY_ACC)
918 void gr_ubitmap05( int x, int y, grs_bitmap *bm )
919 {
920         register int x1, y1;
921         unsigned char *src;
922         short *dst;
923         int mod;
924
925         pa_flush();
926         src = bm->bm_data;
927         dst = (short *)(DATA + y * ROWSIZE + x * PA_BPP);
928         mod = ROWSIZE / 2 - bm->bm_w;
929
930         for (y1=y; y1 < (y+bm->bm_h); y1++ )    {
931                 for (x1=x; x1 < (x+bm->bm_w); x1++ )    {
932                         *dst++ = pa_clut[*src++];
933                 }
934                 dst += mod;
935         }
936 }
937
938 void gr_ubitmap05m( int x, int y, grs_bitmap *bm )
939 {
940         register int x1, y1;
941         unsigned char *src;
942         short *dst;
943         int mod;
944
945         pa_flush();
946         src = bm->bm_data;
947         dst = (short *)(DATA + y * ROWSIZE + x * PA_BPP);
948         mod = ROWSIZE / 2 - bm->bm_w;
949
950         for (y1=y; y1 < (y+bm->bm_h); y1++ )    {
951                 for (x1=x; x1 < (x+bm->bm_w); x1++ )    {
952                         if ( *src != TRANSPARENCY_COLOR )   {
953                                 *dst = pa_clut[*src];
954                         }
955                         src++;
956                         ++dst;
957                 }
958                 dst += mod;
959         }
960 }
961
962 void gr_bm_ubitblt05_rle(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
963 {
964         unsigned short * dbits;
965         unsigned char * sbits, scanline[640];
966         int i, data_offset, j, nextrow;
967
968         pa_flush();
969         nextrow=dest->bm_rowsize/PA_BPP;
970
971         data_offset = 1;
972         if (src->bm_flags & BM_FLAG_RLE_BIG)
973                 data_offset = 2;
974
975         sbits = &src->bm_data[4 + (src->bm_h*data_offset)];
976         for (i=0; i<sy; i++ )
977                 sbits += (int)(INTEL_SHORT(src->bm_data[4+(i*data_offset)]));
978
979         dbits = (unsigned short *)(dest->bm_data + (dest->bm_rowsize * dy) + dx*PA_BPP);
980
981         // No interlacing, copy the whole buffer.
982         for (i=0; i < h; i++ )    {
983                 gr_rle_expand_scanline( scanline, sbits, sx, sx+w-1 );
984                 for(j = 0; j != w; ++j)
985                         dbits[j] = pa_clut[scanline[j]];
986                 if ( src->bm_flags & BM_FLAG_RLE_BIG )
987                         sbits += (int)INTEL_SHORT(*((short *)&(src->bm_data[4+((i+sy)*data_offset)])));
988                 else
989                         sbits += (int)(src->bm_data[4+i+sy]);
990                 dbits += nextrow;
991         }
992 }
993
994 void gr_bm_ubitblt05m_rle(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
995 {
996         unsigned short * dbits;
997         unsigned char * sbits, scanline[640];
998         int i, data_offset, j, nextrow;
999
1000         pa_flush();
1001         nextrow=dest->bm_rowsize/PA_BPP;
1002         data_offset = 1;
1003         if (src->bm_flags & BM_FLAG_RLE_BIG)
1004                 data_offset = 2;
1005
1006         sbits = &src->bm_data[4 + (src->bm_h*data_offset)];
1007         for (i=0; i<sy; i++ )
1008                 sbits += (int)(INTEL_SHORT(src->bm_data[4+(i*data_offset)]));
1009
1010         dbits = (unsigned short *)(dest->bm_data + (dest->bm_rowsize * dy) + dx*PA_BPP);
1011
1012         // No interlacing, copy the whole buffer.
1013         for (i=0; i < h; i++ )    {
1014                 gr_rle_expand_scanline( scanline, sbits, sx, sx+w-1 );
1015                 for(j = 0; j != w; ++j)
1016                         if(scanline[j] != TRANSPARENCY_COLOR)
1017                                 dbits[j] = pa_clut[scanline[j]];
1018                 if ( src->bm_flags & BM_FLAG_RLE_BIG )
1019                         sbits += (int)INTEL_SHORT(*((short *)&(src->bm_data[4+((i+sy)*data_offset)])));
1020                 else
1021                         sbits += (int)(src->bm_data[4+i+sy]);
1022                 dbits += nextrow;
1023         }
1024 }
1025 #endif
1026
1027 void gr_ubitmapGENERIC(int x, int y, grs_bitmap * bm)
1028 {
1029         register int x1, y1;
1030
1031         for (y1=0; y1 < bm->bm_h; y1++ )    {
1032                 for (x1=0; x1 < bm->bm_w; x1++ )    {
1033                         gr_setcolor( gr_gpixel(bm,x1,y1) );
1034                         gr_upixel( x+x1, y+y1 );
1035                 }
1036         }
1037 }
1038
1039 void gr_ubitmapGENERICm(int x, int y, grs_bitmap * bm)
1040 {
1041         register int x1, y1;
1042         ubyte c;
1043
1044         for (y1=0; y1 < bm->bm_h; y1++ ) {
1045                 for (x1=0; x1 < bm->bm_w; x1++ ) {
1046                         c = gr_gpixel(bm,x1,y1);
1047                         if ( c != TRANSPARENCY_COLOR ) {
1048                                 gr_setcolor( c );
1049                                 gr_upixel( x+x1, y+y1 );
1050                         }
1051                 }
1052         }
1053 }
1054
1055
1056 #ifdef __MSDOS__
1057 // From linear to SVGA
1058 void gr_bm_ubitblt02(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
1059 {
1060         unsigned char * sbits;
1061
1062         unsigned int offset, EndingOffset, VideoLocation;
1063
1064         int sbpr, dbpr, y1, page, BytesToMove;
1065
1066         sbpr = src->bm_rowsize;
1067
1068         dbpr = dest->bm_rowsize << gr_bitblt_dest_step_shift;
1069
1070         VideoLocation = (unsigned int)dest->bm_data + (dest->bm_rowsize * dy) + dx;
1071
1072         sbits = src->bm_data + ( sbpr*sy ) + sx;
1073
1074         for (y1=0; y1 < h; y1++ )    {
1075
1076                 page    = VideoLocation >> 16;
1077                 offset  = VideoLocation & 0xFFFF;
1078
1079                 gr_vesa_setpage( page );
1080
1081                 EndingOffset = offset+w-1;
1082
1083                 if ( EndingOffset <= 0xFFFF )
1084                 {
1085                         if ( gr_bitblt_double )
1086                                 gr_linear_rep_movsd_2x( (void *)sbits, (void *)(offset+0xA0000), w );
1087                         else
1088                                 gr_linear_movsd( (void *)sbits, (void *)(offset+0xA0000), w );
1089
1090                         VideoLocation += dbpr;
1091                         sbits += sbpr;
1092                 }
1093                 else
1094                 {
1095                         BytesToMove = 0xFFFF-offset+1;
1096
1097                         if ( gr_bitblt_double )
1098                                 gr_linear_rep_movsd_2x( (void *)sbits, (void *)(offset+0xA0000), BytesToMove );
1099                         else
1100                                 gr_linear_movsd( (void *)sbits, (void *)(offset+0xA0000), BytesToMove );
1101
1102                         page++;
1103                         gr_vesa_setpage(page);
1104
1105                         if ( gr_bitblt_double )
1106                                 gr_linear_rep_movsd_2x( (void *)(sbits+BytesToMove/2), (void *)0xA0000, EndingOffset - 0xFFFF );
1107                         else
1108                                 gr_linear_movsd( (void *)(sbits+BytesToMove), (void *)0xA0000, EndingOffset - 0xFFFF );
1109
1110                         VideoLocation += dbpr;
1111                         sbits += sbpr;
1112                 }
1113         }
1114 }
1115 #endif
1116
1117 #ifdef __MSDOS__
1118
1119 void gr_bm_ubitblt02m(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
1120 {
1121         unsigned char * sbits;
1122
1123         unsigned int offset, EndingOffset, VideoLocation;
1124
1125         int sbpr, dbpr, y1, page, BytesToMove;
1126
1127         sbpr = src->bm_rowsize;
1128
1129         dbpr = dest->bm_rowsize << gr_bitblt_dest_step_shift;
1130
1131         VideoLocation = (unsigned int)dest->bm_data + (dest->bm_rowsize * dy) + dx;
1132
1133         sbits = src->bm_data + ( sbpr*sy ) + sx;
1134
1135         for (y1=0; y1 < h; y1++ )    {
1136
1137                 page    = VideoLocation >> 16;
1138                 offset  = VideoLocation & 0xFFFF;
1139
1140                 gr_vesa_setpage( page );
1141
1142                 EndingOffset = offset+w-1;
1143
1144                 if ( EndingOffset <= 0xFFFF )
1145                 {
1146                         gr_linear_rep_movsdm( (void *)sbits, (void *)(offset+0xA0000), w );
1147
1148                         VideoLocation += dbpr;
1149                         sbits += sbpr;
1150                 }
1151                 else
1152                 {
1153                         BytesToMove = 0xFFFF-offset+1;
1154
1155                         gr_linear_rep_movsdm( (void *)sbits, (void *)(offset+0xA0000), BytesToMove );
1156
1157                         page++;
1158                         gr_vesa_setpage(page);
1159
1160                         gr_linear_rep_movsdm( (void *)(sbits+BytesToMove), (void *)0xA0000, EndingOffset - 0xFFFF );
1161
1162                         VideoLocation += dbpr;
1163                         sbits += sbpr;
1164                 }
1165         }
1166 }
1167
1168
1169 // From SVGA to linear
1170 void gr_bm_ubitblt20(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
1171 {
1172         unsigned char * dbits;
1173
1174         unsigned int offset, offset1, offset2;
1175
1176         int sbpr, dbpr, y1, page;
1177
1178         dbpr = dest->bm_rowsize;
1179
1180         sbpr = src->bm_rowsize;
1181
1182         for (y1=0; y1 < h; y1++ )    {
1183
1184                 offset2 =   (unsigned int)src->bm_data  + (sbpr * (y1+sy)) + sx;
1185                 dbits   =   dest->bm_data + (dbpr * (y1+dy)) + dx;
1186
1187                 page = offset2 >> 16;
1188                 offset = offset2 & 0xFFFF;
1189                 offset1 = offset+w-1;
1190                 gr_vesa_setpage( page );
1191
1192                 if ( offset1 > 0xFFFF )  {
1193                         // Overlaps two pages
1194                         while( offset <= 0xFFFF )
1195                                 *dbits++ = gr_video_memory[offset++];
1196                         offset1 -= (0xFFFF+1);
1197                         offset = 0;
1198                         page++;
1199                         gr_vesa_setpage(page);
1200                 }
1201                 while( offset <= offset1 )
1202                         *dbits++ = gr_video_memory[offset++];
1203
1204         }
1205 }
1206
1207 #endif
1208
1209 //@extern int Interlacing_on;
1210
1211 // From Linear to Linear
1212 void gr_bm_ubitblt00(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
1213 {
1214         unsigned char * dbits;
1215         unsigned char * sbits;
1216         //int src_bm_rowsize_2, dest_bm_rowsize_2;
1217         int dstep;
1218
1219         int i;
1220
1221         sbits =   src->bm_data  + (src->bm_rowsize * sy) + sx;
1222         dbits =   dest->bm_data + (dest->bm_rowsize * dy) + dx;
1223
1224         dstep = dest->bm_rowsize << gr_bitblt_dest_step_shift;
1225
1226         // No interlacing, copy the whole buffer.
1227         for (i=0; i < h; i++ )    {
1228                 if (gr_bitblt_double)
1229                         gr_linear_rep_movsd_2x( sbits, dbits, w );
1230                 else
1231                         gr_linear_movsd( sbits, dbits, w );
1232                 sbits += src->bm_rowsize;
1233                 dbits += dstep;
1234         }
1235 }
1236 // From Linear to Linear Masked
1237 void gr_bm_ubitblt00m(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
1238 {
1239         unsigned char * dbits;
1240         unsigned char * sbits;
1241         //int src_bm_rowsize_2, dest_bm_rowsize_2;
1242
1243         int i;
1244
1245         sbits =   src->bm_data  + (src->bm_rowsize * sy) + sx;
1246         dbits =   dest->bm_data + (dest->bm_rowsize * dy) + dx;
1247
1248         // No interlacing, copy the whole buffer.
1249
1250         if (gr_bitblt_fade_table==NULL) {
1251                 for (i=0; i < h; i++ )    {
1252                         gr_linear_rep_movsdm( sbits, dbits, w );
1253                         sbits += src->bm_rowsize;
1254                         dbits += dest->bm_rowsize;
1255                 }
1256         } else {
1257                 for (i=0; i < h; i++ )    {
1258                         gr_linear_rep_movsdm_faded( sbits, dbits, w, gr_bitblt_fade_table[dy+i] );
1259                         sbits += src->bm_rowsize;
1260                         dbits += dest->bm_rowsize;
1261                 }
1262         }
1263 }
1264
1265
1266 extern void gr_lbitblt( grs_bitmap * source, grs_bitmap * dest, int height, int width );
1267
1268 #if 1 //def MACINTOSH
1269
1270 // width == number of destination pixels
1271
1272 void gr_linear_movsd_double(ubyte *src, ubyte *dest, int width)
1273 {
1274         double  *d = (double *)dest;
1275         uint    *s = (uint *)src;
1276         uint    doubletemp[2];
1277         uint    temp, work;
1278         int     i, num_pixels;
1279
1280         num_pixels = width / 2;
1281         if ( (num_pixels & 0x3) || (((int)src & 0x7) != ((int)dest & 0x7)) ) {
1282                 // not a multiple of 4?  do single pixel at a time
1283                 for (i=0; i<num_pixels; i++) {
1284                         *dest++ = *src;
1285                         *dest++ = *src++;
1286                 }
1287                 return;
1288         }
1289
1290         for (i = 0; i < num_pixels / 4; i++) {
1291                 temp = work = *s++;
1292
1293                 temp = ((temp >> 8) & 0x00FFFF00) | (temp & 0xFF0000FF); // 0xABCDEFGH -> 0xABABCDEF
1294                 temp = ((temp >> 8) & 0x000000FF) | (temp & 0xFFFFFF00); // 0xABABCDEF -> 0xABABCDCD
1295                 doubletemp[0] = temp;
1296
1297                 work = ((work << 8) & 0x00FFFF00) | (work & 0xFF0000FF); // 0xABCDEFGH -> 0xABEFGHGH
1298                 work = ((work << 8) & 0xFF000000) | (work & 0x00FFFFFF); // 0xABEFGHGH -> 0xEFEFGHGH
1299                 doubletemp[1] = work;
1300
1301                 *d = *(double *) &(doubletemp[0]);
1302                 d++;
1303         }
1304 }
1305
1306 //extern void BlitLargeAlign(ubyte *draw_buffer, int dstRowBytes, ubyte *dstPtr, int w, int h, int modulus);
1307
1308 #ifdef MACINTOSH
1309 asm void BlitLargeAlign(ubyte *rSrcPtr, int rDblDStrd, ubyte *rDst1Ptr, int rWidth, int rHeight, int rModulus)
1310 {
1311     stw     r31,-4(SP)          // store non-volatile reg in red zone
1312     addi    r5,r5,-8            // subtract 8 from dst
1313     stw     r30,-8(SP)          // store non-volatile reg in red zone
1314
1315     la      r30,-16(SP)         // calculate copy of local 8-byte variable
1316     sub     r9,r8,r6
1317                                 // rSStrd = modulus - w
1318     add     r31,r5,r4           // dst2 = dstRowBytes + dst1
1319     sub     r4,r4,r6            // r4 = dstRowBytes - w
1320     addi    r7,r7,-1            // subtract 1 from height count
1321     srawi   r6,r6,2             // rWidth = w >> 2
1322     addi    r3,r3,-4            // subtract 4 from src
1323     addi    r6,r6,-1            // subtract 1 from width count
1324     add     r4,r4,r4            // rDblDStrd = 2 * r4
1325
1326 BlitLargeAlignY:                // y count is in r7
1327     lwzu     r10,4(r3)          // load a long into r10
1328     mr       r0,r10             // put a copy in r0
1329     mr       r11,r10
1330 // these are simplified -- can't use 'em    inslwi   r0,r10,16,8
1331 // these are simplified -- can't use 'em    insrwi   r11,r10,16,8
1332     rlwimi   r0,r10,24,8,31
1333     rlwimi   r11,r10,8,8,23
1334     rlwimi   r0,r10,16,24,31
1335     stw      r0,0(r30)
1336     rlwimi   r11,r10,16,0,7
1337     stw      r11,4(r30)
1338     mtctr       r6              // copy x count into the counter
1339     lfd      fp0,0(r30)
1340
1341 BlitLargeAlignX:
1342     lwzu     r10,4(r3)          // load a long into r10
1343     stfdu    fp0,8(r5)
1344     mr       r0,r10             // put a copy in r0
1345     mr       r11,r10
1346 // simplefied   inslwi   r0,r10,16,8
1347 // simplefied   insrwi   r11,r10,16,8
1348     rlwimi   r0,r10,24,8,31
1349     rlwimi   r11,r10,8,8,23
1350     rlwimi   r0,r10,16,24,31
1351     stw      r0,0(r30)
1352     rlwimi   r11,r10,16,0,7
1353     stw      r11,4(r30)
1354     stfdu    fp0,8(r31)
1355     lfd      fp0,0(r30)
1356     bdnz     BlitLargeAlignX    // loop over all x
1357
1358     stfdu    fp0,8(r5)
1359     addic.   r7,r7,-1           // decrement the counter
1360     add      r3,r3,r9
1361                                 // src += sstride
1362     add      r5,r5,r4
1363                                 // dst1 += dstride
1364     stfdu    fp0,8(r31)
1365     add      r31,r31,r4
1366                                 // dst2 += dstride
1367     bne      BlitLargeAlignY    // loop for all y
1368
1369     lwz     r30,-8(SP)          // restore non-volatile regs
1370     lwz     r31,-4(SP)          // restore non-volatile regs
1371     blr                         // return to caller
1372 }
1373
1374 void gr_bm_ubitblt_double(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap *src, grs_bitmap *dest)
1375 {
1376         ubyte * dbits;
1377         ubyte * sbits;
1378         int dstep, i;
1379
1380         sbits = src->bm_data  + (src->bm_rowsize * sy) + sx;
1381         dbits = dest->bm_data + (dest->bm_rowsize * dy) + dx;
1382         dstep = dest->bm_rowsize << gr_bitblt_dest_step_shift;
1383         Assert( !((int)dbits & 0x7) );  // assert to check double word alignment
1384         BlitLargeAlign(sbits, dstep, dbits, src->bm_w, src->bm_h, src->bm_rowsize);
1385 }
1386 #endif
1387
1388 // w and h are the doubled width and height
1389
1390 void gr_bm_ubitblt_double_slow(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap *src, grs_bitmap *dest)
1391 {
1392         ubyte * dbits;
1393         ubyte * sbits;
1394         int dstep, i;
1395
1396         sbits = src->bm_data  + (src->bm_rowsize * sy) + sx;
1397         dbits = dest->bm_data + (dest->bm_rowsize * dy) + dx;
1398         dstep = dest->bm_rowsize << gr_bitblt_dest_step_shift;
1399
1400         for (i=0; i < h; i++ )    {
1401
1402                 gr_linear_movsd_double(sbits, dbits, w);
1403                 dbits += dstep;
1404                 if (i & 1)
1405                         sbits += src->bm_rowsize;
1406         }
1407 }
1408
1409 #endif
1410
1411
1412 // Clipped bitmap ...
1413
1414 void gr_bitmap( int x, int y, grs_bitmap *bm )
1415 {
1416         int dx1=x, dx2=x+bm->bm_w-1;
1417         int dy1=y, dy2=y+bm->bm_h-1;
1418         int sx=0, sy=0;
1419
1420         if ((dx1 >= grd_curcanv->cv_bitmap.bm_w ) || (dx2 < 0)) return;
1421         if ((dy1 >= grd_curcanv->cv_bitmap.bm_h) || (dy2 < 0)) return;
1422         if ( dx1 < 0 ) { sx = -dx1; dx1 = 0; }
1423         if ( dy1 < 0 ) { sy = -dy1; dy1 = 0; }
1424         if ( dx2 >= grd_curcanv->cv_bitmap.bm_w ) { dx2 = grd_curcanv->cv_bitmap.bm_w-1; }
1425         if ( dy2 >= grd_curcanv->cv_bitmap.bm_h ) { dy2 = grd_curcanv->cv_bitmap.bm_h-1; }
1426
1427         // Draw bitmap bm[x,y] into (dx1,dy1)-(dx2,dy2)
1428
1429         gr_bm_ubitblt(dx2-dx1+1,dy2-dy1+1, dx1, dy1, sx, sy, bm, &grd_curcanv->cv_bitmap );
1430
1431 }
1432
1433 //-NOT-used // From linear to SVGA
1434 //-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)
1435 //-NOT-used {
1436 //-NOT-used     unsigned char * sbits;
1437 //-NOT-used
1438 //-NOT-used     unsigned int offset, EndingOffset, VideoLocation;
1439 //-NOT-used
1440 //-NOT-used     int sbpr, dbpr, y1, page, BytesToMove;
1441 //-NOT-used
1442 //-NOT-used     sbpr = src->bm_rowsize;
1443 //-NOT-used
1444 //-NOT-used     dbpr = dest->bm_rowsize << gr_bitblt_dest_step_shift;
1445 //-NOT-used
1446 //-NOT-used     VideoLocation = (unsigned int)dest->bm_data + (dest->bm_rowsize * dy) + dx;
1447 //-NOT-used
1448 //-NOT-used     sbits = src->bm_data + ( sbpr*sy ) + sx;
1449 //-NOT-used
1450 //-NOT-used     for (y1=0; y1 < h; y1++ )    {
1451 //-NOT-used
1452 //-NOT-used             page    = VideoLocation >> 16;
1453 //-NOT-used             offset  = VideoLocation & 0xFFFF;
1454 //-NOT-used
1455 //-NOT-used             gr_vesa_setpage( page );
1456 //-NOT-used
1457 //-NOT-used             EndingOffset = offset+w-1;
1458 //-NOT-used
1459 //-NOT-used             if ( EndingOffset <= 0xFFFF )
1460 //-NOT-used             {
1461 //-NOT-used                     gr_linear_rep_movsd_2x( (void *)sbits, (void *)(offset+0xA0000), w );
1462 //-NOT-used
1463 //-NOT-used                     VideoLocation += dbpr;
1464 //-NOT-used                     sbits += sbpr;
1465 //-NOT-used             }
1466 //-NOT-used             else
1467 //-NOT-used             {
1468 //-NOT-used                     BytesToMove = 0xFFFF-offset+1;
1469 //-NOT-used
1470 //-NOT-used                     gr_linear_rep_movsd_2x( (void *)sbits, (void *)(offset+0xA0000), BytesToMove );
1471 //-NOT-used
1472 //-NOT-used                     page++;
1473 //-NOT-used                     gr_vesa_setpage(page);
1474 //-NOT-used
1475 //-NOT-used                     gr_linear_rep_movsd_2x( (void *)(sbits+BytesToMove/2), (void *)0xA0000, EndingOffset - 0xFFFF );
1476 //-NOT-used
1477 //-NOT-used                     VideoLocation += dbpr;
1478 //-NOT-used                     sbits += sbpr;
1479 //-NOT-used             }
1480 //-NOT-used
1481 //-NOT-used
1482 //-NOT-used     }
1483 //-NOT-used }
1484
1485
1486 //-NOT-used // From Linear to Linear
1487 //-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)
1488 //-NOT-used {
1489 //-NOT-used     unsigned char * dbits;
1490 //-NOT-used     unsigned char * sbits;
1491 //-NOT-used     //int src_bm_rowsize_2, dest_bm_rowsize_2;
1492 //-NOT-used
1493 //-NOT-used     int i;
1494 //-NOT-used
1495 //-NOT-used     sbits =   src->bm_data  + (src->bm_rowsize * sy) + sx;
1496 //-NOT-used     dbits =   dest->bm_data + (dest->bm_rowsize * dy) + dx;
1497 //-NOT-used
1498 //-NOT-used     // No interlacing, copy the whole buffer.
1499 //-NOT-used     for (i=0; i < h; i++ )    {
1500 //-NOT-used             gr_linear_rep_movsd_2x( sbits, dbits, w );
1501 //-NOT-used
1502 //-NOT-used             sbits += src->bm_rowsize;
1503 //-NOT-used             dbits += dest->bm_rowsize << gr_bitblt_dest_step_shift;
1504 //-NOT-used     }
1505 //-NOT-used }
1506
1507 void gr_bm_ubitblt00_rle(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
1508 {
1509         unsigned char * dbits;
1510         unsigned char * sbits;
1511         int i, data_offset;
1512
1513         data_offset = 1;
1514         if (src->bm_flags & BM_FLAG_RLE_BIG)
1515                 data_offset = 2;
1516
1517         sbits = &src->bm_data[4 + (src->bm_h*data_offset)];
1518
1519         for (i=0; i<sy; i++ )
1520                 sbits += (int)(INTEL_SHORT(src->bm_data[4+(i*data_offset)]));
1521
1522         dbits = dest->bm_data + (dest->bm_rowsize * dy) + dx;
1523
1524         // No interlacing, copy the whole buffer.
1525         for (i=0; i < h; i++ )    {
1526                 gr_rle_expand_scanline( dbits, sbits, sx, sx+w-1 );
1527                 if ( src->bm_flags & BM_FLAG_RLE_BIG )
1528                         sbits += (int)INTEL_SHORT(*((short *)&(src->bm_data[4+((i+sy)*data_offset)])));
1529                 else
1530                         sbits += (int)(src->bm_data[4+i+sy]);
1531                 dbits += dest->bm_rowsize << gr_bitblt_dest_step_shift;
1532         }
1533 }
1534
1535 void gr_bm_ubitblt00m_rle(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
1536 {
1537         unsigned char * dbits;
1538         unsigned char * sbits;
1539         int i, data_offset;
1540
1541         data_offset = 1;
1542         if (src->bm_flags & BM_FLAG_RLE_BIG)
1543                 data_offset = 2;
1544
1545         sbits = &src->bm_data[4 + (src->bm_h*data_offset)];
1546         for (i=0; i<sy; i++ )
1547                 sbits += (int)(INTEL_SHORT(src->bm_data[4+(i*data_offset)]));
1548
1549         dbits = dest->bm_data + (dest->bm_rowsize * dy) + dx;
1550
1551         // No interlacing, copy the whole buffer.
1552         for (i=0; i < h; i++ )    {
1553                 gr_rle_expand_scanline_masked( dbits, sbits, sx, sx+w-1 );
1554                 if ( src->bm_flags & BM_FLAG_RLE_BIG )
1555                         sbits += (int)INTEL_SHORT(*((short *)&(src->bm_data[4+((i+sy)*data_offset)])));
1556                 else
1557                         sbits += (int)(src->bm_data[4+i+sy]);
1558                 dbits += dest->bm_rowsize << gr_bitblt_dest_step_shift;
1559         }
1560 }
1561
1562 // in rle.c
1563
1564 extern void gr_rle_expand_scanline_generic( grs_bitmap * dest, int dx, int dy, ubyte *src, int x1, int x2  );
1565 extern void gr_rle_expand_scanline_generic_masked( grs_bitmap * dest, int dx, int dy, ubyte *src, int x1, int x2  );
1566 extern void gr_rle_expand_scanline_svga_masked( grs_bitmap * dest, int dx, int dy, ubyte *src, int x1, int x2  );
1567
1568 void gr_bm_ubitblt0x_rle(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
1569 {
1570         int i, data_offset;
1571         register int y1;
1572         unsigned char * sbits;
1573
1574         //mprintf( 0, "SVGA RLE!\n" );
1575
1576         data_offset = 1;
1577         if (src->bm_flags & BM_FLAG_RLE_BIG)
1578                 data_offset = 2;
1579
1580         sbits = &src->bm_data[4 + (src->bm_h*data_offset)];
1581         for (i=0; i<sy; i++ )
1582                 sbits += (int)(INTEL_SHORT(src->bm_data[4+(i*data_offset)]));
1583
1584         for (y1=0; y1 < h; y1++ )    {
1585                 gr_rle_expand_scanline_generic( dest, dx, dy+y1,  sbits, sx, sx+w-1  );
1586                 if ( src->bm_flags & BM_FLAG_RLE_BIG )
1587                         sbits += (int)INTEL_SHORT(*((short *)&(src->bm_data[4+((y1+sy)*data_offset)])));
1588                 else
1589                         sbits += (int)src->bm_data[4+y1+sy];
1590         }
1591
1592 }
1593
1594 void gr_bm_ubitblt0xm_rle(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
1595 {
1596         int i, data_offset;
1597         register int y1;
1598         unsigned char * sbits;
1599
1600         //mprintf( 0, "SVGA RLE!\n" );
1601
1602         data_offset = 1;
1603         if (src->bm_flags & BM_FLAG_RLE_BIG)
1604                 data_offset = 2;
1605
1606         sbits = &src->bm_data[4 + (src->bm_h*data_offset)];
1607         for (i=0; i<sy; i++ )
1608                 sbits += (int)(INTEL_SHORT(src->bm_data[4+(i*data_offset)]));
1609
1610         for (y1=0; y1 < h; y1++ )    {
1611                 gr_rle_expand_scanline_generic_masked( dest, dx, dy+y1,  sbits, sx, sx+w-1  );
1612                 if ( src->bm_flags & BM_FLAG_RLE_BIG )
1613                         sbits += (int)INTEL_SHORT(*((short *)&(src->bm_data[4+((y1+sy)*data_offset)])));
1614                 else
1615                         sbits += (int)src->bm_data[4+y1+sy];
1616         }
1617
1618 }
1619
1620 #ifdef __MSDOS__
1621 void gr_bm_ubitblt02m_rle(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
1622 {
1623         int i, data_offset;
1624         register int y1;
1625         unsigned char * sbits;
1626
1627         //mprintf( 0, "SVGA RLE!\n" );
1628
1629         data_offset = 1;
1630         if (src->bm_flags & BM_FLAG_RLE_BIG)
1631                 data_offset = 2;
1632
1633         sbits = &src->bm_data[4 + (src->bm_h*data_offset)];
1634         for (i=0; i<sy; i++ )
1635                 sbits += (int)(INTEL_SHORT(src->bm_data[4+(i*data_offset)]));
1636
1637         for (y1=0; y1 < h; y1++ )    {
1638                 gr_rle_expand_scanline_svga_masked( dest, dx, dy+y1,  sbits, sx, sx+w-1  );
1639                 if ( src->bm_flags & BM_FLAG_RLE_BIG )
1640                         sbits += (int)INTEL_SHORT(*((short *)&(src->bm_data[4+((y1+sy)*data_offset)])));
1641                 else
1642                         sbits += (int)src->bm_data[4+y1+sy];
1643         }
1644 }
1645 #endif
1646
1647 void gr_bm_ubitblt(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
1648 {
1649         register int x1, y1;
1650
1651         if ( (src->bm_type == BM_LINEAR) && (dest->bm_type == BM_LINEAR ))
1652         {
1653                 if ( src->bm_flags & BM_FLAG_RLE )
1654                         gr_bm_ubitblt00_rle( w, h, dx, dy, sx, sy, src, dest );
1655                 else
1656                         gr_bm_ubitblt00( w, h, dx, dy, sx, sy, src, dest );
1657                 return;
1658         }
1659
1660 #ifdef OGL
1661         if ( (src->bm_type == BM_LINEAR) && (dest->bm_type == BM_OGL ))
1662         {
1663                 ogl_ubitblt(w, h, dx, dy, sx, sy, src, dest);
1664                 return;
1665         }
1666         if ( (src->bm_type == BM_OGL) && (dest->bm_type == BM_LINEAR ))
1667         {
1668                 ogl_ubitblt_tolinear(w, h, dx, dy, sx, sy, src, dest);
1669                 return;
1670         }
1671         if ( (src->bm_type == BM_OGL) && (dest->bm_type == BM_OGL ))
1672         {
1673                 ogl_ubitblt_copy(w, h, dx, dy, sx, sy, src, dest);
1674                 return;
1675         }
1676 #endif
1677
1678 #ifdef D1XD3D
1679         if ( (src->bm_type == BM_LINEAR) && (dest->bm_type == BM_DIRECTX ))
1680         {
1681                 Assert ((int)dest->bm_data == BM_D3D_RENDER || (int)dest->bm_data == BM_D3D_DISPLAY);
1682                 Win32_BlitLinearToDirectX_bm (src, sx, sy, w, h, dx, dy, 0);
1683                 return;
1684         }
1685         if ( (src->bm_type == BM_DIRECTX) && (dest->bm_type == BM_LINEAR ))
1686         {
1687                 return;
1688         }
1689         if ( (src->bm_type == BM_DIRECTX) && (dest->bm_type == BM_DIRECTX ))
1690         {
1691                 return;
1692         }
1693 #endif
1694
1695         if ( (src->bm_flags & BM_FLAG_RLE ) && (src->bm_type == BM_LINEAR) ) {
1696                 gr_bm_ubitblt0x_rle(w, h, dx, dy, sx, sy, src, dest );
1697                 return;
1698         }
1699
1700 #ifdef __MSDOS__
1701         if ( (src->bm_type == BM_LINEAR) && (dest->bm_type == BM_SVGA ))
1702         {
1703                 gr_bm_ubitblt02( w, h, dx, dy, sx, sy, src, dest );
1704                 return;
1705         }
1706
1707         if ( (src->bm_type == BM_SVGA) && (dest->bm_type == BM_LINEAR ))
1708         {
1709                 gr_bm_ubitblt20( w, h, dx, dy, sx, sy, src, dest );
1710                 return;
1711         }
1712
1713         if ( (src->bm_type == BM_LINEAR) && (dest->bm_type == BM_MODEX ))
1714         {
1715                 gr_bm_ubitblt01( w, h, dx+XOFFSET, dy+YOFFSET, sx, sy, src, dest );
1716                 return;
1717         }
1718 #endif
1719
1720 #if defined(POLY_ACC)
1721         if ( (src->bm_type == BM_LINEAR) && (dest->bm_type == BM_LINEAR15 ))
1722         {
1723                 ubyte *s = src->bm_data + sy * src->bm_rowsize + sx;
1724                 ushort *t = (ushort *)(dest->bm_data + dy * dest->bm_rowsize + dx * PA_BPP);
1725                 int x;
1726                 pa_flush();
1727                 for(;h--;)
1728                 {
1729                         for(x = 0; x < w; x++)
1730                                 t[x] = pa_clut[s[x]];
1731                         s += src->bm_rowsize;
1732                         t += dest->bm_rowsize / PA_BPP;
1733                 }
1734                 return;
1735         }
1736
1737         if ( (src->bm_type == BM_LINEAR15) && (dest->bm_type == BM_LINEAR15 ))
1738         {
1739                 pa_blit(dest, dx, dy, src, sx, sy, w, h);
1740                 return;
1741         }
1742 #endif
1743
1744         for (y1=0; y1 < h; y1++ )    {
1745                 for (x1=0; x1 < w; x1++ )    {
1746                         gr_bm_pixel( dest, dx+x1, dy+y1, gr_gpixel(src,sx+x1,sy+y1) );
1747                 }
1748         }
1749 }
1750
1751 void gr_bm_bitblt(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
1752 {
1753         int dx1=dx, dx2=dx+dest->bm_w-1;
1754         int dy1=dy, dy2=dy+dest->bm_h-1;
1755
1756         int sx1=sx, sx2=sx+src->bm_w-1;
1757         int sy1=sy, sy2=sy+src->bm_h-1;
1758
1759         if ((dx1 >= dest->bm_w ) || (dx2 < 0)) return;
1760         if ((dy1 >= dest->bm_h ) || (dy2 < 0)) return;
1761         if ( dx1 < 0 ) { sx1 += -dx1; dx1 = 0; }
1762         if ( dy1 < 0 ) { sy1 += -dy1; dy1 = 0; }
1763         if ( dx2 >= dest->bm_w ) { dx2 = dest->bm_w-1; }
1764         if ( dy2 >= dest->bm_h ) { dy2 = dest->bm_h-1; }
1765
1766         if ((sx1 >= src->bm_w ) || (sx2 < 0)) return;
1767         if ((sy1 >= src->bm_h ) || (sy2 < 0)) return;
1768         if ( sx1 < 0 ) { dx1 += -sx1; sx1 = 0; }
1769         if ( sy1 < 0 ) { dy1 += -sy1; sy1 = 0; }
1770         if ( sx2 >= src->bm_w ) { sx2 = src->bm_w-1; }
1771         if ( sy2 >= src->bm_h ) { sy2 = src->bm_h-1; }
1772
1773         // Draw bitmap bm[x,y] into (dx1,dy1)-(dx2,dy2)
1774         if ( dx2-dx1+1 < w )
1775                 w = dx2-dx1+1;
1776         if ( dy2-dy1+1 < h )
1777                 h = dy2-dy1+1;
1778         if ( sx2-sx1+1 < w )
1779                 w = sx2-sx1+1;
1780         if ( sy2-sy1+1 < h )
1781                 h = sy2-sy1+1;
1782
1783         gr_bm_ubitblt(w,h, dx1, dy1, sx1, sy1, src, dest );
1784 }
1785
1786 void gr_ubitmap( int x, int y, grs_bitmap *bm )
1787 {
1788         int source, dest;
1789
1790         source = bm->bm_type;
1791         dest = TYPE;
1792
1793         if (source==BM_LINEAR) {
1794                 switch( dest )
1795                 {
1796                 case BM_LINEAR:
1797                         if ( bm->bm_flags & BM_FLAG_RLE )
1798                                 gr_bm_ubitblt00_rle(bm->bm_w, bm->bm_h, x, y, 0, 0, bm, &grd_curcanv->cv_bitmap );
1799                         else
1800                                 gr_ubitmap00( x, y, bm );
1801                         return;
1802 #ifdef OGL
1803                 case BM_OGL:
1804                         ogl_ubitmapm(x,y,bm);
1805                         return;
1806 #endif
1807 #ifdef D1XD3D
1808                 case BM_DIRECTX:
1809                         Assert ((int)grd_curcanv->cv_bitmap.bm_data == BM_D3D_RENDER || (int)grd_curcanv->cv_bitmap.bm_data == BM_D3D_DISPLAY);
1810                         Win32_BlitLinearToDirectX_bm(bm, 0, 0, bm->bm_w, bm->bm_h, x, y, 0);
1811                         return;
1812 #endif
1813 #ifdef __MSDOS__
1814                 case BM_SVGA:
1815                         if ( bm->bm_flags & BM_FLAG_RLE )
1816                                 gr_bm_ubitblt0x_rle(bm->bm_w, bm->bm_h, x, y, 0, 0, bm, &grd_curcanv->cv_bitmap );
1817                         else
1818                                 gr_vesa_bitmap( bm, &grd_curcanv->cv_bitmap, x, y );
1819                         return;
1820                 case BM_MODEX:
1821                         gr_bm_ubitblt01(bm->bm_w, bm->bm_h, x+XOFFSET, y+YOFFSET, 0, 0, bm, &grd_curcanv->cv_bitmap);
1822                         return;
1823 #endif
1824 #if defined(POLY_ACC)
1825                 case BM_LINEAR15:
1826                         if ( bm->bm_flags & BM_FLAG_RLE )
1827                                 gr_bm_ubitblt05_rle(bm->bm_w, bm->bm_h, x, y, 0, 0, bm, &grd_curcanv->cv_bitmap );
1828                         else
1829                                 gr_ubitmap05( x, y, bm);
1830                         return;
1831
1832 #endif
1833                 default:
1834                         gr_ubitmap012( x, y, bm );
1835                         return;
1836                 }
1837         } else  {
1838                 gr_ubitmapGENERIC(x, y, bm);
1839         }
1840 }
1841
1842
1843 void gr_ubitmapm( int x, int y, grs_bitmap *bm )
1844 {
1845         int source, dest;
1846
1847         source = bm->bm_type;
1848         dest = TYPE;
1849
1850         Assert(x+bm->bm_w <= grd_curcanv->cv_w);
1851         Assert(y+bm->bm_h <= grd_curcanv->cv_h);
1852
1853 #ifdef _3DFX
1854         _3dfx_Blit( x, y, bm );
1855         if ( _3dfx_skip_ddraw )
1856                 return;
1857 #endif
1858
1859         if (source==BM_LINEAR) {
1860                 switch( dest )
1861                 {
1862                 case BM_LINEAR:
1863                         if ( bm->bm_flags & BM_FLAG_RLE )
1864                                 gr_bm_ubitblt00m_rle(bm->bm_w, bm->bm_h, x, y, 0, 0, bm, &grd_curcanv->cv_bitmap );
1865                         else
1866                                 gr_ubitmap00m( x, y, bm );
1867                         return;
1868 #ifdef __MSDOS__
1869                 case BM_SVGA:
1870                         if (bm->bm_flags & BM_FLAG_RLE)
1871                                 gr_bm_ubitblt02m_rle(bm->bm_w, bm->bm_h, x, y, 0, 0, bm, &grd_curcanv->cv_bitmap);
1872                         //gr_bm_ubitblt0xm_rle(bm->bm_w, bm->bm_h, x, y, 0, 0, bm, &grd_curcanv->cv_bitmap);
1873                         else
1874                                 gr_bm_ubitblt02m(bm->bm_w, bm->bm_h, x, y, 0, 0, bm, &grd_curcanv->cv_bitmap);
1875                         //gr_ubitmapGENERICm(x, y, bm);
1876                         return;
1877                 case BM_MODEX:
1878                         gr_bm_ubitblt01m(bm->bm_w, bm->bm_h, x+XOFFSET, y+YOFFSET, 0, 0, bm, &grd_curcanv->cv_bitmap);
1879                         return;
1880 #endif
1881 #if defined(POLY_ACC)
1882                 case BM_LINEAR15:
1883                         if ( bm->bm_flags & BM_FLAG_RLE )
1884                                 gr_bm_ubitblt05m_rle(bm->bm_w, bm->bm_h, x, y, 0, 0, bm, &grd_curcanv->cv_bitmap );
1885                         else
1886                                 gr_ubitmap05m( x, y, bm );
1887                         return;
1888 #endif
1889
1890                 default:
1891                         gr_ubitmap012m( x, y, bm );
1892                         return;
1893                 }
1894         } else {
1895                 gr_ubitmapGENERICm(x, y, bm);
1896         }
1897 }
1898
1899
1900 void gr_bitmapm( int x, int y, grs_bitmap *bm )
1901 {
1902         int dx1=x, dx2=x+bm->bm_w-1;
1903         int dy1=y, dy2=y+bm->bm_h-1;
1904         int sx=0, sy=0;
1905
1906         if ((dx1 >= grd_curcanv->cv_bitmap.bm_w ) || (dx2 < 0)) return;
1907         if ((dy1 >= grd_curcanv->cv_bitmap.bm_h) || (dy2 < 0)) return;
1908         if ( dx1 < 0 ) { sx = -dx1; dx1 = 0; }
1909         if ( dy1 < 0 ) { sy = -dy1; dy1 = 0; }
1910         if ( dx2 >= grd_curcanv->cv_bitmap.bm_w ) { dx2 = grd_curcanv->cv_bitmap.bm_w-1; }
1911         if ( dy2 >= grd_curcanv->cv_bitmap.bm_h ) { dy2 = grd_curcanv->cv_bitmap.bm_h-1; }
1912
1913         // Draw bitmap bm[x,y] into (dx1,dy1)-(dx2,dy2)
1914
1915         if ( (bm->bm_type == BM_LINEAR) && (grd_curcanv->cv_bitmap.bm_type == BM_LINEAR ))
1916         {
1917                 if ( bm->bm_flags & BM_FLAG_RLE )
1918                         gr_bm_ubitblt00m_rle(dx2-dx1+1,dy2-dy1+1, dx1, dy1, sx, sy, bm, &grd_curcanv->cv_bitmap );
1919                 else
1920                         gr_bm_ubitblt00m(dx2-dx1+1,dy2-dy1+1, dx1, dy1, sx, sy, bm, &grd_curcanv->cv_bitmap );
1921                 return;
1922         }
1923 #ifdef __MSDOS__
1924         else if ( (bm->bm_type == BM_LINEAR) && (grd_curcanv->cv_bitmap.bm_type == BM_SVGA ))
1925         {
1926                 gr_bm_ubitblt02m(dx2-dx1+1,dy2-dy1+1, dx1, dy1, sx, sy, bm, &grd_curcanv->cv_bitmap );
1927                 return;
1928         }
1929 #endif
1930
1931         gr_bm_ubitbltm(dx2-dx1+1,dy2-dy1+1, dx1, dy1, sx, sy, bm, &grd_curcanv->cv_bitmap );
1932
1933 }
1934
1935 void gr_bm_ubitbltm(int w, int h, int dx, int dy, int sx, int sy, grs_bitmap * src, grs_bitmap * dest)
1936 {
1937         register int x1, y1;
1938         ubyte c;
1939
1940 #ifdef OGL
1941         if ( (src->bm_type == BM_LINEAR) && (dest->bm_type == BM_OGL ))
1942         {
1943                 ogl_ubitblt(w, h, dx, dy, sx, sy, src, dest);
1944                 return;
1945         }
1946         if ( (src->bm_type == BM_OGL) && (dest->bm_type == BM_LINEAR ))
1947         {
1948                 ogl_ubitblt_tolinear(w, h, dx, dy, sx, sy, src, dest);
1949                 return;
1950         }
1951         if ( (src->bm_type == BM_OGL) && (dest->bm_type == BM_OGL ))
1952         {
1953                 ogl_ubitblt_copy(w, h, dx, dy, sx, sy, src, dest);
1954                 return;
1955         }
1956 #endif
1957 #ifdef D1XD3D
1958         if ( (src->bm_type == BM_LINEAR) && (dest->bm_type == BM_DIRECTX ))
1959         {
1960                 Assert ((int)dest->bm_data == BM_D3D_RENDER || (int)dest->bm_data == BM_D3D_DISPLAY);
1961                 Win32_BlitLinearToDirectX_bm (src, sx, sy, w, h, dx, dy, 1);
1962                 return;
1963         }
1964         if ( (src->bm_type == BM_DIRECTX) && (dest->bm_type == BM_DIRECTX ))
1965         {
1966                 Assert ((int)src->bm_data == BM_D3D_RENDER || (int)src->bm_data == BM_D3D_DISPLAY);
1967                 //Win32_BlitDirectXToDirectX (w, h, dx, dy, sx, sy, src->bm_data, dest->bm_data, 0);
1968                 return;
1969         }
1970 #endif
1971 #if defined(POLY_ACC)
1972         if(src->bm_type == BM_LINEAR && dest->bm_type == BM_LINEAR15)
1973         {
1974                 ubyte *s;
1975                 ushort *d;
1976                 ushort u;
1977                 int smod, dmod;
1978
1979                 pa_flush();
1980                 s = (ubyte *)(src->bm_data + src->bm_rowsize * sy + sx);
1981                 smod = src->bm_rowsize - w;
1982                 d = (ushort *)(dest->bm_data + dest->bm_rowsize * dy + dx * PA_BPP);
1983                 dmod = dest->bm_rowsize / PA_BPP - w;
1984                 for (; h--;) {
1985                         for (x1=w; x1--; ) {
1986                                 if ((u = *s) != TRANSPARENCY_COLOR)
1987                                         *d = pa_clut[u];
1988                                 ++s;
1989                                 ++d;
1990                         }
1991                         s += smod;
1992                         d += dmod;
1993                 }
1994         }
1995
1996         if(src->bm_type == BM_LINEAR15)
1997         {
1998                 Assert(src->bm_type == dest->bm_type);         // I don't support 15 to 8 yet.
1999                 pa_blit_transparent(dest, dx, dy, src, sx, sy, w, h);
2000                 return;
2001         }
2002 #endif
2003
2004         for (y1=0; y1 < h; y1++ )    {
2005                 for (x1=0; x1 < w; x1++ )    {
2006                         if ((c=gr_gpixel(src,sx+x1,sy+y1))!=TRANSPARENCY_COLOR)
2007                                 gr_bm_pixel( dest, dx+x1, dy+y1,c  );
2008                 }
2009         }
2010 }
2011
2012
2013 // rescalling bitmaps, 10/14/99 Jan Bobrowski jb@wizard.ae.krakow.pl
2014
2015 inline void scale_line(byte *in, byte *out, int ilen, int olen)
2016 {
2017         int a = olen/ilen, b = olen%ilen;
2018         int c = 0, i;
2019         byte *end = out + olen;
2020         while(out<end) {
2021                 i = a;
2022                 c += b;
2023                 if(c >= ilen) {
2024                         c -= ilen;
2025                         goto inside;
2026                 }
2027                 while(--i>=0) {
2028                 inside:
2029                         *out++ = *in;
2030                 }
2031                 in++;
2032         }
2033 }
2034
2035 void gr_bitmap_scale_to(grs_bitmap *src, grs_bitmap *dst)
2036 {
2037         byte *s = src->bm_data;
2038         byte *d = dst->bm_data;
2039         int h = src->bm_h;
2040         int a = dst->bm_h/h, b = dst->bm_h%h;
2041         int c = 0, i, y;
2042
2043         for(y=0; y<h; y++) {
2044                 i = a;
2045                 c += b;
2046                 if(c >= h) {
2047                         c -= h;
2048                         goto inside;
2049                 }
2050                 while(--i>=0) {
2051                 inside:
2052                         scale_line(s, d, src->bm_w, dst->bm_w);
2053                         d += dst->bm_rowsize;
2054                 }
2055                 s += src->bm_rowsize;
2056         }
2057 }
2058
2059 void show_fullscr(grs_bitmap *bm)
2060 {
2061         grs_bitmap * const scr = &grd_curcanv->cv_bitmap;
2062
2063 #ifdef OGL
2064         if(bm->bm_type == BM_LINEAR && scr->bm_type == BM_OGL) {
2065                 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
2066                 return;
2067         }
2068 #endif
2069         if(scr->bm_type != BM_LINEAR) {
2070                 grs_bitmap *tmp = gr_create_bitmap(scr->bm_w, scr->bm_h);
2071                 gr_bitmap_scale_to(bm, tmp);
2072                 gr_bitmap(0, 0, tmp);
2073                 gr_free_bitmap(tmp);
2074                 return;
2075         }
2076         gr_bitmap_scale_to(bm, scr);
2077 }