HRESULT PrimarySurface::Blt(
    LPRECT lpDestRect,
    LPDIRECTDRAWSURFACE lpDDSrcSurface,
    LPRECT lpSrcRect,
    DWORD dwFlags,
    LPDDBLTFX lpDDBltFx
)
{
#if LOGGER
    std::ostringstream str;
    str << this << " " << __FUNCTION__;
    str << tostr_RECT(lpDestRect);

    if (lpDDSrcSurface == this->_deviceResources->_backbufferSurface)
    {
        str << " BackbufferSurface";
    }
    else
    {
        str << " " << lpDDSrcSurface;
    }

    str << tostr_RECT(lpSrcRect);

    if ((dwFlags & DDBLT_COLORFILL) != 0 && lpDDBltFx != nullptr)
    {
        str << " " << (void*)lpDDBltFx->dwFillColor;
    }

    LogText(str.str());
#endif

    if (dwFlags & DDBLT_COLORFILL)
    {
        if (lpDDBltFx == nullptr)
        {
            return DDERR_INVALIDPARAMS;
        }

        return DD_OK;
    }

    if (lpDDSrcSurface != nullptr)
    {
        if (lpDDSrcSurface == this->_deviceResources->_backbufferSurface)
        {
            return this->Flip(NULL, 0);
        }
    }

#if LOGGER
    str.str("\tDDERR_UNSUPPORTED");
    LogText(str.str());
#endif

    return DDERR_UNSUPPORTED;
}
HRESULT OffscreenSurface::Blt(
	LPRECT lpDestRect,
	LPDIRECTDRAWSURFACE lpDDSrcSurface,
	LPRECT lpSrcRect,
	DWORD dwFlags,
	LPDDBLTFX lpDDBltFx
	)
{
#if LOGGER
	std::ostringstream str;
	str << this << " " << __FUNCTION__;
	str << tostr_RECT(lpDestRect);
	str << " " << lpDDSrcSurface;
	str << tostr_RECT(lpSrcRect);

	if ((dwFlags & DDBLT_COLORFILL) != 0 && lpDDBltFx != nullptr)
	{
		str << " " << (void*)lpDDBltFx->dwFillColor;
	}

	LogText(str.str());
#endif

	if (dwFlags & DDBLT_COLORFILL)
	{
		if (lpDDBltFx == nullptr)
		{
#if LOGGER
			str.str("\tDDERR_INVALIDPARAMS");
			LogText(str.str());
#endif

			return DDERR_INVALIDPARAMS;
		}

		unsigned short* buffer = (unsigned short*)this->_buffer;
		int length = this->_bufferSize / 2;
		unsigned short color = (unsigned short)lpDDBltFx->dwFillColor;

		for (int i = 0; i < length; i++)
		{
			buffer[i] = color;
		}

		return DD_OK;
	}

#if LOGGER
	str.str("\tDDERR_UNSUPPORTED");
	LogText(str.str());
#endif

	return DDERR_UNSUPPORTED;
}
HRESULT OffscreenSurface::Lock(
	LPRECT lpDestRect,
	LPDDSURFACEDESC lpDDSurfaceDesc,
	DWORD dwFlags,
	HANDLE hEvent
	)
{
#if LOGGER
	std::ostringstream str;
	str << this << " " << __FUNCTION__;
	str << tostr_RECT(lpDestRect);
	LogText(str.str());
#endif

	if (lpDDSurfaceDesc == nullptr)
	{
#if LOGGER
		str.str("\tDDERR_INVALIDPARAMS");
		LogText(str.str());
#endif

		return DDERR_INVALIDPARAMS;
	}

	if (lpDestRect == nullptr)
	{
		memset(lpDDSurfaceDesc, 0, sizeof(DDSURFACEDESC));
		lpDDSurfaceDesc->dwSize = sizeof(DDSURFACEDESC);
		lpDDSurfaceDesc->dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
		lpDDSurfaceDesc->ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
		lpDDSurfaceDesc->ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
		lpDDSurfaceDesc->ddpfPixelFormat.dwFlags = DDPF_RGB;
		lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount = 16;
		lpDDSurfaceDesc->ddpfPixelFormat.dwRBitMask = 0xF800;
		lpDDSurfaceDesc->ddpfPixelFormat.dwGBitMask = 0x7E0;
		lpDDSurfaceDesc->ddpfPixelFormat.dwBBitMask = 0x1F;
		lpDDSurfaceDesc->dwHeight = this->_deviceResources->_displayHeight;
		lpDDSurfaceDesc->dwWidth = this->_deviceResources->_displayWidth;
		lpDDSurfaceDesc->lPitch = this->_deviceResources->_displayWidth * 2;
		lpDDSurfaceDesc->lpSurface = this->_buffer;

		return DD_OK;
	}

#if LOGGER
	str.str("\tDDERR_UNSUPPORTED");
	LogText(str.str());
#endif

	return DDERR_UNSUPPORTED;
}
HRESULT TextureSurface::Lock(
	LPRECT lpDestRect,
	LPDDSURFACEDESC lpDDSurfaceDesc,
	DWORD dwFlags,
	HANDLE hEvent
	)
{
#if LOGGER
	std::ostringstream str;
	str << this << " " << __FUNCTION__;
	str << tostr_RECT(lpDestRect);
	LogText(str.str());
#endif

	if (!this->_allocOnLoad)
	{
		if (lpDDSurfaceDesc == nullptr)
		{
#if LOGGER
			str.str("\tDDERR_INVALIDPARAMS");
			LogText(str.str());
#endif

			return DDERR_INVALIDPARAMS;
		}

		if (lpDestRect == nullptr)
		{
			*lpDDSurfaceDesc = {};
			lpDDSurfaceDesc->dwSize = sizeof(DDSURFACEDESC);
			lpDDSurfaceDesc->dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
			lpDDSurfaceDesc->ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY;
			lpDDSurfaceDesc->ddpfPixelFormat = this->_pixelFormat;
			lpDDSurfaceDesc->dwHeight = this->_height;
			lpDDSurfaceDesc->dwWidth = this->_width;
			lpDDSurfaceDesc->lPitch = this->_width * this->_pixelFormat.dwRGBBitCount / 8;
			lpDDSurfaceDesc->lpSurface = this->_buffer;

			return DD_OK;
		}
	}

#if LOGGER
	str.str("\tDDERR_UNSUPPORTED");
	LogText(str.str());
#endif

	return DDERR_UNSUPPORTED;
}
HRESULT PrimarySurface::BltFast(
    DWORD dwX,
    DWORD dwY,
    LPDIRECTDRAWSURFACE lpDDSrcSurface,
    LPRECT lpSrcRect,
    DWORD dwTrans
)
{
#if LOGGER
    std::ostringstream str;
    str << this << " " << __FUNCTION__;
    str << " " << dwX << " " << dwY;

    if (lpDDSrcSurface == nullptr)
    {
        str << " NULL";
    }
    else if (lpDDSrcSurface == this->_deviceResources->_backbufferSurface)
    {
        str << " BackbufferSurface";
    }
    else
    {
        str << " " << lpDDSrcSurface;
    }

    str << tostr_RECT(lpSrcRect);

    if (dwTrans & DDBLTFAST_SRCCOLORKEY)
    {
        str << " SRCCOLORKEY";
    }

    if (dwTrans & DDBLTFAST_DESTCOLORKEY)
    {
        str << " DESTCOLORKEY";
    }

    if (dwTrans & DDBLTFAST_WAIT)
    {
        str << " WAIT";
    }

    if (dwTrans & DDBLTFAST_DONOTWAIT)
    {
        str << " DONOTWAIT";
    }

    LogText(str.str());
#endif

    if (lpDDSrcSurface != nullptr)
    {
        if (lpDDSrcSurface == this->_deviceResources->_backbufferSurface)
        {
            return this->Flip(this->_deviceResources->_backbufferSurface, 0);
        }
    }

#if LOGGER
    str.str("\tDDERR_UNSUPPORTED");
    LogText(str.str());
#endif

    return DDERR_UNSUPPORTED;
}
HRESULT BackbufferSurface::Lock(
	LPRECT lpDestRect,
	LPDDSURFACEDESC lpDDSurfaceDesc,
	DWORD dwFlags,
	HANDLE hEvent
	)
{
#if LOGGER
	std::ostringstream str;
	str << this << " " << __FUNCTION__;
	str << tostr_RECT(lpDestRect);
	LogText(str.str());
#endif

	if (lpDDSurfaceDesc == nullptr)
	{
#if LOGGER
		str.str("\tDDERR_INVALIDPARAMS");
		LogText(str.str());
#endif

		return DDERR_INVALIDPARAMS;
	}

	if (lpDestRect == nullptr)
	{		
		memset(lpDDSurfaceDesc, 0, sizeof(DDSURFACEDESC));
		lpDDSurfaceDesc->dwSize = sizeof(DDSURFACEDESC);
		lpDDSurfaceDesc->dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PITCH | DDSD_LPSURFACE;
		lpDDSurfaceDesc->ddsCaps.dwCaps = DDSCAPS_BACKBUFFER | DDSCAPS_VIDEOMEMORY;
		lpDDSurfaceDesc->ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
		lpDDSurfaceDesc->ddpfPixelFormat.dwFlags = DDPF_RGB;
		lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount = 16;
		lpDDSurfaceDesc->ddpfPixelFormat.dwRBitMask = 0xF800;
		lpDDSurfaceDesc->ddpfPixelFormat.dwGBitMask = 0x7E0;
		lpDDSurfaceDesc->ddpfPixelFormat.dwBBitMask = 0x1F;
		lpDDSurfaceDesc->dwHeight = this->_deviceResources->_displayHeight;
		lpDDSurfaceDesc->dwWidth = this->_deviceResources->_displayWidth;
		lpDDSurfaceDesc->lPitch = this->_deviceResources->_displayWidth * this->_deviceResources->_displayBpp;
		lpDDSurfaceDesc->lpSurface = this->_buffer;

		if (this->_deviceResources->_frontbufferSurface != nullptr)
		{
			memset(this->_buffer, 0x80, this->_bufferSize);
			lpDDSurfaceDesc->lPitch = this->_deviceResources->_displayWidth * 2;
		}
		else
		{
			if (this->_deviceResources->inScene)
			{
				if (!this->_deviceResources->inSceneBackbufferLocked)
				{
					memset(this->_buffer, 0, this->_bufferSize);
				}

				this->_deviceResources->inSceneBackbufferLocked = true;
			}

			if (!this->_deviceResources->inScene && this->_deviceResources->sceneRenderedEmpty)
			{
				this->_deviceResources->sceneRenderedEmpty = false;

#if LOGGER
				str.str("\tSCREENSHOT flight");
				LogText(str.str());
#endif

				this->_deviceResources->RetrieveBackBuffer(this->_buffer, this->_deviceResources->_displayWidth, this->_deviceResources->_displayHeight, this->_deviceResources->_displayBpp);
			}

		}

		return DD_OK;
	}

#if LOGGER
	str.str("\tDDERR_UNSUPPORTED");
	LogText(str.str());
#endif

	return DDERR_UNSUPPORTED;
}
HRESULT BackbufferSurface::BltFast(
	DWORD dwX,
	DWORD dwY,
	LPDIRECTDRAWSURFACE lpDDSrcSurface,
	LPRECT lpSrcRect,
	DWORD dwTrans
	)
{
#if LOGGER
	std::ostringstream str;
	str << this << " " << __FUNCTION__;
	str << " " << dwX << " " << dwY;

	if (lpDDSrcSurface == nullptr)
	{
		str << " NULL";
	}
	else if (lpDDSrcSurface == this->_deviceResources->_frontbufferSurface)
	{
		str << " FrontbufferSurface";
	}
	else if (lpDDSrcSurface == this->_deviceResources->_offscreenSurface)
	{
		str << " OffscreenSurface";
	}
	else
	{
		str << " " << lpDDSrcSurface;
	}

	str << tostr_RECT(lpSrcRect);

	if (dwTrans & DDBLTFAST_SRCCOLORKEY)
	{
		str << " SRCCOLORKEY";
	}

	if (dwTrans & DDBLTFAST_DESTCOLORKEY)
	{
		str << " DESTCOLORKEY";
	}

	if (dwTrans & DDBLTFAST_WAIT)
	{
		str << " WAIT";
	}

	if (dwTrans & DDBLTFAST_DONOTWAIT)
	{
		str << " DONOTWAIT";
	}

	LogText(str.str());
#endif

	if (lpDDSrcSurface != nullptr)
	{
		if (lpDDSrcSurface == this->_deviceResources->_frontbufferSurface)
		{
			copySurface(this->_buffer, this->_deviceResources->_displayWidth, this->_deviceResources->_displayHeight, this->_deviceResources->_displayBpp, this->_deviceResources->_frontbufferSurface->_buffer, this->_deviceResources->_displayWidth, this->_deviceResources->_displayHeight, 2, dwX, dwY, lpSrcRect, (dwTrans & DDBLTFAST_SRCCOLORKEY) != 0);
			this->_deviceResources->_frontbufferSurface->wasBltFastCalled = true;
			return DD_OK;
		}

		if (lpDDSrcSurface == this->_deviceResources->_offscreenSurface)
		{
			copySurface(this->_buffer, this->_deviceResources->_displayWidth, this->_deviceResources->_displayHeight, this->_deviceResources->_displayBpp, this->_deviceResources->_offscreenSurface->_buffer, this->_deviceResources->_displayWidth, this->_deviceResources->_displayHeight, 2, dwX, dwY, lpSrcRect, (dwTrans & DDBLTFAST_SRCCOLORKEY) != 0);
			return DD_OK;
		}
	}

#if LOGGER
	str.str("\tDDERR_UNSUPPORTED");
	LogText(str.str());
#endif

	return DDERR_UNSUPPORTED;
}
HRESULT BackbufferSurface::Blt(
	LPRECT lpDestRect,
	LPDIRECTDRAWSURFACE lpDDSrcSurface,
	LPRECT lpSrcRect,
	DWORD dwFlags,
	LPDDBLTFX lpDDBltFx
	)
{
#if LOGGER
	std::ostringstream str;
	str << this << " " << __FUNCTION__;
	str << tostr_RECT(lpDestRect);
	str << " " << lpDDSrcSurface;
	str << tostr_RECT(lpSrcRect);

	if ((dwFlags & DDBLT_COLORFILL) != 0 && lpDDBltFx != nullptr)
	{
		str << " " << (void*)lpDDBltFx->dwFillColor;
	}

	LogText(str.str());
#endif

	if (dwFlags & DDBLT_COLORFILL)
	{
		if (lpDDBltFx == nullptr)
		{
			return DDERR_INVALIDPARAMS;
		}

		//if (this->_deviceResources->_displayBpp == 2)
		//{
		//	unsigned short* buffer = (unsigned short*)this->_buffer;
		//	int length = this->_bufferSize / 2;
		//	unsigned short color = (unsigned short)lpDDBltFx->dwFillColor;

		//	for (int i = 0; i < length; i++)
		//	{
		//		buffer[i] = color;
		//	}
		//}
		//else
		//{
		//	unsigned int* buffer = (unsigned int*)this->_buffer;
		//	int length = this->_bufferSize / 4;
		//	unsigned short color16 = (unsigned short)lpDDBltFx->dwFillColor;

		//	unsigned int red = (color16 & 0xF800) >> 8;
		//	unsigned int green = (color16 & 0x7E0) >> 3;
		//	unsigned int blue = (color16 & 0x1F) << 3;

		//	unsigned int color = (red << 16) | (green << 8) | blue;

		//	for (int i = 0; i < length; i++)
		//	{
		//		buffer[i] = color;
		//	}
		//}

		memset(this->_buffer, 0, this->_bufferSize);

		return DD_OK;
	}

#if LOGGER
	str.str("\tDDERR_UNSUPPORTED");
	LogText(str.str());
#endif

	return DDERR_UNSUPPORTED;
}