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