FunkyFr3sh / cnc-ddraw

GDI, OpenGL and Direct3D 9 re-implementation of the DirectDraw API for classic 2D games for better compatibility with Windows 2000, XP, Vista, 7, 8, 10, 11, Wine (Linux/macOS/Android) and Virtual Machines
https://discord.gg/afWXJNDDF5
MIT License
2.12k stars 143 forks source link

Dune 2000 - the game minimizes itself #304

Closed Avatar-Lion closed 2 months ago

Avatar-Lion commented 2 months ago

To my surprise, cnc-draw did not fix this problem, although I am absolutely sure that I ran Dune 2000 on Windows 10 in 2019 and everything was fine.

Unfortunately, I don’t remember which version of cnc-draw I used then, but now no options help - the game minimizes to the taskbar at the first mouse click. Are there ways to fix this problem?

FunkyFr3sh commented 2 months ago

Can you upload me a debug log? See this here for all details: https://github.com/FunkyFr3sh/cnc-ddraw/issues/44

Avatar-Lion commented 2 months ago

I think it’s impossible to make a full log, because the game doesn’t crash, but simply minimizes to the taskbar...

I started the game and skipped the introductory cutscenes using the Escape key. Then I left-clicked and the game minimized (that is, minimized, not closed). To remove it from the taskbar, I right-clicked on its name in the taskbar and selected "Close window". cnc-ddraw-1.log

FunkyFr3sh commented 2 months ago

Thanks! I had a similar problem reported once from another game and could never find a solution for it. Your issue might be the same, the log doesn't help unfortunately.

But I guess it shouldn't be a big deal in this case, dune 2000 supports borderless mode perfectly fine. IF you enable it via the cnc-ddraw config/Presentation setting the problem should be solved

elishacloud commented 2 months ago

I had a similar problem reported once from another game and could never find a solution for it.

I am not sure if it helps here. But I added the following code to fix this issue with Dune 2000. It was the only solution I could find.

Avatar-Lion commented 2 months ago

FunkyFr3sh I found a workaround, but it is very awkward and inconvenient: 1) Launch the game and left-click to minimize it 2) Call Task Manager and kill Explorer.exe 3) Close task manager 4) Press Alt + Tab to switch to the game window 5) After the game, open the Task Manager using the keyboard shortcut Ctrl + Shift + Escape and return the Explorer by launching it through a new task.

Then everything works fine. But this is only possible in D3D mode, while in GDI mode I always get a black screen. Of course, I can play D3D, but GDI mode is supported by the excellent xbrz-freescale shader, I would really hate to give it up.

elishacloud I'm not a programmer, but a simple player. Maybe you can tell me how I can try your option?

FunkyFr3sh commented 2 months ago

I had a similar problem reported once from another game and could never find a solution for it.

I am not sure if it helps here. But I added the following code to fix this issue with Dune 2000. It was the only solution I could find.

Interesting idea... But it's kinda weird, almost every game got that flag so it should actaully be a bigger problem. Could you ever reproduce such an issue on your own or was it someone else reporting it?

FunkyFr3sh I found a workaround, but it is very awkward and inconvenient:

  1. Launch the game and left-click to minimize it
  2. Call Task Manager and kill Explorer.exe
  3. Close task manager
  4. Press Alt + Tab to switch to the game window
  5. After the game, open the Task Manager using the keyboard shortcut Ctrl + Shift + Escape and return the Explorer by launching it through a new task.

Then everything works fine. But this is only possible in D3D mode, while in GDI mode I always get a black screen. Of course, I can play D3D, but GDI mode is supported by the excellent xbrz-freescale shader, I would really hate to give it up.

elishacloud I'm not a programmer, but a simple player. Maybe you can tell me how I can try your option?

Here's a test build with the suggested change from elisha:

Edit: wrong file uploaded, check next post

FunkyFr3sh commented 2 months ago

Here's a test build with the suggested change from elisha:

test build 1 (removing WS_POPUP after window was created) ddraw-nopopup-after.zip

test build 2 (removing WS_POPUP upfront) ddraw.zip

Avatar-Lion commented 2 months ago

Thank you very, very, very much! And even the GDI mode with shaders xbrz-freescale worked! Everything is working, you guys are the best!

elishacloud commented 2 months ago

I had a similar problem reported once from another game and could never find a solution for it.

I am not sure if it helps here. But I added the following code to fix this issue with Dune 2000. It was the only solution I could find.

Interesting idea... But it's kinda weird, almost every game got that flag so it should actaully be a bigger problem. Could you ever reproduce such an issue on your own or was it someone else reporting it?

I only remove the flag on very specific conditions, such that it has no siblings and it has no parent. For some reason with this particular case there is an issue. I have kept this code in the project for a very long time and tested literally hundreds of ddraw/Direct3D games and never found a problem with it.

elishacloud commented 2 months ago

Could you ever reproduce such an issue on your own or was it someone else reporting it?

Yes. I own the game and have the same issue as @Avatar-Lion. After looking into it for a while this was the only solution I could find.

elishacloud commented 2 months ago

Sorry for the barrage of messages. I just tested with your builds to see if both builds worked.

test build 1 (removing WS_POPUP after window was created) ddraw-nopopup-after.zip

This build doesn't work for me. For some reason I was also never able to get it to work by setting it after the creation. It has to be set before creation.

test build 2 (removing WS_POPUP upfront) ddraw.zip

This build works for me.

FunkyFr3sh commented 2 months ago

@elishacloud What game version are you using? Not 1.06 I guess?

elishacloud commented 2 months ago

It says V 1.02 in game.

image

elishacloud commented 2 months ago

Here is the application: DUNE2000.zip

FunkyFr3sh commented 2 months ago

Cool, thanks! The main exe is actually dune2000.dat and not dune2000.exe! But it's np, I don't think it will work with my 1.06 install anyways. I'll try to set up a test install from a CD.

I actually have been working on this game for many years, made tons of game patches with over 450 individual hooks and I have never heard about this problem before, which is strange... So I guess this issue does not happen with 1.06 at all, because that what my patch is based on

elishacloud commented 2 months ago

Ok, here are both of the files. It might work with your version, since I think the other files may be the same: DUNE2000.zip

FunkyFr3sh commented 2 months ago

Ok, here are both of the files. It might work with your version, since I think the other files may be the same: DUNE2000.zip

Nice, thanks! Yeah, I can reproduce it

elishacloud commented 2 months ago

Very good. Let me know if you find a better solution.

FunkyFr3sh commented 2 months ago

The problem is that the game is passing the width/height in the CreateWindowExA call from two uninitialized variables so you end up with some very high values most of the time and it will glitch

Still have to think about a good solution, but maybe it's going to be something like this:

if (dwStyle & WS_POPUP)
{
    nWidth = min(nWidth, GetSystemMetrics(SM_CXSCREEN));
    nHeight = min(nHeight, GetSystemMetrics(SM_CXSCREEN));
}

Edit: Actually it does work with high values such as 20000, but 25000 does not work. Not sure what's the actual limit. (tested on Win 7 and Win 10)

if (dwStyle & WS_POPUP)
{
    nWidth = min(nWidth, 20000);
    nHeight = min(nHeight, 20000);
}
elishacloud commented 2 months ago

Keep in mind that CW_USEDEFAULT is a valid option for that field, which is larger than 20000. I am not sure if there are other valid options that may be larger than 20000. But I know some ddraw games use CW_USEDEFAULT.

FunkyFr3sh commented 2 months ago

Keep in mind that CW_USEDEFAULT is a valid option for that field, which is larger than 20000. I am not sure if there are other valid options that may be larger than 20000. But I know some ddraw games use CW_USEDEFAULT.

Yeah, I've seen that. But CW_USEDEFAULT cannot be used on a popup window

CW_USEDEFAULT is valid only for overlapped windows; if CW_USEDEFAULT is specified for a pop-up or child window, nWidth and nHeight are set to zero.

FunkyFr3sh commented 2 months ago

Just noticed that CW_USEDEFAULT equals INT_MIN, so that's fine! All negative values are not causing any problems.

Also, just tested it on Windows XP, the bug doesn't exist there, weird...

elishacloud commented 2 months ago

I finally settled on this code:

// Handle popup window type (some games forget to initialize the nWidth and nHeight values)
if ((dwStyle & WS_POPUP) && !(nWidth & CW_USEDEFAULT) && (nWidth > 20000 || nHeight > 20000))
{
    Utils::GetScreenSize(hWndParent, nWidth, nHeight);
}
elishacloud commented 2 months ago

BTW: I noticed that you changed the value from 20000 to 16384? Did you find an issue with 20000 or did you just use 16384 because the sqrt() of it is an integer number?

FunkyFr3sh commented 2 months ago

I finally settled on this code:

// Handle popup window type (some games forget to initialize the nWidth and nHeight values)
if ((dwStyle & WS_POPUP) && !(nWidth & CW_USEDEFAULT) && (nWidth > 20000 || nHeight > 20000))
{
  Utils::GetScreenSize(hWndParent, nWidth, nHeight);
}

Yeah, looks good!

BTW: I noticed that you changed the value from 20000 to 16384? Did you find an issue with 20000 or did you just use 16384 because the sqrt() of it is an integer number?

It's just the max texture size of directx 12, I also set the same limit for the size of surfaces. Nothing wrong with 20000, seemed to be working fine in all my tests

elishacloud commented 2 months ago

It's just the max texture size of directx 12, I also set the same limit for the size of surfaces. Nothing wrong with 20000, seemed to be working fine in all my tests

Ok, thanks!