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.
18 #define WIN32_LEAN_AND_MEAN
20 #include "win\ddraw.h"
33 // Direct X Variables ---------------------------------------------------------
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;
48 dd_caps ddDriverCaps; // Driver Caps.
50 int _DDFlags=0; // Direct Draw Flags
51 int _DDLockCounter=0; // DirectDraw Lock Surface counter
53 static BOOL DDUseEmulation=FALSE;
54 static HWND DDWnd=NULL;
56 static int DDVideoLocks = 0;
57 static int DDSystemLocks = 0;
59 // Function prototypes --------------------------------------------------------
61 HRESULT CALLBACK EnumDispModesCB(LPDDSURFACEDESC lpddsd, LPVOID context);
62 BOOL CheckDDResult(HRESULT ddresult, char *funcname);
63 BOOL DDRestoreCanvas(dd_grs_canvas *canvas);
66 // Direct Draw Initialization
67 // ----------------------------------------------------------------------------
72 DDCAPS ddcaps, ddcaps2;
76 DDWnd = GetLibraryWindow();
78 // Create Direct Draw Object (Use Emulation if Hardware is off)
80 ddresult = DirectDrawCreate(NULL, &lpdd, NULL);
82 if (ddresult == DDERR_NODIRECTDRAWHW) {
83 ddresult = DirectDrawCreate( (LPVOID) DDCREATE_EMULATIONONLY, &lpdd, NULL );
84 if (!CheckDDResult(ddresult, "InitDD:DirectDrawCreate emulation"))
86 DDUseEmulation = TRUE;
87 logentry("DirectDraw: forcing emulation.\n");
89 else if (ddresult != DD_OK) return FALSE;
90 logentry("DirectDraw: DirectX API hardware compliant.\n");
96 // Determine hardware caps
97 // Determine capture mode (fullscreen takes exclusive, window is normal)
98 if (mode == DDGR_FULLSCREEN) {
101 flags = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN;
104 if (!FindArg("-nomodex")) flags |= DDSCL_ALLOWMODEX;
106 flags |= DDSCL_ALLOWMODEX;
109 if (!FindArg("-disallowreboot")) flags |= DDSCL_ALLOWREBOOT;
111 ddresult = IDirectDraw_SetCooperativeLevel(lpdd, DDWnd, flags);
113 if (!CheckDDResult(ddresult, "DDInit::SetCooperativeLevel")) {
114 IDirectDraw_Release(lpdd);
119 _DDFullScreen = TRUE;
121 else if (mode == DDGR_EXWINDOW) {
122 ddresult = IDirectDraw_SetCooperativeLevel(lpdd, DDWnd,
125 if (!CheckDDResult(ddresult, "DDInit::SetCooperativeLevel"))
128 _DDFullScreen = FALSE;
130 else if (mode == DDGR_WINDOW) {
131 ddresult = IDirectDraw_SetCooperativeLevel(lpdd, DDWnd,
133 if (!CheckDDResult(ddresult, "DDInit::SetCooperativeLevel"))
135 _DDExclusive = FALSE;
136 _DDFullScreen = FALSE;
140 // Get Display modes/Window Sizes
141 // Force invalidation of all modes for now
142 for (num = 0; num < 16; num++)
144 _DDModeList[num].rw = _DDModeList[num].w = -1;
145 _DDModeList[num].rh = _DDModeList[num].h = -1;
148 W95DisplayMode = SM95_640x480x8;
150 if (mode == DDGR_FULLSCREEN) {
151 ddresult = IDirectDraw_EnumDisplayModes(lpdd, 0, NULL, 0,
153 if(!CheckDDResult(ddresult, "DDInit::EnumDisplayModes")) {
154 IDirectDraw_Release(lpdd);
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;
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;
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;
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;
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;
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;
218 // Set appropriate display mode or window mode
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"))
229 logentry("DirectDraw: VRAM free: %d\n", ddcaps.dwVidMemFree);
230 logentry("DirectDraw: VRAM total: %d\n", ddcaps.dwVidMemTotal);
233 if (FindArg("-TsengDebug1")) {
234 IDirectDraw_Release(lpdd);
239 DDSetDisplayMode(W95DisplayMode, 0);
242 if (FindArg("-TsengDebug2")) {
243 IDirectDraw_Release(lpdd);
248 // If 'windowed' do this.
251 ddresult = IDirectDraw_CreateClipper(_lpDD, 0, &_lpDDClipper, NULL);
252 if (!CheckDDResult(ddresult, "DDCreateScreen::CreateClipper"))
255 ddresult = IDirectDrawClipper_SetHWnd(_lpDDClipper, 0, DDWnd);
256 if (!CheckDDResult(ddresult, "DDCreateScreen::SetHWnd"))
259 ddresult = IDirectDrawSurface_SetClipper(_lpDDSPrimary, _lpDDClipper);
260 if (!CheckDDResult(ddresult, "DDCreateScreen::SetClipper"))
264 // Register Optimizations
266 ddcaps.dwSize = sizeof(ddcaps);
267 ddcaps2.dwSize = sizeof(ddcaps);
268 ddresult = IDirectDraw_GetCaps(lpdd, &ddcaps, &ddcaps2);
269 if (!CheckDDResult(ddresult, "DDInit::GetCaps"))
273 if (FindArg("-TsengDebug3")) {
274 IDirectDraw_Release(lpdd);
279 if (FindArg("-vidram")) {
280 logentry("DirectDraw: Forcing VRAM rendering.\n");
281 _DDSysMemSurfacing = FALSE;
283 else if (FindArg("-sysram")) {
284 logentry("DirectDraw: Forcing SRAM rendering.\n");
285 _DDSysMemSurfacing = TRUE;
287 else if (ddcaps.dwCaps & DDCAPS_BANKSWITCHED) {
288 logentry("DirectDraw: Hardware is bank-switched. Using SRAM rendering.\n");
289 _DDSysMemSurfacing = TRUE;
292 logentry("DirectDraw: Hardware is not bank-switched. Using VRAM rendering.\n");
293 _DDSysMemSurfacing = FALSE;
296 if (ddcaps.dwCaps & DDCAPS_COLORKEYHWASSIST)
297 ddDriverCaps.hwcolorkey = 1;
299 ddDriverCaps.hwcolorkey = 0;
300 if (ddcaps.dwCaps & DDCAPS_BLTSTRETCH)
301 ddDriverCaps.hwbltstretch = 1;
303 ddDriverCaps.hwbltstretch = 0;
306 //@@ mprintf((0, "DD::Hardware="));
307 //@@ if (ddcaps.dwCaps & DDCAPS_NOHARDWARE) mprintf((0, "Off\n"));
308 //@@ else mprintf((0, "On\n"));
310 //@@ mprintf((0, "DD::VideoMem=%u bytes\n", ddcaps.dwVidMemTotal));
312 //@@ mprintf((0, "DD::SrcColorKey="));
313 //@@ if (ddcaps.dwCKeyCaps & DDCKEYCAPS_SRCBLT) mprintf((0, "Hardware\n"));
314 //@@ else mprintf((0, "Emulation\n"));
320 // Direct Draw Destruction
321 // ----------------------------------------------------------------------------
325 // Perform cleanup for full screen case and window case
327 if (_lpDDPalette) IDirectDrawPalette_Release(_lpDDPalette);
328 if (_lpDD) IDirectDraw_Release(_lpDD);
330 _DDExclusive = _DDFullScreen = FALSE;
337 // Direct Draw Surface Creation
338 // Create Screen (Page 0 and possibly Page 1 or offscreen buffer)
339 // ----------------------------------------------------------------------------
341 BOOL DDCreateScreen(int flags)
344 DDCAPS ddcaps, ddcaps2;
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"))
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;
363 logentry("DirectDraw: Hardware is not bank-switched. Using VRAM rendering.\n");
364 _DDSysMemSurfacing = FALSE;
367 // Determine GFX caps.
368 if (ddcaps.dwCaps & DDCAPS_COLORKEYHWASSIST)
369 ddDriverCaps.hwcolorkey = 1;
371 ddDriverCaps.hwcolorkey = 0;
372 if (ddcaps.dwCaps & DDCAPS_BLTSTRETCH)
373 ddDriverCaps.hwbltstretch = 1;
375 ddDriverCaps.hwbltstretch = 0;
377 memset(&ddsd, 0, sizeof(ddsd));
378 ddsd.dwSize = sizeof(ddsd);
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 |
387 ddresult = IDirectDraw_CreateSurface(_lpDD, &ddsd, &_lpDDSPrimary, NULL);
388 if (!CheckDDResult(ddresult, "DDCreateScreen::CreateSurface -fullscreen"))
391 ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
392 ddresult = IDirectDrawSurface_GetAttachedSurface(_lpDDSPrimary,
393 &ddscaps, &_lpDDSBack);
394 if (!CheckDDResult(ddresult, "DDCreateScreen::GetAttachedSurface"))
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"))
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"))
417 if (GRMODEINFO(emul)) {
418 _lpDDSBack = DDCreateSurface(_DDModeList[W95DisplayMode].rw,
419 _DDModeList[W95DisplayMode].rh, 1);
421 mprintf((0,"Call to create DDSBackBuffer failed."));
425 else _lpDDSBack = NULL;
429 // Create 8-bit palette
434 memset(&ddsd, 0, sizeof(ddsd));
435 ddsd.dwSize = sizeof(ddsd);
436 IDirectDrawSurface_GetSurfaceDesc(_lpDDSPrimary, &ddsd);
438 logentry("Primary surface pixel format: %x, %d\n", ddsd.ddpfPixelFormat.dwFlags, ddsd.ddpfPixelFormat.dwRGBBitCount);
440 _lpDDPalette = DDCreatePalette(pal);
441 Assert(_lpDDPalette != NULL);
442 DDSetPalette(_lpDDPalette);
449 // DirectDraw Screen Kill
450 // ----------------------------------------------------------------------------
454 if (_lpDDClipper) IDirectDrawClipper_Release(_lpDDClipper);
455 if (_lpDDPalette) IDirectDrawPalette_Release(_lpDDPalette);
456 if (_lpDDSBack) IDirectDrawSurface_Release(_lpDDSBack);
459 if (!GRMODEINFO(modex)) {
463 memset(&ddbltfx, 0, sizeof(DDBLTFX));
464 ddbltfx.dwSize = sizeof( ddbltfx );
465 ddbltfx.dwFillColor = (WORD)(BM_XRGB(0,0,0));
467 ddresult = IDirectDrawSurface_Blt(
468 _lpDDSPrimary, // dest surface
472 DDBLT_COLORFILL | DDBLT_WAIT,
476 IDirectDrawSurface_Release(_lpDDSPrimary);
482 _lpDDSPrimary = NULL;
486 void DDKillEmulatedScreen()
488 if (_lpDDSBack) IDirectDrawSurface_Release(_lpDDSBack);
495 // ----------------------------------------------------------------------------
497 void DDSetDisplayMode(int display_mode, int flags)
501 W95DisplayMode = display_mode;
502 W95OldDisplayMode = display_mode;
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);
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);
513 DDCreateScreen(flags);
519 DDKillEmulatedScreen();
521 dwStyle = GetWindowLong(DDWnd, GWL_STYLE);
522 dwStyle &= ~WS_POPUP;
523 dwStyle |= WS_OVERLAPPED | WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX;
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));
533 SetWindowPos(DDWnd, NULL, 0,0,
534 rect.right-rect.left,
535 rect.bottom-rect.top,
539 SetWindowPos(DDWnd, HWND_NOTOPMOST, 0, 0, 0, 0,
544 DDCreateScreen(flags);
551 // ----------------------------------------------------------------------------
552 int DDRestoreScreen()
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"));
559 if (!GRMODEINFO(paged) && _lpDDSBack) {
560 if (IDirectDrawSurface_Restore(_lpDDSBack) != DD_OK) {
561 mprintf((1, "Warning: Unable to restore Back Surface.\n"));
565 else if (!_DDFullScreen) {
566 if (!_lpDDSBack || IDirectDrawSurface_Restore(_lpDDSBack) != DD_OK) {
567 mprintf((1, "Warning: Unable to restore Back Surface.\n"));
577 // Flip Screens using DirectDraw::Flip
578 // ----------------------------------------------------------------------------
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
592 // Create an offscreen surface hopefully in video memory
593 // ----------------------------------------------------------------------------
594 LPDIRECTDRAWSURFACE DDCreateSurface(int width, int height, BOOL vram)
598 LPDIRECTDRAWSURFACE lpdds;
601 if (_DDSysMemSurfacing && !vram) return DDCreateSysMemSurface(width, height);
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;
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);
621 LPDIRECTDRAWSURFACE DDCreateSysMemSurface(int width, int height)
625 LPDIRECTDRAWSURFACE lpdds;
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;
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);
646 // ----------------------------------------------------------------------------
647 LPDIRECTDRAWPALETTE DDGetPalette(LPDIRECTDRAWSURFACE lpdds)
650 LPDIRECTDRAWPALETTE lpddp;
652 ddresult = IDirectDrawSurface_GetPalette(lpdds, &lpddp);
653 if (ddresult != DD_OK) {
654 mprintf((1, "DDERR: GetPalette %x.\n", ddresult));
662 // ----------------------------------------------------------------------------
663 LPDIRECTDRAWPALETTE DDCreatePalette(ubyte *pal)
666 LPDIRECTDRAWPALETTE lpddpal;
667 PALETTEENTRY pe[256];
670 for (i = 0; i < 256; i++)
672 pe[i].peRed = pal[i*3];
673 pe[i].peGreen = pal[i*3+1];
674 pe[i].peBlue = pal[i*3+2];
678 ddresult = IDirectDraw_CreatePalette(_lpDD,
679 DDPCAPS_8BIT | DDPCAPS_ALLOW256,
682 if (ddresult != DD_OK) {
683 mprintf((1, "DDERR: CreatePalette %x.\n", ddresult));
692 // ----------------------------------------------------------------------------
693 void DDSetPalette(LPDIRECTDRAWPALETTE lpDDPal)
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);
704 Error("Unable to attach palette to primary surface: %x.", ddresult);
710 // DDLock and DDUnlock Canvas
711 // This is required to access any canvas.
712 // ----------------------------------------------------------------------------
714 void DDLockCanvas_D(dd_grs_canvas *canvas, char *filename, int line)
722 bmp = &canvas->canvas.cv_bitmap;
723 memset(&ddsd, 0, sizeof(ddsd));
724 ddsd.dwSize = sizeof(ddsd);
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);
733 ddresult = IDirectDrawSurface_Lock(canvas->lpdds,
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);
745 while (canvas->lock_count) DDUnlockCanvas(canvas);
746 Error("Unable to lock canvas: %x (%s line %d)\n", ddresult, filename, line);
749 bmp->bm_data = (unsigned char *)ddsd.lpSurface;
750 bmp->bm_rowsize = (short)ddsd.lPitch;
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;
760 canvas->lock_count++;
765 void DDLockCanvas(dd_grs_canvas *canvas)
773 bmp = &canvas->canvas.cv_bitmap;
774 memset(&ddsd, 0, sizeof(ddsd));
775 ddsd.dwSize = sizeof(ddsd);
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);
784 ddresult = IDirectDrawSurface_Lock(canvas->lpdds,
789 if (ddresult != DD_OK) {
790 if (ddresult == DDERR_SURFACELOST) {
791 if (!DDRestoreCanvas(canvas))
792 Error("Unable to restore surface for lock:");
796 while (canvas->lock_count) DDUnlockCanvas(canvas);
797 Error("Unable to lock canvas: %x\n", ddresult);
800 bmp->bm_data = (unsigned char *)ddsd.lpSurface;
801 bmp->bm_rowsize = (short)ddsd.lPitch;
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;
811 canvas->lock_count++;
815 void DDUnlockCanvas(dd_grs_canvas *canvas)
820 bmp = &canvas->canvas.cv_bitmap;
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);
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);
834 canvas->canvas.cv_bitmap.bm_data = NULL;
835 canvas->canvas.cv_bitmap.bm_rowsize = 0;
838 canvas->lock_count--;
844 logentry("VRAM locks: %d. SRAM locks: %d\n", DDVideoLocks, DDSystemLocks);
850 // ----------------------------------------------------------------------------
851 void DDFreeSurface(LPDIRECTDRAWSURFACE lpdds)
855 Assert(lpdds != NULL);
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.");
866 // ----------------------------------------------------------------------------
867 BOOL DDRestoreCanvas(dd_grs_canvas *canvas)
871 Assert(canvas->lpdds != NULL);
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);
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"));
886 // force sysmem canvas!
887 canvas->lpdds = DDCreateSysMemSurface(canvas->canvas.cv_bitmap.bm_w,
888 canvas->canvas.cv_bitmap.bm_h);
891 canvas->lpdds = DDCreateSurface(canvas->canvas.cv_bitmap.bm_w,
892 canvas->canvas.cv_bitmap.bm_h,
902 // ----------------------------------------------------------------------------
903 BOOL CheckDDResult(HRESULT ddresult, char *funcname)
907 if (ddresult != DD_OK) {
908 sprintf(buf, "DirectDraw error %x detected in\r\n\t%s", ddresult, funcname);
910 MessageBox(NULL, buf, "DESCENT2::DDRAW", MB_OK);
918 // ----------------------------------------------------------------------------
919 HRESULT CALLBACK EnumDispModesCB(LPDDSURFACEDESC lpddsd, LPVOID context)
921 DWORD width, height,bpp;
925 width = lpddsd->dwWidth;
926 height = lpddsd->dwHeight;
927 bpp = lpddsd->ddpfPixelFormat.dwRGBBitCount;
928 modex = lpddsd->ddsCaps.dwCaps;
930 modex = modex & DDSCAPS_MODEX;
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;
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;
952 if (mode == SM95_320x200x8X) {
953 _DDModeList[mode].modex = 1;
954 _DDModeList[mode].dbuf = 1;
955 _DDModeList[mode].paged = 1;
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;
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;
982 _DDModeList[mode].dbuf = 1;
985 _DDModeList[mode].dbuf = 1;
988 _DDModeList[mode].w = width;
989 _DDModeList[mode].h = height;
990 _DDModeList[mode].bpp = bpp;
998 int DDCheckMode(int mode)
1000 if (_DDModeList[mode].w==-1 && _DDModeList[mode].h==-1) return 1;