In specific case SetCursorPos could cause crazy mouse movement that made the mouse click out of player's control.While the game call this function quite frequently, if i add some sleep to slow down the crazy mouse movement, the whole game become lag. Finally i got an idea is using mouse_event to emulate SetCursorPos, and it works , for this i would like to ask for a new flag(Maybe "Emulate SetCursorPos" ? ;P). The code is something like this:
USER32.CPP extSetCursorPos LINE 1150
//***********Add after MODIFYMOUSE*******//
if(NEWFLAG) {
DWORD nx = x*65535/GetSystemMetrics(0);
DWORD ny = y*65535/GetSystemMetrics(1);
mouse_event(MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_MOVE,nx,ny,0,0);
return 1;
}
//***************************************//
res=0;
if (pSetCursorPos) res=(*pSetCursorPos)(x,y);
2 . FPS control for GDI under Non-windowed mode(i.e. uncheck"run in window flag")
Previous dxwnd version handle this quite well, however in recent versions this function was supressed(or forgot?) after code revision....The code is something like this:
This is really a headache. Dxwnd Shareddc mode(i.e. check"share ddraw and gdi DC" flag) has a leakage issue.
I tried to find it out by myself, at the beginning dxwnd debug log gave me a ddraw out of memory error, it's a baffling result.....anyhow finally i found out is a GDI DC leakage from GetPrimaryDC....While the game calling bitblt frequently, the leaked GDI DCs rapidly increased to 10000 then freeze the program. It wasted me two days to learn this new dxwnd shareddc schema while i doubt whether the new created virtulhdc has any unreleased leakage, but the pefect coded logic gave me nothing...after all....it turns out this leak has nothing to do with compatiable DC, it is from GetDCOrgEx! oh....my....i was glad i finally got the culprit......however.....after some searching here.... faint...Narzoul had reported this year ago!! But it seems that you did not care about it at that time: https://sourceforge.net/p/dxwnd/discussion/general/thread/f8f65f21/?limit=25&page=1#1f02/a406
It is really not easy to understand his report and pay enough attention if you had never investigated on Shareddc....alright.. .long enough...TLDR..
Here is the code:
SHAREDDC.CPP GetPrimaryDC LINE 198
POINT origin = {};
POINT mainwin = {};
(*pGetDCOrgEx)(hdc, &origin);
//(*pGetDCOrgEx)((*pGDIGetDC)(dxw.GethWnd()), &mainwin);//Leakage
//************Release in time************//
HDC WINHDC = (*pGDIGetDC)(dxw.GethWnd());
(*pGetDCOrgEx)(WINHDC, &mainwin);
(*pGDIReleaseDC)(dxw.GethWnd(), WINHDC);
//***************************************//
origin.x -= mainwin.x;
origin.y -= mainwin.y;
ALL THESE 3 PIECES CODE(v2_04_29_src) HAD TESTED ON MY PC, ALL WORKS FINE.
So they are all depends on you gho, if you want to apply them.
Would i expect any patch for these in the next dxwnd release? Thank you!
Last edit: gsky916 2017-05-13
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Ah, my friend gsky916! It's a real pleasure to have you here again.
First of all, don't blame too soon SDL support: this technolgy is interesting because, apart from supporting SDL games, I feel it could be used internally by DxWnd to perform critical operations such as scaled blitting. Do you remember how much effort we placed in the parallel processing of bilinear filtering? The final result was good, but opened our minds to other huge possibilities, like taking advantage of accelerated hw of video cards. But why reinventing the wheel if most of what we need could be implemented already in a SDL scaled blitting function? I'm going to investigate this possibility, it would be great to have the open source community to perform optimized code for DxWnd!
Then, back to your topics:
1 . A new function request.
Very good, no problems to add an extra flag for this purpose. I'd like to have some more details about this problem. You said that SetCursorPos can cause problems, but when (what game? which situation?) and why? Is is possible that simply the problem is caused by some wrong calculation in DxWnd scaled position? Could it be fixed simply by trimming the x,y coordinates within the window boundaries? More, why the 65535 constant (it sould be (WORD)-1, if I'm not mistaken)? How did you get to that idea?
2 . FPS control for GDI under Non-windowed mode
Again, no problem. I'll squeeze my mind trying to remember if there was some reason for this suppression, but if anything comes to my mind I'll recover the missing code.
2 . FPS control for GDI under Non-windowed mode
Resource leaking, my worst nightmare! You can't immagine how happy I am to receive some competent help pointing precisely not to a problem but to a solution! Thank you, gsky916.
So, in conclusion I'll happily try to include all three moifications in next release, hopefully soon, and hopefully together with some SDL progress! ;)
P.s. one of these days, I fear not so soon, when I'll stop moving, replacing, adding and changing the GUI interface, I think that I'll call you again to complete DxWnd chinese support, will you?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Oh, my, incredibly my memory recalled something !
About request #2, I remember I deleted that code because of resource leakage: there are two handles to GDI objects that wouldn't be freed by making the fix in that way.
But this is not a big problem, I can make it this way:
// v2.04.30 gsky916 fix, mod. for leakage handling BOOLbSkip=FALSE;if(IsToScreen&&(dxw.dwFlags3&NOGDIBLT))bSkip=TRUE;if(dxw.HandleFPS())bSkip=TRUE;if(bSkip){if(IsDCLeakageSrc)(*pGDIReleaseDC)(dxw.GethWnd(),hdcSrc);if(IsDCLeakageDest)(*pGDIReleaseDC)(dxw.GethWnd(),hdcDest);returnTRUE;}// v2.04.30 end of gsky916 fix
Last edit: gho 2017-05-13
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
**You said that SetCursorPos can cause problems, but when (what game? which situation?) and why? **
It is WF1,another game of wind fantasy series. Do you remember how to control the sprite in wfsp, here in wf1 mostly the same, you need to click the "move button" then choose the place on the battlefield where you want to move to....Unfortunately WF1 will call SetCursorPos whenever you click the "move button" and set your mouse to somewhere unwanted...Whats more, it seems SetCursorPos carried out too fast, while you click "move button"(press mouse button down)-->your mouse was set to somewhere unwanted at the same time(maybe less than 30ms?)--->(while mouse button up)you already move to the wrong place(no time leave to you for choosing).
Please note this issue has nothing to do with frame bilting or performance counter.
There are three ideas for this :
1 . Hook the mouse and insert a ButtonUP event whenever you press down your mouse , this event must be carried out before SetCursorPos to avoid unwanted movement.
Disadvantages: You could never drag items.....
2 . Slow down SetCursorPos by giving it some sleep()
Disadvantages: the game call SetCursorPos frequently in a lot other places, the whole game become lag.
3 . My emulation idea: MOUSEEVENTF_MOVE do not have overquick problem and have the same effect as SetCursorPos.
Disadvantages: Not find yet.
Is is possible that simply the problem is caused by some wrong calculation in DxWnd scaled position?
NO....It is the game itself...
**Could it be fixed simply by trimming the x,y coordinates within the window boundaries? **
NO...SetCursorPos set your mouse to anywhere within the window....just unwanted places(without your decision), there is no fixed area for the cursor in the game, you could move the cursor to different coordinates under different circumstances, so i can not give out a fixed x,y coordinates for this.
More, why the 65535 constant (it sould be (WORD)-1, if I'm not mistaken)? How did you get to that idea?
I don't know. 65535 constant was just copied from MSDN:https://msdn.microsoft.com/en-us/library/windows/desktop/ms646260%28v=vs.85%29.aspx
Maybe easy for understanding?
If MOUSEEVENTF_ABSOLUTE value is specified, dx and dy contain normalized absolute coordinates between 0 and 65,535. The event procedure maps these coordinates onto the display surface. Coordinate (0,0) maps onto the upper-left corner of the display surface, (65535,65535) maps onto the lower-right corner.
I'm not sure if (WORD)-1 should be used here?
Last edit: gsky916 2017-05-14
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Ok, let's summarize: so your suggested patch is equivalent to the following code:
if(NEWFLAG) {
DWORD nx = x*65535/GetSystemMetrics(SM_CXSCREEN);
DWORD ny = y*65535/GetSystemMetrics(SM_CYSCREEN);
mouse_event(MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_MOVE,nx,ny,0,0);
return TRUE; // ok
}
There are still a few things that puzzles me, and one in particular:
in DxWnd the mouse_event call is intercepted and neutralized (with "Keep cursor fixed" flag) or scaled (with "correct mouse position" flag). In general, within DxWnd code I never make references to hooked system calls because their behaviour may change according to game flags. The solution is to ensure that these calls do are hooked and use the saved original pointer instead, (*pmouse_event) in this case. But the division by GetSystemMetrics(SM_CXSCREEN) and GetSystemMetrics(SM_CYSCREEN) makes me wonder if these weren't added only to compensate the scaling effect of the input_mouse hooker! The answer should be in dxwnd.log file wheere you could find a line like this:
The MSDN note is coherent with your fix, but only if the x,y coordinates are not scaled further by the hooker
If MOUSEEVENTF_ABSOLUTE value is specified, dx and dy contain normalized
absolute coordinates between 0 and 65,535. The event procedure maps these
coordinates onto the display surface. Coordinate (0,0) maps onto the
upper-left corner of the display surface; coordinate (65535,65535) maps onto
the lower-right corner. In a multimonitor system, the coordinates map to the
primary monitor.
Finally, there is a last concern about this MSDN statement:
The mouse_event function synthesizes mouse motion and button clicks.
Note This function has been superseded. Use SendInput instead.
In any case, I assme that mouse_event will last for a while for compatibility reasons, so I think I'm going to make the fix this way:
if(NEWFLAG & pmouse_event) {
DWORD nx = x*65535/GetSystemMetrics(SM_CXSCREEN);
DWORD ny = y*65535/GetSystemMetrics(SM_CYSCREEN);
(*pmouse_event)(MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_MOVE,nx,ny,0,0);
return TRUE; // ok
}
Some leaked alpha release will follow ....
... here it is, ready cooked, but untested. The new flag is "mouse move by event", please try it together with the other two fixes and report the results. Please, do not try to run SDL games, it's a whole mess there ... ;)
I used mouse_event just because it is simple. I believe it should last for some time since it is widely used..Any way it is an experimental flag.
the division by GetSystemMetrics(SM_CXSCREEN) and GetSystemMetrics(SM_CYSCREEN) makes me wonder if these weren't added only to compensate the scaling effect of the input_mouse hooker.
Would you please clarify?
Oh, I forgot!! I use this together with the "correct mouse position" flag!
That's why I add this code after MODIFYMOUSE, coordinate had already been remapped!
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I must say current sw processed bilinear algorythms in dxwnd is fairly well optimized by Ryan Geiss plus our further effort....It's not easy to achieve further significant improvements in sw way, so hw is a good choice.
I had tried dgVoodoo2 mentioned in above link. It uses D3D11 to render ddraw.The result is quite well, CPU cheap,fast, high quality...and also provided windowed mode arbitrary resize. However the compatibility still need to be improved...Both my Nvidia card and AMD card can not run test games with dgVoodoo2(causing crash), so i can only use a intel integrated chips to do the test. The result shows Dxwnd could even achieve better performance with an I7 cpu comparing to a dgVoodoo2 with an integrated chip, regardless of much more cpu consuming...Any how I believe a high end GPU should get much better benchmark here. dgVoodoo2 also provided a sw mode but it is really slow(maybe is for testing purpose), not eligible to compare with dxwnd. Well, Anyway sw render should always be a reserved mode since it would get better compatibility under different situations..
Now my question would be how about SDL compatibility(GPU support) and efficiency?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
In fact there are Chinese users who can not wait for such a long time and began to made personal Chinese versions while distribute on internet forums years(2015?) ago.....
At the beginning even original copyright information of dxwnd was deleted, I tried to contact the translator and he agreed to restore. I ask him to come here so that could get more support but he is not willing to contact with you...There is no source code with the personal distributions, so i also can not confirm the reliability.
Now Dxwnd has more and more flags, should I suggest hide some of them for normal users?
There is an "Expert Mode", I think it's a good idea, maybe you can make a generic mode which only show some commonly used flags. People dazzled by tons of flags...For instance, how many normal users would understand"texture power of two"flag? Even you translated it, it's meaningless. I suggest some expert mode flag should leave them in english, that could be better for understanding, for users who can really understand them, since most tech terms are original named with english, translation here is not always a good choice.
Last edit: gsky916 2017-05-14
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I agree with you and I was thinking at the very same solution. The only problem is how to code it in a relatively simple way, without throwing away the current GUI code. I have some ideas for simplifications, like non-expert mode disabling some (most ?) of the configuration tabs.
The difficult thing, in effect, would be to eliminate part of the single flags without making the GUI look like a swiss cheese (the one with the big holes!). Another idea would be to insert the hi-tech cumbersome fields like "texture power of two" in a drop-down list where you can pick them singularly, but only if interested, pretty much like MS shims are selected.
A nice side effect would also be that only the non-expert mode should receive language support and decent translations, while.... well, shouldn't a real expert know some english?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
It depends...expert mode would translate when the flag translation is nessary and only if you have an accurately corresponding translated tech terms for it in your language. "run unhooked"---->yes, "EXCLUSIVE coop level"---->maybe no.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
gsky@916, please report on the behavior of my second leaked alpha (v2.04.30.a1.rar) so that I could be sure of the changes and leave them on next public release.
P.s. do you think I could retrieve and run this WF1 game? I'm just curious ....
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I'm testing... ASAP I'll give you the result. weird... seems the v2.04.30.a1 caused some lag for the tested gdi game(not wf1...i wont't tell you that is wf2:P). I must understand whether it's fix2(fpshandle) or fix3(leak), maybe fix2?
For WF1 of cause you could, but i only have CD image on hand right now, should i tranfer it to you?
And I'm not sure if you could deal with the messy incomprehensible characters....
Last edit: gsky916 2017-05-15
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
File v2.03.30.a3.rar with updated log, but the MOUSEMOVEBYEVENT will be only on log first line because of the presumable high number of log lines otherwise.
File dd.rar with full source code of current alpha, of course different from last one sent (I can't stop doing changes!) but with GDI32 and USER32 parts pretty stable.
Good hunt!
That is right since in the code I used "(*pmouse_event)" instead of "mouse_event".
Since the mouse_event call is hooked by DxWnd, when you reference mouse_event you risk to activate the hooker that is scaling the coordinates again or making other tricks (look for the extmouse_event internal function within DxWnd code...), so to have a better control of the operations I used (*pmouse_event) that holds the original function pointer.
Of course I asked you to test the functionality because I don't know whether the further coordinate scaling is unwanted or requested: my fix may behave differently from yours, so it is necessary to verify it a little.
Obviously, since the "FIX MOUSEEVENTF_ABSOLUTE (%d,%d) -> (%d,%d)" string is printed by the mouse_event hooker, using the original function pointer bypasses this code so that it is no longer visible.
Last edit: gho 2017-05-15
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
No problem! I try to find this string just because you ask me to get it for you. I must admit I did not look into the log(outtrace) implementation..So now question is do you still need this log information from me? Or do I need to modify the code to do some test for you?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Now after fix2, we put dxw.HandleFPS() before dxw.IsFullScreen(), so each time hooked bitblt will call handlefps twice in these cases that will caused the lag. Maybe we should make a further fix for this?
Last edit: gsky916 2017-05-15
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Definitely yes, here it is, probably broken somewhere else ... :(
The fix is practically returning to the original source code, but let me give a few explainations ...
dxw.HandleFPS does several things, from drawing the FPS counter to inserting a delay between frames or returning TRUE if the frame should be skipped because the frame frequency is too high.
This third usage if skipping frames is why you see the instruction
if(dxw.HandleFPS())return;
Now, in a typical ddraw game that blits whole backbuffers to screen this makes sense: the result will be a little choppy because of the deletion of some trames, but the CPU will be releaved.
But in a typical GDI32/USER32 program where the window surface is blitte on rectangle at a time (individual sprites for mouse, animations and so forth) this possibility is quite dangerous, since it would lead to the disapparition of some elements of the scene! This is why I eliminated in this case the return statement.
Also, it is necessary to handle the additional complexity of blitting from / to different surface types, it would be wrong to introduce a delay between blits among memory surfaces.
So, this this: it should show the FPS counter, isn't it?
P.s. in the fix I inserted the HandleFPS operation in the default case, where it was forgotten. That should improve the case of default (unstretched) GDI handling.
I had looked into the HandleFPS code so I can undertand your concern.
Howerver, in v2.04.30.a4, after returning to the original source code, FPS control won't work anymore for GDI under Non-windowed mode(i.e. when uncheck the "run in window flag") .
My original purpose is to fix that issue, so only improve the case of default (unstretched) GDI handling is not enough.
I would like to remind you that when you use Non-windowed mode the instructions won't go into the IsFullScreen() block, so all these HandleFPS operations in these cases won't take effect.
Last edit: gsky916 2017-05-16
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Off topic: gosh, the DxWnd new look is really exciting. I couldn't believe my eyes to see that such a simplification was possible with that little effort. We're going pro!
Last edit: gho 2017-05-16
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Let's try this way: a dxw.HandleFPS was added in the else statement of the IsFullScreen condition, but only when the destination is a video surface (line 1055). It could work, provided that DxWnd knows about the main window handle in this situation. I can't try it right now, so again t's up to you....
BOOLWINAPIextGDIBitBlt(HDChdcDest,intnXDest,intnYDest,intnWidth,intnHeight,HDChdcSrc,intnXSrc,intnYSrc,DWORDdwRop){BOOLres;BOOLIsToScreen;BOOLIsFromScreen;BOOLIsDCLeakageSrc=FALSE;BOOLIsDCLeakageDest=FALSE;intFlux;OutTraceDW("GDI.BitBlt: HDC=%x(type=%s) nXDest=%d nYDest=%d nWidth=%d nHeight=%d hdcSrc=%x(type=%s) nXSrc=%d nYSrc=%d dwRop=%x(%s)\n",hdcDest,GetObjectTypeStr(hdcDest),nXDest,nYDest,nWidth,nHeight,hdcSrc,GetObjectTypeStr(hdcSrc),nXSrc,nYSrc,dwRop,ExplainROP(dwRop));OutTraceB("GDI.BitBlt: DEBUG FullScreen=%x target hdctype=%x(%s) hwnd=%x\n",dxw.IsFullScreen(),(*pGetObjectType)(hdcDest),ExplainDCType((*pGetObjectType)(hdcDest)),WindowFromDC(hdcDest));// beware: HDC could refer to screen DC that are written directly on screen, or memory DC that will be scaled to// the screen surface later on, on ReleaseDC or ddraw Blit / Flip operation. Scaling of rect coordinates is // needed only in the first case, and must be avoided on the second, otherwise the image would be scaled twice!if(hdcDest==NULL){// happens in Reah, hdc is NULL despite the fact that BeginPaint returns a valid DC. Too bad, we recover here ...hdcDest=(*pGDIGetDC)(dxw.GethWnd());OutTraceB("GDI.BitBlt: DEBUG hdc dest=NULL->%x\n",hdcDest);IsDCLeakageDest=TRUE;}if(hdcSrc==NULL){hdcSrc=(*pGDIGetDC)(dxw.GethWnd());OutTraceB("GDI.BitBlt: DEBUG hdc src=NULL->%x\n",hdcSrc);IsDCLeakageSrc=TRUE;}IsToScreen=(OBJ_DC==(*pGetObjectType)(hdcDest));IsFromScreen=(OBJ_DC==(*pGetObjectType)(hdcSrc));Flux=(IsToScreen?1:0)+(IsFromScreen?2:0);// v2.04.30 fixed handlers leakage if(IsToScreen&&(dxw.dwFlags3&NOGDIBLT)){if(IsDCLeakageSrc)(*pGDIReleaseDC)(dxw.GethWnd(),hdcSrc);if(IsDCLeakageDest)(*pGDIReleaseDC)(dxw.GethWnd(),hdcDest);returnTRUE;}if(IsToScreen&&(dxw.dwFlags8&DUMPDEVCONTEXT))DumpHDC(hdcSrc,nXSrc,nYSrc,nWidth,nHeight);if(dxw.IsFullScreen()){//int nWSrc, nHSrc, intnWDest,nHDest;switch(dxw.GDIEmulationMode){caseGDIMODE_SHAREDDC:switch(Flux){case0:// memory to memoryres=(*pGDIBitBlt)(hdcDest,nXDest,nYDest,nWidth,nHeight,hdcSrc,nXSrc,nYSrc,dwRop);break;case1:// memory to screencase3:// screen to screendxw.HandleFPS();// handle refresh delayssdc.SetOrigin(nXSrc,nYSrc);sdc.GetPrimaryDC(hdcDest,hdcSrc);res=(*pGDIBitBlt)(sdc.GetHdc(),nXDest,nYDest,nWidth,nHeight,hdcSrc,nXSrc,nYSrc,dwRop);sdc.PutPrimaryDC(hdcDest,TRUE,nXDest,nYDest,nWidth,nHeight);break;case2:// screen to memorysdc.GetPrimaryDC(hdcSrc);res=(*pGDIBitBlt)(hdcDest,nXDest,nYDest,nWidth,nHeight,sdc.GetHdc(),nXSrc,nYSrc,dwRop);sdc.PutPrimaryDC(hdcSrc,TRUE,nXDest,nYDest,nWidth,nHeight);break;}break;caseGDIMODE_STRETCHED:nWDest=nWidth;nHDest=nHeight;switch(Flux){case1:// memory to screen// v1.03.58: BitBlt can blitfrom negative coordinates, StretchBlt can't!dxw.HandleFPS();// handle refresh delaysif(nXDest<0){intnXshift=-nXDest;nXDest=0;nXSrc+=nXshift;nWidth-=nXshift;nWDest-=nXshift;}if(nYDest<0){intnYshift=-nYDest;nYDest=0;nYSrc+=nYshift;nHeight-=nYshift;nHDest-=nYshift;}dxw.MapClient(&nXDest,&nYDest,&nWDest,&nHDest);break;case2:// screen to memorydxw.MapClient(&nXSrc,&nYSrc,&nWidth,&nHeight);break;default:break;}res=(*pGDIStretchBlt)(hdcDest,nXDest,nYDest,nWDest,nHDest,hdcSrc,nXSrc,nYSrc,nWidth,nHeight,dwRop);OutTraceB("GDI.BitBlt: DEBUG DC dest=(%d,%d) size=(%d,%d)\n",nXDest,nYDest,nWDest,nHDest);break;caseGDIMODE_EMULATED:if(hdcDest==dxw.RealHDC){hdcDest=dxw.VirtualHDC;dxw.HandleFPS();// handle refresh delays}res=(*pGDIBitBlt)(hdcDest,nXDest,nYDest,nWidth,nHeight,hdcSrc,nXSrc,nYSrc,dwRop);OutTraceB("GDI.BitBlt: DEBUG emulated hdc dest=%x->%x\n",dxw.RealHDC,hdcDest);break;default:if(IsToScreen)dxw.HandleFPS();// v2.04.30: handle refresh delaysres=(*pGDIBitBlt)(hdcDest,nXDest,nYDest,nWidth,nHeight,hdcSrc,nXSrc,nYSrc,dwRop);break;}}else{if(IsToScreen)dxw.HandleFPS();// v2.04.30: handle refresh delaysres=(*pGDIBitBlt)(hdcDest,nXDest,nYDest,nWidth,nHeight,hdcSrc,nXSrc,nYSrc,dwRop);}if(IsDCLeakageSrc)(*pGDIReleaseDC)(dxw.GethWnd(),hdcSrc);if(IsDCLeakageDest)(*pGDIReleaseDC)(dxw.GethWnd(),hdcDest);if(res&&IsToScreen){dxw.ShowOverlay(hdcDest);if(dxw.dwFlags8&MARKGDI32)dxw.Mark(hdcDest,FALSE,RGB(0,0,255),nXDest,nYDest,nWidth,nHeight);}if(!res)OutTraceE("GDI.BitBlt: ERROR err=%d at %d\n",GetLastError(),__LINE__);returnres;}
Hope i will not disturb your SDL plan....
1 . A new function request.
In specific case SetCursorPos could cause crazy mouse movement that made the mouse click out of player's control.While the game call this function quite frequently, if i add some sleep to slow down the crazy mouse movement, the whole game become lag. Finally i got an idea is using mouse_event to emulate SetCursorPos, and it works , for this i would like to ask for a new flag(Maybe "Emulate SetCursorPos" ? ;P). The code is something like this:
2 . FPS control for GDI under Non-windowed mode(i.e. uncheck"run in window flag")
Previous dxwnd version handle this quite well, however in recent versions this function was supressed(or forgot?) after code revision....The code is something like this:
3.Leakage report
This is really a headache. Dxwnd Shareddc mode(i.e. check"share ddraw and gdi DC" flag) has a leakage issue.
I tried to find it out by myself, at the beginning dxwnd debug log gave me a ddraw out of memory error, it's a baffling result.....anyhow finally i found out is a GDI DC leakage from GetPrimaryDC....While the game calling bitblt frequently, the leaked GDI DCs rapidly increased to 10000 then freeze the program. It wasted me two days to learn this new dxwnd shareddc schema while i doubt whether the new created virtulhdc has any unreleased leakage, but the pefect coded logic gave me nothing...after all....it turns out this leak has nothing to do with compatiable DC, it is from GetDCOrgEx! oh....my....i was glad i finally got the culprit......however.....after some searching here.... faint...Narzoul had reported this year ago!! But it seems that you did not care about it at that time:
https://sourceforge.net/p/dxwnd/discussion/general/thread/f8f65f21/?limit=25&page=1#1f02/a406
It is really not easy to understand his report and pay enough attention if you had never investigated on Shareddc....alright.. .long enough...TLDR..
Here is the code:
ALL THESE 3 PIECES CODE(v2_04_29_src) HAD TESTED ON MY PC, ALL WORKS FINE.
So they are all depends on you gho, if you want to apply them.
Would i expect any patch for these in the next dxwnd release? Thank you!
Last edit: gsky916 2017-05-13
Ah, my friend gsky916! It's a real pleasure to have you here again.
First of all, don't blame too soon SDL support: this technolgy is interesting because, apart from supporting SDL games, I feel it could be used internally by DxWnd to perform critical operations such as scaled blitting. Do you remember how much effort we placed in the parallel processing of bilinear filtering? The final result was good, but opened our minds to other huge possibilities, like taking advantage of accelerated hw of video cards. But why reinventing the wheel if most of what we need could be implemented already in a SDL scaled blitting function? I'm going to investigate this possibility, it would be great to have the open source community to perform optimized code for DxWnd!
Then, back to your topics:
1 . A new function request.
Very good, no problems to add an extra flag for this purpose. I'd like to have some more details about this problem. You said that SetCursorPos can cause problems, but when (what game? which situation?) and why? Is is possible that simply the problem is caused by some wrong calculation in DxWnd scaled position? Could it be fixed simply by trimming the x,y coordinates within the window boundaries? More, why the 65535 constant (it sould be (WORD)-1, if I'm not mistaken)? How did you get to that idea?
2 . FPS control for GDI under Non-windowed mode
Again, no problem. I'll squeeze my mind trying to remember if there was some reason for this suppression, but if anything comes to my mind I'll recover the missing code.
2 . FPS control for GDI under Non-windowed mode
Resource leaking, my worst nightmare! You can't immagine how happy I am to receive some competent help pointing precisely not to a problem but to a solution! Thank you, gsky916.
So, in conclusion I'll happily try to include all three moifications in next release, hopefully soon, and hopefully together with some SDL progress! ;)
P.s. one of these days, I fear not so soon, when I'll stop moving, replacing, adding and changing the GUI interface, I think that I'll call you again to complete DxWnd chinese support, will you?
Oh, my, incredibly my memory recalled something !
About request #2, I remember I deleted that code because of resource leakage: there are two handles to GDI objects that wouldn't be freed by making the fix in that way.
But this is not a big problem, I can make it this way:
Last edit: gho 2017-05-13
This is a leaked beta with fix #2 and #3. You can start testing it while you explain better fix#1.....
Some further explanation for #1:
**You said that SetCursorPos can cause problems, but when (what game? which situation?) and why? **
It is WF1,another game of wind fantasy series. Do you remember how to control the sprite in wfsp, here in wf1 mostly the same, you need to click the "move button" then choose the place on the battlefield where you want to move to....Unfortunately WF1 will call SetCursorPos whenever you click the "move button" and set your mouse to somewhere unwanted...Whats more, it seems SetCursorPos carried out too fast, while you click "move button"(press mouse button down)-->your mouse was set to somewhere unwanted at the same time(maybe less than 30ms?)--->(while mouse button up)you already move to the wrong place(no time leave to you for choosing).
Please note this issue has nothing to do with frame bilting or performance counter.
There are three ideas for this :
1 . Hook the mouse and insert a ButtonUP event whenever you press down your mouse , this event must be carried out before SetCursorPos to avoid unwanted movement.
Disadvantages: You could never drag items.....
2 . Slow down SetCursorPos by giving it some sleep()
Disadvantages: the game call SetCursorPos frequently in a lot other places, the whole game become lag.
3 . My emulation idea: MOUSEEVENTF_MOVE do not have overquick problem and have the same effect as SetCursorPos.
Disadvantages: Not find yet.
Is is possible that simply the problem is caused by some wrong calculation in DxWnd scaled position?
NO....It is the game itself...
**Could it be fixed simply by trimming the x,y coordinates within the window boundaries? **
NO...SetCursorPos set your mouse to anywhere within the window....just unwanted places(without your decision), there is no fixed area for the cursor in the game, you could move the cursor to different coordinates under different circumstances, so i can not give out a fixed x,y coordinates for this.
More, why the 65535 constant (it sould be (WORD)-1, if I'm not mistaken)? How did you get to that idea?
I don't know. 65535 constant was just copied from MSDN:https://msdn.microsoft.com/en-us/library/windows/desktop/ms646260%28v=vs.85%29.aspx
Maybe easy for understanding?
I'm not sure if (WORD)-1 should be used here?
Last edit: gsky916 2017-05-14
Ok, let's summarize: so your suggested patch is equivalent to the following code:
There are still a few things that puzzles me, and one in particular:
in DxWnd the mouse_event call is intercepted and neutralized (with "Keep cursor fixed" flag) or scaled (with "correct mouse position" flag). In general, within DxWnd code I never make references to hooked system calls because their behaviour may change according to game flags. The solution is to ensure that these calls do are hooked and use the saved original pointer instead, (*pmouse_event) in this case. But the division by GetSystemMetrics(SM_CXSCREEN) and GetSystemMetrics(SM_CYSCREEN) makes me wonder if these weren't added only to compensate the scaling effect of the input_mouse hooker! The answer should be in dxwnd.log file wheere you could find a line like this:
The MSDN note is coherent with your fix, but only if the x,y coordinates are not scaled further by the hooker
Finally, there is a last concern about this MSDN statement:
In any case, I assme that mouse_event will last for a while for compatibility reasons, so I think I'm going to make the fix this way:
Some leaked alpha release will follow ....
... here it is, ready cooked, but untested. The new flag is "mouse move by event", please try it together with the other two fixes and report the results. Please, do not try to run SDL games, it's a whole mess there ... ;)
Last edit: gho 2017-05-14
I used mouse_event just because it is simple. I believe it should last for some time since it is widely used..Any way it is an experimental flag.
Would you please clarify?
Oh, I forgot!! I use this together with the "correct mouse position" flag!
That's why I add this code after MODIFYMOUSE, coordinate had already been remapped!
Second topic: accelerated hw support.
I should admit i just read this topic:
Any way to force bi filtering without DxWnd's Bilinear option on GPU?
https://sourceforge.net/p/dxwnd/discussion/general/thread/d6b993ea/
I must say current sw processed bilinear algorythms in dxwnd is fairly well optimized by Ryan Geiss plus our further effort....It's not easy to achieve further significant improvements in sw way, so hw is a good choice.
I had tried dgVoodoo2 mentioned in above link. It uses D3D11 to render ddraw.The result is quite well, CPU cheap,fast, high quality...and also provided windowed mode arbitrary resize. However the compatibility still need to be improved...Both my Nvidia card and AMD card can not run test games with dgVoodoo2(causing crash), so i can only use a intel integrated chips to do the test. The result shows Dxwnd could even achieve better performance with an I7 cpu comparing to a dgVoodoo2 with an integrated chip, regardless of much more cpu consuming...Any how I believe a high end GPU should get much better benchmark here. dgVoodoo2 also provided a sw mode but it is really slow(maybe is for testing purpose), not eligible to compare with dxwnd. Well, Anyway sw render should always be a reserved mode since it would get better compatibility under different situations..
Now my question would be how about SDL compatibility(GPU support) and efficiency?
Third Topic: Translation
In fact there are Chinese users who can not wait for such a long time and began to made personal Chinese versions while distribute on internet forums years(2015?) ago.....
At the beginning even original copyright information of dxwnd was deleted, I tried to contact the translator and he agreed to restore. I ask him to come here so that could get more support but he is not willing to contact with you...There is no source code with the personal distributions, so i also can not confirm the reliability.
Now Dxwnd has more and more flags, should I suggest hide some of them for normal users?
There is an "Expert Mode", I think it's a good idea, maybe you can make a generic mode which only show some commonly used flags. People dazzled by tons of flags...For instance, how many normal users would understand"texture power of two"flag? Even you translated it, it's meaningless. I suggest some expert mode flag should leave them in english, that could be better for understanding, for users who can really understand them, since most tech terms are original named with english, translation here is not always a good choice.
Last edit: gsky916 2017-05-14
I agree with you and I was thinking at the very same solution. The only problem is how to code it in a relatively simple way, without throwing away the current GUI code. I have some ideas for simplifications, like non-expert mode disabling some (most ?) of the configuration tabs.
The difficult thing, in effect, would be to eliminate part of the single flags without making the GUI look like a swiss cheese (the one with the big holes!). Another idea would be to insert the hi-tech cumbersome fields like "texture power of two" in a drop-down list where you can pick them singularly, but only if interested, pretty much like MS shims are selected.
A nice side effect would also be that only the non-expert mode should receive language support and decent translations, while.... well, shouldn't a real expert know some english?
It depends...expert mode would translate when the flag translation is nessary and only if you have an accurately corresponding translated tech terms for it in your language. "run unhooked"---->yes, "EXCLUSIVE coop level"---->maybe no.
gsky@916, please report on the behavior of my second leaked alpha (v2.04.30.a1.rar) so that I could be sure of the changes and leave them on next public release.
P.s. do you think I could retrieve and run this WF1 game? I'm just curious ....
I'm testing... ASAP I'll give you the result. weird... seems the v2.04.30.a1 caused some lag for the tested gdi game(not wf1...i wont't tell you that is wf2:P). I must understand whether it's fix2(fpshandle) or fix3(leak), maybe fix2?
For WF1 of cause you could, but i only have CD image on hand right now, should i tranfer it to you?
And I'm not sure if you could deal with the messy incomprehensible characters....
Last edit: gsky916 2017-05-15
mouse move by event woks petfectly!(combine with "correct mouse position" flag )
Anyhow, I can't find any FIX MOUSEEVENTF_ABSOLUTE in the log?
uhm... seems the lag only happened when i using windowed mode, gho could you please give me a piece of v2.04.30.a1 modified GDI32.CPP?
File v2.03.30.a3.rar with updated log, but the MOUSEMOVEBYEVENT will be only on log first line because of the presumable high number of log lines otherwise.
File dd.rar with full source code of current alpha, of course different from last one sent (I can't stop doing changes!) but with GDI32 and USER32 parts pretty stable.
Good hunt!
I can see MOUSEMOVEBYEVENT on the first line, but i never see:
mouse_event: FIX MOUSEEVENTF_ABSOLUTE (%d,%d) -> (%d,%d)
As you mentioned above.
Last edit: gsky916 2017-05-15
That is right since in the code I used "(*pmouse_event)" instead of "mouse_event".
Since the mouse_event call is hooked by DxWnd, when you reference mouse_event you risk to activate the hooker that is scaling the coordinates again or making other tricks (look for the extmouse_event internal function within DxWnd code...), so to have a better control of the operations I used (*pmouse_event) that holds the original function pointer.
Of course I asked you to test the functionality because I don't know whether the further coordinate scaling is unwanted or requested: my fix may behave differently from yours, so it is necessary to verify it a little.
Obviously, since the "FIX MOUSEEVENTF_ABSOLUTE (%d,%d) -> (%d,%d)" string is printed by the mouse_event hooker, using the original function pointer bypasses this code so that it is no longer visible.
Last edit: gho 2017-05-15
No problem! I try to find this string just because you ask me to get it for you. I must admit I did not look into the log(outtrace) implementation..So now question is do you still need this log information from me? Or do I need to modify the code to do some test for you?
About the fix2(fpshandle) lag problem, I think I find out the point.
There are several dxw.HandleFPS() placed in different cases, They are delay routines in previous versions, this is one of them:
Now after fix2, we put dxw.HandleFPS() before dxw.IsFullScreen(), so each time hooked bitblt will call handlefps twice in these cases that will caused the lag. Maybe we should make a further fix for this?
Last edit: gsky916 2017-05-15
Definitely yes, here it is, probably broken somewhere else ... :(
The fix is practically returning to the original source code, but let me give a few explainations ...
dxw.HandleFPS does several things, from drawing the FPS counter to inserting a delay between frames or returning TRUE if the frame should be skipped because the frame frequency is too high.
This third usage if skipping frames is why you see the instruction
Now, in a typical ddraw game that blits whole backbuffers to screen this makes sense: the result will be a little choppy because of the deletion of some trames, but the CPU will be releaved.
But in a typical GDI32/USER32 program where the window surface is blitte on rectangle at a time (individual sprites for mouse, animations and so forth) this possibility is quite dangerous, since it would lead to the disapparition of some elements of the scene! This is why I eliminated in this case the return statement.
Also, it is necessary to handle the additional complexity of blitting from / to different surface types, it would be wrong to introduce a delay between blits among memory surfaces.
So, this this: it should show the FPS counter, isn't it?
P.s. in the fix I inserted the HandleFPS operation in the default case, where it was forgotten. That should improve the case of default (unstretched) GDI handling.
I had looked into the HandleFPS code so I can undertand your concern.
Howerver, in v2.04.30.a4, after returning to the original source code, FPS control won't work anymore for GDI under Non-windowed mode(i.e. when uncheck the "run in window flag") .
My original purpose is to fix that issue, so only improve the case of default (unstretched) GDI handling is not enough.
I would like to remind you that when you use Non-windowed mode the instructions won't go into the IsFullScreen() block, so all these HandleFPS operations in these cases won't take effect.
Last edit: gsky916 2017-05-16
Well, I'll try to fix that.
Off topic: gosh, the DxWnd new look is really exciting. I couldn't believe my eyes to see that such a simplification was possible with that little effort. We're going pro!
Last edit: gho 2017-05-16
Maybe some if condition clauses is necessary here...ah..should I stop squeezing my mind and just cross my fingers?
Let's try this way: a dxw.HandleFPS was added in the else statement of the IsFullScreen condition, but only when the destination is a video surface (line 1055). It could work, provided that DxWnd knows about the main window handle in this situation. I can't try it right now, so again t's up to you....
Last edit: gho 2017-05-16