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