Demo Stage Walloons

Source: src/demo_stage_walloons.c · 27 lines · 9 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

steps() · source line 19
static unsigned steps(uint32_t now, unsigned maximum)
  1. Executeconst unsigned result = (now - phase_started_at) / STEP_MS;
  2. Exit this functionreturn result < maximum ? result : maximum;
Read original function source
static unsigned steps(uint32_t now, unsigned maximum) { const unsigned result = (now - phase_started_at) / STEP_MS; return result < maximum ? result : maximum; }
setPhase() · source line 20
static void setPhase(phase_t next, uint32_t now)
  1. Executephase = next;
  2. Executephase_started_at = now;
Read original function source
static void setPhase(phase_t next, uint32_t now) { phase = next; phase_started_at = now; }
demoStageWalloonsStart() · source line 21
void demoStageWalloonsStart(uint32_t now_ms)
  1. Executephase = TITLE;
  2. Executephase_started_at = now_ms;
  3. Executecompleted_bounces = 0U;
Read original function source
void demoStageWalloonsStart(uint32_t now_ms) { phase = TITLE; phase_started_at = now_ms; completed_bounces = 0U; }
demoStageWalloonsUpdate() · source line 22
void demoStageWalloonsUpdate(uint32_t now_ms)

Calls into this documentation:

  1. Executeconst uint32_t elapsed = now_ms - phase_started_at;
  2. Executeconst uint32_t vertical = 13U * STEP_MS;
  3. Select a casephase

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

      1. Case / labelcase TITLE:
      2. Decisionelapsed >= TITLE_MS
        True
        1. ExecutesetPhase(LEFT_WALK, now_ms);
        False

        Continue after this decision.

      3. Exit enclosing loop or switchbreak;
      4. Case / labelcase LEFT_WALK:
      5. Decisionelapsed >= 12U * STEP_MS
        True
        1. ExecutesetPhase(PAUSE, now_ms);
        False

        Continue after this decision.

      6. Exit enclosing loop or switchbreak;
      7. Case / labelcase PAUSE:
      8. Decisionelapsed >= PAUSE_MS
        True
        1. ExecutesetPhase(RIGHT_WALK, now_ms);
        False

        Continue after this decision.

      9. Exit enclosing loop or switchbreak;
      10. Case / labelcase RIGHT_WALK:
      11. Decisionelapsed >= 14U * STEP_MS
        True
        1. ExecutesetPhase(RIGHT_DROP, now_ms);
        False

        Continue after this decision.

      12. Exit enclosing loop or switchbreak;
      13. Case / labelcase RIGHT_DROP:
      14. Decisionelapsed >= vertical
        True
        1. ExecutesetPhase(RIGHT_UP, now_ms);
        False

        Continue after this decision.

      15. Exit enclosing loop or switchbreak;
      16. Case / labelcase RIGHT_UP:
      17. Decisionelapsed >= vertical
        True
        1. ExecutesetPhase(RIGHT_DOWN, now_ms);
        False

        Continue after this decision.

      18. Exit enclosing loop or switchbreak;
      19. Case / labelcase RIGHT_DOWN:
      20. Decisionelapsed >= vertical
        True
        1. ExecutesetPhase(LEFT_UP, now_ms);
        False

        Continue after this decision.

      21. Exit enclosing loop or switchbreak;
      22. Case / labelcase LEFT_UP:
      23. Decisionelapsed >= vertical
        True
        1. ExecutesetPhase(LEFT_DOWN, now_ms);
        False

        Continue after this decision.

      24. Exit enclosing loop or switchbreak;
      25. Case / labelcase LEFT_DOWN:
      26. Decisionelapsed >= vertical
        True
        1. ExecutesetPhase(LEFT_LANDED, now_ms);
        False

        Continue after this decision.

      27. Exit enclosing loop or switchbreak;
      28. Case / labelcase LEFT_LANDED:
      29. Decisionelapsed >= LANDING_MS
        True
          1. Decision++completed_bounces >= BOUNCE_COUNT
            True
            1. ExecutesetPhase(FINISHED, now_ms);
            False
            1. ExecutesetPhase(RIGHT_UP, now_ms);
        False

        Continue after this decision.

      30. Exit enclosing loop or switchbreak;
      31. Case / labelcase FINISHED:
      32. Exit enclosing loop or switchbreak;
Read original function source
void demoStageWalloonsUpdate(uint32_t now_ms) { const uint32_t elapsed = now_ms - phase_started_at; const uint32_t vertical = 13U * STEP_MS; switch (phase) { case TITLE: if (elapsed >= TITLE_MS) setPhase(LEFT_WALK, now_ms); break; case LEFT_WALK: if (elapsed >= 12U * STEP_MS) setPhase(PAUSE, now_ms); break; case PAUSE: if (elapsed >= PAUSE_MS) setPhase(RIGHT_WALK, now_ms); break; case RIGHT_WALK: if (elapsed >= 14U * STEP_MS) setPhase(RIGHT_DROP, now_ms); break; case RIGHT_DROP: if (elapsed >= vertical) setPhase(RIGHT_UP, now_ms); break; case RIGHT_UP: if (elapsed >= vertical) setPhase(RIGHT_DOWN, now_ms); break; case RIGHT_DOWN: if (elapsed >= vertical) setPhase(LEFT_UP, now_ms); break; case LEFT_UP: if (elapsed >= vertical) setPhase(LEFT_DOWN, now_ms); break; case LEFT_DOWN: if (elapsed >= vertical) setPhase(LEFT_LANDED, now_ms); break; case LEFT_LANDED: if (elapsed >= LANDING_MS) { if (++completed_bounces >= BOUNCE_COUNT) setPhase(FINISHED, now_ms); else setPhase(RIGHT_UP, now_ms); } break; case FINISHED: break; } }
glyph() · source line 23
static void glyph(uint16_t *frame, int c, int r, uint8_t ch)

Calls into this documentation:

  1. Executer += ROW_OFFSET;
  2. Decisionc < 0 || c >= 40 || r < 0 || r >= 21
    True
    1. Exit this functionreturn;
    False

    Continue after this decision.

  3. ExecutedrawPet2001Glyph(frame, c * PET2001_FONT_GLYPH_WIDTH, r * PET2001_FONT_GLYPH_HEIGHT, ch, false, PET_COLOUR, COLOR_BLACK, 1);
Read original function source
static void glyph(uint16_t *frame, int c, int r, uint8_t ch) { r += ROW_OFFSET; if (c < 0 || c >= 40 || r < 0 || r >= 21) return; drawPet2001Glyph(frame, c * PET2001_FONT_GLYPH_WIDTH, r * PET2001_FONT_GLYPH_HEIGHT, ch, false, PET_COLOUR, COLOR_BLACK, 1); }
walloon() · source line 24
static void walloon(uint16_t *f, int c, int r, bool walking)

Calls into this documentation:

  1. Executeglyph(f,c,r,walking?81U:87U);
  2. Executeglyph(f,c-1,r+1,64U);
  3. Executeglyph(f,c,r+1,71U);
  4. Executeglyph(f,c+1,r+1,64U);
  5. Executeglyph(f,c,r+2,90U);
  6. Executeglyph(f,c-1,r+3,78U);
  7. Executeglyph(f,c+1,r+3,77U);
Read original function source
static void walloon(uint16_t *f, int c, int r, bool walking) { glyph(f,c,r,walking?81U:87U); glyph(f,c-1,r+1,64U); glyph(f,c,r+1,71U); glyph(f,c+1,r+1,64U); glyph(f,c,r+2,90U); glyph(f,c-1,r+3,78U); glyph(f,c+1,r+3,77U); }
playfield() · source line 25
static void playfield(uint16_t *f)

Calls into this documentation:

  1. FOR loopint c=10;c<=28;++c

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

    1. Executeglyph(f,c,5,127U);
  2. FOR loopint r=5;r<=15;++r

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

    1. Executeglyph(f,28,r,127U);
Read original function source
static void playfield(uint16_t *f) { for (int c=10;c<=28;++c) glyph(f,c,5,127U); for (int r=5;r<=15;++r) glyph(f,28,r,127U); }
seesaw() · source line 26
static void seesaw(uint16_t *f, bool left_down)

Calls into this documentation:

  1. Executestatic const int left[][2]={{13,19},{14,19},{15,19},{16,18},{17,18},{18,18},{19,17},{20,17},{21,17},{22,16},{23,16},{24,16}};
  2. Executestatic const int right[][2]={{13,16},{14,16},{15,16},{16,17},{17,17},{18,17},{19,18},{20,18},{21,18},{22,19},{23,19},{24,19}};
  3. Executeconst int (*board)[2]=left_down?left:right;
  4. FOR loopsize_t i=0;i<12U;++i

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

    1. Executeglyph(f,board[i][0],board[i][1],SEESAW_LINE);
  5. Executeglyph(f,18,20,233U);
  6. Executeglyph(f,19,20,223U);
Read original function source
static void seesaw(uint16_t *f, bool left_down) { static const int left[][2]={{13,19},{14,19},{15,19},{16,18},{17,18},{18,18},{19,17},{20,17},{21,17},{22,16},{23,16},{24,16}}; static const int right[][2]={{13,16},{14,16},{15,16},{16,17},{17,17},{18,17},{19,18},{20,18},{21,18},{22,19},{23,19},{24,19}}; const int (*board)[2]=left_down?left:right; for (size_t i=0;i<12U;++i) glyph(f,board[i][0],board[i][1],SEESAW_LINE); glyph(f,18,20,233U); glyph(f,19,20,223U); }
demoStageWalloonsDraw() · source line 27
void demoStageWalloonsDraw(uint16_t *f, uint32_t now)

Calls into this documentation:

  1. Decisionphase == TITLE
    True
      1. Executeplayfield(f);
      2. FOR loopint r=5;r<=15;++r

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

        1. Executeglyph(f,10,r,127U);
      3. FOR loopint c=10;c<=25;++c

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

        1. Executeglyph(f,c,15,127U);
      4. ExecutedrawPet2001Text(f,18*PET2001_FONT_GLYPH_WIDTH,7*PET2001_FONT_GLYPH_HEIGHT,"THE",false,PET_COLOUR,COLOR_BLACK,1);
      5. ExecutedrawPet2001Text(f,12*PET2001_FONT_GLYPH_WIDTH,9*PET2001_FONT_GLYPH_HEIGHT,"FLYING WALLOONS",false,PET_COLOUR,COLOR_BLACK,1);
      6. Exit this functionreturn;
    False

    Continue after this decision.

  2. Executeplayfield(f);
  3. Executeconst unsigned s=steps(now,14U);
  4. Executeconst bool walk=(s&1U)!=0U;
  5. Select a casephase

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

      1. Case / labelcase LEFT_WALK:
      2. Executeseesaw(f,true);
      3. Executewalloon(f,2+(int)steps(now,12U),15,walk);
      4. Exit enclosing loop or switchbreak;
      5. Case / labelcase PAUSE:
      6. Executeseesaw(f,true);
      7. Executewalloon(f,14,15,false);
      8. Exit enclosing loop or switchbreak;
      9. Case / labelcase RIGHT_WALK:
      10. Executeseesaw(f,true);
      11. Executewalloon(f,14,15,false);
      12. Executewalloon(f,38-(int)s,2,walk);
      13. Exit enclosing loop or switchbreak;
      14. Case / labelcase RIGHT_DROP:
      15. Executeseesaw(f,true);
      16. Executewalloon(f,14,15,false);
      17. Executewalloon(f,24,2+(int)steps(now,13U),false);
      18. Exit enclosing loop or switchbreak;
      19. Case / labelcase RIGHT_UP:
      20. Case / labelcase RIGHT_DOWN:
      21. Executeseesaw(f,true);
      22. Executewalloon(f,15,15,false);
      23. Executewalloon(f,24,phase==RIGHT_UP?14-(int)steps(now,13U):2+(int)steps(now,13U),false);
      24. Exit enclosing loop or switchbreak;
      25. Case / labelcase LEFT_UP:
      26. Executeseesaw(f,false);
      27. Executewalloon(f,24,14,false);
      28. Executewalloon(f,15,14-(int)steps(now,13U),false);
      29. Exit enclosing loop or switchbreak;
      30. Case / labelcase LEFT_DOWN:
      31. Executeseesaw(f,false);
      32. Executewalloon(f,24,14,false);
      33. Executewalloon(f,15,2+(int)steps(now,13U),false);
      34. Exit enclosing loop or switchbreak;
      35. Case / labelcase LEFT_LANDED:
      36. Executeseesaw(f,true);
      37. Executewalloon(f,15,15,false);
      38. Exit enclosing loop or switchbreak;
      39. Case / labelcase FINISHED:
      40. Executeseesaw(f,true);
      41. Executewalloon(f,15,15,false);
      42. Executewalloon(f,24,14,false);
      43. Exit enclosing loop or switchbreak;
      44. Case / labeldefault:
      45. Exit enclosing loop or switchbreak;
Read original function source
void demoStageWalloonsDraw(uint16_t *f, uint32_t now) { if (phase == TITLE) { playfield(f); for(int r=5;r<=15;++r) glyph(f,10,r,127U); for(int c=10;c<=25;++c) glyph(f,c,15,127U); drawPet2001Text(f,18*PET2001_FONT_GLYPH_WIDTH,7*PET2001_FONT_GLYPH_HEIGHT,"THE",false,PET_COLOUR,COLOR_BLACK,1); drawPet2001Text(f,12*PET2001_FONT_GLYPH_WIDTH,9*PET2001_FONT_GLYPH_HEIGHT,"FLYING WALLOONS",false,PET_COLOUR,COLOR_BLACK,1); return; } playfield(f); const unsigned s=steps(now,14U); const bool walk=(s&1U)!=0U; switch(phase) { case LEFT_WALK: seesaw(f,true); walloon(f,2+(int)steps(now,12U),15,walk); break; case PAUSE: seesaw(f,true); walloon(f,14,15,false); break; case RIGHT_WALK: seesaw(f,true); walloon(f,14,15,false); walloon(f,38-(int)s,2,walk); break; case RIGHT_DROP: seesaw(f,true); walloon(f,14,15,false); walloon(f,24,2+(int)steps(now,13U),false); break; case RIGHT_UP: case RIGHT_DOWN: seesaw(f,true); walloon(f,15,15,false); walloon(f,24,phase==RIGHT_UP?14-(int)steps(now,13U):2+(int)steps(now,13U),false); break; case LEFT_UP: seesaw(f,false); walloon(f,24,14,false); walloon(f,15,14-(int)steps(now,13U),false); break; case LEFT_DOWN: seesaw(f,false); walloon(f,24,14,false); walloon(f,15,2+(int)steps(now,13U),false); break; case LEFT_LANDED: seesaw(f,true); walloon(f,15,15,false); break; case FINISHED: seesaw(f,true); walloon(f,15,15,false); walloon(f,24,14,false); break; default: break; } }
Complete original file, including constants and data
/* Coded By JD(2026) */
#error "Reference listing only — not provided as build-ready source."
#include "demo_stage_walloons.h"
#include "PET2001_font.h"
#include "c64_colors.h"
#include "game_graphics.h"
#include <stdbool.h>
#include <stddef.h>

// Segment 7 owns the original PET Walloons stunt, including all phase timing.
#define STEP_MS 120U
#define TITLE_MS 2000U
#define PAUSE_MS 650U
#define LANDING_MS 360U
#define BOUNCE_COUNT 3U
#define PET_COLOUR C64_COLOR_LIGHT_GREEN
#define ROW_OFFSET -2
#define SEESAW_LINE 64U
typedef enum { TITLE, LEFT_WALK, PAUSE, RIGHT_WALK, RIGHT_DROP, RIGHT_UP, RIGHT_DOWN, LEFT_UP, LEFT_DOWN, LEFT_LANDED, FINISHED } phase_t;
static phase_t phase; static uint32_t phase_started_at; static uint8_t completed_bounces;
static unsigned steps(uint32_t now, unsigned maximum) { const unsigned result = (now - phase_started_at) / STEP_MS; return result < maximum ? result : maximum; }
static void setPhase(phase_t next, uint32_t now) { phase = next; phase_started_at = now; }
void demoStageWalloonsStart(uint32_t now_ms) { phase = TITLE; phase_started_at = now_ms; completed_bounces = 0U; }
void demoStageWalloonsUpdate(uint32_t now_ms) { const uint32_t elapsed = now_ms - phase_started_at; const uint32_t vertical = 13U * STEP_MS; switch (phase) { case TITLE: if (elapsed >= TITLE_MS) setPhase(LEFT_WALK, now_ms); break; case LEFT_WALK: if (elapsed >= 12U * STEP_MS) setPhase(PAUSE, now_ms); break; case PAUSE: if (elapsed >= PAUSE_MS) setPhase(RIGHT_WALK, now_ms); break; case RIGHT_WALK: if (elapsed >= 14U * STEP_MS) setPhase(RIGHT_DROP, now_ms); break; case RIGHT_DROP: if (elapsed >= vertical) setPhase(RIGHT_UP, now_ms); break; case RIGHT_UP: if (elapsed >= vertical) setPhase(RIGHT_DOWN, now_ms); break; case RIGHT_DOWN: if (elapsed >= vertical) setPhase(LEFT_UP, now_ms); break; case LEFT_UP: if (elapsed >= vertical) setPhase(LEFT_DOWN, now_ms); break; case LEFT_DOWN: if (elapsed >= vertical) setPhase(LEFT_LANDED, now_ms); break; case LEFT_LANDED: if (elapsed >= LANDING_MS) { if (++completed_bounces >= BOUNCE_COUNT) setPhase(FINISHED, now_ms); else setPhase(RIGHT_UP, now_ms); } break; case FINISHED: break; } }
static void glyph(uint16_t *frame, int c, int r, uint8_t ch) { r += ROW_OFFSET; if (c < 0 || c >= 40 || r < 0 || r >= 21) return; drawPet2001Glyph(frame, c * PET2001_FONT_GLYPH_WIDTH, r * PET2001_FONT_GLYPH_HEIGHT, ch, false, PET_COLOUR, COLOR_BLACK, 1); }
static void walloon(uint16_t *f, int c, int r, bool walking) { glyph(f,c,r,walking?81U:87U); glyph(f,c-1,r+1,64U); glyph(f,c,r+1,71U); glyph(f,c+1,r+1,64U); glyph(f,c,r+2,90U); glyph(f,c-1,r+3,78U); glyph(f,c+1,r+3,77U); }
static void playfield(uint16_t *f) { for (int c=10;c<=28;++c) glyph(f,c,5,127U); for (int r=5;r<=15;++r) glyph(f,28,r,127U); }
static void seesaw(uint16_t *f, bool left_down) { static const int left[][2]={{13,19},{14,19},{15,19},{16,18},{17,18},{18,18},{19,17},{20,17},{21,17},{22,16},{23,16},{24,16}}; static const int right[][2]={{13,16},{14,16},{15,16},{16,17},{17,17},{18,17},{19,18},{20,18},{21,18},{22,19},{23,19},{24,19}}; const int (*board)[2]=left_down?left:right; for (size_t i=0;i<12U;++i) glyph(f,board[i][0],board[i][1],SEESAW_LINE); glyph(f,18,20,233U); glyph(f,19,20,223U); }
void demoStageWalloonsDraw(uint16_t *f, uint32_t now) { if (phase == TITLE) { playfield(f); for(int r=5;r<=15;++r) glyph(f,10,r,127U); for(int c=10;c<=25;++c) glyph(f,c,15,127U); drawPet2001Text(f,18*PET2001_FONT_GLYPH_WIDTH,7*PET2001_FONT_GLYPH_HEIGHT,"THE",false,PET_COLOUR,COLOR_BLACK,1); drawPet2001Text(f,12*PET2001_FONT_GLYPH_WIDTH,9*PET2001_FONT_GLYPH_HEIGHT,"FLYING WALLOONS",false,PET_COLOUR,COLOR_BLACK,1); return; } playfield(f); const unsigned s=steps(now,14U); const bool walk=(s&1U)!=0U; switch(phase) { case LEFT_WALK: seesaw(f,true); walloon(f,2+(int)steps(now,12U),15,walk); break; case PAUSE: seesaw(f,true); walloon(f,14,15,false); break; case RIGHT_WALK: seesaw(f,true); walloon(f,14,15,false); walloon(f,38-(int)s,2,walk); break; case RIGHT_DROP: seesaw(f,true); walloon(f,14,15,false); walloon(f,24,2+(int)steps(now,13U),false); break; case RIGHT_UP: case RIGHT_DOWN: seesaw(f,true); walloon(f,15,15,false); walloon(f,24,phase==RIGHT_UP?14-(int)steps(now,13U):2+(int)steps(now,13U),false); break; case LEFT_UP: seesaw(f,false); walloon(f,24,14,false); walloon(f,15,14-(int)steps(now,13U),false); break; case LEFT_DOWN: seesaw(f,false); walloon(f,24,14,false); walloon(f,15,2+(int)steps(now,13U),false); break; case LEFT_LANDED: seesaw(f,true); walloon(f,15,15,false); break; case FINISHED: seesaw(f,true); walloon(f,15,15,false); walloon(f,24,14,false); break; default: break; } }