video.c 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264
  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. #if SDL_VERSION_ATLEAST(2,0,0)
  27. SDL_Window *gpWindow = NULL;
  28. static SDL_Renderer *gpRenderer = NULL;
  29. static SDL_Texture *gpTexture = NULL;
  30. static SDL_Texture *gpTouchOverlay = NULL;
  31. #ifdef __WINPHONE__
  32. static SDL_Texture *gpBackKeyMessage = NULL;
  33. #endif
  34. #endif
  35. // The real screen surface
  36. static SDL_Surface *gpScreenReal = NULL;
  37. volatile BOOL g_bRenderPaused = FALSE;
  38. #if (defined (__SYMBIAN32__) && !defined (__S60_5X__)) || defined (PSP) || defined (GEKKO)
  39. static BOOL bScaleScreen = FALSE;
  40. #else
  41. static BOOL bScaleScreen = TRUE;
  42. #endif
  43. // Initial screen size
  44. static WORD g_wInitialWidth = 640;
  45. static WORD g_wInitialHeight = 400;
  46. // Shake times and level
  47. static WORD g_wShakeTime = 0;
  48. static WORD g_wShakeLevel = 0;
  49. #if SDL_VERSION_ATLEAST(2, 0, 0)
  50. #define SDL_SoftStretch SDL_UpperBlit
  51. #endif
  52. INT
  53. #ifdef GEKKO // Rikku2000: Crash on compile, allready define on WIISDK
  54. VIDEO_Init_GEKKO(
  55. #else
  56. VIDEO_Init(
  57. #endif
  58. WORD wScreenWidth,
  59. WORD wScreenHeight,
  60. BOOL fFullScreen
  61. )
  62. /*++
  63. Purpose:
  64. Initialze the video subsystem.
  65. Parameters:
  66. [IN] wScreenWidth - width of the screen.
  67. [IN] wScreenHeight - height of the screen.
  68. [IN] fFullScreen - TRUE to use full screen mode, FALSE to use windowed mode.
  69. Return value:
  70. 0 = success, -1 = fail to create the screen surface,
  71. -2 = fail to create screen buffer.
  72. --*/
  73. {
  74. #if SDL_VERSION_ATLEAST(2,0,0)
  75. SDL_Surface *overlay;
  76. #endif
  77. g_wInitialWidth = wScreenWidth;
  78. g_wInitialHeight = wScreenHeight;
  79. #if SDL_VERSION_ATLEAST(2,0,0)
  80. //
  81. // Before we can render anything, we need a window and a renderer.
  82. //
  83. #if defined (__IOS__) || defined (__ANDROID__) || defined (__WINPHONE__)
  84. gpWindow = SDL_CreateWindow("Pal",
  85. SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, wScreenWidth, wScreenHeight,
  86. SDL_WINDOW_SHOWN);
  87. #else
  88. gpWindow = SDL_CreateWindow("Pal",
  89. SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, wScreenWidth, wScreenHeight,
  90. SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
  91. #endif
  92. if (gpWindow == NULL)
  93. {
  94. return -1;
  95. }
  96. gpRenderer = SDL_CreateRenderer(gpWindow, -1, SDL_RENDERER_ACCELERATED);
  97. if (gpRenderer == NULL)
  98. {
  99. return -1;
  100. }
  101. #if defined (__IOS__)
  102. SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0);
  103. SDL_GL_SetAttribute(SDL_GL_RETAINED_BACKING, 1);
  104. #endif
  105. //
  106. // Create the screen buffer and the backup screen buffer.
  107. //
  108. gpScreen = SDL_CreateRGBSurface(SDL_SWSURFACE, 320, 200, 8, 0, 0, 0, 0);
  109. gpScreenBak = SDL_CreateRGBSurface(SDL_SWSURFACE, 320, 200, 8, 0, 0, 0, 0);
  110. gpScreenReal = SDL_CreateRGBSurface(SDL_SWSURFACE, 320, 200, 32,
  111. 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000);
  112. //
  113. // Create texture for screen.
  114. //
  115. gpTexture = SDL_CreateTexture(gpRenderer, SDL_PIXELFORMAT_ARGB8888,
  116. SDL_TEXTUREACCESS_STREAMING, 320, 200);
  117. //
  118. // Failed?
  119. //
  120. if (gpScreen == NULL || gpScreenBak == NULL || gpScreenReal == NULL || gpTexture == NULL)
  121. {
  122. if (gpScreen != NULL)
  123. {
  124. SDL_FreeSurface(gpScreen);
  125. gpScreen = NULL;
  126. }
  127. if (gpScreenBak != NULL)
  128. {
  129. SDL_FreeSurface(gpScreenBak);
  130. gpScreenBak = NULL;
  131. }
  132. if (gpScreenReal != NULL)
  133. {
  134. SDL_FreeSurface(gpScreenReal);
  135. gpScreenReal = NULL;
  136. }
  137. if (gpTexture != NULL)
  138. {
  139. SDL_DestroyTexture(gpTexture);
  140. gpTexture = NULL;
  141. }
  142. SDL_DestroyRenderer(gpRenderer);
  143. gpRenderer = NULL;
  144. SDL_DestroyWindow(gpWindow);
  145. gpWindow = NULL;
  146. return -2;
  147. }
  148. //
  149. // Create texture for overlay.
  150. //
  151. overlay = SDL_LoadBMP(va("%s%s", PAL_PREFIX, "overlay.bmp"));
  152. if (overlay != NULL)
  153. {
  154. SDL_SetColorKey(overlay, SDL_RLEACCEL, SDL_MapRGB(overlay->format, 255, 0, 255));
  155. gpTouchOverlay = SDL_CreateTextureFromSurface(gpRenderer, overlay);
  156. SDL_SetTextureAlphaMod(gpTouchOverlay, 120);
  157. SDL_FreeSurface(overlay);
  158. }
  159. #ifdef __WINPHONE__
  160. {
  161. //
  162. // Totally ugly hack to satisfy M$'s silly requirements.
  163. // No need to understand this crap.
  164. //
  165. SDL_Color palette[256] = { 0 };
  166. SDL_Surface *p;
  167. palette[0].r = palette[0].g = palette[0].b = palette[0].a = 0;
  168. palette[1].r = palette[1].g = palette[1].b = palette[1].a = 255;
  169. SDL_FillRect(gpScreenBak, NULL, 0);
  170. VIDEO_SetPalette(palette);
  171. p = gpScreen;
  172. gpScreen = gpScreenBak;
  173. switch(gpGlobals->iCodePage)
  174. {
  175. case CP_BIG5:
  176. PAL_DrawText(L"\x518D\x6B21\x6309 Back \x7D50\x675F", PAL_XY(30, 30), 1, FALSE, FALSE);
  177. break;
  178. case CP_GBK:
  179. PAL_DrawText(L"\x518D\x6B21\x6309 Back \x7ED3\x675F", PAL_XY(30, 30), 1, FALSE, FALSE);
  180. break;
  181. case CP_SHIFTJIS:
  182. PAL_DrawText(L"Press Back again to end", PAL_XY(30, 30), 1, FALSE, FALSE); // TODO: Japanese string
  183. break;
  184. }
  185. gpScreen = p;
  186. gpBackKeyMessage = SDL_CreateTextureFromSurface(gpRenderer, gpScreenBak);
  187. SDL_FillRect(gpScreenBak, NULL, 0);
  188. }
  189. #endif
  190. #else
  191. //
  192. // Create the screen surface.
  193. //
  194. #if defined (NDS)
  195. gpScreenReal = SDL_SetVideoMode(293, 196, 8, SDL_SWSURFACE | SDL_FULLSCREEN);
  196. #elif defined (__SYMBIAN32__)
  197. #ifdef __S60_5X__
  198. gpScreenReal = SDL_SetVideoMode(640, 360, 8,
  199. SDL_SWSURFACE | (fFullScreen ? SDL_FULLSCREEN : 0));
  200. #else
  201. gpScreenReal = SDL_SetVideoMode(320, 240, 8,
  202. SDL_SWSURFACE | (fFullScreen ? SDL_FULLSCREEN : 0));
  203. #endif
  204. #elif defined (GEKKO)
  205. gpScreenReal = SDL_SetVideoMode(640, 480, 8,
  206. SDL_SWSURFACE | (fFullScreen ? SDL_FULLSCREEN : 0));
  207. #elif defined (PSP)
  208. gpScreenReal = SDL_SetVideoMode(320, 240, 8, SDL_SWSURFACE | SDL_FULLSCREEN);
  209. #else
  210. gpScreenReal = SDL_SetVideoMode(wScreenWidth, wScreenHeight, 8,
  211. SDL_HWSURFACE | SDL_RESIZABLE | (fFullScreen ? SDL_FULLSCREEN : 0));
  212. #endif
  213. if (gpScreenReal == NULL)
  214. {
  215. //
  216. // Fall back to 640x480 software mode.
  217. //
  218. gpScreenReal = SDL_SetVideoMode(640, 480, 8,
  219. SDL_SWSURFACE | (fFullScreen ? SDL_FULLSCREEN : 0));
  220. }
  221. //
  222. // Still fail?
  223. //
  224. if (gpScreenReal == NULL)
  225. {
  226. return -1;
  227. }
  228. //
  229. // Create the screen buffer and the backup screen buffer.
  230. //
  231. gpScreen = SDL_CreateRGBSurface(gpScreenReal->flags & ~SDL_HWSURFACE, 320, 200, 8,
  232. gpScreenReal->format->Rmask, gpScreenReal->format->Gmask,
  233. gpScreenReal->format->Bmask, gpScreenReal->format->Amask);
  234. gpScreenBak = SDL_CreateRGBSurface(gpScreenReal->flags & ~SDL_HWSURFACE, 320, 200, 8,
  235. gpScreenReal->format->Rmask, gpScreenReal->format->Gmask,
  236. gpScreenReal->format->Bmask, gpScreenReal->format->Amask);
  237. //
  238. // Failed?
  239. //
  240. if (gpScreen == NULL || gpScreenBak == NULL)
  241. {
  242. if (gpScreen != NULL)
  243. {
  244. SDL_FreeSurface(gpScreen);
  245. gpScreen = NULL;
  246. }
  247. if (gpScreenBak != NULL)
  248. {
  249. SDL_FreeSurface(gpScreenBak);
  250. gpScreenBak = NULL;
  251. }
  252. SDL_FreeSurface(gpScreenReal);
  253. gpScreenReal = NULL;
  254. return -2;
  255. }
  256. #endif
  257. if (fFullScreen)
  258. {
  259. SDL_ShowCursor(FALSE);
  260. }
  261. return 0;
  262. }
  263. VOID
  264. VIDEO_Shutdown(
  265. VOID
  266. )
  267. /*++
  268. Purpose:
  269. Shutdown the video subsystem.
  270. Parameters:
  271. None.
  272. Return value:
  273. None.
  274. --*/
  275. {
  276. if (gpScreen != NULL)
  277. {
  278. SDL_FreeSurface(gpScreen);
  279. }
  280. gpScreen = NULL;
  281. if (gpScreenBak != NULL)
  282. {
  283. SDL_FreeSurface(gpScreenBak);
  284. }
  285. gpScreenBak = NULL;
  286. #if SDL_VERSION_ATLEAST(2,0,0)
  287. if (gpTouchOverlay)
  288. {
  289. SDL_DestroyTexture(gpTouchOverlay);
  290. }
  291. gpTouchOverlay = NULL;
  292. #ifdef __WINPHONE__
  293. if (gpBackKeyMessage)
  294. {
  295. SDL_DestroyTexture(gpBackKeyMessage);
  296. }
  297. gpBackKeyMessage = NULL;
  298. #endif
  299. if (gpTexture)
  300. {
  301. SDL_DestroyTexture(gpTexture);
  302. }
  303. gpTexture = NULL;
  304. if (gpRenderer)
  305. {
  306. SDL_DestroyRenderer(gpRenderer);
  307. }
  308. gpRenderer = NULL;
  309. if (gpWindow)
  310. {
  311. SDL_DestroyWindow(gpWindow);
  312. }
  313. gpWindow = NULL;
  314. #endif
  315. if (gpScreenReal != NULL)
  316. {
  317. SDL_FreeSurface(gpScreenReal);
  318. }
  319. gpScreenReal = NULL;
  320. }
  321. VOID
  322. VIDEO_UpdateScreen(
  323. const SDL_Rect *lpRect
  324. )
  325. /*++
  326. Purpose:
  327. Update the screen area specified by lpRect.
  328. Parameters:
  329. [IN] lpRect - Screen area to update.
  330. Return value:
  331. None.
  332. --*/
  333. {
  334. SDL_Rect srcrect, dstrect;
  335. short offset = 240 - 200;
  336. short screenRealHeight = gpScreenReal->h;
  337. short screenRealY = 0;
  338. #if SDL_VERSION_ATLEAST(2,0,0)
  339. if (g_bRenderPaused)
  340. {
  341. return;
  342. }
  343. #endif
  344. //
  345. // Lock surface if needed
  346. //
  347. if (SDL_MUSTLOCK(gpScreenReal))
  348. {
  349. if (SDL_LockSurface(gpScreenReal) < 0)
  350. return;
  351. }
  352. if (!bScaleScreen)
  353. {
  354. screenRealHeight -= offset;
  355. screenRealY = offset / 2;
  356. }
  357. if (lpRect != NULL)
  358. {
  359. dstrect.x = (SHORT)((INT)(lpRect->x) * gpScreenReal->w / gpScreen->w);
  360. dstrect.y = (SHORT)((INT)(screenRealY + lpRect->y) * screenRealHeight / gpScreen->h);
  361. dstrect.w = (WORD)((DWORD)(lpRect->w) * gpScreenReal->w / gpScreen->w);
  362. dstrect.h = (WORD)((DWORD)(lpRect->h) * screenRealHeight / gpScreen->h);
  363. SDL_SoftStretch(gpScreen, (SDL_Rect *)lpRect, gpScreenReal, &dstrect);
  364. if (SDL_MUSTLOCK(gpScreenReal))
  365. {
  366. SDL_UnlockSurface(gpScreenReal);
  367. }
  368. #if SDL_VERSION_ATLEAST(2,0,0)
  369. SDL_UpdateTexture(gpTexture, NULL, gpScreenReal->pixels, gpScreenReal->pitch);
  370. SDL_RenderCopy(gpRenderer, gpTexture, NULL, NULL);
  371. if (gpTouchOverlay)
  372. {
  373. SDL_RenderCopy(gpRenderer, gpTouchOverlay, NULL, NULL);
  374. }
  375. #ifdef __WINPHONE__
  376. if (gpBackKeyMessage)
  377. {
  378. extern unsigned int g_uiLastBackKeyTime;
  379. if (g_uiLastBackKeyTime != 0 && SDL_GetTicks() - g_uiLastBackKeyTime < 800)
  380. {
  381. SDL_RenderCopy(gpRenderer, gpBackKeyMessage, NULL, NULL);
  382. }
  383. }
  384. #endif
  385. SDL_RenderPresent(gpRenderer);
  386. #else
  387. SDL_UpdateRect(gpScreenReal, dstrect.x, dstrect.y, dstrect.w, dstrect.h);
  388. #endif
  389. }
  390. else if (g_wShakeTime != 0)
  391. {
  392. //
  393. // Shake the screen
  394. //
  395. srcrect.x = 0;
  396. srcrect.y = 0;
  397. srcrect.w = 320;
  398. srcrect.h = 200 - g_wShakeLevel;
  399. dstrect.x = 0;
  400. dstrect.y = screenRealY;
  401. dstrect.w = 320 * gpScreenReal->w / gpScreen->w;
  402. dstrect.h = (200 - g_wShakeLevel) * screenRealHeight / gpScreen->h;
  403. if (g_wShakeTime & 1)
  404. {
  405. srcrect.y = g_wShakeLevel;
  406. }
  407. else
  408. {
  409. dstrect.y = (screenRealY + g_wShakeLevel) * screenRealHeight / gpScreen->h;
  410. }
  411. SDL_SoftStretch(gpScreen, &srcrect, gpScreenReal, &dstrect);
  412. if (g_wShakeTime & 1)
  413. {
  414. dstrect.y = (screenRealY + screenRealHeight - g_wShakeLevel) * screenRealHeight / gpScreen->h;
  415. }
  416. else
  417. {
  418. dstrect.y = screenRealY;
  419. }
  420. dstrect.h = g_wShakeLevel * screenRealHeight / gpScreen->h;
  421. SDL_FillRect(gpScreenReal, &dstrect, 0);
  422. if (SDL_MUSTLOCK(gpScreenReal))
  423. {
  424. SDL_UnlockSurface(gpScreenReal);
  425. }
  426. #if SDL_VERSION_ATLEAST(2, 0, 0)
  427. SDL_UpdateTexture(gpTexture, NULL, gpScreenReal->pixels, gpScreenReal->pitch);
  428. SDL_RenderCopy(gpRenderer, gpTexture, NULL, NULL);
  429. if (gpTouchOverlay)
  430. {
  431. SDL_RenderCopy(gpRenderer, gpTouchOverlay, NULL, NULL);
  432. }
  433. #ifdef __WINPHONE__
  434. if (gpBackKeyMessage)
  435. {
  436. extern unsigned int g_uiLastBackKeyTime;
  437. if (g_uiLastBackKeyTime != 0 && SDL_GetTicks() - g_uiLastBackKeyTime < 800)
  438. {
  439. SDL_RenderCopy(gpRenderer, gpBackKeyMessage, NULL, NULL);
  440. }
  441. }
  442. #endif
  443. SDL_RenderPresent(gpRenderer);
  444. #else
  445. SDL_UpdateRect(gpScreenReal, 0, 0, gpScreenReal->w, gpScreenReal->h);
  446. #endif
  447. g_wShakeTime--;
  448. }
  449. else
  450. {
  451. dstrect.x = 0;
  452. dstrect.y = screenRealY;
  453. dstrect.w = gpScreenReal->w;
  454. dstrect.h = screenRealHeight;
  455. SDL_SoftStretch(gpScreen, NULL, gpScreenReal, &dstrect);
  456. if (SDL_MUSTLOCK(gpScreenReal))
  457. {
  458. SDL_UnlockSurface(gpScreenReal);
  459. }
  460. #if SDL_VERSION_ATLEAST(2, 0, 0)
  461. SDL_UpdateTexture(gpTexture, NULL, gpScreenReal->pixels, gpScreenReal->pitch);
  462. SDL_RenderCopy(gpRenderer, gpTexture, NULL, NULL);
  463. if (gpTouchOverlay)
  464. {
  465. SDL_RenderCopy(gpRenderer, gpTouchOverlay, NULL, NULL);
  466. }
  467. #ifdef __WINPHONE__
  468. if (gpBackKeyMessage)
  469. {
  470. extern unsigned int g_uiLastBackKeyTime;
  471. if (g_uiLastBackKeyTime != 0 && SDL_GetTicks() - g_uiLastBackKeyTime < 800)
  472. {
  473. SDL_RenderCopy(gpRenderer, gpBackKeyMessage, NULL, NULL);
  474. }
  475. }
  476. #endif
  477. SDL_RenderPresent(gpRenderer);
  478. #else
  479. SDL_UpdateRect(gpScreenReal, 0, 0, gpScreenReal->w, gpScreenReal->h);
  480. #endif
  481. }
  482. }
  483. VOID
  484. VIDEO_SetPalette(
  485. SDL_Color rgPalette[256]
  486. )
  487. /*++
  488. Purpose:
  489. Set the palette of the screen.
  490. Parameters:
  491. [IN] rgPalette - array of 256 colors.
  492. Return value:
  493. None.
  494. --*/
  495. {
  496. #if SDL_VERSION_ATLEAST(2,0,0)
  497. SDL_Palette *palette = SDL_AllocPalette(256);
  498. if (palette == NULL)
  499. {
  500. return;
  501. }
  502. SDL_SetPaletteColors(palette, rgPalette, 0, 256);
  503. SDL_SetSurfacePalette(gpScreen, palette);
  504. SDL_SetSurfacePalette(gpScreenBak, palette);
  505. //
  506. // HACKHACK: need to invalidate gpScreen->map otherwise the palette
  507. // would not be effective during blit
  508. //
  509. SDL_SetSurfaceColorMod(gpScreen, 0, 0, 0);
  510. SDL_SetSurfaceColorMod(gpScreen, 0xFF, 0xFF, 0xFF);
  511. SDL_SetSurfaceColorMod(gpScreenBak, 0, 0, 0);
  512. SDL_SetSurfaceColorMod(gpScreenBak, 0xFF, 0xFF, 0xFF);
  513. VIDEO_UpdateScreen(NULL);
  514. // The palette should be freed, or memory leak occurs.
  515. SDL_FreePalette(palette);
  516. #else
  517. SDL_SetPalette(gpScreen, SDL_LOGPAL | SDL_PHYSPAL, rgPalette, 0, 256);
  518. SDL_SetPalette(gpScreenBak, SDL_LOGPAL | SDL_PHYSPAL, rgPalette, 0, 256);
  519. SDL_SetPalette(gpScreenReal, SDL_LOGPAL | SDL_PHYSPAL, rgPalette, 0, 256);
  520. #if (defined (__SYMBIAN32__))
  521. {
  522. static UINT32 time = 0;
  523. if (SDL_GetTicks() - time > 50)
  524. {
  525. SDL_UpdateRect(gpScreenReal, 0, 0, gpScreenReal->w, gpScreenReal->h);
  526. time = SDL_GetTicks();
  527. }
  528. }
  529. #endif
  530. #endif
  531. }
  532. VOID
  533. VIDEO_Resize(
  534. INT w,
  535. INT h
  536. )
  537. /*++
  538. Purpose:
  539. This function is called when user resized the window.
  540. Parameters:
  541. [IN] w - width of the window after resizing.
  542. [IN] h - height of the window after resizing.
  543. Return value:
  544. None.
  545. --*/
  546. {
  547. #if SDL_VERSION_ATLEAST(2,0,0)
  548. // TODO
  549. #else
  550. DWORD flags;
  551. PAL_LARGE SDL_Color palette[256];
  552. int i;
  553. //
  554. // Get the original palette.
  555. //
  556. for (i = 0; i < gpScreenReal->format->palette->ncolors; i++)
  557. {
  558. palette[i] = gpScreenReal->format->palette->colors[i];
  559. }
  560. //
  561. // Create the screen surface.
  562. //
  563. flags = gpScreenReal->flags;
  564. SDL_FreeSurface(gpScreenReal);
  565. gpScreenReal = SDL_SetVideoMode(w, h, 8, flags);
  566. if (gpScreenReal == NULL)
  567. {
  568. #ifdef __SYMBIAN32__
  569. #ifdef __S60_5X__
  570. gpScreenReal = SDL_SetVideoMode(640, 360, 8, SDL_SWSURFACE);
  571. #else
  572. gpScreenReal = SDL_SetVideoMode(320, 240, 8, SDL_SWSURFACE);
  573. #endif
  574. #else
  575. //
  576. // Fall back to 640x480 software windowed mode.
  577. //
  578. gpScreenReal = SDL_SetVideoMode(640, 480, 8, SDL_SWSURFACE);
  579. #endif
  580. }
  581. SDL_SetPalette(gpScreenReal, SDL_PHYSPAL | SDL_LOGPAL, palette, 0, i);
  582. VIDEO_UpdateScreen(NULL);
  583. #endif
  584. }
  585. SDL_Color *
  586. VIDEO_GetPalette(
  587. VOID
  588. )
  589. /*++
  590. Purpose:
  591. Get the current palette of the screen.
  592. Parameters:
  593. None.
  594. Return value:
  595. Pointer to the current palette.
  596. --*/
  597. {
  598. #if SDL_VERSION_ATLEAST(2,0,0)
  599. return gpScreen->format->palette->colors;
  600. #else
  601. return gpScreenReal->format->palette->colors;
  602. #endif
  603. }
  604. VOID
  605. VIDEO_ToggleScaleScreen(
  606. VOID
  607. )
  608. /*++
  609. Purpose:
  610. Toggle scalescreen mode.
  611. Parameters:
  612. None.
  613. Return value:
  614. None.
  615. --*/
  616. {
  617. #ifdef __SYMBIAN32__
  618. bScaleScreen = !bScaleScreen;
  619. VIDEO_Resize(320, 240);
  620. VIDEO_UpdateScreen(NULL);
  621. #endif
  622. }
  623. VOID
  624. VIDEO_ToggleFullscreen(
  625. VOID
  626. )
  627. /*++
  628. Purpose:
  629. Toggle fullscreen mode.
  630. Parameters:
  631. None.
  632. Return value:
  633. None.
  634. --*/
  635. {
  636. #if SDL_VERSION_ATLEAST(2,0,0)
  637. // TODO
  638. #else
  639. DWORD flags;
  640. PAL_LARGE SDL_Color palette[256];
  641. int i;
  642. //
  643. // Get the original palette.
  644. //
  645. for (i = 0; i < gpScreenReal->format->palette->ncolors; i++)
  646. {
  647. palette[i] = gpScreenReal->format->palette->colors[i];
  648. }
  649. //
  650. // Get the flags of the original screen surface
  651. //
  652. flags = gpScreenReal->flags;
  653. if (flags & SDL_FULLSCREEN)
  654. {
  655. //
  656. // Already in fullscreen mode. Remove the fullscreen flag.
  657. //
  658. flags &= ~SDL_FULLSCREEN;
  659. flags |= SDL_RESIZABLE;
  660. SDL_ShowCursor(TRUE);
  661. }
  662. else
  663. {
  664. //
  665. // Not in fullscreen mode. Set the fullscreen flag.
  666. //
  667. flags |= SDL_FULLSCREEN;
  668. SDL_ShowCursor(FALSE);
  669. }
  670. //
  671. // Free the original screen surface
  672. //
  673. SDL_FreeSurface(gpScreenReal);
  674. //
  675. // ... and create a new one
  676. //
  677. if (g_wInitialWidth == 640 && g_wInitialHeight == 400 && (flags & SDL_FULLSCREEN))
  678. {
  679. gpScreenReal = SDL_SetVideoMode(640, 480, 8, flags);
  680. }
  681. else if (g_wInitialWidth == 640 && g_wInitialHeight == 480 && !(flags & SDL_FULLSCREEN))
  682. {
  683. gpScreenReal = SDL_SetVideoMode(640, 400, 8, flags);
  684. }
  685. else
  686. {
  687. gpScreenReal = SDL_SetVideoMode(g_wInitialWidth, g_wInitialHeight, 8, flags);
  688. }
  689. VIDEO_SetPalette(palette);
  690. //
  691. // Update the screen
  692. //
  693. VIDEO_UpdateScreen(NULL);
  694. #endif
  695. }
  696. VOID
  697. VIDEO_SaveScreenshot(
  698. VOID
  699. )
  700. /*++
  701. Purpose:
  702. Save the screenshot of current screen to a BMP file.
  703. Parameters:
  704. None.
  705. Return value:
  706. None.
  707. --*/
  708. {
  709. int iNumBMP = 0;
  710. FILE *fp;
  711. //
  712. // Find a usable BMP filename.
  713. //
  714. for (iNumBMP = 0; iNumBMP <= 9999; iNumBMP++)
  715. {
  716. fp = fopen(va("%sscrn%.4d.bmp", PAL_PREFIX, iNumBMP), "rb");
  717. if (fp == NULL)
  718. {
  719. break;
  720. }
  721. fclose(fp);
  722. }
  723. if (iNumBMP > 9999)
  724. {
  725. return;
  726. }
  727. //
  728. // Save the screenshot.
  729. //
  730. #if SDL_VERSION_ATLEAST(2,0,0)
  731. SDL_SaveBMP(gpScreen, va("%sscrn%.4d.bmp", PAL_PREFIX, iNumBMP));
  732. #else
  733. SDL_SaveBMP(gpScreenReal, va("%sscrn%.4d.bmp", PAL_PREFIX, iNumBMP));
  734. #endif
  735. }
  736. VOID
  737. VIDEO_BackupScreen(
  738. VOID
  739. )
  740. /*++
  741. Purpose:
  742. Backup the screen buffer.
  743. Parameters:
  744. None.
  745. Return value:
  746. None.
  747. --*/
  748. {
  749. SDL_BlitSurface(gpScreen, NULL, gpScreenBak, NULL);
  750. }
  751. VOID
  752. VIDEO_RestoreScreen(
  753. VOID
  754. )
  755. /*++
  756. Purpose:
  757. Restore the screen buffer which has been saved with VIDEO_BackupScreen().
  758. Parameters:
  759. None.
  760. Return value:
  761. None.
  762. --*/
  763. {
  764. SDL_BlitSurface(gpScreenBak, NULL, gpScreen, NULL);
  765. }
  766. VOID
  767. VIDEO_ShakeScreen(
  768. WORD wShakeTime,
  769. WORD wShakeLevel
  770. )
  771. /*++
  772. Purpose:
  773. Set the screen shake time and level.
  774. Parameters:
  775. [IN] wShakeTime - how many times should we shake the screen.
  776. [IN] wShakeLevel - level of shaking.
  777. Return value:
  778. None.
  779. --*/
  780. {
  781. g_wShakeTime = wShakeTime;
  782. g_wShakeLevel = wShakeLevel;
  783. }
  784. VOID
  785. VIDEO_SwitchScreen(
  786. WORD wSpeed
  787. )
  788. /*++
  789. Purpose:
  790. Switch the screen from the backup screen buffer to the current screen buffer.
  791. NOTE: This will destroy the backup buffer.
  792. Parameters:
  793. [IN] wSpeed - speed of fading (the larger value, the slower).
  794. Return value:
  795. None.
  796. --*/
  797. {
  798. int i, j;
  799. const int rgIndex[6] = {0, 3, 1, 5, 2, 4};
  800. SDL_Rect dstrect;
  801. short offset = 240 - 200;
  802. short screenRealHeight = gpScreenReal->h;
  803. short screenRealY = 0;
  804. if (!bScaleScreen)
  805. {
  806. screenRealHeight -= offset;
  807. screenRealY = offset / 2;
  808. }
  809. wSpeed++;
  810. wSpeed *= 10;
  811. for (i = 0; i < 6; i++)
  812. {
  813. for (j = rgIndex[i]; j < gpScreen->pitch * gpScreen->h; j += 6)
  814. {
  815. ((LPBYTE)(gpScreenBak->pixels))[j] = ((LPBYTE)(gpScreen->pixels))[j];
  816. }
  817. //
  818. // Draw the backup buffer to the screen
  819. //
  820. dstrect.x = 0;
  821. dstrect.y = screenRealY;
  822. dstrect.w = gpScreenReal->w;
  823. dstrect.h = screenRealHeight;
  824. SDL_SoftStretch(gpScreenBak, NULL, gpScreenReal, &dstrect);
  825. #if SDL_VERSION_ATLEAST(2, 0, 0)
  826. SDL_UpdateTexture(gpTexture, NULL, gpScreenReal->pixels, gpScreenReal->pitch);
  827. SDL_RenderCopy(gpRenderer, gpTexture, NULL, NULL);
  828. if (gpTouchOverlay)
  829. {
  830. SDL_RenderCopy(gpRenderer, gpTouchOverlay, NULL, NULL);
  831. }
  832. #ifdef __WINPHONE__
  833. if (gpBackKeyMessage)
  834. {
  835. extern unsigned int g_uiLastBackKeyTime;
  836. if (g_uiLastBackKeyTime != 0 && SDL_GetTicks() - g_uiLastBackKeyTime < 800)
  837. {
  838. SDL_RenderCopy(gpRenderer, gpBackKeyMessage, NULL, NULL);
  839. }
  840. }
  841. #endif
  842. SDL_RenderPresent(gpRenderer);
  843. #else
  844. SDL_UpdateRect(gpScreenReal, 0, 0, gpScreenReal->w, gpScreenReal->h);
  845. #endif
  846. UTIL_Delay(wSpeed);
  847. }
  848. }
  849. VOID
  850. VIDEO_FadeScreen(
  851. WORD wSpeed
  852. )
  853. /*++
  854. Purpose:
  855. Fade from the backup screen buffer to the current screen buffer.
  856. NOTE: This will destroy the backup buffer.
  857. Parameters:
  858. [IN] wSpeed - speed of fading (the larger value, the slower).
  859. Return value:
  860. None.
  861. --*/
  862. {
  863. int i, j, k;
  864. DWORD time;
  865. BYTE a, b;
  866. const int rgIndex[6] = {0, 3, 1, 5, 2, 4};
  867. SDL_Rect dstrect;
  868. short offset = 240 - 200;
  869. short screenRealHeight = gpScreenReal->h;
  870. short screenRealY = 0;
  871. //
  872. // Lock surface if needed
  873. //
  874. if (SDL_MUSTLOCK(gpScreenReal))
  875. {
  876. if (SDL_LockSurface(gpScreenReal) < 0)
  877. return;
  878. }
  879. if (!bScaleScreen)
  880. {
  881. screenRealHeight -= offset;
  882. screenRealY = offset / 2;
  883. }
  884. time = SDL_GetTicks();
  885. wSpeed++;
  886. wSpeed *= 10;
  887. for (i = 0; i < 12; i++)
  888. {
  889. for (j = 0; j < 6; j++)
  890. {
  891. PAL_ProcessEvent();
  892. while (SDL_GetTicks() <= time)
  893. {
  894. PAL_ProcessEvent();
  895. SDL_Delay(5);
  896. }
  897. time = SDL_GetTicks() + wSpeed;
  898. //
  899. // Blend the pixels in the 2 buffers, and put the result into the
  900. // backup buffer
  901. //
  902. for (k = rgIndex[j]; k < gpScreen->pitch * gpScreen->h; k += 6)
  903. {
  904. a = ((LPBYTE)(gpScreen->pixels))[k];
  905. b = ((LPBYTE)(gpScreenBak->pixels))[k];
  906. if (i > 0)
  907. {
  908. if ((a & 0x0F) > (b & 0x0F))
  909. {
  910. b++;
  911. }
  912. else if ((a & 0x0F) < (b & 0x0F))
  913. {
  914. b--;
  915. }
  916. }
  917. ((LPBYTE)(gpScreenBak->pixels))[k] = ((a & 0xF0) | (b & 0x0F));
  918. }
  919. //
  920. // Draw the backup buffer to the screen
  921. //
  922. if (g_wShakeTime != 0)
  923. {
  924. //
  925. // Shake the screen
  926. //
  927. SDL_Rect srcrect, dstrect;
  928. srcrect.x = 0;
  929. srcrect.y = 0;
  930. srcrect.w = 320;
  931. srcrect.h = 200 - g_wShakeLevel;
  932. dstrect.x = 0;
  933. dstrect.y = screenRealY;
  934. dstrect.w = 320 * gpScreenReal->w / gpScreen->w;
  935. dstrect.h = (200 - g_wShakeLevel) * screenRealHeight / gpScreen->h;
  936. if (g_wShakeTime & 1)
  937. {
  938. srcrect.y = g_wShakeLevel;
  939. }
  940. else
  941. {
  942. dstrect.y = (screenRealY + g_wShakeLevel) * screenRealHeight / gpScreen->h;
  943. }
  944. SDL_SoftStretch(gpScreenBak, &srcrect, gpScreenReal, &dstrect);
  945. if (g_wShakeTime & 1)
  946. {
  947. dstrect.y = (screenRealY + screenRealHeight - g_wShakeLevel) * screenRealHeight / gpScreen->h;
  948. }
  949. else
  950. {
  951. dstrect.y = screenRealY;
  952. }
  953. dstrect.h = g_wShakeLevel * screenRealHeight / gpScreen->h;
  954. SDL_FillRect(gpScreenReal, &dstrect, 0);
  955. #if SDL_VERSION_ATLEAST(2, 0, 0)
  956. SDL_UpdateTexture(gpTexture, NULL, gpScreenReal->pixels, gpScreenReal->pitch);
  957. SDL_RenderCopy(gpRenderer, gpTexture, NULL, NULL);
  958. if (gpTouchOverlay)
  959. {
  960. SDL_RenderCopy(gpRenderer, gpTouchOverlay, NULL, NULL);
  961. }
  962. #ifdef __WINPHONE__
  963. if (gpBackKeyMessage)
  964. {
  965. extern unsigned int g_uiLastBackKeyTime;
  966. if (g_uiLastBackKeyTime != 0 && SDL_GetTicks() - g_uiLastBackKeyTime < 800)
  967. {
  968. SDL_RenderCopy(gpRenderer, gpBackKeyMessage, NULL, NULL);
  969. }
  970. }
  971. #endif
  972. SDL_RenderPresent(gpRenderer);
  973. #else
  974. SDL_UpdateRect(gpScreenReal, 0, 0, gpScreenReal->w, gpScreenReal->h);
  975. #endif
  976. g_wShakeTime--;
  977. }
  978. else
  979. {
  980. dstrect.x = 0;
  981. dstrect.y = screenRealY;
  982. dstrect.w = gpScreenReal->w;
  983. dstrect.h = screenRealHeight;
  984. SDL_SoftStretch(gpScreenBak, NULL, gpScreenReal, &dstrect);
  985. #if SDL_VERSION_ATLEAST(2, 0, 0)
  986. SDL_UpdateTexture(gpTexture, NULL, gpScreenReal->pixels, gpScreenReal->pitch);
  987. SDL_RenderCopy(gpRenderer, gpTexture, NULL, NULL);
  988. if (gpTouchOverlay)
  989. {
  990. SDL_RenderCopy(gpRenderer, gpTouchOverlay, NULL, NULL);
  991. }
  992. #ifdef __WINPHONE__
  993. if (gpBackKeyMessage)
  994. {
  995. extern unsigned int g_uiLastBackKeyTime;
  996. if (g_uiLastBackKeyTime != 0 && SDL_GetTicks() - g_uiLastBackKeyTime < 800)
  997. {
  998. SDL_RenderCopy(gpRenderer, gpBackKeyMessage, NULL, NULL);
  999. }
  1000. }
  1001. #endif
  1002. SDL_RenderPresent(gpRenderer);
  1003. #else
  1004. SDL_UpdateRect(gpScreenReal, 0, 0, gpScreenReal->w, gpScreenReal->h);
  1005. #endif
  1006. }
  1007. }
  1008. }
  1009. if (SDL_MUSTLOCK(gpScreenReal))
  1010. {
  1011. SDL_UnlockSurface(gpScreenReal);
  1012. }
  1013. //
  1014. // Draw the result buffer to the screen as the final step
  1015. //
  1016. VIDEO_UpdateScreen(NULL);
  1017. }
  1018. #if SDL_VERSION_ATLEAST(2,0,0)
  1019. /*++
  1020. Purpose:
  1021. Set the caption of the window. For compatibility with SDL2 only.
  1022. Parameters:
  1023. [IN] lpszCaption - the new caption of the window.
  1024. [IN] lpReserved - not used, for compatibility only.
  1025. Return value:
  1026. None.
  1027. --*/
  1028. VOID
  1029. SDL_WM_SetCaption(
  1030. LPCSTR lpszCaption,
  1031. LPVOID lpReserved
  1032. )
  1033. {
  1034. if (gpWindow != NULL)
  1035. {
  1036. SDL_SetWindowTitle(gpWindow, lpszCaption);
  1037. }
  1038. }
  1039. #endif