video.c 24 KB

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