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