Custom icons for Win32 starpacks

As of 2003-02-09, the SDX "wrap" command supports generating Win32 starpacks which have a custom icon for the executable.

This took some hacking, but first - here's how to do it:

        16x16, 4-bit (16-color)
        16x16, 8-bit (256-color)
        32x32, 4-bit (16-color)
        32x32, 8-bit (256-color)
        48x48, 4-bit (16-color)
        48x48, 8-bit (256-color)
        sdx wrap myapp.exe -runtime tclkit.exe

SDX wrap will see the "tclkit.ico" file at the root level of the starkit (it gets included in VFS, like everything else), and if the runtime is a Win32 executable it'll do some string replaces to overwrite the ICO resource of the generated starpack.

There are a number of comments to make:

That's it. It's all done beneath the surface. All icon substitions done by SDX are reported on stdout.


How SDX replaces icons in Starpacks

The logic behind all this is a bit convoluted. To work, SDX deals with three icons:

  1. the icon resource in the original runtime
  2. the tclkit.ico file in the VFS section of the original runtime
  3. the new myapp.vfs/tclkit.ico file

What SDX then does for each icon resolution it finds in #2, is take the bitmap, search for it in #1, and do s atring replace with the corresponding resolution bitmap from #3.

So the essential trick to make this work is that the runtime with which a starpack is constructed must contain the same icons twice - once as Windows resource, somewhere inside the executable, and once as "original" tclkit.ico in the VFS at the end of that executable.

It's all done as a string search + replace. That way SDX does not need to understand executable file formats, nor exactly how icon files are structured (only enough to locate each icon resolution).

SDX assumes that bitmaps of icons with a specific resolution always use the same number of bytes. It will only replace a bitmap with another one of the same size.

To make SDX customize icons for executables other than tclkit.exe, that runtime must be set up in the same way as tclkit: