Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Initial submit of the wrapper generator
- Loading branch information
1 parent
becf807
commit 554ffc8
Showing
11 changed files
with
1,869 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,3 +11,10 @@ | |
*.lai | ||
*.la | ||
*.a | ||
|
||
Release/ | ||
Debug/ | ||
ipch/ | ||
*.filters | ||
*.opensdf | ||
*.sdf |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,50 @@ | ||
dxwrapper | ||
========= | ||
|
||
DirectX 1-7 wrapper project for making old games run on new hardware | ||
DirectX 1-7 wrapper project for making old games run on new hardware. | ||
|
||
Requires DirectX 8.1 SDK headers (although the parser should(tm) be able to handle just about any version), which the wrapper generator will parse to generate the interface wrappers for the various DirectX interfaces. | ||
|
||
At its current form, the wrapper is a full pass-through wrapper; it doesn't do anything special, just takes in calls from the application, writes the event to a log, and passes the arguments to the real DirectX. | ||
|
||
There's bound to be plenty of bugs left, but I've managed to get a 100k-line log out of Crimson Skies so far.. | ||
|
||
The whole thing, and the generated code, is released under zlib license: | ||
|
||
-- 8< -- 8< -- 8< -- | ||
|
||
Copyright (c) 2013 Jari Komppa | ||
|
||
This software is provided 'as-is', without any express or implied | ||
warranty. In no event will the authors be held liable for any damages | ||
arising from the use of this software. | ||
|
||
Permission is granted to anyone to use this software for any purpose, | ||
including commercial applications, and to alter it and redistribute it | ||
freely, subject to the following restrictions: | ||
|
||
1. The origin of this software must not be misrepresented; you must not | ||
claim that you wrote the original software. If you use this software | ||
in a product, an acknowledgment in the product documentation would be | ||
appreciated but is not required. | ||
|
||
2. Altered source versions must be plainly marked as such, and must not be | ||
misrepresented as being the original software. | ||
|
||
3. This notice may not be removed or altered from any source | ||
distribution. | ||
|
||
-- 8< -- 8< -- 8< -- | ||
|
||
The basic idea is to extend DirectX COM interface classes, and then pass the extended classes to the application. The application doesn't have any clue that it's not talking directly to DirectX (usually. I'm pretty sure punkbuster or some such does have checks against this). Then, when the application calls a function, we can muck around with the parameters before passing it to DirectX, and/or muck around with the returning value. It's also entirely possible to just skip on talking to DirectX and make an OpenGL back-end, like I did with ddhack for Wing Commander games, but that's a lot of work. | ||
|
||
Now, every time the application calls a function with a parameter that happens to be one of our wrapped classes, we also have to change these pointers to point at the original objects. This can get a bit tricky, and I'm sure I've missed several places (especially on interfaces I haven't seen in use yet). Just something to keep in mind when playing with it. | ||
|
||
Sometimes the application calls some function that returns another wrappable object. Sometimes we've already wrapped this. For this, I've added a simple (slow, and stupid) database of pointer pairs that is checked whenever one of those functions is called. Sometimes this can cause a false warning in the log, since the framebuffer, for example, doesn't need to be created implicitly, but is an attached surface. Or something. I've added code to wrap it when it's queried for the first time. | ||
|
||
It's entirely possible that other interfaces (like directmedia/directshow) eat or output directx objects, in which case we're either in trouble, or have to wrap more interfaces. | ||
|
||
If you play with this code, toss me a note, I'm always interested in hearing about it, but I'm most likely too busy to actually help you (much) =) | ||
|
||
Cheers, | ||
Jari |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
#define STRICT | ||
#define WIN32_LEAN_AND_MEAN | ||
#define INITGUID | ||
#define DIRECTDRAW_VERSION 0x0700 | ||
#define DIRECT3D_VERSION 0x0700 | ||
|
||
#include <windows.h> | ||
#include <ddraw.h> | ||
#include "d3d.h" | ||
#include "ddoutput.h" | ||
#include "wrapper.h" | ||
|
||
#ifdef _DEBUG | ||
#define DEBUGMESS(a) OutputDebugStringA(a) | ||
#else | ||
#define DEBUGMESS(a) | ||
#endif | ||
|
||
|
||
typedef HRESULT (_stdcall *DDrawCreateProc)(void* a, void* b, void* c); | ||
typedef HRESULT (_stdcall *DDrawEnumerateProc)(void* callback, void* context); | ||
typedef void (_stdcall *DDrawMiscProc)(); | ||
typedef HRESULT (_stdcall *DDrawCreateExProc)(GUID FAR *lpGUID, LPVOID *lplpDD, REFIID iid, IUnknown FAR *pUnkOuter); | ||
|
||
static DDrawCreateProc DDrawCreate=0; | ||
static DDrawEnumerateProc DDrawEnumerate=0; | ||
static DDrawMiscProc AcquireLock; | ||
static DDrawMiscProc ParseUnknown; | ||
static DDrawMiscProc InternalLock; | ||
static DDrawMiscProc InternalUnlock; | ||
static DDrawMiscProc ReleaseLock; | ||
static DDrawCreateExProc DDrawCreateEx; | ||
|
||
static void LoadDLL() { | ||
char path[MAX_PATH]; | ||
GetSystemDirectoryA(path,MAX_PATH); | ||
strcat_s(path, "\\ddraw.dll"); | ||
HMODULE ddrawdll=LoadLibraryA(path); | ||
//HMODULE ddrawdll=LoadLibraryA("csfix.dll"); | ||
DDrawCreate=(DDrawCreateProc)GetProcAddress(ddrawdll, "DirectDrawCreate"); | ||
DDrawEnumerate=(DDrawEnumerateProc)GetProcAddress(ddrawdll, "DirectDrawEnumerateA"); | ||
DDrawCreateEx=(DDrawCreateExProc)GetProcAddress(ddrawdll, "DirectDrawCreateEx"); | ||
|
||
AcquireLock=(DDrawMiscProc)GetProcAddress(ddrawdll, "AcquireDDThreadLock"); | ||
ParseUnknown=(DDrawMiscProc)GetProcAddress(ddrawdll, "D3DParseUnknownCommand"); | ||
InternalLock=(DDrawMiscProc)GetProcAddress(ddrawdll, "DDInternalLock"); | ||
InternalUnlock=(DDrawMiscProc)GetProcAddress(ddrawdll, "DDInternalUnlock"); | ||
ReleaseLock=(DDrawMiscProc)GetProcAddress(ddrawdll, "ReleaseDDThreadLock"); | ||
} | ||
|
||
extern "C" void __declspec(naked) myAcquireLock() { | ||
logf(__FUNCTION__ "\n"); | ||
_asm jmp AcquireLock; | ||
} | ||
extern "C" void __declspec(naked) myParseUnknown() { | ||
logf(__FUNCTION__ "\n"); | ||
_asm jmp ParseUnknown; | ||
} | ||
extern "C" void __declspec(naked) myInternalLock() { | ||
logf(__FUNCTION__ "\n"); | ||
_asm jmp InternalLock; | ||
} | ||
extern "C" void __declspec(naked) myInternalUnlock() { | ||
logf(__FUNCTION__ "\n"); | ||
_asm jmp InternalUnlock; | ||
} | ||
extern "C" void __declspec(naked) myReleaseLock() { | ||
logf(__FUNCTION__ "\n"); | ||
_asm jmp ReleaseLock; | ||
} | ||
|
||
extern "C" HRESULT _stdcall myDirectDrawCreate(GUID* a, IDirectDraw** b, IUnknown* c) { | ||
logf(__FUNCTION__ "\n"); | ||
if(!DDrawCreate) LoadDLL(); | ||
HRESULT hr=DDrawCreate(a,b,c); | ||
if(FAILED(hr)) return hr; | ||
*b=(IDirectDraw*)new myIDirectDraw(*b); | ||
return 0; | ||
} | ||
|
||
extern "C" HRESULT _stdcall myDirectDrawCreateEx( | ||
GUID FAR *lpGUID, | ||
LPVOID *lplpDD, | ||
REFIID iid, | ||
IUnknown FAR *pUnkOuter | ||
) | ||
{ | ||
logf(__FUNCTION__ "\n"); | ||
if(!DDrawCreate) LoadDLL(); | ||
HRESULT hr = DDrawCreateEx(lpGUID, lplpDD, iid, pUnkOuter); | ||
genericQueryInterface(iid, lplpDD); | ||
return hr; | ||
} | ||
|
||
extern "C" HRESULT _stdcall myDirectDrawEnumerate(void* lpCallback, void* lpContext) { | ||
logf(__FUNCTION__ "\n"); | ||
if(!DDrawEnumerate) LoadDLL(); | ||
return DDrawEnumerate(lpCallback, lpContext); | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
LIBRARY wrapper | ||
EXPORTS | ||
|
||
DirectDrawCreate=myDirectDrawCreate @1 | ||
DirectDrawCreateEx=myDirectDrawCreateEx @2 | ||
DirectDrawEnumerateA=myDirectDrawEnumerate @3 | ||
|
||
AcquireDDThreadLock=myAcquireLock | ||
D3DParseUnknownCommand=myParseUnknown | ||
DDInternalLock=myInternalLock | ||
DDInternalUnlock=myInternalUnlock | ||
ReleaseDDThreadLock=myReleaseLock |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include "wrapper.h" | ||
|
||
void *d3d9InterfaceQuery(REFIID a); | ||
|
||
void genericQueryInterface(REFIID a, void **ptr) | ||
{ | ||
#define QUERYINTERFACE(x) \ | ||
if(a==IID_##x) \ | ||
{ \ | ||
*ptr = (void*)new my##x(*(x **)ptr); \ | ||
logf("\tWrapped: " #x "\n");\ | ||
wrapstore(orig, *ptr);\ | ||
return;\ | ||
} | ||
|
||
logf("\tInterface Query: {%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}\n", | ||
a.Data1, a.Data2, a.Data3, | ||
a.Data4[0],a.Data4[1],a.Data4[2],a.Data4[3], | ||
a.Data4[4],a.Data4[5],a.Data4[6],a.Data4[7]); | ||
|
||
void * orig = *ptr; | ||
|
||
QUERYINTERFACE(IDirect3D); | ||
QUERYINTERFACE(IDirect3D2); | ||
QUERYINTERFACE(IDirect3D3); | ||
QUERYINTERFACE(IDirect3D7); | ||
QUERYINTERFACE(IDirect3DDevice); | ||
QUERYINTERFACE(IDirect3DDevice2); | ||
QUERYINTERFACE(IDirect3DDevice3); | ||
QUERYINTERFACE(IDirect3DDevice7); | ||
QUERYINTERFACE(IDirect3DExecuteBuffer); | ||
QUERYINTERFACE(IDirect3DLight); | ||
QUERYINTERFACE(IDirect3DMaterial); | ||
QUERYINTERFACE(IDirect3DMaterial2); | ||
QUERYINTERFACE(IDirect3DMaterial3); | ||
QUERYINTERFACE(IDirect3DTexture); | ||
QUERYINTERFACE(IDirect3DTexture2); | ||
QUERYINTERFACE(IDirect3DVertexBuffer); | ||
QUERYINTERFACE(IDirect3DVertexBuffer7); | ||
QUERYINTERFACE(IDirect3DViewport); | ||
QUERYINTERFACE(IDirect3DViewport2); | ||
QUERYINTERFACE(IDirect3DViewport3); | ||
QUERYINTERFACE(IDirectDraw); | ||
QUERYINTERFACE(IDirectDraw2); | ||
QUERYINTERFACE(IDirectDraw4); | ||
QUERYINTERFACE(IDirectDraw7); | ||
QUERYINTERFACE(IDirectDrawClipper); | ||
QUERYINTERFACE(IDirectDrawColorControl); | ||
QUERYINTERFACE(IDirectDrawFactory); | ||
QUERYINTERFACE(IDirectDrawGammaControl); | ||
QUERYINTERFACE(IDirectDrawPalette); | ||
QUERYINTERFACE(IDirectDrawSurface); | ||
QUERYINTERFACE(IDirectDrawSurface2); | ||
QUERYINTERFACE(IDirectDrawSurface3); | ||
QUERYINTERFACE(IDirectDrawSurface4); | ||
QUERYINTERFACE(IDirectDrawSurface7); | ||
logf("\t**** Unknown interface - not wrapped\n"); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
#define STRICT | ||
#define WIN32_LEAN_AND_MEAN | ||
|
||
#include <windows.h> | ||
#include <shlobj.h> | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <varargs.h> | ||
//#include "ddoutput.h" | ||
|
||
bool _stdcall SetWindowPosHook(HWND, HWND, int, int, int, int, int) { return true; } | ||
bool _stdcall SetWindowLongHook(HWND, int, int) { return true; } | ||
bool _stdcall ShowWindowHook(HWND, int) { return true; } | ||
|
||
bool _stdcall DllMain(HANDLE, DWORD dwReason, LPVOID) { | ||
if(dwReason==DLL_PROCESS_ATTACH) { | ||
} else if(dwReason==DLL_PROCESS_DETACH) { | ||
//d3d9Exit(); | ||
} | ||
return true; | ||
} | ||
|
||
void logf(char * fmt, ...) | ||
{ | ||
va_list ap; | ||
va_start(ap, fmt); | ||
FILE *f = fopen("wrapper.log", "a"); | ||
if (f) | ||
{ | ||
vfprintf(f, fmt, ap); | ||
fclose(f); | ||
} | ||
va_end(ap); | ||
} | ||
|
||
struct WrapPair | ||
{ | ||
void * mOriginal; | ||
void * mWrapper; | ||
}; | ||
|
||
#define MAX_PAIRS 4096 | ||
WrapPair gWrapPair[MAX_PAIRS]; | ||
int gWrapPairs = 0; | ||
|
||
void * do_wrapfetch(void * aOriginal) | ||
{ | ||
int i; | ||
for (i = 0; i < gWrapPairs; i++) | ||
{ | ||
if (gWrapPair[i].mOriginal == aOriginal) | ||
{ | ||
return gWrapPair[i].mWrapper; | ||
} | ||
} | ||
return NULL; | ||
} | ||
|
||
void wrapstore(void * aOriginal, void * aWrapper) | ||
{ | ||
if (do_wrapfetch(aOriginal) == NULL) | ||
{ | ||
gWrapPair[gWrapPairs].mOriginal = aOriginal; | ||
gWrapPair[gWrapPairs].mWrapper = aWrapper; | ||
gWrapPairs++; | ||
} | ||
else | ||
{ | ||
int i; | ||
for (i = 0; i < gWrapPairs; i++) | ||
{ | ||
if (gWrapPair[i].mOriginal == aOriginal) | ||
{ | ||
gWrapPair[i].mWrapper == aWrapper; | ||
return; | ||
} | ||
} | ||
} | ||
|
||
if (gWrapPairs >= MAX_PAIRS) | ||
{ | ||
logf("\n\t**** Max number of wrappers exceeded - adjust and recompile\n"); | ||
} | ||
} | ||
|
||
void * wrapfetch(void * aOriginal) | ||
{ | ||
void * ret = do_wrapfetch(aOriginal); | ||
|
||
if (ret == NULL) | ||
{ | ||
logf("\t**** Wrapped object not found - returning null - brace yourself\n"); | ||
} | ||
return ret; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
#pragma once | ||
#include <Windows.h> | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include "ddraw.h" | ||
#include "ddrawex.h" | ||
#include "d3d.h" | ||
|
||
#include "myIDirect3D.h" | ||
#include "myIDirect3D2.h" | ||
#include "myIDirect3D3.h" | ||
#include "myIDirect3D7.h" | ||
#include "myIDirect3DDevice.h" | ||
#include "myIDirect3DDevice2.h" | ||
#include "myIDirect3DDevice3.h" | ||
#include "myIDirect3DDevice7.h" | ||
#include "myIDirect3DExecuteBuffer.h" | ||
#include "myIDirect3DLight.h" | ||
#include "myIDirect3DMaterial.h" | ||
#include "myIDirect3DMaterial2.h" | ||
#include "myIDirect3DMaterial3.h" | ||
#include "myIDirect3DTexture.h" | ||
#include "myIDirect3DTexture2.h" | ||
#include "myIDirect3DVertexBuffer.h" | ||
#include "myIDirect3DVertexBuffer7.h" | ||
#include "myIDirect3DViewport.h" | ||
#include "myIDirect3DViewport2.h" | ||
#include "myIDirect3DViewport3.h" | ||
#include "myIDirectDraw.h" | ||
#include "myIDirectDraw2.h" | ||
#include "myIDirectDraw3.h" | ||
#include "myIDirectDraw4.h" | ||
#include "myIDirectDraw7.h" | ||
#include "myIDirectDrawClipper.h" | ||
#include "myIDirectDrawColorControl.h" | ||
#include "myIDirectDrawFactory.h" | ||
#include "myIDirectDrawGammaControl.h" | ||
#include "myIDirectDrawPalette.h" | ||
#include "myIDirectDrawSurface.h" | ||
#include "myIDirectDrawSurface2.h" | ||
#include "myIDirectDrawSurface3.h" | ||
#include "myIDirectDrawSurface4.h" | ||
#include "myIDirectDrawSurface7.h" | ||
|
||
void logf(char * format, ...); | ||
void genericQueryInterface(REFIID riid, LPVOID * ppvObj); | ||
void wrapstore(void * aOriginal, void * aWrapper); | ||
void *wrapfetch(void * aOriginal); |
Oops, something went wrong.