Posts Tagged ‘SDL’

Shadowgrounds: A surprise release

Wednesday, September 16th, 2009

Well, a lot of you have been waiting for Shadowgrounds Survivor. For all of you waiting, we have a nice surprise for you.

Late in the porting of Shadowgrounds Survivor, it became fairly clear that it would be little work to also bring the original Shadowgrounds game to Linux. We discussed it with Igios, who were doing all the hard work, and we decided that we would also release Shashadowgroundsdowgrounds.

But, being the sneaky Linux Game Publishing company that we are, we decided to keep it secret. I guess, I just wanted to give everyone a nice surprise, and get a new game out that none of you were expecting. As it has the same game core as Survivor, it didn’t need the extensive beta test, making it one of the few times we would be able to release a game without a beta to let you all know it was on the way.

Later this week we will be releasing Shadowgrounds Survivor, and so we felt that the best thing to do for Shadowgrounds is to make it a budget title on release. We have decided to set the retail price at just £10, partly because it was easier to port and so the price being lower is fair. Also, and I’ll be honest here, I want lots of people to buy it, get hooked on the gameplay, and just feel that urge to buy the higher priced Survivor. I’m not going to claim to be completely altruistic, we ARE a business afterall {:-)

Now, one thing that will disappoint some players is that neither Shadowgrounds, nor Survivor, come with the co-op multiplayer option that Windows has. This is because of a conflict in the game design, and the design of SDL. It is actually technically impossible to provide the multiplayer (which on Windows requires two keyboards and two mice) with the architecture as it stands, and by the time we realised this, it would have required a complete rewrite of the whole game core to get this working.

However, good news, is that the next version of SDL will contain all we need to get co-op into the game, and Igios has committed to releasing a patch to provide this functionality as soon as SDL can do it.

Shadowgrounds has taken a lot of dedication from the guys at Igios, so I’m counting on the community to do their bit, and buy the game, give them some thanks for the long hours of work they have put in to bring this game to you. You can buy it boxed, or it will be available to download, either for purchase or rental.

  • Share/Bookmark

Handling misbehaving libraries in binary products

Tuesday, August 18th, 2009

It is a bit of an arcane artform, making a game that runs on all Linux versions. We do quite well at LGP but there is always room for improvement.

Recently, we came across an issue with PulseAudio (I will rant about Pulse in some other post). It became almost impossible, due to the architecture of alsa, and the combination of our build environment, and our higher level sound libraries, to make sound work – pretty much at all, in Linux games. Those of you with older games will know that for a while they all stopped having sound. Some of them we still haven’t released patches for yet (they will be forthcoming).

Now, one of the big problems was that sound libraries (such as OpenAL or SDL) go through their own motions of opening sound. We have no way of directly controlling what they do or how they do it. This is a common feature with many libraries, they will load their own dependencies in a way we cannot control.

The biggest problem is that OpenAL and SDL try to dlopen libasound, and on some machines, libasound doesn’t work with our binaries. On others, it can actually crash the whole game due to incompatibilities. This is a common issue when dealing with unknown system configurations when sending out a binary-only product into the world. You never know just what peoples systems will have installed, and just how they may confuse the situation. But you cannot just say ‘well, bad luck, it crashes on your machine’, people will be understandably upset.

We came up with a rather horrible system to make this work, and one that I hope may be of use to those of you who come here for our technical insights. This system is deliberately designed to work with libraries that have the potential to actually crash a program. As a simple example that many here will follow, I am using SDL’s audio system as the target, and using it to test whether ALSA works or crashes the program.

  static int system_asound_ok=-1;

  if (system_asound_ok==-1)
    {
      forkval=fork();
      switch (forkval)
        {
        case -1:
          //This is an error, we couldnt fork() so we just say no to
          //system openal working
          system_asound_ok=0;
        case 0:
          //This is the child, try and run the open, and then close and exit
          {
            //Your code here to remove whichever signal handlers you have set up
          }
          fail=SDL_InitSubSystem(SDL_INIT_AUDIO);
          if (!fail)
            SDL_QuitSubSystem(SDL_INIT_AUDIO);
          //MUST use _exit here not exit
          _exit(0);
          break;
        default:
          //This is the parent, wait for the child to exit somehow
          waitpid(forkval,&fail,0);

          //The child has now exited somehow, check how
          if (WIFEXITED(fail))
            {
              //The child exited ok, we can try and use the system library
              system_asound_ok=1;
            }
          else
            {
              //The child probably crashed, dont try and use the system library
              system_asound_ok=0;
            }
        }
    }

At this point you know whether the system asound (ALSA) library is safe to use.

This is a truly truly horrible system, when you actually have to allow an application to crash, you know something is wrong, but sometimes there is no option.

As a technical note, note the use of _exit() instead of exit(). This ensures that when the program ends, no atexit() functions are called. Using exit() could mean things like SDL’s cleanup being called, or who knows what else!

Signal handlers should be removed at the point in the code indicated. They interfere with the proper signaled exit of the program and will prevent WIFEXITED from detecting a crash properly. Bear in mind the signal removing only happens in the child process and will not affect signals in the parent.

So, what can you do knowing that the system works or doesn’t work?

Well, knowing that it works, you can simply run the initialisation as it stands and enjoy the working library.

If you know it fails, you can either skip this system altogether (in this case run without sound) or you can switch to another library. If you setenv an LD_LIBRARY_PATH this will influence the path that dlopen looks for libraries. LD_LIBRARY_PATH is searched before any other directories, and so will override the default location of the library. This means, in this instance, that SDL_InitSubSystem will dlopen the libasound.so in the location you have set the LD_LIBRARY_PATH to.

I hope this will relieve some headaches for some developers out there. It is always difficult making any application when you do not know what the target system will have installed on it. Of course, we can always say ’sorry, you need a specific version of this or that library’ but when you have just bought a game, that is the last thing you want to hear, and so – we have to jump through some hoops to stop that happening.

  • Share/Bookmark

Our new way to meet the LGPL

Sunday, February 8th, 2009

Hi again, and welcome to our next technical article. This is a mix of technical and legal, but as I know many of us in the open source community are very serious about the licences we work under, I thought you would like a little background reading to lead you up to a really neat and little-known feature of the GNU linker (ld) that we have just adopted.

For years, LGP has been working with libraries such as SDL, ffmpeg, and others that are licensed under the LGPL (GNU Lesser General Public License). Without these invaluable tools from the open source community, LGP would not exist, and nor would hundreds of open source projects.

The LGPL states that an application that links against an LGPL library is not bound by the LGPL itself, but then goes on to qualify this, and make exceptions, and even itself states that the boundaries between what counts as simply linking against a library, and what counts as a derivative work, are ‘not precisely defined by law’.

The problem we have always faced is finding a way to make sure the game is portable. To do this you MUST make sure that you are using a known version of as many libraries as you possibly can. There is no point in exhaustively testing a game against SDL 1.2.12 when next week SDL 1.2.13 comes out, changes a few of our assumptions, and means the game crashes. Multiply the problem by the number of versions a library has, multiplied by the number of libraries a game links against, and you can see why this is a big problem. And so, we like to make sure we build the game, test the game, and run the game, all against exactly the same libraries as the end user will use, in as many cases as is possible.

Since the beginning of commercial Linux games, the common practice has been to create a release of each game such that there was a static and a dynamic linked version of the game in each release. The dynamic version of the game would be completely in compliance with the word and spirit of the LGPL, using the users own system libraries, while the static linked version of the game was released because linking the libraries directly into the game ensured we knew which libraries were being used. The statically linked executable though, was really not very much in the spirit of the LGPL. We always got away with it because we included the exact same game in full LGPL compliance,and because of the wording of the LGPL, it was fairly ambiguous as to whether this was allowed. But even so, we were never happy with it. Loopholes are not something to be proud of using.

There was another method of course. The other method involved forcing the game, via the LD_LIBRARY_PATH to use libraries in a certain directory. However that had issues of its own. To do this you either have to tell the user ‘before you start your game type this long command into the commandline’ or you start the game from a shellscript. Shellscripts are all well and good, but they bring problems of their own, such as (for security) making changes to the euid, resetting values from /etc/profile, and of course, assuming that the shell in use has exactly the same syntax as the shell at the time of release. It was decided that because of this, and many other issues, starting from a shellscript was too much of a risk for portability and was ruled out.

And so, we were left with the method that has been being used for the last 12 or so years. That is until recently, when we found a nice new way to fix this problem once and for all.

Most people are probably unaware of the linker option, -rpath. Most of you don’t ever need to be. This option lets you tell an application where to look for libraries. It works just like adding a new path into the LD_LIBRARY_PATH. Great, but it doesn’t really help like that. It is set at compile time and so we would need to restrict installation to a known directory on everyone’s machine. Obviously unacceptable for most users.

And so the problem remained until one of our devteam discovered a neat little trick that isn’t even documented in the manual for the linker. You can use a special keyword $ORIGIN to say ‘relative to the actual location of the executable’. Suddenly we found we could use -rpath $ORIGIN/lib and it worked. The game was loading the correct libraries, and so was stable and portable, but was also now completely in the spirit of the LGPL as well as the letter!

For those of you a little newer to compiling under Linux, some of you may not even be aware you use the ld linker. It is done automatically by gcc for you. If you are simply using gcc in a Makefile, it is a little more difficult in syntax, but as a hint you would change an example Makefile line that started like this

gcc obj1.o obj2.o -o my_application

to be

gcc -Wl,-rpath,\$$ORIGIN/lib/ obj1.o obj2.o -o my_application

So, that’s the neat little trick I thought I’d like to share with you, maybe it will help some of you out there to organise the way your projects run, as of course it isn’t just useful for closed source, this is useful for any project that has to use a specific library version in order to work properly!

  • Share/Bookmark