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