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