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