Saturday 6 September 2008

More work on STPPC2x

I've fixed some quite important bugs in STPPC2x today.

First, I've been doing Valgrind runs on the code, which has picked up on quite a few little bugs here and there - I didn't free this memory, I lost the thing a pointer was pointing too, I extended outside the boundaries of this allocated memory etc. It's only a game for a handheld, so it's not security-critical but it's always nice to fix something that shouldn't happen, even if it only happens rarely, or it has zero actual impact on the code.

At least one of those bugs left a few hundred thousands bytes of bitmap or fonts in RAM. Not a big deal, because the libc clears up enough after the game is quit, but (in theory) if you were to run enough games inside STPPC2x one after the other, you'd run out of RAM. That's still possible but extremely unlikely now because the only memory leaks left are in SDL libraries and the like and so will affect all GP2X software. They are on the order of 20-30 bytes of lost memory each time, so it'd take months of constant playing without quitting, batteries running out, power going off, etc. to make a difference.

I also fixed two long-standing display bugs. Many people noticed that Solo (the Sudoku puzzle in the collection) wasn't drawing properly. And, if you look carefully, you might notice that several puzzles were drawing a bit awry. There was an off-by-one in the drawing of any rectangles (which are used is virtually all games, even if they are just the "background" for a circular or triangular object) which meant that everything looked slightly off and the Solo's cells "overlapped". That's now fixed. I must have misread or miscontrued the documentation for the puzzles and SDL_gfx because I was sure that I had looked at this several times and it was coded as it was supposed to be.

The other bug was a bug in drawing circles for which the puzzle only wanted the outline (i.e. no "fill" colour). This showed itself most in "Inertia" where the stop-points were dark-red pie-slices when they should have been mere one-pixels arcs. By sheer stupidity, the fill colour for a "empty" circle used colours plucked out of a random location of memory because of a signed overflow in the function. A short, one-line check and I fixed it.

In previous versions, none of the GP2X puzzles looked like their screenshots, if people looked carefully. That's because the screenshots were taken from GTK versions. Now, they are pixel-perfect (I hope) and the same as the GTK screenshots or, indeed, the screenshots of any other version of STPPC.

I also fixed a possible palette-crash that I think I may have introduced myself quite recently. Always check your array boundaries! This was caught by Valgrind, again, and I'm quickly finding Valgrind an invaluable tool when debugging. GDB can get you to the line where a problem occurs, with a small backtrace. Valgrind tells you why the thing crashed and where the relevant parts of the code are - only for memory, overrun and similar errors but it's damn helpful. Valgrind has also found multi-threaded locking problems in the latest version and numerous other bugs.

I also did a quick Valgrind "Heapcheck" run on the code. This checks how much memory it *actually* allocates, rather than trying to guess from what's left over in memory. STPPC2x uses very little memory, a lot less than I supposed. A single session that played over 50 games of various types never went much past 5Mb heap usage with the default config options. Although I consider that quite a large amount of memory for a basic game to use, I was quite impressed - that means that on default settings it uses less than 1/7th of the standard memory available on the GP2X.

I played with a few bits to enable background music. Unfortunately, the GP2X is a little underpowered and stutters on the difficult game generations, or if a move is particularly graphically-intensive. I'm sure there are ways around it with larger buffers, seperate threads etc. but for now I've put it on a backburner - it works, but it's not good enough yet.

The code loading game presets (i.e. difficulty levels) is working really well now - I haven't had a big problem in that code yet. As part of that, I've added a "special" preset which is an extension of the "save config" functionality of the older versions. Basically, you can save *your* favourite difficulty as a preset and have it load up every time you run that game by default. This did present a small logical problem though - what if you accidentally set it to a difficulty so hard that it takes the computer forever to generate the puzzle? You can't get into the game to change the option until it's generated the puzzle!

Fortunately, I've put in a little facility for that - pressing L&R on the list of games will delete your custom settings so that you can run the game with it's (safe) defaults. The keys and mechanism for this might change over time (for instance, I may have it so that if you start a game while holding down a certain button, it just ignores your config instead of removing it).

On the subject of correcting mistakes, I've also put in "Undo" and "Redo" buttons. These work fantastically and let you roll back and forth in the history of the game you're playing. It's something I never use in these games and nobody had asked for it, but the facility is there so it was only sensible to use it.

The new in-game menus are coming along nicely now - there are one or two layout quirks but nothing that can't be fixed and a few places where I really need to ask the user "are you sure?", but it's working well.

All in all, things are coming along smoothly and it's gradually looking more and more like a v1.0 release. I have a lot more "big" items on the agenda before that point but I'm very pleased with how much better it's looking now that I've had another spate of programming on the project.

No comments: