]> icculus.org git repositories - btb/d2x.git/blob - unused/win95/ddraw.c
use the orientation parameter of g3_draw_bitmap
[btb/d2x.git] / unused / win95 / ddraw.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 #define WIN95
17 #define _WIN32
18 #define WIN32_LEAN_AND_MEAN
19 #include <windows.h>
20 #include "win\ddraw.h"
21
22 #include <stdio.h>
23 #include <mem.h>
24
25 #include "gr.h"
26 #include "mono.h"
27 #include "dxxerror.h"
28 #include "winapp.h"
29 #include "dd.h"
30 #include "args.h"
31
32
33 //      Direct X Variables ---------------------------------------------------------
34
35 LPDIRECTDRAW                    _lpDD=0;                                // Direct Draw Object
36 LPDIRECTDRAWSURFACE     _lpDDSPrimary=0;        // Primary Display Screen (Page 1)
37 LPDIRECTDRAWSURFACE     _lpDDSBack=0;           // Page 2 or offscreen canvas
38 LPDIRECTDRAWCLIPPER     _lpDDClipper=0; // Window Clipper Object
39 LPDIRECTDRAWPALETTE     _lpDDPalette=0; // Direct Draw Palette;
40 DDMODEINFO                              _DDModeList[16];        // Mode list for Exclusive mode.
41 int                                             _DDNumModes = 0;        // Number of display modes
42 BOOL                                            _DDFullScreen;          // Full Screen DD mode?
43 BOOL                                            _DDExclusive;           // Exclusive mode?
44 BOOL                                            _DDSysMemSurfacing=TRUE;
45 int                                             W95DisplayMode; // Display mode.
46 int                                             W95OldDisplayMode;
47
48 dd_caps                                 ddDriverCaps;           // Driver Caps.
49
50 int                                             _DDFlags=0;                     // Direct Draw Flags
51 int                                             _DDLockCounter=0;       // DirectDraw Lock Surface counter
52
53 static BOOL                             DDUseEmulation=FALSE;
54 static HWND                             DDWnd=NULL;
55
56 static int                              DDVideoLocks = 0;
57 static int                              DDSystemLocks = 0;
58
59 //      Function prototypes --------------------------------------------------------
60
61 HRESULT CALLBACK EnumDispModesCB(LPDDSURFACEDESC lpddsd, LPVOID context);
62 BOOL CheckDDResult(HRESULT ddresult, char *funcname);
63 BOOL DDRestoreCanvas(dd_grs_canvas *canvas);
64
65
66 //      Direct Draw Initialization
67 // ----------------------------------------------------------------------------
68
69 BOOL DDInit(int mode)
70 {
71         LPDIRECTDRAW lpdd;
72         DDCAPS ddcaps, ddcaps2;
73         HRESULT ddresult;
74         int num;
75
76         DDWnd = GetLibraryWindow();
77
78 //      Create Direct Draw Object (Use Emulation if Hardware is off)
79         if (!_lpDD)     {
80                 ddresult = DirectDrawCreate(NULL, &lpdd, NULL);
81                 
82                 if (ddresult == DDERR_NODIRECTDRAWHW) {
83          ddresult = DirectDrawCreate( (LPVOID) DDCREATE_EMULATIONONLY, &lpdd, NULL );
84                         if (!CheckDDResult(ddresult, "InitDD:DirectDrawCreate emulation"))
85                                 return FALSE;
86                         DDUseEmulation = TRUE;
87                         logentry("DirectDraw: forcing emulation.\n");
88                 }
89                 else if (ddresult != DD_OK) return FALSE;
90                 logentry("DirectDraw: DirectX API hardware compliant.\n");
91         }
92         else return FALSE;
93
94         atexit(DDKill);
95
96 //      Determine hardware caps
97 //      Determine capture mode (fullscreen takes exclusive, window is normal)
98         if (mode == DDGR_FULLSCREEN) {
99                 DWORD flags;
100
101                 flags = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN;
102
103         #ifndef NDEBUG
104                 if (!FindArg("-nomodex")) flags |= DDSCL_ALLOWMODEX;
105         #else
106                 flags |= DDSCL_ALLOWMODEX;
107         #endif
108
109                 if (!FindArg("-disallowreboot")) flags |= DDSCL_ALLOWREBOOT;
110  
111                 ddresult = IDirectDraw_SetCooperativeLevel(lpdd, DDWnd, flags); 
112
113                 if (!CheckDDResult(ddresult, "DDInit::SetCooperativeLevel")) {  
114                         IDirectDraw_Release(lpdd);
115                         return FALSE;
116                 }
117
118                 _DDExclusive = TRUE;
119                 _DDFullScreen = TRUE;                   
120         }
121         else if (mode == DDGR_EXWINDOW) {
122                 ddresult = IDirectDraw_SetCooperativeLevel(lpdd, DDWnd,
123                                                                                 DDSCL_EXCLUSIVE |
124                                                                                 DDSCL_FULLSCREEN);
125                 if (!CheckDDResult(ddresult, "DDInit::SetCooperativeLevel"))
126                         return FALSE;
127                 _DDExclusive = TRUE;
128                 _DDFullScreen = FALSE;
129         }
130         else if (mode == DDGR_WINDOW) {
131                 ddresult = IDirectDraw_SetCooperativeLevel(lpdd, DDWnd,
132                                                                                 DDSCL_NORMAL);
133                 if (!CheckDDResult(ddresult, "DDInit::SetCooperativeLevel"))
134                         return FALSE;
135                 _DDExclusive = FALSE;
136                 _DDFullScreen = FALSE;
137         }
138         else return FALSE;
139         
140 //      Get Display modes/Window Sizes
141 //      Force invalidation of all modes for now
142         for (num = 0; num < 16; num++)
143         {
144                 _DDModeList[num].rw = _DDModeList[num].w = -1;
145                 _DDModeList[num].rh = _DDModeList[num].h = -1;
146         }
147
148         W95DisplayMode = SM95_640x480x8;
149         num = 0;
150         if (mode == DDGR_FULLSCREEN) {
151                 ddresult = IDirectDraw_EnumDisplayModes(lpdd, 0, NULL, 0, 
152                                                                         EnumDispModesCB);
153                 if(!CheckDDResult(ddresult, "DDInit::EnumDisplayModes")) {
154                         IDirectDraw_Release(lpdd);
155                         return FALSE;
156                 }
157         }
158         else if (mode == DDGR_EXWINDOW) {
159                 _DDModeList[SM95_320x200x8X].rw = 320;
160                 _DDModeList[SM95_320x200x8X].rh = 200;
161                 _DDModeList[SM95_320x200x8X].w = 640;
162                 _DDModeList[SM95_320x200x8X].h = 480;
163                 _DDModeList[SM95_320x200x8X].emul = 1;
164                 _DDModeList[SM95_320x200x8X].dbuf = 0;
165                 _DDModeList[SM95_320x200x8X].modex = 0;
166                 _DDModeList[SM95_320x200x8X].paged = 0; 
167
168                 _DDModeList[SM95_640x480x8].rw = 640;
169                 _DDModeList[SM95_640x480x8].rh = 480;
170                 _DDModeList[SM95_640x480x8].w = 640;
171                 _DDModeList[SM95_640x480x8].h = 480;
172                 _DDModeList[SM95_640x480x8].emul = 1;
173                 _DDModeList[SM95_640x480x8].dbuf = 0;
174                 _DDModeList[SM95_640x480x8].modex = 0;
175                 _DDModeList[SM95_640x480x8].paged = 0; 
176
177                 _DDModeList[SM95_800x600x8].rw = 800;
178                 _DDModeList[SM95_800x600x8].rh = 600;
179                 _DDModeList[SM95_800x600x8].w = 640;
180                 _DDModeList[SM95_800x600x8].h = 480;
181                 _DDModeList[SM95_800x600x8].emul = 1;
182                 _DDModeList[SM95_800x600x8].dbuf = 0;
183                 _DDModeList[SM95_800x600x8].modex = 0;
184                 _DDModeList[SM95_800x600x8].paged = 0; 
185                 _DDNumModes = 3;
186         }
187         else if (mode == DDGR_WINDOW) { 
188                 _DDModeList[SM95_320x200x8X].rw = 320;
189                 _DDModeList[SM95_320x200x8X].rh = 200;
190                 _DDModeList[SM95_320x200x8X].w = 640;
191                 _DDModeList[SM95_320x200x8X].h = 480;
192                 _DDModeList[SM95_320x200x8X].emul = 1;
193                 _DDModeList[SM95_320x200x8X].dbuf = 0;
194                 _DDModeList[SM95_320x200x8X].modex = 0;
195                 _DDModeList[SM95_320x200x8X].paged = 0; 
196
197                 _DDModeList[SM95_640x480x8].rw = 640;
198                 _DDModeList[SM95_640x480x8].rh = 480;
199                 _DDModeList[SM95_640x480x8].w = 640;
200                 _DDModeList[SM95_640x480x8].h = 480;
201                 _DDModeList[SM95_640x480x8].emul = 1;
202                 _DDModeList[SM95_640x480x8].dbuf = 0;
203                 _DDModeList[SM95_640x480x8].modex = 0;
204                 _DDModeList[SM95_640x480x8].paged = 0; 
205
206                 _DDModeList[SM95_800x600x8].rw = 800;
207                 _DDModeList[SM95_800x600x8].rh = 600;
208                 _DDModeList[SM95_800x600x8].w = 800;
209                 _DDModeList[SM95_800x600x8].h = 600;
210                 _DDModeList[SM95_800x600x8].emul = 1;
211                 _DDModeList[SM95_800x600x8].dbuf = 0;
212                 _DDModeList[SM95_800x600x8].modex = 0;
213                 _DDModeList[SM95_800x600x8].paged = 0; 
214                 _DDNumModes = 3;
215         }
216         else return FALSE;
217
218 //      Set appropriate display mode or window mode
219
220         _lpDD = lpdd;
221
222         memset(&ddcaps, 0, sizeof(ddcaps));
223         ddcaps.dwSize = sizeof(ddcaps);
224         ddcaps2.dwSize = sizeof(ddcaps);
225         ddresult = IDirectDraw_GetCaps(_lpDD, &ddcaps, NULL);
226         if (!CheckDDResult(ddresult, "InitDD::GetCaps")) 
227                 return FALSE;
228
229         logentry("DirectDraw: VRAM free:  %d\n", ddcaps.dwVidMemFree);  
230         logentry("DirectDraw: VRAM total: %d\n", ddcaps.dwVidMemTotal);
231
232 #ifndef NDEBUG
233         if (FindArg("-TsengDebug1")) {
234                 IDirectDraw_Release(lpdd);
235                 return FALSE;
236         }
237 #endif
238
239         DDSetDisplayMode(W95DisplayMode, 0);
240
241 #ifndef NDEBUG
242         if (FindArg("-TsengDebug2")) {
243                 IDirectDraw_Release(lpdd);
244                 return FALSE;
245         }
246 #endif
247         
248         // If 'windowed' do this.
249         if (!_DDFullScreen) 
250         {
251                         ddresult = IDirectDraw_CreateClipper(_lpDD, 0, &_lpDDClipper, NULL);
252                         if (!CheckDDResult(ddresult, "DDCreateScreen::CreateClipper"))
253                                 return FALSE;
254
255                         ddresult = IDirectDrawClipper_SetHWnd(_lpDDClipper, 0, DDWnd);
256                         if (!CheckDDResult(ddresult, "DDCreateScreen::SetHWnd"))
257                                 return FALSE;
258
259                         ddresult = IDirectDrawSurface_SetClipper(_lpDDSPrimary, _lpDDClipper);
260                         if (!CheckDDResult(ddresult, "DDCreateScreen::SetClipper"))
261                                 return FALSE;
262         }
263
264 //      Register Optimizations
265
266         ddcaps.dwSize = sizeof(ddcaps);
267         ddcaps2.dwSize = sizeof(ddcaps);
268         ddresult = IDirectDraw_GetCaps(lpdd, &ddcaps, &ddcaps2);
269         if (!CheckDDResult(ddresult, "DDInit::GetCaps"))
270                 return FALSE;
271
272 #ifndef NDEBUG
273         if (FindArg("-TsengDebug3")) {
274                 IDirectDraw_Release(lpdd);
275                 return FALSE;
276         }
277 #endif
278
279         if (FindArg("-vidram")) {
280                 logentry("DirectDraw: Forcing VRAM rendering.\n");
281                 _DDSysMemSurfacing = FALSE;
282         }
283         else if (FindArg("-sysram")) {
284                 logentry("DirectDraw: Forcing SRAM rendering.\n");
285                 _DDSysMemSurfacing = TRUE;
286         }
287         else if (ddcaps.dwCaps & DDCAPS_BANKSWITCHED) {
288                 logentry("DirectDraw: Hardware is bank-switched.  Using SRAM rendering.\n");
289                 _DDSysMemSurfacing = TRUE;
290         }
291         else {
292                 logentry("DirectDraw: Hardware is not bank-switched.  Using VRAM rendering.\n");
293                 _DDSysMemSurfacing = FALSE;
294         }
295                 
296         if (ddcaps.dwCaps       & DDCAPS_COLORKEYHWASSIST) 
297                 ddDriverCaps.hwcolorkey = 1;
298         else 
299                 ddDriverCaps.hwcolorkey = 0;
300         if (ddcaps.dwCaps & DDCAPS_BLTSTRETCH)
301                 ddDriverCaps.hwbltstretch = 1;
302         else 
303                 ddDriverCaps.hwbltstretch = 0;
304                 
305
306 //@@    mprintf((0, "DD::Hardware="));
307 //@@    if (ddcaps.dwCaps & DDCAPS_NOHARDWARE) mprintf((0, "Off\n"));
308 //@@    else mprintf((0, "On\n"));
309 //@@
310 //@@    mprintf((0, "DD::VideoMem=%u bytes\n", ddcaps.dwVidMemTotal));
311
312 //@@    mprintf((0, "DD::SrcColorKey="));       
313 //@@    if (ddcaps.dwCKeyCaps & DDCKEYCAPS_SRCBLT) mprintf((0, "Hardware\n"));
314 //@@    else mprintf((0, "Emulation\n"));
315
316         return TRUE;
317 }
318
319
320 //      Direct Draw Destruction
321 // ----------------------------------------------------------------------------
322
323 void DDKill()
324 {
325 //      Perform cleanup for full screen case and window case
326         DDKillScreen();
327         if (_lpDDPalette) IDirectDrawPalette_Release(_lpDDPalette);
328         if (_lpDD) IDirectDraw_Release(_lpDD);
329
330         _DDExclusive = _DDFullScreen = FALSE;
331         _DDNumModes = 0;
332         _DDLockCounter = 0;
333         _lpDD = NULL;
334 }
335
336
337 //      Direct Draw Surface Creation
338 //              Create Screen (Page 0 and possibly Page 1 or offscreen buffer)
339 // ----------------------------------------------------------------------------
340
341 BOOL DDCreateScreen(int flags)
342 {
343         DDSCAPS ddscaps;
344         DDCAPS ddcaps, ddcaps2;
345         DDSURFACEDESC ddsd;
346         HRESULT ddresult;
347
348         memset(&ddcaps, 0, sizeof(ddcaps));
349         memset(&ddcaps2, 0, sizeof(ddcaps2));
350         ddcaps.dwSize = sizeof(ddcaps);
351         ddcaps2.dwSize = sizeof(ddcaps);
352         ddresult = IDirectDraw_GetCaps(_lpDD, &ddcaps, &ddcaps2);
353         if (!CheckDDResult(ddresult, "DDCreateScreen::GetCaps"))
354                 return FALSE;
355
356
357         logentry("DirectDraw HW Caps:  %x\nDirectDraw HEL Caps: %x\n",ddcaps.dwCaps,ddcaps2.dwCaps);
358         if (ddcaps.dwCaps & DDCAPS_BANKSWITCHED) {
359                 logentry("DirectDraw: Hardware is bank-switched.  Using SRAM rendering.\n");
360                 _DDSysMemSurfacing = TRUE;
361         }
362         else {
363                 logentry("DirectDraw: Hardware is not bank-switched.  Using VRAM rendering.\n");
364                 _DDSysMemSurfacing = FALSE;
365         }
366
367 //      Determine GFX caps.
368         if (ddcaps.dwCaps       & DDCAPS_COLORKEYHWASSIST) 
369                 ddDriverCaps.hwcolorkey = 1;
370         else 
371                 ddDriverCaps.hwcolorkey = 0;
372         if (ddcaps.dwCaps & DDCAPS_BLTSTRETCH)
373                 ddDriverCaps.hwbltstretch = 1;
374         else 
375                 ddDriverCaps.hwbltstretch = 0;
376         
377         memset(&ddsd, 0, sizeof(ddsd));
378         ddsd.dwSize = sizeof(ddsd);
379
380         if (_DDFullScreen && GRMODEINFO(paged)) {
381         //      We should use page flipping
382                 ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
383                 ddsd.dwBackBufferCount = 1;
384                 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
385                                                                                 DDSCAPS_FLIP |
386                                                                                 DDSCAPS_COMPLEX;
387                 ddresult = IDirectDraw_CreateSurface(_lpDD, &ddsd, &_lpDDSPrimary, NULL);
388                 if (!CheckDDResult(ddresult, "DDCreateScreen::CreateSurface -fullscreen"))
389                         return FALSE;
390                         
391                 ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
392                 ddresult = IDirectDrawSurface_GetAttachedSurface(_lpDDSPrimary,
393                                                                                                         &ddscaps, &_lpDDSBack);
394                 if (!CheckDDResult(ddresult, "DDCreateScreen::GetAttachedSurface"))
395                         return FALSE;
396         }
397         else {
398         // We just create a primary and offscreen buffer
399                 if (GRMODEINFO(emul) && !_lpDDSPrimary) {
400                 // make sure we don't reinitialize the screen if we already made it
401                 //      beforehand for windowed version
402                         ddsd.dwFlags = DDSD_CAPS;
403                         ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
404                         ddresult = IDirectDraw_CreateSurface(_lpDD, &ddsd, &_lpDDSPrimary, NULL);
405                         if (!CheckDDResult(ddresult, "DDCreateScreen::CreateSurface -windowed"))
406                                 return FALSE;
407                 }
408                 else if (!GRMODEINFO(emul)) {
409                 // If we aren't emulating
410                         ddsd.dwFlags = DDSD_CAPS;
411                         ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
412                         ddresult = IDirectDraw_CreateSurface(_lpDD, &ddsd, &_lpDDSPrimary, NULL);
413                         if (!CheckDDResult(ddresult, "DDCreateScreen::CreateSurface -windowed"))
414                                 return FALSE;
415                 }
416
417                 if (GRMODEINFO(emul)) {
418                         _lpDDSBack = DDCreateSurface(_DDModeList[W95DisplayMode].rw, 
419                                                                                 _DDModeList[W95DisplayMode].rh, 1);
420                         if (!_lpDDSBack) {
421                                 mprintf((0,"Call to create DDSBackBuffer failed."));
422                                 return FALSE;
423                         }
424                 }
425                 else _lpDDSBack = NULL; 
426         
427         }
428
429 //      Create 8-bit palette
430         {
431                 ubyte pal[768];
432                 memset(pal, 0, 768);
433                 
434                 memset(&ddsd, 0, sizeof(ddsd));
435                 ddsd.dwSize = sizeof(ddsd);
436                 IDirectDrawSurface_GetSurfaceDesc(_lpDDSPrimary, &ddsd);
437
438                 logentry("Primary surface pixel format: %x, %d\n", ddsd.ddpfPixelFormat.dwFlags, ddsd.ddpfPixelFormat.dwRGBBitCount); 
439
440                 _lpDDPalette = DDCreatePalette(pal);
441                 Assert(_lpDDPalette != NULL);
442                 DDSetPalette(_lpDDPalette);
443         }
444
445         return TRUE;
446 }
447
448
449 //      DirectDraw Screen Kill
450 //      ----------------------------------------------------------------------------
451
452 void DDKillScreen()
453 {
454         if (_lpDDClipper) IDirectDrawClipper_Release(_lpDDClipper);
455         if (_lpDDPalette) IDirectDrawPalette_Release(_lpDDPalette);
456         if (_lpDDSBack) IDirectDrawSurface_Release(_lpDDSBack);
457         if (_lpDDSPrimary) {
458
459                 if (!GRMODEINFO(modex)) {
460                         DDBLTFX ddbltfx;
461                         HRESULT ddresult;
462
463                         memset(&ddbltfx, 0, sizeof(DDBLTFX));
464                 ddbltfx.dwSize = sizeof( ddbltfx );
465                    ddbltfx.dwFillColor = (WORD)(BM_XRGB(0,0,0));
466
467                 ddresult = IDirectDrawSurface_Blt(
468                             _lpDDSPrimary,                      // dest surface
469                             NULL,                       // dest rect
470                             NULL,                  // src surface
471                             NULL,                  // src rect
472                             DDBLT_COLORFILL | DDBLT_WAIT,
473                             &ddbltfx);
474                 }
475
476                 IDirectDrawSurface_Release(_lpDDSPrimary);
477         }
478
479         _lpDDClipper = NULL;
480         _lpDDPalette = NULL;
481         _lpDDSBack = NULL;
482         _lpDDSPrimary = NULL;
483 }       
484
485
486 void DDKillEmulatedScreen()
487 {
488         if (_lpDDSBack) IDirectDrawSurface_Release(_lpDDSBack);
489
490         _lpDDSBack = NULL;
491 }
492
493
494 //      DDSetDisplayMode
495 //      ----------------------------------------------------------------------------
496
497 void DDSetDisplayMode(int display_mode, int flags)
498 {
499         HRESULT ddresult;
500
501         W95DisplayMode = display_mode;
502         W95OldDisplayMode = display_mode;
503         if (_DDFullScreen) {
504                 logentry("Setting screen display mode to (%dx%dx%d::%dx%dx%d).\n", _DDModeList[W95DisplayMode].w, _DDModeList[W95DisplayMode].h,        _DDModeList[W95DisplayMode].bpp,_DDModeList[W95DisplayMode].rw, _DDModeList[W95DisplayMode].rh, _DDModeList[W95DisplayMode].bpp);
505         
506                 DDKillScreen();
507                 ddresult = IDirectDraw_SetDisplayMode(_lpDD, _DDModeList[W95DisplayMode].w,
508                                                                                 _DDModeList[W95DisplayMode].h,
509                                                                                 _DDModeList[W95DisplayMode].bpp);
510                 if (!CheckDDResult(ddresult, "DDInit::SetDisplayMode")) {
511                         Error("Unable to set display mode: %d.\n", W95DisplayMode);
512                 }
513                 DDCreateScreen(flags);
514         }
515         else {
516                 RECT rect;
517                 DWORD dwStyle;
518
519                 DDKillEmulatedScreen();
520
521                 dwStyle = GetWindowLong(DDWnd, GWL_STYLE);
522                 dwStyle &= ~WS_POPUP;
523                 dwStyle |= WS_OVERLAPPED | WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX;
524
525                 SetRect(&rect, 0, 0, _DDModeList[W95DisplayMode].w,
526                                 _DDModeList[W95DisplayMode].h); 
527                 SetWindowLong(DDWnd, GWL_STYLE, dwStyle);
528                 AdjustWindowRectEx(&rect, 
529                                                 GetWindowLong(DDWnd, GWL_STYLE),
530                                                 GetMenu(DDWnd)!=NULL,
531                                                 GetWindowLong(DDWnd, GWL_EXSTYLE));
532
533                 SetWindowPos(DDWnd, NULL, 0,0,
534                                         rect.right-rect.left,
535                                         rect.bottom-rect.top,
536                                 SWP_NOMOVE | 
537                                 SWP_NOZORDER | 
538                                 SWP_NOACTIVATE);
539                 SetWindowPos(DDWnd, HWND_NOTOPMOST, 0, 0, 0, 0, 
540                                 SWP_NOSIZE |
541                                 SWP_NOMOVE |
542                                 SWP_NOACTIVATE);
543
544                 DDCreateScreen(flags);
545         }
546 }
547
548
549 //      DDRestoreScreen
550 //              Restore screens 
551 //      ----------------------------------------------------------------------------
552 int DDRestoreScreen()
553 {
554         mprintf((1, "Need to Restore DDraw Page0 and Page1.\n"));
555         if (!_lpDDSPrimary || IDirectDrawSurface_Restore(_lpDDSPrimary) !=DD_OK) {
556                 mprintf((1, "Warning: Unable to restore Primary Surface.\n"));
557                 return 0;
558         }
559         if (!GRMODEINFO(paged) && _lpDDSBack) {
560                 if (IDirectDrawSurface_Restore(_lpDDSBack) != DD_OK) {
561                         mprintf((1, "Warning: Unable to restore Back Surface.\n"));
562                         return 0;
563                 }
564         }
565         else if (!_DDFullScreen) {
566                 if (!_lpDDSBack || IDirectDrawSurface_Restore(_lpDDSBack) != DD_OK) {
567                         mprintf((1, "Warning: Unable to restore Back Surface.\n"));
568                         return 0;
569                 }
570         }
571
572         return 1;
573 }
574
575
576 //      DDFlip
577 //              Flip Screens using DirectDraw::Flip
578 //      ----------------------------------------------------------------------------
579 void DDFlip()
580 {
581         HRESULT ddresult;
582
583         ddresult = IDirectDrawSurface_Flip(_lpDDSPrimary, NULL, 0);
584         if (ddresult != DD_OK) {
585                 mprintf((1, "DDFlip:: Unable to flip screen (%X)\n", ddresult));
586                 Int3();                                                                 // Bad flipping
587         }
588 }
589
590
591 //      DDCreateSurface
592 //              Create an offscreen surface hopefully in video memory
593 //      ----------------------------------------------------------------------------
594 LPDIRECTDRAWSURFACE DDCreateSurface(int width, int height, BOOL vram)
595 {
596         DDSURFACEDESC ddsd;
597         HRESULT ddresult;
598         LPDIRECTDRAWSURFACE lpdds;
599         DDCOLORKEY ddck;
600
601         if (_DDSysMemSurfacing && !vram) return DDCreateSysMemSurface(width, height);
602
603         memset(&ddsd, 0, sizeof(ddsd));
604         ddsd.dwSize = sizeof(ddsd);
605         ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
606         ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
607         ddsd.dwWidth = width;
608         ddsd.dwHeight = height;
609
610 //      logentry("Creating %dx%d sysram/vidram surface.\n", width, height);
611         ddresult = IDirectDraw_CreateSurface(_lpDD, &ddsd, &lpdds, NULL);
612         if (ddresult != DD_OK) {
613                 logentry("DDRAW::CreateSurface err: %x\n", ddresult);           
614                 return NULL;
615         }
616
617         return lpdds;
618 }
619
620
621 LPDIRECTDRAWSURFACE DDCreateSysMemSurface(int width, int height)
622 {
623         DDSURFACEDESC ddsd;
624         HRESULT ddresult;
625         LPDIRECTDRAWSURFACE lpdds;
626
627         memset(&ddsd, 0, sizeof(ddsd));
628         ddsd.dwSize = sizeof(ddsd);
629         ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
630         ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
631         ddsd.dwWidth = width;
632         ddsd.dwHeight = height;
633
634 //      logentry("Creating %dx%d sysram surface.\n", width, height);
635         ddresult = IDirectDraw_CreateSurface(_lpDD, &ddsd, &lpdds, NULL);
636         if (ddresult != DD_OK) {
637                 logentry("DDRAW::CreateSysMemSurface err: %x\n", ddresult);             
638                 return NULL;
639         }
640
641         return lpdds;
642 }
643
644
645 //      DDGetPalette
646 //      ----------------------------------------------------------------------------
647 LPDIRECTDRAWPALETTE DDGetPalette(LPDIRECTDRAWSURFACE lpdds)
648 {
649         HRESULT ddresult;
650         LPDIRECTDRAWPALETTE lpddp;
651
652         ddresult = IDirectDrawSurface_GetPalette(lpdds, &lpddp);
653         if (ddresult != DD_OK) {
654                 mprintf((1, "DDERR: GetPalette %x.\n", ddresult));
655                 return NULL;
656         }
657         return lpddp;
658 }
659         
660
661 //      DDCreatePalette
662 //      ----------------------------------------------------------------------------
663 LPDIRECTDRAWPALETTE DDCreatePalette(ubyte *pal)
664 {
665         HRESULT ddresult;
666         LPDIRECTDRAWPALETTE lpddpal;
667         PALETTEENTRY pe[256];
668         int i;
669
670         for (i = 0; i < 256; i++)
671         {
672                 pe[i].peRed = pal[i*3];
673                 pe[i].peGreen = pal[i*3+1];
674                 pe[i].peBlue = pal[i*3+2];
675                 pe[i].peFlags = 0;
676         }
677
678         ddresult = IDirectDraw_CreatePalette(_lpDD, 
679                                                                 DDPCAPS_8BIT | DDPCAPS_ALLOW256, 
680                                                                 pe, 
681                                                                 &lpddpal, NULL);
682         if (ddresult != DD_OK) {
683                 mprintf((1, "DDERR: CreatePalette %x.\n", ddresult));
684                 return NULL;
685         }
686         
687         return lpddpal;
688 }
689
690
691 //      DDSetPalette
692 //      ----------------------------------------------------------------------------
693 void DDSetPalette(LPDIRECTDRAWPALETTE lpDDPal)
694 {
695         HRESULT ddresult;
696
697         ddresult = IDirectDrawSurface_SetPalette(_lpDDSPrimary, lpDDPal);
698         if (ddresult != DD_OK) {
699                 if (ddresult == DDERR_SURFACELOST) {
700                         IDirectDrawSurface_Restore(_lpDDSPrimary);
701                         IDirectDrawSurface_SetPalette(_lpDDSPrimary, lpDDPal);
702                 }
703                 else {
704                         Error("Unable to attach palette to primary surface: %x.", ddresult);
705                 }
706         }
707 }
708
709
710 //      DDLock and DDUnlock Canvas
711 //              This is required to access any canvas.
712 //      ----------------------------------------------------------------------------
713 #ifndef NDEBUG
714 void DDLockCanvas_D(dd_grs_canvas *canvas, char *filename, int line)
715 {
716         HRESULT ddresult;
717         DDSURFACEDESC ddsd;
718         RECT rect;
719         grs_bitmap *bmp;
720
721
722         bmp = &canvas->canvas.cv_bitmap;
723         memset(&ddsd, 0, sizeof(ddsd));
724         ddsd.dwSize = sizeof(ddsd);
725         
726         if (canvas->lock_count == 0) {
727         // Obtain info about a rectangle on the surface
728                 SetRect(&rect, bmp->bm_x, bmp->bm_y, 
729                                 bmp->bm_x+bmp->bm_w, bmp->bm_y+bmp->bm_h);
730
731         RetryLock:
732
733                 ddresult = IDirectDrawSurface_Lock(canvas->lpdds,       
734                                                                                 &rect,
735                                                                                 &ddsd,
736                                                                                 DDLOCK_WAIT,
737                                                                                 NULL);
738                 if (ddresult != DD_OK) {
739                         if (ddresult == DDERR_SURFACELOST) {
740                                 if (!DDRestoreCanvas(canvas))
741                                         Error("Unable to restore surface for lock:%x (%s line %d)\n", ddresult, filename, line);
742                                 else goto RetryLock;
743                         }
744                         else {
745                                 while (canvas->lock_count) DDUnlockCanvas(canvas);
746                                 Error("Unable to lock canvas: %x (%s line %d)\n", ddresult, filename, line);
747                         }
748                 }
749                 bmp->bm_data = (unsigned char *)ddsd.lpSurface;
750                 bmp->bm_rowsize = (short)ddsd.lPitch;
751
752 //              if (canvas->sram && !GRMODEINFO(modex)) {
753 //              //      Manually calculate?
754 //                      bmp->bm_data = bmp->bm_data + (bmp->bm_y*bmp->bm_rowsize);
755 //                      bmp->bm_data += bmp->bm_x;
756 //              } 
757
758                 _DDLockCounter++;
759         }
760         canvas->lock_count++;
761 }
762 #endif
763
764
765 void DDLockCanvas(dd_grs_canvas *canvas)
766 {
767         HRESULT ddresult;
768         DDSURFACEDESC ddsd;
769         RECT rect;
770         grs_bitmap *bmp;
771
772
773         bmp = &canvas->canvas.cv_bitmap;
774         memset(&ddsd, 0, sizeof(ddsd));
775         ddsd.dwSize = sizeof(ddsd);
776         
777         if (canvas->lock_count == 0) {
778         // Obtain info about a rectangle on the surface
779                 SetRect(&rect, bmp->bm_x, bmp->bm_y, 
780                                 bmp->bm_x+bmp->bm_w, bmp->bm_y+bmp->bm_h);
781
782         RetryLock:
783
784                 ddresult = IDirectDrawSurface_Lock(canvas->lpdds,       
785                                                                                 &rect,
786                                                                                 &ddsd,
787                                                                                 DDLOCK_WAIT,
788                                                                                 NULL);
789                 if (ddresult != DD_OK) {
790                         if (ddresult == DDERR_SURFACELOST) {
791                                 if (!DDRestoreCanvas(canvas))
792                                         Error("Unable to restore surface for lock:");
793                                 else goto RetryLock;
794                         }
795                         else {
796                                 while (canvas->lock_count) DDUnlockCanvas(canvas);
797                                 Error("Unable to lock canvas: %x\n", ddresult);
798                         }
799                 }
800                 bmp->bm_data = (unsigned char *)ddsd.lpSurface;
801                 bmp->bm_rowsize = (short)ddsd.lPitch;
802
803 //              if (canvas->sram && !GRMODEINFO(modex)) {
804 //              //      Manually calculate?
805 //                      bmp->bm_data = bmp->bm_data + (bmp->bm_y*bmp->bm_rowsize);
806 //                      bmp->bm_data += bmp->bm_x;
807 //              } 
808
809                 _DDLockCounter++;
810         }
811         canvas->lock_count++;
812 }
813
814
815 void DDUnlockCanvas(dd_grs_canvas *canvas)
816 {
817         HRESULT ddresult;
818         grs_bitmap *bmp;
819
820         bmp = &canvas->canvas.cv_bitmap;
821         
822         if (canvas->lock_count == 1) {
823 //              if (canvas->sram && !GRMODEINFO(modex)) {
824 //                      bmp->bm_data = bmp->bm_data - bmp->bm_x;
825 //                      bmp->bm_data = bmp->bm_data - (bmp->bm_y*bmp->bm_rowsize);
826 //              }
827                 ddresult = IDirectDrawSurface_Unlock(canvas->lpdds, 
828                                                                 canvas->canvas.cv_bitmap.bm_data);
829                 if (ddresult != DD_OK) {        
830                                 Error("Unable to unlock canvas: %x\n", ddresult);
831                                 exit(1);
832                 }
833
834                 canvas->canvas.cv_bitmap.bm_data = NULL;
835                 canvas->canvas.cv_bitmap.bm_rowsize = 0;
836                 _DDLockCounter--;
837         }
838         canvas->lock_count--;
839 }
840
841
842 void DDLockDebug()
843 {
844         logentry("VRAM locks: %d.  SRAM locks: %d\n", DDVideoLocks, DDSystemLocks);
845 }
846
847
848
849 //      DDFreeSurface
850 //      ----------------------------------------------------------------------------
851 void DDFreeSurface(LPDIRECTDRAWSURFACE lpdds)
852 {
853         HRESULT ddresult;
854
855         Assert(lpdds != NULL);
856
857         ddresult = IDirectDrawSurface_Release(lpdds);
858         if (ddresult != DD_OK) {
859                 logentry("DDRAW::FreeSurface err: %x\n", ddresult);             
860                 Error("DDFreeSurface: Unable to free surface.");
861         }
862 }
863
864
865 //      DDRestoreCanvas
866 //      ----------------------------------------------------------------------------
867 BOOL DDRestoreCanvas(dd_grs_canvas *canvas)
868 {
869         HRESULT ddresult;
870         
871         Assert(canvas->lpdds != NULL);
872         
873         ddresult = IDirectDrawSurface_Restore(canvas->lpdds);
874         if (ddresult != DD_OK) {
875                 if (ddresult != DDERR_WRONGMODE) {
876                         logentry("DDRAW::RestoreCanvas::Surface err: %x\n", ddresult);          
877                         return FALSE;
878                 }
879                 mprintf((0, "Recreating surfaces:\n"));
880         // Must recreate canvas
881                 if (canvas->lpdds == _lpDDSPrimary || canvas->lpdds == _lpDDSBack) {
882                         mprintf((0, "DDRestoreCanvas::Screen memory was lost!\n"));
883                         exit(1);
884                 }
885                 if (canvas->sram) {
886                 // force sysmem canvas!
887                         canvas->lpdds = DDCreateSysMemSurface(canvas->canvas.cv_bitmap.bm_w,
888                                                                                         canvas->canvas.cv_bitmap.bm_h);
889                 }
890                 else {
891                         canvas->lpdds = DDCreateSurface(canvas->canvas.cv_bitmap.bm_w, 
892                                                                                         canvas->canvas.cv_bitmap.bm_h,
893                                                                                         _DDSysMemSurfacing);
894                 }                                       
895         }
896         return TRUE;
897 }
898
899
900
901 //      CheckDDResult
902 //      ----------------------------------------------------------------------------
903 BOOL CheckDDResult(HRESULT ddresult, char *funcname)
904 {
905         char buf[256];
906
907         if (ddresult != DD_OK) {
908                 sprintf(buf, "DirectDraw error %x detected in\r\n\t%s", ddresult, funcname);
909                 logentry(buf);
910                 MessageBox(NULL, buf, "DESCENT2::DDRAW", MB_OK);
911                 return FALSE;
912         }
913         else return TRUE;
914 }
915
916
917 //      EnumDispModesCB
918 //      ----------------------------------------------------------------------------
919 HRESULT CALLBACK EnumDispModesCB(LPDDSURFACEDESC lpddsd, LPVOID context)
920 {
921         DWORD width, height,bpp;
922         int mode;
923         DWORD modex;    
924
925         width = lpddsd->dwWidth;
926         height = lpddsd->dwHeight;
927         bpp = lpddsd->ddpfPixelFormat.dwRGBBitCount;
928         modex = lpddsd->ddsCaps.dwCaps;
929
930         modex = modex & DDSCAPS_MODEX;
931
932         if (width == 640 && height == 480 && bpp==8)   
933                 mode = SM95_640x480x8;
934         else if (width == 640 && height == 400 && bpp==8)
935                 mode = SM95_640x400x8;
936         else if (width == 320 && height == 200 && bpp==8) 
937                 mode = SM95_320x200x8X;
938         else if (width == 800 && height == 600 && bpp==8) 
939                 mode = SM95_800x600x8;
940         else if (width == 1024 && height == 768 && bpp==8)
941                 mode = SM95_1024x768x8;
942         else
943                 return DDENUMRET_OK;
944
945         _DDModeList[mode].rw            = width;
946         _DDModeList[mode].rh            = height;
947         _DDModeList[mode].emul          = 0;
948         _DDModeList[mode].modex         = 0;
949         _DDModeList[mode].paged         = 0;
950         _DDModeList[mode].dbuf          = 0;
951
952         if (mode == SM95_320x200x8X) {
953                 _DDModeList[mode].modex = 1;
954                 _DDModeList[mode].dbuf = 1;
955                 _DDModeList[mode].paged = 1;
956         }
957         else if (mode == SM95_640x400x8) {
958         //      Support a range of emulated modes
959         //      320x200x8 Double Pixeled
960                 _DDModeList[SM95_320x200x8].rw = 320;
961                 _DDModeList[SM95_320x200x8].rh = 200;
962                 _DDModeList[SM95_320x200x8].emul = 1;
963                 _DDModeList[SM95_320x200x8].dbuf = 0;
964                 _DDModeList[SM95_320x200x8].modex = 0;
965                 _DDModeList[SM95_320x200x8].paged = 0; 
966                 _DDModeList[SM95_320x200x8].w = 640;
967                 _DDModeList[SM95_320x200x8].h = 400;
968                 _DDModeList[SM95_320x200x8].bpp = 8;
969                 
970                 _DDModeList[SM95_320x400x8].rw = 320;
971                 _DDModeList[SM95_320x400x8].rh = 400;
972                 _DDModeList[SM95_320x400x8].emul = 1;
973                 _DDModeList[SM95_320x400x8].dbuf = 0;
974                 _DDModeList[SM95_320x400x8].modex = 0;
975                 _DDModeList[SM95_320x400x8].paged = 0; 
976                 _DDModeList[SM95_320x400x8].w = 640;
977                 _DDModeList[SM95_320x400x8].h = 400;
978                 _DDModeList[SM95_320x400x8].bpp = 8;
979
980                 _DDNumModes+=2;
981
982                 _DDModeList[mode].dbuf = 1;
983         }
984         else {
985                 _DDModeList[mode].dbuf = 1;
986         }
987
988    _DDModeList[mode].w   = width;
989    _DDModeList[mode].h   = height;
990    _DDModeList[mode].bpp = bpp;
991
992     _DDNumModes++;
993
994     return DDENUMRET_OK;
995 }
996
997
998 int DDCheckMode(int mode)
999 {
1000         if (_DDModeList[mode].w==-1 && _DDModeList[mode].h==-1) return 1;
1001         else return 0;
1002 }