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)
- Execute
const unsigned result = (now - phase_started_at) / STEP_MS; - Exit this function
return 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)
- Execute
phase = next; - Execute
phase_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)
- Execute
phase = TITLE; - Execute
phase_started_at = now_ms; - Execute
completed_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:
- Execute
const uint32_t elapsed = now_ms - phase_started_at; - Execute
const uint32_t vertical = 13U * STEP_MS; - Select a case
phaseEnter matching case; follow source fall-through until a break, return or end.
- Case / label
case TITLE: - Decision
elapsed >= TITLE_MSTrue- Execute
setPhase(LEFT_WALK, now_ms);
FalseContinue after this decision.
- Exit enclosing loop or switch
break; - Case / label
case LEFT_WALK: - Decision
elapsed >= 12U * STEP_MSTrue- Execute
setPhase(PAUSE, now_ms);
FalseContinue after this decision.
- Exit enclosing loop or switch
break; - Case / label
case PAUSE: - Decision
elapsed >= PAUSE_MSTrue- Execute
setPhase(RIGHT_WALK, now_ms);
FalseContinue after this decision.
- Exit enclosing loop or switch
break; - Case / label
case RIGHT_WALK: - Decision
elapsed >= 14U * STEP_MSTrue- Execute
setPhase(RIGHT_DROP, now_ms);
FalseContinue after this decision.
- Exit enclosing loop or switch
break; - Case / label
case RIGHT_DROP: - Decision
elapsed >= verticalTrue- Execute
setPhase(RIGHT_UP, now_ms);
FalseContinue after this decision.
- Exit enclosing loop or switch
break; - Case / label
case RIGHT_UP: - Decision
elapsed >= verticalTrue- Execute
setPhase(RIGHT_DOWN, now_ms);
FalseContinue after this decision.
- Exit enclosing loop or switch
break; - Case / label
case RIGHT_DOWN: - Decision
elapsed >= verticalTrue- Execute
setPhase(LEFT_UP, now_ms);
FalseContinue after this decision.
- Exit enclosing loop or switch
break; - Case / label
case LEFT_UP: - Decision
elapsed >= verticalTrue- Execute
setPhase(LEFT_DOWN, now_ms);
FalseContinue after this decision.
- Exit enclosing loop or switch
break; - Case / label
case LEFT_DOWN: - Decision
elapsed >= verticalTrue- Execute
setPhase(LEFT_LANDED, now_ms);
FalseContinue after this decision.
- Exit enclosing loop or switch
break; - Case / label
case LEFT_LANDED: - Decision
elapsed >= LANDING_MSTrue- Decision
++completed_bounces >= BOUNCE_COUNTTrue- Execute
setPhase(FINISHED, now_ms);
False- Execute
setPhase(RIGHT_UP, now_ms);
FalseContinue after this decision.
- Exit enclosing loop or switch
break; - Case / label
case FINISHED: - Exit enclosing loop or switch
break;
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:
- Execute
r += ROW_OFFSET; - Decision
c < 0 || c >= 40 || r < 0 || r >= 21True- Exit this function
return;
FalseContinue after this decision.
- Execute
drawPet2001Glyph(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:
- Execute
glyph(f,c,r,walking?81U:87U); - Execute
glyph(f,c-1,r+1,64U); - Execute
glyph(f,c,r+1,71U); - Execute
glyph(f,c+1,r+1,64U); - Execute
glyph(f,c,r+2,90U); - Execute
glyph(f,c-1,r+3,78U); - Execute
glyph(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:
- FOR loop
int c=10;c<=28;++cRepeat body while the loop condition permits; then continue below.
- Execute
glyph(f,c,5,127U);
- FOR loop
int r=5;r<=15;++rRepeat body while the loop condition permits; then continue below.
- Execute
glyph(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:
- Execute
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}}; - Execute
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}}; - Execute
const int (*board)[2]=left_down?left:right; - FOR loop
size_t i=0;i<12U;++iRepeat body while the loop condition permits; then continue below.
- Execute
glyph(f,board[i][0],board[i][1],SEESAW_LINE);
- Execute
glyph(f,18,20,233U); - Execute
glyph(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:
- Decision
phase == TITLETrue- Execute
playfield(f); - FOR loop
int r=5;r<=15;++rRepeat body while the loop condition permits; then continue below.
- Execute
glyph(f,10,r,127U);
- FOR loop
int c=10;c<=25;++cRepeat body while the loop condition permits; then continue below.
- Execute
glyph(f,c,15,127U);
- Execute
drawPet2001Text(f,18*PET2001_FONT_GLYPH_WIDTH,7*PET2001_FONT_GLYPH_HEIGHT,"THE",false,PET_COLOUR,COLOR_BLACK,1); - Execute
drawPet2001Text(f,12*PET2001_FONT_GLYPH_WIDTH,9*PET2001_FONT_GLYPH_HEIGHT,"FLYING WALLOONS",false,PET_COLOUR,COLOR_BLACK,1); - Exit this function
return;
FalseContinue after this decision.
- Execute
playfield(f); - Execute
const unsigned s=steps(now,14U); - Execute
const bool walk=(s&1U)!=0U; - Select a case
phaseEnter matching case; follow source fall-through until a break, return or end.
- Case / label
case LEFT_WALK: - Execute
seesaw(f,true); - Execute
walloon(f,2+(int)steps(now,12U),15,walk); - Exit enclosing loop or switch
break; - Case / label
case PAUSE: - Execute
seesaw(f,true); - Execute
walloon(f,14,15,false); - Exit enclosing loop or switch
break; - Case / label
case RIGHT_WALK: - Execute
seesaw(f,true); - Execute
walloon(f,14,15,false); - Execute
walloon(f,38-(int)s,2,walk); - Exit enclosing loop or switch
break; - Case / label
case RIGHT_DROP: - Execute
seesaw(f,true); - Execute
walloon(f,14,15,false); - Execute
walloon(f,24,2+(int)steps(now,13U),false); - Exit enclosing loop or switch
break; - Case / label
case RIGHT_UP: - Case / label
case RIGHT_DOWN: - Execute
seesaw(f,true); - Execute
walloon(f,15,15,false); - Execute
walloon(f,24,phase==RIGHT_UP?14-(int)steps(now,13U):2+(int)steps(now,13U),false); - Exit enclosing loop or switch
break; - Case / label
case LEFT_UP: - Execute
seesaw(f,false); - Execute
walloon(f,24,14,false); - Execute
walloon(f,15,14-(int)steps(now,13U),false); - Exit enclosing loop or switch
break; - Case / label
case LEFT_DOWN: - Execute
seesaw(f,false); - Execute
walloon(f,24,14,false); - Execute
walloon(f,15,2+(int)steps(now,13U),false); - Exit enclosing loop or switch
break; - Case / label
case LEFT_LANDED: - Execute
seesaw(f,true); - Execute
walloon(f,15,15,false); - Exit enclosing loop or switch
break; - Case / label
case FINISHED: - Execute
seesaw(f,true); - Execute
walloon(f,15,15,false); - Execute
walloon(f,24,14,false); - Exit enclosing loop or switch
break; - Case / label
default: - Exit enclosing loop or switch
break;
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; } }