Turbo Loader

Source: src/turbo_loader.c · 135 lines · 6 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

is_game_screen() · source line 35
static bool is_game_screen(screen_id_t screen)
  1. Exit this functionreturn screen == SCREEN_CHECKERS || screen == SCREEN_OTHELLO || screen == SCREEN_CONNECT_FOUR || screen == SCREEN_BATTLESHIPS || screen == SCREEN_BATTLE_ZONE || screen == SCREEN_BOULDER_DASH || screen == SCREEN_YAHTZEE || screen == SCREEN_BLACKJACK || screen == SCREEN_POKER || screen == SCREEN_POKER_DICE || screen == SCREEN_PIG || screen == SCREEN_ASTEROIDS || screen == SCREEN_TEMPEST || screen == SCREEN_INVADERS || screen == SCREEN_MISSILE_COMMAND || screen == SCREEN_SCRAMBLE || screen == SCREEN_BREAKOUT || screen == SCREEN_CRAWLER || screen == SCREEN_MAZE_CHASE || screen == SCREEN_SIMON || screen == SCREEN_DEFENDER || screen == SCREEN_GALAGA || screen == SCREEN_DUNGEON;
Read original function source
static bool is_game_screen(screen_id_t screen)
{
    return screen == SCREEN_CHECKERS || screen == SCREEN_OTHELLO ||
           screen == SCREEN_CONNECT_FOUR || screen == SCREEN_BATTLESHIPS ||
           screen == SCREEN_BATTLE_ZONE || screen == SCREEN_BOULDER_DASH ||
           screen == SCREEN_YAHTZEE || screen == SCREEN_BLACKJACK ||
           screen == SCREEN_POKER || screen == SCREEN_POKER_DICE ||
           screen == SCREEN_PIG || screen == SCREEN_ASTEROIDS ||
           screen == SCREEN_TEMPEST || screen == SCREEN_INVADERS ||
           screen == SCREEN_MISSILE_COMMAND || screen == SCREEN_SCRAMBLE ||
           screen == SCREEN_BREAKOUT || screen == SCREEN_CRAWLER ||
           screen == SCREEN_MAZE_CHASE || screen == SCREEN_SIMON ||
           screen == SCREEN_DEFENDER || screen == SCREEN_GALAGA ||
           screen == SCREEN_DUNGEON;
}
loader_screen_name() · source line 51
static const char *loader_screen_name(screen_id_t screen)
  1. Select a casescreen

    Enter matching case; follow source fall-through until a break, return or end.

      1. Case / labelcase SCREEN_CHECKERS:
      2. Exit this functionreturn "CHECKERS";
      3. Case / labelcase SCREEN_OTHELLO:
      4. Exit this functionreturn "OTHELLO";
      5. Case / labelcase SCREEN_CONNECT_FOUR:
      6. Exit this functionreturn "CONNECT 4";
      7. Case / labelcase SCREEN_BATTLESHIPS:
      8. Exit this functionreturn "BATTLESHIPS";
      9. Case / labelcase SCREEN_BATTLE_ZONE:
      10. Exit this functionreturn "BATTLE ZONE";
      11. Case / labelcase SCREEN_BOULDER_DASH:
      12. Exit this functionreturn "BOULDER DASH";
      13. Case / labelcase SCREEN_YAHTZEE:
      14. Exit this functionreturn "YAHTZEE";
      15. Case / labelcase SCREEN_BLACKJACK:
      16. Exit this functionreturn "BLACKJACK";
      17. Case / labelcase SCREEN_POKER:
      18. Exit this functionreturn "POKER";
      19. Case / labelcase SCREEN_POKER_DICE:
      20. Exit this functionreturn "POKER DICE";
      21. Case / labelcase SCREEN_PIG:
      22. Exit this functionreturn "PIG";
      23. Case / labelcase SCREEN_ASTEROIDS:
      24. Exit this functionreturn "ASTEROIDS";
      25. Case / labelcase SCREEN_TEMPEST:
      26. Exit this functionreturn "TEMPEST";
      27. Case / labelcase SCREEN_INVADERS:
      28. Exit this functionreturn "INVADERS";
      29. Case / labelcase SCREEN_MISSILE_COMMAND:
      30. Exit this functionreturn "MISSILE COMMAND";
      31. Case / labelcase SCREEN_SCRAMBLE:
      32. Exit this functionreturn "SCRAMBLE";
      33. Case / labelcase SCREEN_BREAKOUT:
      34. Exit this functionreturn "BREAKOUT";
      35. Case / labelcase SCREEN_CRAWLER:
      36. Exit this functionreturn "CRAWLER";
      37. Case / labelcase SCREEN_MAZE_CHASE:
      38. Exit this functionreturn "MAZE CHASE";
      39. Case / labelcase SCREEN_SIMON:
      40. Exit this functionreturn "SIMON";
      41. Case / labelcase SCREEN_DEFENDER:
      42. Exit this functionreturn "DEFENDER";
      43. Case / labelcase SCREEN_GALAGA:
      44. Exit this functionreturn "GALAGA";
      45. Case / labelcase SCREEN_DUNGEON:
      46. Exit this functionreturn "DUNGEON";
      47. Case / labeldefault:
      48. Exit this functionreturn "GAME";
Read original function source
static const char *loader_screen_name(screen_id_t screen)
{
    switch (screen) {
        case SCREEN_CHECKERS: return "CHECKERS";
        case SCREEN_OTHELLO: return "OTHELLO";
        case SCREEN_CONNECT_FOUR: return "CONNECT 4";
        case SCREEN_BATTLESHIPS: return "BATTLESHIPS";
        case SCREEN_BATTLE_ZONE: return "BATTLE ZONE";
        case SCREEN_BOULDER_DASH: return "BOULDER DASH";
        case SCREEN_YAHTZEE: return "YAHTZEE";
        case SCREEN_BLACKJACK: return "BLACKJACK";
        case SCREEN_POKER: return "POKER";
        case SCREEN_POKER_DICE: return "POKER DICE";
        case SCREEN_PIG: return "PIG";
        case SCREEN_ASTEROIDS: return "ASTEROIDS";
        case SCREEN_TEMPEST: return "TEMPEST";
        case SCREEN_INVADERS: return "INVADERS";
        case SCREEN_MISSILE_COMMAND: return "MISSILE COMMAND";
        case SCREEN_SCRAMBLE: return "SCRAMBLE";
        case SCREEN_BREAKOUT: return "BREAKOUT";
        case SCREEN_CRAWLER: return "CRAWLER";
        case SCREEN_MAZE_CHASE: return "MAZE CHASE";
        case SCREEN_SIMON: return "SIMON";
        case SCREEN_DEFENDER: return "DEFENDER";
        case SCREEN_GALAGA: return "GALAGA";
        case SCREEN_DUNGEON: return "DUNGEON";
        default: return "GAME";
    }
}
turboLoaderUpdate() · source line 81
void turboLoaderUpdate(screen_id_t requested_screen, uint32_t now_ms)

Calls into this documentation:

  1. Decision!is_game_screen(requested_screen)
    True
      1. Executeloader_active = false;
      2. Executeloader_screen = SCREEN_MENU;
      3. Exit this functionreturn;
    False

    Continue after this decision.

  2. Decisionrequested_screen != loader_screen
    True
      1. Executeloader_screen = requested_screen;
      2. Executeloader_started_ms = now_ms;
      3. Executeloader_active = true;
    False

    Continue after this decision.

  3. Decisionloader_active && now_ms - loader_started_ms >= TURBO_LOADER_DURATION_MS
    True
      1. Executeloader_active = false;
    False

    Continue after this decision.

Read original function source
void turboLoaderUpdate(screen_id_t requested_screen, uint32_t now_ms)
{
    if (!is_game_screen(requested_screen)) {
        loader_active = false;
        loader_screen = SCREEN_MENU;
        return;
    }

    if (requested_screen != loader_screen) {
        loader_screen = requested_screen;
        loader_started_ms = now_ms;
        loader_active = true;
    }

    if (loader_active && now_ms - loader_started_ms >= TURBO_LOADER_DURATION_MS) {
        loader_active = false;
    }
}
turboLoaderActive() · source line 100
bool turboLoaderActive(void)
  1. Exit this functionreturn loader_active;
Read original function source
bool turboLoaderActive(void)
{
    return loader_active;
}
stripe_noise() · source line 105
static uint32_t stripe_noise(uint32_t value)
  1. Executevalue ^= value << 13;
  2. Executevalue ^= value >> 17;
  3. Executevalue ^= value << 5;
  4. Exit this functionreturn value;
Read original function source
static uint32_t stripe_noise(uint32_t value)
{
    value ^= value << 13;
    value ^= value >> 17;
    value ^= value << 5;
    return value;
}
drawTurboLoader() · source line 113
void drawTurboLoader(uint16_t *frame, uint32_t now_ms)

Calls into this documentation:

  1. Executeclear(frame, C64_COLOR_BLACK);
  2. Executeconst uint32_t phase = now_ms / 80U;
  3. Executeconst uint16_t band_colour = turbo_colours[stripe_noise(phase) % (sizeof(turbo_colours) / sizeof(turbo_colours[0]))];
  4. FOR loopint y = 0; y < LCD_HEIGHT; y += TURBO_LOADER_BAR_SPACING

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

      1. Executefill_rect(frame, 0, y, LCD_WIDTH, TURBO_LOADER_BAR_HEIGHT, band_colour);
  5. Executeconst int window_x = (LCD_WIDTH - TURBO_LOADER_WINDOW_WIDTH) / 2;
  6. Executeconst int window_y = (LCD_HEIGHT - TURBO_LOADER_WINDOW_HEIGHT) / 2;
  7. Executechar loading_text[32];
  8. Executesnprintf(loading_text, sizeof(loading_text), "LOADING - %s", loader_screen_name(loader_screen));
  9. Executefill_rect(frame, window_x, window_y, TURBO_LOADER_WINDOW_WIDTH, TURBO_LOADER_WINDOW_HEIGHT, C64_COLOR_BLACK);
  10. ExecutedrawPet2001TextCentredTransparent(frame, LCD_WIDTH / 2, window_y + (TURBO_LOADER_WINDOW_HEIGHT - PET2001_FONT_GLYPH_HEIGHT) / 2, loading_text, C64_COLOR_ORANGE, 1);
Read original function source
void drawTurboLoader(uint16_t *frame, uint32_t now_ms)
{
    // Full horizontal colour bands match the C64 Ocean/Turbo Tape display.
    clear(frame, C64_COLOR_BLACK);

    const uint32_t phase = now_ms / 80U;
    const uint16_t band_colour = turbo_colours[stripe_noise(phase) %
        (sizeof(turbo_colours) / sizeof(turbo_colours[0]))];
    for (int y = 0; y < LCD_HEIGHT; y += TURBO_LOADER_BAR_SPACING) {
        fill_rect(frame, 0, y, LCD_WIDTH, TURBO_LOADER_BAR_HEIGHT, band_colour);
    }

    const int window_x = (LCD_WIDTH - TURBO_LOADER_WINDOW_WIDTH) / 2;
    const int window_y = (LCD_HEIGHT - TURBO_LOADER_WINDOW_HEIGHT) / 2;
    char loading_text[32];
    snprintf(loading_text, sizeof(loading_text), "LOADING - %s", loader_screen_name(loader_screen));
    fill_rect(frame, window_x, window_y, TURBO_LOADER_WINDOW_WIDTH,
              TURBO_LOADER_WINDOW_HEIGHT, C64_COLOR_BLACK);
    drawPet2001TextCentredTransparent(frame, LCD_WIDTH / 2,
                                       window_y + (TURBO_LOADER_WINDOW_HEIGHT - PET2001_FONT_GLYPH_HEIGHT) / 2,
                                       loading_text,
                                       C64_COLOR_ORANGE, 1);
}
Complete original file, including constants and data
/* Coded By JD(2026) */
#error "Reference listing only — not provided as build-ready source."
#include "turbo_loader.h"

#include "c64_colors.h"
#include "game_graphics.h"
#include "PET2001_font.h"

#include <stdio.h>

#define TURBO_LOADER_DURATION_MS 1100U
#define TURBO_LOADER_BAR_HEIGHT  4
#define TURBO_LOADER_BAR_SPACING 8
#define TURBO_LOADER_WINDOW_WIDTH 256
#define TURBO_LOADER_WINDOW_HEIGHT 128

static bool loader_active;
static screen_id_t loader_screen = SCREEN_MENU;
static uint32_t loader_started_ms;

// Bright C64 colours only: black remains the Turbo Tape background.
static const uint16_t turbo_colours[] = {
    C64_COLOR_RED,
    C64_COLOR_CYAN,
    C64_COLOR_PURPLE,
    C64_COLOR_GREEN,
    C64_COLOR_BLUE,
    C64_COLOR_YELLOW,
    C64_COLOR_ORANGE_BROWN,
    C64_COLOR_ORANGE,
    C64_COLOR_SALMON,
    C64_COLOR_LIGHT_GREEN,
    C64_COLOR_LIGHT_PURPLE,
    C64_COLOR_LIGHT_GREY,
};

static bool is_game_screen(screen_id_t screen)
{
    return screen == SCREEN_CHECKERS || screen == SCREEN_OTHELLO ||
           screen == SCREEN_CONNECT_FOUR || screen == SCREEN_BATTLESHIPS ||
           screen == SCREEN_BATTLE_ZONE || screen == SCREEN_BOULDER_DASH ||
           screen == SCREEN_YAHTZEE || screen == SCREEN_BLACKJACK ||
           screen == SCREEN_POKER || screen == SCREEN_POKER_DICE ||
           screen == SCREEN_PIG || screen == SCREEN_ASTEROIDS ||
           screen == SCREEN_TEMPEST || screen == SCREEN_INVADERS ||
           screen == SCREEN_MISSILE_COMMAND || screen == SCREEN_SCRAMBLE ||
           screen == SCREEN_BREAKOUT || screen == SCREEN_CRAWLER ||
           screen == SCREEN_MAZE_CHASE || screen == SCREEN_SIMON ||
           screen == SCREEN_DEFENDER || screen == SCREEN_GALAGA ||
           screen == SCREEN_DUNGEON;
}

static const char *loader_screen_name(screen_id_t screen)
{
    switch (screen) {
        case SCREEN_CHECKERS: return "CHECKERS";
        case SCREEN_OTHELLO: return "OTHELLO";
        case SCREEN_CONNECT_FOUR: return "CONNECT 4";
        case SCREEN_BATTLESHIPS: return "BATTLESHIPS";
        case SCREEN_BATTLE_ZONE: return "BATTLE ZONE";
        case SCREEN_BOULDER_DASH: return "BOULDER DASH";
        case SCREEN_YAHTZEE: return "YAHTZEE";
        case SCREEN_BLACKJACK: return "BLACKJACK";
        case SCREEN_POKER: return "POKER";
        case SCREEN_POKER_DICE: return "POKER DICE";
        case SCREEN_PIG: return "PIG";
        case SCREEN_ASTEROIDS: return "ASTEROIDS";
        case SCREEN_TEMPEST: return "TEMPEST";
        case SCREEN_INVADERS: return "INVADERS";
        case SCREEN_MISSILE_COMMAND: return "MISSILE COMMAND";
        case SCREEN_SCRAMBLE: return "SCRAMBLE";
        case SCREEN_BREAKOUT: return "BREAKOUT";
        case SCREEN_CRAWLER: return "CRAWLER";
        case SCREEN_MAZE_CHASE: return "MAZE CHASE";
        case SCREEN_SIMON: return "SIMON";
        case SCREEN_DEFENDER: return "DEFENDER";
        case SCREEN_GALAGA: return "GALAGA";
        case SCREEN_DUNGEON: return "DUNGEON";
        default: return "GAME";
    }
}

void turboLoaderUpdate(screen_id_t requested_screen, uint32_t now_ms)
{
    if (!is_game_screen(requested_screen)) {
        loader_active = false;
        loader_screen = SCREEN_MENU;
        return;
    }

    if (requested_screen != loader_screen) {
        loader_screen = requested_screen;
        loader_started_ms = now_ms;
        loader_active = true;
    }

    if (loader_active && now_ms - loader_started_ms >= TURBO_LOADER_DURATION_MS) {
        loader_active = false;
    }
}

bool turboLoaderActive(void)
{
    return loader_active;
}

static uint32_t stripe_noise(uint32_t value)
{
    value ^= value << 13;
    value ^= value >> 17;
    value ^= value << 5;
    return value;
}

void drawTurboLoader(uint16_t *frame, uint32_t now_ms)
{
    // Full horizontal colour bands match the C64 Ocean/Turbo Tape display.
    clear(frame, C64_COLOR_BLACK);

    const uint32_t phase = now_ms / 80U;
    const uint16_t band_colour = turbo_colours[stripe_noise(phase) %
        (sizeof(turbo_colours) / sizeof(turbo_colours[0]))];
    for (int y = 0; y < LCD_HEIGHT; y += TURBO_LOADER_BAR_SPACING) {
        fill_rect(frame, 0, y, LCD_WIDTH, TURBO_LOADER_BAR_HEIGHT, band_colour);
    }

    const int window_x = (LCD_WIDTH - TURBO_LOADER_WINDOW_WIDTH) / 2;
    const int window_y = (LCD_HEIGHT - TURBO_LOADER_WINDOW_HEIGHT) / 2;
    char loading_text[32];
    snprintf(loading_text, sizeof(loading_text), "LOADING - %s", loader_screen_name(loader_screen));
    fill_rect(frame, window_x, window_y, TURBO_LOADER_WINDOW_WIDTH,
              TURBO_LOADER_WINDOW_HEIGHT, C64_COLOR_BLACK);
    drawPet2001TextCentredTransparent(frame, LCD_WIDTH / 2,
                                       window_y + (TURBO_LOADER_WINDOW_HEIGHT - PET2001_FONT_GLYPH_HEIGHT) / 2,
                                       loading_text,
                                       C64_COLOR_ORANGE, 1);
}