playdate-reverse-engineering icon indicating copy to clipboard operation
playdate-reverse-engineering copied to clipboard

Investigate PFT font format

Open jaames opened this issue 2 years ago • 1 comments

I haven't had a chance to properly look at this yet. It seems to be pretty similar to the imagetable format, but it wasn't obvious how each glyph is stored.

jaames avatar Mar 01 '22 10:03 jaames

current notes:

overall

file header

  • 12 byte ident (Playdate FNT)
  • u32 flags (0x80000000) = is compressed
  • u32 decompressed data size
  • u32 glyph width
  • u32 glyph height
  • u32 unused!?

rest is compressed if the compression flag is set. after decompression:

header (always 64 bytes?)

  • u8 glyph width
  • u8 glyph height
  • u16 base tracking
  • u32 number of pages minus one (e.g. value of 3 = 4 pages)
  • rest is unknown

offset table

  • u32 page offsets relative to the end of this table
  • more complex fonts can have another u32 offset per page??? unsure what for
  • last offset is end of file

page

  • u8 0?
  • u8 0?
  • u8 0?
  • u8 num chars in page
  • u32 0?
  • 28 bytes of unknown junk
  • per char:
    • u16 end offset for each glyph entry
  • glyph entries

glyph

  • u8 char advance (per-glyph "width" value in caps)
  • u8 num kerning sets? no idea really
  • u8 0
  • u8 0
  • can be extra data here if kerning used?
  • u16 bitmap width
  • u16 bitmap height
  • u16 stride (bytes per image row)
  • u16 bitmap clip left
  • u16 bitmap clip right
  • u16 bitmap clip top
  • u16 bitmap clip bottom
  • u16 bitflags
    • (flags & 0x3) > 0 = Cell contains an alpha map
  • bitmaps are comprised of one or two 1-bit maps stored one after the other - first is the black/white map, second is the alpha map, which is only stored if the correct bitflags are set in the cell header. The width of each map is padded to the nearest multiple of 8. Transparent edges get trimmed, and the dimensions of the trimmed area are recorded in the clip fields.

jaames avatar Jul 08 '22 09:07 jaames