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