Merge branches 'master' and 'nmk112' of https://github.com/tildearrow/furnace into nmk112

This commit is contained in:
cam900 2023-11-04 18:53:30 +09:00
commit 7cf40f2d33
13 changed files with 1207 additions and 42 deletions

View file

@ -809,6 +809,7 @@ src/gui/tutorial.cpp
src/gui/util.cpp src/gui/util.cpp
src/gui/waveEdit.cpp src/gui/waveEdit.cpp
src/gui/volMeter.cpp src/gui/volMeter.cpp
src/gui/xyOsc.cpp
src/gui/gui.cpp src/gui/gui.cpp
) )

View file

@ -154,16 +154,16 @@ ex | FM | OPM | OPZ | OPLL | AY-3-8910 | AY8930 | Lynx
W | | LFO Shape | LFO Shape | Patch | Waveform | Waveform | | Waveform | W | | LFO Shape | LFO Shape | Patch | Waveform | Waveform | | Waveform |
1 | | AMD | AMD | | | Duty | | FilterMode | 1 | | AMD | AMD | | | Duty | | FilterMode |
2 | | PMD | PMD | | Envelope | Envelope | | Resonance | 2 | | PMD | PMD | | Envelope | Envelope | | Resonance |
3 | LFOSpd | LFO Speed | LFO Speed | | AutoEnvNum | AutoEnvNum | | Special | 3 | LFOSpd | LFO Speed | LFO Speed | | AutoEnvNum | AutoEnvNum | | |
A | ALG | ALG | ALG | | AutoEnvDen | AutoEnvDen | | | A | ALG | ALG | ALG | | AutoEnvDen | AutoEnvDen | | Cutoff |
B | FB | FB | FB | | | Noise AND | | | B | FB | FB | FB | | | Noise AND | | |
C | FMS | FMS | FMS | | | Noise OR | | | C | FMS | FMS | FMS | | | Noise OR | | |
D | AMS | AMS | AMS | | | | | | D | AMS | AMS | AMS | | | | | |
4 | OpMask | OpMask | | | | | | Test/Gate | 4 | OpMask | OpMask | | | | | | Special |
5 | | | AMD2 | | | | | | 5 | | | AMD2 | | | | | Attack |
6 | | | PMD2 | | | | | | 6 | | | PMD2 | | | | | Decay |
7 | | | LFO2Speed | | | | | | 7 | | | LFO2Speed | | | | | Sustain |
8 | | | LFO2Shape | | | | | | 8 | | | LFO2Shape | | | | | Release |
ex | SAA1099 | X1-010 | Namco 163 | FDS | Sound Unit | ES5506 | MSM6258 | ex | SAA1099 | X1-010 | Namco 163 | FDS | Sound Unit | ES5506 | MSM6258 |
---|----------|------------|------------|-----------|------------|-----------|----------| ---|----------|------------|------------|-----------|------------|-----------|----------|

View file

@ -5,15 +5,14 @@ the C64 instrument editor consists of two tabs: "C64" to control various paramet
## C64 ## C64
- **Waveform**: allows selecting a waveform. - **Waveform**: allows selecting a waveform.
- more than one waveform can be selected at once. in that case logical AND mix of waves will occur. - more than one waveform can be selected at once. in that case a logical AND mix of waves will occur...
- due to hardware flaws, the mixing is a bit weird and sounds different between the 6581 and the 8580.
- noise is an exception. it cannot be used with any of the other waveforms. - noise is an exception. it cannot be used with any of the other waveforms.
- **Attack**: determines the rising time for the sound. the bigger the value, the slower the attack. (0 to 15). - **Attack**: determines the rising time for the sound. the bigger the value, the slower the attack. (0 to 15).
- **Decay**: determines the diminishing time for the sound. the higher the value, the longer the decay (0 to 15). - **Decay**: determines the diminishing time for the sound. the higher the value, the longer the decay (0 to 15).
- **Sustain**: sets the volume level at which the sound stops decaying and holds steady (0 to 15). - **Sustain**: sets the volume level at which the sound stops decaying and holds steady (0 to 15).
- **Release**: determines the rate at which the sound fades out after note off. the higher the value, the longer the release (0 to 15). - **Release**: determines the rate at which the sound fades out after note off. the higher the value, the longer the release (0 to 15).
- **Duty**: specifies the width of a pulse wave (0 to 4095). - **Duty**: specifies the width of a pulse wave (0 to 4095).
- **Ring Modulation**: when enabled, the channel's output will be multiplied with the previous channel's. - **Ring Modulation**: when enabled, the channel's output will be multiplied with the previous channel's.
- **Oscillator Sync**: enables oscillator hard sync. as the previous channel's oscillator finishes a cycle, it resets the period of the channel's oscillator, forcing the latter to have the same base frequency. this can produce a harmonically rich sound, the timbre of which can be altered by varying the synchronized oscillator's frequency. - **Oscillator Sync**: enables oscillator hard sync. as the previous channel's oscillator finishes a cycle, it resets the period of the channel's oscillator, forcing the latter to have the same base frequency. this can produce a harmonically rich sound, the timbre of which can be altered by varying the synchronized oscillator's frequency.
@ -25,10 +24,9 @@ the C64 instrument editor consists of two tabs: "C64" to control various paramet
- **low**: a low-pass filter. the lower the cutoff, the darker the sound. - **low**: a low-pass filter. the lower the cutoff, the darker the sound.
- **high**: a high-pass filter. higher cutoff values result in a less "bassy" sound. - **high**: a high-pass filter. higher cutoff values result in a less "bassy" sound.
- **band**: a band-pass filter. cutoff determines which part of the sound is heard (from bass to treble). - **band**: a band-pass filter. cutoff determines which part of the sound is heard (from bass to treble).
- **ch3off**: mutes channel 3 when enabled. not sure why is this part of the chip's design, but it is. - **ch3off**: mutes channel 3 when enabled. it was originally planned for usage with two registers where program could read current oscillator and envelope outputs, thus making vibrato and SFX generation easier. but who wanted to sacrifice one channel out of three! so aforementioned was just done in software, and the feature was never used.
- multiple filter modes can be selected simultaneously. for example, selecting both "low" and "high" results in a bandstop (notch) filter.
- **Volume Macro is Cutoff Macro**: turns the volume macro in the Macros tab into a filter cutoff macro.
- volume control is global (affects entire chip output), hence the option.
- **Absolute Cutoff Macro**: when enabled, the cutoff macro will go from 0 to 2047, and it will be absolute (in other words, control the cutoff directly rather than being relative). - **Absolute Cutoff Macro**: when enabled, the cutoff macro will go from 0 to 2047, and it will be absolute (in other words, control the cutoff directly rather than being relative).
- **Absolute Duty Macro**: when enabled, the duty macro will go from 0 to 4095. - **Absolute Duty Macro**: when enabled, the duty macro will go from 0 to 4095.
- **Don't test before new note**: this option disables the one-tick hard reset and test bit before a new note. - **Don't test before new note**: this option disables the one-tick hard reset and test bit before a new note.
@ -37,12 +35,26 @@ the C64 instrument editor consists of two tabs: "C64" to control various paramet
- **Volume**: volume sequence. - **Volume**: volume sequence.
- warning: volume sequence is global! this means it controls the chip's volume and therefore affects all channels. - warning: volume sequence is global! this means it controls the chip's volume and therefore affects all channels.
- this macro becomes **Cutoff** when the **Volume Macro is Cutoff Macro** option is enabled in the C64 tab.
- **Arpeggio**: pitch sequence. - **Arpeggio**: pitch sequence.
- **Duty**: pulse width sequence. - **Duty**: pulse width sequence.
- **Waveform**: select the waveform used by instrument. - **Waveform**: select the waveform used by instrument.
- **Pitch**: fine pitch. - **Pitch**: fine pitch.
- **Cutoff**: filter cutoff.
- **Filter mode**: select the filter mode. - **Filter mode**: select the filter mode.
- **Resonance**: filter resonance sequence. - **Resonance**: filter resonance sequence.
- **Special**: ring and oscillator sync selector. - **Special**: ring and oscillator sync selector, as well as:
- **Test/Gate**: when on, the test bit is set, which mutes the channel. - **gate bit**:
- set (1): key on. if previous state was 0 it triggers envelope start/restart; if previous state was 1, it does nothing.
- reset (0): key off. if previous state was 1 it triggers envelope release; if previous state was 0, it does nothing.
- **test bit**:
- set (1): immediately mute channel
- if the channel is a source of ring mod and/or hard sync, those stop working until the bit is reset.
- reset (0): unmute channel and restore ring mod/hard sync.
- **Attack**: sets envelope attack speed.
- if you modify attack speed when the envelope is in attack phase it immediately changes.
- **Decay**: sets envelope decay speed.
- if you modify decay speed when envelope is in decay phase it immediately changes.
- **Sustain**: sets envelope sustain level.
- if you modify sustain level when envelope is in sustain phase it immediately changes, although you can only go down. for example, 9-to-8 and 8-to-8 both work, but 8-to-9 immediately mutes the channel.
- **Release**: sets envelope release speed.
- if you modify release speed when envelope is in release phase it immediately changes.

View file

@ -30,7 +30,7 @@
template<typename T> struct SharedChannel { template<typename T> struct SharedChannel {
int freq, baseFreq, baseNoteOverride, pitch, pitch2, arpOff; int freq, baseFreq, baseNoteOverride, pitch, pitch2, arpOff;
int ins, note; int ins, note;
bool active, insChanged, freqChanged, fixedArp, keyOn, keyOff, portaPause, inPorta, volChanged; bool active, insChanged, freqChanged, fixedArp, keyOn, keyOff, portaPause, inPorta;
T vol, outVol; T vol, outVol;
DivMacroInt std; DivMacroInt std;
void handleArp(int offset=0) { void handleArp(int offset=0) {
@ -79,7 +79,6 @@ template<typename T> struct SharedChannel {
keyOff(false), keyOff(false),
portaPause(false), portaPause(false),
inPorta(false), inPorta(false),
volChanged(false),
vol(initVol), vol(initVol),
outVol(initVol), outVol(initVol),
std() {} std() {}

View file

@ -191,22 +191,22 @@ void DivPlatformES5506::tick(bool sysTick) {
const int nextVol=VOL_SCALE_LOG((0xfff*chan[i].vol)/0xff,(0xfff*chan[i].std.vol.val)/chan[i].volMacroMax,0xfff); const int nextVol=VOL_SCALE_LOG((0xfff*chan[i].vol)/0xff,(0xfff*chan[i].std.vol.val)/chan[i].volMacroMax,0xfff);
if (chan[i].outVol!=nextVol) { if (chan[i].outVol!=nextVol) {
chan[i].outVol=nextVol; chan[i].outVol=nextVol;
chan[i].volChangedES.lVol=1; chan[i].volChanged.lVol=1;
chan[i].volChangedES.rVol=1; chan[i].volChanged.rVol=1;
} }
} }
if (chan[i].std.panL.had) { if (chan[i].std.panL.had) {
const int nextLVol=VOL_SCALE_LOG((0xfff*chan[i].lVol)/0xff,(0xfff*chan[i].std.panL.val)/chan[i].panMacroMax,0xfff); const int nextLVol=VOL_SCALE_LOG((0xfff*chan[i].lVol)/0xff,(0xfff*chan[i].std.panL.val)/chan[i].panMacroMax,0xfff);
if (chan[i].outLVol!=nextLVol) { if (chan[i].outLVol!=nextLVol) {
chan[i].outLVol=nextLVol; chan[i].outLVol=nextLVol;
chan[i].volChangedES.lVol=1; chan[i].volChanged.lVol=1;
} }
} }
if (chan[i].std.panR.had) { if (chan[i].std.panR.had) {
const int nextRVol=VOL_SCALE_LOG((0xfff*chan[i].rVol)/0xff,(0xfff*chan[i].std.panR.val)/chan[i].panMacroMax,0xfff); const int nextRVol=VOL_SCALE_LOG((0xfff*chan[i].rVol)/0xff,(0xfff*chan[i].std.panR.val)/chan[i].panMacroMax,0xfff);
if (chan[i].outRVol!=nextRVol) { if (chan[i].outRVol!=nextRVol) {
chan[i].outRVol=nextRVol; chan[i].outRVol=nextRVol;
chan[i].volChangedES.rVol=1; chan[i].volChanged.rVol=1;
} }
} }
// arpeggio/pitch macros, frequency related // arpeggio/pitch macros, frequency related
@ -340,7 +340,7 @@ void DivPlatformES5506::tick(bool sysTick) {
if (chan[i].ca!=ca) { if (chan[i].ca!=ca) {
chan[i].ca=ca; chan[i].ca=ca;
if (!chan[i].keyOn) { if (!chan[i].keyOn) {
chan[i].volChangedES.ca=1; chan[i].volChanged.ca=1;
} }
} }
} }
@ -360,9 +360,9 @@ void DivPlatformES5506::tick(bool sysTick) {
} }
} }
// update registers // update registers
if (chan[i].volChangedES.changed) { if (chan[i].volChanged.changed) {
// calculate volume (16 bit) // calculate volume (16 bit)
if (chan[i].volChangedES.lVol) { if (chan[i].volChanged.lVol) {
chan[i].resLVol=VOL_SCALE_LOG(chan[i].outVol,chan[i].outLVol,0xfff); chan[i].resLVol=VOL_SCALE_LOG(chan[i].outVol,chan[i].outLVol,0xfff);
chan[i].resLVol-=volScale; chan[i].resLVol-=volScale;
if (chan[i].resLVol<0) chan[i].resLVol=0; if (chan[i].resLVol<0) chan[i].resLVol=0;
@ -371,7 +371,7 @@ void DivPlatformES5506::tick(bool sysTick) {
pageWrite(0x00|i,0x02,chan[i].resLVol); pageWrite(0x00|i,0x02,chan[i].resLVol);
} }
} }
if (chan[i].volChangedES.rVol) { if (chan[i].volChanged.rVol) {
chan[i].resRVol=VOL_SCALE_LOG(chan[i].outVol,chan[i].outRVol,0xfff); chan[i].resRVol=VOL_SCALE_LOG(chan[i].outVol,chan[i].outRVol,0xfff);
chan[i].resRVol-=volScale; chan[i].resRVol-=volScale;
if (chan[i].resRVol<0) chan[i].resRVol=0; if (chan[i].resRVol<0) chan[i].resRVol=0;
@ -380,10 +380,10 @@ void DivPlatformES5506::tick(bool sysTick) {
pageWrite(0x00|i,0x04,chan[i].resRVol); pageWrite(0x00|i,0x04,chan[i].resRVol);
} }
} }
if (chan[i].volChangedES.ca) { if (chan[i].volChanged.ca) {
pageWriteMask(0x00|i,0x5f,0x00,(chan[i].ca<<10),0x1c00); pageWriteMask(0x00|i,0x5f,0x00,(chan[i].ca<<10),0x1c00);
} }
chan[i].volChangedES.changed=0; chan[i].volChanged.changed=0;
} }
if (chan[i].pcmChanged.changed) { if (chan[i].pcmChanged.changed) {
if (chan[i].pcmChanged.index) { if (chan[i].pcmChanged.index) {
@ -750,7 +750,7 @@ int DivPlatformES5506::dispatch(DivCommand c) {
chan[c.chan].freqChanged=true; chan[c.chan].freqChanged=true;
chan[c.chan].pcmChanged.changed=0xff; chan[c.chan].pcmChanged.changed=0xff;
chan[c.chan].noteChanged.changed=0xff; chan[c.chan].noteChanged.changed=0xff;
chan[c.chan].volChangedES.changed=0xff; chan[c.chan].volChanged.changed=0xff;
} }
if (!chan[c.chan].std.vol.will) { if (!chan[c.chan].std.vol.will) {
chan[c.chan].outVol=(0xfff*chan[c.chan].vol)/0xff; chan[c.chan].outVol=(0xfff*chan[c.chan].vol)/0xff;
@ -787,7 +787,7 @@ int DivPlatformES5506::dispatch(DivCommand c) {
chan[c.chan].vol=c.value; chan[c.chan].vol=c.value;
if (!chan[c.chan].std.vol.has) { if (!chan[c.chan].std.vol.has) {
chan[c.chan].outVol=(0xfff*c.value)/0xff; chan[c.chan].outVol=(0xfff*c.value)/0xff;
chan[c.chan].volChangedES.changed=0xff; chan[c.chan].volChanged.changed=0xff;
} }
} }
break; break;
@ -797,14 +797,14 @@ int DivPlatformES5506::dispatch(DivCommand c) {
case DIV_CMD_PANNING: { case DIV_CMD_PANNING: {
if (chan[c.chan].ca!=0) { if (chan[c.chan].ca!=0) {
chan[c.chan].ca=0; chan[c.chan].ca=0;
chan[c.chan].volChangedES.ca=1; chan[c.chan].volChanged.ca=1;
} }
// Left volume // Left volume
if (chan[c.chan].lVol!=c.value) { if (chan[c.chan].lVol!=c.value) {
chan[c.chan].lVol=c.value; chan[c.chan].lVol=c.value;
if (!chan[c.chan].std.panL.has) { if (!chan[c.chan].std.panL.has) {
chan[c.chan].outLVol=(0xfff*c.value)/0xff; chan[c.chan].outLVol=(0xfff*c.value)/0xff;
chan[c.chan].volChangedES.lVol=1; chan[c.chan].volChanged.lVol=1;
} }
} }
// Right volume // Right volume
@ -812,7 +812,7 @@ int DivPlatformES5506::dispatch(DivCommand c) {
chan[c.chan].rVol=c.value2; chan[c.chan].rVol=c.value2;
if (!chan[c.chan].std.panR.has) { if (!chan[c.chan].std.panR.has) {
chan[c.chan].outRVol=(0xfff*c.value2)/0xff; chan[c.chan].outRVol=(0xfff*c.value2)/0xff;
chan[c.chan].volChangedES.rVol=1; chan[c.chan].volChanged.rVol=1;
} }
} }
break; break;
@ -821,7 +821,7 @@ int DivPlatformES5506::dispatch(DivCommand c) {
unsigned char ca=CLAMP(c.value>>1,0,5); unsigned char ca=CLAMP(c.value>>1,0,5);
if (chan[c.chan].ca!=ca) { if (chan[c.chan].ca!=ca) {
chan[c.chan].ca=ca; chan[c.chan].ca=ca;
chan[c.chan].volChangedES.ca=1; chan[c.chan].volChanged.ca=1;
} }
if ((c.value&1)==0) { if ((c.value&1)==0) {
// Left volume // Left volume
@ -829,7 +829,7 @@ int DivPlatformES5506::dispatch(DivCommand c) {
chan[c.chan].lVol=c.value2; chan[c.chan].lVol=c.value2;
if (!chan[c.chan].std.panL.has) { if (!chan[c.chan].std.panL.has) {
chan[c.chan].outLVol=(0xfff*c.value2)/0xff; chan[c.chan].outLVol=(0xfff*c.value2)/0xff;
chan[c.chan].volChangedES.lVol=1; chan[c.chan].volChanged.lVol=1;
} }
} }
} }
@ -839,7 +839,7 @@ int DivPlatformES5506::dispatch(DivCommand c) {
chan[c.chan].rVol=c.value2; chan[c.chan].rVol=c.value2;
if (!chan[c.chan].std.panR.has) { if (!chan[c.chan].std.panR.has) {
chan[c.chan].outRVol=(0xfff*c.value2)/0xff; chan[c.chan].outRVol=(0xfff*c.value2)/0xff;
chan[c.chan].volChangedES.rVol=1; chan[c.chan].volChanged.rVol=1;
} }
} }
} }
@ -1041,7 +1041,7 @@ void DivPlatformES5506::forceIns() {
chan[i].insChanged=true; chan[i].insChanged=true;
chan[i].freqChanged=true; chan[i].freqChanged=true;
chan[i].noteChanged.changed=0xff; chan[i].noteChanged.changed=0xff;
chan[i].volChangedES.changed=0xff; chan[i].volChanged.changed=0xff;
chan[i].filterChanged.changed=0xff; chan[i].filterChanged.changed=0xff;
chan[i].envChanged.changed=0xff; chan[i].envChanged.changed=0xff;
chan[i].pcmChanged.changed=0xff; chan[i].pcmChanged.changed=0xff;

View file

@ -97,7 +97,7 @@ class DivPlatformES5506: public DivDispatch, public es550x_intf {
VolChanged() : VolChanged() :
changed(0) {} changed(0) {}
} volChangedES; } volChanged;
struct FilterChanged { // Filter changed flags struct FilterChanged { // Filter changed flags
union { // pack flag bits in single byte union { // pack flag bits in single byte
@ -198,7 +198,7 @@ class DivPlatformES5506: public DivDispatch, public es550x_intf {
isReverseLoop(false), isReverseLoop(false),
cr(0), cr(0),
noteChanged(NoteChanged()), noteChanged(NoteChanged()),
volChangedES(VolChanged()), volChanged(VolChanged()),
filterChanged(FilterChanged()), filterChanged(FilterChanged()),
envChanged(EnvChanged()), envChanged(EnvChanged()),
pcmChanged(PCMChanged()), pcmChanged(PCMChanged()),

View file

@ -238,8 +238,863 @@
ImGui::TextColored(ch->mask?colorOn:colorOff,">> Mask"); ImGui::TextColored(ch->mask?colorOn:colorOff,">> Mask");
void putDispatchChip(void* data, int type) { void putDispatchChip(void* data, int type) {
ImGui::Text("I will finish later..."); ImVec4 colorOn=ImVec4(1.0f,1.0f,0.0f,1.0f);
ImVec4 colorOff=ImVec4(0.3f,0.3f,0.3f,1.0f);
switch (type) {
case DIV_SYSTEM_YM2612:
case DIV_SYSTEM_YM2612_EXT:
case DIV_SYSTEM_YM2612_DUALPCM:
case DIV_SYSTEM_YM2612_DUALPCM_EXT: {
GENESIS_CHIP_DEBUG;
break;
}
case DIV_SYSTEM_GENESIS:
case DIV_SYSTEM_GENESIS_EXT: {
GENESIS_CHIP_DEBUG;
SMS_CHIP_DEBUG;
break;
}
case DIV_SYSTEM_SMS: {
SMS_CHIP_DEBUG;
break;
}
case DIV_SYSTEM_YM2203:
case DIV_SYSTEM_YM2203_EXT: {
DivPlatformYM2203* ch=(DivPlatformYM2203*)data;
ImGui::Text("> YM2203");
FM_OPN_CHIP_DEBUG;
ImGui::Text("- sampleBank: %d",ch->sampleBank);
ImGui::Text("- prescale: %d",ch->prescale);
FM_OPN_CHIP_DEBUG_BOOL;
ImGui::TextColored(ch->extMode?colorOn:colorOff,">> ExtMode");
break;
}
case DIV_SYSTEM_YM2608:
case DIV_SYSTEM_YM2608_EXT: {
DivPlatformYM2608* ch=(DivPlatformYM2608*)data;
ImGui::Text("> YM2608");
FM_OPN_CHIP_DEBUG;
ImGui::Text("- sampleBank: %d",ch->sampleBank);
ImGui::Text("- writeRSSOff: %d",ch->writeRSSOff);
ImGui::Text("- writeRSSOn: %d",ch->writeRSSOn);
ImGui::Text("- globalRSSVolume: %d",ch->globalRSSVolume);
ImGui::Text("- prescale: %d",ch->prescale);
FM_OPN_CHIP_DEBUG_BOOL;
ImGui::TextColored(ch->extMode?colorOn:colorOff,">> ExtMode");
break;
}
case DIV_SYSTEM_YM2610:
case DIV_SYSTEM_YM2610_EXT:
case DIV_SYSTEM_YM2610_FULL:
case DIV_SYSTEM_YM2610_FULL_EXT: {
DivPlatformYM2610* ch=(DivPlatformYM2610*)data;
ImGui::Text("> YM2610");
OPNB_CHIP_DEBUG;
break;
}
case DIV_SYSTEM_YM2610B:
case DIV_SYSTEM_YM2610B_EXT: {
DivPlatformYM2610B* ch=(DivPlatformYM2610B*)data;
ImGui::Text("> YM2610B");
OPNB_CHIP_DEBUG;
break;
}
case DIV_SYSTEM_GB: {
DivPlatformGB* ch=(DivPlatformGB*)data;
ImGui::Text("> GameBoy");
COMMON_CHIP_DEBUG;
ImGui::Text("- lastPan: %d",ch->lastPan);
ImGui::Text("- antiClickPeriodCount: %d",ch->antiClickPeriodCount);
ImGui::Text("- antiClickWavePos: %d",ch->antiClickWavePos);
COMMON_CHIP_DEBUG_BOOL;
ImGui::TextColored(ch->antiClickEnabled?colorOn:colorOff,">> AntiClickEnabled");
break;
}
case DIV_SYSTEM_PCE: {
DivPlatformPCE* ch=(DivPlatformPCE*)data;
ImGui::Text("> PCEngine");
COMMON_CHIP_DEBUG;
ImGui::Text("- lastPan: %d",ch->lastPan);
ImGui::Text("- cycles: %d",ch->cycles);
ImGui::Text("- curChan: %d",ch->curChan);
ImGui::Text("- delay: %d",ch->delay);
ImGui::Text("- sampleBank: %d",ch->sampleBank);
ImGui::Text("- lfoMode: %d",ch->lfoMode);
ImGui::Text("- lfoSpeed: %d",ch->lfoSpeed);
COMMON_CHIP_DEBUG_BOOL;
ImGui::TextColored(ch->antiClickEnabled?colorOn:colorOff,">> AntiClickEnabled");
break;
}
case DIV_SYSTEM_NES: {
DivPlatformNES* ch=(DivPlatformNES*)data;
ImGui::Text("> NES");
COMMON_CHIP_DEBUG;
ImGui::Text("* DAC:");
ImGui::Text(" - Period: %d",ch->dacPeriod);
ImGui::Text(" - Rate: %d",ch->dacRate);
ImGui::Text(" - Pos: %d",ch->dacPos);
ImGui::Text(" - AntiClick: %d",ch->dacAntiClick);
ImGui::Text(" - Sample: %d",ch->dacSample);
ImGui::Text("- dpcmBank: %d",ch->dpcmBank);
ImGui::Text("- sampleBank: %d",ch->sampleBank);
ImGui::Text("- writeOscBuf: %d",ch->writeOscBuf);
ImGui::Text("- apuType: %d",ch->apuType);
COMMON_CHIP_DEBUG_BOOL;
ImGui::TextColored(ch->dpcmMode?colorOn:colorOff,">> DPCMMode");
ImGui::TextColored(ch->dacAntiClickOn?colorOn:colorOff,">> DACAntiClickOn");
ImGui::TextColored(ch->useNP?colorOn:colorOff,">> UseNP");
ImGui::TextColored(ch->goingToLoop?colorOn:colorOff,">> GoingToLoop");
break;
}
case DIV_SYSTEM_C64_6581: case DIV_SYSTEM_C64_8580: {
DivPlatformC64* ch=(DivPlatformC64*)data;
ImGui::Text("> C64");
COMMON_CHIP_DEBUG;
ImGui::Text("- filtControl: %d",ch->filtControl);
ImGui::Text("- filtRes: %d",ch->filtRes);
ImGui::Text("- vol: %d",ch->vol);
ImGui::Text("- writeOscBuf: %d",ch->writeOscBuf);
ImGui::Text("- filtCut: %d",ch->filtCut);
ImGui::Text("- resetTime: %d",ch->resetTime);
COMMON_CHIP_DEBUG_BOOL;
break;
}
case DIV_SYSTEM_ARCADE:
case DIV_SYSTEM_YM2151: {
DivPlatformArcade* ch=(DivPlatformArcade*)data;
ImGui::Text("> YM2151");
FM_CHIP_DEBUG;
ImGui::Text("- baseFreqOff: %d",ch->baseFreqOff);
ImGui::Text("- amDepth: %d",ch->amDepth);
ImGui::Text("- pmDepth: %d",ch->pmDepth);
FM_CHIP_DEBUG_BOOL;
ImGui::TextColored(ch->useYMFM?colorOn:colorOff,">> UseYMFM");
break;
}
case DIV_SYSTEM_SEGAPCM:
case DIV_SYSTEM_SEGAPCM_COMPAT: {
DivPlatformSegaPCM* ch=(DivPlatformSegaPCM*)data;
ImGui::Text("> SegaPCM");
COMMON_CHIP_DEBUG;
ImGui::Text("- delay: %d",ch->delay);
ImGui::Text("- pcmL: %d",ch->pcmL);
ImGui::Text("- pcmR: %d",ch->pcmR);
ImGui::Text("- pcmCycles: %d",ch->pcmCycles);
ImGui::Text("- sampleBank: %d",ch->sampleBank);
COMMON_CHIP_DEBUG_BOOL;
break;
}
case DIV_SYSTEM_AY8910: {
DivPlatformAY8910* ch=(DivPlatformAY8910*)data;
ImGui::Text("> AY-3-8910");
COMMON_CHIP_DEBUG;
ImGui::Text("- sampleBank: %d",ch->sampleBank);
ImGui::Text("- stereoSep: %d",ch->stereoSep);
ImGui::Text("- delay: %d",ch->delay);
ImGui::Text("- extClock: %d",ch->extClock);
ImGui::Text("- extDiv: %d",ch->extDiv);
ImGui::Text("- portAVal: %d",ch->portAVal);
ImGui::Text("- portBVal: %d",ch->portBVal);
ImGui::Text("* envelope:");
ImGui::Text(" - mode: %d",ch->ayEnvMode);
ImGui::Text(" - period: %d",ch->ayEnvPeriod);
ImGui::Text(" * slide: %d",ch->ayEnvSlide);
ImGui::Text(" - slideLow: %d",ch->ayEnvSlideLow);
COMMON_CHIP_DEBUG_BOOL;
ImGui::TextColored(ch->extMode?colorOn:colorOff,">> ExtMode");
ImGui::TextColored(ch->stereo?colorOn:colorOff,">> Stereo");
ImGui::TextColored(ch->sunsoft?colorOn:colorOff,">> Sunsoft");
ImGui::TextColored(ch->intellivision?colorOn:colorOff,">> Intellivision");
ImGui::TextColored(ch->clockSel?colorOn:colorOff,">> ClockSel");
ImGui::TextColored(ch->ioPortA?colorOn:colorOff,">> IoPortA");
ImGui::TextColored(ch->ioPortB?colorOn:colorOff,">> IoPortB");
break;
}
case DIV_SYSTEM_AY8930: {
DivPlatformAY8930* ch=(DivPlatformAY8930*)data;
ImGui::Text("> AY8930");
COMMON_CHIP_DEBUG;
ImGui::Text("* noise:");
ImGui::Text(" - and: %d",ch->ayNoiseAnd);
ImGui::Text(" - or: %d",ch->ayNoiseOr);
ImGui::Text("- sampleBank: %d",ch->sampleBank);
ImGui::Text("- stereoSep: %d",ch->stereoSep);
ImGui::Text("- delay: %d",ch->delay);
ImGui::Text("- portAVal: %d",ch->portAVal);
ImGui::Text("- portBVal: %d",ch->portBVal);
COMMON_CHIP_DEBUG_BOOL;
ImGui::TextColored(ch->bank?colorOn:colorOff,">> Bank");
ImGui::TextColored(ch->extMode?colorOn:colorOff,">> ExtMode");
ImGui::TextColored(ch->stereo?colorOn:colorOff,">> Stereo");
ImGui::TextColored(ch->clockSel?colorOn:colorOff,">> ClockSel");
ImGui::TextColored(ch->ioPortA?colorOn:colorOff,">> IoPortA");
ImGui::TextColored(ch->ioPortB?colorOn:colorOff,">> IoPortB");
break;
}
case DIV_SYSTEM_QSOUND: {
DivPlatformQSound* ch=(DivPlatformQSound*)data;
ImGui::Text("> QSound");
COMMON_CHIP_DEBUG;
ImGui::Text("* echo:");
ImGui::Text(" - delay: %d",ch->echoDelay);
ImGui::Text(" - feedback: %d",ch->echoFeedback);
COMMON_CHIP_DEBUG_BOOL;
break;
}
case DIV_SYSTEM_X1_010: {
DivPlatformX1_010* ch=(DivPlatformX1_010*)data;
ImGui::Text("> X1-010");
COMMON_CHIP_DEBUG;
ImGui::Text("- sampleBank: %d",ch->sampleBank);
ImGui::Text("- bankSlot: [%d,%d,%d,%d,%d,%d,%d,%d]",ch->bankSlot[0],ch->bankSlot[1],ch->bankSlot[2],ch->bankSlot[3],ch->bankSlot[4],ch->bankSlot[5],ch->bankSlot[6],ch->bankSlot[7]);
COMMON_CHIP_DEBUG_BOOL;
ImGui::TextColored(ch->stereo?colorOn:colorOff,">> Stereo");
ImGui::TextColored(ch->isBanked?colorOn:colorOff,">> IsBanked");
break;
}
case DIV_SYSTEM_N163: {
DivPlatformN163* ch=(DivPlatformN163*)data;
ImGui::Text("> N163");
COMMON_CHIP_DEBUG;
ImGui::Text("- initChanMax: %d",ch->initChanMax);
ImGui::Text("- chanMax: %d",ch->chanMax);
ImGui::Text("- loadWave: %d",ch->loadWave);
ImGui::Text("- loadPos: %d",ch->loadPos);
COMMON_CHIP_DEBUG_BOOL;
ImGui::TextColored(ch->multiplex?colorOn:colorOff,">> Multiplex");
break;
}
case DIV_SYSTEM_VRC6: {
DivPlatformVRC6* ch=(DivPlatformVRC6*)data;
ImGui::Text("> VRC6");
COMMON_CHIP_DEBUG;
ImGui::Text("- sampleBank: %.2x",ch->sampleBank);
ImGui::Text("- writeOscBuf: %.2x",ch->writeOscBuf);
COMMON_CHIP_DEBUG_BOOL;
break;
}
case DIV_SYSTEM_LYNX: {
DivPlatformLynx* ch=(DivPlatformLynx*)data;
ImGui::Text("> Lynx");
COMMON_CHIP_DEBUG;
COMMON_CHIP_DEBUG_BOOL;
break;
}
case DIV_SYSTEM_PCM_DAC: {
DivPlatformPCMDAC* ch=(DivPlatformPCMDAC*)data;
ImGui::Text("> PCM DAC");
COMMON_CHIP_DEBUG;
ImGui::Text("- outDepth: %d",ch->outDepth);
COMMON_CHIP_DEBUG_BOOL;
ImGui::TextColored(ch->outStereo?colorOn:colorOff,">> OutStereo");
break;
}
case DIV_SYSTEM_ES5506: {
DivPlatformES5506* ch=(DivPlatformES5506*)data;
ImGui::Text("> ES5506");
COMMON_CHIP_DEBUG;
ImGui::Text("- cycle: %d",ch->cycle);
ImGui::Text("- curPage: %d",ch->curPage);
ImGui::Text("- volScale: %d",ch->volScale);
ImGui::Text("- maskedVal: %.2x",ch->maskedVal);
ImGui::Text("- irqv: %.2x",ch->irqv);
ImGui::Text("- curCR: %.8x",ch->curCR);
ImGui::Text("- initChanMax: %d",ch->initChanMax);
ImGui::Text("- chanMax: %d",ch->chanMax);
COMMON_CHIP_DEBUG_BOOL;
ImGui::TextColored(ch->isMasked?colorOn:colorOff,">> IsMasked");
ImGui::TextColored(ch->isReaded?colorOn:colorOff,">> isReaded");
ImGui::TextColored(ch->irqTrigger?colorOn:colorOff,">> IrqTrigger");
break;
}
case DIV_SYSTEM_K007232: {
DivPlatformK007232* ch=(DivPlatformK007232*)data;
ImGui::Text("> K007232");
COMMON_CHIP_DEBUG;
ImGui::Text("- delay: %.2x",ch->delay);
ImGui::Text("- lastLoop: %.2x",ch->lastLoop);
ImGui::Text("- lastVolume: %.2x",ch->lastVolume);
COMMON_CHIP_DEBUG_BOOL;
ImGui::TextColored(ch->stereo?colorOn:colorOff,">> Stereo");
break;
}
case DIV_SYSTEM_GA20: {
DivPlatformGA20* ch=(DivPlatformGA20*)data;
ImGui::Text("> GA20");
COMMON_CHIP_DEBUG;
ImGui::Text("- delay: %.2x",ch->delay);
COMMON_CHIP_DEBUG_BOOL;
break;
}
case DIV_SYSTEM_SM8521: {
DivPlatformSM8521* ch=(DivPlatformSM8521*)data;
ImGui::Text("> SM8521");
COMMON_CHIP_DEBUG;
COMMON_CHIP_DEBUG_BOOL;
ImGui::TextColored(ch->antiClickEnabled?colorOn:colorOff,">> AntiClickEnabled");
break;
}
case DIV_SYSTEM_PV1000: {
DivPlatformPV1000* ch=(DivPlatformPV1000*)data;
ImGui::Text("> PV1000");
COMMON_CHIP_DEBUG;
COMMON_CHIP_DEBUG_BOOL;
break;
}
case DIV_SYSTEM_K053260: {
DivPlatformK053260* ch=(DivPlatformK053260*)data;
ImGui::Text("> K053260");
COMMON_CHIP_DEBUG;
COMMON_CHIP_DEBUG_BOOL;
break;
}
case DIV_SYSTEM_C140: {
DivPlatformC140* ch=(DivPlatformC140*)data;
ImGui::Text("> C140");
COMMON_CHIP_DEBUG;
COMMON_CHIP_DEBUG_BOOL;
break;
}
default:
ImGui::Text("Unimplemented chip! Help!");
break;
}
} }
void putDispatchChan(void* data, int chanNum, int type) { void putDispatchChan(void* data, int chanNum, int type) {
ImGui::Text("I will finish later..."); ImVec4 colorOn=ImVec4(1.0f,1.0f,0.0f,1.0f);
ImVec4 colorOff=ImVec4(0.3f,0.3f,0.3f,1.0f);
switch (type) {
case DIV_SYSTEM_GENESIS: {
if (chanNum>5) {
SMS_CHAN_DEBUG;
} else {
GENESIS_CHAN_DEBUG;
}
break;
}
case DIV_SYSTEM_GENESIS_EXT: {
if (chanNum>8) {
SMS_CHAN_DEBUG;
} else if (chanNum>=2 && chanNum<=5) {
DivPlatformOPN::OPNOpChannelStereo* ch=(DivPlatformOPN::OPNOpChannelStereo*)data;
ImGui::Text("> YM2612 (per operator)");
OPNB_OPCHAN_DEBUG;
} else {
GENESIS_CHAN_DEBUG;
}
break;
}
case DIV_SYSTEM_YM2612:
case DIV_SYSTEM_YM2612_DUALPCM: {
GENESIS_CHAN_DEBUG;
break;
}
case DIV_SYSTEM_YM2612_EXT:
case DIV_SYSTEM_YM2612_DUALPCM_EXT: {
if (chanNum>=2 && chanNum<=5) {
DivPlatformOPN::OPNOpChannelStereo* ch=(DivPlatformOPN::OPNOpChannelStereo*)data;
ImGui::Text("> YM2612 (per operator)");
OPNB_OPCHAN_DEBUG;
} else {
GENESIS_CHAN_DEBUG;
}
break;
}
case DIV_SYSTEM_SMS: {
SMS_CHAN_DEBUG;
break;
}
case DIV_SYSTEM_YM2203: {
OPN_CHAN_DEBUG;
break;
}
case DIV_SYSTEM_YM2203_EXT: {
if (chanNum>=2 && chanNum<=5) {
OPN_OPCHAN_DEBUG;
} else {
OPN_CHAN_DEBUG;
}
break;
}
case DIV_SYSTEM_YM2608: {
DivPlatformOPN::OPNChannelStereo* ch=(DivPlatformOPN::OPNChannelStereo*)data;
ImGui::Text("> YM2608");
OPNB_CHAN_DEBUG;
break;
}
case DIV_SYSTEM_YM2608_EXT: {
if (chanNum>=2 && chanNum<=5) {
DivPlatformOPN::OPNOpChannelStereo* ch=(DivPlatformOPN::OPNOpChannelStereo*)data;
ImGui::Text("> YM2608 (per operator)");
OPNB_OPCHAN_DEBUG;
} else {
DivPlatformOPN::OPNChannelStereo* ch=(DivPlatformOPN::OPNChannelStereo*)data;
ImGui::Text("> YM2608");
OPNB_CHAN_DEBUG;
}
break;
}
case DIV_SYSTEM_YM2610:
case DIV_SYSTEM_YM2610_FULL: {
DivPlatformOPN::OPNChannelStereo* ch=(DivPlatformOPN::OPNChannelStereo*)data;
ImGui::Text("> YM2610");
OPNB_CHAN_DEBUG;
break;
}
case DIV_SYSTEM_YM2610B: {
DivPlatformOPN::OPNChannelStereo* ch=(DivPlatformOPN::OPNChannelStereo*)data;
ImGui::Text("> YM2610B");
OPNB_CHAN_DEBUG;
break;
}
case DIV_SYSTEM_YM2610_EXT:
case DIV_SYSTEM_YM2610_FULL_EXT: {
if (chanNum>=1 && chanNum<=4) {
DivPlatformOPN::OPNOpChannelStereo* ch=(DivPlatformOPN::OPNOpChannelStereo*)data;
ImGui::Text("> YM2610 (per operator)");
OPNB_OPCHAN_DEBUG;
} else {
DivPlatformOPN::OPNChannelStereo* ch=(DivPlatformOPN::OPNChannelStereo*)data;
ImGui::Text("> YM2610");
OPNB_CHAN_DEBUG;
}
break;
}
case DIV_SYSTEM_YM2610B_EXT: {
if (chanNum>=2 && chanNum<=5) {
DivPlatformOPN::OPNOpChannelStereo* ch=(DivPlatformOPN::OPNOpChannelStereo*)data;
ImGui::Text("> YM2610B (per operator)");
OPNB_OPCHAN_DEBUG;
} else {
DivPlatformOPN::OPNChannelStereo* ch=(DivPlatformOPN::OPNChannelStereo*)data;
ImGui::Text("> YM2610B");
OPNB_CHAN_DEBUG;
}
break;
}
case DIV_SYSTEM_GB: {
DivPlatformGB::Channel* ch=(DivPlatformGB::Channel*)data;
ImGui::Text("> GameBoy");
COMMON_CHAN_DEBUG;
ImGui::Text("- duty: %d",ch->duty);
ImGui::Text("- sweep: %.2x",ch->sweep);
ImGui::Text("- wave: %d",ch->wave);
COMMON_CHAN_DEBUG_BOOL;
ImGui::TextColored(ch->sweepChanged?colorOn:colorOff,">> SweepChanged");
break;
}
case DIV_SYSTEM_PCE: {
DivPlatformPCE::Channel* ch=(DivPlatformPCE::Channel*)data;
ImGui::Text("> PCEngine");
COMMON_CHAN_DEBUG;
ImGui::Text("* DAC:");
ImGui::Text(" - period: %d",ch->dacPeriod);
ImGui::Text(" - rate: %d",ch->dacRate);
ImGui::Text(" - pos: %d",ch->dacPos);
ImGui::Text(" - out: %d",ch->dacOut);
ImGui::Text(" - sample: %d",ch->dacSample);
ImGui::Text("- pan: %.2x",ch->pan);
ImGui::Text("- wave: %d",ch->wave);
ImGui::Text("- macroVolMul: %d",ch->macroVolMul);
COMMON_CHAN_DEBUG_BOOL;
ImGui::TextColored(ch->noise?colorOn:colorOff,">> Noise");
ImGui::TextColored(ch->pcm?colorOn:colorOff,">> DAC");
ImGui::TextColored(ch->furnaceDac?colorOn:colorOff,">> FurnaceDAC");
break;
}
case DIV_SYSTEM_NES: {
DivPlatformNES::Channel* ch=(DivPlatformNES::Channel*)data;
ImGui::Text("> NES");
COMMON_CHAN_DEBUG;
ImGui::Text(" - prev: %d",ch->prevFreq);
ImGui::Text("- duty: %d",ch->duty);
ImGui::Text("- sweep: %.2x",ch->sweep);
COMMON_CHAN_DEBUG_BOOL;
ImGui::TextColored(ch->sweepChanged?colorOn:colorOff,">> SweepChanged");
ImGui::TextColored(ch->furnaceDac?colorOn:colorOff,">> FurnaceDAC");
break;
}
case DIV_SYSTEM_C64_6581: case DIV_SYSTEM_C64_8580: {
DivPlatformC64::Channel* ch=(DivPlatformC64::Channel*)data;
ImGui::Text("> C64");
COMMON_CHAN_DEBUG;
ImGui::Text("- prevFreq: %d",ch->prevFreq);
ImGui::Text("- testWhen: %d",ch->testWhen);
ImGui::Text("- duty: %d",ch->duty);
ImGui::Text("- sweep: %.2x",ch->sweep);
ImGui::Text("- wave: %.1x",ch->wave);
ImGui::Text("- ADSR: %.1x %.1x %.1x %.1x",ch->attack,ch->decay,ch->sustain,ch->release);
COMMON_CHAN_DEBUG_BOOL;
ImGui::TextColored(ch->sweepChanged?colorOn:colorOff,">> SweepChanged");
ImGui::TextColored(ch->filter?colorOn:colorOff,">> Filter");
ImGui::TextColored(ch->resetMask?colorOn:colorOff,">> ResetMask");
ImGui::TextColored(ch->resetFilter?colorOn:colorOff,">> ResetFilter");
ImGui::TextColored(ch->resetDuty?colorOn:colorOff,">> ResetDuty");
ImGui::TextColored(ch->ring?colorOn:colorOff,">> Ring");
ImGui::TextColored(ch->sync?colorOn:colorOff,">> Sync");
break;
}
case DIV_SYSTEM_ARCADE:
case DIV_SYSTEM_YM2151: {
DivPlatformArcade::Channel* ch=(DivPlatformArcade::Channel*)data;
ImGui::Text("> YM2151");
ImGui::Text("- freqHL: %.2x%.2x",ch->freqH,ch->freqL);
COMMON_CHAN_DEBUG;
ImGui::Text("- KOnCycles: %d",ch->konCycles);
ImGui::Text("- chVolL: %.2x",ch->chVolL);
ImGui::Text("- chVolR: %.2x",ch->chVolR);
COMMON_CHAN_DEBUG_BOOL;
break;
}
case DIV_SYSTEM_SEGAPCM:
case DIV_SYSTEM_SEGAPCM_COMPAT: {
DivPlatformSegaPCM::Channel* ch=(DivPlatformSegaPCM::Channel*)data;
ImGui::Text("> SegaPCM");
COMMON_CHAN_DEBUG;
ImGui::Text("* PCM:");
ImGui::Text(" - sample: %d",ch->pcm.sample);
ImGui::Text(" - pos: %d",ch->pcm.pos);
ImGui::Text(" - len: %d",ch->pcm.len);
ImGui::Text(" - freq: %d",ch->pcm.freq);
ImGui::Text("- chVolL: %.2x",ch->chVolL);
ImGui::Text("- chVolR: %.2x",ch->chVolR);
ImGui::Text("- chPanL: %.2x",ch->chPanL);
ImGui::Text("- chPanR: %.2x",ch->chPanR);
ImGui::Text("- macroVolMul: %.2x",ch->macroVolMul);
COMMON_CHAN_DEBUG_BOOL;
ImGui::TextColored(ch->furnacePCM?colorOn:colorOff,">> FurnacePCM");
ImGui::TextColored(ch->isNewSegaPCM?colorOn:colorOff,">> IsNewSegaPCM");
break;
}
case DIV_SYSTEM_AY8910: {
DivPlatformAY8910::Channel* ch=(DivPlatformAY8910::Channel*)data;
ImGui::Text("> AY-3-8910");
COMMON_CHAN_DEBUG;
ImGui::Text("* DAC:");
ImGui::Text(" - sample: %d",ch->dac.sample);
ImGui::Text(" - rate: %d",ch->dac.rate);
ImGui::Text(" - period: %d",ch->dac.period);
ImGui::Text(" - pos: %d",ch->dac.pos);
ImGui::Text(" - out: %d",ch->dac.out);
ImGui::Text("- autoEnvNum: %.2x",ch->autoEnvNum);
ImGui::Text("- autoEnvDen: %.2x",ch->autoEnvDen);
COMMON_CHAN_DEBUG_BOOL;
ImGui::TextColored(ch->dac.furnaceDAC?colorOn:colorOff,">> furnaceDAC");
break;
}
case DIV_SYSTEM_AY8930: {
DivPlatformAY8930::Channel* ch=(DivPlatformAY8930::Channel*)data;
ImGui::Text("> AY8930");
COMMON_CHAN_DEBUG;
ImGui::Text("- duty: %d",ch->duty);
ImGui::Text("* DAC:");
ImGui::Text(" - sample: %d",ch->dac.sample);
ImGui::Text(" - rate: %d",ch->dac.rate);
ImGui::Text(" - period: %d",ch->dac.period);
ImGui::Text(" - pos: %d",ch->dac.pos);
ImGui::Text(" - out: %d",ch->dac.out);
ImGui::Text("- autoEnvNum: %.2x",ch->autoEnvNum);
ImGui::Text("- autoEnvDen: %.2x",ch->autoEnvDen);
COMMON_CHAN_DEBUG_BOOL;
ImGui::TextColored(ch->dac.furnaceDAC?colorOn:colorOff,">> furnaceDAC");
break;
}
case DIV_SYSTEM_QSOUND: {
DivPlatformQSound::Channel* ch=(DivPlatformQSound::Channel*)data;
ImGui::Text("> QSound");
COMMON_CHAN_DEBUG;
ImGui::Text("- sample: %d",ch->sample);
ImGui::Text("- echo: %d",ch->echo);
ImGui::Text("- panning: %d",ch->panning);
ImGui::Text("- resVol: %.2x",ch->resVol);
COMMON_CHAN_DEBUG_BOOL;
ImGui::TextColored(ch->useWave?colorOn:colorOff,">> UseWave");
ImGui::TextColored(ch->surround?colorOn:colorOff,">> Surround");
ImGui::TextColored(ch->isNewQSound?colorOn:colorOff,">> IsNewQSound");
break;
}
case DIV_SYSTEM_X1_010: {
DivPlatformX1_010::Channel* ch=(DivPlatformX1_010::Channel*)data;
ImGui::Text("> X1-010");
COMMON_CHAN_DEBUG;
ImGui::Text("- wave: %d",ch->wave);
ImGui::Text("- sample: %d",ch->sample);
ImGui::Text("- pan: %d",ch->pan);
ImGui::Text("* envelope:");
ImGui::Text(" - shape: %d",ch->env.shape);
ImGui::Text(" - period: %.2x",ch->env.period);
ImGui::Text(" - slide: %.2x",ch->env.slide);
ImGui::Text(" - slidefrac: %.2x",ch->env.slidefrac);
ImGui::Text(" - autoEnvNum: %.2x",ch->autoEnvNum);
ImGui::Text(" - autoEnvDen: %.2x",ch->autoEnvDen);
ImGui::Text("- WaveBank: %d",ch->waveBank);
ImGui::Text("- bankSlot: %d",ch->bankSlot);
ImGui::Text("- Lvol: %.2x",ch->lvol);
ImGui::Text("- Rvol: %.2x",ch->rvol);
COMMON_CHAN_DEBUG_BOOL;
ImGui::TextColored(ch->envChanged?colorOn:colorOff,">> EnvChanged");
ImGui::TextColored(ch->furnacePCM?colorOn:colorOff,">> FurnacePCM");
ImGui::TextColored(ch->pcm?colorOn:colorOff,">> PCM");
ImGui::TextColored(ch->env.flag.envEnable?colorOn:colorOff,">> EnvEnable");
ImGui::TextColored(ch->env.flag.envOneshot?colorOn:colorOff,">> EnvOneshot");
ImGui::TextColored(ch->env.flag.envSplit?colorOn:colorOff,">> EnvSplit");
ImGui::TextColored(ch->env.flag.envHinvR?colorOn:colorOff,">> EnvHinvR");
ImGui::TextColored(ch->env.flag.envVinvR?colorOn:colorOff,">> EnvVinvR");
ImGui::TextColored(ch->env.flag.envHinvL?colorOn:colorOff,">> EnvHinvL");
ImGui::TextColored(ch->env.flag.envVinvL?colorOn:colorOff,">> EnvVinvL");
break;
}
case DIV_SYSTEM_N163: {
DivPlatformN163::Channel* ch=(DivPlatformN163::Channel*)data;
ImGui::Text("> N163");
COMMON_CHAN_DEBUG;
ImGui::Text("- wave: %d",ch->wave);
ImGui::Text("- wavepos: %d",ch->wavePos);
ImGui::Text("- wavelen: %d",ch->waveLen);
ImGui::Text("- wavemode: %d",ch->waveMode);
ImGui::Text("- resVol: %.2x",ch->resVol);
COMMON_CHAN_DEBUG_BOOL;
ImGui::TextColored(ch->volumeChanged?colorOn:colorOff,">> VolumeChanged");
ImGui::TextColored(ch->waveChanged?colorOn:colorOff,">> WaveChanged");
ImGui::TextColored(ch->waveUpdated?colorOn:colorOff,">> WaveUpdated");
break;
}
case DIV_SYSTEM_VRC6: {
DivPlatformVRC6::Channel* ch=(DivPlatformVRC6::Channel*)data;
ImGui::Text("> VRC6");
COMMON_CHAN_DEBUG;
ImGui::Text("* DAC:");
ImGui::Text(" - period: %d",ch->dacPeriod);
ImGui::Text(" - rate: %d",ch->dacRate);
ImGui::Text(" - out: %d",ch->dacOut);
ImGui::Text(" - pos: %d",ch->dacPos);
ImGui::Text(" - sample: %d",ch->dacSample);
ImGui::Text("- duty: %d",ch->duty);
COMMON_CHAN_DEBUG_BOOL;
ImGui::TextColored(ch->pcm?colorOn:colorOff,">> DAC");
ImGui::TextColored(ch->furnaceDac?colorOn:colorOff,">> FurnaceDAC");
break;
}
case DIV_SYSTEM_ES5506: {
DivPlatformES5506::Channel* ch=(DivPlatformES5506::Channel*)data;
ImGui::Text("> ES5506");
COMMON_CHAN_DEBUG;
ImGui::Text("- nextFreq: %d",ch->nextFreq);
ImGui::Text("- nextNote: %d",ch->nextNote);
ImGui::Text("- currNote: %d",ch->currNote);
ImGui::Text("- wave: %d",ch->wave);
ImGui::Text("- VolMacroMax: %d",ch->volMacroMax);
ImGui::Text("- PanMacroMax: %d",ch->panMacroMax);
ImGui::Text("* PCM:");
ImGui::Text(" * index: %d",ch->pcm.index);
ImGui::Text(" - next: %d",ch->pcm.next);
ImGui::Text(" - note: %d",ch->pcm.note);
ImGui::Text(" * freqOffs: %.6f",ch->pcm.freqOffs);
ImGui::Text(" - next: %.6f",ch->pcm.nextFreqOffs);
ImGui::Text(" - bank: %.2x",ch->pcm.bank);
ImGui::Text(" - start: %.8x",ch->pcm.start);
ImGui::Text(" - end: %.8x",ch->pcm.end);
ImGui::Text(" - length: %.8x",ch->pcm.length);
ImGui::Text(" - loopStart: %.8x",ch->pcm.loopStart);
ImGui::Text(" - loopEnd: %.8x",ch->pcm.loopEnd);
ImGui::Text(" - loopMode: %d",ch->pcm.loopMode);
ImGui::Text(" - nextPos: %d",ch->pcm.nextPos);
ImGui::Text("* Filter:");
ImGui::Text(" - Mode: %d",ch->filter.mode);
ImGui::Text(" - K1: %.4x",ch->filter.k1);
ImGui::Text(" - K2: %.4x",ch->filter.k2);
ImGui::Text("* Envelope:");
ImGui::Text(" - EnvCount: %.3x",ch->envelope.ecount);
ImGui::Text(" - LVRamp: %d",ch->envelope.lVRamp);
ImGui::Text(" - RVRamp: %d",ch->envelope.rVRamp);
ImGui::Text(" - K1Ramp: %d",ch->envelope.k1Ramp);
ImGui::Text(" - K2Ramp: %d",ch->envelope.k2Ramp);
ImGui::Text(" - K1Offs: %d",ch->k1Offs);
ImGui::Text(" - K2Offs: %d",ch->k2Offs);
ImGui::Text(" - K1Slide: %d",ch->k1Slide);
ImGui::Text(" - K2Slide: %d",ch->k2Slide);
ImGui::Text(" - K1Prev: %.4x",ch->k1Prev);
ImGui::Text(" - K2Prev: %.4x",ch->k2Prev);
ImGui::Text("* Overwrite:");
ImGui::Text(" * Filter:");
ImGui::Text(" - Mode: %d",ch->overwrite.filter.mode);
ImGui::Text(" - K1: %.4x",ch->overwrite.filter.k1);
ImGui::Text(" - K2: %.4x",ch->overwrite.filter.k2);
ImGui::Text(" * Envelope:");
ImGui::Text(" - EnvCount: %.3x",ch->overwrite.envelope.ecount);
ImGui::Text(" - LVRamp: %d",ch->overwrite.envelope.lVRamp);
ImGui::Text(" - RVRamp: %d",ch->overwrite.envelope.rVRamp);
ImGui::Text(" - K1Ramp: %d",ch->overwrite.envelope.k1Ramp);
ImGui::Text(" - K2Ramp: %d",ch->overwrite.envelope.k2Ramp);
ImGui::Text("- CA: %.2x",ch->ca);
ImGui::Text("- LVol: %.2x",ch->lVol);
ImGui::Text("- RVol: %.2x",ch->rVol);
ImGui::Text("- outLVol: %.2x",ch->outLVol);
ImGui::Text("- outRVol: %.2x",ch->outRVol);
ImGui::Text("- ResLVol: %.2x",ch->resLVol);
ImGui::Text("- ResRVol: %.2x",ch->resRVol);
ImGui::Text("- oscOut: %d",ch->oscOut);
COMMON_CHAN_DEBUG_BOOL;
ImGui::TextColored(ch->volChanged.lVol?colorOn:colorOff,">> LVolChanged");
ImGui::TextColored(ch->volChanged.rVol?colorOn:colorOff,">> RVolChanged");
ImGui::TextColored(ch->filterChanged.mode?colorOn:colorOff,">> FilterModeChanged");
ImGui::TextColored(ch->filterChanged.k1?colorOn:colorOff,">> FilterK1Changed");
ImGui::TextColored(ch->filterChanged.k2?colorOn:colorOff,">> FilterK2Changed");
ImGui::TextColored(ch->envChanged.ecount?colorOn:colorOff,">> EnvECountChanged");
ImGui::TextColored(ch->envChanged.lVRamp?colorOn:colorOff,">> EnvLVRampChanged");
ImGui::TextColored(ch->envChanged.rVRamp?colorOn:colorOff,">> EnvRVRampChanged");
ImGui::TextColored(ch->envChanged.k1Ramp?colorOn:colorOff,">> EnvK1RampChanged");
ImGui::TextColored(ch->envChanged.k2Ramp?colorOn:colorOff,">> EnvK2RampChanged");
ImGui::TextColored(ch->pcmChanged.index?colorOn:colorOff,">> PCMIndexChanged");
ImGui::TextColored(ch->pcmChanged.slice?colorOn:colorOff,">> PCMSliceChanged");
ImGui::TextColored(ch->pcmChanged.position?colorOn:colorOff,">> PCMPositionChanged");
ImGui::TextColored(ch->pcmChanged.loopBank?colorOn:colorOff,">> PCMLoopBankChanged");
ImGui::TextColored(ch->isReverseLoop?colorOn:colorOff,">> IsReverseLoop");
ImGui::TextColored(ch->pcm.isNoteMap?colorOn:colorOff,">> PCMIsNoteMap");
ImGui::TextColored(ch->pcm.pause?colorOn:colorOff,">> PCMPause");
ImGui::TextColored(ch->pcm.direction?colorOn:colorOff,">> PCMDirection");
ImGui::TextColored(ch->pcm.setPos?colorOn:colorOff,">> PCMSetPos");
ImGui::TextColored(ch->envelope.k1Slow?colorOn:colorOff,">> EnvK1Slow");
ImGui::TextColored(ch->envelope.k2Slow?colorOn:colorOff,">> EnvK2Slow");
ImGui::TextColored(ch->overwrite.envelope.k1Slow?colorOn:colorOff,">> EnvK1SlowOverwrite");
ImGui::TextColored(ch->overwrite.envelope.k2Slow?colorOn:colorOff,">> EnvK2SlowOverwrite");
ImGui::TextColored(ch->overwrite.state.mode?colorOn:colorOff,">> FilterModeOverwrited");
ImGui::TextColored(ch->overwrite.state.k1?colorOn:colorOff,">> FilterK1Overwrited");
ImGui::TextColored(ch->overwrite.state.k2?colorOn:colorOff,">> FilterK2Overwrited");
ImGui::TextColored(ch->overwrite.state.ecount?colorOn:colorOff,">> EnvECountOverwrited");
ImGui::TextColored(ch->overwrite.state.lVRamp?colorOn:colorOff,">> EnvLVRampOverwrited");
ImGui::TextColored(ch->overwrite.state.rVRamp?colorOn:colorOff,">> EnvRVRampOverwrited");
ImGui::TextColored(ch->overwrite.state.k1Ramp?colorOn:colorOff,">> EnvK1RampOverwrited");
ImGui::TextColored(ch->overwrite.state.k2Ramp?colorOn:colorOff,">> EnvK2RampOverwrited");
break;
}
case DIV_SYSTEM_LYNX: {
DivPlatformLynx::Channel* ch=(DivPlatformLynx::Channel*)data;
ImGui::Text("> Lynx");
COMMON_CHAN_DEBUG;
ImGui::Text("* FreqDiv:");
ImGui::Text(" - clockDivider: %d",ch->fd.clockDivider);
ImGui::Text(" - backup: %d",ch->fd.backup);
ImGui::Text("- actualNote: %d",ch->actualNote);
ImGui::Text("* Sample:");
ImGui::Text(" - sample: %d",ch->sample);
ImGui::Text(" - pos: %d",ch->samplePos);
ImGui::Text(" - accum: %d",ch->sampleAccum);
ImGui::Text(" * freq: %d",ch->sampleFreq);
ImGui::Text(" - base: %d",ch->sampleBaseFreq);
ImGui::Text("* duty:");
ImGui::Text(" - int_feedback7: %d",ch->duty.int_feedback7);
ImGui::Text(" - feedback: %d",ch->duty.feedback);
ImGui::Text("- pan: %.2x",ch->pan);
ImGui::Text("- macroVolMul: %.2x",ch->macroVolMul);
COMMON_CHAN_DEBUG_BOOL;
ImGui::TextColored(ch->pcm?colorOn:colorOff,">> DAC");
break;
}
case DIV_SYSTEM_PCM_DAC: {
DivPlatformPCMDAC::Channel* ch=(DivPlatformPCMDAC::Channel*)data;
ImGui::Text("> PCM DAC");
COMMON_CHAN_DEBUG;
ImGui::Text("* Sample: %d",ch->sample);
ImGui::Text(" - dir: %d",ch->audDir);
ImGui::Text(" - loc: %d",ch->audLoc);
ImGui::Text(" - len: %d",ch->audLen);
ImGui::Text(" * pos: %d",ch->audPos);
ImGui::Text(" - sub: %d",ch->audSub);
ImGui::Text("- wave: %d",ch->wave);
ImGui::Text("- panL: %.2x",ch->panL);
ImGui::Text("- panR: %.2x",ch->panR);
ImGui::Text("- envVol: %.2x",ch->envVol);
COMMON_CHAN_DEBUG_BOOL;
ImGui::TextColored(ch->useWave?colorOn:colorOff,">> UseWave");
ImGui::TextColored(ch->setPos?colorOn:colorOff,">> SetPos");
break;
}
case DIV_SYSTEM_K007232: {
DivPlatformK007232::Channel* ch=(DivPlatformK007232::Channel*)data;
ImGui::Text("> K007232");
COMMON_CHAN_DEBUG;
ImGui::Text("- prevFreq: %d",ch->prevFreq);
ImGui::Text("* Sample: %d",ch->sample);
ImGui::Text(" - pos: %d",ch->audPos);
ImGui::Text(" - prevBank: %d",ch->prevBank);
ImGui::Text("* panning: %d",ch->panning);
ImGui::Text(" - prev: %d",ch->prevPan);
ImGui::Text("- resVol: %.2x",ch->resVol);
ImGui::Text("- lvol: %.2x",ch->lvol);
ImGui::Text("- rvol: %.2x",ch->rvol);
ImGui::Text("- macroVolMul: %.2x",ch->macroVolMul);
COMMON_CHAN_DEBUG_BOOL;
ImGui::TextColored(ch->volumeChanged?colorOn:colorOff,">> VolumeChanged");
ImGui::TextColored(ch->setPos?colorOn:colorOff,">> SetPos");
break;
}
case DIV_SYSTEM_GA20: {
DivPlatformGA20::Channel* ch=(DivPlatformGA20::Channel*)data;
ImGui::Text("> GA20");
COMMON_CHAN_DEBUG;
ImGui::Text("- prevFreq: %d",ch->prevFreq);
ImGui::Text("* Sample: %d",ch->sample);
ImGui::Text(" - pos: %d",ch->audPos);
ImGui::Text("- resVol: %.2x",ch->resVol);
ImGui::Text("- macroVolMul: %.2x",ch->macroVolMul);
COMMON_CHAN_DEBUG_BOOL;
ImGui::TextColored(ch->volumeChanged?colorOn:colorOff,">> VolumeChanged");
ImGui::TextColored(ch->setPos?colorOn:colorOff,">> SetPos");
break;
}
case DIV_SYSTEM_SM8521: {
DivPlatformSM8521::Channel* ch=(DivPlatformSM8521::Channel*)data;
ImGui::Text("> SM8521");
COMMON_CHAN_DEBUG;
ImGui::Text("* AntiClick:");
ImGui::Text(" - periodCount: %d",ch->antiClickPeriodCount);
ImGui::Text(" - wavePos: %d",ch->antiClickWavePos);
ImGui::Text("- wave: %d",ch->wave);
COMMON_CHAN_DEBUG_BOOL;
ImGui::TextColored(ch->volumeChanged?colorOn:colorOff,">> VolumeChanged");
break;
}
case DIV_SYSTEM_PV1000: {
DivPlatformPV1000::Channel* ch=(DivPlatformPV1000::Channel*)data;
ImGui::Text("> PV1000");
COMMON_CHAN_DEBUG;
COMMON_CHAN_DEBUG_BOOL;
break;
}
case DIV_SYSTEM_K053260: {
DivPlatformK053260::Channel* ch=(DivPlatformK053260::Channel*)data;
ImGui::Text("> K053260");
COMMON_CHAN_DEBUG;
ImGui::Text("* Sample: %d",ch->sample);
ImGui::Text(" - pos: %d",ch->audPos);
ImGui::Text("- panning: %d",ch->panning);
ImGui::Text("- macroVolMul: %.2x",ch->macroVolMul);
COMMON_CHAN_DEBUG_BOOL;
ImGui::TextColored(ch->setPos?colorOn:colorOff,">> SetPos");
ImGui::TextColored(ch->reverse?colorOn:colorOff,">> Reverse");
break;
}
case DIV_SYSTEM_C140: {
DivPlatformC140::Channel* ch=(DivPlatformC140::Channel*)data;
ImGui::Text("> C140");
COMMON_CHAN_DEBUG;
ImGui::Text("* Sample: %d",ch->sample);
ImGui::Text(" - pos: %d",ch->audPos);
ImGui::Text("- chPanL: %.2x",ch->chPanL);
ImGui::Text("- chPanR: %.2x",ch->chPanR);
ImGui::Text("- chVolL: %.2x",ch->chVolL);
ImGui::Text("- chVolR: %.2x",ch->chVolR);
ImGui::Text("- macroVolMul: %.2x",ch->macroVolMul);
ImGui::Text("- macroPanMul: %.2x",ch->macroPanMul);
COMMON_CHAN_DEBUG_BOOL;
ImGui::TextColored(ch->volChangedL?colorOn:colorOff,">> VolChangedL");
ImGui::TextColored(ch->volChangedR?colorOn:colorOff,">> VolChangedR");
ImGui::TextColored(ch->setPos?colorOn:colorOff,">> SetPos");
break;
}
default:
ImGui::Text("Unimplemented chip! Help!");
break;
}
} }

View file

@ -279,6 +279,9 @@ void FurnaceGUI::doAction(int what) {
case GUI_ACTION_WINDOW_GROOVES: case GUI_ACTION_WINDOW_GROOVES:
nextWindow=GUI_WINDOW_GROOVES; nextWindow=GUI_WINDOW_GROOVES;
break; break;
case GUI_ACTION_WINDOW_XY_OSC:
nextWindow=GUI_WINDOW_XY_OSC;
break;
case GUI_ACTION_COLLAPSE_WINDOW: case GUI_ACTION_COLLAPSE_WINDOW:
collapseWindow=true; collapseWindow=true;
@ -375,6 +378,9 @@ void FurnaceGUI::doAction(int what) {
case GUI_WINDOW_GROOVES: case GUI_WINDOW_GROOVES:
groovesOpen=false; groovesOpen=false;
break; break;
case GUI_WINDOW_XY_OSC:
xyOscOpen=false;
break;
default: default:
break; break;
} }

View file

@ -591,6 +591,10 @@ void FurnaceGUI::drawMobileControls() {
if (ImGui::Button("Compat Flags")) { if (ImGui::Button("Compat Flags")) {
compatFlagsOpen=!compatFlagsOpen; compatFlagsOpen=!compatFlagsOpen;
} }
ImGui::SameLine();
if (ImGui::Button("XYOsc")) {
xyOscOpen=!xyOscOpen;
}
ImGui::Separator(); ImGui::Separator();

View file

@ -3430,6 +3430,7 @@ bool FurnaceGUI::loop() {
DECLARE_METRIC(readOsc) DECLARE_METRIC(readOsc)
DECLARE_METRIC(osc) DECLARE_METRIC(osc)
DECLARE_METRIC(chanOsc) DECLARE_METRIC(chanOsc)
DECLARE_METRIC(xyOsc)
DECLARE_METRIC(volMeter) DECLARE_METRIC(volMeter)
DECLARE_METRIC(settings) DECLARE_METRIC(settings)
DECLARE_METRIC(debug) DECLARE_METRIC(debug)
@ -4425,6 +4426,7 @@ bool FurnaceGUI::loop() {
if (ImGui::MenuItem("piano/input pad",BIND_FOR(GUI_ACTION_WINDOW_PIANO),pianoOpen)) pianoOpen=!pianoOpen; if (ImGui::MenuItem("piano/input pad",BIND_FOR(GUI_ACTION_WINDOW_PIANO),pianoOpen)) pianoOpen=!pianoOpen;
if (ImGui::MenuItem("oscilloscope (master)",BIND_FOR(GUI_ACTION_WINDOW_OSCILLOSCOPE),oscOpen)) oscOpen=!oscOpen; if (ImGui::MenuItem("oscilloscope (master)",BIND_FOR(GUI_ACTION_WINDOW_OSCILLOSCOPE),oscOpen)) oscOpen=!oscOpen;
if (ImGui::MenuItem("oscilloscope (per-channel)",BIND_FOR(GUI_ACTION_WINDOW_CHAN_OSC),chanOscOpen)) chanOscOpen=!chanOscOpen; if (ImGui::MenuItem("oscilloscope (per-channel)",BIND_FOR(GUI_ACTION_WINDOW_CHAN_OSC),chanOscOpen)) chanOscOpen=!chanOscOpen;
if (ImGui::MenuItem("oscilloscope (X-Y)",BIND_FOR(GUI_ACTION_WINDOW_XY_OSC),xyOscOpen)) xyOscOpen=!xyOscOpen;
if (ImGui::MenuItem("volume meter",BIND_FOR(GUI_ACTION_WINDOW_VOL_METER),volMeterOpen)) volMeterOpen=!volMeterOpen; if (ImGui::MenuItem("volume meter",BIND_FOR(GUI_ACTION_WINDOW_VOL_METER),volMeterOpen)) volMeterOpen=!volMeterOpen;
if (ImGui::MenuItem("clock",BIND_FOR(GUI_ACTION_WINDOW_CLOCK),clockOpen)) clockOpen=!clockOpen; if (ImGui::MenuItem("clock",BIND_FOR(GUI_ACTION_WINDOW_CLOCK),clockOpen)) clockOpen=!clockOpen;
if (ImGui::MenuItem("register view",BIND_FOR(GUI_ACTION_WINDOW_REGISTER_VIEW),regViewOpen)) regViewOpen=!regViewOpen; if (ImGui::MenuItem("register view",BIND_FOR(GUI_ACTION_WINDOW_REGISTER_VIEW),regViewOpen)) regViewOpen=!regViewOpen;
@ -4645,6 +4647,7 @@ bool FurnaceGUI::loop() {
MEASURE(readOsc,readOsc()); MEASURE(readOsc,readOsc());
MEASURE(osc,drawOsc()); MEASURE(osc,drawOsc());
MEASURE(chanOsc,drawChanOsc()); MEASURE(chanOsc,drawChanOsc());
MEASURE(xyOsc,drawXYOsc());
MEASURE(grooves,drawGrooves()); MEASURE(grooves,drawGrooves());
MEASURE(regView,drawRegView()); MEASURE(regView,drawRegView());
} else { } else {
@ -4674,6 +4677,7 @@ bool FurnaceGUI::loop() {
MEASURE(osc,drawOsc()); MEASURE(osc,drawOsc());
MEASURE(chanOsc,drawChanOsc()); MEASURE(chanOsc,drawChanOsc());
MEASURE(xyOsc,drawXYOsc());
MEASURE(volMeter,drawVolMeter()); MEASURE(volMeter,drawVolMeter());
MEASURE(settings,drawSettings()); MEASURE(settings,drawSettings());
MEASURE(debug,drawDebug()); MEASURE(debug,drawDebug());
@ -6413,6 +6417,7 @@ bool FurnaceGUI::init() {
mixerOpen=e->getConfBool("mixerOpen",false); mixerOpen=e->getConfBool("mixerOpen",false);
oscOpen=e->getConfBool("oscOpen",true); oscOpen=e->getConfBool("oscOpen",true);
chanOscOpen=e->getConfBool("chanOscOpen",false); chanOscOpen=e->getConfBool("chanOscOpen",false);
xyOscOpen=e->getConfBool("xyOscOpen",false);
volMeterOpen=e->getConfBool("volMeterOpen",true); volMeterOpen=e->getConfBool("volMeterOpen",true);
statsOpen=e->getConfBool("statsOpen",false); statsOpen=e->getConfBool("statsOpen",false);
compatFlagsOpen=e->getConfBool("compatFlagsOpen",false); compatFlagsOpen=e->getConfBool("compatFlagsOpen",false);
@ -6521,6 +6526,16 @@ bool FurnaceGUI::init() {
chanOscGrad.fromString(e->getConfString("chanOscGrad","")); chanOscGrad.fromString(e->getConfString("chanOscGrad",""));
chanOscGrad.render(); chanOscGrad.render();
xyOscXChannel=e->getConfInt("xyOscXChannel",0);
xyOscXInvert=e->getConfBool("xyOscXInvert",false);
xyOscYChannel=e->getConfInt("xyOscYChannel",1);
xyOscYInvert=e->getConfBool("xyOscYInvert",false);
xyOscZoom=e->getConfFloat("xyOscZoom",1.0f);
xyOscSamples=e->getConfInt("xyOscSamples",32768);
xyOscDecayTime=e->getConfFloat("xyOscDecayTime",10.0f);
xyOscIntensity=e->getConfFloat("xyOscIntensity",2.0f);
xyOscThickness=e->getConfFloat("xyOscThickness",2.0f);
syncSettings(); syncSettings();
syncTutorial(); syncTutorial();
@ -6968,6 +6983,7 @@ void FurnaceGUI::commitState() {
e->setConf("mixerOpen",mixerOpen); e->setConf("mixerOpen",mixerOpen);
e->setConf("oscOpen",oscOpen); e->setConf("oscOpen",oscOpen);
e->setConf("chanOscOpen",chanOscOpen); e->setConf("chanOscOpen",chanOscOpen);
e->setConf("xyOscOpen",xyOscOpen);
e->setConf("volMeterOpen",volMeterOpen); e->setConf("volMeterOpen",volMeterOpen);
e->setConf("statsOpen",statsOpen); e->setConf("statsOpen",statsOpen);
e->setConf("compatFlagsOpen",compatFlagsOpen); e->setConf("compatFlagsOpen",compatFlagsOpen);
@ -7062,6 +7078,17 @@ void FurnaceGUI::commitState() {
e->setConf("chanOscUseGrad",chanOscUseGrad); e->setConf("chanOscUseGrad",chanOscUseGrad);
e->setConf("chanOscGrad",chanOscGrad.toString()); e->setConf("chanOscGrad",chanOscGrad.toString());
// commit x-y osc state
e->setConf("xyOscXChannel",xyOscXChannel);
e->setConf("xyOscXInvert",xyOscXInvert);
e->setConf("xyOscYChannel",xyOscYChannel);
e->setConf("xyOscYInvert",xyOscYInvert);
e->setConf("xyOscZoom",xyOscZoom);
e->setConf("xyOscSamples",xyOscSamples);
e->setConf("xyOscDecayTime",xyOscDecayTime);
e->setConf("xyOscIntensity",xyOscIntensity);
e->setConf("xyOscThickness",xyOscThickness);
// commit recent files // commit recent files
for (int i=0; i<30; i++) { for (int i=0; i<30; i++) {
String key=fmt::sprintf("recentFile%d",i); String key=fmt::sprintf("recentFile%d",i);
@ -7301,6 +7328,7 @@ FurnaceGUI::FurnaceGUI():
clockOpen(false), clockOpen(false),
speedOpen(true), speedOpen(true),
groovesOpen(false), groovesOpen(false),
xyOscOpen(false),
basicMode(true), basicMode(true),
shortIntro(false), shortIntro(false),
insListDir(false), insListDir(false),
@ -7541,6 +7569,17 @@ FurnaceGUI::FurnaceGUI():
chanOscGrad(64,64), chanOscGrad(64,64),
chanOscGradTex(NULL), chanOscGradTex(NULL),
chanOscWorkPool(NULL), chanOscWorkPool(NULL),
xyOscPointTex(NULL),
xyOscOptions(false),
xyOscXChannel(0),
xyOscXInvert(false),
xyOscYChannel(1),
xyOscYInvert(false),
xyOscZoom(1.0f),
xyOscSamples(32768),
xyOscDecayTime(10.0f),
xyOscIntensity(2.0f),
xyOscThickness(2.0f),
followLog(true), followLog(true),
#ifdef IS_MOBILE #ifdef IS_MOBILE
pianoOctaves(7), pianoOctaves(7),

View file

@ -419,6 +419,7 @@ enum FurnaceGUIWindows {
GUI_WINDOW_FIND, GUI_WINDOW_FIND,
GUI_WINDOW_CLOCK, GUI_WINDOW_CLOCK,
GUI_WINDOW_GROOVES, GUI_WINDOW_GROOVES,
GUI_WINDOW_XY_OSC,
GUI_WINDOW_INTRO_MON, GUI_WINDOW_INTRO_MON,
GUI_WINDOW_SPOILER GUI_WINDOW_SPOILER
}; };
@ -572,6 +573,7 @@ enum FurnaceGUIActions {
GUI_ACTION_WINDOW_FIND, GUI_ACTION_WINDOW_FIND,
GUI_ACTION_WINDOW_CLOCK, GUI_ACTION_WINDOW_CLOCK,
GUI_ACTION_WINDOW_GROOVES, GUI_ACTION_WINDOW_GROOVES,
GUI_ACTION_WINDOW_XY_OSC,
GUI_ACTION_COLLAPSE_WINDOW, GUI_ACTION_COLLAPSE_WINDOW,
GUI_ACTION_CLOSE_WINDOW, GUI_ACTION_CLOSE_WINDOW,
@ -1873,7 +1875,7 @@ class FurnaceGUI {
bool mixerOpen, debugOpen, inspectorOpen, oscOpen, volMeterOpen, statsOpen, compatFlagsOpen; bool mixerOpen, debugOpen, inspectorOpen, oscOpen, volMeterOpen, statsOpen, compatFlagsOpen;
bool pianoOpen, notesOpen, channelsOpen, regViewOpen, logOpen, effectListOpen, chanOscOpen; bool pianoOpen, notesOpen, channelsOpen, regViewOpen, logOpen, effectListOpen, chanOscOpen;
bool subSongsOpen, findOpen, spoilerOpen, patManagerOpen, sysManagerOpen, clockOpen, speedOpen; bool subSongsOpen, findOpen, spoilerOpen, patManagerOpen, sysManagerOpen, clockOpen, speedOpen;
bool groovesOpen; bool groovesOpen, xyOscOpen;
bool basicMode, shortIntro; bool basicMode, shortIntro;
bool insListDir, waveListDir, sampleListDir; bool insListDir, waveListDir, sampleListDir;
@ -2167,6 +2169,19 @@ class FurnaceGUI {
planI(NULL) {} planI(NULL) {}
} chanOscChan[DIV_MAX_CHANS]; } chanOscChan[DIV_MAX_CHANS];
// x-y oscilloscope
FurnaceGUITexture* xyOscPointTex;
bool xyOscOptions;
int xyOscXChannel;
bool xyOscXInvert;
int xyOscYChannel;
bool xyOscYInvert;
float xyOscZoom;
int xyOscSamples;
float xyOscDecayTime;
float xyOscIntensity;
float xyOscThickness;
// visualizer // visualizer
float keyHit[DIV_MAX_CHANS]; float keyHit[DIV_MAX_CHANS];
float keyHit1[DIV_MAX_CHANS]; float keyHit1[DIV_MAX_CHANS];
@ -2357,6 +2372,7 @@ class FurnaceGUI {
void drawSpoiler(); void drawSpoiler();
void drawClock(); void drawClock();
void drawTutorial(); void drawTutorial();
void drawXYOsc();
void parseKeybinds(); void parseKeybinds();
void promptKey(int which); void promptKey(int which);

View file

@ -594,6 +594,7 @@ const FurnaceGUIActionDef guiActions[GUI_ACTION_MAX]={
D("WINDOW_FIND", "Find/Replace", FURKMOD_CMD|SDLK_f), D("WINDOW_FIND", "Find/Replace", FURKMOD_CMD|SDLK_f),
D("WINDOW_CLOCK", "Clock", 0), D("WINDOW_CLOCK", "Clock", 0),
D("WINDOW_GROOVES", "Grooves", 0), D("WINDOW_GROOVES", "Grooves", 0),
D("WINDOW_XY_OSC", "Oscilloscope (X-Y)", 0),
D("COLLAPSE_WINDOW", "Collapse/expand current window", 0), D("COLLAPSE_WINDOW", "Collapse/expand current window", 0),
D("CLOSE_WINDOW", "Close current window", FURKMOD_SHIFT|SDLK_ESCAPE), D("CLOSE_WINDOW", "Close current window", FURKMOD_SHIFT|SDLK_ESCAPE),

232
src/gui/xyOsc.cpp Normal file
View file

@ -0,0 +1,232 @@
/**
* Furnace Tracker - multi-system chiptune tracker
* Copyright (C) 2021-2023 tildearrow and contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "gui.h"
#include "imgui_internal.h"
#include <imgui.h>
#include "../ta-log.h"
#include "../engine/filter.h"
void FurnaceGUI::drawXYOsc() {
if (nextWindow==GUI_WINDOW_XY_OSC) {
xyOscOpen=true;
ImGui::SetNextWindowFocus();
nextWindow=GUI_WINDOW_NOTHING;
}
if (!xyOscOpen) return;
ImGui::SetNextWindowSizeConstraints(ImVec2(64.0f*dpiScale,32.0f*dpiScale),ImVec2(canvasW,canvasH));
bool noPadding=settings.oscTakesEntireWindow && !xyOscOptions;
if (noPadding) {
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding,ImVec2(0,0));
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing,ImVec2(0,0));
ImGui::PushStyleVar(ImGuiStyleVar_ItemInnerSpacing,ImVec2(0,0));
}
if (ImGui::Begin("Oscilloscope (X-Y)",&xyOscOpen,globalWinFlags)) {
if (xyOscOptions) {
int xyOscXChannelP1 = xyOscXChannel+1;
int xyOscYChannelP1 = xyOscYChannel+1;
ImGui::Text("X Channel");
ImGui::SameLine();
if (ImGui::DragInt("##XChannel",&xyOscXChannelP1,1.0f,1,DIV_MAX_OUTPUTS)) {
xyOscXChannel=MIN(MAX(xyOscXChannelP1,1),DIV_MAX_OUTPUTS)-1;
} rightClickable
ImGui::SameLine();
ImGui::Checkbox("Invert##X",&xyOscXInvert);
ImGui::Text("Y Channel");
ImGui::SameLine();
if (ImGui::DragInt("##YChannel",&xyOscYChannelP1,1.0f,1,DIV_MAX_OUTPUTS)) {
xyOscXChannel=MIN(MAX(xyOscYChannelP1,1),DIV_MAX_OUTPUTS)-1;
} rightClickable
ImGui::SameLine();
ImGui::Checkbox("Invert##Y",&xyOscYInvert);
if (ImGui::SliderFloat("Zoom",&xyOscZoom,0.5f,4.0f,"%.2fx")) {
xyOscZoom=MAX(xyOscZoom,0.0f);
} rightClickable
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("%.1fdB",20.0f*log10f(xyOscZoom));
}
if (ImGui::IsItemClicked(ImGuiMouseButton_Middle)) {
xyOscZoom=1.0f;
}
if (ImGui::SliderInt("Samples",&xyOscSamples,2,32768)) {
xyOscSamples=MIN(MAX(xyOscSamples,2),32768);
} rightClickable
if (ImGui::SliderFloat("Decay Time (ms)",&xyOscDecayTime,1.0f,1000.0f,"%.1f",ImGuiSliderFlags_Logarithmic)) {
xyOscDecayTime=MAX(xyOscDecayTime,0.0f);
} rightClickable
if (ImGui::SliderFloat("Intensity",&xyOscIntensity,0.0f,5.0f,"%.2f")) {
xyOscIntensity=MAX(xyOscIntensity,0.0f);
} rightClickable
if (ImGui::SliderFloat("Line Thickness",&xyOscThickness,0.0f,10.0f,"%.2f")) {
xyOscThickness=MAX(xyOscThickness,0.0f);
} rightClickable
if (ImGui::Button("OK")) {
xyOscOptions=false;
}
} else {
ImDrawList* dl=ImGui::GetWindowDrawList();
ImGuiWindow* window=ImGui::GetCurrentWindow();
ImVec2 size=ImGui::GetContentRegionAvail();
ImVec2 minArea=window->DC.CursorPos;
ImVec2 maxArea=ImVec2(
minArea.x+size.x,
minArea.y+size.y
);
ImRect rect=ImRect(minArea,maxArea);
ImRect inRect=rect;
inRect.Min.x+=dpiScale;
inRect.Min.y+=dpiScale;
inRect.Max.x-=dpiScale;
inRect.Max.y-=dpiScale;
ImVec2 inSqrCenter=rect.GetCenter();
float inSqrLength;
ImRect inSqr=inRect;
if (rect.GetWidth() > rect.GetHeight()) {
inSqrLength=inSqr.GetHeight()/2;
inSqr.Min.x=inSqrCenter.x-inSqrLength;
inSqr.Max.x=inSqrCenter.x+inSqrLength;
} else {
inSqrLength=inSqr.GetWidth()/2;
inSqr.Min.y=inSqrCenter.y-inSqrLength;
inSqr.Max.y=inSqrCenter.y+inSqrLength;
}
float scaleX=xyOscZoom*inSqrLength*(xyOscXInvert?-1:1);
float scaleY=xyOscZoom*inSqrLength*(xyOscYInvert?1:-1);
const ImGuiStyle& style=ImGui::GetStyle();
ImU32 color=ImGui::GetColorU32(uiColors[GUI_COLOR_OSC_WAVE]);
color&=~IM_COL32_A_MASK;
ImU32 borderColor=ImGui::GetColorU32(uiColors[GUI_COLOR_OSC_BORDER]);
ImU32 refColor=ImGui::GetColorU32(uiColors[GUI_COLOR_OSC_REF]);
ImU32 guideColor=ImGui::GetColorU32(uiColors[GUI_COLOR_OSC_GUIDE]);
ImGui::ItemSize(size,style.FramePadding.y);
if (ImGui::ItemAdd(rect,ImGui::GetID("wsDisplay"))) {
// background
dl->AddRectFilledMultiColor(
inRect.Min,
inRect.Max,
ImGui::GetColorU32(uiColors[GUI_COLOR_OSC_BG1]),
ImGui::GetColorU32(uiColors[GUI_COLOR_OSC_BG2]),
ImGui::GetColorU32(uiColors[GUI_COLOR_OSC_BG4]),
ImGui::GetColorU32(uiColors[GUI_COLOR_OSC_BG3]),
settings.oscRoundedCorners?(8.0f*dpiScale):0.0f
);
// axis guides
dl->AddLine(
ImLerp(rect.Min,rect.Max,ImVec2(0.0f,0.5f)),
ImLerp(rect.Min,rect.Max,ImVec2(1.0f,0.5f)),
refColor,
dpiScale
);
dl->AddLine(
ImLerp(rect.Min,rect.Max,ImVec2(0.5f,0.0f)),
ImLerp(rect.Min,rect.Max,ImVec2(0.5f,1.0f)),
refColor,
dpiScale
);
bool reflect=xyOscXInvert!=xyOscYInvert;
dl->AddLine(
ImLerp(inSqr.Min,inSqr.Max,ImVec2(0.0f,reflect?0.0f:1.0f)),
ImLerp(inSqr.Min,inSqr.Max,ImVec2(1.0f,reflect?1.0f:0.0f)),
refColor,
dpiScale
);
for (int i=1; i<5; i++) {
float ip = (float)i/8.f;
dl->AddRect(
ImLerp(inSqr.Min,inSqr.Max,ImVec2(0.5f-ip,0.5f-ip)),
ImLerp(inSqr.Min,inSqr.Max,ImVec2(0.5f+ip,0.5f+ip)),
guideColor,
0.0f,0,dpiScale
);
}
// line
const float* oscBufX=e->oscBuf[xyOscXChannel];
const float* oscBufY=e->oscBuf[xyOscYChannel];
if (oscBufX!=NULL && oscBufY!=NULL) {
int pos=e->oscWritePos;
float lx=inSqrCenter.x;
float ly=inSqrCenter.y;
float maxA=xyOscIntensity*256.f;
float decay=exp2f(-1e3f/e->getAudioDescGot().rate/xyOscDecayTime);
ImDrawListFlags prevFlags=dl->Flags;
dl->Flags|=ImDrawFlags_RoundCornersNone;
if (!settings.oscAntiAlias || safeMode) {
dl->Flags&=~(ImDrawListFlags_AntiAliasedLines|ImDrawListFlags_AntiAliasedLinesUseTex);
}
if (settings.oscEscapesBoundary) {
dl->PushClipRectFullScreen();
}
for (int i=0; i<xyOscSamples; i++) {
pos=(pos-1)&32767;
float x=oscBufX[pos]*scaleX+inSqrCenter.x;
float y=oscBufY[pos]*scaleY+inSqrCenter.y;
if (i != 0) {
float a=maxA/sqrtf((x-lx)*(x-lx)+(y-ly)*(y-ly));
if (a>=1) {
a=MIN(a,255);
dl->AddLine(ImVec2(lx,ly),ImVec2(x,y),(color|((ImU32)a<<IM_COL32_A_SHIFT)),xyOscThickness*dpiScale);
}
maxA*=decay;
if (maxA<1) {
break;
}
}
lx=x;
ly=y;
}
if (settings.oscEscapesBoundary) {
dl->PopClipRect();
}
dl->Flags=prevFlags;
}
if (settings.oscBorder) {
dl->AddRect(inRect.Min,inRect.Max,borderColor,settings.oscRoundedCorners?(8.0f*dpiScale):0.0f,0,1.5f*dpiScale);
}
}
if (ImGui::IsItemHovered()) {
float valX=20.0f*log10f(fabsf((ImGui::GetMousePos().x-inSqrCenter.x)/scaleX));
float valY=20.0f*log10f(fabsf((ImGui::GetMousePos().y-inSqrCenter.y)/scaleY));
if (valX<=-INFINITY && valY<=-INFINITY) {
ImGui::SetTooltip("(-Infinity)dB,(-Infinity)dB");
} else if (valX<=-INFINITY) {
ImGui::SetTooltip("(-Infinity)dB,%.1fdB",valY);
} else if (valY<=-INFINITY) {
ImGui::SetTooltip("%.1fdB,(-Infinity)dB",valY);
} else {
ImGui::SetTooltip("%.1fdB,%.1fdB",valX,valY);
}
}
if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) {
xyOscOptions=true;
}
}
}
if (noPadding) {
ImGui::PopStyleVar(3);
}
if (ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows)) curWindow=GUI_WINDOW_XY_OSC;
ImGui::End();
}