diff --git a/Makefile b/Makefile index d199333..46b8acc 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ all: - i586-mingw32msvc-gcc -D_DEBUG -Wall -Wl,--enable-stdcall-fixup -shared -s -o ddraw.dll main.c palette.c surface.c clipper.c ddraw.def -lgdi32 -lopengl32 + i586-mingw32msvc-gcc -Wall -Wl,--enable-stdcall-fixup -shared -s -o ddraw.dll main.c palette.c surface.c clipper.c ddraw.def -lgdi32 -lopengl32 clean: rm -f ddraw.dll diff --git a/main.c b/main.c index 5de7f95..c9f5f25 100644 --- a/main.c +++ b/main.c @@ -64,8 +64,20 @@ HRESULT ddraw_SetCooperativeLevel(void *_This, HWND hWnd, DWORD dwFlags) fakeDirectDrawObject *This = (fakeDirectDrawObject *)_This; printf("DirectDraw::SetCooperativeLevel(This=%p, hWnd=0x%08X, dwFlags=0x%08X)\n", This, (unsigned int)hWnd, (unsigned int)dwFlags); + /* Red Alert for some weird reason does this on Windows XP */ + if(hWnd == NULL) + { + return DDERR_INVALIDPARAMS; + } + This->hWnd = hWnd; + if(IDirectDraw_SetCooperativeLevel(This->real_ddraw, hWnd, DDSCL_NORMAL) != DD_OK) + { + printf(" internal SetCooperativeLevel failed\n"); + return DDERR_GENERIC; + } + return DD_OK; } @@ -77,6 +89,8 @@ HRESULT ddraw_SetDisplayMode(void *_This, DWORD width, DWORD height, DWORD bpp) This->width = width; This->height = height; + This->width = 1024; + This->height = 768; This->bpp = bpp; MoveWindow(This->hWnd, 0, 0, This->width, This->height, TRUE); @@ -111,6 +125,7 @@ ULONG ddraw_Release(void *_This) if(This->Ref == 0) { + IDirectDraw_Release(This->real_ddraw); free(This); return 0; } @@ -153,20 +168,40 @@ fakeDirectDraw iface = null //WaitForVerticalBlank }; +int stdout_open = 0; HRESULT WINAPI DirectDrawCreate(GUID FAR* lpGUID, LPDIRECTDRAW FAR* lplpDD, IUnknown FAR* pUnkOuter) { #if _DEBUG - freopen("stdout.txt", "w", stdout); + if(!stdout_open) + { + freopen("stdout.txt", "w", stdout); + setvbuf(stdout, NULL, _IONBF, 0); + stdout_open = 1; + } #endif printf("DirectDrawCreate(lpGUID=%p, lplpDD=%p, pUnkOuter=%p)\n", lpGUID, lplpDD, pUnkOuter); fakeDirectDrawObject *This = (fakeDirectDrawObject *)malloc(sizeof(fakeDirectDrawObject)); - This->Ref = 1; This->Functions = &iface; This->hWnd = NULL; printf(" This = %p\n", This); *lplpDD = (LPDIRECTDRAW)This; + This->real_dll = LoadLibrary("system32\\ddraw.dll"); + if(!This->real_dll) + { + return DDERR_UNSUPPORTED; + } + + This->real_DirectDrawCreate = (HRESULT WINAPI (*)(GUID FAR*, LPDIRECTDRAW FAR*, IUnknown FAR*))GetProcAddress(This->real_dll, "DirectDrawCreate"); + if(This->real_DirectDrawCreate(NULL, &This->real_ddraw, NULL) != DD_OK) + { + return DDERR_UNSUPPORTED; + } + + This->Ref = 0; + ddraw_AddRef(This); + return DD_OK; } diff --git a/main.h b/main.h index 397ea56..f70d239 100644 --- a/main.h +++ b/main.h @@ -64,6 +64,10 @@ typedef struct HWND hWnd; + HMODULE real_dll; + LPDIRECTDRAW real_ddraw; + HRESULT WINAPI (*real_DirectDrawCreate)(GUID FAR*, LPDIRECTDRAW FAR*, IUnknown FAR*); + } fakeDirectDrawObject; #endif diff --git a/palette.c b/palette.c index 2a17cb0..ae77f69 100644 --- a/palette.c +++ b/palette.c @@ -39,7 +39,11 @@ HRESULT ddraw_palette_SetEntries(void *_This, DWORD dwFlags, DWORD dwStartingEnt for(i=0;i<256;i++) { +#if USE_OPENGL This->data[i] = (lpEntries[i].peBlue<<16)|(lpEntries[i].peGreen<<8)|lpEntries[i].peRed; +#else + This->data[i] = (lpEntries[i].peRed<<16)|(lpEntries[i].peGreen<<8)|(lpEntries[i].peBlue); +#endif } return DD_OK; @@ -55,7 +59,7 @@ ULONG ddraw_palette_AddRef(void *_This) { fakeDirectDrawPaletteObject *This = (fakeDirectDrawPaletteObject *)_This; - printf("DirectDraw::AddRef(This=%p)\n", This); + printf("DirectDrawPalette::AddRef(This=%p)\n", This); This->Ref++; diff --git a/surface.c b/surface.c index b44439d..044e392 100644 --- a/surface.c +++ b/surface.c @@ -24,6 +24,7 @@ HRESULT null(); DWORD WINAPI ogl_Thread(void *_This); +DWORD WINAPI dd_Thread(void *_This); void dump_ddsd(DWORD); void dump_ddscaps(DWORD); @@ -52,20 +53,22 @@ ULONG ddraw_surface_Release(void *_This) if(This->Ref == 0) { - if(This->glThread) + if(This->dThread) { - This->glRun = FALSE; + This->dRun = FALSE; SetEvent(This->flipEvent); - WaitForSingleObject(This->glThread, INFINITE); + WaitForSingleObject(This->dThread, INFINITE); } if(This->surface) { free(This->surface); } +#if USE_OPENGL if(This->glTex) { free(This->glTex); } +#endif if(This->palette) { This->palette->Functions->Release(This->palette); @@ -89,14 +92,17 @@ HRESULT ddraw_CreateSurface(void *_This, LPDDSURFACEDESC lpDDSurfaceDesc, LPDIRE Surface->Functions = &siface; /* private stuff */ - Surface->hDC = NULL; + Surface->parent = This; Surface->bpp = This->bpp; Surface->surface = NULL; - Surface->glTex = NULL; Surface->caps = 0; Surface->palette = NULL; - Surface->glThread = NULL; - Surface->glRun = TRUE; + Surface->dThread = NULL; + Surface->dRun = TRUE; +#if USE_OPENGL + Surface->hDC = NULL; + Surface->glTex = NULL; +#endif if(lpDDSurfaceDesc->dwFlags & DDSD_CAPS) { @@ -105,7 +111,11 @@ HRESULT ddraw_CreateSurface(void *_This, LPDDSURFACEDESC lpDDSurfaceDesc, LPDIRE Surface->width = This->width; Surface->height = This->height; Surface->hWnd = This->hWnd; - Surface->glThread = CreateThread(NULL, 0, ogl_Thread, (void *)Surface, 0, NULL); +#if USE_OPENGL + Surface->dThread = CreateThread(NULL, 0, ogl_Thread, (void *)Surface, 0, NULL); +#else + Surface->dThread = CreateThread(NULL, 0, dd_Thread, (void *)Surface, 0, NULL); +#endif } dump_ddscaps(lpDDSurfaceDesc->ddsCaps.dwCaps); @@ -123,7 +133,9 @@ HRESULT ddraw_CreateSurface(void *_This, LPDDSURFACEDESC lpDDSurfaceDesc, LPDIRE Surface->lPitch = Surface->width; Surface->lXPitch = Surface->bpp / 8; Surface->surface = malloc(Surface->width * Surface->height * Surface->lXPitch); +#if USE_OPENGL Surface->glTex = malloc(Surface->width * Surface->height * sizeof(int)); +#endif } printf(" Surface = %p (%dx%d@%d)\n", Surface, (int)Surface->width, (int)Surface->height, (int)Surface->bpp); @@ -308,6 +320,7 @@ fakeDirectDrawSurface siface = null // ddraw_surface_UpdateOverlayZOrder }; +#if USE_OPENGL DWORD WINAPI ogl_Thread(void *_This) { int i,j; @@ -325,13 +338,13 @@ DWORD WINAPI ogl_Thread(void *_This) pfd.cDepthBits = 16; pfd.iLayerType = PFD_MAIN_PLANE; SetPixelFormat( This->hDC, ChoosePixelFormat( This->hDC, &pfd ), &pfd ); - + This->hRC = wglCreateContext( This->hDC ); wglMakeCurrent( This->hDC, This->hRC ); This->flipEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - while(This->glRun) + while(This->dRun) { WaitForSingleObject(This->flipEvent, INFINITE); ResetEvent(This->flipEvent); @@ -369,6 +382,72 @@ DWORD WINAPI ogl_Thread(void *_This) return 0; } +#else // if USE_OPENGL + +DWORD WINAPI dd_Thread(void *_This) +{ + int i,j; + fakeDirectDrawSurfaceObject *This = (fakeDirectDrawSurfaceObject *)_This; + DDSURFACEDESC ddsd; + LPDIRECTDRAWSURFACE primary; + LPDIRECTDRAWCLIPPER clipper; + DWORD width; + POINT pt; + + memset(&ddsd, 0, sizeof(DDSURFACEDESC)); + ddsd.dwSize = sizeof(DDSURFACEDESC); + ddsd.dwFlags = DDSD_CAPS; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; + + IDirectDraw_CreateSurface(This->parent->real_ddraw, &ddsd, &primary, NULL); + + memset(&ddsd, 0, sizeof(DDSURFACEDESC)); + ddsd.dwSize = sizeof(DDSURFACEDESC); + IDirectDrawSurface_GetSurfaceDesc(primary, &ddsd); + + width = ddsd.dwWidth * ddsd.lPitch / (ddsd.dwWidth * ddsd.ddpfPixelFormat.dwRGBBitCount / 8); + + IDirectDraw_CreateClipper(This->parent->real_ddraw, 0, &clipper, NULL); + IDirectDrawClipper_SetHWnd(clipper, 0, This->hWnd); + IDirectDrawSurface_SetClipper(primary, clipper); + + This->flipEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + + while(This->dRun) + { + WaitForSingleObject(This->flipEvent, INFINITE); + + if(!This->dRun) + break; + + pt.x = pt.y = 0; + //ClientToScreen(This->hWnd, &pt); + + if(IDirectDrawSurface_Lock(primary, NULL, &ddsd, DDLOCK_WRITEONLY|DDLOCK_WAIT, NULL) != DD_OK) + continue; + + /* convert ddraw surface to opengl texture */ + for(i=0; iheight; i++) + { + for(j=0; jwidth; j++) + { + ((int *)ddsd.lpSurface)[(i+pt.y)*width+(j+pt.x)] = This->palette->data[((unsigned char *)This->surface)[i*This->lPitch + j*This->lXPitch]]; + } + } + + IDirectDrawSurface_Unlock(primary, NULL); + + ResetEvent(This->flipEvent); + } + + IDirectDrawClipper_Release(clipper); + IDirectDrawSurface_Release(primary); + + return 0; +} + +#endif + void dump_ddscaps(DWORD dwCaps) { if(dwCaps & DDSCAPS_PRIMARYSURFACE) diff --git a/surface.h b/surface.h index 672fda5..b7b24b3 100644 --- a/surface.h +++ b/surface.h @@ -75,20 +75,23 @@ typedef struct DWORD bpp; DWORD caps; + fakeDirectDrawObject *parent; fakeDirectDrawPaletteObject *palette; void *surface; DWORD lPitch; DWORD lXPitch; - HANDLE glThread; - BOOL glRun; + HWND hWnd; + HANDLE dThread; + BOOL dRun; HANDLE flipEvent; - HWND hWnd; +#if USE_OPENGL HDC hDC; HGLRC hRC; int *glTex; +#endif ULONG Ref;