Merge branch 'master' of https://github.com/tildearrow/furnace into ay_divider

* 'master' of https://github.com/tildearrow/furnace: (24 commits)
  GUI: remove insLoadAlwaysReplace setting
  GUI: right click menu for open instrument
  GUI: add a threshold for macro right click
  OPZ: remove debug printf
  GUI: add macro right click menu
  GUI: prepare for macro right click menu
  update gitignore
  add something
  prepare for something
  did i fix macOS build?
  GUI: macro edit improvements
  GUI: now add ability to load VMEM
  Update sysDef.cpp
  GUI: add an option for it
  add preliminary TX81Z SysEx response
  OPL: drum volume
  OPL: implement hard reset
  GUI: add icon size setting
  GUI: macro UI refactor, part 4
  Fix WIN32 define timing in IGFD
  ...
This commit is contained in:
cam900 2022-05-10 09:03:03 +09:00
commit a9a249fd4c
57 changed files with 6506 additions and 115 deletions

View file

@ -2383,6 +2383,22 @@ void DivEngine::setMidiCallback(std::function<int(const TAMidiMessage&)> what) {
midiCallback=what;
}
bool DivEngine::sendMidiMessage(TAMidiMessage& msg) {
if (output==NULL) {
logW("output is NULL!");
return false;
}
if (output->midiOut==NULL) {
logW("MIDI output is NULL!");
return false;
}
BUSY_BEGIN;
logD("sending MIDI message...");
bool ret=(output->midiOut->send(msg));
BUSY_END;
return ret;
}
void DivEngine::synchronized(const std::function<void()>& what) {
BUSY_BEGIN;
what();
@ -2632,6 +2648,8 @@ bool DivEngine::init() {
// init config
#ifdef _WIN32
configPath=getWinConfigPath();
#elif defined(ANDROID)
configPath=SDL_GetPrefPath("tildearrow","furnace");
#else
struct stat st;
char* home=getenv("HOME");

View file

@ -826,6 +826,9 @@ class DivEngine {
// if the specified function returns -2, note feedback will be inhibited.
void setMidiCallback(std::function<int(const TAMidiMessage&)> what);
// send MIDI message
bool sendMidiMessage(TAMidiMessage& msg);
// perform secure/sync operation
void synchronized(const std::function<void()>& what);

View file

@ -166,13 +166,20 @@ struct DivInstrumentMacro {
unsigned char len;
signed char loop;
signed char rel;
// the following variables are used by the GUI and not saved in the file
int vScroll, vZoom;
explicit DivInstrumentMacro(const String& n, bool initOpen=false):
name(n),
mode(0),
open(initOpen),
len(0),
loop(-1),
rel(-1) {
rel(-1),
vScroll(0),
vZoom(-1) {
memset(val,0,256*sizeof(int));
}
};

View file

@ -308,7 +308,7 @@ void DivPlatformOPL::tick(bool sysTick) {
if (isMuted[i]) {
rWrite(baseAddr+ADDR_KSL_TL,63|(op.ksl<<6));
} else {
if (isOutputL[ops==4][chan[i].state.alg][j]) {
if (isOutputL[ops==4][chan[i].state.alg][j] || i>=melodicChans) {
rWrite(baseAddr+ADDR_KSL_TL,(63-(((63-op.tl)*(chan[i].outVol&0x3f))/63))|(op.ksl<<6));
} else {
rWrite(baseAddr+ADDR_KSL_TL,op.tl|(op.ksl<<6));
@ -435,7 +435,7 @@ void DivPlatformOPL::tick(bool sysTick) {
if (isMuted[i]) {
rWrite(baseAddr+ADDR_KSL_TL,63|(op.ksl<<6));
} else {
if (isOutputL[ops==4][chan[i].state.alg][j]) {
if (isOutputL[ops==4][chan[i].state.alg][j] || i>=melodicChans) {
rWrite(baseAddr+ADDR_KSL_TL,(63-(((63-op.tl)*(chan[i].outVol&0x3f))/63))|(op.ksl<<6));
} else {
rWrite(baseAddr+ADDR_KSL_TL,op.tl|(op.ksl<<6));
@ -445,10 +445,34 @@ void DivPlatformOPL::tick(bool sysTick) {
}
if (i<melodicChans) {
if (chan[i].hardReset && chan[i].keyOn) {
for (int j=0; j<ops; j++) {
unsigned char slot=slots[j][i];
if (slot==255) continue;
unsigned short baseAddr=slotMap[slot];
DivInstrumentFM::Operator& op=chan[i].state.op[(ops==4)?orderedOpsL[j]:j];
immWrite(baseAddr+ADDR_SL_RR,0x0f);
immWrite(baseAddr+ADDR_KSL_TL,63|(op.ksl<<6));
oldWrites[baseAddr+ADDR_SL_RR]=-1;
oldWrites[baseAddr+ADDR_KSL_TL]=-1;
}
}
if (chan[i].keyOn || chan[i].keyOff) {
immWrite(chanMap[i]+ADDR_FREQH,0x00|(chan[i].freqH&31));
chan[i].keyOff=false;
}
if (chan[i].hardReset && chan[i].keyOn) {
for (int j=0; j<ops; j++) {
unsigned char slot=slots[j][i];
if (slot==255) continue;
unsigned short baseAddr=slotMap[slot];
DivInstrumentFM::Operator& op=chan[i].state.op[(ops==4)?orderedOpsL[j]:j];
for (int k=0; k<5; k++) {
immWrite(baseAddr+ADDR_SL_RR,0x0f);
immWrite(baseAddr+ADDR_KSL_TL,63|(op.ksl<<6));
}
}
}
}
}
@ -579,7 +603,7 @@ void DivPlatformOPL::muteChannel(int ch, bool mute) {
if (isMuted[ch]) {
rWrite(baseAddr+ADDR_KSL_TL,63|(op.ksl<<6));
} else {
if (isOutputL[ops==4][chan[ch].state.alg][i]) {
if (isOutputL[ops==4][chan[ch].state.alg][i] || ch>=melodicChans) {
rWrite(baseAddr+ADDR_KSL_TL,(63-(((63-op.tl)*(chan[ch].outVol&0x3f))/63))|(op.ksl<<6));
} else {
rWrite(baseAddr+ADDR_KSL_TL,op.tl|(op.ksl<<6));
@ -634,7 +658,7 @@ int DivPlatformOPL::dispatch(DivCommand c) {
if (isMuted[c.chan]) {
rWrite(baseAddr+ADDR_KSL_TL,63|(op.ksl<<6));
} else {
if (isOutputL[ops==4][chan[c.chan].state.alg][i]) {
if (isOutputL[ops==4][chan[c.chan].state.alg][i] || c.chan>=melodicChans) {
rWrite(baseAddr+ADDR_KSL_TL,(63-(((63-op.tl)*(chan[c.chan].outVol&0x3f))/63))|(op.ksl<<6));
} else {
rWrite(baseAddr+ADDR_KSL_TL,op.tl|(op.ksl<<6));
@ -723,7 +747,7 @@ int DivPlatformOPL::dispatch(DivCommand c) {
if (isMuted[c.chan]) {
rWrite(baseAddr+ADDR_KSL_TL,63|(op.ksl<<6));
} else {
if (isOutputL[ops==4][chan[c.chan].state.alg][i]) {
if (isOutputL[ops==4][chan[c.chan].state.alg][i] || c.chan>=melodicChans) {
rWrite(baseAddr+ADDR_KSL_TL,(63-(((63-op.tl)*(chan[c.chan].outVol&0x3f))/63))|(op.ksl<<6));
} else {
rWrite(baseAddr+ADDR_KSL_TL,op.tl|(op.ksl<<6));
@ -856,7 +880,7 @@ int DivPlatformOPL::dispatch(DivCommand c) {
if (isMuted[c.chan]) {
rWrite(baseAddr+ADDR_KSL_TL,63|(op.ksl<<6));
} else {
if (isOutputL[ops==4][chan[c.chan].state.alg][c.value]) {
if (isOutputL[ops==4][chan[c.chan].state.alg][c.value] || c.chan>=melodicChans) {
rWrite(baseAddr+ADDR_KSL_TL,(63-(((63-op.tl)*(chan[c.chan].outVol&0x3f))/63))|(op.ksl<<6));
} else {
rWrite(baseAddr+ADDR_KSL_TL,op.tl|(op.ksl<<6));
@ -1076,7 +1100,7 @@ int DivPlatformOPL::dispatch(DivCommand c) {
if (isMuted[c.chan]) {
rWrite(baseAddr+ADDR_KSL_TL,63|(op.ksl<<6));
} else {
if (isOutputL[ops==4][chan[c.chan].state.alg][i]) {
if (isOutputL[ops==4][chan[c.chan].state.alg][i] || c.chan>=melodicChans) {
rWrite(baseAddr+ADDR_KSL_TL,(63-(((63-op.tl)*(chan[c.chan].outVol&0x3f))/63))|(op.ksl<<6));
} else {
rWrite(baseAddr+ADDR_KSL_TL,op.tl|(op.ksl<<6));
@ -1093,7 +1117,7 @@ int DivPlatformOPL::dispatch(DivCommand c) {
if (isMuted[c.chan]) {
rWrite(baseAddr+ADDR_KSL_TL,63|(op.ksl<<6));
} else {
if (isOutputL[ops==4][chan[c.chan].state.alg][c.value]) {
if (isOutputL[ops==4][chan[c.chan].state.alg][c.value] || c.chan>=melodicChans) {
rWrite(baseAddr+ADDR_KSL_TL,(63-(((63-op.tl)*(chan[c.chan].outVol&0x3f))/63))|(op.ksl<<6));
} else {
rWrite(baseAddr+ADDR_KSL_TL,op.tl|(op.ksl<<6));
@ -1118,6 +1142,9 @@ int DivPlatformOPL::dispatch(DivCommand c) {
}
break;
}
case DIV_CMD_FM_HARD_RESET:
chan[c.chan].hardReset=c.value;
break;
case DIV_ALWAYS_SET_VOLUME:
return 0;
break;
@ -1161,7 +1188,7 @@ void DivPlatformOPL::forceIns() {
if (isMuted[i]) {
rWrite(baseAddr+ADDR_KSL_TL,63|(op.ksl<<6));
} else {
if (isOutputL[ops==4][chan[i].state.alg][j]) {
if (isOutputL[ops==4][chan[i].state.alg][j] || i>=melodicChans) {
rWrite(baseAddr+ADDR_KSL_TL,(63-(((63-op.tl)*(chan[i].outVol&0x3f))/63))|(op.ksl<<6));
} else {
rWrite(baseAddr+ADDR_KSL_TL,op.tl|(op.ksl<<6));

View file

@ -31,7 +31,7 @@ class DivPlatformOPL: public DivDispatch {
DivMacroInt std;
unsigned char freqH, freqL;
int freq, baseFreq, pitch, pitch2, note, ins;
bool active, insChanged, freqChanged, keyOn, keyOff, portaPause, furnaceDac, inPorta, fourOp;
bool active, insChanged, freqChanged, keyOn, keyOff, portaPause, furnaceDac, inPorta, fourOp, hardReset;
int vol, outVol;
unsigned char pan;
void macroInit(DivInstrument* which) {
@ -56,6 +56,7 @@ class DivPlatformOPL: public DivDispatch {
furnaceDac(false),
inPorta(false),
fourOp(false),
hardReset(false),
vol(0),
pan(3) {
state.ops=2;

View file

@ -919,7 +919,6 @@ int DivPlatformTX81Z::dispatch(DivCommand c) {
}
case DIV_CMD_FM_FIXFREQ: {
if (c.value<0 || c.value>3) break;
printf("fixfreq %x\n",c.value2);
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
op.egt=(c.value2>0);

View file

@ -1448,7 +1448,7 @@ void DivEngine::registerSystems() {
);
sysDefs[DIV_SYSTEM_YM2612_EXT]=new DivSysDef(
"Yamaha YM2612 Extended Channel 3", NULL, 0xa0, 0, 9, true, false, 0x150, false,
"Yamaha YM2612 (OPN2) Extended Channel 3", NULL, 0xa0, 0, 9, true, false, 0x150, false,
{"FM 1", "FM 2", "FM 3 OP1", "FM 3 OP2", "FM 3 OP3", "FM 3 OP4", "FM 4", "FM 5", "FM 6"},
{"F1", "F2", "O1", "O2", "O3", "O4", "F4", "F5", "F6"},
{DIV_CH_FM, DIV_CH_FM, DIV_CH_OP, DIV_CH_OP, DIV_CH_OP, DIV_CH_OP, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM},
@ -1481,7 +1481,7 @@ void DivEngine::registerSystems() {
};
sysDefs[DIV_SYSTEM_OPL_DRUMS]=new DivSysDef(
"Yamaha OPL with drums", NULL, 0xa2, 0, 11, true, false, 0x151, false,
"Yamaha YM3526 (OPL) with drums", NULL, 0xa2, 0, 11, true, false, 0x151, false,
{"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "Kick", "Snare", "Tom", "Top", "HiHat"},
{"F1", "F2", "F3", "F4", "F5", "F6", "BD", "SD", "TM", "TP", "HH"},
{DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE},
@ -1492,7 +1492,7 @@ void DivEngine::registerSystems() {
);
sysDefs[DIV_SYSTEM_OPL2_DRUMS]=new DivSysDef(
"Yamaha OPL2 with drums", NULL, 0xa3, 0, 11, true, false, 0x151, false,
"Yamaha YM3812 (OPL2) with drums", NULL, 0xa3, 0, 11, true, false, 0x151, false,
{"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "Kick", "Snare", "Tom", "Top", "HiHat"},
{"F1", "F2", "F3", "F4", "F5", "F6", "BD", "SD", "TM", "TP", "HH"},
{DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE},
@ -1503,7 +1503,7 @@ void DivEngine::registerSystems() {
);
sysDefs[DIV_SYSTEM_OPL3_DRUMS]=new DivSysDef(
"Yamaha OPL3 with drums", NULL, 0xa4, 0, 20, true, false, 0x151, false,
"Yamaha YMF262 (OPL3) with drums", NULL, 0xa4, 0, 20, true, false, 0x151, false,
{"4OP 1", "FM 2", "4OP 3", "FM 4", "4OP 5", "FM 6", "4OP 7", "FM 8", "4OP 9", "FM 10", "4OP 11", "FM 12", "FM 13", "FM 14", "FM 15", "Kick", "Snare", "Tom", "Top", "HiHat"},
{"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "BD", "SD", "TM", "TP", "HH"},
{DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE},
@ -1525,7 +1525,7 @@ void DivEngine::registerSystems() {
);
sysDefs[DIV_SYSTEM_YM2610_FULL_EXT]=new DivSysDef(
"Yamaha YM2610 Extended Channel 2", NULL, 0xa6, 0, 17, true, false, 0x151, false,
"Yamaha YM2610 (OPNB) Extended Channel 2", NULL, 0xa6, 0, 17, true, false, 0x151, false,
{"FM 1", "FM 2 OP1", "FM 2 OP2", "FM 2 OP3", "FM 2 OP4", "FM 3", "FM 4", "PSG 1", "PSG 2", "PSG 3", "ADPCM-A 1", "ADPCM-A 2", "ADPCM-A 3", "ADPCM-A 4", "ADPCM-A 5", "ADPCM-A 6", "ADPCM-B"},
{"F1", "O1", "O2", "O3", "O4", "F3", "F4", "S1", "S2", "S3", "P1", "P2", "P3", "P4", "P5", "P6", "B"},
{DIV_CH_FM, DIV_CH_OP, DIV_CH_OP, DIV_CH_OP, DIV_CH_OP, DIV_CH_FM, DIV_CH_FM, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM},
@ -1536,7 +1536,7 @@ void DivEngine::registerSystems() {
);
sysDefs[DIV_SYSTEM_OPLL_DRUMS]=new DivSysDef(
"Yamaha OPLL with drums", NULL, 0xa7, 0, 11, true, false, 0x150, false,
"Yamaha YM2413 (OPLL) with drums", NULL, 0xa7, 0, 11, true, false, 0x150, false,
{"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "Kick", "Snare", "Tom", "Top", "HiHat"},
{"F1", "F2", "F3", "F4", "F5", "F6", "BD", "SD", "TM", "TP", "HH"},
{DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE},
@ -1617,7 +1617,7 @@ void DivEngine::registerSystems() {
);
sysDefs[DIV_SYSTEM_YM2610B_EXT]=new DivSysDef(
"Yamaha YM2610B Extended Channel 3", NULL, 0xde, 0, 19, true, false, 0x151, false,
"Yamaha YM2610B (OPNB-B) Extended Channel 3", NULL, 0xde, 0, 19, true, false, 0x151, false,
{"FM 1", "FM 2", "FM 3 OP1", "FM 3 OP2", "FM 3 OP3", "FM 3 OP4", "FM 4", "FM 5", "FM 6", "PSG 1", "PSG 2", "PSG 3", "ADPCM-A 1", "ADPCM-A 2", "ADPCM-A 3", "ADPCM-A 4", "ADPCM-A 5", "ADPCM-A 6", "ADPCM-B"},
{"F1", "F2", "O1", "O2", "O3", "O4", "F4", "F5", "F6", "S1", "S2", "S3", "P1", "P2", "P3", "P4", "P5", "P6", "B"},
{DIV_CH_FM, DIV_CH_FM, DIV_CH_OP, DIV_CH_OP, DIV_CH_OP, DIV_CH_OP, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM},