ending.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513
  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 "main.h"
  23. static WORD g_wCurEffectSprite = 0;
  24. VOID
  25. PAL_EndingSetEffectSprite(
  26. WORD wSpriteNum
  27. )
  28. /*++
  29. Purpose:
  30. Set the effect sprite of the ending.
  31. Parameters:
  32. [IN] wSpriteNum - the number of the sprite.
  33. Return value:
  34. None.
  35. --*/
  36. {
  37. g_wCurEffectSprite = wSpriteNum;
  38. }
  39. VOID
  40. PAL_ShowFBP(
  41. WORD wChunkNum,
  42. WORD wFade
  43. )
  44. /*++
  45. Purpose:
  46. Draw an FBP picture to the screen.
  47. Parameters:
  48. [IN] wChunkNum - number of chunk in fbp.mkf file.
  49. [IN] wFade - fading speed of showing the picture.
  50. Return value:
  51. None.
  52. --*/
  53. {
  54. PAL_LARGE BYTE buf[320 * 200];
  55. PAL_LARGE BYTE bufSprite[320 * 200];
  56. const int rgIndex[6] = {0, 3, 1, 5, 2, 4};
  57. int i, j, k;
  58. BYTE a, b;
  59. if (PAL_MKFDecompressChunk(buf, 320 * 200, wChunkNum, gpGlobals->f.fpFBP) <= 0)
  60. {
  61. memset(buf, 0, sizeof(buf));
  62. }
  63. if (g_wCurEffectSprite != 0)
  64. {
  65. PAL_MKFDecompressChunk(bufSprite, 320 * 200, g_wCurEffectSprite, gpGlobals->f.fpMGO);
  66. }
  67. if (wFade)
  68. {
  69. SDL_Surface *p = VIDEO_CreateCompatibleSurface(gpScreen);
  70. wFade++;
  71. wFade *= 10;
  72. PAL_FBPBlitToSurface(buf, p);
  73. VIDEO_BackupScreen(gpScreen);
  74. for (i = 0; i < 16; i++)
  75. {
  76. for (j = 0; j < 6; j++)
  77. {
  78. //
  79. // Blend the pixels in the 2 buffers, and put the result into the
  80. // backup buffer
  81. //
  82. for (k = rgIndex[j]; k < gpScreen->pitch * gpScreen->h; k += 6)
  83. {
  84. a = ((LPBYTE)(p->pixels))[k];
  85. b = ((LPBYTE)(gpScreenBak->pixels))[k];
  86. if (i > 0)
  87. {
  88. if ((a & 0x0F) > (b & 0x0F))
  89. {
  90. b++;
  91. }
  92. else if ((a & 0x0F) < (b & 0x0F))
  93. {
  94. b--;
  95. }
  96. }
  97. ((LPBYTE)(gpScreenBak->pixels))[k] = ((a & 0xF0) | (b & 0x0F));
  98. }
  99. VIDEO_RestoreScreen(gpScreen);
  100. if (g_wCurEffectSprite != 0)
  101. {
  102. int f = SDL_GetTicks() / 150;
  103. PAL_RLEBlitToSurface(PAL_SpriteGetFrame(bufSprite, f % PAL_SpriteGetNumFrames(bufSprite)),
  104. gpScreen, PAL_XY(0, 0));
  105. }
  106. VIDEO_UpdateScreen(NULL);
  107. UTIL_Delay(wFade);
  108. }
  109. }
  110. VIDEO_FreeSurface(p);
  111. }
  112. //
  113. // HACKHACK: to make the ending show correctly
  114. //
  115. if (wChunkNum != (gConfig.fIsWIN95 ? 68 : 49))
  116. {
  117. PAL_FBPBlitToSurface(buf, gpScreen);
  118. }
  119. VIDEO_UpdateScreen(NULL);
  120. }
  121. VOID
  122. PAL_ScrollFBP(
  123. WORD wChunkNum,
  124. WORD wScrollSpeed,
  125. BOOL fScrollDown
  126. )
  127. /*++
  128. Purpose:
  129. Scroll up an FBP picture to the screen.
  130. Parameters:
  131. [IN] wChunkNum - number of chunk in fbp.mkf file.
  132. [IN] wScrollSpeed - scrolling speed of showing the picture.
  133. [IN] fScrollDown - TRUE if scroll down, FALSE if scroll up.
  134. Return value:
  135. None.
  136. --*/
  137. {
  138. SDL_Surface *p;
  139. PAL_LARGE BYTE buf[320 * 200];
  140. PAL_LARGE BYTE bufSprite[320 * 200];
  141. int i, l;
  142. SDL_Rect rect, dstrect;
  143. if (PAL_MKFDecompressChunk(buf, 320 * 200, wChunkNum, gpGlobals->f.fpFBP) <= 0)
  144. {
  145. return;
  146. }
  147. if (g_wCurEffectSprite != 0)
  148. {
  149. PAL_MKFDecompressChunk(bufSprite, 320 * 200, g_wCurEffectSprite, gpGlobals->f.fpMGO);
  150. }
  151. p = VIDEO_CreateCompatibleSurface(gpScreen);
  152. if (p == NULL)
  153. {
  154. return;
  155. }
  156. VIDEO_BackupScreen(gpScreen);
  157. PAL_FBPBlitToSurface(buf, p);
  158. if (wScrollSpeed == 0)
  159. {
  160. wScrollSpeed = 1;
  161. }
  162. rect.x = 0;
  163. rect.w = 320;
  164. dstrect.x = 0;
  165. dstrect.w = 320;
  166. for (l = 0; l < 220; l++)
  167. {
  168. i = l;
  169. if (i > 200)
  170. {
  171. i = 200;
  172. }
  173. if (fScrollDown)
  174. {
  175. rect.y = 0;
  176. dstrect.y = i;
  177. rect.h = 200 - i;
  178. dstrect.h = 200 - i;
  179. }
  180. else
  181. {
  182. rect.y = i;
  183. dstrect.y = 0;
  184. rect.h = 200 - i;
  185. dstrect.h = 200 - i;
  186. }
  187. VIDEO_CopySurface(gpScreenBak, &rect, gpScreen, &dstrect);
  188. if (fScrollDown)
  189. {
  190. rect.y = 200 - i;
  191. dstrect.y = 0;
  192. rect.h = i;
  193. dstrect.h = i;
  194. }
  195. else
  196. {
  197. rect.y = 0;
  198. dstrect.y = 200 - i;
  199. rect.h = i;
  200. dstrect.h = i;
  201. }
  202. VIDEO_CopySurface(p, &rect, gpScreen, &dstrect);
  203. PAL_ApplyWave(gpScreen);
  204. if (g_wCurEffectSprite != 0)
  205. {
  206. int f = SDL_GetTicks() / 150;
  207. PAL_RLEBlitToSurface(PAL_SpriteGetFrame(bufSprite, f % PAL_SpriteGetNumFrames(bufSprite)),
  208. gpScreen, PAL_XY(0, 0));
  209. }
  210. VIDEO_UpdateScreen(NULL);
  211. if (gpGlobals->fNeedToFadeIn)
  212. {
  213. PAL_FadeIn(gpGlobals->wNumPalette, gpGlobals->fNightPalette, 1);
  214. gpGlobals->fNeedToFadeIn = FALSE;
  215. VIDEO_UpdateSurfacePalette(p);
  216. }
  217. UTIL_Delay(800 / wScrollSpeed);
  218. }
  219. VIDEO_CopyEntireSurface(p, gpScreen);
  220. VIDEO_FreeSurface(p);
  221. VIDEO_UpdateScreen(NULL);
  222. }
  223. VOID
  224. PAL_EndingAnimation(
  225. VOID
  226. )
  227. /*++
  228. Purpose:
  229. Show the ending animation.
  230. Parameters:
  231. None.
  232. Return value:
  233. None.
  234. --*/
  235. {
  236. LPBYTE buf;
  237. LPBYTE bufGirl;
  238. SDL_Surface *pUpper;
  239. SDL_Surface *pLower;
  240. SDL_Rect srcrect, dstrect;
  241. int yPosGirl = 180;
  242. int i;
  243. buf = (LPBYTE)UTIL_calloc(1, 64000);
  244. bufGirl = (LPBYTE)UTIL_calloc(1, 6000);
  245. pUpper = VIDEO_CreateCompatibleSurface(gpScreen);
  246. pLower = VIDEO_CreateCompatibleSurface(gpScreen);
  247. PAL_MKFDecompressChunk(buf, 64000, gConfig.fIsWIN95 ? 69 : 61, gpGlobals->f.fpFBP);
  248. PAL_FBPBlitToSurface(buf, pUpper);
  249. PAL_MKFDecompressChunk(buf, 64000, gConfig.fIsWIN95 ? 70 : 62, gpGlobals->f.fpFBP);
  250. PAL_FBPBlitToSurface(buf, pLower);
  251. PAL_MKFDecompressChunk(buf, 64000, 571, gpGlobals->f.fpMGO);
  252. PAL_MKFDecompressChunk(bufGirl, 6000, 572, gpGlobals->f.fpMGO);
  253. srcrect.x = 0;
  254. dstrect.x = 0;
  255. srcrect.w = 320;
  256. dstrect.w = 320;
  257. gpGlobals->wScreenWave = 2;
  258. for (i = 0; i < 400; i++)
  259. {
  260. //
  261. // Draw the background
  262. //
  263. srcrect.y = 0;
  264. srcrect.h = 200 - i / 2;
  265. dstrect.y = i / 2;
  266. dstrect.h = 200 - i / 2;
  267. VIDEO_CopySurface(pLower, &srcrect, gpScreen, &dstrect);
  268. srcrect.y = 200 - i / 2;
  269. srcrect.h = i / 2;
  270. dstrect.y = 0;
  271. dstrect.h = i / 2;
  272. VIDEO_CopySurface(pUpper, &srcrect, gpScreen, &dstrect);
  273. PAL_ApplyWave(gpScreen);
  274. //
  275. // Draw the beast
  276. //
  277. PAL_RLEBlitToSurface(PAL_SpriteGetFrame(buf, 0), gpScreen, PAL_XY(0, -400 + i));
  278. PAL_RLEBlitToSurface(PAL_SpriteGetFrame(buf, 1), gpScreen, PAL_XY(0, -200 + i));
  279. //
  280. // Draw the girl
  281. //
  282. yPosGirl -= i & 1;
  283. if (yPosGirl < 80)
  284. {
  285. yPosGirl = 80;
  286. }
  287. PAL_RLEBlitToSurface(PAL_SpriteGetFrame(bufGirl, (SDL_GetTicks() / 50) % 4),
  288. gpScreen, PAL_XY(220, yPosGirl));
  289. //
  290. // Update the screen
  291. //
  292. VIDEO_UpdateScreen(NULL);
  293. if (gpGlobals->fNeedToFadeIn)
  294. {
  295. PAL_FadeIn(gpGlobals->wNumPalette, gpGlobals->fNightPalette, 1);
  296. gpGlobals->fNeedToFadeIn = FALSE;
  297. VIDEO_UpdateSurfacePalette(pUpper);
  298. VIDEO_UpdateSurfacePalette(pLower);
  299. }
  300. UTIL_Delay(50);
  301. }
  302. gpGlobals->wScreenWave = 0;
  303. VIDEO_FreeSurface(pUpper);
  304. VIDEO_FreeSurface(pLower);
  305. free(buf);
  306. free(bufGirl);
  307. }
  308. VOID
  309. PAL_EndingScreen(
  310. VOID
  311. )
  312. /*++
  313. Purpose:
  314. Show the ending screen for Win95 version.
  315. Parameters:
  316. None.
  317. Return value:
  318. None.
  319. --*/
  320. {
  321. //
  322. // Use AVI & WIN95's music if we can
  323. // Otherwise, simulate the ending of DOS version
  324. //
  325. BOOL avi_played = PAL_PlayAVI("4.avi");
  326. if (!(avi_played = PAL_PlayAVI("5.avi")))
  327. {
  328. BOOL win_music = AUDIO_PlayCDTrack(12);
  329. if (!win_music) AUDIO_PlayMusic(0x1a, TRUE, 0);
  330. PAL_RNGPlay(gpGlobals->iCurPlayingRNG, 110, 150, 7);
  331. PAL_RNGPlay(gpGlobals->iCurPlayingRNG, 151, 999, 9);
  332. PAL_FadeOut(2);
  333. if (!win_music) AUDIO_PlayMusic(0x19, TRUE, 0);
  334. PAL_ShowFBP(75, 0);
  335. PAL_FadeIn(5, FALSE, 1);
  336. PAL_ScrollFBP(74, 0xf, TRUE);
  337. PAL_FadeOut(1);
  338. SDL_FillRect(gpScreen, NULL, 0);
  339. gpGlobals->wNumPalette = 4;
  340. gpGlobals->fNeedToFadeIn = TRUE;
  341. PAL_EndingAnimation();
  342. if (!win_music) AUDIO_PlayMusic(0, FALSE, 2);
  343. PAL_ColorFade(7, 15, FALSE);
  344. if (!win_music && !AUDIO_PlayCDTrack(2))
  345. {
  346. AUDIO_PlayMusic(0x11, TRUE, 0);
  347. }
  348. SDL_FillRect(gpScreen, NULL, 0);
  349. PAL_SetPalette(0, FALSE);
  350. PAL_RNGPlay(0xb, 0, 999, 7);
  351. PAL_FadeOut(2);
  352. SDL_FillRect(gpScreen, NULL, 0);
  353. gpGlobals->wNumPalette = 8;
  354. gpGlobals->fNeedToFadeIn = TRUE;
  355. PAL_RNGPlay(10, 0, 999, 6);
  356. PAL_EndingSetEffectSprite(0);
  357. PAL_ShowFBP(77, 10);
  358. VIDEO_BackupScreen(gpScreen);
  359. PAL_EndingSetEffectSprite(0x27b);
  360. PAL_ShowFBP(76, 7);
  361. PAL_SetPalette(5, FALSE);
  362. PAL_ShowFBP(73, 7);
  363. PAL_ScrollFBP(72, 0xf, TRUE);
  364. PAL_ShowFBP(71, 7);
  365. PAL_ShowFBP(68, 7);
  366. PAL_EndingSetEffectSprite(0);
  367. PAL_ShowFBP(68, 6);
  368. PAL_WaitForKey(0);
  369. AUDIO_PlayMusic(0, FALSE, 1);
  370. UTIL_Delay(500);
  371. }
  372. if (!PAL_PlayAVI("6.avi"))
  373. {
  374. if (avi_played)
  375. {
  376. gpGlobals->fNeedToFadeIn = FALSE;
  377. PAL_SetPalette(5, FALSE);
  378. PAL_EndingSetEffectSprite(0);
  379. }
  380. if (!AUDIO_PlayCDTrack(13))
  381. {
  382. AUDIO_PlayMusic(9, TRUE, 0);
  383. }
  384. PAL_ScrollFBP(67, 0xf, TRUE);
  385. PAL_ScrollFBP(66, 0xf, TRUE);
  386. PAL_ScrollFBP(65, 0xf, TRUE);
  387. PAL_ScrollFBP(64, 0xf, TRUE);
  388. PAL_ScrollFBP(63, 0xf, TRUE);
  389. PAL_ScrollFBP(62, 0xf, TRUE);
  390. PAL_ScrollFBP(61, 0xf, TRUE);
  391. PAL_ScrollFBP(60, 0xf, TRUE);
  392. PAL_ScrollFBP(59, 0xf, TRUE);
  393. AUDIO_PlayMusic(0, FALSE, 6);
  394. PAL_FadeOut(3);
  395. }
  396. }