Sign in to follow this  
i_is_want_smart

DirectDraw Bitmap Blitting (How original :D )

Recommended Posts

Well, hi. I'm trying to get DirectDraw to work, but I have absolutely no idea what I'm doing. I'll show you my code to show you what I've achieved so far... Please tell me why it is turning my screen black instead of displaying a bitmap on it :s Sorry if this question seems stupid or the answer seems obvious to you, I am completely self taught in everything I know, and there reaches a point where you just become absolutely confused and can't get a grasp of the concept without other's help. This is pretty much the first help I've tried to get from actual humans :o Yeah so enough blabbering, and here is my code if you feel like reading through it (I'm hoping this place has BBcode)
#include <windows.h>
#include <ddraw.h>

#pragma comment(lib, "ddraw.lib")

LPDIRECTDRAW lpDD;
LPDIRECTDRAWSURFACE lpMain;
LPDIRECTDRAWSURFACE lpBack;
LPDIRECTDRAWSURFACE lpPic;
bool QuitKey = false;

bool DD_init(HWND hwnd)
{
	HRESULT hr;
	hr = DirectDrawCreate(0, &lpDD, 0);
	if(hr != DD_OK) return false;
	hr = lpDD->SetCooperativeLevel(hwnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
	if(hr != DD_OK) 
	{
		lpDD->Release();
		return false;
	}
	hr = lpDD->SetDisplayMode(1024, 768, 32);
	if(hr != DD_OK)
	{
		lpDD->Release();
		return false;
	}
	return true;
}

IDirectDrawPalette *DDLoadPalette(IDirectDraw * pdd, LPCSTR szBitmap)
{
    IDirectDrawPalette     *ddpal;
    int                     i;
    int                     n;
    int                     fh;
    HRSRC                   h;
    LPBITMAPINFOHEADER      lpbi;
    PALETTEENTRY            ape[256];
    RGBQUAD                *prgb;
    for (i = 0; i < 256; i++)
    {
        ape[i].peRed = (BYTE) (((i >> 5) & 0x07) * 255 / 7);
        ape[i].peGreen = (BYTE) (((i >> 2) & 0x07) * 255 / 7);
        ape[i].peBlue = (BYTE) (((i >> 0) & 0x03) * 255 / 3);
        ape[i].peFlags = (BYTE) 0;
    }
    if (szBitmap && (h = FindResource(NULL, szBitmap, RT_BITMAP)))
    {
        lpbi = (LPBITMAPINFOHEADER) LockResource(LoadResource(NULL, h));
        if (!lpbi)
            OutputDebugString("lock resource failed\n");
        prgb = (RGBQUAD *) ((BYTE *) lpbi + lpbi->biSize);
        if (lpbi == NULL || lpbi->biSize < sizeof(BITMAPINFOHEADER))
            n = 0;
        else if (lpbi->biBitCount > 8)
            n = 0;
        else if (lpbi->biClrUsed == 0)
            n = 1 << lpbi->biBitCount;
        else
            n = lpbi->biClrUsed;
        for (i = 0; i < n; i++)
        {
            ape[i].peRed = prgb[i].rgbRed;
            ape[i].peGreen = prgb[i].rgbGreen;
            ape[i].peBlue = prgb[i].rgbBlue;
            ape[i].peFlags = 0;
        }
    }
    else if (szBitmap && (fh = _lopen(szBitmap, OF_READ)) != -1)
    {
        BITMAPFILEHEADER        bf;
        BITMAPINFOHEADER        bi;

        _lread(fh, &bf, sizeof(bf));
        _lread(fh, &bi, sizeof(bi));
        _lread(fh, ape, sizeof(ape));
        _lclose(fh);
        if (bi.biSize != sizeof(BITMAPINFOHEADER))
            n = 0;
        else if (bi.biBitCount > 8)
            n = 0;
        else if (bi.biClrUsed == 0)
            n = 1 << bi.biBitCount;
        else
            n = bi.biClrUsed;
        for (i = 0; i < n; i++)
        {
            BYTE        r = ape[i].peRed;

            ape[i].peRed = ape[i].peBlue;
            ape[i].peBlue = r;
        }
    }
    pdd->CreatePalette(DDPCAPS_8BIT, ape, &ddpal, NULL);
    return ddpal;
}

bool CreateSurfaces()
{
	DDSURFACEDESC ddsd;
	DDSCAPS ddscaps;
	HRESULT hr;
	memset(&ddsd, 0, sizeof(ddsd));
	ddsd.dwSize = sizeof(ddsd);
	ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
	ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
	ddsd.dwBackBufferCount = 1;
	hr = lpDD->CreateSurface(&ddsd, &lpMain, 0);
	if(hr != DD_OK)
	{
		lpDD->Release();
		return false;
	}
	ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
	hr = lpMain->GetAttachedSurface(&ddscaps, &lpBack);
	if(hr != DD_OK)
	{
		lpMain->Release();
		lpDD->Release();
		return false;
	}
	ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
    ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN |
						  DDSCAPS_VIDEOMEMORY;
	ddsd.dwWidth = 50;
	ddsd.dwHeight = 50;
	hr = lpDD->CreateSurface(&ddsd, &lpPic, 0);
	if(hr != DD_OK)
	{
		lpDD->Release();
		lpMain->Release();
		lpBack->Release();
		return false;
	}
	LPDIRECTDRAWPALETTE lpPalette;
	lpPalette = DDLoadPalette(lpDD, "test.bmp");
	lpMain->SetPalette(lpPalette);
	lpPalette->Release();
	return true;
}


bool LoadBmp(LPDIRECTDRAWSURFACE lpDest, LPCSTR filename)
{
	HDC hdc;
	HDC hdcimage;
	hdcimage = CreateCompatibleDC(0);
	HRESULT hr;
	BITMAP bmp;
	HBITMAP pic = (HBITMAP)LoadImageA(0, filename, 0, 0, 0, LR_LOADFROMFILE);
	GetObject(pic, sizeof(BITMAP), &bmp);
	SelectObject(hdcimage, pic);
	hr = lpDest->GetDC(&hdc);
	if(hr != DD_OK) return false;
	BitBlt(hdc, 0, 0, bmp.bmWidth, bmp.bmHeight, hdcimage, 0, 0, SRCCOPY);
	lpDest->ReleaseDC(hdc);
	DeleteDC(hdcimage);
	DeleteDC(hdc);
	return true;
}


LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
	switch(msg)
	{
	case WM_DESTROY:
		QuitKey = true;
		break;
	}
	return DefWindowProcA(hwnd, msg, wparam, lparam);
}

int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
	MSG msg;
	WNDCLASS wc;
	HWND hwnd;
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hbrBackground = (HBRUSH)(6);
	wc.hCursor = LoadCursorA(0, IDC_ARROW);
	wc.hIcon = 0;
	wc.hInstance = hInstance;
	wc.lpfnWndProc = WndProc;
	wc.lpszClassName = "lol";
	wc.lpszMenuName = 0;
	wc.style = CS_VREDRAW|CS_HREDRAW;
	RegisterClass(&wc);
	hwnd = CreateWindowA("lol", "hi", WS_OVERLAPPEDWINDOW | WS_THICKFRAME, 50, 50, 500, 600, 0, 0, hInstance, 0);
	ShowWindow(hwnd, SW_SHOW);
	if(!DD_init(hwnd))
		return 1;
	if(!CreateSurfaces())
		return 1;
	if(!LoadBmp(lpPic, "test.bmp"))
		return 1;
	RECT rect;
	rect.left = 0;
	rect.top = 0;
	rect.right = 50;
	rect.bottom = 50;
	lpBack->BltFast(0, 0, lpPic, &rect, 1);
	lpMain->Flip(0, 0);
	while(!QuitKey)
	{
		if(PeekMessageA(&msg,0,0,0, PM_REMOVE))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}
	return msg.wParam;
}

Share this post


Link to post
Share on other sites
A little off topic - but why DirectDraw? It's about 8 years old or something, no longer being developed, has almost zero hardware support (Meaning you don't take any advantage of the graphics card at all), is an absolute nightmare to work with, and is useless for just about everything apart from overlays.

The usual way to do this sort of thing is to use Direct3D and draw a textured quad. That way you get hardware acceleration, and you also get rotation, scaling, colour conversion and alpha blending for free.

Share this post


Link to post
Share on other sites
Quote:
Original post by Evil Steve
A little off topic - but why DirectDraw? It's about 8 years old or something, no longer being developed, has almost zero hardware support (Meaning you don't take any advantage of the graphics card at all), is an absolute nightmare to work with, and is useless for just about everything apart from overlays.
More like 12 (or so) years. Anyway, DirectDraw has one gigantic advantage over D3D. It pretty much always just works right out of the box, without having to worry about up-to-date drivers or a modern graphics card or Windows version. Getting D3D to work reliably on a cheap five year old laptop with badly updated drivers is less than fun..
Granted this is probably mostly because because it's largely software emulated and driver developers aren't trying to squeeze every last cycle out of it with dirty tricks and complicated schemes, but it's nevertheless true.
In other words if performance isn't much of an issue and you only need basic blits then DirectDraw (or even GDI, though that lacks hardware page flipping) may well be a valid alternative.

Share this post


Link to post
Share on other sites
Quote:
Original post by Evil Steve
A little off topic - but why DirectDraw? It's about 8 years old or something, no longer being developed, has almost zero hardware support (Meaning you don't take any advantage of the graphics card at all), is an absolute nightmare to work with, and is useless for just about everything apart from overlays.

The usual way to do this sort of thing is to use Direct3D and draw a textured quad. That way you get hardware acceleration, and you also get rotation, scaling, colour conversion and alpha blending for free.



I dunno, I just thought it was the thing to learn before moving on to 3D stuff, but if using Direct3D is better I should probably learn that then ... Thanks for advice.

Share this post


Link to post
Share on other sites
Quote:
Original post by i_is_want_smart
I dunno, I just thought it was the thing to learn before moving on to 3D stuff, but if using Direct3D is better I should probably learn that then ... Thanks for advice.

Nope, you got it wrong. It's a common mistake to think that Direct3D is just for 3D graphics ;)
You can start with "2D" in Direct3D and then you'll have it easier to go for 3D.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this