summaryrefslogtreecommitdiffstats
path: root/docs/release/src/osd/winui/directdraw.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'docs/release/src/osd/winui/directdraw.cpp')
-rw-r--r--docs/release/src/osd/winui/directdraw.cpp382
1 files changed, 382 insertions, 0 deletions
diff --git a/docs/release/src/osd/winui/directdraw.cpp b/docs/release/src/osd/winui/directdraw.cpp
new file mode 100644
index 00000000000..c85f97f8a76
--- /dev/null
+++ b/docs/release/src/osd/winui/directdraw.cpp
@@ -0,0 +1,382 @@
+// For licensing and usage information, read docs/winui_license.txt
+//****************************************************************************
+/***************************************************************************
+
+ directdraw.c
+
+ Direct Draw routines.
+
+ ***************************************************************************/
+
+// standard windows headers
+#include <windows.h>
+
+// MAME/MAMEUI headers
+#include "emu.h"
+#include "winui.h"
+#include "directdraw.h"
+#include "mui_util.h" // For ErrorMsg
+#include "dxdecode.h" // For DirectXDecodeError
+
+// standard C headers
+#include <ddraw.h>
+#include <tchar.h>
+
+/***************************************************************************
+ function prototypes
+ ***************************************************************************/
+
+static BOOL WINAPI DDEnumInfo(GUID FAR *lpGUID, LPTSTR lpDriverDescription,
+ LPTSTR lpDriverName, LPVOID lpContext, HMONITOR hm);
+
+static BOOL WINAPI DDEnumOldInfo(GUID FAR *lpGUID, LPTSTR lpDriverDescription,
+ LPTSTR lpDriverName, LPVOID lpContext);
+
+static void CalculateDisplayModes(void);
+static HRESULT CALLBACK EnumDisplayModesCallback(LPDDSURFACEDESC pddsd, LPVOID Context);
+static HRESULT CALLBACK EnumDisplayModesCallback2(DDSURFACEDESC2* pddsd, LPVOID Context);
+
+/***************************************************************************
+ External variables
+ ***************************************************************************/
+
+/***************************************************************************
+ Internal structures
+ ***************************************************************************/
+
+typedef struct
+{
+ TCHAR* name;
+ GUID* lpguid;
+} display_type;
+
+typedef HRESULT (WINAPI *ddc_proc)(GUID FAR *lpGUID, LPDIRECTDRAW FAR *lplpDD, IUnknown FAR *pUnkOuter);
+
+/***************************************************************************
+ Internal variables
+ ***************************************************************************/
+
+#define MAX_DISPLAYS 100
+static int g_nNumDisplays = 0;
+static display_type g_Displays[MAX_DISPLAYS];
+
+static HANDLE g_hDLL;
+static BOOL g_bHWStretch = 0;
+static BOOL g_bRefresh = 0;
+static struct tDisplayModes g_DisplayModes;
+static IDirectDraw2* g_pDirectDraw2;
+static IDirectDraw4* g_pDirectDraw4;
+
+/***************************************************************************
+ External functions
+ ***************************************************************************/
+
+/****************************************************************************
+ * DirectDrawInitialize
+ *
+ * Initialize the DirectDraw variables.
+ *
+ * This entails the following functions:
+ *
+ * DirectDrawCreate
+ *
+ ****************************************************************************/
+
+#if !defined(LPDIRECTDRAWENUMERATE)
+#if defined(UNICODE)
+
+typedef HRESULT (WINAPI* LPDIRECTDRAWENUMERATEW)(LPDDENUMCALLBACKW lpCallback, LPVOID lpContext);
+
+#define LPDIRECTDRAWENUMERATE LPDIRECTDRAWENUMERATEW
+
+#define SDirectDrawEnumerateEx "DirectDrawEnumerateExW"
+#define SDirectDrawEnumerate "DirectDrawEnumerateW"
+
+#else
+
+typedef HRESULT (WINAPI* LPDIRECTDRAWENUMERATEA)(LPDDENUMCALLBACKA lpCallback, LPVOID lpContext);
+
+#define LPDIRECTDRAWENUMERATE LPDIRECTDRAWENUMERATEA
+
+#define SDirectDrawEnumerateEx "DirectDrawEnumerateExA"
+#define SDirectDrawEnumerate "DirectDrawEnumerateA"
+
+#endif
+#endif /* LPDIRECTDRAWENUMERATE */
+
+/****************************************************************************/
+
+BOOL DirectDraw_Initialize(void)
+{
+ HRESULT hr;
+ UINT error_mode = 0;
+ ddc_proc ddc;
+ DDCAPS ddCaps;
+ DDCAPS ddHelCaps;
+ IDirectDraw* pDirectDraw1;
+ LPDIRECTDRAWENUMERATEEX pDDEnumEx;
+
+ if (g_hDLL != NULL)
+ return TRUE;
+
+ g_nNumDisplays = 0;
+ g_hDLL = NULL;
+ g_bHWStretch = FALSE;
+ g_bRefresh = FALSE;
+ g_pDirectDraw2 = NULL;
+ g_pDirectDraw4 = NULL;
+
+ /* Turn off error dialog for this call */
+ error_mode = SetErrorMode(0);
+ g_hDLL = LoadLibrary(TEXT("ddraw.dll"));
+ SetErrorMode(error_mode);
+
+ if (g_hDLL == NULL)
+ return FALSE;
+
+ ddc = (ddc_proc)GetProcAddress((HINSTANCE)g_hDLL, "DirectDrawCreate");
+ if (ddc == NULL)
+ return FALSE;
+
+ pDirectDraw1 = NULL;
+ g_pDirectDraw2 = NULL;
+ g_pDirectDraw4 = NULL;
+ hr = ddc(NULL, &pDirectDraw1, NULL);
+ if (FAILED(hr))
+ {
+ ErrorMsg("DirectDrawCreate failed: %s", DirectXDecodeError(hr));
+ return FALSE;
+ }
+
+ hr = IDirectDraw_QueryInterface(pDirectDraw1, IID_IDirectDraw4, (void**)&g_pDirectDraw4);
+ if (FAILED(hr))
+ {
+ g_pDirectDraw4 = NULL;
+ hr = IDirectDraw_QueryInterface(pDirectDraw1, IID_IDirectDraw2, (void**)&g_pDirectDraw2);
+ if (FAILED(hr))
+ {
+ ErrorMsg("Query Interface for DirectDraw 2 failed: %s", DirectXDecodeError(hr));
+ g_pDirectDraw2 = NULL;
+ IDirectDraw_Release(pDirectDraw1);
+ return FALSE;
+ }
+ }
+
+ memset(&ddCaps, 0, sizeof(DDCAPS));
+ memset(&ddHelCaps, 0, sizeof(DDCAPS));
+ ddCaps.dwSize = sizeof(DDCAPS);
+ ddHelCaps.dwSize = sizeof(DDCAPS);
+ hr = IDirectDraw_GetCaps(pDirectDraw1, &ddCaps, &ddHelCaps); /* 1 2 or 4? */
+ if (FAILED(hr))
+ {
+ ErrorMsg("Error getting DirectDraw capabilities: %s", DirectXDecodeError(hr));
+ }
+ else
+ g_bHWStretch = ((ddCaps.dwCaps & DDCAPS_BLTSTRETCH) != 0) ? TRUE : FALSE;
+
+ IDirectDraw_Release(pDirectDraw1);
+
+ /*
+ Note that you must know which version of the
+ function to retrieve (see the following text).
+ For this example, we use the ANSI version.
+ */
+ pDDEnumEx = (LPDIRECTDRAWENUMERATEEX) GetProcAddress((HINSTANCE)g_hDLL, SDirectDrawEnumerateEx);
+
+ /*
+ If the function is there, call it to enumerate all display devices
+ attached to the desktop, and any non-display DirectDraw devices.
+ */
+ if (pDDEnumEx)
+ {
+ pDDEnumEx(DDEnumInfo, NULL, DDENUM_ATTACHEDSECONDARYDEVICES | DDENUM_DETACHEDSECONDARYDEVICES);
+ }
+ else
+ {
+ LPDIRECTDRAWENUMERATE lpDDEnum;
+
+ lpDDEnum = (LPDIRECTDRAWENUMERATE) GetProcAddress((HINSTANCE)g_hDLL, SDirectDrawEnumerate);
+ /*
+ * We must be running on an old version of ddraw. Therefore,
+ * by definiton, multimon isn't supported. Fall back on
+ * DirectDrawEnumerate to enumerate standard devices on a
+ * single monitor system.
+ */
+ if (lpDDEnum)
+ {
+ lpDDEnum(DDEnumOldInfo, NULL);
+ }
+ else
+ {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+/****************************************************************************
+ *
+ * DirectDraw_Close
+ *
+ * Terminate our usage of DirectDraw.
+ *
+ ****************************************************************************/
+
+void DirectDraw_Close(void)
+{
+ int i;
+
+ for (i = 0; i < g_nNumDisplays; i++)
+ {
+ free(g_Displays[i].name);
+ g_Displays[i].name = NULL;
+ if (g_Displays[i].lpguid != NULL)
+ {
+ free(g_Displays[i].lpguid);
+ g_Displays[i].lpguid = NULL;
+ }
+
+ }
+ g_nNumDisplays = 0;
+
+ /*
+ Destroy any lingering IDirectDraw object.
+ */
+ if (g_pDirectDraw2)
+ {
+ IDirectDraw2_Release(g_pDirectDraw2);
+ g_pDirectDraw2 = NULL;
+ }
+
+ if (g_pDirectDraw4)
+ {
+ IDirectDraw4_Release(g_pDirectDraw4);
+ g_pDirectDraw4 = NULL;
+ }
+
+ if (g_hDLL)
+ {
+ FreeLibrary((HINSTANCE)g_hDLL);
+ g_hDLL = NULL;
+ }
+}
+
+/****************************************************************************/
+/*
+ Return a list of 16, 24 and 32 bit DirectDraw modes.
+*/
+struct tDisplayModes* DirectDraw_GetDisplayModes(void)
+{
+ if (g_DisplayModes.m_nNumModes == 0)
+ CalculateDisplayModes();
+
+ return &g_DisplayModes;
+}
+
+int DirectDraw_GetNumDisplays(void)
+{
+ return g_nNumDisplays;
+}
+
+BOOL DirectDraw_HasHWStretch(void)
+{
+ return g_bHWStretch;
+}
+
+BOOL DirectDraw_HasRefresh(void)
+{
+ return g_bRefresh;
+}
+
+LPCTSTR DirectDraw_GetDisplayName(int num_display)
+{
+ return g_Displays[num_display].name;
+}
+
+/****************************************************************************/
+/* internal functions */
+/****************************************************************************/
+
+static BOOL WINAPI DDEnumInfo(GUID FAR *lpGUID, LPTSTR lpDriverDescription,
+ LPTSTR lpDriverName, LPVOID lpContext, HMONITOR hm)
+{
+ g_Displays[g_nNumDisplays].name = (TCHAR*)malloc((_tcslen(lpDriverDescription) + 1) * sizeof(TCHAR));
+ _tcscpy(g_Displays[g_nNumDisplays].name, lpDriverDescription);
+
+ if (lpGUID == NULL)
+ g_Displays[g_nNumDisplays].lpguid = NULL;
+ else
+ {
+ g_Displays[g_nNumDisplays].lpguid = (LPGUID)malloc(sizeof(GUID));
+ memcpy(g_Displays[g_nNumDisplays].lpguid, lpGUID, sizeof(GUID));
+ }
+
+ g_nNumDisplays++;
+ if (g_nNumDisplays == MAX_DISPLAYS)
+ return DDENUMRET_CANCEL;
+ else
+ return DDENUMRET_OK;
+}
+
+static BOOL WINAPI DDEnumOldInfo(GUID FAR *lpGUID, LPTSTR lpDriverDescription, LPTSTR lpDriverName, LPVOID lpContext)
+{
+ return DDEnumInfo(lpGUID, lpDriverDescription, lpDriverName, lpContext, NULL);
+}
+
+static HRESULT CALLBACK EnumDisplayModesCallback(LPDDSURFACEDESC pddsd, LPVOID Context)
+{
+ DWORD dwDepth = pddsd->ddpfPixelFormat.dwRGBBitCount;
+
+ struct tDisplayModes* pDisplayModes = (struct tDisplayModes*)Context;
+ if (dwDepth == 16 || dwDepth == 24 || dwDepth == 32)
+ {
+ pDisplayModes->m_Modes[pDisplayModes->m_nNumModes].m_dwWidth = pddsd->dwWidth;
+ pDisplayModes->m_Modes[pDisplayModes->m_nNumModes].m_dwHeight = pddsd->dwHeight;
+ pDisplayModes->m_Modes[pDisplayModes->m_nNumModes].m_dwBPP = dwDepth;
+ pDisplayModes->m_Modes[pDisplayModes->m_nNumModes].m_dwRefresh = 0;
+ pDisplayModes->m_nNumModes++;
+ }
+
+ if (pDisplayModes->m_nNumModes == MAXMODES)
+ return DDENUMRET_CANCEL;
+ else
+ return DDENUMRET_OK;
+}
+
+static HRESULT CALLBACK EnumDisplayModesCallback2(DDSURFACEDESC2* pddsd2, LPVOID Context)
+{
+ struct tDisplayModes* pDisplayModes = (struct tDisplayModes*)Context;
+
+ DWORD dwDepth = pddsd2->ddpfPixelFormat.dwRGBBitCount;
+
+ if (dwDepth == 16 || dwDepth == 24 || dwDepth == 32)
+ {
+ pDisplayModes->m_Modes[pDisplayModes->m_nNumModes].m_dwWidth = pddsd2->dwWidth;
+ pDisplayModes->m_Modes[pDisplayModes->m_nNumModes].m_dwHeight = pddsd2->dwHeight;
+ pDisplayModes->m_Modes[pDisplayModes->m_nNumModes].m_dwBPP = dwDepth;
+ pDisplayModes->m_Modes[pDisplayModes->m_nNumModes].m_dwRefresh = pddsd2->dwRefreshRate;
+ pDisplayModes->m_nNumModes++;
+
+ if (pddsd2->dwRefreshRate != 0)
+ g_bRefresh = TRUE;
+ }
+
+ if (pDisplayModes->m_nNumModes == MAXMODES)
+ return DDENUMRET_CANCEL;
+ else
+ return DDENUMRET_OK;
+}
+
+static void CalculateDisplayModes(void)
+{
+ g_DisplayModes.m_nNumModes = 0;
+
+ if (g_pDirectDraw4)
+ IDirectDraw4_EnumDisplayModes(g_pDirectDraw4, DDEDM_REFRESHRATES, NULL, &g_DisplayModes, EnumDisplayModesCallback2);
+ else
+ if (g_pDirectDraw2)
+ IDirectDraw2_EnumDisplayModes(g_pDirectDraw2, 0, NULL, &g_DisplayModes, EnumDisplayModesCallback);
+}
+
+