diff --git a/examples/chargen.hpp b/examples/chargen.hpp new file mode 100644 index 0000000..8e060b3 --- /dev/null +++ b/examples/chargen.hpp @@ -0,0 +1,516 @@ +#include + +constexpr std::uint8_t uppercase[] = { + 0x3C, 0x66, 0x6E, 0x6E, 0x60, 0x62, 0x3C, 0x00, +0x18, 0x3C, 0x66, 0x7E, 0x66, 0x66, 0x66, 0x00, +0x7C, 0x66, 0x66, 0x7C, 0x66, 0x66, 0x7C, 0x00, +0x3C, 0x66, 0x60, 0x60, 0x60, 0x66, 0x3C, 0x00, +0x78, 0x6C, 0x66, 0x66, 0x66, 0x6C, 0x78, 0x00, +0x7E, 0x60, 0x60, 0x78, 0x60, 0x60, 0x7E, 0x00, +0x7E, 0x60, 0x60, 0x78, 0x60, 0x60, 0x60, 0x00, +0x3C, 0x66, 0x60, 0x6E, 0x66, 0x66, 0x3C, 0x00, +0x66, 0x66, 0x66, 0x7E, 0x66, 0x66, 0x66, 0x00, +0x3C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, +0x1E, 0x0C, 0x0C, 0x0C, 0x0C, 0x6C, 0x38, 0x00, +0x66, 0x6C, 0x78, 0x70, 0x78, 0x6C, 0x66, 0x00, +0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x7E, 0x00, +0x63, 0x77, 0x7F, 0x6B, 0x63, 0x63, 0x63, 0x00, +0x66, 0x76, 0x7E, 0x7E, 0x6E, 0x66, 0x66, 0x00, +0x3C, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00, +0x7C, 0x66, 0x66, 0x7C, 0x60, 0x60, 0x60, 0x00, +0x3C, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x0E, 0x00, +0x7C, 0x66, 0x66, 0x7C, 0x78, 0x6C, 0x66, 0x00, +0x3C, 0x66, 0x60, 0x3C, 0x06, 0x66, 0x3C, 0x00, +0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, +0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00, +0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x00, +0x63, 0x63, 0x63, 0x6B, 0x7F, 0x77, 0x63, 0x00, +0x66, 0x66, 0x3C, 0x18, 0x3C, 0x66, 0x66, 0x00, +0x66, 0x66, 0x66, 0x3C, 0x18, 0x18, 0x18, 0x00, +0x7E, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x7E, 0x00, +0x3C, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3C, 0x00, +0x0C, 0x12, 0x30, 0x7C, 0x30, 0x62, 0xFC, 0x00, +0x3C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x3C, 0x00, +0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x18, +0x00, 0x10, 0x30, 0x7F, 0x7F, 0x30, 0x10, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x18, 0x00, +0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, +0x66, 0x66, 0xFF, 0x66, 0xFF, 0x66, 0x66, 0x00, +0x18, 0x3E, 0x60, 0x3C, 0x06, 0x7C, 0x18, 0x00, +0x62, 0x66, 0x0C, 0x18, 0x30, 0x66, 0x46, 0x00, +0x3C, 0x66, 0x3C, 0x38, 0x67, 0x66, 0x3F, 0x00, +0x06, 0x0C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, +0x0C, 0x18, 0x30, 0x30, 0x30, 0x18, 0x0C, 0x00, +0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x18, 0x30, 0x00, +0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00, +0x00, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, +0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, +0x00, 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x00, +0x3C, 0x66, 0x6E, 0x76, 0x66, 0x66, 0x3C, 0x00, +0x18, 0x18, 0x38, 0x18, 0x18, 0x18, 0x7E, 0x00, +0x3C, 0x66, 0x06, 0x0C, 0x30, 0x60, 0x7E, 0x00, +0x3C, 0x66, 0x06, 0x1C, 0x06, 0x66, 0x3C, 0x00, +0x06, 0x0E, 0x1E, 0x66, 0x7F, 0x06, 0x06, 0x00, +0x7E, 0x60, 0x7C, 0x06, 0x06, 0x66, 0x3C, 0x00, +0x3C, 0x66, 0x60, 0x7C, 0x66, 0x66, 0x3C, 0x00, +0x7E, 0x66, 0x0C, 0x18, 0x18, 0x18, 0x18, 0x00, +0x3C, 0x66, 0x66, 0x3C, 0x66, 0x66, 0x3C, 0x00, +0x3C, 0x66, 0x66, 0x3E, 0x06, 0x66, 0x3C, 0x00, +0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, +0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x18, 0x30, +0x0E, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0E, 0x00, +0x00, 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x00, 0x00, +0x70, 0x18, 0x0C, 0x06, 0x0C, 0x18, 0x70, 0x00, +0x3C, 0x66, 0x06, 0x0C, 0x18, 0x00, 0x18, 0x00, +0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, +0x08, 0x1C, 0x3E, 0x7F, 0x7F, 0x1C, 0x3E, 0x00, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, +0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, +0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, +0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, +0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, +0x00, 0x00, 0x00, 0xE0, 0xF0, 0x38, 0x18, 0x18, +0x18, 0x18, 0x1C, 0x0F, 0x07, 0x00, 0x00, 0x00, +0x18, 0x18, 0x38, 0xF0, 0xE0, 0x00, 0x00, 0x00, +0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xFF, 0xFF, +0xC0, 0xE0, 0x70, 0x38, 0x1C, 0x0E, 0x07, 0x03, +0x03, 0x07, 0x0E, 0x1C, 0x38, 0x70, 0xE0, 0xC0, +0xFF, 0xFF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, +0xFF, 0xFF, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, +0x00, 0x3C, 0x7E, 0x7E, 0x7E, 0x7E, 0x3C, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, +0x36, 0x7F, 0x7F, 0x7F, 0x3E, 0x1C, 0x08, 0x00, +0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, +0x00, 0x00, 0x00, 0x07, 0x0F, 0x1C, 0x18, 0x18, +0xC3, 0xE7, 0x7E, 0x3C, 0x3C, 0x7E, 0xE7, 0xC3, +0x00, 0x3C, 0x7E, 0x66, 0x66, 0x7E, 0x3C, 0x00, +0x18, 0x18, 0x66, 0x66, 0x18, 0x18, 0x3C, 0x00, +0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, +0x08, 0x1C, 0x3E, 0x7F, 0x3E, 0x1C, 0x08, 0x00, +0x18, 0x18, 0x18, 0xFF, 0xFF, 0x18, 0x18, 0x18, +0xC0, 0xC0, 0x30, 0x30, 0xC0, 0xC0, 0x30, 0x30, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x00, 0x00, 0x03, 0x3E, 0x76, 0x36, 0x36, 0x00, +0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, +0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, +0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, +0xCC, 0xCC, 0x33, 0x33, 0xCC, 0xCC, 0x33, 0x33, +0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, +0x00, 0x00, 0x00, 0x00, 0xCC, 0xCC, 0x33, 0x33, +0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80, +0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, +0x18, 0x18, 0x18, 0x1F, 0x1F, 0x18, 0x18, 0x18, +0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, +0x18, 0x18, 0x18, 0x1F, 0x1F, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0xF8, 0xF8, 0x18, 0x18, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, +0x00, 0x00, 0x00, 0x1F, 0x1F, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0xFF, 0xFF, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0xFF, 0xFF, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0xF8, 0xF8, 0x18, 0x18, 0x18, +0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, +0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, +0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, +0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, +0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0xFF, 0xFF, +0x00, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0xF0, 0xF0, +0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, +0x18, 0x18, 0x18, 0xF8, 0xF8, 0x00, 0x00, 0x00, +0xF0, 0xF0, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0x00, +0xF0, 0xF0, 0xF0, 0xF0, 0x0F, 0x0F, 0x0F, 0x0F, +0xC3, 0x99, 0x91, 0x91, 0x9F, 0x99, 0xC3, 0xFF, +0xE7, 0xC3, 0x99, 0x81, 0x99, 0x99, 0x99, 0xFF, +0x83, 0x99, 0x99, 0x83, 0x99, 0x99, 0x83, 0xFF, +0xC3, 0x99, 0x9F, 0x9F, 0x9F, 0x99, 0xC3, 0xFF, +0x87, 0x93, 0x99, 0x99, 0x99, 0x93, 0x87, 0xFF, +0x81, 0x9F, 0x9F, 0x87, 0x9F, 0x9F, 0x81, 0xFF, +0x81, 0x9F, 0x9F, 0x87, 0x9F, 0x9F, 0x9F, 0xFF, +0xC3, 0x99, 0x9F, 0x91, 0x99, 0x99, 0xC3, 0xFF, +0x99, 0x99, 0x99, 0x81, 0x99, 0x99, 0x99, 0xFF, +0xC3, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xC3, 0xFF, +0xE1, 0xF3, 0xF3, 0xF3, 0xF3, 0x93, 0xC7, 0xFF, +0x99, 0x93, 0x87, 0x8F, 0x87, 0x93, 0x99, 0xFF, +0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x81, 0xFF, +0x9C, 0x88, 0x80, 0x94, 0x9C, 0x9C, 0x9C, 0xFF, +0x99, 0x89, 0x81, 0x81, 0x91, 0x99, 0x99, 0xFF, +0xC3, 0x99, 0x99, 0x99, 0x99, 0x99, 0xC3, 0xFF, +0x83, 0x99, 0x99, 0x83, 0x9F, 0x9F, 0x9F, 0xFF, +0xC3, 0x99, 0x99, 0x99, 0x99, 0xC3, 0xF1, 0xFF, +0x83, 0x99, 0x99, 0x83, 0x87, 0x93, 0x99, 0xFF, +0xC3, 0x99, 0x9F, 0xC3, 0xF9, 0x99, 0xC3, 0xFF, +0x81, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xFF, +0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0xC3, 0xFF, +0x99, 0x99, 0x99, 0x99, 0x99, 0xC3, 0xE7, 0xFF, +0x9C, 0x9C, 0x9C, 0x94, 0x80, 0x88, 0x9C, 0xFF, +0x99, 0x99, 0xC3, 0xE7, 0xC3, 0x99, 0x99, 0xFF, +0x99, 0x99, 0x99, 0xC3, 0xE7, 0xE7, 0xE7, 0xFF, +0x81, 0xF9, 0xF3, 0xE7, 0xCF, 0x9F, 0x81, 0xFF, +0xC3, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xC3, 0xFF, +0xF3, 0xED, 0xCF, 0x83, 0xCF, 0x9D, 0x03, 0xFF, +0xC3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xC3, 0xFF, +0xFF, 0xE7, 0xC3, 0x81, 0xE7, 0xE7, 0xE7, 0xE7, +0xFF, 0xEF, 0xCF, 0x80, 0x80, 0xCF, 0xEF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xE7, 0xE7, 0xE7, 0xE7, 0xFF, 0xFF, 0xE7, 0xFF, +0x99, 0x99, 0x99, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0x99, 0x99, 0x00, 0x99, 0x00, 0x99, 0x99, 0xFF, +0xE7, 0xC1, 0x9F, 0xC3, 0xF9, 0x83, 0xE7, 0xFF, +0x9D, 0x99, 0xF3, 0xE7, 0xCF, 0x99, 0xB9, 0xFF, +0xC3, 0x99, 0xC3, 0xC7, 0x98, 0x99, 0xC0, 0xFF, +0xF9, 0xF3, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xF3, 0xE7, 0xCF, 0xCF, 0xCF, 0xE7, 0xF3, 0xFF, +0xCF, 0xE7, 0xF3, 0xF3, 0xF3, 0xE7, 0xCF, 0xFF, +0xFF, 0x99, 0xC3, 0x00, 0xC3, 0x99, 0xFF, 0xFF, +0xFF, 0xE7, 0xE7, 0x81, 0xE7, 0xE7, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xE7, 0xCF, +0xFF, 0xFF, 0xFF, 0x81, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xE7, 0xFF, +0xFF, 0xFC, 0xF9, 0xF3, 0xE7, 0xCF, 0x9F, 0xFF, +0xC3, 0x99, 0x91, 0x89, 0x99, 0x99, 0xC3, 0xFF, +0xE7, 0xE7, 0xC7, 0xE7, 0xE7, 0xE7, 0x81, 0xFF, +0xC3, 0x99, 0xF9, 0xF3, 0xCF, 0x9F, 0x81, 0xFF, +0xC3, 0x99, 0xF9, 0xE3, 0xF9, 0x99, 0xC3, 0xFF, +0xF9, 0xF1, 0xE1, 0x99, 0x80, 0xF9, 0xF9, 0xFF, +0x81, 0x9F, 0x83, 0xF9, 0xF9, 0x99, 0xC3, 0xFF, +0xC3, 0x99, 0x9F, 0x83, 0x99, 0x99, 0xC3, 0xFF, +0x81, 0x99, 0xF3, 0xE7, 0xE7, 0xE7, 0xE7, 0xFF, +0xC3, 0x99, 0x99, 0xC3, 0x99, 0x99, 0xC3, 0xFF, +0xC3, 0x99, 0x99, 0xC1, 0xF9, 0x99, 0xC3, 0xFF, +0xFF, 0xFF, 0xE7, 0xFF, 0xFF, 0xE7, 0xFF, 0xFF, +0xFF, 0xFF, 0xE7, 0xFF, 0xFF, 0xE7, 0xE7, 0xCF, +0xF1, 0xE7, 0xCF, 0x9F, 0xCF, 0xE7, 0xF1, 0xFF, +0xFF, 0xFF, 0x81, 0xFF, 0x81, 0xFF, 0xFF, 0xFF, +0x8F, 0xE7, 0xF3, 0xF9, 0xF3, 0xE7, 0x8F, 0xFF, +0xC3, 0x99, 0xF9, 0xF3, 0xE7, 0xFF, 0xE7, 0xFF, +0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, +0xF7, 0xE3, 0xC1, 0x80, 0x80, 0xE3, 0xC1, 0xFF, +0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, +0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, +0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, +0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, +0xFF, 0xFF, 0xFF, 0x1F, 0x0F, 0xC7, 0xE7, 0xE7, +0xE7, 0xE7, 0xE3, 0xF0, 0xF8, 0xFF, 0xFF, 0xFF, +0xE7, 0xE7, 0xC7, 0x0F, 0x1F, 0xFF, 0xFF, 0xFF, +0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x00, 0x00, +0x3F, 0x1F, 0x8F, 0xC7, 0xE3, 0xF1, 0xF8, 0xFC, +0xFC, 0xF8, 0xF1, 0xE3, 0xC7, 0x8F, 0x1F, 0x3F, +0x00, 0x00, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, +0x00, 0x00, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, +0xFF, 0xC3, 0x81, 0x81, 0x81, 0x81, 0xC3, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, +0xC9, 0x80, 0x80, 0x80, 0xC1, 0xE3, 0xF7, 0xFF, +0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, +0xFF, 0xFF, 0xFF, 0xF8, 0xF0, 0xE3, 0xE7, 0xE7, +0x3C, 0x18, 0x81, 0xC3, 0xC3, 0x81, 0x18, 0x3C, +0xFF, 0xC3, 0x81, 0x99, 0x99, 0x81, 0xC3, 0xFF, +0xE7, 0xE7, 0x99, 0x99, 0xE7, 0xE7, 0xC3, 0xFF, +0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, +0xF7, 0xE3, 0xC1, 0x80, 0xC1, 0xE3, 0xF7, 0xFF, +0xE7, 0xE7, 0xE7, 0x00, 0x00, 0xE7, 0xE7, 0xE7, +0x3F, 0x3F, 0xCF, 0xCF, 0x3F, 0x3F, 0xCF, 0xCF, +0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, +0xFF, 0xFF, 0xFC, 0xC1, 0x89, 0xC9, 0xC9, 0xFF, +0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, +0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, +0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, +0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, +0x33, 0x33, 0xCC, 0xCC, 0x33, 0x33, 0xCC, 0xCC, +0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, +0xFF, 0xFF, 0xFF, 0xFF, 0x33, 0x33, 0xCC, 0xCC, +0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, +0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, +0xE7, 0xE7, 0xE7, 0xE0, 0xE0, 0xE7, 0xE7, 0xE7, +0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0xF0, 0xF0, +0xE7, 0xE7, 0xE7, 0xE0, 0xE0, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0x07, 0x07, 0xE7, 0xE7, 0xE7, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, +0xFF, 0xFF, 0xFF, 0xE0, 0xE0, 0xE7, 0xE7, 0xE7, +0xE7, 0xE7, 0xE7, 0x00, 0x00, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xE7, 0xE7, 0xE7, +0xE7, 0xE7, 0xE7, 0x07, 0x07, 0xE7, 0xE7, 0xE7, +0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, +0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, +0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, +0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, +0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x00, 0x00, +0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x0F, 0x0F, 0x0F, +0xF0, 0xF0, 0xF0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, +0xE7, 0xE7, 0xE7, 0x07, 0x07, 0xFF, 0xFF, 0xFF, +0x0F, 0x0F, 0x0F, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, +0x0F, 0x0F, 0x0F, 0x0F, 0xF0, 0xF0, 0xF0, 0xF0, +}; +constexpr std::uint8_t lowercase[] = { 0x3C, 0x66, 0x6E, 0x6E, 0x60, 0x62, 0x3C, 0x00, +0x00, 0x00, 0x3C, 0x06, 0x3E, 0x66, 0x3E, 0x00, +0x00, 0x60, 0x60, 0x7C, 0x66, 0x66, 0x7C, 0x00, +0x00, 0x00, 0x3C, 0x60, 0x60, 0x60, 0x3C, 0x00, +0x00, 0x06, 0x06, 0x3E, 0x66, 0x66, 0x3E, 0x00, +0x00, 0x00, 0x3C, 0x66, 0x7E, 0x60, 0x3C, 0x00, +0x00, 0x0E, 0x18, 0x3E, 0x18, 0x18, 0x18, 0x00, +0x00, 0x00, 0x3E, 0x66, 0x66, 0x3E, 0x06, 0x7C, +0x00, 0x60, 0x60, 0x7C, 0x66, 0x66, 0x66, 0x00, +0x00, 0x18, 0x00, 0x38, 0x18, 0x18, 0x3C, 0x00, +0x00, 0x06, 0x00, 0x06, 0x06, 0x06, 0x06, 0x3C, +0x00, 0x60, 0x60, 0x6C, 0x78, 0x6C, 0x66, 0x00, +0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, +0x00, 0x00, 0x66, 0x7F, 0x7F, 0x6B, 0x63, 0x00, +0x00, 0x00, 0x7C, 0x66, 0x66, 0x66, 0x66, 0x00, +0x00, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x3C, 0x00, +0x00, 0x00, 0x7C, 0x66, 0x66, 0x7C, 0x60, 0x60, +0x00, 0x00, 0x3E, 0x66, 0x66, 0x3E, 0x06, 0x06, +0x00, 0x00, 0x7C, 0x66, 0x60, 0x60, 0x60, 0x00, +0x00, 0x00, 0x3E, 0x60, 0x3C, 0x06, 0x7C, 0x00, +0x00, 0x18, 0x7E, 0x18, 0x18, 0x18, 0x0E, 0x00, +0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3E, 0x00, +0x00, 0x00, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x00, +0x00, 0x00, 0x63, 0x6B, 0x7F, 0x3E, 0x36, 0x00, +0x00, 0x00, 0x66, 0x3C, 0x18, 0x3C, 0x66, 0x00, +0x00, 0x00, 0x66, 0x66, 0x66, 0x3E, 0x0C, 0x78, +0x00, 0x00, 0x7E, 0x0C, 0x18, 0x30, 0x7E, 0x00, +0x3C, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3C, 0x00, +0x0C, 0x12, 0x30, 0x7C, 0x30, 0x62, 0xFC, 0x00, +0x3C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x3C, 0x00, +0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x18, +0x00, 0x10, 0x30, 0x7F, 0x7F, 0x30, 0x10, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x18, 0x00, +0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, +0x66, 0x66, 0xFF, 0x66, 0xFF, 0x66, 0x66, 0x00, +0x18, 0x3E, 0x60, 0x3C, 0x06, 0x7C, 0x18, 0x00, +0x62, 0x66, 0x0C, 0x18, 0x30, 0x66, 0x46, 0x00, +0x3C, 0x66, 0x3C, 0x38, 0x67, 0x66, 0x3F, 0x00, +0x06, 0x0C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, +0x0C, 0x18, 0x30, 0x30, 0x30, 0x18, 0x0C, 0x00, +0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x18, 0x30, 0x00, +0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00, +0x00, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, +0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, +0x00, 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x00, +0x3C, 0x66, 0x6E, 0x76, 0x66, 0x66, 0x3C, 0x00, +0x18, 0x18, 0x38, 0x18, 0x18, 0x18, 0x7E, 0x00, +0x3C, 0x66, 0x06, 0x0C, 0x30, 0x60, 0x7E, 0x00, +0x3C, 0x66, 0x06, 0x1C, 0x06, 0x66, 0x3C, 0x00, +0x06, 0x0E, 0x1E, 0x66, 0x7F, 0x06, 0x06, 0x00, +0x7E, 0x60, 0x7C, 0x06, 0x06, 0x66, 0x3C, 0x00, +0x3C, 0x66, 0x60, 0x7C, 0x66, 0x66, 0x3C, 0x00, +0x7E, 0x66, 0x0C, 0x18, 0x18, 0x18, 0x18, 0x00, +0x3C, 0x66, 0x66, 0x3C, 0x66, 0x66, 0x3C, 0x00, +0x3C, 0x66, 0x66, 0x3E, 0x06, 0x66, 0x3C, 0x00, +0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, +0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x18, 0x30, +0x0E, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0E, 0x00, +0x00, 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x00, 0x00, +0x70, 0x18, 0x0C, 0x06, 0x0C, 0x18, 0x70, 0x00, +0x3C, 0x66, 0x06, 0x0C, 0x18, 0x00, 0x18, 0x00, +0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, +0x18, 0x3C, 0x66, 0x7E, 0x66, 0x66, 0x66, 0x00, +0x7C, 0x66, 0x66, 0x7C, 0x66, 0x66, 0x7C, 0x00, +0x3C, 0x66, 0x60, 0x60, 0x60, 0x66, 0x3C, 0x00, +0x78, 0x6C, 0x66, 0x66, 0x66, 0x6C, 0x78, 0x00, +0x7E, 0x60, 0x60, 0x78, 0x60, 0x60, 0x7E, 0x00, +0x7E, 0x60, 0x60, 0x78, 0x60, 0x60, 0x60, 0x00, +0x3C, 0x66, 0x60, 0x6E, 0x66, 0x66, 0x3C, 0x00, +0x66, 0x66, 0x66, 0x7E, 0x66, 0x66, 0x66, 0x00, +0x3C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, +0x1E, 0x0C, 0x0C, 0x0C, 0x0C, 0x6C, 0x38, 0x00, +0x66, 0x6C, 0x78, 0x70, 0x78, 0x6C, 0x66, 0x00, +0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x7E, 0x00, +0x63, 0x77, 0x7F, 0x6B, 0x63, 0x63, 0x63, 0x00, +0x66, 0x76, 0x7E, 0x7E, 0x6E, 0x66, 0x66, 0x00, +0x3C, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00, +0x7C, 0x66, 0x66, 0x7C, 0x60, 0x60, 0x60, 0x00, +0x3C, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x0E, 0x00, +0x7C, 0x66, 0x66, 0x7C, 0x78, 0x6C, 0x66, 0x00, +0x3C, 0x66, 0x60, 0x3C, 0x06, 0x66, 0x3C, 0x00, +0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, +0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00, +0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x00, +0x63, 0x63, 0x63, 0x6B, 0x7F, 0x77, 0x63, 0x00, +0x66, 0x66, 0x3C, 0x18, 0x3C, 0x66, 0x66, 0x00, +0x66, 0x66, 0x66, 0x3C, 0x18, 0x18, 0x18, 0x00, +0x7E, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x7E, 0x00, +0x18, 0x18, 0x18, 0xFF, 0xFF, 0x18, 0x18, 0x18, +0xC0, 0xC0, 0x30, 0x30, 0xC0, 0xC0, 0x30, 0x30, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x33, 0x33, 0xCC, 0xCC, 0x33, 0x33, 0xCC, 0xCC, +0x33, 0x99, 0xCC, 0x66, 0x33, 0x99, 0xCC, 0x66, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, +0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, +0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, +0xCC, 0xCC, 0x33, 0x33, 0xCC, 0xCC, 0x33, 0x33, +0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, +0x00, 0x00, 0x00, 0x00, 0xCC, 0xCC, 0x33, 0x33, +0xCC, 0x99, 0x33, 0x66, 0xCC, 0x99, 0x33, 0x66, +0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, +0x18, 0x18, 0x18, 0x1F, 0x1F, 0x18, 0x18, 0x18, +0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, +0x18, 0x18, 0x18, 0x1F, 0x1F, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0xF8, 0xF8, 0x18, 0x18, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, +0x00, 0x00, 0x00, 0x1F, 0x1F, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0xFF, 0xFF, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0xFF, 0xFF, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0xF8, 0xF8, 0x18, 0x18, 0x18, +0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, +0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, +0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, +0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, +0x01, 0x03, 0x06, 0x6C, 0x78, 0x70, 0x60, 0x00, +0x00, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0xF0, 0xF0, +0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, +0x18, 0x18, 0x18, 0xF8, 0xF8, 0x00, 0x00, 0x00, +0xF0, 0xF0, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0x00, +0xF0, 0xF0, 0xF0, 0xF0, 0x0F, 0x0F, 0x0F, 0x0F, +0xC3, 0x99, 0x91, 0x91, 0x9F, 0x99, 0xC3, 0xFF, +0xFF, 0xFF, 0xC3, 0xF9, 0xC1, 0x99, 0xC1, 0xFF, +0xFF, 0x9F, 0x9F, 0x83, 0x99, 0x99, 0x83, 0xFF, +0xFF, 0xFF, 0xC3, 0x9F, 0x9F, 0x9F, 0xC3, 0xFF, +0xFF, 0xF9, 0xF9, 0xC1, 0x99, 0x99, 0xC1, 0xFF, +0xFF, 0xFF, 0xC3, 0x99, 0x81, 0x9F, 0xC3, 0xFF, +0xFF, 0xF1, 0xE7, 0xC1, 0xE7, 0xE7, 0xE7, 0xFF, +0xFF, 0xFF, 0xC1, 0x99, 0x99, 0xC1, 0xF9, 0x83, +0xFF, 0x9F, 0x9F, 0x83, 0x99, 0x99, 0x99, 0xFF, +0xFF, 0xE7, 0xFF, 0xC7, 0xE7, 0xE7, 0xC3, 0xFF, +0xFF, 0xF9, 0xFF, 0xF9, 0xF9, 0xF9, 0xF9, 0xC3, +0xFF, 0x9F, 0x9F, 0x93, 0x87, 0x93, 0x99, 0xFF, +0xFF, 0xC7, 0xE7, 0xE7, 0xE7, 0xE7, 0xC3, 0xFF, +0xFF, 0xFF, 0x99, 0x80, 0x80, 0x94, 0x9C, 0xFF, +0xFF, 0xFF, 0x83, 0x99, 0x99, 0x99, 0x99, 0xFF, +0xFF, 0xFF, 0xC3, 0x99, 0x99, 0x99, 0xC3, 0xFF, +0xFF, 0xFF, 0x83, 0x99, 0x99, 0x83, 0x9F, 0x9F, +0xFF, 0xFF, 0xC1, 0x99, 0x99, 0xC1, 0xF9, 0xF9, +0xFF, 0xFF, 0x83, 0x99, 0x9F, 0x9F, 0x9F, 0xFF, +0xFF, 0xFF, 0xC1, 0x9F, 0xC3, 0xF9, 0x83, 0xFF, +0xFF, 0xE7, 0x81, 0xE7, 0xE7, 0xE7, 0xF1, 0xFF, +0xFF, 0xFF, 0x99, 0x99, 0x99, 0x99, 0xC1, 0xFF, +0xFF, 0xFF, 0x99, 0x99, 0x99, 0xC3, 0xE7, 0xFF, +0xFF, 0xFF, 0x9C, 0x94, 0x80, 0xC1, 0xC9, 0xFF, +0xFF, 0xFF, 0x99, 0xC3, 0xE7, 0xC3, 0x99, 0xFF, +0xFF, 0xFF, 0x99, 0x99, 0x99, 0xC1, 0xF3, 0x87, +0xFF, 0xFF, 0x81, 0xF3, 0xE7, 0xCF, 0x81, 0xFF, +0xC3, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xC3, 0xFF, +0xF3, 0xED, 0xCF, 0x83, 0xCF, 0x9D, 0x03, 0xFF, +0xC3, 0xF3, 0xF3, 0xF3, 0xF3, 0xF3, 0xC3, 0xFF, +0xFF, 0xE7, 0xC3, 0x81, 0xE7, 0xE7, 0xE7, 0xE7, +0xFF, 0xEF, 0xCF, 0x80, 0x80, 0xCF, 0xEF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xE7, 0xE7, 0xE7, 0xE7, 0xFF, 0xFF, 0xE7, 0xFF, +0x99, 0x99, 0x99, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0x99, 0x99, 0x00, 0x99, 0x00, 0x99, 0x99, 0xFF, +0xE7, 0xC1, 0x9F, 0xC3, 0xF9, 0x83, 0xE7, 0xFF, +0x9D, 0x99, 0xF3, 0xE7, 0xCF, 0x99, 0xB9, 0xFF, +0xC3, 0x99, 0xC3, 0xC7, 0x98, 0x99, 0xC0, 0xFF, +0xF9, 0xF3, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xF3, 0xE7, 0xCF, 0xCF, 0xCF, 0xE7, 0xF3, 0xFF, +0xCF, 0xE7, 0xF3, 0xF3, 0xF3, 0xE7, 0xCF, 0xFF, +0xFF, 0x99, 0xC3, 0x00, 0xC3, 0x99, 0xFF, 0xFF, +0xFF, 0xE7, 0xE7, 0x81, 0xE7, 0xE7, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xE7, 0xCF, +0xFF, 0xFF, 0xFF, 0x81, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xE7, 0xFF, +0xFF, 0xFC, 0xF9, 0xF3, 0xE7, 0xCF, 0x9F, 0xFF, +0xC3, 0x99, 0x91, 0x89, 0x99, 0x99, 0xC3, 0xFF, +0xE7, 0xE7, 0xC7, 0xE7, 0xE7, 0xE7, 0x81, 0xFF, +0xC3, 0x99, 0xF9, 0xF3, 0xCF, 0x9F, 0x81, 0xFF, +0xC3, 0x99, 0xF9, 0xE3, 0xF9, 0x99, 0xC3, 0xFF, +0xF9, 0xF1, 0xE1, 0x99, 0x80, 0xF9, 0xF9, 0xFF, +0x81, 0x9F, 0x83, 0xF9, 0xF9, 0x99, 0xC3, 0xFF, +0xC3, 0x99, 0x9F, 0x83, 0x99, 0x99, 0xC3, 0xFF, +0x81, 0x99, 0xF3, 0xE7, 0xE7, 0xE7, 0xE7, 0xFF, +0xC3, 0x99, 0x99, 0xC3, 0x99, 0x99, 0xC3, 0xFF, +0xC3, 0x99, 0x99, 0xC1, 0xF9, 0x99, 0xC3, 0xFF, +0xFF, 0xFF, 0xE7, 0xFF, 0xFF, 0xE7, 0xFF, 0xFF, +0xFF, 0xFF, 0xE7, 0xFF, 0xFF, 0xE7, 0xE7, 0xCF, +0xF1, 0xE7, 0xCF, 0x9F, 0xCF, 0xE7, 0xF1, 0xFF, +0xFF, 0xFF, 0x81, 0xFF, 0x81, 0xFF, 0xFF, 0xFF, +0x8F, 0xE7, 0xF3, 0xF9, 0xF3, 0xE7, 0x8F, 0xFF, +0xC3, 0x99, 0xF9, 0xF3, 0xE7, 0xFF, 0xE7, 0xFF, +0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, +0xE7, 0xC3, 0x99, 0x81, 0x99, 0x99, 0x99, 0xFF, +0x83, 0x99, 0x99, 0x83, 0x99, 0x99, 0x83, 0xFF, +0xC3, 0x99, 0x9F, 0x9F, 0x9F, 0x99, 0xC3, 0xFF, +0x87, 0x93, 0x99, 0x99, 0x99, 0x93, 0x87, 0xFF, +0x81, 0x9F, 0x9F, 0x87, 0x9F, 0x9F, 0x81, 0xFF, +0x81, 0x9F, 0x9F, 0x87, 0x9F, 0x9F, 0x9F, 0xFF, +0xC3, 0x99, 0x9F, 0x91, 0x99, 0x99, 0xC3, 0xFF, +0x99, 0x99, 0x99, 0x81, 0x99, 0x99, 0x99, 0xFF, +0xC3, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xC3, 0xFF, +0xE1, 0xF3, 0xF3, 0xF3, 0xF3, 0x93, 0xC7, 0xFF, +0x99, 0x93, 0x87, 0x8F, 0x87, 0x93, 0x99, 0xFF, +0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x81, 0xFF, +0x9C, 0x88, 0x80, 0x94, 0x9C, 0x9C, 0x9C, 0xFF, +0x99, 0x89, 0x81, 0x81, 0x91, 0x99, 0x99, 0xFF, +0xC3, 0x99, 0x99, 0x99, 0x99, 0x99, 0xC3, 0xFF, +0x83, 0x99, 0x99, 0x83, 0x9F, 0x9F, 0x9F, 0xFF, +0xC3, 0x99, 0x99, 0x99, 0x99, 0xC3, 0xF1, 0xFF, +0x83, 0x99, 0x99, 0x83, 0x87, 0x93, 0x99, 0xFF, +0xC3, 0x99, 0x9F, 0xC3, 0xF9, 0x99, 0xC3, 0xFF, +0x81, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xFF, +0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0xC3, 0xFF, +0x99, 0x99, 0x99, 0x99, 0x99, 0xC3, 0xE7, 0xFF, +0x9C, 0x9C, 0x9C, 0x94, 0x80, 0x88, 0x9C, 0xFF, +0x99, 0x99, 0xC3, 0xE7, 0xC3, 0x99, 0x99, 0xFF, +0x99, 0x99, 0x99, 0xC3, 0xE7, 0xE7, 0xE7, 0xFF, +0x81, 0xF9, 0xF3, 0xE7, 0xCF, 0x9F, 0x81, 0xFF, +0xE7, 0xE7, 0xE7, 0x00, 0x00, 0xE7, 0xE7, 0xE7, +0x3F, 0x3F, 0xCF, 0xCF, 0x3F, 0x3F, 0xCF, 0xCF, +0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, +0xCC, 0xCC, 0x33, 0x33, 0xCC, 0xCC, 0x33, 0x33, +0xCC, 0x66, 0x33, 0x99, 0xCC, 0x66, 0x33, 0x99, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, +0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, +0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, +0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, +0x33, 0x33, 0xCC, 0xCC, 0x33, 0x33, 0xCC, 0xCC, +0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, +0xFF, 0xFF, 0xFF, 0xFF, 0x33, 0x33, 0xCC, 0xCC, +0x33, 0x66, 0xCC, 0x99, 0x33, 0x66, 0xCC, 0x99, +0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, +0xE7, 0xE7, 0xE7, 0xE0, 0xE0, 0xE7, 0xE7, 0xE7, +0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0xF0, 0xF0, +0xE7, 0xE7, 0xE7, 0xE0, 0xE0, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0x07, 0x07, 0xE7, 0xE7, 0xE7, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, +0xFF, 0xFF, 0xFF, 0xE0, 0xE0, 0xE7, 0xE7, 0xE7, +0xE7, 0xE7, 0xE7, 0x00, 0x00, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xE7, 0xE7, 0xE7, +0xE7, 0xE7, 0xE7, 0x07, 0x07, 0xE7, 0xE7, 0xE7, +0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, +0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, +0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, +0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, +0xFE, 0xFC, 0xF9, 0x93, 0x87, 0x8F, 0x9F, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x0F, 0x0F, 0x0F, +0xF0, 0xF0, 0xF0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, +0xE7, 0xE7, 0xE7, 0x07, 0x07, 0xFF, 0xFF, 0xFF, +0x0F, 0x0F, 0x0F, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, +0x0F, 0x0F, 0x0F, 0x0F, 0xF0, 0xF0, 0xF0, 0xF0 }; diff --git a/examples/graphics.cpp b/examples/graphics.cpp new file mode 100644 index 0000000..222ae12 --- /dev/null +++ b/examples/graphics.cpp @@ -0,0 +1,466 @@ +#include +#include +#include +#include +#include +#include + +#include "chargen.hpp" + +enum Colors : uint8_t { WHITE = 0x01 }; + +static volatile uint8_t &memory_loc(const uint16_t loc) { + return *reinterpret_cast(loc); +} + +static void poke(const uint16_t loc, const uint8_t value) { + memory_loc(loc) = value; +} + +static std::uint8_t peek(const std::uint16_t loc) { return memory_loc(loc); } + +static void decrement_border_color() { --memory_loc(0xd020); } + +static void increment_border_color() { ++memory_loc(0xd020); } + +static bool joystick_down() { + uint8_t joystick_state = peek(0xDC00); + return (joystick_state & 2) == 0; +} + +void use_data(std::array &data); + +static void puts(uint8_t x, uint8_t y, std::string_view str) { + const auto start = 0x400 + (y * 40 + x); + + std::memcpy(const_cast(&memory_loc(start)), str.data(), + str.size()); +} + + + +template +struct Graphic +{ + std::array data{}; + + static constexpr auto width() noexcept { + return Width; + } + + static constexpr auto height() noexcept { + return Height; + } + + constexpr Graphic() = default; + + constexpr Graphic(std::array data_) noexcept : data(data_) {} + constexpr Graphic(std::initializer_list data_) noexcept { + std::copy(begin(data_), end(data_), begin(data)); + } + + constexpr auto &operator()(const std::uint8_t x, const std::uint8_t y) noexcept { + return data[y * Width + x]; + } + + constexpr const auto &operator()(const std::uint8_t x, const std::uint8_t y) const noexcept { + return data[y * Width + x]; + } + + constexpr std::size_t match_count(const auto &graphic, const std::uint8_t x, const std::uint8_t y) const + { + std::size_t count = 0; + for (std::uint8_t cur_x = 0; cur_x < graphic.width(); ++cur_x) { + for (std::uint8_t cur_y = 0; cur_y < graphic.height(); ++cur_y) { + if (graphic(cur_x, cur_y) == (*this)(cur_x + x, cur_y + y)) { + ++count; + } + } + } + + return count; + } + + + constexpr bool match(const auto &graphic, const std::uint8_t x, const std::uint8_t y) const + { + return match_count(graphic, x, y) == (graphic.width() * graphic.height()); + } + + +}; + + +static constexpr auto load_charset(const std::span &bits) { + std::array, 256> results{}; + + for (std::size_t idx = 0; idx < 256; ++idx) { + Graphic<8,8> glyph{}; + + for (std::uint8_t row = 0; row < 8; ++row) { + const auto input_row = bits[idx*8+row]; + glyph(0, row) = (0b1000'0000 & input_row) == 0 ? 0 : 1; + glyph(1, row) = (0b0100'0000 & input_row) == 0 ? 0 : 1; + glyph(2, row) = (0b0010'0000 & input_row) == 0 ? 0 : 1; + glyph(3, row) = (0b0001'0000 & input_row) == 0 ? 0 : 1; + glyph(4, row) = (0b0000'1000 & input_row) == 0 ? 0 : 1; + glyph(5, row) = (0b0000'0100 & input_row) == 0 ? 0 : 1; + glyph(6, row) = (0b0000'0010 & input_row) == 0 ? 0 : 1; + glyph(7, row) = (0b0000'0001 & input_row) == 0 ? 0 : 1; + } + + results[idx] = glyph; + } + + return results; +} + + template + static constexpr auto from_pixels_to_petscii(const Graphic &pixels) { + Graphic result{}; + + constexpr auto charset = load_charset(uppercase); + + for (uint8_t x = 0; x < pixels.width(); x += 8) { + for (uint8_t y = 0; y < pixels.height(); y += 8) { + std::uint8_t best_match = 32; + std::size_t match_count = 0; + + std::uint8_t cur_char = 0; + for (const auto &glyph : charset) { + + const auto count = pixels.match_count(glyph, x, y); + if (count > match_count) { + best_match = cur_char; + match_count = count; + } + + ++cur_char; + } + + result(x/8, y/8) = best_match; + } + } + + return result; + } + + + template + static constexpr auto from_pixels_to_2x2(const Graphic &pixels) { + Graphic result{}; + + using GlyphType = std::pair, std::uint8_t>; + constexpr std::array lookup_map { + GlyphType{ {0,0, + 0,0}, 32 }, + GlyphType{ {1,0, + 0,0}, 126 }, + GlyphType{ {0,1, + 0,0}, 124 }, + GlyphType{ {1,1, + 0,0}, 226 }, + GlyphType{ {0,0, + 1,0}, 123 }, + GlyphType{ {1,0, + 1,0}, 97 }, + GlyphType{ {0,1, + 1,0}, 255 }, + GlyphType{ {1,1, + 1,0}, 236 }, + GlyphType{ {0,0, + 0,1}, 108 }, + GlyphType{ {1,0, + 0,1}, 127 }, + GlyphType{ {0,1, + 0,1}, 225 }, + GlyphType{ {1,1, + 0,1}, 251 }, + GlyphType{ {0,0, + 1,1}, 98 }, + GlyphType{ {1,0, + 1,1}, 252 }, + GlyphType{ {0,1, + 1,1}, 254 }, + GlyphType{ {1,1, + 1,1}, 160 } + }; + + + for (uint8_t x = 0; x < pixels.width(); x += 2) { + for (uint8_t y = 0; y < pixels.height(); y += 2) { + for (const auto &glyph : lookup_map) { + if (pixels.match(glyph.first, x, y)) { + result(x/2, y/2) = glyph.second; + break; // go to next Y, we found our match + } + } + } + } + + return result; + } + +static void putc(uint8_t x, uint8_t y, uint8_t c) { + const auto start = 0x400 + (y * 40 + x); + poke(start, c); +} + +static std::uint8_t loadc(uint8_t x, uint8_t y) { + const auto start = 0x400 + (y * 40 + x); + return peek(start); +} + + +static void put_hex(uint8_t x, uint8_t y, uint8_t value) { + const auto put_nibble = [](auto x, auto y, uint8_t nibble) { + if (nibble <= 9) { + putc(x, y, nibble + 48); + } else { + putc(x, y, nibble - 9); + } + }; + + put_nibble(x + 1, y, 0xF & value); + put_nibble(x, y, 0xF & (value >> 4)); +} + +static void put_hex(uint8_t x, uint8_t y, uint16_t value) { + put_hex(x+2,y, static_cast(0xFF & value)); + put_hex(x,y, static_cast(0xFF & (value >> 8))); +} + +static void put_graphic(uint8_t x, uint8_t y, const auto &graphic) +{ + for (uint8_t cur_y = 0; cur_y < graphic.height(); ++cur_y) { + for (uint8_t cur_x = 0; cur_x < graphic.width(); ++cur_x) { + putc(cur_x + x, cur_y + y, graphic(cur_x, cur_y)); + } + } +} + +struct Clock { + using milliseconds = std::chrono::duration; + + // return elapsed time since last restart + [[nodiscard]] milliseconds restart() noexcept { + // stop Timer A + poke(0xDC0E, 0b00000000); + + // last value + const auto previous_value = static_cast( + peek(0xDC04) | (static_cast(peek(0xDC05)) << 8)); + + // reset timer + poke(0xDC04, 0xFF); + poke(0xDC05, 0xFF); + + // restart timer A + poke(0xDC0E, 0b00010001); + + return milliseconds{0xFFFF - previous_value}; + } + + Clock() noexcept { [[maybe_unused]] const auto value = restart(); } +}; + +static void cls() { + for (std::uint16_t i = 0x400; i < 0x400 + 1000; ++i) { + poke(i, 32); + } +} + +template +struct SimpleSprite +{ + std::uint8_t x = 0; + std::uint8_t y = 0; + bool is_shown = false; + Graphic graphic; + Graphic saved_background{}; + + constexpr SimpleSprite(std::initializer_list data_) noexcept + : graphic(data_) + { + } +}; + +struct Screen +{ + void load(std::uint8_t x, std::uint8_t y, auto &s) { + for (std::uint8_t cur_y = 0; cur_y < s.height(); ++cur_y) { + for (std::uint8_t cur_x = 0; cur_x < s.width(); ++cur_x) { + s(cur_x, cur_y) = loadc(cur_x + x, cur_y + y); + } + } + } + + void show(std::uint8_t x, std::uint8_t y, auto &s) { + if (s.is_shown) { + put_graphic(s.x, s.y, s.saved_background); + } + + s.is_shown = true; + + s.x = x; + s.y = y; + load(x, y, s.saved_background); + + put_graphic(x,y,s.graphic); + } +}; + +int main() { + //static constexpr auto charset = load_charset(uppercase); + + static constexpr auto town = + Graphic<4,4> { + 85,67,67,73, + 93,233,223,93, + 93,160,160,93, + 74,67,67,75}; + + static constexpr auto mountain = + Graphic<4,4> { + 32,78,77,32, + 32,32,78,77, + 78,77,32,32, + 32,78,77,32 + }; + + + auto character = + SimpleSprite<2,3> { + 32,87, + 78,79, + 78,77 + }; + + + static constexpr auto overview_map = + Graphic<10, 5> { + 3,1,1,0,3,0,0,0,0,0, + 0,0,1,1,0,0,0,0,3,0, + 0,0,1,0,0,0,0,0,0,0, + 0,3,0,0,0,0,0,0,0,0, + 0,1,1,1,0,0,3,0,0,0, + }; + + + + cls(); + + poke(53280,0); + poke(53281,0); + + static constexpr std::array tile_types{ + [](std::uint8_t x, std::uint8_t y) { + /* do nothing for 0th */ + }, + [](std::uint8_t x, std::uint8_t y) { + put_graphic(x,y,mountain); + }, + [](std::uint8_t x, std::uint8_t y) { + /* do nothing for 2 */ + }, + [](std::uint8_t x, std::uint8_t y) { + put_graphic(x,y,town); + }, + }; + + + const auto draw_map = [](const auto &map) { + for (std::size_t tile = 0; tile < tile_types.size(); ++tile) { + for (std::uint8_t map_large_y =0; map_large_y < map.height(); ++map_large_y) { + for (std::uint8_t map_large_x = 0; map_large_x < map.width(); ++map_large_x) { + if (map(map_large_x,map_large_y) == tile) { + tile_types[tile](map_large_x*4,map_large_y*4); + } + } + } + } + }; + + constexpr auto draw_box = [](uint8_t x, uint8_t y, uint8_t width, uint8_t height) { + putc(x,y, 85); + putc(x+width-1,y, 73); + putc(x+width-1,y+height-1,75); + putc(x,y+height-1,74); + + for (uint8_t cur_x = x+1; cur_x < x+width-1; ++cur_x) { + putc(cur_x, y, 67); + putc(cur_x, y+height-1, 67); + } + + for (uint8_t cur_y = y+1; cur_y < y+height-1; ++cur_y) { + putc(x, cur_y, 93); + putc(x+width-1, cur_y, 93); + } + }; + + + struct GameState { + + std::uint8_t endurance{10}; + std::uint8_t stamina{max_stamina()}; + std::uint16_t cash{100}; + + constexpr std::uint8_t max_stamina() const { + return endurance * 5; + } + + }; + + GameState game; + +// draw_map(map1); + draw_map(overview_map); + draw_box(0,20,40,5); + + constexpr auto show_stats = [](const auto &cur_game) { + puts(1, 21, "stamina:"); + put_hex(12, 21, cur_game.stamina); + put_hex(15, 21, cur_game.max_stamina()); + puts(14,21, "/"); + puts(1, 22, "endurance:"); + put_hex(12,22, cur_game.endurance); + puts(1,23, "cash: "); + put_hex(12,23, cur_game.cash); + }; + + Clock game_clock{}; + Screen screen; + + show_stats(game); + + std::uint8_t x = 0; + + while (true) { + const auto us_elapsed = game_clock.restart().count(); +// show_stats(game); + put_hex(36, 0, us_elapsed); + + screen.show(x++, 10, character); + + if (x == 36) { + x = 0; + } + increment_border_color(); + } + + /* + const auto background_color = [](Colors col) { + memory_loc(0xd021) = static_cast(col); + }; + + background_color(Colors::WHITE); + + while(true) { + if (joystick_down()) { + increment_border_color(); + } else { + decrement_border_color(); + } + } + */ +}