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
34 // ----------------------------------------------------------------------------
35 int dd_gr_initialized = 0;
37 dd_grs_canvas *dd_grd_screencanv = NULL;
38 dd_grs_canvas *dd_grd_backcanv = NULL;
39 dd_grs_canvas *dd_grd_curcanv = NULL;
41 static int ddgr_atexit_called = 0;
43 extern int _DDLockCounter;
44 extern BOOL _DDSysMemSurfacing;
45 extern int W95OldDisplayMode;
47 extern RECT ViewportRect; // Superhack! (from descentw.c. Too much trouble
51 // dd_gr_create_canvas
52 // ----------------------------------------------------------------------------
53 dd_grs_canvas *dd_gr_create_canvas(int w, int h)
59 ddnew = (dd_grs_canvas *)malloc( sizeof(dd_grs_canvas) );
60 ddnew->xoff = ddnew->yoff = 0;
64 new->cv_bitmap.bm_x = 0;
65 new->cv_bitmap.bm_y = 0;
66 new->cv_bitmap.bm_w = w;
67 new->cv_bitmap.bm_h = h;
68 new->cv_bitmap.bm_flags = 0;
69 new->cv_bitmap.bm_type = BM_LINEAR;
70 new->cv_bitmap.bm_rowsize = 0;
71 new->cv_bitmap.bm_data = NULL;
76 new->cv_font_fg_color = 0;
77 new->cv_font_bg_color = 0;
79 ddnew->lpdds = DDCreateSurface(w, h, 0);
81 Error("dd_gr_create_canvas: Unable to create DD Surface");
82 ddnew->lock_count = 0;
84 IDirectDrawSurface_GetCaps(ddnew->lpdds, &ddsc);
86 if (ddDriverCaps.offscreen.sysmem) ddnew->sram = 1;
93 void dd_gr_init_canvas(dd_grs_canvas *canv, int pixtype, int w, int h)
98 canv->xoff = canv->yoff = 0;
102 new->cv_bitmap.bm_x = 0;
103 new->cv_bitmap.bm_y = 0;
104 new->cv_bitmap.bm_w = w;
105 new->cv_bitmap.bm_h = h;
106 new->cv_bitmap.bm_flags = 0;
107 new->cv_bitmap.bm_type = BM_LINEAR;
108 new->cv_bitmap.bm_rowsize = 0;
109 new->cv_bitmap.bm_data = NULL;
112 new->cv_drawmode = 0;
114 new->cv_font_fg_color = 0;
115 new->cv_font_bg_color = 0;
117 canv->lpdds = DDCreateSurface(w,h,0);
119 Error("dd_gr_create_canvas: Unable to create DD Surface");
121 canv->lock_count = 0;
122 IDirectDrawSurface_GetCaps(canv->lpdds, &ddsc);
124 if (ddsc.dwCaps & DDSCAPS_VIDEOMEMORY) canv->sram = 0;
125 else if (ddDriverCaps.offscreen.sysmem) canv->sram = 1;
131 void dd_gr_reinit_canvas(dd_grs_canvas *canv)
135 LPDIRECTDRAWSURFACE lpdds;
137 ddsd.dwSize = sizeof(ddsd);
138 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
139 IDirectDrawSurface_GetSurfaceDesc(canv->lpdds, &ddsd);
143 memset(canv, 0, sizeof(dd_grs_canvas));
146 canv->lock_count = 0;
147 canv->xoff = canv->yoff = 0;
151 new->cv_bitmap.bm_x = 0;
152 new->cv_bitmap.bm_y = 0;
153 new->cv_bitmap.bm_w = ddsd.dwWidth;
154 new->cv_bitmap.bm_h = ddsd.dwHeight;
155 new->cv_bitmap.bm_flags = 0;
156 new->cv_bitmap.bm_type = BM_LINEAR;
157 new->cv_bitmap.bm_rowsize = 0;
158 new->cv_bitmap.bm_data = NULL;
161 new->cv_drawmode = 0;
163 new->cv_font_fg_color = 0;
164 new->cv_font_bg_color = 0;
169 // ----------------------------------------------------------------------------
170 void dd_gr_free_canvas(dd_grs_canvas *canvas)
172 if (canvas == dd_grd_curcanv) { //bad!! freeing current canvas!
174 gr_set_current_canvas(NULL);
177 DDFreeSurface(canvas->lpdds);
182 // dd_gr_create_sub_canvas
183 // ----------------------------------------------------------------------------
184 dd_grs_canvas *dd_gr_create_sub_canvas(dd_grs_canvas *cvs,
185 int x, int y, int w, int h)
187 dd_grs_canvas *ddnew;
193 if (x+w > canv->cv_bitmap.bm_w) {Int3(); w=canv->cv_bitmap.bm_w-x;}
194 if (y+h > canv->cv_bitmap.bm_h) {Int3(); h=canv->cv_bitmap.bm_h-y;}
196 ddnew = (dd_grs_canvas *)malloc( sizeof(dd_grs_canvas) );
197 ddnew->xoff = cvs->xoff;
198 ddnew->yoff = cvs->yoff;
199 ddnew->lock_count = 0;
200 ddnew->lpdds = cvs->lpdds;
201 new = &ddnew->canvas;
203 new->cv_bitmap.bm_x = x+canv->cv_bitmap.bm_x;
204 new->cv_bitmap.bm_y = y+canv->cv_bitmap.bm_y;
205 new->cv_bitmap.bm_w = w;
206 new->cv_bitmap.bm_h = h;
207 new->cv_bitmap.bm_flags = 0;
208 new->cv_bitmap.bm_type = canv->cv_bitmap.bm_type;
209 new->cv_bitmap.bm_rowsize = 0;
211 new->cv_bitmap.bm_data = 0;
213 new->cv_color = canv->cv_color;
214 new->cv_drawmode = canv->cv_drawmode;
215 new->cv_font = canv->cv_font;
216 new->cv_font_fg_color = canv->cv_font_fg_color;
217 new->cv_font_bg_color = canv->cv_font_bg_color;
219 ddnew->sram = cvs->sram;
225 // dd_gr_free_sub_canvas
226 // ----------------------------------------------------------------------------
227 void dd_gr_free_sub_canvas(dd_grs_canvas *cvs)
234 // ----------------------------------------------------------------------------
235 void dd_gr_dup_hack(dd_grs_canvas *hacked, dd_grs_canvas *src)
237 hacked->canvas.cv_bitmap.bm_data = src->canvas.cv_bitmap.bm_data;
238 hacked->canvas.cv_bitmap.bm_rowsize = src->canvas.cv_bitmap.bm_rowsize;
241 void dd_gr_dup_unhack(dd_grs_canvas *hacked)
243 hacked->canvas.cv_bitmap.bm_data = 0;
244 hacked->canvas.cv_bitmap.bm_rowsize = 0;
249 // ----------------------------------------------------------------------------
252 Assert(!dd_gr_initialized);
254 if (!dd_grd_screencanv)
255 dd_grd_screencanv = (dd_grs_canvas *)malloc(sizeof(dd_grs_canvas));
256 if (!dd_grd_backcanv)
257 dd_grd_backcanv = (dd_grs_canvas *)malloc(sizeof(dd_grs_canvas));
260 dd_grd_screencanv->lpdds = NULL;
261 dd_grd_backcanv->lpdds = NULL;
263 if (!ddgr_atexit_called) {
265 ddgr_atexit_called = 1;
267 dd_gr_initialized = 1;
272 // ----------------------------------------------------------------------------
275 Assert(dd_gr_initialized);
277 if (dd_grd_screencanv) free(dd_grd_screencanv);
278 if (dd_grd_backcanv) free(dd_grd_backcanv);
280 dd_grd_screencanv = dd_grd_backcanv = NULL;
281 dd_gr_initialized = 0;
286 // ----------------------------------------------------------------------------
287 void dd_gr_init_screen()
291 // Define screen canvas
292 if (dd_grd_screencanv->lpdds != NULL && !IDirectDrawSurface_IsLost(dd_grd_screencanv->lpdds)) {
294 dd_gr_set_current_canvas(NULL);
295 dd_gr_clear_canvas(BM_XRGB(0,0,0));
296 if (_DDModeList[W95OldDisplayMode].modex) {
298 dd_gr_clear_canvas(BM_XRGB(0,0,0));
303 // Capture the surface's palette.
304 DDSetDisplayMode(W95DisplayMode, 0);
305 grwin_set_winpalette(_lpDD, _lpDDPalette);
308 gr_init_screen(BM_LINEAR,
309 GRMODEINFO(rw), GRMODEINFO(rh),
312 dd_grd_screencanv->lock_count = 0;
313 memcpy(&dd_grd_screencanv->canvas, &grd_curscreen->sc_canvas, sizeof(grs_canvas));
317 // The 'Emulated' Method.
318 // We will define the screen canvas as the Windows equiv to
319 // DOS display memory. This will be our Direct Draw Back canvas.
321 if (GRMODEINFO(emul) || GRMODEINFO(modex)) {
322 dd_grd_screencanv->lpdds = _lpDDSBack;
323 dd_grd_backcanv->lpdds = NULL;
324 dd_grd_curcanv = NULL;
328 // The Page Flipping Full Screen Method
329 // The screen canvas is the actual display
330 // The back canvas is our scratch page
331 // This does not apply to Mode X modes
333 else if (GRMODEINFO(paged) && !GRMODEINFO(modex)) {
334 dd_grd_screencanv->lpdds = _lpDDSPrimary;
336 new = &dd_grd_backcanv->canvas;
338 new->cv_bitmap.bm_x = 0;
339 new->cv_bitmap.bm_y = 0;
340 new->cv_bitmap.bm_w = _DDModeList[W95DisplayMode].rw;
341 new->cv_bitmap.bm_h = _DDModeList[W95DisplayMode].rh;
342 new->cv_bitmap.bm_flags = 0;
343 new->cv_bitmap.bm_type = BM_LINEAR;
344 new->cv_bitmap.bm_rowsize = 0;
345 new->cv_bitmap.bm_data = NULL;
348 new->cv_drawmode = 0;
350 new->cv_font_fg_color = 0;
351 new->cv_font_bg_color = 0;
353 dd_grd_backcanv->lpdds = _lpDDSBack;
354 dd_grd_backcanv->lock_count = 0;
355 dd_grd_curcanv = NULL;
359 // No page flipping (just 1 page), and no use for back surface.
361 else if (GRMODEINFO(dbuf) && !GRMODEINFO(paged)) {
362 dd_grd_screencanv->lpdds = _lpDDSPrimary;
363 dd_grd_backcanv->lpdds = NULL;
364 dd_grd_curcanv = NULL;
370 Int3(); // An illegal hacked graphic mode
373 dd_gr_set_current_canvas(NULL);
374 dd_gr_clear_canvas(BM_XRGB(0,0,0));
375 // if (GRMODEINFO(modex)) {
377 // dd_gr_clear_canvas(BM_XRGB(0,0,0));
383 int dd_gr_restore_canvas(dd_grs_canvas *canvas)
385 if (!DDRestoreSurface(canvas->lpdds)) {
387 DDFreeSurface(canvas->lpdds);
389 canvas->lpdds = DDCreateSysMemSurface(canvas->canvas.cv_bitmap.bm_w,
390 canvas->canvas.cv_bitmap.bm_h);
393 canvas->lpdds = DDCreateSurface(canvas->canvas.cv_bitmap.bm_w,
394 canvas->canvas.cv_bitmap.bm_h, TRUE);
396 if (!canvas->lpdds) return 0;
404 // copies dd_gr_screencanv to grd_curscreen->sc_canvas
405 // ----------------------------------------------------------------------------
406 void dd_gr_screen_lock()
408 if (dd_grd_screencanv->lpdds == _lpDDSPrimary && GRMODEINFO(modex))
409 Int3(); // Can't do this in ModeX!!
410 dd_gr_lock(dd_grd_screencanv);
411 memcpy(&grd_curscreen->sc_canvas, &dd_grd_screencanv->canvas, sizeof(grs_canvas));
415 // dd_gr_screen_unlock
416 // copies grd_curscreen->sc_canvas to dd_gr_screencanv
417 // ----------------------------------------------------------------------------
418 void dd_gr_screen_unlock()
420 memcpy(&dd_grd_screencanv->canvas, &grd_curscreen->sc_canvas, sizeof(grs_canvas));
421 dd_gr_unlock(dd_grd_screencanv);
425 void dd_gr_lock(dd_grs_canvas *canv)
432 if (canv->lock_count == 0)
434 bmp = &canv->canvas.cv_bitmap;
435 SetRect(&rect,bmp->bm_x,bmp->bm_y,bmp->bm_x+bmp->bm_w, bmp->bm_y+bmp->bm_h);
437 if (!dd_gr_restore_canvas(canv))
438 Error("Failed to lock canvas (restore err)!\n");
440 data = DDLockSurface(canv->lpdds, &rect, &rowsize);
441 canv->canvas.cv_bitmap.bm_rowsize = (short)rowsize;
444 Error("Failed to lock canvas! You may need to use the -emul option.\n");
446 canv->canvas.cv_bitmap.bm_data = data;
448 if (canv == dd_grd_curcanv) {
449 gr_set_current_canvas(&canv->canvas);
456 void dd_gr_lock_d(dd_grs_canvas *canv, char *filename, int line)
463 if (canv->lock_count == 0)
465 bmp = &canv->canvas.cv_bitmap;
466 SetRect(&rect,bmp->bm_x,bmp->bm_y,bmp->bm_x+bmp->bm_w, bmp->bm_y+bmp->bm_h);
468 if (!dd_gr_restore_canvas(canv))
470 Error("Failed to lock canvas (restore err) (%s line %d)\n", filename, line);
472 Error("Failed to lock canvas (restore err)!\n");
475 data = DDLockSurface(canv->lpdds, &rect, &rowsize);
476 canv->canvas.cv_bitmap.bm_rowsize = (short)rowsize;
480 Error("Failed to lock canvas (%s line %d)\n", filename, line);
482 Error("Failed to lock canvas! You may ned to use the -emul option.\n");
485 canv->canvas.cv_bitmap.bm_data = data;
487 if (canv == dd_grd_curcanv) {
488 gr_set_current_canvas(&canv->canvas);
496 void dd_gr_unlock(dd_grs_canvas *canv)
498 if (canv->lock_count == 1)
500 DDUnlockSurface(canv->lpdds, canv->canvas.cv_bitmap.bm_data);
506 // dd_gr_set_current_canvas
507 // This function should do this:
508 // set desired canvas to dd_grd_curcanv
509 // call gr_set_current_canvas
511 // If desired canvas is NULL, then set current canvas to screen
512 // set grd_curscreen->sc_canvas.cv_bitmap, etc to dd_grd_screencanv info
513 // call gr_set_current_canvas(NULL)
514 // this will use what is in grd_curscreen->etc to do the proper thing
516 // Note: Must lock desired canvas before calling this.
517 // This causes an address to be delivered to the canvas.
518 // Else address is invalid and will crash.
520 void dd_gr_set_current_canvas(dd_grs_canvas *canvas)
522 if (canvas == NULL) {
523 dd_grd_curcanv = dd_grd_screencanv;
524 gr_set_current_canvas(&dd_grd_screencanv->canvas);
527 dd_grd_curcanv = canvas;
528 gr_set_current_canvas(&dd_grd_curcanv->canvas);
533 // dd_gr_init_sub_canvas
534 // perform gr_init_sub_canvas.
535 // same surface but reset lock count.
536 void dd_gr_init_sub_canvas(dd_grs_canvas *new, dd_grs_canvas *src,
537 int x, int y, int w, int h)
539 gr_init_sub_canvas(&new->canvas, &src->canvas, x, y, w, h);
540 new->xoff = src->xoff;
541 new->yoff = src->yoff;
542 new->lpdds = src->lpdds;
544 new->sram = src->sram;
549 // performs a general 'flip' of canvases.
550 // If we are in a slow display mode, we will copy the screen canvas
552 // If we are in a FullScreen mode, then we will just perform a
556 if (GRMODEINFO(emul)) {
557 dd_gr_blt_display(dd_grd_screencanv,
559 ViewportRect.left, ViewportRect.top,
560 ViewportRect.right-ViewportRect.left,
561 ViewportRect.bottom-ViewportRect.top);
563 else if (_DDFullScreen) {
567 Int3(); // Illegal display mode!
572 // dd_gr_restore_display
573 // blts the screen canvas to the display
574 // (for Slow modes which emulate a DOS display)
575 void dd_gr_restore_display()
577 if (GRMODEINFO(emul)) {
578 // We use a offscreen buffer as grd_screencanv, so just
579 // blt this to the display
581 IDirectDrawSurface_Blt(_lpDDSPrimary,
583 dd_grd_screencanv->lpdds,
588 else if (GRMODEINFO(modex)) {
597 // blts one canvas region to another canvas with scaling and
599 void dd_gr_blt_notrans(dd_grs_canvas *srccanv,
600 int sx, int sy, int swidth, int sheight,
601 dd_grs_canvas *destcanv,
602 int dx, int dy, int dwidth, int dheight)
605 RECT *psrect, *pdrect;
606 grs_bitmap *sbmp, *dbmp;
610 sbmp = &srccanv->canvas.cv_bitmap;
611 dbmp = &destcanv->canvas.cv_bitmap;
613 if (swidth || sheight) {
614 SetRect(psrect, sx+sbmp->bm_x, sy+sbmp->bm_y, sx+sbmp->bm_x+swidth,
615 sy+sbmp->bm_y+sheight);
618 SetRect(psrect, sbmp->bm_x, sbmp->bm_y, sbmp->bm_w+sbmp->bm_x,
619 sbmp->bm_h+sbmp->bm_y);
622 if (dwidth || dheight) {
623 SetRect(pdrect, dx+dbmp->bm_x, dy+dbmp->bm_y, dx+dbmp->bm_x+dwidth,
624 dy+dbmp->bm_y+dheight);
627 SetRect(pdrect, dbmp->bm_x, dbmp->bm_y, dbmp->bm_x+dbmp->bm_w,
628 dbmp->bm_y+dbmp->bm_h);
631 if (_DDFullScreen && !GRMODEINFO(emul)) {
632 IDirectDrawSurface_BltFast(destcanv->lpdds, dx+dbmp->bm_x, dy+dbmp->bm_y,
633 srccanv->lpdds, psrect,
634 DDBLTFAST_NOCOLORKEY | DDBLTFAST_WAIT);
637 IDirectDrawSurface_Blt(destcanv->lpdds,
647 // dd_gr_blt_display (no keying)
648 // blts a canvas region to the display.
649 // for windowed modes, this is the only way to blt
650 // a canvas to the display.
651 void dd_gr_blt_display(dd_grs_canvas *srccanv,
652 int sx, int sy, int swidth, int sheight,
653 int dx, int dy, int dwidth, int dheight)
656 RECT *psrect, *pdrect;
660 if (srccanv->lpdds == _lpDDSPrimary) {
661 Int3(); // This will crash the system
667 sbmp = &srccanv->canvas.cv_bitmap;
669 if (swidth || sheight) {
670 SetRect(psrect, sx+sbmp->bm_x, sy+sbmp->bm_y, sx+sbmp->bm_x+swidth-1,
671 sy+sbmp->bm_y+sheight-1);
674 SetRect(psrect, sbmp->bm_x, sbmp->bm_y, sbmp->bm_w+sbmp->bm_x-1,
675 sbmp->bm_h+sbmp->bm_y-1);
678 if (dwidth || dheight) {
679 SetRect(pdrect, dx, dy, dx+dwidth-1, dy+dheight-1);
683 // We are blting to the display which is _lpDDSPrimary.
684 result = IDirectDrawSurface_Blt(_lpDDSPrimary,
691 Error("DDERR: Blt: (%d)\n", (result & 0x0000ffff));
695 // dd_gr_blt_screen (no keying)
696 // blts canvas to screen canvas
697 void dd_gr_blt_screen(dd_grs_canvas *srccanv,
698 int sx, int sy, int swidth, int sheight,
699 int dx, int dy, int dwidth, int dheight)
701 dd_gr_blt_notrans(srccanv, sx, sy, swidth, sheight,
702 dd_grd_screencanv, dx, dy, dwidth, dheight);
706 // dd_gr_clear_canvas
707 // clears a canvas the 'fast' way.
708 void dd_gr_clear_canvas(int color)
715 bmp = &dd_grd_curcanv->canvas.cv_bitmap;
717 UpdateWindow(GetLibraryWindow());
719 ddbltfx.dwSize = sizeof( ddbltfx );
720 ddbltfx.dwFillColor = (DWORD)color;
722 Assert(_DDLockCounter == 0);
724 SetRect(&drect, bmp->bm_x, bmp->bm_y, bmp->bm_x+bmp->bm_w,
725 bmp->bm_y+bmp->bm_h);
727 ddresult = IDirectDrawSurface_Blt(
728 dd_grd_curcanv->lpdds, // dest surface
732 DDBLT_COLORFILL | DDBLT_WAIT,
734 if (ddresult != DD_OK) {
735 if (ddresult == DDERR_SURFACELOST) {
736 if (!dd_gr_restore_canvas(dd_grd_curcanv))
737 Error("Direct Draw GR library Blt Clear Restore error.");
739 else Error("Direct Draw GR library Blt Clear error: %x", ddresult);
742 if (!_DDFullScreen) {
743 Assert(_DDLockCounter == 0);