#include <windows.h>
#include <stdio.h>
#include <d3d8.h>
#include <d3dx8.h>
#include "stdverts.h"
//////////
//
// DX8 dx8 + fmod + cfl tutorial
// Jari Komppa 2001
char progname[]="DX8+FMOD+CFL tutorial - Sol";
LPDIRECT3D8 d3d; // Direct3d8 object
LPDIRECT3DDEVICE8 d3dd; // Rendering device
LPD3DXFONT debugfont; // Debug font (only used in winmain)
// Rendering function. This is called from winmain() on each rendering pass.
void Render()
{
}
// This is the cleanup function called from winmain().. make sure
// fmod is dead and clean up dx objects.
void Cleanup()
{
if( d3dd != NULL)
d3dd->Release();
if( d3d != NULL)
d3d->Release();
d3dd=NULL;
d3d=NULL;
}
// Window procedure.. this function gets all the window messages.
// (note that clicking on the top left corner 'x' may go directly here
// and skip winmain() loop completely!)
LRESULT CALLBACK WindowProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
switch (uMsg) {
case WM_KEYDOWN:
switch( wParam ) {
case VK_ESCAPE:
case VK_F12:
// if escape or f12 is pressed, post kill message to us.
PostMessage(hWnd, WM_CLOSE, 0, 0);
break;
}
case WM_DESTROY:
// kill message received, post quit one, clean up and quit.
PostQuitMessage(0);
Cleanup();
exit(wParam);
break;
case WM_PAINT:
// If wm_paint should be received, just tell windows everything
// is a-ok..
ValidateRect( hWnd, NULL );
break;
default:
// rest of the messages may do whatever they do by default.
return DefWindowProc (hWnd, uMsg, wParam, lParam) ;
break;
}
return 0;
}
// Windows main function. Set up window, set up dx, call setup to set up the rest
// and finally do the rendering loop.
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpszCmdLine, int nCmdShow)
{
WNDCLASSEX winclass;
HWND hWnd;
MSG msg;
// Create window class
winclass.cbSize=sizeof(WNDCLASSEX);
winclass.style=CS_DBLCLKS;
winclass.lpfnWndProc=&WindowProc;
winclass.cbClsExtra=0;
winclass.cbWndExtra=0;
winclass.hInstance=hInst;
winclass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
winclass.hCursor=LoadCursor(NULL,IDC_ARROW);
winclass.hbrBackground=GetSysColorBrush(COLOR_APPWORKSPACE);
winclass.lpszMenuName=NULL;
winclass.lpszClassName=progname;
winclass.hIconSm=NULL;
// I don't know if this can ever fail, really:
if (!RegisterClassEx(&winclass)) return 0;
// Create a 640 by 480 window (note that the client area will be somewhat smaller!)
hWnd=CreateWindow(progname,progname,WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,0,640,480,NULL,NULL,hInst,NULL);
// Show the window
ShowWindow(hWnd,nCmdShow);
// Create d3d object, or if fail, quit.
if (NULL == (d3d = Direct3DCreate8(D3D_SDK_VERSION))) return E_FAIL;
// Ask user whether we want to go fullscreen or not.
int fullscreen=0;
if (MessageBox(hWnd,"Go fullscreen?",progname,MB_YESNO)==IDYES) fullscreen=1;
// Set up presentation. This is the biggest mess in dx8 and could have
// been designed better in my opinnion.
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
if (fullscreen) {
d3dpp.Windowed=FALSE;
d3dpp.BackBufferWidth=640;
d3dpp.BackBufferHeight=480;
d3dpp.BackBufferFormat=D3DFMT_X8R8G8B8;//D3DFMT_R5G6B5;
d3dpp.BackBufferCount=3;
d3dpp.SwapEffect=D3DSWAPEFFECT_DISCARD;
d3dpp.EnableAutoDepthStencil=TRUE;
d3dpp.AutoDepthStencilFormat=D3DFMT_D24S8;
} else {
D3DDISPLAYMODE d3ddm;
if( FAILED( d3d->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &d3ddm ) ) )
return E_FAIL;
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = d3ddm.Format;
d3dpp.EnableAutoDepthStencil=TRUE;
d3dpp.AutoDepthStencilFormat=D3DFMT_D24S8;
}
// Basically, try to create the device first with whatever we wanted,
// then with 16-bit zbuffer and then with 16-bit color buffer. If all
// of this fails, die.
if( FAILED( d3d->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &d3dd ) ) )
{
if( FAILED( d3d->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &d3dd ) ) )
{
d3dpp.AutoDepthStencilFormat=D3DFMT_D16;
if( FAILED( d3d->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &d3dd ) ) )
{
d3dpp.BackBufferFormat=D3DFMT_R5G6B5;
if( FAILED( d3d->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &d3dd ) ) )
{
return 0;
}
}
}
}
// Now that dx is up, create a debug font so we can see the framerate:
D3DXCreateFont(d3dd,(HFONT)GetStockObject(SYSTEM_FONT),&debugfont);
int frame=0;
int starttime=GetTickCount();
char str[200];
// Main rendering loop.
while (1) {
// Hide the cursor if fullscreen.
if (fullscreen) SetCursor(NULL);
// Clear framebuffer and zbuffer.
d3dd->Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER , D3DCOLOR_XRGB(0,0,0), 1.0f, 0 );
// Begin rendering.
d3dd->BeginScene();
// Do the rendering.
Render();
// Count frames
frame++;
int sec=GetTickCount()-starttime;
// and if we've done counting for more than a second, print the framerate
if (sec>0)
sprintf(str,"fps:%3.3f",(frame*1000.0)/sec);
// Only consider 1-100 frames for frame counting.
if (frame>100) {
frame=0;
starttime+=sec;
}
// Print the framerate on screen. (The text printing is much
// better in dx8 than in dx7, but you get all this rectangle
// mess as well)
RECT r; r.top=11;r.left=11;r.bottom=470;r.right=630;
debugfont->DrawTextA(str,-1,&r,DT_LEFT|DT_TOP,0xff000000);
r.top=10;r.left=10;r.bottom=470;r.right=630;
debugfont->DrawTextA(str,-1,&r,DT_LEFT|DT_TOP,0xffffffff);
// We're done with the scene.
d3dd->EndScene();
// Dump the frame on screen.
d3dd->Present( NULL, NULL, NULL, NULL );
// Check the windows messages and process them.
if(PeekMessage(&msg,hWnd,0,0,PM_REMOVE)) {
WindowProc(hWnd,msg.message,msg.wParam,msg.lParam);
}
}
// This line is never reached:
return 0;
}