Handy PC/Mac OS X Snippets for Indie Development
A number of useful code snippets that abstract common operations for both Mac OS X and Windows.
Introduction
It is a fact that cross-platform indie game development is on the rise these days. The reason behind porting to Mac is that most indies sell as many copies for PC as for Mac platforms. In addition, several of the most popular indie solutions now support both Windows and Macintosh platforms, such as Torque, BlitzMax, PTK and others.
However, even when using commercial engines, there will be a certain functionality that is not covered by the engine, and that will require native code for each platform.
That is why we have collected the following snippets, which I am sure you will find handy during your next cross-platform development.
Get current desktop resolution
If your game supports different video modes, you can use the current desktop settings to adjust the default resolution and color depth in the first run.
void GetDesktopResolution( int & width, int & height, int & bpp)
{
#ifdef __CARBON__
CFDictionaryRef desktopVideoMode = CGDisplayCurrentMode( kCGDirectMainDisplay );
if( !CFNumberGetValue( (CFNumberRef)CFDictionaryGetValue( desktopVideoMode, kCGDisplayWidth ),
kCFNumberIntType,
&width ) ||
!CFNumberGetValue( (CFNumberRef)CFDictionaryGetValue( desktopVideoMode, kCGDisplayHeight ),
kCFNumberIntType,
&height ) ||
!CFNumberGetValue( (CFNumberRef)CFDictionaryGetValue( desktopVideoMode, kCGDisplayBitsPerPixel ),
kCFNumberIntType,
&bpp ) )
{
// error, return default values
// ...
}
#elif WIN32
DEVMODE desktopVideoMode;
ZeroMemory( reinterpret_cast<DEVMODE*>( &desktopVideoMode ), sizeof( desktopVideoMode ) );
if( EnumDisplaySettings( NULL, ENUM_CURRENT_SETTINGS, &desktopVideoMode ) )
{
m_desktopWidth = desktopVideoMode.dmPelsWidth;
m_desktopHeight = desktopVideoMode.dmPelsHeight;
m_desktopBpp = desktopVideoMode.dmBitsPerPel;
}
else
{
// error, return default values
// ...
}
#else
#error unsupported platform
#endif
}
Get installed video RAM
The Mac OS X implementation will give you the exact ammount of video memory of the first valid video adapter found. However, the Windows version, which relies on DirectX 5, will return less memory than is physically installed. For 16MB video cards, it will return about 13MB though. I ignore the purpose of this behaviour, just take it into account.
Requiring DirectX 5 should not be a real problem, being already included in Windows 98. Furthermore, the DirectDraw DLL is dynamically loaded, so the function will just return zero in case of error (still running Windows 95 for instance).
#ifdef WIN32
#include <windows.h>
#include <ddraw.h> // Needs DirectX SDK(>=5), or at least ddraw.h in your path
typedef int (WINAPI *MYPROC)(GUID *,LPDIRECTDRAW *,IUnknown *);
#else
#include <Carbon/Carbon.h>
#include <AGL/agl.h>
#endif
const int GetInstalledVRAM( void )
{
#ifdef __CARBON__
AGLRendererInfo info;
GLint vram( 0 );
info = aglQueryRendererInfo ( NULL, 0 );
while ( info != NULL )
{
if( aglDescribeRenderer( info, AGL_VIDEO_MEMORY, &vram ) == GL_TRUE )
{
// Return megabytes
return static_cast<int>( vram / (1024 * 1024) );
}
info = aglNextRendererInfo( info );
}
return 0;
#elif WIN32
HINSTANCE DDrawDLL;
int vram ( 0 );
DDrawDLL = LoadLibrary( "ddraw.dll" );
if( DDrawDLL != NULL )
{
MYPROC DDrawCreate;
LPDIRECTDRAW DDraw;
HRESULT hres;
DDrawCreate = ( MYPROC ) GetProcAddress( DDrawDLL, "DirectDrawCreate");
if( ( DDrawCreate != NULL )
&& !FAILED( DDrawCreate( NULL, &DDraw, NULL ) ) )
{
DDCAPS caps;
memset(∩︀,0,sizeof(DDCAPS));
caps.dwSize = sizeof(DDCAPS);
hres = IDirectDraw2_GetCaps( DDraw, ∩︀, NULL );
if( hres == S_OK )
{
// Return megabytes
vram = caps.dwVidMemTotal / (1024 * 1024);
}
IDirectDraw_Release( DDraw );
}
FreeLibrary( DDrawDLL );
}
return vram;
#else
#error Unsupported platform
#endif
}
Display a simple message box
void MessageBox( const char* title, const char* message )
{
#if defined( __APPLE__ ) && defined( __MACH__ )
Str255 strTitle;
Str255 strMessage;
CopyCStringToPascal( title, strTitle );
CopyCStringToPascal( message, strMessage );
StandardAlert( kAlertNoteAlert, strTitle, strMessage, NULL, 0 );
#elif WIN32
MessageBox( NULL, message, title, MB_OK );
#else
#error Unsupported platform
#endif
}
Video playback in Windows/Mac OS X
It is unusual to include videos in indie games because they increase the download size noticeably, but just in case you need to, here are a couple of links that will teach you how to render AVI files in OpenGL:
In order to avoid dependencies, I recommend using the standard CinePak codec for AVI files, which is included in all versions of Windows and Mac OS X.
Common non-portable C functions and their alternatives
During your development, you will probably found out that there are some C functions that are not present in both Windows and Mac platforms. Three common non-portable functions are:
round()
You can easily implement your own version as: int Round( float x ) { return( static_cast Is the same as: Is a Microsoft specific routine. Use sprintf() instead. Thanks to Lord Trancos for pointing out the SDL source code as a useful resource to obtain the GetInstalledVRAM() code for Windows. Send any questions and comments to jgf8@alu.ua.es log2()
log( x ) / log( 2 );
itoa()
Greetings
Resources
Related Tutorials
Balancing Game Development and Creative Direction in Indie Production
A practical look at how indie developers can balance creative direction with hands-on game development. This article co…
My Unreal Engine Development Process: From Core Idea to Playable Build
A practical overview of my Unreal Engine development process, covering how I move from a core game idea to a playable b…
Introducing LaneGraph: The Ultimate Road Network Solution for Unity
Discover the power of LaneGraph, a lightweight and flexible lane-based navigation system for Unity. LaneGraph makes it…
Retargeting Mixamo Characters with Root Motion In Unreal Engine 5.4.
I have always found Retargeting Mixamo Characters To have Root Motion is a serious lengthy Tast, Recently I stumbled up…
How To Make A SIMPLE Main Menu In Unity
In this tutorial for unity, i go over how to make a simple main menu for unity, it's an unlisted video because i do not…
Guide to Gameplay Balance
A perspective on competitive gameplay balance, from a background of "shooter" sandbox design.
Discussion
More from Julio Gorg
Comparing Shadow Mapping Techniques with Shadow Explorer
New Incentives and a Whole New Platform From The Intel AppUp developer program
The final installment in this series on Intel's AppUp program details additional incentives and opportunities for devel…
The Game Maker
This book excerpt contains the first chapter of the book that introduces beginning game developers to the Game Maker pr…
Discussion