Palm Icons

Volume 7, Issue 7; 16 Jan 2004; last modified 08 Oct 2010

Reaping the fruits of an evening spent in the joys of reverse engineering and gleeful hackery.

From a programmer's point of view, the user is a peripheral that types when you issue a read request.

P. Williams

My Palm date book application of choice is DateBk5 . Back when DateBk5 only supported black and white icons, I hacked together a little script to convert them to XPM files so I could use them on my laptop. Ever since DateBk5 began supporting color icons, I’ve wanted to do the same thing for them.

Motivated in part by my recent experiments in publishing itineraries, for example, for my trip to Tampa next week, I decided to have a more serious stab at tackling this problem.

The rest of this essay is a technical dive into the joys of reverse engineering and gleeful hackery. Because information not shared is information lost, right?

I’ve done this sort of thing before, the first bit of software I ever published was a shareware application called “SFWare” that manipulated HP LaserJet bitmapped fonts (called “soft fonts”, hence the name) in various ways. Later, I hacked together a tool to convert Windows and Macintosh icons into something I could use on my Unix desktop ( fvwm , if you’re interested).

For my Palm applications, I particularly wanted to convert the FM HiRes Icons. My first thought was, maybe the guy who published them already has them in some convenient format and I won’t actually have to do any work. Alas, no, a couple of email exchanges revealed that not to be the case.

So, onward to conversion. Experience and intuition suggested that the file of icons was probably going to contain a set of row-major arrays of bits, possibly compressed, with additional information about the icon dimensions and colors.

I bought a copy of IconManager , a Palm app for editing icon sets, and did a little exploration. I created a new icon file with a single icon that consisted of nothing but a white canvas with a black pixel in each corner. I used pilot-xfer to copy that file to my laptop and pilot-file to dump its contentsI’m doing all this on my Linux box. If you’re trapped in some proprietary OS, the details will vary but the technique should still work.. (Both of these tools are part of the excellent pilot-link package.)

What I got was encouraging:

0000: 00 00 00 00 00 00 00 00 ff 01 00 00 00 00 00 00
0010: 00 14 00 12 00 14 80 00 08 03 18 00 00 01 00 90
0020: 00 00 00 00 00 00 00 00 00 00 00 30 01 ff 12 00
0030: 01 ff 14 00 14 00 14 00 14 00 14 00 14 00 14 00
0040: 14 00 14 00 14 00 14 00 14 00 14 00 14 00 14 00
0050: 14 00 01 ff 12 00 01 ff

The four ff’s (not counting the one that’s probably in some kind of header) are good candidates for my corner pixels and a regular pattern of 00’s (run length encoded?) smells like the white background. A bit more digging in the IconManager menus revealed an option to store the file uncompressed, saving me the trouble of figuring out exactly how the compression works. It also revealed an option to delete icons at specific resolutions.

The palm has high-resolution and low-resolution 16-bit, 8-bit, grayscale, and monochrome icons. Deleting all but the 8-bit, high-res icons saves me the trouble of figuring out where an icon at one resulution ends and another begins.

With all these choices made, I copied the file back over to my laptop and took another look:

0000: 00 00 00 00 00 00 00 00 ff 01 00 00 00 00 00 00
0010: 00 14 00 12 00 14 00 00 08 03 18 00 00 00 00 90
0020: 00 00 00 00 00 00 00 00 ff 00 00 00 00 00 00 00
0030: 00 00 00 00 00 00 00 00 00 00 00 ff 00 00 00 00
0040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0110: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0120: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0130: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0140: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0150: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0160: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0170: 00 00 00 00 00 00 00 00 00 00 00 00 ff 00 00 00
0180: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff

With a little reformatting, that’s pretty clearly my icon:

ff000000000000000000000000000000000000ff
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
0000000000000000000000000000000000000000
ff000000000000000000000000000000000000ff

So they’re simply stored in a row-major array starting at offset 0x28 from the beginning of the resource. Turning that into an XPM is basically just a matter of mapping the byte values into colors from the system palette. That wasn’t hard to do, though it did require a little fiddling to reconstruct the Palm system palette on my laptop.

Another quick experiment revealed that the byte value stored at offset 0x23 is the “transparent” color.

Wrapping all this up in a little script gives us a straightforward recipe for extracting the icons:

  1. In IconManager on the Palm, copy your icon set, remove the extra images (keeping only the high-res color icons), uncompress the images, and save the data.

  2. Copy the resulting icon file to your PC.

    pilot-xfer -f nameOfIconfFile.prc
  3. Use pilot-file to dump all the resources in the icon file.

    pilot-file -D nameOfIconfFile.prc > /dev/null
  4. Use my little tbmp2xpm Perl script to convert each resource to an XPM file.

    tbmp2xpm Tbmp0001.bin > Tbmp0001.xpm

    Or, more realistically:

    for $f in *.bin; do \
    tbmp2xpm $f `basename $f .bin`.xpm; \
    done

You’ll probably want to rename the files and you may want to convert them to some other format, but that’s all there is to it.

I found that the 20x18 color icons suited my needs. If you wanted the 16-bit icons, you could get them instead with a little tweaking. They’re stored uncompressed too, but they’re two-bytes per pixel instead of one and I don’t know anything about the palette.