Jump to content

  • Log In with Google      Sign In   
  • Create Account


Like
0Likes
Dislike

Handy PC/Mac OS X Snippets for Indie Development

By Julio Gorgé, Pablo Pérez | Published Jan 09 2006 06:40 AM in Game Programming

If you find this article contains errors or problems rendering it unreadable (missing images or files, mangled code, improper text formatting, etc) please contact the editor so corrections can be made. Thank you for helping us improve this resource




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 );

  <span class="codekeyword">if</span>( !CFNumberGetValue( (CFNumberRef)CFDictionaryGetValue( desktopVideoMode, kCGDisplayWidth ),

                         kCFNumberIntType,

                         &width ) ||

      !CFNumberGetValue( (CFNumberRef)CFDictionaryGetValue( desktopVideoMode, kCGDisplayHeight ),

                         kCFNumberIntType,

                         &height ) ||

      !CFNumberGetValue( (CFNumberRef)CFDictionaryGetValue( desktopVideoMode, kCGDisplayBitsPerPixel ),

                         kCFNumberIntType,

                         &bpp ) )

  {

    <span class="codecomment">// error, return default values

    // ...</span>

  }

#elif WIN32

  DEVMODE desktopVideoMode;

  ZeroMemory( <span class="codekeyword">reinterpret_cast</span><DEVMODE*>( &desktopVideoMode ), sizeof( desktopVideoMode ) );



  <span class="codekeyword">if</span>( EnumDisplaySettings( <span class="codekeyword">NULL</span>, ENUM_CURRENT_SETTINGS, &desktopVideoMode ) )

  {

    m_desktopWidth = desktopVideoMode.dmPelsWidth;

    m_desktopHeight = desktopVideoMode.dmPelsHeight;

    m_desktopBpp = desktopVideoMode.dmBitsPerPel;

  }

  else

  {

    <span class="codecomment">// error, return default values

    // ...</span>

  }

#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> <span class="codecomment">// Needs DirectX SDK(>=5), or at least ddraw.h in your path</span>

<span class="codekeyword">typedef int</span> (WINAPI *MYPROC)(GUID *,LPDIRECTDRAW *,IUnknown *);

#else

#include <Carbon/Carbon.h>

#include <AGL/agl.h>

#endif



<span class="codekeyword">const int</span> GetInstalledVRAM( <span class="codekeyword">void</span> )

{

#ifdef __CARBON__

  AGLRendererInfo info;

  GLint           vram( 0 );

  

  info = aglQueryRendererInfo ( <span class="codekeyword">NULL</span>, 0 );



  <span class="codekeyword">while</span> ( info != <span class="codekeyword">NULL</span> )

  {

    <span class="codekeyword">if</span>( aglDescribeRenderer( info, AGL_VIDEO_MEMORY, &vram ) == GL_TRUE )

    {

      <span class="codecomment">// Return megabytes</span>

      <span class="codekeyword">return static_cast</span><int>( vram / (1024 * 1024) );

    }

    info = aglNextRendererInfo( info );

  }



  <span class="codekeyword">return</span> 0;



#elif WIN32



  HINSTANCE DDrawDLL;

  int vram ( 0 );



  DDrawDLL = LoadLibrary( "ddraw.dll" );



  <span class="codekeyword">if</span>( DDrawDLL != <span class="codekeyword">NULL</span> )

  {

    MYPROC DDrawCreate;

    LPDIRECTDRAW DDraw;

    HRESULT hres;



    DDrawCreate = ( MYPROC ) GetProcAddress( DDrawDLL, "DirectDrawCreate");



    if( ( DDrawCreate != <span class="codekeyword">NULL</span> )

        && !FAILED( DDrawCreate( <span class="codekeyword">NULL</span>, &DDraw, <span class="codekeyword">NULL</span> ) ) )

    {

      DDCAPS caps;

      memset(&caps,0,sizeof(DDCAPS));

      caps.dwSize = sizeof(DDCAPS);



      hres = IDirectDraw2_GetCaps( DDraw, &caps, <span class="codekeyword">NULL</span> );

      <span class="codekeyword">if</span>( hres == S_OK )

      {

        <span class="codecomment">// Return megabytes</span>

        vram = caps.dwVidMemTotal / (1024 * 1024);

      }



      IDirectDraw_Release( DDraw );

    }

    FreeLibrary( DDrawDLL );

  }

  <span class="codekeyword">return</span> vram;

#else

#error Unsupported platform

#endif

}



Display a simple message box


<span class="codekeyword">void</span> MessageBox( <span class="codekeyword">const char</span>* title, <span class="codekeyword">const char</span>* message )

{

#if defined( __APPLE__ ) && defined( __MACH__ )

  Str255 strTitle;

  Str255 strMessage;

  CopyCStringToPascal( title, strTitle );

  CopyCStringToPascal( message, strMessage );

  StandardAlert( kAlertNoteAlert, strTitle, strMessage, <span class="codekeyword">NULL</span>, 0 );

#elif WIN32

  MessageBox( <span class="codekeyword">NULL</span>, 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<int>( x + 0.5f ) );
}

log2()

Is the same as:


log( x ) / log( 2 );



itoa()

Is a Microsoft specific routine. Use sprintf() instead.

Greetings

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

Resources







Comments

Note: Please offer only positive, constructive comments - we are looking to promote a positive atmosphere where collaboration is valued above all else.




PARTNERS