I am trying to create a set of functions to allow the user to output a string to a file name EngineLog.txt
It compiles fine, but I get an Unhandled exception at 0x00444c36 in Test.exe: 0xC0000005: Access violation writing location 0x0000000d. This occurs in the EnableLogging() function.
//-----------------------------------------------------------------------------
// The primary engine header file. This file links the entire engine together
// and is the only header file that needs to be included in any project using
// the engine.
//
// Programming a Multiplayer First Person Shooter in DirectX
// Copyright (c) 2004 Vaughan Young
//-----------------------------------------------------------------------------
#ifndef ENGINE_H
#define ENGINE_H
//-----------------------------------------------------------------------------
// DirectInput Version Define
//-----------------------------------------------------------------------------
#define DIRECTINPUT_VERSION 0x0800
//-----------------------------------------------------------------------------
// System Includes
//-----------------------------------------------------------------------------
#include <stdio.h>
#include <tchar.h>
#include <windowsx.h>
//-----------------------------------------------------------------------------
// DirectX Includes
//-----------------------------------------------------------------------------
#include <d3dx9.h>
#include <dinput.h>
#include <dplay8.h>
#include <dmusici.h>
//-----------------------------------------------------------------------------
// standard library Includes
//-----------------------------------------------------------------------------
#include <string>
#include <fstream>
using namespace std;
//-----------------------------------------------------------------------------
// Macros
//-----------------------------------------------------------------------------
#define SAFE_DELETE( p ) { if( p ) { delete ( p ); ( p ) = NULL; } }
#define SAFE_DELETE_ARRAY( p ) { if( p ) { delete[] ( p ); ( p ) = NULL; } }
#define SAFE_RELEASE( p ) { if( p ) { ( p )->Release(); ( p ) = NULL; } }
//-----------------------------------------------------------------------------
// Engine Includes
//-----------------------------------------------------------------------------
#include "LinkedList.h"
#include "ResourceManagement.h"
#include "Geometry.h"
#include "Input.h"
#include "State.h"
#include "LogicState.h"
#include "NetState.h"
#include "RenderState.h"
#include "SndState.h"
#include "UIState.h"
#include "Scripting.h"
//-----------------------------------------------------------------------------
// Engine Setup Structure
//-----------------------------------------------------------------------------
struct EngineSetup
{
HINSTANCE instance; // Application instance handle.
char *name; // Name of the application.
void (*StateSetup)(); // State setup function.
//-------------------------------------------------------------------------
// The engine setup structure constructor.
//-------------------------------------------------------------------------
EngineSetup()
{
instance = NULL;
name = "Application";
StateSetup = NULL;
}
};
//-----------------------------------------------------------------------------
// Engine Class
//-----------------------------------------------------------------------------
class Engine
{
public:
Engine( EngineSetup *setup = NULL );
void EnableLogging();
void WriteToLog(string log);
void CloseLog();
virtual ~Engine();
void Run();
HWND GetWindow();
void SetDeactiveFlag( bool deactive );
void AddState( State *state, bool change = true );
void RemoveState( State *state );
void ChangeState( unsigned long id );
State *GetCurrentState();
ResourceManager< Script > *GetScriptManager();
Input *GetInput();
private:
bool m_loaded; // Indicates if the engine is loading.
HWND m_window; // Main window handle.
bool m_deactive; // Indicates if the application is active or not.
bool logOk; // Ensures that logging has been enabled.
ofstream fout; // variable to output to the text file.
EngineSetup *m_setup; // Copy of the engine setup structure.
LinkedList< State > *m_states; // Linked list of states.
State *m_currentState; // Pointer to the current state.
bool m_stateChanged; // Indicates if the state changed in the current frame.
ResourceManager< Script > *m_scriptManager; // Script manager.
Input *m_input; // Input object.
};
//-----------------------------------------------------------------------------
// Externals
//-----------------------------------------------------------------------------
extern Engine *g_engine;
#endif
//-----------------------------------------------------------------------------
// Engine.h implementation.
// Refer to the Engine.h interface for more details.
//
// Programming a Multiplayer First Person Shooter in DirectX
// Copyright (c) 2004 Vaughan Young
//-----------------------------------------------------------------------------
#include "Engine.h"
//-----------------------------------------------------------------------------
// Globals
//-----------------------------------------------------------------------------
Engine *g_engine = NULL;
//-----------------------------------------------------------------------------
// Handles Windows messages.
//-----------------------------------------------------------------------------
LRESULT CALLBACK WindowProc( HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam )
{
switch( msg )
{
case WM_ACTIVATEAPP:
g_engine->SetDeactiveFlag( !wparam );
return 0;
case WM_DESTROY:
PostQuitMessage( 0 );
return 0;
default:
return DefWindowProc( wnd, msg, wparam, lparam );
}
}
//-----------------------------------------------------------------------------
// The engine class constructor.
//-----------------------------------------------------------------------------
Engine::Engine( EngineSetup *setup )
{
// Indicate that the engine is not yet loaded.
m_loaded = false;
// If no setup structure was passed in, then create a default one.
// Otehrwise, make a copy of the passed in structure.
m_setup = new EngineSetup;
if( setup != NULL )
memcpy( m_setup, setup, sizeof( EngineSetup ) );
// Store a pointer to the engine in a global variable for easy access.
g_engine = this;
// Prepare and register the window class.
WNDCLASSEX wcex;
wcex.cbSize = sizeof( WNDCLASSEX );
wcex.style = CS_CLASSDC;
wcex.lpfnWndProc = WindowProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = m_setup->instance;
wcex.hIcon = LoadIcon( NULL, IDI_APPLICATION );
wcex.hCursor = LoadCursor( NULL, IDC_ARROW );
wcex.hbrBackground = NULL;
wcex.lpszMenuName = NULL;
wcex.lpszClassName = "WindowClass";
wcex.hIconSm = LoadIcon( NULL, IDI_APPLICATION );
RegisterClassEx( &wcex );
// Initialise the COM using multithreaded concurrency.
CoInitializeEx( NULL, COINIT_MULTITHREADED );
// Create the window and retrieve a handle to it.
// Note: Later the window will be created using a windowed/fullscreen flag.
m_window = CreateWindow( "WindowClass", m_setup->name, WS_OVERLAPPED, 0, 0, 800, 600, NULL, NULL, m_setup->instance, NULL );
// Create the linked lists of states.
m_states = new LinkedList< State >;
m_currentState = NULL;
// Create the resource managers.
m_scriptManager = new ResourceManager< Script >;
// Create the input object.
m_input = new Input( m_window );
// Seed the random number generator with the current time.
srand( timeGetTime() );
// Allow the application to perform any state setup now.
if( m_setup->StateSetup != NULL )
m_setup->StateSetup();
// The engine is fully loaded and ready to go.
m_loaded = true;
}
//-----------------------------------------------------------------------------
// Enable logging
//-----------------------------------------------------------------------------
void Engine::EnableLogging()
{
logOk = true;
fout.open("EngineLog.txt");
}
//-----------------------------------------------------------------------------
// Write text to a log file
//-----------------------------------------------------------------------------
void Engine::WriteToLog(string log)
{
if(logOk)
fout << log << "\n";
}
//-----------------------------------------------------------------------------
// Close log file
//-----------------------------------------------------------------------------
void Engine::CloseLog()
{
fout.close();
}
//-----------------------------------------------------------------------------
// The engine class destructor.
//-----------------------------------------------------------------------------
Engine::~Engine()
{
// Ensure the engine is loaded.
if( m_loaded == true )
{
// Destroy the states linked lists.
if( m_currentState != NULL )
m_currentState->Close();
SAFE_DELETE( m_states );
// Destroy everything.
SAFE_DELETE( m_input );
SAFE_DELETE( m_scriptManager );
}
// Uninitialise the COM.
CoUninitialize();
// Unregister the window class.
UnregisterClass( "WindowClass", m_setup->instance );
// Destroy the engine setup structure.
SAFE_DELETE( m_setup );
}
//-----------------------------------------------------------------------------
// Enters the engine into the main processing loop.
//-----------------------------------------------------------------------------
void Engine::Run()
{
// Ensure the engine is loaded.
if( m_loaded == true )
{
// Show the window.
ShowWindow( m_window, SW_NORMAL );
// Used to retrieve details about the viewer from the application.
ViewerSetup viewer;
// Enter the message loop.
MSG msg;
ZeroMemory( &msg, sizeof( MSG ) );
while( msg.message != WM_QUIT )
{
if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
else if( !m_deactive )
{
// Calculate the elapsed time.
unsigned long currentTime = timeGetTime();
static unsigned long lastTime = currentTime;
float elapsed = ( currentTime - lastTime ) / 1000.0f;
lastTime = currentTime;
// Update the input object, reading the keyboard and mouse.
m_input->Update();
// Request the viewer from the current state, if there is one.
if( m_currentState != NULL )
m_currentState->RequestViewer( &viewer );
// Update the current state (if there is one), taking state
// changes into account.
m_stateChanged = false;
if( m_currentState != NULL )
m_currentState->Update( elapsed );
if( m_stateChanged == true )
continue;
}
}
}
// Destroy the engine.
SAFE_DELETE( g_engine );
}
//-----------------------------------------------------------------------------
// Returns the window handle.
//-----------------------------------------------------------------------------
HWND Engine::GetWindow()
{
return m_window;
}
//-----------------------------------------------------------------------------
// Sets the deactive flag.
//-----------------------------------------------------------------------------
void Engine::SetDeactiveFlag( bool deactive )
{
m_deactive = deactive;
}
//-----------------------------------------------------------------------------
// Adds a state to the engine.
//-----------------------------------------------------------------------------
void Engine::AddState( State *state, bool change )
{
m_states->Add( state );
if( change == false )
return;
if( m_currentState != NULL )
m_currentState->Close();
m_currentState = m_states->GetLast();
m_currentState->Load();
}
//-----------------------------------------------------------------------------
// Removes a state from the engine
//-----------------------------------------------------------------------------
void Engine::RemoveState( State *state )
{
m_states->Remove( &state );
}
//-----------------------------------------------------------------------------
// Changes processing to the state with the specified ID.
//-----------------------------------------------------------------------------
void Engine::ChangeState( unsigned long id )
{
// Iterate through the list of states and find the new state to change to.
m_states->Iterate( true );
while( m_states->Iterate() != NULL )
{
if( m_states->GetCurrent()->GetID() == id )
{
// Close the old state.
if( m_currentState != NULL )
m_currentState->Close();
// Set the new current state and load it.
m_currentState = m_states->GetCurrent();
m_currentState->Load();
// Indicate that the state has changed.
m_stateChanged = true;
break;
}
}
}
//-----------------------------------------------------------------------------
// Returns a pointer to the current state.
//-----------------------------------------------------------------------------
State *Engine::GetCurrentState()
{
return m_currentState;
}
//-----------------------------------------------------------------------------
// Returns a pointer to the script manager.
//-----------------------------------------------------------------------------
ResourceManager< Script > *Engine::GetScriptManager()
{
return m_scriptManager;
}
//-----------------------------------------------------------------------------
// Returns a pointer to the input object.
//-----------------------------------------------------------------------------
Input *Engine::GetInput()
{
return m_input;
}
//-----------------------------------------------------------------------------
// System Includes
//-----------------------------------------------------------------------------
#include <windows.h>
//-----------------------------------------------------------------------------
// Engine Includes
//-----------------------------------------------------------------------------
#include "..\Engine\Engine.h"
//-----------------------------------------------------------------------------
// Application specific state setup.
//-----------------------------------------------------------------------------
void StateSetup()
{
g_engine->AddState( new UIState(UI_STATE), true );
g_engine->AddState( new NetState(NET_STATE), true);
g_engine->AddState( new LogicState(LOGIC_STATE), true);
g_engine->AddState( new SndState(SND_STATE), true);
g_engine->AddState( new RenderState(RENDER_STATE), true);
}
//-----------------------------------------------------------------------------
// Entry point for the application.
//-----------------------------------------------------------------------------
int WINAPI WinMain( HINSTANCE instance, HINSTANCE prev, LPSTR cmdLine, int cmdShow )
{
// Create the engine setup structure.
EngineSetup setup;
setup.instance = instance;
setup.name = "Engine Control Test";
setup.StateSetup = StateSetup;
//Test our logging functions
g_engine->EnableLogging();
g_engine->WriteToLog("Did my implementation work?");
g_engine->CloseLog();
// Create the engine (using the setup structure), then run it.
new Engine( &setup );
g_engine->Run();
return true;
}