ending.c 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. //
  2. // Copyright (c) 2009, Wei Mingzhi <whistler_wmz@users.sf.net>.
  3. // All rights reserved.
  4. //
  5. // This file is part of SDLPAL.
  6. //
  7. // SDLPAL is free software: you can redistribute it and/or modify
  8. // it under the terms of the GNU General Public License as published by
  9. // the Free Software Foundation, either version 3 of the License, or
  10. // (at your option) any later version.
  11. //
  12. // This program is distributed in the hope that it will be useful,
  13. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. // GNU General Public License for more details.
  16. //
  17. // You should have received a copy of the GNU General Public License
  18. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. //
  20. #include "main.h"
  21. static WORD g_wCurEffectSprite = 0;
  22. VOID
  23. PAL_EndingSetEffectSprite(
  24. WORD wSpriteNum
  25. )
  26. /*++
  27. Purpose:
  28. Set the effect sprite of the ending.
  29. Parameters:
  30. [IN] wSpriteNum - the number of the sprite.
  31. Return value:
  32. None.
  33. --*/
  34. {
  35. g_wCurEffectSprite = wSpriteNum;
  36. }
  37. VOID
  38. PAL_ShowFBP(
  39. WORD wChunkNum,
  40. WORD wFade
  41. )
  42. /*++
  43. Purpose:
  44. Draw an FBP picture to the screen.
  45. Parameters:
  46. [IN] wChunkNum - number of chunk in fbp.mkf file.
  47. [IN] wFade - fading speed of showing the picture.
  48. Return value:
  49. None.
  50. --*/
  51. {
  52. PAL_LARGE BYTE buf[320 * 200];
  53. PAL_LARGE BYTE bufSprite[320 * 200];
  54. const int rgIndex[6] = {0, 3, 1, 5, 2, 4};
  55. SDL_Surface *p;
  56. int i, j, k;
  57. BYTE a, b;
  58. if (PAL_MKFDecompressChunk(buf, 320 * 200, wChunkNum, gpGlobals->f.fpFBP) <= 0)
  59. {
  60. memset(buf, 0, sizeof(buf));
  61. }
  62. if (g_wCurEffectSprite != 0)
  63. {
  64. PAL_MKFDecompressChunk(bufSprite, 320 * 200, g_wCurEffectSprite, gpGlobals->f.fpMGO);
  65. }
  66. if (wFade)
  67. {
  68. wFade++;
  69. wFade *= 10;
  70. p = SDL_CreateRGBSurface(gpScreen->flags & ~SDL_HWSURFACE, 320, 200, 8,
  71. gpScreen->format->Rmask, gpScreen->format->Gmask,
  72. gpScreen->format->Bmask, gpScreen->format->Amask);
  73. PAL_FBPBlitToSurface(buf, p);
  74. VIDEO_BackupScreen();
  75. for (i = 0; i < 16; i++)
  76. {
  77. for (j = 0; j < 6; j++)
  78. {
  79. //
  80. // Blend the pixels in the 2 buffers, and put the result into the
  81. // backup buffer
  82. //
  83. for (k = rgIndex[j]; k < gpScreen->pitch * gpScreen->h; k += 6)
  84. {
  85. a = ((LPBYTE)(p->pixels))[k];
  86. b = ((LPBYTE)(gpScreenBak->pixels))[k];
  87. if (i > 0)
  88. {
  89. if ((a & 0x0F) > (b & 0x0F))
  90. {
  91. b++;
  92. }
  93. else if ((a & 0x0F) < (b & 0x0F))
  94. {
  95. b--;
  96. }
  97. }
  98. ((LPBYTE)(gpScreenBak->pixels))[k] = ((a & 0xF0) | (b & 0x0F));
  99. }
  100. SDL_BlitSurface(gpScreenBak, NULL, gpScreen, NULL);
  101. if (g_wCurEffectSprite != 0)
  102. {
  103. int f = SDL_GetTicks() / 150;
  104. PAL_RLEBlitToSurface(PAL_SpriteGetFrame(bufSprite, f % PAL_SpriteGetNumFrames(bufSprite)),
  105. gpScreen, PAL_XY(0, 0));
  106. }
  107. VIDEO_UpdateScreen(NULL);
  108. UTIL_Delay(wFade);
  109. }
  110. }
  111. SDL_FreeSurface(p);
  112. }
  113. //
  114. // HACKHACK: to make the ending show correctly
  115. //
  116. if (wChunkNum != 49)
  117. {
  118. PAL_FBPBlitToSurface(buf, gpScreen);
  119. }
  120. VIDEO_UpdateScreen(NULL);
  121. }
  122. VOID
  123. PAL_ScrollFBP(
  124. WORD wChunkNum,
  125. WORD wScrollSpeed,
  126. BOOL fScrollDown
  127. )
  128. /*++
  129. Purpose:
  130. Scroll up an FBP picture to the screen.
  131. Parameters:
  132. [IN] wChunkNum - number of chunk in fbp.mkf file.
  133. [IN] wScrollSpeed - scrolling speed of showing the picture.
  134. [IN] fScrollDown - TRUE if scroll down, FALSE if scroll up.
  135. Return value:
  136. None.
  137. --*/
  138. {
  139. SDL_Surface *p;
  140. PAL_LARGE BYTE buf[320 * 200];
  141. PAL_LARGE BYTE bufSprite[320 * 200];
  142. int i, l;
  143. SDL_Rect rect, dstrect;
  144. if (PAL_MKFDecompressChunk(buf, 320 * 200, wChunkNum, gpGlobals->f.fpFBP) <= 0)
  145. {
  146. return;
  147. }
  148. if (g_wCurEffectSprite != 0)
  149. {
  150. PAL_MKFDecompressChunk(bufSprite, 320 * 200, g_wCurEffectSprite, gpGlobals->f.fpMGO);
  151. }
  152. p = SDL_CreateRGBSurface(gpScreen->flags & ~SDL_HWSURFACE, 320, 200, 8,
  153. gpScreen->format->Rmask, gpScreen->format->Gmask,
  154. gpScreen->format->Bmask, gpScreen->format->Amask);
  155. if (p == NULL)
  156. {
  157. return;
  158. }
  159. VIDEO_BackupScreen();
  160. PAL_FBPBlitToSurface(buf, p);
  161. if (wScrollSpeed == 0)
  162. {
  163. wScrollSpeed = 1;
  164. }
  165. rect.x = 0;
  166. rect.w = 320;
  167. dstrect.x = 0;
  168. dstrect.w = 320;
  169. for (l = 0; l < 220; l++)
  170. {
  171. i = l;
  172. if (i > 200)
  173. {
  174. i = 200;
  175. }
  176. if (fScrollDown)
  177. {
  178. rect.y = 0;
  179. dstrect.y = i;
  180. rect.h = 200 - i;
  181. dstrect.h = 200 - i;
  182. }
  183. else
  184. {
  185. rect.y = i;
  186. dstrect.y = 0;
  187. rect.h = 200 - i;
  188. dstrect.h = 200 - i;
  189. }
  190. SDL_BlitSurface(gpScreenBak, &rect, gpScreen, &dstrect);
  191. if (fScrollDown)
  192. {
  193. rect.y = 200 - i;
  194. dstrect.y = 0;
  195. rect.h = i;
  196. dstrect.h = i;
  197. }
  198. else
  199. {
  200. rect.y = 0;
  201. dstrect.y = 200 - i;
  202. rect.h = i;
  203. dstrect.h = i;
  204. }
  205. SDL_BlitSurface(p, &rect, gpScreen, &dstrect);
  206. PAL_ApplyWave(gpScreen);
  207. if (g_wCurEffectSprite != 0)
  208. {
  209. int f = SDL_GetTicks() / 150;
  210. PAL_RLEBlitToSurface(PAL_SpriteGetFrame(bufSprite, f % PAL_SpriteGetNumFrames(bufSprite)),
  211. gpScreen, PAL_XY(0, 0));
  212. }
  213. VIDEO_UpdateScreen(NULL);
  214. if (gpGlobals->fNeedToFadeIn)
  215. {
  216. PAL_FadeIn(gpGlobals->wNumPalette, gpGlobals->fNightPalette, 1);
  217. gpGlobals->fNeedToFadeIn = FALSE;
  218. }
  219. UTIL_Delay(800 / wScrollSpeed);
  220. }
  221. SDL_BlitSurface(p, NULL, gpScreen, NULL);
  222. SDL_FreeSurface(p);
  223. VIDEO_UpdateScreen(NULL);
  224. }
  225. VOID
  226. PAL_EndingAnimation(
  227. VOID
  228. )
  229. /*++
  230. Purpose:
  231. Show the ending animation.
  232. Parameters:
  233. None.
  234. Return value:
  235. None.
  236. --*/
  237. {
  238. LPBYTE buf;
  239. LPBYTE bufGirl;
  240. SDL_Surface *pUpper;
  241. SDL_Surface *pLower;
  242. SDL_Rect srcrect, dstrect;
  243. int yPosGirl = 180;
  244. int i;
  245. buf = (LPBYTE)UTIL_calloc(1, 64000);
  246. bufGirl = (LPBYTE)UTIL_calloc(1, 6000);
  247. pUpper = SDL_CreateRGBSurface(gpScreen->flags & ~SDL_HWSURFACE, 320, 200, 8,
  248. gpScreen->format->Rmask, gpScreen->format->Gmask,
  249. gpScreen->format->Bmask, gpScreen->format->Amask);
  250. pLower = SDL_CreateRGBSurface(gpScreen->flags & ~SDL_HWSURFACE, 320, 200, 8,
  251. gpScreen->format->Rmask, gpScreen->format->Gmask,
  252. gpScreen->format->Bmask, gpScreen->format->Amask);
  253. PAL_MKFDecompressChunk(buf, 64000, 61, gpGlobals->f.fpFBP);
  254. PAL_FBPBlitToSurface(buf, pUpper);
  255. PAL_MKFDecompressChunk(buf, 64000, 62, gpGlobals->f.fpFBP);
  256. PAL_FBPBlitToSurface(buf, pLower);
  257. PAL_MKFDecompressChunk(buf, 64000, 571, gpGlobals->f.fpMGO);
  258. PAL_MKFDecompressChunk(bufGirl, 6000, 572, gpGlobals->f.fpMGO);
  259. srcrect.x = 0;
  260. dstrect.x = 0;
  261. srcrect.w = 320;
  262. dstrect.w = 320;
  263. gpGlobals->wScreenWave = 2;
  264. for (i = 0; i < 400; i++)
  265. {
  266. //
  267. // Draw the background
  268. //
  269. srcrect.y = 0;
  270. srcrect.h = 200 - i / 2;
  271. dstrect.y = i / 2;
  272. dstrect.h = 200 - i / 2;
  273. SDL_BlitSurface(pLower, &srcrect, gpScreen, &dstrect);
  274. srcrect.y = 200 - i / 2;
  275. srcrect.h = i / 2;
  276. dstrect.y = 0;
  277. dstrect.h = i / 2;
  278. SDL_BlitSurface(pUpper, &srcrect, gpScreen, &dstrect);
  279. PAL_ApplyWave(gpScreen);
  280. //
  281. // Draw the beast
  282. //
  283. PAL_RLEBlitToSurface(PAL_SpriteGetFrame(buf, 0), gpScreen, PAL_XY(0, -400 + i));
  284. PAL_RLEBlitToSurface(PAL_SpriteGetFrame(buf, 1), gpScreen, PAL_XY(0, -200 + i));
  285. //
  286. // Draw the girl
  287. //
  288. yPosGirl -= i & 1;
  289. if (yPosGirl < 80)
  290. {
  291. yPosGirl = 80;
  292. }
  293. PAL_RLEBlitToSurface(PAL_SpriteGetFrame(bufGirl, (SDL_GetTicks() / 50) % 4),
  294. gpScreen, PAL_XY(220, yPosGirl));
  295. //
  296. // Update the screen
  297. //
  298. VIDEO_UpdateScreen(NULL);
  299. if (gpGlobals->fNeedToFadeIn)
  300. {
  301. PAL_FadeIn(gpGlobals->wNumPalette, gpGlobals->fNightPalette, 1);
  302. gpGlobals->fNeedToFadeIn = FALSE;
  303. }
  304. UTIL_Delay(50);
  305. }
  306. gpGlobals->wScreenWave = 0;
  307. SDL_FreeSurface(pUpper);
  308. SDL_FreeSurface(pLower);
  309. free(buf);
  310. free(bufGirl);
  311. }