L.C 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611
  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/cfile/rcs/cfile.c $
  15. * $Revision: 1.7 $
  16. * $Author: matt $
  17. * $Date: 1994/04/13 23:44:59 $
  18. *
  19. * Functions for accessing compressed files.
  20. *
  21. * $Log: cfile.c $
  22. * Revision 1.7 1994/04/13 23:44:59 matt
  23. * When file cannot be opened, free up the buffer for that file.
  24. *
  25. * Revision 1.6 1994/02/18 12:38:20 john
  26. * Optimized a bit
  27. *
  28. * Revision 1.5 1994/02/15 18:13:20 john
  29. * Fixed more bugs.
  30. *
  31. * Revision 1.4 1994/02/15 13:27:58 john
  32. * Works ok...
  33. *
  34. * Revision 1.3 1994/02/15 12:51:57 john
  35. * Crappy inbetween version
  36. *
  37. * Revision 1.2 1994/02/14 20:12:29 john
  38. * First version working with new cfile stuff.
  39. *
  40. * Revision 1.1 1994/02/14 15:51:33 john
  41. * Initial revision
  42. *
  43. * Revision 1.1 1994/02/10 15:45:12 john
  44. * Initial revision
  45. *
  46. *
  47. */
  48. #pragma off (unreferenced)
  49. static char rcsid[] = "$Id: cfile.c 1.7 1994/04/13 23:44:59 matt Exp $";
  50. #pragma on (unreferenced)
  51. #include <time.h>
  52. #include <stdio.h>
  53. #include <stdlib.h>
  54. #include <string.h>
  55. #include <ctype.h>
  56. #include <stdarg.h>
  57. #include <conio.h>
  58. #include <dos.h>
  59. #include <fcntl.h>
  60. #include <io.h>
  61. #include <sys\types.h>
  62. #include <sys\stat.h>
  63. #include <errno.h>
  64. #include <string.h>
  65. #include "mem.h"
  66. #include "error.h"
  67. #include "cfile.h"
  68. #define BITS 15
  69. #define MAX_CODE ( ( 1 << BITS ) - 1 )
  70. #define TABLE_SIZE 35023L
  71. #define END_OF_STREAM 256
  72. #define BUMP_CODE 257
  73. #define FLUSH_CODE 258
  74. #define FIRST_CODE 259
  75. #define UNUSED -1
  76. extern FILE * LibraryGetFileInfo( char *filename, int * others_use, int * lib_offset, int * file_size, int * org_size, int * compressed, char * buffer );
  77. int raw_seek( CFILE * cfile, int pos )
  78. {
  79. int i;
  80. cfile->raw_position = pos;
  81. //printf( "Seeking to %d + %d\n", cfile->lib_offset, cfile->raw_position );
  82. i = fseek( cfile->file, cfile->lib_offset+cfile->raw_position, SEEK_SET );
  83. if (i) Int3();
  84. return i;
  85. }
  86. int raw_getc( CFILE * cfile )
  87. {
  88. int c;
  89. // if (cfile->others_use)
  90. // fseek( cfile->file, cfile->lib_offset+cfile->raw_position, SEEK_SET );
  91. if (cfile->raw_position >= cfile->org_size ) return EOF;
  92. c = getc( cfile->file );
  93. if (c!=EOF)
  94. cfile->raw_position++;
  95. // Assert( cfile->raw_position==(ftell(cfile->file)-cfile->lib_offset) );
  96. return c;
  97. }
  98. int raw_putc( int c, CFILE * cfile )
  99. {
  100. int r;
  101. if (cfile->others_use)
  102. fseek( cfile->file, cfile->lib_offset+cfile->raw_position, SEEK_SET );
  103. r = fputc( c, cfile->file );
  104. if (r!=EOF)
  105. cfile->raw_position++;
  106. Assert( cfile->raw_position==(ftell(cfile->file)-cfile->lib_offset) );
  107. return r;
  108. }
  109. void compress_init_dict( CFILE * cfile )
  110. {
  111. unsigned int i;
  112. for ( i = 0 ; i < TABLE_SIZE ; i++ )
  113. cfile->dict[i].code_value = UNUSED;
  114. cfile->next_code = FIRST_CODE;
  115. cfile->current_code_bits = 9;
  116. cfile->next_bump_code = 511;
  117. }
  118. void compress_init_storage( CFILE * cfile )
  119. {
  120. MALLOC( cfile->dict, DICTIONARY, TABLE_SIZE );
  121. MALLOC( cfile->decode_stack, char, TABLE_SIZE );
  122. }
  123. void compress_free_storage( CFILE * cfile )
  124. {
  125. free(cfile->dict);
  126. free(cfile->decode_stack);
  127. }
  128. unsigned int compress_find_child_node( CFILE * cfile, int parent_code, int child_character ) {
  129. unsigned int index;
  130. int offset;
  131. index = ( child_character << ( BITS - 8 ) ) ^ parent_code;
  132. if ( index == 0 )
  133. offset = 1;
  134. else
  135. offset = TABLE_SIZE - index;
  136. for ( ; ; ) {
  137. if ( cfile->dict[ index ].code_value == UNUSED )
  138. return( (unsigned int) index );
  139. if ( cfile->dict[ index ].parent_code == parent_code &&
  140. cfile->dict[ index ].character == (char) child_character )
  141. return( index );
  142. if ( (int) index >= offset )
  143. index -= offset;
  144. else
  145. index += TABLE_SIZE - offset;
  146. }
  147. }
  148. unsigned int compress_decode_string( CFILE * cfile, unsigned int count, unsigned int code ) {
  149. while ( code > 255 ) {
  150. cfile->decode_stack[ count++ ] = cfile->dict[ code ].character;
  151. code = cfile->dict[ code ].parent_code;
  152. }
  153. cfile->decode_stack[ count++ ] = (char) code;
  154. return( count );
  155. }
  156. void compress_output_bit( CFILE *bit_file, int bit ) {
  157. if ( bit )
  158. bit_file->rack |= bit_file->mask;
  159. bit_file->mask >>= 1;
  160. if ( bit_file->mask == 0 ) {
  161. if ( raw_putc(bit_file->rack, bit_file ) != bit_file->rack )
  162. Error( "Error in compress_output_bit" );
  163. bit_file->rack = 0;
  164. bit_file->mask = 0x80;
  165. }
  166. }
  167. void compress_output_bits( CFILE *bit_file, unsigned int code, int count ) {
  168. unsigned int mask;
  169. mask = 1L << ( count - 1 );
  170. while ( mask != 0) {
  171. if ( mask & code )
  172. bit_file->rack |= bit_file->mask;
  173. bit_file->mask >>= 1;
  174. if ( bit_file->mask == 0 ) {
  175. if ( raw_putc(bit_file->rack, bit_file ) != bit_file->rack )
  176. Error( "Error in compress_output_bits" );
  177. bit_file->rack = 0;
  178. bit_file->mask = 0x80;
  179. }
  180. mask >>= 1;
  181. }
  182. }
  183. int compress_input_bit( CFILE *bit_file ) {
  184. int value;
  185. if ( bit_file->mask == 0x80 ) {
  186. bit_file->rack = raw_getc( bit_file );
  187. if ( bit_file->rack == EOF )
  188. return END_OF_STREAM;
  189. //Error( "Fatal error in compress_input_bit!" );
  190. }
  191. value = bit_file->rack & bit_file->mask;
  192. bit_file->mask >>= 1;
  193. if ( bit_file->mask == 0 )
  194. bit_file->mask = 0x80;
  195. return( value ? 1 : 0 );
  196. }
  197. unsigned int compress_input_bits( CFILE *bit_file, int bit_count ) {
  198. unsigned int mask;
  199. unsigned int return_value;
  200. mask = 1L << ( bit_count - 1 );
  201. return_value = 0;
  202. while ( mask != 0) {
  203. if ( bit_file->mask == 0x80 ) {
  204. bit_file->rack = raw_getc( bit_file );
  205. if ( bit_file->rack == EOF )
  206. return END_OF_STREAM;
  207. //Error( "Fatal error in compress_input_bit!" );
  208. }
  209. if ( bit_file->rack & bit_file->mask )
  210. return_value |= mask;
  211. mask >>= 1;
  212. bit_file->mask >>= 1;
  213. if ( bit_file->mask == 0 )
  214. bit_file->mask = 0x80;
  215. }
  216. return( return_value );
  217. }
  218. CFILE * cfopen(char * filename, char * mode ) {
  219. CFILE *cfile;
  220. char signature[3] = "CF";
  221. MALLOC(cfile, CFILE, 1);
  222. cfile->rack = 0;
  223. cfile->mask = 0x80;
  224. MALLOC(cfile->buffer,char,4096*2);
  225. if (strcmpi( mode, "rc")==0 ) {
  226. cfile->file = LibraryGetFileInfo( filename, &cfile->others_use, &cfile->lib_offset, &cfile->compressed_size, &cfile->org_size, &cfile->compressed, cfile->buffer );
  227. if (cfile->file==NULL ) {
  228. free(cfile->buffer);
  229. free(cfile);
  230. return NULL;
  231. }
  232. raw_seek( cfile, 0 );
  233. if (!cfile->compressed) {
  234. cfile->position = 0;
  235. cfile->readonly=1; // Read
  236. return cfile;
  237. }
  238. compress_init_storage(cfile);
  239. compress_init_dict(cfile);
  240. cfile->old_code = UNUSED;
  241. cfile->readonly=1; // Read
  242. cfile->position = 0;
  243. cfile->count = 0;
  244. //printf( "File is %d bytes, orginal is %d bytes\n", cfile->compressed_size, cfile->org_size );
  245. return cfile;
  246. } else if (strcmpi( mode, "wc")==0 ) {
  247. compress_init_storage(cfile);
  248. compress_init_dict(cfile);
  249. cfile->old_code = UNUSED;
  250. cfile->readonly=0; // Write
  251. cfile->compressed=1;
  252. cfile->string_code = -1;
  253. cfile->position = 0;
  254. cfile->count = 0;
  255. cfile->compressed_size = 0;
  256. cfile->file=fopen( filename, "wb" );
  257. setvbuf( cfile->file, cfile->buffer, _IOFBF, 4096*2 );
  258. cfile->others_use = 0;
  259. cfile->lib_offset = 6;
  260. cfile->org_size = 0;
  261. fwrite( &signature, 2, sizeof(char), cfile->file );
  262. fwrite( &cfile->org_size, sizeof(int), 1, cfile->file );
  263. raw_seek( cfile, 0 );
  264. return cfile;
  265. }
  266. cfile->file = fopen( filename, mode );
  267. setvbuf( cfile->file, cfile->buffer, _IOFBF, 4096*2 );
  268. cfile->org_size = filelength( fileno( cfile->file ));
  269. cfile->compressed_size = cfile->org_size;
  270. cfile->readonly=0;
  271. cfile->position = 0;
  272. cfile->raw_position = 0;
  273. cfile->compressed = 0;
  274. cfile->lib_offset = 0;
  275. cfile->others_use = 0;
  276. return cfile;
  277. }
  278. int cfilelength( CFILE *fp )
  279. {
  280. if ( fp->org_size < fp->position )
  281. return fp->position;
  282. else
  283. return fp->org_size;
  284. }
  285. int cfputc( int c, CFILE *fp )
  286. {
  287. int character;
  288. unsigned int index;
  289. if (!fp->compressed)
  290. return raw_putc( c, fp );
  291. character = c & 0xFF;
  292. if (fp->string_code < 0 ) {
  293. fp->string_code = character;
  294. fp->position++;
  295. return character;
  296. }
  297. fp->position++;
  298. index = compress_find_child_node( fp, fp->string_code, character );
  299. if ( fp->dict[ index ].code_value != - 1 )
  300. fp->string_code = fp->dict[ index ].code_value;
  301. else {
  302. fp->dict[ index ].code_value = fp->next_code++;
  303. fp->dict[ index ].parent_code = fp->string_code;
  304. fp->dict[ index ].character = (char) character;
  305. compress_output_bits( fp, (unsigned long)fp->string_code, fp->current_code_bits );
  306. fp->string_code = character;
  307. if ( fp->next_code > MAX_CODE ) {
  308. compress_output_bits( fp,(unsigned long)FLUSH_CODE, fp->current_code_bits );
  309. compress_init_dict(fp);
  310. } else if ( fp->next_code > fp->next_bump_code ) {
  311. compress_output_bits( fp,(unsigned long)BUMP_CODE, fp->current_code_bits );
  312. fp->current_code_bits++;
  313. fp->next_bump_code <<= 1;
  314. fp->next_bump_code |= 1;
  315. }
  316. }
  317. return character;
  318. }
  319. int cfgetc( CFILE * fp ) {
  320. int new_character;
  321. if ( !fp->compressed )
  322. return raw_getc( fp );
  323. if (fp->position >= fp->org_size )
  324. return EOF;
  325. if ( fp->old_code == UNUSED ) {
  326. fp->old_code = (unsigned int) compress_input_bits( fp, fp->current_code_bits );
  327. if ( fp->old_code == END_OF_STREAM ) {
  328. fp->position = fp->org_size;
  329. return EOF;
  330. }
  331. fp->count = 0;
  332. fp->character = fp->old_code;
  333. fp->position++;
  334. return fp->character;
  335. }
  336. if ( fp->count > 0 ) {
  337. new_character = ( unsigned char )fp->decode_stack[ --fp->count ];
  338. fp->position++;
  339. if (fp->count==0 ) {
  340. fp->dict[ fp->next_code ].parent_code = fp->old_code;
  341. fp->dict[ fp->next_code ].character = (char) fp->character;
  342. fp->next_code++;
  343. fp->old_code = fp->new_code;
  344. }
  345. return new_character;
  346. }
  347. for ( ; ; ) {
  348. fp->new_code = (unsigned int) compress_input_bits( fp, fp->current_code_bits );
  349. switch( fp->new_code )
  350. {
  351. case END_OF_STREAM:
  352. fp->position = fp->org_size;
  353. return EOF;
  354. case FLUSH_CODE:
  355. compress_init_dict(fp);
  356. fp->old_code = (unsigned int) compress_input_bits( fp, fp->current_code_bits );
  357. if ( fp->old_code == END_OF_STREAM ) {
  358. fp->position = fp->org_size;
  359. return EOF;
  360. }
  361. fp->count = 0;
  362. fp->character = fp->old_code;
  363. fp->position++;
  364. return fp->character;
  365. case BUMP_CODE:
  366. fp->current_code_bits++;
  367. break;
  368. default:
  369. if ( fp->new_code >= fp->next_code ) {
  370. fp->decode_stack[ 0 ] = (char) fp->character;
  371. fp->count = compress_decode_string( fp, 1, fp->old_code );
  372. } else {
  373. fp->count = compress_decode_string( fp, 0, fp->new_code );
  374. }
  375. fp->character = fp->decode_stack[ fp->count - 1 ];
  376. new_character = ( unsigned char )fp->decode_stack[ --fp->count ];
  377. fp->position++;
  378. if (fp->count==0 ) {
  379. fp->dict[ fp->next_code ].parent_code = fp->old_code;
  380. fp->dict[ fp->next_code ].character = (char) fp->character;
  381. fp->next_code++;
  382. fp->old_code = fp->new_code;
  383. }
  384. return new_character;
  385. }
  386. }
  387. }
  388. size_t cfread( void * buf, size_t elsize, size_t nelem, CFILE * fp )
  389. {
  390. int c, i = 0;
  391. unsigned char * buffer = (unsigned char *)buf;
  392. if ( !fp->compressed ) {
  393. //if ((cfile->raw_position+(elsize*nelem)) > cfile->org_size ) return EOF;
  394. //i = fread( buf, elsize, nelem, fp->file );
  395. //fp->raw_position += i*elsize;
  396. // return i;
  397. //return raw_fread( buf, elsize, nelem, fp->file );
  398. for ( i=0; i<(elsize*nelem); i++ )
  399. {
  400. c = raw_getc( fp );
  401. if ( c==EOF) return i/elsize;
  402. *buffer++ = c;
  403. }
  404. return nelem;
  405. }
  406. //printf( "Reading %d compressed bytes..\n", elsize*nelem );
  407. for ( i=0; i<(elsize*nelem); i++ )
  408. {
  409. c = cfgetc( fp );
  410. if ( c==EOF) return i/elsize;
  411. *buffer++ = c;
  412. }
  413. return nelem;
  414. }
  415. size_t cfwrite( const void * buf, size_t elsize, size_t nelem, CFILE *fp )
  416. {
  417. int c, i = 0;
  418. unsigned char * buffer = (unsigned char *)buf;
  419. if ( !fp->compressed ) {
  420. //return fwrite( buf, elsize, nelem, fp->file );
  421. for ( i=0; i<(elsize*nelem); i++ )
  422. {
  423. c = *buffer++;
  424. if (raw_putc( c, fp )!=c)
  425. return i/elsize;
  426. }
  427. return nelem;
  428. }
  429. for ( i=0; i<(elsize*nelem); i++ )
  430. {
  431. c = *buffer++;
  432. if (cfputc( c, fp )!=c)
  433. return i/elsize;
  434. }
  435. return nelem;
  436. }
  437. int cftell( CFILE *fp ) {
  438. if ( !fp->compressed )
  439. return fp->raw_position;
  440. return fp->position;
  441. }
  442. int cfseek( CFILE *fp, long int offset, int where )
  443. {
  444. int c, goal_position;
  445. if ( !fp->readonly && fp->compressed ) return 3; // Can only seek on readonly files.
  446. switch( where )
  447. {
  448. case SEEK_SET:
  449. goal_position = offset;
  450. break;
  451. case SEEK_CUR:
  452. if (fp->compressed)
  453. goal_position = fp->position+offset;
  454. else
  455. goal_position = fp->raw_position+offset;
  456. break;
  457. case SEEK_END:
  458. goal_position = fp->org_size+offset;
  459. break;
  460. default:
  461. return 1;
  462. }
  463. if ( !fp->compressed ) {
  464. c = fseek( fp->file, fp->lib_offset + goal_position, SEEK_SET );
  465. fp->raw_position = ftell(fp->file)-fp->lib_offset;
  466. return c;
  467. }
  468. if ( (goal_position<0) || (goal_position>=fp->org_size) )
  469. return 1;
  470. if ( goal_position == fp->position )
  471. return 0; // Already there!
  472. if ( goal_position < fp->position ) {
  473. // We need to back track...
  474. compress_init_dict(fp);
  475. fp->old_code = UNUSED;
  476. fp->position = 0;
  477. fp->raw_position = 0;
  478. fp->count = 0;
  479. fp->rack = 0;
  480. fp->mask = 0x80;
  481. raw_seek( fp, 0 );
  482. //fread( &signature, sizeof(unsigned int), 1, fp->file );
  483. //if (signature != 0xCFCF ) return 1;
  484. //fread( &fp->compressed_size, sizeof(int), 1, fp->file );
  485. }
  486. // Read forward to goal_position...
  487. while( fp->position < goal_position )
  488. {
  489. c = cfgetc( fp );
  490. if (c==EOF) return 2;
  491. }
  492. return 0;
  493. }
  494. void cfclose( CFILE * fp ) {
  495. char signature[3] = "CF";
  496. Assert( fp!=NULL );
  497. if (!fp->compressed) {
  498. if ( !fp->others_use )
  499. fclose(fp->file);
  500. if (fp->buffer) free(fp->buffer);
  501. free(fp);
  502. return;
  503. }
  504. if (!fp->readonly) {
  505. compress_output_bits( fp, (unsigned long) fp->string_code, fp->current_code_bits );
  506. compress_output_bits( fp, (unsigned long) END_OF_STREAM, fp->current_code_bits);
  507. if ( fp->mask != 0x80 ) {
  508. if ( putc( fp->rack, fp->file ) != fp->rack )
  509. Error( "Fatal error in CloseBitFile" );
  510. }
  511. fp->org_size = fp->position;
  512. fseek( fp->file, 0L, SEEK_SET );
  513. fwrite( signature, 2, sizeof(char), fp->file );
  514. fwrite( &fp->org_size, 1, sizeof(int), fp->file );
  515. //printf( "File wrote is %d bytes originally\n", fp->org_size );
  516. }
  517. if (!fp->others_use )
  518. fclose(fp->file);
  519. compress_free_storage(fp);
  520. if (fp->buffer) free(fp->buffer);
  521. free(fp);
  522. }
  523.