video.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263
  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. #ifdef PAL_WIN95
  166. extern BOOL fIsBig5;
  167. #endif
  168. SDL_Color palette[256] = { 0 };
  169. SDL_Surface *p;
  170. #ifdef PAL_WIN95
  171. fIsBig5 = TRUE;
  172. #endif
  173. palette[0].r = palette[0].g = palette[0].b = palette[0].a = 0;
  174. palette[1].r = palette[1].g = palette[1].b = palette[1].a = 255;
  175. SDL_FillRect(gpScreenBak, NULL, 0);
  176. VIDEO_SetPalette(palette);
  177. p = gpScreen;
  178. gpScreen = gpScreenBak;
  179. PAL_DrawText("\xA6\x41\xA6\xB8\xAB\xF6 Back \xB5\xB2\xA7\xF4", PAL_XY(30, 30), 1, FALSE, FALSE);
  180. gpScreen = p;
  181. gpBackKeyMessage = SDL_CreateTextureFromSurface(gpRenderer, gpScreenBak);
  182. SDL_FillRect(gpScreenBak, NULL, 0);
  183. #ifdef PAL_WIN95
  184. fIsBig5 = FALSE;
  185. #endif
  186. }
  187. #endif
  188. #else
  189. //
  190. // Create the screen surface.
  191. //
  192. #if defined (NDS)
  193. gpScreenReal = SDL_SetVideoMode(293, 196, 8, SDL_SWSURFACE | SDL_FULLSCREEN);
  194. #elif defined (__SYMBIAN32__)
  195. #ifdef __S60_5X__
  196. gpScreenReal = SDL_SetVideoMode(640, 360, 8,
  197. SDL_SWSURFACE | (fFullScreen ? SDL_FULLSCREEN : 0));
  198. #else
  199. gpScreenReal = SDL_SetVideoMode(320, 240, 8,
  200. SDL_SWSURFACE | (fFullScreen ? SDL_FULLSCREEN : 0));
  201. #endif
  202. #elif defined (GEKKO)
  203. gpScreenReal = SDL_SetVideoMode(640, 480, 8,
  204. SDL_SWSURFACE | (fFullScreen ? SDL_FULLSCREEN : 0));
  205. #elif defined (PSP)
  206. gpScreenReal = SDL_SetVideoMode(320, 240, 8, SDL_SWSURFACE | SDL_FULLSCREEN);
  207. #else
  208. gpScreenReal = SDL_SetVideoMode(wScreenWidth, wScreenHeight, 8,
  209. SDL_HWSURFACE | SDL_RESIZABLE | (fFullScreen ? SDL_FULLSCREEN : 0));
  210. #endif
  211. if (gpScreenReal == NULL)
  212. {
  213. //
  214. // Fall back to 640x480 software mode.
  215. //
  216. gpScreenReal = SDL_SetVideoMode(640, 480, 8,
  217. SDL_SWSURFACE | (fFullScreen ? SDL_FULLSCREEN : 0));
  218. }
  219. //
  220. // Still fail?
  221. //
  222. if (gpScreenReal == NULL)
  223. {
  224. return -1;
  225. }
  226. //
  227. // Create the screen buffer and the backup screen buffer.
  228. //
  229. gpScreen = SDL_CreateRGBSurface(gpScreenReal->flags & ~SDL_HWSURFACE, 320, 200, 8,
  230. gpScreenReal->format->Rmask, gpScreenReal->format->Gmask,
  231. gpScreenReal->format->Bmask, gpScreenReal->format->Amask);
  232. gpScreenBak = SDL_CreateRGBSurface(gpScreenReal->flags & ~SDL_HWSURFACE, 320, 200, 8,
  233. gpScreenReal->format->Rmask, gpScreenReal->format->Gmask,
  234. gpScreenReal->format->Bmask, gpScreenReal->format->Amask);
  235. //
  236. // Failed?
  237. //
  238. if (gpScreen == NULL || gpScreenBak == NULL)
  239. {
  240. if (gpScreen != NULL)
  241. {
  242. SDL_FreeSurface(gpScreen);
  243. gpScreen = NULL;
  244. }
  245. if (gpScreenBak != NULL)
  246. {
  247. SDL_FreeSurface(gpScreenBak);
  248. gpScreenBak = NULL;
  249. }
  250. SDL_FreeSurface(gpScreenReal);
  251. gpScreenReal = NULL;
  252. return -2;
  253. }
  254. #endif
  255. if (fFullScreen)
  256. {
  257. SDL_ShowCursor(FALSE);
  258. }
  259. return 0;
  260. }
  261. VOID
  262. VIDEO_Shutdown(
  263. VOID
  264. )
  265. /*++
  266. Purpose:
  267. Shutdown the video subsystem.
  268. Parameters:
  269. None.
  270. Return value:
  271. None.
  272. --*/
  273. {
  274. if (gpScreen != NULL)
  275. {
  276. SDL_FreeSurface(gpScreen);
  277. }
  278. gpScreen = NULL;
  279. if (gpScreenBak != NULL)
  280. {
  281. SDL_FreeSurface(gpScreenBak);
  282. }
  283. gpScreenBak = NULL;
  284. #if SDL_VERSION_ATLEAST(2,0,0)
  285. if (gpTouchOverlay)
  286. {
  287. SDL_DestroyTexture(gpTouchOverlay);
  288. }
  289. gpTouchOverlay = NULL;
  290. #ifdef __WINPHONE__
  291. if (gpBackKeyMessage)
  292. {
  293. SDL_DestroyTexture(gpBackKeyMessage);
  294. }
  295. gpBackKeyMessage = NULL;
  296. #endif
  297. if (gpTexture)
  298. {
  299. SDL_DestroyTexture(gpTexture);
  300. }
  301. gpTexture = NULL;
  302. if (gpRenderer)
  303. {
  304. SDL_DestroyRenderer(gpRenderer);
  305. }
  306. gpRenderer = NULL;
  307. if (gpWindow)
  308. {
  309. SDL_DestroyWindow(gpWindow);
  310. }
  311. gpWindow = NULL;
  312. #endif
  313. if (gpScreenReal != NULL)
  314. {
  315. SDL_FreeSurface(gpScreenReal);
  316. }
  317. gpScreenReal = NULL;
  318. }
  319. VOID
  320. VIDEO_UpdateScreen(
  321. const SDL_Rect *lpRect
  322. )
  323. /*++
  324. Purpose:
  325. Update the screen area specified by lpRect.
  326. Parameters:
  327. [IN] lpRect - Screen area to update.
  328. Return value:
  329. None.
  330. --*/
  331. {
  332. SDL_Rect srcrect, dstrect;
  333. short offset = 240 - 200;
  334. short screenRealHeight = gpScreenReal->h;
  335. short screenRealY = 0;
  336. #if SDL_VERSION_ATLEAST(2,0,0)
  337. if (g_bRenderPaused)
  338. {
  339. return;
  340. }
  341. #endif
  342. //
  343. // Lock surface if needed
  344. //
  345. if (SDL_MUSTLOCK(gpScreenReal))
  346. {
  347. if (SDL_LockSurface(gpScreenReal) < 0)
  348. return;
  349. }
  350. if (!bScaleScreen)
  351. {
  352. screenRealHeight -= offset;
  353. screenRealY = offset / 2;
  354. }
  355. if (lpRect != NULL)
  356. {
  357. dstrect.x = (SHORT)((INT)(lpRect->x) * gpScreenReal->w / gpScreen->w);
  358. dstrect.y = (SHORT)((INT)(screenRealY + lpRect->y) * screenRealHeight / gpScreen->h);
  359. dstrect.w = (WORD)((DWORD)(lpRect->w) * gpScreenReal->w / gpScreen->w);
  360. dstrect.h = (WORD)((DWORD)(lpRect->h) * screenRealHeight / gpScreen->h);
  361. SDL_SoftStretch(gpScreen, (SDL_Rect *)lpRect, gpScreenReal, &dstrect);
  362. if (SDL_MUSTLOCK(gpScreenReal))
  363. {
  364. SDL_UnlockSurface(gpScreenReal);
  365. }
  366. #if SDL_VERSION_ATLEAST(2,0,0)
  367. SDL_UpdateTexture(gpTexture, NULL, gpScreenReal->pixels, gpScreenReal->pitch);
  368. SDL_RenderCopy(gpRenderer, gpTexture, NULL, NULL);
  369. if (gpTouchOverlay)
  370. {
  371. SDL_RenderCopy(gpRenderer, gpTouchOverlay, NULL, NULL);
  372. }
  373. #ifdef __WINPHONE__
  374. if (gpBackKeyMessage)
  375. {
  376. extern unsigned int g_uiLastBackKeyTime;
  377. if (g_uiLastBackKeyTime != 0 && SDL_GetTicks() - g_uiLastBackKeyTime < 800)
  378. {
  379. SDL_RenderCopy(gpRenderer, gpBackKeyMessage, NULL, NULL);
  380. }
  381. }
  382. #endif
  383. SDL_RenderPresent(gpRenderer);
  384. #else
  385. SDL_UpdateRect(gpScreenReal, dstrect.x, dstrect.y, dstrect.w, dstrect.h);
  386. #endif
  387. }
  388. else if (g_wShakeTime != 0)
  389. {
  390. //
  391. // Shake the screen
  392. //
  393. srcrect.x = 0;
  394. srcrect.y = 0;
  395. srcrect.w = 320;
  396. srcrect.h = 200 - g_wShakeLevel;
  397. dstrect.x = 0;
  398. dstrect.y = screenRealY;
  399. dstrect.w = 320 * gpScreenReal->w / gpScreen->w;
  400. dstrect.h = (200 - g_wShakeLevel) * screenRealHeight / gpScreen->h;
  401. if (g_wShakeTime & 1)
  402. {
  403. srcrect.y = g_wShakeLevel;
  404. }
  405. else
  406. {
  407. dstrect.y = (screenRealY + g_wShakeLevel) * screenRealHeight / gpScreen->h;
  408. }
  409. SDL_SoftStretch(gpScreen, &srcrect, gpScreenReal, &dstrect);
  410. if (g_wShakeTime & 1)
  411. {
  412. dstrect.y = (screenRealY + screenRealHeight - g_wShakeLevel) * screenRealHeight / gpScreen->h;
  413. }
  414. else
  415. {
  416. dstrect.y = screenRealY;
  417. }
  418. dstrect.h = g_wShakeLevel * screenRealHeight / gpScreen->h;
  419. SDL_FillRect(gpScreenReal, &dstrect, 0);
  420. if (SDL_MUSTLOCK(gpScreenReal))
  421. {
  422. SDL_UnlockSurface(gpScreenReal);
  423. }
  424. #if SDL_VERSION_ATLEAST(2, 0, 0)
  425. SDL_UpdateTexture(gpTexture, NULL, gpScreenReal->pixels, gpScreenReal->pitch);
  426. SDL_RenderCopy(gpRenderer, gpTexture, NULL, NULL);
  427. if (gpTouchOverlay)
  428. {
  429. SDL_RenderCopy(gpRenderer, gpTouchOverlay, NULL, NULL);
  430. }
  431. #ifdef __WINPHONE__
  432. if (gpBackKeyMessage)
  433. {
  434. extern unsigned int g_uiLastBackKeyTime;
  435. if (g_uiLastBackKeyTime != 0 && SDL_GetTicks() - g_uiLastBackKeyTime < 800)
  436. {
  437. SDL_RenderCopy(gpRenderer, gpBackKeyMessage, NULL, NULL);
  438. }
  439. }
  440. #endif
  441. SDL_RenderPresent(gpRenderer);
  442. #else
  443. SDL_UpdateRect(gpScreenReal, 0, 0, gpScreenReal->w, gpScreenReal->h);
  444. #endif
  445. g_wShakeTime--;
  446. }
  447. else
  448. {
  449. dstrect.x = 0;
  450. dstrect.y = screenRealY;
  451. dstrect.w = gpScreenReal->w;
  452. dstrect.h = screenRealHeight;
  453. SDL_SoftStretch(gpScreen, NULL, gpScreenReal, &dstrect);
  454. if (SDL_MUSTLOCK(gpScreenReal))
  455. {
  456. SDL_UnlockSurface(gpScreenReal);
  457. }
  458. #if SDL_VERSION_ATLEAST(2, 0, 0)
  459. SDL_UpdateTexture(gpTexture, NULL, gpScreenReal->pixels, gpScreenReal->pitch);
  460. SDL_RenderCopy(gpRenderer, gpTexture, NULL, NULL);
  461. if (gpTouchOverlay)
  462. {
  463. SDL_RenderCopy(gpRenderer, gpTouchOverlay, NULL, NULL);
  464. }
  465. #ifdef __WINPHONE__
  466. if (gpBackKeyMessage)
  467. {
  468. extern unsigned int g_uiLastBackKeyTime;
  469. if (g_uiLastBackKeyTime != 0 && SDL_GetTicks() - g_uiLastBackKeyTime < 800)
  470. {
  471. SDL_RenderCopy(gpRenderer, gpBackKeyMessage, NULL, NULL);
  472. }
  473. }
  474. #endif
  475. SDL_RenderPresent(gpRenderer);
  476. #else
  477. SDL_UpdateRect(gpScreenReal, 0, 0, gpScreenReal->w, gpScreenReal->h);
  478. #endif
  479. }
  480. }
  481. VOID
  482. VIDEO_SetPalette(
  483. SDL_Color rgPalette[256]
  484. )
  485. /*++
  486. Purpose:
  487. Set the palette of the screen.
  488. Parameters:
  489. [IN] rgPalette - array of 256 colors.
  490. Return value:
  491. None.
  492. --*/
  493. {
  494. #if SDL_VERSION_ATLEAST(2,0,0)
  495. int i;
  496. SDL_Palette *palette = SDL_AllocPalette(256);
  497. if (palette == NULL)
  498. {
  499. return;
  500. }
  501. for (i = 0; i < 256; i++)
  502. {
  503. palette->colors[i] = rgPalette[i];
  504. }
  505. SDL_SetSurfacePalette(gpScreen, palette);
  506. SDL_SetSurfacePalette(gpScreenBak, palette);
  507. //
  508. // HACKHACK: need to invalidate gpScreen->map otherwise the palette
  509. // would not be effective during blit
  510. //
  511. SDL_SetSurfaceColorMod(gpScreen, 0, 0, 0);
  512. SDL_SetSurfaceColorMod(gpScreen, 0xFF, 0xFF, 0xFF);
  513. SDL_SetSurfaceColorMod(gpScreenBak, 0, 0, 0);
  514. SDL_SetSurfaceColorMod(gpScreenBak, 0xFF, 0xFF, 0xFF);
  515. VIDEO_UpdateScreen(NULL);
  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