draw.cpp 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476
  1. /*
  2. LICENSE
  3. -------
  4. Copyright 2005 Nullsoft, Inc.
  5. All rights reserved.
  6. Redistribution and use in source and binary forms, with or without modification,
  7. are permitted provided that the following conditions are met:
  8. * Redistributions of source code must retain the above copyright notice,
  9. this list of conditions and the following disclaimer.
  10. * Redistributions in binary form must reproduce the above copyright notice,
  11. this list of conditions and the following disclaimer in the documentation
  12. and/or other materials provided with the distribution.
  13. * Neither the name of Nullsoft nor the names of its contributors may be used to
  14. endorse or promote products derived from this software without specific prior written permission.
  15. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
  16. IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  17. FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  18. CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  19. DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  20. DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
  21. IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  22. OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  23. */
  24. #include <windows.h>
  25. #include <ddraw.h>
  26. #include "draw.h"
  27. #include <stdio.h>
  28. #include <process.h>
  29. #include "r_defs.h"
  30. #include "resource.h"
  31. #include "vis.h"
  32. #include "../Agave/Language/api_language.h"
  33. extern HINSTANCE g_hInstance;
  34. #define RESIZE_ONRESIZE
  35. int draw_title_p=0;
  36. int cfg_cancelfs_on_deactivate=1;
  37. extern int g_dlg_fps,g_dlg_w,g_dlg_h;
  38. extern int cfg_fs_fps,cfg_fs_flip,cfg_fs_height,cfg_fs_use_overlay;
  39. extern int cfg_bkgnd_render, cfg_bkgnd_render_color;
  40. static LPDIRECTDRAW g_lpDD;
  41. static LPDIRECTDRAWSURFACE g_lpRenderSurf[2], g_lpPrimSurf, g_lpPrimSurfBack;
  42. static int g_bpp, g_fs, g_noshoww;
  43. int g_w, g_h, g_dsw, g_dsh;
  44. extern HWND g_hwnd;
  45. static CRITICAL_SECTION g_cs;
  46. static int g_windowed_dsize;
  47. static int g_initted, g_fs_flip, g_fs_height, g_fs_w, g_fs_h;
  48. static int nodraw=0;
  49. extern int inWharf;
  50. #ifdef RESIZE_ONRESIZE
  51. static int last_used;
  52. #endif
  53. static LPDIRECTDRAWSURFACE g_lpddsOverlay = NULL;
  54. static LPDIRECTDRAWSURFACE g_lpddsPrimary = NULL;
  55. static int g_overlay_init_ok=0;
  56. typedef enum {
  57. UYVY,
  58. YUY2
  59. } fourcc_enum;
  60. static fourcc_enum g_overlay_fourcc=UYVY;
  61. static int g_saved_desktop_values=0;
  62. static char g_saved_desktop_wallpaper[256];
  63. static char g_saved_reg_bkgnd_color[64];
  64. static DWORD g_saved_bkgnd_color;
  65. extern void Wnd_GoWindowed(HWND hwnd);
  66. #define INIT_DIRECTDRAW_STRUCT(x) (ZeroMemory(&x, sizeof(x)), x.dwSize=sizeof(x))
  67. DDPIXELFORMAT g_ddpfOverlayFormats[] =
  68. { {sizeof(DDPIXELFORMAT), DDPF_FOURCC,MAKEFOURCC('U','Y','V','Y'),0,0,0,0,0}, // UYVY
  69. {sizeof(DDPIXELFORMAT), DDPF_FOURCC,MAKEFOURCC('Y','U','Y','2'),0,0,0,0,0}}; // YUY2
  70. #define NUM_OVERLAY_FORMATS (sizeof(g_ddpfOverlayFormats) / sizeof(g_ddpfOverlayFormats[0]))
  71. static HWND hwndOverlayWnd;
  72. static LRESULT CALLBACK FSOverlayWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  73. {
  74. static unsigned int start_t;
  75. if (
  76. (((message == WM_KEYDOWN && (wParam == VK_ESCAPE || wParam == VK_RETURN)) ||
  77. message == WM_LBUTTONUP) && GetTickCount()-start_t > 1000)
  78. ||
  79. (cfg_cancelfs_on_deactivate && ((message == WM_NCACTIVATE && !wParam) ||
  80. message == WM_KILLFOCUS))
  81. )
  82. {
  83. DestroyWindow(hwnd);
  84. Wnd_GoWindowed(g_hwnd);
  85. return 0;
  86. }
  87. switch(message)
  88. {
  89. case WM_CREATE:
  90. start_t=GetTickCount();
  91. return 0;
  92. case WM_SETCURSOR:
  93. SetCursor(NULL);
  94. return TRUE;
  95. case WM_DESTROY:
  96. hwndOverlayWnd=0;
  97. return 0;
  98. case WM_PAINT:
  99. {
  100. PAINTSTRUCT ps;
  101. HDC hdc=BeginPaint(hwnd,&ps);
  102. RECT r;
  103. GetClientRect(hwnd,&r);
  104. int rv=0xff&(cfg_bkgnd_render_color>>16), gv=0xff&(cfg_bkgnd_render_color>>8), bv=0xff&cfg_bkgnd_render_color;
  105. HBRUSH b=CreateSolidBrush(RGB(rv,gv,bv));
  106. SelectObject(ps.hdc, b);
  107. Rectangle(ps.hdc, r.left, r.top, r.right, r.bottom);
  108. DeleteObject(b);
  109. EndPaint(hwnd,&ps);
  110. }
  111. return 0;
  112. case WM_KEYDOWN:
  113. return SendMessage(g_hwnd, message, wParam, lParam);
  114. }
  115. return DefWindowProc(hwnd, message, wParam, lParam);
  116. }
  117. static void DD_CreateFullscreenOverlayWindow()
  118. {
  119. static int inited=0;
  120. if(!inited)
  121. {
  122. WNDCLASSW wc={0,};
  123. wc.style = CS_DBLCLKS|CS_VREDRAW|CS_HREDRAW;
  124. wc.lpfnWndProc = FSOverlayWndProc;
  125. wc.hInstance = g_hInstance;
  126. wc.hbrBackground = NULL;
  127. wc.lpszClassName = L"avsfsoverlaywnd";
  128. wc.hCursor=NULL;
  129. if(!RegisterClassW(&wc)) return;
  130. inited=1;
  131. }
  132. hwndOverlayWnd=CreateWindowExW(WS_EX_TOPMOST|WS_EX_TOOLWINDOW,L"avsfsoverlaywnd",L"",WS_VISIBLE|WS_POPUP,0,0,GetSystemMetrics(SM_CXSCREEN),GetSystemMetrics(SM_CYSCREEN),NULL,NULL,g_hInstance,0);
  133. }
  134. static void DD_RestoreBkgndSettings()
  135. {
  136. if (g_saved_desktop_values)
  137. {
  138. int e=COLOR_DESKTOP;
  139. unsigned long c=g_saved_bkgnd_color;
  140. SetSysColors(1, &e, &c); // FUCKING MESSAGE PUMP AND SETSYSCOLORS
  141. SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, g_saved_desktop_wallpaper, NULL);
  142. g_saved_desktop_values=0;
  143. }
  144. }
  145. void DD_CreateSurfaces(int w, int h, int fsh, int fs, int fsbpp, int flip, int dbl, int fsovl) // fsh is the height to use (not screen res)
  146. {
  147. int resize_h=8, resize_w=8;
  148. #ifdef RESIZE_ONRESIZE
  149. int fb_save[64*65+1];
  150. int fb_save_use=0;
  151. #endif
  152. EnterCriticalSection(&g_cs);
  153. nodraw=0;
  154. if (g_lpDD)
  155. {
  156. extern int config_reuseonresize;
  157. #ifdef RESIZE_ONRESIZE
  158. HRESULT han;
  159. int ll=!!last_used;
  160. DDSURFACEDESC d={sizeof(d),};
  161. if (config_reuseonresize && g_w && g_h && g_lpRenderSurf[ll] &&
  162. (han = g_lpRenderSurf[ll]->Lock(NULL,&d,DDLOCK_WAIT,NULL)) == DD_OK)
  163. {
  164. if (d.lpSurface)
  165. {
  166. int x,y;
  167. int dxpos=(g_w<<16)/64;
  168. int ypos=0;
  169. int dypos=(g_h<<16)/64;
  170. int *pp=((int *)d.lpSurface);
  171. if (g_fs && g_fs_height < g_h) // adjust to use partial screen when
  172. {
  173. int fsy=g_h/2-g_fs_height/2;
  174. dypos=(g_fs_height<<16)/64;
  175. pp+=fsy * g_w;
  176. }
  177. for (y = 0; y < 64; y++)
  178. {
  179. int *p=pp + g_w * (ypos>>16);
  180. int xpos=0;
  181. for (x = 0; x < 64; x ++)
  182. {
  183. fb_save[(y<<6)+x]=p[xpos>>16];
  184. xpos+=dxpos;
  185. }
  186. ypos+=dypos;
  187. }
  188. memset(fb_save+64*64,0,sizeof(int)*65);
  189. fb_save_use=1;
  190. }
  191. g_lpRenderSurf[ll]->Unlock(d.lpSurface);
  192. }
  193. #endif
  194. if (g_lpPrimSurf)
  195. {
  196. g_lpPrimSurf->Release();
  197. g_lpPrimSurfBack=g_lpPrimSurf=NULL;
  198. }
  199. if (g_lpRenderSurf[0]) g_lpRenderSurf[0]->Release();
  200. if (g_lpRenderSurf[1]) g_lpRenderSurf[1]->Release();
  201. g_lpRenderSurf[0]=0;
  202. g_lpRenderSurf[1]=0;
  203. if (g_lpddsOverlay) g_lpddsOverlay->Release();
  204. if (g_lpddsPrimary) g_lpddsPrimary->Release();
  205. g_lpddsOverlay=g_lpddsPrimary=NULL;
  206. g_lpDD->Release();
  207. g_lpDD=NULL;
  208. }
  209. if (DirectDrawCreate(NULL,&g_lpDD,NULL) != DD_OK)
  210. {
  211. g_lpDD=NULL;
  212. MessageBox(g_hwnd,WASABI_API_LNGSTRING(IDS_ERROR_CREATING_DDRAW_OBJECT),"DDraw",0);
  213. LeaveCriticalSection(&g_cs);
  214. return;
  215. }
  216. if (fs && !fsovl)
  217. {
  218. g_fs_w=w;
  219. g_fs_h=h;
  220. g_fs_height=fsh>>dbl;
  221. g_fs_flip=flip;
  222. resize_w=w>>dbl;
  223. resize_h=h>>dbl;
  224. if (g_lpDD->SetCooperativeLevel(g_hwnd,DDSCL_NOWINDOWCHANGES|DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN) != DD_OK)
  225. {
  226. fs=0;
  227. }
  228. else
  229. {
  230. if (g_lpDD->SetDisplayMode(w,h,fsbpp) != DD_OK)
  231. {
  232. fs=0;
  233. }
  234. else
  235. {
  236. DDSURFACEDESC DDsd={sizeof(DDsd),};
  237. DDsd.dwFlags = DDSD_CAPS;
  238. DDsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
  239. if (g_fs_flip&1)
  240. {
  241. DDsd.ddsCaps.dwCaps |= DDSCAPS_COMPLEX|DDSCAPS_FLIP;
  242. DDsd.dwFlags|=DDSD_BACKBUFFERCOUNT;
  243. DDsd.dwBackBufferCount = 1;
  244. }
  245. if (g_lpDD->CreateSurface(&DDsd, &g_lpPrimSurf, NULL) != DD_OK)
  246. {
  247. fs=0;
  248. }
  249. else
  250. {
  251. DDBLTFX ddbfx={sizeof(ddbfx),};
  252. g_lpPrimSurf->Blt(NULL,NULL,NULL,DDBLT_WAIT|DDBLT_COLORFILL,&ddbfx);
  253. if (g_fs_flip&1)
  254. {
  255. DDSCAPS ddscaps;
  256. ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
  257. if (g_lpPrimSurf->GetAttachedSurface(&ddscaps, &g_lpPrimSurfBack) != DD_OK)
  258. {
  259. g_lpPrimSurf->Release();
  260. fs=0;
  261. }
  262. else g_lpPrimSurfBack->Blt(NULL,NULL,NULL,DDBLT_WAIT|DDBLT_COLORFILL,&ddbfx);
  263. }
  264. else
  265. g_lpPrimSurfBack=g_lpPrimSurf;
  266. }
  267. }
  268. }
  269. SetForegroundWindow(g_hwnd);
  270. } else {
  271. g_lpDD->SetCooperativeLevel(g_hwnd,DDSCL_NOWINDOWCHANGES|DDSCL_NORMAL);
  272. resize_w=(((w>>dbl)+3)&~3);
  273. g_noshoww=resize_w-(w>>dbl);
  274. resize_h=h>>dbl;
  275. }
  276. g_fs=fs;
  277. int wh;
  278. for (wh = 0; wh < 2; wh ++)
  279. {
  280. DDSURFACEDESC DDsd={sizeof(DDsd),};
  281. DDsd.dwFlags = DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT|DDSD_PITCH|DDSD_PIXELFORMAT;
  282. DDsd.dwWidth=resize_w;
  283. DDsd.dwHeight=resize_h;
  284. DDsd.lPitch=resize_w*sizeof(int);
  285. DDsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN|DDSCAPS_SYSTEMMEMORY;
  286. DDsd.ddpfPixelFormat.dwSize = sizeof(DDsd.ddpfPixelFormat);
  287. DDsd.ddpfPixelFormat.dwFlags=DDPF_RGB;
  288. DDsd.ddpfPixelFormat.dwRGBBitCount = 32;
  289. DDsd.ddpfPixelFormat.dwRBitMask=0xff0000;
  290. DDsd.ddpfPixelFormat.dwGBitMask=0x00ff00;
  291. DDsd.ddpfPixelFormat.dwBBitMask=0x0000ff;
  292. if (g_lpDD->CreateSurface(&DDsd, &g_lpRenderSurf[wh], NULL) != DD_OK)
  293. {
  294. if (wh)
  295. {
  296. g_lpRenderSurf[0]->Release();
  297. g_lpRenderSurf[0]=0;
  298. }
  299. g_lpRenderSurf[wh]=0;
  300. LeaveCriticalSection(&g_cs);
  301. return;
  302. }
  303. #ifdef RESIZE_ONRESIZE
  304. DDSURFACEDESC d={sizeof(d),};
  305. HRESULT han;
  306. if (fb_save_use && g_lpRenderSurf[wh] &&
  307. (han = g_lpRenderSurf[wh]->Lock(NULL,&d,DDLOCK_WAIT,NULL)) == DD_OK)
  308. {
  309. if (d.lpSurface)
  310. {
  311. int x,y;
  312. int dxpos=(64<<16)/resize_w;
  313. int ypos=0;
  314. int *p=(int *)d.lpSurface;
  315. int h=resize_h;
  316. if (fs && (fsh>>dbl) < resize_h)
  317. {
  318. int fsy=resize_h/2-(((fsh>>dbl)/2));
  319. p+=fsy * resize_w;
  320. h -= fsy*2;
  321. }
  322. int dypos=(64<<16)/h;
  323. for (y = 0; y < h; y ++)
  324. {
  325. int xpos=0;
  326. for (x = 0; x < resize_w; x ++)
  327. {
  328. *p++ = BLEND4_16((unsigned int *)fb_save + ((ypos>>10)&~63) + (xpos>>16),64,xpos,ypos);
  329. xpos+=dxpos;
  330. }
  331. ypos+=dypos;
  332. }
  333. #ifndef NO_MMX
  334. __asm emms;
  335. #endif
  336. }
  337. g_lpRenderSurf[wh]->Unlock(d.lpSurface);
  338. }
  339. #endif
  340. }
  341. g_w=resize_w;
  342. g_h=resize_h;
  343. g_dsh=g_h<<dbl;
  344. g_dsw=g_w<<dbl;
  345. g_bpp=fs?fsbpp:32;
  346. g_windowed_dsize=dbl;
  347. g_overlay_init_ok=0;
  348. if(!(cfg_bkgnd_render&1)) DD_RestoreBkgndSettings();
  349. if((cfg_bkgnd_render&1) || (g_fs && fsovl)) {
  350. // init overlay stuff
  351. DDSURFACEDESC ddsdOverlay;
  352. HRESULT ddrval;
  353. int i;
  354. // It's currently not possible to query for pixel formats supported by the
  355. // overlay hardware (though GetFourCCCodes() usually provides a partial
  356. // list). Instead you need to call CreateSurface() to try a variety of
  357. // formats till one works.
  358. INIT_DIRECTDRAW_STRUCT(ddsdOverlay);
  359. ddsdOverlay.ddsCaps.dwCaps=DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY;
  360. ddsdOverlay.dwFlags= DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT|DDSD_PITCH;
  361. ddsdOverlay.dwWidth=resize_w;
  362. ddsdOverlay.dwHeight=resize_h;
  363. ddsdOverlay.lPitch=resize_w*sizeof(int);
  364. ddsdOverlay.dwBackBufferCount=0;
  365. // Try to create an overlay surface using one of the pixel formats in our
  366. // global list.
  367. i=0;
  368. do
  369. {
  370. ddsdOverlay.ddpfPixelFormat=g_ddpfOverlayFormats[i];
  371. // Try to create the overlay surface
  372. ddrval = g_lpDD->CreateSurface(&ddsdOverlay, &g_lpddsOverlay, NULL);
  373. } while( FAILED(ddrval) && (++i < NUM_OVERLAY_FORMATS) );
  374. if(!FAILED(ddrval))
  375. {
  376. g_overlay_fourcc=(fourcc_enum)i;
  377. HRESULT ddrval;
  378. DDSURFACEDESC ddsd;
  379. INIT_DIRECTDRAW_STRUCT(ddsd);
  380. ddsd.dwFlags = DDSD_CAPS;
  381. ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
  382. ddrval = g_lpDD->CreateSurface(&ddsd, &g_lpddsPrimary, NULL );
  383. RECT rs, rd;
  384. DDOVERLAYFX ovfx;
  385. DDCAPS capsDrv;
  386. unsigned int uDestSizeAlign, uSrcSizeAlign;
  387. DWORD dwUpdateFlags;
  388. INIT_DIRECTDRAW_STRUCT(capsDrv);
  389. ddrval = g_lpDD->GetCaps(&capsDrv, NULL);
  390. uDestSizeAlign = capsDrv.dwAlignSizeDest;
  391. uSrcSizeAlign = capsDrv.dwAlignSizeSrc;
  392. dwUpdateFlags = DDOVER_SHOW | DDOVER_DDFX | DDOVER_KEYDESTOVERRIDE;
  393. DEVMODE d;
  394. d.dmSize=sizeof(d);
  395. d.dmDriverExtra=0;
  396. EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &d);
  397. int rv=0xff&(cfg_bkgnd_render_color>>16), gv=0xff&(cfg_bkgnd_render_color>>8), bv=0xff&cfg_bkgnd_render_color;
  398. if(!fsovl)
  399. {
  400. if (cfg_bkgnd_render&2)
  401. {
  402. if (!g_saved_desktop_values)
  403. {
  404. HKEY key;
  405. g_saved_desktop_wallpaper[0]=0;
  406. g_saved_reg_bkgnd_color[0]=0;
  407. // get wallpaper
  408. if(RegOpenKey(HKEY_CURRENT_USER, "Control Panel\\Desktop",&key)==ERROR_SUCCESS)
  409. {
  410. unsigned long s=sizeof(g_saved_desktop_wallpaper),vt;
  411. RegQueryValueEx(key,"Wallpaper", 0, &vt, (unsigned char *)g_saved_desktop_wallpaper, &s);
  412. }
  413. // get registry bkgnd color
  414. if(RegOpenKey(HKEY_CURRENT_USER, "Control Panel\\Colors",&key)==ERROR_SUCCESS)
  415. {
  416. unsigned long s=sizeof(g_saved_reg_bkgnd_color),vt;
  417. RegQueryValueEx(key,"Background", 0, &vt, (unsigned char *)g_saved_reg_bkgnd_color, &s);
  418. }
  419. g_saved_bkgnd_color=GetSysColor(COLOR_DESKTOP);
  420. g_saved_desktop_values=1;
  421. }
  422. int e=COLOR_DESKTOP;
  423. unsigned long c=RGB(rv,gv,bv);
  424. SetSysColors(1, &e, &c);
  425. SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, "", NULL);
  426. // rewrite registry settings right now so we don't fuck the user desktop if avs crashes
  427. {
  428. HKEY key;
  429. if(RegOpenKey(HKEY_CURRENT_USER, "Control Panel\\Desktop",&key)==ERROR_SUCCESS)
  430. RegSetValueEx(key,"Wallpaper", 0, REG_SZ, (unsigned char *)g_saved_desktop_wallpaper, strlen(g_saved_desktop_wallpaper)+1);
  431. if(RegOpenKey(HKEY_CURRENT_USER, "Control Panel\\Colors",&key)==ERROR_SUCCESS)
  432. RegSetValueEx(key,"Background", 0, REG_SZ, (unsigned char *)g_saved_reg_bkgnd_color, strlen(g_saved_reg_bkgnd_color)+1);
  433. }
  434. }
  435. else DD_RestoreBkgndSettings();
  436. }
  437. INIT_DIRECTDRAW_STRUCT(ovfx);
  438. switch(d.dmBitsPerPel)
  439. {
  440. case 16:
  441. ovfx.dckDestColorkey.dwColorSpaceLowValue=((rv>>3) << 11) | ((gv>>2) << 5) | (bv>>3);
  442. break;
  443. case 15:
  444. ovfx.dckDestColorkey.dwColorSpaceLowValue=((rv>>3) << 10) | ((gv>>3) << 5) | (bv>>3);
  445. break;
  446. case 24: case 32:
  447. ovfx.dckDestColorkey.dwColorSpaceLowValue=(rv << 16) | (gv << 8) | bv;
  448. break;
  449. }
  450. ovfx.dckDestColorkey.dwColorSpaceHighValue=ovfx.dckDestColorkey.dwColorSpaceLowValue;
  451. rs.left=0; rs.top=0;
  452. rs.right = resize_w;
  453. rs.bottom = resize_h;
  454. if (capsDrv.dwCaps & DDCAPS_ALIGNSIZESRC && uSrcSizeAlign)
  455. rs.right -= rs.right % uSrcSizeAlign;
  456. rd.left=0; rd.top=0;
  457. rd.right=GetSystemMetrics(SM_CXSCREEN); rd.bottom=GetSystemMetrics(SM_CYSCREEN);
  458. if (capsDrv.dwCaps & DDCAPS_ALIGNSIZEDEST && uDestSizeAlign)
  459. rd.right = (int)((rd.right+uDestSizeAlign-1)/uDestSizeAlign)*uDestSizeAlign;
  460. // Make the call to UpdateOverlay() which actually displays the overlay on
  461. // the screen.
  462. ddrval = g_lpddsOverlay->UpdateOverlay(&rs, g_lpddsPrimary, &rd, dwUpdateFlags, &ovfx);
  463. if(!FAILED(ddrval)) g_overlay_init_ok=1;
  464. }
  465. }
  466. if(g_fs && fsovl)
  467. {
  468. g_fs_height=fsh>>dbl;
  469. DD_CreateFullscreenOverlayWindow();
  470. }
  471. LeaveCriticalSection(&g_cs);
  472. }
  473. #ifndef NO_MMX
  474. bool CopyRGBSurfaceToYUVSurfaceMMX(
  475. LPDDSURFACEDESC pddsd1,
  476. LPDDSURFACEDESC pddsd2,
  477. fourcc_enum eOverlayFormat)
  478. {
  479. if (pddsd1->dwWidth != pddsd2->dwWidth)
  480. return false;
  481. if (pddsd1->dwHeight != pddsd2->dwHeight)
  482. return false;
  483. DWORD w = pddsd1->dwWidth;
  484. DWORD h = pddsd1->dwHeight;
  485. LONG pitch1 = pddsd1->lPitch;
  486. LONG pitch2 = pddsd2->lPitch;
  487. unsigned __int32 *pPixels1 = (unsigned __int32 *)pddsd1->lpSurface;
  488. unsigned __int32 *pPixels2 = (unsigned __int32 *)pddsd2->lpSurface;
  489. signed __int16 cm1[4];
  490. signed __int16 cm2[4];
  491. signed __int16 cm3[4];
  492. signed __int16 cm4[4];
  493. int loops_per_scanline = w/2;
  494. int extra_bytes_per_scanline_src = pitch1 - w*4;
  495. int extra_bytes_per_scanline_dest = pitch2 - w*2;
  496. if (eOverlayFormat == UYVY) // U Y V Y
  497. {
  498. // swap 0<->1, and 2<->3
  499. cm1[1] = 77/2; cm1[0] = -38/2; cm1[3] = 77/2; cm1[2] = 110/2;
  500. cm2[1] = 150/2; cm2[0] = -74/2; cm2[3] = 150/2; cm2[2] = -92/2;
  501. cm3[1] = 29/2; cm3[0] = 112/2; cm3[3] = 29/2; cm3[2] = -18/2;
  502. cm4[1] = 0; cm4[0] = 32768/2; cm4[3] = 0; cm4[2] = 32768/2;
  503. }
  504. else // Y U Y 2
  505. {
  506. // (laptop)
  507. cm1[0] = 77/2; cm1[1] = -38/2; cm1[2] = 77/2; cm1[3] = 110/2;
  508. cm2[0] = 150/2; cm2[1] = -74/2; cm2[2] = 150/2; cm2[3] = -92/2;
  509. cm3[0] = 29/2; cm3[1] = 112/2; cm3[2] = 29/2; cm3[3] = -18/2;
  510. cm4[0] = 0; cm4[1] = 32768/2; cm4[2] = 0; cm4[3] = 32768/2;
  511. }
  512. __asm
  513. {
  514. mov edx, h
  515. mov esi, pPixels1
  516. mov edi, pPixels2
  517. sub edi, 4 // pre-subtract
  518. movq mm4, cm4
  519. movq mm5, cm1
  520. movq mm6, cm2
  521. movq mm7, cm3
  522. ALIGN 8
  523. yuvscanlineloop:
  524. mov ecx, loops_per_scanline
  525. ALIGN 8
  526. yuvloop:
  527. /*
  528. // prefetch
  529. test ecx, 0x000001ff
  530. jnz PROCESS_PIXEL_MMX32 // every 256th pixel do some prefetches
  531. mov ebx, 2*256 // need to prefetch 256*6 bytes
  532. ALIGN 8
  533. LOAD_ESI_ARRAY_MMX32:
  534. mov eax, [ebx+esi]
  535. mov eax, [ebx+esi+32]
  536. sub ebx, 64
  537. jnz LOAD_ESI_ARRAY_MMX32
  538. ALIGN 8
  539. PROCESS_PIXEL_MMX32:
  540. */
  541. // read in 2 pixels
  542. movq mm0, qword ptr [esi] // -- b1 g1 r1 -- b2 g2 r2
  543. movq mm1, qword ptr [esi] // -- b1 g1 r1 -- b2 g2 r2
  544. movq mm2, qword ptr [esi] // -- b1 g1 r1 -- b2 g2 r2
  545. // quick reference:
  546. // punpcklbw mm7, mm7 // abcdefgh -> eeffgghh
  547. // punpcklbw mm7, mm0 // abcdefgh -> 0e0f0g0h (if mm0 is zero)
  548. // packuswb mm7, mm7 // 0a0b0g0r -> abgrabgr ?
  549. // step 1: get to this state:
  550. // mm0: r1 r1 r2 r2
  551. // mm1: g1 g1 g2 g2
  552. // mm2: b1 b1 b2 b2
  553. // mm3: junk
  554. // mm4: 0 32k 0 32k
  555. // mm5: c1r1 c1r2 c2r1 c2r2
  556. // mm6: c1g1 c1g2 c2g1 c2g2
  557. // mm7: c1b1 c1b2 c2b1 c2b2
  558. // NOTE: the shifts of 8, 16, and 24 below are
  559. // correct (vs. 0-8-16) but might be in
  560. // backwards order!
  561. pslld mm0, 8
  562. pslld mm1, 16
  563. pslld mm2, 24
  564. psrld mm0, 24 // 00 00 00 r1 00 00 00 r2
  565. psrld mm1, 24 // 00 00 00 g1 00 00 00 g2
  566. psrld mm2, 24 // 00 00 00 b1 00 00 00 b2
  567. movq mm3, mm0
  568. pslld mm0, 16
  569. por mm0, mm3 // 00 r1 00 r1 00 r2 00 r2
  570. movq mm3, mm1
  571. pslld mm1, 16
  572. por mm1, mm3 // 00 g1 00 g1 00 g2 00 g2
  573. movq mm3, mm2
  574. pslld mm2, 16
  575. por mm2, mm3 // 00 b1 00 b1 00 b2 00 b2
  576. // step 2: multiply to get to this state:
  577. // mm0: r1*c1r1 r1*c1r2 r2*c2r1 r2*c2r2
  578. // mm1: g1*c1g1 g1*c1g2 g2*c2g1 g2*c2g2
  579. // mm2: b1*c1b1 b1*c1b2 b2*c2b1 b2*c2b2
  580. // mm4: 0 32k 0 32k
  581. pmullw mm0, mm5
  582. add edi, 4
  583. pmullw mm1, mm6
  584. add esi, 8
  585. pmullw mm2, mm7
  586. // step 3: add to get to this state:
  587. // mm0: d1*256 d2*256 d3*256 d4*256
  588. paddsw mm0, mm4
  589. paddsw mm0, mm1
  590. paddsw mm0, mm2
  591. psrlw mm0, 7
  592. packuswb mm0, mm0 // bytes: abgrabgr
  593. movd dword ptr [edi], mm0 // store
  594. loop yuvloop
  595. // scanline complete
  596. add esi, extra_bytes_per_scanline_src
  597. add edi, extra_bytes_per_scanline_dest
  598. dec edx
  599. jnz yuvscanlineloop
  600. emms
  601. }
  602. return true;
  603. }
  604. #else
  605. bool CopyRGBSurfaceToYUVSurface(
  606. LPDDSURFACEDESC pddsd1,
  607. LPDDSURFACEDESC pddsd2,
  608. fourcc_enum eOverlayFormat)
  609. {
  610. if (pddsd1->dwWidth != pddsd2->dwWidth)
  611. return false;
  612. if (pddsd1->dwHeight != pddsd2->dwHeight)
  613. return false;
  614. DWORD w = pddsd1->dwWidth;
  615. DWORD h = pddsd1->dwHeight;
  616. LONG pitch1 = pddsd1->lPitch;
  617. LONG pitch2 = pddsd2->lPitch;
  618. unsigned __int32 *pPixels1 = (unsigned __int32 *)pddsd1->lpSurface;
  619. unsigned __int32 *pPixels2 = (unsigned __int32 *)pddsd2->lpSurface;
  620. unsigned __int32 color1;
  621. LONG offset1 = 0;
  622. LONG offset2 = 0;
  623. unsigned int R, G, B, i1, i2, i3, i4;
  624. BYTE yuv[4];
  625. if (eOverlayFormat == UYVY) // U Y V Y
  626. {
  627. i1 = 1;
  628. i2 = 0;
  629. i3 = 3;
  630. i4 = 2;
  631. }
  632. else // Y U Y 2
  633. {
  634. i1 = 0;
  635. i2 = 1;
  636. i3 = 2;
  637. i4 = 3;
  638. }
  639. // Go through the image 2 pixels at a time and convert to YUV
  640. for (unsigned int y=0; y<h; y++)
  641. {
  642. offset1 = y*pitch1/4;
  643. offset2 = y*pitch2/4;
  644. for (unsigned int x=0; x<w; x+=2)
  645. {
  646. color1 = pPixels1[offset1++];
  647. B = (color1) & 0xFF;
  648. G = (color1 >> 8) & 0xFF;
  649. R = (color1 >> 16) & 0xFF;
  650. yuv[i1] = (77*R + 150*G + 29*B) >> 8;
  651. yuv[i2] = (32768 - 38*R - 74*G + 112*B) >> 8;
  652. color1 = pPixels1[offset1++];
  653. B = (color1) & 0xFF;
  654. G = (color1 >> 8) & 0xFF;
  655. R = (color1 >> 16) & 0xFF;
  656. yuv[i3] = (77*R + 150*G + 29*B) >> 8;
  657. yuv[i4] = (32768 + 110*R - 92*G - 18*B) >> 8;
  658. pPixels2[offset2++] = *((unsigned __int32 *)yuv);
  659. }
  660. }
  661. return true;
  662. }
  663. #endif
  664. int DDraw_Init()
  665. {
  666. InitializeCriticalSection(&g_cs);
  667. return 0;
  668. }
  669. void DDraw_Quit(void)
  670. {
  671. if (g_lpDD)
  672. {
  673. if (g_lpPrimSurf)
  674. {
  675. g_lpPrimSurf->Release();
  676. g_lpPrimSurfBack=g_lpPrimSurf=NULL;
  677. }
  678. if (g_lpRenderSurf[0]) g_lpRenderSurf[0]->Release();
  679. if (g_lpRenderSurf[1]) g_lpRenderSurf[1]->Release();
  680. g_lpRenderSurf[0]=0;
  681. g_lpRenderSurf[1]=0;
  682. if (g_lpddsOverlay) g_lpddsOverlay->Release();
  683. if (g_lpddsPrimary) g_lpddsPrimary->Release();
  684. g_lpddsOverlay=g_lpddsPrimary=NULL;
  685. g_lpDD->Release();
  686. g_lpDD=NULL;
  687. DD_RestoreBkgndSettings();
  688. }
  689. DeleteCriticalSection(&g_cs);
  690. }
  691. void DDraw_BeginResize(void)
  692. {
  693. if (!g_fs) nodraw=1;
  694. }
  695. void DDraw_Resize(int w, int h, int dsize)
  696. {
  697. if (!g_fs) DD_CreateSurfaces(w, h, 0, 0, 0, 0, !!dsize, 0);
  698. }
  699. static void *g_lpsurf[2];
  700. static DDSURFACEDESC d={sizeof(d),};
  701. static DDSURFACEDESC d2={sizeof(d),};
  702. void DDraw_Enter(int *w, int *h, int **fb1, int **fb2)
  703. {
  704. HRESULT han;
  705. if (nodraw)
  706. {
  707. *fb1=*fb2=0;
  708. return;
  709. }
  710. EnterCriticalSection(&g_cs);
  711. *w=g_w;
  712. *h=g_h;
  713. if (!g_lpDD || !g_lpRenderSurf[0] || !g_lpRenderSurf[1])
  714. {
  715. *fb1=*fb2=0;
  716. LeaveCriticalSection(&g_cs);
  717. return;
  718. }
  719. if ((han = g_lpRenderSurf[0]->Lock(NULL,&d,DDLOCK_WAIT,NULL)) != DD_OK)
  720. {
  721. *fb1=*fb2=0;
  722. LeaveCriticalSection(&g_cs);
  723. return;
  724. }
  725. if ((han = g_lpRenderSurf[1]->Lock(NULL,&d2,DDLOCK_WAIT,NULL)) != DD_OK)
  726. {
  727. g_lpRenderSurf[0]->Unlock(d.lpSurface);
  728. *fb1=*fb2=0;
  729. LeaveCriticalSection(&g_cs);
  730. return;
  731. }
  732. *fb1=(int*)(g_lpsurf[0]=d.lpSurface);
  733. *fb2=(int*)(g_lpsurf[1]=d2.lpSurface);
  734. if (g_fs && g_fs_height!=g_h)// && !cfg_fs_use_overlay)
  735. {
  736. int y=g_h/2-((g_fs_height/2));
  737. *h-=y*2;
  738. *fb1 += y*g_w;
  739. *fb2 += y*g_w;
  740. }
  741. }
  742. static unsigned int draw_title_time;
  743. static char last_title[1024];
  744. extern HWND hwnd_WinampParent;
  745. static void do_gettitle()
  746. {
  747. if (draw_title_p < 1 && --draw_title_p < -7)
  748. {
  749. char this_title[2048]={0,};
  750. char *p;
  751. if (IsWindow(hwnd_WinampParent))
  752. {
  753. DWORD id;
  754. if (!SendMessageTimeout( hwnd_WinampParent,WM_GETTEXT,(WPARAM)sizeof(this_title),(LPARAM)this_title,SMTO_BLOCK,50,&id) || !id) return;
  755. }
  756. p = this_title+strlen(this_title);
  757. while (p >= this_title)
  758. {
  759. char buf[9];
  760. memcpy(buf,p,8);
  761. buf[8]=0;
  762. if (!lstrcmpi(buf,"- Winamp")) break;
  763. p--;
  764. }
  765. if (p >= this_title) p--;
  766. while (p >= this_title && *p == ' ') p--;
  767. *++p=0;
  768. if (lstrcmpi(this_title,last_title))
  769. {
  770. strcpy(last_title,this_title);
  771. draw_title_p=1;
  772. draw_title_time=GetTickCount()+1000;
  773. }
  774. else draw_title_p=0;
  775. }
  776. if (draw_title_p == 2)
  777. {
  778. draw_title_p=1;
  779. draw_title_time=GetTickCount()+1000;
  780. }
  781. }
  782. char statustext[256];
  783. DWORD statustext_life;
  784. int statustext_len;
  785. void DDraw_SetStatusText(char *text, int life)
  786. {
  787. strcpy(statustext,text);
  788. statustext_len=life?life:2000;
  789. statustext_life=1;
  790. }
  791. #ifndef NO_X86ASM
  792. void homemadeBlitFrom32bpp(DDSURFACEDESC *out, void *in, int w, int h, int sy, int ey)
  793. {
  794. int mh=min(h,(int)out->dwHeight);
  795. if (sy < 0) sy=0;
  796. if (ey > mh) ey=mh;
  797. if (out->ddpfPixelFormat.dwRGBBitCount == 15)
  798. {
  799. int y;
  800. int mw;
  801. mw=min(w,out->lPitch/2);
  802. unsigned int *inptr=(unsigned int *)in + w*sy;
  803. for (y = sy; y < ey; y ++)
  804. {
  805. unsigned char *optr = (unsigned char *)out->lpSurface + (y * out->lPitch);
  806. __asm
  807. {
  808. mov edi, optr
  809. mov esi, inptr
  810. mov ecx, mw
  811. mov ebx, 00000000111110001111100011111000b
  812. shr ecx, 1
  813. conv15_loop:
  814. mov eax,[esi]
  815. mov edx,[esi+4]
  816. and eax, ebx
  817. and edx, ebx
  818. // 00000000RRRRR000GGGGG000BBBBB000
  819. shr ah,3 // 00000000RRRRR000000GGGGGBBBBB000
  820. shr dh,3
  821. shr ax,3 // 00000000RRRRR000000000GGGGGBBBBB
  822. shr dx,3
  823. // ----------------HHHHHHHHLLLLLLLL
  824. ror eax,10// GGGGGBBBBB00000000RRRRR000000000
  825. ror edx,10
  826. shr ah,1
  827. shr dh,1
  828. mov al,ah
  829. mov dl,dh
  830. rol eax,10
  831. rol edx,10
  832. shl edx, 16
  833. and eax, 0x0000ffff
  834. add esi,8
  835. or eax, edx
  836. mov [edi], eax
  837. add edi, 4
  838. dec ecx
  839. jnz conv15_loop
  840. }
  841. inptr += w;
  842. }
  843. }
  844. else if (out->ddpfPixelFormat.dwRGBBitCount == 16)
  845. {
  846. int y;
  847. int mw;
  848. mw=min(w,out->lPitch/2);
  849. unsigned int *inptr=(unsigned int *)in + w*sy;
  850. for (y = sy; y < ey; y ++)
  851. {
  852. unsigned char *optr = (unsigned char *)out->lpSurface + (y * out->lPitch);
  853. __asm
  854. {
  855. mov edi, optr
  856. mov esi, inptr
  857. mov ecx, mw
  858. mov ebx, 00000000111110001111110011111000b
  859. shr ecx, 1
  860. conv16_loop:
  861. mov eax,[esi]
  862. mov edx,[esi+4]
  863. and eax, ebx
  864. and edx, ebx
  865. // RRRRR000GGGGGG00BBBBB000
  866. shr ah,2 // RRRRR00000GGGGGGBBBBB000
  867. shr dh,2
  868. shr ax,3 // RRRRR00000000GGGGGGBBBBB
  869. shr dx,3
  870. ror eax,8 // GGGBBBBBRRRRR00000000GGG
  871. ror edx,8
  872. add al,ah // GGGBBBBBRRRRR000RRRRRGGG
  873. add dl,dh
  874. rol eax,8 // RRRRR000RRRRRGGGGGGBBBBB
  875. rol edx,8
  876. shl edx, 16
  877. and eax, 0x0000ffff
  878. add esi,8
  879. or eax, edx
  880. mov [edi], eax
  881. add edi, 4
  882. dec ecx
  883. jnz conv16_loop
  884. }
  885. inptr += w;
  886. }
  887. }
  888. else if (out->ddpfPixelFormat.dwRGBBitCount == 24)
  889. { // very unoptimized
  890. int y,x;
  891. int mw;
  892. unsigned int *inptr=(unsigned int *)in+sy;
  893. mw=min(w,out->lPitch/3);
  894. for (y = sy; y < ey; y ++)
  895. {
  896. unsigned char *optr = (unsigned char *)out->lpSurface + (y * out->lPitch);
  897. x=mw/2;
  898. while (x--)
  899. {
  900. int a=inptr[0];
  901. int b=inptr[1];
  902. optr[0]=(unsigned char) a;
  903. optr[3]=(unsigned char) b;
  904. optr[1]=(unsigned char) (a>>8);
  905. optr[4]=(unsigned char) (b>>8);
  906. optr[2]=(unsigned char) (a>>16);
  907. optr[5]=(unsigned char) (b>>16);
  908. optr+=6;
  909. inptr+=2;
  910. }
  911. inptr += (w-mw);
  912. }
  913. }
  914. else
  915. {
  916. unsigned char *outptr;
  917. unsigned int *inptr;
  918. int mw=min(w*4,out->lPitch);
  919. int y;
  920. inptr=(unsigned int*)in + (sy*w);
  921. outptr=(unsigned char *)out->lpSurface + (sy*out->lPitch);
  922. for (y = sy; y < ey; y ++)
  923. {
  924. memcpy(outptr,inptr,mw);
  925. inptr+=w;
  926. outptr+=out->lPitch;
  927. }
  928. }
  929. }
  930. #endif
  931. static int unlocksurfaces()
  932. {
  933. int a=0;
  934. if (g_lpRenderSurf[0] && g_lpRenderSurf[0]->Unlock(g_lpsurf[0]) != DD_OK) a=1;
  935. if (g_lpRenderSurf[1] && g_lpRenderSurf[1]->Unlock(g_lpsurf[1]) != DD_OK) a=1;
  936. return a;
  937. }
  938. void DDraw_Exit(int which)
  939. {
  940. if (!g_lpRenderSurf[0] || !g_lpRenderSurf[1])
  941. {
  942. unlocksurfaces();
  943. goto endfunc;
  944. }
  945. #ifdef RESIZE_ONRESIZE
  946. last_used=which;
  947. #endif
  948. if (g_fs && !cfg_fs_use_overlay)
  949. {
  950. int fsy=g_h/2-((g_fs_height/2));
  951. RECT r={0,0,g_w,g_h};
  952. if (g_bpp != 32) // non-32bpp mode
  953. {
  954. if (fsy>0 && ((cfg_fs_fps&1) || (statustext_life&&!(cfg_fs_fps&8)))) // clear portions of backbuffer if necessary
  955. {
  956. DDBLTFX ddbfx={sizeof(ddbfx),};
  957. int ty=min(fsy,16);
  958. RECT r2={0,0,g_w,ty};
  959. g_lpPrimSurfBack->Blt(&r2,NULL,NULL,DDBLT_WAIT|DDBLT_COLORFILL,&ddbfx);
  960. r2.top=g_h-ty;
  961. r2.bottom=g_h-1;
  962. g_lpPrimSurfBack->Blt(&r2,NULL,NULL,DDBLT_WAIT|DDBLT_COLORFILL,&ddbfx);
  963. }
  964. #ifndef NO_X86ASM
  965. if (!(g_fs_flip&8) && !g_windowed_dsize) // homemade bltshit
  966. {
  967. DDSURFACEDESC d={sizeof(d),};
  968. HRESULT han;
  969. han = g_lpPrimSurfBack->Lock(NULL,&d,DDLOCK_WAIT,NULL);
  970. if (han == DDERR_SURFACELOST)
  971. {
  972. DDBLTFX ddbfx={sizeof(ddbfx),};
  973. g_lpPrimSurfBack->Restore();
  974. g_lpPrimSurfBack->Blt(NULL,NULL,NULL,DDBLT_WAIT|DDBLT_COLORFILL,&ddbfx);
  975. han = g_lpPrimSurfBack->Lock(NULL,&d,DDLOCK_WAIT,NULL);
  976. }
  977. if (han != DD_OK) goto slow_fs_non32bpp;
  978. homemadeBlitFrom32bpp(&d,g_lpsurf[which],g_w,g_h,fsy,g_h-fsy);
  979. int a=0;
  980. if (g_lpPrimSurfBack->Unlock(d.lpSurface) != DD_OK ) a=1;
  981. if (unlocksurfaces()||a)
  982. {
  983. goto endfunc;
  984. }
  985. }
  986. else // slow (stretchblt)
  987. #endif
  988. {
  989. HDC in, out;
  990. #ifndef NO_X86ASM
  991. slow_fs_non32bpp:
  992. #endif
  993. if (unlocksurfaces() || g_lpPrimSurfBack->GetDC(&out) != DD_OK)
  994. {
  995. goto endfunc;
  996. }
  997. if (g_lpRenderSurf[which]->GetDC(&in) != DD_OK)
  998. {
  999. g_lpPrimSurfBack->ReleaseDC(out);
  1000. goto endfunc;
  1001. }
  1002. if (g_windowed_dsize) StretchBlt(out,0,fsy*2,g_dsw,g_dsh-fsy*4,in,0,fsy,g_w,g_h-fsy*2,SRCCOPY);
  1003. else BitBlt(out,0,fsy,g_w,g_h-fsy*2,in,0,fsy,SRCCOPY);
  1004. g_lpRenderSurf[which]->ReleaseDC(in);
  1005. g_lpPrimSurfBack->ReleaseDC(out);
  1006. }
  1007. }
  1008. else // 32bpp - always just use Blt() - will scale if necessary (yay Blt!)
  1009. {
  1010. //RECT or={0,g_go_fs_h/2-g_go_fs_height/2,g_go_fs_w,g_go_fs_h/2+g_go_fs_height/2};
  1011. //RECT ir={0,g_h/2-g_go_fs_height/2,g_w,g_h/2+g_go_fs_height/2};
  1012. if (unlocksurfaces())
  1013. {
  1014. goto endfunc;
  1015. }
  1016. if (g_lpPrimSurfBack->Blt(NULL,g_lpRenderSurf[which],&r,DDBLT_WAIT,NULL) == DDERR_SURFACELOST)
  1017. {
  1018. DDBLTFX ddbfx={sizeof(ddbfx),};
  1019. if (g_fs_flip&1)
  1020. {
  1021. g_lpPrimSurfBack->Restore();
  1022. g_lpPrimSurfBack->Blt(NULL,NULL,NULL,DDBLT_WAIT|DDBLT_COLORFILL,&ddbfx);
  1023. }
  1024. g_lpPrimSurf->Restore();
  1025. g_lpPrimSurf->Blt(NULL,NULL,NULL,DDBLT_WAIT|DDBLT_COLORFILL,&ddbfx);
  1026. goto endfunc;
  1027. }
  1028. }
  1029. do_gettitle();
  1030. if ((cfg_fs_fps&1) || (draw_title_p>0&&!(cfg_fs_fps&16)) || (statustext_life&&!(cfg_fs_fps&8)))
  1031. {
  1032. HDC out;
  1033. if (g_lpPrimSurfBack->GetDC(&out) == DD_OK)
  1034. {
  1035. char str[2048];
  1036. SetBkMode(out,TRANSPARENT);
  1037. if (cfg_fs_fps&1)
  1038. {
  1039. RECT r={2,2,g_fs_w,g_fs_h};
  1040. wsprintf(str,"%d.%d",g_dlg_fps/10,g_dlg_fps%10);
  1041. SetTextColor(out,RGB(0,0,0));
  1042. DrawText(out,str,-1,&r,DT_TOP|DT_LEFT|DT_SINGLELINE|DT_NOCLIP|DT_NOPREFIX);
  1043. r.left=r.top=0;
  1044. SetTextColor(out,RGB(255,255,255));
  1045. DrawText(out,str,-1,&r,DT_TOP|DT_LEFT|DT_SINGLELINE|DT_NOCLIP|DT_NOPREFIX);
  1046. }
  1047. if (statustext_life&&!(cfg_fs_fps&8))
  1048. {
  1049. if (statustext_life==1) statustext_life=GetTickCount()+statustext_len;
  1050. RECT r={0,0,g_fs_w,g_fs_h};
  1051. if (GetTickCount() > statustext_life)
  1052. {
  1053. if (statustext_life==2) statustext_life=0;
  1054. else statustext_life=2;
  1055. }
  1056. else
  1057. {
  1058. SetTextColor(out,RGB(0,0,0));
  1059. DrawText(out,statustext,-1,&r,DT_BOTTOM|DT_RIGHT|DT_SINGLELINE|DT_NOPREFIX);
  1060. SetTextColor(out,RGB(255,255,255));
  1061. r.right-=2;
  1062. r.bottom-=2;
  1063. DrawText(out,statustext,-1,&r,DT_BOTTOM|DT_RIGHT|DT_SINGLELINE|DT_NOPREFIX);
  1064. }
  1065. }
  1066. if (draw_title_p>0&&!(cfg_fs_fps&16))
  1067. {
  1068. RECT r={4,4,g_fs_w,g_fs_h};
  1069. SetTextColor(out,RGB(0,0,0));
  1070. DrawText(out,last_title,-1,&r,DT_VCENTER|DT_CENTER|DT_SINGLELINE|DT_NOPREFIX);
  1071. r.left=r.top=0;
  1072. SetTextColor(out,RGB(255,255,255));
  1073. DrawText(out,last_title,-1,&r,DT_VCENTER|DT_CENTER|DT_SINGLELINE|DT_NOPREFIX);
  1074. }
  1075. g_lpPrimSurfBack->ReleaseDC(out);
  1076. }
  1077. if (draw_title_p>0 && draw_title_time < GetTickCount() && !(cfg_fs_fps&16))
  1078. {
  1079. if (g_lpRenderSurf[which]->GetDC(&out) == DD_OK)
  1080. {
  1081. RECT r={4,4,g_w,g_h};
  1082. SetBkMode(out,TRANSPARENT);
  1083. SetTextColor(out,RGB(0,0,0));
  1084. DrawText(out,last_title,-1,&r,DT_VCENTER|DT_CENTER|DT_SINGLELINE|DT_NOPREFIX);
  1085. r.left=r.top=0;
  1086. SetTextColor(out,RGB(255,255,255));
  1087. DrawText(out,last_title,-1,&r,DT_VCENTER|DT_CENTER|DT_SINGLELINE|DT_NOPREFIX);
  1088. g_lpRenderSurf[which]->ReleaseDC(out);
  1089. }
  1090. draw_title_p=0;
  1091. }
  1092. }
  1093. if (g_fs_flip&1) g_lpPrimSurf->Flip(NULL, DDFLIP_WAIT);
  1094. else if (!(g_fs_flip&2)) g_lpDD->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN,0);
  1095. }
  1096. else
  1097. {
  1098. if(g_overlay_init_ok)
  1099. {
  1100. LPDDSURFACEDESC pd=(which==0?&d:&d2);
  1101. DDSURFACEDESC dd={sizeof(dd),};
  1102. if (g_fs) if (!(cfg_fs_flip&2)) g_lpDD->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN,0);
  1103. if (g_lpddsOverlay->Lock(NULL,&dd,DDLOCK_WAIT,NULL) != DD_OK)
  1104. {
  1105. g_overlay_init_ok=0;
  1106. goto endfunc;
  1107. }
  1108. #ifndef NO_MMX
  1109. CopyRGBSurfaceToYUVSurfaceMMX(pd,&dd,g_overlay_fourcc);
  1110. #else
  1111. CopyRGBSurfaceToYUVSurface(pd,&dd,g_overlay_fourcc);
  1112. #endif
  1113. g_lpddsOverlay->Unlock(&dd);
  1114. if (g_fs)
  1115. {
  1116. unlocksurfaces();
  1117. goto endfunc;
  1118. }
  1119. }
  1120. HDC in1, out, in2=NULL;
  1121. if (unlocksurfaces() || g_lpRenderSurf[which]->GetDC(&in1) != DD_OK)
  1122. {
  1123. goto endfunc;
  1124. }
  1125. do_gettitle();
  1126. if (draw_title_p>0&&!(cfg_fs_fps&4) && draw_title_time < GetTickCount())
  1127. {
  1128. RECT r={4,4,g_w,g_h};
  1129. SetBkMode(in1,TRANSPARENT);
  1130. SetTextColor(in1,RGB(0,0,0));
  1131. DrawText(in1,last_title,-1,&r,DT_VCENTER|DT_CENTER|DT_SINGLELINE|DT_NOPREFIX);
  1132. r.left=r.top=0;
  1133. SetTextColor(in1,RGB(255,255,255));
  1134. DrawText(in1,last_title,-1,&r,DT_VCENTER|DT_CENTER|DT_SINGLELINE|DT_NOPREFIX);
  1135. draw_title_p=0;
  1136. }
  1137. if ((draw_title_p > 0&&!(cfg_fs_fps&4)) || (statustext_life&&!(cfg_fs_fps&2)))
  1138. {
  1139. // draw perframe
  1140. RECT r={4,4,g_w,g_h};
  1141. if (g_lpRenderSurf[which^1]->GetDC(&in2) != DD_OK)
  1142. {
  1143. in2=NULL;
  1144. goto abort_thingy;
  1145. }
  1146. BitBlt(in2,0,0,g_w,g_h,in1,0,0,SRCCOPY);
  1147. SetBkMode(in2,TRANSPARENT);
  1148. if (draw_title_p > 0&&!(cfg_fs_fps&4))
  1149. {
  1150. SetTextColor(in2,RGB(0,0,0));
  1151. DrawText(in2,last_title,-1,&r,DT_VCENTER|DT_CENTER|DT_SINGLELINE|DT_NOPREFIX);
  1152. r.left=r.top=0;
  1153. SetTextColor(in2,RGB(255,255,255));
  1154. DrawText(in2,last_title,-1,&r,DT_VCENTER|DT_CENTER|DT_SINGLELINE|DT_NOPREFIX);
  1155. }
  1156. if (statustext_life&&!(cfg_fs_fps&2))
  1157. {
  1158. if (statustext_life==1) statustext_life=GetTickCount()+statustext_len;
  1159. if (GetTickCount() > statustext_life) statustext_life=0;
  1160. SetTextColor(in2,RGB(0,0,0));
  1161. DrawText(in2,statustext,-1,&r,DT_BOTTOM|DT_RIGHT|DT_SINGLELINE|DT_NOPREFIX);
  1162. r.right-=2;
  1163. r.bottom-=2;
  1164. SetTextColor(in2,RGB(255,255,255));
  1165. DrawText(in2,statustext,-1,&r,DT_BOTTOM|DT_RIGHT|DT_SINGLELINE|DT_NOPREFIX);
  1166. }
  1167. }
  1168. abort_thingy:
  1169. if (!(cfg_fs_flip&4)) g_lpDD->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN,0);
  1170. out=GetDC(g_hwnd);
  1171. if (out)
  1172. {
  1173. if (!g_windowed_dsize)
  1174. {
  1175. #ifndef WA2_EMBED
  1176. BitBlt(out,inWharf?0:7,inWharf?0:15,g_w-g_noshoww,g_h,in2?in2:in1,0,0,SRCCOPY);
  1177. #else
  1178. BitBlt(out,0,0,g_w-g_noshoww,g_h,in2?in2:in1,0,0,SRCCOPY);
  1179. #endif
  1180. }
  1181. else
  1182. {
  1183. #ifndef WA2_EMBED
  1184. StretchBlt(out,inWharf?0:7,inWharf?0:15,g_dsw,g_dsh,in2?in2:in1,0,0,g_w,g_h,SRCCOPY);
  1185. #else
  1186. StretchBlt(out,0,0,g_dsw,g_dsh,in2?in2:in1,0,0,g_w,g_h,SRCCOPY);
  1187. #endif
  1188. }
  1189. ReleaseDC(g_hwnd,out);
  1190. }
  1191. g_lpRenderSurf[which]->ReleaseDC(in1);
  1192. if (in2)
  1193. g_lpRenderSurf[which^1]->ReleaseDC(in2);
  1194. }
  1195. endfunc:
  1196. LeaveCriticalSection(&g_cs);
  1197. }
  1198. void DDraw_SetFullScreen(int fs, int w, int h, int dbl, int bpp)
  1199. {
  1200. if (!fs) DD_CreateSurfaces(w, h, 0, 0, 0, 0, !!dbl, 0);
  1201. else
  1202. {
  1203. DD_CreateSurfaces(w, h, (min(max(1,cfg_fs_height),100)*h)/100, 1, bpp, cfg_fs_flip, !!dbl, cfg_fs_use_overlay);
  1204. }
  1205. }
  1206. int DDraw_IsFullScreen(void)
  1207. {
  1208. return g_fs;
  1209. }
  1210. HRESULT WINAPI _cb(
  1211. LPDDSURFACEDESC lpDDSurfaceDesc, LPVOID lpContext)
  1212. {
  1213. HWND h=(HWND)lpContext;
  1214. if ((lpDDSurfaceDesc->ddpfPixelFormat.dwFlags & DDPF_RGB) &&
  1215. (lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount==32 ||
  1216. lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount==24 ||
  1217. lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount==16 ||
  1218. lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount==15))
  1219. {
  1220. char s[256];
  1221. wsprintf(s,"%dx%d@%dBPP",lpDDSurfaceDesc->dwWidth,lpDDSurfaceDesc->dwHeight,lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount);
  1222. SendMessage(h,CB_ADDSTRING,0,(long)s);
  1223. }
  1224. return DDENUMRET_OK;
  1225. }
  1226. void DDraw_EnumDispModes(HWND hwnd)
  1227. {
  1228. if (g_lpDD)
  1229. g_lpDD->EnumDisplayModes(0,NULL,hwnd,_cb);
  1230. }
  1231. static int g_st;
  1232. HRESULT WINAPI _cb2(
  1233. LPDDSURFACEDESC lpDDSurfaceDesc, LPVOID lpContext)
  1234. {
  1235. DWORD *x=(DWORD *)lpContext;
  1236. if (x[0]==lpDDSurfaceDesc->dwWidth &&
  1237. x[1]==lpDDSurfaceDesc->dwHeight &&
  1238. x[2]==lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount)
  1239. {
  1240. g_st=1;
  1241. return DDENUMRET_CANCEL;
  1242. }
  1243. return DDENUMRET_OK;
  1244. }
  1245. int DDraw_IsMode(int w, int h, int bpp)
  1246. {
  1247. int x[3]={w,h,bpp};
  1248. if (!x[0] || !x[1] || !x[2]) return 0;
  1249. if (!g_lpDD) return 0;
  1250. g_st=0;
  1251. g_lpDD->EnumDisplayModes(0,NULL,(LPVOID)x,_cb2);
  1252. return g_st;
  1253. }
  1254. HRESULT WINAPI _cb3(
  1255. LPDDSURFACEDESC lpDDSurfaceDesc, LPVOID lpContext)
  1256. {
  1257. if ((lpDDSurfaceDesc->ddpfPixelFormat.dwFlags & DDPF_RGB) &&
  1258. (lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount==32 ||
  1259. lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount==24 ||
  1260. lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount==16 ||
  1261. lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount==15))
  1262. {
  1263. int *(*x)=(int **)lpContext;
  1264. if (lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount > (DWORD)x[2][0] ||
  1265. lpDDSurfaceDesc->dwWidth < (DWORD)x[0][0] ||
  1266. lpDDSurfaceDesc->dwHeight < (DWORD)x[1][0])
  1267. {
  1268. x[0][0]=lpDDSurfaceDesc->dwWidth;
  1269. x[1][0]=lpDDSurfaceDesc->dwHeight;
  1270. x[2][0]=lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount;
  1271. }
  1272. }
  1273. return DDENUMRET_OK;
  1274. }
  1275. int DDraw_PickMode(int *w, int *h, int *bpp)
  1276. {
  1277. int *(x[3])={w,h,bpp};
  1278. *w=0;
  1279. *h=0;
  1280. *bpp=0;
  1281. // return if mode found that is suitable
  1282. g_lpDD->EnumDisplayModes(0,NULL,(LPVOID)x,_cb3);
  1283. return *w && *h && *bpp;
  1284. }
  1285. double DDraw_translatePoint(POINT p, int isY)
  1286. {
  1287. double v=0.0;
  1288. if(g_fs && g_overlay_init_ok && hwndOverlayWnd && IsWindow(hwndOverlayWnd))
  1289. {
  1290. RECT r;
  1291. ScreenToClient(hwndOverlayWnd,&p);
  1292. GetClientRect(hwndOverlayWnd,&r);
  1293. if (isY)
  1294. {
  1295. if (r.bottom>0)
  1296. v=p.y/(double)(r.bottom*0.5) - 1.0;
  1297. }
  1298. else
  1299. {
  1300. if (r.right>0)
  1301. v=p.x/(double)(r.right*0.5) - 1.0;
  1302. }
  1303. }
  1304. else
  1305. {
  1306. ScreenToClient(g_hwnd,&p);
  1307. if (isY)
  1308. {
  1309. if (g_dsh>0)
  1310. v=p.y/(double)(g_dsh*0.5) - 1.0;
  1311. }
  1312. else
  1313. {
  1314. if (g_dsw>0)
  1315. v=p.x/(double)(g_dsw*0.5) - 1.0;
  1316. }
  1317. }
  1318. //if (v > 1.0) v=1.0;
  1319. //if (v < -1.0) v=-1.0;
  1320. return v;
  1321. }