//------------------------------------------------------------
// Tony Hyun Kim
// Spring 2007
// 18.354 Project: Lattice gas
// D3D CAMERA HEADER
//------------------------------------------------------------

#ifndef COMMON_H
#define COMMON_H

#include <iostream>
#include <d3d9.h>
#include <d3dx9.h>

using namespace std;

typedef unsigned char BYTE;

//------------------------------------------------------------
// LATTICE PARAMETERS
// ACTUAL VALUES ARE SET IN COMMON.CPP
//------------------------------------------------------------
extern float	   g_spacing;
extern D3DXVECTOR2 g_dir[6];
extern D3DXVECTOR2 g_origin;

//------------------------------------------------------------
// BIT FLAGS
//------------------------------------------------------------
#define POS_ALL_OFF 0x00 // 0000-0000
#define POS_ALL_ON  0x3f // 0011-1111
#define POS_ZERO    0x01 // 0000-0001
#define POS_ONE     0x02 // 0000-0010
#define POS_TWO     0x04 // 0000-0100
#define POS_THREE   0x08 // 0000-1000
#define POS_FOUR    0x10 // 0001-0000
#define POS_FIVE    0x20 // 0010-0000
#define POS_SIX     0x01 // 0000-0001 NOTE THAT WE INDEX 'SIX' WITH ZERO

extern BYTE g_PosFlags[6];
extern BYTE g_FilledFlags[6];

#define CheckPosByte(byte,index) ((byte & g_PosFlags[index]) == g_PosFlags[index])
#define CheckByte(byte,mask)     ((byte & mask) == mask)

#define TYPE_ALL_0  0x00 // 0000-0000
#define TYPE_ALL_1  0x3f // 0011-1111

//------------------------------------------------------------
// BITWISE HELPER FUNCTIONS
//------------------------------------------------------------

inline int CountOccupants(BYTE& b)
{
	int count = 0;
	for(int i=0; i<6; i++)
		if( CheckPosByte(b,i) )
			count++;
	return count;
}

inline void BitRotateShiftRight(BYTE& b, int n)
{
	BYTE temp = b & g_FilledFlags[n-1];
	b = (b >> n) | (temp << (6-n));
}

inline void BitRotateShiftLeft(BYTE& b, int n)
{
	BYTE temp = b & ~g_FilledFlags[n-1];
	b = (POS_ALL_ON & (b << n)) | (temp >> (6-n));
}

inline void BitSwap(BYTE& byte, int lo, int hi)
{
	int diff = hi - lo;
	BYTE lo_byte = (g_PosFlags[lo] & byte) << diff;
	BYTE hi_byte = (g_PosFlags[hi] & byte) >> diff;
	byte = (byte & ~(g_PosFlags[lo] | g_PosFlags[hi])) | hi_byte | lo_byte;
}

//------------------------------------------------------------
// A SIMPLE CLOCK
//------------------------------------------------------------

struct Clock
{
	Clock(int T);
	int   getTime();
	int	  getPeriod();
	float getFraction();
	void  SlowDown();
	void  SpeedUp();
private:
	int count;
	int period;
};

#endif