1476 lines
40 KiB
C++
1476 lines
40 KiB
C++
/*
|
|
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;
|
|
} |