Hacker News new | ask | show | jobs
by FaceKicker 4885 days ago
As someone who's never done any game development at all, can you give me some sense of the work that would be involved to port a Windows-only OpenGL game to Mac or Linux? What pieces of it would need to be redone or significantly overhauled?

I would have expected it would be quite minimal compared to the work involved in developing the game itself, but I guess I must be wrong if there are "many" Windows-only OpenGL games.

2 comments

Sound. Networking. Decent async file I/O. Threading libraries. Dynamic loading of components. Anti-cheat techniques (or any other security stuff you might need). Device input. Choosing and supporting a platform (and the follow-on customer support issues). Diagnosis of customer problems (because they _will_ have them).
Sound: OpenAL abstracts this decently. If you're not using it or an equivalent, you're doing it wrong.

Networking: Most folks building a bespoke networking layer seem to go with ENET, which is cross-platform.

Async file I/O: yup.

Threading libraries: something wrong with Boost Thread? (Boost gets coroutines, too, in 1.53, which I'm pretty excited about.)

Honestly, the biggest problem I see in writing a cross-platform game is device input. Trying to build a joystick/gamepad-based game for Linux and OS X are pretty painful. Fortunately I've lucked onto GLFW as a windowing toolkit, which handles the HID Manager boilerplate and other badness for them.

You can also just use the sdl, which provides abstractions for network, sound, graphics, and input. If you hit snags, you could just commit back the fixes to sdl proper. I've used it a bit and I have had good experiences so far with successful cross platform builds.

It also supports Android, so in theory you could almost have one code base with only a UI and input revamp for Android target every PC os.

SDL is a thing, I guess, but I personally have little use for it. I mean, I've tried it, of course; I'm sure most people have. But, and maybe it's just me, but if I'm going to have to do the legwork of wrapping some C API into a decent, lifecycle-manageable object model, I'm probably going to use the lowest-level one I can so I can state with authority that I fully understand what everything in my stack is doing at all times. Like, OpenGL's C API is super gross, but only very slightly less so than dealing with SDL. And while, sure, "you can commit the fixes back to SDL," you first then have to go unwind their abstraction to actually understand what the hell it's doing--which for me, given the relatively small feature set I need, is almost as much work, if not more, than writing it yourself.

Also, SDL 1.x is LGPL (instant dealbreaker, I build with static libraries on a Mac to avoid dylib hell) and SDL 2.x isn't done. So there's that, too.

In the spirit of abstraction and not having to build the object model I'd get for free with Direct3D, I used SFML for a while; the general idea of it is promising, but the abstraction is janky, it's desktop-only, and I still have a bitter taste in my mouth from the way they handled showstopper bugs in SFML 1.x as far back as three years ago: "Completely reproducible crashes on all modern ATI cards? Just upgrade to our incompatible 2.x alpha!". (2.0 still isn't out, which makes it super groovy.)

.

I now use GLFW for windowing/input, ENET for networking, and PhysFS for I/O; I can pretty easily use each of them in a way that maps pretty well to my own preferences for an object model and a mental model. Probably not scalable (for a multi-person project or a 3D game I'd almost certainly use OGRE rather than doing it myself), but nice for my purposes.

The only part of my codebase that isn't pretty trivially platform-independent right now, without any special effort, is in "platform.cpp", which does the tremendously difficult work of finding me the user directory and the appdata directory. =) I sure haven't done anything special to make it build both in Xcode (my primary environment) or Visual Studio.

OTOH, SDL2 is developed by Sam Lantinga, currently an employee at Valve (IIRC), so this is probably the most promising library of the three you mentioned.

For one, it [SDL2] uses XInput2 for relative mouse input on X11 (and Raw Input on Win32), which is soooo much better than the classic WarpPointer mess.

Another thing, it is really preferable to put libSDL shared library next to your executable, not compile it statically, at least for Linux builds. Quite a number of problems with old games running improperly on erm...modern Linux desktops are solved by swapping the bundled libSDL for distro-provided version.

I'm speaking specifically about windowing/input part of SDL, have zero experience with other parts.

The main difficulty in porting has less to do with OpenGL itself and more to do with the number of platform-specific issues you encounter when you're trying to port code that is highly optimized for specific platforms.
Interesting, can you give any examples of these issues?
They're almost all program and language dependent. If your game doesn't use threads, you don't have to port anything to do with threads. If it does, but you use Java or C++11 and their platform independent thread libraries, you (ideally) don't have to port anything to do with threads. But maybe you used C or C++98 and now you have to run around putting in ifdefs for CreateThread vs. pthread_create and debugging subtle differences between Win32 and POSIX threads, etc.

Or maybe you decided to write the whole thing using multi-platform libraries like Qt in the first place, so that you don't have to change hardly anything. Or maybe you wrote it in Visual Studio using .NET heavily and you have to practically rewrite everything from scratch. It's totally dependent on the decisions you made when writing the original program.

In addition to what AnthonyMouse said, it also gets a bit more complicated than that. If you have a high performance game engine, it's very likely that the inner loops are written in assembly to squeeze every last drop of performance out. The guys who write this code are optimizing for the OS's memory handling behaviors, aligning data to fit into cache lines, using SSE instructions for faster matrix multiplications, and all sorts of other exotic techniques that "mere mortals" don't even think about.

So when you change platforms from, say, the Xbox 360 to the PS3, those assumptions you made about the OS, the CPU, the chipset, and other minute details are suddenly completely, horribly wrong. So the guy who wrote all of that highly optimized code has to write it again to optimize against a completely different set of quirks.