MacBook Pro – The Better GPU

MacBook Pro - System PreferencesIt was a few month after I got my laptop I found this out, but you need to activate the more powerful GPU on the new MacBook Pros, otherwise it just uses the less powerful one.

It is not complicated, but it isn’t exactly intuitive, though apparently Snow Leopard changes the way this works so you don’t require a restart.

MacBook Pro - Switching GPUsFirst goto “System Preferences” on the dock.

Now select “Energy Saver”.

Now select “Higher Performance”, it will ask you to restart for changes to take effect.

Once you’ve restarted, that is it, you’re using the more powerful GPU. My games gained a huge amount of FPS when I did this, and with the help of the Fan Control application, I was able to keep my laptop relatively cold.

To undo the changes, repeat but select “Better battery life” instead.

On another note, I notice the new Firefox takes into account left and right scrolling on the Mac now for moving forward and backward between webpages :).

C# – Mono on Mac OS X

Mono Project LogoI’m always up for trying new ways of not having to boot up VMWare Fusion, and when searching for C# code, I came by a blog about something using Mono. Mono is a cross platform solution for using .NET and it is open source, which means I can write, compile and execute C# in MacOSX.

I found its strangely easy to setup, though I have yet to get WinForms to work from the examples, I have got console apps working. And with the console app, I have been able to use XPath.

The only downside was it took an hour to download from their website, which is quite bad for only 50MB.

Athena: Wiimote and Mac OS X

Wiimote USB DrivesSince solving the problem of the rumbling on the XBox 360 pad, I’ve grown bored of it, and decided to branch out trying to get more controllers working in my engine.

So a few days ago I started with the Wiimote, I had planned to try to the PS3 controller but I didn’t have one, so borrowing one of my housemates Wiimotes I set to work.

There is quite a lot of documentation on the Wiimote at the moment, whether it is the correct way to do things is questionable, since there are cases like “1? – it is set to 1 by the Wii” and “set this to 0x55 at memory address X and set to 0x00 at memory address Y to enable it”.

I started with website called The Wiimote Project, but as their documentation grew scarce I found a better site (which it seemed to copy it all from anyways) called WiiBrew. The WiiBrew wiki is quite comprehensive and within a few minutes I already had the LEDs flashing.

I won’t go into a lot of detail, I’ll just show the basics that I’ve got to grips with from the documentation on WiiBrew – LEDs + Motor, Buttons, and Battery.

Connecting the Wiimote

Connecting the Wiimote to a Mac is far simpler than it is for XBox 360, for a start its a Bluetooth device that operates using the normal protocols and it doesn’t require a key to activate. To connect, first turn on Bluetooth on your Mac, and then select “Set up Bluetooth Device…“.

Follow on the onscreen instructions, and when it gets to the point where it is searching for nearby Bluetooth devices, press 1 + 2 to soft synchronize if the Wiimote isn’t bound to another device, or the sync button to hard synchronize (unbinds the Wiimote from anything it remembers).

When it appears, select it and click the “Passkey Options…” button. Select the “Do not use a passkey with this device” option and then OK. Continue on and the device will be setup and connected. You can’t actually tell since the LEDs are still blinking, but if you have done it correctly, the Bluetooth icon should be different, or the menu will have a disconnect option for the device just setup.

Athena: XBox 360 Pad and Mac OS X (cont further)

Steampunk LincolnThe past couple of week’s I’ve really gotten into writing code that communicates with gaming devices (the Mac is limited in this part of itself).

One annoyance I had was with getting rumbling working on the XBox 360 pad, eventually after essentially pinging all messages, I found and worked out the format for the rumble message, which was annoyingly nothing like the others listed.

Well after that I got kinda bored with the 360 and decided to turn towards another console controller, the Wiimote. And I thought I’d write my own driver.

Long story short, when I was having trouble getting my driver working, I looked at the code for the driver for Tattiebogle’s XBox 360 pad driver, only to find out that it has redefined the rumble message to it’s own format, namely the 4 byte one, only to forward on the settings to the 360 pad.

Well I’m glad I figured out why the message was different, kinda annoying that wasn’t in his FAQ. Hopefully others will find this post and go “ohhhhhhhh” like I did when seeing the code.

As for the Wiimote, writing a driver for a Bluetooth device I’ve decided doesn’t make sense, the device is already designed to communicate with another bluetooth device, so I made a class instead, using a Bluetooth API and documentation I found on WiiBrew.

I’ll hopefully post my Xcode project for testing the 360 pad in a few days. And I’ll probably write up my Wiimote stuff once I get it working the way I want. I’m really tempted to buy lots of cheap USB and Bluetooth devices on eBay now just to see if I can write drivers for them.

Athena: XBox 360 Pad and Mac OS X (cont)

XBox360 Actuator RespondsIn my previous entry, Athena: XBox 360 Pad and Mac OS X, I began work on getting the XBox 360 pad working in my game engine. I also said that I’d post how to change the LEDs and get rumble working when I figured it out.

I had no trouble with getting the LEDs flashing, but for some reason the rumble actuators just would not respond to my message with success.

I had searched at all other documentation on the pad on the internet, but although I found two variations of rumbling, neither worked.

It has taken my a week or two, but then I got the inspiration to just fire all possible messages to the pad, nullified apart from the header, and see responds with success. So I wrote some code to send 255 different type ids, with 255 different lengths.

//
//
void HIDInput::TestDevice( IOHIDDeviceRef inDeviceRef )
{
	unsigned char reportData[255];
 
	// Nullify Report
	memset( reportData, 0, sizeof( unsigned char ) * 255 );
 
	// Loop through most possible messages
	for( unsigned char reportType = 0; reportType < 255; ++reportType )
	{
		for( unsigned char reportLength = 0; reportLength < 255; ++reportLength )
		{
			// Setup Header
			reportData[0] = reportType;
			reportData[1] = reportLength;
 
			// Send Report to Pad
			if( DeviceSendReport( inDeviceRef, reportType, reportData, reportLength ) )
			{
				printf( "Success - Type(%u), Length(%u)\n", reportType, reportLength );
			}
			else
			{
				printf( "Failed - Type(%u), Length(%u)\n", reportType, reportLength );
			}
		}
	}
 
	//
	printf( "Finished\n" );
}

 

I’ll explain show the function body for DeviceSendReport in a minute. After running this, only two reports returned with success, one was the LED report, and the other was of Type 0 with length 4.

Since the header take two bytes, I guessed the last two must be Actuator A and Actuator B. And after setting one of them to 0xff, I successfully managed to get one of the actuators rumbling, and then the other actuator with the other byte.

Now for the code for sending reports to the pad.

//
//
bool HIDInput::DeviceSendReport( IOHIDDeviceRef inDeviceRef, const unsigned char inType, const unsigned char * inReportData, const unsigned char inReportSize )
{
	return IOHIDDeviceSetReport( inDeviceRef, kIOHIDReportTypeOutput, inType, inReportData, inReportSize ) == kIOReturnSuccess;
}

 

As you can see it takes a parameter called inDeviceRef, this is the value that was passed to DeviceMatchingCallback in the previous entry. And now here is the code to get the LED flashing, there are a few status values for it, so I’ve created an enum with some comments explaining what each do.

//
//
enum LEDStatus
{
	kLED_AllOff = 0x00, // All LEDs are turned off
	kLED_AllBlink = 0x01, // All LEDs repeatedly blink on and off
	kLED_P1_FlashOn = 0x02, // Player 1 LED flashes then stays on
	kLED_P2_FlashOn = 0x03, // Player 2 LED flashes then stays on
	kLED_P3_FlashOn = 0x04, // Player 3 LED flashes then stays on
	kLED_P4_FlashOn = 0x05, // Player 4 LED flashes then stays on
	kLED_P1_On = 0x06, // Player 1 LED turns on
	kLED_P2_On = 0x07, // Player 2 LED turns on
	kLED_P3_On = 0x08, // Player 3 LED turns on
	kLED_P4_On = 0x09, // Player 4 LED turns on
	kLED_Rotating = 0x0a, // LEDs flash on in sequence
	kLED_CurrentBlink = 0x0b, // Currently active LED blinks
	kLED_SlowBlink = 0x0c, // All LEDs blink slowly
	kLED_Alternating = 0x0d, // Player 1 & 4 alternate blink with Player 2 & 3
};
 
//
//
void HIDInput::FlashLED( IOHIDDeviceRef inDeviceRef, const LEDStatus inStatus )
{
	//
	const unsigned char kReportType = 0x01;
	const unsigned char kReportSize = 0x03;
	const unsigned char kReportData[kReportSize] =
	{
		kReportType, kReportSize, static_cast<Core::byte>( inStatus )
	};
 
	//
	DeviceSendReport( inDeviceRef, kReportType, kReportData, kReportSize );
}

 

As you can see, it is fairly simple to send a message, all you have to remember is that the first two bytes contain a header (one byte for type, and one type for the size of the report including the header size). And finally for rumbling the motors.

//
//
void HIDInput::SetRumble( IOHIDDeviceRef inDeviceRef, const unsigned char inBigSpeed, const unsigned char inLittleSpeed )
{
	//
	const unsigned char kReportType = 0x00;
	const unsigned char kReportSize = 0x04;
	const unsigned char kReportData[kReportSize] =
	{
		kReportType, kReportSize, inBigSpeed, inLittleSpeed
	};
 
	//
	DeviceSendReport( inDeviceRef, kReportType, kReportData, kReportSize );
}

 

I had some minor problems with the rumble not changing after the first call to SetRumble originally, however it turned out that I had just accidently set the report data variable to be static, so the initialisation was only setup with the first values passed.

Other Rumble Reports

As I mentioned before, I’ve found other message formats for rumbling the motors, I don’t know if its a version thing, or something, but here are the other two I’ve found if you have trouble with mine.

Version 1 (Tattiebogle)

//
//
void HIDInput::SetRumble( IOHIDDeviceRef inDeviceRef, const unsigned char inBigSpeed, const unsigned char inLittleSpeed )
{
	//
	const unsigned char kReportType = 0x00;
	const unsigned char kReportSize = 0x08;
	const unsigned char kReportData[kReportSize] =
	{
		kReportType, kReportSize, 0x00, inBigSpeed, inLittleSpeed, 0x00, 0x00, 0x00
	};
 
	//
	DeviceSendReport( inDeviceRef, kReportType, kReportData, kReportSize );
}

 

Version 2 (http://euc.jp/periphs/xbox-controller.ja.html)

//
//
void HIDInput::SetRumble( IOHIDDeviceRef inDeviceRef, const unsigned char inBigSpeed, const unsigned char inLittleSpeed )
{
	//
	const unsigned char kReportType = 0x00;
	const unsigned char kReportSize = 0x06;
	const unsigned char kReportData[kReportSize] =
	{
		kReportType, kReportSize, 0x00, inBigSpeed, 0x00, inLittleSpeed
	};
 
	//
	DeviceSendReport( inDeviceRef, kReportType, kReportData, kReportSize );
}