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