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