Saturday 20 September 2008

Preview screenshots

Monday 15 September 2008

More version 1.0 news

Version 1.0 Checklist - Current Status

30 fully-working games (including Mines) - Check
Perfect display of the games - Check
Loading of built-in game presets (Easy, Medium, Hard etc.) - Check
Presets menu can cope with any number of presets - Check
Saving your own custom preset for each game, with automatic loading of the preset for that game ("I like net to start on a 10x10" mode) - Check
Ability to bypass the above if you want when starting a game - Check
Blackbox fix (so you can enter, e.g. 4-10 balls instead of a fixed number) - Check
Map fix (so you can see which "countries" were given to you at the start and are therefore locked) - Check
Loopy fix (so that you can still use the "old" presets which are much more playable than the enormous presets in the new code) - Check
Up to ten save slots can be loaded, saved and safely deleted from within the game - Check
Auto-save option so that whenever you quit a puzzle it is saved in a special slot and the same puzzle in the same state greets you next time you run that game - Check
Ability to bypass the above if you want when starting a game - Check
Cursor-key emulation available for certain games (sokoban etc.)
Latest SVN (including a more complex version of Loopy) - Check
Background Music - Check
Volume control - Check
Track list (up to ten music tracks, only turn on the ones you want to play, if any) - Check
Music can be replaced by any OGG file - check
Tweaked floating-point (decimal numbers) support in some games configuration options - Check
Screenshot feature on stick click (with options to snap whole screen or just puzzle area and settings in a global settings menu to hide certain elements) - Check
Game menu can cope with any number of games - Check

Hourglass cursors, credits screens, SVN version number in the title screen, updated text throughout, general help for keys, nicer menu system, smaller executable, smaller distribution (you can even remove the music, which doesn't need to be there), and a million and one tiny tweaks - Check

Basically the only things that remain on my list for v1.0 are "Interruptible generation", a new verson of malloc() and some random code-style, duplicated variables etc. that I can prune but which don't affect the games at all.

Interruptible generation for the games which are "slow" by default (which seems to be Filling and Slide) shouldn't be too hard at all. Moving it to every game will take a bit longer as they all have different generation strategies and it'll take a while to understand the code and find the bottlenecks.

It's also a little tricky to "recover" from a interrupted generation cleanly, but it shouldn't happen too often, so that shouldn't be an issue. Mainly, it's where the game allocated a ton of memory to generate the puzzle and I missed that it should be cleaned up.

The new "malloc" (which allocates memory for the games to use) may well be implemented for v1.0 depending on how easy it is to do. The games already use a "safe malloc" within the puzzle collection for all memory allocations, which leaves the opportunity to extend it to be able to use some of the Video RAM on the GP2X too. Basically, when a "normal" memory allocation fails, it'll be able to carry on and provide a bit of Video RAM to use instead and the games won't even know the difference.

The whole procedure would be transparent to the games, but provide them with up to 32Mb of RAM extra if they need it. I can't see many current games needing it will provide a safety barrier should they touch on the 32Mb mark. I'm looking at a new game (which probably will come after v1.0 if at all) that might well come close to that mark on it's larger settings. Once you add multiple fonts, PNG's loaded into RAM, OGG files, etc. it's better to be safe for the sake of fifty lines of code.

Anyway, version 1.0 is iminent and in a more-than-releaseable state as it is. I just want to playtest some more (the wife is very good at finding bugs accidentally), get those two more bits of code in and then it'll be released.

Thursday 11 September 2008

Feature-creep

Okay, so version 1.0 is slowly taking shape. Here's a few snippets of the smaller parts that are being worked on in between a lot of the "big stuff".

Firstly, there's a couple of things that I've put in there for my own use. For instance, there's screenshot code now, although probably the only person that will use that is myself. It's BMP-only (converting to PNG using libpng just looks way too complex to bother with) and I use it to verify the drawing is correct, to build the new animated GIF's for advertising the game and things like that. Unfortunately, because it needs to be able to activate at any time, this is one of those features that can't be slowly moved into the menus like almost every other new feature and requires a dedicated key. I've put it on Stick-Click for now because most people never press it (and it doesn't even exist on later versions of the GP2X), so it won't get in people's way.

It highlights a big problem that I have - the GP2X doesn't have enough keys! Unbelievable, I know! Excluding the basic up-down-left-right (whether as a "mouse" or "cursor keys") that are common to all the games, and the key-combinations I have for "safety" (e.g. L+R to quit back to the menu etc.) the "keys" required after moving almost everything into the Pause menu are:

Left-click (required in every game)
Right-click (required in a lot of games and sometimes essential to completion / player comfort)
Middle-click (only used in a handful of the games, and not essential to puzzle completion, but convenient)
Pause / Enter Menu
Decrease Digit
Increase Digit (the only way I could make unequal, solo, filling, etc. playable without a keyboard, but still not perfect).
Enter Digit
Undo
Redo

And the buttons I have are: A, B, X, Y, L, R, Select, Start. 8 buttons for 9 functions. So before release I'll be re-jigging all the keys. I don't want to move Undo/Redo into the menus but it's an option. I also don't want to shift a common key into a "combination" (e.g. at the moment I have L+VolDown for Undo and L+VolUp for Redo). I'd also like a key to switch between input systems eventually, so that for some games where it makes more sense to use a "cursor-control" system instead of a mouse-emulation one (such as fifteen and sokoban), the user can change between them at the press of a button.

Some "hidden" combinations need to be present to. Because the user can save their favourite configuration for each game as a preset, and that preset loads by default whenever they start that game, there needs to be a way to cope with two scenarios: The config save file gets corrupted, the config describes a game which takes an inordinately long time to generate. Imagine accidentally saving a config for Net, for example, that takes an hour to generate a game. You'd have to leave your GP2X on for all that time before you'd be able to change the options and play Net normally again. In fact, the easy solution is a little hidden feature - press L or R when loading a game from the main menu and it will completely ignore your preset. You can then get into the game ultra-quickly, change the options and re-save your preset if you need to.

At the moment, the options in the Pause menu are so numerous that they are now sub-categorised:

New Game
Restart Game
Solve Game
Configure Game
- View Presets
- Load "My Preset"
- {Load Preset X}
- {Configuration Option X}
- Save As "My Preset"
Help
- General help (Keys, etc.)
- {Game X} Instructions
- {Game X} Tips and Tricks
Global Options
- Music
- Track List
- Volume (including On/Off)
- Auto-Save Game on Exit
- Screenshots
- Include cursor in screenshot.
- Include status text in screenshot.
Credits & Licenses
- Puzzle Collection
- Third-party Games
- GP2X Port
- Music
Quit to Main Menu (the list of games).

I have decided on the background music I want and got permission of the artist - by strange coincidence, they own a GP2X so they'll be able to play the game with their own music. I've gone for some plinky-plonky ambient music - gentle, relaxing, simple. I'll also retain the ability for the users to replace or remove the music if they so wish - it'll just be 10 OGG files in a music folder. If they aren't there, nothing plays. If they are, they appear on a track list that the user can edit - so even if they don't like my choices, they can choose their favourite tracks to play while they puzzle. And, of course, there's the all important "Music Off" option.

General Updates:

The main menu shows the revision of STPPC that they are based on. This is so that people can see how old the collection is and whether it needs updating to support feature X of a certain game, or indeed any new games that come about. (There's a new, much more configurable, version of Loopy in SVN and it's already in my private version of 1.0 and working perfectly.)

The main menu is now complete and allows loading any of the 30 fully-working games (yes, 30, because Mines works now). It lets you go into and come out of the games as many time as you like without quitting back to the menu and is super-fast. I tried it on my GP2X for a laugh and after 200 entries and exits from particular games without quitting back to the main menu, I was suitably satisifed that I wasn't leaking too much RAM or risking a crash by playing that many games - this test included music, games with saved presets, full games, partial games, games with timers, loading/saving games, etc. A fairly accurate measurement of memory usage says that (with music off) the games rarely go about 5Mb of allocated RAM in their default configurations, although obviously most of them can be allowed to grow to silly sizes if you play with their config options. Without going too mad, I was able to generate "virtually impossible to solve within the GP2X's battery life" puzzles in all the games and didn't once get an out-of-memory error or crash. Although some of them nearly took forever to generate puzzles of that size!

Music works but may stutter on very difficult puzzle generation. There's not much I can do about this without increasing the size of the sound buffer - at the moment puzzle generation is an inherently single-threaded process and it tends to swamp the CPU and all other threads running. When interruptible generation is implemented (a BIG task), then it will hopefully solve itself because in the same place that I put code to check if the user wants to stop, I can refresh the music buffer.

I also know that Blackbox has a configuration option that can take values of the form "4-10" meaning "anything from 4 to 10". That's totally impossible to enter in the options menu in the current state (although you can happily use a Preset or hand-edited config file to play it!), but I may well hack on the Blackbox code to convert this to two configuration options: Min and Max. If you set them to the same number N, it's the same as just "N" in the config box, and if you set them to, say, X and Y respectively, it's the same as entering "X-Y" in the config box. I'll also be on the lookout for other similar options that allow such things.

Config-options are one of those things that are really finicky to convert to a non-keyboard device because they are expecting textual input all the time - the current GP2X code has always had a special "Kludge" switch that allows entry of floating-point numbers in, for example, "Barrier Probability" in net because otherwise you'd only have barriers everywhere or none at all. At the moment, such options are hard-coded in the GP2X code but I'm trying to find a nice way for the puzzles to support telling the so-called "frontend" whether a configuration option should be floating-point or not. It looks like I might have Simon Tatham's ear on that particular issue, however.

There's been a massive reorganisation of the files that the program uses. The folder structure is currently similar to:

Configurations/ (holds the game-specific INI files)
Documentation/ (holds various information about the collection such as licenses etc.)
Help/ (holds the various help textfiles)
Images/ (holds splashscreens and "game previews" that show in the menu)
Images/Screenshots/ (holds any generated .BMP screenshots)
Music/ (hold, erm, the music?)
Saves/ (holds all the savegames)
STPPC2x.gpe

So hopefully, there will be no more hundreds-of-files-in-one-folder and even the above folders should be as empty as they can be.

Finally (for this update at least), I'm looking at making a new game to go into the collection. It won't make it into the official collection, I'm sure, but I'm looking at the possibility of a simple overhead 2D maze game - I have some code that I can use for various "types" of mazes and solvers for them and I'm hoping they'll translate well to the small screen of the GP2X. That will be probably be a post-1.0 thing, though, because believe it or not, programming for that side of the collection is new to me!

Monday 8 September 2008

STPPC2X - "Mines" is now working!

Ah-ha!

Right, FINALLY. I got you, you mines-bast**d. FIXED. FIXED. FIXED. Version 1.0 will have working "mines"! Guaranteed.



Okay, for some reason, the particular version of gcc on ARM that the Open2x development environment uses does not treat an relatively-undocumented (and technically "broken") use of memset on the ARM platform the same as it does on x86. I think it's the alignment of ARM but I can't be bothered to check the exact technical details know that I have found it.

void * memset ( void * ptr, int value, size_t num);
Sets the first num bytes of the block of memory pointed by ptr to the specified value (interpreted as an unsigned char).


Notice the "unsigned char" bit. So when you do what mines.c was doing: memset(a pointer, -2, a number) it works perfectly on x86 (and all the other supported platforms, including MacOS, Palm, etc.) but does this on ARM:

"-1 -2 -2 -2 -1 -2 -2 -2 -1 -2 -2 -2"


Which buggers up mines! The fix is not to use memset but to fill the array manually - you get the proper result and mines no longer crashes but "just works". There were three places, only in mines.c, that do similar things. It seems to work fine for the other uses which are mostly -1's.

This fix was found by the following method:

1) Write original author of mines.c a long begging letter with lots of technical details on the problem
2) Recieve reply with basically says "No idea, can you print out the contents of X at line Y for me to look at?"
3) Edit code to print out contents of X at line Y on both PC and GP2X.
4) Gather debug logs from both platforms and compare.
5) Draft another long begging letter which says "This is what I got".
6) Just before hitting Send with large debug logs attached, notice that there is a pattern to the what-should-be-empty array.
7) On a hunch, gradually keep shifting the debug check higher and higher in the code, eventually placing it immediately after a memset.
8) Spot the problem (memset arrays aren't actually uniformly memset)
9) Google the definition of memset which includes the "unsigned char" line.
10) BELLS RING.
11) Search for all memsets with negative parameters and replace with for() loops.
12) Test on PC and GP2X.
13) Rewrite email to Simon Tatham, including a patch and problem description and press Send.
14) Kick self repeatedly and hard.

Anyway... it's fixed. Mines works. Finally. Can't believe it was something so stupid. Multiple human error, because obviously nobody who's touched the mines code had ever noticed the error before and only a compile on an ARM-based device showed it up. Patch winging its way to Simon Tatham for inclusion in the main code. Sigh of relief. Celebration game of mines.

Now, who's got the champagne?

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.