This commit was generated by cvs2svn to compensate for changes in r2,
[btb/d2x.git] / unused / win95 / dd.c
1 /*
2 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
3 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
4 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
5 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
6 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
7 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
8 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
9 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
10 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.  
11 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
12 */
13
14
15 #pragma off (unreferenced)
16 static char rcsid[] = "$Id: dd.c,v 1.1.1.1 2001-01-19 03:30:15 bradleyb Exp $";
17 #pragma on (unreferenced)
18
19
20
21 #define _WIN32
22 #define WIN95
23 #define WIN32_LEAN_AND_MEAN
24
25 #include <windows.h>
26 #include <windowsx.h>
27
28 #include <stdio.h>
29
30 #include "ddraw.h"
31
32 #include "pstypes.h"
33 #include "mono.h"
34 #include "args.h"
35 #include "error.h"
36 #include "winapp.h"
37 #include "dd.h"
38
39
40
41 //      Globals
42 //      ----------------------------------------------------------------------------
43
44 LPDIRECTDRAW                            _lpDD=0;                                // Direct Draw Object
45
46 LPDIRECTDRAWSURFACE             _lpDDSPrimary=0;        //      Page 0 and 1
47 LPDIRECTDRAWSURFACE             _lpDDSBack=0;           //
48
49 LPDIRECTDRAWCLIPPER             _lpDDClipper=0; // Window clipper Object
50 LPDIRECTDRAWPALETTE             _lpDDPalette=0; // Palette object
51
52 BOOL                                                    _DDFullScreen;          // Game is in window, or fullscreen
53 BOOL                                                    _DDSysMemSurfacing=TRUE;
54
55 int                                                     _DDNumModes=0;          // Number of graphic modes
56 DDMODEINFO                                      _DDModeList[16];        // Mode information list
57 int                                                     _DDLockCounter=0;       // DirectDraw Lock Surface counter
58
59
60 int                                                     W95DisplayMode,         // Current display mode from list
61                                                                 W95OldDisplayMode;//    Old display smode
62
63 dd_caps                                         ddDriverCaps;           // Direct Draw Caps?
64
65 static HWND                                     DDWnd=NULL;                     // Current window that owns the display
66 static FILE                                     *LogFile=NULL;
67 int                                     DD_Emulation=0; // Do we force emulated modes?
68
69 RECT                                    ViewportRect;                                   // Current Viewport
70
71
72 //      Function Prototypes
73 //      ----------------------------------------------------------------------------
74
75 HRESULT CALLBACK EnumDispModesCB(LPDDSURFACEDESC lpddsd, LPVOID context);
76 BOOL CheckDDResult(HRESULT ddresult, char *funcname);
77 void DDEmulateTest(void);
78
79 #define WRITELOG(t) if (LogFile) { fprintf t; fflush(LogFile);}
80
81
82
83 //      Initialization
84 //      ----------------------------------------------------------------------------
85
86 BOOL DDInit(int mode)
87 {
88         LPDIRECTDRAW lpdd;
89         HRESULT ddresult;
90         DWORD flags;
91
92 #ifndef NDEBUG
93         if (FindArg("-logfile")) LogFile = fopen("dd.log", "wt");
94         else LogFile = NULL;
95 #endif  
96
97 //      Create Direct Draw Object (Use Emulation if Hardware is off)
98         if (!_lpDD)     {
99                 {
100                         ddresult = DirectDrawCreate(NULL, &lpdd, NULL);
101                 
102                         if (ddresult == DDERR_NODIRECTDRAWHW) {
103                                 if (FindArg("-ddemul")) {
104                    ddresult = DirectDrawCreate( (LPVOID) DDCREATE_EMULATIONONLY, &lpdd, NULL );
105                                         if (!CheckDDResult(ddresult, "InitDD:DirectDrawCreate emulation"))
106                                                 return FALSE;
107                                         DD_Emulation = 1;
108                                         logentry("DirectDraw: forcing emulation.\n");
109                                 }
110                                 else {
111                                         CheckDDResult(ddresult, "InitDD:DirectDrawCreate noemulation");
112                                         return FALSE;
113                                 }
114                         }
115                         else if (ddresult != DD_OK) 
116                                 return FALSE;
117                 }
118                 WRITELOG((LogFile, "System initiated.\n"));
119         }
120         else return TRUE;
121
122         DDWnd = GetLibraryWindow();
123         _lpDD = lpdd;
124
125         atexit(DDKill);
126
127 //      Set cooperative mode
128         if (mode == DDGR_FULLSCREEN) {
129                 flags = DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE;
130
131         #ifndef NDEBUG
132                 if (!FindArg("-nomodex")) flags |= DDSCL_ALLOWMODEX;
133         #else
134                 flags |= DDSCL_ALLOWMODEX;
135         #endif
136
137                 if (!FindArg("-disallowreboot")) flags |= DDSCL_ALLOWREBOOT;
138  
139                 ddresult = IDirectDraw_SetCooperativeLevel(lpdd, DDWnd, flags); 
140
141                 if (!CheckDDResult(ddresult, "DDInit::SetCooperativeLevel")) {  
142                         IDirectDraw_Release(lpdd);
143                         return FALSE;
144                 }
145
146                 _DDFullScreen = TRUE;                   
147         }
148         else if (mode == DDGR_WINDOW) {
149                 ddresult = IDirectDraw_SetCooperativeLevel(lpdd, DDWnd,
150                                                                                 DDSCL_NORMAL);
151                 if (!CheckDDResult(ddresult, "DDInit::SetCooperativeLevel"))
152                         return FALSE;
153                 _DDFullScreen = FALSE;
154                 if (!DDInitClipper()) return FALSE;
155         }
156         else return FALSE;
157
158 // Perform Emulation test
159         DDEmulateTest();
160
161 //      Direct draw initialized.  Begin post-initialization
162         if (!DDEnumerateModes()) return FALSE;
163 //      DDSETDISPLAYMODE(SM95_640x480x8);
164 //      DDSetDisplayMode(W95DisplayMode, 0);
165
166         return TRUE;
167 }
168
169
170 void DDEmulateTest(void)
171 {
172 // Assume DirectDraw is init and we have exclusive access
173         HRESULT ddresult;
174         RECT rect;
175
176         DD_Emulation = 0;
177
178         if (FindArg("-emul")) {
179                 DD_Emulation = 1;
180                 return;
181         }
182
183         ddresult = IDirectDraw_SetDisplayMode(_lpDD, 640,480,8);
184         if (ddresult != DD_OK) {
185                 DD_Emulation = 1;
186                 return;
187         }
188         else {
189                 DDSURFACEDESC ddsd;
190                 LPDIRECTDRAWSURFACE lpdds;
191
192                 ZeroMemory(&ddsd, sizeof(ddsd));
193                 ddsd.dwSize = sizeof(ddsd);
194                 ddsd.dwFlags = DDSD_CAPS;
195                 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
196                                                         
197                 ddresult = IDirectDraw_CreateSurface(_lpDD, &ddsd, &lpdds, NULL);
198                 if (ddresult != DD_OK) {
199                         DD_Emulation = 1;
200                         return;
201                 }               
202
203         // Performing lock test!
204                 ZeroMemory(&ddsd, sizeof(ddsd));
205                 ddsd.dwSize = sizeof(ddsd);
206                 SetRect(&rect, 10,10,584,200);
207                 ddresult = IDirectDrawSurface_Lock(lpdds, &rect, &ddsd, DDLOCK_WAIT, NULL);
208                 if (ddresult != DD_OK) {
209                         IDirectDrawSurface_Release(lpdds);
210                         DD_Emulation = 1;
211                         return;
212                 }
213                 else {
214                         IDirectDrawSurface_Unlock(lpdds, ddsd.lpSurface);
215                         IDirectDrawSurface_Release(lpdds);
216                         DD_Emulation = 0;
217                 }
218                 
219         // Cleanup
220 //              IDirectDrawSurface_Unlock(lpdds, ddsd.lpSurface);
221 //              IDirectDrawSurface_Release(lpdds);
222         }
223 }
224
225         
226 BOOL DDEnumerateModes(void)
227 {
228         HRESULT ddresult;
229         int i;
230
231 //      Invalidate all modes
232         for (i = 0; i < 16; i++)
233         {
234                 _DDModeList[i].rw = _DDModeList[i].w = -1;
235                 _DDModeList[i].rh = _DDModeList[i].h = -1;
236         }
237
238 //      If we're full screen, enumerate modes.
239         if (_DDFullScreen) {
240                 ddresult = IDirectDraw_EnumDisplayModes(_lpDD, 0, NULL, 0, 
241                                                                         EnumDispModesCB);
242                 if(!CheckDDResult(ddresult, "DDInit::EnumDisplayModes")) {
243                         IDirectDraw_Release(_lpDD);
244                         return FALSE;
245                 }
246         }
247         else {
248                 _DDModeList[SM95_640x480x8].rw = 640;
249                 _DDModeList[SM95_640x480x8].rh = 480;
250                 _DDModeList[SM95_640x480x8].w = 640;
251                 _DDModeList[SM95_640x480x8].h = 480;
252                 _DDModeList[SM95_640x480x8].emul = 1;
253                 _DDModeList[SM95_640x480x8].dbuf = 0;
254                 _DDModeList[SM95_640x480x8].modex = 0;
255                 _DDModeList[SM95_640x480x8].paged = 0; 
256         }
257          
258         return TRUE;
259 }                               
260
261
262 BOOL DDInitClipper(void) 
263 {
264         return FALSE;
265 }
266
267
268 //      Destruction
269 //      ----------------------------------------------------------------------------
270
271 void DDKill(void)
272 {
273         DDKillScreen();
274
275 //      if (_lpDDPalette) IDirectDrawPalette_Release(_lpDDPalette);
276         if (_lpDDClipper) IDirectDrawClipper_Release(_lpDDClipper);
277         if (_lpDD) IDirectDraw_Release(_lpDD);
278
279         _DDFullScreen = FALSE;
280         _DDNumModes = _DDLockCounter = 0;
281         _lpDDClipper = NULL;
282         _lpDD = NULL;
283
284         WRITELOG((LogFile, "System closed.\n"));
285
286         if (LogFile) fclose(LogFile);
287 }
288
289
290 //      Screen functions
291 //      ----------------------------------------------------------------------------
292
293 void DDSetDisplayMode(int display_mode, int flags)
294 {
295         HRESULT ddresult;
296
297         W95DisplayMode = display_mode;
298
299         if (_DDFullScreen) {
300         // Change literal display mode of screen
301                 DDKillScreen();
302                 WRITELOG((LogFile, "Setting display mode to (%dx%dx%d).\n", GRMODEINFO(w), GRMODEINFO(h), GRMODEINFO(bpp)));            
303
304                 ddresult = IDirectDraw_SetDisplayMode(_lpDD, 
305                                                         _DDModeList[W95DisplayMode].w, 
306                                                         _DDModeList[W95DisplayMode].h,
307                                                         _DDModeList[W95DisplayMode].bpp);
308
309                 if (!CheckDDResult(ddresult, "DDInit::SetDisplayMode")) {
310                         Error("Unable to set display mode: %d [%dx%dx%d].( Err: %x ) \n", W95DisplayMode, _DDModeList[W95DisplayMode].w, 
311                                                         _DDModeList[W95DisplayMode].h,
312                                                         _DDModeList[W95DisplayMode].bpp,
313                                                         ddresult);
314                 }
315                 if (!DDCreateScreen()) exit(1);
316                 Sleep(1000);                    
317         }
318         else {
319                 Error("Windowed display modes not currently supported.");
320         }
321
322         W95OldDisplayMode = display_mode;
323 }
324
325
326 void DDResizeViewport()
327 {
328         RECT rect;
329         POINT p1, p2;
330
331         GetClientRect(GetLibraryWindow(), &rect);
332         p1.x = rect.left;
333         p1.y = rect.top;
334         p2.x = rect.right;
335         p2.y = rect.bottom; 
336         ClientToScreen(GetLibraryWindow(), &p1);
337         ClientToScreen(GetLibraryWindow(), &p2);
338
339         if (_DDFullScreen)  {
340                 p1.x = p1.y = 0;
341                 p2.x = _DDModeList[W95DisplayMode].w;
342                 p2.y = _DDModeList[W95DisplayMode].h;
343         }
344
345         ViewportRect.left = p1.x;
346         ViewportRect.top = p1.y;
347         ViewportRect.right = p2.x;
348         ViewportRect.bottom = p2.y;
349
350         mprintf((0, "New Viewport: [%d,%d,%d,%d]\n", p1.x, p1.y, p2.x, p2.y));
351 }
352
353
354 BOOL DDCreateScreen(void)
355 {
356         DDSCAPS                         ddscaps;
357         DDCAPS                          ddcaps, ddcaps2;
358         DDSURFACEDESC   ddsd;
359         HRESULT                         ddresult;
360
361 //      Determine capabilites of this display mode
362         memset(&ddcaps, 0, sizeof(ddcaps));
363         memset(&ddcaps2, 0, sizeof(ddcaps2));
364         ddcaps.dwSize = sizeof(ddcaps);
365         ddcaps2.dwSize = sizeof(ddcaps);
366
367         ddresult = IDirectDraw_GetCaps(_lpDD, &ddcaps, &ddcaps2);
368         if (!CheckDDResult(ddresult, "DDCreateScreen::GetCaps"))
369                 return FALSE;
370
371         WRITELOG((LogFile, "HAL: %8x\tHEL: %8x\n", ddcaps.dwCaps, ddcaps2.dwCaps));
372         WRITELOG((LogFile, "PAL: %8x\tDDS: %8x\n", ddcaps.dwPalCaps, ddcaps.ddsCaps.dwCaps));
373
374 //      This makes the game plenty faster (3 fps extra on Highres)      
375         ddDriverCaps.offscreen.sysmem = 1;
376
377         if (ddcaps.dwCaps       & DDCAPS_COLORKEYHWASSIST) {
378                 WRITELOG((LogFile, "Mode supports hardware colorkeying.\n"));
379                 ddDriverCaps.hwcolorkey = 1;
380         }
381         else ddDriverCaps.hwcolorkey = 0;
382
383         if (ddcaps.dwCaps & DDCAPS_BLTSTRETCH) {
384                 WRITELOG((LogFile, "Mode supports hardware blt stretching.\n"));
385                 ddDriverCaps.hwbltstretch = 1;
386         }
387         else ddDriverCaps.hwbltstretch = 0;
388
389
390 //      Create the screen surfaces
391         memset(&ddsd, 0, sizeof(ddsd));
392         ddsd.dwSize = sizeof(ddsd);
393         ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
394         _lpDDSBack = NULL;
395
396         if (GRMODEINFO(paged)) 
397         {
398         //      Create a flipping surface if we can
399
400                 ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
401                 ddsd.dwBackBufferCount = 1;
402                 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
403                                                         
404 //              ddsd.ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
405                 ddresult = IDirectDraw_CreateSurface(_lpDD, &ddsd, &_lpDDSPrimary, NULL);
406                 if (!CheckDDResult(ddresult, "DDCreateScreen::CreateSurface -paged"))
407                         return FALSE;
408         
409                 ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
410                 ddresult = IDirectDrawSurface_GetAttachedSurface(_lpDDSPrimary,
411                                                                                                         &ddscaps, &_lpDDSBack);
412                 if (!CheckDDResult(ddresult, "DDCreateScreen::GetAttachedSurface"))
413                         return FALSE;
414         }
415         else 
416         {
417         // Normal primary surface (non-emulated)
418                 ddsd.dwFlags = DDSD_CAPS;
419                 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
420 //              ddsd.ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
421                 ddresult = IDirectDraw_CreateSurface(_lpDD, &ddsd, &_lpDDSPrimary, NULL);
422                 if (!CheckDDResult(ddresult, "DDCreateScreen::CreateSurface"))
423                         return FALSE;
424         }
425         
426         if (GRMODEINFO(emul)) 
427         {
428         //      Create emulated 2nd page for window modes that don't let us render to the 
429         //      screen directly.
430                 _lpDDSBack = DDCreateSurface(_DDModeList[W95DisplayMode].rw, 
431                                                                                 _DDModeList[W95DisplayMode].rh, 1);
432                 if (!_lpDDSBack) {
433                         mprintf((0,"Call to create DDSBackBuffer failed."));
434                         return FALSE;
435                 }
436         }
437
438         if (GRMODEINFO(bpp) == 8) 
439         {
440         //      for 8-bit palettized modes, assert that we use the RGB pixel format.    
441         // Also create a base palette for this 8-bit mode.
442                 ubyte pal[768];
443                 memset(pal, 0, 768);
444                 
445                 memset(&ddsd, 0, sizeof(ddsd));
446                 ddsd.dwSize = sizeof(ddsd);
447                 IDirectDrawSurface_GetSurfaceDesc(_lpDDSPrimary, &ddsd);
448
449                 WRITELOG((LogFile, "Surface pixel format: %x, %d\n", ddsd.ddpfPixelFormat.dwFlags, ddsd.ddpfPixelFormat.dwRGBBitCount)); 
450
451                 if ((_lpDDPalette = DDCreatePalette(pal))!= NULL) 
452                         DDSetPalette(_lpDDPalette);
453                 else Error("Failed to create palette for screen.\n");
454         }
455
456         return TRUE;
457 }
458
459
460 void DDClearDisplay();
461
462 void DDKillScreen()
463 {
464         WRITELOG((LogFile, "Killing display mode (%dx%dx%d).\n", _DDModeList[W95OldDisplayMode].w, _DDModeList[W95OldDisplayMode].h, _DDModeList[W95OldDisplayMode].bpp));
465
466 //      if (_lpDDPalette) IDirectDrawPalette_Release(_lpDDPalette);
467         if (_lpDDSBack && !GRMODEINFO(paged)) IDirectDrawSurface_Release(_lpDDSBack);
468         if (_lpDDSPrimary) {
469
470                 if (!GRMODEINFO(modex)) {
471                         DDClearDisplay();
472                 }
473
474                 IDirectDrawSurface_Release(_lpDDSPrimary);
475  
476         }
477
478         _lpDDPalette = NULL;
479         _lpDDSBack = NULL;
480         _lpDDSPrimary = NULL;
481 }
482
483
484 void DDClearDisplay()
485 {
486         DDBLTFX ddbltfx;
487         HRESULT ddresult;
488
489         memset(&ddbltfx, 0, sizeof(DDBLTFX));
490         ddbltfx.dwSize = sizeof( ddbltfx );
491         ddbltfx.dwFillColor = (WORD)(BM_XRGB(0,0,0));
492
493         ddresult = IDirectDrawSurface_Blt(
494                      _lpDDSPrimary,                     // dest surface
495                      NULL,                      // dest rect
496                      NULL,                  // src surface
497                      NULL,                  // src rect
498                      DDBLT_COLORFILL | DDBLT_WAIT,
499                      &ddbltfx);
500 }
501
502
503 void DDFlip()
504 {
505         HRESULT ddresult;
506
507         if (IDirectDrawSurface_GetFlipStatus(_lpDDSBack, DDGFS_ISFLIPDONE) == DDERR_WASSTILLDRAWING) return;
508
509         ddresult = IDirectDrawSurface_Flip(_lpDDSPrimary, NULL, DDFLIP_WAIT);
510         if (ddresult != DD_OK) {
511                 WRITELOG((LogFile, "DDFlip:: Unable to flip screen (%X)\n", ddresult));
512                 Int3();                                                                 // Bad flipping
513         }
514 }
515
516
517
518 //      DirectDrawSurface Routines
519 //      ----------------------------------------------------------------------------
520
521 LPDIRECTDRAWSURFACE DDCreateSurface(int width, int height, BOOL vram)
522 {
523         DDSURFACEDESC ddsd;
524         HRESULT ddresult;
525         LPDIRECTDRAWSURFACE lpdds;
526
527         if (ddDriverCaps.offscreen.sysmem && !vram) 
528                 return DDCreateSysMemSurface(width, height);
529
530         memset(&ddsd, 0, sizeof(ddsd));
531         ddsd.dwSize = sizeof(ddsd);
532         ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
533         ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
534         ddsd.dwWidth = width;
535         ddsd.dwHeight = height;
536
537         ddresult = IDirectDraw_CreateSurface(_lpDD, &ddsd, &lpdds, NULL);
538         if (ddresult != DD_OK) {
539                 WRITELOG((LogFile, "CreateSurface err: %x\n", ddresult));
540                 return NULL;
541         }
542
543         return lpdds;
544 }
545
546
547 LPDIRECTDRAWSURFACE DDCreateSysMemSurface(int width, int height)
548 {
549         DDSURFACEDESC ddsd;
550         HRESULT ddresult;
551         LPDIRECTDRAWSURFACE lpdds;
552
553         memset(&ddsd, 0, sizeof(ddsd));
554         ddsd.dwSize = sizeof(ddsd);
555         ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
556         ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
557         ddsd.dwWidth = width;
558         ddsd.dwHeight = height;
559
560         ddresult = IDirectDraw_CreateSurface(_lpDD, &ddsd, &lpdds, NULL);
561         if (ddresult != DD_OK) {
562                 logentry("DDRAW::CreateSysMemSurface err: %x\n", ddresult);             
563                 return NULL;
564         }
565
566         return lpdds;
567 }
568
569
570 void DDFreeSurface(LPDIRECTDRAWSURFACE lpdds)
571 {
572         HRESULT ddresult;
573
574         Assert(lpdds != NULL);
575
576         ddresult = IDirectDrawSurface_Release(lpdds);
577         if (ddresult != DD_OK) {
578                 Error("DDFreeSurface: Unable to free surface: err %x", ddresult);
579         }
580 }
581
582
583 BOOL DDRestoreSurface(LPDIRECTDRAWSURFACE lpdds)
584 {
585         HRESULT ddresult;
586         
587         Assert(lpdds != NULL);
588         if (IDirectDrawSurface_IsLost(lpdds) == DD_OK) return TRUE;     
589         ddresult = IDirectDrawSurface_Restore(lpdds);
590         if (ddresult != DD_OK) 
591                 return FALSE;
592
593         return TRUE;
594 }
595
596
597
598 //      Locking and Unlocking of DD Surfaces
599
600 ubyte *DDLockSurface(LPDIRECTDRAWSURFACE lpdds, RECT *rect, int *pitch )
601 {
602         HRESULT ddresult;
603         DDSURFACEDESC ddsd;
604         int try_count = 0;
605
606         memset(&ddsd, 0, sizeof(ddsd));
607         ddsd.dwSize = sizeof(ddsd);
608
609 RetryLock:
610
611         ddresult = IDirectDrawSurface_Lock(lpdds, rect, &ddsd, DDLOCK_WAIT, NULL);
612
613         if (ddresult != DD_OK) 
614         {
615                 if (ddresult == DDERR_SURFACELOST) {
616                         if (!DDRestoreSurface(lpdds) || try_count) {
617                                 WRITELOG((LogFile, "Unable to restore surface for lock.\n"));
618                                 return NULL;
619                         }
620                         else {                                                   
621                                 try_count++;
622                                 goto RetryLock;
623                         }
624                 }
625                 else {
626                         WRITELOG((LogFile, "Lock error: %x.\n", ddresult));
627                         return NULL;
628                 }
629         }
630         
631         _DDLockCounter++;
632                         
633         *pitch = (int)ddsd.lPitch;
634         return (ubyte *)ddsd.lpSurface; 
635 }
636
637
638 void DDUnlockSurface(LPDIRECTDRAWSURFACE lpdds, char *data)
639 {
640         HRESULT ddresult;
641         
642         if (_DDLockCounter < 1) return;
643
644         ddresult = IDirectDrawSurface_Unlock(lpdds, data);
645         if (ddresult != DD_OK) {        
646                 Error("Unable to unlock canvas: %x\n", ddresult);
647         }
648
649         _DDLockCounter--;
650 }
651
652
653
654 //      DirectDrawPalette Utilities
655 //      ----------------------------------------------------------------------------
656
657 LPDIRECTDRAWPALETTE DDGetPalette(LPDIRECTDRAWSURFACE lpdds)
658 {
659         HRESULT ddresult;
660         LPDIRECTDRAWPALETTE lpddp;
661
662         ddresult = IDirectDrawSurface_GetPalette(lpdds, &lpddp);
663         if (ddresult != DD_OK) {
664                 mprintf((1, "DDERR: GetPalette %x.\n", ddresult));
665                 return NULL;
666         }
667         return lpddp;
668 }
669         
670
671 LPDIRECTDRAWPALETTE DDCreatePalette(ubyte *pal)
672 {
673         HRESULT ddresult;
674         LPDIRECTDRAWPALETTE lpddpal;
675         PALETTEENTRY pe[256];
676         int i;
677
678         for (i = 0; i < 256; i++)
679         {
680                 pe[i].peRed = pal[i*3];
681                 pe[i].peGreen = pal[i*3+1];
682                 pe[i].peBlue = pal[i*3+2];
683                 pe[i].peFlags = 0;
684         }
685
686         ddresult = IDirectDraw_CreatePalette(_lpDD, 
687                                                                 DDPCAPS_8BIT | DDPCAPS_ALLOW256 | DDPCAPS_INITIALIZE, 
688                                                                 pe, 
689                                                                 &lpddpal, NULL);
690         if (ddresult != DD_OK) {
691                 mprintf((1, "DDERR: CreatePalette %x.\n", ddresult));
692                 return NULL;
693         }
694         
695         return lpddpal;
696 }
697
698
699 void DDSetPalette(LPDIRECTDRAWPALETTE lpDDPal)
700 {
701         HRESULT ddresult;
702
703         ddresult = IDirectDrawSurface_SetPalette(_lpDDSPrimary, lpDDPal);
704         if (ddresult != DD_OK) {
705                 if (ddresult == DDERR_SURFACELOST) {
706                         IDirectDrawSurface_Restore(_lpDDSPrimary);
707                         IDirectDrawSurface_SetPalette(_lpDDSPrimary, lpDDPal);
708                 }
709                 else {
710                         Error("This driver requires you to set your desktop\n to 256 color mode before running Descent II.");
711                 }
712         }
713 }
714
715
716
717 //      Utilities
718 //      ----------------------------------------------------------------------------
719
720 int DDCheckMode(int mode)
721 {
722         if (_DDModeList[mode].w==-1 && _DDModeList[mode].h==-1) return 1;
723         else return 0;
724 }
725
726
727 BOOL CheckDDResult(HRESULT ddresult, char *funcname)
728 {
729         char buf[256];
730
731         if (ddresult != DD_OK) {
732                 sprintf(buf, "DirectDraw error %x detected in\r\n\t%s\n", ddresult, funcname);
733                 WRITELOG((LogFile, buf));
734                 MessageBox(NULL, buf, "DESCENT2::DDRAW", MB_OK);
735                 return FALSE;
736         }
737         else return TRUE;
738 }
739
740
741
742 //      EnumDispModesCB
743 //      ----------------------------------------------------------------------------
744 HRESULT CALLBACK EnumDispModesCB(LPDDSURFACEDESC lpddsd, LPVOID context)
745 {
746         DWORD width, height,bpp;
747         int mode;
748         DWORD modex;    
749
750         width = lpddsd->dwWidth;
751         height = lpddsd->dwHeight;
752         bpp = lpddsd->ddpfPixelFormat.dwRGBBitCount;
753         modex = lpddsd->ddsCaps.dwCaps;
754
755         modex = modex & DDSCAPS_MODEX;
756
757         if (width == 640 && height == 480 && bpp==8)   
758                 mode = SM95_640x480x8;
759         else if (width == 640 && height == 400 && bpp==8)
760                 mode = SM95_640x400x8;
761         else if (width == 320 && height == 200 && bpp==8) {
762                 mode = SM95_320x200x8X;
763                 if (DD_Emulation) return DDENUMRET_OK;
764         }
765         else if (width == 800 && height == 600 && bpp==8) 
766                 mode = SM95_800x600x8;
767         else if (width == 1024 && height == 768 && bpp==8)
768                 mode = SM95_1024x768x8;
769         else
770                 return DDENUMRET_OK;
771
772         _DDModeList[mode].rw            = width;
773         _DDModeList[mode].rh            = height;
774         _DDModeList[mode].emul          = 0;
775         _DDModeList[mode].modex         = 0;
776         _DDModeList[mode].paged         = 0;
777         _DDModeList[mode].dbuf          = 0;
778    _DDModeList[mode].w                  = width;
779    _DDModeList[mode].h                  = height;
780    _DDModeList[mode].bpp                = bpp;
781
782         if (mode == SM95_320x200x8X) {
783                 _DDModeList[mode].modex = 1;
784                 _DDModeList[mode].dbuf = 1;
785                 _DDModeList[mode].paged = 1;
786         }
787         else _DDModeList[mode].dbuf = 1;
788
789         if (DD_Emulation) _DDModeList[mode].emul = 1;
790
791    _DDNumModes++;
792
793         WRITELOG((LogFile, "Register mode (%dx%dx%d) (paged=%d) (dbuf=%d).\n", width, height, bpp, _DDModeList[mode].paged, _DDModeList[mode].dbuf));   
794
795    return DDENUMRET_OK;
796 }