Skip to content

Commit

Permalink
Validate sizes of FmChannel fields at compile-time
Browse files Browse the repository at this point in the history
  • Loading branch information
rhargreaves committed Aug 23, 2024
1 parent 950a270 commit f567008
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 64 deletions.
42 changes: 21 additions & 21 deletions src/synth.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,34 +12,34 @@
#define STEREO_MODE_LEFT 2

typedef struct Operator {
u8 multiple;
u8 detune;
u8 attackRate;
u8 rateScaling;
u8 decayRate;
u8 amplitudeModulation;
u8 sustainLevel;
u8 sustainRate;
u8 releaseRate;
u8 totalLevel;
u8 ssgEg;
u8 multiple : 4;
u8 detune : 3;
u8 attackRate : 5;
u8 rateScaling : 2;
u8 decayRate : 5;
u8 amplitudeModulation : 1;
u8 sustainLevel : 4;
u8 sustainRate : 5;
u8 releaseRate : 4;
u8 totalLevel : 7;
u8 ssgEg : 4;
} Operator;

typedef struct FmChannel {
u8 algorithm;
u8 feedback;
u8 stereo;
u8 ams;
u8 fms;
u8 octave;
u16 freqNumber;
u8 algorithm : 3;
u8 feedback : 3;
u8 stereo : 2;
u8 ams : 2;
u8 fms : 3;
u8 octave : 3;
u16 freqNumber : 11;
Operator operators[MAX_FM_OPERATORS];
} FmChannel;

typedef struct Global {
u8 lfoEnable;
u8 lfoFrequency;
bool specialMode;
u8 lfoEnable : 1;
u8 lfoFrequency : 3;
bool specialMode : 1;
} Global;

typedef enum ParameterUpdated { Channel, Lfo, SpecialMode } ParameterUpdated;
Expand Down
116 changes: 73 additions & 43 deletions src/ui_fm.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ static void initAlgorithmSprites(void);
static void updateFmValuesIfChanSelected(void);
static void synthParameterUpdated(u8 fmChan, ParameterUpdated parameterUpdated);
static bool updateFmValue(
u8* last, const u8* current, bool forceRefresh, FormatTextFunc formatFunc, u8 x, u8 y);
u8 last, const u8 current, bool forceRefresh, FormatTextFunc formatFunc, u8 x, u8 y);

void ui_fm_init(void)
{
Expand Down Expand Up @@ -199,38 +199,38 @@ static const char* formatNum(u8 value)
}

static bool updateFmValue(
u8* last, const u8* current, bool forceRefresh, FormatTextFunc formatFunc, u8 x, u8 y)
u8 last, const u8 current, bool forceRefresh, FormatTextFunc formatFunc, u8 x, u8 y)
{
if (*last != *current || forceRefresh) {
ui_draw_text(formatFunc(*current), x, y);
*last = *current;
if (last != current || forceRefresh) {
ui_draw_text(formatFunc(current), x, y);
last = current;
return true;
}
return false;
}

static bool updateFmValueBool(
bool* last, const bool* current, bool forceRefresh, FormatTextFunc formatFunc, u8 x, u8 y)
bool last, bool current, bool forceRefresh, FormatTextFunc formatFunc, u8 x, u8 y)
{
if (*last != *current || forceRefresh) {
ui_draw_text(formatFunc(*current), x, y);
*last = *current;
if (last != current || forceRefresh) {
ui_draw_text(formatFunc(current), x, y);
return true;
}
return false;
}

static void updateOpValue(u8* last, const u8* current, bool forceRefresh, u8 op, u8 line)
static bool updateOpValue(u8 last, u8 current, bool forceRefresh, u8 op, u8 line)
{
const u8 OP_VALUE_X = OP_HEADING_X + 4;
const u8 OP_VALUE_GAP = 4;

if (*last != *current || forceRefresh) {
if (last != current || forceRefresh) {
char buffer[4];
v_sprintf(buffer, "%3d", *current);
v_sprintf(buffer, "%3d", current);
ui_draw_text(buffer, OP_VALUE_X + (op * OP_VALUE_GAP), BASE_Y + line);
*last = *current;
return true;
}
return false;
}

static void updateOpValues(const FmChannel* channel, bool forceRefresh)
Expand All @@ -239,18 +239,29 @@ static void updateOpValues(const FmChannel* channel, bool forceRefresh)
const Operator* oper = &channel->operators[op];
Operator* lastOper = &lastChannel.operators[op];

updateOpValue(&lastOper->totalLevel, &oper->totalLevel, forceRefresh, op, 4);
updateOpValue(&lastOper->attackRate, &oper->attackRate, forceRefresh, op, 5);
updateOpValue(&lastOper->multiple, &oper->multiple, forceRefresh, op, 6);
updateOpValue(&lastOper->detune, &oper->detune, forceRefresh, op, 7);
updateOpValue(&lastOper->rateScaling, &oper->rateScaling, forceRefresh, op, 8);
updateOpValue(
&lastOper->amplitudeModulation, &oper->amplitudeModulation, forceRefresh, op, 9);
updateOpValue(&lastOper->decayRate, &oper->decayRate, forceRefresh, op, 10);
updateOpValue(&lastOper->sustainRate, &oper->sustainRate, forceRefresh, op, 11);
updateOpValue(&lastOper->sustainLevel, &oper->sustainLevel, forceRefresh, op, 12);
updateOpValue(&lastOper->releaseRate, &oper->releaseRate, forceRefresh, op, 13);
updateOpValue(&lastOper->ssgEg, &oper->ssgEg, forceRefresh, op, 14);
if (updateOpValue(lastOper->totalLevel, oper->totalLevel, forceRefresh, op, 4))
lastOper->totalLevel = oper->totalLevel;
if (updateOpValue(lastOper->attackRate, oper->attackRate, forceRefresh, op, 5))
lastOper->attackRate = oper->attackRate;
if (updateOpValue(lastOper->multiple, oper->multiple, forceRefresh, op, 6))
lastOper->multiple = oper->multiple;
if (updateOpValue(lastOper->detune, oper->detune, forceRefresh, op, 7))
lastOper->detune = oper->detune;
if (updateOpValue(lastOper->rateScaling, oper->rateScaling, forceRefresh, op, 8))
lastOper->rateScaling = oper->rateScaling;
if (updateOpValue(
lastOper->amplitudeModulation, oper->amplitudeModulation, forceRefresh, op, 9))
lastOper->amplitudeModulation = oper->amplitudeModulation;
if (updateOpValue(lastOper->decayRate, oper->decayRate, forceRefresh, op, 10))
lastOper->decayRate = oper->decayRate;
if (updateOpValue(lastOper->sustainRate, oper->sustainRate, forceRefresh, op, 11))
lastOper->sustainRate = oper->sustainRate;
if (updateOpValue(lastOper->sustainLevel, oper->sustainLevel, forceRefresh, op, 12))
lastOper->sustainLevel = oper->sustainLevel;
if (updateOpValue(lastOper->releaseRate, oper->releaseRate, forceRefresh, op, 13))
lastOper->releaseRate = oper->releaseRate;
if (updateOpValue(lastOper->ssgEg, oper->ssgEg, forceRefresh, op, 14))
lastOper->ssgEg = oper->ssgEg;
}
}

Expand All @@ -262,28 +273,47 @@ static void updateFmValues(void)
const u8 COL1_VALUE_X = FM_HEADING_X + 4;
const u8 COL2_VALUE_X = FM_HEADING_X + 11;

updateFmValue(&lastChanParasMidiChannel, &chanParasMidiChan, forceRefresh, chanNumber,
COL1_VALUE_X + 1, BASE_Y + 3);
updateFmValue(
&lastChanParasFmChan, &chanParasFmChan, forceRefresh, chanNumber, COL2_VALUE_X, BASE_Y + 3);
if (updateFmValue(lastChanParasMidiChannel, chanParasMidiChan, forceRefresh, chanNumber,
COL1_VALUE_X + 1, BASE_Y + 3)) {
lastChanParasMidiChannel = chanParasMidiChan;
}
if (updateFmValue(lastChanParasFmChan, chanParasFmChan, forceRefresh, chanNumber, COL2_VALUE_X,
BASE_Y + 3))
lastChanParasFmChan = chanParasFmChan;

if (updateFmValue(&lastChannel.algorithm, &channel->algorithm, forceRefresh, formatNum,
if (updateFmValue(lastChannel.algorithm, channel->algorithm, forceRefresh, formatNum,
COL1_VALUE_X, BASE_Y + 5)) {
lastChannel.algorithm = channel->algorithm;
updateAlgorithmDiagram(channel->algorithm);
}
updateFmValue(&lastChannel.feedback, &channel->feedback, forceRefresh, formatNum, COL1_VALUE_X,
BASE_Y + 6);
updateFmValue(
&lastChannel.stereo, &channel->stereo, forceRefresh, stereoText, COL1_VALUE_X, BASE_Y + 7);
updateFmValue(&lastChannel.fms, &channel->fms, forceRefresh, fmsText, COL1_VALUE_X, BASE_Y + 8);
updateFmValue(&lastChannel.ams, &channel->ams, forceRefresh, amsText, COL1_VALUE_X, BASE_Y + 9);

updateFmValue(&lastGlobal.lfoEnable, &global->lfoEnable, forceRefresh, lfoEnableText,
COL1_VALUE_X, BASE_Y + 11);
updateFmValue(&lastGlobal.lfoFrequency, &global->lfoFrequency, forceRefresh, lfoFreqText,
COL1_VALUE_X + 4, BASE_Y + 11);
updateFmValueBool(&lastGlobal.specialMode, &global->specialMode, forceRefresh,
ch3SpecialModeText, COL1_VALUE_X, BASE_Y + 12);
if (updateFmValue(lastChannel.feedback, channel->feedback, forceRefresh, formatNum,
COL1_VALUE_X, BASE_Y + 6)) {
lastChannel.feedback = channel->feedback;
}
if (updateFmValue(lastChannel.stereo, channel->stereo, forceRefresh, stereoText, COL1_VALUE_X,
BASE_Y + 7)) {
lastChannel.stereo = channel->stereo;
}
if (updateFmValue(
lastChannel.fms, channel->fms, forceRefresh, fmsText, COL1_VALUE_X, BASE_Y + 8)) {
lastChannel.fms = channel->fms;
}
if (updateFmValue(
lastChannel.ams, channel->ams, forceRefresh, amsText, COL1_VALUE_X, BASE_Y + 9)) {
lastChannel.ams = channel->ams;
}
if (updateFmValue(lastGlobal.lfoEnable, global->lfoEnable, forceRefresh, lfoEnableText,
COL1_VALUE_X, BASE_Y + 11)) {
lastGlobal.lfoEnable = global->lfoEnable;
}
if (updateFmValue(lastGlobal.lfoFrequency, global->lfoFrequency, forceRefresh, lfoFreqText,
COL1_VALUE_X + 4, BASE_Y + 11)) {
lastGlobal.lfoFrequency = global->lfoFrequency;
}
if (updateFmValueBool(lastGlobal.specialMode, global->specialMode, forceRefresh,
ch3SpecialModeText, COL1_VALUE_X, BASE_Y + 12)) {
lastGlobal.specialMode = global->specialMode;
}

updateOpValues(channel, forceRefresh);
forceRefresh = false;
Expand Down

0 comments on commit f567008

Please sign in to comment.