palcommon.c 19 KB

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