#include "dxwnd.h" #include "dxwcore.hpp" #include "syslibs.h" #include "hddraw.h" #include "dxhook.h" #include "dxhelper.h" static HookEntry_Type Hooks[]={ {"GetDeviceCaps", (FARPROC)GetDeviceCaps, (FARPROC *)&pGDIGetDeviceCaps, (FARPROC)extGetDeviceCaps}, {"TextOutA", (FARPROC)TextOutA, (FARPROC *)&pGDITextOutA, (FARPROC)extTextOutA}, {"TabbedTextOutA", (FARPROC)TabbedTextOutA, (FARPROC *)&pTabbedTextOutA, (FARPROC)extTabbedTextOutA}, {"ScaleWindowExtEx", (FARPROC)ScaleWindowExtEx, (FARPROC *)&pGDIScaleWindowExtEx, (FARPROC)extScaleWindowExtEx}, {"Rectangle", (FARPROC)Rectangle, (FARPROC *)&pGDIRectangle, (FARPROC)extRectangle}, {"SaveDC", (FARPROC)SaveDC, (FARPROC *)&pGDISaveDC, (FARPROC)extGDISaveDC}, {"RestoreDC", (FARPROC)RestoreDC, (FARPROC *)&pGDIRestoreDC, (FARPROC)extGDIRestoreDC}, {"CreatePalette", (FARPROC)CreatePalette, (FARPROC *)&pGDICreatePalette, (FARPROC)extGDICreatePalette}, {"SelectPalette", (FARPROC)SelectPalette, (FARPROC *)&pGDISelectPalette, (FARPROC)extSelectPalette}, {"RealizePalette", (FARPROC)RealizePalette, (FARPROC *)&pGDIRealizePalette, (FARPROC)extRealizePalette}, {"GetSystemPaletteEntries", (FARPROC)GetSystemPaletteEntries, (FARPROC *)&pGDIGetSystemPaletteEntries, (FARPROC)extGetSystemPaletteEntries}, {0, NULL, 0, 0} // terminator }; static HookEntry_Type DDHooks[]={ {"CreateCompatibleDC", (FARPROC)CreateCompatibleDC, (FARPROC *)&pGDICreateCompatibleDC, (FARPROC)extDDCreateCompatibleDC}, {"DeleteDC", (FARPROC)DeleteDC, (FARPROC *)&pGDIDeleteDC, (FARPROC)extDDDeleteDC}, {"CreateDCA", (FARPROC)CreateDCA, (FARPROC *)&pGDICreateDC, (FARPROC)extDDCreateDC}, {"BitBlt", (FARPROC)BitBlt, (FARPROC *)&pGDIBitBlt, (FARPROC)extDDBitBlt}, {"StretchBlt", (FARPROC)StretchBlt, (FARPROC *)&pGDIStretchBlt, (FARPROC)extDDStretchBlt}, // {"PatBlt", (FARPROC)PatBlt, (FARPROC *)&pGDIPatBlt, (FARPROC)extDDPatBlt}, // missing one ... {0, NULL, 0, 0} // terminator }; static HookEntry_Type GDIHooks[]={ {"CreateCompatibleDC", (FARPROC)CreateCompatibleDC, (FARPROC *)&pGDICreateCompatibleDC, (FARPROC)extGDICreateCompatibleDC}, {"DeleteDC", (FARPROC)DeleteDC, (FARPROC *)&pGDIDeleteDC, (FARPROC)extGDIDeleteDC}, {"CreateDCA", (FARPROC)CreateDCA, (FARPROC *)&pGDICreateDC, (FARPROC)extGDICreateDC}, {"BitBlt", (FARPROC)BitBlt, (FARPROC *)&pGDIBitBlt, (FARPROC)extGDIBitBlt}, {"StretchBlt", (FARPROC)StretchBlt, (FARPROC *)&pGDIStretchBlt, (FARPROC)extGDIStretchBlt}, {"PatBlt", (FARPROC)PatBlt, (FARPROC *)&pGDIPatBlt, (FARPROC)extGDIPatBlt}, {0, NULL, 0, 0} // terminator }; static HookEntry_Type EmuHooks[]={ {"SetTextColor", (FARPROC)SetTextColor, (FARPROC *)&pGDISetTextColor, (FARPROC)extSetTextColor}, {"SetBkColor", (FARPROC)SetBkColor, (FARPROC *)&pGDISetBkColor, (FARPROC)extSetBkColor}, {"CreateFont", (FARPROC)CreateFont, (FARPROC *)&pGDICreateFont, (FARPROC)extCreateFont}, {"CreateFontIndirectA", (FARPROC)CreateFontIndirectA, (FARPROC *)&pGDICreateFontIndirect, (FARPROC)extCreateFontIndirect}, {0, NULL, 0, 0} // terminator }; static HookEntry_Type GammaHooks[]={ {"SetDeviceGammaRamp", (FARPROC)SetDeviceGammaRamp, (FARPROC *)&pGDISetDeviceGammaRamp, (FARPROC)extSetDeviceGammaRamp}, {"GetDeviceGammaRamp", (FARPROC)GetDeviceGammaRamp, (FARPROC *)&pGDIGetDeviceGammaRamp, (FARPROC)extGetDeviceGammaRamp}, {0, NULL, 0, 0} // terminator }; extern HRESULT WINAPI extDirectDrawCreate(GUID FAR *, LPDIRECTDRAW FAR *, IUnknown FAR *); extern HRESULT WINAPI extDirectDrawCreateEx(GUID FAR *, LPDIRECTDRAW FAR *, REFIID, IUnknown FAR *); static char *libname = "gdi32.dll"; void HookGDI32(HMODULE module) { HookLibrary(module, Hooks, libname); if(dxw.dwFlags1 & MAPGDITOPRIMARY) HookLibrary(module, DDHooks, libname); else HookLibrary(module, GDIHooks, libname); if ((dxw.dwFlags1 & EMULATESURFACE) && (dxw.dwFlags1 & HANDLEDC)) HookLibrary(module, EmuHooks, libname); if(dxw.dwFlags2 & DISABLEGAMMARAMP) HookLibrary(module, GammaHooks, libname); } void HookGDI32Init() { HookLibInit(Hooks); HookLibInit(DDHooks); HookLibInit(EmuHooks); HookLibInit(GammaHooks); } FARPROC Remap_GDI32_ProcAddress(LPCSTR proc, HMODULE hModule) { FARPROC addr; if (addr=RemapLibrary(proc, hModule, Hooks)) return addr; if(dxw.dwFlags1 & MAPGDITOPRIMARY) if(addr=RemapLibrary(proc, hModule, DDHooks)) return addr; else if(addr=RemapLibrary(proc, hModule, GDIHooks)) return addr; if ((dxw.dwFlags1 & EMULATESURFACE) && (dxw.dwFlags1 & HANDLEDC)) if(addr=RemapLibrary(proc, hModule, EmuHooks)) return addr; if(dxw.dwFlags2 & DISABLEGAMMARAMP) if(addr=RemapLibrary(proc, hModule, GammaHooks)) return addr; return NULL; } //-------------------------------------------------------------------------------------------- // // extern and common functions // //-------------------------------------------------------------------------------------------- extern DEVMODE *pSetDevMode; extern DWORD PaletteEntries[256]; extern Unlock4_Type pUnlockMethod(LPDIRECTDRAWSURFACE); extern HRESULT WINAPI sBlt(char *, LPDIRECTDRAWSURFACE, LPRECT, LPDIRECTDRAWSURFACE, LPRECT, DWORD, LPDDBLTFX, BOOL); extern GetDC_Type pGetDC; extern ReleaseDC_Type pReleaseDC; static COLORREF GetMatchingColor(COLORREF crColor) { int iDistance, iMinDistance; int iColorIndex, iMinColorIndex; COLORREF PalColor; iMinDistance=0xFFFFFF; iMinColorIndex=0; for(iColorIndex=0; iColorIndex<256; iColorIndex++){ int iDist; iDistance=0; PalColor=PaletteEntries[iColorIndex]; switch(dxw.ActualPixelFormat.dwRGBBitCount){ case 32: PalColor = ((PalColor & 0x00FF0000) >> 16) | (PalColor & 0x0000FF00) | ((PalColor & 0x000000FF) << 16); break; case 16: if(dxw.ActualPixelFormat.dwGBitMask==0x03E0){ // RGB555 screen settings PalColor = ((PalColor & 0x7C00) >> 7) | ((PalColor & 0x03E0) << 6) | ((PalColor & 0x001F) << 19); } else { // RGB565 screen settings PalColor = ((PalColor & 0xF800) >> 8) | ((PalColor & 0x07E0) << 5) | ((PalColor & 0x001F) << 19); } break; } iDist = (crColor & 0x00FF0000) - (PalColor & 0x00FF0000); iDist >>= 16; if (iDist<0) iDist=-iDist; iDist *= iDist; iDistance += iDist; iDist = (crColor & 0x0000FF00) - (PalColor & 0x0000FF00); iDist >>= 8; if (iDist<0) iDist=-iDist; iDist *= iDist; iDistance += iDist; iDist = (crColor & 0x000000FF) - (PalColor & 0x000000FF); // iDist >>= 0; if (iDist<0) iDist=-iDist; iDist *= iDist; iDistance += iDist; if (iDistance < iMinDistance) { iMinDistance = iDistance; iMinColorIndex = iColorIndex; } if (iMinDistance==0) break; // got the perfect match! } OutTraceD("GetMatchingColor: color=%x matched with palette[%d]=%x dist=%d\n", crColor, iMinColorIndex, PaletteEntries[iMinColorIndex], iDistance); PalColor=PaletteEntries[iMinColorIndex]; switch(dxw.ActualPixelFormat.dwRGBBitCount){ case 32: crColor = ((PalColor & 0x00FF0000) >> 16) | (PalColor & 0x0000FF00) | ((PalColor & 0x000000FF) << 16); break; case 16: if(dxw.ActualPixelFormat.dwGBitMask==0x03E0){ // RGB555 screen settings crColor = ((PalColor & 0x7C00) >> 7) | ((PalColor & 0x03E0) << 6) | ((PalColor & 0x001F) << 19); } else { // RGB565 screen settings crColor = ((PalColor & 0xF800) >> 8) | ((PalColor & 0x07E0) << 5) | ((PalColor & 0x001F) << 19); } break; } return crColor; } //-------------------------------------------------------------------------------------------- // // API hookers // //-------------------------------------------------------------------------------------------- int WINAPI extGetDeviceCaps(HDC hdc, int nindex) { DWORD res; res = (*pGDIGetDeviceCaps)(hdc, nindex); OutTraceD("GetDeviceCaps: hdc=%x index=%x(%s) res=%x\n", hdc, nindex, ExplainDeviceCaps(nindex), res); // if you have a bypassed setting, use it first! if(pSetDevMode){ switch(nindex){ case BITSPIXEL: case COLORRES: res = pSetDevMode->dmBitsPerPel; OutTraceD("GetDeviceCaps: fix BITSPIXEL/COLORRES cap=%x\n",res); return res; case HORZRES: res = pSetDevMode->dmPelsWidth; OutTraceD("GetDeviceCaps: fix HORZRES cap=%d\n", res); return res; case VERTRES: res = pSetDevMode->dmPelsHeight; OutTraceD("GetDeviceCaps: fix VERTRES cap=%d\n", res); return res; } } switch(nindex){ case VERTRES: res= dxw.GetScreenHeight(); OutTraceD("GetDeviceCaps: fix VERTRES cap=%d\n", res); break; case HORZRES: res= dxw.GetScreenWidth(); OutTraceD("GetDeviceCaps: fix HORZRES cap=%d\n", res); break; // WARNING: in no-emu mode, the INIT8BPP and INIT16BPP flags expose capabilities that // are NOT implemented and may cause later troubles! case RASTERCAPS: if(dxw.dwFlags2 & INIT8BPP) { res |= RC_PALETTE; // v2.02.12 OutTraceD("GetDeviceCaps: fix RASTERCAPS setting RC_PALETTE cap=%x\n",res); } break; case BITSPIXEL: case COLORRES: if(dxw.dwFlags2 & INIT8BPP|INIT16BPP){ if(dxw.dwFlags2 & INIT8BPP) res = 8; if(dxw.dwFlags2 & INIT16BPP) res = 16; OutTraceD("GetDeviceCaps: fix BITSPIXEL/COLORRES cap=%d\n",res); } break; } if(dxw.dwFlags1 & EMULATESURFACE){ switch(nindex){ case RASTERCAPS: if((dxw.VirtualPixelFormat.dwRGBBitCount==8) || (dxw.dwFlags2 & INIT8BPP)){ res = RC_PALETTE; OutTraceD("GetDeviceCaps: fix RASTERCAPS setting RC_PALETTE cap=%x\n",res); } break; case BITSPIXEL: case COLORRES: int PrevRes; PrevRes=res; if(dxw.VirtualPixelFormat.dwRGBBitCount!=0) res = dxw.VirtualPixelFormat.dwRGBBitCount; if(dxw.dwFlags2 & INIT8BPP) res = 8; if(dxw.dwFlags2 & INIT16BPP) res = 16; if(PrevRes != res) OutTraceD("GetDeviceCaps: fix BITSPIXEL/COLORRES cap=%d\n",res); break; case SIZEPALETTE: res = 256; OutTraceD("GetDeviceCaps: fix SIZEPALETTE cap=%x\n",res); break; case NUMRESERVED: res = 0; OutTraceD("GetDeviceCaps: fix NUMRESERVED cap=%x\n",res); break; } } return res; } BOOL WINAPI extTextOutA(HDC hdc, int nXStart, int nYStart, LPCTSTR lpString, int cchString) { BOOL res; OutTraceD("TextOut: hdc=%x xy=(%d,%d) str=(%d)\"%s\"\n", hdc, nXStart, nYStart, cchString, lpString); if (dxw.dwFlags1 & FIXTEXTOUT) { POINT anchor; anchor.x=nXStart; anchor.y=nYStart; (*pClientToScreen)(dxw.GethWnd(), &anchor); nXStart=anchor.x; nYStart=anchor.y; } res=(*pGDITextOutA)(hdc, nXStart, nYStart, lpString, cchString); return res; } LONG WINAPI extTabbedTextOutA(HDC hDC, int X, int Y, LPCTSTR lpString, int nCount, int nTabPositions, const LPINT lpnTabStopPositions, int nTabOrigin) { BOOL res; OutTraceD("TabbedTextOut: hdc=%x xy=(%d,%d) nCount=%d nTP=%d nTOS=%d str=(%d)\"%s\"\n", hDC, X, Y, nCount, nTabPositions, nTabOrigin, lpString); if (dxw.dwFlags1 & FIXTEXTOUT) { POINT anchor; anchor.x=X; anchor.y=Y; (*pClientToScreen)(dxw.GethWnd(), &anchor); X=anchor.x; Y=anchor.y; } res=(*pTabbedTextOutA)(hDC, X, Y, lpString, nCount, nTabPositions, lpnTabStopPositions, nTabOrigin); return res; } BOOL WINAPI extScaleWindowExtEx(HDC hdc, int Xnum, int Xdenom, int Ynum, int Ydenom, LPSIZE lpSize) { OutTraceD("ScaleWindowExtEx: hdc=%x num=(%d,%d) denom=(%d,%d) lpSize=%d\n", hdc, Xnum, Ynum, Xdenom, Ydenom, lpSize); if ((dxw.dwFlags1 & LOCKWINPOS) && dxw.IsFullScreen()) return 1; return (*pGDIScaleWindowExtEx)(hdc, Xnum, Xdenom, Ynum, Ydenom, lpSize); } BOOL WINAPI extRectangle(HDC hdc, int nLeftRect, int nTopRect, int nRightRect, int nBottomRect) { OutTraceD("Rectangle: hdc=%x xy=(%d,%d)-(%d,%d)\n", hdc, nLeftRect, nTopRect, nRightRect, nBottomRect); if (dxw.dwFlags1 & FIXTEXTOUT) { POINT anchor; anchor.x=nLeftRect; anchor.y=nTopRect; (*pClientToScreen)(dxw.GethWnd(), &anchor); nLeftRect=anchor.x; nTopRect=anchor.y; anchor.x=nRightRect; anchor.y=nBottomRect; (*pClientToScreen)(dxw.GethWnd(), &anchor); nRightRect=anchor.x; nBottomRect=anchor.y; } return (*pGDIRectangle)(hdc, nLeftRect, nTopRect, nRightRect, nBottomRect); } int WINAPI extGDISaveDC(HDC hdc) { int ret; ret=(*pGDISaveDC)(hdc); OutTraceD("GDI.SaveDC: hdc=%x ret=%x\n", hdc, ret); //AutoRefreshThread=CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)AutoRefresh, (LPVOID)hdc, 0, &dwThrdId); return ret; } BOOL WINAPI extGDIRestoreDC(HDC hdc, int nSavedDC) { BOOL ret; ret=(*pGDIRestoreDC)(hdc, nSavedDC); OutTraceD("GDI.RestoreDC: hdc=%x nSavedDC=%x ret=%x\n", hdc, nSavedDC, ret); //TerminateThread(AutoRefreshThread, 0); return ret; } /* --------------------------------------------------------------------------- */ // v2.1.75: Hooking for GDI32 CreatePalette, SelectPalette, RealizePalette: // maps the GDI palette to the buffered DirectDraw one. This fixes the screen // output for "Dementia" (a.k.a. "Armed & Delirious"). HPALETTE WINAPI extGDICreatePalette(CONST LOGPALETTE *plpal) { HPALETTE ret; int idx; dxw.IsGDIPalette=TRUE; OutTraceD("GDI.CreatePalette: plpal=%x version=%x NumEntries=%x\n", plpal, plpal->palVersion, plpal->palNumEntries); ret=(*pGDICreatePalette)(plpal); if(IsDebug){ OutTraceD("PalEntry[%x]= ", plpal->palNumEntries); for(idx=0; idxpalNumEntries; idx++) OutTraceD("(%x)", plpal->palPalEntry[idx]); OutTraceD("\n"); } dxw.palVersion=plpal->palVersion; dxw.palNumEntries=plpal->palNumEntries; if(dxw.palNumEntries>256) dxw.palNumEntries=256; for(idx=0; idxpalPalEntry[idx]; OutTraceD("GDI.CreatePalette: hPalette=%x\n", ret); return ret; } HPALETTE WINAPI extSelectPalette(HDC hdc, HPALETTE hpal, BOOL bForceBackground) { HPALETTE ret; ret=(*pGDISelectPalette)(hdc, hpal, bForceBackground); OutTraceD("GDI.SelectPalette: hdc=%x hpal=%x ForceBackground=%x ret=%x\n", hdc, hpal, bForceBackground, ret); return ret; } UINT WINAPI extRealizePalette(HDC hdc) { UINT ret; extern void mySetPalette(int, int, LPPALETTEENTRY); ret=(*pGDIRealizePalette)(hdc); OutTraceD("GDI.RealizePalette: hdc=%x ret=%x\n", hdc, ret); if(!dxw.IsGDIPalette) return ret; // quick & dirty implementation through a nasty global: // if the SelectPalette didn't force to the background (arg bForceBackground==FALSE) // then don't override the current palette set by the DirectDrawPalette class. // should be cleaned up a little.... // maybe not: now both Diablo & Dementia colors are working... if(dxw.dwFlags1 & EMULATESURFACE) mySetPalette(0, dxw.palNumEntries, dxw.palPalEntry); // DEBUGGING if(IsDebug){ int idx; OutTraceD("PaletteEntries[%x]= ", dxw.palNumEntries); for(idx=0; idxlfHeight, lplf->lfWidth, lplf->lfFaceName); memcpy((char *)&lf, (char *)lplf, sizeof(LOGFONT)); lf.lfQuality=NONANTIALIASED_QUALITY; retHFont=((*pGDICreateFontIndirect)(&lf)); if(retHFont) OutTraceD("CreateFontIndirect: hfont=%x\n", retHFont); else OutTraceD("CreateFontIndirect: error=%d at %d\n", GetLastError(), __LINE__); return retHFont; } BOOL WINAPI extSetDeviceGammaRamp(HDC hDC, LPVOID lpRamp) { BOOL ret; OutTraceD("SetDeviceGammaRamp: hdc=%x\n", hDC); if(dxw.dwFlags2 & DISABLEGAMMARAMP) { OutTraceD("SetDeviceGammaRamp: SUPPRESSED\n"); return TRUE; } ret=(*pGDISetDeviceGammaRamp)(hDC, lpRamp); if(!ret) OutTraceE("SetDeviceGammaRamp: ERROR err=%d\n", GetLastError()); return ret; } BOOL WINAPI extGetDeviceGammaRamp(HDC hDC, LPVOID lpRamp) { BOOL ret; OutTraceD("GetDeviceGammaRamp: hdc=%x\n", hDC); ret=(*pGDIGetDeviceGammaRamp)(hDC, lpRamp); if(!ret) OutTraceE("GetDeviceGammaRamp: ERROR err=%d\n", GetLastError()); return ret; }