// _______________________________________________________________________________
//
//	 - WiiYourself! - native C++ Wiimote library  v1.11 BETA
//	  (c) gl.tter 2007-9 - http://gl.tter.org
//
//	  see License.txt for conditions of use.  see History.txt for change log.
// _______________________________________________________________________________
//
//  demo.cpp  (tab = 4 spaces)
#include "Demo.h"
#include "..\wiimote.h"
#include <mmsystem.h>	// for timeGetTime

// configs:
#define USE_BEEPS_AND_DELAYS			// undefine to test library works without them
#define LOOK_FOR_ADDITIONAL_WIIMOTES	// tries to connect any extra wiimotes

// ------------------------------------------------------------------------------------
//  simple callback example (we use polling for everything else):
// ------------------------------------------------------------------------------------
void on_state_change (wiimote &remote, state_change_flags changed)
	{
	// a MotionPlus was detected
	if(changed & MOTIONPLUS_DETECTED)
		{
		// enable it if there isn't a normal extension plugged into it
		// (MotionPlus devices don't report like normal extensions until
		//  enabled - and then, other extensions attached to it will no longer be
		//  reported (so disable it when you want to access to those again).
		if(remote.ExtensionType == wiimote_state::NONE) {
			bool res = remote.EnableMotionPlus();
			_ASSERT(res);
			}
		}
	else if(changed & MOTIONPLUS_EXTENSION_CONNECTED)
		{
		// an extension is connected to the MotionPlus.  We can't read it if the
		//  MotionPlus is currently enabled, so disable it:
		if(remote.MotionPlusEnabled())
			remote.DisableMotionPlus();
		}
	else if(changed & MOTIONPLUS_EXTENSION_DISCONNECTED)
		{
		// the extension plugged into the MotionPlus was removed, so enable
		//  the MotionPlus data again:
		if(remote.MotionPlusConnected())
			remote.EnableMotionPlus();
		}
	// extension was just connected:
	else if(changed & EXTENSION_CONNECTED)
		{
#ifdef USE_BEEPS_AND_DELAYS
		Beep(1000, 200);
#endif
		// switch to a report mode that includes the extension data (we will
		//  loose the IR dot sizes)
		// note: there is no need to set report types for a Balance Board.
		if(!remote.IsBalanceBoard())
			remote.SetReportType(wiimote::IN_BUTTONS_ACCEL_IR_EXT);
		}
	// extension was just disconnected:
	else if(changed & EXTENSION_DISCONNECTED)
		{
#ifdef USE_BEEPS_AND_DELAYS
		Beep(200, 300);
#endif
		// use a non-extension report mode (this gives us back the IR dot sizes)
		remote.SetReportType(wiimote::IN_BUTTONS_ACCEL_IR);
		}
	}
// ------------------------------------------------------------------------------------
void PrintTitle (HANDLE console)
	{
	BRIGHT_WHITE;
	_tprintf(_T("\n")); 
	_tprintf(_T("   -WiiYourself!- "));
	WHITE; _tprintf(		   _T("library Demo:   "));
	CYAN;  _tprintf(						   _T("| (c) "));
	BRIGHT_CYAN;  _tprintf(							 _T("gl"));
	BRIGHT_PURPLE;_tprintf(                            _T("."));
	BRIGHT_CYAN;  _tprintf(								_T("tter"));
	CYAN; _tprintf(										    _T(" 2007-09\n")
			 _T("                       v") WIIYOURSELF_VERSION_STR
										 _T(" | http://gl.tter.org\n"));
	CYAN;_tprintf(_T(" ______________________________________________________________________\n\n\n"));
	}
// ------------------------------------------------------------------------------------
int _tmain ()
	{
	SetConsoleTitle(_T("- WiiYourself! - Demo: "));
	HANDLE console = GetStdHandle(STD_OUTPUT_HANDLE);

	// write the title
	PrintTitle(console);

	// let's load a couple of samples:
	wiimote_sample sine_sample, daisy_sample;

	// one .raw (just to demonstrate it)
	if(!wiimote::Load16BitMonoSampleRAW(_T("1kSine16 (3130).raw"),
										true, FREQ_3130HZ, sine_sample)) {
		_tprintf(_T("\r  ** can't find 'Sine16 (3130).raw' - (sample won't work!) **"));
		Beep(100, 1000);
		Sleep(3000);
		_tprintf(_T("\r") BLANK_LINE);
		}
	// and one (more convenient) .wav 
	if(!wiimote::Load16bitMonoSampleWAV(_T("Daisy16 (3130).wav"), daisy_sample)) {
		_tprintf(_T("\r  ** can't find 'Daisy16 (3130).wav' - (sample won't work!) **"));
		Beep(100, 1000);
		Sleep(3000);
		_tprintf(_T("\r") BLANK_LINE);
		}

	// create a wiimote object
	wiimote remote;
	
	// simple callback example (we use polling for almost everything here):
	remote.ChangedCallback		= on_state_change;
	//  notify us only when something related to the extension changes
	remote.CallbackTriggerFlags = (state_change_flags)( EXTENSION_CHANGED |
													   MOTIONPLUS_CHANGED);

reconnect:
	COORD pos = { 0, 6 };
	SetConsoleCursorPosition(console, pos);

	// try to connect the first available wiimote in the system
	//  (available means 'installed, and currently Bluetooth-connected'):
	WHITE; _tprintf(_T("  Looking for a Wiimote     "));
	   
	static const TCHAR* wait_str[] = { _T(".  "), _T(".. "), _T("...") };
	unsigned count = 0;
	while(!remote.Connect(wiimote::FIRST_AVAILABLE)) {
		_tprintf(_T("\b\b\b\b%s "), wait_str[count%3]);
		count++;
#ifdef USE_BEEPS_AND_DELAYS
		Beep(500, 30); Sleep(1000);
#endif
		}

	// connected - light all LEDs
	remote.SetLEDs(0x0f);
	BRIGHT_CYAN; _tprintf(_T("\b\b\b\b... connected!"));
	if(remote.IsBalanceBoard()) {
		BRIGHT_WHITE;_tprintf(_T("  (Balance Board)"));
		}

#ifdef USE_BEEPS_AND_DELAYS
	Beep(1000, 300); Sleep(2000);
#endif

	COORD cursor_pos = { 0, 6 };

#ifdef LOOK_FOR_ADDITIONAL_WIIMOTES
	// try to connect any additional wiimotes (just to show the code)
	_tprintf(_T("\n\n"));

	wiimote  *extra_motes [7] = { NULL }; // 7 should cover it
	unsigned detected		  = 0;
	while(detected < 7)
		{
		wiimote *next = new wiimote;
		if(!next->Connect(wiimote::FIRST_AVAILABLE))
			break;
		extra_motes[detected++] = next;
		
		WHITE		; _tprintf(_T("   also found wiimote "));
		BRIGHT_GREEN; _tprintf(_T("%u"), detected+1);
		if(next->IsBalanceBoard()) {
			WHITE; _tprintf(_T("  (Balance Board)"));
			}
		_tprintf(_T("\n\n"));

# ifdef USE_BEEPS_AND_DELAYS
		Beep(1000 + (detected*100), 100);
		Sleep(500);
# endif
		}
	WHITE; _tprintf( ((detected == 7)? _T("     (can't detect any more).") :
									   _T("    (no more found).")) );
# ifdef USE_BEEPS_AND_DELAYS
	Sleep(2000);
# endif
	// clean up
	for(unsigned index=0; index<detected; index++)
		delete extra_motes[index];
	
	SetConsoleCursorPosition(console, cursor_pos);
#endif // LOOK_FOR_ADDITIONAL_WIIMOTES

	// ask the wiimote to report everything (using the 'non-continous updates'
	//  default mode - updates will be frequent anyway due to the acceleration/IR
	//  values changing):

	// note1: you don't need to set a report type for Balance Board - the library
	//         takes care of it (there is only one).
	// note2: for wiimotes, the report mode that includes the extension data
	//		   unfortunately only reports the 'BASIC' IR info (ie. no dot sizes) -
	//		   so let's choose the best mode based on the extension status (we also
	//		   toggle modes as needed in the callback above):
	if(!remote.IsBalanceBoard())
		{
		if(remote.bExtension)
			remote.SetReportType(wiimote::IN_BUTTONS_ACCEL_IR_EXT); // no IR dots
		else
			remote.SetReportType(wiimote::IN_BUTTONS_ACCEL_IR);		//    IR dots
		}

	// print the button event instructions:
	BRIGHT_WHITE;
	_tprintf(_T("\r  -- TRY: B = rumble, A = square, 1 = sine, 2 = daisy, Home = Exit --\n"));

	// (stuff for animations)
	DWORD	 last_rumble_time = timeGetTime(); // for rumble text animation
	DWORD    last_led_time    = timeGetTime(); // for led         animation
	bool	 rumble_text	  = true;
	unsigned lit_led          = 0;	
	
	// display the wiimote state data until 'Home' is pressed:
	bool caliubrate_atrest_once = true;
	while(!remote.Button.Home())// && !GetAsyncKeyState(VK_ESCAPE))
		{
		// the wiimote state needs to be refreshed for each pass
		while(remote.RefreshState() == NO_CHANGE)
			Sleep(1); // // don't hog the CPU if nothing changed

		cursor_pos.Y = 8;
		SetConsoleCursorPosition(console, cursor_pos);

		// did we loose the connection?
		if(remote.ConnectionLost())
			{
			BRIGHT_RED; _tprintf(
				_T("   *** connection lost! ***                                          \n")
				BLANK_LINE BLANK_LINE BLANK_LINE BLANK_LINE BLANK_LINE BLANK_LINE
				BLANK_LINE BLANK_LINE BLANK_LINE BLANK_LINE BLANK_LINE BLANK_LINE
				BLANK_LINE BLANK_LINE BLANK_LINE);
			Beep(100, 1000);
			Sleep(2000);
			COORD pos = { 0, 6 };
			SetConsoleCursorPosition(console, pos);
			_tprintf(BLANK_LINE BLANK_LINE BLANK_LINE);
			goto reconnect;
			}

		// rumble if 'B' (trigger) is pressed
		remote.SetRumble(remote.Button.B());

		// disable MotionPlus (if connected) to allow its own extension port
		//  to work
		if(remote.Button.Minus())
			remote.DisableMotionPlus();

		// actions for buttons just pressed/released:
		static bool last_A = false, last_One = false, last_Two = false;

		#define ON_PRESS_RELEASE(button, pressed_action, released_action)	\
			{ bool pressed = remote.Button.button();						\
			  if(pressed)													\
			 	{				   /* just pressed? */						\
				if(!last_##button) pressed_action;							\
				}															\
			else if(last_##button) /* just released */						\
				released_action;											\
			/* remember the current button state for next time */			\
			last_##button = pressed; }
			
		//  play audio whilst certain buttons are held
		if(!remote.IsBalanceBoard()) {
			ON_PRESS_RELEASE(  A, remote.PlaySquareWave(FREQ_3130HZ, 0x20), 
								  remote.EnableSpeaker (false));
			ON_PRESS_RELEASE(One, remote.PlaySample	   (sine_sample),
								  remote.EnableSpeaker (false));
			ON_PRESS_RELEASE(Two, remote.PlaySample	   (daisy_sample),
								  remote.EnableSpeaker (false));
			}

		// Battery level:
		CYAN; _tprintf(_T("  Battery: "));
		// (the green/yellow colour ranges are rough guesses - my wiimote
		//  with rechargeable battery pack fails at around 15%)
		(remote.bBatteryDrained	    )? BRIGHT_RED   :
		(remote.BatteryPercent >= 30)? BRIGHT_GREEN : BRIGHT_YELLOW;
		_tprintf(_T("%3u%%   "), remote.BatteryPercent);

		DWORD current_time = timeGetTime();

		// LEDs:
		//  animate them every second
		if((current_time - last_led_time) >= 1000) {
			remote.SetLEDs((BYTE)(1<<lit_led));
			lit_led		  = (++lit_led) % 4;
			last_led_time = timeGetTime();
			}

		CYAN; _tprintf(_T("LEDs: ")); WHITE; _tprintf(_T("["));
		for(unsigned led=0; led<4; led++)
			{
			if(remote.LED.Lit(led)) {
				BRIGHT_CYAN; _tprintf(_T("*"));
				}
			else{
				WHITE      ; _tprintf(_T("-"));//_T("%c"), '0'+led);
				}
			}

		// Rumble
		WHITE; _tprintf(_T("]    "));
		if(remote.bRumble) {
			BRIGHT_WHITE; _tprintf(rumble_text? _T(" RUMBLE") : _T("RUMBLE "));
			// animate the text
			if((current_time - last_rumble_time) >= 110) {
				rumble_text		 = !rumble_text;
				last_rumble_time = current_time;
				}
			}
		else
			_tprintf(_T("       "));

		// Output method:
	    CYAN; _tprintf( _T("    using %s\n"), (remote.IsUsingHIDwrites()?
											   _T("HID writes") : _T("WriteFile()")));
		
		// Buttons:
		CYAN; _tprintf(_T("\n  Buttons: ")); WHITE; _tprintf(_T("["));
		for(unsigned bit=0; bit<16; bit++)
			{
			WORD mask = (WORD)(1 << bit);
			// skip unused bits
			if((wiimote_state::buttons::ALL & mask) == 0)
				continue;

			const TCHAR* button_name = wiimote::ButtonNameFromBit[bit];
			bool		 pressed	 = ((remote.Button.Bits & mask) != 0);
			if(bit > 0) {
				CYAN; _tprintf(_T("|")); // seperator
				}
			if(pressed) {
				BRIGHT_WHITE; _tprintf(_T("%s")  , button_name);
				}
			else{
				WHITE       ; _tprintf(_T("%*s"), _tcslen(button_name), _T(""));
				}
			}
		WHITE; _tprintf(_T("]\n"));

		// Acceleration:
		CYAN ; _tprintf(_T("    Accel:"));
		remote.IsBalanceBoard()? RED : WHITE;
		_tprintf(_T("  X %+2.3f  Y %+2.3f  Z %+2.3f  \n"),
					remote.Acceleration.X,
					remote.Acceleration.Y,
					remote.Acceleration.Z);
	
		// Orientation estimate (shown red if last valid update is aging):
		CYAN ; _tprintf(_T("   Orient:"));
		remote.IsBalanceBoard()? RED : WHITE;
		_tprintf(_T("  UpdateAge %3u  "), remote.Acceleration.Orientation.UpdateAge);
		
		//  show if the last orientation update is considered out-of-date
		//   (using an arbitrary threshold)
		if(remote.Acceleration.Orientation.UpdateAge > 10)
			RED;
			
		_tprintf(_T("Pitch:%4ddeg  Roll:%4ddeg  \n")
			     _T("                           (X %+.3f  Y %+.3f  Z %+.3f)      \n"),
				 (int)remote.Acceleration.Orientation.Pitch,
				 (int)remote.Acceleration.Orientation.Roll ,
				 remote.Acceleration.Orientation.X,
				 remote.Acceleration.Orientation.Y,
  				 remote.Acceleration.Orientation.Z);
				
		// IR:
		CYAN ; _tprintf(_T("       IR:"));
		remote.IsBalanceBoard()? RED : WHITE;
		_tprintf(_T("  Mode %s  "),
			((remote.IR.Mode == wiimote_state::ir::OFF     )? _T("OFF  ") :
			 (remote.IR.Mode == wiimote_state::ir::BASIC   )? _T("BASIC") :
			 (remote.IR.Mode == wiimote_state::ir::EXTENDED)? _T("EXT. ") :
															  _T("FULL ")));
		// IR dot sizes are only reported in EXTENDED IR mode (FULL isn't supported yet)
		bool dot_sizes = (remote.IR.Mode == wiimote_state::ir::EXTENDED);

		for(unsigned index=0; index<4; index++)
			{
			wiimote_state::ir::dot &dot = remote.IR.Dot[index];
			
			if(!remote.IsBalanceBoard()) WHITE;
			_tprintf(_T("%u: "), index);

			if(dot.bVisible) {
				WHITE; _tprintf(_T("Seen       "));
				}
			else{
				RED  ; _tprintf(_T("Not seen   "));
				}

			_tprintf(_T("Size"));
			if(dot_sizes)
				 _tprintf(_T("%3d "), dot.Size);
			else{
				RED; _tprintf(_T(" n/a"));
				if(dot.bVisible) WHITE;
				}

			_tprintf(_T("  X %.3f  Y %.3f\n"), dot.X, dot.Y);
			
			if(index < 3)
				_tprintf(_T("                        "));
			}

		// Speaker:
		CYAN ; _tprintf(_T("  Speaker:"));
		remote.IsBalanceBoard()? RED : WHITE;
		_tprintf(_T("  %s | %s    "), (remote.Speaker.bEnabled? _T("On ") :
															    _T("Off")),
									  (remote.Speaker.bMuted  ? _T("Muted") :
																_T("     ")));
		if(!remote.Speaker.bEnabled || remote.Speaker.bMuted)
			RED;
		else//if(remote.IsPlayingAudio()) BRIGHT_WHITE; else WHITE;
			WHITE;
		_tprintf(_T("Frequency %4u Hz   Volume 0x%02x\n"),
				 wiimote::FreqLookup[remote.Speaker.Freq],
				 remote.Speaker.Volume);
		
		// -- Extensions --:
		CYAN ; _tprintf(_T("__________\n  Extnsn.:  "));
		switch(remote.ExtensionType)
			{
			case wiimote_state::NONE:
				{
				RED;
				_tprintf(_T("None                                                             \n"));
				_tprintf(BLANK_LINE BLANK_LINE BLANK_LINE);
				}
				break;
			
			case wiimote_state::PARTIALLY_INSERTED:
				{
				BRIGHT_RED;
				_tprintf(_T("Partially Inserted                                               \n"));
				_tprintf(BLANK_LINE BLANK_LINE BLANK_LINE);
				}
				break;
			
			// -- Nunchuk --
			case wiimote_state::NUNCHUK:
				{
				BRIGHT_WHITE; _tprintf(_T("Nunchuk   "));

				// Buttons:
				CYAN		; _tprintf(_T("Buttons: ")); WHITE; _tprintf(_T("["));
				BRIGHT_WHITE; _tprintf(remote.Nunchuk.C? _T("C") : _T(" "));
				CYAN		; _tprintf(_T("|"));
				BRIGHT_WHITE; _tprintf(remote.Nunchuk.Z? _T("Z") : _T(" "));
				WHITE		; _tprintf(_T("]   "));
				// Joystick:
				CYAN		; _tprintf(_T("Joystick:  "));
				WHITE		; _tprintf(_T("X %+2.3f  Y %+2.3f\n"),
									   remote.Nunchuk.Joystick.X,
									   remote.Nunchuk.Joystick.Y);
				// Acceleration:
				CYAN		; _tprintf(_T("    Accel:"));
				WHITE		; _tprintf(_T("  X %+2.3f  Y %+2.3f  Z %+2.3f  \n"),
									   remote.Nunchuk.Acceleration.X,
									   remote.Nunchuk.Acceleration.Y,
									   remote.Nunchuk.Acceleration.Z);
				
				// Orientation estimate (shown red if last valid update is aging):
				CYAN		; _tprintf(_T("   Orient:"));
				WHITE		; _tprintf(_T("  UpdateAge %3u  "),
								remote.Nunchuk.Acceleration.Orientation.UpdateAge);
				//  show if the last orientation update is aging
				if(remote.Nunchuk.Acceleration.Orientation.UpdateAge > 10)
					RED;
				_tprintf(_T("Pitch %4ddeg  Roll %4ddeg  \n")
					     _T("                           (X %+.2f  Y %+.2f  Z %+.2f)      \n"),
						 (int)remote.Nunchuk.Acceleration.Orientation.Pitch,
						 (int)remote.Nunchuk.Acceleration.Orientation.Roll ,
						 remote.Nunchuk.Acceleration.Orientation.X,
						 remote.Nunchuk.Acceleration.Orientation.Y,
  						 remote.Nunchuk.Acceleration.Orientation.Z);
				}
				break;

			// -- Classic Controller --
			case wiimote_state::CLASSIC:
			case wiimote_state::GH3_GHWT_GUITAR:
			case wiimote_state::GHWT_DRUMS:
				{
				BRIGHT_WHITE;
				// the Guitar Hero controller is just a classic controller with
				//  another ID
				if(remote.ExtensionType == wiimote_state::CLASSIC)
					_tprintf(_T("Classic Controller   "));
				else if(remote.ExtensionType == wiimote_state::GH3_GHWT_GUITAR)
					_tprintf(_T("GH3/GHWT Guitar      "));
				else
					_tprintf(_T("GHWT Drums           "));
				
				// L: Joystick/Trigger
				WHITE; _tprintf(_T("L:  "));
				CYAN ; _tprintf(_T("Joy "));
				WHITE; _tprintf(_T("X %+2.3f  Y %+2.3f  "),
								remote.ClassicController.JoystickL.X,
								remote.ClassicController.JoystickL.Y);
				CYAN ; _tprintf(_T("Trig "));
				WHITE; _tprintf(_T("%+2.3f\n"),
								remote.ClassicController.TriggerL);
				// R: Joystick/Trigger
				WHITE; _tprintf(_T("                                 R:  "));
				CYAN ; _tprintf(_T("Joy "));
				WHITE; _tprintf(_T("X %+2.3f  Y %+2.3f  "),
								remote.ClassicController.JoystickR.X,
								remote.ClassicController.JoystickR.Y);
				CYAN ; _tprintf(_T("Trig "));
				WHITE; _tprintf(_T("%+2.3f\n"),
								remote.ClassicController.TriggerR);

				// Buttons:
				CYAN; _tprintf(_T("  Buttons: ")); WHITE; _tprintf(_T("["));
				for(unsigned bit=0; bit<16; bit++)
					{
					WORD mask = (WORD)(1 << bit);
					// skip unused bits
					if((wiimote_state::classic_controller::buttons::ALL & mask) == 0)
						continue;

					const TCHAR* button_name = wiimote::ClassicButtonNameFromBit[bit];
					const TCHAR* seperator	 = (bit==0)? _T("") : _T("|");
					bool		 pressed	 = ((remote.ClassicController.Button.Bits & mask) != 0);
					CYAN; _tprintf(seperator);
					if(pressed) {
						BRIGHT_WHITE; _tprintf(_T("%s")  , button_name);
						}
					else{
						WHITE	; _tprintf(_T("%*s"), _tcslen(button_name), _T(""));
						}
					}
				WHITE; _tprintf(_T("]"));
				}
				break;

			case wiimote_state::BALANCE_BOARD:
				{
				BRIGHT_WHITE; _tprintf(_T("Balance Board"));

				// Weights:
				CYAN ; _tprintf(_T("   Weight: "));
				WHITE; _tprintf(_T("TL    "));
					   _tprintf(_T("%6.2f"), remote.BalanceBoard.Kg.TopL);
				CYAN ; _tprintf(_T(" kg")); WHITE; ;_tprintf(_T("  TR "));
					   _tprintf(_T("%6.2f"), remote.BalanceBoard.Kg.TopR);
				CYAN;  _tprintf(_T(" kg\n")); WHITE;
					   _tprintf(_T("                                    BL    "));
					   _tprintf(_T("%6.2f"), remote.BalanceBoard.Kg.BottomL);
				CYAN;  _tprintf(_T(" kg")); WHITE; _tprintf(_T("  BR "));
					   _tprintf(_T("%6.2f"), remote.BalanceBoard.Kg.BottomR);
				CYAN;  _tprintf(_T(" kg \n")); WHITE;
					   _tprintf(_T("                                    Total "));
					   _tprintf(_T("%6.2f"), remote.BalanceBoard.Kg.Total);
				CYAN;  _tprintf(_T(" kg"));
				}
				break;

			case wiimote_state::MOTION_PLUS:
				{
				BRIGHT_WHITE; _tprintf(_T("Motion Plus"));

				CYAN ; _tprintf(_T("    Raw: "));
				WHITE; _tprintf(_T("Yaw: %04hx  ")   , remote.MotionPlus.Raw.Yaw);
				WHITE; _tprintf(_T("Pitch: %04hx  ") , remote.MotionPlus.Raw.Pitch);
				WHITE; _tprintf(_T("Roll: %04hx  \n"), remote.MotionPlus.Raw.Roll);
				CYAN ; _tprintf(_T("                         Float: "));
				WHITE; _tprintf(_T("  %8.3fdeg")     , remote.MotionPlus.Speed.Yaw);
				WHITE; _tprintf(_T("  %8.3fdeg")   , remote.MotionPlus.Speed.Pitch);
				WHITE; _tprintf(_T(" %8.3fdeg\n")   , remote.MotionPlus.Speed.Roll);
				_tprintf(BLANK_LINE BLANK_LINE);
//Sleep(500);
				}
				break;
			}
  		}


	// disconnect (auto-happens on wiimote destruction anyway, but let's play nice)
	remote.Disconnect();
	Beep(1000, 200);

	BRIGHT_WHITE; // for automatic 'press any key to continue' msg
	CloseHandle(console);

	return 0;
	}
// ------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------
