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