mirror of
https://github.com/tildearrow/furnace.git
synced 2024-11-02 02:52:40 +00:00
S3M/XM/IT import: tremolo, pan slides and panbrell
This commit is contained in:
parent
bed6ec8eab
commit
e0ad1642c5
3 changed files with 268 additions and 5 deletions
|
@ -187,13 +187,19 @@ bool DivEngine::loadIT(unsigned char* file, size_t len) {
|
||||||
bool doesVibrato[64];
|
bool doesVibrato[64];
|
||||||
bool doesPanning[64];
|
bool doesPanning[64];
|
||||||
bool doesVolSlide[64];
|
bool doesVolSlide[64];
|
||||||
|
bool doesPanSlide[64];
|
||||||
bool doesArp[64];
|
bool doesArp[64];
|
||||||
|
bool doesTremolo[64];
|
||||||
|
bool doesPanbrello[64];
|
||||||
|
|
||||||
memset(doesPitchSlide,0,64*sizeof(bool));
|
memset(doesPitchSlide,0,64*sizeof(bool));
|
||||||
memset(doesVibrato,0,64*sizeof(bool));
|
memset(doesVibrato,0,64*sizeof(bool));
|
||||||
memset(doesPanning,0,64*sizeof(bool));
|
memset(doesPanning,0,64*sizeof(bool));
|
||||||
memset(doesVolSlide,0,64*sizeof(bool));
|
memset(doesVolSlide,0,64*sizeof(bool));
|
||||||
|
memset(doesPanSlide,0,64*sizeof(bool));
|
||||||
memset(doesArp,0,64*sizeof(bool));
|
memset(doesArp,0,64*sizeof(bool));
|
||||||
|
memset(doesTremolo,0,64*sizeof(bool));
|
||||||
|
memset(doesPanbrello,0,64*sizeof(bool));
|
||||||
|
|
||||||
SafeReader reader=SafeReader(file,len);
|
SafeReader reader=SafeReader(file,len);
|
||||||
warnings="";
|
warnings="";
|
||||||
|
@ -867,9 +873,18 @@ bool DivEngine::loadIT(unsigned char* file, size_t len) {
|
||||||
doesVolSlide[chan]=true;
|
doesVolSlide[chan]=true;
|
||||||
doesPitchSlide[chan]=true;
|
doesPitchSlide[chan]=true;
|
||||||
break;
|
break;
|
||||||
|
case 'P': // pan slide
|
||||||
|
doesPanSlide[chan]=true;
|
||||||
|
break;
|
||||||
|
case 'R': // tremolo
|
||||||
|
doesTremolo[chan]=true;
|
||||||
|
break;
|
||||||
case 'U': // fine vibrato
|
case 'U': // fine vibrato
|
||||||
doesVibrato[chan]=true;
|
doesVibrato[chan]=true;
|
||||||
break;
|
break;
|
||||||
|
case 'Y': // panbrello
|
||||||
|
doesPanbrello[chan]=true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -895,6 +910,18 @@ bool DivEngine::loadIT(unsigned char* file, size_t len) {
|
||||||
bool arpStatusChanged[64];
|
bool arpStatusChanged[64];
|
||||||
bool arping[64];
|
bool arping[64];
|
||||||
bool arpingOld[64];
|
bool arpingOld[64];
|
||||||
|
unsigned char panStatus[64];
|
||||||
|
bool panStatusChanged[64];
|
||||||
|
bool panning[64];
|
||||||
|
bool panningOld[64];
|
||||||
|
unsigned char tremStatus[64];
|
||||||
|
bool tremStatusChanged[64];
|
||||||
|
bool treming[64];
|
||||||
|
bool tremingOld[64];
|
||||||
|
unsigned char panSlideStatus[64];
|
||||||
|
bool panSlideStatusChanged[64];
|
||||||
|
bool panSliding[64];
|
||||||
|
bool panSlidingOld[64];
|
||||||
bool did[64];
|
bool did[64];
|
||||||
|
|
||||||
if (patPtr[i]==0) continue;
|
if (patPtr[i]==0) continue;
|
||||||
|
@ -926,6 +953,18 @@ bool DivEngine::loadIT(unsigned char* file, size_t len) {
|
||||||
memset(arpStatusChanged,0,64*sizeof(bool));
|
memset(arpStatusChanged,0,64*sizeof(bool));
|
||||||
memset(arping,0,64*sizeof(bool));
|
memset(arping,0,64*sizeof(bool));
|
||||||
memset(arpingOld,0,64*sizeof(bool));
|
memset(arpingOld,0,64*sizeof(bool));
|
||||||
|
memset(panStatus,0,64);
|
||||||
|
memset(panStatusChanged,0,64*sizeof(bool));
|
||||||
|
memset(panning,0,64*sizeof(bool));
|
||||||
|
memset(panningOld,0,64*sizeof(bool));
|
||||||
|
memset(tremStatus,0,64);
|
||||||
|
memset(tremStatusChanged,0,64*sizeof(bool));
|
||||||
|
memset(treming,0,64*sizeof(bool));
|
||||||
|
memset(tremingOld,0,64*sizeof(bool));
|
||||||
|
memset(panSlideStatus,0,64);
|
||||||
|
memset(panSlideStatusChanged,0,64*sizeof(bool));
|
||||||
|
memset(panSliding,0,64*sizeof(bool));
|
||||||
|
memset(panSlidingOld,0,64*sizeof(bool));
|
||||||
memset(did,0,64*sizeof(bool));
|
memset(did,0,64*sizeof(bool));
|
||||||
|
|
||||||
memset(mask,0,64);
|
memset(mask,0,64);
|
||||||
|
@ -1023,6 +1062,33 @@ bool DivEngine::loadIT(unsigned char* file, size_t len) {
|
||||||
p->data[readRow][effectCol[j]++]=0;
|
p->data[readRow][effectCol[j]++]=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (treming[j]!=tremingOld[j] || tremStatusChanged[j]) {
|
||||||
|
p->data[readRow][effectCol[j]++]=0x07;
|
||||||
|
p->data[readRow][effectCol[j]++]=treming[j]?tremStatus[j]:0;
|
||||||
|
doesTremolo[j]=true;
|
||||||
|
} else if (doesTremolo[j] && mustCommitInitial) {
|
||||||
|
p->data[readRow][effectCol[j]++]=0x07;
|
||||||
|
p->data[readRow][effectCol[j]++]=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (panning[j]!=panningOld[j] || panStatusChanged[j]) {
|
||||||
|
p->data[readRow][effectCol[j]++]=0x84;
|
||||||
|
p->data[readRow][effectCol[j]++]=panning[j]?panStatus[j]:0;
|
||||||
|
doesPanbrello[j]=true;
|
||||||
|
} else if (doesPanbrello[j] && mustCommitInitial) {
|
||||||
|
p->data[readRow][effectCol[j]++]=0x84;
|
||||||
|
p->data[readRow][effectCol[j]++]=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (panSliding[j]!=panSlidingOld[j] || panSlideStatusChanged[j]) {
|
||||||
|
p->data[readRow][effectCol[j]++]=0x83;
|
||||||
|
p->data[readRow][effectCol[j]++]=panSliding[j]?panSlideStatus[j]:0;
|
||||||
|
doesPanSlide[j]=true;
|
||||||
|
} else if (doesPanSlide[j] && mustCommitInitial) {
|
||||||
|
p->data[readRow][effectCol[j]++]=0x83;
|
||||||
|
p->data[readRow][effectCol[j]++]=0;
|
||||||
|
}
|
||||||
|
|
||||||
if ((effectCol[j]>>1)-2>ds.subsong[0]->pat[j].effectCols) {
|
if ((effectCol[j]>>1)-2>ds.subsong[0]->pat[j].effectCols) {
|
||||||
ds.subsong[0]->pat[j].effectCols=(effectCol[j]>>1)-1;
|
ds.subsong[0]->pat[j].effectCols=(effectCol[j]>>1)-1;
|
||||||
}
|
}
|
||||||
|
@ -1034,14 +1100,23 @@ bool DivEngine::loadIT(unsigned char* file, size_t len) {
|
||||||
memcpy(volSlidingOld,volSliding,64*sizeof(bool));
|
memcpy(volSlidingOld,volSliding,64*sizeof(bool));
|
||||||
memcpy(portingOld,porting,64*sizeof(bool));
|
memcpy(portingOld,porting,64*sizeof(bool));
|
||||||
memcpy(arpingOld,arping,64*sizeof(bool));
|
memcpy(arpingOld,arping,64*sizeof(bool));
|
||||||
|
memcpy(panningOld,panning,64*sizeof(bool));
|
||||||
|
memcpy(tremingOld,treming,64*sizeof(bool));
|
||||||
|
memcpy(panSlidingOld,panSliding,64*sizeof(bool));
|
||||||
memset(vibStatusChanged,0,64*sizeof(bool));
|
memset(vibStatusChanged,0,64*sizeof(bool));
|
||||||
memset(volSlideStatusChanged,0,64*sizeof(bool));
|
memset(volSlideStatusChanged,0,64*sizeof(bool));
|
||||||
memset(portaStatusChanged,0,64*sizeof(bool));
|
memset(portaStatusChanged,0,64*sizeof(bool));
|
||||||
memset(arpStatusChanged,0,64*sizeof(bool));
|
memset(arpStatusChanged,0,64*sizeof(bool));
|
||||||
|
memset(panStatusChanged,0,64*sizeof(bool));
|
||||||
|
memset(tremStatusChanged,0,64*sizeof(bool));
|
||||||
|
memset(panSlideStatusChanged,0,64*sizeof(bool));
|
||||||
memset(vibing,0,64*sizeof(bool));
|
memset(vibing,0,64*sizeof(bool));
|
||||||
memset(volSliding,0,64*sizeof(bool));
|
memset(volSliding,0,64*sizeof(bool));
|
||||||
memset(porting,0,64*sizeof(bool));
|
memset(porting,0,64*sizeof(bool));
|
||||||
memset(arping,0,64*sizeof(bool));
|
memset(arping,0,64*sizeof(bool));
|
||||||
|
memset(panning,0,64*sizeof(bool));
|
||||||
|
memset(treming,0,64*sizeof(bool));
|
||||||
|
memset(panSliding,0,64*sizeof(bool));
|
||||||
memset(did,0,64);
|
memset(did,0,64);
|
||||||
mustCommitInitial=false;
|
mustCommitInitial=false;
|
||||||
if (readRow>=patRows) {
|
if (readRow>=patRows) {
|
||||||
|
@ -1252,12 +1327,22 @@ bool DivEngine::loadIT(unsigned char* file, size_t len) {
|
||||||
p->data[readRow][effectCol[chan]++]=effectVal[chan];
|
p->data[readRow][effectCol[chan]++]=effectVal[chan];
|
||||||
break;
|
break;
|
||||||
case 'P': // pan slide
|
case 'P': // pan slide
|
||||||
|
if (effectVal[chan]!=0) {
|
||||||
|
panSlideStatus[chan]=effectVal[chan];
|
||||||
|
panSlideStatusChanged[chan]=true;
|
||||||
|
}
|
||||||
|
panSliding[chan]=true;
|
||||||
break;
|
break;
|
||||||
case 'Q': // retrigger
|
case 'Q': // retrigger
|
||||||
p->data[readRow][effectCol[chan]++]=0x0c;
|
p->data[readRow][effectCol[chan]++]=0x0c;
|
||||||
p->data[readRow][effectCol[chan]++]=effectVal[chan]&15;
|
p->data[readRow][effectCol[chan]++]=effectVal[chan]&15;
|
||||||
break;
|
break;
|
||||||
case 'R': // tremolo
|
case 'R': // tremolo
|
||||||
|
if (effectVal[chan]!=0) {
|
||||||
|
tremStatus[chan]=effectVal[chan];
|
||||||
|
tremStatusChanged[chan]=true;
|
||||||
|
}
|
||||||
|
treming[chan]=true;
|
||||||
break;
|
break;
|
||||||
case 'S': // special...
|
case 'S': // special...
|
||||||
switch (effectVal[chan]>>4) {
|
switch (effectVal[chan]>>4) {
|
||||||
|
@ -1291,6 +1376,11 @@ bool DivEngine::loadIT(unsigned char* file, size_t len) {
|
||||||
p->data[readRow][effectCol[chan]++]=effectVal[chan];
|
p->data[readRow][effectCol[chan]++]=effectVal[chan];
|
||||||
break;
|
break;
|
||||||
case 'Y': // panbrello
|
case 'Y': // panbrello
|
||||||
|
if (effectVal[chan]!=0) {
|
||||||
|
panStatus[chan]=effectVal[chan];
|
||||||
|
panStatusChanged[chan]=true;
|
||||||
|
}
|
||||||
|
panning[chan]=true;
|
||||||
break;
|
break;
|
||||||
case 'Z': // MIDI macro
|
case 'Z': // MIDI macro
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -68,7 +68,10 @@ bool DivEngine::loadS3M(unsigned char* file, size_t len) {
|
||||||
bool doesVibrato[32];
|
bool doesVibrato[32];
|
||||||
bool doesPanning[32];
|
bool doesPanning[32];
|
||||||
bool doesVolSlide[32];
|
bool doesVolSlide[32];
|
||||||
|
bool doesPanSlide[32];
|
||||||
bool doesArp[32];
|
bool doesArp[32];
|
||||||
|
bool doesTremolo[32];
|
||||||
|
bool doesPanbrello[32];
|
||||||
|
|
||||||
memset(chanSettings,0,32);
|
memset(chanSettings,0,32);
|
||||||
memset(insPtr,0,256*sizeof(unsigned int));
|
memset(insPtr,0,256*sizeof(unsigned int));
|
||||||
|
@ -82,7 +85,10 @@ bool DivEngine::loadS3M(unsigned char* file, size_t len) {
|
||||||
memset(doesVibrato,0,32*sizeof(bool));
|
memset(doesVibrato,0,32*sizeof(bool));
|
||||||
memset(doesPanning,0,32*sizeof(bool));
|
memset(doesPanning,0,32*sizeof(bool));
|
||||||
memset(doesVolSlide,0,32*sizeof(bool));
|
memset(doesVolSlide,0,32*sizeof(bool));
|
||||||
|
memset(doesPanSlide,0,32*sizeof(bool));
|
||||||
memset(doesArp,0,32*sizeof(bool));
|
memset(doesArp,0,32*sizeof(bool));
|
||||||
|
memset(doesTremolo,0,32*sizeof(bool));
|
||||||
|
memset(doesPanbrello,0,32*sizeof(bool));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
DivSong ds;
|
DivSong ds;
|
||||||
|
@ -672,6 +678,15 @@ bool DivEngine::loadS3M(unsigned char* file, size_t len) {
|
||||||
doesVolSlide[chan]=true;
|
doesVolSlide[chan]=true;
|
||||||
doesPitchSlide[chan]=true;
|
doesPitchSlide[chan]=true;
|
||||||
break;
|
break;
|
||||||
|
case 'P': // pan slide
|
||||||
|
doesPanSlide[chan]=true;
|
||||||
|
break;
|
||||||
|
case 'R': // tremolo
|
||||||
|
doesTremolo[chan]=true;
|
||||||
|
break;
|
||||||
|
case 'Y': // panbrello
|
||||||
|
doesPanbrello[chan]=true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -697,6 +712,18 @@ bool DivEngine::loadS3M(unsigned char* file, size_t len) {
|
||||||
bool arpStatusChanged[32];
|
bool arpStatusChanged[32];
|
||||||
bool arping[32];
|
bool arping[32];
|
||||||
bool arpingOld[32];
|
bool arpingOld[32];
|
||||||
|
unsigned char panStatus[32];
|
||||||
|
bool panStatusChanged[32];
|
||||||
|
bool panning[32];
|
||||||
|
bool panningOld[32];
|
||||||
|
unsigned char tremStatus[32];
|
||||||
|
bool tremStatusChanged[32];
|
||||||
|
bool treming[32];
|
||||||
|
bool tremingOld[32];
|
||||||
|
unsigned char panSlideStatus[32];
|
||||||
|
bool panSlideStatusChanged[32];
|
||||||
|
bool panSliding[32];
|
||||||
|
bool panSlidingOld[32];
|
||||||
bool did[32];
|
bool did[32];
|
||||||
|
|
||||||
if (patPtr[i]==0) continue;
|
if (patPtr[i]==0) continue;
|
||||||
|
@ -736,6 +763,18 @@ bool DivEngine::loadS3M(unsigned char* file, size_t len) {
|
||||||
memset(arpStatusChanged,0,32*sizeof(bool));
|
memset(arpStatusChanged,0,32*sizeof(bool));
|
||||||
memset(arping,0,32*sizeof(bool));
|
memset(arping,0,32*sizeof(bool));
|
||||||
memset(arpingOld,0,32*sizeof(bool));
|
memset(arpingOld,0,32*sizeof(bool));
|
||||||
|
memset(panStatus,0,32);
|
||||||
|
memset(panStatusChanged,0,32*sizeof(bool));
|
||||||
|
memset(panning,0,32*sizeof(bool));
|
||||||
|
memset(panningOld,0,32*sizeof(bool));
|
||||||
|
memset(tremStatus,0,32);
|
||||||
|
memset(tremStatusChanged,0,32*sizeof(bool));
|
||||||
|
memset(treming,0,32*sizeof(bool));
|
||||||
|
memset(tremingOld,0,32*sizeof(bool));
|
||||||
|
memset(panSlideStatus,0,32);
|
||||||
|
memset(panSlideStatusChanged,0,32*sizeof(bool));
|
||||||
|
memset(panSliding,0,32*sizeof(bool));
|
||||||
|
memset(panSlidingOld,0,32*sizeof(bool));
|
||||||
memset(did,0,32*sizeof(bool));
|
memset(did,0,32*sizeof(bool));
|
||||||
|
|
||||||
while (reader.tell()<dataEnd) {
|
while (reader.tell()<dataEnd) {
|
||||||
|
@ -797,6 +836,33 @@ bool DivEngine::loadS3M(unsigned char* file, size_t len) {
|
||||||
p->data[readRow][effectCol[j]++]=0;
|
p->data[readRow][effectCol[j]++]=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (treming[j]!=tremingOld[j] || tremStatusChanged[j]) {
|
||||||
|
p->data[readRow][effectCol[j]++]=0x07;
|
||||||
|
p->data[readRow][effectCol[j]++]=treming[j]?tremStatus[j]:0;
|
||||||
|
doesTremolo[j]=true;
|
||||||
|
} else if (doesTremolo[j] && mustCommitInitial) {
|
||||||
|
p->data[readRow][effectCol[j]++]=0x07;
|
||||||
|
p->data[readRow][effectCol[j]++]=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (panning[j]!=panningOld[j] || panStatusChanged[j]) {
|
||||||
|
p->data[readRow][effectCol[j]++]=0x84;
|
||||||
|
p->data[readRow][effectCol[j]++]=panning[j]?panStatus[j]:0;
|
||||||
|
doesPanbrello[j]=true;
|
||||||
|
} else if (doesPanbrello[j] && mustCommitInitial) {
|
||||||
|
p->data[readRow][effectCol[j]++]=0x84;
|
||||||
|
p->data[readRow][effectCol[j]++]=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (panSliding[j]!=panSlidingOld[j] || panSlideStatusChanged[j]) {
|
||||||
|
p->data[readRow][effectCol[j]++]=0x83;
|
||||||
|
p->data[readRow][effectCol[j]++]=panSliding[j]?panSlideStatus[j]:0;
|
||||||
|
doesPanSlide[j]=true;
|
||||||
|
} else if (doesPanSlide[j] && mustCommitInitial) {
|
||||||
|
p->data[readRow][effectCol[j]++]=0x83;
|
||||||
|
p->data[readRow][effectCol[j]++]=0;
|
||||||
|
}
|
||||||
|
|
||||||
if (effectCol[j]>=4+8*2) {
|
if (effectCol[j]>=4+8*2) {
|
||||||
logE("oh crap!");
|
logE("oh crap!");
|
||||||
}
|
}
|
||||||
|
@ -990,12 +1056,22 @@ bool DivEngine::loadS3M(unsigned char* file, size_t len) {
|
||||||
p->data[readRow][effectCol[chan]++]=effectVal;
|
p->data[readRow][effectCol[chan]++]=effectVal;
|
||||||
break;
|
break;
|
||||||
case 'P': // pan slide (extension)
|
case 'P': // pan slide (extension)
|
||||||
|
if (effectVal!=0) {
|
||||||
|
panSlideStatus[chan]=effectVal;
|
||||||
|
panSlideStatusChanged[chan]=true;
|
||||||
|
}
|
||||||
|
panSliding[chan]=true;
|
||||||
break;
|
break;
|
||||||
case 'Q': // retrigger
|
case 'Q': // retrigger
|
||||||
p->data[readRow][effectCol[chan]++]=0x0c;
|
p->data[readRow][effectCol[chan]++]=0x0c;
|
||||||
p->data[readRow][effectCol[chan]++]=effectVal&15;
|
p->data[readRow][effectCol[chan]++]=effectVal&15;
|
||||||
break;
|
break;
|
||||||
case 'R': // tremolo
|
case 'R': // tremolo
|
||||||
|
if (effectVal!=0) {
|
||||||
|
tremStatus[chan]=effectVal;
|
||||||
|
tremStatusChanged[chan]=true;
|
||||||
|
}
|
||||||
|
treming[chan]=true;
|
||||||
break;
|
break;
|
||||||
case 'S': // special...
|
case 'S': // special...
|
||||||
switch (effectVal>>4) {
|
switch (effectVal>>4) {
|
||||||
|
@ -1031,6 +1107,11 @@ bool DivEngine::loadS3M(unsigned char* file, size_t len) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'Y': // panbrello (extension)
|
case 'Y': // panbrello (extension)
|
||||||
|
if (effectVal!=0) {
|
||||||
|
panStatus[chan]=effectVal;
|
||||||
|
panStatusChanged[chan]=true;
|
||||||
|
}
|
||||||
|
panning[chan]=true;
|
||||||
break;
|
break;
|
||||||
case 'Z': // MIDI macro (extension)
|
case 'Z': // MIDI macro (extension)
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -135,7 +135,10 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) {
|
||||||
bool doesVibrato[128];
|
bool doesVibrato[128];
|
||||||
bool doesPanning[128];
|
bool doesPanning[128];
|
||||||
bool doesVolSlide[128];
|
bool doesVolSlide[128];
|
||||||
|
bool doesPanSlide[128];
|
||||||
bool doesArp[128];
|
bool doesArp[128];
|
||||||
|
bool doesTremolo[128];
|
||||||
|
bool doesPanbrello[128];
|
||||||
|
|
||||||
SafeReader reader=SafeReader(file,len);
|
SafeReader reader=SafeReader(file,len);
|
||||||
warnings="";
|
warnings="";
|
||||||
|
@ -150,7 +153,10 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) {
|
||||||
memset(doesVibrato,0,128*sizeof(bool));
|
memset(doesVibrato,0,128*sizeof(bool));
|
||||||
memset(doesPanning,0,128*sizeof(bool));
|
memset(doesPanning,0,128*sizeof(bool));
|
||||||
memset(doesVolSlide,0,128*sizeof(bool));
|
memset(doesVolSlide,0,128*sizeof(bool));
|
||||||
|
memset(doesPanSlide,0,128*sizeof(bool));
|
||||||
memset(doesArp,0,128*sizeof(bool));
|
memset(doesArp,0,128*sizeof(bool));
|
||||||
|
memset(doesTremolo,0,128*sizeof(bool));
|
||||||
|
memset(doesPanbrello,0,128*sizeof(bool));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
DivSong ds;
|
DivSong ds;
|
||||||
|
@ -358,10 +364,10 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) {
|
||||||
doesPanning[k]=true;
|
doesPanning[k]=true;
|
||||||
break;
|
break;
|
||||||
case 0xd: // pan slide left
|
case 0xd: // pan slide left
|
||||||
doesPanning[k]=true;
|
doesPanSlide[k]=true;
|
||||||
break;
|
break;
|
||||||
case 0xe: // pan slide right
|
case 0xe: // pan slide right
|
||||||
doesPanning[k]=true;
|
doesPanSlide[k]=true;
|
||||||
break;
|
break;
|
||||||
case 0xf: // porta
|
case 0xf: // porta
|
||||||
doesPitchSlide[k]=true;
|
doesPitchSlide[k]=true;
|
||||||
|
@ -394,6 +400,9 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) {
|
||||||
doesVibrato[k]=true;
|
doesVibrato[k]=true;
|
||||||
doesVolSlide[k]=true;
|
doesVolSlide[k]=true;
|
||||||
break;
|
break;
|
||||||
|
case 7:
|
||||||
|
doesTremolo[k]=true;
|
||||||
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
doesPanning[k]=true;
|
doesPanning[k]=true;
|
||||||
break;
|
break;
|
||||||
|
@ -401,11 +410,14 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) {
|
||||||
doesPanning[k]=true;
|
doesPanning[k]=true;
|
||||||
break;
|
break;
|
||||||
case 0x19: // P
|
case 0x19: // P
|
||||||
doesPanning[k]=true;
|
doesPanSlide[k]=true;
|
||||||
break;
|
break;
|
||||||
case 0x21: // X
|
case 0x21: // X
|
||||||
doesPitchSlide[k]=true;
|
doesPitchSlide[k]=true;
|
||||||
break;
|
break;
|
||||||
|
case 0x22: // Y
|
||||||
|
doesPanbrello[k]=true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (hasEffectVal) {
|
if (hasEffectVal) {
|
||||||
|
@ -665,6 +677,18 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) {
|
||||||
bool arpStatusChanged[128];
|
bool arpStatusChanged[128];
|
||||||
bool arping[128];
|
bool arping[128];
|
||||||
bool arpingOld[128];
|
bool arpingOld[128];
|
||||||
|
unsigned char panStatus[128];
|
||||||
|
bool panStatusChanged[128];
|
||||||
|
bool panning[128];
|
||||||
|
bool panningOld[128];
|
||||||
|
unsigned char tremStatus[128];
|
||||||
|
bool tremStatusChanged[128];
|
||||||
|
bool treming[128];
|
||||||
|
bool tremingOld[128];
|
||||||
|
unsigned char panSlideStatus[128];
|
||||||
|
bool panSlideStatusChanged[128];
|
||||||
|
bool panSliding[128];
|
||||||
|
bool panSlidingOld[128];
|
||||||
unsigned char lastNote[128];
|
unsigned char lastNote[128];
|
||||||
|
|
||||||
bool mustCommitInitial=true;
|
bool mustCommitInitial=true;
|
||||||
|
@ -687,6 +711,18 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) {
|
||||||
memset(arpStatusChanged,0,128*sizeof(bool));
|
memset(arpStatusChanged,0,128*sizeof(bool));
|
||||||
memset(arping,0,128*sizeof(bool));
|
memset(arping,0,128*sizeof(bool));
|
||||||
memset(arpingOld,0,128*sizeof(bool));
|
memset(arpingOld,0,128*sizeof(bool));
|
||||||
|
memset(panStatus,0,128);
|
||||||
|
memset(panStatusChanged,0,128*sizeof(bool));
|
||||||
|
memset(panning,0,128*sizeof(bool));
|
||||||
|
memset(panningOld,0,128*sizeof(bool));
|
||||||
|
memset(tremStatus,0,128);
|
||||||
|
memset(tremStatusChanged,0,128*sizeof(bool));
|
||||||
|
memset(treming,0,128*sizeof(bool));
|
||||||
|
memset(tremingOld,0,128*sizeof(bool));
|
||||||
|
memset(panSlideStatus,0,128);
|
||||||
|
memset(panSlideStatusChanged,0,128*sizeof(bool));
|
||||||
|
memset(panSliding,0,128*sizeof(bool));
|
||||||
|
memset(panSlidingOld,0,128*sizeof(bool));
|
||||||
memset(lastNote,0,128);
|
memset(lastNote,0,128);
|
||||||
|
|
||||||
logV("pattern %d",i);
|
logV("pattern %d",i);
|
||||||
|
@ -856,8 +892,20 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) {
|
||||||
writePanning=false;
|
writePanning=false;
|
||||||
break;
|
break;
|
||||||
case 0xd: // pan slide left
|
case 0xd: // pan slide left
|
||||||
|
if ((vol&15)!=0) {
|
||||||
|
panSlideStatus[k]&=0x0f;
|
||||||
|
panSlideStatus[k]|=(vol&15)<<4;
|
||||||
|
panSlideStatusChanged[k]=true;
|
||||||
|
}
|
||||||
|
panSliding[k]=true;
|
||||||
break;
|
break;
|
||||||
case 0xe: // pan slide right
|
case 0xe: // pan slide right
|
||||||
|
if ((vol&15)!=0) {
|
||||||
|
panSlideStatus[k]&=0xf0;
|
||||||
|
panSlideStatus[k]|=vol&15;
|
||||||
|
panSlideStatusChanged[k]=true;
|
||||||
|
}
|
||||||
|
panSliding[k]=true;
|
||||||
break;
|
break;
|
||||||
case 0xf: // porta
|
case 0xf: // porta
|
||||||
break;
|
break;
|
||||||
|
@ -946,6 +994,11 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) {
|
||||||
vibing[k]=true;
|
vibing[k]=true;
|
||||||
break;
|
break;
|
||||||
case 7: // tremolo
|
case 7: // tremolo
|
||||||
|
if (effectVal!=0) {
|
||||||
|
tremStatus[k]=effectVal;
|
||||||
|
tremStatusChanged[k]=true;
|
||||||
|
}
|
||||||
|
treming[k]=true;
|
||||||
break;
|
break;
|
||||||
case 8: // panning
|
case 8: // panning
|
||||||
p->data[j][effectCol[k]++]=0x80;
|
p->data[j][effectCol[k]++]=0x80;
|
||||||
|
@ -994,8 +1047,6 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x10: // G: global volume (!)
|
|
||||||
break;
|
|
||||||
case 0xf: // speed/tempp
|
case 0xf: // speed/tempp
|
||||||
if (effectVal>=0x20) {
|
if (effectVal>=0x20) {
|
||||||
p->data[j][effectCol[k]++]=0xf0;
|
p->data[j][effectCol[k]++]=0xf0;
|
||||||
|
@ -1004,6 +1055,8 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) {
|
||||||
}
|
}
|
||||||
p->data[j][effectCol[k]++]=effectVal;
|
p->data[j][effectCol[k]++]=effectVal;
|
||||||
break;
|
break;
|
||||||
|
case 0x10: // G: global volume (!)
|
||||||
|
break;
|
||||||
case 0x11: // H: global volume slide (!)
|
case 0x11: // H: global volume slide (!)
|
||||||
break;
|
break;
|
||||||
case 0x14: // K: key off
|
case 0x14: // K: key off
|
||||||
|
@ -1013,6 +1066,11 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) {
|
||||||
case 0x15: // L: set envelope position (!)
|
case 0x15: // L: set envelope position (!)
|
||||||
break;
|
break;
|
||||||
case 0x19: // P: pan slide
|
case 0x19: // P: pan slide
|
||||||
|
if (effectVal!=0) {
|
||||||
|
panSlideStatus[k]=effectVal;
|
||||||
|
panSlideStatusChanged[k]=true;
|
||||||
|
}
|
||||||
|
panSliding[k]=true;
|
||||||
break;
|
break;
|
||||||
case 0x1b: // R: retrigger
|
case 0x1b: // R: retrigger
|
||||||
p->data[j][effectCol[k]++]=0x0c;
|
p->data[j][effectCol[k]++]=0x0c;
|
||||||
|
@ -1022,6 +1080,13 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) {
|
||||||
break;
|
break;
|
||||||
case 0x21: // X: extra fine volume
|
case 0x21: // X: extra fine volume
|
||||||
break;
|
break;
|
||||||
|
case 0x22: // Y: panbrello (extension)
|
||||||
|
if (effectVal!=0) {
|
||||||
|
panStatus[k]=effectVal;
|
||||||
|
panStatusChanged[k]=true;
|
||||||
|
}
|
||||||
|
panning[k]=true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1086,6 +1151,33 @@ bool DivEngine::loadXM(unsigned char* file, size_t len) {
|
||||||
p->data[j][effectCol[k]++]=0;
|
p->data[j][effectCol[k]++]=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (treming[k]!=tremingOld[k] || tremStatusChanged[k]) {
|
||||||
|
p->data[j][effectCol[k]++]=0x07;
|
||||||
|
p->data[j][effectCol[k]++]=treming[k]?tremStatus[k]:0;
|
||||||
|
doesTremolo[k]=true;
|
||||||
|
} else if (doesTremolo[k] && mustCommitInitial) {
|
||||||
|
p->data[j][effectCol[k]++]=0x07;
|
||||||
|
p->data[j][effectCol[k]++]=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (panning[k]!=panningOld[k] || panStatusChanged[k]) {
|
||||||
|
p->data[j][effectCol[k]++]=0x84;
|
||||||
|
p->data[j][effectCol[k]++]=panning[k]?panStatus[k]:0;
|
||||||
|
doesPanbrello[k]=true;
|
||||||
|
} else if (doesPanbrello[k] && mustCommitInitial) {
|
||||||
|
p->data[j][effectCol[k]++]=0x84;
|
||||||
|
p->data[j][effectCol[k]++]=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (panSliding[k]!=panSlidingOld[k] || panSlideStatusChanged[k]) {
|
||||||
|
p->data[j][effectCol[k]++]=0x83;
|
||||||
|
p->data[j][effectCol[k]++]=panSliding[k]?panSlideStatus[k]:0;
|
||||||
|
doesPanSlide[k]=true;
|
||||||
|
} else if (doesPanSlide[k] && mustCommitInitial) {
|
||||||
|
p->data[j][effectCol[k]++]=0x83;
|
||||||
|
p->data[j][effectCol[k]++]=0;
|
||||||
|
}
|
||||||
|
|
||||||
if ((effectCol[k]>>1)-2>ds.subsong[0]->pat[k].effectCols) {
|
if ((effectCol[k]>>1)-2>ds.subsong[0]->pat[k].effectCols) {
|
||||||
ds.subsong[0]->pat[k].effectCols=(effectCol[k]>>1)-1;
|
ds.subsong[0]->pat[k].effectCols=(effectCol[k]>>1)-1;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue