aboutsummaryrefslogtreecommitdiff
path: root/Src/Plugins/Visualization/vis_avs/draw.cpp
diff options
context:
space:
mode:
authorJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
committerJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
commit20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch)
tree12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/Plugins/Visualization/vis_avs/draw.cpp
parent537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
Initial community commit
Diffstat (limited to 'Src/Plugins/Visualization/vis_avs/draw.cpp')
-rw-r--r--Src/Plugins/Visualization/vis_avs/draw.cpp1476
1 files changed, 1476 insertions, 0 deletions
diff --git a/Src/Plugins/Visualization/vis_avs/draw.cpp b/Src/Plugins/Visualization/vis_avs/draw.cpp
new file mode 100644
index 00000000..5eddc451
--- /dev/null
+++ b/Src/Plugins/Visualization/vis_avs/draw.cpp
@@ -0,0 +1,1476 @@
+/*
+ LICENSE
+ -------
+Copyright 2005 Nullsoft, Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ * Neither the name of Nullsoft nor the names of its contributors may be used to
+ endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+#include <windows.h>
+#include <ddraw.h>
+#include "draw.h"
+#include <stdio.h>
+#include <process.h>
+#include "r_defs.h"
+#include "resource.h"
+#include "vis.h"
+#include "../Agave/Language/api_language.h"
+
+extern HINSTANCE g_hInstance;
+
+#define RESIZE_ONRESIZE
+int draw_title_p=0;
+int cfg_cancelfs_on_deactivate=1;
+extern int g_dlg_fps,g_dlg_w,g_dlg_h;
+extern int cfg_fs_fps,cfg_fs_flip,cfg_fs_height,cfg_fs_use_overlay;
+extern int cfg_bkgnd_render, cfg_bkgnd_render_color;
+static LPDIRECTDRAW g_lpDD;
+static LPDIRECTDRAWSURFACE g_lpRenderSurf[2], g_lpPrimSurf, g_lpPrimSurfBack;
+static int g_bpp, g_fs, g_noshoww;
+int g_w, g_h, g_dsw, g_dsh;
+extern HWND g_hwnd;
+static CRITICAL_SECTION g_cs;
+static int g_windowed_dsize;
+static int g_initted, g_fs_flip, g_fs_height, g_fs_w, g_fs_h;
+static int nodraw=0;
+extern int inWharf;
+#ifdef RESIZE_ONRESIZE
+static int last_used;
+#endif
+static LPDIRECTDRAWSURFACE g_lpddsOverlay = NULL;
+static LPDIRECTDRAWSURFACE g_lpddsPrimary = NULL;
+static int g_overlay_init_ok=0;
+typedef enum {
+ UYVY,
+ YUY2
+} fourcc_enum;
+static fourcc_enum g_overlay_fourcc=UYVY;
+static int g_saved_desktop_values=0;
+
+static char g_saved_desktop_wallpaper[256];
+static char g_saved_reg_bkgnd_color[64];
+static DWORD g_saved_bkgnd_color;
+
+extern void Wnd_GoWindowed(HWND hwnd);
+
+#define INIT_DIRECTDRAW_STRUCT(x) (ZeroMemory(&x, sizeof(x)), x.dwSize=sizeof(x))
+DDPIXELFORMAT g_ddpfOverlayFormats[] =
+{ {sizeof(DDPIXELFORMAT), DDPF_FOURCC,MAKEFOURCC('U','Y','V','Y'),0,0,0,0,0}, // UYVY
+ {sizeof(DDPIXELFORMAT), DDPF_FOURCC,MAKEFOURCC('Y','U','Y','2'),0,0,0,0,0}}; // YUY2
+
+#define NUM_OVERLAY_FORMATS (sizeof(g_ddpfOverlayFormats) / sizeof(g_ddpfOverlayFormats[0]))
+
+static HWND hwndOverlayWnd;
+
+static LRESULT CALLBACK FSOverlayWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ static unsigned int start_t;
+
+ if (
+
+ (((message == WM_KEYDOWN && (wParam == VK_ESCAPE || wParam == VK_RETURN)) ||
+ message == WM_LBUTTONUP) && GetTickCount()-start_t > 1000)
+
+ ||
+
+ (cfg_cancelfs_on_deactivate && ((message == WM_NCACTIVATE && !wParam) ||
+ message == WM_KILLFOCUS))
+ )
+ {
+ DestroyWindow(hwnd);
+ Wnd_GoWindowed(g_hwnd);
+ return 0;
+ }
+ switch(message)
+ {
+ case WM_CREATE:
+ start_t=GetTickCount();
+ return 0;
+ case WM_SETCURSOR:
+ SetCursor(NULL);
+ return TRUE;
+ case WM_DESTROY:
+ hwndOverlayWnd=0;
+ return 0;
+ case WM_PAINT:
+ {
+ PAINTSTRUCT ps;
+ HDC hdc=BeginPaint(hwnd,&ps);
+ RECT r;
+ GetClientRect(hwnd,&r);
+ int rv=0xff&(cfg_bkgnd_render_color>>16), gv=0xff&(cfg_bkgnd_render_color>>8), bv=0xff&cfg_bkgnd_render_color;
+ HBRUSH b=CreateSolidBrush(RGB(rv,gv,bv));
+ SelectObject(ps.hdc, b);
+ Rectangle(ps.hdc, r.left, r.top, r.right, r.bottom);
+ DeleteObject(b);
+ EndPaint(hwnd,&ps);
+ }
+ return 0;
+ case WM_KEYDOWN:
+ return SendMessage(g_hwnd, message, wParam, lParam);
+ }
+ return DefWindowProc(hwnd, message, wParam, lParam);
+}
+
+static void DD_CreateFullscreenOverlayWindow()
+{
+ static int inited=0;
+ if(!inited)
+ {
+ WNDCLASSW wc={0,};
+ wc.style = CS_DBLCLKS|CS_VREDRAW|CS_HREDRAW;
+ wc.lpfnWndProc = FSOverlayWndProc;
+ wc.hInstance = g_hInstance;
+ wc.hbrBackground = NULL;
+ wc.lpszClassName = L"avsfsoverlaywnd";
+ wc.hCursor=NULL;
+ if(!RegisterClassW(&wc)) return;
+ inited=1;
+ }
+ 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);
+}
+
+static void DD_RestoreBkgndSettings()
+{
+ if (g_saved_desktop_values)
+ {
+ int e=COLOR_DESKTOP;
+ unsigned long c=g_saved_bkgnd_color;
+ SetSysColors(1, &e, &c); // FUCKING MESSAGE PUMP AND SETSYSCOLORS
+ SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, g_saved_desktop_wallpaper, NULL);
+ g_saved_desktop_values=0;
+ }
+}
+
+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)
+{
+ int resize_h=8, resize_w=8;
+#ifdef RESIZE_ONRESIZE
+ int fb_save[64*65+1];
+ int fb_save_use=0;
+#endif
+ EnterCriticalSection(&g_cs);
+ nodraw=0;
+ if (g_lpDD)
+ {
+ extern int config_reuseonresize;
+#ifdef RESIZE_ONRESIZE
+ HRESULT han;
+ int ll=!!last_used;
+ DDSURFACEDESC d={sizeof(d),};
+ if (config_reuseonresize && g_w && g_h && g_lpRenderSurf[ll] &&
+ (han = g_lpRenderSurf[ll]->Lock(NULL,&d,DDLOCK_WAIT,NULL)) == DD_OK)
+ {
+ if (d.lpSurface)
+ {
+ int x,y;
+ int dxpos=(g_w<<16)/64;
+ int ypos=0;
+ int dypos=(g_h<<16)/64;
+ int *pp=((int *)d.lpSurface);
+
+ if (g_fs && g_fs_height < g_h) // adjust to use partial screen when
+ {
+ int fsy=g_h/2-g_fs_height/2;
+ dypos=(g_fs_height<<16)/64;
+ pp+=fsy * g_w;
+ }
+
+ for (y = 0; y < 64; y++)
+ {
+ int *p=pp + g_w * (ypos>>16);
+ int xpos=0;
+ for (x = 0; x < 64; x ++)
+ {
+ fb_save[(y<<6)+x]=p[xpos>>16];
+ xpos+=dxpos;
+ }
+ ypos+=dypos;
+ }
+ memset(fb_save+64*64,0,sizeof(int)*65);
+ fb_save_use=1;
+ }
+ g_lpRenderSurf[ll]->Unlock(d.lpSurface);
+ }
+#endif
+
+ if (g_lpPrimSurf)
+ {
+ g_lpPrimSurf->Release();
+ g_lpPrimSurfBack=g_lpPrimSurf=NULL;
+ }
+ if (g_lpRenderSurf[0]) g_lpRenderSurf[0]->Release();
+ if (g_lpRenderSurf[1]) g_lpRenderSurf[1]->Release();
+ g_lpRenderSurf[0]=0;
+ g_lpRenderSurf[1]=0;
+ if (g_lpddsOverlay) g_lpddsOverlay->Release();
+ if (g_lpddsPrimary) g_lpddsPrimary->Release();
+ g_lpddsOverlay=g_lpddsPrimary=NULL;
+ g_lpDD->Release();
+ g_lpDD=NULL;
+ }
+
+ if (DirectDrawCreate(NULL,&g_lpDD,NULL) != DD_OK)
+ {
+ g_lpDD=NULL;
+ MessageBox(g_hwnd,WASABI_API_LNGSTRING(IDS_ERROR_CREATING_DDRAW_OBJECT),"DDraw",0);
+ LeaveCriticalSection(&g_cs);
+ return;
+ }
+ if (fs && !fsovl)
+ {
+ g_fs_w=w;
+ g_fs_h=h;
+ g_fs_height=fsh>>dbl;
+ g_fs_flip=flip;
+ resize_w=w>>dbl;
+ resize_h=h>>dbl;
+ if (g_lpDD->SetCooperativeLevel(g_hwnd,DDSCL_NOWINDOWCHANGES|DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN) != DD_OK)
+ {
+ fs=0;
+ }
+ else
+ {
+ if (g_lpDD->SetDisplayMode(w,h,fsbpp) != DD_OK)
+ {
+ fs=0;
+ }
+ else
+ {
+ DDSURFACEDESC DDsd={sizeof(DDsd),};
+ DDsd.dwFlags = DDSD_CAPS;
+ DDsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
+ if (g_fs_flip&1)
+ {
+ DDsd.ddsCaps.dwCaps |= DDSCAPS_COMPLEX|DDSCAPS_FLIP;
+ DDsd.dwFlags|=DDSD_BACKBUFFERCOUNT;
+ DDsd.dwBackBufferCount = 1;
+ }
+ if (g_lpDD->CreateSurface(&DDsd, &g_lpPrimSurf, NULL) != DD_OK)
+ {
+ fs=0;
+ }
+ else
+ {
+ DDBLTFX ddbfx={sizeof(ddbfx),};
+ g_lpPrimSurf->Blt(NULL,NULL,NULL,DDBLT_WAIT|DDBLT_COLORFILL,&ddbfx);
+ if (g_fs_flip&1)
+ {
+ DDSCAPS ddscaps;
+ ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
+ if (g_lpPrimSurf->GetAttachedSurface(&ddscaps, &g_lpPrimSurfBack) != DD_OK)
+ {
+ g_lpPrimSurf->Release();
+ fs=0;
+ }
+ else g_lpPrimSurfBack->Blt(NULL,NULL,NULL,DDBLT_WAIT|DDBLT_COLORFILL,&ddbfx);
+ }
+ else
+ g_lpPrimSurfBack=g_lpPrimSurf;
+ }
+ }
+ }
+ SetForegroundWindow(g_hwnd);
+ } else {
+ g_lpDD->SetCooperativeLevel(g_hwnd,DDSCL_NOWINDOWCHANGES|DDSCL_NORMAL);
+ resize_w=(((w>>dbl)+3)&~3);
+ g_noshoww=resize_w-(w>>dbl);
+ resize_h=h>>dbl;
+ }
+ g_fs=fs;
+
+ int wh;
+ for (wh = 0; wh < 2; wh ++)
+ {
+ DDSURFACEDESC DDsd={sizeof(DDsd),};
+ DDsd.dwFlags = DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT|DDSD_PITCH|DDSD_PIXELFORMAT;
+ DDsd.dwWidth=resize_w;
+ DDsd.dwHeight=resize_h;
+ DDsd.lPitch=resize_w*sizeof(int);
+ DDsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN|DDSCAPS_SYSTEMMEMORY;
+ DDsd.ddpfPixelFormat.dwSize = sizeof(DDsd.ddpfPixelFormat);
+ DDsd.ddpfPixelFormat.dwFlags=DDPF_RGB;
+ DDsd.ddpfPixelFormat.dwRGBBitCount = 32;
+ DDsd.ddpfPixelFormat.dwRBitMask=0xff0000;
+ DDsd.ddpfPixelFormat.dwGBitMask=0x00ff00;
+ DDsd.ddpfPixelFormat.dwBBitMask=0x0000ff;
+ if (g_lpDD->CreateSurface(&DDsd, &g_lpRenderSurf[wh], NULL) != DD_OK)
+ {
+ if (wh)
+ {
+ g_lpRenderSurf[0]->Release();
+ g_lpRenderSurf[0]=0;
+ }
+ g_lpRenderSurf[wh]=0;
+ LeaveCriticalSection(&g_cs);
+ return;
+ }
+
+#ifdef RESIZE_ONRESIZE
+ DDSURFACEDESC d={sizeof(d),};
+ HRESULT han;
+ if (fb_save_use && g_lpRenderSurf[wh] &&
+ (han = g_lpRenderSurf[wh]->Lock(NULL,&d,DDLOCK_WAIT,NULL)) == DD_OK)
+ {
+ if (d.lpSurface)
+ {
+ int x,y;
+ int dxpos=(64<<16)/resize_w;
+ int ypos=0;
+ int *p=(int *)d.lpSurface;
+ int h=resize_h;
+
+ if (fs && (fsh>>dbl) < resize_h)
+ {
+ int fsy=resize_h/2-(((fsh>>dbl)/2));
+ p+=fsy * resize_w;
+ h -= fsy*2;
+ }
+ int dypos=(64<<16)/h;
+
+ for (y = 0; y < h; y ++)
+ {
+ int xpos=0;
+ for (x = 0; x < resize_w; x ++)
+ {
+ *p++ = BLEND4_16((unsigned int *)fb_save + ((ypos>>10)&~63) + (xpos>>16),64,xpos,ypos);
+ xpos+=dxpos;
+ }
+ ypos+=dypos;
+ }
+#ifndef NO_MMX
+ __asm emms;
+#endif
+ }
+ g_lpRenderSurf[wh]->Unlock(d.lpSurface);
+ }
+#endif
+ }
+ g_w=resize_w;
+ g_h=resize_h;
+ g_dsh=g_h<<dbl;
+ g_dsw=g_w<<dbl;
+ g_bpp=fs?fsbpp:32;
+ g_windowed_dsize=dbl;
+
+ g_overlay_init_ok=0;
+ if(!(cfg_bkgnd_render&1)) DD_RestoreBkgndSettings();
+ if((cfg_bkgnd_render&1) || (g_fs && fsovl)) {
+ // init overlay stuff
+ DDSURFACEDESC ddsdOverlay;
+ HRESULT ddrval;
+ int i;
+
+ // It's currently not possible to query for pixel formats supported by the
+ // overlay hardware (though GetFourCCCodes() usually provides a partial
+ // list). Instead you need to call CreateSurface() to try a variety of
+ // formats till one works.
+ INIT_DIRECTDRAW_STRUCT(ddsdOverlay);
+ ddsdOverlay.ddsCaps.dwCaps=DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY;
+ ddsdOverlay.dwFlags= DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT|DDSD_PITCH;
+ ddsdOverlay.dwWidth=resize_w;
+ ddsdOverlay.dwHeight=resize_h;
+ ddsdOverlay.lPitch=resize_w*sizeof(int);
+ ddsdOverlay.dwBackBufferCount=0;
+
+ // Try to create an overlay surface using one of the pixel formats in our
+ // global list.
+ i=0;
+ do
+ {
+ ddsdOverlay.ddpfPixelFormat=g_ddpfOverlayFormats[i];
+ // Try to create the overlay surface
+ ddrval = g_lpDD->CreateSurface(&ddsdOverlay, &g_lpddsOverlay, NULL);
+ } while( FAILED(ddrval) && (++i < NUM_OVERLAY_FORMATS) );
+
+ if(!FAILED(ddrval))
+ {
+ g_overlay_fourcc=(fourcc_enum)i;
+
+ HRESULT ddrval;
+ DDSURFACEDESC ddsd;
+ INIT_DIRECTDRAW_STRUCT(ddsd);
+ ddsd.dwFlags = DDSD_CAPS;
+ ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
+ ddrval = g_lpDD->CreateSurface(&ddsd, &g_lpddsPrimary, NULL );
+
+ RECT rs, rd;
+ DDOVERLAYFX ovfx;
+ DDCAPS capsDrv;
+ unsigned int uDestSizeAlign, uSrcSizeAlign;
+ DWORD dwUpdateFlags;
+
+ INIT_DIRECTDRAW_STRUCT(capsDrv);
+ ddrval = g_lpDD->GetCaps(&capsDrv, NULL);
+
+ uDestSizeAlign = capsDrv.dwAlignSizeDest;
+ uSrcSizeAlign = capsDrv.dwAlignSizeSrc;
+
+ dwUpdateFlags = DDOVER_SHOW | DDOVER_DDFX | DDOVER_KEYDESTOVERRIDE;
+
+ DEVMODE d;
+ d.dmSize=sizeof(d);
+ d.dmDriverExtra=0;
+ EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &d);
+
+ int rv=0xff&(cfg_bkgnd_render_color>>16), gv=0xff&(cfg_bkgnd_render_color>>8), bv=0xff&cfg_bkgnd_render_color;
+
+ if(!fsovl)
+ {
+ if (cfg_bkgnd_render&2)
+ {
+ if (!g_saved_desktop_values)
+ {
+ HKEY key;
+ g_saved_desktop_wallpaper[0]=0;
+ g_saved_reg_bkgnd_color[0]=0;
+
+ // get wallpaper
+ if(RegOpenKey(HKEY_CURRENT_USER, "Control Panel\\Desktop",&key)==ERROR_SUCCESS)
+ {
+ unsigned long s=sizeof(g_saved_desktop_wallpaper),vt;
+ RegQueryValueEx(key,"Wallpaper", 0, &vt, (unsigned char *)g_saved_desktop_wallpaper, &s);
+ }
+
+ // get registry bkgnd color
+ if(RegOpenKey(HKEY_CURRENT_USER, "Control Panel\\Colors",&key)==ERROR_SUCCESS)
+ {
+ unsigned long s=sizeof(g_saved_reg_bkgnd_color),vt;
+ RegQueryValueEx(key,"Background", 0, &vt, (unsigned char *)g_saved_reg_bkgnd_color, &s);
+ }
+
+ g_saved_bkgnd_color=GetSysColor(COLOR_DESKTOP);
+ g_saved_desktop_values=1;
+ }
+ int e=COLOR_DESKTOP;
+ unsigned long c=RGB(rv,gv,bv);
+ SetSysColors(1, &e, &c);
+ SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, "", NULL);
+
+ // rewrite registry settings right now so we don't fuck the user desktop if avs crashes
+ {
+ HKEY key;
+ if(RegOpenKey(HKEY_CURRENT_USER, "Control Panel\\Desktop",&key)==ERROR_SUCCESS)
+ RegSetValueEx(key,"Wallpaper", 0, REG_SZ, (unsigned char *)g_saved_desktop_wallpaper, strlen(g_saved_desktop_wallpaper)+1);
+ if(RegOpenKey(HKEY_CURRENT_USER, "Control Panel\\Colors",&key)==ERROR_SUCCESS)
+ RegSetValueEx(key,"Background", 0, REG_SZ, (unsigned char *)g_saved_reg_bkgnd_color, strlen(g_saved_reg_bkgnd_color)+1);
+ }
+ }
+ else DD_RestoreBkgndSettings();
+ }
+
+ INIT_DIRECTDRAW_STRUCT(ovfx);
+ switch(d.dmBitsPerPel)
+ {
+ case 16:
+ ovfx.dckDestColorkey.dwColorSpaceLowValue=((rv>>3) << 11) | ((gv>>2) << 5) | (bv>>3);
+ break;
+ case 15:
+ ovfx.dckDestColorkey.dwColorSpaceLowValue=((rv>>3) << 10) | ((gv>>3) << 5) | (bv>>3);
+ break;
+ case 24: case 32:
+ ovfx.dckDestColorkey.dwColorSpaceLowValue=(rv << 16) | (gv << 8) | bv;
+ break;
+ }
+ ovfx.dckDestColorkey.dwColorSpaceHighValue=ovfx.dckDestColorkey.dwColorSpaceLowValue;
+
+ rs.left=0; rs.top=0;
+ rs.right = resize_w;
+ rs.bottom = resize_h;
+ if (capsDrv.dwCaps & DDCAPS_ALIGNSIZESRC && uSrcSizeAlign)
+ rs.right -= rs.right % uSrcSizeAlign;
+ rd.left=0; rd.top=0;
+ rd.right=GetSystemMetrics(SM_CXSCREEN); rd.bottom=GetSystemMetrics(SM_CYSCREEN);
+ if (capsDrv.dwCaps & DDCAPS_ALIGNSIZEDEST && uDestSizeAlign)
+ rd.right = (int)((rd.right+uDestSizeAlign-1)/uDestSizeAlign)*uDestSizeAlign;
+ // Make the call to UpdateOverlay() which actually displays the overlay on
+ // the screen.
+ ddrval = g_lpddsOverlay->UpdateOverlay(&rs, g_lpddsPrimary, &rd, dwUpdateFlags, &ovfx);
+ if(!FAILED(ddrval)) g_overlay_init_ok=1;
+ }
+ }
+
+ if(g_fs && fsovl)
+ {
+ g_fs_height=fsh>>dbl;
+ DD_CreateFullscreenOverlayWindow();
+ }
+
+ LeaveCriticalSection(&g_cs);
+}
+
+#ifndef NO_MMX
+bool CopyRGBSurfaceToYUVSurfaceMMX(
+ LPDDSURFACEDESC pddsd1,
+ LPDDSURFACEDESC pddsd2,
+ fourcc_enum eOverlayFormat)
+{
+ if (pddsd1->dwWidth != pddsd2->dwWidth)
+ return false;
+ if (pddsd1->dwHeight != pddsd2->dwHeight)
+ return false;
+
+ DWORD w = pddsd1->dwWidth;
+ DWORD h = pddsd1->dwHeight;
+ LONG pitch1 = pddsd1->lPitch;
+ LONG pitch2 = pddsd2->lPitch;
+ unsigned __int32 *pPixels1 = (unsigned __int32 *)pddsd1->lpSurface;
+ unsigned __int32 *pPixels2 = (unsigned __int32 *)pddsd2->lpSurface;
+ signed __int16 cm1[4];
+ signed __int16 cm2[4];
+ signed __int16 cm3[4];
+ signed __int16 cm4[4];
+ int loops_per_scanline = w/2;
+ int extra_bytes_per_scanline_src = pitch1 - w*4;
+ int extra_bytes_per_scanline_dest = pitch2 - w*2;
+
+ if (eOverlayFormat == UYVY) // U Y V Y
+ {
+ // swap 0<->1, and 2<->3
+ cm1[1] = 77/2; cm1[0] = -38/2; cm1[3] = 77/2; cm1[2] = 110/2;
+ cm2[1] = 150/2; cm2[0] = -74/2; cm2[3] = 150/2; cm2[2] = -92/2;
+ cm3[1] = 29/2; cm3[0] = 112/2; cm3[3] = 29/2; cm3[2] = -18/2;
+ cm4[1] = 0; cm4[0] = 32768/2; cm4[3] = 0; cm4[2] = 32768/2;
+ }
+ else // Y U Y 2
+ {
+ // (laptop)
+ cm1[0] = 77/2; cm1[1] = -38/2; cm1[2] = 77/2; cm1[3] = 110/2;
+ cm2[0] = 150/2; cm2[1] = -74/2; cm2[2] = 150/2; cm2[3] = -92/2;
+ cm3[0] = 29/2; cm3[1] = 112/2; cm3[2] = 29/2; cm3[3] = -18/2;
+ cm4[0] = 0; cm4[1] = 32768/2; cm4[2] = 0; cm4[3] = 32768/2;
+ }
+
+ __asm
+ {
+ mov edx, h
+
+ mov esi, pPixels1
+ mov edi, pPixels2
+ sub edi, 4 // pre-subtract
+ movq mm4, cm4
+ movq mm5, cm1
+ movq mm6, cm2
+ movq mm7, cm3
+
+ ALIGN 8
+ yuvscanlineloop:
+
+ mov ecx, loops_per_scanline
+
+ ALIGN 8
+ yuvloop:
+
+ /*
+ // prefetch
+ test ecx, 0x000001ff
+ jnz PROCESS_PIXEL_MMX32 // every 256th pixel do some prefetches
+
+ mov ebx, 2*256 // need to prefetch 256*6 bytes
+ ALIGN 8
+ LOAD_ESI_ARRAY_MMX32:
+ mov eax, [ebx+esi]
+ mov eax, [ebx+esi+32]
+ sub ebx, 64
+ jnz LOAD_ESI_ARRAY_MMX32
+
+ ALIGN 8
+ PROCESS_PIXEL_MMX32:
+ */
+
+ // read in 2 pixels
+ movq mm0, qword ptr [esi] // -- b1 g1 r1 -- b2 g2 r2
+ movq mm1, qword ptr [esi] // -- b1 g1 r1 -- b2 g2 r2
+ movq mm2, qword ptr [esi] // -- b1 g1 r1 -- b2 g2 r2
+
+ // quick reference:
+ // punpcklbw mm7, mm7 // abcdefgh -> eeffgghh
+ // punpcklbw mm7, mm0 // abcdefgh -> 0e0f0g0h (if mm0 is zero)
+ // packuswb mm7, mm7 // 0a0b0g0r -> abgrabgr ?
+
+ // step 1: get to this state:
+ // mm0: r1 r1 r2 r2
+ // mm1: g1 g1 g2 g2
+ // mm2: b1 b1 b2 b2
+ // mm3: junk
+ // mm4: 0 32k 0 32k
+ // mm5: c1r1 c1r2 c2r1 c2r2
+ // mm6: c1g1 c1g2 c2g1 c2g2
+ // mm7: c1b1 c1b2 c2b1 c2b2
+
+ // NOTE: the shifts of 8, 16, and 24 below are
+ // correct (vs. 0-8-16) but might be in
+ // backwards order!
+
+ pslld mm0, 8
+ pslld mm1, 16
+ pslld mm2, 24
+ psrld mm0, 24 // 00 00 00 r1 00 00 00 r2
+ psrld mm1, 24 // 00 00 00 g1 00 00 00 g2
+ psrld mm2, 24 // 00 00 00 b1 00 00 00 b2
+
+ movq mm3, mm0
+ pslld mm0, 16
+ por mm0, mm3 // 00 r1 00 r1 00 r2 00 r2
+
+ movq mm3, mm1
+ pslld mm1, 16
+ por mm1, mm3 // 00 g1 00 g1 00 g2 00 g2
+
+ movq mm3, mm2
+ pslld mm2, 16
+ por mm2, mm3 // 00 b1 00 b1 00 b2 00 b2
+
+ // step 2: multiply to get to this state:
+ // mm0: r1*c1r1 r1*c1r2 r2*c2r1 r2*c2r2
+ // mm1: g1*c1g1 g1*c1g2 g2*c2g1 g2*c2g2
+ // mm2: b1*c1b1 b1*c1b2 b2*c2b1 b2*c2b2
+ // mm4: 0 32k 0 32k
+ pmullw mm0, mm5
+ add edi, 4
+ pmullw mm1, mm6
+ add esi, 8
+ pmullw mm2, mm7
+
+ // step 3: add to get to this state:
+ // mm0: d1*256 d2*256 d3*256 d4*256
+ paddsw mm0, mm4
+ paddsw mm0, mm1
+ paddsw mm0, mm2
+
+ psrlw mm0, 7
+ packuswb mm0, mm0 // bytes: abgrabgr
+ movd dword ptr [edi], mm0 // store
+
+ loop yuvloop
+
+ // scanline complete
+ add esi, extra_bytes_per_scanline_src
+ add edi, extra_bytes_per_scanline_dest
+
+ dec edx
+ jnz yuvscanlineloop
+
+ emms
+ }
+
+ return true;
+}
+#else
+bool CopyRGBSurfaceToYUVSurface(
+ LPDDSURFACEDESC pddsd1,
+ LPDDSURFACEDESC pddsd2,
+ fourcc_enum eOverlayFormat)
+{
+ if (pddsd1->dwWidth != pddsd2->dwWidth)
+ return false;
+ if (pddsd1->dwHeight != pddsd2->dwHeight)
+ return false;
+
+ DWORD w = pddsd1->dwWidth;
+ DWORD h = pddsd1->dwHeight;
+ LONG pitch1 = pddsd1->lPitch;
+ LONG pitch2 = pddsd2->lPitch;
+ unsigned __int32 *pPixels1 = (unsigned __int32 *)pddsd1->lpSurface;
+ unsigned __int32 *pPixels2 = (unsigned __int32 *)pddsd2->lpSurface;
+ unsigned __int32 color1;
+ LONG offset1 = 0;
+ LONG offset2 = 0;
+ unsigned int R, G, B, i1, i2, i3, i4;
+ BYTE yuv[4];
+
+ if (eOverlayFormat == UYVY) // U Y V Y
+ {
+ i1 = 1;
+ i2 = 0;
+ i3 = 3;
+ i4 = 2;
+ }
+ else // Y U Y 2
+ {
+ i1 = 0;
+ i2 = 1;
+ i3 = 2;
+ i4 = 3;
+ }
+
+ // Go through the image 2 pixels at a time and convert to YUV
+ for (unsigned int y=0; y<h; y++)
+ {
+ offset1 = y*pitch1/4;
+ offset2 = y*pitch2/4;
+
+ for (unsigned int x=0; x<w; x+=2)
+ {
+ color1 = pPixels1[offset1++];
+ B = (color1) & 0xFF;
+ G = (color1 >> 8) & 0xFF;
+ R = (color1 >> 16) & 0xFF;
+ yuv[i1] = (77*R + 150*G + 29*B) >> 8;
+ yuv[i2] = (32768 - 38*R - 74*G + 112*B) >> 8;
+
+ color1 = pPixels1[offset1++];
+ B = (color1) & 0xFF;
+ G = (color1 >> 8) & 0xFF;
+ R = (color1 >> 16) & 0xFF;
+ yuv[i3] = (77*R + 150*G + 29*B) >> 8;
+ yuv[i4] = (32768 + 110*R - 92*G - 18*B) >> 8;
+
+ pPixels2[offset2++] = *((unsigned __int32 *)yuv);
+ }
+ }
+ return true;
+}
+#endif
+
+int DDraw_Init()
+{
+ InitializeCriticalSection(&g_cs);
+ return 0;
+
+}
+void DDraw_Quit(void)
+{
+ if (g_lpDD)
+ {
+ if (g_lpPrimSurf)
+ {
+ g_lpPrimSurf->Release();
+ g_lpPrimSurfBack=g_lpPrimSurf=NULL;
+ }
+ if (g_lpRenderSurf[0]) g_lpRenderSurf[0]->Release();
+ if (g_lpRenderSurf[1]) g_lpRenderSurf[1]->Release();
+ g_lpRenderSurf[0]=0;
+ g_lpRenderSurf[1]=0;
+ if (g_lpddsOverlay) g_lpddsOverlay->Release();
+ if (g_lpddsPrimary) g_lpddsPrimary->Release();
+ g_lpddsOverlay=g_lpddsPrimary=NULL;
+ g_lpDD->Release();
+ g_lpDD=NULL;
+ DD_RestoreBkgndSettings();
+ }
+ DeleteCriticalSection(&g_cs);
+}
+
+
+void DDraw_BeginResize(void)
+{
+ if (!g_fs) nodraw=1;
+}
+void DDraw_Resize(int w, int h, int dsize)
+{
+ if (!g_fs) DD_CreateSurfaces(w, h, 0, 0, 0, 0, !!dsize, 0);
+}
+
+static void *g_lpsurf[2];
+
+static DDSURFACEDESC d={sizeof(d),};
+static DDSURFACEDESC d2={sizeof(d),};
+
+void DDraw_Enter(int *w, int *h, int **fb1, int **fb2)
+{
+ HRESULT han;
+ if (nodraw)
+ {
+ *fb1=*fb2=0;
+ return;
+ }
+ EnterCriticalSection(&g_cs);
+ *w=g_w;
+ *h=g_h;
+ if (!g_lpDD || !g_lpRenderSurf[0] || !g_lpRenderSurf[1])
+ {
+ *fb1=*fb2=0;
+ LeaveCriticalSection(&g_cs);
+ return;
+ }
+ if ((han = g_lpRenderSurf[0]->Lock(NULL,&d,DDLOCK_WAIT,NULL)) != DD_OK)
+ {
+ *fb1=*fb2=0;
+ LeaveCriticalSection(&g_cs);
+ return;
+ }
+ if ((han = g_lpRenderSurf[1]->Lock(NULL,&d2,DDLOCK_WAIT,NULL)) != DD_OK)
+ {
+ g_lpRenderSurf[0]->Unlock(d.lpSurface);
+ *fb1=*fb2=0;
+ LeaveCriticalSection(&g_cs);
+ return;
+ }
+ *fb1=(int*)(g_lpsurf[0]=d.lpSurface);
+ *fb2=(int*)(g_lpsurf[1]=d2.lpSurface);
+
+ if (g_fs && g_fs_height!=g_h)// && !cfg_fs_use_overlay)
+ {
+ int y=g_h/2-((g_fs_height/2));
+ *h-=y*2;
+ *fb1 += y*g_w;
+ *fb2 += y*g_w;
+ }
+}
+
+static unsigned int draw_title_time;
+static char last_title[1024];
+
+extern HWND hwnd_WinampParent;
+
+static void do_gettitle()
+{
+ if (draw_title_p < 1 && --draw_title_p < -7)
+ {
+ char this_title[2048]={0,};
+ char *p;
+ if (IsWindow(hwnd_WinampParent))
+ {
+ DWORD id;
+ if (!SendMessageTimeout( hwnd_WinampParent,WM_GETTEXT,(WPARAM)sizeof(this_title),(LPARAM)this_title,SMTO_BLOCK,50,&id) || !id) return;
+ }
+ p = this_title+strlen(this_title);
+ while (p >= this_title)
+ {
+ char buf[9];
+ memcpy(buf,p,8);
+ buf[8]=0;
+ if (!lstrcmpi(buf,"- Winamp")) break;
+ p--;
+ }
+ if (p >= this_title) p--;
+ while (p >= this_title && *p == ' ') p--;
+ *++p=0;
+ if (lstrcmpi(this_title,last_title))
+ {
+ strcpy(last_title,this_title);
+ draw_title_p=1;
+ draw_title_time=GetTickCount()+1000;
+ }
+ else draw_title_p=0;
+ }
+ if (draw_title_p == 2)
+ {
+ draw_title_p=1;
+ draw_title_time=GetTickCount()+1000;
+ }
+}
+
+
+char statustext[256];
+DWORD statustext_life;
+int statustext_len;
+
+void DDraw_SetStatusText(char *text, int life)
+{
+ strcpy(statustext,text);
+ statustext_len=life?life:2000;
+ statustext_life=1;
+
+}
+
+
+
+#ifndef NO_X86ASM
+void homemadeBlitFrom32bpp(DDSURFACEDESC *out, void *in, int w, int h, int sy, int ey)
+{
+ int mh=min(h,(int)out->dwHeight);
+ if (sy < 0) sy=0;
+ if (ey > mh) ey=mh;
+ if (out->ddpfPixelFormat.dwRGBBitCount == 15)
+ {
+ int y;
+ int mw;
+ mw=min(w,out->lPitch/2);
+ unsigned int *inptr=(unsigned int *)in + w*sy;
+ for (y = sy; y < ey; y ++)
+ {
+ unsigned char *optr = (unsigned char *)out->lpSurface + (y * out->lPitch);
+ __asm
+ {
+ mov edi, optr
+ mov esi, inptr
+ mov ecx, mw
+ mov ebx, 00000000111110001111100011111000b
+ shr ecx, 1
+ conv15_loop:
+ mov eax,[esi]
+
+ mov edx,[esi+4]
+
+ and eax, ebx
+ and edx, ebx
+
+ // 00000000RRRRR000GGGGG000BBBBB000
+ shr ah,3 // 00000000RRRRR000000GGGGGBBBBB000
+ shr dh,3
+
+ shr ax,3 // 00000000RRRRR000000000GGGGGBBBBB
+ shr dx,3
+
+ // ----------------HHHHHHHHLLLLLLLL
+ ror eax,10// GGGGGBBBBB00000000RRRRR000000000
+ ror edx,10
+
+ shr ah,1
+ shr dh,1
+
+ mov al,ah
+ mov dl,dh
+
+ rol eax,10
+
+ rol edx,10
+
+ shl edx, 16
+
+ and eax, 0x0000ffff
+ add esi,8
+
+ or eax, edx
+
+ mov [edi], eax
+
+ add edi, 4
+ dec ecx
+ jnz conv15_loop
+ }
+ inptr += w;
+ }
+
+ }
+ else if (out->ddpfPixelFormat.dwRGBBitCount == 16)
+ {
+ int y;
+ int mw;
+ mw=min(w,out->lPitch/2);
+ unsigned int *inptr=(unsigned int *)in + w*sy;
+ for (y = sy; y < ey; y ++)
+ {
+ unsigned char *optr = (unsigned char *)out->lpSurface + (y * out->lPitch);
+ __asm
+ {
+ mov edi, optr
+ mov esi, inptr
+ mov ecx, mw
+ mov ebx, 00000000111110001111110011111000b
+ shr ecx, 1
+ conv16_loop:
+ mov eax,[esi]
+
+ mov edx,[esi+4]
+
+ and eax, ebx
+ and edx, ebx
+
+ // RRRRR000GGGGGG00BBBBB000
+
+ shr ah,2 // RRRRR00000GGGGGGBBBBB000
+ shr dh,2
+
+ shr ax,3 // RRRRR00000000GGGGGGBBBBB
+ shr dx,3
+
+ ror eax,8 // GGGBBBBBRRRRR00000000GGG
+ ror edx,8
+
+ add al,ah // GGGBBBBBRRRRR000RRRRRGGG
+ add dl,dh
+
+ rol eax,8 // RRRRR000RRRRRGGGGGGBBBBB
+
+ rol edx,8
+
+ shl edx, 16
+
+ and eax, 0x0000ffff
+ add esi,8
+
+ or eax, edx
+
+ mov [edi], eax
+
+ add edi, 4
+ dec ecx
+ jnz conv16_loop
+ }
+ inptr += w;
+ }
+
+ }
+ else if (out->ddpfPixelFormat.dwRGBBitCount == 24)
+ { // very unoptimized
+ int y,x;
+ int mw;
+ unsigned int *inptr=(unsigned int *)in+sy;
+ mw=min(w,out->lPitch/3);
+ for (y = sy; y < ey; y ++)
+ {
+ unsigned char *optr = (unsigned char *)out->lpSurface + (y * out->lPitch);
+ x=mw/2;
+ while (x--)
+ {
+ int a=inptr[0];
+ int b=inptr[1];
+ optr[0]=(unsigned char) a;
+ optr[3]=(unsigned char) b;
+ optr[1]=(unsigned char) (a>>8);
+ optr[4]=(unsigned char) (b>>8);
+ optr[2]=(unsigned char) (a>>16);
+ optr[5]=(unsigned char) (b>>16);
+
+ optr+=6;
+ inptr+=2;
+ }
+ inptr += (w-mw);
+ }
+ }
+ else
+ {
+ unsigned char *outptr;
+ unsigned int *inptr;
+ int mw=min(w*4,out->lPitch);
+ int y;
+ inptr=(unsigned int*)in + (sy*w);
+ outptr=(unsigned char *)out->lpSurface + (sy*out->lPitch);
+ for (y = sy; y < ey; y ++)
+ {
+ memcpy(outptr,inptr,mw);
+ inptr+=w;
+ outptr+=out->lPitch;
+ }
+ }
+}
+#endif
+
+static int unlocksurfaces()
+{
+ int a=0;
+ if (g_lpRenderSurf[0] && g_lpRenderSurf[0]->Unlock(g_lpsurf[0]) != DD_OK) a=1;
+ if (g_lpRenderSurf[1] && g_lpRenderSurf[1]->Unlock(g_lpsurf[1]) != DD_OK) a=1;
+ return a;
+}
+
+void DDraw_Exit(int which)
+{
+ if (!g_lpRenderSurf[0] || !g_lpRenderSurf[1])
+ {
+ unlocksurfaces();
+ goto endfunc;
+ }
+#ifdef RESIZE_ONRESIZE
+ last_used=which;
+#endif
+
+ if (g_fs && !cfg_fs_use_overlay)
+ {
+ int fsy=g_h/2-((g_fs_height/2));
+ RECT r={0,0,g_w,g_h};
+ if (g_bpp != 32) // non-32bpp mode
+ {
+ if (fsy>0 && ((cfg_fs_fps&1) || (statustext_life&&!(cfg_fs_fps&8)))) // clear portions of backbuffer if necessary
+ {
+ DDBLTFX ddbfx={sizeof(ddbfx),};
+ int ty=min(fsy,16);
+ RECT r2={0,0,g_w,ty};
+ g_lpPrimSurfBack->Blt(&r2,NULL,NULL,DDBLT_WAIT|DDBLT_COLORFILL,&ddbfx);
+ r2.top=g_h-ty;
+ r2.bottom=g_h-1;
+ g_lpPrimSurfBack->Blt(&r2,NULL,NULL,DDBLT_WAIT|DDBLT_COLORFILL,&ddbfx);
+ }
+#ifndef NO_X86ASM
+ if (!(g_fs_flip&8) && !g_windowed_dsize) // homemade bltshit
+ {
+ DDSURFACEDESC d={sizeof(d),};
+ HRESULT han;
+ han = g_lpPrimSurfBack->Lock(NULL,&d,DDLOCK_WAIT,NULL);
+ if (han == DDERR_SURFACELOST)
+ {
+ DDBLTFX ddbfx={sizeof(ddbfx),};
+ g_lpPrimSurfBack->Restore();
+ g_lpPrimSurfBack->Blt(NULL,NULL,NULL,DDBLT_WAIT|DDBLT_COLORFILL,&ddbfx);
+ han = g_lpPrimSurfBack->Lock(NULL,&d,DDLOCK_WAIT,NULL);
+ }
+ if (han != DD_OK) goto slow_fs_non32bpp;
+
+ homemadeBlitFrom32bpp(&d,g_lpsurf[which],g_w,g_h,fsy,g_h-fsy);
+
+ int a=0;
+ if (g_lpPrimSurfBack->Unlock(d.lpSurface) != DD_OK ) a=1;
+ if (unlocksurfaces()||a)
+ {
+ goto endfunc;
+ }
+ }
+ else // slow (stretchblt)
+#endif
+ {
+ HDC in, out;
+#ifndef NO_X86ASM
+slow_fs_non32bpp:
+#endif
+ if (unlocksurfaces() || g_lpPrimSurfBack->GetDC(&out) != DD_OK)
+ {
+ goto endfunc;
+ }
+ if (g_lpRenderSurf[which]->GetDC(&in) != DD_OK)
+ {
+ g_lpPrimSurfBack->ReleaseDC(out);
+ goto endfunc;
+ }
+ 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);
+ else BitBlt(out,0,fsy,g_w,g_h-fsy*2,in,0,fsy,SRCCOPY);
+ g_lpRenderSurf[which]->ReleaseDC(in);
+ g_lpPrimSurfBack->ReleaseDC(out);
+ }
+ }
+ else // 32bpp - always just use Blt() - will scale if necessary (yay Blt!)
+ {
+ //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};
+ //RECT ir={0,g_h/2-g_go_fs_height/2,g_w,g_h/2+g_go_fs_height/2};
+ if (unlocksurfaces())
+ {
+ goto endfunc;
+ }
+ if (g_lpPrimSurfBack->Blt(NULL,g_lpRenderSurf[which],&r,DDBLT_WAIT,NULL) == DDERR_SURFACELOST)
+ {
+ DDBLTFX ddbfx={sizeof(ddbfx),};
+ if (g_fs_flip&1)
+ {
+ g_lpPrimSurfBack->Restore();
+ g_lpPrimSurfBack->Blt(NULL,NULL,NULL,DDBLT_WAIT|DDBLT_COLORFILL,&ddbfx);
+ }
+ g_lpPrimSurf->Restore();
+ g_lpPrimSurf->Blt(NULL,NULL,NULL,DDBLT_WAIT|DDBLT_COLORFILL,&ddbfx);
+ goto endfunc;
+ }
+ }
+ do_gettitle();
+ if ((cfg_fs_fps&1) || (draw_title_p>0&&!(cfg_fs_fps&16)) || (statustext_life&&!(cfg_fs_fps&8)))
+ {
+ HDC out;
+ if (g_lpPrimSurfBack->GetDC(&out) == DD_OK)
+ {
+ char str[2048];
+ SetBkMode(out,TRANSPARENT);
+ if (cfg_fs_fps&1)
+ {
+ RECT r={2,2,g_fs_w,g_fs_h};
+ wsprintf(str,"%d.%d",g_dlg_fps/10,g_dlg_fps%10);
+ SetTextColor(out,RGB(0,0,0));
+ DrawText(out,str,-1,&r,DT_TOP|DT_LEFT|DT_SINGLELINE|DT_NOCLIP|DT_NOPREFIX);
+ r.left=r.top=0;
+ SetTextColor(out,RGB(255,255,255));
+ DrawText(out,str,-1,&r,DT_TOP|DT_LEFT|DT_SINGLELINE|DT_NOCLIP|DT_NOPREFIX);
+ }
+ if (statustext_life&&!(cfg_fs_fps&8))
+ {
+ if (statustext_life==1) statustext_life=GetTickCount()+statustext_len;
+ RECT r={0,0,g_fs_w,g_fs_h};
+ if (GetTickCount() > statustext_life)
+ {
+ if (statustext_life==2) statustext_life=0;
+ else statustext_life=2;
+ }
+ else
+ {
+ SetTextColor(out,RGB(0,0,0));
+ DrawText(out,statustext,-1,&r,DT_BOTTOM|DT_RIGHT|DT_SINGLELINE|DT_NOPREFIX);
+ SetTextColor(out,RGB(255,255,255));
+ r.right-=2;
+ r.bottom-=2;
+ DrawText(out,statustext,-1,&r,DT_BOTTOM|DT_RIGHT|DT_SINGLELINE|DT_NOPREFIX);
+ }
+ }
+ if (draw_title_p>0&&!(cfg_fs_fps&16))
+ {
+ RECT r={4,4,g_fs_w,g_fs_h};
+ SetTextColor(out,RGB(0,0,0));
+ DrawText(out,last_title,-1,&r,DT_VCENTER|DT_CENTER|DT_SINGLELINE|DT_NOPREFIX);
+ r.left=r.top=0;
+ SetTextColor(out,RGB(255,255,255));
+ DrawText(out,last_title,-1,&r,DT_VCENTER|DT_CENTER|DT_SINGLELINE|DT_NOPREFIX);
+ }
+ g_lpPrimSurfBack->ReleaseDC(out);
+ }
+ if (draw_title_p>0 && draw_title_time < GetTickCount() && !(cfg_fs_fps&16))
+ {
+ if (g_lpRenderSurf[which]->GetDC(&out) == DD_OK)
+ {
+ RECT r={4,4,g_w,g_h};
+ SetBkMode(out,TRANSPARENT);
+ SetTextColor(out,RGB(0,0,0));
+ DrawText(out,last_title,-1,&r,DT_VCENTER|DT_CENTER|DT_SINGLELINE|DT_NOPREFIX);
+ r.left=r.top=0;
+ SetTextColor(out,RGB(255,255,255));
+ DrawText(out,last_title,-1,&r,DT_VCENTER|DT_CENTER|DT_SINGLELINE|DT_NOPREFIX);
+ g_lpRenderSurf[which]->ReleaseDC(out);
+ }
+ draw_title_p=0;
+ }
+ }
+ if (g_fs_flip&1) g_lpPrimSurf->Flip(NULL, DDFLIP_WAIT);
+ else if (!(g_fs_flip&2)) g_lpDD->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN,0);
+ }
+ else
+ {
+ if(g_overlay_init_ok)
+ {
+ LPDDSURFACEDESC pd=(which==0?&d:&d2);
+ DDSURFACEDESC dd={sizeof(dd),};
+ if (g_fs) if (!(cfg_fs_flip&2)) g_lpDD->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN,0);
+
+ if (g_lpddsOverlay->Lock(NULL,&dd,DDLOCK_WAIT,NULL) != DD_OK)
+ {
+ g_overlay_init_ok=0;
+ goto endfunc;
+ }
+#ifndef NO_MMX
+ CopyRGBSurfaceToYUVSurfaceMMX(pd,&dd,g_overlay_fourcc);
+#else
+ CopyRGBSurfaceToYUVSurface(pd,&dd,g_overlay_fourcc);
+#endif
+ g_lpddsOverlay->Unlock(&dd);
+ if (g_fs)
+ {
+ unlocksurfaces();
+ goto endfunc;
+ }
+ }
+
+ HDC in1, out, in2=NULL;
+ if (unlocksurfaces() || g_lpRenderSurf[which]->GetDC(&in1) != DD_OK)
+ {
+ goto endfunc;
+ }
+ do_gettitle();
+ if (draw_title_p>0&&!(cfg_fs_fps&4) && draw_title_time < GetTickCount())
+ {
+ RECT r={4,4,g_w,g_h};
+ SetBkMode(in1,TRANSPARENT);
+ SetTextColor(in1,RGB(0,0,0));
+ DrawText(in1,last_title,-1,&r,DT_VCENTER|DT_CENTER|DT_SINGLELINE|DT_NOPREFIX);
+ r.left=r.top=0;
+ SetTextColor(in1,RGB(255,255,255));
+ DrawText(in1,last_title,-1,&r,DT_VCENTER|DT_CENTER|DT_SINGLELINE|DT_NOPREFIX);
+ draw_title_p=0;
+ }
+ if ((draw_title_p > 0&&!(cfg_fs_fps&4)) || (statustext_life&&!(cfg_fs_fps&2)))
+ {
+ // draw perframe
+ RECT r={4,4,g_w,g_h};
+ if (g_lpRenderSurf[which^1]->GetDC(&in2) != DD_OK)
+ {
+ in2=NULL;
+ goto abort_thingy;
+ }
+ BitBlt(in2,0,0,g_w,g_h,in1,0,0,SRCCOPY);
+ SetBkMode(in2,TRANSPARENT);
+ if (draw_title_p > 0&&!(cfg_fs_fps&4))
+ {
+ SetTextColor(in2,RGB(0,0,0));
+ DrawText(in2,last_title,-1,&r,DT_VCENTER|DT_CENTER|DT_SINGLELINE|DT_NOPREFIX);
+ r.left=r.top=0;
+ SetTextColor(in2,RGB(255,255,255));
+ DrawText(in2,last_title,-1,&r,DT_VCENTER|DT_CENTER|DT_SINGLELINE|DT_NOPREFIX);
+ }
+ if (statustext_life&&!(cfg_fs_fps&2))
+ {
+ if (statustext_life==1) statustext_life=GetTickCount()+statustext_len;
+ if (GetTickCount() > statustext_life) statustext_life=0;
+ SetTextColor(in2,RGB(0,0,0));
+ DrawText(in2,statustext,-1,&r,DT_BOTTOM|DT_RIGHT|DT_SINGLELINE|DT_NOPREFIX);
+ r.right-=2;
+ r.bottom-=2;
+ SetTextColor(in2,RGB(255,255,255));
+ DrawText(in2,statustext,-1,&r,DT_BOTTOM|DT_RIGHT|DT_SINGLELINE|DT_NOPREFIX);
+ }
+ }
+abort_thingy:
+ if (!(cfg_fs_flip&4)) g_lpDD->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN,0);
+ out=GetDC(g_hwnd);
+ if (out)
+ {
+ if (!g_windowed_dsize)
+ {
+#ifndef WA2_EMBED
+ BitBlt(out,inWharf?0:7,inWharf?0:15,g_w-g_noshoww,g_h,in2?in2:in1,0,0,SRCCOPY);
+#else
+ BitBlt(out,0,0,g_w-g_noshoww,g_h,in2?in2:in1,0,0,SRCCOPY);
+#endif
+ }
+ else
+ {
+#ifndef WA2_EMBED
+ StretchBlt(out,inWharf?0:7,inWharf?0:15,g_dsw,g_dsh,in2?in2:in1,0,0,g_w,g_h,SRCCOPY);
+#else
+ StretchBlt(out,0,0,g_dsw,g_dsh,in2?in2:in1,0,0,g_w,g_h,SRCCOPY);
+#endif
+ }
+ ReleaseDC(g_hwnd,out);
+ }
+ g_lpRenderSurf[which]->ReleaseDC(in1);
+ if (in2)
+ g_lpRenderSurf[which^1]->ReleaseDC(in2);
+ }
+endfunc:
+ LeaveCriticalSection(&g_cs);
+}
+
+
+void DDraw_SetFullScreen(int fs, int w, int h, int dbl, int bpp)
+{
+ if (!fs) DD_CreateSurfaces(w, h, 0, 0, 0, 0, !!dbl, 0);
+ else
+ {
+ DD_CreateSurfaces(w, h, (min(max(1,cfg_fs_height),100)*h)/100, 1, bpp, cfg_fs_flip, !!dbl, cfg_fs_use_overlay);
+ }
+}
+
+int DDraw_IsFullScreen(void)
+{
+ return g_fs;
+}
+
+HRESULT WINAPI _cb(
+ LPDDSURFACEDESC lpDDSurfaceDesc, LPVOID lpContext)
+{
+ HWND h=(HWND)lpContext;
+ if ((lpDDSurfaceDesc->ddpfPixelFormat.dwFlags & DDPF_RGB) &&
+ (lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount==32 ||
+ lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount==24 ||
+ lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount==16 ||
+ lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount==15))
+ {
+ char s[256];
+ wsprintf(s,"%dx%d@%dBPP",lpDDSurfaceDesc->dwWidth,lpDDSurfaceDesc->dwHeight,lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount);
+ SendMessage(h,CB_ADDSTRING,0,(long)s);
+ }
+
+ return DDENUMRET_OK;
+}
+
+
+void DDraw_EnumDispModes(HWND hwnd)
+{
+ if (g_lpDD)
+ g_lpDD->EnumDisplayModes(0,NULL,hwnd,_cb);
+}
+
+static int g_st;
+
+HRESULT WINAPI _cb2(
+ LPDDSURFACEDESC lpDDSurfaceDesc, LPVOID lpContext)
+{
+ DWORD *x=(DWORD *)lpContext;
+ if (x[0]==lpDDSurfaceDesc->dwWidth &&
+ x[1]==lpDDSurfaceDesc->dwHeight &&
+ x[2]==lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount)
+ {
+ g_st=1;
+ return DDENUMRET_CANCEL;
+ }
+
+ return DDENUMRET_OK;
+}
+
+int DDraw_IsMode(int w, int h, int bpp)
+{
+ int x[3]={w,h,bpp};
+ if (!x[0] || !x[1] || !x[2]) return 0;
+ if (!g_lpDD) return 0;
+ g_st=0;
+ g_lpDD->EnumDisplayModes(0,NULL,(LPVOID)x,_cb2);
+ return g_st;
+}
+
+HRESULT WINAPI _cb3(
+ LPDDSURFACEDESC lpDDSurfaceDesc, LPVOID lpContext)
+{
+ if ((lpDDSurfaceDesc->ddpfPixelFormat.dwFlags & DDPF_RGB) &&
+ (lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount==32 ||
+ lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount==24 ||
+ lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount==16 ||
+ lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount==15))
+ {
+ int *(*x)=(int **)lpContext;
+ if (lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount > (DWORD)x[2][0] ||
+ lpDDSurfaceDesc->dwWidth < (DWORD)x[0][0] ||
+ lpDDSurfaceDesc->dwHeight < (DWORD)x[1][0])
+ {
+ x[0][0]=lpDDSurfaceDesc->dwWidth;
+ x[1][0]=lpDDSurfaceDesc->dwHeight;
+ x[2][0]=lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount;
+ }
+ }
+
+ return DDENUMRET_OK;
+}
+
+
+int DDraw_PickMode(int *w, int *h, int *bpp)
+{
+ int *(x[3])={w,h,bpp};
+ *w=0;
+ *h=0;
+ *bpp=0;
+ // return if mode found that is suitable
+ g_lpDD->EnumDisplayModes(0,NULL,(LPVOID)x,_cb3);
+ return *w && *h && *bpp;
+}
+
+double DDraw_translatePoint(POINT p, int isY)
+{
+ double v=0.0;
+ if(g_fs && g_overlay_init_ok && hwndOverlayWnd && IsWindow(hwndOverlayWnd))
+ {
+ RECT r;
+ ScreenToClient(hwndOverlayWnd,&p);
+ GetClientRect(hwndOverlayWnd,&r);
+ if (isY)
+ {
+ if (r.bottom>0)
+ v=p.y/(double)(r.bottom*0.5) - 1.0;
+ }
+ else
+ {
+ if (r.right>0)
+ v=p.x/(double)(r.right*0.5) - 1.0;
+ }
+ }
+ else
+ {
+ ScreenToClient(g_hwnd,&p);
+
+ if (isY)
+ {
+ if (g_dsh>0)
+ v=p.y/(double)(g_dsh*0.5) - 1.0;
+ }
+ else
+ {
+ if (g_dsw>0)
+ v=p.x/(double)(g_dsw*0.5) - 1.0;
+ }
+ }
+ //if (v > 1.0) v=1.0;
+ //if (v < -1.0) v=-1.0;
+ return v;
+} \ No newline at end of file