Flame Effect
Source: src/flame_effect.c · 121 lines · 7 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
flameColor() · source line 11
static uint16_t flameColor(uint8_t value, const flame_palette_t *palette)
- Decision
value < 40UTrue- Exit this function
return COLOR_BLACK;
FalseContinue after this decision.
- Decision
value < 90UTrue- Exit this function
return palette->cool;
FalseContinue after this decision.
- Decision
value < 140UTrue- Exit this function
return palette->warm;
FalseContinue after this decision.
- Decision
value < 190UTrue- Exit this function
return palette->hot;
FalseContinue after this decision.
- Decision
value < 230UTrue- Exit this function
return palette->hottest;
FalseContinue after this decision.
- Exit this function
return palette->peak;
Read original function source
static uint16_t flameColor(uint8_t value, const flame_palette_t *palette)
{
if (value < 40U) return COLOR_BLACK;
if (value < 90U) return palette->cool;
if (value < 140U) return palette->warm;
if (value < 190U) return palette->hot;
if (value < 230U) return palette->hottest;
return palette->peak;
}nextFlameRandom() · source line 21
static uint32_t nextFlameRandom(flame_effect_t *effect)
- Execute
effect->random_state ^= effect->random_state << 13; - Execute
effect->random_state ^= effect->random_state >> 17; - Execute
effect->random_state ^= effect->random_state << 5; - Exit this function
return effect->random_state;
Read original function source
static uint32_t nextFlameRandom(flame_effect_t *effect)
{
effect->random_state ^= effect->random_state << 13;
effect->random_state ^= effect->random_state >> 17;
effect->random_state ^= effect->random_state << 5;
return effect->random_state;
}flameEffectInitialize() · source line 29
void flameEffectInitialize(flame_effect_t *effect, uint8_t *heat, unsigned columns,
unsigned rows, unsigned pixel_width, unsigned pixel_height,
bool rises, uint32_t seed)- Execute
effect->heat = heat; - Execute
effect->columns = columns; - Execute
effect->rows = rows; - Execute
effect->pixel_width = pixel_width; - Execute
effect->pixel_height = pixel_height; - Execute
effect->rises = rises; - Execute
effect->random_state = seed == 0U ? 0x6D2B79F5U : seed; - Execute
memset(heat, 0, (size_t)columns * rows);
Read original function source
void flameEffectInitialize(flame_effect_t *effect, uint8_t *heat, unsigned columns,
unsigned rows, unsigned pixel_width, unsigned pixel_height,
bool rises, uint32_t seed)
{
effect->heat = heat;
effect->columns = columns;
effect->rows = rows;
effect->pixel_width = pixel_width;
effect->pixel_height = pixel_height;
effect->rises = rises;
effect->random_state = seed == 0U ? 0x6D2B79F5U : seed;
memset(heat, 0, (size_t)columns * rows);
}flameEffectSpread() · source line 43
static void flameEffectSpread(flame_effect_t *effect)
Calls into this documentation:
- Decision
effect->risesTrue- FOR loop
unsigned y = 0; y < effect->rows - 1U; ++yRepeat body while the loop condition permits; then continue below.
- Execute
const unsigned row = y * effect->columns; - Execute
const unsigned source = row + effect->columns; - FOR loop
unsigned x = 0; x < effect->columns; ++xRepeat body while the loop condition permits; then continue below.
- Execute
int source_x = (int)x + (int)(nextFlameRandom(effect) % 3U) - 1; - Decision
source_x < 0True- Execute
source_x = 0;
FalseContinue after this decision.
- Decision
source_x >= (int)effect->columnsTrue- Execute
source_x = (int)effect->columns - 1;
FalseContinue after this decision.
- Execute
const int cooled = effect->heat[source + (unsigned)source_x] - (int)(3U + nextFlameRandom(effect) % 7U); - Execute
effect->heat[row + x] = cooled > 0 ? (uint8_t)cooled : 0U;
False- FOR loop
unsigned y = effect->rows - 1U; y > 0U; --yRepeat body while the loop condition permits; then continue below.
- Execute
const unsigned row = y * effect->columns; - Execute
const unsigned source = row - effect->columns; - FOR loop
unsigned x = 0; x < effect->columns; ++xRepeat body while the loop condition permits; then continue below.
- Execute
int source_x = (int)x + (int)(nextFlameRandom(effect) % 3U) - 1; - Decision
source_x < 0True- Execute
source_x = 0;
FalseContinue after this decision.
- Decision
source_x >= (int)effect->columnsTrue- Execute
source_x = (int)effect->columns - 1;
FalseContinue after this decision.
- Execute
const int cooled = effect->heat[source + (unsigned)source_x] - (int)(3U + nextFlameRandom(effect) % 7U); - Execute
effect->heat[row + x] = cooled > 0 ? (uint8_t)cooled : 0U;
Read original function source
static void flameEffectSpread(flame_effect_t *effect)
{
if (effect->rises) {
for (unsigned y = 0; y < effect->rows - 1U; ++y) {
const unsigned row = y * effect->columns;
const unsigned source = row + effect->columns;
for (unsigned x = 0; x < effect->columns; ++x) {
int source_x = (int)x + (int)(nextFlameRandom(effect) % 3U) - 1;
if (source_x < 0) source_x = 0;
if (source_x >= (int)effect->columns) source_x = (int)effect->columns - 1;
const int cooled = effect->heat[source + (unsigned)source_x] -
(int)(3U + nextFlameRandom(effect) % 7U);
effect->heat[row + x] = cooled > 0 ? (uint8_t)cooled : 0U;
}
}
} else {
for (unsigned y = effect->rows - 1U; y > 0U; --y) {
const unsigned row = y * effect->columns;
const unsigned source = row - effect->columns;
for (unsigned x = 0; x < effect->columns; ++x) {
int source_x = (int)x + (int)(nextFlameRandom(effect) % 3U) - 1;
if (source_x < 0) source_x = 0;
if (source_x >= (int)effect->columns) source_x = (int)effect->columns - 1;
const int cooled = effect->heat[source + (unsigned)source_x] -
(int)(3U + nextFlameRandom(effect) % 7U);
effect->heat[row + x] = cooled > 0 ? (uint8_t)cooled : 0U;
}
}
}
}flameEffectUpdate() · source line 74
void flameEffectUpdate(flame_effect_t *effect)
Calls into this documentation:
- Execute
const unsigned source_y = effect->rises ? effect->rows - 1U : 0U; - Execute
const unsigned source_row = source_y * effect->columns; - FOR loop
unsigned x = 0; x < effect->columns; ++xRepeat body while the loop condition permits; then continue below.
- Execute
effect->heat[source_row + x] = 170U + nextFlameRandom(effect) % 86U;
- Execute
flameEffectSpread(effect);
Read original function source
void flameEffectUpdate(flame_effect_t *effect)
{
const unsigned source_y = effect->rises ? effect->rows - 1U : 0U;
const unsigned source_row = source_y * effect->columns;
for (unsigned x = 0; x < effect->columns; ++x)
effect->heat[source_row + x] = 170U + nextFlameRandom(effect) % 86U;
flameEffectSpread(effect);
}flameEffectUpdateFromSource() · source line 83
void flameEffectUpdateFromSource(flame_effect_t *effect, const uint8_t *source_heat)
Calls into this documentation:
- Execute
const unsigned source_y = effect->rises ? effect->rows - 1U : 0U; - Execute
memcpy(effect->heat + source_y * effect->columns, source_heat, effect->columns); - Execute
flameEffectSpread(effect);
Read original function source
void flameEffectUpdateFromSource(flame_effect_t *effect, const uint8_t *source_heat)
{
const unsigned source_y = effect->rises ? effect->rows - 1U : 0U;
memcpy(effect->heat + source_y * effect->columns, source_heat, effect->columns);
flameEffectSpread(effect);
}flameEffectDraw() · source line 90
void flameEffectDraw(uint16_t *frame, const flame_effect_t *effect, int x, int y,
const flame_palette_t *palette)Calls into this documentation:
- Decision
frame == NULL || effect == NULL || effect->heat == NULLTrue- Exit this function
return;
FalseContinue after this decision.
- Decision
palette == NULLTrue- Execute
palette = &default_palette;
FalseContinue after this decision.
- FOR loop
unsigned row = 0; row < effect->rows; ++rowRepeat body while the loop condition permits; then continue below.
- Execute
const int pixel_y = y + (int)(row * effect->pixel_height); - FOR loop
unsigned column = 0; column < effect->columns; ++columnRepeat body while the loop condition permits; then continue below.
- Execute
const int pixel_x = x + (int)(column * effect->pixel_width); - Execute
const uint16_t color = flameColor(effect->heat[row * effect->columns + column], palette); - FOR loop
unsigned pixel_row = 0; pixel_row < effect->pixel_height; ++pixel_rowRepeat body while the loop condition permits; then continue below.
- Execute
const int destination_y = pixel_y + (int)pixel_row; - Decision
destination_y < 0 || destination_y >= LCD_HEIGHTTrue- Next loop iteration
continue;
FalseContinue after this decision.
- FOR loop
unsigned pixel_column = 0; pixel_column < effect->pixel_width; ++pixel_columnRepeat body while the loop condition permits; then continue below.
- Execute
const int destination_x = pixel_x + (int)pixel_column; - Decision
destination_x >= 0 && destination_x < LCD_WIDTHTrue- Execute
frame[(size_t)destination_y * LCD_WIDTH + destination_x] = color;
FalseContinue after this decision.
Read original function source
void flameEffectDraw(uint16_t *frame, const flame_effect_t *effect, int x, int y,
const flame_palette_t *palette)
{
if (frame == NULL || effect == NULL || effect->heat == NULL) {
return;
}
if (palette == NULL) palette = &default_palette;
for (unsigned row = 0; row < effect->rows; ++row) {
const int pixel_y = y + (int)(row * effect->pixel_height);
for (unsigned column = 0; column < effect->columns; ++column) {
const int pixel_x = x + (int)(column * effect->pixel_width);
const uint16_t color = flameColor(effect->heat[row * effect->columns + column],
palette);
for (unsigned pixel_row = 0; pixel_row < effect->pixel_height; ++pixel_row) {
const int destination_y = pixel_y + (int)pixel_row;
if (destination_y < 0 || destination_y >= LCD_HEIGHT) {
continue;
}
for (unsigned pixel_column = 0; pixel_column < effect->pixel_width; ++pixel_column) {
const int destination_x = pixel_x + (int)pixel_column;
// Build the framebuffer address only after both coordinates
// are valid. This guards About and Hall of Fame against a
// damaged or changed flame field corrupting LCD state.
if (destination_x >= 0 && destination_x < LCD_WIDTH) {
frame[(size_t)destination_y * LCD_WIDTH + destination_x] = color;
}
}
}
}
}
}Complete original file, including constants and data
/* Coded By JD(2026) */
#error "Reference listing only — not provided as build-ready source."
#include "flame_effect.h"
#include "game_graphics.h"
#include <stddef.h>
#include <string.h>
static const flame_palette_t default_palette = {
COLOR_DARKRED, COLOR_RED, COLOR_ORANGE, COLOR_YELLOW, COLOR_WHITE,
};
static uint16_t flameColor(uint8_t value, const flame_palette_t *palette)
{
if (value < 40U) return COLOR_BLACK;
if (value < 90U) return palette->cool;
if (value < 140U) return palette->warm;
if (value < 190U) return palette->hot;
if (value < 230U) return palette->hottest;
return palette->peak;
}
static uint32_t nextFlameRandom(flame_effect_t *effect)
{
effect->random_state ^= effect->random_state << 13;
effect->random_state ^= effect->random_state >> 17;
effect->random_state ^= effect->random_state << 5;
return effect->random_state;
}
void flameEffectInitialize(flame_effect_t *effect, uint8_t *heat, unsigned columns,
unsigned rows, unsigned pixel_width, unsigned pixel_height,
bool rises, uint32_t seed)
{
effect->heat = heat;
effect->columns = columns;
effect->rows = rows;
effect->pixel_width = pixel_width;
effect->pixel_height = pixel_height;
effect->rises = rises;
effect->random_state = seed == 0U ? 0x6D2B79F5U : seed;
memset(heat, 0, (size_t)columns * rows);
}
static void flameEffectSpread(flame_effect_t *effect)
{
if (effect->rises) {
for (unsigned y = 0; y < effect->rows - 1U; ++y) {
const unsigned row = y * effect->columns;
const unsigned source = row + effect->columns;
for (unsigned x = 0; x < effect->columns; ++x) {
int source_x = (int)x + (int)(nextFlameRandom(effect) % 3U) - 1;
if (source_x < 0) source_x = 0;
if (source_x >= (int)effect->columns) source_x = (int)effect->columns - 1;
const int cooled = effect->heat[source + (unsigned)source_x] -
(int)(3U + nextFlameRandom(effect) % 7U);
effect->heat[row + x] = cooled > 0 ? (uint8_t)cooled : 0U;
}
}
} else {
for (unsigned y = effect->rows - 1U; y > 0U; --y) {
const unsigned row = y * effect->columns;
const unsigned source = row - effect->columns;
for (unsigned x = 0; x < effect->columns; ++x) {
int source_x = (int)x + (int)(nextFlameRandom(effect) % 3U) - 1;
if (source_x < 0) source_x = 0;
if (source_x >= (int)effect->columns) source_x = (int)effect->columns - 1;
const int cooled = effect->heat[source + (unsigned)source_x] -
(int)(3U + nextFlameRandom(effect) % 7U);
effect->heat[row + x] = cooled > 0 ? (uint8_t)cooled : 0U;
}
}
}
}
void flameEffectUpdate(flame_effect_t *effect)
{
const unsigned source_y = effect->rises ? effect->rows - 1U : 0U;
const unsigned source_row = source_y * effect->columns;
for (unsigned x = 0; x < effect->columns; ++x)
effect->heat[source_row + x] = 170U + nextFlameRandom(effect) % 86U;
flameEffectSpread(effect);
}
void flameEffectUpdateFromSource(flame_effect_t *effect, const uint8_t *source_heat)
{
const unsigned source_y = effect->rises ? effect->rows - 1U : 0U;
memcpy(effect->heat + source_y * effect->columns, source_heat, effect->columns);
flameEffectSpread(effect);
}
void flameEffectDraw(uint16_t *frame, const flame_effect_t *effect, int x, int y,
const flame_palette_t *palette)
{
if (frame == NULL || effect == NULL || effect->heat == NULL) {
return;
}
if (palette == NULL) palette = &default_palette;
for (unsigned row = 0; row < effect->rows; ++row) {
const int pixel_y = y + (int)(row * effect->pixel_height);
for (unsigned column = 0; column < effect->columns; ++column) {
const int pixel_x = x + (int)(column * effect->pixel_width);
const uint16_t color = flameColor(effect->heat[row * effect->columns + column],
palette);
for (unsigned pixel_row = 0; pixel_row < effect->pixel_height; ++pixel_row) {
const int destination_y = pixel_y + (int)pixel_row;
if (destination_y < 0 || destination_y >= LCD_HEIGHT) {
continue;
}
for (unsigned pixel_column = 0; pixel_column < effect->pixel_width; ++pixel_column) {
const int destination_x = pixel_x + (int)pixel_column;
// Build the framebuffer address only after both coordinates
// are valid. This guards About and Hall of Fame against a
// damaged or changed flame field corrupting LCD state.
if (destination_x >= 0 && destination_x < LCD_WIDTH) {
frame[(size_t)destination_y * LCD_WIDTH + destination_x] = color;
}
}
}
}
}
}