JAMPAK.C 25 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114
  1. /* Catacomb Armageddon Source Code
  2. * Copyright (C) 1993-2014 Flat Rock Software
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License along
  15. * with this program; if not, write to the Free Software Foundation, Inc.,
  16. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  17. */
  18. #pragma inline
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #include <ctype.h>
  23. #include <alloc.h>
  24. #include <fcntl.h>
  25. #include <dos.h>
  26. #include <io.h>
  27. #include "def.h"
  28. #include "gelib.h"
  29. #include "jampak.h"
  30. //=========================================================================
  31. //
  32. //
  33. // LOCAL DEFINATIONS
  34. //
  35. //
  36. //=========================================================================
  37. //#define COMPRESSION_CODE // Comment define in for COMPRESS routines
  38. //=========================================================================
  39. //
  40. //
  41. // LOCAL VARIABLES
  42. //
  43. //
  44. //=========================================================================
  45. unsigned char far LZW_ring_buffer[LZW_N + LZW_F - 1];
  46. // ring buffer of size LZW_N, with extra LZW_F-1 bytes to facilitate
  47. // string comparison
  48. #ifdef COMPRESSION_CODE
  49. int LZW_match_pos,
  50. LZW_match_len,
  51. // MAtchLength of longest match. These are set by the InsertNode()
  52. // procedure.
  53. // left & right children & parents -- These constitute binary search trees. */
  54. far LZW_left_child[LZW_N + 1],
  55. far LZW_right_child[LZW_N + 257],
  56. far LZW_parent[LZW_N + 1];
  57. #endif
  58. memptr segptr;
  59. BufferedIO lzwBIO;
  60. //=========================================================================
  61. //
  62. //
  63. // COMPRESSION SUPPORT ROUTINES
  64. //
  65. //
  66. //=========================================================================
  67. #ifdef COMPRESSION_CODE
  68. //---------------------------------------------------------------------------
  69. // InitLZWTree()
  70. //---------------------------------------------------------------------------
  71. void InitLZWTree(void) /* initialize trees */
  72. {
  73. int i;
  74. /* For i = 0 to LZW_N - 1, LZW_right_child[i] and LZW_left_child[i] will be the right and
  75. left children of node i. These nodes need not be initialized.
  76. Also, LZW_parent[i] is the parent of node i. These are initialized to
  77. LZW_NIL (= LZW_N), which stands for 'not used.'
  78. For i = 0 to 255, LZW_right_child[LZW_N + i + 1] is the root of the tree
  79. for strings that begin with character i. These are initialized
  80. to LZW_NIL. Note there are 256 trees. */
  81. for (i = LZW_N + 1; i <= LZW_N + 256; i++)
  82. LZW_right_child[i] = LZW_NIL;
  83. for (i = 0; i < LZW_N; i++)
  84. LZW_parent[i] = LZW_NIL;
  85. }
  86. //---------------------------------------------------------------------------
  87. // InsertLZWNode()
  88. //---------------------------------------------------------------------------
  89. void InsertLZWNode(unsigned long r)
  90. /* Inserts string of length LZW_F, LZW_ring_buffer[r..r+LZW_F-1], into one of the
  91. trees (LZW_ring_buffer[r]'th tree) and returns the longest-match position
  92. and length via the global variables LZW_match_pos and LZW_match_len.
  93. If LZW_match_len = LZW_F, then removes the old node in favor of the new
  94. one, because the old one will be deleted sooner.
  95. Note r plays double role, as tree node and position in buffer. */
  96. {
  97. int i, p, cmp;
  98. unsigned char *key;
  99. cmp = 1;
  100. key = &LZW_ring_buffer[r];
  101. p = LZW_N + 1 + key[0];
  102. LZW_right_child[r] = LZW_left_child[r] = LZW_NIL;
  103. LZW_match_len = 0;
  104. for ( ; ; )
  105. {
  106. if (cmp >= 0)
  107. {
  108. if (LZW_right_child[p] != LZW_NIL)
  109. p = LZW_right_child[p];
  110. else
  111. {
  112. LZW_right_child[p] = r;
  113. LZW_parent[r] = p;
  114. return;
  115. }
  116. }
  117. else
  118. {
  119. if (LZW_left_child[p] != LZW_NIL)
  120. p = LZW_left_child[p];
  121. else
  122. {
  123. LZW_left_child[p] = r;
  124. LZW_parent[r] = p;
  125. return;
  126. }
  127. }
  128. for (i = 1; i < LZW_F; i++)
  129. if ((cmp = key[i] - LZW_ring_buffer[p + i]) != 0)
  130. break;
  131. if (i > LZW_match_len)
  132. {
  133. LZW_match_pos = p;
  134. if ((LZW_match_len = i) >= LZW_F)
  135. break;
  136. }
  137. }
  138. LZW_parent[r] = LZW_parent[p];
  139. LZW_left_child[r] = LZW_left_child[p];
  140. LZW_right_child[r] = LZW_right_child[p];
  141. LZW_parent[LZW_left_child[p]] = r;
  142. LZW_parent[LZW_right_child[p]] = r;
  143. if (LZW_right_child[LZW_parent[p]] == p)
  144. LZW_right_child[LZW_parent[p]] = r;
  145. else
  146. LZW_left_child[LZW_parent[p]] = r;
  147. LZW_parent[p] = LZW_NIL; /* remove p */
  148. }
  149. //---------------------------------------------------------------------------
  150. // DeleteLZWNode()
  151. //---------------------------------------------------------------------------
  152. void DeleteLZWNode(unsigned long p) /* deletes node p from tree */
  153. {
  154. int q;
  155. if (LZW_parent[p] == LZW_NIL)
  156. return; /* not in tree */
  157. if (LZW_right_child[p] == LZW_NIL)
  158. q = LZW_left_child[p];
  159. else
  160. if (LZW_left_child[p] == LZW_NIL)
  161. q = LZW_right_child[p];
  162. else
  163. {
  164. q = LZW_left_child[p];
  165. if (LZW_right_child[q] != LZW_NIL)
  166. {
  167. do {
  168. q = LZW_right_child[q];
  169. } while (LZW_right_child[q] != LZW_NIL);
  170. LZW_right_child[LZW_parent[q]] = LZW_left_child[q];
  171. LZW_parent[LZW_left_child[q]] = LZW_parent[q];
  172. LZW_left_child[q] = LZW_left_child[p];
  173. LZW_parent[LZW_left_child[p]] = q;
  174. }
  175. LZW_right_child[q] = LZW_right_child[p];
  176. LZW_parent[LZW_right_child[p]] = q;
  177. }
  178. LZW_parent[q] = LZW_parent[p];
  179. if (LZW_right_child[LZW_parent[p]] == p)
  180. LZW_right_child[LZW_parent[p]] = q;
  181. else
  182. LZW_left_child[LZW_parent[p]] = q;
  183. LZW_parent[p] = LZW_NIL;
  184. }
  185. #endif
  186. //=========================================================================
  187. //
  188. //
  189. // GENERAL FILE to FILE compression routines
  190. //
  191. // * Mainly for example usage of PTR/PTR (de)compression routines.
  192. //
  193. //
  194. //=========================================================================
  195. //////////////////////////////////////////////////////////////////////
  196. //
  197. // CompressFILEtoFILE() -- Compresses one file stream to another file stream
  198. //
  199. #ifdef COMPRESSION_CODE
  200. unsigned long CompressFILEtoFILE(FILE *infile, FILE *outfile,unsigned long DataLength)
  201. {
  202. unsigned long returnval;
  203. fwrite(COMP,4,1,outfile);
  204. fwrite((char *)&DataLength,4,1,outfile);
  205. returnval = 8+lzwCompress(infile,outfile,DataLength,(SRC_FFILE|DEST_FFILE));
  206. return(returnval);
  207. }
  208. #endif
  209. #if 0
  210. /////////////////////////////////////////////////////////////////////////////
  211. //
  212. // DecompressFILEtoFILE()
  213. //
  214. void DecompressFILEtoFILE(FILE *infile, FILE *outfile)
  215. {
  216. unsigned char Buffer[8];
  217. unsigned long DataLength;
  218. fread(Buffer,1,4,infile);
  219. if (strncmp(Buffer,COMP,4))
  220. {
  221. printf("\nNot a JAM Compressed File!\n");
  222. return;
  223. }
  224. fread((void *)&DataLength,1,4,infile);
  225. lzwDecompress(infile,outfile,DataLength,(SRC_FFILE|DEST_FFILE));
  226. }
  227. #endif
  228. //==========================================================================
  229. //
  230. //
  231. // WRITE/READ PTR ROUTINES
  232. //
  233. //
  234. //==========================================================================
  235. //---------------------------------------------------------------------------
  236. // WritePtr() -- Outputs data to a particular ptr type
  237. //
  238. // PtrType MUST be of type DEST_TYPE.
  239. //
  240. // NOTE : For PtrTypes DEST_MEM a ZERO (0) is always returned.
  241. //
  242. //---------------------------------------------------------------------------
  243. int WritePtr(long outfile, unsigned char data, unsigned PtrType)
  244. {
  245. int returnval = 0;
  246. switch (PtrType & DEST_TYPES)
  247. {
  248. case DEST_FILE:
  249. write(*(int far *)outfile,(char *)&data,1);
  250. break;
  251. case DEST_FFILE:
  252. returnval = putc(data, *(FILE **)outfile);
  253. break;
  254. case DEST_MEM:
  255. // *(*(char far **)outfile++) = data; // Do NOT delete
  256. *((char far *)*(char far **)outfile)++ = data;
  257. break;
  258. default:
  259. TrashProg("WritePtr() : Unknown DEST_PTR type");
  260. break;
  261. }
  262. return(returnval);
  263. }
  264. //---------------------------------------------------------------------------
  265. // ReadPtr() -- Reads data from a particular ptr type
  266. //
  267. // PtrType MUST be of type SRC_TYPE.
  268. //
  269. // RETURNS :
  270. // The char read in or EOF for SRC_FFILE type of reads.
  271. //
  272. //
  273. //---------------------------------------------------------------------------
  274. int ReadPtr(long infile, unsigned PtrType)
  275. {
  276. int returnval = 0;
  277. switch (PtrType & SRC_TYPES)
  278. {
  279. case SRC_FILE:
  280. read(*(int far *)infile,(char *)&returnval,1);
  281. break;
  282. case SRC_FFILE:
  283. // JIM - JTR - is the following correct? "fgetc()" uses a near pointer.
  284. //
  285. returnval = fgetc((FILE far *)*(FILE far **)infile);
  286. break;
  287. case SRC_BFILE:
  288. returnval = bio_readch((BufferedIO *)*(void far **)infile);
  289. break;
  290. case SRC_MEM:
  291. returnval = (char)*(*(char far **)infile++);
  292. // returnval = *((char far *)*(char far **)infile)++; // DO NOT DELETE!
  293. break;
  294. default:
  295. TrashProg("ReadPtr() : Unknown SRC_PTR type");
  296. break;
  297. }
  298. return(returnval);
  299. }
  300. //=========================================================================
  301. //
  302. //
  303. // COMPRESSION & DECOMPRESSION ROUTINES
  304. //
  305. //
  306. //=========================================================================
  307. //--------------------------------------------------------------------------
  308. //
  309. // lzwCompress() - Compresses data from an input ptr to a dest ptr
  310. //
  311. // PARAMS:
  312. // infile - Pointer at the BEGINNING of the data to compress
  313. // outfile - Pointer to the destination (no header).
  314. // DataLength - Number of bytes to compress.
  315. // PtrTypes - Type of pointers being used (SRC_FILE,DEST_FILE,SRC_MEM etc).
  316. //
  317. // RETURNS:
  318. // Length of compressed data.
  319. //
  320. // COMPTYPE : ct_LZW
  321. //
  322. // NOTES : Does not write ANY header information!
  323. //
  324. #ifdef COMPRESSION_CODE
  325. unsigned long lzwCompress(void far *infile, void far *outfile,unsigned long DataLength,unsigned PtrTypes)
  326. {
  327. short i;
  328. short c, len, r, s, last_LZW_match_len, code_buf_ptr;
  329. unsigned char far code_buf[17], mask;
  330. unsigned long complen = 0;
  331. // initialize trees
  332. InitLZWTree();
  333. code_buf[0] = 0;
  334. //
  335. // code_buf[1..16] saves eight units of code, and code_buf[0] works
  336. // as eight flags, "1" representing that the unit is an unencoded
  337. // letter (1 byte), "0" a position-and-length pair (2 bytes). Thus,
  338. // eight units require at most 16 bytes of code.
  339. //
  340. code_buf_ptr = mask = 1;
  341. s = 0;
  342. r = LZW_N - LZW_F;
  343. // Clear the buffer with any character that will appear often.
  344. //
  345. for (i = s; i < r; i++)
  346. LZW_ring_buffer[i] = ' ';
  347. // Read LZW_F bytes into the last LZW_F bytes of the buffer
  348. //
  349. for (len = 0; (len < LZW_F) && DataLength; len++)
  350. {
  351. c = ReadPtr((long)&infile,PtrTypes);
  352. DataLength--;
  353. // text of size zero
  354. LZW_ring_buffer[r + len] = c;
  355. }
  356. if (!(len && DataLength))
  357. return(0);
  358. //
  359. // Insert the LZW_F strings, each of which begins with one or more
  360. // 'space' characters. Note the order in which these strings
  361. // are inserted. This way, degenerate trees will be less likely
  362. // to occur.
  363. //
  364. for (i = 1; i <= LZW_F; i++)
  365. InsertLZWNode(r - i);
  366. //
  367. // Finally, insert the whole string just read. The global
  368. // variables LZW_match_len and LZW_match_pos are set. */
  369. //
  370. InsertLZWNode(r);
  371. do {
  372. // LZW_match_len may be spuriously long near the end of text.
  373. //
  374. if (LZW_match_len > len)
  375. LZW_match_len = len;
  376. if (LZW_match_len <= LZW_THRESHOLD)
  377. {
  378. // Not long enough match. Send one byte.
  379. //
  380. LZW_match_len = 1;
  381. // 'send one byte' flag
  382. //
  383. code_buf[0] |= mask;
  384. // Send uncoded.
  385. //
  386. code_buf[code_buf_ptr++] = LZW_ring_buffer[r];
  387. }
  388. else
  389. {
  390. code_buf[code_buf_ptr++] = (unsigned char) LZW_match_pos;
  391. code_buf[code_buf_ptr++] = (unsigned char) (((LZW_match_pos >> 4) & 0xf0) | (LZW_match_len - (LZW_THRESHOLD + 1)));
  392. // Send position and length pair.
  393. // Note LZW_match_len > LZW_THRESHOLD.
  394. }
  395. if ((mask <<= 1) == 0)
  396. {
  397. // Shift mask left one bit.
  398. // Send at most 8 units of data
  399. for (i = 0; i < code_buf_ptr; i++)
  400. WritePtr((long)&outfile,code_buf[i],PtrTypes);
  401. complen += code_buf_ptr;
  402. code_buf[0] = 0;
  403. code_buf_ptr = mask = 1;
  404. }
  405. last_LZW_match_len = LZW_match_len;
  406. for (i = 0; i < last_LZW_match_len && DataLength; i++)
  407. {
  408. c = ReadPtr((long)&infile,PtrTypes);
  409. DataLength--;
  410. DeleteLZWNode(s); // Delete old strings and
  411. LZW_ring_buffer[s] = c; // read new bytes
  412. // If the position is near the end of buffer, extend the
  413. // buffer to make string comparison easier.
  414. if (s < LZW_F - 1)
  415. LZW_ring_buffer[s + LZW_N] = c;
  416. // Since this is a ring buffer, inc the position modulo LZW_N.
  417. //
  418. s = (s + 1) & (LZW_N - 1);
  419. r = (r + 1) & (LZW_N - 1);
  420. // Register the string in LZW_ring_buffer[r..r+LZW_F-1]
  421. //
  422. InsertLZWNode(r);
  423. }
  424. while (i++ < last_LZW_match_len)
  425. {
  426. // After the end of text,
  427. DeleteLZWNode(s); // no need to read, but
  428. s = (s + 1) & (LZW_N - 1);
  429. r = (r + 1) & (LZW_N - 1);
  430. if (--len)
  431. InsertLZWNode(r); // buffer may not be empty.
  432. }
  433. } while (len > 0); // until length of string to be processed is zero
  434. if (code_buf_ptr > 1)
  435. {
  436. // Send remaining code.
  437. //
  438. for (i = 0; i < code_buf_ptr; i++)
  439. WritePtr((long)&outfile,code_buf[i],PtrTypes);
  440. complen += code_buf_ptr;
  441. }
  442. return(complen);
  443. }
  444. #endif
  445. //--------------------------------------------------------------------------
  446. //
  447. // lzwDecompress() - Compresses data from an input ptr to a dest ptr
  448. //
  449. // PARAMS:
  450. // infile - Pointer at the BEGINNING of the compressed data (no header!)
  451. // outfile - Pointer to the destination.
  452. // DataLength - Length of compressed data.
  453. // PtrTypes - Type of pointers being used (SRC_FILE,DEST_FILE,SRC_MEM etc).
  454. //
  455. // RETURNS:
  456. // Length of compressed data.
  457. //
  458. // COMPTYPE : ct_LZW
  459. //
  460. // NOTES : Does not write ANY header information!
  461. //
  462. void far lzwDecompress(void far *infile, void far *outfile,unsigned long DataLength,unsigned PtrTypes)
  463. {
  464. int i, j, k, r, c;
  465. unsigned int flags;
  466. for (i = 0; i < LZW_N - LZW_F; i++)
  467. LZW_ring_buffer[i] = ' ';
  468. r = LZW_N - LZW_F;
  469. flags = 0;
  470. for ( ; ; )
  471. {
  472. if (((flags >>= 1) & 256) == 0)
  473. {
  474. c = ReadPtr((long)&infile,PtrTypes);
  475. if (!DataLength--)
  476. return;
  477. flags = c | 0xff00; // uses higher byte cleverly to count 8
  478. }
  479. if (flags & 1)
  480. {
  481. c = ReadPtr((long)&infile,PtrTypes); // Could test for EOF iff FFILE type
  482. if (!DataLength--)
  483. return;
  484. WritePtr((long)&outfile,c,PtrTypes);
  485. LZW_ring_buffer[r++] = c;
  486. r &= (LZW_N - 1);
  487. }
  488. else
  489. {
  490. i = ReadPtr((long)&infile,PtrTypes);
  491. if (!DataLength--)
  492. return;
  493. j = ReadPtr((long)&infile,PtrTypes);
  494. if (!DataLength--)
  495. return;
  496. i |= ((j & 0xf0) << 4);
  497. j = (j & 0x0f) + LZW_THRESHOLD;
  498. for (k = 0; k <= j; k++)
  499. {
  500. c = LZW_ring_buffer[(i + k) & (LZW_N - 1)];
  501. WritePtr((long)&outfile,c,PtrTypes);
  502. LZW_ring_buffer[r++] = c;
  503. r &= (LZW_N - 1);
  504. }
  505. }
  506. }
  507. }
  508. #if 0
  509. //=========================================================================
  510. //
  511. //
  512. // BUFFERED I/O ROUTINES
  513. //
  514. //
  515. //=========================================================================
  516. //--------------------------------------------------------------------------
  517. // InitBufferedIO()
  518. //--------------------------------------------------------------------------
  519. memptr InitBufferedIO(int handle, BufferedIO *bio)
  520. {
  521. bio->handle = handle;
  522. bio->offset = BIO_BUFFER_LEN;
  523. bio->status = 0;
  524. MM_GetPtr(&bio->buffer,BIO_BUFFER_LEN);
  525. return(bio->buffer);
  526. }
  527. //--------------------------------------------------------------------------
  528. // FreeBufferedIO()
  529. //--------------------------------------------------------------------------
  530. void FreeBufferedIO(BufferedIO *bio)
  531. {
  532. if (bio->buffer)
  533. MM_FreePtr(&bio->buffer);
  534. }
  535. //--------------------------------------------------------------------------
  536. // bio_readch()
  537. //--------------------------------------------------------------------------
  538. byte bio_readch(BufferedIO *bio)
  539. {
  540. byte far *buffer;
  541. if (bio->offset == BIO_BUFFER_LEN)
  542. {
  543. bio->offset = 0;
  544. bio_fillbuffer(bio);
  545. }
  546. buffer = MK_FP(bio->buffer,bio->offset++);
  547. return(*buffer);
  548. }
  549. //--------------------------------------------------------------------------
  550. // bio_fillbuffer()
  551. //
  552. // BUGS (Not really bugs... More like RULES!)
  553. //
  554. // 1) This code assumes BIO_BUFFER_LEN is no smaller than
  555. // NEAR_BUFFER_LEN!!
  556. //
  557. // 2) BufferedIO.status should be altered by this code to report
  558. // read errors, end of file, etc... If you know how big the file
  559. // is you're reading, determining EOF should be no problem.
  560. //
  561. //--------------------------------------------------------------------------
  562. void bio_fillbuffer(BufferedIO *bio)
  563. {
  564. #define NEAR_BUFFER_LEN (64)
  565. byte near_buffer[NEAR_BUFFER_LEN];
  566. short bio_length,bytes_read,bytes_requested;
  567. bytes_read = 0;
  568. bio_length = BIO_BUFFER_LEN;
  569. while (bio_length)
  570. {
  571. if (bio_length > NEAR_BUFFER_LEN-1)
  572. bytes_requested = NEAR_BUFFER_LEN;
  573. else
  574. bytes_requested = bio_length;
  575. read(bio->handle,near_buffer,bytes_requested);
  576. _fmemcpy(MK_FP(bio->buffer,bytes_read),near_buffer,bytes_requested);
  577. bio_length -= bytes_requested;
  578. bytes_read += bytes_requested;
  579. }
  580. }
  581. #endif
  582. //=========================================================================
  583. //
  584. //
  585. // GENERAL LOAD ROUTINES
  586. //
  587. //
  588. //=========================================================================
  589. //--------------------------------------------------------------------------
  590. // BLoad()
  591. //--------------------------------------------------------------------------
  592. unsigned long BLoad(char *SourceFile, memptr *DstPtr)
  593. {
  594. int handle;
  595. memptr SrcPtr;
  596. longword i, j, k, r, c;
  597. word flags;
  598. byte Buffer[8];
  599. longword DstLen, SrcLen;
  600. boolean comp;
  601. if ((handle = open(SourceFile, O_RDONLY|O_BINARY)) == -1)
  602. return(0);
  603. // Look for 'COMP' header
  604. //
  605. read(handle,Buffer,4);
  606. comp = !strncmp(Buffer,COMP,4);
  607. // Get source and destination length.
  608. //
  609. if (comp)
  610. {
  611. SrcLen = Verify(SourceFile);
  612. read(handle,(void *)&DstLen,4);
  613. MM_GetPtr(DstPtr,DstLen);
  614. if (!*DstPtr)
  615. return(0);
  616. }
  617. else
  618. DstLen = Verify(SourceFile);
  619. // LZW decompress OR simply load the file.
  620. //
  621. if (comp)
  622. {
  623. if (MM_TotalFree() < SrcLen)
  624. {
  625. if (!InitBufferedIO(handle,&lzwBIO))
  626. TrashProg("No memory for buffered I/O.");
  627. lzwDecompress(&lzwBIO,MK_FP(*DstPtr,0),SrcLen,(SRC_BFILE|DEST_MEM));
  628. FreeBufferedIO(&lzwBIO);
  629. }
  630. else
  631. {
  632. CA_LoadFile(SourceFile,&SrcPtr);
  633. lzwDecompress(MK_FP(SrcPtr,8),MK_FP(*DstPtr,0),SrcLen,(SRC_MEM|DEST_MEM));
  634. MM_FreePtr(&SrcPtr);
  635. }
  636. }
  637. else
  638. CA_LoadFile(SourceFile,DstPtr);
  639. close(handle);
  640. return(DstLen);
  641. }
  642. ////////////////////////////////////////////////////////////////////////////
  643. //
  644. // LoadLIBShape()
  645. //
  646. int LoadLIBShape(char *SLIB_Filename, char *Filename,struct Shape *SHP)
  647. {
  648. #define CHUNK(Name) (*ptr == *Name) && \
  649. (*(ptr+1) == *(Name+1)) && \
  650. (*(ptr+2) == *(Name+2)) && \
  651. (*(ptr+3) == *(Name+3))
  652. int RT_CODE;
  653. FILE *fp;
  654. char CHUNK[5];
  655. char far *ptr;
  656. memptr IFFfile = NULL;
  657. unsigned long FileLen, size, ChunkLen;
  658. int loop;
  659. RT_CODE = 1;
  660. // Decompress to ram and return ptr to data and return len of data in
  661. // passed variable...
  662. if (!LoadLIBFile(SLIB_Filename,Filename,&IFFfile))
  663. TrashProg("Error Loading Compressed lib shape!");
  664. // Evaluate the file
  665. //
  666. ptr = MK_FP(IFFfile,0);
  667. if (!CHUNK("FORM"))
  668. goto EXIT_FUNC;
  669. ptr += 4;
  670. FileLen = *(long far *)ptr;
  671. SwapLong((long far *)&FileLen);
  672. ptr += 4;
  673. if (!CHUNK("ILBM"))
  674. goto EXIT_FUNC;
  675. ptr += 4;
  676. FileLen += 4;
  677. while (FileLen)
  678. {
  679. ChunkLen = *(long far *)(ptr+4);
  680. SwapLong((long far *)&ChunkLen);
  681. ChunkLen = (ChunkLen+1) & 0xFFFFFFFE;
  682. if (CHUNK("BMHD"))
  683. {
  684. ptr += 8;
  685. SHP->bmHdr.w = ((struct BitMapHeader far *)ptr)->w;
  686. SHP->bmHdr.h = ((struct BitMapHeader far *)ptr)->h;
  687. SHP->bmHdr.x = ((struct BitMapHeader far *)ptr)->x;
  688. SHP->bmHdr.y = ((struct BitMapHeader far *)ptr)->y;
  689. SHP->bmHdr.d = ((struct BitMapHeader far *)ptr)->d;
  690. SHP->bmHdr.trans = ((struct BitMapHeader far *)ptr)->trans;
  691. SHP->bmHdr.comp = ((struct BitMapHeader far *)ptr)->comp;
  692. SHP->bmHdr.pad = ((struct BitMapHeader far *)ptr)->pad;
  693. SwapWord(&SHP->bmHdr.w);
  694. SwapWord(&SHP->bmHdr.h);
  695. SwapWord(&SHP->bmHdr.x);
  696. SwapWord(&SHP->bmHdr.y);
  697. ptr += ChunkLen;
  698. }
  699. else
  700. if (CHUNK("BODY"))
  701. {
  702. ptr += 4;
  703. size = *((long far *)ptr);
  704. ptr += 4;
  705. SwapLong((long far *)&size);
  706. SHP->BPR = (SHP->bmHdr.w+7) >> 3;
  707. MM_GetPtr(&SHP->Data,size);
  708. if (!SHP->Data)
  709. goto EXIT_FUNC;
  710. movedata(FP_SEG(ptr),FP_OFF(ptr),FP_SEG(SHP->Data),0,size);
  711. ptr += ChunkLen;
  712. break;
  713. }
  714. else
  715. ptr += ChunkLen+8;
  716. FileLen -= ChunkLen+8;
  717. }
  718. RT_CODE = 0;
  719. EXIT_FUNC:;
  720. if (IFFfile)
  721. {
  722. // segptr = (memptr)FP_SEG(IFFfile);
  723. MM_FreePtr(&IFFfile);
  724. }
  725. return (RT_CODE);
  726. }
  727. //----------------------------------------------------------------------------
  728. // LoadLIBFile() -- Copies a file from an existing archive to dos.
  729. //
  730. // PARAMETERS :
  731. //
  732. // LibName - Name of lib file created with SoftLib V1.0
  733. //
  734. // FileName - Name of file to load from lib file.
  735. //
  736. // MemPtr - (IF !NULL) - Pointer to memory to load into ..
  737. // (IF NULL) - Routine allocates necessary memory and
  738. // returns a MEM(SEG) pointer to memory allocated.
  739. //
  740. // RETURN :
  741. //
  742. // (IF !NULL) - A pointer to the loaded data.
  743. // (IF NULL) - Error!
  744. //
  745. //----------------------------------------------------------------------------
  746. memptr LoadLIBFile(char *LibName,char *FileName,memptr *MemPtr)
  747. {
  748. int handle;
  749. unsigned long header;
  750. struct ChunkHeader Header;
  751. unsigned long ChunkLen;
  752. short x;
  753. struct FileEntryHdr FileEntry; // Storage for file once found
  754. struct FileEntryHdr FileEntryHeader; // Header used durring searching
  755. struct SoftLibHdr LibraryHeader; // Library header - Version Checking
  756. boolean FileFound = false;
  757. unsigned long id_slib = ID_SLIB;
  758. unsigned long id_chunk = ID_CHUNK;
  759. //
  760. // OPEN SOFTLIB FILE
  761. //
  762. if ((handle = open(LibName,O_RDONLY | O_BINARY, S_IREAD)) == -1)
  763. return(NULL);
  764. //
  765. // VERIFY it is a SOFTLIB (SLIB) file
  766. //
  767. if (read(handle,&header,4) == -1)
  768. {
  769. close(handle);
  770. return(NULL);
  771. }
  772. if (header != id_slib)
  773. {
  774. close(handle);
  775. return(NULL);
  776. }
  777. //
  778. // CHECK LIBRARY HEADER VERSION NUMBER
  779. //
  780. if (read(handle, &LibraryHeader,sizeof(struct SoftLibHdr)) == -1)
  781. TrashProg("read error in LoadSLIBFile()\n%c",7);
  782. if (LibraryHeader.Version > SOFTLIB_VER)
  783. TrashProg("Unsupported file ver %d",LibraryHeader.Version);
  784. //
  785. // MANAGE FILE ENTRY HEADERS...
  786. //
  787. for (x = 1;x<=LibraryHeader.FileCount;x++)
  788. {
  789. if (read(handle, &FileEntryHeader,sizeof(struct FileEntryHdr)) == -1)
  790. {
  791. close(handle);
  792. return(NULL);
  793. }
  794. if (!stricmp(FileEntryHeader.FileName,FileName))
  795. {
  796. FileEntry = FileEntryHeader;
  797. FileFound = true;
  798. }
  799. }
  800. //
  801. // IF FILE HAS BEEN FOUND THEN SEEK TO POSITION AND EXTRACT
  802. // ELSE RETURN WITH ERROR CODE...
  803. //
  804. if (FileFound)
  805. {
  806. if (lseek(handle,FileEntry.Offset,SEEK_CUR) == -1)
  807. {
  808. close(handle);
  809. return(NULL);
  810. }
  811. //
  812. // READ CHUNK HEADER - Verify we are at the beginning of a chunk..
  813. //
  814. if (read(handle,(char *)&Header,sizeof(struct ChunkHeader)) == -1)
  815. TrashProg("LIB File - Unable to read Header!");
  816. if (Header.HeaderID != id_chunk)
  817. TrashProg("LIB File - BAD HeaderID!");
  818. //
  819. // Allocate memory if Necessary...
  820. //
  821. if (!*MemPtr)
  822. MM_GetPtr(MemPtr,FileEntry.OrginalLength);
  823. //
  824. // Calculate the length of the data (without the chunk header).
  825. //
  826. ChunkLen = FileEntry.ChunkLen - sizeof(struct ChunkHeader);
  827. //
  828. // Extract Data from file
  829. //
  830. switch (Header.Compression)
  831. {
  832. case ct_LZW:
  833. if (!InitBufferedIO(handle,&lzwBIO))
  834. TrashProg("No memory for buffered I/O.");
  835. lzwDecompress(&lzwBIO,MK_FP(*MemPtr,0),ChunkLen,(SRC_BFILE|DEST_MEM));
  836. FreeBufferedIO(&lzwBIO);
  837. break;
  838. case ct_NONE:
  839. if (!CA_FarRead(handle,MK_FP(*MemPtr,0),ChunkLen))
  840. {
  841. close(handle);
  842. *MemPtr = NULL;
  843. }
  844. break;
  845. default:
  846. close(handle);
  847. TrashProg("Uknown Chunk.Compression Type!");
  848. break;
  849. }
  850. }
  851. else
  852. *MemPtr = NULL;
  853. close(handle);
  854. return(*MemPtr);
  855. }