diff --git a/Makefile b/Makefile index 20b35a8..758399d 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ REV=$(shell sh -c 'git rev-parse --short @{0}') all: sed 's/__REV__/$(REV)/g' ddraw.rc.in > ddraw.rc $(WINDRES) -J rc ddraw.rc ddraw.rc.o - $(CC) $(CFLAGS) -shared -o ddraw.dll main.c mouse.c palette.c surface.c clipper.c render.c screenshot.c ddraw.def ddraw.rc.o $(LIBS) + $(CC) $(CFLAGS) -shared -o ddraw.dll main.c mouse.c palette.c surface.c clipper.c render.c render_soft.c screenshot.c ddraw.def ddraw.rc.o $(LIBS) clean: rm -f ddraw.dll diff --git a/main.c b/main.c index 9a4a961..84990ab 100644 --- a/main.c +++ b/main.c @@ -38,6 +38,7 @@ BOOL screenshot(struct IDirectDrawSurfaceImpl *); IDirectDrawImpl *ddraw = NULL; DWORD WINAPI render_main(void); +DWORD WINAPI render_soft_main(void); HRESULT __stdcall ddraw_Compact(IDirectDrawImpl *This) { @@ -247,7 +248,7 @@ HRESULT __stdcall ddraw_SetDisplayMode(IDirectDrawImpl *This, DWORD width, DWORD if(This->render.thread == NULL) { - This->render.thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)render_main, NULL, 0, NULL); + This->render.thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)This->renderer, NULL, 0, NULL); } return DD_OK; @@ -389,7 +390,7 @@ HRESULT __stdcall ddraw_SetCooperativeLevel(IDirectDrawImpl *This, HWND hWnd, DW memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR)); pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR); pfd.nVersion = 1; - pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; + pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER | (This->renderer == render_main ? PFD_SUPPORT_OPENGL : 0); pfd.iPixelType = PFD_TYPE_RGBA; pfd.cColorBits = ddraw->render.bpp ? ddraw->render.bpp : ddraw->mode.dmBitsPerPel; pfd.iLayerType = PFD_MAIN_PLANE; @@ -692,5 +693,17 @@ HRESULT WINAPI DirectDrawCreate(GUID FAR* lpGUID, LPDIRECTDRAW FAR* lplpDD, IUnk This->vhack = 0; } + GetPrivateProfileStringA("ddraw", "renderer", "opengl", tmp, sizeof(tmp), ini_path); + if(tolower(tmp[0]) == 's' || tolower(tmp[0]) == 'g') + { + printf("DirectDrawCreate: Using software renderer\n"); + This->renderer = render_soft_main; + } + else + { + printf("DirectDrawCreate: Using OpenGL renderer\n"); + This->renderer = render_main; + } + return DD_OK; } diff --git a/main.h b/main.h index de98bcd..6017acb 100644 --- a/main.h +++ b/main.h @@ -78,6 +78,7 @@ typedef struct IDirectDrawImpl BOOL vsync; float sensitivity; BOOL vhack; + DWORD WINAPI (*renderer)(void); } IDirectDrawImpl; diff --git a/render_soft.c b/render_soft.c new file mode 100644 index 0000000..7d919b3 --- /dev/null +++ b/render_soft.c @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2011 Toni Spets + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include "main.h" +#include "surface.h" + +DWORD WINAPI render_soft_main(void) +{ + HDC memDC = CreateCompatibleDC(ddraw->render.hDC); + HBITMAP surface = CreateCompatibleBitmap(ddraw->render.hDC, ddraw->width, ddraw->height); + + PBITMAPINFO bmi = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFO) + (sizeof(RGBQUAD) * 256) + 1024); + + bmi->bmiHeader.biSize = sizeof(BITMAPINFO); + bmi->bmiHeader.biWidth = ddraw->width; + bmi->bmiHeader.biHeight = -ddraw->height; + bmi->bmiHeader.biPlanes = 1; + bmi->bmiHeader.biBitCount = 8; + bmi->bmiHeader.biCompression = BI_RGB; + + SelectObject(memDC, surface); + + DWORD tick_start = 0; + DWORD tick_end = 0; + DWORD frame_len = 0; + + if(ddraw->render.maxfps < 0) + { + ddraw->render.maxfps = ddraw->mode.dmDisplayFrequency; + } + + if(ddraw->render.maxfps > 0) + { + frame_len = 1000.0f / ddraw->render.maxfps; + } + + while (ddraw->render.run) + { + if(ddraw->render.maxfps > 0) + { + tick_start = GetTickCount(); + } + + EnterCriticalSection(&ddraw->cs); + if (ddraw->primary && ddraw->primary->palette) + { + if (ddraw->primary->palette->data_rgb == NULL) + { + ddraw->primary->palette->data_rgb = &bmi->bmiColors[1]; + } + + SetDIBits(memDC, surface, 0, ddraw->height, ddraw->primary->surface, bmi, DIB_RGB_COLORS); + + if (ddraw->render.width != ddraw->width || ddraw->render.height != ddraw->height) + { + StretchBlt(ddraw->render.hDC, 0, 0, ddraw->render.width, ddraw->render.height, memDC, 0, 0, ddraw->width, ddraw->height, SRCCOPY); + } + else + { + BitBlt(ddraw->render.hDC, 0, 0, ddraw->width, ddraw->height, memDC, 0, 0, SRCCOPY); + } + } + LeaveCriticalSection(&ddraw->cs); + + if(ddraw->render.maxfps > 0) + { + tick_end = GetTickCount(); + + if(tick_end - tick_start < frame_len) + { + Sleep( frame_len - (tick_end - tick_start) ); + } + } + + SetEvent(ddraw->render.ev); + } + + HeapFree(GetProcessHeap(), 0, bmi); + DeleteObject(surface); + DeleteDC(memDC); + return TRUE; +}