FontX2 'Support' for PETI

Last Updated: 2024-01-24 05:00:00 -0600

When it comes to PETI firmware updates, it’s a small secret that they rarely come out according to plan. The next firmware update, 0.4.0, is no exception - dedicated readers will remember that I had originally promised that release by Christmas, on the heels of a mid-autumn release of the current version, 0.3.0. The update was supposed to support the ability for the pet to sleep and for the implementation of the game’s native evolution system, so it should come as no small shock to anyone that in actual fact its being blocked by - font development. If that doesn’t seem to make sense to you, jump below the cut and we’ll have a look at what’s going on here.

What do Fonts have to do with sleep and evolution?

Ostensibly, nothing. However, when I was working out the evolution logic, I had to clean up an old bit of technical debt and actually define the evolutionary relationships between the pet forms, when it suddenly occured to me - the evolutionary tree is too small. This is not a problem. Since update 0.1.0 extended support for multiple fonts of each size, it’s fairly trivial to add new pets to the game; I just have to design another font with some additional charater art in it, and add them to the evolution metadata.

Or it would have been fairly trivial were it not for some small pain points and a fairly major technical issue with our font editing tool.

The Problem with fontedit

So, I want to stress that Nathan Dumont’s fontedit is actually a perfectly functional tool for what it was actually designed for - the creation and modification of simple text fonts for use with embedded devices. That’s why it was originally specc’d in to peti-helpers when I created the helper tool repo. However, it did have a few small shortcomings that were pain points for creating animation cells using it:

  • Modifying the characters has to be done manually for each distinct character. There’s no copy/paste, meaning minor variations of the pet have to be redrawn fully by hand each time.
  • The default bitwise orientation of the display colors is correct for use with our display, but the default character state is all cells “on” as interpreted by PETI. This is an issue with our implementation, sure, but funcionally it means that the font developer must manually invert every pixel of the character before drawing.
  • On my install specifically and seemingly nobody else’s, drag-to-draw doesn’t work, so characters need to be drawn by clicking each individual pixel.

Again, wonderful tool for what it was designed for, but a bit underpowered with regard to this specific project. Unfortunately though, other than its highly flexible system for custom exports, it stores the font source data by simply pickling the python structure, meaning its save data is fairly proprietary and hard to transfer into other tools, so for a few months I got hung up on the idea that I’d have to redraw the fonts if I switched tools, and just kept picking slowly away at the edges of the font problem in the meantime.

Enter FontX2

It turns out, needing compactly stored bitmap fonts is not actually a novel problem in computer science. Back before we were all carrying the equivalent of the Cray 2 in our pockets on the daily for watching cat videos, many computers relied on bitmap fonts - they were easier to process than full vector fonts and fit comfortably in the storage solutions of the time.

One such standard for this, FONTX2, has seen a resurgence in the embedded development community. Existing examples of FONTX2 fonts are trivially directly used in embedded software, and only slightly less trivially converted to exactly the sort of headers PETI uses to display font information.

After poking around and finding that many editors I liked the look of functionally also had support for FontX2, I decided what we really needed was an exporter module for fontedit that would let me convert the font source files to this format.

Writing the Converter

I expected writing the export conversion module for the format to be difficult, for two reasons:

  • it involved writing to disk in raw bytes using python, a task that always causes me slightly more grief than I feel like it should, and;
  • it involved following an existing standard file format, rather than whinging it, which is my usual approach.

It turns out, I needn’t have been concerned. Working from Elm-Chan’s writeup on the format it became pretty clear that the FONTX2 format is shockingly similar to what, conceptually the PETI font headers already contain:

  • Six bytes, encoding FONTX2 in ASCII, as a magic number
  • Eight bytes, encoding for the name of the font (unusued in my implementation)
  • One byte each giving the font width, then height, in pixels
  • A further byte indicating whether the font is encoded for single-byte (limiting to 256 images) or double-byte (limiting to 65536) images.
  • The font data itself.

I recommend reading the document linked above for a clearer spec, but that was really it. I spent a few weeks after having the idea to do something like this dreading the complexity, and ultimately, ended up writing the converter in a little over an hour, including debugging time. Right now, at this exact moment, it’s not published, but I’ll be including the converter scripts, the converted font files, and the updated fonts in the 0.4.0 update when it’s ready. I’ll also send a PR for the converter to Nathan’s source repo for fontedit, since I think this is a pretty useful addition to his arsenal. Some embedded project frameworks even support fontx2 binaries natively, which’d remove a lot of the need for further custom convertors to future projects.

The principal advantage now is - you no longer need to use a specific tool for this aspect of PETI development. Much like the time I sank into writing custom makefiles to break out of TI’s limited development environment and allow people to use simpler tools, or the tools they preferred, this will allow users to develop on the font using any font-editing tool that supports what was, at one point, a pretty common format, and then simply run a seperate converter script in order to generate the data needed for PETI to actually use the font. Simple as.

What’s left on 0.4.0?

There’s still work to be done before I can release the 0.4.0 firmware update, which is fine because I also want to time that release as close as I can to the general availability of the improved version of the development kit, hopefully by springtime, if I can get the lab budget back into order. It’s a fairly major update, so far we’ve implemented support for:

  • The pet sleeping, including a special naptime function for the baby stage.
  • The display sleeping under certain conditions, saving battery usage.
  • A fairly major memory savings which will allow for additional feature complexity down the line

And I’m still working on:

  • Implementing a total of 10 new forms (bringing the playable total to 26)
  • Impelementing the main evolution mechanic
  • Impelementing the second-to-last secret puzzle feature into the pet, which will unlock two different evolutionary branch points (depending on gameplay)

Now, that sounds like a lot of work, but it really isn’t - the sleep system and the complexities introduced to it will honestly have been more complexity than the evolution mechanism represents.

If you wanted to show your support financially for Arcana Labs projects like Piminder or PETI, but don’t need a virtual pet development kit, your best avenue is through the pathways detailed on our support page.


Using your Fediverse account, you can respond to this article's Mastodon Post. Embracing the spirit of decentralization inherent to the Fediverse, you can use your account on any compatible platform to post. Clicking the "load comments" button below will make your browser request all of the non-private comments and display them below.

This was built based on this reference implementation.