123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583 |
- /*
- THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
- SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
- END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
- ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
- IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
- SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
- FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
- CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
- AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
- COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
- */
- /*
- * $Source: f:/miner/source/2d/rcs/rle.c $
- * $Revision: 1.19 $
- * $Author: john $
- * $Date: 1995/01/14 19:18:31 $
- *
- * Routines to do run length encoding/decoding
- * on bitmaps.
- *
- * $Log: rle.c $
- * Revision 1.19 1995/01/14 19:18:31 john
- * Added assert to check for paged out bitmap.
- *
- * Revision 1.18 1995/01/14 11:32:07 john
- * Added rle_cache_flush function.
- *
- * Revision 1.17 1994/12/13 10:58:27 john
- * Fixed bug with 2 consecutive calls to get_expanded_Texture
- * with 2 different bitmaps, returning the same rle texture,
- * causing doors to disapper.
- *
- * Revision 1.16 1994/11/30 00:55:03 mike
- * optimization
- *
- * Revision 1.15 1994/11/24 13:24:44 john
- * Made sure that some rep movs had the cld set first.
- * Took some unused functions out.
- *
- * Revision 1.14 1994/11/23 16:03:46 john
- * Fixed generic rle'ing to use new bit method.
- *
- * Revision 1.13 1994/11/23 15:45:51 john
- * Changed to a 3 bit rle scheme.
- *
- * Revision 1.12 1994/11/18 22:50:24 john
- * Changed shorts to ints in parameters.
- *
- * Revision 1.11 1994/11/14 17:06:13 john
- * Took out Key_f12.
- *
- * Revision 1.10 1994/11/14 15:54:09 john
- * Put code in for maybe checking bogus rle data.
- *
- * Revision 1.9 1994/11/14 15:51:58 john
- * Added rle_disable_caching variable to prove the stability of my rle caching code
- * to any non-believers.
- *
- * Revision 1.8 1994/11/10 10:31:20 john
- * Reduce cache buffers to 16.
- *
- * Revision 1.7 1994/11/09 19:53:43 john
- * Added texture rle caching.
- *
- * Revision 1.6 1994/11/09 17:41:44 john
- * Made a slow version of rle bitblt to svga, modex.
- *
- * Revision 1.5 1994/11/09 17:07:50 john
- * Fixed bug with bitmap that gets bigger with rle.
- *
- * Revision 1.4 1994/11/09 16:35:17 john
- * First version with working RLE bitmaps.
- *
- * Revision 1.3 1994/10/26 12:54:47 john
- * Fixed bug with decode that used rep movsd instead of
- * rep stosd.
- *
- * Revision 1.2 1994/10/06 17:05:25 john
- * First version of rle stuff.
- *
- * Revision 1.1 1994/10/06 16:53:34 john
- * Initial revision
- *
- *
- */
- #pragma off (unreferenced)
- static char rcsid[] = "$Id: rle.c 1.19 1995/01/14 19:18:31 john Exp $";
- #pragma on (unreferenced)
- #include <stdlib.h>
- #include <malloc.h>
- #include <stdio.h>
- #include <string.h>
- #include "mem.h"
- #include "mono.h"
- #include "gr.h"
- #include "grdef.h"
- #include "dpmi.h"
- #include "error.h"
- #include "key.h"
- //#define RLE_CODE 0xC0
- //#define NOT_RLE_CODE 63
- #define RLE_CODE 0xE0
- #define NOT_RLE_CODE 31
- int gr_rle_decode_asm( ubyte * src, ubyte * dest );
- #pragma aux gr_rle_decode_asm parm [esi] [edi] value [edi] modify exact [eax ebx ecx edx esi edi] = \
- " cld "\
- " xor ecx, ecx "\
- " cld "\
- " jmp NextByte "\
- " "\
- "Unique: "\
- " mov [edi],al "\
- " inc edi "\
- " "\
- "NextByte: "\
- " mov al,[esi] "\
- " inc esi "\
- " "\
- " mov ah, al "\
- " and ah, 0xE0 "\
- " cmp ah, 0xE0 "\
- " jne Unique "\
- " "\
- " mov cl, al "\
- " and cl, 31 "\
- " je done "\
- " "\
- " mov al,[esi] "\
- " inc esi "\
- " mov ah, al "\
- " shr ecx,1 "\
- " rep stosw "\
- " jnc NextByte "\
- " mov [edi],al "\
- " inc edi "\
- " "\
- " jmp NextByte "\
- " "\
- "done: ";
- void gr_rle_decode( ubyte * src, ubyte * dest )
- {
- gr_rle_decode_asm( src, dest );
- }
- void rle_stosb(char *dest, int len, int color);
- #pragma aux rle_stosb = "cld rep stosb" parm [edi] [ecx] [eax] modify exact [edi ecx];
- // Given pointer to start of one scanline of rle data, uncompress it to
- // dest, from source pixels x1 to x2.
- void gr_rle_expand_scanline_masked( ubyte *dest, ubyte *src, int x1, int x2 )
- {
- int i = 0;
- ubyte count;
- ubyte color;
- if ( x2 < x1 ) return;
- count = 0;
- while ( i < x1 ) {
- color = *src++;
- if ( color == RLE_CODE ) return;
- if ( (color & RLE_CODE)==RLE_CODE ) {
- count = color & (~RLE_CODE);
- color = *src++;
- } else {
- // unique
- count = 1;
- }
- i += count;
- }
- count = i - x1;
- i = x1;
- // we know have '*count' pixels of 'color'.
-
- if ( x1+count > x2 ) {
- count = x2-x1+1;
- if ( color != 255 ) rle_stosb( dest, count, color );
- return;
- }
- if ( color != 255 ) rle_stosb( dest, count, color );
- dest += count;
- i += count;
- while( i <= x2 ) {
- color = *src++;
- if ( color == RLE_CODE ) return;
- if ( (color & RLE_CODE) == (RLE_CODE) ) {
- count = color & (~RLE_CODE);
- color = *src++;
- } else {
- // unique
- count = 1;
- }
- // we know have '*count' pixels of 'color'.
- if ( i+count <= x2 ) {
- if ( color != 255 )rle_stosb( dest, count, color );
- i += count;
- dest += count;
- } else {
- count = x2-i+1;
- if ( color != 255 )rle_stosb( dest, count, color );
- i += count;
- dest += count;
- }
- }
- }
- void gr_rle_expand_scanline( ubyte *dest, ubyte *src, int x1, int x2 )
- {
- int i = 0;
- ubyte count;
- ubyte color;
- if ( x2 < x1 ) return;
- count = 0;
- while ( i < x1 ) {
- color = *src++;
- if ( color == RLE_CODE ) return;
- if ( (color & RLE_CODE)==RLE_CODE ) {
- count = color & (~RLE_CODE);
- color = *src++;
- } else {
- // unique
- count = 1;
- }
- i += count;
- }
- count = i - x1;
- i = x1;
- // we know have '*count' pixels of 'color'.
-
- if ( x1+count > x2 ) {
- count = x2-x1+1;
- rle_stosb( dest, count, color );
- return;
- }
- rle_stosb( dest, count, color );
- dest += count;
- i += count;
- while( i <= x2 ) {
- color = *src++;
- if ( color == RLE_CODE ) return;
- if ( (color & RLE_CODE)==RLE_CODE ) {
- count = color & (~RLE_CODE);
- color = *src++;
- } else {
- // unique
- count = 1;
- }
- // we know have '*count' pixels of 'color'.
- if ( i+count <= x2 ) {
- rle_stosb( dest, count, color );
- i += count;
- dest += count;
- } else {
- count = x2-i+1;
- rle_stosb( dest, count, color );
- i += count;
- dest += count;
- }
- }
- }
- int gr_rle_encode( int org_size, ubyte *src, ubyte *dest )
- {
- int i;
- ubyte c, oc;
- ubyte count;
- ubyte *dest_start;
- dest_start = dest;
- oc = *src++;
- count = 1;
- for (i=1; i<org_size; i++ ) {
- c = *src++;
- if ( c!=oc ) {
- if ( count ) {
- if ( (count==1) && ((oc & RLE_CODE)!=RLE_CODE) ) {
- *dest++ = oc;
- Assert( oc != RLE_CODE );
- } else {
- count |= RLE_CODE;
- *dest++ = count;
- *dest++ = oc;
- }
- }
- oc = c;
- count = 0;
- }
- count++;
- if ( count == NOT_RLE_CODE ) {
- count |= RLE_CODE;
- *dest++=count;
- *dest++=oc;
- count = 0;
- }
- }
- if (count) {
- if ( (count==1) && ((oc & RLE_CODE)!=RLE_CODE) ) {
- *dest++ = oc;
- Assert( oc != RLE_CODE );
- } else {
- count |= RLE_CODE;
- *dest++ = count;
- *dest++ = oc;
- }
- }
- *dest++ = RLE_CODE;
- return dest-dest_start;
- }
- int gr_rle_getsize( int org_size, ubyte *src )
- {
- int i;
- ubyte c, oc;
- ubyte count;
- int dest_size=0;
- oc = *src++;
- count = 1;
- for (i=1; i<org_size; i++ ) {
- c = *src++;
- if ( c!=oc ) {
- if ( count ) {
- if ( (count==1) && ((oc & RLE_CODE)!=RLE_CODE) ) {
- dest_size++;
- } else {
- dest_size++;
- dest_size++;
- }
- }
- oc = c;
- count = 0;
- }
- count++;
- if ( count == NOT_RLE_CODE ) {
- dest_size++;
- dest_size++;
- count = 0;
- }
- }
- if (count) {
- if ( (count==1) && ((oc & RLE_CODE)!=RLE_CODE) ) {
- dest_size++;
- } else {
- dest_size++;
- dest_size++;
- }
- }
- dest_size++;
- return dest_size;
- }
- int gr_bitmap_rle_compress( grs_bitmap * bmp )
- {
- int y, d1, d;
- int doffset;
- ubyte *rle_data;
- rle_data=malloc( (bmp->bm_w+1)* bmp->bm_h );
- if (rle_data==NULL) return 0;
- doffset = 4 + bmp->bm_h;
- for (y=0; y<bmp->bm_h; y++ ) {
- d1= gr_rle_getsize( bmp->bm_w, &bmp->bm_data[bmp->bm_w*y] );
- if ( ((doffset+d1) > bmp->bm_w*bmp->bm_h) || (d1 > 255 ) ) {
- free(rle_data);
- return 0;
- }
- d = gr_rle_encode( bmp->bm_w, &bmp->bm_data[bmp->bm_w*y], &rle_data[doffset] );
- Assert( d==d1 );
- doffset += d;
- rle_data[y+4] = d;
- }
- //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 );
- memcpy( rle_data, &doffset, 4 );
- memcpy( bmp->bm_data, rle_data, doffset );
- free(rle_data);
- bmp->bm_flags |= BM_FLAG_RLE;
- return 1;
- }
- #define MAX_CACHE_BITMAPS 32
- typedef struct rle_cache_element {
- grs_bitmap * rle_bitmap;
- ubyte * rle_data;
- grs_bitmap * expanded_bitmap;
- int last_used;
- } rle_cache_element;
- int rle_cache_initialized = 0;
- int rle_counter = 0;
- int rle_next = 0;
- rle_cache_element rle_cache[MAX_CACHE_BITMAPS];
- int rle_hits = 0;
- int rle_misses = 0;
- void rle_cache_close()
- {
- if (rle_cache_initialized) {
- int i;
- rle_cache_initialized = 0;
- for (i=0; i<MAX_CACHE_BITMAPS; i++ ) {
- gr_free_bitmap(rle_cache[i].expanded_bitmap);
- }
- }
- }
- void rle_cache_init()
- {
- int i;
- for (i=0; i<MAX_CACHE_BITMAPS; i++ ) {
- rle_cache[i].rle_bitmap = NULL;
- rle_cache[i].expanded_bitmap = gr_create_bitmap( 64, 64 );
- rle_cache[i].last_used = 0;
- Assert( rle_cache[i].expanded_bitmap != NULL );
- }
- rle_cache_initialized = 1;
- atexit( rle_cache_close );
- }
- void rle_cache_flush()
- {
- int i;
- for (i=0; i<MAX_CACHE_BITMAPS; i++ ) {
- rle_cache[i].rle_bitmap = NULL;
- rle_cache[i].last_used = 0;
- }
- }
- grs_bitmap * rle_expand_texture( grs_bitmap * bmp )
- {
- int i;
- int lowest_count, lc;
- int least_recently_used;
- if (!rle_cache_initialized) rle_cache_init();
- Assert( !(bmp->bm_flags & BM_FLAG_PAGED_OUT) );
- lc = rle_counter;
- rle_counter++;
- if ( rle_counter < lc ) {
- for (i=0; i<MAX_CACHE_BITMAPS; i++ ) {
- rle_cache[i].rle_bitmap = NULL;
- rle_cache[i].last_used = 0;
- }
- }
- // if (((rle_counter % 100)==1) && (rle_hits+rle_misses > 0))
- // mprintf(( 0, "RLE-CACHE %d%%, H:%d, M:%d\n", (rle_misses*100)/(rle_hits+rle_misses), rle_hits, rle_misses ));
- lowest_count = rle_cache[rle_next].last_used;
- least_recently_used = rle_next;
- rle_next++;
- if ( rle_next >= MAX_CACHE_BITMAPS )
- rle_next = 0;
-
- for (i=0; i<MAX_CACHE_BITMAPS; i++ ) {
- if (rle_cache[i].rle_bitmap == bmp) {
- rle_hits++;
- rle_cache[i].last_used = rle_counter;
- return rle_cache[i].expanded_bitmap;
- }
- if ( rle_cache[i].last_used < lowest_count ) {
- lowest_count = rle_cache[i].last_used;
- least_recently_used = i;
- }
- }
- rle_misses++;
- rle_expand_texture_sub( bmp, rle_cache[least_recently_used].expanded_bitmap );
- rle_cache[least_recently_used].rle_bitmap = bmp;
- rle_cache[least_recently_used].last_used = rle_counter;
- return rle_cache[least_recently_used].expanded_bitmap;
- }
- void rle_expand_texture_sub( grs_bitmap * bmp, grs_bitmap * rle_temp_bitmap_1 )
- {
- unsigned char * dbits;
- unsigned char * sbits;
- int i;
- unsigned char * dbits1;
- sbits = &bmp->bm_data[4 + 64];
- dbits = rle_temp_bitmap_1->bm_data;
- rle_temp_bitmap_1->bm_flags = bmp->bm_flags & (~BM_FLAG_RLE);
- for (i=0; i < 64; i++ ) {
- dbits1=(unsigned char *)gr_rle_decode_asm( sbits, dbits );
- sbits += (int)bmp->bm_data[4+i];
- dbits += 64;
- Assert( dbits == dbits1 ); // Get John, bogus rle data!
- }
- }
- void gr_rle_expand_scanline_generic( grs_bitmap * dest, int dx, int dy, ubyte *src, int x1, int x2 )
- {
- int i = 0, j;
- int count;
- ubyte color;
- if ( x2 < x1 ) return;
- count = 0;
- while ( i < x1 ) {
- color = *src++;
- if ( color == RLE_CODE ) return;
- if ( (color & RLE_CODE) == RLE_CODE ) {
- count = color & NOT_RLE_CODE;
- color = *src++;
- } else {
- // unique
- count = 1;
- }
- i += count;
- }
- count = i - x1;
- i = x1;
- // we know have '*count' pixels of 'color'.
-
- if ( x1+count > x2 ) {
- count = x2-x1+1;
- for ( j=0; j<count; j++ )
- gr_bm_pixel( dest, dx++, dy, color );
- return;
- }
- for ( j=0; j<count; j++ )
- gr_bm_pixel( dest, dx++, dy, color );
- i += count;
- while( i <= x2 ) {
- color = *src++;
- if ( color == RLE_CODE ) return;
- if ( (color & RLE_CODE) == RLE_CODE ) {
- count = color & NOT_RLE_CODE;
- color = *src++;
- } else {
- // unique
- count = 1;
- }
- // we know have '*count' pixels of 'color'.
- if ( i+count <= x2 ) {
- for ( j=0; j<count; j++ )
- gr_bm_pixel( dest, dx++, dy, color );
- i += count;
- } else {
- count = x2-i+1;
- for ( j=0; j<count; j++ )
- gr_bm_pixel( dest, dx++, dy, color );
- i += count;
- }
- }
- }
|