Pet2001 Font

Source: src/pet2001_font.c · 138 lines · 8 functions.

Module entry points

These functions are exposed to the rest of the project. Open one to follow its decisions and the helpers it calls.

How to read these diagrams

Each function has its own expandable diagram using the actual expressions and statements from this file. Decisions split into True and False; loop bodies are indented. Returns end the function immediately; break and continue follow their C meanings. Arrows between statements show their order when execution reaches them.

These are structural source diagrams before preprocessing, not runtime traces. Conditional compilation and macros remain source expressions. Ternary choices remain inside their statement. Calls are linked separately; callback execution and task scheduling are not inferred.

Functions in this file

drawPet2001Glyph() · source line 13
void drawPet2001Glyph(uint16_t *frame, int x, int y, uint8_t glyph, bool reverse,
                      uint16_t foreground, uint16_t background, int scale)

Calls into this documentation:

  1. Decisionframe == NULL || scale <= 0 || scale > INT_MAX / PET2001_FONT_GLYPH_WIDTH
    True
    1. Exit this functionreturn;
    False

    Continue after this decision.

  2. FOR loopunsigned row = 0U; row < PET2001_FONT_GLYPH_HEIGHT; ++row

    Repeat body while the loop condition permits; then continue below.

      1. Executeconst uint8_t bits = PET2001_FONT[glyph][row];
      2. FOR loopunsigned column = 0U; column < PET2001_FONT_GLYPH_WIDTH; ++column

        Repeat body while the loop condition permits; then continue below.

          1. Executebool pixel = (bits & (0x80U >> column)) != 0U;
          2. Decisionreverse
            True
            1. Executepixel = !pixel;
            False

            Continue after this decision.

          3. Executefill_rect(frame, x + (int)column * scale, y + (int)row * scale, scale, scale, pixel ? foreground : background);
Read original function source
void drawPet2001Glyph(uint16_t *frame, int x, int y, uint8_t glyph, bool reverse,
                      uint16_t foreground, uint16_t background, int scale)
{
    if (frame == NULL || scale <= 0 || scale > INT_MAX / PET2001_FONT_GLYPH_WIDTH) return;

    for (unsigned row = 0U; row < PET2001_FONT_GLYPH_HEIGHT; ++row) {
        const uint8_t bits = PET2001_FONT[glyph][row];
        for (unsigned column = 0U; column < PET2001_FONT_GLYPH_WIDTH; ++column) {
            bool pixel = (bits & (0x80U >> column)) != 0U;
            if (reverse) pixel = !pixel;
            fill_rect(frame, x + (int)column * scale, y + (int)row * scale,
                      scale, scale, pixel ? foreground : background);
        }
    }
}
drawPet2001Char() · source line 29
void drawPet2001Char(uint16_t *frame, int x, int y, uint8_t character,
                     uint16_t foreground, uint16_t background, int scale)

Calls into this documentation:

  1. ExecutedrawPet2001Glyph(frame, x, y, character & 0x7FU, (character & 0x80U) != 0U, foreground, background, scale);
Read original function source
void drawPet2001Char(uint16_t *frame, int x, int y, uint8_t character,
                     uint16_t foreground, uint16_t background, int scale)
{
    drawPet2001Glyph(frame, x, y, character & 0x7FU, (character & 0x80U) != 0U,
                     foreground, background, scale);
}
petCodeFromAscii() · source line 36
static uint8_t petCodeFromAscii(char character)
  1. Decisioncharacter >= 'A' && character <= 'Z'
    True
    1. Exit this functionreturn (uint8_t)(character - 'A' + 1);
    False

    Continue after this decision.

  2. Decisioncharacter >= 'a' && character <= 'z'
    True
    1. Exit this functionreturn (uint8_t)(character - 'a' + 1);
    False

    Continue after this decision.

  3. Exit this functionreturn (uint8_t)character;
Read original function source
static uint8_t petCodeFromAscii(char character)
{
    if (character >= 'A' && character <= 'Z') return (uint8_t)(character - 'A' + 1);
    if (character >= 'a' && character <= 'z') return (uint8_t)(character - 'a' + 1);
    return (uint8_t)character;
}
drawPet2001AsciiCharTransformed() · source line 43
void drawPet2001AsciiCharTransformed(uint16_t *frame, int centre_x, int centre_y,
                                     char character, float scale, float angle_degrees,
                                     uint16_t foreground)

Calls into this documentation:

  1. Executeconst uint8_t glyph = petCodeFromAscii(character);
  2. Executedraw_bitmap_transformed(frame, centre_x, centre_y, PET2001_FONT[glyph], PET2001_FONT_GLYPH_WIDTH, PET2001_FONT_GLYPH_HEIGHT, scale, angle_degrees, foreground);
Read original function source
void drawPet2001AsciiCharTransformed(uint16_t *frame, int centre_x, int centre_y,
                                     char character, float scale, float angle_degrees,
                                     uint16_t foreground)
{
    const uint8_t glyph = petCodeFromAscii(character);
    draw_bitmap_transformed(frame, centre_x, centre_y, PET2001_FONT[glyph],
                            PET2001_FONT_GLYPH_WIDTH, PET2001_FONT_GLYPH_HEIGHT,
                            scale, angle_degrees, foreground);
}
drawPet2001TextTransformed() · source line 53
void drawPet2001TextTransformed(uint16_t *frame, int destination_centre_x,
                                 int destination_centre_y, const char *text,
                                 int source_scale, float transform_scale,
                                 float angle_degrees, uint16_t foreground)

Calls into this documentation:

  1. Decisionframe == NULL || text == NULL || source_scale <= 0 || source_scale > INT_MAX / PET2001_FONT_GLYPH_WIDTH || transform_scale <= 0.0f || !isfinite(transform_scale) || !isfinite(angle_degrees)
    True
    1. Exit this functionreturn;
    False

    Continue after this decision.

  2. Executeconst size_t length = strlen(text);
  3. Decisionlength == 0U || length > (size_t)INT_MAX / (PET2001_FONT_GLYPH_WIDTH * source_scale)
    True
    1. Exit this functionreturn;
    False

    Continue after this decision.

  4. Executeconst int source_width = (int)length * PET2001_FONT_GLYPH_WIDTH * source_scale;
  5. Executeconst int source_height = PET2001_FONT_GLYPH_HEIGHT * source_scale;
  6. Executeconst float radians = angle_degrees * 0.01745329252f;
  7. Executeconst float cosine = cosf(radians), sine = sinf(radians);
  8. Executeconst float centre_x = ((float)source_width - 1.0f) * 0.5f;
  9. Executeconst float centre_y = ((float)source_height - 1.0f) * 0.5f;
  10. FOR loopsize_t character = 0U; character < length; ++character

    Repeat body while the loop condition permits; then continue below.

      1. Executeconst uint8_t *glyph = PET2001_FONT[petCodeFromAscii(text[character])];
      2. Executeconst int glyph_x = (int)character * PET2001_FONT_GLYPH_WIDTH * source_scale;
      3. FOR loopint row = 0; row < (int)PET2001_FONT_GLYPH_HEIGHT; ++row

        Repeat body while the loop condition permits; then continue below.

          1. FOR loopint column = 0; column < (int)PET2001_FONT_GLYPH_WIDTH; ++column

            Repeat body while the loop condition permits; then continue below.

              1. Decision(glyph[row] & (0x80U >> column)) == 0U
                True
                1. Next loop iterationcontinue;
                False

                Continue after this decision.

              2. FOR loopint pixel_y = 0; pixel_y < source_scale; ++pixel_y

                Repeat body while the loop condition permits; then continue below.

                  1. FOR loopint pixel_x = 0; pixel_x < source_scale; ++pixel_x

                    Repeat body while the loop condition permits; then continue below.

                      1. Executeconst float source_x = glyph_x + column * source_scale + pixel_x - centre_x;
                      2. Executeconst float source_y = row * source_scale + pixel_y - centre_y;
                      3. Executeconst int destination_x = (int)lroundf(destination_centre_x + (cosine * source_x - sine * source_y) * transform_scale);
                      4. Executeconst int destination_y = (int)lroundf(destination_centre_y + (sine * source_x + cosine * source_y) * transform_scale);
                      5. Decisiondestination_x >= 0 && destination_x < LCD_WIDTH && destination_y >= 0 && destination_y < LCD_HEIGHT
                        True
                        1. Executeframe[(size_t)destination_y * LCD_WIDTH + destination_x] = foreground;
                        False

                        Continue after this decision.

Read original function source
void drawPet2001TextTransformed(uint16_t *frame, int destination_centre_x,
                                 int destination_centre_y, const char *text,
                                 int source_scale, float transform_scale,
                                 float angle_degrees, uint16_t foreground)
{
    if (frame == NULL || text == NULL || source_scale <= 0 ||
        source_scale > INT_MAX / PET2001_FONT_GLYPH_WIDTH ||
        transform_scale <= 0.0f || !isfinite(transform_scale) ||
        !isfinite(angle_degrees)) return;

    const size_t length = strlen(text);
    if (length == 0U || length > (size_t)INT_MAX /
        (PET2001_FONT_GLYPH_WIDTH * source_scale)) return;

    const int source_width = (int)length * PET2001_FONT_GLYPH_WIDTH * source_scale;
    const int source_height = PET2001_FONT_GLYPH_HEIGHT * source_scale;
    const float radians = angle_degrees * 0.01745329252f;
    const float cosine = cosf(radians), sine = sinf(radians);
    const float centre_x = ((float)source_width - 1.0f) * 0.5f;
    const float centre_y = ((float)source_height - 1.0f) * 0.5f;

    for (size_t character = 0U; character < length; ++character) {
        const uint8_t *glyph = PET2001_FONT[petCodeFromAscii(text[character])];
        const int glyph_x = (int)character * PET2001_FONT_GLYPH_WIDTH * source_scale;
        for (int row = 0; row < (int)PET2001_FONT_GLYPH_HEIGHT; ++row) {
            for (int column = 0; column < (int)PET2001_FONT_GLYPH_WIDTH; ++column) {
                if ((glyph[row] & (0x80U >> column)) == 0U) continue;
                for (int pixel_y = 0; pixel_y < source_scale; ++pixel_y) {
                    for (int pixel_x = 0; pixel_x < source_scale; ++pixel_x) {
                        const float source_x = glyph_x + column * source_scale + pixel_x - centre_x;
                        const float source_y = row * source_scale + pixel_y - centre_y;
                        const int destination_x = (int)lroundf(destination_centre_x +
                            (cosine * source_x - sine * source_y) * transform_scale);
                        const int destination_y = (int)lroundf(destination_centre_y +
                            (sine * source_x + cosine * source_y) * transform_scale);
                        if (destination_x >= 0 && destination_x < LCD_WIDTH &&
                            destination_y >= 0 && destination_y < LCD_HEIGHT)
                            frame[(size_t)destination_y * LCD_WIDTH + destination_x] = foreground;
                    }
                }
            }
        }
    }
}
drawPet2001Text() · source line 98
void drawPet2001Text(uint16_t *frame, int x, int y, const char *text, bool reverse,
                     uint16_t foreground, uint16_t background, int scale)

Calls into this documentation:

  1. Decisionframe == NULL || text == NULL || scale <= 0 || scale > INT_MAX / PET2001_FONT_GLYPH_WIDTH
    True
    1. Exit this functionreturn;
    False

    Continue after this decision.

  2. FOR loopsize_t index = 0U; text[index] != '\0'; ++index

    Repeat body while the loop condition permits; then continue below.

      1. Executeuint8_t character = petCodeFromAscii(text[index]);
      2. Decisionreverse
        True
        1. Executecharacter |= 0x80U;
        False

        Continue after this decision.

      3. ExecutedrawPet2001Char(frame, x + (int)index * PET2001_FONT_GLYPH_WIDTH * scale, y, character, foreground, background, scale);
Read original function source
void drawPet2001Text(uint16_t *frame, int x, int y, const char *text, bool reverse,
                     uint16_t foreground, uint16_t background, int scale)
{
    if (frame == NULL || text == NULL || scale <= 0 ||
        scale > INT_MAX / PET2001_FONT_GLYPH_WIDTH) return;

    for (size_t index = 0U; text[index] != '\0'; ++index) {
        uint8_t character = petCodeFromAscii(text[index]);
        if (reverse) character |= 0x80U;
        drawPet2001Char(frame, x + (int)index * PET2001_FONT_GLYPH_WIDTH * scale, y,
                        character, foreground, background, scale);
    }
}
drawPet2001TextTransparent() · source line 112
void drawPet2001TextTransparent(uint16_t *frame, int x, int y, const char *text,
                                 uint16_t foreground, int scale)

Calls into this documentation:

  1. Decisionframe == NULL || text == NULL || scale <= 0 || scale > INT_MAX / PET2001_FONT_GLYPH_WIDTH
    True
    1. Exit this functionreturn;
    False

    Continue after this decision.

  2. FOR loopsize_t index = 0U; text[index] != '\0'; ++index

    Repeat body while the loop condition permits; then continue below.

      1. Executeconst uint8_t *glyph = PET2001_FONT[petCodeFromAscii(text[index])];
      2. Executeconst int glyph_x = x + (int)index * PET2001_FONT_GLYPH_WIDTH * scale;
      3. FOR loopunsigned row = 0U; row < PET2001_FONT_GLYPH_HEIGHT; ++row

        Repeat body while the loop condition permits; then continue below.

          1. FOR loopunsigned column = 0U; column < PET2001_FONT_GLYPH_WIDTH; ++column

            Repeat body while the loop condition permits; then continue below.

              1. Decision(glyph[row] & (0x80U >> column)) == 0U
                True
                1. Next loop iterationcontinue;
                False

                Continue after this decision.

              2. Executefill_rect(frame, glyph_x + (int)column * scale, y + (int)row * scale, scale, scale, foreground);
Read original function source
void drawPet2001TextTransparent(uint16_t *frame, int x, int y, const char *text,
                                 uint16_t foreground, int scale)
{
    if (frame == NULL || text == NULL || scale <= 0 ||
        scale > INT_MAX / PET2001_FONT_GLYPH_WIDTH) return;

    for (size_t index = 0U; text[index] != '\0'; ++index) {
        const uint8_t *glyph = PET2001_FONT[petCodeFromAscii(text[index])];
        const int glyph_x = x + (int)index * PET2001_FONT_GLYPH_WIDTH * scale;
        for (unsigned row = 0U; row < PET2001_FONT_GLYPH_HEIGHT; ++row) {
            for (unsigned column = 0U; column < PET2001_FONT_GLYPH_WIDTH; ++column) {
                if ((glyph[row] & (0x80U >> column)) == 0U) continue;
                fill_rect(frame, glyph_x + (int)column * scale, y + (int)row * scale,
                          scale, scale, foreground);
            }
        }
    }
}
drawPet2001TextCentredTransparent() · source line 131
void drawPet2001TextCentredTransparent(uint16_t *frame, int centre_x, int y,
                                        const char *text, uint16_t foreground, int scale)

Calls into this documentation:

  1. Decisiontext == NULL || scale <= 0 || strlen(text) > (size_t)INT_MAX / (PET2001_FONT_GLYPH_WIDTH * scale)
    True
    1. Exit this functionreturn;
    False

    Continue after this decision.

  2. Executeconst int width = (int)strlen(text) * PET2001_FONT_GLYPH_WIDTH * scale;
  3. ExecutedrawPet2001TextTransparent(frame, centre_x - width / 2, y, text, foreground, scale);
Read original function source
void drawPet2001TextCentredTransparent(uint16_t *frame, int centre_x, int y,
                                        const char *text, uint16_t foreground, int scale)
{
    if (text == NULL || scale <= 0 ||
        strlen(text) > (size_t)INT_MAX / (PET2001_FONT_GLYPH_WIDTH * scale)) return;
    const int width = (int)strlen(text) * PET2001_FONT_GLYPH_WIDTH * scale;
    drawPet2001TextTransparent(frame, centre_x - width / 2, y, text, foreground, scale);
}
Complete original file, including constants and data
/* Coded By JD(2026) */
#error "Reference listing only — not provided as build-ready source."
// Own the single global PET 2001 character-ROM definition.
#define PET2001_FONT_IMPLEMENTATION
#include "PET2001_font.h"

#include <stdbool.h>
#include <stddef.h>
#include <limits.h>
#include <math.h>
#include <string.h>

#include "game_graphics.h"

void drawPet2001Glyph(uint16_t *frame, int x, int y, uint8_t glyph, bool reverse,
                      uint16_t foreground, uint16_t background, int scale)
{
    if (frame == NULL || scale <= 0 || scale > INT_MAX / PET2001_FONT_GLYPH_WIDTH) return;

    for (unsigned row = 0U; row < PET2001_FONT_GLYPH_HEIGHT; ++row) {
        const uint8_t bits = PET2001_FONT[glyph][row];
        for (unsigned column = 0U; column < PET2001_FONT_GLYPH_WIDTH; ++column) {
            bool pixel = (bits & (0x80U >> column)) != 0U;
            if (reverse) pixel = !pixel;
            fill_rect(frame, x + (int)column * scale, y + (int)row * scale,
                      scale, scale, pixel ? foreground : background);
        }
    }
}

void drawPet2001Char(uint16_t *frame, int x, int y, uint8_t character,
                     uint16_t foreground, uint16_t background, int scale)
{
    drawPet2001Glyph(frame, x, y, character & 0x7FU, (character & 0x80U) != 0U,
                     foreground, background, scale);
}

static uint8_t petCodeFromAscii(char character)
{
    if (character >= 'A' && character <= 'Z') return (uint8_t)(character - 'A' + 1);
    if (character >= 'a' && character <= 'z') return (uint8_t)(character - 'a' + 1);
    return (uint8_t)character;
}

void drawPet2001AsciiCharTransformed(uint16_t *frame, int centre_x, int centre_y,
                                     char character, float scale, float angle_degrees,
                                     uint16_t foreground)
{
    const uint8_t glyph = petCodeFromAscii(character);
    draw_bitmap_transformed(frame, centre_x, centre_y, PET2001_FONT[glyph],
                            PET2001_FONT_GLYPH_WIDTH, PET2001_FONT_GLYPH_HEIGHT,
                            scale, angle_degrees, foreground);
}

void drawPet2001TextTransformed(uint16_t *frame, int destination_centre_x,
                                 int destination_centre_y, const char *text,
                                 int source_scale, float transform_scale,
                                 float angle_degrees, uint16_t foreground)
{
    if (frame == NULL || text == NULL || source_scale <= 0 ||
        source_scale > INT_MAX / PET2001_FONT_GLYPH_WIDTH ||
        transform_scale <= 0.0f || !isfinite(transform_scale) ||
        !isfinite(angle_degrees)) return;

    const size_t length = strlen(text);
    if (length == 0U || length > (size_t)INT_MAX /
        (PET2001_FONT_GLYPH_WIDTH * source_scale)) return;

    const int source_width = (int)length * PET2001_FONT_GLYPH_WIDTH * source_scale;
    const int source_height = PET2001_FONT_GLYPH_HEIGHT * source_scale;
    const float radians = angle_degrees * 0.01745329252f;
    const float cosine = cosf(radians), sine = sinf(radians);
    const float centre_x = ((float)source_width - 1.0f) * 0.5f;
    const float centre_y = ((float)source_height - 1.0f) * 0.5f;

    for (size_t character = 0U; character < length; ++character) {
        const uint8_t *glyph = PET2001_FONT[petCodeFromAscii(text[character])];
        const int glyph_x = (int)character * PET2001_FONT_GLYPH_WIDTH * source_scale;
        for (int row = 0; row < (int)PET2001_FONT_GLYPH_HEIGHT; ++row) {
            for (int column = 0; column < (int)PET2001_FONT_GLYPH_WIDTH; ++column) {
                if ((glyph[row] & (0x80U >> column)) == 0U) continue;
                for (int pixel_y = 0; pixel_y < source_scale; ++pixel_y) {
                    for (int pixel_x = 0; pixel_x < source_scale; ++pixel_x) {
                        const float source_x = glyph_x + column * source_scale + pixel_x - centre_x;
                        const float source_y = row * source_scale + pixel_y - centre_y;
                        const int destination_x = (int)lroundf(destination_centre_x +
                            (cosine * source_x - sine * source_y) * transform_scale);
                        const int destination_y = (int)lroundf(destination_centre_y +
                            (sine * source_x + cosine * source_y) * transform_scale);
                        if (destination_x >= 0 && destination_x < LCD_WIDTH &&
                            destination_y >= 0 && destination_y < LCD_HEIGHT)
                            frame[(size_t)destination_y * LCD_WIDTH + destination_x] = foreground;
                    }
                }
            }
        }
    }
}

void drawPet2001Text(uint16_t *frame, int x, int y, const char *text, bool reverse,
                     uint16_t foreground, uint16_t background, int scale)
{
    if (frame == NULL || text == NULL || scale <= 0 ||
        scale > INT_MAX / PET2001_FONT_GLYPH_WIDTH) return;

    for (size_t index = 0U; text[index] != '\0'; ++index) {
        uint8_t character = petCodeFromAscii(text[index]);
        if (reverse) character |= 0x80U;
        drawPet2001Char(frame, x + (int)index * PET2001_FONT_GLYPH_WIDTH * scale, y,
                        character, foreground, background, scale);
    }
}

void drawPet2001TextTransparent(uint16_t *frame, int x, int y, const char *text,
                                 uint16_t foreground, int scale)
{
    if (frame == NULL || text == NULL || scale <= 0 ||
        scale > INT_MAX / PET2001_FONT_GLYPH_WIDTH) return;

    for (size_t index = 0U; text[index] != '\0'; ++index) {
        const uint8_t *glyph = PET2001_FONT[petCodeFromAscii(text[index])];
        const int glyph_x = x + (int)index * PET2001_FONT_GLYPH_WIDTH * scale;
        for (unsigned row = 0U; row < PET2001_FONT_GLYPH_HEIGHT; ++row) {
            for (unsigned column = 0U; column < PET2001_FONT_GLYPH_WIDTH; ++column) {
                if ((glyph[row] & (0x80U >> column)) == 0U) continue;
                fill_rect(frame, glyph_x + (int)column * scale, y + (int)row * scale,
                          scale, scale, foreground);
            }
        }
    }
}

void drawPet2001TextCentredTransparent(uint16_t *frame, int centre_x, int y,
                                        const char *text, uint16_t foreground, int scale)
{
    if (text == NULL || scale <= 0 ||
        strlen(text) > (size_t)INT_MAX / (PET2001_FONT_GLYPH_WIDTH * scale)) return;
    const int width = (int)strlen(text) * PET2001_FONT_GLYPH_WIDTH * scale;
    drawPet2001TextTransparent(frame, centre_x - width / 2, y, text, foreground, scale);
}