MW2Shim/patches.c
author Chris Porter <chris@warp13.co.uk>
Tue Jul 21 00:32:15 2009 +0100 (7 months ago)
changeset 12 1bbeb958799f
parent 101b55e9be116f
permissions -rw-r--r--
Copyright update.
     1 /*
     2  * Copyright (C) 2008 Chris Porter
     3  * All rights reserved.
     4  * See LICENSE.txt for licensing information.
     5  */
     6 
     7 #define WIN32_LEAN_AND_MEAN
     8 
     9 #include <windows.h>
    10 #include <stdio.h>
    11 #include <ddraw.h>
    12 #include <mmsystem.h>
    13 
    14 #include "mw2shim.h"
    15 
    16 static BOOL	(WINAPI *TrueBitBlt)(HDC hdc, int x, int y, int cx, int cy, HDC hdcSrc, int x1, int y1, DWORD rop) = BitBlt;
    17 static HANDLE (WINAPI *TrueFindFirstFileA)(LPCSTR lpFileName, LPWIN32_FIND_DATA lpFindFileData) = FindFirstFileA;
    18 static BOOL (WINAPI *TrueFindNextFileA)(HANDLE hFindFile, LPWIN32_FIND_DATA lpFindFileData) = FindNextFileA;
    19 static BOOL (WINAPI *TrueFindClose)(HANDLE hFindFile) = FindClose;
    20 static BOOL (WINAPI *TrueHeapFree)(HANDLE hHeap, DWORD dwFlags, LPVOID lpMem) = HeapFree;
    21 static HRESULT (WINAPI *TrueDirectDrawCreate)(GUID *lpGUID, LPDIRECTDRAW *lplpDD, IUnknown *pUnkOuter);
    22 
    23 static HRESULT (STDMETHODCALLTYPE *TrueCreateSurface)(void *, LPDDSURFACEDESC, LPDIRECTDRAWSURFACE *, IUnknown *);
    24 static HRESULT (STDMETHODCALLTYPE *TrueUnlock)(IDirectDrawSurface *, LPVOID);
    25 static HRESULT (STDMETHODCALLTYPE *TrueLock)(IDirectDrawSurface *, LPRECT, LPDDSURFACEDESC, DWORD, HANDLE);
    26 
    27 static BOOL WINAPI FixedBitBlt(HDC hdc, int x, int y, int cx, int cy, HDC hdcSrc, int x1, int y1, DWORD rop) {
    28   BOOL b = TrueBitBlt(hdc, x, y, cx, cy, hdcSrc, x1, y1, rop);  
    29   if(!b)
    30     return 0;
    31 
    32   return cy;
    33 }
    34 
    35 static HANDLE mechlab = INVALID_HANDLE_VALUE;
    36 
    37 static void mutatefinddata(LPWIN32_FIND_DATA fd) {
    38   memcpy(fd->cAlternateFileName, fd->cFileName, sizeof(fd->cAlternateFileName));
    39   fd->cAlternateFileName[sizeof(fd->cAlternateFileName) - 1] = '\0';
    40 }
    41 
    42 static HANDLE WINAPI FixedFindFirstFileA(LPCSTR lpFileName, LPWIN32_FIND_DATA lpFindFileData) {
    43   HANDLE h = TrueFindFirstFileA(lpFileName, lpFindFileData);
    44   char a, b, c;
    45 
    46   if(h == INVALID_HANDLE_VALUE)
    47     return h;
    48   
    49   if(sscanf_s(lpFileName, "mek\\%c%c%c??usr.mek", &a, &b, &c)) {
    50     mechlab = h;
    51     mutatefinddata(lpFindFileData);
    52   }
    53     
    54   return h;
    55 }
    56 
    57 static BOOL WINAPI FixedFindNextFileA(HANDLE hFindFile, LPWIN32_FIND_DATA lpFindFileData) {
    58   BOOL b = TrueFindNextFileA(hFindFile, lpFindFileData);
    59   
    60   if(b && (mechlab == lpFindFileData))
    61     mutatefinddata(lpFindFileData);
    62   
    63   return b;
    64 }
    65 
    66 static BOOL WINAPI FixedFindClose(HANDLE hFindFile) {
    67   if(mechlab == hFindFile)
    68     mechlab = INVALID_HANDLE_VALUE;
    69 
    70   return TrueFindClose(hFindFile);
    71 }
    72 
    73 static BOOL WINAPI FixedHeapFree(HANDLE hHeap, DWORD dwFlags, LPVOID lpMem) {
    74   /* memory leaks ahoy */
    75   
    76   return TRUE;
    77 }
    78 
    79 static void LimitRate(int rate) {
    80   static DWORD nexttick;
    81   DWORD t = timeGetTime();
    82   DWORD sleepfor;
    83 
    84   if(nexttick == 0)
    85     nexttick = t;
    86 
    87   nexttick+=rate;
    88   
    89   /*sleepfor = nexttick - t;*/
    90 
    91   /* for some reason sleeping here screws up windows... */
    92 
    93   while(timeGetTime() < nexttick)
    94     ;
    95 }
    96 
    97 static int frameratelimit;
    98 static const char *setupframeratelimit(char *args) {
    99   frameratelimit = 1000 / atoi(args);
   100   if(frameratelimit < 1 || frameratelimit > 1000)
   101     return "Bad frame rate limit supplied.";
   102 
   103   return NULL;
   104 }
   105 
   106 static int showfps;
   107 static const char *setupfpscounter(char *args) {
   108   if(!strcmp(args, "1"))
   109     showfps = 1;
   110   
   111   return NULL;
   112 }
   113 
   114 static int getfpsrate() {
   115   static DWORD lastticks;
   116   static int fps, frames;
   117   DWORD ticks = timeGetTime(), delta;
   118 
   119   if(!lastticks) {
   120     lastticks = ticks;
   121     return 0;
   122   }
   123 
   124   frames++;
   125   delta = ticks - lastticks;
   126   if(delta > 1000) {
   127     double denom = ((double)delta / (double)frames);
   128     if(denom == 0) {
   129       fps = 0;
   130     } else {
   131       fps = (int)(1000.0 / denom);
   132     }
   133 
   134     frames = 0;
   135     lastticks = ticks;
   136   }
   137 
   138   return fps;
   139 }
   140 
   141 static LPDDSURFACEDESC mainsurface;
   142 static HRESULT STDMETHODCALLTYPE FixedUnlock(IDirectDrawSurface *p, LPVOID a) {
   143   static TIMECAPS timecaps;
   144   static int gottimecaps;
   145 
   146   if(gottimecaps == 0) {
   147     gottimecaps = 1;
   148     if(timeGetDevCaps(&timecaps, sizeof(timecaps)) != TIMERR_NOERROR)
   149       timecaps.wPeriodMin = 10;
   150   }
   151 
   152   timeBeginPeriod(timecaps.wPeriodMin);
   153   LimitRate(frameratelimit); 
   154 
   155   if(showfps) {
   156     int rate = getfpsrate();
   157     int scale = 4, oncolour = 0, offcolour = 255;
   158     plotnumbers(rate, mainsurface, 0, 0, scale, oncolour);
   159     plotnumbers(rate, mainsurface, 2, 2, scale, oncolour);
   160     plotnumbers(rate, mainsurface, 0, 2, scale, oncolour);
   161     plotnumbers(rate, mainsurface, 2, 0, scale, oncolour);
   162     plotnumbers(rate, mainsurface, 1, 1, scale, offcolour);
   163   }
   164 
   165   timeEndPeriod(timecaps.wPeriodMin);
   166 
   167   return TrueUnlock(p, a);
   168 }
   169 
   170 static HRESULT STDMETHODCALLTYPE FixedLock(IDirectDrawSurface *p, LPRECT a, LPDDSURFACEDESC b, DWORD c, HANDLE d) {
   171   HRESULT ret = TrueLock(p, a, b, c, d);
   172   if(ret != DD_OK)
   173     return ret;
   174 
   175   mainsurface = b;
   176   return ret;
   177 }
   178 
   179 static HRESULT STDMETHODCALLTYPE FixedCreateSurface(void *p, LPDDSURFACEDESC a, LPDIRECTDRAWSURFACE *b, IUnknown *c) {
   180   IDirectDrawSurface *psurf;
   181   HRESULT ret = TrueCreateSurface(p, a, b, c);
   182   
   183   if(ret != DD_OK)
   184     return ret;
   185 
   186   psurf = *b;
   187   
   188   if(psurf->lpVtbl->Unlock != FixedUnlock)
   189     TrueUnlock = psurf->lpVtbl->Unlock;
   190   psurf->lpVtbl->Unlock = FixedUnlock;
   191   
   192   if(showfps) {
   193     if(psurf->lpVtbl->Lock != FixedLock)
   194       TrueLock = psurf->lpVtbl->Lock;
   195     psurf->lpVtbl->Lock = FixedLock;
   196   }
   197 
   198   return ret;
   199 }
   200 
   201 static HRESULT WINAPI FixedDirectDrawCreate(GUID *lpGUID, LPDIRECTDRAW *lplpDD, IUnknown *pUnkOuter) {
   202   IDirectDraw *pdd;
   203   HRESULT ret = TrueDirectDrawCreate(lpGUID, lplpDD, pUnkOuter);
   204   
   205   if(ret != DD_OK)
   206     return ret;
   207   
   208   pdd = *lplpDD;
   209   
   210   if(pdd->lpVtbl->CreateSurface != FixedCreateSurface)
   211     TrueCreateSurface = pdd->lpVtbl->CreateSurface;
   212   pdd->lpVtbl->CreateSurface = FixedCreateSurface;
   213   
   214   return ret;
   215 }
   216 
   217 static hunk hstartup[] = {
   218   { HUNK_FUNC, (void *)&FixedBitBlt, (void *)&TrueBitBlt, },
   219 };
   220 
   221 static hunk hmechlab[] = {
   222   { HUNK_FUNC, (void *)&FixedFindFirstFileA, (void *)&TrueFindFirstFileA },
   223   { HUNK_FUNC, (void *)&FixedFindNextFileA, (void *)&TrueFindNextFileA },
   224   { HUNK_FUNC, (void *)&FixedFindClose, (void *)&TrueFindClose },
   225 };
   226 
   227 static hunk hheaphack[] = {
   228   { HUNK_FUNC, (void *)&FixedHeapFree, (void *)&TrueHeapFree },
   229 };
   230 
   231 static hunk hddraw[] = {
   232   { HUNK_NAME, (void *)&FixedDirectDrawCreate, NULL, "ddraw.dll", "DirectDrawCreate", &TrueDirectDrawCreate },
   233 };
   234 
   235 int patchcount = 5;
   236 patch patches[] = { 
   237   { "startup", "Fixes startup termination", 1, hstartup },
   238   { "mechlab", "Fixes Mech Lab overweight issue", 3, hmechlab },
   239   { "heaphack", "Fixes a lot of random crashes but will increase memory usage.", 1, hheaphack },
   240   { "frameratelimit", "Fixes jumpjet and missile problems", 1, hddraw, "45", "[frame rate in frames/second]", setupframeratelimit },
   241   { "fpscounter", "FPS counter", 1, hddraw, "0", "[1 to enable]", setupfpscounter },
   242 };