Mercurial > vba-clojure
diff 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 |
line wrap: on
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/win32/DirectDraw.cpp Sat Mar 03 10:31:27 2012 -0600 1.3 @@ -0,0 +1,921 @@ 1.4 +#include "stdafx.h" 1.5 + 1.6 +#define DIRECTDRAW_VERSION 0x0700 1.7 +#include "ddraw.h" 1.8 + 1.9 +#include "resource.h" 1.10 +#include "MainWnd.h" 1.11 +#include "Reg.h" 1.12 +#include "VBA.h" 1.13 + 1.14 +#include "../common/System.h" 1.15 +#include "../gba/GBAGlobals.h" 1.16 +#include "../gb/gbGlobals.h" 1.17 +#include "../common/Text.h" 1.18 +#include "../version.h" 1.19 + 1.20 +extern u32 RGB_LOW_BITS_MASK; 1.21 +extern int systemSpeed; 1.22 +extern int Init_2xSaI(u32); 1.23 +extern void directXMessage(const char *); 1.24 +extern void winlog(const char *, ...); 1.25 +extern int winVideoModeSelect(CWnd *, GUID * *); 1.26 + 1.27 +class DirectDrawDisplay : public IDisplay 1.28 +{ 1.29 +private: 1.30 + HINSTANCE ddrawDLL; 1.31 + LPDIRECTDRAW7 pDirectDraw; 1.32 + LPDIRECTDRAWSURFACE7 ddsPrimary; 1.33 + LPDIRECTDRAWSURFACE7 ddsOffscreen; 1.34 + LPDIRECTDRAWSURFACE7 ddsFlip; 1.35 + LPDIRECTDRAWCLIPPER ddsClipper; 1.36 + int width; 1.37 + int height; 1.38 + bool failed; 1.39 + 1.40 + bool initializeOffscreen(int w, int h); 1.41 +public: 1.42 + DirectDrawDisplay(); 1.43 + virtual ~DirectDrawDisplay(); 1.44 + 1.45 + virtual bool initialize(); 1.46 + virtual void cleanup(); 1.47 + virtual void render(); 1.48 + virtual void checkFullScreen(); 1.49 + virtual void renderMenu(); 1.50 + virtual void clear(); 1.51 + virtual bool changeRenderSize(int w, int h); 1.52 + virtual DISPLAY_TYPE getType() { return DIRECT_DRAW; }; 1.53 + virtual void setOption(const char *, int) {} 1.54 + virtual int selectFullScreenMode(GUID * *); 1.55 +}; 1.56 + 1.57 +static HRESULT WINAPI checkModesAvailable(LPDDSURFACEDESC2 surf, LPVOID lpContext) 1.58 +{ 1.59 + if (surf->dwWidth == 320 && 1.60 + surf->dwHeight == 240 && 1.61 + surf->ddpfPixelFormat.dwRGBBitCount == 16) 1.62 + { 1.63 + theApp.mode320Available = TRUE; 1.64 + } 1.65 + if (surf->dwWidth == 640 && 1.66 + surf->dwHeight == 480 && 1.67 + surf->ddpfPixelFormat.dwRGBBitCount == 16) 1.68 + { 1.69 + theApp.mode640Available = TRUE; 1.70 + } 1.71 + if (surf->dwWidth == 800 && 1.72 + surf->dwHeight == 600 && 1.73 + surf->ddpfPixelFormat.dwRGBBitCount == 16) 1.74 + { 1.75 + theApp.mode800Available = TRUE; 1.76 + } 1.77 + return DDENUMRET_OK; 1.78 +} 1.79 + 1.80 +static int ffs(UINT mask) 1.81 +{ 1.82 + int m = 0; 1.83 + if (mask) 1.84 + { 1.85 + while (!(mask & (1 << m))) 1.86 + m++; 1.87 + 1.88 + return (m); 1.89 + } 1.90 + 1.91 + return (0); 1.92 +} 1.93 + 1.94 +DirectDrawDisplay::DirectDrawDisplay() 1.95 +{ 1.96 + pDirectDraw = NULL; 1.97 + ddsPrimary = NULL; 1.98 + ddsOffscreen = NULL; 1.99 + ddsFlip = NULL; 1.100 + ddsClipper = NULL; 1.101 + ddrawDLL = NULL; 1.102 + width = 0; 1.103 + height = 0; 1.104 + failed = false; 1.105 +} 1.106 + 1.107 +DirectDrawDisplay::~DirectDrawDisplay() 1.108 +{ 1.109 + cleanup(); 1.110 +} 1.111 + 1.112 +void DirectDrawDisplay::cleanup() 1.113 +{ 1.114 + if (pDirectDraw != NULL) 1.115 + { 1.116 + if (ddsClipper != NULL) 1.117 + { 1.118 + ddsClipper->Release(); 1.119 + ddsClipper = NULL; 1.120 + } 1.121 + 1.122 + if (ddsFlip != NULL) 1.123 + { 1.124 + ddsFlip->Release(); 1.125 + ddsFlip = NULL; 1.126 + } 1.127 + 1.128 + if (ddsOffscreen != NULL) 1.129 + { 1.130 + ddsOffscreen->Release(); 1.131 + ddsOffscreen = NULL; 1.132 + } 1.133 + 1.134 + if (ddsPrimary != NULL) 1.135 + { 1.136 + ddsPrimary->Release(); 1.137 + ddsPrimary = NULL; 1.138 + } 1.139 + 1.140 + pDirectDraw->Release(); 1.141 + pDirectDraw = NULL; 1.142 + } 1.143 + 1.144 + if (ddrawDLL != NULL) 1.145 + { 1.146 + /**/ ::FreeLibrary(ddrawDLL); 1.147 + ddrawDLL = NULL; 1.148 + } 1.149 + width = 0; 1.150 + height = 0; 1.151 +} 1.152 + 1.153 +bool DirectDrawDisplay::initialize() 1.154 +{ 1.155 + CWnd *pWnd = theApp.m_pMainWnd; 1.156 + 1.157 + GUID *guid = NULL; 1.158 + if (theApp.ddrawEmulationOnly) 1.159 + guid = (GUID *)DDCREATE_EMULATIONONLY; 1.160 + 1.161 + if (theApp.pVideoDriverGUID) 1.162 + guid = theApp.pVideoDriverGUID; 1.163 + 1.164 + ddrawDLL = /**/ ::LoadLibrary("DDRAW.DLL"); 1.165 + HRESULT (WINAPI *DDrawCreateEx)(GUID *, LPVOID *, REFIID, IUnknown *); 1.166 + if (ddrawDLL != NULL) 1.167 + { 1.168 + DDrawCreateEx = (HRESULT (WINAPI *)(GUID *, LPVOID *, REFIID, IUnknown *)) 1.169 + GetProcAddress(ddrawDLL, "DirectDrawCreateEx"); 1.170 + 1.171 + if (DDrawCreateEx == NULL) 1.172 + { 1.173 + directXMessage("DirectDrawCreateEx"); 1.174 + return FALSE; 1.175 + } 1.176 + } 1.177 + else 1.178 + { 1.179 + directXMessage("DDRAW.DLL"); 1.180 + return FALSE; 1.181 + } 1.182 + 1.183 + theApp.ddrawUsingEmulationOnly = theApp.ddrawEmulationOnly; 1.184 + 1.185 + HRESULT hret = DDrawCreateEx(guid, 1.186 + (void * *)&pDirectDraw, 1.187 + IID_IDirectDraw7, 1.188 + NULL); 1.189 + 1.190 + if (hret != DD_OK) 1.191 + { 1.192 + winlog("Error creating DirectDraw object %08x\n", hret); 1.193 + if (theApp.ddrawEmulationOnly) 1.194 + { 1.195 + // disable emulation only setting in case of failure 1.196 + regSetDwordValue("ddrawEmulationOnly", 0); 1.197 + } 1.198 + // errorMessage(myLoadString(IDS_ERROR_DISP_DRAWCREATE), hret); 1.199 + return FALSE; 1.200 + } 1.201 + 1.202 + if (theApp.ddrawDebug) 1.203 + { 1.204 + DDCAPS driver; 1.205 + DDCAPS hel; 1.206 + ZeroMemory(&driver, sizeof(driver)); 1.207 + ZeroMemory(&hel, sizeof(hel)); 1.208 + driver.dwSize = sizeof(driver); 1.209 + hel.dwSize = sizeof(hel); 1.210 + pDirectDraw->GetCaps(&driver, &hel); 1.211 + int i; 1.212 + DWORD *p = (DWORD *)&driver; 1.213 + for (i = 0; i < (int)driver.dwSize; i += 4) 1.214 + winlog("Driver CAPS %2d: %08x\n", i>>2, *p++); 1.215 + p = (DWORD *)&hel; 1.216 + for (i = 0; i < (int)hel.dwSize; i += 4) 1.217 + winlog("HEL CAPS %2d: %08x\n", i>>2, *p++); 1.218 + } 1.219 + 1.220 + theApp.mode320Available = false; 1.221 + theApp.mode640Available = false; 1.222 + theApp.mode800Available = false; 1.223 + 1.224 + // check for available fullscreen modes 1.225 + pDirectDraw->EnumDisplayModes(DDEDM_STANDARDVGAMODES, NULL, NULL, checkModesAvailable); 1.226 + 1.227 + DWORD flags = DDSCL_NORMAL; 1.228 + 1.229 + if (theApp.videoOption >= VIDEO_320x240) 1.230 + flags = DDSCL_ALLOWMODEX | 1.231 + DDSCL_ALLOWREBOOT | 1.232 + DDSCL_EXCLUSIVE | 1.233 + DDSCL_FULLSCREEN; 1.234 + 1.235 + hret = pDirectDraw->SetCooperativeLevel(pWnd->m_hWnd, flags); 1.236 + 1.237 + if (hret != DD_OK) 1.238 + { 1.239 + winlog("Error SetCooperativeLevel %08x\n", hret); 1.240 + // errorMessage(myLoadString(IDS_ERROR_DISP_DRAWLEVEL), hret); 1.241 + return FALSE; 1.242 + } 1.243 + 1.244 + if (theApp.videoOption > VIDEO_4X) 1.245 + { 1.246 + hret = pDirectDraw->SetDisplayMode(theApp.fsWidth, 1.247 + theApp.fsHeight, 1.248 + theApp.fsColorDepth, 1.249 + 0, 1.250 + 0); 1.251 + if (hret != DD_OK) 1.252 + { 1.253 + winlog("Error SetDisplayMode %08x\n", hret); 1.254 + // errorMessage(myLoadString(IDS_ERROR_DISP_DRAWSET), hret); 1.255 + return FALSE; 1.256 + } 1.257 + } 1.258 + 1.259 + DDSURFACEDESC2 ddsd; 1.260 + ZeroMemory(&ddsd, sizeof(ddsd)); 1.261 + ddsd.dwSize = sizeof(ddsd); 1.262 + ddsd.dwFlags = DDSD_CAPS; 1.263 + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; 1.264 + 1.265 + if (theApp.videoOption > VIDEO_4X && theApp.tripleBuffering) 1.266 + { 1.267 + // setup triple buffering 1.268 + ddsd.dwFlags |= DDSD_BACKBUFFERCOUNT; 1.269 + ddsd.ddsCaps.dwCaps |= DDSCAPS_COMPLEX | DDSCAPS_FLIP; 1.270 + ddsd.dwBackBufferCount = 2; 1.271 + } 1.272 + 1.273 + hret = pDirectDraw->CreateSurface(&ddsd, &ddsPrimary, NULL); 1.274 + if (hret != DD_OK) 1.275 + { 1.276 + winlog("Error primary CreateSurface %08x\n", hret); 1.277 + // errorMessage(myLoadString(IDS_ERROR_DISP_DRAWSURFACE), hret); 1.278 + return FALSE; 1.279 + } 1.280 + 1.281 + if (theApp.ddrawDebug) 1.282 + { 1.283 + DDSCAPS2 caps; 1.284 + ZeroMemory(&caps, sizeof(caps)); 1.285 + ddsPrimary->GetCaps(&caps); 1.286 + 1.287 + winlog("Primary CAPS 1: %08x\n", caps.dwCaps); 1.288 + winlog("Primary CAPS 2: %08x\n", caps.dwCaps2); 1.289 + winlog("Primary CAPS 3: %08x\n", caps.dwCaps3); 1.290 + winlog("Primary CAPS 4: %08x\n", caps.dwCaps4); 1.291 + } 1.292 + 1.293 + if (theApp.videoOption > VIDEO_4X && theApp.tripleBuffering) 1.294 + { 1.295 + DDSCAPS2 caps; 1.296 + ZeroMemory(&caps, sizeof(caps)); 1.297 + // this gets the third surface. The front one is the primary, 1.298 + // the second is the backbuffer and the third is the flip 1.299 + // surface 1.300 + caps.dwCaps = DDSCAPS_BACKBUFFER; 1.301 + 1.302 + hret = ddsPrimary->GetAttachedSurface(&caps, &ddsFlip); 1.303 + if (hret != DD_OK) 1.304 + { 1.305 + winlog("Failed to get attached surface %08x", hret); 1.306 + return FALSE; 1.307 + } 1.308 + ddsFlip->AddRef(); 1.309 + clear(); 1.310 + } 1.311 + 1.312 + // create clipper in all modes to avoid paint problems 1.313 + // if(videoOption <= VIDEO_4X) { 1.314 + hret = pDirectDraw->CreateClipper(0, &ddsClipper, NULL); 1.315 + if (hret == DD_OK) 1.316 + { 1.317 + ddsClipper->SetHWnd(0, pWnd->m_hWnd); 1.318 + if (theApp.videoOption > VIDEO_4X) 1.319 + { 1.320 + if (theApp.tripleBuffering) 1.321 + ddsFlip->SetClipper(ddsClipper); 1.322 + else 1.323 + ddsPrimary->SetClipper(ddsClipper); 1.324 + } 1.325 + else 1.326 + ddsPrimary->SetClipper(ddsClipper); 1.327 + } 1.328 + // } 1.329 + 1.330 + DDPIXELFORMAT px; 1.331 + 1.332 + px.dwSize = sizeof(px); 1.333 + 1.334 + hret = ddsPrimary->GetPixelFormat(&px); 1.335 + 1.336 + switch (px.dwRGBBitCount) 1.337 + { 1.338 + case 15: 1.339 + case 16: 1.340 + systemColorDepth = 16; 1.341 + break; 1.342 + case 24: 1.343 + systemColorDepth = 24; 1.344 + theApp.filterFunction = NULL; 1.345 + break; 1.346 + case 32: 1.347 + systemColorDepth = 32; 1.348 + break; 1.349 + default: 1.350 + systemMessage( 1.351 + IDS_ERROR_DISP_COLOR, 1.352 + "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.", 1.353 + px.dwRGBBitCount); 1.354 + return FALSE; 1.355 + } 1.356 + theApp.updateFilter(); 1.357 + theApp.updateIFB(); 1.358 + 1.359 + if (failed) 1.360 + return false; 1.361 + 1.362 + pWnd->DragAcceptFiles(TRUE); 1.363 + 1.364 + return true; 1.365 +} 1.366 + 1.367 +bool DirectDrawDisplay::changeRenderSize(int w, int h) 1.368 +{ 1.369 + if (w != width || h != height) 1.370 + { 1.371 + if (ddsOffscreen) 1.372 + { 1.373 + ddsOffscreen->Release(); 1.374 + ddsOffscreen = NULL; 1.375 + } 1.376 + if (!initializeOffscreen(w, h)) 1.377 + { 1.378 + failed = true; 1.379 + return false; 1.380 + } 1.381 + } 1.382 + return true; 1.383 +} 1.384 + 1.385 +bool DirectDrawDisplay::initializeOffscreen(int w, int h) 1.386 +{ 1.387 + DDSURFACEDESC2 ddsd; 1.388 + 1.389 + ZeroMemory(&ddsd, sizeof(ddsd)); 1.390 + ddsd.dwSize = sizeof(ddsd); 1.391 + ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; 1.392 + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; 1.393 + if (theApp.ddrawUseVideoMemory) 1.394 + ddsd.ddsCaps.dwCaps |= (DDSCAPS_LOCALVIDMEM|DDSCAPS_VIDEOMEMORY); 1.395 + ddsd.dwWidth = w; 1.396 + ddsd.dwHeight = h; 1.397 + 1.398 + HRESULT hret = pDirectDraw->CreateSurface(&ddsd, &ddsOffscreen, NULL); 1.399 + 1.400 + if (hret != DD_OK) 1.401 + { 1.402 + winlog("Error offscreen CreateSurface %08x\n", hret); 1.403 + if (theApp.ddrawUseVideoMemory) 1.404 + { 1.405 + regSetDwordValue("ddrawUseVideoMemory", 0); 1.406 + } 1.407 + // errorMessage(myLoadString(IDS_ERROR_DISP_DRAWSURFACE2), hret); 1.408 + return false; 1.409 + } 1.410 + 1.411 + if (theApp.ddrawDebug) 1.412 + { 1.413 + DDSCAPS2 caps; 1.414 + ZeroMemory(&caps, sizeof(caps)); 1.415 + ddsOffscreen->GetCaps(&caps); 1.416 + 1.417 + winlog("Offscreen CAPS 1: %08x\n", caps.dwCaps); 1.418 + winlog("Offscreen CAPS 2: %08x\n", caps.dwCaps2); 1.419 + winlog("Offscreen CAPS 3: %08x\n", caps.dwCaps3); 1.420 + winlog("Offscreen CAPS 4: %08x\n", caps.dwCaps4); 1.421 + } 1.422 + 1.423 + DDPIXELFORMAT px; 1.424 + 1.425 + px.dwSize = sizeof(px); 1.426 + 1.427 + hret = ddsOffscreen->GetPixelFormat(&px); 1.428 + 1.429 + if (theApp.ddrawDebug) 1.430 + { 1.431 + DWORD *pdword = (DWORD *)&px; 1.432 + for (int ii = 0; ii < 8; ii++) 1.433 + { 1.434 + winlog("Pixel format %d %08x\n", ii, pdword[ii]); 1.435 + } 1.436 + } 1.437 + 1.438 + switch (px.dwRGBBitCount) 1.439 + { 1.440 + case 15: 1.441 + case 16: 1.442 + systemColorDepth = 16; 1.443 + break; 1.444 + case 24: 1.445 + systemColorDepth = 24; 1.446 + theApp.filterFunction = NULL; 1.447 + break; 1.448 + case 32: 1.449 + systemColorDepth = 32; 1.450 + break; 1.451 + default: 1.452 + systemMessage( 1.453 + IDS_ERROR_DISP_COLOR, 1.454 + "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.", 1.455 + px.dwRGBBitCount); 1.456 + return FALSE; 1.457 + } 1.458 + if (theApp.ddrawDebug) 1.459 + { 1.460 + winlog("R Mask: %08x\n", px.dwRBitMask); 1.461 + winlog("G Mask: %08x\n", px.dwGBitMask); 1.462 + winlog("B Mask: %08x\n", px.dwBBitMask); 1.463 + } 1.464 + 1.465 + systemRedShift = ffs(px.dwRBitMask); 1.466 + systemGreenShift = ffs(px.dwGBitMask); 1.467 + systemBlueShift = ffs(px.dwBBitMask); 1.468 + 1.469 +#ifdef MMX 1.470 + if (!theApp.disableMMX) 1.471 + cpu_mmx = theApp.detectMMX(); 1.472 + else 1.473 + cpu_mmx = 0; 1.474 +#endif 1.475 + 1.476 + if ((px.dwFlags&DDPF_RGB) != 0 && 1.477 + px.dwRBitMask == 0xF800 && 1.478 + px.dwGBitMask == 0x07E0 && 1.479 + px.dwBBitMask == 0x001F) 1.480 + { 1.481 + systemGreenShift++; 1.482 + Init_2xSaI(565); 1.483 + RGB_LOW_BITS_MASK = 0x821; 1.484 + } 1.485 + else if ((px.dwFlags&DDPF_RGB) != 0 && 1.486 + px.dwRBitMask == 0x7C00 && 1.487 + px.dwGBitMask == 0x03E0 && 1.488 + px.dwBBitMask == 0x001F) 1.489 + { 1.490 + Init_2xSaI(555); 1.491 + RGB_LOW_BITS_MASK = 0x421; 1.492 + } 1.493 + else if ((px.dwFlags&DDPF_RGB) != 0 && 1.494 + px.dwRBitMask == 0x001F && 1.495 + px.dwGBitMask == 0x07E0 && 1.496 + px.dwBBitMask == 0xF800) 1.497 + { 1.498 + systemGreenShift++; 1.499 + Init_2xSaI(565); 1.500 + RGB_LOW_BITS_MASK = 0x821; 1.501 + } 1.502 + else if ((px.dwFlags&DDPF_RGB) != 0 && 1.503 + px.dwRBitMask == 0x001F && 1.504 + px.dwGBitMask == 0x03E0 && 1.505 + px.dwBBitMask == 0x7C00) 1.506 + { 1.507 + Init_2xSaI(555); 1.508 + RGB_LOW_BITS_MASK = 0x421; 1.509 + } 1.510 + else 1.511 + { 1.512 + // 32-bit or 24-bit 1.513 + if (systemColorDepth == 32 || systemColorDepth == 24) 1.514 + { 1.515 + systemRedShift += 3; 1.516 + systemGreenShift += 3; 1.517 + systemBlueShift += 3; 1.518 + if (systemColorDepth == 32) 1.519 + Init_2xSaI(32); 1.520 + } 1.521 + } 1.522 + 1.523 + if (theApp.ddrawDebug) 1.524 + { 1.525 + winlog("R shift: %d\n", systemRedShift); 1.526 + winlog("G shift: %d\n", systemGreenShift); 1.527 + winlog("B shift: %d\n", systemBlueShift); 1.528 + } 1.529 + 1.530 + switch (systemColorDepth) 1.531 + { 1.532 + case 16: 1.533 + { 1.534 + for (int i = 0; i < 0x10000; i++) 1.535 + { 1.536 + systemColorMap16[i] = ((i & 0x1f) << systemRedShift) | 1.537 + (((i & 0x3e0) >> 5) << systemGreenShift) | 1.538 + (((i & 0x7c00) >> 10) << systemBlueShift); 1.539 + } 1.540 + break; 1.541 + } 1.542 + case 24: 1.543 + case 32: 1.544 + { 1.545 + for (int i = 0; i < 0x10000; i++) 1.546 + { 1.547 + systemColorMap32[i] = ((i & 0x1f) << systemRedShift) | 1.548 + (((i & 0x3e0) >> 5) << systemGreenShift) | 1.549 + (((i & 0x7c00) >> 10) << systemBlueShift); 1.550 + } 1.551 + break; 1.552 + } 1.553 + } 1.554 + width = w; 1.555 + height = h; 1.556 + return true; 1.557 +} 1.558 + 1.559 +void DirectDrawDisplay::clear() 1.560 +{ 1.561 + if (theApp.videoOption <= VIDEO_4X || !theApp.tripleBuffering || ddsFlip == NULL) 1.562 + return; 1.563 + 1.564 + DDBLTFX fx; 1.565 + ZeroMemory(&fx, sizeof(fx)); 1.566 + fx.dwSize = sizeof(fx); 1.567 + fx.dwFillColor = 0; 1.568 + ddsFlip->Blt(NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx); 1.569 + ddsPrimary->Flip(NULL, 0); 1.570 + ddsFlip->Blt(NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx); 1.571 + ddsPrimary->Flip(NULL, 0); 1.572 + ddsFlip->Blt(NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx); 1.573 + ddsPrimary->Flip(NULL, 0); 1.574 +} 1.575 + 1.576 +void DirectDrawDisplay::renderMenu() 1.577 +{ 1.578 + checkFullScreen(); 1.579 + theApp.m_pMainWnd->DrawMenuBar(); 1.580 +} 1.581 + 1.582 +void DirectDrawDisplay::checkFullScreen() 1.583 +{ 1.584 + if (theApp.tripleBuffering) 1.585 + pDirectDraw->FlipToGDISurface(); 1.586 +} 1.587 + 1.588 +void DirectDrawDisplay::render() 1.589 +{ 1.590 + HRESULT hret; 1.591 + 1.592 + if (pDirectDraw == NULL || 1.593 + ddsOffscreen == NULL || 1.594 + ddsPrimary == NULL) 1.595 + return; 1.596 + 1.597 + bool fastForward = speedup; 1.598 +#if (defined(WIN32) && !defined(SDL)) 1.599 + if (theApp.frameSearchSkipping) 1.600 + { 1.601 + if (theApp.frameSearchFirstStep) 1.602 + fastForward = true; 1.603 + else 1.604 + return; // don't render skipped frame search frames 1.605 + } 1.606 +#endif 1.607 + 1.608 + DDSURFACEDESC2 ddsDesc; 1.609 + 1.610 + ZeroMemory(&ddsDesc, sizeof(ddsDesc)); 1.611 + 1.612 + ddsDesc.dwSize = sizeof(ddsDesc); 1.613 + 1.614 + hret = ddsOffscreen->Lock(NULL, 1.615 + &ddsDesc, 1.616 +#ifndef FINAL_VERSION 1.617 + DDLOCK_NOSYSLOCK | 1.618 +#endif 1.619 + DDLOCK_WRITEONLY | DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, 1.620 + NULL); 1.621 + 1.622 + if (hret == DDERR_SURFACELOST) 1.623 + { 1.624 + hret = ddsPrimary->Restore(); 1.625 + if (hret == DD_OK) 1.626 + { 1.627 + hret = ddsOffscreen->Restore(); 1.628 + 1.629 + if (hret == DD_OK) 1.630 + { 1.631 + hret = ddsOffscreen->Lock(NULL, 1.632 + &ddsDesc, 1.633 +#ifndef FINAL_VERSION 1.634 + DDLOCK_NOSYSLOCK | 1.635 +#endif 1.636 + DDLOCK_WRITEONLY | DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, 1.637 + NULL); 1.638 + } 1.639 + } 1.640 + } 1.641 + 1.642 + if (hret == DD_OK) 1.643 + { 1.644 + if (theApp.filterFunction) 1.645 + { 1.646 + if (systemColorDepth == 16) 1.647 + (*theApp.filterFunction)(pix + theApp.filterWidth * 2 + 4, 1.648 + theApp.filterWidth * 2 + 4, 1.649 + (u8 *)theApp.delta, 1.650 + (u8 *)ddsDesc.lpSurface, 1.651 + ddsDesc.lPitch, 1.652 + theApp.filterWidth, 1.653 + theApp.filterHeight); 1.654 + else 1.655 + (*theApp.filterFunction)(pix + theApp.filterWidth * 4 + 4, 1.656 + theApp.filterWidth * 4 + 4, 1.657 + (u8 *)theApp.delta, 1.658 + (u8 *)ddsDesc.lpSurface, 1.659 + ddsDesc.lPitch, 1.660 + theApp.filterWidth, 1.661 + theApp.filterHeight); 1.662 + } 1.663 + else 1.664 + { 1.665 + int copyX = 240; 1.666 + int copyY = 160; 1.667 + 1.668 + if (systemCartridgeType == 1) 1.669 + { 1.670 + if (gbBorderOn) 1.671 + { 1.672 + copyX = 256; 1.673 + copyY = 224; 1.674 + } 1.675 + else 1.676 + { 1.677 + copyX = 160; 1.678 + copyY = 144; 1.679 + } 1.680 + } 1.681 + // MMX doesn't seem to be faster to copy the data 1.682 + __asm { 1.683 + mov eax, copyX; 1.684 + mov ebx, copyY; 1.685 + 1.686 + mov esi, pix; 1.687 + mov edi, ddsDesc.lpSurface; 1.688 + mov edx, ddsDesc.lPitch; 1.689 + cmp systemColorDepth, 16; 1.690 + jnz gbaOtherColor; 1.691 + sub edx, eax; 1.692 + sub edx, eax; 1.693 + lea esi, [esi+2*eax+4]; 1.694 + shr eax, 1; 1.695 +gbaLoop16bit: 1.696 + mov ecx, eax; 1.697 + repz movsd; 1.698 + inc esi; 1.699 + inc esi; 1.700 + inc esi; 1.701 + inc esi; 1.702 + add edi, edx; 1.703 + dec ebx; 1.704 + jnz gbaLoop16bit; 1.705 + jmp gbaLoopEnd; 1.706 +gbaOtherColor: 1.707 + cmp systemColorDepth, 32; 1.708 + jnz gbaOtherColor2; 1.709 + 1.710 + sub edx, eax; 1.711 + sub edx, eax; 1.712 + sub edx, eax; 1.713 + sub edx, eax; 1.714 + lea esi, [esi+4*eax+4]; 1.715 +gbaLoop32bit: 1.716 + mov ecx, eax; 1.717 + repz movsd; 1.718 + add esi, 4; 1.719 + add edi, edx; 1.720 + dec ebx; 1.721 + jnz gbaLoop32bit; 1.722 + jmp gbaLoopEnd; 1.723 +gbaOtherColor2: 1.724 + lea eax, [eax+2*eax]; 1.725 + sub edx, eax; 1.726 +gbaLoop24bit: 1.727 + mov ecx, eax; 1.728 + shr ecx, 2; 1.729 + repz movsd; 1.730 + add edi, edx; 1.731 + dec ebx; 1.732 + jnz gbaLoop24bit; 1.733 +gbaLoopEnd: 1.734 + } 1.735 + } 1.736 + if (theApp.showSpeed && theApp.videoOption > VIDEO_4X) 1.737 + { 1.738 + char buffer[30]; 1.739 + if (theApp.showSpeed == 1) 1.740 + sprintf(buffer, "%3d%%", systemSpeed); 1.741 + else 1.742 + sprintf(buffer, "%3d%%(%d, %d fps)", systemSpeed, 1.743 + systemFrameSkip, 1.744 + theApp.showRenderedFrames); 1.745 + if (theApp.showSpeedTransparent) 1.746 + drawTextTransp((u8 *)ddsDesc.lpSurface, 1.747 + ddsDesc.lPitch, 1.748 + theApp.rect.left+10, 1.749 + theApp.rect.bottom-10, 1.750 + buffer); 1.751 + else 1.752 + drawText((u8 *)ddsDesc.lpSurface, 1.753 + ddsDesc.lPitch, 1.754 + theApp.rect.left+10, 1.755 + theApp.rect.bottom-10, 1.756 + buffer); 1.757 + } 1.758 + 1.759 + if (textMethod == 1) 1.760 + { 1.761 + DrawTextMessages((u8 *)ddsDesc.lpSurface, ddsDesc.lPitch, theApp.rect.left, theApp.rect.bottom); 1.762 + } 1.763 + } 1.764 + else if (theApp.ddrawDebug) 1.765 + winlog("Error during lock: %08x\n", hret); 1.766 + 1.767 + hret = ddsOffscreen->Unlock(NULL); 1.768 + 1.769 + if (hret == DD_OK) 1.770 + { 1.771 + // the correct point where to wait 1.772 + if (theApp.vsync && !fastForward) 1.773 + { 1.774 + hret = pDirectDraw->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN, 0); 1.775 + } 1.776 + 1.777 + ddsOffscreen->PageLock(0); 1.778 + if (theApp.tripleBuffering && theApp.videoOption > VIDEO_4X) 1.779 + { 1.780 + hret = ddsFlip->Blt(&theApp.dest, ddsOffscreen, NULL, DDBLT_WAIT, NULL); 1.781 + if (hret == DD_OK) 1.782 + { 1.783 + if (theApp.menuToggle || !theApp.active) 1.784 + { 1.785 + pDirectDraw->FlipToGDISurface(); 1.786 + ddsPrimary->SetClipper(ddsClipper); 1.787 + hret = ddsPrimary->Blt(&theApp.dest, ddsFlip, NULL, DDBLT_ASYNC, NULL); 1.788 + // if using emulation only, then we have to redraw the menu 1.789 + // everytime. It seems like a bug in DirectDraw to me as we not 1.790 + // overwritting the menu area at all. 1.791 + if (theApp.ddrawUsingEmulationOnly) 1.792 + theApp.m_pMainWnd->DrawMenuBar(); 1.793 + } 1.794 + else 1.795 + hret = ddsPrimary->Flip(NULL, 0); 1.796 + } 1.797 + } 1.798 + else 1.799 + { 1.800 + hret = ddsPrimary->Blt(&theApp.dest, ddsOffscreen, NULL, DDBLT_ASYNC, NULL); 1.801 + 1.802 + if (hret == DDERR_SURFACELOST) 1.803 + { 1.804 + hret = ddsPrimary->Restore(); 1.805 + 1.806 + if (hret == DD_OK) 1.807 + { 1.808 + hret = ddsPrimary->Blt(&theApp.dest, ddsOffscreen, NULL, DDBLT_ASYNC, NULL); 1.809 + } 1.810 + } 1.811 + } 1.812 + ddsOffscreen->PageUnlock(0); 1.813 + } 1.814 + else if (theApp.ddrawDebug) 1.815 + winlog("Error during unlock: %08x\n", hret); 1.816 + 1.817 + bool textMessageStarted = false; 1.818 + 1.819 + if (textMethod == 2) 1.820 + { 1.821 + HDC hdc; 1.822 + 1.823 + for (int slot = 0; slot < SCREEN_MESSAGE_SLOTS; slot++) 1.824 + { 1.825 + if (theApp.screenMessage[slot]) 1.826 + { 1.827 + if ((theApp.screenMessageDuration[slot] < 0 || 1.828 + (int)(GetTickCount() - theApp.screenMessageTime[slot]) < theApp.screenMessageDuration[slot]) && 1.829 + (!theApp.disableStatusMessage || slot == 1 || slot == 2)) 1.830 + { 1.831 + if (!textMessageStarted) 1.832 + { 1.833 + textMessageStarted = true; 1.834 + ddsPrimary->SetClipper(ddsClipper); 1.835 + ddsPrimary->GetDC(&hdc); 1.836 + SetBkMode(hdc, TRANSPARENT); 1.837 + SetTextColor(hdc, textColor != 7 ? RGB(0, 0, 0) : RGB(255, 255, 255)); 1.838 + } 1.839 + 1.840 + if (outlinedText) 1.841 + { 1.842 + // draw black outline 1.843 + const static int xd [8] = {-1, 0, 1, 1, 1, 0, -1, -1}; 1.844 + const static int yd [8] = {-1, -1, -1, 0, 1, 1, 1, 0}; 1.845 + for (int i = 0; i < 8; i++) 1.846 + { 1.847 + TextOut(hdc, 1.848 + theApp.dest.left+10+xd[i], 1.849 + theApp.dest.bottom - 20*(slot+1)+yd[i], 1.850 + theApp.screenMessageBuffer[slot], 1.851 + strlen(theApp.screenMessageBuffer[slot])); 1.852 + } 1.853 + } 1.854 + } 1.855 + else 1.856 + { 1.857 + theApp.screenMessage[slot] = false; 1.858 + } 1.859 + } 1.860 + } 1.861 + 1.862 + if (textMessageStarted) 1.863 + { 1.864 + COLORREF color; 1.865 + switch (textColor) 1.866 + { 1.867 + case 0: 1.868 + color = RGB(255, 255, 255); break; 1.869 + case 1: 1.870 + color = RGB(255, 0, 0); break; 1.871 + case 2: 1.872 + color = RGB(255, 255, 0); break; 1.873 + case 3: 1.874 + color = RGB(0, 255, 0); break; 1.875 + case 4: 1.876 + color = RGB(0, 255, 255); break; 1.877 + case 5: 1.878 + color = RGB(0, 0, 255); break; 1.879 + case 6: 1.880 + color = RGB(255, 0, 255); break; 1.881 + case 7: 1.882 + color = RGB(0, 0, 0); break; 1.883 + } 1.884 + SetTextColor(hdc, color); 1.885 + 1.886 + // draw center text 1.887 + for (int slot = 0; slot < SCREEN_MESSAGE_SLOTS; slot++) 1.888 + { 1.889 + if (theApp.screenMessage[slot]) 1.890 + { 1.891 + if ((theApp.screenMessageDuration[slot] < 0 || 1.892 + (int)(GetTickCount() - theApp.screenMessageTime[slot]) < theApp.screenMessageDuration[slot]) && 1.893 + (!theApp.disableStatusMessage || slot == 1 || slot == 2)) 1.894 + { 1.895 + TextOut(hdc, theApp.dest.left+10, theApp.dest.bottom - 20*(slot+1), theApp.screenMessageBuffer[slot], 1.896 + strlen(theApp.screenMessageBuffer[slot])); 1.897 + } 1.898 + } 1.899 + } 1.900 + } 1.901 + 1.902 + if (textMessageStarted) 1.903 + { 1.904 + ddsPrimary->ReleaseDC(hdc); 1.905 + } 1.906 + } 1.907 + 1.908 + if (hret != DD_OK) 1.909 + { 1.910 + if (theApp.ddrawDebug) 1.911 + winlog("Error on update screen: %08x\n", hret); 1.912 + } 1.913 +} 1.914 + 1.915 +int DirectDrawDisplay::selectFullScreenMode(GUID **pGUID) 1.916 +{ 1.917 + return winVideoModeSelect(theApp.m_pMainWnd, pGUID); 1.918 +} 1.919 + 1.920 +IDisplay *newDirectDrawDisplay() 1.921 +{ 1.922 + return new DirectDrawDisplay(); 1.923 +} 1.924 +