/*****************************************************************************
 * $Id: gfx_machine.hh,v 1.4 2006/08/03 02:17:21 devel Exp $
 * @file
 * @author	Jim E. Brooks  http://www.jimbrooks.org
 * @brief	State-machine.
 *//*
 * LEGAL:	COPYRIGHT (C) 2005 JIM E. BROOKS
 *          THIS SOURCE CODE IS RELEASED UNDER THE TERMS
 *          OF THE GNU GENERAL PUBLIC LICENSE (GPL).
 *****************************************************************************/

#ifndef GFX_MACHINE_HH
#define GFX_MACHINE_HH 1

#include <stack>
#include "gfx_machine_defs.hh"

namespace gfx {

////////////////////////////////////////////////////////////////////////////////
// Machine class.
class Machine
{
    PREVENT_COPYING(Machine)
public:
	typedef long Opcode;
	typedef	bool (*MachineFunc)( Machine* );
	enum eMachineState
	{
		eMachineState_RUNNING,
		eMachineState_SUSPEND,
		eMachineState_QUIT
	};

public:
					Machine( Opcode* ip, void* userData );
	explicit		Machine( void* userData );
					~Machine() { }
	void			Switch( Opcode* ip );
	bool			Tick( void );
	int				GetTick( void ) { return mCLOCK; }
	void*			GetUserData( void ) { return mUserData; }

private:
	void			Init( Opcode* ip, void* userData );
	void			SetIP( Opcode* ip );
	eMachineState	Execute( void );
	void			Compile( void );
#if DEBUG
	const char*		GetProcName( void );
	const char*		GetOpcodeName( Machine::Opcode opc );
#endif
	enum
	{
		PROC_MAX_LEN = 256,		// maximum amount of instructions in one procedure
	};

private:
	// Virtual processor registers:
	Opcode*			mIP;			// instruction pointer
	bool			mFLAG;			// one-bit bool flag register
	stack<Opcode*>	mSTACK;			// procedure/call stack
	int				mCLOCK;			// count of clock ticks
#if DEBUG
	// PROC is a debug register used to catch if the virtual processor
	// is executing in the Twilight Zone and to display a procedure's name.
	Opcode*			mPROC;			// points to first instruction of current procedure
	stack<Opcode*>	mSTACK_PROC;	// stack of PROC register values
#endif

	void*			mUserData;		// user-defined object associated with this machine object
};

} // namespace gfx

#endif // GFX_MACHINE_HH
