Original Post
could you possibly run my code and figure out why it just quits for no reason? I figure it has something to do with the LoadAlphabet(), PrintChar(), PrintString() and UnloadAlphabet() functions. It crashes on me when i debug, forcing me to cold boot.
heres the cpp file
and heres the .h file
please try that out, and i appreciate your help, email me if ya want c_chack@yahoo.com
[edited by - Sabonis on January 4, 2003 2:21:49 PM]
#define WIN32_LEAN_AND_MEAN
// The main windows include file
#include <windows.h>
#include <mmsystem.h>
#include <d3d8.h>
#include <d3dx8.h>
#include "MustangII.h"
int GameInit();
int GameLoop();
int GameShutdown();
int Render();
#define RENDER_GDI 2 //Render with the GDI
#define RENDER_D3D 1 // Render with Direct 3D
#define RENDER_BOTH 0 //Render with both
// 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_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;
}
case WM_KEYDOWN:
{
switch( wParam )
{
case VK_SPACE:
{
g_RenderMode++;
if( g_RenderMode > 2)
g_RenderMode = 0;
break;
}
default:
break;
}
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[] = "Direct3D Initialization FullScreen";
// 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_OVERLAPPEDWINDOW,// 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; // Holds return values
// 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_X8R8G8B8, g_pD3D, &g_pDevice );
if(FAILED(r))
{
SetError("Initialization of the device failed");
return E_FAIL;
}
g_pDevice->Clear(0,0, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,0), 1.0f,0);
r = g_pDevice->GetBackBuffer( 0, D3DBACKBUFFER_TYPE_MONO, &g_pBackSurface );
if( FAILED( r ) )
{
SetError( "Couldnt get backbuffer" );
return E_FAIL;
}
LoadAlphabet("Alphabet Small.BMP",16,32);
srand(GetTickCount());
return S_OK;
}
int GameLoop()
{
Render();
if( GetAsyncKeyState( VK_ESCAPE ) )
PostQuitMessage(0);
return S_OK;
}
LPDIRECT3DSURFACE8 g_pBackSurf = 0;
int Render()
{
HRESULT r = 0;
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;
r = g_pBackSurface->LockRect( &Locked, 0, 0 );
if(FAILED(r))
{
SetError("Could not lock the LOCKED surface");
return E_FAIL;
}
DWORD* pLockedData = (DWORD*)Locked.pBits;
//Locked.Pitch /=4;
PrintString(10, 30, "The Alphabet Begins with Z!!!", TRUE, D3DCOLOR_ARGB(0, 255, 0, 255),0,0);
//PrintFrameRate( 550, 400, TRUE, D3DCOLOR_ARGB(0,255,0,255), pLockedData, Locked.Pitch);
g_pBackSurface->UnlockRect();
g_pDevice->Present(NULL,NULL,NULL,NULL);
return S_OK;
}
int GameShutdown()
{
//Delete the DC and bitmap for the GDI image
//Release the pointer back to the surface
if( g_pBackSurf)
g_pBackSurface->Release();
//Release the surface holding the D3D image
if(g_pD3DBitmapSurf)
g_pD3DBitmapSurf->Release();
// Release the pointer to IDirect3DDevice8
if( g_pDevice )
g_pDevice->Release();
// Release the pointer to IDirect3D8
if( g_pD3D )
g_pD3D->Release();
UnloadAlphabet();
return S_OK;
}
#include <stdio.h>
D3DPRESENT_PARAMETERS g_SavedPresParams;
int g_RenderMode = 0;
LPDIRECT3D8 g_pD3D = 0;
LPDIRECT3DDEVICE8 g_pDevice = 0;
LPDIRECT3DSURFACE8 g_pBackSurface = 0;
LPDIRECT3DSURFACE8 g_pD3DBitmapSurf = 0;
HBITMAP g_hGDIBitmap = 0;
HDC g_hGDIBitmapDC = 0;
HWND g_hWndMain;
int g_DeviceWidth = 0;
int g_DeviceHeight = 0;
HRESULT RestoreGraphics();
INT64 g_Frequency = 0;
int g_AlphabetWidth = 0;
int g_AlphabetHeight = 0;
int g_AlphabetLetterWidth = 0;
int g_AlphabetLetterHeight = 0;
int g_AlphabetLettersPerRow = 0;
LPDIRECT3DSURFACE8 g_pAlphabetSurface = 0;
//has the alphabet been loaded yet?
BOOL g_bAlphabetLoaded = FALSE;
BOOL bTransparent;
int g_FrameCount;
int g_FrameRate;
// Output an error to the debug window
void SetError( char* String )
{
OutputDebugString( "ERROR: " );
OutputDebugString( String );
OutputDebugString( "\n" );
}
/**************************************************************
***************************************************************
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 = 0;
// 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_HAL, 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 RENDERING CODE*********************************
//******************************************************************************
//Set a single pixel to a color
void SetPixel32( int x, int y, DWORD Color, int Pitch, DWORD* pData)
{
if( x > g_DeviceWidth || x < 0)
return;
if(y > g_DeviceHeight || y < 0)
return;
pData[ ((Pitch/4) * y) + x ] = Color;
}
//Old slow way of drawing a rectangle
void Rectangle32( D3DRECT* pRect, DWORD Color, int Pitch, DWORD* pData )
{
int y1 = pRect->y1;
int y2 = pRect->y2;
int x1 = pRect->x1;
int x2 = pRect->x2;
int Pitch4 = Pitch / 4;
DWORD Offset = y1 * Pitch4 + x1;
for( int y = y1 ; y < y2 ; y++ )
{
for( int x = x1 ; x < x2 ; x++ )
{
pData[ Offset + x ] = Color;
}
Offset += Pitch4;
}
}
//New good fast way to draw a rectangle
void Rectangle32Fast( D3DRECT* pRect, DWORD Color, LPDIRECT3DDEVICE8 pDevice)
{
pDevice->Clear(1,pRect,D3DCLEAR_TARGET, Color, 0.0f, 0);
}
//Loading a bitmap to the primary surface
int LoadBitmapToSurface( char* PathName, LPDIRECT3DSURFACE8* ppSurface, LPDIRECT3DDEVICE8 pDevice)
{
HRESULT r;
HBITMAP hBitmap;
BITMAP Bitmap;
hBitmap = (HBITMAP)LoadImage(NULL, PathName, IMAGE_BITMAP,0,0,LR_LOADFROMFILE | LR_CREATEDIBSECTION);
if(hBitmap == NULL)
{
SetError("Unable to load Bitmap");
return E_FAIL;
}
GetObject( hBitmap, sizeof(BITMAP),&Bitmap);
DeleteObject(hBitmap);
r= pDevice->CreateImageSurface(Bitmap.bmWidth, Bitmap.bmHeight, D3DFMT_X8R8G8B8, ppSurface);
if(FAILED(r))
{
SetError("Unable to create Surface for bitmap to load");
return E_FAIL;
}
r= D3DXLoadSurfaceFromFile(*ppSurface, NULL, NULL, PathName, NULL, D3DX_FILTER_NONE, 0, NULL);
if(FAILED(r))
{
SetError("Unable to load the file to surface");
return E_FAIL;
}
return S_OK;
}
//Create a compatible Device context from GDI for use with DX surfaces
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));
//Size of the stucture 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 topdown image )
bi.bmiHeader.biHeight = -Height;
//Obsolete - -Just set to 1
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;
}
//Delete the bitmap from memory
void DeleteD3DCompatibleDC( HDC hDC, HBITMAP hDibSection)
{
// Delete the bitmap
DeleteObject( hDibSection);
//Delete the DC
DeleteDC(hDC);
}
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 abou 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 map in the DC
//is to be copied
if( !pSrcRect )
SetRect( &SourceRect, 0, 0, SrcTotalWidth, SrcTotalHeight);
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 DC source 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;
}
//Conver 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 destination pointer by the pitch
DestOffset+=Pitch32;
//incerase 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++;
}
}
}
//Unlock the surface
pDestSurf->UnlockRect();
//return success
return S_OK;
}
//Check for a valid device
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)
{
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");
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;
}
HRESULT RestoreGraphics()
{
return S_OK;
}
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 se the rectangle to encompass 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 become DWORD compatible
LockedSource.Pitch /= 4;
LockedDest.Pitch /= 4;
//Get 32-bit pointers to the surface data
DWORD* pSourceData = (DWORD*)LockedSource.pBits;
DWORD* pDestData = (DWORD*)LockedDest.pBits;
//Get the offset into the soruce surface
int SourceOffset = SourceRect.top * LockedSource.Pitch + SourceRect.left;
//get the offset of 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 requestec
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 the next pixel in the source
SourceOffset++;
}
//move the source offset to the next row of the image y 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;
}
HRESULT InitTiming()
{
//get the number of counts per second
QueryPerformanceFrequency( (LARGE_INTEGER*) &g_Frequency );
//if the frequency is zero then the system does not have high performance timers
if( g_Frequency == 0)
{
SetError("The system does not support high resolution timers" );
return E_FAIL;
}
return S_OK;
}
void Pause(int Milliseconds)
{
//Convert the milliseconds to seconds
INT64 SecondsDelay = (INT64)Milliseconds * 1000;
INT64 StartTime;
INT64 CurrentTime;
//get the start time
QueryPerformanceCounter((LARGE_INTEGER*)&StartTime);
while(TRUE)
{
//get the current time
QueryPerformanceCounter((LARGE_INTEGER*)&CurrentTime);
//if enough time has passed then break from the loop
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 difference since the last count
//get the current count
QueryPerformanceCounter((LARGE_INTEGER*)&NewCount);
//if the count is 0 then the 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;
}
}
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 the global surface
r = LoadBitmapToSurface(strPathName, &g_pAlphabetSurface, g_pDevice);
if(FAILED(r))
{
SetError("Unable to load the alphabet bitmap");
return E_FAIL;
}
//holds information about the alphabet 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 laded flay 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 coy 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 Transparent, 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
PrintChar(x + (g_AlphabetLetterWidth * i ), y, String[i], bTransparent, ColorKey, pDestData, DestPitch );
}
}
void PrintFrameRate(int x, int y, BOOL bTransparent, D3DCOLOR ColorKey, DWORD* pDestData, int DestPitch)
{
char string[4];
//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 );
}