![]() |
![]() |
![]() ![]() ![]() |
Portability, in my opinion, is one area of game programming that is least paid attention to/most thoroughly neglected.
This text aims to dispell many myths around that programmers believe which is their reason for thinking it's futile to even try to make portable code.
Cross-platform compatibility sounds insane for games usually. Why (or how) on earth can a program that requires direct access to hardware run on different systems/machines? Why would you even want to try?
It sounds unreasonable, but some companies (id Software for one) do it all the time, as much as possible. Portable code has several advantages that most developers fail to see/care about.
Development environment. Probably one of the most essential reasons for writing portable code. There are probably plenty of better development enviornments avaliable for platforms OTHER than the one you are directly working in (the grass is greener on the other side effect), ignoring these other environments is rather foolish in it's own light. You're passing up the oppurtunity to make your game the best it can be. (kind of like owning the all of the grass in the neighborhood).
Quake (I'll be referring to Quake a lot) was developed on a combination of Linux and NeXTStep, yet you'd swear it was native to DOS from the ground up. NeXTStep and Linux are both superior development environments compared to DOS/Win32, I don't see how one can debate that.
If you don't believe this, give them a try, they're a programmer's dreams. They allow programmers to get deeply in touch with their environment, either with an easy to use API or the ability to do anything they want to their code, and when you're comfortable, you can usually work more efficiently. (NOTE: NeXT will now become Rhapsody, which might have the same development environment as NeXT. Developers who have the releases claim it's just as great. Watch it to see what materializes)
Sales. If you ever plan on selling your work, leaving your game open to as many targets as possible might make the potential buyer who happens to be a MacOS addict go out and buy the game if their platform is supported. Sure Win32 is the broadest platform for reaching users, and you want as many users as possible to enjoy your work, wouldn't it make sense to offer your game to as many people as you can? Portable code can make this easier to achieve since expecting others to ditch their OS just to play your game usually isn't going to happen.
Respect. Writing portable code earns you respect, plain and simple. John BeOS User will appreciate you more if your game can run on his system, instead of seeing requirements that say "DirectX Win95 only". That's just annoying, and you'd seem like a Microsoft lapdog. Half of the reason I respect John Carmack is because his code is so damned portable. I know I'd respect you just the same.
Egotism. The ego boost is wonderful. You are the Warrior and code is your weapon. You can defy the limits of any system and the restrictions of any machine. Your code runs in it's own universe. If a platform dies, your code still lives because it does not need it to live. Your code isn't a parasite. This is true freedom. Do you deny your code basic civil rights?
Myth:
Porting code to other Systems is hard and a long drawn out process, usually requiring many extra expendatures and debugging.
Fact:
Absolutely not!! This is one of the most horrible myths ever started in this industry, probably by companies who don't want a particular platform supported because of strategic commercial advantage rather than actual expendatures. This used to be true, back in the days, because most (game) programming was done largely in assembler, but in this day and age, where a lot more code is written in C, so hence it's not an impossibility. All that is required is a reasonable well organized design plan. You already have an organized game design plan, so fitting this in shouldn't, be a problem.
To put this into some sort of perspective, recently, some thief on the internet who was passed along a copy of Quake source, was able to get Quake working under Linux in 24(!) hours, his work ended up becoming the base of squake, which is now supported by id (indirectly). The programmer takes very little credit for doing it himself, stating the real commendations should go to John Carmack for making it so easy to port. (The thief was never arrested and is currently at large)
Tweny Four hours. Almost instant gratification.
He put in about 100 or 300 lines of his own code. How much is ~200 lines? Not very much, relative to a time/cost scale. Could you live with (re)writing a couple of hundred lines of code to get your game working on another Operating System? I sure could.
As far as debugging goes, it took about a week in competent hands to get working smoothly. Not too horrible, and Quake suffered no speed loss whatsoever (it gained 1 fps on average in fact under Linux).
What about "DirectX"? And "MMX"? and "insert cool propriety thing here". Won't making my games portable force me to give these things up?
Not at all. It's all about modularity.
Interesting side note. Compare the marketing practices of successful companies to unsuccessful companies. One of the clearest signs of a developer that is in fear, (because of general incompetence or lack of faith in their design staff) is one that constantly boasts that their game is MMX enhanced and whatnot. They continuously throw around buzzwords in the hopes that someone will say "oh, I have MMX! I should get this game" If your game is truly free and your skill true, you don't need to boast about such things, because if you wanted to add MMX functionality or port it to OpenGL/3Dfx, or get it working on an Alpha, you could do so by simply rewriting a module or three. With good knowledge of the platform, it shouldn't take you long at all.
Consolidate your code. This is one of the most principle rules of programming, and often aids in debugging and program modification. Don't sprinkle system dependant calls or embedd machine dependant assembler throughout your code.
It's all about dedicating certain parts of your codebase to a specific task. Almost like data hiding if you will. The only way to access these specific parts is through a cleanly established interface.
Lets say we want to write a portable graphics module.
First, think over your design, document what abslutely must be at the lowest level. Gather a nice collection of these functions that absolutely must be system dependant, and create an interface to them.
Then you'd want to flesh out this interface. For drawing, what do you really need? Video mode setting code, access to video memory, and changing the palette. The basics.
Granted, your game might be more complex, and require exotic access to this hardware. Try to get a feel of what systems you want to bring this to in advance, and find a compromise, you might have to implement a little more than just the basics, but if it's anything overly complex, you might be doing something wrong.
Store this interface (prototypes and structures) in a header file that all of your implementations will conveniantly include. For our purposes, lets call it "gfx.h".
Keep in mind, your rendering engine, should it make video-related calls, should only use the interface outlined in gfx.h, don't use anything defined outside of this scope, or you make your code harder to port.
In the implementation, you'd make a module, called gfx_svga.c or gfx_directx.c (depending on what you aim for), and define all of those functions you outlined in gfx.h Here is where you can go nuts, embedd all the assembly you could ever want, and be as dependant on the platform as a heroin addict is to crank.
You're practically wrapping the system dependancies in code that will act as a black box according to your rendering engine no matter what system it's on.
As I'm sure you're aware of, the goal is to make as many modules as system nuetral as possible. If a module isn't writing to video, or handling sound, or polling for input, or maintaining a network connection, it SHOULD not make any system dependant calls. You should only really need the ANSI C library at most, and if you find yourself needing video/sound/input access, you do so through your system dependant modules. If you find they don't supply what you need, it's time to rethink your attack plan or include redesign some of the modules.
Once your game has been released, (after much fierce coding) you will be ready to start writing ports. Move all of your code over to another platform, and get busy.
Of course, your system nuetral modules should compile without flaw if you're using a (ANSI) standard development enviornment. Now, you'd just simply go about rewriting the system dependant code, while leaving the interface -completely- intact.
Hell, you might just want to pay someone else to do it.
Some people will even do it for free if you give them due credit.
You now rewrite all of the mode setting and screen writing and critical system dependant code, compile and link it into your nuetral base, and you should be able to run it without flaw. Granted, there will be some wacky problems here and there, but they should be managable.
This isn't as thrilling as brainstorming an idea, and then rushing out and laying down lots of code, because you need to define a consistent interface to the system, and stay with it, but in the long run, this will pay off.
Perhaps this stuff sounded highly trivial to you. It probably did, because it sounds as trivial as hell to me. If this is the case, then why does this document even exist? Why aren't there any portable games? Can't figure it out hmm? Niether can I!
One of the reasons I can see though, is that the majority of programmer's write for the platform they use (naturally). As a programmer, you should be seeking out newer and better things. Find platforms that you might be comfortable developing your tools in, and use those if need be. There's always things to be learned in new terrain, and isolating yourself to a single platform isn't a good idea in this era. Linux is quite an affordable solution, and I urge all programmers to try it, whether they care about portability or not.
Ignore the temptations of companies that try to lure you in with "development kits" and other general system dependant trinkets, your code will quickly come to be dependant on that platform and you won't have any chance to escape should you find something unwanted.
While I have the mic, might I reccomend the technical superiority of OpenGL over Direct3D. Give it a try, if you don't agree that it is one of the coolest things you've ever used, you'd be better off with Direct3D anyway. :)
Porting code is made out to be harder than it really is. It can be done, and it should be done. Now that you've read this, I expect you to make the right decision.