]> icculus.org git repositories - btb/d2x.git/blob - 2d/rle.c
remove old _3DFX code
[btb/d2x.git] / 2d / rle.c
1 /* $Id: rle.c,v 1.20 2005-07-30 01:51:42 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-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
13 */
14
15 /*
16  *
17  * Routines to do run length encoding/decoding
18  * on bitmaps.
19  *
20  */
21
22
23 #ifdef HAVE_CONFIG_H
24 #include <conf.h>
25 #endif
26
27 #ifdef RCS
28 static char rcsid[] = "$Id: rle.c,v 1.20 2005-07-30 01:51:42 chris Exp $";
29 #endif
30
31 #include <stdlib.h>
32 #include <stdio.h>
33 #include <string.h>
34
35 #include "pstypes.h"
36 #include "u_mem.h"
37 #include "mono.h"
38
39
40 #include "gr.h"
41 #include "grdef.h"
42 #include "error.h"
43 //#include "key.h"
44 #include "rle.h"
45 #include "byteswap.h"
46
47 #define RLE_CODE        0xE0
48 #define NOT_RLE_CODE    31
49
50 #define IS_RLE_CODE(x) (((x) & RLE_CODE) == RLE_CODE)
51
52 #if !defined(NO_ASM) && defined(__WATCOMC__)
53 #define RLE_DECODE_ASM
54
55 ubyte *gr_rle_decode_asm( ubyte * src, ubyte * dest );
56 #pragma aux gr_rle_decode_asm parm [esi] [edi] value [edi] modify exact [eax ebx ecx edx esi edi] = \
57 "  cld              " \
58 "   xor ecx, ecx    " \
59 "   cld             " \
60 "   jmp NextByte    " \
61 "                   " \
62 "Unique:            " \
63 "   mov [edi],al    " \
64 "   inc edi         " \
65 "                   " \
66 "NextByte:          " \
67 "   mov al,[esi]    " \
68 "   inc esi         " \
69 "                   " \
70 "   mov ah, al      " \
71 "   and ah, 0xE0    " \
72 "  cmp  ah, 0xE0    " \
73 "   jne   Unique    " \
74 "                   " \
75 "   mov cl, al      " \
76 "   and cl, 31      " \
77 "   je      done    " \
78 "                   " \
79 "   mov al,[esi]    " \
80 "   inc esi         " \
81 "   mov ah, al      " \
82 "   shr ecx,1       " \
83 "   rep stosw       " \
84 "   jnc NextByte    " \
85 "   mov [edi],al    " \
86 "   inc edi         " \
87 "                   " \
88 "   jmp NextByte    " \
89 "                   " \
90 "done:              ";
91
92 #elif !defined(NO_ASM) && defined(__GNUC__)
93 #define RLE_DECODE_ASM
94
95 static inline int gr_rle_decode_asm( ubyte * src, ubyte * dest ) {
96    register int __ret;
97    int dummy;
98    __asm__ __volatile__ (
99 "   cld;"
100 "   xorl %%ecx, %%ecx;"
101 "   jmp 1f;"
102 "0:;"
103 "   movb %%al,(%%edi);"
104 "   incl %%edi;"
105 "1:;"
106 "   movb (%%esi), %%al;"
107 "   incl %%esi;"
108 "   movb %%al, %%ah;"
109 "   andb $0xE0, %%ah;"
110 "   cmpb $0xE0, %%ah;"
111 "   jne 0b;"
112 "   movb %%al, %%cl;"
113 "   andb $31, %%cl;"
114 "   je 2f;"
115 "   movb (%%esi), %%al;"
116 "   incl %%esi;"
117 "   movb %%al, %%ah;"
118 "   shrl $1, %%ecx;"
119 "   rep; stosw;"
120 "   jnc 1b;"
121 "   movb %%al, (%%edi);"
122 "   incl %%edi;"
123 "   jmp 1b;"
124 "2:"
125 : "=D" (__ret), "=S" (dummy) : "1" (src), "D" (dest) : "%eax", "%ecx");
126   return __ret;
127 }
128
129 #elif !defined(NO_ASM) && defined(_MSC_VER)
130 #define RLE_DECODE_ASM
131
132 __inline int gr_rle_decode_asm( ubyte * src, ubyte * dest )
133 {
134          int retval;
135         __asm {
136                 mov esi,[src]
137                 mov edi,[dest]
138         xor ecx, ecx
139                 cld
140                 jmp NextByte
141 Unique:
142                 mov [edi], al
143                 inc edi
144 NextByte:
145                 mov al,[esi]
146                 inc esi
147                 mov ah, al
148                 and ah,0xE0
149                 cmp ah,0xE0
150                 jne Unique
151
152                 mov cl, al
153                 and cl, 31
154                 je done
155
156                 mov al, [esi]
157                 inc esi
158                 mov ah, al
159                 shr ecx, 1
160                 rep stosw
161                 jnc NextByte
162                 mov [edi], al
163                 inc edi
164                 jmp NextByte
165 done:
166                 mov [retval],edi
167         }
168         return retval;
169 }
170
171 #endif
172
173 #ifdef RLE_DECODE_ASM
174
175 #if 0
176 void gr_rle_decode( ubyte * src, ubyte * dest, int dest_len )
177 {
178         ubyte *dest_end;
179
180         dest_end = (ubyte *)gr_rle_decode_asm( src, dest );
181
182         Assert(dest_end-src < dest_len);
183 }
184 #else
185 void gr_rle_decode( ubyte * src, ubyte * dest )
186 {
187     gr_rle_decode_asm( src, dest );
188 }
189 #endif
190
191 #else // NO_ASM or unknown compiler
192
193 void gr_rle_decode( ubyte * src, ubyte * dest )
194 {
195         int i;
196         ubyte data, count = 0;
197
198         while(1) {
199                 data = *src++;
200                 if ( ! IS_RLE_CODE(data) ) {
201                         *dest++ = data;
202                 } else {
203                         count = data & NOT_RLE_CODE;
204                         if (count == 0)
205                                 return;
206                         data = *src++;
207                         for (i = 0; i < count; i++)
208                                 *dest++ = data;
209                 }
210         }
211 }
212
213 #endif
214
215 void rle_stosb (unsigned char *dest, int len, int color);
216
217 #if !defined(NO_ASM) && defined(__WATCOMC__)
218
219 #pragma aux rle_stosb = "cld rep    stosb" parm [edi] [ecx] [eax] modify exact [edi ecx];
220
221 #elif !defined(NO_ASM) && defined(__GNUC__)
222
223 inline void rle_stosb (unsigned char *dest, int len, int color) {
224         int dummy[2];
225    __asm__ __volatile__ (
226     "cld; rep; stosb"
227     : "=D" (dummy[0]), "=c" (dummy[1])
228         : "0" (dest), "1" (len), "a" (color) );
229 }
230
231 #elif !defined(NO_ASM) && defined(_MSC_VER)
232
233 __inline void rle_stosb (unsigned char *dest, int len, int color)
234 {
235   __asm {
236         mov edi,[dest]
237         mov ecx,[len]
238         mov eax,[color]
239         cld
240         rep stosb
241   }
242 }
243
244 #else // NO_ASM or unknown compiler
245
246 void rle_stosb (unsigned char *dest, int len, int color)
247 {
248         int i;
249         for (i=0; i<len; i++ )
250                 *dest++ = color;
251 }
252
253 #endif
254
255 // Given pointer to start of one scanline of rle data, uncompress it to
256 // dest, from source pixels x1 to x2.
257 void gr_rle_expand_scanline_masked( ubyte *dest, ubyte *src, int x1, int x2  )
258 {
259         int i = 0;
260         ubyte count;
261         ubyte color=0;
262
263         if ( x2 < x1 ) return;
264
265         count = 0;
266         while ( i < x1 )        {
267                 color = *src++;
268                 if ( color == RLE_CODE ) return;
269                 if ( IS_RLE_CODE(color) )       {
270                         count = color & (~RLE_CODE);
271                         color = *src++;
272                 } else {
273                         // unique
274                         count = 1;
275                 }
276                 i += count;
277         }
278         count = i - x1;
279         i = x1;
280         // we know have '*count' pixels of 'color'.
281         
282         if ( x1+count > x2 )    {
283                 count = x2-x1+1;
284                 if ( color != TRANSPARENCY_COLOR )      rle_stosb( dest, count, color );
285                 return;
286         }
287
288         if ( color != TRANSPARENCY_COLOR )      rle_stosb( dest, count, color );
289         dest += count;
290         i += count;
291
292         while( i <= x2 )                {
293                 color = *src++;
294                 if ( color == RLE_CODE ) return;
295                 if ( IS_RLE_CODE(color) )       {
296                         count = color & (~RLE_CODE);
297                         color = *src++;
298                 } else {
299                         // unique
300                         count = 1;
301                 }
302                 // we know have '*count' pixels of 'color'.
303                 if ( i+count <= x2 )    {
304                         if ( color != TRANSPARENCY_COLOR )rle_stosb( dest, count, color );
305                         i += count;
306                         dest += count;
307                 } else {
308                         count = x2-i+1;
309                         if ( color != TRANSPARENCY_COLOR )rle_stosb( dest, count, color );
310                         i += count;
311                         dest += count;
312                 }
313
314         }       
315 }
316
317 void gr_rle_expand_scanline( ubyte *dest, ubyte *src, int x1, int x2  )
318 {
319         int i = 0;
320         ubyte count;
321         ubyte color=0;
322
323         if ( x2 < x1 ) return;
324
325         count = 0;
326         while ( i < x1 )        {
327                 color = *src++;
328                 if ( color == RLE_CODE ) return;
329                 if ( IS_RLE_CODE(color) )       {
330                         count = color & (~RLE_CODE);
331                         color = *src++;
332                 } else {
333                         // unique
334                         count = 1;
335                 }
336                 i += count;
337         }
338         count = i - x1;
339         i = x1;
340         // we know have '*count' pixels of 'color'.
341         
342         if ( x1+count > x2 )    {
343                 count = x2-x1+1;
344                 rle_stosb( dest, count, color );
345                 return;
346         }
347
348         rle_stosb( dest, count, color );
349         dest += count;
350         i += count;
351
352         while( i <= x2 )                {
353                 color = *src++;
354                 if ( color == RLE_CODE ) return;
355                 if ( IS_RLE_CODE(color) )       {
356                         count = color & (~RLE_CODE);
357                         color = *src++;
358                 } else {
359                         // unique
360                         count = 1;
361                 }
362                 // we know have '*count' pixels of 'color'.
363                 if ( i+count <= x2 )    {
364                         rle_stosb( dest, count, color );
365                         i += count;
366                         dest += count;
367                 } else {
368                         count = x2-i+1;
369                         rle_stosb( dest, count, color );
370                         i += count;
371                         dest += count;
372                 }
373         }
374 }
375
376
377 int gr_rle_encode( int org_size, ubyte *src, ubyte *dest )
378 {
379         int i;
380         ubyte c, oc;
381         ubyte count;
382         ubyte *dest_start;
383
384         dest_start = dest;
385         oc = *src++;
386         count = 1;
387
388         for (i=1; i<org_size; i++ )     {
389                 c = *src++;
390                 if ( c!=oc )    {
391                         if ( count )    {
392                                 if ( (count==1) && (! IS_RLE_CODE(oc)) )        {
393                                         *dest++ = oc;
394                                         Assert( oc != RLE_CODE );
395                                 } else {
396                                         count |= RLE_CODE;
397                                         *dest++ = count;
398                                         *dest++ = oc;
399                                 }
400                         }
401                         oc = c;
402                         count = 0;
403                 }
404                 count++;
405                 if ( count == NOT_RLE_CODE )    {
406                         count |= RLE_CODE;
407                         *dest++=count;
408                         *dest++=oc;
409                         count = 0;
410                 }
411         }
412         if (count)      {
413                 if ( (count==1) && (! IS_RLE_CODE(oc)) )        {
414                         *dest++ = oc;
415                         Assert( oc != RLE_CODE );
416                 } else {
417                         count |= RLE_CODE;
418                         *dest++ = count;
419                         *dest++ = oc;
420                 }
421         }
422         *dest++ = RLE_CODE;
423
424         return dest-dest_start;
425 }
426
427
428 int gr_rle_getsize( int org_size, ubyte *src )
429 {
430         int i;
431         ubyte c, oc;
432         ubyte count;
433         int dest_size=0;
434
435         oc = *src++;
436         count = 1;
437
438         for (i=1; i<org_size; i++ )     {
439                 c = *src++;
440                 if ( c!=oc )    {
441                         if ( count )    {
442                                 if ( (count==1) && (! IS_RLE_CODE(oc)) )        {
443                                         dest_size++;
444                                 } else {
445                                         dest_size++;
446                                         dest_size++;
447                                 }
448                         }
449                         oc = c;
450                         count = 0;
451                 }
452                 count++;
453                 if ( count == NOT_RLE_CODE )    {
454                         dest_size++;
455                         dest_size++;
456                         count = 0;
457                 }
458         }
459         if (count)      {
460                 if ( (count==1) && (! IS_RLE_CODE(oc)) )        {
461                         dest_size++;
462                 } else {
463                         dest_size++;
464                         dest_size++;
465                 }
466         }
467         dest_size++;
468
469         return dest_size;
470 }
471
472 int gr_bitmap_rle_compress( grs_bitmap * bmp )
473 {
474         int y, d1, d;
475         int doffset;
476         ubyte *rle_data;
477         int large_rle = 0;
478
479         // first must check to see if this is large bitmap.
480
481         for (y=0; y<bmp->bm_h; y++ )    {
482                 d1= gr_rle_getsize( bmp->bm_w, &bmp->bm_data[bmp->bm_w*y] );
483                 if (d1 > 255) {
484                         large_rle = 1;
485                         break;
486                 }
487         }
488
489         rle_data=d_malloc( MAX_BMP_SIZE(bmp->bm_w, bmp->bm_h) );
490         if (rle_data==NULL) return 0;
491         if (!large_rle)
492                 doffset = 4 + bmp->bm_h;
493         else
494                 doffset = 4 + (2 * bmp->bm_h);          // each row of rle'd bitmap has short instead of byte offset now
495
496         for (y=0; y<bmp->bm_h; y++ )    {
497                 d1= gr_rle_getsize( bmp->bm_w, &bmp->bm_data[bmp->bm_w*y] );
498                 if ( ((doffset+d1) > bmp->bm_w*bmp->bm_h) || (d1 > (large_rle?32767:255) ) ) {
499                         d_free(rle_data);
500                         return 0;
501                 }
502                 d = gr_rle_encode( bmp->bm_w, &bmp->bm_data[bmp->bm_w*y], &rle_data[doffset] );
503                 Assert( d==d1 );
504                 doffset += d;
505                 if (large_rle)
506                         *((short *)&(rle_data[(y*2)+4])) = (short)d;
507                 else
508                         rle_data[y+4] = d;
509         }
510         //mprintf( 0, "Bitmap of size %dx%d, (%d bytes) went down to %d bytes\n", bmp->bm_w, bmp->bm_h, bmp->bm_h*bmp->bm_w, doffset );
511         memcpy(         rle_data, &doffset, 4 );
512         memcpy(         bmp->bm_data, rle_data, doffset );
513         d_free(rle_data);
514         bmp->bm_flags |= BM_FLAG_RLE;
515         if (large_rle)
516                 bmp->bm_flags |= BM_FLAG_RLE_BIG;
517         return 1;
518 }
519
520 #define MAX_CACHE_BITMAPS 32
521
522 typedef struct rle_cache_element {
523         grs_bitmap * rle_bitmap;
524         ubyte * rle_data;
525         grs_bitmap * expanded_bitmap;
526         int last_used;
527 } rle_cache_element;
528
529 int rle_cache_initialized = 0;
530 int rle_counter = 0;
531 int rle_next = 0;
532 rle_cache_element rle_cache[MAX_CACHE_BITMAPS];
533
534 int rle_hits = 0;
535 int rle_misses = 0;
536
537 void rle_cache_close(void)
538 {
539         if (rle_cache_initialized)      {
540                 int i;
541                 rle_cache_initialized = 0;
542                 for (i=0; i<MAX_CACHE_BITMAPS; i++ )    {
543                         gr_free_bitmap(rle_cache[i].expanded_bitmap);
544                 }
545         }
546 }
547
548 void rle_cache_init()
549 {
550         int i;
551         for (i=0; i<MAX_CACHE_BITMAPS; i++ )    {
552                 rle_cache[i].rle_bitmap = NULL;
553                 rle_cache[i].expanded_bitmap = gr_create_bitmap( 64, 64 );
554                 rle_cache[i].last_used = 0;
555                 Assert( rle_cache[i].expanded_bitmap != NULL );
556         }
557         rle_cache_initialized = 1;
558         atexit( rle_cache_close );
559 }
560
561 void rle_cache_flush()
562 {
563         int i;
564         for (i=0; i<MAX_CACHE_BITMAPS; i++ )    {
565                 rle_cache[i].rle_bitmap = NULL;
566                 rle_cache[i].last_used = 0;
567         }
568 }
569
570 void rle_expand_texture_sub( grs_bitmap * bmp, grs_bitmap * rle_temp_bitmap_1 )
571 {
572         unsigned char * dbits;
573         unsigned char * sbits;
574         int i;
575 #ifdef RLE_DECODE_ASM
576         unsigned char * dbits1;
577 #endif
578
579 #ifdef D1XD3D
580         Assert (bmp->iMagic == BM_MAGIC_NUMBER);
581 #endif
582
583         sbits = &bmp->bm_data[4 + bmp->bm_h];
584         dbits = rle_temp_bitmap_1->bm_data;
585
586         rle_temp_bitmap_1->bm_flags = bmp->bm_flags & (~BM_FLAG_RLE);
587
588         for (i=0; i < bmp->bm_h; i++ )    {
589 #ifdef RLE_DECODE_ASM
590                 dbits1=(unsigned char *)gr_rle_decode_asm( sbits, dbits );
591 #else
592                 gr_rle_decode( sbits, dbits );
593 #endif
594                 sbits += (int)bmp->bm_data[4+i];
595                 dbits += bmp->bm_w;
596 #ifdef RLE_DECODE_ASM
597                 Assert( dbits == dbits1 );              // Get John, bogus rle data!
598 #endif
599         }
600 #ifdef D1XD3D
601         gr_set_bitmap_data (rle_temp_bitmap_1, rle_temp_bitmap_1->bm_data);
602 #endif
603 }
604
605
606 grs_bitmap * rle_expand_texture( grs_bitmap * bmp )
607 {
608         int i;
609         int lowest_count, lc;
610         int least_recently_used;
611
612         if (!rle_cache_initialized) rle_cache_init();
613
614         Assert( !(bmp->bm_flags & BM_FLAG_PAGED_OUT) );
615
616         lc = rle_counter;
617         rle_counter++;
618         if ( rle_counter < lc ) {
619                 for (i=0; i<MAX_CACHE_BITMAPS; i++ )    {
620                         rle_cache[i].rle_bitmap = NULL;
621                         rle_cache[i].last_used = 0;
622                 }
623         }
624
625 //      if (((rle_counter % 100)==1) && (rle_hits+rle_misses > 0))
626 //              mprintf(( 0, "RLE-CACHE %d%%, H:%d, M:%d\n", (rle_misses*100)/(rle_hits+rle_misses), rle_hits, rle_misses ));
627
628         lowest_count = rle_cache[rle_next].last_used;
629         least_recently_used = rle_next;
630         rle_next++;
631         if ( rle_next >= MAX_CACHE_BITMAPS )
632                 rle_next = 0;
633
634         for (i=0; i<MAX_CACHE_BITMAPS; i++ )    {
635                 if (rle_cache[i].rle_bitmap == bmp)     {
636                         rle_hits++;
637                         rle_cache[i].last_used = rle_counter;
638                         return rle_cache[i].expanded_bitmap;
639                 }
640                 if ( rle_cache[i].last_used < lowest_count )    {
641                         lowest_count = rle_cache[i].last_used;
642                         least_recently_used = i;
643                 }
644         }
645
646         Assert(bmp->bm_w<=64 && bmp->bm_h<=64); //dest buffer is 64x64
647         rle_misses++;
648         rle_expand_texture_sub( bmp, rle_cache[least_recently_used].expanded_bitmap );
649         rle_cache[least_recently_used].rle_bitmap = bmp;
650         rle_cache[least_recently_used].last_used = rle_counter;
651         return rle_cache[least_recently_used].expanded_bitmap;
652 }
653
654
655 void gr_rle_expand_scanline_generic( grs_bitmap * dest, int dx, int dy, ubyte *src, int x1, int x2 )
656 {
657         int i = 0, j;
658         int count;
659         ubyte color=0;
660
661         if ( x2 < x1 ) return;
662
663         count = 0;
664         while ( i < x1 )        {
665                 color = *src++;
666                 if ( color == RLE_CODE ) return;
667                 if ( IS_RLE_CODE(color) )       {
668                         count = color & NOT_RLE_CODE;
669                         color = *src++;
670                 } else {
671                         // unique
672                         count = 1;
673                 }
674                 i += count;
675         }
676         count = i - x1;
677         i = x1;
678         // we know have '*count' pixels of 'color'.
679
680         if ( x1+count > x2 )    {
681                 count = x2-x1+1;
682                 for ( j=0; j<count; j++ )
683                         gr_bm_pixel( dest, dx++, dy, color );
684                 return;
685         }
686
687         for ( j=0; j<count; j++ )
688                 gr_bm_pixel( dest, dx++, dy, color );
689         i += count;
690
691         while( i <= x2 )                {
692                 color = *src++;
693                 if ( color == RLE_CODE ) return;
694                 if ( IS_RLE_CODE(color) )       {
695                         count = color & NOT_RLE_CODE;
696                         color = *src++;
697                 } else {
698                         // unique
699                         count = 1;
700                 }
701                 // we know have '*count' pixels of 'color'.
702                 if ( i+count <= x2 )    {
703                         for ( j=0; j<count; j++ )
704                                 gr_bm_pixel( dest, dx++, dy, color );
705                         i += count;
706                 } else {
707                         count = x2-i+1;
708                         for ( j=0; j<count; j++ )
709                                 gr_bm_pixel( dest, dx++, dy, color );
710                         i += count;
711                 }
712         }
713 }
714
715 void gr_rle_expand_scanline_generic_masked( grs_bitmap * dest, int dx, int dy, ubyte *src, int x1, int x2  )
716 {
717         int i = 0, j;
718         int count;
719         ubyte color = 0;
720
721         if ( x2 < x1 ) return;
722
723         count = 0;
724         while ( i < x1 )        {
725                 color = *src++;
726                 if ( color == RLE_CODE ) return;
727                 if ( IS_RLE_CODE(color) )       {
728                         count = color & NOT_RLE_CODE;
729                         color = *src++;
730                 } else {
731                         // unique
732                         count = 1;
733                 }
734                 i += count;
735         }
736         count = i - x1;
737         i = x1;
738         // we know have '*count' pixels of 'color'.
739
740         if ( x1+count > x2 )    {
741                 count = x2-x1+1;
742                 if (color != TRANSPARENCY_COLOR) {
743                         for ( j=0; j<count; j++ )
744                                 gr_bm_pixel( dest, dx++, dy, color );
745                 }
746                 return;
747         }
748
749         if ( color != TRANSPARENCY_COLOR ) {
750                 for ( j=0; j<count; j++ )
751                         gr_bm_pixel( dest, dx++, dy, color );
752         } else
753                 dx += count;
754         i += count;
755
756         while( i <= x2 )                {
757                 color = *src++;
758                 if ( color == RLE_CODE ) return;
759                 if ( IS_RLE_CODE(color) )       {
760                         count = color & NOT_RLE_CODE;
761                         color = *src++;
762                 } else {
763                         // unique
764                         count = 1;
765                 }
766                 // we know have '*count' pixels of 'color'.
767                 if ( i+count <= x2 )    {
768                         if ( color != TRANSPARENCY_COLOR ) {
769                                 for ( j=0; j<count; j++ )
770                                         gr_bm_pixel( dest, dx++, dy, color );
771                         } else
772                                 dx += count;
773                         i += count;
774                 } else {
775                         count = x2-i+1;
776                         if ( color != TRANSPARENCY_COLOR ) {
777                                 for ( j=0; j<count; j++ )
778                                         gr_bm_pixel( dest, dx++, dy, color );
779                         } else
780                                 dx += count;
781                         i += count;
782                 }
783         }
784 }
785
786
787 #ifdef __MSDOS__
788 void gr_rle_expand_scanline_svga_masked( grs_bitmap * dest, int dx, int dy, ubyte *src, int x1, int x2  )
789 {
790         int i = 0, j;
791         int count;
792         ubyte color;
793         ubyte * vram = (ubyte *)0xA0000;
794         int VideoLocation,page,offset;
795
796         if ( x2 < x1 ) return;
797
798         VideoLocation = (unsigned int)dest->bm_data + (dest->bm_rowsize * dy) + dx;
799         page    = VideoLocation >> 16;
800         offset  = VideoLocation & 0xFFFF;
801
802         gr_vesa_setpage( page );
803
804         if ( (offset + (x2-x1+1)) < 65536 )     {
805                 // We don't cross a svga page, so blit it fast!
806                 gr_rle_expand_scanline_masked( &vram[offset], src, x1, x2 );
807                 return;
808         }
809
810         count = 0;
811         while ( i < x1 )        {
812                 color = *src++;
813                 if ( color == RLE_CODE ) return;
814                 if ( IS_RLE_CODE(color) )       {
815                         count = color & NOT_RLE_CODE;
816                         color = *src++;
817                 } else {
818                         // unique
819                         count = 1;
820                 }
821                 i += count;
822         }
823         count = i - x1;
824         i = x1;
825         // we know have '*count' pixels of 'color'.
826
827         if ( x1+count > x2 )    {
828                 count = x2-x1+1;
829                 if (color != TRANSPARENCY_COLOR) {
830                         for ( j=0; j<count; j++ )       {
831                                 vram[offset++] = color;
832                                 if ( offset >= 65536 ) {
833                                         offset -= 65536;
834                                         page++;
835                                         gr_vesa_setpage(page);
836                                 }
837                         }
838                 }
839                 return;
840         }
841
842         if ( color != TRANSPARENCY_COLOR ) {
843                 for ( j=0; j<count; j++ )       {
844                         vram[offset++] = color;
845                         if ( offset >= 65536 ) {
846                                 offset -= 65536;
847                                 page++;
848                                 gr_vesa_setpage(page);
849                         }
850                 }
851         } else  {
852                 offset += count;
853                 if ( offset >= 65536 ) {
854                         offset -= 65536;
855                         page++;
856                         gr_vesa_setpage(page);
857                 }
858         }
859         i += count;
860
861         while( i <= x2 )                {
862                 color = *src++;
863                 if ( color == RLE_CODE ) return;
864                 if ( IS_RLE_CODE(color) )       {
865                         count = color & NOT_RLE_CODE;
866                         color = *src++;
867                 } else {
868                         // unique
869                         count = 1;
870                 }
871                 // we know have '*count' pixels of 'color'.
872                 if ( i+count <= x2 )    {
873                         if ( color != TRANSPARENCY_COLOR ) {
874                                 for ( j=0; j<count; j++ )       {
875                                         vram[offset++] = color;
876                                         if ( offset >= 65536 ) {
877                                                 offset -= 65536;
878                                                 page++;
879                                                 gr_vesa_setpage(page);
880                                         }
881                                 }
882                         } else  {
883                                 offset += count;
884                                 if ( offset >= 65536 ) {
885                                         offset -= 65536;
886                                         page++;
887                                         gr_vesa_setpage(page);
888                                 }
889                         }
890                         i += count;
891                 } else {
892                         count = x2-i+1;
893                         if ( color != TRANSPARENCY_COLOR ) {
894                                 for ( j=0; j<count; j++ )       {
895                                         vram[offset++] = color;
896                                         if ( offset >= 65536 ) {
897                                                 offset -= 65536;
898                                                 page++;
899                                                 gr_vesa_setpage(page);
900                                         }
901                                 }
902                         } else  {
903                                 offset += count;
904                                 if ( offset >= 65536 ) {
905                                         offset -= 65536;
906                                         page++;
907                                         gr_vesa_setpage(page);
908                                 }
909                         }
910                         i += count;
911                 }
912         }
913 }
914 #endif // __MSDOS__
915
916
917 /*
918  * swaps entries 0 and 255 in an RLE bitmap without uncompressing it
919  */
920 void rle_swap_0_255(grs_bitmap *bmp)
921 {
922         int i, j, len, rle_big;
923         unsigned char *ptr, *ptr2, *temp, *start;
924         unsigned short line_size;
925
926         rle_big = bmp->bm_flags & BM_FLAG_RLE_BIG;
927
928         temp = d_malloc( MAX_BMP_SIZE(bmp->bm_w, bmp->bm_h) );
929
930         if (rle_big) {                  // set ptrs to first lines
931                 ptr = bmp->bm_data + 4 + 2 * bmp->bm_h;
932                 ptr2 = temp + 4 + 2 * bmp->bm_h;
933         } else {
934                 ptr = bmp->bm_data + 4 + bmp->bm_h;
935                 ptr2 = temp + 4 + bmp->bm_h;
936         }
937         for (i = 0; i < bmp->bm_h; i++) {
938                 start = ptr2;
939                 if (rle_big)
940                         line_size = INTEL_SHORT(*((unsigned short *)&bmp->bm_data[4 + 2 * i]));
941                 else
942                         line_size = bmp->bm_data[4 + i];
943                 for (j = 0; j < line_size; j++) {
944                         if ( ! IS_RLE_CODE(ptr[j]) ) {
945                                 if (ptr[j] == 0) {
946                                         *ptr2++ = RLE_CODE | 1;
947                                         *ptr2++ = 255;
948                                 } else
949                                         *ptr2++ = ptr[j];
950                         } else {
951                                 *ptr2++ = ptr[j];
952                                 if ((ptr[j] & NOT_RLE_CODE) == 0)
953                                         break;
954                                 j++;
955                                 if (ptr[j] == 0)
956                                         *ptr2++ = 255;
957                                 else if (ptr[j] == 255)
958                                         *ptr2++ = 0;
959                                 else
960                                         *ptr2++ = ptr[j];
961                         }
962                 }
963                 if (rle_big)                // set line size
964                         *((unsigned short *)&temp[4 + 2 * i]) = INTEL_SHORT(ptr2 - start);
965                 else
966                         temp[4 + i] = ptr2 - start;
967                 ptr += line_size;           // go to next line
968         }
969         len = ptr2 - temp;
970         *((int *)temp) = len;           // set total size
971         memcpy(bmp->bm_data, temp, len);
972         d_free(temp);
973 }
974
975 /*
976  * remaps all entries using colormap in an RLE bitmap without uncompressing it
977  */
978 void rle_remap(grs_bitmap *bmp, ubyte *colormap)
979 {
980         int i, j, len, rle_big;
981         unsigned char *ptr, *ptr2, *temp, *start;
982         unsigned short line_size;
983
984         rle_big = bmp->bm_flags & BM_FLAG_RLE_BIG;
985
986         temp = d_malloc( MAX_BMP_SIZE(bmp->bm_w, bmp->bm_h) + 30000 );
987
988         if (rle_big) {                  // set ptrs to first lines
989                 ptr = bmp->bm_data + 4 + 2 * bmp->bm_h;
990                 ptr2 = temp + 4 + 2 * bmp->bm_h;
991         } else {
992                 ptr = bmp->bm_data + 4 + bmp->bm_h;
993                 ptr2 = temp + 4 + bmp->bm_h;
994         }
995         for (i = 0; i < bmp->bm_h; i++) {
996                 start = ptr2;
997                 if (rle_big)
998                         line_size = INTEL_SHORT(*((unsigned short *)&bmp->bm_data[4 + 2 * i]));
999                 else
1000                         line_size = bmp->bm_data[4 + i];
1001                 for (j = 0; j < line_size; j++) {
1002                         if ( ! IS_RLE_CODE(ptr[j])) {
1003                                 if (IS_RLE_CODE(colormap[ptr[j]])) 
1004                                         *ptr2++ = RLE_CODE | 1; // add "escape sequence"
1005                                 *ptr2++ = colormap[ptr[j]]; // translate
1006                         } else {
1007                                 *ptr2++ = ptr[j]; // just copy current rle code
1008                                 if ((ptr[j] & NOT_RLE_CODE) == 0)
1009                                         break;
1010                                 j++;
1011                                 *ptr2++ = colormap[ptr[j]]; // translate
1012                         }
1013                 }
1014                 if (rle_big)                // set line size
1015                         *((unsigned short *)&temp[4 + 2 * i]) = INTEL_SHORT(ptr2 - start);
1016                 else
1017                         temp[4 + i] = ptr2 - start;
1018                 ptr += line_size;           // go to next line
1019         }
1020         len = ptr2 - temp;
1021         *((int *)temp) = len;           // set total size
1022         memcpy(bmp->bm_data, temp, len);
1023         d_free(temp);
1024 }