palcommon.c 19 KB

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