VOGONS

Common searches


First post, by kjliew

User metadata
Rank Oldbie
Rank
Oldbie

No sure if anyone has ever done this or there are available resources online that were archived. It seems to me that Microsoft has never shown any interests to make such information public so that 3rd-parties can provide solution to bridge compatibility issues without resorting to emulation, but I have no insights on those with access to MSDN developers' subscription. Obviously, my great interests is to restore Win9X games play-ability on Win2K/XP or more recent Windows if possible.

The most notorious example is the GDI32 BitBlt(). Many Win9x era games simply failed because the API returned value changed from "number of lines blt'ed" to boolean "TRUE/FALSE". Other examples on my radar such as FreeLibrary() returned reference count instead of boolean TRUE/FALSE. Those information were hard to come by and buried deep within community patches, APIs hookers and DxWnd-like enhancements. I guess Windows ACT is somehow also a layer of translation that provides such solution.

Today's mingw-w64-i686 toolchain can easily build proxy DLL. Only the hooked APIs need to be implemented while the tools generate forwarder RVAs for the rest of the APIs using DLL .DEF file. Kontza published a good article for MSVC toolchain here, but I prefer the mingw GNU toolchain. Kontza's method uses LoadLibrary()/GetProcAddress() for the hooked API. This is no longer needed with mingw GNU toolchain, and it is as simple as calling the API directly.

#include <windows.h>

int WINAPI wrap_BitBlt(
HDC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight,
HDC hdcSrc, int nXSrc, int nYSrc, DWORD dwRop
)
{
// Call the real blitter, and store its return value.

BOOL retVal = BitBlt( hdcDest,
nXDest,
nYDest,
nWidth,
nHeight,
hdcSrc,
nXSrc,
nYSrc,
dwRop );

return (retVal)? nHeight:0;
}

And the DLL .DEF file takes care of the symbol redirection.

BitBlt = wrap_BitBlt
OtherFunc = gdi32.OtherFunc
...

Similar technique can be used for timeGetTime() in WINMM.DLL discussed here.

Reply 1 of 3, by UCyborg

User metadata
Rank Member
Rank
Member
kjliew wrote:

The most notorious example is the GDI32 BitBlt(). Many Win9x era games simply failed because the API returned value changed from "number of lines blt'ed" to boolean "TRUE/FALSE".

True, but the function was always declared as BOOL BitBlt (...) in the SDK. In Windows NT 4.0, it also returns either 1 or 0. But devs rather shrugged NT as unsupported instead of testing return value like:

if (retVal)
{
// success
}
else
{
// failure
}
kjliew wrote:

Other examples on my radar such as FreeLibrary() returned reference count instead of boolean TRUE/FALSE.

Are you sure? I tested on updated Windows 98 SE and it returns 1 when calling FreeLibrary on a library handle which library it refers to was loaded several times.

Arthur Schopenhauer wrote:

A man can be himself only so long as he is alone; and if he does not love solitude, he will not love freedom; for it is only when he is alone that he is really free.

Reply 2 of 3, by kjliew

User metadata
Rank Oldbie
Rank
Oldbie
UCyborg wrote on 2020-02-11, 17:28:

True, but the function was always declared as BOOL BitBlt (...) in the SDK. In Windows NT 4.0, it also returns either 1 or 0.

You are right. The SDK has never said a programmer can depend on the BitBlt() returned value to decide how many lines was blt'ed. Perhaps, some genius game hackers turned programmers figured it out and used it. The history of PC was full of such wits and tricks all over the place. It turned out that is the most cursed API used by games, and you're right also about games didn't pay a shit about Windows NT at all back then, not until Windows 2000.

UCyborg wrote on 2020-02-11, 17:28:

Are you sure? I tested on updated Windows 98 SE and it returns 1 when calling FreeLibrary on a library handle which library it refers to was loaded several times.

DxWnd has a hook implemented for this. Heavy Gear 1.2 patched was affected by this. It was a beta patch but with markedly improved graphics details. Perhaps it could be a programming error. It is not as widely spread as the GDI32 BitBlt() example. I still remember that I didn't find any issue running Heavy Gear 1.2 patched on real Win98SE box back then. But the patch came too late at a time and I was already done with the game at 1.1 patched. It also requires at least 4MB texture memory which wasn't very common back then.