parent
ff07a19405
commit
0f3f173b6e
|
@ -15,6 +15,7 @@ enum DivDispatchCmds {
|
||||||
DIV_CMD_PANNING,
|
DIV_CMD_PANNING,
|
||||||
DIV_CMD_LEGATO,
|
DIV_CMD_LEGATO,
|
||||||
DIV_CMD_PRE_PORTA,
|
DIV_CMD_PRE_PORTA,
|
||||||
|
DIV_CMD_PRE_NOTE, // used in C64
|
||||||
|
|
||||||
DIV_CMD_SAMPLE_MODE,
|
DIV_CMD_SAMPLE_MODE,
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ struct DivChannelState {
|
||||||
std::vector<DivDelayedCommand> delayed;
|
std::vector<DivDelayedCommand> delayed;
|
||||||
int note, pitch, portaSpeed, portaNote;
|
int note, pitch, portaSpeed, portaNote;
|
||||||
int volume, volSpeed, cut, rowDelay, volMax;
|
int volume, volSpeed, cut, rowDelay, volMax;
|
||||||
|
int delayOrder, delayRow;
|
||||||
int vibratoDepth, vibratoRate, vibratoPos, vibratoDir, vibratoFine;
|
int vibratoDepth, vibratoRate, vibratoPos, vibratoDir, vibratoFine;
|
||||||
int tremoloDepth, tremoloRate, tremoloPos;
|
int tremoloDepth, tremoloRate, tremoloPos;
|
||||||
unsigned char arp, arpStage, arpTicks;
|
unsigned char arp, arpStage, arpTicks;
|
||||||
|
@ -34,6 +35,8 @@ struct DivChannelState {
|
||||||
volSpeed(0),
|
volSpeed(0),
|
||||||
cut(-1),
|
cut(-1),
|
||||||
rowDelay(0),
|
rowDelay(0),
|
||||||
|
delayOrder(0),
|
||||||
|
delayRow(0),
|
||||||
vibratoDepth(0),
|
vibratoDepth(0),
|
||||||
vibratoRate(0),
|
vibratoRate(0),
|
||||||
vibratoPos(0),
|
vibratoPos(0),
|
||||||
|
@ -104,7 +107,7 @@ class DivEngine {
|
||||||
speedAB(false),
|
speedAB(false),
|
||||||
ticks(0),
|
ticks(0),
|
||||||
cycles(0),
|
cycles(0),
|
||||||
curRow(-1),
|
curRow(0),
|
||||||
curOrder(0),
|
curOrder(0),
|
||||||
changeOrd(-1),
|
changeOrd(-1),
|
||||||
changePos(0),
|
changePos(0),
|
||||||
|
|
|
@ -10,31 +10,6 @@ void DivPlatformC64::acquire(int& l, int& r) {
|
||||||
r=l;
|
r=l;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned char noiseTable[256]={
|
|
||||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 4,
|
|
||||||
15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4,
|
|
||||||
15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4,
|
|
||||||
3, 2, 1, 0, 11, 10, 9, 8, 7, 6, 5, 4,
|
|
||||||
15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4,
|
|
||||||
3, 2, 1, 0, 11, 10, 9, 8, 7, 6, 5, 4,
|
|
||||||
15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4,
|
|
||||||
3, 2, 1, 0, 11, 10, 9, 8, 7, 6, 5, 4,
|
|
||||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
|
||||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
|
||||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
|
||||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
|
||||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
|
||||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
|
||||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
|
||||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
|
||||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
|
||||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
|
||||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
|
||||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
|
||||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
|
||||||
15
|
|
||||||
};
|
|
||||||
|
|
||||||
void DivPlatformC64::tick() {
|
void DivPlatformC64::tick() {
|
||||||
for (int i=0; i<3; i++) {
|
for (int i=0; i<3; i++) {
|
||||||
chan[i].std.next();
|
chan[i].std.next();
|
||||||
|
@ -84,16 +59,10 @@ void DivPlatformC64::tick() {
|
||||||
//rWrite(16+i*5,chan[i].sweep);
|
//rWrite(16+i*5,chan[i].sweep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (chan[i].onTheKey) {
|
if (chan[i].testWhen>0) {
|
||||||
DivInstrument* ins=parent->getIns(chan[i].ins);
|
if (--chan[i].testWhen<1) {
|
||||||
sid.write(i*7+4,
|
sid.write(i*7+4,8);
|
||||||
(ins->c64.noiseOn<<7)|
|
}
|
||||||
(ins->c64.pulseOn<<6)|
|
|
||||||
(ins->c64.sawOn<<5)|
|
|
||||||
(ins->c64.triOn<<4)|
|
|
||||||
1
|
|
||||||
);
|
|
||||||
chan[i].onTheKey=false;
|
|
||||||
}
|
}
|
||||||
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
|
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
|
||||||
DivInstrument* ins=parent->getIns(chan[i].ins);
|
DivInstrument* ins=parent->getIns(chan[i].ins);
|
||||||
|
@ -106,9 +75,8 @@ void DivPlatformC64::tick() {
|
||||||
(ins->c64.pulseOn<<6)|
|
(ins->c64.pulseOn<<6)|
|
||||||
(ins->c64.sawOn<<5)|
|
(ins->c64.sawOn<<5)|
|
||||||
(ins->c64.triOn<<4)|
|
(ins->c64.triOn<<4)|
|
||||||
8
|
1
|
||||||
);
|
);
|
||||||
chan[i].onTheKey=true;
|
|
||||||
}
|
}
|
||||||
if (chan[i].keyOff) {
|
if (chan[i].keyOff) {
|
||||||
sid.write(i*7+5,(ins->c64.a<<4)|(ins->c64.d));
|
sid.write(i*7+5,(ins->c64.a<<4)|(ins->c64.d));
|
||||||
|
@ -207,6 +175,9 @@ int DivPlatformC64::dispatch(DivCommand c) {
|
||||||
chan[c.chan].std.init(parent->getIns(chan[c.chan].ins));
|
chan[c.chan].std.init(parent->getIns(chan[c.chan].ins));
|
||||||
chan[c.chan].inPorta=c.value;
|
chan[c.chan].inPorta=c.value;
|
||||||
break;
|
break;
|
||||||
|
case DIV_CMD_PRE_NOTE:
|
||||||
|
chan[c.chan].testWhen=c.value;
|
||||||
|
break;
|
||||||
case DIV_CMD_GET_VOLMAX:
|
case DIV_CMD_GET_VOLMAX:
|
||||||
return 15;
|
return 15;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -7,9 +7,9 @@
|
||||||
|
|
||||||
class DivPlatformC64: public DivDispatch {
|
class DivPlatformC64: public DivDispatch {
|
||||||
struct Channel {
|
struct Channel {
|
||||||
int freq, baseFreq, pitch, prevFreq;
|
int freq, baseFreq, pitch, prevFreq, testWhen;
|
||||||
unsigned char ins, note, duty, sweep;
|
unsigned char ins, note, duty, sweep;
|
||||||
bool active, insChanged, freqChanged, sweepChanged, keyOn, keyOff, inPorta, onTheKey;
|
bool active, insChanged, freqChanged, sweepChanged, keyOn, keyOff, inPorta;
|
||||||
signed char vol, outVol, wave;
|
signed char vol, outVol, wave;
|
||||||
DivMacroInt std;
|
DivMacroInt std;
|
||||||
Channel():
|
Channel():
|
||||||
|
@ -17,6 +17,7 @@ class DivPlatformC64: public DivDispatch {
|
||||||
baseFreq(0),
|
baseFreq(0),
|
||||||
pitch(0),
|
pitch(0),
|
||||||
prevFreq(65535),
|
prevFreq(65535),
|
||||||
|
testWhen(0),
|
||||||
ins(-1),
|
ins(-1),
|
||||||
note(0),
|
note(0),
|
||||||
duty(0),
|
duty(0),
|
||||||
|
@ -28,7 +29,6 @@ class DivPlatformC64: public DivDispatch {
|
||||||
keyOn(false),
|
keyOn(false),
|
||||||
keyOff(false),
|
keyOff(false),
|
||||||
inPorta(false),
|
inPorta(false),
|
||||||
onTheKey(false),
|
|
||||||
vol(15),
|
vol(15),
|
||||||
wave(-1) {}
|
wave(-1) {}
|
||||||
};
|
};
|
||||||
|
|
|
@ -23,6 +23,7 @@ const char* cmdName[DIV_CMD_MAX]={
|
||||||
"PANNING",
|
"PANNING",
|
||||||
"LEGATO",
|
"LEGATO",
|
||||||
"PRE_PORTA",
|
"PRE_PORTA",
|
||||||
|
"PRE_NOTE",
|
||||||
|
|
||||||
"SAMPLE_MODE",
|
"SAMPLE_MODE",
|
||||||
|
|
||||||
|
@ -205,25 +206,29 @@ bool DivEngine::perSystemPostEffect(int ch, unsigned char effect, unsigned char
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivEngine::processRow(int i, bool afterDelay) {
|
void DivEngine::processRow(int i, bool afterDelay) {
|
||||||
DivPattern* pat=song.pat[i]->data[curOrder];
|
int whatOrder=afterDelay?chan[i].delayOrder:curOrder;
|
||||||
|
int whatRow=afterDelay?chan[i].delayRow:curRow;
|
||||||
|
DivPattern* pat=song.pat[i]->data[whatOrder];
|
||||||
// pre effects
|
// pre effects
|
||||||
if (!afterDelay) for (int j=0; j<song.pat[i]->effectRows; j++) {
|
if (!afterDelay) for (int j=0; j<song.pat[i]->effectRows; j++) {
|
||||||
short effect=pat->data[curRow][4+(j<<1)];
|
short effect=pat->data[whatRow][4+(j<<1)];
|
||||||
short effectVal=pat->data[curRow][5+(j<<1)];
|
short effectVal=pat->data[whatRow][5+(j<<1)];
|
||||||
|
|
||||||
if (effectVal==-1) effectVal=0;
|
if (effectVal==-1) effectVal=0;
|
||||||
if (effect==0xed) {
|
if (effect==0xed) {
|
||||||
chan[i].rowDelay=effectVal+1;
|
chan[i].rowDelay=effectVal+1;
|
||||||
|
chan[i].delayOrder=whatOrder;
|
||||||
|
chan[i].delayRow=whatRow;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// instrument
|
// instrument
|
||||||
if (pat->data[curRow][2]!=-1) {
|
if (pat->data[whatRow][2]!=-1) {
|
||||||
dispatchCmd(DivCommand(DIV_CMD_INSTRUMENT,i,pat->data[curRow][2]));
|
dispatchCmd(DivCommand(DIV_CMD_INSTRUMENT,i,pat->data[whatRow][2]));
|
||||||
}
|
}
|
||||||
// note
|
// note
|
||||||
if (pat->data[curRow][0]==100) {
|
if (pat->data[whatRow][0]==100) {
|
||||||
chan[i].note=-1;
|
chan[i].note=-1;
|
||||||
chan[i].keyOn=false;
|
chan[i].keyOn=false;
|
||||||
if (chan[i].stopOnOff) {
|
if (chan[i].stopOnOff) {
|
||||||
|
@ -232,8 +237,8 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
||||||
chan[i].stopOnOff=false;
|
chan[i].stopOnOff=false;
|
||||||
}
|
}
|
||||||
dispatchCmd(DivCommand(DIV_CMD_NOTE_OFF,i));
|
dispatchCmd(DivCommand(DIV_CMD_NOTE_OFF,i));
|
||||||
} else if (!(pat->data[curRow][0]==0 && pat->data[curRow][1]==0)) {
|
} else if (!(pat->data[whatRow][0]==0 && pat->data[whatRow][1]==0)) {
|
||||||
chan[i].note=pat->data[curRow][0]+pat->data[curRow][1]*12;
|
chan[i].note=pat->data[whatRow][0]+pat->data[whatRow][1]*12;
|
||||||
if (!chan[i].keyOn) {
|
if (!chan[i].keyOn) {
|
||||||
chan[i].arp=0;
|
chan[i].arp=0;
|
||||||
}
|
}
|
||||||
|
@ -244,17 +249,17 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// volume
|
// volume
|
||||||
if (pat->data[curRow][3]!=-1) {
|
if (pat->data[whatRow][3]!=-1) {
|
||||||
if (dispatchCmd(DivCommand(DIV_ALWAYS_SET_VOLUME,i)) || (MIN(chan[i].volMax,chan[i].volume)>>8)!=pat->data[curRow][3]) {
|
if (dispatchCmd(DivCommand(DIV_ALWAYS_SET_VOLUME,i)) || (MIN(chan[i].volMax,chan[i].volume)>>8)!=pat->data[whatRow][3]) {
|
||||||
chan[i].volume=pat->data[curRow][3]<<8;
|
chan[i].volume=pat->data[whatRow][3]<<8;
|
||||||
dispatchCmd(DivCommand(DIV_CMD_VOLUME,i,chan[i].volume>>8));
|
dispatchCmd(DivCommand(DIV_CMD_VOLUME,i,chan[i].volume>>8));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// effects
|
// effects
|
||||||
for (int j=0; j<song.pat[i]->effectRows; j++) {
|
for (int j=0; j<song.pat[i]->effectRows; j++) {
|
||||||
short effect=pat->data[curRow][4+(j<<1)];
|
short effect=pat->data[whatRow][4+(j<<1)];
|
||||||
short effectVal=pat->data[curRow][5+(j<<1)];
|
short effectVal=pat->data[whatRow][5+(j<<1)];
|
||||||
|
|
||||||
if (effectVal==-1) effectVal=0;
|
if (effectVal==-1) effectVal=0;
|
||||||
|
|
||||||
|
@ -336,6 +341,8 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
||||||
break;
|
break;
|
||||||
case 0x0c: // retrigger
|
case 0x0c: // retrigger
|
||||||
chan[i].rowDelay=effectVal+1;
|
chan[i].rowDelay=effectVal+1;
|
||||||
|
chan[i].delayOrder=whatOrder;
|
||||||
|
chan[i].delayRow=whatRow;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xe0: // arp speed
|
case 0xe0: // arp speed
|
||||||
|
@ -399,8 +406,8 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
||||||
|
|
||||||
// post effects
|
// post effects
|
||||||
for (int j=0; j<song.pat[i]->effectRows; j++) {
|
for (int j=0; j<song.pat[i]->effectRows; j++) {
|
||||||
short effect=pat->data[curRow][4+(j<<1)];
|
short effect=pat->data[whatRow][4+(j<<1)];
|
||||||
short effectVal=pat->data[curRow][5+(j<<1)];
|
short effectVal=pat->data[whatRow][5+(j<<1)];
|
||||||
|
|
||||||
if (effectVal==-1) effectVal=0;
|
if (effectVal==-1) effectVal=0;
|
||||||
perSystemPostEffect(i,effect,effectVal);
|
perSystemPostEffect(i,effect,effectVal);
|
||||||
|
@ -412,18 +419,6 @@ void DivEngine::nextRow() {
|
||||||
static char pb1[4096];
|
static char pb1[4096];
|
||||||
static char pb2[4096];
|
static char pb2[4096];
|
||||||
static char pb3[4096];
|
static char pb3[4096];
|
||||||
if (++curRow>=song.patLen) {
|
|
||||||
nextOrder();
|
|
||||||
}
|
|
||||||
if (changeOrd>=0) {
|
|
||||||
curRow=changePos;
|
|
||||||
curOrder=changeOrd;
|
|
||||||
if (curOrder>=song.ordersLen) {
|
|
||||||
curOrder=0;
|
|
||||||
}
|
|
||||||
changeOrd=-1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (view==DIV_STATUS_PATTERN) {
|
if (view==DIV_STATUS_PATTERN) {
|
||||||
strcpy(pb1,"");
|
strcpy(pb1,"");
|
||||||
strcpy(pb3,"");
|
strcpy(pb3,"");
|
||||||
|
@ -469,6 +464,33 @@ void DivEngine::nextRow() {
|
||||||
chan[i].rowDelay=0;
|
chan[i].rowDelay=0;
|
||||||
processRow(i,false);
|
processRow(i,false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (++curRow>=song.patLen) {
|
||||||
|
nextOrder();
|
||||||
|
}
|
||||||
|
if (changeOrd>=0) {
|
||||||
|
curRow=changePos;
|
||||||
|
curOrder=changeOrd;
|
||||||
|
if (curOrder>=song.ordersLen) {
|
||||||
|
curOrder=0;
|
||||||
|
}
|
||||||
|
changeOrd=-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (speedAB) {
|
||||||
|
ticks=song.speed2*(song.timeBase+1);
|
||||||
|
} else {
|
||||||
|
ticks=song.speed1*(song.timeBase+1);
|
||||||
|
}
|
||||||
|
speedAB=!speedAB;
|
||||||
|
|
||||||
|
// post row details
|
||||||
|
for (int i=0; i<chans; i++) {
|
||||||
|
DivPattern* pat=song.pat[i]->data[curOrder];
|
||||||
|
if (!(pat->data[curRow][0]==0 && pat->data[curRow][1]==0)) {
|
||||||
|
dispatchCmd(DivCommand(DIV_CMD_PRE_NOTE,i,ticks));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivEngine::nextTick() {
|
void DivEngine::nextTick() {
|
||||||
|
@ -483,12 +505,6 @@ void DivEngine::nextTick() {
|
||||||
}
|
}
|
||||||
if (--ticks<=0) {
|
if (--ticks<=0) {
|
||||||
nextRow();
|
nextRow();
|
||||||
if (speedAB) {
|
|
||||||
ticks=song.speed2*(song.timeBase+1);
|
|
||||||
} else {
|
|
||||||
ticks=song.speed1*(song.timeBase+1);
|
|
||||||
}
|
|
||||||
speedAB=!speedAB;
|
|
||||||
}
|
}
|
||||||
// process stuff
|
// process stuff
|
||||||
for (int i=0; i<chans; i++) {
|
for (int i=0; i<chans; i++) {
|
||||||
|
|
Loading…
Reference in New Issue