I’ve released a new version of DxWnd (requires the VC8SP0 CRT) – version 1.034. This is a minor release that, among fixing a couple of various bugs and some internal code cleanup and reorganization to build under VC8, adds a new feature: Video output rescaling.
I recently got a nice 20.1″ LCD to use as a second monitor for my main laptop at home. Unfortunately, I discovered that a lot of my old favorite classic games tended to do not-so-great things to your desktop color depth when you run them natively (in fullscreen mode), which while you might normally not care about, turns out to be a real bummer if you have something like an IM client or whatnot up on a second monitor.
So, I turned to a program I had written a couple of years ago – DxWnd. DxWnd is a program that lets you run DirectDraw 7 (or below) programs that only support fullscreen mode in a window. It accomplishes this by hooking various DirectDraw APIs and tricking the program into thinking that it is running at 640×480 (or whatever resolution it wants) fullscreen, when it is in fact running in a plain window at that resolution. Unfortunately, while DxWnd solves the color depth issue, running games at 640×480 on a 1920×1200 desktop is not really the best experience. Thus, I set out to make a couple of minor modifications to DxWnd to support rescaling the output. These are fairly simple in principle:
- Use StretchBlt instead of BitBlt to copy data from the DirectDraw surface that the program writes to into the GDI device context associated with the actual window I am displaying on screen. The reason why I perform this extra buffering step in the first place is that GDI provides nice automatic palette conversions from DirectDraw surface DCs to plain desktop window DCs. Changing the BitBlt to a StretchBlt simply rescales the current video image to a new resolution as it is copied for display purposes.
- For programs that call ScreenToClient / ClientToScreen / MapWindowPoints (or deal with mouse cursor coordinates), but do not correctly handle the fact that their program’s client area may not be centered at (0, 0) (after all, the program was written to only run in fullscreen mode, so normally this shortcut can be taken), DxWnd needs to alter the lie it tells in these functions. Previously, DxWnd would “fix up” the coordinates that get returned to a program (or that a program gives to Windows) so that the program only sees things centered at (0, 0). Now, in addition to that, DxWnd needs to scale these coordinates either from the real output resolution to the resolution that the program appears to be running at, or vice versa, depending on whether the coordinates are going “into” or “out of” the program. This does have one unfortunate side effect, which is that relative to a program that natively supports a given resolution, there is a perceived loss of precision when you move the mouse pointer in the rescaled video output window. This is because mouse cursor coordinates must be rescaled to values that are relative to the resolution that the program is expecting to be running at. For example, if you are running at twice the program’s native resolution, and the program draws a custom mouse cursor, then the cursor may only appear to move every two pixels that you move it instead of every one pixel (like you might expect).
- For programs that use DirectInput for mouse coordinates, these coordinates also need to be scaled so that they are relative to the virtual screen at (0, 0) that the program expects all coordinates to be relative to.
- Since we are scaling the output of a program, DxWnd can now allow the user to resize, maximize, or restore the window it creates to contain the video data from the program being hooked. For programs where the user has asked DxWnd to capture the mouse to the client area of the video output window, the mouse cursor capture needs to be recalculated if the window size changes (otherwise, you could not move the mouse cursor outside of the original window size).
With the new DxWnd, I can play some old classics like Master of Orion 2 or Privateer 2 rescaled to my desktop resolution on one monitor while still using a second monitor for things like e-mail or IM – and, without the color depth on my auxiliary display being reduced to 8-bit (or worse). There is some more information about DxWnd on the corresponding topic on the Valhalla Legends forum, if you are interested.