palcommon.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935
  1. /* -*- mode: c; tab-width: 4; c-basic-offset: 3; c-file-style: "linux" -*- */
  2. //
  3. // Copyright (c) 2009, Wei Mingzhi <whistler_wmz@users.sf.net>.
  4. // All rights reserved.
  5. //
  6. // Based on PAL MapEditor by Baldur.
  7. //
  8. // This file is part of SDLPAL.
  9. //
  10. // SDLPAL is free software: you can redistribute it and/or modify
  11. // it under the terms of the GNU General Public License as published by
  12. // the Free Software Foundation, either version 3 of the License, or
  13. // (at your option) any later version.
  14. //
  15. // This program is distributed in the hope that it will be useful,
  16. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. // GNU General Public License for more details.
  19. //
  20. // You should have received a copy of the GNU General Public License
  21. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  22. //
  23. #include "palcommon.h"
  24. #include "global.h"
  25. INT
  26. PAL_RLEBlitToSurface(
  27. LPCBITMAPRLE lpBitmapRLE,
  28. SDL_Surface *lpDstSurface,
  29. PAL_POS pos
  30. )
  31. /*++
  32. Purpose:
  33. Blit an RLE-compressed bitmap to an SDL surface.
  34. NOTE: Assume the surface is already locked, and the surface is a 8-bit one.
  35. Parameters:
  36. [IN] lpBitmapRLE - pointer to the RLE-compressed bitmap to be decoded.
  37. [OUT] lpDstSurface - pointer to the destination SDL surface.
  38. [IN] pos - position of the destination area.
  39. Return value:
  40. 0 = success, -1 = error.
  41. --*/
  42. {
  43. UINT i, j;
  44. INT x, y;
  45. UINT uiLen = 0;
  46. UINT uiWidth = 0;
  47. UINT uiHeight = 0;
  48. BYTE T;
  49. INT dx = PAL_X(pos);
  50. INT dy = PAL_Y(pos);
  51. //
  52. // Check for NULL pointer.
  53. //
  54. if (lpBitmapRLE == NULL || lpDstSurface == NULL)
  55. {
  56. return -1;
  57. }
  58. //
  59. // Skip the 0x00000002 in the file header.
  60. //
  61. if (lpBitmapRLE[0] == 0x02 && lpBitmapRLE[1] == 0x00 &&
  62. lpBitmapRLE[2] == 0x00 && lpBitmapRLE[3] == 0x00)
  63. {
  64. lpBitmapRLE += 4;
  65. }
  66. //
  67. // Get the width and height of the bitmap.
  68. //
  69. uiWidth = lpBitmapRLE[0] | (lpBitmapRLE[1] << 8);
  70. uiHeight = lpBitmapRLE[2] | (lpBitmapRLE[3] << 8);
  71. //
  72. // Calculate the total length of the bitmap.
  73. // The bitmap is 8-bpp, each pixel will use 1 byte.
  74. //
  75. uiLen = uiWidth * uiHeight;
  76. //
  77. // Start decoding and blitting the bitmap.
  78. //
  79. lpBitmapRLE += 4;
  80. for (i = 0; i < uiLen;)
  81. {
  82. T = *lpBitmapRLE++;
  83. if ((T & 0x80) && T <= 0x80 + uiWidth)
  84. {
  85. i += T - 0x80;
  86. }
  87. else
  88. {
  89. for (j = 0; j < T; j++)
  90. {
  91. //
  92. // Calculate the destination coordination.
  93. // FIXME: This could be optimized
  94. //
  95. y = (i + j) / uiWidth + dy;
  96. x = (i + j) % uiWidth + dx;
  97. //
  98. // Skip the points which are out of the surface.
  99. //
  100. if (x < 0)
  101. {
  102. j += -x - 1;
  103. continue;
  104. }
  105. else if (x >= lpDstSurface->w)
  106. {
  107. j += x - lpDstSurface->w;
  108. continue;
  109. }
  110. if (y < 0)
  111. {
  112. j += -y * uiWidth - 1;
  113. continue;
  114. }
  115. else if (y >= lpDstSurface->h)
  116. {
  117. goto end; // No more pixels needed, break out
  118. }
  119. //
  120. // Put the pixel onto the surface (FIXME: inefficient).
  121. //
  122. ((LPBYTE)lpDstSurface->pixels)[y * lpDstSurface->pitch + x] = lpBitmapRLE[j];
  123. }
  124. lpBitmapRLE += T;
  125. i += T;
  126. }
  127. }
  128. end:
  129. //
  130. // Success
  131. //
  132. return 0;
  133. }
  134. INT
  135. PAL_RLEBlitWithColorShift(
  136. LPCBITMAPRLE lpBitmapRLE,
  137. SDL_Surface *lpDstSurface,
  138. PAL_POS pos,
  139. INT iColorShift
  140. )
  141. /*++
  142. Purpose:
  143. Blit an RLE-compressed bitmap to an SDL surface.
  144. NOTE: Assume the surface is already locked, and the surface is a 8-bit one.
  145. Parameters:
  146. [IN] lpBitmapRLE - pointer to the RLE-compressed bitmap to be decoded.
  147. [OUT] lpDstSurface - pointer to the destination SDL surface.
  148. [IN] pos - position of the destination area.
  149. [IN] iColorShift - shift the color by this value.
  150. Return value:
  151. 0 = success, -1 = error.
  152. --*/
  153. {
  154. UINT i, j;
  155. INT x, y;
  156. UINT uiLen = 0;
  157. UINT uiWidth = 0;
  158. UINT uiHeight = 0;
  159. BYTE T, b;
  160. INT dx = PAL_X(pos);
  161. INT dy = PAL_Y(pos);
  162. //
  163. // Check for NULL pointer.
  164. //
  165. if (lpBitmapRLE == NULL || lpDstSurface == NULL)
  166. {
  167. return -1;
  168. }
  169. //
  170. // Skip the 0x00000002 in the file header.
  171. //
  172. if (lpBitmapRLE[0] == 0x02 && lpBitmapRLE[1] == 0x00 &&
  173. lpBitmapRLE[2] == 0x00 && lpBitmapRLE[3] == 0x00)
  174. {
  175. lpBitmapRLE += 4;
  176. }
  177. //
  178. // Get the width and height of the bitmap.
  179. //
  180. uiWidth = lpBitmapRLE[0] | (lpBitmapRLE[1] << 8);
  181. uiHeight = lpBitmapRLE[2] | (lpBitmapRLE[3] << 8);
  182. //
  183. // Calculate the total length of the bitmap.
  184. // The bitmap is 8-bpp, each pixel will use 1 byte.
  185. //
  186. uiLen = uiWidth * uiHeight;
  187. //
  188. // Start decoding and blitting the bitmap.
  189. //
  190. lpBitmapRLE += 4;
  191. for (i = 0; i < uiLen;)
  192. {
  193. T = *lpBitmapRLE++;
  194. if ((T & 0x80) && T <= 0x80 + uiWidth)
  195. {
  196. i += T - 0x80;
  197. }
  198. else
  199. {
  200. for (j = 0; j < T; j++)
  201. {
  202. //
  203. // Calculate the destination coordination.
  204. // FIXME: This could be optimized
  205. //
  206. y = (i + j) / uiWidth + dy;
  207. x = (i + j) % uiWidth + dx;
  208. //
  209. // Skip the points which are out of the surface.
  210. //
  211. if (x < 0)
  212. {
  213. j += -x - 1;
  214. continue;
  215. }
  216. else if (x >= lpDstSurface->w)
  217. {
  218. j += x - lpDstSurface->w;
  219. continue;
  220. }
  221. if (y < 0)
  222. {
  223. j += -y * uiWidth - 1;
  224. continue;
  225. }
  226. else if (y >= lpDstSurface->h)
  227. {
  228. goto end; // No more pixels needed, break out
  229. }
  230. //
  231. // Put the pixel onto the surface (FIXME: inefficient).
  232. //
  233. b = (lpBitmapRLE[j] & 0x0F);
  234. if ((INT)b + iColorShift > 0x0F)
  235. {
  236. b = 0x0F;
  237. }
  238. else if ((INT)b + iColorShift < 0)
  239. {
  240. b = 0;
  241. }
  242. else
  243. {
  244. b += iColorShift;
  245. }
  246. ((LPBYTE)lpDstSurface->pixels)[y * lpDstSurface->pitch + x] =
  247. (b | (lpBitmapRLE[j] & 0xF0));
  248. }
  249. lpBitmapRLE += T;
  250. i += T;
  251. }
  252. }
  253. end:
  254. //
  255. // Success
  256. //
  257. return 0;
  258. }
  259. INT
  260. PAL_RLEBlitMonoColor(
  261. LPCBITMAPRLE lpBitmapRLE,
  262. SDL_Surface *lpDstSurface,
  263. PAL_POS pos,
  264. BYTE bColor,
  265. INT iColorShift
  266. )
  267. /*++
  268. Purpose:
  269. Blit an RLE-compressed bitmap to an SDL surface in mono-color form.
  270. NOTE: Assume the surface is already locked, and the surface is a 8-bit one.
  271. Parameters:
  272. [IN] lpBitmapRLE - pointer to the RLE-compressed bitmap to be decoded.
  273. [OUT] lpDstSurface - pointer to the destination SDL surface.
  274. [IN] pos - position of the destination area.
  275. [IN] bColor - the color to be used while drawing.
  276. [IN] iColorShift - shift the color by this value.
  277. Return value:
  278. 0 = success, -1 = error.
  279. --*/
  280. {
  281. UINT i, j;
  282. INT x, y;
  283. UINT uiLen = 0;
  284. UINT uiWidth = 0;
  285. UINT uiHeight = 0;
  286. BYTE T, b;
  287. INT dx = PAL_X(pos);
  288. INT dy = PAL_Y(pos);
  289. //
  290. // Check for NULL pointer.
  291. //
  292. if (lpBitmapRLE == NULL || lpDstSurface == NULL)
  293. {
  294. return -1;
  295. }
  296. //
  297. // Skip the 0x00000002 in the file header.
  298. //
  299. if (lpBitmapRLE[0] == 0x02 && lpBitmapRLE[1] == 0x00 &&
  300. lpBitmapRLE[2] == 0x00 && lpBitmapRLE[3] == 0x00)
  301. {
  302. lpBitmapRLE += 4;
  303. }
  304. //
  305. // Get the width and height of the bitmap.
  306. //
  307. uiWidth = lpBitmapRLE[0] | (lpBitmapRLE[1] << 8);
  308. uiHeight = lpBitmapRLE[2] | (lpBitmapRLE[3] << 8);
  309. //
  310. // Calculate the total length of the bitmap.
  311. // The bitmap is 8-bpp, each pixel will use 1 byte.
  312. //
  313. uiLen = uiWidth * uiHeight;
  314. //
  315. // Start decoding and blitting the bitmap.
  316. //
  317. lpBitmapRLE += 4;
  318. bColor &= 0xF0;
  319. for (i = 0; i < uiLen;)
  320. {
  321. T = *lpBitmapRLE++;
  322. if ((T & 0x80) && T <= 0x80 + uiWidth)
  323. {
  324. i += T - 0x80;
  325. }
  326. else
  327. {
  328. for (j = 0; j < T; j++)
  329. {
  330. //
  331. // Calculate the destination coordination.
  332. // FIXME: This could be optimized
  333. //
  334. y = (i + j) / uiWidth + dy;
  335. x = (i + j) % uiWidth + dx;
  336. //
  337. // Skip the points which are out of the surface.
  338. //
  339. if (x < 0)
  340. {
  341. j += -x - 1;
  342. continue;
  343. }
  344. else if (x >= lpDstSurface->w)
  345. {
  346. j += x - lpDstSurface->w;
  347. continue;
  348. }
  349. if (y < 0)
  350. {
  351. j += -y * uiWidth - 1;
  352. continue;
  353. }
  354. else if (y >= lpDstSurface->h)
  355. {
  356. goto end; // No more pixels needed, break out
  357. }
  358. //
  359. // Put the pixel onto the surface (FIXME: inefficient).
  360. //
  361. b = lpBitmapRLE[j] & 0x0F;
  362. if ((INT)b + iColorShift > 0x0F)
  363. {
  364. b = 0x0F;
  365. }
  366. else if ((INT)b + iColorShift < 0)
  367. {
  368. b = 0;
  369. }
  370. else
  371. {
  372. b += iColorShift;
  373. }
  374. ((LPBYTE)lpDstSurface->pixels)[y * lpDstSurface->pitch + x] = (b | bColor);
  375. }
  376. lpBitmapRLE += T;
  377. i += T;
  378. }
  379. }
  380. end:
  381. //
  382. // Success
  383. //
  384. return 0;
  385. }
  386. INT
  387. PAL_FBPBlitToSurface(
  388. LPBYTE lpBitmapFBP,
  389. SDL_Surface *lpDstSurface
  390. )
  391. /*++
  392. Purpose:
  393. Blit an uncompressed bitmap in FBP.MKF to an SDL surface.
  394. NOTE: Assume the surface is already locked, and the surface is a 8-bit 320x200 one.
  395. Parameters:
  396. [IN] lpBitmapFBP - pointer to the RLE-compressed bitmap to be decoded.
  397. [OUT] lpDstSurface - pointer to the destination SDL surface.
  398. Return value:
  399. 0 = success, -1 = error.
  400. --*/
  401. {
  402. int x, y;
  403. LPBYTE p;
  404. if (lpBitmapFBP == NULL || lpDstSurface == NULL ||
  405. lpDstSurface->w != 320 || lpDstSurface->h != 200)
  406. {
  407. return -1;
  408. }
  409. //
  410. // simply copy everything to the surface
  411. //
  412. for (y = 0; y < 200; y++)
  413. {
  414. p = (LPBYTE)(lpDstSurface->pixels) + y * lpDstSurface->pitch;
  415. for (x = 0; x < 320; x++)
  416. {
  417. *(p++) = *(lpBitmapFBP++);
  418. }
  419. }
  420. return 0;
  421. }
  422. INT
  423. PAL_RLEGetWidth(
  424. LPCBITMAPRLE lpBitmapRLE
  425. )
  426. /*++
  427. Purpose:
  428. Get the width of an RLE-compressed bitmap.
  429. Parameters:
  430. [IN] lpBitmapRLE - pointer to an RLE-compressed bitmap.
  431. Return value:
  432. Integer value which indicates the height of the bitmap.
  433. --*/
  434. {
  435. if (lpBitmapRLE == NULL)
  436. {
  437. return 0;
  438. }
  439. //
  440. // Skip the 0x00000002 in the file header.
  441. //
  442. if (lpBitmapRLE[0] == 0x02 && lpBitmapRLE[1] == 0x00 &&
  443. lpBitmapRLE[2] == 0x00 && lpBitmapRLE[3] == 0x00)
  444. {
  445. lpBitmapRLE += 4;
  446. }
  447. //
  448. // Return the width of the bitmap.
  449. //
  450. return lpBitmapRLE[0] | (lpBitmapRLE[1] << 8);
  451. }
  452. INT
  453. PAL_RLEGetHeight(
  454. LPCBITMAPRLE lpBitmapRLE
  455. )
  456. /*++
  457. Purpose:
  458. Get the height of an RLE-compressed bitmap.
  459. Parameters:
  460. [IN] lpBitmapRLE - pointer of an RLE-compressed bitmap.
  461. Return value:
  462. Integer value which indicates the height of the bitmap.
  463. --*/
  464. {
  465. if (lpBitmapRLE == NULL)
  466. {
  467. return 0;
  468. }
  469. //
  470. // Skip the 0x00000002 in the file header.
  471. //
  472. if (lpBitmapRLE[0] == 0x02 && lpBitmapRLE[1] == 0x00 &&
  473. lpBitmapRLE[2] == 0x00 && lpBitmapRLE[3] == 0x00)
  474. {
  475. lpBitmapRLE += 4;
  476. }
  477. //
  478. // Return the height of the bitmap.
  479. //
  480. return lpBitmapRLE[2] | (lpBitmapRLE[3] << 8);
  481. }
  482. WORD
  483. PAL_SpriteGetNumFrames(
  484. LPCSPRITE lpSprite
  485. )
  486. /*++
  487. Purpose:
  488. Get the total number of frames of a sprite.
  489. Parameters:
  490. [IN] lpSprite - pointer to the sprite.
  491. Return value:
  492. Number of frames of the sprite.
  493. --*/
  494. {
  495. if (lpSprite == NULL)
  496. {
  497. return 0;
  498. }
  499. return (lpSprite[0] | (lpSprite[1] << 8)) - 1;
  500. }
  501. LPCBITMAPRLE
  502. PAL_SpriteGetFrame(
  503. LPCSPRITE lpSprite,
  504. INT iFrameNum
  505. )
  506. /*++
  507. Purpose:
  508. Get the pointer to the specified frame from a sprite.
  509. Parameters:
  510. [IN] lpSprite - pointer to the sprite.
  511. [IN] iFrameNum - number of the frame.
  512. Return value:
  513. Pointer to the specified frame. NULL if the frame does not exist.
  514. --*/
  515. {
  516. int imagecount, offset;
  517. if (lpSprite == NULL)
  518. {
  519. return NULL;
  520. }
  521. //
  522. // Hack for broken sprites like the Bloody-Mouth Bug
  523. //
  524. // imagecount = (lpSprite[0] | (lpSprite[1] << 8)) - 1;
  525. imagecount = (lpSprite[0] | (lpSprite[1] << 8));
  526. if (iFrameNum < 0 || iFrameNum >= imagecount)
  527. {
  528. //
  529. // The frame does not exist
  530. //
  531. return NULL;
  532. }
  533. //
  534. // Get the offset of the frame
  535. //
  536. iFrameNum <<= 1;
  537. offset = ((lpSprite[iFrameNum] | (lpSprite[iFrameNum + 1] << 8)) << 1);
  538. if (!gpGlobals->fIsWIN95) offset = (WORD)offset;
  539. return &lpSprite[offset];
  540. }
  541. INT
  542. PAL_MKFGetChunkCount(
  543. FILE *fp
  544. )
  545. /*++
  546. Purpose:
  547. Get the number of chunks in an MKF archive.
  548. Parameters:
  549. [IN] fp - pointer to an fopen'ed MKF file.
  550. Return value:
  551. Integer value which indicates the number of chunks in the specified MKF file.
  552. --*/
  553. {
  554. INT iNumChunk;
  555. if (fp == NULL)
  556. {
  557. return 0;
  558. }
  559. fseek(fp, 0, SEEK_SET);
  560. fread(&iNumChunk, sizeof(INT), 1, fp);
  561. iNumChunk = (SDL_SwapLE32(iNumChunk) - 4) / 4;
  562. return iNumChunk;
  563. }
  564. INT
  565. PAL_MKFGetChunkSize(
  566. UINT uiChunkNum,
  567. FILE *fp
  568. )
  569. /*++
  570. Purpose:
  571. Get the size of a chunk in an MKF archive.
  572. Parameters:
  573. [IN] uiChunkNum - the number of the chunk in the MKF archive.
  574. [IN] fp - pointer to the fopen'ed MKF file.
  575. Return value:
  576. Integer value which indicates the size of the chunk.
  577. -1 if the chunk does not exist.
  578. --*/
  579. {
  580. UINT uiOffset = 0;
  581. UINT uiNextOffset = 0;
  582. UINT uiChunkCount = 0;
  583. //
  584. // Get the total number of chunks.
  585. //
  586. uiChunkCount = PAL_MKFGetChunkCount(fp);
  587. if (uiChunkNum >= uiChunkCount)
  588. {
  589. return -1;
  590. }
  591. //
  592. // Get the offset of the specified chunk and the next chunk.
  593. //
  594. fseek(fp, 4 * uiChunkNum, SEEK_SET);
  595. fread(&uiOffset, sizeof(UINT), 1, fp);
  596. fread(&uiNextOffset, sizeof(UINT), 1, fp);
  597. uiOffset = SDL_SwapLE32(uiOffset);
  598. uiNextOffset = SDL_SwapLE32(uiNextOffset);
  599. //
  600. // Return the length of the chunk.
  601. //
  602. return uiNextOffset - uiOffset;
  603. }
  604. INT
  605. PAL_MKFReadChunk(
  606. LPBYTE lpBuffer,
  607. UINT uiBufferSize,
  608. UINT uiChunkNum,
  609. FILE *fp
  610. )
  611. /*++
  612. Purpose:
  613. Read a chunk from an MKF archive into lpBuffer.
  614. Parameters:
  615. [OUT] lpBuffer - pointer to the destination buffer.
  616. [IN] uiBufferSize - size of the destination buffer.
  617. [IN] uiChunkNum - the number of the chunk in the MKF archive to read.
  618. [IN] fp - pointer to the fopen'ed MKF file.
  619. Return value:
  620. Integer value which indicates the size of the chunk.
  621. -1 if there are error in parameters.
  622. -2 if buffer size is not enough.
  623. --*/
  624. {
  625. UINT uiOffset = 0;
  626. UINT uiNextOffset = 0;
  627. UINT uiChunkCount;
  628. UINT uiChunkLen;
  629. if (lpBuffer == NULL || fp == NULL || uiBufferSize == 0)
  630. {
  631. return -1;
  632. }
  633. //
  634. // Get the total number of chunks.
  635. //
  636. uiChunkCount = PAL_MKFGetChunkCount(fp);
  637. if (uiChunkNum >= uiChunkCount)
  638. {
  639. return -1;
  640. }
  641. //
  642. // Get the offset of the chunk.
  643. //
  644. fseek(fp, 4 * uiChunkNum, SEEK_SET);
  645. fread(&uiOffset, 4, 1, fp);
  646. fread(&uiNextOffset, 4, 1, fp);
  647. uiOffset = SDL_SwapLE32(uiOffset);
  648. uiNextOffset = SDL_SwapLE32(uiNextOffset);
  649. //
  650. // Get the length of the chunk.
  651. //
  652. uiChunkLen = uiNextOffset - uiOffset;
  653. if (uiChunkLen > uiBufferSize)
  654. {
  655. return -2;
  656. }
  657. if (uiChunkLen != 0)
  658. {
  659. fseek(fp, uiOffset, SEEK_SET);
  660. fread(lpBuffer, uiChunkLen, 1, fp);
  661. }
  662. else
  663. {
  664. return -1;
  665. }
  666. return (INT)uiChunkLen;
  667. }
  668. INT
  669. PAL_MKFGetDecompressedSize(
  670. UINT uiChunkNum,
  671. FILE *fp
  672. )
  673. /*++
  674. Purpose:
  675. Get the decompressed size of a compressed chunk in an MKF archive.
  676. Parameters:
  677. [IN] uiChunkNum - the number of the chunk in the MKF archive.
  678. [IN] fp - pointer to the fopen'ed MKF file.
  679. Return value:
  680. Integer value which indicates the size of the chunk.
  681. -1 if the chunk does not exist.
  682. --*/
  683. {
  684. DWORD buf[2];
  685. UINT uiOffset;
  686. UINT uiChunkCount;
  687. if (fp == NULL)
  688. {
  689. return -1;
  690. }
  691. //
  692. // Get the total number of chunks.
  693. //
  694. uiChunkCount = PAL_MKFGetChunkCount(fp);
  695. if (uiChunkNum >= uiChunkCount)
  696. {
  697. return -1;
  698. }
  699. //
  700. // Get the offset of the chunk.
  701. //
  702. fseek(fp, 4 * uiChunkNum, SEEK_SET);
  703. fread(&uiOffset, 4, 1, fp);
  704. uiOffset = SDL_SwapLE32(uiOffset);
  705. //
  706. // Read the header.
  707. //
  708. fseek(fp, uiOffset, SEEK_SET);
  709. if (gpGlobals->fIsWIN95)
  710. {
  711. fread(buf, sizeof(DWORD), 1, fp);
  712. buf[0] = SDL_SwapLE32(buf[0]);
  713. return (INT)buf[0];
  714. }
  715. else
  716. {
  717. fread(buf, sizeof(DWORD), 2, fp);
  718. buf[0] = SDL_SwapLE32(buf[0]);
  719. buf[1] = SDL_SwapLE32(buf[1]);
  720. return (buf[0] != 0x315f4a59) ? -1 : (INT)buf[1];
  721. }
  722. }
  723. INT
  724. PAL_MKFDecompressChunk(
  725. LPBYTE lpBuffer,
  726. UINT uiBufferSize,
  727. UINT uiChunkNum,
  728. FILE *fp
  729. )
  730. /*++
  731. Purpose:
  732. Decompress a compressed chunk from an MKF archive into lpBuffer.
  733. Parameters:
  734. [OUT] lpBuffer - pointer to the destination buffer.
  735. [IN] uiBufferSize - size of the destination buffer.
  736. [IN] uiChunkNum - the number of the chunk in the MKF archive to read.
  737. [IN] fp - pointer to the fopen'ed MKF file.
  738. Return value:
  739. Integer value which indicates the size of the chunk.
  740. -1 if there are error in parameters, or buffer size is not enough.
  741. -3 if cannot allocate memory for decompression.
  742. --*/
  743. {
  744. LPBYTE buf;
  745. int len;
  746. len = PAL_MKFGetChunkSize(uiChunkNum, fp);
  747. if (len <= 0)
  748. {
  749. return len;
  750. }
  751. buf = (LPBYTE)malloc(len);
  752. if (buf == NULL)
  753. {
  754. return -3;
  755. }
  756. PAL_MKFReadChunk(buf, len, uiChunkNum, fp);
  757. len = Decompress(buf, lpBuffer, uiBufferSize);
  758. free(buf);
  759. return len;
  760. }