view src/win32/DirectDraw.cpp @ 7:c0a590a394c3

ignore generated files
author Robert McIntyre <rlm@mit.edu>
date Sat, 03 Mar 2012 10:50:33 -0600
parents f9f4f1b99eed
children
line wrap: on
line source
1 #include "stdafx.h"
3 #define DIRECTDRAW_VERSION 0x0700
4 #include "ddraw.h"
6 #include "resource.h"
7 #include "MainWnd.h"
8 #include "Reg.h"
9 #include "VBA.h"
11 #include "../common/System.h"
12 #include "../gba/GBAGlobals.h"
13 #include "../gb/gbGlobals.h"
14 #include "../common/Text.h"
15 #include "../version.h"
17 extern u32 RGB_LOW_BITS_MASK;
18 extern int systemSpeed;
19 extern int Init_2xSaI(u32);
20 extern void directXMessage(const char *);
21 extern void winlog(const char *, ...);
22 extern int winVideoModeSelect(CWnd *, GUID * *);
24 class DirectDrawDisplay : public IDisplay
25 {
26 private:
27 HINSTANCE ddrawDLL;
28 LPDIRECTDRAW7 pDirectDraw;
29 LPDIRECTDRAWSURFACE7 ddsPrimary;
30 LPDIRECTDRAWSURFACE7 ddsOffscreen;
31 LPDIRECTDRAWSURFACE7 ddsFlip;
32 LPDIRECTDRAWCLIPPER ddsClipper;
33 int width;
34 int height;
35 bool failed;
37 bool initializeOffscreen(int w, int h);
38 public:
39 DirectDrawDisplay();
40 virtual ~DirectDrawDisplay();
42 virtual bool initialize();
43 virtual void cleanup();
44 virtual void render();
45 virtual void checkFullScreen();
46 virtual void renderMenu();
47 virtual void clear();
48 virtual bool changeRenderSize(int w, int h);
49 virtual DISPLAY_TYPE getType() { return DIRECT_DRAW; };
50 virtual void setOption(const char *, int) {}
51 virtual int selectFullScreenMode(GUID * *);
52 };
54 static HRESULT WINAPI checkModesAvailable(LPDDSURFACEDESC2 surf, LPVOID lpContext)
55 {
56 if (surf->dwWidth == 320 &&
57 surf->dwHeight == 240 &&
58 surf->ddpfPixelFormat.dwRGBBitCount == 16)
59 {
60 theApp.mode320Available = TRUE;
61 }
62 if (surf->dwWidth == 640 &&
63 surf->dwHeight == 480 &&
64 surf->ddpfPixelFormat.dwRGBBitCount == 16)
65 {
66 theApp.mode640Available = TRUE;
67 }
68 if (surf->dwWidth == 800 &&
69 surf->dwHeight == 600 &&
70 surf->ddpfPixelFormat.dwRGBBitCount == 16)
71 {
72 theApp.mode800Available = TRUE;
73 }
74 return DDENUMRET_OK;
75 }
77 static int ffs(UINT mask)
78 {
79 int m = 0;
80 if (mask)
81 {
82 while (!(mask & (1 << m)))
83 m++;
85 return (m);
86 }
88 return (0);
89 }
91 DirectDrawDisplay::DirectDrawDisplay()
92 {
93 pDirectDraw = NULL;
94 ddsPrimary = NULL;
95 ddsOffscreen = NULL;
96 ddsFlip = NULL;
97 ddsClipper = NULL;
98 ddrawDLL = NULL;
99 width = 0;
100 height = 0;
101 failed = false;
102 }
104 DirectDrawDisplay::~DirectDrawDisplay()
105 {
106 cleanup();
107 }
109 void DirectDrawDisplay::cleanup()
110 {
111 if (pDirectDraw != NULL)
112 {
113 if (ddsClipper != NULL)
114 {
115 ddsClipper->Release();
116 ddsClipper = NULL;
117 }
119 if (ddsFlip != NULL)
120 {
121 ddsFlip->Release();
122 ddsFlip = NULL;
123 }
125 if (ddsOffscreen != NULL)
126 {
127 ddsOffscreen->Release();
128 ddsOffscreen = NULL;
129 }
131 if (ddsPrimary != NULL)
132 {
133 ddsPrimary->Release();
134 ddsPrimary = NULL;
135 }
137 pDirectDraw->Release();
138 pDirectDraw = NULL;
139 }
141 if (ddrawDLL != NULL)
142 {
143 /**/ ::FreeLibrary(ddrawDLL);
144 ddrawDLL = NULL;
145 }
146 width = 0;
147 height = 0;
148 }
150 bool DirectDrawDisplay::initialize()
151 {
152 CWnd *pWnd = theApp.m_pMainWnd;
154 GUID *guid = NULL;
155 if (theApp.ddrawEmulationOnly)
156 guid = (GUID *)DDCREATE_EMULATIONONLY;
158 if (theApp.pVideoDriverGUID)
159 guid = theApp.pVideoDriverGUID;
161 ddrawDLL = /**/ ::LoadLibrary("DDRAW.DLL");
162 HRESULT (WINAPI *DDrawCreateEx)(GUID *, LPVOID *, REFIID, IUnknown *);
163 if (ddrawDLL != NULL)
164 {
165 DDrawCreateEx = (HRESULT (WINAPI *)(GUID *, LPVOID *, REFIID, IUnknown *))
166 GetProcAddress(ddrawDLL, "DirectDrawCreateEx");
168 if (DDrawCreateEx == NULL)
169 {
170 directXMessage("DirectDrawCreateEx");
171 return FALSE;
172 }
173 }
174 else
175 {
176 directXMessage("DDRAW.DLL");
177 return FALSE;
178 }
180 theApp.ddrawUsingEmulationOnly = theApp.ddrawEmulationOnly;
182 HRESULT hret = DDrawCreateEx(guid,
183 (void * *)&pDirectDraw,
184 IID_IDirectDraw7,
185 NULL);
187 if (hret != DD_OK)
188 {
189 winlog("Error creating DirectDraw object %08x\n", hret);
190 if (theApp.ddrawEmulationOnly)
191 {
192 // disable emulation only setting in case of failure
193 regSetDwordValue("ddrawEmulationOnly", 0);
194 }
195 // errorMessage(myLoadString(IDS_ERROR_DISP_DRAWCREATE), hret);
196 return FALSE;
197 }
199 if (theApp.ddrawDebug)
200 {
201 DDCAPS driver;
202 DDCAPS hel;
203 ZeroMemory(&driver, sizeof(driver));
204 ZeroMemory(&hel, sizeof(hel));
205 driver.dwSize = sizeof(driver);
206 hel.dwSize = sizeof(hel);
207 pDirectDraw->GetCaps(&driver, &hel);
208 int i;
209 DWORD *p = (DWORD *)&driver;
210 for (i = 0; i < (int)driver.dwSize; i += 4)
211 winlog("Driver CAPS %2d: %08x\n", i>>2, *p++);
212 p = (DWORD *)&hel;
213 for (i = 0; i < (int)hel.dwSize; i += 4)
214 winlog("HEL CAPS %2d: %08x\n", i>>2, *p++);
215 }
217 theApp.mode320Available = false;
218 theApp.mode640Available = false;
219 theApp.mode800Available = false;
221 // check for available fullscreen modes
222 pDirectDraw->EnumDisplayModes(DDEDM_STANDARDVGAMODES, NULL, NULL, checkModesAvailable);
224 DWORD flags = DDSCL_NORMAL;
226 if (theApp.videoOption >= VIDEO_320x240)
227 flags = DDSCL_ALLOWMODEX |
228 DDSCL_ALLOWREBOOT |
229 DDSCL_EXCLUSIVE |
230 DDSCL_FULLSCREEN;
232 hret = pDirectDraw->SetCooperativeLevel(pWnd->m_hWnd, flags);
234 if (hret != DD_OK)
235 {
236 winlog("Error SetCooperativeLevel %08x\n", hret);
237 // errorMessage(myLoadString(IDS_ERROR_DISP_DRAWLEVEL), hret);
238 return FALSE;
239 }
241 if (theApp.videoOption > VIDEO_4X)
242 {
243 hret = pDirectDraw->SetDisplayMode(theApp.fsWidth,
244 theApp.fsHeight,
245 theApp.fsColorDepth,
246 0,
247 0);
248 if (hret != DD_OK)
249 {
250 winlog("Error SetDisplayMode %08x\n", hret);
251 // errorMessage(myLoadString(IDS_ERROR_DISP_DRAWSET), hret);
252 return FALSE;
253 }
254 }
256 DDSURFACEDESC2 ddsd;
257 ZeroMemory(&ddsd, sizeof(ddsd));
258 ddsd.dwSize = sizeof(ddsd);
259 ddsd.dwFlags = DDSD_CAPS;
260 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
262 if (theApp.videoOption > VIDEO_4X && theApp.tripleBuffering)
263 {
264 // setup triple buffering
265 ddsd.dwFlags |= DDSD_BACKBUFFERCOUNT;
266 ddsd.ddsCaps.dwCaps |= DDSCAPS_COMPLEX | DDSCAPS_FLIP;
267 ddsd.dwBackBufferCount = 2;
268 }
270 hret = pDirectDraw->CreateSurface(&ddsd, &ddsPrimary, NULL);
271 if (hret != DD_OK)
272 {
273 winlog("Error primary CreateSurface %08x\n", hret);
274 // errorMessage(myLoadString(IDS_ERROR_DISP_DRAWSURFACE), hret);
275 return FALSE;
276 }
278 if (theApp.ddrawDebug)
279 {
280 DDSCAPS2 caps;
281 ZeroMemory(&caps, sizeof(caps));
282 ddsPrimary->GetCaps(&caps);
284 winlog("Primary CAPS 1: %08x\n", caps.dwCaps);
285 winlog("Primary CAPS 2: %08x\n", caps.dwCaps2);
286 winlog("Primary CAPS 3: %08x\n", caps.dwCaps3);
287 winlog("Primary CAPS 4: %08x\n", caps.dwCaps4);
288 }
290 if (theApp.videoOption > VIDEO_4X && theApp.tripleBuffering)
291 {
292 DDSCAPS2 caps;
293 ZeroMemory(&caps, sizeof(caps));
294 // this gets the third surface. The front one is the primary,
295 // the second is the backbuffer and the third is the flip
296 // surface
297 caps.dwCaps = DDSCAPS_BACKBUFFER;
299 hret = ddsPrimary->GetAttachedSurface(&caps, &ddsFlip);
300 if (hret != DD_OK)
301 {
302 winlog("Failed to get attached surface %08x", hret);
303 return FALSE;
304 }
305 ddsFlip->AddRef();
306 clear();
307 }
309 // create clipper in all modes to avoid paint problems
310 // if(videoOption <= VIDEO_4X) {
311 hret = pDirectDraw->CreateClipper(0, &ddsClipper, NULL);
312 if (hret == DD_OK)
313 {
314 ddsClipper->SetHWnd(0, pWnd->m_hWnd);
315 if (theApp.videoOption > VIDEO_4X)
316 {
317 if (theApp.tripleBuffering)
318 ddsFlip->SetClipper(ddsClipper);
319 else
320 ddsPrimary->SetClipper(ddsClipper);
321 }
322 else
323 ddsPrimary->SetClipper(ddsClipper);
324 }
325 // }
327 DDPIXELFORMAT px;
329 px.dwSize = sizeof(px);
331 hret = ddsPrimary->GetPixelFormat(&px);
333 switch (px.dwRGBBitCount)
334 {
335 case 15:
336 case 16:
337 systemColorDepth = 16;
338 break;
339 case 24:
340 systemColorDepth = 24;
341 theApp.filterFunction = NULL;
342 break;
343 case 32:
344 systemColorDepth = 32;
345 break;
346 default:
347 systemMessage(
348 IDS_ERROR_DISP_COLOR,
349 "Unsupported display setting for color depth: %d bits. \nWindows desktop must be in either 16-bit, 24-bit or 32-bit mode for this program to work in window mode.",
350 px.dwRGBBitCount);
351 return FALSE;
352 }
353 theApp.updateFilter();
354 theApp.updateIFB();
356 if (failed)
357 return false;
359 pWnd->DragAcceptFiles(TRUE);
361 return true;
362 }
364 bool DirectDrawDisplay::changeRenderSize(int w, int h)
365 {
366 if (w != width || h != height)
367 {
368 if (ddsOffscreen)
369 {
370 ddsOffscreen->Release();
371 ddsOffscreen = NULL;
372 }
373 if (!initializeOffscreen(w, h))
374 {
375 failed = true;
376 return false;
377 }
378 }
379 return true;
380 }
382 bool DirectDrawDisplay::initializeOffscreen(int w, int h)
383 {
384 DDSURFACEDESC2 ddsd;
386 ZeroMemory(&ddsd, sizeof(ddsd));
387 ddsd.dwSize = sizeof(ddsd);
388 ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
389 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
390 if (theApp.ddrawUseVideoMemory)
391 ddsd.ddsCaps.dwCaps |= (DDSCAPS_LOCALVIDMEM|DDSCAPS_VIDEOMEMORY);
392 ddsd.dwWidth = w;
393 ddsd.dwHeight = h;
395 HRESULT hret = pDirectDraw->CreateSurface(&ddsd, &ddsOffscreen, NULL);
397 if (hret != DD_OK)
398 {
399 winlog("Error offscreen CreateSurface %08x\n", hret);
400 if (theApp.ddrawUseVideoMemory)
401 {
402 regSetDwordValue("ddrawUseVideoMemory", 0);
403 }
404 // errorMessage(myLoadString(IDS_ERROR_DISP_DRAWSURFACE2), hret);
405 return false;
406 }
408 if (theApp.ddrawDebug)
409 {
410 DDSCAPS2 caps;
411 ZeroMemory(&caps, sizeof(caps));
412 ddsOffscreen->GetCaps(&caps);
414 winlog("Offscreen CAPS 1: %08x\n", caps.dwCaps);
415 winlog("Offscreen CAPS 2: %08x\n", caps.dwCaps2);
416 winlog("Offscreen CAPS 3: %08x\n", caps.dwCaps3);
417 winlog("Offscreen CAPS 4: %08x\n", caps.dwCaps4);
418 }
420 DDPIXELFORMAT px;
422 px.dwSize = sizeof(px);
424 hret = ddsOffscreen->GetPixelFormat(&px);
426 if (theApp.ddrawDebug)
427 {
428 DWORD *pdword = (DWORD *)&px;
429 for (int ii = 0; ii < 8; ii++)
430 {
431 winlog("Pixel format %d %08x\n", ii, pdword[ii]);
432 }
433 }
435 switch (px.dwRGBBitCount)
436 {
437 case 15:
438 case 16:
439 systemColorDepth = 16;
440 break;
441 case 24:
442 systemColorDepth = 24;
443 theApp.filterFunction = NULL;
444 break;
445 case 32:
446 systemColorDepth = 32;
447 break;
448 default:
449 systemMessage(
450 IDS_ERROR_DISP_COLOR,
451 "Unsupported display setting for color depth: %d bits. \nWindows desktop must be in either 16-bit, 24-bit or 32-bit mode for this program to work in window mode.",
452 px.dwRGBBitCount);
453 return FALSE;
454 }
455 if (theApp.ddrawDebug)
456 {
457 winlog("R Mask: %08x\n", px.dwRBitMask);
458 winlog("G Mask: %08x\n", px.dwGBitMask);
459 winlog("B Mask: %08x\n", px.dwBBitMask);
460 }
462 systemRedShift = ffs(px.dwRBitMask);
463 systemGreenShift = ffs(px.dwGBitMask);
464 systemBlueShift = ffs(px.dwBBitMask);
466 #ifdef MMX
467 if (!theApp.disableMMX)
468 cpu_mmx = theApp.detectMMX();
469 else
470 cpu_mmx = 0;
471 #endif
473 if ((px.dwFlags&DDPF_RGB) != 0 &&
474 px.dwRBitMask == 0xF800 &&
475 px.dwGBitMask == 0x07E0 &&
476 px.dwBBitMask == 0x001F)
477 {
478 systemGreenShift++;
479 Init_2xSaI(565);
480 RGB_LOW_BITS_MASK = 0x821;
481 }
482 else if ((px.dwFlags&DDPF_RGB) != 0 &&
483 px.dwRBitMask == 0x7C00 &&
484 px.dwGBitMask == 0x03E0 &&
485 px.dwBBitMask == 0x001F)
486 {
487 Init_2xSaI(555);
488 RGB_LOW_BITS_MASK = 0x421;
489 }
490 else if ((px.dwFlags&DDPF_RGB) != 0 &&
491 px.dwRBitMask == 0x001F &&
492 px.dwGBitMask == 0x07E0 &&
493 px.dwBBitMask == 0xF800)
494 {
495 systemGreenShift++;
496 Init_2xSaI(565);
497 RGB_LOW_BITS_MASK = 0x821;
498 }
499 else if ((px.dwFlags&DDPF_RGB) != 0 &&
500 px.dwRBitMask == 0x001F &&
501 px.dwGBitMask == 0x03E0 &&
502 px.dwBBitMask == 0x7C00)
503 {
504 Init_2xSaI(555);
505 RGB_LOW_BITS_MASK = 0x421;
506 }
507 else
508 {
509 // 32-bit or 24-bit
510 if (systemColorDepth == 32 || systemColorDepth == 24)
511 {
512 systemRedShift += 3;
513 systemGreenShift += 3;
514 systemBlueShift += 3;
515 if (systemColorDepth == 32)
516 Init_2xSaI(32);
517 }
518 }
520 if (theApp.ddrawDebug)
521 {
522 winlog("R shift: %d\n", systemRedShift);
523 winlog("G shift: %d\n", systemGreenShift);
524 winlog("B shift: %d\n", systemBlueShift);
525 }
527 switch (systemColorDepth)
528 {
529 case 16:
530 {
531 for (int i = 0; i < 0x10000; i++)
532 {
533 systemColorMap16[i] = ((i & 0x1f) << systemRedShift) |
534 (((i & 0x3e0) >> 5) << systemGreenShift) |
535 (((i & 0x7c00) >> 10) << systemBlueShift);
536 }
537 break;
538 }
539 case 24:
540 case 32:
541 {
542 for (int i = 0; i < 0x10000; i++)
543 {
544 systemColorMap32[i] = ((i & 0x1f) << systemRedShift) |
545 (((i & 0x3e0) >> 5) << systemGreenShift) |
546 (((i & 0x7c00) >> 10) << systemBlueShift);
547 }
548 break;
549 }
550 }
551 width = w;
552 height = h;
553 return true;
554 }
556 void DirectDrawDisplay::clear()
557 {
558 if (theApp.videoOption <= VIDEO_4X || !theApp.tripleBuffering || ddsFlip == NULL)
559 return;
561 DDBLTFX fx;
562 ZeroMemory(&fx, sizeof(fx));
563 fx.dwSize = sizeof(fx);
564 fx.dwFillColor = 0;
565 ddsFlip->Blt(NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
566 ddsPrimary->Flip(NULL, 0);
567 ddsFlip->Blt(NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
568 ddsPrimary->Flip(NULL, 0);
569 ddsFlip->Blt(NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx);
570 ddsPrimary->Flip(NULL, 0);
571 }
573 void DirectDrawDisplay::renderMenu()
574 {
575 checkFullScreen();
576 theApp.m_pMainWnd->DrawMenuBar();
577 }
579 void DirectDrawDisplay::checkFullScreen()
580 {
581 if (theApp.tripleBuffering)
582 pDirectDraw->FlipToGDISurface();
583 }
585 void DirectDrawDisplay::render()
586 {
587 HRESULT hret;
589 if (pDirectDraw == NULL ||
590 ddsOffscreen == NULL ||
591 ddsPrimary == NULL)
592 return;
594 bool fastForward = speedup;
595 #if (defined(WIN32) && !defined(SDL))
596 if (theApp.frameSearchSkipping)
597 {
598 if (theApp.frameSearchFirstStep)
599 fastForward = true;
600 else
601 return; // don't render skipped frame search frames
602 }
603 #endif
605 DDSURFACEDESC2 ddsDesc;
607 ZeroMemory(&ddsDesc, sizeof(ddsDesc));
609 ddsDesc.dwSize = sizeof(ddsDesc);
611 hret = ddsOffscreen->Lock(NULL,
612 &ddsDesc,
613 #ifndef FINAL_VERSION
614 DDLOCK_NOSYSLOCK |
615 #endif
616 DDLOCK_WRITEONLY | DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT,
617 NULL);
619 if (hret == DDERR_SURFACELOST)
620 {
621 hret = ddsPrimary->Restore();
622 if (hret == DD_OK)
623 {
624 hret = ddsOffscreen->Restore();
626 if (hret == DD_OK)
627 {
628 hret = ddsOffscreen->Lock(NULL,
629 &ddsDesc,
630 #ifndef FINAL_VERSION
631 DDLOCK_NOSYSLOCK |
632 #endif
633 DDLOCK_WRITEONLY | DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT,
634 NULL);
635 }
636 }
637 }
639 if (hret == DD_OK)
640 {
641 if (theApp.filterFunction)
642 {
643 if (systemColorDepth == 16)
644 (*theApp.filterFunction)(pix + theApp.filterWidth * 2 + 4,
645 theApp.filterWidth * 2 + 4,
646 (u8 *)theApp.delta,
647 (u8 *)ddsDesc.lpSurface,
648 ddsDesc.lPitch,
649 theApp.filterWidth,
650 theApp.filterHeight);
651 else
652 (*theApp.filterFunction)(pix + theApp.filterWidth * 4 + 4,
653 theApp.filterWidth * 4 + 4,
654 (u8 *)theApp.delta,
655 (u8 *)ddsDesc.lpSurface,
656 ddsDesc.lPitch,
657 theApp.filterWidth,
658 theApp.filterHeight);
659 }
660 else
661 {
662 int copyX = 240;
663 int copyY = 160;
665 if (systemCartridgeType == 1)
666 {
667 if (gbBorderOn)
668 {
669 copyX = 256;
670 copyY = 224;
671 }
672 else
673 {
674 copyX = 160;
675 copyY = 144;
676 }
677 }
678 // MMX doesn't seem to be faster to copy the data
679 __asm {
680 mov eax, copyX;
681 mov ebx, copyY;
683 mov esi, pix;
684 mov edi, ddsDesc.lpSurface;
685 mov edx, ddsDesc.lPitch;
686 cmp systemColorDepth, 16;
687 jnz gbaOtherColor;
688 sub edx, eax;
689 sub edx, eax;
690 lea esi, [esi+2*eax+4];
691 shr eax, 1;
692 gbaLoop16bit:
693 mov ecx, eax;
694 repz movsd;
695 inc esi;
696 inc esi;
697 inc esi;
698 inc esi;
699 add edi, edx;
700 dec ebx;
701 jnz gbaLoop16bit;
702 jmp gbaLoopEnd;
703 gbaOtherColor:
704 cmp systemColorDepth, 32;
705 jnz gbaOtherColor2;
707 sub edx, eax;
708 sub edx, eax;
709 sub edx, eax;
710 sub edx, eax;
711 lea esi, [esi+4*eax+4];
712 gbaLoop32bit:
713 mov ecx, eax;
714 repz movsd;
715 add esi, 4;
716 add edi, edx;
717 dec ebx;
718 jnz gbaLoop32bit;
719 jmp gbaLoopEnd;
720 gbaOtherColor2:
721 lea eax, [eax+2*eax];
722 sub edx, eax;
723 gbaLoop24bit:
724 mov ecx, eax;
725 shr ecx, 2;
726 repz movsd;
727 add edi, edx;
728 dec ebx;
729 jnz gbaLoop24bit;
730 gbaLoopEnd:
731 }
732 }
733 if (theApp.showSpeed && theApp.videoOption > VIDEO_4X)
734 {
735 char buffer[30];
736 if (theApp.showSpeed == 1)
737 sprintf(buffer, "%3d%%", systemSpeed);
738 else
739 sprintf(buffer, "%3d%%(%d, %d fps)", systemSpeed,
740 systemFrameSkip,
741 theApp.showRenderedFrames);
742 if (theApp.showSpeedTransparent)
743 drawTextTransp((u8 *)ddsDesc.lpSurface,
744 ddsDesc.lPitch,
745 theApp.rect.left+10,
746 theApp.rect.bottom-10,
747 buffer);
748 else
749 drawText((u8 *)ddsDesc.lpSurface,
750 ddsDesc.lPitch,
751 theApp.rect.left+10,
752 theApp.rect.bottom-10,
753 buffer);
754 }
756 if (textMethod == 1)
757 {
758 DrawTextMessages((u8 *)ddsDesc.lpSurface, ddsDesc.lPitch, theApp.rect.left, theApp.rect.bottom);
759 }
760 }
761 else if (theApp.ddrawDebug)
762 winlog("Error during lock: %08x\n", hret);
764 hret = ddsOffscreen->Unlock(NULL);
766 if (hret == DD_OK)
767 {
768 // the correct point where to wait
769 if (theApp.vsync && !fastForward)
770 {
771 hret = pDirectDraw->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN, 0);
772 }
774 ddsOffscreen->PageLock(0);
775 if (theApp.tripleBuffering && theApp.videoOption > VIDEO_4X)
776 {
777 hret = ddsFlip->Blt(&theApp.dest, ddsOffscreen, NULL, DDBLT_WAIT, NULL);
778 if (hret == DD_OK)
779 {
780 if (theApp.menuToggle || !theApp.active)
781 {
782 pDirectDraw->FlipToGDISurface();
783 ddsPrimary->SetClipper(ddsClipper);
784 hret = ddsPrimary->Blt(&theApp.dest, ddsFlip, NULL, DDBLT_ASYNC, NULL);
785 // if using emulation only, then we have to redraw the menu
786 // everytime. It seems like a bug in DirectDraw to me as we not
787 // overwritting the menu area at all.
788 if (theApp.ddrawUsingEmulationOnly)
789 theApp.m_pMainWnd->DrawMenuBar();
790 }
791 else
792 hret = ddsPrimary->Flip(NULL, 0);
793 }
794 }
795 else
796 {
797 hret = ddsPrimary->Blt(&theApp.dest, ddsOffscreen, NULL, DDBLT_ASYNC, NULL);
799 if (hret == DDERR_SURFACELOST)
800 {
801 hret = ddsPrimary->Restore();
803 if (hret == DD_OK)
804 {
805 hret = ddsPrimary->Blt(&theApp.dest, ddsOffscreen, NULL, DDBLT_ASYNC, NULL);
806 }
807 }
808 }
809 ddsOffscreen->PageUnlock(0);
810 }
811 else if (theApp.ddrawDebug)
812 winlog("Error during unlock: %08x\n", hret);
814 bool textMessageStarted = false;
816 if (textMethod == 2)
817 {
818 HDC hdc;
820 for (int slot = 0; slot < SCREEN_MESSAGE_SLOTS; slot++)
821 {
822 if (theApp.screenMessage[slot])
823 {
824 if ((theApp.screenMessageDuration[slot] < 0 ||
825 (int)(GetTickCount() - theApp.screenMessageTime[slot]) < theApp.screenMessageDuration[slot]) &&
826 (!theApp.disableStatusMessage || slot == 1 || slot == 2))
827 {
828 if (!textMessageStarted)
829 {
830 textMessageStarted = true;
831 ddsPrimary->SetClipper(ddsClipper);
832 ddsPrimary->GetDC(&hdc);
833 SetBkMode(hdc, TRANSPARENT);
834 SetTextColor(hdc, textColor != 7 ? RGB(0, 0, 0) : RGB(255, 255, 255));
835 }
837 if (outlinedText)
838 {
839 // draw black outline
840 const static int xd [8] = {-1, 0, 1, 1, 1, 0, -1, -1};
841 const static int yd [8] = {-1, -1, -1, 0, 1, 1, 1, 0};
842 for (int i = 0; i < 8; i++)
843 {
844 TextOut(hdc,
845 theApp.dest.left+10+xd[i],
846 theApp.dest.bottom - 20*(slot+1)+yd[i],
847 theApp.screenMessageBuffer[slot],
848 strlen(theApp.screenMessageBuffer[slot]));
849 }
850 }
851 }
852 else
853 {
854 theApp.screenMessage[slot] = false;
855 }
856 }
857 }
859 if (textMessageStarted)
860 {
861 COLORREF color;
862 switch (textColor)
863 {
864 case 0:
865 color = RGB(255, 255, 255); break;
866 case 1:
867 color = RGB(255, 0, 0); break;
868 case 2:
869 color = RGB(255, 255, 0); break;
870 case 3:
871 color = RGB(0, 255, 0); break;
872 case 4:
873 color = RGB(0, 255, 255); break;
874 case 5:
875 color = RGB(0, 0, 255); break;
876 case 6:
877 color = RGB(255, 0, 255); break;
878 case 7:
879 color = RGB(0, 0, 0); break;
880 }
881 SetTextColor(hdc, color);
883 // draw center text
884 for (int slot = 0; slot < SCREEN_MESSAGE_SLOTS; slot++)
885 {
886 if (theApp.screenMessage[slot])
887 {
888 if ((theApp.screenMessageDuration[slot] < 0 ||
889 (int)(GetTickCount() - theApp.screenMessageTime[slot]) < theApp.screenMessageDuration[slot]) &&
890 (!theApp.disableStatusMessage || slot == 1 || slot == 2))
891 {
892 TextOut(hdc, theApp.dest.left+10, theApp.dest.bottom - 20*(slot+1), theApp.screenMessageBuffer[slot],
893 strlen(theApp.screenMessageBuffer[slot]));
894 }
895 }
896 }
897 }
899 if (textMessageStarted)
900 {
901 ddsPrimary->ReleaseDC(hdc);
902 }
903 }
905 if (hret != DD_OK)
906 {
907 if (theApp.ddrawDebug)
908 winlog("Error on update screen: %08x\n", hret);
909 }
910 }
912 int DirectDrawDisplay::selectFullScreenMode(GUID **pGUID)
913 {
914 return winVideoModeSelect(theApp.m_pMainWnd, pGUID);
915 }
917 IDisplay *newDirectDrawDisplay()
918 {
919 return new DirectDrawDisplay();
920 }