narzoul / DDrawCompat

DirectDraw and Direct3D 1-7 compatibility, performance and visual enhancements for Windows Vista, 7, 8, 10 and 11
BSD Zero Clause License
885 stars 67 forks source link

Need for Speed III and IV crash on startup when set to borderless #216

Closed PlayNeth closed 7 months ago

PlayNeth commented 1 year ago

No matter what I do I always get a blackscreen on startup. Borderless mode to my knowledge is the only way to actually record games using ddrawcompat since no recording app can pick up exclusive mode at all, so I'm kinda stuck here.

Using the latest version of ddrawcompat DDrawCompat-nfs3.log DDrawCompat-nfshs.log

A video showcasing the issue: https://user-images.githubusercontent.com/82559127/226183049-a05d4cb6-c86f-4a1d-a852-4904724b8ae9.mp4

narzoul commented 1 year ago

I can't reproduce the issue with NFS3, and I can't get NFS4 running anymore.

Anyway, in both of your logs it's crashing in pfnSetStreamSource, even though the exact same call was fine as long as it was called from the initial thread. For some reason, the game switches to a different rendering thread after a short time, and then it crashes on the very same driver call with the exact same parameters. I suspect it might be an Intel driver bug. But I'm wondering why it doesn't crash in exclusive fullscreen mode then. Can you also upload a debug log from NFS3 with FullscreenMode=exclusive? Just getting to the main menu is enough, to keep the log small.

Also, please try to get a crash dump (with borderless) as described here: https://github.com/narzoul/DDrawCompat/issues/50#issuecomment-520162844 Just to make sure it's not crashing somewhere in the wrapper code.

PlayNeth commented 1 year ago

Sure thing. DDrawCompat-nfs3.zip File ended up being a mega byte over the upload limit on here so I zipped it up https://drive.google.com/file/d/13TACoPP4bkgxbj_PTSPVZ7pn0ld0vjzB/view?usp=share_link And the dump file. Used the task manager method because the game would simply just stay frozen in not responding until I forcefully close it.

narzoul commented 1 year ago

Thanks! The log shows the same thing, except there's no crash after the rendering thread changes.

The crash dump from task manager won't work, since the initial rendering thread already crashed and disappeared by the time you take it. The exception (most likely an access violation) would have to be caught the moment it is raised, which is what automatic crash dumps are usually good for. But in this case, since the whole process doesn't crash, I don't know if it captures anything at all, maybe the exception is silently handled by something in the process. The only way to catch it properly then is to run the game through a debugger (such as the one in Visual Studio), which can stop at the moment when the exception is thrown, and then you can create a dump at that point.

Meanwhile I also checked the code, and realized that pfnSetStreamSource is actually not immediately passed to the driver, so it looks like the crash is in the wrapper. But that shouldn't be possible unless there's some heap corruption taking place, which would be difficult to impossible to debug remotely.

narzoul commented 1 year ago

Nevermind! I looked further into the crash logs and found that it actually crashed even earlier, in ShaderBlitter::genBilinearBlt, because one of the arguments unexpectedly became null. I don't fully understand it yet, but it might have something to do with gamma correction, which makes sense, since it's only emulated in borderless windowed mode.

However, I can't find a gamma setting in the game, and my version doesn't try to either query or change gamma ramps at all, hence why I can't reproduce the issue. But I might be able to figure out what's wrong from the logs, I'm just too tired to do it tonight.

narzoul commented 1 year ago

Ok, I found the issue. Here is a quick fix: ddraw.zip (diff.txt compared to v0.4.0)

I had the driver set to DX5 for NFS3, which is why I didn't see any gamma related operations. They are present with the DX7 driver.

It looks like Intel uses a different default gamma ramp than AMD/NVIDIA. This currently causes DDrawCompat to detect Intel's default ramp as non-default, and unnecessarily applies a gamma shader in borderless fullscreen mode. I'll fix this in the next release.

Intel's default gamma ramp is: k 256 (k=0..255) while for AMD/NVIDIA it is: k 65535 / 255 = k * 257

PlayNeth commented 1 year ago

That did the trick! working like a charm now. Many thanks.

narzoul commented 1 year ago

Please keep it open until I fix it in the next release, otherwise I might forget about it.

narzoul commented 7 months ago

Fixed in v0.5.0.