Archived

This topic is now archived and is closed to further replies.

Direct3d opens... then closes?!?!

This topic is 5176 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Well that title explains it all... I found some GREAT direct3d tutorials that had compilable code that would open, then close straight away. i checked my paths over and over again... they all check out... This same thing happened with the "Zen of D3D game programming" book''s source. The win32 programs work fine, but when he adds the d3d initialization code, i see the window come up for a brief second then it closes. I debugged the code and it sais that one of the initialization procedures failed. I tried as many things as i could, but it still wouldnt work... any ideas? This is the procedure it fails on: r = pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWndTarget, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, ppDevice ); pD3D was used before, and that procedure passed (pD3D->GetAdapterDisplayMode) so im stumped... Any help would be greatly appreciated! Chris

Share this post


Link to post
Share on other sites
This may be related to drivers. I have had problems with NVIDIA Detonator drivers for the last few releases. D3D device creation always fails. If you recently upgraded the driver, revert back to the last version that worked.

Share this post


Link to post
Share on other sites
A directX 9 game that didnt work on my computer worked on another of my computers, which is newer and has a far more superior graphics card. Do you think that my old laptop cant take the newest d3d versions? I think this problem only happens with directX 9...

So the driver is the problem?

Share this post


Link to post
Share on other sites
And actually this is a d3d 8 program that i am having trouble with... interesting...

O and if this helps, i compile the sample program, then move it to my better, newer comp but it still doesnt work... I think its a problem in the coding but i dont know what could be wronge...

[edited by - Pirosan on October 14, 2003 7:49:59 PM]

Share this post


Link to post
Share on other sites
Maybe you're trying to initialize Direct3D to a resolution your computer can't handle?

Try 640x480 at 16 bit colour. Or even 256 colours.

If that doesn't work, you should post some code.

[edited by - glassJAw on October 14, 2003 7:53:23 PM]

Share this post


Link to post
Share on other sites
ok i have 2 source files.. the first is main.cpp:

//

////////////////////////////////////////////

//

// Author: Peter Walsh

// 9th Dec 2000

//

//

//


#define WIN32_LEAN_AND_MEAN

// The main windows include file

#include <windows.h>
#include <mmsystem.h>

#include <d3d8.h>
#include <d3dx8.h>

#include "Engine.h"

int GameInit();
int GameLoop();
int GameShutdown();
int Render();

CConsole Console;
int ConsoleParser( CCommand* pCommand );

HWND g_hWndMain;

struct ZENVERTEX
{
float x, y, z;
DWORD DiffuseColor;
};

#define CUSTOM_ZENVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE)

LPDIRECT3DVERTEXBUFFER8 g_pVB = 0;


// The window procedure to handle events

long CALLBACK WndProc( HWND hWnd, UINT uMessage,
WPARAM wParam, LPARAM lParam )
{

// Switch the windows message to figure out what it is

switch( uMessage )
{
case WM_CREATE: // The CreateWindow() function was just called

{
// One Time Initialization

return 0;
}

case WM_PAINT: // The window needs to be redrawn

{
ValidateRect( hWnd, NULL );

return 0;
}

case WM_KEYDOWN:
{
Console.OnKeyDown( wParam );

return 0;
}

case WM_CHAR:
{
Console.OnChar( wParam );

return 0;
}

case WM_DESTROY: // The window is about to be closed

{
// Our main window is closing. This means we want our app to exit.

// Tell windows to put a WM_QUIT message in our message queue

PostQuitMessage( 0 );
return 0;
}

default: // Some other message

{
// Let windows handle this message

return DefWindowProc( hWnd, uMessage, wParam, lParam );
}
}
}

// The windows entry point. The application will start executing here

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR pstrCmdLine, int iCmdShow )
{
HWND hWnd; // The handle to our main window

MSG msg; // The message windows is sending us

WNDCLASSEX wc; // The window class used to create our window


// The name of our class and also the title to our window

static char strAppName[] = "First Windows App, Zen Style";

// Fill in the window class with the attributes for our main window


// The size of this struture in bytes

wc.cbSize = sizeof( WNDCLASSEX );

// The style of the window.

wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
// Useless information. Just set to zero.

wc.cbClsExtra = 0;
// Useless information. Just set to zero.

wc.cbWndExtra = 0;
// The name of our event handler

wc.lpfnWndProc = WndProc;
// A handle to the applications instance

wc.hInstance = hInstance;
// The handle to the brush to use for the window background

wc.hbrBackground = (HBRUSH)GetStockObject( DKGRAY_BRUSH );
// A handle to the icon to use for the window

wc.hIcon = LoadIcon( NULL, IDI_APPLICATION );
// A handle to a smaller version of the apps icon

wc.hIconSm = LoadIcon( NULL, IDI_APPLICATION );
// A handle to the cursor to use while the mouse is over our window

wc.hCursor = LoadCursor( NULL, IDC_CROSS );
// A handle to the resource to use as our menu

wc.lpszMenuName = NULL;
// The human readable name for this class

wc.lpszClassName = strAppName;

// Register the class with windows

RegisterClassEx( &wc );

// Create the window based on the previous class

hWnd = CreateWindowEx( WS_EX_TOPMOST, // Advanced style settings

strAppName, // The name of the class

strAppName, // The window caption

WS_POPUP | WS_SYSMENU | WS_VISIBLE ,// The window style

CW_USEDEFAULT, // The initial x position

CW_USEDEFAULT, // The initial y position

512, 512, // The intiial width / height

NULL, // Handle to parent window

NULL, // Handle to the menu

hInstance, // Handle to the apps instance

NULL ); // Advanced context


g_hWndMain = hWnd;

// Display the window we just created

ShowWindow( hWnd, iCmdShow );
// Draw the window contents for the first time

UpdateWindow( hWnd );

if( FAILED( GameInit() ) )
{
SetError( "Initialization Failed" );
GameShutdown();
return E_FAIL;
}

// Start the message loop

while( TRUE )
{
// Check if a message is waiting for processing

if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
{
// Check if the message is to quit the application

if( msg.message == WM_QUIT )
// Exit the message loop

break;

// Change the format of certain messages

TranslateMessage( &msg );
// Pass the message to WndProc() for processing

DispatchMessage( &msg );
}
else
{
GameLoop();
}
}

GameShutdown();

// Return control to windows with the exit code

return msg.wParam;
}



int GameInit()
{

HRESULT r = 0;

// Acquire a pointer to IDirect3D8

g_pD3D = Direct3DCreate8( D3D_SDK_VERSION );
if( g_pD3D == NULL )
{
SetError( "Could not create IDirect3D8 object" );
return E_FAIL;
}

// Create the device

r = InitDirect3DDevice( g_hWndMain, 640, 480, FALSE, D3DFMT_A8R8G8B8, g_pD3D, &g_pDevice );
if( FAILED( r ) )
{
SetError( "Initialization of the device failed" );
return E_FAIL;
}

CreateViewport();

SetProjectionMatrix();

D3DXMATRIX ViewMatrix;
D3DXMatrixLookAtLH( &ViewMatrix, &D3DXVECTOR3( 0.0f, 3.0f,-5.0f ),
&D3DXVECTOR3( 0.0f, 0.0f, 0.0f ),
&D3DXVECTOR3( 0.0f, 1.0f, 0.0f ) );

g_pDevice->SetTransform( D3DTS_VIEW, &ViewMatrix );

// Clear the back buffer

g_pDevice->Clear( 0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB( 0, 0, 55 ), 1.0f, 0 );

// Get a pointer to the back buffer and save it in a global variable

r = g_pDevice->GetBackBuffer( 0, D3DBACKBUFFER_TYPE_MONO, &g_pBackSurface );
if( FAILED( r ) )
{
SetError( "Couldnt get backbuffer" );
return E_FAIL;
}

// Load the alphabet

LoadAlphabet( "Alphabet vSmall.bmp", 8, 16 );

// Intialize timing for frame rate counters, etc

srand( GetTickCount() );
InitTiming();

// Initialize the console

Console.Initialize( g_pDevice, g_pBackSurface );
Console.SetParserCallback( ConsoleParser );

// The vertices for the triangle

ZENVERTEX ZenVertices[] =
{
{ -2.0f,-2.0f, 0.0f, D3DCOLOR_XRGB( 255, 0, 0 ), },
{ 2.0f,-2.0f, 0.0f, D3DCOLOR_XRGB( 255, 255, 0 ), },
{ 0.0f, 2.0f, 0.0f, D3DCOLOR_XRGB( 0, 0, 255 ), },
};

// Create the vertex buffer

r = g_pDevice->CreateVertexBuffer( sizeof(ZENVERTEX)*3, 0, CUSTOM_ZENVERTEX, D3DPOOL_DEFAULT, &g_pVB );
if( FAILED( r ) )
{
SetError( "Couldnt create the vertex buffer" );
return E_FAIL;
}


// Pointer to the vertex buffer

BYTE* pVertices = 0;

// Lock the vertex buffer

r = g_pVB->Lock( 0, sizeof( ZenVertices ), &pVertices, 0 );
if( FAILED( r ) )
{
SetError( "Could not lock the vertex buffer" );
return E_FAIL;
}
// Turn off culling so the back of the triangle does not disapear

g_pDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );

// Turn off lighting because we have are own colors for the vertices

g_pDevice->SetRenderState( D3DRS_LIGHTING, FALSE );


// Fill the buffer with the vertices

CopyMemory( pVertices, &ZenVertices, sizeof( ZenVertices ) );

// Unlock the buffer

g_pVB->Unlock();


return S_OK;
}

int GameLoop()
{
FrameCount();

Render();

if( GetAsyncKeyState( VK_ESCAPE ) )
PostQuitMessage(0);

return S_OK;
}

int GameShutdown()
{
Console.Shutdown();

UnloadAlphabet();

if( g_pVB )
g_pVB->Release();

// Release the pointer to the back surface

if( g_pBackSurface )
g_pBackSurface->Release();

// Release the pointer to IDirect3DDevice8

if( g_pDevice )
g_pDevice->Release();

// Release the pointer to IDirect3D8

if( g_pD3D )
g_pD3D->Release();

return S_OK;
}



int Render()
{
HRESULT r = 0;

g_pDevice->Clear( 0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB( 0, 0, 100 ), 1.0f, 0 );

// Make sure the device is valid

if( !g_pDevice )
{
SetError( "Cannot render because there is no device" );
return E_FAIL;
}

// Return if the device is not ready;

r = ValidateDevice();
if( FAILED( r ) )
{
return E_FAIL;
}

D3DLOCKED_RECT Locked;

g_pBackSurface->LockRect( &Locked, 0, 0 );

// Render text

PrintFrameRate( 550, 400, TRUE, D3DCOLOR_ARGB( 255, 255, 0, 255 ), (DWORD*)Locked.pBits, Locked.Pitch );

// Unlock the back surface

g_pBackSurface->UnlockRect();

D3DXMATRIX RotationX, RotationY, WorldMatrix;

D3DXMatrixRotationY( &RotationY, timeGetTime()/200.0f );
D3DXMatrixRotationX( &RotationX, timeGetTime()/800.0f );
D3DXMatrixMultiply( &WorldMatrix, &RotationX, &RotationY );

g_pDevice->SetTransform( D3DTS_WORLD, &WorldMatrix );

// Tell Direct3D we are about to start rendering in 3D

g_pDevice->BeginScene();

// Set the rendering stream

g_pDevice->SetStreamSource( 0, g_pVB, sizeof(ZENVERTEX) );

// Set the vertex shading mode

g_pDevice->SetVertexShader( CUSTOM_ZENVERTEX );

// Draw the triangle

g_pDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 1 );

// Tell Direct3D we have finished drawing in 3D

g_pDevice->EndScene();

// Render the console

Console.Render();

// Present the back buffer to the primary surface

r = g_pDevice->Present( NULL, NULL, NULL, NULL );

return S_OK;
}

int ConsoleParser( CCommand* pCommand )
{
char* pstrCmd = pCommand->pstrCommand;
char* pstrParams[MAX_PARAMS];
memcpy( &pstrParams, &(pCommand->pstrParams), sizeof( pstrParams ) );
int NumParams = pCommand->NumParams;

if( MATCH( pstrCmd, "exit" ) || MATCH( pstrCmd, "quit" ) )
{
PostQuitMessage(0);
return 0;
}
if( MATCH( pstrCmd, "cls" ) )
{
Console.Clear();
return 0;
}

if( MATCH( pstrCmd, "add" ) )
{
if( NumParams < 2 )
return E_FAIL;

int a = ParseStringForNumber( pstrParams[0] );
int b = ParseStringForNumber( pstrParams[1] );

int Result = a + b;

char OutputString[20];

itoa( Result, OutputString, 10 );

Console.OutputString( OutputString );

return S_OK;

}

return -1;
}





Then there is the Engine.h:


////////////////////////////

// Purpose: Engine Code

// Author: Peter Walsh

//



#include <stdio.h>

HRESULT RestoreGraphics();

LPDIRECT3DSURFACE8 g_pBackSurface = 0;

int g_DeviceWidth = 0;
int g_DeviceHeight = 0;

const int MAX_CHARSPERLINE = 256;

#define MATCH(a, b) (!strcmp( a, b ))

D3DPRESENT_PARAMETERS g_SavedPresParams;

/**************************************************************
***************************************************************

Generic Code

***************************************************************
**************************************************************/


// Output an error to the debug window

void SetError( char* String )
{
OutputDebugString( "ERROR: " );
OutputDebugString( String );
OutputDebugString( "\n" );
}

// This function attempts to parse the supplied string

// and return an integer. It returns 0 if it is

// unable to parse the string.

int ParseStringForNumber( char* pString )
{
// Some boolean tests

if( MATCH( pString, "on" ) )
return 1;
if( MATCH( pString, "off" ) )
return 0;
if( MATCH( pString, "true" ) )
return 1;
if( MATCH( pString, "false" ) )
return 0;
if( MATCH( pString, "yes" ) )
return 1;
if( MATCH( pString, "no" ) )
return 0;

// Some spelled number tests

if( MATCH( pString, "zero" ) )
return 0;
if( MATCH( pString, "one" ) )
return 1;
if( MATCH( pString, "two" ) )
return 2;
if( MATCH( pString, "three" ) )
return 3;
if( MATCH( pString, "four" ) )
return 4;
if( MATCH( pString, "five" ) )
return 5;
if( MATCH( pString, "six" ) )
return 6;
if( MATCH( pString, "seven" ) )
return 7;
if( MATCH( pString, "eight" ) )
return 8;
if( MATCH( pString, "nine" ) )
return 9;
if( MATCH( pString, "ten" ) )
return 10;

// Try converting to string

return atoi( pString );
}

/**************************************************************
***************************************************************

Direct3D Initialization Code

***************************************************************
**************************************************************/


// Initializes the Direct3D device

int InitDirect3DDevice( HWND hWndTarget, int Width, int Height, BOOL bWindowed,
D3DFORMAT FullScreenFormat, LPDIRECT3D8 pD3D,
LPDIRECT3DDEVICE8* ppDevice )
{
// Structure to hold information about the rendering method

D3DPRESENT_PARAMETERS d3dpp;
// Structure to hold information about the current display mode

D3DDISPLAYMODE d3ddm;

HRESULT r = 0;

if( *ppDevice )
(*ppDevice)->Release();

// Initialize the structure to 0

ZeroMemory( &d3dpp, sizeof( D3DPRESENT_PARAMETERS ) );

// Get the settings for the current display mode

r = pD3D->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &d3ddm );
if( FAILED( r ) )
{
SetError( "Could not get display adapter information" );
return E_FAIL;
}

// The width of the back buffer in pixels

d3dpp.BackBufferWidth = Width;
// The height of the buffer in pixels

d3dpp.BackBufferHeight = Height;
// The format of the back buffer

d3dpp.BackBufferFormat = bWindowed ? d3ddm.Format : FullScreenFormat;

// The number of back buffers

d3dpp.BackBufferCount = 1;

// The type of multisampling

d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
// The swap effect

d3dpp.SwapEffect = D3DSWAPEFFECT_COPY;

// The handle to the window that we want to render to

d3dpp.hDeviceWindow = hWndTarget;
// Windowed or fullscreen

d3dpp.Windowed = bWindowed;

// Let Direct3D manage the depth buffer

d3dpp.EnableAutoDepthStencil = TRUE;
// Set the depth buffer format to 16 bits

d3dpp.AutoDepthStencilFormat = D3DFMT_D16;

// Use the default refresh rate available

d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;

// Present the information as fast as possible

d3dpp.FullScreen_PresentationInterval = bWindowed ? 0 : D3DPRESENT_INTERVAL_IMMEDIATE;
// Allow the back buffer to be accessed for 2D work

d3dpp.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;

// Acquire a pointer to IDirect3DDevice8

r = pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_SW, hWndTarget,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp, ppDevice );
if( FAILED( r ) )
{
SetError( "Could not create the render device" );
return E_FAIL;
}

// Save global copies of the device dimensions

g_DeviceHeight = Height;
g_DeviceWidth = Width;

// Save a copy of the pres params for use in device validation later

g_SavedPresParams = d3dpp;

return S_OK;
}

/**************************************************************
***************************************************************

2D Graphics Code

***************************************************************
**************************************************************/


// Set a pixel to specified color

void SetPixel32( int x, int y, DWORD Color, int Pitch, DWORD* pData )
{
// Make sure the pixel is within screen boundaries

if( x > g_DeviceWidth || x < 0 )
return;

if( y > g_DeviceHeight || y < 0 )
return;

// Set the pixel

pData[ ((Pitch/4) * y) + x ] = Color;
}

// Draw a rectangle

void Rectangle32( D3DRECT* pRect, DWORD Color, int Pitch, DWORD* pData )
{
// Use local variables to avoid dereferencing inside the loop

int y1 = pRect->y1;
int y2 = pRect->y2;
int x1 = pRect->x1;
int x2 = pRect->x2;

// Convert the pitch from bytes to DWORDS

int Pitch32 = Pitch / 4;

// Get the offset into the target

DWORD Offset = y1 * Pitch32 + x1;

// Loop for each row of the rectangle

for( int y = y1 ; y < y2 ; y++ )
{
// Loop for each column in the image

for( int x = x1 ; x < x2 ; x++ )
{
// Set the pixel to the correct color

pData[ Offset + x ] = Color;
}

// Increment the offset to the next row of the rectangle

Offset += Pitch32;
}
}

// This uses hardware accelaration to draw a rectangle. It only works for

// the back buffer

void Rectangle32Fast( D3DRECT* pRect, DWORD Color, LPDIRECT3DDEVICE8 pDevice )
{
pDevice->Clear( 1, pRect, D3DCLEAR_TARGET, Color, 0.0f, 0 );
}

// Loads a bitmap to a surface

int LoadBitmapToSurface( char* PathName, LPDIRECT3DSURFACE8* ppSurface, LPDIRECT3DDEVICE8 pDevice )
{
HRESULT r;
HBITMAP hBitmap;
BITMAP Bitmap;

// Load the bitmap first using the GDI to get info about it

hBitmap = (HBITMAP)LoadImage( NULL, PathName, IMAGE_BITMAP, 0, 0,
LR_LOADFROMFILE | LR_CREATEDIBSECTION );
if( hBitmap == NULL )
{
// The file probably does not exist

SetError( "Unable to load bitmap" );
return E_FAIL;
}

// Get information about the object

GetObject( hBitmap, sizeof( BITMAP ), &Bitmap );
// Unload the bitmap from memory

DeleteObject( hBitmap );

// Now create a surface using the information gained from

// the previous load

r = pDevice->CreateImageSurface( Bitmap.bmWidth,
Bitmap.bmHeight, D3DFMT_A8R8G8B8, ppSurface );
if( FAILED( r ) )
{
SetError( "Unable to create surface for bitmap load" );
return E_FAIL;
}

// Load the image again, this time using Direct3D to load

// it directly to the new surface

r = D3DXLoadSurfaceFromFile( *ppSurface, NULL, NULL, PathName,
NULL, D3DX_FILTER_NONE, 0, NULL );
if( FAILED( r ) )
{
SetError( "Unable to load file to surface" );
return E_FAIL;
}

return S_OK;
}

/*-----------------------------------------------------------------------
CopySurfaceToSurface()
Parameters:
1) Pointer to a RECT that defines the dimensions for the source rectangle. If
set to NULL then the entire source surface is used.
2) Pointer to the source surface. Must be valid
3) Pointer to a POINT that defines where the origin on the destination should
be for the source image. If NULL then copying will start at (0, 0)
on the destination.
4) Pointer to the destination surface. Must be valid
5) Flag indicating if transparency is wanted
6) The colorkey to use if transparency is enabled.

Notes:
Call this function to copy one surface to another with transparency if
required. Make sure that both surfaces are valid and NOT locked before
you pass them to this function, otherwise it will fail.
-----------------------------------------------------------------------*/


HRESULT CopySurfaceToSurface( RECT* pSourceRect, LPDIRECT3DSURFACE8 pSourceSurf, POINT* pDestPoint,
LPDIRECT3DSURFACE8 pDestSurf, BOOL bTransparent, D3DCOLOR ColorKey )
{
// Holds error return values

HRESULT r = 0;

// Holds information about the surfaces when they are locked

D3DLOCKED_RECT LockedSource;
D3DLOCKED_RECT LockedDest;

// Make sure the source surface is valid

if( !pSourceSurf )
return E_FAIL;

// Make sure the destination surface is valid

if( !pDestSurf )
return E_FAIL;

// The source rectangle

RECT SourceRect;
// The destination point

POINT DestPoint;

// Holds information about the source surface

D3DSURFACE_DESC d3dsdSource;
// Get information about the source surface

pSourceSurf->GetDesc( &d3dsdSource );

// Holds information about the destination surface

D3DSURFACE_DESC d3dsdDest;
// Get information about the destination surface

pDestSurf->GetDesc( &d3dsdDest );

// If a source rectangle was specified then copy it

// into the local RECT structure

if( pSourceRect )
SourceRect = *pSourceRect;
else
// Otherwise set the rectangle to encompas the entire source surface

SetRect( &SourceRect, 0, 0, d3dsdSource.Width, d3dsdSource.Height );

// If a destination point was specified then copy it

// to the local POINT structure

if( pDestPoint )
DestPoint = *pDestPoint;
else
{
// Otherwise set the point to (0,0)

DestPoint.x = DestPoint.y = 0;
}

// Lock the source surface.

r = pSourceSurf->LockRect( &LockedSource, 0, D3DLOCK_READONLY );
if( FAILED( r ) )
// Fatal Error

return E_FAIL;

// Lock the destination surface

r = pDestSurf->LockRect( &LockedDest, 0, 0 );
if( FAILED( r ) )
{
// Fatal error, so unlock the source

// surface before exiting

pSourceSurf->UnlockRect();
return E_FAIL;
}

// Modify the pitch to be DWORD compatible

LockedSource.Pitch /= 4;
LockedDest.Pitch /= 4;

// Get 32bit pointers to the surface data

DWORD* pSourceData = (DWORD*)LockedSource.pBits;
DWORD* pDestData = (DWORD*)LockedDest.pBits;

// Get the offset into the source surface

int SourceOffset = SourceRect.top * LockedSource.Pitch + SourceRect.left;
// Get the offset into the destination surface

int DestOffset = DestPoint.y * LockedDest.Pitch + DestPoint.x;

// Loop for each row of the source image

for( int y = 0 ; y < SourceRect.bottom ; y++ )
{
// Loop for each column of the source image

for( int x = 0 ; x < SourceRect.right ; x++ )
{
// If transparency was requested

if( bTransparent )
{
// Then check to see if the current source pixel

// matches the color key. If it does then do

// not copy it.

if( pSourceData[ SourceOffset ] != ColorKey )
{
// The current pixel does not match the color

// key so it is ok to copy it to the destination

pDestData[ DestOffset ] = pSourceData[ SourceOffset ];
}
}
else // Transparency was not requested

{
// Copy the source pixel to the destination

// without any comparison

pDestData[ DestOffset ] = pSourceData[ SourceOffset ];
}

// Increment to the next pixel in the destination

DestOffset++;
// Increment to the next pixel in the source

SourceOffset++;
}

// Move the source offset to the next row of the image

// by adding the pitch minus the width of the source image

SourceOffset += LockedSource.Pitch - SourceRect.right;
// Move the destination offset to the next row of the image

DestOffset += LockedDest.Pitch - SourceRect.right;
}

// Copying is complete so unlock the surfaces

pSourceSurf->UnlockRect();
pDestSurf->UnlockRect();

// Return success

return S_OK;
}

/**************************************************************
***************************************************************

DC to Surface Code

***************************************************************
**************************************************************/


// Creates a GDI DC that can be copied to a surface later

HDC CreateD3DCompatibleDC( int Width, int Height, HBITMAP* phDibSection )
{
// Create a new DC that is compatible with the current display mode

HDC hDC = CreateCompatibleDC(0);

// Temp pointer to the DIB data

void* pDibSection = 0;

// Structure to hold information about the bitmap

BITMAPINFO bi;
ZeroMemory( &bi, sizeof( BITMAPINFO ) );

// The size of this structure in bytes

bi.bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
// The width of the new bitmap

bi.bmiHeader.biWidth = Width;
// The height of the new bitmap( negative for a top down image )

bi.bmiHeader.biHeight = -Height;
// Obselete - just set to one

bi.bmiHeader.biPlanes = 1;
// The bit depth of the surface

bi.bmiHeader.biBitCount = 32;
// The compression format. BI_RGB indicates none

bi.bmiHeader.biCompression = BI_RGB;

// Create a new DIB

HBITMAP hDibSection = CreateDIBSection( hDC, &bi, DIB_RGB_COLORS, &pDibSection, NULL, NULL );

// Select the bitmap into the new DC

SelectObject( hDC, hDibSection );

// Update the pointer to the handle to the bitmap

*phDibSection = hDibSection;

// Return the handle to the device context

return hDC;
}

// Copies a GDI DC to Direct3D surface

HRESULT CopyDCToSurface( LPDIRECT3DSURFACE8 pDestSurf, POINT* pDestPoint,
HDC hDCSource, HBITMAP hDibSection, RECT* pSrcRect, COLORREF ColorKey )
{
HRESULT r = 0;

// The source rectangle

RECT SourceRect;
// The destination origin point

POINT DestPoint;

// Holds information about the bitmap

DIBSECTION DibSection;

// Holds information about the surface when locked

D3DLOCKED_RECT LockedRect;

// Get information about the bitmap in the DC

GetObject( hDibSection, sizeof( DIBSECTION ), &DibSection );

int SrcTotalWidth = DibSection.dsBm.bmWidth;
int SrcTotalHeight = DibSection.dsBm.bmHeight;

// If no source rectangle was specified then this indicates

// that the entire bitmap in the DC is to be copied

if( !pSrcRect )
SetRect( &SourceRect, 0, 0, SrcTotalWidth, SrcTotalWidth);
else
SourceRect = *(pSrcRect);

// If no destination point was specified then the origin

// is set to (0,0)

if( !pDestPoint )
DestPoint.x = DestPoint.y = 0;
else
DestPoint = *(pDestPoint);

// Return failure if a valid destination surface was not specified

if( !pDestSurf )
return E_FAIL;

// Return failure if a valid source DC was not specified

if( !hDCSource )
return E_FAIL;

// Lock the source surface

r = pDestSurf->LockRect( &LockedRect, 0, 0 );
if( FAILED( r ) )
{
SetError( "Unable to lock the surface for GDI transfer" );
return E_FAIL;
}

D3DSURFACE_DESC d3dsd;
pDestSurf->GetDesc( &d3dsd );

if( (UINT)(SourceRect.bottom + DestPoint.y) > (UINT)d3dsd.Height )
SourceRect.bottom = d3dsd.Height;

if( (UINT)(SourceRect.right + DestPoint.x) > (UINT)d3dsd.Width )
SourceRect.right = d3dsd.Width;

// Convert the source and destination data pointers

// to DWORD( 32 bit) values

DWORD* pSrcData = (DWORD*)(DibSection.dsBm.bmBits);
DWORD* pDestData = (DWORD*)(LockedRect.pBits);

// Convert the pitch to a 32 bit value

int Pitch32 = LockedRect.Pitch/4;

// Compute the dimensions for the copy

int SrcHeight = SourceRect.bottom - SourceRect.top;
int SrcWidth = SourceRect.right - SourceRect.left;

// Compute the index into memory

DWORD SrcOffset = SourceRect.top * SrcTotalWidth + SourceRect.left;
DWORD DestOffset = DestPoint.y * Pitch32 + DestPoint.x;

// If not using a color key then a faster copy can be done

if( ColorKey == -1 )
{
// Loop for each row in the image

for( int y = 0 ; y < SrcHeight ; y++ )
{
// Copy this line of the image

memcpy( (void*)&(pDestData[ DestOffset ]), (void*)&(pSrcData[ SrcOffset ]), SrcWidth*4);

// Increase the destation pointer by the pitch

DestOffset+=Pitch32;
// Increase the source pointer by the total width

SrcOffset +=SrcTotalWidth;
}
}
else // a color key was specified

{
// Loop for each row in the image

for( int y = 0 ; y < SrcHeight ; y++ )
{
// Loop for each column

for( int x = 0 ; x < SrcWidth ; x++ )
{

// If the source pixel is not the same as the color key

if( pSrcData[ SrcOffset ] != ColorKey )
// Then copy the pixel to the destination

pDestData[ DestOffset ] = pSrcData[ SrcOffset ];

// Move to the next pixel in the source

SrcOffset++;
// Move to the next pixel in the destination

DestOffset++;
}

DestOffset += Pitch32 - SrcWidth;
}
}

// Unlock the surface

pDestSurf->UnlockRect();

// Return success

return S_OK;
}

// Deletes a GDI DC that was created with CreateD3DCompatibleDC()

void DeleteD3DCompatibleDC( HDC hDC, HBITMAP hDibSection )
{
// Delete the bitmap

DeleteObject( hDibSection );
// Delete the DC

DeleteDC( hDC );
}

/**************************************************************
***************************************************************

Device Validation Code

***************************************************************
**************************************************************/


LPDIRECT3D8 g_pD3D = 0;
LPDIRECT3DDEVICE8 g_pDevice = 0;

// Call every frame to check if the device is valid. If it

// is not then the it is reaquired if possible

HRESULT ValidateDevice()
{
HRESULT r = 0;

// Test the current state of the device

r = g_pDevice->TestCooperativeLevel();
if( FAILED( r ) )
{
// If the device is lost then return failure

if( r == D3DERR_DEVICELOST )
return E_FAIL;

// If the device is ready to be reset then attempt to do so

if( r == D3DERR_DEVICENOTRESET )
{
// Release the back surface so it can be recreated

g_pBackSurface->Release();

// Reset the device

r = g_pDevice->Reset( &g_SavedPresParams );
if( FAILED( r ) )
{
// If the device was not reset then exit

SetError( "Could not reset device" );
PostQuitMessage( E_FAIL );
return E_FAIL;
}

// Reaquire a pointer to the new back buffer

r = g_pDevice->GetBackBuffer( 0, D3DBACKBUFFER_TYPE_MONO, &g_pBackSurface );
if( FAILED( r ) )
{
SetError( "Unable to reaquire the back buffer" );
PostQuitMessage( 0 );
return E_FAIL;
}
g_pDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB( 0, 0, 0 ), 0.0f, 0 );

RestoreGraphics();
}
}

return S_OK;
}

// Use this function to reinit any surfaces that were lost

// when the device was lost.

HRESULT RestoreGraphics()
{

return S_OK;
}

/**************************************************************
***************************************************************

Font Engine Code

***************************************************************
**************************************************************/



int g_AlphabetWidth = 0; // The width of the Alphabet bitmap

int g_AlphabetHeight = 0; // The height of the Alphabet bitmap

int g_AlphabetLetterWidth = 0; // The width of a letter

int g_AlphabetLetterHeight = 0; // The height of a letter

int g_AlphabetLettersPerRow = 0; // The number of letters per row


// The surface holding the alphabet bitmap

LPDIRECT3DSURFACE8 g_pAlphabetSurface = 0;

// Has the alphabet bitmap been loaded yet?

BOOL g_bAlphabetLoaded = FALSE;

// Used to load an alphabet bitmap into memory

HRESULT LoadAlphabet( char* strPathName, int LetterWidth, int LetterHeight )
{
// Make sure a valid path was specified

if( !strPathName )
return E_FAIL;

// Make sure the size of the letters is greater than 0

if( !LetterWidth || !LetterHeight )
return E_FAIL;

HRESULT r = 0;

// Load the bitmap into memory

r = LoadBitmapToSurface( strPathName, &g_pAlphabetSurface, g_pDevice );
if( FAILED( r ) )
{
SetError( "Unable to load alphabet bitmap" );
return E_FAIL;
}

// Holds information about the alpahbet surface

D3DSURFACE_DESC d3dsd;

// Get information about the alphabet surface

g_pAlphabetSurface->GetDesc( &d3dsd );

// Update globals with the letter dimensions

g_AlphabetWidth = d3dsd.Width;
g_AlphabetHeight = d3dsd.Height;
g_AlphabetLetterWidth = LetterWidth;
g_AlphabetLetterHeight = LetterHeight;

// Compute the number of letters in a row

g_AlphabetLettersPerRow = g_AlphabetWidth / g_AlphabetLetterWidth;

// Set the loaded flag to TRUE

g_bAlphabetLoaded = TRUE;

return S_OK;
}

// Unloads the alphabet from memory

HRESULT UnloadAlphabet()
{
// Check if the alphabet exists

if( g_pAlphabetSurface )
{
// Release the surface

g_pAlphabetSurface->Release();
// NULL the pointer

g_pAlphabetSurface = 0;
// Set the loaded flag to FALSE

g_bAlphabetLoaded = FALSE;
}

return S_OK;
}

// Print a character to a surface using the loaded alphabet

void PrintChar( int x, int y, char Character, BOOL bTransparent,
D3DCOLOR ColorKey, DWORD* pDestData, int DestPitch )
{
HRESULT r = 0;

div_t Result; // Holds the result of divisions


// The offset into the alphabet image

int OffsetX = 0, OffsetY = 0;

POINT LetterDestPoint = { 0, 0 }; // The destination point for the letter

RECT LetterRect = { 0, 0, 0, 0 }; // The source rectangle for the letter


// If the alphabet has not been loaded yet then exit

if( !g_bAlphabetLoaded )
return;

// The characters are specified in ASCII code, which begins at 32 so

// we want to decrement this value by 32 to make it zero based

Character -= 32;

// Divide the character code by the number of letters per row.

// The quotient will help get the vertical offset and the

// remainder will help get the horizontal offset

Result = div( Character, g_AlphabetLettersPerRow );

// Get the horizontal offset by multiplying the remainder

// by the width of the Letter

OffsetX = Result.rem * g_AlphabetLetterWidth;
// Get the vertical offset by multiplying the quotient

// by the height of the letter

OffsetY = Result.quot * g_AlphabetLetterHeight;

// Fill in the source rectangle with the computed offsets

SetRect( &LetterRect, OffsetX, OffsetY,
OffsetX + g_AlphabetLetterWidth, OffsetY + g_AlphabetLetterHeight );

// Fill in the destination point

LetterDestPoint.x = x;
LetterDestPoint.y = y;

D3DLOCKED_RECT LockedAlphabet; // Holds info about the alphabet surface


// Lock the source surface

r = g_pAlphabetSurface->LockRect( &LockedAlphabet, 0, D3DLOCK_READONLY );
if( FAILED( r ) )
{
SetError( "Couldnt lock alphabet surface for PrintChar()" );
return;
}

// Get a DWORD pointer to each surface

DWORD* pAlphaData = (DWORD*)LockedAlphabet.pBits;

// Convert the BYTE pitch pointer to a DWORD ptr

LockedAlphabet.Pitch /=4;
DestPitch /= 4;

// Compute the offset into the alphabet

int AlphaOffset = OffsetY * LockedAlphabet.Pitch + OffsetX;
// Compute the offset into the destination surface

int DestOffset = y * DestPitch + x;

// Loop for each row in the letter

for( int cy = 0 ; cy < g_AlphabetLetterHeight ; cy++ )
{
// Loop for each column in the letter

for( int cx = 0 ; cx < g_AlphabetLetterWidth ; cx++ )
{
if( bTransparent )
{
// If this alphabet pixel is not transparent

if( pAlphaData[ AlphaOffset ] != ColorKey )
{
// Then copy the pixel to the destination

pDestData[ DestOffset ] = pAlphaData[ AlphaOffset ];
}

// Increment the offsets to the next pixel

}
else
{
pDestData[ DestOffset ] = pAlphaData[ AlphaOffset ];
}

AlphaOffset++;
DestOffset++;
}

// Move the offsets to the start of the next row

DestOffset += DestPitch - g_AlphabetLetterWidth;
AlphaOffset += LockedAlphabet.Pitch - g_AlphabetLetterWidth;
}

// Unlock the surface

g_pAlphabetSurface->UnlockRect();

}

void PrintString( int x, int y, char* String, BOOL bTransparent,
D3DCOLOR ColorKey, DWORD* pDestData, int DestPitch )
{
// Loop for each character in the string

for( UINT i = 0 ; i < strlen( String ) ; i++ )
{
// Print the current character

int cx = x + (g_AlphabetLetterWidth * i);

if( cx + g_AlphabetLetterWidth > g_DeviceWidth )
continue;

PrintChar( cx, y, String[i],
bTransparent, ColorKey, pDestData, DestPitch );
}
}

/**************************************************************
***************************************************************

Timing Code

***************************************************************
**************************************************************/


// The number of high performance ticks per second

INT64 g_Frequency = 0;
// The number of elapsed frames this counting period

int g_FrameCount = 0;
// The number of elapsed frames this second

int g_FrameRate = 0;

HRESULT InitTiming()
{
// Get the number of counts per second

QueryPerformanceFrequency( (LARGE_INTEGER*)&g_Frequency );

// If the frequency is 0 then this system does not have

// high performance timers

if( g_Frequency == 0 )
{
SetError( "The system does not support high resolution timing" );
return E_FAIL;
}

return S_OK;
}

void Pause( int Milliseconds )
{
INT64 SecondsDelay = (INT64)Milliseconds * 1000;

INT64 StartTime;
INT64 CurrentTime;

QueryPerformanceCounter( (LARGE_INTEGER*)&StartTime );

while(1)
{
QueryPerformanceCounter( (LARGE_INTEGER*)&CurrentTime );

if( (CurrentTime - StartTime) > (INT64)SecondsDelay )
break;
}
}

float GetNumTicksPerMs()
{
return ((float)g_Frequency / 1000.0f);
}

void FrameCount()
{
INT64 NewCount = 0; // The current count

static INT64 LastCount = 0; // The last count

INT64 Difference = 0; // The differnce since the last count


// Get the current count

QueryPerformanceCounter( (LARGE_INTEGER*)&NewCount );

// If the count is 0 then this system does not have

// high performance timers

if( NewCount == 0 )
SetError( "The system does not support high resolution timing" );

// Increase the frame count

g_FrameCount++;

// Compute the difference since the last count

Difference = NewCount - LastCount;

// If more than a second has passed

if( Difference >= g_Frequency )
{
// Record the number of elapsed frames

g_FrameRate = g_FrameCount;
// Reset the counter

g_FrameCount = 0;

// Update the last count

LastCount = NewCount;
}

}

// Prints the frame rate to the screen

void PrintFrameRate( int x, int y, BOOL bTransparent, D3DCOLOR ColorKey, DWORD* pDestData, int DestPitch )
{
char string[4]; // String to hold the frame rate


// Zero out the string

ZeroMemory( &string, sizeof( string ) );

// Convert the frame rate to a string

itoa( g_FrameRate, string, 10 );

// Output the string to the back surface

PrintString( x, y, string, bTransparent, ColorKey, pDestData, DestPitch );
}

/**************************************************************
***************************************************************

Console Code

***************************************************************
**************************************************************/


// ------------------------- CEntry Class

// Used to represent a row of text


class CEntry
{
public:
CEntry(); // The constructor

~CEntry(); // The destructor


// Variables:

protected:
char* m_pstrText; // The text buffer for this entry

CEntry* m_pNext; // Pointer to next entry( row )


int m_VerticalPos; // The y position to render


// Functions:

public:
// Returns the next entry(row)

CEntry* GetNext(){ return m_pNext; }
// Sets the next entry(row)

void SetNext( CEntry* pNext ){ m_pNext = pNext; }
// Draws the text using the GDI to the console surface

int RenderText( int NumHorzChars, DWORD* pData, int DestPitch );
// Adds a character to the text buffer

int OnChar( char Key );
// Returns the text in the buffer

int GetText( char* pstrText, int Length );
// Clears and then sets the text in the buffer

int SetText( char* pstrText );
// Returns the number of characters in the buffer

int GetTextLength(){ return strlen( m_pstrText ); }
// Sets the vertical position of this entry

void SetVerticalPos( int Pos ){ m_VerticalPos = Pos; }
// Returns the vertical position for this entry

int GetVerticalPos(){ return m_VerticalPos; }
};

// Constructor

CEntry::CEntry()
{
// Allocate memory for the buffer

m_pstrText = new char[MAX_CHARSPERLINE];
if( m_pstrText )
ZeroMemory( m_pstrText, sizeof( char[MAX_CHARSPERLINE] ) );
else
m_pstrText = 0;

// Zero out member variables

m_pNext = 0;
m_VerticalPos = 0;
}
// Destructor

CEntry::~CEntry()
{
// Delete the text buffer if it exists

if( m_pstrText )
{
delete m_pstrText;
m_pstrText = 0;
}
}
// This function copies the text in the buffer

// to the supplied string variable

int CEntry::GetText( char* pstrText, int Length )
{
// Make sure the length doesnt overrun our buffer

if( Length > MAX_CHARSPERLINE )
Length = MAX_CHARSPERLINE;

// Copy the string

CopyMemory( pstrText, m_pstrText, Length );

return S_OK;
}
// This function sets the text in the buffer

int CEntry::SetText( char* pstrText )
{
// Clear out any text that is already there

ZeroMemory( m_pstrText, sizeof( char[MAX_CHARSPERLINE] ) );

// Make sure the supplied text doesnt overrun our buffer

int Length = strlen( pstrText );
if( Length > MAX_CHARSPERLINE )
Length = MAX_CHARSPERLINE;

// Copy the supplied text into our buffer

CopyMemory( m_pstrText, pstrText, strlen( pstrText ) );

return S_OK;
}

// This function draws the text to the console surface

// using the GDI

int CEntry::RenderText( int NumHorzChars, DWORD* pData, int DestPitch )
{
// Only draw the number of characters that fit on the screen

int Length = strlen( m_pstrText );
if( Length > NumHorzChars )
Length = NumHorzChars;

PrintString( 10, m_VerticalPos, m_pstrText, TRUE,
D3DCOLOR_ARGB( 255, 255, 0, 255 ), pData, DestPitch );

return S_OK;
}
// This function is called whenever a character

// key is pressed that needs to be added to the buffer

int CEntry::OnChar( char Key )
{
// Check if the backspace key was pressed

if( Key == '\b' )
{
// Make a temporary string holder

char pstrTemp[MAX_CHARSPERLINE];
// Get the length of the buffer

int Length = strlen( m_pstrText );

// If the buffer is empty then return

if( Length == 0 )
return S_OK;

// Reduce the length of the string by one

Length--;

// Copy the string(-1) to the temp string

CopyMemory( pstrTemp, m_pstrText, Length );
// Zero out the buffer

ZeroMemory( m_pstrText, sizeof( char[MAX_CHARSPERLINE] ) );
// Copy the text back into the buffer

CopyMemory( m_pstrText, pstrTemp, Length );
}
else // A normal key was pressed

{
// Make sure the buffer has not overflowed

if( strlen( m_pstrText ) > MAX_CHARSPERLINE )
return E_FAIL;

// Append the text buffer with the character

strncat( m_pstrText, &Key, 1 );
}

return S_OK;
}

const int MAX_PARAMS = 25;

// ------------------------- Command Class

// Holds pre parsed commands


class CCommand
{
public:

// Holds the main command. eg 'SetScreenRes'

char* pstrCommand;
// Holds the number of parameters. eg 2

int NumParams;
// Holds the parameters. eg 640 and 480

char* pstrParams[MAX_PARAMS];

// Constructor

CCommand()
{
// Initialize all the variables to 0

pstrCommand = 0;
NumParams = 0;

ZeroMemory( &pstrParams, sizeof( pstrParams ) );
}
// Destructor

~CCommand()
{
// Destroy the command string

// if it exists

if( pstrCommand )
delete pstrCommand;

// Destroy any parameter strings

// if they exist

for( int i = 0 ; i < MAX_PARAMS ; i++ )
{
if( pstrParams[i] )
delete pstrParams[i];
}
}

};

typedef int (*CONSOLE_PARSER_CALLBACK)( CCommand* pCommand );


// ------------------------- Console Class

// Deals with keyboard input, visibility managment, and command parsing

class CConsole
{
public:
CConsole();
~CConsole();

// Functions:

public:
void Shutdown();
HRESULT Initialize( LPDIRECT3DDEVICE8 pDevice, LPDIRECT3DSURFACE8 pTargetSurface );
void Render();

BOOL GetVisibility(){ return m_bVisible; }
void SetVisibility( BOOL bVisible )
{
// The render code will figure out when the console

// is not visible.

m_bVisible = TRUE;

// If bVisible is true then the console must be invisible

// and about to animate down. Otherwise it will be

// animating up.

m_Animation = bVisible ? Down : Up;
}

void OutputString( char* pString );
void Clear();
int OnChar( char Key );
int OnKeyDown( WPARAM wParam );

void SetParserCallback( CONSOLE_PARSER_CALLBACK pfnCallback );
void PreParse( char* pstrText, CCommand* pCommand );

protected:
void RotateEntries();


// Variables:

protected:
BOOL m_bInitialized; // Has the console been initialized?


int m_Width; // The width of the console surface

int m_Height; // The height of the console surface


LPDIRECT3DSURFACE8 m_pConsoleSurface; // Pointer to the console surface

LPDIRECT3DSURFACE8 m_pConsoleBackgroundSurf; // Pointer to the background bitmap surface

LPDIRECT3DSURFACE8 m_pTargetSurface; // Pointer to the target render surface( eg back buffer )

LPDIRECT3DDEVICE8 m_pDevice; // Pointer to the device


BOOL m_bVisible; // Is the console visible?


// The current state of the console

enum ANIM{ Up, Down, None }m_Animation;

CEntry* m_pActiveEntry; // The active entry(accepts key input)

CEntry* m_pEntryList; // The list of old entries


// Pointer to an external console parser

CONSOLE_PARSER_CALLBACK m_pfnCallback;
// Is there an external parser?

BOOL m_bParserCallback;

};

// Constructor

CConsole::CConsole()
{
m_pConsoleSurface = 0;
m_pConsoleBackgroundSurf = 0;
m_pTargetSurface = 0;

m_Width = 0;
m_Height = 0;

m_bInitialized = FALSE;
m_bVisible = FALSE;

m_Animation = None;

m_pActiveEntry = 0;
m_pEntryList = 0;

m_pfnCallback = 0;
m_bParserCallback = FALSE;
}

// Destructor

CConsole::~CConsole()
{
// Release the console surface

if( m_pConsoleSurface )
{
m_pConsoleSurface->Release();
m_pConsoleSurface = 0;
}

// Release the background bitmap surface

if( m_pConsoleBackgroundSurf )
{
m_pConsoleBackgroundSurf->Release();
m_pConsoleBackgroundSurf = 0;
}

// Release the target surface

if( m_pTargetSurface )
{
m_pTargetSurface->Release();
m_pTargetSurface = 0;
}

// Destroy all of the entries

CEntry* pEntry = m_pEntryList;
CEntry* pTemp = 0;

if( !pEntry )
return;

// Loop for each entry

while( pEntry->GetNext() )
{
// Copy the next entry into a temp pointer

pTemp = pEntry->GetNext();
// Delete the current pointer

delete pEntry;
// Set the current pointer to the next pointer

pEntry = pTemp;
}
}

// Shutsdown the console

void CConsole::Shutdown()
{
if( m_pConsoleSurface )
{
m_pConsoleSurface->Release();
m_pConsoleSurface = 0;
}

if( m_pConsoleBackgroundSurf )
{
m_pConsoleBackgroundSurf->Release();
m_pConsoleBackgroundSurf = 0;
}

if( m_pTargetSurface )
{
m_pTargetSurface->Release();
m_pTargetSurface = 0;
}

// Destroy all of the entries

CEntry* pEntry = m_pEntryList;
CEntry* pTemp = 0;

if( !pEntry )
return;

// Loop for each entry

while( pEntry->GetNext() )
{
// Copy the next entry into a temp pointer

pTemp = pEntry->GetNext();
// Delete the current pointer

delete pEntry;
// Set the current pointer to the next pointer

pEntry = pTemp;
}

m_pEntryList = 0;

m_bInitialized = FALSE;
}

// Sets the external command parser

void CConsole::SetParserCallback( CONSOLE_PARSER_CALLBACK pfnCallback )
{
// Set the function pointer

m_pfnCallback = pfnCallback;
// Set the flag to show that a parser has been specified

m_bParserCallback = TRUE;
}

// Clears the contents of all the entries

void CConsole::Clear()
{
// Create a pointer to the first entry

CEntry* pEntry = m_pEntryList;

// Loop for every entry

while( pEntry->GetNext() )
{
// Set the entries text to nothing

pEntry->SetText( "" );
// Get the next entry

pEntry = pEntry->GetNext();
}
}

// Handles character input

int CConsole::OnChar( char Key )
{
// This holds the last key pressed

static char LastKey = 0;

// If the console is not visible

// then ignore the keypress

if( !m_bVisible )
return 0;

// Ignore the enter key

if( Key == '\r' )
return 0;

// Change the tab key to a space key

if( Key == '\t' )
Key = ' ';

// Only allow one space

if( (Key == ' ') && (LastKey == ' ') )
return 0;

// Make sure the first character in a line

// is not a space

if( (Key == ' ') && (LastKey == 0 ) )
return 0;

// Only send the message to the active

// entry if the Last Key is not being

// reset

if( Key != 0 )
m_pActiveEntry->OnChar( Key );

// Update the last key pressed variable

LastKey = Key;

return 0;
}

// Handles non character keyboard input

int CConsole::OnKeyDown( WPARAM wParam )
{
int Result = 0; // Holds result of parse operation


// Figure out which key was pressed

switch( wParam )
{
// The F11 key was pressed

case VK_F11:
{
SetVisibility( !GetVisibility() );

break;
}
// The enter key.

case VK_RETURN:
{
// Ignore if the console is not visible

if( !m_bVisible )
return 0;

// Reset the last keypressed

OnChar( 0 );

// Check if a parser has been set

if( m_bParserCallback )
{
// Create a temporary string

char* String = new char[MAX_CHARSPERLINE];
// Get the string from the active entry

m_pActiveEntry->GetText( String, MAX_CHARSPERLINE );

// If nothing was typed just ignore it

if( !MATCH( String, "
" ) && !MATCH( String, " " ) )
{
// Create a new command class

CCommand Command;
// Convert the string into a command

PreParse( String, &Command );
// Send the command to the parser

Result = m_pfnCallback( &Command );
if( FAILED( Result ) )
OutputString( "
-- Unknown Command --" );
}

// Destroy the temporary string

delete String;
}

// Move all the entries up

RotateEntries();
break;
}

// The left arrow key was pressed

case VK_LEFT:
{
// Treat this like a backspace press

OnChar( '\b' );
break;
}

}

return 0;
}

// Converts the command string into a

// command and a list of parameters

void CConsole::PreParse( char* pstrText, CCommand* pCommand )
{
// The parameter separators are

// the comma and space characters

char Separators[] = "
,";
// String to hold the current parameter

char* Token;
// The number of parameters

int TokenCount = 0;

// Convert the string to lowercase

strlwr( pstrText );

// Get the command string

Token = strtok( pstrText, Separators );

// If the line was not blank...

if( Token )
{
// ...Set the command string to the token.

// Create a string in the command to hold the command string

pCommand->pstrCommand = new char[ strlen( Token ) + 1 ];
// Copy the string into the command string

strcpy( pCommand->pstrCommand, Token );
}
else // The line was blank

{
// Create a single character to hold a blank character.

// This will notify the keypress event that the line

// was empty

pCommand->pstrCommand = new char;
// Copy a blank character into a new

strcpy( pCommand->pstrCommand, "
" );
// Set the number of parameters to zero

pCommand->NumParams = 0;
// Return; there is nothing left to do

return;
}

// Get the next token in the string

Token = strtok( NULL, Separators );

// Loop for the rest of the tokens

while( Token != NULL )
{
// Allocate memory in the command for this parameter

pCommand->pstrParams[TokenCount] = new char[ strlen( Token ) + 1 ];
// Copy the parameter into the allocated memory

strcpy( pCommand->pstrParams[TokenCount], Token );
// Get the next token in the string

Token = strtok( NULL, Separators );
// Increase the parameter count

TokenCount++;
// Make sure there are not too many parameters

if( TokenCount > MAX_PARAMS )
break;
}

// Set the number of parameters in command

pCommand->NumParams = TokenCount;
}


// Output a string to the console

void CConsole::OutputString( char* pString )
{
// Move the entries up

RotateEntries();

// Set the new active entry to the specified string

m_pActiveEntry->SetText( pString );
}

// Moves the entries up one row. The top

// entry is deleted and a new one is

// created for the bottom

void CConsole::RotateEntries()
{
// Get a pointer to the first entry

CEntry* pEntry = m_pEntryList;
// A temporary entry pointer

CEntry* pTempEntry = 0;
// A pointer to the new entry

CEntry* pNewEntry = 0;

// Loop for each entry

while( pEntry->GetNext() )
{
// Set the temp entry to the current entry

pTempEntry = pEntry;
// Increase the vertical position of the current entry

pEntry->SetVerticalPos( pEntry->GetVerticalPos() - g_AlphabetLetterHeight );
// Set the current entry to the next entry

pEntry = pEntry->GetNext();
}

// The pEntry variable now points to the last

// entry in the list and pTempEntry to the 2nd last.


// Delete the last entry in the list

delete pEntry;
// Get a pointer to the new last entry

pEntry = pTempEntry;
// Set the new last entries pNext pointer to zero

pEntry->SetNext( NULL );

// Create a new entry for the top of the list

pNewEntry = new CEntry;

// Set new entries pNext variable to last first entry

pNewEntry->SetNext( m_pEntryList );
// Set the start of the Entry list to the new entry

m_pEntryList = pNewEntry;

// Set the active entry to the new entry

m_pActiveEntry = pNewEntry;
// Set the vertical position of the new entry to the bottom

// of the console

m_pActiveEntry->SetVerticalPos( (m_Height-5) - g_AlphabetLetterHeight );

}

// Initializes the console

HRESULT CConsole::Initialize( LPDIRECT3DDEVICE8 pDevice, LPDIRECT3DSURFACE8 pTargetSurface )
{
// Make sure a valid device was specified

if( !pDevice )
return E_FAIL;

// Make sure a valid target surface was specified

if( !pTargetSurface )
return E_FAIL;

HRESULT r = 0;

// Keep a local pointer of the device

m_pDevice = pDevice;

// Keep a local copy of the target suface

m_pTargetSurface = pTargetSurface;
m_pTargetSurface->AddRef();

// Holds information about the target surface

D3DSURFACE_DESC d3dsd;
// Get information about the target surface

m_pTargetSurface->GetDesc( &d3dsd );

// Set the dimensions of the console the width and 1/2 the height of the target

m_Width = d3dsd.Width;
m_Height = d3dsd.Height / 2;

// Create a surface for the console

r = m_pDevice->CreateImageSurface( m_Width, m_Height, D3DFMT_A8R8G8B8, &m_pConsoleSurface );
if( FAILED( r ) )
{
SetError( "
Unable to create image surface for console" );
Shutdown();
return E_FAIL;
}

// Load the background bitmap for the console

r = LoadBitmapToSurface( "
Console Background.bmp", &m_pConsoleBackgroundSurf, m_pDevice );
if( FAILED( r ) )
{
SetError( "
Unable to load console background image" );
Shutdown();
return E_FAIL;
}

m_pEntryList = new CEntry; // Start the list with a new entry

CEntry* pEntry = m_pEntryList; // Get a temp pointer to the new entry

m_pActiveEntry = m_pEntryList; // Set the active entry to the start of the list


// Compute the number of visible rows of text

int VisibleRows = m_Height / g_AlphabetLetterHeight;

// Loop for each possible visible row of text

for( int i = 1 ; i < VisibleRows ; i++ )
{
// Create a new entry

pEntry->SetNext( new CEntry );
// Set its vertical position to above the previous row

pEntry->SetVerticalPos( (m_Height-5) - (i * g_AlphabetLetterHeight) );
// Get a pointer to the new entry

pEntry = pEntry->GetNext();
}

// Set the initialized flag to TRUE

m_bInitialized = TRUE;

return S_OK;
}

// Renders the console to the target surface

void CConsole::Render()
{
// Make sure the console has been initialized

if( !m_bInitialized )
return;

// Holds the current vertical position of the

// console during scrolling operations

static int CurrentY = m_Height;

// If the console is animating down then

// subtract from the current Y coord

if( m_Animation == Down )
CurrentY-=10;
// Else if the console is going up

// then add to the current Y coord

else if( m_Animation == Up )
CurrentY+=10;

// Stop the animation if the console has completely expanded

if( m_Animation == Down && CurrentY == 0 )
m_Animation = None;

// Stop the animation if the console has completely retracted

if( m_Animation == Up && CurrentY == m_Height )
{
m_bVisible = FALSE;
m_Animation = None;
}

// Set the source rectangle

RECT SourceRect = { 0, CurrentY, m_Width, m_Height };
// Set the destination point

POINT DestPoint = { 0, 0 };

// If the console is not visible then return

if( !m_bVisible )
return;

// Copy the background surface to the console surface

D3DXLoadSurfaceFromSurface( m_pConsoleSurface, NULL, NULL, m_pConsoleBackgroundSurf, NULL,
NULL, D3DX_FILTER_POINT, 0 );

// Get a pointer to the start of the entry list

CEntry* pEntry = m_pEntryList;

D3DLOCKED_RECT LockedRect;

m_pConsoleSurface->LockRect( &LockedRect, 0, 0 );

// Loop for each entry in the list

while( pEntry->GetNext() )
{
// Render this entry

pEntry->RenderText( MAX_CHARSPERLINE, (DWORD*)LockedRect.pBits, LockedRect.Pitch );
// Move to the next entry

pEntry = pEntry->GetNext();
}

m_pConsoleSurface->UnlockRect();

// Copy the console to the target surface

m_pDevice->CopyRects( m_pConsoleSurface, &SourceRect, 1, m_pTargetSurface, &DestPoint );

}


class CSprite
{
public:
CSprite();
~CSprite();

// Functions:

public:
HRESULT Initialize( char* strPathName, int SpriteWidth, int SpriteHeight, int NumSprites );
HRESULT Initialize( LPDIRECT3DSURFACE8 pSourceSurface, int SpriteWidth, int SpriteHeight, int NumSprites );
void Shutdown();

HRESULT SelectActiveSprite( int SpriteNum );
HRESULT Render( LPDIRECT3DSURFACE8 pDestSurface );

void SetColorKey( D3DCOLOR ColorKey );
D3DCOLOR GetColorKey(){ return m_ColorKey; }

void SetPosition( int x, int y ){ m_x = x; m_y = y; }
void GetPosition( int* px, int* py){ *px = m_x, *py = m_y; }

void GetBounds( RECT* pRect );
BOOL CheckForCollisionWith( CSprite* pOtherSprite );

void SetVelocity( int vx, int vy )
{
m_VelocityX = vx;
m_VelocityY = vy;
}
void GetVelocity( int* pvx, int* pvy )
{
*pvx = m_VelocityX;
*pvy = m_VelocityY;
}

void SetNext( CSprite* pNext ){ m_pNext = pNext; }
CSprite* GetNext(){ return m_pNext; }

void Update();

protected:


// Variables

public:
int m_SurfaceWidth;
int m_SurfaceHeight;
int m_SpriteWidth;
int m_SpriteHeight;
int m_NumSprites;

BOOL m_bTransparent;

int m_State;

protected:
LPDIRECT3DSURFACE8 m_pSpriteSurface;
LPDIRECT3DSURFACE8 m_pActiveSurface;

BOOL m_bInitialized;

D3DCOLOR m_ColorKey;

int m_x, m_y;
int m_VelocityX;
int m_VelocityY;

CSprite* m_pNext;
};

CSprite::CSprite()
{
m_SurfaceWidth = 0;
m_SurfaceHeight = 0;
m_SpriteWidth = 0;
m_SpriteHeight = 0;
m_NumSprites = 0;

m_pSpriteSurface = 0;
m_pActiveSurface = 0;

m_bInitialized = FALSE;

m_ColorKey = D3DCOLOR_ARGB( 0, 255, 0, 255 );

m_bTransparent = TRUE;

m_x = m_y = 0;
m_VelocityX = 0;
m_VelocityY = 0;

m_State = 0;

m_pNext = 0;
}

CSprite::~CSprite()
{
if( m_pSpriteSurface )
{
m_pSpriteSurface->Release();
m_pSpriteSurface = 0;
}

if( m_pActiveSurface )
{
m_pActiveSurface->Release();
m_pActiveSurface = 0;
}


}

void CSprite::Shutdown()
{
if( m_pSpriteSurface )
{
m_pSpriteSurface->Release();
m_pSpriteSurface = 0;
}

if( m_pActiveSurface )
{
m_pActiveSurface->Release();
m_pActiveSurface = 0;
}


m_SurfaceWidth = 0;
m_SurfaceHeight = 0;
m_SpriteWidth = 0;
m_SpriteHeight = 0;
m_NumSprites = 0;

m_pSpriteSurface = 0;

m_bInitialized = FALSE;
}

void CSprite::Update()
{
m_x += m_VelocityX;
m_y += m_VelocityY;
}


BOOL CSprite::CheckForCollisionWith( CSprite* pOtherSprite )
{
if( !pOtherSprite )
return 0;

RECT ThisRect, OtherRect, TempRect;

GetBounds( &ThisRect );
pOtherSprite->GetBounds( &OtherRect );

if( IntersectRect( &TempRect, &ThisRect, &OtherRect ) )
return TRUE;
else
return FALSE;

}

void CSprite::GetBounds( RECT* pRect )
{
SetRect( pRect, m_x, m_y, m_SpriteWidth + m_x, m_SpriteHeight + m_y );
}

HRESULT CSprite::Initialize( LPDIRECT3DSURFACE8 pSourceSurface,
int SpriteWidth, int SpriteHeight, int NumSprites )
{
if( m_pSpriteSurface )
{
m_pSpriteSurface->Release();
m_pSpriteSurface = 0;
}

if( m_pActiveSurface )
{
m_pActiveSurface->Release();
m_pActiveSurface = 0;
}

HRESULT r = 0;

NumSprites--;

if( !pSourceSurface )
{
SetError( "
Invalid source sprite surface" );
return E_FAIL;
}

m_pSpriteSurface = pSourceSurface;
pSourceSurface->AddRef();

m_SpriteWidth = SpriteWidth;
m_SpriteHeight = SpriteHeight;
m_NumSprites = NumSprites;

D3DSURFACE_DESC d3dsd;
m_pSpriteSurface->GetDesc( &d3dsd );

m_SurfaceWidth = d3dsd.Width;
m_SurfaceHeight = d3dsd.Height;

r = g_pDevice->CreateImageSurface( m_SpriteWidth, m_SpriteHeight, D3DFMT_A8R8G8B8, &m_pActiveSurface );
if( FAILED( r ) )
{
Shutdown();
return E_FAIL;
}

RECT SpriteRect = { 0, 0, SpriteWidth, SpriteHeight };
POINT SpritePoint = { 0, 0 };

g_pDevice->CopyRects( m_pSpriteSurface, &SpriteRect, 1, m_pActiveSurface, &SpritePoint );

m_bInitialized = TRUE;

return S_OK;
}

HRESULT CSprite::Initialize( char* strPathName, int SpriteWidth, int SpriteHeight, int NumSprites )
{
if( m_pSpriteSurface )
{
m_pSpriteSurface->Release();
m_pSpriteSurface = 0;
}

if( m_pActiveSurface )
{
m_pActiveSurface->Release();
m_pActiveSurface = 0;
}

HRESULT r = 0;

NumSprites--;

r = LoadBitmapToSurface( strPathName, &m_pSpriteSurface, g_pDevice );
if( FAILED( r ) )
{
return E_FAIL;
}

m_SpriteWidth = SpriteWidth;
m_SpriteHeight = SpriteHeight;
m_NumSprites = NumSprites;

D3DSURFACE_DESC d3dsd;
m_pSpriteSurface->GetDesc( &d3dsd );

m_SurfaceWidth = d3dsd.Width;
m_SurfaceHeight = d3dsd.Height;

r = g_pDevice->CreateImageSurface( m_SpriteWidth, m_SpriteHeight, D3DFMT_A8R8G8B8, &m_pActiveSurface );
if( FAILED( r ) )
{
Shutdown();
return E_FAIL;
}

RECT SpriteRect = { 0, 0, SpriteWidth, SpriteHeight };
POINT SpritePoint = { 0, 0 };

g_pDevice->CopyRects( m_pSpriteSurface, &SpriteRect, 1, m_pActiveSurface, &SpritePoint );

m_bInitialized = TRUE;

return S_OK;
}

HRESULT CSprite::SelectActiveSprite( int SpriteNum )
{
HRESULT r = 0;

div_t Result;

int OffsetX = 0;
int OffsetY = 0;
int SpritesPerRow = m_SurfaceWidth / m_SpriteWidth;

if( SpriteNum > m_NumSprites )
SpriteNum = 0;

Result = div( SpriteNum, SpritesPerRow );

OffsetX = Result.rem * m_SpriteWidth;
OffsetY = Result.quot* m_SpriteHeight;

if( OffsetX > m_SurfaceWidth )
return E_FAIL;

if( OffsetY > m_SurfaceHeight )
return E_FAIL;

RECT SpriteRect = { OffsetX, OffsetY, OffsetX + m_SpriteWidth, OffsetY + m_SpriteHeight };
POINT DestPoint = { 0, 0 };

r = g_pDevice->CopyRects( m_pSpriteSurface, &SpriteRect, 1, m_pActiveSurface, &DestPoint );

return r;
}

HRESULT CSprite::Render( LPDIRECT3DSURFACE8 pDestSurface )
{
if( !pDestSurface )
return E_FAIL;

HRESULT r = 0;

RECT SourceRect = { 0, 0, m_SpriteWidth, m_SpriteHeight };
POINT DestPoint = { m_x, m_y };

if( m_bTransparent )
CopySurfaceToSurface( &SourceRect, m_pActiveSurface, &DestPoint, pDestSurface, TRUE, m_ColorKey );
else
g_pDevice->CopyRects( m_pActiveSurface, &SourceRect, 1, pDestSurface, &DestPoint );

return r;
}


class CLayer
{
public:
CLayer();
~CLayer();

// Functions

public:
void SetColorKey( D3DCOLOR ColorKey );
D3DCOLOR GetColorKey(){ return m_ColorKey; }

void SetVelocity( int vx, int vy ){ m_VelocityX = vx; m_VelocityY = vy; }
void GetVelocity( int* pvx, int* pvy ){ *pvx = m_VelocityX; *pvx = m_VelocityY; }

void SetPosition( int x, int y ){ m_x = x; m_y = y; }
void GetPosition( int* px, int* py){ *px = m_x, *py = m_y; }

void Update();

HRESULT Initialize( char* strPathName, BOOL bTransparent );

HRESULT Render( LPDIRECT3DSURFACE8 pTargetSurface );

void Shutdown();

protected:

// Variables

public:

protected:
LPDIRECT3DSURFACE8 m_pLayerSurface;

BOOL m_bTransparent;
D3DCOLOR m_ColorKey;

int m_x, m_y;
int m_VelocityX;
int m_VelocityY;

int m_SurfaceWidth;
int m_SurfaceHeight;

enum MOVEMENT{ None, Horizontal, Vertical, Both }m_MoveDirection;

};


CLayer::CLayer()
{
m_pLayerSurface = 0;
m_bTransparent = TRUE;
m_ColorKey = D3DCOLOR_ARGB( 0, 255, 0, 255 );

m_x = m_y = 0;
m_VelocityX = 0;
m_VelocityY = 0;

m_SurfaceWidth = 0;
m_SurfaceHeight = 0;

m_MoveDirection = None;
}

CLayer::~CLayer()
{
if( m_pLayerSurface )
{
m_pLayerSurface->Release();
m_pLayerSurface = 0;
}
}

void CLayer::Update()
{
if( m_VelocityX != 0 && m_VelocityY == 0 )
m_MoveDirection = Horizontal;

else if( m_VelocityY != 0 && m_VelocityX == 0 )
m_MoveDirection = Vertical;

else if( m_VelocityY != 0 && m_VelocityX != 0 )
m_MoveDirection = Both;

else if( m_VelocityY == 0 && m_VelocityX == 0 )
{
m_MoveDirection = None;
return;
}

m_x += m_VelocityX;
m_y += m_VelocityY;

if( m_x >= g_DeviceWidth )
m_x = m_x - g_DeviceWidth;

if( m_x <= -g_DeviceWidth )
m_x = m_x + g_DeviceWidth;

if( m_y >= g_DeviceHeight )
m_y = m_y - g_DeviceHeight;

if( m_y <= -g_DeviceHeight )
m_y = m_y + g_DeviceHeight;
}

void CLayer::Shutdown()
{
m_pLayerSurface = 0;
m_bTransparent = TRUE;
m_ColorKey = D3DCOLOR_ARGB( 0, 255, 0, 255 );

m_x = m_y = 0;
m_VelocityX = 0;
m_VelocityY = 0;

m_SurfaceWidth = 0;
m_SurfaceHeight = 0;

if( m_pLayerSurface )
{
m_pLayerSurface->Release();
m_pLayerSurface = 0;
}
}

HRESULT CLayer::Initialize( char* strPathName, BOOL bTransparent )
{
if( m_pLayerSurface )
{
m_pLayerSurface->Release();
m_pLayerSurface = 0;
}

HRESULT r = 0;

r = LoadBitmapToSurface( strPathName, &m_pLayerSurface, g_pDevice );
if( FAILED( r ) )
return E_FAIL;

m_bTransparent = bTransparent;

D3DSURFACE_DESC d3dsd;

m_pLayerSurface->GetDesc( &d3dsd );

m_SurfaceWidth = d3dsd.Width;
m_SurfaceHeight = d3dsd.Height;

return S_OK;
}



HRESULT CLayer::Render( LPDIRECT3DSURFACE8 pTargetSurface )
{
// If there is no target surface then return failure

if( !pTargetSurface )
return E_FAIL;

// Hods information about the target surface

D3DSURFACE_DESC d3dsd;

// Get information about the target surface

pTargetSurface->GetDesc( &d3dsd );

// Create local copies of the layer position for modification

int OffsetX = m_x;
int OffsetY = m_y;

// If the layers position is less than 0 then rendering

// will fail. It turns out that moving the layer forward

// by the surface width + the negative offset creates

// the same effect. So (-10,-10) changes to (630,470)

if( OffsetX < 0 )
{
OffsetX = d3dsd.Width + m_x;
}
if( OffsetY < 0 )
{
OffsetY = m_SurfaceHeight + OffsetY;
}

// Figure out which way the layer is moving

switch( m_MoveDirection )
{
case None:
{
// The layer is not moving so just straight copy it

CopySurfaceToSurface( 0, m_pLayerSurface, 0, pTargetSurface, m_bTransparent, m_ColorKey );
return S_OK;
}

case Horizontal:
{
// The layer is moving horizontally so it needs to

// be split into two different reagions; left and right

RECT RectL, RectR;

// The right rectangle starts at the offset

POINT DestPointR = { OffsetX, OffsetY };
// The left rectangle starts at the origin

POINT DestPointL = { 0, OffsetY };

// Fill in the source dimensions for the right

// rectangle

SetRect( &RectR, 0,
0,
m_SurfaceWidth - OffsetX,
m_SurfaceHeight );

// Fill in the source dimensions for the left

// rectangle

SetRect( &RectL, m_SurfaceWidth - OffsetX,
0,
OffsetX,
m_SurfaceHeight );

// Copy the left rectangle to the destination surface

CopySurfaceToSurface( &RectL, m_pLayerSurface, &DestPointL,
pTargetSurface, m_bTransparent, m_ColorKey );
// Copy the right rectangle to the destination surface

CopySurfaceToSurface( &RectR, m_pLayerSurface, &DestPointR,
pTargetSurface, m_bTransparent, m_ColorKey );

return S_OK;
}

case Vertical:
{
// The layer is moving vertically so it

// needs to be split into 2 regions; top and bottom

RECT RectT, RectB;

// Fill in the destination for the top rectangle

POINT DestPointT = { OffsetX, 0 };
// Fill in the destination for the bottom rectangle

POINT DestPointB = { OffsetX, OffsetY };

// Fill in the source dimensions for the top rectangle

SetRect( &RectT, 0,
m_SurfaceHeight - OffsetY,
m_SurfaceWidth,
OffsetY );

// Fill in the source dimensions for the bottom rectangle

SetRect( &RectB, 0,
0,
m_SurfaceWidth,
m_SurfaceHeight - OffsetY);

// Copy the top rectangle to the destination surface

CopySurfaceToSurface( &RectT, m_pLayerSurface, &DestPointT,
pTargetSurface, m_bTransparent, m_ColorKey );
// Copy the bottom rectangle to the destination surface

CopySurfaceToSurface( &RectB, m_pLayerSurface, &DestPointB,
pTargetSurface, m_bTransparent, m_ColorKey );

return S_OK;
}

case Both:
{
// The layer is moving diagonally so

// it needs to be split into four regions

RECT Rect0, Rect1, Rect2, Rect3;

// Fill in the destination points for the four rectangles

POINT DestPoint0 = { OffsetX, OffsetY },
DestPoint1 = { OffsetX, 0 },
DestPoint2 = { 0, OffsetY },
DestPoint3 = { 0, 0 };

// Fill in the dimensions for the source rectangles

SetRect( &Rect0, 0, 0, m_SurfaceWidth - OffsetX, m_SurfaceHeight - OffsetY );
SetRect( &Rect1, 0, m_SurfaceHeight - OffsetY, m_SurfaceWidth - OffsetX, OffsetY );
SetRect( &Rect2, m_SurfaceWidth - OffsetX, 0, OffsetX, m_SurfaceHeight - OffsetY );
SetRect( &Rect3, m_SurfaceWidth - OffsetX, m_SurfaceHeight - OffsetY, OffsetX, OffsetY );

// Copy the rectangles to the destination surface

CopySurfaceToSurface( &Rect0, m_pLayerSurface, &DestPoint0,
pTargetSurface, m_bTransparent, m_ColorKey );
CopySurfaceToSurface( &Rect1, m_pLayerSurface, &DestPoint1,
pTargetSurface, m_bTransparent, m_ColorKey );
CopySurfaceToSurface( &Rect2, m_pLayerSurface, &DestPoint2,
pTargetSurface, m_bTransparent, m_ColorKey );
CopySurfaceToSurface( &Rect3, m_pLayerSurface, &DestPoint3,
pTargetSurface, m_bTransparent, m_ColorKey );

return S_OK;

}
}

return S_OK;
}

/*******************************************************************
********************************************************************
*
* Direct3D 3D Code
*
********************************************************************
********************************************************************/


HRESULT CreateViewport()
{
HRESULT r = 0;

if( !g_pDevice )
return E_FAIL;

D3DVIEWPORT8 Viewport;

Viewport.X = 0;
Viewport.Y = 0;
Viewport.Width = g_DeviceWidth;
Viewport.Height = g_DeviceHeight;
Viewport.MinZ = 0.0f;
Viewport.MaxZ = 1.0f;

r = g_pDevice->SetViewport( &Viewport );

return r;
}

void SetProjectionMatrix()
{
D3DXMATRIX ProjectionMatrix;
ZeroMemory( &ProjectionMatrix, sizeof( D3DXMATRIX ) );

float ScreenAspect = (float)g_DeviceWidth / (float)g_DeviceHeight;
float FOV = D3DX_PI / 4;

D3DXMatrixPerspectiveFovLH( &ProjectionMatrix, FOV, ScreenAspect, 1.0f, 1000.0f );

g_pDevice->SetTransform( D3DTS_PROJECTION, &ProjectionMatrix );
}


It didnt work when i changed the resolution around...

PS: YES, this isnt original code but code from the examples in "zen of d3d game programming"...

[edited by - Pirosan on October 14, 2003 8:23:05 PM]

[edited by - Pirosan on October 14, 2003 8:25:23 PM]

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
make your device type D3DDEVTYPE_REF or D3DDEVTYPE_HAL not D3DDEVTYPE_SW

Share this post


Link to post
Share on other sites
Is the program stopping after you try to create the device for sure? Try debugging it if your not sure...

D3DFMT_A8R8G8B8 might not work for you. You might have to use D3DFMT_R5G6B5 or D3DFMT_X8R8G8B8. (This is in your InitDirect3DDevice() call). You can find an entire list of all the D3DFORMAT''s under D3DFORMAT in the index of the sdk (this is the 9.0b sdk though).


Share this post


Link to post
Share on other sites
i debugged it, and it returns false when the CreateDevice is called so i know thats where it stops the program.

I also tried the ideas u had, they had the same effect. I also tried different resolutions and screen sizes...

[edited by - Pirosan on October 14, 2003 9:57:41 PM]

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
I’m guessing your present parameters don’t match up to your hardware support.

Take a look at the SDK doc “Selecting a Device”


Oh and D3DPRESENT_INTERVAL_IMMEDIATE wont work with a REF device. You can try D3DPRESENT_INTERVAL_ONE

Share this post


Link to post
Share on other sites
Try running some of the samples in the sdk, and go into the display options. You will be able to see what modes you have available to you. It prints out the device, window size, and format on the screen, too, so you should be able to find some stuff there.


Share this post


Link to post
Share on other sites
Well, i figured out what was wronge...

I went to the sdk sample MFC fog, and i changed my device settings to mimic the sdk's settings... I changed the settings to HAL and D3DFMT_R5G6B5(D3DFMT_A8R8G8B8 was the faulty setting) and it WORKS!!!

Thankyou everyone for helping me out... I really should have thought of referencing sdk projects... it mustv slipped my mind...


Again, thankyou to all who helped me find out the fault!


Chris Gibson

-------
HAPPY CODING

[edited by - Pirosan on October 14, 2003 10:30:20 PM]

Share this post


Link to post
Share on other sites
D3DFMT_X8R8G8B8 did not work either... D3DFMT_R5G6B5 worked, and the program ran with no problems. The samples now work!! (yippy)


[edited by - Pirosan on October 15, 2003 2:52:49 AM]

Share this post


Link to post
Share on other sites
please tell me what videocard you have because it can''t seem to handle 32 bits color modes, which is really really weird. X8R8G8B8 should also work for adapters which use 24 bits modes doesn''t it?

Share this post


Link to post
Share on other sites
I dont know how old this comp''s graphics card is... but its old (i got this laptop like 2 years ago)

I have an Intel 82815 Graphics Controller... Does that help?

Share this post


Link to post
Share on other sites
I looked at some code and came up with a function using a little of the code i saw to find out what settings (how many bits) you have:


D3DFORMAT findMode(void){
HRESULT hr;

hr=g_D3D->CheckDeviceType(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,D3DFMT_R5G6B5,D3DFMT_R5G6B5,FALSE);
if(SUCCEEDED(hr)){
//yey it has D3DFMT_R5G6B5

return D3DFMT_R5G6B5;
}

hr=g_D3D->CheckDeviceType(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,D3DFMT_X1R5G5B5,D3DFMT_X1R5G5B5,FALSE);
if(SUCCEEDED(hr)){
//yey it has D3DFMT_X1R5G5B5

return D3DFMT_X1R5G5B5;
}
//This isnt going to work... bail out BAIL OUT!!!


return (D3DFORMAT)NULL;
}


that should eliminate the death of my program, and it will work for older and newer graphics cards (i think :D)

BTW: I havent fully tested this so it might have a bug... i dunno now...

Also, this can be used to check out more than just two bit settings... i could add many more :D
[edited by - Pirosan on October 15, 2003 6:52:37 PM]

[edited by - Pirosan on October 15, 2003 6:53:30 PM]

Share this post


Link to post
Share on other sites