[NCSF] Minor code changes to reduce code duplication.
* Made a function in the Override struct to centralize where it
determines whether to use the override value or not.
* Made a function that returns the number of bytes that a command needs,
and used that to remove all the conditionals for processing a command to
instead handle that within the IF command itself.
Thanks to fincs and Henke37 for the suggestions to do this.
--- a/src/in_ncsf/SSEQPlayer/Track.cpp
+++ b/src/in_ncsf/SSEQPlayer/Track.cpp
@@ -8,7 +8,6 @@
* https://github.com/fincs/FSS
*/
-#include <functional>
#include <cstdlib>
#include "Track.h"
#include "Player.h"
@@ -41,7 +40,7 @@
this->stackPos = 0;
memset(this->loopCount, 0, sizeof(this->loopCount));
this->overriding() = false;
- this->lastComparisonResult = this->processCommand = true;
+ this->lastComparisonResult = true;
this->wait = 0;
this->patch = 0;
@@ -320,6 +319,79 @@
SSEQ_CMD_MUTE = 0xD7 // Unsupported
};
+static const uint8_t VariableByteCount = 1 << 7;
+static const uint8_t ExtraByteOnNoteOrVarOrCmp = 1 << 6;
+
+static inline uint8_t SseqCommandByteCount(int cmd)
+{
+ if (cmd < 0x80)
+ return 1 | VariableByteCount;
+ else
+ switch (cmd)
+ {
+ case SSEQ_CMD_REST:
+ case SSEQ_CMD_PATCH:
+ return VariableByteCount;
+
+ case SSEQ_CMD_PAN:
+ case SSEQ_CMD_VOL:
+ case SSEQ_CMD_MASTERVOL:
+ case SSEQ_CMD_PRIO:
+ case SSEQ_CMD_NOTEWAIT:
+ case SSEQ_CMD_TIE:
+ case SSEQ_CMD_EXPR:
+ case SSEQ_CMD_LOOPSTART:
+ case SSEQ_CMD_TRANSPOSE:
+ case SSEQ_CMD_PITCHBEND:
+ case SSEQ_CMD_PITCHBENDRANGE:
+ case SSEQ_CMD_ATTACK:
+ case SSEQ_CMD_DECAY:
+ case SSEQ_CMD_SUSTAIN:
+ case SSEQ_CMD_RELEASE:
+ case SSEQ_CMD_PORTAKEY:
+ case SSEQ_CMD_PORTAFLAG:
+ case SSEQ_CMD_PORTATIME:
+ case SSEQ_CMD_MODDEPTH:
+ case SSEQ_CMD_MODSPEED:
+ case SSEQ_CMD_MODTYPE:
+ case SSEQ_CMD_MODRANGE:
+ case SSEQ_CMD_PRINTVAR:
+ case SSEQ_CMD_MUTE:
+ return 1;
+
+ case SSEQ_CMD_TEMPO:
+ case SSEQ_CMD_SWEEPPITCH:
+ case SSEQ_CMD_MODDELAY:
+ return 2;
+
+ case SSEQ_CMD_GOTO:
+ case SSEQ_CMD_CALL:
+ case SSEQ_CMD_SETVAR:
+ case SSEQ_CMD_ADDVAR:
+ case SSEQ_CMD_SUBVAR:
+ case SSEQ_CMD_MULVAR:
+ case SSEQ_CMD_DIVVAR:
+ case SSEQ_CMD_SHIFTVAR:
+ case SSEQ_CMD_RANDVAR:
+ case SSEQ_CMD_CMP_EQ:
+ case SSEQ_CMD_CMP_GE:
+ case SSEQ_CMD_CMP_GT:
+ case SSEQ_CMD_CMP_LE:
+ case SSEQ_CMD_CMP_LT:
+ case SSEQ_CMD_CMP_NE:
+ return 3;
+
+ case SSEQ_CMD_FROMVAR:
+ return 1 | ExtraByteOnNoteOrVarOrCmp; // Technically 2 bytes with an additional 1, leaving 1 off because we will be reading it to determine if the additional byte is needed
+
+ case SSEQ_CMD_RANDOM:
+ return 4 | ExtraByteOnNoteOrVarOrCmp; // Technically 5 bytes with an additional 1, leaving 1 off because we will be reading it to determine if the additional byte is needed
+
+ default:
+ return 0;
+ }
+}
+
static auto varFuncSet = [](int16_t, int16_t value) { return value; };
static auto varFuncAdd = [](int16_t var, int16_t value) -> int16_t { return var + value; };
static auto varFuncSub = [](int16_t var, int16_t value) -> int16_t { return var - value; };
@@ -420,27 +492,14 @@
{
// Note on
int key = cmd + this->transpose;
- int vel;
- int len;
- if (this->overriding())
- {
- vel = this->overriding.extraValue;
- len = this->overriding.value;
- }
+ int vel = this->overriding.val(pData, read8, true);
+ int len = this->overriding.val(pData, readvl);
+ if (this->state[TS_NOTEWAIT])
+ this->wait = len;
+ if (this->state[TS_TIEBIT])
+ this->NoteOnTie(key, vel);
else
- {
- vel = read8(pData);
- len = readvl(pData);
- }
- if (this->processCommand)
- {
- if (this->state[TS_NOTEWAIT])
- this->wait = len;
- if (this->state[TS_TIEBIT])
- this->NoteOnTie(key, vel);
- else
- this->NoteOn(key, vel, len);
- }
+ this->NoteOn(key, vel, len);
}
else
{
@@ -452,32 +511,20 @@
//-----------------------------------------------------------------
case SSEQ_CMD_REST:
- if (this->overriding())
- value = this->overriding.value;
- else
- value = readvl(pData);
- if (this->processCommand)
- this->wait = value;
+ this->wait = this->overriding.val(pData, readvl);
break;
case SSEQ_CMD_PATCH:
- if (this->overriding())
- value = this->overriding.value;
- else
- value = readvl(pData);
- if (this->processCommand)
- this->patch = value;
+ this->patch = this->overriding.val(pData, readvl);
break;
case SSEQ_CMD_GOTO:
- value = read24(pData);
- if (this->processCommand)
- *pData = &this->ply->sseq->data[value];
+ *pData = &this->ply->sseq->data[read24(pData)];
break;
case SSEQ_CMD_CALL:
value = read24(pData);
- if (this->processCommand && this->stackPos < FSS_TRACKSTACKSIZE)
+ if (this->stackPos < FSS_TRACKSTACKSIZE)
{
const uint8_t *dest = &this->ply->sseq->data[value];
this->stack[this->stackPos++] = StackValue(STACKTYPE_CALL, *pData);
@@ -486,101 +533,56 @@
break;
case SSEQ_CMD_RET:
- if (this->processCommand && this->stackPos && this->stack[this->stackPos - 1].type == STACKTYPE_CALL)
+ if (this->stackPos && this->stack[this->stackPos - 1].type == STACKTYPE_CALL)
*pData = this->stack[--this->stackPos].dest;
break;
case SSEQ_CMD_PAN:
- if (this->overriding())
- value = this->overriding.value;
- else
- value = read8(pData);
- if (this->processCommand)
- {
- this->pan = value - 64;
- this->updateFlags.set(TUF_PAN);
- }
+ this->pan = this->overriding.val(pData, read8) - 64;
+ this->updateFlags.set(TUF_PAN);
break;
case SSEQ_CMD_VOL:
- if (this->overriding())
- value = this->overriding.value;
- else
- value = read8(pData);
- if (this->processCommand)
- {
- this->vol = value;
- this->updateFlags.set(TUF_VOL);
- }
+ this->vol = this->overriding.val(pData, read8);
+ this->updateFlags.set(TUF_VOL);
break;
case SSEQ_CMD_MASTERVOL:
- if (this->overriding())
- value = this->overriding.value;
- else
- value = read8(pData);
- if (this->processCommand)
- {
- this->ply->masterVol = Cnv_Sust(value);
- for (uint8_t i = 0; i < this->ply->nTracks; ++i)
- this->ply->tracks[this->ply->trackIds[i]].updateFlags.set(TUF_VOL);
- }
+ this->ply->masterVol = Cnv_Sust(this->overriding.val(pData, read8));
+ for (uint8_t i = 0; i < this->ply->nTracks; ++i)
+ this->ply->tracks[this->ply->trackIds[i]].updateFlags.set(TUF_VOL);
break;
case SSEQ_CMD_PRIO:
- value = read8(pData);
- if (this->processCommand)
- this->prio = this->ply->prio + value;
+ this->prio = this->ply->prio + read8(pData);
// Update here?
break;
case SSEQ_CMD_NOTEWAIT:
- value = read8(pData);
- if (this->processCommand)
- this->state.set(TS_NOTEWAIT, !!value);
+ this->state.set(TS_NOTEWAIT, !!read8(pData));
break;
case SSEQ_CMD_TIE:
- value = read8(pData);
- if (this->processCommand)
- {
- this->state.set(TS_TIEBIT, !!value);
- this->ReleaseAllNotes();
- }
+ this->state.set(TS_TIEBIT, !!read8(pData));
+ this->ReleaseAllNotes();
break;
case SSEQ_CMD_EXPR:
- if (this->overriding())
- value = this->overriding.value;
- else
- value = read8(pData);
- if (this->processCommand)
- {
- this->expr = value;
- this->updateFlags.set(TUF_VOL);
- }
+ this->expr = this->overriding.val(pData, read8);
+ this->updateFlags.set(TUF_VOL);
break;
case SSEQ_CMD_TEMPO:
- value = read16(pData);
- if (this->processCommand)
- this->ply->tempo = value;
+ this->ply->tempo = read16(pData);
break;
case SSEQ_CMD_END:
- if (this->processCommand)
- {
- this->state.set(TS_END);
- return;
- }
- break;
+ this->state.set(TS_END);
+ return;
case SSEQ_CMD_LOOPSTART:
- if (this->overriding())
- value = this->overriding.value;
- else
- value = read8(pData);
- if (this->processCommand && this->stackPos < FSS_TRACKSTACKSIZE)
+ value = this->overriding.val(pData, read8);
+ if (this->stackPos < FSS_TRACKSTACKSIZE)
{
this->loopCount[this->stackPos] = value;
this->stack[this->stackPos++] = StackValue(STACKTYPE_LOOP, *pData);
@@ -588,7 +590,7 @@
break;
case SSEQ_CMD_LOOPEND:
- if (this->processCommand && this->stackPos && this->stack[this->stackPos - 1].type == STACKTYPE_LOOP)
+ if (this->stackPos && this->stack[this->stackPos - 1].type == STACKTYPE_LOOP)
{
const uint8_t *rPos = this->stack[this->stackPos - 1].dest;
uint8_t &nR = this->loopCount[this->stackPos - 1];
@@ -610,33 +612,17 @@
//-----------------------------------------------------------------
case SSEQ_CMD_TRANSPOSE:
- if (this->overriding())
- value = this->overriding.value;
- else
- value = read8(pData);
- if (this->processCommand)
- this->transpose = value;
+ this->transpose = this->overriding.val(pData, read8);
break;
case SSEQ_CMD_PITCHBEND:
- if (this->overriding())
- value = this->overriding.value;
- else
- value = read8(pData);
- if (this->processCommand)
- {
- this->pitchBend = value;
- this->updateFlags.set(TUF_TIMER);
- }
+ this->pitchBend = this->overriding.val(pData, read8);
+ this->updateFlags.set(TUF_TIMER);
break;
case SSEQ_CMD_PITCHBENDRANGE:
- value = read8(pData);
- if (this->processCommand)
- {
- this->pitchBendRange = value;
- this->updateFlags.set(TUF_TIMER);
- }
+ this->pitchBendRange = read8(pData);
+ this->updateFlags.set(TUF_TIMER);
break;
//-----------------------------------------------------------------
@@ -644,39 +630,19 @@
//-----------------------------------------------------------------
case SSEQ_CMD_ATTACK:
- if (this->overriding())
- value = this->overriding.value;
- else
- value = read8(pData);
- if (this->processCommand)
- this->a = value;
+ this->a = this->overriding.val(pData, read8);
break;
case SSEQ_CMD_DECAY:
- if (this->overriding())
- value = this->overriding.value;
- else
- value = read8(pData);
- if (this->processCommand)
- this->d = value;
+ this->d = this->overriding.val(pData, read8);
break;
case SSEQ_CMD_SUSTAIN:
- if (this->overriding())
- value = this->overriding.value;
- else
- value = read8(pData);
- if (this->processCommand)
- this->s = value;
+ this->s = this->overriding.val(pData, read8);
break;
case SSEQ_CMD_RELEASE:
- if (this->overriding())
- value = this->overriding.value;
- else
- value = read8(pData);
- if (this->processCommand)
- this->r = value;
+ this->r = this->overriding.val(pData, read8);
break;
//-----------------------------------------------------------------
@@ -684,41 +650,23 @@
//-----------------------------------------------------------------
case SSEQ_CMD_PORTAKEY:
- value = read8(pData);
- if (this->processCommand)
- {
- this->portaKey = value + this->transpose;
- this->state.set(TS_PORTABIT);
- // Update here?
- }
+ this->portaKey = read8(pData) + this->transpose;
+ this->state.set(TS_PORTABIT);
+ // Update here?
break;
case SSEQ_CMD_PORTAFLAG:
- value = read8(pData);
- if (this->processCommand)
- {
- this->state.set(TS_PORTABIT, !!value);
- // Update here?
- }
+ this->state.set(TS_PORTABIT, !!read8(pData));
+ // Update here?
break;
case SSEQ_CMD_PORTATIME:
- if (this->overriding())
- value = this->overriding.value;
- else
- value = read8(pData);
- if (this->processCommand)
- this->portaTime = value;
+ this->portaTime = this->overriding.val(pData, read8);
// Update here?
break;
case SSEQ_CMD_SWEEPPITCH:
- if (this->overriding())
- value = this->overriding.value;
- else
- value = read16(pData);
- if (this->processCommand)
- this->sweepPitch = value;
+ this->sweepPitch = this->overriding.val(pData, read16);
// Update here?
break;
@@ -727,57 +675,28 @@
//-----------------------------------------------------------------
case SSEQ_CMD_MODDEPTH:
- if (this->overriding())
- value = this->overriding.value;
- else
- value = read8(pData);
- if (this->processCommand)
- {
- this->modDepth = value;
- this->updateFlags.set(TUF_MOD);
- }
+ this->modDepth = this->overriding.val(pData, read8);
+ this->updateFlags.set(TUF_MOD);
break;
case SSEQ_CMD_MODSPEED:
- if (this->overriding())
- value = this->overriding.value;
- else
- value = read8(pData);
- if (this->processCommand)
- {
- this->modSpeed = value;
- this->updateFlags.set(TUF_MOD);
- }
+ this->modSpeed = this->overriding.val(pData, read8);
+ this->updateFlags.set(TUF_MOD);
break;
case SSEQ_CMD_MODTYPE:
- value = read8(pData);
- if (this->processCommand)
- {
- this->modType = value;
- this->updateFlags.set(TUF_MOD);
- }
+ this->modType = read8(pData);
+ this->updateFlags.set(TUF_MOD);
break;
case SSEQ_CMD_MODRANGE:
- value = read8(pData);
- if (this->processCommand)
- {
- this->modRange = value;
- this->updateFlags.set(TUF_MOD);
- }
+ this->modRange = read8(pData);
+ this->updateFlags.set(TUF_MOD);
break;
case SSEQ_CMD_MODDELAY:
- if (this->overriding())
- value = this->overriding.value;
- else
- value = read16(pData);
- if (this->processCommand)
- {
- this->modDelay = value;
- this->updateFlags.set(TUF_MOD);
- }
+ this->modDelay = this->overriding.val(pData, read16);
+ this->updateFlags.set(TUF_MOD);
break;
//-----------------------------------------------------------------
@@ -786,8 +705,7 @@
case SSEQ_CMD_RANDOM:
{
- if (this->processCommand)
- this->overriding() = true;
+ this->overriding() = true;
this->overriding.cmd = read8(pData);
if ((this->overriding.cmd >= SSEQ_CMD_SETVAR && this->overriding.cmd <= SSEQ_CMD_CMP_NE) || this->overriding.cmd < 0x80)
this->overriding.extraValue = read8(pData);
@@ -802,8 +720,7 @@
//-----------------------------------------------------------------
case SSEQ_CMD_FROMVAR:
- if (this->processCommand)
- this->overriding() = true;
+ this->overriding() = true;
this->overriding.cmd = read8(pData);
if ((this->overriding.cmd >= SSEQ_CMD_SETVAR && this->overriding.cmd <= SSEQ_CMD_CMP_NE) || this->overriding.cmd < 0x80)
this->overriding.extraValue = read8(pData);
@@ -818,21 +735,11 @@
case SSEQ_CMD_SHIFTVAR:
case SSEQ_CMD_RANDVAR:
{
- int8_t varNo;
- if (this->overriding())
- {
- varNo = this->overriding.extraValue;
- value = this->overriding.value;
- }
- else
- {
- varNo = read8(pData);
- value = read16(pData);
- }
+ int8_t varNo = this->overriding.val(pData, read8, true);
+ value = this->overriding.val(pData, read16);
if (cmd == SSEQ_CMD_DIVVAR && !value) // Division by 0, skip it to prevent crashing
break;
- if (this->processCommand)
- this->ply->variables[varNo] = VarFunc(cmd)(this->ply->variables[varNo], value);
+ this->ply->variables[varNo] = VarFunc(cmd)(this->ply->variables[varNo], value);
break;
}
@@ -847,39 +754,39 @@
case SSEQ_CMD_CMP_LT:
case SSEQ_CMD_CMP_NE:
{
- int8_t varNo;
- if (this->overriding())
+ int8_t varNo = this->overriding.val(pData, read8, true);
+ value = this->overriding.val(pData, read16);
+ this->lastComparisonResult = CompareFunc(cmd)(this->ply->variables[varNo], value);
+ break;
+ }
+
+ case SSEQ_CMD_IF:
+ if (!this->lastComparisonResult)
{
- varNo = this->overriding.extraValue;
- value = this->overriding.value;
+ int nextCmd = read8(pData);
+ uint8_t cmdBytes = SseqCommandByteCount(nextCmd);
+ bool variableBytes = !!(cmdBytes & VariableByteCount);
+ bool extraByte = !!(cmdBytes & ExtraByteOnNoteOrVarOrCmp);
+ cmdBytes &= ~(VariableByteCount | ExtraByteOnNoteOrVarOrCmp);
+ if (extraByte)
+ {
+ int extraCmd = read8(pData);
+ if ((extraCmd >= SSEQ_CMD_SETVAR && extraCmd <= SSEQ_CMD_CMP_NE) || extraCmd < 0x80)
+ ++cmdBytes;
+ }
+ *pData += cmdBytes;
+ if (variableBytes)
+ readvl(pData);
}
- else
- {
- varNo = read8(pData);
- value = read16(pData);
- }
- if (this->processCommand)
- this->lastComparisonResult = CompareFunc(cmd)(this->ply->variables[varNo], value);
- break;
- }
-
- case SSEQ_CMD_IF:
- this->processCommand = this->lastComparisonResult;
- break;
-
- case SSEQ_CMD_PRINTVAR:
- ++*pData;
- break;
-
- case SSEQ_CMD_MUTE: // UNSUPPORTED
- ++*pData;
+ break;
+
+ default:
+ *pData += SseqCommandByteCount(cmd);
}
}
if (cmd != SSEQ_CMD_RANDOM && cmd != SSEQ_CMD_FROMVAR)
this->overriding() = false;
- if (cmd != SSEQ_CMD_IF)
- this->processCommand = true;
- }
-}
-
+ }
+}
+
--- a/src/in_ncsf/SSEQPlayer/Track.h
+++ b/src/in_ncsf/SSEQPlayer/Track.h
@@ -10,6 +10,7 @@
#pragma once
+#include <functional>
#include <bitset>
#include "consts.h"
@@ -40,6 +41,13 @@
Override() : overriding(false) { }
bool operator()() const { return this->overriding; }
bool &operator()() { return this->overriding; }
+ int val(const uint8_t **pData, std::function<int (const uint8_t **)> reader, bool returnExtra = false)
+ {
+ if (this->overriding)
+ return returnExtra ? this->extraValue : this->value;
+ else
+ return reader(pData);
+ }
};
struct Track
@@ -57,7 +65,6 @@
uint8_t loopCount[FSS_TRACKSTACKSIZE];
Override overriding;
bool lastComparisonResult;
- bool processCommand;
int wait;
uint16_t patch;