SOFT.C 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480
  1. /* Catacomb Apocalypse 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. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include <ctype.h>
  22. #include <alloc.h>
  23. #include <fcntl.h>
  24. #include <dos.h>
  25. #include <io.h>
  26. #include "def.h"
  27. #include "gelib.h"
  28. #include "soft.h"
  29. #include "lzw.h"
  30. #include "lzhuff.h"
  31. #include "jam_io.h"
  32. //===========================================================================
  33. //
  34. // SWITCHES
  35. //
  36. //===========================================================================
  37. #define LZH_SUPPORT 1
  38. #define LZW_SUPPORT 0
  39. //=========================================================================
  40. //
  41. //
  42. // GENERAL LOAD ROUTINES
  43. //
  44. //
  45. //=========================================================================
  46. //--------------------------------------------------------------------------
  47. // BLoad() -- THIS HAS NOT BEEN FULLY TESTED!
  48. //
  49. // NOTICE : This version of BLOAD is compatable with JAMPak V3.0 and the
  50. // new fileformat...
  51. //--------------------------------------------------------------------------
  52. unsigned long BLoad(char *SourceFile, memptr *DstPtr)
  53. {
  54. int handle;
  55. memptr SrcPtr;
  56. unsigned long i, j, k, r, c;
  57. word flags;
  58. byte Buffer[8];
  59. unsigned long SrcLen,DstLen;
  60. struct CMP1Header CompHeader;
  61. boolean Compressed = false;
  62. memset((void *)&CompHeader,0,sizeof(struct CMP1Header));
  63. //
  64. // Open file to load....
  65. //
  66. if ((handle = open(SourceFile, O_RDONLY|O_BINARY)) == -1)
  67. return(0);
  68. //
  69. // Look for JAMPAK headers
  70. //
  71. read(handle,Buffer,4);
  72. if (!strncmp(Buffer,COMP,4))
  73. {
  74. //
  75. // Compressed under OLD file format
  76. //
  77. Compressed = true;
  78. SrcLen = Verify(SourceFile);
  79. read(handle,(void *)&CompHeader.OrginalLen,4);
  80. CompHeader.CompType = ct_LZW;
  81. MM_GetPtr(DstPtr,CompHeader.OrginalLen);
  82. if (!*DstPtr)
  83. return(0);
  84. }
  85. else
  86. if (!strncmp(Buffer,CMP1,4))
  87. {
  88. //
  89. // Compressed under new file format...
  90. //
  91. Compressed = true;
  92. SrcLen = Verify(SourceFile);
  93. read(handle,(void *)&CompHeader,sizeof(struct CMP1Header));
  94. MM_GetPtr(DstPtr,CompHeader.OrginalLen);
  95. if (!*DstPtr)
  96. return(0);
  97. }
  98. else
  99. DstLen = Verify(SourceFile);
  100. //
  101. // Load the file in memory...
  102. //
  103. if (Compressed)
  104. {
  105. DstLen = CompHeader.OrginalLen;
  106. if ((MM_TotalFree() < SrcLen) && (CompHeader.CompType))
  107. {
  108. if (!InitBufferedIO(handle,&lzwBIO))
  109. TrashProg("No memory for buffered I/O.");
  110. switch (CompHeader.CompType)
  111. {
  112. #if LZW_SUPPORT
  113. case ct_LZW:
  114. lzwDecompress(&lzwBIO,MK_FP(*DstPtr,0),CompHeader.OrginalLen,(SRC_BFILE|DEST_MEM));
  115. break;
  116. #endif
  117. #if LZH_SUPPORT
  118. case ct_LZH:
  119. lzhDecompress(&lzwBIO,MK_FP(*DstPtr,0),CompHeader.OrginalLen,CompHeader.CompressLen,(SRC_BFILE|DEST_MEM));
  120. break;
  121. #endif
  122. default:
  123. TrashProg("BLoad() - Unrecognized/Supported compression");
  124. break;
  125. }
  126. FreeBufferedIO(&lzwBIO);
  127. }
  128. else
  129. {
  130. CA_LoadFile(SourceFile,&SrcPtr);
  131. switch (CompHeader.CompType)
  132. {
  133. #if LZW_SUPPORT
  134. case ct_LZW:
  135. lzwDecompress(MK_FP(SrcPtr,8),MK_FP(*DstPtr,0),CompHeader.OrginalLen,(SRC_MEM|DEST_MEM));
  136. break;
  137. #endif
  138. #if LZH_SUPPORT
  139. case ct_LZH:
  140. lzhDecompress(MK_FP(SrcPtr,8),MK_FP(*DstPtr,0),CompHeader.OrginalLen,CompHeader.CompressLen,(SRC_MEM|DEST_MEM));
  141. break;
  142. #endif
  143. default:
  144. TrashProg("BLoad() - Unrecognized/Supported compression");
  145. break;
  146. }
  147. MM_FreePtr(&SrcPtr);
  148. }
  149. }
  150. else
  151. CA_LoadFile(SourceFile,DstPtr);
  152. close(handle);
  153. return(DstLen);
  154. }
  155. ////////////////////////////////////////////////////////////////////////////
  156. //
  157. // LoadLIBShape()
  158. //
  159. int LoadLIBShape(char *SLIB_Filename, char *Filename,struct Shape *SHP)
  160. {
  161. #define CHUNK(Name) (*ptr == *Name) && \
  162. (*(ptr+1) == *(Name+1)) && \
  163. (*(ptr+2) == *(Name+2)) && \
  164. (*(ptr+3) == *(Name+3))
  165. int RT_CODE;
  166. FILE *fp;
  167. char CHUNK[5];
  168. char far *ptr;
  169. memptr IFFfile = NULL;
  170. unsigned long FileLen, size, ChunkLen;
  171. int loop;
  172. RT_CODE = 1;
  173. // Decompress to ram and return ptr to data and return len of data in
  174. // passed variable...
  175. if (!LoadLIBFile(SLIB_Filename,Filename,&IFFfile))
  176. TrashProg("Error Loading Compressed lib shape!");
  177. // Evaluate the file
  178. //
  179. ptr = MK_FP(IFFfile,0);
  180. if (!CHUNK("FORM"))
  181. goto EXIT_FUNC;
  182. ptr += 4;
  183. FileLen = *(long far *)ptr;
  184. SwapLong((long far *)&FileLen);
  185. ptr += 4;
  186. if (!CHUNK("ILBM"))
  187. goto EXIT_FUNC;
  188. ptr += 4;
  189. FileLen += 4;
  190. while (FileLen)
  191. {
  192. ChunkLen = *(long far *)(ptr+4);
  193. SwapLong((long far *)&ChunkLen);
  194. ChunkLen = (ChunkLen+1) & 0xFFFFFFFE;
  195. if (CHUNK("BMHD"))
  196. {
  197. ptr += 8;
  198. SHP->bmHdr.w = ((struct BitMapHeader far *)ptr)->w;
  199. SHP->bmHdr.h = ((struct BitMapHeader far *)ptr)->h;
  200. SHP->bmHdr.x = ((struct BitMapHeader far *)ptr)->x;
  201. SHP->bmHdr.y = ((struct BitMapHeader far *)ptr)->y;
  202. SHP->bmHdr.d = ((struct BitMapHeader far *)ptr)->d;
  203. SHP->bmHdr.trans = ((struct BitMapHeader far *)ptr)->trans;
  204. SHP->bmHdr.comp = ((struct BitMapHeader far *)ptr)->comp;
  205. SHP->bmHdr.pad = ((struct BitMapHeader far *)ptr)->pad;
  206. SwapWord(&SHP->bmHdr.w);
  207. SwapWord(&SHP->bmHdr.h);
  208. SwapWord(&SHP->bmHdr.x);
  209. SwapWord(&SHP->bmHdr.y);
  210. ptr += ChunkLen;
  211. }
  212. else
  213. if (CHUNK("BODY"))
  214. {
  215. ptr += 4;
  216. size = *((long far *)ptr);
  217. ptr += 4;
  218. SwapLong((long far *)&size);
  219. SHP->BPR = (SHP->bmHdr.w+7) >> 3;
  220. MM_GetPtr(&SHP->Data,size);
  221. if (!SHP->Data)
  222. goto EXIT_FUNC;
  223. movedata(FP_SEG(ptr),FP_OFF(ptr),FP_SEG(SHP->Data),0,size);
  224. ptr += ChunkLen;
  225. break;
  226. }
  227. else
  228. ptr += ChunkLen+8;
  229. FileLen -= ChunkLen+8;
  230. }
  231. RT_CODE = 0;
  232. EXIT_FUNC:;
  233. if (IFFfile)
  234. {
  235. // segptr = (memptr)FP_SEG(IFFfile);
  236. MM_FreePtr(&IFFfile);
  237. }
  238. return (RT_CODE);
  239. }
  240. //----------------------------------------------------------------------------
  241. // LoadLIBFile() -- Copies a file from an existing archive to dos.
  242. //
  243. // PARAMETERS :
  244. //
  245. // LibName - Name of lib file created with SoftLib V1.0
  246. //
  247. // FileName - Name of file to load from lib file.
  248. //
  249. // MemPtr - (IF !NULL) - Pointer to memory to load into ..
  250. // (IF NULL) - Routine allocates necessary memory and
  251. // returns a MEM(SEG) pointer to memory allocated.
  252. //
  253. // RETURN :
  254. //
  255. // (IF !NULL) - A pointer to the loaded data.
  256. // (IF NULL) - Error!
  257. //
  258. //----------------------------------------------------------------------------
  259. memptr LoadLIBFile(char *LibName,char *FileName,memptr *MemPtr)
  260. {
  261. int handle;
  262. unsigned long header;
  263. struct ChunkHeader Header;
  264. unsigned long ChunkLen;
  265. short x;
  266. struct FileEntryHdr FileEntry; // Storage for file once found
  267. struct FileEntryHdr FileEntryHeader; // Header used durring searching
  268. struct SoftLibHdr LibraryHeader; // Library header - Version Checking
  269. boolean FileFound = false;
  270. unsigned long id_slib = ID_SLIB;
  271. unsigned long id_chunk = ID_CHUNK;
  272. //
  273. // OPEN SOFTLIB FILE
  274. //
  275. if ((handle = open(LibName,O_RDONLY|O_BINARY, S_IREAD)) == -1)
  276. return(NULL);
  277. //
  278. // VERIFY it is a SOFTLIB (SLIB) file
  279. //
  280. if (read(handle,&header,4) == -1)
  281. {
  282. close(handle);
  283. return(NULL);
  284. }
  285. if (header != id_slib)
  286. {
  287. close(handle);
  288. return(NULL);
  289. }
  290. //
  291. // CHECK LIBRARY HEADER VERSION NUMBER
  292. //
  293. if (read(handle, &LibraryHeader,sizeof(struct SoftLibHdr)) == -1)
  294. TrashProg("read error in LoadSLIBFile()\n%c",7);
  295. if (LibraryHeader.Version > SOFTLIB_VER)
  296. TrashProg("Unsupported file ver %d",LibraryHeader.Version);
  297. //
  298. // MANAGE FILE ENTRY HEADERS...
  299. //
  300. for (x = 1;x<=LibraryHeader.FileCount;x++)
  301. {
  302. if (read(handle, &FileEntryHeader,sizeof(struct FileEntryHdr)) == -1)
  303. {
  304. close(handle);
  305. return(NULL);
  306. }
  307. if (!stricmp(FileEntryHeader.FileName,FileName))
  308. {
  309. FileEntry = FileEntryHeader;
  310. FileFound = true;
  311. }
  312. }
  313. //
  314. // IF FILE HAS BEEN FOUND THEN SEEK TO POSITION AND EXTRACT
  315. // ELSE RETURN WITH ERROR CODE...
  316. //
  317. if (FileFound)
  318. {
  319. if (lseek(handle,FileEntry.Offset,SEEK_CUR) == -1)
  320. {
  321. close(handle);
  322. return(NULL);
  323. }
  324. //
  325. // READ CHUNK HEADER - Verify we are at the beginning of a chunk..
  326. //
  327. if (read(handle,(char *)&Header,sizeof(struct ChunkHeader)) == -1)
  328. TrashProg("LIB File - Unable to read Header!");
  329. if (Header.HeaderID != id_chunk)
  330. TrashProg("LIB File - BAD HeaderID!");
  331. //
  332. // Allocate memory if Necessary...
  333. //
  334. if (!*MemPtr)
  335. MM_GetPtr(MemPtr,FileEntry.OrginalLength);
  336. //
  337. // Calculate the length of the data (without the chunk header).
  338. //
  339. ChunkLen = FileEntry.ChunkLen - sizeof(struct ChunkHeader);
  340. //
  341. // Extract Data from file
  342. //
  343. switch (Header.Compression)
  344. {
  345. #if LZW_SUPPORT
  346. case ct_LZW:
  347. if (!InitBufferedIO(handle,&lzwBIO))
  348. TrashProg("No memory for buffered I/O.");
  349. lzwDecompress(&lzwBIO,MK_FP(*MemPtr,0),FileEntry.OrginalLength,(SRC_BFILE|DEST_MEM));
  350. FreeBufferedIO(&lzwBIO);
  351. break;
  352. #endif
  353. #if LZH_SUPPORT
  354. case ct_LZH:
  355. if (!InitBufferedIO(handle,&lzwBIO))
  356. TrashProg("No memory for buffered I/O.");
  357. lzhDecompress(&lzwBIO, MK_FP(*MemPtr,0), FileEntry.OrginalLength, ChunkLen, (SRC_BFILE|DEST_MEM));
  358. FreeBufferedIO(&lzwBIO);
  359. break;
  360. #endif
  361. case ct_NONE:
  362. if (!CA_FarRead(handle,MK_FP(*MemPtr,0),ChunkLen))
  363. {
  364. // close(handle);
  365. *MemPtr = NULL;
  366. }
  367. break;
  368. default:
  369. close(handle);
  370. TrashProg("Unknown Chunk.Compression Type!");
  371. break;
  372. }
  373. }
  374. else
  375. *MemPtr = NULL;
  376. close(handle);
  377. return(*MemPtr);
  378. }