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-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-01-19 11:16:54 -05:00
|
|
|
lpDDSPrimHDC = NULL;
|
|
|
|
//IsWithinDDraw = FALSE;
|
|
|
|
IsGDIPalette = FALSE;
|
|
|
|
|
|
|
|
memset(PrimSurfaces, 0, sizeof(PrimSurfaces));
|
2013-08-01 12:16:53 -04:00
|
|
|
|
|
|
|
// preserved syslibs pointers
|
|
|
|
pClientToScreen=ClientToScreen;
|
|
|
|
pClipCursor=ClipCursor;
|
|
|
|
pGetClientRect=GetClientRect;
|
|
|
|
pGetCursorPos=GetCursorPos;
|
|
|
|
pInvalidateRect=InvalidateRect;
|
|
|
|
pScreenToClient=ScreenToClient;
|
2012-12-24 10:20:23 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
dxwCore::~dxwCore()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2013-06-01 12:16:52 -04:00
|
|
|
void dxwCore::InitTarget(TARGETMAP *target)
|
|
|
|
{
|
|
|
|
dwFlags1 = target->flags;
|
|
|
|
dwFlags2 = target->flags2;
|
|
|
|
dwTFlags = target->tflags;
|
|
|
|
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;
|
|
|
|
if(dwTargetDDVersion<0) dwTargetDDVersion=0;
|
|
|
|
if(dwTargetDDVersion>10) dwTargetDDVersion=10;
|
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;
|
2013-01-19 11:16:54 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ------------------------------------------------------------------ */
|
|
|
|
// Primary surfaces auxiliary functions
|
|
|
|
/* ------------------------------------------------------------------ */
|
|
|
|
|
|
|
|
void dxwCore::MarkPrimarySurface(LPDIRECTDRAWSURFACE ps)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
// OutTraceD("PRIMARYSURFACE add %x\n",ps);
|
|
|
|
for (i=0;i<DDSQLEN;i++) {
|
|
|
|
if (PrimSurfaces[i]==(DWORD)ps) return; // if already there ....
|
|
|
|
if (PrimSurfaces[i]==(DWORD)0) break; // got end of list
|
|
|
|
}
|
|
|
|
PrimSurfaces[i]=(DWORD)ps;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Note: since MS itself declares that the object refcount is not reliable and should
|
|
|
|
// be used for debugging only, it's not safe to rely on refcount==0 when releasing a
|
|
|
|
// surface to terminate its classification as primary. As an alternate and more reliable
|
|
|
|
// way, we use UnmarkPrimarySurface each time you create a new not primary surface,
|
|
|
|
// eliminating the risk that a surface previously classified as primary and then closed
|
|
|
|
// had the same surface handle than this new one that is not primary at all.
|
|
|
|
|
|
|
|
void dxwCore::UnmarkPrimarySurface(LPDIRECTDRAWSURFACE ps)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
// OutTraceD("PRIMARYSURFACE del %x\n",ps);
|
|
|
|
for (i=0;i<DDSQLEN;i++) {
|
|
|
|
if (PrimSurfaces[i]==(DWORD)ps) break;
|
|
|
|
if (PrimSurfaces[i]==0) break;
|
|
|
|
}
|
|
|
|
if (PrimSurfaces[i]==(DWORD)ps){
|
|
|
|
for (; i<DDSQLEN; i++){
|
|
|
|
PrimSurfaces[i]=PrimSurfaces[i+1];
|
|
|
|
if (PrimSurfaces[i]==0) break;
|
|
|
|
}
|
|
|
|
PrimSurfaces[DDSQLEN]=0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL dxwCore::IsAPrimarySurface(LPDIRECTDRAWSURFACE ps)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
// treat NULL surface ptr as a non primary
|
|
|
|
if(!ps) return FALSE;
|
|
|
|
for (i=0;i<DDSQLEN;i++) {
|
|
|
|
if (PrimSurfaces[i]==(DWORD)ps) return TRUE;
|
|
|
|
if (PrimSurfaces[i]==0) return FALSE;
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
LPDIRECTDRAWSURFACE dxwCore::GetPrimarySurface(void)
|
|
|
|
{
|
|
|
|
// return last opened one....
|
|
|
|
int i;
|
|
|
|
for (i=0;i<DDSQLEN;i++) {
|
|
|
|
if (PrimSurfaces[i]==0) break;
|
|
|
|
}
|
|
|
|
if (i) return((LPDIRECTDRAWSURFACE)PrimSurfaces[i-1]);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void dxwCore::SetPrimarySurface(void)
|
|
|
|
{
|
|
|
|
if (!lpDDSPrimHDC) lpDDSPrimHDC=GetPrimarySurface();
|
|
|
|
}
|
|
|
|
|
|
|
|
void dxwCore::ResetPrimarySurface(void)
|
|
|
|
{
|
|
|
|
lpDDSPrimHDC=NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
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-01-04 10:30:38 -05:00
|
|
|
RECT dxwCore::GetScreenRect()
|
2012-12-24 10:20:23 -05:00
|
|
|
{
|
2013-01-04 10:30:38 -05:00
|
|
|
static RECT Screen;
|
|
|
|
Screen.left=0;
|
|
|
|
Screen.top=0;
|
|
|
|
Screen.right=dwScreenWidth;
|
|
|
|
Screen.bottom=dwScreenHeight;
|
|
|
|
return Screen;
|
2012-12-24 10:20:23 -05:00
|
|
|
}
|
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
return FixCursorPos(hWnd, prev);
|
|
|
|
}
|
|
|
|
|
|
|
|
POINT dxwCore::FixCursorPos(HWND hwnd, POINT prev)
|
2012-12-24 10:20:23 -05:00
|
|
|
{
|
|
|
|
POINT curr;
|
|
|
|
RECT rect;
|
|
|
|
extern LPRECT lpClipRegion;
|
|
|
|
|
|
|
|
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){
|
|
|
|
if (!(*pGetClientRect)(hwnd, &rect)) {
|
2012-12-24 10:20:23 -05:00
|
|
|
OutTraceD("GetClientRect ERROR %d at %d\n", GetLastError(),__LINE__);
|
|
|
|
curr.x = curr.y = 0;
|
|
|
|
}
|
|
|
|
|
2013-01-04 10:30:38 -05:00
|
|
|
if (rect.right) curr.x = (curr.x * dxw.GetScreenWidth()) / rect.right;
|
|
|
|
if (rect.bottom) curr.y = (curr.y * dxw.GetScreenHeight()) / rect.bottom;
|
2012-12-24 10:20:23 -05:00
|
|
|
}
|
|
|
|
|
2013-01-04 10:30:38 -05:00
|
|
|
if((dxw.dwFlags1 & ENABLECLIPPING) && 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
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
void dxwCore::SetClipCursor()
|
|
|
|
{
|
|
|
|
RECT Rect;
|
|
|
|
POINT UpLeftCorner;
|
|
|
|
|
2013-01-19 11:16:54 -05:00
|
|
|
OutTraceD("SetClipCursor:\n");
|
2013-01-04 10:30:38 -05:00
|
|
|
if (hWnd==NULL) {
|
2013-01-19 11:16:54 -05:00
|
|
|
OutTraceD("SetClipCursor: ASSERT hWnd==NULL\n");
|
2013-01-04 10:30:38 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
(*pGetClientRect)(hWnd, &Rect);
|
|
|
|
UpLeftCorner.x=UpLeftCorner.y=0;
|
|
|
|
(*pClientToScreen)(hWnd, &UpLeftCorner);
|
|
|
|
Rect.left+=UpLeftCorner.x;
|
|
|
|
Rect.right+=UpLeftCorner.x;
|
|
|
|
Rect.top+=UpLeftCorner.y;
|
|
|
|
Rect.bottom+=UpLeftCorner.y;
|
|
|
|
(*pClipCursor)(NULL);
|
|
|
|
if(!(*pClipCursor)(&Rect)){
|
|
|
|
OutTraceE("ClipCursor: ERROR err=%d at %d\n", GetLastError(), __LINE__);
|
|
|
|
}
|
2013-01-19 11:16:54 -05:00
|
|
|
OutTraceD("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-01-19 11:16:54 -05:00
|
|
|
OutTraceD("EraseClipCursor:\n");
|
2013-01-04 10:30:38 -05:00
|
|
|
(*pClipCursor)(NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
// MapWindow Rect: returns a rectangle in the real coordinate system from the virtual coordinates
|
|
|
|
// of an emulated fullscreen window. NULL or void returns the rectangle of the whole client area.
|
|
|
|
|
|
|
|
RECT dxwCore::MapWindowRect(void)
|
|
|
|
{
|
|
|
|
return MapWindowRect(NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
RECT dxwCore::MapWindowRect(LPRECT lpRect)
|
|
|
|
{
|
|
|
|
POINT UpLeft={0,0};
|
|
|
|
RECT RetRect;
|
|
|
|
RECT ClientRect;
|
|
|
|
if (!(*pGetClientRect)(hWnd, &ClientRect)){
|
|
|
|
OutTraceE("GetClientRect ERROR: err=%d hwnd=%x at %d\n", GetLastError(), hWnd, __LINE__);
|
|
|
|
}
|
|
|
|
if(lpRect){
|
|
|
|
RetRect.left = lpRect->left * ClientRect.right / dwScreenWidth;
|
|
|
|
RetRect.right = lpRect->right * ClientRect.right / dwScreenWidth;
|
|
|
|
RetRect.top = lpRect->top * ClientRect.bottom / dwScreenHeight;
|
|
|
|
RetRect.bottom = lpRect->bottom * ClientRect.bottom / dwScreenHeight;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
RetRect=ClientRect;
|
|
|
|
}
|
|
|
|
if(!(*pClientToScreen)(hWnd, &UpLeft)){
|
|
|
|
OutTraceE("ClientToScreen ERROR: err=%d hwnd=%x at %d\n", GetLastError(), hWnd, __LINE__);
|
|
|
|
}
|
|
|
|
if(!OffsetRect(&RetRect ,UpLeft.x, UpLeft.y)){
|
|
|
|
OutTraceE("OffsetRect ERROR: err=%d hwnd=%x at %d\n", GetLastError(), hWnd, __LINE__);
|
|
|
|
}
|
|
|
|
return RetRect;
|
|
|
|
}
|
|
|
|
|
2013-06-01 12:16:52 -04:00
|
|
|
void dxwCore::MapRect(int *nXDest, int *nYDest, int *nWDest, int *nHDest)
|
|
|
|
{
|
|
|
|
RECT client;
|
|
|
|
(*pGetClientRect)(hWnd, &client);
|
|
|
|
*nXDest= *nXDest * client.right / dwScreenWidth;
|
|
|
|
*nYDest= *nYDest * client.bottom / dwScreenHeight;
|
|
|
|
*nWDest= *nWDest * client.right / dwScreenWidth;
|
|
|
|
*nHDest= *nHDest * client.bottom / dwScreenHeight;
|
|
|
|
}
|
|
|
|
|
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;
|
2013-01-19 11:16:54 -05:00
|
|
|
// extern LPDIRECTDRAWSURFACE GetPrimarySurface();
|
2013-01-04 10:30:38 -05:00
|
|
|
extern HRESULT WINAPI extBlt(LPDIRECTDRAWSURFACE lpdds, LPRECT lpdestrect, LPDIRECTDRAWSURFACE lpddssrc, LPRECT lpsrcrect, DWORD dwflags, LPDDBLTFX lpddbltfx);
|
|
|
|
|
|
|
|
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-01-19 11:16:54 -05:00
|
|
|
lpDDSPrim=dxw.GetPrimarySurface();
|
2013-01-04 10:30:38 -05:00
|
|
|
// if too early ....
|
|
|
|
if (lpDDSPrim)
|
|
|
|
extBlt(lpDDSPrim, NULL, lpDDSPrim, NULL, 0, NULL);
|
|
|
|
|
|
|
|
(*pInvalidateRect)(hWnd, NULL, FALSE);
|
|
|
|
t = tn;
|
2013-06-01 12:16:52 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
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;
|
2013-01-25 11:17:02 -05:00
|
|
|
extern void SetFPS(int);
|
|
|
|
//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 sBuf[80+12+1]; // title + fps string + terminator
|
|
|
|
char *fpss;
|
2013-06-01 12:16:52 -04:00
|
|
|
// log fps count
|
2013-01-29 11:17:05 -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){
|
|
|
|
GetWindowText(hwnd, sBuf, 80);
|
|
|
|
fpss=strstr(sBuf," ~ (");
|
|
|
|
if(fpss==NULL) fpss=&sBuf[strlen(sBuf)];
|
|
|
|
sprintf(fpss, " ~ (%d FPS)", FPSCount);
|
|
|
|
SetWindowText(hwnd, sBuf);
|
|
|
|
}
|
2013-06-01 12:16:52 -04:00
|
|
|
// reset
|
|
|
|
FPSCount=0;
|
|
|
|
time = tmp;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
FPSCount++;
|
2013-01-29 11:17:05 -05:00
|
|
|
OutTrace("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
|
|
|
{
|
2013-01-25 11:17:02 -05:00
|
|
|
static DWORD oldtime=(*pGetTickCount)();
|
|
|
|
DWORD newtime;
|
|
|
|
newtime = (*pGetTickCount)();
|
|
|
|
// use '<' and not '<=' to avoid the risk of sleeping forever....
|
2013-01-29 11:17:05 -05:00
|
|
|
if(newtime < oldtime+delay) {
|
|
|
|
//extern void do_slow(int);
|
|
|
|
if(IsDebug) OutTrace("FPS limit: old=%x new=%x delay=%d sleep=%d\n",
|
|
|
|
oldtime, newtime, delay, (oldtime+delay-newtime));
|
|
|
|
(*pSleep)(oldtime+delay-newtime);
|
|
|
|
// no good processing messages in the meanwhile: AoE series won't work at all!
|
|
|
|
//do_slow(oldtime+delay-newtime);
|
|
|
|
oldtime += delay; // same as doing "oldtime=(*pGetTickCount)();" now
|
|
|
|
}
|
|
|
|
else
|
|
|
|
oldtime = newtime;
|
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-01-25 11:17:02 -05:00
|
|
|
if(dwFlags2 & (SHOWFPS|SHOWFPSOVERLAY)) CountFPS(hWnd);
|
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
|
|
|
}
|
|
|
|
|
2013-01-20 11:16:58 -05:00
|
|
|
static DWORD TimeShifter(DWORD val, int shift)
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2013-08-01 12:16:53 -04:00
|
|
|
DWORD dxwCore::GetTickCount(void)
|
|
|
|
{
|
|
|
|
DWORD dwTick;
|
|
|
|
static DWORD dwLastRealTick=0;
|
|
|
|
static DWORD dwLastFakeTick=0;
|
|
|
|
DWORD dwNextRealTick;
|
|
|
|
|
|
|
|
dwNextRealTick=(*pGetTickCount)();
|
|
|
|
dwTick=(dwNextRealTick-dwLastRealTick);
|
2013-01-25 11:17:02 -05:00
|
|
|
TimeShift=GetHookInfo()->TimeShift;
|
2013-01-20 11:16:58 -05:00
|
|
|
dwTick = TimeShifter(dwTick, TimeShift);
|
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;
|
2013-01-20 11:16:58 -05:00
|
|
|
dwTimer = TimeShifter(dwTimer, -TimeShift);
|
2013-01-19 11:16:54 -05:00
|
|
|
return dwTimer;
|
|
|
|
}
|
|
|
|
|
2013-01-25 11:17:02 -05:00
|
|
|
void dxwCore::GetSystemTimeAsFileTime(LPFILETIME lpSystemTimeAsFileTime)
|
|
|
|
{
|
|
|
|
DWORD dwTick;
|
|
|
|
DWORD dwCurrentTick;
|
|
|
|
FILETIME CurrFileTime;
|
|
|
|
static DWORD dwStartTick=0;
|
|
|
|
static DWORD dwUpdateTick=0;
|
|
|
|
static FILETIME StartFileTime;
|
|
|
|
extern DXWNDSTATUS *pStatus;
|
|
|
|
|
|
|
|
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;
|
|
|
|
dwTick = TimeShifter(dwTick, TimeShift);
|
|
|
|
// 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 DWORD dwUpdateTick=0;
|
|
|
|
static FILETIME StartFileTime;
|
|
|
|
extern DXWNDSTATUS *pStatus;
|
|
|
|
|
|
|
|
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;
|
2013-01-20 11:16:58 -05:00
|
|
|
dwTick = TimeShifter(dwTick, TimeShift);
|
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-01-25 11:17:02 -05:00
|
|
|
void dxwCore::ShowFPS(HDC xdc)
|
|
|
|
{
|
|
|
|
char sBuf[81];
|
|
|
|
static DWORD dwTimer = 0;
|
|
|
|
static int corner = 0;
|
|
|
|
static int x, y;
|
|
|
|
static DWORD color;
|
|
|
|
|
|
|
|
if((*pGetTickCount)()-dwTimer > 4000){
|
|
|
|
RECT rect;
|
|
|
|
dwTimer = (*pGetTickCount)();
|
|
|
|
corner = dwTimer % 4;
|
|
|
|
color=0xFF0000; // blue
|
|
|
|
(*pGetClientRect)(hWnd, &rect);
|
|
|
|
switch (corner) {
|
|
|
|
case 0: x=10; y=10; break;
|
|
|
|
case 1: x=rect.right-60; y=10; break;
|
|
|
|
case 2: x=rect.right-60; y=rect.bottom-20; break;
|
|
|
|
case 3: x=10; y=rect.bottom-20; break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SetTextColor(xdc,color);
|
|
|
|
//SetBkMode(xdc, TRANSPARENT);
|
|
|
|
SetBkMode(xdc, OPAQUE);
|
|
|
|
sprintf(sBuf, "FPS: %d", GetHookInfo()->FPSCount);
|
|
|
|
TextOut(xdc, x, y, sBuf, strlen(sBuf));
|
|
|
|
}
|
|
|
|
|
2013-01-22 11:17:01 -05:00
|
|
|
void dxwCore::ShowFPS(LPDIRECTDRAWSURFACE lpdds)
|
|
|
|
{
|
|
|
|
HDC xdc; // the working dc
|
|
|
|
char sBuf[81];
|
|
|
|
static DWORD dwTimer = 0;
|
|
|
|
static int corner = 0;
|
|
|
|
static int x, y;
|
|
|
|
static DWORD color;
|
|
|
|
|
|
|
|
if((*pGetTickCount)()-dwTimer > 4000){
|
|
|
|
dwTimer = (*pGetTickCount)();
|
|
|
|
corner = dwTimer % 4;
|
|
|
|
color=0xFF0000; // blue
|
|
|
|
switch (corner) {
|
|
|
|
case 0: x=10; y=10; break;
|
|
|
|
case 1: x=dwScreenWidth-60; y=10; break;
|
|
|
|
case 2: x=dwScreenWidth-60; y=dwScreenHeight-20; break;
|
|
|
|
case 3: x=10; y=dwScreenHeight-20; break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (FAILED(lpdds->GetDC(&xdc))) return;
|
|
|
|
SetTextColor(xdc,color);
|
|
|
|
//SetBkMode(xdc, TRANSPARENT);
|
|
|
|
SetBkMode(xdc, OPAQUE);
|
2013-01-25 11:17:02 -05:00
|
|
|
sprintf(sBuf, "FPS: %d", GetHookInfo()->FPSCount);
|
2013-01-22 11:17:01 -05:00
|
|
|
TextOut(xdc, x, y, sBuf, strlen(sBuf));
|
|
|
|
lpdds->ReleaseDC(xdc);
|
|
|
|
}
|
|
|
|
|
|
|
|
char *dxwCore::GetTSCaption(int shift)
|
|
|
|
{
|
|
|
|
static char *sTSCaption[17]={
|
|
|
|
"x16","x12","x8","x6",
|
|
|
|
"x4","x3","x2","x1.5",
|
|
|
|
"x1",
|
|
|
|
":1.5",":2",":3",":4",
|
|
|
|
":6",":8",":12",":16"};
|
|
|
|
if (shift<0 || shift>16) return "???";
|
|
|
|
return sTSCaption[shift+8];
|
|
|
|
}
|
|
|
|
char *dxwCore::GetTSCaption(void)
|
|
|
|
{
|
|
|
|
return GetTSCaption(TimeShift);
|
2012-12-24 10:20:23 -05:00
|
|
|
}
|