1 /* -*- c++ -*-
2 FILE: WrapDD.cpp
3 RCS REVISION: $Revision: 1.9 $
4 
5 COPYRIGHT: (c) 1999 -- 2003 Melinda Green, Don Hatch, and Jay Berkenbilt - Superliminal Software
6 
7 LICENSE: Free to use and modify for non-commercial purposes as long as the
8     following conditions are adhered to:
9     1) Obvious credit for the source of this code and the designs it embodies
10        are clearly made, and
11     2) Ports and derived versions of 4D Magic Cube programs are not distributed
12        without the express written permission of the authors.
13 
14 DESCRIPTION:
15     Abstraction on top of DirectX
16 */
17 
18 #include "WrapDX.h"
19 #include "assert.h"
20 
21 #define TRACE Trace
22 #define RELEASE(x) if (x != NULL) {x->Release(); x = NULL;}
23 
24 #ifdef _DEBUG
25 
26 extern      "C" int vsprintf(char *, const char *, va_list);
27 
28 void
Trace(const char * format,...)29 Trace(const char *format, ...)
30 {
31     va_list     args;
32     int         count;
33     char        buffer[512];
34 
35     va_start(args, format);
36     count = vsprintf(buffer, format, args);
37     va_end(args);
38 
39     OutputDebugString(buffer);
40 }
41 
42 #else
43 
44 inline void
Trace(const char *,...)45 Trace(const char *, ...)
46 {
47 }
48 
49 #endif /* _DEBUG */
50 
WrapDD()51 WrapDD::WrapDD ()
52 {
53     m_pFrontBuffer          = 0;
54     m_pBackBuffer           = 0;
55     m_pZBuffer              = 0;
56     m_pClipper              = 0;
57     m_pPalette              = 0;
58     m_pDirectDraw           = 0;
59     m_bIsOnPrimaryDevice    = TRUE;
60     m_pText1Surface         = 0;
61     m_pText2Surface         = 0;
62     memset(&m_HWddsCaps, 0, sizeof(m_HWddsCaps));
63 
64     // instead of AppInfo app
65     m_hWndMain              = 0;
66     m_modeCount             = 0;
67     m_bIgnoreWM_SIZE        = FALSE;
68 
69     // Parameters and status flags
70     m_bPrimaryPalettized    = FALSE;
71     m_bOnlySystemMemory     = FALSE;
72 
73     memset(&m_guid, 0, sizeof(m_guid));
74     m_bFullScreen           = FALSE;
75     m_bOnlySoftRender       = FALSE;
76 
77     m_pauseCount            = 0;
78 
79     m_pErrorHandler         = 0;
80     m_pFatalErrorHandler    = 0;
81     m_pErrorHandlerArg      = 0;
82     m_pFatalErrorHandlerArg = 0;
83 }
84 
~WrapDD()85 WrapDD::   ~WrapDD ()
86 {
87     Destroy();
88 }
89 
90 BOOL
Create(HWND hWnd,BOOL fullScreen,int width,int height,int bpp,const PALETTEENTRY * pPaletteEntries,int paletteEntryCount)91 WrapDD::Create(HWND hWnd,
92                BOOL fullScreen,
93                int width, int height, int bpp,
94                const PALETTEENTRY * pPaletteEntries,
95                int paletteEntryCount)
96 {
97     // assert(!m_hWndMain);
98 
99     // ??? we should reset all data members
100 
101     m_hWndMain = hWnd;
102 
103     if (!m_pDirectDraw)
104     {
105         CacheOriginalPaletteEntries();
106 
107         if (!DDCreate())
108         {
109             return FALSE;
110         }
111     }
112 
113     // if DirectDraw is not on primary display, assume it only does
114     // fullscreen
115     if (!m_bIsOnPrimaryDevice)
116     {
117         fullScreen = TRUE;
118     }
119 
120     if (!DDInit(fullScreen))
121     {
122         return FALSE;
123     }
124 
125     if (!SetPaletteEntries(pPaletteEntries, paletteEntryCount, fullScreen))
126     {
127         return FALSE;
128     }
129 
130     if (!DDSetMode(width, height, bpp))
131     {
132         return FALSE;
133     }
134 
135     return TRUE;
136 }
137 
138 // Save the original palette for when we are paused
139 // In case we start in fullScreen, put it in m_paletteEntries
CacheOriginalPaletteEntries()140 BOOL WrapDD::CacheOriginalPaletteEntries()
141 {
142     HDC         hdc;
143 
144     hdc = GetDC(NULL);
145     GetSystemPaletteEntries(hdc, 0, (1 << 8), &m_originalPaletteEntries[0]);
146 #if 0
147     for (i = 0; i < 256; i++)
148     {
149         m_paletteEntries[i] = m_originalPaletteEntries[i];
150     }
151 #endif
152     ReleaseDC(NULL, hdc);
153 
154     return TRUE;
155 }
156 
157 
SetPaletteEntries(const PALETTEENTRY * pPaletteEntries,int paletteEntryCount,BOOL fullScreen)158 BOOL WrapDD::SetPaletteEntries(const PALETTEENTRY * pPaletteEntries,
159                                int paletteEntryCount, BOOL fullScreen)
160 {
161     int         reservedLowEntryCount;
162     int         reservedHighEntryCount;
163     HDC         hdc;
164     int         i;
165 
166     hdc = GetDC(NULL);
167     // start out with system palette
168     GetSystemPaletteEntries(hdc, 0, (1 << 8), m_paletteEntries);
169     ReleaseDC(NULL, hdc);
170 
171     if (fullScreen)
172     {
173         reservedLowEntryCount = 1;
174         reservedHighEntryCount = 1;
175     }
176     else
177     {
178         reservedLowEntryCount = 10;
179         reservedHighEntryCount = 10;
180     }
181 
182     for (i = 0; i < reservedLowEntryCount; i++)
183     {
184         m_paletteEntries[i].peFlags = D3DPAL_READONLY;
185     }
186 
187     for (i = reservedLowEntryCount; i < 256 - reservedHighEntryCount; i++)
188     {
189         m_paletteEntries[i].peFlags = D3DPAL_READONLY;
190     }
191 
192     for (i = 256 - reservedHighEntryCount; i < 256; i++)
193     {
194         m_paletteEntries[i].peFlags = D3DPAL_READONLY;
195     }
196 
197     // then replace entries as specified
198     assert(paletteEntryCount <=
199            (sizeof(m_paletteEntries) / sizeof(m_paletteEntries[0])));
200     // ??? In fullscreen:  should we set entry 0 and 255
201     // In window mode: should we set entry 0-9 and 246-255
202     for (i = reservedLowEntryCount;
203          (i < paletteEntryCount) && (i < 256 - reservedHighEntryCount); i++)
204     {
205         m_paletteEntries[i].peRed = pPaletteEntries[i].peRed;
206         m_paletteEntries[i].peGreen = pPaletteEntries[i].peGreen;
207         m_paletteEntries[i].peBlue = pPaletteEntries[i].peBlue;
208     }
209 
210     if (m_pPalette)
211     {
212         HRESULT     result;
213 
214         result = m_pPalette->SetEntries(0, 0,
215                                         sizeof(m_paletteEntries) /
216                                         sizeof(m_paletteEntries[0]),
217                                         m_paletteEntries);
218         if (result != DD_OK)
219         {
220             Error("SetEntries failed", result);
221             return FALSE;
222         }
223     }
224 
225     return TRUE;
226 }
227 
228 // Releases all objects, scene, textures and other memory.
Destroy()229 void WrapDD::Destroy()
230 {
231     DestroyButNotDirectDraw();
232     RELEASE(m_pDirectDraw);
233 
234     // ??? reset other members, or in Create()
235     m_bIsOnPrimaryDevice = TRUE;
236 }
237 
238 // Releases all objects, scene, textures and other memory except DirectDraw
DestroyButNotDirectDraw()239 void WrapDD::DestroyButNotDirectDraw()
240 {
241     // ???
242     RestoreOriginalPaletteEntries();
243 
244     if (m_bFullScreen)
245     {
246         if (m_pDirectDraw)
247         {
248             m_bIgnoreWM_SIZE = TRUE;
249             m_pDirectDraw->RestoreDisplayMode();
250             m_bIgnoreWM_SIZE = FALSE;
251         }
252     }
253 
254     RELEASE(m_pPalette);
255     RELEASE(m_pClipper);
256     RELEASE(m_pText1Surface);
257     RELEASE(m_pText2Surface);
258     RELEASE(m_pZBuffer);
259     RELEASE(m_pBackBuffer);
260     RELEASE(m_pFrontBuffer);
261 }
262 
SetErrorHandler(ErrorHandler errorHandler,void * pArg)263 void WrapDD::SetErrorHandler(ErrorHandler errorHandler, void *pArg)
264 {
265     m_pErrorHandler = errorHandler;
266     m_pErrorHandlerArg = pArg;
267 }
268 
SetFatalErrorHandler(ErrorHandler errorHandler,void * pArg)269 void WrapDD::SetFatalErrorHandler(ErrorHandler errorHandler, void *pArg)
270 {
271     m_pFatalErrorHandler = errorHandler;
272     m_pFatalErrorHandlerArg = pArg;
273 }
274 
275 /*************************************************************************
276   DirectDraw functions
277  *************************************************************************/
278 
279 // Checks to see if there is enough free video memory
FreeVideoMemory()280 long WrapDD::FreeVideoMemory()
281 {
282     HRESULT     result;
283     DDCAPS      ddcaps;
284 
285     memset(&ddcaps, 0, sizeof(ddcaps));
286     ddcaps.dwSize = sizeof(ddcaps);
287     result = m_pDirectDraw->GetCaps(&ddcaps, NULL);
288     if (result != DD_OK)
289     {
290         Error("GetCaps failed while checking for free memory", result);
291         return FALSE;
292     }
293     return ddcaps.dwVidMemFree;
294 }
295 
TotalVideoMemory()296 long WrapDD::TotalVideoMemory()
297 {
298     HRESULT     result;
299     DDCAPS      ddcaps;
300 
301     memset(&ddcaps, 0, sizeof(ddcaps));
302     ddcaps.dwSize = sizeof(ddcaps);
303     result = m_pDirectDraw->GetCaps(&ddcaps, NULL);
304     if (result != DD_OK)
305     {
306         Error("GetCaps failed while checking for total video memory", result);
307         return FALSE;
308     }
309 
310     return (long)(ddcaps.dwVidMemTotal);
311 }
312 
313 // Determines Z buffer depth.
GetHardwareCaps(DDCAPS & rDriverCaps,DDCAPS & rHELCaps)314 BOOL WrapDD::GetHardwareCaps(DDCAPS &rDriverCaps, DDCAPS &rHELCaps)
315 {
316     HRESULT     result;
317 
318     memset(&rDriverCaps, 0, sizeof(rDriverCaps));
319     memset(&rHELCaps, 0, sizeof(rHELCaps));
320     rDriverCaps.dwSize = sizeof(DDCAPS);
321     rHELCaps.dwSize = sizeof(DDCAPS);
322 
323     result = m_pDirectDraw->GetCaps(&rDriverCaps, &rHELCaps);
324     if (result != DD_OK)
325     {
326         Error("GetCaps failed", result);
327     }
328 
329     return (result == DD_OK);
330 }
331 
332 BOOL CALLBACK
EnumDirectDrawCallback(GUID * pGUID,char * pDriverDesc,char * pDriverName,void * pContext)333 WrapDD::EnumDirectDrawCallback(GUID * pGUID,
334                                char *pDriverDesc,
335                                char *pDriverName, void *pContext)
336 {
337     WrapDD     *pDirectDraw = (WrapDD *)pContext;
338 
339     return pDirectDraw->EnumDirectDrawCallback(pGUID, pDriverDesc,
340                                                pDriverName);
341 }
342 
EnumDirectDrawCallback(GUID * pGUID,char * pDriverDesc,char * pDriverName)343 BOOL WrapDD::EnumDirectDrawCallback(GUID * pGUID,
344                                     char *pDriverDesc, char *pDriverName)
345 {
346     if (pGUID)
347     {
348         IDirectDraw *pDirectDraw;
349         DDCAPS      driverCaps, helCaps;
350         HRESULT     result;
351 
352         result = DirectDrawCreate(pGUID, &pDirectDraw, NULL);
353         if (result != DD_OK)
354         {
355             Error
356                 ("Failing creating a DirectDraw device for testing. Continuing...",
357                  result);
358             return DDENUMRET_OK;
359         }
360 
361         if (!GetHardwareCaps(driverCaps, helCaps))
362         {
363             pDirectDraw->Release();
364             return DDENUMRET_OK;
365         }
366 
367         if (driverCaps.dwCaps & DDCAPS_3D)
368         {
369             // We have found a 3d hardware device
370             memcpy(&m_guid, pGUID, sizeof(GUID));
371 
372             m_bIsOnPrimaryDevice = FALSE;
373             m_pDirectDraw = pDirectDraw;
374             return DDENUMRET_CANCEL;
375         }
376 
377         // just to be sure
378         m_bIsOnPrimaryDevice = TRUE;
379         m_pDirectDraw = 0;
380         pDirectDraw->Release();
381     }
382 
383     return DDENUMRET_OK;
384 }
385 
386 // Create the DirectDraw object.
DDCreate()387 BOOL WrapDD::DDCreate()
388 {
389     HRESULT     result;
390 
391     assert(!m_pDirectDraw);
392 
393     // search for a 3D DirectDraw device
394     result = DirectDrawEnumerate(EnumDirectDrawCallback, (void *)this);
395     if (result != DD_OK)
396     {
397         Error("DirectDrawEnumerate failed", result);
398     }
399 
400     if (!m_pDirectDraw)
401     {
402         // did not find 3D DirectDraw device, use HEL
403         m_bIsOnPrimaryDevice = TRUE;
404         memset(&m_guid, 0, sizeof(m_guid));
405         result = DirectDrawCreate(0, &m_pDirectDraw, NULL);
406         if (result != DD_OK)
407         {
408             Error("DirectDrawCreate failed", result);
409         }
410     }
411 
412     return (m_pDirectDraw != 0);
413 }
414 
415 // Initialize the DirectDraw object.
DDInit(BOOL fullScreen)416 BOOL WrapDD::DDInit(BOOL fullScreen)
417 {
418     DDSURFACEDESC ddsd;
419     DDCAPS      driverCaps, helCaps;
420     HRESULT     result;
421 
422     assert(m_pDirectDraw);
423 
424     if (fullScreen)
425     {
426         m_bIgnoreWM_SIZE = TRUE;
427         result = m_pDirectDraw->SetCooperativeLevel(m_hWndMain,
428 #ifdef _DEBUG
429                                                     DDSCL_ALLOWREBOOT |
430 #endif
431 #if 0
432                                                     DDSCL_ALLOWMODEX |
433 #endif
434                                                     DDSCL_EXCLUSIVE |
435                                                     DDSCL_FULLSCREEN);
436         m_bIgnoreWM_SIZE = FALSE;
437     }
438     else
439     {
440         result = m_pDirectDraw->SetCooperativeLevel(m_hWndMain, DDSCL_NORMAL);
441     }
442 
443     if (result != DD_OK)
444     {
445         Error("SetCooperativeLevel failed", result);
446         return FALSE;
447     }
448 
449     if (!GetHardwareCaps(driverCaps, helCaps))
450     {
451         return FALSE;
452     }
453     memcpy(&m_HWddsCaps, &driverCaps.ddsCaps, sizeof(m_HWddsCaps));
454 
455     m_totalVideoMemory = TotalVideoMemory();
456 
457     if (!EnumerateDisplayModes())
458     {
459         return FALSE;
460     }
461 
462     memset(&ddsd, 0, sizeof(ddsd));
463     ddsd.dwSize = sizeof(ddsd);
464     result = m_pDirectDraw->GetDisplayMode(&ddsd);
465     if (result != DD_OK)
466     {
467         Error("GetDisplayMode failed", result);
468         return FALSE;
469     }
470 
471 #if 0
472     m_szWindowsDisplay.cx = ddsd.dwWidth;
473     m_szWindowsDisplay.cy = ddsd.dwHeight;
474 #endif
475 
476     m_bFullScreen = fullScreen;
477 
478     return TRUE;
479 }
480 
IsSupportedMode(int width,int height,int bpp)481 BOOL WrapDD::IsSupportedMode(int width, int height, int bpp)
482 {
483     Mode        mode = { width, height, bpp };
484     int         i;
485 
486     for (i = 0; i < m_modeCount; i++)
487     {
488         if (mode == m_modes[i])
489         {
490             return TRUE;
491         }
492     }
493 
494     return FALSE;
495 }
496 void
EnableResizing(HWND hwnd,BOOL flag)497 EnableResizing(HWND hwnd, BOOL flag)
498 {
499     static DWORD dwStyle;
500 
501     if (!flag)
502     {
503         dwStyle = GetWindowLong(hwnd, GWL_STYLE);
504         if (dwStyle & WS_THICKFRAME)
505         {
506             SetWindowLong(hwnd, GWL_STYLE,
507                           GetWindowLong(hwnd, GWL_STYLE) ^ WS_THICKFRAME);
508         }
509     }
510     else
511     {
512         SetWindowLong(hwnd, GWL_STYLE, dwStyle);
513     }
514 }
515 
516 // Initializes DirectDraw for a new display mode or window size.
DDSetMode(int width,int height,int bpp)517 BOOL WrapDD::DDSetMode(int width, int height, int bpp)
518 {
519     HRESULT     result;
520 
521     if (m_bFullScreen)
522     {
523         EnableResizing(m_hWndMain, FALSE);
524 
525         // For fullScreen, set the actual display mode.
526         if (!IsSupportedMode(width, height, bpp))
527         {
528             width = m_modes[0].width;
529             height = m_modes[0].height;
530             bpp = m_modes[0].bitsPerPixel;
531         }
532 
533         m_bIgnoreWM_SIZE = TRUE;
534         result = m_pDirectDraw->SetDisplayMode(width, height, bpp);
535         m_bIgnoreWM_SIZE = FALSE;
536 
537         if (result != DD_OK)
538         {
539             Error("SetDisplayMode failed", result);
540             return FALSE;
541         }
542     }
543     else
544     {
545         if (!m_bIsOnPrimaryDevice)
546         {
547             Error
548                 ("Attempt made enter a windowed mode on a DirectDraw device that is not the primary display",
549                  DDERR_GENERIC);
550             return FALSE;
551         }
552 /*
553  * I don't understand this code, but it doesn't seem to work at all,
554  * and taking it out helps. Bad, I know, but a girl's got to do what a
555  * girl's got to do.
556  */
557 #if 0
558         // For a window, set the window size.
559         RECT        rc;
560         DWORD       dwStyle;
561 
562         // Convert to a normal app window if we are still a WS_POPUP window.
563         m_bIgnoreWM_SIZE = TRUE;
564         dwStyle = GetWindowLong(m_hWndMain, GWL_STYLE);
565         dwStyle &= ~WS_POPUP;
566         dwStyle |= WS_OVERLAPPED | WS_CAPTION | WS_THICKFRAME;
567         SetWindowLong(m_hWndMain, GWL_STYLE, dwStyle);
568         SetRect(&rc, 0, 0, width, height);
569         AdjustWindowRectEx(&rc, GetWindowLong(m_hWndMain, GWL_STYLE),
570                            GetMenu(m_hWndMain) != NULL,
571                            GetWindowLong(m_hWndMain, GWL_EXSTYLE));
572         SetWindowPos(m_hWndMain, NULL,
573                      0, 0, rc.right - rc.left, rc.bottom - rc.top,
574                      SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
575         SetWindowPos(m_hWndMain, HWND_NOTOPMOST,
576                      0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
577         m_bIgnoreWM_SIZE = FALSE;
578 #endif
579     }
580 
581     m_currentMode.width = width;
582     m_currentMode.height = height;
583     m_currentMode.bitsPerPixel = bpp;
584 
585     // Create the front and back buffer surfaces
586     if (!DDCreateSurfaces())
587     {
588         return FALSE;
589     }
590 
591     // Palettize if we are not in a 16-bit mode.
592     DDSURFACEDESC ddsd;
593 
594     if (!GetDDSurfaceDesc(&ddsd, m_pBackBuffer))
595     {
596         return FALSE;
597     }
598 
599     if (ddsd.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8)
600     {
601         m_bPrimaryPalettized = TRUE;
602     }
603     else
604     {
605         m_bPrimaryPalettized = FALSE;
606     }
607 
608     if (m_bPrimaryPalettized)
609     {
610         result =
611             m_pDirectDraw->
612             CreatePalette(DDPCAPS_8BIT | DDPCAPS_ALLOW256 |
613                           DDPCAPS_INITIALIZE, m_paletteEntries, &m_pPalette,
614                           NULL);
615         if (result != DD_OK)
616         {
617             Error("CreatePalette failed", result);
618             return FALSE;
619         }
620         result = m_pBackBuffer->SetPalette(m_pPalette);
621         result = m_pFrontBuffer->SetPalette(m_pPalette);
622         if (result != DD_OK)
623         {
624             Error("SetPalette failed", result);
625             return FALSE;
626         }
627     }
628 
629     if (!CreateTextSurfaces())
630         return FALSE;
631     return TRUE;
632 }
633 
634 // Used to create surfaces instead of calling DD directly.
635 HRESULT
CreateDDSurface(LPDDSURFACEDESC lpDDSurfDesc,LPDIRECTDRAWSURFACE FAR * lpDDSurface,IUnknown FAR * pUnkOuter)636 WrapDD::CreateDDSurface(LPDDSURFACEDESC lpDDSurfDesc,
637                         LPDIRECTDRAWSURFACE FAR * lpDDSurface,
638                         IUnknown FAR * pUnkOuter)
639 {
640     HRESULT     result;
641     result =
642         m_pDirectDraw->CreateSurface(lpDDSurfDesc, lpDDSurface, pUnkOuter);
643     // TRACE("Created Surface<0x%x>\n", (void*) *lpDDSurface);
644     return result;
645 }
646 
647 // Gets a surface description.
648 BOOL
GetDDSurfaceDesc(LPDDSURFACEDESC lpDDSurfDesc,LPDIRECTDRAWSURFACE lpDDSurf)649 WrapDD::GetDDSurfaceDesc(LPDDSURFACEDESC lpDDSurfDesc,
650                          LPDIRECTDRAWSURFACE lpDDSurf)
651 {
652     HRESULT     result;
653 
654     memset(lpDDSurfDesc, 0, sizeof(DDSURFACEDESC));
655     lpDDSurfDesc->dwSize = sizeof(DDSURFACEDESC);
656     result = lpDDSurf->GetSurfaceDesc(lpDDSurfDesc);
657     if (result != DD_OK)
658     {
659         Error("Error getting a surface description", result);
660     }
661 
662     return (result == DD_OK);
663 }
664 
665 // Create front and back buffers as DirectDraw surfaces.
DDCreateSurfaces()666 BOOL WrapDD::DDCreateSurfaces()
667 {
668     HRESULT     result;
669     DDSURFACEDESC ddsd;
670     DDSCAPS     ddscaps;
671 
672     if (m_bFullScreen)
673     {
674         // Create a complex flipping surface for fullScreen mode.
675         memset(&ddsd, 0, sizeof(DDSURFACEDESC));
676         ddsd.dwSize = sizeof(ddsd);
677         ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
678         ddsd.ddsCaps.dwCaps =
679             DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_3DDEVICE |
680             DDSCAPS_COMPLEX;
681         if (m_bOnlySystemMemory)
682             ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
683         ddsd.dwBackBufferCount = 1;
684         result = CreateDDSurface(&ddsd, &m_pFrontBuffer, NULL);
685         // TRACE("Created Front Buffer<0x%x>\n", (void*) m_pFrontBuffer);
686         if (result != DD_OK)
687         {
688             Error("CreateSurface for front/back fullScreen buffer failed",
689                   result);
690             return FALSE;
691         }
692         ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
693         result = m_pFrontBuffer->GetAttachedSurface(&ddscaps, &m_pBackBuffer);
694         if (result != DD_OK)
695         {
696             Error("GetAttachedSurface failed to get back buffer", result);
697             return FALSE;
698         }
699         if (!GetDDSurfaceDesc(&ddsd, m_pBackBuffer))
700         {
701             return FALSE;
702         }
703 
704         if (!(ddsd.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
705         {
706             // ???
707             m_bOnlySoftRender;
708         }
709     }
710     else
711     {
712         // Window case
713         memset(&ddsd, 0, sizeof(DDSURFACEDESC));
714         ddsd.dwSize = sizeof(DDSURFACEDESC);
715         ddsd.dwFlags = DDSD_CAPS;
716         ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
717         result = CreateDDSurface(&ddsd, &m_pFrontBuffer, NULL);
718         // TRACE("Created Front Buffer<0x%x>\n", (void*) m_pFrontBuffer);
719         if (result != DD_OK)
720         {
721             Error("CreateSurface for window front buffer failed", result);
722             return FALSE;
723         }
724         ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
725         ddsd.dwHeight = m_currentMode.height;
726         ddsd.dwWidth = m_currentMode.width;
727         ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
728         if (m_bOnlySystemMemory)
729             ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
730         result = CreateDDSurface(&ddsd, &m_pBackBuffer, NULL);
731         // TRACE("Created Back Buffer<0x%x>\n", (void*) m_pBackBuffer);
732         if (result != DD_OK)
733         {
734             Error("CreateSurface for window back buffer failed", result);
735             return FALSE;
736         }
737         if (!GetDDSurfaceDesc(&ddsd, m_pBackBuffer))
738         {
739             return FALSE;
740         }
741         if (!(ddsd.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
742         {
743             // ???
744             m_bOnlySoftRender;
745         }
746 
747         // Create a DirectDrawClipper object.
748         result = m_pDirectDraw->CreateClipper(0, &m_pClipper, NULL);
749         if (result != DD_OK)
750         {
751             Error("CreateClipper failed", result);
752             return FALSE;
753         }
754         result = m_pClipper->SetHWnd(0, m_hWndMain);
755         if (result != DD_OK)
756         {
757             Error("Clipper SetHWnd failed", result);
758             return FALSE;
759         }
760         result = m_pFrontBuffer->SetClipper(m_pClipper);
761         if (result != DD_OK)
762         {
763             Error("SetClipper failed", result);
764             return FALSE;
765         }
766     }
767 
768     return TRUE;
769 }
770 
771 BOOL
TextSurfaceToBackBuffer(IDirectDrawSurface * pSurface,SIZE & textSizeOnSurface,int y)772 WrapDD::TextSurfaceToBackBuffer(IDirectDrawSurface * pSurface,
773                                 SIZE & textSizeOnSurface, int y)
774 {
775     if (textSizeOnSurface.cx > 0 &&
776         textSizeOnSurface.cy > 0 &&
777         textSizeOnSurface.cx < m_currentMode.width &&
778         textSizeOnSurface.cy < m_currentMode.height)
779     {
780         HRESULT     result;
781         RECT        rc;
782         int         x;
783 
784         SetRect(&rc, 0, 0, textSizeOnSurface.cx, textSizeOnSurface.cy);
785         x = (int)(0.5 * (m_currentMode.width - textSizeOnSurface.cx) + 0.5);
786         result = m_pBackBuffer->BltFast(x, y, pSurface, &rc,
787                                         DDBLTFAST_SRCCOLORKEY |
788                                         DDBLTFAST_WAIT);
789         if (result != DD_OK)
790         {
791             return FALSE;
792         }
793     }
794 
795     return TRUE;
796 }
797 
TextSurface1ToBackBuffer()798 BOOL WrapDD::TextSurface1ToBackBuffer()
799 {
800     return TextSurfaceToBackBuffer(m_pText1Surface, m_text1SizeOnSurface, 0);
801 }
802 
TextSurface2ToBackBuffer()803 BOOL WrapDD::TextSurface2ToBackBuffer()
804 {
805     return TextSurfaceToBackBuffer(m_pText2Surface,
806                                    m_text2SizeOnSurface,
807                                    m_currentMode.height -
808                                    m_text2SizeOnSurface.cy);
809 }
810 
811 BOOL
TextToTextSurface(const char * text,IDirectDrawSurface * pSurface,SIZE & textSizeOnSurface)812 WrapDD::TextToTextSurface(const char *text,
813                           IDirectDrawSurface * pSurface,
814                           SIZE & textSizeOnSurface)
815 {
816     HRESULT     result;
817     HDC         hdc;
818     RECT        rc;
819     size_t      textLength;
820 
821     if (!pSurface)
822         return FALSE;
823 
824     result = pSurface->GetDC(&hdc);
825     if (result != DD_OK)
826     {
827         Error("GetDC for text surface failed", result);
828         return FALSE;
829     }
830 
831     textLength = strlen(text);
832 
833     SelectObject(hdc, m_hFont);
834     SetTextColor(hdc, RGB(255, 255, 0));
835     SetBkColor(hdc, RGB(0, 0, 0));
836     SetBkMode(hdc, OPAQUE);
837     GetTextExtentPoint32(hdc, text, textLength, &textSizeOnSurface);
838     SetRect(&rc, 0, 0, textSizeOnSurface.cx, textSizeOnSurface.cy);
839     ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rc, text, textLength, NULL);
840     pSurface->ReleaseDC(hdc);
841 
842     return TRUE;
843 }
844 
TextToTextSurface1(const char * text)845 BOOL WrapDD::TextToTextSurface1(const char *text)
846 {
847     return TextToTextSurface(text, m_pText1Surface, m_text1SizeOnSurface);
848 }
849 
TextToTextSurface2(const char * text)850 BOOL WrapDD::TextToTextSurface2(const char *text)
851 {
852     return TextToTextSurface(text, m_pText2Surface, m_text2SizeOnSurface);
853 }
854 
CreateTextSurfaces()855 BOOL WrapDD::CreateTextSurfaces()
856 {
857     HRESULT     result;
858     DDCOLORKEY  ddck;
859     DDSURFACEDESC ddsd;
860     HDC         hdc;
861     char        dummyinfo[] = "000x000x00 (RAMP) 0000";
862     char        dummyfps[] = "000.00 fps (000.00 fps (000.00 fps) 00000 tps)";
863     /*
864      * Create the font.
865      */
866     if (m_hFont != NULL)
867     {
868         DeleteObject(m_hFont);
869     }
870     m_hFont = CreateFont(m_currentMode.width <= 600 ? 12 : 24,
871                          0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE,
872                          ANSI_CHARSET,
873                          OUT_DEFAULT_PRECIS,
874                          CLIP_DEFAULT_PRECIS,
875                          DEFAULT_QUALITY, VARIABLE_PITCH, "Arial");
876 
877     hdc = GetDC(NULL);
878     SelectObject(hdc, m_hFont);
879     GetTextExtentPoint(hdc, dummyfps, strlen(dummyfps),
880                        &m_text1SizeOnSurface);
881     GetTextExtentPoint(hdc, dummyinfo, strlen(dummyinfo),
882                        &m_text2SizeOnSurface);
883     ReleaseDC(NULL, hdc);
884 
885     memset(&ddsd, 0, sizeof(ddsd));
886     ddsd.dwSize = sizeof(ddsd);
887     ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
888     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
889     if (m_bOnlySystemMemory)
890         ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
891     ddsd.dwHeight = m_text1SizeOnSurface.cy;
892     ddsd.dwWidth = m_text1SizeOnSurface.cx;
893     result = CreateDDSurface(&ddsd, &m_pText1Surface, NULL);
894     // TRACE("Created Text1 Surface<0x%x>\n", (void*) m_pText1Surface);
895     if (result != DD_OK)
896     {
897         Error("CreateSurface for text surface 1 failed", result);
898         return FALSE;
899     }
900     memset(&ddck, 0, sizeof(ddck));
901     m_pText1Surface->SetColorKey(DDCKEY_SRCBLT, &ddck);
902     if (!TextToTextSurface1(dummyfps))
903         return FALSE;
904 
905     memset(&ddsd, 0, sizeof(ddsd));
906     ddsd.dwSize = sizeof(ddsd);
907     ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
908     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
909     if (m_bOnlySystemMemory)
910         ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
911     ddsd.dwHeight = m_text2SizeOnSurface.cy;
912     ddsd.dwWidth = m_text2SizeOnSurface.cx;
913     result = CreateDDSurface(&ddsd, &m_pText2Surface, NULL);
914     // TRACE("Created Text2 Surface<0x%x>\n", (void*) m_pText2Surface);
915     if (result != DD_OK)
916     {
917         Error("CreateSurface for text surface 2 failed", result);
918         return FALSE;
919     }
920     memset(&ddck, 0, sizeof(ddck));
921     m_pText2Surface->SetColorKey(DDCKEY_SRCBLT, &ddck);
922     if (!TextToTextSurface2(dummyinfo))
923         return FALSE;
924     return TRUE;
925 }
926 
927 // Restores any lost surfaces.
RestoreSurfaces()928 BOOL WrapDD::RestoreSurfaces()
929 {
930     HRESULT     result;
931 
932     if (m_pFrontBuffer->IsLost() == DDERR_SURFACELOST)
933     {
934         result = m_pFrontBuffer->Restore();
935         if (result != DD_OK)
936         {
937             Error("Restore of front buffer failed", result);
938             return FALSE;
939         }
940     }
941     if (m_pBackBuffer->IsLost() == DDERR_SURFACELOST)
942     {
943         result = m_pBackBuffer->Restore();
944         if (result != DD_OK)
945         {
946             Error("Restore of back buffer failed", result);
947             return FALSE;
948         }
949     }
950     if (m_pZBuffer->IsLost() == DDERR_SURFACELOST)
951     {
952         result = m_pZBuffer->Restore();
953         if (result != DD_OK)
954         {
955             Error("Restore of Z-buffer failed", result);
956             return FALSE;
957         }
958     }
959     if (m_pText1Surface->IsLost() == DDERR_SURFACELOST)
960     {
961         result = m_pText1Surface->Restore();
962         if (result != DD_OK)
963         {
964             Error("Restore of text surface 1 failed", result);
965             return FALSE;
966         }
967     }
968     if (m_pText2Surface->IsLost() == DDERR_SURFACELOST)
969     {
970         result = m_pText2Surface->Restore();
971         if (result != DD_OK)
972         {
973             Error("Restore of text surface 2 failed", result);
974             return FALSE;
975         }
976     }
977 
978     return TRUE;
979 }
980 
981 /*************************************************************************
982  Enumerating the display modes.
983  *************************************************************************/
984 
EnumDisplayModesCallback(LPDDSURFACEDESC pddsd,LPVOID pContext)985 HRESULT CALLBACK WrapDD::EnumDisplayModesCallback(LPDDSURFACEDESC pddsd,
986                                                   LPVOID pContext)
987 {
988     WrapDD     *pDirectDraw = (WrapDD *)pContext;
989 
990     return pDirectDraw->EnumDisplayModesCallback(pddsd);
991 }
992 
EnumDisplayModesCallback(LPDDSURFACEDESC pddsd)993 HRESULT WrapDD::EnumDisplayModesCallback(LPDDSURFACEDESC pddsd)
994 {
995     if (FilterDisplayModes(pddsd))
996     {
997         m_modes[m_modeCount].width = pddsd->dwWidth;
998         m_modes[m_modeCount].height = pddsd->dwHeight;
999         m_modes[m_modeCount].bitsPerPixel =
1000             pddsd->ddpfPixelFormat.dwRGBBitCount;
1001         // TRACE("DisplayMode %d [%dx%dx%d]\n",
1002         // m_modeCount,
1003         // m_modes[m_modeCount].width,
1004         // m_modes[m_modeCount].height,
1005         // m_modes[m_modeCount].bitsPerPixel);
1006         m_modeCount++;
1007     }
1008 
1009     if (m_modeCount >= (sizeof(m_modes) / sizeof(m_modes[0])))
1010     {
1011         assert(0);
1012         return DDENUMRET_CANCEL;
1013     }
1014 
1015     return DDENUMRET_OK;
1016 }
1017 
FilterDisplayModes(LPDDSURFACEDESC)1018 BOOL WrapDD::FilterDisplayModes(LPDDSURFACEDESC)
1019 {
1020     return TRUE;
1021 }
1022 
1023 // Compare two display modes for sorting purposes.
CompareModes(const void * element1,const void * element2)1024 int _cdecl WrapDD::CompareModes(const void *element1, const void *element2)
1025 {
1026     Mode       *pMode1 = (Mode *) element1;
1027     Mode       *pMode2 = (Mode *) element2;
1028 
1029     if (pMode1->bitsPerPixel > pMode2->bitsPerPixel)
1030         return -1;
1031     else if (pMode2->bitsPerPixel > pMode1->bitsPerPixel)
1032         return 1;
1033     else if (pMode1->width > pMode2->width)
1034         return -1;
1035     else if (pMode2->width > pMode1->width)
1036         return 1;
1037     else if (pMode1->height > pMode2->height)
1038         return -1;
1039     else if (pMode2->height > pMode1->height)
1040         return 1;
1041     else
1042         return 0;
1043 }
1044 
1045 // Generates the list of available display modes.
EnumerateDisplayModes()1046 BOOL WrapDD::EnumerateDisplayModes()
1047 {
1048     HRESULT     result;
1049 
1050     m_modeCount = 0;
1051     result = m_pDirectDraw->EnumDisplayModes(0, 0, (void *)this,
1052                                              EnumDisplayModesCallback);
1053     if (result != DD_OK)
1054     {
1055         Error("EnumDisplayModes failed", result);
1056         return FALSE;
1057     }
1058     qsort((void *)&m_modes[0], (size_t) m_modeCount, sizeof(m_modes[0]),
1059           CompareModes);
1060 
1061     return TRUE;
1062 }
1063 
1064 /*************************************************************************
1065   Direct3D initialization
1066  *************************************************************************/
1067 
CreateZBuffer(DWORD memorytype,DWORD depth)1068 BOOL WrapDD::CreateZBuffer(DWORD memorytype, DWORD depth)
1069 {
1070     HRESULT     result;
1071     LPDIRECTDRAWSURFACE lpZBuffer;
1072     DDSURFACEDESC ddsd;
1073 
1074     // Create a Z-Buffer and attach it to the back buffer.
1075 
1076     memset(&ddsd, 0, sizeof(ddsd));
1077     ddsd.dwSize = sizeof(ddsd);
1078     ddsd.dwFlags =
1079         DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_ZBUFFERBITDEPTH;
1080     ddsd.dwHeight = m_currentMode.height;
1081     ddsd.dwWidth = m_currentMode.width;
1082     ddsd.dwZBufferBitDepth = depth;
1083     ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | memorytype;
1084     result = CreateDDSurface(&ddsd, &lpZBuffer, 0);
1085 
1086     // TRACE("Created Z Buffer<0x%x>\n", (void*) lpZBuffer);
1087 
1088     if (result != DD_OK)
1089     {
1090         Error("CreateSurface for fullScreen Z-buffer failed", result);
1091         return FALSE;
1092     }
1093 
1094     result = m_pBackBuffer->AddAttachedSurface(lpZBuffer);
1095     if (result != DD_OK)
1096     {
1097         Error("AddAttachedBuffer failed for Z-Buffer", result);
1098         return FALSE;
1099     }
1100 
1101     m_pZBuffer = lpZBuffer;
1102     return TRUE;
1103 }
1104 
1105 // application should call this when it "pauses"
Pause(BOOL pause)1106 BOOL WrapDD::Pause(BOOL pause)
1107 {
1108     if (pause)
1109     {
1110         ++m_pauseCount;
1111 
1112         if (m_pauseCount > 1)
1113         {
1114             return TRUE;
1115         }
1116 
1117         if (!RestoreOriginalPaletteEntries())
1118         {
1119             return FALSE;
1120         }
1121 
1122         if (m_bFullScreen)
1123         {
1124             if (!FlipToGDISurface())
1125             {
1126                 return FALSE;
1127             }
1128 
1129             // ???
1130             DrawMenuBar(m_hWndMain);
1131             RedrawWindow(m_hWndMain, NULL, NULL, RDW_FRAME);
1132         }
1133     }
1134     else
1135     {
1136         --m_pauseCount;
1137 
1138         if (m_pauseCount > 0)
1139         {
1140             return TRUE;
1141         }
1142 
1143         if (m_pauseCount < 0)
1144         {
1145             m_pauseCount = 0;
1146         }
1147 
1148         if (!RestorePaletteEntries())
1149         {
1150             return FALSE;
1151         }
1152     }
1153 
1154     return TRUE;
1155 }
1156 
Flip()1157 BOOL WrapDD::Flip()
1158 {
1159     HRESULT     result;
1160 
1161     result = m_pFrontBuffer->Flip(m_pBackBuffer, DDFLIP_WAIT);
1162     if (result != DD_OK)
1163     {
1164         Error("Flip failed", result);
1165     }
1166 
1167     return (result == DD_OK);
1168 }
1169 
BltBackBuffer(RECT & to,RECT & from)1170 BOOL WrapDD::BltBackBuffer(RECT &to, RECT &from)
1171 {
1172     HRESULT     result;
1173 
1174     result = m_pFrontBuffer->Blt(&to, m_pBackBuffer, &from, DDBLT_WAIT, NULL);
1175     if (result != DD_OK)
1176     {
1177         Error("Blt of back to front buffer failed", result);
1178     }
1179 
1180     return (result == DD_OK);
1181 }
1182 
Activate()1183 BOOL WrapDD::Activate()
1184 {
1185     if (m_bPrimaryPalettized)
1186     {
1187         HRESULT     result;
1188 
1189         result = m_pFrontBuffer->SetPalette(m_pPalette);
1190         if (result != DD_OK)
1191         {
1192             Error("SetPalette on front buffer failed", result);
1193         }
1194 
1195         return (result == DD_OK);
1196     }
1197 
1198     return TRUE;
1199 }
1200 
RestorePaletteEntries()1201 BOOL WrapDD::RestorePaletteEntries()
1202 {
1203     if (m_bFullScreen && m_bPrimaryPalettized)
1204     {
1205         if (m_pPalette)
1206         {
1207             HRESULT     result;
1208 
1209             result = m_pPalette->SetEntries(0, 0,
1210                                             sizeof(m_paletteEntries) /
1211                                             sizeof(m_paletteEntries[0]),
1212                                             m_paletteEntries);
1213             if (result != DD_OK)
1214             {
1215                 Error("SetEntries failed", result);
1216                 return FALSE;
1217             }
1218         }
1219     }
1220 
1221     return TRUE;
1222 }
1223 
RestoreOriginalPaletteEntries()1224 BOOL WrapDD::RestoreOriginalPaletteEntries()
1225 {
1226     if (m_bPrimaryPalettized)
1227     {
1228 #if 0
1229         HRESULT     result;
1230 
1231         result = m_pPalette->GetEntries(0, 0, 256, &m_paletteEntries[0]);
1232         if (result != DD_OK)
1233         {
1234             Error("GetEntries failed", result);
1235             return FALSE;
1236         }
1237 
1238         for (int i = 10; i < 246; i++)
1239         {
1240             m_originalPaletteEntries[i] = m_paletteEntries[i];
1241         }
1242 #endif
1243         if (m_pPalette)
1244         {
1245             HRESULT     result;
1246 
1247             result = m_pPalette->SetEntries(0, 0,
1248                                             sizeof(m_originalPaletteEntries) /
1249                                             sizeof(m_originalPaletteEntries
1250                                                    [0]),
1251                                             m_originalPaletteEntries);
1252             if (result != DD_OK)
1253             {
1254                 Error("SetEntries failed", result);
1255                 return FALSE;
1256             }
1257         }
1258     }
1259 
1260     return TRUE;
1261 }
1262 
FlipToGDISurface()1263 BOOL WrapDD::FlipToGDISurface()
1264 {
1265     if (m_pDirectDraw)
1266     {
1267         HRESULT     result;
1268 
1269         result = m_pDirectDraw->FlipToGDISurface();
1270         if (result != DD_OK)
1271         {
1272             Error("FlipToGDISurface failed", result);
1273         }
1274 
1275         return (result == DD_OK);
1276     }
1277 
1278     return TRUE;
1279 }
1280 
1281 #if 0
1282 // ???
1283 case WM_PAINT:
1284 if (stat.bFullscreen && !app.bAppPaused)
1285 {
1286     ValidateRect(hWnd, NULL);
1287     return 1;
1288 }
1289 break;
1290 case WM_NCPAINT:
1291 if (stat.bFullscreen && !app.bAppPaused)
1292     return 1;
1293 break;
1294 case WM_ERASEBKGND:
1295 if (stat.bFullscreen && !app.bAppPaused)
1296     return 1;
1297 break;
1298 case WM_MOVING:
1299 if (stat.bFullscreen)
1300 {
1301     GetWindowRect(app.hWndMain, (LPRECT) lParam);
1302     return 1;
1303 }
1304 break;
1305 case WM_MOVE:
1306 p1.x = p1.y = 0;
1307 ClientToScreen(app.hWndMain, &p1);
1308 p2.x = app.Mode.cx;
1309 p2.y = app.Mode.cy;
1310 ClientToScreen(app.hWndMain, &p2);
1311 SetRect(&app.rcClient, p1.x, p1.y, p2.x, p2.y);
1312 break;
1313 
1314 case WM_SIZE:
1315 ...;
1316 if (app.Mode.cx > szWindowsDisplay.cx)
1317     app.Mode.cx = szWindowsDisplay.cx;
1318 if (app.Mode.cy > szWindowsDisplay.cy)
1319     app.Mode.cy = szWindowsDisplay.cy;
1320 ...break;
1321 
1322 case MENU_FULLSCREEN:
1323 if (!dd.bIsPrimary)
1324     break;
1325 stat.bFullscreen = !stat.bFullscreen;
1326 if (!SwitchMode())
1327 {
1328     CleanUpAndPostQuit();
1329     break;
1330 }
1331 #endif
1332 
FatalError(const char * message,HRESULT error)1333 void WrapDD::FatalError(const char *message, HRESULT error)
1334 {
1335     static BOOL g_isInsideFatalError = FALSE;
1336 
1337     if (g_isInsideFatalError)
1338     {
1339         return;
1340     }
1341 
1342     g_isInsideFatalError = TRUE;
1343 
1344     Destroy();
1345 
1346     if (m_pFatalErrorHandler)
1347     {
1348         m_pFatalErrorHandler(message, error, m_pFatalErrorHandlerArg);
1349     }
1350 }
1351 
Error(const char * message,HRESULT error)1352 void WrapDD::Error(const char *message, HRESULT error)
1353 {
1354     static BOOL g_isInsideError = FALSE;
1355 
1356     if (g_isInsideError)
1357     {
1358         return;
1359     }
1360 
1361     g_isInsideError = TRUE;
1362 
1363     Destroy();
1364 
1365     if (m_pErrorHandler)
1366     {
1367         m_pErrorHandler(message, error, m_pErrorHandlerArg);
1368     }
1369 
1370     g_isInsideError = FALSE;
1371 }
1372 
1373 // Returns a pointer to a string describing the given error code.
ErrorToString(HRESULT error)1374 const char *WrapDD::ErrorToString(HRESULT error)
1375 {
1376     switch (error)
1377     {
1378     case DD_OK:
1379         return "No error.\0";
1380     case DDERR_ALREADYINITIALIZED:
1381         return "This object is already initialized.\0";
1382     case DDERR_BLTFASTCANTCLIP:
1383         return
1384             "Return if a clipper object is attached to the source surface passed into a BltFast call.\0";
1385     case DDERR_CANNOTATTACHSURFACE:
1386         return "This surface can not be attached to the requested surface.\0";
1387     case DDERR_CANNOTDETACHSURFACE:
1388         return
1389             "This surface can not be detached from the requested surface.\0";
1390     case DDERR_CANTCREATEDC:
1391         return "Windows can not create any more DCs.\0";
1392     case DDERR_CANTDUPLICATE:
1393         return
1394             "Can't duplicate primary & 3D surfaces, or surfaces that are implicitly created.\0";
1395     case DDERR_CLIPPERISUSINGHWND:
1396         return
1397             "An attempt was made to set a cliplist for a clipper object that is already monitoring an hwnd.\0";
1398     case DDERR_COLORKEYNOTSET:
1399         return "No src color key specified for this operation.\0";
1400     case DDERR_CURRENTLYNOTAVAIL:
1401         return "Support is currently not available.\0";
1402     case DDERR_DIRECTDRAWALREADYCREATED:
1403         return
1404             "A DirectDraw object representing this driver has already been created for this process.\0";
1405     case DDERR_EXCEPTION:
1406         return
1407             "An exception was encountered while performing the requested operation.\0";
1408     case DDERR_EXCLUSIVEMODEALREADYSET:
1409         return
1410             "An attempt was made to set the cooperative level when it was already set to exclusive.\0";
1411     case DDERR_GENERIC:
1412         return "Generic failure.\0";
1413     case DDERR_HEIGHTALIGN:
1414         return
1415             "Height of rectangle provided is not a multiple of reqd alignment.\0";
1416     case DDERR_HWNDALREADYSET:
1417         return
1418             "The CooperativeLevel HWND has already been set. It can not be reset while the process has surfaces or palettes created.\0";
1419     case DDERR_HWNDSUBCLASSED:
1420         return
1421             "HWND used by DirectDraw CooperativeLevel has been subclassed, this prevents DirectDraw from restoring state.\0";
1422     case DDERR_IMPLICITLYCREATED:
1423         return
1424             "This surface can not be restored because it is an implicitly created surface.\0";
1425     case DDERR_INCOMPATIBLEPRIMARY:
1426         return
1427             "Unable to match primary surface creation request with existing primary surface.\0";
1428     case DDERR_INVALIDCAPS:
1429         return
1430             "One or more of the caps bits passed to the callback are incorrect.\0";
1431     case DDERR_INVALIDCLIPLIST:
1432         return "DirectDraw does not support the provided cliplist.\0";
1433     case DDERR_INVALIDDIRECTDRAWGUID:
1434         return
1435             "The GUID passed to DirectDrawCreate is not a valid DirectDraw driver identifier.\0";
1436     case DDERR_INVALIDMODE:
1437         return "DirectDraw does not support the requested mode.\0";
1438     case DDERR_INVALIDOBJECT:
1439         return
1440             "DirectDraw received a pointer that was an invalid DIRECTDRAW object.\0";
1441     case DDERR_INVALIDPARAMS:
1442         return
1443             "One or more of the parameters passed to the function are incorrect.\0";
1444     case DDERR_INVALIDPIXELFORMAT:
1445         return "The pixel format was invalid as specified.\0";
1446     case DDERR_INVALIDPOSITION:
1447         return
1448             "Returned when the position of the overlay on the destination is no longer legal for that destination.\0";
1449     case DDERR_INVALIDRECT:
1450         return "Rectangle provided was invalid.\0";
1451     case DDERR_LOCKEDSURFACES:
1452         return
1453             "Operation could not be carried out because one or more surfaces are locked.\0";
1454     case DDERR_NO3D:
1455         return "There is no 3D present.\0";
1456     case DDERR_NOALPHAHW:
1457         return
1458             "Operation could not be carried out because there is no alpha accleration hardware present or available.\0";
1459     case DDERR_NOBLTHW:
1460         return "No blitter hardware present.\0";
1461     case DDERR_NOCLIPLIST:
1462         return "No cliplist available.\0";
1463     case DDERR_NOCLIPPERATTACHED:
1464         return "No clipper object attached to surface object.\0";
1465     case DDERR_NOCOLORCONVHW:
1466         return
1467             "Operation could not be carried out because there is no color conversion hardware present or available.\0";
1468     case DDERR_NOCOLORKEY:
1469         return "Surface doesn't currently have a color key\0";
1470     case DDERR_NOCOLORKEYHW:
1471         return
1472             "Operation could not be carried out because there is no hardware support of the destination color key.\0";
1473     case DDERR_NOCOOPERATIVELEVELSET:
1474         return
1475             "Create function called without DirectDraw object method SetCooperativeLevel being called.\0";
1476     case DDERR_NODC:
1477         return "No DC was ever created for this surface.\0";
1478     case DDERR_NODDROPSHW:
1479         return "No DirectDraw ROP hardware.\0";
1480     case DDERR_NODIRECTDRAWHW:
1481         return
1482             "A hardware-only DirectDraw object creation was attempted but the driver did not support any hardware.\0";
1483     case DDERR_NOEMULATION:
1484         return "Software emulation not available.\0";
1485     case DDERR_NOEXCLUSIVEMODE:
1486         return
1487             "Operation requires the application to have exclusive mode but the application does not have exclusive mode.\0";
1488     case DDERR_NOFLIPHW:
1489         return "Flipping visible surfaces is not supported.\0";
1490     case DDERR_NOGDI:
1491         return "There is no GDI present.\0";
1492     case DDERR_NOHWND:
1493         return
1494             "Clipper notification requires an HWND or no HWND has previously been set as the CooperativeLevel HWND.\0";
1495     case DDERR_NOMIRRORHW:
1496         return
1497             "Operation could not be carried out because there is no hardware present or available.\0";
1498     case DDERR_NOOVERLAYDEST:
1499         return
1500             "Returned when GetOverlayPosition is called on an overlay that UpdateOverlay has never been called on to establish a destination.\0";
1501     case DDERR_NOOVERLAYHW:
1502         return
1503             "Operation could not be carried out because there is no overlay hardware present or available.\0";
1504     case DDERR_NOPALETTEATTACHED:
1505         return "No palette object attached to this surface.\0";
1506     case DDERR_NOPALETTEHW:
1507         return "No hardware support for 16 or 256 color palettes.\0";
1508     case DDERR_NORASTEROPHW:
1509         return
1510             "Operation could not be carried out because there is no appropriate raster op hardware present or available.\0";
1511     case DDERR_NOROTATIONHW:
1512         return
1513             "Operation could not be carried out because there is no rotation hardware present or available.\0";
1514     case DDERR_NOSTRETCHHW:
1515         return
1516             "Operation could not be carried out because there is no hardware support for stretching.\0";
1517     case DDERR_NOT4BITCOLOR:
1518         return
1519             "DirectDrawSurface is not in 4 bit color palette and the requested operation requires 4 bit color palette.\0";
1520     case DDERR_NOT4BITCOLORINDEX:
1521         return
1522             "DirectDrawSurface is not in 4 bit color index palette and the requested operation requires 4 bit color index palette.\0";
1523     case DDERR_NOT8BITCOLOR:
1524         return
1525             "DirectDrawSurface is not in 8 bit color mode and the requested operation requires 8 bit color.\0";
1526     case DDERR_NOTAOVERLAYSURFACE:
1527         return
1528             "Returned when an overlay member is called for a non-overlay surface.\0";
1529     case DDERR_NOTEXTUREHW:
1530         return
1531             "Operation could not be carried out because there is no texture mapping hardware present or available.\0";
1532     case DDERR_NOTFLIPPABLE:
1533         return
1534             "An attempt has been made to flip a surface that is not flippable.\0";
1535     case DDERR_NOTFOUND:
1536         return "Requested item was not found.\0";
1537     case DDERR_NOTLOCKED:
1538         return
1539             "Surface was not locked.  An attempt to unlock a surface that was not locked at all, or by this process, has been attempted.\0";
1540     case DDERR_NOTPALETTIZED:
1541         return "The surface being used is not a palette-based surface.\0";
1542     case DDERR_NOVSYNCHW:
1543         return
1544             "Operation could not be carried out because there is no hardware support for vertical blank synchronized operations.\0";
1545     case DDERR_NOZBUFFERHW:
1546         return
1547             "Operation could not be carried out because there is no hardware support for zbuffer blitting.\0";
1548     case DDERR_NOZOVERLAYHW:
1549         return
1550             "Overlay surfaces could not be z layered based on their BltOrder because the hardware does not support z layering of overlays.\0";
1551     case DDERR_OUTOFCAPS:
1552         return
1553             "The hardware needed for the requested operation has already been allocated.\0";
1554     case DDERR_OUTOFMEMORY:
1555         return
1556             "DirectDraw does not have enough memory to perform the operation.\0";
1557     case DDERR_OUTOFVIDEOMEMORY:
1558         return
1559             "DirectDraw does not have enough memory to perform the operation.\0";
1560     case DDERR_OVERLAYCANTCLIP:
1561         return "The hardware does not support clipped overlays.\0";
1562     case DDERR_OVERLAYCOLORKEYONLYONEACTIVE:
1563         return
1564             "Can only have ony color key active at one time for overlays.\0";
1565     case DDERR_OVERLAYNOTVISIBLE:
1566         return
1567             "Returned when GetOverlayPosition is called on a hidden overlay.\0";
1568     case DDERR_PALETTEBUSY:
1569         return
1570             "Access to this palette is being refused because the palette is already locked by another thread.\0";
1571     case DDERR_PRIMARYSURFACEALREADYEXISTS:
1572         return "This process already has created a primary surface.\0";
1573     case DDERR_REGIONTOOSMALL:
1574         return "Region passed to Clipper::GetClipList is too small.\0";
1575     case DDERR_SURFACEALREADYATTACHED:
1576         return
1577             "This surface is already attached to the surface it is being attached to.\0";
1578     case DDERR_SURFACEALREADYDEPENDENT:
1579         return
1580             "This surface is already a dependency of the surface it is being made a dependency of.\0";
1581     case DDERR_SURFACEBUSY:
1582         return
1583             "Access to this surface is being refused because the surface is already locked by another thread.\0";
1584     case DDERR_SURFACEISOBSCURED:
1585         return "Access to surface refused because the surface is obscured.\0";
1586     case DDERR_SURFACELOST:
1587         return
1588             "Access to this surface is being refused because the surface memory is gone. The DirectDrawSurface object representing this surface should have Restore called on it.\0";
1589     case DDERR_SURFACENOTATTACHED:
1590         return "The requested surface is not attached.\0";
1591     case DDERR_TOOBIGHEIGHT:
1592         return "Height requested by DirectDraw is too large.\0";
1593     case DDERR_TOOBIGSIZE:
1594         return
1595             "Size requested by DirectDraw is too large, but the individual height and width are OK.\0";
1596     case DDERR_TOOBIGWIDTH:
1597         return "Width requested by DirectDraw is too large.\0";
1598     case DDERR_UNSUPPORTED:
1599         return "Action not supported.\0";
1600     case DDERR_UNSUPPORTEDFORMAT:
1601         return "FOURCC format requested is unsupported by DirectDraw.\0";
1602     case DDERR_UNSUPPORTEDMASK:
1603         return
1604             "Bitmask in the pixel format requested is unsupported by DirectDraw.\0";
1605     case DDERR_VERTICALBLANKINPROGRESS:
1606         return "Vertical blank is in progress.\0";
1607     case DDERR_WASSTILLDRAWING:
1608         return
1609             "Informs DirectDraw that the previous Blt which is transfering information to or from this Surface is incomplete.\0";
1610     case DDERR_WRONGMODE:
1611         return
1612             "This surface can not be restored because it was created in a different mode.\0";
1613     case DDERR_XALIGN:
1614         return
1615             "Rectangle provided was not horizontally aligned on required boundary.\0";
1616     default:
1617         return "Unrecognized error value.\0";
1618     }
1619 }
1620 
1621 // Local Variables:
1622 // c-basic-offset: 4
1623 // c-comment-only-line-offset: 0
1624 // c-file-offsets: ((defun-block-intro . +) (block-open . 0) (substatement-open . 0) (statement-cont . +) (statement-case-open . +4) (arglist-intro . +) (arglist-close . +) (inline-open . 0))
1625 // indent-tabs-mode: nil
1626 // End:
1627