RLE.C 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583
  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. * $Source: f:/miner/source/2d/rcs/rle.c $
  15. * $Revision: 1.19 $
  16. * $Author: john $
  17. * $Date: 1995/01/14 19:18:31 $
  18. *
  19. * Routines to do run length encoding/decoding
  20. * on bitmaps.
  21. *
  22. * $Log: rle.c $
  23. * Revision 1.19 1995/01/14 19:18:31 john
  24. * Added assert to check for paged out bitmap.
  25. *
  26. * Revision 1.18 1995/01/14 11:32:07 john
  27. * Added rle_cache_flush function.
  28. *
  29. * Revision 1.17 1994/12/13 10:58:27 john
  30. * Fixed bug with 2 consecutive calls to get_expanded_Texture
  31. * with 2 different bitmaps, returning the same rle texture,
  32. * causing doors to disapper.
  33. *
  34. * Revision 1.16 1994/11/30 00:55:03 mike
  35. * optimization
  36. *
  37. * Revision 1.15 1994/11/24 13:24:44 john
  38. * Made sure that some rep movs had the cld set first.
  39. * Took some unused functions out.
  40. *
  41. * Revision 1.14 1994/11/23 16:03:46 john
  42. * Fixed generic rle'ing to use new bit method.
  43. *
  44. * Revision 1.13 1994/11/23 15:45:51 john
  45. * Changed to a 3 bit rle scheme.
  46. *
  47. * Revision 1.12 1994/11/18 22:50:24 john
  48. * Changed shorts to ints in parameters.
  49. *
  50. * Revision 1.11 1994/11/14 17:06:13 john
  51. * Took out Key_f12.
  52. *
  53. * Revision 1.10 1994/11/14 15:54:09 john
  54. * Put code in for maybe checking bogus rle data.
  55. *
  56. * Revision 1.9 1994/11/14 15:51:58 john
  57. * Added rle_disable_caching variable to prove the stability of my rle caching code
  58. * to any non-believers.
  59. *
  60. * Revision 1.8 1994/11/10 10:31:20 john
  61. * Reduce cache buffers to 16.
  62. *
  63. * Revision 1.7 1994/11/09 19:53:43 john
  64. * Added texture rle caching.
  65. *
  66. * Revision 1.6 1994/11/09 17:41:44 john
  67. * Made a slow version of rle bitblt to svga, modex.
  68. *
  69. * Revision 1.5 1994/11/09 17:07:50 john
  70. * Fixed bug with bitmap that gets bigger with rle.
  71. *
  72. * Revision 1.4 1994/11/09 16:35:17 john
  73. * First version with working RLE bitmaps.
  74. *
  75. * Revision 1.3 1994/10/26 12:54:47 john
  76. * Fixed bug with decode that used rep movsd instead of
  77. * rep stosd.
  78. *
  79. * Revision 1.2 1994/10/06 17:05:25 john
  80. * First version of rle stuff.
  81. *
  82. * Revision 1.1 1994/10/06 16:53:34 john
  83. * Initial revision
  84. *
  85. *
  86. */
  87. #pragma off (unreferenced)
  88. static char rcsid[] = "$Id: rle.c 1.19 1995/01/14 19:18:31 john Exp $";
  89. #pragma on (unreferenced)
  90. #include <stdlib.h>
  91. #include <malloc.h>
  92. #include <stdio.h>
  93. #include <string.h>
  94. #include "mem.h"
  95. #include "mono.h"
  96. #include "gr.h"
  97. #include "grdef.h"
  98. #include "dpmi.h"
  99. #include "error.h"
  100. #include "key.h"
  101. //#define RLE_CODE 0xC0
  102. //#define NOT_RLE_CODE 63
  103. #define RLE_CODE 0xE0
  104. #define NOT_RLE_CODE 31
  105. int gr_rle_decode_asm( ubyte * src, ubyte * dest );
  106. #pragma aux gr_rle_decode_asm parm [esi] [edi] value [edi] modify exact [eax ebx ecx edx esi edi] = \
  107. " cld "\
  108. " xor ecx, ecx "\
  109. " cld "\
  110. " jmp NextByte "\
  111. " "\
  112. "Unique: "\
  113. " mov [edi],al "\
  114. " inc edi "\
  115. " "\
  116. "NextByte: "\
  117. " mov al,[esi] "\
  118. " inc esi "\
  119. " "\
  120. " mov ah, al "\
  121. " and ah, 0xE0 "\
  122. " cmp ah, 0xE0 "\
  123. " jne Unique "\
  124. " "\
  125. " mov cl, al "\
  126. " and cl, 31 "\
  127. " je done "\
  128. " "\
  129. " mov al,[esi] "\
  130. " inc esi "\
  131. " mov ah, al "\
  132. " shr ecx,1 "\
  133. " rep stosw "\
  134. " jnc NextByte "\
  135. " mov [edi],al "\
  136. " inc edi "\
  137. " "\
  138. " jmp NextByte "\
  139. " "\
  140. "done: ";
  141. void gr_rle_decode( ubyte * src, ubyte * dest )
  142. {
  143. gr_rle_decode_asm( src, dest );
  144. }
  145. void rle_stosb(char *dest, int len, int color);
  146. #pragma aux rle_stosb = "cld rep stosb" parm [edi] [ecx] [eax] modify exact [edi ecx];
  147. // Given pointer to start of one scanline of rle data, uncompress it to
  148. // dest, from source pixels x1 to x2.
  149. void gr_rle_expand_scanline_masked( ubyte *dest, ubyte *src, int x1, int x2 )
  150. {
  151. int i = 0;
  152. ubyte count;
  153. ubyte color;
  154. if ( x2 < x1 ) return;
  155. count = 0;
  156. while ( i < x1 ) {
  157. color = *src++;
  158. if ( color == RLE_CODE ) return;
  159. if ( (color & RLE_CODE)==RLE_CODE ) {
  160. count = color & (~RLE_CODE);
  161. color = *src++;
  162. } else {
  163. // unique
  164. count = 1;
  165. }
  166. i += count;
  167. }
  168. count = i - x1;
  169. i = x1;
  170. // we know have '*count' pixels of 'color'.
  171. if ( x1+count > x2 ) {
  172. count = x2-x1+1;
  173. if ( color != 255 ) rle_stosb( dest, count, color );
  174. return;
  175. }
  176. if ( color != 255 ) rle_stosb( dest, count, color );
  177. dest += count;
  178. i += count;
  179. while( i <= x2 ) {
  180. color = *src++;
  181. if ( color == RLE_CODE ) return;
  182. if ( (color & RLE_CODE) == (RLE_CODE) ) {
  183. count = color & (~RLE_CODE);
  184. color = *src++;
  185. } else {
  186. // unique
  187. count = 1;
  188. }
  189. // we know have '*count' pixels of 'color'.
  190. if ( i+count <= x2 ) {
  191. if ( color != 255 )rle_stosb( dest, count, color );
  192. i += count;
  193. dest += count;
  194. } else {
  195. count = x2-i+1;
  196. if ( color != 255 )rle_stosb( dest, count, color );
  197. i += count;
  198. dest += count;
  199. }
  200. }
  201. }
  202. void gr_rle_expand_scanline( ubyte *dest, ubyte *src, int x1, int x2 )
  203. {
  204. int i = 0;
  205. ubyte count;
  206. ubyte color;
  207. if ( x2 < x1 ) return;
  208. count = 0;
  209. while ( i < x1 ) {
  210. color = *src++;
  211. if ( color == RLE_CODE ) return;
  212. if ( (color & RLE_CODE)==RLE_CODE ) {
  213. count = color & (~RLE_CODE);
  214. color = *src++;
  215. } else {
  216. // unique
  217. count = 1;
  218. }
  219. i += count;
  220. }
  221. count = i - x1;
  222. i = x1;
  223. // we know have '*count' pixels of 'color'.
  224. if ( x1+count > x2 ) {
  225. count = x2-x1+1;
  226. rle_stosb( dest, count, color );
  227. return;
  228. }
  229. rle_stosb( dest, count, color );
  230. dest += count;
  231. i += count;
  232. while( i <= x2 ) {
  233. color = *src++;
  234. if ( color == RLE_CODE ) return;
  235. if ( (color & RLE_CODE)==RLE_CODE ) {
  236. count = color & (~RLE_CODE);
  237. color = *src++;
  238. } else {
  239. // unique
  240. count = 1;
  241. }
  242. // we know have '*count' pixels of 'color'.
  243. if ( i+count <= x2 ) {
  244. rle_stosb( dest, count, color );
  245. i += count;
  246. dest += count;
  247. } else {
  248. count = x2-i+1;
  249. rle_stosb( dest, count, color );
  250. i += count;
  251. dest += count;
  252. }
  253. }
  254. }
  255. int gr_rle_encode( int org_size, ubyte *src, ubyte *dest )
  256. {
  257. int i;
  258. ubyte c, oc;
  259. ubyte count;
  260. ubyte *dest_start;
  261. dest_start = dest;
  262. oc = *src++;
  263. count = 1;
  264. for (i=1; i<org_size; i++ ) {
  265. c = *src++;
  266. if ( c!=oc ) {
  267. if ( count ) {
  268. if ( (count==1) && ((oc & RLE_CODE)!=RLE_CODE) ) {
  269. *dest++ = oc;
  270. Assert( oc != RLE_CODE );
  271. } else {
  272. count |= RLE_CODE;
  273. *dest++ = count;
  274. *dest++ = oc;
  275. }
  276. }
  277. oc = c;
  278. count = 0;
  279. }
  280. count++;
  281. if ( count == NOT_RLE_CODE ) {
  282. count |= RLE_CODE;
  283. *dest++=count;
  284. *dest++=oc;
  285. count = 0;
  286. }
  287. }
  288. if (count) {
  289. if ( (count==1) && ((oc & RLE_CODE)!=RLE_CODE) ) {
  290. *dest++ = oc;
  291. Assert( oc != RLE_CODE );
  292. } else {
  293. count |= RLE_CODE;
  294. *dest++ = count;
  295. *dest++ = oc;
  296. }
  297. }
  298. *dest++ = RLE_CODE;
  299. return dest-dest_start;
  300. }
  301. int gr_rle_getsize( int org_size, ubyte *src )
  302. {
  303. int i;
  304. ubyte c, oc;
  305. ubyte count;
  306. int dest_size=0;
  307. oc = *src++;
  308. count = 1;
  309. for (i=1; i<org_size; i++ ) {
  310. c = *src++;
  311. if ( c!=oc ) {
  312. if ( count ) {
  313. if ( (count==1) && ((oc & RLE_CODE)!=RLE_CODE) ) {
  314. dest_size++;
  315. } else {
  316. dest_size++;
  317. dest_size++;
  318. }
  319. }
  320. oc = c;
  321. count = 0;
  322. }
  323. count++;
  324. if ( count == NOT_RLE_CODE ) {
  325. dest_size++;
  326. dest_size++;
  327. count = 0;
  328. }
  329. }
  330. if (count) {
  331. if ( (count==1) && ((oc & RLE_CODE)!=RLE_CODE) ) {
  332. dest_size++;
  333. } else {
  334. dest_size++;
  335. dest_size++;
  336. }
  337. }
  338. dest_size++;
  339. return dest_size;
  340. }
  341. int gr_bitmap_rle_compress( grs_bitmap * bmp )
  342. {
  343. int y, d1, d;
  344. int doffset;
  345. ubyte *rle_data;
  346. rle_data=malloc( (bmp->bm_w+1)* bmp->bm_h );
  347. if (rle_data==NULL) return 0;
  348. doffset = 4 + bmp->bm_h;
  349. for (y=0; y<bmp->bm_h; y++ ) {
  350. d1= gr_rle_getsize( bmp->bm_w, &bmp->bm_data[bmp->bm_w*y] );
  351. if ( ((doffset+d1) > bmp->bm_w*bmp->bm_h) || (d1 > 255 ) ) {
  352. free(rle_data);
  353. return 0;
  354. }
  355. d = gr_rle_encode( bmp->bm_w, &bmp->bm_data[bmp->bm_w*y], &rle_data[doffset] );
  356. Assert( d==d1 );
  357. doffset += d;
  358. rle_data[y+4] = d;
  359. }
  360. //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 );
  361. memcpy( rle_data, &doffset, 4 );
  362. memcpy( bmp->bm_data, rle_data, doffset );
  363. free(rle_data);
  364. bmp->bm_flags |= BM_FLAG_RLE;
  365. return 1;
  366. }
  367. #define MAX_CACHE_BITMAPS 32
  368. typedef struct rle_cache_element {
  369. grs_bitmap * rle_bitmap;
  370. ubyte * rle_data;
  371. grs_bitmap * expanded_bitmap;
  372. int last_used;
  373. } rle_cache_element;
  374. int rle_cache_initialized = 0;
  375. int rle_counter = 0;
  376. int rle_next = 0;
  377. rle_cache_element rle_cache[MAX_CACHE_BITMAPS];
  378. int rle_hits = 0;
  379. int rle_misses = 0;
  380. void rle_cache_close()
  381. {
  382. if (rle_cache_initialized) {
  383. int i;
  384. rle_cache_initialized = 0;
  385. for (i=0; i<MAX_CACHE_BITMAPS; i++ ) {
  386. gr_free_bitmap(rle_cache[i].expanded_bitmap);
  387. }
  388. }
  389. }
  390. void rle_cache_init()
  391. {
  392. int i;
  393. for (i=0; i<MAX_CACHE_BITMAPS; i++ ) {
  394. rle_cache[i].rle_bitmap = NULL;
  395. rle_cache[i].expanded_bitmap = gr_create_bitmap( 64, 64 );
  396. rle_cache[i].last_used = 0;
  397. Assert( rle_cache[i].expanded_bitmap != NULL );
  398. }
  399. rle_cache_initialized = 1;
  400. atexit( rle_cache_close );
  401. }
  402. void rle_cache_flush()
  403. {
  404. int i;
  405. for (i=0; i<MAX_CACHE_BITMAPS; i++ ) {
  406. rle_cache[i].rle_bitmap = NULL;
  407. rle_cache[i].last_used = 0;
  408. }
  409. }
  410. grs_bitmap * rle_expand_texture( grs_bitmap * bmp )
  411. {
  412. int i;
  413. int lowest_count, lc;
  414. int least_recently_used;
  415. if (!rle_cache_initialized) rle_cache_init();
  416. Assert( !(bmp->bm_flags & BM_FLAG_PAGED_OUT) );
  417. lc = rle_counter;
  418. rle_counter++;
  419. if ( rle_counter < lc ) {
  420. for (i=0; i<MAX_CACHE_BITMAPS; i++ ) {
  421. rle_cache[i].rle_bitmap = NULL;
  422. rle_cache[i].last_used = 0;
  423. }
  424. }
  425. // if (((rle_counter % 100)==1) && (rle_hits+rle_misses > 0))
  426. // mprintf(( 0, "RLE-CACHE %d%%, H:%d, M:%d\n", (rle_misses*100)/(rle_hits+rle_misses), rle_hits, rle_misses ));
  427. lowest_count = rle_cache[rle_next].last_used;
  428. least_recently_used = rle_next;
  429. rle_next++;
  430. if ( rle_next >= MAX_CACHE_BITMAPS )
  431. rle_next = 0;
  432. for (i=0; i<MAX_CACHE_BITMAPS; i++ ) {
  433. if (rle_cache[i].rle_bitmap == bmp) {
  434. rle_hits++;
  435. rle_cache[i].last_used = rle_counter;
  436. return rle_cache[i].expanded_bitmap;
  437. }
  438. if ( rle_cache[i].last_used < lowest_count ) {
  439. lowest_count = rle_cache[i].last_used;
  440. least_recently_used = i;
  441. }
  442. }
  443. rle_misses++;
  444. rle_expand_texture_sub( bmp, rle_cache[least_recently_used].expanded_bitmap );
  445. rle_cache[least_recently_used].rle_bitmap = bmp;
  446. rle_cache[least_recently_used].last_used = rle_counter;
  447. return rle_cache[least_recently_used].expanded_bitmap;
  448. }
  449. void rle_expand_texture_sub( grs_bitmap * bmp, grs_bitmap * rle_temp_bitmap_1 )
  450. {
  451. unsigned char * dbits;
  452. unsigned char * sbits;
  453. int i;
  454. unsigned char * dbits1;
  455. sbits = &bmp->bm_data[4 + 64];
  456. dbits = rle_temp_bitmap_1->bm_data;
  457. rle_temp_bitmap_1->bm_flags = bmp->bm_flags & (~BM_FLAG_RLE);
  458. for (i=0; i < 64; i++ ) {
  459. dbits1=(unsigned char *)gr_rle_decode_asm( sbits, dbits );
  460. sbits += (int)bmp->bm_data[4+i];
  461. dbits += 64;
  462. Assert( dbits == dbits1 ); // Get John, bogus rle data!
  463. }
  464. }
  465. void gr_rle_expand_scanline_generic( grs_bitmap * dest, int dx, int dy, ubyte *src, int x1, int x2 )
  466. {
  467. int i = 0, j;
  468. int count;
  469. ubyte color;
  470. if ( x2 < x1 ) return;
  471. count = 0;
  472. while ( i < x1 ) {
  473. color = *src++;
  474. if ( color == RLE_CODE ) return;
  475. if ( (color & RLE_CODE) == RLE_CODE ) {
  476. count = color & NOT_RLE_CODE;
  477. color = *src++;
  478. } else {
  479. // unique
  480. count = 1;
  481. }
  482. i += count;
  483. }
  484. count = i - x1;
  485. i = x1;
  486. // we know have '*count' pixels of 'color'.
  487. if ( x1+count > x2 ) {
  488. count = x2-x1+1;
  489. for ( j=0; j<count; j++ )
  490. gr_bm_pixel( dest, dx++, dy, color );
  491. return;
  492. }
  493. for ( j=0; j<count; j++ )
  494. gr_bm_pixel( dest, dx++, dy, color );
  495. i += count;
  496. while( i <= x2 ) {
  497. color = *src++;
  498. if ( color == RLE_CODE ) return;
  499. if ( (color & RLE_CODE) == RLE_CODE ) {
  500. count = color & NOT_RLE_CODE;
  501. color = *src++;
  502. } else {
  503. // unique
  504. count = 1;
  505. }
  506. // we know have '*count' pixels of 'color'.
  507. if ( i+count <= x2 ) {
  508. for ( j=0; j<count; j++ )
  509. gr_bm_pixel( dest, dx++, dy, color );
  510. i += count;
  511. } else {
  512. count = x2-i+1;
  513. for ( j=0; j<count; j++ )
  514. gr_bm_pixel( dest, dx++, dy, color );
  515. i += count;
  516. }
  517. }
  518. }
  519.