VOGONS


Dark Rift

Topic actions

First post, by xttx

User metadata
Rank Newbie
Rank
Newbie

I've been reading this forum for, at least, 10 years, but this is my first post, because, I think, I don't know English well enough, so, I apologize in advance... And maybe I also choose the wrong section...

This game is quite obscure port from N64.
It doesn't work on PCem/dosbox, because of using windowed d3d mode, and voodoo can't do this.
And it doesn't work on windows 10 neither with nor without dgVoodoo because it require 16bit color mode and there is no way to switch windows 10 to this mode.
Compatibility option (reduced color mode) doesn't help.
In API monitor we can see, that this compatibility flag doesn't work at all, and the value returned from GetDeviceCaps still 0x20 (32 in decimal).
1a.jpg

Anyway, I disabled this check in ollyDbg:
5.jpg
I'm very noob in debugging, and I just hope, that I didn't break something. Because now, I have this:
"The operation requires the application to have exclusive mode, but the application does not have exclusive mode."

If I understood correctly, it's trying to change video mode to 640x480x16, it fails but begin to draw something, and then directx throw this error.
But, shouldn't dgVoodoo handle this somehow? I mean, when it was querying the current bit depth, it was in user32.dll, and dgVoodoo couldn't control this, but now, it's trying to change video mode, and fails. Did I actually break this thing, when trying to remove bit depth check, or am I doing something completely wrong here? 😢

Reply 2 of 6, by xttx

User metadata
Rank Newbie
Rank
Newbie

Yes, but with dxwnd it's not easy to figure out what settings a game needs. But I tried to set initial, max and limit resolution to 640x480 and every option that mention 16 bit color. It doesn't change anything, and I've got the same message about exclusive mode.

Reply 3 of 6, by Dege

User metadata
Rank l33t
Rank
l33t
xttx wrote:

And it doesn't work on windows 10 neither with nor without dgVoodoo because it require 16bit color mode and there is no way to switch windows 10 to this mode.
Compatibility option (reduced color mode) doesn't help.
In API monitor we can see, that this compatibility flag doesn't work at all, and the value returned from GetDeviceCaps still 0x20 (32 in decimal).

Hmm, Reduced color mode should work, dgVoodoo itself uses GetDeviceCaps (..., BITSPIXEL) to determine the desktop (primary surface) surface bit depth.
I've just tested it and it nicely works for 8 and 16 bit as well. (on Win 10)

xttx wrote:
I'm very noob in debugging, and I just hope, that I didn't break something. Because now, I have this: "The operation requires th […]
Show full quote

I'm very noob in debugging, and I just hope, that I didn't break something. Because now, I have this:
"The operation requires the application to have exclusive mode, but the application does not have exclusive mode."

If I understood correctly, it's trying to change video mode to 640x480x16, it fails but begin to draw something, and then directx throw this error.
But, shouldn't dgVoodoo handle this somehow? I mean, when it was querying the current bit depth, it was in user32.dll, and dgVoodoo couldn't control this, but now, it's trying to change video mode, and fails. Did I actually break this thing, when trying to remove bit depth check, or am I doing something completely wrong here? 😢

Removing the check shouldn't do any harm, except if the game stores that value for later usage.
Setting a display mode through DirectDraw requires exclusive mode (SetCooperativeLevel call on DirectDraw) (even through dgVoodoo), probably it's unset or set to DDSCL_NORMAL for some reason.
Could you extract the full DDraw/D3D API calls from API monitor, to see exactly what happens?

Reply 4 of 6, by Peixoto

User metadata
Rank Member
Rank
Member

If the game as you say, is "trying to change video mode to 640x480x16" and is using "windowed d3d mode" then it is calling ChangeDisplaySettings (https://msdn.microsoft.com/pt-br/librar ... s.85).aspx)

Reply 5 of 6, by xttx

User metadata
Rank Newbie
Rank
Newbie
Dege wrote:

Could you extract the full DDraw/D3D API calls from API monitor, to see exactly what happens?

Here it is: https://drive.google.com/file/d/0B8-6PBRjkqU6 … iew?usp=sharing
There are 2 logs.
I did a little bit more hacking (all credits for finding correct addresses goes to beha_r from friendly forum), and removed DDSCL_FULLSCREEN flag and changed arguments of IDirectDraw::SetDisplayMode to 1440x900x32. The game works now, but it's completely unplayable because of speed (I have something around 600fps).
With dgVoodoo the error still the same - "The operation requires the application to have exclusive mode, but the application does not have exclusive mode."
So, I included both logs, modified and original (in case, I broke something).

The game does not use Sleep(), timeGetTime(), GetTickCount(), QueryPerformanceFrequency(), QueryPerformanceCounter(), rdtsc and IDirectDrawSurface::Flip(). It draws frames directly with IDirectDrawSurface::Blt. So dxWnd is completely useless. I don't know if dgVoodoo could help with vsync, in this case.

Peixoto wrote:

If the game as you say, is "trying to change video mode to 640x480x16" and is using "windowed d3d mode" then it is calling ChangeDisplaySettings (https://msdn.microsoft.com/pt-br/librar ... s.85).aspx)

I don't know why, but this "compatibility manifest" is just not working as described there. Actually, it's not working at all. I don't know why, maybe it's just me, and I accidently broke something in windows, or maybe it's a conflict with other apps... It's just doesn't work. 🙁

PS. Regarding this speed issue, I tried to insert a sleep() in main loop, but I don't know yet how to insert winApi in asm if it's not already present in extern. Then, I tried to hook blt from outside. It's a real pain to work with hooks and unmanaged stuff in .net, I can't even google it! Finally, I figured out how to do this, but blt is called many times per frame, and I have got some misplaced textures and 2d overlays...

Reply 6 of 6, by Dege

User metadata
Rank l33t
Rank
l33t

Ok, thanks, I see what the problem is:

20	7:58:53.284 AM	1	dr.backup.exe	IDirectDraw::SetCooperativeLevel ( NULL, DDSCL_NORMAL )	DD_OK		0.0001720
21 7:58:53.285 AM 1 dr.backup.exe IDirectDraw::SetDisplayMode ( 640, 480, 32 ) DDERR_NOEXCLUSIVEMODE 0x887600e1 = 0.0000003

A cooperative level set with NULL window + SetDisplayMode combination won't work through dgVoodoo.
dgVoodoo needs a non-NULL window because settings display mode through DXGI (D3D11) is tied to swapchains, which are, in turn, allocated behind windows (unlike in old DDraw). 😖
(and, exclusive mode cooperative level can only be set with a non-NULL window even in native DDraw)

Edit: I should change the returned error code to something else, e.g. E_FAIL for that case.

If the game has its main window created at this point, and the SetCooperativeLevel call could be hacked to pass the real HWND instead of NULL then it should work via dgVoodoo too.

xttx wrote:

The game does not use Sleep(), timeGetTime(), GetTickCount(), QueryPerformanceFrequency(), QueryPerformanceCounter(), rdtsc and IDirectDrawSurface::Flip(). It draws frames directly with IDirectDrawSurface::Blt. So dxWnd is completely useless. I don't know if dgVoodoo could help with vsync, in this case.

So I guess, this game was made to be suited on the old hardware it was written on. I can't recommend Sleep () because of the global timer resolution, it's not accurate.
If v-sync is forced in dgVoodoo then that takes effect even when Blt-ing to the primary surface, so dgVoodoo could help there.
However, if the game does more than one Blt's to the primary surface within a 'game frame' then the refresh rate (say, 60Hz) unfortunately gets divided by the number of Blt's.