Font: Difference between revisions

From Boktai Hacking Wiki
mNo edit summary
No edit summary
Line 1: Line 1:
The font stores all characters the game uses for drawing text. There are two types of characters: Narrow characters are 8x16 px in size (two tiles), and wide characters are 16x16 px in size (four tiles).
The font stores all characters the game uses for drawing text. There are three different types of characters:
 
* Narrow characters are 8x16 px in size (two tiles)
* Wide characters in Boktai 2 and Boktai 3 are 16x16 px in size (four tiles).
* Wide characters in Boktai 1 are '''13x12 px in size''' (one custom tile, implemented in software by Boktai 1. Only 12x12 px are stored in the ROM, the final pixel in each row is computed depending on the pixel to the left)


The font is stored in the directory with id_low=0x6d24, id_high=0xa705 in the [[master file table]]. That directory will contain a single font file with id=0x3f51.
The font is stored in the directory with id_low=0x6d24, id_high=0xa705 in the [[master file table]]. That directory will contain a single font file with id=0x3f51.
'''Warning:''' In Boktai 1, wide characters are structured differently than described here. In Boktai 1, each wide character is 0x48 bytes in size, whereas in Boktai 2 and 3 each wide character is 0x80 bytes in size. The format of Boktai 1 wide characters still needs to be reverse engineered.


= File format =
= File format =
Line 35: Line 37:
</syntaxhighlight>
</syntaxhighlight>


= Wide characters =
= Wide characters (Boktai 2/3) =


The font can also provide arbitrarily many wide 16x16 px characters. These are referenced from strings using a two-byte sequence, stored in big-endian byte order, with the top bit of the first byte set. For example, to reference the wide character 0x123, the string should contain the two bytes <code>0x81 0x23</code>. The first wide character has index 0:
The font can also provide arbitrarily many 16x16 px characters. These are referenced from strings using a two-byte sequence, stored in big-endian byte order, with the top bit of the first byte set. For example, to reference the wide character 0x123, the string should contain the two bytes <code>0x81 0x23</code>. The first wide character has index 0:


<syntaxhighlight lang="c">
<syntaxhighlight lang="c">
Line 56: Line 58:
}
}
</syntaxhighlight>
</syntaxhighlight>
= Wide characters (Boktai 1) =
Similar to Boktai 2/3, but each character is 13x12 px in size, and constructed from a single custom 12x12 px 4bpp tile (= 0x48 bytes per tile). The rightmost pixel in each row is computed from the pixel to the left of it.


[[Category:Documentation]] [[Category:File formats]]
[[Category:Documentation]] [[Category:File formats]]
[[Category:Boktai 1]] [[Category:Boktai 2]] [[Category:Boktai 3]]
[[Category:Boktai 1]] [[Category:Boktai 2]] [[Category:Boktai 3]]

Revision as of 15:17, 22 September 2024

The font stores all characters the game uses for drawing text. There are three different types of characters:

  • Narrow characters are 8x16 px in size (two tiles)
  • Wide characters in Boktai 2 and Boktai 3 are 16x16 px in size (four tiles).
  • Wide characters in Boktai 1 are 13x12 px in size (one custom tile, implemented in software by Boktai 1. Only 12x12 px are stored in the ROM, the final pixel in each row is computed depending on the pixel to the left)

The font is stored in the directory with id_low=0x6d24, id_high=0xa705 in the master file table. That directory will contain a single font file with id=0x3f51.

File format

struct FontHeader {
    /* offset 0x0 */ u16 narrowCharCount;
    /* offset 0x2 */ u16 wideCharCount;
    /* offset 0x4 */ u32 offsetToNarrowChars;
    /* offset 0x8 */ u32 offsetToWideChars;

    // Array of 8x8 px 4bpp tiles follows (32 bytes per tile)
};

Narrow characters

The font should provide one 8x16 px character for each ASCII byte between 0x20 and 0xff inclusive (= 224 characters in total). If a byte is less than 0x20, the game will not render a character for that byte:

void DrawNarrowCharacter(int x, int y, char ch, FontHeader* font) {
    // The 1st 0x20 ASCII characters are not stored in the font, and cannot be rendered
    int charIndex = ch - 0x20;
    // Each tile is 0x20 bytes in size, a narrow character is 1x2 tiles in size,
    // giving a total size of 0x40 bytes per character
    u8* tileStart = (u8*)font + font->offsetToNarrowChars + charIndex*0x40;
    // Draw two tiles, stacked vertically
    DrawTile(x, y,   tileStart);
    DrawTile(x, y+1, tileStart + 0x20);
}

Wide characters (Boktai 2/3)

The font can also provide arbitrarily many 16x16 px characters. These are referenced from strings using a two-byte sequence, stored in big-endian byte order, with the top bit of the first byte set. For example, to reference the wide character 0x123, the string should contain the two bytes 0x81 0x23. The first wide character has index 0:

void DrawWideCharacter(int x, int y, char* text, FontHeader* font) {
    char high = text[0];
    char low = text[1];
    // Combine the two bytes, and clear the top bit
    int charIndex = ((high & 0x7f) << 8) | low

    // Each tile is 0x80 bytes in size, a wide character is 2x2 tiles in size,
    // giving a total size of 0x80 bytes per character
    u8* tileStart = (u8*)font + font->offsetToWideChars + charIndex*0x80;
    // Draw four tiles
    DrawTile(x,   y,   tileStart);
    DrawTile(x+1, y,   tileStart + 0x20);
    DrawTile(x,   y+1, tileStart + 0x40);
    DrawTile(x+1, y+1, tileStart + 0x60);
}

Wide characters (Boktai 1)

Similar to Boktai 2/3, but each character is 13x12 px in size, and constructed from a single custom 12x12 px 4bpp tile (= 0x48 bytes per tile). The rightmost pixel in each row is computed from the pixel to the left of it.