2013-08-25 12:38:13 -04:00
|
|
|
#define _CRT_SECURE_NO_WARNINGS
|
2015-06-22 12:40:59 -04:00
|
|
|
#define SYSLIBNAMES_DEFINES
|
2013-08-25 12:38:13 -04:00
|
|
|
|
2013-01-22 11:17:01 -05:00
|
|
|
#include <stdio.h>
|
2012-12-24 10:20:23 -05:00
|
|
|
#include "dxwnd.h"
|
2013-01-04 10:30:38 -05:00
|
|
|
#include "dxwcore.hpp"
|
2012-12-24 10:20:23 -05:00
|
|
|
#include "syslibs.h"
|
2013-06-29 12:38:04 -04:00
|
|
|
#include "dxhelper.h"
|
2013-12-02 11:17:07 -05:00
|
|
|
#include "resource.h"
|
2015-04-10 12:42:09 -04:00
|
|
|
#include "hddraw.h"
|
2015-04-26 12:40:41 -04:00
|
|
|
#include "d3d9.h"
|
2016-06-04 12:45:32 -04:00
|
|
|
extern GetDC_Type pGetDCMethod();
|
|
|
|
extern ReleaseDC_Type pReleaseDC1;
|
2016-04-03 12:42:48 -04:00
|
|
|
extern HandleDDThreadLock_Type pReleaseDDThreadLock;
|
2012-12-24 10:20:23 -05:00
|
|
|
|
2014-03-23 12:38:58 -04:00
|
|
|
/* ------------------------------------------------------------------ */
|
|
|
|
// Internal function pointers
|
|
|
|
/* ------------------------------------------------------------------ */
|
|
|
|
|
|
|
|
typedef DWORD (*TimeShifter_Type)(DWORD, int);
|
|
|
|
typedef LARGE_INTEGER (*TimeShifter64_Type)(LARGE_INTEGER, int);
|
|
|
|
|
|
|
|
TimeShifter_Type pTimeShifter;
|
|
|
|
TimeShifter64_Type pTimeShifter64;
|
|
|
|
|
|
|
|
static DWORD TimeShifterFine(DWORD, int);
|
|
|
|
static LARGE_INTEGER TimeShifter64Fine(LARGE_INTEGER, int);
|
|
|
|
static DWORD TimeShifterCoarse(DWORD, int);
|
|
|
|
static LARGE_INTEGER TimeShifter64Coarse(LARGE_INTEGER, int);
|
|
|
|
|
2013-01-19 11:16:54 -05:00
|
|
|
/* ------------------------------------------------------------------ */
|
|
|
|
// Constructor, destructor, initialization....
|
|
|
|
/* ------------------------------------------------------------------ */
|
2012-12-24 10:20:23 -05:00
|
|
|
|
|
|
|
dxwCore::dxwCore()
|
|
|
|
{
|
2013-01-04 10:30:38 -05:00
|
|
|
// initialization stuff ....
|
|
|
|
FullScreen=FALSE;
|
|
|
|
SethWnd(NULL);
|
|
|
|
SetScreenSize();
|
|
|
|
dwMaxDDVersion=7;
|
|
|
|
hParentWnd = 0;
|
|
|
|
hChildWnd = 0;
|
|
|
|
bActive = TRUE;
|
|
|
|
bDInputAbs = 0;
|
2013-08-01 12:16:53 -04:00
|
|
|
TimeShift = 0;
|
2013-08-30 12:38:14 -04:00
|
|
|
ResetEmulatedDC();
|
2013-08-12 12:38:35 -04:00
|
|
|
MustShowOverlay=FALSE;
|
2014-11-01 12:38:41 -04:00
|
|
|
TimerEvent.dwTimerType = TIMER_TYPE_NONE;
|
2014-10-08 12:39:38 -04:00
|
|
|
// initialization of default vsync emulation array
|
|
|
|
iRefreshDelays[0]=16;
|
|
|
|
iRefreshDelays[1]=17;
|
|
|
|
iRefreshDelayCount=2;
|
2015-11-19 11:42:28 -05:00
|
|
|
TimeFreeze = FALSE;
|
2016-12-28 11:49:00 -05:00
|
|
|
dwScreenWidth = 0;
|
|
|
|
dwScreenHeight = 0;
|
2012-12-24 10:20:23 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
dxwCore::~dxwCore()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2013-08-25 12:38:13 -04:00
|
|
|
void dxwCore::SetFullScreen(BOOL fs, int line)
|
|
|
|
{
|
2013-12-22 11:38:36 -05:00
|
|
|
OutTraceDW("SetFullScreen: %s at %d\n", fs?"FULLSCREEN":"WINDOWED", line);
|
2013-08-25 12:38:13 -04:00
|
|
|
FullScreen=fs;
|
|
|
|
}
|
|
|
|
|
|
|
|
void dxwCore::SetFullScreen(BOOL fs)
|
|
|
|
{
|
2013-07-09 12:38:16 -04:00
|
|
|
if(dxw.dwFlags3 & FULLSCREENONLY) fs=TRUE;
|
2013-12-22 11:38:36 -05:00
|
|
|
OutTraceDW("SetFullScreen: %s\n", fs?"FULLSCREEN":"WINDOWED");
|
2013-08-25 12:38:13 -04:00
|
|
|
FullScreen=fs;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL dxwCore::IsFullScreen()
|
|
|
|
{
|
2016-04-03 12:42:48 -04:00
|
|
|
return (Windowize && FullScreen);
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL dxwCore::IsToRemap(HDC hdc)
|
|
|
|
{
|
2016-07-13 12:46:31 -04:00
|
|
|
if(!hdc) return TRUE;
|
2016-04-03 12:42:48 -04:00
|
|
|
return (Windowize && FullScreen && (OBJ_DC == (*pGetObjectType)(hdc)));
|
2013-08-25 12:38:13 -04:00
|
|
|
}
|
|
|
|
|
2013-06-01 12:16:52 -04:00
|
|
|
void dxwCore::InitTarget(TARGETMAP *target)
|
|
|
|
{
|
|
|
|
dwFlags1 = target->flags;
|
|
|
|
dwFlags2 = target->flags2;
|
2013-04-27 12:19:14 -04:00
|
|
|
dwFlags3 = target->flags3;
|
|
|
|
dwFlags4 = target->flags4;
|
2014-07-28 12:39:37 -04:00
|
|
|
dwFlags5 = target->flags5;
|
2015-04-26 12:40:41 -04:00
|
|
|
dwFlags6 = target->flags6;
|
2016-01-19 11:42:45 -05:00
|
|
|
dwFlags7 = target->flags7;
|
|
|
|
dwFlags8 = target->flags8;
|
2017-03-25 09:59:46 -04:00
|
|
|
dwFlags9 = target->flags9;
|
|
|
|
dwFlags10= target->flags10;
|
2013-06-01 12:16:52 -04:00
|
|
|
dwTFlags = target->tflags;
|
2014-02-05 11:39:10 -05:00
|
|
|
Windowize = (dwFlags2 & WINDOWIZE) ? TRUE : FALSE;
|
2016-11-13 11:48:08 -05:00
|
|
|
IsVisible = TRUE;
|
2014-02-05 11:39:10 -05:00
|
|
|
if(dwFlags3 & FULLSCREENONLY) FullScreen=TRUE;
|
2013-06-01 12:16:52 -04:00
|
|
|
gsModules = target->module;
|
|
|
|
MaxFPS = target->MaxFPS;
|
2013-01-19 11:16:54 -05:00
|
|
|
CustomOpenGLLib = target->OpenGLLib;
|
|
|
|
if(!strlen(CustomOpenGLLib)) CustomOpenGLLib=NULL;
|
2013-06-01 12:16:52 -04:00
|
|
|
// bounds control
|
|
|
|
dwTargetDDVersion = target->dxversion;
|
2016-01-19 11:42:45 -05:00
|
|
|
MaxDdrawInterface = target->MaxDdrawInterface;
|
2013-06-01 12:16:52 -04:00
|
|
|
if(dwTargetDDVersion<0) dwTargetDDVersion=0;
|
2013-04-27 12:19:14 -04:00
|
|
|
if(dwTargetDDVersion>12) dwTargetDDVersion=12;
|
2013-01-19 11:16:54 -05:00
|
|
|
TimeShift = target->InitTS;
|
2013-01-20 11:16:58 -05:00
|
|
|
if(TimeShift < -8) TimeShift = -8;
|
|
|
|
if(TimeShift > 8) TimeShift = 8;
|
2013-01-27 11:17:04 -05:00
|
|
|
FakeVersionId = target->FakeVersionId;
|
2014-04-01 12:38:40 -04:00
|
|
|
MaxScreenRes = target->MaxScreenRes;
|
2013-06-15 12:21:25 -04:00
|
|
|
Coordinates = target->coordinates;
|
2015-04-26 12:40:41 -04:00
|
|
|
switch(target->SwapEffect){
|
|
|
|
case 0: SwapEffect = D3DSWAPEFFECT_DISCARD; break;
|
|
|
|
case 1: SwapEffect = D3DSWAPEFFECT_FLIP; break;
|
|
|
|
case 2: SwapEffect = D3DSWAPEFFECT_COPY; break;
|
|
|
|
case 3: SwapEffect = D3DSWAPEFFECT_OVERLAY; break;
|
|
|
|
case 4: SwapEffect = D3DSWAPEFFECT_FLIPEX; break;
|
|
|
|
}
|
2013-08-12 12:38:35 -04:00
|
|
|
MustShowOverlay=((dwFlags2 & SHOWFPSOVERLAY) || (dwFlags4 & SHOWTIMESTRETCH));
|
2014-03-23 12:38:58 -04:00
|
|
|
if(dwFlags4 & FINETIMING){
|
|
|
|
pTimeShifter = TimeShifterFine;
|
|
|
|
pTimeShifter64 = TimeShifter64Fine;
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
pTimeShifter = TimeShifterCoarse;
|
|
|
|
pTimeShifter64 = TimeShifter64Coarse;
|
|
|
|
}
|
2016-06-11 12:48:04 -04:00
|
|
|
iSiz0X = iSizX = target->sizx;
|
|
|
|
iSiz0Y = iSizY = target->sizy;
|
2017-01-30 11:49:56 -05:00
|
|
|
iPos0X = iPosX = target->posx;
|
|
|
|
iPos0Y = iPosY = target->posy;
|
2016-05-10 12:47:31 -04:00
|
|
|
iMaxW = target->resw;
|
|
|
|
iMaxH = target->resh;
|
2014-08-10 12:39:50 -04:00
|
|
|
// Aspect Ratio from window size, or traditional 4:3 by default
|
|
|
|
iRatioX = iSizX ? iSizX : 800;
|
|
|
|
iRatioY = iSizY ? iSizY : 600;
|
2016-09-27 12:47:23 -04:00
|
|
|
// AutoScale: when iSizX == iSizY == 0, size is set to current screen resolution
|
|
|
|
bAutoScale = !(iSizX && iSizY);
|
|
|
|
// guessed initial screen resolution
|
2016-12-28 11:49:00 -05:00
|
|
|
// v2.04.01.fx4: set default value ONLY when zero, because some program may initialize
|
|
|
|
// them before creating a window that triggers second initialization, like "Spearhead"
|
|
|
|
// through the Smack32 SmackSetSystemRes call
|
|
|
|
if(!dwScreenWidth) dwScreenWidth = 800;
|
|
|
|
if(!dwScreenHeight) dwScreenHeight = 600;
|
2015-12-11 11:42:26 -05:00
|
|
|
|
2016-10-05 12:45:56 -04:00
|
|
|
SlowRatio = target->SlowRatio;
|
2016-11-26 11:48:21 -05:00
|
|
|
ScanLine = target->ScanLine;
|
2016-10-05 12:45:56 -04:00
|
|
|
|
2016-04-03 12:42:48 -04:00
|
|
|
GDIEmulationMode = GDIMODE_NONE; // default
|
2015-12-11 11:42:26 -05:00
|
|
|
if (dwFlags2 & GDISTRETCHED) GDIEmulationMode = GDIMODE_STRETCHED;
|
|
|
|
if (dwFlags3 & GDIEMULATEDC) GDIEmulationMode = GDIMODE_EMULATED;
|
2016-04-03 12:42:48 -04:00
|
|
|
if (dwFlags6 & SHAREDDC) GDIEmulationMode = GDIMODE_SHAREDDC;
|
2016-04-17 12:45:41 -04:00
|
|
|
|
2016-12-16 11:48:42 -05:00
|
|
|
if(dwFlags5 & HYBRIDMODE) {
|
|
|
|
// special mode settings ....
|
|
|
|
dwFlags1 |= EMULATESURFACE;
|
|
|
|
dwFlags2 |= SETCOMPATIBILITY;
|
|
|
|
dwFlags5 &= ~(BILINEARFILTER | AEROBOOST);
|
|
|
|
}
|
|
|
|
if(dwFlags5 & GDIMODE) dwFlags1 |= EMULATESURFACE;
|
|
|
|
if(dwFlags5 & STRESSRESOURCES) dwFlags5 |= LIMITRESOURCES;
|
|
|
|
IsEmulated = (dwFlags1 & (EMULATESURFACE|EMULATEBUFFER)) ? TRUE : FALSE; // includes also the HYBRIDMODE and GDIMODE cases ....
|
|
|
|
|
2016-04-17 12:45:41 -04:00
|
|
|
extern GetWindowLong_Type pGetWindowLong;
|
|
|
|
extern SetWindowLong_Type pSetWindowLong;
|
|
|
|
// made before hooking !!!
|
|
|
|
pGetWindowLong = (dwFlags5 & ANSIWIDE) ? GetWindowLongW : GetWindowLongA;
|
|
|
|
pSetWindowLong = (dwFlags5 & ANSIWIDE) ? SetWindowLongW : SetWindowLongA;
|
2016-07-24 12:46:36 -04:00
|
|
|
|
|
|
|
// hint system
|
|
|
|
bHintActive = (dwFlags7 & SHOWHINTS) ? TRUE : FALSE;
|
2016-09-19 12:47:15 -04:00
|
|
|
|
|
|
|
MonitorId = target->monitorid;
|
2016-05-10 12:47:31 -04:00
|
|
|
|
|
|
|
// if specified, set the custom initial resolution
|
|
|
|
if(dxw.dwFlags7 & INITIALRES) SetScreenSize(target->resw, target->resh);
|
2013-01-19 11:16:54 -05:00
|
|
|
}
|
|
|
|
|
2014-04-01 12:38:40 -04:00
|
|
|
void dxwCore::SetScreenSize(void)
|
|
|
|
{
|
2016-05-10 12:47:31 -04:00
|
|
|
// if specified, use values registered in InitTarget
|
|
|
|
if(dxw.dwFlags7 & INITIALRES) return;
|
|
|
|
|
|
|
|
if(dxw.Windowize){
|
2014-12-10 11:39:52 -05:00
|
|
|
SetScreenSize(800, 600); // set to default screen resolution
|
2016-05-10 12:47:31 -04:00
|
|
|
}
|
2014-12-10 11:39:52 -05:00
|
|
|
else{
|
|
|
|
int sizx, sizy;
|
|
|
|
sizx = GetSystemMetrics(SM_CXSCREEN);
|
|
|
|
sizy = GetSystemMetrics(SM_CYSCREEN);
|
|
|
|
SetScreenSize(sizx, sizy);
|
|
|
|
}
|
2014-04-01 12:38:40 -04:00
|
|
|
}
|
|
|
|
|
2014-12-10 11:39:52 -05:00
|
|
|
void dxwCore::SetScreenSize(int x, int y)
|
2014-04-01 12:38:40 -04:00
|
|
|
{
|
|
|
|
DXWNDSTATUS *p;
|
|
|
|
OutTraceDW("DXWND: set screen size=(%d,%d)\n", x, y);
|
|
|
|
if(x) dwScreenWidth=x;
|
|
|
|
if(y) dwScreenHeight=y;
|
|
|
|
p = GetHookInfo();
|
|
|
|
if(p) {
|
|
|
|
p->Width = (short)dwScreenWidth;
|
|
|
|
p->Height = (short)dwScreenHeight;
|
|
|
|
}
|
2014-04-13 12:39:06 -04:00
|
|
|
if(dwFlags4 & LIMITSCREENRES){
|
|
|
|
#define HUGE 100000
|
|
|
|
DWORD maxw, maxh;
|
|
|
|
maxw=HUGE; maxh=HUGE;
|
|
|
|
switch(dxw.MaxScreenRes){
|
|
|
|
case DXW_LIMIT_320x200: maxw=320; maxh=200; break;
|
2014-08-10 12:39:50 -04:00
|
|
|
case DXW_LIMIT_400x300: maxw=400; maxh=300; break;
|
2014-04-13 12:39:06 -04:00
|
|
|
case DXW_LIMIT_640x480: maxw=640; maxh=480; break;
|
|
|
|
case DXW_LIMIT_800x600: maxw=800; maxh=600; break;
|
|
|
|
case DXW_LIMIT_1024x768: maxw=1024; maxh=768; break;
|
|
|
|
case DXW_LIMIT_1280x960: maxw=1280; maxh=960; break;
|
|
|
|
}
|
|
|
|
if(((DWORD)p->Width > maxw) || ((DWORD)p->Height > maxh)){
|
|
|
|
OutTraceDW("DXWND: limit device size=(%d,%d)\n", maxw, maxh);
|
2014-12-10 11:39:52 -05:00
|
|
|
// v2.02.95 setting new virtual desktop size
|
|
|
|
dwScreenWidth = p->Width = (short)maxw;
|
|
|
|
dwScreenHeight= p->Height = (short)maxh;
|
2014-04-13 12:39:06 -04:00
|
|
|
}
|
|
|
|
}
|
2016-05-10 12:47:31 -04:00
|
|
|
if(dxw.dwFlags7 & MAXIMUMRES){
|
|
|
|
if(((long)p->Width > dxw.iMaxW) || ((long)p->Height > dxw.iMaxH)){
|
|
|
|
OutTraceDW("DXWND: limit device size=(%d,%d)\n", dxw.iMaxW, dxw.iMaxH);
|
|
|
|
// v2.03.90 setting new virtual desktop size
|
|
|
|
dwScreenWidth = p->Width = (short)dxw.iMaxW;
|
|
|
|
dwScreenHeight= p->Height = (short)dxw.iMaxH;
|
|
|
|
}
|
|
|
|
}
|
2014-04-01 12:38:40 -04:00
|
|
|
}
|
|
|
|
|
2014-10-08 12:39:38 -04:00
|
|
|
void dxwCore::DumpDesktopStatus()
|
|
|
|
{
|
|
|
|
HDC hDC;
|
|
|
|
HWND hDesktop;
|
|
|
|
RECT desktop;
|
|
|
|
PIXELFORMATDESCRIPTOR pfd;
|
|
|
|
int iPixelFormat, iBPP;
|
2014-08-13 12:39:40 -04:00
|
|
|
char ColorMask[32+1];
|
2014-10-08 12:39:38 -04:00
|
|
|
|
|
|
|
// get the current pixel format index
|
|
|
|
hDesktop = GetDesktopWindow();
|
|
|
|
hDC = GetDC(hDesktop);
|
|
|
|
::GetWindowRect(hDesktop, &desktop);
|
|
|
|
iBPP = GetDeviceCaps(hDC, BITSPIXEL);
|
|
|
|
iPixelFormat = GetPixelFormat(hDC);
|
|
|
|
if(!iPixelFormat) iPixelFormat=1; // why returns 0???
|
|
|
|
// obtain a detailed description of that pixel format
|
|
|
|
if(!DescribePixelFormat(hDC, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd)){
|
|
|
|
OutTrace("DescribePixelFormat ERROR: err=%d\n", GetLastError());
|
|
|
|
return;
|
|
|
|
}
|
2014-08-29 12:39:42 -04:00
|
|
|
|
2014-08-13 12:39:40 -04:00
|
|
|
memset(ColorMask, ' ', 32); // blank fill
|
|
|
|
ColorMask[32] = 0; // terminate
|
|
|
|
if ((pfd.cRedShift+pfd.cRedBits <= 32) &&
|
|
|
|
(pfd.cGreenShift+pfd.cGreenBits <= 32) &&
|
|
|
|
(pfd.cBlueShift+pfd.cBlueBits <= 32) &&
|
|
|
|
(pfd.cAlphaShift+pfd.cAlphaBits <= 32)){ // everything within the 32 bits ...
|
|
|
|
for (int i=pfd.cRedShift; i<pfd.cRedShift+pfd.cRedBits; i++) ColorMask[i]='R';
|
|
|
|
for (int i=pfd.cGreenShift; i<pfd.cGreenShift+pfd.cGreenBits; i++) ColorMask[i]='G';
|
|
|
|
for (int i=pfd.cBlueShift; i<pfd.cBlueShift+pfd.cBlueBits; i++) ColorMask[i]='B';
|
|
|
|
for (int i=pfd.cAlphaShift; i<pfd.cAlphaShift+pfd.cAlphaBits; i++) ColorMask[i]='A';
|
|
|
|
}
|
|
|
|
else
|
|
|
|
strcpy(ColorMask, "???");
|
2014-10-08 12:39:38 -04:00
|
|
|
OutTrace(
|
|
|
|
"Desktop"
|
|
|
|
"\tSize (W x H)=(%d x %d)\n"
|
|
|
|
"\tColor depth = %d (color bits = %d)\n"
|
|
|
|
"\tPixel format = %d\n"
|
|
|
|
"\tColor mask (RGBA)= (%d,%d,%d,%d)\n"
|
|
|
|
"\tColor shift (RGBA)= (%d,%d,%d,%d)\n"
|
|
|
|
"\tColor mask = \"%s\"\n"
|
|
|
|
,
|
|
|
|
desktop.right, desktop.bottom,
|
|
|
|
iBPP, pfd.cColorBits,
|
|
|
|
iPixelFormat,
|
|
|
|
pfd.cRedBits, pfd.cGreenBits, pfd.cBlueBits, pfd.cAlphaBits,
|
|
|
|
pfd.cRedShift, pfd.cGreenShift, pfd.cBlueShift, pfd.cAlphaShift,
|
|
|
|
ColorMask
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2013-01-19 11:16:54 -05:00
|
|
|
void dxwCore::InitWindowPos(int x, int y, int w, int h)
|
|
|
|
{
|
|
|
|
iPosX = x;
|
2013-01-29 11:17:05 -05:00
|
|
|
iPosY = y; //v2.02.09
|
2013-01-19 11:16:54 -05:00
|
|
|
iSizX = w;
|
|
|
|
iSizY = h;
|
2013-06-01 12:16:52 -04:00
|
|
|
}
|
|
|
|
|
2013-05-16 12:19:15 -04:00
|
|
|
BOOL dxwCore::IsDesktop(HWND hwnd)
|
|
|
|
{
|
|
|
|
return (
|
|
|
|
(hwnd == 0)
|
|
|
|
||
|
|
|
|
(hwnd == (*pGetDesktopWindow)())
|
|
|
|
||
|
|
|
|
(hwnd == hWnd)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2013-08-25 12:38:13 -04:00
|
|
|
BOOL dxwCore::IsRealDesktop(HWND hwnd)
|
|
|
|
{
|
|
|
|
return (
|
|
|
|
(hwnd == 0)
|
|
|
|
||
|
|
|
|
(hwnd == (*pGetDesktopWindow)())
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2013-01-04 10:30:38 -05:00
|
|
|
// v2.1.93: FixCursorPos completely revised to introduce a clipping tolerance in
|
|
|
|
// clipping regions as well as in normal operations
|
|
|
|
|
|
|
|
#define CLIP_TOLERANCE 4
|
|
|
|
|
|
|
|
POINT dxwCore::FixCursorPos(POINT prev)
|
2012-12-24 10:20:23 -05:00
|
|
|
{
|
|
|
|
POINT curr;
|
|
|
|
RECT rect;
|
|
|
|
extern LPRECT lpClipRegion;
|
2015-01-03 11:40:25 -05:00
|
|
|
static BOOL IsWithin = TRUE;
|
|
|
|
static POINT LastPos;
|
2012-12-24 10:20:23 -05:00
|
|
|
|
|
|
|
curr=prev;
|
|
|
|
|
|
|
|
// scale mouse coordinates
|
|
|
|
// remember: rect from GetClientRect always start at 0,0!
|
2013-01-04 10:30:38 -05:00
|
|
|
if(dxw.dwFlags1 & MODIFYMOUSE){
|
2016-09-19 12:47:15 -04:00
|
|
|
int w, h; // width, height and border
|
2013-09-18 12:38:18 -04:00
|
|
|
|
2013-10-08 12:38:12 -04:00
|
|
|
if (!(*pGetClientRect)(hWnd, &rect)) { // v2.02.30: always use desktop win
|
2013-12-22 11:38:36 -05:00
|
|
|
OutTraceDW("GetClientRect ERROR %d at %d\n", GetLastError(),__LINE__);
|
2012-12-24 10:20:23 -05:00
|
|
|
curr.x = curr.y = 0;
|
|
|
|
}
|
2013-10-08 12:38:12 -04:00
|
|
|
w = rect.right - rect.left;
|
|
|
|
h = rect.bottom - rect.top;
|
|
|
|
|
2014-04-22 12:39:07 -04:00
|
|
|
if(dxw.dwFlags4 & RELEASEMOUSE){
|
2015-01-03 11:40:25 -05:00
|
|
|
if ((curr.x < 0) || (curr.y < 0) || (curr.x > w) || (curr.y > h)){
|
|
|
|
if(IsWithin){
|
|
|
|
int RestX, RestY;
|
|
|
|
RestX = w ? ((CLIP_TOLERANCE * w) / dxw.GetScreenWidth()) + 2 : CLIP_TOLERANCE + 2;
|
|
|
|
RestY = h ? ((CLIP_TOLERANCE * h) / dxw.GetScreenHeight()) + 2 : CLIP_TOLERANCE + 2;
|
|
|
|
if (curr.x < 0) curr.x = RestX;
|
|
|
|
if (curr.y < 0) curr.y = RestY;
|
|
|
|
if (curr.x > w) curr.x = w - RestX;
|
|
|
|
if (curr.y > h) curr.y = h - RestY;
|
|
|
|
LastPos = curr;
|
|
|
|
IsWithin = FALSE;
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
curr = LastPos;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
IsWithin = TRUE;
|
|
|
|
LastPos = curr;
|
|
|
|
}
|
2014-04-22 12:39:07 -04:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (curr.x < 0) curr.x = 0;
|
|
|
|
if (curr.y < 0) curr.y = 0;
|
|
|
|
if (curr.x > w) curr.x = w;
|
|
|
|
if (curr.y > h) curr.y = h;
|
|
|
|
}
|
2013-07-04 12:18:11 -04:00
|
|
|
|
2013-10-08 12:38:12 -04:00
|
|
|
if (w) curr.x = (curr.x * dxw.GetScreenWidth()) / w;
|
|
|
|
if (h) curr.y = (curr.y * dxw.GetScreenHeight()) / h;
|
2012-12-24 10:20:23 -05:00
|
|
|
}
|
|
|
|
|
2016-10-12 12:48:37 -04:00
|
|
|
if((dxw.dwFlags1 & DISABLECLIPPING) && lpClipRegion){
|
2012-12-24 10:20:23 -05:00
|
|
|
// v2.1.93:
|
|
|
|
// in clipping mode, avoid the cursor position to lay outside the valid rect
|
|
|
|
// note 1: the rect follow the convention and valid coord lay between left to righ-1,
|
|
|
|
// top to bottom-1
|
|
|
|
// note 2: CLIP_TOLERANCE is meant to handle possible integer divide tolerance errors
|
|
|
|
// that may prevent reaching the clip rect borders. The smaller you shrink the window,
|
|
|
|
// the bigger tolerance is required
|
|
|
|
if (curr.x < lpClipRegion->left+CLIP_TOLERANCE) curr.x=lpClipRegion->left;
|
|
|
|
if (curr.y < lpClipRegion->top+CLIP_TOLERANCE) curr.y=lpClipRegion->top;
|
|
|
|
if (curr.x >= lpClipRegion->right-CLIP_TOLERANCE) curr.x=lpClipRegion->right-1;
|
|
|
|
if (curr.y >= lpClipRegion->bottom-CLIP_TOLERANCE) curr.y=lpClipRegion->bottom-1;
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
if (curr.x < CLIP_TOLERANCE) curr.x=0;
|
|
|
|
if (curr.y < CLIP_TOLERANCE) curr.y=0;
|
2013-01-04 10:30:38 -05:00
|
|
|
if (curr.x >= (LONG)dxw.GetScreenWidth()-CLIP_TOLERANCE) curr.x=dxw.GetScreenWidth()-1;
|
|
|
|
if (curr.y >= (LONG)dxw.GetScreenHeight()-CLIP_TOLERANCE) curr.y=dxw.GetScreenHeight()-1;
|
2012-12-24 10:20:23 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
return curr;
|
2013-01-04 10:30:38 -05:00
|
|
|
}
|
|
|
|
|
2013-04-04 12:17:08 -04:00
|
|
|
POINT dxwCore::ScreenToClient(POINT point)
|
|
|
|
{
|
|
|
|
// convert absolute screen coordinates to frame relative
|
|
|
|
if (!(*pScreenToClient)(hWnd, &point)) {
|
|
|
|
OutTraceE("ScreenToClient(%x) ERROR %d at %d\n", hWnd, GetLastError(), __LINE__);
|
|
|
|
point.x =0; point.y=0;
|
|
|
|
}
|
2013-07-04 12:18:11 -04:00
|
|
|
|
2013-04-04 12:17:08 -04:00
|
|
|
return point;
|
|
|
|
}
|
|
|
|
|
2013-01-04 10:30:38 -05:00
|
|
|
void dxwCore::FixNCHITCursorPos(LPPOINT lppoint)
|
|
|
|
{
|
|
|
|
RECT rect;
|
|
|
|
POINT point;
|
|
|
|
|
|
|
|
point=*lppoint;
|
|
|
|
(*pGetClientRect)(dxw.GethWnd(), &rect);
|
|
|
|
(*pScreenToClient)(dxw.GethWnd(), &point);
|
|
|
|
|
|
|
|
if (point.x < 0) return;
|
|
|
|
if (point.y < 0) return;
|
|
|
|
if (point.x > rect.right) return;
|
|
|
|
if (point.y > rect.bottom) return;
|
|
|
|
|
|
|
|
*lppoint=point;
|
|
|
|
lppoint->x = (lppoint->x * dxw.GetScreenWidth()) / rect.right;
|
|
|
|
lppoint->y = (lppoint->y * dxw.GetScreenHeight()) / rect.bottom;
|
|
|
|
if(lppoint->x < CLIP_TOLERANCE) lppoint->x=0;
|
|
|
|
if(lppoint->y < CLIP_TOLERANCE) lppoint->y=0;
|
|
|
|
if(lppoint->x > (LONG)dxw.GetScreenWidth()-CLIP_TOLERANCE) lppoint->x=dxw.GetScreenWidth()-1;
|
|
|
|
if(lppoint->y > (LONG)dxw.GetScreenHeight()-CLIP_TOLERANCE) lppoint->y=dxw.GetScreenHeight()-1;
|
|
|
|
}
|
|
|
|
|
2017-02-05 11:50:05 -05:00
|
|
|
void dxwCore::InitializeClipCursorState(void)
|
|
|
|
{
|
|
|
|
RECT cliprect;
|
|
|
|
BOOL clipret;
|
|
|
|
clipret = (*pGetClipCursor)(&cliprect);
|
|
|
|
// v2.04.06: you always get a clipper area. To tell that the clipper is NOT active for your window
|
|
|
|
// you can compare the clipper area with the whole desktop. If they are equivalent, you have no
|
|
|
|
// clipper (or you are in fullscreen mode, but that is equivalent).
|
|
|
|
ClipCursorToggleState = TRUE;
|
|
|
|
if (((cliprect.right - cliprect.left) == (*pGetSystemMetrics)(SM_CXVIRTUALSCREEN)) &&
|
|
|
|
((cliprect.bottom - cliprect.top) == (*pGetSystemMetrics)(SM_CYVIRTUALSCREEN)))
|
|
|
|
ClipCursorToggleState = FALSE;
|
|
|
|
OutTraceDW("Initial clipper status=%x\n", ClipCursorToggleState);
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL dxwCore::IsClipCursorActive(void)
|
|
|
|
{
|
|
|
|
static BOOL bDoOnce = TRUE;
|
|
|
|
if (bDoOnce) InitializeClipCursorState();
|
|
|
|
return ClipCursorToggleState;
|
|
|
|
}
|
|
|
|
|
2013-01-04 10:30:38 -05:00
|
|
|
void dxwCore::SetClipCursor()
|
|
|
|
{
|
|
|
|
RECT Rect;
|
2013-07-09 12:38:16 -04:00
|
|
|
POINT UpLeftCorner={0,0};
|
2013-01-04 10:30:38 -05:00
|
|
|
|
2013-12-22 11:38:36 -05:00
|
|
|
OutTraceDW("SetClipCursor:\n");
|
2013-01-04 10:30:38 -05:00
|
|
|
if (hWnd==NULL) {
|
2013-12-22 11:38:36 -05:00
|
|
|
OutTraceDW("SetClipCursor: ASSERT hWnd==NULL\n");
|
2013-01-04 10:30:38 -05:00
|
|
|
return;
|
|
|
|
}
|
2016-04-20 12:45:44 -04:00
|
|
|
|
2016-04-01 12:42:40 -04:00
|
|
|
// check for errors to avoid setting random clip regions
|
2017-02-15 11:50:18 -05:00
|
|
|
//if((*pIsWindowVisible)(hWnd)){
|
|
|
|
// OutTraceE("SetClipCursor: not visible\n");
|
|
|
|
// return;
|
|
|
|
//}
|
2016-04-01 12:42:40 -04:00
|
|
|
if(!(*pGetClientRect)(hWnd, &Rect)){
|
2016-12-04 11:45:35 -05:00
|
|
|
OutTraceE("SetClipCursor: GetClientRect ERROR err=%d at %d\n", GetLastError(), __LINE__);
|
2016-04-01 12:42:40 -04:00
|
|
|
return;
|
|
|
|
}
|
2016-02-09 11:47:00 -05:00
|
|
|
if((Rect.right == 0) && (Rect.bottom == 0)){
|
|
|
|
OutTraceE("SetClipCursor: GetClientRect returns zero sized rect at %d\n", __LINE__);
|
|
|
|
return;
|
|
|
|
}
|
2016-04-01 12:42:40 -04:00
|
|
|
if(!(*pClientToScreen)(hWnd, &UpLeftCorner)){
|
2016-12-04 11:45:35 -05:00
|
|
|
OutTraceE("SetClipCursor: ClientToScreen ERROR err=%d at %d\n", GetLastError(), __LINE__);
|
2016-04-01 12:42:40 -04:00
|
|
|
return ;
|
|
|
|
}
|
2013-01-04 10:30:38 -05:00
|
|
|
Rect.left+=UpLeftCorner.x;
|
|
|
|
Rect.right+=UpLeftCorner.x;
|
|
|
|
Rect.top+=UpLeftCorner.y;
|
|
|
|
Rect.bottom+=UpLeftCorner.y;
|
2017-02-02 11:50:00 -05:00
|
|
|
|
2017-02-05 11:50:05 -05:00
|
|
|
if(dwFlags8 & CLIPMENU) {
|
|
|
|
// v2.04.11:
|
|
|
|
// if flag set and the window has a menu, extend the mouse clipper area to allow reaching the manu
|
|
|
|
// implementation is partial: doesn't take in account multi-lines menues or menus positioned
|
|
|
|
// not on the top of the window client area, but it seems good for the most cases.
|
|
|
|
if(GetMenu(hWnd)) Rect.top -= (*pGetSystemMetrics)(SM_CYMENU);
|
|
|
|
}
|
2017-02-02 11:50:00 -05:00
|
|
|
|
2013-01-04 10:30:38 -05:00
|
|
|
(*pClipCursor)(NULL);
|
2017-02-05 11:50:05 -05:00
|
|
|
if((*pClipCursor)(&Rect)){
|
|
|
|
ClipCursorToggleState = TRUE;
|
|
|
|
}
|
|
|
|
else{
|
2016-12-04 11:45:35 -05:00
|
|
|
OutTraceE("SetClipCursor: ERROR err=%d at %d\n", GetLastError(), __LINE__);
|
2017-02-05 11:50:05 -05:00
|
|
|
}
|
|
|
|
|
2013-12-22 11:38:36 -05:00
|
|
|
OutTraceDW("SetClipCursor: rect=(%d,%d)-(%d,%d)\n",
|
2013-01-04 10:30:38 -05:00
|
|
|
Rect.left, Rect.top, Rect.right, Rect.bottom);
|
|
|
|
}
|
|
|
|
|
|
|
|
void dxwCore::EraseClipCursor()
|
|
|
|
{
|
2013-12-22 11:38:36 -05:00
|
|
|
OutTraceDW("EraseClipCursor:\n");
|
2013-01-04 10:30:38 -05:00
|
|
|
(*pClipCursor)(NULL);
|
2017-02-05 11:50:05 -05:00
|
|
|
ClipCursorToggleState = FALSE;
|
2013-01-04 10:30:38 -05:00
|
|
|
}
|
|
|
|
|
2013-08-25 12:38:13 -04:00
|
|
|
void dxwCore::SethWnd(HWND hwnd)
|
|
|
|
{
|
2013-12-27 11:38:38 -05:00
|
|
|
RECT WinRect;
|
2014-04-01 12:38:40 -04:00
|
|
|
if(!pGetWindowRect) pGetWindowRect=::GetWindowRect;
|
|
|
|
if(!pGDIGetDC) pGDIGetDC=::GetDC;
|
|
|
|
|
2013-08-25 12:38:13 -04:00
|
|
|
hWnd=hwnd;
|
2014-04-01 12:38:40 -04:00
|
|
|
hWndFPS=hwnd;
|
|
|
|
|
2015-12-11 11:42:26 -05:00
|
|
|
if(hwnd){
|
|
|
|
(*pGetWindowRect)(hwnd, &WinRect);
|
2016-07-13 12:46:31 -04:00
|
|
|
OutTraceDW("SethWnd: setting main win=%x pos=(%d,%d)-(%d,%d)\n",
|
|
|
|
hwnd, WinRect.left, WinRect.top, WinRect.right, WinRect.bottom);
|
2015-12-11 11:42:26 -05:00
|
|
|
}
|
|
|
|
else{
|
|
|
|
OutTraceDW("SethWnd: clearing main win\n");
|
|
|
|
}
|
2013-08-25 12:38:13 -04:00
|
|
|
}
|
|
|
|
|
2014-10-30 12:39:54 -04:00
|
|
|
BOOL dxwCore::ishWndFPS(HWND hwnd)
|
|
|
|
{
|
|
|
|
return (hwnd == hWndFPS);
|
|
|
|
}
|
|
|
|
|
2013-09-16 12:38:17 -04:00
|
|
|
void dxwCore::FixWorkarea(LPRECT workarea)
|
|
|
|
{
|
|
|
|
int w, h, b; // width, height and border
|
2013-09-18 12:38:18 -04:00
|
|
|
|
2013-09-16 12:38:17 -04:00
|
|
|
w = workarea->right - workarea->left;
|
|
|
|
h = workarea->bottom - workarea->top;
|
2013-09-18 12:38:18 -04:00
|
|
|
if ((w * iRatioY) > (h * iRatioX)){
|
|
|
|
b = (w - (h * iRatioX / iRatioY))/2;
|
2013-09-16 12:38:17 -04:00
|
|
|
workarea->left += b;
|
|
|
|
workarea->right -= b;
|
|
|
|
}
|
|
|
|
else {
|
2013-09-18 12:38:18 -04:00
|
|
|
b = (h - (w * iRatioY / iRatioX))/2;
|
2013-09-16 12:38:17 -04:00
|
|
|
workarea->top += b;
|
|
|
|
workarea->bottom -= b;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-13 12:40:54 -04:00
|
|
|
//#define DUMPALLPALETTECHANGES TRUE
|
|
|
|
|
2013-11-28 11:38:31 -05:00
|
|
|
void dxwCore::DumpPalette(DWORD dwcount, LPPALETTEENTRY lpentries)
|
|
|
|
{
|
2015-11-02 11:40:21 -05:00
|
|
|
char sInfo[(14*256)+1];
|
|
|
|
sInfo[0]=0;
|
2016-12-28 11:49:00 -05:00
|
|
|
// "Spearhead" has a bug that sets 897 palette entries!
|
|
|
|
if(dwcount > 256) dwcount=256;
|
2013-11-28 11:38:31 -05:00
|
|
|
for(DWORD idx=0; idx<dwcount; idx++)
|
2015-11-02 11:40:21 -05:00
|
|
|
sprintf(sInfo, "%s(%02x.%02x.%02x:%02x)", sInfo,
|
2013-11-28 11:38:31 -05:00
|
|
|
lpentries[idx].peRed, lpentries[idx].peGreen, lpentries[idx].peBlue, lpentries[idx].peFlags);
|
2015-11-02 11:40:21 -05:00
|
|
|
strcat(sInfo,"\n");
|
|
|
|
OutTrace(sInfo);
|
2015-06-13 12:40:54 -04:00
|
|
|
|
|
|
|
#ifdef DUMPALLPALETTECHANGES
|
|
|
|
if(DUMPALLPALETTECHANGES){
|
|
|
|
extern DXWNDSTATUS *pStatus;
|
|
|
|
for(DWORD idx=0; idx<dwcount; idx++)
|
|
|
|
pStatus->Palette[idx]= lpentries[idx];
|
|
|
|
Sleep(2000);
|
|
|
|
}
|
|
|
|
#endif
|
2013-11-28 11:38:31 -05:00
|
|
|
}
|
|
|
|
|
2013-01-04 10:30:38 -05:00
|
|
|
void dxwCore::ScreenRefresh(void)
|
|
|
|
{
|
|
|
|
// optimization: don't blit too often!
|
|
|
|
// 20mSec seems a good compromise.
|
|
|
|
#define DXWREFRESHINTERVAL 20
|
|
|
|
|
|
|
|
LPDIRECTDRAWSURFACE lpDDSPrim;
|
2016-06-04 12:45:32 -04:00
|
|
|
extern HRESULT WINAPI extBlt(int, Blt_Type, LPDIRECTDRAWSURFACE, LPRECT, LPDIRECTDRAWSURFACE, LPRECT, DWORD, LPDDBLTFX);
|
2013-01-04 10:30:38 -05:00
|
|
|
|
|
|
|
static int t = -1;
|
|
|
|
if (t == -1)
|
2013-01-29 11:17:05 -05:00
|
|
|
t = (*pGetTickCount)()-(DXWREFRESHINTERVAL+1); // V.2.1.69: trick - subtract
|
|
|
|
int tn = (*pGetTickCount)();
|
2013-01-04 10:30:38 -05:00
|
|
|
|
|
|
|
if (tn-t < DXWREFRESHINTERVAL) return;
|
2013-11-28 11:38:31 -05:00
|
|
|
t = tn;
|
2013-01-04 10:30:38 -05:00
|
|
|
|
2014-03-23 12:38:58 -04:00
|
|
|
// if not too early, refresh primary surface ....
|
2015-05-23 12:40:49 -04:00
|
|
|
lpDDSPrim=dxwss.GetPrimarySurface();
|
2016-06-04 12:45:32 -04:00
|
|
|
extern Blt_Type pBltMethod();
|
|
|
|
extern int lpddsHookedVersion();
|
|
|
|
if (lpDDSPrim) extBlt(lpddsHookedVersion(), pBltMethod(), lpDDSPrim, NULL, lpDDSPrim, NULL, 0, NULL);
|
2013-01-04 10:30:38 -05:00
|
|
|
|
2013-11-28 11:38:31 -05:00
|
|
|
// v2.02.44 - used for what? Commenting out seems to fix the palette update glitches
|
2015-04-18 12:40:38 -04:00
|
|
|
// and make the "Palette updates don't blit" option useless....
|
2013-11-28 11:38:31 -05:00
|
|
|
//(*pInvalidateRect)(hWnd, NULL, FALSE);
|
2013-06-01 12:16:52 -04:00
|
|
|
}
|
|
|
|
|
2013-05-02 12:17:06 -04:00
|
|
|
void dxwCore::DoSlow(int delay)
|
|
|
|
{
|
|
|
|
MSG uMsg;
|
|
|
|
int t, tn;
|
|
|
|
t = (*pGetTickCount)();
|
|
|
|
|
|
|
|
uMsg.message=0; // initialize somehow...
|
|
|
|
while((tn = (*pGetTickCount)())-t < delay){
|
|
|
|
while (PeekMessage (&uMsg, NULL, 0, 0, PM_REMOVE) > 0){
|
|
|
|
if(WM_QUIT == uMsg.message) break;
|
|
|
|
TranslateMessage (&uMsg);
|
|
|
|
DispatchMessage (&uMsg);
|
|
|
|
}
|
|
|
|
(*pSleep)(1);
|
|
|
|
}
|
|
|
|
}
|
2013-06-01 12:16:52 -04:00
|
|
|
|
2014-10-30 12:39:54 -04:00
|
|
|
// Remarks:
|
|
|
|
// If the target window is owned by the current process, GetWindowText causes a WM_GETTEXT message
|
|
|
|
// to be sent to the specified window or control. If the target window is owned by another process
|
|
|
|
// and has a caption, GetWindowText retrieves the window caption text. If the window does not have
|
|
|
|
// a caption, the return value is a null string. This behavior is by design. It allows applications
|
|
|
|
// to call GetWindowText without becoming unresponsive if the process that owns the target window
|
|
|
|
// is not responding. However, if the target window is not responding and it belongs to the calling
|
|
|
|
// application, GetWindowText will cause the calling application to become unresponsive.
|
|
|
|
|
2013-01-25 11:17:02 -05:00
|
|
|
static void CountFPS(HWND hwnd)
|
2013-06-01 12:16:52 -04:00
|
|
|
{
|
|
|
|
static DWORD time = 0xFFFFFFFF;
|
|
|
|
static DWORD FPSCount = 0;
|
2014-10-30 12:39:54 -04:00
|
|
|
static HWND LasthWnd = 0;
|
2013-01-25 11:17:02 -05:00
|
|
|
extern void SetFPS(int);
|
2014-10-30 12:39:54 -04:00
|
|
|
static char sBuf[80+15+1]; // title + fps string + terminator
|
2013-01-25 11:17:02 -05:00
|
|
|
//DXWNDSTATUS Status;
|
2013-06-01 12:16:52 -04:00
|
|
|
DWORD tmp;
|
2013-01-29 11:17:05 -05:00
|
|
|
tmp = (*pGetTickCount)();
|
2013-06-01 12:16:52 -04:00
|
|
|
if((tmp - time) > 1000) {
|
2013-01-25 11:17:02 -05:00
|
|
|
char *fpss;
|
2013-06-01 12:16:52 -04:00
|
|
|
// log fps count
|
2013-12-22 11:38:36 -05:00
|
|
|
// OutTrace("FPS: Delta=%x FPSCount=%d\n", (tmp-time), FPSCount);
|
2013-06-01 12:16:52 -04:00
|
|
|
// show fps count on status win
|
2013-01-25 11:17:02 -05:00
|
|
|
GetHookInfo()->FPSCount = FPSCount; // for overlay display
|
|
|
|
// show fps on win title bar
|
|
|
|
if (dxw.dwFlags2 & SHOWFPS){
|
2014-10-30 12:39:54 -04:00
|
|
|
if(hwnd != LasthWnd){
|
|
|
|
GetWindowText(hwnd, sBuf, 80);
|
|
|
|
LasthWnd = hwnd;
|
|
|
|
}
|
2013-01-25 11:17:02 -05:00
|
|
|
fpss=strstr(sBuf," ~ (");
|
|
|
|
if(fpss==NULL) fpss=&sBuf[strlen(sBuf)];
|
2013-05-16 12:19:15 -04:00
|
|
|
sprintf_s(fpss, 15, " ~ (%d FPS)", FPSCount);
|
2013-01-25 11:17:02 -05:00
|
|
|
SetWindowText(hwnd, sBuf);
|
|
|
|
}
|
2013-06-01 12:16:52 -04:00
|
|
|
// reset
|
|
|
|
FPSCount=0;
|
|
|
|
time = tmp;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
FPSCount++;
|
2013-05-16 12:19:15 -04:00
|
|
|
OutTraceB("FPS: Delta=%x FPSCount++=%d\n", (tmp-time), FPSCount);
|
2013-06-01 12:16:52 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-25 11:17:02 -05:00
|
|
|
static void LimitFrameCount(DWORD delay)
|
2013-06-01 12:16:52 -04:00
|
|
|
{
|
2014-10-30 12:39:54 -04:00
|
|
|
static DWORD oldtime = (*pGetTickCount)();
|
2013-01-25 11:17:02 -05:00
|
|
|
DWORD newtime;
|
|
|
|
newtime = (*pGetTickCount)();
|
2014-10-30 12:39:54 -04:00
|
|
|
if(IsDebug) OutTrace("FPS limit: old=%x new=%x delay=%d sleep=%d\n",
|
|
|
|
oldtime, newtime, delay, (oldtime+delay-newtime));
|
2013-01-25 11:17:02 -05:00
|
|
|
// use '<' and not '<=' to avoid the risk of sleeping forever....
|
2014-10-30 12:39:54 -04:00
|
|
|
if((newtime < oldtime+delay) && (newtime >= oldtime)) {
|
|
|
|
//if(IsDebug) OutTrace("FPS limit: old=%x new=%x delay=%d sleep=%d\n",
|
|
|
|
// oldtime, newtime, delay, (oldtime+delay-newtime));
|
|
|
|
do{
|
|
|
|
if(IsDebug) OutTrace("FPS limit: sleep=%d\n", oldtime+delay-newtime);
|
|
|
|
(*pSleep)(oldtime+delay-newtime);
|
|
|
|
newtime = (*pGetTickCount)();
|
|
|
|
if(IsDebug) OutTrace("FPS limit: newtime=%d\n", newtime);
|
|
|
|
} while(newtime < oldtime+delay);
|
2013-01-29 11:17:05 -05:00
|
|
|
}
|
2014-10-30 12:39:54 -04:00
|
|
|
oldtime += delay;
|
|
|
|
if(oldtime < newtime-delay) oldtime = newtime-delay;
|
2013-06-01 12:16:52 -04:00
|
|
|
}
|
|
|
|
|
2013-01-25 11:17:02 -05:00
|
|
|
static BOOL SkipFrameCount(DWORD delay)
|
2013-06-01 12:16:52 -04:00
|
|
|
{
|
2013-01-25 11:17:02 -05:00
|
|
|
static DWORD oldtime=(*pGetTickCount)();
|
|
|
|
DWORD newtime;
|
|
|
|
newtime = (*pGetTickCount)();
|
2013-01-29 11:17:05 -05:00
|
|
|
if(newtime < oldtime+delay) return TRUE; // TRUE => skip the screen refresh
|
2013-01-25 11:17:02 -05:00
|
|
|
oldtime = newtime;
|
2013-01-29 11:17:05 -05:00
|
|
|
return FALSE; // don't skip, do the update
|
2013-01-25 11:17:02 -05:00
|
|
|
|
2013-06-01 12:16:52 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
BOOL dxwCore::HandleFPS()
|
|
|
|
{
|
2013-06-15 12:21:25 -04:00
|
|
|
if(dwFlags2 & (SHOWFPS|SHOWFPSOVERLAY)) CountFPS(hWndFPS);
|
2013-06-01 12:16:52 -04:00
|
|
|
if(dwFlags2 & LIMITFPS) LimitFrameCount(dxw.MaxFPS);
|
|
|
|
if(dwFlags2 & SKIPFPS) if(SkipFrameCount(dxw.MaxFPS)) return TRUE;
|
|
|
|
return FALSE;
|
2013-08-01 12:16:53 -04:00
|
|
|
}
|
2014-10-08 12:39:38 -04:00
|
|
|
|
|
|
|
// auxiliary functions ...
|
|
|
|
|
|
|
|
void dxwCore::SetVSyncDelays(UINT RefreshRate)
|
|
|
|
{
|
|
|
|
int Reminder;
|
2015-11-02 11:40:21 -05:00
|
|
|
char sInfo[256];
|
2014-10-08 12:39:38 -04:00
|
|
|
|
2015-02-15 11:40:23 -05:00
|
|
|
if(!(dxw.dwFlags1 & SAVELOAD)) return;
|
2014-10-08 12:39:38 -04:00
|
|
|
if((RefreshRate < 10) || (RefreshRate > 100)) return;
|
|
|
|
|
|
|
|
gdwRefreshRate = RefreshRate;
|
|
|
|
if(!gdwRefreshRate) return;
|
|
|
|
iRefreshDelayCount=0;
|
|
|
|
Reminder=0;
|
|
|
|
do{
|
|
|
|
iRefreshDelays[iRefreshDelayCount]=(1000+Reminder)/gdwRefreshRate;
|
|
|
|
Reminder=(1000+Reminder)-(iRefreshDelays[iRefreshDelayCount]*gdwRefreshRate);
|
|
|
|
iRefreshDelayCount++;
|
|
|
|
} while(Reminder && (iRefreshDelayCount<MAXREFRESHDELAYCOUNT));
|
2015-11-02 11:40:21 -05:00
|
|
|
if(IsTraceDW){
|
|
|
|
strcpy(sInfo, "");
|
|
|
|
for(int i=0; i<iRefreshDelayCount; i++) sprintf(sInfo, "%s%d ", sInfo, iRefreshDelays[i]);
|
|
|
|
OutTraceDW("Refresh rate=%d: delay=%s\n", gdwRefreshRate, sInfo);
|
|
|
|
}
|
2014-10-08 12:39:38 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void dxwCore::VSyncWait()
|
|
|
|
{
|
|
|
|
static DWORD time = 0;
|
|
|
|
static BOOL step = 0;
|
|
|
|
DWORD tmp;
|
|
|
|
tmp = (*pGetTickCount)();
|
|
|
|
if((time - tmp) > 32) time = tmp;
|
|
|
|
(*pSleep)(time - tmp);
|
|
|
|
time += iRefreshDelays[step++];
|
|
|
|
if(step >= iRefreshDelayCount) step=0;
|
|
|
|
}
|
|
|
|
|
2016-11-26 11:48:21 -05:00
|
|
|
void dxwCore::VSyncWaitLine(DWORD ScanLine)
|
|
|
|
{
|
|
|
|
extern LPDIRECTDRAW lpPrimaryDD;
|
|
|
|
static DWORD iLastScanLine = 0;
|
|
|
|
DWORD iCurrentScanLine;
|
|
|
|
if (!lpPrimaryDD) return;
|
|
|
|
while(1){
|
|
|
|
HRESULT res;
|
|
|
|
if(res=lpPrimaryDD->GetScanLine(&iCurrentScanLine)) {
|
|
|
|
OutTraceE("VSyncWaitLine: GetScanLine ERROR res=%x\n", res);
|
|
|
|
iLastScanLine = 0;
|
|
|
|
break; // error
|
|
|
|
}
|
|
|
|
if((iLastScanLine <= ScanLine) && (iCurrentScanLine > ScanLine)) {
|
|
|
|
OutTraceB("VSyncWaitLine: line=%d last=%d\n", iCurrentScanLine, iLastScanLine);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
iLastScanLine = iCurrentScanLine;
|
|
|
|
(*pSleep)(1);
|
|
|
|
}
|
|
|
|
}
|
2014-10-08 12:39:38 -04:00
|
|
|
|
2014-03-23 12:38:58 -04:00
|
|
|
static float fMul[17]={2.14F, 1.95F, 1.77F, 1.61F, 1.46F, 1.33F, 1.21F, 1.10F, 1.00F, 0.91F, 0.83F, 0.75F, 0.68F, 0.62F, 0.56F, 0.51F, 0.46F};
|
2013-08-01 12:16:53 -04:00
|
|
|
|
2014-03-23 12:38:58 -04:00
|
|
|
static DWORD TimeShifterFine(DWORD val, int shift)
|
|
|
|
{
|
|
|
|
float fVal;
|
|
|
|
fVal = (float)val * fMul[shift+8];
|
|
|
|
return (DWORD)fVal;
|
|
|
|
}
|
|
|
|
|
|
|
|
static DWORD TimeShifterCoarse(DWORD val, int shift)
|
2013-01-20 11:16:58 -05:00
|
|
|
{
|
|
|
|
int exp, reminder;
|
|
|
|
if (shift > 0) {
|
|
|
|
exp = shift >> 1;
|
|
|
|
reminder = shift & 0x1;
|
|
|
|
if (reminder) val -= (val >> 2); // val * (1-1/4) = val * 3/4
|
|
|
|
val >>= exp; // val * 2^exp
|
|
|
|
}
|
|
|
|
if (shift < 0) {
|
|
|
|
exp = (-shift) >> 1;
|
|
|
|
reminder = (-shift) & 0x1;
|
|
|
|
val <<= exp; // val / 2^exp
|
|
|
|
if (reminder) val += (val >> 1); // val * (1+1/2) = val * 3/2
|
|
|
|
}
|
|
|
|
return val;
|
|
|
|
}
|
|
|
|
|
2014-03-23 12:38:58 -04:00
|
|
|
static LARGE_INTEGER TimeShifter64Fine(LARGE_INTEGER val, int shift)
|
|
|
|
{
|
|
|
|
float fVal;
|
|
|
|
fVal = (float)val.LowPart * fMul[shift+8];
|
|
|
|
val.HighPart = 0;
|
|
|
|
val.LowPart = (DWORD)fVal;
|
|
|
|
return val;
|
|
|
|
}
|
|
|
|
|
|
|
|
static LARGE_INTEGER TimeShifter64Coarse(LARGE_INTEGER val, int shift)
|
2014-04-01 12:38:40 -04:00
|
|
|
{
|
|
|
|
int exp, reminder;
|
|
|
|
if (shift > 0) {
|
|
|
|
exp = shift >> 1;
|
|
|
|
reminder = shift & 0x1;
|
|
|
|
if (reminder) val.QuadPart -= (val.QuadPart >> 2); // val * (1-1/4) = val * 3/4
|
|
|
|
val.QuadPart >>= exp; // val * 2^exp
|
|
|
|
}
|
|
|
|
if (shift < 0) {
|
|
|
|
exp = (-shift) >> 1;
|
|
|
|
reminder = (-shift) & 0x1;
|
|
|
|
val.QuadPart <<= exp; // val / 2^exp
|
|
|
|
if (reminder) val.QuadPart += (val.QuadPart >> 1); // val * (1+1/2) = val * 3/2
|
|
|
|
}
|
|
|
|
return val;
|
|
|
|
}
|
|
|
|
|
2013-08-01 12:16:53 -04:00
|
|
|
DWORD dxwCore::GetTickCount(void)
|
|
|
|
{
|
|
|
|
DWORD dwTick;
|
|
|
|
static DWORD dwLastRealTick=0;
|
|
|
|
static DWORD dwLastFakeTick=0;
|
|
|
|
DWORD dwNextRealTick;
|
2014-03-23 12:38:58 -04:00
|
|
|
static BOOL FirstTime = TRUE;
|
2013-08-01 12:16:53 -04:00
|
|
|
|
2014-01-03 11:38:52 -05:00
|
|
|
if(FirstTime){
|
|
|
|
dwLastRealTick=(*pGetTickCount)();
|
|
|
|
dwLastFakeTick=dwLastRealTick;
|
|
|
|
FirstTime=FALSE;
|
|
|
|
}
|
2013-08-01 12:16:53 -04:00
|
|
|
dwNextRealTick=(*pGetTickCount)();
|
|
|
|
dwTick=(dwNextRealTick-dwLastRealTick);
|
2013-01-25 11:17:02 -05:00
|
|
|
TimeShift=GetHookInfo()->TimeShift;
|
2014-03-23 12:38:58 -04:00
|
|
|
dwTick = (*pTimeShifter)(dwTick, TimeShift);
|
2015-11-19 11:42:28 -05:00
|
|
|
if(TimeFreeze) dwTick=0;
|
2013-08-01 12:16:53 -04:00
|
|
|
dwLastFakeTick += dwTick;
|
|
|
|
dwLastRealTick = dwNextRealTick;
|
|
|
|
return dwLastFakeTick;
|
2013-01-19 11:16:54 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
DWORD dxwCore::StretchTime(DWORD dwTimer)
|
|
|
|
{
|
2013-01-25 11:17:02 -05:00
|
|
|
TimeShift=GetHookInfo()->TimeShift;
|
2014-03-23 12:38:58 -04:00
|
|
|
dwTimer = (*pTimeShifter)(dwTimer, -TimeShift);
|
2013-01-19 11:16:54 -05:00
|
|
|
return dwTimer;
|
|
|
|
}
|
|
|
|
|
2013-11-17 11:38:28 -05:00
|
|
|
DWORD dxwCore::StretchCounter(DWORD dwTimer)
|
|
|
|
{
|
|
|
|
TimeShift=GetHookInfo()->TimeShift;
|
2014-03-23 12:38:58 -04:00
|
|
|
dwTimer = (*pTimeShifter)(dwTimer, TimeShift);
|
2015-11-19 11:42:28 -05:00
|
|
|
return (dxw.TimeFreeze) ? 0 : dwTimer;
|
2013-11-17 11:38:28 -05:00
|
|
|
}
|
|
|
|
|
2014-04-01 12:38:40 -04:00
|
|
|
LARGE_INTEGER dxwCore::StretchCounter(LARGE_INTEGER dwTimer)
|
|
|
|
{
|
2014-01-03 11:38:52 -05:00
|
|
|
static int Reminder = 0;
|
|
|
|
LARGE_INTEGER ret;
|
2015-11-19 11:42:28 -05:00
|
|
|
LARGE_INTEGER zero = {0,0};
|
2014-04-01 12:38:40 -04:00
|
|
|
TimeShift=GetHookInfo()->TimeShift;
|
2014-01-03 11:38:52 -05:00
|
|
|
dwTimer.QuadPart += Reminder;
|
2014-03-23 12:38:58 -04:00
|
|
|
ret = (*pTimeShifter64)(dwTimer, TimeShift);
|
2014-01-03 11:38:52 -05:00
|
|
|
Reminder = (ret.QuadPart==0) ? dwTimer.LowPart : 0;
|
2015-11-19 11:42:28 -05:00
|
|
|
return (dxw.TimeFreeze) ? zero : ret;
|
2014-04-01 12:38:40 -04:00
|
|
|
}
|
|
|
|
|
2013-01-25 11:17:02 -05:00
|
|
|
void dxwCore::GetSystemTimeAsFileTime(LPFILETIME lpSystemTimeAsFileTime)
|
|
|
|
{
|
|
|
|
DWORD dwTick;
|
|
|
|
DWORD dwCurrentTick;
|
|
|
|
FILETIME CurrFileTime;
|
|
|
|
static DWORD dwStartTick=0;
|
|
|
|
static FILETIME StartFileTime;
|
|
|
|
|
|
|
|
if(dwStartTick==0) {
|
|
|
|
SYSTEMTIME StartingTime;
|
|
|
|
// first time through, initialize & return true time
|
|
|
|
dwStartTick = (*pGetTickCount)();
|
|
|
|
(*pGetSystemTime)(&StartingTime);
|
|
|
|
SystemTimeToFileTime(&StartingTime, &StartFileTime);
|
|
|
|
*lpSystemTimeAsFileTime = StartFileTime;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
dwCurrentTick=(*pGetTickCount)();
|
|
|
|
dwTick=(dwCurrentTick-dwStartTick);
|
|
|
|
TimeShift=GetHookInfo()->TimeShift;
|
2014-03-23 12:38:58 -04:00
|
|
|
dwTick = (*pTimeShifter)(dwTick, TimeShift);
|
2015-11-19 11:42:28 -05:00
|
|
|
if(dxw.TimeFreeze) dwTick=0;
|
2013-01-25 11:17:02 -05:00
|
|
|
// From MSDN: Contains a 64-bit value representing the number of
|
|
|
|
// 100-nanosecond intervals since January 1, 1601 (UTC).
|
|
|
|
// So, since 1mSec = 10.000 * 100nSec, you still have to multiply by 10.000.
|
|
|
|
CurrFileTime.dwHighDateTime = StartFileTime.dwHighDateTime; // wrong !!!!
|
|
|
|
CurrFileTime.dwLowDateTime = StartFileTime.dwLowDateTime + (10000 * dwTick); // wrong !!!!
|
|
|
|
*lpSystemTimeAsFileTime=CurrFileTime;
|
|
|
|
// reset to avoid time jumps on TimeShift changes...
|
|
|
|
StartFileTime = CurrFileTime;
|
|
|
|
dwStartTick = dwCurrentTick;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-19 11:16:54 -05:00
|
|
|
void dxwCore::GetSystemTime(LPSYSTEMTIME lpSystemTime)
|
|
|
|
{
|
|
|
|
DWORD dwTick;
|
|
|
|
DWORD dwCurrentTick;
|
|
|
|
FILETIME CurrFileTime;
|
|
|
|
static DWORD dwStartTick=0;
|
|
|
|
static FILETIME StartFileTime;
|
|
|
|
|
|
|
|
if(dwStartTick==0) {
|
|
|
|
SYSTEMTIME StartingTime;
|
|
|
|
// first time through, initialize & return true time
|
|
|
|
dwStartTick = (*pGetTickCount)();
|
|
|
|
(*pGetSystemTime)(&StartingTime);
|
|
|
|
SystemTimeToFileTime(&StartingTime, &StartFileTime);
|
|
|
|
*lpSystemTime = StartingTime;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
dwCurrentTick=(*pGetTickCount)();
|
|
|
|
dwTick=(dwCurrentTick-dwStartTick);
|
2013-01-25 11:17:02 -05:00
|
|
|
TimeShift=GetHookInfo()->TimeShift;
|
2014-03-23 12:38:58 -04:00
|
|
|
dwTick = (*pTimeShifter)(dwTick, TimeShift);
|
2015-11-22 11:42:31 -05:00
|
|
|
if(TimeFreeze) dwTick=0;
|
2013-01-19 11:16:54 -05:00
|
|
|
// From MSDN: Contains a 64-bit value representing the number of
|
|
|
|
// 100-nanosecond intervals since January 1, 1601 (UTC).
|
|
|
|
// So, since 1mSec = 10.000 * 100nSec, you still have to multiply by 10.000.
|
|
|
|
CurrFileTime.dwHighDateTime = StartFileTime.dwHighDateTime; // wrong !!!!
|
|
|
|
CurrFileTime.dwLowDateTime = StartFileTime.dwLowDateTime + (10000 * dwTick); // wrong !!!!
|
|
|
|
FileTimeToSystemTime(&CurrFileTime, lpSystemTime);
|
|
|
|
// reset to avoid time jumps on TimeShift changes...
|
|
|
|
StartFileTime = CurrFileTime;
|
|
|
|
dwStartTick = dwCurrentTick;
|
|
|
|
}
|
2013-01-22 11:17:01 -05:00
|
|
|
}
|
|
|
|
|
2013-03-12 12:38:32 -04:00
|
|
|
void dxwCore::ShowOverlay()
|
|
|
|
{
|
2014-10-08 12:39:38 -04:00
|
|
|
if (MustShowOverlay) {
|
|
|
|
RECT rect;
|
|
|
|
(*pGetClientRect)(hWnd, &rect);
|
|
|
|
this->ShowOverlay(GetDC(hWnd), rect.right, rect.bottom);
|
|
|
|
}
|
2013-03-12 12:38:32 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void dxwCore::ShowOverlay(LPDIRECTDRAWSURFACE lpdds)
|
|
|
|
{
|
2015-04-26 12:40:41 -04:00
|
|
|
typedef HRESULT (WINAPI *GetDC_Type) (LPDIRECTDRAWSURFACE, HDC FAR *);
|
|
|
|
typedef HRESULT (WINAPI *ReleaseDC_Type)(LPDIRECTDRAWSURFACE, HDC);
|
2016-06-04 12:45:32 -04:00
|
|
|
extern GetDC_Type pGetDCMethod();
|
|
|
|
extern ReleaseDC_Type pReleaseDCMethod();
|
2013-08-12 12:38:35 -04:00
|
|
|
if (MustShowOverlay) {
|
2014-10-08 12:39:38 -04:00
|
|
|
HDC hdc; // the working dc
|
|
|
|
int h, w;
|
2013-08-12 12:38:35 -04:00
|
|
|
if(!lpdds) return;
|
2016-06-04 12:45:32 -04:00
|
|
|
if (FAILED((*pGetDCMethod())(lpdds, &hdc))) return;
|
2014-10-08 12:39:38 -04:00
|
|
|
w = this->GetScreenWidth();
|
|
|
|
h = this->GetScreenHeight();
|
2014-08-10 12:39:50 -04:00
|
|
|
if(this->dwFlags4 & BILINEAR2XFILTER) {
|
2014-10-08 12:39:38 -04:00
|
|
|
w <<=1;
|
|
|
|
h <<=1;
|
|
|
|
}
|
|
|
|
this->ShowOverlay(hdc, w, h);
|
2016-06-04 12:45:32 -04:00
|
|
|
(*pReleaseDCMethod())(lpdds, hdc);
|
2013-08-12 12:38:35 -04:00
|
|
|
}
|
2013-03-12 12:38:32 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void dxwCore::ShowOverlay(HDC hdc)
|
|
|
|
{
|
2013-08-12 12:38:35 -04:00
|
|
|
if(!hdc) return;
|
2014-10-08 12:39:38 -04:00
|
|
|
RECT rect;
|
|
|
|
(*pGetClientRect)(hWnd, &rect);
|
2015-11-02 11:40:21 -05:00
|
|
|
this->ShowOverlay(hdc, rect.right, rect.bottom);
|
2014-10-08 12:39:38 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void dxwCore::ShowOverlay(HDC hdc, int w, int h)
|
|
|
|
{
|
|
|
|
if(!hdc) return;
|
|
|
|
if (dwFlags2 & SHOWFPSOVERLAY) ShowFPS(hdc, w, h);
|
|
|
|
if (dwFlags4 & SHOWTIMESTRETCH) ShowTimeStretching(hdc, w, h);
|
|
|
|
}
|
2013-11-28 11:38:31 -05:00
|
|
|
|
2014-05-20 12:39:14 -04:00
|
|
|
// nasty global to ensure that the corner is picked semi-random, but never overlapped
|
|
|
|
// between FPS and TimeStretch (and, as a side effect, never twice the same!)
|
|
|
|
static int LastCorner;
|
|
|
|
|
2014-10-08 12:39:38 -04:00
|
|
|
void dxwCore::ShowFPS(HDC xdc, int w, int h)
|
2013-01-25 11:17:02 -05:00
|
|
|
{
|
|
|
|
char sBuf[81];
|
|
|
|
static DWORD dwTimer = 0;
|
|
|
|
static int corner = 0;
|
|
|
|
static int x, y;
|
|
|
|
static DWORD color;
|
|
|
|
|
2014-06-22 12:39:24 -04:00
|
|
|
if((*pGetTickCount)()-dwTimer > 6000){
|
2013-01-25 11:17:02 -05:00
|
|
|
dwTimer = (*pGetTickCount)();
|
|
|
|
corner = dwTimer % 4;
|
2014-05-20 12:39:14 -04:00
|
|
|
if(corner==LastCorner) corner = (corner+1) % 4;
|
|
|
|
LastCorner = corner;
|
2013-01-25 11:17:02 -05:00
|
|
|
color=0xFF0000; // blue
|
|
|
|
switch (corner) {
|
|
|
|
case 0: x=10; y=10; break;
|
2014-10-08 12:39:38 -04:00
|
|
|
case 1: x=w-60; y=10; break;
|
|
|
|
case 2: x=w-60; y=h-20; break;
|
|
|
|
case 3: x=10; y=h-20; break;
|
2013-01-25 11:17:02 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SetTextColor(xdc,color);
|
|
|
|
SetBkMode(xdc, OPAQUE);
|
2013-05-16 12:19:15 -04:00
|
|
|
sprintf_s(sBuf, 80, "FPS: %d", GetHookInfo()->FPSCount);
|
2013-01-25 11:17:02 -05:00
|
|
|
TextOut(xdc, x, y, sBuf, strlen(sBuf));
|
|
|
|
}
|
|
|
|
|
2014-10-08 12:39:38 -04:00
|
|
|
void dxwCore::ShowTimeStretching(HDC xdc, int w, int h)
|
2013-01-22 11:17:01 -05:00
|
|
|
{
|
|
|
|
char sBuf[81];
|
|
|
|
static DWORD dwTimer = 0;
|
|
|
|
static int corner = 0;
|
|
|
|
static int x, y;
|
|
|
|
static DWORD color;
|
2013-11-28 11:38:31 -05:00
|
|
|
static int LastTimeShift = 1000; // any initial number different from -8 .. +8
|
2015-11-19 11:42:28 -05:00
|
|
|
static int LastTimeFreeze = 1000; // any initial number different from TRUE, FALSE
|
2013-01-22 11:17:01 -05:00
|
|
|
|
|
|
|
if((*pGetTickCount)()-dwTimer > 4000){
|
2015-11-19 11:42:28 -05:00
|
|
|
if((LastTimeShift==TimeShift) && (LastTimeFreeze==TimeFreeze)) return; // after a while, stop the show
|
2013-01-22 11:17:01 -05:00
|
|
|
dwTimer = (*pGetTickCount)();
|
2013-11-28 11:38:31 -05:00
|
|
|
LastTimeShift=TimeShift;
|
2013-01-22 11:17:01 -05:00
|
|
|
corner = dwTimer % 4;
|
2014-05-20 12:39:14 -04:00
|
|
|
if(corner==LastCorner) corner = (corner+1) % 4;
|
|
|
|
LastCorner = corner;
|
2013-11-28 11:38:31 -05:00
|
|
|
color=0x0000FF; // red
|
2013-01-22 11:17:01 -05:00
|
|
|
switch (corner) {
|
|
|
|
case 0: x=10; y=10; break;
|
2014-10-08 12:39:38 -04:00
|
|
|
case 1: x=w-60; y=10; break;
|
|
|
|
case 2: x=w-60; y=h-20; break;
|
|
|
|
case 3: x=10; y=h-20; break;
|
2013-01-22 11:17:01 -05:00
|
|
|
}
|
2013-11-28 11:38:31 -05:00
|
|
|
}
|
2013-01-22 11:17:01 -05:00
|
|
|
|
|
|
|
SetTextColor(xdc,color);
|
|
|
|
SetBkMode(xdc, OPAQUE);
|
2014-03-23 12:38:58 -04:00
|
|
|
sprintf_s(sBuf, 80, "t%s", dxw.GetTSCaption());
|
2013-01-22 11:17:01 -05:00
|
|
|
TextOut(xdc, x, y, sBuf, strlen(sBuf));
|
|
|
|
}
|
|
|
|
|
|
|
|
char *dxwCore::GetTSCaption(int shift)
|
|
|
|
{
|
2014-03-23 12:38:58 -04:00
|
|
|
static char *sTSCaptionCoarse[17]={
|
2013-01-22 11:17:01 -05:00
|
|
|
"x16","x12","x8","x6",
|
|
|
|
"x4","x3","x2","x1.5",
|
|
|
|
"x1",
|
|
|
|
":1.5",":2",":3",":4",
|
|
|
|
":6",":8",":12",":16"};
|
2014-03-23 12:38:58 -04:00
|
|
|
static char *sTSCaptionFine[17]={
|
|
|
|
"x2.14","x1.95","x1.77","x1.61",
|
|
|
|
"x1.46","x1.33","x1.21","x1.10",
|
|
|
|
"x1.00",
|
|
|
|
":1.10",":1.21",":1.33",":1.46",
|
|
|
|
":1.61",":1.77",":1.95",":2.14"};
|
2015-11-19 11:42:28 -05:00
|
|
|
if(TimeFreeze) return "x0";
|
2013-09-22 12:38:19 -04:00
|
|
|
if (shift<(-8) || shift>(+8)) return "???";
|
2014-03-23 12:38:58 -04:00
|
|
|
shift += 8;
|
|
|
|
return (dxw.dwFlags4 & FINETIMING) ? sTSCaptionFine[shift] : sTSCaptionCoarse[shift];
|
2013-01-22 11:17:01 -05:00
|
|
|
}
|
2013-11-28 11:38:31 -05:00
|
|
|
|
2013-01-22 11:17:01 -05:00
|
|
|
char *dxwCore::GetTSCaption(void)
|
|
|
|
{
|
|
|
|
return GetTSCaption(TimeShift);
|
2013-12-02 11:17:07 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void dxwCore::ShowBanner(HWND hwnd)
|
|
|
|
{
|
|
|
|
static BOOL JustOnce=FALSE;
|
|
|
|
extern HMODULE hInst;
|
|
|
|
BITMAP bm;
|
|
|
|
HDC hClientDC;
|
|
|
|
HBITMAP g_hbmBall;
|
|
|
|
RECT client;
|
2013-08-30 12:38:14 -04:00
|
|
|
RECT win;
|
|
|
|
POINT PrevViewPort;
|
2015-01-31 11:40:19 -05:00
|
|
|
int StretchMode;
|
2013-12-02 11:17:07 -05:00
|
|
|
|
2016-07-13 12:46:31 -04:00
|
|
|
hClientDC=(*pGDIGetDC)(hwnd);
|
|
|
|
(*pGetClientRect)(hwnd, &client);
|
2016-06-11 12:48:04 -04:00
|
|
|
//(*pInvalidateRect)((*pGetDesktopWindow)(), NULL, FALSE); // invalidate full desktop, no erase.
|
|
|
|
(*pInvalidateRect)(0, NULL, FALSE); // invalidate full desktop, no erase.
|
2016-07-13 12:46:31 -04:00
|
|
|
(*pGDIBitBlt)(hClientDC, 0, 0, client.right, client.bottom, NULL, 0, 0, BLACKNESS);
|
|
|
|
|
2016-02-09 11:47:00 -05:00
|
|
|
if(JustOnce || (dwFlags2 & NOBANNER)) return;
|
|
|
|
JustOnce=TRUE;
|
|
|
|
|
2013-12-02 11:17:07 -05:00
|
|
|
g_hbmBall = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BANNER));
|
|
|
|
HDC hdcMem = CreateCompatibleDC(hClientDC);
|
2017-01-27 11:49:51 -05:00
|
|
|
HBITMAP hbmOld = (HBITMAP)(*pSelectObject)(hdcMem, g_hbmBall);
|
2013-12-02 11:17:07 -05:00
|
|
|
GetObject(g_hbmBall, sizeof(bm), &bm);
|
2013-08-30 12:38:14 -04:00
|
|
|
|
|
|
|
(*pGetWindowRect)(hwnd, &win);
|
2013-12-22 11:38:36 -05:00
|
|
|
OutTraceDW("ShowBanner: hwnd=%x win=(%d,%d)-(%d,%d) banner size=(%dx%d)\n",
|
2013-08-30 12:38:14 -04:00
|
|
|
hwnd, win.left, win.top, win.right, win.bottom, bm.bmWidth, bm.bmHeight);
|
|
|
|
|
|
|
|
//if(!pSetViewportOrgEx) pSetViewportOrgEx=SetViewportOrgEx;
|
|
|
|
(*pSetViewportOrgEx)(hClientDC, 0, 0, &PrevViewPort);
|
2015-01-31 11:40:19 -05:00
|
|
|
StretchMode=GetStretchBltMode(hClientDC);
|
|
|
|
SetStretchBltMode(hClientDC, HALFTONE);
|
2013-12-02 11:17:07 -05:00
|
|
|
for (int i=1; i<=16; i++){
|
|
|
|
int w, h;
|
|
|
|
w=(bm.bmWidth*i)/8;
|
|
|
|
h=(bm.bmHeight*i)/8;
|
2013-08-30 12:38:14 -04:00
|
|
|
(*pGDIStretchBlt)(hClientDC, (client.right-w)/2, (client.bottom-h)/2, w, h, hdcMem, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
|
2013-12-02 11:17:07 -05:00
|
|
|
Sleep(40);
|
|
|
|
}
|
|
|
|
for (int i=16; i>=8; i--){
|
|
|
|
int w, h;
|
|
|
|
w=(bm.bmWidth*i)/8;
|
|
|
|
h=(bm.bmHeight*i)/8;
|
2013-08-30 12:38:14 -04:00
|
|
|
(*pGDIBitBlt)(hClientDC, 0, 0, client.right, client.bottom, NULL, 0, 0, BLACKNESS);
|
|
|
|
(*pGDIStretchBlt)(hClientDC, (client.right-w)/2, (client.bottom-h)/2, w, h, hdcMem, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
|
2013-12-02 11:17:07 -05:00
|
|
|
Sleep(40);
|
|
|
|
}
|
2015-01-31 11:40:19 -05:00
|
|
|
SetStretchBltMode(hClientDC, StretchMode);
|
2013-08-30 12:38:14 -04:00
|
|
|
(*pSetViewportOrgEx)(hClientDC, PrevViewPort.x, PrevViewPort.y, NULL);
|
2017-01-27 11:49:51 -05:00
|
|
|
(*pSelectObject)(hdcMem, hbmOld);
|
2013-12-02 11:17:07 -05:00
|
|
|
DeleteDC(hdcMem);
|
2016-07-13 12:46:31 -04:00
|
|
|
(*pGDIReleaseDC)(hwnd, hClientDC);
|
2013-12-02 11:17:07 -05:00
|
|
|
Sleep(200);
|
2013-02-06 11:19:16 -05:00
|
|
|
}
|
|
|
|
|
2016-10-21 12:47:48 -04:00
|
|
|
void dxwCore::PushDLL(char *lpName, int idx)
|
|
|
|
{
|
|
|
|
SysNames[idx] = lpName; // add entry
|
|
|
|
}
|
|
|
|
|
2013-02-06 11:19:16 -05:00
|
|
|
int dxwCore::GetDLLIndex(char *lpFileName)
|
|
|
|
{
|
|
|
|
int idx;
|
|
|
|
char *lpName, *lpNext;
|
2015-06-22 12:40:59 -04:00
|
|
|
|
2013-02-06 11:19:16 -05:00
|
|
|
lpName=lpFileName;
|
|
|
|
while (lpNext=strchr(lpName,'\\')) lpName=lpNext+1;
|
|
|
|
for(idx=0; SysNames[idx]; idx++){
|
|
|
|
char SysNameExt[81];
|
|
|
|
strcpy(SysNameExt, SysNames[idx]);
|
|
|
|
strcat(SysNameExt, ".dll");
|
|
|
|
if(
|
|
|
|
(!lstrcmpi(lpName,SysNames[idx])) ||
|
|
|
|
(!lstrcmpi(lpName,SysNameExt))
|
|
|
|
){
|
2013-12-22 11:38:36 -05:00
|
|
|
OutTraceDW("Registered DLL FileName=%s\n", lpFileName);
|
2013-02-06 11:19:16 -05:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!SysNames[idx]) return -1;
|
|
|
|
return idx;
|
2013-06-29 12:38:04 -04:00
|
|
|
}
|
|
|
|
|
2016-07-30 12:46:40 -04:00
|
|
|
DWORD dxwCore::FixWinStyle(DWORD dwStyle)
|
|
|
|
{
|
|
|
|
switch(dxw.Coordinates){
|
|
|
|
case DXW_SET_COORDINATES:
|
|
|
|
case DXW_DESKTOP_CENTER:
|
|
|
|
if(dxw.dwFlags2 & MODALSTYLE){
|
|
|
|
dwStyle &= ~(WS_BORDER | WS_CAPTION | WS_DLGFRAME | WS_SYSMENU | WS_THICKFRAME);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
dwStyle = WS_OVERLAPPEDWINDOW;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case DXW_DESKTOP_WORKAREA:
|
|
|
|
case DXW_DESKTOP_FULL:
|
|
|
|
dwStyle = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return dwStyle;
|
|
|
|
}
|
|
|
|
|
|
|
|
DWORD dxwCore::FixWinExStyle(DWORD dwExStyle)
|
|
|
|
{
|
|
|
|
switch(dxw.Coordinates){
|
|
|
|
case DXW_SET_COORDINATES:
|
|
|
|
case DXW_DESKTOP_CENTER:
|
|
|
|
if(dxw.dwFlags2 & MODALSTYLE){
|
|
|
|
dwExStyle &= ~(WS_EX_CLIENTEDGE | WS_EX_DLGMODALFRAME | WS_EX_STATICEDGE | WS_EX_WINDOWEDGE);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
dwExStyle &= ~(WS_EX_CLIENTEDGE | WS_EX_DLGMODALFRAME | WS_EX_STATICEDGE | WS_EX_WINDOWEDGE);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case DXW_DESKTOP_WORKAREA:
|
|
|
|
case DXW_DESKTOP_FULL:
|
|
|
|
dwExStyle = 0;
|
|
|
|
break;
|
|
|
|
}
|
2017-01-30 11:49:56 -05:00
|
|
|
|
2016-07-30 12:46:40 -04:00
|
|
|
return dwExStyle;
|
|
|
|
}
|
|
|
|
|
2014-04-01 12:38:40 -04:00
|
|
|
void dxwCore::FixWindowFrame(HWND hwnd)
|
|
|
|
{
|
2016-07-30 12:46:40 -04:00
|
|
|
LONG nStyle, nExStyle;
|
|
|
|
|
|
|
|
OutTraceDW("FixWindowFrame: hwnd=%x foreground=%x\n", hwnd, GetForegroundWindow());
|
2014-04-01 12:38:40 -04:00
|
|
|
|
2016-07-30 12:46:40 -04:00
|
|
|
nStyle=(*pGetWindowLong)(hwnd, GWL_STYLE);
|
2017-01-22 11:49:46 -05:00
|
|
|
// beware: 0 is a valid return code!
|
|
|
|
//if (!nStyle){
|
|
|
|
// OutTraceE("FixWindowFrame: GetWindowLong ERROR %d at %d\n",GetLastError(),__LINE__);
|
|
|
|
// return;
|
|
|
|
//}
|
2014-04-01 12:38:40 -04:00
|
|
|
|
2016-07-30 12:46:40 -04:00
|
|
|
nExStyle=(*pGetWindowLong)(hwnd, GWL_EXSTYLE);
|
2017-01-22 11:49:46 -05:00
|
|
|
// beware: 0 is a valid return code!
|
|
|
|
//if (!nExStyle){
|
|
|
|
// OutTraceE("FixWindowFrame: GetWindowLong ERROR %d at %d\n",GetLastError(),__LINE__);
|
|
|
|
// return;
|
|
|
|
//}
|
2014-04-01 12:38:40 -04:00
|
|
|
|
2016-07-30 12:46:40 -04:00
|
|
|
OutTraceDW("FixWindowFrame: style=%x(%s) exstyle=%x(%s)\n",
|
|
|
|
nStyle, ExplainStyle(nStyle),
|
|
|
|
nExStyle, ExplainExStyle(nExStyle));
|
2014-04-01 12:38:40 -04:00
|
|
|
|
|
|
|
// fix style
|
2016-07-30 12:46:40 -04:00
|
|
|
if (!(*pSetWindowLongA)(hwnd, GWL_STYLE, FixWinStyle(nStyle))){
|
2014-04-01 12:38:40 -04:00
|
|
|
OutTraceE("FixWindowFrame: SetWindowLong ERROR %d at %d\n",GetLastError(),__LINE__);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// fix exstyle
|
2016-07-30 12:46:40 -04:00
|
|
|
if (!(*pSetWindowLongA)(hwnd, GWL_EXSTYLE, FixWinExStyle(nExStyle))){
|
2014-04-01 12:38:40 -04:00
|
|
|
OutTraceE("FixWindowFrame: SetWindowLong ERROR %d at %d\n",GetLastError(),__LINE__);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ShowWindow retcode means in no way an error code! Better ignore it.
|
|
|
|
(*pShowWindow)(hwnd, SW_RESTORE);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-06-29 12:38:04 -04:00
|
|
|
void dxwCore::FixStyle(char *ApiName, HWND hwnd, WPARAM wParam, LPARAM lParam)
|
|
|
|
{
|
|
|
|
LPSTYLESTRUCT lpSS;
|
|
|
|
lpSS = (LPSTYLESTRUCT) lParam;
|
|
|
|
|
|
|
|
switch (wParam) {
|
|
|
|
case GWL_STYLE:
|
2013-12-22 11:38:36 -05:00
|
|
|
OutTraceDW("%s: new Style=%x(%s)\n",
|
2013-06-29 12:38:04 -04:00
|
|
|
ApiName, lpSS->styleNew, ExplainStyle(lpSS->styleNew));
|
|
|
|
if (dxw.dwFlags1 & FIXWINFRAME){ // set canonical style
|
2017-03-25 09:59:46 -04:00
|
|
|
lpSS->styleNew= WS_OVERLAPPEDWINDOW;
|
|
|
|
}
|
|
|
|
if (dxw.dwFlags9 & FIXTHINFRAME){ // set canonical style with thin border
|
|
|
|
lpSS->styleNew= WS_OVERLAPPEDTHIN;
|
2013-06-29 12:38:04 -04:00
|
|
|
}
|
|
|
|
if (dxw.dwFlags1 & LOCKWINSTYLE){ // set to current value
|
2016-04-17 12:45:41 -04:00
|
|
|
lpSS->styleNew= (*pGetWindowLong)(hwnd, GWL_STYLE);
|
2013-06-29 12:38:04 -04:00
|
|
|
}
|
|
|
|
if (dxw.dwFlags1 & PREVENTMAXIMIZE){ // disable maximize settings
|
|
|
|
if (lpSS->styleNew & WS_MAXIMIZE){
|
2013-12-22 11:38:36 -05:00
|
|
|
OutTraceDW("%s: prevent maximize style\n", ApiName);
|
2013-06-29 12:38:04 -04:00
|
|
|
lpSS->styleNew &= ~WS_MAXIMIZE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case GWL_EXSTYLE:
|
2013-12-22 11:38:36 -05:00
|
|
|
OutTraceDW("%s: new ExStyle=%x(%s)\n",
|
2013-06-29 12:38:04 -04:00
|
|
|
ApiName, lpSS->styleNew, ExplainExStyle(lpSS->styleNew));
|
|
|
|
if (dxw.dwFlags1 & FIXWINFRAME){ // set canonical style
|
|
|
|
lpSS->styleNew= 0;
|
|
|
|
}
|
|
|
|
if (dxw.dwFlags1 & LOCKWINSTYLE){ // set to current value
|
2016-04-17 12:45:41 -04:00
|
|
|
lpSS->styleNew= (*pGetWindowLong)(hwnd, GWL_EXSTYLE);
|
2013-06-29 12:38:04 -04:00
|
|
|
}
|
2016-11-26 11:48:21 -05:00
|
|
|
if ((dxw.dwFlags5 & UNLOCKZORDER) && (hwnd==hWnd)){ // disable maximize settings
|
2013-06-29 12:38:04 -04:00
|
|
|
if (lpSS->styleNew & WS_EX_TOPMOST){
|
2013-12-22 11:38:36 -05:00
|
|
|
OutTraceDW("%s: prevent EXSTYLE topmost style\n", ApiName);
|
2013-06-29 12:38:04 -04:00
|
|
|
lpSS->styleNew &= ~WS_EX_TOPMOST;
|
|
|
|
}
|
2016-11-26 11:48:21 -05:00
|
|
|
}
|
2013-06-29 12:38:04 -04:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2013-08-30 12:38:14 -04:00
|
|
|
|
2014-04-01 12:38:40 -04:00
|
|
|
void dxwCore::PushTimer(UINT uTimerId, UINT uDelay, UINT uResolution, LPTIMECALLBACK lpTimeProc, DWORD_PTR dwUser, UINT fuEvent)
|
|
|
|
{
|
|
|
|
// save current timer
|
2014-11-01 12:38:41 -04:00
|
|
|
TimerEvent.dwTimerType = TIMER_TYPE_WINMM;
|
|
|
|
TimerEvent.t.uTimerId = uTimerId;
|
|
|
|
TimerEvent.t.uDelay = uDelay;
|
|
|
|
TimerEvent.t.uResolution = uResolution;
|
|
|
|
TimerEvent.t.lpTimeProc = lpTimeProc;
|
|
|
|
TimerEvent.t.dwUser = dwUser;
|
|
|
|
TimerEvent.t.fuEvent = fuEvent;
|
|
|
|
}
|
|
|
|
|
|
|
|
void dxwCore::PushTimer(HWND hWnd, UINT_PTR nIDEvent, UINT uElapse, TIMERPROC lpTimerFunc)
|
|
|
|
{
|
|
|
|
// save current timer
|
|
|
|
TimerEvent.dwTimerType = TIMER_TYPE_USER32;
|
|
|
|
TimerEvent.t.hWnd = hWnd;
|
|
|
|
TimerEvent.t.nIDEvent = nIDEvent;
|
|
|
|
TimerEvent.t.uElapse = uElapse;
|
|
|
|
TimerEvent.t.lpTimerFunc = lpTimerFunc;
|
2014-04-01 12:38:40 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void dxwCore::PopTimer(UINT uTimerId)
|
|
|
|
{
|
2014-11-01 12:38:41 -04:00
|
|
|
// clear current timer
|
|
|
|
if(TimerEvent.dwTimerType != TIMER_TYPE_WINMM) {
|
|
|
|
// this should never happen, unless there are more than 1 timer!
|
|
|
|
char msg[256];
|
|
|
|
sprintf(msg,"PopTimer: TimerType=%x last=%x\n", TIMER_TYPE_WINMM, TimerEvent.dwTimerType);
|
2014-05-14 12:39:12 -04:00
|
|
|
//MessageBox(0, msg, "PopTimer", MB_OK | MB_ICONEXCLAMATION);
|
|
|
|
OutTraceE(msg);
|
2014-11-01 12:38:41 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if(uTimerId != TimerEvent.t.uTimerId){
|
|
|
|
// this should never happen, unless there are more than 1 timer!
|
|
|
|
char msg[256];
|
|
|
|
sprintf(msg,"PopTimer: TimerId=%x last=%x\n", uTimerId, TimerEvent.t.uTimerId);
|
2014-05-14 12:39:12 -04:00
|
|
|
//MessageBox(0, msg, "PopTimer", MB_OK | MB_ICONEXCLAMATION);
|
|
|
|
OutTraceE(msg);
|
2014-11-01 12:38:41 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
TimerEvent.dwTimerType = TIMER_TYPE_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void dxwCore::PopTimer(HWND hWnd, UINT_PTR nIDEvent)
|
|
|
|
{
|
|
|
|
// clear current timer
|
|
|
|
if(TimerEvent.dwTimerType != TIMER_TYPE_USER32) {
|
2014-04-01 12:38:40 -04:00
|
|
|
// this should never happen, unless there are more than 1 timer!
|
|
|
|
char msg[256];
|
2014-11-01 12:38:41 -04:00
|
|
|
sprintf(msg,"PopTimer: TimerType=%x last=%x\n", TIMER_TYPE_WINMM, TimerEvent.dwTimerType);
|
2014-05-14 12:39:12 -04:00
|
|
|
//MessageBox(0, msg, "PopTimer", MB_OK | MB_ICONEXCLAMATION);
|
|
|
|
OutTraceE(msg);
|
2014-04-01 12:38:40 -04:00
|
|
|
return;
|
|
|
|
}
|
2014-11-01 12:38:41 -04:00
|
|
|
if(nIDEvent != TimerEvent.t.nIDEvent){
|
|
|
|
// this should never happen, unless there are more than 1 timer!
|
|
|
|
char msg[256];
|
|
|
|
sprintf(msg,"PopTimer: TimerId=%x last=%x\n", nIDEvent, TimerEvent.t.nIDEvent);
|
2014-05-14 12:39:12 -04:00
|
|
|
//MessageBox(0, msg, "PopTimer", MB_OK | MB_ICONEXCLAMATION);
|
|
|
|
OutTraceE(msg);
|
2014-11-01 12:38:41 -04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
TimerEvent.dwTimerType = TIMER_TYPE_NONE;
|
2014-04-01 12:38:40 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void dxwCore::RenewTimers()
|
|
|
|
{
|
2014-02-19 11:38:50 -05:00
|
|
|
OutTraceE("DXWND: RenewTimers type=%x\n", TimerEvent.dwTimerType);
|
2014-11-01 12:38:41 -04:00
|
|
|
switch(TimerEvent.dwTimerType){
|
|
|
|
case TIMER_TYPE_NONE:
|
2014-02-19 11:38:50 -05:00
|
|
|
OutTraceDW("DXWND: RenewTimers type=NONE\n");
|
2014-11-01 12:38:41 -04:00
|
|
|
break;
|
|
|
|
case TIMER_TYPE_USER32:
|
|
|
|
if(pSetTimer && pKillTimer){
|
|
|
|
UINT uElapse;
|
|
|
|
UINT_PTR res;
|
2014-02-19 11:38:50 -05:00
|
|
|
res=(*pKillTimer)(TimerEvent.t.hWnd, TimerEvent.t.nIDEvent);
|
|
|
|
if(!res) OutTraceE("DXWND: KillTimer ERROR hWnd=%x IDEvent=%x err=%d\n", TimerEvent.t.hWnd, TimerEvent.t.nIDEvent, GetLastError());
|
2014-11-01 12:38:41 -04:00
|
|
|
uElapse = dxw.StretchTime(TimerEvent.t.uElapse);
|
|
|
|
res=(*pSetTimer)(TimerEvent.t.hWnd, TimerEvent.t.nIDEvent, uElapse, TimerEvent.t.lpTimerFunc);
|
|
|
|
TimerEvent.t.nIDEvent = res;
|
2014-02-19 11:38:50 -05:00
|
|
|
if(res)
|
2014-11-01 12:38:41 -04:00
|
|
|
OutTraceDW("DXWND: RenewTimers type=USER32 Elsapse=%d IDEvent=%x\n", uElapse, res);
|
2014-02-19 11:38:50 -05:00
|
|
|
else
|
|
|
|
OutTraceE("DXWND: SetTimer ERROR hWnd=%x Elapse=%d TimerFunc=%x err=%d\n", TimerEvent.t.hWnd, uElapse, TimerEvent.t.lpTimerFunc, GetLastError());
|
2014-11-01 12:38:41 -04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case TIMER_TYPE_WINMM:
|
|
|
|
if(ptimeKillEvent && ptimeSetEvent){
|
|
|
|
UINT NewDelay;
|
|
|
|
MMRESULT res;
|
|
|
|
(*ptimeKillEvent)(TimerEvent.t.uTimerId);
|
|
|
|
NewDelay = dxw.StretchTime(TimerEvent.t.uDelay);
|
|
|
|
res=(*ptimeSetEvent)(NewDelay, TimerEvent.t.uResolution, TimerEvent.t.lpTimeProc, TimerEvent.t.dwUser, TimerEvent.t.fuEvent);
|
|
|
|
TimerEvent.t.uTimerId = res;
|
|
|
|
OutTraceDW("DXWND: RenewTimers type=WINMM Delay=%d TimerId=%x\n", NewDelay, res);
|
|
|
|
}
|
|
|
|
break;
|
2014-02-19 11:38:50 -05:00
|
|
|
default:
|
|
|
|
OutTraceE("DXWND: RenewTimers type=%x(UNKNOWN)\n", TimerEvent.dwTimerType);
|
|
|
|
break;
|
2014-04-01 12:38:40 -04:00
|
|
|
}
|
2013-08-30 12:38:14 -04:00
|
|
|
}
|
2014-01-19 11:38:43 -05:00
|
|
|
|
2014-02-19 11:38:50 -05:00
|
|
|
LARGE_INTEGER dxwCore::StretchLargeCounter(LARGE_INTEGER CurrentInCount)
|
|
|
|
{
|
|
|
|
LARGE_INTEGER CurrentOutPerfCount;
|
|
|
|
static LARGE_INTEGER LastInPerfCount;
|
|
|
|
static LARGE_INTEGER LastOutPerfCount;
|
|
|
|
static BOOL FirstTime = TRUE;
|
|
|
|
LARGE_INTEGER ElapsedCount;
|
|
|
|
|
|
|
|
if(FirstTime){
|
|
|
|
// first time through, initialize both inner and output per counters with real values
|
|
|
|
LastInPerfCount.QuadPart = CurrentInCount.QuadPart;
|
|
|
|
LastOutPerfCount.QuadPart = CurrentInCount.QuadPart;
|
|
|
|
FirstTime=FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
ElapsedCount.QuadPart = CurrentInCount.QuadPart - LastInPerfCount.QuadPart;
|
|
|
|
ElapsedCount = dxw.StretchCounter(ElapsedCount);
|
|
|
|
CurrentOutPerfCount.QuadPart = LastOutPerfCount.QuadPart + ElapsedCount.QuadPart;
|
|
|
|
LastInPerfCount = CurrentInCount;
|
|
|
|
LastOutPerfCount = CurrentOutPerfCount;
|
|
|
|
|
|
|
|
OutTraceB("dxw::StretchCounter: Count=[%x-%x]\n", CurrentOutPerfCount.HighPart, CurrentOutPerfCount.LowPart);
|
|
|
|
return CurrentOutPerfCount;
|
|
|
|
}
|
|
|
|
|
2014-01-19 11:38:43 -05:00
|
|
|
BOOL dxwCore::CheckScreenResolution(unsigned int w, unsigned int h)
|
|
|
|
{
|
|
|
|
#define HUGE 100000
|
|
|
|
if(dxw.dwFlags4 & LIMITSCREENRES){
|
|
|
|
DWORD maxw, maxh;
|
2014-10-30 12:39:54 -04:00
|
|
|
maxw=HUGE; maxh=HUGE; // v2.02.96
|
2014-01-19 11:38:43 -05:00
|
|
|
switch(MaxScreenRes){
|
|
|
|
case DXW_NO_LIMIT: maxw=HUGE; maxh=HUGE; break;
|
|
|
|
case DXW_LIMIT_320x200: maxw=320; maxh=200; break;
|
|
|
|
case DXW_LIMIT_640x480: maxw=640; maxh=480; break;
|
|
|
|
case DXW_LIMIT_800x600: maxw=800; maxh=600; break;
|
|
|
|
case DXW_LIMIT_1024x768: maxw=1024; maxh=768; break;
|
|
|
|
case DXW_LIMIT_1280x960: maxw=1280; maxh=960; break;
|
2016-09-19 12:47:15 -04:00
|
|
|
case DXW_LIMIT_1280x1024: maxw=1280; maxh=1024; break;
|
2014-01-19 11:38:43 -05:00
|
|
|
}
|
|
|
|
if((w > maxw) || (h > maxh)) return FALSE;
|
|
|
|
}
|
2016-05-10 12:47:31 -04:00
|
|
|
|
|
|
|
if(dxw.dwFlags7 & MAXIMUMRES){
|
|
|
|
if(((long)w > dxw.iMaxW) || ((long)h > dxw.iMaxH)) return FALSE;
|
|
|
|
}
|
|
|
|
|
2014-01-19 11:38:43 -05:00
|
|
|
return TRUE;
|
|
|
|
}
|
2014-05-14 12:39:12 -04:00
|
|
|
|
|
|
|
UINT VKeyConfig[DXVK_SIZE];
|
|
|
|
|
2014-05-20 12:39:14 -04:00
|
|
|
static char *VKeyLabels[DXVK_SIZE]={
|
|
|
|
"none",
|
|
|
|
"cliptoggle",
|
|
|
|
"refresh",
|
|
|
|
"logtoggle",
|
|
|
|
"plocktoggle",
|
|
|
|
"fpstoggle",
|
|
|
|
"timefast",
|
|
|
|
"timeslow",
|
|
|
|
"timetoggle",
|
2015-11-03 11:40:28 -05:00
|
|
|
"altf4",
|
2015-10-21 12:42:12 -04:00
|
|
|
"printscreen",
|
2015-11-19 11:42:28 -05:00
|
|
|
"corner",
|
2016-12-04 11:45:35 -05:00
|
|
|
"freezetime",
|
|
|
|
"fullscreen",
|
|
|
|
"workarea",
|
|
|
|
"desktop",
|
2014-05-20 12:39:14 -04:00
|
|
|
};
|
2014-05-14 12:39:12 -04:00
|
|
|
|
2014-05-20 12:39:14 -04:00
|
|
|
void dxwCore::MapKeysInit()
|
2014-05-14 12:39:12 -04:00
|
|
|
{
|
|
|
|
char InitPath[MAX_PATH];
|
|
|
|
char *p;
|
|
|
|
DWORD dwAttrib;
|
2014-05-20 12:39:14 -04:00
|
|
|
int KeyIdx;
|
2014-05-14 12:39:12 -04:00
|
|
|
dwAttrib = GetFileAttributes("dxwnd.dll");
|
|
|
|
if (dwAttrib != INVALID_FILE_ATTRIBUTES && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY)) return;
|
|
|
|
GetModuleFileName(GetModuleHandle("dxwnd"), InitPath, MAX_PATH);
|
|
|
|
p=&InitPath[strlen(InitPath)-strlen("dxwnd.dll")];
|
|
|
|
strcpy(p, "dxwnd.ini");
|
|
|
|
VKeyConfig[DXVK_NONE]=DXVK_NONE;
|
2014-05-20 12:39:14 -04:00
|
|
|
for(KeyIdx=1; KeyIdx<DXVK_SIZE; KeyIdx++){
|
|
|
|
VKeyConfig[KeyIdx]=GetPrivateProfileInt("keymapping", VKeyLabels[KeyIdx], KeyIdx==DXVK_ALTF4 ? 0x73 : 0x00, InitPath);
|
|
|
|
OutTrace("keymapping[%d](%s)=%x\n", KeyIdx, VKeyLabels[KeyIdx], VKeyConfig[KeyIdx]);
|
|
|
|
}
|
2014-05-14 12:39:12 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
UINT dxwCore::MapKeysConfig(UINT message, LPARAM lparam, WPARAM wparam)
|
|
|
|
{
|
|
|
|
if(message!=WM_SYSKEYDOWN) return DXVK_NONE;
|
|
|
|
for(int idx=1; idx<DXVK_SIZE; idx++)
|
|
|
|
if(VKeyConfig[idx]==wparam) {
|
2016-12-04 11:45:35 -05:00
|
|
|
OutTrace("keymapping GOT=0x%02X\n", idx);
|
2014-05-14 12:39:12 -04:00
|
|
|
return idx;
|
|
|
|
}
|
|
|
|
return DXVK_NONE;
|
|
|
|
}
|
2015-11-19 11:42:28 -05:00
|
|
|
|
|
|
|
void dxwCore::ToggleFreezedTime()
|
|
|
|
{
|
|
|
|
static DWORD dwLastTime = 0;
|
2015-11-22 11:42:31 -05:00
|
|
|
if(((*pGetTickCount)() - dwLastTime) < 1000) return;
|
2015-11-19 11:42:28 -05:00
|
|
|
TimeFreeze = !TimeFreeze;
|
|
|
|
dwLastTime = (*pGetTickCount)();
|
|
|
|
OutTraceDW("DxWnd: time is %s\n", dxw.TimeFreeze ? "freezed" : "unfreezed");
|
2016-09-29 12:47:27 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void dxwCore::MessagePump()
|
|
|
|
{
|
|
|
|
MSG msg;
|
|
|
|
while(PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)){
|
|
|
|
OutTraceW("MESSAGEPUMP: msg=%x l-wParam=(%x,%x)\n", msg.message, msg.lParam, msg.wParam);
|
|
|
|
if((msg.message >= WM_KEYFIRST) && (msg.message <= WM_KEYLAST)) break; // do not consume keyboard inputs
|
|
|
|
if((msg.message >= WM_MOUSEFIRST) && (msg.message <= WM_MOUSELAST)) break; // do not consume mouse inputs
|
|
|
|
PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
|
|
|
|
TranslateMessage(&msg);
|
|
|
|
DispatchMessage(&msg);
|
|
|
|
}
|
|
|
|
}
|
2017-01-15 11:49:23 -05:00
|
|
|
|
|
|
|
void dxwCore::Mark(HDC hdc, BOOL scale, COLORREF color, int x, int y, int cx, int cy)
|
|
|
|
{
|
|
|
|
RECT frame;
|
|
|
|
HBRUSH brush = CreateSolidBrush(color);
|
|
|
|
frame.left = x; frame.top = y;
|
|
|
|
frame.right = x+cx; frame.bottom = y+cy;
|
|
|
|
if(scale) dxw.MapClient(&frame);
|
|
|
|
(*pFrameRect)(hdc, &frame, brush);
|
|
|
|
DeleteObject(brush);
|
|
|
|
}
|
|
|
|
|
|
|
|
void dxwCore::Mark(HDC hdc, BOOL scale, COLORREF color, RECT frame)
|
|
|
|
{
|
|
|
|
HBRUSH brush = CreateSolidBrush(color);
|
|
|
|
if(scale) dxw.MapClient(&frame);
|
|
|
|
(*pFrameRect)(hdc, &frame, brush);
|
|
|
|
DeleteObject(brush);
|
|
|
|
}
|