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