Program crashes immediately after launch...

I'm trying to get a window up using unmanaged dx9. It compiles, but for some reason it never actually gets to run() and breaks where it says if (msg.message == WM_QUIT). I'm sure I've gotmost of it right, but am missing something stupid....

Here's what I have:

// cppdx9demo001.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include "cppdx9demo001.h"

#define MAX_LOADSTRING 100

// Global Variables:
HWND hWnd;
HINSTANCE hInst; // current instance
TCHAR szTitle[MAX_LOADSTRING]; // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name

// Forward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);

int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);

// TODO: Place code here.
MSG msg;
HACCEL hAccelTable;

// Initialize global strings
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_CPPDX9DEMO001, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);

// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return -2;
}

hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_CPPDX9DEMO001));

if (!GAMEENGINE->Start(hWnd, hInstance))
{
//assert(0);
//OutputDebugString("Failed to start the game!\n");
return -1;
}

// Main message loop:
do
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message = WM_QUIT)
{
break;
}

TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
GAMEENGINE->Run();
}
}
while(true);

return GAMEENGINE->Shutdown();
}

//
// FUNCTION: MyRegisterClass()
//
// PURPOSE: Registers the window class.
//
// COMMENTS:
//
// This function and its usage are only necessary if you want this code
// to be compatible with Win32 systems prior to the 'RegisterClassEx'
// function that was added to Windows 95. It is important to call this function
// so that the application will get 'well formed' small icons associated
// with it.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;

wcex.cbSize = sizeof(WNDCLASSEX);

wcex.style = CS_CLASSDC;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_CPPDX9DEMO001));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_CPPDX9DEMO001);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

return RegisterClassEx(&wcex);
}

//
// FUNCTION: InitInstance(HINSTANCE, int)
//
// PURPOSE: Saves instance handle and creates main window
//
// COMMENTS:
//
// In this function, we save the instance handle in a global variable and
// create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // Store instance handle in our global variable

hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
graphics::DEFAULT_SCREEN_WIDTH,
graphics::DEFAULT_SCREEN_HEIGHT,
GetDesktopWindow(), NULL, hInstance, NULL);

if (!hWnd)
{
return FALSE;
}

ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);

return TRUE;
}

//
// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// PURPOSE: Processes messages for the main window.
//
// WM_COMMAND - process the application menu
// WM_PAINT - Paint the main window
// WM_DESTROY - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;

switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code here...
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}

// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;

case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}

//cppdx9demo001.h
#pragma once

#include "resource.h"
#include "graphics.h"

#define GAMEENGINE graphics::cGameEngine::getInstance()

//graphics.h
#include "stdafx.h"
#include "vardefines.h"
#include <d3d9.h>
#include <d3dx9.h>

namespace graphics
{
const indUInt DEFAULT_SCREEN_WIDTH = 640;
const indUInt DEFAULT_SCREEN_HEIGHT = 480;
const indReal32 DEFAULT_GAME_FPS = 60.0f;

class cGameEngine
{
public:
virtual ~cGameEngine(){};

private:
cGameEngine(){};

template <class T>
inline void SAFE_RELEASE(T*& pObj)
{
if(pObj != NULL)
{
pObj->Release();
pObj = NULL;
}

else
{
//debug code here
}
}

indBool InitializeGraphics()
{
ZeroMemory( &m_D3DPresentParams, sizeof(m_D3DPresentParams) );

if (NULL == (m_pDirect3D = Direct3DCreate9(D3D_SDK_VERSION)))
{
return false;
}

if (m_bFullscreen)
{
m_D3DPresentParams.BackBufferWidth = m_ScreenWidth;
m_D3DPresentParams.BackBufferHeight = m_ScreenHeight;
m_D3DPresentParams.BackBufferFormat = D3DFMT_A8R8G8B8;
m_D3DPresentParams.BackBufferCount = 1;
m_D3DPresentParams.MultiSampleType = D3DMULTISAMPLE_NONE;
m_D3DPresentParams.MultiSampleQuality = 0;
m_D3DPresentParams.SwapEffect = D3DSWAPEFFECT_DISCARD;
m_D3DPresentParams.hDeviceWindow = *m_hMainWnd;
m_D3DPresentParams.Windowed = FALSE;
m_D3DPresentParams.EnableAutoDepthStencil = 1;
m_D3DPresentParams.AutoDepthStencilFormat = D3DFMT_D24S8;
m_D3DPresentParams.Flags = D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL;
m_D3DPresentParams.FullScreen_RefreshRateInHz = 0;
m_D3DPresentParams.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
}

else
{
m_D3DPresentParams.BackBufferWidth = m_ScreenWidth;
m_D3DPresentParams.BackBufferHeight = m_ScreenHeight;
m_D3DPresentParams.BackBufferFormat = D3DFMT_UNKNOWN;
m_D3DPresentParams.BackBufferCount = 1;
m_D3DPresentParams.MultiSampleType = D3DMULTISAMPLE_NONE;
m_D3DPresentParams.MultiSampleQuality = 0;
m_D3DPresentParams.SwapEffect = D3DSWAPEFFECT_DISCARD;
m_D3DPresentParams.hDeviceWindow = *m_hMainWnd;
m_D3DPresentParams.Windowed = TRUE;
m_D3DPresentParams.EnableAutoDepthStencil = 1;
m_D3DPresentParams.AutoDepthStencilFormat = D3DFMT_D24S8;
m_D3DPresentParams.Flags = D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL;
m_D3DPresentParams.FullScreen_RefreshRateInHz = 0;
m_D3DPresentParams.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
}

CreateDevice();

m_pDevice->SetRenderState(D3DRS_LIGHTING, 0);

m_pDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
m_pDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
m_pDevice->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);

return true;
}

indBool CreateDevice()
{
HRESULT hr = m_pDirect3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
*m_hMainWnd,
D3DCREATE_HARDWARE_VERTEXPROCESSING,
&m_D3DPresentParams, &m_pDevice);

if (FAILED(hr))
{
//printf("Failed to create device");
return false;
}
return true;
}

indBool ValidateDevice()
{
HRESULT deviceState = m_pDevice->TestCooperativeLevel();

if (deviceState = D3D_OK)
{
return true;
}

if (deviceState = D3DERR_DRIVERINTERNALERROR)
{
return false;
}

if (deviceState = D3DERR_DEVICENOTRESET)
{
SAFE_RELEASE(m_pDevice);
CreateDevice();
return true;
}

return false;
}

indBool PreRender()
{
m_pDevice->BeginScene();

m_pDevice->Clear(0, NULL,
D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL,
D3DCOLOR_XRGB(0,0, 100),1.0f, 0);

return true;
}

indBool Render()
{
return true;
}

indBool PostRender()
{
m_pDevice->EndScene();
m_pDevice->Present(0,0,0,0);
return true;
}

public:
bool Start(HWND hWnd, HINSTANCE hInstance)
{
m_hMainWnd = &hWnd;
if (!InitializeGraphics())
return false;

return true;
}

indInt Run()
{
if(!ValidateDevice())
return 0;

PreRender();
Render();
PostRender();

return true;
}

indBool Shutdown()
{
SAFE_RELEASE(m_pDevice);
SAFE_RELEASE(m_pDirect3D);

return true;
}

static cGameEngine* getInstance()
{
if(!ms_InstanceFlag)
{
ms_pEngine = new cGameEngine();
ms_InstanceFlag = true;
return ms_pEngine;
}
else
{
return ms_pEngine;
}

}

protected:
HWND* m_hMainWnd;
HINSTANCE m_hInstance;
static cGameEngine* ms_pEngine;
static bool ms_InstanceFlag;

D3DPRESENT_PARAMETERS m_D3DPresentParams;

LPDIRECT3DDEVICE9 m_pDevice;
LPDIRECT3D9 m_pDirect3D;

static indUInt m_ScreenWidth;
static indUInt m_ScreenHeight;
static indBool m_bFullscreen;
};
}

//graphics.cpp
#include "stdafx.h"
#include "graphics.h"

namespace graphics
{
bool cGameEngine::ms_InstanceFlag = false;
indBool cGameEngine::m_bFullscreen = false;
indUInt cGameEngine::m_ScreenWidth = 640;
indUInt cGameEngine::m_ScreenHeight = 480;

cGameEngine* cGameEngine::ms_pEngine = NULL;
}

// vardefines.h
#define indInt int
#define indUInt unsigned int
#define indReal32 float
#define indBool bool

[11235 byte] By [DanoruX] at [2007-12-23]
# 1

The first question I always ask is: Have you compared your program infrastructure to the "Empty Project" sample in the DX Sample Browser?

DavidWeller at 2007-8-30 > top of Msdn Tech,Game Technologies: DirectX, XNA, XACT, etc.,Game Technologies: DirectX 101...
# 2
David Weller wrote:

The first question I always ask is: Have you compared your program infrastructure to the "Empty Project" sample in the DX Sample Browser?

No, because looking through emptyproject in the first place requires looking through literally 20000 lines of code.

DanoruX at 2007-8-30 > top of Msdn Tech,Game Technologies: DirectX, XNA, XACT, etc.,Game Technologies: DirectX 101...
# 3

How is it crashing? Is it actually crashing, or does the window just close as soon as you run the program?

Here's one problem I see in your message loop, and it may be painfully obvious:

if (msg.message = WM_QUIT)
{
break;
}

it's using an assignment operator. Should be a comparison operator (==) like you said at the begining of your post.

Also, I would try using the reference device until you get the program to a stable operation. So instead of D3DDEVTYPE_HAL use D3DDEVTYPE_REF.

There's a lot of other small things that I would change about the over all structure and names (I would rename cGameEngine to cGraphics, not only because it's in the cGaphics namespace, but also because it's not a game engine. You can't really sum up a game engine in one class unless it encapsulates all the other classes that make it tick), but it's probably just a matter of personal preference. It just looks kind of messy...

Hope that helps.

Ridiculous at 2007-8-30 > top of Msdn Tech,Game Technologies: DirectX, XNA, XACT, etc.,Game Technologies: DirectX 101...
# 4
D'oh! I should've seen that typo sooner...

Yeah, I know alot of stuff should be renamed, I just wanted to get something compilable first.

Thanks alot!

DanoruX at 2007-8-30 > top of Msdn Tech,Game Technologies: DirectX, XNA, XACT, etc.,Game Technologies: DirectX 101...