(This post was migrated from my previous blog. Originally published: 2007-04-19 02:45:20)
I had some good time hacking Battle for Wesnoth for my GP2X today, which I have not done in a while. As a result, I managed to make progress on the most pressing memory usage problems and with some help from alink, improved the image scaling script (used to resize images in tiny-gui mode) to reduce number of artifacts related to improper scaling (blurring) of alpha channel.
Memory (or lack of thereof) has been a problem since the beginning of Wesnoth for GP2X. It used to crash randomly early into the game and was completely unplayable. BfW can be pretty resource hungry and my little console has very little memory available compared to a typical PC. Also, it has no swap. Downscaled images require less space and I’ve already removed big parts of code which is not usable in my scenario, but the greatest problem lies in Wesnoth itself – it caches displayed images, but almost never releases this memory. As you may expect, cache grows over time as player scrolls around the map, browses help, watches story images, etc..
The first step was to determine how much memory is actually being used for graphics. I’ve written a simple wrapper for SDL functions that create and free surfaces to check it, and results have been rather frustrating: over 20MB of memory used in the first scenario of Heir to the Throne – way too much. As almost all images are being accessed via abstract locators with a get_image() function which also handles caching, a solution is simple. Adding an optional parameter determining if a given image should be cached and then using it for images which are rarely displayed reduced memory usage in first scenario of HttT to about 5MB, no matter what has been played before or how many help pages full of images have been opened. Dumb flush of cache at the end of intro sequences helps as well. Great success.
There used to be some problems with images scaled for the tiny-gui mode. Namely, there have been some annoying artifacts appearing on hex edges and small details have been rather blurry due to stray semi-transparent pixels. A slightly updated version of the script solved the problem. It now detects if an image has alpha channel and if that’s true, decomposes it, scales alpha without interpolation (RGB with bicubic, I think), and then combines everything back into one file. Visual quality has improved noticeably. Just in case someone needs it in the future, this is what it looks like (+/-):
convert -separate -channel A -filter point -resize 50% f.png fA.png
convert -separate -channel R -resize 50% f.png fR.png
convert -separate -channel G -resize 50% f.png fG.png
convert -separate -channel B -resize 50% f.png fB.png
convert -channel RGBA -combine fR.png fG.png fB.png fA.png final.png
The above sequence, however, was producing strange results on my system. As it turns out, it’s a bug in the latest version of ImageMagick available in my 64-bit Gentoo. Compare the two images:
“convert” utility from 32-bit Debian system:
“convert” utility from 64-bit Gentoo system: