My favorites | Sign in
Logo
                
Search
for
Updated Nov 16, 2009 by pulkomandy
Labels: Developpers, Phase-Implementation
PlatformDependantCode  
Platform detection and platform-dependant code

Introduction

How to code in GrafX2 for one platform without breaking the others.

List of platforms

Symbols table for detection

#ifdefLinuxWin9x (MinGW)Win9x (Watcom)MacOSXAmiga OS4BeosHaikuAROSMorphOSFreeBSDGP2XAmigaOS 3
__WIN32__ X X
__MINGW32__ X
__WATCOMC__ X
__linux__ X X X
__macosx__ X
__amigaos4__ X
__BEOS__ X
__HAIKU__ X
__AROS__ X
__MORPHOS__ X
__FreeBSD__ X
__GP2X__ X
__amigaos__ X

Generally, you should assume a globally "unix" platform, and only put code in #ifdef block when you need to do something different for one platform.

Be careful that linux applies to MacOSX as well.

If you need to code a complicated kind of "switch", the cleanest way to write it would be:

#if defined(__BEOS__)||defined(__HAIKU__)
  // put BeOS/Haiku-specific code here
#elif defined(__amigaos4__)
  // put OS4-specific code
#else
  // put default alternative code here
#endif

System-specific

Windows

Environment variable: COMSPEC. This holds the path to the command interpreter (ex: C:\CMD.COM) The Makefile uses this variable to detect Windows build. Hopefully nobody sets it in an other system.

Environment variable: WINDIR. This holds the path to the windows drive and directory (ex: C:\WINDOWS). Used to find fonts. Directory separator: Windows filesystems traditionally use the character \ as a separator between directories, however / is also supported in almost all file i/o functions, and must be expected too.

Drives: An absolute file name begins with a drive name, from "A:" to "Z:". It is followed by a path separator, ex: "C:\GrafX2\gfx2.ini"

Amiga-like systems (AmigaOS 3 and 4, AROS, MorphOS

Drives: AmigaOS filesystem has volume/drive name. It can be a "technical" name like "df0:" for Disk Floppy drive 0, or a user-set name like "games:". The volume or drive is not followed by a path separator, ex: "mp3:Switchblade Symphony/Clown.mp3". This means that a directory name can be "something:", with no trailing slash. The parent directory is /, not .. like on other systems.

Endianness

SDL already provides reliable macros to determine the host system's endianness (Big-Endian like PowerPC, or Little-Endian like Intel) The syntax is

#if SDL_BYTEORDER == SDL_LIL_ENDIAN

#if SDL_BYTEORDER == SDL_BIG_ENDIAN

Don't use them. The only reason you need to know endianness is when you read or write data to disk, and all the necessary functions have been coded in io.c, in two forms : big-endian (Read_word_be()) and little-endian (Read_word_le()). Just choose the functions that have the right endianness for the file format (ex:GIF is little-endian, LBM is big-endian), and the functions will perform swapping as necessary.

Struct packing

It's not really a matter of platform, but a topic of interest for someone trying to make GrafX2 run on a new platform: Structs in C are not guaranteed to be contiguous in memory, the compiler can insert dummy bytes between struct members in order to align the members on 2-byte, 4-byte or 8-byte addresses, it can make the program faster. One platform ("Sparc" cpu) even requires padding to access the members at all.

The default behavior of Watcom C was to pack structures (Original code from 1996) The default behavior of gcc is to pad them, so 2-byte data is on address multiple of 2, 4-byte data is on addresses multiple of 4.

As you can guess, when porting grafx2 we ran right into this one. An early fix was to pack a lot of structures by marking them with an GCC extension attribute: __attribute__((__packed__)). Since then, to support big-endian cpus, all datatypes of more than one byte had to be handled individually for endianness anyway, the code now loads/saves them as individuel fread() and fwrite(), and thus the program no longer relies on having the structures packed.

Make dependencies

In release source packages, the dependency file (Makefile.dep) is packed with the sources, and may be used on a different platform than the one where it was generated. When this file is not up-to-date, you can get strange compilation or run-time time errors, that disappear only when you make clean and then make. To keep everybody happy, running make depend should generate an identical file on all platforms. It's not difficult, you only have to avoid including some grafx2 headers conditionally:

#ifdef __WIN32__
#include "gfx2win.h" // bad
#endif

If you have such situation where there is source file that is not needed for all platforms ("gfx2win.c"), include the header always, and in the header file itself, enclose all the declarations in a conditional #if.


Sign in to add a comment
Hosted by Google Code