I’ve been updating Bocfel to work with Infocom’s graphical games, including supporting the adaptive palette chunk of Blorb.
There is a problem, though: the APal chunk requires you to apply one PNG file’s palette to another PNG file, but Glk does not provide access to images directly. That means you can neither read nor write image palettes. I’ve got a workaround via a new BPal chunk. The idea is to precompute all possible combinations of non-APal × APal images, and store them in the Blorb file. Interpreters can look up whether there is an entry for the current palette plus the requested image, and if so, plot that image instead.
The chunk is tentatively documented as follows:
Because Glk does not give access to the underlying images in a Blorb file (instead allowing you to refer to them by number only), using the Adaptive Palette chunk from a Blorb file (see the Blorb specification, §11.3) is not possible: you cannot read a palette from an image, and you cannot apply a palette to an image.
To work around this, Bocfel introduces the Bocfel Adaptive Palette Chunk, with type ‘BPal’. All requirements for APal chunks apply to BPal as well, and BPal serves as a replacement for APal when APal is not able to be used.
4 bytes 'BPal' chunk ID
4 bytes num*12 chunk length
num*12 bytes ... adaptive palette entries
Each entry is 12 bytes, of the form:
4 bytes current current palette image number
4 bytes adaptive requested APal image number
4 bytes replacement the image with palette pre-applied
Blorb’s adaptive palette works by applying the “Current Palette” (the last-drawn non-adaptive image’s palette) to a plotted image, if that image is listed in the APal chunk.
The BPal chunk operates by pre-applying all possible palettes to APal images, and storing these in the Blorb file. Each entry is a combination of a current palette image (which must not be in the APal chunk), an adaptive palette image (which is from the APal chunk), and the replacement image ID, which has the palette pre-applied. In short, “replacement” is the ID of an image representing “adaptive” with the “current” palette applied.
The “Current Palette” should be tracked as in APal. Whenever a picture is plotted, the BPal chunk should be consulted. If there is an entry corresponding to the current palette and the requested image, the replacement image should be plotted instead.
All replacement images must be the same size as the image they are replacing. No new Reso entries are added for the replacement images, even if the original image has a corresponding Reso entry. Instead, interpreters must look up a Reso entry for the original image, and apply it to the replacement.
This is a ridiculously niche case: Z-machine interpreters supporting Arthur and/or Zork Zero, but which don’t have access to the images directly, which effectively means using Glk. Be that as it may, I’m looking for feedback from anybody interested in this area.
This does increase the size of Blorb files, of course: Arthur jumps from 271K to 340K, and Zork Zero from 229K to 960K. There’s room for optimization, by including only combinations that are known to be generated by the game, but it’s hardly worth it as far as I’m concerned, when we’re still talking under a meg. I’d rather have a larger Blorb file than accidentally miss an image.
One thing I discovered about Arthur, too, while working on this: the Blorb spec’s recommendation for how to track the current palette and apply it is not sufficient: Arthur does not tend to redraw the banner/staffs, which are the only APal images in the game: rather, it draws them once and then keeps drawing room images on top. At game start, it draws the room first, though, so the first room’s palette is applied and then it sticks, unless you force a redraw, e.g. with F1. You can see this in SDL Frotz: head east at the beginning of the game and hit F1. The banner will change from purple to gold.
I’ve worked around this by manually redrawing the banner image first whenever a room image is drawn, which is hacky, but so’s the rest of my version 6 support, so it’s par for the course.