Mercurial > vba-linux
comparison src/win32/DirectDraw.cpp @ 1:f9f4f1b99eed
importing src directory
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 10:31:27 -0600 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
0:8ced16adf2e1 | 1:f9f4f1b99eed |
---|---|
1 #include "stdafx.h" | |
2 | |
3 #define DIRECTDRAW_VERSION 0x0700 | |
4 #include "ddraw.h" | |
5 | |
6 #include "resource.h" | |
7 #include "MainWnd.h" | |
8 #include "Reg.h" | |
9 #include "VBA.h" | |
10 | |
11 #include "../common/System.h" | |
12 #include "../gba/GBAGlobals.h" | |
13 #include "../gb/gbGlobals.h" | |
14 #include "../common/Text.h" | |
15 #include "../version.h" | |
16 | |
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 * *); | |
23 | |
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; | |
36 | |
37 bool initializeOffscreen(int w, int h); | |
38 public: | |
39 DirectDrawDisplay(); | |
40 virtual ~DirectDrawDisplay(); | |
41 | |
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 }; | |
53 | |
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 } | |
76 | |
77 static int ffs(UINT mask) | |
78 { | |
79 int m = 0; | |
80 if (mask) | |
81 { | |
82 while (!(mask & (1 << m))) | |
83 m++; | |
84 | |
85 return (m); | |
86 } | |
87 | |
88 return (0); | |
89 } | |
90 | |
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 } | |
103 | |
104 DirectDrawDisplay::~DirectDrawDisplay() | |
105 { | |
106 cleanup(); | |
107 } | |
108 | |
109 void DirectDrawDisplay::cleanup() | |
110 { | |
111 if (pDirectDraw != NULL) | |
112 { | |
113 if (ddsClipper != NULL) | |
114 { | |
115 ddsClipper->Release(); | |
116 ddsClipper = NULL; | |
117 } | |
118 | |
119 if (ddsFlip != NULL) | |
120 { | |
121 ddsFlip->Release(); | |
122 ddsFlip = NULL; | |
123 } | |
124 | |
125 if (ddsOffscreen != NULL) | |
126 { | |
127 ddsOffscreen->Release(); | |
128 ddsOffscreen = NULL; | |
129 } | |
130 | |
131 if (ddsPrimary != NULL) | |
132 { | |
133 ddsPrimary->Release(); | |
134 ddsPrimary = NULL; | |
135 } | |
136 | |
137 pDirectDraw->Release(); | |
138 pDirectDraw = NULL; | |
139 } | |
140 | |
141 if (ddrawDLL != NULL) | |
142 { | |
143 /**/ ::FreeLibrary(ddrawDLL); | |
144 ddrawDLL = NULL; | |
145 } | |
146 width = 0; | |
147 height = 0; | |
148 } | |
149 | |
150 bool DirectDrawDisplay::initialize() | |
151 { | |
152 CWnd *pWnd = theApp.m_pMainWnd; | |
153 | |
154 GUID *guid = NULL; | |
155 if (theApp.ddrawEmulationOnly) | |
156 guid = (GUID *)DDCREATE_EMULATIONONLY; | |
157 | |
158 if (theApp.pVideoDriverGUID) | |
159 guid = theApp.pVideoDriverGUID; | |
160 | |
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"); | |
167 | |
168 if (DDrawCreateEx == NULL) | |
169 { | |
170 directXMessage("DirectDrawCreateEx"); | |
171 return FALSE; | |
172 } | |
173 } | |
174 else | |
175 { | |
176 directXMessage("DDRAW.DLL"); | |
177 return FALSE; | |
178 } | |
179 | |
180 theApp.ddrawUsingEmulationOnly = theApp.ddrawEmulationOnly; | |
181 | |
182 HRESULT hret = DDrawCreateEx(guid, | |
183 (void * *)&pDirectDraw, | |
184 IID_IDirectDraw7, | |
185 NULL); | |
186 | |
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 } | |
198 | |
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 } | |
216 | |
217 theApp.mode320Available = false; | |
218 theApp.mode640Available = false; | |
219 theApp.mode800Available = false; | |
220 | |
221 // check for available fullscreen modes | |
222 pDirectDraw->EnumDisplayModes(DDEDM_STANDARDVGAMODES, NULL, NULL, checkModesAvailable); | |
223 | |
224 DWORD flags = DDSCL_NORMAL; | |
225 | |
226 if (theApp.videoOption >= VIDEO_320x240) | |
227 flags = DDSCL_ALLOWMODEX | | |
228 DDSCL_ALLOWREBOOT | | |
229 DDSCL_EXCLUSIVE | | |
230 DDSCL_FULLSCREEN; | |
231 | |
232 hret = pDirectDraw->SetCooperativeLevel(pWnd->m_hWnd, flags); | |
233 | |
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 } | |
240 | |
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 } | |
255 | |
256 DDSURFACEDESC2 ddsd; | |
257 ZeroMemory(&ddsd, sizeof(ddsd)); | |
258 ddsd.dwSize = sizeof(ddsd); | |
259 ddsd.dwFlags = DDSD_CAPS; | |
260 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; | |
261 | |
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 } | |
269 | |
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 } | |
277 | |
278 if (theApp.ddrawDebug) | |
279 { | |
280 DDSCAPS2 caps; | |
281 ZeroMemory(&caps, sizeof(caps)); | |
282 ddsPrimary->GetCaps(&caps); | |
283 | |
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 } | |
289 | |
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; | |
298 | |
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 } | |
308 | |
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 // } | |
326 | |
327 DDPIXELFORMAT px; | |
328 | |
329 px.dwSize = sizeof(px); | |
330 | |
331 hret = ddsPrimary->GetPixelFormat(&px); | |
332 | |
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(); | |
355 | |
356 if (failed) | |
357 return false; | |
358 | |
359 pWnd->DragAcceptFiles(TRUE); | |
360 | |
361 return true; | |
362 } | |
363 | |
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 } | |
381 | |
382 bool DirectDrawDisplay::initializeOffscreen(int w, int h) | |
383 { | |
384 DDSURFACEDESC2 ddsd; | |
385 | |
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; | |
394 | |
395 HRESULT hret = pDirectDraw->CreateSurface(&ddsd, &ddsOffscreen, NULL); | |
396 | |
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 } | |
407 | |
408 if (theApp.ddrawDebug) | |
409 { | |
410 DDSCAPS2 caps; | |
411 ZeroMemory(&caps, sizeof(caps)); | |
412 ddsOffscreen->GetCaps(&caps); | |
413 | |
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 } | |
419 | |
420 DDPIXELFORMAT px; | |
421 | |
422 px.dwSize = sizeof(px); | |
423 | |
424 hret = ddsOffscreen->GetPixelFormat(&px); | |
425 | |
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 } | |
434 | |
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 } | |
461 | |
462 systemRedShift = ffs(px.dwRBitMask); | |
463 systemGreenShift = ffs(px.dwGBitMask); | |
464 systemBlueShift = ffs(px.dwBBitMask); | |
465 | |
466 #ifdef MMX | |
467 if (!theApp.disableMMX) | |
468 cpu_mmx = theApp.detectMMX(); | |
469 else | |
470 cpu_mmx = 0; | |
471 #endif | |
472 | |
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 } | |
519 | |
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 } | |
526 | |
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 } | |
555 | |
556 void DirectDrawDisplay::clear() | |
557 { | |
558 if (theApp.videoOption <= VIDEO_4X || !theApp.tripleBuffering || ddsFlip == NULL) | |
559 return; | |
560 | |
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 } | |
572 | |
573 void DirectDrawDisplay::renderMenu() | |
574 { | |
575 checkFullScreen(); | |
576 theApp.m_pMainWnd->DrawMenuBar(); | |
577 } | |
578 | |
579 void DirectDrawDisplay::checkFullScreen() | |
580 { | |
581 if (theApp.tripleBuffering) | |
582 pDirectDraw->FlipToGDISurface(); | |
583 } | |
584 | |
585 void DirectDrawDisplay::render() | |
586 { | |
587 HRESULT hret; | |
588 | |
589 if (pDirectDraw == NULL || | |
590 ddsOffscreen == NULL || | |
591 ddsPrimary == NULL) | |
592 return; | |
593 | |
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 | |
604 | |
605 DDSURFACEDESC2 ddsDesc; | |
606 | |
607 ZeroMemory(&ddsDesc, sizeof(ddsDesc)); | |
608 | |
609 ddsDesc.dwSize = sizeof(ddsDesc); | |
610 | |
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); | |
618 | |
619 if (hret == DDERR_SURFACELOST) | |
620 { | |
621 hret = ddsPrimary->Restore(); | |
622 if (hret == DD_OK) | |
623 { | |
624 hret = ddsOffscreen->Restore(); | |
625 | |
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 } | |
638 | |
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; | |
664 | |
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; | |
682 | |
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; | |
706 | |
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 } | |
755 | |
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); | |
763 | |
764 hret = ddsOffscreen->Unlock(NULL); | |
765 | |
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 } | |
773 | |
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); | |
798 | |
799 if (hret == DDERR_SURFACELOST) | |
800 { | |
801 hret = ddsPrimary->Restore(); | |
802 | |
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); | |
813 | |
814 bool textMessageStarted = false; | |
815 | |
816 if (textMethod == 2) | |
817 { | |
818 HDC hdc; | |
819 | |
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 } | |
836 | |
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 } | |
858 | |
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); | |
882 | |
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 } | |
898 | |
899 if (textMessageStarted) | |
900 { | |
901 ddsPrimary->ReleaseDC(hdc); | |
902 } | |
903 } | |
904 | |
905 if (hret != DD_OK) | |
906 { | |
907 if (theApp.ddrawDebug) | |
908 winlog("Error on update screen: %08x\n", hret); | |
909 } | |
910 } | |
911 | |
912 int DirectDrawDisplay::selectFullScreenMode(GUID **pGUID) | |
913 { | |
914 return winVideoModeSelect(theApp.m_pMainWnd, pGUID); | |
915 } | |
916 | |
917 IDisplay *newDirectDrawDisplay() | |
918 { | |
919 return new DirectDrawDisplay(); | |
920 } | |
921 |