Merge branch 'tildearrow:master' into SID3
This commit is contained in:
commit
1a67453b99
|
@ -263,6 +263,8 @@ enum DivDispatchCmds {
|
|||
DIV_CMD_BIFURCATOR_STATE_LOAD,
|
||||
DIV_CMD_BIFURCATOR_PARAMETER,
|
||||
|
||||
DIV_CMD_FDS_MOD_AUTO,
|
||||
|
||||
DIV_CMD_MAX
|
||||
};
|
||||
|
||||
|
|
|
@ -200,6 +200,15 @@ void DivPlatformFDS::tick(bool sysTick) {
|
|||
}
|
||||
rWrite(0x4082,chan[i].freq&0xff);
|
||||
rWrite(0x4083,(chan[i].freq>>8)&15);
|
||||
|
||||
if (chan[i].autoModNum>0 && chan[i].autoModDen>0) {
|
||||
chan[i].modFreq=(chan[i].freq*chan[i].autoModNum)/chan[i].autoModDen;
|
||||
if (chan[i].modFreq>4095) chan[i].modFreq=4095;
|
||||
if (chan[i].modFreq<0) chan[i].modFreq=0;
|
||||
rWrite(0x4086,chan[i].modFreq&0xff);
|
||||
rWrite(0x4087,chan[i].modFreq>>8);
|
||||
}
|
||||
|
||||
if (chan[i].keyOn) chan[i].keyOn=false;
|
||||
if (chan[i].keyOff) chan[i].keyOff=false;
|
||||
chan[i].freqChanged=false;
|
||||
|
@ -342,6 +351,13 @@ int DivPlatformFDS::dispatch(DivCommand c) {
|
|||
rWrite(0x4087,chan[c.chan].modFreq>>8);
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FDS_MOD_AUTO:
|
||||
chan[c.chan].autoModNum=c.value>>4;
|
||||
chan[c.chan].autoModDen=c.value&15;
|
||||
chan[c.chan].freqChanged=true;
|
||||
chan[c.chan].modOn=(chan[c.chan].autoModNum && chan[c.chan].autoModDen);
|
||||
rWrite(0x4084,(chan[c.chan].modOn<<7)|0x40|chan[c.chan].modDepth);
|
||||
break;
|
||||
case DIV_CMD_NOTE_PORTA: {
|
||||
int destFreq=NOTE_FREQUENCY(c.value2);
|
||||
bool return2=false;
|
||||
|
|
|
@ -29,6 +29,7 @@ class DivPlatformFDS: public DivDispatch {
|
|||
struct Channel: public SharedChannel<signed char> {
|
||||
int prevFreq, modFreq;
|
||||
unsigned char duty, sweep, modDepth, modPos;
|
||||
unsigned char autoModNum, autoModDen;
|
||||
bool sweepChanged, modOn;
|
||||
signed short wave;
|
||||
signed char modTable[32];
|
||||
|
@ -40,6 +41,8 @@ class DivPlatformFDS: public DivDispatch {
|
|||
sweep(8),
|
||||
modDepth(0),
|
||||
modPos(0),
|
||||
autoModNum(0),
|
||||
autoModDen(0),
|
||||
sweepChanged(false),
|
||||
modOn(false),
|
||||
wave(-1) {
|
||||
|
|
|
@ -261,7 +261,9 @@ const char* cmdName[]={
|
|||
"MINMOD_ECHO",
|
||||
|
||||
"BIFURCATOR_STATE_LOAD",
|
||||
"BIFURCATOR_PARAMETER"
|
||||
"BIFURCATOR_PARAMETER",
|
||||
|
||||
"FDS_MOD_AUTO"
|
||||
};
|
||||
|
||||
static_assert((sizeof(cmdName)/sizeof(void*))==DIV_CMD_MAX,"update cmdName!");
|
||||
|
|
|
@ -1067,6 +1067,7 @@ void DivEngine::registerSystems() {
|
|||
{0x13, {DIV_CMD_FDS_MOD_LOW, _("13xx: Set modulation speed low byte")}},
|
||||
{0x14, {DIV_CMD_FDS_MOD_POS, _("14xx: Set modulator position")}},
|
||||
{0x15, {DIV_CMD_FDS_MOD_WAVE, _("15xx: Set modulator table to waveform")}},
|
||||
{0x16, {DIV_CMD_FDS_MOD_AUTO, _("16xy: Automatic modulation speed (x: numerator; y: denominator)")}},
|
||||
}
|
||||
);
|
||||
|
||||
|
|
|
@ -486,7 +486,7 @@ std::vector<String>& FurnaceGUIFileDialog::getFileName() {
|
|||
return fileName;
|
||||
} else {
|
||||
fileName.clear();
|
||||
if (dialogType==1) {
|
||||
if (dialogType!=0) {
|
||||
fileName.push_back(ImGuiFileDialog::Instance()->GetFilePathName());
|
||||
} else {
|
||||
for (auto& i: ImGuiFileDialog::Instance()->GetSelection()) {
|
||||
|
|
|
@ -5159,11 +5159,81 @@ bool FurnaceGUI::loop() {
|
|||
}
|
||||
}
|
||||
break;
|
||||
case GUI_FILE_INS_SAVE_ALL:
|
||||
case GUI_FILE_WAVE_SAVE_ALL:
|
||||
case GUI_FILE_SAMPLE_SAVE_ALL:
|
||||
showError("Placeholder.");
|
||||
case GUI_FILE_INS_SAVE_ALL: {
|
||||
String errors;
|
||||
for (int i=0; i<e->song.insLen; i++) {
|
||||
String nextPath=copyOfName;
|
||||
nextPath+=DIR_SEPARATOR_STR;
|
||||
nextPath+=fmt::sprintf("%.2X_",i);
|
||||
for (char j: e->song.ins[i]->name) {
|
||||
switch (j) {
|
||||
// these chars are reserved
|
||||
case '/': case '<': case '>': case ':': case '"': case '\\': case '|': case '?': case '*':
|
||||
nextPath+='_';
|
||||
break;
|
||||
default:
|
||||
nextPath+=j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
nextPath+=".fui";
|
||||
logV("%s",nextPath);
|
||||
if (!e->song.ins[i]->save(nextPath.c_str(),&e->song,settings.writeInsNames)) {
|
||||
errors+=fmt::sprintf("%s: could not save!\n",e->song.ins[i]->name);
|
||||
}
|
||||
}
|
||||
|
||||
if (!errors.empty()) {
|
||||
showError(errors);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GUI_FILE_WAVE_SAVE_ALL: {
|
||||
String errors;
|
||||
for (int i=0; i<e->song.waveLen; i++) {
|
||||
String nextPath=copyOfName;
|
||||
nextPath+=DIR_SEPARATOR_STR;
|
||||
nextPath+=fmt::sprintf("%.2X.fuw",i);
|
||||
logV("%s",nextPath);
|
||||
if (!e->song.wave[i]->save(nextPath.c_str())) {
|
||||
errors+=fmt::sprintf("%d: could not save!\n",i);
|
||||
}
|
||||
}
|
||||
|
||||
if (!errors.empty()) {
|
||||
showError(errors);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GUI_FILE_SAMPLE_SAVE_ALL: {
|
||||
String errors;
|
||||
for (int i=0; i<e->song.sampleLen; i++) {
|
||||
String nextPath=copyOfName;
|
||||
nextPath+=DIR_SEPARATOR_STR;
|
||||
nextPath+=fmt::sprintf("%.2X_",i);
|
||||
for (char j: e->song.sample[i]->name) {
|
||||
switch (j) {
|
||||
// these chars are reserved
|
||||
case '/': case '<': case '>': case ':': case '"': case '\\': case '|': case '?': case '*':
|
||||
nextPath+='_';
|
||||
break;
|
||||
default:
|
||||
nextPath+=j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
nextPath+=".wav";
|
||||
logV("%s",nextPath);
|
||||
if (!e->song.sample[i]->save(nextPath.c_str())) {
|
||||
errors+=fmt::sprintf("%s: could not save!\n",e->song.sample[i]->name);
|
||||
}
|
||||
}
|
||||
|
||||
if (!errors.empty()) {
|
||||
showError(errors);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GUI_FILE_WAVE_SAVE:
|
||||
if (curWave>=0 && curWave<(int)e->song.wave.size()) {
|
||||
if (e->song.wave[curWave]->save(copyOfName.c_str())) {
|
||||
|
|
Loading…
Reference in a new issue