diff --git a/Include/dxwnd.h b/Include/dxwnd.h
index 4314890..c9a948b 100644
--- a/Include/dxwnd.h
+++ b/Include/dxwnd.h
@@ -145,6 +145,7 @@ LRESULT CALLBACK extWindowProc(HWND, UINT, WPARAM, LPARAM);
#define OutTraceX if(dxw.dwTFlags & OUTPROXYTRACE) OutTrace
#define OutTraceD if(dxw.dwTFlags & OUTDDRAWTRACE) OutTrace
#define OutTraceC if(dxw.dwTFlags & OUTCURSORTRACE) OutTrace
+#define OutTraceB if(dxw.dwTFlags & OUTDEBUG) OutTrace
#define OutTraceP OutTrace
#define OutTraceE OutTrace
diff --git a/build/dxwnd.dll b/build/dxwnd.dll
index 715d1f8..4d26043 100644
--- a/build/dxwnd.dll
+++ b/build/dxwnd.dll
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:42bf1dd1c3802f28d8bf51d0612a2a5df8e070e0218e2c15912e038ece52c5aa
-size 272384
+oid sha256:5d86d12841bdee7ce3d7140b40baf24b55ea5067689bd374bd8ca59dad6a6d7b
+size 272896
diff --git a/build/dxwnd.exe b/build/dxwnd.exe
index 68baad2..40dda8c 100644
--- a/build/dxwnd.exe
+++ b/build/dxwnd.exe
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:cb6552a857a81cef451a0851137395257ef958b967bc307ded9978abeb09b517
+oid sha256:a5cb263e1da61a6fa71899a4885cf2b6bb608dc3af7af603244d471d524c1cf4
size 488960
diff --git a/build/readme-relnotes.txt b/build/readme-relnotes.txt
index 4e43665..6adac8b 100644
--- a/build/readme-relnotes.txt
+++ b/build/readme-relnotes.txt
@@ -30,3 +30,11 @@ many fixes on the FPS and time control features.
v2.02.08:
fixed some errors in the main directdraw palette descriptor. That gives better compatibility and less complicated source code.
added Fake Version feature: now Dungeon Keeper II (original version, not GOG hack) can detect a fake Win2000 / WinXP environment on Win7 and newer. Tested and working on Win7. Many thanks to Maxim for pushing me hard to win my lazyness and implement this new feature.
+
+v2.02.09:
+Fixed some x,y window coordinates bugs
+Fixed some proxy log messages (missing \n line terminator)
+Fixed Trace "DirectX" flag.
+improved GetDC handling in 8BPP palette mode: AddPalette called on demand, and on any surface (including backbuffers): makes Emergency work with no "Handle DC" flag set. Beware: this may affect the "Map GDI HDC on Primary DC" flag causing surface locks.
+Fixed limit FPS timing issues: now the max possible FPS is 1000/delay.
+Fixed EndPaint bug causing HDC lock in "Map GDI HDC to Primary DC" mode.
\ No newline at end of file
diff --git a/debug/dxwnd.ini b/debug/dxwnd.ini
index 744202e..3a8f455 100644
--- a/debug/dxwnd.ini
+++ b/debug/dxwnd.ini
@@ -21,7 +21,7 @@ path1=D:\Games\7th_Legion\LEGION.EXE
module1=
ver1=0
flag1=402669607
-flagg1=67600
+flagg1=2185232
tflag1=12
initx1=0
inity1=0
@@ -90,7 +90,7 @@ module5=
ver5=1
flag5=134217762
flagg5=32
-tflag5=3
+tflag5=2
initx5=0
inity5=0
minx5=0
@@ -106,8 +106,8 @@ path6=D:\Games\Age of Empires\EMPIRES.EXE
module6=
ver6=0
flag6=402653347
-flagg6=2179088
-tflag6=3
+flagg6=2166800
+tflag6=259
initx6=0
inity6=0
minx6=0
@@ -123,7 +123,7 @@ path7=D:\Games\Age of Empires 2\empires2.exe
module7=
ver7=0
flag7=134217762
-flagg7=0
+flagg7=20480
tflag7=0
initx7=0
inity7=0
@@ -158,7 +158,7 @@ module9=VideoP.dpl vcl30.dpl
ver9=0
flag9=545390594
flagg9=17
-tflag9=131
+tflag9=130
initx9=0
inity9=0
minx9=0
@@ -277,7 +277,7 @@ module16=
ver16=0
flag16=142606370
flagg16=1048576
-tflag16=259
+tflag16=258
initx16=0
inity16=0
minx16=0
@@ -719,7 +719,7 @@ module42=OpenGL32.dll
ver42=9
flag42=514
flagg42=513
-tflag42=387
+tflag42=386
initx42=0
inity42=0
minx42=0
@@ -923,7 +923,7 @@ module54=
ver54=1
flag54=134234150
flagg54=16
-tflag54=3
+tflag54=2
initx54=0
inity54=0
minx54=0
@@ -957,7 +957,7 @@ module56=
ver56=8
flag56=0
flagg56=20480
-tflag56=259
+tflag56=258
initx56=0
inity56=0
minx56=0
@@ -991,7 +991,7 @@ module58=
ver58=9
flag58=679477249
flagg58=303104
-tflag58=257
+tflag58=256
initx58=0
inity58=0
minx58=0
@@ -1037,19 +1037,19 @@ posy60=50
sizx60=800
sizy60=600
title61=Dungeon Keeper II
-path61=C:\Games\Dungeon Keeper II\DKII.exe
+path61=D:\Games\Dungeon Keeper 2\DKII.exe
module61=
ver61=0
flag61=34
flagg61=0
-tflag61=82
+tflag61=2
initx61=0
inity61=0
minx61=0
miny61=0
maxx61=0
maxy61=0
-posx61=50
+posx61=150
posy61=50
sizx61=800
sizy61=600
@@ -1057,9 +1057,9 @@ title62=Emergency Fighters for life
path62=D:\Games\Emergency\EMERGY.EXE
module62=
ver62=0
-flag62=134283811
+flag62=134545443
flagg62=18
-tflag62=3
+tflag62=2
initx62=0
inity62=0
minx62=0
@@ -1365,7 +1365,7 @@ module80=
ver80=10
flag80=1073741826
flagg80=513
-tflag80=259
+tflag80=258
initx80=0
inity80=0
minx80=0
@@ -1382,7 +1382,7 @@ module81=
ver81=1
flag81=1073741826
flagg81=16384
-tflag81=3
+tflag81=2
initx81=0
inity81=0
minx81=0
@@ -1399,7 +1399,7 @@ module82=
ver82=9
flag82=570425377
flagg82=0
-tflag82=479
+tflag82=478
initx82=0
inity82=0
minx82=0
@@ -1483,8 +1483,8 @@ path87=D:\Games\Hexen II\glh2.exe
module87=
ver87=10
flag87=3
-flagg87=2310145
-tflag87=387
+flagg87=155649
+tflag87=386
initx87=0
inity87=0
minx87=0
@@ -1533,7 +1533,7 @@ title90=Hyperblade
path90=D:\Games\Hyperblade\HYPERX.EXE
module90=
ver90=0
-flag90=163
+flag90=134217891
flagg90=3231762
tflag90=3
initx90=0
@@ -1620,7 +1620,7 @@ module95=
ver95=8
flag95=134217760
flagg95=0
-tflag95=3
+tflag95=2
initx95=0
inity95=0
minx95=0
@@ -1654,7 +1654,7 @@ module97=winmm
ver97=9
flag97=537010208
flagg97=196608
-tflag97=259
+tflag97=258
initx97=0
inity97=0
minx97=0
@@ -1671,7 +1671,7 @@ module98=
ver98=0
flag98=0
flagg98=512
-tflag98=267
+tflag98=266
initx98=0
inity98=0
minx98=0
@@ -1773,7 +1773,7 @@ module104=
ver104=7
flag104=0
flagg104=512
-tflag104=259
+tflag104=258
initx104=0
inity104=0
minx104=0
@@ -2147,7 +2147,7 @@ module126=
ver126=10
flag126=167772672
flagg126=1
-tflag126=387
+tflag126=386
initx126=0
inity126=0
minx126=0
@@ -2283,7 +2283,7 @@ module134=
ver134=0
flag134=134234114
flagg134=212992
-tflag134=257
+tflag134=256
initx134=0
inity134=0
minx134=0
@@ -2317,7 +2317,7 @@ module136=
ver136=0
flag136=134217730
flagg136=0
-tflag136=387
+tflag136=386
initx136=0
inity136=0
minx136=0
@@ -2334,7 +2334,7 @@ module137=
ver137=0
flag137=134218242
flagg137=0
-tflag137=259
+tflag137=258
initx137=0
inity137=0
minx137=0
@@ -2436,7 +2436,7 @@ module143=ref_gl.dll ref_soft.dll
ver143=10
flag143=402670082
flagg143=769
-tflag143=387
+tflag143=386
initx143=0
inity143=0
minx143=0
@@ -2640,7 +2640,7 @@ module155=
ver155=10
flag155=0
flagg155=65536
-tflag155=3
+tflag155=2
initx155=0
inity155=0
minx155=0
@@ -2827,7 +2827,7 @@ module166=
ver166=0
flag166=-2013265886
flagg166=16
-tflag166=3
+tflag166=2
initx166=0
inity166=0
minx166=0
@@ -2944,9 +2944,9 @@ title173=Tomb Raider 2 the Golden Mask
path173=D:\Games\TR2 Golden Mask\T2GOLD.EXE
module173=
ver173=0
-flag173=570688034
-flagg173=2179072
-tflag173=387
+flag173=570687522
+flagg173=3227648
+tflag173=259
initx173=0
inity173=0
minx173=0
@@ -3014,7 +3014,7 @@ module177=
ver177=1
flag177=33554434
flagg177=1069056
-tflag177=1
+tflag177=0
initx177=0
inity177=0
minx177=0
@@ -3065,7 +3065,7 @@ module180=
ver180=0
flag180=671236130
flagg180=256
-tflag180=259
+tflag180=258
initx180=0
inity180=0
minx180=0
@@ -3081,8 +3081,8 @@ path181=D:\Games\Warcraft 2\Warcraft II BNE.exe
module181=
ver181=0
flag181=24739
-flagg181=2166800
-tflag181=0
+flagg181=2183184
+tflag181=3
initx181=0
inity181=0
minx181=0
@@ -3115,8 +3115,8 @@ path183=D:\Games\WARLORDS3\Darklord.exe
module183=
ver183=0
flag183=-2013265374
-flagg183=1048608
-tflag183=2
+flagg183=32
+tflag183=3
initx183=0
inity183=0
minx183=0
@@ -3125,8 +3125,8 @@ maxx183=0
maxy183=0
posx183=50
posy183=50
-sizx183=800
-sizy183=600
+sizx183=0
+sizy183=0
title184=WarTorn
path184=C:\Games\WarTorn\W.exe
module184=
@@ -3196,13 +3196,13 @@ posy187=50
sizx187=800
sizy187=600
maxfps0=0
-maxfps1=0
+maxfps1=40
maxfps2=0
maxfps3=0
maxfps4=0
maxfps5=0
-maxfps6=0
-maxfps7=0
+maxfps6=40
+maxfps7=40
maxfps8=0
maxfps9=0
maxfps10=0
@@ -3282,10 +3282,10 @@ maxfps83=0
maxfps84=0
maxfps85=0
maxfps86=0
-maxfps87=100
+maxfps87=50
maxfps88=0
maxfps89=0
-maxfps90=40
+maxfps90=25
maxfps91=0
maxfps92=0
maxfps93=0
@@ -3581,7 +3581,7 @@ initts88=0
opengllib89=
initts89=0
opengllib90=
-initts90=2
+initts90=1
opengllib91=
initts91=0
opengllib92=
@@ -3966,8 +3966,8 @@ module198=
opengllib198=
ver198=0
flag198=134217762
-flagg198=65536
-tflag198=3
+flagg198=2113536
+tflag198=259
initx198=0
inity198=0
minx198=0
@@ -3978,5 +3978,25 @@ posx198=50
posy198=50
sizx198=800
sizy198=600
-maxfps198=0
+maxfps198=20
initts198=-9
+title199=Urban Assault CD
+path199=D:\Games\Urban Assault CD\UA.EXE
+module199=
+opengllib199=
+ver199=0
+flag199=671498274
+flagg199=256
+tflag199=274
+initx199=0
+inity199=0
+minx199=0
+miny199=0
+maxx199=0
+maxy199=0
+posx199=50
+posy199=100
+sizx199=800
+sizy199=600
+maxfps199=0
+initts199=0
diff --git a/dll/dxemublt.cpp b/dll/dxemublt.cpp
index 1b6c085..19482b1 100644
--- a/dll/dxemublt.cpp
+++ b/dll/dxemublt.cpp
@@ -62,7 +62,7 @@ static HRESULT WINAPI EmuBlt_8_to_32(LPDIRECTDRAWSURFACE lpddsdst, LPRECT lpdest
}
}
else {
- if ((*pLock)(lpddssrc, 0, (LPDIRECTDRAWSURFACE)&ddsd_src, DDLOCK_SURFACEMEMORYPTR|DDLOCK_READONLY, 0)) {
+ if(res=(*pLock)(lpddssrc, 0, (LPDIRECTDRAWSURFACE)&ddsd_src, DDLOCK_SURFACEMEMORYPTR|DDLOCK_READONLY, 0)) {
(*pUnlockMethod(lpddsdst))(lpddsdst,0);
OutTraceE("EmuBlt8_32: Lock ERROR res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
return 0;
@@ -131,7 +131,7 @@ static HRESULT WINAPI EmuBlt_16_to_32(LPDIRECTDRAWSURFACE lpddsdst, LPRECT lpdes
}
}
else {
- if (res=(*pLock)(lpddssrc, 0, (LPDIRECTDRAWSURFACE)&ddsd_src, DDLOCK_SURFACEMEMORYPTR|DDLOCK_READONLY|DDLOCK_WAIT, 0)) {
+ if(res=(*pLock)(lpddssrc, 0, (LPDIRECTDRAWSURFACE)&ddsd_src, DDLOCK_SURFACEMEMORYPTR|DDLOCK_READONLY|DDLOCK_WAIT, 0)) {
(*pUnlockMethod(lpddsdst))(lpddsdst,0);
OutTraceE("EmuBlt16_32: Lock ERROR res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
return res;
@@ -227,7 +227,7 @@ static HRESULT WINAPI EmuBlt_24_to_32(LPDIRECTDRAWSURFACE lpddsdst, LPRECT lpdes
}
}
else {
- if (res=(*pLock)(lpddssrc, 0, (LPDIRECTDRAWSURFACE)&ddsd_src, DDLOCK_SURFACEMEMORYPTR|DDLOCK_READONLY, 0)) {
+ if(res=(*pLock)(lpddssrc, 0, (LPDIRECTDRAWSURFACE)&ddsd_src, DDLOCK_SURFACEMEMORYPTR|DDLOCK_READONLY, 0)) {
(*pUnlockMethod(lpddsdst))(lpddsdst,0);
OutTraceE("EmuBlt24_32: Lock ERROR res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
return res;
@@ -302,7 +302,7 @@ static HRESULT WINAPI EmuBlt_32_to_32(LPDIRECTDRAWSURFACE lpddsdst, LPRECT lpdes
}
}
else {
- if ((*pLock)(lpddssrc, 0, (LPDIRECTDRAWSURFACE)&ddsd_src, DDLOCK_SURFACEMEMORYPTR|DDLOCK_READONLY, 0)) {
+ if(res=(*pLock)(lpddssrc, 0, (LPDIRECTDRAWSURFACE)&ddsd_src, DDLOCK_SURFACEMEMORYPTR|DDLOCK_READONLY, 0)) {
(*pUnlockMethod(lpddsdst))(lpddsdst,0);
OutTraceE("EmuBlt32_32: Lock ERROR res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
return res;
@@ -371,7 +371,7 @@ static HRESULT WINAPI EmuBlt_8_to_16(LPDIRECTDRAWSURFACE lpddsdst, LPRECT lpdest
}
}
else {
- if ((*pLock)(lpddssrc, 0, (LPDIRECTDRAWSURFACE)&ddsd_src, DDLOCK_SURFACEMEMORYPTR|DDLOCK_READONLY, 0)) {
+ if(res=(*pLock)(lpddssrc, 0, (LPDIRECTDRAWSURFACE)&ddsd_src, DDLOCK_SURFACEMEMORYPTR|DDLOCK_READONLY, 0)) {
(*pUnlockMethod(lpddsdst))(lpddsdst,0);
OutTraceE("EmuBlt8_16: Lock ERROR res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
return 0;
@@ -454,7 +454,7 @@ static HRESULT WINAPI EmuBlt_24_to_16(LPDIRECTDRAWSURFACE lpddsdst, LPRECT lpdes
}
}
else {
- if ((*pLock)(lpddssrc, 0, (LPDIRECTDRAWSURFACE)&ddsd_src, DDLOCK_SURFACEMEMORYPTR|DDLOCK_READONLY, 0)) {
+ if(res=(*pLock)(lpddssrc, 0, (LPDIRECTDRAWSURFACE)&ddsd_src, DDLOCK_SURFACEMEMORYPTR|DDLOCK_READONLY, 0)) {
(*pUnlockMethod(lpddsdst))(lpddsdst,0);
OutTraceE("EmuBlt24_16: Lock ERROR res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
return 0;
diff --git a/dll/dxhook.cpp b/dll/dxhook.cpp
index aeb2a7b..efbdb84 100644
--- a/dll/dxhook.cpp
+++ b/dll/dxhook.cpp
@@ -320,13 +320,13 @@ void CalculateWindowPos(HWND hwnd, DWORD width, DWORD height, LPWINDOWPOS wp)
HMENU hMenu;
rect.left = dxw.iPosX;
- rect.top = dxw.iPosX;
+ rect.top = dxw.iPosY; //v2.02.09
MaxX = dxw.iSizX;
MaxY = dxw.iSizY;
if (!MaxX) MaxX = width;
if (!MaxY) MaxY = height;
rect.right = dxw.iPosX+MaxX;
- rect.bottom = dxw.iPosX+MaxY;
+ rect.bottom = dxw.iPosY+MaxY; //v2.02.09
dwStyle=(*pGetWindowLong)(hwnd, GWL_STYLE);
hMenu = GetMenu(hwnd);
@@ -417,8 +417,8 @@ INT_PTR CALLBACK extDialogWindowProc(HWND hwnd, UINT message, WPARAM wparam, LPA
static int t = -1;
if (t == -1)
- t = GetTickCount();
- int tn = GetTickCount();
+ t = (*pGetTickCount)();
+ int tn = (*pGetTickCount)();
OutTraceW("DEBUG: DialogWinMsg [0x%x]%s(%x,%x)\n", message, ExplainWinMessage(message), wparam, lparam);
@@ -1192,7 +1192,7 @@ int HookInit(TARGETMAP *target, HWND hwnd)
InitScreenParameters();
- if (IsDebug) OutTraceD("MoveWindow: target pos=(%d,%d) size=(%d,%d)\n", dxw.iPosX, dxw.iPosX, dxw.iSizX, dxw.iSizY);
+ if (IsDebug) OutTraceD("MoveWindow: target pos=(%d,%d) size=(%d,%d)\n", dxw.iPosX, dxw.iPosY, dxw.iSizX, dxw.iSizY); //v2.02.09
if(dxw.dwFlags1 & FIXPARENTWIN){
CalculateWindowPos(hwnd, dxw.iSizX, dxw.iSizY, &wp);
if (IsDebug) OutTraceD("MoveWindow: dxw.hParentWnd=%x pos=(%d,%d) size=(%d,%d)\n", dxw.hParentWnd, wp.x, wp.y, wp.cx, wp.cy);
diff --git a/dll/dxwcore.cpp b/dll/dxwcore.cpp
index 1847209..962242e 100644
--- a/dll/dxwcore.cpp
+++ b/dll/dxwcore.cpp
@@ -132,7 +132,7 @@ void dxwCore::ResetPrimarySurface(void)
void dxwCore::InitWindowPos(int x, int y, int w, int h)
{
iPosX = x;
- iPosX = y;
+ iPosY = y; //v2.02.09
iSizX = w;
iSizY = h;
}
@@ -310,8 +310,8 @@ void dxwCore::ScreenRefresh(void)
static int t = -1;
if (t == -1)
- t = GetTickCount()-(DXWREFRESHINTERVAL+1); // V.2.1.69: trick - subtract
- int tn = GetTickCount();
+ t = (*pGetTickCount)()-(DXWREFRESHINTERVAL+1); // V.2.1.69: trick - subtract
+ int tn = (*pGetTickCount)();
if (tn-t < DXWREFRESHINTERVAL) return;
@@ -332,12 +332,12 @@ static void CountFPS(HWND hwnd)
extern void SetFPS(int);
//DXWNDSTATUS Status;
DWORD tmp;
- tmp = GetTickCount();
+ tmp = (*pGetTickCount)();
if((tmp - time) > 1000) {
char sBuf[80+12+1]; // title + fps string + terminator
char *fpss;
// log fps count
- OutTrace("FPSCount=%d\n", FPSCount);
+ OutTrace("FPS: Delta=%x FPSCount=%d\n", (tmp-time), FPSCount);
// show fps count on status win
GetHookInfo()->FPSCount = FPSCount; // for overlay display
// show fps on win title bar
@@ -354,18 +354,27 @@ static void CountFPS(HWND hwnd)
}
else {
FPSCount++;
+ OutTrace("FPS: Delta=%x FPSCount++=%d\n", (tmp-time), FPSCount);
}
}
-
static void LimitFrameCount(DWORD delay)
{
static DWORD oldtime=(*pGetTickCount)();
DWORD newtime;
newtime = (*pGetTickCount)();
// use '<' and not '<=' to avoid the risk of sleeping forever....
- if(newtime < oldtime+delay) (*pSleep)(oldtime+delay-newtime);
- oldtime = newtime;
+ 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;
}
static BOOL SkipFrameCount(DWORD delay)
@@ -373,10 +382,9 @@ static BOOL SkipFrameCount(DWORD delay)
static DWORD oldtime=(*pGetTickCount)();
DWORD newtime;
newtime = (*pGetTickCount)();
- // use '<' and not '<=' to avoid the risk of sleeping forever....
- if(newtime < oldtime+delay) return TRUE;
+ if(newtime < oldtime+delay) return TRUE; // TRUE => skip the screen refresh
oldtime = newtime;
- return FALSE;
+ return FALSE; // don't skip, do the update
}
diff --git a/dll/dxwnd.cpp b/dll/dxwnd.cpp
index 1028aa2..24579e3 100644
--- a/dll/dxwnd.cpp
+++ b/dll/dxwnd.cpp
@@ -23,7 +23,7 @@ along with this program. If not, see .
#include
#include "dxwnd.h"
-#define VERSION "2.02.08"
+#define VERSION "2.02.09"
LRESULT CALLBACK HookProc(int ncode, WPARAM wparam, LPARAM lparam);
diff --git a/dll/dxwnd.vs2008.suo b/dll/dxwnd.vs2008.suo
index a03763a..420eb1a 100644
Binary files a/dll/dxwnd.vs2008.suo and b/dll/dxwnd.vs2008.suo differ
diff --git a/dll/hddproxy.cpp b/dll/hddproxy.cpp
index a970e45..a407594 100644
--- a/dll/hddproxy.cpp
+++ b/dll/hddproxy.cpp
@@ -1597,9 +1597,9 @@ HRESULT WINAPI extAddOverlayDirtyRectProxy(LPDIRECTDRAWSURFACE lpdds, LPRECT dre
HRESULT res;
OutTraceP("AddOverlayDirtyRect(S): PROXED lpdds=%x ", lpdds);
if (drect)
- OutTraceP(" drect=(%d,%d)-(%d,%d)",drect->left, drect->top, drect->right, drect->bottom);
+ OutTraceP(" drect=(%d,%d)-(%d,%d)\n",drect->left, drect->top, drect->right, drect->bottom);
else
- OutTraceP(" drect=(NULL)");
+ OutTraceP(" drect=(NULL)\n");
res=(*pAddOverlayDirtyRect)(lpdds, drect);
if(res) OutTraceP("AddOverlayDirtyRect(S): ERROR res=%x(%s)\n", res, ExplainDDError(res));
@@ -1615,9 +1615,9 @@ HRESULT WINAPI extUpdateOverlayProxy(LPDIRECTDRAWSURFACE lpdds, LPRECT lpSrcRect
else
OutTraceP(" src=(NULL)");
if (lpDestRect)
- OutTraceP(" dest=(%d,%d)-(%d,%d)",lpDestRect->left, lpDestRect->top, lpDestRect->right, lpDestRect->bottom);
+ OutTraceP(" dest=(%d,%d)-(%d,%d)\n",lpDestRect->left, lpDestRect->top, lpDestRect->right, lpDestRect->bottom);
else
- OutTraceP(" dest=(NULL)");
+ OutTraceP(" dest=(NULL)\n");
res=(*pUpdateOverlay)(lpdds, lpSrcRect, lpddsdest, lpDestRect, dwflags, f);
if(res) OutTraceP("UpdateOverlay(S): ERROR res=%x(%s)\n", res, ExplainDDError(res));
return res;
diff --git a/dll/hddraw.cpp b/dll/hddraw.cpp
index bea0acb..41bb288 100644
--- a/dll/hddraw.cpp
+++ b/dll/hddraw.cpp
@@ -669,10 +669,10 @@ void do_slow(int delay)
{
MSG uMsg;
int t, tn;
- t = GetTickCount();
+ t = (*pGetTickCount)();
uMsg.message=0; // initialize somehow...
- while((tn = GetTickCount())-t < delay){
+ while((tn = (*pGetTickCount)())-t < delay){
while (PeekMessage (&uMsg, NULL, 0, 0, PM_REMOVE) > 0){
if(WM_QUIT == uMsg.message) break;
TranslateMessage (&uMsg);
@@ -832,7 +832,7 @@ static void HookDDSession(LPDIRECTDRAW *lplpdd, int dxversion)
if (dxversion >= 4)
SetHook((void *)(**(DWORD **)lplpdd + 104), extTestCooperativeLevel, (void **)&pTestCooperativeLevel, "TestCooperativeLevel(D)");
- if (!(dxw.dwFlags1 & OUTPROXYTRACE)) return;
+ if (!(dxw.dwTFlags & OUTPROXYTRACE)) return;
// Just proxed ...
// IDIrectDraw::AddRef
@@ -845,7 +845,7 @@ static void HookDDSession(LPDIRECTDRAW *lplpdd, int dxversion)
else
SetHook((void *)(**(DWORD **)lplpdd + 36), extEnumSurfacesProxy4, (void **)&pEnumSurfaces4, "EnumSurfaces(D4)");
// IDIrectDraw::GetCaps
- SetHook((void *)(**(DWORD **)lplpdd + 44), extGetCapsD, (void **)&pGetCapsD, "GetCapsD(D)");
+ SetHook((void *)(**(DWORD **)lplpdd + 44), extGetCapsD, (void **)&pGetCapsD, "GetCaps(D)");
// IDIrectDraw::GetFourCCCodes
SetHook((void *)(**(DWORD **)lplpdd + 52), extGetFourCCCodesProxy, (void **)&pGetFourCCCodes, "GetFourCCCodes(D)");
// IDIrectDraw::GetMonitorFrequency
@@ -878,7 +878,7 @@ static void HookDDClipper(LPDIRECTDRAWCLIPPER FAR* lplpDDClipper)
// IDirectDrawClipper::Release
SetHook((void *)(**(DWORD **)lplpDDClipper + 8), extReleaseC, (void **)&pReleaseC, "Release(C)");
- if (!(dxw.dwFlags1 & OUTPROXYTRACE)) return;
+ if (!(dxw.dwTFlags & OUTPROXYTRACE)) return;
// Just proxed ...
// IDirectDrawClipper::QueryInterface
@@ -911,7 +911,7 @@ static void HookDDPalette(LPDIRECTDRAWPALETTE FAR* lplpDDPalette)
// IDirectDrawPalette::SetEntries
SetHook((void *)(**(DWORD **)lplpDDPalette + 24), extSetEntries, (void **)&pSetEntries, "SetEntries(P)");
- if (!(dxw.dwFlags1 & OUTPROXYTRACE)) return;
+ if (!(dxw.dwTFlags & OUTPROXYTRACE)) return;
// IDirectDrawPalette::QueryInterface
SetHook((void *)(**(DWORD **)lplpDDPalette), extQueryInterfacePProxy, (void **)&pQueryInterfaceP, "QueryInterface(P)");
@@ -1013,7 +1013,7 @@ static void HookDDSurfacePrim(LPDIRECTDRAWSURFACE *lplpdds, int dxversion)
SetHook((void *)(**(DWORD **)lplpdds + 128), extUnlock4, (void **)&pUnlock4, "Unlock(S4)");
}
- if (!(dxw.dwFlags1 & OUTPROXYTRACE)) return;
+ if (!(dxw.dwTFlags & OUTPROXYTRACE)) return;
// Just proxed ...
@@ -1099,7 +1099,7 @@ static void HookDDSurfaceGeneric(LPDIRECTDRAWSURFACE *lplpdds, int dxversion)
// IDirectDrawSurface::ReleaseDC
SetHook((void *)(**(DWORD **)lplpdds + 104), extReleaseDC, (void **)&pReleaseDC, "ReleaseDC(S)");
- if (!(dxw.dwFlags1 & OUTPROXYTRACE)) return;
+ if (!(dxw.dwTFlags & OUTPROXYTRACE)) return;
// just proxed ....
@@ -1616,9 +1616,12 @@ HRESULT WINAPI extSetCooperativeLevel(void *lpdd, HWND hwnd, DWORD dwflags)
if(dxw.dwFlags1 & FIXPARENTWIN) hwnd=dxw.hParentWnd;
}
- if (dwflags & DDSCL_FULLSCREEN){
+ if (dwflags & DDSCL_FULLSCREEN){
dxw.SetFullScreen(TRUE);
- res=(*pSetCooperativeLevel)(lpdd, hwnd, DDSCL_NORMAL);
+ dwflags &= ~(DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE | DDSCL_ALLOWMODEX);
+ dwflags |= DDSCL_NORMAL;
+ //res=(*pSetCooperativeLevel)(lpdd, hwnd, DDSCL_NORMAL);
+ res=(*pSetCooperativeLevel)(lpdd, hwnd, dwflags);
AdjustWindowFrame(hwnd, dxw.GetScreenWidth(), dxw.GetScreenHeight());
//FixWindowFrame(hwnd); //-- incompatible with Microsoft Madness
if (dxw.dwFlags1 & FIXWINFRAME) FixWindowFrame(hwnd);
@@ -1788,7 +1791,7 @@ HRESULT WINAPI extCreateSurfaceEmu(int dxversion, CreateSurface_Type pCreateSurf
dxw.UnmarkPrimarySurface(lpDDSEmu_Prim);
// can't hook lpDDSEmu_Prim as generic, since the Flip method is unimplemented for a PRIMARY surface!
// better avoid it or hook just useful methods.
- //if (dxw.dwFlags1 & OUTPROXYTRACE) HookDDSurfaceGeneric(&lpDDSEmu_Prim, dxw.dwDDVersion);
+ //if (dxw.dwTFlags & OUTPROXYTRACE) HookDDSurfaceGeneric(&lpDDSEmu_Prim, dxw.dwDDVersion);
// rebuild emulated primary backbuffer surface
@@ -1812,7 +1815,7 @@ HRESULT WINAPI extCreateSurfaceEmu(int dxversion, CreateSurface_Type pCreateSurf
}
dxw.UnmarkPrimarySurface(lpDDSEmu_Back);
- if (dxw.dwFlags1 & OUTPROXYTRACE) HookDDSurfaceGeneric(&lpDDSEmu_Back, dxversion);
+ if (dxw.dwTFlags & OUTPROXYTRACE) HookDDSurfaceGeneric(&lpDDSEmu_Back, dxversion);
OutTraceD("CreateSurface: created DDSEmu_Prim=%x DDSEmu_Back=%x DDSPrim=%x DDSBack=%x\n",
lpDDSEmu_Prim, lpDDSEmu_Back, lpDDSPrim, lpDDSBack);
@@ -1864,24 +1867,6 @@ HRESULT WINAPI extCreateSurfaceEmu(int dxversion, CreateSurface_Type pCreateSurf
return res;
}
- // for 8BPP palettized surfaces, connect them to either the ddraw emulated palette or the GDI emulated palette
- if(ddsd.ddpfPixelFormat.dwRGBBitCount==8){ // use a better condition here....
- if(lpDDP==NULL){
- // should link here to the GDI palette? See Hyperblade....
- dxw.palNumEntries=256;
- res=(*pCreatePalette)(lpdd, DDPCAPS_ALLOW256|DDPCAPS_8BIT|DDPCAPS_INITIALIZE, dxw.palPalEntry, &lpDDP, NULL);
- if (res) {
- OutTraceE("CreateSurface: CreatePalette ERROR res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
- return res;
- }
- }
- res=(*pSetPalette)(*lplpdds, lpDDP);
- if (res) {
- OutTraceE("CreateSurface: SetPalette ERROR res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
- return res;
- }
- }
-
// diagnostic hooks ....
HookDDSurfaceGeneric(lplpdds, dxversion);
// unmark this as possible primary
@@ -2443,7 +2428,8 @@ HRESULT WINAPI sBlt(char *api, LPDIRECTDRAWSURFACE lpdds, LPRECT lpdestrect,
// Try to handle HDC lock concurrency....
if(res==DDERR_SURFACEBUSY){
- (*pUnlockMethod(lpddssrc))(lpddssrc, NULL);
+ res=(*pUnlockMethod(lpddssrc))(lpddssrc, NULL);
+ if(res) OutTraceE("Unlock ERROR: err=%x(%s)\n", res, ExplainDDError(res));
res=(*pBlt)(lpdds, &emurect, lpddssrc, lpsrcrect, dwflags, lpddbltfx);
if (res) BlitError(res, lpsrcrect, &destrect, __LINE__);
}
@@ -2665,7 +2651,7 @@ HRESULT WINAPI extWaitForVerticalBlank(LPDIRECTDRAW lpdd, DWORD dwflags, HANDLE
static BOOL step = 0;
DWORD tmp;
if(!(dxw.dwFlags1 & SAVELOAD)) return (*pWaitForVerticalBlank)(lpdd, dwflags, hevent);
- tmp = GetTickCount();
+ tmp = (*pGetTickCount)();
if((time - tmp) > 32) time = tmp;
(*pSleep)(time - tmp);
if(step) time += 16;
@@ -2712,6 +2698,7 @@ HRESULT WINAPI extSetPalette(LPDIRECTDRAWSURFACE lpdds, LPDIRECTDRAWPALETTE lpdd
isPrim=dxw.IsAPrimarySurface(lpdds);
OutTraceD("SetPalette: lpdds=%x%s lpddp=%x\n", lpdds, isPrim?"(PRIM)":"", lpddp);
+#if 0
if(!(dxw.dwFlags1 & EMULATESURFACE) || !isPrim) {
res=(*pSetPalette)(lpdds, lpddp);
if(res)OutTraceE("SetPalette: ERROR res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
@@ -2735,6 +2722,25 @@ HRESULT WINAPI extSetPalette(LPDIRECTDRAWSURFACE lpdds, LPDIRECTDRAWPALETTE lpdd
}
return 0;
+#else
+ res=(*pSetPalette)(lpdds, lpddp);
+ if(res)OutTraceE("SetPalette: ERROR res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
+
+ if((dxw.dwFlags1 & EMULATESURFACE) && (res==DD_OK)){
+ OutTraceD("SetPalette: DEBUG emulating palette\n");
+ lpDDP = lpddp;
+
+ if(lpddp){
+ HRESULT res2;
+ lpentries = (LPPALETTEENTRY)PaletteEntries;
+ res2=lpddp->GetEntries(0, 0, 256, lpentries);
+ if(res2) OutTraceE("SetPalette: GetEntries ERROR res=%x(%s)\n", res2, ExplainDDError(res2));
+ mySetPalette(0, 256, lpentries);
+ }
+ }
+
+ return res;
+#endif
}
HRESULT WINAPI extSetEntries(LPDIRECTDRAWPALETTE lpddp, DWORD dwflags, DWORD dwstart, DWORD dwcount, LPPALETTEENTRY lpentries)
@@ -2926,6 +2932,30 @@ HRESULT WINAPI extGetDC(LPDIRECTDRAWSURFACE lpdds, HDC FAR *pHDC)
IsPrim=dxw.IsAPrimarySurface(lpdds);
OutTraceD("GetDC: lpdss=%x%s\n",lpdds, IsPrim?"(PRIM)":"");
res=(*pGetDC)(lpdds,pHDC);
+
+ if (res==DDERR_CANTCREATEDC &&
+ (dxw.dwFlags1 & EMULATESURFACE) &&
+ dxw.VirtualPixelFormat.dwRGBBitCount==8) {
+ // for 8BPP palettized surfaces, connect them to either the ddraw emulated palette or the GDI emulated palette
+ OutTraceD("GetDC: adding 8BPP palette to surface lpdds=%x\n", lpdds);
+ if(lpDDP==NULL){
+ // should link here to the GDI palette? See Hyperblade....
+ dxw.palNumEntries=256;
+ res=(*pCreatePalette)(lpDD, DDPCAPS_ALLOW256|DDPCAPS_8BIT|DDPCAPS_INITIALIZE, dxw.palPalEntry, &lpDDP, NULL);
+ if (res) {
+ OutTraceE("CreateSurface: CreatePalette ERROR res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
+ return res;
+ }
+ }
+ res=(*pSetPalette)(lpdds, lpDDP);
+ if (res) {
+ OutTraceE("CreateSurface: SetPalette ERROR res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
+ return res;
+ }
+ // retry ....
+ res=(*pGetDC)(lpdds,pHDC);
+ }
+
if(res){
// take care: actually, many games (AoE, Beasts & Bumpkins) get an error code here,
// but pretending nothing happened seems the best way to get tha game working somehow.
diff --git a/dll/hddraw.cpp.bak b/dll/hddraw.cpp.bak
new file mode 100644
index 0000000..91c7205
--- /dev/null
+++ b/dll/hddraw.cpp.bak
@@ -0,0 +1,3838 @@
+// to do: duplicate EnumSurfaces(D) handling
+// fix Unlock duplicate hook in Judge Dredd Pinball
+
+#define INITGUID
+
+#include
+#include
+#include "dxwnd.h"
+#include "dxwcore.hpp"
+#include "stdio.h"
+#include "hddraw.h"
+#include "hddproxy.h"
+#include "dxhelper.h"
+#include "syslibs.h"
+
+// DirectDraw API
+HRESULT WINAPI extDirectDrawCreate(GUID FAR *, LPDIRECTDRAW FAR *, IUnknown FAR *);
+HRESULT WINAPI extDirectDrawCreateEx(GUID FAR *, LPDIRECTDRAW FAR *, REFIID, IUnknown FAR *);
+
+// DirectDraw
+HRESULT WINAPI extQueryInterfaceD(void *, REFIID, LPVOID *);
+ULONG WINAPI extReleaseD(LPDIRECTDRAW);
+ /*** IDirectDraw methods ***/
+HRESULT WINAPI extCreateClipper(LPDIRECTDRAW, DWORD, LPDIRECTDRAWCLIPPER FAR* , IUnknown FAR*);
+HRESULT WINAPI extCreatePalette(LPDIRECTDRAW, DWORD, LPPALETTEENTRY, LPDIRECTDRAWPALETTE *, IUnknown *);
+HRESULT WINAPI extCreateSurface1(LPDIRECTDRAW, DDSURFACEDESC *, LPDIRECTDRAWSURFACE *, void *);
+HRESULT WINAPI extCreateSurface2(LPDIRECTDRAW, DDSURFACEDESC *, LPDIRECTDRAWSURFACE *, void *);
+HRESULT WINAPI extCreateSurface4(LPDIRECTDRAW, DDSURFACEDESC2 *, LPDIRECTDRAWSURFACE *, void *);
+HRESULT WINAPI extCreateSurface7(LPDIRECTDRAW, DDSURFACEDESC2 *, LPDIRECTDRAWSURFACE *, void *);
+HRESULT WINAPI extDuplicateSurface(LPDIRECTDRAW, LPDIRECTDRAWSURFACE, LPDIRECTDRAWSURFACE *);
+HRESULT WINAPI extFlipToGDISurface(LPDIRECTDRAW);
+HRESULT WINAPI extGetDisplayMode(LPDIRECTDRAW, LPDDSURFACEDESC);
+HRESULT WINAPI extGetGDISurface(LPDIRECTDRAW, LPDIRECTDRAWSURFACE *);
+HRESULT WINAPI extEnumDisplayModes1(LPDIRECTDRAW, DWORD, LPDDSURFACEDESC, LPVOID, LPDDENUMMODESCALLBACK);
+HRESULT WINAPI extEnumDisplayModes4(LPDIRECTDRAW, DWORD, LPDDSURFACEDESC2, LPVOID, LPDDENUMMODESCALLBACK2);
+// STDMETHOD(Initialize)(THIS_ GUID FAR *) PURE;
+HRESULT WINAPI extSetCooperativeLevel(void *, HWND, DWORD);
+HRESULT WINAPI extSetDisplayMode1(LPDIRECTDRAW, DWORD, DWORD, DWORD);
+HRESULT WINAPI extSetDisplayMode2(LPDIRECTDRAW, DWORD, DWORD, DWORD, DWORD, DWORD);
+HRESULT WINAPI extWaitForVerticalBlank(LPDIRECTDRAW, DWORD, HANDLE);
+ /*** Added in the V4 Interface ***/
+HRESULT WINAPI extTestCooperativeLevel(LPDIRECTDRAW);
+// STDMETHOD(StartModeTest)(THIS_ LPSIZE, DWORD, DWORD ) PURE;
+// STDMETHOD(EvaluateMode)(THIS_ DWORD, DWORD * ) PURE;
+HRESULT WINAPI extGetCapsD(LPDIRECTDRAW, LPDDCAPS, LPDDCAPS);
+
+
+// DirectDrawSurface
+HRESULT WINAPI extQueryInterfaceS(void *, REFIID, LPVOID *);
+HRESULT WINAPI extReleaseS(LPDIRECTDRAWSURFACE);
+
+ /*** IDirectDrawSurface methods ***/
+HRESULT WINAPI extAddAttachedSurface(LPDIRECTDRAWSURFACE, LPDIRECTDRAWSURFACE);
+HRESULT WINAPI extBlt(LPDIRECTDRAWSURFACE, LPRECT, LPDIRECTDRAWSURFACE, LPRECT, DWORD, LPDDBLTFX);
+HRESULT WINAPI extBltFast(LPDIRECTDRAWSURFACE, DWORD, DWORD, LPDIRECTDRAWSURFACE, LPRECT, DWORD);
+HRESULT WINAPI extDeleteAttachedSurface(LPDIRECTDRAWSURFACE, DWORD, LPDIRECTDRAWSURFACE);
+HRESULT WINAPI extEnumAttachedSurfaces(LPDIRECTDRAWSURFACE, LPVOID, LPDDENUMSURFACESCALLBACK);
+HRESULT WINAPI extFlip(LPDIRECTDRAWSURFACE, LPDIRECTDRAWSURFACE, DWORD);
+HRESULT WINAPI extGetAttachedSurface1(LPDIRECTDRAWSURFACE, DDSCAPS *, LPDIRECTDRAWSURFACE *);
+HRESULT WINAPI extGetAttachedSurface3(LPDIRECTDRAWSURFACE, DDSCAPS *, LPDIRECTDRAWSURFACE *);
+HRESULT WINAPI extGetAttachedSurface4(LPDIRECTDRAWSURFACE, DDSCAPS *, LPDIRECTDRAWSURFACE *);
+HRESULT WINAPI extGetAttachedSurface7(LPDIRECTDRAWSURFACE, DDSCAPS *, LPDIRECTDRAWSURFACE *);
+HRESULT WINAPI extGetCaps1S(LPDIRECTDRAWSURFACE, LPDDSCAPS);
+HRESULT WINAPI extGetCaps2S(LPDIRECTDRAWSURFACE, LPDDSCAPS);
+HRESULT WINAPI extGetCaps3S(LPDIRECTDRAWSURFACE, LPDDSCAPS);
+HRESULT WINAPI extGetCaps4S(LPDIRECTDRAWSURFACE, LPDDSCAPS2);
+HRESULT WINAPI extGetCaps7S(LPDIRECTDRAWSURFACE, LPDDSCAPS2);
+HRESULT WINAPI extGetColorKey(LPDIRECTDRAWSURFACE, DWORD, LPDDCOLORKEY);
+HRESULT WINAPI extGetDC(LPDIRECTDRAWSURFACE, HDC FAR *);
+HRESULT WINAPI extGetPalette(LPDIRECTDRAWSURFACE, LPDIRECTDRAWPALETTE *);
+HRESULT WINAPI extGetPixelFormat(LPDIRECTDRAWSURFACE, LPDDPIXELFORMAT);
+HRESULT WINAPI extGetSurfaceDesc1(LPDIRECTDRAWSURFACE lpdds, LPDDSURFACEDESC lpddsd);
+HRESULT WINAPI extGetSurfaceDesc2(LPDIRECTDRAWSURFACE2 lpdds, LPDDSURFACEDESC2 lpddsd);
+// STDMETHOD(Initialize)(THIS_ LPDIRECTDRAW, LPDDSURFACEDESC2) PURE;
+HRESULT WINAPI extLock(LPDIRECTDRAWSURFACE, LPRECT, LPDIRECTDRAWSURFACE, DWORD, HANDLE);
+HRESULT WINAPI extReleaseDC(LPDIRECTDRAWSURFACE, HDC);
+HRESULT WINAPI extSetClipper(LPDIRECTDRAWSURFACE, LPDIRECTDRAWCLIPPER);
+HRESULT WINAPI extSetColorKey(LPDIRECTDRAWSURFACE, DWORD, LPDDCOLORKEY);
+HRESULT WINAPI extSetPalette(LPDIRECTDRAWSURFACE, LPDIRECTDRAWPALETTE);
+HRESULT WINAPI extUnlock4(LPDIRECTDRAWSURFACE, LPRECT);
+HRESULT WINAPI extUnlock1(LPDIRECTDRAWSURFACE, LPVOID);
+
+HRESULT WINAPI extCreateSurface(int, CreateSurface_Type, LPDIRECTDRAW, DDSURFACEDESC2 *, LPDIRECTDRAWSURFACE *, void *);
+
+// DirectDrawClipper
+HRESULT WINAPI extReleaseC(LPDIRECTDRAWCLIPPER);
+
+// DirectDrawPalette
+HRESULT WINAPI extReleaseP(LPDIRECTDRAWPALETTE);
+// STDMETHOD(Initialize)(THIS_ LPDIRECTDRAW, DWORD, LPPALETTEENTRY) PURE;
+HRESULT WINAPI extSetEntries(LPDIRECTDRAWPALETTE, DWORD, DWORD, DWORD, LPPALETTEENTRY);
+
+HDC WINAPI extGDIGetDC(HWND);
+HDC WINAPI extGDIGetWindowDC(HWND);
+int WINAPI extGDIReleaseDC(HWND, HDC);
+
+/* DirectDraw APIs */
+DirectDrawCreate_Type pDirectDrawCreate;
+DirectDrawCreateEx_Type pDirectDrawCreateEx;
+DirectDrawEnumerate_Type pDirectDrawEnumerate;
+DirectDrawEnumerateEx_Type pDirectDrawEnumerateEx;
+
+/* DirectDraw hook pointers */
+QueryInterface_Type pQueryInterfaceD;
+AddRefD_Type pAddRefD;
+ReleaseD_Type pReleaseD;
+Compact_Type pCompact;
+CreateClipper_Type pCreateClipper=NULL;
+CreatePalette_Type pCreatePalette;
+CreateSurface1_Type pCreateSurface1;
+CreateSurface1_Type pCreateSurface2;
+CreateSurface1_Type pCreateSurface3;
+CreateSurface2_Type pCreateSurface4;
+CreateSurface2_Type pCreateSurface7;
+DuplicateSurface_Type pDuplicateSurface;
+EnumDisplayModes1_Type pEnumDisplayModes1;
+EnumDisplayModes4_Type pEnumDisplayModes4;
+EnumSurfaces1_Type pEnumSurfaces1;
+EnumSurfaces4_Type pEnumSurfaces4;
+FlipToGDISurface_Type pFlipToGDISurface;
+GetCapsD_Type pGetCapsD;
+GetDisplayMode_Type pGetDisplayMode;
+GetFourCCCodes_Type pGetFourCCCodes;
+GetGDISurface_Type pGetGDISurface;
+GetMonitorFrequency_Type pGetMonitorFrequency;
+GetScanLine_Type pGetScanLine;
+GetVerticalBlankStatus_Type pGetVerticalBlankStatus;
+//Initialize
+RestoreDisplayMode_Type pRestoreDisplayMode;
+SetCooperativeLevel_Type pSetCooperativeLevel;
+SetDisplayMode1_Type pSetDisplayMode1;
+SetDisplayMode2_Type pSetDisplayMode2;
+WaitForVerticalBlank_Type pWaitForVerticalBlank;
+GetSurfaceFromDC_Type pGetSurfaceFromDC;
+GetAvailableVidMem_Type pGetAvailableVidMem;
+RestoreAllSurfaces_Type pRestoreAllSurfaces;
+TestCooperativeLevel_Type pTestCooperativeLevel;
+GetDeviceIdentifier_Type pGetDeviceIdentifier;
+
+/* DirectDrawSurface hook pointers */
+QueryInterface_Type pQueryInterfaceS;
+AddRefS_Type pAddRefS;
+ReleaseS_Type pReleaseS;
+AddAttachedSurface_Type pAddAttachedSurface;
+AddOverlayDirtyRect_Type pAddOverlayDirtyRect;
+Blt_Type pBlt;
+BltBatch_Type pBltBatch;
+BltFast_Type pBltFast;
+DeleteAttachedSurface_Type pDeleteAttachedSurface;
+EnumAttachedSurfaces_Type pEnumAttachedSurfaces;
+EnumOverlayZOrders_Type pEnumOverlayZOrders;
+Flip_Type pFlip;
+GetAttachedSurface_Type pGetAttachedSurface1;
+GetAttachedSurface_Type pGetAttachedSurface3;
+GetAttachedSurface_Type pGetAttachedSurface4;
+GetAttachedSurface_Type pGetAttachedSurface7;
+GetBltStatus_Type pGetBltStatus;
+GetCapsS_Type pGetCaps1S;
+GetCapsS_Type pGetCaps2S;
+GetCapsS_Type pGetCaps3S;
+GetCaps2S_Type pGetCaps4S;
+GetCaps2S_Type pGetCaps7S;
+GetClipper_Type pGetClipper;
+GetColorKey_Type pGetColorKey;
+GetDC_Type pGetDC;
+GetFlipStatus_Type pGetFlipStatus;
+GetOverlayPosition_Type pGetOverlayPosition;
+GetPalette_Type pGetPalette;
+GetPixelFormat_Type pGetPixelFormat;
+GetSurfaceDesc_Type pGetSurfaceDesc1;
+GetSurfaceDesc2_Type pGetSurfaceDesc4;
+//Initialize
+IsLost_Type pIsLost;
+Lock_Type pLock;
+ReleaseDC_Type pReleaseDC;
+Restore_Type pRestore;
+SetClipper_Type pSetClipper;
+SetColorKey_Type pSetColorKey;
+SetOverlayPosition_Type pSetOverlayPosition;
+SetPalette_Type pSetPalette;
+Unlock1_Type pUnlock1;
+Unlock4_Type pUnlock4;
+UpdateOverlay_Type pUpdateOverlay;
+UpdateOverlayDisplay_Type pUpdateOverlayDisplay;
+UpdateOverlayZOrder_Type pUpdateOverlayZOrder;
+
+/* DirectDrawClipper hook pointers */
+QueryInterface_Type pQueryInterfaceC;
+AddRefC_Type pAddRefC;
+ReleaseC_Type pReleaseC;
+GetClipList_Type pGetClipList;
+GetHWnd_Type pGetHWnd;
+InitializeC_Type pInitializeC;
+IsClipListChanged_Type pIsClipListChanged;
+SetClipList_Type pSetClipList;
+SetHWnd_Type pSetHWnd;
+
+/* DirectDrawPalette hook pointers */
+QueryInterfaceP_Type pQueryInterfaceP;
+AddRefP_Type pAddRefP;
+ReleaseP_Type pReleaseP;
+ /*** IDirectDrawPalette methods ***/
+GetCapsP_Type pGetCapsP;
+GetEntries_Type pGetEntries;
+// STDMETHOD(Initialize)(THIS_ LPDIRECTDRAW, DWORD, LPPALETTEENTRY) PURE;
+SetEntries_Type pSetEntries;
+
+#define MAXBACKBUFFERS 4
+
+LPDIRECTDRAWSURFACE lpDDSEmu_Prim=NULL, lpDDSEmu_Back=NULL;
+LPDIRECTDRAWSURFACE lpDDSBack=NULL;
+LPDIRECTDRAWCLIPPER lpDDC=NULL;
+LPDIRECTDRAWPALETTE lpDDP=NULL;
+LPDIRECTDRAW lpDD=NULL;
+// v2.1.87: lpServiceDD is the DIRECTDRAW object to which the primary surface and all
+// the service objects (emulated backbuffer, emulater primary, ....) are attached.
+LPDIRECTDRAW lpServiceDD=NULL;
+DWORD PaletteEntries[256];
+DWORD *Palette16BPP = NULL;
+void *EmuScreenBuffer = NULL; // to implement pitch bug fix
+DWORD rPitch = 0;
+LPVOID rSurface = NULL;
+static char *SetPixFmt(LPDDSURFACEDESC2);
+int FlipChainLength=0;
+
+/* ------------------------------------------------------------------------------ */
+// auxiliary (static) functions
+/* ------------------------------------------------------------------------------ */
+
+static void LogSurfaceAttributes(LPDDSURFACEDESC lpddsd, char *label, int line)
+{
+ OutTraceD("SurfaceDesc: %s Flags=%x(%s)",
+ label,
+ lpddsd->dwFlags, ExplainFlags(lpddsd->dwFlags));
+ if (lpddsd->dwFlags & DDSD_BACKBUFFERCOUNT) OutTraceD(" BackBufferCount=%d", lpddsd->dwBackBufferCount);
+ if (lpddsd->dwFlags & DDSD_WIDTH) OutTraceD(" Width=%d", lpddsd->dwWidth);
+ if (lpddsd->dwFlags & DDSD_HEIGHT) OutTraceD(" Height=%d", lpddsd->dwHeight);
+ if (lpddsd->dwFlags & DDSD_CAPS) OutTraceD(" Caps=%x(%s)", lpddsd->ddsCaps.dwCaps, ExplainDDSCaps(lpddsd->ddsCaps.dwCaps));
+ if (lpddsd->dwFlags & DDSD_CKDESTBLT ) OutTraceD(" CKDestBlt=(%x,%x)", lpddsd->ddckCKDestBlt.dwColorSpaceLowValue, lpddsd->ddckCKDestBlt.dwColorSpaceHighValue);
+ if (lpddsd->dwFlags & DDSD_CKDESTOVERLAY ) OutTraceD(" CKDestOverlay=(%x,%x)", lpddsd->ddckCKDestOverlay.dwColorSpaceLowValue, lpddsd->ddckCKDestOverlay.dwColorSpaceHighValue);
+ if (lpddsd->dwFlags & DDSD_CKSRCBLT ) OutTraceD(" CKSrcBlt=(%x,%x)", lpddsd->ddckCKSrcBlt.dwColorSpaceLowValue, lpddsd->ddckCKSrcBlt.dwColorSpaceHighValue);
+ if (lpddsd->dwFlags & DDSD_CKSRCOVERLAY ) OutTraceD(" CKSrcOverlay=(%x,%x)", lpddsd->ddckCKSrcOverlay.dwColorSpaceLowValue, lpddsd->ddckCKSrcOverlay.dwColorSpaceHighValue);
+ if (lpddsd->dwFlags & DDSD_PIXELFORMAT ) OutTraceD(" PixelFormat BPP=%d RGBA=(%x,%x,%x,%x)",
+ lpddsd->ddpfPixelFormat.dwRGBBitCount,
+ lpddsd->ddpfPixelFormat.dwRBitMask,
+ lpddsd->ddpfPixelFormat.dwGBitMask,
+ lpddsd->ddpfPixelFormat.dwBBitMask,
+ lpddsd->ddpfPixelFormat.dwRGBAlphaBitMask);
+ if (lpddsd->dwFlags & DDSD_LPSURFACE) OutTraceD(" Surface=%x", lpddsd->lpSurface);
+ OutTraceD("\n");
+}
+
+static void DumpSurfaceAttributes(LPDDSURFACEDESC lpddsd, char *label, int line)
+{
+ if(!IsDebug) return;
+ LogSurfaceAttributes(lpddsd, label, line);
+}
+
+/* ------------------------------------------------------------------------------ */
+// auxiliary (static) functions for HDC service surfaces stack
+/* ------------------------------------------------------------------------------ */
+
+typedef struct {
+ LPDIRECTDRAWSURFACE lpdds;
+ HDC hdc;
+} DCStackEntry_Type;
+
+DCStackEntry_Type DCStack[22];
+
+static void InitDCStack()
+{
+ int i;
+ for(i=0; i<22; i++) {
+ DCStack[i].hdc=NULL;
+ DCStack[i].lpdds=NULL;
+ }
+}
+
+static void PushDC(LPDIRECTDRAWSURFACE lpdds, HDC hdc)
+{
+ int i;
+ for(i=0; DCStack[i].hdc; i++);
+ if(i<20){
+ DCStack[i].lpdds=lpdds;
+ DCStack[i].hdc=hdc;
+ }
+}
+
+static LPDIRECTDRAWSURFACE PopDC(HDC hdc)
+{
+ int i;
+ LPDIRECTDRAWSURFACE ret;
+ for(i=0; DCStack[i].hdc && (DCStack[i].hdc!=hdc); i++);
+ ret=DCStack[i].lpdds;
+ for(; DCStack[i].hdc; i++) DCStack[i].hdc=NULL;
+ return ret;
+}
+
+BOOL isPaletteUpdated;
+
+void mySetPalette(int dwstart, int dwcount, LPPALETTEENTRY lpentries)
+{
+ int i;
+ OutTraceD("mySetPalette DEBUG: BPP=%d GBitMask=%x count=%d\n",
+ dxw.ActualPixelFormat.dwRGBBitCount, dxw.ActualPixelFormat.dwGBitMask, dwcount);
+
+ if(IsDebug){
+ int idx;
+ OutTraceD("PaletteEntries: start=%d count=%d ", dwstart, dwcount);
+ for(idx=0; idx> 3)
+ :
+ (((DWORD)lpentries[i].peRed & 0xF8) << 8) + (((DWORD)lpentries[i].peGreen & 0xF8) << 3) + (((DWORD)lpentries[i].peBlue &0xF8) >> 3);
+ }
+ break;
+ default:
+ OutTraceD("ASSERT: unsupported Color BPP=%d\n", dxw.ActualPixelFormat.dwRGBBitCount);
+ break;
+ }
+
+ isPaletteUpdated = TRUE;
+}
+
+void InitDDScreenParameters(LPDIRECTDRAW lpdd)
+{
+ HRESULT res;
+ DDSURFACEDESC ddsd;
+ ddsd.dwSize=sizeof(DDSURFACEDESC);
+ if(res=(*pGetDisplayMode)(lpdd, &ddsd)){
+ OutTraceE("GetDisplayMode: ERROR res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
+ return;
+ }
+
+ OutTraceD("InitDDScreenParameters: Flags=%x FourCC=%x RGBBitCount=%d RGBA BitMask=(%x,%x,%x,%x)\n",
+ ddsd.ddpfPixelFormat.dwFlags,
+ ddsd.ddpfPixelFormat.dwFourCC,
+ ddsd.ddpfPixelFormat.dwRGBBitCount,
+ ddsd.ddpfPixelFormat.dwRBitMask,
+ ddsd.ddpfPixelFormat.dwGBitMask,
+ ddsd.ddpfPixelFormat.dwBBitMask,
+ ddsd.ddpfPixelFormat.dwRGBAlphaBitMask);
+
+ dxw.ActualPixelFormat=ddsd.ddpfPixelFormat;
+ SetBltTransformations();
+
+ return;
+}
+
+void InitDSScreenParameters(LPDIRECTDRAWSURFACE lpdds)
+{
+ HRESULT res;
+ DDPIXELFORMAT p;
+ p.dwSize=sizeof(DDPIXELFORMAT);
+ if(res=(*pGetPixelFormat)(lpdds, &p)){
+ OutTraceE("GetPixelFormat: ERROR res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
+ return;
+ }
+
+ OutTraceD("InitDSScreenParameters: Flags=%x FourCC=%x RGBBitCount=%d RGBA BitMask=(%x,%x,%x,%x)\n",
+ p.dwFlags,
+ p.dwFourCC,
+ p.dwRGBBitCount,
+ p.dwRBitMask,
+ p.dwGBitMask,
+ p.dwBBitMask,
+ p.dwRGBAlphaBitMask);
+
+ dxw.ActualPixelFormat=p;
+ SetBltTransformations();
+
+ return;
+}
+
+void InitScreenParameters()
+{
+ DEVMODE CurrDevMode;
+ static int DoOnce = FALSE;
+
+ if(DoOnce) return;
+ DoOnce = TRUE;
+
+ // set default VGA mode 800x600
+ // should I make it configurable ? (640x480, 800x600, 1024x768)
+ dxw.SetScreenSize(); // 800 x 600 by default
+ GetHookInfo()->Height=(short)dxw.GetScreenHeight();
+ GetHookInfo()->Width=(short)dxw.GetScreenWidth();
+ GetHookInfo()->ColorDepth=0; // unknown
+ GetHookInfo()->DXVersion=0; // unknown
+ GetHookInfo()->isLogging=(dxw.dwTFlags & OUTTRACE);
+
+ if(!EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &CurrDevMode)){
+ OutTraceE("EnumDisplaySettings: ERROR err=%d at %d\n", GetLastError(), __LINE__);
+ return;
+ }
+ memset(&dxw.ActualPixelFormat, 0, sizeof(DDPIXELFORMAT));
+ // initialize to default null values, but dwRGBBitCount
+ dxw.ActualPixelFormat.dwRGBBitCount=CurrDevMode.dmBitsPerPel;
+ dxw.VirtualPixelFormat.dwRGBBitCount=CurrDevMode.dmBitsPerPel; // until set differently
+ //if(dxw.dwFlags2 & INIT8BPP) dxw.VirtualPixelFormat.dwRGBBitCount = 8;
+ OutTraceD("InitScreenParameters: RGBBitCount=%d\n", CurrDevMode.dmBitsPerPel);
+ SetBltTransformations();
+ InitDCStack();
+
+ return;
+}
+
+void FixPixelFormat(int ColorDepth, DDPIXELFORMAT *pf)
+{
+ pf->dwFlags = DDPF_RGB;
+ switch(ColorDepth){
+ case 8:
+ pf->dwFlags |= DDPF_PALETTEINDEXED8;
+ pf->dwRGBBitCount = 8;
+ pf->dwRBitMask = 0;
+ pf->dwGBitMask = 0;
+ pf->dwBBitMask = 0;
+ pf->dwRGBAlphaBitMask = 0x0000;
+ break;
+ case 16:
+ pf->dwRGBBitCount = 16;
+ if (dxw.dwFlags1 & USERGB565){
+ pf->dwRBitMask = 0xf800;
+ pf->dwGBitMask = 0x07e0;
+ pf->dwBBitMask = 0x001f;
+ }
+ else {
+ pf->dwRBitMask = 0x7c00;
+ pf->dwGBitMask = 0x03e0;
+ pf->dwBBitMask = 0x001f;
+ }
+ pf->dwRGBAlphaBitMask = 0x8000;
+ break;
+ case 24:
+ pf->dwRGBBitCount = 24;
+ pf->dwRBitMask = 0x00FF0000;
+ pf->dwGBitMask = 0x0000FF00;
+ pf->dwBBitMask = 0x000000FF;
+ pf->dwRGBAlphaBitMask = 0x00000000;
+ break;
+ case 32:
+ pf->dwRGBBitCount = 32;
+ pf->dwRBitMask = 0x00FF0000;
+ pf->dwGBitMask = 0x0000FF00;
+ pf->dwBBitMask = 0x000000FF;
+ pf->dwRGBAlphaBitMask = 0xFF000000;
+ break;
+ }
+}
+
+// -------------------------------------------------------------------------------------
+// Ole32 CoCreateInstance handling: you can create DirectDraw objects through it!
+// utilized so far in a single game: Axiz & Allies
+// -------------------------------------------------------------------------------------
+
+static void HookDDSession(LPDIRECTDRAW *, int);
+//CoCreateInstance_Type pCoCreateInstance=NULL;
+
+HRESULT STDAPICALLTYPE extCoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID riid, LPVOID FAR* ppv)
+{
+ HRESULT res;
+ OutTraceD("CoCreateInstance: rclsid=%x UnkOuter=%x ClsContext=%x refiid=%x\n",
+ rclsid, pUnkOuter, dwClsContext, riid);
+ res=(*pCoCreateInstance)(rclsid, pUnkOuter, dwClsContext, riid, ppv);
+ if(res)
+ OutTraceE("CoCreateInstance: ERROR res=%x\n", res);
+ else
+ OutTraceD("CoCreateInstance: ppv=%x->%x\n", *ppv, *(DWORD *)*ppv);
+
+ if (*(DWORD *)&rclsid==*(DWORD *)&CLSID_DirectDraw){
+ LPDIRECTDRAW lpOldDDraw;
+ OutTraceD("CoCreateInstance: CLSID_DirectDraw object\n");
+ switch (*(DWORD *)&riid){
+ case 0x6C14DB80:
+ OutTraceD("DirectDrawCreate: IID_DirectDraw RIID\n");
+ res=extDirectDrawCreate(NULL, (LPDIRECTDRAW *)&ppv, 0);
+ if(res)OutTraceD("DirectDrawCreate: res=%x(%s)\n", res, ExplainDDError(res));
+ break;
+ case 0xB3A6F3E0:
+ OutTraceD("DirectDrawCreate: IID_DirectDraw2 RIID\n");
+ res=extDirectDrawCreate(NULL, &lpOldDDraw, 0);
+ if(res)OutTraceD("DirectDrawCreate: res=%x(%s)\n", res, ExplainDDError(res));
+ res=lpOldDDraw->QueryInterface(IID_IDirectDraw2, (LPVOID *)&ppv);
+ if(res)OutTraceD("QueryInterface: res=%x(%s)\n", res, ExplainDDError(res));
+ lpOldDDraw->Release();
+ break;
+ case 0x9c59509a:
+ OutTraceD("DirectDrawCreate: IID_DirectDraw4 RIID\n");
+ res=extDirectDrawCreate(NULL, &lpOldDDraw, 0);
+ if(res)OutTraceD("DirectDrawCreate: res=%x(%s)\n", res, ExplainDDError(res));
+ res=lpOldDDraw->QueryInterface(IID_IDirectDraw4, (LPVOID *)&ppv);
+ if(res)OutTraceD("QueryInterface: res=%x(%s)\n", res, ExplainDDError(res));
+ lpOldDDraw->Release();
+ case 0x15e65ec0:
+ OutTraceD("CoCreateInstance: IID_DirectDraw7 RIID\n");
+ res=extDirectDrawCreateEx(NULL, (LPDIRECTDRAW *)&ppv, IID_IDirectDraw7, 0);
+ if(res)OutTraceD("DirectDrawCreateEx: res=%x(%s)\n", res, ExplainDDError(res));
+ break;
+ }
+ }
+ return res;
+}
+
+int HookOle32(char *module, int version)
+{
+ // used by Axis & Allies ....
+ void *tmp;
+ //return 0;
+ OutTraceD("HookOle32 version=%d\n", version); //GHO
+ tmp = HookAPI(module, "ole32.dll", NULL, "CoCreateInstance", extCoCreateInstance);
+ if(tmp) pCoCreateInstance = (CoCreateInstance_Type)tmp;
+ return 0;
+}
+
+int HookDirectDraw(char *module, int version)
+{
+ HINSTANCE hinst;
+ void *tmp;
+ const GUID dd7 = {0x15e65ec0,0x3b9c,0x11d2,0xb9,0x2f,0x00,0x60,0x97,0x97,0xea,0x5b};
+
+ OutTraceD("HookDirectDraw version=%d\n", version); //GHO
+ switch(version){
+ case 0: // automatic
+ tmp = HookAPI(module, "ddraw.dll", NULL, "DirectDrawCreate", extDirectDrawCreate);
+ if(tmp) pDirectDrawCreate = (DirectDrawCreate_Type)tmp;
+ tmp = HookAPI(module, "ddraw.dll", NULL, "DirectDrawCreateEx", extDirectDrawCreateEx);
+ if(tmp) pDirectDrawCreateEx = (DirectDrawCreateEx_Type)tmp;
+ tmp = HookAPI(module, "ddraw.dll", NULL, "DirectDrawEnumerateA", extDirectDrawEnumerateProxy);
+ if(tmp) pDirectDrawEnumerate = (DirectDrawEnumerate_Type)tmp;
+ tmp = HookAPI(module, "ddraw.dll", NULL, "DirectDrawEnumerateExA", extDirectDrawEnumerateExProxy);
+ if(tmp) pDirectDrawEnumerateEx = (DirectDrawEnumerateEx_Type)tmp;
+ break;
+ case 1:
+ case 2:
+ case 3:
+ case 5:
+ case 6:
+ hinst = LoadLibrary("ddraw.dll");
+ pDirectDrawEnumerate =
+ (DirectDrawEnumerate_Type)GetProcAddress(hinst, "DirectDrawEnumerateA");
+ pDirectDrawCreate =
+ (DirectDrawCreate_Type)GetProcAddress(hinst, "DirectDrawCreate");
+ if(pDirectDrawCreate){
+ LPDIRECTDRAW lpdd;
+ BOOL res;
+ HookAPI(module, "ddraw.dll", pDirectDrawCreate, "DirectDrawCreate", extDirectDrawCreate);
+ HookAPI(module, "ddraw.dll", pDirectDrawEnumerate, "DirectDrawEnumerateA", extDirectDrawEnumerateProxy);
+ res=extDirectDrawCreate(0, &lpdd, 0);
+ if (res){
+ OutTraceE("DirectDrawCreate: ERROR res=%x(%s)\n", res, ExplainDDError(res));
+ }
+ lpdd->Release();
+ }
+ break;
+ case 7:
+ hinst = LoadLibrary("ddraw.dll");
+ pDirectDrawEnumerate =
+ (DirectDrawEnumerate_Type)GetProcAddress(hinst, "DirectDrawEnumerateA");
+ pDirectDrawEnumerateEx =
+ (DirectDrawEnumerateEx_Type)GetProcAddress(hinst, "DirectDrawEnumerateExA");
+ pDirectDrawCreate =
+ (DirectDrawCreate_Type)GetProcAddress(hinst, "DirectDrawCreate");
+ if(pDirectDrawCreate){
+ LPDIRECTDRAW lpdd;
+ BOOL res;
+ HookAPI(module, "ddraw.dll", pDirectDrawCreate, "DirectDrawCreate", extDirectDrawCreateProxy);
+ HookAPI(module, "ddraw.dll", pDirectDrawEnumerate, "DirectDrawEnumerateA", extDirectDrawEnumerateProxy);
+ HookAPI(module, "ddraw.dll", pDirectDrawEnumerateEx, "DirectDrawEnumerateExA", extDirectDrawEnumerateExProxy);
+ res=extDirectDrawCreate(0, &lpdd, 0);
+ if (res) OutTraceE("DirectDrawCreate: ERROR res=%x(%s)\n", res, ExplainDDError(res));
+ lpdd->Release();
+ }
+ pDirectDrawCreateEx =
+ (DirectDrawCreateEx_Type)GetProcAddress(hinst, "DirectDrawCreateEx");
+ if(pDirectDrawCreateEx){
+ LPDIRECTDRAW lpdd;
+ BOOL res;
+ HookAPI(module, "ddraw.dll", pDirectDrawCreateEx, "DirectDrawCreateEx", extDirectDrawCreateEx);
+ res=extDirectDrawCreateEx(0, &lpdd, dd7, 0);
+ if (res) OutTraceE("DirectDrawCreateEx: ERROR res=%x(%s)\n", res, ExplainDDError(res));
+ lpdd->Release();
+ }
+ break;
+ }
+
+ if(pDirectDrawCreate || pDirectDrawCreateEx) return 1;
+ return 0;
+}
+
+Unlock4_Type pUnlockMethod(LPDIRECTDRAWSURFACE lpdds)
+{
+ char sMsg[81];
+ void * extUnlock;
+ extUnlock=(void *)*(DWORD *)(*(DWORD *)lpdds + 128);
+ if(extUnlock==(void *)extUnlock1) return (Unlock4_Type)pUnlock1;
+ if(extUnlock==(void *)extUnlock4) return (Unlock4_Type)pUnlock4;
+ sprintf_s(sMsg, 80, "pUnlockMethod: pUnlock(%x) can't match %x\n", lpdds, extUnlock);
+ OutTraceD(sMsg);
+ if (IsAssertEnabled) MessageBox(0, sMsg, "pUnlockMethod", MB_OK | MB_ICONEXCLAMATION);
+ if (pUnlock4) return pUnlock4;
+ return (Unlock4_Type)pUnlock1;
+}
+
+CreateSurface2_Type pCreateSurfaceMethod(LPDIRECTDRAWSURFACE lpdds)
+{
+ char sMsg[81];
+ void * extUnlock;
+ extUnlock=(void *)*(DWORD *)(*(DWORD *)lpdds + 128);
+ if(extUnlock==(void *)extUnlock1) return (CreateSurface2_Type)pCreateSurface1;
+ if(extUnlock==(void *)extUnlock4) return (CreateSurface2_Type)pCreateSurface4;
+ sprintf_s(sMsg, 80, "pCreateSurfaceMethod: pUnlock(%x) can't match %x\n", lpdds, extUnlock);
+ OutTraceD(sMsg);
+ if (IsAssertEnabled) MessageBox(0, sMsg, "pCreateSurfaceMethod", MB_OK | MB_ICONEXCLAMATION);
+ if (pCreateSurface4) return pCreateSurface4;
+ return (CreateSurface2_Type)pCreateSurface1;
+}
+
+int lpddsHookedVersion(LPDIRECTDRAWSURFACE lpdds)
+{
+ char sMsg[81];
+ void * extGetCaps;
+
+ extGetCaps=(void *)*(DWORD *)(*(DWORD *)lpdds + 56);
+ if(extGetCaps==(void *)extGetCaps1S) return 1;
+ if(extGetCaps==(void *)extGetCaps2S) return 2;
+ if(extGetCaps==(void *)extGetCaps3S) return 3;
+ if(extGetCaps==(void *)extGetCaps4S) return 4;
+ if(extGetCaps==(void *)extGetCaps7S) return 7;
+ sprintf_s(sMsg, 80, "lpddsHookedVersion(%x) can't match %x\n", lpdds, extGetCaps);
+ OutTraceD(sMsg);
+ if (IsAssertEnabled) MessageBox(0, sMsg, "lpddsHookedVersion", MB_OK | MB_ICONEXCLAMATION);
+ return 0;
+}
+
+int lpddHookedVersion(LPDIRECTDRAW lpdd)
+{
+ char sMsg[81];
+ void * extCreateSurface;
+
+ extCreateSurface=(void *)*(DWORD *)(*(DWORD *)lpdd + 24);
+ if(extCreateSurface==(void *)extCreateSurface1) return 1;
+ if(extCreateSurface==(void *)extCreateSurface2) return 2;
+ if(extCreateSurface==(void *)extCreateSurface4) return 4;
+ if(extCreateSurface==(void *)extCreateSurface7) return 7;
+ sprintf_s(sMsg, 80, "lpddHookedVersion(%x) can't match %x\n", lpdd, extCreateSurface);
+ OutTraceD(sMsg);
+ if (IsAssertEnabled) MessageBox(0, sMsg, "lpddHookedVersion", MB_OK | MB_ICONEXCLAMATION);
+ return 0;
+}
+
+/* ------------------------------------------------------------------ */
+
+void do_slow(int delay)
+{
+ MSG uMsg;
+ int t, tn;
+ t = GetTickCount();
+
+ uMsg.message=0; // initialize somehow...
+ while((tn = GetTickCount())-t < delay){
+ while (PeekMessage (&uMsg, NULL, 0, 0, PM_REMOVE) > 0){
+ if(WM_QUIT == uMsg.message) break;
+ TranslateMessage (&uMsg);
+ DispatchMessage (&uMsg);
+ }
+ (*pSleep)(1);
+ }
+}
+
+static void DumpPixFmt(LPDDSURFACEDESC2 lpdd)
+{
+ OutTraceD("PixFmt: Size=%x Flags=%x FourCC=%x RGBBitCount=%d RGBA BitMask=(%x,%x,%x,%x)\n",
+ lpdd->ddpfPixelFormat.dwSize,
+ lpdd->ddpfPixelFormat.dwFlags,
+ lpdd->ddpfPixelFormat.dwFourCC,
+ lpdd->ddpfPixelFormat.dwRGBBitCount,
+ lpdd->ddpfPixelFormat.dwRBitMask,
+ lpdd->ddpfPixelFormat.dwGBitMask,
+ lpdd->ddpfPixelFormat.dwBBitMask,
+ lpdd->ddpfPixelFormat.dwRGBAlphaBitMask);
+}
+
+static char *SetPixFmt(LPDDSURFACEDESC2 lpdd)
+{
+ char *pfstr;
+ OutTraceD("SetPixFmt: BPP=%d Use565=%d\n", dxw.VirtualPixelFormat.dwRGBBitCount, dxw.dwFlags1 & USERGB565 ? 1:0);
+ memset(&lpdd->ddpfPixelFormat,0,sizeof(DDPIXELFORMAT));
+ lpdd->ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
+ lpdd->ddpfPixelFormat.dwRGBBitCount = dxw.ActualPixelFormat.dwRGBBitCount;
+ if(dxw.ActualPixelFormat.dwRGBBitCount==dxw.VirtualPixelFormat.dwRGBBitCount && dxw.ActualPixelFormat.dwRBitMask){
+ // if same color depth, choose current color masks
+ pfstr="CURRENT";
+ lpdd->ddpfPixelFormat=dxw.ActualPixelFormat;
+ }
+ else
+ {
+ switch (dxw.VirtualPixelFormat.dwRGBBitCount)
+ {
+ case 8:
+ pfstr="RGB8";
+ FixPixelFormat(8, &lpdd->ddpfPixelFormat);
+ break;
+ case 16:
+ pfstr=(dxw.dwFlags1 & USERGB565)?"RGB16-565":"RGB16-555";
+ FixPixelFormat(16, &lpdd->ddpfPixelFormat);
+ break;
+ case 24:
+ pfstr="RGB24";
+ FixPixelFormat(24, &lpdd->ddpfPixelFormat);
+ break;
+ case 32:
+ pfstr="RGB32";
+ FixPixelFormat(32, &lpdd->ddpfPixelFormat);
+ break;
+ default:
+ pfstr="unsupported";
+ OutTraceE("CreateSurface ERROR: Unsupported resolution ColorBPP=%d\n", dxw.VirtualPixelFormat.dwRGBBitCount);
+ break;
+ }
+ }
+
+ // remember current virtual settings
+ dxw.VirtualPixelFormat=lpdd->ddpfPixelFormat;
+
+ OutTraceD("SetPixFmt: RGBBitCount=%d Flags=%x FourCC=%x RGBA BitMask=(%x,%x,%x,%x)\n",
+ lpdd->ddpfPixelFormat.dwRGBBitCount,
+ lpdd->ddpfPixelFormat.dwFlags,
+ lpdd->ddpfPixelFormat.dwFourCC,
+ lpdd->ddpfPixelFormat.dwRBitMask,
+ lpdd->ddpfPixelFormat.dwGBitMask,
+ lpdd->ddpfPixelFormat.dwBBitMask,
+ lpdd->ddpfPixelFormat.dwRGBAlphaBitMask);
+
+ return pfstr;
+}
+
+/* ------------------------------------------------------------------ */
+// hook query functions that determines the object versioning ....
+/* ------------------------------------------------------------------ */
+
+int Set_dwSize_From_Surface(LPDIRECTDRAWSURFACE lpdds)
+{
+ int dxversion;
+ if (lpdds==NULL ||
+ lpdds==lpDDSEmu_Prim ||
+ lpdds==lpDDSEmu_Back
+ )
+ dxversion=lpddHookedVersion(lpServiceDD); // v2.1.87 fix
+ else
+ dxversion=lpddsHookedVersion(lpdds);
+
+ return (dxversion < 4) ? sizeof(DDSURFACEDESC) : sizeof(DDSURFACEDESC2);
+}
+
+int Set_dwSize_From_DDraw(LPDIRECTDRAW lpdd)
+{
+ return (lpddHookedVersion(lpdd) < 4) ? sizeof(DDSURFACEDESC) : sizeof(DDSURFACEDESC2);
+}
+
+static void HookDDSession(LPDIRECTDRAW *lplpdd, int dxversion)
+{
+ OutTraceD("Hooking directdraw session dd=%x dxversion=%d thread_id=%x\n",
+ *lplpdd, dxversion, GetCurrentThreadId());
+
+ // IDIrectDraw::QueryInterface
+ SetHook((void *)(**(DWORD **)lplpdd), extQueryInterfaceD, (void **)&pQueryInterfaceD, "QueryInterface(D)");
+ // IDIrectDraw::Release
+ SetHook((void *)(**(DWORD **)lplpdd + 8), extReleaseD, (void **)&pReleaseD, "Release(D)");
+ // IDIrectDraw::CreateClipper
+ SetHook((void *)(**(DWORD **)lplpdd + 16), extCreateClipper, (void **)&pCreateClipper, "CreateClipper(D)");
+ // IDIrectDraw::CreatePalette
+ SetHook((void *)(**(DWORD **)lplpdd + 20), extCreatePalette, (void **)&pCreatePalette, "CreatePalette(D)");
+ // IDIrectDraw::CreateSurface
+ switch(dxversion) {
+ case 1:
+ SetHook((void *)(**(DWORD **)lplpdd + 24), extCreateSurface1, (void **)&pCreateSurface1, "CreateSurface(S1)");
+ break;
+ case 2:
+ SetHook((void *)(**(DWORD **)lplpdd + 24), extCreateSurface2, (void **)&pCreateSurface2, "CreateSurface(S2)");
+ break;
+ case 4:
+ SetHook((void *)(**(DWORD **)lplpdd + 24), extCreateSurface4, (void **)&pCreateSurface4, "CreateSurface(S4)");
+ break;
+ case 7:
+ SetHook((void *)(**(DWORD **)lplpdd + 24), extCreateSurface7, (void **)&pCreateSurface7, "CreateSurface(S7)");
+ break;
+ }
+ // IDIrectDraw::DuplicateSurface
+ SetHook((void *)(**(DWORD **)lplpdd + 28), extDuplicateSurface, (void **)&pDuplicateSurface, "DuplicateSurface(D)");
+ // IDIrectDraw::EnumDisplayModes
+ switch(dxversion) {
+ case 1:
+ case 2:
+ SetHook((void *)(**(DWORD **)lplpdd + 32), extEnumDisplayModes1, (void **)&pEnumDisplayModes1, "EnumDisplayModes(D1)");
+ break;
+ case 4:
+ case 7:
+ SetHook((void *)(**(DWORD **)lplpdd + 32), extEnumDisplayModes4, (void **)&pEnumDisplayModes4, "EnumDisplayModes(D4)");
+ break;
+ }
+ // IDIrectDraw::FlipToGDISurface
+ SetHook((void *)(**(DWORD **)lplpdd + 40), extFlipToGDISurface, (void **)&pFlipToGDISurface, "FlipToGDISurface(D)");
+ // IDIrectDraw::GetDisplayMode
+ SetHook((void *)(**(DWORD **)lplpdd + 48), extGetDisplayMode, (void **)&pGetDisplayMode, "GetDisplayMode(D)");
+ // IDIrectDraw::GetGDISurface
+ SetHook((void *)(**(DWORD **)lplpdd + 56), extGetGDISurface, (void **)&pGetGDISurface, "GetGDISurface(D)");
+ // IDIrectDraw::SetCooperativeLevel
+ SetHook((void *)(**(DWORD **)lplpdd + 80), extSetCooperativeLevel, (void **)&pSetCooperativeLevel, "SetCooperativeLevel(D)");
+ // IDIrectDraw::SetDisplayMode
+ if (dxversion > 1)
+ SetHook((void *)(**(DWORD **)lplpdd + 84), extSetDisplayMode2, (void **)&pSetDisplayMode2, "SetDisplayMode(D2)");
+ else
+ SetHook((void *)(**(DWORD **)lplpdd + 84), extSetDisplayMode1, (void **)&pSetDisplayMode1, "SetDisplayMode(D1)");
+ // IDIrectDraw::WaitForVerticalBlank
+ SetHook((void *)(**(DWORD **)lplpdd + 88), extWaitForVerticalBlank, (void **)&pWaitForVerticalBlank, "WaitForVerticalBlank(D)");
+ // IDIrectDraw::TestCooperativeLevel
+ if (dxversion >= 4)
+ SetHook((void *)(**(DWORD **)lplpdd + 104), extTestCooperativeLevel, (void **)&pTestCooperativeLevel, "TestCooperativeLevel(D)");
+
+ if (!(dxw.dwTFlags & OUTPROXYTRACE)) return;
+ // Just proxed ...
+
+ // IDIrectDraw::AddRef
+ SetHook((void *)(**(DWORD **)lplpdd + 4), extAddRefDProxy, (void **)&pAddRefD, "AddRef(D)");
+ // IDIrectDraw::Compact
+ SetHook((void *)(**(DWORD **)lplpdd + 12), extCompactProxy, (void **)&pCompact, "Compact(D)");
+ // IDIrectDraw::EnumSurfaces
+ if (dxversion < 4)
+ SetHook((void *)(**(DWORD **)lplpdd + 36), extEnumSurfacesProxy1, (void **)&pEnumSurfaces1, "EnumSurfaces(D1)");
+ else
+ SetHook((void *)(**(DWORD **)lplpdd + 36), extEnumSurfacesProxy4, (void **)&pEnumSurfaces4, "EnumSurfaces(D4)");
+ // IDIrectDraw::GetCaps
+ SetHook((void *)(**(DWORD **)lplpdd + 44), extGetCapsD, (void **)&pGetCapsD, "GetCaps(D)");
+ // IDIrectDraw::GetFourCCCodes
+ SetHook((void *)(**(DWORD **)lplpdd + 52), extGetFourCCCodesProxy, (void **)&pGetFourCCCodes, "GetFourCCCodes(D)");
+ // IDIrectDraw::GetMonitorFrequency
+ SetHook((void *)(**(DWORD **)lplpdd + 60), extGetMonitorFrequencyProxy, (void **)&pGetMonitorFrequency, "GetMonitorFrequency(D)");
+ // IDIrectDraw::GetScanLine
+ SetHook((void *)(**(DWORD **)lplpdd + 64), extGetScanLineProxy, (void **)&pGetScanLine, "GetScanLine(D)");
+ // IDIrectDraw::GetVerticalBlankStatus
+ SetHook((void *)(**(DWORD **)lplpdd + 68), extGetVerticalBlankStatusProxy, (void **)&pGetVerticalBlankStatus, "GetVerticalBlankStatus(D)");
+ // IDIrectDraw::Initialize
+ // offset 72: Undocumented
+ // IDIrectDraw::RestoreDisplayMode
+ SetHook((void *)(**(DWORD **)lplpdd + 76), extRestoreDisplayModeProxy, (void **)&pRestoreDisplayMode, "RestoreDisplayMode(D)");
+ // IDIrectDraw::GetAvailableVidMem
+ if (dxversion >= 2)
+ SetHook((void *)(**(DWORD **)lplpdd + 92), extGetAvailableVidMemProxy, (void **)&pGetAvailableVidMem, "GetAvailableVidMem(D)");
+ if (dxversion >= 4){
+ // IDIrectDraw::GetSurfaceFromDC
+ SetHook((void *)(**(DWORD **)lplpdd + 96), extGetSurfaceFromDCProxy, (void **)&pGetSurfaceFromDC, "GetSurfaceFromDC(D)");
+ // IDIrectDraw::RestoreAllSurfaces
+ SetHook((void *)(**(DWORD **)lplpdd + 100), extRestoreAllSurfacesProxy, (void **)&pRestoreAllSurfaces, "RestoreAllSurfaces(D)");
+ // IDIrectDraw::GetDeviceIdentifier
+ SetHook((void *)(**(DWORD **)lplpdd + 108), extGetDeviceIdentifierProxy, (void **)&pGetDeviceIdentifier, "GetDeviceIdentifier(D)");
+ }
+}
+
+static void HookDDClipper(LPDIRECTDRAWCLIPPER FAR* lplpDDClipper)
+{
+ OutTraceD("Hooking directdraw clipper dd=%x\n", *lplpDDClipper);
+
+ // IDirectDrawClipper::Release
+ SetHook((void *)(**(DWORD **)lplpDDClipper + 8), extReleaseC, (void **)&pReleaseC, "Release(C)");
+
+ if (!(dxw.dwTFlags & OUTPROXYTRACE)) return;
+ // Just proxed ...
+
+ // IDirectDrawClipper::QueryInterface
+ SetHook((void *)(**(DWORD **)lplpDDClipper), extQueryInterfaceCProxy, (void **)&pQueryInterfaceC, "QueryInterface(C)");
+ // IDirectDrawClipper::AddRef
+ SetHook((void *)(**(DWORD **)lplpDDClipper + 4), extAddRefCProxy, (void **)&pAddRefC, "AddRef(C)");
+ // IDirectDrawClipper::GetClipList
+ SetHook((void *)(**(DWORD **)lplpDDClipper + 12), extGetClipListProxy, (void **)&pGetClipList, "GetClipList(C)");
+ // IDirectDrawClipper::GetHWnd
+ SetHook((void *)(**(DWORD **)lplpDDClipper + 16), extGetHWndProxy, (void **)&pGetHWnd, "GetHWnd(C)");
+ // IDirectDrawClipper::Initialize
+ SetHook((void *)(**(DWORD **)lplpDDClipper + 20), extInitializeCProxy, (void **)&pInitializeC, "Initialize(C)");
+ // IDirectDrawClipper::IsClipListChanged
+ SetHook((void *)(**(DWORD **)lplpDDClipper + 24), extIsClipListChangedProxy, (void **)&pIsClipListChanged, "IsClipListChanged(C)");
+ // IDirectDrawClipper::SetClipList
+ SetHook((void *)(**(DWORD **)lplpDDClipper + 28), extSetClipListProxy, (void **)&pSetClipList, "SetClipList(C)");
+ // IDirectDrawClipper::SetHWnd
+ SetHook((void *)(**(DWORD **)lplpDDClipper + 32), extSetHWndProxy, (void **)&pSetHWnd, "SetHWnd(C)");
+
+ return;
+}
+
+static void HookDDPalette(LPDIRECTDRAWPALETTE FAR* lplpDDPalette)
+{
+ OutTraceD("Hooking directdraw palette dd=%x\n", *lplpDDPalette);
+
+ /*** IDirectDrawPalette methods ***/
+ // IDirectDrawPalette::Release
+ SetHook((void *)(**(DWORD **)lplpDDPalette + 8), extReleaseP, (void **)&pReleaseP, "Release(P)");
+ // IDirectDrawPalette::SetEntries
+ SetHook((void *)(**(DWORD **)lplpDDPalette + 24), extSetEntries, (void **)&pSetEntries, "SetEntries(P)");
+
+ if (!(dxw.dwTFlags & OUTPROXYTRACE)) return;
+
+ // IDirectDrawPalette::QueryInterface
+ SetHook((void *)(**(DWORD **)lplpDDPalette), extQueryInterfacePProxy, (void **)&pQueryInterfaceP, "QueryInterface(P)");
+ // IDirectDrawPalette::AddRef
+ SetHook((void *)(**(DWORD **)lplpDDPalette + 4), extAddRefPProxy, (void **)&pAddRefP, "AddRef(P)");
+ // IDirectDrawPalette::GetCaps
+ SetHook((void *)(**(DWORD **)lplpDDPalette + 12), extGetCapsPProxy, (void **)&pGetCapsP, "GetCaps(P)");
+ // IDirectDrawPalette::GetEntries
+ SetHook((void *)(**(DWORD **)lplpDDPalette + 16), extGetEntriesProxy, (void **)&pGetEntries, "GetEntries(P)");
+
+ return;
+}
+
+static void HookDDSurfacePrim(LPDIRECTDRAWSURFACE *lplpdds, int dxversion)
+{
+ OutTraceD("Hooking surface as primary dds=%x dxversion=%d thread_id=%x\n",
+ *lplpdds, dxversion, GetCurrentThreadId());
+
+ // IDirectDrawSurface::Query
+ SetHook((void *)(**(DWORD **)lplpdds), extQueryInterfaceS, (void **)&pQueryInterfaceS, "QueryInterface(S)");
+ // IDirectDrawSurface::Release
+ SetHook((void *)(**(DWORD **)lplpdds + 8), extReleaseS, (void **)&pReleaseS, "Release(S)");
+ // IDirectDrawSurface::AddAttachedSurface
+ SetHook((void *)(**(DWORD **)lplpdds + 12), extAddAttachedSurface, (void **)&pAddAttachedSurface, "AddAttachedSurface(S)");
+ // IDirectDrawSurface::Blt
+ SetHook((void *)(**(DWORD **)lplpdds + 20), extBlt, (void **)&pBlt, "Blt(S)");
+ // IDirectDrawSurface::BltFast
+ SetHook((void *)(**(DWORD **)lplpdds + 28), extBltFast, (void **)&pBltFast, "BltFast(S)");
+ // IDirectDrawSurface::DeleteAttachedSurface
+ SetHook((void *)(**(DWORD **)lplpdds + 32), extDeleteAttachedSurface, (void **)&pDeleteAttachedSurface, "DeleteAttachedSurface(S)");
+ // IDirectDrawSurface::EnumAttachedSurfaces
+ SetHook((void *)(**(DWORD **)lplpdds + 36), extEnumAttachedSurfaces, (void **)&pEnumAttachedSurfaces, "EnumAttachedSurfaces(S)");
+ // IDirectDrawSurface::Flip
+ SetHook((void *)(**(DWORD **)lplpdds + 44), extFlip, (void **)&pFlip, "Flip(S)");
+ // IDirectDrawSurface::GetAttachedSurface
+ switch(dxversion) {
+ case 1:
+ case 2:
+ SetHook((void *)(**(DWORD **)lplpdds + 48), extGetAttachedSurface1, (void **)&pGetAttachedSurface1, "GetAttachedSurface(S1)");
+ break;
+ case 3:
+ SetHook((void *)(**(DWORD **)lplpdds + 48), extGetAttachedSurface3, (void **)&pGetAttachedSurface3, "GetAttachedSurface(S3)");
+ break;
+ case 4:
+ SetHook((void *)(**(DWORD **)lplpdds + 48), extGetAttachedSurface4, (void **)&pGetAttachedSurface4, "GetAttachedSurface(S4)");
+ break;
+ case 7:
+ SetHook((void *)(**(DWORD **)lplpdds + 48), extGetAttachedSurface7, (void **)&pGetAttachedSurface7, "GetAttachedSurface(S7)");
+ break;
+ }
+ // IDirectDrawSurface::GetCaps
+ switch(dxversion) {
+ case 1:
+ SetHook((void *)(**(DWORD **)lplpdds + 56), extGetCaps1S, (void **)&pGetCaps1S, "GetCaps(S1)");
+ break;
+ case 2:
+ SetHook((void *)(**(DWORD **)lplpdds + 56), extGetCaps2S, (void **)&pGetCaps2S, "GetCaps(S2)");
+ break;
+ case 3:
+ SetHook((void *)(**(DWORD **)lplpdds + 56), extGetCaps3S, (void **)&pGetCaps3S, "GetCaps(S3)");
+ break;
+ case 4:
+ SetHook((void *)(**(DWORD **)lplpdds + 56), extGetCaps4S, (void **)&pGetCaps4S, "GetCaps(S4)");
+ break;
+ case 7:
+ SetHook((void *)(**(DWORD **)lplpdds + 56), extGetCaps7S, (void **)&pGetCaps7S, "GetCaps(S7)");
+ break;
+ }
+ // IDirectDrawSurface::GetColorKey
+ SetHook((void *)(**(DWORD **)lplpdds + 64), extGetColorKey, (void **)&pGetColorKey, "GetColorKey(S)");
+ // IDirectDrawSurface::GetPalette
+ SetHook((void *)(**(DWORD **)lplpdds + 80), extGetPalette, (void **)&pGetPalette, "GetPalette(S)");
+ // IDirectDrawSurface::GetPixelFormat
+ SetHook((void *)(**(DWORD **)lplpdds + 84), extGetPixelFormat, (void **)&pGetPixelFormat, "GetPixelFormat(S)");
+ // IDirectDrawSurface::GetSurfaceDesc
+ if (dxversion < 4) {
+ SetHook((void *)(**(DWORD **)lplpdds + 88), extGetSurfaceDesc1, (void **)&pGetSurfaceDesc1, "GetSurfaceDesc(S1)");
+ }
+ else {
+ SetHook((void *)(**(DWORD **)lplpdds + 88), extGetSurfaceDesc2, (void **)&pGetSurfaceDesc4, "GetSurfaceDesc(S4)");
+ }
+ // IDirectDrawSurface::SetClipper
+ SetHook((void *)(**(DWORD **)lplpdds + 112), extSetClipper, (void **)&pSetClipper, "SetClipper(S)");
+ // IDirectDrawSurface::SetColorKey
+ SetHook((void *)(**(DWORD **)lplpdds + 116), extSetColorKey, (void **)&pSetColorKey, "SetColorKey(S)");
+ // IDirectDrawSurface::SetPalette
+ SetHook((void *)(**(DWORD **)lplpdds + 124), extSetPalette, (void **)&pSetPalette, "SetPalette(S)");
+ // IDirectDrawSurface::GetDC
+ SetHook((void *)(**(DWORD **)lplpdds + 68), extGetDC, (void **)&pGetDC, "GetDC(S)");
+ // IDirectDrawSurface::ReleaseDC
+ SetHook((void *)(**(DWORD **)lplpdds + 104), extReleaseDC, (void **)&pReleaseDC, "ReleaseDC(S)");
+ if (dxw.dwFlags1 & (EMULATESURFACE|EMULATEBUFFER)){
+ // IDirectDrawSurface::Lock
+ SetHook((void *)(**(DWORD **)lplpdds + 100), extLock, (void **)&pLock, "Lock(S)");
+ // IDirectDrawSurface::Unlock
+ if (dxversion < 4)
+ SetHook((void *)(**(DWORD **)lplpdds + 128), extUnlock1, (void **)&pUnlock1, "Unlock(S1)");
+ else
+ SetHook((void *)(**(DWORD **)lplpdds + 128), extUnlock4, (void **)&pUnlock4, "Unlock(S4)");
+ }
+
+ if (!(dxw.dwTFlags & OUTPROXYTRACE)) return;
+
+ // Just proxed ...
+
+ // IDirectDrawSurface::AddRef
+ SetHook((void *)(**(DWORD **)lplpdds + 4), extAddRefSProxy, (void **)&pAddRefS, "AddRef(S)");
+ // IDirectDrawSurface::AddOverlayDirtyRect
+ SetHook((void *)(**(DWORD **)lplpdds + 16), extAddOverlayDirtyRectProxy, (void **)&pAddOverlayDirtyRect, "AddOverlayDirtyRect(S)");
+ // IDirectDrawSurface::BltBatch
+ SetHook((void *)(**(DWORD **)lplpdds + 24), extBltBatchProxy, (void **)&pBltBatch, "BltBatch(S)");
+ // IDirectDrawSurface::EnumOverlayZOrders
+ SetHook((void *)(**(DWORD **)lplpdds + 40), extEnumOverlayZOrdersProxy, (void **)&pEnumOverlayZOrders, "EnumOverlayZOrders(S)");
+ // IDirectDrawSurface::GetBltStatus
+ SetHook((void *)(**(DWORD **)lplpdds + 52), extGetBltStatusProxy, (void **)&pGetBltStatus, "GetBltStatus(S)");
+ // IDirectDrawSurface::GetClipper
+ SetHook((void *)(**(DWORD **)lplpdds + 60), extGetClipperProxy, (void **)&pGetClipper, "GetClipper(S)");
+ // IDirectDrawSurface::GetFlipStatus
+ SetHook((void *)(**(DWORD **)lplpdds + 72), extGetFlipStatusProxy, (void **)&pGetFlipStatus, "GetFlipStatus(S)");
+ // IDirectDrawSurface::GetOverlayPosition
+ SetHook((void *)(**(DWORD **)lplpdds + 76), extGetOverlayPositionProxy, (void **)&pGetOverlayPosition, "GetOverlayPosition(S)");
+ // IDirectDrawSurface::IsLost
+ SetHook((void *)(**(DWORD **)lplpdds + 96), extIsLostProxy, (void **)&pIsLost, "IsLost(S)");
+ // IDirectDrawSurface::Restore
+ SetHook((void *)(**(DWORD **)lplpdds + 108), extRestoreProxy, (void **)&pRestore, "Restore(S)");
+ // IDirectDrawSurface::SetOverlayPosition
+ SetHook((void *)(**(DWORD **)lplpdds + 120), extSetOverlayPositionProxy, (void **)&pSetOverlayPosition, "SetOverlayPosition(S)");
+ // IDirectDrawSurface::UpdateOverlay
+ SetHook((void *)(**(DWORD **)lplpdds + 132), extUpdateOverlayProxy, (void **)&pUpdateOverlay, "UpdateOverlay(S)");
+ // IDirectDrawSurface::UpdateOverlayDisplay
+ SetHook((void *)(**(DWORD **)lplpdds + 136), extUpdateOverlayDisplayProxy, (void **)&pUpdateOverlayDisplay, "UpdateOverlayDisplay(S)");
+ // IDirectDrawSurface::UpdateOverlayZOrder
+ SetHook((void *)(**(DWORD **)lplpdds + 140), extUpdateOverlayZOrderProxy, (void **)&pUpdateOverlayZOrder, "UpdateOverlayZOrder(S)");
+ if (!(dxw.dwFlags1 & (EMULATESURFACE|EMULATEBUFFER))){
+ // IDirectDrawSurface::Lock
+ SetHook((void *)(**(DWORD **)lplpdds + 100), extLock, (void **)&pLock, "Lock(S)");
+ // IDirectDrawSurface::Unlock
+ if (dxversion < 4)
+ SetHook((void *)(**(DWORD **)lplpdds + 128), extUnlock1, (void **)&pUnlock1, "Unlock(S)");
+ else
+ SetHook((void *)(**(DWORD **)lplpdds + 128), extUnlock4, (void **)&pUnlock4, "Unlock(S)");
+ }
+}
+
+static void HookDDSurfaceGeneric(LPDIRECTDRAWSURFACE *lplpdds, int dxversion)
+{
+ OutTraceD("Hooking surface as generic dds=%x dxversion=%d thread_id=%x\n",
+ *lplpdds, dxversion, GetCurrentThreadId());
+
+ // IDirectDrawSurface::Release
+ SetHook((void *)(**(DWORD **)lplpdds + 8), extReleaseS, (void **)&pReleaseS, "Release(S)");
+ // IDirectDrawSurface::Flip
+ SetHook((void *)(**(DWORD **)lplpdds + 44), extFlip, (void **)&pFlip, "Flip(S)");
+ // IDirectDrawSurface::Blt
+ SetHook((void *)(**(DWORD **)lplpdds + 20), extBlt, (void **)&pBlt, "Blt(S)");
+ // IDirectDrawSurface::BltFast
+ SetHook((void *)(**(DWORD **)lplpdds + 28), extBltFast, (void **)&pBltFast, "BltFast(S)");
+ // IDirectDrawSurface::DeleteAttachedSurface
+ SetHook((void *)(**(DWORD **)lplpdds + 32), extDeleteAttachedSurface, (void **)&pDeleteAttachedSurface, "DeleteAttachedSurface(S)");
+ // IDirectDrawSurface::GetCaps
+ switch(dxversion) {
+ case 1:
+ SetHook((void *)(**(DWORD **)lplpdds + 56), extGetCaps1S, (void **)&pGetCaps1S, "GetCaps(S1)");
+ break;
+ case 2:
+ SetHook((void *)(**(DWORD **)lplpdds + 56), extGetCaps2S, (void **)&pGetCaps2S, "GetCaps(S2)");
+ break;
+ case 3:
+ SetHook((void *)(**(DWORD **)lplpdds + 56), extGetCaps3S, (void **)&pGetCaps3S, "GetCaps(S3)");
+ break;
+ case 4:
+ SetHook((void *)(**(DWORD **)lplpdds + 56), extGetCaps4S, (void **)&pGetCaps4S, "GetCaps(S4)");
+ break;
+ case 7:
+ SetHook((void *)(**(DWORD **)lplpdds + 56), extGetCaps7S, (void **)&pGetCaps7S, "GetCaps(S7)");
+ break;
+ }
+ // IDirectDrawSurface::GetSurfaceDesc
+ if (dxversion < 4) {
+ SetHook((void *)(**(DWORD **)lplpdds + 88), extGetSurfaceDesc1, (void **)&pGetSurfaceDesc1, "GetSurfaceDesc(S1)");
+ }
+ else {
+ SetHook((void *)(**(DWORD **)lplpdds + 88), extGetSurfaceDesc2, (void **)&pGetSurfaceDesc4, "GetSurfaceDesc(S4)");
+ }
+ // IDirectDrawSurface::ReleaseDC
+ SetHook((void *)(**(DWORD **)lplpdds + 104), extReleaseDC, (void **)&pReleaseDC, "ReleaseDC(S)");
+
+ if (!(dxw.dwTFlags & OUTPROXYTRACE)) return;
+
+ // just proxed ....
+
+ // IDirectDrawSurface::QueryInterface
+ SetHook((void *)(**(DWORD **)lplpdds), extQueryInterfaceS, (void **)&pQueryInterfaceS, "QueryInterface(S)");
+ // IDirectDrawSurface::AddRef
+ SetHook((void *)(**(DWORD **)lplpdds + 4), extAddRefSProxy, (void **)&pAddRefS, "AddRef(S)");
+ // IDirectDrawSurface::AddAttachedSurface
+ SetHook((void *)(**(DWORD **)lplpdds + 12), extAddAttachedSurface, (void **)&pAddAttachedSurface, "AddAttachedSurface(S)");
+ // IDirectDrawSurface::AddOverlayDirtyRect
+ SetHook((void *)(**(DWORD **)lplpdds + 16), extAddOverlayDirtyRectProxy, (void **)&pAddOverlayDirtyRect, "AddOverlayDirtyRect(S)");
+ // IDirectDrawSurface::BltBatch
+ SetHook((void *)(**(DWORD **)lplpdds + 24), extBltBatchProxy, (void **)&pBltBatch, "BltBatch(S)");
+ // IDirectDrawSurface::GetAttachedSurface
+ switch(dxversion) {
+ case 1:
+ case 2:
+ SetHook((void *)(**(DWORD **)lplpdds + 48), extGetAttachedSurface1Proxy, (void **)&pGetAttachedSurface1, "GetAttachedSurface(S1)");
+ break;
+ case 3:
+ SetHook((void *)(**(DWORD **)lplpdds + 48), extGetAttachedSurface3Proxy, (void **)&pGetAttachedSurface3, "GetAttachedSurface(S3)");
+ break;
+ case 4:
+ SetHook((void *)(**(DWORD **)lplpdds + 48), extGetAttachedSurface4Proxy, (void **)&pGetAttachedSurface4, "GetAttachedSurface(S4)");
+ break;
+ case 7:
+ SetHook((void *)(**(DWORD **)lplpdds + 48), extGetAttachedSurface7Proxy, (void **)&pGetAttachedSurface7, "GetAttachedSurface(S7)");
+ break;
+ }
+ // IDirectDrawSurface::EnumAttachedSurfaces
+ SetHook((void *)(**(DWORD **)lplpdds + 36), extEnumAttachedSurfaces, (void **)&pEnumAttachedSurfaces, "EnumAttachedSurfaces(S)");
+ // IDirectDrawSurface::EnumOverlayZOrders
+ SetHook((void *)(**(DWORD **)lplpdds + 40), extEnumOverlayZOrdersProxy, (void **)&pEnumOverlayZOrders, "EnumOverlayZOrders(S)");
+ // IDirectDrawSurface::GetBltStatus
+ SetHook((void *)(**(DWORD **)lplpdds + 52), extGetBltStatusProxy, (void **)&pGetBltStatus, "GetBltStatus(S)");
+ // IDirectDrawSurface::GetClipper
+ SetHook((void *)(**(DWORD **)lplpdds + 60), extGetClipperProxy, (void **)&pGetClipper, "GetClipper(S)");
+ // IDirectDrawSurface::GetFlipStatus
+ SetHook((void *)(**(DWORD **)lplpdds + 72), extGetFlipStatusProxy, (void **)&pGetFlipStatus, "GetFlipStatus(S)");
+ // IDirectDrawSurface::GetOverlayPosition
+ SetHook((void *)(**(DWORD **)lplpdds + 76), extGetOverlayPositionProxy, (void **)&pGetOverlayPosition, "GetOverlayPosition(S)");
+ // IDirectDrawSurface::IsLost
+ SetHook((void *)(**(DWORD **)lplpdds + 96), extIsLostProxy, (void **)&pIsLost, "IsLost(S)");
+ // IDirectDrawSurface::Lock
+ SetHook((void *)(**(DWORD **)lplpdds + 100), extLock, (void **)&pLock, "Lock(S)");
+ // IDirectDrawSurface::Restore
+ SetHook((void *)(**(DWORD **)lplpdds + 108), extRestoreProxy, (void **)&pRestore, "Restore(S)");
+ // IDirectDrawSurface::SetOverlayPosition
+ SetHook((void *)(**(DWORD **)lplpdds + 120), extSetOverlayPositionProxy, (void **)&pSetOverlayPosition, "SetOverlayPosition(S)");
+ // IDirectDrawSurface::Unlock
+ if (dxversion < 4)
+ SetHook((void *)(**(DWORD **)lplpdds + 128), extUnlock1, (void **)&pUnlock1, "Unlock(S1)");
+ else
+ SetHook((void *)(**(DWORD **)lplpdds + 128), extUnlock4, (void **)&pUnlock4, "Unlock(S4)");
+ // IDirectDrawSurface::UpdateOverlay
+ SetHook((void *)(**(DWORD **)lplpdds + 132), extUpdateOverlayProxy, (void **)&pUpdateOverlay, "UpdateOverlay(S)");
+ // IDirectDrawSurface::UpdateOverlayDisplay
+ SetHook((void *)(**(DWORD **)lplpdds + 136), extUpdateOverlayDisplayProxy, (void **)&pUpdateOverlayDisplay, "UpdateOverlayDisplay(S)");
+ // IDirectDrawSurface::UpdateOverlayZOrder
+ SetHook((void *)(**(DWORD **)lplpdds + 140), extUpdateOverlayZOrderProxy, (void **)&pUpdateOverlayZOrder, "UpdateOverlayZOrder(S)");
+}
+
+static void RenewClipper(LPDIRECTDRAW lpdd, LPDIRECTDRAWSURFACE lpdds)
+{
+ HRESULT res;
+
+ return;
+
+ if (lpDDC) lpDDC->Release();
+ res=lpdd->CreateClipper(0, &lpDDC, NULL);
+ if(res) OutTraceE("CreateSurface: CreateClipper ERROR: lpdd=%x res=%x(%s) at %d\n", lpdd, res, ExplainDDError(res), __LINE__);
+ //HookDDClipper(&lpDDC);
+ res=lpDDC->SetHWnd(0, dxw.GethWnd());
+ if(res) OutTraceE("CreateSurface: SetHWnd ERROR: hWnd=%x res=%x(%s) at %d\n", dxw.GethWnd(), res, ExplainDDError(res), __LINE__);
+ res=lpdds->SetClipper(lpDDC);
+ //res=(*pSetClipper)(lpdds, lpDDC);
+ if(res) OutTraceE("CreateSurface: SetClipper ERROR: lpdds=%x res=%x(%s) at %d\n", lpdds, res, ExplainDDError(res), __LINE__);
+ return;
+}
+
+/* ------------------------------------------------------------------------------ */
+// directdraw method hooks
+/* ------------------------------------------------------------------------------ */
+
+HRESULT WINAPI extGetCapsD(LPDIRECTDRAW lpdd, LPDDCAPS c1, LPDDCAPS c2)
+{
+ HRESULT res;
+ OutTraceD("GetCaps(D): PROXED lpdd=%x\n", lpdd);
+ res=(*pGetCapsD)(lpdd, c1, c2);
+ if(res)
+ OutTraceE("GetCaps(D): ERROR res=%x(%s)\n", res, ExplainDDError(res));
+ else {
+ OutTraceD("GetCaps(D): ");
+ if (c1) OutTraceD("hwcaps=%x(%s) ", c1->ddsCaps.dwCaps, ExplainDDSCaps(c1->ddsCaps.dwCaps));
+ if (c2) OutTraceD("swcaps=%x(%s) ", c2->ddsCaps.dwCaps, ExplainDDSCaps(c2->ddsCaps.dwCaps));
+ OutTraceD("\n");
+ }
+
+ // GHO TRY
+ // tricky: it seems that this DD method is called using an un-hooked directdraw handle....
+ lpDD=lpdd;
+
+ return res;
+}
+
+HRESULT WINAPI extDirectDrawCreate(GUID FAR *lpguid, LPDIRECTDRAW FAR *lplpdd, IUnknown FAR *pu)
+{
+ HRESULT res;
+
+ OutTraceD("DirectDrawCreate: guid=%x(%s)\n", lpguid, ExplainGUID(lpguid));
+
+ if(!pDirectDrawCreate){ // not hooked yet....
+ HINSTANCE hinst;
+ hinst = LoadLibrary("ddraw.dll");
+ pDirectDrawCreate =
+ (DirectDrawCreate_Type)GetProcAddress(hinst, "DirectDrawCreate");
+ if(pDirectDrawCreate)
+ HookAPI(NULL, "ddraw.dll", pDirectDrawCreate, "DirectDrawCreate", extDirectDrawCreate);
+ else{
+ char sMsg[81];
+ sprintf_s(sMsg, 80, "DirectDrawCreate hook failed: error=%d\n", GetLastError());
+ OutTraceD(sMsg);
+ if(IsAssertEnabled) MessageBox(0, sMsg, "Hook", MB_OK | MB_ICONEXCLAMATION);
+ return DDERR_GENERIC; // is there a better one?
+ }
+ }
+
+ res = (*pDirectDrawCreate)(lpguid, lplpdd, pu);
+ if(res) {
+ OutTraceE("DirectDrawCreate: ERROR res=%x(%s)\n", res, ExplainDDError(res));
+ return res;
+ }
+
+ dxw.dwDDVersion=1;
+ char *mode;
+ switch ((DWORD)lpguid){
+ case 0: mode="NULL"; break;
+ case DDCREATE_HARDWAREONLY: mode="DDCREATE_HARDWAREONLY"; break;
+ case DDCREATE_EMULATIONONLY: mode="DDCREATE_EMULATIONONLY"; break;
+ default:
+ switch (*(DWORD *)lpguid){
+ case 0x6C14DB80: dxw.dwDDVersion=1; mode="IID_IDirectDraw"; break;
+ case 0xB3A6F3E0: dxw.dwDDVersion=2; mode="IID_IDirectDraw2"; break;
+ case 0x9c59509a: dxw.dwDDVersion=4; mode="IID_IDirectDraw4"; break;
+ case 0x15e65ec0: dxw.dwDDVersion=7; mode="IID_IDirectDraw7"; break;
+ default: mode="unknown"; break;
+ }
+ break;
+ }
+ OutTraceD("DirectDrawCreate: lpdd=%x guid=%s DDVersion=%d\n", *lplpdd, mode, dxw.dwDDVersion);
+
+ HookDDSession(lplpdd, dxw.dwDDVersion);
+
+ // added v2.1.44
+ lpDD = *lplpdd;
+ return 0;
+}
+
+/* ------------------------------------------------------------------------------ */
+// CleanRect:
+// takes care of a corrupted RECT struct where some elements are not valid pointers.
+// In this case, the whole RECT * variable is set to NULL, a value that is interpreted
+// by directdraw functions as the whole surface area.
+/* ------------------------------------------------------------------------------ */
+
+static void CleanRect(RECT **lprect, int line)
+{
+ __try {
+ // normally unharmful statements
+ if(*lprect){
+ int i;
+ i=(*lprect)->bottom;
+ i=(*lprect)->top;
+ i=(*lprect)->left;
+ i=(*lprect)->right;
+ }
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER){
+ OutTraceE("Rectangle exception caught at %d: invalid RECT\n", __LINE__);
+ if(IsAssertEnabled) MessageBox(0, "Rectangle exception", "CleanRect", MB_OK | MB_ICONEXCLAMATION);
+ *lprect=NULL;
+ }
+}
+
+HRESULT WINAPI extDirectDrawCreateEx(GUID FAR *lpguid,
+ LPDIRECTDRAW FAR *lplpdd, REFIID iid, IUnknown FAR *pu)
+{
+ HRESULT res;
+ OutTraceD("DirectDrawCreateEx: guid=%x(%s) refiid=%x\n", lpguid, ExplainGUID(lpguid), iid);
+
+ // v2.1.70: auto-hooking (just in case...)
+ if(!pDirectDrawCreateEx){ // not hooked yet....
+ HINSTANCE hinst;
+ hinst = LoadLibrary("ddraw.dll");
+ if(!hinst){
+ OutTraceE("LoadLibrary ERROR err=%d at %d\n", GetLastError(), __LINE__);
+ }
+ pDirectDrawCreateEx =
+ (DirectDrawCreateEx_Type)GetProcAddress(hinst, "DirectDrawCreateEx");
+ if(pDirectDrawCreateEx)
+ HookAPI(NULL, "ddraw.dll", pDirectDrawCreateEx, "DirectDrawCreateEx", extDirectDrawCreateEx);
+ else{
+ char sMsg[81];
+ sprintf_s(sMsg, 80, "DirectDrawCreateEx hook failed: error=%d\n", GetLastError());
+ OutTraceD(sMsg);
+ if(IsAssertEnabled) MessageBox(0, sMsg, "Hook", MB_OK | MB_ICONEXCLAMATION);
+ return DDERR_GENERIC; // is there a better one?
+ }
+ }
+
+ res = (*pDirectDrawCreateEx)(lpguid, lplpdd, iid, pu);
+ if (res){
+ OutTraceD("DirectDrawCreateEx: res=%x(%s)\n",res, ExplainDDError(res));
+ return res;
+ }
+
+ dxw.dwDDVersion=7;
+ char *mode;
+ switch ((DWORD)lpguid){
+ case 0: mode="NULL"; break;
+ case DDCREATE_HARDWAREONLY: mode="DDCREATE_HARDWAREONLY"; break;
+ case DDCREATE_EMULATIONONLY: mode="DDCREATE_EMULATIONONLY"; break;
+ default:
+ switch (*(DWORD *)lpguid){
+ case 0x6C14DB80: dxw.dwDDVersion=1; mode="IID_IDirectDraw"; break;
+ case 0xB3A6F3E0: dxw.dwDDVersion=2; mode="IID_IDirectDraw2"; break;
+ case 0x9c59509a: dxw.dwDDVersion=4; mode="IID_IDirectDraw4"; break;
+ case 0x15e65ec0: dxw.dwDDVersion=7; mode="IID_IDirectDraw7"; break;
+ default: mode="unknown"; break;
+ }
+ break;
+ }
+ OutTraceD("DirectDrawCreateEx: lpdd=%x guid=%s DDVersion=%d\n", *lplpdd, mode, dxw.dwDDVersion);
+
+ HookDDSession(lplpdd,dxw.dwDDVersion);
+
+ // added v2.1.44
+ lpDD = *lplpdd;
+ return 0;
+}
+
+HRESULT WINAPI extQueryInterfaceD(void *lpdd, REFIID riid, LPVOID *obp)
+{
+ HRESULT res;
+ unsigned int dwLocalDDVersion;
+
+ res = (*pQueryInterfaceD)(lpdd, riid, obp);
+ OutTraceD("QueryInterface(D): lpdd=%x REFIID=%x obp=%x ret=%x at %d\n",
+ lpdd, riid.Data1, *obp, res, __LINE__);
+
+ if(res) return res;
+
+ dwLocalDDVersion=0;
+ switch(riid.Data1){
+ case 0x6C14DB80: //DirectDraw1
+ dwLocalDDVersion = 1;
+ break;
+ case 0xB3A6F3E0: //DirectDraw2
+ dwLocalDDVersion = 2;
+ break;
+ case 0x9c59509a: //DirectDraw4
+ dwLocalDDVersion = 4;
+ break;
+ case 0x15e65ec0: //DirectDraw7
+ dwLocalDDVersion = 7;
+ break;
+ }
+
+ if (! *obp) {
+ OutTraceD("QueryInterface(D): Interface for DX version %d not found\n", dwLocalDDVersion);
+ return(0);
+ }
+
+ if (dwLocalDDVersion > dxw.dwMaxDDVersion) {
+ *obp = NULL;
+ OutTraceD("QueryInterface(D): lpdd=%x REFIID=%x obp=(NULL) ret=%x at %d\n",
+ lpdd, riid.Data1, res, __LINE__);
+ return(0);
+ }
+
+ switch (dwLocalDDVersion){
+ case 1: // you never know ....
+ case 2:
+ case 4:
+ // it's not supposed to be written for DDVersion==7, but it works ....
+ case 7:
+ dxw.dwDDVersion=dwLocalDDVersion;
+ HookDDSession((LPDIRECTDRAW *)obp, dxw.dwDDVersion);
+
+ break;
+ }
+
+ OutTraceD("QueryInterface(D): lpdd=%x REFIID=%x obp=%x DDVersion=%d ret=0\n",
+ lpdd, riid.Data1, *obp, dxw.dwDDVersion);
+
+ return 0;
+}
+
+HRESULT WINAPI extQueryInterfaceS(void *lpdds, REFIID riid, LPVOID *obp)
+{
+ HRESULT res;
+ BOOL IsPrim;
+ unsigned int dwLocalDDVersion;
+
+ IsPrim=dxw.IsAPrimarySurface((LPDIRECTDRAWSURFACE)lpdds);
+
+ dwLocalDDVersion=0;
+ switch(riid.Data1){
+ case 0x6C14DB81:
+ dwLocalDDVersion = 1;
+ break;
+ case 0x57805885: //DDSurface2 - WIP (Dark Reign)
+ dwLocalDDVersion = 2;
+ break;
+ case 0xDA044E00: //DDSurface3
+ dwLocalDDVersion = 3;
+ break;
+ case 0x0B2B8630:
+ dwLocalDDVersion = 4;
+ break;
+ case 0x06675a80:
+ dwLocalDDVersion = 7;
+ break;
+ }
+
+ if (dwLocalDDVersion > dxw.dwMaxDDVersion) {
+ *obp = NULL;
+ OutTraceD("QueryInterface(S): DDVersion=%d SUPPRESSED lpdds=%x(%s) REFIID=%x obp=(NULL) ret=0 at %d\n",
+ dwLocalDDVersion, lpdds, IsPrim?"":"(PRIM)", riid.Data1, __LINE__);
+ return(0);
+ }
+
+ res = (*pQueryInterfaceS)(lpdds, riid, obp);
+
+ if(res) // added trace
+ {
+ OutTraceD("QueryInterface(S): ERROR lpdds=%x%s REFIID=%x obp=%x ret=%x(%s) at %d\n",
+ lpdds, IsPrim?"(PRIM)":"", riid.Data1, *obp, res, ExplainDDError(res), __LINE__);
+ return res;
+ }
+
+ if (! *obp) {
+ OutTraceD("QueryInterface(S): Interface for DX version %d not found\n", dwLocalDDVersion);
+ return(0);
+ }
+
+ // added trace
+ OutTraceD("QueryInterface(S): lpdds=%x%s REFIID=%x obp=%x DDVersion=%d ret=0\n",
+ lpdds, IsPrim?"(PRIM)":"", riid.Data1, *obp, dwLocalDDVersion);
+
+ switch (dwLocalDDVersion){
+ case 1: // added for The Sims
+ case 2:
+ case 3:
+ case 4:
+ case 7:
+
+ dxw.dwDDVersion=dwLocalDDVersion;
+
+ if(IsPrim){
+ OutTraceD("QueryInterface(S): primary=%x new=%x\n", lpdds, *obp);
+ dxw.MarkPrimarySurface((LPDIRECTDRAWSURFACE)*obp);
+ HookDDSurfacePrim((LPDIRECTDRAWSURFACE *)obp, dxw.dwDDVersion);
+ }
+ else{
+ dxw.UnmarkPrimarySurface((LPDIRECTDRAWSURFACE)*obp);
+ HookDDSurfaceGeneric((LPDIRECTDRAWSURFACE *)obp, dxw.dwDDVersion);
+ }
+
+ break;
+ }
+
+ return 0;
+}
+
+HRESULT WINAPI extSetDisplayMode(int version, LPDIRECTDRAW lpdd,
+ DWORD dwwidth, DWORD dwheight, DWORD dwbpp, DWORD dwrefreshrate, DWORD dwflags)
+{
+ DDSURFACEDESC2 ddsd;
+ HRESULT res = 0;
+
+ if(IsTraceD){
+ OutTrace("SetDisplayMode: version=%d dwWidth=%i dwHeight=%i dwBPP=%i",
+ version, dwwidth, dwheight, dwbpp);
+ if (version==2)
+ OutTrace(" dwRefresh=%i dwFlags=%x\n", dwrefreshrate, dwflags);
+ else
+ OutTrace("\n");
+ }
+
+ dxw.SetScreenSize(dwwidth, dwheight);
+ GetHookInfo()->Height=(short)dxw.GetScreenHeight();
+ GetHookInfo()->Width=(short)dxw.GetScreenWidth();
+ AdjustWindowFrame(dxw.GethWnd(), dwwidth, dwheight);
+
+ if(dxw.dwFlags1 & EMULATESURFACE){
+ dxw.VirtualPixelFormat.dwRGBBitCount = dwbpp;
+ dwbpp = dxw.ActualPixelFormat.dwRGBBitCount;
+ SetBltTransformations();
+ OutTraceD("SetDisplayMode: mode=EMULATESURFACE EmuBPP=%d ActBPP=%d\n", dxw.VirtualPixelFormat.dwRGBBitCount, dxw.ActualPixelFormat.dwRGBBitCount);
+ }
+ else {
+ OutTraceD("SetDisplayMode: mode=STANDARD BPP=%d\n", dwbpp);
+ dxw.ActualPixelFormat.dwRGBBitCount = dwbpp;
+ }
+
+ ZeroMemory(&ddsd, sizeof(ddsd));
+ ddsd.dwSize = Set_dwSize_From_DDraw(lpdd);
+ ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_REFRESHRATE;
+ ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
+ ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
+
+ (*pGetDisplayMode)(lpdd, (LPDDSURFACEDESC)&ddsd);
+ if(ddsd.ddpfPixelFormat.dwRGBBitCount != dwbpp){
+ OutTraceD("SetDisplayMode: fixing colordepth current=%d required=%d size=(%dx%d)\n",
+ ddsd.ddpfPixelFormat.dwRGBBitCount, dwbpp, ddsd.dwWidth, ddsd.dwHeight);
+ if (version==1)
+ res = (*pSetDisplayMode1)(lpdd, ddsd.dwWidth, ddsd.dwHeight, dwbpp);
+ else
+ res = (*pSetDisplayMode2)(lpdd, ddsd.dwWidth, ddsd.dwHeight, dwbpp, ddsd.dwRefreshRate, 0);
+ }
+
+ return 0;
+}
+
+HRESULT WINAPI extSetDisplayMode2(LPDIRECTDRAW lpdd,
+ DWORD dwwidth, DWORD dwheight, DWORD dwbpp, DWORD dwrefreshrate, DWORD dwflags)
+{
+ return extSetDisplayMode(2, lpdd, dwwidth, dwheight, dwbpp, dwrefreshrate, dwflags);
+}
+
+HRESULT WINAPI extSetDisplayMode1(LPDIRECTDRAW lpdd,
+ DWORD dwwidth, DWORD dwheight, DWORD dwbpp)
+{
+ return extSetDisplayMode(1, lpdd, dwwidth, dwheight, dwbpp, 0, 0);
+}
+
+HRESULT WINAPI extGetDisplayMode(LPDIRECTDRAW lpdd, LPDDSURFACEDESC lpddsd)
+{
+ OutTraceD("GetDisplayMode\n");
+
+ (*pGetDisplayMode)(lpdd, lpddsd);
+ if(dxw.dwFlags1 & EMULATESURFACE) SetPixFmt((LPDDSURFACEDESC2)lpddsd);
+ lpddsd->dwWidth = dxw.GetScreenWidth();
+ lpddsd->dwHeight = dxw.GetScreenHeight();
+
+ // v2.1.96: fake screen color depth
+ if(dxw.dwFlags2 & INIT8BPP|INIT16BPP){
+ if(dxw.dwFlags2 & INIT8BPP) FixPixelFormat(8, &lpddsd->ddpfPixelFormat);
+ if(dxw.dwFlags2 & INIT16BPP) FixPixelFormat(16, &lpddsd->ddpfPixelFormat);
+ OutTraceD("GetDisplayMode: fix RGBBitCount=%d\n", lpddsd->ddpfPixelFormat.dwRGBBitCount);
+ }
+
+ OutTraceD("GetDisplayMode: returning WxH=(%dx%d) PixelFormat Flags=%x(%s) RGBBitCount=%d RGBAmask=(%x,%x,%x,%x) Caps=%x(%s)\n",
+ lpddsd->dwWidth, lpddsd->dwHeight,
+ lpddsd->ddpfPixelFormat.dwFlags, ExplainPixelFormatFlags(lpddsd->ddpfPixelFormat.dwFlags),
+ lpddsd->ddpfPixelFormat.dwRGBBitCount,
+ lpddsd->ddpfPixelFormat.dwRBitMask, lpddsd->ddpfPixelFormat.dwGBitMask, lpddsd->ddpfPixelFormat.dwBBitMask,
+ lpddsd->ddpfPixelFormat.dwRGBAlphaBitMask,
+ lpddsd->ddsCaps.dwCaps, ExplainDDSCaps(lpddsd->ddsCaps.dwCaps));
+
+ return 0;
+}
+
+void FixWindowFrame(HWND hwnd)
+{
+ LONG nOldStyle;
+
+ OutTraceD("FixWindowFrame: hwnd=%x\n", hwnd);
+
+ nOldStyle=(*pGetWindowLong)(hwnd, GWL_STYLE);
+ if (!nOldStyle){
+ OutTraceE("GetWindowLong ERROR %d at %d\n",GetLastError(),__LINE__);
+ return;
+ }
+
+ OutTraceD("FixWindowFrame: style=%x(%s)\n",nOldStyle,ExplainStyle(nOldStyle));
+
+ // fix style
+ if (!(*pSetWindowLong)(hwnd, GWL_STYLE, WS_OVERLAPPEDWINDOW)){
+ OutTraceE("SetWindowLong ERROR %d at %d\n",GetLastError(),__LINE__);
+ return;
+ }
+ // fix exstyle
+ if (!(*pSetWindowLong)(hwnd, GWL_EXSTYLE, 0)){
+ OutTraceE("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;
+}
+
+HRESULT WINAPI extSetCooperativeLevel(void *lpdd, HWND hwnd, DWORD dwflags)
+{
+ HRESULT res;
+ HWND hDesktop;
+
+ OutTraceD("SetCooperativeLevel: hwnd=%x dwFlags=%x(%s)\n",
+ hwnd, dwflags,ExplainCoopFlags(dwflags));
+
+ InitDDScreenParameters((LPDIRECTDRAW)lpdd);
+
+ // WARN: Tomb Raider 4 demo is setting cooperative level against hwnd 0 (desktop)
+ // so in this case better use the registered hWnd value. Same as GP500, who uses
+ // the desktop window handle.
+ // v2.1.82 fix:
+ hDesktop=(*pGetDesktopWindow)();
+ if ((hwnd==0) || (hwnd==hDesktop)) {
+ OutTraceD("SetCooperativeLevel: detected desktop hwnd=%x redirected to %x\n", hwnd, dxw.GethWnd());
+ hwnd=dxw.GethWnd();
+ // this fixes the blocks on "Tomb Raider IV" !!!!
+ if(dxw.dwFlags1 & FIXPARENTWIN) hwnd=dxw.hParentWnd;
+ }
+
+ if (dwflags & DDSCL_FULLSCREEN){
+ dxw.SetFullScreen(TRUE);
+ dwflags &= ~(DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE | DDSCL_ALLOWMODEX);
+ dwflags |= DDSCL_NORMAL;
+ //res=(*pSetCooperativeLevel)(lpdd, hwnd, DDSCL_NORMAL);
+ res=(*pSetCooperativeLevel)(lpdd, hwnd, dwflags);
+ AdjustWindowFrame(hwnd, dxw.GetScreenWidth(), dxw.GetScreenHeight());
+ //FixWindowFrame(hwnd); //-- incompatible with Microsoft Madness
+ if (dxw.dwFlags1 & FIXWINFRAME) FixWindowFrame(hwnd);
+ }
+ else{
+ dxw.SetFullScreen(FALSE);
+ res=(*pSetCooperativeLevel)(lpdd, hwnd, dwflags);
+ }
+ if(res)
+ OutTraceE("SetCooperativeLevel: ERROR err=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
+
+ GetHookInfo()->IsFullScreen=dxw.IsFullScreen();
+
+ // WARN: GP500 was setting cooperative level against the desktop! This can be partially
+ // intercepted by hooking the GetDesktopWindow() call, but in windowed mode this can't be
+ // done, so better repeat the check here.
+
+ if ((res==DD_OK) && (hwnd!=NULL)){
+ if (hwnd==hDesktop){
+ OutTraceE("SetCooperativeLevel: attempt to work on desktop window\n");
+ }
+ else
+ dxw.SethWnd(hwnd); // save the good one
+ }
+
+ return res;
+}
+
+HRESULT WINAPI extCreateSurfaceEmu(int dxversion, CreateSurface_Type pCreateSurface, LPDIRECTDRAW lpdd, DDSURFACEDESC2 *lpddsd,
+ LPDIRECTDRAWSURFACE *lplpdds, void *pu)
+{
+ HRESULT res;
+ DDSURFACEDESC2 ddsd;
+ LPDIRECTDRAWSURFACE lpDDSPrim;
+ char *pfmt;
+ DWORD CurFlags, CurSize;
+
+ if((lpddsd->dwSize != sizeof(DDSURFACEDESC2)) && (lpddsd->dwSize != sizeof(DDSURFACEDESC))){
+ char sMsg[81];
+ sprintf_s(sMsg,80, "CreateSurface: ASSERT bad dwSize=%d\n", lpddsd->dwSize);
+ OutTraceD(sMsg);
+ if(IsAssertEnabled) MessageBox(0, sMsg, "CreateSurface", MB_OK | MB_ICONEXCLAMATION);
+ return DDERR_INVALIDPARAMS;
+ }
+
+ memset(&ddsd, 0, sizeof(ddsd)); // Clean all
+ memcpy(&ddsd, lpddsd, lpddsd->dwSize); // Copy
+ CurSize = (dxversion < 4) ? sizeof(DDSURFACEDESC) : sizeof(DDSURFACEDESC2);
+ ddsd.dwSize = CurSize;
+
+ if(ddsd.dwFlags & DDSD_CAPS && ddsd.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE){
+ GetHookInfo()->Height=(short)dxw.GetScreenHeight();
+ GetHookInfo()->Width=(short)dxw.GetScreenWidth();
+ GetHookInfo()->ColorDepth=(short)dxw.VirtualPixelFormat.dwRGBBitCount;
+ GetHookInfo()->DXVersion=dxversion;
+ lpServiceDD = lpdd; // v2.1.87
+
+ dxw.dwPrimarySurfaceCaps = ddsd.ddsCaps.dwCaps;
+ dxw.dwBackBufferCount = (ddsd.dwFlags & DDSD_BACKBUFFERCOUNT) ? ddsd.dwBackBufferCount : 0;
+
+ // beware of the different behaviour between older and newer directdraw releases...
+ if(dxversion >= 4){
+ if (lpDDC) while(lpDDC->Release());
+ if (lpDDSEmu_Back) while(lpDDSEmu_Back->Release());
+ if (lpDDSEmu_Prim) while(lpDDSEmu_Prim->Release());
+ if (ddsd.dwFlags & DDSD_BACKBUFFERCOUNT)
+ if (lpDDSBack) while(lpDDSBack->Release());
+ }
+ lpDDC=NULL;
+ lpDDSEmu_Back=NULL;
+ lpDDSEmu_Prim=NULL;
+ if (ddsd.dwFlags & DDSD_BACKBUFFERCOUNT)
+ lpDDSBack=NULL;
+
+ int BBCount=1;
+ if (ddsd.dwFlags & DDSD_BACKBUFFERCOUNT) BBCount=ddsd.dwBackBufferCount;
+ if (BBCount > MAXBACKBUFFERS){
+ char sMsg[81];
+ sprintf_s(sMsg, 80, "CreateSurface: BackBufferCount=%d\n", BBCount);
+ OutTraceD(sMsg);
+ if (IsAssertEnabled) MessageBox(0, sMsg, "CreateSurface", MB_OK | MB_ICONEXCLAMATION);
+ // recover ...
+ dxw.dwBackBufferCount =MAXBACKBUFFERS;
+ BBCount = MAXBACKBUFFERS;
+ }
+
+ // emulated primary surface
+ ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
+ ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
+ if (lpddsd->dwFlags & DDSD_CKDESTBLT) ddsd.dwFlags|=DDSD_CKDESTBLT;
+ if (lpddsd->dwFlags & DDSD_CKDESTOVERLAY) ddsd.dwFlags|=DDSD_CKDESTOVERLAY;
+ if (lpddsd->dwFlags & DDSD_CKSRCBLT) ddsd.dwFlags|=DDSD_CKSRCBLT;
+ if (lpddsd->dwFlags & DDSD_CKSRCOVERLAY) ddsd.dwFlags|=DDSD_CKSRCOVERLAY;
+ ddsd.dwWidth = dxw.GetScreenWidth();
+ ddsd.dwHeight = dxw.GetScreenHeight();
+ pfmt=SetPixFmt(&ddsd);
+ CurFlags=ddsd.dwFlags;
+
+ // create Primary surface
+ DumpSurfaceAttributes((LPDDSURFACEDESC)&ddsd, "[Primary]" , __LINE__);
+ res=(*pCreateSurface)(lpdd, &ddsd, lplpdds, 0);
+ if(res){
+ OutTraceE("CreateSurface ERROR: res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
+ if(res==DDERR_INVALIDPIXELFORMAT) DumpPixFmt(&ddsd);
+ return res;
+ }
+ lpDDSPrim = *lplpdds;
+ OutTraceD("CreateSurface: created PRIMARY DDSPrim=%x\n", lpDDSPrim);
+ dxw.MarkPrimarySurface(*lplpdds);
+ HookDDSurfacePrim(lplpdds, dxversion);
+
+ if (BBCount){
+ // create BackBuffer surface
+ memset(&ddsd, 0, sizeof(ddsd)); // Clean all
+ ddsd.dwSize = CurSize;
+ ddsd.dwFlags = CurFlags;
+ ddsd.ddsCaps.dwCaps=DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
+ ddsd.dwWidth = dxw.GetScreenWidth();
+ ddsd.dwHeight = dxw.GetScreenHeight();
+ pfmt=SetPixFmt(&ddsd);
+ //ddsd.ddsCaps.dwCaps |= DDSCAPS_BACKBUFFER;
+ DumpSurfaceAttributes((LPDDSURFACEDESC)&ddsd, "[Backbuf]" , __LINE__);
+ res=(*pCreateSurface)(lpdd, &ddsd, &lpDDSBack, 0);
+ if(res){
+ OutTraceE("CreateSurface ERROR: res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
+ if(res==DDERR_INVALIDPIXELFORMAT) DumpPixFmt(&ddsd);
+ return res;
+ }
+ //ddsd.ddsCaps.dwCaps &= ~DDSCAPS_BACKBUFFER;
+ OutTraceD("CreateSurface: created BACK DDSBack=%x\n", lpDDSBack);
+ dxw.UnmarkPrimarySurface(lpDDSBack);
+ HookDDSurfaceGeneric(&lpDDSBack, dxversion); // added !!!
+ }
+ FlipChainLength=BBCount;
+ // V2.1.85: tricky !!!!
+ // When a real backbuffer is created, it has a reference to its frontbuffer.
+ // some games (Monopoly 3D) may depend on this setting - i.e. they could close
+ // the exceeding references - so this is better be replicated adding an initial
+ // reference to the zero count.
+ lpDDSBack->AddRef(); // should it be repeated BBCount times????
+
+#if 0
+ // for 8BPP palettized surfaces, connect them to either the ddraw emulated palette or the GDI emulated palette
+ if(ddsd.ddpfPixelFormat.dwRGBBitCount==8){ // use a better condition here....
+ if(lpDDP==NULL){
+ // should link here to the GDI palette? See Hyperblade....
+ dxw.palNumEntries=256;
+ res=(*pCreatePalette)(lpdd, DDPCAPS_ALLOW256|DDPCAPS_8BIT|DDPCAPS_INITIALIZE, dxw.palPalEntry, &lpDDP, NULL);
+ if (res) {
+ OutTraceE("CreateSurface: CreatePalette ERROR res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
+ return res;
+ }
+ }
+ res=(*pSetPalette)(lpDDSBack, lpDDP);
+ if (res) {
+ OutTraceE("CreateSurface: SetPalette ERROR res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
+ return res;
+ }
+ }
+#endif
+
+
+ // rebuild emulated primary surface
+
+ if(lpDDSEmu_Prim==NULL){
+ memset(&ddsd, 0, sizeof(ddsd)); // Clean all
+ ddsd.dwSize = CurSize;
+ ddsd.dwFlags = DDSD_CAPS;
+ ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
+ pfmt=SetPixFmt(&ddsd);
+ DumpSurfaceAttributes((LPDDSURFACEDESC)&ddsd, "[EmuPrim]" , __LINE__);
+ res=(*pCreateSurface)(lpdd, &ddsd, &lpDDSEmu_Prim, 0);
+ if(res==DDERR_PRIMARYSURFACEALREADYEXISTS){
+ OutTraceD("CreateSurface: ASSERT DDSEmu_Prim already exists\n");
+ res=(*pGetGDISurface)(lpdd, &lpDDSEmu_Prim);
+ }
+ if(res){
+ OutTraceE("CreateSurface: CreateSurface ERROR on DDSEmu_Prim res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
+ if(res==DDERR_INVALIDPIXELFORMAT) DumpPixFmt(&ddsd);
+ return res;
+ }
+ OutTraceD("CreateSurface: created new DDSEmu_Prim=%x\n",lpDDSEmu_Prim);
+ InitDSScreenParameters(lpDDSEmu_Prim);
+ }
+
+ if (lpDDC==NULL) RenewClipper(lpdd, lpDDSEmu_Prim);
+
+ dxw.UnmarkPrimarySurface(lpDDSEmu_Prim);
+ // can't hook lpDDSEmu_Prim as generic, since the Flip method is unimplemented for a PRIMARY surface!
+ // better avoid it or hook just useful methods.
+ //if (dxw.dwTFlags & OUTPROXYTRACE) HookDDSurfaceGeneric(&lpDDSEmu_Prim, dxw.dwDDVersion);
+
+ // rebuild emulated primary backbuffer surface
+
+ if(lpDDSEmu_Back==NULL){
+ memset(&ddsd, 0, sizeof(ddsd)); // Clean all
+ ddsd.dwSize = CurSize;
+ ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
+ ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
+ ddsd.dwWidth = dxw.GetScreenWidth();
+ ddsd.dwHeight = dxw.GetScreenHeight();
+ //pfmt=SetPixFmt(&ddsd);
+ DumpSurfaceAttributes((LPDDSURFACEDESC)&ddsd, "[EmuBack]" , __LINE__);
+
+ res=(*pCreateSurface)(lpdd, &ddsd, &lpDDSEmu_Back, 0);
+ if(res){
+ OutTraceE("CreateSurface: CreateSurface ERROR on DDSEmuBack : res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
+ if(res==DDERR_INVALIDPIXELFORMAT) DumpPixFmt(&ddsd);
+ return res;
+ }
+ OutTraceD("CreateSurface: created new DDSEmu_Back=%x\n", lpDDSEmu_Back);
+ }
+
+ dxw.UnmarkPrimarySurface(lpDDSEmu_Back);
+ if (dxw.dwTFlags & OUTPROXYTRACE) HookDDSurfaceGeneric(&lpDDSEmu_Back, dxversion);
+
+ OutTraceD("CreateSurface: created DDSEmu_Prim=%x DDSEmu_Back=%x DDSPrim=%x DDSBack=%x\n",
+ lpDDSEmu_Prim, lpDDSEmu_Back, lpDDSPrim, lpDDSBack);
+
+ // creation of lpDDSHDC service surfae moved to GetDC method
+
+ if(dxw.dwFlags1 & CLIPCURSOR) dxw.SetClipCursor();
+ return 0;
+ }
+
+ // not primary emulated surface ....
+ if(((ddsd.dwFlags & DDSD_WIDTH) && !(ddsd.dwFlags & DDSD_HEIGHT)) ||
+ (ddsd.dwFlags & DDSD_ZBUFFERBITDEPTH) ||
+ (ddsd.dwFlags & DDSD_PIXELFORMAT) ||
+ //((ddsd.dwFlags & DDSD_CAPS) && (ddsd.ddsCaps.dwCaps & DDSCAPS_TEXTURE)) ||
+ // ((ddsd.dwFlags & DDSD_CAPS) && (ddsd.ddsCaps.dwCaps & DDSCAPS_ZBUFFER)) || // v2.02.09
+ ((ddsd.dwFlags & DDSD_CAPS) && (ddsd.ddsCaps.dwCaps & DDSCAPS_3DDEVICE))){
+ // don't alter pixel format
+ //ddsd.dwFlags &= ~DDSD_PIXELFORMAT; // Warhammer Dark Omen
+ pfmt="(none)";
+ }
+ else {
+ // adjust pixel format
+ pfmt="(none)";
+ ddsd.dwFlags |= DDSD_CAPS | DDSD_PIXELFORMAT;
+ ddsd.ddsCaps.dwCaps &= ~DDSCAPS_VIDEOMEMORY;
+ ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY|DDSCAPS_OFFSCREENPLAIN;
+ pfmt=SetPixFmt(&ddsd);
+ }
+
+ DumpSurfaceAttributes((LPDDSURFACEDESC)&ddsd, "[Emu Generic]" , __LINE__);
+ res=(*pCreateSurface)(lpdd, &ddsd, lplpdds, pu);
+ if(res){
+ // v2.1.81: retry on system memory may fix not only the DDERR_OUTOFVIDEOMEMORY
+ // error, but the DDERR_INVALIDPIXELFORMAT (see "The Sims ???")
+ if ((dxw.dwFlags1 & SWITCHVIDEOMEMORY) &&
+ ((res==DDERR_OUTOFVIDEOMEMORY) || (res==DDERR_INVALIDPIXELFORMAT))){
+ OutTraceD("CreateSurface: CreateSurface ERROR err=%x(%s) at %d, retry in SYSTEMMEMORY\n",
+ res, ExplainDDError(res), __LINE__);
+ ddsd.dwFlags |= DDSD_CAPS;
+ ddsd.ddsCaps.dwCaps &= ~DDSCAPS_VIDEOMEMORY;
+ ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
+ DumpSurfaceAttributes((LPDDSURFACEDESC)&ddsd, "[Emu Generic2]" , __LINE__);
+ res=(*pCreateSurface)(lpdd, &ddsd, lplpdds, 0);
+ }
+ }
+ if (res) {
+ OutTraceE("CreateSurface: CreateSurface ERROR res=%x(%s) pfmt=%s at %d\n", res, ExplainDDError(res), pfmt, __LINE__);
+ if(res==DDERR_INVALIDPIXELFORMAT) DumpPixFmt(&ddsd);
+ return res;
+ }
+
+#if 0
+ // for 8BPP palettized surfaces, connect them to either the ddraw emulated palette or the GDI emulated palette
+ if(ddsd.ddpfPixelFormat.dwRGBBitCount==8){ // use a better condition here....
+ if(lpDDP==NULL){
+ // should link here to the GDI palette? See Hyperblade....
+ dxw.palNumEntries=256;
+ res=(*pCreatePalette)(lpdd, DDPCAPS_ALLOW256|DDPCAPS_8BIT|DDPCAPS_INITIALIZE, dxw.palPalEntry, &lpDDP, NULL);
+ if (res) {
+ OutTraceE("CreateSurface: CreatePalette ERROR res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
+ return res;
+ }
+ }
+ res=(*pSetPalette)(*lplpdds, lpDDP);
+ if (res) {
+ OutTraceE("CreateSurface: SetPalette ERROR res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
+ return res;
+ }
+ }
+#endif
+
+ // diagnostic hooks ....
+ HookDDSurfaceGeneric(lplpdds, dxversion);
+ // unmark this as possible primary
+ dxw.UnmarkPrimarySurface(*lplpdds);
+ OutTraceD("CreateSurface: created EMU_GENERIC dds=%x type=%s\n", *lplpdds, pfmt);
+
+ return 0;
+}
+
+HRESULT WINAPI extCreateSurfaceDir(int dxversion, CreateSurface_Type pCreateSurface, LPDIRECTDRAW lpdd, DDSURFACEDESC2 *lpddsd,
+ LPDIRECTDRAWSURFACE *lplpdds, void *pu)
+{
+ HRESULT res;
+ DDSURFACEDESC2 ddsd;
+ LPDIRECTDRAWSURFACE lpDDSPrim;
+ int dwSize;
+
+ memset(&ddsd, 0, sizeof(ddsd)); // Clean all
+ memcpy(&ddsd, lpddsd, lpddsd->dwSize); // Copy
+ dwSize = (dxversion < 4) ? sizeof(DDSURFACEDESC) : sizeof(DDSURFACEDESC2);
+ ddsd.dwSize = dwSize;
+
+ if(ddsd.dwFlags & DDSD_CAPS && ddsd.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE){
+ GetHookInfo()->Height=(short)dxw.GetScreenHeight();
+ GetHookInfo()->Width=(short)dxw.GetScreenWidth();
+ GetHookInfo()->ColorDepth=(short)dxw.VirtualPixelFormat.dwRGBBitCount;
+ GetHookInfo()->DXVersion=dxversion;
+ dxw.dwPrimarySurfaceCaps = ddsd.ddsCaps.dwCaps;
+ dxw.dwBackBufferCount = (ddsd.dwFlags & DDSD_BACKBUFFERCOUNT) ? ddsd.dwBackBufferCount : 0;
+ lpServiceDD = lpdd; // v2.1.87
+
+ // clean up service objects
+ // beware of the different behaviour between older and newer directdraw releases...
+ if(dxversion >= 4){
+ if (lpDDC){
+ __try { while(lpDDC && lpDDC->Release()); }
+ __except(EXCEPTION_EXECUTE_HANDLER){
+ OutTraceD("Release(lpDDC): exception caught at %d\n", __LINE__);
+ lpDDC=NULL;
+ }
+ }
+ if (lpDDSBack){
+ __try { while(lpDDSBack && lpDDSBack->Release()); }
+ __except(EXCEPTION_EXECUTE_HANDLER){
+ OutTraceD("Release(lpDDSBack): exception caught at %d\n", __LINE__);
+ lpDDSBack=NULL;
+ }
+ }
+ }
+ lpDDC=NULL;
+
+ int BBCount=1;
+ if (ddsd.dwFlags & DDSD_BACKBUFFERCOUNT) BBCount=ddsd.dwBackBufferCount;
+ if (BBCount > 0){
+ lpDDSBack=NULL;
+ OutTraceD("CreateSurface: BackBufferCount=%d\n", BBCount);
+ }
+
+ if((dxw.dwFlags1 & EMULATEBUFFER) && lpDDSEmu_Prim){
+ __try { while(lpDDSEmu_Prim && lpDDSEmu_Prim->Release()); }
+ __except(EXCEPTION_EXECUTE_HANDLER){
+ OutTraceD("Release(lpDDSEmu_Prim): exception caught at %d\n", __LINE__);
+ lpDDSEmu_Prim=NULL;
+ }
+ }
+
+ // genuine primary surface
+ ddsd.dwFlags &= ~(DDSD_WIDTH|DDSD_HEIGHT|DDSD_BACKBUFFERCOUNT|DDSD_REFRESHRATE|DDSD_PIXELFORMAT);
+ ddsd.ddsCaps.dwCaps &= ~(DDSCAPS_FLIP | DDSCAPS_COMPLEX);
+ DumpSurfaceAttributes((LPDDSURFACEDESC)&ddsd, "[Dir Primary]" , __LINE__);
+ res = (*pCreateSurface)(lpdd, &ddsd, &lpDDSPrim, pu);
+ if(res){
+ if ((dxw.dwFlags1 & SWITCHVIDEOMEMORY) && (res==DDERR_OUTOFVIDEOMEMORY)){
+ OutTraceD("CreateSurface: CreateSurface DDERR_OUTOFVIDEOMEMORY ERROR at %d, retry in SYSTEMMEMORY\n", __LINE__);
+ ddsd.ddsCaps.dwCaps &= ~DDSCAPS_VIDEOMEMORY; // try ...
+ ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; // try ...
+ res=(*pCreateSurface)(lpdd, &ddsd, lplpdds, 0);
+ }
+ if(res){
+ OutTraceE("CreateSurface: CreateSurface ERROR on DDSPrim res=%x(%s) at %d\n",
+ res, ExplainDDError(res), __LINE__);
+ return res;
+ }
+ }
+
+ if(dxw.dwFlags1 & EMULATEBUFFER){
+ lpDDSEmu_Prim = lpDDSPrim;
+ dxw.UnmarkPrimarySurface(lpDDSEmu_Prim);
+ OutTraceD("CreateSurface: created PRIMARY DDSPrim=%x flags=%x(%s) caps=%x(%s)\n",
+ lpDDSPrim, ddsd.dwFlags, ExplainFlags(ddsd.dwFlags), ddsd.ddsCaps.dwCaps, ExplainDDSCaps(ddsd.ddsCaps.dwCaps));
+ RenewClipper(lpdd, lpDDSEmu_Prim);
+
+ ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
+ // warning: can't create zero sized backbuffer surface !!!!
+ ddsd.dwWidth = dxw.GetScreenWidth();
+ ddsd.dwHeight = dxw.GetScreenHeight();
+ ddsd.ddsCaps.dwCaps = 0;
+ if (dxversion >= 4) ddsd.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN;
+ DumpSurfaceAttributes((LPDDSURFACEDESC)&ddsd, "[Dir FixBuf]" , __LINE__);
+ res=(*pCreateSurface)(lpdd, &ddsd, &lpDDSPrim, 0);
+ if(res){
+ OutTraceE("CreateSurface: ERROR on DDSPrim res=%x(%s) at %d\n",res, ExplainDDError(res), __LINE__);
+ return res;
+ }
+
+ *lplpdds = lpDDSPrim;
+ dxw.MarkPrimarySurface(lpDDSPrim);
+ OutTraceD("CreateSurface: created FIX DDSPrim=%x flags=%x(%s) caps=%x(%s)\n",
+ *lplpdds, ddsd.dwFlags, ExplainFlags(ddsd.dwFlags), ddsd.ddsCaps.dwCaps, ExplainDDSCaps(ddsd.ddsCaps.dwCaps));
+ }
+ else{
+ *lplpdds = lpDDSPrim;
+ dxw.MarkPrimarySurface(lpDDSPrim);
+ OutTraceD("CreateSurface: created PRIMARY DDSPrim=%x flags=%x(%s) caps=%x(%s)\n",
+ *lplpdds, ddsd.dwFlags, ExplainFlags(ddsd.dwFlags), ddsd.ddsCaps.dwCaps, ExplainDDSCaps(ddsd.ddsCaps.dwCaps));
+ RenewClipper(lpdd, lpDDSPrim);
+ }
+
+
+ HookDDSurfacePrim(&lpDDSPrim, dxversion);
+
+ if (!BBCount) return 0;
+ FlipChainLength=BBCount;
+
+ ddsd.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
+ // warning: can't create zero sized backbuffer surface !!!!
+ ddsd.dwWidth = dxw.GetScreenWidth();
+ ddsd.dwHeight = dxw.GetScreenHeight();
+ if (dxw.dwFlags2 & BACKBUFATTACH) {
+ DDSURFACEDESC2 prim;
+ prim.dwSize = dwSize;
+ res=lpDDSPrim->GetSurfaceDesc((DDSURFACEDESC *)&prim);
+ ddsd.dwWidth = prim.dwWidth;
+ ddsd.dwHeight = prim.dwHeight;
+ OutTraceD("BMX FIX: res=%x(%s) wxh=(%dx%d)\n", res, ExplainDDError(res),ddsd.dwWidth, ddsd.dwHeight);
+ }
+
+ // preserve original CAPS....
+ ddsd.ddsCaps.dwCaps &= ~DDSCAPS_PRIMARYSURFACE;
+ if (dxversion >= 4) ddsd.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN;
+ DumpSurfaceAttributes((LPDDSURFACEDESC)&ddsd, "[Dir Backbuf]" , __LINE__);
+ res=(*pCreateSurface)(lpdd, &ddsd, &lpDDSBack, pu);
+ if(res) {
+ if ((dxw.dwFlags1 & SWITCHVIDEOMEMORY) && (res==DDERR_OUTOFVIDEOMEMORY)){
+ OutTraceD("CreateSurface: CreateSurface DDERR_OUTOFVIDEOMEMORY ERROR at %d, retry in SYSTEMMEMORY\n", __LINE__);
+ ddsd.ddsCaps.dwCaps &= ~DDSCAPS_VIDEOMEMORY; // try ...
+ ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; // try ...
+ res=(*pCreateSurface)(lpdd, &ddsd, &lpDDSBack, pu);
+ }
+ if(res){
+ OutTraceE("CreateSurface: CreateSurface ERROR on DDSBack res=%x(%s) caps=%x(%s) at %d\n",
+ res, ExplainDDError(res), ddsd.ddsCaps.dwCaps, ExplainDDSCaps(ddsd.ddsCaps.dwCaps), __LINE__);
+ return res;
+ }
+ }
+ OutTraceD("CreateSurface: created BACK DDSBack=%x flags=%x(%s) caps=%x(%s)\n",
+ lpDDSBack, ddsd.dwFlags, ExplainFlags(ddsd.dwFlags), ddsd.ddsCaps.dwCaps, ExplainDDSCaps(ddsd.ddsCaps.dwCaps));
+
+ HookDDSurfaceGeneric(&lpDDSBack, dxversion);
+ // V2.1.84: tricky !!!!
+ // When a real backbuffer is created, it has a reference to its frontbuffer.
+ // some games (Monopoly 3D) may depend on this setting - i.e. they could close
+ // the exceeding references - so this is better be replicated adding an initial
+ // reference to the zero count.
+ // Should this hold for EMULATED mode as well? Maybe, but Diablo crashes....
+ lpDDSBack->AddRef();
+
+ if(dxw.dwFlags1 & CLIPCURSOR) dxw.SetClipCursor();
+ return 0;
+ }
+
+ //BACKBUFATTACH: needed for Syberia
+ if ((dxw.dwFlags2 & BACKBUFATTACH) && (lpddsd->ddsCaps.dwCaps & DDSCAPS_ZBUFFER)){
+ DDSURFACEDESC2 backbuf;
+ backbuf.dwSize = dwSize;
+ res=lpDDSBack->GetSurfaceDesc((DDSURFACEDESC *)&backbuf);
+ ddsd.dwWidth = backbuf.dwWidth;
+ ddsd.dwHeight = backbuf.dwHeight;
+ }
+
+ DumpSurfaceAttributes((LPDDSURFACEDESC)lpddsd, "[Dir Generic]" , __LINE__);
+ res = (*pCreateSurface)(lpdd, lpddsd, lplpdds, 0);
+ if(res){
+ if ((dxw.dwFlags1 & SWITCHVIDEOMEMORY) && (res==DDERR_OUTOFVIDEOMEMORY)){
+ OutTraceD("CreateSurface ERROR: res=%x(%s) at %d, retry\n", res, ExplainDDError(res), __LINE__);
+ lpddsd->ddsCaps.dwCaps &= ~DDSCAPS_VIDEOMEMORY;
+ lpddsd->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
+ res = (*pCreateSurface)(lpdd, lpddsd, lplpdds, 0);
+ }
+ if(res){
+ OutTraceE("CreateSurface: CreateSurface ERROR res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
+ return res;
+ }
+ }
+ OutTraceD("CreateSurface: created GENERIC surface dds=%x flags=%x(%s) caps=%x(%s)\n",
+ *lplpdds, lpddsd->dwFlags, ExplainFlags(lpddsd->dwFlags), lpddsd->ddsCaps.dwCaps, ExplainDDSCaps(lpddsd->ddsCaps.dwCaps));
+
+ // hooks ....
+ HookDDSurfaceGeneric(lplpdds, dxversion);
+ dxw.UnmarkPrimarySurface(*lplpdds);
+
+ OutTraceD("CreateSurface: created lpdds=%x type=GENUINE Return=%x\n", *lplpdds, res);
+ return res;
+}
+
+HRESULT WINAPI extCreateSurface1(LPDIRECTDRAW lpdd, DDSURFACEDESC *lpddsd, LPDIRECTDRAWSURFACE *lplpdds, void *pu)
+{
+ return extCreateSurface(1, (CreateSurface_Type)pCreateSurface1, lpdd, (DDSURFACEDESC2 *)lpddsd, lplpdds, pu);
+}
+
+HRESULT WINAPI extCreateSurface2(LPDIRECTDRAW lpdd, DDSURFACEDESC *lpddsd, LPDIRECTDRAWSURFACE *lplpdds, void *pu)
+{
+ return extCreateSurface(2, (CreateSurface_Type)pCreateSurface2, lpdd, (DDSURFACEDESC2 *)lpddsd, lplpdds, pu);
+}
+
+HRESULT WINAPI extCreateSurface4(LPDIRECTDRAW lpdd, DDSURFACEDESC2 *lpddsd, LPDIRECTDRAWSURFACE *lplpdds, void *pu)
+{
+ return extCreateSurface(4, (CreateSurface_Type)pCreateSurface4, lpdd, (DDSURFACEDESC2 *)lpddsd, lplpdds, pu);
+}
+
+HRESULT WINAPI extCreateSurface7(LPDIRECTDRAW lpdd, DDSURFACEDESC2 *lpddsd, LPDIRECTDRAWSURFACE *lplpdds, void *pu)
+{
+ return extCreateSurface(7, (CreateSurface_Type)pCreateSurface7, lpdd, (DDSURFACEDESC2 *)lpddsd, lplpdds, pu);
+}
+
+HRESULT WINAPI extCreateSurface(int dxversion, CreateSurface_Type pCreateSurface, LPDIRECTDRAW lpdd, DDSURFACEDESC2 *lpddsd,
+ LPDIRECTDRAWSURFACE *lplpdds, void *pu)
+{
+ HRESULT res;
+
+ //GHO: beware: incomplete trace line - must be line terminated below!
+ if(IsTraceD){
+ OutTrace("CreateSurface: Version=%d lpdd=%x Flags=%x(%s)", dxversion, lpdd, lpddsd->dwFlags, ExplainFlags(lpddsd->dwFlags));
+ if (lpddsd->dwFlags & DDSD_CAPS && lpddsd->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) OutTrace(" VirtualScreen=(%d,%d)", dxw.GetScreenWidth(), dxw.GetScreenHeight());
+ if (lpddsd->dwFlags & DDSD_BACKBUFFERCOUNT) OutTrace(" BackBufferCount=%d", lpddsd->dwBackBufferCount);
+ if (lpddsd->dwFlags & DDSD_WIDTH) OutTrace(" Width=%d", lpddsd->dwWidth);
+ if (lpddsd->dwFlags & DDSD_HEIGHT) OutTrace(" Height=%d", lpddsd->dwHeight);
+ if (lpddsd->dwFlags & DDSD_CAPS) OutTrace(" Caps=%x(%s)", lpddsd->ddsCaps.dwCaps, ExplainDDSCaps(lpddsd->ddsCaps.dwCaps));
+ if (lpddsd->dwFlags & DDSD_CKDESTBLT ) OutTrace(" CKDestBlt=(%x,%x)", lpddsd->ddckCKDestBlt.dwColorSpaceLowValue, lpddsd->ddckCKDestBlt.dwColorSpaceHighValue);
+ if (lpddsd->dwFlags & DDSD_CKDESTOVERLAY ) OutTrace(" CKDestOverlay=(%x,%x)", lpddsd->ddckCKDestOverlay.dwColorSpaceLowValue, lpddsd->ddckCKDestOverlay.dwColorSpaceHighValue);
+ if (lpddsd->dwFlags & DDSD_CKSRCBLT ) OutTrace(" CKSrcBlt=(%x,%x)", lpddsd->ddckCKSrcBlt.dwColorSpaceLowValue, lpddsd->ddckCKSrcBlt.dwColorSpaceHighValue);
+ if (lpddsd->dwFlags & DDSD_CKSRCOVERLAY ) OutTrace(" CKSrcOverlay=(%x,%x)", lpddsd->ddckCKSrcOverlay.dwColorSpaceLowValue, lpddsd->ddckCKSrcOverlay.dwColorSpaceHighValue);
+ OutTrace("\n");
+ }
+
+ //GHO workaround (needed for WarWind):
+ if (lpddsd->dwFlags && !(lpddsd->dwFlags & 0x1)){
+ OutTraceD("CreateSurface: fixing illegal dwFlags value: %x -> %x\n",
+ lpddsd->dwFlags, lpddsd->dwFlags+1);
+ lpddsd->dwFlags++;
+ }
+
+ lpDD = lpdd;
+
+ if (dxw.dwFlags1 & EMULATESURFACE)
+ res= extCreateSurfaceEmu(dxversion, pCreateSurface, lpdd, lpddsd, lplpdds, pu);
+ else
+ res= extCreateSurfaceDir(dxversion, pCreateSurface, lpdd, lpddsd, lplpdds, pu);
+
+ return res;
+}
+
+HRESULT WINAPI extGetAttachedSurface(int dxversion, GetAttachedSurface_Type pGetAttachedSurface,
+ LPDIRECTDRAWSURFACE lpdds, LPDDSCAPS lpddsc, LPDIRECTDRAWSURFACE *lplpddas)
+{
+ HRESULT res;
+ BOOL IsPrim;
+
+ IsPrim=dxw.IsAPrimarySurface(lpdds);
+ OutTraceD("GetAttachedSurface(%d): lpdds=%x%s caps=%x(%s)\n",
+ dxversion, lpdds, (IsPrim?"(PRIM)":""), lpddsc->dwCaps, ExplainDDSCaps(lpddsc->dwCaps));
+
+ // if not primary, just proxy the method
+
+ // v2.1.81: fix to make "Silver" working: if the primary surface was created with
+ // backbuffercount == 2, the game expects some more surface to be attached to
+ // the attached backbuffer. Since there would be no use for it, just return
+ // the attached backbuffer itself. Makes Silver working, anyway....
+ // beware: "Snowboard Racer" fails if you return an attached surface anyhow! There,
+ // the primary surface was created with back buffer count == 1.
+
+ if ((lpdds == lpDDSBack) && (dxw.dwBackBufferCount > 1)){
+ *lplpddas = lpDDSBack;
+ OutTraceD("GetAttachedSurface(%d): DOUBLEBUFFER attached=%x\n", dxversion, *lplpddas);
+ return 0;
+ }
+
+ if(!IsPrim){
+ res=(*pGetAttachedSurface)(lpdds, lpddsc, lplpddas);
+ if(res)
+ OutTraceE("GetAttachedSurface(%d): ERROR res=%x(%s) at %d\n", dxversion, res, ExplainDDError(res), __LINE__);
+ else
+ OutTraceD("GetAttachedSurface(%d): attached=%x\n", dxversion, *lplpddas);
+ return(res);
+ }
+
+ // on primary surface return the lpDDSBack surface coming from either an explicit
+ // AddAttachedSurface, or a primary complex surface creation otherwise....
+
+ if(lpddsc->dwCaps & DDSCAPS_BACKBUFFER){ // WIPWIP
+ if (lpDDSBack) {
+ *lplpddas = lpDDSBack;
+ OutTraceD("GetAttachedSurface(%d): BACKBUFFER attached=%x\n", dxversion, *lplpddas);
+ return 0;
+ }
+ else {
+ *lplpddas = NULL;
+ OutTraceD("GetAttachedSurface(%d): no attached BACKBUFFER\n", dxversion);
+ return DDERR_NOTFOUND;
+ }
+ }
+ else{
+ res=(*pGetAttachedSurface)(lpdds, lpddsc, lplpddas);
+ if(res)
+ OutTraceE("GetAttachedSurface(%d): ERROR res=%x(%s) at %d\n", dxversion, res, ExplainDDError(res), __LINE__);
+ else
+ OutTraceD("GetAttachedSurface(%d): attached=%x\n", dxversion, *lplpddas);
+ return res;
+ }
+}
+
+HRESULT WINAPI extGetAttachedSurface1(LPDIRECTDRAWSURFACE lpdds, LPDDSCAPS lpddsc, LPDIRECTDRAWSURFACE *lplpddas)
+{
+ return extGetAttachedSurface(1, pGetAttachedSurface1, lpdds, lpddsc, lplpddas);
+}
+
+HRESULT WINAPI extGetAttachedSurface3(LPDIRECTDRAWSURFACE lpdds, LPDDSCAPS lpddsc, LPDIRECTDRAWSURFACE *lplpddas)
+{
+ return extGetAttachedSurface(3, pGetAttachedSurface3, lpdds, lpddsc, lplpddas);
+}
+
+HRESULT WINAPI extGetAttachedSurface4(LPDIRECTDRAWSURFACE lpdds, LPDDSCAPS lpddsc, LPDIRECTDRAWSURFACE *lplpddas)
+{
+ return extGetAttachedSurface(4, pGetAttachedSurface4, lpdds, lpddsc, lplpddas);
+}
+
+HRESULT WINAPI extGetAttachedSurface7(LPDIRECTDRAWSURFACE lpdds, LPDDSCAPS lpddsc, LPDIRECTDRAWSURFACE *lplpddas)
+{
+ return extGetAttachedSurface(7, pGetAttachedSurface7, lpdds, lpddsc, lplpddas);
+}
+
+static void BlitError(HRESULT res, LPRECT lps, LPRECT lpd, int line)
+{
+ OutTraceE("Blt: ERROR %x(%s) at %d", res, ExplainDDError(res), line);
+ if (res==DDERR_INVALIDRECT){
+ if (lps)
+ OutTraceE(" src=(%d,%d)-(%d,%d)",lps->left, lps->top, lps->right, lps->bottom);
+ else
+ OutTraceE(" src=(NULL)");
+ if (lpd)
+ OutTraceE(" dest=(%d,%d)-(%d,%d)",lpd->left, lpd->top, lpd->right, lpd->bottom);
+ else
+ OutTraceE(" dest=(NULL)");
+ }
+ OutTraceE("\n");
+ return;
+}
+
+HRESULT WINAPI sBlt(char *api, LPDIRECTDRAWSURFACE lpdds, LPRECT lpdestrect,
+ LPDIRECTDRAWSURFACE lpddssrc, LPRECT lpsrcrect, DWORD dwflags, LPDDBLTFX lpddbltfx, BOOL isFlipping)
+{
+ RECT emurect, destrect;
+ POINT p = {0, 0};
+ HRESULT res;
+ BOOL ToPrim, FromPrim, ToScreen, FromScreen;
+ //CkArg arg;
+
+ ToPrim=dxw.IsAPrimarySurface(lpdds);
+ FromPrim=dxw.IsAPrimarySurface(lpddssrc);
+ ToScreen=ToPrim && !(dxw.dwFlags1 & EMULATESURFACE);
+ FromScreen=FromPrim && !(dxw.dwFlags1 & EMULATESURFACE);
+
+ CleanRect(&lpdestrect,__LINE__);
+ CleanRect(&lpsrcrect,__LINE__);
+
+ // log
+ if(IsTraceD){
+ OutTrace("%s: dest=%x%s src=%x%s dwFlags=%x(%s)",
+ api, lpdds, (ToPrim ? "(PRIM)":""), lpddssrc, (FromPrim ? "(PRIM)":""), dwflags, ExplainBltFlags(dwflags));
+ if (lpdestrect)
+ OutTrace(" destrect=(%d,%d)-(%d,%d)", lpdestrect->left, lpdestrect->top, lpdestrect->right, lpdestrect->bottom);
+ else
+ OutTrace(" destrect=(NULL)");
+ if (lpsrcrect)
+ OutTrace(" srcrect=(%d,%d)-(%d,%d)", lpsrcrect->left, lpsrcrect->top, lpsrcrect->right, lpsrcrect->bottom);
+ else
+ OutTrace(" srcrect=(NULL)");
+ //if (lpddbltfx)
+ // OutTrace(" ddbltfx.(destcolor=%x srccolor=%x fillcolor=%x filldepth=%x)",
+ // lpddbltfx->ddckDestColorkey,
+ // lpddbltfx->ddckSrcColorkey,
+ // lpddbltfx->dwFillColor,
+ // lpddbltfx->dwFillDepth);
+ OutTrace("\n");
+ }
+
+#define ONEPIXELFIXFlag 1
+#define FIXBIGGERRECT 1
+
+ if (ONEPIXELFIXFlag){
+ if (lpdestrect){
+ if (lpdestrect->bottom == dxw.GetScreenHeight() -1) lpdestrect->bottom = dxw.GetScreenHeight();
+ if (lpdestrect->right == dxw.GetScreenWidth() -1) lpdestrect->right = dxw.GetScreenWidth();
+ }
+ }
+
+ if(FIXBIGGERRECT){
+ if(ToPrim && lpdestrect){
+ if((DWORD)lpdestrect->bottom > dxw.GetScreenHeight()) lpdestrect->bottom = dxw.GetScreenHeight();
+ if((DWORD)lpdestrect->right > dxw.GetScreenWidth()) lpdestrect->right = dxw.GetScreenWidth();
+ }
+ }
+
+ if((dxw.dwFlags1 & EMULATESURFACE) && (dwflags==DDBLT_COLORFILL)){
+ OutTraceD("Debug: dwFillDepth=%d, EmuBPP=%d, dwFillColor=%x\n",
+ lpddbltfx->dwFillDepth, dxw.VirtualPixelFormat.dwRGBBitCount, lpddbltfx->dwFillColor);
+ //lpddbltfx->dwFillDepth=VirtualScr.dwRGBBitCount;
+ }
+
+ if(IsDebug){
+ if(dwflags & DDBLT_COLORFILL){
+ OutTrace("DEBUG: ColorFill=%x depth=%d\n", lpddbltfx->dwFillColor, lpddbltfx->dwFillDepth);
+ }
+ if(dwflags & DDBLT_KEYSRC){
+ DDCOLORKEY ColorKey;
+ (*pGetColorKey)(lpddssrc, DDCKEY_SRCBLT, &ColorKey);
+ OutTrace("DEBUG: KeySrc=%x\n", ColorKey.dwColorSpaceHighValue);
+ }
+ if(dwflags & DDBLT_KEYDEST){
+ DDCOLORKEY ColorKey;
+ (*pGetColorKey)(lpddssrc, DDCKEY_DESTBLT, &ColorKey);
+ OutTrace("DEBUG: KeyDest=%x\n", ColorKey.dwColorSpaceHighValue);
+ }
+ if(dwflags & DDBLT_KEYSRCOVERRIDE){
+ OutTrace("DEBUG: SrcColorkey=%x\n", lpddbltfx->ddckSrcColorkey.dwColorSpaceHighValue);
+ OutTrace("DEBUG: KeySrcAlpha=%x depth=%d\n", lpddbltfx->dwAlphaSrcConst, lpddbltfx->dwAlphaSrcConstBitDepth);
+ }
+ if(dwflags & DDBLT_KEYDESTOVERRIDE){
+ OutTrace("DEBUG: DestColorkey=%x\n", lpddbltfx->ddckDestColorkey.dwColorSpaceHighValue);
+ OutTrace("DEBUG: KeyDestAlpha=%x depth=%d\n", lpddbltfx->dwAlphaDestConst, lpddbltfx->dwAlphaDestConstBitDepth);
+ }
+ }
+
+ // blit to non primary surface
+
+ if(!ToPrim){
+ //RECT srcrect, winrect;
+ RECT srcrect;
+ // make a working copy of srcrect if not NULL
+ if (lpsrcrect){
+ srcrect=*lpsrcrect;
+ }
+ // when blitting from a primary surface on screen (that is in non emulated mode), correct offsets
+ // You should take account also for scaled primary surfaces, but that would be a hard task:
+ // a reduced primary surface (in not-emulated mode) would bring quality loss!!!
+ // v2.1.83: BLITFROMBACKBUFFER mode, let you chose to blit from backbuffer, where the surface size
+ // is fixed no matter how the window/primary surface is scaled.
+ // In "The Sims" there is no quality loss, but some scrolling artifact.
+ if(lpsrcrect && FromScreen){
+ if(lpDDSBack && (dxw.dwFlags1 & BLITFROMBACKBUFFER)){
+ lpddssrc=lpDDSBack;
+ srcrect=dxw.GetScreenRect();
+ }
+ else{
+ srcrect=dxw.MapWindowRect(lpsrcrect);
+ }
+ }
+ res= (*pBlt)(lpdds, lpdestrect, lpddssrc, lpsrcrect ? &srcrect : NULL, dwflags, lpddbltfx);
+ // Blitting compressed data may work to screen surfaces only. In this case, it may be worth
+ // trying blitting directly to lpDDSEmu_Prim: it makes DK2 intro movies working.
+ switch(res){
+ case DDERR_UNSUPPORTED:
+ if (dxw.dwFlags1 & EMULATESURFACE){
+ res=(*pBlt)(lpDDSEmu_Prim, lpdestrect, lpddssrc, lpsrcrect ? &srcrect : NULL, dwflags, lpddbltfx);
+ }
+ break;
+ case DDERR_SURFACEBUSY:
+ (*pUnlockMethod(lpdds))(lpdds, NULL);
+ if (lpddssrc) (*pUnlockMethod(lpddssrc))(lpddssrc, NULL);
+ res=(*pBlt)(lpdds, lpdestrect, lpddssrc, lpsrcrect ? &srcrect : NULL, dwflags|DDBLT_WAIT, lpddbltfx);
+ break;
+ default:
+ break;
+ }
+ if (res) BlitError(res, &srcrect, lpdestrect, __LINE__);
+ if(dxw.dwFlags1 & SUPPRESSDXERRORS) res=0;
+ return res;
+ }
+
+ // Blit to primary surface
+
+ if(dxw.HandleFPS()) return DD_OK;
+
+ destrect=dxw.MapWindowRect(lpdestrect);
+
+ if(!(dxw.dwFlags1 & (EMULATESURFACE|EMULATEBUFFER))){
+ res=0;
+ // blit only when source and dest surface are different. Should make ScreenRefresh faster.
+ if (lpdds != lpddssrc) {
+ //OutTrace("DEBUG: lpdds=%x lpddssrc=%x destrect=(%d,%d)-(%d,%d) lpsrcrect=%x flags=%x lpddbltfx=%x\n",
+ // lpdds, lpddssrc, destrect.left, destrect.top, destrect.right, destrect.bottom, lpsrcrect, dwflags, lpddbltfx);
+ res= (*pBlt)(lpdds, &destrect, lpddssrc, lpsrcrect, dwflags, lpddbltfx);
+ }
+ if(res){
+ BlitError(res, lpsrcrect, &destrect, __LINE__);
+ // Try to handle HDC lock concurrency....
+ if(res==DDERR_SURFACEBUSY){
+ (*pUnlockMethod(lpdds))(lpdds, NULL);
+ res= (*pBlt)(lpdds, &destrect, lpddssrc, lpsrcrect, dwflags, lpddbltfx);
+ if (res) BlitError(res, lpsrcrect, &destrect, __LINE__);
+ }
+
+ if(dxw.dwFlags1 & SUPPRESSDXERRORS) res=0;
+ }
+
+ return res;
+ }
+
+ // ... else blitting on emulated surface
+ // Blit/Flip to emulated primary surface
+
+ if(!lpddssrc) {
+ if (isFlipping){
+ // handle the flipping chain ...
+ lpddssrc=lpDDSBack;
+ OutTraceD("Flip: setting flip chain to lpdds=%x\n", lpddssrc);
+ }
+ }
+
+ if (lpdestrect){
+ emurect=*lpdestrect;
+ }
+ else{
+ // emurect: emulated rect is full surface (dwWidth x dwHeight)
+ emurect.left = 0;
+ emurect.top = 0;
+ emurect.right = dxw.GetScreenWidth();
+ emurect.bottom = dxw.GetScreenHeight();
+ }
+
+ res=0;
+ // blit only when source and dest surface are different. Should make ScreenRefresh faster.
+ if (lpdds != lpddssrc)
+ res=(*pBlt)(lpdds, &emurect, lpddssrc, lpsrcrect, dwflags, lpddbltfx);
+
+ if (res) {
+ BlitError(res, lpsrcrect, &emurect, __LINE__);
+ /*
+ Dungeon Keeper II intro movies bug ....
+ it seems that you can't blit from compressed or different surfaces in memory,
+ while the operation COULD be supported to video. As a mater of fact, it DOES
+ work on my PC.
+ */
+ if(res==DDERR_UNSUPPORTED){
+ if (dxw.dwFlags2 & SHOWFPSOVERLAY) dxw.ShowFPS(lpddssrc);
+ res=(*pBlt)(lpDDSEmu_Prim, &destrect, lpddssrc, lpsrcrect, dwflags, lpddbltfx);
+ if (res) BlitError(res, lpsrcrect, &destrect, __LINE__);
+ }
+
+ // Try to handle HDC lock concurrency....
+ if(res==DDERR_SURFACEBUSY){
+ (*pUnlockMethod(lpddssrc))(lpddssrc, NULL);
+ res=(*pBlt)(lpdds, &emurect, lpddssrc, lpsrcrect, dwflags, lpddbltfx);
+ if (res) BlitError(res, lpsrcrect, &destrect, __LINE__);
+ }
+
+ if(dxw.dwFlags1 & SUPPRESSDXERRORS) res=0;
+ return res;
+ }
+
+ LPDIRECTDRAWSURFACE lpDDSSource;
+
+ if(dxw.dwFlags1 & EMULATESURFACE){
+ res=(*pEmuBlt)(lpDDSEmu_Back, &emurect, lpdds, &emurect, DDBLT_WAIT, 0);
+ if(res==DDERR_SURFACEBUSY){
+ (*pUnlockMethod(lpdds))(lpdds, NULL);
+ (*pUnlockMethod(lpDDSEmu_Back))(lpDDSEmu_Back, NULL);
+ res=(*pEmuBlt)(lpDDSEmu_Back, &emurect, lpdds, &emurect, DDBLT_WAIT, 0);
+ }
+ if(res) {
+ if(dxw.dwFlags1 & SUPPRESSDXERRORS) res=0;
+ return res;
+ }
+ lpDDSSource = lpDDSEmu_Back;
+ }
+ else{
+ lpDDSSource = lpdds;
+ }
+
+ if (dxw.dwFlags2 & SHOWFPSOVERLAY) dxw.ShowFPS(lpDDSSource);
+ res=(*pBlt)(lpDDSEmu_Prim, &destrect, lpDDSSource, &emurect, DDBLT_WAIT, 0);
+ if (res==DDERR_NOCLIPLIST){
+ RenewClipper(lpDD, lpDDSEmu_Prim);
+ res=(*pBlt)(lpDDSEmu_Prim, &destrect, lpDDSSource, &emurect, DDBLT_WAIT, 0);
+ }
+
+ if (res) BlitError(res, &emurect, &destrect, __LINE__);
+ if(dxw.dwFlags1 & SUPPRESSDXERRORS) res=0;
+ return res;
+}
+
+HRESULT WINAPI extFlip(LPDIRECTDRAWSURFACE lpdds, LPDIRECTDRAWSURFACE lpddssrc, DWORD dwflags)
+{
+ BOOL IsPrim;
+ HRESULT res;
+
+ IsPrim=dxw.IsAPrimarySurface(lpdds);
+ OutTraceD("Flip: lpdds=%x%s, src=%x, flags=%x(%s)\n",
+ lpdds, IsPrim?"(PRIM)":"", lpddssrc, dwflags, ExplainFlipFlags(dwflags));
+
+ if (!IsPrim){
+ if(lpddssrc){
+ //return 0;
+ res=(*pFlip)(lpdds, lpddssrc, dwflags);
+ }
+ else{
+ LPDIRECTDRAWSURFACE lpddsAttached;
+ DDSCAPS ddsc;
+ DDSURFACEDESC2 sd;
+
+ sd.dwSize=Set_dwSize_From_Surface(lpdds);
+ res=lpdds->GetSurfaceDesc((DDSURFACEDESC *)&sd);
+ if (res) OutTraceD("Flip: GetSurfaceDesc res=%x at %d\n",res, __LINE__);
+
+ // replace these CAPS (good for seven kingdoms II) with same as lpdds surface
+ //ddsc.dwCaps=DDSCAPS_OFFSCREENPLAIN+DDSCAPS_SYSTEMMEMORY;
+ ddsc.dwCaps=sd.ddsCaps.dwCaps;
+
+ //res=lpdds->GetAttachedSurface(0,&lpddsAttached);
+ //res=(*pGetAttachedSurface)(lpdds, &ddsc, &lpddsAttached);
+ res=lpdds->GetAttachedSurface(&ddsc, &lpddsAttached);
+ if(res){
+ OutTraceE("Flip: GetAttachedSurface ERROR %x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
+ return res;
+ }
+ res=sBlt("Flip", lpdds, NULL, lpddsAttached, NULL, DDBLT_WAIT, 0, TRUE);
+ if(res){
+ OutTraceE("Flip: Blt ERROR %x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
+ return res;
+ }
+ }
+ if(res) OutTraceE("Flip: ERROR %x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
+ return res;
+ }
+
+ // emulation to primary surface Flip - you can't flip to window surfaces,
+ // so you have to replace it with Blt operations.
+
+ //lpdds->GetDDInterface(lpDD); from IDirectDrawSurface2 only
+ if((dwflags & DDFLIP_WAIT) || (dxw.dwFlags1 & SAVELOAD)) lpDD->WaitForVerticalBlank(DDWAITVB_BLOCKEND , 0);
+
+ if(lpddssrc){
+ //res=lpdds->Blt(0, lpddssrc, 0, DDBLT_WAIT, 0);
+ res=sBlt("Flip", lpdds, NULL, lpddssrc, NULL, DDBLT_WAIT, 0, TRUE);
+ }
+ else{
+ if (dxw.dwFlags2 & BACKBUFATTACH){
+ RECT NullArea;
+ NullArea.left=NullArea.top=0;
+ NullArea.bottom=dxw.GetScreenHeight();
+ NullArea.right=dxw.GetScreenWidth();
+ res=sBlt("Flip", lpdds, NULL, lpDDSBack, &NullArea, DDBLT_WAIT, 0, TRUE);
+ }
+ else
+ res=sBlt("Flip", lpdds, NULL, lpDDSBack, NULL, DDBLT_WAIT, 0, TRUE);
+ }
+
+ if(res) OutTraceE("Flip: Blt ERROR %x(%s)\n", res, ExplainDDError(res));
+ return res;
+}
+
+HRESULT WINAPI extBlt(LPDIRECTDRAWSURFACE lpdds, LPRECT lpdestrect,
+ LPDIRECTDRAWSURFACE lpddssrc, LPRECT lpsrcrect, DWORD dwflags, LPDDBLTFX lpddbltfx)
+{
+ return sBlt("Blt", lpdds, lpdestrect, lpddssrc, lpsrcrect, dwflags, lpddbltfx, FALSE);
+}
+
+HRESULT WINAPI extBltFast(LPDIRECTDRAWSURFACE lpdds, DWORD dwx, DWORD dwy,
+ LPDIRECTDRAWSURFACE lpddssrc, LPRECT lpsrcrect, DWORD dwtrans)
+{
+ // BltFast is supported just on screen surfaces, so it has to be replaced
+ // by ordinary Blt operation in EMULATESURFACE mode.
+ // Mind that screen surface doesn't necessarily mean PRIMARY surfaces!
+
+ RECT srcrect, destrect;
+ DWORD flags = 0;
+ DDSURFACEDESC2 ddsd;
+ HRESULT ret;
+ BOOL ToPrim, FromPrim;
+
+ ToPrim=dxw.IsAPrimarySurface(lpdds);
+ FromPrim=dxw.IsAPrimarySurface(lpddssrc);
+
+ CleanRect(&lpsrcrect,__LINE__);
+
+ if(IsTraceD){
+ OutTrace("BltFast: dest=%x%s src=%x%s dwTrans=%x(%s) (x,y)=(%d,%d) ",
+ lpdds, ToPrim?"(PRIM)":"", lpddssrc, FromPrim?"(PRIM)":"", dwtrans, ExplainBltFastFlags(dwtrans), dwx, dwy);
+ if (lpsrcrect)
+ OutTrace("srcrect=(%d,%d)-(%d,%d)\n",
+ lpsrcrect->left, lpsrcrect->top, lpsrcrect->right, lpsrcrect->bottom);
+ else
+ OutTrace("srcrect=(NULL)\n");
+ }
+
+ // consistency check ....
+ if (lpsrcrect)
+ if((lpsrcrect->left >= lpsrcrect->right) || (lpsrcrect->top >= lpsrcrect->bottom)) {
+ OutTraceD("BltFast: ASSERT bad rect at %d\n", __LINE__);
+ return 0;
+ }
+
+ if(dwtrans & DDBLTFAST_WAIT) flags = DDBLT_WAIT;
+ if(dwtrans & DDBLTFAST_DESTCOLORKEY) flags |= DDBLT_KEYDEST;
+ if(dwtrans & DDBLTFAST_SRCCOLORKEY) flags |= DDBLT_KEYSRC;
+
+ destrect.left = dwx;
+ destrect.top = dwy;
+ if(lpsrcrect){
+ destrect.right = destrect.left + lpsrcrect->right - lpsrcrect->left;
+ destrect.bottom = destrect.top + lpsrcrect->bottom - lpsrcrect->top;
+ // avoid altering pointed values....
+ srcrect=*lpsrcrect;
+ //ret=lpdds->Blt(&destrect, lpddssrc, &srcrect, flags, 0);
+ ret=sBlt("BltFast", lpdds, &destrect, lpddssrc, &srcrect, flags, 0, FALSE);
+ }
+ else{
+ // does it EVER goes through here? NULL is not a valid rect value for BltFast call....
+ ddsd.dwSize=Set_dwSize_From_Surface(lpddssrc);
+ ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
+ ret=lpddssrc->GetSurfaceDesc((LPDDSURFACEDESC)&ddsd);
+ if (ret){
+ OutTraceE("BltFast: GetSurfaceDesc ERROR %x at %d\n", ret, __LINE__);
+ return 0;
+ }
+ destrect.right = destrect.left + ddsd.dwWidth;
+ destrect.bottom = destrect.top + ddsd.dwHeight;
+ ret=sBlt("BltFast", lpdds, &destrect, lpddssrc, NULL, flags, 0, FALSE);
+ }
+
+ return ret;
+}
+
+HRESULT WINAPI extCreatePalette(LPDIRECTDRAW lpdd, DWORD dwflags, LPPALETTEENTRY lpddpa,
+ LPDIRECTDRAWPALETTE *lplpddp, IUnknown *pu)
+{
+ HRESULT res;
+
+ OutTraceD("CreatePalette: dwFlags=%x(%s)\n", dwflags, ExplainCreatePaletteFlags(dwflags));
+
+ if(!(dxw.dwFlags1 & EMULATESURFACE)){
+ res = (*pCreatePalette)(lpdd, dwflags, lpddpa, lplpddp, pu);
+ if (res) {
+ OutTraceD("CreatePalette: res=%x(%s)\n", res, ExplainDDError(res));
+ return res;
+ }
+ HookDDPalette(lplpddp);
+ OutTraceD("CreatePalette: GENUINE lpddp=%x\n", *lplpddp);
+ return res;
+ }
+
+ res = (*pCreatePalette)(lpdd, dwflags & ~DDPCAPS_PRIMARYSURFACE, lpddpa, lplpddp, pu);
+ if(res) {
+ if (res) OutTraceD("CreatePalette: res=%x(%s)\n", res, ExplainDDError(res));
+ return res;
+ }
+
+ HookDDPalette(lplpddp);
+
+ if(dwflags & DDPCAPS_PRIMARYSURFACE){
+ mySetPalette(0, 256, lpddpa);
+ lpDDP = *lplpddp;
+ }
+ OutTraceD("CreatePalette: EMULATED lpddp=%x\n", *lplpddp);
+ return 0;
+}
+
+HRESULT WINAPI extWaitForVerticalBlank(LPDIRECTDRAW lpdd, DWORD dwflags, HANDLE hevent)
+{
+ static DWORD time = 0;
+ static BOOL step = 0;
+ DWORD tmp;
+ if(!(dxw.dwFlags1 & SAVELOAD)) return (*pWaitForVerticalBlank)(lpdd, dwflags, hevent);
+ tmp = GetTickCount();
+ if((time - tmp) > 32) time = tmp;
+ (*pSleep)(time - tmp);
+ if(step) time += 16;
+ else time += 17;
+ step ^= 1;
+ return 0;
+}
+
+// extGetPalette: To revise completely. Un-hooked right now, to make things working.
+
+HRESULT WINAPI extGetPalette(LPDIRECTDRAWSURFACE lpdds, LPDIRECTDRAWPALETTE *lplpddp)
+{
+ HRESULT res;
+
+ OutTraceD("GetPalette: lpdds=%x\n", lpdds);
+
+ // if NO-EMU mode, just proxy the call
+ if(!(dxw.dwFlags1 & EMULATESURFACE)){
+ res=(*pGetPalette)(lpdds, lplpddp);
+ if (res) OutTraceE("GetPalette: ERROR res=%x(%s)\n", res, ExplainDDError(res));
+ return 0;
+ return res;
+ }
+
+ // in EMU mode, return the global palette ptr
+ if (lpDDP){
+ *lplpddp = lpDDP;
+ return 0;
+ }
+ else {
+ OutTraceD("GetPalette: ASSERT no lpDDP\n");
+ *lplpddp = lpDDP;
+ return DDERR_NOPALETTEATTACHED;
+ }
+}
+
+HRESULT WINAPI extSetPalette(LPDIRECTDRAWSURFACE lpdds, LPDIRECTDRAWPALETTE lpddp)
+{
+ PALETTEENTRY *lpentries;
+ BOOL isPrim;
+ HRESULT res;
+
+ dxw.IsGDIPalette=FALSE;
+ isPrim=dxw.IsAPrimarySurface(lpdds);
+ OutTraceD("SetPalette: lpdds=%x%s lpddp=%x\n", lpdds, isPrim?"(PRIM)":"", lpddp);
+
+#if 0
+ if(!(dxw.dwFlags1 & EMULATESURFACE) || !isPrim) {
+ res=(*pSetPalette)(lpdds, lpddp);
+ if(res)OutTraceE("SetPalette: ERROR res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
+ return res;
+ }
+
+ OutTraceD("SetPalette: DEBUG emulating palette\n");
+ lpDDP = lpddp;
+ //if (lpDDSBack) { GHOGHO
+ // res=(*pSetPalette)(lpDDSBack, lpddp);
+ // if(res) OutTraceE("SetPalette: ERROR res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
+ //}
+ // add a reference to simulate what would happen in reality....
+ lpdds->AddRef();
+
+ if(lpddp){
+ lpentries = (LPPALETTEENTRY)PaletteEntries;
+ res=lpddp->GetEntries(0, 0, 256, lpentries);
+ if(res) OutTraceE("SetPalette: GetEntries ERROR res=%x(%s)\n", res, ExplainDDError(res));
+ mySetPalette(0, 256, lpentries);
+ }
+
+ return 0;
+#else
+ res=(*pSetPalette)(lpdds, lpddp);
+ if(res)OutTraceE("SetPalette: ERROR res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
+
+ if((dxw.dwFlags1 & EMULATESURFACE) && (res==DD_OK)){
+ OutTraceD("SetPalette: DEBUG emulating palette\n");
+ lpDDP = lpddp;
+
+ if(lpddp){
+ HRESULT res2;
+ lpentries = (LPPALETTEENTRY)PaletteEntries;
+ res2=lpddp->GetEntries(0, 0, 256, lpentries);
+ if(res2) OutTraceE("SetPalette: GetEntries ERROR res=%x(%s)\n", res2, ExplainDDError(res2));
+ mySetPalette(0, 256, lpentries);
+ }
+ }
+
+ return res;
+#endif
+}
+
+HRESULT WINAPI extSetEntries(LPDIRECTDRAWPALETTE lpddp, DWORD dwflags, DWORD dwstart, DWORD dwcount, LPPALETTEENTRY lpentries)
+{
+ HRESULT res;
+
+ dxw.IsGDIPalette=FALSE;
+ OutTraceD("SetEntries: dwFlags=%x, start=%d, count=%d\n", //GHO: added trace infos
+ dwflags, dwstart, dwcount);
+
+ res = (*pSetEntries)(lpddp, dwflags, dwstart, dwcount, lpentries);
+ if(res) OutTraceE("SetEntries: ERROR res=%x(%s)\n", res, ExplainDDError(res));
+
+ if(!(dxw.dwFlags1 & EMULATESURFACE) || lpDDP != lpddp){
+ return res;
+ }
+
+ if ((dwstart + dwcount > 256) || (dwstart<0)){
+ dwcount=256;
+ dwstart=0;
+ OutTraceD("SetEntries: ASSERT start+count > 256\n");
+ }
+
+ mySetPalette(dwstart, dwcount, lpentries);
+
+ // GHO: needed for fixed rect and variable palette animations,
+ // e.g. dungeon keeper loading screen
+ if (dxw.dwFlags1 & EMULATESURFACE) dxw.ScreenRefresh();
+
+ return 0;
+}
+
+HRESULT WINAPI extSetClipper(LPDIRECTDRAWSURFACE lpdds, LPDIRECTDRAWCLIPPER lpddc)
+{
+ HRESULT res;
+ BOOL isPrim;
+ isPrim=dxw.IsAPrimarySurface(lpdds);
+ OutTraceD("SetClipper: lpdds=%x%s lpddc=%x\n", lpdds, isPrim?"(PRIM)":"", lpddc);
+
+ // v2.1.84: SUPPRESSCLIPPING flag - improves "Monopoly Edition 3D" where continuous
+ // clipping ON & OFF affects blitting on primary surface.
+ if(dxw.dwFlags1 & SUPPRESSCLIPPING) return 0;
+
+ if(isPrim && (dxw.dwFlags1 & (EMULATESURFACE|EMULATEBUFFER)) && lpDDSEmu_Prim){
+ res=(*pSetClipper)(lpDDSEmu_Prim, lpddc);
+ if(res) OutTraceE("CreateSurface: SetClipper ERROR: res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
+ lpDDC = lpddc;
+ // n.b. SetHWnd was not wrapped, so pSetHWnd is not usable (NULL) !!!
+ if(lpDDC) res=lpDDC->SetHWnd( 0, dxw.GethWnd());
+ //res=(*pSetHWnd)(lpDDC, 0, dxw.GethWnd());
+ if(res) OutTraceE("CreateSurface: SetHWnd ERROR: res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
+ //res = 0;
+ }
+ else
+ // just proxy ...
+ res=(*pSetClipper)(lpdds, lpddc);
+ if (res)
+ OutTraceE("SetClipper: ERROR res=%x(%s)\n", res, ExplainDDError(res));
+ return res;
+}
+
+HRESULT WINAPI extLock(LPDIRECTDRAWSURFACE lpdds, LPRECT lprect, LPDIRECTDRAWSURFACE lpdds2, DWORD flags, HANDLE hEvent)
+{
+ HRESULT res;
+ BOOL IsPrim;
+
+ IsPrim=dxw.IsAPrimarySurface(lpdds);
+
+ if(IsTraceD){
+ OutTrace("Lock: lpdds=%x%s flags=%x(%s) lpdds2=%x",
+ lpdds, (IsPrim ? "(PRIM)":""), flags, ExplainLockFlags(flags), lpdds2);
+ if (lprect)
+ OutTrace(" rect=(%d,%d)-(%d,%d)\n", lprect->left, lprect->top, lprect->right, lprect->bottom);
+ else
+ OutTrace(" rect=(NULL)\n");
+ }
+
+ res=(*pLock)(lpdds, lprect, lpdds2, flags, hEvent);
+ if(res==DDERR_SURFACEBUSY){ // v70: fix for "Ancient Evil"
+ (*pUnlockMethod(lpdds))(lpdds, NULL);
+ res = (*pLock)(lpdds, lprect, lpdds2, flags, hEvent);
+ OutTraceD("Lock RETRY: ret=%x(%s)\n", res, ExplainDDError(res));
+ }
+ if(res) OutTraceE("Lock ERROR: ret=%x(%s)\n", res, ExplainDDError(res));
+ DumpSurfaceAttributes((LPDDSURFACEDESC)lpdds2, "[Locked]" , __LINE__);
+ if(dxw.dwFlags1 & SUPPRESSDXERRORS) res=DD_OK;
+
+ // shouldn't happen.... if hooked to non primary surface, just call regular method.
+ // it happens in "Deadlock 2" backbuffer surface!!!
+ return res;
+}
+
+HRESULT WINAPI extUnlock(int dxversion, Unlock4_Type pUnlock, LPDIRECTDRAWSURFACE lpdds, LPRECT lprect)
+{
+ HRESULT res;
+ RECT screen, rect;
+ BOOL IsPrim;
+
+ IsPrim=dxw.IsAPrimarySurface(lpdds);
+
+ if ((dxversion == 4) && lprect) CleanRect(&lprect,__LINE__);
+
+ if(IsTraceD){
+ OutTrace("Unlock: lpdds=%x%s ", lpdds, (IsPrim ? "(PRIM)":""));
+ if (dxversion == 4){
+ if (lprect){
+ OutTrace("rect=(%d,%d)-(%d,%d)\n", lprect->left, lprect->top, lprect->right, lprect->bottom);
+ }
+ else
+ OutTrace("rect=(NULL)\n");
+ }
+ else
+ OutTrace("lpvoid=%x\n", lprect);
+ }
+
+ //if(dxw.dwFlags1 & SLOWDOWN) do_slow(2);
+
+ if (!IsPrim){
+ res=(*pUnlock)(lpdds, lprect);
+ if (res) OutTraceE("Unlock ERROR res=%x(%s) at %d\n",res, ExplainDDError(res), __LINE__);
+ if(dxw.dwFlags1 & SUPPRESSDXERRORS) res=0;
+ return res;
+ }
+
+ res=(*pUnlock)(lpdds, lprect);
+ if (res) OutTraceE("Unlock ERROR res=%x(%s) at %d\n",res, ExplainDDError(res), __LINE__);
+
+ // unlock on primary surface .....
+ if (dxw.HandleFPS()) return DD_OK;
+
+ if (dxw.dwFlags1 & (EMULATESURFACE|EMULATEBUFFER)){
+ DDSURFACEDESC2 ddsd;
+ LPDIRECTDRAWSURFACE lpDDSSource;
+
+ ddsd.dwSize=Set_dwSize_From_Surface(lpdds);
+ if(res=lpdds->GetSurfaceDesc((LPDDSURFACEDESC)&ddsd)) {
+ OutTraceE("Unlock: GetSurfaceDesc ERROR res=%x(%s) at %d\n",res, ExplainDDError(res), __LINE__);
+ return res;
+ }
+
+ rect.top=0;
+ rect.left=0;
+ rect.bottom=ddsd.dwHeight;
+ rect.right=ddsd.dwWidth;
+
+ screen=dxw.MapWindowRect();
+
+ if(dxw.dwFlags1 & EMULATESURFACE){
+ (*pEmuBlt)(lpDDSEmu_Back, &rect, lpdds, &rect, DDBLT_WAIT, ddsd.lpSurface);
+ lpDDSSource=lpDDSEmu_Back;
+ }
+ else{
+ lpDDSSource=lpdds;
+ }
+
+ if (dxw.dwFlags2 & SHOWFPSOVERLAY) dxw.ShowFPS(lpDDSSource);
+ res=(*pBlt)(lpDDSEmu_Prim, &screen, lpDDSSource, &rect, DDBLT_WAIT, 0);
+ if (res==DDERR_NOCLIPLIST) {
+ RenewClipper(lpDD, lpDDSEmu_Prim);
+ res=(*pBlt)(lpDDSEmu_Prim, &screen, lpDDSSource, &rect, DDBLT_WAIT, 0);
+ }
+ if (res) BlitError(res,&rect,&screen,__LINE__);
+ }
+
+ return 0;
+}
+
+HRESULT WINAPI extUnlock4(LPDIRECTDRAWSURFACE lpdds, LPRECT lprect)
+{
+ return extUnlock(4, pUnlock4, lpdds, lprect);
+}
+
+HRESULT WINAPI extUnlock1(LPDIRECTDRAWSURFACE lpdds, LPVOID lpvoid)
+{
+ return extUnlock(1, (Unlock4_Type)pUnlock1, lpdds, (LPRECT)lpvoid);
+}
+
+/* to do: instead of calling GDI GetDC, try to map GetDC with Lock and
+ReleaseDC with Unlock, returning the surface memory ptr (???) as HDC
+and avoiding the consistency check performed by surface::GetDC (why
+should it bother if the screen is 32BPP and the surface is not??? */
+
+HRESULT WINAPI extGetDC(LPDIRECTDRAWSURFACE lpdds, HDC FAR *pHDC)
+{
+ HRESULT res;
+ BOOL IsPrim;
+ RECT client;
+
+ IsPrim=dxw.IsAPrimarySurface(lpdds);
+ OutTraceD("GetDC: lpdss=%x%s\n",lpdds, IsPrim?"(PRIM)":"");
+ res=(*pGetDC)(lpdds,pHDC);
+
+ if (res==DDERR_CANTCREATEDC && (dxw.dwFlags1 & EMULATESURFACE) && dxw.VirtualPixelFormat.dwRGBBitCount==8) {
+ // for 8BPP palettized surfaces, connect them to either the ddraw emulated palette or the GDI emulated palette
+ OutTraceD("GetDC: adding 8BPP palette to surface lpdds=%x\n", lpdds);
+ if(lpDDP==NULL){
+ // should link here to the GDI palette? See Hyperblade....
+ dxw.palNumEntries=256;
+ res=(*pCreatePalette)(lpDD, DDPCAPS_ALLOW256|DDPCAPS_8BIT|DDPCAPS_INITIALIZE, dxw.palPalEntry, &lpDDP, NULL);
+ if (res) {
+ OutTraceE("CreateSurface: CreatePalette ERROR res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
+ return res;
+ }
+ }
+ res=(*pSetPalette)(lpdds, lpDDP);
+ if (res) {
+ OutTraceE("CreateSurface: SetPalette ERROR res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
+ return res;
+ }
+ // retry ....
+ res=(*pGetDC)(lpdds,pHDC);
+ }
+
+ if(res){
+ // take care: actually, many games (AoE, Beasts & Bumpkins) get an error code here,
+ // but pretending nothing happened seems the best way to get tha game working somehow.
+ // Should the surface have a RGB color setting to allow for DC creation?
+
+ // log an error just when not intercepted by EMULATESURFACE|HANDLEDC handling below
+ if ((dxw.dwFlags1 & (EMULATESURFACE|HANDLEDC))!=(EMULATESURFACE|HANDLEDC))
+ OutTraceE("GetDC ERROR: lpdss=%x%s, hdc=%x, res=%x(%s) at %d\n",
+ lpdds, IsPrim?"(PRIM)":"", *pHDC, res, ExplainDDError(res), __LINE__);
+
+ if(res==DDERR_DCALREADYCREATED){
+ OutTraceD("GetDC: HDC DDERR_DCALREADYCREATED\n");
+ }
+ }
+
+ // when getting DC from primary surface, save hdc and lpdds
+ // for later possible use in GDI BitBlt wrapper function
+ if (IsPrim){
+ dxw.lpDDSPrimHDC=lpdds;
+ }
+
+ // tricky part to allog GDI to operate on top of a directdraw surface's HDI.
+ // needed for Age of Empires I & II and some other oldies.
+ // To Do: check that lpdds hdc doesn't stay locked!
+ if (res && (dxw.dwFlags1 & EMULATESURFACE)){
+ if (dxw.dwFlags1 & HANDLEDC) {
+ DDSURFACEDESC2 sd, hdcsd;
+ LPDIRECTDRAWSURFACE lpddshdc;
+
+ if (res==DDERR_CANTCREATEDC) (*pReleaseDC)(lpdds,*pHDC);
+
+ sd.dwSize=Set_dwSize_From_Surface(lpdds);
+ res=lpdds->GetSurfaceDesc((DDSURFACEDESC *)&sd);
+ if (res) OutTraceE("GetDC ERROR: GetSurfaceDesc res=%x(%s) at %d\n",res, ExplainDDError(res), __LINE__);
+ client.left=0;
+ client.right=sd.dwWidth;
+ client.top=0;
+ client.bottom=sd.dwHeight;
+
+ // v2.1.90 fix: Warlords III can't handle very big service surfaces. Better skip.
+ if(sd.dwWidth>dxw.GetScreenWidth() || sd.dwHeight>dxw.GetScreenHeight()) return DDERR_CANTCREATEDC;
+
+ // create a service lpDDSHDC surface of the needed size....
+
+ memset(&hdcsd, 0, sizeof(hdcsd)); // Clean all
+ hdcsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
+ hdcsd.dwSize = sd.dwSize;
+ hdcsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
+ hdcsd.dwWidth = sd.dwWidth;
+ hdcsd.dwHeight = sd.dwHeight;
+
+ (*pCreateSurfaceMethod(lpdds))(lpDD, &hdcsd, &lpddshdc, 0);
+ if(res){
+ OutTraceE("GetDC: CreateSurface ERROR on DDSHDC: res=%x(%s) at %d\n",res, ExplainDDError(res), __LINE__);
+ if(res==DDERR_INVALIDPIXELFORMAT) DumpPixFmt(&hdcsd);
+ return res;
+ }
+
+ OutTraceD("GetDC: created DDSHDC=%x\n", lpddshdc);
+
+ // initialize the auxiliary surface
+
+ res=(*pEmuBlt)(lpddshdc, &client, lpdds, &client, DDBLT_WAIT, 0);
+ if (res) OutTraceE("GetDC ERROR: EmuBlt res=%x(%s) at %d\n",res, ExplainDDError(res), __LINE__);
+
+ // return a valid device context handle, even though not a 8BPP one!
+ res=(*pGetDC)(lpddshdc,pHDC);
+ if(res) OutTraceE("GetDC ERROR: GetDC err=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
+
+ OutTraceD("GetDC: PushDC(%x,%x)\n", lpddshdc, *pHDC);
+ PushDC(lpddshdc,*pHDC);
+ }
+ else {
+ *pHDC=(*pGDIGetDC)(dxw.GethWnd());
+ if(!*pHDC) {
+ OutTraceE("GDI.GetDC ERROR: err=%d at %d\n", GetLastError(), __LINE__);
+ res=DDERR_CANTCREATEDC;
+ }
+ else {
+ res=DD_OK;
+ }
+ }
+ }
+
+ OutTraceD("GetDC: res=%x hdc=%x\n",res, *pHDC);
+ return res;
+
+}
+
+HRESULT WINAPI extReleaseDC(LPDIRECTDRAWSURFACE lpdds, HDC FAR hdc)
+{
+ HRESULT res;
+ POINT p = {0, 0};
+ RECT client;
+
+ // this must cope with the action policy of GetDC.
+
+ OutTraceD("ReleaseDC: lpdds=%x hdc=%x\n",lpdds, hdc);
+ res=(*pReleaseDC)(lpdds,hdc);
+ if (res==DD_OK) return res;
+
+ do { // fake loop to break out ...
+ if (dxw.dwFlags1 & EMULATESURFACE){
+ if (dxw.dwFlags1 & HANDLEDC){
+ DDSURFACEDESC2 sd;
+ LPDIRECTDRAWSURFACE lpddshdc;
+
+ // release the HDC
+ lpddshdc=PopDC(hdc);
+ OutTraceD("ReleaseDC: %x=PopDC(%x)\n", lpddshdc, hdc);
+
+ if(lpddshdc==NULL) break;
+
+ res=(*pReleaseDC)(lpddshdc, hdc);
+ if (res) {
+ OutTraceE("ReleaseDC: ReleaseDC ERROR res=%x(%s) at %d\n",res, ExplainDDError(res), __LINE__);
+ break;
+ }
+
+ sd.dwSize=Set_dwSize_From_Surface(lpdds);
+ res=lpdds->GetSurfaceDesc((DDSURFACEDESC *)&sd);
+ if (res) {
+ OutTraceE("GetDC: GetSurfaceDesc ERROR res=%x(%s) at %d\n",res, ExplainDDError(res), __LINE__);
+ break;
+ }
+ client.left=0;
+ client.right=sd.dwWidth;
+ client.top=0;
+ client.bottom=sd.dwHeight;
+ // OutTraceD("DEBUG: reverting to lpdds=%x rect=(%d,%d)-(%d,%d)\n", lpdds, client.left, client.top, client.right, client.bottom);
+ // revert the surface moddified by GDI functions to the original target surface
+ // works pretty well with Darklords III
+ res=(*pRevBlt)(lpddshdc, &client, lpdds, &client);
+ if (res) {
+ OutTraceE("ReleaseDC: RevBlt ERROR res=%x(%s) at %d\n",res, ExplainDDError(res), __LINE__);
+ break;
+ }
+ if(dxw.IsAPrimarySurface(lpdds)){
+ res=sBlt("ReleaseDC", lpdds, NULL, lpdds, NULL, 0, NULL, FALSE);
+ if (res) OutTraceE("ReleaseDC: Blt ERROR res=%x(%s) at %d\n",res, ExplainDDError(res), __LINE__);
+ }
+
+ (*pReleaseS)(lpddshdc);
+ }
+ else {
+ if((*pGDIReleaseDC)(dxw.GethWnd(),hdc)) res=DD_OK;
+ else {
+ OutTraceE("ReleaseDC: ReleaseDC ERROR err=%x at %d\n", GetLastError(), __LINE__);
+ res=DDERR_INVALIDPARAMS; // maybe there's a better value....
+ }
+ }
+ }
+ } while(0);
+
+ if (res) OutTraceE("ReleaseDC: ERROR res=%x(%s)\n", res, ExplainDDError(res));
+ return res;
+}
+
+
+HRESULT WINAPI extFlipToGDISurface(LPDIRECTDRAW lpdd)
+{
+ //HRESULT res;
+
+ OutTraceD("FlipToGDISurface: lpdd=%x\n", lpdd);
+ // to revise: so far, it seems the best thing to do is NOTHING, just return 0.
+ //res=(*pFlipToGDISurface)(lpdd);
+ //if (res) OutTraceE("FlipToGDISurface: ERROR res=%x(%s), skipping\n", res, ExplainDDError(res));
+ // pretend you flipped anyway....
+ return 0;
+}
+
+HRESULT WINAPI extGetGDISurface(LPDIRECTDRAW lpdd, LPDIRECTDRAWSURFACE *w)
+{
+ int res;
+ res=(*pGetGDISurface)(lpdd, w);
+ if (res) {
+ OutTraceE("GetGDISurface: ERROR lpdd=%x res=%x(%s)\n", lpdd, res, ExplainDDError(res));
+ }
+ else {
+ OutTraceD("GetGDISurface: PROXED lpdd=%x w=%x\n", lpdd, *w);
+ }
+
+ return res;
+}
+
+// debug function to dump all video modes queried by the DirectDrav::EnumDisplayModes method
+
+HRESULT WINAPI EnumModesCallbackDumper(LPDDSURFACEDESC lpDDSurfaceDesc, LPVOID lpContext)
+{
+ OutTrace("EnumModesCallback:\n");
+ OutTrace("\tdwSize=%d\n", lpDDSurfaceDesc->dwSize);
+ OutTrace("\tdwFlags=%x(%s)\n", lpDDSurfaceDesc->dwFlags, ExplainFlags(lpDDSurfaceDesc->dwFlags));
+ OutTrace("\tdwHeight x dwWidth=(%d,%d)\n", lpDDSurfaceDesc->dwHeight, lpDDSurfaceDesc->dwWidth);
+ OutTrace("\tlPitch=%d\n", lpDDSurfaceDesc->lPitch);
+ OutTrace("\tdwBackBufferCount=%d\n", lpDDSurfaceDesc->dwBackBufferCount);
+ OutTrace("\tdwRefreshRate=%d\n", lpDDSurfaceDesc->dwRefreshRate);
+ OutTrace("\tlpSurface=%x\n", lpDDSurfaceDesc->lpSurface);
+ OutTrace("\tddpfPixelFormat.dwSize=%D\n", lpDDSurfaceDesc->ddpfPixelFormat.dwSize);
+ OutTrace("\tddpfPixelFormat.dwFlags=%x\n", lpDDSurfaceDesc->ddpfPixelFormat.dwFlags);
+ OutTrace("\tddpfPixelFormat.dwRGBBitCount=%d\n", lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount);
+ OutTrace("\tddpfPixelFormat.dwARGBBitMask=(%x,%x,%x,%x)\n",
+ lpDDSurfaceDesc->ddpfPixelFormat.dwRGBAlphaBitMask,
+ lpDDSurfaceDesc->ddpfPixelFormat.dwRBitMask,
+ lpDDSurfaceDesc->ddpfPixelFormat.dwGBitMask,
+ lpDDSurfaceDesc->ddpfPixelFormat.dwBBitMask);
+ return DDENUMRET_OK;
+}
+
+typedef HRESULT (WINAPI *EnumModesCallback_Type)(LPDDSURFACEDESC, LPVOID);
+typedef struct {LPVOID lpContext; EnumModesCallback_Type lpCallback; } NewContext_Type;
+
+HRESULT WINAPI myEnumModesFilter(LPDDSURFACEDESC lpDDSurfaceDesc, LPVOID lpContext)
+{
+ if (IsDebug) EnumModesCallbackDumper(lpDDSurfaceDesc, NULL);
+
+ if (dxw.dwFlags1 & PREVENTMAXIMIZE){
+ // if PREVENTMAXIMIZE is set, don't let the caller know about forbidden screen settings.
+ if((lpDDSurfaceDesc->dwHeight > dxw.GetScreenHeight()) ||
+ (lpDDSurfaceDesc->dwWidth > dxw.GetScreenWidth())){
+ OutTraceD("EnumDisplayModes: skipping screen size=(%d,%d)\n", lpDDSurfaceDesc->dwHeight, lpDDSurfaceDesc->dwWidth);
+ return DDENUMRET_OK;
+ }
+ }
+
+ // tricky part: in 16BPP color depth let the callback believe that the pixel encoding
+ // is actually the one implemented in the emulation routines.
+ // should it fix also the other color depths?
+
+ switch(lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount){
+ case 8:
+ case 16:
+ case 24:
+ case 32:
+ FixPixelFormat(lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount, &lpDDSurfaceDesc->ddpfPixelFormat);
+ return (*((NewContext_Type *)lpContext)->lpCallback)(lpDDSurfaceDesc, ((NewContext_Type *)lpContext)->lpContext);
+ break;
+ }
+ return DDENUMRET_OK;
+}
+
+HRESULT WINAPI extEnumDisplayModes(EnumDisplayModes1_Type pEnumDisplayModes, LPDIRECTDRAW lpdd, DWORD dwflags, LPDDSURFACEDESC lpddsd, LPVOID lpContext, LPDDENUMMODESCALLBACK cb)
+{
+ HRESULT res;
+ OutTraceP("EnumDisplayModes(D): lpdd=%x flags=%x lpddsd=%x callback=%x\n", lpdd, dwflags, lpddsd, cb);
+
+ // note: extEnumDisplayModes serves both the EnumDisplayModes and EnumDisplayModes2 interfaces:
+ // they differ for the lpddsd argument that should point to either DDSURFACEDESC or DDSURFACEDESC2
+ // structures, but unification is possible if the lpddsd->dwSize is properly set and is left untouched.
+
+ if(dxw.dwFlags1 & EMULATESURFACE){
+#if 0
+ struct {int w; int h;}SupportedRes[5]= {(320,240),(640,480),(800,600),(1024,1200),(0,0)};
+ int SupportedDepths[5]={8,16,24,32,0};
+ int ResIdx, DepthIdx, ColorDepth;
+ DDSURFACEDESC2 EmuDesc;
+
+ //if (1) res=(*pEnumDisplayModes)(lpdd, dwflags, lpddsd, lpContext, EnumModesCallbackDumper);
+
+ EmuDesc.dwRefreshRate = 0;
+ EmuDesc.ddpfPixelFormat.dwFlags = DDPF_RGB;
+ if (lpddsd) EmuDesc.dwSize=lpddsd->dwSize; // sizeof either DDSURFACEDESC or DDSURFACEDESC2 !!!
+ else EmuDesc.dwSize = sizeof(DDSURFACEDESC2);
+ EmuDesc.dwFlags=DDSD_PIXELFORMAT|DDSD_REFRESHRATE|DDSD_WIDTH|DDSD_HEIGHT|DDSD_PITCH;
+ for (ResIdx=0; ResIdx<4; ResIdx++){
+ EmuDesc.dwHeight=SupportedRes[ResIdx].h;
+ EmuDesc.dwWidth=SupportedRes[ResIdx].w;
+ EmuDesc.ddpfPixelFormat.dwSize=sizeof(DDPIXELFORMAT);
+ EmuDesc.ddpfPixelFormat.dwFlags=DDPF_RGB;
+ for (DepthIdx=0; DepthIdx<4; DepthIdx++) {
+ ColorDepth=SupportedDepths[DepthIdx];
+ EmuDesc.ddpfPixelFormat.dwRGBBitCount=ColorDepth;
+ EmuDesc.lPitch=(ColorDepth/8) * SupportedRes[ResIdx].w;
+ switch (SupportedDepths[DepthIdx]){
+ case 8:
+ EmuDesc.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8;
+ break;
+ case 16:
+ if (dxw.dwFlags1 & USERGB565){
+ EmuDesc.ddpfPixelFormat.dwRBitMask = 0xf800; // Grim Fandango
+ EmuDesc.ddpfPixelFormat.dwGBitMask = 0x07e0;
+ EmuDesc.ddpfPixelFormat.dwBBitMask = 0x001f;
+ EmuDesc.ddpfPixelFormat.dwRGBAlphaBitMask = 0x0000;
+ }
+ else {
+ EmuDesc.ddpfPixelFormat.dwRBitMask = 0x7c00;
+ EmuDesc.ddpfPixelFormat.dwGBitMask = 0x03e0;
+ EmuDesc.ddpfPixelFormat.dwBBitMask = 0x001f;
+ EmuDesc.ddpfPixelFormat.dwRGBAlphaBitMask = 0x8000;
+ }
+ break;
+ case 24:
+ EmuDesc.ddpfPixelFormat.dwRBitMask = 0x00FF0000;
+ EmuDesc.ddpfPixelFormat.dwGBitMask = 0x0000FF00;
+ EmuDesc.ddpfPixelFormat.dwBBitMask = 0x000000FF;
+ EmuDesc.ddpfPixelFormat.dwRGBAlphaBitMask = 0x00000000;
+ break;
+ case 32:
+ EmuDesc.ddpfPixelFormat.dwRBitMask = 0x00FF0000;
+ EmuDesc.ddpfPixelFormat.dwGBitMask = 0x0000FF00;
+ EmuDesc.ddpfPixelFormat.dwBBitMask = 0x000000FF;
+ EmuDesc.ddpfPixelFormat.dwRGBAlphaBitMask = 0xFF000000;
+ break;
+ }
+ res=(*cb)((LPDDSURFACEDESC)&EmuDesc, lpContext);
+ if(res==DDENUMRET_CANCEL) break;
+ }
+ if(res==DDENUMRET_CANCEL) break;
+ }
+ OutTraceD("EnumDisplayModes(D): cycled to res=%d size=(%d,%d)\n",
+ SupportedDepths[DepthIdx], SupportedRes[ResIdx].w, SupportedRes[ResIdx].h);
+#else
+ NewContext_Type NewContext;
+ NewContext.lpContext=lpContext;
+ NewContext.lpCallback=cb;
+
+ res=(*pEnumDisplayModes)(lpdd, dwflags, lpddsd, &NewContext, myEnumModesFilter);
+#endif
+ }
+ else{
+ // proxy the call
+ res=(*pEnumDisplayModes)(lpdd, dwflags, lpddsd, lpContext, cb);
+ }
+ if(res) OutTraceD("EnumDisplayModes(D): ERROR res=%x(%s)\n", res, ExplainDDError(res));
+ return res;
+}
+
+HRESULT WINAPI extEnumDisplayModes1(LPDIRECTDRAW lpdd, DWORD dwflags, LPDDSURFACEDESC lpddsd, LPVOID lpContext, LPDDENUMMODESCALLBACK cb)
+{
+ return extEnumDisplayModes(pEnumDisplayModes1, lpdd, dwflags, lpddsd, lpContext, cb);
+}
+
+HRESULT WINAPI extEnumDisplayModes4(LPDIRECTDRAW lpdd, DWORD dwflags, LPDDSURFACEDESC2 lpddsd, LPVOID lpContext, LPDDENUMMODESCALLBACK2 cb)
+{
+ return extEnumDisplayModes((EnumDisplayModes1_Type)pEnumDisplayModes4, lpdd, dwflags, (LPDDSURFACEDESC)lpddsd, lpContext, (LPDDENUMMODESCALLBACK)cb);
+}
+
+HRESULT WINAPI extDuplicateSurface(LPDIRECTDRAW lpdd, LPDIRECTDRAWSURFACE s, LPDIRECTDRAWSURFACE *sp)
+{
+ int res;
+ res=(*pDuplicateSurface)(lpdd, s, sp);
+ if (res)
+ OutTraceE("DuplicateSurface: ERROR dds=%x res=%x(%s)\n", s, res, ExplainDDError(res));
+ else
+ OutTraceD("DuplicateSurface: dds=%x pdds=%x\n", s, *sp);
+ return res;
+}
+
+HRESULT WINAPI extGetPixelFormat(LPDIRECTDRAWSURFACE lpdds, LPDDPIXELFORMAT p)
+{
+ DWORD res;
+ BOOL IsPrim;
+
+ IsPrim=dxw.IsAPrimarySurface(lpdds);
+ OutTraceD("GetPixelFormat: lpdds=%x%s\n", lpdds, IsPrim?"(PRIM)":"");
+ res=(*pGetPixelFormat)(lpdds, p);
+ if(res){
+ OutTraceE("GetPixelFormat: ERROR res=%x(%s)\n", res, ExplainDDError(res));
+ }
+ else{
+ OutTraceD("GetPixelFormat: Flags=%x(%s) FourCC=%x BitCount=%d RGBA=(%x,%x,%x,%x)\n",
+ p->dwFlags, ExplainPixelFlags(p->dwFlags), p->dwFourCC, p->dwRGBBitCount,
+ p->dwRBitMask, p->dwGBitMask, p->dwBBitMask, p->dwRGBAlphaBitMask );
+ }
+
+ if ((dxw.dwFlags1 & EMULATESURFACE) && IsPrim){
+ p->dwFlags = dxw.VirtualPixelFormat.dwFlags;
+ p->dwRGBBitCount= dxw.VirtualPixelFormat.dwRGBBitCount;
+ p->dwRBitMask = dxw.VirtualPixelFormat.dwRBitMask;
+ p->dwGBitMask = dxw.VirtualPixelFormat.dwGBitMask;
+ p->dwBBitMask = dxw.VirtualPixelFormat.dwBBitMask;
+ p->dwRGBAlphaBitMask = dxw.VirtualPixelFormat.dwRGBAlphaBitMask;
+ OutTraceD("GetPixelFormat: EMULATED BitCount=%d RGBA=(%x,%x,%x,%x)\n",
+ p->dwRGBBitCount, p->dwRBitMask, p->dwGBitMask, p->dwBBitMask, p->dwRGBAlphaBitMask );
+ }
+
+ return res;
+}
+
+HRESULT WINAPI extTestCooperativeLevel(LPDIRECTDRAW lpdd)
+{
+ HRESULT res;
+ res=(*pTestCooperativeLevel)(lpdd);
+ if(IsDebug)
+ OutTrace("TestCooperativeLevel: lpdd=%x res=%x(%s)\n", lpdd, res, ExplainDDError(res));
+ return DD_OK;
+}
+
+HRESULT WINAPI extReleaseS(LPDIRECTDRAWSURFACE lpdds)
+{
+ HRESULT res;
+ BOOL IsPrim;
+ BOOL IsClosed;
+ OutTraceD("Release(S): DEBUG - lpdds=%x\n", lpdds);
+
+ IsPrim=dxw.IsAPrimarySurface(lpdds);
+
+ // handling of service closed surfaces
+ IsClosed=0;
+ __try{HRESULT dw=(DWORD)(*pReleaseS);}
+ __except (EXCEPTION_EXECUTE_HANDLER){
+ OutTraceD("Exception at %d\n",__LINE__);
+ IsClosed=1;
+ };
+
+ // avoid crashing....
+ res = IsClosed ? 0 :(*pReleaseS)(lpdds);
+
+ OutTraceD("Release(S): lpdds=%x%s refcount=%d\n", lpdds, IsPrim?"(PRIM)":"", res);
+ if (res==0) { // common precondition
+ // when releasing primary surface, erase clipping region
+ if(IsPrim && (dxw.dwFlags1 & CLIPCURSOR)) dxw.EraseClipCursor();
+ // if primary, clean primay surface list
+ if(IsPrim) dxw.UnmarkPrimarySurface(lpdds);
+ // service surfaces cleanup
+ if(lpdds==lpDDSBack) {
+ OutTraceD("Release(S): Clearing lpDDSBack pointer\n");
+ lpDDSBack=NULL;
+ }
+ if (dxw.dwFlags1 & EMULATESURFACE) {
+ if(lpdds==lpDDSEmu_Prim) {
+ OutTraceD("Release(S): Clearing lpDDSEmu_Prim pointer\n");
+ lpDDSEmu_Prim=NULL;
+ }
+ if(lpdds==lpDDSEmu_Back) {
+ OutTraceD("Release(S): Clearing lpDDSEmu_Back pointer\n");
+ lpDDSEmu_Back=NULL;
+ }
+ if(lpdds==dxw.lpDDSPrimHDC) {
+ OutTraceD("Release(S): Clearing lpDDSPrimHDC pointer\n");
+ dxw.ResetPrimarySurface();
+ }
+ }
+ }
+ return res;
+}
+
+HRESULT WINAPI extSetColorKey(LPDIRECTDRAWSURFACE lpdds, DWORD flags, LPDDCOLORKEY lpDDColorKey)
+{
+ HRESULT res;
+ BOOL IsPrim;
+ IsPrim=dxw.IsAPrimarySurface(lpdds);
+ if(IsTraceD){
+ OutTrace("SetColorKey: lpdds=%x%s flags=%x(%s) ",
+ lpdds, (IsPrim ? "(PRIM)" : ""), flags, ExplainColorKeyFlag(flags));
+ if (lpDDColorKey)
+ OutTrace("colors=(L:%x,H:%x)\n",lpDDColorKey->dwColorSpaceLowValue, lpDDColorKey->dwColorSpaceHighValue);
+ else
+ OutTrace("colors=(NULL)\n");
+ }
+
+ res=(*pSetColorKey)(lpdds, flags, lpDDColorKey);
+ if(res) OutTraceE("SetColorKey: ERROR flags=%x lpdds=%x res=%x(%s)\n",
+ flags, lpdds, res, ExplainDDError(res));
+ return res;
+}
+
+HRESULT WINAPI extGetColorKey(LPDIRECTDRAWSURFACE lpdds, DWORD flags, LPDDCOLORKEY lpDDColorKey)
+{
+ HRESULT res;
+ BOOL IsPrim;
+ IsPrim=dxw.IsAPrimarySurface(lpdds);
+ OutTraceD("GetColorKey(S): lpdds=%x%s flags=%x(%s)\n",
+ lpdds, (IsPrim ? "(PRIM)" : ""), flags, ExplainColorKeyFlag(flags));
+ res=(*pGetColorKey)(lpdds, flags, lpDDColorKey);
+ if(res)
+ OutTraceE("GetColorKey: ERROR lpdds=%x flags=%x res=%x(%s)\n", lpdds, flags, res, ExplainDDError(res));
+ else
+ OutTraceD("GetColorKey: colors=(L:%x,H:%x)\n",
+ lpdds, lpDDColorKey->dwColorSpaceLowValue, lpDDColorKey->dwColorSpaceHighValue);
+ return res;
+}
+
+HRESULT WINAPI extEnumAttachedSurfaces(LPDIRECTDRAWSURFACE lpdds, LPVOID lpContext, LPDDENUMSURFACESCALLBACK lpEnumSurfacesCallback)
+{
+ HRESULT res;
+ BOOL IsPrim;
+
+ IsPrim=dxw.IsAPrimarySurface(lpdds);
+
+ OutTraceD("EnumAttachedSurfaces: lpdds=%x%s Context=%x Callback=%x\n",
+ lpdds, (IsPrim ? "(PRIM)":""), lpContext, lpEnumSurfacesCallback);
+
+ if (IsPrim){
+ // A Primary surface has not backbuffer attached surfaces actually,
+ // so don't rely on ddraw and call the callback function directly.
+ // Needed to make Nox working.
+ DDSURFACEDESC2 ddsd;
+ // first, call hooked function
+ res=(*pEnumAttachedSurfaces)(lpdds, lpContext, lpEnumSurfacesCallback);
+ if (res)
+ OutTraceE("EnumAttachedSurfaces: ERROR %x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
+ if(lpDDSBack){
+ ddsd.dwSize=Set_dwSize_From_Surface(lpDDSBack);
+ res=lpDDSBack->GetSurfaceDesc((LPDDSURFACEDESC)&ddsd);
+ if(res){
+ OutTraceE("EnumAttachedSurfaces: GetSurfaceDesc ERROR %x(%s)\n",
+ res, ExplainDDError(res));
+ return res;
+ }
+ res=(lpEnumSurfacesCallback)(lpDDSBack, (LPDDSURFACEDESC)&ddsd, lpContext);
+ OutTraceD("EnumSurfacesCallback: on DDSBack res=%x(%s)\n", res, ExplainDDError(res));
+ }
+ res=0; // for Black Dahlia
+ }
+ else {
+ res=(*pEnumAttachedSurfaces)(lpdds, lpContext, lpEnumSurfacesCallback);
+ if (res)
+ OutTraceE("EnumAttachedSurfaces: ERROR %x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
+ }
+ return res;
+}
+
+HRESULT WINAPI extAddAttachedSurface(LPDIRECTDRAWSURFACE lpdds, LPDIRECTDRAWSURFACE lpddsadd)
+{
+ HRESULT res;
+ BOOL IsPrim;
+
+ // You can add backbuffers to primary surfaces to join the flipping chain, but you can't do that
+ // to an emulated primary surface, and you receive a DDERR_CANNOTATTACHSURFACE error code.
+ // In that case, it's worth to try to emulate the attach, and since the Flip method is emulated,
+ // just remember this for further handling in the Flip operation.
+ // But beware: this holds to BACKBUFFER surfaces only, and NOT for attached ZBUFFERS or similar!
+
+ IsPrim=dxw.IsAPrimarySurface(lpdds);
+ OutTraceD("AddAttachedSurface: lpdds=%x%s lpddsadd=%x\n", lpdds, IsPrim?"(PRIM)":"", lpddsadd);
+ res=(*pAddAttachedSurface)(lpdds, lpddsadd);
+ if (res) {
+ if (IsPrim){
+ HRESULT sdres;
+ DDSURFACEDESC2 sd;
+ sd.dwSize=Set_dwSize_From_Surface(lpddsadd);
+ sdres=lpddsadd->GetSurfaceDesc((DDSURFACEDESC *)&sd);
+ if (sdres)
+ OutTraceE("AddAttachedSurface: GetSurfaceDesc ERROR res=%x at %d\n", sdres, __LINE__);
+ else
+ OutTraceD("AddAttachedSurface: GetSurfaceDesc dwCaps=%x(%s)\n",
+ sd.ddsCaps.dwCaps, ExplainDDSCaps(sd.ddsCaps.dwCaps));
+ if (sd.ddsCaps.dwCaps & DDSCAPS_BACKBUFFER)
+ if ((dxw.dwFlags1 & EMULATESURFACE) && (res==DDERR_CANNOTATTACHSURFACE) ||
+ (res==DDERR_NOEXCLUSIVEMODE))
+ OutTraceD("AddAttachedSurface: emulating surface attach on PRIMARY\n");
+ lpDDSBack=lpddsadd;
+ res=0;
+ }
+ //// v2.1.73: Alien Cabal 95 in EMU mode
+ //if((lpdds==lpDDSBack) && (dxw.dwFlags1 & EMULATESURFACE)){
+ // OutTraceD("AddAttachedSurface: ignoring err=%x(%s) on BACKBUFFER surface attach\n", res, ExplainDDError(res));
+ // res=DD_OK;
+ //}
+ }
+ if (res) OutTraceE("AddAttachedSurface: ERROR %x(%s)\n", res, ExplainDDError(res));
+ return res;
+}
+
+HRESULT WINAPI extDeleteAttachedSurface(LPDIRECTDRAWSURFACE lpdds, DWORD dwflags, LPDIRECTDRAWSURFACE lpddsdel)
+{
+ HRESULT res;
+ OutTraceD("DeleteAttachedSurface: lpdds=%x flags=%x lpddsdel=%x\n", lpdds, dwflags, lpddsdel);
+ res=(*pDeleteAttachedSurface)(lpdds, dwflags, lpddsdel);
+ if(res) OutTraceE("DeleteAttachedSurface: ERROR %x(%s)\n", res, ExplainDDError(res));
+ if (res && (lpddsdel==lpDDSBack)){
+ OutTraceD("DeleteAttachedSurface: emulating surface detach lpdds=%x\n", lpddsdel);
+ lpDDSBack->Release(); // GHO TRY
+ lpDDSBack=NULL;
+ res=0;
+ }
+ return res;
+}
+
+HRESULT WINAPI cbDump(LPDDSURFACEDESC lpDDSurfaceDesc, LPVOID lpContext)
+{
+ OutTraceD("EnumDisplayModes: CALLBACK lpdds=%x Context=%x Caps=%x(%s)\n",
+ lpDDSurfaceDesc, lpContext,
+ lpDDSurfaceDesc->ddsCaps.dwCaps, ExplainDDSCaps(lpDDSurfaceDesc->ddsCaps.dwCaps));
+ return 1;
+}
+
+HRESULT WINAPI extGetCapsS(int dxInterface, GetCapsS_Type pGetCapsS, LPDIRECTDRAWSURFACE lpdds, LPDDSCAPS caps)
+{
+ HRESULT res;
+ BOOL IsPrim;
+ IsPrim=dxw.IsAPrimarySurface(lpdds);
+ OutTraceD("GetCaps(S%d): lpdds=%x%s, lpcaps=%x\n", dxInterface, lpdds, IsPrim?"(PRIM)":"", caps);
+ res=(*pGetCapsS)(lpdds, caps);
+ if(res)
+ OutTraceE("GetCaps(S%d): ERROR %x(%s)\n", dxInterface, res, ExplainDDError(res));
+ else
+ OutTraceD("GetCaps(S%d): lpdds=%x caps=%x(%s)\n", dxInterface, lpdds, caps->dwCaps, ExplainDDSCaps(caps->dwCaps));
+
+ if (!(dxw.dwFlags1 & EMULATESURFACE)) return res;
+
+ // note: C&C95 Gold Edition includes a check for the primary surface NOT having
+ // DDSCAPS_SYSTEMMEMORY bit set
+
+ if(IsPrim) caps->dwCaps = dxw.dwPrimarySurfaceCaps;
+ // v2.1.83: add FLIP capability (Funtraks a.k.a. Ignition)
+ if((dxw.dwFlags1 & EMULATESURFACE) && (lpdds == lpDDSBack)) caps->dwCaps |= DDSCAPS_FLIP;
+
+ OutTraceD("GetCaps(S%d): lpdds=%x FIXED caps=%x(%s)\n", dxInterface, lpdds, caps->dwCaps, ExplainDDSCaps(caps->dwCaps));
+ return res;
+}
+
+HRESULT WINAPI extGetCaps1S(LPDIRECTDRAWSURFACE lpdds, LPDDSCAPS caps)
+{
+ return extGetCapsS(1, pGetCaps1S, lpdds, caps);
+}
+HRESULT WINAPI extGetCaps2S(LPDIRECTDRAWSURFACE lpdds, LPDDSCAPS caps)
+{
+ return extGetCapsS(2, pGetCaps2S, lpdds, caps);
+}
+HRESULT WINAPI extGetCaps3S(LPDIRECTDRAWSURFACE lpdds, LPDDSCAPS caps)
+{
+ return extGetCapsS(3, pGetCaps3S, lpdds, caps);
+}
+HRESULT WINAPI extGetCaps4S(LPDIRECTDRAWSURFACE lpdds, LPDDSCAPS2 caps)
+{
+ return extGetCapsS(4, (GetCapsS_Type)pGetCaps4S, lpdds, (LPDDSCAPS)caps);
+}
+HRESULT WINAPI extGetCaps7S(LPDIRECTDRAWSURFACE lpdds, LPDDSCAPS2 caps)
+{
+ return extGetCapsS(7, (GetCapsS_Type)pGetCaps7S, lpdds, (LPDDSCAPS)caps);
+}
+
+ULONG WINAPI extReleaseD(LPDIRECTDRAW lpdd)
+{
+ ULONG ref;
+ int dxversion;
+
+ dxversion=lpddHookedVersion(lpdd); // must be called BEFORE releasing the session!!
+ OutTraceD("Release(D): lpdd=%x\n", lpdd);
+
+ ref=(*pReleaseD)(lpdd);
+
+ if (lpdd == lpServiceDD) { // v2.1.87: fix for Dungeon Keeper II
+ OutTraceD("Release(D): service lpdd=%x version=%d\n", lpdd, dxversion);
+ if(dxversion >= 4){
+ // directdraw recent versions link the objects to the directdraw session, so that they MUST be
+ // released BEFORE the parent object
+ int ServiceObjCount;
+ ServiceObjCount=0;
+
+ if (lpDDSEmu_Prim) ServiceObjCount++;
+ if (lpDDSEmu_Back) ServiceObjCount++;
+ //if (lpDDSHDC) ServiceObjCount++;
+ if (lpDDC) ServiceObjCount++;
+ if (lpDDSBack) ServiceObjCount++;
+
+ OutTraceD("Release(D): ref=%x ServiceObjCount=%x\n", ref, ServiceObjCount);
+ // BEWARE: releasing surfaces will cause releasing references of parent obj directdraw, then
+ // lpdd->Release() would be called recursively without the strict check ref==ServiceObjectCount !!!
+ if ((int)ref==ServiceObjCount){
+ OutTraceD("Release(D): RefCount reached service object count=%d - RESET condition\n", ServiceObjCount);
+ if (lpDDSBack) {
+ OutTraceD("Release(D): released lpDDSBack=%x\n", lpDDSBack);
+ while(lpDDSBack->Release());
+ lpDDSBack=NULL;
+ }
+ if (lpDDC) {
+ OutTraceD("Release(D): released lpDDC=%x\n", lpDDC);
+ while(lpDDC->Release());
+ lpDDC=NULL;
+ }
+ if (lpDDSEmu_Prim) {
+ OutTraceD("Release(D): released lpDDSEmu_Prim=%x\n", lpDDSEmu_Prim);
+ while(lpDDSEmu_Prim->Release());
+ lpDDSEmu_Prim=NULL;
+ }
+ if (lpDDSEmu_Back) {
+ OutTraceD("Release(D): released lpDDSEmu_Back=%x\n", lpDDSEmu_Back);
+ while(lpDDSEmu_Back->Release());
+ lpDDSEmu_Back=NULL;
+ }
+ if (lpDDP) {
+ OutTraceD("Release(D): released lpDDP=%x\n", lpDDP);
+ while(lpDDP->Release());
+ lpDDP=NULL;
+ }
+ lpServiceDD = NULL; // v2.1.87
+ ref=0; // it should be ....
+ }
+ }
+ else {
+ // directdraw older versions automatically free all linked objects when the parent session is closed.
+ if (ref==0){
+ OutTraceD("Release(D): RefCount=0 - service object RESET condition\n");
+ lpDDSEmu_Prim=NULL;
+ lpDDSEmu_Back=NULL;
+ lpDDC=NULL;
+ lpDDSBack=NULL;
+ lpDDP=NULL;
+ }
+ }
+ }
+
+ OutTraceD("Release(D): lpdd=%x ref=%x\n", lpdd, ref);
+ return ref;
+}
+
+HRESULT WINAPI extCreateClipper(LPDIRECTDRAW lpdd, DWORD dwflags,
+ LPDIRECTDRAWCLIPPER FAR* lplpDDClipper, IUnknown FAR* pUnkOuter)
+{
+ HRESULT res;
+ OutTraceD("CreateClipper: lpdd=%x flags=%x\n", lpdd, dwflags);
+ res=(*pCreateClipper)(lpdd, dwflags, lplpDDClipper, pUnkOuter);
+ if(res) {
+ OutTraceE("CreateClipper: ERROR res=%x(%s)\n", lpdd, res, ExplainDDError(res));
+ return res;
+ }
+ HookDDClipper(lplpDDClipper);
+ return res;
+}
+
+HRESULT WINAPI extReleaseC(LPDIRECTDRAWCLIPPER lpddClip)
+{
+ ULONG ref;
+ BOOL IsClosed;
+
+ // handling of service closed clipper
+ IsClosed=0;
+ __try{DWORD dw=(DWORD)(*pReleaseC);}
+ __except (EXCEPTION_EXECUTE_HANDLER){
+ OutTraceD("Exception at %d\n",__LINE__);
+ IsClosed=1;
+ };
+
+ // avoid crashing....
+ ref= IsClosed ? 0 : (*pReleaseC)(lpddClip);
+
+ OutTraceD("Release(C): PROXED lpddClip=%x ref=%x\n", lpddClip, ref);
+ if (lpddClip==lpDDC && ref==0) {
+ OutTraceD("Release(C): Clearing lpDDC pointer\n");
+ lpDDC=NULL;
+ }
+ return ref;
+}
+
+HRESULT WINAPI extGetSurfaceDesc(GetSurfaceDesc_Type pGetSurfaceDesc, LPDIRECTDRAWSURFACE lpdds, LPDDSURFACEDESC lpddsd)
+{
+ HRESULT res;
+ BOOL IsPrim;
+ IsPrim=dxw.IsAPrimarySurface(lpdds);
+
+ if (!pGetSurfaceDesc) {
+ OutTraceE("GetSurfaceDesc: ERROR no hooked function\n");
+ return DDERR_INVALIDPARAMS;
+ }
+
+ res=(*pGetSurfaceDesc)(lpdds, lpddsd);
+ OutTraceD("GetSurfaceDesc: %slpdds=%x%s res=%x(%s)\n",
+ res?"ERROR ":"", lpdds, IsPrim?"(PRIM)":"", res, ExplainDDError(res));
+ if(res) {
+ OutTraceE("GetSurfaceDesc: ERROR err=%d(%s) at %d\n", res, ExplainDDError(res), __LINE__);
+ return res;
+ }
+
+ LogSurfaceAttributes(lpddsd, "GetSurfaceDesc", __LINE__);
+
+ if (IsPrim) {
+ // expose original caps
+ if (dxw.dwFlags1 & EMULATESURFACE) {
+ lpddsd->ddpfPixelFormat = dxw.VirtualPixelFormat;
+ }
+ //lpddsd->ddsCaps.dwCaps=dxw.dwPrimarySurfaceCaps;
+ // V2.1.84: better .OR. the capabilities (you don't ask but get for DDSCAPS_VISIBLE...)
+ lpddsd->ddsCaps.dwCaps |= dxw.dwPrimarySurfaceCaps;
+ lpddsd->ddsCaps.dwCaps |= DDSCAPS_PRIMARYSURFACE|DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER; // you never know....
+ lpddsd->dwBackBufferCount=dxw.dwBackBufferCount;
+ lpddsd->dwHeight=dxw.GetScreenHeight();
+ lpddsd->dwWidth=dxw.GetScreenWidth();
+
+ //OutTraceD("GetSurfaceDesc: DEBUG restoring original caps=%x(%s) size=(%dx%d) BackBufferCount=%d\n",
+ // lpddsd->ddsCaps.dwCaps, ExplainDDSCaps(lpddsd->ddsCaps.dwCaps),
+ // lpddsd->dwWidth=dxw.GetScreenWidth(), lpddsd->dwHeight=dxw.GetScreenHeight(),
+ // lpddsd->dwBackBufferCount);
+
+ DumpSurfaceAttributes(lpddsd, "GetSurfaceDesc FIXED", __LINE__);
+ }
+
+ return res;
+}
+
+// Beware: despite the surface version, some game (The Sims!!!) intentionally uses a different dwSize, so that
+// you shouldn't reset the value
+
+HRESULT WINAPI extGetSurfaceDesc1(LPDIRECTDRAWSURFACE lpdds, LPDDSURFACEDESC lpddsd)
+{
+ if (!lpddsd->dwSize) lpddsd->dwSize = sizeof(DDSURFACEDESC); // enforce correct dwSize value
+ switch(lpddsd->dwSize){
+ case sizeof(DDSURFACEDESC):
+ if (pGetSurfaceDesc1) return extGetSurfaceDesc(pGetSurfaceDesc1, lpdds, lpddsd);
+ break;
+ case sizeof(DDSURFACEDESC2):
+ if (pGetSurfaceDesc4) return extGetSurfaceDesc((GetSurfaceDesc_Type)pGetSurfaceDesc4, (LPDIRECTDRAWSURFACE)lpdds, (LPDDSURFACEDESC)lpddsd);
+ break;
+ default:
+ OutTraceD("GetSurfaceDesc: ASSERT - bad dwSize=%d lpdds=%x at %d\n", lpddsd->dwSize, lpdds, __LINE__);
+ return DDERR_INVALIDOBJECT;
+ break;
+ }
+ OutTraceD("GetSurfaceDesc: ASSERT - missing hook lpdds=%x dwSize=%d(%s) at %d\n",
+ lpdds, lpddsd->dwSize, lpddsd->dwSize==sizeof(DDSURFACEDESC)?"DDSURFACEDESC":"DDSURFACEDESC2", __LINE__);
+ return DDERR_INVALIDOBJECT;
+}
+
+HRESULT WINAPI extGetSurfaceDesc2(LPDIRECTDRAWSURFACE2 lpdds, LPDDSURFACEDESC2 lpddsd)
+{
+ if (!lpddsd->dwSize) lpddsd->dwSize = sizeof(DDSURFACEDESC2); // enforce correct dwSize value
+ switch(lpddsd->dwSize){
+ case sizeof(DDSURFACEDESC):
+ if (pGetSurfaceDesc1) return extGetSurfaceDesc(pGetSurfaceDesc1, (LPDIRECTDRAWSURFACE)lpdds, (LPDDSURFACEDESC)lpddsd);
+ break;
+ case sizeof(DDSURFACEDESC2):
+ if (pGetSurfaceDesc4) return extGetSurfaceDesc((GetSurfaceDesc_Type)pGetSurfaceDesc4, (LPDIRECTDRAWSURFACE)lpdds, (LPDDSURFACEDESC)lpddsd);
+ break;
+ default:
+ OutTraceD("GetSurfaceDesc: ASSERT - bad dwSize=%d lpdds=%x at %d\n", lpddsd->dwSize, lpdds, __LINE__);
+ return DDERR_INVALIDOBJECT;
+ }
+ OutTraceD("GetSurfaceDesc: ASSERT - missing hook lpdds=%x dwSize=%d(%s) at %d\n",
+ lpdds, lpddsd->dwSize, lpddsd->dwSize==sizeof(DDSURFACEDESC)?"DDSURFACEDESC":"DDSURFACEDESC2", __LINE__);
+ return DDERR_INVALIDOBJECT;
+}
+
+HRESULT WINAPI extReleaseP(LPDIRECTDRAWPALETTE lpddPalette)
+{
+ // v2.1.26: Release Palette FIX:
+ // Uprising 2 crashed trying to use palette functions after having fully released the
+ // current palette (ref=0!) causing a game crash. The fix pretends that the palette
+ // was released when attempting the operation to the last object reference (LastRefCount==1)
+ // returning a ref 0 without actually releasing the object.
+ //v2.02.08: Better fix: to avoid the problem, just remember to NULL-ify the global main
+ // palette pointer lpDDP
+ ULONG ref;
+ ref=(*pReleaseP)(lpddPalette);
+ OutTraceD("Release(P): lpddPalette=%x ref=%x\n", lpddPalette, ref);
+ if(lpddPalette==lpDDP && ref==0){
+ OutTraceD("Release(P): clearing lpDDP=%x->NULL\n", lpDDP);
+ lpDDP=NULL;
+ }
+ return ref;
+}
diff --git a/dll/syslibs.cpp b/dll/syslibs.cpp
index e1001d6..e9eda15 100644
--- a/dll/syslibs.cpp
+++ b/dll/syslibs.cpp
@@ -1308,20 +1308,26 @@ ATOM WINAPI extRegisterClassExA(WNDCLASSEX *lpwcx)
return (*pRegisterClassExA)(lpwcx);
}
-BOOL WINAPI extClientToScreen(HWND whnd, LPPOINT lppoint)
+BOOL WINAPI extClientToScreen(HWND hwnd, LPPOINT lppoint)
{
- if (lppoint && dxw.IsFullScreen() && (whnd == dxw.GethWnd()))
+ OutTraceB("ClientToScreen: hwnd=%x hWnd=%x FullScreen=%x point=(%d,%d)\n",
+ hwnd, dxw.GethWnd(), dxw.IsFullScreen(), lppoint->x, lppoint->y);
+
+ if (lppoint && dxw.IsFullScreen() && (hwnd == dxw.GethWnd()))
return 1;
else
- return (*pClientToScreen)(whnd, lppoint);
+ return (*pClientToScreen)(hwnd, lppoint);
}
-BOOL WINAPI extScreenToClient(HWND whnd, LPPOINT lppoint)
+BOOL WINAPI extScreenToClient(HWND hwnd, LPPOINT lppoint)
{
- if (lppoint && dxw.IsFullScreen() && (whnd == dxw.GethWnd()))
+ OutTraceB("ScreenToClient: hwnd=%x hWnd=%x FullScreen=%x point=(%d,%d)\n",
+ hwnd, dxw.GethWnd(), dxw.IsFullScreen(), lppoint->x, lppoint->y);
+
+ if (lppoint && dxw.IsFullScreen() && (hwnd == dxw.GethWnd()))
return 1;
else
- return (*pScreenToClient)(whnd, lppoint);
+ return (*pScreenToClient)(hwnd, lppoint);
}
BOOL WINAPI extGetClientRect(HWND hwnd, LPRECT lpRect)
@@ -2160,6 +2166,7 @@ HDC WINAPI extBeginPaint(HWND hwnd, LPPAINTSTRUCT lpPaint)
BOOL WINAPI extEndPaint(HWND hwnd, const PAINTSTRUCT *lpPaint)
{
BOOL ret;
+ HRESULT WINAPI extReleaseDC(LPDIRECTDRAWSURFACE lpdds, HDC FAR hdc);
// proxy part ...
OutTraceD("GDI.EndPaint: hwnd=%x lpPaint=%x\n", hwnd, lpPaint);
@@ -2170,6 +2177,14 @@ BOOL WINAPI extEndPaint(HWND hwnd, const PAINTSTRUCT *lpPaint)
// if not in fullscreen mode, that's all!
if(!dxw.IsFullScreen()) return ret;
+ // v2.02.09: on MAPGDITOPRIMARY, release the PrimHDC handle
+ if(dxw.dwFlags1 & MAPGDITOPRIMARY) {
+ if(pReleaseDC && dxw.lpDDSPrimHDC){
+ extReleaseDC(dxw.lpDDSPrimHDC, PrimHDC);
+ OutTraceD("GDI.EndPaint: released hdc=%x\n", PrimHDC);
+ }
+ }
+
return ret;
}
diff --git a/host/dxwndhost.vs2008.suo b/host/dxwndhost.vs2008.suo
index 37ce158..3e0580f 100644
Binary files a/host/dxwndhost.vs2008.suo and b/host/dxwndhost.vs2008.suo differ
diff --git a/makebuild.bat b/makebuild.bat
deleted file mode 100644
index 4b901f5..0000000
--- a/makebuild.bat
+++ /dev/null
@@ -1,17 +0,0 @@
-del dll\dxwnd.*.user
-del dll\dxwnd.*.ncb
-
-del host\dxwndhost.*.user
-del host\dxwndhost.*.ncb
-
-copy Release\dxwnd.exe build
-copy Release\dxwnd.dll build
-
-del dll\Debug\*.*
-del dll\Release\*.*
-
-del host\Debug\*.*
-del host\Release\*.*
-
-echo build done
-pause