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