video.c 25 KB

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