video.c 20 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037
  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. // This file is part of SDLPAL.
  7. //
  8. // SDLPAL is free software: you can redistribute it and/or modify
  9. // it under the terms of the GNU General Public License as published by
  10. // the Free Software Foundation, either version 3 of the License, or
  11. // (at your option) any later version.
  12. //
  13. // This program is distributed in the hope that it will be useful,
  14. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. // GNU General Public License for more details.
  17. //
  18. // You should have received a copy of the GNU General Public License
  19. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  20. //
  21. #include "main.h"
  22. // Screen buffer
  23. SDL_Surface *gpScreen = NULL;
  24. // Backup screen buffer
  25. SDL_Surface *gpScreenBak = NULL;
  26. // The real screen surface
  27. #if SDL_VERSION_ATLEAST(2,0,0)
  28. static SDL_Window *gpWindow = NULL;
  29. static SDL_Renderer *gpRenderer = NULL;
  30. #else
  31. static SDL_Surface *gpScreenReal = NULL;
  32. #endif
  33. #if (defined (__SYMBIAN32__) && !defined (__S60_5X__)) || defined (PSP) || defined (GEKKO)
  34. static BOOL bScaleScreen = FALSE;
  35. #else
  36. static BOOL bScaleScreen = TRUE;
  37. #endif
  38. // Initial screen size
  39. static WORD g_wInitialWidth = 640;
  40. static WORD g_wInitialHeight = 400;
  41. // Shake times and level
  42. static WORD g_wShakeTime = 0;
  43. static WORD g_wShakeLevel = 0;
  44. INT
  45. #ifdef GEKKO // Rikku2000: Crash on compile, allready define on WIISDK
  46. VIDEO_Init_GEKKO(
  47. #else
  48. VIDEO_Init(
  49. #endif
  50. WORD wScreenWidth,
  51. WORD wScreenHeight,
  52. BOOL fFullScreen
  53. )
  54. /*++
  55. Purpose:
  56. Initialze the video subsystem.
  57. Parameters:
  58. [IN] wScreenWidth - width of the screen.
  59. [IN] wScreenHeight - height of the screen.
  60. [IN] fFullScreen - TRUE to use full screen mode, FALSE to use windowed mode.
  61. Return value:
  62. 0 = success, -1 = fail to create the screen surface,
  63. -2 = fail to create screen buffer.
  64. --*/
  65. {
  66. g_wInitialWidth = wScreenWidth;
  67. g_wInitialHeight = wScreenHeight;
  68. #if SDL_VERSION_ATLEAST(2,0,0)
  69. //
  70. // Before we can render anything, we need a window and a renderer.
  71. //
  72. gpWindow = SDL_CreateWindow("Pal",
  73. SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 400,
  74. SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
  75. if (gpWindow == NULL)
  76. {
  77. return -1;
  78. }
  79. gpRenderer = SDL_CreateRenderer(gpWindow, -1, SDL_RENDERER_ACCELERATED);
  80. if (gpRenderer == NULL)
  81. {
  82. return -1;
  83. }
  84. //
  85. // Create the screen buffer and the backup screen buffer.
  86. //
  87. gpScreen = SDL_CreateRGBSurface(SDL_SWSURFACE, 320, 200, 8, 0, 0, 0, 0);
  88. gpScreenBak = SDL_CreateRGBSurface(SDL_SWSURFACE, 320, 200, 8, 0, 0, 0, 0);
  89. //
  90. // Failed?
  91. //
  92. if (gpScreen == NULL || gpScreenBak == NULL)
  93. {
  94. if (gpScreen != NULL)
  95. {
  96. SDL_FreeSurface(gpScreen);
  97. gpScreen = NULL;
  98. }
  99. if (gpScreenBak != NULL)
  100. {
  101. SDL_FreeSurface(gpScreenBak);
  102. gpScreenBak = NULL;
  103. }
  104. SDL_DestroyRenderer(gpRenderer);
  105. gpRenderer = NULL;
  106. SDL_DestroyWindow(gpWindow);
  107. gpWindow = NULL;
  108. return -2;
  109. }
  110. #else
  111. //
  112. // Create the screen surface.
  113. //
  114. #if defined (NDS)
  115. gpScreenReal = SDL_SetVideoMode(293, 196, 8, SDL_SWSURFACE | SDL_FULLSCREEN);
  116. #elif defined (__SYMBIAN32__)
  117. #ifdef __S60_5X__
  118. gpScreenReal = SDL_SetVideoMode(640, 360, 8,
  119. SDL_SWSURFACE | (fFullScreen ? SDL_FULLSCREEN : 0));
  120. #else
  121. gpScreenReal = SDL_SetVideoMode(320, 240, 8,
  122. SDL_SWSURFACE | (fFullScreen ? SDL_FULLSCREEN : 0));
  123. #endif
  124. #elif defined (GEKKO)
  125. gpScreenReal = SDL_SetVideoMode(640, 480, 8,
  126. SDL_SWSURFACE | (fFullScreen ? SDL_FULLSCREEN : 0));
  127. #elif defined (PSP)
  128. gpScreenReal = SDL_SetVideoMode(320, 240, 8, SDL_SWSURFACE | SDL_FULLSCREEN);
  129. #else
  130. gpScreenReal = SDL_SetVideoMode(wScreenWidth, wScreenHeight, 8,
  131. SDL_HWSURFACE | SDL_RESIZABLE | (fFullScreen ? SDL_FULLSCREEN : 0));
  132. #endif
  133. if (gpScreenReal == NULL)
  134. {
  135. //
  136. // Fall back to 640x480 software mode.
  137. //
  138. gpScreenReal = SDL_SetVideoMode(640, 480, 8,
  139. SDL_SWSURFACE | (fFullScreen ? SDL_FULLSCREEN : 0));
  140. }
  141. //
  142. // Still fail?
  143. //
  144. if (gpScreenReal == NULL)
  145. {
  146. return -1;
  147. }
  148. //
  149. // Create the screen buffer and the backup screen buffer.
  150. //
  151. gpScreen = SDL_CreateRGBSurface(gpScreenReal->flags & ~SDL_HWSURFACE, 320, 200, 8,
  152. gpScreenReal->format->Rmask, gpScreenReal->format->Gmask,
  153. gpScreenReal->format->Bmask, gpScreenReal->format->Amask);
  154. gpScreenBak = SDL_CreateRGBSurface(gpScreenReal->flags & ~SDL_HWSURFACE, 320, 200, 8,
  155. gpScreenReal->format->Rmask, gpScreenReal->format->Gmask,
  156. gpScreenReal->format->Bmask, gpScreenReal->format->Amask);
  157. //
  158. // Failed?
  159. //
  160. if (gpScreen == NULL || gpScreenBak == NULL)
  161. {
  162. if (gpScreen != NULL)
  163. {
  164. SDL_FreeSurface(gpScreen);
  165. gpScreen = NULL;
  166. }
  167. if (gpScreenBak != NULL)
  168. {
  169. SDL_FreeSurface(gpScreenBak);
  170. gpScreenBak = NULL;
  171. }
  172. SDL_FreeSurface(gpScreenReal);
  173. gpScreenReal = NULL;
  174. return -2;
  175. }
  176. #endif
  177. if (fFullScreen)
  178. {
  179. SDL_ShowCursor(FALSE);
  180. }
  181. return 0;
  182. }
  183. VOID
  184. VIDEO_Shutdown(
  185. VOID
  186. )
  187. /*++
  188. Purpose:
  189. Shutdown the video subsystem.
  190. Parameters:
  191. None.
  192. Return value:
  193. None.
  194. --*/
  195. {
  196. if (gpScreen != NULL)
  197. {
  198. SDL_FreeSurface(gpScreen);
  199. }
  200. gpScreen = NULL;
  201. if (gpScreenBak != NULL)
  202. {
  203. SDL_FreeSurface(gpScreenBak);
  204. }
  205. gpScreenBak = NULL;
  206. #if SDL_VERSION_ATLEAST(2,0,0)
  207. if (gpRenderer)
  208. {
  209. SDL_DestroyRenderer(gpRenderer);
  210. }
  211. gpRenderer = NULL;
  212. if (gpWindow)
  213. {
  214. SDL_DestroyWindow(gpWindow);
  215. }
  216. gpWindow = NULL;
  217. #else
  218. if (gpScreenReal != NULL)
  219. {
  220. SDL_FreeSurface(gpScreenReal);
  221. }
  222. gpScreenReal = NULL;
  223. #endif
  224. }
  225. VOID
  226. VIDEO_UpdateScreen(
  227. const SDL_Rect *lpRect
  228. )
  229. /*++
  230. Purpose:
  231. Update the screen area specified by lpRect.
  232. Parameters:
  233. [IN] lpRect - Screen area to update.
  234. Return value:
  235. None.
  236. --*/
  237. {
  238. #if SDL_VERSION_ATLEAST(2,0,0)
  239. // TODO
  240. SDL_Texture *pTexture = SDL_CreateTextureFromSurface(gpRenderer, gpScreen);
  241. SDL_RenderClear(gpRenderer);
  242. SDL_RenderCopy(gpRenderer, pTexture, NULL/*srcrect*/, NULL/*dstrect*/);
  243. SDL_RenderPresent(gpRenderer);
  244. SDL_DestroyTexture(pTexture);
  245. #else
  246. SDL_Rect srcrect, dstrect;
  247. short offset = 240 - 200;
  248. short screenRealHeight = gpScreenReal->h;
  249. short screenRealY = 0;
  250. //
  251. // Lock surface if needed
  252. //
  253. if (SDL_MUSTLOCK(gpScreenReal))
  254. {
  255. if (SDL_LockSurface(gpScreenReal) < 0)
  256. return;
  257. }
  258. if (!bScaleScreen)
  259. {
  260. screenRealHeight -= offset;
  261. screenRealY = offset / 2;
  262. }
  263. if (lpRect != NULL)
  264. {
  265. dstrect.x = (SHORT)((INT)(lpRect->x) * gpScreenReal->w / gpScreen->w);
  266. dstrect.y = (SHORT)((INT)(screenRealY + lpRect->y) * screenRealHeight / gpScreen->h);
  267. dstrect.w = (WORD)((DWORD)(lpRect->w) * gpScreenReal->w / gpScreen->w);
  268. dstrect.h = (WORD)((DWORD)(lpRect->h) * screenRealHeight / gpScreen->h);
  269. SDL_SoftStretch(gpScreen, (SDL_Rect *)lpRect, gpScreenReal, &dstrect);
  270. if (SDL_MUSTLOCK(gpScreenReal))
  271. {
  272. SDL_UnlockSurface(gpScreenReal);
  273. }
  274. SDL_UpdateRect(gpScreenReal, dstrect.x, dstrect.y, dstrect.w, dstrect.h);
  275. }
  276. else if (g_wShakeTime != 0)
  277. {
  278. //
  279. // Shake the screen
  280. //
  281. srcrect.x = 0;
  282. srcrect.y = 0;
  283. srcrect.w = 320;
  284. srcrect.h = 200 - g_wShakeLevel;
  285. dstrect.x = 0;
  286. dstrect.y = screenRealY;
  287. dstrect.w = 320 * gpScreenReal->w / gpScreen->w;
  288. dstrect.h = (200 - g_wShakeLevel) * screenRealHeight / gpScreen->h;
  289. if (g_wShakeTime & 1)
  290. {
  291. srcrect.y = g_wShakeLevel;
  292. }
  293. else
  294. {
  295. dstrect.y = (screenRealY + g_wShakeLevel) * screenRealHeight / gpScreen->h;
  296. }
  297. SDL_SoftStretch(gpScreen, &srcrect, gpScreenReal, &dstrect);
  298. if (g_wShakeTime & 1)
  299. {
  300. dstrect.y = (screenRealY + screenRealHeight - g_wShakeLevel) * screenRealHeight / gpScreen->h;
  301. }
  302. else
  303. {
  304. dstrect.y = screenRealY;
  305. }
  306. dstrect.h = g_wShakeLevel * screenRealHeight / gpScreen->h;
  307. SDL_FillRect(gpScreenReal, &dstrect, 0);
  308. if (SDL_MUSTLOCK(gpScreenReal))
  309. {
  310. SDL_UnlockSurface(gpScreenReal);
  311. }
  312. SDL_UpdateRect(gpScreenReal, 0, 0, gpScreenReal->w, gpScreenReal->h);
  313. g_wShakeTime--;
  314. }
  315. else
  316. {
  317. dstrect.x = 0;
  318. dstrect.y = screenRealY;
  319. dstrect.w = gpScreenReal->w;
  320. dstrect.h = screenRealHeight;
  321. SDL_SoftStretch(gpScreen, NULL, gpScreenReal, &dstrect);
  322. if (SDL_MUSTLOCK(gpScreenReal))
  323. {
  324. SDL_UnlockSurface(gpScreenReal);
  325. }
  326. SDL_UpdateRect(gpScreenReal, 0, 0, gpScreenReal->w, gpScreenReal->h);
  327. }
  328. #endif
  329. }
  330. VOID
  331. VIDEO_SetPalette(
  332. SDL_Color rgPalette[256]
  333. )
  334. /*++
  335. Purpose:
  336. Set the palette of the screen.
  337. Parameters:
  338. [IN] rgPalette - array of 256 colors.
  339. Return value:
  340. None.
  341. --*/
  342. {
  343. #if SDL_VERSION_ATLEAST(2,0,0)
  344. int i;
  345. SDL_Palette *palette = SDL_AllocPalette(256);
  346. if (palette == NULL)
  347. {
  348. return;
  349. }
  350. for (i = 0; i < 256; i++)
  351. {
  352. palette->colors[i] = rgPalette[i];
  353. }
  354. SDL_SetSurfacePalette(gpScreen, palette);
  355. SDL_SetSurfacePalette(gpScreenBak, palette);
  356. #else
  357. SDL_SetPalette(gpScreen, SDL_LOGPAL | SDL_PHYSPAL, rgPalette, 0, 256);
  358. SDL_SetPalette(gpScreenReal, SDL_LOGPAL | SDL_PHYSPAL, rgPalette, 0, 256);
  359. #if (defined (__SYMBIAN32__))
  360. {
  361. static UINT32 time = 0;
  362. if (SDL_GetTicks() - time > 50)
  363. {
  364. SDL_UpdateRect(gpScreenReal, 0, 0, gpScreenReal->w, gpScreenReal->h);
  365. time = SDL_GetTicks();
  366. }
  367. }
  368. #endif
  369. #endif
  370. }
  371. VOID
  372. VIDEO_Resize(
  373. INT w,
  374. INT h
  375. )
  376. /*++
  377. Purpose:
  378. This function is called when user resized the window.
  379. Parameters:
  380. [IN] w - width of the window after resizing.
  381. [IN] h - height of the window after resizing.
  382. Return value:
  383. None.
  384. --*/
  385. {
  386. #if SDL_VERSION_ATLEAST(2,0,0)
  387. // TODO
  388. #else
  389. DWORD flags;
  390. PAL_LARGE SDL_Color palette[256];
  391. int i;
  392. //
  393. // Get the original palette.
  394. //
  395. for (i = 0; i < gpScreenReal->format->palette->ncolors; i++)
  396. {
  397. palette[i] = gpScreenReal->format->palette->colors[i];
  398. }
  399. //
  400. // Create the screen surface.
  401. //
  402. flags = gpScreenReal->flags;
  403. SDL_FreeSurface(gpScreenReal);
  404. gpScreenReal = SDL_SetVideoMode(w, h, 8, flags);
  405. if (gpScreenReal == NULL)
  406. {
  407. #ifdef __SYMBIAN32__
  408. #ifdef __S60_5X__
  409. gpScreenReal = SDL_SetVideoMode(640, 360, 8, SDL_SWSURFACE);
  410. #else
  411. gpScreenReal = SDL_SetVideoMode(320, 240, 8, SDL_SWSURFACE);
  412. #endif
  413. #else
  414. //
  415. // Fall back to 640x480 software windowed mode.
  416. //
  417. gpScreenReal = SDL_SetVideoMode(640, 480, 8, SDL_SWSURFACE);
  418. #endif
  419. }
  420. SDL_SetPalette(gpScreenReal, SDL_PHYSPAL | SDL_LOGPAL, palette, 0, i);
  421. VIDEO_UpdateScreen(NULL);
  422. #endif
  423. }
  424. SDL_Color *
  425. VIDEO_GetPalette(
  426. VOID
  427. )
  428. /*++
  429. Purpose:
  430. Get the current palette of the screen.
  431. Parameters:
  432. None.
  433. Return value:
  434. Pointer to the current palette.
  435. --*/
  436. {
  437. #if SDL_VERSION_ATLEAST(2,0,0)
  438. return gpScreen->format->palette->colors;
  439. #else
  440. return gpScreenReal->format->palette->colors;
  441. #endif
  442. }
  443. VOID
  444. VIDEO_ToggleScaleScreen(
  445. VOID
  446. )
  447. /*++
  448. Purpose:
  449. Toggle scalescreen mode.
  450. Parameters:
  451. None.
  452. Return value:
  453. None.
  454. --*/
  455. {
  456. #ifdef __SYMBIAN32__
  457. bScaleScreen = !bScaleScreen;
  458. VIDEO_Resize(320, 240);
  459. VIDEO_UpdateScreen(NULL);
  460. #endif
  461. }
  462. VOID
  463. VIDEO_ToggleFullscreen(
  464. VOID
  465. )
  466. /*++
  467. Purpose:
  468. Toggle fullscreen mode.
  469. Parameters:
  470. None.
  471. Return value:
  472. None.
  473. --*/
  474. {
  475. #if SDL_VERSION_ATLEAST(2,0,0)
  476. // TODO
  477. #else
  478. DWORD flags;
  479. PAL_LARGE SDL_Color palette[256];
  480. int i;
  481. //
  482. // Get the original palette.
  483. //
  484. for (i = 0; i < gpScreenReal->format->palette->ncolors; i++)
  485. {
  486. palette[i] = gpScreenReal->format->palette->colors[i];
  487. }
  488. //
  489. // Get the flags of the original screen surface
  490. //
  491. flags = gpScreenReal->flags;
  492. if (flags & SDL_FULLSCREEN)
  493. {
  494. //
  495. // Already in fullscreen mode. Remove the fullscreen flag.
  496. //
  497. flags &= ~SDL_FULLSCREEN;
  498. flags |= SDL_RESIZABLE;
  499. SDL_ShowCursor(TRUE);
  500. }
  501. else
  502. {
  503. //
  504. // Not in fullscreen mode. Set the fullscreen flag.
  505. //
  506. flags |= SDL_FULLSCREEN;
  507. SDL_ShowCursor(FALSE);
  508. }
  509. //
  510. // Free the original screen surface
  511. //
  512. SDL_FreeSurface(gpScreenReal);
  513. //
  514. // ... and create a new one
  515. //
  516. if (g_wInitialWidth == 640 && g_wInitialHeight == 400 && (flags & SDL_FULLSCREEN))
  517. {
  518. gpScreenReal = SDL_SetVideoMode(640, 480, 8, flags);
  519. }
  520. else if (g_wInitialWidth == 640 && g_wInitialHeight == 480 && !(flags & SDL_FULLSCREEN))
  521. {
  522. gpScreenReal = SDL_SetVideoMode(640, 400, 8, flags);
  523. }
  524. else
  525. {
  526. gpScreenReal = SDL_SetVideoMode(g_wInitialWidth, g_wInitialHeight, 8, flags);
  527. }
  528. VIDEO_SetPalette(palette);
  529. //
  530. // Update the screen
  531. //
  532. VIDEO_UpdateScreen(NULL);
  533. #endif
  534. }
  535. VOID
  536. VIDEO_SaveScreenshot(
  537. VOID
  538. )
  539. /*++
  540. Purpose:
  541. Save the screenshot of current screen to a BMP file.
  542. Parameters:
  543. None.
  544. Return value:
  545. None.
  546. --*/
  547. {
  548. int iNumBMP = 0;
  549. FILE *fp;
  550. //
  551. // Find a usable BMP filename.
  552. //
  553. for (iNumBMP = 0; iNumBMP <= 9999; iNumBMP++)
  554. {
  555. fp = fopen(va("%sscrn%.4d.bmp", PAL_PREFIX, iNumBMP), "rb");
  556. if (fp == NULL)
  557. {
  558. break;
  559. }
  560. fclose(fp);
  561. }
  562. if (iNumBMP > 9999)
  563. {
  564. return;
  565. }
  566. //
  567. // Save the screenshot.
  568. //
  569. #if SDL_VERSION_ATLEAST(2,0,0)
  570. SDL_SaveBMP(gpScreen, va("%sscrn%.4d.bmp", PAL_PREFIX, iNumBMP));
  571. #else
  572. SDL_SaveBMP(gpScreenReal, va("%sscrn%.4d.bmp", PAL_PREFIX, iNumBMP));
  573. #endif
  574. }
  575. VOID
  576. VIDEO_BackupScreen(
  577. VOID
  578. )
  579. /*++
  580. Purpose:
  581. Backup the screen buffer.
  582. Parameters:
  583. None.
  584. Return value:
  585. None.
  586. --*/
  587. {
  588. SDL_BlitSurface(gpScreen, NULL, gpScreenBak, NULL);
  589. }
  590. VOID
  591. VIDEO_RestoreScreen(
  592. VOID
  593. )
  594. /*++
  595. Purpose:
  596. Restore the screen buffer which has been saved with VIDEO_BackupScreen().
  597. Parameters:
  598. None.
  599. Return value:
  600. None.
  601. --*/
  602. {
  603. SDL_BlitSurface(gpScreenBak, NULL, gpScreen, NULL);
  604. }
  605. VOID
  606. VIDEO_ShakeScreen(
  607. WORD wShakeTime,
  608. WORD wShakeLevel
  609. )
  610. /*++
  611. Purpose:
  612. Set the screen shake time and level.
  613. Parameters:
  614. [IN] wShakeTime - how many times should we shake the screen.
  615. [IN] wShakeLevel - level of shaking.
  616. Return value:
  617. None.
  618. --*/
  619. {
  620. g_wShakeTime = wShakeTime;
  621. g_wShakeLevel = wShakeLevel;
  622. }
  623. VOID
  624. VIDEO_SwitchScreen(
  625. WORD wSpeed
  626. )
  627. /*++
  628. Purpose:
  629. Switch the screen from the backup screen buffer to the current screen buffer.
  630. NOTE: This will destroy the backup buffer.
  631. Parameters:
  632. [IN] wSpeed - speed of fading (the larger value, the slower).
  633. Return value:
  634. None.
  635. --*/
  636. {
  637. #if SDL_VERSION_ATLEAST(2,0,0)
  638. // TODO
  639. #else
  640. int i, j;
  641. const int rgIndex[6] = {0, 3, 1, 5, 2, 4};
  642. SDL_Rect dstrect;
  643. short offset = 240 - 200;
  644. short screenRealHeight = gpScreenReal->h;
  645. short screenRealY = 0;
  646. if (!bScaleScreen)
  647. {
  648. screenRealHeight -= offset;
  649. screenRealY = offset / 2;
  650. }
  651. wSpeed++;
  652. wSpeed *= 10;
  653. for (i = 0; i < 6; i++)
  654. {
  655. for (j = rgIndex[i]; j < gpScreen->pitch * gpScreen->h; j += 6)
  656. {
  657. ((LPBYTE)(gpScreenBak->pixels))[j] = ((LPBYTE)(gpScreen->pixels))[j];
  658. }
  659. //
  660. // Draw the backup buffer to the screen
  661. //
  662. dstrect.x = 0;
  663. dstrect.y = screenRealY;
  664. dstrect.w = gpScreenReal->w;
  665. dstrect.h = screenRealHeight;
  666. SDL_SoftStretch(gpScreenBak, NULL, gpScreenReal, &dstrect);
  667. SDL_UpdateRect(gpScreenReal, 0, 0, gpScreenReal->w, gpScreenReal->h);
  668. UTIL_Delay(wSpeed);
  669. }
  670. #endif
  671. }
  672. VOID
  673. VIDEO_FadeScreen(
  674. WORD wSpeed
  675. )
  676. /*++
  677. Purpose:
  678. Fade from the backup screen buffer to the current screen buffer.
  679. NOTE: This will destroy the backup buffer.
  680. Parameters:
  681. [IN] wSpeed - speed of fading (the larger value, the slower).
  682. Return value:
  683. None.
  684. --*/
  685. {
  686. #if SDL_VERSION_ATLEAST(2,0,0)
  687. // TODO
  688. #else
  689. int i, j, k;
  690. DWORD time;
  691. BYTE a, b;
  692. const int rgIndex[6] = {0, 3, 1, 5, 2, 4};
  693. SDL_Rect dstrect;
  694. short offset = 240 - 200;
  695. short screenRealHeight = gpScreenReal->h;
  696. short screenRealY = 0;
  697. //
  698. // Lock surface if needed
  699. //
  700. if (SDL_MUSTLOCK(gpScreenReal))
  701. {
  702. if (SDL_LockSurface(gpScreenReal) < 0)
  703. return;
  704. }
  705. if (!bScaleScreen)
  706. {
  707. screenRealHeight -= offset;
  708. screenRealY = offset / 2;
  709. }
  710. time = SDL_GetTicks();
  711. wSpeed++;
  712. wSpeed *= 10;
  713. for (i = 0; i < 12; i++)
  714. {
  715. for (j = 0; j < 6; j++)
  716. {
  717. PAL_ProcessEvent();
  718. while (SDL_GetTicks() <= time)
  719. {
  720. PAL_ProcessEvent();
  721. SDL_Delay(5);
  722. }
  723. time = SDL_GetTicks() + wSpeed;
  724. //
  725. // Blend the pixels in the 2 buffers, and put the result into the
  726. // backup buffer
  727. //
  728. for (k = rgIndex[j]; k < gpScreen->pitch * gpScreen->h; k += 6)
  729. {
  730. a = ((LPBYTE)(gpScreen->pixels))[k];
  731. b = ((LPBYTE)(gpScreenBak->pixels))[k];
  732. if (i > 0)
  733. {
  734. if ((a & 0x0F) > (b & 0x0F))
  735. {
  736. b++;
  737. }
  738. else if ((a & 0x0F) < (b & 0x0F))
  739. {
  740. b--;
  741. }
  742. }
  743. ((LPBYTE)(gpScreenBak->pixels))[k] = ((a & 0xF0) | (b & 0x0F));
  744. }
  745. //
  746. // Draw the backup buffer to the screen
  747. //
  748. if (g_wShakeTime != 0)
  749. {
  750. //
  751. // Shake the screen
  752. //
  753. SDL_Rect srcrect, dstrect;
  754. srcrect.x = 0;
  755. srcrect.y = 0;
  756. srcrect.w = 320;
  757. srcrect.h = 200 - g_wShakeLevel;
  758. dstrect.x = 0;
  759. dstrect.y = screenRealY;
  760. dstrect.w = 320 * gpScreenReal->w / gpScreen->w;
  761. dstrect.h = (200 - g_wShakeLevel) * screenRealHeight / gpScreen->h;
  762. if (g_wShakeTime & 1)
  763. {
  764. srcrect.y = g_wShakeLevel;
  765. }
  766. else
  767. {
  768. dstrect.y = (screenRealY + g_wShakeLevel) * screenRealHeight / gpScreen->h;
  769. }
  770. SDL_SoftStretch(gpScreenBak, &srcrect, gpScreenReal, &dstrect);
  771. if (g_wShakeTime & 1)
  772. {
  773. dstrect.y = (screenRealY + screenRealHeight - g_wShakeLevel) * screenRealHeight / gpScreen->h;
  774. }
  775. else
  776. {
  777. dstrect.y = screenRealY;
  778. }
  779. dstrect.h = g_wShakeLevel * screenRealHeight / gpScreen->h;
  780. SDL_FillRect(gpScreenReal, &dstrect, 0);
  781. SDL_UpdateRect(gpScreenReal, 0, 0, gpScreenReal->w, gpScreenReal->h);
  782. g_wShakeTime--;
  783. }
  784. else
  785. {
  786. dstrect.x = 0;
  787. dstrect.y = screenRealY;
  788. dstrect.w = gpScreenReal->w;
  789. dstrect.h = screenRealHeight;
  790. SDL_SoftStretch(gpScreenBak, NULL, gpScreenReal, &dstrect);
  791. SDL_UpdateRect(gpScreenReal, 0, 0, gpScreenReal->w, gpScreenReal->h);
  792. }
  793. }
  794. }
  795. if (SDL_MUSTLOCK(gpScreenReal))
  796. {
  797. SDL_UnlockSurface(gpScreenReal);
  798. }
  799. //
  800. // Draw the result buffer to the screen as the final step
  801. //
  802. VIDEO_UpdateScreen(NULL);
  803. #endif
  804. }
  805. #if SDL_VERSION_ATLEAST(2,0,0)
  806. /*++
  807. Purpose:
  808. Set the caption of the window. For compatibility with SDL2 only.
  809. Parameters:
  810. [IN] lpszCaption - the new caption of the window.
  811. [IN] lpReserved - not used, for compatibility only.
  812. Return value:
  813. None.
  814. --*/
  815. VOID
  816. SDL_WM_SetCaption(
  817. LPCSTR lpszCaption,
  818. LPVOID lpReserved
  819. )
  820. {
  821. if (gpWindow != NULL)
  822. {
  823. SDL_SetWindowTitle(gpWindow, lpszCaption);
  824. }
  825. }
  826. #endif