← index
Old.Learning.Projects/mx2_1/Masterx.cpp
Source: Old.Learning.Projects/mx2_1/Masterx.cpp
/* MasterX Software Devlopment Kit (SDK) 2.1
DirectX/Win32 Encapsulation For easy game programming.
Written by Jared Bruni
Email Me: JaredBruni@lostsidedead.com 
www.lostsidedead.com


  now contains NuclearMedia
  written by Lee Trager 

  now also includes MasterGraphicEx
  by Danny Anderson
   garageguy@garagegaming.com
   www.garagegaming.com


  as well as MasterLump resource file support 
  
  for MasterX SDK documentation check out
  www.lostsidedead.com
 
  note required librarys within your project link settings

  dxguid.lib ddraw.lib dsound.lib dinput.lib  wsock32.lib winmm.lib

  also before you include this header file
  use
  #define MASTERFILE
  to use the File Lump releated algorithms
  use 
  #define WIN2K
  to use Windows 2000 stuff
  (very little as of now)

*/



#include "MasterX.h"



/********** MasterScreen Object ******************/

MasterScreen::~MasterScreen()
{
	if(lpBack)
	{
		lpBack->Release();
		lpBack = NULL;
	}

	if(lpFront)
	{
		lpFront->Release();
		lpFront = NULL;
	}

	if(lpDD)
	{
		lpDD->Release();
		lpDD = NULL;
	}
}

// ****************** MasterXHWND Object 


// Create and initilze MasterX

bool MasterXHWND::CreateMasterX(char* mytitle,int width, int height,DisplayColor color,WNDPROC proc,HINSTANCE hInst,HICON icon,HCURSOR cursor)
{

	WNDCLASS wc;
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
	wc.hInstance = hInst;
	wc.hIcon = icon;
	wc.hCursor = cursor;
	wc.lpfnWndProc = (WNDPROC) proc;
	wc.lpszClassName = mytitle;
	wc.lpszMenuName = NULL;
	wc.style = CS_HREDRAW | CS_VREDRAW;

	RegisterClass(&wc);

	hwnd = CreateWindow(mytitle,mytitle,WS_POPUPWINDOW,0,0,width,height,0,0,hInst,0);

	if(hwnd == 0)
	{
		return false;
	}

	ShowWindow(hwnd,SW_SHOW);
	UpdateWindow(hwnd);

	int bpp;


	switch(color)
	{
	case COLOR_DEFAULT:
    HDC hdc;
	// retrieves device-specific information about 

    // the specified device. 

	
    // Get the windows device context

	hdc = GetDC(NULL);
    // Get the number of adjacent color bits for each pixel.

    bpp = GetDeviceCaps(hdc, BITSPIXEL);
    // Release the Device Context

	ReleaseDC(NULL, hdc);
		break;

	case COLOR_8:
		bpp = 8;
		break;
	case COLOR_16:
		bpp = 16;
		break;
	case COLOR_24:
		bpp = 24;
		break;
	case COLOR_32:
		bpp = 32;
		break;
	}

	
	HRESULT ddrval;
	
	// create main dd object

	
	ddrval = DirectDrawCreate(NULL, &scr.lpDD,NULL);
	
	if(ddrval != DD_OK)
	{
		MessageBox(NULL,"Couldnt Create DirectX Object! Error: Terminating!","Error!!!",MB_ICONERROR);
		Kill();
		return false;
	}
	
	ddrval = scr.lpDD->SetCooperativeLevel(hwnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT );
	

	
	if(ddrval != DD_OK)
	{
		scr.lpDD->Release();
		MessageBox(0,"Couldnt Set Cooperative Level, Fatal Error Aborting","Error",MB_ICONERROR);		
	}
	
	ddrval = scr.lpDD->SetDisplayMode(width,height,bpp);
	
	if(ddrval != DD_OK)
	{
		MessageBox(0,"Error Setting Display Mode",0,MB_ICONERROR);
		scr.lpDD->Release();
		return false;
		
	}
	
	if(setprimarysurface())
	{
		sound_ok = initSound();
	}
	else
	{
		MessageBox(0,"Couldnt Set Surfaces! Fatal Error! DirectX is jacked Man","Broken Software :(",MB_ICONERROR);
		return false;
	}

	initInput();
	text.init((MasterScreen*)&scr);
	paint.init(&scr);
	
	alive = true;

	return true;
}

// initilize Message Processing Loop

WPARAM MasterXHWND::InitLoop(void(* update)(MASTERSCREEN xscr))
{
	
	MSG msg;

	while(1)
    {
		if (!alive)
		{
			Destroy();
			break;
		}	

        int t = PeekMessage(&msg, NULL, 0U, 0U, PM_NOREMOVE);
        if (t)
        {
            if (!GetMessage (& msg, NULL, 0, 0))
            return msg.wParam;
            TranslateMessage (&msg);
            DispatchMessage (&msg);
        }
        
        else if (activeapp)// this is important here

		{	
			clear();
			update(mscr);
			mx_update();

		}
        else if (!activeapp)
		{
         WaitMessage();
		}
    }

	return msg.wParam;
	
}

// release and destroy Objects 

void MasterXHWND::Destroy()
{
	// Kill Sound Handler

	// Kill Graphic Handler

	pKeyboard->Unacquire();
	pKeyboard->Release();
	pDI->Release();
	pDI = NULL;

	if(pDS)
	{
		pDS->Release();
	}

	
}
// Break the Loop and kill this Program

void MasterXHWND::Kill()
{
	alive = false;
}


// Get Current Screen

MASTERSCREEN MasterXHWND::GetScreen()
{
	return mscr;
}
// Set the Screen

void MasterXHWND::SetScreen(MASTERSCREEN xmscr)
{
	mscr = xmscr;
}

// Send a Message to the HWND current iniilized

LRESULT MasterXHWND::SendMasterMessage(UINT msg,WPARAM wParam,LPARAM lParam)
{

	return SendMessage(hwnd,msg,wParam,lParam);
}
// Master Clear Screen

void MasterXHWND::clear()
{
	ZeroMemory(&ddbltfx,sizeof(ddbltfx));
	ddbltfx.dwSize = sizeof(ddbltfx);
	ddbltfx.dwFillColor = 0;
	scr.lpBack->Blt(NULL,NULL,NULL,DDBLT_COLORFILL | DDBLT_WAIT,&ddbltfx);
}

// Manual MasterX Update (Buffer Flip)

void MasterXHWND::mx_update()
{
	
	HRESULT ddrval;
	ddrval = scr.lpFront->Flip(NULL, DDFLIP_WAIT);
	
	if(ddrval == DD_OK)
	{
	}
	else
	{
  	 scr.lpFront->Restore();
	}
}
// initilize Input

void MasterXHWND::initInput()
{
	DirectInputCreate(GetModuleHandle(NULL),DIRECTINPUT_VERSION,(struct IDirectInputA**)&pDI,NULL);

	pDI->CreateDevice(GUID_SysKeyboard,&pKeyboard,NULL);
	pKeyboard->SetDataFormat(&c_dfDIKeyboard);

	// Set the cooperative level 

	pKeyboard->SetCooperativeLevel(hwnd, 
		DISCL_FOREGROUND | DISCL_NONEXCLUSIVE); 
	pKeyboard->Acquire();
}

// set primary surfaces

bool MasterXHWND::setprimarysurface()
{
	
	DDSURFACEDESC ddsd;
	DDSCAPS ddscaps;
	HRESULT ddrval;
	
	memset(&ddsd,0,sizeof(ddsd)); // ok were filling out a surface description

	ddsd.dwSize = sizeof(ddsd); // then using createsurface

	// to attach it to the global surface

	ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
    ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
	ddsd.dwBackBufferCount = 1;
	
	ddrval = scr.lpDD->CreateSurface(&ddsd,&scr.lpFront,NULL);
	if(ddrval != DD_OK)
	{
        scr.lpDD->Release();
		return false;
	}
	
	// Set the description for backbuffer

	
	ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
	ddrval = scr.lpFront->GetAttachedSurface(&ddscaps, &scr.lpBack);
	if(ddrval != DD_OK)
	{
		
		scr.lpFront->Release();
		scr.lpDD->Release();
		return false;
	}
	
	return true;
}

// init sound

bool MasterXHWND::initSound()
{
	HRESULT h;
	
	h = DirectSoundCreate(NULL, &pDS, NULL);
	if (h != DS_OK)
		return FALSE;
	
	HWND hWnd = GetForegroundWindow();
	if (hWnd == NULL)
		hWnd = GetDesktopWindow();
	
	h = pDS->SetCooperativeLevel(hWnd, DSSCL_PRIORITY);
	if (h != DS_OK)
	{	pDS->Release();
	pDS = NULL;
	return FALSE;
	}
	
	IDirectSoundBuffer *lpDsb;
	DSBUFFERDESC		dsbdesc;
	
	memset(&dsbdesc, 0, sizeof(DSBUFFERDESC));
	dsbdesc.dwSize = sizeof(DSBUFFERDESC);
	dsbdesc.dwFlags = DSBCAPS_PRIMARYBUFFER;
	dsbdesc.dwBufferBytes = 0;
	dsbdesc.lpwfxFormat = NULL;
	
	if (pDS->CreateSoundBuffer(&dsbdesc, &lpDsb, NULL) != DS_OK)
	{	pDS->Release();
	pDS = NULL;
	return FALSE;
	}
	lpDsb->Play(0, 0, DSBPLAY_LOOPING);
	
	return TRUE;
}
// Load a Graphic 

bool MasterXHWND::LoadGraphic(MasterGraphic* g,char* filename)
{
	return g->LoadGraphic(filename,&scr);
}
// load 


// Load a Sound

bool MasterXHWND::LoadSound(MasterSound* s,LPCSTR resourceID)
{
	return s->LoadSound(pDS,resourceID);
}
// Check a keystate via DirectInput

bool MasterXHWND::KeyCheck(int key)
{
	BYTE	state[256];
	pKeyboard->GetDeviceState(sizeof(state), &state);

	if(state[key] & 0x80)
	{
		return true;
	}
	else
	{
		return false;
	}
}
// get mouse pos through windows api

void MasterXHWND::GetMousePosWin(long& x, long& y)
{
	POINT point;
	GetCursorPos(&point);
	x = point.x;
	y = point.y;
}

// Check a keystate via Windows

bool MasterXHWND::AsyncKeyCheck(int key)
{
  if(GetAsyncKeyState(key))
  {
	  return true;
  }
  else
  {
	  return false;
  }
}
// create a font, to use with the text object

HFONT MasterXHWND::CreateMasterFont(char* font_name,int size)
{
	// make a font

	return CreateFont(size,0,0,0,FW_DONTCARE,0,0,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,FF_MODERN,font_name);
}
// create timer by, id and interval

void MasterXHWND::InitTimer(int id, int interval)
{
	int addamt = 0; 
#ifdef WIN2K

	addamt += 50;
#endif

	SetTimer(hwnd,id,interval + addamt,NULL);
}
// destroy the timer by id

void MasterXHWND::DestroyTimer(int id)
{
	KillTimer(hwnd,id);
}
// hide the cursor

void MasterXHWND::HideCursor()
{
	ShowCursor(false);
}
// show the cursor

void MasterXHWND::RestoreCursor()
{
	ShowCursor(true);
}
// has time changed?

bool MasterXHWND::TimeChange()
{
	if(pre_time == timer_count)
	{
	return false;
	}
	else
	{
		pre_time = timer_count;
		return true;
	}
}
// change the time

void MasterXHWND::ChangeTime()
{
	timer_count++;

	if(timer_count > 100)
	{
		timer_count = 0;
	}
}
// auto set time change

void MasterXHWND::SetTimeFlag()
{
	time_flag = TimeChange();
}
// insync update

bool MasterXHWND::SyncChange()
{
	return time_flag;
}


/***** Master Text Object *****************************************/
// set the default font back agian & shit

// set the default font

void MasterText::setdefaultfont()
{
	font = CreateFont(13,
        0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE,
        ANSI_CHARSET,
        OUT_DEFAULT_PRECIS,
        CLIP_DEFAULT_PRECIS,
        NONANTIALIASED_QUALITY,
        VARIABLE_PITCH,
        "Arial");
}


//init master text object

void MasterText::init(MasterScreen* x)
{
	
	scr = (MasterScreen*)x;
	font = CreateFont(13,
        0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE,
        ANSI_CHARSET,
        OUT_DEFAULT_PRECIS,
        CLIP_DEFAULT_PRECIS,
        NONANTIALIASED_QUALITY,
        VARIABLE_PITCH,
        "Arial"); //  Create a Stupid Font

	
	underfont = CreateFont(13,
        0, 0, 0, FW_NORMAL, FALSE, TRUE, FALSE,
        ANSI_CHARSET,
        OUT_DEFAULT_PRECIS,
        CLIP_DEFAULT_PRECIS,
        NONANTIALIASED_QUALITY,
        VARIABLE_PITCH,
        "Arial"); //  Create a Stupid Font

	
	bk = TRANSPARENT;
	text = RGB(255,0,0);
	
}
// set the font

void MasterText::setfont(HFONT f)
{
    font = f;
	
}
// set ud

void MasterText::setunderfont(HFONT f)
{
	underfont = f;
}
// set the bg color (RGB)

void MasterText::setbkcolor(COLORREF f)
{
	
	bk = f;
	
}
// set the textcolor

void MasterText::settextcolor(COLORREF f)
{
	
	text = f;
	
}
// print text

void FAST MasterText::printtext(char* strtext, int x, int y)
{
	
	HDC dc;
    scr->lpBack->GetDC(&dc);
	
	SetTextColor(dc,text);
	SetBkColor(dc,bk);
	
	if(font != NULL)
	{
		SelectObject(dc, font);
	}
	
	TextOut(dc,x,y,strtext,strlen(strtext));
	
	scr->lpBack->ReleaseDC(dc);
	
	
	
}

void FAST MasterText::sprinttext(int x, int y, char* str, ...)
{
	va_list list; 
	char string[5000];
	va_start(list, str); 
	vsprintf((char*)string,str,list);
	va_end(list); 
	printtext(string,x,y);
}

// printtextrect stream

void FAST MasterText::printtextrectf(int x, int y, int x2, int y2, char* str, ...)
{
	va_list list; 
	char string[5000];
	va_start(list, str); 
	vsprintf((char*)string,str,list);
	va_end(list); 
	printtextrect(string,x,y,x2,y2);
}

// print formated text within a rectangle

void FAST MasterText::printtextrect(char* strtext, int x, int y, int w, int h)
{
	RECT rt;
	SetRect(&rt,x,y,w,h);
	
	HDC dc;
    scr->lpBack->GetDC(&dc);
	
	SetTextColor(dc,text);
	SetBkColor(dc,bk);
	
	if(font != NULL)
	{
		SelectObject(dc, font);
	}
	
	DrawText(dc,strtext,strlen(strtext),&rt,DT_EDITCONTROL);
	
	scr->lpBack->ReleaseDC(dc);
	
	
	
}
// print text with a underline

void FAST MasterText::printtextunderline(char* strtext, int x, int y)
{
	HDC dc;
    scr->lpBack->GetDC(&dc);
	
	SetTextColor(dc,text);
	SetBkColor(dc,bk);
	
	if(underfont != NULL)
	{
		SelectObject(dc, underfont);
	}
	
	TextOut(dc,x,y,strtext,strlen(strtext));
	
	scr->lpBack->ReleaseDC(dc);
	
}


//************************************* GRAPHIC OBJECT ***************************************/


MasterGraphic::~MasterGraphic()
{
	if(surf != NULL)
	{
		surf->Release();
		surf = NULL;
	}
}

MasterGraphic::MasterGraphic()
{
	ckey = false;
	surf = NULL;
	scr  = NULL;
}
// Release a exisiting MasterX Graphic

void MasterGraphic::Release()
{
	if(surf)
	{
		surf->Release();
	}
}
// Display Graphic ex (display a area of the bitmap)

void MasterGraphic::DisplayGraphicEx(int bx, int by, int bw, int bh,int image_x, int image_y)
{
	HRESULT ddrval;
	RECT     rcRect;

	SetRect(&rcRect,bx,by,bw,bh);

	if(surf)
	{

	if(ckey)
	{
		ddrval= scr->lpBack->BltFast(image_x, image_y, surf,&rcRect, DDBLTFAST_SRCCOLORKEY);

		if(ddrval != DD_OK)
		{
			ReLoadGraphic();
		}
	}
	else
	{
		ddrval = scr->lpBack->BltFast(image_x,image_y,surf,&rcRect,DDBLTFAST_NOCOLORKEY | DDBLTFAST_WAIT);
		if(ddrval != DD_OK)
		{
			ReLoadGraphic();
		}
	}
	}
}


// Display a exisiting MasterX Graphic

void MasterGraphic::DisplayGraphic(int x, int y)
{
	HRESULT ddrval;
	RECT     rcRect;

	SetRect(&rcRect,0,0,w,h);

	if(surf)
	{

	if(ckey)
	{
		ddrval= scr->lpBack->BltFast(x, y, surf,&rcRect, DDBLTFAST_SRCCOLORKEY);

		if(ddrval != DD_OK)
		{
			ReLoadGraphic();
		}
	}
	else
	{

		ddrval = scr->lpBack->BltFast(x,y,surf,&rcRect,DDBLTFAST_NOCOLORKEY | DDBLTFAST_WAIT);
		if(ddrval != DD_OK)
		{
			ReLoadGraphic();
		}
	}
	}
}
// initilize the Screen Data structure

void MasterGraphic::init(MasterScreen* xscr)
{
	scr = xscr;
}
// Load MasterX Graphic

bool MasterGraphic::LoadGraphic(char* filenamex, MasterScreen* scrx)
{
	scr = scrx;
	strcpy(filename,filenamex);
	return LoadGraphic(filename);
}
// Reload the Graphic when Destroyed

void MasterGraphic::ReLoadGraphic()
{
	DDReLoadBitmap(surf,filename);
}
// Load the Graphic, if you already initilized a screen

bool MasterGraphic::LoadGraphic(char* filenamex)
{
	strcpy(filename,filenamex);
	if(scr != NULL)
	{
		surf = DDLoadBitmap(scr->lpDD,filename);
		if(surf) 
		{
			w = MXWIDTH; // from static global

	    	h = MXHEIGHT; // from static global


		return true;

		}
		else
		{
			return false;
		}
	} else
	{
		return false;// no screen initilized

	}
}


// Set a Color key to this graphic

void MasterGraphic::SetColorKey(COLORREF r)
{
	if(surf)
	{

	DDSetColorKey(surf,r);
	ckey = true;
	
	}
}

/* mastergraphic ex by Danny Anderson */


///////////////////////////////////////////////////////////////

//Name: MasterGraphicEx ()

//Info: Constructor just clears ddblyfx variable

//Params: none

//Returns: 0L - failure

//		   else - a pointer to the pixels of this graphic

///////////////////////////////////////////////////////////////

MasterGraphicEx::MasterGraphicEx ()
{
	ZeroMemory (&m_ddbltfx, sizeof (m_ddbltfx));
	m_ddbltfx.dwSize = sizeof (m_ddbltfx);
	color_key = RGB (0, 0, 0);
}

///////////////////////////////////////////////////////////////

//Name: generic_draw ()

//Info: Basically uses Blt () to display the surface

//Params: x, y - position

//			dest_w, dest_h - new size of graphic (for scaling)

//			blt_flags - flags for Blt function

//Returns: none

///////////////////////////////////////////////////////////////


void MasterGraphicEx::generic_draw (const int x, const int y, 
									const int dest_w, const int dest_h, 
									DWORD blt_flags)
{
	DWORD flags = DDBLT_WAIT | blt_flags;
	
	//add color key flag if necessary

	if (ckey)
	{
		flags|=DDBLT_KEYSRC; 
	}

	RECT dest, source;
	//rect of image

	source.left=0;
	source.top=0;
	source.right=w;
	source.bottom=h;

	//destination rect

	dest.left = x;
	dest.top = y;
	dest.right = x + dest_w;
	dest.bottom = y + dest_h;

	if (surf)
	{
	//blit the surface to the screen (it will scale automatically)

	HRESULT ddrval= scr->lpBack->Blt(&dest, surf, &source, flags, &m_ddbltfx);
	
	//if there is a problem, reload the graphic

	if(ddrval != DD_OK)
	{
		ReLoadGraphic();
	}
	}
}

///////////////////////////////////////////////////////////////

//Name: generic_draw_clip ()

//Info: Basically uses Blt () to display the surface but

//		also adds support for clipping

//Params: x, y - position

//			dest_w, dest_h - new size of graphic (for scaling)

//			clip_rect - clips graphic to this rect

//			blt_flags - flags for Blt function

//Returns: none

///////////////////////////////////////////////////////////////


void MasterGraphicEx::generic_draw_clip (const int x, const int y, 
										 const int dest_w, const int dest_h, 
										 const RECT* clip_rect, 
										 DWORD blt_flags)
{

	DWORD flags = DDBLT_WAIT | blt_flags;

	//add flages for colorkey

	if (ckey)
	{
		flags|=DDBLT_KEYSRC; 
	}

	RECT dest, source;

	//image rect

	source.left=0;
	source.top=0;
	source.right=w;
	source.bottom=h;
	
	//destination rect

	dest.left = x;
	dest.top = y;
	dest.right = x + dest_w;
	dest.bottom = y + dest_h;

	//this is basic clipping math...

	if (dest.left < clip_rect->left)
	{
		source.left = clip_rect->left-dest.left;
		dest.left = clip_rect->left;
	}

	if (dest.top < clip_rect->top)
	{
		source.top = clip_rect->top-dest.top;
		dest.top = clip_rect->top;
	}

	if (dest.right > clip_rect->right)
	{
		source.right -= dest.right-clip_rect->right;
		
		dest.right = clip_rect->right;
	}

	if (dest.bottom > clip_rect->bottom)
	{
		source.bottom -= dest.bottom-clip_rect->bottom;
		dest.bottom = clip_rect->bottom;
	}

	// Out of clipping borders

	if (dest.right<dest.left || dest.bottom<dest.top) return; 

	if (surf)
	{
	//now we are ready to Blt...

	HRESULT ddrval = scr->lpBack->Blt(&dest, surf, &source, flags, &m_ddbltfx);
	
	if(ddrval != DD_OK)
	{
		ReLoadGraphic();
	}
	}
}

///////////////////////////////////////////////////////////////

//Name: filter ()

//Info: Applies various filters to an RGB value.

//Params: type - type of filter

//			r - assigns new red value to this param

//			g - "		"	green	"	"	"   "

//			b - "		'	blue	"	"	"	"

//			amount - some filters have different intensities (range 0-1)

//Returns: applies a filter of type to r, g, b. On failure, r, g, b stay 

//			the same

///////////////////////////////////////////////////////////////

void MasterGraphicEx::filter (const int type, int& r, int& g, int& b, const float r_amount, const float g_amount, const float b_amount)
{
	switch (type)
	{
	//grayscale

	case GRAYSCALE:
		{
			//just average the 3 rgb values

			int s = (r + g + b) / 3;
			r = g = b = s;
		}
		break;

	//darken

	case DARKEN:
		{
			//darken each rgb value

			r = (int)((1.0f - r_amount)*r);
			g = (int)((1.0f - g_amount)*g);
			b = (int)((1.0f - b_amount)*b);
		}
		break;

	//brighten

	case BRIGHTEN:
		{
			//brighten each rgb value

			r = (int)(r + r_amount*(float)(255-r));
			g = (int)(g + g_amount*(float)(255-g));
			b = (int)(b + b_amount*(float)(255-b));
		}
		break;
	
	//complement (inverting colors)

	case COMPLEMENT:
		{
			//invert each rgb value

			r = 255 - r;
			g = 255 - g;
			b = 255 - b;
		}
		break;

	//color balance (basically, controls the brighten/darken for each

	// rgb component

	case BALANCE:
		{
			if (r_amount < 0)
			{
				r = (int)((1.0f - r_amount)*r);
			}
			else
			{
				r = (int)(r + r_amount*(float)(255-r));
			}

			if (g_amount < 0)
			{
				g = (int)((1.0f - g_amount)*g);
			}
			else
			{
				g = (int)(g + g_amount*(float)(255-g));
			}

			if (b_amount < 0)
			{
				b = (int)((1.0f - b_amount)*b);
			}
			else
			{
				b = (int)(b + b_amount*(float)(255-b));
			}
		}
		break;

	}
}

///////////////////////////////////////////////////////////////

//Name: apply_filter_to_pixels ()

//Info: This does all the work for the filters. It gets the pixels

//	from the surface. Then it gets the bits per pixel of the current

//	DirectDraw environment. It goes through each pixel, ripping

//	the rgb components. Next, it applies the filter and rebuilds

//	the pixel. Calling ReLoadImage will restore the surface to its

//	original state.

//Params:	type - filter type

//			r_amount, g_amount, b_amount - amount of intensity of filter

//Returns: none

///////////////////////////////////////////////////////////////


void MasterGraphicEx::apply_filter_to_pixels (const int type, const float r_amount, const float g_amount, const float b_amount)
{
	//check for a valid surface before we do anything

	if (surf == 0L)
	{
		//check surf->IsLost () also would be a good idea!

		return;
	}
	//get the bit count

	int bit_count = get_bit_count ();
	//amount of bytes between end of scanline and start of next

	int pitch;
	//temporary place holders for color information

	int r, g, b, a;

	//temporary position variable

	int x;
	//verify the bit count

	if (bit_count == -1)
	{
		return;
	}
	
	//get the pixels of this graphic

	DDSURFACEDESC surface_desc = get_surface_desc ();

	//verify we have any pixels at all

	if (surface_desc.lpSurface == 0L)
	{
		return;
	}


	//i only support 15, 16, 24 & 32 bit conversions

	switch (bit_count)
	{
		////////////////////////////////////////////////////////////////

		//15/16 bit case:

		//This is a nice bit pattern to work with, small (2 bytes) and

		//it has good color. Basically, we rip the color, apply filter

		//and reassemble image. The 15/16 pixel reading is a little 

		//buggy (not comparing color keys properly and reading pixels

		// a little off)

		///////////////////////////////////////////////////////////////

		case 15:
		{
			//get pixels from surface

			unsigned short* pixels_2_bytes = 
				(unsigned short*)surface_desc.lpSurface;
			
			//get extra bytes

			pitch = surface_desc.lPitch - w*2;
			//convert bytest to pixels

			pitch /= 2;
			
			//go through pixel by pixel

			for (int i = 0; i < h; i++)
			{
				//go to beginning of next line

				x = i*w + i*pitch;

				for (int j = 0; j < w; j++)
				{
				//extract color (we are ORing with 7 for a higher intensity

				//conversion

				r = ((pixels_2_bytes[x + j]>>10)&BIT_5_MASK)<<3;
				if (r)
					r |= 0x7;
				g = ((pixels_2_bytes[x + j]>>5)&BIT_5_MASK)<<3;
				if (g)
					g |= 0x7;
				b = (pixels_2_bytes[x + j]&BIT_5_MASK)<<3;
				if (b)
					b |= 0x7;

				//dont apply the color filter to the transparent color

				if (!ckey || (RGB (r, g, b) != (color_key)))
				{		
					//apply filter

					filter (type, r, g, b, r_amount, g_amount, b_amount);
					//rebuild pixel

					pixels_2_bytes[x + j] = (unsigned short) (((r&0xF8)<<7) | ((g&0xF8)<<2) | (b>>3));
				}
				}
			}
		}
		break;

		case 16:
		{
			//get extra bytes

			pitch = surface_desc.lPitch - w*2;
			//convert bytest to pixels

			pitch /= 2;
			
			//get pixels from surface

			unsigned short* pixels_2_bytes = 
				(unsigned short*)surface_desc.lpSurface;

			for (int i = 0; i < h; i++)
			{
				//get beginning position of scanline

				x = i*w + i*pitch;
				for (int j = 0; j < w; j++)
				{
					
					//extract colors

					r = ((pixels_2_bytes[x + j]>>11)&BIT_5_MASK)<<3;
					if (r)
						r |= 7;
					g = ((pixels_2_bytes[x + j]>>5)&BIT_6_MASK)<<2;
					if (g)
						g |= 7;
					b = (pixels_2_bytes[x + j]&BIT_5_MASK)<<3;
					if (b)
						b |= 7;

					if (!ckey || (RGB (r, g, b) != (color_key)))
					{
					filter (type, r, g, b, r_amount, g_amount, b_amount);

					//rebuild pixel

					pixels_2_bytes[x + j] = (unsigned short) (((r&0xF8)<<8) | ((g&0xF8)<<3) | (b>>3));
					}
			
				}
			}


		}
		break;

		////////////////////////////////////////////////////////////////

		//24 bit case:

		//This is usually the worst one to deal with because 24 bit 

		//color is stored as 3 bytes, too big for a short, too small 

		//for an int. In addition, as a 24 bit DirectDraw surface,

		//there are 8 (DDSURFACE->lPitch / 2) bytes appended to each

		//image scanline. So we have to skip operation on these unused

		//bytes. Note, there can be optimizations here, this was a 

		//first attempt

		///////////////////////////////////////////////////////////////

		
		case 24:
		{

			//cast surface_pixels as a byte array

			unsigned char* pixels_1_byte 
				= (unsigned char*)surface_desc.lpSurface;

			//this formula took a while to figure out,

			//but it works (pitch is the amount of bytes

			//from the end a scanline, to the beginning

			//of the next

			pitch = surface_desc.lPitch - 3*w;


			//cycle through the byte array, 3(rgb) at a time

			
			//go 1 scanline at a time

			for (int i = 0; i < h; i++)
			{
				//go through each 3 byte pixel of the scanline

				//WARNING: there is extra crap appended to each

				//scanline and we cant apply the filter to those!

				
				x = (i*3*w) + (i*pitch);

				for (int j = 0; j < (w*3); j+=3)
				{
				//get current position in pixel array

				//pitch is the amount of extra bytes 

				//3*w is the width of actual image in bytes

				//j is the position in current line


				
				//get rgb values

				r = pixels_1_byte[x + j];
				g = pixels_1_byte[x + j + 1];
				b = pixels_1_byte[x + j + 2];
				
				if (!ckey || (RGB (r, g, b) != color_key))
				{				
				//apply filter

				filter (type, r, g, b, r_amount, g_amount, b_amount);

				//reassign the rgb values

				pixels_1_byte[x + j]= r;
				pixels_1_byte[x + j + 1] = g;
				pixels_1_byte[x + j + 2] = b;
				}
				}

			}

		}
		break;

		////////////////////////////////////////////////////////////////

		//32 bit case:

		//32 bit color is stored as 4 bytes, so it fits into an int.

		//In 32 bit, I read the pixel then extract the ARGB color components

		//from it. (a is the alpha channel, for translucency). Then, I apply

		//the filter and recreate the pixel. I am preserving the original

		//a value and not applying it to the filter.

		///////////////////////////////////////////////////////////////


		case 32:
		{

			char d[100];
			wsprintf (d, "pitch: %i\n", surface_desc.lPitch);
			OutputDebugString (d);
			
			//get extra bytes at end of line

			pitch = surface_desc.lPitch - (w*4);
			//convert bytes to pixels

			pitch /= 4;

			//4 bytes per pixel

			unsigned int* pixels_4_bytes = (unsigned int*)surface_desc.lpSurface;
			//go to each pixel

			for (int i = 0; i < h; i++)
			{	
				x = (i*w) + (i*pitch);
				for (int j = 0; j < w; j++)
				{

					//get color components

					a = pixels_4_bytes[x + j]>>24;
					r = (pixels_4_bytes[x + j]>>16)&BIT_8_MASK;
					g = (pixels_4_bytes[x + j]>>8)&BIT_8_MASK;
					b = pixels_4_bytes[x + j]&BIT_8_MASK;

					if (!ckey || (RGB (r, g, b) != color_key))
					{
					//apply filter

					filter (type, r, g, b, r_amount, g_amount, b_amount);

					//construct pixel and assign it to array

					pixels_4_bytes[x + j] = (unsigned int)((a<<24) | (r<<16) | ((g) << 8) | b);
					}
				}
			}

		}
		break;

	}


}

///////////////////////////////////////////////////////////////

//Name: get_bit_count ()

//Info: This method attempts to get a point to the pixels

//		of this graphic's DirectDraw Surface. This is a pointer

//		right to the video memory. Reading/Writing to video

//		memory is very slow. But, these filters are intended to

//		be applied only once to the graphic.

//Params: none

//Returns: -1 - failure

//		   15, 16, 24, 32 - bits per pixel of the DirectDraw environment

///////////////////////////////////////////////////////////////

int MasterGraphicEx::get_bit_count ()
{
	int bit_count;
	DDSURFACEDESC ddsd;
	ddsd.dwSize = sizeof (ddsd);

	//get display mode, I am using the DirectDraw object 

	//rather than the surface on purpose (they both should be the same)

	scr->lpDD->GetDisplayMode (&ddsd);
	//get the bit count

	bit_count = ddsd.ddpfPixelFormat.dwRGBBitCount;

	if (bit_count == 16)
	{
		//find out which 16 bit we have (5x5x5 or 5x6x5)

		if (ddsd.ddpfPixelFormat.dwGBitMask == (BIT_5_MASK<<5))
		{
			bit_count = 15;
		}
		else if (ddsd.ddpfPixelFormat.dwGBitMask == (BIT_6_MASK<<5))
		{
			bit_count = 16;
		}		
	}
	//we only support 15, 16, 24 & 32

	else if ((bit_count != 24) && (bit_count != 32))
	{
		bit_count = -1;
	}

	return bit_count;
}

///////////////////////////////////////////////////////////////

//Name: get_surface_pixels ()

//Info: This method attempts to get a point to the pixels

//		of this graphic's DirectDraw Surface. This is a pointer

//		right to the video memory. Reading/Writing to video

//		memory is very slow. But, these filters are intended to

//		be applied only once to the graphic.

//Params: none

//Returns: 0L - failure

//		   else - a pointer to the pixels of this graphic

///////////////////////////////////////////////////////////////

DDSURFACEDESC MasterGraphicEx::get_surface_desc ()
{
	DDSURFACEDESC OffSurfaceDescription;
	HRESULT rval;	

	//clear the offsurface description structure

	ZeroMemory (&OffSurfaceDescription, sizeof (OffSurfaceDescription));
	OffSurfaceDescription.dwSize = sizeof (OffSurfaceDescription);
	
	//get the surface description

	rval = surf->Lock (NULL,&OffSurfaceDescription,
											DDLOCK_SURFACEMEMORYPTR, NULL);
	
	
	//check if lock did its job

	if (rval != DD_OK)
	{
		//we have a problem, return NULL

		ZeroMemory (&OffSurfaceDescription, sizeof (OffSurfaceDescription));
	}


	//unlock the surface, or DX will crash

	surf->Unlock (0L);

	return (OffSurfaceDescription);
}

///////////////////////////////////////////////////////////////

//Name: constrain_amount ()

//Info: Constrains amount to the range low to high

//Params: amount - changes amount to the specified range

//			low - floor of range

//			high - ceiling of range

//Returns: none

///////////////////////////////////////////////////////////////


void MasterGraphicEx::constrain_amount (float& amount, const float low, const float high)
{
	if (amount < low)
	{
		amount = low;
	}

	if (amount > high)
	{
		amount = high;
	}
}

void MasterGraphicEx::SetColorKey (COLORREF r)
{
	color_key = r;
	MasterGraphic::SetColorKey (color_key);
}

///////////////////////////////////////////////////////////////

//Client interface for drawing methods

///////////////////////////////////////////////////////////////


void MasterGraphicEx::DisplayGraphic_draw (const int x, const int y)
{
	generic_draw (x, y, w, h, 0);
}

void MasterGraphicEx::DisplayGraphic_clip (const int x, const int y, 
										   const RECT* clip_rect)
{
	generic_draw_clip (x, y, w, h, clip_rect, 0);
}

void MasterGraphicEx::DisplayGraphic_scale (const int x, const int y, 
											const int dest_w, const int dest_h)
{

	generic_draw (x, y, dest_w, dest_h, 0);
}

void MasterGraphicEx::DisplayGraphic_flip (const int x, const int y, 
										   const bool horizontal)
{
	m_ddbltfx.dwDDFX = horizontal?DDBLTFX_MIRRORLEFTRIGHT:DDBLTFX_MIRRORUPDOWN;

	generic_draw (x, y, w, h, DDBLT_DDFX);
}

//it turns out that scaling and clipping requires a little 

//extra math... =(

void MasterGraphicEx::DisplayGraphic_scale_clip (const int x, const int y, const int dest_w, const int dest_h, const RECT* clip_rect)
{

	DWORD flags = DDBLT_WAIT;

	//flag for color key

	if (ckey)
	{
		flags|=DDBLT_KEYSRC; 
	}

	RECT dest, source;

	//image rect

	source.left=0;
	source.top=0;
	source.right=w;
	source.bottom=h;

	//destination rect

	dest.left = x;
	dest.top = y;
	dest.right = x + dest_w;
	dest.bottom = y + dest_h;

	//scaling and clipping math ... 

	float dx = float(w)/dest_w;
	float dy = float(h)/dest_h;

	if (dest.left < clip_rect->left)
	{
		source.left = int((clip_rect->left-dest.left)*dx+0.5);
		dest.left = clip_rect->left;
	}

	if (dest.top < clip_rect->top)
	{
		source.top = int((clip_rect->top-dest.top)*dy+0.5);
		dest.top = clip_rect->top;
	}

	if (dest.right > clip_rect->right)
	{
		source.right -= int((dest.right-clip_rect->right)*dx+0.5);
		dest.right = clip_rect->right;
	}

	if (dest.bottom > clip_rect->bottom)
	{
		source.bottom -= int((dest.bottom-clip_rect->bottom)*dy+0.5);
		dest.bottom = clip_rect->bottom;
	}

	if (dest.right<dest.left || dest.bottom<dest.top) return; // Out of clipping borders


	if (surf)
	{
	//Blt to screen

	HRESULT ddrval= scr->lpBack->Blt(&dest, surf, &source, flags, &m_ddbltfx);

	if(ddrval != DD_OK)
	{
		ReLoadGraphic();
	}
	}
}

void MasterGraphicEx::DisplayGraphic_flip_clip (const int x, const int y, const bool horizontal, const RECT* clip_rect)
{

	m_ddbltfx.dwDDFX = horizontal?DDBLTFX_MIRRORLEFTRIGHT:DDBLTFX_MIRRORUPDOWN;

	generic_draw_clip (x, y, w, h, clip_rect, DDBLT_DDFX);
}

///////////////////////////////////////////////////////////////

//Client interfaces to filters (self expanatory)

///////////////////////////////////////////////////////////////

void MasterGraphicEx::apply_grayscale ()
{
	apply_filter_to_pixels (GRAYSCALE);
}

void MasterGraphicEx::apply_complement ()
{
	apply_filter_to_pixels (COMPLEMENT);
}

void MasterGraphicEx::apply_brighten (float amount)
{
	constrain_amount (amount, 0.0f, 1.0f);
	apply_filter_to_pixels (BRIGHTEN, amount, amount, amount);
}

void MasterGraphicEx::apply_darken (float amount)
{	
	constrain_amount (amount, 0.0f, 1.0f);
	apply_filter_to_pixels (DARKEN, amount, amount, amount);
}

void MasterGraphicEx::apply_balance (float r_amount, float g_amount, float b_amount)
{
	constrain_amount (r_amount, -1.0f, 1.0f);
	constrain_amount (g_amount, -1.0f, 1.0f);
	constrain_amount (b_amount, -1.0f, 1.0f);

	apply_filter_to_pixels (BALANCE, r_amount, g_amount, b_amount);
}
/* end of danny's code */




/***************************** THE PAITNING OBJECT ******************************************/
// initlize the MasterPaint

void MasterPaint::init(MasterScreen* xscr)
{
	scr = xscr;
}
// set a pixel

void FAST MasterPaint::mxsetpixel(int x, int y, COLORREF rgbval)
{
	HDC dc;
	scr->lpBack->GetDC(&dc);
	SetPixel(dc, x, y, rgbval);  
	scr->lpBack->ReleaseDC(dc);
}
// draw a vertical line

void FAST MasterPaint::mxverticalline(int y1,int y2,int x,COLORREF color)
{
	HDC dc;
	scr->lpBack->GetDC(&dc);
	for(int i = y1; i <=y2; i++)
	{

	SetPixel(dc, x, i, color);
	
	}
	scr->lpBack->ReleaseDC(dc);
}
// draw a horizontal line

void FAST MasterPaint::mxhorizontalline(int x1, int x2, int y,COLORREF color)
{
	HDC dc;
	scr->lpBack->GetDC(&dc);
	for(int i = x2; i>=x1; i--)
	{

	SetPixel(dc, i, y, color);
	
	}
	scr->lpBack->ReleaseDC(dc);
}
// draw a line from any 2 points, algorithm orignaly written by

// Bresenham, in 1950

void FAST MasterPaint::mxline(int start_x,int start_y,int stop_x, int stop_y,COLORREF color)
{
	int y_unit,x_unit;
	int ydiff = stop_y-start_y;
	if(ydiff<0)
	{
		ydiff = ydiff;
		y_unit=-1;
	}
	else
	{
		y_unit =1;
	}
	int xdiff=stop_x-start_x;
	if(xdiff<0)
	{
		xdiff=-xdiff;
		x_unit = -1;
	}
	else
	{
		x_unit = 1;
	}

	// drawing


	HDC dc;
	scr->lpBack->GetDC(&dc);


	int error_term=0;
	if(xdiff>ydiff)
	{
		int length=xdiff+1;
		for(int i = 0; i <length; i++)
		{
			SetPixel(dc,start_x,start_y,color);
			start_x += x_unit;
			error_term+=ydiff;
			if(error_term>xdiff)
			{
				error_term-=xdiff;
				start_y+=y_unit;
			}
		}
	}
	else
	{
		int length = ydiff+1;
		for(int i = 0; i < length; i++)
		{
			SetPixel(dc,start_x,start_y,color);
			start_y += y_unit;
			error_term+=xdiff;
			if(error_term>0)
			{
				error_term-=ydiff;
				start_x += x_unit;
			}

		}
	}

	scr->lpBack->ReleaseDC(dc);
}

// get the color of a pixel

COLORREF FAST MasterPaint::mxgetpixel(int x, int y)
{
	COLORREF rgbval;
	HDC dc;
	scr->lpBack->GetDC(&dc);
	rgbval = GetPixel(dc, x, y);     // Save current pixel value

	scr->lpBack->ReleaseDC(dc);
	return rgbval;
}

// draw an arc

void FAST MasterPaint::mxarc(int x1, int x2, int x3, int x4,int x5, int x6,int x7, int x8,COLORREF fill,COLORREF outline)
{
	
	HDC dc;
	scr->lpBack->GetDC(&dc);
	
	   HBRUSH hNewBrush,hOldBrush;
	   HPEN hNewPen,hOldPen; 
	   
	   hNewBrush = (HBRUSH)CreateSolidBrush(fill);
	   hOldBrush = (HBRUSH)SelectObject(dc,(HBRUSH)hNewBrush); // set this brush and get the old brush

	   
	   hNewPen = CreatePen(PS_SOLID,2,outline); // create this pen

	   hOldPen= (HPEN__*)SelectObject(dc,(HPEN__*)hNewPen); // set this pen and  get the old one

	   
	   Arc(dc,x1,x2,x3,x4,x5,x6,x7,x8);
	   
	   SelectObject(dc,hOldPen);
	   SelectObject(dc,hOldBrush);
	   
	   DeleteObject(hNewBrush); 
	   DeleteObject(hNewPen); 
	   scr->lpBack->ReleaseDC(dc);
}

// draw a line

void FAST MasterPaint::mxlineto(int x, int y,COLORREF fill,COLORREF outline)
{
	
	HDC dc;
	scr->lpBack->GetDC(&dc);
	
    HBRUSH hNewBrush,hOldBrush;
    HPEN hNewPen,hOldPen; 
	   
    hNewBrush = (HBRUSH)CreateSolidBrush(fill);
    hOldBrush = (HBRUSH)SelectObject(dc,(HBRUSH)hNewBrush); // set this brush and get the old brush

	   
    hNewPen = CreatePen(PS_SOLID,2,outline); // create this pen

    hOldPen= (HPEN__*)SelectObject(dc,(HPEN__*)hNewPen); // set this pen and  get the old one

	   
	LineTo(dc,x,y);
	   
	SelectObject(dc,hOldPen);
	SelectObject(dc,hOldBrush);
	  
	DeleteObject(hNewBrush); 
	DeleteObject(hNewPen); 
	scr->lpBack->ReleaseDC(dc);
}

// draw a angle arc

void FAST MasterPaint::mxanglearc(int x, int y, long radius, float startangle,float sweepangle,COLORREF outline)
{
	HDC dc;
	scr->lpBack->GetDC(&dc);
	
    HBRUSH hNewBrush,hOldBrush;
    HPEN hNewPen,hOldPen; 
	COLORREF fill = RGB(0,0,0); // null colored brush

    hNewBrush = (HBRUSH)CreateSolidBrush(fill);
    hOldBrush = (HBRUSH)SelectObject(dc,(HBRUSH)hNewBrush); // set this brush and get the old brush

	   
    hNewPen = CreatePen(PS_SOLID,2,outline); // create this pen

    hOldPen= (HPEN__*)SelectObject(dc,(HPEN__*)hNewPen); // set this pen and  get the old one

	   
	AngleArc(dc,x,y,radius,startangle,sweepangle);
	   
	SelectObject(dc,hOldPen);
	SelectObject(dc,hOldBrush);
	  
	DeleteObject(hNewBrush); 
	DeleteObject(hNewPen); 
	scr->lpBack->ReleaseDC(dc);
}

// draw a polygon

void FAST MasterPaint::mxpolygon(CONST POINT* point,int n_points,COLORREF fill,COLORREF outline)
{
	HDC dc;
	scr->lpBack->GetDC(&dc);
	
	   HBRUSH hNewBrush,hOldBrush;
	   HPEN hNewPen,hOldPen; 
	   
	   hNewBrush = (HBRUSH)CreateSolidBrush(fill);
	   hOldBrush = (HBRUSH)SelectObject(dc,(HBRUSH)hNewBrush); // set this brush and get the old brush

	   
	   hNewPen = CreatePen(PS_SOLID,2,outline); // create this pen

	   hOldPen= (HPEN__*)SelectObject(dc,(HPEN__*)hNewPen); // set this pen and  get the old one

	   
	   Polygon(dc,point,n_points);
	   
	   SelectObject(dc,hOldPen);
	   SelectObject(dc,hOldBrush);
	   
	   DeleteObject(hNewBrush); 
	   DeleteObject(hNewPen); 
	   scr->lpBack->ReleaseDC(dc);
}


// Draw a Rectangle

void FAST MasterPaint::mxdrawrect(int x, int y, int xx, int yy, COLORREF fill, COLORREF outline)
{
	HDC dc;
	scr->lpBack->GetDC(&dc);
	
	   HBRUSH hNewBrush,hOldBrush;
	   HPEN hNewPen,hOldPen; 
	   
	   hNewBrush = (HBRUSH)CreateSolidBrush(fill);
	   hOldBrush = (HBRUSH)SelectObject(dc,(HBRUSH)hNewBrush); // set this brush and get the old brush

	   
	   hNewPen = CreatePen(PS_SOLID,2,outline); // create this pen

	   hOldPen= (HPEN__*)SelectObject(dc,(HPEN__*)hNewPen); // set this pen and  get the old one

	   
	   Rectangle(dc,x,y,xx,yy); // Draw a rectangle

	   
	   SelectObject(dc,hOldPen);
	   SelectObject(dc,hOldBrush);
	   
	   DeleteObject(hNewBrush); 
	   DeleteObject(hNewPen); 
	   scr->lpBack->ReleaseDC(dc);
}
// Draw a rectangle

void FAST MasterPaint::mxdrawroundrect(int x, int y, int x2, int y2, int cw, int ch, COLORREF fill,COLORREF outline)
{
	HDC dc;
	scr->lpBack->GetDC(&dc);
	
	HBRUSH hNewBrush,hOldBrush;// new Brush to paint with and one thats current (so we can restore)

	   HPEN hNewPen,hOldPen; // New pen to paint with and the current (so we can restore)

	   
	   hNewBrush = (HBRUSH)CreateSolidBrush(fill); // create this brush

	   hOldBrush = (HBRUSH)SelectObject(dc,(HBRUSH)hNewBrush); // set this brush and get the old brush

	   
	   hNewPen = CreatePen(PS_SOLID,2,outline); // create this pen

	   hOldPen= (HPEN__*)SelectObject(dc,(HPEN__*)hNewPen); // set this pen and  get the old one

	   
	   
	   RoundRect(dc,x,y,x2,y2,cw,ch);
	   
	   
	   SelectObject(dc,hOldPen);
	   SelectObject(dc,hOldBrush);
	   
	   DeleteObject(hNewBrush);
	   DeleteObject(hNewPen); // i dont need this sso lets KILL It

	   scr->lpBack->ReleaseDC(dc);
}
// draw a circle (pie)

void FAST MasterPaint::mxdrawpie(int x, int y, int x2, int y2, int nx, int ny, int nx2, int ny2, COLORREF fill,COLORREF outline)
{
	HDC dc;
	scr->lpBack->GetDC(&dc);
	
	HBRUSH hNewBrush,hOldBrush;// new Brush to paint with and one thats current (so we can restore)

	   HPEN hNewPen,hOldPen; // New pen to paint with and the current (so we can restore)

	   
	   hNewBrush = (HBRUSH)CreateSolidBrush(fill); // create this brush

	   hOldBrush = (HBRUSH)SelectObject(dc,(HBRUSH)hNewBrush); // set this brush and get the old brush

	   
	   hNewPen = CreatePen(PS_SOLID,2,outline); // create this pen

	   hOldPen= (HPEN__*)SelectObject(dc,(HPEN__*)hNewPen); // set this pen and  get the old one

	   
	   
	   Pie(dc,x,y,x2,y2,nx,ny,nx2,ny2);
	   
	   SelectObject(dc,hOldPen);
	   SelectObject(dc,hOldBrush);
	   
	   DeleteObject(hNewBrush); 
	   DeleteObject(hNewPen); 
	   scr->lpBack->ReleaseDC(dc);
}
// draw chord

void FAST MasterPaint::mxdrawchord(int x, int y, int x2, int y2, int nx, int ny, int nx2, int ny2,COLORREF fill,COLORREF outline)
{
	   HDC dc;
	   scr->lpBack->GetDC(&dc);
	   
       HBRUSH hNewBrush,hOldBrush;// new Brush to paint with and one thats current (so we can restore)

	   HPEN hNewPen,hOldPen; // New pen to paint with and the current (so we can restore)

	   
	   hNewBrush = (HBRUSH)CreateSolidBrush(fill); // create this brush

	   hOldBrush = (HBRUSH)SelectObject(dc,(HBRUSH)hNewBrush); // set this brush and get the old brush

	   
	   hNewPen = CreatePen(PS_SOLID,2,outline); // create this pen

	   hOldPen= (HPEN__*)SelectObject(dc,(HPEN__*)hNewPen); // set this pen and  get the old one

	   
	   Chord(dc,x,y,x2,y2,nx,ny,nx2,ny2);
	   
	   SelectObject(dc,hOldPen);
	   SelectObject(dc,hOldBrush);
	   
	   DeleteObject(hNewBrush); 
	   DeleteObject(hNewPen);
	   scr->lpBack->ReleaseDC(dc);
}
// draw ellipse

void FAST MasterPaint::mxdrawellipse(int x, int y, int x2, int y2,COLORREF fill,COLORREF outline)
{
	   HDC dc;
	   scr->lpBack->GetDC(&dc);
	   
       HBRUSH hNewBrush,hOldBrush;// new Brush to paint with and one thats current (so we can restore)

	   HPEN hNewPen,hOldPen; // New pen to paint with and the current (so we can restore)

	   
	   hNewBrush = (HBRUSH)CreateSolidBrush(fill); // create this brush

	   hOldBrush = (HBRUSH)SelectObject(dc,(HBRUSH)hNewBrush); // set this brush and get the old brush

	   
	   hNewPen = CreatePen(PS_SOLID,2,outline); // create this pen

	   hOldPen= (HPEN__*)SelectObject(dc,(HPEN__*)hNewPen); // set this pen and  get the old one

	   
	   Ellipse(dc,x,y,x2,y2);
	   
	   
	   
	   SelectObject(dc,hOldPen);
	   SelectObject(dc,hOldBrush);
	   
	   DeleteObject(hNewBrush); 
	   DeleteObject(hNewPen); 
	   scr->lpBack->ReleaseDC(dc);
}

//*********************** MASTER SOUND OBJECT ***********************************************/


MasterSound::MasterSound()
{
	pSound = NULL;
}

MasterSound::~MasterSound()
{
	if(sound_ok)
	{

	if(pSound)
	{
		pSound->Release();
	}

	}
}

// Load a Sound

bool MasterSound::LoadSound(IDirectSound *pds,LPCSTR name)
{
	if(sound_ok)
	{


	pSound = DSLoadSoundBuffer(pds,name);

	if(pSound)
	{
		return true;
	}
	else
	{
		return false;
	}

	}

	return false;
}
// Play the Sound

void MasterSound::Play()
{
	if(sound_ok)
	{


	if(pSound)
	{
		pSound->Play(0,0,0);
	}

	}
}
// Play status of Sound (is it Playing?)

bool MasterSound::PlayStatus()
{
	if(sound_ok) {
   DWORD status;
   pSound->GetStatus(&status);

	  if(status & DSBSTATUS_PLAYING)
	  { 
		  return true;
	  } 
	  else 
	  {
		  return false;
	  }
		
	  return false;

	}

	else {


		return false;
	}
}

void MasterSound::Release()
{
	if(pSound)
	{
		pSound->Release();
	}
}


//************** NON CLASS RELATED FUNCTION **************************************************/

// DirectDraw Load Bitmap (to surface)

IDirectDrawSurface* DDLoadBitmap(IDirectDraw* pdd, LPCSTR szBitmap)
{
	 
	HBITMAP hbm;
	BITMAP bm;
	IDirectDrawSurface *pdds;
	
	// Load Image for loading from Disk

	
	hbm = (HBITMAP)LoadImage(NULL, szBitmap, IMAGE_BITMAP,0,0,LR_LOADFROMFILE | LR_CREATEDIBSECTION);
	
	
	
	if(hbm == NULL) { return NULL; }
	
	GetObject(hbm, sizeof(bm), &bm); // size

	
	
	// Create Surface for this Bitmap

	
	int cw = bm.bmWidth;
	int ch = bm.bmHeight;

	MXWIDTH = cw;
	MXHEIGHT = ch;

	
	pdds = CreateOffScreenSurface(pdd, bm.bmWidth,bm.bmHeight);
	
	if(pdds)
	{
		
		DDCopyBitmap(pdds, hbm, bm.bmWidth,bm.bmHeight);
	}
	
	
	DeleteObject(hbm);
	
	return pdds;
	
}

mxbitmap DDLoadBitmapX(IDirectDraw* pdd, LPCSTR szBitmap)
{
	
	HBITMAP hbm;
	BITMAP bm;
	IDirectDrawSurface *pdds;
	
	// Load Image for loading from Disk

	
	hbm = (HBITMAP)LoadImage(NULL, szBitmap, IMAGE_BITMAP,0,0,LR_LOADFROMFILE | LR_CREATEDIBSECTION);
	
	mxbitmap xbm;
	

	
	if(hbm == NULL) { xbm.surf = NULL; return xbm; }
	
	GetObject(hbm, sizeof(bm), &bm); // size

	
	
	// Create Surface for this Bitmap

	
	int cw = bm.bmWidth;
	int ch = bm.bmHeight;
	
	pdds = CreateOffScreenSurface(pdd, bm.bmWidth,bm.bmHeight);
	
	if(pdds)
	{
		
		DDCopyBitmap(pdds, hbm, bm.bmWidth,bm.bmHeight);
	}
	
	
	DeleteObject(hbm);
	
	xbm.surf = pdds;
	xbm.w = cw;
	xbm.h = ch;

	return xbm;
	
}
// this is a surface when can be cliped 

IDirectDrawSurface* CreateOffScreenSurface(IDirectDraw* pdd, int dx, int dy)
{
	
	DDSURFACEDESC ddsd;
	IDirectDrawSurface* pdds;
	
	// Create Surface for this bitmap

	
	ZeroMemory(&ddsd,sizeof(ddsd));
	ddsd.dwSize = sizeof(ddsd);
	ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
	ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
	ddsd.dwWidth = dx;
	ddsd.dwHeight = dy;
	
	if(pdd->CreateSurface(&ddsd, &pdds,NULL) != DD_OK)
	{
		return NULL;
		
	} else {
		
		return pdds;
		
	}
	
}
// Copy Bitmap

HRESULT DDCopyBitmap(IDirectDrawSurface* pdds, HBITMAP hbm, int dx, int dy)
{
	
	HDC hdcImage;
	HDC hdc;
	HRESULT hr;
	HBITMAP hbmOld;
	
	// Select Bitmap into a MemoryDC 

	
	hdcImage = CreateCompatibleDC(NULL);
	hbmOld = (HBITMAP)SelectObject(hdcImage, hbm);
	
	if((hr = pdds->GetDC(&hdc)) == DD_OK)
	{
		
		BitBlt(hdc,0,0,dx,dy,hdcImage,0,0,SRCCOPY);
		pdds->ReleaseDC(hdc);
	}
	
	SelectObject(hdcImage, hbmOld);
	DeleteDC(hdcImage);
	
	return hr;
	
}

// Wav Data

static const TCHAR c_szWAV[] = {"WAVE"};

///////////////////////////////////////////////////////////////////////////////

//

// DSLoadSoundBuffer

//

///////////////////////////////////////////////////////////////////////////////


IDirectSoundBuffer *DSLoadSoundBuffer(IDirectSound *pDS, LPCTSTR lpName)
{
	IDirectSoundBuffer *pDSB = NULL;
	DSBUFFERDESC dsBD = {0};
	BYTE *pbWaveData;
	
	if (DSGetWaveResource(NULL, lpName, &dsBD.lpwfxFormat, &pbWaveData, &dsBD.dwBufferBytes))
	{
		dsBD.dwSize = sizeof(dsBD);
		dsBD.dwFlags = DSBCAPS_STATIC | DSBCAPS_GETCURRENTPOSITION2;
		
		if (SUCCEEDED(pDS->CreateSoundBuffer(&dsBD, &pDSB, NULL)))
		{
			if (!DSFillSoundBuffer(pDSB, pbWaveData, dsBD.dwBufferBytes))
			{
				pDSB->Release();
				pDSB = NULL;
			}
		}
		else
		{
			pDSB = NULL;
		}
	}
	
	return pDSB;
}

///////////////////////////////////////////////////////////////////////////////

//

// DSReloadSoundBuffer

//

///////////////////////////////////////////////////////////////////////////////


BOOL DSReloadSoundBuffer(IDirectSoundBuffer *pDSB, LPCTSTR lpName)
{
	BOOL result=FALSE;
	BYTE *pbWaveData;
	DWORD cbWaveSize;
	
	if (DSGetWaveResource(NULL, lpName, NULL, &pbWaveData, &cbWaveSize))
	{
		if (SUCCEEDED(pDSB->Restore()) &&
			DSFillSoundBuffer(pDSB, pbWaveData, cbWaveSize))
		{
			result = TRUE;
		}
	}
	
	return result;
}

///////////////////////////////////////////////////////////////////////////////

//

// DSGetWaveResource

//

///////////////////////////////////////////////////////////////////////////////


BOOL DSGetWaveResource(HMODULE hModule, LPCTSTR lpName,
					   WAVEFORMATEX **ppWaveHeader, BYTE **ppbWaveData, DWORD *pcbWaveSize)
{
	HRSRC hResInfo;
	HGLOBAL hResData;
	void *pvRes;
	
	if (((hResInfo = FindResource(hModule, lpName, c_szWAV)) != NULL) &&
		((hResData = LoadResource(hModule, hResInfo)) != NULL) &&
		((pvRes = LockResource(hResData)) != NULL) &&
		DSParseWaveResource(pvRes, ppWaveHeader, ppbWaveData, pcbWaveSize))
	{
		return TRUE;
	}
	
	return FALSE;
}

///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////


BOOL DSFillSoundBuffer(IDirectSoundBuffer *pDSB, BYTE *pbWaveData, DWORD cbWaveSize)
{
	if (pDSB && pbWaveData && cbWaveSize)
	{
		LPVOID pMem1, pMem2;
		DWORD dwSize1, dwSize2;
		
		if (SUCCEEDED(pDSB->Lock(0, cbWaveSize, &pMem1, &dwSize1, &pMem2, &dwSize2, 0)))
		{
			CopyMemory(pMem1, pbWaveData, dwSize1);
			
			if ( 0 != dwSize2 )
				CopyMemory(pMem2, pbWaveData+dwSize1, dwSize2);
			
			pDSB->Unlock(pMem1, dwSize1, pMem2, dwSize2);
			return TRUE;
		}
	}
	
	return FALSE;
}

///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////


BOOL DSParseWaveResource(void *pvRes, WAVEFORMATEX **ppWaveHeader, BYTE **ppbWaveData,DWORD *pcbWaveSize)
{
	DWORD *pdw;
	DWORD *pdwEnd;
	DWORD dwRiff;
	DWORD dwType;
	DWORD dwLength;
	
	if (ppWaveHeader)
		*ppWaveHeader = NULL;
	
	if (ppbWaveData)
		*ppbWaveData = NULL;
	
	if (pcbWaveSize)
		*pcbWaveSize = 0;
	
	pdw = (DWORD *)pvRes;
	dwRiff = *pdw++;
	dwLength = *pdw++;
	dwType = *pdw++;
	
	if (dwRiff != mmioFOURCC('R', 'I', 'F', 'F'))
		goto exit;		// not even RIFF

	
	if (dwType != mmioFOURCC('W', 'A', 'V', 'E'))
		goto exit;		// not a WAV

	
	pdwEnd = (DWORD *)((BYTE *)pdw + dwLength-4);
	
	while (pdw < pdwEnd)
	{
		dwType = *pdw++;
		dwLength = *pdw++;
		
		switch (dwType)
		{
		case mmioFOURCC('f', 'm', 't', ' '):
			if (ppWaveHeader && !*ppWaveHeader)
			{
				if (dwLength < sizeof(WAVEFORMAT))
					goto exit;		// not a WAV

				
				*ppWaveHeader = (WAVEFORMATEX *)pdw;
				
				if ((!ppbWaveData || *ppbWaveData) &&
					(!pcbWaveSize || *pcbWaveSize))
				{
					return TRUE;
				}
			}
			break;
			
		case mmioFOURCC('d', 'a', 't', 'a'):
			if ((ppbWaveData && !*ppbWaveData) ||
				(pcbWaveSize && !*pcbWaveSize))
			{
				if (ppbWaveData)
					*ppbWaveData = (LPBYTE)pdw;
				
				if (pcbWaveSize)
					*pcbWaveSize = dwLength;
				
				if (!ppWaveHeader || *ppWaveHeader)
					return TRUE;
			}
			break;
		}
		
		pdw = (DWORD *)((BYTE *)pdw + ((dwLength+1)&~1));
	}
	
exit:
	return FALSE;
}

HRESULT
DDSetColorKey(IDirectDrawSurface * pdds, COLORREF rgb)
{
    DDCOLORKEY              ddck;
	
    ddck.dwColorSpaceLowValue = DDColorMatch(pdds, rgb);
    ddck.dwColorSpaceHighValue = ddck.dwColorSpaceLowValue;
    return pdds->SetColorKey(DDCKEY_SRCBLT, &ddck);
}


DWORD
DDColorMatch(IDirectDrawSurface * pdds, COLORREF rgb)
{
    COLORREF                rgbT;
    HDC                     hdc;
    DWORD                   dw = CLR_INVALID;
    DDSURFACEDESC          ddsd;
    HRESULT                 hres;
	
    //

    //  Use GDI SetPixel to color match for us

    //

    if (rgb != CLR_INVALID && pdds->GetDC(&hdc) == DD_OK)
    {
        rgbT = GetPixel(hdc, 0, 0);     // Save current pixel value

        SetPixel(hdc, 0, 0, rgb);       // Set our value

        pdds->ReleaseDC(hdc);
    }
    //

    // Now lock the surface so we can read back the converted color

    //

    ddsd.dwSize = sizeof(ddsd);
    while ((hres = pdds->Lock(NULL, &ddsd, 0, NULL)) == DDERR_WASSTILLDRAWING)
        ;
    if (hres == DD_OK)
    {
        dw = *(DWORD *) ddsd.lpSurface;                 // Get DWORD

        if (ddsd.ddpfPixelFormat.dwRGBBitCount < 32)
            dw &= (1 << ddsd.ddpfPixelFormat.dwRGBBitCount) - 1;  // Mask it to bpp

        pdds->Unlock(NULL);
    }
    //

    //  Now put the color that was there back.

    //

    if (rgb != CLR_INVALID && pdds->GetDC(&hdc) == DD_OK)
    {
        SetPixel(hdc, 0, 0, rgbT);
        pdds->ReleaseDC(hdc);
    }
    return dw;
}

HRESULT
DDReLoadBitmap(IDirectDrawSurface * pdds, LPCSTR szBitmap)
{
    HBITMAP                 hbm;
    HRESULT                 hr;

    //

    //  Try to load the bitmap as a resource, if that fails, try it as a file

    //

    hbm = (HBITMAP) LoadImage(GetModuleHandle(NULL), szBitmap, IMAGE_BITMAP, 0,
                              0, LR_CREATEDIBSECTION);
    if (hbm == NULL)
        hbm = (HBITMAP) LoadImage(NULL, szBitmap, IMAGE_BITMAP, 0, 0,
                                  LR_LOADFROMFILE | LR_CREATEDIBSECTION);
    if (hbm == NULL)
    {
        OutputDebugString("handle is null\n");
        return E_FAIL;
    }

	hr = DDCopyBitmap2(pdds, hbm, 0, 0, 0, 0);

   
	if (hr != DD_OK)
    {
        OutputDebugString("ddcopybitmap failed\n");
    }
    DeleteObject(hbm);
    return hr;
}

HRESULT
DDCopyBitmap2(IDirectDrawSurface * pdds, HBITMAP hbm, int x, int y,
             int dx, int dy)
{
    HDC                     hdcImage;
    HDC                     hdc;
    BITMAP                  bm;
    DDSURFACEDESC          ddsd;
    HRESULT                 hr;

    if (hbm == NULL || pdds == NULL)
        return E_FAIL;
    //

    // Make sure this surface is restored.

    //

    pdds->Restore();
    //

    // Select bitmap into a memoryDC so we can use it.

    //

    hdcImage = CreateCompatibleDC(NULL);
    if (!hdcImage)
        OutputDebugString("createcompatible dc failed\n");
    SelectObject(hdcImage, hbm);
    //

    // Get size of the bitmap

    //

    GetObject(hbm, sizeof(bm), &bm);
    dx = dx == 0 ? bm.bmWidth : dx;     // Use the passed size, unless zero

    dy = dy == 0 ? bm.bmHeight : dy;
    //

    // Get size of surface.

    //

    ddsd.dwSize = sizeof(ddsd);
    ddsd.dwFlags = DDSD_HEIGHT | DDSD_WIDTH;
    pdds->GetSurfaceDesc(&ddsd);

    if ((hr = pdds->GetDC(&hdc)) == DD_OK)
    {
        StretchBlt(hdc, 0, 0, ddsd.dwWidth, ddsd.dwHeight, hdcImage, x, y,
                   dx, dy, SRCCOPY);
        pdds->ReleaseDC(hdc);
    }
    DeleteDC(hdcImage);
    return hr;
}

// ****** misc


HFONT MakeFont(char* ftype, int size)
{
	return CreateFont(size,0,0,0,FW_DONTCARE,0,0,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,FF_MODERN,ftype);
}

//*********


// ************************************* MASTERSOCKET


// initilze windows sockets

void initwinsock()
{
	
WORD wVersionRequested;
WSADATA wsaData;
int err;

wVersionRequested = MAKEWORD( 1, 1 );

err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 ) {
 	MessageBox(0,"Error Couldnt Init Winsock!","Aborting",MB_ICONINFORMATION);
	PostQuitMessage(0);
    return;
}


if ( LOBYTE( wsaData.wVersion ) != 1 ||
         HIBYTE( wsaData.wVersion ) != 1 ) {
    WSACleanup( );
    return;   

}
}

// killwinsock, on lcose

void killwinsock()
{
	WSACleanup();
}

// the master socket data structure

void MasterSocket::CreateSocket(HWND hwndx, UINT SOCKET_IDx)
{
	hwnd = hwndx;
	SOCKET_ID = SOCKET_IDx;
	socketx = socket(AF_INET,SOCK_STREAM,0);
	WSAAsyncSelect(socketx,hwnd,SOCKET_ID,FD_CONNECT|FD_READ|FD_CLOSE|FD_ACCEPT);
}

// begin listening

void MasterSocket::Listen(UINT port)
{
	if(port == DEFAULT_PORT) { port = 7; }
     struct sockaddr_in addy;
	// begin watching on port 7

  	addy.sin_family = AF_INET;
	addy.sin_port = htons(port);
	addy.sin_addr.s_addr = INADDR_ANY; //inet_addr("172.129.243.252");

   	bind(socketx,(struct sockaddr*)&addy,sizeof(addy));
	listen(socketx,5);
}
// connect to a remote socket

void MasterSocket::Connect(char* ipaddress,UINT port)
{
	struct sockaddr_in addy2;
	if(port == DEFAULT_PORT) { port = 7; }

	addy2.sin_family = AF_INET;
	addy2.sin_port = htons(port);
	addy2.sin_addr.s_addr = inet_addr(ipaddress);
	connect(socketx,(struct sockaddr*)&addy2,sizeof(addy2));
}
// accept a request from remote socket

void MasterSocket::Accept()
{
	struct sockaddr cli_addr;
    int clilen;
	clilen = sizeof(cli_addr);
	socketx = accept(socketx,(struct sockaddr*)&cli_addr,&clilen);
}

// send data once socket is connected

void MasterSocket::Send(char* buff, int len)
{
	send(socketx,buff,len,0);
}
// recive data from a connected socket

int MasterSocket::Recive(char* buff,int len)
{
	return recv(socketx,buff,len,0);
}
// get the ID of a given socket, for the wndproc callback

const UINT MasterSocket::GetID()
{
	return (const UINT)SOCKET_ID;
}
// close an open socket

void MasterSocket::Close()
{
	closesocket(socketx);
}
//***********

// MasterJoyStick


// return how many joysticks there are

unsigned int MasterJoyStick::GetJoysticks()
{
	return joyGetNumDevs();
}
// does joysticks exisit

bool MasterJoyStick::JoyExisit()
{
	joystickInfoEx.dwSize = sizeof(JOYINFOEX);
	joystickPresent = (joyGetPosEx(JOYSTICKID1,&joystickInfoEx) == JOYERR_NOERROR);
	if(!joystickPresent)
	{
		return false;
	}

	return true;
}
// setup this joystick

bool MasterJoyStick::SetupJoystick()
{
	if(JoyExisit() == false)
	{
		return false;
	}

	joyGetDevCaps(JOYSTICKID1,&joystickCaps,sizeof(joystickCaps));
	joystickHasThrottle = (joystickCaps.wCaps & JOYCAPS_HASZ);
	int joystickDeadSize = (joystickCaps.wXmax - joystickCaps.wXmin) * JOY_DEADZONE / 100;
	joystickDeadXMax = (joystickCaps.wXmax - joystickCaps.wYmin) / 2 + (joystickDeadSize / 2);
	joystickDeadXMin = joystickDeadXMax - joystickDeadSize;
	joystickDeadSize = (joystickCaps.wYmax - joystickCaps.wYmin) * JOY_DEADZONE / 100;
	joystickDeadYMax = (joystickCaps.wYmax - joystickCaps.wYmin) / 2 + (joystickDeadSize / 2);
	joystickDeadYMin = joystickDeadYMax - joystickDeadSize;
	return true;
}
// get joystick cordinates

bool MasterJoyStick::GetJoystickCoords(JOYINFOEX* info)
{
	if(!joystickPresent) return false;
	info->dwSize  = sizeof(JOYINFOEX);
	info->dwFlags = JOY_RETURNX | JOY_RETURNY;
	return (!joyGetPosEx(JOYSTICKID1,info));
}
// is the joystick still

bool MasterJoyStick::JoyStop()
{
	if(!GetJoystickCoords(&joystickInfoEx)) return false;
	return (( joystickInfoEx.dwYpos > joystickDeadYMin) && (joystickInfoEx.dwYpos < joystickDeadYMax) &&
		(joystickInfoEx.dwXpos > joystickDeadXMin) &&
		(joystickInfoEx.dwXpos < joystickDeadXMax));
}

// is the joystick being pressed forward (UP)

bool MasterJoyStick::JoyForward()
{
	if(!GetJoystickCoords(&joystickInfoEx)) return false;
	return (joystickInfoEx.dwYpos < joystickDeadYMin);
}
// is the joystick being pressed backwards (DOWN)

bool MasterJoyStick::JoyBackward()
{
	if(!GetJoystickCoords(&joystickInfoEx)) return false;
	return(joystickInfoEx.dwYpos > joystickDeadYMax);
}
// is the joystick being pressed left 

bool MasterJoyStick::JoyLeft()
{
	if(!GetJoystickCoords(&joystickInfoEx)) return false;
	return(joystickInfoEx.dwXpos < joystickDeadXMin);
}
// is the joystick being pressed right

bool MasterJoyStick::JoyRight()
{
	if(!GetJoystickCoords(&joystickInfoEx)) return false;
	return (joystickInfoEx.dwXpos > joystickDeadXMax);
}
// get the currently pressed button

int MasterJoyStick::GetButtonPressed(JOYINFOEX* info)
{
	if(!joystickPresent) { return 0; }

	info->dwSize = sizeof(joystickInfoEx);
	info->dwFlags =  JOY_RETURNBUTTONS;
        joyGetPosEx(JOYSTICKID1,info);
	int x = info->dwButtonNumber;	
	return x;
}

// get the pressed button

int MasterJoyStick::JoyButtonDown()
{
	return GetButtonPressed(&joystickInfoEx);
}

//**********************************************************************************



// ENTRY

int APIENTRY WinMain(HINSTANCE hInst,HINSTANCE hPrev,LPSTR l,int CmdShow)
{
	return MasterMain(hInst,l);
}