rlm@1: #include "stdafx.h" rlm@1: rlm@1: #define DIRECTDRAW_VERSION 0x0700 rlm@1: #include "ddraw.h" rlm@1: rlm@1: #include "resource.h" rlm@1: #include "MainWnd.h" rlm@1: #include "Reg.h" rlm@1: #include "VBA.h" rlm@1: rlm@1: #include "../common/System.h" rlm@1: #include "../gba/GBAGlobals.h" rlm@1: #include "../gb/gbGlobals.h" rlm@1: #include "../common/Text.h" rlm@1: #include "../version.h" rlm@1: rlm@1: extern u32 RGB_LOW_BITS_MASK; rlm@1: extern int systemSpeed; rlm@1: extern int Init_2xSaI(u32); rlm@1: extern void directXMessage(const char *); rlm@1: extern void winlog(const char *, ...); rlm@1: extern int winVideoModeSelect(CWnd *, GUID * *); rlm@1: rlm@1: class DirectDrawDisplay : public IDisplay rlm@1: { rlm@1: private: rlm@1: HINSTANCE ddrawDLL; rlm@1: LPDIRECTDRAW7 pDirectDraw; rlm@1: LPDIRECTDRAWSURFACE7 ddsPrimary; rlm@1: LPDIRECTDRAWSURFACE7 ddsOffscreen; rlm@1: LPDIRECTDRAWSURFACE7 ddsFlip; rlm@1: LPDIRECTDRAWCLIPPER ddsClipper; rlm@1: int width; rlm@1: int height; rlm@1: bool failed; rlm@1: rlm@1: bool initializeOffscreen(int w, int h); rlm@1: public: rlm@1: DirectDrawDisplay(); rlm@1: virtual ~DirectDrawDisplay(); rlm@1: rlm@1: virtual bool initialize(); rlm@1: virtual void cleanup(); rlm@1: virtual void render(); rlm@1: virtual void checkFullScreen(); rlm@1: virtual void renderMenu(); rlm@1: virtual void clear(); rlm@1: virtual bool changeRenderSize(int w, int h); rlm@1: virtual DISPLAY_TYPE getType() { return DIRECT_DRAW; }; rlm@1: virtual void setOption(const char *, int) {} rlm@1: virtual int selectFullScreenMode(GUID * *); rlm@1: }; rlm@1: rlm@1: static HRESULT WINAPI checkModesAvailable(LPDDSURFACEDESC2 surf, LPVOID lpContext) rlm@1: { rlm@1: if (surf->dwWidth == 320 && rlm@1: surf->dwHeight == 240 && rlm@1: surf->ddpfPixelFormat.dwRGBBitCount == 16) rlm@1: { rlm@1: theApp.mode320Available = TRUE; rlm@1: } rlm@1: if (surf->dwWidth == 640 && rlm@1: surf->dwHeight == 480 && rlm@1: surf->ddpfPixelFormat.dwRGBBitCount == 16) rlm@1: { rlm@1: theApp.mode640Available = TRUE; rlm@1: } rlm@1: if (surf->dwWidth == 800 && rlm@1: surf->dwHeight == 600 && rlm@1: surf->ddpfPixelFormat.dwRGBBitCount == 16) rlm@1: { rlm@1: theApp.mode800Available = TRUE; rlm@1: } rlm@1: return DDENUMRET_OK; rlm@1: } rlm@1: rlm@1: static int ffs(UINT mask) rlm@1: { rlm@1: int m = 0; rlm@1: if (mask) rlm@1: { rlm@1: while (!(mask & (1 << m))) rlm@1: m++; rlm@1: rlm@1: return (m); rlm@1: } rlm@1: rlm@1: return (0); rlm@1: } rlm@1: rlm@1: DirectDrawDisplay::DirectDrawDisplay() rlm@1: { rlm@1: pDirectDraw = NULL; rlm@1: ddsPrimary = NULL; rlm@1: ddsOffscreen = NULL; rlm@1: ddsFlip = NULL; rlm@1: ddsClipper = NULL; rlm@1: ddrawDLL = NULL; rlm@1: width = 0; rlm@1: height = 0; rlm@1: failed = false; rlm@1: } rlm@1: rlm@1: DirectDrawDisplay::~DirectDrawDisplay() rlm@1: { rlm@1: cleanup(); rlm@1: } rlm@1: rlm@1: void DirectDrawDisplay::cleanup() rlm@1: { rlm@1: if (pDirectDraw != NULL) rlm@1: { rlm@1: if (ddsClipper != NULL) rlm@1: { rlm@1: ddsClipper->Release(); rlm@1: ddsClipper = NULL; rlm@1: } rlm@1: rlm@1: if (ddsFlip != NULL) rlm@1: { rlm@1: ddsFlip->Release(); rlm@1: ddsFlip = NULL; rlm@1: } rlm@1: rlm@1: if (ddsOffscreen != NULL) rlm@1: { rlm@1: ddsOffscreen->Release(); rlm@1: ddsOffscreen = NULL; rlm@1: } rlm@1: rlm@1: if (ddsPrimary != NULL) rlm@1: { rlm@1: ddsPrimary->Release(); rlm@1: ddsPrimary = NULL; rlm@1: } rlm@1: rlm@1: pDirectDraw->Release(); rlm@1: pDirectDraw = NULL; rlm@1: } rlm@1: rlm@1: if (ddrawDLL != NULL) rlm@1: { rlm@1: /**/ ::FreeLibrary(ddrawDLL); rlm@1: ddrawDLL = NULL; rlm@1: } rlm@1: width = 0; rlm@1: height = 0; rlm@1: } rlm@1: rlm@1: bool DirectDrawDisplay::initialize() rlm@1: { rlm@1: CWnd *pWnd = theApp.m_pMainWnd; rlm@1: rlm@1: GUID *guid = NULL; rlm@1: if (theApp.ddrawEmulationOnly) rlm@1: guid = (GUID *)DDCREATE_EMULATIONONLY; rlm@1: rlm@1: if (theApp.pVideoDriverGUID) rlm@1: guid = theApp.pVideoDriverGUID; rlm@1: rlm@1: ddrawDLL = /**/ ::LoadLibrary("DDRAW.DLL"); rlm@1: HRESULT (WINAPI *DDrawCreateEx)(GUID *, LPVOID *, REFIID, IUnknown *); rlm@1: if (ddrawDLL != NULL) rlm@1: { rlm@1: DDrawCreateEx = (HRESULT (WINAPI *)(GUID *, LPVOID *, REFIID, IUnknown *)) rlm@1: GetProcAddress(ddrawDLL, "DirectDrawCreateEx"); rlm@1: rlm@1: if (DDrawCreateEx == NULL) rlm@1: { rlm@1: directXMessage("DirectDrawCreateEx"); rlm@1: return FALSE; rlm@1: } rlm@1: } rlm@1: else rlm@1: { rlm@1: directXMessage("DDRAW.DLL"); rlm@1: return FALSE; rlm@1: } rlm@1: rlm@1: theApp.ddrawUsingEmulationOnly = theApp.ddrawEmulationOnly; rlm@1: rlm@1: HRESULT hret = DDrawCreateEx(guid, rlm@1: (void * *)&pDirectDraw, rlm@1: IID_IDirectDraw7, rlm@1: NULL); rlm@1: rlm@1: if (hret != DD_OK) rlm@1: { rlm@1: winlog("Error creating DirectDraw object %08x\n", hret); rlm@1: if (theApp.ddrawEmulationOnly) rlm@1: { rlm@1: // disable emulation only setting in case of failure rlm@1: regSetDwordValue("ddrawEmulationOnly", 0); rlm@1: } rlm@1: // errorMessage(myLoadString(IDS_ERROR_DISP_DRAWCREATE), hret); rlm@1: return FALSE; rlm@1: } rlm@1: rlm@1: if (theApp.ddrawDebug) rlm@1: { rlm@1: DDCAPS driver; rlm@1: DDCAPS hel; rlm@1: ZeroMemory(&driver, sizeof(driver)); rlm@1: ZeroMemory(&hel, sizeof(hel)); rlm@1: driver.dwSize = sizeof(driver); rlm@1: hel.dwSize = sizeof(hel); rlm@1: pDirectDraw->GetCaps(&driver, &hel); rlm@1: int i; rlm@1: DWORD *p = (DWORD *)&driver; rlm@1: for (i = 0; i < (int)driver.dwSize; i += 4) rlm@1: winlog("Driver CAPS %2d: %08x\n", i>>2, *p++); rlm@1: p = (DWORD *)&hel; rlm@1: for (i = 0; i < (int)hel.dwSize; i += 4) rlm@1: winlog("HEL CAPS %2d: %08x\n", i>>2, *p++); rlm@1: } rlm@1: rlm@1: theApp.mode320Available = false; rlm@1: theApp.mode640Available = false; rlm@1: theApp.mode800Available = false; rlm@1: rlm@1: // check for available fullscreen modes rlm@1: pDirectDraw->EnumDisplayModes(DDEDM_STANDARDVGAMODES, NULL, NULL, checkModesAvailable); rlm@1: rlm@1: DWORD flags = DDSCL_NORMAL; rlm@1: rlm@1: if (theApp.videoOption >= VIDEO_320x240) rlm@1: flags = DDSCL_ALLOWMODEX | rlm@1: DDSCL_ALLOWREBOOT | rlm@1: DDSCL_EXCLUSIVE | rlm@1: DDSCL_FULLSCREEN; rlm@1: rlm@1: hret = pDirectDraw->SetCooperativeLevel(pWnd->m_hWnd, flags); rlm@1: rlm@1: if (hret != DD_OK) rlm@1: { rlm@1: winlog("Error SetCooperativeLevel %08x\n", hret); rlm@1: // errorMessage(myLoadString(IDS_ERROR_DISP_DRAWLEVEL), hret); rlm@1: return FALSE; rlm@1: } rlm@1: rlm@1: if (theApp.videoOption > VIDEO_4X) rlm@1: { rlm@1: hret = pDirectDraw->SetDisplayMode(theApp.fsWidth, rlm@1: theApp.fsHeight, rlm@1: theApp.fsColorDepth, rlm@1: 0, rlm@1: 0); rlm@1: if (hret != DD_OK) rlm@1: { rlm@1: winlog("Error SetDisplayMode %08x\n", hret); rlm@1: // errorMessage(myLoadString(IDS_ERROR_DISP_DRAWSET), hret); rlm@1: return FALSE; rlm@1: } rlm@1: } rlm@1: rlm@1: DDSURFACEDESC2 ddsd; rlm@1: ZeroMemory(&ddsd, sizeof(ddsd)); rlm@1: ddsd.dwSize = sizeof(ddsd); rlm@1: ddsd.dwFlags = DDSD_CAPS; rlm@1: ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; rlm@1: rlm@1: if (theApp.videoOption > VIDEO_4X && theApp.tripleBuffering) rlm@1: { rlm@1: // setup triple buffering rlm@1: ddsd.dwFlags |= DDSD_BACKBUFFERCOUNT; rlm@1: ddsd.ddsCaps.dwCaps |= DDSCAPS_COMPLEX | DDSCAPS_FLIP; rlm@1: ddsd.dwBackBufferCount = 2; rlm@1: } rlm@1: rlm@1: hret = pDirectDraw->CreateSurface(&ddsd, &ddsPrimary, NULL); rlm@1: if (hret != DD_OK) rlm@1: { rlm@1: winlog("Error primary CreateSurface %08x\n", hret); rlm@1: // errorMessage(myLoadString(IDS_ERROR_DISP_DRAWSURFACE), hret); rlm@1: return FALSE; rlm@1: } rlm@1: rlm@1: if (theApp.ddrawDebug) rlm@1: { rlm@1: DDSCAPS2 caps; rlm@1: ZeroMemory(&caps, sizeof(caps)); rlm@1: ddsPrimary->GetCaps(&caps); rlm@1: rlm@1: winlog("Primary CAPS 1: %08x\n", caps.dwCaps); rlm@1: winlog("Primary CAPS 2: %08x\n", caps.dwCaps2); rlm@1: winlog("Primary CAPS 3: %08x\n", caps.dwCaps3); rlm@1: winlog("Primary CAPS 4: %08x\n", caps.dwCaps4); rlm@1: } rlm@1: rlm@1: if (theApp.videoOption > VIDEO_4X && theApp.tripleBuffering) rlm@1: { rlm@1: DDSCAPS2 caps; rlm@1: ZeroMemory(&caps, sizeof(caps)); rlm@1: // this gets the third surface. The front one is the primary, rlm@1: // the second is the backbuffer and the third is the flip rlm@1: // surface rlm@1: caps.dwCaps = DDSCAPS_BACKBUFFER; rlm@1: rlm@1: hret = ddsPrimary->GetAttachedSurface(&caps, &ddsFlip); rlm@1: if (hret != DD_OK) rlm@1: { rlm@1: winlog("Failed to get attached surface %08x", hret); rlm@1: return FALSE; rlm@1: } rlm@1: ddsFlip->AddRef(); rlm@1: clear(); rlm@1: } rlm@1: rlm@1: // create clipper in all modes to avoid paint problems rlm@1: // if(videoOption <= VIDEO_4X) { rlm@1: hret = pDirectDraw->CreateClipper(0, &ddsClipper, NULL); rlm@1: if (hret == DD_OK) rlm@1: { rlm@1: ddsClipper->SetHWnd(0, pWnd->m_hWnd); rlm@1: if (theApp.videoOption > VIDEO_4X) rlm@1: { rlm@1: if (theApp.tripleBuffering) rlm@1: ddsFlip->SetClipper(ddsClipper); rlm@1: else rlm@1: ddsPrimary->SetClipper(ddsClipper); rlm@1: } rlm@1: else rlm@1: ddsPrimary->SetClipper(ddsClipper); rlm@1: } rlm@1: // } rlm@1: rlm@1: DDPIXELFORMAT px; rlm@1: rlm@1: px.dwSize = sizeof(px); rlm@1: rlm@1: hret = ddsPrimary->GetPixelFormat(&px); rlm@1: rlm@1: switch (px.dwRGBBitCount) rlm@1: { rlm@1: case 15: rlm@1: case 16: rlm@1: systemColorDepth = 16; rlm@1: break; rlm@1: case 24: rlm@1: systemColorDepth = 24; rlm@1: theApp.filterFunction = NULL; rlm@1: break; rlm@1: case 32: rlm@1: systemColorDepth = 32; rlm@1: break; rlm@1: default: rlm@1: systemMessage( rlm@1: IDS_ERROR_DISP_COLOR, rlm@1: "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: px.dwRGBBitCount); rlm@1: return FALSE; rlm@1: } rlm@1: theApp.updateFilter(); rlm@1: theApp.updateIFB(); rlm@1: rlm@1: if (failed) rlm@1: return false; rlm@1: rlm@1: pWnd->DragAcceptFiles(TRUE); rlm@1: rlm@1: return true; rlm@1: } rlm@1: rlm@1: bool DirectDrawDisplay::changeRenderSize(int w, int h) rlm@1: { rlm@1: if (w != width || h != height) rlm@1: { rlm@1: if (ddsOffscreen) rlm@1: { rlm@1: ddsOffscreen->Release(); rlm@1: ddsOffscreen = NULL; rlm@1: } rlm@1: if (!initializeOffscreen(w, h)) rlm@1: { rlm@1: failed = true; rlm@1: return false; rlm@1: } rlm@1: } rlm@1: return true; rlm@1: } rlm@1: rlm@1: bool DirectDrawDisplay::initializeOffscreen(int w, int h) rlm@1: { rlm@1: DDSURFACEDESC2 ddsd; rlm@1: rlm@1: ZeroMemory(&ddsd, sizeof(ddsd)); rlm@1: ddsd.dwSize = sizeof(ddsd); rlm@1: ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; rlm@1: ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; rlm@1: if (theApp.ddrawUseVideoMemory) rlm@1: ddsd.ddsCaps.dwCaps |= (DDSCAPS_LOCALVIDMEM|DDSCAPS_VIDEOMEMORY); rlm@1: ddsd.dwWidth = w; rlm@1: ddsd.dwHeight = h; rlm@1: rlm@1: HRESULT hret = pDirectDraw->CreateSurface(&ddsd, &ddsOffscreen, NULL); rlm@1: rlm@1: if (hret != DD_OK) rlm@1: { rlm@1: winlog("Error offscreen CreateSurface %08x\n", hret); rlm@1: if (theApp.ddrawUseVideoMemory) rlm@1: { rlm@1: regSetDwordValue("ddrawUseVideoMemory", 0); rlm@1: } rlm@1: // errorMessage(myLoadString(IDS_ERROR_DISP_DRAWSURFACE2), hret); rlm@1: return false; rlm@1: } rlm@1: rlm@1: if (theApp.ddrawDebug) rlm@1: { rlm@1: DDSCAPS2 caps; rlm@1: ZeroMemory(&caps, sizeof(caps)); rlm@1: ddsOffscreen->GetCaps(&caps); rlm@1: rlm@1: winlog("Offscreen CAPS 1: %08x\n", caps.dwCaps); rlm@1: winlog("Offscreen CAPS 2: %08x\n", caps.dwCaps2); rlm@1: winlog("Offscreen CAPS 3: %08x\n", caps.dwCaps3); rlm@1: winlog("Offscreen CAPS 4: %08x\n", caps.dwCaps4); rlm@1: } rlm@1: rlm@1: DDPIXELFORMAT px; rlm@1: rlm@1: px.dwSize = sizeof(px); rlm@1: rlm@1: hret = ddsOffscreen->GetPixelFormat(&px); rlm@1: rlm@1: if (theApp.ddrawDebug) rlm@1: { rlm@1: DWORD *pdword = (DWORD *)&px; rlm@1: for (int ii = 0; ii < 8; ii++) rlm@1: { rlm@1: winlog("Pixel format %d %08x\n", ii, pdword[ii]); rlm@1: } rlm@1: } rlm@1: rlm@1: switch (px.dwRGBBitCount) rlm@1: { rlm@1: case 15: rlm@1: case 16: rlm@1: systemColorDepth = 16; rlm@1: break; rlm@1: case 24: rlm@1: systemColorDepth = 24; rlm@1: theApp.filterFunction = NULL; rlm@1: break; rlm@1: case 32: rlm@1: systemColorDepth = 32; rlm@1: break; rlm@1: default: rlm@1: systemMessage( rlm@1: IDS_ERROR_DISP_COLOR, rlm@1: "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: px.dwRGBBitCount); rlm@1: return FALSE; rlm@1: } rlm@1: if (theApp.ddrawDebug) rlm@1: { rlm@1: winlog("R Mask: %08x\n", px.dwRBitMask); rlm@1: winlog("G Mask: %08x\n", px.dwGBitMask); rlm@1: winlog("B Mask: %08x\n", px.dwBBitMask); rlm@1: } rlm@1: rlm@1: systemRedShift = ffs(px.dwRBitMask); rlm@1: systemGreenShift = ffs(px.dwGBitMask); rlm@1: systemBlueShift = ffs(px.dwBBitMask); rlm@1: rlm@1: #ifdef MMX rlm@1: if (!theApp.disableMMX) rlm@1: cpu_mmx = theApp.detectMMX(); rlm@1: else rlm@1: cpu_mmx = 0; rlm@1: #endif rlm@1: rlm@1: if ((px.dwFlags&DDPF_RGB) != 0 && rlm@1: px.dwRBitMask == 0xF800 && rlm@1: px.dwGBitMask == 0x07E0 && rlm@1: px.dwBBitMask == 0x001F) rlm@1: { rlm@1: systemGreenShift++; rlm@1: Init_2xSaI(565); rlm@1: RGB_LOW_BITS_MASK = 0x821; rlm@1: } rlm@1: else if ((px.dwFlags&DDPF_RGB) != 0 && rlm@1: px.dwRBitMask == 0x7C00 && rlm@1: px.dwGBitMask == 0x03E0 && rlm@1: px.dwBBitMask == 0x001F) rlm@1: { rlm@1: Init_2xSaI(555); rlm@1: RGB_LOW_BITS_MASK = 0x421; rlm@1: } rlm@1: else if ((px.dwFlags&DDPF_RGB) != 0 && rlm@1: px.dwRBitMask == 0x001F && rlm@1: px.dwGBitMask == 0x07E0 && rlm@1: px.dwBBitMask == 0xF800) rlm@1: { rlm@1: systemGreenShift++; rlm@1: Init_2xSaI(565); rlm@1: RGB_LOW_BITS_MASK = 0x821; rlm@1: } rlm@1: else if ((px.dwFlags&DDPF_RGB) != 0 && rlm@1: px.dwRBitMask == 0x001F && rlm@1: px.dwGBitMask == 0x03E0 && rlm@1: px.dwBBitMask == 0x7C00) rlm@1: { rlm@1: Init_2xSaI(555); rlm@1: RGB_LOW_BITS_MASK = 0x421; rlm@1: } rlm@1: else rlm@1: { rlm@1: // 32-bit or 24-bit rlm@1: if (systemColorDepth == 32 || systemColorDepth == 24) rlm@1: { rlm@1: systemRedShift += 3; rlm@1: systemGreenShift += 3; rlm@1: systemBlueShift += 3; rlm@1: if (systemColorDepth == 32) rlm@1: Init_2xSaI(32); rlm@1: } rlm@1: } rlm@1: rlm@1: if (theApp.ddrawDebug) rlm@1: { rlm@1: winlog("R shift: %d\n", systemRedShift); rlm@1: winlog("G shift: %d\n", systemGreenShift); rlm@1: winlog("B shift: %d\n", systemBlueShift); rlm@1: } rlm@1: rlm@1: switch (systemColorDepth) rlm@1: { rlm@1: case 16: rlm@1: { rlm@1: for (int i = 0; i < 0x10000; i++) rlm@1: { rlm@1: systemColorMap16[i] = ((i & 0x1f) << systemRedShift) | rlm@1: (((i & 0x3e0) >> 5) << systemGreenShift) | rlm@1: (((i & 0x7c00) >> 10) << systemBlueShift); rlm@1: } rlm@1: break; rlm@1: } rlm@1: case 24: rlm@1: case 32: rlm@1: { rlm@1: for (int i = 0; i < 0x10000; i++) rlm@1: { rlm@1: systemColorMap32[i] = ((i & 0x1f) << systemRedShift) | rlm@1: (((i & 0x3e0) >> 5) << systemGreenShift) | rlm@1: (((i & 0x7c00) >> 10) << systemBlueShift); rlm@1: } rlm@1: break; rlm@1: } rlm@1: } rlm@1: width = w; rlm@1: height = h; rlm@1: return true; rlm@1: } rlm@1: rlm@1: void DirectDrawDisplay::clear() rlm@1: { rlm@1: if (theApp.videoOption <= VIDEO_4X || !theApp.tripleBuffering || ddsFlip == NULL) rlm@1: return; rlm@1: rlm@1: DDBLTFX fx; rlm@1: ZeroMemory(&fx, sizeof(fx)); rlm@1: fx.dwSize = sizeof(fx); rlm@1: fx.dwFillColor = 0; rlm@1: ddsFlip->Blt(NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx); rlm@1: ddsPrimary->Flip(NULL, 0); rlm@1: ddsFlip->Blt(NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx); rlm@1: ddsPrimary->Flip(NULL, 0); rlm@1: ddsFlip->Blt(NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &fx); rlm@1: ddsPrimary->Flip(NULL, 0); rlm@1: } rlm@1: rlm@1: void DirectDrawDisplay::renderMenu() rlm@1: { rlm@1: checkFullScreen(); rlm@1: theApp.m_pMainWnd->DrawMenuBar(); rlm@1: } rlm@1: rlm@1: void DirectDrawDisplay::checkFullScreen() rlm@1: { rlm@1: if (theApp.tripleBuffering) rlm@1: pDirectDraw->FlipToGDISurface(); rlm@1: } rlm@1: rlm@1: void DirectDrawDisplay::render() rlm@1: { rlm@1: HRESULT hret; rlm@1: rlm@1: if (pDirectDraw == NULL || rlm@1: ddsOffscreen == NULL || rlm@1: ddsPrimary == NULL) rlm@1: return; rlm@1: rlm@1: bool fastForward = speedup; rlm@1: #if (defined(WIN32) && !defined(SDL)) rlm@1: if (theApp.frameSearchSkipping) rlm@1: { rlm@1: if (theApp.frameSearchFirstStep) rlm@1: fastForward = true; rlm@1: else rlm@1: return; // don't render skipped frame search frames rlm@1: } rlm@1: #endif rlm@1: rlm@1: DDSURFACEDESC2 ddsDesc; rlm@1: rlm@1: ZeroMemory(&ddsDesc, sizeof(ddsDesc)); rlm@1: rlm@1: ddsDesc.dwSize = sizeof(ddsDesc); rlm@1: rlm@1: hret = ddsOffscreen->Lock(NULL, rlm@1: &ddsDesc, rlm@1: #ifndef FINAL_VERSION rlm@1: DDLOCK_NOSYSLOCK | rlm@1: #endif rlm@1: DDLOCK_WRITEONLY | DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, rlm@1: NULL); rlm@1: rlm@1: if (hret == DDERR_SURFACELOST) rlm@1: { rlm@1: hret = ddsPrimary->Restore(); rlm@1: if (hret == DD_OK) rlm@1: { rlm@1: hret = ddsOffscreen->Restore(); rlm@1: rlm@1: if (hret == DD_OK) rlm@1: { rlm@1: hret = ddsOffscreen->Lock(NULL, rlm@1: &ddsDesc, rlm@1: #ifndef FINAL_VERSION rlm@1: DDLOCK_NOSYSLOCK | rlm@1: #endif rlm@1: DDLOCK_WRITEONLY | DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, rlm@1: NULL); rlm@1: } rlm@1: } rlm@1: } rlm@1: rlm@1: if (hret == DD_OK) rlm@1: { rlm@1: if (theApp.filterFunction) rlm@1: { rlm@1: if (systemColorDepth == 16) rlm@1: (*theApp.filterFunction)(pix + theApp.filterWidth * 2 + 4, rlm@1: theApp.filterWidth * 2 + 4, rlm@1: (u8 *)theApp.delta, rlm@1: (u8 *)ddsDesc.lpSurface, rlm@1: ddsDesc.lPitch, rlm@1: theApp.filterWidth, rlm@1: theApp.filterHeight); rlm@1: else rlm@1: (*theApp.filterFunction)(pix + theApp.filterWidth * 4 + 4, rlm@1: theApp.filterWidth * 4 + 4, rlm@1: (u8 *)theApp.delta, rlm@1: (u8 *)ddsDesc.lpSurface, rlm@1: ddsDesc.lPitch, rlm@1: theApp.filterWidth, rlm@1: theApp.filterHeight); rlm@1: } rlm@1: else rlm@1: { rlm@1: int copyX = 240; rlm@1: int copyY = 160; rlm@1: rlm@1: if (systemCartridgeType == 1) rlm@1: { rlm@1: if (gbBorderOn) rlm@1: { rlm@1: copyX = 256; rlm@1: copyY = 224; rlm@1: } rlm@1: else rlm@1: { rlm@1: copyX = 160; rlm@1: copyY = 144; rlm@1: } rlm@1: } rlm@1: // MMX doesn't seem to be faster to copy the data rlm@1: __asm { rlm@1: mov eax, copyX; rlm@1: mov ebx, copyY; rlm@1: rlm@1: mov esi, pix; rlm@1: mov edi, ddsDesc.lpSurface; rlm@1: mov edx, ddsDesc.lPitch; rlm@1: cmp systemColorDepth, 16; rlm@1: jnz gbaOtherColor; rlm@1: sub edx, eax; rlm@1: sub edx, eax; rlm@1: lea esi, [esi+2*eax+4]; rlm@1: shr eax, 1; rlm@1: gbaLoop16bit: rlm@1: mov ecx, eax; rlm@1: repz movsd; rlm@1: inc esi; rlm@1: inc esi; rlm@1: inc esi; rlm@1: inc esi; rlm@1: add edi, edx; rlm@1: dec ebx; rlm@1: jnz gbaLoop16bit; rlm@1: jmp gbaLoopEnd; rlm@1: gbaOtherColor: rlm@1: cmp systemColorDepth, 32; rlm@1: jnz gbaOtherColor2; rlm@1: rlm@1: sub edx, eax; rlm@1: sub edx, eax; rlm@1: sub edx, eax; rlm@1: sub edx, eax; rlm@1: lea esi, [esi+4*eax+4]; rlm@1: gbaLoop32bit: rlm@1: mov ecx, eax; rlm@1: repz movsd; rlm@1: add esi, 4; rlm@1: add edi, edx; rlm@1: dec ebx; rlm@1: jnz gbaLoop32bit; rlm@1: jmp gbaLoopEnd; rlm@1: gbaOtherColor2: rlm@1: lea eax, [eax+2*eax]; rlm@1: sub edx, eax; rlm@1: gbaLoop24bit: rlm@1: mov ecx, eax; rlm@1: shr ecx, 2; rlm@1: repz movsd; rlm@1: add edi, edx; rlm@1: dec ebx; rlm@1: jnz gbaLoop24bit; rlm@1: gbaLoopEnd: rlm@1: } rlm@1: } rlm@1: if (theApp.showSpeed && theApp.videoOption > VIDEO_4X) rlm@1: { rlm@1: char buffer[30]; rlm@1: if (theApp.showSpeed == 1) rlm@1: sprintf(buffer, "%3d%%", systemSpeed); rlm@1: else rlm@1: sprintf(buffer, "%3d%%(%d, %d fps)", systemSpeed, rlm@1: systemFrameSkip, rlm@1: theApp.showRenderedFrames); rlm@1: if (theApp.showSpeedTransparent) rlm@1: drawTextTransp((u8 *)ddsDesc.lpSurface, rlm@1: ddsDesc.lPitch, rlm@1: theApp.rect.left+10, rlm@1: theApp.rect.bottom-10, rlm@1: buffer); rlm@1: else rlm@1: drawText((u8 *)ddsDesc.lpSurface, rlm@1: ddsDesc.lPitch, rlm@1: theApp.rect.left+10, rlm@1: theApp.rect.bottom-10, rlm@1: buffer); rlm@1: } rlm@1: rlm@1: if (textMethod == 1) rlm@1: { rlm@1: DrawTextMessages((u8 *)ddsDesc.lpSurface, ddsDesc.lPitch, theApp.rect.left, theApp.rect.bottom); rlm@1: } rlm@1: } rlm@1: else if (theApp.ddrawDebug) rlm@1: winlog("Error during lock: %08x\n", hret); rlm@1: rlm@1: hret = ddsOffscreen->Unlock(NULL); rlm@1: rlm@1: if (hret == DD_OK) rlm@1: { rlm@1: // the correct point where to wait rlm@1: if (theApp.vsync && !fastForward) rlm@1: { rlm@1: hret = pDirectDraw->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN, 0); rlm@1: } rlm@1: rlm@1: ddsOffscreen->PageLock(0); rlm@1: if (theApp.tripleBuffering && theApp.videoOption > VIDEO_4X) rlm@1: { rlm@1: hret = ddsFlip->Blt(&theApp.dest, ddsOffscreen, NULL, DDBLT_WAIT, NULL); rlm@1: if (hret == DD_OK) rlm@1: { rlm@1: if (theApp.menuToggle || !theApp.active) rlm@1: { rlm@1: pDirectDraw->FlipToGDISurface(); rlm@1: ddsPrimary->SetClipper(ddsClipper); rlm@1: hret = ddsPrimary->Blt(&theApp.dest, ddsFlip, NULL, DDBLT_ASYNC, NULL); rlm@1: // if using emulation only, then we have to redraw the menu rlm@1: // everytime. It seems like a bug in DirectDraw to me as we not rlm@1: // overwritting the menu area at all. rlm@1: if (theApp.ddrawUsingEmulationOnly) rlm@1: theApp.m_pMainWnd->DrawMenuBar(); rlm@1: } rlm@1: else rlm@1: hret = ddsPrimary->Flip(NULL, 0); rlm@1: } rlm@1: } rlm@1: else rlm@1: { rlm@1: hret = ddsPrimary->Blt(&theApp.dest, ddsOffscreen, NULL, DDBLT_ASYNC, NULL); rlm@1: rlm@1: if (hret == DDERR_SURFACELOST) rlm@1: { rlm@1: hret = ddsPrimary->Restore(); rlm@1: rlm@1: if (hret == DD_OK) rlm@1: { rlm@1: hret = ddsPrimary->Blt(&theApp.dest, ddsOffscreen, NULL, DDBLT_ASYNC, NULL); rlm@1: } rlm@1: } rlm@1: } rlm@1: ddsOffscreen->PageUnlock(0); rlm@1: } rlm@1: else if (theApp.ddrawDebug) rlm@1: winlog("Error during unlock: %08x\n", hret); rlm@1: rlm@1: bool textMessageStarted = false; rlm@1: rlm@1: if (textMethod == 2) rlm@1: { rlm@1: HDC hdc; rlm@1: rlm@1: for (int slot = 0; slot < SCREEN_MESSAGE_SLOTS; slot++) rlm@1: { rlm@1: if (theApp.screenMessage[slot]) rlm@1: { rlm@1: if ((theApp.screenMessageDuration[slot] < 0 || rlm@1: (int)(GetTickCount() - theApp.screenMessageTime[slot]) < theApp.screenMessageDuration[slot]) && rlm@1: (!theApp.disableStatusMessage || slot == 1 || slot == 2)) rlm@1: { rlm@1: if (!textMessageStarted) rlm@1: { rlm@1: textMessageStarted = true; rlm@1: ddsPrimary->SetClipper(ddsClipper); rlm@1: ddsPrimary->GetDC(&hdc); rlm@1: SetBkMode(hdc, TRANSPARENT); rlm@1: SetTextColor(hdc, textColor != 7 ? RGB(0, 0, 0) : RGB(255, 255, 255)); rlm@1: } rlm@1: rlm@1: if (outlinedText) rlm@1: { rlm@1: // draw black outline rlm@1: const static int xd [8] = {-1, 0, 1, 1, 1, 0, -1, -1}; rlm@1: const static int yd [8] = {-1, -1, -1, 0, 1, 1, 1, 0}; rlm@1: for (int i = 0; i < 8; i++) rlm@1: { rlm@1: TextOut(hdc, rlm@1: theApp.dest.left+10+xd[i], rlm@1: theApp.dest.bottom - 20*(slot+1)+yd[i], rlm@1: theApp.screenMessageBuffer[slot], rlm@1: strlen(theApp.screenMessageBuffer[slot])); rlm@1: } rlm@1: } rlm@1: } rlm@1: else rlm@1: { rlm@1: theApp.screenMessage[slot] = false; rlm@1: } rlm@1: } rlm@1: } rlm@1: rlm@1: if (textMessageStarted) rlm@1: { rlm@1: COLORREF color; rlm@1: switch (textColor) rlm@1: { rlm@1: case 0: rlm@1: color = RGB(255, 255, 255); break; rlm@1: case 1: rlm@1: color = RGB(255, 0, 0); break; rlm@1: case 2: rlm@1: color = RGB(255, 255, 0); break; rlm@1: case 3: rlm@1: color = RGB(0, 255, 0); break; rlm@1: case 4: rlm@1: color = RGB(0, 255, 255); break; rlm@1: case 5: rlm@1: color = RGB(0, 0, 255); break; rlm@1: case 6: rlm@1: color = RGB(255, 0, 255); break; rlm@1: case 7: rlm@1: color = RGB(0, 0, 0); break; rlm@1: } rlm@1: SetTextColor(hdc, color); rlm@1: rlm@1: // draw center text rlm@1: for (int slot = 0; slot < SCREEN_MESSAGE_SLOTS; slot++) rlm@1: { rlm@1: if (theApp.screenMessage[slot]) rlm@1: { rlm@1: if ((theApp.screenMessageDuration[slot] < 0 || rlm@1: (int)(GetTickCount() - theApp.screenMessageTime[slot]) < theApp.screenMessageDuration[slot]) && rlm@1: (!theApp.disableStatusMessage || slot == 1 || slot == 2)) rlm@1: { rlm@1: TextOut(hdc, theApp.dest.left+10, theApp.dest.bottom - 20*(slot+1), theApp.screenMessageBuffer[slot], rlm@1: strlen(theApp.screenMessageBuffer[slot])); rlm@1: } rlm@1: } rlm@1: } rlm@1: } rlm@1: rlm@1: if (textMessageStarted) rlm@1: { rlm@1: ddsPrimary->ReleaseDC(hdc); rlm@1: } rlm@1: } rlm@1: rlm@1: if (hret != DD_OK) rlm@1: { rlm@1: if (theApp.ddrawDebug) rlm@1: winlog("Error on update screen: %08x\n", hret); rlm@1: } rlm@1: } rlm@1: rlm@1: int DirectDrawDisplay::selectFullScreenMode(GUID **pGUID) rlm@1: { rlm@1: return winVideoModeSelect(theApp.m_pMainWnd, pGUID); rlm@1: } rlm@1: rlm@1: IDisplay *newDirectDrawDisplay() rlm@1: { rlm@1: return new DirectDrawDisplay(); rlm@1: } rlm@1: